llmist 6.0.0 → 6.2.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.
@@ -1,4 +1,5 @@
1
- import { ZodTypeAny } from 'zod';
1
+ import * as zod from 'zod';
2
+ import { ZodType, ZodTypeAny } from 'zod';
2
3
  import { Logger, ILogObj } from 'tslog';
3
4
 
4
5
  /**
@@ -213,6 +214,943 @@ interface SpeechModelSpec {
213
214
  };
214
215
  }
215
216
 
217
+ interface LLMGenerationOptions {
218
+ model: string;
219
+ messages: LLMMessage[];
220
+ maxTokens?: number;
221
+ temperature?: number;
222
+ topP?: number;
223
+ stopSequences?: string[];
224
+ responseFormat?: "text";
225
+ metadata?: Record<string, unknown>;
226
+ extra?: Record<string, unknown>;
227
+ /**
228
+ * Optional abort signal for cancelling the request mid-flight.
229
+ *
230
+ * When the signal is aborted, the provider will attempt to cancel
231
+ * the underlying HTTP request and the stream will terminate with
232
+ * an abort error. Use `isAbortError()` from `@/core/errors` to
233
+ * detect cancellation in error handling.
234
+ *
235
+ * @example
236
+ * ```typescript
237
+ * const controller = new AbortController();
238
+ *
239
+ * const stream = client.stream({
240
+ * model: "claude-3-5-sonnet-20241022",
241
+ * messages: [{ role: "user", content: "Tell me a long story" }],
242
+ * signal: controller.signal,
243
+ * });
244
+ *
245
+ * // Cancel after 5 seconds
246
+ * setTimeout(() => controller.abort(), 5000);
247
+ *
248
+ * try {
249
+ * for await (const chunk of stream) {
250
+ * process.stdout.write(chunk.text);
251
+ * }
252
+ * } catch (error) {
253
+ * if (isAbortError(error)) {
254
+ * console.log("\nRequest was cancelled");
255
+ * } else {
256
+ * throw error;
257
+ * }
258
+ * }
259
+ * ```
260
+ */
261
+ signal?: AbortSignal;
262
+ }
263
+ interface TokenUsage {
264
+ inputTokens: number;
265
+ outputTokens: number;
266
+ totalTokens: number;
267
+ /** Number of input tokens served from cache (subset of inputTokens) */
268
+ cachedInputTokens?: number;
269
+ /** Number of input tokens written to cache (subset of inputTokens, Anthropic only) */
270
+ cacheCreationInputTokens?: number;
271
+ }
272
+ interface LLMStreamChunk {
273
+ text: string;
274
+ /**
275
+ * Indicates that the provider has finished producing output and includes the reason if available.
276
+ */
277
+ finishReason?: string | null;
278
+ /**
279
+ * Token usage information, typically available in the final chunk when the stream completes.
280
+ */
281
+ usage?: TokenUsage;
282
+ /**
283
+ * Provider specific payload emitted at the same time as the text chunk. This is useful for debugging and tests.
284
+ */
285
+ rawEvent?: unknown;
286
+ }
287
+ interface LLMStream extends AsyncIterable<LLMStreamChunk> {
288
+ }
289
+ type ProviderIdentifier = string;
290
+ interface ModelDescriptor {
291
+ provider: string;
292
+ name: string;
293
+ }
294
+ declare class ModelIdentifierParser {
295
+ private readonly defaultProvider;
296
+ constructor(defaultProvider?: string);
297
+ parse(identifier: string): ModelDescriptor;
298
+ }
299
+
300
+ /**
301
+ * Unified event types for the Execution Tree.
302
+ *
303
+ * All events carry full tree context (nodeId, parentId, depth, path).
304
+ * No special SubagentEvent wrapper needed - subagent events are regular
305
+ * events with depth > 0.
306
+ *
307
+ * @module core/execution-events
308
+ */
309
+
310
+ /**
311
+ * Base properties shared by all execution events.
312
+ * Every event carries full tree context.
313
+ */
314
+ interface BaseExecutionEvent {
315
+ /** Monotonically increasing event ID */
316
+ eventId: number;
317
+ /** Event timestamp */
318
+ timestamp: number;
319
+ /** Node that emitted this event */
320
+ nodeId: string;
321
+ /** Parent node ID (null for root events) */
322
+ parentId: string | null;
323
+ /** Nesting depth (0 = root, 1 = child, etc.) */
324
+ depth: number;
325
+ /** Full path from root to this node */
326
+ path: string[];
327
+ }
328
+ /**
329
+ * Emitted when an LLM call starts.
330
+ */
331
+ interface LLMCallStartEvent extends BaseExecutionEvent {
332
+ type: "llm_call_start";
333
+ /** Iteration number within agent loop (1-indexed) */
334
+ iteration: number;
335
+ /** Model identifier */
336
+ model: string;
337
+ /** Request messages */
338
+ request?: LLMMessage[];
339
+ }
340
+ /**
341
+ * Emitted for each streaming chunk from LLM.
342
+ */
343
+ interface LLMCallStreamEvent extends BaseExecutionEvent {
344
+ type: "llm_call_stream";
345
+ /** Text chunk */
346
+ chunk: string;
347
+ }
348
+ /**
349
+ * Emitted when an LLM call completes successfully.
350
+ */
351
+ interface LLMCallCompleteEvent extends BaseExecutionEvent {
352
+ type: "llm_call_complete";
353
+ /** Complete response text */
354
+ response: string;
355
+ /** Token usage */
356
+ usage?: TokenUsage;
357
+ /** Finish reason from LLM */
358
+ finishReason?: string | null;
359
+ /** Cost in USD */
360
+ cost?: number;
361
+ }
362
+ /**
363
+ * Emitted when an LLM call fails.
364
+ */
365
+ interface LLMCallErrorEvent extends BaseExecutionEvent {
366
+ type: "llm_call_error";
367
+ /** The error that occurred */
368
+ error: Error;
369
+ /** Whether the error was recovered by a controller */
370
+ recovered: boolean;
371
+ }
372
+ /**
373
+ * Emitted when a gadget call is parsed from LLM output (before execution).
374
+ */
375
+ interface GadgetCallEvent extends BaseExecutionEvent {
376
+ type: "gadget_call";
377
+ /** Invocation ID */
378
+ invocationId: string;
379
+ /** Gadget name */
380
+ name: string;
381
+ /** Parameters */
382
+ parameters: Record<string, unknown>;
383
+ /** Dependencies (other invocation IDs) */
384
+ dependencies: string[];
385
+ }
386
+ /**
387
+ * Emitted when gadget execution starts.
388
+ */
389
+ interface GadgetStartEvent extends BaseExecutionEvent {
390
+ type: "gadget_start";
391
+ /** Invocation ID */
392
+ invocationId: string;
393
+ /** Gadget name */
394
+ name: string;
395
+ }
396
+ /**
397
+ * Emitted when gadget execution completes successfully.
398
+ */
399
+ interface GadgetCompleteEvent extends BaseExecutionEvent {
400
+ type: "gadget_complete";
401
+ /** Invocation ID */
402
+ invocationId: string;
403
+ /** Gadget name */
404
+ name: string;
405
+ /** Result string */
406
+ result: string;
407
+ /** Execution time in ms */
408
+ executionTimeMs: number;
409
+ /** Cost in USD */
410
+ cost?: number;
411
+ /** Media outputs */
412
+ media?: GadgetMediaOutput[];
413
+ }
414
+ /**
415
+ * Emitted when gadget execution fails.
416
+ */
417
+ interface GadgetErrorEvent extends BaseExecutionEvent {
418
+ type: "gadget_error";
419
+ /** Invocation ID */
420
+ invocationId: string;
421
+ /** Gadget name */
422
+ name: string;
423
+ /** Error message */
424
+ error: string;
425
+ /** Execution time in ms */
426
+ executionTimeMs: number;
427
+ }
428
+ /**
429
+ * Emitted when a gadget is skipped.
430
+ */
431
+ interface GadgetSkippedEvent$1 extends BaseExecutionEvent {
432
+ type: "gadget_skipped";
433
+ /** Invocation ID */
434
+ invocationId: string;
435
+ /** Gadget name */
436
+ name: string;
437
+ /** Reason for skipping */
438
+ reason: "dependency_failed" | "controller_skip";
439
+ /** Error message (combines reason and failedDependencyError for consistency with GadgetErrorEvent) */
440
+ error: string;
441
+ /** Failed dependency invocation ID (if dependency_failed) */
442
+ failedDependency?: string;
443
+ /** Error message from failed dependency */
444
+ failedDependencyError?: string;
445
+ }
446
+ /**
447
+ * Emitted for text output from LLM (pure notification, not a tree node).
448
+ */
449
+ interface TextEvent extends BaseExecutionEvent {
450
+ type: "text";
451
+ /** Text content */
452
+ content: string;
453
+ }
454
+ /**
455
+ * Emitted when context compaction occurs.
456
+ */
457
+ interface CompactionEvent$1 extends BaseExecutionEvent {
458
+ type: "compaction";
459
+ /** Tokens before compaction */
460
+ tokensBefore: number;
461
+ /** Tokens after compaction */
462
+ tokensAfter: number;
463
+ /** Compaction strategy used */
464
+ strategy: string;
465
+ /** Messages removed */
466
+ messagesRemoved: number;
467
+ }
468
+ /**
469
+ * Emitted when human input is required.
470
+ */
471
+ interface HumanInputRequiredEvent extends BaseExecutionEvent {
472
+ type: "human_input_required";
473
+ /** Question for the user */
474
+ question: string;
475
+ /** Gadget name requesting input */
476
+ gadgetName: string;
477
+ /** Invocation ID */
478
+ invocationId: string;
479
+ }
480
+ /**
481
+ * Emitted when the execution stream completes.
482
+ */
483
+ interface StreamCompleteEvent extends BaseExecutionEvent {
484
+ type: "stream_complete";
485
+ /** Whether any gadgets were executed */
486
+ didExecuteGadgets: boolean;
487
+ /** Whether the agent loop should break */
488
+ shouldBreakLoop: boolean;
489
+ /** Total cost for this iteration */
490
+ iterationCost?: number;
491
+ }
492
+ /**
493
+ * All LLM-related events.
494
+ */
495
+ type LLMEvent = LLMCallStartEvent | LLMCallStreamEvent | LLMCallCompleteEvent | LLMCallErrorEvent;
496
+ /**
497
+ * All gadget-related events.
498
+ */
499
+ type GadgetEvent = GadgetCallEvent | GadgetStartEvent | GadgetCompleteEvent | GadgetErrorEvent | GadgetSkippedEvent$1;
500
+ /**
501
+ * Union of all execution events.
502
+ */
503
+ type ExecutionEvent = LLMCallStartEvent | LLMCallStreamEvent | LLMCallCompleteEvent | LLMCallErrorEvent | GadgetCallEvent | GadgetStartEvent | GadgetCompleteEvent | GadgetErrorEvent | GadgetSkippedEvent$1 | TextEvent | CompactionEvent$1 | HumanInputRequiredEvent | StreamCompleteEvent;
504
+ /**
505
+ * Event type discriminator.
506
+ */
507
+ type ExecutionEventType = ExecutionEvent["type"] | "*";
508
+ /**
509
+ * Check if an event is an LLM event.
510
+ */
511
+ declare function isLLMEvent(event: ExecutionEvent): event is LLMEvent;
512
+ /**
513
+ * Check if an event is a gadget event.
514
+ */
515
+ declare function isGadgetEvent(event: ExecutionEvent): event is GadgetEvent;
516
+ /**
517
+ * Check if an event is from a subagent (nested execution).
518
+ */
519
+ declare function isSubagentEvent(event: ExecutionEvent): boolean;
520
+ /**
521
+ * Check if an event is from the root agent.
522
+ */
523
+ declare function isRootEvent(event: ExecutionEvent): boolean;
524
+ /**
525
+ * Filter events by depth.
526
+ */
527
+ declare function filterByDepth(events: ExecutionEvent[], depth: number): ExecutionEvent[];
528
+ /**
529
+ * Filter events by parent node.
530
+ */
531
+ declare function filterByParent(events: ExecutionEvent[], parentId: string): ExecutionEvent[];
532
+ /**
533
+ * Filter events to only root-level events.
534
+ */
535
+ declare function filterRootEvents(events: ExecutionEvent[]): ExecutionEvent[];
536
+ /**
537
+ * Group events by their parent node.
538
+ */
539
+ declare function groupByParent(events: ExecutionEvent[]): Map<string | null, ExecutionEvent[]>;
540
+
541
+ /**
542
+ * First-class Execution Tree model for nested subagent support.
543
+ *
544
+ * The ExecutionTree is THE single source of truth for execution state.
545
+ * All nodes (including nested subagent nodes) live in one tree.
546
+ * Events are projections of tree changes.
547
+ *
548
+ * @module core/execution-tree
549
+ */
550
+
551
+ /**
552
+ * Unique identifier for any execution node.
553
+ * Format examples: "llm_1", "gadget_abc123", "llm_1_2" (nested)
554
+ */
555
+ type NodeId = string;
556
+ /**
557
+ * Node type discriminator.
558
+ */
559
+ type ExecutionNodeType = "llm_call" | "gadget";
560
+ /**
561
+ * Base properties shared by all execution nodes.
562
+ */
563
+ interface BaseExecutionNode {
564
+ /** Unique identifier for this node */
565
+ id: NodeId;
566
+ /** Node type discriminator */
567
+ type: ExecutionNodeType;
568
+ /** Parent node ID (null for root nodes) */
569
+ parentId: NodeId | null;
570
+ /** Nesting depth (0 = root, 1 = child of gadget, etc.) */
571
+ depth: number;
572
+ /** Path from root to this node: ["llm_1", "gadget_abc", "llm_1_1"] */
573
+ path: NodeId[];
574
+ /** Creation timestamp */
575
+ createdAt: number;
576
+ /** Completion timestamp (null if in progress) */
577
+ completedAt: number | null;
578
+ }
579
+ /**
580
+ * LLM call execution node.
581
+ */
582
+ interface LLMCallNode extends BaseExecutionNode {
583
+ type: "llm_call";
584
+ /** Iteration number within the agent loop (1-indexed for display) */
585
+ iteration: number;
586
+ /** Model identifier */
587
+ model: string;
588
+ /** Request messages (set when call starts) */
589
+ request?: LLMMessage[];
590
+ /** Accumulated response text */
591
+ response: string;
592
+ /** Token usage (set on completion) */
593
+ usage?: TokenUsage;
594
+ /** Finish reason from LLM */
595
+ finishReason?: string | null;
596
+ /** Cost in USD */
597
+ cost?: number;
598
+ /** Child node IDs (gadgets spawned by this LLM call) */
599
+ children: NodeId[];
600
+ }
601
+ /**
602
+ * Gadget execution state.
603
+ */
604
+ type GadgetState = "pending" | "running" | "completed" | "failed" | "skipped";
605
+ /**
606
+ * Gadget execution node.
607
+ */
608
+ interface GadgetNode extends BaseExecutionNode {
609
+ type: "gadget";
610
+ /** Invocation ID (LLM-generated or auto) */
611
+ invocationId: string;
612
+ /** Gadget name */
613
+ name: string;
614
+ /** Parameters passed to the gadget */
615
+ parameters: Record<string, unknown>;
616
+ /** Dependencies (other invocation IDs this gadget waits for) */
617
+ dependencies: string[];
618
+ /** Execution state */
619
+ state: GadgetState;
620
+ /** Result string (if completed successfully) */
621
+ result?: string;
622
+ /** Error message (if failed or skipped) */
623
+ error?: string;
624
+ /** Failed dependency invocation ID (if skipped due to dependency) */
625
+ failedDependency?: string;
626
+ /** Execution time in milliseconds */
627
+ executionTimeMs?: number;
628
+ /** Cost in USD */
629
+ cost?: number;
630
+ /** Media outputs from this gadget */
631
+ media?: GadgetMediaOutput[];
632
+ /** Child node IDs (nested LLM calls for subagent gadgets) */
633
+ children: NodeId[];
634
+ /** Whether this gadget is a subagent (has nested LLM calls) */
635
+ isSubagent: boolean;
636
+ }
637
+ /**
638
+ * Union of all execution node types.
639
+ */
640
+ type ExecutionNode = LLMCallNode | GadgetNode;
641
+ interface AddLLMCallParams {
642
+ /** Iteration number (1-indexed) */
643
+ iteration: number;
644
+ /** Model identifier */
645
+ model: string;
646
+ /** Request messages */
647
+ request?: LLMMessage[];
648
+ /** Parent node ID (for subagent LLM calls) */
649
+ parentId?: NodeId | null;
650
+ }
651
+ interface AddGadgetParams {
652
+ /** Invocation ID */
653
+ invocationId: string;
654
+ /** Gadget name */
655
+ name: string;
656
+ /** Parameters */
657
+ parameters: Record<string, unknown>;
658
+ /** Dependencies */
659
+ dependencies?: string[];
660
+ /** Parent LLM call node ID */
661
+ parentId?: NodeId | null;
662
+ }
663
+ interface CompleteLLMCallParams {
664
+ /** Accumulated response text */
665
+ response?: string;
666
+ /** Token usage */
667
+ usage?: TokenUsage;
668
+ /** Finish reason */
669
+ finishReason?: string | null;
670
+ /** Cost in USD */
671
+ cost?: number;
672
+ }
673
+ interface CompleteGadgetParams {
674
+ /** Result string */
675
+ result?: string;
676
+ /** Error message */
677
+ error?: string;
678
+ /** Failed dependency (for skipped gadgets) */
679
+ failedDependency?: string;
680
+ /** Execution time in ms */
681
+ executionTimeMs?: number;
682
+ /** Cost in USD */
683
+ cost?: number;
684
+ /** Media outputs */
685
+ media?: GadgetMediaOutput[];
686
+ }
687
+
688
+ /** Event listener function type */
689
+ type EventListener = (event: ExecutionEvent) => void;
690
+ /**
691
+ * The Execution Tree - single source of truth for all execution state.
692
+ *
693
+ * Features:
694
+ * - Stores all nodes (LLM calls, gadgets) in a hierarchical structure
695
+ * - Emits events on mutations
696
+ * - Provides query methods for aggregation (costs, media, descendants)
697
+ * - Supports single shared tree model for nested subagents
698
+ *
699
+ * @example
700
+ * ```typescript
701
+ * const tree = new ExecutionTree();
702
+ *
703
+ * // Add root LLM call
704
+ * const llmNode = tree.addLLMCall({ iteration: 1, model: "sonnet" });
705
+ *
706
+ * // Add gadget under the LLM call
707
+ * const gadgetNode = tree.addGadget({
708
+ * invocationId: "gc_1",
709
+ * name: "ReadFile",
710
+ * parameters: { path: "/foo.txt" },
711
+ * parentId: llmNode.id,
712
+ * });
713
+ *
714
+ * // Complete the gadget
715
+ * tree.completeGadget(gadgetNode.id, { result: "file contents", executionTimeMs: 50 });
716
+ *
717
+ * // Query total cost
718
+ * console.log(tree.getTotalCost());
719
+ * ```
720
+ */
721
+ declare class ExecutionTree {
722
+ private nodes;
723
+ private rootIds;
724
+ private eventListeners;
725
+ private eventIdCounter;
726
+ private invocationIdToNodeId;
727
+ private eventQueue;
728
+ private eventWaiters;
729
+ private isCompleted;
730
+ /**
731
+ * Base depth for all nodes in this tree.
732
+ * Used when this tree is a subagent's view into a parent tree.
733
+ */
734
+ readonly baseDepth: number;
735
+ /**
736
+ * Parent node ID for subagent trees.
737
+ * All root nodes in this tree will have this as their parentId.
738
+ */
739
+ readonly parentNodeId: NodeId | null;
740
+ constructor(options?: {
741
+ baseDepth?: number;
742
+ parentNodeId?: NodeId | null;
743
+ });
744
+ private generateLLMCallId;
745
+ private gadgetIdCounter;
746
+ private generateGadgetId;
747
+ private emit;
748
+ private createBaseEventProps;
749
+ /**
750
+ * Add a new LLM call node to the tree.
751
+ */
752
+ addLLMCall(params: AddLLMCallParams): LLMCallNode;
753
+ /**
754
+ * Add text to an LLM call's response (for streaming).
755
+ */
756
+ appendLLMResponse(nodeId: NodeId, chunk: string): void;
757
+ /**
758
+ * Complete an LLM call node.
759
+ */
760
+ completeLLMCall(nodeId: NodeId, params: CompleteLLMCallParams): void;
761
+ /**
762
+ * Mark an LLM call as failed.
763
+ */
764
+ failLLMCall(nodeId: NodeId, error: Error, recovered: boolean): void;
765
+ /**
766
+ * Add a new gadget node to the tree.
767
+ */
768
+ addGadget(params: AddGadgetParams): GadgetNode;
769
+ /**
770
+ * Mark a gadget as started (running).
771
+ */
772
+ startGadget(nodeId: NodeId): void;
773
+ /**
774
+ * Complete a gadget node successfully.
775
+ */
776
+ completeGadget(nodeId: NodeId, params: CompleteGadgetParams): void;
777
+ /**
778
+ * Mark a gadget as skipped due to dependency failure.
779
+ */
780
+ skipGadget(nodeId: NodeId, failedDependency: string, failedDependencyError: string, reason: "dependency_failed" | "controller_skip"): void;
781
+ /**
782
+ * Emit a text event (notification only, not stored in tree).
783
+ */
784
+ emitText(content: string, llmCallNodeId: NodeId): void;
785
+ /**
786
+ * Get a node by ID.
787
+ */
788
+ getNode(id: NodeId): ExecutionNode | undefined;
789
+ /**
790
+ * Get a gadget node by invocation ID.
791
+ */
792
+ getNodeByInvocationId(invocationId: string): GadgetNode | undefined;
793
+ /**
794
+ * Get all root nodes (depth 0 for this tree).
795
+ */
796
+ getRoots(): ExecutionNode[];
797
+ /**
798
+ * Get children of a node.
799
+ */
800
+ getChildren(id: NodeId): ExecutionNode[];
801
+ /**
802
+ * Get ancestors of a node (from root to parent).
803
+ */
804
+ getAncestors(id: NodeId): ExecutionNode[];
805
+ /**
806
+ * Get all descendants of a node.
807
+ */
808
+ getDescendants(id: NodeId, type?: ExecutionNodeType): ExecutionNode[];
809
+ /**
810
+ * Get the current (most recent incomplete) LLM call node.
811
+ */
812
+ getCurrentLLMCallId(): NodeId | undefined;
813
+ /**
814
+ * Get total cost for entire tree.
815
+ */
816
+ getTotalCost(): number;
817
+ /**
818
+ * Get total cost for a subtree (node and all descendants).
819
+ */
820
+ getSubtreeCost(nodeId: NodeId): number;
821
+ /**
822
+ * Get token usage for entire tree.
823
+ */
824
+ getTotalTokens(): {
825
+ input: number;
826
+ output: number;
827
+ cached: number;
828
+ };
829
+ /**
830
+ * Get token usage for a subtree.
831
+ */
832
+ getSubtreeTokens(nodeId: NodeId): {
833
+ input: number;
834
+ output: number;
835
+ cached: number;
836
+ };
837
+ /**
838
+ * Collect all media from a subtree.
839
+ */
840
+ getSubtreeMedia(nodeId: NodeId): GadgetMediaOutput[];
841
+ /**
842
+ * Check if a subtree is complete (all nodes finished).
843
+ */
844
+ isSubtreeComplete(nodeId: NodeId): boolean;
845
+ /**
846
+ * Get node counts.
847
+ */
848
+ getNodeCount(): {
849
+ llmCalls: number;
850
+ gadgets: number;
851
+ };
852
+ /**
853
+ * Subscribe to events of a specific type.
854
+ * Returns unsubscribe function.
855
+ *
856
+ * @param type - Event type to subscribe to (use "*" for all events)
857
+ * @param listener - Callback function that receives matching events
858
+ * @returns Unsubscribe function
859
+ *
860
+ * @example
861
+ * ```typescript
862
+ * const unsubscribe = tree.on("gadget_complete", (event) => {
863
+ * if (event.type === "gadget_complete") {
864
+ * console.log(`Gadget ${event.name} completed`);
865
+ * }
866
+ * });
867
+ * ```
868
+ */
869
+ on(type: ExecutionEventType, listener: EventListener): () => void;
870
+ /**
871
+ * Subscribe to all events.
872
+ */
873
+ onAll(listener: EventListener): () => void;
874
+ /**
875
+ * Get async iterable of all events.
876
+ * Events are yielded as they occur.
877
+ */
878
+ events(): AsyncGenerator<ExecutionEvent>;
879
+ /**
880
+ * Mark the tree as complete (no more events will be emitted).
881
+ */
882
+ complete(): void;
883
+ /**
884
+ * Check if the tree is complete.
885
+ */
886
+ isComplete(): boolean;
887
+ }
888
+
889
+ /**
890
+ * Function-based gadget creation helper.
891
+ *
892
+ * For simple gadgets, use createGadget() instead of defining a class.
893
+ * Parameters are automatically typed from the Zod schema.
894
+ *
895
+ * @example
896
+ * ```typescript
897
+ * const calculator = createGadget({
898
+ * description: "Performs arithmetic operations",
899
+ * schema: z.object({
900
+ * operation: z.enum(["add", "subtract"]),
901
+ * a: z.number(),
902
+ * b: z.number(),
903
+ * }),
904
+ * execute: ({ operation, a, b }) => {
905
+ * // Automatically typed!
906
+ * return operation === "add" ? String(a + b) : String(a - b);
907
+ * },
908
+ * });
909
+ * ```
910
+ */
911
+
912
+ /**
913
+ * Infer the TypeScript type from a Zod schema.
914
+ */
915
+ type InferSchema$1<T> = T extends ZodType<infer U> ? U : never;
916
+ /**
917
+ * Configuration for creating a function-based gadget.
918
+ */
919
+ interface CreateGadgetConfig<TSchema extends ZodType> {
920
+ /** Optional custom name (defaults to "FunctionGadget") */
921
+ name?: string;
922
+ /** Human-readable description of what the gadget does */
923
+ description: string;
924
+ /** Zod schema for parameter validation */
925
+ schema: TSchema;
926
+ /**
927
+ * Execution function with typed parameters.
928
+ * Can return string or { result, cost? }.
929
+ * Optionally receives ExecutionContext for callback-based cost reporting.
930
+ */
931
+ execute: (params: InferSchema$1<TSchema>, ctx?: ExecutionContext) => GadgetExecuteReturn | Promise<GadgetExecuteReturn>;
932
+ /** Optional timeout in milliseconds */
933
+ timeoutMs?: number;
934
+ /** Optional usage examples to help LLMs understand proper invocation */
935
+ examples?: GadgetExample<InferSchema$1<TSchema>>[];
936
+ }
937
+ /**
938
+ * Creates a gadget from a function (simpler than class-based approach).
939
+ *
940
+ * This is perfect for simple gadgets where you don't need the full
941
+ * power of a class. Parameters are automatically typed from the schema.
942
+ *
943
+ * @param config - Configuration with execute function and schema
944
+ * @returns Gadget instance ready to be registered
945
+ *
946
+ * @example
947
+ * ```typescript
948
+ * import { z } from 'zod';
949
+ * import { createGadget } from 'llmist';
950
+ *
951
+ * // Simple calculator gadget
952
+ * const calculator = createGadget({
953
+ * description: "Performs arithmetic operations",
954
+ * schema: z.object({
955
+ * operation: z.enum(["add", "subtract", "multiply", "divide"]),
956
+ * a: z.number().describe("First number"),
957
+ * b: z.number().describe("Second number"),
958
+ * }),
959
+ * execute: ({ operation, a, b }) => {
960
+ * // Parameters are automatically typed!
961
+ * switch (operation) {
962
+ * case "add": return String(a + b);
963
+ * case "subtract": return String(a - b);
964
+ * case "multiply": return String(a * b);
965
+ * case "divide": return String(a / b);
966
+ * }
967
+ * },
968
+ * });
969
+ * ```
970
+ *
971
+ * @example
972
+ * ```typescript
973
+ * // Async gadget with custom name and timeout
974
+ * const weather = createGadget({
975
+ * name: "weather",
976
+ * description: "Fetches current weather for a city",
977
+ * schema: z.object({
978
+ * city: z.string().min(1).describe("City name"),
979
+ * }),
980
+ * timeoutMs: 10000,
981
+ * execute: async ({ city }) => {
982
+ * const response = await fetch(`https://api.weather.com/${city}`);
983
+ * const data = await response.json();
984
+ * return `Weather in ${city}: ${data.description}, ${data.temp}°C`;
985
+ * },
986
+ * });
987
+ * ```
988
+ *
989
+ * @example
990
+ * ```typescript
991
+ * // Use with agent
992
+ * const agent = LLMist.createAgent()
993
+ * .withGadgets(calculator, weather)
994
+ * .ask("What's the weather in Paris and what's 10 + 5?");
995
+ * ```
996
+ */
997
+ declare function createGadget<TSchema extends ZodType>(config: CreateGadgetConfig<TSchema>): AbstractGadget;
998
+
999
+ /**
1000
+ * Type-safe gadget factory with automatic parameter inference.
1001
+ *
1002
+ * Gadget eliminates the need for manual type assertions
1003
+ * by automatically inferring parameter types from the Zod schema.
1004
+ *
1005
+ * @example
1006
+ * ```typescript
1007
+ * class Calculator extends Gadget({
1008
+ * description: "Performs arithmetic operations",
1009
+ * schema: z.object({
1010
+ * operation: z.enum(["add", "subtract"]),
1011
+ * a: z.number(),
1012
+ * b: z.number(),
1013
+ * }),
1014
+ * }) {
1015
+ * // ✨ params is automatically typed!
1016
+ * execute(params: this['params']): string {
1017
+ * const { operation, a, b } = params; // All typed!
1018
+ * return operation === "add" ? String(a + b) : String(a - b);
1019
+ * }
1020
+ * }
1021
+ * ```
1022
+ */
1023
+
1024
+ /**
1025
+ * Infer the TypeScript type from a Zod schema.
1026
+ */
1027
+ type InferSchema<T> = T extends ZodType<infer U> ? U : never;
1028
+ /**
1029
+ * Configuration for creating a typed gadget.
1030
+ */
1031
+ interface GadgetConfig<TSchema extends ZodType> {
1032
+ /** Human-readable description of what the gadget does */
1033
+ description: string;
1034
+ /** Zod schema for parameter validation */
1035
+ schema: TSchema;
1036
+ /** Optional custom name (defaults to class name) */
1037
+ name?: string;
1038
+ /** Optional timeout in milliseconds */
1039
+ timeoutMs?: number;
1040
+ /** Optional usage examples to help LLMs understand proper invocation */
1041
+ examples?: GadgetExample<InferSchema<TSchema>>[];
1042
+ }
1043
+ /**
1044
+ * Factory function to create a typed gadget base class.
1045
+ *
1046
+ * The returned class automatically infers parameter types from the Zod schema,
1047
+ * eliminating the need for manual type assertions in the execute method.
1048
+ *
1049
+ * @param config - Configuration with description and schema
1050
+ * @returns Base class to extend with typed execute method
1051
+ *
1052
+ * @example
1053
+ * ```typescript
1054
+ * import { z } from 'zod';
1055
+ * import { Gadget } from 'llmist';
1056
+ *
1057
+ * class Calculator extends Gadget({
1058
+ * description: "Performs arithmetic operations",
1059
+ * schema: z.object({
1060
+ * operation: z.enum(["add", "subtract", "multiply", "divide"]),
1061
+ * a: z.number().describe("First number"),
1062
+ * b: z.number().describe("Second number"),
1063
+ * }),
1064
+ * }) {
1065
+ * execute(params: this['params']): string {
1066
+ * // params is automatically typed as:
1067
+ * // { operation: "add" | "subtract" | "multiply" | "divide"; a: number; b: number }
1068
+ * const { operation, a, b } = params;
1069
+ *
1070
+ * switch (operation) {
1071
+ * case "add": return String(a + b);
1072
+ * case "subtract": return String(a - b);
1073
+ * case "multiply": return String(a * b);
1074
+ * case "divide": return String(a / b);
1075
+ * }
1076
+ * }
1077
+ * }
1078
+ * ```
1079
+ *
1080
+ * @example
1081
+ * ```typescript
1082
+ * // With async execution
1083
+ * class WeatherGadget extends Gadget({
1084
+ * description: "Fetches weather for a city",
1085
+ * schema: z.object({
1086
+ * city: z.string().min(1).describe("City name"),
1087
+ * }),
1088
+ * timeoutMs: 10000,
1089
+ * }) {
1090
+ * async execute(params: this['params']): Promise<string> {
1091
+ * const { city } = params; // Automatically typed as { city: string }
1092
+ * const weather = await fetchWeather(city);
1093
+ * return `Weather in ${city}: ${weather}`;
1094
+ * }
1095
+ * }
1096
+ * ```
1097
+ */
1098
+ declare function Gadget<TSchema extends ZodType>(config: GadgetConfig<TSchema>): {
1099
+ new (): {
1100
+ description: string;
1101
+ parameterSchema: TSchema;
1102
+ name: string | undefined;
1103
+ timeoutMs: number | undefined;
1104
+ examples: GadgetExample<InferSchema<TSchema>>[] | undefined;
1105
+ /**
1106
+ * Type helper property for accessing inferred parameter type.
1107
+ * This is used in the execute method signature: `execute(params: this['params'])`
1108
+ *
1109
+ * Note: This is just for type inference - the actual params in execute()
1110
+ * will be Record<string, unknown> which you can safely cast to this['params']
1111
+ */
1112
+ readonly params: InferSchema<TSchema>;
1113
+ /**
1114
+ * Execute the gadget. Subclasses should cast params to this['params'].
1115
+ *
1116
+ * @param params - Validated parameters from the LLM
1117
+ * @param ctx - Optional execution context for cost reporting and LLM access
1118
+ * @returns Result as a string, or an object with result and optional cost
1119
+ *
1120
+ * @example
1121
+ * ```typescript
1122
+ * // Simple string return (free gadget)
1123
+ * execute(params: this['params']) {
1124
+ * return String(params.a + params.b);
1125
+ * }
1126
+ *
1127
+ * // Using context for callback-based cost reporting
1128
+ * execute(params: this['params'], ctx) {
1129
+ * ctx.reportCost(0.001);
1130
+ * return "result";
1131
+ * }
1132
+ *
1133
+ * // Using wrapped LLMist for automatic cost tracking
1134
+ * async execute(params: this['params'], ctx) {
1135
+ * return ctx.llmist.complete('Summarize: ' + params.text);
1136
+ * }
1137
+ * ```
1138
+ */
1139
+ execute(params: Record<string, unknown>, ctx?: ExecutionContext): GadgetExecuteReturn | Promise<GadgetExecuteReturn>;
1140
+ throwIfAborted(ctx?: ExecutionContext): void;
1141
+ onAbort(ctx: ExecutionContext | undefined, cleanup: () => void | Promise<void>): void;
1142
+ createLinkedAbortController(ctx?: ExecutionContext): AbortController;
1143
+ get instruction(): string;
1144
+ getInstruction(optionsOrArgPrefix?: string | {
1145
+ argPrefix?: string;
1146
+ startPrefix?: string;
1147
+ endPrefix?: string;
1148
+ }): string;
1149
+ } & {
1150
+ params: InferSchema<TSchema>;
1151
+ };
1152
+ };
1153
+
216
1154
  /**
217
1155
  * Model Catalog Types
218
1156
  *
@@ -643,89 +1581,6 @@ declare class ModelRegistry {
643
1581
  getCheapestModel(inputTokens: number, outputTokens: number, providerId?: string): ModelSpec | undefined;
644
1582
  }
645
1583
 
646
- interface LLMGenerationOptions {
647
- model: string;
648
- messages: LLMMessage[];
649
- maxTokens?: number;
650
- temperature?: number;
651
- topP?: number;
652
- stopSequences?: string[];
653
- responseFormat?: "text";
654
- metadata?: Record<string, unknown>;
655
- extra?: Record<string, unknown>;
656
- /**
657
- * Optional abort signal for cancelling the request mid-flight.
658
- *
659
- * When the signal is aborted, the provider will attempt to cancel
660
- * the underlying HTTP request and the stream will terminate with
661
- * an abort error. Use `isAbortError()` from `@/core/errors` to
662
- * detect cancellation in error handling.
663
- *
664
- * @example
665
- * ```typescript
666
- * const controller = new AbortController();
667
- *
668
- * const stream = client.stream({
669
- * model: "claude-3-5-sonnet-20241022",
670
- * messages: [{ role: "user", content: "Tell me a long story" }],
671
- * signal: controller.signal,
672
- * });
673
- *
674
- * // Cancel after 5 seconds
675
- * setTimeout(() => controller.abort(), 5000);
676
- *
677
- * try {
678
- * for await (const chunk of stream) {
679
- * process.stdout.write(chunk.text);
680
- * }
681
- * } catch (error) {
682
- * if (isAbortError(error)) {
683
- * console.log("\nRequest was cancelled");
684
- * } else {
685
- * throw error;
686
- * }
687
- * }
688
- * ```
689
- */
690
- signal?: AbortSignal;
691
- }
692
- interface TokenUsage {
693
- inputTokens: number;
694
- outputTokens: number;
695
- totalTokens: number;
696
- /** Number of input tokens served from cache (subset of inputTokens) */
697
- cachedInputTokens?: number;
698
- /** Number of input tokens written to cache (subset of inputTokens, Anthropic only) */
699
- cacheCreationInputTokens?: number;
700
- }
701
- interface LLMStreamChunk {
702
- text: string;
703
- /**
704
- * Indicates that the provider has finished producing output and includes the reason if available.
705
- */
706
- finishReason?: string | null;
707
- /**
708
- * Token usage information, typically available in the final chunk when the stream completes.
709
- */
710
- usage?: TokenUsage;
711
- /**
712
- * Provider specific payload emitted at the same time as the text chunk. This is useful for debugging and tests.
713
- */
714
- rawEvent?: unknown;
715
- }
716
- interface LLMStream extends AsyncIterable<LLMStreamChunk> {
717
- }
718
- type ProviderIdentifier = string;
719
- interface ModelDescriptor {
720
- provider: string;
721
- name: string;
722
- }
723
- declare class ModelIdentifierParser {
724
- private readonly defaultProvider;
725
- constructor(defaultProvider?: string);
726
- parse(identifier: string): ModelDescriptor;
727
- }
728
-
729
1584
  /**
730
1585
  * Quick execution methods for simple use cases.
731
1586
  *
@@ -1091,6 +1946,8 @@ interface SubagentEvent {
1091
1946
  gadgetInvocationId: string;
1092
1947
  /** Nesting depth (1 = direct child, 2 = grandchild, etc.) */
