{"version":3,"sources":["../src/core/execution-tree-aggregator.ts","../src/core/execution-tree-event-emitter.ts","../src/core/execution-tree.ts","../src/core/constants.ts","../src/core/input-content.ts","../src/core/prompt-config.ts","../src/core/messages.ts","../src/core/model-shortcuts.ts","../src/core/rate-limit.ts","../src/core/retry.ts","../src/gadgets/exceptions.ts","../src/gadgets/media-store.ts","../src/logging/logger.ts","../src/agent/agent-internal-key.ts","../src/agent/compaction/config.ts","../src/agent/compaction/strategy.ts","../src/agent/compaction/strategies/sliding-window.ts","../src/agent/compaction/strategies/summarization.ts","../src/agent/compaction/strategies/hybrid.ts","../src/agent/compaction/strategies/index.ts","../src/agent/compaction/manager.ts","../src/agent/conversation-manager.ts","../src/agent/conversation-updater.ts","../src/agent/event-handlers.ts","../src/agent/hook-validators.ts","../src/agent/safe-observe.ts","../src/agent/tree-hook-bridge.ts","../src/agent/llm-call-lifecycle.ts","../src/gadgets/schema-to-json.ts","../src/gadgets/schema-validator.ts","../src/gadgets/gadget.ts","../src/gadgets/create-gadget.ts","../src/gadgets/output-viewer.ts","../src/agent/gadget-output-store.ts","../src/agent/output-limit-manager.ts","../src/core/errors.ts","../src/agent/retry-orchestrator.ts","../src/gadgets/registry.ts","../src/skills/activation.ts","../src/skills/load-skill-gadget.ts","../src/skills/parser.ts","../src/skills/registry.ts","../src/skills/skill.ts","../src/skills/loader.ts","../src/agent/builder-utils.ts","../src/agent/file-logging.ts","../src/agent/hook-presets.ts","../src/agent/hook-composer.ts","../src/providers/anthropic-models.ts","../src/providers/base-provider.ts","../src/providers/constants.ts","../src/providers/utils.ts","../src/providers/anthropic.ts","../src/providers/gemini-cache-manager.ts","../src/providers/gemini-image-models.ts","../src/providers/gemini-models.ts","../src/research/constants.ts","../src/research/errors.ts","../src/providers/gemini-research.ts","../src/providers/gemini-research-models.ts","../src/providers/gemini-speech-models.ts","../src/providers/gemini.ts","../src/providers/huggingface-models.ts","../src/providers/openai-compatible-provider.ts","../src/providers/huggingface.ts","../src/providers/openai-image-models.ts","../src/providers/openai-models.ts","../src/providers/openai-research.ts","../src/providers/openai-research-models.ts","../src/providers/openai-speech-models.ts","../src/providers/openai.ts","../src/providers/openrouter-models.ts","../src/providers/openrouter-research.ts","../src/providers/openrouter-research-models.ts","../src/providers/openrouter-speech-models.ts","../src/providers/openrouter.ts","../src/providers/discovery.ts","../src/research/cost.ts","../src/research/collector.ts","../src/research/job.ts","../src/research/types.ts","../src/research/namespace.ts","../src/core/model-registry.ts","../src/core/namespaces/image.ts","../src/core/namespaces/speech.ts","../src/core/quick-methods.ts","../src/core/namespaces/text.ts","../src/core/namespaces/vision.ts","../src/core/options.ts","../src/core/client.ts","../src/agent/builder.ts","../src/agent/hook-utils.ts","../src/gadgets/schema-introspector.ts","../src/gadgets/block-params.ts","../src/gadgets/cost-reporting-client.ts","../src/gadgets/error-formatter.ts","../src/gadgets/parser.ts","../src/gadgets/typed-gadget.ts","../src/gadgets/executor.ts","../src/agent/gadget-concurrency-manager.ts","../src/agent/gadget-dependency-resolver.ts","../src/agent/observer-notifier.ts","../src/agent/gadget-dispatcher.ts","../src/agent/gadget-hook-lifecycle.ts","../src/agent/gadget-limit-guard.ts","../src/agent/stream-processor.ts","../src/agent/stream-processor-factory.ts","../src/mcp/errors.ts","../src/mcp/allowlist.ts","../src/mcp/client.ts","../src/mcp/lifecycle.ts","../src/mcp/multi-server.ts","../src/mcp/prompt-adapter.ts","../src/gadgets/helpers.ts","../src/mcp/json-schema-to-zod.ts","../src/mcp/tool-adapter.ts","../src/mcp/runtime.ts","../src/agent/agent.ts","../src/index.ts","../src/agent/compaction/index.ts","../src/agent/index.ts","../src/agent/hints.ts","../src/core/execution-events.ts","../src/mcp/index.ts","../src/mcp/gadget-exporter.ts","../src/gadgets/validation.ts","../src/mcp/skill-exporter.ts","../src/mcp/server.ts","../src/research/index.ts","../src/utils/config-resolver.ts","../src/agent/subagent.ts","../src/package/manifest.ts","../src/session/manager.ts","../src/skills/index.ts","../src/utils/format.ts","../src/utils/timing.ts"],"sourcesContent":["/**\n * ExecutionTreeAggregator — cost, token, and media aggregation for ExecutionTree.\n *\n * This class is responsible solely for rollup computations. It receives the\n * node map and a traversal callback from `ExecutionTree` at construction time\n * and exposes the same aggregation methods that used to live on `ExecutionTree`.\n *\n * Keeping this logic separate makes it straightforward to test the aggregation\n * math in isolation, without needing to drive a full `ExecutionTree` instance.\n *\n * @module core/execution-tree-aggregator\n */\n\nimport type { GadgetMediaOutput } from \"../gadgets/types.js\";\n\n// ---------------------------------------------------------------------------\n// Minimal node interfaces (structural — actual ExecutionNode objects satisfy these)\n// ---------------------------------------------------------------------------\n\ninterface UsageSnapshot {\n  inputTokens: number;\n  outputTokens: number;\n  cachedInputTokens?: number;\n}\n\ninterface AggregableNode {\n  type: string;\n  completedAt: number | null;\n  children: string[];\n  /** Present only on llm_call nodes */\n  cost?: number;\n  /** Present only on llm_call nodes */\n  usage?: UsageSnapshot;\n  /** Present only on gadget nodes */\n  media?: GadgetMediaOutput[];\n}\n\n// ---------------------------------------------------------------------------\n// ExecutionTreeAggregator\n// ---------------------------------------------------------------------------\n\n/**\n * Provides aggregation over an `ExecutionTree`'s node map.\n *\n * @example\n * ```typescript\n * // ExecutionTree creates the aggregator internally:\n * const agg = new ExecutionTreeAggregator(\n *   this.nodes,\n *   (id, type) => this.getDescendants(id, type),\n * );\n * console.log(agg.getTotalCost());\n * ```\n */\nexport class ExecutionTreeAggregator {\n  constructor(\n    private readonly nodes: ReadonlyMap<string, AggregableNode>,\n    private readonly getDescendants: (id: string, type?: string) => ReadonlyArray<AggregableNode>,\n  ) {}\n\n  // ===========================================================================\n  // Private helpers\n  // ===========================================================================\n\n  /**\n   * Extract the monetary cost from a single node (0 when not set).\n   */\n  private getNodeCost(node: AggregableNode): number {\n    return node.cost ?? 0;\n  }\n\n  /**\n   * Accumulate token counts from an iterable of nodes.\n   * Non-LLM nodes (gadgets) are ignored.\n   */\n  private accumulateTokens(nodes: Iterable<AggregableNode>): {\n    input: number;\n    output: number;\n    cached: number;\n  } {\n    let input = 0;\n    let output = 0;\n    let cached = 0;\n\n    for (const node of nodes) {\n      if (node.type === \"llm_call\" && node.usage) {\n        input += node.usage.inputTokens;\n        output += node.usage.outputTokens;\n        cached += node.usage.cachedInputTokens ?? 0;\n      }\n    }\n\n    return { input, output, cached };\n  }\n\n  // ===========================================================================\n  // Cost\n  // ===========================================================================\n\n  /**\n   * Total cost across every node in the tree.\n   */\n  getTotalCost(): number {\n    let total = 0;\n    for (const node of this.nodes.values()) {\n      total += this.getNodeCost(node);\n    }\n    return total;\n  }\n\n  /**\n   * Total cost for a subtree (node + all descendants).\n   */\n  getSubtreeCost(nodeId: string): number {\n    const node = this.nodes.get(nodeId);\n    if (!node) return 0;\n\n    let total = this.getNodeCost(node);\n    for (const descendant of this.getDescendants(nodeId)) {\n      total += this.getNodeCost(descendant);\n    }\n    return total;\n  }\n\n  // ===========================================================================\n  // Tokens\n  // ===========================================================================\n\n  /**\n   * Aggregate token usage across the entire tree.\n   */\n  getTotalTokens(): { input: number; output: number; cached: number } {\n    return this.accumulateTokens(this.nodes.values());\n  }\n\n  /**\n   * Aggregate token usage for a subtree.\n   */\n  getSubtreeTokens(nodeId: string): { input: number; output: number; cached: number } {\n    const node = this.nodes.get(nodeId);\n    if (!node) return { input: 0, output: 0, cached: 0 };\n\n    return this.accumulateTokens([node, ...this.getDescendants(nodeId)]);\n  }\n\n  // ===========================================================================\n  // Media\n  // ===========================================================================\n\n  /**\n   * Collect all media outputs from gadget nodes in a subtree.\n   */\n  getSubtreeMedia(nodeId: string): GadgetMediaOutput[] {\n    const node = this.nodes.get(nodeId);\n    if (!node) return [];\n\n    const media: GadgetMediaOutput[] = [];\n    const nodesToProcess: AggregableNode[] = node.type === \"gadget\" ? [node] : [];\n    nodesToProcess.push(...(this.getDescendants(nodeId, \"gadget\") as AggregableNode[]));\n\n    for (const n of nodesToProcess) {\n      if (n.type === \"gadget\" && n.media) {\n        media.push(...n.media);\n      }\n    }\n\n    return media;\n  }\n\n  // ===========================================================================\n  // Completion & counts\n  // ===========================================================================\n\n  /**\n   * Check whether a subtree is fully complete (all nodes have `completedAt` set).\n   */\n  isSubtreeComplete(nodeId: string): boolean {\n    const node = this.nodes.get(nodeId);\n    if (!node) return true;\n    if (!node.completedAt) return false;\n\n    for (const descendant of this.getDescendants(nodeId)) {\n      if (!descendant.completedAt) return false;\n    }\n\n    return true;\n  }\n\n  /**\n   * Count LLM call nodes and gadget nodes in the tree.\n   */\n  getNodeCount(): { llmCalls: number; gadgets: number } {\n    let llmCalls = 0;\n    let gadgets = 0;\n\n    for (const node of this.nodes.values()) {\n      if (node.type === \"llm_call\") llmCalls++;\n      else if (node.type === \"gadget\") gadgets++;\n    }\n\n    return { llmCalls, gadgets };\n  }\n}\n","/**\n * ExecutionTreeEventEmitter — responsible for event notification within ExecutionTree.\n *\n * Handles:\n * - Synchronous event dispatch to named and wildcard listeners (`on`, `onAll`)\n * - Async back-pressure queue consumed by the `events()` async generator\n * - Tree-completion signalling via `complete()`\n *\n * @module core/execution-tree-event-emitter\n */\n\nimport type { ExecutionEvent, ExecutionEventType } from \"./execution-events.js\";\n\n/** Event listener function type */\ntype EventListener = (event: ExecutionEvent) => void;\n\n/** Minimal node shape needed to build base event properties. */\ninterface NodeEventProps {\n  id: string;\n  parentId: string | null;\n  depth: number;\n  path: string[];\n}\n\n/**\n * Manages synchronous event dispatch and the async event queue for ExecutionTree.\n *\n * `ExecutionTree` holds one instance and delegates all event-related public\n * methods to it, keeping event infrastructure separate from node storage and\n * aggregation logic.\n */\nexport class ExecutionTreeEventEmitter {\n  private eventListeners = new Map<ExecutionEventType, Set<EventListener>>();\n  private eventQueue: ExecutionEvent[] = [];\n  private eventWaiters: Array<(event: ExecutionEvent | null) => void> = [];\n  private isCompleted = false;\n  private eventIdCounter = 0;\n\n  // ===========================================================================\n  // Base event props factory\n  // ===========================================================================\n\n  /**\n   * Build the common event properties derived from a node.\n   */\n  createBaseEventProps(node: NodeEventProps): {\n    eventId: number;\n    timestamp: number;\n    nodeId: string;\n    parentId: string | null;\n    depth: number;\n    path: string[];\n  } {\n    return {\n      eventId: ++this.eventIdCounter,\n      timestamp: Date.now(),\n      nodeId: node.id,\n      parentId: node.parentId,\n      depth: node.depth,\n      path: node.path,\n    };\n  }\n\n  // ===========================================================================\n  // Synchronous dispatch\n  // ===========================================================================\n\n  /**\n   * Dispatch an event to all registered listeners and push it to the async queue.\n   */\n  emit(event: ExecutionEvent): void {\n    // Notify typed listeners\n    const listeners = this.eventListeners.get(event.type);\n    if (listeners) {\n      for (const listener of listeners) {\n        try {\n          listener(event);\n        } catch (error) {\n          console.error(`Error in event listener for ${event.type}:`, error);\n        }\n      }\n    }\n\n    // Notify wildcard listeners\n    const allListeners = this.eventListeners.get(\"*\");\n    if (allListeners) {\n      for (const listener of allListeners) {\n        try {\n          listener(event);\n        } catch (error) {\n          console.error(\"Error in wildcard event listener:\", error);\n        }\n      }\n    }\n\n    // Push to async queue or wake waiting consumer\n    if (this.eventWaiters.length > 0) {\n      const waiter = this.eventWaiters.shift()!;\n      waiter(event);\n    } else {\n      this.eventQueue.push(event);\n    }\n  }\n\n  // ===========================================================================\n  // Subscription\n  // ===========================================================================\n\n  /**\n   * Subscribe to events of a specific type.\n   *\n   * @param type - Event type, or `\"*\"` for all events\n   * @param listener - Callback invoked for each matching event\n   * @returns Unsubscribe function\n   */\n  on(type: ExecutionEventType, listener: EventListener): () => void {\n    if (!this.eventListeners.has(type)) {\n      this.eventListeners.set(type, new Set());\n    }\n    const listeners = this.eventListeners.get(type)!;\n    listeners.add(listener);\n\n    return () => {\n      listeners.delete(listener);\n    };\n  }\n\n  /**\n   * Subscribe to all events (alias for `on(\"*\", listener)`).\n   */\n  onAll(listener: EventListener): () => void {\n    return this.on(\"*\", listener);\n  }\n\n  // ===========================================================================\n  // Async event stream\n  // ===========================================================================\n\n  /**\n   * Async generator that yields all events in order.\n   * Terminates when `complete()` is called.\n   */\n  async *events(): AsyncGenerator<ExecutionEvent> {\n    while (!this.isCompleted) {\n      // Drain queue first\n      while (this.eventQueue.length > 0) {\n        yield this.eventQueue.shift()!;\n      }\n\n      if (this.isCompleted) break;\n\n      // Wait for next event (null signals tree completion)\n      const event = await new Promise<ExecutionEvent | null>((resolve) => {\n        // Check queue again in case events arrived while setting up\n        if (this.eventQueue.length > 0) {\n          resolve(this.eventQueue.shift()!);\n        } else {\n          this.eventWaiters.push(resolve);\n        }\n      });\n\n      if (event === null) break;\n      yield event;\n    }\n\n    // Drain any remaining buffered events\n    while (this.eventQueue.length > 0) {\n      yield this.eventQueue.shift()!;\n    }\n  }\n\n  // ===========================================================================\n  // Completion\n  // ===========================================================================\n\n  /**\n   * Mark the emitter as complete. Wakes all consumers waiting in `events()`.\n   */\n  complete(): void {\n    this.isCompleted = true;\n    for (const waiter of this.eventWaiters) {\n      waiter(null);\n    }\n    this.eventWaiters = [];\n  }\n\n  /**\n   * Whether `complete()` has been called.\n   */\n  isComplete(): boolean {\n    return this.isCompleted;\n  }\n}\n","/**\n * First-class Execution Tree model for nested subagent support.\n *\n * The ExecutionTree is THE single source of truth for execution state.\n * All nodes (including nested subagent nodes) live in one tree.\n * Events are projections of tree changes.\n *\n * @module core/execution-tree\n */\n\nimport type { GadgetMediaOutput, StoredMedia } from \"../gadgets/types.js\";\nimport type { LLMMessage } from \"./messages.js\";\nimport type { TokenUsage } from \"./options.js\";\n\n// =============================================================================\n// Node Identifiers\n// =============================================================================\n\n/**\n * Unique identifier for any execution node.\n * Format examples: \"llm_1\", \"gadget_abc123\", \"llm_1_2\" (nested)\n */\nexport type NodeId = string;\n\n/**\n * Node type discriminator.\n */\nexport type ExecutionNodeType = \"llm_call\" | \"gadget\";\n\n// =============================================================================\n// Execution Node Types\n// =============================================================================\n\n/**\n * Base properties shared by all execution nodes.\n */\ninterface BaseExecutionNode {\n  /** Unique identifier for this node */\n  id: NodeId;\n  /** Node type discriminator */\n  type: ExecutionNodeType;\n  /** Parent node ID (null for root nodes) */\n  parentId: NodeId | null;\n  /** Nesting depth (0 = root, 1 = child of gadget, etc.) */\n  depth: number;\n  /** Path from root to this node: [\"llm_1\", \"gadget_abc\", \"llm_1_1\"] */\n  path: NodeId[];\n  /** Creation timestamp */\n  createdAt: number;\n  /** Completion timestamp (null if in progress) */\n  completedAt: number | null;\n}\n\n/**\n * LLM call execution node.\n */\nexport interface LLMCallNode extends BaseExecutionNode {\n  type: \"llm_call\";\n  /** Iteration number within the agent loop (1-indexed for display) */\n  iteration: number;\n  /** Model identifier */\n  model: string;\n  /** Request messages (set when call starts) */\n  request?: LLMMessage[];\n  /** Accumulated response text */\n  response: string;\n  /** Token usage (set on completion) */\n  usage?: TokenUsage;\n  /** Finish reason from LLM */\n  finishReason?: string | null;\n  /** Cost in USD */\n  cost?: number;\n  /** Child node IDs (gadgets spawned by this LLM call) */\n  children: NodeId[];\n}\n\n/**\n * Gadget execution state.\n */\nexport type GadgetState = \"pending\" | \"running\" | \"completed\" | \"failed\" | \"skipped\";\n\n/**\n * Gadget execution node.\n */\nexport interface GadgetNode extends BaseExecutionNode {\n  type: \"gadget\";\n  /** Invocation ID (LLM-generated or auto) */\n  invocationId: string;\n  /** Gadget name */\n  name: string;\n  /** Parameters passed to the gadget */\n  parameters: Record<string, unknown>;\n  /** Dependencies (other invocation IDs this gadget waits for) */\n  dependencies: string[];\n  /** Execution state */\n  state: GadgetState;\n  /** Result string (if completed successfully) */\n  result?: string;\n  /** Error message (if failed or skipped) */\n  error?: string;\n  /** Failed dependency invocation ID (if skipped due to dependency) */\n  failedDependency?: string;\n  /** Execution time in milliseconds */\n  executionTimeMs?: number;\n  /** Cost in USD */\n  cost?: number;\n  /** Media outputs from this gadget */\n  media?: GadgetMediaOutput[];\n  /** Child node IDs (nested LLM calls for subagent gadgets) */\n  children: NodeId[];\n  /** Whether this gadget is a subagent (has nested LLM calls) */\n  isSubagent: boolean;\n}\n\n/**\n * Union of all execution node types.\n */\nexport type ExecutionNode = LLMCallNode | GadgetNode;\n\n// =============================================================================\n// Node Creation Parameters\n// =============================================================================\n\nexport interface AddLLMCallParams {\n  /** Iteration number (1-indexed) */\n  iteration: number;\n  /** Model identifier */\n  model: string;\n  /** Request messages */\n  request?: LLMMessage[];\n  /** Parent node ID (for subagent LLM calls) */\n  parentId?: NodeId | null;\n}\n\nexport interface AddGadgetParams {\n  /** Invocation ID */\n  invocationId: string;\n  /** Gadget name */\n  name: string;\n  /** Parameters */\n  parameters: Record<string, unknown>;\n  /** Dependencies */\n  dependencies?: string[];\n  /** Parent LLM call node ID */\n  parentId?: NodeId | null;\n}\n\nexport interface CompleteLLMCallParams {\n  /** Accumulated response text */\n  response?: string;\n  /** Token usage */\n  usage?: TokenUsage;\n  /** Finish reason */\n  finishReason?: string | null;\n  /** Cost in USD */\n  cost?: number;\n  /** Accumulated thinking/reasoning content from reasoning models */\n  thinkingContent?: string;\n}\n\nexport interface CompleteGadgetParams {\n  /** Result string */\n  result?: string;\n  /** Error message */\n  error?: string;\n  /** Failed dependency (for skipped gadgets) */\n  failedDependency?: string;\n  /** Execution time in ms */\n  executionTimeMs?: number;\n  /** Cost in USD */\n  cost?: number;\n  /** Media outputs */\n  media?: GadgetMediaOutput[];\n  /** Stored media with file paths */\n  storedMedia?: StoredMedia[];\n}\n\n// =============================================================================\n// Event Types (imported from execution-events.ts)\n// =============================================================================\n\n// Forward declaration - actual types in execution-events.ts\nimport type { ExecutionEvent, ExecutionEventType } from \"./execution-events.js\";\nimport { ExecutionTreeAggregator } from \"./execution-tree-aggregator.js\";\nimport { ExecutionTreeEventEmitter } from \"./execution-tree-event-emitter.js\";\n\nexport type { ExecutionEvent, ExecutionEventType };\nexport { ExecutionTreeAggregator, ExecutionTreeEventEmitter };\n\n// =============================================================================\n// ExecutionTree Class\n// =============================================================================\n\n/**\n * The Execution Tree - single source of truth for all execution state.\n *\n * Features:\n * - Stores all nodes (LLM calls, gadgets) in a hierarchical structure\n * - Emits events on mutations\n * - Provides query methods for aggregation (costs, media, descendants)\n * - Supports single shared tree model for nested subagents\n *\n * @example\n * ```typescript\n * const tree = new ExecutionTree();\n *\n * // Add root LLM call\n * const llmNode = tree.addLLMCall({ iteration: 1, model: \"sonnet\" });\n *\n * // Add gadget under the LLM call\n * const gadgetNode = tree.addGadget({\n *   invocationId: \"gc_1\",\n *   name: \"ReadFile\",\n *   parameters: { path: \"/foo.txt\" },\n *   parentId: llmNode.id,\n * });\n *\n * // Complete the gadget\n * tree.completeGadget(gadgetNode.id, { result: \"file contents\", executionTimeMs: 50 });\n *\n * // Query total cost\n * console.log(tree.getTotalCost());\n * ```\n */\nexport class ExecutionTree {\n  private nodes = new Map<NodeId, ExecutionNode>();\n  private rootIds: NodeId[] = [];\n  private invocationIdToNodeId = new Map<string, NodeId>();\n  private emitter = new ExecutionTreeEventEmitter();\n  private aggregator!: ExecutionTreeAggregator;\n\n  /**\n   * Base depth for all nodes in this tree.\n   * Used when this tree is a subagent's view into a parent tree.\n   */\n  public readonly baseDepth: number;\n\n  /**\n   * Parent node ID for subagent trees.\n   * All root nodes in this tree will have this as their parentId.\n   */\n  public readonly parentNodeId: NodeId | null;\n\n  constructor(options?: { baseDepth?: number; parentNodeId?: NodeId | null }) {\n    this.baseDepth = options?.baseDepth ?? 0;\n    this.parentNodeId = options?.parentNodeId ?? null;\n    this.aggregator = new ExecutionTreeAggregator(\n      this.nodes as any,\n      (id, type) => this.getDescendants(id, type as \"llm_call\" | \"gadget\" | undefined) as any,\n    );\n  }\n\n  // ===========================================================================\n  // Node ID Generation\n  // ===========================================================================\n\n  private generateLLMCallId(iteration: number, parentId: NodeId | null): NodeId {\n    if (parentId) {\n      // Subagent LLM call: include parent info for uniqueness\n      return `llm_${parentId}_${iteration}`;\n    }\n    return `llm_${iteration}`;\n  }\n\n  private gadgetIdCounter = 0;\n  private generateGadgetId(invocationId: string): NodeId {\n    return `gadget_${invocationId}_${++this.gadgetIdCounter}`;\n  }\n\n  // ===========================================================================\n  // Event Emission (delegated to ExecutionTreeEventEmitter)\n  // ===========================================================================\n\n  private emit(event: ExecutionEvent): void {\n    this.emitter.emit(event);\n  }\n\n  private createBaseEventProps(\n    node: ExecutionNode,\n  ): ReturnType<ExecutionTreeEventEmitter[\"createBaseEventProps\"]> {\n    return this.emitter.createBaseEventProps(node);\n  }\n\n  // ===========================================================================\n  // Node Creation\n  // ===========================================================================\n\n  /**\n   * Add a new LLM call node to the tree.\n   */\n  addLLMCall(params: AddLLMCallParams): LLMCallNode {\n    const parentId = params.parentId ?? this.parentNodeId;\n    const parent = parentId ? this.nodes.get(parentId) : null;\n\n    const depth = parent ? parent.depth + 1 : this.baseDepth;\n    const path = parent ? [...parent.path] : [];\n\n    const id = this.generateLLMCallId(params.iteration, parentId);\n    path.push(id);\n\n    const node: LLMCallNode = {\n      id,\n      type: \"llm_call\",\n      parentId,\n      depth,\n      path,\n      createdAt: Date.now(),\n      completedAt: null,\n      iteration: params.iteration,\n      model: params.model,\n      request: params.request,\n      response: \"\",\n      children: [],\n    };\n\n    this.nodes.set(id, node);\n\n    if (!parentId) {\n      this.rootIds.push(id);\n    } else if (parent) {\n      parent.children.push(id);\n    }\n\n    this.emit({\n      type: \"llm_call_start\",\n      ...this.createBaseEventProps(node),\n      iteration: node.iteration,\n      model: node.model,\n      request: node.request,\n    });\n\n    return node;\n  }\n\n  /**\n   * Add text to an LLM call's response (for streaming).\n   */\n  appendLLMResponse(nodeId: NodeId, chunk: string): void {\n    const node = this.nodes.get(nodeId);\n    if (!node || node.type !== \"llm_call\") {\n      throw new Error(`LLM call node not found: ${nodeId}`);\n    }\n\n    (node as LLMCallNode).response += chunk;\n\n    this.emit({\n      type: \"llm_call_stream\",\n      ...this.createBaseEventProps(node),\n      chunk,\n    });\n  }\n\n  /**\n   * Mark an LLM call's response as ended (tokens stopped).\n   *\n   * Called when the LLM stream ends, before gadget execution completes.\n   * Use this event to track \"LLM thinking time\" separately from gadget execution.\n   *\n   * @param nodeId - The LLM call node ID\n   * @param params - Response end parameters (finishReason, usage)\n   */\n  endLLMResponse(\n    nodeId: NodeId,\n    params: { finishReason: string | null; usage?: import(\"./options.js\").TokenUsage },\n  ): void {\n    const node = this.nodes.get(nodeId);\n    if (!node || node.type !== \"llm_call\") {\n      return; // Silently ignore if node not found (may be called during cleanup)\n    }\n\n    const llmNode = node as LLMCallNode;\n\n    this.emit({\n      type: \"llm_response_end\",\n      ...this.createBaseEventProps(node),\n      iteration: llmNode.iteration,\n      model: llmNode.model,\n      finishReason: params.finishReason,\n      usage: params.usage,\n    });\n  }\n\n  /**\n   * Complete an LLM call node (after all gadgets finish).\n   */\n  completeLLMCall(nodeId: NodeId, params: CompleteLLMCallParams): void {\n    const node = this.nodes.get(nodeId);\n    if (!node || node.type !== \"llm_call\") {\n      throw new Error(`LLM call node not found: ${nodeId}`);\n    }\n\n    const llmNode = node as LLMCallNode;\n    llmNode.completedAt = Date.now();\n    if (params.response !== undefined) llmNode.response = params.response;\n    if (params.usage) llmNode.usage = params.usage;\n    if (params.finishReason !== undefined) llmNode.finishReason = params.finishReason;\n    if (params.cost !== undefined) llmNode.cost = params.cost;\n\n    this.emit({\n      type: \"llm_call_complete\",\n      ...this.createBaseEventProps(node),\n      response: llmNode.response,\n      usage: llmNode.usage,\n      finishReason: llmNode.finishReason,\n      cost: llmNode.cost,\n      thinkingContent: params.thinkingContent,\n    });\n  }\n\n  /**\n   * Mark an LLM call as failed.\n   */\n  failLLMCall(nodeId: NodeId, error: Error, recovered: boolean): void {\n    const node = this.nodes.get(nodeId);\n    if (!node || node.type !== \"llm_call\") {\n      throw new Error(`LLM call node not found: ${nodeId}`);\n    }\n\n    const llmNode = node as LLMCallNode;\n    llmNode.completedAt = Date.now();\n\n    this.emit({\n      type: \"llm_call_error\",\n      ...this.createBaseEventProps(node),\n      error,\n      recovered,\n    });\n  }\n\n  /**\n   * Add a new gadget node to the tree.\n   */\n  addGadget(params: AddGadgetParams): GadgetNode {\n    const parentId = params.parentId ?? this.getCurrentLLMCallId() ?? this.parentNodeId;\n    const parent = parentId ? this.nodes.get(parentId) : null;\n\n    const depth = parent ? parent.depth + 1 : this.baseDepth;\n    const path = parent ? [...parent.path] : [];\n\n    const id = this.generateGadgetId(params.invocationId);\n    path.push(id);\n\n    const node: GadgetNode = {\n      id,\n      type: \"gadget\",\n      parentId,\n      depth,\n      path,\n      createdAt: Date.now(),\n      completedAt: null,\n      invocationId: params.invocationId,\n      name: params.name,\n      parameters: params.parameters,\n      dependencies: params.dependencies ?? [],\n      state: \"pending\",\n      children: [],\n      isSubagent: false,\n    };\n\n    this.nodes.set(id, node);\n    this.invocationIdToNodeId.set(params.invocationId, id);\n\n    if (parent) {\n      parent.children.push(id);\n    }\n\n    this.emit({\n      type: \"gadget_call\",\n      ...this.createBaseEventProps(node),\n      invocationId: node.invocationId,\n      name: node.name,\n      parameters: node.parameters,\n      dependencies: node.dependencies,\n    });\n\n    return node;\n  }\n\n  /**\n   * Update a gadget's parameters (e.g., after interceptor modifies them).\n   * This is called after the gadget is added to the tree but before execution.\n   */\n  updateGadgetParameters(invocationId: string, parameters: Record<string, unknown>): void {\n    const nodeId = this.invocationIdToNodeId.get(invocationId);\n    if (!nodeId) {\n      return;\n    }\n    const node = this.nodes.get(nodeId);\n    if (node?.type === \"gadget\") {\n      (node as GadgetNode).parameters = parameters;\n    }\n  }\n\n  /**\n   * Mark a gadget as started (running).\n   */\n  startGadget(nodeId: NodeId): void {\n    const node = this.nodes.get(nodeId);\n    if (!node || node.type !== \"gadget\") {\n      throw new Error(`Gadget node not found: ${nodeId}`);\n    }\n\n    const gadgetNode = node as GadgetNode;\n    gadgetNode.state = \"running\";\n\n    this.emit({\n      type: \"gadget_start\",\n      ...this.createBaseEventProps(node),\n      invocationId: gadgetNode.invocationId,\n      name: gadgetNode.name,\n    });\n  }\n\n  /**\n   * Complete a gadget node successfully.\n   */\n  completeGadget(nodeId: NodeId, params: CompleteGadgetParams): void {\n    const node = this.nodes.get(nodeId);\n    if (!node || node.type !== \"gadget\") {\n      throw new Error(`Gadget node not found: ${nodeId}`);\n    }\n\n    const gadgetNode = node as GadgetNode;\n    gadgetNode.completedAt = Date.now();\n    gadgetNode.state = params.error ? \"failed\" : \"completed\";\n    if (params.result !== undefined) gadgetNode.result = params.result;\n    if (params.error) gadgetNode.error = params.error;\n    if (params.executionTimeMs !== undefined) gadgetNode.executionTimeMs = params.executionTimeMs;\n    if (params.cost !== undefined) gadgetNode.cost = params.cost;\n    if (params.media) gadgetNode.media = params.media;\n\n    // Mark as subagent if it has child LLM calls\n    gadgetNode.isSubagent = gadgetNode.children.some((childId) => {\n      const child = this.nodes.get(childId);\n      return child?.type === \"llm_call\";\n    });\n\n    if (params.error) {\n      this.emit({\n        type: \"gadget_error\",\n        ...this.createBaseEventProps(node),\n        invocationId: gadgetNode.invocationId,\n        name: gadgetNode.name,\n        error: params.error,\n        executionTimeMs: params.executionTimeMs ?? 0,\n      });\n    } else {\n      this.emit({\n        type: \"gadget_complete\",\n        ...this.createBaseEventProps(node),\n        invocationId: gadgetNode.invocationId,\n        name: gadgetNode.name,\n        result: params.result ?? \"\",\n        executionTimeMs: params.executionTimeMs ?? 0,\n        cost: params.cost,\n        media: params.media,\n        storedMedia: params.storedMedia,\n      });\n    }\n  }\n\n  /**\n   * Mark a gadget as skipped due to dependency failure.\n   */\n  skipGadget(\n    nodeId: NodeId,\n    failedDependency: string,\n    failedDependencyError: string,\n    reason: \"dependency_failed\" | \"controller_skip\" | \"limit_exceeded\",\n  ): void {\n    const node = this.nodes.get(nodeId);\n    if (!node || node.type !== \"gadget\") {\n      throw new Error(`Gadget node not found: ${nodeId}`);\n    }\n\n    const gadgetNode = node as GadgetNode;\n    gadgetNode.completedAt = Date.now();\n    gadgetNode.state = \"skipped\";\n    gadgetNode.failedDependency = failedDependency;\n    gadgetNode.error = failedDependencyError;\n\n    // Build error message combining reason and dependency error\n    const error =\n      reason === \"controller_skip\"\n        ? \"Skipped by controller\"\n        : `Dependency ${failedDependency} failed: ${failedDependencyError}`;\n\n    this.emit({\n      type: \"gadget_skipped\",\n      ...this.createBaseEventProps(node),\n      invocationId: gadgetNode.invocationId,\n      name: gadgetNode.name,\n      reason,\n      error,\n      failedDependency,\n      failedDependencyError,\n    });\n  }\n\n  // ===========================================================================\n  // Text Events (pure notifications, not tree nodes)\n  // ===========================================================================\n\n  /**\n   * Emit a text event (notification only, not stored in tree).\n   */\n  emitText(content: string, llmCallNodeId: NodeId): void {\n    const node = this.nodes.get(llmCallNodeId);\n    if (!node) {\n      throw new Error(`Node not found: ${llmCallNodeId}`);\n    }\n\n    this.emit({\n      type: \"text\",\n      ...this.createBaseEventProps(node),\n      content,\n    });\n  }\n\n  // ===========================================================================\n  // Query Methods\n  // ===========================================================================\n\n  /**\n   * Get a node by ID.\n   */\n  getNode(id: NodeId): ExecutionNode | undefined {\n    return this.nodes.get(id);\n  }\n\n  /**\n   * Get a gadget node by invocation ID.\n   */\n  getNodeByInvocationId(invocationId: string): GadgetNode | undefined {\n    const nodeId = this.invocationIdToNodeId.get(invocationId);\n    if (!nodeId) return undefined;\n    const node = this.nodes.get(nodeId);\n    return node?.type === \"gadget\" ? (node as GadgetNode) : undefined;\n  }\n\n  /**\n   * Get all root nodes (depth 0 for this tree).\n   */\n  getRoots(): ExecutionNode[] {\n    return this.rootIds\n      .map((id) => this.nodes.get(id))\n      .filter((node): node is ExecutionNode => node !== undefined);\n  }\n\n  /**\n   * Get children of a node.\n   */\n  getChildren(id: NodeId): ExecutionNode[] {\n    const node = this.nodes.get(id);\n    if (!node) return [];\n    return node.children\n      .map((childId) => this.nodes.get(childId))\n      .filter((child): child is ExecutionNode => child !== undefined);\n  }\n\n  /**\n   * Get ancestors of a node (from root to parent).\n   */\n  getAncestors(id: NodeId): ExecutionNode[] {\n    const node = this.nodes.get(id);\n    if (!node) return [];\n\n    const ancestors: ExecutionNode[] = [];\n    let currentId = node.parentId;\n    while (currentId) {\n      const ancestor = this.nodes.get(currentId);\n      if (ancestor) {\n        ancestors.unshift(ancestor);\n        currentId = ancestor.parentId;\n      } else {\n        break;\n      }\n    }\n    return ancestors;\n  }\n\n  /**\n   * Get all descendants of a node.\n   */\n  getDescendants(id: NodeId, type?: ExecutionNodeType): ExecutionNode[] {\n    const node = this.nodes.get(id);\n    if (!node) return [];\n\n    const descendants: ExecutionNode[] = [];\n    const stack = [...node.children];\n\n    while (stack.length > 0) {\n      const childId = stack.pop()!;\n      const child = this.nodes.get(childId);\n      if (child) {\n        if (!type || child.type === type) {\n          descendants.push(child);\n        }\n        stack.push(...child.children);\n      }\n    }\n\n    return descendants;\n  }\n\n  /**\n   * Get the current (most recent incomplete) LLM call node.\n   */\n  getCurrentLLMCallId(): NodeId | undefined {\n    // Find the most recent root LLM call that's not complete\n    for (let i = this.rootIds.length - 1; i >= 0; i--) {\n      const node = this.nodes.get(this.rootIds[i]);\n      if (node?.type === \"llm_call\" && !node.completedAt) {\n        return node.id;\n      }\n    }\n    return undefined;\n  }\n\n  // ===========================================================================\n  // Aggregation Methods (delegated to ExecutionTreeAggregator)\n  // ===========================================================================\n\n  /**\n   * Get total cost for entire tree.\n   */\n  getTotalCost(): number {\n    return this.aggregator.getTotalCost();\n  }\n\n  /**\n   * Get total cost for a subtree (node and all descendants).\n   */\n  getSubtreeCost(nodeId: NodeId): number {\n    return this.aggregator.getSubtreeCost(nodeId);\n  }\n\n  /**\n   * Get token usage for entire tree.\n   */\n  getTotalTokens(): { input: number; output: number; cached: number } {\n    return this.aggregator.getTotalTokens();\n  }\n\n  /**\n   * Get token usage for a subtree.\n   */\n  getSubtreeTokens(nodeId: NodeId): { input: number; output: number; cached: number } {\n    return this.aggregator.getSubtreeTokens(nodeId);\n  }\n\n  /**\n   * Collect all media from a subtree.\n   */\n  getSubtreeMedia(nodeId: NodeId): GadgetMediaOutput[] {\n    return this.aggregator.getSubtreeMedia(nodeId);\n  }\n\n  /**\n   * Check if a subtree is complete (all nodes finished).\n   */\n  isSubtreeComplete(nodeId: NodeId): boolean {\n    return this.aggregator.isSubtreeComplete(nodeId);\n  }\n\n  /**\n   * Get node counts.\n   */\n  getNodeCount(): { llmCalls: number; gadgets: number } {\n    return this.aggregator.getNodeCount();\n  }\n\n  // ===========================================================================\n  // Event Subscription\n  // ===========================================================================\n\n  /**\n   * Subscribe to events of a specific type.\n   * Returns unsubscribe function.\n   *\n   * @param type - Event type to subscribe to (use \"*\" for all events)\n   * @param listener - Callback function that receives matching events\n   * @returns Unsubscribe function\n   *\n   * @example\n   * ```typescript\n   * const unsubscribe = tree.on(\"gadget_complete\", (event) => {\n   *   if (event.type === \"gadget_complete\") {\n   *     console.log(`Gadget ${event.name} completed`);\n   *   }\n   * });\n   * ```\n   */\n  on(type: ExecutionEventType, listener: (event: ExecutionEvent) => void): () => void {\n    return this.emitter.on(type, listener);\n  }\n\n  /**\n   * Subscribe to all events.\n   */\n  onAll(listener: (event: ExecutionEvent) => void): () => void {\n    return this.emitter.onAll(listener);\n  }\n\n  /**\n   * Get async iterable of all events.\n   * Events are yielded as they occur.\n   */\n  events(): AsyncGenerator<ExecutionEvent> {\n    return this.emitter.events();\n  }\n\n  /**\n   * Mark the tree as complete (no more events will be emitted).\n   * Wakes up any consumers waiting in the events() async generator.\n   */\n  complete(): void {\n    this.emitter.complete();\n  }\n\n  /**\n   * Check if the tree is complete.\n   */\n  isComplete(): boolean {\n    return this.emitter.isComplete();\n  }\n}\n","// Gadget marker constants\nexport const GADGET_START_PREFIX = \"!!!GADGET_START:\";\nexport const GADGET_END_PREFIX = \"!!!GADGET_END\";\nexport const GADGET_ARG_PREFIX = \"!!!ARG:\";\n\n// Default configuration values\nexport const DEFAULT_MAX_TOKENS = 1024;\nexport const DEFAULT_MAX_ITERATIONS = 10;\n\n// Gadget output limiting defaults\n/** Default: gadget output limiting is enabled */\nexport const DEFAULT_GADGET_OUTPUT_LIMIT = true;\n\n/** Default: limit gadget output to 15% of context window */\nexport const DEFAULT_GADGET_OUTPUT_LIMIT_PERCENT = 15;\n\n/** Approximate characters per token for 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 * Model shortcuts and aliases for more expressive DX.\n *\n * This module provides convenient aliases for common model names,\n * allowing developers to use short, memorable names instead of\n * verbose provider:model-id formats.\n *\n * @example\n * ```typescript\n * // Instead of:\n * model: \"openai:gpt-5-nano\"\n *\n * // You can use:\n * model: \"gpt5-nano\"\n * // or even:\n * model: \"gpt-5-nano\" // Auto-detects provider\n * ```\n */\n\n/**\n * Map of common model aliases to their full provider:model-id format.\n *\n * Updated: 2025-12-20\n */\nexport const MODEL_ALIASES: Record<string, string> = {\n  // OpenAI aliases - GPT-5.2 is the latest flagship\n  gpt4: \"openai:gpt-4o\",\n  gpt4o: \"openai:gpt-4o\",\n  \"gpt4o-mini\": \"openai:gpt-4o-mini\",\n  gpt5: \"openai:gpt-5.2\", // Latest flagship\n  \"gpt5.2\": \"openai:gpt-5.2\",\n  \"gpt5.1\": \"openai:gpt-5.1\",\n  \"gpt5-mini\": \"openai:gpt-5-mini\",\n  \"gpt5-nano\": \"openai:gpt-5-nano\",\n  \"gpt5-codex\": \"openai:gpt-5-codex\",\n  o1: \"openai:o1\",\n  o3: \"openai:o3\",\n  \"o4-mini\": \"openai:o4-mini\",\n\n  // Anthropic aliases\n  sonnet: \"anthropic:claude-sonnet-4-5\",\n  \"claude-sonnet\": \"anthropic:claude-sonnet-4-5\",\n  haiku: \"anthropic:claude-haiku-4-5\",\n  \"claude-haiku\": \"anthropic:claude-haiku-4-5\",\n  opus: \"anthropic:claude-opus-4-5\",\n  \"claude-opus\": \"anthropic:claude-opus-4-5\",\n\n  // Gemini aliases - 2.5 Flash is the recommended fast model\n  flash: \"gemini:gemini-2.5-flash\",\n  \"gemini-flash\": \"gemini:gemini-2.5-flash\",\n  \"flash-lite\": \"gemini:gemini-2.5-flash-lite\",\n  \"gemini-pro\": \"gemini:gemini-3-pro-preview\",\n  pro: \"gemini:gemini-3-pro-preview\",\n\n  // OpenRouter aliases (or: prefix for short)\n  \"or:sonnet\": \"openrouter:anthropic/claude-sonnet-4-5\",\n  \"or:opus\": \"openrouter:anthropic/claude-opus-4-5\",\n  \"or:haiku\": \"openrouter:anthropic/claude-haiku-4-5\",\n  \"or:gpt4o\": \"openrouter:openai/gpt-4o\",\n  \"or:gpt5\": \"openrouter:openai/gpt-5.2\",\n  \"or:flash\": \"openrouter:google/gemini-2.5-flash\",\n  \"or:llama\": \"openrouter:meta-llama/llama-3.3-70b-instruct\",\n  \"or:deepseek\": \"openrouter:deepseek/deepseek-r1\",\n};\n\n/**\n * Options for resolveModel function.\n */\nexport interface ResolveModelOptions {\n  /**\n   * If true, throw an error for unknown model names instead of falling back to OpenAI.\n   * This helps catch typos like \"gp4\" instead of \"gpt4\".\n   * Default: false\n   */\n  strict?: boolean;\n\n  /**\n   * If true, suppress warnings for unknown model names.\n   * Default: false\n   */\n  silent?: boolean;\n}\n\n/**\n * Known model name patterns for validation.\n * These patterns help detect typos and unknown models.\n */\nconst KNOWN_MODEL_PATTERNS = [\n  /^gpt-?\\d/i, // gpt-4, gpt-3.5, gpt4, etc.\n  /^claude-?\\d/i, // claude-3, claude-2, etc.\n  /^gemini-?(\\d|pro|flash)/i, // gemini-2.0, gemini-pro, gemini-flash, etc.\n  /^o\\d/i, // OpenAI o1, o3, etc.\n];\n\n/**\n * Check if a model name matches known patterns.\n *\n * @param model - Model name to check\n * @returns True if the model matches a known pattern\n */\nfunction isKnownModelPattern(model: string): boolean {\n  const normalized = model.toLowerCase();\n\n  // Check if it's a known alias\n  if (MODEL_ALIASES[normalized]) {\n    return true;\n  }\n\n  // Check against known patterns\n  return KNOWN_MODEL_PATTERNS.some((pattern) => pattern.test(model));\n}\n\n/**\n * Resolves a model name to its full provider:model format.\n *\n * Supports:\n * - Direct aliases: 'gpt5', 'sonnet', 'flash'\n * - Auto-detection: 'gpt-5-nano' → 'openai:gpt-5-nano'\n * - Pass-through: 'openai:gpt-5' → 'openai:gpt-5'\n *\n * Warnings:\n * - Logs a warning when an unknown model name falls back to OpenAI\n * - Use { strict: true } to throw an error instead\n * - Use { silent: true } to suppress warnings\n *\n * @param model - Model name or alias\n * @param options - Resolution options\n * @returns Full provider:model-id string\n *\n * @example\n * ```typescript\n * resolveModel('gpt5')              // → 'openai:gpt-5'\n * resolveModel('sonnet')            // → 'anthropic:claude-sonnet-4-5'\n * resolveModel('gpt-5-nano')        // → 'openai:gpt-5-nano'\n * resolveModel('openai:gpt-5')      // → 'openai:gpt-5' (passthrough)\n * resolveModel('claude-3-5-sonnet') // → 'anthropic:claude-3-5-sonnet'\n *\n * // Typo detection\n * resolveModel('gp5')  // ⚠️ Warning: Unknown model 'gp5', falling back to 'openai:gp5'\n *\n * // Strict mode (throws on typos)\n * resolveModel('gp5', { strict: true })  // ❌ Error: Unknown model 'gp5'\n * ```\n */\nexport function resolveModel(model: string, options: ResolveModelOptions = {}): string {\n  // Check if it's a known alias first (this handles or:* aliases too)\n  const normalized = model.toLowerCase();\n  if (MODEL_ALIASES[normalized]) {\n    return MODEL_ALIASES[normalized];\n  }\n\n  // Already has provider prefix - pass through\n  if (model.includes(\":\")) {\n    return model;\n  }\n\n  // Smart detection by model name patterns\n  // OpenAI models start with 'gpt'\n  if (normalized.startsWith(\"gpt\")) {\n    return `openai:${model}`;\n  }\n\n  // Anthropic models start with 'claude'\n  if (normalized.startsWith(\"claude\")) {\n    return `anthropic:${model}`;\n  }\n\n  // Gemini models start with 'gemini'\n  if (normalized.startsWith(\"gemini\")) {\n    return `gemini:${model}`;\n  }\n\n  // OpenAI o-series models (o1, o3, etc.)\n  if (normalized.match(/^o\\d/)) {\n    return `openai:${model}`;\n  }\n\n  // Unknown model: validate and warn/error\n  if (!isKnownModelPattern(model)) {\n    if (options.strict) {\n      throw new Error(\n        `Unknown model '${model}'. Did you mean one of: gpt4, sonnet, haiku, flash? ` +\n          `Use explicit provider prefix like 'openai:${model}' to bypass this check.`,\n      );\n    }\n\n    if (!options.silent) {\n      console.warn(\n        `⚠️  Unknown model '${model}', falling back to 'openai:${model}'. ` +\n          `This might be a typo. Did you mean: gpt4, gpt5, gpt5-nano, sonnet, haiku, flash? ` +\n          `Use { strict: true } to error on unknown models, or { silent: true } to suppress this warning.`,\n      );\n    }\n  }\n\n  // Default: assume OpenAI for unknown models\n  // This provides a reasonable fallback for most cases\n  return `openai:${model}`;\n}\n\n/**\n * Check if a model string is already in provider:model format.\n *\n * @param model - Model string to check\n * @returns True if the model has a provider prefix\n *\n * @example\n * ```typescript\n * hasProviderPrefix('openai:gpt-4o')    // → true\n * hasProviderPrefix('gpt4')              // → false\n * hasProviderPrefix('claude-3-5-sonnet') // → false\n * ```\n */\nexport function hasProviderPrefix(model: string): boolean {\n  return model.includes(\":\");\n}\n\n/**\n * Extract the provider from a full model string.\n *\n * @param model - Full model string (provider:model-id)\n * @returns Provider name, or undefined if no prefix\n *\n * @example\n * ```typescript\n * getProvider('openai:gpt-4o')     // → 'openai'\n * getProvider('anthropic:claude')  // → 'anthropic'\n * getProvider('gpt4')              // → undefined\n * ```\n */\nexport function getProvider(model: string): string | undefined {\n  const separatorIndex = model.indexOf(\":\");\n  if (separatorIndex === -1) {\n    return undefined;\n  }\n  return model.slice(0, separatorIndex);\n}\n\n/**\n * Extract the model ID from a full model string.\n *\n * @param model - Full model string (provider:model-id)\n * @returns Model ID, or the original string if no prefix\n *\n * @example\n * ```typescript\n * getModelId('openai:gpt-4o')      // → 'gpt-4o'\n * getModelId('anthropic:claude')   // → 'claude'\n * getModelId('gpt4')               // → 'gpt4'\n * ```\n */\nexport function getModelId(model: string): string {\n  const separatorIndex = model.indexOf(\":\");\n  if (separatorIndex === -1) {\n    return model;\n  }\n  return model.slice(separatorIndex + 1);\n}\n\n/**\n * Strip the provider prefix from a model string.\n *\n * Identical to {@link getModelId}: removes the `provider:` portion and returns\n * just the model ID. If there is no prefix, the original string is returned.\n *\n * Use this when you need the bare model ID (e.g. for a cost-registry lookup)\n * and the input may or may not carry a provider prefix.\n *\n * @param modelId - Full model string, optionally with provider prefix\n * @returns Model ID without provider prefix\n *\n * @example\n * ```typescript\n * stripProviderPrefix('openai:gpt-4o')          // → 'gpt-4o'\n * stripProviderPrefix('anthropic:claude-sonnet') // → 'claude-sonnet'\n * stripProviderPrefix('gpt-4o')                 // → 'gpt-4o'  (no prefix — returned as-is)\n * ```\n */\nexport function stripProviderPrefix(modelId: string): string {\n  return getModelId(modelId);\n}\n","/**\n * Proactive rate limiting for LLM API calls.\n *\n * Tracks request and token usage in sliding windows to prevent rate limit errors\n * before they occur. Works in conjunction with reactive backoff (retry.ts) for\n * comprehensive rate limit handling.\n */\n\n/**\n * Configuration for proactive rate limiting.\n *\n * Set these values based on your API tier to prevent rate limit errors.\n * When limits are approached, requests will be automatically delayed.\n *\n * @example\n * ```typescript\n * // Gemini free tier limits\n * const agent = LLMist.createAgent()\n *   .withRateLimits({\n *     requestsPerMinute: 15,\n *     tokensPerMinute: 1_000_000,\n *     safetyMargin: 0.8,\n *   });\n *\n * // OpenAI Tier 1 limits\n * const agent = LLMist.createAgent()\n *   .withRateLimits({\n *     requestsPerMinute: 500,\n *     tokensPerMinute: 200_000,\n *   });\n * ```\n */\nexport interface RateLimitConfig {\n  /**\n   * Maximum requests per minute.\n   * Set based on your API tier. If not set, RPM limiting is disabled.\n   */\n  requestsPerMinute?: number;\n\n  /**\n   * Maximum tokens per minute (input + output combined).\n   * Set based on your API tier. If not set, TPM limiting is disabled.\n   */\n  tokensPerMinute?: number;\n\n  /**\n   * Maximum tokens per day (optional).\n   * Useful for Gemini free tier which has daily limits.\n   * If not set, daily limiting is disabled.\n   */\n  tokensPerDay?: number;\n\n  /**\n   * Safety margin - start throttling at this percentage of limit.\n   * A value of 0.9 means throttling starts at 90% of the limit.\n   * Lower values provide more safety but may reduce throughput.\n   * @default 0.9\n   */\n  safetyMargin?: number;\n\n  /**\n   * Whether proactive rate limiting is enabled.\n   * @default true (when any limit is configured)\n   */\n  enabled?: boolean;\n}\n\n/**\n * Resolved rate limit configuration with all defaults applied.\n */\nexport interface ResolvedRateLimitConfig {\n  requestsPerMinute?: number;\n  tokensPerMinute?: number;\n  tokensPerDay?: number;\n  safetyMargin: number;\n  enabled: boolean;\n}\n\n/**\n * Default rate limit configuration values.\n */\nexport const DEFAULT_RATE_LIMIT_CONFIG: Pick<ResolvedRateLimitConfig, \"safetyMargin\" | \"enabled\"> =\n  {\n    safetyMargin: 0.9,\n    enabled: true,\n  };\n\n/**\n * Resolves a partial rate limit configuration by applying defaults.\n *\n * @param config - Partial configuration (optional)\n * @returns Fully resolved configuration\n */\nexport function resolveRateLimitConfig(config?: RateLimitConfig): ResolvedRateLimitConfig {\n  if (!config) {\n    return { safetyMargin: DEFAULT_RATE_LIMIT_CONFIG.safetyMargin, enabled: false };\n  }\n\n  const hasLimits =\n    config.requestsPerMinute !== undefined ||\n    config.tokensPerMinute !== undefined ||\n    config.tokensPerDay !== undefined;\n\n  return {\n    requestsPerMinute: config.requestsPerMinute,\n    tokensPerMinute: config.tokensPerMinute,\n    tokensPerDay: config.tokensPerDay,\n    safetyMargin: config.safetyMargin ?? DEFAULT_RATE_LIMIT_CONFIG.safetyMargin,\n    enabled: config.enabled ?? (hasLimits && DEFAULT_RATE_LIMIT_CONFIG.enabled),\n  };\n}\n\n/**\n * Information about a triggered rate limit.\n */\nexport interface TriggeredLimitInfo {\n  /** Current usage value */\n  current: number;\n  /** Configured limit value */\n  limit: number;\n  /** Effective limit after safety margin (limit × safetyMargin) */\n  effectiveLimit: number;\n}\n\n/**\n * Usage statistics from the rate limit tracker.\n */\nexport interface RateLimitStats {\n  /** Current requests per minute */\n  rpm: number;\n  /** Current tokens per minute */\n  tpm: number;\n  /** Tokens used today (UTC) */\n  dailyTokens: number;\n  /** Whether any limit is currently being approached */\n  isApproachingLimit: boolean;\n  /** Delay required before next request (0 if none) */\n  requiredDelayMs: number;\n  /** Which limit(s) triggered throttling, if any (present when requiredDelayMs > 0) */\n  triggeredBy?: {\n    rpm?: TriggeredLimitInfo;\n    tpm?: TriggeredLimitInfo;\n    daily?: TriggeredLimitInfo;\n  };\n}\n\n/**\n * Token usage entry for sliding window tracking.\n */\ninterface TokenUsageEntry {\n  timestamp: number;\n  tokens: number;\n}\n\n/**\n * Tracks API usage and calculates required delays for proactive rate limiting.\n *\n * Uses sliding windows to track requests and token usage, automatically\n * calculating delays needed to stay within configured limits.\n *\n * @example\n * ```typescript\n * const tracker = new RateLimitTracker({\n *   requestsPerMinute: 60,\n *   tokensPerMinute: 100000,\n * });\n *\n * // Before each request\n * const delay = tracker.getRequiredDelayMs();\n * if (delay > 0) {\n *   await sleep(delay);\n * }\n *\n * // After each request\n * tracker.recordUsage(inputTokens, outputTokens);\n * ```\n */\nexport class RateLimitTracker {\n  private config: ResolvedRateLimitConfig;\n\n  /** Timestamps of requests in the current minute window */\n  private requestTimestamps: number[] = [];\n\n  /** Token usage entries in the current minute window */\n  private tokenUsage: TokenUsageEntry[] = [];\n\n  /** Daily token count */\n  private dailyTokens = 0;\n\n  /** Date string (YYYY-MM-DD UTC) for daily reset tracking */\n  private dailyResetDate: string;\n\n  /** Count of pending reservations (for backward compatibility) */\n  private pendingReservations = 0;\n\n  constructor(config?: RateLimitConfig) {\n    this.config = resolveRateLimitConfig(config);\n    this.dailyResetDate = this.getCurrentDateUTC();\n  }\n\n  /**\n   * Record a completed request with its token usage.\n   *\n   * If reserveRequest() was called before the LLM call (recommended for concurrent\n   * scenarios), the request timestamp was already recorded. Otherwise, this method\n   * will add it for backward compatibility.\n   *\n   * @param inputTokens - Number of input tokens used\n   * @param outputTokens - Number of output tokens generated\n   */\n  recordUsage(inputTokens: number, outputTokens: number): void {\n    const now = Date.now();\n    const totalTokens = inputTokens + outputTokens;\n\n    // Check if this request was pre-reserved\n    if (this.pendingReservations > 0) {\n      // Request already counted by reserveRequest()\n      this.pendingReservations--;\n    } else {\n      // Legacy path: add request timestamp here (backward compatibility)\n      this.requestTimestamps.push(now);\n    }\n\n    // Record token usage\n    this.tokenUsage.push({ timestamp: now, tokens: totalTokens });\n\n    // Update daily tokens\n    this.checkDailyReset();\n    this.dailyTokens += totalTokens;\n\n    // Clean up old entries\n    this.pruneOldEntries(now);\n  }\n\n  /**\n   * Calculate the delay needed before the next request.\n   *\n   * Returns 0 if no delay is needed, otherwise returns the number of\n   * milliseconds to wait to stay within rate limits.\n   *\n   * @returns Delay in milliseconds (0 if none needed)\n   */\n  getRequiredDelayMs(): number {\n    if (!this.config.enabled) {\n      return 0;\n    }\n\n    const now = Date.now();\n    this.pruneOldEntries(now);\n    this.checkDailyReset();\n\n    let maxDelay = 0;\n\n    // Check RPM limit\n    if (this.config.requestsPerMinute !== undefined) {\n      const delay = this.calculateRpmDelay(now);\n      maxDelay = Math.max(maxDelay, delay);\n    }\n\n    // Check TPM limit\n    if (this.config.tokensPerMinute !== undefined) {\n      const delay = this.calculateTpmDelay(now);\n      maxDelay = Math.max(maxDelay, delay);\n    }\n\n    // Check daily token limit\n    if (this.config.tokensPerDay !== undefined) {\n      const effectiveLimit = this.config.tokensPerDay * this.config.safetyMargin;\n      if (this.dailyTokens >= effectiveLimit) {\n        // Daily limit reached - return time until midnight UTC\n        maxDelay = Math.max(maxDelay, this.getTimeUntilMidnightUTC());\n      }\n    }\n\n    return Math.ceil(maxDelay);\n  }\n\n  /**\n   * Check if we're approaching any configured limits.\n   *\n   * @returns true if any limit is at or above the safety margin threshold\n   */\n  isApproachingLimit(): boolean {\n    if (!this.config.enabled) {\n      return false;\n    }\n\n    const now = Date.now();\n    this.pruneOldEntries(now);\n    this.checkDailyReset();\n\n    // Check RPM\n    if (this.config.requestsPerMinute !== undefined) {\n      const currentRpm = this.requestTimestamps.length;\n      const threshold = this.config.requestsPerMinute * this.config.safetyMargin;\n      if (currentRpm >= threshold) {\n        return true;\n      }\n    }\n\n    // Check TPM\n    if (this.config.tokensPerMinute !== undefined) {\n      const currentTpm = this.tokenUsage.reduce((sum, entry) => sum + entry.tokens, 0);\n      const threshold = this.config.tokensPerMinute * this.config.safetyMargin;\n      if (currentTpm >= threshold) {\n        return true;\n      }\n    }\n\n    // Check daily tokens\n    if (this.config.tokensPerDay !== undefined) {\n      const threshold = this.config.tokensPerDay * this.config.safetyMargin;\n      if (this.dailyTokens >= threshold) {\n        return true;\n      }\n    }\n\n    return false;\n  }\n\n  /**\n   * Get current usage statistics.\n   *\n   * @returns Current usage stats for monitoring/logging\n   */\n  getUsageStats(): RateLimitStats {\n    const now = Date.now();\n    this.pruneOldEntries(now);\n    this.checkDailyReset();\n\n    const currentRpm = this.requestTimestamps.length;\n    const currentTpm = this.tokenUsage.reduce((sum, entry) => sum + entry.tokens, 0);\n\n    // Determine which limits triggered throttling\n    const triggeredBy: RateLimitStats[\"triggeredBy\"] = {};\n\n    if (this.config.requestsPerMinute !== undefined) {\n      const effectiveLimit = this.config.requestsPerMinute * this.config.safetyMargin;\n      if (currentRpm >= effectiveLimit) {\n        triggeredBy.rpm = {\n          current: currentRpm,\n          limit: this.config.requestsPerMinute,\n          effectiveLimit,\n        };\n      }\n    }\n\n    if (this.config.tokensPerMinute !== undefined) {\n      const effectiveLimit = this.config.tokensPerMinute * this.config.safetyMargin;\n      if (currentTpm >= effectiveLimit) {\n        triggeredBy.tpm = {\n          current: currentTpm,\n          limit: this.config.tokensPerMinute,\n          effectiveLimit,\n        };\n      }\n    }\n\n    if (this.config.tokensPerDay !== undefined) {\n      const effectiveLimit = this.config.tokensPerDay * this.config.safetyMargin;\n      if (this.dailyTokens >= effectiveLimit) {\n        triggeredBy.daily = {\n          current: this.dailyTokens,\n          limit: this.config.tokensPerDay,\n          effectiveLimit,\n        };\n      }\n    }\n\n    return {\n      rpm: currentRpm,\n      tpm: currentTpm,\n      dailyTokens: this.dailyTokens,\n      isApproachingLimit: this.isApproachingLimit(),\n      requiredDelayMs: this.getRequiredDelayMs(),\n      triggeredBy: Object.keys(triggeredBy).length > 0 ? triggeredBy : undefined,\n    };\n  }\n\n  /**\n   * Reset all tracking state.\n   * Useful for testing or when switching API keys/tiers.\n   */\n  reset(): void {\n    this.requestTimestamps = [];\n    this.tokenUsage = [];\n    this.dailyTokens = 0;\n    this.dailyResetDate = this.getCurrentDateUTC();\n    this.pendingReservations = 0;\n  }\n\n  /**\n   * Update configuration dynamically.\n   * Useful when API tier changes or for testing.\n   *\n   * @param config - New configuration to apply\n   */\n  updateConfig(config: RateLimitConfig): void {\n    this.config = resolveRateLimitConfig(config);\n  }\n\n  /**\n   * Reserve a request slot before making an LLM call.\n   *\n   * This is critical for concurrent subagents sharing a rate limiter.\n   * Without reservation, multiple subagents checking getRequiredDelayMs()\n   * simultaneously would all see zero usage and proceed, causing rate limit errors.\n   *\n   * Call this AFTER waiting for getRequiredDelayMs() but BEFORE making the LLM call.\n   * The reservation ensures subsequent concurrent checks see the pending request.\n   *\n   * @example\n   * ```typescript\n   * // Proactive rate limiting with reservation\n   * const delay = tracker.getRequiredDelayMs();\n   * if (delay > 0) await sleep(delay);\n   *\n   * tracker.reserveRequest(); // Claim slot BEFORE making call\n   * try {\n   *   const result = await llm.call();\n   *   tracker.recordUsage(result.inputTokens, result.outputTokens);\n   * } catch (error) {\n   *   // Request already reserved; recordUsage updates token count\n   *   throw error;\n   * }\n   * ```\n   */\n  reserveRequest(): void {\n    const now = Date.now();\n    this.requestTimestamps.push(now);\n    this.pendingReservations++;\n  }\n\n  // ─────────────────────────────────────────────────────────────────────────\n  // Private methods\n  // ─────────────────────────────────────────────────────────────────────────\n\n  /**\n   * Calculate delay needed based on RPM limit.\n   */\n  private calculateRpmDelay(now: number): number {\n    const effectiveLimit = this.config.requestsPerMinute! * this.config.safetyMargin;\n    const currentRpm = this.requestTimestamps.length;\n\n    if (currentRpm < effectiveLimit) {\n      return 0;\n    }\n\n    // Find the oldest request and calculate when it will expire from the window\n    const oldestTimestamp = this.requestTimestamps[0];\n    if (oldestTimestamp === undefined) {\n      return 0;\n    }\n\n    // Wait until the oldest request expires from the 1-minute window\n    const expiryTime = oldestTimestamp + 60000;\n    return Math.max(0, expiryTime - now);\n  }\n\n  /**\n   * Calculate delay needed based on TPM limit.\n   */\n  private calculateTpmDelay(now: number): number {\n    const effectiveLimit = this.config.tokensPerMinute! * this.config.safetyMargin;\n    const currentTpm = this.tokenUsage.reduce((sum, entry) => sum + entry.tokens, 0);\n\n    if (currentTpm < effectiveLimit) {\n      return 0;\n    }\n\n    // Find when enough tokens will expire to be under the limit\n    // Sort by timestamp (should already be sorted, but be safe)\n    const sorted = [...this.tokenUsage].sort((a, b) => a.timestamp - b.timestamp);\n\n    let tokensToFree = currentTpm - effectiveLimit;\n    let delay = 0;\n\n    for (const entry of sorted) {\n      tokensToFree -= entry.tokens;\n      if (tokensToFree <= 0) {\n        delay = entry.timestamp + 60000 - now;\n        break;\n      }\n    }\n\n    return Math.max(0, delay);\n  }\n\n  /**\n   * Remove entries older than 1 minute from the sliding window.\n   */\n  private pruneOldEntries(now: number): void {\n    const cutoff = now - 60000;\n\n    // Prune request timestamps\n    while (this.requestTimestamps.length > 0 && this.requestTimestamps[0]! < cutoff) {\n      this.requestTimestamps.shift();\n    }\n\n    // Prune token usage entries\n    while (this.tokenUsage.length > 0 && this.tokenUsage[0]!.timestamp < cutoff) {\n      this.tokenUsage.shift();\n    }\n  }\n\n  /**\n   * Check if the day has changed (UTC) and reset daily counters.\n   */\n  private checkDailyReset(): void {\n    const currentDate = this.getCurrentDateUTC();\n    if (currentDate !== this.dailyResetDate) {\n      this.dailyTokens = 0;\n      this.dailyResetDate = currentDate;\n    }\n  }\n\n  /**\n   * Get current date in YYYY-MM-DD format (UTC).\n   */\n  private getCurrentDateUTC(): string {\n    return new Date().toISOString().split(\"T\")[0]!;\n  }\n\n  /**\n   * Calculate milliseconds until midnight UTC.\n   */\n  private getTimeUntilMidnightUTC(): number {\n    const now = new Date();\n    const midnight = new Date(\n      Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate() + 1),\n    );\n    return midnight.getTime() - now.getTime();\n  }\n}\n","/**\n * Retry configuration for LLM API calls.\n *\n * Provides exponential backoff with jitter to handle transient failures\n * like rate limits (429), server errors (5xx), and connection issues.\n */\n\n/**\n * Configuration options for retry behavior.\n *\n * @example\n * ```typescript\n * // Custom retry with monitoring\n * const agent = LLMist.createAgent()\n *   .withRetry({\n *     retries: 5,\n *     minTimeout: 2000,\n *     onRetry: (error, attempt) => console.log(`Retry ${attempt}`),\n *   })\n *   .ask(\"Hello\");\n * ```\n */\nexport interface RetryConfig {\n  /**\n   * Whether retry is enabled.\n   * @default true\n   */\n  enabled?: boolean;\n\n  /**\n   * Maximum number of retry attempts.\n   * @default 3\n   */\n  retries?: number;\n\n  /**\n   * Minimum delay before the first retry in milliseconds.\n   * @default 1000\n   */\n  minTimeout?: number;\n\n  /**\n   * Maximum delay between retries in milliseconds.\n   * @default 30000\n   */\n  maxTimeout?: number;\n\n  /**\n   * Exponential factor for backoff calculation.\n   * @default 2\n   */\n  factor?: number;\n\n  /**\n   * Whether to add random jitter to prevent thundering herd.\n   * @default true\n   */\n  randomize?: boolean;\n\n  /**\n   * Called before each retry attempt.\n   * Use for logging or metrics.\n   */\n  onRetry?: (error: Error, attempt: number) => void;\n\n  /**\n   * Called when all retries are exhausted and the operation fails.\n   * The error will still be thrown after this callback.\n   */\n  onRetriesExhausted?: (error: Error, attempts: number) => void;\n\n  /**\n   * Custom function to determine if an error should trigger a retry.\n   * If not provided, uses the default `isRetryableError` classification.\n   *\n   * @returns true to retry, false to fail immediately\n   */\n  shouldRetry?: (error: Error) => boolean;\n\n  /**\n   * Whether to respect Retry-After headers from providers.\n   * When true, delays will be adjusted to honor server-requested wait times.\n   * Supported providers: Anthropic, OpenAI (HTTP headers), Gemini (error message parsing).\n   * @default true\n   */\n  respectRetryAfter?: boolean;\n\n  /**\n   * Maximum wait time to honor from Retry-After headers (in milliseconds).\n   * If a server requests a longer wait, this cap is used instead.\n   * @default 120000 (2 minutes)\n   */\n  maxRetryAfterMs?: number;\n\n  /**\n   * Whether to treat an empty completion (a 200-OK response with no text,\n   * no tool calls, and no reasoning) as a transient failure and retry it.\n   * When all attempts come back empty, an `EmptyCompletionError` is thrown\n   * rather than committing a silent blank turn. Only takes effect when\n   * `enabled` is true.\n   * @default true\n   */\n  retryOnEmpty?: boolean;\n}\n\n/**\n * Resolved retry configuration with all defaults applied.\n */\nexport interface ResolvedRetryConfig {\n  enabled: boolean;\n  retries: number;\n  minTimeout: number;\n  maxTimeout: number;\n  factor: number;\n  randomize: boolean;\n  onRetry?: (error: Error, attempt: number) => void;\n  onRetriesExhausted?: (error: Error, attempts: number) => void;\n  shouldRetry?: (error: Error) => boolean;\n  respectRetryAfter: boolean;\n  maxRetryAfterMs: number;\n  retryOnEmpty: boolean;\n}\n\n/**\n * Default retry configuration values.\n * Conservative defaults: 3 retries with up to 30s delay, respecting Retry-After headers.\n */\nexport const DEFAULT_RETRY_CONFIG: Omit<\n  ResolvedRetryConfig,\n  \"onRetry\" | \"onRetriesExhausted\" | \"shouldRetry\"\n> = {\n  enabled: true,\n  retries: 3,\n  minTimeout: 1000,\n  maxTimeout: 30000,\n  factor: 2,\n  randomize: true,\n  respectRetryAfter: true,\n  maxRetryAfterMs: 120000, // 2 minutes cap\n  retryOnEmpty: true,\n};\n\n/**\n * Resolves a partial retry configuration by applying defaults.\n *\n * @param config - Partial configuration (optional)\n * @returns Fully resolved configuration with defaults applied\n */\nexport function resolveRetryConfig(config?: RetryConfig): ResolvedRetryConfig {\n  if (!config) {\n    return { ...DEFAULT_RETRY_CONFIG };\n  }\n\n  return {\n    enabled: config.enabled ?? DEFAULT_RETRY_CONFIG.enabled,\n    retries: config.retries ?? DEFAULT_RETRY_CONFIG.retries,\n    minTimeout: config.minTimeout ?? DEFAULT_RETRY_CONFIG.minTimeout,\n    maxTimeout: config.maxTimeout ?? DEFAULT_RETRY_CONFIG.maxTimeout,\n    factor: config.factor ?? DEFAULT_RETRY_CONFIG.factor,\n    randomize: config.randomize ?? DEFAULT_RETRY_CONFIG.randomize,\n    onRetry: config.onRetry,\n    onRetriesExhausted: config.onRetriesExhausted,\n    shouldRetry: config.shouldRetry,\n    respectRetryAfter: config.respectRetryAfter ?? DEFAULT_RETRY_CONFIG.respectRetryAfter,\n    maxRetryAfterMs: config.maxRetryAfterMs ?? DEFAULT_RETRY_CONFIG.maxRetryAfterMs,\n    retryOnEmpty: config.retryOnEmpty ?? DEFAULT_RETRY_CONFIG.retryOnEmpty,\n  };\n}\n\n/**\n * Extract numeric status code from error object.\n * Handles common patterns: error.status, error.code, error.statusCode\n */\nfunction getErrorStatusCode(error: Error): number | undefined {\n  const errAny = error as unknown as Record<string, unknown>;\n\n  // Check common status properties\n  if (typeof errAny.status === \"number\") return errAny.status;\n  if (typeof errAny.code === \"number\") return errAny.code;\n  if (typeof errAny.statusCode === \"number\") return errAny.statusCode;\n\n  // Some errors have string codes like \"502\"\n  if (typeof errAny.code === \"string\" && /^\\d{3}$/.test(errAny.code)) {\n    return parseInt(errAny.code, 10);\n  }\n\n  return undefined;\n}\n\n/**\n * Determines if an error is retryable based on common LLM API error patterns.\n *\n * Retryable errors include:\n * - Rate limits (429)\n * - Server errors (500, 502, 503, 504)\n * - Timeouts and connection errors\n * - Provider-specific transient errors\n *\n * Non-retryable errors include:\n * - Authentication errors (401, 403)\n * - Bad request errors (400)\n * - Not found errors (404)\n * - Content policy violations\n *\n * @param error - The error to classify\n * @returns true if the error is retryable\n */\nexport function isRetryableError(error: Error): boolean {\n  const message = error.message.toLowerCase();\n  const name = error.name;\n  const statusCode = getErrorStatusCode(error);\n\n  // Check numeric status code first (most reliable)\n  if (statusCode !== undefined) {\n    // Rate limit (429) - retry\n    if (statusCode === 429) return true;\n    // Server errors (5xx) - retry\n    if (statusCode >= 500 && statusCode < 600) return true;\n    // Client errors (4xx except 429) - don't retry\n    if (statusCode >= 400 && statusCode < 500) return false;\n  }\n\n  // Rate limits (429) - always retry\n  if (message.includes(\"429\") || message.includes(\"rate limit\") || message.includes(\"rate_limit\")) {\n    return true;\n  }\n\n  // Server errors (5xx) - retry\n  if (\n    message.includes(\"500\") ||\n    message.includes(\"502\") ||\n    message.includes(\"503\") ||\n    message.includes(\"504\") ||\n    message.includes(\"internal server error\") ||\n    message.includes(\"bad gateway\") ||\n    message.includes(\"service unavailable\") ||\n    message.includes(\"gateway timeout\")\n  ) {\n    return true;\n  }\n\n  // Timeouts - retry\n  if (\n    message.includes(\"timeout\") ||\n    message.includes(\"etimedout\") ||\n    message.includes(\"timed out\")\n  ) {\n    return true;\n  }\n\n  // Connection errors - retry\n  if (\n    message.includes(\"econnreset\") ||\n    message.includes(\"econnrefused\") ||\n    message.includes(\"enotfound\") ||\n    message.includes(\"connection\") ||\n    message.includes(\"network\")\n  ) {\n    return true;\n  }\n\n  // Provider-specific error names (from Anthropic, OpenAI SDKs)\n  if (\n    name === \"APIConnectionError\" ||\n    name === \"RateLimitError\" ||\n    name === \"InternalServerError\" ||\n    name === \"ServiceUnavailableError\" ||\n    name === \"APITimeoutError\"\n  ) {\n    return true;\n  }\n\n  // Overloaded errors (common with Claude)\n  if (message.includes(\"overloaded\") || message.includes(\"capacity\")) {\n    return true;\n  }\n\n  // Gemini-specific retryable errors (gRPC status codes)\n  if (\n    message.includes(\"resource_exhausted\") ||\n    message.includes(\"quota exceeded\") ||\n    message.includes(\"unavailable\") ||\n    message.includes(\"deadline_exceeded\")\n  ) {\n    return true;\n  }\n\n  // Anthropic-specific retryable errors\n  if (message.includes(\"overloaded_error\") || message.includes(\"api_error\")) {\n    return true;\n  }\n\n  // HuggingFace-specific: 400 errors on serverless are often transient (model loading, capacity)\n  // These are wrapped by the HF provider with \"hf bad request\" prefix\n  if (message.includes(\"hf bad request\")) {\n    return true;\n  }\n\n  // SSE stream parsing errors (Gemini SDK and proxy layers)\n  // These occur when the API injects errors into the SSE stream mid-response,\n  // the stream ends with truncated data, or chunks fail to parse.\n  if (\n    message.includes(\"incomplete json segment\") ||\n    message.includes(\"exception parsing stream chunk\") ||\n    message.includes(\"json error injected into sse stream\") ||\n    (message.includes(\"sending request\") && message.includes(\"exception\")) ||\n    (message.includes(\"invalid chunk\") && message.includes(\"finish reason\")) ||\n    message.includes(\"unexpected line format\")\n  ) {\n    return true;\n  }\n\n  // Don't retry authentication, bad requests, or content policy errors\n  if (\n    message.includes(\"401\") ||\n    message.includes(\"403\") ||\n    message.includes(\"400\") ||\n    message.includes(\"404\") ||\n    message.includes(\"authentication\") ||\n    message.includes(\"unauthorized\") ||\n    message.includes(\"forbidden\") ||\n    message.includes(\"invalid\") ||\n    message.includes(\"content policy\") ||\n    name === \"AuthenticationError\" ||\n    name === \"BadRequestError\" ||\n    name === \"NotFoundError\" ||\n    name === \"PermissionDeniedError\"\n  ) {\n    return false;\n  }\n\n  // Default: don't retry unknown errors\n  return false;\n}\n\n/**\n * Heuristically detects whether an error is likely caused by context overflow\n * (request too large for the provider/model), as opposed to other 400 errors\n * like authentication failures or content policy violations.\n *\n * Used by the agent's main loop to decide whether forced compaction + retry\n * is a viable recovery strategy.\n *\n * @param error - The error to classify\n * @returns true if the error is likely a context overflow\n */\nexport function isLikelyContextOverflow(error: Error): boolean {\n  const message = error.message.toLowerCase();\n  const statusCode = getErrorStatusCode(error);\n\n  // Explicit overflow keywords — match regardless of status code.\n  // These are unambiguous signals from providers that the request is too large.\n  if (\n    message.includes(\"context length\") ||\n    message.includes(\"token limit\") ||\n    message.includes(\"payload too large\") ||\n    message.includes(\"request too large\") ||\n    message.includes(\"request entity too large\") ||\n    message.includes(\"maximum context\") ||\n    message.includes(\"content size exceeded\") ||\n    message.includes(\"content too large\")\n  ) {\n    return true;\n  }\n\n  // Must be a 400-class error (by status code or message) to continue\n  const is400 = statusCode === 400 || (statusCode === undefined && message.includes(\"400\"));\n  if (!is400) {\n    return false;\n  }\n\n  // Exclude 400 errors that are clearly not context overflow.\n  // This list must be broader than the auth-only check — many 400 reasons\n  // indicate bad parameters, not an oversized request.\n  if (\n    message.includes(\"authentication\") ||\n    message.includes(\"unauthorized\") ||\n    message.includes(\"invalid api key\") ||\n    message.includes(\"invalid key\") ||\n    message.includes(\"invalid model\") ||\n    message.includes(\"invalid parameter\") ||\n    message.includes(\"content policy\") ||\n    message.includes(\"safety\") ||\n    message.includes(\"permission\") ||\n    message.includes(\"unsupported\") ||\n    message.includes(\"not supported\") ||\n    message.includes(\"missing required\") ||\n    message.includes(\"malformed\") ||\n    message.includes(\"not found\")\n  ) {\n    return false;\n  }\n\n  // Generic 400 — could be context overflow from a provider that returns\n  // opaque error messages (e.g., OpenRouter's \"400 Provider returned error\")\n  return true;\n}\n\n/**\n * Context for enhanced error formatting.\n */\nexport interface FormatLLMErrorContext {\n  /** Provider name for provider-specific suggestions */\n  provider?: \"anthropic\" | \"openai\" | \"gemini\" | string;\n  /** Whether all retry attempts were exhausted */\n  retriesExhausted?: boolean;\n}\n\n/**\n * Formats an LLM API error into a clean, user-friendly message.\n *\n * Extracts the most relevant information from provider error objects,\n * hiding verbose JSON/stack traces while preserving actionable details.\n *\n * When retries are exhausted and provider is known, includes actionable\n * suggestions and links to provider documentation.\n *\n * @param error - The error to format\n * @param context - Optional context for enhanced error messages\n * @returns A clean error message, multi-line when retries exhausted\n *\n * @example\n * ```typescript\n * // Gemini RESOURCE_EXHAUSTED error\n * formatLLMError(error);\n * // Returns: \"Rate limit exceeded (429) - retry after a few seconds\"\n *\n * // With context and exhausted retries\n * formatLLMError(error, { provider: 'anthropic', retriesExhausted: true });\n * // Returns multi-line message with suggestions and documentation link\n * ```\n */\nexport function formatLLMError(error: Error, context?: FormatLLMErrorContext): string {\n  const message = error.message;\n  const name = error.name;\n\n  // Gemini RESOURCE_EXHAUSTED or 429 errors\n  if (message.includes(\"RESOURCE_EXHAUSTED\") || message.includes(\"429\")) {\n    let formatted = \"Rate limit exceeded (429)\";\n\n    // Add provider-specific suggestions if retries exhausted\n    if (context?.retriesExhausted) {\n      formatted += \"\\n\\nAll retry attempts exhausted. To resolve this:\";\n      formatted += \"\\n1. Configure higher rate limits in ~/.llmist/cli.toml\";\n      formatted += \"\\n2. Upgrade your API tier with the provider\";\n      formatted += \"\\n3. Add delays between requests (--rate-limit-rpm option)\";\n\n      // Provider-specific documentation\n      if (context?.provider) {\n        const docsUrls: Record<string, string> = {\n          anthropic: \"https://docs.anthropic.com/en/api/rate-limits\",\n          openai: \"https://platform.openai.com/docs/guides/rate-limits\",\n          gemini: \"https://ai.google.dev/gemini-api/docs/quota\",\n        };\n\n        const docsUrl = docsUrls[context.provider];\n        if (docsUrl) {\n          formatted += `\\n\\nProvider: ${context.provider}`;\n          formatted += `\\nDocumentation: ${docsUrl}`;\n        }\n      }\n    } else {\n      formatted += \" - retry after a few seconds\";\n    }\n\n    return formatted;\n  }\n\n  // Generic rate limit errors\n  if (\n    message.toLowerCase().includes(\"rate limit\") ||\n    message.toLowerCase().includes(\"rate_limit\")\n  ) {\n    let formatted = \"Rate limit exceeded\";\n\n    if (context?.retriesExhausted) {\n      formatted += \"\\n\\nAll retry attempts exhausted. To resolve this:\";\n      formatted += \"\\n1. Configure higher rate limits in ~/.llmist/cli.toml\";\n      formatted += \"\\n2. Upgrade your API tier with the provider\";\n      formatted += \"\\n3. Add delays between requests (--rate-limit-rpm option)\";\n\n      if (context?.provider) {\n        const docsUrls: Record<string, string> = {\n          anthropic: \"https://docs.anthropic.com/en/api/rate-limits\",\n          openai: \"https://platform.openai.com/docs/guides/rate-limits\",\n          gemini: \"https://ai.google.dev/gemini-api/docs/quota\",\n        };\n\n        const docsUrl = docsUrls[context.provider];\n        if (docsUrl) {\n          formatted += `\\n\\nProvider: ${context.provider}`;\n          formatted += `\\nDocumentation: ${docsUrl}`;\n        }\n      }\n    } else {\n      formatted += \" - retry after a few seconds\";\n    }\n\n    return formatted;\n  }\n\n  // Overloaded/capacity errors\n  if (message.toLowerCase().includes(\"overloaded\") || message.toLowerCase().includes(\"capacity\")) {\n    return \"API overloaded - retry later\";\n  }\n\n  // Server errors\n  if (message.includes(\"500\") || message.toLowerCase().includes(\"internal server error\")) {\n    return \"Internal server error (500) - the API is experiencing issues\";\n  }\n  if (message.includes(\"502\") || message.toLowerCase().includes(\"bad gateway\")) {\n    return \"Bad gateway (502) - the API is temporarily unavailable\";\n  }\n  if (message.includes(\"503\") || message.toLowerCase().includes(\"service unavailable\")) {\n    return \"Service unavailable (503) - the API is temporarily down\";\n  }\n  if (message.includes(\"504\") || message.toLowerCase().includes(\"gateway timeout\")) {\n    return \"Gateway timeout (504) - the request took too long\";\n  }\n\n  // Timeout errors\n  if (message.toLowerCase().includes(\"timeout\") || message.toLowerCase().includes(\"timed out\")) {\n    return \"Request timed out - the API took too long to respond\";\n  }\n\n  // Connection errors\n  if (message.toLowerCase().includes(\"econnrefused\")) {\n    return \"Connection refused - unable to reach the API\";\n  }\n  if (message.toLowerCase().includes(\"econnreset\")) {\n    return \"Connection reset - the API closed the connection\";\n  }\n  if (message.toLowerCase().includes(\"enotfound\")) {\n    return \"DNS error - unable to resolve API hostname\";\n  }\n\n  // Auth errors\n  if (\n    message.includes(\"401\") ||\n    message.toLowerCase().includes(\"unauthorized\") ||\n    name === \"AuthenticationError\"\n  ) {\n    return \"Authentication failed - check your API key\";\n  }\n  if (\n    message.includes(\"403\") ||\n    message.toLowerCase().includes(\"forbidden\") ||\n    name === \"PermissionDeniedError\"\n  ) {\n    return \"Permission denied - your API key lacks required permissions\";\n  }\n\n  // Bad request\n  if (message.includes(\"400\") || name === \"BadRequestError\") {\n    // Try to extract a useful message from the error\n    const match = message.match(/message['\":\\s]+['\"]?([^'\"}\\]]+)/i);\n    if (match) {\n      return `Bad request: ${match[1].trim()}`;\n    }\n    return \"Bad request - check your input parameters\";\n  }\n\n  // Content policy\n  if (\n    message.toLowerCase().includes(\"content policy\") ||\n    message.toLowerCase().includes(\"safety\")\n  ) {\n    return \"Content policy violation - the request was blocked\";\n  }\n\n  // SSE stream parsing errors\n  if (\n    message.toLowerCase().includes(\"incomplete json segment\") ||\n    message.toLowerCase().includes(\"exception parsing stream chunk\") ||\n    message.toLowerCase().includes(\"json error injected into sse stream\") ||\n    (message.toLowerCase().includes(\"sending request\") &&\n      message.toLowerCase().includes(\"exception\")) ||\n    (message.toLowerCase().includes(\"invalid chunk\") &&\n      message.toLowerCase().includes(\"finish reason\")) ||\n    message.toLowerCase().includes(\"unexpected line format\")\n  ) {\n    return \"Stream interrupted - the API returned corrupted or incomplete data\";\n  }\n\n  // Try to extract a clean message from JSON errors\n  // First try proper JSON parsing (handles nested structures and escaped quotes)\n  try {\n    const parsed = JSON.parse(message);\n    // Support common API error structures: {error: {message: \"...\"}} or {message: \"...\"}\n    const extractedMessage = parsed?.error?.message || parsed?.message;\n    if (typeof extractedMessage === \"string\" && extractedMessage.length > 0) {\n      return extractedMessage.trim();\n    }\n  } catch {\n    // Not valid JSON, fall through to regex\n  }\n\n  // Fall back to regex extraction for malformed JSON or partial strings\n  const jsonMatch = message.match(/[\"']?message[\"']?\\s*[:=]\\s*[\"']([^\"']+)[\"']/i);\n  if (jsonMatch) {\n    return jsonMatch[1].trim();\n  }\n\n  // If the message is very long (likely JSON dump), truncate it\n  if (message.length > 200) {\n    // Try to find the first sentence or meaningful part\n    const firstPart = message.split(/[.!?\\n]/)[0];\n    if (firstPart && firstPart.length > 10 && firstPart.length < 150) {\n      return firstPart.trim();\n    }\n    return `${message.slice(0, 150).trim()}...`;\n  }\n\n  // Return the original message if we couldn't simplify it\n  return message;\n}\n\n/**\n * Parses a Retry-After header value into milliseconds.\n *\n * Supports two formats:\n * - Seconds: \"30\" → 30000ms\n * - HTTP date: \"Wed, 21 Oct 2015 07:28:00 GMT\" → milliseconds until that time\n *\n * @param value - The Retry-After header value\n * @returns Delay in milliseconds, or null if parsing fails\n */\nexport function parseRetryAfterHeader(value: string): number | null {\n  // Try as seconds first (most common)\n  const seconds = Number.parseFloat(value);\n  if (!Number.isNaN(seconds) && seconds > 0) {\n    return Math.ceil(seconds * 1000);\n  }\n\n  // Try as HTTP date\n  const date = Date.parse(value);\n  if (!Number.isNaN(date)) {\n    const delay = date - Date.now();\n    return delay > 0 ? delay : null;\n  }\n\n  return null;\n}\n\n/**\n * Error with headers property (common in Anthropic/OpenAI SDK errors).\n */\ninterface ErrorWithHeaders extends Error {\n  headers?: Record<string, string> | Headers;\n  response?: {\n    headers?: Record<string, string> | Headers;\n  };\n}\n\n/**\n * Extracts Retry-After delay from an error object.\n *\n * Supports multiple sources:\n * - Anthropic/OpenAI: error.headers['retry-after'] or error.response.headers\n * - Gemini: Parses \"retry after Xs\" from error message\n *\n * @param error - The error to extract Retry-After from\n * @returns Delay in milliseconds, or null if not found\n *\n * @example\n * ```typescript\n * // Anthropic/OpenAI SDK error with headers\n * const delay = extractRetryAfterMs(error); // e.g., 30000\n *\n * // Gemini RESOURCE_EXHAUSTED error\n * // \"Please retry in 45.283754998s\"\n * const delay = extractRetryAfterMs(error); // 45284\n * ```\n */\nexport function extractRetryAfterMs(error: Error): number | null {\n  const errorWithHeaders = error as ErrorWithHeaders;\n\n  // Check for headers property (Anthropic/OpenAI SDK errors)\n  const headers = errorWithHeaders.headers || errorWithHeaders.response?.headers;\n\n  if (headers) {\n    // Handle both Record<string, string> and Headers objects\n    const retryAfter =\n      typeof headers.get === \"function\"\n        ? headers.get(\"retry-after\")\n        : (headers as Record<string, string>)[\"retry-after\"];\n\n    if (retryAfter) {\n      const parsed = parseRetryAfterHeader(retryAfter);\n      if (parsed !== null) {\n        return parsed;\n      }\n    }\n  }\n\n  // Parse Gemini-style error messages\n  // Examples:\n  // - \"Please retry in 45.283754998s\"\n  // - \"retry after 30 seconds\"\n  // - \"Retry-After: 60\"\n  const message = error.message;\n\n  // Match patterns like \"retry in 45.28s\", \"retry after 30 seconds\", \"Retry-After: 60\"\n  const patterns = [\n    /retry\\s+(?:in|after)\\s+(\\d+(?:\\.\\d+)?)\\s*s(?:econds?)?/i,\n    /retry-after:\\s*(\\d+(?:\\.\\d+)?)/i,\n    /wait\\s+(\\d+(?:\\.\\d+)?)\\s*s(?:econds?)?/i,\n  ];\n\n  for (const pattern of patterns) {\n    const match = message.match(pattern);\n    if (match) {\n      const seconds = Number.parseFloat(match[1]);\n      if (!Number.isNaN(seconds) && seconds > 0) {\n        return Math.ceil(seconds * 1000);\n      }\n    }\n  }\n\n  // Default delay for known rate limit errors without explicit timing\n  // This provides a reasonable backoff when no Retry-After is specified\n  if (\n    message.toLowerCase().includes(\"resource_exhausted\") ||\n    message.toLowerCase().includes(\"quota exceeded\")\n  ) {\n    return 60000; // 60 seconds default for Gemini quota errors\n  }\n\n  return null;\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","/**\n * MediaStore: Session-scoped storage for gadget media outputs.\n *\n * This module provides an abstraction layer between gadgets and the filesystem.\n * Instead of exposing raw file paths, it assigns unique IDs to stored media\n * that can be shared with the LLM and user.\n *\n * @example\n * ```typescript\n * const store = new MediaStore();\n *\n * // Store an image, get back ID\n * const stored = await store.store({\n *   kind: \"image\",\n *   data: base64EncodedPng,\n *   mimeType: \"image/png\",\n *   description: \"Screenshot\"\n * }, \"Screenshot\");\n *\n * console.log(stored.id); // \"media_a1b2c3\"\n * console.log(stored.path); // \"/tmp/llmist-media-xxx/Screenshot_001.png\"\n *\n * // Later: retrieve by ID\n * const retrieved = store.get(\"media_a1b2c3\");\n * ```\n */\n\nimport { randomBytes } from \"node:crypto\";\nimport { mkdir, rm, writeFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { GadgetMediaOutput, MediaKind, StoredMedia } from \"./types.js\";\n\n// Re-export StoredMedia for convenience\nexport type { StoredMedia };\n\n/**\n * Get the llmist temp directory path.\n * Uses ~/.llmist/tmp for user-scoped storage.\n */\nfunction getLlmistTmpDir(): string {\n  return join(homedir(), \".llmist\", \"tmp\");\n}\n\n/**\n * Common MIME type to file extension mapping.\n */\nconst MIME_TO_EXTENSION: Record<string, string> = {\n  // Images\n  \"image/png\": \".png\",\n  \"image/jpeg\": \".jpg\",\n  \"image/gif\": \".gif\",\n  \"image/webp\": \".webp\",\n  \"image/svg+xml\": \".svg\",\n  \"image/bmp\": \".bmp\",\n  \"image/tiff\": \".tiff\",\n  // Audio\n  \"audio/mp3\": \".mp3\",\n  \"audio/mpeg\": \".mp3\",\n  \"audio/wav\": \".wav\",\n  \"audio/webm\": \".webm\",\n  \"audio/ogg\": \".ogg\",\n  \"audio/flac\": \".flac\",\n  \"audio/aac\": \".aac\",\n  // Video\n  \"video/mp4\": \".mp4\",\n  \"video/webm\": \".webm\",\n  \"video/ogg\": \".ogv\",\n  \"video/quicktime\": \".mov\",\n  \"video/x-msvideo\": \".avi\",\n  // Documents\n  \"application/pdf\": \".pdf\",\n  \"application/json\": \".json\",\n  \"text/plain\": \".txt\",\n  \"text/html\": \".html\",\n  \"text/css\": \".css\",\n  \"text/javascript\": \".js\",\n};\n\n/**\n * Session-scoped media storage with ID abstraction.\n *\n * Each MediaStore instance manages media for a single agent session.\n * Media files are stored in a temporary directory and referenced by\n * short, unique IDs rather than file paths.\n */\nexport class MediaStore {\n  private readonly items = new Map<string, StoredMedia>();\n  private readonly outputDir: string;\n  private counter = 0;\n  private initialized = false;\n\n  /**\n   * Create a new MediaStore.\n   *\n   * @param sessionId - Optional session ID for the output directory.\n   *                    If not provided, a random ID is generated.\n   */\n  constructor(sessionId?: string) {\n    const id = sessionId ?? randomBytes(8).toString(\"hex\");\n    this.outputDir = join(getLlmistTmpDir(), `media-${id}`);\n  }\n\n  /**\n   * Get the output directory path.\n   */\n  getOutputDir(): string {\n    return this.outputDir;\n  }\n\n  /**\n   * Ensure the output directory exists.\n   * @throws Error if directory creation fails\n   */\n  private async ensureDir(): Promise<void> {\n    if (this.initialized) return;\n\n    try {\n      await mkdir(this.outputDir, { recursive: true });\n      this.initialized = true;\n    } catch (error) {\n      throw new Error(\n        `MediaStore: Failed to create directory ${this.outputDir}: ${error instanceof Error ? error.message : String(error)}`,\n      );\n    }\n  }\n\n  /**\n   * Generate a unique media ID.\n   * Format: \"media_\" + 6 random alphanumeric characters\n   */\n  private generateId(): string {\n    const chars = \"abcdefghijklmnopqrstuvwxyz0123456789\";\n    let id = \"media_\";\n    const bytes = randomBytes(6);\n    for (let i = 0; i < 6; i++) {\n      id += chars[bytes[i] % chars.length];\n    }\n    return id;\n  }\n\n  /**\n   * Get file extension from MIME type.\n   */\n  private getExtension(mimeType: string): string {\n    return MIME_TO_EXTENSION[mimeType] ?? \".bin\";\n  }\n\n  /**\n   * Store media and return stored metadata with ID.\n   *\n   * @param media - The media output from a gadget\n   * @param gadgetName - Name of the gadget that created this media\n   * @returns Stored media information including generated ID\n   * @throws Error if file write fails\n   */\n  async store(media: GadgetMediaOutput, gadgetName: string): Promise<StoredMedia> {\n    await this.ensureDir();\n\n    const id = this.generateId();\n    const ext = this.getExtension(media.mimeType);\n    // Use provided fileName or generate one\n    const filename =\n      media.fileName ?? `${gadgetName}_${String(++this.counter).padStart(3, \"0\")}${ext}`;\n    const filePath = join(this.outputDir, filename);\n\n    // Decode base64 and write to file\n    const buffer = Buffer.from(media.data, \"base64\");\n\n    try {\n      await writeFile(filePath, buffer);\n    } catch (error) {\n      throw new Error(\n        `MediaStore: Failed to write media file ${filePath}: ${error instanceof Error ? error.message : String(error)}`,\n      );\n    }\n\n    const stored: StoredMedia = {\n      id,\n      kind: media.kind,\n      path: filePath,\n      mimeType: media.mimeType,\n      sizeBytes: buffer.length,\n      description: media.description,\n      metadata: media.metadata,\n      gadgetName,\n      createdAt: new Date(),\n    };\n\n    this.items.set(id, stored);\n    return stored;\n  }\n\n  /**\n   * Get stored media by ID.\n   *\n   * @param id - The media ID (e.g., \"media_a1b2c3\")\n   * @returns The stored media or undefined if not found\n   */\n  get(id: string): StoredMedia | undefined {\n    return this.items.get(id);\n  }\n\n  /**\n   * Get the actual file path for a media ID.\n   * Convenience method for gadgets that need the raw path.\n   *\n   * @param id - The media ID\n   * @returns The file path or undefined if not found\n   */\n  getPath(id: string): string | undefined {\n    return this.items.get(id)?.path;\n  }\n\n  /**\n   * List all stored media, optionally filtered by kind.\n   *\n   * @param kind - Optional media kind to filter by\n   * @returns Array of stored media items\n   */\n  list(kind?: MediaKind): StoredMedia[] {\n    const all = Array.from(this.items.values());\n    if (kind) {\n      return all.filter((item) => item.kind === kind);\n    }\n    return all;\n  }\n\n  /**\n   * Get the count of stored media items.\n   */\n  get size(): number {\n    return this.items.size;\n  }\n\n  /**\n   * Check if a media ID exists.\n   */\n  has(id: string): boolean {\n    return this.items.has(id);\n  }\n\n  /**\n   * Clear in-memory store without deleting files.\n   * Resets the counter but leaves files on disk.\n   */\n  clear(): void {\n    this.items.clear();\n    this.counter = 0;\n  }\n\n  /**\n   * Delete all stored files and clear memory.\n   * Removes the entire session directory.\n   */\n  async cleanup(): Promise<void> {\n    if (this.initialized) {\n      try {\n        await rm(this.outputDir, { recursive: true, force: true });\n      } catch {\n        // Ignore cleanup errors (directory may already be deleted)\n      }\n      this.initialized = false;\n    }\n    this.clear();\n  }\n}\n","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. tslog routes positional Error\n            // args into logErrors (not logArgs) — append them so the message and\n            // stack survive instead of being silently dropped.\n            if (sharedLogFileStream) {\n              const meta = stripAnsi(logMetaMarkup);\n              const fileArgs = args.map((a) => stripAnsi(a));\n              const errTail = logErrors.length\n                ? `\\n${logErrors.map((e) => stripAnsi(e)).join(\"\\n\")}`\n                : \"\";\n              sharedLogFileStream.write(`${meta}${fileArgs.join(\" \")}${errTail}\\n`);\n            }\n\n            // Console: preserve ANSI colors\n            if (teeToConsole) {\n              const errTail = logErrors.length ? `\\n${logErrors.join(\"\\n\")}` : \"\";\n              process.stdout.write(`${logMetaMarkup}${args.join(\" \")}${errTail}\\n`);\n            }\n          },\n        }\n      : defaultType === \"pretty\"\n        ? {\n            // Diagnostics go to stderr (POSIX convention). tslog's default\n            // pretty transport uses console.log, which pollutes stdout —\n            // breaking consumers whose stdout is content or machine-readable\n            // (piped CLI output, --json/NDJSON modes, --background job refs).\n            transportFormatted: (\n              logMetaMarkup: string,\n              logArgs: unknown[],\n              logErrors: string[],\n            ) => {\n              const args = logArgs.map((arg) =>\n                typeof arg === \"string\" ? arg : JSON.stringify(arg),\n              );\n              // tslog routes positional Error args into logErrors — append them so\n              // error messages and stacks reach stderr (default-transport parity).\n              const errTail = logErrors.length ? `\\n${logErrors.join(\"\\n\")}` : \"\";\n              process.stderr.write(`${logMetaMarkup}${args.join(\" \")}${errTail}\\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 * Internal key for Agent instantiation.\n * This Symbol is used to ensure only AgentBuilder can create Agent instances.\n *\n * @internal\n */\nexport const AGENT_INTERNAL_KEY = Symbol(\"AGENT_INTERNAL_KEY\");\n\n/**\n * Type guard to check if the key is the correct internal key\n * @internal\n */\nexport function isValidAgentKey(key: unknown): key is typeof AGENT_INTERNAL_KEY {\n  return key === AGENT_INTERNAL_KEY;\n}\n","/**\n * Configuration types for the context compaction system.\n *\n * Context compaction automatically manages conversation history to prevent\n * context window overflow in long-running agent conversations.\n */\n\nimport type { CompactionStrategy } from \"./strategy.js\";\n\n/**\n * Event emitted when compaction occurs.\n * This is included in StreamEvent for UI visibility.\n */\nexport interface CompactionEvent {\n  /** The strategy that performed the compaction */\n  strategy: string;\n  /** Token count before compaction */\n  tokensBefore: number;\n  /** Token count after compaction */\n  tokensAfter: number;\n  /** Number of messages before compaction */\n  messagesBefore: number;\n  /** Number of messages after compaction */\n  messagesAfter: number;\n  /** Summary text if summarization was used */\n  summary?: string;\n  /** Agent iteration when compaction occurred */\n  iteration: number;\n}\n\n/**\n * Statistics about compaction activity.\n */\nexport interface CompactionStats {\n  /** Total number of compactions performed */\n  totalCompactions: number;\n  /** Total tokens saved across all compactions */\n  totalTokensSaved: number;\n  /** Current context usage */\n  currentUsage: {\n    tokens: number;\n    percent: number;\n  };\n  /** Model's context window size */\n  contextWindow: number;\n}\n\n/**\n * Configuration for the context compaction system.\n *\n * @example\n * ```typescript\n * // Custom configuration\n * const agent = await LLMist.createAgent()\n *   .withModel('sonnet')\n *   .withCompaction({\n *     triggerThresholdPercent: 70,\n *     targetPercent: 40,\n *     preserveRecentTurns: 10,\n *   })\n *   .ask('...');\n *\n * // Disable compaction\n * const agent = await LLMist.createAgent()\n *   .withModel('sonnet')\n *   .withoutCompaction()\n *   .ask('...');\n * ```\n */\nexport interface CompactionConfig {\n  /**\n   * Enable or disable compaction.\n   * @default true\n   */\n  enabled?: boolean;\n\n  /**\n   * The compaction strategy to use.\n   * - 'sliding-window': Fast, drops oldest turns (no LLM call)\n   * - 'summarization': LLM-based compression of old messages\n   * - 'hybrid': Summarizes old messages + keeps recent turns (recommended)\n   * - Or provide a custom CompactionStrategy instance\n   * @default 'hybrid'\n   */\n  strategy?: \"sliding-window\" | \"summarization\" | \"hybrid\" | CompactionStrategy;\n\n  /**\n   * Context usage percentage that triggers compaction.\n   * When token count exceeds this percentage of the context window,\n   * compaction is performed before the next LLM call.\n   * @default 80\n   */\n  triggerThresholdPercent?: number;\n\n  /**\n   * Target context usage percentage after compaction.\n   * The compaction will aim to reduce tokens to this percentage.\n   * @default 50\n   */\n  targetPercent?: number;\n\n  /**\n   * Number of recent turns to preserve during compaction.\n   * A \"turn\" is a user message + assistant response pair.\n   * Recent turns are kept verbatim while older ones are summarized/dropped.\n   * @default 5\n   */\n  preserveRecentTurns?: number;\n\n  /**\n   * Model to use for summarization.\n   * If not specified, uses the agent's model.\n   * @default undefined (uses agent's model)\n   */\n  summarizationModel?: string;\n\n  /**\n   * Custom system prompt for summarization.\n   * If not specified, uses a default prompt optimized for context preservation.\n   */\n  summarizationPrompt?: string;\n\n  /**\n   * Callback invoked when compaction occurs.\n   * Useful for logging or analytics.\n   */\n  onCompaction?: (event: CompactionEvent) => void;\n}\n\n/**\n * Default configuration values for compaction.\n * Compaction is enabled by default with the hybrid strategy.\n */\nexport const DEFAULT_COMPACTION_CONFIG: Required<\n  Omit<CompactionConfig, \"summarizationModel\" | \"summarizationPrompt\" | \"onCompaction\">\n> = {\n  enabled: true,\n  strategy: \"hybrid\",\n  triggerThresholdPercent: 80,\n  targetPercent: 50,\n  preserveRecentTurns: 5,\n};\n\n/**\n * Default prompt used for summarization strategy.\n */\nexport const DEFAULT_SUMMARIZATION_PROMPT = `Summarize this conversation history concisely, preserving:\n1. Key decisions made and their rationale\n2. Important facts and data discovered\n3. Errors encountered and how they were resolved\n4. Current task context and goals\n\nFormat as a brief narrative paragraph, not bullet points.\nPrevious conversation:`;\n\n/**\n * Resolved configuration with all defaults applied.\n */\nexport interface ResolvedCompactionConfig {\n  enabled: boolean;\n  strategy: \"sliding-window\" | \"summarization\" | \"hybrid\";\n  triggerThresholdPercent: number;\n  targetPercent: number;\n  preserveRecentTurns: number;\n  summarizationModel?: string;\n  summarizationPrompt: string;\n  onCompaction?: (event: CompactionEvent) => void;\n}\n\n/**\n * Resolves partial configuration with defaults.\n */\nexport function resolveCompactionConfig(config: CompactionConfig = {}): ResolvedCompactionConfig {\n  const trigger =\n    config.triggerThresholdPercent ?? DEFAULT_COMPACTION_CONFIG.triggerThresholdPercent;\n  const target = config.targetPercent ?? DEFAULT_COMPACTION_CONFIG.targetPercent;\n\n  // Warn about potentially misconfigured thresholds\n  if (target >= trigger) {\n    console.warn(\n      `[llmist/compaction] targetPercent (${target}) should be less than triggerThresholdPercent (${trigger}) to be effective.`,\n    );\n  }\n\n  // Handle custom strategy instances vs string names\n  const strategy = config.strategy ?? DEFAULT_COMPACTION_CONFIG.strategy;\n  const strategyName =\n    typeof strategy === \"object\" && \"name\" in strategy\n      ? (strategy.name as \"sliding-window\" | \"summarization\" | \"hybrid\")\n      : strategy;\n\n  return {\n    enabled: config.enabled ?? DEFAULT_COMPACTION_CONFIG.enabled,\n    strategy: strategyName,\n    triggerThresholdPercent: trigger,\n    targetPercent: target,\n    preserveRecentTurns:\n      config.preserveRecentTurns ?? DEFAULT_COMPACTION_CONFIG.preserveRecentTurns,\n    summarizationModel: config.summarizationModel,\n    summarizationPrompt: config.summarizationPrompt ?? DEFAULT_SUMMARIZATION_PROMPT,\n    onCompaction: config.onCompaction,\n  };\n}\n","/**\n * Strategy interface for context compaction.\n *\n * Strategies define how conversation history is compressed to fit within\n * context window limits. Different strategies trade off between:\n * - Speed (LLM calls vs local processing)\n * - Context preservation (summary quality vs simple truncation)\n * - Cost (summarization model usage)\n */\n\nimport type { LLMist } from \"../../core/client.js\";\nimport type { LLMMessage } from \"../../core/messages.js\";\nimport type { ModelLimits } from \"../../core/model-catalog.js\";\nimport type { ResolvedCompactionConfig } from \"./config.js\";\n\n/**\n * Context provided to compaction strategies.\n */\nexport interface CompactionContext {\n  /** Current token count of the conversation */\n  currentTokens: number;\n  /** Target token count after compaction */\n  targetTokens: number;\n  /** Model's context window limits */\n  modelLimits: ModelLimits;\n  /** LLMist client for summarization calls */\n  client: LLMist;\n  /** Model identifier for token counting and summarization */\n  model: string;\n}\n\n/**\n * Result of a compaction operation.\n */\nexport interface CompactionResult {\n  /** Compacted messages to replace history with */\n  messages: LLMMessage[];\n  /** Summary text if summarization was used */\n  summary?: string;\n  /** The name of the strategy that was ultimately executed */\n  strategyName: string;\n  /** Metadata about the compaction */\n  metadata: {\n    /** Number of messages before compaction */\n    originalCount: number;\n    /** Number of messages after compaction */\n    compactedCount: number;\n    /** Estimated tokens before compaction */\n    tokensBefore: number;\n    /** Estimated tokens after compaction */\n    tokensAfter: number;\n  };\n}\n\n/**\n * Interface for compaction strategy implementations.\n *\n * Strategies receive the conversation history (excluding base messages like\n * system prompt and gadget instructions) and must return a compacted version.\n *\n * @example\n * ```typescript\n * class MyCustomStrategy implements CompactionStrategy {\n *   readonly name = 'my-custom';\n *\n *   async compact(\n *     messages: LLMMessage[],\n *     config: ResolvedCompactionConfig,\n *     context: CompactionContext\n *   ): Promise<CompactionResult> {\n *     // Custom compaction logic\n *     return {\n *       messages: compactedMessages,\n *       metadata: { ... }\n *     };\n *   }\n * }\n * ```\n */\nexport interface CompactionStrategy {\n  /** Human-readable name of the strategy */\n  readonly name: string;\n\n  /**\n   * Compact the given messages to fit within target token count.\n   *\n   * @param messages - Conversation history messages (excludes system/gadget base)\n   * @param config - Resolved compaction configuration\n   * @param context - Context including token counts and LLM client\n   * @returns Compacted messages with metadata\n   */\n  compact(\n    messages: LLMMessage[],\n    config: ResolvedCompactionConfig,\n    context: CompactionContext,\n  ): Promise<CompactionResult>;\n}\n\n/**\n * Utility to group messages into logical conversation turns.\n *\n * A \"turn\" is typically a user message followed by an assistant response.\n * Gadget calls are grouped with the preceding assistant message.\n */\nexport interface MessageTurn {\n  /** Messages in this turn (user + assistant + any gadget results) */\n  messages: LLMMessage[];\n  /** Estimated token count for this turn */\n  tokenEstimate: number;\n}\n\n/**\n * Groups messages into logical conversation turns.\n *\n * Rules:\n * - A turn starts with a user message\n * - A turn includes all subsequent assistant messages until the next user message\n * - The first message(s) before any user message are considered \"preamble\"\n *\n * @param messages - Array of conversation messages\n * @returns Array of message turns\n */\nexport function groupIntoTurns(messages: LLMMessage[]): MessageTurn[] {\n  const turns: MessageTurn[] = [];\n  let currentTurn: LLMMessage[] = [];\n\n  for (const msg of messages) {\n    if (msg.role === \"user\" && currentTurn.length > 0) {\n      // Start new turn - save current one\n      turns.push({\n        messages: currentTurn,\n        tokenEstimate: estimateTurnTokens(currentTurn),\n      });\n      currentTurn = [msg];\n    } else {\n      currentTurn.push(msg);\n    }\n  }\n\n  // Don't forget the last turn\n  if (currentTurn.length > 0) {\n    turns.push({\n      messages: currentTurn,\n      tokenEstimate: estimateTurnTokens(currentTurn),\n    });\n  }\n\n  return turns;\n}\n\n/**\n * Rough token estimation for a turn (4 chars per token).\n */\nfunction estimateTurnTokens(messages: LLMMessage[]): number {\n  return Math.ceil(messages.reduce((sum, msg) => sum + (msg.content?.length ?? 0), 0) / 4);\n}\n\n/**\n * Flattens turns back into a message array.\n */\nexport function flattenTurns(turns: MessageTurn[]): LLMMessage[] {\n  return turns.flatMap((turn) => turn.messages);\n}\n","/**\n * Sliding Window Compaction Strategy\n *\n * A fast, no-LLM-call strategy that simply keeps the most recent N turns\n * and drops older ones. Best for:\n * - Long-running conversations where older context becomes irrelevant\n * - Scenarios requiring minimal latency\n * - As a fallback when summarization is too slow\n */\n\nimport type { LLMMessage } from \"../../../core/messages.js\";\nimport type { ResolvedCompactionConfig } from \"../config.js\";\nimport {\n  type CompactionContext,\n  type CompactionResult,\n  type CompactionStrategy,\n  flattenTurns,\n  groupIntoTurns,\n} from \"../strategy.js\";\n\n/**\n * Marker message inserted to indicate truncation.\n */\nconst TRUNCATION_MARKER_TEMPLATE =\n  \"[Previous conversation truncated. Removed {count} turn(s) to fit context window.]\";\n\n/**\n * Sliding window strategy - keeps recent turns, drops older ones.\n *\n * This strategy:\n * 1. Groups messages into logical turns (user + assistant pairs)\n * 2. Keeps the `preserveRecentTurns` most recent turns\n * 3. Inserts a truncation marker at the beginning\n * 4. Requires no LLM call - very fast\n */\nexport class SlidingWindowStrategy implements CompactionStrategy {\n  readonly name = \"sliding-window\";\n\n  async compact(\n    messages: LLMMessage[],\n    config: ResolvedCompactionConfig,\n    context: CompactionContext,\n  ): Promise<CompactionResult> {\n    const turns = groupIntoTurns(messages);\n    const preserveCount = Math.min(config.preserveRecentTurns, turns.length);\n\n    // If we have fewer turns than the preserve count, nothing to compact\n    if (turns.length <= preserveCount) {\n      return {\n        messages,\n        strategyName: this.name,\n        metadata: {\n          originalCount: messages.length,\n          compactedCount: messages.length,\n          tokensBefore: context.currentTokens,\n          tokensAfter: context.currentTokens,\n        },\n      };\n    }\n\n    // Keep only the most recent turns\n    const turnsToKeep = turns.slice(-preserveCount);\n    const turnsRemoved = turns.length - preserveCount;\n\n    // Sticky-preservation contract: messages carrying `metadata.sticky === true`\n    // survive compaction regardless of how old they are, so multi-KB tool\n    // outputs the agent needs to remember (loaded skill bodies, retrieved\n    // documents, etc.) stay in context for the rest of the conversation.\n    //\n    // We compute the set of stickies from the OLDER half (turns we're about to\n    // drop) only — stickies inside `turnsToKeep` are already in the preserved\n    // window and re-inserting them between the marker and `turnsToKeep` would\n    // duplicate them. Strict `=== true` comparison avoids accidentally\n    // promoting messages whose `metadata.sticky` is something truthy but\n    // unintended (`\"true\"`, `1`, etc.).\n    const keptMessageRefs = new Set(turnsToKeep.flatMap((turn) => turn.messages));\n    const stickyToPreserve = messages.filter(\n      (msg) => msg.metadata?.sticky === true && !keptMessageRefs.has(msg),\n    );\n\n    // Create truncation marker\n    const truncationMarker: LLMMessage = {\n      role: \"user\",\n      content: TRUNCATION_MARKER_TEMPLATE.replace(\"{count}\", turnsRemoved.toString()),\n    };\n\n    // Build compacted message list\n    const compactedMessages: LLMMessage[] = [\n      truncationMarker,\n      ...stickyToPreserve,\n      ...flattenTurns(turnsToKeep),\n    ];\n\n    // Estimate new token count\n    const tokensAfter = Math.ceil(\n      compactedMessages.reduce((sum, msg) => sum + (msg.content?.length ?? 0), 0) / 4,\n    );\n\n    return {\n      messages: compactedMessages,\n      strategyName: this.name,\n      metadata: {\n        originalCount: messages.length,\n        compactedCount: compactedMessages.length,\n        tokensBefore: context.currentTokens,\n        tokensAfter,\n      },\n    };\n  }\n}\n","/**\n * Summarization Compaction Strategy\n *\n * Uses an LLM to summarize older conversation messages into a concise summary.\n * Best for:\n * - Tasks where historical context matters\n * - Complex multi-step reasoning\n * - When accuracy is more important than speed\n */\n\nimport type { LLMMessage } from \"../../../core/messages.js\";\nimport type { ResolvedCompactionConfig } from \"../config.js\";\nimport {\n  type CompactionContext,\n  type CompactionResult,\n  type CompactionStrategy,\n  flattenTurns,\n  groupIntoTurns,\n} from \"../strategy.js\";\n\n/**\n * Summarization strategy - uses LLM to compress conversation history.\n *\n * This strategy:\n * 1. Groups messages into logical turns\n * 2. Keeps recent turns intact\n * 3. Summarizes older turns using LLM\n * 4. Returns summary + recent turns\n */\nexport class SummarizationStrategy implements CompactionStrategy {\n  readonly name = \"summarization\";\n\n  async compact(\n    messages: LLMMessage[],\n    config: ResolvedCompactionConfig,\n    context: CompactionContext,\n  ): Promise<CompactionResult> {\n    const turns = groupIntoTurns(messages);\n    const preserveCount = Math.min(config.preserveRecentTurns, turns.length);\n\n    // If we have fewer turns than the preserve count, nothing to compact\n    if (turns.length <= preserveCount) {\n      return {\n        messages,\n        strategyName: this.name,\n        metadata: {\n          originalCount: messages.length,\n          compactedCount: messages.length,\n          tokensBefore: context.currentTokens,\n          tokensAfter: context.currentTokens,\n        },\n      };\n    }\n\n    // Split into turns to summarize and turns to keep\n    const turnsToSummarize = turns.slice(0, -preserveCount);\n    const turnsToKeep = turns.slice(-preserveCount);\n\n    // Sticky-preservation contract (mirror of sliding-window): messages\n    // carrying `metadata.sticky === true` survive compaction so multi-KB tool\n    // outputs the agent needs to remember (loaded skill bodies, retrieved\n    // documents, etc.) stay in context for the rest of the conversation.\n    // Compute from the OLDER half only — stickies inside `turnsToKeep` are\n    // already preserved naturally. Use strict `=== true` so unrelated truthy\n    // metadata values don't accidentally promote messages.\n    const keptMessageRefs = new Set(turnsToKeep.flatMap((turn) => turn.messages));\n    const stickyToPreserve = messages.filter(\n      (msg) => msg.metadata?.sticky === true && !keptMessageRefs.has(msg),\n    );\n\n    // Build conversation text to summarize. Exclude the sticky messages so\n    // we don't ask the LLM to re-state the same content immediately under a\n    // \"Previous conversation summary\" header (the agent will see both).\n    const turnsToSummarizeMessages = flattenTurns(turnsToSummarize).filter(\n      (msg) => msg.metadata?.sticky !== true,\n    );\n    const conversationToSummarize = this.formatTurnsForSummary(turnsToSummarizeMessages);\n\n    // Generate summary using LLM\n    const summary = await this.generateSummary(conversationToSummarize, config, context);\n\n    // Create summary message\n    const summaryMessage: LLMMessage = {\n      role: \"user\",\n      content: `[Previous conversation summary]\\n${summary}\\n[End of summary - conversation continues below]`,\n    };\n\n    // Build compacted message list — sticky messages sit between the summary\n    // and the preserved recent turns, in their original input order.\n    const compactedMessages: LLMMessage[] = [\n      summaryMessage,\n      ...stickyToPreserve,\n      ...flattenTurns(turnsToKeep),\n    ];\n\n    // Estimate new token count\n    const tokensAfter = Math.ceil(\n      compactedMessages.reduce((sum, msg) => sum + (msg.content?.length ?? 0), 0) / 4,\n    );\n\n    return {\n      messages: compactedMessages,\n      summary,\n      strategyName: this.name,\n      metadata: {\n        originalCount: messages.length,\n        compactedCount: compactedMessages.length,\n        tokensBefore: context.currentTokens,\n        tokensAfter,\n      },\n    };\n  }\n\n  /**\n   * Formats messages into a readable conversation format for summarization.\n   */\n  private formatTurnsForSummary(messages: LLMMessage[]): string {\n    return messages\n      .map((msg) => {\n        const role = msg.role.charAt(0).toUpperCase() + msg.role.slice(1);\n        return `${role}: ${msg.content}`;\n      })\n      .join(\"\\n\\n\");\n  }\n\n  /**\n   * Generates a summary using the configured LLM.\n   */\n  private async generateSummary(\n    conversation: string,\n    config: ResolvedCompactionConfig,\n    context: CompactionContext,\n  ): Promise<string> {\n    const model = config.summarizationModel ?? context.model;\n    const prompt = `${config.summarizationPrompt}\\n\\n${conversation}`;\n\n    // Use the LLMist client's complete method for summarization\n    const response = await context.client.complete(prompt, {\n      model,\n      temperature: 0.3, // Low temperature for factual summarization\n    });\n\n    return response.trim();\n  }\n}\n","/**\n * Hybrid Compaction Strategy\n *\n * Combines sliding window and summarization for the best of both worlds:\n * 1. Identifies which turns to compact vs keep (like sliding window)\n * 2. Summarizes the older turns (like summarization)\n * 3. Returns summary + recent turns intact\n *\n * Falls back to sliding window if there are too few turns to summarize.\n */\n\nimport type { LLMMessage } from \"../../../core/messages.js\";\nimport type { ResolvedCompactionConfig } from \"../config.js\";\nimport {\n  type CompactionContext,\n  type CompactionResult,\n  type CompactionStrategy,\n  groupIntoTurns,\n} from \"../strategy.js\";\nimport { SlidingWindowStrategy } from \"./sliding-window.js\";\nimport { SummarizationStrategy } from \"./summarization.js\";\n\n/**\n * Minimum turns needed to make summarization worthwhile.\n * Below this threshold, we fall back to sliding window.\n */\nconst MIN_TURNS_FOR_SUMMARIZATION = 3;\n\n/**\n * Hybrid strategy - summarizes old turns + keeps recent turns.\n *\n * This is the recommended default strategy as it:\n * - Preserves important historical context via summarization\n * - Keeps recent conversation turns verbatim for continuity\n * - Falls back gracefully to sliding window when appropriate\n */\nexport class HybridStrategy implements CompactionStrategy {\n  readonly name = \"hybrid\";\n\n  private readonly slidingWindow = new SlidingWindowStrategy();\n  private readonly summarization = new SummarizationStrategy();\n\n  async compact(\n    messages: LLMMessage[],\n    config: ResolvedCompactionConfig,\n    context: CompactionContext,\n  ): Promise<CompactionResult> {\n    const turns = groupIntoTurns(messages);\n    const preserveCount = Math.min(config.preserveRecentTurns, turns.length);\n\n    // If we have fewer turns than the preserve count, nothing to compact\n    if (turns.length <= preserveCount) {\n      return {\n        messages,\n        strategyName: this.name,\n        metadata: {\n          originalCount: messages.length,\n          compactedCount: messages.length,\n          tokensBefore: context.currentTokens,\n          tokensAfter: context.currentTokens,\n        },\n      };\n    }\n\n    // Calculate how many turns would be summarized\n    const turnsToSummarize = turns.length - preserveCount;\n\n    // If there are too few turns to summarize, use sliding window instead\n    if (turnsToSummarize < MIN_TURNS_FOR_SUMMARIZATION) {\n      // Delegate to sliding window - propagate its strategyName for accurate reporting\n      return this.slidingWindow.compact(messages, config, context);\n    }\n\n    // Use summarization for older turns - propagate its strategyName\n    return this.summarization.compact(messages, config, context);\n  }\n}\n","/**\n * Compaction Strategy Implementations\n *\n * Available strategies:\n * - SlidingWindowStrategy: Fast, drops oldest turns (no LLM call)\n * - SummarizationStrategy: LLM-based compression\n * - HybridStrategy: Summarizes old + keeps recent (recommended)\n */\n\nexport { HybridStrategy } from \"./hybrid.js\";\nexport { SlidingWindowStrategy } from \"./sliding-window.js\";\nexport { SummarizationStrategy } from \"./summarization.js\";\n","/**\n * CompactionManager - Central orchestrator for context compaction.\n *\n * Monitors token usage and coordinates compaction strategies to keep\n * conversation context within model limits.\n */\n\nimport type { ILogObj, Logger } from \"tslog\";\nimport type { LLMist } from \"../../core/client.js\";\nimport type { LLMMessage } from \"../../core/messages.js\";\nimport type { ModelLimits } from \"../../core/model-catalog.js\";\nimport { createLogger } from \"../../logging/logger.js\";\nimport type { IConversationManager } from \"../interfaces.js\";\nimport {\n  type CompactionConfig,\n  type CompactionEvent,\n  type CompactionStats,\n  type ResolvedCompactionConfig,\n  resolveCompactionConfig,\n} from \"./config.js\";\nimport {\n  HybridStrategy,\n  SlidingWindowStrategy,\n  SummarizationStrategy,\n} from \"./strategies/index.js\";\nimport type { CompactionStrategy } from \"./strategy.js\";\n\n/**\n * Pre-computed token counts to avoid redundant counting.\n * Passed from checkAndCompact to compact for efficiency.\n */\ninterface PrecomputedTokens {\n  historyMessages: LLMMessage[];\n  baseMessages: LLMMessage[];\n  historyTokens: number;\n  baseTokens: number;\n  currentTokens: number;\n}\n\n/**\n * Creates a strategy instance from a strategy name.\n */\nfunction createStrategy(name: string): CompactionStrategy {\n  switch (name) {\n    case \"sliding-window\":\n      return new SlidingWindowStrategy();\n    case \"summarization\":\n      return new SummarizationStrategy();\n    case \"hybrid\":\n      return new HybridStrategy();\n    default:\n      throw new Error(`Unknown compaction strategy: ${name}`);\n  }\n}\n\n/**\n * CompactionManager orchestrates context compaction for an agent.\n *\n * It:\n * - Monitors token usage before each LLM call\n * - Triggers compaction when threshold is exceeded\n * - Coordinates with ConversationManager to update history\n * - Tracks statistics for observability\n */\nexport class CompactionManager {\n  private readonly client: LLMist;\n  private readonly model: string;\n  private readonly config: ResolvedCompactionConfig;\n  private readonly strategy: CompactionStrategy;\n  private readonly logger: Logger<ILogObj>;\n  private modelLimits?: ModelLimits;\n  private hasWarnedModelNotFound = false;\n  private hasWarnedNoTokenCounting = false;\n\n  // Statistics\n  private totalCompactions = 0;\n  private totalTokensSaved = 0;\n  private lastTokenCount = 0;\n\n  constructor(\n    client: LLMist,\n    model: string,\n    config: CompactionConfig = {},\n    logger?: Logger<ILogObj>,\n  ) {\n    this.client = client;\n    this.model = model;\n    this.config = resolveCompactionConfig(config);\n    this.logger = logger ?? createLogger({ name: \"llmist:compaction\" });\n\n    // Create strategy instance (support both string name and custom instance)\n    if (typeof config.strategy === \"object\" && \"compact\" in config.strategy) {\n      this.strategy = config.strategy as CompactionStrategy;\n    } else {\n      this.strategy = createStrategy(this.config.strategy);\n    }\n  }\n\n  /**\n   * Check if compaction is needed and perform it if so.\n   *\n   * @param conversation - The conversation manager to compact\n   * @param iteration - Current agent iteration (for event metadata)\n   * @returns CompactionEvent if compaction was performed, null otherwise\n   */\n  async checkAndCompact(\n    conversation: IConversationManager,\n    iteration: number,\n  ): Promise<CompactionEvent | null> {\n    if (!this.config.enabled) {\n      return null;\n    }\n\n    // Get model limits (cached after first call)\n    if (!this.resolveModelLimits()) {\n      return null;\n    }\n\n    // Count current tokens (skip if client doesn't support token counting)\n    if (!this.client.countTokens) {\n      if (!this.hasWarnedNoTokenCounting) {\n        this.hasWarnedNoTokenCounting = true;\n        this.logger.warn(\"Compaction skipped: client does not support token counting\", {\n          model: this.model,\n        });\n      }\n      return null;\n    }\n    const messages = conversation.getMessages();\n    const currentTokens = await this.client.countTokens(this.model, messages);\n    this.lastTokenCount = currentTokens;\n\n    // Calculate usage percentage (modelLimits guaranteed by resolveModelLimits above)\n    const usagePercent = (currentTokens / this.modelLimits!.contextWindow) * 100;\n\n    // Check if we need to compact\n    if (usagePercent < this.config.triggerThresholdPercent) {\n      return null;\n    }\n\n    // Perform compaction with precomputed token counts to avoid redundant counting\n    const historyMessages = conversation.getHistoryMessages();\n    const baseMessages = conversation.getBaseMessages();\n    const historyTokens = await this.client.countTokens(this.model, historyMessages);\n    const baseTokens = await this.client.countTokens(this.model, baseMessages);\n\n    return this.compact(conversation, iteration, {\n      historyMessages,\n      baseMessages,\n      historyTokens,\n      baseTokens,\n      currentTokens: historyTokens + baseTokens,\n    });\n  }\n\n  /**\n   * Force compaction regardless of threshold.\n   *\n   * @param conversation - The conversation manager to compact\n   * @param iteration - Current agent iteration (for event metadata). Use -1 for manual compaction.\n   * @param precomputed - Optional pre-computed token counts (passed from checkAndCompact for efficiency)\n   * @returns CompactionEvent with compaction details\n   */\n  async compact(\n    conversation: IConversationManager,\n    iteration: number,\n    precomputed?: PrecomputedTokens,\n  ): Promise<CompactionEvent | null> {\n    if (!this.resolveModelLimits()) {\n      return null;\n    }\n\n    // Use precomputed values if available, otherwise compute them\n    const historyMessages = precomputed?.historyMessages ?? conversation.getHistoryMessages();\n    const baseMessages = precomputed?.baseMessages ?? conversation.getBaseMessages();\n    const historyTokens =\n      precomputed?.historyTokens ?? (await this.client.countTokens(this.model, historyMessages));\n    const baseTokens =\n      precomputed?.baseTokens ?? (await this.client.countTokens(this.model, baseMessages));\n    const currentTokens = precomputed?.currentTokens ?? historyTokens + baseTokens;\n\n    // Calculate target tokens for history (leaving room for base messages and output)\n    // modelLimits guaranteed by resolveModelLimits above\n    const targetTotalTokens = Math.floor(\n      (this.modelLimits!.contextWindow * this.config.targetPercent) / 100,\n    );\n    const targetHistoryTokens = Math.max(0, targetTotalTokens - baseTokens);\n\n    // Run the compaction strategy\n    const result = await this.strategy.compact(historyMessages, this.config, {\n      currentTokens: historyTokens,\n      targetTokens: targetHistoryTokens,\n      modelLimits: this.modelLimits!,\n      client: this.client,\n      model: this.config.summarizationModel ?? this.model,\n    });\n\n    // Replace the conversation history\n    conversation.replaceHistory(result.messages);\n\n    // Count tokens after compaction\n    const afterTokens = await this.client.countTokens(this.model, conversation.getMessages());\n    const tokensSaved = currentTokens - afterTokens;\n\n    // Update statistics\n    this.totalCompactions++;\n    this.totalTokensSaved += tokensSaved;\n    this.lastTokenCount = afterTokens;\n\n    // Create event - use result.strategyName for accurate reporting (e.g., when hybrid falls back to sliding-window)\n    const event: CompactionEvent = {\n      strategy: result.strategyName,\n      tokensBefore: currentTokens,\n      tokensAfter: afterTokens,\n      messagesBefore: historyMessages.length + baseMessages.length,\n      messagesAfter: result.messages.length + baseMessages.length,\n      summary: result.summary,\n      iteration,\n    };\n\n    // Call onCompaction callback if provided\n    if (this.config.onCompaction) {\n      try {\n        this.config.onCompaction(event);\n      } catch (err) {\n        console.warn(\"[llmist/compaction] onCompaction callback error:\", err);\n      }\n    }\n\n    return event;\n  }\n\n  /**\n   * Feed API-reported input token count for reactive threshold checking.\n   * Call this after each LLM response with the actual inputTokens from usage.\n   */\n  updateUsage(inputTokens: number): void {\n    this.lastTokenCount = inputTokens;\n  }\n\n  /**\n   * Check if compaction should trigger based on API-reported usage.\n   * Unlike checkAndCompact() which uses estimated token counts,\n   * this uses the ground-truth token count from the last LLM response.\n   */\n  shouldCompactFromUsage(): boolean {\n    if (!this.config.enabled) return false;\n    if (!this.resolveModelLimits()) return false;\n\n    const usagePercent = (this.lastTokenCount / this.modelLimits!.contextWindow) * 100;\n    return usagePercent >= this.config.triggerThresholdPercent;\n  }\n\n  /**\n   * Resolve and cache model limits from registry. Warns once if not found.\n   * @returns true if limits are available, false otherwise\n   */\n  private resolveModelLimits(): boolean {\n    if (this.modelLimits) return true;\n\n    this.modelLimits = this.client.modelRegistry.getModelLimits(this.model);\n    if (!this.modelLimits) {\n      if (!this.hasWarnedModelNotFound) {\n        this.hasWarnedModelNotFound = true;\n        this.logger.warn(\"Compaction skipped: model not found in registry\", {\n          model: this.model,\n        });\n      }\n      return false;\n    }\n    return true;\n  }\n\n  /**\n   * Get compaction statistics.\n   */\n  getStats(): CompactionStats {\n    const contextWindow = this.modelLimits?.contextWindow ?? 0;\n    return {\n      totalCompactions: this.totalCompactions,\n      totalTokensSaved: this.totalTokensSaved,\n      currentUsage: {\n        tokens: this.lastTokenCount,\n        percent: contextWindow > 0 ? (this.lastTokenCount / contextWindow) * 100 : 0,\n      },\n      contextWindow,\n    };\n  }\n\n  /**\n   * Check if compaction is enabled.\n   */\n  isEnabled(): boolean {\n    return this.config.enabled;\n  }\n}\n","/**\n * ConversationManager handles conversation state and message building.\n * Extracted from AgentLoop to follow Single Responsibility Principle.\n */\n\nimport type { MessageContent } from \"../core/messages.js\";\nimport { extractMessageText, type LLMMessage, LLMMessageBuilder } from \"../core/messages.js\";\nimport type { GadgetMediaOutput, StoredMedia } from \"../gadgets/types.js\";\nimport type { IConversationManager } from \"./interfaces.js\";\n\n/**\n * Options for ConversationManager constructor.\n */\nexport interface ConversationManagerOptions {\n  /** Custom gadget start marker prefix */\n  startPrefix?: string;\n  /** Custom gadget end marker prefix */\n  endPrefix?: string;\n  /** Custom argument prefix for block format */\n  argPrefix?: string;\n}\n\n/**\n * Default implementation of IConversationManager.\n * Manages conversation history by building on top of base messages (system prompt, gadget instructions).\n */\nexport class ConversationManager implements IConversationManager {\n  private baseMessages: LLMMessage[];\n  private readonly initialMessages: LLMMessage[];\n  private historyBuilder: LLMMessageBuilder;\n  private readonly startPrefix?: string;\n  private readonly endPrefix?: string;\n  private readonly argPrefix?: string;\n\n  constructor(\n    baseMessages: LLMMessage[],\n    initialMessages: LLMMessage[],\n    options: ConversationManagerOptions = {},\n  ) {\n    this.baseMessages = baseMessages;\n    this.initialMessages = initialMessages;\n    this.historyBuilder = new LLMMessageBuilder();\n\n    // Store prefixes for history replacement\n    this.startPrefix = options.startPrefix;\n    this.endPrefix = options.endPrefix;\n    this.argPrefix = options.argPrefix;\n\n    // Apply custom prefixes if provided (must match system prompt markers)\n    if (options.startPrefix && options.endPrefix) {\n      this.historyBuilder.withPrefixes(options.startPrefix, options.endPrefix, options.argPrefix);\n    }\n  }\n\n  addUserMessage(content: MessageContent): void {\n    this.historyBuilder.addUser(content);\n  }\n\n  addAssistantMessage(content: string): void {\n    this.historyBuilder.addAssistant(content);\n  }\n\n  addGadgetCallResult(\n    gadgetName: string,\n    parameters: Record<string, unknown>,\n    result: string,\n    invocationId: string,\n    media?: GadgetMediaOutput[],\n    mediaIds?: string[],\n    storedMedia?: StoredMedia[],\n    metadata?: Record<string, unknown>,\n  ): void {\n    this.historyBuilder.addGadgetCallResult(\n      gadgetName,\n      parameters,\n      result,\n      invocationId,\n      media,\n      mediaIds,\n      storedMedia,\n      metadata,\n    );\n  }\n\n  getMessages(): LLMMessage[] {\n    return [...this.baseMessages, ...this.initialMessages, ...this.historyBuilder.build()];\n  }\n\n  getHistoryMessages(): LLMMessage[] {\n    return this.historyBuilder.build();\n  }\n\n  getBaseMessages(): LLMMessage[] {\n    return [...this.baseMessages, ...this.initialMessages];\n  }\n\n  /**\n   * Replace the base (system + gadget catalog) messages.\n   *\n   * Used when async setup (e.g. MCP server connect-and-list) discovers\n   * additional gadgets after the agent was constructed. Conversation history\n   * is preserved; only the leading system block is swapped.\n   */\n  replaceBaseMessages(newBase: LLMMessage[]): void {\n    this.baseMessages = newBase;\n  }\n\n  replaceHistory(newHistory: LLMMessage[]): void {\n    // Create a new builder with the same prefixes\n    this.historyBuilder = new LLMMessageBuilder();\n    if (this.startPrefix && this.endPrefix) {\n      this.historyBuilder.withPrefixes(this.startPrefix, this.endPrefix, this.argPrefix);\n    }\n\n    // Add each message from the new history\n    for (const msg of newHistory) {\n      if (msg.role === \"user\") {\n        this.historyBuilder.addUser(msg.content);\n      } else if (msg.role === \"assistant\") {\n        // Assistant messages are always text, extract if multimodal\n        this.historyBuilder.addAssistant(extractMessageText(msg.content));\n      }\n      // System messages are not added to history (they're in baseMessages)\n    }\n  }\n\n  getConversationHistory(): LLMMessage[] {\n    // Returns full conversation history: initial messages (from previous sessions via withHistory())\n    // plus runtime history (from current session). Excludes base messages (system prompt, gadget instructions).\n    return [...this.initialMessages, ...this.historyBuilder.build()];\n  }\n}\n","/**\n * ConversationUpdater: Encapsulates conversation history updates after LLM responses.\n *\n * Extracted from Agent to isolate conversation history logic — handling text-only\n * vs text-with-gadgets responses, synthetic invocation wrapping, result formatting,\n * and conversation manager calls.\n *\n * @module agent/conversation-updater\n */\n\nimport type { ILogObj, Logger } from \"tslog\";\nimport type { StreamEvent, TextOnlyHandler } from \"../gadgets/types.js\";\nimport type { ConversationManager } from \"./conversation-manager.js\";\n\n/**\n * Configuration for wrapping text that accompanies gadget calls as a synthetic gadget call.\n */\nexport interface TextWithGadgetsHandlerConfig {\n  /** Name of the gadget to use for wrapping text */\n  gadgetName: string;\n  /** Maps text content to gadget parameters */\n  parameterMapping: (text: string) => Record<string, unknown>;\n  /** Maps text content to the result string (optional, defaults to text) */\n  resultMapping?: (text: string) => string;\n}\n\n/**\n * ConversationUpdater handles updating conversation history after each LLM response.\n *\n * Owns:\n * - Text-only response handling (`textOnlyHandler`)\n * - Text-alongside-gadgets wrapping (`textWithGadgetsHandler`)\n * - Synthetic invocation ID generation (`syntheticInvocationCounter`)\n */\nexport class ConversationUpdater {\n  private readonly conversation: ConversationManager;\n  private readonly textOnlyHandler: TextOnlyHandler;\n  private readonly textWithGadgetsHandler?: TextWithGadgetsHandlerConfig;\n  private readonly logger: Logger<ILogObj>;\n  private syntheticInvocationCounter = 0;\n\n  constructor(\n    conversation: ConversationManager,\n    textOnlyHandler: TextOnlyHandler,\n    textWithGadgetsHandler: TextWithGadgetsHandlerConfig | undefined,\n    logger: Logger<ILogObj>,\n  ) {\n    this.conversation = conversation;\n    this.textOnlyHandler = textOnlyHandler;\n    this.textWithGadgetsHandler = textWithGadgetsHandler;\n    this.logger = logger;\n  }\n\n  /**\n   * Generate a unique synthetic invocation ID for wrapped text content.\n   * Used when `textWithGadgetsHandler` is set and text accompanies gadget calls.\n   *\n   * @returns A unique synthetic invocation ID string\n   */\n  createSyntheticInvocation(): string {\n    return `gc_text_${++this.syntheticInvocationCounter}`;\n  }\n\n  /**\n   * Process a text-only LLM response (no gadgets were called).\n   *\n   * Determines whether the agent loop should continue or terminate based\n   * on the configured handler.\n   *\n   * @param _textOutputs - Array of text chunks from the LLM response (reserved for future use)\n   * @returns 'terminate' if the agent loop should stop, 'continue' if it should keep going\n   */\n  handleTextOnly(_textOutputs: string[]): \"continue\" | \"terminate\" {\n    const handler = this.textOnlyHandler;\n\n    if (typeof handler === \"string\") {\n      switch (handler) {\n        case \"terminate\":\n          this.logger.info(\"No gadgets called, ending loop\");\n          return \"terminate\";\n        case \"acknowledge\":\n          this.logger.info(\"No gadgets called, continuing loop\");\n          return \"continue\";\n        case \"wait_for_input\":\n          this.logger.info(\"No gadgets called, waiting for input\");\n          return \"terminate\";\n        default:\n          this.logger.warn(`Unknown text-only strategy: ${handler}, defaulting to terminate`);\n          return \"terminate\";\n      }\n    }\n\n    // For gadget and custom handlers, they would need to be implemented\n    // This is simplified for now\n    return \"terminate\";\n  }\n\n  /**\n   * Update conversation history with LLM response results.\n   *\n   * When gadgets were executed:\n   * - Optionally wraps accompanying text as a synthetic gadget call (if textWithGadgetsHandler is set)\n   * - Adds all gadget results to conversation\n   *\n   * When no gadgets were executed (text-only response):\n   * - Adds the final message as an assistant message to conversation\n   * - Delegates to handleTextOnly() for continuation decision\n   *\n   * @param textOutputs - Array of text chunks from the LLM response (used for text wrapping with gadgets)\n   * @param gadgetResults - Array of gadget_result stream events from this response\n   * @param finalMessage - The final assistant message (possibly modified by afterLLMCall controller)\n   * @returns true if the agent loop should break (text-only handler requested termination)\n   */\n  updateWithResults(\n    textOutputs: string[],\n    gadgetResults: StreamEvent[],\n    finalMessage: string,\n  ): boolean {\n    const didExecuteGadgets = gadgetResults.some((e) => e.type === \"gadget_result\");\n\n    if (didExecuteGadgets) {\n      // If configured, wrap accompanying text as a synthetic gadget call\n      if (this.textWithGadgetsHandler) {\n        const textContent = textOutputs.join(\"\");\n\n        if (textContent.trim()) {\n          const { gadgetName, parameterMapping, resultMapping } = this.textWithGadgetsHandler;\n          const syntheticId = this.createSyntheticInvocation();\n          this.conversation.addGadgetCallResult(\n            gadgetName,\n            parameterMapping(textContent),\n            resultMapping ? resultMapping(textContent) : textContent,\n            syntheticId,\n          );\n        }\n      }\n\n      // Add all gadget results to conversation\n      for (const output of gadgetResults) {\n        if (output.type === \"gadget_result\") {\n          const gadgetResult = output.result;\n          // Sticky-result wiring: if the gadget definition opted in via\n          // `stickyResult: true` AND the execution succeeded (no error), mark\n          // the persisted user-message sticky so the compaction layer keeps\n          // it past truncation. Failed runs stay non-sticky so a bad LoadSkill\n          // doesn't pin itself in context.\n          const metadata =\n            gadgetResult.stickyResult === true && gadgetResult.error === undefined\n              ? { sticky: true }\n              : undefined;\n          this.conversation.addGadgetCallResult(\n            gadgetResult.gadgetName,\n            gadgetResult.parameters,\n            gadgetResult.error ?? gadgetResult.result ?? \"\",\n            gadgetResult.invocationId,\n            gadgetResult.media,\n            gadgetResult.mediaIds,\n            gadgetResult.storedMedia,\n            metadata,\n          );\n        }\n      }\n\n      return false; // Don't break loop\n    }\n\n    // No gadgets executed — add final message as assistant message\n    if (finalMessage.trim()) {\n      this.conversation.addAssistantMessage(finalMessage);\n    }\n\n    // Handle text-only responses\n    return this.handleTextOnly(textOutputs) === \"terminate\";\n  }\n}\n","/**\n * Event handler sugar for cleaner event processing.\n *\n * Instead of verbose if/else chains, use named handlers\n * for each event type.\n *\n * @example\n * ```typescript\n * await agent.runWith({\n *   onText: (content) => console.log(\"LLM:\", content),\n *   onGadgetResult: (result) => console.log(\"Result:\", result.result),\n * });\n * ```\n */\n\nimport type { StreamEvent } from \"../gadgets/types.js\";\n\n/**\n * Named event handlers for different event types.\n */\nexport interface EventHandlers {\n  /** Called when text is generated by the LLM */\n  onText?: (content: string) => void | Promise<void>;\n\n  /** Called when a gadget is about to be executed */\n  onGadgetCall?: (call: {\n    gadgetName: string;\n    invocationId: string;\n    parameters?: Record<string, unknown>;\n    parametersRaw: string;\n    dependencies: string[];\n  }) => void | Promise<void>;\n\n  /**\n   * Called for each progressive argument partial while a gadget call is still\n   * streaming (before `onGadgetCall`). Values are RAW/uncoerced; prefer `value`\n   * (replace) over `delta` (append). Great for live form-fill UIs.\n   */\n  onGadgetArgsPartial?: (partial: {\n    gadgetName: string;\n    invocationId: string;\n    fieldPath: string;\n    value: string;\n    delta: string;\n    isFieldComplete: boolean;\n  }) => void | Promise<void>;\n\n  /** Called when a gadget execution completes */\n  onGadgetResult?: (result: {\n    gadgetName: string;\n    invocationId: string;\n    result?: string;\n    error?: string;\n    parameters: Record<string, unknown>;\n  }) => void | Promise<void>;\n\n  /** Called when human input is required */\n  onHumanInputRequired?: (data: { question: string; gadgetName: string }) => void | Promise<void>;\n\n  /** Called for any other event type */\n  onOther?: (event: StreamEvent) => void | Promise<void>;\n}\n\n/**\n * Helper to run an agent with named event handlers.\n *\n * @param agentGenerator - Agent's run() async generator\n * @param handlers - Named event handlers\n *\n * @example\n * ```typescript\n * await runWithHandlers(agent.run(), {\n *   onText: (text) => console.log(\"LLM:\", text),\n *   onGadgetResult: (result) => console.log(\"Result:\", result.result),\n * });\n * ```\n */\nexport async function runWithHandlers(\n  agentGenerator: AsyncGenerator<StreamEvent>,\n  handlers: EventHandlers,\n): Promise<void> {\n  for await (const event of agentGenerator) {\n    switch (event.type) {\n      case \"text\":\n        if (handlers.onText) {\n          await handlers.onText(event.content);\n        }\n        break;\n\n      case \"gadget_call\":\n        if (handlers.onGadgetCall) {\n          await handlers.onGadgetCall({\n            gadgetName: event.call.gadgetName,\n            invocationId: event.call.invocationId,\n            parameters: event.call.parameters,\n            parametersRaw: event.call.parametersRaw,\n            dependencies: event.call.dependencies,\n          });\n        }\n        break;\n\n      case \"gadget_args_partial\":\n        if (handlers.onGadgetArgsPartial) {\n          await handlers.onGadgetArgsPartial({\n            gadgetName: event.gadgetName,\n            invocationId: event.invocationId,\n            fieldPath: event.fieldPath,\n            value: event.value,\n            delta: event.delta,\n            isFieldComplete: event.isFieldComplete,\n          });\n        }\n        break;\n\n      case \"gadget_result\":\n        if (handlers.onGadgetResult) {\n          await handlers.onGadgetResult(event.result);\n        }\n        break;\n\n      case \"human_input_required\":\n        if (handlers.onHumanInputRequired) {\n          await handlers.onHumanInputRequired({\n            question: event.question,\n            gadgetName: event.gadgetName,\n          });\n        }\n        break;\n\n      default:\n        if (handlers.onOther) {\n          await handlers.onOther(event);\n        }\n        break;\n    }\n  }\n}\n\n/**\n * Helper to collect events by type.\n *\n * @param agentGenerator - Agent's run() async generator\n * @param collect - Object specifying which event types to collect\n * @returns Object with collected events\n *\n * @example\n * ```typescript\n * const { text, gadgetResults } = await collectEvents(agent.run(), {\n *   text: true,\n *   gadgetResults: true,\n * });\n *\n * console.log(\"Full response:\", text.join(\"\"));\n * console.log(\"Gadget calls:\", gadgetResults.length);\n * ```\n */\nexport async function collectEvents(\n  agentGenerator: AsyncGenerator<StreamEvent>,\n  collect: {\n    text?: boolean;\n    gadgetCalls?: boolean;\n    gadgetResults?: boolean;\n  },\n): Promise<{\n  text: string[];\n  gadgetCalls: Array<{ gadgetName: string; parameters: Record<string, unknown> }>;\n  gadgetResults: Array<{\n    gadgetName: string;\n    result?: string;\n    error?: string;\n    parameters: Record<string, unknown>;\n  }>;\n}> {\n  const result = {\n    text: [] as string[],\n    gadgetCalls: [] as Array<{ gadgetName: string; parameters: Record<string, unknown> }>,\n    gadgetResults: [] as Array<{\n      gadgetName: string;\n      result?: string;\n      error?: string;\n      parameters: Record<string, unknown>;\n    }>,\n  };\n\n  for await (const event of agentGenerator) {\n    switch (event.type) {\n      case \"text\":\n        if (collect.text) {\n          result.text.push(event.content);\n        }\n        break;\n\n      case \"gadget_call\":\n        if (collect.gadgetCalls && event.call.parameters) {\n          result.gadgetCalls.push({\n            gadgetName: event.call.gadgetName,\n            parameters: event.call.parameters,\n          });\n        }\n        break;\n\n      case \"gadget_result\":\n        if (collect.gadgetResults) {\n          result.gadgetResults.push(event.result);\n        }\n        break;\n    }\n  }\n\n  return result;\n}\n\n/**\n * Helper to collect only text from an agent run.\n *\n * @param agentGenerator - Agent's run() async generator\n * @returns Combined text response\n *\n * @example\n * ```typescript\n * const response = await collectText(agent.run());\n * console.log(response);\n * ```\n */\nexport async function collectText(agentGenerator: AsyncGenerator<StreamEvent>): Promise<string> {\n  const chunks: string[] = [];\n\n  for await (const event of agentGenerator) {\n    if (event.type === \"text\") {\n      chunks.push(event.content);\n    }\n  }\n\n  return chunks.join(\"\");\n}\n","/**\n * Runtime validators for hook action types.\n *\n * These validators ensure that controllers return valid action objects,\n * catching common mistakes like missing required fields.\n */\n\nimport type {\n  AfterGadgetExecutionAction,\n  AfterLLMCallAction,\n  AfterLLMErrorAction,\n  BeforeGadgetExecutionAction,\n  BeforeLLMCallAction,\n} from \"./hooks.js\";\n\nexport class HookValidationError extends Error {\n  constructor(hookName: string, message: string) {\n    super(`Invalid action from ${hookName}: ${message}`);\n    this.name = \"HookValidationError\";\n  }\n}\n\n/**\n * Validate beforeLLMCall action.\n */\nexport function validateBeforeLLMCallAction(action: BeforeLLMCallAction): void {\n  if (!action || typeof action !== \"object\" || !(\"action\" in action)) {\n    throw new HookValidationError(\n      \"beforeLLMCall\",\n      \"Must return an action object with an 'action' field\",\n    );\n  }\n\n  const actionType = action.action;\n  if (actionType !== \"proceed\" && actionType !== \"skip\") {\n    throw new HookValidationError(\n      \"beforeLLMCall\",\n      `Invalid action type: ${actionType}. Must be 'proceed' or 'skip'`,\n    );\n  }\n\n  if (actionType === \"skip\" && !action.syntheticResponse) {\n    throw new HookValidationError(\n      \"beforeLLMCall\",\n      \"When action is 'skip', syntheticResponse is required\",\n    );\n  }\n}\n\n/**\n * Validate afterLLMCall action.\n */\nexport function validateAfterLLMCallAction(action: AfterLLMCallAction): void {\n  if (!action || typeof action !== \"object\" || !(\"action\" in action)) {\n    throw new HookValidationError(\n      \"afterLLMCall\",\n      \"Must return an action object with an 'action' field\",\n    );\n  }\n\n  const actionType = action.action;\n  const validActions = [\"continue\", \"append_messages\", \"modify_and_continue\", \"append_and_modify\"];\n  if (!validActions.includes(actionType)) {\n    throw new HookValidationError(\n      \"afterLLMCall\",\n      `Invalid action type: ${actionType}. Must be one of: ${validActions.join(\", \")}`,\n    );\n  }\n\n  if (actionType === \"append_messages\" || actionType === \"append_and_modify\") {\n    if (!(\"messages\" in action) || !action.messages || !Array.isArray(action.messages)) {\n      throw new HookValidationError(\n        \"afterLLMCall\",\n        `When action is '${actionType}', messages array is required`,\n      );\n    }\n\n    if (action.messages.length === 0) {\n      throw new HookValidationError(\n        \"afterLLMCall\",\n        `When action is '${actionType}', messages array must not be empty`,\n      );\n    }\n\n    // Validate each message\n    for (let i = 0; i < action.messages.length; i++) {\n      const msg = action.messages[i];\n      if (!msg || typeof msg !== \"object\") {\n        throw new HookValidationError(\"afterLLMCall\", `Message at index ${i} must be an object`);\n      }\n      if (!msg.role || !msg.content) {\n        throw new HookValidationError(\n          \"afterLLMCall\",\n          `Message at index ${i} must have 'role' and 'content' fields`,\n        );\n      }\n      if (![\"system\", \"user\", \"assistant\"].includes(msg.role)) {\n        throw new HookValidationError(\n          \"afterLLMCall\",\n          `Message at index ${i} has invalid role: ${msg.role}`,\n        );\n      }\n    }\n  }\n\n  if (actionType === \"modify_and_continue\" || actionType === \"append_and_modify\") {\n    if (!(\"modifiedMessage\" in action) || !action.modifiedMessage) {\n      throw new HookValidationError(\n        \"afterLLMCall\",\n        `When action is '${actionType}', modifiedMessage is required`,\n      );\n    }\n  }\n}\n\n/**\n * Validate afterLLMError action.\n */\nexport function validateAfterLLMErrorAction(action: AfterLLMErrorAction): void {\n  if (!action || typeof action !== \"object\" || !(\"action\" in action)) {\n    throw new HookValidationError(\n      \"afterLLMError\",\n      \"Must return an action object with an 'action' field\",\n    );\n  }\n\n  const actionType = action.action;\n  if (actionType !== \"rethrow\" && actionType !== \"recover\") {\n    throw new HookValidationError(\n      \"afterLLMError\",\n      `Invalid action type: ${actionType}. Must be 'rethrow' or 'recover'`,\n    );\n  }\n\n  if (actionType === \"recover\" && !action.fallbackResponse) {\n    throw new HookValidationError(\n      \"afterLLMError\",\n      \"When action is 'recover', fallbackResponse is required\",\n    );\n  }\n}\n\n/**\n * Validate beforeGadgetExecution action.\n */\nexport function validateBeforeGadgetExecutionAction(action: BeforeGadgetExecutionAction): void {\n  if (!action || typeof action !== \"object\" || !(\"action\" in action)) {\n    throw new HookValidationError(\n      \"beforeGadgetExecution\",\n      \"Must return an action object with an 'action' field\",\n    );\n  }\n\n  const actionType = action.action;\n  if (actionType !== \"proceed\" && actionType !== \"skip\") {\n    throw new HookValidationError(\n      \"beforeGadgetExecution\",\n      `Invalid action type: ${actionType}. Must be 'proceed' or 'skip'`,\n    );\n  }\n\n  if (actionType === \"skip\" && !action.syntheticResult) {\n    throw new HookValidationError(\n      \"beforeGadgetExecution\",\n      \"When action is 'skip', syntheticResult is required\",\n    );\n  }\n}\n\n/**\n * Validate afterGadgetExecution action.\n */\nexport function validateAfterGadgetExecutionAction(action: AfterGadgetExecutionAction): void {\n  if (!action || typeof action !== \"object\" || !(\"action\" in action)) {\n    throw new HookValidationError(\n      \"afterGadgetExecution\",\n      \"Must return an action object with an 'action' field\",\n    );\n  }\n\n  const actionType = action.action;\n  if (actionType !== \"continue\" && actionType !== \"recover\") {\n    throw new HookValidationError(\n      \"afterGadgetExecution\",\n      `Invalid action type: ${actionType}. Must be 'continue' or 'recover'`,\n    );\n  }\n\n  if (actionType === \"recover\" && !action.fallbackResult) {\n    throw new HookValidationError(\n      \"afterGadgetExecution\",\n      \"When action is 'recover', fallbackResult is required\",\n    );\n  }\n}\n","/**\n * Shared safeObserve utility for consistent observer error handling across the agent module.\n *\n * Observers are non-critical — errors should be logged but must not crash the system.\n */\n\nimport type { ILogObj, Logger } from \"tslog\";\n\n/**\n * Safely execute an observer function, catching and logging any errors.\n * Observers are non-critical, so errors are logged but don't crash the system.\n *\n * @param fn - The observer function to execute\n * @param logger - Logger instance for error reporting\n * @param label - Optional label for contextualizing the error message\n */\nexport async function safeObserve(\n  fn: () => void | Promise<void>,\n  logger: Logger<ILogObj>,\n  label?: string,\n): Promise<void> {\n  try {\n    await fn();\n  } catch (error) {\n    const message = label ? `Observer error in ${label}:` : \"Observer threw error (ignoring)\";\n    logger.error(message, {\n      error: error instanceof Error ? error.message : String(error),\n    });\n  }\n}\n","/**\n * Bridge between ExecutionTree events and hook observers.\n *\n * This module handles:\n * - LLM call events for subagent visibility (fire-and-forget)\n * - Gadget events for subagent visibility (fire-and-forget)\n * - Exports `getSubagentContextForNode()` for deriving subagent context\n *\n * The ExecutionTree is the single source of truth for all execution events.\n * For subagent events (depth > 0), this bridge propagates events to parent hooks.\n *\n * NOTE: For the ROOT agent's own events (depth === 0), gadget observer hooks\n * are called DIRECTLY in stream-processor.ts with await to ensure proper ordering.\n * This bridge only handles SUBAGENT events to avoid double-calling.\n *\n * @module agent/tree-hook-bridge\n */\n\nimport type { ILogObj, Logger } from \"tslog\";\nimport type {\n  ExecutionEvent,\n  GadgetCompleteEvent,\n  GadgetErrorEvent,\n  GadgetSkippedEvent,\n  GadgetStartEvent,\n  LLMCallCompleteEvent,\n  LLMCallErrorEvent,\n  LLMCallStartEvent,\n} from \"../core/execution-events.js\";\nimport type { ExecutionTree, GadgetNode, LLMCallNode, NodeId } from \"../core/execution-tree.js\";\nimport type {\n  AgentHooks,\n  ObserveGadgetCompleteContext,\n  ObserveGadgetSkippedContext,\n  ObserveGadgetStartContext,\n  ObserveLLMCallContext,\n  ObserveLLMCompleteContext,\n  ObserveLLMErrorContext,\n  SubagentContext,\n} from \"./hooks.js\";\nimport { safeObserve } from \"./safe-observe.js\";\n\n/**\n * Find the parent gadget's invocation ID by walking up the tree.\n * For subagent events, this returns the gadget that spawned the subagent.\n */\nfunction findParentGadgetInvocationId(tree: ExecutionTree, nodeId: NodeId): string | undefined {\n  let currentId: NodeId | null = nodeId;\n\n  while (currentId) {\n    const node = tree.getNode(currentId);\n    if (!node) break;\n\n    // Walk up to parent\n    currentId = node.parentId;\n    if (!currentId) break;\n\n    const parentNode = tree.getNode(currentId);\n    if (parentNode?.type === \"gadget\") {\n      return (parentNode as GadgetNode).invocationId;\n    }\n  }\n\n  return undefined;\n}\n\n/**\n * Get the iteration number from the nearest LLM call ancestor.\n */\nfunction getIterationFromTree(tree: ExecutionTree, nodeId: NodeId): number {\n  let currentId: NodeId | null = nodeId;\n\n  while (currentId) {\n    const node = tree.getNode(currentId);\n    if (!node) break;\n\n    if (node.type === \"llm_call\") {\n      return (node as LLMCallNode).iteration;\n    }\n\n    currentId = node.parentId;\n  }\n\n  return 0;\n}\n\n/**\n * Build SubagentContext for events that are inside a subagent's execution.\n *\n * A SubagentContext exists only if the event has a parent gadget in its ancestry.\n * This distinguishes:\n * - Root agent gadgets (no parent gadget) → returns undefined\n * - Subagent gadgets (have parent gadget that spawned them) → returns SubagentContext\n */\nfunction buildSubagentContext(\n  tree: ExecutionTree,\n  event: ExecutionEvent,\n): SubagentContext | undefined {\n  const parentGadgetInvocationId = findParentGadgetInvocationId(tree, event.nodeId);\n\n  if (!parentGadgetInvocationId) {\n    return undefined; // No parent gadget = not in subagent context\n  }\n\n  return {\n    parentGadgetInvocationId,\n    depth: event.depth,\n  };\n}\n\n/**\n * Get SubagentContext for a specific node in the execution tree.\n *\n * This is exported for use by agent.ts when calling LLM hooks directly.\n * LLM hooks are awaited (unlike gadget hooks which are fire-and-forget via the bridge),\n * so they need to derive SubagentContext manually.\n *\n * @param tree - The ExecutionTree to query\n * @param nodeId - The node ID to get context for\n * @returns SubagentContext if the node is inside a subagent execution, undefined otherwise\n *\n * @example\n * ```typescript\n * const subagentContext = getSubagentContextForNode(this.tree, llmNodeId);\n * const context: ObserveLLMCallContext = {\n *   iteration,\n *   options: llmOptions,\n *   logger: this.logger,\n *   subagentContext,\n * };\n * ```\n */\nexport function getSubagentContextForNode(\n  tree: ExecutionTree,\n  nodeId: NodeId,\n): SubagentContext | undefined {\n  const node = tree.getNode(nodeId);\n  if (!node) return undefined;\n\n  const parentGadgetInvocationId = findParentGadgetInvocationId(tree, nodeId);\n\n  if (!parentGadgetInvocationId) {\n    return undefined; // No parent gadget = not in subagent context\n  }\n\n  return {\n    parentGadgetInvocationId,\n    depth: node.depth,\n  };\n}\n\n/**\n * Chain an observer call to ensure proper ordering for the same entity.\n *\n * This ensures that for a given key (invocationId for gadgets, nodeId for LLM calls),\n * events are processed in order. For example, gadget_start must complete before\n * gadget_complete for the same invocation.\n *\n * @param chainMap - Map to store promise chains by key\n * @param key - Unique identifier for the entity (invocationId or nodeId)\n * @param fn - The observer function to call\n * @param logger - Logger for error reporting\n * @param eventType - Event type name for logging\n * @param cleanup - Whether to remove the map entry after completion\n */\nfunction chainObserverCall(\n  chainMap: Map<string, Promise<void>>,\n  key: string,\n  fn: () => void | Promise<void>,\n  logger: Logger<ILogObj>,\n  eventType: string,\n  cleanup: boolean = false,\n): void {\n  const previousPromise = chainMap.get(key) ?? Promise.resolve();\n  const newPromise = previousPromise.then(() => safeObserve(fn, logger, eventType));\n  chainMap.set(key, newPromise);\n\n  if (cleanup) {\n    newPromise.finally(() => chainMap.delete(key));\n  }\n}\n\n/**\n * Bridge ExecutionTree events to hook observers.\n *\n * This bridge handles both LLM and gadget events for subagent visibility.\n * Events from subagents (depth > 0) are fire-and-forget to the parent's hooks.\n *\n * Root agent events (depth === 0) are NOT handled here - they are called\n * directly in stream-processor.ts with await to ensure proper ordering.\n *\n * @param tree - The ExecutionTree to subscribe to\n * @param hooks - Hook observers to call\n * @param logger - Logger for error reporting\n * @returns Unsubscribe function\n *\n * @example\n * ```typescript\n * const unsubscribe = bridgeTreeToHooks(agent.getTree(), hooks, logger);\n *\n * // Later, when done:\n * unsubscribe();\n * ```\n */\nexport function bridgeTreeToHooks(\n  tree: ExecutionTree,\n  hooks: AgentHooks,\n  logger: Logger<ILogObj>,\n): () => void {\n  // Map invocationId -> Promise chain for ordered gadget execution\n  const gadgetPromiseChains = new Map<string, Promise<void>>();\n\n  // Map nodeId -> Promise chain for ordered LLM call execution\n  const llmPromiseChains = new Map<string, Promise<void>>();\n\n  return tree.onAll((event) => {\n    const subagentContext = buildSubagentContext(tree, event);\n\n    switch (event.type) {\n      // =================================================================\n      // GADGET EVENTS - Bridged for subagent visibility\n      // =================================================================\n      // When a subagent executes gadgets, these events propagate through\n      // the shared tree to the parent's hooks.\n      // Only bridged for subagent events (depth > 0) to avoid double-calling\n      // root agent events which are handled directly in stream-processor.ts\n\n      case \"gadget_start\": {\n        if (subagentContext && hooks.observers?.onGadgetExecutionStart) {\n          const gadgetEvent = event as GadgetStartEvent;\n          const gadgetNode = tree.getNode(event.nodeId) as GadgetNode | undefined;\n\n          const context: ObserveGadgetStartContext = {\n            iteration: getIterationFromTree(tree, event.nodeId),\n            gadgetName: gadgetEvent.name,\n            invocationId: gadgetEvent.invocationId,\n            parameters: gadgetNode?.parameters ?? {},\n            logger,\n            subagentContext,\n          };\n\n          // Chain by invocationId to ensure start completes before complete/error/skipped\n          chainObserverCall(\n            gadgetPromiseChains,\n            gadgetEvent.invocationId,\n            () => hooks.observers?.onGadgetExecutionStart?.(context),\n            logger,\n            \"onGadgetExecutionStart\",\n            false, // Don't cleanup - wait for completion event\n          );\n        }\n        break;\n      }\n\n      case \"gadget_complete\": {\n        if (subagentContext && hooks.observers?.onGadgetExecutionComplete) {\n          const gadgetEvent = event as GadgetCompleteEvent;\n          const gadgetNode = tree.getNode(event.nodeId) as GadgetNode | undefined;\n\n          const context: ObserveGadgetCompleteContext = {\n            iteration: getIterationFromTree(tree, event.nodeId),\n            gadgetName: gadgetEvent.name,\n            invocationId: gadgetEvent.invocationId,\n            parameters: gadgetNode?.parameters ?? {},\n            finalResult: gadgetEvent.result,\n            executionTimeMs: gadgetEvent.executionTimeMs,\n            cost: gadgetEvent.cost,\n            logger,\n            subagentContext,\n          };\n\n          // Chain by invocationId to ensure this runs after start, then cleanup\n          chainObserverCall(\n            gadgetPromiseChains,\n            gadgetEvent.invocationId,\n            () => hooks.observers?.onGadgetExecutionComplete?.(context),\n            logger,\n            \"onGadgetExecutionComplete\",\n            true, // Cleanup after completion\n          );\n        }\n        break;\n      }\n\n      case \"gadget_error\": {\n        if (subagentContext && hooks.observers?.onGadgetExecutionComplete) {\n          const gadgetEvent = event as GadgetErrorEvent;\n          const gadgetNode = tree.getNode(event.nodeId) as GadgetNode | undefined;\n\n          // For errors, we call onGadgetExecutionComplete with error field set\n          const context: ObserveGadgetCompleteContext = {\n            iteration: getIterationFromTree(tree, event.nodeId),\n            gadgetName: gadgetEvent.name,\n            invocationId: gadgetEvent.invocationId,\n            parameters: gadgetNode?.parameters ?? {},\n            error: gadgetEvent.error,\n            executionTimeMs: gadgetEvent.executionTimeMs,\n            logger,\n            subagentContext,\n          };\n\n          // Chain by invocationId to ensure this runs after start, then cleanup\n          chainObserverCall(\n            gadgetPromiseChains,\n            gadgetEvent.invocationId,\n            () => hooks.observers?.onGadgetExecutionComplete?.(context),\n            logger,\n            \"onGadgetExecutionComplete\",\n            true, // Cleanup after error\n          );\n        }\n        break;\n      }\n\n      case \"gadget_skipped\": {\n        if (subagentContext && hooks.observers?.onGadgetSkipped) {\n          const gadgetEvent = event as GadgetSkippedEvent;\n          const gadgetNode = tree.getNode(event.nodeId) as GadgetNode | undefined;\n\n          const context: ObserveGadgetSkippedContext = {\n            iteration: getIterationFromTree(tree, event.nodeId),\n            gadgetName: gadgetEvent.name,\n            invocationId: gadgetEvent.invocationId,\n            parameters: gadgetNode?.parameters ?? {},\n            failedDependency: gadgetEvent.failedDependency ?? \"\",\n            failedDependencyError: gadgetEvent.failedDependencyError ?? gadgetEvent.error,\n            logger,\n            subagentContext,\n          };\n\n          // Chain by invocationId to ensure this runs after start, then cleanup\n          chainObserverCall(\n            gadgetPromiseChains,\n            gadgetEvent.invocationId,\n            () => hooks.observers?.onGadgetSkipped?.(context),\n            logger,\n            \"onGadgetSkipped\",\n            true, // Cleanup after skipped\n          );\n        }\n        break;\n      }\n\n      // =================================================================\n      // LLM EVENTS - Bridged for subagent visibility\n      // =================================================================\n      // When a subagent makes LLM calls, these events propagate through\n      // the shared tree to the parent's hooks.\n\n      case \"llm_call_start\": {\n        // Only call hooks for subagent events (depth > 0)\n        // Root agent events are already handled directly in agent.ts\n        if (subagentContext && hooks.observers?.onLLMCallStart) {\n          const llmEvent = event as LLMCallStartEvent;\n\n          const context: ObserveLLMCallContext = {\n            iteration: llmEvent.iteration,\n            options: {\n              model: llmEvent.model,\n              messages: llmEvent.request ?? [],\n              // These fields are not available from tree events, use defaults\n              temperature: undefined,\n              maxTokens: undefined,\n            },\n            logger,\n            subagentContext,\n          };\n\n          // Chain by nodeId to ensure start completes before complete/error\n          chainObserverCall(\n            llmPromiseChains,\n            event.nodeId,\n            () => hooks.observers?.onLLMCallStart?.(context),\n            logger,\n            \"onLLMCallStart\",\n            false, // Don't cleanup - wait for completion event\n          );\n        }\n        break;\n      }\n\n      case \"llm_call_complete\": {\n        // Only call hooks for subagent events (depth > 0)\n        if (subagentContext && hooks.observers?.onLLMCallComplete) {\n          const llmEvent = event as LLMCallCompleteEvent;\n          const llmNode = tree.getNode(event.nodeId) as LLMCallNode | undefined;\n\n          const context: ObserveLLMCompleteContext = {\n            iteration: llmNode?.iteration ?? 1,\n            options: {\n              model: llmNode?.model ?? \"unknown\",\n              messages: llmNode?.request ?? [],\n              temperature: undefined,\n              maxTokens: undefined,\n            },\n            finishReason: llmEvent.finishReason ?? null,\n            usage: llmEvent.usage,\n            rawResponse: llmEvent.response,\n            // Use rawResponse as finalMessage since interceptor modifications aren't available from tree events\n            finalMessage: llmEvent.response,\n            logger,\n            subagentContext,\n          };\n\n          // Chain by nodeId to ensure this runs after start, then cleanup\n          chainObserverCall(\n            llmPromiseChains,\n            event.nodeId,\n            () => hooks.observers?.onLLMCallComplete?.(context),\n            logger,\n            \"onLLMCallComplete\",\n            true, // Cleanup after completion\n          );\n        }\n        break;\n      }\n\n      case \"llm_call_error\": {\n        // Only call hooks for subagent events (depth > 0)\n        if (subagentContext && hooks.observers?.onLLMCallError) {\n          const llmEvent = event as LLMCallErrorEvent;\n          const llmNode = tree.getNode(event.nodeId) as LLMCallNode | undefined;\n\n          const context: ObserveLLMErrorContext = {\n            iteration: llmNode?.iteration ?? 1,\n            options: {\n              model: llmNode?.model ?? \"unknown\",\n              messages: llmNode?.request ?? [],\n              temperature: undefined,\n              maxTokens: undefined,\n            },\n            error: llmEvent.error,\n            recovered: llmEvent.recovered,\n            logger,\n            subagentContext,\n          };\n\n          // Chain by nodeId to ensure this runs after start, then cleanup\n          chainObserverCall(\n            llmPromiseChains,\n            event.nodeId,\n            () => hooks.observers?.onLLMCallError?.(context),\n            logger,\n            \"onLLMCallError\",\n            true, // Cleanup after error\n          );\n        }\n        break;\n      }\n\n      // Other event types (text, compaction, etc.) are not bridged\n      // as they don't have corresponding hook observer interfaces\n    }\n  });\n}\n","/**\n * LLMCallLifecycle: Encapsulates LLM call preparation, completion, and observer notification.\n *\n * Extracted from Agent to provide a focused, testable module for managing the LLM\n * call lifecycle — from building options and tree nodes, through hook notifications,\n * to cost calculation and after-call controller invocation.\n *\n * Follows the stateless helper class pattern (like RetryOrchestrator) — no instance state\n * beyond injected dependencies, just methods that operate on Agent dependencies.\n *\n * ## Observer Call Order (preserved from Agent)\n * 1. `onLLMCallStart`  — fires when tree node is created, before controller\n * 2. `beforeLLMCall` controller — can skip or modify options\n * 3. `onLLMCallReady` — fires after controller modifications, before API call\n * 4. [LLM API Call + Stream]\n * 5. `onLLMCallComplete` — fires after stream completes\n * 6. `afterLLMCall` controller — can modify/append messages\n * 7. `onLLMCallError` — fires when an error escapes the stream\n *\n * @module agent/llm-call-lifecycle\n */\n\nimport type { ILogObj, Logger } from \"tslog\";\nimport type { LLMist } from \"../core/client.js\";\nimport type { ExecutionTree, NodeId } from \"../core/execution-tree.js\";\nimport { extractMessageText } from \"../core/messages.js\";\nimport type { ModelSpec } from \"../core/model-catalog.js\";\nimport type { CachingConfig, LLMGenerationOptions, ReasoningConfig } from \"../core/options.js\";\nimport type { RateLimitTracker } from \"../core/rate-limit.js\";\nimport type { StreamCompletionEvent } from \"../gadgets/types.js\";\nimport type { ConversationManager } from \"./conversation-manager.js\";\nimport {\n  validateAfterLLMCallAction,\n  validateAfterLLMErrorAction,\n  validateBeforeLLMCallAction,\n} from \"./hook-validators.js\";\nimport type {\n  AfterLLMCallAction,\n  AfterLLMCallControllerContext,\n  AfterLLMErrorAction,\n  AgentHooks,\n  BeforeLLMCallAction,\n  LLMCallControllerContext,\n  LLMErrorControllerContext,\n  ObserveLLMCallContext,\n  ObserveLLMCallReadyContext,\n  ObserveLLMCompleteContext,\n  ObserveLLMErrorContext,\n} from \"./hooks.js\";\nimport { safeObserve } from \"./safe-observe.js\";\nimport { getSubagentContextForNode } from \"./tree-hook-bridge.js\";\n\n// ============================================================================\n// Constructor options\n// ============================================================================\n\n/**\n * Options for constructing an LLMCallLifecycle instance.\n *\n * All dependencies are injected from the owning Agent so the lifecycle\n * helper remains stateless beyond what it receives here.\n */\nexport interface LLMCallLifecycleOptions {\n  /** The LLMist client used to resolve model specs and pricing */\n  client: LLMist;\n  /** Conversation manager holding current message history */\n  conversation: ConversationManager;\n  /** Execution tree for node creation and cost tracking */\n  tree: ExecutionTree;\n  /** Agent hooks (observers, interceptors, controllers) */\n  hooks: AgentHooks;\n  /** Logger instance */\n  logger: Logger<ILogObj>;\n  /** Rate limit tracker (optional) */\n  rateLimitTracker?: RateLimitTracker;\n  /** Optional abort signal */\n  signal?: AbortSignal;\n  /** Temperature override */\n  temperature?: number;\n  /** Reasoning configuration */\n  reasoning?: ReasoningConfig;\n  /** Caching configuration */\n  caching?: CachingConfig;\n  /** Model ID (resolved) */\n  model: string;\n  /** Default max tokens from model catalog */\n  defaultMaxTokens?: number;\n  /** Maximum iterations configured for the agent */\n  maxIterations: number;\n  /** Budget limit in USD (optional) */\n  budget?: number;\n  /** Parent node ID for tree hierarchy (null for root agent) */\n  parentNodeId: NodeId | null;\n}\n\n// ============================================================================\n// LLMCallLifecycle\n// ============================================================================\n\n/**\n * LLMCallLifecycle: Stateless helper that encapsulates LLM call lifecycle logic.\n *\n * Provides four public methods:\n * - `prepareLLMCall(iteration, nodeId)` — builds options, creates tree node, fires hooks\n * - `completeLLMCall(nodeId, metadata)` — fires onLLMCallComplete, updates tree with cost\n * - `notifyLLMCallReady(iteration, nodeId, options)` — fires onLLMCallReady observer\n * - `notifyLLMError(iteration, nodeId, error)` — fires onLLMError observer + controller\n *\n * @example\n * ```typescript\n * const lifecycle = new LLMCallLifecycle({ client, conversation, tree, hooks, logger, ... });\n *\n * const prepared = await lifecycle.prepareLLMCall(iteration);\n * // ... run the LLM stream ...\n * await lifecycle.completeLLMCall(prepared.llmNodeId, streamResult, iteration, prepared.options, gadgetCallCount);\n * ```\n */\nexport class LLMCallLifecycle {\n  private readonly client: LLMist;\n  private readonly conversation: ConversationManager;\n  private readonly tree: ExecutionTree;\n  private readonly hooks: AgentHooks;\n  private readonly logger: Logger<ILogObj>;\n  private readonly rateLimitTracker?: RateLimitTracker;\n  private readonly signal?: AbortSignal;\n  private readonly temperature?: number;\n  private readonly reasoning?: ReasoningConfig;\n  private readonly caching?: CachingConfig;\n  private readonly model: string;\n  private readonly defaultMaxTokens?: number;\n  private readonly maxIterations: number;\n  private readonly budget?: number;\n  private readonly parentNodeId: NodeId | null;\n\n  constructor(options: LLMCallLifecycleOptions) {\n    this.client = options.client;\n    this.conversation = options.conversation;\n    this.tree = options.tree;\n    this.hooks = options.hooks;\n    this.logger = options.logger;\n    this.rateLimitTracker = options.rateLimitTracker;\n    this.signal = options.signal;\n    this.temperature = options.temperature;\n    this.reasoning = options.reasoning;\n    this.caching = options.caching;\n    this.model = options.model;\n    this.defaultMaxTokens = options.defaultMaxTokens;\n    this.maxIterations = options.maxIterations;\n    this.budget = options.budget;\n    this.parentNodeId = options.parentNodeId;\n  }\n\n  // ==========================================================================\n  // Public API\n  // ==========================================================================\n\n  /**\n   * Prepare LLM call options, create a tree node, and process lifecycle hooks.\n   *\n   * Fires `onLLMCallStart` and `onLLMCallReady` observers, and runs the\n   * `beforeLLMCall` controller (which may skip the call or modify options).\n   *\n   * @param iteration - Current agent iteration number\n   * @returns Resolved options, node ID, and optional skip-with-synthetic response\n   */\n  async prepareLLMCall(\n    iteration: number,\n  ): Promise<{ options: LLMGenerationOptions; llmNodeId: string; skipWithSynthetic?: string }> {\n    // Resolve reasoning config: explicit config > auto-enable for reasoning models > none\n    const spec = this.client.modelRegistry?.getModelSpec?.(this.model);\n    const reasoning = this.resolveReasoningConfig(spec);\n\n    // Resolve caching config: explicit config > default enabled\n    const caching = this.resolveCachingConfig();\n\n    let llmOptions: LLMGenerationOptions = {\n      model: this.model,\n      messages: this.conversation.getMessages(),\n      temperature: this.temperature,\n      maxTokens: this.defaultMaxTokens,\n      signal: this.signal,\n      reasoning,\n      caching,\n    };\n\n    // Create LLM call node in execution tree BEFORE hooks\n    // This allows hooks to receive SubagentContext\n    const llmNode = this.tree.addLLMCall({\n      iteration,\n      model: llmOptions.model,\n      parentId: this.parentNodeId,\n      request: llmOptions.messages,\n    });\n\n    // Observer: LLM call start\n    await safeObserve(async () => {\n      if (this.hooks.observers?.onLLMCallStart) {\n        const subagentContext = getSubagentContextForNode(this.tree, llmNode.id);\n        const context: ObserveLLMCallContext = {\n          iteration,\n          options: llmOptions,\n          logger: this.logger,\n          subagentContext,\n        };\n        await this.hooks.observers.onLLMCallStart(context);\n      }\n    }, this.logger);\n\n    // Controller: Before LLM call\n    if (this.hooks.controllers?.beforeLLMCall) {\n      const context: LLMCallControllerContext = {\n        iteration,\n        maxIterations: this.maxIterations,\n        budget: this.budget,\n        totalCost: this.tree.getTotalCost(),\n        options: llmOptions,\n        logger: this.logger,\n      };\n      const action: BeforeLLMCallAction = await this.hooks.controllers.beforeLLMCall(context);\n\n      // Validate the action\n      validateBeforeLLMCallAction(action);\n\n      if (action.action === \"skip\") {\n        this.logger.info(\"Controller skipped LLM call, using synthetic response\");\n        return {\n          options: llmOptions,\n          llmNodeId: llmNode.id,\n          skipWithSynthetic: action.syntheticResponse,\n        };\n      } else if (action.action === \"proceed\" && action.modifiedOptions) {\n        llmOptions = { ...llmOptions, ...action.modifiedOptions };\n      }\n    }\n\n    // Observer: LLM call ready (after controller modifications)\n    await safeObserve(async () => {\n      if (this.hooks.observers?.onLLMCallReady) {\n        const subagentContext = getSubagentContextForNode(this.tree, llmNode.id);\n        const context: ObserveLLMCallReadyContext = {\n          iteration,\n          maxIterations: this.maxIterations,\n          budget: this.budget,\n          totalCost: this.tree.getTotalCost(),\n          options: llmOptions,\n          logger: this.logger,\n          subagentContext,\n        };\n        await this.hooks.observers.onLLMCallReady(context);\n      }\n    }, this.logger);\n\n    return { options: llmOptions, llmNodeId: llmNode.id };\n  }\n\n  /**\n   * Complete an LLM call: fire `onLLMCallComplete` observer, update the execution\n   * tree with cost, and process the `afterLLMCall` controller.\n   *\n   * @param nodeId - The execution tree node ID for this call\n   * @param result - The stream completion event with usage, finishReason, etc.\n   * @param iteration - Current agent iteration number\n   * @param llmOptions - The options that were used for the LLM call\n   * @param gadgetCallCount - Number of gadget calls in this response\n   * @returns The (possibly modified) final message\n   */\n  async completeLLMCall(\n    nodeId: NodeId,\n    result: StreamCompletionEvent,\n    iteration: number,\n    llmOptions: LLMGenerationOptions,\n    gadgetCallCount: number,\n  ): Promise<string> {\n    // Observer: LLM call complete\n    await safeObserve(async () => {\n      if (this.hooks.observers?.onLLMCallComplete) {\n        const subagentContext = getSubagentContextForNode(this.tree, nodeId);\n        const context: ObserveLLMCompleteContext = {\n          iteration,\n          options: llmOptions,\n          finishReason: result.finishReason,\n          usage: result.usage,\n          rawResponse: result.rawResponse,\n          finalMessage: result.finalMessage,\n          thinkingContent: result.thinkingContent,\n          logger: this.logger,\n          subagentContext,\n        };\n        await this.hooks.observers.onLLMCallComplete(context);\n      }\n    }, this.logger);\n\n    // Complete LLM call in execution tree (with cost calculation)\n    this.completeLLMCallInTree(nodeId, result);\n\n    // Process afterLLMCall controller (may modify finalMessage or append messages)\n    return this.processAfterLLMCallController(iteration, llmOptions, result, gadgetCallCount);\n  }\n\n  /**\n   * Notify the `onLLMCallReady` observer with the given options.\n   *\n   * Called separately when the caller needs to fire the ready hook outside the\n   * normal `prepareLLMCall` flow (e.g., after an interrupted call is resumed).\n   *\n   * @param iteration - Current agent iteration number\n   * @param nodeId - The execution tree node ID\n   * @param options - The final LLM options (after any controller modifications)\n   */\n  async notifyLLMCallReady(\n    iteration: number,\n    nodeId: NodeId,\n    options: LLMGenerationOptions,\n  ): Promise<void> {\n    await safeObserve(async () => {\n      if (this.hooks.observers?.onLLMCallReady) {\n        const subagentContext = getSubagentContextForNode(this.tree, nodeId);\n        const context: ObserveLLMCallReadyContext = {\n          iteration,\n          maxIterations: this.maxIterations,\n          budget: this.budget,\n          totalCost: this.tree.getTotalCost(),\n          options,\n          logger: this.logger,\n          subagentContext,\n        };\n        await this.hooks.observers.onLLMCallReady(context);\n      }\n    }, this.logger);\n  }\n\n  /**\n   * Notify the `onLLMCallError` observer and invoke the `afterLLMError` controller.\n   *\n   * Returns the controller's action result (either \"rethrow\" or \"recover\" with a\n   * fallback response). The caller is responsible for acting on the returned action.\n   *\n   * @param iteration - Current agent iteration number\n   * @param nodeId - The execution tree node ID (may be undefined if error occurred before node creation)\n   * @param error - The error that occurred\n   * @returns The AfterLLMErrorAction (or a default \"rethrow\" action if no controller is set)\n   */\n  async notifyLLMError(\n    iteration: number,\n    nodeId: string | undefined,\n    error: Error,\n  ): Promise<AfterLLMErrorAction> {\n    this.logger.error(\"LLM call failed\", { error: error.message });\n\n    let action: AfterLLMErrorAction = { action: \"rethrow\" };\n\n    if (this.hooks.controllers?.afterLLMError) {\n      const context: LLMErrorControllerContext = {\n        iteration,\n        options: {\n          model: this.model,\n          messages: this.conversation.getMessages(),\n          temperature: this.temperature,\n          maxTokens: this.defaultMaxTokens,\n        },\n        error,\n        logger: this.logger,\n      };\n      action = await this.hooks.controllers.afterLLMError(context);\n\n      // Validate the action\n      validateAfterLLMErrorAction(action);\n    }\n\n    // Observer: LLM error (fires after controller so `recovered` reflects controller decision)\n    const recovered = action.action === \"recover\";\n    await safeObserve(async () => {\n      if (this.hooks.observers?.onLLMCallError) {\n        const subagentContext = nodeId ? getSubagentContextForNode(this.tree, nodeId) : undefined;\n        const context: ObserveLLMErrorContext = {\n          iteration,\n          options: {\n            model: this.model,\n            messages: this.conversation.getMessages(),\n            temperature: this.temperature,\n            maxTokens: this.defaultMaxTokens,\n          },\n          error,\n          recovered,\n          logger: this.logger,\n          subagentContext,\n        };\n        await this.hooks.observers.onLLMCallError(context);\n      }\n    }, this.logger);\n\n    return action;\n  }\n\n  // ==========================================================================\n  // Private helpers\n  // ==========================================================================\n\n  /**\n   * Resolve reasoning configuration with auto-enable logic.\n   *\n   * Priority: explicit config > auto-enable for reasoning models > undefined\n   * When a model has `features.reasoning: true` and no explicit config is set,\n   * reasoning is automatically enabled at \"medium\" effort.\n   */\n  private resolveReasoningConfig(spec: ModelSpec | undefined): ReasoningConfig | undefined {\n    // Explicit config always wins\n    if (this.reasoning !== undefined) return this.reasoning;\n    // Auto-enable for reasoning-capable models\n    if (spec?.features?.reasoning) {\n      return { enabled: true, effort: \"medium\" };\n    }\n    return undefined;\n  }\n\n  /**\n   * Resolve caching configuration.\n   *\n   * Priority: explicit config > default enabled (preserves Anthropic's existing behavior)\n   * Default is `{ enabled: true }` which means:\n   * - Anthropic: `cache_control` markers are added (existing behavior preserved)\n   * - Gemini: Cache manager is consulted but skips if no explicit config was set\n   * - OpenAI: No-op (server-side automatic)\n   */\n  private resolveCachingConfig(): CachingConfig | undefined {\n    // Explicit config always wins\n    if (this.caching !== undefined) return this.caching;\n    // Default: enabled (preserves Anthropic's existing always-on caching behavior)\n    return { enabled: true };\n  }\n\n  /**\n   * Calculate cost and complete LLM call in execution tree.\n   * Also records usage to rate limit tracker for proactive throttling.\n   */\n  private completeLLMCallInTree(nodeId: NodeId, result: StreamCompletionEvent): void {\n    const inputTokens = result.usage?.inputTokens ?? 0;\n    const outputTokens = result.usage?.outputTokens ?? 0;\n\n    // Record usage to rate limit tracker for proactive throttling\n    if (this.rateLimitTracker) {\n      this.rateLimitTracker.recordUsage(inputTokens, outputTokens);\n    }\n\n    // Calculate cost using ModelRegistry (if available)\n    const llmCost = this.client.modelRegistry?.estimateCost?.(\n      this.model,\n      inputTokens,\n      outputTokens,\n      result.usage?.cachedInputTokens ?? 0,\n      result.usage?.cacheCreationInputTokens ?? 0,\n      result.usage?.reasoningTokens ?? 0,\n    )?.totalCost;\n\n    // Complete LLM call in execution tree (including cost for automatic aggregation)\n    this.tree.completeLLMCall(nodeId, {\n      response: result.rawResponse,\n      usage: result.usage,\n      finishReason: result.finishReason,\n      cost: llmCost,\n      thinkingContent: result.thinkingContent,\n    });\n  }\n\n  /**\n   * Process afterLLMCall controller and return modified final message.\n   *\n   * Skips controller invocation for interrupted calls (`finishReason === \"interrupted\"`)\n   * to preserve the original Agent behavior: the `afterLLMCall` controller was never\n   * invoked for interrupted calls in the pre-extraction code. Skipping it here prevents\n   * side effects (e.g., `append_messages` mutating conversation state) during cleanup\n   * of an already-exited run loop.\n   */\n  private async processAfterLLMCallController(\n    iteration: number,\n    llmOptions: LLMGenerationOptions,\n    result: StreamCompletionEvent,\n    gadgetCallCount: number,\n  ): Promise<string> {\n    let finalMessage = result.finalMessage;\n\n    // Skip controller for interrupted calls — the run loop has already exited,\n    // so controller side effects (append_messages, append_and_modify) would mutate\n    // conversation state with no subsequent LLM call to consume those messages.\n    if (!this.hooks.controllers?.afterLLMCall || result.finishReason === \"interrupted\") {\n      return finalMessage;\n    }\n\n    const context: AfterLLMCallControllerContext = {\n      iteration,\n      maxIterations: this.maxIterations,\n      budget: this.budget,\n      totalCost: this.tree.getTotalCost(),\n      options: llmOptions,\n      finishReason: result.finishReason,\n      usage: result.usage,\n      finalMessage: result.finalMessage,\n      gadgetCallCount,\n      logger: this.logger,\n    };\n    const action: AfterLLMCallAction = await this.hooks.controllers.afterLLMCall(context);\n\n    // Validate the action\n    validateAfterLLMCallAction(action);\n\n    if (action.action === \"modify_and_continue\" || action.action === \"append_and_modify\") {\n      finalMessage = action.modifiedMessage;\n    }\n\n    if (action.action === \"append_messages\" || action.action === \"append_and_modify\") {\n      for (const msg of action.messages) {\n        if (msg.role === \"user\") {\n          this.conversation.addUserMessage(msg.content);\n        } else if (msg.role === \"assistant\") {\n          this.conversation.addAssistantMessage(extractMessageText(msg.content));\n        } else if (msg.role === \"system\") {\n          this.conversation.addUserMessage(`[System] ${extractMessageText(msg.content)}`);\n        }\n      }\n    }\n\n    return finalMessage;\n  }\n}\n","/**\n * 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   * Hints to the consuming agent loop that when this gadget appears in an\n   * LLM iteration's tool batch, no other gadget in the same batch should\n   * execute. Sibling tool calls in the same iteration are expected to be\n   * skipped (not executed) with a synthetic result; the next LLM iteration\n   * gets only this gadget's output back, and must re-plan from there.\n   *\n   * llmist exposes this as declarative metadata only — enforcement is the\n   * consuming agent loop's responsibility (the loop already owns the\n   * stream-event consumption and the `beforeGadgetExecution` controller, so\n   * it can buffer per-iteration calls, decide barrier-status at\n   * `llm_response_end`, and skip non-barrier siblings via the standard\n   * skip-with-synthetic-result mechanism). See `LoadSkill` for the canonical\n   * use case: the agent loop should freeze sibling tool execution so the\n   * LLM sees only the loaded skill body before issuing dependent work.\n   *\n   * Orthogonal to `stickyResult` (which affects compaction) and `exclusive`\n   * (which queues the marked gadget alone, AFTER others — opposite of this\n   * flag's \"freeze the others\" semantic).\n   */\n  iterationBarrier?: 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   * If true, the consuming agent loop should treat this gadget as a per-\n   * iteration barrier — when it appears in a tool batch, no sibling gadgets\n   * in the same batch execute. See `AbstractGadget.iterationBarrier` for the\n   * full contract (enforcement is consumer-side; this flag is declarative).\n   */\n  iterationBarrier?: 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    iterationBarrier = config.iterationBarrier;\n\n    execute(\n      params: Record<string, unknown>,\n      ctx?: ExecutionContext,\n    ): GadgetExecuteReturn | Promise<GadgetExecuteReturn> {\n      // Cast to inferred type and call user's function with context\n      return config.execute(params as InferSchema<TSchema>, ctx);\n    }\n  }\n\n  return new DynamicGadget();\n}\n","/**\n * GadgetOutputViewer - Browse stored outputs from gadgets that exceeded the size limit.\n *\n * Supports two access patterns:\n * - `mode: \"line\"`: grep-like filtering and line pagination.\n * - `mode: \"character\"`: raw character windows for dense or single-line output.\n */\n\nimport { z } from \"zod\";\nimport type { GadgetOutputStore, StoredOutput } from \"../agent/gadget-output-store.js\";\nimport { createGadget } from \"./create-gadget.js\";\n\n/**\n * Pattern filter configuration.\n */\ninterface PatternFilter {\n  /** Regular expression to match */\n  regex: string;\n  /** true = keep matches, false = exclude matches */\n  include: boolean;\n  /** Context lines before match (like grep -B) */\n  before: number;\n  /** Context lines after match (like grep -A) */\n  after: number;\n}\n\ntype LimitWindow =\n  | { kind: \"first\"; count: number }\n  | { kind: \"last\"; count: number }\n  | { kind: \"range\"; start: number; end: number };\n\ninterface CharacterWindow {\n  text: string;\n  start: number;\n  end: number;\n  total: number;\n  truncatedBySize: boolean;\n  hasMoreAfter: boolean;\n}\n\n/** Default max output in characters (~19k tokens at 4 chars/token) */\nconst DEFAULT_MAX_OUTPUT_CHARS = 76_800;\nconst CHARACTER_HINT_WINDOW = 2_000;\nconst DENSE_LINE_THRESHOLD = 4_000;\n\nfunction pluralize(count: number, singular: string, plural: string = `${singular}s`): string {\n  return count === 1 ? singular : plural;\n}\n\n/**\n * Apply a single pattern filter to lines.\n *\n * For include=true: keeps lines that match (with before/after context).\n * For include=false: removes lines that match.\n */\nfunction applyPattern(lines: string[], pattern: PatternFilter): string[] {\n  const regex = new RegExp(pattern.regex);\n\n  if (!pattern.include) {\n    return lines.filter((line) => !regex.test(line));\n  }\n\n  const matchIndices = new Set<number>();\n\n  for (let i = 0; i < lines.length; i++) {\n    if (regex.test(lines[i])) {\n      const start = Math.max(0, i - pattern.before);\n      const end = Math.min(lines.length - 1, i + pattern.after);\n      for (let j = start; j <= end; j++) {\n        matchIndices.add(j);\n      }\n    }\n  }\n\n  return lines.filter((_, index) => matchIndices.has(index));\n}\n\n/**\n * Apply multiple pattern filters in sequence (like piping through grep commands).\n */\nfunction applyPatterns(lines: string[], patterns: PatternFilter[]): string[] {\n  let result = lines;\n  for (const pattern of patterns) {\n    result = applyPattern(result, pattern);\n  }\n  return result;\n}\n\n/**\n * Parse a limit string used by both line mode and character mode.\n *\n * Formats:\n * - \"100-\" → first 100 units\n * - \"-25\" → last 25 units\n * - \"50-100\" → units 50-100 (1-indexed, inclusive)\n */\nfunction parseLimitWindow(limit: string): LimitWindow | null {\n  const trimmed = limit.trim();\n\n  if (trimmed.endsWith(\"-\") && !trimmed.startsWith(\"-\")) {\n    const n = parseInt(trimmed.slice(0, -1), 10);\n    if (!Number.isNaN(n) && n > 0) {\n      return { kind: \"first\", count: n };\n    }\n  }\n\n  if (trimmed.startsWith(\"-\") && !trimmed.includes(\"-\", 1)) {\n    const n = parseInt(trimmed, 10);\n    if (!Number.isNaN(n) && n < 0) {\n      return { kind: \"last\", count: Math.abs(n) };\n    }\n  }\n\n  const rangeMatch = trimmed.match(/^(\\d+)-(\\d+)$/);\n  if (rangeMatch) {\n    const start = parseInt(rangeMatch[1], 10);\n    const end = parseInt(rangeMatch[2], 10);\n    if (!Number.isNaN(start) && !Number.isNaN(end) && start > 0 && end >= start) {\n      return { kind: \"range\", start, end };\n    }\n  }\n\n  return null;\n}\n\n/**\n * Apply line pagination using the parsed limit window.\n */\nfunction applyLineLimit(lines: string[], limit: string): string[] {\n  const window = parseLimitWindow(limit);\n  if (!window) return lines;\n\n  switch (window.kind) {\n    case \"first\":\n      return lines.slice(0, window.count);\n    case \"last\":\n      return lines.slice(-window.count);\n    case \"range\":\n      return lines.slice(window.start - 1, window.end);\n  }\n}\n\n/**\n * Apply character pagination over the raw stored string.\n */\nfunction applyCharacterLimit(\n  content: string,\n  limit: string | undefined,\n  maxOutputChars: number,\n): CharacterWindow {\n  const total = content.length;\n  if (total === 0) {\n    return { text: \"\", start: 0, end: 0, total: 0, truncatedBySize: false, hasMoreAfter: false };\n  }\n\n  let startIndex = 0;\n  let endExclusive = total;\n  const window = limit ? parseLimitWindow(limit) : null;\n\n  if (window) {\n    switch (window.kind) {\n      case \"first\":\n        endExclusive = Math.min(window.count, total);\n        break;\n      case \"last\":\n        startIndex = Math.max(0, total - window.count);\n        break;\n      case \"range\":\n        startIndex = Math.min(window.start - 1, total);\n        endExclusive = Math.min(window.end, total);\n        break;\n    }\n  }\n\n  let text = content.slice(startIndex, endExclusive);\n  let truncatedBySize = false;\n  if (text.length > maxOutputChars) {\n    text = window?.kind === \"last\" ? text.slice(-maxOutputChars) : text.slice(0, maxOutputChars);\n    if (window?.kind === \"last\") {\n      startIndex = endExclusive - text.length;\n    }\n    truncatedBySize = true;\n  }\n\n  return {\n    text,\n    start: text.length === 0 ? 0 : startIndex + 1,\n    end: text.length === 0 ? 0 : startIndex + text.length,\n    total,\n    truncatedBySize,\n    hasMoreAfter: startIndex + text.length < total,\n  };\n}\n\nfunction buildCharacterRangeHint(start: number, total: number): string | null {\n  if (total <= 0 || start > total) return null;\n  const end = Math.min(total, start + CHARACTER_HINT_WINDOW - 1);\n  return `${start}-${end}`;\n}\n\nfunction buildCharacterModeSuggestion(\n  stored: Pick<StoredOutput, \"charCount\" | \"lineCount\" | \"maxLineLength\">,\n  opts: { removePatterns?: boolean; start?: number } = {},\n): string {\n  const hint = buildCharacterRangeHint(opts.start ?? 1, stored.charCount);\n  const action = opts.removePatterns ? \"Remove patterns and then try\" : \"Try\";\n  const lineLabel = pluralize(stored.lineCount, \"line\");\n\n  return (\n    `This output is dense (${stored.lineCount.toLocaleString()} ${lineLabel}; ` +\n    `longest line ${stored.maxLineLength.toLocaleString()} chars). ` +\n    `${action} mode: \"character\"` +\n    (hint ? `, limit: \"${hint}\"` : \"\") +\n    \".\"\n  );\n}\n\nfunction shouldSuggestCharacterMode(\n  stored: Pick<StoredOutput, \"lineCount\" | \"maxLineLength\">,\n  maxOutputChars: number = DEFAULT_MAX_OUTPUT_CHARS,\n): boolean {\n  return (\n    stored.lineCount <= 3 &&\n    (stored.maxLineLength > maxOutputChars || stored.maxLineLength >= DENSE_LINE_THRESHOLD)\n  );\n}\n\n/**\n * Schema for pattern filter objects.\n */\nconst patternSchema = z.object({\n  regex: z.string().describe(\"Regular expression to match\"),\n  include: z\n    .boolean()\n    .default(true)\n    .describe(\"true = keep matching lines, false = exclude matching lines\"),\n  before: z\n    .number()\n    .int()\n    .min(0)\n    .default(0)\n    .describe(\"Context lines before each match (like grep -B)\"),\n  after: z\n    .number()\n    .int()\n    .min(0)\n    .default(0)\n    .describe(\"Context lines after each match (like grep -A)\"),\n});\n\n/**\n * Create a GadgetOutputViewer gadget instance bound to a specific output store.\n *\n * @param store - The GadgetOutputStore to read outputs from\n * @param maxOutputChars - Maximum characters to return (default: 76,800 = ~19k tokens)\n * @returns A GadgetOutputViewer gadget instance\n */\nexport function createGadgetOutputViewer(\n  store: GadgetOutputStore,\n  maxOutputChars: number = DEFAULT_MAX_OUTPUT_CHARS,\n) {\n  return createGadget({\n    name: \"GadgetOutputViewer\",\n    description:\n      \"View stored output from gadgets that returned too much data. \" +\n      'Use mode \"line\" for grep-like filtering and mode \"character\" for raw chunked browsing ' +\n      \"when the output is dense or effectively single-line. Patterns work only in line mode.\",\n    schema: z.object({\n      id: z.string().describe(\"ID of the stored output (from the truncation message)\"),\n      mode: z\n        .enum([\"line\", \"character\"])\n        .default(\"line\")\n        .describe(\n          'Browse by \"line\" (supports patterns) or by \"character\" (raw windows for dense output).',\n        ),\n      patterns: z\n        .array(patternSchema)\n        .optional()\n        .describe(\n          \"Line-mode filter patterns applied in order (like piping through grep). \" +\n            'Not supported in mode \"character\".',\n        ),\n      limit: z\n        .string()\n        .optional()\n        .describe(\n          'Pagination window. In mode \"line\" it is a line range; in mode \"character\" it is ' +\n            `a character range. Formats: \"100-\" (first 100), \"-25\" (last 25), ` +\n            '\"50-100\" (inclusive range).',\n        ),\n    }),\n    examples: [\n      {\n        comment: \"View first 50 lines of stored output\",\n        params: { id: \"Search_abc12345\", mode: \"line\", limit: \"50-\" },\n      },\n      {\n        comment: \"Filter for error lines with context\",\n        params: {\n          id: \"Search_abc12345\",\n          mode: \"line\",\n          patterns: [{ regex: \"error|Error|ERROR\", include: true, before: 2, after: 5 }],\n        },\n      },\n      {\n        comment: \"Exclude blank lines, then show first 100 lines\",\n        params: {\n          id: \"Search_abc12345\",\n          mode: \"line\",\n          patterns: [{ regex: \"^\\\\s*$\", include: false, before: 0, after: 0 }],\n          limit: \"100-\",\n        },\n      },\n      {\n        comment: \"Browse the raw output by character window when line mode is too dense\",\n        params: {\n          id: \"Search_abc12345\",\n          mode: \"character\",\n          limit: \"1-2000\",\n        },\n      },\n    ],\n    execute: ({ id, mode, patterns, limit }) => {\n      const stored = store.get(id);\n      if (!stored) {\n        return `Error: No stored output with id \"${id}\". Available IDs: ${store.getIds().join(\", \") || \"(none)\"}`;\n      }\n\n      const suggestCharacterMode = shouldSuggestCharacterMode(stored, maxOutputChars);\n\n      if (mode === \"character\") {\n        if (patterns && patterns.length > 0) {\n          return (\n            'Error: patterns are only supported in mode \"line\". ' +\n            'Remove patterns or switch back to mode: \"line\".'\n          );\n        }\n\n        const window = applyCharacterLimit(stored.content, limit, maxOutputChars);\n        if (window.total === 0) {\n          return \"[Mode: character | Output is empty]\";\n        }\n\n        const header = [\n          `[Mode: character | Showing chars ${window.start.toLocaleString()}-${window.end.toLocaleString()} of ${window.total.toLocaleString()}${\n            window.truncatedBySize ? \" (truncated due to viewer size limit)\" : \"\"\n          }]`,\n        ];\n\n        if (window.hasMoreAfter) {\n          const nextRange = buildCharacterRangeHint(window.end + 1, window.total);\n          if (nextRange) {\n            header.push(`[Next chunk: mode: \"character\", limit: \"${nextRange}\"]`);\n          }\n        }\n\n        return `${header.join(\"\\n\")}\\n${window.text}`;\n      }\n\n      let lines = stored.content.split(\"\\n\");\n\n      if (patterns && patterns.length > 0) {\n        lines = applyPatterns(\n          lines,\n          patterns.map((p) => ({\n            regex: p.regex,\n            include: p.include ?? true,\n            before: p.before ?? 0,\n            after: p.after ?? 0,\n          })),\n        );\n      }\n\n      if (limit) {\n        lines = applyLineLimit(lines, limit);\n      }\n\n      const totalLines = stored.lineCount;\n      const totalLineLabel = pluralize(totalLines, \"line\");\n      const returnedLines = lines.length;\n\n      if (returnedLines === 0) {\n        const base = `No lines matched the filters. Original output had ${totalLines.toLocaleString()} lines.`;\n        if (!suggestCharacterMode) return base;\n        return `${base} ${buildCharacterModeSuggestion(stored, {\n          removePatterns: Boolean(patterns && patterns.length > 0),\n        })}`;\n      }\n\n      let output = lines.join(\"\\n\");\n      let truncatedBySize = false;\n      let linesIncluded = returnedLines;\n      let clippedFirstLine = false;\n\n      if (output.length > maxOutputChars) {\n        truncatedBySize = true;\n        let truncatedOutput = \"\";\n        linesIncluded = 0;\n\n        for (const line of lines) {\n          const addition = linesIncluded === 0 ? line : `\\n${line}`;\n          if (truncatedOutput.length + addition.length > maxOutputChars) break;\n          truncatedOutput += addition;\n          linesIncluded++;\n        }\n\n        if (linesIncluded === 0) {\n          clippedFirstLine = true;\n          linesIncluded = 1;\n          truncatedOutput = lines[0].slice(0, maxOutputChars);\n        }\n\n        output = truncatedOutput;\n      }\n\n      let header: string;\n      if (clippedFirstLine) {\n        header =\n          `[Mode: line | Showing 1 partial line of ${totalLines.toLocaleString()} ${totalLineLabel} ` +\n          \"(the selected line exceeds the viewer size limit)]\\n\";\n      } else if (truncatedBySize) {\n        const remainingLines = returnedLines - linesIncluded;\n        header =\n          `[Mode: line | Showing ${linesIncluded.toLocaleString()} of ${totalLines.toLocaleString()} ${totalLineLabel} ` +\n          \"(truncated due to size limit)]\\n\" +\n          `[... ${remainingLines.toLocaleString()} more ${pluralize(remainingLines, \"line\")}. ` +\n          `Use limit parameter to paginate, e.g., limit: \"${linesIncluded + 1}-${linesIncluded + 200}\"]\\n`;\n      } else if (returnedLines < totalLines) {\n        header =\n          `[Mode: line | Showing ${returnedLines.toLocaleString()} ` +\n          `of ${totalLines.toLocaleString()} ${totalLineLabel}]\\n`;\n      } else {\n        header = `[Mode: line | Showing all ${totalLines.toLocaleString()} ${totalLineLabel}]\\n`;\n      }\n\n      const footer =\n        suggestCharacterMode || clippedFirstLine\n          ? `\\n[Tip: ${buildCharacterModeSuggestion(stored, {\n              removePatterns: Boolean(patterns && patterns.length > 0),\n            })}]`\n          : \"\";\n\n      return header + output + footer;\n    },\n  });\n}\n\n// Export helpers for testing\nexport {\n  applyCharacterLimit,\n  applyLineLimit,\n  applyPattern,\n  applyPatterns,\n  buildCharacterModeSuggestion,\n  parseLimitWindow,\n  shouldSuggestCharacterMode,\n};\n","/**\n * Storage for large gadget outputs that exceed the configured limit.\n *\n * When a gadget returns more data than the configured limit, the output\n * is stored here and can be browsed later using GadgetOutputViewer.\n */\n\nimport { randomBytes } from \"node:crypto\";\n\n/**\n * Metadata and content for a stored gadget output.\n */\nexport interface StoredOutput {\n  /** Unique identifier (e.g., \"Search_d34db33f\") */\n  id: string;\n  /** Name of the gadget that produced this output */\n  gadgetName: string;\n  /** Full output content */\n  content: string;\n  /** Total character count of the stored content */\n  charCount: number;\n  /** Size in bytes */\n  byteSize: number;\n  /** Number of lines */\n  lineCount: number;\n  /** Length of the longest line in characters */\n  maxLineLength: number;\n  /** When the output was stored */\n  timestamp: Date;\n}\n\n/**\n * In-memory store for large gadget outputs.\n *\n * Outputs are stored with generated IDs in the format `{GadgetName}_{hex8}`.\n * The store is tied to an agent run and cleared when the agent completes.\n *\n * @example\n * ```typescript\n * const store = new GadgetOutputStore();\n * const id = store.store(\"Search\", largeOutput);\n * // id = \"Search_a1b2c3d4\"\n *\n * const stored = store.get(id);\n * console.log(stored?.lineCount); // 4200\n * ```\n */\nexport class GadgetOutputStore {\n  private outputs = new Map<string, StoredOutput>();\n\n  /**\n   * Store a gadget output and return its ID.\n   *\n   * @param gadgetName - Name of the gadget that produced the output\n   * @param content - Full output content to store\n   * @returns Generated ID for retrieving the output later\n   */\n  store(gadgetName: string, content: string): string {\n    const id = this.generateId(gadgetName);\n    const encoder = new TextEncoder();\n    const lines = content.split(\"\\n\");\n\n    const stored: StoredOutput = {\n      id,\n      gadgetName,\n      content,\n      charCount: content.length,\n      byteSize: encoder.encode(content).length,\n      lineCount: lines.length,\n      maxLineLength: lines.reduce((max, line) => Math.max(max, line.length), 0),\n      timestamp: new Date(),\n    };\n\n    this.outputs.set(id, stored);\n    return id;\n  }\n\n  /**\n   * Retrieve a stored output by ID.\n   *\n   * @param id - The output ID (e.g., \"Search_d34db33f\")\n   * @returns The stored output or undefined if not found\n   */\n  get(id: string): StoredOutput | undefined {\n    return this.outputs.get(id);\n  }\n\n  /**\n   * Check if an output exists.\n   *\n   * @param id - The output ID to check\n   * @returns True if the output exists\n   */\n  has(id: string): boolean {\n    return this.outputs.has(id);\n  }\n\n  /**\n   * Get all stored output IDs.\n   *\n   * @returns Array of output IDs\n   */\n  getIds(): string[] {\n    return Array.from(this.outputs.keys());\n  }\n\n  /**\n   * Get the number of stored outputs.\n   */\n  get size(): number {\n    return this.outputs.size;\n  }\n\n  /**\n   * Clear all stored outputs.\n   * Called when the agent run completes.\n   */\n  clear(): void {\n    this.outputs.clear();\n  }\n\n  /**\n   * Generate a unique ID for a stored output.\n   * Format: {GadgetName}_{8 hex chars}\n   */\n  private generateId(gadgetName: string): string {\n    const hex = randomBytes(4).toString(\"hex\");\n    return `${gadgetName}_${hex}`;\n  }\n}\n","/**\n * OutputLimitManager - Manages gadget output size limiting.\n *\n * Calculates character limits from model context windows, registers\n * GadgetOutputViewer when enabled, and chains the output limiter\n * interceptor with user-provided hooks.\n */\n\nimport type { ILogObj, Logger } from \"tslog\";\nimport type { LLMist } from \"../core/client.js\";\nimport {\n  CHARS_PER_TOKEN,\n  DEFAULT_GADGET_OUTPUT_LIMIT,\n  DEFAULT_GADGET_OUTPUT_LIMIT_PERCENT,\n  FALLBACK_CONTEXT_WINDOW,\n} from \"../core/constants.js\";\nimport {\n  buildCharacterModeSuggestion,\n  createGadgetOutputViewer,\n  shouldSuggestCharacterMode,\n} from \"../gadgets/output-viewer.js\";\nimport type { GadgetRegistry } from \"../gadgets/registry.js\";\nimport { createLogger } from \"../logging/logger.js\";\nimport { GadgetOutputStore } from \"./gadget-output-store.js\";\nimport type { AgentHooks, GadgetResultInterceptorContext } from \"./hooks.js\";\n\n/**\n * Configuration for output limiting.\n */\nexport interface OutputLimitConfig {\n  /** Whether output limiting is enabled (default: true) */\n  enabled?: boolean;\n  /** Max gadget output as % of model context window (default: 15) */\n  limitPercent?: number;\n}\n\n/**\n * OutputLimitManager orchestrates gadget output size limiting for an agent.\n *\n * It:\n * - Calculates the character limit from the model context window and limitPercent\n * - Registers GadgetOutputViewer when limiting is enabled\n * - Chains the output limiter interceptor with user-provided hooks\n * - Stores oversized gadget outputs for later browsing\n */\nexport class OutputLimitManager {\n  private readonly outputStore: GadgetOutputStore;\n  private readonly enabled: boolean;\n  private readonly charLimit: number;\n  private readonly logger: Logger<ILogObj>;\n\n  constructor(\n    client: LLMist,\n    model: string,\n    config: OutputLimitConfig,\n    registry: GadgetRegistry,\n    logger?: Logger<ILogObj>,\n  ) {\n    this.logger = logger ?? createLogger({ name: \"llmist:output-limit-manager\" });\n    this.enabled = config.enabled ?? DEFAULT_GADGET_OUTPUT_LIMIT;\n    this.outputStore = new GadgetOutputStore();\n\n    // Calculate character limit from model context window\n    const limitPercent = config.limitPercent ?? DEFAULT_GADGET_OUTPUT_LIMIT_PERCENT;\n    const limits = client.modelRegistry.getModelLimits(model);\n    const contextWindow = limits?.contextWindow ?? FALLBACK_CONTEXT_WINDOW;\n    this.charLimit = Math.floor(contextWindow * (limitPercent / 100) * CHARS_PER_TOKEN);\n\n    // Auto-register GadgetOutputViewer when limiting is enabled\n    // Pass the same character limit so viewer output is also bounded\n    if (this.enabled) {\n      registry.register(\n        \"GadgetOutputViewer\",\n        createGadgetOutputViewer(this.outputStore, this.charLimit),\n      );\n    }\n  }\n\n  /**\n   * Get the hooks with the output limiter interceptor chained with user hooks.\n   *\n   * The limiter interceptor runs first, then the user-provided interceptor.\n   *\n   * @param userHooks - Optional user-provided hooks to chain with\n   * @returns AgentHooks with the output limiter interceptor chained in\n   */\n  getHooks(userHooks?: AgentHooks): AgentHooks {\n    if (!this.enabled) {\n      return userHooks ?? {};\n    }\n\n    const limiterInterceptor = (result: string, ctx: GadgetResultInterceptorContext): string => {\n      // Skip limiting for GadgetOutputViewer itself to avoid recursion\n      if (ctx.gadgetName === \"GadgetOutputViewer\") {\n        return result;\n      }\n\n      if (result.length > this.charLimit) {\n        const id = this.outputStore.store(ctx.gadgetName, result);\n        const stored = this.outputStore.get(id);\n        const lines = stored?.lineCount ?? result.split(\"\\n\").length;\n        const bytes = stored?.byteSize ?? new TextEncoder().encode(result).length;\n        const denseSuggestion =\n          stored && shouldSuggestCharacterMode(stored, this.charLimit)\n            ? ` ${buildCharacterModeSuggestion(stored)}`\n            : \"\";\n\n        this.logger.info(\"Gadget output exceeded limit, stored for browsing\", {\n          gadgetName: ctx.gadgetName,\n          outputId: id,\n          bytes,\n          lines,\n          charCount: stored?.charCount,\n          maxLineLength: stored?.maxLineLength,\n          charLimit: this.charLimit,\n        });\n\n        return (\n          `[Gadget \"${ctx.gadgetName}\" returned too much data: ` +\n          `${bytes.toLocaleString()} bytes, ${lines.toLocaleString()} lines. ` +\n          `Use GadgetOutputViewer with id \"${id}\" to read it.]` +\n          denseSuggestion\n        );\n      }\n\n      return result;\n    };\n\n    // Chain with any user-provided interceptor (limiter runs first)\n    const userInterceptor = userHooks?.interceptors?.interceptGadgetResult;\n    const chainedInterceptor = userInterceptor\n      ? (result: string, ctx: GadgetResultInterceptorContext) =>\n          userInterceptor(limiterInterceptor(result, ctx), ctx)\n      : limiterInterceptor;\n\n    return {\n      ...userHooks,\n      interceptors: {\n        ...userHooks?.interceptors,\n        interceptGadgetResult: chainedInterceptor,\n      },\n    };\n  }\n\n  /**\n   * Get the output store for accessing stored oversized outputs.\n   *\n   * @returns The GadgetOutputStore instance\n   */\n  getOutputStore(): GadgetOutputStore {\n    return this.outputStore;\n  }\n\n  /**\n   * Check if output limiting is enabled.\n   *\n   * @returns true if output limiting is enabled\n   */\n  isEnabled(): boolean {\n    return this.enabled;\n  }\n}\n","/**\n * Error utilities for llmist.\n */\n\n/**\n * Thrown when an LLM provider returns a completion with no usable output —\n * no text, no tool calls, and no reasoning — typically a transient provider\n * glitch (e.g. a 200-OK response with an empty body). The retry orchestrator\n * treats this as a retryable failure; if every attempt comes back empty it\n * surfaces this error rather than committing a silent blank turn.\n */\nexport class EmptyCompletionError extends Error {\n  /** Agent iteration on which the empty completion was observed. */\n  readonly iteration: number;\n  /** Finish reason reported alongside the empty body (often null). */\n  readonly finishReason: string | null;\n\n  constructor(params: { iteration: number; finishReason: string | null }) {\n    super(\n      `LLM returned an empty completion (no text, tool calls, or reasoning) on iteration ${params.iteration}`,\n    );\n    this.name = \"EmptyCompletionError\";\n    this.iteration = params.iteration;\n    this.finishReason = params.finishReason;\n  }\n}\n\n/**\n * Detects if an error is an abort/cancellation error from any provider.\n *\n * Different providers throw different error types when a request is aborted:\n * - Standard: `AbortError` (name) - from fetch/AbortController\n * - Anthropic SDK: `APIConnectionAbortedError`\n * - OpenAI SDK: `APIUserAbortError`\n * - Generic: errors with \"abort\", \"cancelled\", or \"canceled\" in the message\n *\n * @param error - The error to check\n * @returns `true` if the error is an abort-related error, `false` otherwise\n *\n * @example\n * ```typescript\n * import { isAbortError } from \"@llmist/core/errors\";\n *\n * const controller = new AbortController();\n *\n * try {\n *   for await (const chunk of client.stream({ signal: controller.signal, ... })) {\n *     // Process chunks...\n *   }\n * } catch (error) {\n *   if (isAbortError(error)) {\n *     console.log(\"Request was cancelled - this is expected\");\n *     return; // Graceful exit\n *   }\n *   // Re-throw unexpected errors\n *   throw error;\n * }\n * ```\n */\nexport function isAbortError(error: unknown): boolean {\n  if (!(error instanceof Error)) return false;\n\n  // Standard AbortError (from fetch/AbortController)\n  if (error.name === \"AbortError\") return true;\n\n  // Anthropic SDK\n  if (error.name === \"APIConnectionAbortedError\") return true;\n\n  // OpenAI SDK\n  if (error.name === \"APIUserAbortError\") return true;\n\n  // Message-based detection (fallback for edge cases)\n  const message = error.message.toLowerCase();\n  if (message.includes(\"abort\")) return true;\n  if (message.includes(\"cancelled\")) return true;\n  if (message.includes(\"canceled\")) return true;\n\n  return false;\n}\n","/**\n * RetryOrchestrator: Encapsulates retry logic for LLM stream execution.\n *\n * Extracted from the 155-line `executeWithRetry()` method in `agent.ts` to provide\n * a focused, testable module for managing retry attempts with exponential backoff,\n * Retry-After header support, jitter, and observer hook notification.\n *\n * Follows the `GadgetDependencyResolver` pattern: constructor receives all dependencies,\n * exposes a clean public API.\n */\n\nimport type { ILogObj, Logger } from \"tslog\";\nimport { EmptyCompletionError } from \"../core/errors.js\";\nimport type { ExecutionTree } from \"../core/execution-tree.js\";\nimport type { LLMGenerationOptions } from \"../core/options.js\";\nimport type { ResolvedRetryConfig } from \"../core/retry.js\";\nimport { extractRetryAfterMs, isRetryableError } from \"../core/retry.js\";\nimport type { StreamCompletionEvent, StreamEvent } from \"../gadgets/types.js\";\nimport type { AgentHooks, ObserveRetryAttemptContext } from \"./hooks.js\";\nimport { safeObserve } from \"./safe-observe.js\";\nimport type { StreamProcessor } from \"./stream-processor.js\";\nimport { getSubagentContextForNode } from \"./tree-hook-bridge.js\";\n\n/**\n * Determines whether a stream completion carried no usable output at all —\n * no text, no executed gadgets, and no reasoning content.\n *\n * This is the signature of a provider glitch (e.g. a 200-OK response with an\n * empty body): the call \"succeeded\" but produced nothing. A turn with empty\n * text but an executed gadget is NOT empty — the tool call is the output — so\n * `didExecuteGadgets` short-circuits to `false`.\n */\nexport function isEmptyCompletion(meta: StreamCompletionEvent): boolean {\n  if (meta.didExecuteGadgets) return false;\n  if (meta.rawResponse?.trim() || meta.finalMessage?.trim()) return false;\n  if (meta.thinkingContent?.trim()) return false;\n  return true;\n}\n\n/**\n * The final result returned by a successful `orchestrate()` call.\n * Contains stream metadata and accumulated tracking state from the final\n * successful attempt only (state is reset between retry attempts).\n */\nexport interface RetryResult {\n  /** Stream completion metadata from the final successful attempt */\n  streamMetadata: StreamCompletionEvent;\n  /** All text content yielded during the final successful attempt */\n  textOutputs: string[];\n  /** All gadget result events from the final successful attempt */\n  gadgetResults: StreamEvent[];\n  /** Total number of gadget calls during the final successful attempt */\n  gadgetCallCount: number;\n}\n\n/**\n * Callback type for creating an LLM stream.\n * Receives the same arguments as the corresponding `Agent.createStream()` method.\n */\nexport type CreateStreamFn = (\n  llmOptions: LLMGenerationOptions,\n  iteration: number,\n  llmNodeId: string,\n) => Promise<ReturnType<import(\"../core/client.js\").LLMist[\"stream\"]>>;\n\n/**\n * Callback type for creating a StreamProcessor for a given iteration.\n */\nexport type CreateStreamProcessorFn = (iteration: number, llmNodeId: string) => StreamProcessor;\n\n/**\n * Options for constructing a RetryOrchestrator.\n */\nexport interface RetryOrchestratorOptions {\n  /** Resolved retry configuration controlling backoff behaviour */\n  retryConfig: ResolvedRetryConfig;\n  /** Logger for emitting warnings and errors */\n  logger: Logger<ILogObj>;\n  /** Agent hooks (observers) for emitting `onRetryAttempt` events */\n  hooks: AgentHooks;\n  /** Execution tree used to signal LLM response end and derive subagent context */\n  tree: ExecutionTree;\n  /** Sleep function (injectable for testing) */\n  sleep: (ms: number) => Promise<void>;\n}\n\n/**\n * RetryOrchestrator: Manages all retry state and orchestration for a single\n * LLM stream execution attempt (across one or more stream attempts).\n *\n * Encapsulates:\n * - Attempt counter and max-attempts calculation\n * - Accumulated outputs (`textOutputs`, `gadgetResults`, `gadgetCallCount`)\n * - Backoff calculation: exponential factor, capping, Retry-After extraction, jitter\n * - Observer hook emission (`onRetryAttempt`) with correct context\n * - Cross-iteration invocation ID tracking (`completedInvocationIds`, `failedInvocationIds`)\n *\n * @example\n * ```typescript\n * const orchestrator = new RetryOrchestrator({\n *   retryConfig,\n *   logger,\n *   hooks,\n *   tree,\n *   sleep: (ms) => new Promise((r) => setTimeout(r, ms)),\n * });\n *\n * const gen = orchestrator.orchestrate(llmOptions, iteration, llmNodeId, createStream, createStreamProcessor);\n * let next = await gen.next();\n * while (!next.done) {\n *   yield next.value;\n *   next = await gen.next();\n * }\n * const result = next.value; // RetryResult | null\n * ```\n */\nexport class RetryOrchestrator {\n  private readonly retryConfig: ResolvedRetryConfig;\n  private readonly logger: Logger<ILogObj>;\n  private readonly hooks: AgentHooks;\n  private readonly tree: ExecutionTree;\n  private readonly sleep: (ms: number) => Promise<void>;\n\n  /** Invocation IDs that completed in the last orchestrate() call */\n  private completedInvocationIds: Set<string> = new Set();\n  /** Invocation IDs that failed in the last orchestrate() call */\n  private failedInvocationIds: Set<string> = new Set();\n\n  constructor(options: RetryOrchestratorOptions) {\n    this.retryConfig = options.retryConfig;\n    this.logger = options.logger;\n    this.hooks = options.hooks;\n    this.tree = options.tree;\n    this.sleep = options.sleep;\n  }\n\n  // ==========================================================================\n  // Cross-iteration accessors (for Agent to accumulate IDs across iterations)\n  // ==========================================================================\n\n  /**\n   * Returns the set of invocation IDs that completed successfully in the most\n   * recent `orchestrate()` call. The Agent uses this to accumulate cross-iteration\n   * dependency state.\n   */\n  getCompletedInvocationIds(): Set<string> {\n    return this.completedInvocationIds;\n  }\n\n  /**\n   * Returns the set of invocation IDs that failed in the most recent\n   * `orchestrate()` call.\n   */\n  getFailedInvocationIds(): Set<string> {\n    return this.failedInvocationIds;\n  }\n\n  // ==========================================================================\n  // Core orchestration\n  // ==========================================================================\n\n  /**\n   * Execute a single LLM call attempt with full retry orchestration.\n   *\n   * Handles stream creation, retry attempts with exponential backoff, error handling,\n   * and state reset between attempts. Yields stream events in real-time and returns\n   * the final stream completion metadata along with accumulated tracking state\n   * (textOutputs, gadgetResults, gadgetCallCount) from the final successful attempt only.\n   * State is reset between retry attempts to prevent accumulation of partial data.\n   *\n   * @param llmOptions - LLM generation options to pass to the stream\n   * @param iteration - Current agent iteration number\n   * @param llmNodeId - Node ID in the execution tree for this LLM call\n   * @param createStream - Callback that creates the LLM stream\n   * @param createStreamProcessor - Callback that creates the StreamProcessor\n   */\n  async *orchestrate(\n    llmOptions: LLMGenerationOptions,\n    iteration: number,\n    llmNodeId: string,\n    createStream: CreateStreamFn,\n    createStreamProcessor: CreateStreamProcessorFn,\n  ): AsyncGenerator<StreamEvent, RetryResult | null> {\n    // Reset cross-iteration tracking for this orchestrate() call\n    this.completedInvocationIds = new Set();\n    this.failedInvocationIds = new Set();\n\n    const maxStreamAttempts = this.retryConfig.enabled ? this.retryConfig.retries + 1 : 1;\n    let streamAttempt = 0;\n    let streamMetadata: StreamCompletionEvent | null = null;\n    let gadgetCallCount = 0;\n    const textOutputs: string[] = [];\n    const gadgetResults: StreamEvent[] = [];\n    // Set when every attempt returned an empty completion; thrown after the\n    // loop so it never falls into the generic error-retry catch below.\n    let emptyFailure: EmptyCompletionError | null = null;\n\n    while (streamAttempt < maxStreamAttempts) {\n      streamAttempt++;\n\n      try {\n        // Create LLM stream with rate limiting (retry is handled by this outer loop)\n        const stream = await createStream(llmOptions, iteration, llmNodeId);\n\n        // Process stream — ALL complexity delegated to StreamProcessor\n        const processor = createStreamProcessor(iteration, llmNodeId);\n\n        // Consume the stream processor generator, yielding events in real-time.\n        // The final event is a StreamCompletionEvent containing metadata.\n        for await (const event of processor.process(stream)) {\n          if (event.type === \"stream_complete\") {\n            // Capture the completion metadata but DEFER yielding it until\n            // after the empty-completion check below. `stream_complete` is\n            // always the final event from the processor, so deferring its\n            // yield preserves event order for the success path while\n            // ensuring a retried (discarded) empty attempt's terminal event\n            // never reaches the consumer.\n            //\n            // Yielding `stream_complete` is load-bearing for any consumer\n            // that needs the post-`waitForInFlightExecutions` boundary\n            // (after every in-flight gadget body has completed). The\n            // earlier `llm_response_end` event fires before gadgets\n            // complete, so it can't be used as a \"this iteration is fully\n            // done\" signal — that's exactly what `stream_complete` is for.\n            streamMetadata = event;\n            continue;\n          }\n\n          if (event.type === \"llm_response_end\") {\n            // Signal that LLM finished generating (before gadgets complete).\n            // This allows consumers to track \"LLM thinking time\" separately.\n            this.tree.endLLMResponse(llmNodeId, {\n              finishReason: event.finishReason,\n              usage: event.usage,\n            });\n          }\n\n          // Track outputs from this attempt for conversation history updates\n          if (event.type === \"text\") {\n            textOutputs.push(event.content);\n          } else if (event.type === \"gadget_result\") {\n            gadgetCallCount++;\n            gadgetResults.push(event);\n          }\n\n          // Yield event to consumer in real-time\n          // (includes subagent events from completedResultsQueue for real-time streaming)\n          yield event;\n        }\n\n        // Collect completed/failed invocation IDs for cross-iteration dependency tracking\n        for (const id of processor.getCompletedInvocationIds()) {\n          this.completedInvocationIds.add(id);\n        }\n        for (const id of processor.getFailedInvocationIds()) {\n          this.failedInvocationIds.add(id);\n        }\n\n        // Dropped-completion guard: a 200-OK response with no text, no tool\n        // calls, and no reasoning AND no finish reason is a provider glitch\n        // (the response was dropped), not a real turn. A deliberately empty\n        // turn carries an explicit finish reason (e.g. \"stop\") — the model\n        // chose to say nothing, often after a prior tool call — and must NOT\n        // be retried. Route only genuine drops through the same backoff\n        // machinery as thrown errors so a blank reply is retried instead of\n        // silently committed.\n        if (\n          this.retryConfig.enabled &&\n          this.retryConfig.retryOnEmpty &&\n          streamMetadata !== null &&\n          !streamMetadata.finishReason &&\n          isEmptyCompletion(streamMetadata)\n        ) {\n          const emptyError = new EmptyCompletionError({\n            iteration,\n            finishReason: streamMetadata.finishReason,\n          });\n\n          if (streamAttempt < maxStreamAttempts) {\n            await this.backoffBeforeRetry(\n              emptyError,\n              streamAttempt,\n              maxStreamAttempts,\n              iteration,\n              llmNodeId,\n            );\n\n            // Reset state for retry attempt (discard the empty attempt)\n            streamMetadata = null;\n            gadgetCallCount = 0;\n            textOutputs.length = 0;\n            gadgetResults.length = 0;\n\n            continue;\n          }\n\n          // Every attempt came back empty. Record the failure and break; it\n          // is thrown after the loop so it cannot re-enter the catch below.\n          emptyFailure = emptyError;\n          break;\n        }\n\n        // Stream completed successfully — emit the deferred terminal event\n        // and break the retry loop.\n        if (streamMetadata !== null) {\n          yield streamMetadata;\n        }\n        break;\n      } catch (streamError) {\n        // Check if this is a retryable error and we have attempts remaining\n        const error = streamError as Error;\n        const canRetry = this.retryConfig.enabled && streamAttempt < maxStreamAttempts;\n        const shouldRetryError = this.retryConfig.shouldRetry\n          ? this.retryConfig.shouldRetry(error)\n          : isRetryableError(error);\n\n        if (canRetry && shouldRetryError) {\n          await this.backoffBeforeRetry(\n            error,\n            streamAttempt,\n            maxStreamAttempts,\n            iteration,\n            llmNodeId,\n          );\n\n          // Reset state for retry attempt (clear any partial results from failed attempt)\n          streamMetadata = null;\n          gadgetCallCount = 0;\n          textOutputs.length = 0;\n          gadgetResults.length = 0;\n\n          continue;\n        }\n\n        // Not retryable or retries exhausted\n        if (streamAttempt > 1) {\n          // We had at least one retry — call exhausted callback\n          this.logger.error(`Stream iteration failed after ${streamAttempt} attempts`, {\n            error: error.message,\n            iteration,\n          });\n          this.retryConfig.onRetriesExhausted?.(error, streamAttempt);\n        }\n        throw error;\n      }\n    }\n\n    // Surface an all-empty run as a hard failure rather than a silent blank.\n    if (emptyFailure !== null) {\n      this.logger.error(`LLM returned empty completions on all ${streamAttempt} attempts`, {\n        iteration,\n      });\n      this.retryConfig.onRetriesExhausted?.(emptyFailure, streamAttempt);\n      throw emptyFailure;\n    }\n\n    return streamMetadata !== null\n      ? { streamMetadata, textOutputs, gadgetResults, gadgetCallCount }\n      : null;\n  }\n\n  /**\n   * Apply the configured backoff before a retry attempt: compute the delay\n   * (Retry-After hint or exponential backoff, with optional jitter), emit the\n   * retry log, fire the `onRetry` callback and `onRetryAttempt` observer, then\n   * sleep. Shared by the error-retry and empty-completion-retry paths so both\n   * honour identical backoff and observer semantics.\n   */\n  private async backoffBeforeRetry(\n    error: Error,\n    streamAttempt: number,\n    maxStreamAttempts: number,\n    iteration: number,\n    llmNodeId: string,\n  ): Promise<void> {\n    // Extract Retry-After hint if present\n    const retryAfterMs = this.retryConfig.respectRetryAfter ? extractRetryAfterMs(error) : null;\n\n    // Calculate delay: use Retry-After if available, otherwise exponential backoff\n    const baseDelay = this.retryConfig.minTimeout * this.retryConfig.factor ** (streamAttempt - 1);\n    const cappedBaseDelay = Math.min(baseDelay, this.retryConfig.maxTimeout);\n    const delay =\n      retryAfterMs !== null\n        ? Math.min(retryAfterMs, this.retryConfig.maxRetryAfterMs)\n        : cappedBaseDelay;\n\n    // Add jitter if randomize is enabled\n    const finalDelay = this.retryConfig.randomize ? delay * (0.5 + Math.random()) : delay;\n\n    this.logger.warn(\n      `Stream iteration failed (attempt ${streamAttempt}/${maxStreamAttempts}), retrying...`,\n      {\n        error: error.message,\n        retriesLeft: maxStreamAttempts - streamAttempt,\n        delayMs: Math.round(finalDelay),\n        retryAfterMs,\n      },\n    );\n\n    // Call retry callback\n    this.retryConfig.onRetry?.(error, streamAttempt);\n\n    // Emit observer hook for retry attempt\n    await safeObserve(async () => {\n      if (this.hooks.observers?.onRetryAttempt) {\n        const subagentContext = getSubagentContextForNode(this.tree, llmNodeId);\n        const hookContext: ObserveRetryAttemptContext = {\n          iteration,\n          attemptNumber: streamAttempt,\n          retriesLeft: maxStreamAttempts - streamAttempt,\n          error,\n          retryAfterMs: retryAfterMs ?? undefined,\n          logger: this.logger,\n          subagentContext,\n        };\n        await this.hooks.observers.onRetryAttempt(hookContext);\n      }\n    }, this.logger);\n\n    // Wait before retrying\n    await this.sleep(finalDelay);\n  }\n}\n","import type { AbstractGadget } from \"./gadget.js\";\nimport { validateGadgetSchema } from \"./schema-validator.js\";\n\n// Type for gadget constructor\nexport type GadgetClass = new (...args: unknown[]) => AbstractGadget;\n\n// Type for gadget or gadget class\nexport type GadgetOrClass = AbstractGadget | GadgetClass;\n\nexport class GadgetRegistry {\n  private readonly gadgets = new Map<string, AbstractGadget>();\n\n  /**\n   * Creates a registry from an array of gadget classes or instances,\n   * or an object mapping names to gadgets.\n   *\n   * @param gadgets - Array of gadgets/classes or object with custom names\n   * @returns New GadgetRegistry with all gadgets registered\n   *\n   * @example\n   * ```typescript\n   * // From array of classes\n   * const registry = GadgetRegistry.from([Calculator, Weather]);\n   *\n   * // From array of instances\n   * const registry = GadgetRegistry.from([new Calculator(), new Weather()]);\n   *\n   * // From object with custom names\n   * const registry = GadgetRegistry.from({\n   *   calc: Calculator,\n   *   weather: new Weather({ apiKey: \"...\" })\n   * });\n   * ```\n   */\n  static from(gadgets: GadgetOrClass[] | Record<string, GadgetOrClass>): GadgetRegistry {\n    const registry = new GadgetRegistry();\n\n    if (Array.isArray(gadgets)) {\n      // Array of gadgets or classes\n      registry.registerMany(gadgets);\n    } else {\n      // Object with custom names\n      for (const [name, gadget] of Object.entries(gadgets)) {\n        const instance = typeof gadget === \"function\" ? new gadget() : gadget;\n        registry.register(name, instance);\n      }\n    }\n\n    return registry;\n  }\n\n  /**\n   * Registers multiple gadgets at once from an array.\n   *\n   * @param gadgets - Array of gadget instances or classes\n   * @returns This registry for chaining\n   *\n   * @example\n   * ```typescript\n   * registry.registerMany([Calculator, Weather, Email]);\n   * registry.registerMany([new Calculator(), new Weather()]);\n   * ```\n   */\n  registerMany(gadgets: GadgetOrClass[]): this {\n    for (const gadget of gadgets) {\n      const instance = typeof gadget === \"function\" ? new gadget() : gadget;\n      this.registerByClass(instance);\n    }\n    return this;\n  }\n\n  // Register a gadget by name\n  register(name: string, gadget: AbstractGadget): void {\n    const normalizedName = name.toLowerCase();\n    if (this.gadgets.has(normalizedName)) {\n      throw new Error(`Gadget '${name}' is already registered`);\n    }\n\n    // Validate schema if present\n    if (gadget.parameterSchema) {\n      validateGadgetSchema(gadget.parameterSchema, name);\n    }\n\n    this.gadgets.set(normalizedName, gadget);\n  }\n\n  // Register a gadget using its name property or class name\n  registerByClass(gadget: AbstractGadget): void {\n    const name = gadget.name ?? gadget.constructor.name;\n    this.register(name, gadget);\n  }\n\n  // Get gadget by name (case-insensitive)\n  get(name: string): AbstractGadget | undefined {\n    return this.gadgets.get(name.toLowerCase());\n  }\n\n  // Check if gadget exists (case-insensitive)\n  has(name: string): boolean {\n    return this.gadgets.has(name.toLowerCase());\n  }\n\n  // Get all registered gadget names\n  getNames(): string[] {\n    return Array.from(this.gadgets.keys());\n  }\n\n  // Get all gadgets for instruction generation\n  getAll(): AbstractGadget[] {\n    return Array.from(this.gadgets.values());\n  }\n\n  // Unregister gadget (useful for testing, case-insensitive)\n  unregister(name: string): boolean {\n    return this.gadgets.delete(name.toLowerCase());\n  }\n\n  // Clear all gadgets (useful for testing)\n  clear(): void {\n    this.gadgets.clear();\n  }\n}\n","/**\n * Skill activation logic.\n *\n * Handles $ARGUMENTS substitution and !`command` shell preprocessing\n * to resolve skill instructions before injection into agent context.\n *\n * @module skills/activation\n */\n\nimport { execSync } from \"node:child_process\";\n\n/**\n * Substitute $ARGUMENTS and positional $0, $1, etc. in skill instructions.\n */\nexport function substituteArguments(instructions: string, args?: string): string {\n  if (!args) {\n    // Replace all argument placeholders with empty string.\n    // Order: indexed forms first, then bare $ARGUMENTS, then positional $N.\n    return instructions\n      .replace(/\\$ARGUMENTS\\[\\d+\\]/g, \"\")\n      .replace(/\\$ARGUMENTS/g, \"\")\n      .replace(/\\$\\d+/g, \"\");\n  }\n\n  const parts = splitArguments(args);\n\n  // Replace indexed forms first (more specific), then bare $ARGUMENTS\n  let result = instructions.replace(/\\$ARGUMENTS\\[(\\d+)\\]/g, (_match, index) => {\n    const i = Number.parseInt(index, 10);\n    return parts[i] ?? \"\";\n  });\n\n  result = result.replace(/\\$ARGUMENTS/g, args);\n\n  result = result.replace(/\\$(\\d+)/g, (_match, index) => {\n    const i = Number.parseInt(index, 10);\n    return parts[i] ?? \"\";\n  });\n\n  return result;\n}\n\n/**\n * Execute !`command` shell preprocessing directives in skill instructions.\n *\n * Commands enclosed in !`...` are executed synchronously and their stdout\n * replaces the directive. This happens before the LLM sees the instructions.\n */\nexport function preprocessShellCommands(\n  instructions: string,\n  options?: { cwd?: string; shell?: \"bash\" | \"powershell\"; timeoutMs?: number },\n): string {\n  const { cwd, shell = \"bash\", timeoutMs = 10_000 } = options ?? {};\n\n  return instructions.replace(/!`([^`]+)`/g, (_match, command: string) => {\n    try {\n      const output = execSync(command, {\n        cwd,\n        shell: shell === \"powershell\" ? \"powershell\" : \"/bin/bash\",\n        timeout: timeoutMs,\n        encoding: \"utf-8\",\n        stdio: [\"pipe\", \"pipe\", \"pipe\"],\n      });\n      return output.trim();\n    } catch (error: unknown) {\n      const msg = error instanceof Error ? error.message : String(error);\n      return `[Error executing \\`${command}\\`: ${msg}]`;\n    }\n  });\n}\n\n/**\n * Substitute ${VARIABLE} environment-style variables in skill instructions.\n *\n * Supported variables:\n * - ${CLAUDE_SKILL_DIR} / ${SKILL_DIR} - directory containing SKILL.md\n * - ${CLAUDE_SESSION_ID} / ${SESSION_ID} - current session ID (if provided)\n */\nexport function substituteVariables(\n  instructions: string,\n  variables: Record<string, string>,\n): string {\n  return instructions.replace(/\\$\\{(\\w+)\\}/g, (_match, varName: string) => {\n    return variables[varName] ?? \"\";\n  });\n}\n\n/**\n * Full activation pipeline: variables -> arguments -> shell preprocessing.\n */\nexport function resolveInstructions(\n  instructions: string,\n  options?: {\n    arguments?: string;\n    variables?: Record<string, string>;\n    cwd?: string;\n    shell?: \"bash\" | \"powershell\";\n    shellTimeoutMs?: number;\n    enableShellPreprocessing?: boolean;\n  },\n): string {\n  let resolved = instructions;\n\n  // Step 1: Variable substitution\n  if (options?.variables) {\n    resolved = substituteVariables(resolved, options.variables);\n  }\n\n  // Step 2: Argument substitution\n  resolved = substituteArguments(resolved, options?.arguments);\n\n  // Step 3: Shell preprocessing (opt-in, since it executes commands)\n  if (options?.enableShellPreprocessing !== false) {\n    resolved = preprocessShellCommands(resolved, {\n      cwd: options?.cwd,\n      shell: options?.shell,\n      timeoutMs: options?.shellTimeoutMs,\n    });\n  }\n\n  return resolved;\n}\n\n// ─── Helpers ─────────────────────────────────────────────────────────────────\n\n/**\n * Split argument string into positional parts, respecting quotes.\n */\nfunction splitArguments(args: string): string[] {\n  const parts: string[] = [];\n  let current = \"\";\n  let inQuote: string | null = null;\n\n  for (const char of args) {\n    if (inQuote) {\n      if (char === inQuote) {\n        inQuote = null;\n      } else {\n        current += char;\n      }\n    } else if (char === '\"' || char === \"'\") {\n      inQuote = char;\n    } else if (char === \" \" || char === \"\\t\") {\n      if (current) {\n        parts.push(current);\n        current = \"\";\n      }\n    } else {\n      current += char;\n    }\n  }\n\n  if (current) parts.push(current);\n  return parts;\n}\n","/**\n * LoadSkill meta-gadget — bridges the skill system into the gadget execution pipeline.\n *\n * When skills are registered with an agent, this gadget is auto-created and added\n * to the gadget registry. The LLM invokes it with an array of skill names; each\n * skill's resolved instructions are composed into a single multi-section result.\n *\n * This approach requires zero changes to the stream processor or agent loop.\n *\n * @module skills/load-skill-gadget\n */\n\nimport { z } from \"zod\";\nimport { createGadget } from \"../gadgets/create-gadget.js\";\nimport type { AbstractGadget } from \"../gadgets/gadget.js\";\nimport type { SkillRegistry } from \"./registry.js\";\n\n/** Name for the auto-generated LoadSkill gadget. */\nexport const LOAD_SKILL_GADGET_NAME = \"LoadSkill\";\n\n/**\n * Compose multiple resolved-instruction bodies into a single delimited string.\n *\n * Section format:\n *\n *   ==== <skill-name> ====\n *   <body>\n *\n *   ==== <next-skill> ====\n *   <body>\n *\n * Keeps the markers literal (no markdown) so they're unambiguous when the\n * agent grep-searches its own context, and so the LLM doesn't get confused\n * by adjacent skill bodies containing markdown headers of their own.\n */\nfunction composeSkillSections(sections: Array<{ name: string; body: string }>): string {\n  return sections.map(({ name, body }) => `==== ${name} ====\\n${body}`).join(\"\\n\\n\");\n}\n\n/**\n * Create the LoadSkill meta-gadget from a skill registry.\n *\n * The gadget's tool description includes a summary of all available skills, so\n * the LLM knows what skills exist and when to load them. Setting\n * `iterationBarrier: true` and `stickyResult: true` are the two declarative\n * flags every LoadSkill should carry:\n *\n *   - `iterationBarrier`: tells the consuming agent loop to skip every sibling\n *     tool call in the same iteration's batch. The next LLM iteration sees\n *     only the loaded skill bodies and re-plans from there.\n *   - `stickyResult`: tells the compaction layer to preserve the result past\n *     truncation, so the agent doesn't re-load the same skill ten turns later.\n */\nexport function createLoadSkillGadget(registry: SkillRegistry): AbstractGadget {\n  const summaries = registry.getMetadataSummaries();\n  const skillNames = registry.getModelInvocable().map((s) => s.name);\n\n  const description = [\n    \"Load one or more skill bodies into context. Pass `skills` as a JSON\",\n    \"array of skill-name strings — NOT a string of a JSON-encoded array.\",\n    'Right: `{\"skills\": [\"alpha\"]}` or `{\"skills\": [\"alpha\", \"beta\"]}`.',\n    'Wrong: `{\"skills\": \"[\\\\\"alpha\\\\\"]\"}` (the value is a string, not an array).',\n    \"**This gadget is an iteration barrier — no other gadgets in the same\",\n    \"tool batch will execute, so load every skill you know you'll need in\",\n    \"one shot.** The loaded bodies are sticky and survive context compaction.\",\n    \"\",\n    \"Available skills:\",\n    summaries,\n  ].join(\"\\n\");\n\n  // Concrete usage examples rendered alongside the schema in\n  // `getInstruction()`. Reference real skill names from the registry so the\n  // LLM sees a literal `{skills: [\"<actual name>\"]}` shape and doesn't\n  // hallucinate a stringified form. Always include the single-skill case;\n  // include the multi-skill case only when the registry has 2+ invocable\n  // skills (so the second example doesn't repeat the first verbatim).\n  const examples: Array<{\n    params: { skills: string[]; arguments?: string };\n    comment: string;\n  }> = [];\n  if (skillNames.length >= 1) {\n    examples.push({\n      params: { skills: [skillNames[0]] },\n      comment: \"Single-skill call — `skills` is still an array of length 1.\",\n    });\n  }\n  if (skillNames.length >= 2) {\n    examples.push({\n      params: { skills: [skillNames[0], skillNames[1]] },\n      comment: \"Multi-skill call — load several skills in one shot to avoid round-trips.\",\n    });\n  }\n\n  return createGadget({\n    name: LOAD_SKILL_GADGET_NAME,\n    description,\n    schema: z.object({\n      skills: z\n        .array(z.enum(skillNames as [string, ...string[]]))\n        .min(1)\n        .describe(\n          \"One or more skill names to load in this single call. Prefer loading \" +\n            \"everything you know you'll need at once — this gadget is an iteration \" +\n            \"barrier, so sibling tool calls in the same batch will not execute.\",\n        ),\n      arguments: z\n        .string()\n        .optional()\n        .describe(\n          \"Optional argument string substituted into each skill's $ARGUMENTS \" +\n            \"placeholders. Applies to every skill in the batch. To pass \" +\n            \"different arguments to different skills, issue separate LoadSkill calls.\",\n        ),\n    }),\n    stickyResult: true,\n    iterationBarrier: true,\n    examples,\n    execute: async ({ skills: skillNamesArg, arguments: args }) => {\n      const sections: Array<{ name: string; body: string }> = [];\n      for (const skillName of skillNamesArg) {\n        const skill = registry.get(skillName);\n        if (!skill) {\n          sections.push({\n            name: skillName,\n            body: `Unknown skill: \"${skillName}\". Available skills: ${skillNames.join(\", \")}`,\n          });\n          continue;\n        }\n        const activation = await skill.activate({\n          arguments: args,\n          cwd: process.cwd(),\n        });\n        sections.push({ name: skillName, body: activation.resolvedInstructions });\n      }\n      return composeSkillSections(sections);\n    },\n  });\n}\n","/**\n * SKILL.md parser for the Agent Skills open standard.\n *\n * Parses YAML frontmatter (between --- markers) and markdown body.\n * Scans skill directories for Tier 3 resources (scripts/, references/, assets/).\n *\n * @module skills/parser\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport yaml from \"js-yaml\";\nimport type { ParsedSkill, SkillMetadata, SkillResource, SkillSource } from \"./types.js\";\n\n/** Resource subdirectory categories. */\nconst RESOURCE_CATEGORIES = [\"scripts\", \"references\", \"assets\"] as const;\n\n/** Maximum allowed length for skill name. */\nconst MAX_NAME_LENGTH = 64;\n\n/** Maximum allowed length for skill description. */\nconst MAX_DESCRIPTION_LENGTH = 1024;\n\n/** Pattern for valid skill names: lowercase letters, numbers, hyphens. */\nconst NAME_PATTERN = /^[a-z0-9][a-z0-9-]*$/;\n\n/**\n * Parse YAML frontmatter from SKILL.md content.\n *\n * Extracts the YAML block between the first pair of `---` markers\n * and the remaining markdown body.\n */\nexport function parseFrontmatter(content: string): {\n  frontmatter: Record<string, unknown>;\n  body: string;\n} {\n  const trimmed = content.trimStart();\n  if (!trimmed.startsWith(\"---\")) {\n    return { frontmatter: {}, body: content };\n  }\n\n  // Find the closing ---\n  const endIndex = trimmed.indexOf(\"\\n---\", 3);\n  if (endIndex === -1) {\n    return { frontmatter: {}, body: content };\n  }\n\n  const yamlBlock = trimmed.slice(3, endIndex).trim();\n  const body = trimmed.slice(endIndex + 4).trim();\n\n  const parsed = yaml.load(yamlBlock);\n  const frontmatter =\n    typeof parsed === \"object\" && parsed !== null ? (parsed as Record<string, unknown>) : {};\n\n  return { frontmatter, body };\n}\n\n/**\n * Convert raw frontmatter to validated SkillMetadata.\n *\n * Maps kebab-case YAML keys to camelCase TypeScript properties.\n * Falls back to directory name for missing name field.\n */\nexport function parseMetadata(\n  frontmatter: Record<string, unknown>,\n  fallbackName?: string,\n): SkillMetadata {\n  const name = parseString(frontmatter.name) ?? fallbackName ?? \"unnamed-skill\";\n  const description = parseString(frontmatter.description) ?? \"\";\n\n  return {\n    name,\n    description,\n    argumentHint: parseString(frontmatter[\"argument-hint\"]),\n    allowedTools: parseStringArray(frontmatter[\"allowed-tools\"]),\n    model: parseString(frontmatter.model),\n    context: parseContext(frontmatter.context),\n    agent: parseString(frontmatter.agent),\n    paths: parseStringArray(frontmatter.paths),\n    gadgets: parseStringArray(frontmatter.gadgets),\n    disableModelInvocation: parseBool(frontmatter[\"disable-model-invocation\"]),\n    userInvocable: parseBool(frontmatter[\"user-invocable\"]),\n    shell: parseShell(frontmatter.shell),\n    version: parseString(frontmatter.version),\n  };\n}\n\n/**\n * Scan a skill directory for Tier 3 resource files.\n */\nexport function scanResources(skillDir: string): SkillResource[] {\n  const resources: SkillResource[] = [];\n\n  for (const category of RESOURCE_CATEGORIES) {\n    const categoryDir = path.join(skillDir, category);\n    if (!fs.existsSync(categoryDir)) continue;\n\n    const stat = fs.statSync(categoryDir);\n    if (!stat.isDirectory()) continue;\n\n    for (const file of walkDirectory(categoryDir)) {\n      resources.push({\n        relativePath: path.relative(skillDir, file),\n        absolutePath: file,\n        category,\n      });\n    }\n  }\n\n  return resources;\n}\n\n/**\n * Parse a SKILL.md file from disk.\n *\n * This performs Tier 1 parsing (metadata) and optionally Tier 2 (instructions).\n * Resources are discovered but not loaded.\n *\n * @param skillMdPath - Absolute path to SKILL.md\n * @param source - Where this skill was discovered from\n * @param loadInstructions - Whether to load Tier 2 body (default: false for lazy loading)\n */\nexport function parseSkillFile(\n  skillMdPath: string,\n  source: SkillSource,\n  loadInstructions = false,\n): ParsedSkill {\n  const content = fs.readFileSync(skillMdPath, \"utf-8\");\n  return parseSkillContent(content, skillMdPath, source, loadInstructions);\n}\n\n/**\n * Parse SKILL.md content from a string.\n *\n * Useful for testing without filesystem access.\n */\nexport function parseSkillContent(\n  content: string,\n  sourcePath: string,\n  source: SkillSource,\n  loadInstructions = false,\n): ParsedSkill {\n  const sourceDir = path.dirname(sourcePath);\n  const fallbackName = path.basename(sourceDir);\n\n  const { frontmatter, body } = parseFrontmatter(content);\n  const metadata = parseMetadata(frontmatter, fallbackName);\n  const resources = fs.existsSync(sourceDir) ? scanResources(sourceDir) : [];\n\n  return {\n    metadata,\n    instructions: loadInstructions ? body : null,\n    resources,\n    sourcePath,\n    sourceDir,\n    source,\n  };\n}\n\n/**\n * Validate skill metadata.\n * Returns an array of validation issues (empty if valid).\n */\nexport function validateMetadata(metadata: SkillMetadata): string[] {\n  const issues: string[] = [];\n\n  if (!metadata.name) {\n    issues.push(\"Skill name is required\");\n  } else {\n    if (metadata.name.length > MAX_NAME_LENGTH) {\n      issues.push(`Skill name exceeds ${MAX_NAME_LENGTH} characters`);\n    }\n    if (!NAME_PATTERN.test(metadata.name)) {\n      issues.push(\n        \"Skill name must contain only lowercase letters, numbers, and hyphens, \" +\n          \"and must start with a letter or number\",\n      );\n    }\n  }\n\n  if (!metadata.description) {\n    issues.push(\"Skill description is required\");\n  } else if (metadata.description.length > MAX_DESCRIPTION_LENGTH) {\n    issues.push(`Skill description exceeds ${MAX_DESCRIPTION_LENGTH} characters`);\n  }\n\n  if (metadata.context && metadata.context !== \"fork\" && metadata.context !== \"inline\") {\n    issues.push('Skill context must be \"fork\" or \"inline\"');\n  }\n\n  return issues;\n}\n\n// ─── Helpers ─────────────────────────────────────────────────────────────────\n\n/** Safely extract a string value, rejecting objects/arrays. */\nfunction parseString(value: unknown): string | undefined {\n  if (value == null) return undefined;\n  if (typeof value === \"string\") return value;\n  if (typeof value === \"number\" || typeof value === \"boolean\") return String(value);\n  return undefined; // Reject objects, arrays, etc. instead of \"[object Object]\"\n}\n\nfunction parseStringArray(value: unknown): string[] | undefined {\n  if (value == null) return undefined;\n  if (Array.isArray(value)) {\n    return value.filter((v) => typeof v === \"string\" || typeof v === \"number\").map(String);\n  }\n  if (typeof value === \"string\") return [value];\n  return undefined;\n}\n\nfunction parseContext(value: unknown): \"fork\" | \"inline\" | undefined {\n  if (value === \"fork\" || value === \"inline\") return value;\n  return undefined;\n}\n\nfunction parseShell(value: unknown): \"bash\" | \"powershell\" | undefined {\n  if (value === \"bash\" || value === \"powershell\") return value;\n  return undefined;\n}\n\nfunction parseBool(value: unknown): boolean | undefined {\n  if (value === true || value === false) return value;\n  if (value === \"true\") return true;\n  if (value === \"false\") return false;\n  return undefined;\n}\n\n/** Recursively walk a directory and yield file paths. */\nfunction* walkDirectory(dir: string): Generator<string> {\n  const entries = fs.readdirSync(dir, { withFileTypes: true });\n  for (const entry of entries) {\n    const fullPath = path.join(dir, entry.name);\n    if (entry.isDirectory()) {\n      yield* walkDirectory(fullPath);\n    } else if (entry.isFile()) {\n      yield fullPath;\n    }\n  }\n}\n","/**\n * SkillRegistry — manages skill discovery, lookup, and metadata summaries.\n *\n * Parallel to GadgetRegistry but with different semantics: skills are not\n * executable tools registered with the LLM directly. They are available\n * for activation by the agent or user, surfaced via metadata summaries.\n *\n * @module skills/registry\n */\n\nimport { minimatch } from \"minimatch\";\nimport type { Skill } from \"./skill.js\";\n\n/** Default character budget for metadata summaries (~1% of 200K context). */\nconst DEFAULT_CHAR_BUDGET = 8_000;\n\n/** Maximum description length in summaries to keep them concise. */\nconst SUMMARY_DESCRIPTION_LIMIT = 250;\n\nexport class SkillRegistry {\n  private readonly skills = new Map<string, Skill>();\n\n  /**\n   * Register a skill. Overwrites any existing skill with the same name.\n   *\n   * Unlike GadgetRegistry (which throws on duplicates), SkillRegistry allows\n   * overwriting because skills are loaded from multiple sources with intentional\n   * priority ordering (project > user > default).\n   */\n  register(skill: Skill): void {\n    this.skills.set(skill.name.toLowerCase(), skill);\n  }\n\n  /** Register multiple skills. */\n  registerMany(skills: Skill[]): void {\n    for (const skill of skills) {\n      this.register(skill);\n    }\n  }\n\n  /** Remove a skill by name (case-insensitive). Returns true if removed. */\n  remove(name: string): boolean {\n    return this.skills.delete(name.toLowerCase());\n  }\n\n  /** Remove all registered skills. */\n  clear(): void {\n    this.skills.clear();\n  }\n\n  /** Get a skill by name (case-insensitive). */\n  get(name: string): Skill | undefined {\n    return this.skills.get(name.toLowerCase());\n  }\n\n  /** Check if a skill exists by name (case-insensitive). */\n  has(name: string): boolean {\n    return this.skills.has(name.toLowerCase());\n  }\n\n  /** Get all registered skills. */\n  getAll(): Skill[] {\n    return [...this.skills.values()];\n  }\n\n  /** Get all skill names. */\n  getNames(): string[] {\n    return [...this.skills.keys()];\n  }\n\n  /** Number of registered skills. */\n  get size(): number {\n    return this.skills.size;\n  }\n\n  /**\n   * Get skills that are visible to the LLM for auto-triggering.\n   * Excludes skills with disableModelInvocation: true.\n   */\n  getModelInvocable(): Skill[] {\n    return this.getAll().filter((s) => s.isModelInvocable);\n  }\n\n  /**\n   * Get skills that the user can invoke via /skill-name.\n   * Excludes skills with userInvocable: false.\n   */\n  getUserInvocable(): Skill[] {\n    return this.getAll().filter((s) => s.isUserInvocable);\n  }\n\n  /**\n   * Generate metadata summaries for system prompt injection (Tier 1).\n   *\n   * Each skill contributes a one-line summary: \"name — description\".\n   * Output is truncated to fit the character budget.\n   *\n   * @param charBudget - Maximum characters for all summaries combined.\n   */\n  getMetadataSummaries(charBudget = DEFAULT_CHAR_BUDGET): string {\n    const invocable = this.getModelInvocable();\n    if (invocable.length === 0) return \"\";\n\n    const lines: string[] = [];\n    let totalChars = 0;\n\n    for (const skill of invocable) {\n      const desc =\n        skill.description.length > SUMMARY_DESCRIPTION_LIMIT\n          ? `${skill.description.slice(0, SUMMARY_DESCRIPTION_LIMIT - 3)}...`\n          : skill.description;\n\n      const line = `- ${skill.name}: ${desc}`;\n\n      if (totalChars + line.length > charBudget) break;\n\n      lines.push(line);\n      totalChars += line.length + 1; // +1 for newline\n    }\n\n    return lines.join(\"\\n\");\n  }\n\n  /**\n   * Find skills whose `paths` patterns match a given file path.\n   * Used for auto-activation when the user is working on specific files.\n   */\n  findByFilePath(filePath: string): Skill[] {\n    return this.getModelInvocable().filter((skill) => {\n      const patterns = skill.metadata.paths;\n      if (!patterns || patterns.length === 0) return false;\n      return patterns.some((pattern) => minimatch(filePath, pattern));\n    });\n  }\n\n  /**\n   * Merge another registry into this one.\n   * Skills from the other registry overwrite existing skills with the same name.\n   */\n  merge(other: SkillRegistry): void {\n    for (const skill of other.getAll()) {\n      this.register(skill);\n    }\n  }\n\n  /** Create a registry from an array of skills. */\n  static from(skills: Skill[]): SkillRegistry {\n    const registry = new SkillRegistry();\n    registry.registerMany(skills);\n    return registry;\n  }\n}\n","/**\n * Skill class with lazy-loading progressive disclosure.\n *\n * Tier 1 (metadata) is always available after construction.\n * Tier 2 (instructions) and Tier 3 (resources) are loaded on demand.\n *\n * @module skills/skill\n */\n\nimport fs from \"node:fs/promises\";\nimport { resolveInstructions } from \"./activation.js\";\nimport { parseFrontmatter, parseSkillContent } from \"./parser.js\";\nimport type {\n  ParsedSkill,\n  SkillActivation,\n  SkillActivationOptions,\n  SkillMetadata,\n  SkillResource,\n  SkillSource,\n} from \"./types.js\";\n\nexport class Skill {\n  readonly metadata: SkillMetadata;\n  readonly sourcePath: string;\n  readonly sourceDir: string;\n  readonly source: SkillSource;\n\n  private _instructions: string | null;\n  private _resources: SkillResource[];\n  private readonly _resourceCache = new Map<string, string>();\n  private readonly _resourceLoading = new Map<string, Promise<string>>();\n\n  constructor(parsed: ParsedSkill) {\n    this.metadata = parsed.metadata;\n    this.sourcePath = parsed.sourcePath;\n    this.sourceDir = parsed.sourceDir;\n    this.source = parsed.source;\n    this._instructions = parsed.instructions;\n    this._resources = parsed.resources;\n  }\n\n  /** Skill name for registry lookup. */\n  get name(): string {\n    return this.metadata.name;\n  }\n\n  /** Skill description for LLM matching. */\n  get description(): string {\n    return this.metadata.description;\n  }\n\n  /** Whether the LLM can auto-trigger this skill. */\n  get isModelInvocable(): boolean {\n    return this.metadata.disableModelInvocation !== true;\n  }\n\n  /** Whether the user can invoke this skill via /skill-name. */\n  get isUserInvocable(): boolean {\n    return this.metadata.userInvocable !== false;\n  }\n\n  /**\n   * Load and cache Tier 2 instructions.\n   * If instructions were loaded during parsing, returns the cached value.\n   */\n  async getInstructions(): Promise<string> {\n    if (this._instructions !== null) return this._instructions;\n\n    const content = await fs.readFile(this.sourcePath, \"utf-8\");\n    const { body } = parseFrontmatter(content);\n    this._instructions = body;\n    return body;\n  }\n\n  /**\n   * List Tier 3 resources.\n   * Resources are discovered at parse time but content is loaded on demand.\n   */\n  getResources(): SkillResource[] {\n    return this._resources;\n  }\n\n  /**\n   * Load a specific Tier 3 resource by relative path.\n   * Results are cached for the lifetime of this Skill instance.\n   * Concurrent calls for the same resource share a single read.\n   */\n  async getResource(relativePath: string): Promise<string> {\n    if (relativePath.includes(\"..\")) {\n      throw new Error(`Invalid resource path (path traversal): ${relativePath}`);\n    }\n\n    const cached = this._resourceCache.get(relativePath);\n    if (cached !== undefined) return cached;\n\n    // Deduplicate concurrent loads for the same resource\n    const existing = this._resourceLoading.get(relativePath);\n    if (existing) return existing;\n\n    const resource = this._resources.find((r) => r.relativePath === relativePath);\n    if (!resource) {\n      throw new Error(`Resource not found: ${relativePath} in skill ${this.name}`);\n    }\n\n    const loadPromise = fs.readFile(resource.absolutePath, \"utf-8\").then(\n      (content) => {\n        this._resourceCache.set(relativePath, content);\n        this._resourceLoading.delete(relativePath);\n        return content;\n      },\n      (error) => {\n        this._resourceLoading.delete(relativePath);\n        throw new Error(\n          `Failed to load resource ${relativePath} in skill ${this.name}: ${error instanceof Error ? error.message : String(error)}`,\n        );\n      },\n    );\n\n    this._resourceLoading.set(relativePath, loadPromise);\n    return loadPromise;\n  }\n\n  /**\n   * Activate this skill with optional arguments.\n   *\n   * Performs:\n   * 1. Variable substitution (${SKILL_DIR}, etc.)\n   * 2. Argument substitution ($ARGUMENTS, $0, $1)\n   * 3. Shell preprocessing (!`command`)\n   * 4. Resource loading (if eagerResources is true)\n   */\n  async activate(options?: SkillActivationOptions): Promise<SkillActivation> {\n    const instructions = await this.getInstructions();\n\n    const resolvedInstructions = resolveInstructions(instructions, {\n      arguments: options?.arguments,\n      variables: {\n        SKILL_DIR: this.sourceDir,\n        CLAUDE_SKILL_DIR: this.sourceDir,\n      },\n      cwd: options?.cwd ?? this.sourceDir,\n      shell: this.metadata.shell,\n      enableShellPreprocessing: options?.enableShellPreprocessing,\n      shellTimeoutMs: options?.shellTimeoutMs,\n    });\n\n    const loadedResources = new Map<string, string>();\n    if (options?.eagerResources) {\n      for (const resource of this._resources) {\n        const content = await this.getResource(resource.relativePath);\n        loadedResources.set(resource.relativePath, content);\n      }\n    }\n\n    return {\n      skillName: this.name,\n      resolvedInstructions,\n      gadgets: [], // Gadgets are resolved by the CLI layer\n      loadedResources,\n    };\n  }\n\n  /**\n   * Create a Skill from a SKILL.md content string.\n   * Useful for testing or dynamic skill creation.\n   */\n  static fromContent(\n    content: string,\n    sourcePath: string,\n    source: SkillSource = { type: \"directory\", path: sourcePath },\n  ): Skill {\n    const parsed = parseSkillContent(content, sourcePath, source, true);\n    return new Skill(parsed);\n  }\n}\n","/**\n * Filesystem-based skill discovery and loading.\n *\n * Scans directories for subdirectories containing SKILL.md files.\n * Supports standard discovery locations and custom directories.\n *\n * @module skills/loader\n */\n\nimport fs from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { parseSkillFile } from \"./parser.js\";\nimport { SkillRegistry } from \"./registry.js\";\nimport { Skill } from \"./skill.js\";\nimport type { SkillSource } from \"./types.js\";\n\n/** Standard skill directory name within project or user config. */\nconst SKILLS_DIR_NAME = \"skills\";\n\n/** Project config directory name. */\nconst CONFIG_DIR_NAME = \".llmist\";\n\n/**\n * Load skills from a directory.\n *\n * Recursively scans for subdirectories containing a SKILL.md file.\n * Each such directory is treated as a single skill.\n *\n * @param dir - Directory to scan\n * @param source - Origin for all discovered skills\n */\nexport function loadSkillsFromDirectory(\n  dir: string,\n  source: SkillSource,\n  onWarning?: (msg: string) => void,\n): Skill[] {\n  if (!fs.existsSync(dir)) return [];\n\n  const stat = fs.statSync(dir);\n  if (!stat.isDirectory()) return [];\n\n  const skills: Skill[] = [];\n  scanForSkills(dir, source, skills, onWarning);\n  return skills;\n}\n\n/**\n * Discover skills from standard locations.\n *\n * Discovery order (later sources overwrite earlier on name collision):\n * 1. User skills: ~/.llmist/skills/\n * 2. Project skills: <projectDir>/.llmist/skills/\n * 3. Additional directories (explicit)\n */\nexport function discoverSkills(options?: {\n  projectDir?: string;\n  userDir?: string;\n  additionalDirs?: string[];\n}): SkillRegistry {\n  const registry = new SkillRegistry();\n\n  // 1. User-level skills\n  const userSkillsDir =\n    options?.userDir ?? path.join(os.homedir(), CONFIG_DIR_NAME, SKILLS_DIR_NAME);\n  const userSkills = loadSkillsFromDirectory(userSkillsDir, {\n    type: \"user\",\n    path: userSkillsDir,\n  });\n  registry.registerMany(userSkills);\n\n  // 2. Project-level skills (override user-level)\n  if (options?.projectDir) {\n    const projectSkillsDir = path.join(options.projectDir, CONFIG_DIR_NAME, SKILLS_DIR_NAME);\n    const projectSkills = loadSkillsFromDirectory(projectSkillsDir, {\n      type: \"project\",\n      path: projectSkillsDir,\n    });\n    registry.registerMany(projectSkills);\n  }\n\n  // 3. Additional directories (override both)\n  if (options?.additionalDirs) {\n    for (const dir of options.additionalDirs) {\n      const resolvedDir = dir.startsWith(\"~\") ? path.join(os.homedir(), dir.slice(1)) : dir;\n      const skills = loadSkillsFromDirectory(resolvedDir, {\n        type: \"directory\",\n        path: resolvedDir,\n      });\n      registry.registerMany(skills);\n    }\n  }\n\n  return registry;\n}\n\n// ─── Helpers ─────────────────────────────────────────────────────────────────\n\n/**\n * Recursively scan a directory for SKILL.md files.\n */\nfunction scanForSkills(\n  dir: string,\n  source: SkillSource,\n  results: Skill[],\n  onWarning?: (msg: string) => void,\n): void {\n  let entries: fs.Dirent[];\n  try {\n    entries = fs.readdirSync(dir, { withFileTypes: true });\n  } catch (error: unknown) {\n    onWarning?.(\n      `Cannot read skill directory ${dir}: ${error instanceof Error ? error.message : String(error)}`,\n    );\n    return;\n  }\n\n  // Check if this directory itself contains a SKILL.md\n  const skillMdPath = path.join(dir, \"SKILL.md\");\n  if (fs.existsSync(skillMdPath)) {\n    try {\n      const parsed = parseSkillFile(skillMdPath, source, false);\n      results.push(new Skill(parsed));\n    } catch (error: unknown) {\n      onWarning?.(\n        `Failed to parse ${skillMdPath}: ${error instanceof Error ? error.message : String(error)}`,\n      );\n    }\n    return;\n  }\n\n  for (const entry of entries) {\n    if (entry.isDirectory() && !entry.name.startsWith(\".\")) {\n      scanForSkills(path.join(dir, entry.name), source, results, onWarning);\n    }\n  }\n}\n","import { GADGET_ARG_PREFIX, GADGET_END_PREFIX, GADGET_START_PREFIX } from \"../core/constants.js\";\nimport type { ContentPart, ImageMimeType } from \"../core/input-content.js\";\nimport { detectImageMimeType, text, toBase64 } from \"../core/input-content.js\";\nimport type { LLMMessage, MessageContent } from \"../core/messages.js\";\nimport type { HistoryMessage } from \"./builder-types.js\";\n\n/**\n * Format a complete gadget call block.\n */\nexport function formatGadgetCall(\n  gadgetName: string,\n  invocationId: string,\n  parameters: Record<string, unknown>,\n  prefixes?: {\n    start?: string;\n    end?: string;\n    arg?: string;\n  },\n): string {\n  const startPrefix = prefixes?.start ?? GADGET_START_PREFIX;\n  const endPrefix = prefixes?.end ?? GADGET_END_PREFIX;\n  const argPrefix = prefixes?.arg ?? GADGET_ARG_PREFIX;\n\n  const paramStr = formatBlockParameters(parameters, \"\", argPrefix);\n\n  return `${startPrefix}${gadgetName}:${invocationId}\\n${paramStr}\\n${endPrefix}`;\n}\n\n/**\n * Format parameters as block format with JSON Pointer paths.\n * Used internally by AgentBuilder and SystemMessageBuilder.\n */\nexport function formatBlockParameters(\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      value.forEach((item, index) => {\n        const itemPath = `${fullPath}/${index}`;\n        if (typeof item === \"object\" && item !== null) {\n          lines.push(formatBlockParameters(item as Record<string, unknown>, itemPath, argPrefix));\n        } else {\n          lines.push(`${argPrefix}${itemPath}`);\n          lines.push(String(item));\n        }\n      });\n    } else if (typeof value === \"object\" && value !== null) {\n      lines.push(formatBlockParameters(value as Record<string, unknown>, fullPath, argPrefix));\n    } else {\n      lines.push(`${argPrefix}${fullPath}`);\n      lines.push(String(value));\n    }\n  }\n\n  return lines.join(\"\\n\");\n}\n\n/**\n * Normalize HistoryMessage objects into standard LLMMessage format.\n */\nexport function normalizeHistory(messages: HistoryMessage[]): Array<{\n  role: \"system\" | \"user\" | \"assistant\";\n  content: MessageContent;\n}> {\n  return messages.map((msg) => {\n    if (\"user\" in msg) {\n      return { role: \"user\", content: msg.user };\n    }\n    if (\"assistant\" in msg) {\n      return { role: \"assistant\", content: msg.assistant };\n    }\n    if (\"system\" in msg) {\n      return { role: \"system\", content: msg.system };\n    }\n    throw new Error(\"Invalid history message format\");\n  });\n}\n\n/**\n * Build multimodal content from image data.\n */\nexport function buildMultimodalContent(\n  textPrompt: string,\n  imageData: Buffer | Uint8Array | string,\n  mimeType?: ImageMimeType,\n): ContentPart[] {\n  const imageBuffer = 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  return [\n    text(textPrompt),\n    {\n      type: \"image\",\n      source: {\n        type: \"base64\",\n        mediaType: detectedMime,\n        data: toBase64(imageBuffer),\n      },\n    },\n  ];\n}\n\n/**\n * Extract messages from a previous agent's conversation.\n */\nexport function extractMessagesFromAgent(agent: {\n  getConversation: () => { getConversationHistory: () => LLMMessage[] };\n}): Array<{ role: \"system\" | \"user\" | \"assistant\"; content: MessageContent }> {\n  const history = agent.getConversation().getConversationHistory();\n  return history\n    .filter((msg) => msg.role === \"user\" || msg.role === \"assistant\")\n    .map((msg) => ({\n      role: msg.role as \"user\" | \"assistant\",\n      content: msg.content,\n    }));\n}\n","/**\n * File-based logging for LLM requests and responses.\n *\n * Provides hooks to write raw LLM requests and responses to files for debugging,\n * auditing, and analysis. Supports both programmatic configuration and\n * zero-code activation via environment variables.\n *\n * ## Programmatic Usage\n *\n * ```typescript\n * import { LLMist, HookPresets } from 'llmist';\n *\n * const agent = LLMist.createAgent()\n *   .withHooks(HookPresets.fileLogging({\n *     directory: './logs/session-001'\n *   }))\n *   .ask(\"Hello\");\n *\n * // Creates: ./logs/session-001/0001.request\n * //          ./logs/session-001/0001.response\n * ```\n *\n * ## Environment Variable\n *\n * Set `LLMIST_LOG_RAW_DIRECTORY` to enable logging without code changes:\n *\n * ```bash\n * export LLMIST_LOG_RAW_DIRECTORY=\"/tmp/llm-debug\"\n * node my-app.js\n * ```\n */\n\nimport { mkdir, writeFile } from \"node:fs/promises\";\nimport { join, resolve } from \"node:path\";\n\nimport { extractMessageText, type LLMMessage } from \"../core/messages.js\";\nimport type { AgentHooks, SubagentContext } from \"./hooks.js\";\n\n// ============================================================================\n// FILE LOGGING STATE MANAGEMENT\n// ============================================================================\n\n/**\n * State container for file logging session.\n * Encapsulates all mutable state to enable session isolation and proper\n * handling of concurrent subagents.\n *\n * @remarks\n * Using a state object instead of module-level globals provides:\n * - **Session isolation**: Multiple agent sessions don't interfere with each other\n * - **Testability**: Tests can inject fresh state without needing to reset globals\n * - **Concurrent subagent support**: Context-based keys prevent race conditions\n */\nexport interface FileLoggingState {\n  /** Counter per directory path (normalized) */\n  readonly counters: Map<string, number>;\n\n  /**\n   * Subagent context key -> assigned directory path.\n   * Key format: `${parentDir}:${parentGadgetInvocationId}`\n   */\n  readonly subagentDirectories: Map<string, string>;\n\n  /**\n   * Context key -> active directory for that execution context.\n   * Key format: `${parentGadgetInvocationId}:${depth}` (or \"root:0\" for main agent)\n   *\n   * This replaces the previous depth-only keying which caused race conditions\n   * when multiple subagents at the same depth ran concurrently.\n   */\n  readonly activeDirectoryByContext: Map<string, string>;\n}\n\n/**\n * Creates a fresh file logging state container.\n *\n * Use this to create isolated state for testing or when running multiple\n * independent agent sessions that shouldn't share counters.\n *\n * @example\n * ```typescript\n * // For testing with isolated state:\n * const state = createFileLoggingState();\n * const hooks = createFileLoggingHooks({ directory: './logs' }, state);\n *\n * // For production (uses default shared state):\n * const hooks = createFileLoggingHooks({ directory: './logs' });\n * ```\n */\nexport function createFileLoggingState(): FileLoggingState {\n  return {\n    counters: new Map(),\n    subagentDirectories: new Map(),\n    activeDirectoryByContext: new Map(),\n  };\n}\n\n/**\n * Default global state for backward compatibility.\n * Created lazily on first use.\n */\nlet defaultState: FileLoggingState | undefined;\n\n/**\n * Gets the default global state, creating it if needed.\n */\nfunction getDefaultState(): FileLoggingState {\n  if (!defaultState) {\n    defaultState = createFileLoggingState();\n  }\n  return defaultState;\n}\n\n/**\n * Gets the next counter for a directory within a state container.\n */\nfunction getNextCounter(state: FileLoggingState, directory: string): number {\n  const current = state.counters.get(directory) ?? 0;\n  const next = current + 1;\n  state.counters.set(directory, next);\n  return next;\n}\n\n/**\n * Creates a unique key for tracking active directories per execution context.\n * Uses parent invocation ID + depth to correctly handle concurrent subagents.\n *\n * @param subagentContext - Subagent context (undefined for main agent)\n * @returns Context key string\n */\nfunction getContextKey(subagentContext?: SubagentContext): string {\n  if (!subagentContext) return \"root:0\";\n  return `${subagentContext.parentGadgetInvocationId}:${subagentContext.depth}`;\n}\n\n/**\n * Resets the default global state. For testing only.\n * @internal\n */\nexport function resetFileLoggingState(): void {\n  defaultState = undefined;\n}\n\n/**\n * Finds the parent directory key for a nested subagent.\n *\n * For depth > 1, we need to find which depth-(N-1) directory this subagent\n * should nest under. Since SubagentContext only gives us parentGadgetInvocationId\n * (the gadget that spawned us), we search for an active directory at the parent depth.\n *\n * @param state - The file logging state\n * @param currentDepth - The current subagent depth\n * @returns The context key of the parent directory, or \"root:0\" if not found\n */\nfunction findParentContextKey(state: FileLoggingState, currentDepth: number): string {\n  const parentDepth = currentDepth - 1;\n\n  // For depth 1, parent is always the root\n  if (parentDepth === 0) return \"root:0\";\n\n  // For deeper levels, find any active entry at parent depth\n  // This works because subagents spawn sequentially within their parent context\n  for (const [key, _path] of state.activeDirectoryByContext) {\n    if (key.endsWith(`:${parentDepth}`)) {\n      return key;\n    }\n  }\n\n  return \"root:0\";\n}\n\n/**\n * Resolves the logging directory for a given context.\n * - Main agent: uses base directory directly\n * - Subagent: creates/reuses a numbered subdirectory inside parent's directory\n *\n * Uses context-based tracking (parentInvocationId:depth) to determine where\n * nested subagents should go. This approach handles concurrent subagents at\n * the same depth correctly, unlike depth-only keying.\n *\n * @param state - The file logging state container\n * @param baseDirectory - The root directory for logging (normalized)\n * @param counterPadding - Number of digits for zero-padding\n * @param subagentContext - Subagent context if this is a subagent call\n * @returns The resolved directory path for this agent/subagent\n */\nfunction resolveLoggingDirectory(\n  state: FileLoggingState,\n  baseDirectory: string,\n  counterPadding: number,\n  subagentContext?: SubagentContext,\n): string {\n  const contextKey = getContextKey(subagentContext);\n\n  if (!subagentContext) {\n    // Main agent - register as root context\n    state.activeDirectoryByContext.set(contextKey, baseDirectory);\n    return baseDirectory;\n  }\n\n  const { parentGadgetInvocationId, depth } = subagentContext;\n\n  // Find the parent directory using context-based lookup\n  const parentContextKey = findParentContextKey(state, depth);\n  const parentDir = state.activeDirectoryByContext.get(parentContextKey) ?? baseDirectory;\n\n  // Check if we already assigned a directory for this specific subagent invocation\n  const subagentKey = `${parentDir}:${parentGadgetInvocationId}`;\n  let fullPath = state.subagentDirectories.get(subagentKey);\n\n  if (!fullPath) {\n    // First call from this subagent - assign a chronological number\n    const chronoNumber = getNextCounter(state, parentDir);\n    const subdirName = `${formatCallNumber(chronoNumber, counterPadding)}-${parentGadgetInvocationId}`;\n    fullPath = join(parentDir, subdirName);\n    state.subagentDirectories.set(subagentKey, fullPath);\n  }\n\n  // Register this as the active directory for this execution context\n  state.activeDirectoryByContext.set(contextKey, fullPath);\n\n  return fullPath;\n}\n\n/**\n * Environment variable name for zero-code activation.\n */\nexport const ENV_LOG_RAW_DIRECTORY = \"LLMIST_LOG_RAW_DIRECTORY\";\n\n/**\n * Options for configuring file-based LLM logging.\n */\nexport interface FileLoggingOptions {\n  /**\n   * Directory where log files will be written.\n   * Will be created recursively if it doesn't exist.\n   */\n  directory: string;\n\n  /**\n   * Starting counter for file numbering. Default: 1\n   */\n  startingCounter?: number;\n\n  /**\n   * Number of digits for zero-padded file numbers. Default: 4\n   * Example: 4 produces \"0001\", \"0042\", etc.\n   */\n  counterPadding?: number;\n\n  /**\n   * Skip logging for subagent calls. Default: true\n   * When true, only main agent calls are logged.\n   */\n  skipSubagents?: boolean;\n\n  /**\n   * Custom formatter for request content.\n   * By default, uses formatLlmRequest() which produces human-readable output.\n   */\n  formatRequest?: (messages: LLMMessage[]) => string;\n\n  /**\n   * Callback invoked after each file is written.\n   * Useful for tracking, metrics, or UI updates.\n   */\n  onFileWritten?: (info: FileWrittenInfo) => void;\n}\n\n/**\n * Information about a written log file.\n */\nexport interface FileWrittenInfo {\n  /** Full path to the written file */\n  filePath: string;\n\n  /** Type of log file */\n  type: \"request\" | \"response\";\n\n  /** LLM call number (1-indexed) within the current directory */\n  callNumber: number;\n\n  /** Length of the written content in characters */\n  contentLength: number;\n\n  /** Gadget invocation ID that spawned this subagent (undefined for main agent) */\n  parentGadgetInvocationId?: string;\n\n  /** Subagent depth (undefined for main agent) */\n  depth?: number;\n}\n\n/**\n * Formats LLM messages as plain text for debugging.\n *\n * Each message is formatted with a header showing the role (USER, ASSISTANT, SYSTEM)\n * followed by the message content. Multimodal content is converted to text.\n *\n * @param messages - Array of LLM messages to format\n * @returns Formatted string with all messages\n *\n * @example\n * ```typescript\n * const formatted = formatLlmRequest([\n *   { role: \"system\", content: \"You are a helpful assistant.\" },\n *   { role: \"user\", content: \"Hello!\" }\n * ]);\n * // Output:\n * // === SYSTEM ===\n * // You are a helpful assistant.\n * //\n * // === USER ===\n * // Hello!\n * ```\n */\nexport function formatLlmRequest(messages: LLMMessage[]): string {\n  const lines: string[] = [];\n  for (const msg of messages) {\n    lines.push(`=== ${msg.role.toUpperCase()} ===`);\n    // Handle undefined content (for incomplete/malformed messages)\n    lines.push(msg.content ? extractMessageText(msg.content) : \"\");\n    lines.push(\"\");\n  }\n  return lines.join(\"\\n\");\n}\n\n/**\n * Formats a call number as a zero-padded string.\n *\n * @param n - The number to format\n * @param padding - Number of digits (default: 4)\n * @returns Zero-padded string (e.g., 1 → \"0001\", 42 → \"0042\")\n *\n * @example\n * ```typescript\n * formatCallNumber(1);    // \"0001\"\n * formatCallNumber(42);   // \"0042\"\n * formatCallNumber(1, 6); // \"000001\"\n * ```\n */\nexport function formatCallNumber(n: number, padding = 4): string {\n  return n.toString().padStart(padding, \"0\");\n}\n\n/**\n * Writes a log file, creating the directory if needed.\n *\n * @param dir - Directory path\n * @param filename - File name\n * @param content - Content to write\n */\nasync function writeLogFile(dir: string, filename: string, content: string): Promise<void> {\n  await mkdir(dir, { recursive: true });\n  await writeFile(join(dir, filename), content, \"utf-8\");\n}\n\n/**\n * Creates hooks for file-based LLM request/response logging.\n *\n * Files are named `{counter}.request` and `{counter}.response` where counter\n * is a zero-padded number that increments with each LLM call.\n *\n * @param options - Configuration options\n * @param state - Optional state container for session isolation. If not provided,\n *                uses a default global state. Pass `createFileLoggingState()` for\n *                isolated testing or independent agent sessions.\n * @returns AgentHooks configuration for use with .withHooks()\n *\n * @example\n * ```typescript\n * // Standard usage (shared global state):\n * const hooks = createFileLoggingHooks({\n *   directory: './debug-logs',\n *   onFileWritten: (info) => console.log(`Wrote ${info.filePath}`)\n * });\n *\n * // Isolated state for testing:\n * const state = createFileLoggingState();\n * const hooks = createFileLoggingHooks({ directory: './logs' }, state);\n *\n * const agent = LLMist.createAgent()\n *   .withHooks(hooks)\n *   .ask(\"Hello\");\n * ```\n */\nexport function createFileLoggingHooks(\n  options: FileLoggingOptions,\n  state: FileLoggingState = getDefaultState(),\n): AgentHooks {\n  const {\n    startingCounter = 1,\n    counterPadding = 4,\n    skipSubagents = true,\n    formatRequest = formatLlmRequest,\n    onFileWritten,\n  } = options;\n\n  // Normalize directory path to prevent /tmp/logs vs /tmp/logs/ issues\n  const baseDirectory = resolve(options.directory);\n\n  // Initialize base directory counter if needed (subtract 1 because getNextCounter increments first)\n  if (!state.counters.has(baseDirectory)) {\n    state.counters.set(baseDirectory, startingCounter - 1);\n  }\n\n  // Track current call for request-response correlation within this hook instance\n  let currentCallNumber = 0;\n  let currentDirectory = baseDirectory;\n\n  return {\n    observers: {\n      /**\n       * Write request file when LLM call is ready (messages are finalized).\n       */\n      onLLMCallReady: async (context) => {\n        // Skip subagent calls if configured\n        if (skipSubagents && context.subagentContext) {\n          return;\n        }\n\n        // Resolve directory (may create numbered subdirectory for subagents)\n        currentDirectory = resolveLoggingDirectory(\n          state,\n          baseDirectory,\n          counterPadding,\n          context.subagentContext,\n        );\n\n        // Get next counter for THIS directory (local to the agent/subagent)\n        currentCallNumber = getNextCounter(state, currentDirectory);\n\n        const filename = `${formatCallNumber(currentCallNumber, counterPadding)}.request`;\n        const content = formatRequest(context.options.messages);\n\n        try {\n          await writeLogFile(currentDirectory, filename, content);\n\n          if (onFileWritten) {\n            onFileWritten({\n              filePath: join(currentDirectory, filename),\n              type: \"request\",\n              callNumber: currentCallNumber,\n              contentLength: content.length,\n              parentGadgetInvocationId: context.subagentContext?.parentGadgetInvocationId,\n              depth: context.subagentContext?.depth,\n            });\n          }\n        } catch (error) {\n          // Graceful degradation: log warning but don't crash agent\n          console.warn(`[file-logging] Failed to write ${filename}:`, error);\n        }\n      },\n\n      /**\n       * Write response file when LLM call completes.\n       */\n      onLLMCallComplete: async (context) => {\n        // Skip subagent calls if configured\n        if (skipSubagents && context.subagentContext) {\n          return;\n        }\n\n        // Guard: ensure onLLMCallReady was called first and set currentCallNumber\n        if (currentCallNumber === 0) {\n          console.warn(\"[file-logging] Skipping response write: no matching request recorded\");\n          return;\n        }\n\n        const filename = `${formatCallNumber(currentCallNumber, counterPadding)}.response`;\n        const content = context.rawResponse;\n\n        try {\n          await writeLogFile(currentDirectory, filename, content);\n\n          if (onFileWritten) {\n            onFileWritten({\n              filePath: join(currentDirectory, filename),\n              type: \"response\",\n              callNumber: currentCallNumber,\n              contentLength: content.length,\n              parentGadgetInvocationId: context.subagentContext?.parentGadgetInvocationId,\n              depth: context.subagentContext?.depth,\n            });\n          }\n        } catch (error) {\n          // Graceful degradation: log warning but don't crash agent\n          console.warn(`[file-logging] Failed to write ${filename}:`, error);\n        }\n      },\n    },\n  };\n}\n\n/**\n * Gets file logging hooks from environment variable configuration.\n *\n * Checks for the `LLMIST_LOG_RAW_DIRECTORY` environment variable.\n * If set, returns configured hooks; otherwise returns undefined.\n *\n * @returns AgentHooks if env var is set, undefined otherwise\n *\n * @example\n * ```typescript\n * // In your application startup or AgentBuilder:\n * const envHooks = getEnvFileLoggingHooks();\n * if (envHooks) {\n *   builder.withHooks(envHooks);\n * }\n * ```\n */\nexport function getEnvFileLoggingHooks(): AgentHooks | undefined {\n  const directory = process.env[ENV_LOG_RAW_DIRECTORY]?.trim();\n  if (!directory) {\n    return undefined;\n  }\n\n  return createFileLoggingHooks({ directory });\n}\n","/**\n * Ready-to-use hook configurations for common monitoring, logging, and debugging tasks.\n *\n * HookPresets provide instant observability without writing custom hooks. They're the\n * fastest way to add monitoring to your agents during development and production.\n *\n * ## Available Presets\n *\n * - **logging(options?)** - Log LLM calls and gadget execution\n * - **timing()** - Measure execution time for operations\n * - **tokenTracking()** - Track cumulative token usage and costs\n * - **progressTracking(options?)** - Track progress with iterations, tokens, cost, and timing (SHOWCASE)\n * - **errorLogging()** - Log detailed error information\n * - **silent()** - No output (useful for testing)\n * - **monitoring(options?)** - All-in-one preset combining logging, timing, tokens, and errors\n * - **merge(...hookSets)** - Combine multiple hook configurations\n *\n * ## Quick Start\n *\n * @example\n * ```typescript\n * import { LLMist, HookPresets } from 'llmist';\n *\n * // Basic logging\n * await LLMist.createAgent()\n *   .withHooks(HookPresets.logging())\n *   .ask(\"Your prompt\");\n *\n * // Full monitoring suite (recommended for development)\n * await LLMist.createAgent()\n *   .withHooks(HookPresets.monitoring({ verbose: true }))\n *   .ask(\"Your prompt\");\n *\n * // Combine multiple presets\n * await LLMist.createAgent()\n *   .withHooks(HookPresets.merge(\n *     HookPresets.timing(),\n *     HookPresets.tokenTracking()\n *   ))\n *   .ask(\"Your prompt\");\n *\n * // Environment-based configuration\n * const hooks = process.env.NODE_ENV === 'production'\n *   ? HookPresets.merge(HookPresets.errorLogging(), HookPresets.tokenTracking())\n *   : HookPresets.monitoring({ verbose: true });\n *\n * await LLMist.createAgent()\n *   .withHooks(hooks)\n *   .ask(\"Your prompt\");\n * ```\n *\n * @see {@link https://github.com/zbigniewsobiecki/llmist/blob/main/docs/HOOKS.md | Full documentation}\n */\n\nimport type { ModelRegistry } from \"../core/model-registry.js\";\nimport { stripProviderPrefix } from \"../core/model-shortcuts.js\";\nimport { createFileLoggingHooks, type FileLoggingOptions } from \"./file-logging.js\";\nimport type { AgentHooks } from \"./hooks.js\";\n\n/**\n * Options for logging preset.\n */\nexport interface LoggingOptions {\n  /** Include verbose details like parameters and results */\n  verbose?: boolean;\n}\n\n/**\n * Progress statistics reported by progressTracking preset.\n *\n * Contains cumulative metrics across all LLM calls in the agent session,\n * useful for building progress UI, cost monitoring, and performance tracking.\n */\nexport interface ProgressStats {\n  /** Current iteration number (increments on each LLM call start) */\n  currentIteration: number;\n\n  /** Total number of completed LLM calls */\n  totalCalls: number;\n\n  /** Cumulative input tokens across all calls */\n  totalInputTokens: number;\n\n  /** Cumulative output tokens across all calls */\n  totalOutputTokens: number;\n\n  /** Total tokens (input + output) */\n  totalTokens: number;\n\n  /** Cumulative cost in USD (includes LLM and gadget costs; requires modelRegistry for LLM cost estimation) */\n  totalCost: number;\n\n  /** Elapsed time in seconds since first call */\n  elapsedSeconds: number;\n}\n\n/**\n * Options for progressTracking preset.\n *\n * Controls how progress data is tracked and reported during agent execution.\n */\nexport interface ProgressTrackingOptions {\n  /**\n   * Model registry for cost calculation.\n   *\n   * If provided, enables automatic cost estimation based on token usage\n   * and model pricing data. Without it, totalCost will always be 0.\n   *\n   * @example\n   * ```typescript\n   * import { LLMist, HookPresets } from 'llmist';\n   *\n   * const client = LLMist.create();\n   * const hooks = HookPresets.progressTracking({\n   *   modelRegistry: client.modelRegistry  // Enable cost tracking\n   * });\n   * ```\n   */\n  modelRegistry?: ModelRegistry;\n\n  /**\n   * Callback invoked after each LLM call completion with cumulative stats.\n   *\n   * Use this to update progress UI, log metrics, or track budgets in real-time.\n   *\n   * @example\n   * ```typescript\n   * HookPresets.progressTracking({\n   *   modelRegistry: client.modelRegistry,\n   *   onProgress: (stats) => {\n   *     console.log(`Iteration #${stats.currentIteration}`);\n   *     console.log(`Cost so far: $${stats.totalCost.toFixed(4)}`);\n   *     console.log(`Elapsed: ${stats.elapsedSeconds}s`);\n   *   }\n   * })\n   * ```\n   */\n  onProgress?: (stats: ProgressStats) => void;\n\n  /**\n   * Whether to log progress to console after each LLM call.\n   *\n   * When enabled, prints a summary line with tokens, cost, and elapsed time.\n   * Useful for quick debugging without implementing a custom callback.\n   *\n   * Default: false\n   *\n   * @example\n   * ```typescript\n   * // Quick console-based progress tracking\n   * HookPresets.progressTracking({\n   *   modelRegistry: client.modelRegistry,\n   *   logProgress: true  // Log to console\n   * })\n   * // Output: 📊 Progress: Iteration #2 | 1,234 tokens | $0.0056 | 12.3s\n   * ```\n   */\n  logProgress?: boolean;\n}\n\n/**\n * Common hook presets.\n */\nexport class HookPresets {\n  /**\n   * Logs LLM calls and gadget execution to console with optional verbosity.\n   *\n   * **Output (basic mode):**\n   * - LLM call start/complete events with iteration numbers\n   * - Gadget execution start/complete with gadget names\n   * - Token counts when available\n   *\n   * **Output (verbose mode):**\n   * - All basic mode output\n   * - Full gadget parameters (formatted JSON)\n   * - Full gadget results\n   * - Complete LLM response text\n   *\n   * **Use cases:**\n   * - Basic development debugging and execution flow visibility\n   * - Understanding agent decision-making and tool usage\n   * - Troubleshooting gadget invocations\n   *\n   * **Performance:** Minimal overhead. Console writes are synchronous but fast.\n   *\n   * @param options - Logging options\n   * @param options.verbose - Include full parameters and results. Default: false\n   * @returns Hook configuration that can be passed to .withHooks()\n   *\n   * @example\n   * ```typescript\n   * // Basic logging\n   * await LLMist.createAgent()\n   *   .withHooks(HookPresets.logging())\n   *   .ask(\"Calculate 15 * 23\");\n   * // Output: [LLM] Starting call (iteration 0)\n   * //         [GADGET] Executing Calculator\n   * //         [GADGET] Completed Calculator\n   * //         [LLM] Completed (tokens: 245)\n   * ```\n   *\n   * @example\n   * ```typescript\n   * // Verbose logging with full details\n   * await LLMist.createAgent()\n   *   .withHooks(HookPresets.logging({ verbose: true }))\n   *   .ask(\"Calculate 15 * 23\");\n   * // Output includes: parameters, results, and full responses\n   * ```\n   *\n   * @example\n   * ```typescript\n   * // Environment-based verbosity\n   * const isDev = process.env.NODE_ENV === 'development';\n   * .withHooks(HookPresets.logging({ verbose: isDev }))\n   * ```\n   *\n   * @see {@link https://github.com/zbigniewsobiecki/llmist/blob/main/docs/HOOKS.md#hookpresetsloggingoptions | Full documentation}\n   */\n  static logging(options: LoggingOptions = {}): AgentHooks {\n    return {\n      observers: {\n        onLLMCallStart: async (ctx) => {\n          console.log(`[LLM] Starting call (iteration ${ctx.iteration})`);\n        },\n        onLLMCallComplete: async (ctx) => {\n          const tokens = ctx.usage?.totalTokens ?? \"unknown\";\n          console.log(`[LLM] Completed (tokens: ${tokens})`);\n          if (options.verbose && ctx.finalMessage) {\n            console.log(`[LLM] Response: ${ctx.finalMessage}`);\n          }\n        },\n        onGadgetExecutionStart: async (ctx) => {\n          console.log(`[GADGET] Executing ${ctx.gadgetName}`);\n          if (options.verbose) {\n            console.log(`[GADGET] Parameters:`, JSON.stringify(ctx.parameters, null, 2));\n          }\n        },\n        onGadgetExecutionComplete: async (ctx) => {\n          console.log(`[GADGET] Completed ${ctx.gadgetName}`);\n          if (options.verbose) {\n            const display = ctx.error ?? ctx.finalResult ?? \"(no result)\";\n            console.log(`[GADGET] Result: ${display}`);\n          }\n        },\n      },\n    };\n  }\n\n  /**\n   * Measures and logs execution time for LLM calls and gadgets.\n   *\n   * **Output:**\n   * - Duration in milliseconds with ⏱️ emoji for each operation\n   * - Separate timing for each LLM iteration\n   * - Separate timing for each gadget execution\n   *\n   * **Use cases:**\n   * - Performance profiling and optimization\n   * - Identifying slow operations (LLM calls vs gadget execution)\n   * - Monitoring response times in production\n   * - Capacity planning and SLA tracking\n   *\n   * **Performance:** Negligible overhead. Uses Date.now() for timing measurements.\n   *\n   * @returns Hook configuration that can be passed to .withHooks()\n   *\n   * @example\n   * ```typescript\n   * // Basic timing\n   * await LLMist.createAgent()\n   *   .withHooks(HookPresets.timing())\n   *   .withGadgets(Weather, Database)\n   *   .ask(\"What's the weather in NYC?\");\n   * // Output: ⏱️ LLM call took 1234ms\n   * //         ⏱️ Gadget Weather took 567ms\n   * //         ⏱️ LLM call took 890ms\n   * ```\n   *\n   * @example\n   * ```typescript\n   * // Combined with logging for full context\n   * .withHooks(HookPresets.merge(\n   *   HookPresets.logging(),\n   *   HookPresets.timing()\n   * ))\n   * ```\n   *\n   * @example\n   * ```typescript\n   * // Correlate performance with cost\n   * .withHooks(HookPresets.merge(\n   *   HookPresets.timing(),\n   *   HookPresets.tokenTracking()\n   * ))\n   * ```\n   *\n   * @see {@link https://github.com/zbigniewsobiecki/llmist/blob/main/docs/HOOKS.md#hookpresetstiming | Full documentation}\n   */\n  static timing(): AgentHooks {\n    const timings = new Map<string, number>();\n\n    return {\n      observers: {\n        onLLMCallStart: async (ctx) => {\n          timings.set(`llm-${ctx.iteration}`, Date.now());\n        },\n        onLLMCallComplete: async (ctx) => {\n          const start = timings.get(`llm-${ctx.iteration}`);\n          if (start) {\n            const duration = Date.now() - start;\n            console.log(`⏱️  LLM call took ${duration}ms`);\n            timings.delete(`llm-${ctx.iteration}`);\n          }\n        },\n        onGadgetExecutionStart: async (ctx) => {\n          timings.set(ctx.invocationId, Date.now());\n        },\n        onGadgetExecutionComplete: async (ctx) => {\n          const start = timings.get(ctx.invocationId);\n          if (start) {\n            const duration = Date.now() - start;\n            console.log(`⏱️  Gadget ${ctx.gadgetName} took ${duration}ms`);\n            timings.delete(ctx.invocationId);\n          }\n        },\n      },\n    };\n  }\n\n  /**\n   * Tracks cumulative token usage across all LLM calls.\n   *\n   * @public\n   *\n   * **Output:**\n   * - Per-call token count with 📊 emoji\n   * - Cumulative total across all calls\n   * - Call count for average calculations\n   *\n   * **Use cases:**\n   * - Cost monitoring and budget tracking\n   * - Optimizing prompts to reduce token usage\n   * - Comparing token efficiency across different approaches\n   * - Real-time cost estimation\n   *\n   * **Performance:** Minimal overhead. Simple counter increments.\n   *\n   * **Note:** Token counts depend on the provider's response. Some providers\n   * may not include usage data, in which case counts won't be logged.\n   *\n   * @returns Hook configuration that can be passed to .withHooks()\n   *\n   * @example\n   * ```typescript\n   * // Basic token tracking\n   * await LLMist.createAgent()\n   *   .withHooks(HookPresets.tokenTracking())\n   *   .ask(\"Summarize this document...\");\n   * // Output: 📊 Tokens this call: 1,234\n   * //         📊 Total tokens: 1,234 (across 1 calls)\n   * //         📊 Tokens this call: 567\n   * //         📊 Total tokens: 1,801 (across 2 calls)\n   * ```\n   *\n   * @example\n   * ```typescript\n   * // Cost calculation with custom hook\n   * let totalTokens = 0;\n   * .withHooks(HookPresets.merge(\n   *   HookPresets.tokenTracking(),\n   *   {\n   *     observers: {\n   *       onLLMCallComplete: async (ctx) => {\n   *         totalTokens += ctx.usage?.totalTokens ?? 0;\n   *         const cost = (totalTokens / 1_000_000) * 3.0; // $3 per 1M tokens\n   *         console.log(`💰 Estimated cost: $${cost.toFixed(4)}`);\n   *       },\n   *     },\n   *   }\n   * ))\n   * ```\n   *\n   * @see {@link https://github.com/zbigniewsobiecki/llmist/blob/main/docs/HOOKS.md#hookpresetstokentracking | Full documentation}\n   */\n  static tokenTracking(): AgentHooks {\n    let totalTokens = 0;\n    let totalCalls = 0;\n\n    return {\n      observers: {\n        onLLMCallComplete: async (ctx) => {\n          totalCalls++;\n          if (ctx.usage?.totalTokens) {\n            totalTokens += ctx.usage.totalTokens;\n            console.log(`📊 Tokens this call: ${ctx.usage.totalTokens}`);\n            console.log(`📊 Total tokens: ${totalTokens} (across ${totalCalls} calls)`);\n          }\n        },\n      },\n    };\n  }\n\n  /**\n   * Tracks comprehensive progress metrics including iterations, tokens, cost, and timing.\n   *\n   * **This preset showcases llmist's core capabilities by demonstrating:**\n   * - Observer pattern for non-intrusive monitoring\n   * - Integration with ModelRegistry for cost estimation\n   * - Callback-based architecture for flexible UI updates\n   * - Provider-agnostic token and cost tracking\n   *\n   * Unlike `tokenTracking()` which only logs to console, this preset provides\n   * structured data through callbacks, making it perfect for building custom UIs,\n   * dashboards, or progress indicators (like the llmist CLI).\n   *\n   * **Output (when logProgress: true):**\n   * - Iteration number and call count\n   * - Cumulative token usage (input + output)\n   * - Cumulative cost in USD (requires modelRegistry)\n   * - Elapsed time in seconds\n   *\n   * **Use cases:**\n   * - Building CLI progress indicators with live updates\n   * - Creating web dashboards with real-time metrics\n   * - Budget monitoring and cost alerts\n   * - Performance tracking and optimization\n   * - Custom logging to external systems (Datadog, CloudWatch, etc.)\n   *\n   * **Performance:** Minimal overhead. Uses Date.now() for timing and optional\n   * ModelRegistry.estimateCost() which is O(1) lookup. Callback invocation is\n   * synchronous and fast.\n   *\n   * @param options - Progress tracking options\n   * @param options.modelRegistry - ModelRegistry for cost estimation (optional)\n   * @param options.onProgress - Callback invoked after each LLM call (optional)\n   * @param options.logProgress - Log progress to console (default: false)\n   * @returns Hook configuration with progress tracking observers\n   *\n   * @example\n   * ```typescript\n   * // Basic usage with callback (RECOMMENDED - used by llmist CLI)\n   * import { LLMist, HookPresets } from 'llmist';\n   *\n   * const client = LLMist.create();\n   *\n   * await client.agent()\n   *   .withHooks(HookPresets.progressTracking({\n   *     modelRegistry: client.modelRegistry,\n   *     onProgress: (stats) => {\n   *       // Update your UI with stats\n   *       console.log(`#${stats.currentIteration} | ${stats.totalTokens} tokens | $${stats.totalCost.toFixed(4)}`);\n   *     }\n   *   }))\n   *   .withGadgets(Calculator)\n   *   .ask(\"Calculate 15 * 23\");\n   * // Output: #1 | 245 tokens | $0.0012\n   * ```\n   *\n   * @example\n   * ```typescript\n   * // Console logging mode (quick debugging)\n   * await client.agent()\n   *   .withHooks(HookPresets.progressTracking({\n   *     modelRegistry: client.modelRegistry,\n   *     logProgress: true  // Simple console output\n   *   }))\n   *   .ask(\"Your prompt\");\n   * // Output: 📊 Progress: Iteration #1 | 245 tokens | $0.0012 | 1.2s\n   * ```\n   *\n   * @example\n   * ```typescript\n   * // Budget monitoring with alerts\n   * const BUDGET_USD = 0.10;\n   *\n   * await client.agent()\n   *   .withHooks(HookPresets.progressTracking({\n   *     modelRegistry: client.modelRegistry,\n   *     onProgress: (stats) => {\n   *       if (stats.totalCost > BUDGET_USD) {\n   *         throw new Error(`Budget exceeded: $${stats.totalCost.toFixed(4)}`);\n   *       }\n   *     }\n   *   }))\n   *   .ask(\"Long running task...\");\n   * ```\n   *\n   * @example\n   * ```typescript\n   * // Web dashboard integration\n   * let progressBar: HTMLElement;\n   *\n   * await client.agent()\n   *   .withHooks(HookPresets.progressTracking({\n   *     modelRegistry: client.modelRegistry,\n   *     onProgress: (stats) => {\n   *       // Update web UI in real-time\n   *       progressBar.textContent = `Iteration ${stats.currentIteration}`;\n   *       progressBar.dataset.cost = stats.totalCost.toFixed(4);\n   *       progressBar.dataset.tokens = stats.totalTokens.toString();\n   *     }\n   *   }))\n   *   .ask(\"Your prompt\");\n   * ```\n   *\n   * @example\n   * ```typescript\n   * // External logging (Datadog, CloudWatch, etc.)\n   * await client.agent()\n   *   .withHooks(HookPresets.progressTracking({\n   *     modelRegistry: client.modelRegistry,\n   *     onProgress: async (stats) => {\n   *       await metrics.gauge('llm.iteration', stats.currentIteration);\n   *       await metrics.gauge('llm.cost', stats.totalCost);\n   *       await metrics.gauge('llm.tokens', stats.totalTokens);\n   *     }\n   *   }))\n   *   .ask(\"Your prompt\");\n   * ```\n   *\n   * @see {@link https://github.com/zbigniewsobiecki/llmist/blob/main/docs/HOOKS.md#hookpresetsprogresstrackingoptions | Full documentation}\n   * @see {@link ProgressTrackingOptions} for detailed options\n   * @see {@link ProgressStats} for the callback data structure\n   */\n  static progressTracking(options?: ProgressTrackingOptions): AgentHooks {\n    const { modelRegistry, onProgress, logProgress = false } = options ?? {};\n\n    // State tracking - follows same pattern as tokenTracking()\n    let totalCalls = 0;\n    let currentIteration = 0;\n    let totalInputTokens = 0;\n    let totalOutputTokens = 0;\n    let totalCost = 0;\n    let totalGadgetCost = 0;\n    const startTime = Date.now();\n\n    return {\n      observers: {\n        // Track iteration on each LLM call start\n        onLLMCallStart: async (ctx) => {\n          currentIteration++;\n        },\n\n        // Accumulate metrics and report progress on each LLM call completion\n        onLLMCallComplete: async (ctx) => {\n          totalCalls++;\n\n          // Track token usage from provider response\n          if (ctx.usage) {\n            totalInputTokens += ctx.usage.inputTokens;\n            totalOutputTokens += ctx.usage.outputTokens;\n\n            // Calculate cost using ModelRegistry (core llmist feature)\n            // This showcases integration with llmist's pricing catalog\n            if (modelRegistry) {\n              try {\n                // Extract model name from provider:model format\n                // Example: \"openai:gpt-4o\" -> \"gpt-4o\"\n                const modelName = stripProviderPrefix(ctx.options.model);\n\n                // Use core's estimateCost() for accurate pricing\n                const costEstimate = modelRegistry.estimateCost(\n                  modelName,\n                  ctx.usage.inputTokens,\n                  ctx.usage.outputTokens,\n                  ctx.usage.cachedInputTokens ?? 0,\n                  ctx.usage.cacheCreationInputTokens ?? 0,\n                  ctx.usage.reasoningTokens ?? 0,\n                );\n\n                if (costEstimate) {\n                  totalCost += costEstimate.totalCost;\n                }\n              } catch (error) {\n                // Graceful degradation - log error but don't crash\n                // This follows llmist's principle of non-intrusive monitoring\n                if (logProgress) {\n                  console.warn(`⚠️  Cost estimation failed:`, error);\n                }\n              }\n            }\n          }\n\n          // Build comprehensive progress stats (LLM + gadget costs combined)\n          const stats: ProgressStats = {\n            currentIteration,\n            totalCalls,\n            totalInputTokens,\n            totalOutputTokens,\n            totalTokens: totalInputTokens + totalOutputTokens,\n            totalCost: totalCost + totalGadgetCost,\n            elapsedSeconds: Number(((Date.now() - startTime) / 1000).toFixed(1)),\n          };\n\n          // Invoke callback if provided (used by CLI and custom UIs)\n          if (onProgress) {\n            onProgress(stats);\n          }\n\n          // Optional console logging for quick debugging\n          if (logProgress) {\n            const formattedTokens =\n              stats.totalTokens >= 1000\n                ? `${(stats.totalTokens / 1000).toFixed(1)}k`\n                : `${stats.totalTokens}`;\n\n            const formattedCost = stats.totalCost > 0 ? `$${stats.totalCost.toFixed(4)}` : \"$0\";\n\n            console.log(\n              `📊 Progress: Iteration #${stats.currentIteration} | ${formattedTokens} tokens | ${formattedCost} | ${stats.elapsedSeconds}s`,\n            );\n          }\n        },\n\n        // Track gadget execution costs\n        onGadgetExecutionComplete: async (ctx) => {\n          if (ctx.cost && ctx.cost > 0) {\n            totalGadgetCost += ctx.cost;\n          }\n        },\n      },\n    };\n  }\n\n  /**\n   * Logs detailed error information for debugging and troubleshooting.\n   *\n   * @public\n   *\n   * **Output:**\n   * - LLM errors with ❌ emoji, including model and recovery status\n   * - Gadget errors with full context (parameters, error message)\n   * - Separate logging for LLM and gadget failures\n   *\n   * **Use cases:**\n   * - Troubleshooting production issues\n   * - Understanding error patterns and frequency\n   * - Debugging error recovery behavior\n   * - Collecting error metrics for monitoring\n   *\n   * **Performance:** Minimal overhead. Only logs when errors occur.\n   *\n   * @returns Hook configuration that can be passed to .withHooks()\n   *\n   * @example\n   * ```typescript\n   * // Basic error logging\n   * await LLMist.createAgent()\n   *   .withHooks(HookPresets.errorLogging())\n   *   .withGadgets(Database)\n   *   .ask(\"Fetch user data\");\n   * // Output (on LLM error): ❌ LLM Error (iteration 1): Rate limit exceeded\n   * //                        Model: gpt-5-nano\n   * //                        Recovered: true\n   * // Output (on gadget error): ❌ Gadget Error: Database\n   * //                            Error: Connection timeout\n   * //                            Parameters: {...}\n   * ```\n   *\n   * @example\n   * ```typescript\n   * // Combine with monitoring for full context\n   * .withHooks(HookPresets.merge(\n   *   HookPresets.monitoring(),  // Includes errorLogging\n   *   customErrorAnalytics\n   * ))\n   * ```\n   *\n   * @example\n   * ```typescript\n   * // Error analytics collection\n   * const errors: any[] = [];\n   * .withHooks(HookPresets.merge(\n   *   HookPresets.errorLogging(),\n   *   {\n   *     observers: {\n   *       onLLMCallError: async (ctx) => {\n   *         errors.push({ type: 'llm', error: ctx.error, recovered: ctx.recovered });\n   *       },\n   *     },\n   *   }\n   * ))\n   * ```\n   *\n   * @see {@link https://github.com/zbigniewsobiecki/llmist/blob/main/docs/HOOKS.md#hookpresetserrorlogging | Full documentation}\n   */\n  static errorLogging(): AgentHooks {\n    return {\n      observers: {\n        onLLMCallError: async (ctx) => {\n          console.error(`❌ LLM Error (iteration ${ctx.iteration}):`, ctx.error.message);\n          console.error(`   Model: ${ctx.options.model}`);\n          console.error(`   Recovered: ${ctx.recovered}`);\n        },\n        onGadgetExecutionComplete: async (ctx) => {\n          if (ctx.error) {\n            console.error(`❌ Gadget Error: ${ctx.gadgetName}`);\n            console.error(`   Error: ${ctx.error}`);\n            console.error(`   Parameters:`, JSON.stringify(ctx.parameters, null, 2));\n          }\n        },\n      },\n    };\n  }\n\n  /**\n   * Tracks context compaction events.\n   *\n   * @public\n   *\n   * **Output:**\n   * - Compaction events with 🗜️ emoji\n   * - Strategy name, tokens before/after, and savings\n   * - Cumulative statistics\n   *\n   * **Use cases:**\n   * - Monitoring long-running conversations\n   * - Understanding when and how compaction occurs\n   * - Debugging context management issues\n   *\n   * **Performance:** Minimal overhead. Simple console output.\n   *\n   * @returns Hook configuration that can be passed to .withHooks()\n   *\n   * @example\n   * ```typescript\n   * await LLMist.createAgent()\n   *   .withHooks(HookPresets.compactionTracking())\n   *   .ask(\"Your prompt\");\n   * ```\n   */\n  static compactionTracking(): AgentHooks {\n    return {\n      observers: {\n        onCompaction: async (ctx) => {\n          const saved = ctx.event.tokensBefore - ctx.event.tokensAfter;\n          const percent = ((saved / ctx.event.tokensBefore) * 100).toFixed(1);\n          console.log(\n            `🗜️  Compaction (${ctx.event.strategy}): ${ctx.event.tokensBefore} → ${ctx.event.tokensAfter} tokens (saved ${saved}, ${percent}%)`,\n          );\n          console.log(`   Messages: ${ctx.event.messagesBefore} → ${ctx.event.messagesAfter}`);\n          if (ctx.stats.totalCompactions > 1) {\n            console.log(\n              `   Cumulative: ${ctx.stats.totalCompactions} compactions, ${ctx.stats.totalTokensSaved} tokens saved`,\n            );\n          }\n        },\n      },\n    };\n  }\n\n  /**\n   * Logs LLM requests and responses to files for debugging and audit trails.\n   *\n   * Files are named `{counter}.request` and `{counter}.response` where counter\n   * is a zero-padded number that increments with each LLM call.\n   *\n   * **Output:**\n   * - Request files containing formatted LLM message history\n   * - Response files containing raw LLM output\n   *\n   * **Use cases:**\n   * - Debugging complex agent interactions\n   * - Creating audit trails for compliance\n   * - Analyzing LLM behavior patterns\n   * - Replaying conversations for testing\n   *\n   * **Performance:** Minimal overhead - only file I/O, no synchronous blocking.\n   *\n   * **Note:** Can also be enabled via `LLMIST_LOG_RAW_DIRECTORY` environment\n   * variable for zero-code activation.\n   *\n   * @param options - File logging options\n   * @param options.directory - Directory where log files will be written\n   * @param options.startingCounter - Starting counter (default: 1)\n   * @param options.counterPadding - Number of digits for padding (default: 4)\n   * @param options.skipSubagents - Skip subagent calls (default: true)\n   * @param options.formatRequest - Custom request formatter\n   * @param options.onFileWritten - Callback after each file is written\n   * @returns Hook configuration that can be passed to .withHooks()\n   *\n   * @example\n   * ```typescript\n   * // Basic file logging\n   * await LLMist.createAgent()\n   *   .withHooks(HookPresets.fileLogging({\n   *     directory: './debug-logs'\n   *   }))\n   *   .ask(\"Hello\");\n   * // Creates: ./debug-logs/0001.request\n   * //          ./debug-logs/0001.response\n   * ```\n   *\n   * @example\n   * ```typescript\n   * // With callback for tracking\n   * await LLMist.createAgent()\n   *   .withHooks(HookPresets.fileLogging({\n   *     directory: './logs',\n   *     onFileWritten: (info) => {\n   *       console.log(`Wrote ${info.type}: ${info.filePath}`);\n   *     }\n   *   }))\n   *   .ask(\"Hello\");\n   * ```\n   *\n   * @example\n   * ```typescript\n   * // Combined with other presets\n   * .withHooks(HookPresets.merge(\n   *   HookPresets.fileLogging({ directory: logDir }),\n   *   HookPresets.progressTracking({ onProgress: updateUI }),\n   *   HookPresets.errorLogging()\n   * ))\n   * ```\n   *\n   * @see {@link https://github.com/zbigniewsobiecki/llmist/blob/main/docs/HOOKS.md#hookpresetsfileloggingoptions | Full documentation}\n   */\n  static fileLogging(options: FileLoggingOptions): AgentHooks {\n    return createFileLoggingHooks(options);\n  }\n\n  /**\n   * Returns empty hook configuration for clean output without any logging.\n   *\n   * @public\n   *\n   * **Output:**\n   * - None. Returns {} (empty object).\n   *\n   * **Use cases:**\n   * - Clean test output without console noise\n   * - Production environments where logging is handled externally\n   * - Baseline for custom hook development\n   * - Temporary disable of all hook output\n   *\n   * **Performance:** Zero overhead. No-op hook configuration.\n   *\n   * @returns Empty hook configuration\n   *\n   * @example\n   * ```typescript\n   * // Clean test output\n   * describe('Agent tests', () => {\n   *   it('should calculate correctly', async () => {\n   *     const result = await LLMist.createAgent()\n   *       .withHooks(HookPresets.silent()) // No console output\n   *       .withGadgets(Calculator)\n   *       .askAndCollect(\"What is 15 times 23?\");\n   *\n   *     expect(result).toContain(\"345\");\n   *   });\n   * });\n   * ```\n   *\n   * @example\n   * ```typescript\n   * // Conditional silence based on environment\n   * const isTesting = process.env.NODE_ENV === 'test';\n   * .withHooks(isTesting ? HookPresets.silent() : HookPresets.monitoring())\n   * ```\n   *\n   * @see {@link https://github.com/zbigniewsobiecki/llmist/blob/main/docs/HOOKS.md#hookpresetssilent | Full documentation}\n   */\n  static silent(): AgentHooks {\n    return {};\n  }\n\n  /**\n   * Combines multiple hook configurations into one.\n   *\n   * Merge allows you to compose preset and custom hooks for modular monitoring\n   * configurations. Understanding merge behavior is crucial for proper composition.\n   *\n   * **Merge behavior:**\n   * - **Observers:** Composed - all handlers run sequentially in order\n   * - **Interceptors:** Last one wins - only the last interceptor applies\n   * - **Controllers:** Last one wins - only the last controller applies\n   *\n   * **Why interceptors/controllers don't compose:**\n   * - Interceptors have different signatures per method, making composition impractical\n   * - Controllers return specific actions that can't be meaningfully combined\n   * - Only observers support composition because they're read-only and independent\n   *\n   * **Use cases:**\n   * - Combining multiple presets (logging + timing + tokens)\n   * - Adding custom hooks to presets\n   * - Building modular, reusable monitoring configurations\n   * - Environment-specific hook composition\n   *\n   * **Performance:** Minimal overhead for merging. Runtime performance depends on merged hooks.\n   *\n   * @param hookSets - Variable number of hook configurations to merge\n   * @returns Single merged hook configuration with composed/overridden handlers\n   *\n   * @example\n   * ```typescript\n   * // Combine multiple presets\n   * .withHooks(HookPresets.merge(\n   *   HookPresets.logging(),\n   *   HookPresets.timing(),\n   *   HookPresets.tokenTracking()\n   * ))\n   * // All observers from all three presets will run\n   * ```\n   *\n   * @example\n   * ```typescript\n   * // Add custom observer to preset (both run)\n   * .withHooks(HookPresets.merge(\n   *   HookPresets.timing(),\n   *   {\n   *     observers: {\n   *       onLLMCallComplete: async (ctx) => {\n   *         await saveMetrics({ tokens: ctx.usage?.totalTokens });\n   *       },\n   *     },\n   *   }\n   * ))\n   * ```\n   *\n   * @example\n   * ```typescript\n   * // Multiple interceptors (last wins!)\n   * .withHooks(HookPresets.merge(\n   *   {\n   *     interceptors: {\n   *       interceptTextChunk: (chunk) => chunk.toUpperCase(), // Ignored\n   *     },\n   *   },\n   *   {\n   *     interceptors: {\n   *       interceptTextChunk: (chunk) => chunk.toLowerCase(), // This wins\n   *     },\n   *   }\n   * ))\n   * // Result: text will be lowercase\n   * ```\n   *\n   * @example\n   * ```typescript\n   * // Modular environment-based configuration\n   * const baseHooks = HookPresets.errorLogging();\n   * const devHooks = HookPresets.merge(baseHooks, HookPresets.monitoring({ verbose: true }));\n   * const prodHooks = HookPresets.merge(baseHooks, HookPresets.tokenTracking());\n   *\n   * const hooks = process.env.NODE_ENV === 'production' ? prodHooks : devHooks;\n   * .withHooks(hooks)\n   * ```\n   *\n   * @see {@link https://github.com/zbigniewsobiecki/llmist/blob/main/docs/HOOKS.md#hookpresetsmergehooksets | Full documentation}\n   */\n  static merge(...hookSets: AgentHooks[]): AgentHooks {\n    const merged: AgentHooks = {\n      observers: {},\n      interceptors: {},\n      controllers: {},\n    };\n\n    // Compose observers: run all handlers for the same event\n    for (const hooks of hookSets) {\n      if (hooks.observers) {\n        for (const [key, handler] of Object.entries(hooks.observers)) {\n          const typedKey = key as keyof typeof hooks.observers;\n          if (merged.observers![typedKey]) {\n            // Compose: run both existing and new handler\n            const existing = merged.observers![typedKey];\n            merged.observers![typedKey] = async (ctx: any) => {\n              await existing(ctx);\n              await handler(ctx);\n            };\n          } else {\n            merged.observers![typedKey] = handler as any;\n          }\n        }\n      }\n\n      // Interceptors: last one wins (complex signatures make composition impractical)\n      // Each interceptor has different parameters (chunk, message, parameters, etc.)\n      // so we can't meaningfully compose them like we do with observers\n      if (hooks.interceptors) {\n        Object.assign(merged.interceptors!, hooks.interceptors);\n      }\n\n      // Controllers: last one wins (can't meaningfully compose boolean returns)\n      if (hooks.controllers) {\n        Object.assign(merged.controllers!, hooks.controllers);\n      }\n    }\n\n    return merged;\n  }\n\n  /**\n   * Composite preset combining logging, timing, tokenTracking, and errorLogging.\n   *\n   * @public\n   *\n   * This is the recommended preset for development and initial production deployments,\n   * providing comprehensive observability with a single method call.\n   *\n   * **Includes:**\n   * - All output from `logging()` preset (with optional verbosity)\n   * - All output from `timing()` preset (execution times)\n   * - All output from `tokenTracking()` preset (token usage)\n   * - All output from `errorLogging()` preset (error details)\n   *\n   * **Output format:**\n   * - Event logging: [LLM]/[GADGET] messages\n   * - Timing: ⏱️ emoji with milliseconds\n   * - Tokens: 📊 emoji with per-call and cumulative counts\n   * - Errors: ❌ emoji with full error details\n   *\n   * **Use cases:**\n   * - Full observability during development\n   * - Comprehensive monitoring in production\n   * - One-liner for complete agent visibility\n   * - Troubleshooting and debugging with full context\n   *\n   * **Performance:** Combined overhead of all four presets, but still minimal in practice.\n   *\n   * @param options - Monitoring options\n   * @param options.verbose - Passed to logging() preset for detailed output. Default: false\n   * @returns Merged hook configuration combining all monitoring presets\n   *\n   * @example\n   * ```typescript\n   * // Basic monitoring (recommended for development)\n   * await LLMist.createAgent()\n   *   .withHooks(HookPresets.monitoring())\n   *   .withGadgets(Calculator, Weather)\n   *   .ask(\"What is 15 times 23, and what's the weather in NYC?\");\n   * // Output: All events, timing, tokens, and errors in one place\n   * ```\n   *\n   * @example\n   * ```typescript\n   * // Verbose monitoring with full details\n   * await LLMist.createAgent()\n   *   .withHooks(HookPresets.monitoring({ verbose: true }))\n   *   .ask(\"Your prompt\");\n   * // Output includes: parameters, results, and complete responses\n   * ```\n   *\n   * @example\n   * ```typescript\n   * // Environment-based monitoring\n   * const isDev = process.env.NODE_ENV === 'development';\n   * .withHooks(HookPresets.monitoring({ verbose: isDev }))\n   * ```\n   *\n   * @see {@link https://github.com/zbigniewsobiecki/llmist/blob/main/docs/HOOKS.md#hookpresetsmonitoringoptions | Full documentation}\n   */\n  static monitoring(options: LoggingOptions = {}): AgentHooks {\n    return HookPresets.merge(\n      HookPresets.logging(options),\n      HookPresets.timing(),\n      HookPresets.tokenTracking(),\n      HookPresets.errorLogging(),\n    );\n  }\n}\n","import { getEnvFileLoggingHooks } from \"./file-logging.js\";\nimport { HookPresets } from \"./hook-presets.js\";\nimport type { AgentHooks, BeforeLLMCallAction, LLMCallControllerContext } from \"./hooks.js\";\n\n/**\n * Context available to trailing message functions.\n * Provides iteration information for dynamic message generation.\n */\nexport type TrailingMessageContext = Pick<\n  LLMCallControllerContext,\n  \"iteration\" | \"maxIterations\" | \"budget\" | \"totalCost\"\n>;\n\n/**\n * Trailing message can be a static string or a function that generates the message.\n * The function receives context about the current iteration.\n */\nexport type TrailingMessage = string | ((ctx: TrailingMessageContext) => string);\n\n/**\n * Logic for composing and augmenting agent hooks.\n *\n * Encapsulates:\n * 1. Merging user hooks with environment-based logging\n * 2. Injecting trailing message controllers\n * 3. Future hook augmentation (e.g. debugging, metrics)\n */\nexport class HookComposer {\n  /**\n   * Compose the final hooks, including trailing message injection if configured.\n   *\n   * @param userHooks - User-provided hooks\n   * @param trailingMessage - Optional trailing message configuration\n   * @returns Final composed hooks or undefined\n   */\n  static compose(\n    userHooks?: AgentHooks,\n    trailingMessage?: TrailingMessage,\n  ): AgentHooks | undefined {\n    let hooks = userHooks;\n\n    // Auto-inject environment-based file logging if LLMIST_LOG_RAW_DIRECTORY is set\n    const envFileLogging = getEnvFileLoggingHooks();\n    if (envFileLogging) {\n      // Merge env hooks with user hooks (user hooks take precedence)\n      hooks = hooks ? HookPresets.merge(envFileLogging, hooks) : envFileLogging;\n    }\n\n    // Handle trailing message injection\n    if (!trailingMessage) {\n      return hooks;\n    }\n\n    const trailingMsg = trailingMessage;\n    const existingBeforeLLMCall = hooks?.controllers?.beforeLLMCall;\n\n    const trailingMessageController = async (\n      ctx: LLMCallControllerContext,\n    ): Promise<BeforeLLMCallAction> => {\n      // Run existing beforeLLMCall first if present\n      const result: BeforeLLMCallAction = existingBeforeLLMCall\n        ? await existingBeforeLLMCall(ctx)\n        : { action: \"proceed\" };\n\n      // If action is \"skip\", don't inject trailing message\n      if (result.action === \"skip\") {\n        return result;\n      }\n\n      // Get messages (possibly already modified by existing controller)\n      const messages = [...(result.modifiedOptions?.messages || ctx.options.messages)];\n\n      // Generate trailing message content\n      const content =\n        typeof trailingMsg === \"function\"\n          ? trailingMsg({\n              iteration: ctx.iteration,\n              maxIterations: ctx.maxIterations,\n              budget: ctx.budget,\n              totalCost: ctx.totalCost,\n            })\n          : trailingMsg;\n\n      // Append as ephemeral user message\n      messages.push({ role: \"user\", content });\n\n      return {\n        action: \"proceed\",\n        modifiedOptions: { ...result.modifiedOptions, messages },\n      };\n    };\n\n    return {\n      ...hooks,\n      controllers: {\n        ...hooks?.controllers,\n        beforeLLMCall: trailingMessageController,\n      },\n    };\n  }\n}\n","/**\n * Anthropic Claude Model Specifications\n *\n * Model data for Anthropic Claude models including Sonnet and Opus variants\n * with their specifications, pricing, and capabilities.\n */\n\nimport type { ModelSpec } from \"../core/model-catalog.js\";\n\nexport const ANTHROPIC_MODELS: ModelSpec[] = [\n  {\n    provider: \"anthropic\",\n    modelId: \"claude-sonnet-4-5-20250929\",\n    displayName: \"Claude Sonnet 4.5\",\n    contextWindow: 200_000,\n    maxOutputTokens: 64_000,\n    pricing: {\n      input: 3.0,\n      output: 15.0,\n      cachedInput: 0.3,\n      cacheWriteInput: 3.75,\n    },\n    knowledgeCutoff: \"2025-01\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: true,\n      reasoning: true,\n    },\n    metadata: {\n      family: \"Claude 4\",\n      releaseDate: \"2025-09-29\",\n      notes: \"Smartest model for complex agents and coding. Extended thinking. 1M context in beta.\",\n    },\n  },\n  {\n    provider: \"anthropic\",\n    modelId: \"claude-haiku-4-5-20251001\",\n    displayName: \"Claude Haiku 4.5\",\n    contextWindow: 200_000,\n    maxOutputTokens: 64_000,\n    pricing: {\n      input: 1.0,\n      output: 5.0,\n      cachedInput: 0.1,\n      cacheWriteInput: 1.25,\n    },\n    knowledgeCutoff: \"2025-02\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: true,\n      reasoning: true,\n    },\n    metadata: {\n      family: \"Claude 4\",\n      releaseDate: \"2025-10-01\",\n      notes:\n        \"Fastest model with near-frontier intelligence. Excellent for coding (73.3% SWE-bench).\",\n    },\n  },\n  {\n    provider: \"anthropic\",\n    modelId: \"claude-sonnet-4-20250514\",\n    displayName: \"Claude Sonnet 4\",\n    contextWindow: 200_000,\n    maxOutputTokens: 64_000,\n    pricing: {\n      input: 3.0,\n      output: 15.0,\n      cachedInput: 0.3,\n      cacheWriteInput: 3.75,\n    },\n    knowledgeCutoff: \"2025-03\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: true,\n      reasoning: true,\n    },\n    metadata: {\n      family: \"Claude 4\",\n      releaseDate: \"2025-05-14\",\n      notes: \"High performance with vision and extended thinking\",\n    },\n  },\n  {\n    provider: \"anthropic\",\n    modelId: \"claude-3-7-sonnet-20250219\",\n    displayName: \"Claude Sonnet 3.7\",\n    contextWindow: 200_000,\n    maxOutputTokens: 64_000,\n    pricing: {\n      input: 3.0,\n      output: 15.0,\n      cachedInput: 0.3,\n      cacheWriteInput: 3.75,\n    },\n    knowledgeCutoff: \"2024-11\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: true,\n      reasoning: true,\n    },\n    metadata: {\n      family: \"Claude 3\",\n      releaseDate: \"2025-02-19\",\n      notes: \"Legacy model - consider upgrading to Claude 4 family\",\n    },\n  },\n  {\n    provider: \"anthropic\",\n    modelId: \"claude-opus-4-1-20250805\",\n    displayName: \"Claude Opus 4.1\",\n    contextWindow: 200_000,\n    maxOutputTokens: 32_000,\n    pricing: {\n      input: 15.0,\n      output: 75.0,\n      cachedInput: 1.5,\n      cacheWriteInput: 18.75,\n    },\n    knowledgeCutoff: \"2025-01\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: true,\n      reasoning: true,\n    },\n    metadata: {\n      family: \"Claude 4\",\n      releaseDate: \"2025-08-05\",\n      notes: \"Exceptional for specialized reasoning tasks. Extended thinking support.\",\n    },\n  },\n  {\n    provider: \"anthropic\",\n    modelId: \"claude-opus-4-20250514\",\n    displayName: \"Claude Opus 4\",\n    contextWindow: 200_000,\n    maxOutputTokens: 32_000,\n    pricing: {\n      input: 15.0,\n      output: 75.0,\n      cachedInput: 1.5,\n      cacheWriteInput: 18.75,\n    },\n    knowledgeCutoff: \"2025-03\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: true,\n    },\n    metadata: {\n      family: \"Claude 4\",\n      releaseDate: \"2025-05-14\",\n      notes: \"Legacy Opus model - consider Opus 4.1 for improved reasoning\",\n    },\n  },\n  {\n    provider: \"anthropic\",\n    modelId: \"claude-3-5-haiku-20241022\",\n    displayName: \"Claude Haiku 3.5\",\n    contextWindow: 200_000,\n    maxOutputTokens: 8_192,\n    pricing: {\n      input: 0.8,\n      output: 4.0,\n      cachedInput: 0.08,\n      cacheWriteInput: 1.0,\n    },\n    knowledgeCutoff: \"2024-07\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: true,\n    },\n    metadata: {\n      family: \"Claude 3\",\n      releaseDate: \"2024-10-22\",\n      notes: \"Legacy model - upgrade to Haiku 4.5 for better performance\",\n    },\n  },\n  {\n    provider: \"anthropic\",\n    modelId: \"claude-3-haiku-20240307\",\n    displayName: \"Claude Haiku 3\",\n    contextWindow: 200_000,\n    maxOutputTokens: 4_096,\n    pricing: {\n      input: 0.25,\n      output: 1.25,\n      cachedInput: 0.025,\n      cacheWriteInput: 0.3125,\n    },\n    knowledgeCutoff: \"2023-08\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: true,\n    },\n    metadata: {\n      family: \"Claude 3\",\n      releaseDate: \"2024-03-07\",\n      notes: \"Legacy model - upgrade to Haiku 4.5 for better performance\",\n    },\n  },\n  // Dated Opus 4.5\n  {\n    provider: \"anthropic\",\n    modelId: \"claude-opus-4-5-20251124\",\n    displayName: \"Claude Opus 4.5\",\n    contextWindow: 200_000,\n    maxOutputTokens: 64_000,\n    pricing: {\n      input: 5.0,\n      output: 25.0,\n      cachedInput: 0.5,\n      cacheWriteInput: 6.25,\n    },\n    knowledgeCutoff: \"2025-03\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: true,\n      reasoning: true,\n    },\n    metadata: {\n      family: \"Claude 4\",\n      releaseDate: \"2025-11-24\",\n      notes: \"Most powerful model for coding and computer use. Extended thinking support.\",\n    },\n  },\n\n  // Modern aliases (recommended by Anthropic)\n  {\n    provider: \"anthropic\",\n    modelId: \"claude-haiku-4-5\",\n    displayName: \"Claude Haiku 4.5\",\n    contextWindow: 200_000,\n    maxOutputTokens: 64_000,\n    pricing: {\n      input: 1.0,\n      output: 5.0,\n      cachedInput: 0.1,\n      cacheWriteInput: 1.25,\n    },\n    knowledgeCutoff: \"2025-02\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: true,\n      reasoning: true,\n    },\n    metadata: {\n      family: \"Claude 4\",\n      releaseDate: \"2025-10-01\",\n      notes: \"Alias for claude-haiku-4-5-20251001. Fastest model with near-frontier intelligence.\",\n    },\n  },\n  {\n    provider: \"anthropic\",\n    modelId: \"claude-sonnet-4-5\",\n    displayName: \"Claude Sonnet 4.5\",\n    contextWindow: 200_000,\n    maxOutputTokens: 64_000,\n    pricing: {\n      input: 3.0,\n      output: 15.0,\n      cachedInput: 0.3,\n      cacheWriteInput: 3.75,\n    },\n    knowledgeCutoff: \"2025-01\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: true,\n      reasoning: true,\n    },\n    metadata: {\n      family: \"Claude 4\",\n      releaseDate: \"2025-09-29\",\n      notes: \"Alias for claude-sonnet-4-5-20250929. Smartest model for complex agents and coding.\",\n    },\n  },\n  {\n    provider: \"anthropic\",\n    modelId: \"claude-opus-4-5\",\n    displayName: \"Claude Opus 4.5\",\n    contextWindow: 200_000,\n    maxOutputTokens: 64_000,\n    pricing: {\n      input: 5.0,\n      output: 25.0,\n      cachedInput: 0.5,\n      cacheWriteInput: 6.25,\n    },\n    knowledgeCutoff: \"2025-03\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: true,\n      reasoning: true,\n    },\n    metadata: {\n      family: \"Claude 4\",\n      releaseDate: \"2025-11-24\",\n      notes: \"Alias for claude-opus-4-5-20251124. Most powerful model for coding and computer use.\",\n    },\n  },\n];\n","/**\n * Base Provider Adapter\n *\n * Abstract base class for provider adapters that implements the Template Method pattern.\n * This class defines the skeleton of the streaming algorithm, leaving provider-specific\n * details to be implemented by concrete subclasses.\n *\n * The streaming workflow consists of four main steps:\n * 1. Prepare messages (optional transformation for provider-specific requirements)\n * 2. Build the request payload (provider-specific formatting)\n * 3. Execute the stream request (call the provider's SDK)\n * 4. Wrap the stream (transform provider-specific chunks into universal format)\n */\n\nimport type { LLMMessage } from \"../core/messages.js\";\nimport type { ModelSpec } from \"../core/model-catalog.js\";\nimport type { LLMGenerationOptions, LLMStream, ModelDescriptor } from \"../core/options.js\";\nimport type { ProviderAdapter } from \"./provider.js\";\n\nexport abstract class BaseProviderAdapter implements ProviderAdapter {\n  abstract readonly providerId: string;\n\n  constructor(protected readonly client: unknown) {}\n\n  abstract supports(descriptor: ModelDescriptor): boolean;\n\n  /**\n   * Optionally provide model specifications for this provider.\n   * This allows the model registry to discover available models and their capabilities.\n   */\n  getModelSpecs?(): ModelSpec[];\n\n  /**\n   * Template method that defines the skeleton of the streaming algorithm.\n   * This orchestrates the four-step process without dictating provider-specific details.\n   */\n  async *stream(\n    options: LLMGenerationOptions,\n    descriptor: ModelDescriptor,\n    spec?: ModelSpec,\n  ): LLMStream {\n    // Step 1: Prepare messages (can be overridden for special cases like Gemini)\n    const preparedMessages = this.prepareMessages(options.messages);\n\n    // Step 2: Build the provider-specific request payload\n    const payload = this.buildApiRequest(options, descriptor, spec, preparedMessages);\n\n    // Step 3: Execute the stream request using the provider's SDK (with optional abort signal)\n    const rawStream = await this.executeStreamRequest(payload, options.signal);\n\n    // Step 4: Normalize provider-specific stream into universal format\n    yield* this.normalizeProviderStream(rawStream);\n  }\n\n  /**\n   * Prepare messages for the request.\n   * Default implementation returns messages unchanged.\n   * Override this to implement provider-specific message transformations\n   * (e.g., Gemini's consecutive message merging, Anthropic's system message extraction).\n   *\n   * @param messages - The input messages\n   * @returns Prepared messages\n   */\n  protected prepareMessages(messages: LLMMessage[]): LLMMessage[] {\n    return messages;\n  }\n\n  /**\n   * Build the provider-specific API request.\n   * This method must be implemented by each concrete provider.\n   *\n   * @param options - The generation options\n   * @param descriptor - The model descriptor\n   * @param spec - Optional model specification with metadata\n   * @param messages - The prepared messages\n   * @returns Provider-specific request object ready for the API call\n   */\n  protected abstract buildApiRequest(\n    options: LLMGenerationOptions,\n    descriptor: ModelDescriptor,\n    spec: ModelSpec | undefined,\n    messages: LLMMessage[],\n  ): unknown;\n\n  /**\n   * Execute the stream request using the provider's SDK.\n   * This method must be implemented by each concrete provider.\n   *\n   * @param payload - The provider-specific payload\n   * @param signal - Optional abort signal for cancelling the request\n   * @returns An async iterable of provider-specific chunks\n   */\n  protected abstract executeStreamRequest(\n    payload: unknown,\n    signal?: AbortSignal,\n  ): Promise<AsyncIterable<unknown>>;\n\n  /**\n   * Normalize the provider-specific stream into the universal LLMStream format.\n   * This method must be implemented by each concrete provider.\n   *\n   * @param rawStream - The provider-specific stream\n   * @returns Universal LLMStream\n   */\n  protected abstract normalizeProviderStream(rawStream: AsyncIterable<unknown>): LLMStream;\n}\n","/**\n * Provider-specific constants and default values.\n *\n * This file centralizes magic numbers and hardcoded defaults to improve\n * maintainability and documentation. Each constant includes a comment\n * explaining its purpose and rationale.\n */\n\n/**\n * Default maximum output tokens for Anthropic models.\n *\n * Rationale: Most Anthropic models (Claude 3 Opus, Sonnet, Haiku) support\n * at least 4096 output tokens. This is used as a fallback when:\n * - The user doesn't specify maxTokens explicitly\n * - The model spec doesn't define maxOutputTokens\n *\n * Note: Anthropic's API requires the max_tokens parameter, unlike OpenAI\n * which can infer it from the context window. This default ensures the API\n * call succeeds while allowing substantial output.\n *\n * Reference: https://docs.anthropic.com/en/docs/about-claude/models\n */\nexport const ANTHROPIC_DEFAULT_MAX_OUTPUT_TOKENS = 4096;\n\n/**\n * Character-to-token ratio for fallback token estimation.\n *\n * Used only when tiktoken (the primary fallback) is unavailable. A value of 2\n * errs on the side of overestimating token count, which is safer for\n * compaction triggers and output limiting.\n *\n * Rationale: The previous value of 4 was based on English prose averages, but\n * agentic sessions are dominated by JSON, code, and structured data where the\n * real ratio is ~1.5-2.5 chars/token. A 4-char estimate underestimated tokens\n * by up to 250%, causing compaction and output limiting to never trigger.\n */\nexport const FALLBACK_CHARS_PER_TOKEN = 2;\n\n/**\n * OpenAI message structure overhead in tokens.\n *\n * Rationale: OpenAI's chat completion format adds tokens for message\n * boundaries and structure. Each message follows the pattern:\n * <im_start>{role/name}\\n{content}<im_end>\\n\n *\n * This overhead accounts for:\n * - <im_start> token\n * - Role/name field tokens\n * - Newline and separator tokens\n * - <im_end> token\n *\n * The value of 4 tokens per message is based on OpenAI's official\n * tokenization examples and testing.\n *\n * Reference: https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb\n */\nexport const OPENAI_MESSAGE_OVERHEAD_TOKENS = 4;\n\n/**\n * OpenAI reply priming overhead in tokens.\n *\n * Rationale: Every OpenAI assistant reply is primed with the tokens:\n * <im_start>assistant\\n\n *\n * This adds 2 tokens to the total input token count before the actual\n * response generation begins. This is part of OpenAI's message formatting\n * and must be accounted for in accurate token counting.\n *\n * Reference: https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb\n */\nexport const OPENAI_REPLY_PRIMING_TOKENS = 2;\n\n/**\n * OpenAI name field overhead in tokens.\n *\n * Rationale: When a message includes a \"name\" field (for identifying the\n * speaker in multi-party conversations), OpenAI's format adds 1 extra\n * token beyond the name's actual token count.\n *\n * This accounts for the separator between the role and name fields.\n *\n * Reference: https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb\n */\nexport const OPENAI_NAME_FIELD_OVERHEAD_TOKENS = 1;\n","/**\n * Common utility functions shared across provider implementations\n */\n\n/**\n * Safely read an environment variable\n * @param key - The environment variable key to read\n * @returns The value if found and valid, undefined otherwise\n */\nexport function readEnvVar(key: string): string | undefined {\n  if (typeof process === \"undefined\" || typeof process.env === \"undefined\") {\n    return undefined;\n  }\n  const value = process.env[key];\n  return typeof value === \"string\" ? value : undefined;\n}\n\n/**\n * Check if a value is a non-empty string\n * @param value - The value to check\n * @returns true if the value is a non-empty string, false otherwise\n */\nexport function isNonEmpty(value: string | undefined): value is string {\n  return typeof value === \"string\" && value.trim().length > 0;\n}\n\n/**\n * Generic factory function for creating provider instances from environment variables\n * @param envVarName - Name of the environment variable containing the API key\n * @param ClientClass - Constructor for the SDK client\n * @param ProviderClass - Constructor for the provider adapter\n * @param clientOptions - Optional additional options to pass to the client constructor\n * @returns Provider instance or null if API key is not set\n */\nexport function createProviderFromEnv<TClient, TProvider>(\n  envVarName: string,\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  ClientClass: new (config: any) => TClient,\n  ProviderClass: new (client: TClient) => TProvider,\n  clientOptions?: Record<string, unknown>,\n): TProvider | null {\n  const apiKey = readEnvVar(envVarName);\n  if (!isNonEmpty(apiKey)) {\n    return null;\n  }\n\n  // Create client with API key and optional config\n  // Disable SDK-level retries - llmist handles all retries at application level for consistency\n  const client = new ClientClass({ apiKey: apiKey.trim(), maxRetries: 0, ...clientOptions });\n\n  return new ProviderClass(client);\n}\n","import Anthropic from \"@anthropic-ai/sdk\";\nimport type {\n  ContentBlockParam,\n  ImageBlockParam,\n  MessageCreateParamsStreaming,\n  MessageStreamEvent,\n  TextBlockParam,\n} from \"@anthropic-ai/sdk/resources/messages\";\nimport type { ContentPart, ImageContentPart, ImageMimeType } from \"../core/input-content.js\";\nimport type { LLMMessage, MessageContent } from \"../core/messages.js\";\nimport { extractMessageText, normalizeMessageContent } from \"../core/messages.js\";\nimport type { ModelSpec } from \"../core/model-catalog.js\";\nimport type {\n  LLMGenerationOptions,\n  LLMStream,\n  ModelDescriptor,\n  ReasoningConfig,\n  ReasoningEffort,\n} from \"../core/options.js\";\nimport { ANTHROPIC_MODELS } from \"./anthropic-models.js\";\nimport { BaseProviderAdapter } from \"./base-provider.js\";\nimport { ANTHROPIC_DEFAULT_MAX_OUTPUT_TOKENS, FALLBACK_CHARS_PER_TOKEN } from \"./constants.js\";\nimport { createProviderFromEnv } from \"./utils.js\";\n\n/** Maps llmist reasoning effort levels to Anthropic thinking budget_tokens */\nconst ANTHROPIC_EFFORT_BUDGET: Record<ReasoningEffort, number> = {\n  none: 1024, // Minimum allowed by Anthropic\n  low: 2048,\n  medium: 8192,\n  high: 16384,\n  maximum: 32768,\n};\n\n/** Resolve Anthropic thinking parameters from ReasoningConfig */\nfunction resolveAnthropicThinking(\n  reasoning: ReasoningConfig | undefined,\n): { type: \"enabled\"; budget_tokens: number } | undefined {\n  if (!reasoning?.enabled) return undefined;\n\n  // Explicit budget takes precedence (clamped to Anthropic's minimum of 1024)\n  const budget = reasoning.budgetTokens\n    ? Math.max(1024, reasoning.budgetTokens)\n    : ANTHROPIC_EFFORT_BUDGET[reasoning.effort ?? \"medium\"];\n\n  return { type: \"enabled\", budget_tokens: budget };\n}\n\nexport class AnthropicMessagesProvider extends BaseProviderAdapter {\n  readonly providerId = \"anthropic\" as const;\n\n  supports(descriptor: ModelDescriptor): boolean {\n    return descriptor.provider === this.providerId;\n  }\n\n  getModelSpecs() {\n    return ANTHROPIC_MODELS;\n  }\n\n  // =========================================================================\n  // Image Generation (Not Supported)\n  // =========================================================================\n\n  supportsImageGeneration(_modelId: string): boolean {\n    return false;\n  }\n\n  async generateImage(): Promise<never> {\n    throw new Error(\n      \"Anthropic does not support image generation. Use OpenAI (DALL-E, GPT Image) or Google Gemini (Imagen) instead.\",\n    );\n  }\n\n  // =========================================================================\n  // Speech Generation (Not Supported)\n  // =========================================================================\n\n  supportsSpeechGeneration(_modelId: string): boolean {\n    return false;\n  }\n\n  async generateSpeech(): Promise<never> {\n    throw new Error(\n      \"Anthropic does not support speech generation. Use OpenAI (TTS) or Google Gemini (TTS) instead.\",\n    );\n  }\n\n  protected buildApiRequest(\n    options: LLMGenerationOptions,\n    descriptor: ModelDescriptor,\n    spec: ModelSpec | undefined,\n    messages: LLMMessage[],\n  ): MessageCreateParamsStreaming {\n    // Caching is enabled by default for Anthropic (preserves existing behavior).\n    // Only disabled when explicitly set to false via withoutCaching().\n    const cachingEnabled = options.caching?.enabled !== false;\n\n    const systemMessages = messages.filter((message) => message.role === \"system\");\n\n    // System message as array of text blocks with cache_control on last block\n    // This enables Anthropic's prompt caching for the system prompt\n    // System messages are always text-only\n    const system =\n      systemMessages.length > 0\n        ? systemMessages.map((m, index) => ({\n            type: \"text\" as const,\n            text: extractMessageText(m.content),\n            // Add cache_control to the LAST system message block (only when caching is enabled)\n            ...(cachingEnabled && index === systemMessages.length - 1\n              ? { cache_control: { type: \"ephemeral\" as const } }\n              : {}),\n          }))\n        : undefined;\n\n    const nonSystemMessages = messages.filter(\n      (message): message is LLMMessage & { role: \"user\" | \"assistant\" } =>\n        message.role !== \"system\",\n    );\n\n    // Find index of last user message for cache breakpoint\n    const lastUserIndex = nonSystemMessages.reduce(\n      (lastIdx, msg, idx) => (msg.role === \"user\" ? idx : lastIdx),\n      -1,\n    );\n\n    // Build conversation with multimodal content support\n    // Cache_control is added to the last part of the last user message (only when caching is enabled)\n    const conversation = nonSystemMessages.map((message, index) => ({\n      role: message.role,\n      content: this.convertToAnthropicContent(\n        message.content,\n        cachingEnabled && message.role === \"user\" && index === lastUserIndex,\n      ),\n    }));\n\n    // Anthropic requires max_tokens, so use a smart default if not specified\n    // Use model's max from the passed spec, or fall back to the default constant\n    const defaultMaxTokens = spec?.maxOutputTokens ?? ANTHROPIC_DEFAULT_MAX_OUTPUT_TOKENS;\n\n    // Resolve thinking configuration from reasoning config\n    const thinking = resolveAnthropicThinking(options.reasoning);\n\n    // Anthropic forbids temperature when thinking is enabled\n    const temperature = thinking ? undefined : options.temperature;\n\n    const payload: MessageCreateParamsStreaming = {\n      model: descriptor.name,\n      system,\n      messages: conversation,\n      max_tokens: options.maxTokens ?? defaultMaxTokens,\n      temperature,\n      top_p: options.topP,\n      stop_sequences: options.stopSequences,\n      stream: true,\n      ...(thinking ? { thinking } : {}),\n      ...options.extra,\n    };\n\n    return payload;\n  }\n\n  /**\n   * Convert llmist content to Anthropic's content block format.\n   * Handles text, images (base64 only), and applies cache_control.\n   */\n  private convertToAnthropicContent(\n    content: MessageContent,\n    addCacheControl: boolean,\n  ): ContentBlockParam[] {\n    const parts = normalizeMessageContent(content);\n\n    return parts.map((part, index) => {\n      const isLastPart = index === parts.length - 1;\n      const cacheControl =\n        addCacheControl && isLastPart ? { cache_control: { type: \"ephemeral\" as const } } : {};\n\n      if (part.type === \"text\") {\n        return {\n          type: \"text\" as const,\n          text: part.text,\n          ...cacheControl,\n        } as TextBlockParam;\n      }\n\n      if (part.type === \"image\") {\n        return this.convertImagePart(part, cacheControl);\n      }\n\n      if (part.type === \"audio\") {\n        throw new Error(\n          \"Anthropic does not support audio input. Use Google Gemini for audio processing.\",\n        );\n      }\n\n      throw new Error(`Unsupported content type: ${(part as ContentPart).type}`);\n    });\n  }\n\n  /**\n   * Convert an image content part to Anthropic's image block format.\n   */\n  private convertImagePart(\n    part: ImageContentPart,\n    cacheControl: { cache_control?: { type: \"ephemeral\" } },\n  ): ImageBlockParam {\n    if (part.source.type === \"url\") {\n      throw new Error(\n        \"Anthropic does not support image URLs. Please provide base64-encoded image data instead.\",\n      );\n    }\n\n    return {\n      type: \"image\" as const,\n      source: {\n        type: \"base64\" as const,\n        media_type: part.source.mediaType as ImageMimeType,\n        data: part.source.data,\n      },\n      ...cacheControl,\n    };\n  }\n\n  protected async executeStreamRequest(\n    payload: MessageCreateParamsStreaming,\n    signal?: AbortSignal,\n  ): Promise<AsyncIterable<MessageStreamEvent>> {\n    const client = this.client as Anthropic;\n    // Pass abort signal to SDK via request options\n    const stream = await client.messages.create(payload, signal ? { signal } : undefined);\n    return stream as unknown as AsyncIterable<MessageStreamEvent>;\n  }\n\n  protected async *normalizeProviderStream(iterable: AsyncIterable<unknown>): LLMStream {\n    const stream = iterable as AsyncIterable<MessageStreamEvent>;\n    let inputTokens = 0;\n    let cachedInputTokens = 0;\n    let cacheCreationInputTokens = 0;\n\n    for await (const event of stream) {\n      // Track and yield input tokens from message_start event\n      // Anthropic returns cache_read_input_tokens and cache_creation_input_tokens\n      if (event.type === \"message_start\") {\n        const usage = event.message.usage as {\n          input_tokens: number;\n          cache_read_input_tokens?: number;\n          cache_creation_input_tokens?: number;\n        };\n        // Total input tokens includes uncached + cached reads + cache writes\n        cachedInputTokens = usage.cache_read_input_tokens ?? 0;\n        cacheCreationInputTokens = usage.cache_creation_input_tokens ?? 0;\n        inputTokens = usage.input_tokens + cachedInputTokens + cacheCreationInputTokens;\n        // Yield early so hooks can access input tokens before text streams\n        yield {\n          text: \"\",\n          usage: {\n            inputTokens,\n            outputTokens: 0,\n            totalTokens: inputTokens,\n            cachedInputTokens,\n            cacheCreationInputTokens,\n          },\n          rawEvent: event,\n        };\n        continue;\n      }\n\n      // Handle thinking content blocks (from extended thinking / reasoning mode)\n      if (event.type === \"content_block_start\") {\n        const block = event.content_block as { type: string };\n        if (block.type === \"thinking\") {\n          yield { text: \"\", thinking: { content: \"\", type: \"thinking\" }, rawEvent: event };\n          continue;\n        }\n        if (block.type === \"redacted_thinking\") {\n          yield { text: \"\", thinking: { content: \"\", type: \"redacted\" }, rawEvent: event };\n          continue;\n        }\n      }\n\n      if (event.type === \"content_block_delta\") {\n        const delta = event.delta as { type: string; thinking?: string; signature?: string };\n        if (delta.type === \"thinking_delta\" && delta.thinking) {\n          yield {\n            text: \"\",\n            thinking: { content: delta.thinking, type: \"thinking\" },\n            rawEvent: event,\n          };\n          continue;\n        }\n        if (delta.type === \"signature_delta\" && delta.signature) {\n          yield {\n            text: \"\",\n            thinking: { content: \"\", type: \"thinking\", signature: delta.signature },\n            rawEvent: event,\n          };\n          continue;\n        }\n        if (delta.type === \"text_delta\") {\n          yield { text: (delta as { text?: string }).text ?? \"\", rawEvent: event };\n          continue;\n        }\n        continue;\n      }\n\n      if (event.type === \"message_delta\") {\n        const usage = event.usage\n          ? {\n              inputTokens,\n              outputTokens: event.usage.output_tokens,\n              totalTokens: inputTokens + event.usage.output_tokens,\n              cachedInputTokens,\n              cacheCreationInputTokens,\n            }\n          : undefined;\n\n        if (event.delta.stop_reason || usage) {\n          yield {\n            text: \"\",\n            finishReason: event.delta.stop_reason ?? undefined,\n            usage,\n            rawEvent: event,\n          };\n        }\n        continue;\n      }\n\n      if (event.type === \"message_stop\") {\n        yield { text: \"\", finishReason: \"stop\", rawEvent: event };\n      }\n    }\n  }\n\n  /**\n   * Count tokens in messages using Anthropic's native token counting API.\n   *\n   * This method provides accurate token estimation for Anthropic models by:\n   * - Using the native messages.countTokens() API\n   * - Properly handling system messages and conversation structure\n   * - Transforming messages to Anthropic's expected format\n   *\n   * @param messages - The messages to count tokens for\n   * @param descriptor - Model descriptor containing the model name\n   * @param _spec - Optional model specification (currently unused)\n   * @returns Promise resolving to the estimated input token count\n   *\n   * @throws Never throws - falls back to character-based estimation (4 chars/token) on error\n   *\n   * @example\n   * ```typescript\n   * const count = await provider.countTokens(\n   *   [{ role: \"user\", content: \"Hello!\" }],\n   *   { provider: \"anthropic\", name: \"claude-3-5-sonnet-20241022\" }\n   * );\n   * ```\n   */\n  async countTokens(\n    messages: LLMMessage[],\n    descriptor: ModelDescriptor,\n    _spec?: ModelSpec,\n  ): Promise<number> {\n    const client = this.client as Anthropic;\n\n    // Extract system messages and conversation messages\n    const systemMessages = messages.filter((message) => message.role === \"system\");\n    const system =\n      systemMessages.length > 0\n        ? systemMessages.map((m) => extractMessageText(m.content)).join(\"\\n\\n\")\n        : undefined;\n\n    // Convert messages to Anthropic format, handling multimodal content\n    const conversation = messages\n      .filter(\n        (message): message is LLMMessage & { role: \"user\" | \"assistant\" } =>\n          message.role !== \"system\",\n      )\n      .map((message) => ({\n        role: message.role,\n        content: this.convertToAnthropicContent(message.content, false),\n      }));\n\n    try {\n      // Use the native token counting API\n      const response = await client.messages.countTokens({\n        model: descriptor.name,\n        messages: conversation,\n        ...(system ? { system } : {}),\n      });\n\n      return response.input_tokens;\n    } catch (error) {\n      // Log the error for debugging\n      console.warn(\n        `Token counting failed for ${descriptor.name}, using fallback estimation:`,\n        error,\n      );\n      // Fallback to rough estimation if API fails\n      // For multimodal, extract text and estimate; images add ~1000 tokens\n      let totalChars = 0;\n      let imageCount = 0;\n      for (const msg of messages) {\n        const parts = normalizeMessageContent(msg.content);\n        for (const part of parts) {\n          if (part.type === \"text\") {\n            totalChars += part.text.length;\n          } else if (part.type === \"image\") {\n            imageCount++;\n          }\n        }\n      }\n      // Anthropic charges ~1000 tokens per image (rough estimate).\n      // Source: https://docs.anthropic.com/en/docs/build-with-claude/vision\n      // Actual cost depends on image size, but this provides a reasonable fallback.\n      return Math.ceil(totalChars / FALLBACK_CHARS_PER_TOKEN) + imageCount * 1000;\n    }\n  }\n}\n\nexport function createAnthropicProviderFromEnv(): AnthropicMessagesProvider | null {\n  return createProviderFromEnv(\"ANTHROPIC_API_KEY\", Anthropic, AnthropicMessagesProvider);\n}\n","/**\n * Gemini Context Cache Manager\n *\n * Manages the lifecycle of Gemini's explicit context caches. Unlike Anthropic's\n * ephemeral caching (automatic via markers), Gemini requires creating cache\n * resources via the API and referencing them by name in generation requests.\n *\n * Cache lifecycle:\n * 1. Content is hashed to detect changes\n * 2. If existing cache matches hash and hasn't expired, it's reused\n * 3. Otherwise, a new cache is created (old one is cleaned up best-effort)\n * 4. The cache name is returned for use in `generateContentStream({ cachedContent: name })`\n *\n * Caches auto-expire via TTL, so cleanup failures are non-critical.\n */\n\nimport { createHash } from \"node:crypto\";\nimport { FunctionCallingConfigMode, type GoogleGenAI } from \"@google/genai\";\nimport type { CachingConfig, CachingScope } from \"../core/options.js\";\n\n/**\n * A Gemini content object (role + parts).\n * Matches the format used by GeminiGenerativeProvider.\n */\nexport type GeminiCacheContent = {\n  role: string;\n  parts: Array<{ text: string } | { inlineData: { mimeType: string; data: string } }>;\n};\n\n/**\n * Tracks the active cache entry for reuse detection.\n */\ninterface ActiveCacheEntry {\n  /** Server-assigned cache resource name (for referencing in generation calls) */\n  name: string;\n  /** Model the cache was created for */\n  model: string;\n  /** Hash of the cached content (for change detection) */\n  contentHash: string;\n  /** When the cache expires (ISO 8601) */\n  expireTime: string;\n}\n\nexport class GeminiCacheManager {\n  private activeCache: ActiveCacheEntry | null = null;\n\n  constructor(private readonly client: GoogleGenAI) {}\n\n  /**\n   * Get or create a cache for the given content.\n   *\n   * Returns the cache name if a cache was created/reused, or `null` if caching\n   * was skipped (disabled, below threshold, or API error).\n   *\n   * @param model - Gemini model name (e.g., \"gemini-2.5-flash\")\n   * @param allContents - All Gemini-formatted contents (system + conversation)\n   * @param config - Caching configuration from the user\n   * @param lastUserMessageIndex - Index of the last user message (content after this is not cached)\n   * @returns Cache name string or null\n   */\n  async getOrCreateCache(\n    model: string,\n    allContents: GeminiCacheContent[],\n    config: CachingConfig,\n    lastUserMessageIndex: number,\n  ): Promise<{ cacheName: string; cachedContentCount: number } | null> {\n    // Guard: caching must be enabled\n    if (!config.enabled) return null;\n\n    const scope: CachingScope = config.scope ?? \"conversation\";\n    const ttl = config.ttl ?? \"3600s\";\n    const minTokenThreshold = config.minTokenThreshold ?? 32768;\n\n    // Determine what content to cache based on scope\n    const cacheableContents = this.selectCacheableContents(\n      allContents,\n      scope,\n      lastUserMessageIndex,\n    );\n\n    if (cacheableContents.length === 0) return null;\n\n    // Estimate token count using character-based heuristic (avoid extra API call)\n    // Gemini's countTokens would be more accurate but adds latency\n    const estimatedTokens = this.estimateTokenCount(cacheableContents);\n    if (estimatedTokens < minTokenThreshold) return null;\n\n    // Compute content hash for change detection\n    const contentHash = this.computeContentHash(cacheableContents, model);\n\n    // Check if existing cache can be reused\n    if (this.activeCache && this.canReuseCache(this.activeCache, model, contentHash)) {\n      return {\n        cacheName: this.activeCache.name,\n        cachedContentCount: cacheableContents.length,\n      };\n    }\n\n    // Create new cache (clean up old one best-effort)\n    try {\n      await this.cleanupActiveCache();\n\n      const response = await this.client.caches.create({\n        model,\n        config: {\n          contents: cacheableContents,\n          ttl,\n          displayName: `llmist-${scope}-${Date.now()}`,\n          toolConfig: {\n            functionCallingConfig: {\n              mode: FunctionCallingConfigMode.NONE,\n            },\n          },\n        },\n      });\n\n      if (!response.name) {\n        return null;\n      }\n\n      this.activeCache = {\n        name: response.name,\n        model,\n        contentHash,\n        expireTime: response.expireTime ?? \"\",\n      };\n\n      return {\n        cacheName: response.name,\n        cachedContentCount: cacheableContents.length,\n      };\n    } catch (error) {\n      // Graceful degradation: log and continue without caching\n      console.warn(\"Gemini cache creation failed, continuing without cache:\", error);\n      return null;\n    }\n  }\n\n  /**\n   * Clean up the active cache (best-effort).\n   * Caches auto-expire via TTL, so failure is non-critical.\n   */\n  async dispose(): Promise<void> {\n    await this.cleanupActiveCache();\n  }\n\n  /**\n   * Select which contents to cache based on scope.\n   *\n   * - \"system\": Only system-derived messages (the initial user+model exchanges\n   *   generated from system messages)\n   * - \"conversation\": Everything except the last user message\n   */\n  private selectCacheableContents(\n    allContents: GeminiCacheContent[],\n    scope: CachingScope,\n    lastUserMessageIndex: number,\n  ): GeminiCacheContent[] {\n    if (scope === \"system\") {\n      // System messages are converted to user+model pairs at the start.\n      // Find where the initial system-derived exchanges end:\n      // They follow the pattern: user (instruction) → model (\"Understood.\")\n      let systemEndIndex = 0;\n      for (let i = 0; i < allContents.length; i++) {\n        const content = allContents[i];\n        if (\n          content.role === \"model\" &&\n          content.parts.length === 1 &&\n          \"text\" in content.parts[0] &&\n          content.parts[0].text === \"Understood.\"\n        ) {\n          // This model response confirms the preceding user message was a system instruction\n          systemEndIndex = i + 1;\n        } else if (content.role === \"user\") {\n          // Check if the next entry is a model \"Understood.\" (i.e., still a system pair)\n          const next = allContents[i + 1];\n          if (\n            next &&\n            next.role === \"model\" &&\n            next.parts.length === 1 &&\n            \"text\" in next.parts[0] &&\n            next.parts[0].text === \"Understood.\"\n          ) {\n            // Still in system section, continue scanning\n            continue;\n          }\n          // Not a system message, stop here\n          break;\n        } else {\n          break;\n        }\n      }\n      return allContents.slice(0, systemEndIndex);\n    }\n\n    // \"conversation\" scope: everything up to (but not including) the last user message\n    if (lastUserMessageIndex <= 0) return [];\n    return allContents.slice(0, lastUserMessageIndex);\n  }\n\n  /**\n   * Estimate token count from contents using character-based heuristic.\n   * Uses ~4 characters per token (conservative estimate for English text).\n   */\n  private estimateTokenCount(contents: GeminiCacheContent[]): number {\n    let totalChars = 0;\n    for (const content of contents) {\n      for (const part of content.parts) {\n        if (\"text\" in part) {\n          totalChars += part.text.length;\n        } else if (\"inlineData\" in part) {\n          // Images/audio: rough estimate of 258 tokens each\n          totalChars += 258 * 4;\n        }\n      }\n    }\n    return Math.ceil(totalChars / 4);\n  }\n\n  /**\n   * Compute a stable hash of the cacheable contents for change detection.\n   */\n  private computeContentHash(contents: GeminiCacheContent[], model: string): string {\n    const hash = createHash(\"sha256\");\n    hash.update(model);\n    for (const content of contents) {\n      hash.update(content.role);\n      for (const part of content.parts) {\n        if (\"text\" in part) {\n          hash.update(part.text);\n        } else if (\"inlineData\" in part) {\n          hash.update(part.inlineData.mimeType);\n          hash.update(part.inlineData.data);\n        }\n      }\n    }\n    return hash.digest(\"hex\");\n  }\n\n  /**\n   * Check if an existing cache can be reused.\n   */\n  private canReuseCache(cache: ActiveCacheEntry, model: string, contentHash: string): boolean {\n    if (cache.model !== model) return false;\n    if (cache.contentHash !== contentHash) return false;\n\n    // Check expiry (with 60-second safety margin)\n    if (cache.expireTime) {\n      const expiresAt = new Date(cache.expireTime).getTime();\n      const now = Date.now();\n      if (expiresAt - now < 60_000) return false;\n    }\n\n    return true;\n  }\n\n  /**\n   * Delete the active cache (best-effort).\n   */\n  private async cleanupActiveCache(): Promise<void> {\n    if (!this.activeCache) return;\n\n    try {\n      await this.client.caches.delete({ name: this.activeCache.name });\n    } catch {\n      // Best-effort: caches auto-expire via TTL anyway\n    }\n\n    this.activeCache = null;\n  }\n}\n","/**\n * Google Gemini Image Generation Model Catalog\n *\n * Pricing as of December 2025:\n *\n * Imagen 4 Family (standalone image generation):\n * - imagen-4.0-fast-generate-001: $0.02 per image\n * - imagen-4.0-generate-001: $0.04 per image\n * - imagen-4.0-ultra-generate-001: $0.06 per image\n *\n * Gemini Native Image Generation (multimodal):\n * - gemini-2.5-flash-image: $0.039 per output image\n * - gemini-3-pro-image-preview: ~$0.134 per 1K/2K image, $0.24 per 4K\n *\n * @see https://ai.google.dev/gemini-api/docs/pricing\n * @see https://ai.google.dev/gemini-api/docs/imagen\n */\n\nimport type { ImageModelSpec } from \"../core/media-types.js\";\n\n/** Imagen 4 supported aspect ratios */\nexport const IMAGEN4_ASPECT_RATIOS = [\"1:1\", \"3:4\", \"4:3\", \"9:16\", \"16:9\"] as const;\nexport type Imagen4AspectRatio = (typeof IMAGEN4_ASPECT_RATIOS)[number];\n\n/** Gemini native image supported aspect ratios */\nexport const GEMINI_IMAGE_ASPECT_RATIOS = [\"1:1\", \"3:4\", \"4:3\", \"9:16\", \"16:9\"] as const;\n\n/**\n * Google Image Model Specifications\n */\nexport const geminiImageModels: ImageModelSpec[] = [\n  // Imagen 4 Family (standalone image generation)\n  {\n    provider: \"gemini\",\n    modelId: \"imagen-4.0-fast-generate-001\",\n    displayName: \"Imagen 4 Fast\",\n    pricing: {\n      perImage: 0.02,\n    },\n    supportedSizes: [...IMAGEN4_ASPECT_RATIOS],\n    maxImages: 4,\n    defaultSize: \"1:1\",\n    features: {\n      textRendering: true,\n    },\n  },\n  {\n    provider: \"gemini\",\n    modelId: \"imagen-4.0-generate-001\",\n    displayName: \"Imagen 4\",\n    pricing: {\n      perImage: 0.04,\n    },\n    supportedSizes: [...IMAGEN4_ASPECT_RATIOS],\n    maxImages: 4,\n    defaultSize: \"1:1\",\n    features: {\n      textRendering: true,\n    },\n  },\n  {\n    provider: \"gemini\",\n    modelId: \"imagen-4.0-ultra-generate-001\",\n    displayName: \"Imagen 4 Ultra\",\n    pricing: {\n      perImage: 0.06,\n    },\n    supportedSizes: [...IMAGEN4_ASPECT_RATIOS],\n    maxImages: 4,\n    defaultSize: \"1:1\",\n    features: {\n      textRendering: true,\n    },\n  },\n  // Preview versions\n  {\n    provider: \"gemini\",\n    modelId: \"imagen-4.0-generate-preview-06-06\",\n    displayName: \"Imagen 4 (Preview)\",\n    pricing: {\n      perImage: 0.04,\n    },\n    supportedSizes: [...IMAGEN4_ASPECT_RATIOS],\n    maxImages: 4,\n    defaultSize: \"1:1\",\n    features: {\n      textRendering: true,\n    },\n  },\n  {\n    provider: \"gemini\",\n    modelId: \"imagen-4.0-ultra-generate-preview-06-06\",\n    displayName: \"Imagen 4 Ultra (Preview)\",\n    pricing: {\n      perImage: 0.06,\n    },\n    supportedSizes: [...IMAGEN4_ASPECT_RATIOS],\n    maxImages: 4,\n    defaultSize: \"1:1\",\n    features: {\n      textRendering: true,\n    },\n  },\n  // Gemini Native Image Generation (multimodal models)\n  {\n    provider: \"gemini\",\n    modelId: \"gemini-2.5-flash-image\",\n    displayName: \"Gemini 2.5 Flash Image\",\n    pricing: {\n      perImage: 0.039,\n    },\n    supportedSizes: [...GEMINI_IMAGE_ASPECT_RATIOS],\n    maxImages: 1,\n    defaultSize: \"1:1\",\n    features: {\n      conversational: true,\n      textRendering: true,\n    },\n  },\n  {\n    provider: \"gemini\",\n    modelId: \"gemini-2.5-flash-image-preview\",\n    displayName: \"Gemini 2.5 Flash Image (Preview)\",\n    pricing: {\n      perImage: 0.039,\n    },\n    supportedSizes: [...GEMINI_IMAGE_ASPECT_RATIOS],\n    maxImages: 1,\n    defaultSize: \"1:1\",\n    features: {\n      conversational: true,\n      textRendering: true,\n    },\n  },\n  {\n    provider: \"gemini\",\n    modelId: \"gemini-3-pro-image-preview\",\n    displayName: \"Gemini 3 Pro Image (Preview)\",\n    pricing: {\n      // Token-based: ~$0.134 per 1K/2K image, $0.24 per 4K\n      // Using 2K as default\n      bySize: {\n        \"1K\": 0.134,\n        \"2K\": 0.134,\n        \"4K\": 0.24,\n      },\n    },\n    supportedSizes: [\"1K\", \"2K\", \"4K\"],\n    maxImages: 1,\n    defaultSize: \"2K\",\n    features: {\n      conversational: true,\n      textRendering: true,\n    },\n  },\n  // Alias: nano-banana-pro-preview is gemini-3-pro-image-preview\n  {\n    provider: \"gemini\",\n    modelId: \"nano-banana-pro-preview\",\n    displayName: \"Nano Banana Pro (Gemini 3 Pro Image)\",\n    pricing: {\n      bySize: {\n        \"1K\": 0.134,\n        \"2K\": 0.134,\n        \"4K\": 0.24,\n      },\n    },\n    supportedSizes: [\"1K\", \"2K\", \"4K\"],\n    maxImages: 1,\n    defaultSize: \"2K\",\n    features: {\n      conversational: true,\n      textRendering: true,\n    },\n  },\n];\n\n/**\n * Get image model spec by model ID.\n */\nexport function getGeminiImageModelSpec(modelId: string): ImageModelSpec | undefined {\n  return geminiImageModels.find((m) => m.modelId === modelId);\n}\n\n/**\n * Check if a model ID is a Gemini image model.\n */\nexport function isGeminiImageModel(modelId: string): boolean {\n  return geminiImageModels.some((m) => m.modelId === modelId);\n}\n\n/**\n * Calculate cost for image generation.\n *\n * @param modelId - The model ID\n * @param size - Image size (for models with size-based pricing)\n * @param n - Number of images\n * @returns Cost in USD, or undefined if model not found\n */\nexport function calculateGeminiImageCost(modelId: string, size = \"1:1\", n = 1): number | undefined {\n  const spec = getGeminiImageModelSpec(modelId);\n  if (!spec) return undefined;\n\n  // Simple per-image pricing (Imagen 4, Gemini Flash Image)\n  if (spec.pricing.perImage !== undefined) {\n    return spec.pricing.perImage * n;\n  }\n\n  // Size-based pricing (Gemini 3 Pro Image)\n  if (spec.pricing.bySize) {\n    const sizePrice = spec.pricing.bySize[size];\n    if (typeof sizePrice === \"number\") {\n      return sizePrice * n;\n    }\n  }\n\n  return undefined;\n}\n","/**\n * Google Gemini Model Specifications\n *\n * Model data for Google Gemini models including 3.0, 2.5 and 2.0 series\n * with their specifications, pricing (Standard Paid tier), and capabilities.\n *\n * Pricing source: https://ai.google.dev/gemini-api/docs/pricing\n * Last updated: 2025-12-20\n */\n\nimport type { ModelSpec } from \"../core/model-catalog.js\";\n\nexport const GEMINI_MODELS: ModelSpec[] = [\n  // Gemini 3 Pro (Preview)\n  {\n    provider: \"gemini\",\n    modelId: \"gemini-3-pro-preview\",\n    displayName: \"Gemini 3 Pro (Preview)\",\n    contextWindow: 1_048_576,\n    maxOutputTokens: 65_536,\n    pricing: {\n      input: 2.0, // $2.00 for prompts <= 200k, $4.00 for > 200k (using lower tier)\n      output: 12.0, // $12.00 for prompts <= 200k, $18.00 for > 200k\n      cachedInput: 0.2, // $0.20 for prompts <= 200k\n    },\n    knowledgeCutoff: \"2025-01\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: true,\n      reasoning: true,\n      structuredOutputs: true,\n    },\n    metadata: {\n      family: \"Gemini 3\",\n      releaseDate: \"2025-11-18\",\n      notes:\n        \"Best model for multimodal understanding, agentic and vibe-coding. Deep Think mode available.\",\n    },\n  },\n\n  // Gemini 3 Flash (Preview)\n  {\n    provider: \"gemini\",\n    modelId: \"gemini-3-flash-preview\",\n    displayName: \"Gemini 3 Flash (Preview)\",\n    contextWindow: 1_048_576,\n    maxOutputTokens: 65_536,\n    pricing: {\n      input: 0.5, // $0.50 for text/image/video\n      output: 3.0,\n      cachedInput: 0.05,\n    },\n    knowledgeCutoff: \"2025-01\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: true,\n      reasoning: true,\n      structuredOutputs: true,\n    },\n    metadata: {\n      family: \"Gemini 3\",\n      releaseDate: \"2025-12\",\n      notes: \"Fast, cost-effective model with Deep Think mode. Good for agentic tasks.\",\n    },\n  },\n\n  // Gemini 2.5 Pro\n  {\n    provider: \"gemini\",\n    modelId: \"gemini-2.5-pro\",\n    displayName: \"Gemini 2.5 Pro\",\n    contextWindow: 1_048_576,\n    maxOutputTokens: 65_536,\n    pricing: {\n      input: 1.25, // $1.25 for prompts <= 200k, $2.50 for > 200k\n      output: 10.0, // $10.00 for prompts <= 200k, $15.00 for > 200k\n      cachedInput: 0.125, // $0.125 for prompts <= 200k\n    },\n    knowledgeCutoff: \"2025-01\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: true,\n      reasoning: true,\n      structuredOutputs: true,\n    },\n    metadata: {\n      family: \"Gemini 2.5\",\n      releaseDate: \"2025-06\",\n      notes: \"State-of-the-art multipurpose model. Excels at coding and complex reasoning.\",\n    },\n  },\n\n  // Gemini 2.5 Flash\n  {\n    provider: \"gemini\",\n    modelId: \"gemini-2.5-flash\",\n    displayName: \"Gemini 2.5 Flash\",\n    contextWindow: 1_048_576,\n    maxOutputTokens: 65_536,\n    pricing: {\n      input: 0.3, // $0.30 for text/image/video, $1.00 for audio\n      output: 2.5,\n      cachedInput: 0.03, // $0.03 for text/image/video\n    },\n    knowledgeCutoff: \"2025-01\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: true,\n      reasoning: true,\n      structuredOutputs: true,\n    },\n    metadata: {\n      family: \"Gemini 2.5\",\n      releaseDate: \"2025-06\",\n      notes: \"First hybrid reasoning model with 1M context and thinking budgets.\",\n    },\n  },\n\n  // Gemini 2.5 Flash-Lite\n  {\n    provider: \"gemini\",\n    modelId: \"gemini-2.5-flash-lite\",\n    displayName: \"Gemini 2.5 Flash-Lite\",\n    contextWindow: 1_048_576,\n    maxOutputTokens: 65_536,\n    pricing: {\n      input: 0.1, // $0.10 for text/image/video, $0.30 for audio\n      output: 0.4,\n      cachedInput: 0.01, // $0.01 for text/image/video\n    },\n    knowledgeCutoff: \"2025-01\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: true,\n      structuredOutputs: true,\n    },\n    metadata: {\n      family: \"Gemini 2.5\",\n      releaseDate: \"2025-06\",\n      notes: \"Smallest and most cost effective model, built for at scale usage.\",\n    },\n  },\n\n  // Gemini 2.0 Flash\n  {\n    provider: \"gemini\",\n    modelId: \"gemini-2.0-flash\",\n    displayName: \"Gemini 2.0 Flash\",\n    contextWindow: 1_048_576,\n    maxOutputTokens: 8_192,\n    pricing: {\n      input: 0.1, // $0.10 for text/image/video, $0.70 for audio\n      output: 0.4,\n      cachedInput: 0.025, // $0.025 for text/image/video\n    },\n    knowledgeCutoff: \"2024-08\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: true,\n      structuredOutputs: true,\n    },\n    metadata: {\n      family: \"Gemini 2.0\",\n      notes: \"Balanced multimodal model with 1M context, built for the era of Agents.\",\n    },\n  },\n\n  // Gemini 2.0 Flash-Lite\n  {\n    provider: \"gemini\",\n    modelId: \"gemini-2.0-flash-lite\",\n    displayName: \"Gemini 2.0 Flash-Lite\",\n    contextWindow: 1_048_576,\n    maxOutputTokens: 8_192,\n    pricing: {\n      input: 0.075,\n      output: 0.3,\n      // No context caching available for 2.0-flash-lite\n    },\n    knowledgeCutoff: \"2024-08\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: true,\n      structuredOutputs: true,\n    },\n    metadata: {\n      family: \"Gemini 2.0\",\n      notes: \"Smallest and most cost effective 2.0 model for at scale usage.\",\n    },\n  },\n];\n","/**\n * Research constants.\n *\n * Every tunable lives here (repo rule: no magic numbers). Timeouts are\n * deliberately generous — research runs take minutes to an hour.\n */\n\n/**\n * Default client-side time budget for a research run.\n * 1 hour — OpenAI's documented SDK timeout recommendation for synchronous\n * deep-research calls, and the Gemini Interactions hard cap.\n */\nexport const RESEARCH_DEFAULT_TIMEOUT_MS = 3_600_000;\n\n/**\n * Gemini Interactions API hard cap on research duration (60 minutes).\n * Runs exceeding it are terminated server-side.\n */\nexport const GEMINI_RESEARCH_MAX_DURATION_MS = 3_600_000;\n\n/**\n * Per-request HTTP timeout for OpenAI Responses research calls\n * (overrides SDK defaults; background polling uses short requests but\n * synchronous streams can run for the full duration).\n */\nexport const OPENAI_RESEARCH_HTTP_TIMEOUT_MS = 3_600_000;\n\n/**\n * Per-request HTTP timeout for OpenRouter research calls. The env-created\n * OpenRouter client defaults to 120s, which multi-minute research runs exceed.\n */\nexport const OPENROUTER_RESEARCH_HTTP_TIMEOUT_MS = 3_600_000;\n\n/** Initial polling interval for background jobs without streaming. */\nexport const RESEARCH_POLL_INTERVAL_MS = 10_000;\n\n/** Ceiling for the backed-off polling interval. */\nexport const RESEARCH_POLL_MAX_INTERVAL_MS = 60_000;\n\n/** Multiplier applied to the polling interval after each poll. */\nexport const RESEARCH_POLL_BACKOFF_FACTOR = 1.5;\n\n/**\n * Maximum consecutive stream-reconnect attempts (cursor-based resume) before\n * giving up. The counter resets whenever an event is successfully received.\n */\nexport const RESEARCH_STREAM_RECONNECT_MAX_ATTEMPTS = 5;\n\n/**\n * How many days before a model's `shutdownDate` a warning is logged when\n * starting a run on it.\n */\nexport const RESEARCH_SHUTDOWN_WARNING_WINDOW_DAYS = 30;\n\n/** Decimal places for cost estimates (avoids float noise in reported USD). */\nexport const RESEARCH_COST_DECIMALS = 6;\n\n/** Tokens per million — denominator for per-1M-token pricing. */\nexport const TOKENS_PER_MILLION = 1_000_000;\n\n/** Searches per thousand — denominator for per-1k-search pricing. */\nexport const SEARCHES_PER_THOUSAND = 1_000;\n\n/** Milliseconds per day (shutdown-window arithmetic). */\nexport const MS_PER_DAY = 86_400_000;\n","/**\n * Typed errors for the research surface.\n *\n * Follows the core error convention (plain `Error` subclasses with `name`\n * set) — see `core/errors.ts`.\n */\n\n/** Thrown when no registered provider supports research for the given model. */\nexport class ResearchNotSupportedError extends Error {\n  constructor(message: string) {\n    super(message);\n    this.name = \"ResearchNotSupportedError\";\n  }\n}\n\n/**\n * Thrown when a job cannot produce a serializable ref (no server-side job id —\n * e.g. OpenRouter research runs) or a ref cannot be resumed on its provider.\n */\nexport class ResearchJobNotResumableError extends Error {\n  constructor(message: string) {\n    super(message);\n    this.name = \"ResearchJobNotResumableError\";\n  }\n}\n\n/** Thrown when status polling is requested on a provider without it. */\nexport class ResearchNotPollableError extends Error {\n  constructor(message: string) {\n    super(message);\n    this.name = \"ResearchNotPollableError\";\n  }\n}\n\n/**\n * Thrown when the client-side time budget expires. The transport is aborted;\n * a background job keeps running server-side and its ref stays valid.\n */\nexport class ResearchTimeoutError extends Error {\n  readonly timeoutMs: number;\n\n  constructor(timeoutMs: number) {\n    super(\n      `Research run exceeded the client-side time budget of ${timeoutMs}ms. ` +\n        `A background job keeps running server-side — re-attach via its ref.`,\n    );\n    this.name = \"ResearchTimeoutError\";\n    this.timeoutMs = timeoutMs;\n  }\n}\n\n/** Thrown when starting a run on a model past its announced shutdown date. */\nexport class ResearchDeprecatedModelError extends Error {\n  readonly modelId: string;\n  readonly shutdownDate: string;\n  readonly replacement?: string;\n\n  constructor(params: { modelId: string; shutdownDate: string; replacement?: string }) {\n    super(\n      `Research model \"${params.modelId}\" was shut down by its provider on ${params.shutdownDate}.` +\n        (params.replacement ? ` Use \"${params.replacement}\" instead.` : \"\"),\n    );\n    this.name = \"ResearchDeprecatedModelError\";\n    this.modelId = params.modelId;\n    this.shutdownDate = params.shutdownDate;\n    this.replacement = params.replacement;\n  }\n}\n\n/** Thrown when options fail pre-flight validation against the model's spec. */\nexport class ResearchValidationError extends Error {\n  constructor(message: string) {\n    super(message);\n    this.name = \"ResearchValidationError\";\n  }\n}\n\n/** Thrown when a job's event stream is consumed more than once. */\nexport class ResearchStreamConsumedError extends Error {\n  constructor() {\n    super(\n      \"This research job's event stream was already consumed. \" +\n        \"Iterate events() (or the job itself) once; use result() for the aggregated outcome.\",\n    );\n    this.name = \"ResearchStreamConsumedError\";\n  }\n}\n","/**\n * Gemini deep research via the Interactions API (`client.interactions.*`).\n *\n * Deep research is exclusive to the Interactions API — it cannot run through\n * generateContent. Runs are agents (`agent` field), background execution is\n * mandatory, streams resume via `last_event_id`, and follow-ups chain through\n * `previous_interaction_id`.\n *\n * Wire schema: the current (May-2026) Interactions schema via\n * `@google/genai` >= 2.x — `interaction.created/completed/status_update`,\n * `step.start/delta/stop` over `steps[]`. The pre-2.0 SDK schema\n * (`interaction.start`, `content.*`, `outputs[]`) is rejected by the live\n * API (\"The legacy Interactions API schema is no longer supported\").\n *\n * Transport is isolated behind small functions consuming/returning the SDK's\n * `InteractionSSEEvent` stream so a raw-fetch SSE fallback can be swapped in\n * if the preview API drifts from the installed SDK again.\n */\n\nimport type { GoogleGenAI, Interactions } from \"@google/genai\";\nimport { isAbortError } from \"../core/errors.js\";\nimport { extractRetryAfterMs, isRetryableError } from \"../core/retry.js\";\nimport {\n  GEMINI_RESEARCH_MAX_DURATION_MS,\n  RESEARCH_POLL_INTERVAL_MS,\n} from \"../research/constants.js\";\nimport { ResearchValidationError } from \"../research/errors.js\";\nimport type { ResearchModelSpec } from \"../research/model-spec.js\";\nimport type {\n  ResearchCitation,\n  ResearchEvent,\n  ResearchJobRef,\n  ResearchOptions,\n  ResearchStatus,\n  ResearchStatusSnapshot,\n  ResearchUsage,\n} from \"../research/types.js\";\n\ntype InteractionSSEEvent = Interactions.InteractionSSEEvent;\ntype Interaction = Interactions.Interaction;\ntype Step = Interactions.Step;\ntype Annotation = Interactions.Annotation;\n\n/** Retries for the create call (no interaction exists yet — safe). */\nconst GEMINI_RESEARCH_CREATE_MAX_RETRIES = 3;\n\n// =============================================================================\n// Request building\n// =============================================================================\n\ninterface GeminiAgentRequest {\n  agent: string;\n  input: string;\n  background: boolean;\n  store: boolean;\n  agent_config: { type: \"deep-research\"; thinking_summaries: \"auto\" | \"none\" };\n  system_instruction?: string;\n  previous_interaction_id?: string;\n  [key: string]: unknown;\n}\n\n/**\n * Build the Interactions create request. Background execution is mandatory\n * for deep research — an explicit `background: false` is rejected.\n */\nexport function buildGeminiResearchRequest(\n  options: ResearchOptions,\n  agentId: string,\n): GeminiAgentRequest {\n  if (options.background === false) {\n    throw new ResearchValidationError(\n      \"Gemini deep research requires background execution — background: false is not supported.\",\n    );\n  }\n\n  return {\n    agent: agentId,\n    input: options.query,\n    background: true,\n    store: true,\n    agent_config: {\n      type: \"deep-research\",\n      thinking_summaries: options.reasoning?.includeThinking === false ? \"none\" : \"auto\",\n    },\n    ...(options.systemPrompt ? { system_instruction: options.systemPrompt } : {}),\n    ...(options.previousJobId ? { previous_interaction_id: options.previousJobId } : {}),\n    ...(options.extra ?? {}),\n  };\n}\n\n// =============================================================================\n// Interaction → result extraction (poll/status paths)\n// =============================================================================\n\nconst GEMINI_STATUS_VALUES: ReadonlySet<ResearchStatus> = new Set([\n  \"queued\",\n  \"in_progress\",\n  \"requires_action\",\n  \"completed\",\n  \"failed\",\n  \"cancelled\",\n  \"incomplete\",\n  \"budget_exceeded\",\n]);\n\nexport function mapInteractionStatus(status: string | undefined | null): ResearchStatus {\n  if (status && GEMINI_STATUS_VALUES.has(status as ResearchStatus)) {\n    return status as ResearchStatus;\n  }\n  return \"in_progress\";\n}\n\nfunction annotationToCitation(annotation: Annotation): ResearchCitation | undefined {\n  if (annotation.type !== \"url_citation\" || !annotation.url) return undefined;\n  return {\n    url: annotation.url,\n    title: annotation.title,\n    startIndex: annotation.start_index,\n    endIndex: annotation.end_index,\n  };\n}\n\ninterface ExtractedReport {\n  report: string;\n  citations: ResearchCitation[];\n}\n\n/** Pull report text + citations out of an interaction's model_output steps. */\nexport function extractReportFromInteraction(interaction: Interaction): ExtractedReport {\n  const parts: string[] = [];\n  const citations: ResearchCitation[] = [];\n  for (const step of interaction.steps ?? []) {\n    if (step.type !== \"model_output\") continue;\n    for (const content of step.content ?? []) {\n      if (content.type !== \"text\") continue;\n      parts.push(content.text);\n      for (const annotation of content.annotations ?? []) {\n        const citation = annotationToCitation(annotation);\n        if (citation) citations.push(citation);\n      }\n    }\n  }\n  return { report: parts.join(\"\"), citations };\n}\n\n/**\n * Count search queries in an interaction's steps (poll/status path).\n * The SDK's Usage carries no search count, so this client-side count is what\n * makes the catalog's perThousandSearches pricing apply to Gemini runs. Each\n * google_search_call may fan out multiple queries; count queries, not calls.\n */\nfunction countSearchesInSteps(interaction: Interaction): number {\n  let searches = 0;\n  for (const step of interaction.steps ?? []) {\n    if (step.type === \"google_search_call\") {\n      searches += step.arguments?.queries?.length ?? 1;\n    }\n  }\n  return searches;\n}\n\n/**\n * Map an interaction's usage to ResearchUsage. `streamedSearches` (query\n * fan-out tallied off the stream) takes precedence; the poll/status paths\n * fall back to counting from steps, which a non-stream GET populates.\n */\nexport function usageFromInteraction(\n  interaction: Interaction,\n  streamedSearches?: number,\n): ResearchUsage {\n  const usage = interaction.usage;\n  const searches = streamedSearches ?? countSearchesInSteps(interaction);\n  return {\n    inputTokens: usage?.total_input_tokens ?? 0,\n    outputTokens: usage?.total_output_tokens ?? 0,\n    totalTokens: usage?.total_tokens ?? 0,\n    cachedInputTokens: usage?.total_cached_tokens,\n    reasoningTokens: usage?.total_thought_tokens,\n    ...(searches > 0 ? { searches } : {}),\n  };\n}\n\nfunction doneEventFromInteraction(\n  interaction: Interaction,\n  streamedSearches?: number,\n): ResearchEvent {\n  const { report, citations } = extractReportFromInteraction(interaction);\n  return {\n    type: \"done\",\n    result: {\n      status: mapInteractionStatus(interaction.status),\n      report,\n      citations,\n      usage: usageFromInteraction(interaction, streamedSearches),\n      raw: interaction,\n    },\n  };\n}\n\n// =============================================================================\n// Stream normalization\n// =============================================================================\n\n/**\n * Normalize an Interactions SSE stream into research events.\n *\n * Every event's `cursor` is its `event_id` (the `last_event_id` resume\n * token) — when the API populates it. Live agent streams have been observed\n * omitting `event_id` from the data payload (the token rides the SSE `id:`\n * line, which the SDK's flattened stream drops), so cursors may be absent;\n * resume then falls back to a full replay, which is safe.\n *\n * `fetchFinal` covers another live-observed gap: `interaction.completed`\n * embeds an interaction WITHOUT `usage` or `steps`. When provided, the\n * stored interaction is fetched (a free GET) for authoritative usage and\n * report/citations; on fetch failure the embedded payload is used as-is.\n */\nexport async function* normalizeInteractionsStream(\n  stream: AsyncIterable<InteractionSSEEvent>,\n  fetchFinal?: (id: string) => Promise<Interaction>,\n): AsyncGenerator<ResearchEvent> {\n  // The SDK never reports a search count, and the stream's terminal payload\n  // carries no steps — tally query fan-out off the stream so the catalog's\n  // perThousandSearches pricing applies. Guarded per step index so a\n  // google_search_call arriving as BOTH step.start and a delta counts once.\n  let streamedSearches = 0;\n  const countedSearchSteps = new Set<number>();\n\n  // The lifecycle events carry a partial interaction; SSE-event interactions\n  // and full Interactions are structurally compatible for our extractors.\n  type LifecycleInteraction = Interaction;\n\n  let interactionId: string | undefined;\n\n  for await (const event of stream) {\n    const cursor = event.event_id;\n\n    switch (event.event_type) {\n      case \"interaction.created\": {\n        const interaction = event.interaction as LifecycleInteraction;\n        interactionId = interaction.id;\n        yield { type: \"created\", jobId: interaction.id, cursor, rawEvent: event };\n        yield { type: \"status\", status: mapInteractionStatus(interaction.status), cursor };\n        break;\n      }\n\n      case \"interaction.status_update\":\n        yield {\n          type: \"status\",\n          status: mapInteractionStatus(event.status),\n          cursor,\n          rawEvent: event,\n        };\n        break;\n\n      case \"step.start\": {\n        const step = event.step as Step;\n        if (step.type === \"thought\") {\n          yield { type: \"phase\", phase: \"reasoning\", cursor, rawEvent: event };\n        } else if (step.type === \"model_output\") {\n          yield { type: \"phase\", phase: \"writing\", cursor, rawEvent: event };\n        } else if (step.type === \"google_search_call\") {\n          if (!countedSearchSteps.has(event.index)) {\n            countedSearchSteps.add(event.index);\n            streamedSearches += step.arguments?.queries?.length ?? 1;\n          }\n          yield { type: \"phase\", phase: \"searching\", cursor, rawEvent: event };\n          yield {\n            type: \"search\",\n            action: \"search\",\n            status: \"started\",\n            query: step.arguments?.queries?.join(\"; \"),\n            cursor,\n          };\n        } else if (step.type === \"google_search_result\") {\n          yield { type: \"search\", action: \"search\", status: \"completed\", cursor, rawEvent: event };\n        }\n        break;\n      }\n\n      case \"step.delta\":\n        yield* normalizeDelta(event, cursor, (queries) => {\n          if (!countedSearchSteps.has(event.index)) {\n            countedSearchSteps.add(event.index);\n            streamedSearches += queries;\n          }\n        });\n        break;\n\n      case \"step.stop\":\n        break;\n\n      case \"interaction.completed\": {\n        let interaction = event.interaction as LifecycleInteraction;\n        const finalId = interaction.id ?? interactionId;\n        if (fetchFinal && finalId !== undefined && !interaction.usage?.total_tokens) {\n          try {\n            interaction = await fetchFinal(finalId);\n          } catch {\n            // Free authoritative GET failed — the embedded payload still\n            // yields a valid (if usage-less) terminal sequence.\n          }\n        }\n        const searches = streamedSearches > 0 ? streamedSearches : undefined;\n        yield {\n          type: \"usage\",\n          usage: usageFromInteraction(interaction, searches),\n          cursor,\n          rawEvent: event,\n        };\n        yield { ...doneEventFromInteraction(interaction, searches), cursor };\n        break;\n      }\n\n      case \"error\":\n        // A client_closed_request marker records a PREVIOUS consumer's\n        // disconnect in the interaction's event log — it can never describe\n        // the current consumer, who is provably connected (reading it).\n        // Replay streams opened after a disconnect end with this marker\n        // instead of interaction.completed (live-observed); surfacing it\n        // would mark a healthy run as failed.\n        if (event.error?.code === \"client_closed_request\") break;\n        yield {\n          type: \"error\",\n          error: {\n            message: event.error?.message ?? \"Gemini interaction error\",\n            code: event.error?.code !== undefined ? String(event.error.code) : undefined,\n            retryable: isRetryableError(new Error(event.error?.message ?? \"\")),\n          },\n          cursor,\n          rawEvent: event,\n        };\n        break;\n\n      default: {\n        // Defensive: preview docs are inconsistent (e.g. \"interaction.error\").\n        const type = (event as { event_type?: string }).event_type ?? \"\";\n        if (type.endsWith(\"error\")) {\n          const err = (event as { error?: { message?: string; code?: string } }).error;\n          // Same suppression as the `error` branch: a client_closed_request\n          // marker records a PREVIOUS consumer's disconnect, never the current\n          // (provably connected) one — surfacing it under this alternate shape\n          // would fail a healthy run just the same.\n          if (err?.code === \"client_closed_request\") break;\n          yield {\n            type: \"error\",\n            error: { message: err?.message ?? \"Gemini interaction error\", retryable: false },\n            cursor,\n            rawEvent: event,\n          };\n        }\n        break;\n      }\n    }\n  }\n}\n\nfunction* normalizeDelta(\n  event: Extract<InteractionSSEEvent, { event_type: \"step.delta\" }>,\n  cursor: string | undefined,\n  onSearchCall: (queries: number) => void,\n): Generator<ResearchEvent> {\n  // Widened to a plain discriminator: the preview API has emitted shapes the\n  // SDK union didn't know yet (e.g. docs once showed \"thought\" for\n  // \"thought_summary\").\n  const delta = event.delta as { type: string };\n\n  switch (delta.type) {\n    case \"text\": {\n      const textDelta = delta as unknown as { text: string };\n      yield { type: \"text\", delta: textDelta.text, cursor, rawEvent: event };\n      break;\n    }\n\n    // Citations arrive as dedicated annotation deltas in the current schema.\n    case \"text_annotation_delta\": {\n      const annotationDelta = delta as unknown as { annotations?: Annotation[] };\n      for (const annotation of annotationDelta.annotations ?? []) {\n        const citation = annotationToCitation(annotation);\n        if (citation) {\n          yield { type: \"citation\", citation, cursor, rawEvent: event };\n        }\n      }\n      break;\n    }\n\n    // The SDK emits \"thought_summary\"; some preview docs show \"thought\" —\n    // handle both defensively.\n    case \"thought_summary\":\n    case \"thought\": {\n      const thought = delta as unknown as { content?: { type?: string; text?: string } };\n      const text = thought.content?.type === \"text\" ? (thought.content.text ?? \"\") : \"\";\n      if (text.length > 0) {\n        yield { type: \"thinking\", delta: text, cursor, rawEvent: event };\n      }\n      break;\n    }\n\n    case \"thought_signature\":\n      break;\n\n    case \"google_search_call\": {\n      const call = delta as unknown as { arguments?: { queries?: string[] } };\n      onSearchCall(call.arguments?.queries?.length ?? 1);\n      yield {\n        type: \"search\",\n        action: \"search\",\n        status: \"started\",\n        query: call.arguments?.queries?.join(\"; \"),\n        cursor,\n        rawEvent: event,\n      };\n      break;\n    }\n\n    case \"google_search_result\": {\n      const result = delta as unknown as { result?: Array<{ url?: string }> };\n      yield {\n        type: \"search\",\n        action: \"search\",\n        status: \"completed\",\n        url: result.result?.[0]?.url,\n        cursor,\n        rawEvent: event,\n      };\n      break;\n    }\n\n    case \"url_context_call\": {\n      // SDK shape: URLContextCallArguments = { urls?: string[] } (plural).\n      const call = delta as unknown as { arguments?: { urls?: string[] } };\n      yield {\n        type: \"search\",\n        action: \"open_page\",\n        status: \"started\",\n        url: call.arguments?.urls?.[0],\n        cursor,\n        rawEvent: event,\n      };\n      break;\n    }\n    case \"url_context_result\":\n      yield { type: \"search\", action: \"open_page\", status: \"completed\", cursor, rawEvent: event };\n      break;\n\n    case \"code_execution_call\":\n      yield { type: \"tool\", tool: \"code_interpreter\", status: \"started\", cursor, rawEvent: event };\n      break;\n    case \"code_execution_result\":\n      yield {\n        type: \"tool\",\n        tool: \"code_interpreter\",\n        status: \"completed\",\n        cursor,\n        rawEvent: event,\n      };\n      break;\n\n    case \"file_search_call\":\n      yield { type: \"tool\", tool: \"file_search\", status: \"started\", cursor, rawEvent: event };\n      break;\n    case \"file_search_result\":\n      yield { type: \"tool\", tool: \"file_search\", status: \"completed\", cursor, rawEvent: event };\n      break;\n\n    case \"mcp_server_tool_call\":\n      yield { type: \"tool\", tool: \"mcp\", status: \"started\", cursor, rawEvent: event };\n      break;\n    case \"mcp_server_tool_result\":\n      yield { type: \"tool\", tool: \"mcp\", status: \"completed\", cursor, rawEvent: event };\n      break;\n\n    default:\n      break;\n  }\n}\n\n// =============================================================================\n// Lifecycle: start / resume / status / cancel\n// =============================================================================\n\nfunction abortError(): Error {\n  const error = new Error(\"The operation was aborted\");\n  error.name = \"AbortError\";\n  return error;\n}\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n  return new Promise((resolve, reject) => {\n    if (signal?.aborted) {\n      reject(abortError());\n      return;\n    }\n    const timer = setTimeout(() => {\n      signal?.removeEventListener(\"abort\", onAbort);\n      resolve();\n    }, ms);\n    (timer as { unref?: () => void }).unref?.();\n    const onAbort = () => {\n      clearTimeout(timer);\n      reject(abortError());\n    };\n    signal?.addEventListener(\"abort\", onAbort, { once: true });\n  });\n}\n\nasync function withRetries<T>(\n  fn: () => Promise<T>,\n  maxRetries: number,\n  signal?: AbortSignal,\n): Promise<T> {\n  let attempt = 0;\n  while (true) {\n    try {\n      return await fn();\n    } catch (error) {\n      const err = error instanceof Error ? error : new Error(String(error));\n      if (isAbortError(err) || !isRetryableError(err) || attempt >= maxRetries) {\n        throw err;\n      }\n      attempt += 1;\n      await sleep(extractRetryAfterMs(err) ?? RESEARCH_POLL_INTERVAL_MS, signal);\n    }\n  }\n}\n\nconst requestOptions = (signal?: AbortSignal) => ({\n  timeout: GEMINI_RESEARCH_MAX_DURATION_MS,\n  signal,\n  // The SDK's own retries would fight llmist's retry policy.\n  maxRetries: 0,\n});\n\n/** Structural view of the SDK's interactions client (methods we use). */\ninterface InteractionsApi {\n  create(params: unknown, options?: unknown): Promise<unknown>;\n  get(id: string, params?: unknown, options?: unknown): Promise<unknown>;\n  cancel(id: string, params?: unknown, options?: unknown): Promise<unknown>;\n}\n\ntype InteractionsClient = GoogleGenAI & { interactions: InteractionsApi };\n\n/** Fetch the stored interaction — authoritative usage/steps for terminal events. */\nconst finalInteractionFetcher =\n  (client: GoogleGenAI, signal?: AbortSignal) =>\n  (id: string): Promise<Interaction> =>\n    (client as InteractionsClient).interactions.get(\n      id,\n      undefined,\n      requestOptions(signal),\n    ) as Promise<Interaction>;\n\n/**\n * Follow a normalized stream and, when it ends without a `done` event, poll\n * the stored interaction to a terminal state and emit the real terminal\n * sequence. LIVE-observed: replay streams opened after a client disconnect\n * end with a client_closed_request marker instead of interaction.completed,\n * while the interaction itself runs to completion server-side.\n */\nasync function* withTerminalReconciliation(\n  events: AsyncIterable<ResearchEvent>,\n  client: GoogleGenAI,\n  jobIdHint: string | undefined,\n  signal?: AbortSignal,\n): AsyncGenerator<ResearchEvent> {\n  let jobId = jobIdHint;\n  let sawDone = false;\n  for await (const event of events) {\n    if (event.type === \"created\" && event.jobId !== null) jobId = event.jobId;\n    if (event.type === \"done\") sawDone = true;\n    yield event;\n  }\n  if (sawDone || jobId === undefined) return;\n\n  const fetchInteraction = finalInteractionFetcher(client, signal);\n  while (true) {\n    const interaction = await fetchInteraction(jobId);\n    const status = mapInteractionStatus(interaction.status);\n    yield { type: \"status\", status };\n    if (isTerminalStatus(status)) {\n      yield { type: \"usage\", usage: usageFromInteraction(interaction) };\n      yield doneEventFromInteraction(interaction);\n      return;\n    }\n    await sleep(RESEARCH_POLL_INTERVAL_MS, signal);\n  }\n}\n\n/**\n * Start a deep research interaction as a normalized event stream.\n *\n * Create is deliberately NOT streamed. LIVE-observed: a streaming create\n * ties the background interaction's fate to that HTTP connection — when the\n * create stream disconnects (client abort, network drop), the API cancels\n * the whole run with `client_closed_request` at its next agent checkpoint,\n * even though status polls keep reporting in_progress in the meantime. That\n * silently breaks the abort≠cancel guarantee and burns the run's spend.\n * A plain create returns once the interaction is registered; events then\n * come from a separate GET stream, which is designed to be dropped and\n * resumed (`last_event_id`).\n */\nexport function startGeminiResearch(\n  client: GoogleGenAI,\n  options: ResearchOptions,\n  agentId: string,\n  _spec: ResearchModelSpec | undefined,\n): AsyncIterable<ResearchEvent> {\n  const request = buildGeminiResearchRequest(options, agentId);\n  return (async function* () {\n    const interaction = (await withRetries(\n      () =>\n        (client as InteractionsClient).interactions.create(request, requestOptions(options.signal)),\n      GEMINI_RESEARCH_CREATE_MAX_RETRIES,\n      options.signal,\n    )) as Interaction;\n\n    if (interaction.id === undefined) {\n      throw new Error(\n        \"Gemini interactions.create returned no interaction id — cannot stream events.\",\n      );\n    }\n\n    yield { type: \"created\", jobId: interaction.id, rawEvent: interaction };\n    yield { type: \"status\", status: mapInteractionStatus(interaction.status) };\n\n    const stream = (await (client as InteractionsClient).interactions.get(\n      interaction.id,\n      { stream: true },\n      requestOptions(options.signal),\n    )) as AsyncIterable<InteractionSSEEvent>;\n\n    // The GET stream replays from the beginning, including interaction.created —\n    // drop the duplicate (created was already emitted from the create response).\n    for await (const event of withTerminalReconciliation(\n      normalizeInteractionsStream(stream, finalInteractionFetcher(client, options.signal)),\n      client,\n      interaction.id,\n      options.signal,\n    )) {\n      if (event.type === \"created\") continue;\n      yield event;\n    }\n  })();\n}\n\nfunction isTerminalStatus(status: ResearchStatus): boolean {\n  return (\n    status === \"completed\" ||\n    status === \"failed\" ||\n    status === \"cancelled\" ||\n    status === \"incomplete\" ||\n    status === \"budget_exceeded\"\n  );\n}\n\n/** Resume a background interaction stream from the ref's `last_event_id`. */\nexport function resumeGeminiResearch(\n  client: GoogleGenAI,\n  ref: ResearchJobRef,\n  signal?: AbortSignal,\n): AsyncIterable<ResearchEvent> {\n  return (async function* () {\n    // Status-first: a job that finished while detached may have nothing left\n    // to stream (OpenAI's stream-resume hangs on terminal responses — apply\n    // the same defense here). Emit the terminal sequence from steps instead.\n    const current = (await (client as InteractionsClient).interactions.get(\n      ref.jobId,\n      undefined,\n      requestOptions(signal),\n    )) as Interaction;\n    const status = mapInteractionStatus(current.status);\n    if (isTerminalStatus(status)) {\n      yield { type: \"status\", status };\n      const { report, citations } = extractReportFromInteraction(current);\n      if (report.length > 0) {\n        yield { type: \"text\", delta: report };\n      }\n      for (const citation of citations) {\n        yield { type: \"citation\", citation };\n      }\n      yield { type: \"usage\", usage: usageFromInteraction(current) };\n      yield doneEventFromInteraction(current);\n      return;\n    }\n\n    const stream = (await (client as InteractionsClient).interactions.get(\n      ref.jobId,\n      { stream: true, ...(ref.cursor !== undefined ? { last_event_id: ref.cursor } : {}) },\n      requestOptions(signal),\n    )) as AsyncIterable<InteractionSSEEvent>;\n    yield* withTerminalReconciliation(\n      normalizeInteractionsStream(stream, finalInteractionFetcher(client, signal)),\n      client,\n      ref.jobId,\n      signal,\n    );\n  })();\n}\n\n/** One-shot status poll; returns the terminal result when available. */\nexport async function getGeminiResearchStatus(\n  client: GoogleGenAI,\n  ref: ResearchJobRef,\n): Promise<ResearchStatusSnapshot> {\n  const interaction = (await (client as InteractionsClient).interactions.get(\n    ref.jobId,\n  )) as Interaction;\n  const status = mapInteractionStatus(interaction.status);\n  if (!isTerminalStatus(status)) {\n    return { status };\n  }\n  const { report, citations } = extractReportFromInteraction(interaction);\n  return {\n    status,\n    result: {\n      jobId: interaction.id,\n      provider: \"gemini\",\n      model: ref.model,\n      status,\n      report,\n      citations,\n      usage: usageFromInteraction(interaction),\n      raw: interaction,\n    },\n  };\n}\n\nexport async function cancelGeminiResearch(\n  client: GoogleGenAI,\n  ref: ResearchJobRef,\n): Promise<void> {\n  await (client as InteractionsClient).interactions.cancel(ref.jobId);\n}\n","/**\n * Gemini research agent catalog (Interactions API deep research).\n *\n * Deep research runs as provider-managed *agents* (`agent` field, not\n * `model`) — `kind: \"agent\"`, no chat/context-window semantics. Google\n * publishes no unversioned alias; these preview ids are the current set.\n *\n * Pricing: per-token at standard Gemini rates (base ≤200K-context tier)\n * plus Google Search at $14/1k queries after the free tier. Verified\n * 2026-07-02 against ai.google.dev/gemini-api/docs/pricing.\n */\n\nimport { GEMINI_RESEARCH_MAX_DURATION_MS } from \"../research/constants.js\";\nimport type { ResearchModelSpec } from \"../research/model-spec.js\";\n\nfunction geminiResearchAgent(params: {\n  agentId: string;\n  displayName: string;\n  notes?: string;\n}): ResearchModelSpec {\n  return {\n    provider: \"gemini\",\n    modelId: params.agentId,\n    kind: \"agent\",\n    displayName: params.displayName,\n    // Gemini 3.1 Pro base-tier token rates; >200K-context tier is higher.\n    pricing: { input: 2, output: 12, perThousandSearches: 14 },\n    capabilities: {\n      streaming: true,\n      // The Interactions API requires background execution for deep research.\n      background: true,\n      resumable: true,\n      followUps: true,\n      // Research tools are agent-managed — the tools option is not accepted.\n      tools: [],\n    },\n    // Interactions enforces a 60-minute research cap server-side.\n    maxDurationMs: GEMINI_RESEARCH_MAX_DURATION_MS,\n    metadata: params.notes ? { notes: params.notes } : undefined,\n  };\n}\n\nexport const geminiResearchModels: ResearchModelSpec[] = [\n  geminiResearchAgent({\n    agentId: \"deep-research-preview-04-2026\",\n    displayName: \"Gemini Deep Research (preview 04-2026)\",\n    notes: \"Speed-optimized deep research agent on a Gemini 3.1 Pro core.\",\n  }),\n  geminiResearchAgent({\n    agentId: \"deep-research-max-preview-04-2026\",\n    displayName: \"Gemini Deep Research Max (preview 04-2026)\",\n    notes: \"Maximum-comprehensiveness variant; roughly 2x the searches and tokens per run.\",\n  }),\n  geminiResearchAgent({\n    agentId: \"deep-research-pro-preview-12-2025\",\n    displayName: \"Gemini Deep Research Pro (preview 12-2025)\",\n    notes: \"Original deep research agent (Gemini 3 Pro core); prefer the 04-2026 agents.\",\n  }),\n];\n\nconst byId = new Map(geminiResearchModels.map((spec) => [spec.modelId, spec]));\n\nexport function getGeminiResearchModelSpec(agentId: string): ResearchModelSpec | undefined {\n  return byId.get(agentId);\n}\n\nexport function isGeminiResearchModel(agentId: string): boolean {\n  return byId.has(agentId);\n}\n","/**\n * Google Gemini Speech (TTS) Model Catalog\n *\n * Pricing as of December 2025 (per 1M tokens):\n *\n * Gemini 2.5 Flash Preview TTS:\n * - Input (text): $0.50\n * - Output (audio): $10.00\n *\n * Gemini 2.5 Pro Preview TTS:\n * - Input (text): $1.00\n * - Output (audio): $20.00\n *\n * @see https://ai.google.dev/gemini-api/docs/pricing\n * @see https://ai.google.dev/gemini-api/docs/speech-generation\n */\n\nimport type { AudioFormat, SpeechModelSpec } from \"../core/media-types.js\";\n\n/**\n * Gemini TTS voices (30 prebuilt voices)\n * Each has distinct characteristics like \"Bright\", \"Upbeat\", \"Breathy\", \"Warm\", etc.\n */\nexport const GEMINI_TTS_VOICES = [\n  \"Zephyr\", // Bright\n  \"Puck\", // Upbeat\n  \"Charon\", // Informative\n  \"Kore\", // Firm\n  \"Fenrir\", // Excitable\n  \"Leda\", // Youthful\n  \"Orus\", // Firm\n  \"Aoede\", // Breezy\n  \"Callirrhoe\", // Easy-going\n  \"Autonoe\", // Bright\n  \"Enceladus\", // Breathy\n  \"Iapetus\", // Clear\n  \"Umbriel\", // Easy-going\n  \"Algieba\", // Smooth\n  \"Despina\", // Smooth\n  \"Erinome\", // Clear\n  \"Algenib\", // Gravelly\n  \"Rasalgethi\", // Informative\n  \"Laomedeia\", // Upbeat\n  \"Achernar\", // Soft\n  \"Alnilam\", // Firm\n  \"Schedar\", // Even\n  \"Gacrux\", // Mature\n  \"Pulcherrima\", // Forward\n  \"Achird\", // Friendly\n  \"Zubenelgenubi\", // Casual\n  \"Vindemiatrix\", // Gentle\n  \"Sadachbia\", // Lively\n  \"Sadaltager\", // Knowledgeable\n  \"Sulafat\", // Warm\n] as const;\n\nexport type GeminiTTSVoice = (typeof GEMINI_TTS_VOICES)[number];\n\n/** Gemini TTS supported audio format (PCM only, converted to WAV) */\nexport const GEMINI_TTS_FORMATS: AudioFormat[] = [\"pcm\", \"wav\"];\n\n/**\n * Gemini Speech Model Specifications\n */\nexport const geminiSpeechModels: SpeechModelSpec[] = [\n  {\n    provider: \"gemini\",\n    modelId: \"gemini-2.5-flash-preview-tts\",\n    displayName: \"Gemini 2.5 Flash TTS (Preview)\",\n    pricing: {\n      // $0.50 per 1M input tokens = $0.0000005 per token\n      perInputToken: 0.0000005,\n      // $10.00 per 1M audio output tokens = $0.00001 per token\n      perAudioOutputToken: 0.00001,\n      // Rough estimate: ~$0.01 per minute of audio\n      perMinute: 0.01,\n    },\n    voices: [...GEMINI_TTS_VOICES],\n    formats: GEMINI_TTS_FORMATS,\n    maxInputLength: 8000, // bytes (text + prompt combined)\n    defaultVoice: \"Zephyr\",\n    defaultFormat: \"wav\",\n    features: {\n      multiSpeaker: true,\n      languages: 24,\n      voiceInstructions: true,\n    },\n  },\n  {\n    provider: \"gemini\",\n    modelId: \"gemini-2.5-pro-preview-tts\",\n    displayName: \"Gemini 2.5 Pro TTS (Preview)\",\n    pricing: {\n      // $1.00 per 1M input tokens = $0.000001 per token\n      perInputToken: 0.000001,\n      // $20.00 per 1M audio output tokens = $0.00002 per token\n      perAudioOutputToken: 0.00002,\n      // Rough estimate: ~$0.02 per minute of audio\n      perMinute: 0.02,\n    },\n    voices: [...GEMINI_TTS_VOICES],\n    formats: GEMINI_TTS_FORMATS,\n    maxInputLength: 8000, // bytes\n    defaultVoice: \"Zephyr\",\n    defaultFormat: \"wav\",\n    features: {\n      multiSpeaker: true,\n      languages: 24,\n      voiceInstructions: true,\n    },\n  },\n];\n\n/**\n * Get speech model spec by model ID.\n */\nexport function getGeminiSpeechModelSpec(modelId: string): SpeechModelSpec | undefined {\n  return geminiSpeechModels.find((m) => m.modelId === modelId);\n}\n\n/**\n * Check if a model ID is a Gemini speech model.\n */\nexport function isGeminiSpeechModel(modelId: string): boolean {\n  return geminiSpeechModels.some((m) => m.modelId === modelId);\n}\n\n/**\n * Calculate cost for speech generation.\n *\n * Uses per-minute approximation since exact token counts are hard to predict.\n *\n * @param modelId - The model ID\n * @param characterCount - Number of characters in the input\n * @param estimatedMinutes - Optional: estimated audio duration\n * @returns Cost in USD, or undefined if model not found\n */\nexport function calculateGeminiSpeechCost(\n  modelId: string,\n  characterCount: number,\n  estimatedMinutes?: number,\n): number | undefined {\n  const spec = getGeminiSpeechModelSpec(modelId);\n  if (!spec) return undefined;\n\n  // Use per-minute approximation\n  if (spec.pricing.perMinute !== undefined) {\n    if (estimatedMinutes !== undefined) {\n      return estimatedMinutes * spec.pricing.perMinute;\n    }\n    // Fallback: rough estimate based on ~150 words/min, ~5 chars/word\n    // ~750 chars/min of audio\n    const approxMinutes = characterCount / 750;\n    return approxMinutes * spec.pricing.perMinute;\n  }\n\n  return undefined;\n}\n","import { FunctionCallingConfigMode, GoogleGenAI, Modality } from \"@google/genai\";\nimport type { ContentPart } from \"../core/input-content.js\";\nimport type {\n  ImageGenerationOptions,\n  ImageGenerationResult,\n  ImageModelSpec,\n  SpeechGenerationOptions,\n  SpeechGenerationResult,\n  SpeechModelSpec,\n} from \"../core/media-types.js\";\nimport type { LLMMessage, MessageContent } from \"../core/messages.js\";\nimport { extractMessageText, normalizeMessageContent } from \"../core/messages.js\";\nimport type { ModelSpec } from \"../core/model-catalog.js\";\nimport type {\n  CachingConfig,\n  LLMGenerationOptions,\n  LLMStream,\n  ModelDescriptor,\n  ReasoningConfig,\n  ReasoningEffort,\n} from \"../core/options.js\";\nimport type { ResearchModelSpec } from \"../research/model-spec.js\";\nimport type {\n  ResearchEvent,\n  ResearchJobRef,\n  ResearchOptions,\n  ResearchStatusSnapshot,\n} from \"../research/types.js\";\nimport { BaseProviderAdapter } from \"./base-provider.js\";\nimport { FALLBACK_CHARS_PER_TOKEN } from \"./constants.js\";\nimport { GeminiCacheManager } from \"./gemini-cache-manager.js\";\nimport {\n  calculateGeminiImageCost,\n  geminiImageModels,\n  getGeminiImageModelSpec,\n  isGeminiImageModel,\n} from \"./gemini-image-models.js\";\nimport { GEMINI_MODELS } from \"./gemini-models.js\";\nimport {\n  cancelGeminiResearch,\n  getGeminiResearchStatus,\n  resumeGeminiResearch,\n  startGeminiResearch,\n} from \"./gemini-research.js\";\nimport { geminiResearchModels, isGeminiResearchModel } from \"./gemini-research-models.js\";\nimport {\n  calculateGeminiSpeechCost,\n  geminiSpeechModels,\n  getGeminiSpeechModelSpec,\n  isGeminiSpeechModel,\n} from \"./gemini-speech-models.js\";\nimport { createProviderFromEnv } from \"./utils.js\";\n\n/**\n * Gemini content part - can be text or inline data (images/audio).\n */\ntype GeminiPart = { text: string } | { inlineData: { mimeType: string; data: string } };\n\n/**\n * Gemini content with role and multimodal parts.\n */\ntype GeminiContent = {\n  role: string;\n  parts: GeminiPart[];\n};\n\ntype GeminiChunk = {\n  text?: () => string;\n  candidates?: Array<{\n    content?: {\n      parts?: Array<{ text?: string; thought?: boolean; thoughtSignature?: string }>;\n    };\n    finishReason?: string;\n  }>;\n  usageMetadata?: {\n    promptTokenCount?: number;\n    candidatesTokenCount?: number;\n    totalTokenCount?: number;\n    cachedContentTokenCount?: number;\n    thoughtsTokenCount?: number;\n  };\n};\n\n/** Maps llmist reasoning effort to Gemini 3 Pro thinkingLevel (supports only \"low\" and \"high\") */\nconst GEMINI3_PRO_THINKING_LEVEL: Record<ReasoningEffort, string> = {\n  none: \"low\",\n  low: \"low\",\n  medium: \"high\",\n  high: \"high\",\n  maximum: \"high\",\n};\n\n/** Maps llmist reasoning effort to Gemini 3 Flash thinkingLevel (supports full range) */\nconst GEMINI3_FLASH_THINKING_LEVEL: Record<ReasoningEffort, string> = {\n  none: \"minimal\",\n  low: \"low\",\n  medium: \"medium\",\n  high: \"high\",\n  maximum: \"high\",\n};\n\n/** Maps llmist reasoning effort to Gemini 2.5 thinkingBudget */\nconst GEMINI25_THINKING_BUDGET: Record<ReasoningEffort, number> = {\n  none: 0,\n  low: 2048,\n  medium: 8192,\n  high: 16384,\n  maximum: 24576,\n};\n\n/** Resolve Gemini thinking config from ReasoningConfig */\nfunction resolveGeminiThinkingConfig(\n  reasoning: ReasoningConfig | undefined,\n  modelName: string,\n): Record<string, unknown> | undefined {\n  if (!reasoning?.enabled) return undefined;\n\n  const isGemini3 = modelName.includes(\"gemini-3\");\n\n  if (isGemini3) {\n    // Gemini 3 uses thinkingLevel — Pro only supports \"low\"/\"high\", Flash supports full range\n    const levelMap = modelName.includes(\"pro\")\n      ? GEMINI3_PRO_THINKING_LEVEL\n      : GEMINI3_FLASH_THINKING_LEVEL;\n    return {\n      thinkingConfig: {\n        thinkingLevel: levelMap[reasoning.effort ?? \"medium\"],\n      },\n    };\n  }\n\n  // Gemini 2.5 uses thinkingBudget (numeric)\n  const budget = reasoning.budgetTokens ?? GEMINI25_THINKING_BUDGET[reasoning.effort ?? \"medium\"];\n  return {\n    thinkingConfig: {\n      thinkingBudget: budget,\n    },\n  };\n}\n\nconst GEMINI_ROLE_MAP: Record<LLMMessage[\"role\"], \"user\" | \"model\"> = {\n  system: \"user\",\n  user: \"user\",\n  assistant: \"model\",\n};\n\n/**\n * Wraps raw PCM audio data in a WAV file container.\n *\n * WAV format structure:\n * - RIFF header (12 bytes)\n * - fmt chunk (24 bytes) - describes audio format\n * - data chunk (8 bytes + audio data)\n *\n * @param pcmData - Raw PCM audio samples\n * @param sampleRate - Sample rate in Hz (e.g., 24000)\n * @param bitsPerSample - Bits per sample (e.g., 16)\n * @param numChannels - Number of audio channels (1 = mono, 2 = stereo)\n * @returns ArrayBuffer containing valid WAV file\n */\nfunction wrapPcmInWav(\n  pcmData: Uint8Array,\n  sampleRate: number,\n  bitsPerSample: number,\n  numChannels: number,\n): ArrayBuffer {\n  const byteRate = (sampleRate * numChannels * bitsPerSample) / 8;\n  const blockAlign = (numChannels * bitsPerSample) / 8;\n  const dataSize = pcmData.length;\n  const headerSize = 44;\n  const fileSize = headerSize + dataSize - 8; // File size minus RIFF header\n\n  const buffer = new ArrayBuffer(headerSize + dataSize);\n  const view = new DataView(buffer);\n  const uint8 = new Uint8Array(buffer);\n\n  // RIFF header\n  view.setUint32(0, 0x52494646, false); // \"RIFF\"\n  view.setUint32(4, fileSize, true); // File size - 8\n  view.setUint32(8, 0x57415645, false); // \"WAVE\"\n\n  // fmt chunk\n  view.setUint32(12, 0x666d7420, false); // \"fmt \"\n  view.setUint32(16, 16, true); // fmt chunk size (16 for PCM)\n  view.setUint16(20, 1, true); // Audio format (1 = PCM)\n  view.setUint16(22, numChannels, true); // Number of channels\n  view.setUint32(24, sampleRate, true); // Sample rate\n  view.setUint32(28, byteRate, true); // Byte rate\n  view.setUint16(32, blockAlign, true); // Block align\n  view.setUint16(34, bitsPerSample, true); // Bits per sample\n\n  // data chunk\n  view.setUint32(36, 0x64617461, false); // \"data\"\n  view.setUint32(40, dataSize, true); // Data size\n\n  // Copy PCM data\n  uint8.set(pcmData, headerSize);\n\n  return buffer;\n}\n\nexport class GeminiGenerativeProvider extends BaseProviderAdapter {\n  readonly providerId = \"gemini\" as const;\n  private readonly cacheManager: GeminiCacheManager;\n\n  constructor(client: unknown) {\n    super(client);\n    this.cacheManager = new GeminiCacheManager(client as GoogleGenAI);\n  }\n\n  supports(descriptor: ModelDescriptor): boolean {\n    return descriptor.provider === this.providerId;\n  }\n\n  getModelSpecs() {\n    return GEMINI_MODELS;\n  }\n\n  /**\n   * Override the base stream method to inject cache logic.\n   *\n   * When caching is enabled, we:\n   * 1. Prepare messages as usual\n   * 2. Attempt to get/create a cache for the cacheable prefix\n   * 3. If a cache is available, strip cached contents from the request and add cachedContent ref\n   * 4. Otherwise, proceed normally (graceful degradation)\n   */\n  async *stream(\n    options: LLMGenerationOptions,\n    descriptor: ModelDescriptor,\n    spec?: ModelSpec,\n  ): LLMStream {\n    const preparedMessages = this.prepareMessages(options.messages);\n    const contents = this.convertMessagesToContents(preparedMessages);\n\n    // Attempt caching if configured\n    const cachingConfig = options.caching;\n    let cacheName: string | null = null;\n    let cachedContentCount = 0;\n\n    if (cachingConfig?.enabled) {\n      // Find the index of the last user message in contents\n      let lastUserIndex = -1;\n      for (let i = contents.length - 1; i >= 0; i--) {\n        if (contents[i].role === \"user\") {\n          lastUserIndex = i;\n          break;\n        }\n      }\n\n      const cacheResult = await this.cacheManager.getOrCreateCache(\n        descriptor.name,\n        contents,\n        cachingConfig,\n        lastUserIndex,\n      );\n\n      if (cacheResult) {\n        cacheName = cacheResult.cacheName;\n        cachedContentCount = cacheResult.cachedContentCount;\n      }\n    }\n\n    // Build the API request, potentially with cache reference\n    const payload = this.buildApiRequestFromContents(\n      options,\n      descriptor,\n      spec,\n      contents,\n      cacheName,\n      cachedContentCount,\n    );\n\n    const rawStream = await this.executeStreamRequest(payload, options.signal);\n    yield* this.normalizeProviderStream(rawStream);\n  }\n\n  // =========================================================================\n  // Image Generation\n  // =========================================================================\n\n  getImageModelSpecs(): ImageModelSpec[] {\n    return geminiImageModels;\n  }\n\n  supportsImageGeneration(modelId: string): boolean {\n    return isGeminiImageModel(modelId);\n  }\n\n  async generateImage(options: ImageGenerationOptions): Promise<ImageGenerationResult> {\n    const client = this.client as GoogleGenAI;\n    const spec = getGeminiImageModelSpec(options.model);\n    const isImagenModel = options.model.startsWith(\"imagen\");\n\n    const aspectRatio = options.size ?? spec?.defaultSize ?? \"1:1\";\n    const n = options.n ?? 1;\n\n    if (isImagenModel) {\n      // Use Imagen API for imagen models\n      // Note: safetyFilterLevel and personGeneration can be configured for less restrictive filtering\n      // Valid safetyFilterLevel values: \"BLOCK_NONE\" | \"BLOCK_ONLY_HIGH\" | \"BLOCK_MEDIUM_AND_ABOVE\" | \"BLOCK_LOW_AND_ABOVE\"\n      // Valid personGeneration values: \"ALLOW_ALL\" | \"ALLOW_ADULT\" | \"DONT_ALLOW\"\n      const response = await client.models.generateImages({\n        model: options.model,\n        prompt: options.prompt,\n        config: {\n          numberOfImages: n,\n          aspectRatio: aspectRatio,\n          outputMimeType: options.responseFormat === \"b64_json\" ? \"image/png\" : \"image/jpeg\",\n        },\n      });\n\n      const images = response.generatedImages ?? [];\n      const cost = calculateGeminiImageCost(options.model, aspectRatio, images.length);\n\n      return {\n        // Gemini's imageBytes is already base64 encoded, so use it directly\n        images: images.map((img) => ({\n          b64Json: img.image?.imageBytes ?? undefined,\n        })),\n        model: options.model,\n        usage: {\n          imagesGenerated: images.length,\n          size: aspectRatio,\n          quality: \"standard\",\n        },\n        cost,\n      };\n    }\n    // Use native Gemini image generation for gemini-* models\n    const response = await client.models.generateContent({\n      model: options.model,\n      contents: [{ role: \"user\", parts: [{ text: options.prompt }] }],\n      config: {\n        responseModalities: [Modality.IMAGE, Modality.TEXT],\n      },\n    });\n\n    // Extract images from response\n    const images: Array<{ b64Json?: string; url?: string }> = [];\n    const candidate = response.candidates?.[0];\n    if (candidate?.content?.parts) {\n      for (const part of candidate.content.parts) {\n        if (\"inlineData\" in part && part.inlineData) {\n          images.push({\n            b64Json: part.inlineData.data,\n          });\n        }\n      }\n    }\n\n    const cost = calculateGeminiImageCost(options.model, aspectRatio, images.length);\n\n    return {\n      images,\n      model: options.model,\n      usage: {\n        imagesGenerated: images.length,\n        size: aspectRatio,\n        quality: \"standard\",\n      },\n      cost,\n    };\n  }\n\n  // =========================================================================\n  // Speech Generation\n  // =========================================================================\n\n  getSpeechModelSpecs(): SpeechModelSpec[] {\n    return geminiSpeechModels;\n  }\n\n  supportsSpeechGeneration(modelId: string): boolean {\n    return isGeminiSpeechModel(modelId);\n  }\n\n  async generateSpeech(options: SpeechGenerationOptions): Promise<SpeechGenerationResult> {\n    const client = this.client as GoogleGenAI;\n    const spec = getGeminiSpeechModelSpec(options.model);\n\n    const voice = options.voice ?? spec?.defaultVoice ?? \"Zephyr\";\n\n    // Gemini TTS uses speech configuration\n    const response = await client.models.generateContent({\n      model: options.model,\n      contents: [\n        {\n          role: \"user\",\n          parts: [{ text: options.input }],\n        },\n      ],\n      config: {\n        responseModalities: [Modality.AUDIO],\n        speechConfig: {\n          voiceConfig: {\n            prebuiltVoiceConfig: {\n              voiceName: voice,\n            },\n          },\n        },\n      },\n    });\n\n    // Extract audio from response\n    let pcmData: Uint8Array | undefined;\n    const candidate = response.candidates?.[0];\n    if (candidate?.content?.parts) {\n      for (const part of candidate.content.parts) {\n        if (\"inlineData\" in part && part.inlineData?.data) {\n          // Convert base64 to Uint8Array\n          const base64 = part.inlineData.data;\n          const binary = atob(base64);\n          pcmData = new Uint8Array(binary.length);\n          for (let i = 0; i < binary.length; i++) {\n            pcmData[i] = binary.charCodeAt(i);\n          }\n          break;\n        }\n      }\n    }\n\n    if (!pcmData) {\n      throw new Error(\"No audio data in Gemini TTS response\");\n    }\n\n    // Wrap raw PCM data in WAV headers (Gemini returns 24kHz, 16-bit, mono PCM)\n    const audioData = wrapPcmInWav(pcmData, 24000, 16, 1);\n\n    const cost = calculateGeminiSpeechCost(options.model, options.input.length);\n\n    return {\n      audio: audioData,\n      model: options.model,\n      usage: {\n        characterCount: options.input.length,\n      },\n      cost,\n      format: spec?.defaultFormat ?? \"wav\",\n    };\n  }\n\n  // =========================================================================\n  // Deep Research (Interactions API)\n  // =========================================================================\n\n  getResearchModelSpecs(): ResearchModelSpec[] {\n    return geminiResearchModels;\n  }\n\n  supportsResearch(agentId: string): boolean {\n    return isGeminiResearchModel(agentId);\n  }\n\n  startResearch(\n    options: ResearchOptions,\n    descriptor: ModelDescriptor,\n    spec?: ResearchModelSpec,\n  ): AsyncIterable<ResearchEvent> {\n    return startGeminiResearch(this.client as GoogleGenAI, options, descriptor.name, spec);\n  }\n\n  resumeResearch(ref: ResearchJobRef, signal?: AbortSignal): AsyncIterable<ResearchEvent> {\n    return resumeGeminiResearch(this.client as GoogleGenAI, ref, signal);\n  }\n\n  getResearchStatus(ref: ResearchJobRef): Promise<ResearchStatusSnapshot> {\n    return getGeminiResearchStatus(this.client as GoogleGenAI, ref);\n  }\n\n  cancelResearch(ref: ResearchJobRef): Promise<void> {\n    return cancelGeminiResearch(this.client as GoogleGenAI, ref);\n  }\n\n  protected buildApiRequest(\n    options: LLMGenerationOptions,\n    descriptor: ModelDescriptor,\n    _spec: ModelSpec | undefined,\n    messages: LLMMessage[],\n  ): {\n    model: string;\n    contents: GeminiContent[];\n    config: Record<string, unknown>;\n  } {\n    // Convert messages to Gemini format (system messages become user+model exchanges)\n    const contents = this.convertMessagesToContents(messages);\n    return this.buildApiRequestFromContents(options, descriptor, _spec, contents, null, 0);\n  }\n\n  /**\n   * Build API request from pre-converted Gemini contents.\n   *\n   * When a cache name is provided, the cached prefix is stripped from contents\n   * and the cache reference is added to the config. This tells Gemini to use\n   * the pre-computed KV pairs instead of reprocessing the cached content.\n   */\n  private buildApiRequestFromContents(\n    options: LLMGenerationOptions,\n    descriptor: ModelDescriptor,\n    _spec: ModelSpec | undefined,\n    contents: GeminiContent[],\n    cacheName: string | null,\n    cachedContentCount: number,\n  ): {\n    model: string;\n    contents: GeminiContent[];\n    config: Record<string, unknown>;\n  } {\n    // If cache is active, strip the cached prefix from contents\n    const effectiveContents = cacheName ? contents.slice(cachedContentCount) : contents;\n\n    const generationConfig = this.buildGenerationConfig(options);\n\n    // Resolve thinking config for Gemini 2.5/3 reasoning models\n    const thinkingConfig = resolveGeminiThinkingConfig(options.reasoning, descriptor.name);\n\n    // Build the config object for the new SDK\n    const config: Record<string, unknown> = {\n      // Note: systemInstruction removed - it doesn't work with countTokens()\n      // System messages are now included in contents as user+model exchanges\n      ...(generationConfig ? { ...generationConfig } : {}),\n      // When using cached content, toolConfig lives inside the cache resource.\n      // Gemini rejects requests that include both cachedContent and toolConfig.\n      ...(cacheName\n        ? { cachedContent: cacheName }\n        : {\n            toolConfig: {\n              functionCallingConfig: {\n                mode: FunctionCallingConfigMode.NONE,\n              },\n            },\n          }),\n      ...(thinkingConfig ?? {}),\n      ...options.extra,\n    };\n\n    return {\n      model: descriptor.name,\n      contents: effectiveContents,\n      config,\n    };\n  }\n\n  protected async executeStreamRequest(\n    payload: {\n      model: string;\n      contents: GeminiContent[];\n      config: Record<string, unknown>;\n    },\n    signal?: AbortSignal,\n  ): Promise<AsyncIterable<GeminiChunk>> {\n    const client = this.client as GoogleGenAI;\n    // Gemini SDK uses abortSignal in the config object\n    const streamResponse = await client.models.generateContentStream({\n      ...payload,\n      config: {\n        ...payload.config,\n        ...(signal ? { abortSignal: signal } : {}),\n      },\n    });\n    return streamResponse as unknown as AsyncIterable<GeminiChunk>;\n  }\n\n  /**\n   * Convert LLM messages to Gemini contents format.\n   *\n   * For Gemini, we convert system messages to user+model exchanges instead of\n   * using systemInstruction, because:\n   * 1. systemInstruction doesn't work with countTokens() API\n   * 2. This approach gives perfect token counting accuracy (0% error)\n   * 3. The model receives and follows system instructions identically\n   *\n   * System message: \"You are a helpful assistant\"\n   * Becomes:\n   * - User: \"You are a helpful assistant\"\n   * - Model: \"Understood.\"\n   */\n  private convertMessagesToContents(messages: LLMMessage[]): GeminiContent[] {\n    const expandedMessages: Array<{ role: LLMMessage[\"role\"]; content: MessageContent }> = [];\n\n    for (const message of messages) {\n      if (message.role === \"system\") {\n        // Convert system message to user+model exchange\n        // System messages are always text-only\n        expandedMessages.push({\n          role: \"user\",\n          content: extractMessageText(message.content),\n        });\n        expandedMessages.push({\n          role: \"assistant\",\n          content: \"Understood.\",\n        });\n      } else {\n        expandedMessages.push({\n          role: message.role,\n          content: message.content,\n        });\n      }\n    }\n\n    return this.mergeConsecutiveMessages(expandedMessages);\n  }\n\n  /**\n   * Merge consecutive messages with the same role (required by Gemini).\n   * Handles multimodal content by converting to Gemini's part format.\n   */\n  private mergeConsecutiveMessages(\n    messages: Array<{ role: LLMMessage[\"role\"]; content: MessageContent }>,\n  ): GeminiContent[] {\n    if (messages.length === 0) {\n      return [];\n    }\n\n    const result: GeminiContent[] = [];\n    let currentGroup: GeminiContent | null = null;\n\n    for (const message of messages) {\n      const geminiRole = GEMINI_ROLE_MAP[message.role];\n      const geminiParts = this.convertToGeminiParts(message.content);\n\n      if (currentGroup && currentGroup.role === geminiRole) {\n        // Merge into current group\n        currentGroup.parts.push(...geminiParts);\n      } else {\n        // Start new group\n        if (currentGroup) {\n          result.push(currentGroup);\n        }\n        currentGroup = {\n          role: geminiRole,\n          parts: geminiParts,\n        };\n      }\n    }\n\n    // Push the last group\n    if (currentGroup) {\n      result.push(currentGroup);\n    }\n\n    return result;\n  }\n\n  /**\n   * Convert llmist content to Gemini's part format.\n   * Handles text, images, and audio (Gemini supports all three).\n   */\n  private convertToGeminiParts(content: MessageContent): GeminiPart[] {\n    const parts = normalizeMessageContent(content);\n\n    return parts.map((part) => {\n      if (part.type === \"text\") {\n        return { text: part.text };\n      }\n\n      if (part.type === \"image\") {\n        if (part.source.type === \"url\") {\n          throw new Error(\n            \"Gemini does not support image URLs directly. Please provide base64-encoded image data.\",\n          );\n        }\n        return {\n          inlineData: {\n            mimeType: part.source.mediaType,\n            data: part.source.data,\n          },\n        };\n      }\n\n      if (part.type === \"audio\") {\n        return {\n          inlineData: {\n            mimeType: part.source.mediaType,\n            data: part.source.data,\n          },\n        };\n      }\n\n      throw new Error(`Unsupported content type: ${(part as ContentPart).type}`);\n    });\n  }\n\n  private buildGenerationConfig(options: LLMGenerationOptions) {\n    const config: Record<string, unknown> = {};\n\n    // Only set maxOutputTokens if explicitly provided\n    // Otherwise let Gemini use \"as much as fits\" in the context window\n    if (typeof options.maxTokens === \"number\") {\n      config.maxOutputTokens = options.maxTokens;\n    }\n\n    if (typeof options.temperature === \"number\") {\n      config.temperature = options.temperature;\n    }\n    if (typeof options.topP === \"number\") {\n      config.topP = options.topP;\n    }\n    if (options.stopSequences?.length) {\n      config.stopSequences = options.stopSequences;\n    }\n\n    return Object.keys(config).length > 0 ? config : null;\n  }\n\n  protected async *normalizeProviderStream(iterable: AsyncIterable<unknown>): LLMStream {\n    const stream = iterable as AsyncIterable<GeminiChunk>;\n    for await (const chunk of stream) {\n      // Extract thinking and regular text from parts\n      const { text, thinkingText, thinkingSignature } = this.extractTextAndThinking(chunk);\n\n      // Yield thinking content as ThinkingChunk\n      if (thinkingText) {\n        yield {\n          text: \"\",\n          thinking: {\n            content: thinkingText,\n            type: \"thinking\",\n            signature: thinkingSignature,\n          },\n          rawEvent: chunk,\n        };\n      }\n\n      if (text) {\n        yield { text, rawEvent: chunk };\n      }\n\n      const finishReason = this.extractFinishReason(chunk);\n      const usage = this.extractUsage(chunk);\n\n      if (finishReason || usage) {\n        yield { text: \"\", finishReason, usage, rawEvent: chunk };\n      }\n    }\n  }\n\n  /**\n   * Extract both regular text and thinking text from a chunk.\n   * Gemini marks thinking parts with `thought: true`.\n   */\n  private extractTextAndThinking(chunk: GeminiChunk): {\n    text: string;\n    thinkingText: string;\n    thinkingSignature?: string;\n  } {\n    if (!chunk?.candidates) {\n      return { text: \"\", thinkingText: \"\" };\n    }\n\n    let text = \"\";\n    let thinkingText = \"\";\n    let thinkingSignature: string | undefined;\n\n    for (const candidate of chunk.candidates) {\n      for (const part of candidate.content?.parts ?? []) {\n        if (part.thought) {\n          thinkingText += part.text ?? \"\";\n          if (part.thoughtSignature) {\n            thinkingSignature = part.thoughtSignature;\n          }\n        } else {\n          text += part.text ?? \"\";\n        }\n      }\n    }\n\n    return { text, thinkingText, thinkingSignature };\n  }\n\n  private extractFinishReason(chunk: GeminiChunk): string | null {\n    const candidate = chunk?.candidates?.find((item) => item.finishReason);\n    return candidate?.finishReason ?? null;\n  }\n\n  private extractUsage(chunk: GeminiChunk) {\n    const usageMetadata = chunk?.usageMetadata;\n    if (!usageMetadata) {\n      return undefined;\n    }\n\n    return {\n      inputTokens: usageMetadata.promptTokenCount ?? 0,\n      outputTokens: usageMetadata.candidatesTokenCount ?? 0,\n      totalTokens: usageMetadata.totalTokenCount ?? 0,\n      // Gemini returns cached token count in cachedContentTokenCount\n      cachedInputTokens: usageMetadata.cachedContentTokenCount ?? 0,\n      // Gemini returns thinking tokens in thoughtsTokenCount\n      reasoningTokens: usageMetadata.thoughtsTokenCount,\n    };\n  }\n\n  /**\n   * Count tokens in messages using Gemini's native token counting API.\n   *\n   * This method provides accurate token estimation for Gemini models by:\n   * - Using the SDK's countTokens() method\n   * - Converting system messages to user+model exchanges (same as in generation)\n   * - This gives perfect token counting accuracy (0% error vs actual usage)\n   *\n   * @param messages - The messages to count tokens for\n   * @param descriptor - Model descriptor containing the model name\n   * @param _spec - Optional model specification (currently unused)\n   * @returns Promise resolving to the estimated input token count\n   *\n   * @throws Never throws - falls back to character-based estimation (4 chars/token) on error\n   *\n   * @example\n   * ```typescript\n   * const count = await provider.countTokens(\n   *   [{ role: \"user\", content: \"Hello!\" }],\n   *   { provider: \"gemini\", name: \"gemini-1.5-pro\" }\n   * );\n   * ```\n   */\n  async countTokens(\n    messages: LLMMessage[],\n    descriptor: ModelDescriptor,\n    _spec?: ModelSpec,\n  ): Promise<number> {\n    const client = this.client as GoogleGenAI;\n\n    // Convert messages to Gemini format (same as buildRequestPayload)\n    // This now handles multimodal content\n    const contents = this.convertMessagesToContents(messages);\n\n    // Return 0 for empty messages - Gemini API requires non-empty contents\n    if (!contents || contents.length === 0) {\n      return 0;\n    }\n\n    try {\n      // Use Gemini's count_tokens method\n      const response = await client.models.countTokens({\n        model: descriptor.name,\n        contents,\n        // Note: systemInstruction not used - it's not supported by countTokens()\n        // and would cause a 2100% token counting error\n      });\n      return response.totalTokens ?? 0;\n    } catch (error) {\n      // Log the error for debugging\n      console.warn(\n        `Token counting failed for ${descriptor.name}, using fallback estimation:`,\n        error,\n      );\n      // Fallback to rough estimation if API fails\n      // For multimodal, extract text and estimate; images/audio add tokens\n      let totalChars = 0;\n      let mediaCount = 0;\n      for (const msg of messages) {\n        const parts = normalizeMessageContent(msg.content);\n        for (const part of parts) {\n          if (part.type === \"text\") {\n            totalChars += part.text.length;\n          } else if (part.type === \"image\" || part.type === \"audio\") {\n            mediaCount++;\n          }\n        }\n      }\n      // Gemini charges ~258 tokens per image/audio (for standard size).\n      // Source: https://ai.google.dev/gemini-api/docs/tokens\n      // Actual cost varies by media type and dimensions.\n      return Math.ceil(totalChars / FALLBACK_CHARS_PER_TOKEN) + mediaCount * 258;\n    }\n  }\n}\n\nexport function createGeminiProviderFromEnv(): GeminiGenerativeProvider | null {\n  return createProviderFromEnv(\"GEMINI_API_KEY\", GoogleGenAI, GeminiGenerativeProvider);\n}\n","/**\n * Hugging Face Model Specifications\n *\n * Curated list of trending and popular open-source models available on Hugging Face,\n * with verified specifications and pricing.\n *\n * Pricing: Free tier via serverless inference (router.huggingface.co)\n * Dedicated endpoints have separate pricing: https://huggingface.co/pricing#endpoints\n *\n * Model specs sourced from:\n * - Trending models on https://huggingface.co/models\n * - HF Inference Providers documentation\n * - Model cards and specifications\n *\n * Last updated: 2026-01-11 (based on current HF trending models)\n */\n\nimport type { ModelSpec } from \"../core/model-catalog.js\";\n\nexport const HUGGINGFACE_MODELS: ModelSpec[] = [\n  // ==========================================================================\n  // DeepSeek Models (Top Trending - January 2026)\n  // ==========================================================================\n\n  {\n    provider: \"huggingface\",\n    modelId: \"deepseek-ai/DeepSeek-V3.2\",\n    displayName: \"DeepSeek V3.2\",\n    contextWindow: 163_840,\n    maxOutputTokens: 65_536,\n    pricing: {\n      input: 0.269,\n      output: 0.4,\n      cachedInput: 0.1345,\n    },\n    knowledgeCutoff: \"2024-12\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: false,\n      reasoning: true,\n      structuredOutputs: true,\n    },\n    metadata: {\n      family: \"DeepSeek V3\",\n      releaseDate: \"2025-12\",\n      notes:\n        \"685B MoE model optimized for faster, lower-cost inference with strong general reasoning and tool use. Pricing via Novita AI.\",\n    },\n  },\n\n  {\n    provider: \"huggingface\",\n    modelId: \"deepseek-ai/DeepSeek-R1\",\n    displayName: \"DeepSeek R1\",\n    contextWindow: 64_000,\n    maxOutputTokens: 8_192,\n    pricing: {\n      input: 0.0,\n      output: 0.0,\n    },\n    knowledgeCutoff: \"2024-11\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: false,\n      reasoning: true,\n    },\n    metadata: {\n      family: \"DeepSeek\",\n      releaseDate: \"2025-01\",\n      notes:\n        \"MoE reasoning model that excels at math, logic, and coding with step-by-step reasoning.\",\n    },\n  },\n\n  {\n    provider: \"huggingface\",\n    modelId: \"deepseek-ai/DeepSeek-V3\",\n    displayName: \"DeepSeek V3\",\n    contextWindow: 64_000,\n    maxOutputTokens: 4_096,\n    pricing: {\n      input: 0.0,\n      output: 0.0,\n    },\n    knowledgeCutoff: \"2024-11\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: false,\n    },\n    metadata: {\n      family: \"DeepSeek\",\n      releaseDate: \"2024-12\",\n      notes: \"Mixture-of-experts model with strong coding and reasoning capabilities.\",\n    },\n  },\n\n  {\n    provider: \"huggingface\",\n    modelId: \"deepseek-ai/DeepSeek-Coder-V2-Instruct\",\n    displayName: \"DeepSeek Coder V2 Instruct\",\n    contextWindow: 128_000,\n    maxOutputTokens: 4_096,\n    pricing: {\n      input: 0.0,\n      output: 0.0,\n    },\n    knowledgeCutoff: \"2024-06\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: false,\n    },\n    metadata: {\n      family: \"DeepSeek Coder\",\n      releaseDate: \"2024-06\",\n      notes: \"Specialized for code generation and programming tasks. Supports 338 languages.\",\n    },\n  },\n\n  // ==========================================================================\n  // Meta Llama Models (Most Widely Supported)\n  // ==========================================================================\n\n  {\n    provider: \"huggingface\",\n    modelId: \"meta-llama/Llama-3.1-8B-Instruct\",\n    displayName: \"Llama 3.1 8B Instruct\",\n    contextWindow: 128_000,\n    maxOutputTokens: 4_096,\n    pricing: {\n      input: 0.0,\n      output: 0.0,\n    },\n    knowledgeCutoff: \"2023-12\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: false,\n    },\n    metadata: {\n      family: \"Llama 3.1\",\n      releaseDate: \"2024-07\",\n      notes:\n        \"Most widely supported and downloaded model on HF. Multi-provider support. Efficient 8B model with strong instruction following.\",\n    },\n  },\n\n  {\n    provider: \"huggingface\",\n    modelId: \"meta-llama/Llama-3.3-70B-Instruct\",\n    displayName: \"Llama 3.3 70B Instruct\",\n    contextWindow: 128_000,\n    maxOutputTokens: 8_192,\n    pricing: {\n      input: 0.0,\n      output: 0.0,\n    },\n    knowledgeCutoff: \"2023-12\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: false,\n    },\n    metadata: {\n      family: \"Llama 3.3\",\n      releaseDate: \"2024-12\",\n      notes: \"Multilingual LLM with strong performance across benchmarks.\",\n    },\n  },\n\n  {\n    provider: \"huggingface\",\n    modelId: \"meta-llama/Llama-3.2-11B-Vision-Instruct\",\n    displayName: \"Llama 3.2 11B Vision Instruct\",\n    contextWindow: 128_000,\n    maxOutputTokens: 4_096,\n    pricing: {\n      input: 0.0,\n      output: 0.0,\n    },\n    knowledgeCutoff: \"2024-09\",\n    features: {\n      streaming: true,\n      functionCalling: false,\n      vision: true, // Vision support will be enabled in Phase 2\n    },\n    metadata: {\n      family: \"Llama 3.2\",\n      releaseDate: \"2024-09\",\n      notes:\n        \"Multimodal model with vision capabilities. Vision support in llmist coming in Phase 2.\",\n    },\n  },\n\n  // ==========================================================================\n  // Mistral Models\n  // ==========================================================================\n\n  {\n    provider: \"huggingface\",\n    modelId: \"mistralai/Mistral-7B-Instruct-v0.3\",\n    displayName: \"Mistral 7B Instruct v0.3\",\n    contextWindow: 32_768,\n    maxOutputTokens: 4_096,\n    pricing: {\n      input: 0.0,\n      output: 0.0,\n    },\n    knowledgeCutoff: \"2023-09\",\n    features: {\n      streaming: true,\n      functionCalling: false,\n      vision: false,\n    },\n    metadata: {\n      family: \"Mistral\",\n      releaseDate: \"2024-05\",\n      notes: \"Fast and efficient 7B model with extended context window.\",\n    },\n  },\n\n  {\n    provider: \"huggingface\",\n    modelId: \"mistralai/Mixtral-8x7B-Instruct-v0.1\",\n    displayName: \"Mixtral 8x7B Instruct v0.1\",\n    contextWindow: 32_768,\n    maxOutputTokens: 4_096,\n    pricing: {\n      input: 0.0,\n      output: 0.0,\n    },\n    knowledgeCutoff: \"2023-12\",\n    features: {\n      streaming: true,\n      functionCalling: false,\n      vision: false,\n    },\n    metadata: {\n      family: \"Mixtral\",\n      releaseDate: \"2023-12\",\n      notes: \"Mixture-of-experts model with 8 experts, only 2 active per token for efficiency.\",\n    },\n  },\n\n  {\n    provider: \"huggingface\",\n    modelId: \"mistralai/Mistral-Nemo-Instruct-2407\",\n    displayName: \"Mistral Nemo Instruct 2407\",\n    contextWindow: 128_000,\n    maxOutputTokens: 4_096,\n    pricing: {\n      input: 0.0,\n      output: 0.0,\n    },\n    knowledgeCutoff: \"2024-04\",\n    features: {\n      streaming: true,\n      functionCalling: false,\n      vision: false,\n    },\n    metadata: {\n      family: \"Mistral Nemo\",\n      releaseDate: \"2024-07\",\n      notes: \"12B model with 128k context, developed in partnership with NVIDIA.\",\n    },\n  },\n\n  // ==========================================================================\n  // Qwen Models (Fast Inference, Top Tier)\n  // ==========================================================================\n\n  {\n    provider: \"huggingface\",\n    modelId: \"Qwen/Qwen3-Next-80B-A3B-Instruct\",\n    displayName: \"Qwen 3 Next 80B Instruct\",\n    contextWindow: 200_000,\n    maxOutputTokens: 8_192,\n    pricing: {\n      input: 0.0,\n      output: 0.0,\n    },\n    knowledgeCutoff: \"2024-12\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: false,\n      reasoning: true,\n      structuredOutputs: true,\n    },\n    metadata: {\n      family: \"Qwen 3\",\n      releaseDate: \"2025-12\",\n      notes:\n        \"Instruction-tuned Qwen with enhanced multilingual reasoning, coding, and long context capabilities.\",\n    },\n  },\n\n  {\n    provider: \"huggingface\",\n    modelId: \"Qwen/Qwen2.5-7B-Instruct\",\n    displayName: \"Qwen 2.5 7B Instruct\",\n    contextWindow: 128_000,\n    maxOutputTokens: 8_192,\n    pricing: {\n      input: 0.0,\n      output: 0.0,\n    },\n    knowledgeCutoff: \"2024-09\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: false,\n    },\n    metadata: {\n      family: \"Qwen 2.5\",\n      releaseDate: \"2024-09\",\n      notes:\n        \"Fast inference with tool calling support. Efficient 7B model with strong multilingual support.\",\n    },\n  },\n\n  {\n    provider: \"huggingface\",\n    modelId: \"Qwen/Qwen2.5-72B-Instruct\",\n    displayName: \"Qwen 2.5 72B Instruct\",\n    contextWindow: 128_000,\n    maxOutputTokens: 8_192,\n    pricing: {\n      input: 0.0,\n      output: 0.0,\n    },\n    knowledgeCutoff: \"2024-09\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: false,\n    },\n    metadata: {\n      family: \"Qwen 2.5\",\n      releaseDate: \"2024-09\",\n      notes: \"Multilingual model with excellent coding and math capabilities.\",\n    },\n  },\n\n  {\n    provider: \"huggingface\",\n    modelId: \"Qwen/Qwen3-4B-Instruct-2507\",\n    displayName: \"Qwen 3 4B Instruct\",\n    contextWindow: 32_000,\n    maxOutputTokens: 4_096,\n    pricing: {\n      input: 0.0,\n      output: 0.0,\n    },\n    knowledgeCutoff: \"2025-06\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: false,\n    },\n    metadata: {\n      family: \"Qwen 3\",\n      releaseDate: \"2025-07\",\n      notes:\n        \"Ultra-lightweight model optimized for mobile and edge deployment with tool calling support.\",\n    },\n  },\n\n  {\n    provider: \"huggingface\",\n    modelId: \"Qwen/Qwen2.5-Coder-32B-Instruct\",\n    displayName: \"Qwen 2.5 Coder 32B Instruct\",\n    contextWindow: 128_000,\n    maxOutputTokens: 8_192,\n    pricing: {\n      input: 0.0,\n      output: 0.0,\n    },\n    knowledgeCutoff: \"2024-09\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: false,\n    },\n    metadata: {\n      family: \"Qwen 2.5 Coder\",\n      releaseDate: \"2024-11\",\n      notes: \"Specialized coding model with support for 92 programming languages.\",\n    },\n  },\n\n  {\n    provider: \"huggingface\",\n    modelId: \"Qwen/Qwen2.5-7B-Instruct\",\n    displayName: \"Qwen 2.5 7B Instruct\",\n    contextWindow: 128_000,\n    maxOutputTokens: 8_192,\n    pricing: {\n      input: 0.0,\n      output: 0.0,\n    },\n    knowledgeCutoff: \"2024-09\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: false,\n    },\n    metadata: {\n      family: \"Qwen 2.5\",\n      releaseDate: \"2024-09\",\n      notes: \"Efficient 7B model with strong multilingual support.\",\n    },\n  },\n\n  {\n    provider: \"huggingface\",\n    modelId: \"Qwen/Qwen2-VL-72B-Instruct\",\n    displayName: \"Qwen 2 VL 72B Instruct\",\n    contextWindow: 32_768,\n    maxOutputTokens: 8_192,\n    pricing: {\n      input: 0.0,\n      output: 0.0,\n    },\n    knowledgeCutoff: \"2024-06\",\n    features: {\n      streaming: true,\n      functionCalling: false,\n      vision: true, // Vision support coming in Phase 2\n    },\n    metadata: {\n      family: \"Qwen 2 VL\",\n      releaseDate: \"2024-08\",\n      notes: \"Multimodal vision-language model. Vision support in llmist coming in Phase 2.\",\n    },\n  },\n\n  // ==========================================================================\n  // DeepSeek Models\n  // ==========================================================================\n\n  {\n    provider: \"huggingface\",\n    modelId: \"deepseek-ai/DeepSeek-V3\",\n    displayName: \"DeepSeek V3\",\n    contextWindow: 64_000,\n    maxOutputTokens: 4_096,\n    pricing: {\n      input: 0.0,\n      output: 0.0,\n    },\n    knowledgeCutoff: \"2024-11\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: false,\n    },\n    metadata: {\n      family: \"DeepSeek\",\n      releaseDate: \"2024-12\",\n      notes: \"Mixture-of-experts model with strong coding and reasoning capabilities.\",\n    },\n  },\n\n  {\n    provider: \"huggingface\",\n    modelId: \"deepseek-ai/DeepSeek-R1\",\n    displayName: \"DeepSeek R1\",\n    contextWindow: 64_000,\n    maxOutputTokens: 8_192,\n    pricing: {\n      input: 0.0,\n      output: 0.0,\n    },\n    knowledgeCutoff: \"2024-11\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: false,\n      reasoning: true,\n    },\n    metadata: {\n      family: \"DeepSeek\",\n      releaseDate: \"2025-01\",\n      notes: \"Reasoning-focused model with chain-of-thought capabilities.\",\n    },\n  },\n\n  {\n    provider: \"huggingface\",\n    modelId: \"deepseek-ai/DeepSeek-Coder-V2-Instruct\",\n    displayName: \"DeepSeek Coder V2 Instruct\",\n    contextWindow: 128_000,\n    maxOutputTokens: 4_096,\n    pricing: {\n      input: 0.0,\n      output: 0.0,\n    },\n    knowledgeCutoff: \"2024-06\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: false,\n    },\n    metadata: {\n      family: \"DeepSeek Coder\",\n      releaseDate: \"2024-06\",\n      notes: \"Specialized for code generation and programming tasks. Supports 338 languages.\",\n    },\n  },\n\n  // ==========================================================================\n  // Google Gemma Models\n  // ==========================================================================\n\n  {\n    provider: \"huggingface\",\n    modelId: \"google/gemma-2-9b-it\",\n    displayName: \"Gemma 2 9B Instruct\",\n    contextWindow: 8_192,\n    maxOutputTokens: 2_048,\n    pricing: {\n      input: 0.0,\n      output: 0.0,\n    },\n    knowledgeCutoff: \"2024-02\",\n    features: {\n      streaming: true,\n      functionCalling: false,\n      vision: false,\n    },\n    metadata: {\n      family: \"Gemma 2\",\n      releaseDate: \"2024-06\",\n      notes: \"Lightweight model from Google, efficient for edge deployment.\",\n    },\n  },\n\n  {\n    provider: \"huggingface\",\n    modelId: \"google/gemma-2-27b-it\",\n    displayName: \"Gemma 2 27B Instruct\",\n    contextWindow: 8_192,\n    maxOutputTokens: 4_096,\n    pricing: {\n      input: 0.0,\n      output: 0.0,\n    },\n    knowledgeCutoff: \"2024-02\",\n    features: {\n      streaming: true,\n      functionCalling: false,\n      vision: false,\n    },\n    metadata: {\n      family: \"Gemma 2\",\n      releaseDate: \"2024-06\",\n      notes: \"Larger Gemma variant with improved capabilities.\",\n    },\n  },\n\n  // ==========================================================================\n  // Microsoft Phi Models\n  // ==========================================================================\n\n  {\n    provider: \"huggingface\",\n    modelId: \"microsoft/Phi-3-mini-4k-instruct\",\n    displayName: \"Phi-3 Mini 4K Instruct\",\n    contextWindow: 4_096,\n    maxOutputTokens: 2_048,\n    pricing: {\n      input: 0.0,\n      output: 0.0,\n    },\n    knowledgeCutoff: \"2023-10\",\n    features: {\n      streaming: true,\n      functionCalling: false,\n      vision: false,\n    },\n    metadata: {\n      family: \"Phi-3\",\n      releaseDate: \"2024-04\",\n      notes: \"Small language model (3.8B) optimized for mobile and edge devices.\",\n    },\n  },\n\n  {\n    provider: \"huggingface\",\n    modelId: \"microsoft/Phi-3-medium-4k-instruct\",\n    displayName: \"Phi-3 Medium 4K Instruct\",\n    contextWindow: 4_096,\n    maxOutputTokens: 2_048,\n    pricing: {\n      input: 0.0,\n      output: 0.0,\n    },\n    knowledgeCutoff: \"2023-10\",\n    features: {\n      streaming: true,\n      functionCalling: false,\n      vision: false,\n    },\n    metadata: {\n      family: \"Phi-3\",\n      releaseDate: \"2024-04\",\n      notes: \"14B parameter model balancing size and performance.\",\n    },\n  },\n\n  // ==========================================================================\n  // Cohere Command Models\n  // ==========================================================================\n\n  {\n    provider: \"huggingface\",\n    modelId: \"CohereForAI/c4ai-command-r-plus-08-2024\",\n    displayName: \"Command R+ (Aug 2024)\",\n    contextWindow: 128_000,\n    maxOutputTokens: 4_096,\n    pricing: {\n      input: 0.0,\n      output: 0.0,\n    },\n    knowledgeCutoff: \"2024-06\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: false,\n    },\n    metadata: {\n      family: \"Command R\",\n      releaseDate: \"2024-08\",\n      notes: \"RAG-optimized model with strong multilingual capabilities (23 languages).\",\n    },\n  },\n\n  {\n    provider: \"huggingface\",\n    modelId: \"CohereForAI/c4ai-command-r-08-2024\",\n    displayName: \"Command R (Aug 2024)\",\n    contextWindow: 128_000,\n    maxOutputTokens: 4_096,\n    pricing: {\n      input: 0.0,\n      output: 0.0,\n    },\n    knowledgeCutoff: \"2024-06\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: false,\n    },\n    metadata: {\n      family: \"Command R\",\n      releaseDate: \"2024-08\",\n      notes: \"Efficient model optimized for retrieval-augmented generation (RAG) tasks.\",\n    },\n  },\n\n  // ==========================================================================\n  // Alibaba Qwen Models (Additional)\n  // ==========================================================================\n\n  {\n    provider: \"huggingface\",\n    modelId: \"Qwen/Qwen2.5-Coder-32B-Instruct\",\n    displayName: \"Qwen 2.5 Coder 32B Instruct\",\n    contextWindow: 128_000,\n    maxOutputTokens: 8_192,\n    pricing: {\n      input: 0.0,\n      output: 0.0,\n    },\n    knowledgeCutoff: \"2024-09\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: false,\n    },\n    metadata: {\n      family: \"Qwen 2.5 Coder\",\n      releaseDate: \"2024-11\",\n      notes: \"Specialized coding model with support for 92 programming languages.\",\n    },\n  },\n\n  // ==========================================================================\n  // NousResearch Models\n  // ==========================================================================\n\n  {\n    provider: \"huggingface\",\n    modelId: \"NousResearch/Hermes-3-Llama-3.1-8B\",\n    displayName: \"Hermes 3 Llama 3.1 8B\",\n    contextWindow: 128_000,\n    maxOutputTokens: 4_096,\n    pricing: {\n      input: 0.0,\n      output: 0.0,\n    },\n    knowledgeCutoff: \"2024-07\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: false,\n    },\n    metadata: {\n      family: \"Hermes\",\n      releaseDate: \"2024-08\",\n      notes:\n        \"Fine-tuned Llama 3.1 with enhanced function calling and structured output capabilities.\",\n    },\n  },\n\n  // ==========================================================================\n  // StabilityAI Models\n  // ==========================================================================\n\n  {\n    provider: \"huggingface\",\n    modelId: \"stabilityai/stablelm-2-12b-chat\",\n    displayName: \"StableLM 2 12B Chat\",\n    contextWindow: 4_096,\n    maxOutputTokens: 2_048,\n    pricing: {\n      input: 0.0,\n      output: 0.0,\n    },\n    knowledgeCutoff: \"2023-11\",\n    features: {\n      streaming: true,\n      functionCalling: false,\n      vision: false,\n    },\n    metadata: {\n      family: \"StableLM 2\",\n      releaseDate: \"2024-01\",\n      notes: \"Efficient chat model with multilingual support.\",\n    },\n  },\n\n  // ==========================================================================\n  // Databricks Models\n  // ==========================================================================\n\n  {\n    provider: \"huggingface\",\n    modelId: \"databricks/dbrx-instruct\",\n    displayName: \"DBRX Instruct\",\n    contextWindow: 32_768,\n    maxOutputTokens: 4_096,\n    pricing: {\n      input: 0.0,\n      output: 0.0,\n    },\n    knowledgeCutoff: \"2023-12\",\n    features: {\n      streaming: true,\n      functionCalling: false,\n      vision: false,\n    },\n    metadata: {\n      family: \"DBRX\",\n      releaseDate: \"2024-03\",\n      notes: \"Mixture-of-experts model (132B params, 36B active) optimized for efficiency.\",\n    },\n  },\n\n  // ==========================================================================\n  // OpenAI Community Models\n  // ==========================================================================\n\n  {\n    provider: \"huggingface\",\n    modelId: \"openai/gpt-oss-120b\",\n    displayName: \"GPT OSS 120B\",\n    contextWindow: 8_192,\n    maxOutputTokens: 2_048,\n    pricing: {\n      input: 0.0,\n      output: 0.0,\n    },\n    knowledgeCutoff: \"2023-09\",\n    features: {\n      streaming: true,\n      functionCalling: false,\n      vision: false,\n    },\n    metadata: {\n      family: \"GPT OSS\",\n      releaseDate: \"2024-12\",\n      notes: \"Open-source GPT-style model from OpenAI research.\",\n    },\n  },\n\n  // ==========================================================================\n  // MiniMax Models\n  // ==========================================================================\n\n  {\n    provider: \"huggingface\",\n    modelId: \"MiniMaxAI/MiniMax-M2.1\",\n    displayName: \"MiniMax M2.1\",\n    contextWindow: 204_800,\n    maxOutputTokens: 131_072,\n    pricing: {\n      input: 0.3,\n      output: 1.2,\n    },\n    knowledgeCutoff: \"2025-01\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: false,\n    },\n    metadata: {\n      family: \"MiniMax\",\n      releaseDate: \"2025-01\",\n      notes: \"Large-scale model with strong multilingual and reasoning capabilities.\",\n    },\n  },\n];\n","/**\n * OpenAI-Compatible Provider Base Class\n *\n * Base class for \"meta-providers\" that expose an OpenAI-compatible API\n * but route to multiple underlying models/providers. Examples include:\n * - OpenRouter (openrouter.ai)\n * - TogetherAI (together.ai)\n * - Fireworks (fireworks.ai)\n * - Anyscale (anyscale.com)\n *\n * This base class provides:\n * - OpenAI SDK integration with custom baseURL\n * - Message conversion to OpenAI format\n * - Streaming normalization\n * - Character-based token estimation\n * - Custom header support for analytics/tracking\n * - Pluggable error enhancement\n *\n * Subclasses implement:\n * - providerId and providerAlias\n * - getModelSpecs() for available models\n * - getCustomHeaders() for provider-specific headers\n * - enhanceError() for provider-specific error messages\n * - buildProviderSpecificParams() for provider-specific request options\n */\n\nimport OpenAI from \"openai\";\nimport type {\n  ChatCompletionChunk,\n  ChatCompletionContentPart,\n  ChatCompletionMessageParam,\n} from \"openai/resources/chat/completions\";\nimport { get_encoding } from \"tiktoken\";\nimport type { ContentPart, ImageContentPart } from \"../core/input-content.js\";\nimport type { LLMMessage, MessageContent } from \"../core/messages.js\";\nimport { extractMessageText, normalizeMessageContent } from \"../core/messages.js\";\nimport type { ModelSpec } from \"../core/model-catalog.js\";\nimport type { LLMGenerationOptions, LLMStream, ModelDescriptor } from \"../core/options.js\";\nimport { BaseProviderAdapter } from \"./base-provider.js\";\nimport { FALLBACK_CHARS_PER_TOKEN } from \"./constants.js\";\n\nconst ROLE_MAP: Record<LLMMessage[\"role\"], \"system\" | \"user\" | \"assistant\"> = {\n  system: \"system\",\n  user: \"user\",\n  assistant: \"assistant\",\n};\n\n/**\n * Base configuration for OpenAI-compatible providers.\n * Subclasses can extend this with provider-specific options.\n */\nexport interface OpenAICompatibleConfig {\n  /**\n   * Optional custom headers to include in all requests.\n   * Useful for analytics/tracking.\n   */\n  customHeaders?: Record<string, string>;\n}\n\n/**\n * Abstract base class for providers using OpenAI-compatible APIs.\n *\n * @example\n * ```typescript\n * class MyMetaProvider extends OpenAICompatibleProvider<MyConfig> {\n *   readonly providerId = \"myprovider\" as const;\n *   protected readonly providerAlias = \"mp\";\n *\n *   getModelSpecs() { return MY_MODELS; }\n *\n *   protected getCustomHeaders(): Record<string, string> {\n *     return { \"X-My-Header\": this.config.myValue };\n *   }\n *\n *   protected enhanceError(error: unknown): Error {\n *     // Provider-specific error handling\n *   }\n * }\n * ```\n */\nexport abstract class OpenAICompatibleProvider<\n  TConfig extends OpenAICompatibleConfig = OpenAICompatibleConfig,\n> extends BaseProviderAdapter {\n  abstract readonly providerId: string;\n\n  /**\n   * Short alias for the provider (e.g., \"or\" for openrouter, \"hf\" for huggingface).\n   * If not set, only the full providerId is accepted.\n   */\n  protected readonly providerAlias?: string;\n\n  protected readonly config: TConfig;\n\n  constructor(client: OpenAI, config: TConfig) {\n    super(client);\n    this.config = config;\n  }\n\n  /**\n   * Check if this provider supports the given model descriptor.\n   * Accepts both the full providerId and the short alias.\n   */\n  supports(descriptor: ModelDescriptor): boolean {\n    return (\n      descriptor.provider === this.providerId ||\n      (this.providerAlias !== undefined && descriptor.provider === this.providerAlias)\n    );\n  }\n\n  /**\n   * Return the model specs for this provider.\n   * Must be implemented by subclasses.\n   */\n  abstract getModelSpecs(): ModelSpec[];\n\n  /**\n   * Get custom headers to include in requests.\n   * Override in subclasses for provider-specific headers.\n   */\n  protected getCustomHeaders(): Record<string, string> {\n    return this.config.customHeaders ?? {};\n  }\n\n  /**\n   * Enhance error messages with provider-specific guidance.\n   * Override in subclasses for better error messages.\n   */\n  protected enhanceError(error: unknown): Error {\n    if (error instanceof Error) {\n      return error;\n    }\n    return new Error(String(error));\n  }\n\n  /**\n   * Build provider-specific request parameters.\n   * Override in subclasses to add custom parameters from `extra`.\n   *\n   * @param extra - The extra options from LLMGenerationOptions\n   * @returns Object with provider-specific params to merge into the request\n   */\n  protected buildProviderSpecificParams(\n    _extra: Record<string, unknown> | undefined,\n  ): Record<string, unknown> {\n    return {};\n  }\n\n  protected buildApiRequest(\n    options: LLMGenerationOptions,\n    descriptor: ModelDescriptor,\n    _spec: ModelSpec | undefined,\n    messages: LLMMessage[],\n  ): Parameters<OpenAI[\"chat\"][\"completions\"][\"create\"]>[0] {\n    const { maxTokens, temperature, topP, stopSequences, extra } = options;\n\n    // Build base request\n    const request: Record<string, unknown> = {\n      model: descriptor.name,\n      messages: messages.map((message) => this.convertMessage(message)),\n      stream: true,\n      stream_options: { include_usage: true },\n    };\n\n    // Standard optional parameters\n    if (maxTokens !== undefined) {\n      request.max_tokens = maxTokens;\n    }\n    if (temperature !== undefined) {\n      request.temperature = temperature;\n    }\n    if (topP !== undefined) {\n      request.top_p = topP;\n    }\n    if (stopSequences) {\n      request.stop = stopSequences;\n    }\n\n    // Add provider-specific parameters\n    const providerParams = this.buildProviderSpecificParams(extra as Record<string, unknown>);\n    Object.assign(request, providerParams);\n\n    // Pass through remaining extra options\n    if (extra) {\n      // Filter out keys that were already handled by buildProviderSpecificParams\n      const handledKeys = Object.keys(providerParams);\n      for (const [key, value] of Object.entries(extra)) {\n        if (!handledKeys.includes(key) && !this.isProviderSpecificKey(key)) {\n          request[key] = value;\n        }\n      }\n    }\n\n    return request as unknown as Parameters<OpenAI[\"chat\"][\"completions\"][\"create\"]>[0];\n  }\n\n  /**\n   * Check if a key should be filtered from passthrough.\n   * Override in subclasses to filter provider-specific keys from extra.\n   */\n  protected isProviderSpecificKey(_key: string): boolean {\n    return false;\n  }\n\n  /**\n   * Convert an LLMMessage to OpenAI's ChatCompletionMessageParam format.\n   */\n  protected convertMessage(message: LLMMessage): ChatCompletionMessageParam {\n    const role = ROLE_MAP[message.role];\n\n    // User messages support multimodal content\n    if (role === \"user\") {\n      const content = this.convertContent(message.content);\n      return {\n        role: \"user\",\n        content,\n        ...(message.name ? { name: message.name } : {}),\n      };\n    }\n\n    // System and assistant messages only support string content\n    const textContent =\n      typeof message.content === \"string\" ? message.content : extractMessageText(message.content);\n\n    if (role === \"system\") {\n      return {\n        role: \"system\",\n        content: textContent,\n        ...(message.name ? { name: message.name } : {}),\n      };\n    }\n\n    // Assistant role\n    return {\n      role: \"assistant\",\n      content: textContent,\n      ...(message.name ? { name: message.name } : {}),\n    };\n  }\n\n  /**\n   * Convert llmist content to OpenAI's content format.\n   */\n  protected convertContent(content: MessageContent): string | ChatCompletionContentPart[] {\n    // Optimization: keep simple string content as-is\n    if (typeof content === \"string\") {\n      return content;\n    }\n\n    // Convert array content to OpenAI-compatible format\n    return content.map((part) => {\n      if (part.type === \"text\") {\n        return { type: \"text\" as const, text: part.text };\n      }\n\n      if (part.type === \"image\") {\n        return this.convertImagePart(part);\n      }\n\n      if (part.type === \"audio\") {\n        throw new Error(\n          `${this.providerId} does not support audio input through llmist. ` +\n            `Check provider docs for model-specific audio support.`,\n        );\n      }\n\n      throw new Error(`Unsupported content type: ${(part as ContentPart).type}`);\n    });\n  }\n\n  /**\n   * Convert an image content part to OpenAI's image_url format.\n   */\n  protected convertImagePart(part: ImageContentPart): ChatCompletionContentPart {\n    if (part.source.type === \"url\") {\n      return {\n        type: \"image_url\" as const,\n        image_url: { url: part.source.url },\n      };\n    }\n\n    // Convert base64 to data URL format\n    return {\n      type: \"image_url\" as const,\n      image_url: {\n        url: `data:${part.source.mediaType};base64,${part.source.data}`,\n      },\n    };\n  }\n\n  protected async executeStreamRequest(\n    payload: Parameters<OpenAI[\"chat\"][\"completions\"][\"create\"]>[0],\n    signal?: AbortSignal,\n  ): Promise<AsyncIterable<ChatCompletionChunk>> {\n    const client = this.client as OpenAI;\n\n    // Get custom headers from subclass\n    const headers = this.getCustomHeaders();\n\n    const requestOptions: { signal?: AbortSignal; headers?: Record<string, string> } = {};\n    if (signal) {\n      requestOptions.signal = signal;\n    }\n    if (Object.keys(headers).length > 0) {\n      requestOptions.headers = headers;\n    }\n\n    try {\n      const stream = await client.chat.completions.create(\n        payload,\n        Object.keys(requestOptions).length > 0 ? requestOptions : undefined,\n      );\n      return stream as unknown as AsyncIterable<ChatCompletionChunk>;\n    } catch (error) {\n      // Use subclass-specific error enhancement\n      throw this.enhanceError(error);\n    }\n  }\n\n  protected async *normalizeProviderStream(iterable: AsyncIterable<unknown>): LLMStream {\n    const stream = iterable as AsyncIterable<ChatCompletionChunk>;\n\n    for await (const chunk of stream) {\n      const text = chunk.choices.map((choice) => choice.delta?.content ?? \"\").join(\"\");\n      if (text) {\n        yield { text, rawEvent: chunk };\n      }\n\n      const finishReason = chunk.choices.find((choice) => choice.finish_reason)?.finish_reason;\n\n      // Extract token usage if available (typically in the final chunk)\n      // Includes cached input tokens and reasoning tokens from nested details\n      type CompatUsageDetails = {\n        prompt_tokens_details?: { cached_tokens?: number };\n        completion_tokens_details?: { reasoning_tokens?: number };\n      };\n      const usageDetails = chunk.usage as (typeof chunk.usage & CompatUsageDetails) | undefined;\n      const usage = chunk.usage\n        ? {\n            inputTokens: chunk.usage.prompt_tokens,\n            outputTokens: chunk.usage.completion_tokens,\n            totalTokens: chunk.usage.total_tokens,\n            cachedInputTokens: usageDetails?.prompt_tokens_details?.cached_tokens ?? 0,\n            reasoningTokens: usageDetails?.completion_tokens_details?.reasoning_tokens,\n          }\n        : undefined;\n\n      if (finishReason || usage) {\n        yield { text: \"\", finishReason, usage, rawEvent: chunk };\n      }\n    }\n  }\n\n  /**\n   * Count tokens using tiktoken o200k_base encoding.\n   *\n   * While o200k_base isn't model-exact for non-OpenAI models routed through\n   * meta-providers like OpenRouter, BPE tokenizers with 200K vocab produce\n   * counts within 10-20% of true values — far better than the character-based\n   * fallback which can be off by 250% for JSON/code-heavy content.\n   *\n   * Falls back to character-based estimation if tiktoken fails.\n   */\n  async countTokens(\n    messages: LLMMessage[],\n    descriptor: ModelDescriptor,\n    _spec?: ModelSpec,\n  ): Promise<number> {\n    if (!messages || messages.length === 0) return 0;\n\n    try {\n      const encoding = get_encoding(\"o200k_base\");\n      try {\n        let tokenCount = 0;\n        for (const msg of messages) {\n          const parts = normalizeMessageContent(msg.content);\n          for (const part of parts) {\n            if (part.type === \"text\") {\n              tokenCount += encoding.encode(part.text).length;\n            }\n          }\n        }\n        return tokenCount;\n      } finally {\n        encoding.free();\n      }\n    } catch (error) {\n      console.warn(\n        `Token counting with tiktoken failed for ${descriptor.name}, using fallback estimation:`,\n        error,\n      );\n      let totalChars = 0;\n      for (const msg of messages) {\n        const parts = normalizeMessageContent(msg.content);\n        for (const part of parts) {\n          if (part.type === \"text\") {\n            totalChars += part.text.length;\n          }\n        }\n      }\n      return Math.ceil(totalChars / FALLBACK_CHARS_PER_TOKEN);\n    }\n  }\n}\n\n/**\n * Helper function to create an OpenAI-compatible provider from environment.\n *\n * @param envKey - Environment variable name for the API key\n * @param baseURL - Base URL for the provider's API\n * @param ProviderClass - The provider class constructor\n * @param configFactory - Factory function to create config from env\n * @returns Provider instance or null if no API key\n */\nexport function createOpenAICompatibleProviderFromEnv<\n  TConfig extends OpenAICompatibleConfig,\n  TProvider extends OpenAICompatibleProvider<TConfig>,\n>(\n  envKey: string,\n  baseURL: string,\n  ProviderClass: new (client: OpenAI, config: TConfig) => TProvider,\n  configFactory: () => TConfig,\n): TProvider | null {\n  const apiKey = process.env[envKey];\n\n  if (!apiKey || apiKey.trim() === \"\") {\n    return null;\n  }\n\n  const config = configFactory();\n\n  const client = new OpenAI({\n    apiKey: apiKey.trim(),\n    baseURL,\n    timeout: 120_000, // 2 minute timeout\n    maxRetries: 0, // Disable SDK retries - llmist handles all retries at application level\n  });\n\n  return new ProviderClass(client, config);\n}\n","/**\n * Hugging Face Provider Adapter\n *\n * Supports both serverless inference (router.huggingface.co) and\n * dedicated inference endpoints. Uses OpenAI SDK for API compatibility\n * since HF APIs follow OpenAI's chat completions format.\n *\n * Environment variables:\n * - HF_TOKEN (primary) or HUGGING_FACE_API_KEY (fallback)\n * - HF_ENDPOINT_URL (optional) - for dedicated endpoints\n *\n * Provider selection syntax (serverless only):\n * - model:fastest - route to fastest available provider\n * - model:cheapest - route to cheapest provider\n * - model:sambanova, model:groq, etc. - route to specific provider\n */\n\nimport OpenAI from \"openai\";\nimport type { LLMMessage } from \"../core/messages.js\";\nimport type { ModelSpec } from \"../core/model-catalog.js\";\nimport type { LLMGenerationOptions, ModelDescriptor } from \"../core/options.js\";\nimport { HUGGINGFACE_MODELS } from \"./huggingface-models.js\";\nimport {\n  type OpenAICompatibleConfig,\n  OpenAICompatibleProvider,\n} from \"./openai-compatible-provider.js\";\nimport { isNonEmpty, readEnvVar } from \"./utils.js\";\n\n/**\n * Configuration for HuggingFace provider.\n */\nexport interface HuggingFaceConfig extends OpenAICompatibleConfig {\n  /**\n   * Endpoint type for HuggingFace inference.\n   * - 'serverless': Use HF serverless inference (default)\n   * - 'dedicated': Use dedicated inference endpoint\n   */\n  endpointType?: \"serverless\" | \"dedicated\";\n}\n\nexport class HuggingFaceProvider extends OpenAICompatibleProvider<HuggingFaceConfig> {\n  readonly providerId = \"huggingface\" as const;\n  protected readonly providerAlias = \"hf\";\n\n  constructor(client: OpenAI, config: HuggingFaceConfig = {}) {\n    super(client, { endpointType: \"serverless\", ...config });\n  }\n\n  getModelSpecs(): ModelSpec[] {\n    return HUGGINGFACE_MODELS;\n  }\n\n  /**\n   * Override buildApiRequest to inject DeepSeek-specific thinking parameters.\n   * DeepSeek models use `extra_body: { thinking: { type: \"enabled\" } }` for reasoning.\n   */\n  protected buildApiRequest(\n    options: LLMGenerationOptions,\n    descriptor: ModelDescriptor,\n    spec: ModelSpec | undefined,\n    messages: LLMMessage[],\n  ): Parameters<OpenAI[\"chat\"][\"completions\"][\"create\"]>[0] {\n    const request = super.buildApiRequest(options, descriptor, spec, messages);\n\n    // Inject DeepSeek thinking mode when reasoning is enabled for DeepSeek models\n    if (options.reasoning?.enabled && descriptor.name.toLowerCase().includes(\"deepseek\")) {\n      const requestObj = request as unknown as Record<string, unknown>;\n      requestObj.extra_body = {\n        ...(requestObj.extra_body as Record<string, unknown> | undefined),\n        thinking: { type: \"enabled\" },\n      };\n    }\n\n    return request;\n  }\n\n  /**\n   * Enhance error messages with HuggingFace-specific guidance.\n   */\n  protected enhanceError(error: unknown): Error {\n    if (!(error instanceof Error)) {\n      return new Error(String(error));\n    }\n\n    const message = error.message.toLowerCase();\n\n    // Rate limit exceeded\n    if (message.includes(\"rate limit\") || message.includes(\"429\")) {\n      return new Error(\n        `HF rate limit exceeded. Free tier has limits. Consider upgrading or using a dedicated endpoint.\\n` +\n          `Original error: ${error.message}`,\n      );\n    }\n\n    // Model not found\n    if (message.includes(\"model not found\") || message.includes(\"404\")) {\n      return new Error(\n        `Model not available on HF ${this.config.endpointType} inference. ` +\n          `Check model name or try a different endpoint type.\\n` +\n          `Original error: ${error.message}`,\n      );\n    }\n\n    // Authentication failed\n    if (message.includes(\"401\") || message.includes(\"unauthorized\")) {\n      return new Error(\n        `HF authentication failed. Check that HF_TOKEN or HUGGING_FACE_API_KEY ` +\n          `is set correctly and starts with 'hf_'.\\n` +\n          `Original error: ${error.message}`,\n      );\n    }\n\n    // HF serverless inference often returns 400 for transient capacity/loading issues\n    // Wrap these to make them identifiable and allow retry logic to treat them as rate limits\n    if (message.includes(\"400\") || message.includes(\"bad request\")) {\n      return new Error(\n        `HF bad request (often transient on serverless). ` + `Original error: ${error.message}`,\n      );\n    }\n\n    return error;\n  }\n}\n\n/**\n * Create a Hugging Face provider from environment variables.\n *\n * Environment variables:\n * - HF_TOKEN (primary) or HUGGING_FACE_API_KEY (fallback) - Required for authentication\n * - HF_ENDPOINT_URL (optional) - Custom endpoint URL for dedicated deployments\n *\n * @returns HuggingFaceProvider instance or null if no API key is found\n *\n * @example\n * ```bash\n * # Serverless inference (default)\n * export HF_TOKEN=\"hf_...\"\n *\n * # Dedicated endpoint\n * export HF_TOKEN=\"hf_...\"\n * export HF_ENDPOINT_URL=\"https://xxx.endpoints.huggingface.cloud\"\n * ```\n */\nexport function createHuggingFaceProviderFromEnv(): HuggingFaceProvider | null {\n  // Try HF_TOKEN first (official HF environment variable), then fallback to HUGGING_FACE_API_KEY\n  const token = readEnvVar(\"HF_TOKEN\") || readEnvVar(\"HUGGING_FACE_API_KEY\");\n\n  if (!isNonEmpty(token)) {\n    return null;\n  }\n\n  // Validate token format (HF tokens should start with \"hf_\")\n  if (!token.startsWith(\"hf_\")) {\n    console.warn(\n      \"Warning: HF token should start with 'hf_'. Authentication may fail if token format is incorrect.\",\n    );\n  }\n\n  // Check for custom endpoint URL (for dedicated deployments)\n  const endpointUrl = readEnvVar(\"HF_ENDPOINT_URL\");\n  const baseURL = endpointUrl || \"https://router.huggingface.co/v1\";\n  const endpointType = endpointUrl ? \"dedicated\" : \"serverless\";\n\n  const config: HuggingFaceConfig = {\n    endpointType,\n  };\n\n  // Create OpenAI SDK client with HF base URL\n  const client = new OpenAI({\n    apiKey: token.trim(),\n    baseURL,\n    timeout: 60_000, // 60s timeout - HF free tier can be slower than OpenAI\n    maxRetries: 0, // Disable SDK retries - llmist handles all retries at application level\n  });\n\n  return new HuggingFaceProvider(client, config);\n}\n","/**\n * OpenAI Image Generation Model Catalog\n *\n * Pricing as of December 2025:\n *\n * GPT Image 1.5 (flagship):\n * - Low quality: ~$0.008 per image\n * - Medium quality: ~$0.03 per image\n * - High quality: ~$0.13 per image\n *\n * GPT Image 1 (previous gen):\n * - Low quality: ~$0.011 per image\n * - Medium quality: ~$0.04 per image\n * - High quality: ~$0.17 per image\n *\n * GPT Image 1 Mini (cost-effective):\n * - Low quality: ~$0.005 per image\n * - Medium quality: ~$0.02 per image\n * - High quality: ~$0.052 per image\n *\n * Sora 2 (video generation):\n * - Standard quality: ~$0.50 per 5-second clip\n * - High quality: ~$1.00 per 5-second clip\n *\n * DALL-E 3 (deprecated):\n * - 1024x1024: $0.040 (standard), $0.080 (hd)\n * - 1024x1792: $0.080 (standard), $0.120 (hd)\n * - 1792x1024: $0.080 (standard), $0.120 (hd)\n *\n * DALL-E 2 (deprecated):\n * - 256x256: $0.016\n * - 512x512: $0.018\n * - 1024x1024: $0.020\n *\n * @see https://platform.openai.com/docs/guides/images\n */\n\nimport type { ImageModelSpec } from \"../core/media-types.js\";\n\n/** GPT Image supported sizes */\nexport const GPT_IMAGE_SIZES = [\n  \"1024x1024\",\n  \"1024x1536\",\n  \"1536x1024\",\n  \"1920x1080\",\n  \"auto\",\n] as const;\nexport type GptImageSize = (typeof GPT_IMAGE_SIZES)[number];\n\n/** GPT Image quality levels */\nexport const GPT_IMAGE_QUALITIES = [\"low\", \"medium\", \"high\"] as const;\nexport type GptImageQuality = (typeof GPT_IMAGE_QUALITIES)[number];\n\n/** Sora video durations */\nexport const SORA_DURATIONS = [\"5s\", \"10s\", \"15s\", \"20s\"] as const;\nexport type SoraDuration = (typeof SORA_DURATIONS)[number];\n\n/** DALL-E 3 supported sizes (deprecated) */\nexport const DALLE3_SIZES = [\"1024x1024\", \"1024x1792\", \"1792x1024\"] as const;\nexport type DallE3Size = (typeof DALLE3_SIZES)[number];\n\n/** DALL-E 3 quality levels (deprecated) */\nexport const DALLE3_QUALITIES = [\"standard\", \"hd\"] as const;\nexport type DallE3Quality = (typeof DALLE3_QUALITIES)[number];\n\n/** DALL-E 2 supported sizes (deprecated) */\nexport const DALLE2_SIZES = [\"256x256\", \"512x512\", \"1024x1024\"] as const;\nexport type DallE2Size = (typeof DALLE2_SIZES)[number];\n\n/**\n * OpenAI Image Model Specifications\n */\nexport const openaiImageModels: ImageModelSpec[] = [\n  // GPT Image 1.5 Family (flagship)\n  {\n    provider: \"openai\",\n    modelId: \"gpt-image-1.5\",\n    displayName: \"GPT Image 1.5\",\n    pricing: {\n      bySize: {\n        \"1024x1024\": { low: 0.008, medium: 0.03, high: 0.13 },\n        \"1024x1536\": { low: 0.012, medium: 0.045, high: 0.195 },\n        \"1536x1024\": { low: 0.012, medium: 0.045, high: 0.195 },\n        \"1920x1080\": { low: 0.016, medium: 0.06, high: 0.26 },\n      },\n    },\n    supportedSizes: [...GPT_IMAGE_SIZES],\n    supportedQualities: [...GPT_IMAGE_QUALITIES],\n    maxImages: 1,\n    defaultSize: \"1024x1024\",\n    defaultQuality: \"medium\",\n    features: {\n      textRendering: true,\n      transparency: true,\n      editing: true,\n    },\n  },\n  // GPT Image 1 Family (previous gen)\n  {\n    provider: \"openai\",\n    modelId: \"gpt-image-1\",\n    displayName: \"GPT Image 1\",\n    pricing: {\n      bySize: {\n        \"1024x1024\": { low: 0.011, medium: 0.04, high: 0.17 },\n        \"1024x1536\": { low: 0.016, medium: 0.06, high: 0.25 },\n        \"1536x1024\": { low: 0.016, medium: 0.06, high: 0.25 },\n      },\n    },\n    supportedSizes: [\"1024x1024\", \"1024x1536\", \"1536x1024\"],\n    supportedQualities: [...GPT_IMAGE_QUALITIES],\n    maxImages: 1,\n    defaultSize: \"1024x1024\",\n    defaultQuality: \"medium\",\n    features: {\n      textRendering: true,\n      transparency: true,\n    },\n  },\n  {\n    provider: \"openai\",\n    modelId: \"gpt-image-1-mini\",\n    displayName: \"GPT Image 1 Mini\",\n    pricing: {\n      bySize: {\n        \"1024x1024\": { low: 0.005, medium: 0.02, high: 0.052 },\n        \"1024x1536\": { low: 0.0075, medium: 0.03, high: 0.078 },\n        \"1536x1024\": { low: 0.0075, medium: 0.03, high: 0.078 },\n      },\n    },\n    supportedSizes: [\"1024x1024\", \"1024x1536\", \"1536x1024\"],\n    supportedQualities: [...GPT_IMAGE_QUALITIES],\n    maxImages: 1,\n    defaultSize: \"1024x1024\",\n    defaultQuality: \"medium\",\n    features: {\n      textRendering: true,\n      transparency: true,\n    },\n  },\n  // Sora Video Generation Models\n  {\n    provider: \"openai\",\n    modelId: \"sora-2\",\n    displayName: \"Sora 2\",\n    pricing: {\n      bySize: {\n        \"1920x1080\": { standard: 0.5, high: 1.0 },\n        \"1080x1920\": { standard: 0.5, high: 1.0 },\n        \"1024x1024\": { standard: 0.4, high: 0.8 },\n      },\n    },\n    supportedSizes: [\"1920x1080\", \"1080x1920\", \"1024x1024\"],\n    supportedQualities: [\"standard\", \"high\"],\n    maxImages: 1,\n    defaultSize: \"1920x1080\",\n    defaultQuality: \"standard\",\n    features: {\n      videoGeneration: true,\n    },\n  },\n  {\n    provider: \"openai\",\n    modelId: \"sora-2-pro\",\n    displayName: \"Sora 2 Pro\",\n    pricing: {\n      bySize: {\n        \"1920x1080\": { standard: 1.0, high: 2.0 },\n        \"1080x1920\": { standard: 1.0, high: 2.0 },\n        \"1024x1024\": { standard: 0.8, high: 1.6 },\n      },\n    },\n    supportedSizes: [\"1920x1080\", \"1080x1920\", \"1024x1024\"],\n    supportedQualities: [\"standard\", \"high\"],\n    maxImages: 1,\n    defaultSize: \"1920x1080\",\n    defaultQuality: \"standard\",\n    features: {\n      videoGeneration: true,\n      extendedDuration: true,\n    },\n  },\n  // DALL-E Family (deprecated - use GPT Image models instead)\n  {\n    provider: \"openai\",\n    modelId: \"dall-e-3\",\n    displayName: \"DALL-E 3 (Deprecated)\",\n    pricing: {\n      bySize: {\n        \"1024x1024\": { standard: 0.04, hd: 0.08 },\n        \"1024x1792\": { standard: 0.08, hd: 0.12 },\n        \"1792x1024\": { standard: 0.08, hd: 0.12 },\n      },\n    },\n    supportedSizes: [...DALLE3_SIZES],\n    supportedQualities: [...DALLE3_QUALITIES],\n    maxImages: 1, // DALL-E 3 only supports n=1\n    defaultSize: \"1024x1024\",\n    defaultQuality: \"standard\",\n    features: {\n      textRendering: true,\n    },\n  },\n  {\n    provider: \"openai\",\n    modelId: \"dall-e-2\",\n    displayName: \"DALL-E 2 (Deprecated)\",\n    pricing: {\n      bySize: {\n        \"256x256\": 0.016,\n        \"512x512\": 0.018,\n        \"1024x1024\": 0.02,\n      },\n    },\n    supportedSizes: [...DALLE2_SIZES],\n    maxImages: 10,\n    defaultSize: \"1024x1024\",\n  },\n];\n\n/**\n * Get image model spec by model ID.\n */\nexport function getOpenAIImageModelSpec(modelId: string): ImageModelSpec | undefined {\n  return openaiImageModels.find((m) => m.modelId === modelId);\n}\n\n/**\n * Check if a model ID is an OpenAI image model.\n */\nexport function isOpenAIImageModel(modelId: string): boolean {\n  return openaiImageModels.some((m) => m.modelId === modelId);\n}\n\n/**\n * Calculate cost for image generation.\n *\n * @param modelId - The model ID (dall-e-3 or dall-e-2)\n * @param size - Image size\n * @param quality - Quality level (for DALL-E 3)\n * @param n - Number of images\n * @returns Cost in USD, or undefined if model not found\n */\nexport function calculateOpenAIImageCost(\n  modelId: string,\n  size: string,\n  quality = \"standard\",\n  n = 1,\n): number | undefined {\n  const spec = getOpenAIImageModelSpec(modelId);\n  if (!spec) return undefined;\n\n  // Get price for this size\n  const sizePrice = spec.pricing.bySize?.[size];\n  if (sizePrice === undefined) return undefined;\n\n  let pricePerImage: number;\n\n  if (typeof sizePrice === \"number\") {\n    // Flat pricing (DALL-E 2)\n    pricePerImage = sizePrice;\n  } else {\n    // Quality-based pricing (DALL-E 3)\n    pricePerImage = sizePrice[quality];\n    if (pricePerImage === undefined) return undefined;\n  }\n\n  return pricePerImage * n;\n}\n","/**\n * OpenAI Model Specifications\n *\n * Model data for OpenAI models including GPT-5.2, GPT-5.1, GPT-5, GPT-4.1, GPT-4o, and o-series\n * with their specifications, pricing (Standard tier), and capabilities.\n *\n * Pricing source: https://openai.com/api/pricing (Standard tier)\n * Last updated: 2025-12-20\n */\n\nimport type { ModelSpec } from \"../core/model-catalog.js\";\n\nexport const OPENAI_MODELS: ModelSpec[] = [\n  // GPT-5.2 Family (Latest flagship)\n  {\n    provider: \"openai\",\n    modelId: \"gpt-5.2\",\n    displayName: \"GPT-5.2\",\n    contextWindow: 1_000_000,\n    maxOutputTokens: 128_000,\n    pricing: {\n      input: 1.25,\n      output: 10.0,\n      cachedInput: 0.125,\n    },\n    knowledgeCutoff: \"2025-03-31\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: true,\n      reasoning: true,\n      structuredOutputs: true,\n      fineTuning: true,\n    },\n    metadata: {\n      family: \"GPT-5.2\",\n      releaseDate: \"2025-12-01\",\n      notes: \"Latest flagship model with 1M context window and enhanced reasoning.\",\n      supportsTemperature: false,\n    },\n  },\n  {\n    provider: \"openai\",\n    modelId: \"gpt-5.2-pro\",\n    displayName: \"GPT-5.2 Pro\",\n    contextWindow: 1_000_000,\n    maxOutputTokens: 128_000,\n    pricing: {\n      input: 15.0,\n      output: 120.0,\n    },\n    knowledgeCutoff: \"2025-03-31\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: true,\n      reasoning: true,\n      structuredOutputs: true,\n    },\n    metadata: {\n      family: \"GPT-5.2\",\n      releaseDate: \"2025-12-01\",\n      notes: \"Premium tier GPT-5.2 with enhanced reasoning. Does not support prompt caching.\",\n      supportsTemperature: false,\n    },\n  },\n\n  // GPT-5.1 Family\n  {\n    provider: \"openai\",\n    modelId: \"gpt-5.1\",\n    displayName: \"GPT-5.1\",\n    contextWindow: 1_000_000,\n    maxOutputTokens: 32_768,\n    pricing: {\n      input: 1.25,\n      output: 10.0,\n      cachedInput: 0.125,\n    },\n    knowledgeCutoff: \"2024-09-30\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: true,\n      reasoning: true,\n      structuredOutputs: true,\n      fineTuning: true,\n    },\n    metadata: {\n      family: \"GPT-5.1\",\n      releaseDate: \"2025-11-12\",\n      notes: \"GPT-5 variant with improved instruction following. 2-3x faster than GPT-5.\",\n      supportsTemperature: false,\n    },\n  },\n  {\n    provider: \"openai\",\n    modelId: \"gpt-5.1-codex\",\n    displayName: \"GPT-5.1 Codex\",\n    contextWindow: 1_000_000,\n    maxOutputTokens: 32_768,\n    pricing: {\n      input: 1.25,\n      output: 10.0,\n      cachedInput: 0.125,\n    },\n    knowledgeCutoff: \"2024-09-30\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: true,\n      reasoning: true,\n      structuredOutputs: true,\n    },\n    metadata: {\n      family: \"GPT-5.1\",\n      notes: \"GPT-5.1 variant optimized for code generation and analysis.\",\n      supportsTemperature: false,\n    },\n  },\n  {\n    provider: \"openai\",\n    modelId: \"gpt-5.1-codex-max\",\n    displayName: \"GPT-5.1 Codex Max\",\n    contextWindow: 1_000_000,\n    maxOutputTokens: 32_768,\n    pricing: {\n      input: 1.25,\n      output: 10.0,\n      cachedInput: 0.125,\n    },\n    knowledgeCutoff: \"2024-09-30\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: true,\n      reasoning: true,\n      structuredOutputs: true,\n    },\n    metadata: {\n      family: \"GPT-5.1\",\n      notes: \"Extended thinking variant of GPT-5.1 Codex for complex code tasks.\",\n      supportsTemperature: false,\n    },\n  },\n\n  // GPT-5 Family\n  {\n    provider: \"openai\",\n    modelId: \"gpt-5\",\n    displayName: \"GPT-5\",\n    contextWindow: 1_000_000,\n    maxOutputTokens: 128_000,\n    pricing: {\n      input: 1.25,\n      output: 10.0,\n      cachedInput: 0.125,\n    },\n    knowledgeCutoff: \"2024-09-30\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: true,\n      reasoning: true,\n      structuredOutputs: true,\n      fineTuning: true,\n    },\n    metadata: {\n      family: \"GPT-5\",\n      releaseDate: \"2025-08-07\",\n      notes: \"High-capability model for coding and agentic tasks. 90% caching discount.\",\n      supportsTemperature: false,\n    },\n  },\n  {\n    provider: \"openai\",\n    modelId: \"gpt-5-codex\",\n    displayName: \"GPT-5 Codex\",\n    contextWindow: 1_000_000,\n    maxOutputTokens: 128_000,\n    pricing: {\n      input: 1.25,\n      output: 10.0,\n      cachedInput: 0.125,\n    },\n    knowledgeCutoff: \"2024-09-30\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: true,\n      reasoning: true,\n      structuredOutputs: true,\n    },\n    metadata: {\n      family: \"GPT-5\",\n      notes: \"GPT-5 variant optimized for code generation and analysis.\",\n      supportsTemperature: false,\n    },\n  },\n  {\n    provider: \"openai\",\n    modelId: \"gpt-5-mini\",\n    displayName: \"GPT-5 Mini\",\n    contextWindow: 272_000,\n    maxOutputTokens: 32_768,\n    pricing: {\n      input: 0.25,\n      output: 2.0,\n      cachedInput: 0.025,\n    },\n    knowledgeCutoff: \"2024-06-01\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: true,\n      structuredOutputs: true,\n      fineTuning: true,\n    },\n    metadata: {\n      family: \"GPT-5\",\n      notes: \"Fast and cost-efficient with adaptive reasoning\",\n      supportsTemperature: false,\n    },\n  },\n  {\n    provider: \"openai\",\n    modelId: \"gpt-5-nano\",\n    displayName: \"GPT-5 Nano\",\n    contextWindow: 272_000,\n    maxOutputTokens: 32_768,\n    pricing: {\n      input: 0.05,\n      output: 0.4,\n      cachedInput: 0.005,\n    },\n    knowledgeCutoff: \"2024-05-31\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: true,\n      structuredOutputs: true,\n      fineTuning: true,\n    },\n    metadata: {\n      family: \"GPT-5\",\n      notes: \"Fastest, most cost-efficient version for well-defined tasks\",\n      supportsTemperature: false,\n    },\n  },\n  {\n    provider: \"openai\",\n    modelId: \"gpt-5-pro\",\n    displayName: \"GPT-5 Pro\",\n    contextWindow: 272_000,\n    maxOutputTokens: 128_000,\n    pricing: {\n      input: 15.0,\n      output: 120.0,\n      // No cached input pricing for gpt-5-pro\n    },\n    knowledgeCutoff: \"2024-09-30\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: true,\n      reasoning: true,\n      structuredOutputs: true,\n    },\n    metadata: {\n      family: \"GPT-5\",\n      notes: \"Premium tier with enhanced capabilities. Does not support prompt caching.\",\n      supportsTemperature: false,\n    },\n  },\n\n  // GPT-4.1 Family\n  {\n    provider: \"openai\",\n    modelId: \"gpt-4.1\",\n    displayName: \"GPT-4.1\",\n    contextWindow: 128_000,\n    maxOutputTokens: 32_768,\n    pricing: {\n      input: 2.0,\n      output: 8.0,\n      cachedInput: 0.5,\n    },\n    knowledgeCutoff: \"2024-04-01\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: true,\n      structuredOutputs: true,\n      fineTuning: true,\n    },\n    metadata: {\n      family: \"GPT-4.1\",\n      notes: \"Improved GPT-4 with better instruction following\",\n    },\n  },\n  {\n    provider: \"openai\",\n    modelId: \"gpt-4.1-mini\",\n    displayName: \"GPT-4.1 Mini\",\n    contextWindow: 128_000,\n    maxOutputTokens: 32_768,\n    pricing: {\n      input: 0.4,\n      output: 1.6,\n      cachedInput: 0.1,\n    },\n    knowledgeCutoff: \"2024-04-01\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: true,\n      structuredOutputs: true,\n      fineTuning: true,\n    },\n    metadata: {\n      family: \"GPT-4.1\",\n      notes: \"Cost-efficient GPT-4.1 variant\",\n    },\n  },\n  {\n    provider: \"openai\",\n    modelId: \"gpt-4.1-nano\",\n    displayName: \"GPT-4.1 Nano\",\n    contextWindow: 128_000,\n    maxOutputTokens: 32_768,\n    pricing: {\n      input: 0.1,\n      output: 0.4,\n      cachedInput: 0.025,\n    },\n    knowledgeCutoff: \"2024-04-01\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: true,\n      structuredOutputs: true,\n      fineTuning: true,\n    },\n    metadata: {\n      family: \"GPT-4.1\",\n      notes: \"Fastest GPT-4.1 variant for simple tasks\",\n    },\n  },\n\n  // GPT-4o Family\n  {\n    provider: \"openai\",\n    modelId: \"gpt-4o\",\n    displayName: \"GPT-4o\",\n    contextWindow: 128_000,\n    maxOutputTokens: 16_384,\n    pricing: {\n      input: 2.5,\n      output: 10.0,\n      cachedInput: 1.25,\n    },\n    knowledgeCutoff: \"2024-04-01\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: true,\n      structuredOutputs: true,\n      fineTuning: true,\n    },\n    metadata: {\n      family: \"GPT-4o\",\n      notes: \"Multimodal model optimized for speed\",\n    },\n  },\n  {\n    provider: \"openai\",\n    modelId: \"gpt-4o-mini\",\n    displayName: \"GPT-4o Mini\",\n    contextWindow: 128_000,\n    maxOutputTokens: 16_384,\n    pricing: {\n      input: 0.15,\n      output: 0.6,\n      cachedInput: 0.075,\n    },\n    knowledgeCutoff: \"2024-04-01\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: true,\n      structuredOutputs: true,\n      fineTuning: true,\n    },\n    metadata: {\n      family: \"GPT-4o\",\n      notes: \"Fast and affordable multimodal model\",\n    },\n  },\n\n  // o-series (Reasoning models)\n  {\n    provider: \"openai\",\n    modelId: \"o1\",\n    displayName: \"o1\",\n    contextWindow: 200_000,\n    maxOutputTokens: 100_000,\n    pricing: {\n      input: 15.0,\n      output: 60.0,\n      cachedInput: 7.5,\n    },\n    knowledgeCutoff: \"2024-12-01\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: true,\n      reasoning: true,\n      structuredOutputs: true,\n    },\n    metadata: {\n      family: \"o-series\",\n      notes: \"Advanced reasoning model with chain-of-thought\",\n      supportsTemperature: false,\n    },\n  },\n  {\n    provider: \"openai\",\n    modelId: \"o1-pro\",\n    displayName: \"o1 Pro\",\n    contextWindow: 200_000,\n    maxOutputTokens: 100_000,\n    pricing: {\n      input: 150.0,\n      output: 600.0,\n    },\n    knowledgeCutoff: \"2024-12-01\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: true,\n      reasoning: true,\n      structuredOutputs: true,\n    },\n    metadata: {\n      family: \"o-series\",\n      notes: \"Premium tier o1 with extended reasoning. Does not support prompt caching.\",\n      supportsTemperature: false,\n    },\n  },\n  {\n    provider: \"openai\",\n    modelId: \"o3\",\n    displayName: \"o3\",\n    contextWindow: 200_000,\n    maxOutputTokens: 100_000,\n    pricing: {\n      input: 2.0,\n      output: 8.0,\n      cachedInput: 0.5,\n    },\n    knowledgeCutoff: \"2025-01-01\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: true,\n      reasoning: true,\n      structuredOutputs: true,\n    },\n    metadata: {\n      family: \"o-series\",\n      notes: \"Next-gen reasoning model, more efficient than o1\",\n      supportsTemperature: false,\n    },\n  },\n  {\n    provider: \"openai\",\n    modelId: \"o4-mini\",\n    displayName: \"o4 Mini\",\n    contextWindow: 200_000,\n    maxOutputTokens: 100_000,\n    pricing: {\n      input: 1.1,\n      output: 4.4,\n      cachedInput: 0.275,\n    },\n    knowledgeCutoff: \"2025-04-01\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: true,\n      reasoning: true,\n      structuredOutputs: true,\n      fineTuning: true,\n    },\n    metadata: {\n      family: \"o-series\",\n      notes: \"Cost-efficient reasoning model\",\n      supportsTemperature: false,\n    },\n  },\n  {\n    provider: \"openai\",\n    modelId: \"o3-mini\",\n    displayName: \"o3 Mini\",\n    contextWindow: 200_000,\n    maxOutputTokens: 100_000,\n    pricing: {\n      input: 1.1,\n      output: 4.4,\n      cachedInput: 0.55,\n    },\n    knowledgeCutoff: \"2025-01-01\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: true,\n      reasoning: true,\n      structuredOutputs: true,\n    },\n    metadata: {\n      family: \"o-series\",\n      notes: \"Compact reasoning model for cost-sensitive applications\",\n      supportsTemperature: false,\n    },\n  },\n];\n","/**\n * OpenAI deep research via the Responses API.\n *\n * Generic Responses-API job client: create (with `background`), poll,\n * stream, stream-resume (`starting_after`), cancel — plus the normalizer\n * from Responses SSE events to the llmist `ResearchEvent` union.\n *\n * Deep research is NOT available on Chat Completions; requests must include\n * at least one data-source tool and use `web_search_preview` (the GA\n * `web_search` tool type breaks research models).\n */\n\nimport type OpenAI from \"openai\";\nimport type {\n  Response,\n  ResponseCreateParamsBase,\n  ResponseStreamEvent,\n  Tool,\n} from \"openai/resources/responses/responses\";\nimport { isAbortError } from \"../core/errors.js\";\nimport { extractRetryAfterMs, isRetryableError } from \"../core/retry.js\";\nimport {\n  OPENAI_RESEARCH_HTTP_TIMEOUT_MS,\n  RESEARCH_POLL_BACKOFF_FACTOR,\n  RESEARCH_POLL_INTERVAL_MS,\n  RESEARCH_POLL_MAX_INTERVAL_MS,\n} from \"../research/constants.js\";\nimport { ResearchValidationError } from \"../research/errors.js\";\nimport type { ResearchModelSpec } from \"../research/model-spec.js\";\nimport type {\n  ResearchCitation,\n  ResearchEvent,\n  ResearchJobRef,\n  ResearchOptions,\n  ResearchStatus,\n  ResearchStatusSnapshot,\n  ResearchUsage,\n} from \"../research/types.js\";\n\n/** OpenAI file_search accepts at most this many vector stores. */\nconst OPENAI_FILE_SEARCH_MAX_VECTOR_STORES = 2;\n\n/** Retries for the create call (no job exists yet — safe to retry). */\nconst OPENAI_RESEARCH_CREATE_MAX_RETRIES = 3;\n\n/** Retries per poll request (idempotent GET — retried generously). */\nconst OPENAI_RESEARCH_POLL_MAX_RETRIES = 5;\n\n// =============================================================================\n// Request building\n// =============================================================================\n\n/** Map llmist research tools to Responses API tool shapes. */\nfunction buildTools(options: ResearchOptions): Tool[] {\n  const tools: Tool[] = [];\n  for (const tool of options.tools ?? []) {\n    switch (tool.type) {\n      case \"web_search\":\n        // NOT the GA \"web_search\" type — research models require the preview type.\n        tools.push({ type: \"web_search_preview\" } as Tool);\n        break;\n      case \"file_search\":\n        if (tool.vectorStoreIds.length > OPENAI_FILE_SEARCH_MAX_VECTOR_STORES) {\n          throw new ResearchValidationError(\n            `OpenAI file_search accepts at most ${OPENAI_FILE_SEARCH_MAX_VECTOR_STORES} vector stores ` +\n              `(got ${tool.vectorStoreIds.length}).`,\n          );\n        }\n        tools.push({ type: \"file_search\", vector_store_ids: tool.vectorStoreIds } as Tool);\n        break;\n      case \"mcp\":\n        tools.push({\n          type: \"mcp\",\n          server_label: tool.serverLabel,\n          server_url: tool.serverUrl,\n          require_approval: tool.requireApproval ?? \"never\",\n        } as Tool);\n        break;\n      case \"code_interpreter\":\n        tools.push({ type: \"code_interpreter\", container: { type: \"auto\" } } as Tool);\n        break;\n    }\n  }\n  return tools;\n}\n\n/**\n * Build the Responses API request for a research run.\n * The namespace validates tools/background against the catalog spec before\n * this is called; this builder enforces OpenAI-specific constraints.\n */\nexport function buildResponsesResearchRequest(\n  options: ResearchOptions,\n  spec: ResearchModelSpec | undefined,\n  modelId: string,\n): ResponseCreateParamsBase {\n  const tools = buildTools(options);\n  const hasDataSource = (options.tools ?? []).some((tool) =>\n    [\"web_search\", \"file_search\", \"mcp\"].includes(tool.type),\n  );\n  if (!hasDataSource) {\n    throw new ResearchValidationError(\n      \"OpenAI deep research requires at least one data-source tool \" +\n        \"(web_search, file_search, or mcp).\",\n    );\n  }\n\n  const background = options.background ?? spec?.capabilities.background ?? true;\n  // Deep research has no system role — fold the system prompt into the input.\n  const input = options.systemPrompt\n    ? `${options.systemPrompt}\\n\\n${options.query}`\n    : options.query;\n\n  const request: ResponseCreateParamsBase = {\n    model: modelId,\n    input,\n    background,\n    // Background mode requires stored responses; polling/resume need them too.\n    ...(background ? { store: true } : {}),\n    reasoning: {\n      summary: \"auto\",\n      ...(options.reasoning?.effort && options.reasoning.effort !== \"none\"\n        ? { effort: mapEffort(options.reasoning.effort) }\n        : {}),\n    },\n    tools,\n    ...(options.maxToolCalls !== undefined ? { max_tool_calls: options.maxToolCalls } : {}),\n    ...((options.extra as Partial<ResponseCreateParamsBase>) ?? {}),\n  };\n  return request;\n}\n\ntype OpenAIReasoningEffort = \"low\" | \"medium\" | \"high\" | \"xhigh\";\n\nfunction mapEffort(\n  effort: NonNullable<ResearchOptions[\"reasoning\"]>[\"effort\"],\n): OpenAIReasoningEffort {\n  // Mirrors OPENAI_EFFORT_MAP in openai.ts (kept local: research accepts a subset).\n  switch (effort) {\n    case \"maximum\":\n      return \"xhigh\";\n    case \"low\":\n    case \"medium\":\n    case \"high\":\n      return effort;\n    default:\n      return \"medium\";\n  }\n}\n\n// =============================================================================\n// Response → result extraction (shared by stream, poll, and status paths)\n// =============================================================================\n\ninterface ExtractedReport {\n  report: string;\n  citations: ResearchCitation[];\n}\n\n/** Pull the final report text + url citations out of a Response object. */\nexport function extractReportFromResponse(response: Response): ExtractedReport {\n  const citations: ResearchCitation[] = [];\n  const parts: string[] = [];\n\n  for (const item of response.output ?? []) {\n    if (item.type !== \"message\") continue;\n    for (const content of item.content ?? []) {\n      if (content.type !== \"output_text\") continue;\n      parts.push(content.text);\n      for (const annotation of content.annotations ?? []) {\n        const citation = annotationToCitation(annotation);\n        if (citation) citations.push(citation);\n      }\n    }\n  }\n\n  return { report: parts.join(\"\"), citations };\n}\n\nfunction annotationToCitation(annotation: unknown): ResearchCitation | undefined {\n  if (typeof annotation !== \"object\" || annotation === null) return undefined;\n  const a = annotation as Record<string, unknown>;\n  if (a.type !== \"url_citation\" || typeof a.url !== \"string\") return undefined;\n  return {\n    url: a.url,\n    title: typeof a.title === \"string\" ? a.title : undefined,\n    startIndex: typeof a.start_index === \"number\" ? a.start_index : undefined,\n    endIndex: typeof a.end_index === \"number\" ? a.end_index : undefined,\n  };\n}\n\n/** Count completed web searches in the response output. */\nfunction countSearches(response: Response): number {\n  let searches = 0;\n  for (const item of response.output ?? []) {\n    if (item.type === \"web_search_call\") searches += 1;\n  }\n  return searches;\n}\n\nexport function usageFromResponse(response: Response): ResearchUsage {\n  const usage = response.usage;\n  return {\n    inputTokens: usage?.input_tokens ?? 0,\n    outputTokens: usage?.output_tokens ?? 0,\n    totalTokens: usage?.total_tokens ?? 0,\n    cachedInputTokens: usage?.input_tokens_details?.cached_tokens,\n    reasoningTokens: usage?.output_tokens_details?.reasoning_tokens,\n    searches: countSearches(response),\n  };\n}\n\nconst STATUS_MAP: Record<string, ResearchStatus> = {\n  queued: \"queued\",\n  in_progress: \"in_progress\",\n  completed: \"completed\",\n  failed: \"failed\",\n  cancelled: \"cancelled\",\n  incomplete: \"incomplete\",\n};\n\nexport function mapResponseStatus(status: string | undefined | null): ResearchStatus {\n  return (status && STATUS_MAP[status]) || \"in_progress\";\n}\n\nfunction doneEventFromResponse(response: Response): ResearchEvent {\n  const { report, citations } = extractReportFromResponse(response);\n  return {\n    type: \"done\",\n    result: {\n      status: mapResponseStatus(response.status),\n      report,\n      citations,\n      usage: usageFromResponse(response),\n      raw: response,\n    },\n  };\n}\n\n// =============================================================================\n// Stream normalization\n// =============================================================================\n\n/**\n * Normalize a Responses SSE event stream into research events.\n * Every event's `cursor` is its stringified `sequence_number` (resume token).\n */\nexport async function* normalizeResponsesStream(\n  stream: AsyncIterable<ResponseStreamEvent>,\n): AsyncGenerator<ResearchEvent> {\n  // web_search_call items report progress via several events; dedupe \"started\".\n  const searchStarted = new Set<string>();\n\n  for await (const event of stream) {\n    const cursor = String(event.sequence_number);\n\n    switch (event.type) {\n      case \"response.created\":\n        yield { type: \"created\", jobId: event.response.id, cursor, rawEvent: event };\n        yield { type: \"status\", status: mapResponseStatus(event.response.status), cursor };\n        break;\n      case \"response.queued\":\n        yield { type: \"status\", status: \"queued\", cursor, rawEvent: event };\n        break;\n      case \"response.in_progress\":\n        yield { type: \"status\", status: \"in_progress\", cursor, rawEvent: event };\n        break;\n\n      case \"response.output_item.added\": {\n        const item = event.item;\n        if (item.type === \"reasoning\") {\n          yield { type: \"phase\", phase: \"reasoning\", cursor, rawEvent: event };\n        } else if (item.type === \"web_search_call\") {\n          const action = \"action\" in item ? item.action : undefined;\n          searchStarted.add(item.id);\n          yield {\n            type: \"search\",\n            action: action?.type ?? \"search\",\n            status: \"started\",\n            query: action && \"query\" in action ? (action.query ?? undefined) : undefined,\n            url: action && \"url\" in action ? (action.url ?? undefined) : undefined,\n            cursor,\n            rawEvent: event,\n          };\n        } else if (item.type === \"code_interpreter_call\") {\n          yield {\n            type: \"tool\",\n            tool: \"code_interpreter\",\n            status: \"started\",\n            cursor,\n            rawEvent: event,\n          };\n        } else if (item.type === \"file_search_call\") {\n          yield { type: \"tool\", tool: \"file_search\", status: \"started\", cursor, rawEvent: event };\n        } else if (item.type === \"mcp_call\") {\n          yield { type: \"tool\", tool: \"mcp\", status: \"started\", cursor, rawEvent: event };\n        } else if (item.type === \"message\") {\n          yield { type: \"phase\", phase: \"writing\", cursor, rawEvent: event };\n        }\n        break;\n      }\n\n      case \"response.web_search_call.in_progress\":\n      case \"response.web_search_call.searching\":\n        if (!searchStarted.has(event.item_id)) {\n          searchStarted.add(event.item_id);\n          yield { type: \"search\", action: \"search\", status: \"started\", cursor, rawEvent: event };\n        }\n        break;\n      case \"response.web_search_call.completed\":\n        yield { type: \"search\", action: \"search\", status: \"completed\", cursor, rawEvent: event };\n        break;\n\n      case \"response.code_interpreter_call.completed\":\n        yield {\n          type: \"tool\",\n          tool: \"code_interpreter\",\n          status: \"completed\",\n          cursor,\n          rawEvent: event,\n        };\n        break;\n      case \"response.file_search_call.completed\":\n        yield { type: \"tool\", tool: \"file_search\", status: \"completed\", cursor, rawEvent: event };\n        break;\n      case \"response.mcp_call.completed\":\n        yield { type: \"tool\", tool: \"mcp\", status: \"completed\", cursor, rawEvent: event };\n        break;\n\n      case \"response.reasoning_summary_text.delta\":\n        yield { type: \"thinking\", delta: event.delta, cursor, rawEvent: event };\n        break;\n\n      case \"response.output_text.delta\":\n        yield { type: \"text\", delta: event.delta, cursor, rawEvent: event };\n        break;\n\n      case \"response.output_text.annotation.added\": {\n        const citation = annotationToCitation(event.annotation);\n        if (citation) {\n          yield { type: \"citation\", citation, cursor, rawEvent: event };\n        }\n        break;\n      }\n\n      case \"response.completed\":\n      case \"response.failed\":\n      case \"response.incomplete\": {\n        const response = event.response;\n        yield { type: \"usage\", usage: usageFromResponse(response), cursor, rawEvent: event };\n        if (event.type === \"response.failed\") {\n          const message = response.error?.message ?? \"OpenAI research run failed\";\n          yield {\n            type: \"error\",\n            error: { message, code: response.error?.code ?? undefined, retryable: false },\n            cursor,\n          };\n        }\n        yield { ...doneEventFromResponse(response), cursor };\n        break;\n      }\n\n      case \"error\": {\n        const err = new Error(event.message ?? \"OpenAI stream error\");\n        yield {\n          type: \"error\",\n          error: {\n            message: event.message ?? \"OpenAI stream error\",\n            code: event.code ?? undefined,\n            retryable: isRetryableError(err),\n          },\n          cursor,\n          rawEvent: event,\n        };\n        break;\n      }\n\n      default: {\n        // Terminal statuses without a typed SDK event (e.g. response.cancelled).\n        const type = (event as { type: string }).type;\n        if (type === \"response.cancelled\") {\n          const response = (event as unknown as { response: Response }).response;\n          // Parity with the typed terminal branches: a cancelled run may have\n          // accrued token/search usage — cost tracking shouldn't be blind here.\n          yield { type: \"usage\", usage: usageFromResponse(response), cursor, rawEvent: event };\n          yield { ...doneEventFromResponse(response), cursor };\n        }\n        // All other events (content_part boundaries, obfuscation padding,\n        // reasoning summary part events, ...) carry no research semantics.\n        break;\n      }\n    }\n  }\n}\n\n// =============================================================================\n// Lifecycle: start / resume / status / cancel\n// =============================================================================\n\n/** Abortable sleep. */\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n  return new Promise((resolve, reject) => {\n    if (signal?.aborted) {\n      reject(abortError());\n      return;\n    }\n    const timer = setTimeout(() => {\n      signal?.removeEventListener(\"abort\", onAbort);\n      resolve();\n    }, ms);\n    (timer as { unref?: () => void }).unref?.();\n    const onAbort = () => {\n      clearTimeout(timer);\n      reject(abortError());\n    };\n    signal?.addEventListener(\"abort\", onAbort, { once: true });\n  });\n}\n\nfunction abortError(): Error {\n  const error = new Error(\"The operation was aborted\");\n  error.name = \"AbortError\";\n  return error;\n}\n\n/** Retry helper for idempotent-or-safe calls, honoring Retry-After. */\nasync function withRetries<T>(\n  fn: () => Promise<T>,\n  maxRetries: number,\n  signal?: AbortSignal,\n): Promise<T> {\n  let attempt = 0;\n  while (true) {\n    try {\n      return await fn();\n    } catch (error) {\n      const err = error instanceof Error ? error : new Error(String(error));\n      if (isAbortError(err) || !isRetryableError(err) || attempt >= maxRetries) {\n        throw err;\n      }\n      attempt += 1;\n      const retryAfter = extractRetryAfterMs(err);\n      await sleep(retryAfter ?? RESEARCH_POLL_INTERVAL_MS, signal);\n    }\n  }\n}\n\nconst requestOptions = (signal?: AbortSignal) => ({\n  timeout: OPENAI_RESEARCH_HTTP_TIMEOUT_MS,\n  signal,\n});\n\n/**\n * Start a research run. Streaming specs get a live SSE stream; non-streaming\n * specs (gpt-5.5-pro) run background create + poll with status heartbeats.\n */\nexport function startOpenAIResearch(\n  client: OpenAI,\n  options: ResearchOptions,\n  modelId: string,\n  spec: ResearchModelSpec | undefined,\n): AsyncIterable<ResearchEvent> {\n  const request = buildResponsesResearchRequest(options, spec, modelId);\n  const streaming = spec?.capabilities.streaming ?? true;\n\n  if (streaming) {\n    return (async function* () {\n      const stream = await withRetries(\n        () =>\n          client.responses.create(\n            { ...request, stream: true },\n            requestOptions(options.signal),\n          ) as Promise<AsyncIterable<ResponseStreamEvent>>,\n        OPENAI_RESEARCH_CREATE_MAX_RETRIES,\n        options.signal,\n      );\n      yield* normalizeResponsesStream(stream);\n    })();\n  }\n\n  return (async function* () {\n    const created = await withRetries(\n      () =>\n        client.responses.create(\n          { ...request, background: true, store: true, stream: false },\n          requestOptions(options.signal),\n        ) as Promise<Response>,\n      OPENAI_RESEARCH_CREATE_MAX_RETRIES,\n      options.signal,\n    );\n    yield { type: \"created\", jobId: created.id, rawEvent: created } as ResearchEvent;\n    yield* pollResponseToCompletion(client, created.id, created, options.signal);\n  })();\n}\n\n/** Emit the terminal event sequence for a finished response. */\nfunction* emitTerminalResponse(response: Response): Generator<ResearchEvent> {\n  const status = mapResponseStatus(response.status);\n  const { report, citations } = extractReportFromResponse(response);\n  if (report.length > 0) {\n    yield { type: \"text\", delta: report };\n  }\n  for (const citation of citations) {\n    yield { type: \"citation\", citation };\n  }\n  yield { type: \"usage\", usage: usageFromResponse(response) };\n  if (status === \"failed\") {\n    yield {\n      type: \"error\",\n      error: {\n        message: response.error?.message ?? \"OpenAI research run failed\",\n        code: response.error?.code ?? undefined,\n        retryable: false,\n      },\n    };\n  }\n  yield doneEventFromResponse(response);\n}\n\n/**\n * Poll a background response until terminal, emitting status heartbeats and\n * a final text + done. Used by the non-streaming path and poll-mode resume.\n */\nasync function* pollResponseToCompletion(\n  client: OpenAI,\n  responseId: string,\n  initial: Response | undefined,\n  signal?: AbortSignal,\n): AsyncGenerator<ResearchEvent> {\n  let interval = RESEARCH_POLL_INTERVAL_MS;\n  let current = initial;\n\n  while (true) {\n    const status = mapResponseStatus(current?.status);\n    yield { type: \"status\", status, rawEvent: current };\n\n    if (current && isTerminalStatus(status)) {\n      yield* emitTerminalResponse(current);\n      return;\n    }\n\n    await sleep(interval, signal);\n    interval = Math.min(interval * RESEARCH_POLL_BACKOFF_FACTOR, RESEARCH_POLL_MAX_INTERVAL_MS);\n    current = await withRetries(\n      () => client.responses.retrieve(responseId, {}, requestOptions(signal)) as Promise<Response>,\n      OPENAI_RESEARCH_POLL_MAX_RETRIES,\n      signal,\n    );\n  }\n}\n\nfunction isTerminalStatus(status: ResearchStatus): boolean {\n  return (\n    status === \"completed\" ||\n    status === \"failed\" ||\n    status === \"cancelled\" ||\n    status === \"incomplete\"\n  );\n}\n\n/**\n * Re-attach to a background run. Streaming-capable models resume the SSE\n * stream from the ref's cursor (`starting_after`); poll-only models re-enter\n * the poll loop.\n */\nexport function resumeOpenAIResearch(\n  client: OpenAI,\n  ref: ResearchJobRef,\n  spec: ResearchModelSpec | undefined,\n  signal?: AbortSignal,\n): AsyncIterable<ResearchEvent> {\n  const streaming = spec?.capabilities.streaming ?? true;\n\n  if (streaming) {\n    return (async function* () {\n      // Status-first: a job that finished while detached has nothing left to\n      // stream, and OpenAI's stream-resume HANGS on terminal responses\n      // (observed live). Emit the terminal sequence directly in that case.\n      const current = await withRetries(\n        () => client.responses.retrieve(ref.jobId, {}, requestOptions(signal)) as Promise<Response>,\n        OPENAI_RESEARCH_POLL_MAX_RETRIES,\n        signal,\n      );\n      if (isTerminalStatus(mapResponseStatus(current.status))) {\n        yield { type: \"status\", status: mapResponseStatus(current.status) } as ResearchEvent;\n        yield* emitTerminalResponse(current);\n        return;\n      }\n\n      const stream = (await client.responses.retrieve(\n        ref.jobId,\n        {\n          stream: true,\n          ...(ref.cursor !== undefined ? { starting_after: Number(ref.cursor) } : {}),\n        },\n        requestOptions(signal),\n      )) as AsyncIterable<ResponseStreamEvent>;\n      yield* normalizeResponsesStream(stream);\n    })();\n  }\n\n  return pollResponseToCompletion(client, ref.jobId, undefined, signal);\n}\n\n/** One-shot status poll; returns the terminal result when available. */\nexport async function getOpenAIResearchStatus(\n  client: OpenAI,\n  ref: ResearchJobRef,\n): Promise<ResearchStatusSnapshot> {\n  const response = (await client.responses.retrieve(ref.jobId, {})) as Response;\n  const status = mapResponseStatus(response.status);\n  if (!isTerminalStatus(status)) {\n    return { status };\n  }\n  const { report, citations } = extractReportFromResponse(response);\n  return {\n    status,\n    result: {\n      jobId: response.id,\n      provider: \"openai\",\n      model: ref.model,\n      status,\n      report,\n      citations,\n      usage: usageFromResponse(response),\n      raw: response,\n    },\n  };\n}\n\nexport async function cancelOpenAIResearch(client: OpenAI, ref: ResearchJobRef): Promise<void> {\n  await client.responses.cancel(ref.jobId);\n}\n","/**\n * OpenAI research model catalog (Responses API deep research).\n *\n * Research capability is catalog-driven — nothing outside this file should\n * test OpenAI model-id strings for research support.\n *\n * ⚠️ `o3-deep-research` and `o4-mini-deep-research` (and their dated\n * snapshots) are deprecated upstream with shutdown on 2026-07-23; the\n * namespace warns/throws based on the metadata below. `gpt-5.5-pro` is the\n * durable research path (background + poll only — no streaming).\n *\n * Pricing verified 2026-07-02 against developers.openai.com/api/docs/pricing.\n */\n\nimport type { ResearchModelSpec } from \"../research/model-spec.js\";\n\n/** All four data-source/auxiliary tool types are accepted by DR models. */\nconst DEEP_RESEARCH_TOOLS: ResearchModelSpec[\"capabilities\"][\"tools\"] = [\n  \"web_search\",\n  \"file_search\",\n  \"mcp\",\n  \"code_interpreter\",\n];\n\nconst DEEP_RESEARCH_SHUTDOWN = {\n  deprecationDate: \"2026-04-22\",\n  shutdownDate: \"2026-07-23\",\n  replacement: \"gpt-5.5-pro\",\n} as const;\n\nfunction o3DeepResearch(modelId: string): ResearchModelSpec {\n  return {\n    provider: \"openai\",\n    modelId,\n    kind: \"model\",\n    displayName: \"o3 Deep Research\",\n    contextWindow: 200_000,\n    maxOutputTokens: 100_000,\n    pricing: { input: 10, cachedInput: 2.5, output: 40, perThousandSearches: 10 },\n    capabilities: {\n      streaming: true,\n      background: true,\n      resumable: true,\n      tools: DEEP_RESEARCH_TOOLS,\n    },\n    requiredTools: [{ type: \"web_search\" }],\n    metadata: { releaseDate: \"2025-06-26\", ...DEEP_RESEARCH_SHUTDOWN },\n  };\n}\n\nfunction o4MiniDeepResearch(modelId: string): ResearchModelSpec {\n  return {\n    provider: \"openai\",\n    modelId,\n    kind: \"model\",\n    displayName: \"o4-mini Deep Research\",\n    contextWindow: 200_000,\n    maxOutputTokens: 100_000,\n    pricing: { input: 2, cachedInput: 0.5, output: 8, perThousandSearches: 10 },\n    capabilities: {\n      streaming: true,\n      background: true,\n      resumable: true,\n      tools: DEEP_RESEARCH_TOOLS,\n    },\n    requiredTools: [{ type: \"web_search\" }],\n    metadata: { releaseDate: \"2025-06-26\", ...DEEP_RESEARCH_SHUTDOWN },\n  };\n}\n\nexport const openaiResearchModels: ResearchModelSpec[] = [\n  o3DeepResearch(\"o3-deep-research\"),\n  o3DeepResearch(\"o3-deep-research-2025-06-26\"),\n  o4MiniDeepResearch(\"o4-mini-deep-research\"),\n  o4MiniDeepResearch(\"o4-mini-deep-research-2025-06-26\"),\n  {\n    provider: \"openai\",\n    modelId: \"gpt-5.5-pro\",\n    kind: \"model\",\n    displayName: \"GPT-5.5 Pro (research)\",\n    contextWindow: 1_050_000,\n    maxOutputTokens: 128_000,\n    pricing: { input: 30, output: 180, perThousandSearches: 10 },\n    capabilities: {\n      // No live streaming — runs execute via background create + poll.\n      streaming: false,\n      background: true,\n      // Resumable in the attach sense: the poll loop re-attaches by job id.\n      resumable: true,\n      tools: DEEP_RESEARCH_TOOLS,\n    },\n    requiredTools: [{ type: \"web_search\" }],\n    metadata: {\n      releaseDate: \"2026-04-24\",\n      notes: \"Designated replacement for the o3/o4-mini deep research models.\",\n    },\n  },\n];\n\nconst byId = new Map(openaiResearchModels.map((spec) => [spec.modelId, spec]));\n\nexport function getOpenAIResearchModelSpec(modelId: string): ResearchModelSpec | undefined {\n  return byId.get(modelId);\n}\n\nexport function isOpenAIResearchModel(modelId: string): boolean {\n  return byId.has(modelId);\n}\n","/**\n * OpenAI Speech (TTS) Model Catalog\n *\n * Pricing as of December 2025:\n * - tts-1: $15.00 per 1M characters\n * - tts-1-hd: $30.00 per 1M characters\n * - gpt-4o-mini-tts: $0.60/1M input tokens + $12/1M audio output tokens (~$0.015/min)\n *\n * @see https://platform.openai.com/docs/guides/text-to-speech\n */\n\nimport type { AudioFormat, SpeechModelSpec } from \"../core/media-types.js\";\n\n/** OpenAI TTS voices for standard models (tts-1, tts-1-hd) */\nexport const OPENAI_TTS_VOICES = [\"alloy\", \"echo\", \"fable\", \"onyx\", \"nova\", \"shimmer\"] as const;\n\n/** Additional voices available in gpt-4o-mini-tts */\nexport const OPENAI_TTS_EXTENDED_VOICES = [\n  ...OPENAI_TTS_VOICES,\n  \"ash\",\n  \"ballad\",\n  \"coral\",\n  \"sage\",\n  \"verse\",\n] as const;\n\nexport type OpenAITTSVoice = (typeof OPENAI_TTS_VOICES)[number];\nexport type OpenAITTSExtendedVoice = (typeof OPENAI_TTS_EXTENDED_VOICES)[number];\n\n/** OpenAI supported audio formats */\nexport const OPENAI_TTS_FORMATS: AudioFormat[] = [\"mp3\", \"opus\", \"aac\", \"flac\", \"wav\", \"pcm\"];\n\n/**\n * OpenAI Speech Model Specifications\n */\nexport const openaiSpeechModels: SpeechModelSpec[] = [\n  // Standard TTS models (character-based pricing)\n  {\n    provider: \"openai\",\n    modelId: \"tts-1\",\n    displayName: \"TTS-1\",\n    pricing: {\n      // $15 per 1M characters = $0.000015 per character\n      perCharacter: 0.000015,\n    },\n    voices: [...OPENAI_TTS_VOICES],\n    formats: OPENAI_TTS_FORMATS,\n    maxInputLength: 4096,\n    defaultVoice: \"alloy\",\n    defaultFormat: \"mp3\",\n    features: {\n      voiceInstructions: false,\n    },\n  },\n  {\n    provider: \"openai\",\n    modelId: \"tts-1-1106\",\n    displayName: \"TTS-1 (Nov 2023)\",\n    pricing: {\n      perCharacter: 0.000015,\n    },\n    voices: [...OPENAI_TTS_VOICES],\n    formats: OPENAI_TTS_FORMATS,\n    maxInputLength: 4096,\n    defaultVoice: \"alloy\",\n    defaultFormat: \"mp3\",\n    features: {\n      voiceInstructions: false,\n    },\n  },\n  {\n    provider: \"openai\",\n    modelId: \"tts-1-hd\",\n    displayName: \"TTS-1 HD\",\n    pricing: {\n      // $30 per 1M characters = $0.00003 per character\n      perCharacter: 0.00003,\n    },\n    voices: [...OPENAI_TTS_VOICES],\n    formats: OPENAI_TTS_FORMATS,\n    maxInputLength: 4096,\n    defaultVoice: \"alloy\",\n    defaultFormat: \"mp3\",\n    features: {\n      voiceInstructions: false,\n    },\n  },\n  {\n    provider: \"openai\",\n    modelId: \"tts-1-hd-1106\",\n    displayName: \"TTS-1 HD (Nov 2023)\",\n    pricing: {\n      perCharacter: 0.00003,\n    },\n    voices: [...OPENAI_TTS_VOICES],\n    formats: OPENAI_TTS_FORMATS,\n    maxInputLength: 4096,\n    defaultVoice: \"alloy\",\n    defaultFormat: \"mp3\",\n    features: {\n      voiceInstructions: false,\n    },\n  },\n  // Token-based TTS model with voice instructions support\n  {\n    provider: \"openai\",\n    modelId: \"gpt-4o-mini-tts\",\n    displayName: \"GPT-4o Mini TTS\",\n    pricing: {\n      // $0.60 per 1M input tokens = $0.0000006 per token\n      perInputToken: 0.0000006,\n      // $12 per 1M audio output tokens = $0.000012 per token\n      perAudioOutputToken: 0.000012,\n      // ~$0.015 per minute of audio\n      perMinute: 0.015,\n    },\n    voices: [...OPENAI_TTS_EXTENDED_VOICES],\n    formats: OPENAI_TTS_FORMATS,\n    maxInputLength: 2000, // tokens, not characters\n    defaultVoice: \"alloy\",\n    defaultFormat: \"mp3\",\n    features: {\n      voiceInstructions: true,\n    },\n  },\n];\n\n/**\n * Get speech model spec by model ID.\n */\nexport function getOpenAISpeechModelSpec(modelId: string): SpeechModelSpec | undefined {\n  return openaiSpeechModels.find((m) => m.modelId === modelId);\n}\n\n/**\n * Check if a model ID is an OpenAI speech model.\n */\nexport function isOpenAISpeechModel(modelId: string): boolean {\n  return openaiSpeechModels.some((m) => m.modelId === modelId);\n}\n\n/**\n * Calculate cost for speech generation.\n *\n * For character-based models (tts-1, tts-1-hd): cost = characters * perCharacter\n * For token-based models (gpt-4o-mini-tts): uses perMinute approximation\n *\n * @param modelId - The model ID\n * @param characterCount - Number of characters in the input\n * @param estimatedMinutes - Optional: estimated audio duration for token-based models\n * @returns Cost in USD, or undefined if model not found\n */\nexport function calculateOpenAISpeechCost(\n  modelId: string,\n  characterCount: number,\n  estimatedMinutes?: number,\n): number | undefined {\n  const spec = getOpenAISpeechModelSpec(modelId);\n  if (!spec) return undefined;\n\n  // Character-based pricing (tts-1, tts-1-hd)\n  if (spec.pricing.perCharacter !== undefined) {\n    return characterCount * spec.pricing.perCharacter;\n  }\n\n  // Token-based pricing (gpt-4o-mini-tts) - use per-minute approximation\n  if (spec.pricing.perMinute !== undefined && estimatedMinutes !== undefined) {\n    return estimatedMinutes * spec.pricing.perMinute;\n  }\n\n  // Fallback: rough estimate based on ~150 words/min, ~5 chars/word\n  // ~750 chars/min of audio\n  if (spec.pricing.perMinute !== undefined) {\n    const approxMinutes = characterCount / 750;\n    return approxMinutes * spec.pricing.perMinute;\n  }\n\n  return undefined;\n}\n","import OpenAI from \"openai\";\nimport type {\n  ChatCompletionChunk,\n  ChatCompletionContentPart,\n  ChatCompletionMessageParam,\n} from \"openai/resources/chat/completions\";\nimport { encoding_for_model, type TiktokenModel } from \"tiktoken\";\nimport type { ContentPart, ImageContentPart } from \"../core/input-content.js\";\nimport type {\n  ImageGenerationOptions,\n  ImageGenerationResult,\n  ImageModelSpec,\n  SpeechGenerationOptions,\n  SpeechGenerationResult,\n  SpeechModelSpec,\n} from \"../core/media-types.js\";\nimport type { LLMMessage, MessageContent } from \"../core/messages.js\";\nimport { extractMessageText, normalizeMessageContent } from \"../core/messages.js\";\nimport type { ModelSpec } from \"../core/model-catalog.js\";\nimport type {\n  LLMGenerationOptions,\n  LLMStream,\n  ModelDescriptor,\n  ReasoningEffort,\n} from \"../core/options.js\";\nimport type { ResearchModelSpec } from \"../research/model-spec.js\";\nimport type {\n  ResearchEvent,\n  ResearchJobRef,\n  ResearchOptions,\n  ResearchStatusSnapshot,\n} from \"../research/types.js\";\nimport { BaseProviderAdapter } from \"./base-provider.js\";\nimport {\n  FALLBACK_CHARS_PER_TOKEN,\n  OPENAI_MESSAGE_OVERHEAD_TOKENS,\n  OPENAI_NAME_FIELD_OVERHEAD_TOKENS,\n  OPENAI_REPLY_PRIMING_TOKENS,\n} from \"./constants.js\";\nimport {\n  calculateOpenAIImageCost,\n  getOpenAIImageModelSpec,\n  isOpenAIImageModel,\n  openaiImageModels,\n} from \"./openai-image-models.js\";\nimport { OPENAI_MODELS } from \"./openai-models.js\";\nimport {\n  cancelOpenAIResearch,\n  getOpenAIResearchStatus,\n  resumeOpenAIResearch,\n  startOpenAIResearch,\n} from \"./openai-research.js\";\nimport {\n  getOpenAIResearchModelSpec,\n  isOpenAIResearchModel,\n  openaiResearchModels,\n} from \"./openai-research-models.js\";\nimport {\n  calculateOpenAISpeechCost,\n  getOpenAISpeechModelSpec,\n  isOpenAISpeechModel,\n  openaiSpeechModels,\n} from \"./openai-speech-models.js\";\nimport { createProviderFromEnv } from \"./utils.js\";\n\nconst ROLE_MAP: Record<LLMMessage[\"role\"], \"system\" | \"user\" | \"assistant\"> = {\n  system: \"system\",\n  user: \"user\",\n  assistant: \"assistant\",\n};\n\n// Note: Temperature support is now determined from the ModelSpec passed to stream()\n// instead of being hardcoded at module level\n\n/** Maps llmist reasoning effort levels to OpenAI's reasoning effort parameter */\nconst OPENAI_EFFORT_MAP: Record<ReasoningEffort, string> = {\n  none: \"none\",\n  low: \"low\",\n  medium: \"medium\",\n  high: \"high\",\n  maximum: \"xhigh\",\n};\n\nfunction sanitizeExtra(\n  extra: Record<string, unknown> | undefined,\n  allowTemperature: boolean,\n): Record<string, unknown> | undefined {\n  if (!extra) {\n    return undefined;\n  }\n\n  if (allowTemperature || !Object.hasOwn(extra, \"temperature\")) {\n    return extra;\n  }\n\n  return Object.fromEntries(Object.entries(extra).filter(([key]) => key !== \"temperature\"));\n}\n\nexport class OpenAIChatProvider extends BaseProviderAdapter {\n  readonly providerId = \"openai\" as const;\n\n  supports(descriptor: ModelDescriptor): boolean {\n    return descriptor.provider === this.providerId;\n  }\n\n  getModelSpecs() {\n    return OPENAI_MODELS;\n  }\n\n  // =========================================================================\n  // Image Generation\n  // =========================================================================\n\n  getImageModelSpecs(): ImageModelSpec[] {\n    return openaiImageModels;\n  }\n\n  supportsImageGeneration(modelId: string): boolean {\n    return isOpenAIImageModel(modelId);\n  }\n\n  async generateImage(options: ImageGenerationOptions): Promise<ImageGenerationResult> {\n    const client = this.client as OpenAI;\n    const spec = getOpenAIImageModelSpec(options.model);\n\n    const size = options.size ?? spec?.defaultSize ?? \"1024x1024\";\n    const quality = options.quality ?? spec?.defaultQuality ?? \"standard\";\n    const n = options.n ?? 1;\n\n    // Determine which parameters to include based on model capabilities\n    const isDallE2 = options.model === \"dall-e-2\";\n    const isGptImage = options.model.startsWith(\"gpt-image\");\n\n    // Build request payload conditionally\n    // - DALL-E 2: no quality parameter, no response_format\n    // - GPT Image: quality uses low/medium/high, no response_format (uses output_format)\n    // - DALL-E 3: supports quality (standard/hd) and response_format\n    const requestParams: Parameters<typeof client.images.generate>[0] = {\n      model: options.model,\n      prompt: options.prompt,\n      size: size as \"1024x1024\" | \"1024x1792\" | \"1792x1024\" | \"256x256\" | \"512x512\",\n      n,\n    };\n\n    // Only DALL-E 3 supports the quality parameter with standard/hd values\n    if (!isDallE2 && !isGptImage) {\n      requestParams.quality = quality as \"standard\" | \"hd\";\n    }\n\n    // GPT Image models use output_format instead of response_format\n    if (isGptImage) {\n      // GPT Image supports: png, webp, jpeg\n      // Map b64_json to the default format (png) since GPT Image API is different\n      // For now, we'll always return URLs for GPT Image models\n      // Note: GPT Image API uses different response structure\n    } else if (!isDallE2) {\n      // DALL-E 3 supports response_format\n      requestParams.response_format = options.responseFormat ?? \"url\";\n    }\n\n    const response = await client.images.generate(requestParams);\n\n    const cost = calculateOpenAIImageCost(options.model, size, quality, n);\n    // Type assertion: we're not using streaming, so response is ImagesResponse\n    const images = (response as OpenAI.Images.ImagesResponse).data ?? [];\n\n    return {\n      images: images.map((img) => ({\n        url: img.url,\n        b64Json: img.b64_json,\n        revisedPrompt: img.revised_prompt,\n      })),\n      model: options.model,\n      usage: {\n        imagesGenerated: images.length,\n        size,\n        quality,\n      },\n      cost,\n    };\n  }\n\n  // =========================================================================\n  // Speech Generation\n  // =========================================================================\n\n  getSpeechModelSpecs(): SpeechModelSpec[] {\n    return openaiSpeechModels;\n  }\n\n  supportsSpeechGeneration(modelId: string): boolean {\n    return isOpenAISpeechModel(modelId);\n  }\n\n  async generateSpeech(options: SpeechGenerationOptions): Promise<SpeechGenerationResult> {\n    const client = this.client as OpenAI;\n    const spec = getOpenAISpeechModelSpec(options.model);\n\n    const format = options.responseFormat ?? spec?.defaultFormat ?? \"mp3\";\n    const voice = options.voice ?? spec?.defaultVoice ?? \"alloy\";\n\n    const response = await client.audio.speech.create({\n      model: options.model,\n      input: options.input,\n      voice: voice as \"alloy\" | \"echo\" | \"fable\" | \"onyx\" | \"nova\" | \"shimmer\",\n      response_format: format as \"mp3\" | \"opus\" | \"aac\" | \"flac\" | \"wav\" | \"pcm\",\n      speed: options.speed ?? 1.0,\n    });\n\n    const audioBuffer = await response.arrayBuffer();\n    const cost = calculateOpenAISpeechCost(options.model, options.input.length);\n\n    return {\n      audio: audioBuffer,\n      model: options.model,\n      usage: {\n        characterCount: options.input.length,\n      },\n      cost,\n      format,\n    };\n  }\n\n  // =========================================================================\n  // Deep Research (Responses API)\n  // =========================================================================\n\n  getResearchModelSpecs(): ResearchModelSpec[] {\n    return openaiResearchModels;\n  }\n\n  supportsResearch(modelId: string): boolean {\n    return isOpenAIResearchModel(modelId);\n  }\n\n  startResearch(\n    options: ResearchOptions,\n    descriptor: ModelDescriptor,\n    spec?: ResearchModelSpec,\n  ): AsyncIterable<ResearchEvent> {\n    return startOpenAIResearch(this.client as OpenAI, options, descriptor.name, spec);\n  }\n\n  resumeResearch(ref: ResearchJobRef, signal?: AbortSignal): AsyncIterable<ResearchEvent> {\n    return resumeOpenAIResearch(\n      this.client as OpenAI,\n      ref,\n      getOpenAIResearchModelSpec(ref.model),\n      signal,\n    );\n  }\n\n  getResearchStatus(ref: ResearchJobRef): Promise<ResearchStatusSnapshot> {\n    return getOpenAIResearchStatus(this.client as OpenAI, ref);\n  }\n\n  cancelResearch(ref: ResearchJobRef): Promise<void> {\n    return cancelOpenAIResearch(this.client as OpenAI, ref);\n  }\n\n  protected buildApiRequest(\n    options: LLMGenerationOptions,\n    descriptor: ModelDescriptor,\n    spec: ModelSpec | undefined,\n    messages: LLMMessage[],\n  ): Parameters<OpenAI[\"chat\"][\"completions\"][\"create\"]>[0] {\n    const { maxTokens, temperature, topP, stopSequences, extra, reasoning } = options;\n\n    // Use spec metadata to determine temperature support, defaulting to true if spec is unavailable\n    const supportsTemperature = spec?.metadata?.supportsTemperature !== false;\n    const shouldIncludeTemperature = typeof temperature === \"number\" && supportsTemperature;\n    const sanitizedExtra = sanitizeExtra(extra, shouldIncludeTemperature);\n\n    // Build reasoning parameter for OpenAI reasoning models (o-series, etc.)\n    const reasoningParam =\n      reasoning?.enabled !== undefined\n        ? {\n            reasoning: {\n              effort: OPENAI_EFFORT_MAP[reasoning.effort ?? \"medium\"],\n            },\n          }\n        : {};\n\n    return {\n      model: descriptor.name,\n      messages: messages.map((message) => this.convertToOpenAIMessage(message)),\n      // Only set max_completion_tokens if explicitly provided\n      // Otherwise let the API use \"as much as fits\" in the context window\n      ...(maxTokens !== undefined ? { max_completion_tokens: maxTokens } : {}),\n      top_p: topP,\n      stop: stopSequences,\n      stream: true,\n      stream_options: { include_usage: true },\n      ...reasoningParam,\n      ...(sanitizedExtra ?? {}),\n      ...(shouldIncludeTemperature ? { temperature } : {}),\n    };\n  }\n\n  /**\n   * Convert an LLMMessage to OpenAI's ChatCompletionMessageParam.\n   * Handles role-specific content type requirements:\n   * - system/assistant: string content only\n   * - user: string or multimodal array content\n   */\n  private convertToOpenAIMessage(message: LLMMessage): ChatCompletionMessageParam {\n    const role = ROLE_MAP[message.role];\n\n    // User messages support multimodal content\n    if (role === \"user\") {\n      const content = this.convertToOpenAIContent(message.content);\n      return {\n        role: \"user\",\n        content,\n        ...(message.name ? { name: message.name } : {}),\n      };\n    }\n\n    // System and assistant messages only support string content\n    const textContent =\n      typeof message.content === \"string\" ? message.content : extractMessageText(message.content);\n\n    if (role === \"system\") {\n      return {\n        role: \"system\",\n        content: textContent,\n        ...(message.name ? { name: message.name } : {}),\n      };\n    }\n\n    // Assistant role\n    return {\n      role: \"assistant\",\n      content: textContent,\n      ...(message.name ? { name: message.name } : {}),\n    };\n  }\n\n  /**\n   * Convert llmist content to OpenAI's content format.\n   * Optimizes by returning string for text-only content, array for multimodal.\n   */\n  private convertToOpenAIContent(content: MessageContent): string | ChatCompletionContentPart[] {\n    // Optimization: keep simple string content as-is\n    if (typeof content === \"string\") {\n      return content;\n    }\n\n    // Convert array content to OpenAI format\n    return content.map((part) => {\n      if (part.type === \"text\") {\n        return { type: \"text\" as const, text: part.text };\n      }\n\n      if (part.type === \"image\") {\n        return this.convertImagePart(part);\n      }\n\n      if (part.type === \"audio\") {\n        throw new Error(\n          \"OpenAI chat completions do not support audio input. Use Whisper for transcription or Gemini for audio understanding.\",\n        );\n      }\n\n      throw new Error(`Unsupported content type: ${(part as ContentPart).type}`);\n    });\n  }\n\n  /**\n   * Convert an image content part to OpenAI's image_url format.\n   * Supports both URLs and base64 data URLs.\n   */\n  private convertImagePart(part: ImageContentPart): ChatCompletionContentPart {\n    if (part.source.type === \"url\") {\n      return {\n        type: \"image_url\" as const,\n        image_url: { url: part.source.url },\n      };\n    }\n\n    // Convert base64 to data URL format\n    return {\n      type: \"image_url\" as const,\n      image_url: {\n        url: `data:${part.source.mediaType};base64,${part.source.data}`,\n      },\n    };\n  }\n\n  protected async executeStreamRequest(\n    payload: Parameters<OpenAI[\"chat\"][\"completions\"][\"create\"]>[0],\n    signal?: AbortSignal,\n  ): Promise<AsyncIterable<ChatCompletionChunk>> {\n    const client = this.client as OpenAI;\n    // Pass abort signal to SDK via request options\n    const stream = await client.chat.completions.create(payload, signal ? { signal } : undefined);\n    return stream as unknown as AsyncIterable<ChatCompletionChunk>;\n  }\n\n  protected async *normalizeProviderStream(iterable: AsyncIterable<unknown>): LLMStream {\n    const stream = iterable as AsyncIterable<ChatCompletionChunk>;\n    for await (const chunk of stream) {\n      const text = chunk.choices.map((choice) => choice.delta?.content ?? \"\").join(\"\");\n      if (text) {\n        yield { text, rawEvent: chunk };\n      }\n\n      const finishReason = chunk.choices.find((choice) => choice.finish_reason)?.finish_reason;\n\n      // Extract token usage if available (typically in the final chunk)\n      // OpenAI returns cached token count in prompt_tokens_details.cached_tokens\n      // and reasoning tokens in completion_tokens_details.reasoning_tokens\n      type OpenAIUsageDetails = {\n        prompt_tokens_details?: { cached_tokens?: number };\n        completion_tokens_details?: { reasoning_tokens?: number };\n      };\n      const usageDetails = chunk.usage as (typeof chunk.usage & OpenAIUsageDetails) | undefined;\n      const usage = chunk.usage\n        ? {\n            inputTokens: chunk.usage.prompt_tokens,\n            outputTokens: chunk.usage.completion_tokens,\n            totalTokens: chunk.usage.total_tokens,\n            cachedInputTokens: usageDetails?.prompt_tokens_details?.cached_tokens ?? 0,\n            reasoningTokens: usageDetails?.completion_tokens_details?.reasoning_tokens,\n          }\n        : undefined;\n\n      if (finishReason || usage) {\n        yield { text: \"\", finishReason, usage, rawEvent: chunk };\n      }\n    }\n  }\n\n  /**\n   * Count tokens in messages using OpenAI's tiktoken library.\n   *\n   * This method provides accurate token estimation for OpenAI models by:\n   * - Using the model-specific tokenizer encoding\n   * - Accounting for message formatting overhead\n   * - Falling back to gpt-4o encoding for unknown models\n   *\n   * @param messages - The messages to count tokens for\n   * @param descriptor - Model descriptor containing the model name\n   * @param _spec - Optional model specification (currently unused)\n   * @returns Promise resolving to the estimated input token count\n   *\n   * @throws Never throws - falls back to character-based estimation (4 chars/token) on error\n   *\n   * @example\n   * ```typescript\n   * const count = await provider.countTokens(\n   *   [{ role: \"user\", content: \"Hello!\" }],\n   *   { provider: \"openai\", name: \"gpt-4\" }\n   * );\n   * ```\n   */\n  async countTokens(\n    messages: LLMMessage[],\n    descriptor: ModelDescriptor,\n    _spec?: ModelSpec,\n  ): Promise<number> {\n    try {\n      // Map model names to tiktoken models\n      // For models not directly supported, use a reasonable default\n      const modelName = descriptor.name as TiktokenModel;\n      let encoding;\n\n      try {\n        encoding = encoding_for_model(modelName);\n      } catch {\n        // If the specific model isn't supported, fall back to gpt-4o which uses cl100k_base\n        encoding = encoding_for_model(\"gpt-4o\");\n      }\n\n      try {\n        let tokenCount = 0;\n        let imageCount = 0;\n\n        // Count tokens per message with proper formatting\n        // OpenAI's format adds tokens for message boundaries and roles\n        // Token overhead based on OpenAI's message formatting\n        // See: https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb\n        for (const message of messages) {\n          // Every message follows <im_start>{role/name}\\n{content}<im_end>\\n\n          tokenCount += OPENAI_MESSAGE_OVERHEAD_TOKENS;\n\n          const roleText = ROLE_MAP[message.role];\n          tokenCount += encoding.encode(roleText).length;\n\n          // Handle multimodal content\n          const textContent = extractMessageText(message.content);\n          tokenCount += encoding.encode(textContent).length;\n\n          // Count images for estimation (each image ~85 tokens base + variable)\n          const parts = normalizeMessageContent(message.content);\n          for (const part of parts) {\n            if (part.type === \"image\") {\n              imageCount++;\n            }\n          }\n\n          if (message.name) {\n            tokenCount += encoding.encode(message.name).length;\n            tokenCount += OPENAI_NAME_FIELD_OVERHEAD_TOKENS;\n          }\n        }\n\n        tokenCount += OPENAI_REPLY_PRIMING_TOKENS;\n        // Add ~765 tokens per image (low detail mode).\n        // Source: https://platform.openai.com/docs/guides/vision\n        // High detail mode varies by image size (510-1105 tokens per 512px tile + 85 base).\n        tokenCount += imageCount * 765;\n\n        return tokenCount;\n      } finally {\n        // Always free the encoding to prevent memory leaks\n        encoding.free();\n      }\n    } catch (error) {\n      // Log the error for debugging\n      console.warn(\n        `Token counting failed for ${descriptor.name}, using fallback estimation:`,\n        error,\n      );\n      // If tiktoken fails, provide a rough estimate\n      let totalChars = 0;\n      let imageCount = 0;\n      for (const msg of messages) {\n        const parts = normalizeMessageContent(msg.content);\n        for (const part of parts) {\n          if (part.type === \"text\") {\n            totalChars += part.text.length;\n          } else if (part.type === \"image\") {\n            imageCount++;\n          }\n        }\n      }\n      // Use same image token estimate as tiktoken path (765 tokens per image).\n      return Math.ceil(totalChars / FALLBACK_CHARS_PER_TOKEN) + imageCount * 765;\n    }\n  }\n}\n\nexport function createOpenAIProviderFromEnv(): OpenAIChatProvider | null {\n  return createProviderFromEnv(\"OPENAI_API_KEY\", OpenAI, OpenAIChatProvider);\n}\n","/**\n * OpenRouter Model Specifications\n *\n * Curated list of popular models available through OpenRouter.\n * OpenRouter provides access to 400+ models, but we include only the most\n * commonly used ones here for discoverability.\n *\n * IMPORTANT: Pricing is approximate and may change. OpenRouter pricing is\n * dynamic and can vary based on provider availability. Check openrouter.ai\n * for current pricing.\n *\n * Model IDs use OpenRouter's format: provider/model-name\n */\n\nimport type { ModelSpec } from \"../core/model-catalog.js\";\n\nexport const OPENROUTER_MODELS: ModelSpec[] = [\n  // ============================================================\n  // Anthropic Claude Models (via OpenRouter)\n  // ============================================================\n  {\n    provider: \"openrouter\",\n    modelId: \"anthropic/claude-sonnet-4-5\",\n    displayName: \"Claude Sonnet 4.5 (OpenRouter)\",\n    contextWindow: 200_000,\n    maxOutputTokens: 64_000,\n    pricing: {\n      input: 3.0,\n      output: 15.0,\n    },\n    knowledgeCutoff: \"2025-01\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: true,\n      reasoning: true,\n    },\n    metadata: {\n      family: \"Claude 4\",\n      notes: \"Anthropic Claude via OpenRouter. Pricing may vary.\",\n    },\n  },\n  {\n    provider: \"openrouter\",\n    modelId: \"anthropic/claude-opus-4-5\",\n    displayName: \"Claude Opus 4.5 (OpenRouter)\",\n    contextWindow: 200_000,\n    maxOutputTokens: 64_000,\n    pricing: {\n      input: 15.0,\n      output: 75.0,\n    },\n    knowledgeCutoff: \"2025-01\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: true,\n      reasoning: true,\n    },\n    metadata: {\n      family: \"Claude 4\",\n      notes: \"Anthropic Claude Opus via OpenRouter. Most capable Claude model.\",\n    },\n  },\n  {\n    provider: \"openrouter\",\n    modelId: \"anthropic/claude-haiku-4-5\",\n    displayName: \"Claude Haiku 4.5 (OpenRouter)\",\n    contextWindow: 200_000,\n    maxOutputTokens: 64_000,\n    pricing: {\n      input: 0.8,\n      output: 4.0,\n    },\n    knowledgeCutoff: \"2025-02\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: true,\n      reasoning: true,\n    },\n    metadata: {\n      family: \"Claude 4\",\n      notes: \"Anthropic Claude Haiku via OpenRouter. Fast and efficient.\",\n    },\n  },\n\n  // ============================================================\n  // OpenAI GPT Models (via OpenRouter)\n  // ============================================================\n  {\n    provider: \"openrouter\",\n    modelId: \"openai/gpt-4o\",\n    displayName: \"GPT-4o (OpenRouter)\",\n    contextWindow: 128_000,\n    maxOutputTokens: 16_384,\n    pricing: {\n      input: 2.5,\n      output: 10.0,\n    },\n    knowledgeCutoff: \"2024-10\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: true,\n    },\n    metadata: {\n      family: \"GPT-4\",\n      notes: \"OpenAI GPT-4o via OpenRouter.\",\n    },\n  },\n  {\n    provider: \"openrouter\",\n    modelId: \"openai/gpt-4o-mini\",\n    displayName: \"GPT-4o Mini (OpenRouter)\",\n    contextWindow: 128_000,\n    maxOutputTokens: 16_384,\n    pricing: {\n      input: 0.15,\n      output: 0.6,\n    },\n    knowledgeCutoff: \"2024-10\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: true,\n    },\n    metadata: {\n      family: \"GPT-4\",\n      notes: \"OpenAI GPT-4o Mini via OpenRouter. Cost-effective option.\",\n    },\n  },\n  {\n    provider: \"openrouter\",\n    modelId: \"openai/gpt-5.2\",\n    displayName: \"GPT-5.2 (OpenRouter)\",\n    contextWindow: 1_000_000,\n    maxOutputTokens: 128_000,\n    pricing: {\n      input: 5.0,\n      output: 20.0,\n    },\n    knowledgeCutoff: \"2025-03\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: true,\n      reasoning: true,\n    },\n    metadata: {\n      family: \"GPT-5\",\n      notes: \"OpenAI GPT-5.2 via OpenRouter. Latest flagship model.\",\n    },\n  },\n\n  // ============================================================\n  // Google Gemini Models (via OpenRouter)\n  // ============================================================\n  {\n    provider: \"openrouter\",\n    modelId: \"google/gemini-2.5-flash\",\n    displayName: \"Gemini 2.5 Flash (OpenRouter)\",\n    contextWindow: 1_048_576,\n    maxOutputTokens: 65_535,\n    pricing: {\n      input: 0.3,\n      output: 2.5,\n    },\n    knowledgeCutoff: \"2025-06\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: true,\n      reasoning: true,\n      structuredOutputs: true,\n    },\n    metadata: {\n      family: \"Gemini 2.5\",\n      releaseDate: \"2025-06-17\",\n      notes:\n        \"Google Gemini 2.5 Flash via OpenRouter. Workhorse model for reasoning, coding, and math.\",\n    },\n  },\n  {\n    provider: \"openrouter\",\n    modelId: \"google/gemini-2.5-pro\",\n    displayName: \"Gemini 2.5 Pro (OpenRouter)\",\n    contextWindow: 1_000_000,\n    maxOutputTokens: 65_536,\n    pricing: {\n      input: 2.5,\n      output: 10.0,\n    },\n    knowledgeCutoff: \"2025-01\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: true,\n      reasoning: true,\n    },\n    metadata: {\n      family: \"Gemini 2.5\",\n      notes: \"Google Gemini 2.5 Pro via OpenRouter.\",\n    },\n  },\n  {\n    provider: \"openrouter\",\n    modelId: \"google/gemini-3-pro-preview\",\n    displayName: \"Gemini 3 Pro Preview (OpenRouter)\",\n    contextWindow: 1_048_576,\n    maxOutputTokens: 65_536,\n    pricing: {\n      input: 2.0,\n      output: 12.0,\n    },\n    knowledgeCutoff: \"2025-11\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: true,\n      reasoning: true,\n      structuredOutputs: true,\n    },\n    metadata: {\n      family: \"Gemini 3\",\n      releaseDate: \"2025-11-18\",\n      notes:\n        \"Gemini 3 Pro Preview via OpenRouter. Flagship frontier model for multimodal reasoning.\",\n    },\n  },\n  {\n    provider: \"openrouter\",\n    modelId: \"google/gemini-3-flash-preview\",\n    displayName: \"Gemini 3 Flash Preview (OpenRouter)\",\n    contextWindow: 1_048_576,\n    maxOutputTokens: 65_535,\n    pricing: {\n      input: 0.5,\n      output: 3.0,\n    },\n    knowledgeCutoff: \"2025-12\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: true,\n      reasoning: true,\n      structuredOutputs: true,\n    },\n    metadata: {\n      family: \"Gemini 3\",\n      releaseDate: \"2025-12-17\",\n      notes:\n        \"Gemini 3 Flash Preview via OpenRouter. High-speed thinking model for agentic workflows.\",\n    },\n  },\n\n  // ============================================================\n  // Google Gemini 3.1 Models (via OpenRouter)\n  // ============================================================\n  {\n    provider: \"openrouter\",\n    modelId: \"google/gemini-3.1-pro-preview\",\n    displayName: \"Gemini 3.1 Pro Preview (OpenRouter)\",\n    contextWindow: 1_048_576,\n    maxOutputTokens: 65_536,\n    pricing: {\n      input: 2.0,\n      output: 12.0,\n    },\n    knowledgeCutoff: \"2025-01\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: true,\n      reasoning: true,\n      structuredOutputs: true,\n    },\n    metadata: {\n      family: \"Gemini 3.1\",\n      releaseDate: \"2026-03\",\n      notes:\n        \"Gemini 3.1 Pro Preview via OpenRouter. Frontier reasoning with enhanced software engineering performance.\",\n    },\n  },\n  {\n    provider: \"openrouter\",\n    modelId: \"google/gemini-3.1-pro-preview-customtools\",\n    displayName: \"Gemini 3.1 Pro Preview Custom Tools (OpenRouter)\",\n    contextWindow: 1_048_576,\n    maxOutputTokens: 65_536,\n    pricing: {\n      input: 2.0,\n      output: 12.0,\n    },\n    knowledgeCutoff: \"2025-01\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: true,\n      reasoning: true,\n      structuredOutputs: true,\n    },\n    metadata: {\n      family: \"Gemini 3.1\",\n      releaseDate: \"2026-03\",\n      notes:\n        \"Gemini 3.1 Pro Preview Custom Tools via OpenRouter. Improved tool selection to prevent overuse of general tools in agent workflows.\",\n    },\n  },\n  {\n    provider: \"openrouter\",\n    modelId: \"google/gemini-3.1-flash-lite-preview\",\n    displayName: \"Gemini 3.1 Flash Lite Preview (OpenRouter)\",\n    contextWindow: 1_048_576,\n    maxOutputTokens: 65_536,\n    pricing: {\n      input: 0.25,\n      output: 1.5,\n    },\n    knowledgeCutoff: \"2025-01\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: true,\n      reasoning: true,\n      structuredOutputs: true,\n    },\n    metadata: {\n      family: \"Gemini 3.1\",\n      releaseDate: \"2026-03\",\n      notes:\n        \"Gemini 3.1 Flash Lite Preview via OpenRouter. High-efficiency model with full thinking levels for cost/performance trade-offs.\",\n    },\n  },\n  {\n    provider: \"openrouter\",\n    modelId: \"google/gemini-3.1-flash-image-preview\",\n    displayName: \"Gemini 3.1 Flash Image Preview (OpenRouter)\",\n    contextWindow: 65_536,\n    maxOutputTokens: 65_536,\n    pricing: {\n      input: 0.5,\n      output: 3.0,\n    },\n    knowledgeCutoff: \"2025-01\",\n    features: {\n      streaming: true,\n      functionCalling: false,\n      vision: true,\n    },\n    metadata: {\n      family: \"Gemini 3.1\",\n      releaseDate: \"2026-03\",\n      notes:\n        \"Gemini 3.1 Flash Image Preview via OpenRouter. Pro-level image generation and editing at Flash speed.\",\n    },\n  },\n\n  // ============================================================\n  // Meta Llama Models (via OpenRouter)\n  // ============================================================\n  {\n    provider: \"openrouter\",\n    modelId: \"meta-llama/llama-3.3-70b-instruct\",\n    displayName: \"Llama 3.3 70B Instruct (OpenRouter)\",\n    contextWindow: 128_000,\n    maxOutputTokens: 8_192,\n    pricing: {\n      input: 0.4,\n      output: 0.4,\n    },\n    knowledgeCutoff: \"2024-12\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: false,\n    },\n    metadata: {\n      family: \"Llama 3.3\",\n      notes: \"Meta Llama 3.3 70B via OpenRouter. Excellent open-source model.\",\n    },\n  },\n  {\n    provider: \"openrouter\",\n    modelId: \"meta-llama/llama-4-maverick\",\n    displayName: \"Llama 4 Maverick (OpenRouter)\",\n    contextWindow: 1_000_000,\n    maxOutputTokens: 128_000,\n    pricing: {\n      input: 0.2,\n      output: 0.6,\n    },\n    knowledgeCutoff: \"2025-04\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: true,\n    },\n    metadata: {\n      family: \"Llama 4\",\n      notes: \"Meta Llama 4 Maverick via OpenRouter. Latest Llama generation.\",\n    },\n  },\n\n  // ============================================================\n  // DeepSeek Models (via OpenRouter)\n  // ============================================================\n  {\n    provider: \"openrouter\",\n    modelId: \"deepseek/deepseek-r1\",\n    displayName: \"DeepSeek R1 (OpenRouter)\",\n    contextWindow: 64_000,\n    maxOutputTokens: 8_192,\n    pricing: {\n      input: 0.55,\n      output: 2.19,\n    },\n    knowledgeCutoff: \"2025-01\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: false,\n      reasoning: true,\n    },\n    metadata: {\n      family: \"DeepSeek R1\",\n      notes: \"DeepSeek R1 via OpenRouter. Strong reasoning capabilities.\",\n    },\n  },\n  {\n    provider: \"openrouter\",\n    modelId: \"deepseek/deepseek-chat\",\n    displayName: \"DeepSeek Chat (OpenRouter)\",\n    contextWindow: 64_000,\n    maxOutputTokens: 8_192,\n    pricing: {\n      input: 0.14,\n      output: 0.28,\n    },\n    knowledgeCutoff: \"2025-01\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: false,\n    },\n    metadata: {\n      family: \"DeepSeek V3\",\n      notes: \"DeepSeek Chat via OpenRouter. Very cost-effective.\",\n    },\n  },\n  {\n    provider: \"openrouter\",\n    modelId: \"deepseek/deepseek-v3.2\",\n    displayName: \"DeepSeek V3.2 (OpenRouter)\",\n    contextWindow: 163_840,\n    maxOutputTokens: 65_536,\n    pricing: {\n      input: 0.25,\n      output: 0.38,\n    },\n    knowledgeCutoff: \"2025-12\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: false,\n      reasoning: true,\n    },\n    metadata: {\n      family: \"DeepSeek V3.2\",\n      releaseDate: \"2025-12-01\",\n      notes:\n        \"DeepSeek V3.2 via OpenRouter. GPT-5 class performance with DeepSeek Sparse Attention.\",\n    },\n  },\n\n  // ============================================================\n  // Mistral Models (via OpenRouter)\n  // ============================================================\n  {\n    provider: \"openrouter\",\n    modelId: \"mistralai/mistral-large\",\n    displayName: \"Mistral Large (OpenRouter)\",\n    contextWindow: 128_000,\n    maxOutputTokens: 8_192,\n    pricing: {\n      input: 2.0,\n      output: 6.0,\n    },\n    knowledgeCutoff: \"2024-11\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: false,\n    },\n    metadata: {\n      family: \"Mistral Large\",\n      notes: \"Mistral Large via OpenRouter. Strong multilingual capabilities.\",\n    },\n  },\n  {\n    provider: \"openrouter\",\n    modelId: \"mistralai/mixtral-8x22b-instruct\",\n    displayName: \"Mixtral 8x22B Instruct (OpenRouter)\",\n    contextWindow: 65_536,\n    maxOutputTokens: 8_192,\n    pricing: {\n      input: 0.9,\n      output: 0.9,\n    },\n    knowledgeCutoff: \"2024-04\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: false,\n    },\n    metadata: {\n      family: \"Mixtral\",\n      notes: \"Mixtral 8x22B via OpenRouter. Sparse MoE architecture.\",\n    },\n  },\n\n  // ============================================================\n  // Qwen Models (via OpenRouter)\n  // ============================================================\n  {\n    provider: \"openrouter\",\n    modelId: \"qwen/qwen-2.5-72b-instruct\",\n    displayName: \"Qwen 2.5 72B Instruct (OpenRouter)\",\n    contextWindow: 131_072,\n    maxOutputTokens: 8_192,\n    pricing: {\n      input: 0.35,\n      output: 0.4,\n    },\n    knowledgeCutoff: \"2024-09\",\n    features: {\n      streaming: true,\n      functionCalling: true,\n      vision: false,\n    },\n    metadata: {\n      family: \"Qwen 2.5\",\n      notes: \"Qwen 2.5 72B via OpenRouter. Strong coding and math.\",\n    },\n  },\n];\n","/**\n * OpenRouter deep research over chat completions.\n *\n * Research models on OpenRouter (Perplexity Sonar Deep Research, OpenAI's\n * research models) run their agentic loop server-side and stream reasoning\n * followed by the cited report through the ordinary chat-completions SSE\n * surface. Peculiarities handled here:\n *\n * - reasoning arrives as `delta.reasoning` and/or `delta.reasoning_details[]`\n *   (both may be present — details win to avoid double-emitting)\n * - citations arrive as `annotations[].url_citation` (delta or final message)\n *   AND/OR a legacy top-level `citations: [urls]` array — read both, dedupe\n * - keep-alive comment lines (`: OPENROUTER PROCESSING`) are stripped by the\n *   openai SDK's SSE parser before chunks reach us\n * - there is no job id: `created` carries `jobId: null`, refs/resume are\n *   unavailable, and a dropped stream is surfaced as a non-retryable error\n */\n\nimport type { ChatCompletionChunk } from \"openai/resources/chat/completions\";\nimport { ResearchValidationError } from \"../research/errors.js\";\nimport type {\n  ResearchCitation,\n  ResearchEvent,\n  ResearchOptions,\n  ResearchStatus,\n  ResearchUsage,\n} from \"../research/types.js\";\n\n// =============================================================================\n// Request building\n// =============================================================================\n\nexport interface OpenRouterResearchMessages {\n  messages: Array<{ role: \"system\" | \"user\"; content: string }>;\n}\n\n/**\n * Validate research options for the OpenRouter surface and produce the chat\n * messages. (The full request is assembled by the provider, which owns\n * headers, reasoning mapping, and extra handling.)\n */\nexport function buildOpenRouterResearchMessages(\n  options: ResearchOptions,\n): OpenRouterResearchMessages {\n  if (options.background === true) {\n    throw new ResearchValidationError(\n      \"OpenRouter has no background mode for research runs — the stream must stay open.\",\n    );\n  }\n  if (options.tools !== undefined && options.tools.length > 0) {\n    throw new ResearchValidationError(\n      \"OpenRouter research models manage their tools server-side — omit the tools option.\",\n    );\n  }\n\n  const messages: OpenRouterResearchMessages[\"messages\"] = [];\n  if (options.systemPrompt) {\n    messages.push({ role: \"system\", content: options.systemPrompt });\n  }\n  messages.push({ role: \"user\", content: options.query });\n  return { messages };\n}\n\n// =============================================================================\n// Chunk normalization\n// =============================================================================\n\n/** Extended delta shape OpenRouter emits beyond the OpenAI typings. */\ninterface OpenRouterDelta {\n  content?: string | null;\n  reasoning?: string | null;\n  reasoning_details?: Array<{ type?: string; text?: string }>;\n  annotations?: OpenRouterAnnotation[];\n}\n\ninterface OpenRouterAnnotation {\n  type?: string;\n  url_citation?: {\n    url?: string;\n    title?: string;\n    content?: string;\n    start_index?: number;\n    end_index?: number;\n  };\n}\n\n/** Extended chunk shape: legacy top-level citations + usage extras. */\ninterface OpenRouterChunkExtras {\n  citations?: string[];\n  usage?: ChatCompletionChunk[\"usage\"] & {\n    num_search_queries?: number;\n    server_tool_use?: { web_search_requests?: number };\n    /** OpenRouter usage accounting: authoritative billed cost in USD credits\n     *  (requires `usage: {include: true}` on the request). Covers per-search\n     *  and reasoning fees our token-based estimate cannot see. */\n    cost?: number;\n  };\n}\n\nfunction citationKey(citation: ResearchCitation): string {\n  return `${citation.url}#${citation.startIndex ?? \"\"}`;\n}\n\nfunction mapFinishReason(reason: string | null | undefined): ResearchStatus {\n  switch (reason) {\n    case \"length\":\n      return \"incomplete\";\n    case \"error\":\n      return \"failed\";\n    default:\n      return \"completed\";\n  }\n}\n\n/**\n * Normalize an OpenRouter chat-completions chunk stream into research events.\n * No cursors — OpenRouter research runs are not resumable.\n */\nexport async function* normalizeOpenRouterResearchStream(\n  stream: AsyncIterable<ChatCompletionChunk>,\n): AsyncGenerator<ResearchEvent> {\n  let createdEmitted = false;\n  // Annotation citations are deduped by url#offset (one source cited at several\n  // offsets is legitimately distinct). `seenCitationUrls` additionally records\n  // every emitted url so the legacy bare-url shape can dedupe against it by url\n  // alone — symmetrically, and independent of arrival order.\n  const seenCitations = new Set<string>();\n  const seenCitationUrls = new Set<string>();\n  // Legacy top-level `citations: [urls]` are bare urls with no offsets. Buffer\n  // them (with their source chunk) and flush after the stream so a richer\n  // annotation for the same url always wins, whichever shape the provider emits\n  // first. Emitting inline was order-dependent: a legacy url streamed before its\n  // annotation produced both a bare `url#` and a full `url#0`, which the\n  // collector (keyed by url#startIndex) keeps as two duplicate citations.\n  const bufferedLegacyCitations: Array<{ url: string; rawEvent: unknown }> = [];\n  let usage: ResearchUsage | undefined;\n  let terminalStatus: ResearchStatus | undefined;\n  let lastRaw: unknown;\n\n  for await (const chunk of stream) {\n    lastRaw = chunk;\n    if (!createdEmitted) {\n      createdEmitted = true;\n      yield { type: \"created\", jobId: null, rawEvent: chunk };\n      yield { type: \"status\", status: \"in_progress\" };\n    }\n\n    const choice = chunk.choices?.[0];\n    const delta = (choice?.delta ?? {}) as OpenRouterDelta;\n\n    // Reasoning: prefer typed reasoning_details; fall back to the plain\n    // reasoning string. Never emit both for the same chunk.\n    const detailTexts = (delta.reasoning_details ?? [])\n      .filter((detail) => typeof detail.text === \"string\" && detail.text.length > 0)\n      .map((detail) => detail.text as string);\n    if (detailTexts.length > 0) {\n      for (const text of detailTexts) {\n        yield { type: \"thinking\", delta: text, rawEvent: chunk };\n      }\n    } else if (typeof delta.reasoning === \"string\" && delta.reasoning.length > 0) {\n      yield { type: \"thinking\", delta: delta.reasoning, rawEvent: chunk };\n    }\n\n    if (typeof delta.content === \"string\" && delta.content.length > 0) {\n      yield { type: \"text\", delta: delta.content, rawEvent: chunk };\n    }\n\n    // Citations: annotations on the delta (and, on some providers, the final\n    // message object), deduplicated by url + offset.\n    const annotationSources: OpenRouterAnnotation[] = [\n      ...(delta.annotations ?? []),\n      ...(((choice as { message?: { annotations?: OpenRouterAnnotation[] } } | undefined)?.message\n        ?.annotations ?? []) as OpenRouterAnnotation[]),\n    ];\n    for (const annotation of annotationSources) {\n      if (annotation.type !== \"url_citation\" || !annotation.url_citation?.url) continue;\n      const citation: ResearchCitation = {\n        url: annotation.url_citation.url,\n        title: annotation.url_citation.title,\n        content: annotation.url_citation.content,\n        startIndex: annotation.url_citation.start_index,\n        endIndex: annotation.url_citation.end_index,\n      };\n      const key = citationKey(citation);\n      if (!seenCitations.has(key)) {\n        seenCitations.add(key);\n        seenCitationUrls.add(citation.url);\n        yield { type: \"citation\", citation, rawEvent: chunk };\n      }\n    }\n\n    // Legacy top-level citations array (Perplexity passthrough): bare urls.\n    // Buffered and flushed after the stream (below) so annotation-derived\n    // citations for the same url take precedence, whatever order they stream in.\n    const legacyCitations = (chunk as OpenRouterChunkExtras).citations;\n    if (Array.isArray(legacyCitations)) {\n      for (const url of legacyCitations) {\n        bufferedLegacyCitations.push({ url, rawEvent: chunk });\n      }\n    }\n\n    if (choice?.finish_reason) {\n      terminalStatus = mapFinishReason(choice.finish_reason);\n    }\n\n    const chunkUsage = (chunk as OpenRouterChunkExtras).usage;\n    if (chunkUsage) {\n      usage = {\n        inputTokens: chunkUsage.prompt_tokens ?? 0,\n        outputTokens: chunkUsage.completion_tokens ?? 0,\n        totalTokens: chunkUsage.total_tokens ?? 0,\n        cachedInputTokens: chunkUsage.prompt_tokens_details?.cached_tokens ?? undefined,\n        reasoningTokens: chunkUsage.completion_tokens_details?.reasoning_tokens ?? undefined,\n        searches:\n          chunkUsage.num_search_queries ??\n          chunkUsage.server_tool_use?.web_search_requests ??\n          undefined,\n        // Authoritative billed cost from OpenRouter usage accounting —\n        // preferred over the catalog estimate (collector keeps it).\n        costUSD: typeof chunkUsage.cost === \"number\" ? chunkUsage.cost : undefined,\n      };\n    }\n  }\n\n  // Flush buffered legacy citations for any url not already emitted via a\n  // richer annotation, deduplicated by url. Runs after the stream so every\n  // annotation has been recorded in `seenCitationUrls` first — the annotation\n  // form wins over a bare legacy url regardless of which arrived first.\n  for (const { url, rawEvent } of bufferedLegacyCitations) {\n    if (seenCitationUrls.has(url)) continue;\n    seenCitationUrls.add(url);\n    yield { type: \"citation\", citation: { url }, rawEvent };\n  }\n\n  if (usage) {\n    yield { type: \"usage\", usage };\n  }\n  yield {\n    type: \"done\",\n    result: {\n      status: terminalStatus ?? \"completed\",\n      // Report text was streamed as deltas; the collector joins them.\n      report: \"\",\n      usage,\n      raw: lastRaw,\n    },\n  };\n}\n","/**\n * OpenRouter research model catalog.\n *\n * These models run deep research server-side (at Perplexity / OpenAI) over\n * OpenRouter's plain chat-completions surface: streaming is mandatory\n * (multi-minute runs hit 60s idle disconnects otherwise), there is no\n * background mode, no job id, and no resume — a dropped stream cannot be\n * re-attached and is never silently re-run (money-safety).\n *\n * Pricing verified 2026-07-02 against the live OpenRouter models API.\n */\n\nimport type { ResearchModelSpec } from \"../research/model-spec.js\";\n\n/** Shared capability shape: stream-only, no background/resume, no tools param. */\nconst OPENROUTER_STREAM_ONLY: ResearchModelSpec[\"capabilities\"] = {\n  streaming: true,\n  background: false,\n  resumable: false,\n  tools: [],\n};\n\nexport const openrouterResearchModels: ResearchModelSpec[] = [\n  {\n    provider: \"openrouter\",\n    modelId: \"perplexity/sonar-deep-research\",\n    kind: \"model\",\n    displayName: \"Perplexity Sonar Deep Research\",\n    contextWindow: 128_000,\n    pricing: {\n      input: 2,\n      output: 8,\n      // Internal reasoning tokens are priced separately from output.\n      internalReasoning: 3,\n      perThousandSearches: 5,\n    },\n    capabilities: OPENROUTER_STREAM_ONLY,\n    metadata: {\n      notes:\n        \"R1-style think-then-write: expect a long reasoning stream (100k+ tokens) before report text.\",\n    },\n  },\n  {\n    provider: \"openrouter\",\n    modelId: \"perplexity/sonar-pro-search\",\n    kind: \"model\",\n    displayName: \"Perplexity Sonar Pro Search\",\n    contextWindow: 200_000,\n    pricing: { input: 3, output: 15, perThousandSearches: 18 },\n    capabilities: OPENROUTER_STREAM_ONLY,\n    metadata: { notes: \"Agentic multi-step Pro Search — lighter than full deep research.\" },\n  },\n  {\n    provider: \"openrouter\",\n    modelId: \"openai/o3-deep-research\",\n    kind: \"model\",\n    displayName: \"OpenAI o3 Deep Research (via OpenRouter)\",\n    contextWindow: 200_000,\n    maxOutputTokens: 100_000,\n    pricing: { input: 10, cachedInput: 2.5, output: 40, perThousandSearches: 10 },\n    capabilities: OPENROUTER_STREAM_ONLY,\n    metadata: {\n      // Upstream OpenAI shutdown propagates through OpenRouter.\n      deprecationDate: \"2026-04-22\",\n      shutdownDate: \"2026-07-23\",\n      replacement: \"perplexity/sonar-deep-research\",\n      notes: \"Tools are managed upstream — requests carry no tools param via OpenRouter.\",\n    },\n  },\n  {\n    provider: \"openrouter\",\n    modelId: \"openai/o4-mini-deep-research\",\n    kind: \"model\",\n    displayName: \"OpenAI o4-mini Deep Research (via OpenRouter)\",\n    contextWindow: 200_000,\n    maxOutputTokens: 100_000,\n    pricing: { input: 2, cachedInput: 0.5, output: 8, perThousandSearches: 10 },\n    capabilities: OPENROUTER_STREAM_ONLY,\n    metadata: {\n      deprecationDate: \"2026-04-22\",\n      shutdownDate: \"2026-07-23\",\n      replacement: \"perplexity/sonar-deep-research\",\n      notes: \"Tools are managed upstream — requests carry no tools param via OpenRouter.\",\n    },\n  },\n];\n\nconst byId = new Map(openrouterResearchModels.map((spec) => [spec.modelId, spec]));\n\nexport function getOpenRouterResearchModelSpec(modelId: string): ResearchModelSpec | undefined {\n  return byId.get(modelId);\n}\n\nexport function isOpenRouterResearchModel(modelId: string): boolean {\n  return byId.has(modelId);\n}\n","/**\n * OpenRouter Speech (TTS) Model Catalog\n *\n * OpenRouter provides TTS through audio-capable models using chat completions\n * with the `modalities: [\"text\", \"audio\"]` parameter.\n *\n * Pricing as of March 2026:\n * - openai/gpt-audio: $2.50/M input, $10/M output, $32-64/M audio\n * - openai/gpt-audio-mini: $0.60/M input, $2.40/M output, $0.60/M audio\n *\n * @see https://openrouter.ai/docs/guides/overview/multimodal/audio\n */\n\nimport type { AudioFormat, SpeechModelSpec } from \"../core/media-types.js\";\n\n/** OpenRouter TTS voices (same as OpenAI) */\nexport const OPENROUTER_TTS_VOICES = [\"alloy\", \"echo\", \"fable\", \"onyx\", \"nova\", \"shimmer\"] as const;\n\nexport type OpenRouterTTSVoice = (typeof OPENROUTER_TTS_VOICES)[number];\n\n/**\n * OpenRouter supported audio formats for TTS via streaming.\n *\n * IMPORTANT: OpenRouter audio output requires streaming (stream: true),\n * and streaming only supports pcm16 format. Other formats like mp3, wav,\n * opus are NOT supported when streaming is enabled.\n *\n * If you need mp3/wav output, you must convert from pcm16 after receiving.\n */\nexport const OPENROUTER_TTS_FORMATS: AudioFormat[] = [\"pcm16\"];\n\n/**\n * OpenRouter Speech Model Specifications\n *\n * Note: OpenRouter TTS works via chat completions with audio modality,\n * not a dedicated TTS endpoint like OpenAI's `/audio/speech`.\n */\nexport const openrouterSpeechModels: SpeechModelSpec[] = [\n  {\n    provider: \"openrouter\",\n    modelId: \"openai/gpt-4o-audio-preview\",\n    displayName: \"GPT-4o Audio Preview (via OpenRouter)\",\n    pricing: {\n      perInputToken: 0.0000025,\n      perAudioOutputToken: 0.00001,\n      perMinute: 0.06,\n    },\n    voices: [...OPENROUTER_TTS_VOICES],\n    formats: OPENROUTER_TTS_FORMATS,\n    maxInputLength: 128000,\n    defaultVoice: \"alloy\",\n    defaultFormat: \"pcm16\",\n    features: {\n      voiceInstructions: true,\n    },\n  },\n  {\n    provider: \"openrouter\",\n    modelId: \"openai/gpt-audio\",\n    displayName: \"GPT Audio (via OpenRouter)\",\n    pricing: {\n      // Token-based pricing with audio output\n      perInputToken: 0.0000025, // $2.50 per 1M\n      perAudioOutputToken: 0.000064, // ~$64 per 1M audio tokens\n      // Approximate per-minute cost for estimation\n      perMinute: 0.08,\n    },\n    voices: [...OPENROUTER_TTS_VOICES],\n    formats: OPENROUTER_TTS_FORMATS,\n    maxInputLength: 128000, // 128K context\n    defaultVoice: \"alloy\",\n    defaultFormat: \"pcm16\",\n    features: {\n      voiceInstructions: true,\n    },\n  },\n  {\n    provider: \"openrouter\",\n    modelId: \"openai/gpt-audio-mini\",\n    displayName: \"GPT Audio Mini (via OpenRouter)\",\n    pricing: {\n      // More affordable option\n      perInputToken: 0.0000006, // $0.60 per 1M\n      perAudioOutputToken: 0.0000006, // $0.60 per 1M audio tokens\n      // Approximate per-minute cost for estimation\n      perMinute: 0.015,\n    },\n    voices: [...OPENROUTER_TTS_VOICES],\n    formats: OPENROUTER_TTS_FORMATS,\n    maxInputLength: 128000, // 128K context\n    defaultVoice: \"alloy\",\n    defaultFormat: \"pcm16\",\n    features: {\n      voiceInstructions: true,\n    },\n  },\n];\n\n/**\n * Get speech model spec by model ID.\n */\nexport function getOpenRouterSpeechModelSpec(modelId: string): SpeechModelSpec | undefined {\n  return openrouterSpeechModels.find((m) => m.modelId === modelId);\n}\n\n/**\n * Check if a model ID is an OpenRouter speech model.\n */\nexport function isOpenRouterSpeechModel(modelId: string): boolean {\n  return openrouterSpeechModels.some((m) => m.modelId === modelId);\n}\n\n/**\n * Calculate cost for OpenRouter speech generation.\n *\n * Uses per-minute pricing when available, falling back to token-based\n * estimation when per-minute pricing is not defined.\n *\n * @param modelId - The model ID\n * @param characterCount - Number of characters in the input\n * @param estimatedMinutes - Optional: estimated audio duration (improves accuracy)\n * @returns Cost in USD, or undefined if model not found\n */\nexport function calculateOpenRouterSpeechCost(\n  modelId: string,\n  characterCount: number,\n  estimatedMinutes?: number,\n): number | undefined {\n  const spec = getOpenRouterSpeechModelSpec(modelId);\n  if (!spec) return undefined;\n\n  // Primary: per-minute approximation (most accurate for TTS)\n  if (spec.pricing.perMinute !== undefined) {\n    // Estimate duration: ~150 words/min, ~5 chars/word = ~750 chars/min\n    const minutes = estimatedMinutes ?? characterCount / 750;\n    return minutes * spec.pricing.perMinute;\n  }\n\n  // Fallback: token-based calculation\n  // Estimate ~4 characters per token for English text\n  if (spec.pricing.perInputToken !== undefined) {\n    const estimatedTokens = Math.ceil(characterCount / 4);\n    const inputCost = estimatedTokens * spec.pricing.perInputToken;\n\n    // If we have audio output token pricing and can estimate audio duration,\n    // include that in the calculation\n    if (spec.pricing.perAudioOutputToken !== undefined && estimatedMinutes !== undefined) {\n      // Very rough estimate: ~100 audio tokens per second of speech\n      const audioTokens = estimatedMinutes * 60 * 100;\n      return inputCost + audioTokens * spec.pricing.perAudioOutputToken;\n    }\n\n    return inputCost;\n  }\n\n  return undefined;\n}\n","/**\n * OpenRouter Provider Adapter\n *\n * Provides access to 400+ AI models from dozens of providers through\n * OpenRouter's unified API gateway.\n *\n * Environment variables:\n * - OPENROUTER_API_KEY (required) - Your OpenRouter API key\n * - OPENROUTER_SITE_URL (optional) - Your app URL for analytics\n * - OPENROUTER_APP_NAME (optional) - Your app name for analytics\n *\n * Model naming format: provider/model-name\n * Examples:\n * - anthropic/claude-sonnet-4-5\n * - openai/gpt-4o\n * - meta-llama/llama-3.3-70b-instruct\n *\n * @see https://openrouter.ai/docs\n */\n\nimport OpenAI from \"openai\";\nimport type { ChatCompletionChunk } from \"openai/resources/chat/completions\";\nimport type { Stream } from \"openai/streaming\";\nimport type {\n  SpeechGenerationOptions,\n  SpeechGenerationResult,\n  SpeechModelSpec,\n} from \"../core/media-types.js\";\nimport type { LLMMessage } from \"../core/messages.js\";\nimport type { ModelSpec } from \"../core/model-catalog.js\";\nimport { getModelId } from \"../core/model-shortcuts.js\";\nimport type { LLMGenerationOptions, ModelDescriptor, ReasoningEffort } from \"../core/options.js\";\nimport { createLogger } from \"../logging/logger.js\";\nimport { OPENROUTER_RESEARCH_HTTP_TIMEOUT_MS } from \"../research/constants.js\";\nimport type { ResearchModelSpec } from \"../research/model-spec.js\";\nimport type { ResearchEvent, ResearchOptions } from \"../research/types.js\";\nimport {\n  type OpenAICompatibleConfig,\n  OpenAICompatibleProvider,\n} from \"./openai-compatible-provider.js\";\nimport { OPENROUTER_MODELS } from \"./openrouter-models.js\";\nimport {\n  buildOpenRouterResearchMessages,\n  normalizeOpenRouterResearchStream,\n} from \"./openrouter-research.js\";\nimport {\n  isOpenRouterResearchModel,\n  openrouterResearchModels,\n} from \"./openrouter-research-models.js\";\nimport {\n  calculateOpenRouterSpeechCost,\n  getOpenRouterSpeechModelSpec,\n  isOpenRouterSpeechModel,\n  openrouterSpeechModels,\n} from \"./openrouter-speech-models.js\";\nimport { isNonEmpty, readEnvVar } from \"./utils.js\";\n\n/** Logger for OpenRouter provider debugging */\nconst logger = createLogger({ name: \"openrouter\" });\n\n/** Maps llmist reasoning effort levels to OpenRouter/OpenAI reasoning effort */\nconst OPENROUTER_EFFORT_MAP: Record<ReasoningEffort, string> = {\n  none: \"none\",\n  low: \"low\",\n  medium: \"medium\",\n  high: \"high\",\n  maximum: \"xhigh\",\n};\n\n/**\n * Configuration for OpenRouter provider.\n */\nexport interface OpenRouterConfig extends OpenAICompatibleConfig {\n  /**\n   * Your app's URL for OpenRouter analytics dashboard.\n   * Maps to HTTP-Referer header.\n   */\n  siteUrl?: string;\n\n  /**\n   * Your app's name shown in OpenRouter analytics.\n   * Maps to X-Title header.\n   */\n  appName?: string;\n}\n\n/**\n * OpenRouter-specific routing options for model selection.\n * Pass these via the `extra` parameter in generation options.\n *\n * @example\n * ```typescript\n * agent.withExtra({\n *   routing: {\n *     models: [\"anthropic/claude-sonnet-4-5\", \"openai/gpt-4o\"],\n *     route: \"cheapest\",\n *   },\n * })\n * ```\n */\nexport interface OpenRouterRouting {\n  /**\n   * Ordered list of models to try as fallbacks.\n   * If the first model fails or is unavailable, OpenRouter tries the next.\n   */\n  models?: string[];\n\n  /**\n   * Specific provider to route to for models available from multiple providers.\n   */\n  provider?: string;\n\n  /**\n   * Ordered list of providers to prefer.\n   */\n  order?: string[];\n\n  /**\n   * Routing preference for model selection.\n   * - 'fastest': Route to the fastest available provider\n   * - 'cheapest': Route to the cheapest provider\n   * - 'quality': Route to the highest quality provider (default)\n   */\n  route?: \"fastest\" | \"cheapest\" | \"quality\";\n}\n\nexport class OpenRouterProvider extends OpenAICompatibleProvider<OpenRouterConfig> {\n  readonly providerId = \"openrouter\" as const;\n  protected readonly providerAlias = \"or\";\n\n  constructor(client: OpenAI, config: OpenRouterConfig = {}) {\n    super(client, config);\n  }\n\n  getModelSpecs(): ModelSpec[] {\n    return OPENROUTER_MODELS;\n  }\n\n  // =========================================================================\n  // Deep Research (chat-completions surface)\n  //\n  // Stream-only: no background mode, no job id, no resume. resumeResearch /\n  // getResearchStatus / cancelResearch are deliberately NOT implemented — the\n  // research job surfaces typed errors for those operations, and a dropped\n  // stream is never silently re-run (a multi-dollar research run).\n  // =========================================================================\n\n  getResearchModelSpecs(): ResearchModelSpec[] {\n    return openrouterResearchModels;\n  }\n\n  supportsResearch(modelId: string): boolean {\n    return isOpenRouterResearchModel(modelId);\n  }\n\n  startResearch(\n    options: ResearchOptions,\n    descriptor: ModelDescriptor,\n    _spec?: ResearchModelSpec,\n  ): AsyncIterable<ResearchEvent> {\n    const { messages } = buildOpenRouterResearchMessages(options);\n    const client = this.client as OpenAI;\n\n    const request: Record<string, unknown> = {\n      model: descriptor.name,\n      messages,\n      // Mandatory: multi-minute runs hit idle disconnects without streaming.\n      stream: true,\n      stream_options: { include_usage: true },\n      // OpenRouter usage accounting: report the authoritative billed cost\n      // (covers per-search fees that token-based estimation cannot see).\n      usage: { include: true },\n    };\n    if (options.reasoning?.enabled !== undefined) {\n      request.reasoning = {\n        effort: OPENROUTER_EFFORT_MAP[options.reasoning.effort ?? \"medium\"],\n      };\n    }\n    // OpenRouter conventions: extra.routing → models/route/provider params,\n    // all other extra keys pass through (e.g. web_search_options) — EXCEPT\n    // the core request keys: mandatory streaming is a money-safety guarantee\n    // (non-streamed multi-minute runs idle-disconnect), so extra must not be\n    // able to clobber it, nor swap the model/messages/usage accounting.\n    const protectedKeys = new Set([\"model\", \"messages\", \"stream\", \"stream_options\", \"usage\"]);\n    Object.assign(request, this.buildProviderSpecificParams(options.extra));\n    for (const [key, value] of Object.entries(options.extra ?? {})) {\n      if (!this.isProviderSpecificKey(key) && !protectedKeys.has(key)) {\n        request[key] = value;\n      }\n    }\n\n    const headers = this.getCustomHeaders();\n    const requestOptions = {\n      signal: options.signal,\n      // Research runs take minutes — override the client's default timeout.\n      timeout: OPENROUTER_RESEARCH_HTTP_TIMEOUT_MS,\n      ...(Object.keys(headers).length > 0 ? { headers } : {}),\n    };\n\n    const enhance = (error: unknown) => this.enhanceError(error);\n    return (async function* () {\n      let stream: AsyncIterable<ChatCompletionChunk>;\n      try {\n        stream = (await client.chat.completions.create(\n          request as unknown as Parameters<OpenAI[\"chat\"][\"completions\"][\"create\"]>[0],\n          requestOptions,\n        )) as unknown as AsyncIterable<ChatCompletionChunk>;\n      } catch (error) {\n        throw enhance(error);\n      }\n      yield* normalizeOpenRouterResearchStream(stream);\n    })();\n  }\n\n  /**\n   * Override buildApiRequest to inject reasoning parameters and cache_control breakpoints.\n   * OpenRouter normalizes reasoning into the standard OpenAI format,\n   * and supports cache_control on message content blocks for both\n   * Anthropic Claude and Google Gemini models.\n   */\n  protected buildApiRequest(\n    options: LLMGenerationOptions,\n    descriptor: ModelDescriptor,\n    spec: ModelSpec | undefined,\n    messages: LLMMessage[],\n  ): Parameters<OpenAI[\"chat\"][\"completions\"][\"create\"]>[0] {\n    const request = super.buildApiRequest(options, descriptor, spec, messages);\n\n    // Inject reasoning parameter when reasoning is enabled\n    if (options.reasoning?.enabled !== undefined) {\n      const requestObj = request as unknown as Record<string, unknown>;\n      requestObj.reasoning = {\n        effort: OPENROUTER_EFFORT_MAP[options.reasoning.effort ?? \"medium\"],\n      };\n    }\n\n    // Inject cache_control breakpoints when caching is enabled (default: enabled).\n    // OpenRouter supports cache_control on message content blocks for both\n    // Anthropic Claude and Google Gemini models, using the same format.\n    const cachingEnabled = options.caching?.enabled !== false;\n    if (cachingEnabled) {\n      this.injectCacheBreakpoints(request);\n    }\n\n    return request;\n  }\n\n  /** Minimal shape for messages in the already-built OpenAI-compatible request. */\n  private static readonly CACHE_CONTROL = { type: \"ephemeral\" as const };\n\n  /**\n   * Add cache_control breakpoints to the last system message and last user message.\n   * This enables OpenRouter's prompt caching for supported providers (Anthropic, Gemini).\n   *\n   * Operates on the already-built request object. We cast through `unknown` because\n   * OpenAI's `ChatCompletionMessageParam` union is too narrow to assign content arrays\n   * with the non-standard `cache_control` property.\n   */\n  private injectCacheBreakpoints(\n    request: Parameters<OpenAI[\"chat\"][\"completions\"][\"create\"]>[0],\n  ): void {\n    type RequestMessage = { role: string; content: string | Array<Record<string, unknown>> };\n    const msgs = request.messages as unknown as RequestMessage[];\n\n    let lastSystemIdx = -1;\n    let lastUserIdx = -1;\n    for (let i = 0; i < msgs.length; i++) {\n      if (msgs[i].role === \"system\") lastSystemIdx = i;\n      if (msgs[i].role === \"user\") lastUserIdx = i;\n    }\n\n    if (lastSystemIdx >= 0) {\n      msgs[lastSystemIdx].content = this.withCacheControl(msgs[lastSystemIdx].content);\n    }\n    if (lastUserIdx >= 0) {\n      msgs[lastUserIdx].content = this.withCacheControl(msgs[lastUserIdx].content);\n    }\n  }\n\n  /**\n   * Return a new content array with cache_control on the last block.\n   * String content is promoted to a single-element text block array.\n   */\n  private withCacheControl(\n    content: string | Array<Record<string, unknown>>,\n  ): Array<Record<string, unknown>> {\n    if (typeof content === \"string\") {\n      return [{ type: \"text\", text: content, cache_control: OpenRouterProvider.CACHE_CONTROL }];\n    }\n\n    return content.map((block, i) =>\n      i === content.length - 1\n        ? { ...block, cache_control: OpenRouterProvider.CACHE_CONTROL }\n        : block,\n    );\n  }\n\n  /**\n   * Get custom headers for OpenRouter analytics.\n   */\n  protected getCustomHeaders(): Record<string, string> {\n    const headers: Record<string, string> = {};\n\n    if (this.config.siteUrl) {\n      headers[\"HTTP-Referer\"] = this.config.siteUrl;\n    }\n    if (this.config.appName) {\n      headers[\"X-Title\"] = this.config.appName;\n    }\n\n    return headers;\n  }\n\n  /**\n   * Build OpenRouter-specific request parameters from `extra.routing`.\n   */\n  protected buildProviderSpecificParams(\n    extra: Record<string, unknown> | undefined,\n  ): Record<string, unknown> {\n    const routing = extra?.routing as OpenRouterRouting | undefined;\n    if (!routing) {\n      return {};\n    }\n\n    const params: Record<string, unknown> = {};\n\n    // Model fallback chain\n    if (routing.models && routing.models.length > 0) {\n      params.models = routing.models;\n    }\n\n    // Routing preference\n    if (routing.route) {\n      params.route = routing.route;\n    }\n\n    // Provider routing\n    if (routing.provider) {\n      params.provider = { order: [routing.provider] };\n    } else if (routing.order && routing.order.length > 0) {\n      params.provider = { order: routing.order };\n    }\n\n    return params;\n  }\n\n  /**\n   * Filter out the 'routing' key from extra passthrough.\n   */\n  protected isProviderSpecificKey(key: string): boolean {\n    return key === \"routing\";\n  }\n\n  /**\n   * Enhance error messages with OpenRouter-specific guidance.\n   */\n  protected enhanceError(error: unknown): Error {\n    if (!(error instanceof Error)) {\n      return new Error(String(error));\n    }\n\n    const message = error.message.toLowerCase();\n\n    // 402: Insufficient credits\n    if (message.includes(\"402\") || message.includes(\"insufficient\")) {\n      return new Error(\n        `OpenRouter: Insufficient credits. Add funds at https://openrouter.ai/credits\\n` +\n          `Original error: ${error.message}`,\n      );\n    }\n\n    // 429: Rate limit exceeded\n    if (message.includes(\"429\") || message.includes(\"rate limit\")) {\n      return new Error(\n        `OpenRouter: Rate limit exceeded. Consider upgrading your plan or reducing request frequency.\\n` +\n          `Original error: ${error.message}`,\n      );\n    }\n\n    // 503: Model unavailable\n    if (message.includes(\"503\") || message.includes(\"unavailable\")) {\n      return new Error(\n        `OpenRouter: Model temporarily unavailable. Try a different model or use the 'models' ` +\n          `fallback option for automatic retry.\\n` +\n          `Original error: ${error.message}`,\n      );\n    }\n\n    // 400: Bad request (may indicate context overflow, model rejection, or invalid params).\n    // Must be checked BEFORE 401 — the 401 handler's broad \"invalid\" check would\n    // otherwise intercept 400 errors like \"400 invalid request payload\".\n    if (message.includes(\"400\") || message.includes(\"bad request\")) {\n      const enhanced = new Error(\n        `OpenRouter: Provider returned error (400). This may indicate the request exceeded ` +\n          `the model's limits, or a model-specific rejection.\\n` +\n          `Original error: ${error.message}`,\n      );\n      // Preserve status code for downstream detection (e.g., isLikelyContextOverflow)\n      const originalStatus = (error as unknown as { status?: number }).status;\n      Object.assign(enhanced, {\n        status: typeof originalStatus === \"number\" ? originalStatus : 400,\n      });\n      return enhanced;\n    }\n\n    // 401: Authentication failed\n    if (\n      message.includes(\"401\") ||\n      message.includes(\"unauthorized\") ||\n      message.includes(\"invalid api key\") ||\n      message.includes(\"invalid key\") ||\n      message.includes(\"invalid_api_key\")\n    ) {\n      return new Error(\n        `OpenRouter: Authentication failed. Check that OPENROUTER_API_KEY is set correctly.\\n` +\n          `Original error: ${error.message}`,\n      );\n    }\n\n    return error;\n  }\n\n  // =========================================================================\n  // Speech Generation (TTS via Chat Completions with Audio Modality)\n  // =========================================================================\n\n  /**\n   * Get speech model specifications for OpenRouter.\n   */\n  getSpeechModelSpecs(): SpeechModelSpec[] {\n    return openrouterSpeechModels;\n  }\n\n  /**\n   * Check if this provider supports speech generation for a given model.\n   * Handles both prefixed (openrouter:openai/gpt-audio-mini) and unprefixed model IDs.\n   */\n  supportsSpeechGeneration(modelId: string): boolean {\n    // Strip provider prefix if present (e.g., \"openrouter:openai/gpt-audio-mini\" → \"openai/gpt-audio-mini\")\n    const bareModelId = getModelId(modelId);\n    return isOpenRouterSpeechModel(bareModelId);\n  }\n\n  /**\n   * Generate speech audio from text using OpenRouter's audio-capable models.\n   *\n   * OpenRouter TTS works via chat completions with audio modality, not a\n   * dedicated TTS endpoint. The model receives a prompt asking it to say\n   * the text, and returns audio data via streaming.\n   *\n   * @param options - Speech generation options\n   * @returns Promise resolving to the generation result with audio and cost\n   * @throws Error if model is unknown, voice/format are invalid, or no audio is returned\n   */\n  async generateSpeech(options: SpeechGenerationOptions): Promise<SpeechGenerationResult> {\n    const client = this.client as OpenAI;\n    // Strip provider prefix if present (e.g., \"openrouter:openai/gpt-audio-mini\" → \"openai/gpt-audio-mini\")\n    const bareModelId = getModelId(options.model);\n    const spec = getOpenRouterSpeechModelSpec(bareModelId);\n\n    if (!spec) {\n      throw new Error(`Unknown OpenRouter TTS model: ${options.model}`);\n    }\n\n    const voice = options.voice ?? spec.defaultVoice ?? \"alloy\";\n    if (!spec.voices.includes(voice)) {\n      throw new Error(\n        `Invalid voice \"${voice}\" for ${options.model}. Valid voices: ${spec.voices.join(\", \")}`,\n      );\n    }\n\n    const format = options.responseFormat ?? spec.defaultFormat ?? \"mp3\";\n    if (!spec.formats.includes(format)) {\n      throw new Error(\n        `Invalid format \"${format}\" for ${options.model}. Valid formats: ${spec.formats.join(\", \")}`,\n      );\n    }\n\n    // OpenRouter TTS uses chat completions with audio modality\n    // The response comes as streaming chunks with base64-encoded audio\n    logger.debug(\"TTS request\", {\n      model: bareModelId,\n      voice,\n      format,\n      inputLength: options.input.length,\n    });\n\n    try {\n      const response = (await client.chat.completions.create({\n        model: bareModelId,\n        messages: [\n          {\n            role: \"user\",\n            content: `Please say the following text exactly: \"${options.input}\"`,\n          },\n        ],\n        // OpenRouter-specific parameters for audio output\n        // Note: OpenRouter TTS via chat completions does NOT support the speed parameter\n        // (unlike OpenAI's dedicated /audio/speech endpoint which does)\n        modalities: [\"text\", \"audio\"],\n        audio: {\n          voice,\n          format,\n        },\n        stream: true,\n      } as Parameters<typeof client.chat.completions.create>[0])) as Stream<ChatCompletionChunk>;\n\n      // Collect audio chunks from streaming response with runtime type validation\n      const audioChunks: Buffer[] = [];\n\n      for await (const chunk of response) {\n        // Runtime type narrowing for streaming audio data\n        const delta = chunk.choices[0]?.delta;\n        if (!delta || typeof delta !== \"object\") continue;\n\n        const audioObj = (delta as Record<string, unknown>).audio;\n        if (!audioObj || typeof audioObj !== \"object\") continue;\n\n        const audioData = (audioObj as Record<string, unknown>).data;\n        if (typeof audioData !== \"string\" || audioData.length === 0) continue;\n\n        // Validate and decode base64 audio data\n        const decoded = Buffer.from(audioData, \"base64\");\n        if (decoded.length === 0) {\n          throw new Error(\"Invalid base64 audio data received from OpenRouter\");\n        }\n        audioChunks.push(decoded);\n      }\n\n      // Concatenate all audio chunks and extract ArrayBuffer safely\n      const audioBuffer = Buffer.concat(audioChunks);\n\n      // Validate that we received audio data\n      if (audioBuffer.length === 0) {\n        throw new Error(\n          \"OpenRouter TTS returned no audio data. The model may have failed to generate audio or the stream was interrupted.\",\n        );\n      }\n      const cost = calculateOpenRouterSpeechCost(bareModelId, options.input.length);\n\n      return {\n        // Use Uint8Array for clean ArrayBuffer extraction (safer than buffer.slice for Node.js Buffer)\n        audio: new Uint8Array(audioBuffer).buffer,\n        model: options.model,\n        usage: {\n          characterCount: options.input.length,\n        },\n        cost,\n        format,\n      };\n    } catch (error: unknown) {\n      // Enhance error message with more context for debugging\n      const err = error as Error & {\n        status?: number;\n        error?: { message?: string; code?: string; type?: string };\n        response?: { data?: unknown };\n        body?: unknown;\n      };\n      const apiError = err.error?.message || err.error?.code || \"\";\n      const bodyInfo = err.body ? JSON.stringify(err.body) : \"\";\n      const details = apiError || bodyInfo || err.message || \"Unknown error\";\n\n      // Log detailed error for debugging (visible with LLMIST_LOG_LEVEL=debug)\n      logger.debug(\"TTS error\", {\n        model: bareModelId,\n        voice,\n        format,\n        status: err.status,\n        error: err.error,\n        body: err.body,\n        message: err.message,\n      });\n\n      throw new Error(\n        `OpenRouter TTS failed for model ${bareModelId}: ${details}` +\n          (err.status ? ` (HTTP ${err.status})` : \"\"),\n      );\n    }\n  }\n}\n\n/**\n * Create an OpenRouter provider from environment variables.\n *\n * Environment variables:\n * - OPENROUTER_API_KEY (required) - Your OpenRouter API key\n * - OPENROUTER_SITE_URL (optional) - Your app URL for analytics\n * - OPENROUTER_APP_NAME (optional) - Your app name for analytics\n *\n * @returns OpenRouterProvider instance or null if no API key is found\n *\n * @example\n * ```bash\n * # Basic usage\n * export OPENROUTER_API_KEY=\"sk-or-...\"\n *\n * # With analytics tracking\n * export OPENROUTER_API_KEY=\"sk-or-...\"\n * export OPENROUTER_SITE_URL=\"https://myapp.com\"\n * export OPENROUTER_APP_NAME=\"MyApp\"\n * ```\n */\nexport function createOpenRouterProviderFromEnv(): OpenRouterProvider | null {\n  const apiKey = readEnvVar(\"OPENROUTER_API_KEY\");\n\n  if (!isNonEmpty(apiKey)) {\n    return null;\n  }\n\n  const config: OpenRouterConfig = {\n    siteUrl: readEnvVar(\"OPENROUTER_SITE_URL\"),\n    appName: readEnvVar(\"OPENROUTER_APP_NAME\") || \"llmist\",\n  };\n\n  const client = new OpenAI({\n    apiKey: apiKey.trim(),\n    baseURL: \"https://openrouter.ai/api/v1\",\n    timeout: 120_000, // 2 minute timeout\n    maxRetries: 0, // Disable SDK retries - llmist handles all retries at application level\n  });\n\n  return new OpenRouterProvider(client, config);\n}\n","import { createAnthropicProviderFromEnv } from \"./anthropic.js\";\nimport { createGeminiProviderFromEnv } from \"./gemini.js\";\nimport { createHuggingFaceProviderFromEnv } from \"./huggingface.js\";\nimport { createOpenAIProviderFromEnv } from \"./openai.js\";\nimport { createOpenRouterProviderFromEnv } from \"./openrouter.js\";\nimport type { ProviderAdapter } from \"./provider.js\";\n\nexport type ProviderDiscoverer = () => ProviderAdapter | null | undefined;\n\nconst DISCOVERERS: ProviderDiscoverer[] = [\n  createOpenAIProviderFromEnv,\n  createAnthropicProviderFromEnv,\n  createGeminiProviderFromEnv,\n  createHuggingFaceProviderFromEnv,\n  createOpenRouterProviderFromEnv,\n];\n\nexport function discoverProviderAdapters(): ProviderAdapter[] {\n  const adapters: ProviderAdapter[] = [];\n\n  for (const discover of DISCOVERERS) {\n    const adapter = discover();\n    if (adapter) {\n      adapters.push(adapter);\n    }\n  }\n\n  return adapters;\n}\n","/**\n * Research cost estimation.\n *\n * Separate from `ModelRegistry.estimateCost` because research pricing has\n * dimensions the chat cost model lacks: per-search fees and separately-priced\n * internal reasoning tokens (see {@link ResearchPricing}).\n */\n\nimport { RESEARCH_COST_DECIMALS, SEARCHES_PER_THOUSAND, TOKENS_PER_MILLION } from \"./constants.js\";\nimport type { ResearchPricing } from \"./model-spec.js\";\nimport type { ResearchUsage } from \"./types.js\";\n\n/**\n * Estimate the USD cost of a research run.\n *\n * Semantics:\n * - `cachedInputTokens` are a subset of `inputTokens` and billed at\n *   `cachedInput` (falling back to `input` when unset).\n * - `reasoningTokens` are a subset of `outputTokens`. When\n *   `internalReasoning` is priced, reasoning tokens are billed at that rate\n *   and excluded from the output rate; otherwise they remain part of output.\n * - `searches` are billed at `perThousandSearches / 1000` each.\n */\nexport function estimateResearchCost(pricing: ResearchPricing, usage: ResearchUsage): number {\n  const cachedTokens = usage.cachedInputTokens ?? 0;\n  const freshInputTokens = Math.max(0, usage.inputTokens - cachedTokens);\n  const cachedRate = pricing.cachedInput ?? pricing.input;\n\n  let outputTokens = usage.outputTokens;\n  let reasoningCost = 0;\n  if (pricing.internalReasoning !== undefined && usage.reasoningTokens !== undefined) {\n    outputTokens = Math.max(0, outputTokens - usage.reasoningTokens);\n    reasoningCost = (usage.reasoningTokens * pricing.internalReasoning) / TOKENS_PER_MILLION;\n  }\n\n  const searchCost =\n    pricing.perThousandSearches !== undefined && usage.searches !== undefined\n      ? (usage.searches * pricing.perThousandSearches) / SEARCHES_PER_THOUSAND\n      : 0;\n\n  const total =\n    (freshInputTokens * pricing.input) / TOKENS_PER_MILLION +\n    (cachedTokens * cachedRate) / TOKENS_PER_MILLION +\n    (outputTokens * pricing.output) / TOKENS_PER_MILLION +\n    reasoningCost +\n    searchCost;\n\n  return Number(total.toFixed(RESEARCH_COST_DECIMALS));\n}\n","/**\n * Aggregates a research event stream into a final {@link ResearchResult}.\n *\n * Provider normalizers emit what they know; the collector merges streamed\n * state (text deltas, citations, usage) with the terminal `done` payload:\n * - report: `done.report` wins when non-empty, else accumulated text deltas\n * - citations: union of streamed + done citations, deduplicated\n * - usage: last-write-wins for token fields, max for cumulative counters\n * - costUSD: computed from catalog pricing when a spec is provided\n */\n\nimport { estimateResearchCost } from \"./cost.js\";\nimport type { ResearchModelSpec } from \"./model-spec.js\";\nimport type {\n  ResearchCitation,\n  ResearchErrorInfo,\n  ResearchEvent,\n  ResearchResult,\n  ResearchStatus,\n  ResearchUsage,\n} from \"./types.js\";\n\nconst EMPTY_USAGE: ResearchUsage = { inputTokens: 0, outputTokens: 0, totalTokens: 0 };\n\n/**\n * Statuses that describe a run that has *ended*. An `error` event promotes the\n * status to \"failed\" only when the last-seen status is NOT already terminal —\n * e.g. a client-side timeout reports \"incomplete\" (a partial) before its error,\n * and that explicit terminal status must win over the failure default.\n */\nconst TERMINAL_STATUSES: ReadonlySet<ResearchStatus> = new Set([\n  \"completed\",\n  \"failed\",\n  \"cancelled\",\n  \"incomplete\",\n  \"budget_exceeded\",\n]);\n\n/** Identity key for citation deduplication. */\nfunction citationKey(citation: ResearchCitation): string {\n  return `${citation.url}#${citation.startIndex ?? \"\"}`;\n}\n\nexport interface ResearchResultContext {\n  provider: string;\n  model: string;\n  jobId: string | null;\n}\n\nexport class ResearchResultCollector {\n  private reportParts: string[] = [];\n  private citations = new Map<string, ResearchCitation>();\n  private usage: ResearchUsage | undefined;\n  private lastStatus: ResearchStatus | undefined;\n  private doneReport = \"\";\n  private doneRaw: unknown;\n  private hasDone = false;\n  private firstEventAt: number | undefined;\n  private terminalAt: number | undefined;\n\n  /**\n   * Terminal error info from an `error` event.\n   * @internal Read by tests only — not part of the public consumer contract.\n   */\n  terminalError: ResearchErrorInfo | undefined;\n\n  constructor(\n    private readonly spec?: ResearchModelSpec,\n    private readonly now: () => number = Date.now,\n  ) {}\n\n  ingest(event: ResearchEvent): void {\n    this.firstEventAt ??= this.now();\n\n    switch (event.type) {\n      case \"text\":\n        this.reportParts.push(event.delta);\n        break;\n      case \"citation\":\n        this.addCitation(event.citation);\n        break;\n      case \"usage\":\n        this.mergeUsage(event.usage);\n        break;\n      case \"status\":\n        this.lastStatus = event.status;\n        break;\n      case \"error\":\n        this.terminalError = event.error;\n        this.terminalAt = this.now();\n        break;\n      case \"done\": {\n        this.hasDone = true;\n        this.lastStatus = event.result.status;\n        this.doneReport = event.result.report;\n        this.doneRaw = event.result.raw;\n        for (const citation of event.result.citations ?? []) {\n          this.addCitation(citation);\n        }\n        if (event.result.usage) {\n          this.mergeUsage(event.result.usage);\n        }\n        this.terminalAt = this.now();\n        break;\n      }\n      default:\n        break;\n    }\n  }\n\n  toResult(context: ResearchResultContext): ResearchResult {\n    const usage: ResearchUsage = { ...(this.usage ?? EMPTY_USAGE) };\n    // A provider-reported cost (e.g. OpenRouter usage accounting) is\n    // authoritative; fall back to the catalog-based estimate.\n    if (usage.costUSD === undefined && this.spec) {\n      usage.costUSD = estimateResearchCost(this.spec.pricing, usage);\n    }\n\n    const status: ResearchStatus =\n      this.lastStatus ?? (this.terminalError ? \"failed\" : \"in_progress\");\n    const lastIsTerminal = this.lastStatus !== undefined && TERMINAL_STATUSES.has(this.lastStatus);\n\n    return {\n      jobId: context.jobId,\n      provider: context.provider,\n      model: context.model,\n      // An error fails the run only when no explicit terminal status preceded\n      // it (a timeout's \"incomplete\" is a partial, not a failure).\n      status: this.terminalError && !this.hasDone && !lastIsTerminal ? \"failed\" : status,\n      report: this.doneReport !== \"\" ? this.doneReport : this.reportParts.join(\"\"),\n      citations: [...this.citations.values()],\n      usage,\n      durationMs:\n        this.firstEventAt !== undefined && this.terminalAt !== undefined\n          ? this.terminalAt - this.firstEventAt\n          : undefined,\n      raw: this.doneRaw,\n    };\n  }\n\n  /** Whether a terminal event (`done` or `error`) was ingested. */\n  get isTerminal(): boolean {\n    return this.hasDone || this.terminalError !== undefined;\n  }\n\n  private addCitation(citation: ResearchCitation): void {\n    const key = citationKey(citation);\n    if (!this.citations.has(key)) {\n      this.citations.set(key, citation);\n    }\n  }\n\n  private mergeUsage(incoming: ResearchUsage): void {\n    const current = this.usage ?? { ...EMPTY_USAGE };\n    this.usage = {\n      ...current,\n      ...incoming,\n      // Cumulative counters may be re-reported; never let them regress.\n      searches: max(current.searches, incoming.searches),\n    };\n  }\n}\n\nfunction max(a: number | undefined, b: number | undefined): number | undefined {\n  if (a === undefined) return b;\n  if (b === undefined) return a;\n  return Math.max(a, b);\n}\n","/**\n * Research job handle implementation.\n *\n * Wraps a provider's normalized event stream with:\n * - lazy stream opening (nothing happens until first iteration / result())\n * - cursor + jobId tracking and result aggregation (collector)\n * - automatic cursor-based reconnect on transient stream drops (resumable providers)\n * - a client-side time budget (aborts transport only; server-side job survives)\n * - abort-vs-cancel semantics (see ResearchOptions.signal / ResearchJob.cancel)\n */\n\nimport { isAbortError } from \"../core/errors.js\";\nimport type { ModelDescriptor } from \"../core/options.js\";\nimport type { ProviderAdapter } from \"../providers/provider.js\";\nimport { ResearchResultCollector } from \"./collector.js\";\nimport {\n  RESEARCH_DEFAULT_TIMEOUT_MS,\n  RESEARCH_STREAM_RECONNECT_MAX_ATTEMPTS,\n} from \"./constants.js\";\nimport {\n  ResearchJobNotResumableError,\n  ResearchNotPollableError,\n  ResearchStreamConsumedError,\n  ResearchTimeoutError,\n} from \"./errors.js\";\nimport type { ResearchModelSpec } from \"./model-spec.js\";\nimport type {\n  ResearchEvent,\n  ResearchJob,\n  ResearchJobRef,\n  ResearchOptions,\n  ResearchResult,\n  ResearchStatus,\n} from \"./types.js\";\n\ninterface ResearchJobInit {\n  adapter: ProviderAdapter;\n  descriptor: ModelDescriptor;\n  spec?: ResearchModelSpec;\n  /** Present in start mode. */\n  options?: ResearchOptions;\n  /** Present in attach mode. */\n  resumeFrom?: ResearchJobRef;\n}\n\ntype JobState = \"idle\" | \"streaming\" | \"finished\";\n\nexport class ResearchJobImpl implements ResearchJob {\n  private readonly adapter: ProviderAdapter;\n  private readonly descriptor: ModelDescriptor;\n  private readonly spec?: ResearchModelSpec;\n  private readonly options?: ResearchOptions;\n  private readonly resumeFrom?: ResearchJobRef;\n\n  private readonly collector: ResearchResultCollector;\n  private readonly controller = new AbortController();\n  private readonly timeoutMs: number;\n\n  private state: JobState = \"idle\";\n  private currentJobId: string | null;\n  private cursor?: string;\n  private startedAt?: string;\n  private timedOut = false;\n  private cancelRequested = false;\n  private finalResult?: ResearchResult;\n  private failure?: Error;\n  private completion?: { promise: Promise<void>; resolve: () => void };\n\n  constructor(init: ResearchJobInit) {\n    this.adapter = init.adapter;\n    this.descriptor = init.descriptor;\n    this.spec = init.spec;\n    this.options = init.options;\n    this.resumeFrom = init.resumeFrom;\n    this.collector = new ResearchResultCollector(init.spec);\n    this.currentJobId = init.resumeFrom?.jobId ?? null;\n    this.cursor = init.resumeFrom?.cursor;\n    this.startedAt = init.resumeFrom?.startedAt;\n\n    // An explicit user timeout deliberately bypasses the spec's maxDurationMs\n    // cap — the cap only shapes the default. (The provider still enforces its\n    // own server-side limit regardless of what the client waits for.)\n    const specCap = init.spec?.maxDurationMs ?? Number.POSITIVE_INFINITY;\n    this.timeoutMs = init.options?.timeoutMs ?? Math.min(RESEARCH_DEFAULT_TIMEOUT_MS, specCap);\n\n    if (init.options?.signal) {\n      const external = init.options.signal;\n      if (external.aborted) {\n        this.controller.abort(external.reason);\n      } else {\n        external.addEventListener(\"abort\", () => this.controller.abort(external.reason), {\n          once: true,\n        });\n      }\n    }\n  }\n\n  get jobId(): string | null {\n    return this.currentJobId;\n  }\n\n  get provider(): string {\n    return this.adapter.providerId;\n  }\n\n  get model(): string {\n    return this.descriptor.name;\n  }\n\n  [Symbol.asyncIterator](): AsyncIterator<ResearchEvent> {\n    return this.events()[Symbol.asyncIterator]();\n  }\n\n  events(): AsyncIterable<ResearchEvent> {\n    if (this.state !== \"idle\") {\n      throw new ResearchStreamConsumedError();\n    }\n    this.state = \"streaming\";\n    let resolveCompletion: () => void = () => {};\n    const promise = new Promise<void>((resolve) => {\n      resolveCompletion = resolve;\n    });\n    this.completion = { promise, resolve: resolveCompletion };\n    return this.run();\n  }\n\n  async result(): Promise<ResearchResult> {\n    if (this.state === \"idle\") {\n      // Drain internally.\n      for await (const _event of this.events()) {\n        // collector ingests inside run()\n      }\n    } else if (this.state === \"streaming\" && this.completion) {\n      await this.completion.promise;\n    }\n\n    if (this.failure) {\n      throw this.failure;\n    }\n    this.finalResult ??= this.collector.toResult(this.resultContext());\n    return this.finalResult;\n  }\n\n  async status(): Promise<ResearchStatus> {\n    if (!this.adapter.getResearchStatus) {\n      throw new ResearchNotPollableError(\n        `Provider \"${this.provider}\" does not support research status polling.`,\n      );\n    }\n    if (this.currentJobId === null) {\n      throw new ResearchNotPollableError(\n        `Research run on \"${this.provider}\" has no server-side job id to poll.`,\n      );\n    }\n    const snapshot = await this.adapter.getResearchStatus(this.buildRef());\n    return snapshot.status;\n  }\n\n  async cancel(): Promise<void> {\n    this.cancelRequested = true;\n    if (this.adapter.cancelResearch && this.currentJobId !== null) {\n      await this.adapter.cancelResearch(this.buildRef());\n    }\n    this.controller.abort();\n  }\n\n  toRef(): ResearchJobRef {\n    if (this.currentJobId === null) {\n      throw new ResearchJobNotResumableError(\n        `Research run on \"${this.provider}\" has no server-side job id — ` +\n          `the provider does not support background jobs, so it cannot be re-attached.`,\n      );\n    }\n    return this.buildRef();\n  }\n\n  private buildRef(): ResearchJobRef {\n    if (this.currentJobId === null) {\n      throw new ResearchJobNotResumableError(\"Research job has no server-side job id.\");\n    }\n    return {\n      provider: this.provider,\n      model: this.descriptor.name,\n      jobId: this.currentJobId,\n      cursor: this.cursor,\n      startedAt: this.startedAt,\n    };\n  }\n\n  private resultContext() {\n    return { provider: this.provider, model: this.descriptor.name, jobId: this.currentJobId };\n  }\n\n  private openStream(resume: boolean): AsyncIterable<ResearchEvent> {\n    if (resume) {\n      if (!this.adapter.resumeResearch) {\n        throw new ResearchJobNotResumableError(\n          `Provider \"${this.provider}\" does not support resuming research jobs.`,\n        );\n      }\n      return this.adapter.resumeResearch(this.buildRef(), this.controller.signal);\n    }\n    if (!this.adapter.startResearch || !this.options) {\n      throw new ResearchJobNotResumableError(\n        `Provider \"${this.provider}\" cannot start this research job.`,\n      );\n    }\n    return this.adapter.startResearch(\n      { ...this.options, signal: this.controller.signal },\n      this.descriptor,\n      this.spec,\n    );\n  }\n\n  private observe(event: ResearchEvent): void {\n    if (event.cursor !== undefined) {\n      this.cursor = event.cursor;\n    }\n    if (event.type === \"created\") {\n      if (event.jobId !== null) {\n        this.currentJobId = event.jobId;\n      }\n      this.startedAt ??= new Date().toISOString();\n    }\n    this.collector.ingest(event);\n  }\n\n  private canResume(): boolean {\n    if (this.adapter.resumeResearch === undefined || this.currentJobId === null) {\n      return false;\n    }\n    // Catalog spec is authoritative; without one (mocks, custom models) the\n    // presence of resumeResearch on the adapter decides.\n    return this.spec ? this.spec.capabilities.resumable : true;\n  }\n\n  private async *run(): AsyncGenerator<ResearchEvent> {\n    const timer = setTimeout(() => {\n      this.timedOut = true;\n      this.controller.abort(new ResearchTimeoutError(this.timeoutMs));\n    }, this.timeoutMs);\n    // Don't keep the process alive for the time budget (Node-only API).\n    (timer as { unref?: () => void }).unref?.();\n\n    let reconnectAttempts = 0;\n    let source = this.openStream(this.resumeFrom !== undefined);\n\n    try {\n      while (true) {\n        const iterator = source[Symbol.asyncIterator]();\n        try {\n          while (true) {\n            const next = await iterator.next();\n            if (next.done) {\n              return;\n            }\n            reconnectAttempts = 0;\n            this.observe(next.value);\n            yield next.value;\n            if (this.collector.isTerminal) {\n              return;\n            }\n          }\n        } catch (error) {\n          const err = error instanceof Error ? error : new Error(String(error));\n\n          if (this.timedOut) {\n            // A client-side timeout is a PARTIAL outcome, not a failure: the\n            // transport is torn down but the background job keeps running\n            // server-side (abort ≠ cancel), so the collected partial and a\n            // re-attachable ref stay valid. Emit an explicit \"incomplete\"\n            // status (so result() yields a partial rather than \"failed\") plus\n            // the timeout error (so streaming consumers still see it), and do\n            // NOT set this.failure — result() must not throw away the partial.\n            const statusEvent: ResearchEvent = { type: \"status\", status: \"incomplete\" };\n            this.collector.ingest(statusEvent);\n            yield statusEvent;\n            const info = {\n              message: new ResearchTimeoutError(this.timeoutMs).message,\n              code: \"timeout\",\n              retryable: false,\n            };\n            this.collector.ingest({ type: \"error\", error: info });\n            yield { type: \"error\", error: info };\n            return;\n          }\n\n          if (this.cancelRequested && isAbortError(err)) {\n            const event: ResearchEvent = { type: \"status\", status: \"cancelled\" };\n            this.observe(event);\n            yield event;\n            return;\n          }\n\n          if (isAbortError(err)) {\n            // External abort: transport-only teardown; surface to the caller.\n            this.failure = err;\n            throw err;\n          }\n\n          if (this.canResume() && reconnectAttempts < RESEARCH_STREAM_RECONNECT_MAX_ATTEMPTS) {\n            reconnectAttempts += 1;\n            source = this.openStream(true);\n            continue;\n          }\n\n          const info = { message: err.message, retryable: false };\n          this.collector.ingest({ type: \"error\", error: info });\n          yield { type: \"error\", error: info };\n          return;\n        }\n      }\n    } finally {\n      clearTimeout(timer);\n      this.state = \"finished\";\n      this.finalResult = this.collector.toResult(this.resultContext());\n      this.completion?.resolve();\n    }\n  }\n}\n","/**\n * Deep Research — normalized types.\n *\n * Deep research runs are long-lived (minutes to an hour), server-side agentic\n * jobs that browse the web and return cited reports. This module defines the\n * provider-independent surface: options, the normalized event union, the final\n * result, and the serializable job reference used to re-attach to a running\n * background job after a disconnect or process restart.\n */\n\nimport type { ReasoningConfig, TokenUsage } from \"../core/options.js\";\nimport type { ResearchModelSpec } from \"./model-spec.js\";\n\n/**\n * Lifecycle status of a research job.\n *\n * Superset of provider statuses:\n * - OpenAI Responses: `queued | in_progress | completed | failed | cancelled | incomplete`\n * - Gemini Interactions adds `requires_action` and `budget_exceeded`\n */\nexport type ResearchStatus =\n  | \"queued\"\n  | \"in_progress\"\n  | \"requires_action\"\n  | \"completed\"\n  | \"failed\"\n  | \"cancelled\"\n  | \"incomplete\"\n  | \"budget_exceeded\";\n\n/**\n * Data-source / auxiliary tools a research run may use.\n *\n * Providers map these to their native tool shapes (e.g. `web_search` becomes\n * OpenAI's `web_search_preview`). Which types a given model accepts is\n * declared in {@link ResearchModelSpec.capabilities.tools}.\n */\nexport type ResearchToolConfig =\n  | { type: \"web_search\" }\n  | { type: \"file_search\"; vectorStoreIds: string[] }\n  | { type: \"mcp\"; serverLabel: string; serverUrl: string; requireApproval?: \"never\" }\n  | { type: \"code_interpreter\" };\n\n/** Union of the tool type discriminators. */\nexport type ResearchToolType = ResearchToolConfig[\"type\"];\n\n/** Tool types that count as a data source (OpenAI requires at least one). */\nexport const RESEARCH_DATA_SOURCE_TOOL_TYPES: readonly ResearchToolType[] = [\n  \"web_search\",\n  \"file_search\",\n  \"mcp\",\n];\n\n/**\n * Options for starting a research run.\n */\nexport interface ResearchOptions {\n  /**\n   * Model identifier, optionally provider-prefixed:\n   * `\"openai:gpt-5.5-pro\"`, `\"gemini:deep-research-preview-04-2026\"`,\n   * `\"openrouter:perplexity/sonar-deep-research\"`.\n   */\n  model: string;\n  /** The research question / brief. */\n  query: string;\n  /**\n   * System-level guidance. Folded into the input on providers without a\n   * system slot (OpenAI deep research), mapped to `system_instruction`\n   * (Gemini) or a system message (OpenRouter) elsewhere.\n   */\n  systemPrompt?: string;\n  /**\n   * Run as a server-side background job (survives disconnects; enables\n   * {@link ResearchJob.toRef} / attach). Defaults to the model's\n   * `capabilities.background`. Requesting `true` on a provider without\n   * background support is a validation error.\n   */\n  background?: boolean;\n  /**\n   * Data-source / auxiliary tools. Defaults to the model's\n   * `requiredTools`. Tools outside the model's `capabilities.tools`\n   * are rejected before any network call.\n   */\n  tools?: ResearchToolConfig[];\n  /** Cap on total built-in tool calls (cost control; OpenAI `max_tool_calls`). */\n  maxToolCalls?: number;\n  /** Reasoning configuration (mapped per provider: summaries, effort, thinking). */\n  reasoning?: ReasoningConfig;\n  /**\n   * Continue from a previous **completed** research job (Gemini\n   * `previous_interaction_id`). Rejected on models without follow-up support.\n   */\n  previousJobId?: string;\n  /**\n   * Overall time budget for the run as observed by this client. Expiry aborts\n   * the transport (the server-side job keeps running and stays attachable) and\n   * surfaces a `ResearchTimeoutError`. Defaults to\n   * `min(RESEARCH_DEFAULT_TIMEOUT_MS, spec.maxDurationMs)`.\n   */\n  timeoutMs?: number;\n  /**\n   * Aborts the transport only — a background job keeps running server-side\n   * and can be re-attached via its ref. Use {@link ResearchJob.cancel} to stop\n   * the job on the server.\n   */\n  signal?: AbortSignal;\n  /** Provider-specific passthrough (same spirit as `LLMGenerationOptions.extra`). */\n  extra?: Record<string, unknown>;\n}\n\n/** A citation attached to the research report. */\nexport interface ResearchCitation {\n  url: string;\n  title?: string;\n  /** Start offset of the cited span in the report text, when provided. */\n  startIndex?: number;\n  /** End offset of the cited span in the report text, when provided. */\n  endIndex?: number;\n  /** Excerpt of the cited source content, when provided (OpenRouter). */\n  content?: string;\n}\n\n/** Token usage extended with research-specific dimensions. */\nexport interface ResearchUsage extends TokenUsage {\n  /** Number of web searches performed, when the provider reports it. */\n  searches?: number;\n  /** Estimated cost in USD, computed from catalog pricing when available. */\n  costUSD?: number;\n}\n\n/** Error payload carried by `error` events. */\nexport interface ResearchErrorInfo {\n  message: string;\n  code?: string;\n  /** Whether retrying (or resuming) may succeed. */\n  retryable: boolean;\n}\n\n/**\n * Normalized research event union.\n *\n * Every event may carry a `cursor` (provider stream position: OpenAI\n * `sequence_number`, Gemini `event_id`) used for lossless resume, and a\n * `rawEvent` escape hatch with the provider's original payload.\n */\nexport type ResearchEvent = { cursor?: string; rawEvent?: unknown } & (\n  | {\n      type: \"created\";\n      /** Server-side job id; `null` on providers without job handles (OpenRouter). */\n      jobId: string | null;\n    }\n  | { type: \"status\"; status: ResearchStatus }\n  | {\n      type: \"phase\";\n      /** Coarse activity phase. Providers may emit additional phase strings. */\n      phase: \"planning\" | \"searching\" | \"reasoning\" | \"writing\" | (string & {});\n    }\n  | { type: \"thinking\"; delta: string }\n  | {\n      type: \"search\";\n      action: \"search\" | \"open_page\" | \"find_in_page\";\n      status: \"started\" | \"completed\";\n      query?: string;\n      url?: string;\n    }\n  | {\n      type: \"tool\";\n      tool: \"code_interpreter\" | \"file_search\" | \"mcp\";\n      status: \"started\" | \"completed\";\n      detail?: string;\n    }\n  | { type: \"text\"; delta: string }\n  | { type: \"citation\"; citation: ResearchCitation }\n  | { type: \"usage\"; usage: ResearchUsage }\n  | { type: \"error\"; error: ResearchErrorInfo }\n  | { type: \"done\"; result: ResearchDoneInfo }\n);\n\n/**\n * Terminal payload emitted by provider normalizers on `done`.\n *\n * Providers fill what they know; the job's collector merges it with\n * accumulated stream state (text deltas, citations, usage) into the final\n * {@link ResearchResult}. `report` may be empty when the report was fully\n * streamed as `text` deltas.\n */\nexport interface ResearchDoneInfo {\n  status: ResearchStatus;\n  /** Full report text when the provider returns it wholesale (else \"\"). */\n  report: string;\n  citations?: ResearchCitation[];\n  usage?: ResearchUsage;\n  /** Final provider object (response / interaction / last chunk). */\n  raw?: unknown;\n}\n\n/** Final result of a research run. */\nexport interface ResearchResult {\n  /** Server-side job id, or `null` on providers without job handles. */\n  jobId: string | null;\n  /** Adapter provider id that ran the job (e.g. \"openai\", \"mock\"). */\n  provider: string;\n  /** Model / agent id (unprefixed). */\n  model: string;\n  status: ResearchStatus;\n  /** The research report text. */\n  report: string;\n  /** Deduplicated citations. */\n  citations: ResearchCitation[];\n  usage: ResearchUsage;\n  /** Wall-clock duration observed by this client, when measurable. */\n  durationMs?: number;\n  /** Final provider payload, when available. */\n  raw?: unknown;\n}\n\n/**\n * JSON-serializable reference to a background research job.\n *\n * Round-trip contract: `JSON.parse(JSON.stringify(ref))` is a valid ref, and\n * `client.research.attach(ref)` resumes the event stream from `cursor` —\n * across process restarts.\n */\nexport interface ResearchJobRef {\n  /** Adapter provider id (e.g. \"openai\", \"gemini\", \"mock\"). */\n  provider: string;\n  /** Model / agent id (unprefixed). */\n  model: string;\n  /** Server-side job id. */\n  jobId: string;\n  /** Last observed stream cursor; resume yields events strictly after it. */\n  cursor?: string;\n  /** ISO timestamp of job creation, when known. */\n  startedAt?: string;\n}\n\n/** Snapshot returned by status polls. */\nexport interface ResearchStatusSnapshot {\n  status: ResearchStatus;\n  /** Present when the job reached a terminal state and the result is available. */\n  result?: ResearchResult;\n}\n\n/**\n * Handle to a research run.\n *\n * The job is itself async-iterable (equivalent to iterating\n * {@link ResearchJob.events}). The event stream may be consumed **once**.\n */\nexport interface ResearchJob extends AsyncIterable<ResearchEvent> {\n  /** Server-side job id once known (`created` event), else `null`. */\n  readonly jobId: string | null;\n  /** Adapter provider id. */\n  readonly provider: string;\n  /** Model / agent id (unprefixed). */\n  readonly model: string;\n  /**\n   * Live event stream. Auto-reconnects with the last cursor on transient\n   * stream drops when the model is resumable. Single consumption only.\n   */\n  events(): AsyncIterable<ResearchEvent>;\n  /**\n   * Final result. Drains the event stream internally when not already\n   * consumed; otherwise resolves when iteration completes.\n   */\n  result(): Promise<ResearchResult>;\n  /**\n   * One-shot server-side status poll.\n   * @throws ResearchNotPollableError on providers without status polling.\n   */\n  status(): Promise<ResearchStatus>;\n  /**\n   * Cancel the job server-side where supported; otherwise aborts the\n   * transport. See {@link ResearchOptions.signal} for the abort-vs-cancel\n   * distinction.\n   */\n  cancel(): Promise<void>;\n  /**\n   * Serializable reference for later {@link ResearchNamespaceLike.attach}.\n   * @throws ResearchJobNotResumableError when the job has no server-side id.\n   */\n  toRef(): ResearchJobRef;\n}\n\n/**\n * Minimal structural interface of the research namespace (used by docs/tests;\n * the concrete class lives in `namespace.ts`).\n */\nexport interface ResearchNamespaceLike {\n  start(options: ResearchOptions): ResearchJob;\n  attach(ref: ResearchJobRef): ResearchJob;\n}\n","/**\n * Research namespace — `client.research`.\n *\n * Mirrors the image/speech capability namespaces: dispatches to the first\n * adapter (in priority order) that supports the model, after validating the\n * request against the model's catalog spec. Providers plug in via the\n * optional research methods on {@link ProviderAdapter}.\n */\n\nimport type { ILogObj, Logger } from \"tslog\";\nimport type { ModelDescriptor, ModelIdentifierParser } from \"../core/options.js\";\nimport { createLogger } from \"../logging/logger.js\";\nimport type { ProviderAdapter } from \"../providers/provider.js\";\nimport { MS_PER_DAY, RESEARCH_SHUTDOWN_WARNING_WINDOW_DAYS } from \"./constants.js\";\nimport {\n  ResearchDeprecatedModelError,\n  ResearchJobNotResumableError,\n  ResearchNotPollableError,\n  ResearchNotSupportedError,\n  ResearchValidationError,\n} from \"./errors.js\";\nimport { ResearchJobImpl } from \"./job.js\";\nimport type { ResearchModelSpec } from \"./model-spec.js\";\nimport type {\n  ResearchJob,\n  ResearchJobRef,\n  ResearchOptions,\n  ResearchStatusSnapshot,\n  ResearchToolConfig,\n} from \"./types.js\";\nimport { RESEARCH_DATA_SOURCE_TOOL_TYPES } from \"./types.js\";\n\nexport class ResearchNamespace {\n  private readonly logger: Logger<ILogObj>;\n\n  constructor(\n    private readonly adapters: ProviderAdapter[],\n    private readonly parser: ModelIdentifierParser,\n    private readonly now: () => number = Date.now,\n    logger?: Logger<ILogObj>,\n  ) {\n    this.logger = logger ?? createLogger({ name: \"llmist:research\" });\n  }\n\n  /**\n   * Start a research run. Returns immediately; the provider stream opens\n   * lazily on first iteration (or on `result()`).\n   */\n  start(options: ResearchOptions): ResearchJob {\n    const descriptor = this.parser.parse(options.model);\n    const adapter = this.findResearchAdapter(descriptor);\n    if (!adapter) {\n      throw new ResearchNotSupportedError(\n        `No provider supports deep research for model \"${options.model}\". ` +\n          `Research-capable models: ${this.describeAvailableModels()}`,\n      );\n    }\n\n    const spec = this.findSpec(adapter, descriptor.name);\n    const validated = spec ? this.validate(options, spec) : options;\n\n    return new ResearchJobImpl({ adapter, descriptor, spec, options: validated });\n  }\n\n  /**\n   * Re-attach to a background research job from a serialized ref.\n   * No network happens until the returned job is iterated.\n   */\n  attach(ref: ResearchJobRef): ResearchJob {\n    const adapter = this.findAdapterByProviderId(ref.provider);\n    if (!adapter) {\n      throw new ResearchNotSupportedError(\n        `No registered provider with id \"${ref.provider}\" to attach research job \"${ref.jobId}\".`,\n      );\n    }\n    if (!adapter.resumeResearch) {\n      throw new ResearchJobNotResumableError(\n        `Provider \"${ref.provider}\" does not support resuming research jobs.`,\n      );\n    }\n    const descriptor: ModelDescriptor = { provider: ref.provider, name: ref.model };\n    const spec = this.findSpec(adapter, ref.model);\n    return new ResearchJobImpl({ adapter, descriptor, spec, resumeFrom: ref });\n  }\n\n  /** One-shot status poll for a job ref. */\n  async get(ref: ResearchJobRef): Promise<ResearchStatusSnapshot> {\n    const adapter = this.findAdapterByProviderId(ref.provider);\n    if (!adapter) {\n      throw new ResearchNotSupportedError(`No registered provider with id \"${ref.provider}\".`);\n    }\n    if (!adapter.getResearchStatus) {\n      throw new ResearchNotPollableError(\n        `Provider \"${ref.provider}\" does not support research status polling.`,\n      );\n    }\n    return adapter.getResearchStatus(ref);\n  }\n\n  /** Cancel a background job server-side. */\n  async cancel(ref: ResearchJobRef): Promise<void> {\n    const adapter = this.findAdapterByProviderId(ref.provider);\n    if (!adapter) {\n      throw new ResearchNotSupportedError(`No registered provider with id \"${ref.provider}\".`);\n    }\n    if (!adapter.cancelResearch) {\n      throw new ResearchNotSupportedError(\n        `Provider \"${ref.provider}\" does not support cancelling research jobs.`,\n      );\n    }\n    return adapter.cancelResearch(ref);\n  }\n\n  /** All research-capable models/agents across registered providers. */\n  listModels(): ResearchModelSpec[] {\n    const specs: ResearchModelSpec[] = [];\n    for (const adapter of this.adapters) {\n      specs.push(...(adapter.getResearchModelSpecs?.() ?? []));\n    }\n    return specs;\n  }\n\n  /** Whether any registered provider supports research for this model. */\n  supportsModel(model: string): boolean {\n    try {\n      return this.findResearchAdapter(this.parser.parse(model)) !== undefined;\n    } catch {\n      return false;\n    }\n  }\n\n  private findResearchAdapter(descriptor: ModelDescriptor): ProviderAdapter | undefined {\n    return this.adapters.find(\n      (adapter) =>\n        adapter.supports(descriptor) && (adapter.supportsResearch?.(descriptor.name) ?? false),\n    );\n  }\n\n  private findAdapterByProviderId(providerId: string): ProviderAdapter | undefined {\n    return this.adapters.find((adapter) => adapter.providerId === providerId);\n  }\n\n  private findSpec(adapter: ProviderAdapter, modelId: string): ResearchModelSpec | undefined {\n    return adapter.getResearchModelSpecs?.().find((spec) => spec.modelId === modelId);\n  }\n\n  private describeAvailableModels(): string {\n    const models = this.listModels();\n    if (models.length === 0) {\n      return \"(none registered)\";\n    }\n    return models.map((spec) => `${spec.provider}:${spec.modelId}`).join(\", \");\n  }\n\n  /**\n   * Pre-flight validation against the catalog spec — fails fast before any\n   * network call and applies spec-driven defaults.\n   */\n  private validate(options: ResearchOptions, spec: ResearchModelSpec): ResearchOptions {\n    this.enforceLifecycle(spec);\n\n    const background = options.background ?? spec.capabilities.background;\n    if (background && !spec.capabilities.background) {\n      throw new ResearchValidationError(\n        `Model \"${spec.modelId}\" does not support background research jobs.`,\n      );\n    }\n\n    if (options.previousJobId && !spec.capabilities.followUps) {\n      throw new ResearchValidationError(\n        `Model \"${spec.modelId}\" does not support follow-up research runs (previousJobId).`,\n      );\n    }\n\n    const tools = this.resolveTools(options, spec);\n\n    return { ...options, background, tools };\n  }\n\n  private resolveTools(\n    options: ResearchOptions,\n    spec: ResearchModelSpec,\n  ): ResearchToolConfig[] | undefined {\n    if (options.tools === undefined) {\n      return spec.requiredTools;\n    }\n\n    for (const tool of options.tools) {\n      if (!spec.capabilities.tools.includes(tool.type)) {\n        throw new ResearchValidationError(\n          `Model \"${spec.modelId}\" does not accept the \"${tool.type}\" tool. ` +\n            (spec.capabilities.tools.length > 0\n              ? `Accepted tools: ${spec.capabilities.tools.join(\", \")}.`\n              : \"This model manages its research tools itself — omit the tools option.\"),\n        );\n      }\n    }\n\n    const hasDataSource = options.tools.some((tool) =>\n      RESEARCH_DATA_SOURCE_TOOL_TYPES.includes(tool.type),\n    );\n    if (!hasDataSource && spec.requiredTools) {\n      return [...spec.requiredTools, ...options.tools];\n    }\n    return options.tools;\n  }\n\n  private enforceLifecycle(spec: ResearchModelSpec): void {\n    const shutdownDate = spec.metadata?.shutdownDate;\n    if (!shutdownDate) {\n      return;\n    }\n    const shutdownMs = Date.parse(shutdownDate);\n    if (Number.isNaN(shutdownMs)) {\n      return;\n    }\n    const nowMs = this.now();\n    if (nowMs >= shutdownMs) {\n      throw new ResearchDeprecatedModelError({\n        modelId: spec.modelId,\n        shutdownDate,\n        replacement: spec.metadata?.replacement,\n      });\n    }\n    const warningStartMs = shutdownMs - RESEARCH_SHUTDOWN_WARNING_WINDOW_DAYS * MS_PER_DAY;\n    if (nowMs >= warningStartMs) {\n      this.logger.warn(\n        `Research model \"${spec.modelId}\" shuts down on ${shutdownDate}` +\n          (spec.metadata?.replacement ? ` — migrate to \"${spec.metadata.replacement}\".` : \".\"),\n      );\n    }\n  }\n}\n","/**\n * Model Registry\n *\n * Centralized registry for querying LLM model specifications,\n * validating configurations, and estimating costs.\n *\n * Model data is provided by ProviderAdapter implementations and\n * automatically populated when providers are registered.\n */\n\nimport type { ProviderAdapter } from \"../providers/provider.js\";\nimport type { CostEstimate, ModelLimits, ModelSpec } from \"./model-catalog.js\";\nimport { stripProviderPrefix } from \"./model-shortcuts.js\";\n\nexport class ModelRegistry {\n  private modelSpecs: ModelSpec[] = [];\n  private providerMap = new Map<string, ModelSpec[]>();\n\n  /**\n   * Register a provider and collect its model specifications\n   */\n  registerProvider(provider: ProviderAdapter): void {\n    const specs = [...(provider.getModelSpecs?.() ?? [])];\n\n    if (specs.length > 0) {\n      this.modelSpecs.push(...specs);\n      this.providerMap.set(provider.providerId, specs);\n    }\n  }\n\n  /**\n   * Register a custom model specification at runtime\n   *\n   * Use this to add models that aren't in the built-in catalog, such as:\n   * - Fine-tuned models with custom pricing\n   * - New models not yet supported by llmist\n   * - Custom deployments with different configurations\n   *\n   * @param spec - Complete model specification\n   * @throws {Error} If spec is missing required fields\n   *\n   * @example\n   * ```ts\n   * client.modelRegistry.registerModel({\n   *   provider: \"openai\",\n   *   modelId: \"ft:gpt-4o-2024-08-06:my-org:custom:abc123\",\n   *   displayName: \"My Fine-tuned GPT-4o\",\n   *   contextWindow: 128_000,\n   *   maxOutputTokens: 16_384,\n   *   pricing: { input: 7.5, output: 30.0 },\n   *   knowledgeCutoff: \"2024-08\",\n   *   features: { streaming: true, functionCalling: true, vision: true }\n   * });\n   * ```\n   */\n  registerModel(spec: ModelSpec): void {\n    // Validate required fields\n    if (!spec.modelId || !spec.provider) {\n      throw new Error(\"ModelSpec must have modelId and provider\");\n    }\n\n    // Check for duplicates\n    const existing = this.getModelSpec(spec.modelId);\n    if (existing) {\n      console.warn(\n        `[llmist] Overwriting existing model spec for \"${spec.modelId}\". ` +\n          `Previous: ${existing.displayName}, New: ${spec.displayName}`,\n      );\n      // Remove old spec from arrays\n      const index = this.modelSpecs.findIndex((m) => m.modelId === spec.modelId);\n      if (index !== -1) {\n        this.modelSpecs.splice(index, 1);\n      }\n      // Remove from provider map\n      const providerSpecs = this.providerMap.get(spec.provider);\n      if (providerSpecs) {\n        const providerIndex = providerSpecs.findIndex((m) => m.modelId === spec.modelId);\n        if (providerIndex !== -1) {\n          providerSpecs.splice(providerIndex, 1);\n        }\n      }\n    }\n\n    // Add to registry\n    this.modelSpecs.push(spec);\n\n    // Update provider map\n    const providerSpecs = this.providerMap.get(spec.provider) ?? [];\n    providerSpecs.push(spec);\n    this.providerMap.set(spec.provider, providerSpecs);\n  }\n\n  /**\n   * Register multiple custom model specifications at once\n   *\n   * @param specs - Array of complete model specifications\n   *\n   * @example\n   * ```ts\n   * client.modelRegistry.registerModels([\n   *   { provider: \"openai\", modelId: \"gpt-5\", ... },\n   *   { provider: \"openai\", modelId: \"gpt-5-mini\", ... }\n   * ]);\n   * ```\n   */\n  registerModels(specs: ModelSpec[]): void {\n    for (const spec of specs) {\n      this.registerModel(spec);\n    }\n  }\n\n  /**\n   * Get model specification by model ID\n   * @param modelId - Full model identifier, optionally with provider prefix\n   *                  (e.g., 'gpt-5', 'claude-sonnet-4-5-20250929', 'anthropic:claude-sonnet-4-5')\n   * @returns ModelSpec if found, undefined otherwise\n   */\n  getModelSpec(modelId: string): ModelSpec | undefined {\n    // Support provider-prefixed model IDs (e.g., \"anthropic:claude-sonnet-4-5\")\n    // Strip the prefix to match against the registry's model IDs\n    const normalizedId = stripProviderPrefix(modelId);\n    return this.modelSpecs.find((model) => model.modelId === normalizedId);\n  }\n\n  /**\n   * List all models, optionally filtered by provider\n   * @param providerId - Optional provider ID to filter by (e.g., 'openai', 'anthropic')\n   * @returns Array of ModelSpec objects\n   */\n  listModels(providerId?: string): ModelSpec[] {\n    if (!providerId) {\n      return [...this.modelSpecs];\n    }\n\n    return [...(this.providerMap.get(providerId) ?? [])];\n  }\n\n  /**\n   * Get context window and output limits for a model\n   * @param modelId - Full model identifier\n   * @returns ModelLimits if model found, undefined otherwise\n   */\n  getModelLimits(modelId: string): ModelLimits | undefined {\n    const spec = this.getModelSpec(modelId);\n    if (!spec) return undefined;\n\n    return {\n      contextWindow: spec.contextWindow,\n      maxOutputTokens: spec.maxOutputTokens,\n    };\n  }\n\n  /**\n   * Estimate API cost for a given model and token usage\n   * @param modelId - Full model identifier\n   * @param inputTokens - Number of input tokens (total, including cached and cache creation)\n   * @param outputTokens - Number of output tokens\n   * @param cachedInputTokens - Number of cached input tokens (subset of inputTokens)\n   * @param cacheCreationInputTokens - Number of cache creation tokens (subset of inputTokens, Anthropic only)\n   * @param reasoningTokens - Number of reasoning/thinking tokens (subset of outputTokens)\n   * @returns CostEstimate if model found, undefined otherwise\n   */\n  estimateCost(\n    modelId: string,\n    inputTokens: number,\n    outputTokens: number,\n    cachedInputTokens = 0,\n    cacheCreationInputTokens = 0,\n    reasoningTokens = 0,\n  ): CostEstimate | undefined {\n    const spec = this.getModelSpec(modelId);\n    if (!spec) return undefined;\n\n    // Pricing is per 1M tokens, so convert to actual cost\n    // Cached tokens are charged at a lower rate (or same rate if no cached pricing)\n    // Cache creation tokens are charged at a higher rate (Anthropic: 1.25x input)\n    const cachedRate = spec.pricing.cachedInput ?? spec.pricing.input;\n    const cacheWriteRate = spec.pricing.cacheWriteInput ?? spec.pricing.input;\n    const uncachedInputTokens = inputTokens - cachedInputTokens - cacheCreationInputTokens;\n\n    const uncachedInputCost = (uncachedInputTokens / 1_000_000) * spec.pricing.input;\n    const cachedInputCost = (cachedInputTokens / 1_000_000) * cachedRate;\n    const cacheCreationCost = (cacheCreationInputTokens / 1_000_000) * cacheWriteRate;\n    const inputCost = uncachedInputCost + cachedInputCost + cacheCreationCost;\n\n    // Reasoning tokens use reasoningOutput pricing when available, otherwise output pricing\n    // They are a subset of outputTokens, so we split the output cost accordingly\n    const reasoningRate = spec.pricing.reasoningOutput ?? spec.pricing.output;\n    const nonReasoningOutputTokens = outputTokens - reasoningTokens;\n    const reasoningCost = (reasoningTokens / 1_000_000) * reasoningRate;\n    const nonReasoningOutputCost = (nonReasoningOutputTokens / 1_000_000) * spec.pricing.output;\n    const outputCost = nonReasoningOutputCost + reasoningCost;\n    const totalCost = inputCost + outputCost;\n\n    return {\n      inputCost,\n      cachedInputCost,\n      cacheCreationCost,\n      outputCost,\n      reasoningCost,\n      totalCost,\n      currency: \"USD\",\n    };\n  }\n\n  /**\n   * Validate that requested token count fits within model limits\n   * @param modelId - Full model identifier\n   * @param requestedTokens - Total tokens requested (input + output)\n   * @returns true if valid, false if model not found or exceeds limits\n   */\n  validateModelConfig(modelId: string, requestedTokens: number): boolean {\n    const limits = this.getModelLimits(modelId);\n    if (!limits) return false;\n\n    return requestedTokens <= limits.contextWindow;\n  }\n\n  /**\n   * Check if a model supports a specific feature\n   * @param modelId - Full model identifier\n   * @param feature - Feature to check ('streaming', 'functionCalling', 'vision', etc.)\n   * @returns true if model supports feature, false otherwise\n   */\n  supportsFeature(modelId: string, feature: keyof ModelSpec[\"features\"]): boolean {\n    const spec = this.getModelSpec(modelId);\n    if (!spec) return false;\n\n    return spec.features[feature] === true;\n  }\n\n  /**\n   * Get all models that support a specific feature\n   * @param feature - Feature to filter by\n   * @param providerId - Optional provider ID to filter by\n   * @returns Array of ModelSpec objects that support the feature\n   */\n  getModelsByFeature(feature: keyof ModelSpec[\"features\"], providerId?: string): ModelSpec[] {\n    const models = this.listModels(providerId);\n    return models.filter((model) => model.features[feature] === true);\n  }\n\n  /**\n   * Get the most cost-effective model for a given provider and token budget\n   * @param inputTokens - Expected input tokens\n   * @param outputTokens - Expected output tokens\n   * @param providerId - Optional provider ID to filter by\n   * @returns ModelSpec with lowest total cost, or undefined if no models found\n   */\n  getCheapestModel(\n    inputTokens: number,\n    outputTokens: number,\n    providerId?: string,\n  ): ModelSpec | undefined {\n    const models = this.listModels(providerId);\n    if (models.length === 0) return undefined;\n\n    let cheapest: { model: ModelSpec; cost: number } | undefined;\n\n    for (const model of models) {\n      const estimate = this.estimateCost(model.modelId, inputTokens, outputTokens);\n      if (!estimate) continue;\n\n      if (!cheapest || estimate.totalCost < cheapest.cost) {\n        cheapest = { model, cost: estimate.totalCost };\n      }\n    }\n\n    return cheapest?.model;\n  }\n}\n","/**\n * Image Generation Namespace\n *\n * Provides image generation methods.\n *\n * @example\n * ```typescript\n * const llmist = new LLMist();\n *\n * const result = await llmist.image.generate({\n *   model: \"dall-e-3\",\n *   prompt: \"A cat in space\",\n *   size: \"1024x1024\",\n *   quality: \"hd\",\n * });\n *\n * console.log(result.images[0].url);\n * console.log(\"Cost:\", result.cost);\n * ```\n */\n\nimport type { ProviderAdapter } from \"../../providers/provider.js\";\nimport type {\n  ImageGenerationOptions,\n  ImageGenerationResult,\n  ImageModelSpec,\n} from \"../media-types.js\";\n\nexport class ImageNamespace {\n  constructor(\n    private readonly adapters: ProviderAdapter[],\n    private readonly defaultProvider: string,\n  ) {}\n\n  /**\n   * Generate images from a text prompt.\n   *\n   * @param options - Image generation options\n   * @returns Promise resolving to the generation result with images and cost\n   * @throws Error if the provider doesn't support image generation\n   */\n  async generate(options: ImageGenerationOptions): Promise<ImageGenerationResult> {\n    const modelId = options.model;\n\n    // Find an adapter that supports this image model\n    const adapter = this.findImageAdapter(modelId);\n    if (!adapter || !adapter.generateImage) {\n      throw new Error(\n        `No provider supports image generation for model \"${modelId}\". ` +\n          `Available image models: ${this.listModels()\n            .map((m) => m.modelId)\n            .join(\", \")}`,\n      );\n    }\n\n    return adapter.generateImage(options);\n  }\n\n  /**\n   * List all available image generation models.\n   */\n  listModels(): ImageModelSpec[] {\n    const models: ImageModelSpec[] = [];\n    for (const adapter of this.adapters) {\n      if (adapter.getImageModelSpecs) {\n        models.push(...adapter.getImageModelSpecs());\n      }\n    }\n    return models;\n  }\n\n  /**\n   * Check if a model is supported for image generation.\n   */\n  supportsModel(modelId: string): boolean {\n    return this.findImageAdapter(modelId) !== undefined;\n  }\n\n  private findImageAdapter(modelId: string): ProviderAdapter | undefined {\n    return this.adapters.find((adapter) => adapter.supportsImageGeneration?.(modelId) ?? false);\n  }\n}\n","/**\n * Speech Generation Namespace\n *\n * Provides text-to-speech generation methods.\n *\n * @example\n * ```typescript\n * const llmist = new LLMist();\n *\n * const result = await llmist.speech.generate({\n *   model: \"tts-1-hd\",\n *   input: \"Hello, world!\",\n *   voice: \"nova\",\n * });\n *\n * // Save the audio\n * fs.writeFileSync(\"output.mp3\", Buffer.from(result.audio));\n * console.log(\"Cost:\", result.cost);\n * ```\n */\n\nimport type { ProviderAdapter } from \"../../providers/provider.js\";\nimport type {\n  SpeechGenerationOptions,\n  SpeechGenerationResult,\n  SpeechModelSpec,\n} from \"../media-types.js\";\n\nexport class SpeechNamespace {\n  constructor(\n    private readonly adapters: ProviderAdapter[],\n    private readonly defaultProvider: string,\n  ) {}\n\n  /**\n   * Generate speech audio from text.\n   *\n   * @param options - Speech generation options\n   * @returns Promise resolving to the generation result with audio and cost\n   * @throws Error if the provider doesn't support speech generation\n   */\n  async generate(options: SpeechGenerationOptions): Promise<SpeechGenerationResult> {\n    const modelId = options.model;\n\n    // Find an adapter that supports this speech model\n    const adapter = this.findSpeechAdapter(modelId);\n    if (!adapter || !adapter.generateSpeech) {\n      throw new Error(\n        `No provider supports speech generation for model \"${modelId}\". ` +\n          `Available speech models: ${this.listModels()\n            .map((m) => m.modelId)\n            .join(\", \")}`,\n      );\n    }\n\n    return adapter.generateSpeech(options);\n  }\n\n  /**\n   * List all available speech generation models.\n   */\n  listModels(): SpeechModelSpec[] {\n    const models: SpeechModelSpec[] = [];\n    for (const adapter of this.adapters) {\n      if (adapter.getSpeechModelSpecs) {\n        models.push(...adapter.getSpeechModelSpecs());\n      }\n    }\n    return models;\n  }\n\n  /**\n   * Check if a model is supported for speech generation.\n   */\n  supportsModel(modelId: string): boolean {\n    return this.findSpeechAdapter(modelId) !== undefined;\n  }\n\n  private findSpeechAdapter(modelId: string): ProviderAdapter | undefined {\n    return this.adapters.find((adapter) => adapter.supportsSpeechGeneration?.(modelId) ?? false);\n  }\n}\n","/**\n * Quick execution methods for simple use cases.\n *\n * These methods provide convenient shortcuts for common operations\n * without requiring full agent setup.\n *\n * @example\n * ```typescript\n * // Quick completion\n * const answer = await llmist.complete(\"What is 2+2?\");\n *\n * // Quick streaming\n * for await (const chunk of llmist.stream(\"Tell me a story\")) {\n *   process.stdout.write(chunk);\n * }\n * ```\n */\n\nimport type { LLMist } from \"./client.js\";\nimport { LLMMessageBuilder } from \"./messages.js\";\nimport { resolveModel } from \"./model-shortcuts.js\";\n\n/**\n * Options for text generation methods (complete/stream).\n */\nexport interface TextGenerationOptions {\n  /** Model to use (supports aliases like \"gpt4\", \"sonnet\", \"flash\") */\n  model?: string;\n\n  /** Temperature (0-1) */\n  temperature?: number;\n\n  /** System prompt */\n  systemPrompt?: string;\n\n  /** Max tokens to generate */\n  maxTokens?: number;\n}\n\n/**\n * Quick completion - returns final text response.\n *\n * @param client - LLMist client instance\n * @param prompt - User prompt\n * @param options - Optional configuration\n * @returns Complete text response\n *\n * @example\n * ```typescript\n * const client = new LLMist();\n * const answer = await complete(client, \"What is 2+2?\");\n * console.log(answer); // \"4\" or \"2+2 equals 4\"\n * ```\n */\nexport async function complete(\n  client: LLMist,\n  prompt: string,\n  options: TextGenerationOptions = {},\n): Promise<string> {\n  const model = resolveModel(options.model ?? \"gpt-5-nano\");\n\n  const builder = new LLMMessageBuilder();\n  if (options.systemPrompt) {\n    builder.addSystem(options.systemPrompt);\n  }\n  builder.addUser(prompt);\n\n  let fullResponse = \"\";\n  for await (const chunk of client.stream({\n    model,\n    messages: builder.build(),\n    temperature: options.temperature,\n    maxTokens: options.maxTokens,\n  })) {\n    fullResponse += chunk.text;\n  }\n\n  return fullResponse.trim();\n}\n\n/**\n * Quick streaming - returns async generator of text chunks.\n *\n * @param client - LLMist client instance\n * @param prompt - User prompt\n * @param options - Optional configuration\n * @returns Async generator yielding text chunks\n *\n * @example\n * ```typescript\n * const client = new LLMist();\n *\n * for await (const chunk of stream(client, \"Tell me a story\")) {\n *   process.stdout.write(chunk);\n * }\n * ```\n */\nexport async function* stream(\n  client: LLMist,\n  prompt: string,\n  options: TextGenerationOptions = {},\n): AsyncGenerator<string> {\n  const model = resolveModel(options.model ?? \"gpt-5-nano\");\n\n  const builder = new LLMMessageBuilder();\n  if (options.systemPrompt) {\n    builder.addSystem(options.systemPrompt);\n  }\n  builder.addUser(prompt);\n\n  for await (const chunk of client.stream({\n    model,\n    messages: builder.build(),\n    temperature: options.temperature,\n    maxTokens: options.maxTokens,\n  })) {\n    yield chunk.text;\n  }\n}\n","/**\n * Text Generation Namespace\n *\n * Provides text completion and streaming methods.\n * Replaces the deprecated llmist.complete() and llmist.stream() methods.\n *\n * @example\n * ```typescript\n * const llmist = new LLMist();\n *\n * // Complete\n * const answer = await llmist.text.complete(\"What is 2+2?\");\n *\n * // Stream\n * for await (const chunk of llmist.text.stream(\"Tell me a story\")) {\n *   process.stdout.write(chunk);\n * }\n * ```\n */\n\nimport type { LLMist } from \"../client.js\";\nimport { complete, stream, type TextGenerationOptions } from \"../quick-methods.js\";\n\nexport class TextNamespace {\n  constructor(private readonly client: LLMist) {}\n\n  /**\n   * Generate a complete text response.\n   *\n   * @param prompt - User prompt\n   * @param options - Optional configuration\n   * @returns Complete text response\n   */\n  async complete(prompt: string, options?: TextGenerationOptions): Promise<string> {\n    return complete(this.client, prompt, options);\n  }\n\n  /**\n   * Stream text chunks.\n   *\n   * @param prompt - User prompt\n   * @param options - Optional configuration\n   * @returns Async generator yielding text chunks\n   */\n  stream(prompt: string, options?: TextGenerationOptions): AsyncGenerator<string> {\n    return stream(this.client, prompt, options);\n  }\n}\n","/**\n * Vision Analysis Namespace\n *\n * Provides one-shot image analysis without agent setup.\n * Useful for quick image understanding tasks.\n *\n * @example\n * ```typescript\n * const llmist = new LLMist();\n *\n * const description = await llmist.vision.analyze({\n *   model: \"gpt-4o\",\n *   image: await readFile(\"photo.jpg\"),\n *   prompt: \"Describe this image in detail\",\n * });\n *\n * console.log(description);\n * ```\n */\n\nimport type { LLMist } from \"../client.js\";\nimport type { ImageMimeType } from \"../input-content.js\";\nimport {\n  detectImageMimeType,\n  imageFromBuffer,\n  imageFromUrl,\n  isDataUrl,\n  parseDataUrl,\n  text,\n} from \"../input-content.js\";\nimport { LLMMessageBuilder } from \"../messages.js\";\n\n/**\n * Options for vision analysis.\n */\nexport interface VisionAnalyzeOptions {\n  /** Model to use (must support vision, e.g., \"gpt-4o\", \"claude-sonnet-4-20250514\", \"gemini-2.5-flash\") */\n  model: string;\n\n  /** Image data: Buffer, Uint8Array, base64 string, data URL, or HTTPS URL */\n  image: string | Buffer | Uint8Array;\n\n  /** Analysis prompt describing what to do with the image */\n  prompt: string;\n\n  /** MIME type (auto-detected if not provided for Buffer/Uint8Array) */\n  mimeType?: ImageMimeType;\n\n  /** System prompt for analysis context */\n  systemPrompt?: string;\n\n  /** Max tokens for response */\n  maxTokens?: number;\n\n  /** Temperature (0-1) */\n  temperature?: number;\n}\n\n/**\n * Result of vision analysis.\n */\nexport interface VisionAnalyzeResult {\n  /** The analysis text */\n  text: string;\n\n  /** Model used */\n  model: string;\n\n  /** Token usage if available */\n  usage?: {\n    inputTokens: number;\n    outputTokens: number;\n    totalTokens: number;\n  };\n}\n\nexport class VisionNamespace {\n  constructor(private readonly client: LLMist) {}\n\n  /**\n   * Build a message builder with the image content attached.\n   * Handles URLs, data URLs, base64 strings, and binary buffers.\n   */\n  private buildImageMessage(options: VisionAnalyzeOptions): LLMMessageBuilder {\n    const builder = new LLMMessageBuilder();\n\n    if (options.systemPrompt) {\n      builder.addSystem(options.systemPrompt);\n    }\n\n    // Handle different image source types\n    if (typeof options.image === \"string\") {\n      if (options.image.startsWith(\"http://\") || options.image.startsWith(\"https://\")) {\n        // URL - only supported by OpenAI\n        builder.addUserWithImageUrl(options.prompt, options.image);\n      } else if (isDataUrl(options.image)) {\n        // Data URL - parse and use\n        const parsed = parseDataUrl(options.image);\n        if (!parsed) {\n          throw new Error(\"Invalid data URL format\");\n        }\n        builder.addUserWithImage(options.prompt, parsed.data, parsed.mimeType as ImageMimeType);\n      } else {\n        // Assume base64 string\n        const buffer = Buffer.from(options.image, \"base64\");\n        builder.addUserWithImage(options.prompt, buffer, options.mimeType);\n      }\n    } else {\n      // Buffer or Uint8Array\n      builder.addUserWithImage(options.prompt, options.image, options.mimeType);\n    }\n\n    return builder;\n  }\n\n  /**\n   * Stream the response and collect text and usage information.\n   */\n  private async streamAndCollect(\n    options: VisionAnalyzeOptions,\n    builder: LLMMessageBuilder,\n  ): Promise<{ text: string; usage?: VisionAnalyzeResult[\"usage\"] }> {\n    let response = \"\";\n    let finalUsage: VisionAnalyzeResult[\"usage\"] | undefined;\n\n    for await (const chunk of this.client.stream({\n      model: options.model,\n      messages: builder.build(),\n      maxTokens: options.maxTokens,\n      temperature: options.temperature,\n    })) {\n      response += chunk.text;\n      if (chunk.usage) {\n        finalUsage = {\n          inputTokens: chunk.usage.inputTokens,\n          outputTokens: chunk.usage.outputTokens,\n          totalTokens: chunk.usage.totalTokens,\n        };\n      }\n    }\n\n    return { text: response.trim(), usage: finalUsage };\n  }\n\n  /**\n   * Analyze an image with a vision-capable model.\n   * Returns the analysis as a string.\n   *\n   * @param options - Vision analysis options\n   * @returns Promise resolving to the analysis text\n   * @throws Error if the image format is unsupported or model doesn't support vision\n   *\n   * @example\n   * ```typescript\n   * // From file\n   * const result = await llmist.vision.analyze({\n   *   model: \"gpt-4o\",\n   *   image: await fs.readFile(\"photo.jpg\"),\n   *   prompt: \"What's in this image?\",\n   * });\n   *\n   * // From URL (OpenAI only)\n   * const result = await llmist.vision.analyze({\n   *   model: \"gpt-4o\",\n   *   image: \"https://example.com/image.jpg\",\n   *   prompt: \"Describe this image\",\n   * });\n   * ```\n   */\n  async analyze(options: VisionAnalyzeOptions): Promise<string> {\n    const builder = this.buildImageMessage(options);\n    const { text } = await this.streamAndCollect(options, builder);\n    return text;\n  }\n\n  /**\n   * Analyze an image and return detailed result with usage info.\n   *\n   * @param options - Vision analysis options\n   * @returns Promise resolving to the analysis result with usage info\n   */\n  async analyzeWithUsage(options: VisionAnalyzeOptions): Promise<VisionAnalyzeResult> {\n    const builder = this.buildImageMessage(options);\n    const { text, usage } = await this.streamAndCollect(options, builder);\n\n    return {\n      text,\n      model: options.model,\n      usage,\n    };\n  }\n\n  /**\n   * Check if a model supports vision/image input.\n   *\n   * @param modelId - Model ID to check\n   * @returns True if the model supports vision\n   */\n  supportsModel(modelId: string): boolean {\n    const spec = this.client.modelRegistry.getModelSpec(modelId);\n    return spec?.features?.vision === true;\n  }\n\n  /**\n   * List all models that support vision.\n   *\n   * @returns Array of model IDs that support vision\n   */\n  listModels(): string[] {\n    return this.client.modelRegistry\n      .listModels()\n      .filter((spec) => spec.features?.vision === true)\n      .map((spec) => spec.modelId);\n  }\n}\n","import type { LLMMessage } from \"./messages.js\";\n\n// =============================================================================\n// Reasoning / Thinking Types\n// =============================================================================\n\n/**\n * Provider-agnostic reasoning effort level.\n *\n * Maps to provider-specific values:\n * - **OpenAI**: \"none\"|\"low\"|\"medium\"|\"high\"|\"xhigh\"\n * - **Anthropic**: budget_tokens (1024–32768)\n * - **Gemini 3**: thinkingLevel \"minimal\"|\"low\"|\"medium\"|\"high\"\n * - **Gemini 2.5**: thinkingBudget (0–24576)\n * - **DeepSeek**: binary (enabled/disabled)\n */\nexport type ReasoningEffort = \"none\" | \"low\" | \"medium\" | \"high\" | \"maximum\";\n\n/**\n * Configuration for reasoning/thinking mode on supported models.\n *\n * When `enabled` is true, the provider will be instructed to use\n * extended reasoning before generating its response.\n */\nexport interface ReasoningConfig {\n  /** Whether reasoning is enabled */\n  enabled: boolean;\n  /** Reasoning effort level (default: \"medium\") */\n  effort?: ReasoningEffort;\n  /** Explicit token budget for thinking (Anthropic/Gemini 2.5, overrides effort) */\n  budgetTokens?: number;\n  /** Whether to surface thinking content in the stream (default: true) */\n  includeThinking?: boolean;\n  /** Enable interleaved thinking for multi-turn tool use (Anthropic only) */\n  interleaved?: boolean;\n}\n\n/**\n * A chunk of thinking/reasoning content from a reasoning model.\n *\n * Emitted during streaming when a reasoning model produces thinking output.\n * The `type` field distinguishes actual thinking from redacted content\n * (e.g., Anthropic may redact thinking in certain scenarios).\n */\nexport interface ThinkingChunk {\n  /** The thinking text content */\n  content: string;\n  /** Whether this is actual thinking or redacted content */\n  type: \"thinking\" | \"redacted\";\n  /** Verification signature (Anthropic/Gemini) */\n  signature?: string;\n}\n\n// =============================================================================\n// Context Caching Types\n// =============================================================================\n\n/**\n * What content to include in the cache.\n *\n * - `\"system\"`: Cache only system prompt (lowest cost, highest reuse)\n * - `\"conversation\"`: Cache system prompt + all conversation turns except the latest user message\n */\nexport type CachingScope = \"system\" | \"conversation\";\n\n/**\n * Configuration for context caching across providers.\n *\n * Context caching allows reusing previously computed key-value pairs across\n * requests, reducing latency and cost for repeated context.\n *\n * Provider behavior:\n * - **Anthropic**: Automatic ephemeral caching via `cache_control` markers (always-on by default).\n *   Use `enabled: false` to disable markers and opt out of caching.\n * - **Gemini**: Explicit cache lifecycle via `caches.create()`. Requires `scope` and `ttl`.\n * - **OpenAI**: Server-side automatic caching (no-op, but respects the unified API).\n */\nexport interface CachingConfig {\n  /** Whether context caching is enabled */\n  enabled: boolean;\n  /**\n   * What to cache (Gemini only, default: \"conversation\").\n   * - `\"system\"`: Cache only system-derived messages\n   * - `\"conversation\"`: Cache system + all turns except the latest user message\n   */\n  scope?: CachingScope;\n  /** TTL for cache entries (Gemini only, format: \"3600s\", default: \"3600s\", min: \"300s\") */\n  ttl?: string;\n  /** Minimum token count for content to be eligible for caching (Gemini default: 32768) */\n  minTokenThreshold?: number;\n}\n\nexport interface LLMGenerationOptions {\n  model: string;\n  messages: LLMMessage[];\n  maxTokens?: number;\n  temperature?: number;\n  topP?: number;\n  stopSequences?: string[];\n  responseFormat?: \"text\";\n  metadata?: Record<string, unknown>;\n  extra?: Record<string, unknown>;\n  /**\n   * Optional abort signal for cancelling the request mid-flight.\n   *\n   * When the signal is aborted, the provider will attempt to cancel\n   * the underlying HTTP request and the stream will terminate with\n   * an abort error. Use `isAbortError()` from `@/core/errors` to\n   * detect cancellation in error handling.\n   *\n   * @example\n   * ```typescript\n   * const controller = new AbortController();\n   *\n   * const stream = client.stream({\n   *   model: \"claude-3-5-sonnet-20241022\",\n   *   messages: [{ role: \"user\", content: \"Tell me a long story\" }],\n   *   signal: controller.signal,\n   * });\n   *\n   * // Cancel after 5 seconds\n   * setTimeout(() => controller.abort(), 5000);\n   *\n   * try {\n   *   for await (const chunk of stream) {\n   *     process.stdout.write(chunk.text);\n   *   }\n   * } catch (error) {\n   *   if (isAbortError(error)) {\n   *     console.log(\"\\nRequest was cancelled\");\n   *   } else {\n   *     throw error;\n   *   }\n   * }\n   * ```\n   */\n  signal?: AbortSignal;\n  /** Reasoning/thinking configuration for reasoning-capable models */\n  reasoning?: ReasoningConfig;\n  /** Context caching configuration for supported providers */\n  caching?: CachingConfig;\n}\n\nexport interface TokenUsage {\n  inputTokens: number;\n  outputTokens: number;\n  totalTokens: number;\n  /** Number of input tokens served from cache (subset of inputTokens) */\n  cachedInputTokens?: number;\n  /** Number of input tokens written to cache (subset of inputTokens, Anthropic only) */\n  cacheCreationInputTokens?: number;\n  /** Number of reasoning/thinking tokens used (subset of outputTokens) */\n  reasoningTokens?: number;\n}\n\nexport interface LLMStreamChunk {\n  text: string;\n  /**\n   * Indicates that the provider has finished producing output and includes the reason if available.\n   */\n  finishReason?: string | null;\n  /**\n   * Token usage information, typically available in the final chunk when the stream completes.\n   */\n  usage?: TokenUsage;\n  /**\n   * Provider specific payload emitted at the same time as the text chunk. This is useful for debugging and tests.\n   */\n  rawEvent?: unknown;\n  /** Thinking/reasoning content from reasoning models */\n  thinking?: ThinkingChunk;\n}\n\nexport interface LLMStream extends AsyncIterable<LLMStreamChunk> {}\n\nexport type ProviderIdentifier = string;\n\nexport interface ModelDescriptor {\n  provider: string;\n  name: string;\n}\n\nexport class ModelIdentifierParser {\n  constructor(private readonly defaultProvider: string = \"openai\") {}\n\n  parse(identifier: string): ModelDescriptor {\n    const trimmed = identifier.trim();\n    if (!trimmed) {\n      throw new Error(\"Model identifier cannot be empty\");\n    }\n\n    const [maybeProvider, ...rest] = trimmed.split(\":\");\n    if (rest.length === 0) {\n      return { provider: this.defaultProvider, name: maybeProvider };\n    }\n\n    const provider = maybeProvider;\n    const name = rest.join(\":\");\n    if (!name) {\n      throw new Error(\"Model name cannot be empty\");\n    }\n\n    return { provider, name };\n  }\n}\n","import { AgentBuilder } from \"../agent/builder.js\";\nimport { discoverProviderAdapters } from \"../providers/discovery.js\";\nimport type { ProviderAdapter } from \"../providers/provider.js\";\nimport { ResearchNamespace } from \"../research/namespace.js\";\nimport { CHARS_PER_TOKEN } from \"./constants.js\";\nimport type { LLMMessage } from \"./messages.js\";\nimport type { ModelSpec } from \"./model-catalog.js\";\nimport { ModelRegistry } from \"./model-registry.js\";\nimport { ImageNamespace } from \"./namespaces/image.js\";\nimport { SpeechNamespace } from \"./namespaces/speech.js\";\nimport { TextNamespace } from \"./namespaces/text.js\";\nimport { VisionNamespace } from \"./namespaces/vision.js\";\nimport type { LLMGenerationOptions, LLMStream, ModelDescriptor } from \"./options.js\";\nimport { ModelIdentifierParser } from \"./options.js\";\nimport {\n  complete as completeHelper,\n  stream as streamHelper,\n  type TextGenerationOptions,\n} from \"./quick-methods.js\";\n\nexport interface LLMistOptions {\n  /**\n   * Provider adapters to register manually.\n   */\n  adapters?: ProviderAdapter[];\n  /**\n   * Default provider prefix applied when a model identifier omits it.\n   */\n  defaultProvider?: string;\n  /**\n   * Automatically discover built-in providers based on environment configuration.\n   * Enabled by default.\n   */\n  autoDiscoverProviders?: boolean;\n  /**\n   * Custom model specifications to register at initialization.\n   * Use this to define models not in the built-in catalog, such as:\n   * - Fine-tuned models with custom pricing\n   * - New models not yet supported by llmist\n   * - Custom deployments with different configurations\n   *\n   * @example\n   * ```ts\n   * new LLMist({\n   *   customModels: [{\n   *     provider: \"openai\",\n   *     modelId: \"ft:gpt-4o-2024-08-06:my-org:custom:abc123\",\n   *     displayName: \"My Fine-tuned GPT-4o\",\n   *     contextWindow: 128_000,\n   *     maxOutputTokens: 16_384,\n   *     pricing: { input: 7.5, output: 30.0 },\n   *     knowledgeCutoff: \"2024-08\",\n   *     features: { streaming: true, functionCalling: true, vision: true }\n   *   }]\n   * });\n   * ```\n   */\n  customModels?: ModelSpec[];\n}\n\nexport class LLMist {\n  private readonly parser: ModelIdentifierParser;\n  private readonly defaultProvider: string;\n  readonly modelRegistry: ModelRegistry;\n  private readonly adapters: ProviderAdapter[];\n\n  // Namespaces for different generation types\n  readonly text: TextNamespace;\n  readonly image: ImageNamespace;\n  readonly speech: SpeechNamespace;\n  readonly vision: VisionNamespace;\n  /**\n   * Deep research — long-running, server-side research jobs with cited\n   * reports (OpenAI Responses, Gemini Interactions, OpenRouter research\n   * models). See docs/specs/002-deep-research.md.\n   */\n  readonly research: ResearchNamespace;\n\n  constructor();\n  constructor(adapters: ProviderAdapter[]);\n  constructor(adapters: ProviderAdapter[], defaultProvider: string);\n  constructor(options: LLMistOptions);\n  constructor(...args: [] | [ProviderAdapter[]] | [ProviderAdapter[], string] | [LLMistOptions]) {\n    let adapters: ProviderAdapter[] = [];\n    let defaultProvider: string | undefined;\n    let autoDiscoverProviders = true;\n    let customModels: ModelSpec[] = [];\n\n    if (args.length === 0) {\n      // Use defaults\n    } else if (Array.isArray(args[0])) {\n      adapters = args[0];\n      if (args.length > 1) {\n        defaultProvider = args[1];\n      }\n    } else if (typeof args[0] === \"object\" && args[0] !== null) {\n      const options = args[0];\n      adapters = options.adapters ?? [];\n      defaultProvider = options.defaultProvider;\n      customModels = options.customModels ?? [];\n      if (typeof options.autoDiscoverProviders === \"boolean\") {\n        autoDiscoverProviders = options.autoDiscoverProviders;\n      }\n    }\n\n    const discoveredAdapters = autoDiscoverProviders ? discoverProviderAdapters() : [];\n    const combinedAdapters: ProviderAdapter[] = [...adapters];\n    for (const adapter of discoveredAdapters) {\n      if (!combinedAdapters.some((existing) => existing.providerId === adapter.providerId)) {\n        combinedAdapters.push(adapter);\n      }\n    }\n\n    if (combinedAdapters.length === 0) {\n      throw new Error(\n        \"No LLM providers available. Provide adapters explicitly or set provider API keys in the environment.\",\n      );\n    }\n\n    const resolvedDefaultProvider = defaultProvider ?? combinedAdapters[0]?.providerId ?? \"openai\";\n\n    // Sort by priority (descending: higher priority first)\n    // Use stable sort to preserve order for equal priorities\n    this.adapters = [...combinedAdapters].sort((a, b) => {\n      const priorityA = a.priority ?? 0;\n      const priorityB = b.priority ?? 0;\n      return priorityB - priorityA;\n    });\n    this.defaultProvider = resolvedDefaultProvider;\n    this.parser = new ModelIdentifierParser(resolvedDefaultProvider);\n    this.modelRegistry = new ModelRegistry();\n\n    // Register all providers with the model registry\n    for (const adapter of this.adapters) {\n      this.modelRegistry.registerProvider(adapter);\n    }\n\n    // Register custom models if provided\n    if (customModels.length > 0) {\n      this.modelRegistry.registerModels(customModels);\n    }\n\n    // Initialize generation namespaces\n    this.text = new TextNamespace(this);\n    this.image = new ImageNamespace(this.adapters, this.defaultProvider);\n    this.speech = new SpeechNamespace(this.adapters, this.defaultProvider);\n    this.vision = new VisionNamespace(this);\n    this.research = new ResearchNamespace(this.adapters, this.parser);\n  }\n\n  stream(options: LLMGenerationOptions): LLMStream {\n    const descriptor = this.parser.parse(options.model);\n    const spec = this.modelRegistry.getModelSpec(descriptor.name);\n    const adapter = this.resolveAdapter(descriptor);\n\n    // Apply global default temperature of 0 (deterministic) when not specified\n    const optionsWithDefaults: LLMGenerationOptions = {\n      ...options,\n      temperature: options.temperature ?? 0,\n    };\n\n    return adapter.stream(optionsWithDefaults, descriptor, spec);\n  }\n\n  /**\n   * Count tokens in messages for a given model.\n   *\n   * Uses provider-specific token counting methods for accurate estimation:\n   * - OpenAI: tiktoken library with model-specific encodings\n   * - Anthropic: Native messages.countTokens() API\n   * - Gemini: SDK's countTokens() method\n   *\n   * Falls back to character-based estimation (4 chars/token) if the provider\n   * doesn't support native token counting or if counting fails.\n   *\n   * This is useful for:\n   * - Pre-request cost estimation\n   * - Context window management\n   * - Request batching optimization\n   *\n   * @param model - Model identifier (e.g., \"openai:gpt-4\", \"anthropic:claude-3-5-sonnet-20241022\")\n   * @param messages - Array of messages to count tokens for\n   * @returns Promise resolving to the estimated input token count\n   *\n   * @example\n   * ```typescript\n   * const client = new LLMist();\n   * const messages = [\n   *   { role: 'system', content: 'You are a helpful assistant.' },\n   *   { role: 'user', content: 'Hello!' }\n   * ];\n   *\n   * const tokenCount = await client.countTokens('openai:gpt-4', messages);\n   * console.log(`Estimated tokens: ${tokenCount}`);\n   * ```\n   */\n  async countTokens(model: string, messages: LLMMessage[]): Promise<number> {\n    const descriptor = this.parser.parse(model);\n    const spec = this.modelRegistry.getModelSpec(descriptor.name);\n    const adapter = this.resolveAdapter(descriptor);\n\n    // Check if the provider supports token counting\n    if (adapter.countTokens) {\n      return adapter.countTokens(messages, descriptor, spec);\n    }\n\n    // Fallback: use tiktoken o200k_base for approximate counting\n    try {\n      const { get_encoding } = await import(\"tiktoken\");\n      const encoding = get_encoding(\"o200k_base\");\n      try {\n        let tokenCount = 0;\n        for (const msg of messages) {\n          const content = msg.content;\n          if (typeof content === \"string\") {\n            tokenCount += encoding.encode(content).length;\n          } else if (Array.isArray(content)) {\n            for (const part of content) {\n              if (part.type === \"text\") {\n                tokenCount += encoding.encode(part.text).length;\n              }\n            }\n          }\n        }\n        return tokenCount;\n      } finally {\n        encoding.free();\n      }\n    } catch {\n      // Ultimate fallback if tiktoken isn't available: extract text and estimate\n      let totalChars = 0;\n      for (const msg of messages) {\n        const content = msg.content;\n        if (typeof content === \"string\") {\n          totalChars += content.length;\n        } else if (Array.isArray(content)) {\n          for (const part of content) {\n            if (part.type === \"text\") {\n              totalChars += part.text.length;\n            }\n          }\n        }\n      }\n      return Math.ceil(totalChars / CHARS_PER_TOKEN);\n    }\n  }\n\n  private resolveAdapter(descriptor: ModelDescriptor): ProviderAdapter {\n    const adapter = this.adapters.find((item) => item.supports(descriptor));\n    if (!adapter) {\n      throw new Error(`No adapter registered for provider ${descriptor.provider}`);\n    }\n\n    return adapter;\n  }\n\n  /**\n   * Quick completion - returns final text response.\n   * Convenient for simple queries without needing agent setup.\n   *\n   * @param prompt - User prompt\n   * @param options - Optional configuration\n   * @returns Complete text response\n   *\n   * @example\n   * ```typescript\n   * const answer = await LLMist.complete(\"What is 2+2?\");\n   * console.log(answer); // \"4\" or \"2+2 equals 4\"\n   *\n   * const answer = await LLMist.complete(\"Tell me a joke\", {\n   *   model: \"sonnet\",\n   *   temperature: 0.9\n   * });\n   * ```\n   */\n  static async complete(prompt: string, options?: TextGenerationOptions): Promise<string> {\n    const client = new LLMist();\n    return completeHelper(client, prompt, options);\n  }\n\n  /**\n   * Quick streaming - returns async generator of text chunks.\n   * Convenient for streaming responses without needing agent setup.\n   *\n   * @param prompt - User prompt\n   * @param options - Optional configuration\n   * @returns Async generator yielding text chunks\n   *\n   * @example\n   * ```typescript\n   * for await (const chunk of LLMist.stream(\"Tell me a story\")) {\n   *   process.stdout.write(chunk);\n   * }\n   *\n   * // With options\n   * for await (const chunk of LLMist.stream(\"Generate code\", {\n   *   model: \"gpt4\",\n   *   systemPrompt: \"You are a coding assistant\"\n   * })) {\n   *   process.stdout.write(chunk);\n   * }\n   * ```\n   */\n  static stream(prompt: string, options?: TextGenerationOptions): AsyncGenerator<string> {\n    const client = new LLMist();\n    return streamHelper(client, prompt, options);\n  }\n\n  /**\n   * Instance method: Quick completion using this client instance.\n   *\n   * @param prompt - User prompt\n   * @param options - Optional configuration\n   * @returns Complete text response\n   */\n  async complete(prompt: string, options?: TextGenerationOptions): Promise<string> {\n    return completeHelper(this, prompt, options);\n  }\n\n  /**\n   * Instance method: Quick streaming using this client instance.\n   *\n   * @param prompt - User prompt\n   * @param options - Optional configuration\n   * @returns Async generator yielding text chunks\n   */\n  streamText(prompt: string, options?: TextGenerationOptions): AsyncGenerator<string> {\n    return streamHelper(this, prompt, options);\n  }\n\n  /**\n   * Create a fluent agent builder.\n   * Provides a chainable API for configuring and creating agents.\n   *\n   * @returns AgentBuilder instance for chaining\n   *\n   * @example\n   * ```typescript\n   * const agent = LLMist.createAgent()\n   *   .withModel(\"sonnet\")\n   *   .withSystem(\"You are a helpful assistant\")\n   *   .withGadgets(Calculator, Weather)\n   *   .ask(\"What's the weather in Paris?\");\n   *\n   * for await (const event of agent.run()) {\n   *   // handle events\n   * }\n   * ```\n   *\n   * @example\n   * ```typescript\n   * // Quick one-liner for simple queries\n   * const answer = await LLMist.createAgent()\n   *   .withModel(\"gpt4-mini\")\n   *   .askAndCollect(\"What is 2+2?\");\n   * ```\n   */\n  static createAgent(): AgentBuilder {\n    return new AgentBuilder();\n  }\n\n  /**\n   * Create agent builder with this client instance.\n   * Useful when you want to reuse a configured client.\n   *\n   * @returns AgentBuilder instance using this client\n   *\n   * @example\n   * ```typescript\n   * const client = new LLMist({ ... });\n   *\n   * const agent = client.createAgent()\n   *   .withModel(\"sonnet\")\n   *   .ask(\"Hello\");\n   * ```\n   */\n  createAgent(): AgentBuilder {\n    return new AgentBuilder(this);\n  }\n}\n","/**\n * Fluent builder for creating agents with delightful DX.\n */\n\nimport type { ILogObj, Logger } from \"tslog\";\nimport type { LLMist } from \"../core/client.js\";\nimport type { ContentPart, ImageMimeType } from \"../core/input-content.js\";\nimport { resolveModel } from \"../core/model-shortcuts.js\";\nimport type { CachingConfig, ReasoningConfig, ReasoningEffort } from \"../core/options.js\";\nimport type { PromptTemplateConfig } from \"../core/prompt-config.js\";\nimport type { RateLimitConfig } from \"../core/rate-limit.js\";\nimport type { RetryConfig } from \"../core/retry.js\";\nimport type { GadgetOrClass } from \"../gadgets/registry.js\";\nimport { GadgetRegistry } from \"../gadgets/registry.js\";\nimport type {\n  ExecutionContext,\n  GadgetExecutionMode,\n  SubagentConfigMap,\n  TextOnlyHandler,\n} from \"../gadgets/types.js\";\nimport { resolveInstructions } from \"../skills/activation.js\";\nimport { createLoadSkillGadget } from \"../skills/load-skill-gadget.js\";\nimport { loadSkillsFromDirectory } from \"../skills/loader.js\";\nimport { parseFrontmatter } from \"../skills/parser.js\";\nimport type { SkillRegistry } from \"../skills/registry.js\";\nimport { Agent, type AgentOptions } from \"./agent.js\";\nimport { AGENT_INTERNAL_KEY } from \"./agent-internal-key.js\";\nimport type {\n  CoreState,\n  GadgetState,\n  HistoryMessage,\n  McpState,\n  PolicyState,\n  RetryState,\n  SkillState,\n  SubagentState,\n} from \"./builder-types.js\";\nimport {\n  buildMultimodalContent,\n  extractMessagesFromAgent,\n  formatGadgetCall,\n  normalizeHistory,\n} from \"./builder-utils.js\";\nimport type { CompactionConfig } from \"./compaction/config.js\";\nimport { collectText, type EventHandlers } from \"./event-handlers.js\";\nimport { HookComposer, type TrailingMessage } from \"./hook-composer.js\";\nimport type { AgentHooks } from \"./hooks.js\";\n\nexport type { HistoryMessage } from \"./builder-types.js\";\n\n/**\n * Fluent builder for creating agents.\n *\n * Provides a chainable API for configuring and creating agents,\n * making the code more expressive and easier to read.\n */\nexport class AgentBuilder {\n  private core: CoreState;\n  private gadgets: GadgetState;\n  private retry: RetryState;\n  private subagents: SubagentState;\n  private policies: PolicyState;\n  private skills: SkillState;\n  private mcp: McpState;\n\n  constructor(client?: LLMist) {\n    this.core = { client, initialMessages: [] };\n    this.gadgets = { gadgets: [] };\n    this.retry = {};\n    this.subagents = {};\n    this.policies = {};\n    this.skills = { preActivated: [], skillDirs: [] };\n    this.mcp = { servers: [] };\n  }\n\n  /** Set the model to use. Supports aliases like \"sonnet\", \"flash\". */\n  withModel(model: string): this {\n    this.core.model = resolveModel(model);\n    return this;\n  }\n\n  /** Set the system prompt. */\n  withSystem(prompt: string): this {\n    this.core.systemPrompt = prompt;\n    return this;\n  }\n\n  /** Set the temperature (0-1). */\n  withTemperature(temperature: number): this {\n    this.core.temperature = temperature;\n    return this;\n  }\n\n  /** Set maximum iterations. */\n  withMaxIterations(max: number): this {\n    this.core.maxIterations = max;\n    return this;\n  }\n\n  /** Set the budget limit in USD. */\n  withBudget(amountUSD: number): this {\n    this.core.budget = amountUSD;\n    return this;\n  }\n\n  /** Set logger instance. */\n  withLogger(logger: Logger<ILogObj>): this {\n    this.core.logger = logger;\n    return this;\n  }\n\n  /** Add hooks for agent lifecycle events. */\n  withHooks(hooks: AgentHooks): this {\n    this.core.hooks = hooks;\n    return this;\n  }\n\n  /** Configure custom prompts for gadget system messages. */\n  withPromptTemplateConfig(config: PromptTemplateConfig): this {\n    this.core.promptConfig = config;\n    return this;\n  }\n\n  /** Add gadgets (classes or instances). */\n  withGadgets(...gadgets: GadgetOrClass[]): this {\n    this.gadgets.gadgets.push(...gadgets);\n    return this;\n  }\n\n  /**\n   * Attach a Model Context Protocol (MCP) server.\n   *\n   * The agent connects to the server lazily at the start of `run()`,\n   * discovers its tools, and registers them as native gadgets so the LLM\n   * can call them through the standard streaming block format.\n   *\n   * Calling this multiple times accumulates servers. Tools across servers\n   * are merged into a single registry; in plan 1, conflicting tool names\n   * raise a registration warning. Plan 2 introduces deterministic\n   * `<server>__<tool>` prefixing for collisions.\n   *\n   * STDIO commands are gated by an allowlist (see allowlist.ts) — pass\n   * `trust: true` on the spec to opt in for non-allowlisted binaries.\n   *\n   * Zero-overhead invariant: if you never call this method, the MCP\n   * runtime module is never loaded. Agents without MCP pay nothing.\n   *\n   * @example\n   * ```typescript\n   * const agent = LLMist.createAgent()\n   *   .withModel(\"sonnet\")\n   *   .withMcpServer({\n   *     name: \"filesystem\",\n   *     transport: \"stdio\",\n   *     command: \"npx\",\n   *     args: [\"-y\", \"@modelcontextprotocol/server-filesystem\", \"/tmp\"],\n   *   })\n   *   .ask(\"list files in /tmp\");\n   * ```\n   */\n  withMcpServer(spec: import(\"../mcp/types.js\").McpServerSpec): this {\n    this.mcp.servers.push(spec);\n    return this;\n  }\n\n  /** Inspect the configured MCP server specs. Useful for tests. */\n  getMcpServerSpecs(): readonly import(\"../mcp/types.js\").McpServerSpec[] {\n    return this.mcp.servers;\n  }\n\n  /** Add conversation history messages. */\n  withHistory(messages: HistoryMessage[]): this {\n    this.core.initialMessages.push(...normalizeHistory(messages));\n    return this;\n  }\n\n  /** Add a single message to the conversation history. */\n  addMessage(message: HistoryMessage): this {\n    return this.withHistory([message]);\n  }\n\n  /** Clear any previously set conversation history. */\n  clearHistory(): this {\n    this.core.initialMessages = [];\n    return this;\n  }\n\n  /** Continue conversation from a previous agent's history. */\n  continueFrom(agent: Agent): this {\n    this.clearHistory();\n    this.core.initialMessages.push(...extractMessagesFromAgent(agent));\n    return this;\n  }\n\n  /** Set the human input handler for interactive conversations. */\n  onHumanInput(handler: (question: string) => Promise<string>): this {\n    this.core.requestHumanInput = handler;\n    return this;\n  }\n\n  /** Set custom gadget marker prefix. */\n  withGadgetStartPrefix(prefix: string): this {\n    this.gadgets.gadgetStartPrefix = prefix;\n    return this;\n  }\n\n  /** Set custom gadget marker suffix. */\n  withGadgetEndPrefix(suffix: string): this {\n    this.gadgets.gadgetEndPrefix = suffix;\n    return this;\n  }\n\n  /** Set custom argument prefix for block format parameters. */\n  withGadgetArgPrefix(prefix: string): this {\n    this.gadgets.gadgetArgPrefix = prefix;\n    return this;\n  }\n\n  /** Set the text-only handler strategy. */\n  withTextOnlyHandler(handler: TextOnlyHandler): this {\n    this.gadgets.textOnlyHandler = handler;\n    return this;\n  }\n\n  /** Set the handler for text content that appears alongside gadget calls. */\n  withTextWithGadgetsHandler(handler: {\n    gadgetName: string;\n    parameterMapping: (text: string) => Record<string, unknown>;\n    resultMapping?: (text: string) => string;\n  }): this {\n    this.gadgets.textWithGadgetsHandler = handler;\n    return this;\n  }\n\n  /** Set default timeout for gadget execution. */\n  withDefaultGadgetTimeout(timeoutMs: number): this {\n    if (timeoutMs < 0) throw new Error(\"Timeout must be a non-negative number\");\n    this.gadgets.defaultGadgetTimeoutMs = timeoutMs;\n    return this;\n  }\n\n  /** Set the gadget execution mode ('parallel' or 'sequential'). */\n  withGadgetExecutionMode(mode: GadgetExecutionMode): this {\n    this.gadgets.gadgetExecutionMode = mode;\n    return this;\n  }\n\n  /** Set the maximum number of gadgets to execute per LLM response. */\n  withMaxGadgetsPerResponse(max: number): this {\n    if (max < 0) throw new Error(\"maxGadgetsPerResponse must be a non-negative number\");\n    if (!Number.isInteger(max)) throw new Error(\"maxGadgetsPerResponse must be an integer\");\n    this.gadgets.maxGadgetsPerResponse = max;\n    return this;\n  }\n\n  /** Enable or disable gadget output limiting. */\n  withGadgetOutputLimit(enabled: boolean): this {\n    this.gadgets.gadgetOutputLimit = enabled;\n    return this;\n  }\n\n  /** Set the maximum gadget output as a percentage of the context window. */\n  withGadgetOutputLimitPercent(percent: number): this {\n    if (percent < 1 || percent > 100)\n      throw new Error(\"Output limit percent must be between 1 and 100\");\n    this.gadgets.gadgetOutputLimitPercent = percent;\n    return this;\n  }\n\n  /** Configure context compaction. */\n  withCompaction(config: CompactionConfig): this {\n    this.policies.compactionConfig = { ...config, enabled: config.enabled ?? true };\n    return this;\n  }\n\n  /** Disable context compaction. */\n  withoutCompaction(): this {\n    this.policies.compactionConfig = { enabled: false };\n    return this;\n  }\n\n  // ─── Skills ──────────────────────────────────────────────────────────────────\n\n  /** Register a skill registry for this agent. */\n  withSkills(registry: SkillRegistry): this {\n    this.skills.registry = registry;\n    return this;\n  }\n\n  /**\n   * Pre-activate a specific skill before the agent starts.\n   * Instructions are injected into the system prompt.\n   *\n   * Note: each call replaces (not appends) the pre-activated skill for that name.\n   * This is safe for REPL loops where the same builder is reused.\n   */\n  withSkill(name: string, args?: string): this {\n    // Deduplicate: replace existing entry for same skill name\n    const existing = this.skills.preActivated.findIndex((s) => s.name === name);\n    if (existing !== -1) {\n      this.skills.preActivated[existing] = { name, args };\n    } else {\n      this.skills.preActivated.push({ name, args });\n    }\n    return this;\n  }\n\n  /** Clear all pre-activated skills. Call between REPL iterations. */\n  clearPreActivatedSkills(): this {\n    this.skills.preActivated = [];\n    return this;\n  }\n\n  /** Add a directory to scan for skills. */\n  withSkillsFrom(dir: string): this {\n    this.skills.skillDirs.push(dir);\n    return this;\n  }\n\n  /** Configure retry behavior for LLM API calls. */\n  withRetry(config: RetryConfig): this {\n    this.retry.retryConfig = { ...config, enabled: config.enabled ?? true };\n    return this;\n  }\n\n  /** Disable automatic retry for LLM API calls. */\n  withoutRetry(): this {\n    this.retry.retryConfig = { enabled: false };\n    return this;\n  }\n\n  /** Configure proactive rate limiting to prevent rate limit errors. */\n  withRateLimits(config: RateLimitConfig): this {\n    this.subagents.rateLimitConfig = config;\n    return this;\n  }\n\n  /** Set an abort signal for cancelling requests mid-flight. */\n  withSignal(signal: AbortSignal): this {\n    this.core.signal = signal;\n    return this;\n  }\n\n  /** Enable reasoning/thinking mode for reasoning-capable models. */\n  withReasoning(config?: ReasoningConfig | ReasoningEffort): this {\n    if (typeof config === \"string\") {\n      this.core.reasoningConfig = { enabled: true, effort: config };\n    } else if (config === undefined) {\n      this.core.reasoningConfig = { enabled: true, effort: \"medium\" };\n    } else {\n      this.core.reasoningConfig = config;\n    }\n    return this;\n  }\n\n  /** Explicitly disable reasoning for this agent. */\n  withoutReasoning(): this {\n    this.core.reasoningConfig = { enabled: false };\n    return this;\n  }\n\n  /** Enable context caching for supported providers. */\n  withCaching(config?: CachingConfig): this {\n    this.core.cachingConfig = config ?? { enabled: true };\n    return this;\n  }\n\n  /** Explicitly disable context caching. */\n  withoutCaching(): this {\n    this.core.cachingConfig = { enabled: false };\n    return this;\n  }\n\n  /** Set subagent configuration overrides. */\n  withSubagentConfig(config: SubagentConfigMap): this {\n    this.subagents.subagentConfig = config;\n    return this;\n  }\n\n  /** Share parent agent's ExecutionTree for unified event visibility. */\n  withParentContext(ctx: ExecutionContext, depth = 1): this {\n    if (ctx.tree) {\n      this.subagents.parentContext = { tree: ctx.tree, nodeId: ctx.nodeId, depth };\n    }\n    if (ctx.signal && !this.core.signal) this.core.signal = ctx.signal;\n    if (ctx.logger && !this.core.logger) this.core.logger = ctx.logger;\n    if (ctx.parentObservers && !this.subagents.parentObservers) {\n      this.subagents.parentObservers = ctx.parentObservers;\n    }\n    if (ctx.rateLimitTracker && !this.subagents.sharedRateLimitTracker) {\n      this.subagents.sharedRateLimitTracker = ctx.rateLimitTracker;\n    }\n    if (ctx.retryConfig && !this.retry.sharedRetryConfig) {\n      this.retry.sharedRetryConfig = ctx.retryConfig;\n    }\n    return this;\n  }\n\n  /** Add an ephemeral trailing message that appears at the end of each LLM request. */\n  withTrailingMessage(message: TrailingMessage): this {\n    this.core.trailingMessage = message;\n    return this;\n  }\n\n  /** Add a synthetic gadget call to the conversation history for in-context learning. */\n  withSyntheticGadgetCall(\n    gadgetName: string,\n    parameters: Record<string, unknown>,\n    result: string,\n    invocationId: string,\n  ): this {\n    const content = formatGadgetCall(gadgetName, invocationId, parameters, {\n      start: this.gadgets.gadgetStartPrefix,\n      end: this.gadgets.gadgetEndPrefix,\n      arg: this.gadgets.gadgetArgPrefix,\n    });\n\n    this.core.initialMessages.push({ role: \"assistant\", content });\n    this.core.initialMessages.push({\n      role: \"user\",\n      content: `Result (${invocationId}): ${result}`,\n    });\n    return this;\n  }\n\n  private composeHooks(): AgentHooks | undefined {\n    return HookComposer.compose(this.core.hooks, this.core.trailingMessage);\n  }\n\n  private resolveSkillRegistry(): SkillRegistry | undefined {\n    if (this.skills.registry) {\n      if (this.skills.skillDirs.length > 0) {\n        for (const dir of this.skills.skillDirs) {\n          const skills = loadSkillsFromDirectory(dir, { type: \"directory\", path: dir });\n          this.skills.registry.registerMany(skills);\n        }\n      }\n      return this.skills.registry;\n    }\n\n    if (this.skills.skillDirs.length > 0) {\n      const { SkillRegistry: SR } = require(\"../skills/registry.js\");\n      const reg = new SR();\n      for (const dir of this.skills.skillDirs) {\n        const skills = loadSkillsFromDirectory(dir, { type: \"directory\", path: dir });\n        reg.registerMany(skills);\n      }\n      return reg;\n    }\n\n    return undefined;\n  }\n\n  /**\n   * Resolve pre-activated skill instructions synchronously.\n   * Reads SKILL.md from disk via readFileSync (skills are local files).\n   */\n  private resolvePreActivatedInstructions(skillRegistry: SkillRegistry): string | undefined {\n    if (this.skills.preActivated.length === 0) return undefined;\n\n    const fs = require(\"node:fs\");\n    const blocks: string[] = [];\n    for (const { name, args } of this.skills.preActivated) {\n      const skill = skillRegistry.get(name);\n      if (!skill) continue;\n      const content = fs.readFileSync(skill.sourcePath, \"utf-8\");\n      const { body } = parseFrontmatter(content);\n      const resolved = resolveInstructions(body, {\n        arguments: args,\n        variables: { SKILL_DIR: skill.sourceDir, CLAUDE_SKILL_DIR: skill.sourceDir },\n        cwd: skill.sourceDir,\n        shell: skill.metadata.shell,\n      });\n      blocks.push(`## Skill: ${name}\\n\\n${resolved}`);\n    }\n    return blocks.length > 0 ? blocks.join(\"\\n\\n---\\n\\n\") : undefined;\n  }\n\n  private buildAgentOptions(userPrompt?: string | ContentPart[]): AgentOptions {\n    if (!this.core.client) {\n      const { LLMist: LLMistClass } = require(\"../core/client.js\");\n      this.core.client = new LLMistClass();\n    }\n\n    const registry = GadgetRegistry.from(this.gadgets.gadgets);\n\n    // ─── Skills integration ────────────────────────────────────────────────\n    let systemPrompt = this.core.systemPrompt;\n    const skillRegistry = this.resolveSkillRegistry();\n\n    if (skillRegistry && skillRegistry.size > 0) {\n      if (skillRegistry.getModelInvocable().length > 0) {\n        registry.registerByClass(createLoadSkillGadget(skillRegistry));\n      }\n\n      const preActivatedBlock = this.resolvePreActivatedInstructions(skillRegistry);\n      if (preActivatedBlock) {\n        systemPrompt = systemPrompt ? `${systemPrompt}\\n\\n${preActivatedBlock}` : preActivatedBlock;\n      }\n    }\n\n    return {\n      client: this.core.client as LLMist,\n      model: this.core.model ?? \"openai:gpt-5-nano\",\n      systemPrompt,\n      userPrompt,\n      registry,\n      maxIterations: this.core.maxIterations,\n      budget: this.core.budget,\n      temperature: this.core.temperature,\n      logger: this.core.logger,\n      hooks: this.composeHooks(),\n      promptConfig: this.core.promptConfig,\n      initialMessages: this.core.initialMessages,\n      requestHumanInput: this.core.requestHumanInput,\n      prefixConfig: {\n        gadgetStartPrefix: this.gadgets.gadgetStartPrefix,\n        gadgetEndPrefix: this.gadgets.gadgetEndPrefix,\n        gadgetArgPrefix: this.gadgets.gadgetArgPrefix,\n      },\n      textOnlyHandler: this.gadgets.textOnlyHandler,\n      textWithGadgetsHandler: this.gadgets.textWithGadgetsHandler,\n      defaultGadgetTimeoutMs: this.gadgets.defaultGadgetTimeoutMs,\n      gadgetExecutionMode: this.gadgets.gadgetExecutionMode,\n      maxGadgetsPerResponse: this.gadgets.maxGadgetsPerResponse,\n      outputLimitConfig: {\n        enabled: this.gadgets.gadgetOutputLimit,\n        limitPercent: this.gadgets.gadgetOutputLimitPercent,\n      },\n      compactionConfig: this.policies.compactionConfig,\n      retryConfig: this.retry.retryConfig,\n      rateLimitConfig: this.subagents.rateLimitConfig,\n      signal: this.core.signal,\n      reasoning: this.core.reasoningConfig,\n      caching: this.core.cachingConfig,\n      subagentConfig: this.subagents.subagentConfig,\n      treeConfig: {\n        tree: this.subagents.parentContext?.tree,\n        parentNodeId: this.subagents.parentContext?.nodeId,\n        baseDepth: this.subagents.parentContext ? (this.subagents.parentContext.depth ?? 0) + 1 : 0,\n        parentObservers: this.subagents.parentObservers,\n      },\n      sharedRateLimitTracker: this.subagents.sharedRateLimitTracker,\n      sharedRetryConfig: this.retry.sharedRetryConfig,\n      mcpSpecs: this.mcp.servers.length > 0 ? [...this.mcp.servers] : undefined,\n    };\n  }\n\n  /** Create agent and start with a user prompt. */\n  ask(userPrompt: string): Agent {\n    return new Agent(AGENT_INTERNAL_KEY, this.buildAgentOptions(userPrompt));\n  }\n\n  /** Create agent with multimodal input (text + image). */\n  askWithImage(\n    textPrompt: string,\n    imageData: Buffer | Uint8Array | string,\n    mimeType?: ImageMimeType,\n  ): Agent {\n    const content = buildMultimodalContent(textPrompt, imageData, mimeType);\n    return new Agent(AGENT_INTERNAL_KEY, this.buildAgentOptions(content));\n  }\n\n  /** Create agent with flexible multimodal content parts. */\n  askWithContent(content: ContentPart[]): Agent {\n    return new Agent(AGENT_INTERNAL_KEY, this.buildAgentOptions(content));\n  }\n\n  /** Run agent and collect text response. */\n  async askAndCollect(userPrompt: string): Promise<string> {\n    return collectText(this.ask(userPrompt).run());\n  }\n\n  /** Run agent with event handlers. */\n  async askWith(userPrompt: string, handlers: EventHandlers): Promise<void> {\n    await this.ask(userPrompt).runWith(handlers);\n  }\n\n  /** Build agent without a prompt (useful for testing/inspection). */\n  build(): Agent {\n    return new Agent(AGENT_INTERNAL_KEY, this.buildAgentOptions());\n  }\n}\n","/**\n * Utility functions for hook manipulation.\n */\n\nimport type { Observers } from \"./hooks.js\";\n\n/**\n * Merge two observer objects into one.\n * When both have the same hook, creates a composite that calls both.\n * Child observers are called first, then parent observers.\n *\n * This enables proper observer inheritance in subagent chains:\n * - Parent agent defines onGadgetExecutionStart for tracking\n * - Subagent defines onLLMCallReady for page state refresh\n * - Both should work together, not replace each other\n *\n * @param child - Child agent's observers (called first)\n * @param parent - Parent agent's observers (called after child)\n * @returns Merged observers object, or undefined if both are undefined\n */\nexport function mergeObservers(child?: Observers, parent?: Observers): Observers | undefined {\n  if (!child && !parent) return undefined;\n  if (!child) return parent;\n  if (!parent) return child;\n\n  // Start with parent's observers as base\n  const merged: Observers = { ...parent };\n\n  // For each key in child, either add it or create composite\n  for (const key of Object.keys(child) as (keyof Observers)[]) {\n    const childFn = child[key];\n    const parentFn = parent[key];\n\n    if (!childFn) continue;\n\n    if (!parentFn) {\n      // Only child has this hook - use it directly\n      (merged as Record<string, unknown>)[key] = childFn;\n    } else {\n      // Both have this hook - create composite that calls both\n      // Child runs first (can modify state), parent runs after (for logging/tracking)\n      (merged as Record<string, unknown>)[key] = async (ctx: unknown) => {\n        await (childFn as (ctx: unknown) => void | Promise<void>)(ctx);\n        await (parentFn as (ctx: unknown) => void | Promise<void>)(ctx);\n      };\n    }\n  }\n\n  return merged;\n}\n","import type { ZodTypeAny } from \"zod\";\n\n/**\n * Helper to safely access Zod's internal _def structure.\n * Zod's _def is not publicly typed, so we cast through unknown.\n */\nfunction getDef(schema: ZodTypeAny): Record<string, unknown> {\n  return schema._def as unknown as Record<string, unknown>;\n}\n\n/**\n * Type hints that guide value coercion.\n * - 'string': Keep the value as a string, no coercion\n * - 'number': Coerce to number if possible\n * - 'boolean': Coerce to boolean if possible\n * - 'unknown': Use default auto-coercion logic (backwards compatible)\n */\nexport type TypeHint = \"string\" | \"number\" | \"boolean\" | \"unknown\";\n\n/**\n * Get the type name from a Zod schema's _def.\n * Handles both Zod v3 (typeName) and Zod v4 (type) structures.\n * Note: We cast _def to any since Zod's internal structure isn't publicly typed.\n */\nfunction getTypeName(schema: ZodTypeAny): string | undefined {\n  const def = getDef(schema);\n  // Zod v4 uses _def.type, Zod v3 uses _def.typeName\n  return (def?.type ?? def?.typeName) as string | undefined;\n}\n\n/**\n * Get the shape from a Zod object schema's _def.\n * Handles both Zod v3 (shape()) and Zod v4 (shape) structures.\n * Note: We cast _def to any since Zod's internal structure isn't publicly typed.\n */\nfunction getShape(schema: ZodTypeAny): Record<string, ZodTypeAny> | undefined {\n  const def = getDef(schema);\n  // Zod v4 uses _def.shape directly, Zod v3 uses _def.shape()\n  if (typeof def?.shape === \"function\") {\n    return (def.shape as () => Record<string, ZodTypeAny>)();\n  }\n  return def?.shape as Record<string, ZodTypeAny> | undefined;\n}\n\n/**\n * Introspects Zod schemas to determine expected types at JSON pointer paths.\n *\n * This enables schema-aware type coercion - instead of blindly converting\n * \"1\" to a number, the parser can check if the schema expects a string\n * and preserve the original value.\n *\n * Design decisions:\n * - Union types prefer string over other primitives (preserves LLM intent)\n * - Transform/effect schemas return 'unknown' (let Zod handle transformation)\n * - Invalid paths return 'unknown' (fall back to auto-coercion)\n *\n * @example\n * ```typescript\n * const schema = z.object({\n *   id: z.string(),\n *   count: z.number(),\n *   config: z.object({ timeout: z.number() })\n * });\n *\n * const introspector = new SchemaIntrospector(schema);\n * introspector.getTypeAtPath(\"id\");           // 'string'\n * introspector.getTypeAtPath(\"count\");        // 'number'\n * introspector.getTypeAtPath(\"config/timeout\"); // 'number'\n * introspector.getTypeAtPath(\"unknown\");      // 'unknown'\n * ```\n */\nexport class SchemaIntrospector {\n  private readonly schema: ZodTypeAny;\n  private readonly cache = new Map<string, TypeHint>();\n\n  constructor(schema: ZodTypeAny) {\n    this.schema = schema;\n  }\n\n  /**\n   * Get the expected type at a JSON pointer path.\n   *\n   * @param pointer - JSON pointer path without leading / (e.g., \"config/timeout\", \"items/0\")\n   * @returns Type hint for coercion decision\n   */\n  getTypeAtPath(pointer: string): TypeHint {\n    // Check cache first\n    const cached = this.cache.get(pointer);\n    if (cached !== undefined) {\n      return cached;\n    }\n\n    const result = this.resolveTypeAtPath(pointer);\n    this.cache.set(pointer, result);\n    return result;\n  }\n\n  /**\n   * Internal method to resolve type at path without caching.\n   */\n  private resolveTypeAtPath(pointer: string): TypeHint {\n    // Empty pointer means the root - shouldn't happen for parameters\n    if (!pointer) {\n      return this.getBaseType(this.schema);\n    }\n\n    const segments = pointer.split(\"/\");\n    let current: ZodTypeAny = this.schema;\n\n    for (const segment of segments) {\n      // Unwrap any wrapper types (optional, default, nullable, etc.)\n      current = this.unwrapSchema(current);\n\n      // Navigate based on schema type\n      const typeName = getTypeName(current);\n\n      if (typeName === \"object\" || typeName === \"ZodObject\") {\n        // Navigate into object property\n        const shape = getShape(current);\n        if (!shape || !(segment in shape)) {\n          return \"unknown\"; // Property doesn't exist in schema\n        }\n        current = shape[segment];\n      } else if (typeName === \"array\" || typeName === \"ZodArray\") {\n        // For array indices, get element type\n        if (!/^\\d+$/.test(segment)) {\n          return \"unknown\"; // Not a numeric index\n        }\n        // Zod v4 uses _def.element, Zod v3 uses _def.type\n        const def = getDef(current);\n        const elementType = (def?.element ?? def?.type) as ZodTypeAny | undefined;\n        if (!elementType) {\n          return \"unknown\";\n        }\n        current = elementType;\n      } else if (typeName === \"tuple\" || typeName === \"ZodTuple\") {\n        // For tuples, get element at specific index\n        if (!/^\\d+$/.test(segment)) {\n          return \"unknown\";\n        }\n        const index = parseInt(segment, 10);\n        const def = getDef(current);\n        const items = def?.items as ZodTypeAny[] | undefined;\n        if (!items || index >= items.length) {\n          return \"unknown\";\n        }\n        current = items[index];\n      } else if (typeName === \"record\" || typeName === \"ZodRecord\") {\n        // For records, all values have the same type\n        // Zod v4 uses _def.valueType, Zod v3 uses _def.valueType\n        const def = getDef(current);\n        const valueType = def?.valueType as ZodTypeAny | undefined;\n        if (!valueType) {\n          return \"unknown\";\n        }\n        current = valueType;\n      } else {\n        // Can't navigate further (e.g., trying to access property on a string)\n        return \"unknown\";\n      }\n    }\n\n    // Get the base type of the final schema\n    return this.getBaseType(current);\n  }\n\n  /**\n   * Unwrap schema modifiers (optional, default, nullable, branded, etc.)\n   * to get to the underlying type.\n   */\n  private unwrapSchema(schema: ZodTypeAny): ZodTypeAny {\n    let current = schema;\n    let iterations = 0;\n    const maxIterations = 20; // Prevent infinite loops\n\n    while (iterations < maxIterations) {\n      const typeName = getTypeName(current);\n\n      // Check for wrapper types (both Zod v3 and v4 naming)\n      const wrapperTypes = [\n        \"optional\",\n        \"nullable\",\n        \"default\",\n        \"catch\",\n        \"branded\",\n        \"readonly\",\n        \"pipeline\",\n        \"ZodOptional\",\n        \"ZodNullable\",\n        \"ZodDefault\",\n        \"ZodCatch\",\n        \"ZodBranded\",\n        \"ZodReadonly\",\n        \"ZodPipeline\",\n      ];\n\n      if (typeName && wrapperTypes.includes(typeName)) {\n        const def = getDef(current);\n        const inner = (def?.innerType ?? def?.in ?? def?.type) as ZodTypeAny | undefined;\n        if (!inner || inner === current) break;\n        current = inner;\n        iterations++;\n        continue;\n      }\n\n      break;\n    }\n\n    return current;\n  }\n\n  /**\n   * Get the primitive type hint from an unwrapped schema.\n   */\n  private getBaseType(schema: ZodTypeAny): TypeHint {\n    const unwrapped = this.unwrapSchema(schema);\n    const typeName = getTypeName(unwrapped);\n\n    // Map both Zod v3 (ZodString) and v4 (string) type names\n    switch (typeName) {\n      // Primitive types\n      case \"string\":\n      case \"ZodString\":\n        return \"string\";\n      case \"number\":\n      case \"ZodNumber\":\n      case \"bigint\":\n      case \"ZodBigInt\":\n        return \"number\";\n      case \"boolean\":\n      case \"ZodBoolean\":\n        return \"boolean\";\n\n      // Literal types - check the literal value type\n      case \"literal\":\n      case \"ZodLiteral\": {\n        // Zod v4 uses _def.values (array), Zod v3 uses _def.value\n        const def = getDef(unwrapped);\n        const values = def?.values as unknown[] | undefined;\n        const value = values?.[0] ?? def?.value;\n        if (typeof value === \"string\") return \"string\";\n        if (typeof value === \"number\" || typeof value === \"bigint\") return \"number\";\n        if (typeof value === \"boolean\") return \"boolean\";\n        return \"unknown\";\n      }\n\n      // Enum - always string keys\n      case \"enum\":\n      case \"ZodEnum\":\n      case \"nativeEnum\":\n      case \"ZodNativeEnum\":\n        return \"string\";\n\n      // Union - return 'unknown' to let auto-coercion decide\n      // Since multiple types are valid, we can't definitively say what the LLM intended\n      // Auto-coercion will handle common cases (numbers, booleans) appropriately\n      case \"union\":\n      case \"ZodUnion\":\n        return \"unknown\";\n\n      // Discriminated union - complex, return unknown\n      case \"discriminatedUnion\":\n      case \"ZodDiscriminatedUnion\":\n        return \"unknown\";\n\n      // Intersection - check both sides\n      case \"intersection\":\n      case \"ZodIntersection\": {\n        const def = getDef(unwrapped);\n        const left = def?.left as ZodTypeAny | undefined;\n        const right = def?.right as ZodTypeAny | undefined;\n        if (!left || !right) return \"unknown\";\n\n        const leftType = this.getBaseType(left);\n        const rightType = this.getBaseType(right);\n\n        // If both are the same type, return it\n        if (leftType === rightType) return leftType;\n        // If one is string, prefer string\n        if (leftType === \"string\" || rightType === \"string\") return \"string\";\n        // Otherwise return unknown (complex intersection)\n        return \"unknown\";\n      }\n\n      // Effects/transforms - return unknown to let Zod handle it\n      case \"effects\":\n      case \"ZodEffects\":\n        // ZodEffects wraps transforms, refinements, etc.\n        // The transform expects input in original format, so don't coerce\n        return \"unknown\";\n\n      // Lazy - can't resolve without evaluating\n      case \"lazy\":\n      case \"ZodLazy\":\n        return \"unknown\";\n\n      // Complex types - return unknown\n      case \"object\":\n      case \"ZodObject\":\n      case \"array\":\n      case \"ZodArray\":\n      case \"tuple\":\n      case \"ZodTuple\":\n      case \"record\":\n      case \"ZodRecord\":\n      case \"map\":\n      case \"ZodMap\":\n      case \"set\":\n      case \"ZodSet\":\n      case \"function\":\n      case \"ZodFunction\":\n      case \"promise\":\n      case \"ZodPromise\":\n      case \"date\":\n      case \"ZodDate\":\n        return \"unknown\";\n\n      // Unknown/any/never/void/undefined/null\n      case \"unknown\":\n      case \"ZodUnknown\":\n      case \"any\":\n      case \"ZodAny\":\n      case \"never\":\n      case \"ZodNever\":\n      case \"void\":\n      case \"ZodVoid\":\n      case \"undefined\":\n      case \"ZodUndefined\":\n      case \"null\":\n      case \"ZodNull\":\n        return \"unknown\";\n\n      default:\n        return \"unknown\";\n    }\n  }\n}\n","import type { ZodTypeAny } from \"zod\";\nimport { GADGET_ARG_PREFIX } from \"../core/constants.js\";\nimport { SchemaIntrospector, type TypeHint } from \"./schema-introspector.js\";\n\nexport interface BlockParseOptions {\n  /** Prefix that declares an argument. Default: \"!!!ARG:\" */\n  argPrefix?: string;\n  /** Optional Zod schema for schema-aware type coercion */\n  schema?: ZodTypeAny;\n}\n\n/**\n * Parse block format parameters into an object.\n *\n * Block format uses !!!ARG:pointer syntax where pointer is a JSON Pointer\n * path (without leading /) that defines where to place the value.\n *\n * Example input:\n * ```\n * !!!ARG:filename\n * calculator.ts\n * !!!ARG:config/timeout\n * 30\n * !!!ARG:items/0\n * first\n * ```\n *\n * Produces:\n * ```json\n * {\n *   \"filename\": \"calculator.ts\",\n *   \"config\": { \"timeout\": 30 },\n *   \"items\": [\"first\"]\n * }\n * ```\n *\n * Single-line values are automatically coerced:\n * - \"true\" / \"false\" → boolean\n * - Numeric strings → number\n * - Multiline values always stay as strings (for code/content)\n *\n * @param content - Raw parameter content (after gadget name line, before end marker)\n * @param options - Parser options\n * @returns Parsed parameters object with coerced values\n * @throws Error if duplicate pointers or invalid array indices\n */\nexport function parseBlockParams(\n  content: string,\n  options?: BlockParseOptions,\n): Record<string, unknown> {\n  const argPrefix = options?.argPrefix ?? GADGET_ARG_PREFIX;\n  const result: Record<string, unknown> = {};\n  const seenPointers = new Set<string>();\n\n  // Create schema introspector if schema is provided\n  const introspector = options?.schema ? new SchemaIntrospector(options.schema) : undefined;\n\n  // Split content by arg prefix to get individual arg entries\n  // First element will be empty or whitespace before first arg\n  const parts = content.split(argPrefix);\n\n  for (let i = 1; i < parts.length; i++) {\n    const part = parts[i];\n\n    // Find the pointer (first line) and value (rest)\n    const newlineIndex = part.indexOf(\"\\n\");\n    if (newlineIndex === -1) {\n      // Arg with no value (just the pointer line)\n      const pointer = part.trim();\n      if (pointer) {\n        if (seenPointers.has(pointer)) {\n          throw new Error(`Duplicate pointer: ${pointer}`);\n        }\n        seenPointers.add(pointer);\n        setByPointer(result, pointer, \"\", introspector);\n      }\n      continue;\n    }\n\n    const pointer = part.substring(0, newlineIndex).trim();\n    let value = part.substring(newlineIndex + 1);\n\n    // Strip single trailing newline if present (per spec)\n    if (value.endsWith(\"\\n\")) {\n      value = value.slice(0, -1);\n    }\n\n    if (!pointer) {\n      continue; // Skip empty pointers\n    }\n\n    if (seenPointers.has(pointer)) {\n      throw new Error(`Duplicate pointer: ${pointer}`);\n    }\n    seenPointers.add(pointer);\n\n    setByPointer(result, pointer, value, introspector);\n  }\n\n  return result;\n}\n\n/**\n * Coerce a string value to its appropriate primitive type.\n *\n * When an `expectedType` hint is provided (from schema introspection), the coercion\n * respects the schema's expected type:\n * - 'string': Keep value as string, no coercion\n * - 'number': Coerce to number if valid\n * - 'boolean': Coerce to boolean if \"true\"/\"false\"\n * - 'unknown': Use auto-coercion logic (backwards compatible)\n *\n * Without a type hint (undefined), uses auto-coercion:\n * - \"true\" / \"false\" → boolean\n * - Numeric strings → number\n * - Everything else stays string\n *\n * Multiline values are never coerced (likely code/content).\n *\n * @param value - The string value to coerce\n * @param expectedType - Optional type hint from schema introspection\n * @returns Coerced value\n */\nfunction coerceValue(value: string, expectedType?: TypeHint): string | number | boolean {\n  // Don't coerce multiline values - they're likely code/content\n  if (value.includes(\"\\n\")) {\n    return value;\n  }\n\n  const trimmed = value.trim();\n\n  // If schema provides a type hint, respect it\n  if (expectedType === \"string\") {\n    // Keep as string - no coercion at all\n    return value;\n  }\n\n  if (expectedType === \"boolean\") {\n    // Only coerce recognized boolean strings\n    if (trimmed === \"true\") return true;\n    if (trimmed === \"false\") return false;\n    // Invalid boolean - keep as string for Zod to report error\n    return value;\n  }\n\n  if (expectedType === \"number\") {\n    // Attempt to coerce to number\n    const num = Number(trimmed);\n    if (!isNaN(num) && isFinite(num) && trimmed !== \"\") {\n      return num;\n    }\n    // Invalid number - keep as string for Zod to report error\n    return value;\n  }\n\n  // expectedType === 'unknown' or undefined: use auto-coercion logic\n  // This maintains backwards compatibility when no schema is provided\n  // or when schema introspection can't determine the type\n\n  // Boolean coercion\n  if (trimmed === \"true\") return true;\n  if (trimmed === \"false\") return false;\n\n  // Number coercion - only for values that look clearly numeric\n  // Avoid coercing things like \"123abc\" or empty strings\n  if (trimmed !== \"\" && /^-?\\d+(\\.\\d+)?$/.test(trimmed)) {\n    const num = Number(trimmed);\n    if (!isNaN(num) && isFinite(num)) {\n      return num;\n    }\n  }\n\n  return value;\n}\n\n/**\n * Set a value in an object using a JSON Pointer path (without leading /).\n *\n * Handles:\n * - Simple keys: \"name\" → { name: value }\n * - Nested paths: \"config/timeout\" → { config: { timeout: value } }\n * - Array indices: \"items/0\" → { items: [value] }\n *\n * Values are coerced based on the schema's expected type when an introspector\n * is provided. Without a schema, falls back to auto-coercion (backwards compatible).\n *\n * @param obj - Target object to modify\n * @param pointer - JSON Pointer path without leading /\n * @param value - Value to set (string that may be coerced)\n * @param introspector - Optional schema introspector for type-aware coercion\n * @throws Error if array index gaps detected\n */\nfunction setByPointer(\n  obj: Record<string, unknown>,\n  pointer: string,\n  value: string,\n  introspector?: SchemaIntrospector,\n): void {\n  const segments = pointer.split(\"/\");\n  let current: Record<string, unknown> | unknown[] = obj;\n\n  for (let i = 0; i < segments.length - 1; i++) {\n    const segment = segments[i];\n    const nextSegment = segments[i + 1];\n    const nextIsArrayIndex = /^\\d+$/.test(nextSegment);\n\n    if (Array.isArray(current)) {\n      const index = parseInt(segment, 10);\n      if (isNaN(index) || index < 0) {\n        throw new Error(`Invalid array index: ${segment}`);\n      }\n      // Validate no gaps\n      if (index > current.length) {\n        throw new Error(`Array index gap: expected ${current.length}, got ${index}`);\n      }\n      if (current[index] === undefined) {\n        current[index] = nextIsArrayIndex ? [] : {};\n      }\n      current = current[index] as Record<string, unknown> | unknown[];\n    } else {\n      // current is an object\n      const rec = current as Record<string, unknown>;\n      if (rec[segment] === undefined) {\n        rec[segment] = nextIsArrayIndex ? [] : {};\n      }\n      current = rec[segment] as Record<string, unknown> | unknown[];\n    }\n  }\n\n  // Set the final value\n  const lastSegment = segments[segments.length - 1];\n\n  // Get expected type from schema if available, then coerce accordingly\n  const expectedType = introspector?.getTypeAtPath(pointer);\n  const coercedValue = coerceValue(value, expectedType);\n\n  if (Array.isArray(current)) {\n    const index = parseInt(lastSegment, 10);\n    if (isNaN(index) || index < 0) {\n      throw new Error(`Invalid array index: ${lastSegment}`);\n    }\n    // Validate no gaps\n    if (index > current.length) {\n      throw new Error(`Array index gap: expected ${current.length}, got ${index}`);\n    }\n    current[index] = coercedValue;\n  } else {\n    (current as Record<string, unknown>)[lastSegment] = coercedValue;\n  }\n}\n","/**\n * LLMist client wrapper that automatically reports LLM costs via callback.\n *\n * Used internally by ExecutionContext to provide ctx.llmist for gadgets.\n * All LLM calls made through this wrapper will have their costs automatically\n * tracked and reported via the provided callback.\n *\n * @module gadgets/cost-reporting-client\n */\n\nimport type { LLMist } from \"../core/client.js\";\nimport type {\n  ImageGenerationOptions,\n  ImageGenerationResult,\n  SpeechGenerationOptions,\n  SpeechGenerationResult,\n} from \"../core/media-types.js\";\nimport type { ModelRegistry } from \"../core/model-registry.js\";\nimport { resolveModel } from \"../core/model-shortcuts.js\";\nimport type { LLMGenerationOptions, LLMStream, LLMStreamChunk } from \"../core/options.js\";\nimport type { TextGenerationOptions } from \"../core/quick-methods.js\";\nimport type {\n  CostReportingImageNamespace,\n  CostReportingLLMist,\n  CostReportingSpeechNamespace,\n} from \"./types.js\";\n\n/**\n * Callback type for reporting costs.\n */\nexport type CostReporter = (amount: number) => void;\n\n/**\n * LLMist client wrapper that automatically reports LLM costs.\n *\n * This wrapper intercepts all LLM calls, tracks token usage from responses,\n * calculates costs using ModelRegistry, and reports them via the callback.\n *\n * @example\n * ```typescript\n * let totalCost = 0;\n * const wrapper = new CostReportingLLMistWrapper(client, (cost) => {\n *   totalCost += cost;\n * });\n *\n * // LLM cost automatically reported after completion\n * const result = await wrapper.complete(\"Hello\");\n * console.log(`Cost: $${totalCost}`);\n * ```\n */\nexport class CostReportingLLMistWrapper implements CostReportingLLMist {\n  readonly image: CostReportingImageNamespace;\n  readonly speech: CostReportingSpeechNamespace;\n\n  constructor(\n    private readonly client: LLMist,\n    private readonly reportCost: CostReporter,\n  ) {\n    // Initialize image namespace with cost reporting\n    this.image = {\n      generate: async (options: ImageGenerationOptions): Promise<ImageGenerationResult> => {\n        const result = await this.client.image.generate(options);\n        // Report cost if available in the result\n        if (result.cost !== undefined && result.cost > 0) {\n          this.reportCost(result.cost);\n        }\n        return result;\n      },\n    };\n\n    // Initialize speech namespace with cost reporting\n    this.speech = {\n      generate: async (options: SpeechGenerationOptions): Promise<SpeechGenerationResult> => {\n        const result = await this.client.speech.generate(options);\n        // Report cost if available in the result\n        if (result.cost !== undefined && result.cost > 0) {\n          this.reportCost(result.cost);\n        }\n        return result;\n      },\n    };\n  }\n\n  /**\n   * Access to model registry for cost estimation.\n   */\n  get modelRegistry(): ModelRegistry {\n    return this.client.modelRegistry;\n  }\n\n  /**\n   * Quick completion with automatic cost reporting.\n   *\n   * Streams internally to track token usage, then reports the calculated cost.\n   *\n   * @param prompt - User prompt\n   * @param options - Optional configuration (model, temperature, etc.)\n   * @returns Complete text response\n   */\n  async complete(prompt: string, options?: TextGenerationOptions): Promise<string> {\n    const model = resolveModel(options?.model ?? \"haiku\");\n    let result = \"\";\n    let inputTokens = 0;\n    let outputTokens = 0;\n    let cachedInputTokens = 0;\n    let cacheCreationInputTokens = 0;\n    let reasoningTokens = 0;\n\n    const messages = [\n      ...(options?.systemPrompt\n        ? [{ role: \"system\" as const, content: options.systemPrompt }]\n        : []),\n      { role: \"user\" as const, content: prompt },\n    ];\n\n    for await (const chunk of this.client.stream({\n      model,\n      messages,\n      temperature: options?.temperature,\n      maxTokens: options?.maxTokens,\n    })) {\n      result += chunk.text ?? \"\";\n      if (chunk.usage) {\n        inputTokens = chunk.usage.inputTokens;\n        outputTokens = chunk.usage.outputTokens;\n        cachedInputTokens = chunk.usage.cachedInputTokens ?? 0;\n        cacheCreationInputTokens = chunk.usage.cacheCreationInputTokens ?? 0;\n        reasoningTokens = chunk.usage.reasoningTokens ?? 0;\n      }\n    }\n\n    this.reportCostFromUsage(\n      model,\n      inputTokens,\n      outputTokens,\n      cachedInputTokens,\n      cacheCreationInputTokens,\n      reasoningTokens,\n    );\n    return result;\n  }\n\n  /**\n   * Quick streaming with automatic cost reporting when stream completes.\n   *\n   * Yields text chunks as they arrive, then reports cost in finally block.\n   *\n   * @param prompt - User prompt\n   * @param options - Optional configuration (model, temperature, etc.)\n   * @returns Async generator yielding text chunks\n   */\n  async *streamText(prompt: string, options?: TextGenerationOptions): AsyncGenerator<string> {\n    const model = resolveModel(options?.model ?? \"haiku\");\n    let inputTokens = 0;\n    let outputTokens = 0;\n    let cachedInputTokens = 0;\n    let cacheCreationInputTokens = 0;\n    let reasoningTokens = 0;\n\n    const messages = [\n      ...(options?.systemPrompt\n        ? [{ role: \"system\" as const, content: options.systemPrompt }]\n        : []),\n      { role: \"user\" as const, content: prompt },\n    ];\n\n    try {\n      for await (const chunk of this.client.stream({\n        model,\n        messages,\n        temperature: options?.temperature,\n        maxTokens: options?.maxTokens,\n      })) {\n        if (chunk.text) {\n          yield chunk.text;\n        }\n        if (chunk.usage) {\n          inputTokens = chunk.usage.inputTokens;\n          outputTokens = chunk.usage.outputTokens;\n          cachedInputTokens = chunk.usage.cachedInputTokens ?? 0;\n          cacheCreationInputTokens = chunk.usage.cacheCreationInputTokens ?? 0;\n          reasoningTokens = chunk.usage.reasoningTokens ?? 0;\n        }\n      }\n    } finally {\n      // Report cost when stream ends (success or early exit)\n      this.reportCostFromUsage(\n        model,\n        inputTokens,\n        outputTokens,\n        cachedInputTokens,\n        cacheCreationInputTokens,\n        reasoningTokens,\n      );\n    }\n  }\n\n  /**\n   * Low-level stream access with automatic cost reporting.\n   *\n   * Returns a wrapped stream that reports costs when iteration completes.\n   *\n   * @param options - Full LLM generation options\n   * @returns Wrapped LLM stream that auto-reports costs\n   */\n  stream(options: LLMGenerationOptions): LLMStream {\n    return this.createCostReportingStream(options);\n  }\n\n  /**\n   * Creates a wrapped stream that tracks usage and reports costs on completion.\n   */\n  private createCostReportingStream(options: LLMGenerationOptions): LLMStream {\n    const innerStream = this.client.stream(options);\n    const reportCostFromUsage = this.reportCostFromUsage.bind(this);\n    const model = options.model;\n\n    async function* costReportingWrapper(): AsyncGenerator<LLMStreamChunk> {\n      let inputTokens = 0;\n      let outputTokens = 0;\n      let cachedInputTokens = 0;\n      let cacheCreationInputTokens = 0;\n      let reasoningTokens = 0;\n\n      try {\n        for await (const chunk of innerStream) {\n          if (chunk.usage) {\n            inputTokens = chunk.usage.inputTokens;\n            outputTokens = chunk.usage.outputTokens;\n            cachedInputTokens = chunk.usage.cachedInputTokens ?? 0;\n            cacheCreationInputTokens = chunk.usage.cacheCreationInputTokens ?? 0;\n            reasoningTokens = chunk.usage.reasoningTokens ?? 0;\n          }\n          yield chunk;\n        }\n      } finally {\n        // Report cost when stream completes (success or early exit)\n        if (inputTokens > 0 || outputTokens > 0) {\n          reportCostFromUsage(\n            model,\n            inputTokens,\n            outputTokens,\n            cachedInputTokens,\n            cacheCreationInputTokens,\n            reasoningTokens,\n          );\n        }\n      }\n    }\n\n    return costReportingWrapper();\n  }\n\n  /**\n   * Calculates and reports cost from token usage.\n   */\n  private reportCostFromUsage(\n    model: string,\n    inputTokens: number,\n    outputTokens: number,\n    cachedInputTokens = 0,\n    cacheCreationInputTokens = 0,\n    reasoningTokens = 0,\n  ): void {\n    if (inputTokens === 0 && outputTokens === 0) return;\n\n    // Model registry now handles provider-prefixed model IDs internally\n    const estimate = this.client.modelRegistry.estimateCost(\n      model,\n      inputTokens,\n      outputTokens,\n      cachedInputTokens,\n      cacheCreationInputTokens,\n      reasoningTokens,\n    );\n\n    if (estimate && estimate.totalCost > 0) {\n      this.reportCost(estimate.totalCost);\n    }\n  }\n}\n","import type { ZodError } from \"zod\";\nimport { GADGET_ARG_PREFIX, GADGET_END_PREFIX, GADGET_START_PREFIX } from \"../core/constants.js\";\nimport type { AbstractGadget } from \"./gadget.js\";\n\nexport interface ErrorFormatterOptions {\n  /** Custom argument prefix for block format examples. Default: \"!!!ARG:\" */\n  argPrefix?: string;\n  /** Custom start prefix for block format examples. Default: \"!!!GADGET_START:\" */\n  startPrefix?: string;\n  /** Custom end prefix for block format examples. Default: \"!!!GADGET_END\" */\n  endPrefix?: string;\n}\n\n/**\n * Formats gadget execution errors with helpful context for LLM self-correction.\n *\n * This class generates error messages that include:\n * - Clear error description\n * - Full gadget usage instructions (via getInstruction())\n * - Block format reference for parse errors\n *\n * The goal is to help LLMs self-correct on subsequent invocation attempts.\n */\nexport class GadgetExecutionErrorFormatter {\n  private readonly argPrefix: string;\n  private readonly startPrefix: string;\n  private readonly endPrefix: string;\n\n  constructor(options: ErrorFormatterOptions = {}) {\n    this.argPrefix = options.argPrefix ?? GADGET_ARG_PREFIX;\n    this.startPrefix = options.startPrefix ?? GADGET_START_PREFIX;\n    this.endPrefix = options.endPrefix ?? GADGET_END_PREFIX;\n  }\n\n  /**\n   * Format a Zod validation error with full gadget instructions.\n   *\n   * @param gadgetName - Name of the gadget that was called\n   * @param zodError - The Zod validation error\n   * @param gadget - The gadget instance (for generating instructions)\n   * @returns Formatted error message with usage instructions\n   */\n  formatValidationError(gadgetName: string, zodError: ZodError, gadget: AbstractGadget): string {\n    const parts: string[] = [];\n\n    // Error header\n    parts.push(`Error: Invalid parameters for '${gadgetName}':`);\n\n    // Format each validation issue\n    for (const issue of zodError.issues) {\n      const path = issue.path.join(\".\") || \"root\";\n      parts.push(`  - ${path}: ${issue.message}`);\n    }\n\n    // Add gadget usage instructions\n    parts.push(\"\");\n    parts.push(\"Gadget Usage:\");\n    parts.push(gadget.getInstruction(this.argPrefix));\n\n    return parts.join(\"\\n\");\n  }\n\n  /**\n   * Format a parse error with block format reference.\n   *\n   * @param gadgetName - Name of the gadget that was called\n   * @param parseError - The parse error message\n   * @param gadget - The gadget instance if found (for generating instructions)\n   * @returns Formatted error message with format reference\n   */\n  formatParseError(\n    gadgetName: string,\n    parseError: string,\n    gadget: AbstractGadget | undefined,\n  ): string {\n    const parts: string[] = [];\n\n    // Error header\n    parts.push(`Error: Failed to parse parameters for '${gadgetName}':`);\n    parts.push(`  ${parseError}`);\n\n    // Add gadget usage instructions if gadget exists\n    if (gadget) {\n      parts.push(\"\");\n      parts.push(\"Gadget Usage:\");\n      parts.push(gadget.getInstruction(this.argPrefix));\n    }\n\n    // Always add block format reference\n    parts.push(\"\");\n    parts.push(\"Block Format Reference:\");\n    parts.push(`  ${this.startPrefix}${gadgetName}`);\n    parts.push(`  ${this.argPrefix}parameterName`);\n    parts.push(\"  parameter value here\");\n    parts.push(`  ${this.endPrefix}`);\n\n    return parts.join(\"\\n\");\n  }\n\n  /**\n   * Format a registry error (gadget not found) with available gadgets list.\n   *\n   * @param gadgetName - Name of the gadget that was not found\n   * @param availableGadgets - List of available gadget names\n   * @returns Formatted error message with available gadgets\n   */\n  formatRegistryError(gadgetName: string, availableGadgets: string[]): string {\n    const parts: string[] = [];\n\n    // Error header\n    parts.push(`Error: Gadget '${gadgetName}' not found.`);\n\n    // List available gadgets\n    if (availableGadgets.length > 0) {\n      parts.push(\"\");\n      parts.push(`Available gadgets: ${availableGadgets.join(\", \")}`);\n    } else {\n      parts.push(\"\");\n      parts.push(\"No gadgets are currently registered.\");\n    }\n\n    return parts.join(\"\\n\");\n  }\n}\n\n/**\n * Create a pre-configured error formatter instance.\n *\n * @param options - Formatter options\n * @returns Configured GadgetExecutionErrorFormatter instance\n */\nexport function createErrorFormatter(\n  options: ErrorFormatterOptions = {},\n): GadgetExecutionErrorFormatter {\n  return new GadgetExecutionErrorFormatter(options);\n}\n","import { GADGET_ARG_PREFIX, GADGET_END_PREFIX, GADGET_START_PREFIX } from \"../core/constants.js\";\nimport { parseBlockParams } from \"./block-params.js\";\nimport type { StreamEvent } from \"./types.js\";\n\nexport type ParameterFormat = \"block\";\n\n/**\n * Strip markdown code fences from parameter content.\n * LLMs sometimes wrap their parameters in ```toml, ```yaml, ```json, or plain ``` blocks.\n * This function removes those fences to allow successful parsing.\n *\n * @internal Exported for testing only\n */\nexport function stripMarkdownFences(content: string): string {\n  let cleaned = content.trim();\n\n  // Pattern: ```toml, ```yaml, ```json, or just ``` at start (case-insensitive)\n  const openingFence = /^```(?:toml|yaml|json)?\\s*\\n/i;\n  // Pattern: ``` at end (with optional preceding newline)\n  const closingFence = /\\n?```\\s*$/;\n\n  // Strip opening fence if present\n  cleaned = cleaned.replace(openingFence, \"\");\n  // Strip closing fence if present\n  cleaned = cleaned.replace(closingFence, \"\");\n\n  return cleaned.trim();\n}\n\nexport interface StreamParserOptions {\n  startPrefix?: string;\n  endPrefix?: string;\n  /** Prefix for block format arguments. Default: \"!!!ARG:\" */\n  argPrefix?: string;\n}\n\n// Global counter for generating unique invocation IDs across all parser instances\nlet globalInvocationCounter = 0;\n\n/**\n * Reset the global invocation counter. Only use this in tests!\n * @internal\n */\nexport function resetGlobalInvocationCounter(): void {\n  globalInvocationCounter = 0;\n}\n\n/**\n * Tracks the single in-progress (trailing) gadget while its block streams, so we\n * can emit progressive argument partials with a stable invocationId and per-field\n * deltas, then a single authoritative `gadget_call` when the block completes.\n */\ninterface PartialGadgetState {\n  gadgetName: string;\n  invocationId: string;\n  dependencies: string[];\n  /** fieldPath -> length of the value already emitted (drives delta + de-dup). */\n  emittedFieldLengths: Map<string, number>;\n  /** fieldPaths already emitted as complete (avoid re-emitting completion). */\n  completedFields: Set<string>;\n  /**\n   * Body-relative count of bytes already scanned for markers. Lets each feed resume\n   * marker scanning near the tail (with overlap) instead of re-scanning the whole\n   * growing body — the difference between O(n) and O(n²) for large streamed gadgets.\n   */\n  bodyScannedLen: number;\n  /** Body-relative offset of the in-progress field's `!!!ARG:` marker (-1 = none yet). */\n  lastArgRelOffset: number;\n}\n\n/**\n * Parser for extracting gadget invocations from LLM text output.\n * Processes text chunks incrementally and emits events for text and gadget calls.\n */\nexport class GadgetCallParser {\n  private buffer = \"\";\n  private lastEmittedTextOffset = 0;\n  /** Non-null only while a single trailing gadget block is mid-stream. */\n  private currentPartial: PartialGadgetState | null = null;\n  private readonly startPrefix: string;\n  private readonly endPrefix: string;\n  private readonly argPrefix: string;\n  /** Length of the longest marker; `maxMarkerLength - 1` is the scan-resume overlap. */\n  private readonly maxMarkerLength: number;\n\n  constructor(options: StreamParserOptions = {}) {\n    this.startPrefix = options.startPrefix ?? GADGET_START_PREFIX;\n    this.endPrefix = options.endPrefix ?? GADGET_END_PREFIX;\n    this.argPrefix = options.argPrefix ?? GADGET_ARG_PREFIX;\n    this.maxMarkerLength = Math.max(\n      this.startPrefix.length,\n      this.endPrefix.length,\n      this.argPrefix.length,\n    );\n  }\n\n  /**\n   * Extract and consume text up to the given index.\n   * Returns undefined if no meaningful text to emit.\n   */\n  private extractTextSegment(index: number): string | undefined {\n    if (index <= this.lastEmittedTextOffset) {\n      return undefined;\n    }\n\n    const segment = this.buffer.slice(this.lastEmittedTextOffset, index);\n    this.lastEmittedTextOffset = index;\n\n    return segment.trim().length > 0 ? segment : undefined;\n  }\n\n  /**\n   * Parse gadget invocation metadata from the header line.\n   *\n   * Supported formats:\n   * - `GadgetName` - Auto-generate ID, no dependencies\n   * - `GadgetName:my_id` - Explicit ID, no dependencies\n   * - `GadgetName:my_id:dep1,dep2` - Explicit ID with dependencies\n   * - `GadgetName:my_id:dep1:dep2:dep3` - Colons treated as dep separators (LLM resilience)\n   *\n   * Dependencies can be comma-separated or colon-separated invocation IDs.\n   */\n  private parseInvocationMetadata(headerLine: string): {\n    gadgetName: string;\n    invocationId: string;\n    dependencies: string[];\n  } {\n    const parts = headerLine.split(\":\");\n\n    if (parts.length === 1) {\n      // Just name: GadgetName\n      return {\n        gadgetName: parts[0],\n        invocationId: `gadget_${++globalInvocationCounter}`,\n        dependencies: [],\n      };\n    } else if (parts.length === 2) {\n      // Name + ID: GadgetName:calc_1\n      return {\n        gadgetName: parts[0],\n        invocationId: parts[1].trim(),\n        dependencies: [],\n      };\n    } else {\n      // Name + ID + deps: GadgetName:calc_1:dep1,dep2\n      // Also handles LLM using colons instead of commas: GadgetName:id:dep1:dep2\n      const depsRaw = parts.slice(2).join(\",\");\n      const deps = [\n        ...new Set(\n          depsRaw\n            .split(\",\")\n            .map((d) => d.trim())\n            .filter((d) => d.length > 0),\n        ),\n      ];\n      return {\n        gadgetName: parts[0],\n        invocationId: parts[1].trim(),\n        dependencies: deps,\n      };\n    }\n  }\n\n  /**\n   * Extract the error message from a parse error.\n   * Preserves full message since the error formatter adds contextual help\n   * that benefits from precise, detailed error information.\n   */\n  private extractParseError(error: unknown): string {\n    return error instanceof Error ? error.message : String(error);\n  }\n\n  /**\n   * Parse parameter string using block format\n   */\n  private parseParameters(raw: string): {\n    parameters?: Record<string, unknown>;\n    parseError?: string;\n  } {\n    // Strip markdown code fences if LLM wrapped the parameters\n    const cleaned = stripMarkdownFences(raw);\n\n    try {\n      return { parameters: parseBlockParams(cleaned, { argPrefix: this.argPrefix }) };\n    } catch (error) {\n      return { parseError: this.extractParseError(error) };\n    }\n  }\n\n  // Feed a chunk of text and get parsed events\n  *feed(chunk: string): Generator<StreamEvent> {\n    this.buffer += chunk;\n\n    let startIndex = 0;\n    while (true) {\n      // Find next gadget start marker\n      const partStartIndex = this.buffer.indexOf(this.startPrefix, startIndex);\n      if (partStartIndex === -1) break;\n\n      // Yield any text before the gadget\n      const textBefore = this.extractTextSegment(partStartIndex);\n      if (textBefore !== undefined) {\n        yield { type: \"text\", content: textBefore };\n      }\n\n      // Extract gadget metadata from header line\n      const metadataStartIndex = partStartIndex + this.startPrefix.length;\n      const metadataEndIndex = this.buffer.indexOf(\"\\n\", metadataStartIndex);\n      if (metadataEndIndex === -1) break; // Wait for more data\n\n      const headerLine = this.buffer.substring(metadataStartIndex, metadataEndIndex).trim();\n      // Parse the header metadata exactly ONCE per gadget. While a gadget streams\n      // across multiple feeds we reuse the cached values so the (possibly\n      // auto-generated) invocationId is stable across every partial AND the final\n      // gadget_call — and the global counter is not bumped on each feed.\n      const { gadgetName, invocationId, dependencies } = this.currentPartial\n        ? this.currentPartial\n        : this.parseInvocationMetadata(headerLine);\n\n      const contentStartIndex = metadataEndIndex + 1;\n\n      let partEndIndex: number;\n      let endMarkerLength = 0;\n\n      // Look for end marker OR next start marker (implicit end). When a gadget is\n      // mid-stream we resume the scan near the tail (backing off by one marker's\n      // worth so a marker split across a chunk boundary is still found) instead of\n      // re-scanning the whole growing body every feed — O(n) instead of O(n²).\n      const bodySearchStart = this.currentPartial\n        ? contentStartIndex +\n          Math.max(0, this.currentPartial.bodyScannedLen - (this.maxMarkerLength - 1))\n        : contentStartIndex;\n\n      // Look for next gadget start (potential implicit end)\n      const nextStartPos = this.buffer.indexOf(this.startPrefix, bodySearchStart);\n\n      // Look for end marker\n      const endPos = this.buffer.indexOf(this.endPrefix, bodySearchStart);\n\n      // Decide which terminator to use:\n      // - If next start comes before end marker, use next start (implicit end)\n      // - Otherwise use the end marker if found\n      if (nextStartPos !== -1 && (endPos === -1 || nextStartPos < endPos)) {\n        // Found next gadget start before any end marker - implicit end\n        partEndIndex = nextStartPos;\n        endMarkerLength = 0; // Don't consume the next start marker\n      } else if (endPos !== -1) {\n        // Found proper end marker\n        partEndIndex = endPos;\n        endMarkerLength = this.endPrefix.length;\n      } else {\n        // Neither end marker nor next start found yet. The gadget is still\n        // streaming: surface the growing argument values as partials, then wait.\n        if (!this.currentPartial) {\n          this.currentPartial = this.newPartialState(gadgetName, invocationId, dependencies);\n        }\n        yield* this.emitArgPartials(\n          this.currentPartial,\n          contentStartIndex,\n          this.buffer.length,\n          false,\n        );\n        break;\n      }\n\n      // Gadget is complete. If we were streaming partials for it, flush any final\n      // deltas (marking every field complete) BEFORE the authoritative gadget_call.\n      const rawSlice = this.buffer.substring(contentStartIndex, partEndIndex);\n      if (this.currentPartial) {\n        yield* this.emitArgPartials(this.currentPartial, contentStartIndex, partEndIndex, true);\n      }\n\n      // Parse parameters according to configured format\n      const parametersRaw = rawSlice.trim();\n      const { parameters, parseError } = this.parseParameters(parametersRaw);\n\n      yield {\n        type: \"gadget_call\",\n        call: {\n          gadgetName,\n          invocationId,\n          parametersRaw,\n          parameters,\n          parseError,\n          dependencies,\n        },\n      };\n\n      // This gadget is done; the next trailing gadget (if any) re-initializes fresh.\n      this.currentPartial = null;\n\n      // Move past this gadget\n      startIndex = partEndIndex + endMarkerLength;\n\n      this.lastEmittedTextOffset = startIndex;\n    }\n\n    // Keep unprocessed data in buffer\n    if (startIndex > 0) {\n      this.buffer = this.buffer.substring(startIndex);\n      this.lastEmittedTextOffset = 0;\n    }\n  }\n\n  /** Create fresh partial-tracking state for a newly-started streaming gadget. */\n  private newPartialState(\n    gadgetName: string,\n    invocationId: string,\n    dependencies: string[],\n  ): PartialGadgetState {\n    return {\n      gadgetName,\n      invocationId,\n      dependencies,\n      emittedFieldLengths: new Map(),\n      completedFields: new Set(),\n      bodyScannedLen: 0,\n      lastArgRelOffset: -1,\n    };\n  }\n\n  /**\n   * Emit per-field \"growing value\" partials for an in-progress (or, when\n   * `allComplete`, a just-completed) gadget body delimited by [bodyStart, bodyEnd).\n   *\n   * Incremental by design: each call resumes the `!!!ARG:` scan near where the last\n   * one stopped (backing off by one marker's worth so a marker split across a chunk\n   * boundary is still found) and only re-touches the in-progress field, so a long\n   * streamed body costs O(new bytes) per feed instead of O(body). Every field except\n   * the in-progress (last) one is complete — a following `!!!ARG:` terminated it; the\n   * last field is tentative unless `allComplete`. The tentative field holds back any\n   * suffix that is a partial prefix of a gadget marker so it never leaks into a value.\n   *\n   * We deliberately do NOT run stripMarkdownFences here: an unbalanced opening fence\n   * sits before the first `!!!ARG:` (never emitted) and the authoritative gadget_call\n   * still strips fences from the full raw parameters.\n   */\n  private *emitArgPartials(\n    state: PartialGadgetState,\n    bodyStart: number,\n    bodyEnd: number,\n    allComplete: boolean,\n  ): Generator<StreamEvent> {\n    const argLen = this.argPrefix.length;\n\n    // Resume the !!!ARG: scan near the tail, but never before the current field's own\n    // marker (so the overlap re-scan can't re-finalize a field we already emitted).\n    let searchAbs = bodyStart + Math.max(0, state.bodyScannedLen - (this.maxMarkerLength - 1));\n    if (state.lastArgRelOffset >= 0) {\n      searchAbs = Math.max(searchAbs, bodyStart + state.lastArgRelOffset + argLen);\n    }\n\n    // Walk every NEW !!!ARG: marker. Each one terminates the prior in-progress field.\n    while (true) {\n      const argAbs = this.buffer.indexOf(this.argPrefix, searchAbs);\n      if (argAbs === -1 || argAbs >= bodyEnd) break;\n\n      if (state.lastArgRelOffset >= 0) {\n        // A following !!!ARG: proves the current field's value is final.\n        yield* this.emitFieldRange(state, bodyStart + state.lastArgRelOffset, argAbs, true);\n      }\n      state.lastArgRelOffset = argAbs - bodyStart;\n      searchAbs = argAbs + argLen;\n    }\n\n    // Emit the in-progress (last) field, value running to bodyEnd; complete only if\n    // the whole gadget body is done.\n    if (state.lastArgRelOffset >= 0) {\n      yield* this.emitFieldRange(state, bodyStart + state.lastArgRelOffset, bodyEnd, allComplete);\n    }\n\n    state.bodyScannedLen = bodyEnd - bodyStart;\n  }\n\n  /**\n   * Emit a single field whose `!!!ARG:` marker starts at `markerAbs` and whose value\n   * runs to `valueEndAbs` (the next marker, or the body end). Mirrors the per-field\n   * semantics of the old split-based emitter: field-path line, hold-back for a\n   * tentative value, single trailing-newline strip.\n   */\n  private *emitFieldRange(\n    state: PartialGadgetState,\n    markerAbs: number,\n    valueEndAbs: number,\n    complete: boolean,\n  ): Generator<StreamEvent> {\n    const pathStart = markerAbs + this.argPrefix.length;\n    const newlineAbs = this.buffer.indexOf(\"\\n\", pathStart);\n\n    // No field-path newline within this field's range — we don't know the name yet.\n    if (newlineAbs === -1 || newlineAbs >= valueEndAbs) {\n      // Wait, unless the field is already complete: then surface the trimmed pointer\n      // with an empty value (mirrors the old `newlineIndex === -1` branch).\n      if (!complete) return;\n      const pointer = this.buffer.substring(pathStart, valueEndAbs).trim();\n      if (pointer) yield* this.emitFieldDelta(state, pointer, \"\", true);\n      return;\n    }\n\n    const fieldPath = this.buffer.substring(pathStart, newlineAbs).trim();\n    if (!fieldPath) return;\n\n    let value = this.buffer.substring(newlineAbs + 1, valueEndAbs);\n\n    if (!complete) {\n      // Hold back a trailing partial marker so it never leaks into the value.\n      const hold = this.trailingPartialMarkerLength(value);\n      if (hold > 0) value = value.slice(0, value.length - hold);\n    }\n\n    // Strip a single trailing newline to match parseBlockParams semantics.\n    if (value.endsWith(\"\\n\")) value = value.slice(0, -1);\n\n    yield* this.emitFieldDelta(state, fieldPath, value, complete);\n  }\n\n  /**\n   * Emit a single partial for a field, but only when its value grew or it newly\n   * completed — keeping event volume proportional to field growth, not characters.\n   */\n  private *emitFieldDelta(\n    state: PartialGadgetState,\n    fieldPath: string,\n    value: string,\n    fieldComplete: boolean,\n  ): Generator<StreamEvent> {\n    const previousLength = state.emittedFieldLengths.get(fieldPath) ?? -1; // -1 => never emitted\n    const grew = value.length > previousLength;\n    const newlyComplete = fieldComplete && !state.completedFields.has(fieldPath);\n    if (!grew && !newlyComplete) return;\n\n    const delta = previousLength < 0 ? value : value.slice(Math.min(previousLength, value.length));\n    state.emittedFieldLengths.set(fieldPath, value.length);\n    if (fieldComplete) state.completedFields.add(fieldPath);\n\n    yield {\n      type: \"gadget_args_partial\",\n      invocationId: state.invocationId,\n      gadgetName: state.gadgetName,\n      fieldPath,\n      value,\n      delta,\n      isFieldComplete: fieldComplete,\n    };\n  }\n\n  /**\n   * Length of the longest suffix of `value` that is a proper prefix of any gadget\n   * marker (start/end/arg). Used to hold back the beginning of an incoming marker\n   * so it never appears inside a streamed value.\n   */\n  private trailingPartialMarkerLength(value: string): number {\n    const markers = [this.startPrefix, this.endPrefix, this.argPrefix];\n    const limit = Math.min(this.maxMarkerLength - 1, value.length);\n    for (let len = limit; len >= 1; len--) {\n      const suffix = value.slice(value.length - len);\n      for (const marker of markers) {\n        if (suffix.length < marker.length && marker.startsWith(suffix)) return len;\n      }\n    }\n    return 0;\n  }\n\n  // Finalize parsing and return remaining text or incomplete gadgets\n  *finalize(): Generator<StreamEvent> {\n    // Check if there's an incomplete gadget in the buffer\n    const startIndex = this.buffer.indexOf(this.startPrefix, this.lastEmittedTextOffset);\n\n    if (startIndex !== -1) {\n      // There's an incomplete gadget - try to parse it\n      const textBefore = this.extractTextSegment(startIndex);\n      if (textBefore !== undefined) {\n        yield { type: \"text\", content: textBefore };\n      }\n\n      // Extract gadget metadata from header line\n      const metadataStartIndex = startIndex + this.startPrefix.length;\n      const metadataEndIndex = this.buffer.indexOf(\"\\n\", metadataStartIndex);\n\n      if (metadataEndIndex !== -1) {\n        const headerLine = this.buffer.substring(metadataStartIndex, metadataEndIndex).trim();\n        // Reuse cached metadata so the invocationId matches partials already emitted.\n        const { gadgetName, invocationId, dependencies } = this.currentPartial\n          ? this.currentPartial\n          : this.parseInvocationMetadata(headerLine);\n        const contentStartIndex = metadataEndIndex + 1;\n\n        // Everything after the newline to end of buffer is the gadget body.\n        const contentRaw = this.buffer.substring(contentStartIndex);\n\n        // Flush any final partials (all fields complete) before the gadget_call.\n        if (this.currentPartial) {\n          yield* this.emitArgPartials(\n            this.currentPartial,\n            contentStartIndex,\n            this.buffer.length,\n            true,\n          );\n        }\n\n        const parametersRaw = contentRaw.trim();\n        const { parameters, parseError } = this.parseParameters(parametersRaw);\n\n        yield {\n          type: \"gadget_call\",\n          call: {\n            gadgetName,\n            invocationId,\n            parametersRaw: parametersRaw,\n            parameters,\n            parseError,\n            dependencies,\n          },\n        };\n\n        this.currentPartial = null;\n        return;\n      }\n    }\n\n    // No incomplete gadget - just emit remaining text\n    const remainingText = this.extractTextSegment(this.buffer.length);\n    if (remainingText !== undefined) {\n      yield { type: \"text\", content: remainingText };\n    }\n  }\n\n  // Reset parser state (note: global invocation counter is NOT reset to ensure unique IDs)\n  reset(): void {\n    this.buffer = \"\";\n    this.lastEmittedTextOffset = 0;\n    this.currentPartial = null;\n  }\n}\n","/**\n * Type-safe gadget factory with automatic parameter inference.\n *\n * Gadget eliminates the need for manual type assertions\n * by automatically inferring parameter types from the Zod schema.\n *\n * @example\n * ```typescript\n * class Calculator extends Gadget({\n *   description: \"Performs arithmetic operations\",\n *   schema: z.object({\n *     operation: z.enum([\"add\", \"subtract\"]),\n *     a: z.number(),\n *     b: z.number(),\n *   }),\n * }) {\n *   // ✨ params is automatically typed!\n *   execute(params: this['params']): string {\n *     const { operation, a, b } = params; // All typed!\n *     return operation === \"add\" ? String(a + b) : String(a - b);\n *   }\n * }\n * ```\n */\n\nimport type { ZodType } from \"zod\";\nimport { AbstractGadget } from \"./gadget.js\";\nimport type { ExecutionContext, GadgetExample, GadgetExecuteReturn } from \"./types.js\";\n\n/**\n * Infer the TypeScript type from a Zod schema.\n */\ntype InferSchema<T> = T extends ZodType<infer U> ? U : never;\n\n/**\n * Configuration for creating a typed gadget.\n */\nexport interface GadgetConfig<TSchema extends ZodType> {\n  /** Human-readable description of what the gadget does */\n  description: string;\n\n  /** Zod schema for parameter validation */\n  schema: TSchema;\n\n  /** Optional custom name (defaults to class name) */\n  name?: string;\n\n  /** Optional timeout in milliseconds */\n  timeoutMs?: number;\n\n  /** Optional usage examples to help LLMs understand proper invocation */\n  examples?: GadgetExample<InferSchema<TSchema>>[];\n\n  /**\n   * 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 must execute alone — no other gadgets in the same\n   * LLM response can run in parallel. Deferred until in-flight gadgets complete.\n   * Use for gadgets that terminate the agent loop (e.g., Finish).\n   */\n  exclusive?: boolean;\n}\n\n/**\n * Factory function to create a typed gadget base class.\n *\n * The returned class automatically infers parameter types from the Zod schema,\n * eliminating the need for manual type assertions in the execute method.\n *\n * @param config - Configuration with description and schema\n * @returns Base class to extend with typed execute method\n *\n * @example\n * ```typescript\n * import { z } from 'zod';\n * import { Gadget } from 'llmist';\n *\n * class Calculator extends Gadget({\n *   description: \"Performs arithmetic operations\",\n *   schema: z.object({\n *     operation: z.enum([\"add\", \"subtract\", \"multiply\", \"divide\"]),\n *     a: z.number().describe(\"First number\"),\n *     b: z.number().describe(\"Second number\"),\n *   }),\n * }) {\n *   execute(params: this['params']): string {\n *     // params is automatically typed as:\n *     // { operation: \"add\" | \"subtract\" | \"multiply\" | \"divide\"; a: number; b: number }\n *     const { operation, a, b } = params;\n *\n *     switch (operation) {\n *       case \"add\": return String(a + b);\n *       case \"subtract\": return String(a - b);\n *       case \"multiply\": return String(a * b);\n *       case \"divide\": return String(a / b);\n *     }\n *   }\n * }\n * ```\n *\n * @example\n * ```typescript\n * // With async execution\n * class WeatherGadget extends Gadget({\n *   description: \"Fetches weather for a city\",\n *   schema: z.object({\n *     city: z.string().min(1).describe(\"City name\"),\n *   }),\n *   timeoutMs: 10000,\n * }) {\n *   async execute(params: this['params']): Promise<string> {\n *     const { city } = params; // Automatically typed as { city: string }\n *     const weather = await fetchWeather(city);\n *     return `Weather in ${city}: ${weather}`;\n *   }\n * }\n * ```\n */\nexport function Gadget<TSchema extends ZodType>(config: GadgetConfig<TSchema>) {\n  abstract class GadgetBase extends AbstractGadget {\n    description = config.description;\n    parameterSchema = config.schema;\n    name = config.name;\n    timeoutMs = config.timeoutMs;\n    examples = config.examples;\n    maxConcurrent = config.maxConcurrent;\n    exclusive = config.exclusive;\n\n    /**\n     * Type helper property for accessing inferred parameter type.\n     * This is used in the execute method signature: `execute(params: this['params'])`\n     *\n     * Note: This is just for type inference - the actual params in execute()\n     * will be Record<string, unknown> which you can safely cast to this['params']\n     */\n    readonly params!: InferSchema<TSchema>;\n\n    /**\n     * Execute the gadget. Subclasses should cast params to this['params'].\n     *\n     * @param params - Validated parameters from the LLM\n     * @param ctx - Optional execution context for cost reporting and LLM access\n     * @returns Result as a string, or an object with result and optional cost\n     *\n     * @example\n     * ```typescript\n     * // Simple string return (free gadget)\n     * execute(params: this['params']) {\n     *   return String(params.a + params.b);\n     * }\n     *\n     * // Using context for callback-based cost reporting\n     * execute(params: this['params'], ctx) {\n     *   ctx.reportCost(0.001);\n     *   return \"result\";\n     * }\n     *\n     * // Using wrapped LLMist for automatic cost tracking\n     * async execute(params: this['params'], ctx) {\n     *   return ctx.llmist.complete('Summarize: ' + params.text);\n     * }\n     * ```\n     */\n    abstract execute(\n      params: Record<string, unknown>,\n      ctx?: ExecutionContext,\n    ): GadgetExecuteReturn | Promise<GadgetExecuteReturn>;\n  }\n\n  return GadgetBase as {\n    new (): GadgetBase & { params: InferSchema<TSchema> };\n  };\n}\n","import equal from \"fast-deep-equal\";\nimport type { ILogObj, Logger } from \"tslog\";\nimport { z } from \"zod\";\nimport { AgentBuilder } from \"../agent/builder.js\";\nimport { mergeObservers } from \"../agent/hook-utils.js\";\nimport type { Observers } from \"../agent/hooks.js\";\nimport { LLMist } from \"../core/client.js\";\nimport { GADGET_ARG_PREFIX } from \"../core/constants.js\";\nimport { ExecutionTree, type NodeId } from \"../core/execution-tree.js\";\nimport type { RateLimitTracker } from \"../core/rate-limit.js\";\nimport type { ResolvedRetryConfig } from \"../core/retry.js\";\nimport { createLogger } from \"../logging/logger.js\";\nimport { parseBlockParams } from \"./block-params.js\";\nimport { CostReportingLLMistWrapper } from \"./cost-reporting-client.js\";\nimport { createGadget } from \"./create-gadget.js\";\nimport { type ErrorFormatterOptions, GadgetExecutionErrorFormatter } from \"./error-formatter.js\";\nimport {\n  AbortException,\n  type HumanInputRequiredException,\n  TaskCompletionSignal,\n  TimeoutException,\n} from \"./exceptions.js\";\nimport type { MediaStore } from \"./media-store.js\";\nimport { stripMarkdownFences } from \"./parser.js\";\nimport type { GadgetRegistry } from \"./registry.js\";\nimport { Gadget } from \"./typed-gadget.js\";\nimport type {\n  AgentContextConfig,\n  ExecutionContext,\n  GadgetExecuteResult,\n  GadgetExecuteResultWithMedia,\n  GadgetExecutionResult,\n  GadgetMediaOutput,\n  HostExports,\n  ParsedGadgetCall,\n  SubagentConfigMap,\n} from \"./types.js\";\n\n/**\n * Get host exports for external gadgets to use when creating subagents.\n *\n * Note: We intentionally do NOT cache these references. In bundled environments,\n * caching can capture class references before they are fully initialized,\n * leading to stale AgentBuilder instances that lack methods like withParentContext.\n */\nfunction getHostExportsInternal(): HostExports {\n  return {\n    AgentBuilder,\n    Gadget,\n    createGadget,\n    ExecutionTree,\n    LLMist,\n    z,\n  };\n}\n\n/**\n * Options for constructing a GadgetExecutor.\n */\nexport interface GadgetExecutorOptions {\n  /** Gadget registry used to look up and execute gadgets */\n  registry: GadgetRegistry;\n\n  /** Optional callback to request human input during gadget execution */\n  requestHumanInput?: (question: string) => Promise<string>;\n\n  /** Logger instance; defaults to a new \"llmist:executor\" logger if omitted */\n  logger?: Logger<ILogObj>;\n\n  /** Default timeout in milliseconds applied to all gadgets without an explicit timeout */\n  defaultGadgetTimeoutMs?: number;\n\n  /** Options for formatting gadget execution errors */\n  errorFormatterOptions?: ErrorFormatterOptions;\n\n  /** LLMist client made available to gadgets via ExecutionContext.llmist */\n  client?: LLMist;\n\n  /** Media store for persisting gadget media outputs */\n  mediaStore?: MediaStore;\n\n  /** Parent agent configuration inherited by subagents */\n  agentConfig?: AgentContextConfig;\n\n  /** Per-gadget configuration overrides (e.g., timeoutMs, model) */\n  subagentConfig?: SubagentConfigMap;\n\n  /** Execution tree for tracking LLM calls and gadget executions */\n  tree?: ExecutionTree;\n\n  /** Parent node ID in the execution tree */\n  parentNodeId?: NodeId | null;\n\n  /** Base depth for nodes created during execution */\n  baseDepth?: number;\n\n  /**\n   * Parent agent's observer hooks for subagent visibility.\n   * When a subagent uses withParentContext(ctx), these observers are also called\n   * for gadget events in addition to the subagent's own hooks.\n   */\n  parentObservers?: Observers;\n\n  /**\n   * Current agent's observers.\n   * Passed to ExecutionContext.parentObservers so gadgets creating subagents\n   * can inherit them via withParentContext(ctx).\n   */\n  currentObservers?: Observers;\n\n  /** Shared rate limit tracker for coordinated throttling across subagents */\n  rateLimitTracker?: RateLimitTracker;\n\n  /** Shared retry config for consistent backoff behavior across subagents */\n  retryConfig?: ResolvedRetryConfig;\n}\n\nexport class GadgetExecutor {\n  private readonly registry: GadgetRegistry;\n  private readonly requestHumanInput?: (question: string) => Promise<string>;\n  private readonly defaultGadgetTimeoutMs?: number;\n  private readonly client?: LLMist;\n  private readonly mediaStore?: MediaStore;\n  private readonly agentConfig?: AgentContextConfig;\n  private readonly subagentConfig?: SubagentConfigMap;\n  private readonly tree?: ExecutionTree;\n  private readonly parentNodeId?: NodeId | null;\n  private readonly baseDepth?: number;\n  private readonly parentObservers?: Observers;\n  private readonly currentObservers?: Observers;\n  private readonly rateLimitTracker?: RateLimitTracker;\n  private readonly retryConfig?: ResolvedRetryConfig;\n  private readonly logger: Logger<ILogObj>;\n  private readonly errorFormatter: GadgetExecutionErrorFormatter;\n  private readonly argPrefix: string;\n\n  constructor(options: GadgetExecutorOptions) {\n    this.registry = options.registry;\n    this.requestHumanInput = options.requestHumanInput;\n    this.defaultGadgetTimeoutMs = options.defaultGadgetTimeoutMs;\n    this.client = options.client;\n    this.mediaStore = options.mediaStore;\n    this.agentConfig = options.agentConfig;\n    this.subagentConfig = options.subagentConfig;\n    this.tree = options.tree;\n    this.parentNodeId = options.parentNodeId;\n    this.baseDepth = options.baseDepth;\n    this.parentObservers = options.parentObservers;\n    this.currentObservers = options.currentObservers;\n    this.rateLimitTracker = options.rateLimitTracker;\n    this.retryConfig = options.retryConfig;\n    this.logger = options.logger ?? createLogger({ name: \"llmist:executor\" });\n    this.errorFormatter = new GadgetExecutionErrorFormatter(options.errorFormatterOptions);\n    this.argPrefix = options.errorFormatterOptions?.argPrefix ?? GADGET_ARG_PREFIX;\n  }\n\n  /**\n   * Creates a promise that rejects with a TimeoutException after the specified timeout.\n   * Aborts the provided AbortController before rejecting, allowing gadgets to clean up.\n   * Returns both the promise and a cancel function to clear the timeout when no longer needed.\n   */\n  private createTimeoutPromise(\n    gadgetName: string,\n    timeoutMs: number,\n    abortController: AbortController,\n  ): { promise: Promise<never>; cancel: () => void } {\n    let timeoutId: ReturnType<typeof setTimeout>;\n\n    const promise = new Promise<never>((_, reject) => {\n      timeoutId = setTimeout(() => {\n        const timeoutError = new TimeoutException(gadgetName, timeoutMs);\n        // Signal abort FIRST so gadgets can clean up before exception is thrown\n        // Pass the timeout message as reason for better debugging context\n        abortController.abort(timeoutError.message);\n        reject(timeoutError);\n      }, timeoutMs);\n    });\n\n    return {\n      promise,\n      cancel: () => clearTimeout(timeoutId),\n    };\n  }\n\n  /**\n   * Unify gadget execute result to consistent internal format.\n   * Handles string returns (backwards compat), object returns with cost,\n   * and object returns with media.\n   */\n  private unifyExecuteResult(raw: string | GadgetExecuteResult | GadgetExecuteResultWithMedia): {\n    result: string;\n    media?: GadgetMediaOutput[];\n    cost: number;\n  } {\n    if (typeof raw === \"string\") {\n      return { result: raw, cost: 0 };\n    }\n    // Check if it has media property (GadgetExecuteResultWithMedia)\n    if (\"media\" in raw && raw.media) {\n      return { result: raw.result, media: raw.media, cost: raw.cost ?? 0 };\n    }\n    return { result: raw.result, cost: raw.cost ?? 0 };\n  }\n\n  // Execute a gadget call asynchronously\n  async execute(call: ParsedGadgetCall): Promise<GadgetExecutionResult> {\n    const startTime = Date.now();\n\n    this.logger.debug(\"Executing gadget\", {\n      gadgetName: call.gadgetName,\n      invocationId: call.invocationId,\n      parameters: call.parameters,\n    });\n\n    const rawParameters: Record<string, unknown> = call.parameters ?? {};\n    let validatedParameters: Record<string, unknown> = rawParameters;\n\n    try {\n      // Check if gadget exists\n      const gadget = this.registry.get(call.gadgetName);\n      if (!gadget) {\n        this.logger.error(\"Gadget not found\", { gadgetName: call.gadgetName });\n        const availableGadgets = this.registry.getNames();\n        return {\n          gadgetName: call.gadgetName,\n          invocationId: call.invocationId,\n          parameters: call.parameters ?? {},\n          error: this.errorFormatter.formatRegistryError(call.gadgetName, availableGadgets),\n          executionTimeMs: Date.now() - startTime,\n        };\n      }\n\n      // Check for parse errors\n      if (call.parseError || !call.parameters) {\n        this.logger.error(\"Gadget parameter parse error\", {\n          gadgetName: call.gadgetName,\n          parseError: call.parseError,\n          rawParameters: call.parametersRaw,\n        });\n        const parseErrorMessage = call.parseError ?? \"Failed to parse parameters\";\n        return {\n          gadgetName: call.gadgetName,\n          invocationId: call.invocationId,\n          parameters: {},\n          error: this.errorFormatter.formatParseError(call.gadgetName, parseErrorMessage, gadget),\n          executionTimeMs: Date.now() - startTime,\n        };\n      }\n\n      // Re-parse parameters with schema for type-aware coercion (Approach B)\n      // This allows the parser to use the schema to determine correct types\n      // (e.g., keeping \"1\" as string when schema expects z.string())\n      // Only re-parse if:\n      // 1. The raw content is in block format (contains configured arg prefix)\n      // 2. Parameters weren't modified by an interceptor (compare with initial parse)\n      let schemaAwareParameters: Record<string, unknown> = rawParameters;\n      const hasBlockFormat = call.parametersRaw?.includes(this.argPrefix);\n      if (gadget.parameterSchema && hasBlockFormat) {\n        try {\n          const cleanedRaw = stripMarkdownFences(call.parametersRaw);\n\n          // First, parse without schema to get what initial parse would produce\n          const initialParse = parseBlockParams(cleanedRaw, { argPrefix: this.argPrefix });\n\n          // Check if parameters were modified by an interceptor\n          // by comparing current parameters with what initial parse produces\n          const parametersWereModified = !equal(rawParameters, initialParse);\n\n          if (parametersWereModified) {\n            // Parameters were modified by an interceptor - keep the modifications\n            this.logger.debug(\"Parameters modified by interceptor, skipping re-parse\", {\n              gadgetName: call.gadgetName,\n            });\n            schemaAwareParameters = rawParameters;\n          } else {\n            // Re-parse with schema for type-aware coercion\n            schemaAwareParameters = parseBlockParams(cleanedRaw, {\n              argPrefix: this.argPrefix,\n              schema: gadget.parameterSchema,\n            });\n            this.logger.debug(\"Re-parsed parameters with schema\", {\n              gadgetName: call.gadgetName,\n              original: rawParameters,\n              schemaAware: schemaAwareParameters,\n            });\n          }\n        } catch (error) {\n          // If re-parsing fails, fall back to original parameters\n          // This shouldn't happen if initial parse succeeded, but be safe\n          this.logger.warn(\"Schema-aware re-parsing failed, using original parameters\", {\n            gadgetName: call.gadgetName,\n            error: error instanceof Error ? error.message : String(error),\n          });\n          schemaAwareParameters = rawParameters;\n        }\n      }\n\n      if (gadget.parameterSchema) {\n        const validationResult = gadget.parameterSchema.safeParse(schemaAwareParameters);\n        if (!validationResult.success) {\n          const validationError = this.errorFormatter.formatValidationError(\n            call.gadgetName,\n            validationResult.error,\n            gadget,\n          );\n          this.logger.error(\"Gadget parameter validation failed\", {\n            gadgetName: call.gadgetName,\n            issueCount: validationResult.error.issues.length,\n          });\n\n          return {\n            gadgetName: call.gadgetName,\n            invocationId: call.invocationId,\n            parameters: schemaAwareParameters,\n            error: validationError,\n            executionTimeMs: Date.now() - startTime,\n          };\n        }\n\n        validatedParameters = validationResult.data as Record<string, unknown>;\n      } else {\n        // No schema - use the schema-aware parameters (which are same as raw if no schema)\n        validatedParameters = schemaAwareParameters;\n      }\n\n      // Determine the timeout for this gadget\n      // Priority: subagentConfig[name].timeoutMs > gadget.timeoutMs > defaultGadgetTimeoutMs > no timeout\n      const subagentTimeout = this.subagentConfig?.[call.gadgetName]?.timeoutMs;\n      const timeoutMs = subagentTimeout ?? gadget.timeoutMs ?? this.defaultGadgetTimeoutMs;\n\n      // Create AbortController for cancellation support\n      // Signal is always provided to gadgets, even without timeout\n      const abortController = new AbortController();\n\n      // Create execution context with cost accumulator and abort signal\n      let callbackCost = 0;\n      const reportCost = (amount: number) => {\n        if (amount > 0) {\n          callbackCost += amount;\n          this.logger.debug(\"Gadget reported cost via callback\", {\n            gadgetName: call.gadgetName,\n            amount,\n            totalCallbackCost: callbackCost,\n          });\n        }\n      };\n\n      // Build execution context with abort signal, agent config, and tree access\n      // Look up the gadget's own node ID from the tree (not the parent LLM call's ID)\n      const gadgetNodeId = this.tree?.getNodeByInvocationId(call.invocationId)?.id;\n      const gadgetDepth = gadgetNodeId\n        ? (this.tree?.getNode(gadgetNodeId)?.depth ?? this.baseDepth)\n        : this.baseDepth;\n\n      const ctx: ExecutionContext = {\n        reportCost,\n        llmist: this.client ? new CostReportingLLMistWrapper(this.client, reportCost) : undefined,\n        signal: abortController.signal,\n        agentConfig: this.agentConfig,\n        subagentConfig: this.subagentConfig,\n        invocationId: call.invocationId,\n        // Tree context for subagent support - use gadget's own node ID\n        tree: this.tree,\n        nodeId: gadgetNodeId,\n        depth: gadgetDepth,\n        // Host exports for external gadgets to use host's llmist classes\n        hostExports: getHostExportsInternal(),\n        // Logger for structured logging (respects CLI's log level/file config)\n        logger: this.logger,\n        // Human input callback for subagents to bubble up input requests\n        requestHumanInput: this.requestHumanInput,\n        // Parent observer hooks for subagent visibility\n        // When a subagent uses withParentContext(ctx), it will receive these\n        // and call them for gadget events in addition to its own hooks\n        // Merge child and parent observers so both get called (child first, then parent)\n        parentObservers: mergeObservers(this.currentObservers, this.parentObservers),\n        // Shared rate limit tracker for coordinated throttling across subagents\n        rateLimitTracker: this.rateLimitTracker,\n        // Shared retry config for consistent backoff behavior across subagents\n        retryConfig: this.retryConfig,\n      };\n\n      // Execute gadget (handle both sync and async)\n      let rawResult: string | GadgetExecuteResult;\n      if (timeoutMs && timeoutMs > 0) {\n        // Execute with timeout - abort signal will be triggered before timeout rejection\n        this.logger.debug(\"Executing gadget with timeout\", {\n          gadgetName: call.gadgetName,\n          timeoutMs,\n        });\n        const timeout = this.createTimeoutPromise(call.gadgetName, timeoutMs, abortController);\n        try {\n          rawResult = await Promise.race([\n            Promise.resolve(gadget.execute(validatedParameters, ctx)),\n            timeout.promise,\n          ]);\n        } finally {\n          // Always cancel the timeout to prevent it from keeping the event loop alive\n          timeout.cancel();\n        }\n      } else {\n        // Execute without timeout\n        rawResult = await Promise.resolve(gadget.execute(validatedParameters, ctx));\n      }\n\n      // Normalize result: handle string returns (legacy), object returns with cost, and media\n      const { result, media, cost: returnCost } = this.unifyExecuteResult(rawResult);\n\n      // Sum callback costs + return costs\n      const totalCost = callbackCost + returnCost;\n\n      // Store media in MediaStore if present\n      let mediaIds: string[] | undefined;\n      let storedMedia: import(\"./types.js\").StoredMedia[] | undefined;\n      if (media && media.length > 0 && this.mediaStore) {\n        storedMedia = await Promise.all(\n          media.map((item) => this.mediaStore!.store(item, call.gadgetName)),\n        );\n        mediaIds = storedMedia.map((m) => m.id);\n        this.logger.debug(\"Stored media outputs\", {\n          gadgetName: call.gadgetName,\n          mediaIds,\n          count: media.length,\n        });\n      }\n\n      const executionTimeMs = Date.now() - startTime;\n      this.logger.info(\"Gadget executed successfully\", {\n        gadgetName: call.gadgetName,\n        invocationId: call.invocationId,\n        executionTimeMs,\n        cost: totalCost > 0 ? totalCost : undefined,\n        callbackCost: callbackCost > 0 ? callbackCost : undefined,\n        returnCost: returnCost > 0 ? returnCost : undefined,\n        mediaCount: media?.length,\n      });\n\n      this.logger.debug(\"Gadget result\", {\n        gadgetName: call.gadgetName,\n        invocationId: call.invocationId,\n        parameters: validatedParameters,\n        result,\n        cost: totalCost,\n        executionTimeMs,\n        mediaIds,\n      });\n\n      return {\n        gadgetName: call.gadgetName,\n        invocationId: call.invocationId,\n        parameters: validatedParameters,\n        result,\n        executionTimeMs,\n        cost: totalCost,\n        media,\n        mediaIds,\n        storedMedia,\n        // Copy the gadget's sticky flag into the result envelope so the\n        // conversation-updater can mark the persisted message sticky for\n        // the compaction layer. Only set on success — errors and other\n        // unsuccessful exits skip this so failed loads don't pin themselves\n        // in context.\n        stickyResult: gadget.stickyResult,\n      };\n    } catch (error) {\n      // Check if this is a TaskCompletionSignal using duck typing\n      // (handles module duplication issues when external gadgets throw signals)\n      const isTaskCompletionSignal =\n        error instanceof Error && error.name === \"TaskCompletionSignal\";\n      if (isTaskCompletionSignal) {\n        this.logger.info(\"Gadget requested loop termination\", {\n          gadgetName: call.gadgetName,\n          message: error.message,\n        });\n        return {\n          gadgetName: call.gadgetName,\n          invocationId: call.invocationId,\n          parameters: validatedParameters,\n          result: error.message,\n          breaksLoop: true,\n          executionTimeMs: Date.now() - startTime,\n        };\n      }\n\n      // Check if this is a TimeoutException\n      if (error instanceof TimeoutException) {\n        this.logger.error(\"Gadget execution timed out\", {\n          gadgetName: call.gadgetName,\n          timeoutMs: error.timeoutMs,\n          executionTimeMs: Date.now() - startTime,\n        });\n        return {\n          gadgetName: call.gadgetName,\n          invocationId: call.invocationId,\n          parameters: validatedParameters,\n          error: error.message,\n          executionTimeMs: Date.now() - startTime,\n        };\n      }\n\n      // Check if this is an AbortException (thrown by gadgets when they detect abort signal)\n      if (error instanceof AbortException) {\n        this.logger.info(\"Gadget execution was aborted\", {\n          gadgetName: call.gadgetName,\n          executionTimeMs: Date.now() - startTime,\n        });\n        return {\n          gadgetName: call.gadgetName,\n          invocationId: call.invocationId,\n          parameters: validatedParameters,\n          error: error.message,\n          executionTimeMs: Date.now() - startTime,\n        };\n      }\n\n      // Check if this is a HumanInputRequiredException using duck typing\n      // (handles module duplication issues in monorepos)\n      const isHumanInputError =\n        error instanceof Error &&\n        error.name === \"HumanInputRequiredException\" &&\n        \"question\" in error;\n      if (isHumanInputError) {\n        const question = (error as HumanInputRequiredException).question;\n        this.logger.info(\"Gadget requested human input\", {\n          gadgetName: call.gadgetName,\n          question,\n        });\n\n        // If callback is provided, call it and wait for answer\n        if (this.requestHumanInput) {\n          try {\n            const answer = await this.requestHumanInput(question);\n            this.logger.debug(\"Human input received\", {\n              gadgetName: call.gadgetName,\n              answerLength: answer.length,\n            });\n            return {\n              gadgetName: call.gadgetName,\n              invocationId: call.invocationId,\n              parameters: validatedParameters,\n              result: answer,\n              executionTimeMs: Date.now() - startTime,\n            };\n          } catch (inputError) {\n            this.logger.error(\"Human input callback error\", {\n              gadgetName: call.gadgetName,\n              error: inputError instanceof Error ? inputError.message : String(inputError),\n            });\n            return {\n              gadgetName: call.gadgetName,\n              invocationId: call.invocationId,\n              parameters: validatedParameters,\n              error: inputError instanceof Error ? inputError.message : String(inputError),\n              executionTimeMs: Date.now() - startTime,\n            };\n          }\n        }\n\n        // No callback - return error since we can't get human input\n        this.logger.warn(\"Human input required but no callback provided\", {\n          gadgetName: call.gadgetName,\n        });\n        return {\n          gadgetName: call.gadgetName,\n          invocationId: call.invocationId,\n          parameters: validatedParameters,\n          error: \"Human input required but not available (stdin is not interactive)\",\n          executionTimeMs: Date.now() - startTime,\n        };\n      }\n\n      const executionTimeMs = Date.now() - startTime;\n      this.logger.error(\"Gadget execution failed\", {\n        gadgetName: call.gadgetName,\n        error: error instanceof Error ? error.message : String(error),\n        executionTimeMs,\n      });\n\n      return {\n        gadgetName: call.gadgetName,\n        invocationId: call.invocationId,\n        parameters: validatedParameters,\n        error: error instanceof Error ? error.message : String(error),\n        executionTimeMs,\n      };\n    }\n  }\n}\n","/**\n * GadgetConcurrencyManager: Manages concurrency control for gadget execution.\n *\n * Extracted from StreamProcessor to provide a focused, testable module for\n * managing concurrency state and logic during stream processing.\n *\n * Manages:\n * - Active execution counts per gadget name\n * - Concurrency queues for gadgets waiting for a slot\n * - In-flight executions (fire-and-forget parallel gadgets)\n * - Exclusive gadget queue (runs alone after in-flight complete)\n */\n\nimport type { ILogObj, Logger } from \"tslog\";\nimport type { GadgetRegistry } from \"../gadgets/registry.js\";\nimport type { ParsedGadgetCall, SubagentConfigMap } from \"../gadgets/types.js\";\nimport { createLogger } from \"../logging/logger.js\";\n\n/**\n * Options for constructing a GadgetConcurrencyManager.\n */\nexport interface GadgetConcurrencyManagerOptions {\n  /** Gadget registry for reading maxConcurrent/exclusive gadget config */\n  registry: GadgetRegistry;\n\n  /** Subagent configuration map for external concurrency limits */\n  subagentConfig?: SubagentConfigMap;\n\n  /** Logger instance */\n  logger?: Logger<ILogObj>;\n}\n\n/**\n * GadgetConcurrencyManager: Manages concurrency state and logic for gadget execution.\n *\n * Provides a clean API for:\n * - Checking whether a gadget can start immediately (canStart)\n * - Tracking active execution counts (trackExecution / onComplete)\n * - Queueing gadgets that exceed concurrency limits (queueForLater)\n * - Deferring exclusive gadgets until in-flight work finishes (exclusiveQueue)\n * - Waiting for all in-flight executions to finish (waitForAll)\n *\n * @example\n * ```typescript\n * const manager = new GadgetConcurrencyManager({ registry, subagentConfig });\n *\n * if (manager.canStart(call)) {\n *   manager.trackExecution(call.invocationId, executePromise);\n * } else {\n *   manager.queueForLater(call);\n * }\n *\n * // on completion:\n * manager.onComplete(call.gadgetName);\n * ```\n */\nexport class GadgetConcurrencyManager {\n  private readonly registry: GadgetRegistry;\n  private readonly subagentConfig?: SubagentConfigMap;\n  private readonly logger: Logger<ILogObj>;\n\n  /** Track active execution count per gadget name */\n  private activeCountByGadget: Map<string, number> = new Map();\n\n  /** Queue of gadgets waiting for a concurrency slot (per gadget name) */\n  private concurrencyQueue: Map<string, ParsedGadgetCall[]> = new Map();\n\n  /** All active gadget promises, keyed by invocationId */\n  private inFlightExecutions: Map<string, Promise<void>> = new Map();\n\n  /** Gadget name for each in-flight invocationId (for timeout event emission) */\n  private inFlightGadgetNames: Map<string, string> = new Map();\n\n  /** Queue of exclusive gadgets deferred until in-flight gadgets complete */\n  private exclusiveQueue: ParsedGadgetCall[] = [];\n\n  constructor(options: GadgetConcurrencyManagerOptions) {\n    this.registry = options.registry;\n    this.subagentConfig = options.subagentConfig;\n    this.logger = options.logger ?? createLogger({ name: \"llmist:gadget-concurrency-manager\" });\n  }\n\n  // ==========================================================================\n  // Concurrency limit resolution\n  // ==========================================================================\n\n  /**\n   * Get the effective concurrency limit for a gadget.\n   * Uses \"most restrictive wins\" strategy: the lowest non-zero value from\n   * external config (SubagentConfig) and gadget's intrinsic maxConcurrent.\n   *\n   * This ensures gadget authors can set safety floors (e.g., maxConcurrent: 1\n   * for file writers) that cannot be weakened by external configuration.\n   *\n   * @returns 0 if unlimited, otherwise the effective limit\n   */\n  getConcurrencyLimit(gadgetName: string): number {\n    // External config limit (SubagentConfig)\n    const configLimit = this.subagentConfig?.[gadgetName]?.maxConcurrent;\n\n    // Gadget's intrinsic limit\n    const gadget = this.registry.get(gadgetName);\n    const gadgetLimit = gadget?.maxConcurrent;\n\n    // Most restrictive wins: lowest non-zero value\n    // Treat 0 and undefined as \"unlimited\" (Infinity for comparison)\n    const config = configLimit || Number.POSITIVE_INFINITY;\n    const intrinsic = gadgetLimit || Number.POSITIVE_INFINITY;\n    const effective = Math.min(config, intrinsic);\n\n    return effective === Number.POSITIVE_INFINITY ? 0 : effective;\n  }\n\n  // ==========================================================================\n  // Concurrency checks\n  // ==========================================================================\n\n  /**\n   * Check whether a gadget call can start immediately given current concurrency state.\n   * Returns false if:\n   * - The gadget is exclusive and other gadgets are in-flight\n   * - The gadget has a concurrency limit and it is already reached\n   *\n   * Does NOT modify any state.\n   */\n  canStart(call: ParsedGadgetCall): boolean {\n    const gadget = this.registry.get(call.gadgetName);\n\n    // Exclusive gadgets must wait for all in-flight gadgets to complete\n    if (gadget?.exclusive && this.inFlightExecutions.size > 0) {\n      return false;\n    }\n\n    // Check per-gadget concurrency limit\n    const limit = this.getConcurrencyLimit(call.gadgetName);\n    if (limit > 0) {\n      const activeCount = this.activeCountByGadget.get(call.gadgetName) ?? 0;\n      if (activeCount >= limit) {\n        return false;\n      }\n    }\n\n    return true;\n  }\n\n  /**\n   * Check whether a gadget is marked as exclusive.\n   */\n  isExclusive(gadgetName: string): boolean {\n    const gadget = this.registry.get(gadgetName);\n    return gadget?.exclusive === true;\n  }\n\n  /**\n   * Get the current count of in-flight (actively executing) gadgets.\n   */\n  get inFlightCount(): number {\n    return this.inFlightExecutions.size;\n  }\n\n  /**\n   * Get the total count of actively executing gadgets across all gadget types.\n   * Used to know when all work is truly complete.\n   */\n  getTotalActiveGadgetCount(): number {\n    let total = 0;\n    for (const count of this.activeCountByGadget.values()) {\n      total += count;\n    }\n    return total;\n  }\n\n  /**\n   * Check if there are any gadgets waiting in concurrency queues.\n   */\n  hasQueuedGadgets(): boolean {\n    for (const queue of this.concurrencyQueue.values()) {\n      if (queue.length > 0) return true;\n    }\n    return false;\n  }\n\n  /**\n   * Get total count of queued gadgets across all queues.\n   */\n  getQueuedGadgetCount(): number {\n    let count = 0;\n    for (const queue of this.concurrencyQueue.values()) {\n      count += queue.length;\n    }\n    return count;\n  }\n\n  /**\n   * Check if there are exclusive gadgets waiting.\n   */\n  get hasExclusiveQueued(): boolean {\n    return this.exclusiveQueue.length > 0;\n  }\n\n  /**\n   * Drain and return all exclusive gadgets from the queue.\n   * The caller is responsible for executing them.\n   */\n  drainExclusiveQueue(): ParsedGadgetCall[] {\n    const queue = this.exclusiveQueue;\n    this.exclusiveQueue = [];\n    return queue;\n  }\n\n  // ==========================================================================\n  // State mutation\n  // ==========================================================================\n\n  /**\n   * Track an in-flight gadget execution.\n   * Increments the active count for the gadget name and registers the promise.\n   *\n   * @param invocationId - Unique ID for this execution\n   * @param gadgetName - Name of the gadget being executed\n   * @param promise - The execution promise to track\n   */\n  trackExecution(invocationId: string, gadgetName: string, promise: Promise<void>): void {\n    const currentCount = this.activeCountByGadget.get(gadgetName) ?? 0;\n    this.activeCountByGadget.set(gadgetName, currentCount + 1);\n    this.inFlightExecutions.set(invocationId, promise);\n    this.inFlightGadgetNames.set(invocationId, gadgetName);\n  }\n\n  /**\n   * Called when a gadget execution completes.\n   * Decrements active count and triggers queue processing if a slot opened up.\n   *\n   * @param gadgetName - Name of the gadget that completed\n   * @returns The next queued gadget call for this gadget, if one was promoted, otherwise null\n   */\n  onComplete(gadgetName: string): ParsedGadgetCall | null {\n    const newCount = (this.activeCountByGadget.get(gadgetName) ?? 1) - 1;\n    this.activeCountByGadget.set(gadgetName, newCount);\n    return this.promoteFromQueue(gadgetName);\n  }\n\n  /**\n   * Queue a gadget for later execution due to a concurrency limit being reached.\n   *\n   * @param call - The gadget call to defer\n   */\n  queueForLater(call: ParsedGadgetCall): void {\n    this.logger.debug(\"Gadget queued due to concurrency limit\", {\n      gadgetName: call.gadgetName,\n      invocationId: call.invocationId,\n      activeCount: this.activeCountByGadget.get(call.gadgetName) ?? 0,\n      limit: this.getConcurrencyLimit(call.gadgetName),\n    });\n    const queue = this.concurrencyQueue.get(call.gadgetName) ?? [];\n    queue.push(call);\n    this.concurrencyQueue.set(call.gadgetName, queue);\n  }\n\n  /**\n   * Queue a gadget for exclusive execution (after all in-flight complete).\n   *\n   * @param call - The exclusive gadget call to defer\n   */\n  queueExclusive(call: ParsedGadgetCall): void {\n    this.logger.debug(\"Deferring exclusive gadget until in-flight gadgets complete\", {\n      gadgetName: call.gadgetName,\n      invocationId: call.invocationId,\n      inFlightCount: this.inFlightExecutions.size,\n    });\n    this.exclusiveQueue.push(call);\n  }\n\n  /**\n   * Clear all in-flight tracking state.\n   * Called after all promises have completed, or on force-timeout.\n   * Also clears active gadget counts to prevent stale state when\n   * hanging promises eventually resolve into the void.\n   */\n  clearInFlight(): void {\n    this.inFlightExecutions.clear();\n    this.inFlightGadgetNames.clear();\n    this.activeCountByGadget.clear();\n  }\n\n  /**\n   * Get metadata for all currently in-flight executions.\n   * Used by the dispatcher to emit skip events when the in-flight timeout fires.\n   */\n  getInFlightEntries(): Array<{ invocationId: string; gadgetName: string }> {\n    return Array.from(this.inFlightGadgetNames.entries()).map(([invocationId, gadgetName]) => ({\n      invocationId,\n      gadgetName,\n    }));\n  }\n\n  // ==========================================================================\n  // Waiting\n  // ==========================================================================\n\n  /**\n   * Wait for all currently in-flight gadget executions to complete.\n   * Resolves when the Promise.all of all tracked promises resolves.\n   *\n   * Note: new executions may be started during waiting (from the queue).\n   * Callers should loop until inFlightCount === 0 AND hasQueuedGadgets() === false.\n   */\n  async waitForAll(): Promise<void> {\n    if (this.inFlightExecutions.size === 0) return;\n    await Promise.all(this.inFlightExecutions.values());\n  }\n\n  /**\n   * Get a promise that resolves when all current in-flight executions complete.\n   * Returns a resolved promise if no executions are in-flight.\n   */\n  getAllDonePromise(): Promise<\"done\"> {\n    if (this.inFlightExecutions.size === 0) {\n      return Promise.resolve(\"done\" as const);\n    }\n    return Promise.all(this.inFlightExecutions.values()).then(() => \"done\" as const);\n  }\n\n  // ==========================================================================\n  // Private helpers\n  // ==========================================================================\n\n  /**\n   * Check the concurrency queue for a gadget name and promote the next queued\n   * call if a slot is available.\n   *\n   * @param gadgetName - The gadget name to check\n   * @returns The promoted call, or null if queue is empty or limit still reached\n   */\n  private promoteFromQueue(gadgetName: string): ParsedGadgetCall | null {\n    const queue = this.concurrencyQueue.get(gadgetName);\n    if (!queue || queue.length === 0) return null;\n\n    const limit = this.getConcurrencyLimit(gadgetName);\n    const activeCount = this.activeCountByGadget.get(gadgetName) ?? 0;\n\n    if (limit === 0 || activeCount < limit) {\n      const nextCall = queue.shift()!;\n      this.logger.debug(\"Processing queued gadget\", {\n        gadgetName,\n        invocationId: nextCall.invocationId,\n        remainingInQueue: queue.length,\n      });\n      return nextCall;\n    }\n\n    return null;\n  }\n}\n","/**\n * GadgetDependencyResolver: Tracks and resolves gadget execution dependencies.\n *\n * Extracted from StreamProcessor to provide a focused, testable module for\n * managing the DAG of gadget dependencies across a single stream iteration.\n *\n * Manages:\n * - Gadgets awaiting their dependencies\n * - Completed gadget results (for dependency satisfaction checks)\n * - Failed invocations (for dependency skip propagation)\n * - Cross-iteration dependency state (prior completed/failed invocations)\n */\n\nimport type { GadgetExecutionResult, ParsedGadgetCall } from \"../gadgets/types.js\";\n\n/**\n * Options for constructing a GadgetDependencyResolver.\n */\nexport interface GadgetDependencyResolverOptions {\n  /**\n   * Set of invocation IDs that completed in previous iterations.\n   * Used to resolve dependencies on gadgets from prior LLM responses.\n   */\n  priorCompletedInvocations?: Set<string>;\n\n  /**\n   * Set of invocation IDs that failed in previous iterations.\n   * Used to skip gadgets that depend on previously-failed gadgets.\n   */\n  priorFailedInvocations?: Set<string>;\n}\n\n/**\n * GadgetDependencyResolver: Manages dependency state and resolution logic\n * for the gadget execution DAG within a single stream processing iteration.\n *\n * Provides a clean API for:\n * - Queuing gadgets that are waiting on dependencies\n * - Recording completed and failed gadget results\n * - Querying which gadgets are ready to execute\n * - Checking whether all dependencies have been satisfied or failed\n *\n * @example\n * ```typescript\n * const resolver = new GadgetDependencyResolver({\n *   priorCompletedInvocations: new Set([\"prev_gadget\"]),\n * });\n *\n * resolver.addPending(gadgetCall);\n * // ...after dependency executes:\n * resolver.markComplete(result);\n *\n * const ready = resolver.getReadyCalls();\n * ```\n */\nexport class GadgetDependencyResolver {\n  /** Gadgets waiting for their dependencies to complete */\n  private gadgetsAwaitingDependencies: Map<string, ParsedGadgetCall> = new Map();\n  /** Completed gadget results, keyed by invocation ID */\n  private completedResults: Map<string, GadgetExecutionResult> = new Map();\n  /** Invocation IDs of gadgets that have failed (error or skipped due to dependency) */\n  private failedInvocations: Set<string> = new Set();\n\n  /** Invocation IDs completed in previous iterations (read-only) */\n  private readonly priorCompletedInvocations: Set<string>;\n  /** Invocation IDs that failed in previous iterations (read-only) */\n  private readonly priorFailedInvocations: Set<string>;\n\n  constructor(options: GadgetDependencyResolverOptions = {}) {\n    this.priorCompletedInvocations = options.priorCompletedInvocations ?? new Set();\n    this.priorFailedInvocations = options.priorFailedInvocations ?? new Set();\n  }\n\n  // ==========================================================================\n  // State mutation\n  // ==========================================================================\n\n  /**\n   * Queue a gadget call that is waiting for one or more dependencies to complete.\n   * Call this when a gadget's dependencies are not yet all satisfied.\n   *\n   * @param call - The parsed gadget call to defer\n   */\n  addPending(call: ParsedGadgetCall): void {\n    this.gadgetsAwaitingDependencies.set(call.invocationId, call);\n  }\n\n  /**\n   * Record that a gadget completed successfully.\n   * This may unblock other gadgets that depend on this invocation.\n   *\n   * Also marks as failed if the result contains an error.\n   *\n   * @param result - The completed gadget execution result\n   */\n  markComplete(result: GadgetExecutionResult): void {\n    this.completedResults.set(result.invocationId, result);\n    if (result.error) {\n      this.failedInvocations.add(result.invocationId);\n    }\n  }\n\n  /**\n   * Mark an invocation ID as failed without recording a full result.\n   * Use this for gadgets that are skipped before execution (e.g., limit exceeded,\n   * self-referential dependency, dependency skip).\n   *\n   * @param invocationId - The invocation ID to mark as failed\n   */\n  markFailed(invocationId: string): void {\n    this.failedInvocations.add(invocationId);\n  }\n\n  /**\n   * Remove a gadget from the pending queue (called just before execution).\n   *\n   * @param invocationId - The invocation ID to remove from pending\n   */\n  removePending(invocationId: string): void {\n    this.gadgetsAwaitingDependencies.delete(invocationId);\n  }\n\n  /**\n   * Clear all remaining pending gadgets (e.g., after handling unresolvable deps).\n   */\n  clearPending(): void {\n    this.gadgetsAwaitingDependencies.clear();\n  }\n\n  // ==========================================================================\n  // Queries\n  // ==========================================================================\n\n  /**\n   * Get all gadget calls currently waiting for dependencies.\n   * Returns entries as [invocationId, call] pairs.\n   */\n  getPendingEntries(): Array<[string, ParsedGadgetCall]> {\n    return Array.from(this.gadgetsAwaitingDependencies.entries());\n  }\n\n  /**\n   * Get the number of gadgets currently waiting for dependencies.\n   */\n  get pendingCount(): number {\n    return this.gadgetsAwaitingDependencies.size;\n  }\n\n  /**\n   * Check whether a given invocation ID has been completed successfully\n   * (either in this iteration or a prior one).\n   */\n  isCompleted(invocationId: string): boolean {\n    return (\n      this.completedResults.has(invocationId) || this.priorCompletedInvocations.has(invocationId)\n    );\n  }\n\n  /**\n   * Check whether a given invocation ID has failed\n   * (either in this iteration or a prior one).\n   */\n  isFailed(invocationId: string): boolean {\n    return (\n      this.failedInvocations.has(invocationId) || this.priorFailedInvocations.has(invocationId)\n    );\n  }\n\n  /**\n   * Get the execution result for a completed invocation, if available.\n   * Only returns results from the current iteration; prior iterations\n   * are tracked by ID only.\n   */\n  getCompletedResult(invocationId: string): GadgetExecutionResult | undefined {\n    return this.completedResults.get(invocationId);\n  }\n\n  /**\n   * Check if all dependencies for a gadget call are satisfied.\n   * A dependency is satisfied if it completed in this or a prior iteration.\n   *\n   * @param call - The gadget call whose dependencies to check\n   * @returns true if all deps are satisfied, false if any are still pending\n   */\n  isAllSatisfied(call: ParsedGadgetCall): boolean {\n    return call.dependencies.every((dep) => this.isCompleted(dep));\n  }\n\n  /**\n   * Find the first failed dependency for a gadget call, if any.\n   * A dependency is considered failed if it failed in this or a prior iteration.\n   *\n   * @param call - The gadget call to check\n   * @returns The invocation ID of the failed dependency, or undefined if none\n   */\n  getFailedDependency(call: ParsedGadgetCall): string | undefined {\n    return call.dependencies.find((dep) => this.isFailed(dep));\n  }\n\n  /**\n   * Separate the pending gadgets into two groups:\n   * - Those ready to execute (all deps satisfied)\n   * - Those ready to skip (at least one dep has failed)\n   *\n   * Gadgets that are neither ready nor skippable remain pending.\n   *\n   * @returns Object with `readyToExecute` and `readyToSkip` arrays\n   */\n  getReadyCalls(): {\n    readyToExecute: ParsedGadgetCall[];\n    readyToSkip: Array<{ call: ParsedGadgetCall; failedDep: string }>;\n  } {\n    const readyToExecute: ParsedGadgetCall[] = [];\n    const readyToSkip: Array<{ call: ParsedGadgetCall; failedDep: string }> = [];\n\n    for (const [_invocationId, call] of this.gadgetsAwaitingDependencies) {\n      const failedDep = this.getFailedDependency(call);\n      if (failedDep) {\n        readyToSkip.push({ call, failedDep });\n        continue;\n      }\n\n      if (this.isAllSatisfied(call)) {\n        readyToExecute.push(call);\n      }\n    }\n\n    return { readyToExecute, readyToSkip };\n  }\n\n  // ==========================================================================\n  // Cross-iteration accessors (for Agent to accumulate state)\n  // ==========================================================================\n\n  /**\n   * Get all invocation IDs that completed successfully in this iteration.\n   * Used by Agent to accumulate completed IDs across iterations.\n   */\n  getCompletedInvocationIds(): Set<string> {\n    return new Set(this.completedResults.keys());\n  }\n\n  /**\n   * Get all invocation IDs that failed in this iteration.\n   * Used by Agent to accumulate failed IDs across iterations.\n   */\n  getFailedInvocationIds(): Set<string> {\n    return new Set(this.failedInvocations);\n  }\n}\n","/**\n * Observer notification helpers for consolidated gadget event dispatching.\n *\n * Encapsulates the repeated ~30-line pattern that appeared 6× in StreamProcessor:\n * 1. Resolve subagentContext from the execution tree\n * 2. Call hooks observers (awaited)\n * 3. Call parentObservers (awaited)\n *\n * Preserves sequential await behavior — critical for observer ordering guarantees.\n *\n * @module agent/observer-notifier\n */\n\nimport type { ILogObj, Logger } from \"tslog\";\nimport type { ExecutionTree, NodeId } from \"../core/execution-tree.js\";\nimport type { GadgetArgsPartialEvent } from \"../gadgets/types.js\";\nimport type {\n  ObserveGadgetArgsPartialContext,\n  ObserveGadgetCompleteContext,\n  ObserveGadgetSkippedContext,\n  ObserveGadgetStartContext,\n  Observers,\n} from \"./hooks.js\";\nimport { safeObserve } from \"./safe-observe.js\";\nimport { getSubagentContextForNode } from \"./tree-hook-bridge.js\";\n\n// ============================================================================\n// Context types for each notification kind\n// ============================================================================\n\n/**\n * Shared base data needed to resolve subagentContext and call observers.\n */\ninterface NotifyBaseContext {\n  /** Execution tree used to look up node and derive subagentContext */\n  tree: ExecutionTree | undefined;\n  /** Current agent's observer hooks */\n  hooks: Observers | undefined;\n  /** Parent agent's observer hooks (for subagent visibility) */\n  parentObservers: Observers | undefined;\n  /** Logger for safeObserve error reporting */\n  logger: Logger<ILogObj>;\n  /** Iteration number for the observer context */\n  iteration: number;\n}\n\n/** Data specific to the onGadgetSkipped notification */\nexport interface NotifyGadgetSkippedContext extends NotifyBaseContext {\n  gadgetName: string;\n  invocationId: string;\n  parameters: Record<string, unknown>;\n  failedDependency: string;\n  failedDependencyError: string;\n}\n\n/** Data specific to the onGadgetExecutionStart notification */\nexport interface NotifyGadgetStartContext extends NotifyBaseContext {\n  gadgetName: string;\n  invocationId: string;\n  parameters: Record<string, unknown>;\n}\n\n/** Data specific to the onGadgetArgsPartial notification */\nexport interface NotifyGadgetArgsPartialContext extends NotifyBaseContext {\n  /**\n   * The LLM-call node these gadgets hang off (StreamProcessor's parentNodeId).\n   * Used to derive subagentContext — the gadget's own node does not exist yet.\n   */\n  parentNodeId: NodeId | null | undefined;\n  event: GadgetArgsPartialEvent;\n}\n\n/** Data specific to the onGadgetExecutionComplete notification */\nexport interface NotifyGadgetCompleteContext extends NotifyBaseContext {\n  gadgetName: string;\n  invocationId: string;\n  parameters: Record<string, unknown>;\n  finalResult: string | undefined;\n  error: string | undefined;\n  executionTimeMs: number;\n  cost: number | undefined;\n}\n\n// ============================================================================\n// Notification helpers\n// ============================================================================\n\n/**\n * Notify all relevant observers when a gadget is skipped.\n *\n * Sequentially awaits:\n * 1. hooks.observers.onGadgetSkipped (current agent)\n * 2. parentObservers.onGadgetSkipped (parent agent, if present)\n */\nexport async function notifyGadgetSkipped(ctx: NotifyGadgetSkippedContext): Promise<void> {\n  const gadgetNode = ctx.tree?.getNodeByInvocationId(ctx.invocationId);\n  const subagentContext =\n    ctx.tree && gadgetNode ? getSubagentContextForNode(ctx.tree, gadgetNode.id) : undefined;\n\n  const context: ObserveGadgetSkippedContext = {\n    iteration: ctx.iteration,\n    gadgetName: ctx.gadgetName,\n    invocationId: ctx.invocationId,\n    parameters: ctx.parameters,\n    failedDependency: ctx.failedDependency,\n    failedDependencyError: ctx.failedDependencyError,\n    logger: ctx.logger,\n    subagentContext,\n  };\n\n  if (ctx.hooks?.onGadgetSkipped) {\n    const hookFn = ctx.hooks.onGadgetSkipped;\n    await safeObserve(() => hookFn(context), ctx.logger);\n  }\n\n  if (ctx.parentObservers?.onGadgetSkipped) {\n    const hookFn = ctx.parentObservers.onGadgetSkipped;\n    await safeObserve(() => hookFn(context), ctx.logger);\n  }\n}\n\n/**\n * Notify all relevant observers when a gadget execution starts.\n *\n * Sequentially awaits:\n * 1. hooks.observers.onGadgetExecutionStart (current agent)\n * 2. parentObservers.onGadgetExecutionStart (parent agent, if present)\n */\nexport async function notifyGadgetStart(ctx: NotifyGadgetStartContext): Promise<void> {\n  const gadgetNode = ctx.tree?.getNodeByInvocationId(ctx.invocationId);\n  const subagentContext =\n    ctx.tree && gadgetNode ? getSubagentContextForNode(ctx.tree, gadgetNode.id) : undefined;\n\n  const context: ObserveGadgetStartContext = {\n    iteration: ctx.iteration,\n    gadgetName: ctx.gadgetName,\n    invocationId: ctx.invocationId,\n    parameters: ctx.parameters,\n    logger: ctx.logger,\n    subagentContext,\n  };\n\n  if (ctx.hooks?.onGadgetExecutionStart) {\n    const hookFn = ctx.hooks.onGadgetExecutionStart;\n    await safeObserve(() => hookFn(context), ctx.logger);\n  }\n\n  if (ctx.parentObservers?.onGadgetExecutionStart) {\n    const hookFn = ctx.parentObservers.onGadgetExecutionStart;\n    await safeObserve(() => hookFn(context), ctx.logger);\n  }\n}\n\n/**\n * Notify observers of a progressive gadget-argument partial.\n *\n * Unlike start/complete, the gadget's ExecutionTree node does not exist yet (it is\n * created at gadget_call dispatch), so subagentContext is derived from the spawning\n * LLM-call node (`parentNodeId`) — the same approach agent.ts uses for LLM hooks.\n *\n * Awaited so per-field deltas are observed in emission order.\n */\nexport async function notifyGadgetArgsPartial(ctx: NotifyGadgetArgsPartialContext): Promise<void> {\n  if (!ctx.hooks?.onGadgetArgsPartial && !ctx.parentObservers?.onGadgetArgsPartial) return;\n\n  const subagentContext =\n    ctx.tree && ctx.parentNodeId\n      ? getSubagentContextForNode(ctx.tree, ctx.parentNodeId)\n      : undefined;\n\n  const context: ObserveGadgetArgsPartialContext = {\n    iteration: ctx.iteration,\n    invocationId: ctx.event.invocationId,\n    gadgetName: ctx.event.gadgetName,\n    fieldPath: ctx.event.fieldPath,\n    value: ctx.event.value,\n    delta: ctx.event.delta,\n    isFieldComplete: ctx.event.isFieldComplete,\n    logger: ctx.logger,\n    subagentContext,\n  };\n\n  if (ctx.hooks?.onGadgetArgsPartial) {\n    const hookFn = ctx.hooks.onGadgetArgsPartial;\n    await safeObserve(() => hookFn(context), ctx.logger);\n  }\n\n  if (ctx.parentObservers?.onGadgetArgsPartial) {\n    const hookFn = ctx.parentObservers.onGadgetArgsPartial;\n    await safeObserve(() => hookFn(context), ctx.logger);\n  }\n}\n\n/**\n * Notify all relevant observers when a gadget execution completes (success or error).\n *\n * Sequentially awaits:\n * 1. hooks.observers.onGadgetExecutionComplete (current agent)\n * 2. parentObservers.onGadgetExecutionComplete (parent agent, if present)\n */\nexport async function notifyGadgetComplete(ctx: NotifyGadgetCompleteContext): Promise<void> {\n  const gadgetNode = ctx.tree?.getNodeByInvocationId(ctx.invocationId);\n  const subagentContext =\n    ctx.tree && gadgetNode ? getSubagentContextForNode(ctx.tree, gadgetNode.id) : undefined;\n\n  const context: ObserveGadgetCompleteContext = {\n    iteration: ctx.iteration,\n    gadgetName: ctx.gadgetName,\n    invocationId: ctx.invocationId,\n    parameters: ctx.parameters,\n    finalResult: ctx.finalResult,\n    error: ctx.error,\n    executionTimeMs: ctx.executionTimeMs,\n    cost: ctx.cost,\n    logger: ctx.logger,\n    subagentContext,\n  };\n\n  if (ctx.hooks?.onGadgetExecutionComplete) {\n    const hookFn = ctx.hooks.onGadgetExecutionComplete;\n    await safeObserve(() => hookFn(context), ctx.logger);\n  }\n\n  if (ctx.parentObservers?.onGadgetExecutionComplete) {\n    const hookFn = ctx.parentObservers.onGadgetExecutionComplete;\n    await safeObserve(() => hookFn(context), ctx.logger);\n  }\n}\n","/**\n * GadgetDispatcher: Orchestrates the dispatch decision tree for gadget execution.\n *\n * Extracted from StreamProcessor to provide a focused module for:\n * - Routing gadget calls through the dependency/concurrency/limit decision tree\n * - Managing fire-and-forget parallel execution and queue draining\n * - Resolving pending gadgets whose dependencies were just satisfied\n * - Handling failed dependencies (skip, execute_anyway, use_fallback)\n * - Waiting for all in-flight parallel executions to finish\n *\n * Orchestrates:\n *   GadgetLimitGuard       — enforces maxGadgetsPerResponse\n *   GadgetDependencyResolver — DAG dependency tracking\n *   GadgetConcurrencyManager — per-gadget concurrency limits + exclusive queue\n *   GadgetHookLifecycle    — full hook lifecycle per gadget\n *\n * @module agent/gadget-dispatcher\n */\n\nimport type { ILogObj, Logger } from \"tslog\";\nimport type { ExecutionTree, NodeId } from \"../core/execution-tree.js\";\nimport type {\n  GadgetExecutionMode,\n  GadgetExecutionResult,\n  GadgetSkippedEvent,\n  ParsedGadgetCall,\n  StreamEvent,\n} from \"../gadgets/types.js\";\nimport { createLogger } from \"../logging/logger.js\";\nimport type { GadgetConcurrencyManager } from \"./gadget-concurrency-manager.js\";\nimport type { GadgetDependencyResolver } from \"./gadget-dependency-resolver.js\";\nimport type { GadgetHookLifecycle } from \"./gadget-hook-lifecycle.js\";\nimport type { GadgetLimitGuard } from \"./gadget-limit-guard.js\";\nimport type {\n  AgentHooks,\n  DependencySkipAction,\n  DependencySkipControllerContext,\n  Observers,\n} from \"./hooks.js\";\nimport { notifyGadgetSkipped } from \"./observer-notifier.js\";\n\n/**\n * Options for constructing a GadgetDispatcher.\n */\nexport interface GadgetDispatcherOptions {\n  /** Current iteration number */\n  iteration: number;\n\n  /** Hook lifecycle orchestrator for single-gadget execution */\n  hookLifecycle: GadgetHookLifecycle;\n\n  /** Dependency resolver (manages the DAG) */\n  dependencyResolver: GadgetDependencyResolver;\n\n  /** Concurrency manager */\n  concurrencyManager: GadgetConcurrencyManager;\n\n  /** Gadget limit guard */\n  limitGuard: GadgetLimitGuard;\n\n  /** Gadget execution mode */\n  gadgetExecutionMode: GadgetExecutionMode;\n\n  /** Execution tree for tree-tracking operations */\n  tree?: ExecutionTree;\n\n  /** Parent node ID for gadget nodes added to the tree */\n  parentNodeId?: NodeId | null;\n\n  /** Current agent hooks */\n  hooks: AgentHooks;\n\n  /** Parent agent observer hooks for subagent visibility */\n  parentObservers?: Observers;\n\n  /** Logger instance */\n  logger?: Logger<ILogObj>;\n\n  /**\n   * Callback to push completed events into the outer queue.\n   * Used during fire-and-forget parallel execution so results can be\n   * streamed to the caller while other chunks are being processed.\n   */\n  pushToQueue: (event: StreamEvent) => void;\n\n  /**\n   * Callback to drain and return all events currently in the outer queue.\n   * Called during the poll loop in waitForInFlightExecutions to enable\n   * real-time streaming of completed parallel gadget results.\n   */\n  drainQueue: () => StreamEvent[];\n\n  /**\n   * Maximum time (ms) to wait for in-flight gadgets to complete.\n   * If exceeded, remaining gadgets are force-cleared and the poll loop exits.\n   * Default: 300_000 (5 minutes).\n   */\n  inFlightTimeoutMs?: number;\n}\n\n/**\n * GadgetDispatcher: Routes each gadget call through the full dispatch decision tree\n * and manages parallel execution life-cycles.\n */\nexport class GadgetDispatcher {\n  private readonly iteration: number;\n  private readonly hookLifecycle: GadgetHookLifecycle;\n  private readonly dependencyResolver: GadgetDependencyResolver;\n  private readonly concurrencyManager: GadgetConcurrencyManager;\n  private readonly limitGuard: GadgetLimitGuard;\n  private readonly gadgetExecutionMode: GadgetExecutionMode;\n  private readonly tree?: ExecutionTree;\n  private readonly parentNodeId: NodeId | null;\n  private readonly hooks: AgentHooks;\n  private readonly parentObservers?: Observers;\n  private readonly logger: Logger<ILogObj>;\n  private readonly pushToQueue: (event: StreamEvent) => void;\n  private readonly drainQueue: () => StreamEvent[];\n  private readonly inFlightTimeoutMs: number;\n\n  constructor(options: GadgetDispatcherOptions) {\n    this.iteration = options.iteration;\n    this.hookLifecycle = options.hookLifecycle;\n    this.dependencyResolver = options.dependencyResolver;\n    this.concurrencyManager = options.concurrencyManager;\n    this.limitGuard = options.limitGuard;\n    this.gadgetExecutionMode = options.gadgetExecutionMode;\n    this.tree = options.tree;\n    this.parentNodeId = options.parentNodeId ?? null;\n    this.hooks = options.hooks;\n    this.parentObservers = options.parentObservers;\n    this.logger = options.logger ?? createLogger({ name: \"llmist:gadget-dispatcher\" });\n    this.pushToQueue = options.pushToQueue;\n    this.drainQueue = options.drainQueue;\n    this.inFlightTimeoutMs = options.inFlightTimeoutMs ?? 300_000;\n  }\n\n  // ==========================================================================\n  // Primary dispatch entry point\n  // ==========================================================================\n\n  /**\n   * Dispatch a single gadget call through the full decision tree.\n   *\n   * Decision order:\n   * 1. If limit exceeded → return (no events)\n   * 2. Yield gadget_call event (real-time feedback)\n   * 3. Add to execution tree\n   * 4. Handle self-referential dependency → skip\n   * 5. Handle already-failed dependency → skip or override\n   * 6. If unsatisfied deps → add to pending queue\n   * 7. If deps all satisfied → check limit, then execute\n   * 8. If no deps → check limit, concurrency, then execute (or queue)\n   */\n  async *dispatch(call: ParsedGadgetCall): AsyncGenerator<StreamEvent> {\n    // Early exit if limit already exceeded - don't emit events for buffered gadgets\n    if (this.limitGuard.isLimitExceeded) {\n      return;\n    }\n\n    // Yield gadget_call IMMEDIATELY (real-time feedback before execution)\n    yield { type: \"gadget_call\", call };\n\n    // Add gadget to execution tree\n    if (this.tree) {\n      this.tree.addGadget({\n        invocationId: call.invocationId,\n        name: call.gadgetName,\n        parameters: call.parameters ?? {},\n        dependencies: call.dependencies,\n        parentId: this.parentNodeId,\n      });\n    }\n\n    // Check for dependencies — use effectiveCall for dispatch (call retains original for tree/events)\n    let effectiveCall = call;\n    if (call.dependencies.length > 0) {\n      // Partition into self-referential and valid deps in a single pass\n      const selfRefs: string[] = [];\n      const validDeps: string[] = [];\n      for (const dep of call.dependencies) {\n        (dep === call.invocationId ? selfRefs : validDeps).push(dep);\n      }\n\n      if (selfRefs.length > 0) {\n        this.logger.warn(\"Filtering self-referential dependencies\", {\n          gadgetName: call.gadgetName,\n          invocationId: call.invocationId,\n          removedSelfRefs: selfRefs,\n          remainingDeps: validDeps,\n        });\n        effectiveCall = { ...call, dependencies: validDeps };\n\n        // If ALL dependencies were self-referential, skip the gadget entirely\n        if (validDeps.length === 0) {\n          const errorMessage = `Gadget \"${call.invocationId}\" cannot depend on itself (self-referential dependency)`;\n          for await (const evt of this.emitGadgetSkipEvents(\n            effectiveCall,\n            call.invocationId,\n            errorMessage,\n          )) {\n            yield evt;\n          }\n          return;\n        }\n      }\n\n      // Check if any dependency has failed (including from prior iterations)\n      const failedDep = this.dependencyResolver.getFailedDependency(effectiveCall);\n      if (failedDep) {\n        // Dependency failed - handle skip\n        const skipEvents = await this.handleFailedDependency(effectiveCall, failedDep);\n        for (const evt of skipEvents) {\n          yield evt;\n        }\n        return;\n      }\n\n      // Check if all dependencies are satisfied (including from prior iterations)\n      if (!this.dependencyResolver.isAllSatisfied(effectiveCall)) {\n        const unsatisfied = effectiveCall.dependencies.filter(\n          (dep) => !this.dependencyResolver.isCompleted(dep),\n        );\n        // Queue for later execution - gadget_call already yielded above\n        this.logger.debug(\"Queueing gadget for later - waiting on dependencies\", {\n          gadgetName: effectiveCall.gadgetName,\n          invocationId: effectiveCall.invocationId,\n          waitingOn: unsatisfied,\n        });\n        this.dependencyResolver.addPending(effectiveCall);\n        return; // Execution deferred, gadget_call already yielded\n      }\n\n      // All dependencies satisfied - check limit then execute\n      for await (const evt of this._checkLimitThenExecute(effectiveCall)) {\n        yield evt;\n      }\n\n      // Check if any pending gadgets can now execute\n      for await (const evt of this.processPendingGadgets()) {\n        yield evt;\n      }\n      return;\n    }\n\n    // NO dependencies - check gadget limit FIRST, then concurrency\n    for await (const evt of this._checkLimitThenExecuteWithConcurrency(call)) {\n      yield evt;\n    }\n  }\n\n  // ==========================================================================\n  // Pending gadget resolution\n  // ==========================================================================\n\n  /**\n   * Process pending gadgets whose dependencies are now satisfied.\n   * Yields events in real-time as gadgets complete.\n   *\n   * Gadgets are executed in parallel for efficiency,\n   * but results are yielded as they become available.\n   */\n  async *processPendingGadgets(): AsyncGenerator<StreamEvent> {\n    // Skip processing pending gadgets if limit already exceeded\n    if (this.limitGuard.isLimitExceeded) {\n      return;\n    }\n\n    let progress = true;\n\n    while (progress && this.dependencyResolver.pendingCount > 0) {\n      progress = false;\n\n      // Ask the resolver which gadgets are ready to execute or skip\n      const { readyToExecute, readyToSkip } = this.dependencyResolver.getReadyCalls();\n\n      // Handle skipped gadgets\n      for (const { call, failedDep } of readyToSkip) {\n        this.dependencyResolver.removePending(call.invocationId);\n        const skipEvents = await this.handleFailedDependency(call, failedDep);\n        for (const evt of skipEvents) {\n          yield evt;\n        }\n        progress = true;\n      }\n\n      // Execute ready gadgets\n      if (readyToExecute.length > 0) {\n        // Remove from pending before executing\n        for (const call of readyToExecute) {\n          this.dependencyResolver.removePending(call.invocationId);\n        }\n\n        if (this.gadgetExecutionMode === \"sequential\") {\n          // Sequential: execute one at a time, checking limit for each\n          this.logger.debug(\"Executing ready gadgets sequentially\", {\n            count: readyToExecute.length,\n            invocationIds: readyToExecute.map((c) => c.invocationId),\n          });\n\n          for (const call of readyToExecute) {\n            // Check limit before execution\n            const limitExceeded = yield* this._yieldLimitCheck(call);\n            if (limitExceeded) {\n              continue; // Limit exceeded, skip this gadget but continue with others\n            }\n\n            for await (const evt of this.hookLifecycle.execute(call)) {\n              yield evt;\n            }\n          }\n        } else {\n          // Parallel: check limit for each and execute allowed gadgets concurrently\n          this.logger.debug(\"Executing ready gadgets in parallel\", {\n            count: readyToExecute.length,\n            invocationIds: readyToExecute.map((c) => c.invocationId),\n          });\n\n          const eventSets = await Promise.all(\n            readyToExecute.map(async (call) => {\n              const events: StreamEvent[] = [];\n\n              // Check limit before execution\n              const limitGen = this.limitGuard.checkAndIncrement(call, {\n                tree: this.tree,\n                hooks: this.hooks.observers,\n                parentObservers: this.parentObservers,\n                iteration: this.iteration,\n                logger: this.logger,\n                markFailed: (invocationId) => this.dependencyResolver.markFailed(invocationId),\n              });\n              for await (const evt of limitGen) {\n                events.push(evt);\n              }\n              if (this.limitGuard.isLimitExceeded) {\n                return events; // Return skip events only\n              }\n\n              for await (const evt of this.hookLifecycle.execute(call)) {\n                events.push(evt);\n              }\n              return events;\n            }),\n          );\n\n          // Yield all events from parallel execution\n          for (const events of eventSets) {\n            for (const evt of events) {\n              yield evt;\n            }\n          }\n        }\n\n        progress = true;\n      }\n    }\n\n    // Warn about any remaining unresolved gadgets (circular or missing dependencies)\n    if (this.dependencyResolver.pendingCount > 0) {\n      // Collect all pending invocation IDs to detect circular dependencies\n      const pendingEntries = this.dependencyResolver.getPendingEntries();\n      const pendingIds = new Set(pendingEntries.map(([id]) => id));\n\n      for (const [invocationId, call] of pendingEntries) {\n        // Filter to deps that are not completed (in current or prior iterations)\n        const missingDeps = call.dependencies.filter(\n          (dep) => !this.dependencyResolver.isCompleted(dep),\n        );\n\n        // Categorize the dependency issue\n        const circularDeps = missingDeps.filter((dep) => pendingIds.has(dep));\n        const trulyMissingDeps = missingDeps.filter((dep) => !pendingIds.has(dep));\n\n        let errorMessage: string;\n        let logLevel: \"warn\" | \"error\" = \"warn\";\n\n        if (circularDeps.length > 0 && trulyMissingDeps.length > 0) {\n          errorMessage = `Dependencies unresolvable: circular=[${circularDeps.join(\", \")}], missing=[${trulyMissingDeps.join(\", \")}]`;\n          logLevel = \"error\";\n        } else if (circularDeps.length > 0) {\n          errorMessage = `Circular dependency detected: \"${invocationId}\" depends on \"${circularDeps[0]}\" which also depends on \"${invocationId}\" (directly or indirectly)`;\n        } else {\n          errorMessage = `Dependency \"${missingDeps[0]}\" was never executed - check that the invocation ID exists and is spelled correctly`;\n        }\n\n        this.logger[logLevel](\"Gadget has unresolvable dependencies\", {\n          gadgetName: call.gadgetName,\n          invocationId,\n          circularDependencies: circularDeps,\n          missingDependencies: trulyMissingDeps,\n        });\n\n        // Mark as failed and emit skip event\n        yield* this.emitGadgetSkipEvents(call, missingDeps[0], errorMessage);\n      }\n      this.dependencyResolver.clearPending();\n    }\n  }\n\n  // ==========================================================================\n  // In-flight execution management\n  // ==========================================================================\n\n  /**\n   * Wait for all in-flight gadget executions to complete, yielding events in real-time.\n   * Called at stream end to ensure all parallel executions finish.\n   */\n  async *waitForInFlightExecutions(): AsyncGenerator<StreamEvent> {\n    if (\n      this.concurrencyManager.inFlightCount === 0 &&\n      !this.concurrencyManager.hasQueuedGadgets() &&\n      !this.concurrencyManager.hasExclusiveQueued\n    ) {\n      return;\n    }\n\n    this.logger.debug(\"Waiting for in-flight gadget executions\", {\n      count: this.concurrencyManager.inFlightCount,\n      queuedCount: this.concurrencyManager.getQueuedGadgetCount(),\n    });\n\n    // Poll interval for draining queue (100ms provides responsive updates)\n    const POLL_INTERVAL_MS = 100;\n    const startTime = Date.now();\n\n    // Poll loop: yield queued events while waiting for gadgets to complete\n    // Continue while there are in-flight executions OR queued gadgets waiting\n    while (\n      this.concurrencyManager.inFlightCount > 0 ||\n      this.concurrencyManager.hasQueuedGadgets()\n    ) {\n      // Check global timeout to prevent indefinite hangs\n      if (Date.now() - startTime >= this.inFlightTimeoutMs) {\n        const timedOutEntries = this.concurrencyManager.getInFlightEntries();\n        this.logger.error(\"In-flight gadget timeout exceeded, force-clearing remaining gadgets\", {\n          timeoutMs: this.inFlightTimeoutMs,\n          remainingInFlight: timedOutEntries.length,\n          remainingQueued: this.concurrencyManager.getQueuedGadgetCount(),\n          timedOutInvocations: timedOutEntries.map((e) => e.invocationId),\n        });\n\n        // Emit gadget_skipped events for each timed-out gadget so consumers\n        // see proper terminal events and the execution tree has no dangling nodes\n        const timeoutError = `Gadget execution timed out after ${this.inFlightTimeoutMs}ms`;\n        for (const { invocationId, gadgetName } of timedOutEntries) {\n          this.dependencyResolver.markFailed(invocationId);\n          yield {\n            type: \"gadget_skipped\",\n            gadgetName,\n            invocationId,\n            parameters: {},\n            failedDependency: invocationId,\n            failedDependencyError: timeoutError,\n          } as StreamEvent;\n        }\n\n        this.concurrencyManager.clearInFlight();\n        break;\n      }\n\n      // Create a combined promise that resolves when current gadgets complete\n      const allDone = this.concurrencyManager.getAllDonePromise();\n\n      // Race between: all current gadgets completing OR poll timeout\n      const result = await Promise.race([\n        allDone,\n        new Promise<\"poll\">((resolve) => setTimeout(() => resolve(\"poll\"), POLL_INTERVAL_MS)),\n      ]);\n\n      // Yield any events that accumulated in the outer queue (real-time streaming)\n      for (const evt of this.drainQueue()) {\n        yield evt;\n      }\n\n      if (\n        result === \"done\" &&\n        this.concurrencyManager.getTotalActiveGadgetCount() === 0 &&\n        !this.concurrencyManager.hasQueuedGadgets()\n      ) {\n        // All gadgets complete (none active), no more queued - exit loop\n        break;\n      }\n      // Continue polling\n    }\n\n    // Clear the map after all promises have completed\n    this.concurrencyManager.clearInFlight();\n\n    // Process exclusive gadgets now that all in-flight gadgets have completed\n    if (this.concurrencyManager.hasExclusiveQueued) {\n      const exclusiveQueue = this.concurrencyManager.drainExclusiveQueue();\n      this.logger.debug(\"Processing deferred exclusive gadgets\", {\n        count: exclusiveQueue.length,\n      });\n      for (const call of exclusiveQueue) {\n        for await (const evt of this.hookLifecycle.execute(call)) {\n          yield evt;\n        }\n      }\n    }\n  }\n\n  // ==========================================================================\n  // Private helpers\n  // ==========================================================================\n\n  /**\n   * Check the limit, then execute with full concurrency routing (for no-dep gadgets).\n   */\n  private async *_checkLimitThenExecuteWithConcurrency(\n    call: ParsedGadgetCall,\n  ): AsyncGenerator<StreamEvent> {\n    // Check maxGadgetsPerResponse limit before any execution path\n    const limitExceeded = yield* this._yieldLimitCheck(call);\n    if (limitExceeded) {\n      return; // Limit exceeded, gadget was skipped\n    }\n\n    // Check exclusive constraint: exclusive gadgets must run alone\n    if (\n      this.concurrencyManager.isExclusive(call.gadgetName) &&\n      this.concurrencyManager.inFlightCount > 0\n    ) {\n      this.concurrencyManager.queueExclusive(call);\n      return;\n    }\n\n    // Check concurrency limit - queue for later if limit reached\n    if (!this.concurrencyManager.canStart(call)) {\n      this.concurrencyManager.queueForLater(call);\n      return;\n    }\n\n    // Execute based on execution mode\n    if (this.gadgetExecutionMode === \"sequential\") {\n      for await (const evt of this.hookLifecycle.execute(call)) {\n        yield evt;\n      }\n    } else {\n      // Parallel: fire-and-forget with concurrency tracking\n      this._startGadgetWithConcurrencyTracking(call);\n    }\n  }\n\n  /**\n   * Check the limit, then execute directly (for gadgets with satisfied deps).\n   */\n  private async *_checkLimitThenExecute(call: ParsedGadgetCall): AsyncGenerator<StreamEvent> {\n    const limitExceeded = yield* this._yieldLimitCheck(call);\n    if (limitExceeded) {\n      return;\n    }\n    for await (const evt of this.hookLifecycle.execute(call)) {\n      yield evt;\n    }\n  }\n\n  /**\n   * Run the limit check generator and yield any produced events.\n   * Returns true if the limit was exceeded (caller should return/continue).\n   *\n   * Passes a markFailed callback to the guard so that when a gadget is skipped\n   * due to the limit, it is also recorded as failed in the dependency resolver.\n   * This ensures that any gadgets depending on the skipped gadget are also skipped.\n   */\n  private async *_yieldLimitCheck(call: ParsedGadgetCall): AsyncGenerator<StreamEvent, boolean> {\n    for await (const evt of this.limitGuard.checkAndIncrement(call, {\n      tree: this.tree,\n      hooks: this.hooks.observers,\n      parentObservers: this.parentObservers,\n      iteration: this.iteration,\n      logger: this.logger,\n      markFailed: (invocationId) => this.dependencyResolver.markFailed(invocationId),\n    })) {\n      yield evt;\n    }\n    return this.limitGuard.isLimitExceeded;\n  }\n\n  /**\n   * Start a gadget execution with concurrency tracking (fire-and-forget).\n   * Events are pushed to completedResultsQueue for real-time streaming to the caller.\n   */\n  private _startGadgetWithConcurrencyTracking(call: ParsedGadgetCall): void {\n    const gadgetName = call.gadgetName;\n\n    const executionPromise = this._executeAndCollect(call).finally(() => {\n      // Notify manager that this gadget completed - it returns the next queued call if any\n      const nextCall = this.concurrencyManager.onComplete(gadgetName);\n      if (nextCall) {\n        this._startGadgetWithConcurrencyTracking(nextCall);\n      }\n    });\n\n    this.concurrencyManager.trackExecution(call.invocationId, gadgetName, executionPromise);\n  }\n\n  /**\n   * Execute a gadget and push each produced event into the shared queue.\n   * Used for fire-and-forget parallel execution.\n   */\n  private async _executeAndCollect(call: ParsedGadgetCall): Promise<void> {\n    for await (const evt of this.hookLifecycle.execute(call)) {\n      this.pushToQueue(evt);\n    }\n  }\n\n  /**\n   * Handle a gadget that cannot execute because a dependency failed.\n   * Calls the onDependencySkipped controller to allow customization.\n   */\n  async handleFailedDependency(call: ParsedGadgetCall, failedDep: string): Promise<StreamEvent[]> {\n    const events: StreamEvent[] = [];\n    const depResult = this.dependencyResolver.getCompletedResult(failedDep);\n    const depError = depResult?.error ?? \"Dependency failed\";\n\n    // Call controller to allow customization of skip behavior\n    let action: DependencySkipAction = { action: \"skip\" };\n    if (this.hooks.controllers?.onDependencySkipped) {\n      const context: DependencySkipControllerContext = {\n        iteration: this.iteration,\n        gadgetName: call.gadgetName,\n        invocationId: call.invocationId,\n        parameters: call.parameters ?? {},\n        failedDependency: failedDep,\n        failedDependencyError: depError,\n        logger: this.logger,\n      };\n      action = await this.hooks.controllers.onDependencySkipped(context);\n    }\n\n    if (action.action === \"skip\") {\n      // Skip gadget in execution tree\n      if (this.tree) {\n        const gadgetNode = this.tree.getNodeByInvocationId(call.invocationId);\n        if (gadgetNode) {\n          this.tree.skipGadget(gadgetNode.id, failedDep, depError, \"dependency_failed\");\n        }\n      }\n\n      // Emit skip event and notify observers (also marks as failed)\n      for await (const evt of this.emitGadgetSkipEvents(call, failedDep, depError)) {\n        events.push(evt);\n      }\n\n      this.logger.info(\"Gadget skipped due to failed dependency\", {\n        gadgetName: call.gadgetName,\n        invocationId: call.invocationId,\n        failedDependency: failedDep,\n      });\n    } else if (action.action === \"execute_anyway\") {\n      // Execute despite failed dependency\n      this.logger.info(\"Executing gadget despite failed dependency (controller override)\", {\n        gadgetName: call.gadgetName,\n        invocationId: call.invocationId,\n        failedDependency: failedDep,\n      });\n      for await (const evt of this.hookLifecycle.execute(call)) {\n        events.push(evt);\n      }\n    } else if (action.action === \"use_fallback\") {\n      // Use fallback result without executing\n      const fallbackResult: GadgetExecutionResult = {\n        gadgetName: call.gadgetName,\n        invocationId: call.invocationId,\n        parameters: call.parameters ?? {},\n        result: action.fallbackResult,\n        executionTimeMs: 0,\n      };\n      this.dependencyResolver.markComplete(fallbackResult);\n      events.push({ type: \"gadget_result\", result: fallbackResult });\n\n      this.logger.info(\"Using fallback result for gadget with failed dependency\", {\n        gadgetName: call.gadgetName,\n        invocationId: call.invocationId,\n        failedDependency: failedDep,\n      });\n    }\n\n    return events;\n  }\n\n  /**\n   * Emit gadget skip events: marks the gadget as failed, yields a GadgetSkippedEvent,\n   * and notifies onGadgetSkipped observers.\n   */\n  async *emitGadgetSkipEvents(\n    call: ParsedGadgetCall,\n    failedDep: string,\n    errorMessage: string,\n  ): AsyncGenerator<StreamEvent> {\n    this.dependencyResolver.markFailed(call.invocationId);\n\n    const skipEvent: GadgetSkippedEvent = {\n      type: \"gadget_skipped\",\n      gadgetName: call.gadgetName,\n      invocationId: call.invocationId,\n      parameters: call.parameters ?? {},\n      failedDependency: failedDep,\n      failedDependencyError: errorMessage,\n    };\n    yield skipEvent;\n\n    // Notify onGadgetSkipped observers (AWAITED for proper ordering)\n    await notifyGadgetSkipped({\n      tree: this.tree,\n      hooks: this.hooks.observers,\n      parentObservers: this.parentObservers,\n      logger: this.logger,\n      iteration: this.iteration,\n      gadgetName: call.gadgetName,\n      invocationId: call.invocationId,\n      parameters: call.parameters ?? {},\n      failedDependency: failedDep,\n      failedDependencyError: errorMessage,\n    });\n  }\n}\n","/**\n * GadgetHookLifecycle: Orchestrates the full hook lifecycle for a single gadget execution.\n *\n * Extracted from StreamProcessor.executeGadgetGenerator() (~170 lines) to provide a\n * focused, independently-testable class for the ordered sequence:\n *\n *   1. interceptGadgetParameters\n *   2. beforeGadgetExecution controller (can skip)\n *   3. Mark gadget as running in tree\n *   4. onGadgetExecutionStart observers\n *   5. Execute gadget (or use synthetic result if skipped)\n *   6. interceptGadgetResult\n *   7. afterGadgetExecution controller (can recover from error)\n *   8. Complete gadget in tree\n *   9. onGadgetExecutionComplete observers\n *  10. Mark complete in dependency resolver\n *  11. Yield gadget_result event\n *\n * @module agent/gadget-hook-lifecycle\n */\n\nimport type { ILogObj, Logger } from \"tslog\";\nimport type { ExecutionTree } from \"../core/execution-tree.js\";\nimport type { GadgetExecutor } from \"../gadgets/executor.js\";\nimport type { GadgetExecutionResult, ParsedGadgetCall, StreamEvent } from \"../gadgets/types.js\";\nimport type { GadgetDependencyResolver } from \"./gadget-dependency-resolver.js\";\nimport {\n  validateAfterGadgetExecutionAction,\n  validateBeforeGadgetExecutionAction,\n} from \"./hook-validators.js\";\nimport type {\n  AfterGadgetExecutionAction,\n  AfterGadgetExecutionControllerContext,\n  AgentHooks,\n  BeforeGadgetExecutionAction,\n  GadgetExecutionControllerContext,\n  GadgetParameterInterceptorContext,\n  GadgetResultInterceptorContext,\n  Observers,\n} from \"./hooks.js\";\nimport { notifyGadgetComplete, notifyGadgetStart } from \"./observer-notifier.js\";\n\n/**\n * Options for constructing a GadgetHookLifecycle.\n */\nexport interface GadgetHookLifecycleOptions {\n  /** Current iteration number */\n  iteration: number;\n\n  /** Hooks (controllers, interceptors, observers) */\n  hooks: AgentHooks;\n\n  /** Logger instance */\n  logger: Logger<ILogObj>;\n\n  /** Executor that actually runs the gadget */\n  executor: GadgetExecutor;\n\n  /** Execution tree for tracking gadget state */\n  tree?: ExecutionTree;\n\n  /** Parent agent observers for subagent visibility */\n  parentObservers?: Observers;\n\n  /** Dependency resolver to mark completion after execution */\n  dependencyResolver: GadgetDependencyResolver;\n}\n\n/**\n * GadgetHookLifecycle: Runs the full ordered hook sequence for a single gadget.\n *\n * @example\n * ```typescript\n * const lifecycle = new GadgetHookLifecycle({ iteration, hooks, logger, executor, tree, ... });\n *\n * for await (const evt of lifecycle.execute(call)) {\n *   yield evt; // gadget_result (and no other events)\n * }\n * ```\n */\nexport class GadgetHookLifecycle {\n  private readonly iteration: number;\n  private readonly hooks: AgentHooks;\n  private readonly logger: Logger<ILogObj>;\n  private readonly executor: GadgetExecutor;\n  private readonly tree?: ExecutionTree;\n  private readonly parentObservers?: Observers;\n  private readonly dependencyResolver: GadgetDependencyResolver;\n\n  constructor(options: GadgetHookLifecycleOptions) {\n    this.iteration = options.iteration;\n    this.hooks = options.hooks;\n    this.logger = options.logger;\n    this.executor = options.executor;\n    this.tree = options.tree;\n    this.parentObservers = options.parentObservers;\n    this.dependencyResolver = options.dependencyResolver;\n  }\n\n  /**\n   * Execute a single gadget call through the full hook lifecycle.\n   *\n   * Yields a single gadget_result event (after all hooks complete).\n   * Modifies dependency resolver state as a side effect.\n   */\n  async *execute(call: ParsedGadgetCall): AsyncGenerator<StreamEvent> {\n    // Log parse errors if present (execution continues - errors are part of the result)\n    if (call.parseError) {\n      this.logger.warn(\"Gadget has parse error\", {\n        gadgetName: call.gadgetName,\n        error: call.parseError,\n        rawParameters: call.parametersRaw,\n      });\n    }\n\n    // Step 1: Interceptor - Transform parameters\n    let parameters = call.parameters ?? {};\n    if (this.hooks.interceptors?.interceptGadgetParameters) {\n      const context: GadgetParameterInterceptorContext = {\n        iteration: this.iteration,\n        gadgetName: call.gadgetName,\n        invocationId: call.invocationId,\n        logger: this.logger,\n      };\n      parameters = this.hooks.interceptors.interceptGadgetParameters(parameters, context);\n    }\n\n    // Update call with intercepted parameters\n    call.parameters = parameters;\n\n    // Update tree node with intercepted parameters (so observers see the modified values)\n    if (this.tree) {\n      this.tree.updateGadgetParameters(call.invocationId, parameters);\n    }\n\n    // Step 2: Controller - Before execution\n    let shouldSkip = false;\n    let syntheticResult: string | undefined;\n\n    if (this.hooks.controllers?.beforeGadgetExecution) {\n      const context: GadgetExecutionControllerContext = {\n        iteration: this.iteration,\n        gadgetName: call.gadgetName,\n        invocationId: call.invocationId,\n        parameters,\n        logger: this.logger,\n      };\n      const action: BeforeGadgetExecutionAction =\n        await this.hooks.controllers.beforeGadgetExecution(context);\n\n      // Validate the action\n      validateBeforeGadgetExecutionAction(action);\n\n      if (action.action === \"skip\") {\n        shouldSkip = true;\n        syntheticResult = action.syntheticResult;\n        this.logger.info(\"Controller skipped gadget execution\", {\n          gadgetName: call.gadgetName,\n        });\n      }\n    }\n\n    // Step 3: Mark gadget as running in tree\n    if (this.tree) {\n      const gadgetNode = this.tree.getNodeByInvocationId(call.invocationId);\n      if (gadgetNode) {\n        this.tree.startGadget(gadgetNode.id);\n      }\n    }\n\n    // Step 3b: Notify onGadgetExecutionStart observers (AWAITED for proper ordering)\n    await notifyGadgetStart({\n      tree: this.tree,\n      hooks: this.hooks.observers,\n      parentObservers: this.parentObservers,\n      logger: this.logger,\n      iteration: this.iteration,\n      gadgetName: call.gadgetName,\n      invocationId: call.invocationId,\n      parameters,\n    });\n\n    // Step 4: Execute or use synthetic result\n    let result: GadgetExecutionResult;\n    if (shouldSkip) {\n      result = {\n        gadgetName: call.gadgetName,\n        invocationId: call.invocationId,\n        parameters,\n        result: syntheticResult ?? \"Execution skipped\",\n        executionTimeMs: 0,\n      };\n    } else {\n      result = await this.executor.execute(call);\n    }\n\n    // Step 5: Interceptor - Transform result and/or error text\n    if ((result.result || result.error) && this.hooks.interceptors?.interceptGadgetResult) {\n      const context: GadgetResultInterceptorContext = {\n        iteration: this.iteration,\n        gadgetName: result.gadgetName,\n        invocationId: result.invocationId,\n        parameters,\n        executionTimeMs: result.executionTimeMs,\n        logger: this.logger,\n      };\n      if (result.result) {\n        result.result = this.hooks.interceptors.interceptGadgetResult(result.result, context);\n      }\n      if (result.error) {\n        result.error = this.hooks.interceptors.interceptGadgetResult(result.error, context);\n      }\n    }\n\n    // Step 6: Controller - After execution (can further modify result)\n    if (this.hooks.controllers?.afterGadgetExecution) {\n      const context: AfterGadgetExecutionControllerContext = {\n        iteration: this.iteration,\n        gadgetName: result.gadgetName,\n        invocationId: result.invocationId,\n        parameters,\n        result: result.result,\n        error: result.error,\n        executionTimeMs: result.executionTimeMs,\n        logger: this.logger,\n      };\n      const action: AfterGadgetExecutionAction =\n        await this.hooks.controllers.afterGadgetExecution(context);\n\n      // Validate the action\n      validateAfterGadgetExecutionAction(action);\n\n      if (action.action === \"recover\" && result.error) {\n        this.logger.info(\"Controller recovered from gadget error\", {\n          gadgetName: result.gadgetName,\n          originalError: result.error,\n        });\n        result = {\n          ...result,\n          error: undefined,\n          result: action.fallbackResult,\n        };\n      }\n    }\n\n    // Step 7: Complete gadget in tree\n    if (this.tree) {\n      const gadgetNode = this.tree.getNodeByInvocationId(result.invocationId);\n      if (gadgetNode) {\n        if (result.error) {\n          this.tree.completeGadget(gadgetNode.id, {\n            error: result.error,\n            executionTimeMs: result.executionTimeMs,\n            cost: result.cost,\n          });\n        } else {\n          this.tree.completeGadget(gadgetNode.id, {\n            result: result.result,\n            executionTimeMs: result.executionTimeMs,\n            cost: result.cost,\n            media: result.media,\n            storedMedia: result.storedMedia,\n          });\n        }\n      }\n    }\n\n    // Step 7b: Notify onGadgetExecutionComplete observers (AWAITED for proper ordering)\n    await notifyGadgetComplete({\n      tree: this.tree,\n      hooks: this.hooks.observers,\n      parentObservers: this.parentObservers,\n      logger: this.logger,\n      iteration: this.iteration,\n      gadgetName: result.gadgetName,\n      invocationId: result.invocationId,\n      parameters,\n      finalResult: result.result,\n      error: result.error,\n      executionTimeMs: result.executionTimeMs,\n      cost: result.cost,\n    });\n\n    // Track completion for dependency resolution\n    this.dependencyResolver.markComplete(result);\n\n    // Yield result event immediately\n    yield { type: \"gadget_result\", result };\n  }\n}\n","/**\n * GadgetLimitGuard: Enforces the maxGadgetsPerResponse limit.\n *\n * Extracted from StreamProcessor to provide a focused, testable module for\n * tracking how many gadgets have been started in a single LLM response and\n * emitting skip events when the limit is exceeded.\n *\n * Manages:\n * - `maxGadgetsPerResponse` threshold (0 = unlimited)\n * - `gadgetStartedCount` counter of gadgets admitted for execution\n * - `limitExceeded` flag used by StreamProcessor to break the chunk loop\n */\n\nimport type { ILogObj, Logger } from \"tslog\";\nimport type { ExecutionTree } from \"../core/execution-tree.js\";\nimport type { GadgetSkippedEvent, ParsedGadgetCall, StreamEvent } from \"../gadgets/types.js\";\nimport { createLogger } from \"../logging/logger.js\";\nimport type { Observers } from \"./hooks.js\";\nimport { notifyGadgetSkipped } from \"./observer-notifier.js\";\n\n/**\n * Options for constructing a GadgetLimitGuard.\n */\nexport interface GadgetLimitGuardOptions {\n  /** Maximum number of gadgets to admit per response. 0 = unlimited. */\n  maxGadgetsPerResponse: number;\n\n  /** Logger instance */\n  logger?: Logger<ILogObj>;\n}\n\n/**\n * GadgetLimitGuard: Tracks how many gadgets have been admitted for execution\n * within a single LLM response and enforces the configured limit.\n *\n * @example\n * ```typescript\n * const guard = new GadgetLimitGuard({ maxGadgetsPerResponse: 5 });\n *\n * // Before executing a gadget:\n * for await (const evt of guard.checkAndIncrement(call, { tree, hooks, ... })) {\n *   yield evt; // skip events if limit exceeded\n * }\n * if (guard.isLimitExceeded) {\n *   return; // skip execution\n * }\n * ```\n */\nexport class GadgetLimitGuard {\n  private readonly maxGadgetsPerResponse: number;\n  private readonly logger: Logger<ILogObj>;\n  private gadgetStartedCount = 0;\n  private _limitExceeded = false;\n\n  constructor(options: GadgetLimitGuardOptions) {\n    this.maxGadgetsPerResponse = options.maxGadgetsPerResponse;\n    this.logger = options.logger ?? createLogger({ name: \"llmist:gadget-limit-guard\" });\n  }\n\n  /**\n   * Whether the gadget limit has been exceeded in this response.\n   * When true, the stream loop should stop reading further chunks.\n   */\n  get isLimitExceeded(): boolean {\n    return this._limitExceeded;\n  }\n\n  /**\n   * Check whether this gadget call is within the response limit.\n   *\n   * - If no limit is configured (maxGadgetsPerResponse <= 0), always admits.\n   * - If the limit has already been reached, emits skip events and sets the\n   *   `isLimitExceeded` flag.\n   * - Otherwise, increments the counter and allows execution.\n   *\n   * The async generator yields zero or more StreamEvents (skip events when\n   * the limit is exceeded). When the generator returns, callers should check\n   * `guard.isLimitExceeded` to decide whether to proceed with execution.\n   *\n   * @param call - The parsed gadget call being evaluated\n   * @param ctx  - Observer/tree context needed to emit skip events\n   */\n  async *checkAndIncrement(\n    call: ParsedGadgetCall,\n    ctx: {\n      tree?: ExecutionTree;\n      hooks?: Observers;\n      parentObservers?: Observers;\n      iteration: number;\n      logger: Logger<ILogObj>;\n      /** Called when this specific call is skipped due to limit, before yielding the skip event */\n      markFailed?: (invocationId: string) => void;\n    },\n  ): AsyncGenerator<StreamEvent> {\n    // No limit configured — always admit\n    if (this.maxGadgetsPerResponse <= 0) {\n      this.gadgetStartedCount++;\n      return;\n    }\n\n    // Limit already reached — skip this gadget\n    if (this.gadgetStartedCount >= this.maxGadgetsPerResponse) {\n      const errorMessage = `Gadget limit (${this.maxGadgetsPerResponse}) exceeded. Consider calling fewer gadgets per response.`;\n\n      // Set flag to break stream loop - stops reading further chunks\n      this._limitExceeded = true;\n\n      this.logger.info(\"Gadget limit exceeded, stopping stream processing\", {\n        gadgetName: call.gadgetName,\n        invocationId: call.invocationId,\n        limit: this.maxGadgetsPerResponse,\n        currentCount: this.gadgetStartedCount,\n      });\n\n      // Mark skipped in execution tree\n      if (ctx.tree) {\n        const gadgetNode = ctx.tree.getNodeByInvocationId(call.invocationId);\n        if (gadgetNode) {\n          ctx.tree.skipGadget(\n            gadgetNode.id,\n            \"maxGadgetsPerResponse\",\n            errorMessage,\n            \"limit_exceeded\",\n          );\n        }\n      }\n\n      // Mark as failed in the dependency resolver (so dependents can be skipped)\n      ctx.markFailed?.(call.invocationId);\n\n      // Emit skip events\n      yield* this._emitSkipEvents(call, \"maxGadgetsPerResponse\", errorMessage, ctx);\n      return;\n    }\n\n    // Limit not exceeded — admit this gadget\n    this.gadgetStartedCount++;\n  }\n\n  // --------------------------------------------------------------------------\n  // Private helpers\n  // --------------------------------------------------------------------------\n\n  private async *_emitSkipEvents(\n    call: ParsedGadgetCall,\n    failedDep: string,\n    errorMessage: string,\n    ctx: {\n      tree?: ExecutionTree;\n      hooks?: Observers;\n      parentObservers?: Observers;\n      iteration: number;\n      logger: Logger<ILogObj>;\n    },\n  ): AsyncGenerator<StreamEvent> {\n    const skipEvent: GadgetSkippedEvent = {\n      type: \"gadget_skipped\",\n      gadgetName: call.gadgetName,\n      invocationId: call.invocationId,\n      parameters: call.parameters ?? {},\n      failedDependency: failedDep,\n      failedDependencyError: errorMessage,\n    };\n    yield skipEvent;\n\n    await notifyGadgetSkipped({\n      tree: ctx.tree,\n      hooks: ctx.hooks,\n      parentObservers: ctx.parentObservers,\n      logger: ctx.logger,\n      iteration: ctx.iteration,\n      gadgetName: call.gadgetName,\n      invocationId: call.invocationId,\n      parameters: call.parameters ?? {},\n      failedDependency: failedDep,\n      failedDependencyError: errorMessage,\n    });\n  }\n}\n","/**\n * StreamProcessor: The heart of the new hooks architecture.\n *\n * Replaces the complex wiring between Agent, ResponseProcessor, and GadgetRuntime.\n * Owns ALL stream processing and hook coordination with a clean, predictable flow.\n *\n * After refactoring, StreamProcessor is a thin orchestrator (~300 lines) that:\n * - Iterates over raw LLM stream chunks\n * - Applies raw-chunk and text-chunk interceptors\n * - Delegates gadget dispatch to GadgetDispatcher\n * - Yields events in real-time\n * - Applies the final assistant-message interceptor\n *\n * Extracted classes:\n * - GadgetLimitGuard     — maxGadgetsPerResponse enforcement\n * - GadgetHookLifecycle  — full hook sequence for a single gadget\n * - GadgetDispatcher     — dispatch decision tree + concurrency + dependency\n */\n\nimport type { ILogObj, Logger } from \"tslog\";\nimport type { LLMist } from \"../core/client.js\";\nimport type { ExecutionTree, NodeId } from \"../core/execution-tree.js\";\nimport type { LLMStreamChunk, TokenUsage } from \"../core/options.js\";\nimport type { RateLimitTracker } from \"../core/rate-limit.js\";\nimport type { ResolvedRetryConfig } from \"../core/retry.js\";\nimport { GadgetExecutor } from \"../gadgets/executor.js\";\nimport type { MediaStore } from \"../gadgets/media-store.js\";\nimport { GadgetCallParser } from \"../gadgets/parser.js\";\nimport type { GadgetRegistry } from \"../gadgets/registry.js\";\nimport type {\n  AgentContextConfig,\n  GadgetExecutionMode,\n  StreamCompletionEvent,\n  StreamEvent,\n  SubagentConfigMap,\n} from \"../gadgets/types.js\";\nimport { createLogger } from \"../logging/logger.js\";\nimport { GadgetConcurrencyManager } from \"./gadget-concurrency-manager.js\";\nimport { GadgetDependencyResolver } from \"./gadget-dependency-resolver.js\";\nimport { GadgetDispatcher } from \"./gadget-dispatcher.js\";\nimport { GadgetHookLifecycle } from \"./gadget-hook-lifecycle.js\";\nimport { GadgetLimitGuard } from \"./gadget-limit-guard.js\";\nimport type {\n  AgentHooks,\n  ChunkInterceptorContext,\n  MessageInterceptorContext,\n  ObserveChunkContext,\n  Observers,\n} from \"./hooks.js\";\nimport { notifyGadgetArgsPartial } from \"./observer-notifier.js\";\nimport { safeObserve } from \"./safe-observe.js\";\n// NOTE: Gadget observer hooks (onGadgetExecutionStart, onGadgetExecutionComplete,\n// onGadgetSkipped) are called DIRECTLY here (awaited) to ensure proper ordering.\n// This guarantees that observer commands complete before gadget execution continues.\n\n/**\n * Configuration for the StreamProcessor.\n */\nexport interface StreamProcessorOptions {\n  /** Current iteration number */\n  iteration: number;\n\n  /** Gadget registry for execution */\n  registry: GadgetRegistry;\n\n  /** Custom gadget start prefix */\n  gadgetStartPrefix?: string;\n\n  /** Custom gadget end prefix */\n  gadgetEndPrefix?: string;\n\n  /** Custom argument prefix for block format */\n  gadgetArgPrefix?: string;\n\n  /** Hooks for lifecycle events */\n  hooks?: AgentHooks;\n\n  /** Logger instance */\n  logger?: Logger<ILogObj>;\n\n  /** Callback for requesting human input during execution */\n  requestHumanInput?: (question: string) => Promise<string>;\n\n  /** Default gadget timeout */\n  defaultGadgetTimeoutMs?: number;\n\n  /** Maximum time (ms) to wait for in-flight gadgets to complete. Default: 300s. */\n  inFlightTimeoutMs?: number;\n\n  /** Gadget execution mode ('parallel' | 'sequential') */\n  gadgetExecutionMode?: GadgetExecutionMode;\n\n  /** LLMist client for ExecutionContext.llmist */\n  client?: LLMist;\n\n  /** MediaStore for storing gadget media outputs */\n  mediaStore?: MediaStore;\n\n  /** Parent agent configuration for subagents to inherit */\n  agentConfig?: AgentContextConfig;\n\n  /** Subagent-specific configuration overrides */\n  subagentConfig?: SubagentConfigMap;\n\n  // ==========================================================================\n  // Execution Tree Context (for tree-based tracking)\n  // ==========================================================================\n\n  /** Execution tree for tracking LLM calls and gadget executions */\n  tree?: ExecutionTree;\n\n  /** Parent node ID (for gadget nodes created by this processor) */\n  parentNodeId?: NodeId | null;\n\n  /** Base depth for nodes created by this processor */\n  baseDepth?: number;\n\n  // ==========================================================================\n  // Cross-Iteration Dependency Resolution\n  // ==========================================================================\n\n  /**\n   * Set of invocation IDs that completed in previous iterations.\n   * Used to resolve dependencies on gadgets from prior LLM responses.\n   */\n  priorCompletedInvocations?: Set<string>;\n\n  /**\n   * Set of invocation IDs that failed in previous iterations.\n   * Used to skip gadgets that depend on previously-failed gadgets.\n   */\n  priorFailedInvocations?: Set<string>;\n\n  // ==========================================================================\n  // Parent Observer Hooks (for subagent visibility)\n  // ==========================================================================\n\n  /**\n   * Parent agent's observer hooks for subagent visibility.\n   *\n   * When a subagent is created with withParentContext(ctx), these observers\n   * are also called for gadget events (in addition to the subagent's own hooks),\n   * enabling the parent to observe subagent gadget activity.\n   */\n  parentObservers?: Observers;\n\n  // ==========================================================================\n  // Rate Limiting & Retry (shared across subagents)\n  // ==========================================================================\n\n  /** Shared rate limit tracker for coordinated throttling across subagents */\n  rateLimitTracker?: RateLimitTracker;\n\n  /** Shared retry config for consistent backoff behavior across subagents */\n  retryConfig?: ResolvedRetryConfig;\n\n  /** Maximum gadgets to execute per response (0 = unlimited) */\n  maxGadgetsPerResponse?: number;\n}\n\n/**\n * Result of stream processing.\n *\n * @deprecated StreamProcessor.process() is now an async generator that yields\n * StreamEvent items directly. Use StreamCompletionEvent (the final yielded event)\n * to obtain the metadata formerly returned in this type. This interface is retained\n * for backward compatibility but is not used internally.\n */\nexport interface StreamProcessingResult {\n  /** All emitted events */\n  outputs: StreamEvent[];\n\n  /** Whether the loop should break */\n  shouldBreakLoop: boolean;\n\n  /** Whether any gadgets were executed */\n  didExecuteGadgets: boolean;\n\n  /** LLM finish reason */\n  finishReason: string | null;\n\n  /** Token usage (including cached token counts when available) */\n  usage?: TokenUsage;\n\n  /** The raw accumulated response text */\n  rawResponse: string;\n\n  /** The final message (after interceptors) */\n  finalMessage: string;\n}\n\n/**\n * StreamProcessor: Thin orchestrator for stream processing and hook coordination.\n *\n * Execution order:\n * 1. Raw chunk arrives from LLM\n * 2. Interceptor: interceptRawChunk (transform raw text)\n * 3. Observer: onStreamChunk (logging)\n * 4. Parse for gadgets\n * 5. If gadget found → delegate to GadgetDispatcher\n * 6. If text chunk:\n *    a. Interceptor: interceptTextChunk (transform display text)\n *    b. Yield to user\n * 7. Stream complete\n * 8. Interceptor: interceptAssistantMessage (transform final message)\n */\nexport class StreamProcessor {\n  private readonly iteration: number;\n  private readonly hooks: AgentHooks;\n  private readonly logger: Logger<ILogObj>;\n  private readonly parser: GadgetCallParser;\n\n  // Execution Tree context\n  private readonly tree?: ExecutionTree;\n  /** LLM-call node these gadgets hang off; used to derive subagentContext for partials. */\n  private readonly parentNodeId?: NodeId | null;\n  /** Parent agent observers (subagent visibility) — also notified for arg partials. */\n  private readonly parentObservers?: Observers;\n\n  private responseText = \"\";\n\n  // Dependency resolution is delegated to GadgetDependencyResolver\n  private readonly dependencyResolver: GadgetDependencyResolver;\n\n  /** Queue of completed gadget results ready to be yielded (for real-time streaming) */\n  private completedResultsQueue: StreamEvent[] = [];\n\n  // Extracted orchestrators\n  private readonly dispatcher: GadgetDispatcher;\n  private readonly limitGuard: GadgetLimitGuard;\n\n  constructor(options: StreamProcessorOptions) {\n    this.iteration = options.iteration;\n    this.hooks = options.hooks ?? {};\n    this.logger = options.logger ?? createLogger({ name: \"llmist:stream-processor\" });\n\n    // Initialize tree context\n    this.tree = options.tree;\n    this.parentNodeId = options.parentNodeId;\n    this.parentObservers = options.parentObservers;\n\n    // Initialize dependency resolver with cross-iteration state\n    this.dependencyResolver = new GadgetDependencyResolver({\n      priorCompletedInvocations: options.priorCompletedInvocations,\n      priorFailedInvocations: options.priorFailedInvocations,\n    });\n\n    // Initialize concurrency manager (delegates all concurrency state/logic)\n    const concurrencyManager = new GadgetConcurrencyManager({\n      registry: options.registry,\n      subagentConfig: options.subagentConfig,\n      logger: this.logger.getSubLogger({ name: \"concurrency\" }),\n    });\n\n    // Initialize gadget limiting (0 = unlimited)\n    this.limitGuard = new GadgetLimitGuard({\n      maxGadgetsPerResponse: options.maxGadgetsPerResponse ?? 0,\n      logger: this.logger.getSubLogger({ name: \"limit-guard\" }),\n    });\n\n    this.parser = new GadgetCallParser({\n      startPrefix: options.gadgetStartPrefix,\n      endPrefix: options.gadgetEndPrefix,\n      argPrefix: options.gadgetArgPrefix,\n    });\n\n    const executor = new GadgetExecutor({\n      registry: options.registry,\n      requestHumanInput: options.requestHumanInput,\n      logger: this.logger.getSubLogger({ name: \"executor\" }),\n      defaultGadgetTimeoutMs: options.defaultGadgetTimeoutMs,\n      errorFormatterOptions: { argPrefix: options.gadgetArgPrefix },\n      client: options.client,\n      mediaStore: options.mediaStore,\n      agentConfig: options.agentConfig,\n      subagentConfig: options.subagentConfig,\n      // Tree context for gadget execution\n      tree: options.tree,\n      parentNodeId: options.parentNodeId,\n      baseDepth: options.baseDepth,\n      // Parent observer hooks for subagent visibility\n      parentObservers: options.parentObservers,\n      // Current agent's observers for subagent inheritance\n      currentObservers: options.hooks?.observers,\n      // Shared rate limit tracker for coordinated throttling across subagents\n      rateLimitTracker: options.rateLimitTracker,\n      // Shared retry config for consistent backoff behavior across subagents\n      retryConfig: options.retryConfig,\n    });\n\n    const hookLifecycle = new GadgetHookLifecycle({\n      iteration: options.iteration,\n      hooks: this.hooks,\n      logger: this.logger,\n      executor,\n      tree: options.tree,\n      parentObservers: options.parentObservers,\n      dependencyResolver: this.dependencyResolver,\n    });\n\n    this.dispatcher = new GadgetDispatcher({\n      iteration: options.iteration,\n      hookLifecycle,\n      dependencyResolver: this.dependencyResolver,\n      concurrencyManager,\n      limitGuard: this.limitGuard,\n      gadgetExecutionMode: options.gadgetExecutionMode ?? \"parallel\",\n      tree: options.tree,\n      parentNodeId: options.parentNodeId,\n      hooks: this.hooks,\n      parentObservers: options.parentObservers,\n      logger: this.logger.getSubLogger({ name: \"dispatcher\" }),\n      pushToQueue: (evt) => this.completedResultsQueue.push(evt),\n      drainQueue: () => {\n        const evts = [...this.completedResultsQueue];\n        this.completedResultsQueue = [];\n        return evts;\n      },\n      inFlightTimeoutMs: options.inFlightTimeoutMs,\n    });\n  }\n\n  /**\n   * Process an LLM stream and yield events in real-time.\n   *\n   * This is an async generator that yields events immediately as they occur:\n   * - Text events are yielded as text is streamed from the LLM\n   * - gadget_call events are yielded immediately when a gadget call is parsed\n   * - gadget_result events are yielded when gadget execution completes\n   *\n   * The final event is always a StreamCompletionEvent containing metadata.\n   */\n  async *process(stream: AsyncIterable<LLMStreamChunk>): AsyncGenerator<StreamEvent> {\n    let finishReason: string | null = null;\n    let usage: TokenUsage | undefined;\n    let thinkingContent = \"\";\n\n    // Mutable state for gadget result tracking (passed to trackGadgetResult helper)\n    const state = { didExecuteGadgets: false, shouldBreakLoop: false };\n\n    // Process stream chunks\n    for await (const chunk of stream) {\n      // Capture metadata\n      if (chunk.finishReason) finishReason = chunk.finishReason;\n      if (chunk.usage) usage = chunk.usage;\n\n      // Emit thinking content as a thinking event\n      if (chunk.thinking?.content) {\n        thinkingContent += chunk.thinking.content;\n        yield {\n          type: \"thinking\",\n          content: chunk.thinking.content,\n          thinkingType: chunk.thinking.type,\n        };\n      }\n\n      // Process text content if present\n      let processedChunk = \"\";\n      if (chunk.text) {\n        // Step 1: Interceptor - Transform raw chunk\n        processedChunk = chunk.text;\n        if (this.hooks.interceptors?.interceptRawChunk) {\n          const context: ChunkInterceptorContext = {\n            iteration: this.iteration,\n            accumulatedText: this.responseText,\n            logger: this.logger,\n          };\n          const intercepted = this.hooks.interceptors.interceptRawChunk(processedChunk, context);\n          if (intercepted === null) {\n            // Chunk suppressed\n            processedChunk = \"\";\n          } else {\n            processedChunk = intercepted;\n          }\n        }\n\n        // Accumulate text\n        if (processedChunk) {\n          this.responseText += processedChunk;\n        }\n      }\n\n      // Step 2: Observer - Observe chunk (called for text OR usage updates)\n      if (this.hooks.observers?.onStreamChunk && (processedChunk || chunk.usage)) {\n        const chunkObservers: Array<() => void | Promise<void>> = [];\n        chunkObservers.push(async () => {\n          const context: ObserveChunkContext = {\n            iteration: this.iteration,\n            rawChunk: processedChunk,\n            accumulatedText: this.responseText,\n            usage,\n            logger: this.logger,\n          };\n          await this.hooks.observers?.onStreamChunk?.(context);\n        });\n        await this.runObserversInParallel(chunkObservers);\n      }\n\n      // Skip further processing if no text\n      if (!processedChunk) {\n        continue;\n      }\n\n      // Step 3: Parse and process events - yield immediately\n      for (const event of this.parser.feed(processedChunk)) {\n        for await (const processedEvent of this.processEventGenerator(event)) {\n          yield processedEvent;\n\n          // Track gadget execution\n          this.trackGadgetResult(processedEvent, state);\n        }\n      }\n\n      // Step 4: Drain completed parallel gadget results (real-time streaming)\n      // This yields results from gadgets that completed during this chunk processing\n      for (const evt of this.drainCompletedResults()) {\n        yield evt;\n\n        this.trackGadgetResult(evt, state);\n      }\n\n      // Step 5: Break stream loop if gadget limit exceeded\n      // This stops reading further chunks, letting in-flight gadgets complete\n      // and allowing the agent to continue to the next iteration\n      if (this.limitGuard.isLimitExceeded) {\n        this.logger.info(\"Breaking stream loop due to gadget limit\");\n        break;\n      }\n    }\n\n    // Signal that LLM response is complete (tokens stopped flowing)\n    // This fires BEFORE gadget execution finishes, allowing consumers to track\n    // \"LLM thinking time\" separately from gadget execution time\n    yield { type: \"llm_response_end\", finishReason, usage } as StreamEvent;\n\n    // Finalize parsing\n    for (const event of this.parser.finalize()) {\n      for await (const processedEvent of this.processEventGenerator(event)) {\n        yield processedEvent;\n\n        this.trackGadgetResult(processedEvent, state);\n      }\n    }\n\n    // Wait for all in-flight parallel gadgets to complete, yielding events in real-time\n    // This enables subagent events to be displayed during long-running gadget execution\n    for await (const evt of this.dispatcher.waitForInFlightExecutions()) {\n      yield evt;\n\n      this.trackGadgetResult(evt, state);\n    }\n\n    // Drain any remaining completed results (stragglers that finished after final poll)\n    for (const evt of this.drainCompletedResults()) {\n      yield evt;\n\n      this.trackGadgetResult(evt, state);\n    }\n\n    // Final pass to process any remaining pending gadgets\n    // This handles cases where the last gadgets in the stream have dependencies\n    // (now that in-flight gadgets have completed, their dependents can execute)\n    for await (const evt of this.dispatcher.processPendingGadgets()) {\n      yield evt;\n\n      this.trackGadgetResult(evt, state);\n    }\n\n    // Step 4: Interceptor - Transform final message\n    let finalMessage = this.responseText;\n    if (this.hooks.interceptors?.interceptAssistantMessage) {\n      const context: MessageInterceptorContext = {\n        iteration: this.iteration,\n        rawResponse: this.responseText,\n        logger: this.logger,\n      };\n      finalMessage = this.hooks.interceptors.interceptAssistantMessage(finalMessage, context);\n    }\n\n    // Yield completion event with all metadata\n    const completionEvent: StreamCompletionEvent = {\n      type: \"stream_complete\",\n      shouldBreakLoop: state.shouldBreakLoop,\n      didExecuteGadgets: state.didExecuteGadgets,\n      finishReason,\n      usage,\n      rawResponse: this.responseText,\n      finalMessage,\n      thinkingContent: thinkingContent || undefined,\n    };\n    yield completionEvent;\n  }\n\n  /**\n   * Process a single parsed event, yielding events in real-time.\n   */\n  private async *processEventGenerator(event: StreamEvent): AsyncGenerator<StreamEvent> {\n    if (event.type === \"text\") {\n      // processTextEvent is async - need to await the result before iterating\n      for (const e of await this.processTextEvent(event)) {\n        yield e;\n      }\n    } else if (event.type === \"gadget_call\") {\n      for await (const e of this.dispatcher.dispatch(event.call)) {\n        yield e;\n      }\n    } else if (event.type === \"gadget_args_partial\") {\n      // Fire the observer (errors isolated) before yielding the partial downstream.\n      // No tree node exists yet, so subagentContext is derived from parentNodeId.\n      await notifyGadgetArgsPartial({\n        tree: this.tree,\n        hooks: this.hooks.observers,\n        parentObservers: this.parentObservers,\n        logger: this.logger,\n        iteration: this.iteration,\n        parentNodeId: this.parentNodeId,\n        event,\n      });\n      yield event;\n    } else {\n      yield event;\n    }\n  }\n\n  /**\n   * Process a text event through interceptors.\n   */\n  private async processTextEvent(event: { type: \"text\"; content: string }): Promise<StreamEvent[]> {\n    let content = event.content;\n\n    // Interceptor: Transform text chunk\n    if (this.hooks.interceptors?.interceptTextChunk) {\n      const context: ChunkInterceptorContext = {\n        iteration: this.iteration,\n        accumulatedText: this.responseText,\n        logger: this.logger,\n      };\n      const intercepted = this.hooks.interceptors.interceptTextChunk(content, context);\n      if (intercepted === null) {\n        // Chunk suppressed\n        return [];\n      }\n      content = intercepted;\n    }\n\n    return [{ type: \"text\", content }];\n  }\n\n  /**\n   * Drain all completed results from the queue.\n   * Used to yield results as they complete during stream processing.\n   * @returns Generator that yields all events currently in the queue\n   */\n  private *drainCompletedResults(): Generator<StreamEvent> {\n    while (this.completedResultsQueue.length > 0) {\n      yield this.completedResultsQueue.shift()!;\n    }\n  }\n\n  /**\n   * Update gadget result tracking flags based on a stream event.\n   * Checks if the event is a gadget_result and, if so, marks gadgets as executed\n   * and sets the break-loop flag when the result requests it.\n   *\n   * @param evt - The stream event to inspect\n   * @param state - Mutable state object holding the tracking flags\n   */\n  private trackGadgetResult(\n    evt: StreamEvent,\n    state: { didExecuteGadgets: boolean; shouldBreakLoop: boolean },\n  ): void {\n    if (evt.type === \"gadget_result\") {\n      state.didExecuteGadgets = true;\n      if (evt.result.breaksLoop) {\n        state.shouldBreakLoop = true;\n      }\n    }\n  }\n\n  /**\n   * Execute multiple observers in parallel.\n   * All observers run concurrently and failures are tracked but don't crash.\n   */\n  private async runObserversInParallel(\n    observers: Array<() => void | Promise<void>>,\n  ): Promise<void> {\n    if (observers.length === 0) return;\n\n    // Run all observers in parallel, waiting for completion\n    // Errors are logged in safeObserve, no need to handle rejected promises\n    await Promise.allSettled(observers.map((observer) => safeObserve(observer, this.logger)));\n  }\n\n  // ==========================================================================\n  // Public accessors for cross-iteration dependency tracking\n  // ==========================================================================\n\n  /**\n   * Get all invocation IDs that completed successfully in this iteration.\n   * Used by Agent to accumulate completed IDs across iterations.\n   */\n  getCompletedInvocationIds(): Set<string> {\n    return this.dependencyResolver.getCompletedInvocationIds();\n  }\n\n  /**\n   * Get all invocation IDs that failed in this iteration.\n   * Used by Agent to accumulate failed IDs across iterations.\n   */\n  getFailedInvocationIds(): Set<string> {\n    return this.dependencyResolver.getFailedInvocationIds();\n  }\n}\n","/**\n * StreamProcessorFactory: Encapsulates all configuration needed to construct StreamProcessor\n * instances, eliminating ~15 pass-through fields from the Agent class.\n *\n * ## Motivation\n *\n * Agent previously stored many fields that existed only to be forwarded to StreamProcessor\n * on each iteration. By extracting this construction logic into a dedicated factory, the\n * Agent's constructor and field count are significantly reduced.\n *\n * ## Design\n *\n * - Holds all static (per-agent) StreamProcessor configuration\n * - `create(iteration, llmNodeId, crossIterationState)` creates a StreamProcessor for one iteration\n * - Cross-iteration mutable state (completedInvocationIds, failedInvocationIds) is passed\n *   per-call rather than stored, keeping factory instances immutable\n * - Follows the LLMCallLifecycle extraction pattern\n *\n * @module agent/stream-processor-factory\n */\n\nimport type { ILogObj, Logger } from \"tslog\";\nimport type { LLMist } from \"../core/client.js\";\nimport type { ExecutionTree, NodeId } from \"../core/execution-tree.js\";\nimport type { RateLimitTracker } from \"../core/rate-limit.js\";\nimport type { ResolvedRetryConfig } from \"../core/retry.js\";\nimport type { MediaStore } from \"../gadgets/media-store.js\";\nimport type { GadgetRegistry } from \"../gadgets/registry.js\";\nimport type {\n  AgentContextConfig,\n  GadgetExecutionMode,\n  SubagentConfigMap,\n} from \"../gadgets/types.js\";\nimport type { PrefixConfig } from \"./agent.js\";\nimport type { AgentHooks, Observers } from \"./hooks.js\";\nimport { StreamProcessor } from \"./stream-processor.js\";\n\n// ============================================================================\n// Constructor options\n// ============================================================================\n\n/**\n * Options for constructing a StreamProcessorFactory.\n *\n * These are all static (per-agent-lifetime) configuration values that do not\n * change between iterations. Cross-iteration mutable state is passed to `create()`.\n */\nexport interface StreamProcessorFactoryOptions {\n  /** Gadget registry for execution */\n  registry: GadgetRegistry;\n\n  /** Custom gadget block format prefixes */\n  prefixConfig?: PrefixConfig;\n\n  /** Agent hooks (observers, interceptors, controllers) */\n  hooks: AgentHooks;\n\n  /** Logger instance (factory creates a sub-logger for each processor) */\n  logger: Logger<ILogObj>;\n\n  /** Callback for requesting human input during execution */\n  requestHumanInput?: (question: string) => Promise<string>;\n\n  /** Default gadget timeout in milliseconds */\n  defaultGadgetTimeoutMs?: number;\n\n  /** Maximum time (ms) to wait for in-flight gadgets to complete. Default: 300s. */\n  inFlightTimeoutMs?: number;\n\n  /** Gadget execution mode: 'parallel' (default) or 'sequential' */\n  gadgetExecutionMode: GadgetExecutionMode;\n\n  /** LLMist client for gadget execution contexts */\n  client: LLMist;\n\n  /** MediaStore for storing gadget media outputs */\n  mediaStore: MediaStore;\n\n  /** Parent agent configuration for subagents to inherit */\n  agentContextConfig: AgentContextConfig;\n\n  /** Subagent-specific configuration overrides */\n  subagentConfig?: SubagentConfigMap;\n\n  /** Execution tree for tracking LLM calls and gadget executions */\n  tree: ExecutionTree;\n\n  /** Base depth for nodes created by this agent's processors */\n  baseDepth: number;\n\n  /** Parent agent's observer hooks for subagent visibility */\n  parentObservers?: Observers;\n\n  /** Shared rate limit tracker for coordinated throttling across subagents */\n  rateLimitTracker?: RateLimitTracker;\n\n  /** Shared retry config for consistent backoff behavior across subagents */\n  retryConfig: ResolvedRetryConfig;\n\n  /** Maximum gadgets to execute per LLM response (0 = unlimited) */\n  maxGadgetsPerResponse: number;\n}\n\n/**\n * Cross-iteration mutable state passed to `create()` on each invocation.\n * These values change between iterations and cannot be stored on the factory.\n */\nexport interface StreamProcessorCrossIterationState {\n  /** Invocation IDs that completed successfully in prior iterations */\n  priorCompletedInvocations: Set<string>;\n\n  /** Invocation IDs that failed in prior iterations */\n  priorFailedInvocations: Set<string>;\n}\n\n// ============================================================================\n// StreamProcessorFactory\n// ============================================================================\n\n/**\n * StreamProcessorFactory: Stateless factory for constructing StreamProcessor instances.\n *\n * Holds all static per-agent StreamProcessor configuration and constructs a new\n * StreamProcessor for each agent iteration via `create()`.\n *\n * @example\n * ```typescript\n * const factory = new StreamProcessorFactory({\n *   registry, hooks, logger, client, mediaStore, ...\n * });\n *\n * // In agent loop:\n * const processor = factory.create(iteration, llmNodeId, {\n *   priorCompletedInvocations: this.completedInvocationIds,\n *   priorFailedInvocations: this.failedInvocationIds,\n * });\n * ```\n */\nexport class StreamProcessorFactory {\n  private readonly registry: GadgetRegistry;\n  private readonly prefixConfig?: PrefixConfig;\n  private readonly hooks: AgentHooks;\n  private readonly logger: Logger<ILogObj>;\n  private readonly requestHumanInput?: (question: string) => Promise<string>;\n  private readonly defaultGadgetTimeoutMs?: number;\n  private readonly inFlightTimeoutMs?: number;\n  private readonly gadgetExecutionMode: GadgetExecutionMode;\n  private readonly client: LLMist;\n  private readonly mediaStore: MediaStore;\n  private readonly agentContextConfig: AgentContextConfig;\n  private readonly subagentConfig?: SubagentConfigMap;\n  private readonly tree: ExecutionTree;\n  private readonly baseDepth: number;\n  private readonly parentObservers?: Observers;\n  private readonly rateLimitTracker?: RateLimitTracker;\n  private readonly retryConfig: ResolvedRetryConfig;\n  private readonly maxGadgetsPerResponse: number;\n\n  constructor(options: StreamProcessorFactoryOptions) {\n    this.registry = options.registry;\n    this.prefixConfig = options.prefixConfig;\n    this.hooks = options.hooks;\n    this.logger = options.logger;\n    this.requestHumanInput = options.requestHumanInput;\n    this.defaultGadgetTimeoutMs = options.defaultGadgetTimeoutMs;\n    this.inFlightTimeoutMs = options.inFlightTimeoutMs;\n    this.gadgetExecutionMode = options.gadgetExecutionMode;\n    this.client = options.client;\n    this.mediaStore = options.mediaStore;\n    this.agentContextConfig = options.agentContextConfig;\n    this.subagentConfig = options.subagentConfig;\n    this.tree = options.tree;\n    this.baseDepth = options.baseDepth;\n    this.parentObservers = options.parentObservers;\n    this.rateLimitTracker = options.rateLimitTracker;\n    this.retryConfig = options.retryConfig;\n    this.maxGadgetsPerResponse = options.maxGadgetsPerResponse;\n  }\n\n  /**\n   * Construct a StreamProcessor configured for a single agent iteration.\n   *\n   * @param iteration - Current iteration number\n   * @param llmNodeId - The LLM call node ID (gadgets are children of this node)\n   * @param crossIterationState - Mutable dependency-tracking sets from the agent loop\n   * @returns A fully configured StreamProcessor ready to process an LLM stream\n   */\n  create(\n    iteration: number,\n    llmNodeId: NodeId,\n    crossIterationState: StreamProcessorCrossIterationState,\n  ): StreamProcessor {\n    return new StreamProcessor({\n      iteration,\n      registry: this.registry,\n      gadgetStartPrefix: this.prefixConfig?.gadgetStartPrefix,\n      gadgetEndPrefix: this.prefixConfig?.gadgetEndPrefix,\n      gadgetArgPrefix: this.prefixConfig?.gadgetArgPrefix,\n      hooks: this.hooks,\n      logger: this.logger.getSubLogger({ name: \"stream-processor\" }),\n      requestHumanInput: this.requestHumanInput,\n      defaultGadgetTimeoutMs: this.defaultGadgetTimeoutMs,\n      inFlightTimeoutMs: this.inFlightTimeoutMs,\n      gadgetExecutionMode: this.gadgetExecutionMode,\n      client: this.client,\n      mediaStore: this.mediaStore,\n      agentConfig: this.agentContextConfig,\n      subagentConfig: this.subagentConfig,\n      // Tree context for execution tracking\n      tree: this.tree,\n      parentNodeId: llmNodeId, // Gadgets are children of this LLM call\n      baseDepth: this.baseDepth,\n      // Cross-iteration dependency tracking\n      priorCompletedInvocations: crossIterationState.priorCompletedInvocations,\n      priorFailedInvocations: crossIterationState.priorFailedInvocations,\n      // Parent observer hooks for subagent visibility\n      parentObservers: this.parentObservers,\n      // Shared rate limit tracker and retry config for subagents\n      rateLimitTracker: this.rateLimitTracker,\n      retryConfig: this.retryConfig,\n      // Gadget limiting\n      maxGadgetsPerResponse: this.maxGadgetsPerResponse,\n    });\n  }\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 * Deterministic multi-server tool name conflict resolution.\n *\n * When two or more MCP servers expose tools with the same name, llmist\n * prefixes those servers' tools with `<server>__`. The check is per-tool-name:\n * any name that appears on more than one server triggers prefixing on every\n * server that owns the colliding name. To keep the gadget naming uniform\n * within a server, all tools on a server with at least one collision get the\n * prefix.\n *\n * This shape matches the convention used by every major MCP-aware framework\n * (LangChain, OpenAI Agents SDK, Cline) — divergence buys nothing.\n *\n * @module mcp/multi-server\n */\n\nimport type { McpServerSpec, McpToolDescriptor } from \"./types.js\";\n\nexport interface ServerToolList {\n  server: McpServerSpec;\n  tools: McpToolDescriptor[];\n}\n\nexport interface ResolvedServerToolList extends ServerToolList {\n  /** Prefix applied to each tool of this server (e.g. \"fs__\"). undefined when no collision. */\n  prefix: string | undefined;\n}\n\nexport function resolveToolNames(input: ServerToolList[]): ResolvedServerToolList[] {\n  // Count occurrences of each tool name across servers.\n  const counts = new Map<string, number>();\n  for (const s of input) {\n    for (const t of s.tools) {\n      counts.set(t.name, (counts.get(t.name) ?? 0) + 1);\n    }\n  }\n\n  // Determine which servers have at least one colliding tool.\n  const collidingServers = new Set<string>();\n  for (const s of input) {\n    if (s.tools.some((t) => (counts.get(t.name) ?? 0) > 1)) {\n      collidingServers.add(s.server.name);\n    }\n  }\n\n  return input.map((s) => ({\n    ...s,\n    prefix: collidingServers.has(s.server.name) ? `${s.server.name}__` : undefined,\n  }));\n}\n","/**\n * Adapter that wraps an MCP prompt descriptor as an llmist Skill-shaped\n * artifact, so MCP prompts compose with the existing skill subsystem\n * (slash invocation, skill registry, load-skill meta-gadget).\n *\n * The shape returned mirrors the public surface of `Skill` that llmist\n * consumers use (name, description, getInstructions, invocable flags),\n * plus a `mcpArguments` field for MCP-specific argument metadata.\n *\n * @module mcp/prompt-adapter\n */\n\nimport type { McpClient } from \"./client.js\";\nimport type { McpContentBlock, McpPromptArgument, McpPromptDescriptor } from \"./types.js\";\n\nexport interface McpPromptSkillOptions {\n  /** Prefix prepended to the skill name. Used for multi-server name conflict resolution. */\n  prefix?: string;\n}\n\nexport interface McpPromptSkillMetadata {\n  name: string;\n  description: string;\n  arguments?: McpPromptArgument[];\n}\n\nexport class McpPromptSkill {\n  readonly name: string;\n  readonly description: string;\n  readonly metadata: McpPromptSkillMetadata;\n  readonly isUserInvocable: boolean = true;\n  readonly isModelInvocable: boolean = true;\n\n  private readonly client: McpClient;\n  private readonly mcpToolName: string;\n\n  constructor(descriptor: McpPromptDescriptor, client: McpClient, opts?: McpPromptSkillOptions) {\n    const prefix = opts?.prefix ?? \"\";\n    this.name = prefix + descriptor.name;\n    this.description =\n      descriptor.description ??\n      `MCP prompt \"${descriptor.name}\" from server \"${client.serverName}\"`;\n    this.metadata = {\n      name: this.name,\n      description: this.description,\n      ...(descriptor.arguments ? { arguments: descriptor.arguments } : {}),\n    };\n    this.client = client;\n    this.mcpToolName = descriptor.name;\n  }\n\n  /**\n   * Render the prompt by calling the MCP server's prompts/get with the\n   * supplied arguments and joining the resulting message text.\n   */\n  async getInstructions(args?: Record<string, unknown>): Promise<string> {\n    const result = await this.client.getPrompt(this.mcpToolName, args ?? {});\n    const parts: string[] = [];\n    for (const m of result.messages) {\n      const c = m.content as McpContentBlock;\n      if (c.type === \"text\" && typeof (c as { text?: unknown }).text === \"string\") {\n        parts.push((c as { text: string }).text);\n      } else {\n        try {\n          parts.push(JSON.stringify(c));\n        } catch {\n          parts.push(String(c));\n        }\n      }\n    }\n    return parts.join(\"\\n\");\n  }\n}\n\nexport function mcpPromptToSkill(\n  descriptor: McpPromptDescriptor,\n  client: McpClient,\n  opts?: McpPromptSkillOptions,\n): McpPromptSkill {\n  return new McpPromptSkill(descriptor, client, opts);\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","/**\n * Runtime orchestration for MCP-attached agents. This file is dynamic-imported\n * by Agent.run() only when at least one MCP server is configured, so agents\n * that don't use MCP never load the SDK.\n *\n * @module mcp/runtime\n */\n\nimport type { ILogObj, Logger } from \"tslog\";\nimport type { PrefixConfig } from \"../agent/agent.js\";\nimport type { ConversationManager } from \"../agent/conversation-manager.js\";\nimport { LLMMessageBuilder } from \"../core/messages.js\";\nimport type { GadgetRegistry } from \"../gadgets/registry.js\";\nimport { McpClient } from \"./client.js\";\nimport { McpLifecycle } from \"./lifecycle.js\";\nimport { resolveToolNames, type ServerToolList } from \"./multi-server.js\";\nimport { type McpPromptSkill, mcpPromptToSkill } from \"./prompt-adapter.js\";\nimport { mcpToolToGadget } from \"./tool-adapter.js\";\nimport type { McpServerSpec } from \"./types.js\";\n\nexport interface SetupMcpServersOptions {\n  specs: McpServerSpec[];\n  registry: GadgetRegistry;\n  conversation: ConversationManager;\n  prefixConfig?: PrefixConfig;\n  systemPrompt?: string;\n  logger: Logger<ILogObj>;\n  /** Receives discovered MCP prompts as skill-shaped artifacts for slash invocation. */\n  onPromptDiscovered?: (skill: McpPromptSkill) => void;\n}\n\n/**\n * Setup MCP servers attached to an agent.\n *\n * - Connects each server in parallel.\n * - Lists tools and registers them as adapter gadgets in the agent's registry.\n * - Rebuilds the conversation's base (system + gadget catalog) messages so\n *   the LLM sees the full effective gadget set.\n *\n * Returns an `McpLifecycle` instance the caller must close at agent teardown.\n *\n * If a server fails to connect, the failure is logged and that server is\n * skipped — the agent continues with whatever servers connected\n * successfully. (Plan 2 will polish this with hook-driven error events.)\n */\nexport async function setupMcpServers(opts: SetupMcpServersOptions): Promise<McpLifecycle> {\n  const { specs, registry, conversation, prefixConfig, systemPrompt, logger, onPromptDiscovered } =\n    opts;\n\n  const lifecycle = new McpLifecycle();\n  lifecycle.installSignalHandlers();\n\n  // Phase 1: connect every server in parallel, list its tools.\n  type ConnectedServer = { client: McpClient; serverToolList: ServerToolList };\n  const connected: ConnectedServer[] = [];\n\n  await Promise.all(\n    specs.map(async (spec) => {\n      const client = new McpClient(spec);\n      try {\n        await client.connect();\n      } catch (err) {\n        logger.warn(\n          `MCP server \"${spec.name}\" failed to connect — skipping. Reason: ${(err as Error).message}`,\n        );\n        return;\n      }\n      lifecycle.register(client);\n\n      // Capability negotiation: only fetch tools if the server advertises them.\n      const caps = client.serverCapabilities;\n      const hasTools = caps?.tools !== undefined;\n\n      let tools: import(\"./types.js\").McpToolDescriptor[] = [];\n      if (hasTools) {\n        try {\n          tools = await client.listTools();\n        } catch (err) {\n          logger.warn(\n            `MCP server \"${spec.name}\" listTools failed — skipping. Reason: ${(err as Error).message}`,\n          );\n          return;\n        }\n      } else {\n        logger.debug(\n          `MCP server \"${spec.name}\" did not advertise tools capability — skipping listTools.`,\n        );\n      }\n\n      // Surface unsupported-primitive warnings once.\n      if (caps?.resources !== undefined) {\n        logger.debug(\n          `MCP server \"${spec.name}\" advertises 'resources' capability — not yet implemented in llmist (deferred to v1.5).`,\n        );\n      }\n\n      // Discover prompts (capability-gated).\n      if (caps?.prompts !== undefined && onPromptDiscovered) {\n        try {\n          const prompts = await client.listPrompts();\n          for (const p of prompts) {\n            onPromptDiscovered(mcpPromptToSkill(p, client));\n          }\n        } catch (err) {\n          logger.debug(\n            `MCP server \"${spec.name}\" listPrompts failed — skipping prompts. Reason: ${(err as Error).message}`,\n          );\n        }\n      }\n\n      connected.push({ client, serverToolList: { server: spec, tools } });\n    }),\n  );\n\n  // Phase 2: resolve tool name conflicts, then register each as a gadget.\n  const resolved = resolveToolNames(connected.map((c) => c.serverToolList));\n\n  for (const r of resolved) {\n    const cs = connected.find((c) => c.serverToolList.server.name === r.server.name);\n    if (!cs) continue;\n    for (const tool of r.tools) {\n      const gadget = mcpToolToGadget(tool, cs.client, { prefix: r.prefix });\n      try {\n        registry.register(gadget.name ?? tool.name, gadget);\n      } catch (err) {\n        logger.warn(\n          `MCP server \"${r.server.name}\" tool \"${tool.name}\" was not registered: ${(err as Error).message}`,\n        );\n      }\n    }\n  }\n\n  // Rebuild conversation base messages so the system prompt's gadget catalog\n  // includes the freshly-added MCP-backed gadgets.\n  const builder = new LLMMessageBuilder();\n  if (typeof systemPrompt === \"string\" && systemPrompt.length > 0) {\n    builder.addSystem(systemPrompt);\n  }\n  builder.addGadgets(registry.getAll(), {\n    startPrefix: prefixConfig?.gadgetStartPrefix,\n    endPrefix: prefixConfig?.gadgetEndPrefix,\n    argPrefix: prefixConfig?.gadgetArgPrefix,\n  });\n  conversation.replaceBaseMessages(builder.build());\n\n  return lifecycle;\n}\n","/**\n * Agent: Lean orchestrator using the clean hooks architecture.\n *\n * The Agent delegates ALL stream processing and hook coordination to StreamProcessor,\n * making it a simple loop orchestrator with clear responsibilities.\n */\n\nimport type { ILogObj, Logger } from \"tslog\";\nimport type { LLMist } from \"../core/client.js\";\nimport { ExecutionTree, type NodeId } from \"../core/execution-tree.js\";\nimport type { ContentPart } from \"../core/input-content.js\";\nimport type { MessageContent } from \"../core/messages.js\";\nimport { LLMMessageBuilder } from \"../core/messages.js\";\nimport { resolveModel } from \"../core/model-shortcuts.js\";\nimport type { CachingConfig, LLMGenerationOptions, ReasoningConfig } from \"../core/options.js\";\nimport type { PromptTemplateConfig } from \"../core/prompt-config.js\";\nimport type { RateLimitConfig } from \"../core/rate-limit.js\";\nimport { RateLimitTracker, resolveRateLimitConfig } from \"../core/rate-limit.js\";\nimport type { ResolvedRetryConfig, RetryConfig } from \"../core/retry.js\";\nimport { isLikelyContextOverflow, resolveRetryConfig } from \"../core/retry.js\";\nimport { BudgetPricingUnavailableError } from \"../gadgets/exceptions.js\";\nimport { MediaStore } from \"../gadgets/media-store.js\";\nimport type { GadgetRegistry } from \"../gadgets/registry.js\";\nimport type {\n  GadgetExecutionMode,\n  StreamCompletionEvent,\n  StreamEvent,\n  SubagentConfigMap,\n  TextOnlyHandler,\n} from \"../gadgets/types.js\";\nimport { createLogger } from \"../logging/logger.js\";\nimport { type AGENT_INTERNAL_KEY, isValidAgentKey } from \"./agent-internal-key.js\";\nimport type { CompactionConfig, CompactionEvent, CompactionStats } from \"./compaction/config.js\";\nimport { CompactionManager } from \"./compaction/manager.js\";\nimport { ConversationManager } from \"./conversation-manager.js\";\nimport { ConversationUpdater } from \"./conversation-updater.js\";\nimport { type EventHandlers, runWithHandlers } from \"./event-handlers.js\";\nimport type {\n  AgentHooks,\n  ObserveAbortContext,\n  ObserveRateLimitThrottleContext,\n  Observers,\n} from \"./hooks.js\";\nimport type { IConversationManager } from \"./interfaces.js\";\nimport { LLMCallLifecycle } from \"./llm-call-lifecycle.js\";\nimport type { OutputLimitConfig } from \"./output-limit-manager.js\";\nimport { OutputLimitManager } from \"./output-limit-manager.js\";\nimport { RetryOrchestrator } from \"./retry-orchestrator.js\";\nimport { safeObserve } from \"./safe-observe.js\";\nimport type { StreamProcessor } from \"./stream-processor.js\";\nimport { StreamProcessorFactory } from \"./stream-processor-factory.js\";\nimport { bridgeTreeToHooks, getSubagentContextForNode } from \"./tree-hook-bridge.js\";\n\n/**\n * Minimum number of history messages required before attempting context overflow\n * recovery via compaction. This ensures there's meaningful content to compact\n * (at least 2 conversation turns: user+assistant pairs). If history is smaller,\n * compaction can't reduce context enough to help and the error should propagate.\n */\nconst OVERFLOW_RECOVERY_MIN_HISTORY = 4;\n\n/**\n * Configuration for the execution tree context (shared tree model with subagents).\n */\nexport interface TreeConfig {\n  /**\n   * Shared execution tree for tracking all LLM calls and gadget executions.\n   * If provided (by a parent subagent), nodes are added to this tree.\n   * If not provided, the Agent creates its own tree.\n   */\n  tree?: ExecutionTree;\n\n  /**\n   * Parent node ID in the tree (when this agent is a subagent).\n   * Used to set parentId on all nodes created by this agent.\n   */\n  parentNodeId?: NodeId;\n\n  /**\n   * Base depth for nodes created by this agent.\n   * Root agents use 0; subagents use (parentDepth + 1).\n   */\n  baseDepth?: number;\n\n  /**\n   * Parent agent's observer hooks for subagent visibility.\n   *\n   * When a subagent is created with withParentContext(ctx), these observers\n   * are also called for gadget events (in addition to the subagent's own hooks),\n   * enabling the parent to observe subagent gadget activity.\n   */\n  parentObservers?: Observers;\n}\n\n/**\n * Configuration for custom gadget block format prefixes.\n */\nexport interface PrefixConfig {\n  /** Custom gadget start prefix */\n  gadgetStartPrefix?: string;\n\n  /** Custom gadget end prefix */\n  gadgetEndPrefix?: string;\n\n  /** Custom gadget argument prefix for block format parameters */\n  gadgetArgPrefix?: string;\n}\n\n/**\n * Configuration options for the Agent.\n */\nexport interface AgentOptions {\n  /** The LLM client */\n  client: LLMist;\n\n  /** The model ID */\n  model: string;\n\n  /** System prompt */\n  systemPrompt?: string;\n\n  /** Initial user prompt (optional if using build()). Can be text or multimodal content. */\n  userPrompt?: string | ContentPart[];\n\n  /** Maximum iterations */\n  maxIterations?: number;\n\n  /** Budget limit in USD. Agent loop stops when cumulative cost reaches this limit. */\n  budget?: number;\n\n  /** Temperature */\n  temperature?: number;\n\n  /** Gadget registry */\n  registry: GadgetRegistry;\n\n  /** Logger */\n  logger?: Logger<ILogObj>;\n\n  /** Clean hooks system */\n  hooks?: AgentHooks;\n\n  /** Callback for requesting human input during execution */\n  requestHumanInput?: (question: string) => Promise<string>;\n\n  /**\n   * Gadget prefix configuration (start/end/arg prefixes for block format).\n   */\n  prefixConfig?: PrefixConfig;\n\n  /** Initial messages. User messages support multimodal content. */\n  initialMessages?: Array<{ role: \"system\" | \"user\" | \"assistant\"; content: MessageContent }>;\n\n  /** Text-only handler */\n  textOnlyHandler?: TextOnlyHandler;\n\n  /**\n   * Handler for text content that appears alongside gadget calls.\n   * When set, text accompanying gadgets will be wrapped as a synthetic gadget call.\n   */\n  textWithGadgetsHandler?: {\n    /** Name of the gadget to use for wrapping text */\n    gadgetName: string;\n    /** Maps text content to gadget parameters */\n    parameterMapping: (text: string) => Record<string, unknown>;\n    /** Maps text content to the result string (optional, defaults to text) */\n    resultMapping?: (text: string) => string;\n  };\n\n  /** Default gadget timeout */\n  defaultGadgetTimeoutMs?: number;\n\n  /** Gadget execution mode: 'parallel' (default) or 'sequential' */\n  gadgetExecutionMode?: GadgetExecutionMode;\n\n  /** Custom prompt configuration for gadget system prompts */\n  promptConfig?: PromptTemplateConfig;\n\n  /**\n   * Gadget output limit configuration.\n   */\n  outputLimitConfig?: OutputLimitConfig;\n\n  /** Context compaction configuration (enabled by default) */\n  compactionConfig?: CompactionConfig;\n\n  /** Retry configuration for LLM API calls (enabled by default) */\n  retryConfig?: RetryConfig;\n\n  /** Rate limit configuration for proactive throttling */\n  rateLimitConfig?: RateLimitConfig;\n\n  /** Optional abort signal for cancelling requests mid-flight */\n  signal?: AbortSignal;\n\n  /** Reasoning/thinking configuration for reasoning-capable models */\n  reasoning?: ReasoningConfig;\n\n  /** Context caching configuration for supported providers */\n  caching?: CachingConfig;\n\n  /** Subagent-specific configuration overrides (from CLI config) */\n  subagentConfig?: SubagentConfigMap;\n\n  /** Maximum gadgets to execute per LLM response (0 = unlimited) */\n  maxGadgetsPerResponse?: number;\n\n  // ==========================================================================\n  // Execution Tree Context (for shared tree model with subagents)\n  // ==========================================================================\n\n  /**\n   * Execution tree configuration (shared tree model with subagents).\n   */\n  treeConfig?: TreeConfig;\n\n  /**\n   * Shared rate limit tracker from parent agent.\n   *\n   * When provided (via withParentContext), this agent uses the parent's tracker\n   * instead of creating its own. All LLM calls count toward the shared limits.\n   */\n  sharedRateLimitTracker?: RateLimitTracker;\n\n  /**\n   * Shared retry configuration from parent agent.\n   *\n   * When provided (via withParentContext), this agent uses the parent's retry\n   * settings instead of creating its own.\n   */\n  sharedRetryConfig?: ResolvedRetryConfig;\n\n  /**\n   * MCP server specs to attach to the agent.\n   *\n   * When non-empty, the agent connects to each server lazily at the start of\n   * `run()`, lists their tools, wraps them as native gadgets, and registers\n   * them on the registry alongside any explicitly-provided gadgets. The\n   * lifecycle teardown happens in the agent's `finally` block.\n   *\n   * When empty or omitted, the MCP module is never imported — agents that\n   * don't use MCP pay zero overhead at load time.\n   */\n  mcpSpecs?: import(\"../mcp/types.js\").McpServerSpec[];\n}\n\n/**\n * Agent: Lean orchestrator that delegates to StreamProcessor.\n *\n * Responsibilities:\n * - Run the main agent loop\n * - Call LLM API\n * - Delegate stream processing to StreamProcessor\n * - Coordinate conversation management\n * - Execute top-level lifecycle controllers\n *\n * NOT responsible for:\n * - Stream parsing (StreamProcessor)\n * - Hook coordination (StreamProcessor)\n * - Gadget execution (StreamProcessor -> GadgetExecutor)\n */\nexport class Agent {\n  private readonly client: LLMist;\n  private readonly model: string;\n  private readonly maxIterations: number;\n  private readonly budget?: number;\n  private readonly temperature?: number;\n  private readonly logger: Logger<ILogObj>;\n  private readonly hooks: AgentHooks;\n  private readonly conversation: ConversationManager;\n  private readonly registry: GadgetRegistry;\n  private readonly prefixConfig?: PrefixConfig;\n  private readonly conversationUpdater: ConversationUpdater;\n  private readonly defaultMaxTokens?: number;\n  private hasUserPrompt: boolean;\n\n  // Gadget output limiting\n  private readonly outputLimitManager: OutputLimitManager;\n\n  // Context compaction\n  private readonly compactionManager?: CompactionManager;\n\n  // Media storage (for gadgets returning images, audio, etc.)\n  private readonly mediaStore: MediaStore;\n\n  // Cancellation\n  private readonly signal?: AbortSignal;\n  private readonly reasoning?: ReasoningConfig;\n  private readonly caching?: CachingConfig;\n\n  // Retry configuration (shared reference also passed to StreamProcessorFactory)\n  private readonly retryConfig: ResolvedRetryConfig;\n\n  // Rate limit tracker for proactive throttling\n  private readonly rateLimitTracker?: RateLimitTracker;\n\n  // Cross-iteration dependency tracking - allows gadgets to depend on results from prior iterations\n  private readonly completedInvocationIds: Set<string> = new Set();\n  private readonly failedInvocationIds: Set<string> = new Set();\n\n  // Queue for user messages injected during agent execution (REPL mid-session input)\n  private readonly pendingUserMessages: string[] = [];\n\n  // Execution Tree - first-class model for nested subagent support\n  private readonly tree: ExecutionTree;\n  private readonly parentNodeId: NodeId | null;\n\n  // StreamProcessor factory - encapsulates all pass-through StreamProcessor config\n  private readonly streamProcessorFactory: StreamProcessorFactory;\n\n  // LLM call lifecycle helper (encapsulates prepareLLMCall, completeLLMCall, notifyLLMError)\n  private readonly llmCallLifecycle: LLMCallLifecycle;\n\n  // MCP integration — populated only when mcpSpecs were provided.\n  private readonly mcpSpecs: import(\"../mcp/types.js\").McpServerSpec[];\n  private mcpLifecycle: { closeAll(): Promise<void> } | null = null;\n  private readonly mcpDiscoveredPrompts: import(\"../mcp/prompt-adapter.js\").McpPromptSkill[] = [];\n\n  /**\n   * Creates a new Agent instance.\n   * @internal This constructor is private. Use LLMist.createAgent() or AgentBuilder instead.\n   */\n  constructor(key: typeof AGENT_INTERNAL_KEY, options: AgentOptions) {\n    if (!isValidAgentKey(key)) {\n      throw new Error(\n        \"Agent cannot be instantiated directly. Use LLMist.createAgent() or new AgentBuilder() instead.\",\n      );\n    }\n\n    this.client = options.client;\n    this.model = resolveModel(options.model);\n    this.maxIterations = options.maxIterations ?? 10;\n    this.budget = options.budget;\n    this.temperature = options.temperature;\n    this.logger = options.logger ?? createLogger({ name: \"llmist:agent\" });\n    this.registry = options.registry;\n\n    // Store prefix config as a single object (used by conversation and factory)\n    this.prefixConfig = options.prefixConfig;\n\n    this.defaultMaxTokens = this.resolveMaxTokensFromCatalog(options.model);\n\n    // Read output limit config\n    const outputLimitConfig: OutputLimitConfig = {\n      enabled: options.outputLimitConfig?.enabled,\n      limitPercent: options.outputLimitConfig?.limitPercent,\n    };\n\n    // Initialize gadget output limiting\n    this.outputLimitManager = new OutputLimitManager(\n      this.client,\n      this.model,\n      outputLimitConfig,\n      this.registry,\n      this.logger,\n    );\n\n    // Initialize media storage for gadgets returning images, audio, etc.\n    this.mediaStore = new MediaStore();\n\n    // Chain output limiter interceptor with user hooks\n    // NOTE: this.hooks must be set BEFORE creating StreamProcessorFactory\n    this.hooks = this.outputLimitManager.getHooks(options.hooks);\n\n    // Build conversation\n    const baseBuilder = new LLMMessageBuilder(options.promptConfig);\n    if (options.systemPrompt) {\n      baseBuilder.addSystem(options.systemPrompt);\n    }\n\n    baseBuilder.addGadgets(this.registry.getAll(), {\n      startPrefix: this.prefixConfig?.gadgetStartPrefix,\n      endPrefix: this.prefixConfig?.gadgetEndPrefix,\n      argPrefix: this.prefixConfig?.gadgetArgPrefix,\n    });\n    const baseMessages = baseBuilder.build();\n\n    const initialMessages = (options.initialMessages ?? []).map((message) => ({\n      role: message.role,\n      content: message.content,\n    }));\n\n    this.conversation = new ConversationManager(baseMessages, initialMessages, {\n      startPrefix: this.prefixConfig?.gadgetStartPrefix,\n      endPrefix: this.prefixConfig?.gadgetEndPrefix,\n      argPrefix: this.prefixConfig?.gadgetArgPrefix,\n    });\n    this.hasUserPrompt = !!options.userPrompt;\n    if (options.userPrompt) {\n      this.conversation.addUserMessage(options.userPrompt);\n    }\n\n    // Initialize conversation updater (owns text-only and text-with-gadgets handling)\n    this.conversationUpdater = new ConversationUpdater(\n      this.conversation,\n      options.textOnlyHandler ?? \"terminate\",\n      options.textWithGadgetsHandler,\n      this.logger,\n    );\n\n    // Initialize context compaction (enabled by default)\n    const compactionEnabled = options.compactionConfig?.enabled ?? true;\n    if (compactionEnabled) {\n      this.compactionManager = new CompactionManager(\n        this.client,\n        this.model,\n        options.compactionConfig,\n        this.logger,\n      );\n    }\n\n    // Store abort signal for cancellation\n    this.signal = options.signal;\n\n    // Capture MCP server specs (only honored when non-empty — zero-overhead\n    // when no MCP servers were configured).\n    this.mcpSpecs = options.mcpSpecs ?? [];\n\n    // Store reasoning configuration\n    this.reasoning = options.reasoning;\n\n    // Store caching configuration\n    this.caching = options.caching;\n\n    // Initialize retry configuration\n    // Prefer shared config from parent (for coordinated retry across subagents)\n    this.retryConfig = options.sharedRetryConfig ?? resolveRetryConfig(options.retryConfig);\n\n    // Initialize rate limit tracker for proactive throttling\n    // Prefer shared tracker from parent (for coordinated limits across subagents)\n    if (options.sharedRateLimitTracker) {\n      this.rateLimitTracker = options.sharedRateLimitTracker;\n    } else {\n      const rateLimitConfig = resolveRateLimitConfig(options.rateLimitConfig);\n      if (rateLimitConfig.enabled) {\n        this.rateLimitTracker = new RateLimitTracker(options.rateLimitConfig);\n      }\n    }\n\n    // Initialize Execution Tree from treeConfig (or create a new one for root agents)\n    const treeConfig = options.treeConfig;\n    this.tree = treeConfig?.tree ?? new ExecutionTree();\n    this.parentNodeId = treeConfig?.parentNodeId ?? null;\n\n    // Initialize StreamProcessor factory — encapsulates all pass-through StreamProcessor config\n    this.streamProcessorFactory = new StreamProcessorFactory({\n      registry: this.registry,\n      prefixConfig: this.prefixConfig,\n      hooks: this.hooks,\n      logger: this.logger,\n      requestHumanInput: options.requestHumanInput,\n      defaultGadgetTimeoutMs: options.defaultGadgetTimeoutMs,\n      gadgetExecutionMode: options.gadgetExecutionMode ?? \"parallel\",\n      client: this.client,\n      mediaStore: this.mediaStore,\n      agentContextConfig: {\n        model: this.model,\n        temperature: this.temperature,\n      },\n      subagentConfig: options.subagentConfig,\n      tree: this.tree,\n      baseDepth: treeConfig?.baseDepth ?? 0,\n      parentObservers: treeConfig?.parentObservers,\n      rateLimitTracker: this.rateLimitTracker,\n      retryConfig: this.retryConfig,\n      maxGadgetsPerResponse: options.maxGadgetsPerResponse ?? 0,\n    });\n\n    // Initialize LLM call lifecycle helper\n    this.llmCallLifecycle = new LLMCallLifecycle({\n      client: this.client,\n      conversation: this.conversation,\n      tree: this.tree,\n      hooks: this.hooks,\n      logger: this.logger,\n      rateLimitTracker: this.rateLimitTracker,\n      signal: this.signal,\n      temperature: this.temperature,\n      reasoning: this.reasoning,\n      caching: this.caching,\n      model: this.model,\n      defaultMaxTokens: this.defaultMaxTokens,\n      maxIterations: this.maxIterations,\n      budget: this.budget,\n      parentNodeId: this.parentNodeId,\n    });\n\n    // Validate budget against model pricing\n    if (this.budget !== undefined) {\n      const spec = this.client.modelRegistry?.getModelSpec?.(this.model);\n      if (!spec || (spec.pricing.input === 0 && spec.pricing.output === 0)) {\n        throw new BudgetPricingUnavailableError(this.model, this.budget);\n      }\n    }\n  }\n\n  /**\n   * Get the gadget registry for this agent.\n   *\n   * Useful for inspecting registered gadgets in tests or advanced use cases.\n   *\n   * @returns The GadgetRegistry instance\n   *\n   * @example\n   * ```typescript\n   * const agent = new AgentBuilder()\n   *   .withModel(\"sonnet\")\n   *   .withGadgets(Calculator, Weather)\n   *   .build();\n   *\n   * // Inspect registered gadgets\n   * console.log(agent.getRegistry().getNames()); // ['Calculator', 'Weather']\n   * ```\n   */\n  getRegistry(): GadgetRegistry {\n    return this.registry;\n  }\n\n  /**\n   * Get the media store for this agent session.\n   *\n   * The media store holds all media outputs (images, audio, etc.) produced by gadgets\n   * during this agent's execution. Use this to:\n   * - Access stored media files by ID\n   * - List all stored media\n   * - Clean up temporary files after execution\n   *\n   * @returns The MediaStore instance for this agent\n   *\n   * @example\n   * ```typescript\n   * const agent = new AgentBuilder()\n   *   .withModel(\"sonnet\")\n   *   .build();\n   *\n   * // After execution, access stored media\n   * const store = agent.getMediaStore();\n   * for (const media of store.list()) {\n   *   console.log(`${media.id}: ${media.path}`);\n   * }\n   *\n   * // Clean up when done\n   * await store.cleanup();\n   * ```\n   */\n  getMediaStore(): MediaStore {\n    return this.mediaStore;\n  }\n\n  /**\n   * Get the execution tree for this agent.\n   *\n   * The execution tree provides a first-class model of all LLM calls and gadget executions,\n   * including nested subagent activity. Use this to:\n   * - Query execution state: `tree.getNode(id)`\n   * - Get total cost: `tree.getTotalCost()`\n   * - Get subtree cost/media/tokens: `tree.getSubtreeCost(nodeId)`\n   * - Subscribe to events: `tree.on(\"llm_call_complete\", handler)`\n   * - Stream all events: `for await (const event of tree.events())`\n   *\n   * For subagents (created with `withParentContext`), the tree is shared with the parent,\n   * enabling unified tracking and real-time visibility across all nesting levels.\n   *\n   * @returns The ExecutionTree instance\n   *\n   * @example\n   * ```typescript\n   * const agent = LLMist.createAgent()\n   *   .withModel(\"sonnet\")\n   *   .withGadgets(BrowseWeb)\n   *   .ask(\"Research topic X\");\n   *\n   * for await (const event of agent.run()) {\n   *   // Process events...\n   * }\n   *\n   * // After execution, query the tree\n   * const tree = agent.getTree();\n   * console.log(`Total cost: $${tree.getTotalCost().toFixed(4)}`);\n   *\n   * // Inspect all LLM calls\n   * for (const node of tree.getAllNodes()) {\n   *   if (node.type === \"llm_call\") {\n   *     console.log(`LLM #${node.iteration}: ${node.model}`);\n   *   }\n   * }\n   * ```\n   */\n  getTree(): ExecutionTree {\n    return this.tree;\n  }\n\n  /**\n   * Manually trigger context compaction.\n   *\n   * Forces compaction regardless of threshold. Useful for:\n   * - Pre-emptive context management before expected long operations\n   * - Testing compaction behavior\n   *\n   * @returns CompactionEvent if compaction was performed, null if not configured or no history\n   *\n   * @example\n   * ```typescript\n   * const agent = await LLMist.createAgent()\n   *   .withModel('sonnet')\n   *   .withCompaction()\n   *   .ask('...');\n   *\n   * // Manually compact before a long operation\n   * const event = await agent.compact();\n   * if (event) {\n   *   console.log(`Saved ${event.tokensBefore - event.tokensAfter} tokens`);\n   * }\n   * ```\n   */\n  async compact(): Promise<CompactionEvent | null> {\n    if (!this.compactionManager) {\n      return null;\n    }\n    // Use -1 to indicate manual (out-of-band) compaction, not part of the normal iteration cycle\n    return this.compactionManager.compact(this.conversation, -1);\n  }\n\n  /**\n   * Get compaction statistics.\n   *\n   * @returns CompactionStats if compaction is enabled, null otherwise\n   *\n   * @example\n   * ```typescript\n   * const stats = agent.getCompactionStats();\n   * if (stats) {\n   *   console.log(`Total compactions: ${stats.totalCompactions}`);\n   *   console.log(`Tokens saved: ${stats.totalTokensSaved}`);\n   *   console.log(`Current usage: ${stats.currentUsage.percent.toFixed(1)}%`);\n   * }\n   * ```\n   */\n  getCompactionStats(): CompactionStats | null {\n    return this.compactionManager?.getStats() ?? null;\n  }\n\n  /**\n   * Get the conversation manager for this agent.\n   * Used by REPL mode to extract session history for continuation.\n   *\n   * @returns The conversation manager containing all messages\n   *\n   * @example\n   * ```typescript\n   * // After running agent, extract history for next session\n   * const history = agent.getConversation().getConversationHistory();\n   * // Pass to next agent via builder.withHistory()\n   * ```\n   */\n  getConversation(): IConversationManager {\n    return this.conversation;\n  }\n\n  /**\n   * Inject a user message to be processed in the next iteration.\n   * Used by REPL mode to allow user input during a running session.\n   *\n   * The message is queued and will be added to the conversation before\n   * the next LLM call. This allows users to provide additional context\n   * or instructions while the agent is executing.\n   *\n   * @param message - The user message to inject\n   *\n   * @example\n   * ```typescript\n   * // While agent is running in TUI:\n   * tui.onMidSessionInput((msg) => {\n   *   agent.injectUserMessage(msg);\n   * });\n   * ```\n   */\n  injectUserMessage(message: string): void {\n    this.pendingUserMessages.push(message);\n    this.logger.debug(\"User message queued for injection\", { message });\n  }\n\n  /**\n   * Run the agent loop.\n   * Clean, simple orchestration - all complexity is in StreamProcessor.\n   *\n   * ## Event Architecture\n   *\n   * ExecutionTree is the single source of truth for all agent events.\n   * Gadget observer hooks (`onGadgetExecutionStart`, `onGadgetExecutionComplete`,\n   * `onGadgetSkipped`) are derived from tree events via `tree-hook-bridge.ts`.\n   * This ensures consistent `subagentContext` for nested agents - both the TUI\n   * and user hook observers receive identical event context.\n   *\n   * @throws {Error} If no user prompt was provided (when using build() without ask())\n   */\n  async *run(): AsyncGenerator<StreamEvent> {\n    if (!this.hasUserPrompt) {\n      throw new Error(\n        \"No user prompt provided. Use .ask(prompt) instead of .build(), or call agent.run() after providing a prompt.\",\n      );\n    }\n\n    // Bridge ExecutionTree events to hook observers for gadget events.\n    // This is the single source of truth - tree events trigger hooks with proper subagentContext.\n    const unsubscribeBridge = bridgeTreeToHooks(this.tree, this.hooks, this.logger);\n\n    // Lazy MCP setup — only runs when at least one MCP server was attached.\n    // Connects each server, registers tools as adapter gadgets, and rebuilds\n    // the conversation system prompt so the LLM sees the full gadget catalog.\n    if (this.mcpSpecs.length > 0) {\n      const { setupMcpServers } = await import(\"../mcp/runtime.js\");\n      this.mcpLifecycle = await setupMcpServers({\n        specs: this.mcpSpecs,\n        registry: this.registry,\n        conversation: this.conversation,\n        prefixConfig: this.prefixConfig,\n        systemPrompt:\n          this.conversation.getBaseMessages()[0]?.role === \"system\"\n            ? (this.conversation.getBaseMessages()[0]!.content as string)\n            : undefined,\n        logger: this.logger,\n        onPromptDiscovered: (skill) => this.mcpDiscoveredPrompts.push(skill),\n      });\n    }\n\n    let currentIteration = 0;\n\n    this.logger.info(\"Starting agent loop\", {\n      model: this.model,\n      maxIterations: this.maxIterations,\n      ...(this.budget !== undefined && { budget: this.budget }),\n    });\n\n    // Declare outside while loop so they're accessible in the finally block\n    // for safety net completion of in-flight LLM calls\n    let currentLLMNodeId: string | undefined;\n    let llmOptions: LLMGenerationOptions | undefined;\n\n    // Track whether we've already attempted context overflow recovery (max 1 per agent run).\n    // This prevents infinite compaction→retry→fail loops.\n    let hasAttemptedOverflowRecovery = false;\n\n    try {\n      while (currentIteration < this.maxIterations) {\n        // Check abort signal at start of each iteration\n        if (await this.checkAbortAndNotify(currentIteration)) {\n          return;\n        }\n\n        // Process any injected user messages (from REPL mid-session input)\n        while (this.pendingUserMessages.length > 0) {\n          const msg = this.pendingUserMessages.shift()!;\n          this.conversation.addUserMessage(msg);\n          this.logger.info(\"Injected user message into conversation\", {\n            iteration: currentIteration,\n            messageLength: msg.length,\n          });\n        }\n\n        this.logger.debug(\"Starting iteration\", { iteration: currentIteration });\n\n        try {\n          // Check and perform context compaction if needed\n          const compactionEvent = await this.checkAndPerformCompaction(currentIteration);\n          if (compactionEvent) {\n            yield compactionEvent;\n          }\n\n          // Prepare LLM call (creates tree node and calls onLLMCallStart/Ready hooks)\n          const prepared = await this.llmCallLifecycle.prepareLLMCall(currentIteration);\n          llmOptions = prepared.options;\n          currentLLMNodeId = prepared.llmNodeId;\n\n          // Handle skip action from beforeLLMCall controller\n          if (prepared.skipWithSynthetic !== undefined) {\n            this.conversation.addAssistantMessage(prepared.skipWithSynthetic);\n            yield { type: \"text\", content: prepared.skipWithSynthetic };\n            break;\n          }\n\n          // Call LLM\n          this.logger.info(\"Calling LLM\", { model: this.model });\n          this.logger.silly(\"LLM request details\", {\n            model: llmOptions.model,\n            temperature: llmOptions.temperature,\n            maxTokens: llmOptions.maxTokens,\n            messageCount: llmOptions.messages.length,\n            messages: llmOptions.messages,\n          });\n\n          // Stream creation and iteration with retry for errors during streaming.\n          // All retry orchestration is encapsulated in executeWithRetry(), which also\n          // tracks textOutputs, gadgetResults, and gadgetCallCount — resetting them\n          // between retry attempts so only data from the final successful attempt is returned.\n\n          // Iterate the retry generator manually to capture its return value (stream metadata\n          // and accumulated tracking state). for-await-of discards the generator's final\n          // done-value, so we use .next() directly.\n          const retryGen = this.executeWithRetry(llmOptions, currentIteration, currentLLMNodeId);\n          let next = await retryGen.next();\n          while (!next.done) {\n            // Yield event to consumer in real-time\n            yield next.value;\n            next = await retryGen.next();\n          }\n          // When done === true, the value is the generator's return value\n          const retryResult = next.value;\n\n          // Ensure we received the completion metadata\n          if (!retryResult) {\n            throw new Error(\"Stream processing completed without metadata event\");\n          }\n\n          const { streamMetadata, textOutputs, gadgetResults, gadgetCallCount } = retryResult;\n\n          // Use streamMetadata as the result for remaining logic\n          const result = streamMetadata;\n\n          this.logger.info(\"LLM response completed\", {\n            finishReason: result.finishReason,\n            usage: result.usage,\n            didExecuteGadgets: result.didExecuteGadgets,\n          });\n          this.logger.silly(\"LLM response details\", {\n            rawResponse: result.rawResponse,\n          });\n\n          // Complete LLM call: fire onLLMCallComplete observer, update tree with cost,\n          // process afterLLMCall controller (may modify finalMessage or append messages)\n          const finalMessage = await this.llmCallLifecycle.completeLLMCall(\n            currentLLMNodeId!,\n            result,\n            currentIteration,\n            llmOptions!,\n            gadgetCallCount,\n          );\n\n          // Update conversation with results (gadgets or text-only)\n          const shouldBreakFromTextOnly = this.conversationUpdater.updateWithResults(\n            textOutputs,\n            gadgetResults,\n            finalMessage,\n          );\n          if (shouldBreakFromTextOnly) {\n            break;\n          }\n\n          // Check if loop should break\n          if (result.shouldBreakLoop) {\n            this.logger.info(\"Loop terminated by gadget or processor\");\n            break;\n          }\n\n          // Reactive compaction: use API-reported input tokens (ground truth) to check\n          // if we've crossed the compaction threshold. This catches cases where the\n          // proactive char-based estimate (at iteration start) underestimates token usage.\n          // Placed after break checks so we don't compact on the final iteration.\n          if (this.compactionManager && result.usage?.inputTokens) {\n            this.compactionManager.updateUsage(result.usage.inputTokens);\n            if (this.compactionManager.shouldCompactFromUsage()) {\n              this.logger.info(\"Reactive compaction triggered from API-reported usage\", {\n                inputTokens: result.usage.inputTokens,\n                iteration: currentIteration,\n              });\n              const reactiveCompaction = await this.compactionManager.compact(\n                this.conversation,\n                currentIteration,\n              );\n              if (reactiveCompaction) {\n                yield await this.emitCompactionEvent(reactiveCompaction, currentIteration);\n              }\n            }\n          }\n\n          // Check if budget limit has been reached\n          if (this.budget !== undefined) {\n            const totalCost = this.tree.getTotalCost();\n            if (totalCost >= this.budget) {\n              this.logger.info(\"Budget limit reached\", {\n                totalCost,\n                budget: this.budget,\n                iteration: currentIteration,\n              });\n              break;\n            }\n          }\n        } catch (error) {\n          // Attempt context overflow recovery: if the error looks like context overflow\n          // and we haven't already tried recovery, force compaction and retry the iteration.\n          // Minimum history of 4 messages (2 conversation turns) ensures there's meaningful\n          // content to compact — otherwise compaction can't reduce the context enough to help.\n          const historyLength = this.conversation.getHistoryMessages().length;\n          if (\n            this.compactionManager &&\n            !hasAttemptedOverflowRecovery &&\n            isLikelyContextOverflow(error as Error) &&\n            historyLength >= OVERFLOW_RECOVERY_MIN_HISTORY\n          ) {\n            hasAttemptedOverflowRecovery = true;\n            this.logger.warn(\"Possible context overflow detected, attempting compaction recovery\", {\n              error: (error as Error).message,\n              iteration: currentIteration,\n              historyMessages: historyLength,\n            });\n\n            try {\n              const compactionEvent = await this.compactionManager.compact(\n                this.conversation,\n                currentIteration,\n              );\n\n              if (compactionEvent) {\n                const event = await this.emitCompactionEvent(compactionEvent, currentIteration);\n                yield event;\n                // Re-iterate with compacted context (continue skips currentIteration++,\n                // so we retry the same iteration number with a smaller context)\n                continue;\n              }\n              this.logger.warn(\"Compaction returned no result, cannot recover from overflow\");\n            } catch (compactionError) {\n              this.logger.warn(\n                \"Compaction failed during overflow recovery, propagating original error\",\n                {\n                  compactionError: (compactionError as Error).message,\n                },\n              );\n            }\n          }\n\n          // Delegate error handling and observer notification to lifecycle helper\n          const action = await this.llmCallLifecycle.notifyLLMError(\n            currentIteration,\n            currentLLMNodeId,\n            error as Error,\n          );\n\n          if (action.action === \"recover\") {\n            this.logger.info(\"Controller recovered from LLM error\");\n            this.conversation.addAssistantMessage(action.fallbackResponse);\n          } else {\n            throw error;\n          }\n        }\n\n        currentIteration++;\n      }\n\n      let reason: string;\n      if (this.budget !== undefined && this.tree.getTotalCost() >= this.budget) {\n        reason = \"budget_exceeded\";\n      } else if (currentIteration >= this.maxIterations) {\n        reason = \"max_iterations\";\n      } else {\n        reason = \"natural_completion\";\n      }\n\n      this.logger.info(\"Agent loop completed\", {\n        totalIterations: currentIteration,\n        reason,\n        ...(this.budget !== undefined && {\n          totalCost: this.tree.getTotalCost(),\n          budget: this.budget,\n        }),\n      });\n    } finally {\n      // Safety net: Complete any in-flight LLM call if generator terminated early\n      // This handles cases where consumers break from for-await loop prematurely\n      if (currentLLMNodeId) {\n        const node = this.tree.getNode(currentLLMNodeId);\n        if (node && node.type === \"llm_call\" && !node.completedAt) {\n          // Delegate to lifecycle helper: fires onLLMCallComplete observer and updates tree\n          await this.llmCallLifecycle.completeLLMCall(\n            currentLLMNodeId,\n            {\n              type: \"stream_complete\",\n              finishReason: \"interrupted\",\n              usage: undefined,\n              rawResponse: \"\", // No response available for interrupted request\n              finalMessage: \"\", // No final message for interrupted request\n              didExecuteGadgets: false,\n              shouldBreakLoop: false,\n            },\n            currentIteration,\n            llmOptions ?? {\n              model: this.model,\n              messages: this.conversation.getMessages(),\n              temperature: this.temperature,\n              maxTokens: this.defaultMaxTokens,\n            },\n            0, // gadgetCallCount: no gadgets for interrupted call\n          );\n        }\n      }\n\n      // Always clean up the bridge subscription\n      unsubscribeBridge();\n\n      // Tear down MCP servers (no-op when none were attached).\n      if (this.mcpLifecycle) {\n        try {\n          await this.mcpLifecycle.closeAll();\n        } catch (err) {\n          this.logger.debug(\"MCP lifecycle teardown error (suppressed):\", err);\n        }\n        this.mcpLifecycle = null;\n      }\n    }\n  }\n\n  /**\n   * Execute a single LLM call attempt with full retry orchestration.\n   *\n   * Delegates all retry logic to RetryOrchestrator, then propagates the accumulated\n   * invocation IDs back to the agent's cross-iteration tracking sets.\n   *\n   * Yields stream events in real-time and returns the final stream completion metadata\n   * along with accumulated tracking state from the final successful attempt only.\n   */\n  private async *executeWithRetry(\n    llmOptions: LLMGenerationOptions,\n    currentIteration: number,\n    currentLLMNodeId: string,\n  ): AsyncGenerator<\n    StreamEvent,\n    {\n      streamMetadata: StreamCompletionEvent;\n      textOutputs: string[];\n      gadgetResults: StreamEvent[];\n      gadgetCallCount: number;\n    } | null\n  > {\n    const orchestrator = new RetryOrchestrator({\n      retryConfig: this.retryConfig,\n      logger: this.logger,\n      hooks: this.hooks,\n      tree: this.tree,\n      sleep: (ms) => this.sleep(ms),\n    });\n\n    const result = yield* orchestrator.orchestrate(\n      llmOptions,\n      currentIteration,\n      currentLLMNodeId,\n      (opts, iter, nodeId) => this.createStream(opts, iter, nodeId),\n      (iter, nodeId) => this.createStreamProcessor(iter, nodeId),\n    );\n\n    // Propagate accumulated invocation IDs to agent's cross-iteration tracking\n    for (const id of orchestrator.getCompletedInvocationIds()) {\n      this.completedInvocationIds.add(id);\n    }\n    for (const id of orchestrator.getFailedInvocationIds()) {\n      this.failedInvocationIds.add(id);\n    }\n\n    return result;\n  }\n\n  /**\n   * Create LLM stream with proactive rate limit protection.\n   *\n   * Note: Retry logic for errors during streaming is handled by the outer loop in run().\n   * This method only handles proactive rate limiting (delaying requests to stay within limits).\n   */\n  private async createStream(\n    llmOptions: LLMGenerationOptions,\n    iteration: number,\n    llmNodeId: string,\n  ): Promise<ReturnType<LLMist[\"stream\"]>> {\n    // Proactive rate limit throttling\n    if (this.rateLimitTracker) {\n      const throttleDelay = this.rateLimitTracker.getRequiredDelayMs();\n      if (throttleDelay > 0) {\n        this.logger.debug(\"Rate limit throttling\", { delayMs: throttleDelay });\n\n        // Emit observer hook for rate limit throttling\n        await safeObserve(async () => {\n          if (this.hooks.observers?.onRateLimitThrottle) {\n            const subagentContext = getSubagentContextForNode(this.tree, llmNodeId);\n            const context: ObserveRateLimitThrottleContext = {\n              iteration,\n              delayMs: throttleDelay,\n              stats: this.rateLimitTracker!.getUsageStats(),\n              logger: this.logger,\n              subagentContext,\n            };\n            await this.hooks.observers.onRateLimitThrottle(context);\n          }\n        }, this.logger);\n\n        await this.sleep(throttleDelay);\n      }\n\n      // Reserve a request slot BEFORE making the call\n      // This ensures concurrent subagents see this pending request\n      this.rateLimitTracker.reserveRequest();\n    }\n\n    return this.client.stream(llmOptions);\n  }\n\n  /**\n   * Factory method for constructing a StreamProcessor for a given iteration.\n   *\n   * Delegates to StreamProcessorFactory, which encapsulates all static\n   * StreamProcessor configuration. Cross-iteration mutable state is passed here.\n   */\n  private createStreamProcessor(iteration: number, llmNodeId: string): StreamProcessor {\n    return this.streamProcessorFactory.create(iteration, llmNodeId, {\n      priorCompletedInvocations: this.completedInvocationIds,\n      priorFailedInvocations: this.failedInvocationIds,\n    });\n  }\n\n  /**\n   * Simple sleep utility for rate limit delays.\n   */\n  private sleep(ms: number): Promise<void> {\n    return new Promise((resolve) => setTimeout(resolve, ms));\n  }\n\n  /**\n   * Resolve max tokens from model catalog.\n   */\n  private resolveMaxTokensFromCatalog(modelId: string): number | undefined {\n    const limits = this.client.modelRegistry.getModelLimits(modelId);\n    if (limits?.maxOutputTokens !== undefined) {\n      return limits.maxOutputTokens;\n    }\n\n    const separatorIndex = modelId.indexOf(\":\");\n    if (separatorIndex === -1) {\n      return undefined;\n    }\n\n    const unprefixedModelId = modelId.slice(separatorIndex + 1).trim();\n    if (!unprefixedModelId) {\n      return undefined;\n    }\n\n    return this.client.modelRegistry.getModelLimits(unprefixedModelId)?.maxOutputTokens;\n  }\n\n  // ==========================================================================\n  // Agent Loop Helper Methods (extracted from run() for readability)\n  // ==========================================================================\n\n  /**\n   * Check abort signal and notify observers if aborted.\n   * @returns true if agent should terminate\n   */\n  private async checkAbortAndNotify(iteration: number): Promise<boolean> {\n    if (!this.signal?.aborted) return false;\n\n    this.logger.info(\"Agent loop terminated by abort signal\", {\n      iteration,\n      reason: this.signal.reason,\n    });\n\n    await safeObserve(async () => {\n      if (this.hooks.observers?.onAbort) {\n        const context: ObserveAbortContext = {\n          iteration,\n          reason: this.signal?.reason,\n          logger: this.logger,\n        };\n        await this.hooks.observers.onAbort(context);\n      }\n    }, this.logger);\n\n    return true;\n  }\n\n  /**\n   * Check and perform context compaction if needed.\n   * @returns compaction stream event if compaction occurred, null otherwise\n   */\n  private async checkAndPerformCompaction(iteration: number): Promise<StreamEvent | null> {\n    if (!this.compactionManager) return null;\n\n    const compactionEvent = await this.compactionManager.checkAndCompact(\n      this.conversation,\n      iteration,\n    );\n\n    if (!compactionEvent) return null;\n\n    return this.emitCompactionEvent(compactionEvent, iteration);\n  }\n\n  /**\n   * Log compaction, notify observers, and return a StreamEvent.\n   * Shared by proactive compaction (checkAndPerformCompaction) and\n   * reactive overflow recovery (catch block).\n   */\n  private async emitCompactionEvent(\n    compactionEvent: CompactionEvent,\n    iteration: number,\n  ): Promise<StreamEvent> {\n    this.logger.info(\"Context compacted\", {\n      strategy: compactionEvent.strategy,\n      tokensBefore: compactionEvent.tokensBefore,\n      tokensAfter: compactionEvent.tokensAfter,\n    });\n\n    await safeObserve(async () => {\n      if (this.hooks.observers?.onCompaction) {\n        await this.hooks.observers.onCompaction({\n          iteration,\n          event: compactionEvent,\n          // biome-ignore lint/style/noNonNullAssertion: compactionManager exists if compactionEvent is truthy\n          stats: this.compactionManager!.getStats(),\n          logger: this.logger,\n        });\n      }\n    }, this.logger);\n\n    return { type: \"compaction\", event: compactionEvent } as StreamEvent;\n  }\n\n  /**\n   * Run agent with named event handlers (syntactic sugar).\n   *\n   * Instead of verbose if/else chains, use named handlers for cleaner code.\n   *\n   * @param handlers - Named event handlers\n   *\n   * @example\n   * ```typescript\n   * await agent.runWith({\n   *   onText: (text) => console.log(\"LLM:\", text),\n   *   onGadgetResult: (result) => console.log(\"Result:\", result.result),\n   *   onGadgetCall: (call) => console.log(\"Calling:\", call.gadgetName),\n   * });\n   * ```\n   */\n  async runWith(handlers: EventHandlers): Promise<void> {\n    return runWithHandlers(this.run(), handlers);\n  }\n}\n","// Re-export Zod's z for schema definitions\n// Using llmist's z ensures .describe() metadata is preserved in JSON schemas\nexport { z } from \"zod\";\n// Agent class (for type references)\nexport { Agent } from \"./agent/agent.js\";\n// Syntactic sugar: Agent builder and event handlers\nexport type { HistoryMessage } from \"./agent/builder.js\";\nexport { AgentBuilder } from \"./agent/builder.js\";\nexport type { EventHandlers } from \"./agent/event-handlers.js\";\nexport { collectEvents, collectText, runWithHandlers } from \"./agent/event-handlers.js\";\n// File-based logging for debugging and auditing\nexport type {\n  FileLoggingOptions,\n  FileLoggingState,\n  FileWrittenInfo,\n} from \"./agent/file-logging.js\";\nexport {\n  createFileLoggingState,\n  formatCallNumber,\n  formatLlmRequest,\n  resetFileLoggingState,\n} from \"./agent/file-logging.js\";\nexport type { TrailingMessage, TrailingMessageContext } from \"./agent/hook-composer.js\";\n// Syntactic sugar: Hook presets\nexport type { LoggingOptions } from \"./agent/hook-presets.js\";\nexport { HookPresets } from \"./agent/hook-presets.js\";\n// Agent infrastructure\n// New clean hooks system\nexport type {\n  AfterGadgetExecutionAction,\n  AfterGadgetExecutionControllerContext,\n  AfterLLMCallAction,\n  AfterLLMCallControllerContext,\n  AfterLLMErrorAction,\n  AgentHooks,\n  AgentOptions,\n  BeforeGadgetExecutionAction,\n  BeforeLLMCallAction,\n  BeforeSkillActivationAction,\n  // Interceptor contexts\n  ChunkInterceptorContext,\n  // Context compaction\n  CompactionConfig,\n  CompactionContext,\n  CompactionEvent,\n  CompactionResult,\n  CompactionStats,\n  CompactionStrategy,\n  Controllers,\n  GadgetExecutionControllerContext,\n  GadgetParameterInterceptorContext,\n  GadgetResultInterceptorContext,\n  // LLM Assistance Hints\n  HintsConfig,\n  IConversationManager,\n  Interceptors,\n  IterationHintOptions,\n  // Controller contexts and actions\n  LLMCallControllerContext,\n  LLMErrorControllerContext,\n  MessageInterceptorContext,\n  MessageTurn,\n  ObserveChunkContext,\n  ObserveCompactionContext,\n  ObserveGadgetArgsPartialContext,\n  ObserveGadgetCompleteContext,\n  ObserveGadgetStartContext,\n  // Observer contexts\n  ObserveLLMCallContext,\n  ObserveLLMCompleteContext,\n  ObserveLLMErrorContext,\n  ObserveRateLimitThrottleContext,\n  ObserveRetryAttemptContext,\n  Observers,\n  // Skill hook contexts\n  ObserveSkillActivatedContext,\n  // Gadget output limit configuration\n  OutputLimitConfig,\n  ParallelGadgetHintOptions,\n  // Gadget prefix configuration\n  PrefixConfig,\n  ResolvedCompactionConfig,\n  SkillActivationControllerContext,\n  SkillInstructionInterceptorContext,\n  // Gadget output limiting\n  StoredOutput,\n  StreamProcessingResult,\n  StreamProcessorOptions,\n  // Subagent context for hook observers\n  SubagentContext,\n  // Execution tree configuration\n  TreeConfig,\n} from \"./agent/index.js\";\nexport {\n  // Compaction exports\n  CompactionManager,\n  // Existing exports\n  ConversationManager,\n  // LLM Assistance Hints\n  createHints,\n  DEFAULT_COMPACTION_CONFIG,\n  DEFAULT_SUMMARIZATION_PROMPT,\n  GadgetOutputStore,\n  HybridStrategy,\n  iterationProgressHint,\n  parallelGadgetHint,\n  SlidingWindowStrategy,\n  StreamProcessor,\n  SummarizationStrategy,\n} from \"./agent/index.js\";\nexport type { LLMistOptions } from \"./core/client.js\";\nexport { LLMist } from \"./core/client.js\";\n// Constants for gadget block format parsing\nexport {\n  GADGET_ARG_PREFIX,\n  GADGET_END_PREFIX,\n  GADGET_START_PREFIX,\n} from \"./core/constants.js\";\n// Error utilities\nexport { EmptyCompletionError, isAbortError } from \"./core/errors.js\";\n// Unified execution events with tree context\nexport type {\n  BaseExecutionEvent,\n  CompactionEvent as TreeCompactionEvent,\n  ExecutionEvent,\n  ExecutionEventType,\n  GadgetCallEvent,\n  GadgetCompleteEvent,\n  GadgetErrorEvent,\n  GadgetEvent,\n  GadgetSkippedEvent as TreeGadgetSkippedEvent,\n  GadgetStartEvent,\n  HumanInputRequiredEvent,\n  LLMCallCompleteEvent,\n  LLMCallErrorEvent,\n  LLMCallStartEvent,\n  LLMCallStreamEvent,\n  LLMEvent,\n  LLMResponseEndEvent,\n  StreamCompleteEvent,\n  TextEvent,\n  ThinkingEvent,\n} from \"./core/execution-events.js\";\nexport {\n  filterByDepth,\n  filterByParent,\n  filterRootEvents,\n  groupByParent,\n  isGadgetEvent,\n  isLLMEvent,\n  isRootEvent,\n  isSubagentEvent,\n} from \"./core/execution-events.js\";\n// Execution Tree - first-class model for nested subagent support\nexport type {\n  AddGadgetParams,\n  AddLLMCallParams,\n  CompleteGadgetParams,\n  CompleteLLMCallParams,\n  ExecutionNode,\n  ExecutionNodeType,\n  GadgetNode,\n  GadgetState,\n  LLMCallNode,\n  NodeId,\n} from \"./core/execution-tree.js\";\nexport { ExecutionTree } from \"./core/execution-tree.js\";\n// Input content types for multimodal messages\nexport type {\n  AudioContentPart,\n  AudioMimeType,\n  AudioSource,\n  ContentPart,\n  ImageBase64Source,\n  ImageContentPart,\n  ImageMimeType,\n  ImageSource,\n  ImageUrlSource,\n  TextContentPart,\n} from \"./core/input-content.js\";\nexport {\n  audioFromBase64,\n  audioFromBuffer,\n  detectAudioMimeType,\n  detectImageMimeType,\n  imageFromBase64,\n  imageFromBuffer,\n  imageFromUrl,\n  isAudioPart,\n  isDataUrl,\n  isImagePart,\n  isTextPart,\n  parseDataUrl,\n  text,\n  toBase64,\n} from \"./core/input-content.js\";\n// Media generation types (image, speech)\nexport type {\n  ImageGenerationOptions,\n  ImageGenerationResult,\n  ImageModelSpec,\n  SpeechGenerationOptions,\n  SpeechGenerationResult,\n  SpeechModelSpec,\n} from \"./core/media-types.js\";\nexport type { LLMMessage, MessageContent, MessageRole } from \"./core/messages.js\";\nexport { extractMessageText, LLMMessageBuilder, normalizeMessageContent } from \"./core/messages.js\";\n// Model catalog\nexport type {\n  CostEstimate,\n  ModelFeatures,\n  ModelLimits,\n  ModelPricing,\n  ModelSpec,\n} from \"./core/model-catalog.js\";\nexport { ModelRegistry } from \"./core/model-registry.js\";\n// Syntactic sugar: Model shortcuts and quick methods\nexport {\n  getModelId,\n  getProvider,\n  hasProviderPrefix,\n  MODEL_ALIASES,\n  resolveModel,\n  stripProviderPrefix,\n} from \"./core/model-shortcuts.js\";\n// Vision namespace for one-shot image analysis\nexport type { VisionAnalyzeOptions, VisionAnalyzeResult } from \"./core/namespaces/vision.js\";\nexport type {\n  CachingConfig,\n  CachingScope,\n  LLMGenerationOptions,\n  LLMStream,\n  LLMStreamChunk,\n  ModelDescriptor,\n  ProviderIdentifier,\n  ReasoningConfig,\n  ReasoningEffort,\n  ThinkingChunk,\n  TokenUsage,\n} from \"./core/options.js\";\nexport { ModelIdentifierParser } from \"./core/options.js\";\nexport type {\n  HintContext,\n  HintTemplate,\n  PromptContext,\n  PromptTemplate,\n  PromptTemplateConfig,\n} from \"./core/prompt-config.js\";\nexport {\n  DEFAULT_HINTS,\n  DEFAULT_PROMPTS,\n  resolveHintTemplate,\n  resolvePromptTemplate,\n  resolveRulesTemplate,\n} from \"./core/prompt-config.js\";\nexport type { TextGenerationOptions } from \"./core/quick-methods.js\";\nexport { complete, stream } from \"./core/quick-methods.js\";\n// Rate limit configuration for proactive throttling\nexport type {\n  RateLimitConfig,\n  RateLimitStats,\n  ResolvedRateLimitConfig,\n  TriggeredLimitInfo,\n} from \"./core/rate-limit.js\";\nexport {\n  DEFAULT_RATE_LIMIT_CONFIG,\n  RateLimitTracker,\n  resolveRateLimitConfig,\n} from \"./core/rate-limit.js\";\n// Retry configuration for LLM API calls\nexport type {\n  FormatLLMErrorContext,\n  ResolvedRetryConfig,\n  RetryConfig,\n} from \"./core/retry.js\";\nexport {\n  DEFAULT_RETRY_CONFIG,\n  extractRetryAfterMs,\n  formatLLMError,\n  isLikelyContextOverflow,\n  isRetryableError,\n  parseRetryAfterHeader,\n  resolveRetryConfig,\n} from \"./core/retry.js\";\nexport type { CreateGadgetConfig } from \"./gadgets/create-gadget.js\";\nexport { createGadget } from \"./gadgets/create-gadget.js\";\n// Gadget infrastructure\nexport {\n  AbortException,\n  BudgetPricingUnavailableError,\n  HumanInputRequiredException,\n  TaskCompletionSignal,\n  TimeoutException,\n} from \"./gadgets/exceptions.js\";\nexport { GadgetExecutor, type GadgetExecutorOptions } from \"./gadgets/executor.js\";\nexport { AbstractGadget } from \"./gadgets/gadget.js\";\n// Response and media output helpers for gadgets\nexport {\n  // Media output\n  createMediaOutput,\n  // Response formatting\n  gadgetError,\n  gadgetSuccess,\n  getErrorMessage,\n  resultWithAudio,\n  resultWithFile,\n  resultWithImage,\n  resultWithImages,\n  resultWithMedia,\n  withErrorHandling,\n} from \"./gadgets/helpers.js\";\n// Gadget output viewer (for custom output store integration)\nexport { createGadgetOutputViewer } from \"./gadgets/output-viewer.js\";\nexport { GadgetCallParser } from \"./gadgets/parser.js\";\nexport type { GadgetClass, GadgetOrClass } from \"./gadgets/registry.js\";\nexport { GadgetRegistry } from \"./gadgets/registry.js\";\n// Syntactic sugar: Typed gadgets and helpers\nexport type { GadgetConfig } from \"./gadgets/typed-gadget.js\";\nexport { Gadget } from \"./gadgets/typed-gadget.js\";\nexport type {\n  CostReportingLLMist,\n  ExecutionContext,\n  GadgetArgsPartialEvent,\n  GadgetExample,\n  GadgetExecuteResult,\n  GadgetExecuteResultWithMedia,\n  GadgetExecuteReturn,\n  GadgetExecutionMode,\n  GadgetExecutionResult,\n  GadgetMediaOutput,\n  GadgetSkippedEvent,\n  // Host exports for external gadgets\n  HostExports,\n  MediaKind,\n  MediaMetadata,\n  ParsedGadgetCall,\n  StoredMedia,\n  StreamEvent,\n  // Subagent config types\n  SubagentConfig,\n  SubagentConfigMap,\n  TextOnlyAction,\n  TextOnlyContext,\n  TextOnlyCustomHandler,\n  TextOnlyGadgetConfig,\n  TextOnlyHandler,\n  TextOnlyStrategy,\n} from \"./gadgets/types.js\";\n// ============================================================================\n// Model Context Protocol (MCP) integration\n// ============================================================================\nexport {\n  assertCommandAllowed,\n  type CreateMcpServerOptions,\n  createMcpServer,\n  DEFAULT_MCP_COMMAND_ALLOWLIST,\n  gadgetResultToMcpContent,\n  gadgetToMcpTool,\n  type HttpMcpServerSpec,\n  type JSONSchemaLike,\n  JsonSchemaConversionError,\n  jsonSchemaToZod,\n  McpClient,\n  type McpClientOptions,\n  McpConnectError,\n  type McpContentBlock,\n  McpError,\n  McpLifecycle,\n  type McpServerCapabilities,\n  type McpServerHandle,\n  type McpServerSpec,\n  type McpToolAdapterOptions,\n  McpToolCallError,\n  type McpToolDescriptor,\n  type McpToolResult,\n  McpUntrustedCommandError,\n  mcpToolToGadget,\n  renderSkillForMcpPrompt,\n  runGadgetForMcp,\n  type StdioMcpServerSpec,\n  skillToMcpPrompt,\n} from \"./mcp/index.js\";\n// Provider constants (for token estimation)\nexport { FALLBACK_CHARS_PER_TOKEN } from \"./providers/constants.js\";\nexport type {\n  ResearchCapabilities,\n  ResearchCitation,\n  ResearchDoneInfo,\n  ResearchErrorInfo,\n  ResearchEvent,\n  ResearchJob,\n  ResearchJobRef,\n  ResearchModelMetadata,\n  ResearchModelSpec,\n  ResearchOptions,\n  ResearchPricing,\n  ResearchResult,\n  ResearchStatus,\n  ResearchStatusSnapshot,\n  ResearchToolConfig,\n  ResearchToolType,\n  ResearchUsage,\n} from \"./research/index.js\";\n// Deep research (spec 002)\nexport {\n  estimateResearchCost,\n  RESEARCH_DATA_SOURCE_TOOL_TYPES,\n  ResearchDeprecatedModelError,\n  ResearchJobNotResumableError,\n  ResearchNamespace,\n  ResearchNotPollableError,\n  ResearchNotSupportedError,\n  ResearchResultCollector,\n  ResearchStreamConsumedError,\n  ResearchTimeoutError,\n  ResearchValidationError,\n} from \"./research/index.js\";\n\n// Host exports helper for external gadgets\nimport type { ExecutionContext, HostExports } from \"./gadgets/types.js\";\n\n/**\n * Get host llmist exports from execution context.\n *\n * External gadgets MUST use this instead of importing classes directly from 'llmist'\n * to ensure they use the same version as the host CLI, enabling proper tree sharing\n * and avoiding the \"dual-package problem\".\n *\n * @param ctx - The execution context passed to gadget.execute()\n * @returns The host's llmist exports (AgentBuilder, Gadget, etc.)\n * @throws Error if ctx or ctx.hostExports is undefined\n *\n * @example\n * ```typescript\n * import { getHostExports, Gadget, z } from 'llmist';\n * import type { ExecutionContext } from 'llmist';\n *\n * class BrowseWeb extends Gadget({\n *   name: 'BrowseWeb',\n *   description: 'Browse a website autonomously',\n *   schema: z.object({ task: z.string(), url: z.string() }),\n * }) {\n *   async execute(params: this['params'], ctx?: ExecutionContext) {\n *     // Get host's AgentBuilder to ensure tree sharing works correctly\n *     const { AgentBuilder } = getHostExports(ctx!);\n *\n *     const agent = new AgentBuilder()\n *       .withParentContext(ctx!)\n *       .withGadgets(Navigate, Click, Screenshot)\n *       .ask(params.task);\n *\n *     for await (const event of agent.run()) {\n *       // Events flow through host's shared tree\n *     }\n *   }\n * }\n * ```\n */\nexport function getHostExports(ctx: ExecutionContext): HostExports {\n  if (!ctx?.hostExports) {\n    throw new Error(\n      \"hostExports not available. Gadgets that create subagents must be run \" +\n        \"via llmist agent, not standalone. Ensure you are using llmist >= 6.2.0.\",\n    );\n  }\n  return ctx.hostExports;\n}\n// Re-export Logger type for external gadgets that need to type ctx.logger\nexport type { ILogObj, Logger } from \"tslog\";\n// ============================================================================\n// Subagent Helpers\n// ============================================================================\nexport type { SubagentOptions } from \"./agent/subagent.js\";\nexport { createSubagent, hasHostExports } from \"./agent/subagent.js\";\n// Media storage for gadget outputs\nexport { MediaStore } from \"./gadgets/media-store.js\";\n// Schema utilities\nexport { schemaToJSONSchema } from \"./gadgets/schema-to-json.js\";\nexport { validateGadgetSchema } from \"./gadgets/schema-validator.js\";\nexport type { ValidationIssue, ValidationResult } from \"./gadgets/validation.js\";\nexport { validateAndApplyDefaults, validateGadgetParams } from \"./gadgets/validation.js\";\nexport type { LoggerOptions } from \"./logging/logger.js\";\nexport { createLogger, defaultLogger } from \"./logging/logger.js\";\n// ============================================================================\n// Package Manifest Types\n// ============================================================================\nexport type {\n  GadgetFactoryExports,\n  LLMistPackageManifest,\n  PresetDefinition,\n  SessionManifestEntry,\n  SubagentManifestEntry,\n} from \"./package/index.js\";\nexport {\n  getPresetGadgets,\n  getSubagent,\n  hasPreset,\n  hasSubagents,\n  listPresets,\n  listSubagents,\n  parseManifest,\n} from \"./package/index.js\";\nexport {\n  AnthropicMessagesProvider,\n  createAnthropicProviderFromEnv,\n} from \"./providers/anthropic.js\";\nexport { discoverProviderAdapters } from \"./providers/discovery.js\";\nexport { createGeminiProviderFromEnv, GeminiGenerativeProvider } from \"./providers/gemini.js\";\nexport {\n  createHuggingFaceProviderFromEnv,\n  HuggingFaceProvider,\n} from \"./providers/huggingface.js\";\nexport { createOpenAIProviderFromEnv, OpenAIChatProvider } from \"./providers/openai.js\";\n// OpenAI-compatible base class for meta-providers (HuggingFace, OpenRouter, etc.)\nexport type { OpenAICompatibleConfig } from \"./providers/openai-compatible-provider.js\";\nexport { OpenAICompatibleProvider } from \"./providers/openai-compatible-provider.js\";\n// OpenRouter meta-provider (400+ models via unified gateway)\nexport type { OpenRouterConfig, OpenRouterRouting } from \"./providers/openrouter.js\";\nexport {\n  createOpenRouterProviderFromEnv,\n  OpenRouterProvider,\n} from \"./providers/openrouter.js\";\nexport type { ProviderAdapter } from \"./providers/provider.js\";\n// ============================================================================\n// Session Management\n// ============================================================================\nexport type { ISessionManager } from \"./session/index.js\";\nexport { BaseSessionManager, SimpleSessionManager } from \"./session/index.js\";\n// ============================================================================\n// Skills System (Agent Skills Open Standard)\n// ============================================================================\nexport type {\n  ParsedSkill,\n  SkillActivation,\n  SkillActivationOptions,\n  SkillMetadata,\n  SkillResource,\n  SkillSource,\n} from \"./skills/index.js\";\nexport {\n  createLoadSkillGadget,\n  discoverSkills,\n  LOAD_SKILL_GADGET_NAME,\n  loadSkillsFromDirectory,\n  parseFrontmatter,\n  parseMetadata,\n  parseSkillContent,\n  parseSkillFile,\n  resolveInstructions,\n  Skill,\n  SkillRegistry,\n  scanResources,\n  substituteArguments,\n  substituteVariables,\n  validateMetadata,\n} from \"./skills/index.js\";\n// Utility functions for subagent gadgets\nexport type { ResolveValueOptions } from \"./utils/config-resolver.js\";\nexport {\n  resolveConfig,\n  resolveSubagentModel,\n  resolveSubagentTimeout,\n  resolveValue,\n} from \"./utils/config-resolver.js\";\n// ============================================================================\n// Formatting Utilities\n// ============================================================================\nexport {\n  format,\n  formatBytes,\n  formatDate,\n  formatDuration,\n  truncate,\n} from \"./utils/format.js\";\n// ============================================================================\n// Timing Utilities\n// ============================================================================\nexport type { RetryOptions } from \"./utils/timing.js\";\nexport {\n  humanDelay,\n  randomDelay,\n  timing,\n  withRetry,\n  withTimeout,\n} from \"./utils/timing.js\";\n","/**\n * Context Compaction System\n *\n * Automatically manages conversation context to prevent context window overflow\n * in long-running agent conversations.\n *\n * Features:\n * - Automatic threshold monitoring (default: 80% of context window)\n * - Multiple strategies: sliding-window, summarization, hybrid (default)\n * - Full visibility via StreamEvents and hooks\n * - Enabled by default with sensible defaults\n *\n * @example\n * ```typescript\n * // Auto-enabled with defaults\n * const agent = await LLMist.createAgent()\n *   .withModel('sonnet')\n *   .ask('Help me...');\n *\n * // Custom configuration\n * const agent = await LLMist.createAgent()\n *   .withModel('gpt-4')\n *   .withCompaction({\n *     triggerThresholdPercent: 70,\n *     preserveRecentTurns: 10,\n *   })\n *   .ask('...');\n *\n * // Disable compaction\n * const agent = await LLMist.createAgent()\n *   .withModel('sonnet')\n *   .withoutCompaction()\n *   .ask('...');\n * ```\n */\n\n// Configuration\nexport {\n  type CompactionConfig,\n  type CompactionEvent,\n  type CompactionStats,\n  DEFAULT_COMPACTION_CONFIG,\n  DEFAULT_SUMMARIZATION_PROMPT,\n  type ResolvedCompactionConfig,\n  resolveCompactionConfig,\n} from \"./config.js\";\n// Manager\nexport { CompactionManager } from \"./manager.js\";\n\n// Strategy implementations\nexport {\n  HybridStrategy,\n  SlidingWindowStrategy,\n  SummarizationStrategy,\n} from \"./strategies/index.js\";\n// Strategy interface and utilities\nexport {\n  type CompactionContext,\n  type CompactionResult,\n  type CompactionStrategy,\n  flattenTurns,\n  groupIntoTurns,\n  type MessageTurn,\n} from \"./strategy.js\";\n","/**\n * Agent module - Composable, single-responsibility architecture for LLM agents.\n * This module provides a cleaner alternative to the monolithic AgentLoop.\n */\n\nexport type { AgentOptions, PrefixConfig, TreeConfig } from \"./agent.js\";\n// Context compaction\nexport {\n  type CompactionConfig,\n  type CompactionContext,\n  type CompactionEvent,\n  CompactionManager,\n  type CompactionResult,\n  type CompactionStats,\n  type CompactionStrategy,\n  DEFAULT_COMPACTION_CONFIG,\n  DEFAULT_SUMMARIZATION_PROMPT,\n  HybridStrategy,\n  type MessageTurn,\n  type ResolvedCompactionConfig,\n  SlidingWindowStrategy,\n  SummarizationStrategy,\n} from \"./compaction/index.js\";\nexport { ConversationManager } from \"./conversation-manager.js\";\n// Gadget output limiting\nexport type { StoredOutput } from \"./gadget-output-store.js\";\nexport { GadgetOutputStore } from \"./gadget-output-store.js\";\n// LLM Assistance Hints\nexport {\n  createHints,\n  type HintsConfig,\n  type IterationHintOptions,\n  iterationProgressHint,\n  type ParallelGadgetHintOptions,\n  parallelGadgetHint,\n} from \"./hints.js\";\n// New clean hooks system\nexport type {\n  AfterGadgetExecutionAction,\n  AfterGadgetExecutionControllerContext,\n  AfterLLMCallAction,\n  AfterLLMCallControllerContext,\n  AfterLLMErrorAction,\n  AgentHooks,\n  BeforeGadgetExecutionAction,\n  BeforeLLMCallAction,\n  BeforeSkillActivationAction,\n  // Interceptor contexts\n  ChunkInterceptorContext,\n  Controllers,\n  // Dependency skip controller\n  DependencySkipAction,\n  DependencySkipControllerContext,\n  GadgetExecutionControllerContext,\n  GadgetParameterInterceptorContext,\n  GadgetResultInterceptorContext,\n  Interceptors,\n  // Controller contexts and actions\n  LLMCallControllerContext,\n  LLMErrorControllerContext,\n  MessageInterceptorContext,\n  ObserveChunkContext,\n  ObserveCompactionContext,\n  ObserveGadgetArgsPartialContext,\n  ObserveGadgetCompleteContext,\n  // Gadget skip observer\n  ObserveGadgetSkippedContext,\n  ObserveGadgetStartContext,\n  // Observer contexts\n  ObserveLLMCallContext,\n  ObserveLLMCompleteContext,\n  ObserveLLMErrorContext,\n  ObserveRateLimitThrottleContext,\n  ObserveRetryAttemptContext,\n  Observers,\n  // Skill hook contexts\n  ObserveSkillActivatedContext,\n  SkillActivationControllerContext,\n  SkillInstructionInterceptorContext,\n  // Subagent context for distinguishing subagent events in hooks\n  SubagentContext,\n} from \"./hooks.js\";\nexport type { IConversationManager } from \"./interfaces.js\";\n// Gadget output limit configuration (OutputLimitConfig is defined in output-limit-manager)\nexport type { OutputLimitConfig } from \"./output-limit-manager.js\";\n// Shared observer error-handling utility\nexport { safeObserve } from \"./safe-observe.js\";\n// StreamProcessor for advanced use cases\nexport {\n  type StreamProcessingResult,\n  StreamProcessor,\n  type StreamProcessorOptions,\n} from \"./stream-processor.js\";\n","/**\n * LLM Assistance Hints System\n *\n * Provides reusable hook factories that inject helpful context and coaching\n * messages to guide LLM behavior during agentic execution.\n *\n * ## Two Types of Hints\n *\n * 1. **Proactive (beforeLLMCall)**: Inject context before LLM generates response\n *    - Example: Iteration progress (\"You're on iteration 3/10\")\n *\n * 2. **Reactive (afterLLMCall)**: Coach based on what LLM did\n *    - Example: \"Tip: You can call multiple gadgets in parallel\"\n *\n * ## Usage\n *\n * ```typescript\n * import { createHints, iterationProgressHint, parallelGadgetHint } from \"llmist\";\n *\n * // Option 1: Use individual hints\n * const agent = new AgentBuilder()\n *   .withHooks(HookPresets.merge(\n *     iterationProgressHint({ timing: \"late\" }),\n *     parallelGadgetHint(),\n *   ))\n *   .build();\n *\n * // Option 2: Use convenience factory\n * const agent = new AgentBuilder()\n *   .withHooks(createHints({\n *     iterationProgress: { timing: \"late\" },\n *     parallelGadgets: true,\n *   }))\n *   .build();\n * ```\n *\n * @module agent/hints\n */\n\nimport {\n  DEFAULT_HINTS,\n  type HintContext,\n  type HintTemplate,\n  resolveHintTemplate,\n} from \"../core/prompt-config.js\";\nimport { HookPresets } from \"./hook-presets.js\";\nimport type { AgentHooks } from \"./hooks.js\";\n\n// ============================================================================\n// CONFIGURATION TYPES\n// ============================================================================\n\n/**\n * Options for iteration progress hint.\n */\nexport interface IterationHintOptions {\n  /**\n   * When to show the hint.\n   * - \"always\": Show on every iteration\n   * - \"late\": Show only when >= 50% through iterations\n   * - \"urgent\": Show only when >= 80% through iterations\n   * @default \"always\"\n   */\n  timing?: \"always\" | \"late\" | \"urgent\";\n\n  /**\n   * Whether to include urgency indicators for late iterations.\n   * Adds extra text when running low on iterations.\n   * @default true\n   */\n  showUrgency?: boolean;\n\n  /**\n   * Custom template. Supports placeholders: {iteration}, {maxIterations}, {remaining}\n   * Or a function receiving HintContext.\n   * @default DEFAULT_HINTS.iterationProgressHint\n   */\n  template?: HintTemplate;\n}\n\n/**\n * Options for parallel gadget usage hint.\n */\nexport interface ParallelGadgetHintOptions {\n  /**\n   * Minimum number of gadget calls to consider \"efficient\".\n   * If response has fewer calls, hint will suggest parallelization.\n   * @default 2\n   */\n  minGadgetsForEfficiency?: number;\n\n  /**\n   * Custom message when single gadget detected.\n   * @default DEFAULT_HINTS.parallelGadgetsHint\n   */\n  message?: string;\n\n  /**\n   * Whether to enable this hint.\n   * @default true\n   */\n  enabled?: boolean;\n}\n\n/**\n * Combined hints configuration for createHints().\n */\nexport interface HintsConfig {\n  /**\n   * Enable iteration progress hints.\n   * Pass `true` for defaults, or options object for customization.\n   */\n  iterationProgress?: boolean | IterationHintOptions;\n\n  /**\n   * Enable parallel gadget hints.\n   * Pass `true` for defaults, or options object for customization.\n   */\n  parallelGadgets?: boolean | ParallelGadgetHintOptions;\n\n  /**\n   * Additional custom hooks to merge.\n   */\n  custom?: AgentHooks[];\n}\n\n// ============================================================================\n// HINT FACTORIES\n// ============================================================================\n\n/**\n * Creates a proactive hint that informs the LLM about iteration progress.\n *\n * This hint is injected before each LLM call (via beforeLLMCall controller),\n * helping the LLM understand how much \"budget\" remains for completing the task.\n *\n * @param options - Configuration options\n * @returns AgentHooks that can be merged with other hooks\n *\n * @example\n * ```typescript\n * // Basic usage - show on every iteration\n * const hooks = iterationProgressHint();\n *\n * // Show only when running low on iterations\n * const hooks = iterationProgressHint({ timing: \"late\" });\n *\n * // Custom template\n * const hooks = iterationProgressHint({\n *   template: \"Turn {iteration} of {maxIterations}. {remaining} turns left.\",\n * });\n * ```\n */\nexport function iterationProgressHint(options?: IterationHintOptions): AgentHooks {\n  const { timing = \"always\", showUrgency = true, template } = options ?? {};\n\n  return {\n    controllers: {\n      beforeLLMCall: async (ctx) => {\n        const iteration = ctx.iteration + 1; // 1-based for user-friendliness\n        const maxIterations = ctx.maxIterations;\n        const progress = iteration / maxIterations;\n\n        // Check timing condition\n        if (timing === \"late\" && progress < 0.5) {\n          return { action: \"proceed\" };\n        }\n        if (timing === \"urgent\" && progress < 0.8) {\n          return { action: \"proceed\" };\n        }\n\n        // Build hint context with all fields populated\n        const remaining = maxIterations - iteration;\n        const hintContext: HintContext = {\n          iteration,\n          maxIterations,\n          remaining,\n        };\n\n        // Resolve template\n        let hint = resolveHintTemplate(template, DEFAULT_HINTS.iterationProgressHint, hintContext);\n\n        // Add urgency indicator if late in iterations\n        if (showUrgency && progress >= 0.8) {\n          hint += \" ⚠️ Running low on iterations - focus on completing the task.\";\n        }\n\n        // Inject as system-level context in messages\n        const messages = [...ctx.options.messages];\n\n        // Find last user message index (compatible with older ES targets)\n        let lastUserIndex = -1;\n        for (let i = messages.length - 1; i >= 0; i--) {\n          if (messages[i].role === \"user\") {\n            lastUserIndex = i;\n            break;\n          }\n        }\n\n        if (lastUserIndex >= 0) {\n          // Insert hint after the last user message\n          messages.splice(lastUserIndex + 1, 0, {\n            role: \"user\",\n            content: `[System Hint] ${hint}`,\n          });\n        } else {\n          // No user messages found - append hint at the end\n          messages.push({\n            role: \"user\",\n            content: `[System Hint] ${hint}`,\n          });\n        }\n\n        return {\n          action: \"proceed\",\n          modifiedOptions: { messages },\n        };\n      },\n    },\n  };\n}\n\n/**\n * Creates a reactive hint that encourages parallel gadget usage.\n *\n * This hint analyzes the LLM's response and, if only a single gadget was called,\n * appends a reminder that multiple gadgets can be used in parallel for efficiency.\n *\n * @param options - Configuration options\n * @returns AgentHooks that can be merged with other hooks\n *\n * @example\n * ```typescript\n * // Basic usage\n * const hooks = parallelGadgetHint();\n *\n * // Custom threshold and message\n * const hooks = parallelGadgetHint({\n *   minGadgetsForEfficiency: 3,\n *   message: \"Consider calling multiple gadgets at once!\",\n * });\n * ```\n */\nexport function parallelGadgetHint(options?: ParallelGadgetHintOptions): AgentHooks {\n  const {\n    minGadgetsForEfficiency = 2,\n    message = DEFAULT_HINTS.parallelGadgetsHint,\n    enabled = true,\n  } = options ?? {};\n\n  return {\n    controllers: {\n      afterLLMCall: async (ctx) => {\n        if (!enabled) {\n          return { action: \"continue\" };\n        }\n\n        // Only hint if gadgets were called but below efficiency threshold\n        if (ctx.gadgetCallCount > 0 && ctx.gadgetCallCount < minGadgetsForEfficiency) {\n          return {\n            action: \"append_messages\",\n            messages: [\n              {\n                role: \"user\",\n                content: `[System Hint] ${message}`,\n              },\n            ],\n          };\n        }\n\n        return { action: \"continue\" };\n      },\n    },\n  };\n}\n\n// ============================================================================\n// CONVENIENCE FACTORY\n// ============================================================================\n\n/**\n * Creates combined hints from a configuration object.\n *\n * This is a convenience function that creates and merges multiple hints\n * based on a simple configuration object.\n *\n * @param config - Configuration for which hints to enable\n * @returns Merged AgentHooks\n *\n * @example\n * ```typescript\n * const hooks = createHints({\n *   iterationProgress: { timing: \"late\" },\n *   parallelGadgets: true,\n * });\n *\n * const agent = new AgentBuilder()\n *   .withHooks(HookPresets.merge(existingHooks, hooks))\n *   .build();\n * ```\n */\nexport function createHints(config: HintsConfig): AgentHooks {\n  const hooksToMerge: AgentHooks[] = [];\n\n  // Iteration progress hint\n  if (config.iterationProgress) {\n    const options = typeof config.iterationProgress === \"boolean\" ? {} : config.iterationProgress;\n    hooksToMerge.push(iterationProgressHint(options));\n  }\n\n  // Parallel gadgets hint\n  if (config.parallelGadgets) {\n    const options = typeof config.parallelGadgets === \"boolean\" ? {} : config.parallelGadgets;\n    hooksToMerge.push(parallelGadgetHint(options));\n  }\n\n  // Custom hooks\n  if (config.custom) {\n    hooksToMerge.push(...config.custom);\n  }\n\n  return HookPresets.merge(...hooksToMerge);\n}\n","/**\n * Unified event types for the Execution Tree.\n *\n * All events carry full tree context (nodeId, parentId, depth, path).\n * No special SubagentEvent wrapper needed - subagent events are regular\n * events with depth > 0.\n *\n * @module core/execution-events\n */\n\nimport type { GadgetMediaOutput, StoredMedia } from \"../gadgets/types.js\";\nimport type { LLMMessage } from \"./messages.js\";\nimport type { TokenUsage } from \"./options.js\";\n\n// =============================================================================\n// Base Event Properties\n// =============================================================================\n\n/**\n * Base properties shared by all execution events.\n * Every event carries full tree context.\n */\nexport interface BaseExecutionEvent {\n  /** Monotonically increasing event ID */\n  eventId: number;\n  /** Event timestamp */\n  timestamp: number;\n  /** Node that emitted this event */\n  nodeId: string;\n  /** Parent node ID (null for root events) */\n  parentId: string | null;\n  /** Nesting depth (0 = root, 1 = child, etc.) */\n  depth: number;\n  /** Full path from root to this node */\n  path: string[];\n}\n\n// =============================================================================\n// LLM Call Events\n// =============================================================================\n\n/**\n * Emitted when an LLM call starts.\n */\nexport interface LLMCallStartEvent extends BaseExecutionEvent {\n  type: \"llm_call_start\";\n  /** Iteration number within agent loop (1-indexed) */\n  iteration: number;\n  /** Model identifier */\n  model: string;\n  /** Request messages */\n  request?: LLMMessage[];\n}\n\n/**\n * Emitted for each streaming chunk from LLM.\n */\nexport interface LLMCallStreamEvent extends BaseExecutionEvent {\n  type: \"llm_call_stream\";\n  /** Text chunk */\n  chunk: string;\n}\n\n/**\n * Emitted when the LLM finishes generating tokens (before gadget execution completes).\n *\n * This event fires when the LLM stream ends, allowing consumers to track\n * \"LLM thinking time\" separately from gadget execution time.\n *\n * Event order: llm_call_start → llm_response_end → llm_call_complete\n */\nexport interface LLMResponseEndEvent extends BaseExecutionEvent {\n  type: \"llm_response_end\";\n  /** Iteration number within agent loop */\n  iteration: number;\n  /** Model identifier */\n  model: string;\n  /** Finish reason from LLM */\n  finishReason: string | null;\n  /** Token usage (may be partial, final usage in llm_call_complete) */\n  usage?: TokenUsage;\n}\n\n/**\n * Emitted when an LLM call completes successfully (after all gadgets finish).\n */\nexport interface LLMCallCompleteEvent extends BaseExecutionEvent {\n  type: \"llm_call_complete\";\n  /** Complete response text */\n  response: string;\n  /** Token usage */\n  usage?: TokenUsage;\n  /** Finish reason from LLM */\n  finishReason?: string | null;\n  /** Cost in USD */\n  cost?: number;\n  /** Accumulated thinking/reasoning content from reasoning models */\n  thinkingContent?: string;\n}\n\n/**\n * Emitted when an LLM call fails.\n */\nexport interface LLMCallErrorEvent extends BaseExecutionEvent {\n  type: \"llm_call_error\";\n  /** The error that occurred */\n  error: Error;\n  /** Whether the error was recovered by a controller */\n  recovered: boolean;\n}\n\n// =============================================================================\n// Gadget Events\n// =============================================================================\n\n/**\n * Emitted when a gadget call is parsed from LLM output (before execution).\n */\nexport interface GadgetCallEvent extends BaseExecutionEvent {\n  type: \"gadget_call\";\n  /** Invocation ID */\n  invocationId: string;\n  /** Gadget name */\n  name: string;\n  /** Parameters */\n  parameters: Record<string, unknown>;\n  /** Dependencies (other invocation IDs) */\n  dependencies: string[];\n}\n\n/**\n * Emitted when gadget execution starts.\n */\nexport interface GadgetStartEvent extends BaseExecutionEvent {\n  type: \"gadget_start\";\n  /** Invocation ID */\n  invocationId: string;\n  /** Gadget name */\n  name: string;\n}\n\n/**\n * Emitted when gadget execution completes successfully.\n */\nexport interface GadgetCompleteEvent extends BaseExecutionEvent {\n  type: \"gadget_complete\";\n  /** Invocation ID */\n  invocationId: string;\n  /** Gadget name */\n  name: string;\n  /** Result string */\n  result: string;\n  /** Execution time in ms */\n  executionTimeMs: number;\n  /** Cost in USD */\n  cost?: number;\n  /** Media outputs */\n  media?: GadgetMediaOutput[];\n  /** Stored media with file paths */\n  storedMedia?: StoredMedia[];\n}\n\n/**\n * Emitted when gadget execution fails.\n */\nexport interface GadgetErrorEvent extends BaseExecutionEvent {\n  type: \"gadget_error\";\n  /** Invocation ID */\n  invocationId: string;\n  /** Gadget name */\n  name: string;\n  /** Error message */\n  error: string;\n  /** Execution time in ms */\n  executionTimeMs: number;\n}\n\n/**\n * Emitted when a gadget is skipped.\n */\nexport interface GadgetSkippedEvent extends BaseExecutionEvent {\n  type: \"gadget_skipped\";\n  /** Invocation ID */\n  invocationId: string;\n  /** Gadget name */\n  name: string;\n  /** Reason for skipping */\n  reason: \"dependency_failed\" | \"controller_skip\" | \"limit_exceeded\";\n  /** Error message (combines reason and failedDependencyError for consistency with GadgetErrorEvent) */\n  error: string;\n  /** Failed dependency invocation ID (if dependency_failed) */\n  failedDependency?: string;\n  /** Error message from failed dependency */\n  failedDependencyError?: string;\n}\n\n// =============================================================================\n// Text Events\n// =============================================================================\n\n/**\n * Emitted for text output from LLM (pure notification, not a tree node).\n */\nexport interface TextEvent extends BaseExecutionEvent {\n  type: \"text\";\n  /** Text content */\n  content: string;\n}\n\n// =============================================================================\n// Thinking / Reasoning Events\n// =============================================================================\n\n/**\n * Emitted when a reasoning model produces thinking content during streaming.\n * This gives consumers a dedicated event type to listen for reasoning output.\n */\nexport interface ThinkingEvent extends BaseExecutionEvent {\n  type: \"thinking\";\n  /** Thinking text content */\n  content: string;\n  /** Whether this is actual thinking or redacted content */\n  thinkingType: \"thinking\" | \"redacted\";\n}\n\n// =============================================================================\n// Other Events\n// =============================================================================\n\n/**\n * Emitted when context compaction occurs.\n */\nexport interface CompactionEvent extends BaseExecutionEvent {\n  type: \"compaction\";\n  /** Tokens before compaction */\n  tokensBefore: number;\n  /** Tokens after compaction */\n  tokensAfter: number;\n  /** Compaction strategy used */\n  strategy: string;\n  /** Messages removed */\n  messagesRemoved: number;\n}\n\n/**\n * Emitted when human input is required.\n */\nexport interface HumanInputRequiredEvent extends BaseExecutionEvent {\n  type: \"human_input_required\";\n  /** Question for the user */\n  question: string;\n  /** Gadget name requesting input */\n  gadgetName: string;\n  /** Invocation ID */\n  invocationId: string;\n}\n\n/**\n * Emitted when the execution stream completes.\n */\nexport interface StreamCompleteEvent extends BaseExecutionEvent {\n  type: \"stream_complete\";\n  /** Whether any gadgets were executed */\n  didExecuteGadgets: boolean;\n  /** Whether the agent loop should break */\n  shouldBreakLoop: boolean;\n  /** Total cost for this iteration */\n  iterationCost?: number;\n}\n\n// =============================================================================\n// Union Types\n// =============================================================================\n\n/**\n * All LLM-related events.\n */\nexport type LLMEvent =\n  | LLMCallStartEvent\n  | LLMCallStreamEvent\n  | LLMResponseEndEvent\n  | LLMCallCompleteEvent\n  | LLMCallErrorEvent;\n\n/**\n * All gadget-related events.\n */\nexport type GadgetEvent =\n  | GadgetCallEvent\n  | GadgetStartEvent\n  | GadgetCompleteEvent\n  | GadgetErrorEvent\n  | GadgetSkippedEvent;\n\n/**\n * Union of all execution events.\n */\nexport type ExecutionEvent =\n  | LLMCallStartEvent\n  | LLMCallStreamEvent\n  | LLMResponseEndEvent\n  | LLMCallCompleteEvent\n  | LLMCallErrorEvent\n  | GadgetCallEvent\n  | GadgetStartEvent\n  | GadgetCompleteEvent\n  | GadgetErrorEvent\n  | GadgetSkippedEvent\n  | TextEvent\n  | ThinkingEvent\n  | CompactionEvent\n  | HumanInputRequiredEvent\n  | StreamCompleteEvent;\n\n/**\n * Event type discriminator.\n */\nexport type ExecutionEventType = ExecutionEvent[\"type\"] | \"*\";\n\n// =============================================================================\n// Type Guards\n// =============================================================================\n\n/**\n * Check if an event is an LLM event.\n */\nexport function isLLMEvent(event: ExecutionEvent): event is LLMEvent {\n  return event.type.startsWith(\"llm_call_\");\n}\n\n/**\n * Check if an event is a gadget event.\n */\nexport function isGadgetEvent(event: ExecutionEvent): event is GadgetEvent {\n  return event.type.startsWith(\"gadget_\");\n}\n\n/**\n * Check if an event is from a subagent (nested execution).\n */\nexport function isSubagentEvent(event: ExecutionEvent): boolean {\n  return event.depth > 0;\n}\n\n/**\n * Check if an event is from the root agent.\n */\nexport function isRootEvent(event: ExecutionEvent): boolean {\n  return event.depth === 0;\n}\n\n// =============================================================================\n// Event Filtering Utilities\n// =============================================================================\n\n/**\n * Filter events by depth.\n */\nexport function filterByDepth(events: ExecutionEvent[], depth: number): ExecutionEvent[] {\n  return events.filter((e) => e.depth === depth);\n}\n\n/**\n * Filter events by parent node.\n */\nexport function filterByParent(events: ExecutionEvent[], parentId: string): ExecutionEvent[] {\n  return events.filter((e) => e.parentId === parentId);\n}\n\n/**\n * Filter events to only root-level events.\n */\nexport function filterRootEvents(events: ExecutionEvent[]): ExecutionEvent[] {\n  return filterByDepth(events, 0);\n}\n\n/**\n * Group events by their parent node.\n */\nexport function groupByParent(events: ExecutionEvent[]): Map<string | null, ExecutionEvent[]> {\n  const groups = new Map<string | null, ExecutionEvent[]>();\n\n  for (const event of events) {\n    const parentId = event.parentId;\n    if (!groups.has(parentId)) {\n      groups.set(parentId, []);\n    }\n    groups.get(parentId)?.push(event);\n  }\n\n  return groups;\n}\n","/**\n * Model Context Protocol (MCP) integration for llmist.\n *\n * Plan 1 — foundation: stdio consumer with allowlist security baseline.\n * Plan 2 — adds Streamable HTTP, multi-server, prompts, error isolation.\n * Plan 3 — adds the `llmist mcp serve` exposer.\n *\n * @module mcp\n */\n\nexport {\n  assertCommandAllowed,\n  DEFAULT_MCP_COMMAND_ALLOWLIST,\n} from \"./allowlist.js\";\nexport { McpClient, type McpClientOptions } from \"./client.js\";\nexport {\n  JsonSchemaConversionError,\n  McpConnectError,\n  McpError,\n  McpToolCallError,\n  McpUntrustedCommandError,\n} from \"./errors.js\";\nexport {\n  gadgetResultToMcpContent,\n  gadgetToMcpTool,\n  runGadgetForMcp,\n} from \"./gadget-exporter.js\";\nexport { type JSONSchemaLike, jsonSchemaToZod } from \"./json-schema-to-zod.js\";\nexport { McpLifecycle } from \"./lifecycle.js\";\nexport {\n  type CreateMcpServerOptions,\n  createMcpServer,\n  type McpServerHandle,\n} from \"./server.js\";\nexport { renderSkillForMcpPrompt, skillToMcpPrompt } from \"./skill-exporter.js\";\nexport { type McpToolAdapterOptions, mcpToolToGadget } from \"./tool-adapter.js\";\nexport type {\n  HttpMcpServerSpec,\n  McpContentBlock,\n  McpPromptArgument,\n  McpPromptDescriptor,\n  McpPromptMessage,\n  McpPromptResult,\n  McpServerCapabilities,\n  McpServerSpec,\n  McpToolDescriptor,\n  McpToolResult,\n  StdioMcpServerSpec,\n} from \"./types.js\";\n","/**\n * Convert native llmist gadgets into MCP tool descriptors and run them on\n * behalf of an MCP server. The inverse of `tool-adapter.ts` (which converts\n * MCP tools into native gadgets).\n *\n * @module mcp/gadget-exporter\n */\n\nimport type { AbstractGadget } from \"../gadgets/gadget.js\";\nimport { schemaToJSONSchema } from \"../gadgets/schema-to-json.js\";\nimport type {\n  GadgetExecuteResultWithMedia,\n  GadgetExecuteReturn,\n  GadgetMediaOutput,\n} from \"../gadgets/types.js\";\nimport { validateAndApplyDefaults } from \"../gadgets/validation.js\";\nimport type { McpContentBlock, McpToolDescriptor, McpToolResult } from \"./types.js\";\n\n/** Convert a native gadget into an MCP tool descriptor. */\nexport function gadgetToMcpTool(gadget: AbstractGadget): McpToolDescriptor {\n  const description =\n    gadget.description && gadget.description.length > 0\n      ? gadget.description\n      : `Native llmist gadget \"${gadget.name ?? \"unnamed\"}\"`;\n  let inputSchema: Record<string, unknown>;\n  if (gadget.parameterSchema) {\n    inputSchema = schemaToJSONSchema(gadget.parameterSchema);\n  } else {\n    inputSchema = { type: \"object\", properties: {} };\n  }\n  return {\n    name: gadget.name ?? \"unnamed-gadget\",\n    description,\n    inputSchema,\n  };\n}\n\n/**\n * Convert a gadget's execute() return value into MCP content blocks.\n *\n * Shapes handled:\n *  - string → single `text` block\n *  - { result, media[] } → `text` block + per-media block\n *  - other (object) → JSON-stringified `text` block\n */\nexport function gadgetResultToMcpContent(ret: GadgetExecuteReturn): McpContentBlock[] {\n  if (typeof ret === \"string\") {\n    return [{ type: \"text\", text: ret }];\n  }\n  if (ret && typeof ret === \"object\" && \"result\" in ret) {\n    const r = ret as GadgetExecuteResultWithMedia;\n    const blocks: McpContentBlock[] = [];\n    if (typeof r.result === \"string\") {\n      blocks.push({ type: \"text\", text: r.result });\n    } else {\n      blocks.push({ type: \"text\", text: JSON.stringify(r.result) });\n    }\n    if (r.media) {\n      for (const m of r.media as GadgetMediaOutput[]) {\n        if (m.kind === \"image\" || m.kind === \"audio\") {\n          blocks.push({\n            type: m.kind,\n            data: m.data,\n            mimeType: m.mimeType,\n          });\n        }\n      }\n    }\n    return blocks;\n  }\n  // Plain object or primitive — stringify.\n  return [{ type: \"text\", text: JSON.stringify(ret) }];\n}\n\n/**\n * Validate params and run the gadget, converting both the success and error\n * paths into MCP tool result shapes.\n *\n * Used by the McpServer's `tools/call` handler.\n */\nexport async function runGadgetForMcp(\n  gadget: AbstractGadget,\n  rawParams: unknown,\n): Promise<McpToolResult> {\n  // Validate input against the gadget's Zod schema (if any).\n  if (gadget.parameterSchema) {\n    const validation = validateAndApplyDefaults(\n      gadget.parameterSchema,\n      (rawParams as Record<string, unknown>) ?? {},\n    );\n    if (!validation.success) {\n      return {\n        isError: true,\n        content: [\n          {\n            type: \"text\",\n            text: `Invalid arguments for gadget \"${gadget.name}\": ${validation.error}`,\n          },\n        ],\n      };\n    }\n    rawParams = validation.data;\n  }\n\n  try {\n    const result = await gadget.execute(rawParams as Record<string, unknown>);\n    return {\n      content: gadgetResultToMcpContent(result),\n    };\n  } catch (err) {\n    return {\n      isError: true,\n      content: [\n        {\n          type: \"text\",\n          text: `Gadget \"${gadget.name}\" failed: ${(err as Error).message}`,\n        },\n      ],\n    };\n  }\n}\n","/**\n * Validation utilities for gadget parameters.\n *\n * Provides standalone validation with Zod schema support, including\n * default application and formatted error output.\n *\n * @module gadgets/validation\n */\n\nimport type { ZodTypeAny } from \"zod\";\nimport type { AbstractGadget } from \"./gadget.js\";\n\n/**\n * Individual validation issue with path and message.\n */\nexport interface ValidationIssue {\n  /** Dot-separated path to the invalid field (e.g., \"user.email\") */\n  path: string;\n  /** Human-readable error message */\n  message: string;\n}\n\n/**\n * Result of parameter validation.\n * Discriminated union based on `success` field.\n */\nexport type ValidationResult<T = Record<string, unknown>> =\n  | {\n      success: true;\n      /** Validated and transformed data with defaults applied */\n      data: T;\n    }\n  | {\n      success: false;\n      /** Formatted error message */\n      error: string;\n      /** Individual validation issues */\n      issues: ValidationIssue[];\n    };\n\n/**\n * Validate parameters against a Zod schema and apply defaults/transformations.\n *\n * This replicates the validation behavior from GadgetExecutor, making it\n * available for direct use in tests and other contexts.\n *\n * @param schema - Zod schema to validate against\n * @param params - Raw parameters to validate\n * @returns ValidationResult with either validated data or error details\n *\n * @example\n * ```typescript\n * import { validateAndApplyDefaults } from 'llmist';\n * import { z } from 'zod';\n *\n * const schema = z.object({\n *   delay: z.number().default(100),\n *   retries: z.number().int().min(0).default(3),\n * });\n *\n * const result = validateAndApplyDefaults(schema, { delay: 50 });\n * if (result.success) {\n *   console.log(result.data); // { delay: 50, retries: 3 }\n * }\n * ```\n */\nexport function validateAndApplyDefaults<T = Record<string, unknown>>(\n  schema: ZodTypeAny,\n  params: Record<string, unknown>,\n): ValidationResult<T> {\n  const result = schema.safeParse(params);\n\n  if (result.success) {\n    return {\n      success: true,\n      data: result.data as T,\n    };\n  }\n\n  const issues: ValidationIssue[] = result.error.issues.map((issue) => ({\n    path: issue.path.join(\".\") || \"root\",\n    message: issue.message,\n  }));\n\n  const formattedError = `Invalid parameters: ${issues.map((i) => `${i.path}: ${i.message}`).join(\"; \")}`;\n\n  return {\n    success: false,\n    error: formattedError,\n    issues,\n  };\n}\n\n/**\n * Validate gadget parameters using the gadget's schema.\n *\n * Convenience wrapper that extracts the schema from a gadget instance.\n * If the gadget has no schema, validation always succeeds with the\n * original parameters.\n *\n * @param gadget - Gadget instance with optional parameterSchema\n * @param params - Raw parameters to validate\n * @returns ValidationResult with either validated data or error details\n *\n * @example\n * ```typescript\n * import { validateGadgetParams, createGadget } from 'llmist';\n * import { z } from 'zod';\n *\n * const calculator = createGadget({\n *   description: 'Add numbers',\n *   schema: z.object({\n *     a: z.number(),\n *     b: z.number().default(0),\n *   }),\n *   execute: ({ a, b }) => String(a + b),\n * });\n *\n * const result = validateGadgetParams(calculator, { a: 5 });\n * if (result.success) {\n *   console.log(result.data); // { a: 5, b: 0 }\n * }\n * ```\n */\nexport function validateGadgetParams(\n  gadget: AbstractGadget,\n  params: Record<string, unknown>,\n): ValidationResult {\n  if (!gadget.parameterSchema) {\n    return {\n      success: true,\n      data: params,\n    };\n  }\n\n  return validateAndApplyDefaults(gadget.parameterSchema, params);\n}\n","/**\n * Convert native llmist Skills into MCP prompt descriptors and render them\n * on behalf of an MCP server.\n *\n * Plan 3 maps:\n *  - Skill metadata.name → prompt name\n *  - Skill metadata.description → prompt description\n *  - argumentHint (when present) → a single optional `arguments` parameter\n *    (the existing skill-substitution machinery handles `$ARGUMENTS`, `$0`,\n *    `$1`, etc., from a single string)\n *  - Skill body, after argument substitution, becomes a single user-role\n *    text message in the prompt response\n *\n * @module mcp/skill-exporter\n */\n\nimport type { Skill } from \"../skills/skill.js\";\nimport type { McpPromptArgument, McpPromptDescriptor, McpPromptResult } from \"./types.js\";\n\nexport function skillToMcpPrompt(skill: Skill): McpPromptDescriptor {\n  const description =\n    skill.description && skill.description.length > 0\n      ? skill.description\n      : `Native llmist skill \"${skill.name}\"`;\n\n  const args: McpPromptArgument[] = [];\n  if (skill.metadata.argumentHint) {\n    args.push({\n      name: \"arguments\",\n      description: skill.metadata.argumentHint,\n      required: false,\n    });\n  }\n\n  return {\n    name: skill.name,\n    description,\n    ...(args.length > 0 ? { arguments: args } : {}),\n  };\n}\n\n/**\n * Render a skill's body as a single MCP prompt message after argument\n * substitution.\n *\n * `args.arguments` is a string interpreted by the existing skill activation\n * pipeline ($ARGUMENTS, $0, $1, ...). We don't try to map MCP's per-argument\n * named parameters into the existing positional substitution model — the\n * skill author already chose the substitution shape.\n */\nexport async function renderSkillForMcpPrompt(\n  skill: Skill,\n  args: Record<string, unknown>,\n): Promise<McpPromptResult> {\n  const argString =\n    typeof args.arguments === \"string\"\n      ? args.arguments\n      : Object.values(args)\n          .filter((v) => typeof v === \"string\")\n          .join(\" \");\n\n  const activation = await skill.activate({\n    arguments: argString || undefined,\n  });\n\n  return {\n    description: skill.description,\n    messages: [\n      {\n        role: \"user\",\n        content: { type: \"text\", text: activation.resolvedInstructions },\n      },\n    ],\n  };\n}\n","/**\n * Wrap the MCP SDK's Server class with llmist semantics: register native\n * gadgets as MCP tools and (optionally) llmist skills as MCP prompts.\n *\n * Lazy-imports the SDK so callers that don't expose anything pay no cost.\n *\n * @module mcp/server\n */\n\nimport type { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport type { GadgetRegistry } from \"../gadgets/registry.js\";\nimport type { SkillRegistry } from \"../skills/registry.js\";\nimport { gadgetToMcpTool, runGadgetForMcp } from \"./gadget-exporter.js\";\nimport { renderSkillForMcpPrompt, skillToMcpPrompt } from \"./skill-exporter.js\";\n\nexport interface CreateMcpServerOptions {\n  gadgets: GadgetRegistry;\n  skills?: SkillRegistry;\n  /** Override the protocol version advertised. Defaults to 2025-06-18. */\n  protocolVersion?: string;\n  /** Server identity sent on initialize. */\n  serverInfo?: { name: string; version: string };\n}\n\nexport interface McpServerHandle {\n  /** Connect the server to a Transport (stdio, in-memory test transport, etc.). */\n  connect(transport: Transport): Promise<void>;\n  /** Close the underlying server cleanly. Idempotent. */\n  stop(): Promise<void>;\n  /** True between connect() and stop(). */\n  readonly running: boolean;\n}\n\nconst DEFAULT_SERVER_INFO = { name: \"llmist\", version: \"0.0.0\" };\n\nexport function createMcpServer(opts: CreateMcpServerOptions): McpServerHandle {\n  const { gadgets, skills } = opts;\n\n  const hasTools = gadgets.getAll().length > 0;\n  const hasPrompts = !!skills && skills.size > 0;\n\n  const capabilities: Record<string, unknown> = {};\n  if (hasTools) capabilities.tools = {};\n  if (hasPrompts) capabilities.prompts = {};\n\n  let sdkServer: {\n    connect(t: Transport): Promise<void>;\n    close(): Promise<void>;\n    setRequestHandler<T>(schema: T, handler: unknown): void;\n  } | null = null;\n  let running = false;\n\n  async function ensureServer(): Promise<typeof sdkServer & object> {\n    if (sdkServer) return sdkServer;\n    const [serverMod, typesMod] = await Promise.all([\n      import(\"@modelcontextprotocol/sdk/server/index.js\"),\n      import(\"@modelcontextprotocol/sdk/types.js\"),\n    ]);\n    const ServerClass = serverMod.Server as unknown as new (\n      info: { name: string; version: string },\n      options: { capabilities: Record<string, unknown> },\n    ) => {\n      connect(t: Transport): Promise<void>;\n      close(): Promise<void>;\n      setRequestHandler<T>(schema: T, handler: unknown): void;\n    };\n    const server = new ServerClass(opts.serverInfo ?? DEFAULT_SERVER_INFO, {\n      capabilities,\n    });\n\n    if (hasTools) {\n      server.setRequestHandler(typesMod.ListToolsRequestSchema, async () => ({\n        tools: gadgets.getAll().map(gadgetToMcpTool),\n      }));\n      server.setRequestHandler(\n        typesMod.CallToolRequestSchema,\n        async (req: { params: { name: string; arguments?: unknown } }) => {\n          const gadget = gadgets.get(req.params.name);\n          if (!gadget) {\n            return {\n              isError: true,\n              content: [\n                {\n                  type: \"text\",\n                  text: `Unknown tool \"${req.params.name}\". Call tools/list first.`,\n                },\n              ],\n            };\n          }\n          return runGadgetForMcp(gadget, req.params.arguments ?? {});\n        },\n      );\n    }\n\n    if (hasPrompts && skills) {\n      server.setRequestHandler(typesMod.ListPromptsRequestSchema, async () => ({\n        prompts: Array.from(skills.getAll()).map(skillToMcpPrompt),\n      }));\n      server.setRequestHandler(\n        typesMod.GetPromptRequestSchema,\n        async (req: { params: { name: string; arguments?: Record<string, unknown> } }) => {\n          const skill = skills.get(req.params.name);\n          if (!skill) {\n            throw new Error(`Unknown prompt \"${req.params.name}\"`);\n          }\n          const result = await renderSkillForMcpPrompt(skill, req.params.arguments ?? {});\n          return result;\n        },\n      );\n    }\n\n    sdkServer = server;\n    return server;\n  }\n\n  return {\n    get running() {\n      return running;\n    },\n    async connect(transport: Transport) {\n      const server = await ensureServer();\n      await server.connect(transport);\n      running = true;\n    },\n    async stop() {\n      if (!sdkServer) return;\n      try {\n        await sdkServer.close();\n      } catch {\n        // teardown must not throw\n      }\n      sdkServer = null;\n      running = false;\n    },\n  };\n}\n","/**\n * Deep Research module (spec 002-deep-research).\n */\n\nexport { ResearchResultCollector } from \"./collector.js\";\nexport * from \"./constants.js\";\nexport { estimateResearchCost } from \"./cost.js\";\nexport {\n  ResearchDeprecatedModelError,\n  ResearchJobNotResumableError,\n  ResearchNotPollableError,\n  ResearchNotSupportedError,\n  ResearchStreamConsumedError,\n  ResearchTimeoutError,\n  ResearchValidationError,\n} from \"./errors.js\";\nexport { ResearchJobImpl } from \"./job.js\";\nexport type {\n  ResearchCapabilities,\n  ResearchModelMetadata,\n  ResearchModelSpec,\n  ResearchPricing,\n} from \"./model-spec.js\";\nexport { ResearchNamespace } from \"./namespace.js\";\nexport type {\n  ResearchCitation,\n  ResearchDoneInfo,\n  ResearchErrorInfo,\n  ResearchEvent,\n  ResearchJob,\n  ResearchJobRef,\n  ResearchOptions,\n  ResearchResult,\n  ResearchStatus,\n  ResearchStatusSnapshot,\n  ResearchToolConfig,\n  ResearchToolType,\n  ResearchUsage,\n} from \"./types.js\";\nexport { RESEARCH_DATA_SOURCE_TOOL_TYPES } from \"./types.js\";\n","/**\n * Config resolution utility for subagent gadgets.\n *\n * Simplifies the common pattern of resolving configuration from multiple sources:\n * 1. Runtime params (explicit gadget call parameters)\n * 2. Subagent config (from CLI [subagents.Name] sections)\n * 3. Parent agent config (model inheritance)\n * 4. Package defaults\n *\n * @module utils/config-resolver\n */\n\nimport type { ExecutionContext } from \"../gadgets/types.js\";\n\n/**\n * Options for resolving a single config value.\n */\nexport interface ResolveValueOptions<T> {\n  /** Runtime parameter value (highest priority) */\n  runtime?: T;\n  /** Subagent config key to check */\n  subagentKey?: string;\n  /** Parent config key to check (for inheritance) - \"model\" or \"temperature\" */\n  parentKey?: \"model\" | \"temperature\";\n  /** Default value (lowest priority) */\n  defaultValue: T;\n  /** Whether \"inherit\" string means use parent value */\n  handleInherit?: boolean;\n}\n\n/**\n * Resolve a single configuration value through the priority chain.\n *\n * Priority (highest to lowest):\n * 1. Runtime parameter (if provided and not undefined)\n * 2. Subagent config (from ctx.subagentConfig[gadgetName][key])\n * 3. Parent config (from ctx.agentConfig[key], if parentKey specified)\n * 4. Default value\n *\n * Special handling for \"inherit\" string:\n * - If handleInherit is true and value is \"inherit\", falls through to parent/default\n *\n * @param ctx - ExecutionContext from gadget execution\n * @param gadgetName - Name of the subagent gadget (e.g., \"BrowseWeb\")\n * @param options - Resolution options\n * @returns Resolved value\n *\n * @example\n * ```typescript\n * const model = resolveValue(ctx, \"BrowseWeb\", {\n *   runtime: params.model,\n *   subagentKey: \"model\",\n *   parentKey: \"model\",\n *   defaultValue: \"sonnet\",\n *   handleInherit: true,\n * });\n * ```\n */\nexport function resolveValue<T>(\n  ctx: ExecutionContext,\n  gadgetName: string,\n  options: ResolveValueOptions<T>,\n): T {\n  const { runtime, subagentKey, parentKey, defaultValue, handleInherit } = options;\n\n  // Priority 1: Runtime parameter\n  if (runtime !== undefined) {\n    // Handle \"inherit\" string if enabled\n    if (handleInherit && runtime === \"inherit\") {\n      // Fall through to lower priorities\n    } else {\n      return runtime;\n    }\n  }\n\n  // Priority 2: Subagent config\n  if (subagentKey && ctx.subagentConfig) {\n    const subagentCfg = ctx.subagentConfig[gadgetName];\n    if (subagentCfg && subagentKey in subagentCfg) {\n      const value = subagentCfg[subagentKey] as T;\n      // Handle \"inherit\" string if enabled\n      if (handleInherit && value === \"inherit\") {\n        // Fall through to parent/default\n      } else if (value !== undefined) {\n        return value;\n      }\n    }\n  }\n\n  // Priority 3: Parent config (inheritance)\n  if (parentKey && ctx.agentConfig && parentKey in ctx.agentConfig) {\n    const parentValue = ctx.agentConfig[parentKey] as T;\n    if (parentValue !== undefined) {\n      return parentValue;\n    }\n  }\n\n  // Priority 4: Default value\n  return defaultValue;\n}\n\n/**\n * Bulk configuration resolution for subagent gadgets.\n *\n * Takes a map of config keys to their resolution options and returns\n * a fully resolved configuration object.\n *\n * @param ctx - ExecutionContext from gadget execution\n * @param gadgetName - Name of the subagent gadget (e.g., \"BrowseWeb\")\n * @param config - Map of config keys to resolution options\n * @returns Fully resolved configuration object\n *\n * @example\n * ```typescript\n * // Before: 27 lines of manual fallback logic\n * const subagentConfig = ctx.subagentConfig?.Dhalsim ?? {};\n * const parentModel = ctx.agentConfig?.model;\n * const model = params.model ?? subagentConfig.model ?? parentModel ?? \"sonnet\";\n * const maxIterations = params.maxIterations ?? subagentConfig.maxIterations ?? 15;\n * const headless = params.headless ?? subagentConfig.headless ?? true;\n *\n * // After: One function call\n * const { model, maxIterations, headless } = resolveConfig(ctx, \"BrowseWeb\", {\n *   model: { runtime: params.model, subagentKey: \"model\", parentKey: \"model\", defaultValue: \"sonnet\", handleInherit: true },\n *   maxIterations: { runtime: params.maxIterations, subagentKey: \"maxIterations\", defaultValue: 15 },\n *   headless: { runtime: params.headless, subagentKey: \"headless\", defaultValue: true },\n * });\n * ```\n */\nexport function resolveConfig<T extends Record<string, unknown>>(\n  ctx: ExecutionContext,\n  gadgetName: string,\n  config: { [K in keyof T]: ResolveValueOptions<T[K]> },\n): T {\n  const result: Record<string, unknown> = {};\n\n  for (const [key, options] of Object.entries(config)) {\n    result[key] = resolveValue(ctx, gadgetName, options as ResolveValueOptions<unknown>);\n  }\n\n  return result as T;\n}\n\n/**\n * Convenience function for resolving subagent model with \"inherit\" support.\n *\n * This is the most common resolution pattern for subagent gadgets:\n * - Use runtime model if provided\n * - Check subagent config for model override\n * - Inherit parent model if configured\n * - Fall back to default\n *\n * @param ctx - ExecutionContext from gadget execution\n * @param gadgetName - Name of the subagent gadget\n * @param runtimeModel - Model from gadget parameters\n * @param defaultModel - Default model if nothing else specified\n * @returns Resolved model string\n *\n * @example\n * ```typescript\n * const model = resolveSubagentModel(ctx, \"BrowseWeb\", params.model, \"sonnet\");\n * ```\n */\nexport function resolveSubagentModel(\n  ctx: ExecutionContext,\n  gadgetName: string,\n  runtimeModel: string | undefined,\n  defaultModel: string,\n): string {\n  return resolveValue(ctx, gadgetName, {\n    runtime: runtimeModel,\n    subagentKey: \"model\",\n    parentKey: \"model\",\n    defaultValue: defaultModel,\n    handleInherit: true,\n  });\n}\n\n/**\n * Convenience function for resolving subagent timeout.\n *\n * Resolves timeout from the configuration priority chain:\n * - Use runtime timeout if provided\n * - Check subagent config for timeout override\n * - Fall back to default\n *\n * @param ctx - ExecutionContext from gadget execution\n * @param gadgetName - Name of the subagent gadget\n * @param runtimeTimeout - Timeout from gadget parameters\n * @param defaultTimeout - Default timeout if nothing else specified\n * @returns Resolved timeout in milliseconds\n *\n * @example\n * ```typescript\n * const timeoutMs = resolveSubagentTimeout(ctx, \"BrowseWeb\", params.timeoutMs, 300000);\n * ```\n */\nexport function resolveSubagentTimeout(\n  ctx: ExecutionContext,\n  gadgetName: string,\n  runtimeTimeout: number | undefined,\n  defaultTimeout: number,\n): number {\n  return resolveValue(ctx, gadgetName, {\n    runtime: runtimeTimeout,\n    subagentKey: \"timeoutMs\",\n    defaultValue: defaultTimeout,\n  });\n}\n","/**\n * Subagent creation helper for gadget authors.\n *\n * Simplifies the common pattern of creating subagents from within gadgets.\n * Handles:\n * - Getting host exports (AgentBuilder, LLMist) from context\n * - Model resolution with \"inherit\" support\n * - Parent context sharing for cost tracking\n * - Common configuration options\n *\n * @module agent/subagent\n *\n * @example\n * ```typescript\n * import { createSubagent, Gadget, z } from \"llmist\";\n * import type { ExecutionContext } from \"llmist\";\n *\n * class BrowseWeb extends Gadget({\n *   name: \"BrowseWeb\",\n *   schema: z.object({\n *     task: z.string(),\n *     url: z.string().url(),\n *     model: z.string().optional(),\n *   }),\n * }) {\n *   async execute(params: this[\"params\"], ctx?: ExecutionContext) {\n *     const agent = createSubagent(ctx!, {\n *       name: \"BrowseWeb\",\n *       gadgets: [Navigate, Click, Screenshot],\n *       systemPrompt: BROWSER_SYSTEM_PROMPT,\n *       model: params.model,  // Optional override\n *       maxIterations: 15,\n *     }).ask(params.task);\n *\n *     for await (const event of agent.run()) {\n *       // Process events...\n *     }\n *\n *     return result;\n *   }\n * }\n * ```\n */\n\nimport type { AbstractGadget } from \"../gadgets/gadget.js\";\nimport type { ExecutionContext, HostExports } from \"../gadgets/types.js\";\nimport { resolveSubagentModel, resolveValue } from \"../utils/config-resolver.js\";\nimport type { AgentBuilder } from \"./builder.js\";\nimport type { AgentHooks } from \"./hooks.js\";\n\n/**\n * Options for creating a subagent.\n */\nexport interface SubagentOptions {\n  /**\n   * Name of the subagent (used for config resolution).\n   * Should match the gadget name in CLI config, e.g., \"BrowseWeb\".\n   */\n  name: string;\n\n  /**\n   * Gadgets to register with the subagent.\n   */\n  gadgets: AbstractGadget[];\n\n  /**\n   * System prompt for the subagent.\n   */\n  systemPrompt?: string;\n\n  /**\n   * Model to use. If not provided, inherits from parent or uses default.\n   * Can be a runtime parameter from gadget params.\n   */\n  model?: string;\n\n  /**\n   * Default model if no other source provides one.\n   * @default \"sonnet\"\n   */\n  defaultModel?: string;\n\n  /**\n   * Maximum iterations for the agent loop.\n   */\n  maxIterations?: number;\n\n  /**\n   * Default max iterations if not specified.\n   * @default 15\n   */\n  defaultMaxIterations?: number;\n\n  /**\n   * Agent hooks for observers, interceptors, controllers.\n   */\n  hooks?: AgentHooks;\n\n  /**\n   * Temperature for LLM calls.\n   */\n  temperature?: number;\n}\n\n/**\n * Get host exports from execution context.\n *\n * This helper ensures gadgets use the same llmist version as the host CLI,\n * avoiding the \"dual-package problem\" where different versions have\n * incompatible classes.\n *\n * @param ctx - Execution context from gadget execute()\n * @returns Host exports (AgentBuilder, LLMist, etc.)\n * @throws Error if host exports not available\n */\nfunction getHostExports(ctx: ExecutionContext): HostExports {\n  if (!ctx?.hostExports) {\n    throw new Error(\n      \"hostExports not available. Subagent gadgets must be run via llmist agent. \" +\n        \"Ensure you are using llmist >= 6.2.0 and running through the CLI or AgentBuilder.\",\n    );\n  }\n  return ctx.hostExports;\n}\n\n/**\n * Create a subagent from within a gadget.\n *\n * This helper simplifies the common pattern of creating nested agents.\n * It automatically:\n * - Gets the correct AgentBuilder from host exports\n * - Resolves model with \"inherit\" support from CLI config\n * - Shares the parent's execution tree for cost tracking\n * - Forwards the abort signal for proper cancellation\n * - Inherits human input handler (for 2FA, CAPTCHAs, etc.)\n *\n * @param ctx - ExecutionContext passed to gadget's execute()\n * @param options - Subagent configuration options\n * @returns Configured AgentBuilder ready for .ask()\n *\n * @example\n * ```typescript\n * // Basic usage\n * const agent = createSubagent(ctx, {\n *   name: \"BrowseWeb\",\n *   gadgets: [Navigate, Click],\n * }).ask(\"Go to google.com\");\n *\n * // With all options\n * const agent = createSubagent(ctx, {\n *   name: \"BrowseWeb\",\n *   gadgets: [Navigate, Click, Screenshot],\n *   systemPrompt: \"You are a browser automation agent...\",\n *   model: params.model,  // Runtime override\n *   defaultModel: \"sonnet\",\n *   maxIterations: 20,\n *   hooks: {\n *     observers: {\n *       onLLMCallReady: () => refreshPageState(),\n *     },\n *   },\n * }).ask(params.task);\n *\n * for await (const event of agent.run()) {\n *   // Events flow through shared tree automatically\n * }\n *\n * // Human input bubbles up automatically:\n * // If a gadget throws HumanInputRequiredException,\n * // the parent's onHumanInput handler will be called\n * ```\n */\nexport function createSubagent(ctx: ExecutionContext, options: SubagentOptions): AgentBuilder {\n  const {\n    name,\n    gadgets,\n    systemPrompt,\n    model: runtimeModel,\n    defaultModel = \"sonnet\",\n    maxIterations: runtimeMaxIterations,\n    defaultMaxIterations = 15,\n    hooks,\n    temperature,\n  } = options;\n\n  // Get host's AgentBuilder to ensure tree sharing works correctly\n  const { AgentBuilder, LLMist } = getHostExports(ctx);\n\n  // Create LLMist client for the subagent\n  const client = new LLMist();\n\n  // Resolve model with config hierarchy support\n  const model = resolveSubagentModel(ctx, name, runtimeModel, defaultModel);\n\n  // Resolve max iterations\n  const maxIterations = resolveValue(ctx, name, {\n    runtime: runtimeMaxIterations,\n    subagentKey: \"maxIterations\",\n    defaultValue: defaultMaxIterations,\n  });\n\n  // Build the subagent\n  let builder = new AgentBuilder(client)\n    .withModel(model)\n    .withGadgets(...gadgets)\n    .withMaxIterations(maxIterations)\n    .withParentContext(ctx); // Share tree, forward signal\n\n  // Inherit human input capability from parent context\n  // This allows subagents to bubble up input requests (e.g., 2FA codes)\n  if (ctx.requestHumanInput) {\n    builder = builder.onHumanInput(ctx.requestHumanInput);\n  }\n\n  // Apply optional configuration\n  if (systemPrompt) {\n    builder = builder.withSystem(systemPrompt);\n  }\n\n  if (hooks) {\n    builder = builder.withHooks(hooks);\n  }\n\n  if (temperature !== undefined) {\n    builder = builder.withTemperature(temperature);\n  }\n\n  // Forward logger from parent context if available\n  if (ctx.logger) {\n    builder = builder.withLogger(ctx.logger);\n  }\n\n  return builder;\n}\n\n/**\n * Check if an execution context has valid host exports.\n *\n * Useful for conditional logic when gadgets may run standalone or via agent.\n *\n * @param ctx - Execution context\n * @returns True if host exports are available\n */\nexport function hasHostExports(ctx?: ExecutionContext): boolean {\n  return ctx?.hostExports !== undefined;\n}\n","/**\n * Package manifest types for llmist gadget packages.\n *\n * These types define the structure of the `llmist` field in package.json\n * for gadget packages. This enables:\n * - Preset-based gadget loading\n * - Subagent discovery\n * - Factory function support\n * - Session management metadata\n *\n * @module package/manifest\n *\n * @example package.json\n * ```json\n * {\n *   \"name\": \"dhalsim\",\n *   \"llmist\": {\n *     \"gadgets\": \"./dist/index.js\",\n *     \"factory\": \"./dist/index.js\",\n *     \"presets\": {\n *       \"minimal\": [\"Navigate\", \"GetFullPageContent\"],\n *       \"readonly\": [\"Navigate\", \"GetFullPageContent\", \"Screenshot\"],\n *       \"all\": \"*\"\n *     },\n *     \"subagents\": {\n *       \"BrowseWeb\": {\n *         \"entryPoint\": \"./dist/index.js\",\n *         \"export\": \"Dhalsim\",\n *         \"description\": \"Autonomous web browser agent\",\n *         \"defaultModel\": \"sonnet\",\n *         \"maxIterations\": 15\n *       }\n *     },\n *     \"session\": {\n *       \"factory\": \"getSessionManager\",\n *       \"type\": \"browser\"\n *     }\n *   }\n * }\n * ```\n */\n\n/**\n * Subagent definition in the manifest.\n */\nexport interface SubagentManifestEntry {\n  /**\n   * Entry point file path relative to package root.\n   * @example \"./dist/index.js\"\n   */\n  entryPoint: string;\n\n  /**\n   * Export name from the entry point.\n   * @example \"Dhalsim\" or \"BrowseWeb\"\n   */\n  export: string;\n\n  /**\n   * Human-readable description of what this subagent does.\n   */\n  description?: string;\n\n  /**\n   * List of gadget names this subagent uses internally.\n   * Useful for documentation and dependency tracking.\n   */\n  uses?: string[];\n\n  /**\n   * Default model for this subagent.\n   * Can be \"inherit\" to use parent's model.\n   * @default \"inherit\"\n   */\n  defaultModel?: string;\n\n  /**\n   * Default maximum iterations.\n   * @default 15\n   */\n  maxIterations?: number;\n}\n\n/**\n * Session factory metadata in the manifest.\n */\nexport interface SessionManifestEntry {\n  /**\n   * Export name of the session factory function.\n   * @example \"getSessionManager\"\n   */\n  factory: string;\n\n  /**\n   * Type of session for categorization.\n   * @example \"browser\", \"api\", \"database\"\n   */\n  type: string;\n}\n\n/**\n * Preset definition - either an array of gadget names or \"*\" for all.\n */\nexport type PresetDefinition = string[] | \"*\";\n\n/**\n * llmist package manifest structure.\n *\n * This is the shape of the `llmist` field in package.json\n * for gadget packages.\n */\nexport interface LLMistPackageManifest {\n  /**\n   * Entry point for all gadgets.\n   * The module should export gadgets or a gadgets array.\n   * @example \"./dist/index.js\"\n   */\n  gadgets?: string;\n\n  /**\n   * Entry point for factory functions.\n   * Should export `createGadgetsByPreset(preset)` and/or `createGadgetsByName(names)`.\n   * @example \"./dist/index.js\"\n   */\n  factory?: string;\n\n  /**\n   * Subagent definitions.\n   * Key is the subagent name as it appears in CLI config.\n   */\n  subagents?: Record<string, SubagentManifestEntry>;\n\n  /**\n   * Preset definitions.\n   * Key is preset name, value is array of gadget names or \"*\" for all.\n   * @example { \"minimal\": [\"Navigate\", \"Screenshot\"], \"all\": \"*\" }\n   */\n  presets?: Record<string, PresetDefinition>;\n\n  /**\n   * Session factory metadata.\n   */\n  session?: SessionManifestEntry;\n\n  /**\n   * Skills directory relative to package root.\n   * Contains subdirectories with SKILL.md files.\n   * @example \"./skills\"\n   */\n  skills?: string;\n}\n\n/**\n * Factory function types that packages can export.\n */\nexport interface GadgetFactoryExports {\n  /**\n   * Create gadgets by preset name.\n   */\n  createGadgetsByPreset?: (preset: string, config?: unknown) => unknown;\n\n  /**\n   * Create gadgets by specific names.\n   */\n  createGadgetsByName?: (names: string[], config?: unknown) => unknown;\n\n  /**\n   * Create all gadgets with optional config.\n   */\n  createGadgets?: (config?: unknown) => unknown;\n}\n\n/**\n * Read and parse the llmist manifest from a package.json object.\n *\n * @param packageJson - Parsed package.json object\n * @returns Manifest or undefined if not present\n *\n * @example\n * ```typescript\n * import { readFileSync } from \"fs\";\n *\n * const pkg = JSON.parse(readFileSync(\"package.json\", \"utf-8\"));\n * const manifest = parseManifest(pkg);\n *\n * if (manifest?.presets?.minimal) {\n *   console.log(\"Minimal preset:\", manifest.presets.minimal);\n * }\n * ```\n */\nexport function parseManifest(\n  packageJson: Record<string, unknown>,\n): LLMistPackageManifest | undefined {\n  const llmist = packageJson.llmist;\n  if (!llmist || typeof llmist !== \"object\") {\n    return undefined;\n  }\n  return llmist as LLMistPackageManifest;\n}\n\n/**\n * Check if a manifest has a specific preset.\n */\nexport function hasPreset(\n  manifest: LLMistPackageManifest | undefined,\n  presetName: string,\n): boolean {\n  return manifest?.presets?.[presetName] !== undefined;\n}\n\n/**\n * Get gadget names for a preset.\n * Returns undefined if preset not found, empty array if preset is invalid.\n */\nexport function getPresetGadgets(\n  manifest: LLMistPackageManifest | undefined,\n  presetName: string,\n): string[] | \"*\" | undefined {\n  const preset = manifest?.presets?.[presetName];\n  if (preset === undefined) return undefined;\n  return preset;\n}\n\n/**\n * Check if a manifest has subagent definitions.\n */\nexport function hasSubagents(manifest: LLMistPackageManifest | undefined): boolean {\n  return manifest?.subagents !== undefined && Object.keys(manifest.subagents).length > 0;\n}\n\n/**\n * Get subagent entry by name.\n */\nexport function getSubagent(\n  manifest: LLMistPackageManifest | undefined,\n  name: string,\n): SubagentManifestEntry | undefined {\n  return manifest?.subagents?.[name];\n}\n\n/**\n * List all subagent names in a manifest.\n */\nexport function listSubagents(manifest: LLMistPackageManifest | undefined): string[] {\n  if (!manifest?.subagents) return [];\n  return Object.keys(manifest.subagents);\n}\n\n/**\n * List all preset names in a manifest.\n */\nexport function listPresets(manifest: LLMistPackageManifest | undefined): string[] {\n  if (!manifest?.presets) return [];\n  return Object.keys(manifest.presets);\n}\n","/**\n * Session management interface and base class for gadget packages.\n *\n * Provides a standardized way to manage sessions (browser instances, API clients, etc.)\n * across gadgets. This enables:\n * - Consistent session lifecycle management\n * - Per-agent session isolation\n * - Automatic cleanup\n *\n * @module session/manager\n *\n * @example\n * ```typescript\n * import { BaseSessionManager, ISessionManager } from \"llmist\";\n *\n * // Extend for browser sessions\n * class BrowserSessionManager extends BaseSessionManager<Page, BrowserConfig> {\n *   async createSession(config?: BrowserConfig): Promise<string> {\n *     const browser = await launchBrowser(config);\n *     const page = await browser.newPage();\n *     const id = this.generateId(\"p\");\n *     this.sessions.set(id, page);\n *     return id;\n *   }\n *\n *   async closeSession(id: string): Promise<void> {\n *     const page = this.sessions.get(id);\n *     if (page) {\n *       await page.close();\n *       this.sessions.delete(id);\n *     }\n *   }\n * }\n * ```\n */\n\n/**\n * Interface for session managers.\n *\n * Session managers track and manage external resources (browser pages, API connections, etc.)\n * that need to be shared across multiple gadgets and properly cleaned up.\n *\n * @typeParam TSession - Type of session object (e.g., Page, APIClient)\n * @typeParam TConfig - Configuration type for creating sessions\n */\nexport interface ISessionManager<TSession = unknown, TConfig = unknown> {\n  /**\n   * Create a new session.\n   *\n   * @param config - Optional configuration for the session\n   * @returns Promise resolving to the session ID\n   */\n  createSession(config?: TConfig): Promise<string>;\n\n  /**\n   * Get a session by ID.\n   *\n   * @param id - Session ID\n   * @returns Session object or undefined if not found\n   */\n  getSession(id: string): TSession | undefined;\n\n  /**\n   * Get a session by ID, throwing if not found.\n   *\n   * @param id - Session ID\n   * @returns Session object\n   * @throws Error if session not found\n   */\n  requireSession(id: string): TSession;\n\n  /**\n   * Close and remove a session.\n   *\n   * @param id - Session ID to close\n   */\n  closeSession(id: string): Promise<void>;\n\n  /**\n   * Close all sessions.\n   */\n  closeAll(): Promise<void>;\n\n  /**\n   * List all active session IDs.\n   *\n   * @returns Array of session IDs\n   */\n  listSessions(): string[];\n\n  /**\n   * Check if a session exists.\n   *\n   * @param id - Session ID\n   * @returns True if session exists\n   */\n  hasSession(id: string): boolean;\n}\n\n/**\n * Base implementation of session manager with common functionality.\n *\n * Extend this class to create domain-specific session managers.\n * You only need to implement `createSession` and `closeSession`.\n *\n * @typeParam TSession - Type of session object\n * @typeParam TConfig - Configuration type for creating sessions\n *\n * @example\n * ```typescript\n * class APIClientManager extends BaseSessionManager<APIClient, APIConfig> {\n *   async createSession(config?: APIConfig): Promise<string> {\n *     const client = new APIClient(config);\n *     const id = this.generateId(\"api\");\n *     this.sessions.set(id, client);\n *     return id;\n *   }\n *\n *   async closeSession(id: string): Promise<void> {\n *     const client = this.sessions.get(id);\n *     if (client) {\n *       await client.disconnect();\n *       this.sessions.delete(id);\n *     }\n *   }\n * }\n * ```\n */\nexport abstract class BaseSessionManager<TSession, TConfig = unknown>\n  implements ISessionManager<TSession, TConfig>\n{\n  /** Map of session ID to session object */\n  protected sessions = new Map<string, TSession>();\n\n  /** Counter for generating unique session IDs */\n  protected idCounter = 0;\n\n  /**\n   * Generate a unique session ID with the given prefix.\n   *\n   * @param prefix - Prefix for the ID (e.g., \"p\" for pages, \"b\" for browsers)\n   * @returns Unique ID like \"p1\", \"p2\", etc.\n   */\n  protected generateId(prefix: string): string {\n    return `${prefix}${++this.idCounter}`;\n  }\n\n  /**\n   * Create a new session.\n   * Must be implemented by subclasses.\n   */\n  abstract createSession(config?: TConfig): Promise<string>;\n\n  /**\n   * Close and remove a session.\n   * Must be implemented by subclasses.\n   */\n  abstract closeSession(id: string): Promise<void>;\n\n  /**\n   * Get a session by ID.\n   */\n  getSession(id: string): TSession | undefined {\n    return this.sessions.get(id);\n  }\n\n  /**\n   * Get a session by ID, throwing if not found.\n   */\n  requireSession(id: string): TSession {\n    const session = this.sessions.get(id);\n    if (!session) {\n      throw new Error(`Session not found: ${id}`);\n    }\n    return session;\n  }\n\n  /**\n   * List all active session IDs.\n   */\n  listSessions(): string[] {\n    return Array.from(this.sessions.keys());\n  }\n\n  /**\n   * Check if a session exists.\n   */\n  hasSession(id: string): boolean {\n    return this.sessions.has(id);\n  }\n\n  /**\n   * Close all sessions.\n   * Closes sessions in reverse order (most recent first).\n   */\n  async closeAll(): Promise<void> {\n    const ids = this.listSessions().reverse();\n    for (const id of ids) {\n      try {\n        await this.closeSession(id);\n      } catch {\n        // Continue closing other sessions even if one fails\n      }\n    }\n  }\n}\n\n/**\n * Simple in-memory session manager for testing or lightweight use cases.\n *\n * Sessions are just stored objects with no special cleanup logic.\n *\n * @example\n * ```typescript\n * const manager = new SimpleSessionManager<MyData>();\n * const id = await manager.createSession({ value: 42 });\n * const data = manager.requireSession(id);  // { value: 42 }\n * await manager.closeSession(id);\n * ```\n */\nexport class SimpleSessionManager<TSession> extends BaseSessionManager<TSession, TSession> {\n  /**\n   * Create a session by storing the provided data.\n   */\n  async createSession(data?: TSession): Promise<string> {\n    const id = this.generateId(\"s\");\n    if (data !== undefined) {\n      this.sessions.set(id, data);\n    }\n    return id;\n  }\n\n  /**\n   * Close a session by removing it from the map.\n   */\n  async closeSession(id: string): Promise<void> {\n    this.sessions.delete(id);\n  }\n\n  /**\n   * Set session data directly.\n   */\n  setSession(id: string, data: TSession): void {\n    this.sessions.set(id, data);\n  }\n}\n","/**\n * Skills system — Agent Skills open standard (agentskills.io) support.\n *\n * Skills are markdown-based instruction packages that extend agent capabilities\n * through prompt injection and context management. They use three-tier\n * progressive disclosure to manage context window budget.\n *\n * @module skills\n */\n\n// Activation logic\nexport {\n  preprocessShellCommands,\n  resolveInstructions,\n  substituteArguments,\n  substituteVariables,\n} from \"./activation.js\";\n// LoadSkill meta-gadget\nexport { createLoadSkillGadget, LOAD_SKILL_GADGET_NAME } from \"./load-skill-gadget.js\";\n// Filesystem loader\nexport { discoverSkills, loadSkillsFromDirectory } from \"./loader.js\";\n// SKILL.md parser\nexport {\n  parseFrontmatter,\n  parseMetadata,\n  parseSkillContent,\n  parseSkillFile,\n  scanResources,\n  validateMetadata,\n} from \"./parser.js\";\n// Registry\nexport { SkillRegistry } from \"./registry.js\";\n// Skill class\nexport { Skill } from \"./skill.js\";\n// Core types\nexport type {\n  ParsedSkill,\n  SkillActivation,\n  SkillActivationOptions,\n  SkillMetadata,\n  SkillResource,\n  SkillSource,\n} from \"./types.js\";\n","/**\n * Formatting utilities for gadget authors and CLI output.\n *\n * Provides common formatting functions for:\n * - Text truncation\n * - Byte size formatting\n * - Date formatting\n * - Duration formatting\n *\n * @module utils/format\n *\n * @example\n * ```typescript\n * import { format } from \"llmist\";\n *\n * format.truncate(\"Long text...\", 10);  // \"Long tex...\"\n * format.bytes(1536);                    // \"1.5 KB\"\n * format.date(\"2024-01-15T10:30:00Z\");  // \"Jan 15, 2024 10:30 AM\"\n * format.duration(125000);               // \"2m 5s\"\n * ```\n */\n\n/**\n * Truncate text to a maximum length, adding suffix if truncated.\n *\n * @param text - Text to truncate\n * @param maxLength - Maximum length including suffix\n * @param suffix - Suffix to append when truncated (default: \"...\")\n * @returns Truncated text\n *\n * @example\n * ```typescript\n * truncate(\"Hello, World!\", 10);  // \"Hello, ...\"\n * truncate(\"Short\", 10);          // \"Short\"\n * truncate(\"Custom\", 6, \"…\");     // \"Custo…\"\n * ```\n */\nexport function truncate(text: string, maxLength: number, suffix = \"...\"): string {\n  if (text.length <= maxLength) return text;\n  const truncateAt = maxLength - suffix.length;\n  if (truncateAt <= 0) return suffix.slice(0, maxLength);\n  return text.slice(0, truncateAt) + suffix;\n}\n\n/**\n * Format bytes as human-readable string.\n *\n * @param bytes - Number of bytes\n * @param decimals - Number of decimal places (default: 1)\n * @returns Formatted string (e.g., \"1.5 KB\", \"2.3 MB\")\n *\n * @example\n * ```typescript\n * formatBytes(0);        // \"0 B\"\n * formatBytes(1024);     // \"1 KB\"\n * formatBytes(1536);     // \"1.5 KB\"\n * formatBytes(1048576);  // \"1 MB\"\n * ```\n */\nexport function formatBytes(bytes: number, decimals = 1): string {\n  if (bytes === 0) return \"0 B\";\n\n  const k = 1024;\n  const sizes = [\"B\", \"KB\", \"MB\", \"GB\", \"TB\", \"PB\"];\n  const i = Math.floor(Math.log(bytes) / Math.log(k));\n  const size = bytes / k ** i;\n\n  // Use integer for whole numbers, decimals otherwise\n  const formatted = size % 1 === 0 ? size.toString() : size.toFixed(decimals);\n\n  return `${formatted} ${sizes[i]}`;\n}\n\n/**\n * Format ISO date string as human-readable date.\n *\n * @param isoDate - ISO date string (e.g., \"2024-01-15T10:30:00Z\")\n * @param options - Intl.DateTimeFormat options\n * @returns Formatted date string\n *\n * @example\n * ```typescript\n * formatDate(\"2024-01-15T10:30:00Z\");\n * // \"Jan 15, 2024, 10:30 AM\" (in local timezone)\n *\n * formatDate(\"2024-01-15T10:30:00Z\", { dateStyle: \"short\" });\n * // \"1/15/24\"\n * ```\n */\nexport function formatDate(\n  isoDate: string,\n  options: Intl.DateTimeFormatOptions = {\n    year: \"numeric\",\n    month: \"short\",\n    day: \"numeric\",\n    hour: \"2-digit\",\n    minute: \"2-digit\",\n  },\n): string {\n  try {\n    const date = new Date(isoDate);\n    return date.toLocaleString(undefined, options);\n  } catch {\n    return isoDate; // Return original if parsing fails\n  }\n}\n\n/**\n * Format duration in milliseconds as human-readable string.\n *\n * @param ms - Duration in milliseconds\n * @param options - Formatting options\n * @returns Formatted duration string\n *\n * @example\n * ```typescript\n * formatDuration(500);      // \"500ms\"\n * formatDuration(1500);     // \"1.5s\"\n * formatDuration(65000);    // \"1m 5s\"\n * formatDuration(3725000);  // \"1h 2m 5s\"\n * ```\n */\nexport function formatDuration(ms: number, options: { compact?: boolean } = {}): string {\n  if (ms < 1000) {\n    return `${Math.round(ms)}ms`;\n  }\n\n  const seconds = Math.floor(ms / 1000);\n  const minutes = Math.floor(seconds / 60);\n  const hours = Math.floor(minutes / 60);\n\n  if (hours > 0) {\n    const remainingMinutes = minutes % 60;\n    const remainingSeconds = seconds % 60;\n    if (options.compact) {\n      return `${hours}h ${remainingMinutes}m`;\n    }\n    return remainingSeconds > 0\n      ? `${hours}h ${remainingMinutes}m ${remainingSeconds}s`\n      : `${hours}h ${remainingMinutes}m`;\n  }\n\n  if (minutes > 0) {\n    const remainingSeconds = seconds % 60;\n    return remainingSeconds > 0 ? `${minutes}m ${remainingSeconds}s` : `${minutes}m`;\n  }\n\n  // Less than a minute - show seconds with one decimal if not whole\n  const secs = ms / 1000;\n  return secs % 1 === 0 ? `${secs}s` : `${secs.toFixed(1)}s`;\n}\n\n/**\n * Format namespace object for convenient access.\n *\n * @example\n * ```typescript\n * import { format } from \"llmist\";\n *\n * format.truncate(\"text\", 5);\n * format.bytes(1024);\n * format.date(\"2024-01-15\");\n * format.duration(5000);\n * ```\n */\nexport const format = {\n  truncate,\n  bytes: formatBytes,\n  date: formatDate,\n  duration: formatDuration,\n} as const;\n","/**\n * Timing utilities for gadget authors.\n *\n * Provides common timing functions for:\n * - Random delays (human-like timing)\n * - Timeout handling\n * - Retry logic with backoff\n *\n * @module utils/timing\n *\n * @example\n * ```typescript\n * import { timing } from \"llmist\";\n *\n * // Human-like delays for browser automation\n * await timing.humanDelay(50, 150);\n *\n * // Add timeout to async operations\n * const result = await timing.withTimeout(\n *   () => fetchData(),\n *   5000,\n *   signal\n * );\n *\n * // Retry with exponential backoff\n * const data = await timing.withRetry(\n *   () => unreliableApi(),\n *   { maxRetries: 3, delay: 1000, backoff: \"exponential\" }\n * );\n * ```\n */\n\n/**\n * Generate a random delay within a range.\n *\n * @param min - Minimum delay in milliseconds\n * @param max - Maximum delay in milliseconds\n * @returns Random integer between min and max (inclusive)\n *\n * @example\n * ```typescript\n * const delay = randomDelay(50, 150);  // e.g., 87\n * ```\n */\nexport function randomDelay(min: number, max: number): number {\n  return Math.floor(Math.random() * (max - min + 1)) + min;\n}\n\n/**\n * Sleep for a random duration (for human-like timing).\n *\n * Useful for browser automation to appear more human-like.\n *\n * @param min - Minimum delay in milliseconds (default: 50)\n * @param max - Maximum delay in milliseconds (default: 150)\n * @returns Promise that resolves after the random delay\n *\n * @example\n * ```typescript\n * // Default human-like delay (50-150ms)\n * await humanDelay();\n *\n * // Custom range for slower actions\n * await humanDelay(100, 300);\n * ```\n */\nexport async function humanDelay(min = 50, max = 150): Promise<void> {\n  const delay = randomDelay(min, max);\n  return new Promise((resolve) => setTimeout(resolve, delay));\n}\n\n/**\n * Execute an async function with a timeout.\n *\n * @param fn - Async function to execute\n * @param timeoutMs - Timeout in milliseconds\n * @param signal - Optional AbortSignal for early cancellation\n * @returns Promise that resolves with the function result or rejects on timeout\n * @throws Error with \"Operation timed out\" message if timeout is exceeded\n *\n * @example\n * ```typescript\n * const result = await withTimeout(\n *   () => fetch(\"https://api.example.com/data\"),\n *   5000\n * );\n *\n * // With abort signal\n * const controller = new AbortController();\n * const result = await withTimeout(\n *   () => longRunningTask(),\n *   30000,\n *   controller.signal\n * );\n * ```\n */\nexport async function withTimeout<T>(\n  fn: () => Promise<T>,\n  timeoutMs: number,\n  signal?: AbortSignal,\n): Promise<T> {\n  return new Promise<T>((resolve, reject) => {\n    // Check if already aborted\n    if (signal?.aborted) {\n      reject(new Error(\"Operation aborted\"));\n      return;\n    }\n\n    let settled = false;\n\n    // Handle external abort - use { once: true } to auto-remove on fire\n    const abortHandler = () => {\n      if (!settled) {\n        settled = true;\n        clearTimeout(timeoutId);\n        reject(new Error(\"Operation aborted\"));\n      }\n    };\n\n    signal?.addEventListener(\"abort\", abortHandler, { once: true });\n\n    const timeoutId = setTimeout(() => {\n      if (!settled) {\n        settled = true;\n        signal?.removeEventListener(\"abort\", abortHandler);\n        reject(new Error(`Operation timed out after ${timeoutMs}ms`));\n      }\n    }, timeoutMs);\n\n    fn()\n      .then((result) => {\n        if (!settled) {\n          settled = true;\n          clearTimeout(timeoutId);\n          signal?.removeEventListener(\"abort\", abortHandler);\n          resolve(result);\n        }\n      })\n      .catch((error) => {\n        if (!settled) {\n          settled = true;\n          clearTimeout(timeoutId);\n          signal?.removeEventListener(\"abort\", abortHandler);\n          reject(error);\n        }\n      });\n  });\n}\n\n/**\n * Options for retry logic.\n */\nexport interface RetryOptions {\n  /** Maximum number of retry attempts (default: 3) */\n  maxRetries?: number;\n  /** Initial delay between retries in milliseconds (default: 1000) */\n  delay?: number;\n  /** Backoff strategy: \"linear\" adds delay, \"exponential\" doubles it (default: \"exponential\") */\n  backoff?: \"linear\" | \"exponential\";\n  /** Maximum delay cap in milliseconds (default: 30000) */\n  maxDelay?: number;\n  /** Optional function to determine if error is retryable (default: all errors) */\n  shouldRetry?: (error: unknown, attempt: number) => boolean;\n  /** Optional callback on each retry attempt */\n  onRetry?: (error: unknown, attempt: number, delay: number) => void;\n}\n\n/**\n * Execute an async function with retry logic.\n *\n * @param fn - Async function to execute\n * @param options - Retry options\n * @returns Promise that resolves with the function result or rejects after all retries exhausted\n *\n * @example\n * ```typescript\n * // Basic retry with defaults (3 retries, exponential backoff)\n * const result = await withRetry(() => unreliableApi());\n *\n * // Custom retry configuration\n * const result = await withRetry(\n *   () => fetchWithErrors(),\n *   {\n *     maxRetries: 5,\n *     delay: 500,\n *     backoff: \"exponential\",\n *     shouldRetry: (error) => error.status === 429 || error.status >= 500,\n *     onRetry: (error, attempt, delay) => {\n *       console.log(`Retry ${attempt} after ${delay}ms`);\n *     }\n *   }\n * );\n * ```\n */\nexport async function withRetry<T>(fn: () => Promise<T>, options: RetryOptions = {}): Promise<T> {\n  const {\n    maxRetries = 3,\n    delay = 1000,\n    backoff = \"exponential\",\n    maxDelay = 30000,\n    shouldRetry = () => true,\n    onRetry,\n  } = options;\n\n  let lastError: unknown;\n  let currentDelay = delay;\n\n  for (let attempt = 0; attempt <= maxRetries; attempt++) {\n    try {\n      return await fn();\n    } catch (error) {\n      lastError = error;\n\n      // Check if we should retry\n      if (attempt >= maxRetries || !shouldRetry(error, attempt)) {\n        throw error;\n      }\n\n      // Calculate delay for next attempt\n      const waitTime = Math.min(currentDelay, maxDelay);\n\n      // Call onRetry callback\n      onRetry?.(error, attempt + 1, waitTime);\n\n      // Wait before retry\n      await new Promise((resolve) => setTimeout(resolve, waitTime));\n\n      // Update delay for next iteration\n      if (backoff === \"exponential\") {\n        currentDelay *= 2;\n      } else {\n        currentDelay += delay;\n      }\n    }\n  }\n\n  // Should never reach here, but TypeScript needs it\n  throw lastError;\n}\n\n/**\n * Timing namespace object for convenient access.\n *\n * @example\n * ```typescript\n * import { timing } from \"llmist\";\n *\n * await timing.humanDelay();\n * const result = await timing.withTimeout(() => fetch(url), 5000);\n * const data = await timing.withRetry(() => api.call(), { maxRetries: 3 });\n * ```\n */\nexport const timing = {\n  randomDelay,\n  humanDelay,\n  withTimeout,\n  withRetry,\n} as const;\n"],"mappings":"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","names":["resolve","path","path","logger","import_node_path","logger","logger","logger","logger","path","path","z","text","header","import_node_crypto","max","logger","stream","import_zod","yaml","path","fs","import_node_fs","import_node_path","init_registry","import_promises","fs","fs","path","os","import_node_fs","import_node_os","import_node_path","init_registry","import_promises","import_node_path","init_constants","Anthropic","init_constants","stream","import_node_crypto","init_constants","init_errors","stream","text","resolve","init_constants","init_errors","init_constants","import_genai","init_constants","response","images","cost","stream","text","init_constants","requestOptions","stream","text","OpenAI","import_openai","annotationToCitation","stream","sleep","resolve","abortError","withRetries","requestOptions","isTerminalStatus","init_constants","init_errors","byId","OpenAI","import_openai","import_tiktoken","ROLE_MAP","init_constants","format","stream","text","stream","text","init_errors","byId","OpenAI","import_openai","init_constants","requestOptions","stream","format","init_constants","citationKey","init_constants","init_errors","resolve","info","init_constants","init_errors","logger","providerSpecs","text","get_encoding","max","logger","fs","pointer","path","init_parser","complete","import_zod","init_parser","equal","resolve","init_parser","stream","init_errors","path","import_node_path","init_errors","init_client","init_errors","resolve","literals","import_zod","init_errors","text","import_zod","logger","init_client","setupMcpServers","resolve","getHostExports","import_zod","timing","init_parser","init_client","init_errors","init_constants","init_constants","init_errors","AgentBuilder","LLMist","init_registry","text","max","resolve","getHostExports"]}