llmist 7.0.0 → 8.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +410 -1038
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6073 -4
- package/dist/index.d.ts +6073 -4
- package/dist/index.js +11955 -115
- package/dist/index.js.map +1 -1
- package/package.json +8 -36
- package/LICENSE +0 -21
- package/README.md +0 -511
- package/dist/chunk-5KEZ7SQX.js +0 -1182
- package/dist/chunk-5KEZ7SQX.js.map +0 -1
- package/dist/chunk-SFZIL2VR.js +0 -12214
- package/dist/chunk-SFZIL2VR.js.map +0 -1
- package/dist/cli.cjs +0 -18226
- package/dist/cli.cjs.map +0 -1
- package/dist/cli.d.cts +0 -1
- package/dist/cli.d.ts +0 -1
- package/dist/cli.js +0 -7819
- package/dist/cli.js.map +0 -1
- package/dist/mock-stream-r5vjy2Iq.d.cts +0 -6397
- package/dist/mock-stream-r5vjy2Iq.d.ts +0 -6397
- package/dist/testing/index.cjs +0 -12088
- package/dist/testing/index.cjs.map +0 -1
- package/dist/testing/index.d.cts +0 -710
- package/dist/testing/index.d.ts +0 -710
- package/dist/testing/index.js +0 -83
- package/dist/testing/index.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/agent/hook-presets.ts","../src/agent/compaction/index.ts","../src/agent/index.ts","../src/agent/hints.ts","../src/core/execution-events.ts","../src/gadgets/helpers.ts","../src/utils/config-resolver.ts"],"sourcesContent":["// Re-export Zod's z for schema definitions\n// Using llmist's z ensures .describe() metadata is preserved in JSON schemas\nexport { z } from \"zod\";\n// Syntactic sugar: Agent builder and event handlers\nexport type { HistoryMessage, TrailingMessage, TrailingMessageContext } from \"./agent/builder.js\";\nexport { AgentBuilder } from \"./agent/builder.js\";\nexport type { EventHandlers } from \"./agent/event-handlers.js\";\nexport { collectEvents, collectText, runWithHandlers } from \"./agent/event-handlers.js\";\n// Syntactic sugar: Hook presets\nexport type { LoggingOptions } from \"./agent/hook-presets.js\";\nexport { HookPresets } from \"./agent/hook-presets.js\";\n// Agent infrastructure\n// New clean hooks system\nexport type {\n AfterGadgetExecutionAction,\n AfterGadgetExecutionControllerContext,\n AfterLLMCallAction,\n AfterLLMCallControllerContext,\n AfterLLMErrorAction,\n AgentHooks,\n AgentOptions,\n BeforeGadgetExecutionAction,\n BeforeLLMCallAction,\n // Interceptor contexts\n ChunkInterceptorContext,\n // Context compaction\n CompactionConfig,\n CompactionContext,\n CompactionEvent,\n CompactionResult,\n CompactionStats,\n CompactionStrategy,\n Controllers,\n GadgetExecutionControllerContext,\n GadgetParameterInterceptorContext,\n GadgetResultInterceptorContext,\n // LLM Assistance Hints\n HintsConfig,\n IConversationManager,\n Interceptors,\n IterationHintOptions,\n // Controller contexts and actions\n LLMCallControllerContext,\n LLMErrorControllerContext,\n MessageInterceptorContext,\n MessageTurn,\n ObserveChunkContext,\n ObserveCompactionContext,\n ObserveGadgetCompleteContext,\n ObserveGadgetStartContext,\n // Observer contexts\n ObserveLLMCallContext,\n ObserveLLMCompleteContext,\n ObserveLLMErrorContext,\n Observers,\n ParallelGadgetHintOptions,\n ResolvedCompactionConfig,\n // Gadget output limiting\n StoredOutput,\n StreamProcessingResult,\n StreamProcessorOptions,\n // Subagent context for hook observers\n SubagentContext,\n} from \"./agent/index.js\";\nexport {\n // Compaction exports\n CompactionManager,\n // Existing exports\n ConversationManager,\n // LLM Assistance Hints\n createHints,\n DEFAULT_COMPACTION_CONFIG,\n DEFAULT_SUMMARIZATION_PROMPT,\n GadgetOutputStore,\n HybridStrategy,\n iterationProgressHint,\n parallelGadgetHint,\n SlidingWindowStrategy,\n StreamProcessor,\n SummarizationStrategy,\n} from \"./agent/index.js\";\nexport type { LLMistOptions } from \"./core/client.js\";\nexport { LLMist } from \"./core/client.js\";\n\n// Execution Tree - first-class model for nested subagent support\nexport type {\n AddGadgetParams,\n AddLLMCallParams,\n CompleteGadgetParams,\n CompleteLLMCallParams,\n ExecutionNode,\n ExecutionNodeType,\n GadgetNode,\n GadgetState,\n LLMCallNode,\n NodeId,\n} from \"./core/execution-tree.js\";\nexport { ExecutionTree } from \"./core/execution-tree.js\";\n\n// Unified execution events with tree context\nexport type {\n BaseExecutionEvent,\n CompactionEvent as TreeCompactionEvent,\n ExecutionEvent,\n ExecutionEventType,\n GadgetCallEvent,\n GadgetCompleteEvent,\n GadgetErrorEvent,\n GadgetEvent,\n GadgetSkippedEvent as TreeGadgetSkippedEvent,\n GadgetStartEvent,\n HumanInputRequiredEvent,\n LLMCallCompleteEvent,\n LLMCallErrorEvent,\n LLMCallStartEvent,\n LLMCallStreamEvent,\n LLMEvent,\n StreamCompleteEvent,\n TextEvent,\n} from \"./core/execution-events.js\";\nexport {\n filterByDepth,\n filterByParent,\n filterRootEvents,\n groupByParent,\n isGadgetEvent,\n isLLMEvent,\n isRootEvent,\n isSubagentEvent,\n} from \"./core/execution-events.js\";\n\n// Input content types for multimodal messages\nexport type {\n AudioContentPart,\n AudioMimeType,\n AudioSource,\n ContentPart,\n ImageBase64Source,\n ImageContentPart,\n ImageMimeType,\n ImageSource,\n ImageUrlSource,\n TextContentPart,\n} from \"./core/input-content.js\";\nexport {\n audioFromBase64,\n audioFromBuffer,\n detectAudioMimeType,\n detectImageMimeType,\n imageFromBase64,\n imageFromBuffer,\n imageFromUrl,\n isAudioPart,\n isDataUrl,\n isImagePart,\n isTextPart,\n parseDataUrl,\n text,\n toBase64,\n} from \"./core/input-content.js\";\n\nexport type { LLMMessage, MessageContent, MessageRole } from \"./core/messages.js\";\nexport { extractMessageText, LLMMessageBuilder, normalizeMessageContent } from \"./core/messages.js\";\n// Model catalog\nexport type {\n CostEstimate,\n ModelFeatures,\n ModelLimits,\n ModelPricing,\n ModelSpec,\n} from \"./core/model-catalog.js\";\nexport { ModelRegistry } from \"./core/model-registry.js\";\n// Syntactic sugar: Model shortcuts and quick methods\nexport {\n getModelId,\n getProvider,\n hasProviderPrefix,\n MODEL_ALIASES,\n resolveModel,\n} from \"./core/model-shortcuts.js\";\n// Vision namespace for one-shot image analysis\nexport type { VisionAnalyzeOptions, VisionAnalyzeResult } from \"./core/namespaces/vision.js\";\nexport type {\n LLMGenerationOptions,\n LLMStream,\n LLMStreamChunk,\n ModelDescriptor,\n ProviderIdentifier,\n TokenUsage,\n} from \"./core/options.js\";\nexport { ModelIdentifierParser } from \"./core/options.js\";\nexport type {\n HintContext,\n HintTemplate,\n PromptContext,\n PromptTemplate,\n PromptTemplateConfig,\n} from \"./core/prompt-config.js\";\nexport {\n DEFAULT_HINTS,\n DEFAULT_PROMPTS,\n resolveHintTemplate,\n resolvePromptTemplate,\n resolveRulesTemplate,\n} from \"./core/prompt-config.js\";\nexport type { TextGenerationOptions } from \"./core/quick-methods.js\";\nexport { complete, stream } from \"./core/quick-methods.js\";\nexport type { CreateGadgetConfig } from \"./gadgets/create-gadget.js\";\nexport { createGadget } from \"./gadgets/create-gadget.js\";\n// Gadget infrastructure\nexport {\n AbortException,\n HumanInputRequiredException,\n TaskCompletionSignal,\n TimeoutException,\n} from \"./gadgets/exceptions.js\";\nexport { GadgetExecutor } from \"./gadgets/executor.js\";\nexport { AbstractGadget } from \"./gadgets/gadget.js\";\n// Gadget output viewer (for custom output store integration)\nexport { createGadgetOutputViewer } from \"./gadgets/output-viewer.js\";\nexport { GadgetCallParser } from \"./gadgets/parser.js\";\nexport type { GadgetClass, GadgetOrClass } from \"./gadgets/registry.js\";\nexport { GadgetRegistry } from \"./gadgets/registry.js\";\n\n// Syntactic sugar: Typed gadgets and helpers\nexport type { GadgetConfig } from \"./gadgets/typed-gadget.js\";\nexport { Gadget } from \"./gadgets/typed-gadget.js\";\nexport type {\n CostReportingLLMist,\n ExecutionContext,\n GadgetExample,\n GadgetExecuteResult,\n GadgetExecuteResultWithMedia,\n GadgetExecuteReturn,\n GadgetExecutionResult,\n GadgetMediaOutput,\n GadgetSkippedEvent,\n // Host exports for external gadgets\n HostExports,\n MediaKind,\n MediaMetadata,\n ParsedGadgetCall,\n StoredMedia,\n StreamEvent,\n // Subagent event types\n SubagentEvent,\n SubagentStreamEvent,\n TextOnlyAction,\n TextOnlyContext,\n TextOnlyCustomHandler,\n TextOnlyGadgetConfig,\n TextOnlyHandler,\n TextOnlyStrategy,\n} from \"./gadgets/types.js\";\n// Media output helpers for gadgets\nexport {\n createMediaOutput,\n resultWithAudio,\n resultWithFile,\n resultWithImage,\n resultWithImages,\n resultWithMedia,\n} from \"./gadgets/helpers.js\";\n\n// Host exports helper for external gadgets\nimport type { ExecutionContext, HostExports } from \"./gadgets/types.js\";\n\n/**\n * Get host llmist exports from execution context.\n *\n * External gadgets MUST use this instead of importing classes directly from 'llmist'\n * to ensure they use the same version as the host CLI, enabling proper tree sharing\n * and avoiding the \"dual-package problem\".\n *\n * @param ctx - The execution context passed to gadget.execute()\n * @returns The host's llmist exports (AgentBuilder, Gadget, etc.)\n * @throws Error if ctx or ctx.hostExports is undefined\n *\n * @example\n * ```typescript\n * import { getHostExports, Gadget, z } from 'llmist';\n * import type { ExecutionContext } from 'llmist';\n *\n * class BrowseWeb extends Gadget({\n * name: 'BrowseWeb',\n * description: 'Browse a website autonomously',\n * schema: z.object({ task: z.string(), url: z.string() }),\n * }) {\n * async execute(params: this['params'], ctx?: ExecutionContext) {\n * // Get host's AgentBuilder to ensure tree sharing works correctly\n * const { AgentBuilder } = getHostExports(ctx!);\n *\n * const agent = new AgentBuilder()\n * .withParentContext(ctx!)\n * .withGadgets(Navigate, Click, Screenshot)\n * .ask(params.task);\n *\n * for await (const event of agent.run()) {\n * // Events flow through host's shared tree\n * }\n * }\n * }\n * ```\n */\nexport function getHostExports(ctx: ExecutionContext): HostExports {\n if (!ctx?.hostExports) {\n throw new Error(\n \"hostExports not available. Gadgets that create subagents must be run \" +\n \"via llmist agent, not standalone. Ensure you are using llmist >= 6.2.0.\",\n );\n }\n return ctx.hostExports;\n}\n// Media storage for gadget outputs\nexport { MediaStore } from \"./gadgets/media-store.js\";\nexport type { ValidationIssue, ValidationResult } from \"./gadgets/validation.js\";\nexport { validateAndApplyDefaults, validateGadgetParams } from \"./gadgets/validation.js\";\nexport type { LoggerOptions } from \"./logging/logger.js\";\nexport { createLogger, defaultLogger } from \"./logging/logger.js\";\n// Re-export Logger type for external gadgets that need to type ctx.logger\nexport type { ILogObj, Logger } from \"tslog\";\n\n// Utility functions for subagent gadgets\nexport type { ResolveValueOptions } from \"./utils/config-resolver.js\";\nexport { resolveConfig, resolveSubagentModel, resolveValue } from \"./utils/config-resolver.js\";\nexport {\n AnthropicMessagesProvider,\n createAnthropicProviderFromEnv,\n} from \"./providers/anthropic.js\";\nexport { discoverProviderAdapters } from \"./providers/discovery.js\";\nexport { createGeminiProviderFromEnv, GeminiGenerativeProvider } from \"./providers/gemini.js\";\nexport { createOpenAIProviderFromEnv, OpenAIChatProvider } from \"./providers/openai.js\";\nexport type { ProviderAdapter } from \"./providers/provider.js\";\n\n// Testing/Mock infrastructure\nexport type {\n MockMatcher,\n MockMatcherContext,\n MockOptions,\n MockRegistration,\n MockResponse,\n MockStats,\n} from \"./testing/index.js\";\nexport {\n createMockAdapter,\n createMockClient,\n createMockStream,\n createTextMockStream,\n getMockManager,\n MockBuilder,\n MockManager,\n MockProviderAdapter,\n mockLLM,\n} from \"./testing/index.js\";\n","/**\n * Ready-to-use hook configurations for common monitoring, logging, and debugging tasks.\n *\n * HookPresets provide instant observability without writing custom hooks. They're the\n * fastest way to add monitoring to your agents during development and production.\n *\n * ## Available Presets\n *\n * - **logging(options?)** - Log LLM calls and gadget execution\n * - **timing()** - Measure execution time for operations\n * - **tokenTracking()** - Track cumulative token usage and costs\n * - **progressTracking(options?)** - Track progress with iterations, tokens, cost, and timing (SHOWCASE)\n * - **errorLogging()** - Log detailed error information\n * - **silent()** - No output (useful for testing)\n * - **monitoring(options?)** - All-in-one preset combining logging, timing, tokens, and errors\n * - **merge(...hookSets)** - Combine multiple hook configurations\n *\n * ## Quick Start\n *\n * @example\n * ```typescript\n * import { LLMist, HookPresets } from 'llmist';\n *\n * // Basic logging\n * await LLMist.createAgent()\n * .withHooks(HookPresets.logging())\n * .ask(\"Your prompt\");\n *\n * // Full monitoring suite (recommended for development)\n * await LLMist.createAgent()\n * .withHooks(HookPresets.monitoring({ verbose: true }))\n * .ask(\"Your prompt\");\n *\n * // Combine multiple presets\n * await LLMist.createAgent()\n * .withHooks(HookPresets.merge(\n * HookPresets.timing(),\n * HookPresets.tokenTracking()\n * ))\n * .ask(\"Your prompt\");\n *\n * // Environment-based configuration\n * const hooks = process.env.NODE_ENV === 'production'\n * ? HookPresets.merge(HookPresets.errorLogging(), HookPresets.tokenTracking())\n * : HookPresets.monitoring({ verbose: true });\n *\n * await LLMist.createAgent()\n * .withHooks(hooks)\n * .ask(\"Your prompt\");\n * ```\n *\n * @see {@link https://github.com/zbigniewsobiecki/llmist/blob/main/docs/HOOKS.md | Full documentation}\n */\n\nimport type { ModelRegistry } from \"../core/model-registry.js\";\nimport type { AgentHooks } from \"./hooks.js\";\n\n/**\n * Options for logging preset.\n */\nexport interface LoggingOptions {\n /** Include verbose details like parameters and results */\n verbose?: boolean;\n}\n\n/**\n * Progress statistics reported by progressTracking preset.\n *\n * Contains cumulative metrics across all LLM calls in the agent session,\n * useful for building progress UI, cost monitoring, and performance tracking.\n */\nexport interface ProgressStats {\n /** Current iteration number (increments on each LLM call start) */\n currentIteration: number;\n\n /** Total number of completed LLM calls */\n totalCalls: number;\n\n /** Cumulative input tokens across all calls */\n totalInputTokens: number;\n\n /** Cumulative output tokens across all calls */\n totalOutputTokens: number;\n\n /** Total tokens (input + output) */\n totalTokens: number;\n\n /** Cumulative cost in USD (includes LLM and gadget costs; requires modelRegistry for LLM cost estimation) */\n totalCost: number;\n\n /** Elapsed time in seconds since first call */\n elapsedSeconds: number;\n}\n\n/**\n * Options for progressTracking preset.\n *\n * Controls how progress data is tracked and reported during agent execution.\n */\nexport interface ProgressTrackingOptions {\n /**\n * Model registry for cost calculation.\n *\n * If provided, enables automatic cost estimation based on token usage\n * and model pricing data. Without it, totalCost will always be 0.\n *\n * @example\n * ```typescript\n * import { LLMist, HookPresets } from 'llmist';\n *\n * const client = LLMist.create();\n * const hooks = HookPresets.progressTracking({\n * modelRegistry: client.modelRegistry // Enable cost tracking\n * });\n * ```\n */\n modelRegistry?: ModelRegistry;\n\n /**\n * Callback invoked after each LLM call completion with cumulative stats.\n *\n * Use this to update progress UI, log metrics, or track budgets in real-time.\n *\n * @example\n * ```typescript\n * HookPresets.progressTracking({\n * modelRegistry: client.modelRegistry,\n * onProgress: (stats) => {\n * console.log(`Iteration #${stats.currentIteration}`);\n * console.log(`Cost so far: $${stats.totalCost.toFixed(4)}`);\n * console.log(`Elapsed: ${stats.elapsedSeconds}s`);\n * }\n * })\n * ```\n */\n onProgress?: (stats: ProgressStats) => void;\n\n /**\n * Whether to log progress to console after each LLM call.\n *\n * When enabled, prints a summary line with tokens, cost, and elapsed time.\n * Useful for quick debugging without implementing a custom callback.\n *\n * Default: false\n *\n * @example\n * ```typescript\n * // Quick console-based progress tracking\n * HookPresets.progressTracking({\n * modelRegistry: client.modelRegistry,\n * logProgress: true // Log to console\n * })\n * // Output: 📊 Progress: Iteration #2 | 1,234 tokens | $0.0056 | 12.3s\n * ```\n */\n logProgress?: boolean;\n}\n\n/**\n * Common hook presets.\n */\nexport class HookPresets {\n /**\n * Logs LLM calls and gadget execution to console with optional verbosity.\n *\n * **Output (basic mode):**\n * - LLM call start/complete events with iteration numbers\n * - Gadget execution start/complete with gadget names\n * - Token counts when available\n *\n * **Output (verbose mode):**\n * - All basic mode output\n * - Full gadget parameters (formatted JSON)\n * - Full gadget results\n * - Complete LLM response text\n *\n * **Use cases:**\n * - Basic development debugging and execution flow visibility\n * - Understanding agent decision-making and tool usage\n * - Troubleshooting gadget invocations\n *\n * **Performance:** Minimal overhead. Console writes are synchronous but fast.\n *\n * @param options - Logging options\n * @param options.verbose - Include full parameters and results. Default: false\n * @returns Hook configuration that can be passed to .withHooks()\n *\n * @example\n * ```typescript\n * // Basic logging\n * await LLMist.createAgent()\n * .withHooks(HookPresets.logging())\n * .ask(\"Calculate 15 * 23\");\n * // Output: [LLM] Starting call (iteration 0)\n * // [GADGET] Executing Calculator\n * // [GADGET] Completed Calculator\n * // [LLM] Completed (tokens: 245)\n * ```\n *\n * @example\n * ```typescript\n * // Verbose logging with full details\n * await LLMist.createAgent()\n * .withHooks(HookPresets.logging({ verbose: true }))\n * .ask(\"Calculate 15 * 23\");\n * // Output includes: parameters, results, and full responses\n * ```\n *\n * @example\n * ```typescript\n * // Environment-based verbosity\n * const isDev = process.env.NODE_ENV === 'development';\n * .withHooks(HookPresets.logging({ verbose: isDev }))\n * ```\n *\n * @see {@link https://github.com/zbigniewsobiecki/llmist/blob/main/docs/HOOKS.md#hookpresetsloggingoptions | Full documentation}\n */\n static logging(options: LoggingOptions = {}): AgentHooks {\n return {\n observers: {\n onLLMCallStart: async (ctx) => {\n console.log(`[LLM] Starting call (iteration ${ctx.iteration})`);\n },\n onLLMCallComplete: async (ctx) => {\n const tokens = ctx.usage?.totalTokens ?? \"unknown\";\n console.log(`[LLM] Completed (tokens: ${tokens})`);\n if (options.verbose && ctx.finalMessage) {\n console.log(`[LLM] Response: ${ctx.finalMessage}`);\n }\n },\n onGadgetExecutionStart: async (ctx) => {\n console.log(`[GADGET] Executing ${ctx.gadgetName}`);\n if (options.verbose) {\n console.log(`[GADGET] Parameters:`, JSON.stringify(ctx.parameters, null, 2));\n }\n },\n onGadgetExecutionComplete: async (ctx) => {\n console.log(`[GADGET] Completed ${ctx.gadgetName}`);\n if (options.verbose) {\n const display = ctx.error ?? ctx.finalResult ?? \"(no result)\";\n console.log(`[GADGET] Result: ${display}`);\n }\n },\n },\n };\n }\n\n /**\n * Measures and logs execution time for LLM calls and gadgets.\n *\n * **Output:**\n * - Duration in milliseconds with ⏱️ emoji for each operation\n * - Separate timing for each LLM iteration\n * - Separate timing for each gadget execution\n *\n * **Use cases:**\n * - Performance profiling and optimization\n * - Identifying slow operations (LLM calls vs gadget execution)\n * - Monitoring response times in production\n * - Capacity planning and SLA tracking\n *\n * **Performance:** Negligible overhead. Uses Date.now() for timing measurements.\n *\n * @returns Hook configuration that can be passed to .withHooks()\n *\n * @example\n * ```typescript\n * // Basic timing\n * await LLMist.createAgent()\n * .withHooks(HookPresets.timing())\n * .withGadgets(Weather, Database)\n * .ask(\"What's the weather in NYC?\");\n * // Output: ⏱️ LLM call took 1234ms\n * // ⏱️ Gadget Weather took 567ms\n * // ⏱️ LLM call took 890ms\n * ```\n *\n * @example\n * ```typescript\n * // Combined with logging for full context\n * .withHooks(HookPresets.merge(\n * HookPresets.logging(),\n * HookPresets.timing()\n * ))\n * ```\n *\n * @example\n * ```typescript\n * // Correlate performance with cost\n * .withHooks(HookPresets.merge(\n * HookPresets.timing(),\n * HookPresets.tokenTracking()\n * ))\n * ```\n *\n * @see {@link https://github.com/zbigniewsobiecki/llmist/blob/main/docs/HOOKS.md#hookpresetstiming | Full documentation}\n */\n static timing(): AgentHooks {\n const timings = new Map<string, number>();\n\n return {\n observers: {\n onLLMCallStart: async (ctx) => {\n timings.set(`llm-${ctx.iteration}`, Date.now());\n },\n onLLMCallComplete: async (ctx) => {\n const start = timings.get(`llm-${ctx.iteration}`);\n if (start) {\n const duration = Date.now() - start;\n console.log(`⏱️ LLM call took ${duration}ms`);\n timings.delete(`llm-${ctx.iteration}`);\n }\n },\n onGadgetExecutionStart: async (ctx) => {\n const key = `gadget-${ctx.gadgetName}-${Date.now()}`;\n timings.set(key, Date.now());\n // Store key for lookup in complete handler\n (ctx as any)._timingKey = key;\n },\n onGadgetExecutionComplete: async (ctx) => {\n const key = (ctx as any)._timingKey;\n if (key) {\n const start = timings.get(key);\n if (start) {\n const duration = Date.now() - start;\n console.log(`⏱️ Gadget ${ctx.gadgetName} took ${duration}ms`);\n timings.delete(key);\n }\n }\n },\n },\n };\n }\n\n /**\n * Tracks cumulative token usage across all LLM calls.\n *\n * **Output:**\n * - Per-call token count with 📊 emoji\n * - Cumulative total across all calls\n * - Call count for average calculations\n *\n * **Use cases:**\n * - Cost monitoring and budget tracking\n * - Optimizing prompts to reduce token usage\n * - Comparing token efficiency across different approaches\n * - Real-time cost estimation\n *\n * **Performance:** Minimal overhead. Simple counter increments.\n *\n * **Note:** Token counts depend on the provider's response. Some providers\n * may not include usage data, in which case counts won't be logged.\n *\n * @returns Hook configuration that can be passed to .withHooks()\n *\n * @example\n * ```typescript\n * // Basic token tracking\n * await LLMist.createAgent()\n * .withHooks(HookPresets.tokenTracking())\n * .ask(\"Summarize this document...\");\n * // Output: 📊 Tokens this call: 1,234\n * // 📊 Total tokens: 1,234 (across 1 calls)\n * // 📊 Tokens this call: 567\n * // 📊 Total tokens: 1,801 (across 2 calls)\n * ```\n *\n * @example\n * ```typescript\n * // Cost calculation with custom hook\n * let totalTokens = 0;\n * .withHooks(HookPresets.merge(\n * HookPresets.tokenTracking(),\n * {\n * observers: {\n * onLLMCallComplete: async (ctx) => {\n * totalTokens += ctx.usage?.totalTokens ?? 0;\n * const cost = (totalTokens / 1_000_000) * 3.0; // $3 per 1M tokens\n * console.log(`💰 Estimated cost: $${cost.toFixed(4)}`);\n * },\n * },\n * }\n * ))\n * ```\n *\n * @see {@link https://github.com/zbigniewsobiecki/llmist/blob/main/docs/HOOKS.md#hookpresetstokentracking | Full documentation}\n */\n static tokenTracking(): AgentHooks {\n let totalTokens = 0;\n let totalCalls = 0;\n\n return {\n observers: {\n onLLMCallComplete: async (ctx) => {\n totalCalls++;\n if (ctx.usage?.totalTokens) {\n totalTokens += ctx.usage.totalTokens;\n console.log(`📊 Tokens this call: ${ctx.usage.totalTokens}`);\n console.log(`📊 Total tokens: ${totalTokens} (across ${totalCalls} calls)`);\n }\n },\n },\n };\n }\n\n /**\n * Tracks comprehensive progress metrics including iterations, tokens, cost, and timing.\n *\n * **This preset showcases llmist's core capabilities by demonstrating:**\n * - Observer pattern for non-intrusive monitoring\n * - Integration with ModelRegistry for cost estimation\n * - Callback-based architecture for flexible UI updates\n * - Provider-agnostic token and cost tracking\n *\n * Unlike `tokenTracking()` which only logs to console, this preset provides\n * structured data through callbacks, making it perfect for building custom UIs,\n * dashboards, or progress indicators (like the llmist CLI).\n *\n * **Output (when logProgress: true):**\n * - Iteration number and call count\n * - Cumulative token usage (input + output)\n * - Cumulative cost in USD (requires modelRegistry)\n * - Elapsed time in seconds\n *\n * **Use cases:**\n * - Building CLI progress indicators with live updates\n * - Creating web dashboards with real-time metrics\n * - Budget monitoring and cost alerts\n * - Performance tracking and optimization\n * - Custom logging to external systems (Datadog, CloudWatch, etc.)\n *\n * **Performance:** Minimal overhead. Uses Date.now() for timing and optional\n * ModelRegistry.estimateCost() which is O(1) lookup. Callback invocation is\n * synchronous and fast.\n *\n * @param options - Progress tracking options\n * @param options.modelRegistry - ModelRegistry for cost estimation (optional)\n * @param options.onProgress - Callback invoked after each LLM call (optional)\n * @param options.logProgress - Log progress to console (default: false)\n * @returns Hook configuration with progress tracking observers\n *\n * @example\n * ```typescript\n * // Basic usage with callback (RECOMMENDED - used by llmist CLI)\n * import { LLMist, HookPresets } from 'llmist';\n *\n * const client = LLMist.create();\n *\n * await client.agent()\n * .withHooks(HookPresets.progressTracking({\n * modelRegistry: client.modelRegistry,\n * onProgress: (stats) => {\n * // Update your UI with stats\n * console.log(`#${stats.currentIteration} | ${stats.totalTokens} tokens | $${stats.totalCost.toFixed(4)}`);\n * }\n * }))\n * .withGadgets(Calculator)\n * .ask(\"Calculate 15 * 23\");\n * // Output: #1 | 245 tokens | $0.0012\n * ```\n *\n * @example\n * ```typescript\n * // Console logging mode (quick debugging)\n * await client.agent()\n * .withHooks(HookPresets.progressTracking({\n * modelRegistry: client.modelRegistry,\n * logProgress: true // Simple console output\n * }))\n * .ask(\"Your prompt\");\n * // Output: 📊 Progress: Iteration #1 | 245 tokens | $0.0012 | 1.2s\n * ```\n *\n * @example\n * ```typescript\n * // Budget monitoring with alerts\n * const BUDGET_USD = 0.10;\n *\n * await client.agent()\n * .withHooks(HookPresets.progressTracking({\n * modelRegistry: client.modelRegistry,\n * onProgress: (stats) => {\n * if (stats.totalCost > BUDGET_USD) {\n * throw new Error(`Budget exceeded: $${stats.totalCost.toFixed(4)}`);\n * }\n * }\n * }))\n * .ask(\"Long running task...\");\n * ```\n *\n * @example\n * ```typescript\n * // Web dashboard integration\n * let progressBar: HTMLElement;\n *\n * await client.agent()\n * .withHooks(HookPresets.progressTracking({\n * modelRegistry: client.modelRegistry,\n * onProgress: (stats) => {\n * // Update web UI in real-time\n * progressBar.textContent = `Iteration ${stats.currentIteration}`;\n * progressBar.dataset.cost = stats.totalCost.toFixed(4);\n * progressBar.dataset.tokens = stats.totalTokens.toString();\n * }\n * }))\n * .ask(\"Your prompt\");\n * ```\n *\n * @example\n * ```typescript\n * // External logging (Datadog, CloudWatch, etc.)\n * await client.agent()\n * .withHooks(HookPresets.progressTracking({\n * modelRegistry: client.modelRegistry,\n * onProgress: async (stats) => {\n * await metrics.gauge('llm.iteration', stats.currentIteration);\n * await metrics.gauge('llm.cost', stats.totalCost);\n * await metrics.gauge('llm.tokens', stats.totalTokens);\n * }\n * }))\n * .ask(\"Your prompt\");\n * ```\n *\n * @see {@link https://github.com/zbigniewsobiecki/llmist/blob/main/docs/HOOKS.md#hookpresetsprogresstrackingoptions | Full documentation}\n * @see {@link ProgressTrackingOptions} for detailed options\n * @see {@link ProgressStats} for the callback data structure\n */\n static progressTracking(options?: ProgressTrackingOptions): AgentHooks {\n const { modelRegistry, onProgress, logProgress = false } = options ?? {};\n\n // State tracking - follows same pattern as tokenTracking()\n let totalCalls = 0;\n let currentIteration = 0;\n let totalInputTokens = 0;\n let totalOutputTokens = 0;\n let totalCost = 0;\n let totalGadgetCost = 0;\n const startTime = Date.now();\n\n return {\n observers: {\n // Track iteration on each LLM call start\n onLLMCallStart: async (ctx) => {\n currentIteration++;\n },\n\n // Accumulate metrics and report progress on each LLM call completion\n onLLMCallComplete: async (ctx) => {\n totalCalls++;\n\n // Track token usage from provider response\n if (ctx.usage) {\n totalInputTokens += ctx.usage.inputTokens;\n totalOutputTokens += ctx.usage.outputTokens;\n\n // Calculate cost using ModelRegistry (core llmist feature)\n // This showcases integration with llmist's pricing catalog\n if (modelRegistry) {\n try {\n // Extract model name from provider:model format\n // Example: \"openai:gpt-4o\" -> \"gpt-4o\"\n const modelName = ctx.options.model.includes(\":\")\n ? ctx.options.model.split(\":\")[1]\n : ctx.options.model;\n\n // Use core's estimateCost() for accurate pricing\n const costEstimate = modelRegistry.estimateCost(\n modelName,\n ctx.usage.inputTokens,\n ctx.usage.outputTokens,\n );\n\n if (costEstimate) {\n totalCost += costEstimate.totalCost;\n }\n } catch (error) {\n // Graceful degradation - log error but don't crash\n // This follows llmist's principle of non-intrusive monitoring\n if (logProgress) {\n console.warn(`⚠️ Cost estimation failed:`, error);\n }\n }\n }\n }\n\n // Build comprehensive progress stats (LLM + gadget costs combined)\n const stats: ProgressStats = {\n currentIteration,\n totalCalls,\n totalInputTokens,\n totalOutputTokens,\n totalTokens: totalInputTokens + totalOutputTokens,\n totalCost: totalCost + totalGadgetCost,\n elapsedSeconds: Number(((Date.now() - startTime) / 1000).toFixed(1)),\n };\n\n // Invoke callback if provided (used by CLI and custom UIs)\n if (onProgress) {\n onProgress(stats);\n }\n\n // Optional console logging for quick debugging\n if (logProgress) {\n const formattedTokens =\n stats.totalTokens >= 1000\n ? `${(stats.totalTokens / 1000).toFixed(1)}k`\n : `${stats.totalTokens}`;\n\n const formattedCost = stats.totalCost > 0 ? `$${stats.totalCost.toFixed(4)}` : \"$0\";\n\n console.log(\n `📊 Progress: Iteration #${stats.currentIteration} | ${formattedTokens} tokens | ${formattedCost} | ${stats.elapsedSeconds}s`,\n );\n }\n },\n\n // Track gadget execution costs\n onGadgetExecutionComplete: async (ctx) => {\n if (ctx.cost && ctx.cost > 0) {\n totalGadgetCost += ctx.cost;\n }\n },\n },\n };\n }\n\n /**\n * Logs detailed error information for debugging and troubleshooting.\n *\n * **Output:**\n * - LLM errors with ❌ emoji, including model and recovery status\n * - Gadget errors with full context (parameters, error message)\n * - Separate logging for LLM and gadget failures\n *\n * **Use cases:**\n * - Troubleshooting production issues\n * - Understanding error patterns and frequency\n * - Debugging error recovery behavior\n * - Collecting error metrics for monitoring\n *\n * **Performance:** Minimal overhead. Only logs when errors occur.\n *\n * @returns Hook configuration that can be passed to .withHooks()\n *\n * @example\n * ```typescript\n * // Basic error logging\n * await LLMist.createAgent()\n * .withHooks(HookPresets.errorLogging())\n * .withGadgets(Database)\n * .ask(\"Fetch user data\");\n * // Output (on LLM error): ❌ LLM Error (iteration 1): Rate limit exceeded\n * // Model: gpt-5-nano\n * // Recovered: true\n * // Output (on gadget error): ❌ Gadget Error: Database\n * // Error: Connection timeout\n * // Parameters: {...}\n * ```\n *\n * @example\n * ```typescript\n * // Combine with monitoring for full context\n * .withHooks(HookPresets.merge(\n * HookPresets.monitoring(), // Includes errorLogging\n * customErrorAnalytics\n * ))\n * ```\n *\n * @example\n * ```typescript\n * // Error analytics collection\n * const errors: any[] = [];\n * .withHooks(HookPresets.merge(\n * HookPresets.errorLogging(),\n * {\n * observers: {\n * onLLMCallError: async (ctx) => {\n * errors.push({ type: 'llm', error: ctx.error, recovered: ctx.recovered });\n * },\n * },\n * }\n * ))\n * ```\n *\n * @see {@link https://github.com/zbigniewsobiecki/llmist/blob/main/docs/HOOKS.md#hookpresetserrorlogging | Full documentation}\n */\n static errorLogging(): AgentHooks {\n return {\n observers: {\n onLLMCallError: async (ctx) => {\n console.error(`❌ LLM Error (iteration ${ctx.iteration}):`, ctx.error.message);\n console.error(` Model: ${ctx.options.model}`);\n console.error(` Recovered: ${ctx.recovered}`);\n },\n onGadgetExecutionComplete: async (ctx) => {\n if (ctx.error) {\n console.error(`❌ Gadget Error: ${ctx.gadgetName}`);\n console.error(` Error: ${ctx.error}`);\n console.error(` Parameters:`, JSON.stringify(ctx.parameters, null, 2));\n }\n },\n },\n };\n }\n\n /**\n * Tracks context compaction events.\n *\n * **Output:**\n * - Compaction events with 🗜️ emoji\n * - Strategy name, tokens before/after, and savings\n * - Cumulative statistics\n *\n * **Use cases:**\n * - Monitoring long-running conversations\n * - Understanding when and how compaction occurs\n * - Debugging context management issues\n *\n * **Performance:** Minimal overhead. Simple console output.\n *\n * @returns Hook configuration that can be passed to .withHooks()\n *\n * @example\n * ```typescript\n * await LLMist.createAgent()\n * .withHooks(HookPresets.compactionTracking())\n * .ask(\"Your prompt\");\n * ```\n */\n static compactionTracking(): AgentHooks {\n return {\n observers: {\n onCompaction: async (ctx) => {\n const saved = ctx.event.tokensBefore - ctx.event.tokensAfter;\n const percent = ((saved / ctx.event.tokensBefore) * 100).toFixed(1);\n console.log(\n `🗜️ Compaction (${ctx.event.strategy}): ${ctx.event.tokensBefore} → ${ctx.event.tokensAfter} tokens (saved ${saved}, ${percent}%)`,\n );\n console.log(` Messages: ${ctx.event.messagesBefore} → ${ctx.event.messagesAfter}`);\n if (ctx.stats.totalCompactions > 1) {\n console.log(\n ` Cumulative: ${ctx.stats.totalCompactions} compactions, ${ctx.stats.totalTokensSaved} tokens saved`,\n );\n }\n },\n },\n };\n }\n\n /**\n * Returns empty hook configuration for clean output without any logging.\n *\n * **Output:**\n * - None. Returns {} (empty object).\n *\n * **Use cases:**\n * - Clean test output without console noise\n * - Production environments where logging is handled externally\n * - Baseline for custom hook development\n * - Temporary disable of all hook output\n *\n * **Performance:** Zero overhead. No-op hook configuration.\n *\n * @returns Empty hook configuration\n *\n * @example\n * ```typescript\n * // Clean test output\n * describe('Agent tests', () => {\n * it('should calculate correctly', async () => {\n * const result = await LLMist.createAgent()\n * .withHooks(HookPresets.silent()) // No console output\n * .withGadgets(Calculator)\n * .askAndCollect(\"What is 15 times 23?\");\n *\n * expect(result).toContain(\"345\");\n * });\n * });\n * ```\n *\n * @example\n * ```typescript\n * // Conditional silence based on environment\n * const isTesting = process.env.NODE_ENV === 'test';\n * .withHooks(isTesting ? HookPresets.silent() : HookPresets.monitoring())\n * ```\n *\n * @see {@link https://github.com/zbigniewsobiecki/llmist/blob/main/docs/HOOKS.md#hookpresetssilent | Full documentation}\n */\n static silent(): AgentHooks {\n return {};\n }\n\n /**\n * Combines multiple hook configurations into one.\n *\n * Merge allows you to compose preset and custom hooks for modular monitoring\n * configurations. Understanding merge behavior is crucial for proper composition.\n *\n * **Merge behavior:**\n * - **Observers:** Composed - all handlers run sequentially in order\n * - **Interceptors:** Last one wins - only the last interceptor applies\n * - **Controllers:** Last one wins - only the last controller applies\n *\n * **Why interceptors/controllers don't compose:**\n * - Interceptors have different signatures per method, making composition impractical\n * - Controllers return specific actions that can't be meaningfully combined\n * - Only observers support composition because they're read-only and independent\n *\n * **Use cases:**\n * - Combining multiple presets (logging + timing + tokens)\n * - Adding custom hooks to presets\n * - Building modular, reusable monitoring configurations\n * - Environment-specific hook composition\n *\n * **Performance:** Minimal overhead for merging. Runtime performance depends on merged hooks.\n *\n * @param hookSets - Variable number of hook configurations to merge\n * @returns Single merged hook configuration with composed/overridden handlers\n *\n * @example\n * ```typescript\n * // Combine multiple presets\n * .withHooks(HookPresets.merge(\n * HookPresets.logging(),\n * HookPresets.timing(),\n * HookPresets.tokenTracking()\n * ))\n * // All observers from all three presets will run\n * ```\n *\n * @example\n * ```typescript\n * // Add custom observer to preset (both run)\n * .withHooks(HookPresets.merge(\n * HookPresets.timing(),\n * {\n * observers: {\n * onLLMCallComplete: async (ctx) => {\n * await saveMetrics({ tokens: ctx.usage?.totalTokens });\n * },\n * },\n * }\n * ))\n * ```\n *\n * @example\n * ```typescript\n * // Multiple interceptors (last wins!)\n * .withHooks(HookPresets.merge(\n * {\n * interceptors: {\n * interceptTextChunk: (chunk) => chunk.toUpperCase(), // Ignored\n * },\n * },\n * {\n * interceptors: {\n * interceptTextChunk: (chunk) => chunk.toLowerCase(), // This wins\n * },\n * }\n * ))\n * // Result: text will be lowercase\n * ```\n *\n * @example\n * ```typescript\n * // Modular environment-based configuration\n * const baseHooks = HookPresets.errorLogging();\n * const devHooks = HookPresets.merge(baseHooks, HookPresets.monitoring({ verbose: true }));\n * const prodHooks = HookPresets.merge(baseHooks, HookPresets.tokenTracking());\n *\n * const hooks = process.env.NODE_ENV === 'production' ? prodHooks : devHooks;\n * .withHooks(hooks)\n * ```\n *\n * @see {@link https://github.com/zbigniewsobiecki/llmist/blob/main/docs/HOOKS.md#hookpresetsmergehooksets | Full documentation}\n */\n static merge(...hookSets: AgentHooks[]): AgentHooks {\n const merged: AgentHooks = {\n observers: {},\n interceptors: {},\n controllers: {},\n };\n\n // Compose observers: run all handlers for the same event\n for (const hooks of hookSets) {\n if (hooks.observers) {\n for (const [key, handler] of Object.entries(hooks.observers)) {\n const typedKey = key as keyof typeof hooks.observers;\n if (merged.observers![typedKey]) {\n // Compose: run both existing and new handler\n const existing = merged.observers![typedKey];\n merged.observers![typedKey] = async (ctx: any) => {\n await existing(ctx);\n await handler(ctx);\n };\n } else {\n merged.observers![typedKey] = handler as any;\n }\n }\n }\n\n // Interceptors: last one wins (complex signatures make composition impractical)\n // Each interceptor has different parameters (chunk, message, parameters, etc.)\n // so we can't meaningfully compose them like we do with observers\n if (hooks.interceptors) {\n Object.assign(merged.interceptors!, hooks.interceptors);\n }\n\n // Controllers: last one wins (can't meaningfully compose boolean returns)\n if (hooks.controllers) {\n Object.assign(merged.controllers!, hooks.controllers);\n }\n }\n\n return merged;\n }\n\n /**\n * Composite preset combining logging, timing, tokenTracking, and errorLogging.\n *\n * This is the recommended preset for development and initial production deployments,\n * providing comprehensive observability with a single method call.\n *\n * **Includes:**\n * - All output from `logging()` preset (with optional verbosity)\n * - All output from `timing()` preset (execution times)\n * - All output from `tokenTracking()` preset (token usage)\n * - All output from `errorLogging()` preset (error details)\n *\n * **Output format:**\n * - Event logging: [LLM]/[GADGET] messages\n * - Timing: ⏱️ emoji with milliseconds\n * - Tokens: 📊 emoji with per-call and cumulative counts\n * - Errors: ❌ emoji with full error details\n *\n * **Use cases:**\n * - Full observability during development\n * - Comprehensive monitoring in production\n * - One-liner for complete agent visibility\n * - Troubleshooting and debugging with full context\n *\n * **Performance:** Combined overhead of all four presets, but still minimal in practice.\n *\n * @param options - Monitoring options\n * @param options.verbose - Passed to logging() preset for detailed output. Default: false\n * @returns Merged hook configuration combining all monitoring presets\n *\n * @example\n * ```typescript\n * // Basic monitoring (recommended for development)\n * await LLMist.createAgent()\n * .withHooks(HookPresets.monitoring())\n * .withGadgets(Calculator, Weather)\n * .ask(\"What is 15 times 23, and what's the weather in NYC?\");\n * // Output: All events, timing, tokens, and errors in one place\n * ```\n *\n * @example\n * ```typescript\n * // Verbose monitoring with full details\n * await LLMist.createAgent()\n * .withHooks(HookPresets.monitoring({ verbose: true }))\n * .ask(\"Your prompt\");\n * // Output includes: parameters, results, and complete responses\n * ```\n *\n * @example\n * ```typescript\n * // Environment-based monitoring\n * const isDev = process.env.NODE_ENV === 'development';\n * .withHooks(HookPresets.monitoring({ verbose: isDev }))\n * ```\n *\n * @see {@link https://github.com/zbigniewsobiecki/llmist/blob/main/docs/HOOKS.md#hookpresetsmonitoringoptions | Full documentation}\n */\n static monitoring(options: LoggingOptions = {}): AgentHooks {\n return HookPresets.merge(\n HookPresets.logging(options),\n HookPresets.timing(),\n HookPresets.tokenTracking(),\n HookPresets.errorLogging(),\n );\n }\n}\n","/**\n * Context Compaction System\n *\n * Automatically manages conversation context to prevent context window overflow\n * in long-running agent conversations.\n *\n * Features:\n * - Automatic threshold monitoring (default: 80% of context window)\n * - Multiple strategies: sliding-window, summarization, hybrid (default)\n * - Full visibility via StreamEvents and hooks\n * - Enabled by default with sensible defaults\n *\n * @example\n * ```typescript\n * // Auto-enabled with defaults\n * const agent = await LLMist.createAgent()\n * .withModel('sonnet')\n * .ask('Help me...');\n *\n * // Custom configuration\n * const agent = await LLMist.createAgent()\n * .withModel('gpt-4')\n * .withCompaction({\n * triggerThresholdPercent: 70,\n * preserveRecentTurns: 10,\n * })\n * .ask('...');\n *\n * // Disable compaction\n * const agent = await LLMist.createAgent()\n * .withModel('sonnet')\n * .withoutCompaction()\n * .ask('...');\n * ```\n */\n\n// Configuration\nexport {\n type CompactionConfig,\n type CompactionEvent,\n type CompactionStats,\n DEFAULT_COMPACTION_CONFIG,\n DEFAULT_SUMMARIZATION_PROMPT,\n type ResolvedCompactionConfig,\n resolveCompactionConfig,\n} from \"./config.js\";\n// Manager\nexport { CompactionManager } from \"./manager.js\";\n\n// Strategy implementations\nexport {\n HybridStrategy,\n SlidingWindowStrategy,\n SummarizationStrategy,\n} from \"./strategies/index.js\";\n// Strategy interface and utilities\nexport {\n type CompactionContext,\n type CompactionResult,\n type CompactionStrategy,\n flattenTurns,\n groupIntoTurns,\n type MessageTurn,\n} from \"./strategy.js\";\n","/**\n * Agent module - Composable, single-responsibility architecture for LLM agents.\n * This module provides a cleaner alternative to the monolithic AgentLoop.\n */\n\nexport type { AgentOptions } from \"./agent.js\";\n// Context compaction\nexport {\n type CompactionConfig,\n type CompactionContext,\n type CompactionEvent,\n CompactionManager,\n type CompactionResult,\n type CompactionStats,\n type CompactionStrategy,\n DEFAULT_COMPACTION_CONFIG,\n DEFAULT_SUMMARIZATION_PROMPT,\n HybridStrategy,\n type MessageTurn,\n type ResolvedCompactionConfig,\n SlidingWindowStrategy,\n SummarizationStrategy,\n} from \"./compaction/index.js\";\nexport { ConversationManager } from \"./conversation-manager.js\";\n// Gadget output limiting\nexport type { StoredOutput } from \"./gadget-output-store.js\";\nexport { GadgetOutputStore } from \"./gadget-output-store.js\";\n// LLM Assistance Hints\nexport {\n createHints,\n type HintsConfig,\n type IterationHintOptions,\n iterationProgressHint,\n type ParallelGadgetHintOptions,\n parallelGadgetHint,\n} from \"./hints.js\";\n// New clean hooks system\nexport type {\n AfterGadgetExecutionAction,\n AfterGadgetExecutionControllerContext,\n AfterLLMCallAction,\n AfterLLMCallControllerContext,\n AfterLLMErrorAction,\n AgentHooks,\n BeforeGadgetExecutionAction,\n BeforeLLMCallAction,\n // Interceptor contexts\n ChunkInterceptorContext,\n Controllers,\n // Dependency skip controller\n DependencySkipAction,\n DependencySkipControllerContext,\n GadgetExecutionControllerContext,\n GadgetParameterInterceptorContext,\n GadgetResultInterceptorContext,\n Interceptors,\n // Controller contexts and actions\n LLMCallControllerContext,\n LLMErrorControllerContext,\n MessageInterceptorContext,\n ObserveChunkContext,\n ObserveCompactionContext,\n ObserveGadgetCompleteContext,\n // Gadget skip observer\n ObserveGadgetSkippedContext,\n ObserveGadgetStartContext,\n // Observer contexts\n ObserveLLMCallContext,\n ObserveLLMCompleteContext,\n ObserveLLMErrorContext,\n Observers,\n // Subagent context for distinguishing subagent events in hooks\n SubagentContext,\n} from \"./hooks.js\";\nexport type { IConversationManager } from \"./interfaces.js\";\n// StreamProcessor for advanced use cases\nexport {\n type StreamProcessingResult,\n StreamProcessor,\n type StreamProcessorOptions,\n} from \"./stream-processor.js\";\n","/**\n * LLM Assistance Hints System\n *\n * Provides reusable hook factories that inject helpful context and coaching\n * messages to guide LLM behavior during agentic execution.\n *\n * ## Two Types of Hints\n *\n * 1. **Proactive (beforeLLMCall)**: Inject context before LLM generates response\n * - Example: Iteration progress (\"You're on iteration 3/10\")\n *\n * 2. **Reactive (afterLLMCall)**: Coach based on what LLM did\n * - Example: \"Tip: You can call multiple gadgets in parallel\"\n *\n * ## Usage\n *\n * ```typescript\n * import { createHints, iterationProgressHint, parallelGadgetHint } from \"llmist\";\n *\n * // Option 1: Use individual hints\n * const agent = new AgentBuilder()\n * .withHooks(HookPresets.merge(\n * iterationProgressHint({ timing: \"late\" }),\n * parallelGadgetHint(),\n * ))\n * .build();\n *\n * // Option 2: Use convenience factory\n * const agent = new AgentBuilder()\n * .withHooks(createHints({\n * iterationProgress: { timing: \"late\" },\n * parallelGadgets: true,\n * }))\n * .build();\n * ```\n *\n * @module agent/hints\n */\n\nimport {\n DEFAULT_HINTS,\n type HintContext,\n type HintTemplate,\n resolveHintTemplate,\n} from \"../core/prompt-config.js\";\nimport { HookPresets } from \"./hook-presets.js\";\nimport type { AgentHooks } from \"./hooks.js\";\n\n// ============================================================================\n// CONFIGURATION TYPES\n// ============================================================================\n\n/**\n * Options for iteration progress hint.\n */\nexport interface IterationHintOptions {\n /**\n * When to show the hint.\n * - \"always\": Show on every iteration\n * - \"late\": Show only when >= 50% through iterations\n * - \"urgent\": Show only when >= 80% through iterations\n * @default \"always\"\n */\n timing?: \"always\" | \"late\" | \"urgent\";\n\n /**\n * Whether to include urgency indicators for late iterations.\n * Adds extra text when running low on iterations.\n * @default true\n */\n showUrgency?: boolean;\n\n /**\n * Custom template. Supports placeholders: {iteration}, {maxIterations}, {remaining}\n * Or a function receiving HintContext.\n * @default DEFAULT_HINTS.iterationProgressHint\n */\n template?: HintTemplate;\n}\n\n/**\n * Options for parallel gadget usage hint.\n */\nexport interface ParallelGadgetHintOptions {\n /**\n * Minimum number of gadget calls to consider \"efficient\".\n * If response has fewer calls, hint will suggest parallelization.\n * @default 2\n */\n minGadgetsForEfficiency?: number;\n\n /**\n * Custom message when single gadget detected.\n * @default DEFAULT_HINTS.parallelGadgetsHint\n */\n message?: string;\n\n /**\n * Whether to enable this hint.\n * @default true\n */\n enabled?: boolean;\n}\n\n/**\n * Combined hints configuration for createHints().\n */\nexport interface HintsConfig {\n /**\n * Enable iteration progress hints.\n * Pass `true` for defaults, or options object for customization.\n */\n iterationProgress?: boolean | IterationHintOptions;\n\n /**\n * Enable parallel gadget hints.\n * Pass `true` for defaults, or options object for customization.\n */\n parallelGadgets?: boolean | ParallelGadgetHintOptions;\n\n /**\n * Additional custom hooks to merge.\n */\n custom?: AgentHooks[];\n}\n\n// ============================================================================\n// HINT FACTORIES\n// ============================================================================\n\n/**\n * Creates a proactive hint that informs the LLM about iteration progress.\n *\n * This hint is injected before each LLM call (via beforeLLMCall controller),\n * helping the LLM understand how much \"budget\" remains for completing the task.\n *\n * @param options - Configuration options\n * @returns AgentHooks that can be merged with other hooks\n *\n * @example\n * ```typescript\n * // Basic usage - show on every iteration\n * const hooks = iterationProgressHint();\n *\n * // Show only when running low on iterations\n * const hooks = iterationProgressHint({ timing: \"late\" });\n *\n * // Custom template\n * const hooks = iterationProgressHint({\n * template: \"Turn {iteration} of {maxIterations}. {remaining} turns left.\",\n * });\n * ```\n */\nexport function iterationProgressHint(options?: IterationHintOptions): AgentHooks {\n const { timing = \"always\", showUrgency = true, template } = options ?? {};\n\n return {\n controllers: {\n beforeLLMCall: async (ctx) => {\n const iteration = ctx.iteration + 1; // 1-based for user-friendliness\n const maxIterations = ctx.maxIterations;\n const progress = iteration / maxIterations;\n\n // Check timing condition\n if (timing === \"late\" && progress < 0.5) {\n return { action: \"proceed\" };\n }\n if (timing === \"urgent\" && progress < 0.8) {\n return { action: \"proceed\" };\n }\n\n // Build hint context with all fields populated\n const remaining = maxIterations - iteration;\n const hintContext: HintContext = {\n iteration,\n maxIterations,\n remaining,\n };\n\n // Resolve template\n let hint = resolveHintTemplate(template, DEFAULT_HINTS.iterationProgressHint, hintContext);\n\n // Add urgency indicator if late in iterations\n if (showUrgency && progress >= 0.8) {\n hint += \" ⚠️ Running low on iterations - focus on completing the task.\";\n }\n\n // Inject as system-level context in messages\n const messages = [...ctx.options.messages];\n\n // Find last user message index (compatible with older ES targets)\n let lastUserIndex = -1;\n for (let i = messages.length - 1; i >= 0; i--) {\n if (messages[i].role === \"user\") {\n lastUserIndex = i;\n break;\n }\n }\n\n if (lastUserIndex >= 0) {\n // Insert hint after the last user message\n messages.splice(lastUserIndex + 1, 0, {\n role: \"user\",\n content: `[System Hint] ${hint}`,\n });\n } else {\n // No user messages found - append hint at the end\n messages.push({\n role: \"user\",\n content: `[System Hint] ${hint}`,\n });\n }\n\n return {\n action: \"proceed\",\n modifiedOptions: { messages },\n };\n },\n },\n };\n}\n\n/**\n * Creates a reactive hint that encourages parallel gadget usage.\n *\n * This hint analyzes the LLM's response and, if only a single gadget was called,\n * appends a reminder that multiple gadgets can be used in parallel for efficiency.\n *\n * @param options - Configuration options\n * @returns AgentHooks that can be merged with other hooks\n *\n * @example\n * ```typescript\n * // Basic usage\n * const hooks = parallelGadgetHint();\n *\n * // Custom threshold and message\n * const hooks = parallelGadgetHint({\n * minGadgetsForEfficiency: 3,\n * message: \"Consider calling multiple gadgets at once!\",\n * });\n * ```\n */\nexport function parallelGadgetHint(options?: ParallelGadgetHintOptions): AgentHooks {\n const {\n minGadgetsForEfficiency = 2,\n message = DEFAULT_HINTS.parallelGadgetsHint,\n enabled = true,\n } = options ?? {};\n\n return {\n controllers: {\n afterLLMCall: async (ctx) => {\n if (!enabled) {\n return { action: \"continue\" };\n }\n\n // Only hint if gadgets were called but below efficiency threshold\n if (ctx.gadgetCallCount > 0 && ctx.gadgetCallCount < minGadgetsForEfficiency) {\n return {\n action: \"append_messages\",\n messages: [\n {\n role: \"user\",\n content: `[System Hint] ${message}`,\n },\n ],\n };\n }\n\n return { action: \"continue\" };\n },\n },\n };\n}\n\n// ============================================================================\n// CONVENIENCE FACTORY\n// ============================================================================\n\n/**\n * Creates combined hints from a configuration object.\n *\n * This is a convenience function that creates and merges multiple hints\n * based on a simple configuration object.\n *\n * @param config - Configuration for which hints to enable\n * @returns Merged AgentHooks\n *\n * @example\n * ```typescript\n * const hooks = createHints({\n * iterationProgress: { timing: \"late\" },\n * parallelGadgets: true,\n * });\n *\n * const agent = new AgentBuilder()\n * .withHooks(HookPresets.merge(existingHooks, hooks))\n * .build();\n * ```\n */\nexport function createHints(config: HintsConfig): AgentHooks {\n const hooksToMerge: AgentHooks[] = [];\n\n // Iteration progress hint\n if (config.iterationProgress) {\n const options = typeof config.iterationProgress === \"boolean\" ? {} : config.iterationProgress;\n hooksToMerge.push(iterationProgressHint(options));\n }\n\n // Parallel gadgets hint\n if (config.parallelGadgets) {\n const options = typeof config.parallelGadgets === \"boolean\" ? {} : config.parallelGadgets;\n hooksToMerge.push(parallelGadgetHint(options));\n }\n\n // Custom hooks\n if (config.custom) {\n hooksToMerge.push(...config.custom);\n }\n\n return HookPresets.merge(...hooksToMerge);\n}\n","/**\n * Unified event types for the Execution Tree.\n *\n * All events carry full tree context (nodeId, parentId, depth, path).\n * No special SubagentEvent wrapper needed - subagent events are regular\n * events with depth > 0.\n *\n * @module core/execution-events\n */\n\nimport type { GadgetMediaOutput } from \"../gadgets/types.js\";\nimport type { LLMMessage } from \"./messages.js\";\nimport type { TokenUsage } from \"./options.js\";\n\n// =============================================================================\n// Base Event Properties\n// =============================================================================\n\n/**\n * Base properties shared by all execution events.\n * Every event carries full tree context.\n */\nexport interface BaseExecutionEvent {\n /** Monotonically increasing event ID */\n eventId: number;\n /** Event timestamp */\n timestamp: number;\n /** Node that emitted this event */\n nodeId: string;\n /** Parent node ID (null for root events) */\n parentId: string | null;\n /** Nesting depth (0 = root, 1 = child, etc.) */\n depth: number;\n /** Full path from root to this node */\n path: string[];\n}\n\n// =============================================================================\n// LLM Call Events\n// =============================================================================\n\n/**\n * Emitted when an LLM call starts.\n */\nexport interface LLMCallStartEvent extends BaseExecutionEvent {\n type: \"llm_call_start\";\n /** Iteration number within agent loop (1-indexed) */\n iteration: number;\n /** Model identifier */\n model: string;\n /** Request messages */\n request?: LLMMessage[];\n}\n\n/**\n * Emitted for each streaming chunk from LLM.\n */\nexport interface LLMCallStreamEvent extends BaseExecutionEvent {\n type: \"llm_call_stream\";\n /** Text chunk */\n chunk: string;\n}\n\n/**\n * Emitted when an LLM call completes successfully.\n */\nexport interface LLMCallCompleteEvent extends BaseExecutionEvent {\n type: \"llm_call_complete\";\n /** Complete response text */\n response: string;\n /** Token usage */\n usage?: TokenUsage;\n /** Finish reason from LLM */\n finishReason?: string | null;\n /** Cost in USD */\n cost?: number;\n}\n\n/**\n * Emitted when an LLM call fails.\n */\nexport interface LLMCallErrorEvent extends BaseExecutionEvent {\n type: \"llm_call_error\";\n /** The error that occurred */\n error: Error;\n /** Whether the error was recovered by a controller */\n recovered: boolean;\n}\n\n// =============================================================================\n// Gadget Events\n// =============================================================================\n\n/**\n * Emitted when a gadget call is parsed from LLM output (before execution).\n */\nexport interface GadgetCallEvent extends BaseExecutionEvent {\n type: \"gadget_call\";\n /** Invocation ID */\n invocationId: string;\n /** Gadget name */\n name: string;\n /** Parameters */\n parameters: Record<string, unknown>;\n /** Dependencies (other invocation IDs) */\n dependencies: string[];\n}\n\n/**\n * Emitted when gadget execution starts.\n */\nexport interface GadgetStartEvent extends BaseExecutionEvent {\n type: \"gadget_start\";\n /** Invocation ID */\n invocationId: string;\n /** Gadget name */\n name: string;\n}\n\n/**\n * Emitted when gadget execution completes successfully.\n */\nexport interface GadgetCompleteEvent extends BaseExecutionEvent {\n type: \"gadget_complete\";\n /** Invocation ID */\n invocationId: string;\n /** Gadget name */\n name: string;\n /** Result string */\n result: string;\n /** Execution time in ms */\n executionTimeMs: number;\n /** Cost in USD */\n cost?: number;\n /** Media outputs */\n media?: GadgetMediaOutput[];\n}\n\n/**\n * Emitted when gadget execution fails.\n */\nexport interface GadgetErrorEvent extends BaseExecutionEvent {\n type: \"gadget_error\";\n /** Invocation ID */\n invocationId: string;\n /** Gadget name */\n name: string;\n /** Error message */\n error: string;\n /** Execution time in ms */\n executionTimeMs: number;\n}\n\n/**\n * Emitted when a gadget is skipped.\n */\nexport interface GadgetSkippedEvent extends BaseExecutionEvent {\n type: \"gadget_skipped\";\n /** Invocation ID */\n invocationId: string;\n /** Gadget name */\n name: string;\n /** Reason for skipping */\n reason: \"dependency_failed\" | \"controller_skip\";\n /** Error message (combines reason and failedDependencyError for consistency with GadgetErrorEvent) */\n error: string;\n /** Failed dependency invocation ID (if dependency_failed) */\n failedDependency?: string;\n /** Error message from failed dependency */\n failedDependencyError?: string;\n}\n\n// =============================================================================\n// Text Events\n// =============================================================================\n\n/**\n * Emitted for text output from LLM (pure notification, not a tree node).\n */\nexport interface TextEvent extends BaseExecutionEvent {\n type: \"text\";\n /** Text content */\n content: string;\n}\n\n// =============================================================================\n// Other Events\n// =============================================================================\n\n/**\n * Emitted when context compaction occurs.\n */\nexport interface CompactionEvent extends BaseExecutionEvent {\n type: \"compaction\";\n /** Tokens before compaction */\n tokensBefore: number;\n /** Tokens after compaction */\n tokensAfter: number;\n /** Compaction strategy used */\n strategy: string;\n /** Messages removed */\n messagesRemoved: number;\n}\n\n/**\n * Emitted when human input is required.\n */\nexport interface HumanInputRequiredEvent extends BaseExecutionEvent {\n type: \"human_input_required\";\n /** Question for the user */\n question: string;\n /** Gadget name requesting input */\n gadgetName: string;\n /** Invocation ID */\n invocationId: string;\n}\n\n/**\n * Emitted when the execution stream completes.\n */\nexport interface StreamCompleteEvent extends BaseExecutionEvent {\n type: \"stream_complete\";\n /** Whether any gadgets were executed */\n didExecuteGadgets: boolean;\n /** Whether the agent loop should break */\n shouldBreakLoop: boolean;\n /** Total cost for this iteration */\n iterationCost?: number;\n}\n\n// =============================================================================\n// Union Types\n// =============================================================================\n\n/**\n * All LLM-related events.\n */\nexport type LLMEvent =\n | LLMCallStartEvent\n | LLMCallStreamEvent\n | LLMCallCompleteEvent\n | LLMCallErrorEvent;\n\n/**\n * All gadget-related events.\n */\nexport type GadgetEvent =\n | GadgetCallEvent\n | GadgetStartEvent\n | GadgetCompleteEvent\n | GadgetErrorEvent\n | GadgetSkippedEvent;\n\n/**\n * Union of all execution events.\n */\nexport type ExecutionEvent =\n | LLMCallStartEvent\n | LLMCallStreamEvent\n | LLMCallCompleteEvent\n | LLMCallErrorEvent\n | GadgetCallEvent\n | GadgetStartEvent\n | GadgetCompleteEvent\n | GadgetErrorEvent\n | GadgetSkippedEvent\n | TextEvent\n | CompactionEvent\n | HumanInputRequiredEvent\n | StreamCompleteEvent;\n\n/**\n * Event type discriminator.\n */\nexport type ExecutionEventType = ExecutionEvent[\"type\"] | \"*\";\n\n// =============================================================================\n// Type Guards\n// =============================================================================\n\n/**\n * Check if an event is an LLM event.\n */\nexport function isLLMEvent(event: ExecutionEvent): event is LLMEvent {\n return event.type.startsWith(\"llm_call_\");\n}\n\n/**\n * Check if an event is a gadget event.\n */\nexport function isGadgetEvent(event: ExecutionEvent): event is GadgetEvent {\n return event.type.startsWith(\"gadget_\");\n}\n\n/**\n * Check if an event is from a subagent (nested execution).\n */\nexport function isSubagentEvent(event: ExecutionEvent): boolean {\n return event.depth > 0;\n}\n\n/**\n * Check if an event is from the root agent.\n */\nexport function isRootEvent(event: ExecutionEvent): boolean {\n return event.depth === 0;\n}\n\n// =============================================================================\n// Event Filtering Utilities\n// =============================================================================\n\n/**\n * Filter events by depth.\n */\nexport function filterByDepth(events: ExecutionEvent[], depth: number): ExecutionEvent[] {\n return events.filter((e) => e.depth === depth);\n}\n\n/**\n * Filter events by parent node.\n */\nexport function filterByParent(events: ExecutionEvent[], parentId: string): ExecutionEvent[] {\n return events.filter((e) => e.parentId === parentId);\n}\n\n/**\n * Filter events to only root-level events.\n */\nexport function filterRootEvents(events: ExecutionEvent[]): ExecutionEvent[] {\n return filterByDepth(events, 0);\n}\n\n/**\n * Group events by their parent node.\n */\nexport function groupByParent(events: ExecutionEvent[]): Map<string | null, ExecutionEvent[]> {\n const groups = new Map<string | null, ExecutionEvent[]>();\n\n for (const event of events) {\n const parentId = event.parentId;\n if (!groups.has(parentId)) {\n groups.set(parentId, []);\n }\n groups.get(parentId)?.push(event);\n }\n\n return groups;\n}\n","/**\n * Helper functions for gadget authors to easily return media outputs.\n *\n * These functions provide type-specific conveniences while using the\n * generic GadgetMediaOutput system underneath.\n *\n * @example\n * ```typescript\n * import { resultWithImage } from \"llmist/gadgets\";\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 GadgetExecuteResultWithMedia,\n GadgetMediaOutput,\n MediaKind,\n MediaMetadata,\n} from \"./types.js\";\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 * 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"],"mappings":"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","names":[]}
|