1093
1948
  depth: number;
1949
+ /** LLM iteration number within the subagent (for gadget parenting in TUI) */
1950
+ iteration?: number;
1094
1951
  /** The actual event data - either a StreamEvent or LLMCallInfo */
1095
1952
  event: StreamEvent | LLMCallInfo;
1096
1953
  }
@@ -1437,6 +2294,134 @@ interface ExecutionContext {
1437
2294
  * ```
1438
2295
  */
1439
2296
  onSubagentEvent?: (event: SubagentEvent) => void;
2297
+ /**
2298
+ * The execution tree tracking all LLM calls and gadget executions.
2299
+ *
2300
+ * Subagent gadgets can use the tree to:
2301
+ * - Automatically aggregate costs via `tree.getSubtreeCost(nodeId)`
2302
+ * - Collect media outputs via `tree.getSubtreeMedia(nodeId)`
2303
+ * - Query token usage via `tree.getSubtreeTokens(nodeId)`
2304
+ *
2305
+ * When using `withParentContext(ctx)`, the subagent shares the parent's tree,
2306
+ * enabling unified cost tracking and progress visibility across all nesting levels.
2307
+ *
2308
+ * This is optional - it will be `undefined` for:
2309
+ * - Gadgets executed via CLI `gadget run` command
2310
+ * - Direct gadget testing without agent context
2311
+ * - Legacy code that hasn't adopted the ExecutionTree model
2312
+ *
2313
+ * @example
2314
+ * ```typescript
2315
+ * execute: async (params, ctx) => {
2316
+ * // Build subagent with parent context (shares tree)
2317
+ * const agent = new AgentBuilder(client)
2318
+ * .withParentContext(ctx)
2319
+ * .withGadgets(Navigate, Click)
2320
+ * .ask(params.task);
2321
+ *
2322
+ * for await (const event of agent.run()) {
2323
+ * // Process events...
2324
+ * }
2325
+ *
2326
+ * // After subagent completes, costs are automatically tracked in tree
2327
+ * // No need for manual cost aggregation!
2328
+ * const subtreeCost = ctx.tree?.getSubtreeCost(ctx.nodeId!);
2329
+ *
2330
+ * // Media from all nested gadgets also aggregated
2331
+ * const allMedia = ctx.tree?.getSubtreeMedia(ctx.nodeId!);
2332
+ *
2333
+ * return { result: "done", media: allMedia };
2334
+ * }
2335
+ * ```
2336
+ */
2337
+ tree?: ExecutionTree;
2338
+ /**
2339
+ * The tree node ID for this gadget execution.
2340
+ *
2341
+ * This identifies the current gadget's node in the execution tree.
2342
+ * Use with tree methods to query/aggregate data for this subtree:
2343
+ * - `tree.getSubtreeCost(nodeId)` - total cost including nested calls
2344
+ * - `tree.getSubtreeMedia(nodeId)` - all media from nested gadgets
2345
+ * - `tree.getSubtreeTokens(nodeId)` - token usage breakdown
2346
+ * - `tree.getDescendants(nodeId)` - all child nodes
2347
+ *
2348
+ * Note: This is distinct from `invocationId` which identifies the gadget call
2349
+ * (used in conversation history). `nodeId` is the tree node identifier.
2350
+ */
2351
+ nodeId?: NodeId;
2352
+ /**
2353
+ * Nesting depth of this gadget execution.
2354
+ *
2355
+ * - 0 = Root level (direct gadget call from main agent)
2356
+ * - 1 = First-level subagent (gadget called by a gadget)
2357
+ * - 2+ = Deeper nesting
2358
+ *
2359
+ * Useful for:
2360
+ * - Conditional behavior based on nesting level
2361
+ * - Logging with appropriate indentation
2362
+ * - Limiting recursion depth
2363
+ *
2364
+ * @example
2365
+ * ```typescript
2366
+ * execute: async (params, ctx) => {
2367
+ * // Prevent infinite recursion
2368
+ * if ((ctx.depth ?? 0) > 3) {
2369
+ * return "Maximum nesting depth reached";
2370
+ * }
2371
+ *
2372
+ * // Log with depth-aware indentation
2373
+ * const indent = " ".repeat(ctx.depth ?? 0);
2374
+ * console.log(`${indent}Executing at depth ${ctx.depth}`);
2375
+ * }
2376
+ * ```
2377
+ */
2378
+ depth?: number;
2379
+ /**
2380
+ * Host llmist exports for external gadgets.
2381
+ *
2382
+ * External gadgets MUST use these instead of importing from 'llmist'
2383
+ * to ensure they use the same version as the host CLI, enabling proper
2384
+ * tree sharing and feature compatibility.
2385
+ *
2386
+ * Use the `getHostExports(ctx)` helper function to access these exports
2387
+ * with proper error handling.
2388
+ *
2389
+ * @example
2390
+ * ```typescript
2391
+ * import { getHostExports, Gadget, z } from 'llmist';
2392
+ *
2393
+ * class BrowseWeb extends Gadget({...}) {
2394
+ * async execute(params, ctx) {
2395
+ * const { AgentBuilder } = getHostExports(ctx);
2396
+ * const agent = new AgentBuilder()
2397
+ * .withParentContext(ctx)
2398
+ * .ask(params.task);
2399
+ * }
2400
+ * }
2401
+ * ```
2402
+ */
2403
+ hostExports?: HostExports;
2404
+ }
2405
+ /**
2406
+ * Host llmist exports provided to external gadgets via ExecutionContext.
2407
+ *
2408
+ * This ensures external gadgets use the same class instances as the host CLI,
2409
+ * enabling proper tree sharing and avoiding the "dual-package problem" where
2410
+ * different versions of llmist have incompatible classes.
2411
+ */
2412
+ interface HostExports {
2413
+ /** AgentBuilder for creating subagents with proper tree sharing */
2414
+ AgentBuilder: typeof AgentBuilder;
2415
+ /** Gadget factory for defining gadgets */
2416
+ Gadget: typeof Gadget;
2417
+ /** createGadget for functional gadget definitions */
2418
+ createGadget: typeof createGadget;
2419
+ /** ExecutionTree for tree operations */
2420
+ ExecutionTree: typeof ExecutionTree;
2421
+ /** LLMist client */
2422
+ LLMist: typeof LLMist;
2423
+ /** Zod schema builder */
2424
+ z: typeof zod.z;
1440
2425
  }
1441
2426
  /**
1442
2427
  * Parent agent configuration passed to gadgets.
@@ -2143,13 +3128,16 @@ declare class LLMMessageBuilder {
2143
3128
  * Record a gadget execution result in the message history.
2144
3129
  * Creates an assistant message with the gadget invocation and a user message with the result.
2145
3130
  *
3131
+ * The invocationId is shown to the LLM so it can reference previous calls when building dependencies.
3132
+ *
2146
3133
  * @param gadget - Name of the gadget that was executed
2147
3134
  * @param parameters - Parameters that were passed to the gadget
2148
3135
  * @param result - Text result from the gadget execution
3136
+ * @param invocationId - Invocation ID (shown to LLM so it can reference for dependencies)
2149
3137
  * @param media - Optional media outputs from the gadget
2150
3138
  * @param mediaIds - Optional IDs for the media outputs
2151
3139
  */
2152
- addGadgetCallResult(gadget: string, parameters: Record<string, unknown>, result: string, media?: GadgetMediaOutput[], mediaIds?: string[]): this;
3140
+ addGadgetCallResult(gadget: string, parameters: Record<string, unknown>, result: string, invocationId: string, media?: GadgetMediaOutput[], mediaIds?: string[]): this;
2153
3141
  /**
2154
3142
  * Format parameters as Block format with JSON Pointer paths.
2155
3143
  * Uses the configured argPrefix for consistency with system prompt.
@@ -3623,15 +4611,6 @@ interface AgentOptions {
3623
4611
  /** Maps text content to the result string (optional, defaults to text) */
3624
4612
  resultMapping?: (text: string) => string;
3625
4613
  };
3626
- /** Stop on gadget error */
3627
- stopOnGadgetError?: boolean;
3628
- /** Custom error recovery logic */
3629
- canRecoverFromGadgetError?: (context: {
3630
- error: string;
3631
- gadgetName: string;
3632
- errorType: "parse" | "validation" | "execution";
3633
- parameters?: Record<string, unknown>;
3634
- }) => boolean | Promise<boolean>;
3635
4614
  /** Default gadget timeout */
3636
4615
  defaultGadgetTimeoutMs?: number;
3637
4616
  /** Custom prompt configuration for gadget system prompts */
@@ -3648,6 +4627,22 @@ interface AgentOptions {
3648
4627
  subagentConfig?: SubagentConfigMap;
3649
4628
  /** Callback for subagent gadgets to report subagent events to parent */
3650
4629
  onSubagentEvent?: (event: SubagentEvent) => void;
4630
+ /**
4631
+ * Shared execution tree for tracking all LLM calls and gadget executions.
4632
+ * If provided (by a parent subagent), nodes are added to this tree.
4633
+ * If not provided, the Agent creates its own tree.
4634
+ */
4635
+ parentTree?: ExecutionTree;
4636
+ /**
4637
+ * Parent node ID in the tree (when this agent is a subagent).
4638
+ * Used to set parentId on all nodes created by this agent.
4639
+ */
4640
+ parentNodeId?: NodeId;
4641
+ /**
4642
+ * Base depth for nodes created by this agent.
4643
+ * Root agents use 0; subagents use (parentDepth + 1).
4644
+ */
4645
+ baseDepth?: number;
3651
4646
  }
3652
4647
  /**
3653
4648
  * Agent: Lean orchestrator that delegates to StreamProcessor.
@@ -3679,8 +4674,6 @@ declare class Agent {
3679
4674
  private readonly requestHumanInput?;
3680
4675
  private readonly textOnlyHandler;
3681
4676
  private readonly textWithGadgetsHandler?;
3682
- private readonly stopOnGadgetError;
3683
- private readonly canRecoverFromGadgetError?;
3684
4677
  private readonly defaultGadgetTimeoutMs?;
3685
4678
  private readonly defaultMaxTokens?;
3686
4679
  private hasUserPrompt;
@@ -3695,6 +4688,10 @@ declare class Agent {
3695
4688
  private readonly userSubagentEventCallback?;
3696
4689
  private readonly pendingSubagentEvents;
3697
4690
  private readonly onSubagentEvent;
4691
+ private syntheticInvocationCounter;
4692
+ private readonly tree;
4693
+ private readonly parentNodeId;
4694
+ private readonly baseDepth;
3698
4695
  /**
3699
4696
  * Creates a new Agent instance.
3700
4697
  * @internal This constructor is private. Use LLMist.createAgent() or AgentBuilder instead.
@@ -3752,6 +4749,46 @@ declare class Agent {
3752
4749
  * ```
3753
4750
  */
3754
4751
  getMediaStore(): MediaStore;
4752
+ /**
4753
+ * Get the execution tree for this agent.
4754
+ *
4755
+ * The execution tree provides a first-class model of all LLM calls and gadget executions,
4756
+ * including nested subagent activity. Use this to:
4757
+ * - Query execution state: `tree.getNode(id)`
4758
+ * - Get total cost: `tree.getTotalCost()`
4759
+ * - Get subtree cost/media/tokens: `tree.getSubtreeCost(nodeId)`
4760
+ * - Subscribe to events: `tree.on("llm_call_complete", handler)`
4761
+ * - Stream all events: `for await (const event of tree.events())`
4762
+ *
4763
+ * For subagents (created with `withParentContext`), the tree is shared with the parent,
4764
+ * enabling unified tracking and real-time visibility across all nesting levels.
4765
+ *
4766
+ * @returns The ExecutionTree instance
4767
+ *
4768
+ * @example
4769
+ * ```typescript
4770
+ * const agent = LLMist.createAgent()
4771
+ * .withModel("sonnet")
4772
+ * .withGadgets(BrowseWeb)
4773
+ * .ask("Research topic X");
4774
+ *
4775
+ * for await (const event of agent.run()) {
4776
+ * // Process events...
4777
+ * }
4778
+ *
4779
+ * // After execution, query the tree
4780
+ * const tree = agent.getTree();
4781
+ * console.log(`Total cost: $${tree.getTotalCost().toFixed(4)}`);
4782
+ *
4783
+ * // Inspect all LLM calls
4784
+ * for (const node of tree.getAllNodes()) {
4785
+ * if (node.type === "llm_call") {
4786
+ * console.log(`LLM #${node.iteration}: ${node.model}`);
4787
+ * }
4788
+ * }
4789
+ * ```
4790
+ */
4791
+ getTree(): ExecutionTree;
3755
4792
  /**
3756
4793
  * Manually trigger context compaction.
3757
4794
  *
@@ -3901,8 +4938,6 @@ declare class AgentBuilder {
3901
4938
  private gadgetArgPrefix?;
3902
4939
  private textOnlyHandler?;
3903
4940
  private textWithGadgetsHandler?;
3904
- private stopOnGadgetError?;
3905
- private canRecoverFromGadgetError?;
3906
4941
  private defaultGadgetTimeoutMs?;
3907
4942
  private gadgetOutputLimit?;
3908
4943
  private gadgetOutputLimitPercent?;
@@ -4140,61 +5175,6 @@ declare class AgentBuilder {
4140
5175
  parameterMapping: (text: string) => Record<string, unknown>;
4141
5176
  resultMapping?: (text: string) => string;
4142
5177
  }): this;
4143
- /**
4144
- * Set whether to stop gadget execution on first error.
4145
- *
4146
- * When true (default), if a gadget fails:
4147
- * - Subsequent gadgets in the same response are skipped
4148
- * - LLM stream is cancelled to save costs
4149
- * - Agent loop continues with error in context
4150
- *
4151
- * When false:
4152
- * - All gadgets in the response still execute
4153
- * - LLM stream continues to completion
4154
- *
4155
- * @param stop - Whether to stop on gadget error
4156
- * @returns This builder for chaining
4157
- *
4158
- * @example
4159
- * ```typescript
4160
- * .withStopOnGadgetError(false)
4161
- * ```
4162
- */
4163
- withStopOnGadgetError(stop: boolean): this;
4164
- /**
4165
- * Set custom error handling logic.
4166
- *
4167
- * Provides fine-grained control over whether to continue after different types of errors.
4168
- * Overrides `stopOnGadgetError` when provided.
4169
- *
4170
- * **Note:** This builder method configures the underlying `canRecoverFromGadgetError` option
4171
- * in `AgentOptions`. The method is named `withErrorHandler` for better developer experience,
4172
- * but maps to the `canRecoverFromGadgetError` property internally.
4173
- *
4174
- * @param handler - Function that decides whether to continue after an error.
4175
- * Return `true` to continue execution, `false` to stop.
4176
- * @returns This builder for chaining
4177
- *
4178
- * @example
4179
- * ```typescript
4180
- * .withErrorHandler((context) => {
4181
- * // Stop on parse errors, continue on validation/execution errors
4182
- * if (context.errorType === "parse") {
4183
- * return false;
4184
- * }
4185
- * if (context.error.includes("CRITICAL")) {
4186
- * return false;
4187
- * }
4188
- * return true;
4189
- * })
4190
- * ```
4191
- */
4192
- withErrorHandler(handler: (context: {
4193
- error: string;
4194
- gadgetName: string;
4195
- errorType: "parse" | "validation" | "execution";
4196
- parameters?: Record<string, unknown>;
4197
- }) => boolean | Promise<boolean>): this;
4198
5178
  /**
4199
5179
  * Set default timeout for gadget execution.
4200
5180
  *
@@ -4359,6 +5339,15 @@ declare class AgentBuilder {
4359
5339
  * The method extracts `invocationId` and `onSubagentEvent` from the execution
4360
5340
  * context and sets up automatic forwarding via hooks and event wrapping.
4361
5341
  *
5342
+ * **NEW: Shared Tree Model** - When the parent provides an ExecutionTree via context,
5343
+ * the subagent shares that tree instead of creating its own. This enables:
5344
+ * - Unified cost tracking across all nesting levels
5345
+ * - Automatic media aggregation via `tree.getSubtreeMedia(nodeId)`
5346
+ * - Real-time visibility of nested execution in the parent
5347
+ *
5348
+ * **Signal Forwarding** - When parent context includes a signal, it's automatically
5349
+ * forwarded to the subagent for proper cancellation propagation.
5350
+ *
4362
5351
  * @param ctx - ExecutionContext passed to the gadget's execute() method
4363
5352
  * @param depth - Nesting depth (default: 1 for direct child)
4364
5353
  * @returns This builder for chaining
@@ -4379,6 +5368,11 @@ declare class AgentBuilder {
4379
5368
  * result = event.content;
4380
5369
  * }
4381
5370
  * }
5371
+ *
5372
+ * // After subagent completes, costs are automatically aggregated
5373
+ * // No manual tracking needed - use tree methods:
5374
+ * const totalCost = ctx.tree?.getSubtreeCost(ctx.nodeId!);
5375
+ * const allMedia = ctx.tree?.getSubtreeMedia(ctx.nodeId!);
4382
5376
  * }
4383
5377
  * ```
4384
5378
  */
@@ -4410,11 +5404,13 @@ declare class AgentBuilder {
4410
5404
  *
4411
5405
  * This is useful for in-context learning - showing the LLM what "past self"
4412
5406
  * did correctly so it mimics the pattern. The call is formatted with proper
4413
- * markers and parameter format.
5407
+ * markers and parameter format, including the invocation ID so the LLM can
5408
+ * reference previous calls when building dependencies.
4414
5409
  *
4415
5410
  * @param gadgetName - Name of the gadget
4416
5411
  * @param parameters - Parameters passed to the gadget
4417
5412
  * @param result - Result returned by the gadget
5413
+ * @param invocationId - Invocation ID (shown to LLM so it can reference for dependencies)
4418
5414
  * @returns This builder for chaining
4419
5415
  *
4420
5416
  * @example
@@ -4426,15 +5422,18 @@ declare class AgentBuilder {
4426
5422
  * done: false,
4427
5423
  * type: 'info'
4428
5424
  * },
4429
- * 'ℹ️ 👋 Hello!\n\nHere\'s what I can do:\n- Analyze code\n- Run commands'
5425
+ * 'ℹ️ 👋 Hello!\n\nHere\'s what I can do:\n- Analyze code\n- Run commands',
5426
+ * 'gc_1'
4430
5427
  * )
4431
5428
  * ```
4432
5429
  */
4433
- withSyntheticGadgetCall(gadgetName: string, parameters: Record<string, unknown>, result: string): this;
5430
+ withSyntheticGadgetCall(gadgetName: string, parameters: Record<string, unknown>, result: string, invocationId: string): this;
4434
5431
  /**
4435
- * Compose the final hooks, including:
4436
- * - Trailing message injection (if configured)
4437
- * - Subagent event forwarding for LLM calls (if parentContext is set)
5432
+ * Compose the final hooks, including trailing message injection if configured.
5433
+ *
5434
+ * Note: Subagent event visibility is now handled entirely by the ExecutionTree.
5435
+ * When a subagent uses withParentContext(ctx), it shares the parent's tree,
5436
+ * and all events are automatically visible to tree subscribers (like the TUI).
4438
5437
  */
4439
5438
  private composeHooks;
4440
5439
  /**
@@ -4604,9 +5603,10 @@ interface IConversationManager {
4604
5603
  addAssistantMessage(content: string): void;
4605
5604
  /**
4606
5605
  * Adds a gadget call and its result to the conversation.
5606
+ * The invocationId is shown to the LLM so it can reference previous calls when building dependencies.
4607
5607
  * Optionally includes media outputs (images, audio, etc.) for multimodal results.
4608
5608
  */
4609
- addGadgetCallResult(gadgetName: string, parameters: Record<string, unknown>, result: string, media?: GadgetMediaOutput[], mediaIds?: string[]): void;
5609
+ addGadgetCallResult(gadgetName: string, parameters: Record<string, unknown>, result: string, invocationId: string, media?: GadgetMediaOutput[], mediaIds?: string[]): void;
4610
5610
  /**
4611
5611
  * Gets the complete conversation history including base messages (system prompts, gadget instructions).
4612
5612
  */
@@ -5342,4 +6342,4 @@ declare function createTextMockStream(text: string, options?: {
5342
6342
  usage?: MockResponse["usage"];
5343
6343
  }): LLMStream;
5344
6344
 
5345
- export { type LLMGenerationOptions as $, AbstractGadget as A, type MessageContent as B, type CompactionConfig as C, GadgetRegistry as D, MediaStore as E, type AgentContextConfig as F, type GadgetMediaOutput as G, type HintTemplate as H, type IConversationManager as I, type SubagentConfigMap as J, type SubagentEvent as K, type LLMMessage as L, MockProviderAdapter as M, type ExecutionContext as N, type GadgetExecuteReturn as O, type GadgetExample as P, type ParsedGadgetCall as Q, type ResolvedCompactionConfig as R, type StreamEvent as S, type TokenUsage as T, type GadgetExecutionResult as U, type MediaKind as V, type MediaMetadata as W, type GadgetExecuteResultWithMedia as X, type ProviderAdapter as Y, type ModelDescriptor as Z, type ModelSpec as _, type LLMStream as a, isImagePart as a$, type ImageModelSpec as a0, type ImageGenerationOptions as a1, type ImageGenerationResult as a2, type SpeechModelSpec as a3, type SpeechGenerationOptions as a4, type SpeechGenerationResult as a5, type HistoryMessage as a6, type TrailingMessage as a7, type TrailingMessageContext as a8, AgentBuilder as a9, type ObserveLLMCallContext as aA, type ObserveLLMCompleteContext as aB, type ObserveLLMErrorContext as aC, type Observers as aD, type SubagentContext as aE, DEFAULT_COMPACTION_CONFIG as aF, DEFAULT_SUMMARIZATION_PROMPT as aG, type LLMistOptions as aH, type AudioContentPart as aI, type AudioMimeType as aJ, type AudioSource as aK, type ContentPart as aL, type ImageBase64Source as aM, type ImageContentPart as aN, type ImageMimeType as aO, type ImageSource as aP, type ImageUrlSource as aQ, type TextContentPart as aR, audioFromBase64 as aS, audioFromBuffer as aT, detectAudioMimeType as aU, detectImageMimeType as aV, imageFromBase64 as aW, imageFromBuffer as aX, imageFromUrl as aY, isAudioPart as aZ, isDataUrl as a_, type EventHandlers as aa, collectEvents as ab, collectText as ac, runWithHandlers as ad, type AfterGadgetExecutionAction as ae, type AfterGadgetExecutionControllerContext as af, type AfterLLMCallAction as ag, type AfterLLMCallControllerContext as ah, type AfterLLMErrorAction as ai, type AgentOptions as aj, type BeforeGadgetExecutionAction as ak, type BeforeLLMCallAction as al, type ChunkInterceptorContext as am, type Controllers as an, type GadgetExecutionControllerContext as ao, type GadgetParameterInterceptorContext as ap, type GadgetResultInterceptorContext as aq, type Interceptors as ar, type LLMCallControllerContext as as, type LLMErrorControllerContext as at, type MessageInterceptorContext as au, type MessageTurn as av, type ObserveChunkContext as aw, type ObserveCompactionContext as ax, type ObserveGadgetCompleteContext as ay, type ObserveGadgetStartContext as az, type LLMStreamChunk as b, isTextPart as b0, parseDataUrl as b1, text as b2, toBase64 as b3, type MessageRole as b4, extractMessageText as b5, LLMMessageBuilder as b6, normalizeMessageContent as b7, type CostEstimate as b8, type ModelFeatures as b9, type TextOnlyContext as bA, type TextOnlyCustomHandler as bB, type TextOnlyGadgetConfig as bC, type TextOnlyHandler as bD, type TextOnlyStrategy as bE, type ModelLimits as ba, type ModelPricing as bb, type VisionAnalyzeOptions as bc, type VisionAnalyzeResult as bd, type ProviderIdentifier as be, ModelIdentifierParser as bf, type HintContext as bg, type PromptContext as bh, type PromptTemplate as bi, type PromptTemplateConfig as bj, DEFAULT_HINTS as bk, DEFAULT_PROMPTS as bl, resolveHintTemplate as bm, resolvePromptTemplate as bn, resolveRulesTemplate as bo, type TextGenerationOptions as bp, complete as bq, stream as br, type GadgetClass as bs, type GadgetOrClass as bt, type CostReportingLLMist as bu, type GadgetExecuteResult as bv, type GadgetSkippedEvent as bw, type StoredMedia as bx, type SubagentStreamEvent as by, type TextOnlyAction as bz, createMockAdapter as c, MockBuilder as d, createMockClient as e, MockManager as f, getMockManager as g, createMockStream as h, createTextMockStream as i, type MockAudioData as j, type MockImageData as k, type MockMatcher as l, mockLLM as m, type MockMatcherContext as n, type MockOptions as o, type MockRegistration as p, type MockResponse as q, type MockStats as r, type AgentHooks as s, ModelRegistry as t, LLMist as u, type CompactionEvent as v, type CompactionStats as w, type CompactionStrategy as x, type CompactionContext as y, type CompactionResult as z };
6345
+ export { type LLMGenerationOptions as $, AbstractGadget as A, type MessageContent as B, type CompactionConfig as C, GadgetRegistry as D, MediaStore as E, type AgentContextConfig as F, type GadgetMediaOutput as G, type HintTemplate as H, type IConversationManager as I, type SubagentConfigMap as J, type SubagentEvent as K, type LLMMessage as L, MockProviderAdapter as M, ExecutionTree as N, type NodeId as O, type ParsedGadgetCall as P, type GadgetExecutionResult as Q, type ResolvedCompactionConfig as R, type StreamEvent as S, type TokenUsage as T, type MediaKind as U, type MediaMetadata as V, type GadgetExecuteResultWithMedia as W, type ExecutionContext as X, type ProviderAdapter as Y, type ModelDescriptor as Z, type ModelSpec as _, type LLMStream as a, type GadgetStartEvent as a$, type ImageModelSpec as a0, type ImageGenerationOptions as a1, type ImageGenerationResult as a2, type SpeechModelSpec as a3, type SpeechGenerationOptions as a4, type SpeechGenerationResult as a5, type HostExports as a6, type HistoryMessage as a7, type TrailingMessage as a8, type TrailingMessageContext as a9, type ObserveGadgetStartContext as aA, type ObserveLLMCallContext as aB, type ObserveLLMCompleteContext as aC, type ObserveLLMErrorContext as aD, type Observers as aE, type SubagentContext as aF, DEFAULT_COMPACTION_CONFIG as aG, DEFAULT_SUMMARIZATION_PROMPT as aH, type LLMistOptions as aI, type AddGadgetParams as aJ, type AddLLMCallParams as aK, type CompleteGadgetParams as aL, type CompleteLLMCallParams as aM, type ExecutionNode as aN, type ExecutionNodeType as aO, type GadgetNode as aP, type GadgetState as aQ, type LLMCallNode as aR, type BaseExecutionEvent as aS, type CompactionEvent$1 as aT, type ExecutionEvent as aU, type ExecutionEventType as aV, type GadgetCallEvent as aW, type GadgetCompleteEvent as aX, type GadgetErrorEvent as aY, type GadgetEvent as aZ, type GadgetSkippedEvent$1 as a_, AgentBuilder as aa, type EventHandlers as ab, collectEvents as ac, collectText as ad, runWithHandlers as ae, type AfterGadgetExecutionAction as af, type AfterGadgetExecutionControllerContext as ag, type AfterLLMCallAction as ah, type AfterLLMCallControllerContext as ai, type AfterLLMErrorAction as aj, type AgentOptions as ak, type BeforeGadgetExecutionAction as al, type BeforeLLMCallAction as am, type ChunkInterceptorContext as an, type Controllers as ao, type GadgetExecutionControllerContext as ap, type GadgetParameterInterceptorContext as aq, type GadgetResultInterceptorContext as ar, type Interceptors as as, type LLMCallControllerContext as at, type LLMErrorControllerContext as au, type MessageInterceptorContext as av, type MessageTurn as aw, type ObserveChunkContext as ax, type ObserveCompactionContext as ay, type ObserveGadgetCompleteContext as az, type LLMStreamChunk as b, stream as b$, type HumanInputRequiredEvent as b0, type LLMCallCompleteEvent as b1, type LLMCallErrorEvent as b2, type LLMCallStartEvent as b3, type LLMCallStreamEvent as b4, type LLMEvent as b5, type StreamCompleteEvent as b6, type TextEvent as b7, filterByDepth as b8, filterByParent as b9, isTextPart as bA, parseDataUrl as bB, text as bC, toBase64 as bD, type MessageRole as bE, extractMessageText as bF, LLMMessageBuilder as bG, normalizeMessageContent as bH, type CostEstimate as bI, type ModelFeatures as bJ, type ModelLimits as bK, type ModelPricing as bL, type VisionAnalyzeOptions as bM, type VisionAnalyzeResult as bN, type ProviderIdentifier as bO, ModelIdentifierParser as bP, type HintContext as bQ, type PromptContext as bR, type PromptTemplate as bS, type PromptTemplateConfig as bT, DEFAULT_HINTS as bU, DEFAULT_PROMPTS as bV, resolveHintTemplate as bW, resolvePromptTemplate as bX, resolveRulesTemplate as bY, type TextGenerationOptions as bZ, complete as b_, filterRootEvents as ba, groupByParent as bb, isGadgetEvent as bc, isLLMEvent as bd, isRootEvent as be, isSubagentEvent as bf, type AudioContentPart as bg, type AudioMimeType as bh, type AudioSource as bi, type ContentPart as bj, type ImageBase64Source as bk, type ImageContentPart as bl, type ImageMimeType as bm, type ImageSource as bn, type ImageUrlSource as bo, type TextContentPart as bp, audioFromBase64 as bq, audioFromBuffer as br, detectAudioMimeType as bs, detectImageMimeType as bt, imageFromBase64 as bu, imageFromBuffer as bv, imageFromUrl as bw, isAudioPart as bx, isDataUrl as by, isImagePart as bz, createMockAdapter as c, type CreateGadgetConfig as c0, createGadget as c1, type GadgetClass as c2, type GadgetOrClass as c3, type GadgetConfig as c4, Gadget as c5, type CostReportingLLMist as c6, type GadgetExample as c7, type GadgetExecuteResult as c8, type GadgetExecuteReturn as c9, type GadgetSkippedEvent as ca, type StoredMedia as cb, type SubagentStreamEvent as cc, type TextOnlyAction as cd, type TextOnlyContext as ce, type TextOnlyCustomHandler as cf, type TextOnlyGadgetConfig as cg, type TextOnlyHandler as ch, type TextOnlyStrategy as ci, MockBuilder as d, createMockClient as e, MockManager as f, getMockManager as g, createMockStream as h, createTextMockStream as i, type MockAudioData as j, type MockImageData as k, type MockMatcher as l, mockLLM as m, type MockMatcherContext as n, type MockOptions as o, type MockRegistration as p, type MockResponse as q, type MockStats as r, type AgentHooks as s, ModelRegistry as t, LLMist as u, type CompactionEvent as v, type CompactionStats as w, type CompactionStrategy as x, type CompactionContext as y, type CompactionResult as z };