@falai/agent 1.1.3 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (193) hide show
  1. package/README.md +9 -0
  2. package/dist/cjs/core/Agent.d.ts +17 -1
  3. package/dist/cjs/core/Agent.d.ts.map +1 -1
  4. package/dist/cjs/core/Agent.js +47 -0
  5. package/dist/cjs/core/Agent.js.map +1 -1
  6. package/dist/cjs/core/BatchPromptBuilder.d.ts +3 -0
  7. package/dist/cjs/core/BatchPromptBuilder.d.ts.map +1 -1
  8. package/dist/cjs/core/BatchPromptBuilder.js +4 -1
  9. package/dist/cjs/core/BatchPromptBuilder.js.map +1 -1
  10. package/dist/cjs/core/CompactionEngine.d.ts +65 -0
  11. package/dist/cjs/core/CompactionEngine.d.ts.map +1 -0
  12. package/dist/cjs/core/CompactionEngine.js +251 -0
  13. package/dist/cjs/core/CompactionEngine.js.map +1 -0
  14. package/dist/cjs/core/PromptComposer.d.ts +8 -1
  15. package/dist/cjs/core/PromptComposer.d.ts.map +1 -1
  16. package/dist/cjs/core/PromptComposer.js +238 -126
  17. package/dist/cjs/core/PromptComposer.js.map +1 -1
  18. package/dist/cjs/core/PromptSectionCache.d.ts +57 -0
  19. package/dist/cjs/core/PromptSectionCache.d.ts.map +1 -0
  20. package/dist/cjs/core/PromptSectionCache.js +108 -0
  21. package/dist/cjs/core/PromptSectionCache.js.map +1 -0
  22. package/dist/cjs/core/ResponseEngine.d.ts +3 -2
  23. package/dist/cjs/core/ResponseEngine.d.ts.map +1 -1
  24. package/dist/cjs/core/ResponseEngine.js +8 -8
  25. package/dist/cjs/core/ResponseEngine.js.map +1 -1
  26. package/dist/cjs/core/ResponseModal.d.ts.map +1 -1
  27. package/dist/cjs/core/ResponseModal.js +120 -70
  28. package/dist/cjs/core/ResponseModal.js.map +1 -1
  29. package/dist/cjs/core/ResponsePipeline.d.ts +2 -1
  30. package/dist/cjs/core/ResponsePipeline.d.ts.map +1 -1
  31. package/dist/cjs/core/ResponsePipeline.js +17 -19
  32. package/dist/cjs/core/ResponsePipeline.js.map +1 -1
  33. package/dist/cjs/core/RoutingEngine.d.ts +10 -0
  34. package/dist/cjs/core/RoutingEngine.d.ts.map +1 -1
  35. package/dist/cjs/core/RoutingEngine.js +5 -4
  36. package/dist/cjs/core/RoutingEngine.js.map +1 -1
  37. package/dist/cjs/core/SessionManager.d.ts.map +1 -1
  38. package/dist/cjs/core/SessionManager.js +20 -0
  39. package/dist/cjs/core/SessionManager.js.map +1 -1
  40. package/dist/cjs/core/StreamingToolExecutor.d.ts +142 -0
  41. package/dist/cjs/core/StreamingToolExecutor.d.ts.map +1 -0
  42. package/dist/cjs/core/StreamingToolExecutor.js +455 -0
  43. package/dist/cjs/core/StreamingToolExecutor.js.map +1 -0
  44. package/dist/cjs/core/ToolManager.d.ts +18 -1
  45. package/dist/cjs/core/ToolManager.d.ts.map +1 -1
  46. package/dist/cjs/core/ToolManager.js +91 -0
  47. package/dist/cjs/core/ToolManager.js.map +1 -1
  48. package/dist/cjs/index.d.ts +5 -1
  49. package/dist/cjs/index.d.ts.map +1 -1
  50. package/dist/cjs/index.js +8 -2
  51. package/dist/cjs/index.js.map +1 -1
  52. package/dist/cjs/providers/AnthropicProvider.d.ts +7 -0
  53. package/dist/cjs/providers/AnthropicProvider.d.ts.map +1 -1
  54. package/dist/cjs/providers/AnthropicProvider.js +109 -19
  55. package/dist/cjs/providers/AnthropicProvider.js.map +1 -1
  56. package/dist/cjs/providers/GeminiProvider.d.ts +32 -0
  57. package/dist/cjs/providers/GeminiProvider.d.ts.map +1 -1
  58. package/dist/cjs/providers/GeminiProvider.js +160 -53
  59. package/dist/cjs/providers/GeminiProvider.js.map +1 -1
  60. package/dist/cjs/providers/OpenAIProvider.d.ts +5 -0
  61. package/dist/cjs/providers/OpenAIProvider.d.ts.map +1 -1
  62. package/dist/cjs/providers/OpenAIProvider.js +65 -18
  63. package/dist/cjs/providers/OpenAIProvider.js.map +1 -1
  64. package/dist/cjs/providers/OpenRouterProvider.d.ts +5 -0
  65. package/dist/cjs/providers/OpenRouterProvider.d.ts.map +1 -1
  66. package/dist/cjs/providers/OpenRouterProvider.js +57 -18
  67. package/dist/cjs/providers/OpenRouterProvider.js.map +1 -1
  68. package/dist/cjs/types/agent.d.ts +44 -0
  69. package/dist/cjs/types/agent.d.ts.map +1 -1
  70. package/dist/cjs/types/agent.js.map +1 -1
  71. package/dist/cjs/types/ai.d.ts +2 -2
  72. package/dist/cjs/types/ai.d.ts.map +1 -1
  73. package/dist/cjs/types/compaction.d.ts +50 -0
  74. package/dist/cjs/types/compaction.d.ts.map +1 -0
  75. package/dist/cjs/types/compaction.js +6 -0
  76. package/dist/cjs/types/compaction.js.map +1 -0
  77. package/dist/cjs/types/index.d.ts +4 -2
  78. package/dist/cjs/types/index.d.ts.map +1 -1
  79. package/dist/cjs/types/index.js.map +1 -1
  80. package/dist/cjs/types/tool.d.ts +84 -0
  81. package/dist/cjs/types/tool.d.ts.map +1 -1
  82. package/dist/core/Agent.d.ts +17 -1
  83. package/dist/core/Agent.d.ts.map +1 -1
  84. package/dist/core/Agent.js +47 -0
  85. package/dist/core/Agent.js.map +1 -1
  86. package/dist/core/BatchPromptBuilder.d.ts +3 -0
  87. package/dist/core/BatchPromptBuilder.d.ts.map +1 -1
  88. package/dist/core/BatchPromptBuilder.js +4 -1
  89. package/dist/core/BatchPromptBuilder.js.map +1 -1
  90. package/dist/core/CompactionEngine.d.ts +65 -0
  91. package/dist/core/CompactionEngine.d.ts.map +1 -0
  92. package/dist/core/CompactionEngine.js +244 -0
  93. package/dist/core/CompactionEngine.js.map +1 -0
  94. package/dist/core/PromptComposer.d.ts +8 -1
  95. package/dist/core/PromptComposer.d.ts.map +1 -1
  96. package/dist/core/PromptComposer.js +238 -126
  97. package/dist/core/PromptComposer.js.map +1 -1
  98. package/dist/core/PromptSectionCache.d.ts +57 -0
  99. package/dist/core/PromptSectionCache.d.ts.map +1 -0
  100. package/dist/core/PromptSectionCache.js +104 -0
  101. package/dist/core/PromptSectionCache.js.map +1 -0
  102. package/dist/core/ResponseEngine.d.ts +3 -2
  103. package/dist/core/ResponseEngine.d.ts.map +1 -1
  104. package/dist/core/ResponseEngine.js +8 -8
  105. package/dist/core/ResponseEngine.js.map +1 -1
  106. package/dist/core/ResponseModal.d.ts.map +1 -1
  107. package/dist/core/ResponseModal.js +121 -71
  108. package/dist/core/ResponseModal.js.map +1 -1
  109. package/dist/core/ResponsePipeline.d.ts +2 -1
  110. package/dist/core/ResponsePipeline.d.ts.map +1 -1
  111. package/dist/core/ResponsePipeline.js +18 -20
  112. package/dist/core/ResponsePipeline.js.map +1 -1
  113. package/dist/core/RoutingEngine.d.ts +10 -0
  114. package/dist/core/RoutingEngine.d.ts.map +1 -1
  115. package/dist/core/RoutingEngine.js +6 -5
  116. package/dist/core/RoutingEngine.js.map +1 -1
  117. package/dist/core/SessionManager.d.ts.map +1 -1
  118. package/dist/core/SessionManager.js +17 -0
  119. package/dist/core/SessionManager.js.map +1 -1
  120. package/dist/core/StreamingToolExecutor.d.ts +142 -0
  121. package/dist/core/StreamingToolExecutor.d.ts.map +1 -0
  122. package/dist/core/StreamingToolExecutor.js +448 -0
  123. package/dist/core/StreamingToolExecutor.js.map +1 -0
  124. package/dist/core/ToolManager.d.ts +18 -1
  125. package/dist/core/ToolManager.d.ts.map +1 -1
  126. package/dist/core/ToolManager.js +91 -0
  127. package/dist/core/ToolManager.js.map +1 -1
  128. package/dist/index.d.ts +5 -1
  129. package/dist/index.d.ts.map +1 -1
  130. package/dist/index.js +3 -0
  131. package/dist/index.js.map +1 -1
  132. package/dist/providers/AnthropicProvider.d.ts +7 -0
  133. package/dist/providers/AnthropicProvider.d.ts.map +1 -1
  134. package/dist/providers/AnthropicProvider.js +109 -19
  135. package/dist/providers/AnthropicProvider.js.map +1 -1
  136. package/dist/providers/GeminiProvider.d.ts +32 -0
  137. package/dist/providers/GeminiProvider.d.ts.map +1 -1
  138. package/dist/providers/GeminiProvider.js +160 -53
  139. package/dist/providers/GeminiProvider.js.map +1 -1
  140. package/dist/providers/OpenAIProvider.d.ts +5 -0
  141. package/dist/providers/OpenAIProvider.d.ts.map +1 -1
  142. package/dist/providers/OpenAIProvider.js +65 -18
  143. package/dist/providers/OpenAIProvider.js.map +1 -1
  144. package/dist/providers/OpenRouterProvider.d.ts +5 -0
  145. package/dist/providers/OpenRouterProvider.d.ts.map +1 -1
  146. package/dist/providers/OpenRouterProvider.js +57 -18
  147. package/dist/providers/OpenRouterProvider.js.map +1 -1
  148. package/dist/types/agent.d.ts +44 -0
  149. package/dist/types/agent.d.ts.map +1 -1
  150. package/dist/types/agent.js.map +1 -1
  151. package/dist/types/ai.d.ts +2 -2
  152. package/dist/types/ai.d.ts.map +1 -1
  153. package/dist/types/compaction.d.ts +50 -0
  154. package/dist/types/compaction.d.ts.map +1 -0
  155. package/dist/types/compaction.js +5 -0
  156. package/dist/types/compaction.js.map +1 -0
  157. package/dist/types/index.d.ts +4 -2
  158. package/dist/types/index.d.ts.map +1 -1
  159. package/dist/types/index.js.map +1 -1
  160. package/dist/types/tool.d.ts +84 -0
  161. package/dist/types/tool.d.ts.map +1 -1
  162. package/docs/api/overview.md +140 -0
  163. package/docs/core/tools/enhanced-tool.md +186 -0
  164. package/docs/core/tools/streaming-execution.md +161 -0
  165. package/docs/guides/context-compaction.md +96 -0
  166. package/docs/guides/prompt-optimization.md +164 -0
  167. package/examples/advanced-patterns/context-compaction.ts +223 -0
  168. package/examples/advanced-patterns/streaming-responses.ts +85 -7
  169. package/examples/tools/enhanced-tool-metadata.ts +268 -0
  170. package/examples/tools/streaming-tool-execution.ts +283 -0
  171. package/package.json +1 -1
  172. package/src/core/Agent.ts +58 -2
  173. package/src/core/BatchPromptBuilder.ts +4 -1
  174. package/src/core/CompactionEngine.ts +318 -0
  175. package/src/core/PromptComposer.ts +259 -156
  176. package/src/core/PromptSectionCache.ts +136 -0
  177. package/src/core/ResponseEngine.ts +7 -11
  178. package/src/core/ResponseModal.ts +133 -83
  179. package/src/core/ResponsePipeline.ts +22 -22
  180. package/src/core/RoutingEngine.ts +16 -5
  181. package/src/core/SessionManager.ts +19 -0
  182. package/src/core/StreamingToolExecutor.ts +572 -0
  183. package/src/core/ToolManager.ts +151 -41
  184. package/src/index.ts +14 -0
  185. package/src/providers/AnthropicProvider.ts +121 -24
  186. package/src/providers/GeminiProvider.ts +174 -54
  187. package/src/providers/OpenAIProvider.ts +77 -25
  188. package/src/providers/OpenRouterProvider.ts +68 -25
  189. package/src/types/agent.ts +45 -0
  190. package/src/types/ai.ts +2 -2
  191. package/src/types/compaction.ts +52 -0
  192. package/src/types/index.ts +35 -14
  193. package/src/types/tool.ts +108 -0
@@ -12,6 +12,9 @@ import type {
12
12
  ApiCallConfig,
13
13
  ComputationConfig,
14
14
  ToolContext,
15
+ ToolCallRequest,
16
+ ToolExecutionUpdate,
17
+ EnhancedTool,
15
18
  Event,
16
19
  } from "../types";
17
20
  import { ToolScope } from "../types";
@@ -19,6 +22,7 @@ import { logger } from "../utils";
19
22
  import { Agent } from "./Agent";
20
23
  import { Route } from "./Route";
21
24
  import { Step } from "./Step";
25
+ import { StreamingToolExecutor } from "./StreamingToolExecutor";
22
26
 
23
27
  /**
24
28
  * Error thrown when tool creation fails
@@ -283,13 +287,13 @@ export class ToolManager<TContext = unknown, TData = unknown> {
283
287
 
284
288
  this.toolRegistry.set(tool.id, tool);
285
289
  logger.debug(`[ToolManager] Registered tool: ${tool.id} (${tool.name || 'unnamed'})`);
286
-
290
+
287
291
  return tool;
288
292
  } catch (error) {
289
293
  if (error instanceof ToolCreationError) {
290
294
  throw error;
291
295
  }
292
-
296
+
293
297
  const toolId = tool?.id || 'unknown';
294
298
  throw new ToolCreationError(
295
299
  `Failed to register tool '${toolId}': ${error instanceof Error ? error.message : String(error)}`,
@@ -387,14 +391,14 @@ export class ToolManager<TContext = unknown, TData = unknown> {
387
391
  if (!tool || !tool.id || !tool.handler) {
388
392
  throw new ToolCreationError('Invalid tool: must have id and handler properties', tool?.id || 'unknown');
389
393
  }
390
-
394
+
391
395
  // Add to agent's tools array using the unified interface
392
396
  if (this.agent) {
393
397
  this.agent.addTool(tool);
394
398
  } else {
395
399
  logger.warn(`[ToolManager] No agent available, tool not added to agent scope: ${tool.id}`);
396
400
  }
397
-
401
+
398
402
  logger.debug(`[ToolManager] Added tool to agent scope: ${tool.id}`);
399
403
  return tool;
400
404
  }
@@ -403,7 +407,7 @@ export class ToolManager<TContext = unknown, TData = unknown> {
403
407
  * Add a tool to a specific route scope (creates and adds in one operation)
404
408
  */
405
409
  addToRoute(
406
- route: Route<TContext, TData>,
410
+ route: Route<TContext, TData>,
407
411
  tool: Tool<TContext, TData>
408
412
  ): Tool<TContext, TData> {
409
413
  // Add to route's tools array using the existing createTool method
@@ -412,7 +416,7 @@ export class ToolManager<TContext = unknown, TData = unknown> {
412
416
  } else {
413
417
  logger.warn(`[ToolManager] Route does not support createTool method, tool not added to route scope: ${tool.id}`);
414
418
  }
415
-
419
+
416
420
  logger.debug(`[ToolManager] Added tool to route scope: ${tool.id}`);
417
421
  return tool;
418
422
  }
@@ -479,7 +483,7 @@ export class ToolManager<TContext = unknown, TData = unknown> {
479
483
  logger.debug(`[ToolManager] Found tool in registry: ${toolId}`);
480
484
  return registeredTool;
481
485
  }
482
-
486
+
483
487
  // Also check by name in registry
484
488
  for (const [id, tool] of Array.from(this.toolRegistry.entries())) {
485
489
  if (tool.name === toolId) {
@@ -557,7 +561,7 @@ export class ToolManager<TContext = unknown, TData = unknown> {
557
561
 
558
562
  // Convert map to array, preserving priority order
559
563
  const allTools = Array.from(toolMap.values());
560
-
564
+
561
565
  // If we have step-specific tools, prioritize them
562
566
  if (resolvedTools.length > 0) {
563
567
  // Add resolved step tools first, then other tools not already included
@@ -575,7 +579,7 @@ export class ToolManager<TContext = unknown, TData = unknown> {
575
579
  * Consolidates tool execution logic from ToolExecutor and ResponseModal
576
580
  */
577
581
  async execute(
578
- toolId: string,
582
+ toolId: string,
579
583
  args?: Record<string, unknown>,
580
584
  context?: {
581
585
  step?: Step<TContext, TData>;
@@ -610,14 +614,14 @@ export class ToolManager<TContext = unknown, TData = unknown> {
610
614
  // Tool not found - try fallback tools if available
611
615
  if (fallbackTools.length > 0) {
612
616
  logger.warn(`[ToolManager] Primary tool '${toolId}' not found, trying fallback tools: ${fallbackTools.join(', ')}`);
613
-
617
+
614
618
  for (const fallbackId of fallbackTools) {
615
619
  const fallbackResult = await this.execute(fallbackId, args, {
616
620
  ...context,
617
621
  fallbackTools: [], // Prevent infinite recursion
618
622
  retryCount: 0 // Don't retry fallback tools
619
623
  });
620
-
624
+
621
625
  if (fallbackResult.success) {
622
626
  logger.info(`[ToolManager] Fallback tool '${fallbackId}' succeeded for primary tool '${toolId}'`);
623
627
  return {
@@ -676,13 +680,13 @@ export class ToolManager<TContext = unknown, TData = unknown> {
676
680
  } catch (error) {
677
681
  lastError = error instanceof Error ? error : new Error(String(error));
678
682
  const errorMessage = lastError.message;
679
-
683
+
680
684
  // Check if this is a transient error that should be retried
681
685
  const isTransientError = this.isTransientError(lastError);
682
-
686
+
683
687
  if (attempt < maxRetries && isTransientError) {
684
688
  logger.warn(`[ToolManager] Tool execution attempt ${attempt + 1} failed for ${toolId}, retrying: ${errorMessage}`);
685
-
689
+
686
690
  // Exponential backoff for retries
687
691
  const delay = Math.min(1000 * Math.pow(2, attempt), 5000);
688
692
  await new Promise(resolve => setTimeout(resolve, delay));
@@ -697,7 +701,7 @@ export class ToolManager<TContext = unknown, TData = unknown> {
697
701
  // All retries failed - try fallback tools
698
702
  if (fallbackTools.length > 0) {
699
703
  logger.warn(`[ToolManager] Primary tool '${toolId}' failed after retries, trying fallback tools: ${fallbackTools.join(', ')}`);
700
-
704
+
701
705
  for (const fallbackId of fallbackTools) {
702
706
  try {
703
707
  const fallbackResult = await this.execute(fallbackId, args, {
@@ -705,7 +709,7 @@ export class ToolManager<TContext = unknown, TData = unknown> {
705
709
  fallbackTools: [], // Prevent infinite recursion
706
710
  retryCount: 0 // Don't retry fallback tools
707
711
  });
708
-
712
+
709
713
  if (fallbackResult.success) {
710
714
  logger.info(`[ToolManager] Fallback tool '${fallbackId}' succeeded for failed primary tool '${toolId}'`);
711
715
  return {
@@ -769,7 +773,7 @@ export class ToolManager<TContext = unknown, TData = unknown> {
769
773
  }): Promise<ToolExecutionResult> {
770
774
  const { tool, context, updateContext, updateData, history, data, toolArguments } = params;
771
775
  const startTime = Date.now();
772
-
776
+
773
777
  try {
774
778
  // Validate tool before execution
775
779
  if (!tool || !tool.handler || typeof tool.handler !== 'function') {
@@ -802,6 +806,40 @@ export class ToolManager<TContext = unknown, TData = unknown> {
802
806
 
803
807
  logger.debug(`[ToolManager] Executing tool: ${tool.id} with args:`, toolArguments);
804
808
 
809
+ // EnhancedTool validation gate (Req 9.2, 10.6)
810
+ const enhanced = tool as EnhancedTool<TContext, TData>;
811
+ if (typeof enhanced.validateInput === 'function' && toolArguments) {
812
+ const validation = await enhanced.validateInput(toolArguments, toolContext);
813
+ if (!validation.valid) {
814
+ const executionTime = Date.now() - startTime;
815
+ logger.warn(`[ToolManager] Tool ${tool.id} input validation failed: ${validation.error}`);
816
+ return {
817
+ success: false,
818
+ error: `Validation failed: ${validation.error || 'Invalid input'}`,
819
+ metadata: { toolId: tool.id, executionTime, gate: 'validateInput' }
820
+ };
821
+ }
822
+ }
823
+
824
+ // EnhancedTool permission gate (Req 9.3, 10.6)
825
+ if (typeof enhanced.checkPermissions === 'function' && toolArguments) {
826
+ const permission = await enhanced.checkPermissions(toolArguments, toolContext);
827
+ if (!permission.allowed) {
828
+ const executionTime = Date.now() - startTime;
829
+ logger.warn(`[ToolManager] Tool ${tool.id} permission denied: ${permission.reason}`);
830
+ return {
831
+ success: false,
832
+ error: `Permission denied: ${permission.reason || 'Not allowed'}`,
833
+ metadata: {
834
+ toolId: tool.id,
835
+ executionTime,
836
+ gate: 'checkPermissions',
837
+ canOverride: permission.canOverride
838
+ }
839
+ };
840
+ }
841
+ }
842
+
805
843
  // Execute tool with timeout protection
806
844
  const executionTimeout = 30000; // 30 seconds default timeout
807
845
  const timeoutPromise = new Promise<never>((_, reject) => {
@@ -818,7 +856,7 @@ export class ToolManager<TContext = unknown, TData = unknown> {
818
856
 
819
857
  // Handle different result types
820
858
  let toolResult: ToolResult<unknown, TContext, TData>;
821
-
859
+
822
860
  if (result && typeof result === 'object' && ('data' in result || 'success' in result || 'error' in result)) {
823
861
  // It's already a ToolResult-like object
824
862
  toolResult = result as ToolResult<unknown, TContext, TData>;
@@ -882,9 +920,9 @@ export class ToolManager<TContext = unknown, TData = unknown> {
882
920
  };
883
921
  } catch (error) {
884
922
  const executionTime = Date.now() - startTime;
885
-
923
+
886
924
  logger.error(`[ToolManager] Tool execution error for ${tool.id} after ${executionTime}ms:`, error);
887
-
925
+
888
926
  // Re-throw the error so the execute method can handle retries
889
927
  throw error;
890
928
  }
@@ -936,6 +974,78 @@ export class ToolManager<TContext = unknown, TData = unknown> {
936
974
  return results;
937
975
  }
938
976
 
977
+ /**
978
+ * Execute tool calls with concurrency control using StreamingToolExecutor.
979
+ * Creates a StreamingToolExecutor, resolves tools, queues them, and yields
980
+ * ToolExecutionUpdate results in original request order.
981
+ *
982
+ * Concurrency-safe tools run in parallel; non-safe tools run serially.
983
+ * Progress messages are yielded immediately.
984
+ */
985
+ async *executeWithConcurrency(params: {
986
+ toolCalls: ToolCallRequest[];
987
+ context: TContext;
988
+ data?: Partial<TData>;
989
+ history?: Event[];
990
+ signal?: AbortSignal;
991
+ route?: Route<TContext, TData>;
992
+ step?: Step<TContext, TData>;
993
+ }): AsyncGenerator<ToolExecutionUpdate<TData>> {
994
+ const { toolCalls, context, data, history, signal, route, step } = params;
995
+
996
+ if (toolCalls.length === 0) {
997
+ return;
998
+ }
999
+
1000
+ // Build a ToolContext for the executor
1001
+ const toolContext: ToolContext<TContext, TData> = {
1002
+ context,
1003
+ data: data || {} as Partial<TData>,
1004
+ history: history || [],
1005
+ step: step ? { id: step.id, routeId: route?.id || '' } : undefined,
1006
+ updateContext: (updates: Partial<TContext>): Promise<void> => {
1007
+ Object.assign(context as Record<string, unknown>, updates);
1008
+ return Promise.resolve();
1009
+ },
1010
+ updateData: (updates: Partial<TData>): Promise<void> => {
1011
+ if (data) {
1012
+ Object.assign(data as Record<string, unknown>, updates);
1013
+ }
1014
+ return Promise.resolve();
1015
+ },
1016
+ getField: <K extends keyof TData>(key: K): TData[K] | undefined => {
1017
+ return data?.[key];
1018
+ },
1019
+ setField: <K extends keyof TData>(key: K, value: TData[K]): Promise<void> => {
1020
+ if (data) {
1021
+ (data as TData)[key] = value;
1022
+ }
1023
+ return Promise.resolve();
1024
+ },
1025
+ hasField: <K extends keyof TData>(key: K): boolean => {
1026
+ return data != null && key in (data as Record<string, unknown>);
1027
+ },
1028
+ };
1029
+
1030
+ const executor = new StreamingToolExecutor<TContext, TData>(toolContext, {
1031
+ signal,
1032
+ });
1033
+
1034
+ // Resolve and queue each tool call
1035
+ for (const toolCall of toolCalls) {
1036
+ const tool = this.find(toolCall.toolName, undefined, step, route);
1037
+ if (!tool) {
1038
+ logger.warn(`[ToolManager] Tool not found for concurrent execution: ${toolCall.toolName}`);
1039
+ continue;
1040
+ }
1041
+ // Cast to EnhancedTool — plain Tools are compatible (defaults apply)
1042
+ executor.addTool(toolCall, tool as EnhancedTool<TContext, TData>);
1043
+ }
1044
+
1045
+ // Yield all results in order
1046
+ yield* executor.getRemainingResults();
1047
+ }
1048
+
939
1049
  /**
940
1050
  * Create a data enrichment tool that modifies collected data
941
1051
  * Returns a tool instance that can be registered or added to scope
@@ -945,7 +1055,7 @@ export class ToolManager<TContext = unknown, TData = unknown> {
945
1055
  ): Tool<TContext, TData, void> {
946
1056
  // Validate configuration first
947
1057
  this.validateDataEnrichmentConfig(config);
948
-
1058
+
949
1059
  const tool: Tool<TContext, TData, void> = {
950
1060
  id: config.id,
951
1061
  name: config.name || `Data Enrichment: ${config.id}`,
@@ -982,7 +1092,7 @@ export class ToolManager<TContext = unknown, TData = unknown> {
982
1092
  }
983
1093
 
984
1094
  logger.debug(`[ToolManager] Data enrichment completed for tool: ${config.id}`);
985
-
1095
+
986
1096
  return {
987
1097
  success: true,
988
1098
  dataUpdate: enrichedData
@@ -1012,7 +1122,7 @@ export class ToolManager<TContext = unknown, TData = unknown> {
1012
1122
  ): Tool<TContext, TData, ValidationResult> {
1013
1123
  // Validate configuration first
1014
1124
  this.validateValidationConfig(config);
1015
-
1125
+
1016
1126
  const tool: Tool<TContext, TData, ValidationResult> = {
1017
1127
  id: config.id,
1018
1128
  name: config.name || `Validation: ${config.id}`,
@@ -1048,7 +1158,7 @@ export class ToolManager<TContext = unknown, TData = unknown> {
1048
1158
  } catch (error) {
1049
1159
  const errorMessage = error instanceof Error ? error.message : String(error);
1050
1160
  logger.error(`[ToolManager] Validation failed for ${config.id}: ${errorMessage}`);
1051
-
1161
+
1052
1162
  // Return validation failure result instead of throwing
1053
1163
  return {
1054
1164
  valid: false,
@@ -1076,7 +1186,7 @@ export class ToolManager<TContext = unknown, TData = unknown> {
1076
1186
  ): Tool<TContext, TData, TResult> {
1077
1187
  // Validate configuration first
1078
1188
  this.validateApiCallConfig(config);
1079
-
1189
+
1080
1190
  const tool: Tool<TContext, TData, TResult> = {
1081
1191
  id: config.id,
1082
1192
  name: config.name || `API Call: ${config.id}`,
@@ -1098,7 +1208,7 @@ export class ToolManager<TContext = unknown, TData = unknown> {
1098
1208
  handler: async (context: ToolContext<TContext, TData>, args?: Record<string, unknown>): Promise<TResult> => {
1099
1209
  try {
1100
1210
  // Resolve endpoint URL
1101
- const endpoint = typeof config.endpoint === 'function'
1211
+ const endpoint = typeof config.endpoint === 'function'
1102
1212
  ? config.endpoint(context.context, context.data)
1103
1213
  : config.endpoint;
1104
1214
 
@@ -1124,7 +1234,7 @@ export class ToolManager<TContext = unknown, TData = unknown> {
1124
1234
 
1125
1235
  // Make the API call
1126
1236
  const response = await fetch(endpoint, requestOptions);
1127
-
1237
+
1128
1238
  if (!response.ok) {
1129
1239
  throw new Error(`HTTP ${response.status}: ${response.statusText}`);
1130
1240
  }
@@ -1146,7 +1256,7 @@ export class ToolManager<TContext = unknown, TData = unknown> {
1146
1256
  } catch (error) {
1147
1257
  const errorMessage = error instanceof Error ? error.message : String(error);
1148
1258
  logger.error(`[ToolManager] API call failed for ${config.id}: ${errorMessage}`);
1149
-
1259
+
1150
1260
  throw new ToolExecutionError(
1151
1261
  `API call failed: ${errorMessage}`,
1152
1262
  config.id,
@@ -1169,7 +1279,7 @@ export class ToolManager<TContext = unknown, TData = unknown> {
1169
1279
  ): Tool<TContext, TData, TResult> {
1170
1280
  // Validate configuration first
1171
1281
  this.validateComputationConfig(config);
1172
-
1282
+
1173
1283
  const tool: Tool<TContext, TData, TResult> = {
1174
1284
  id: config.id,
1175
1285
  name: config.name || `Computation: ${config.id}`,
@@ -1205,7 +1315,7 @@ export class ToolManager<TContext = unknown, TData = unknown> {
1205
1315
  } catch (error) {
1206
1316
  const errorMessage = error instanceof Error ? error.message : String(error);
1207
1317
  logger.error(`[ToolManager] Computation failed for ${config.id}: ${errorMessage}`);
1208
-
1318
+
1209
1319
  throw new ToolExecutionError(
1210
1320
  `Computation failed: ${errorMessage}`,
1211
1321
  config.id,
@@ -1229,36 +1339,36 @@ export class ToolManager<TContext = unknown, TData = unknown> {
1229
1339
  metadata?: Record<string, unknown>;
1230
1340
  } {
1231
1341
  const tool = this.find(toolId, scope, step, route);
1232
-
1342
+
1233
1343
  if (!tool) {
1234
1344
  return { found: false };
1235
1345
  }
1236
1346
 
1237
1347
  // Determine which scope the tool was found in
1238
1348
  let foundScope = 'unknown';
1239
-
1349
+
1240
1350
  // Check step scope
1241
1351
  if (step?.tools) {
1242
- const stepTool = step.tools.find((t) =>
1243
- (typeof t === 'string' && t === toolId) ||
1352
+ const stepTool = step.tools.find((t) =>
1353
+ (typeof t === 'string' && t === toolId) ||
1244
1354
  (typeof t === 'object' && (t.id === toolId || t.name === toolId))
1245
1355
  );
1246
1356
  if (stepTool) foundScope = 'step';
1247
1357
  }
1248
-
1358
+
1249
1359
  // Check route scope
1250
1360
  if (foundScope === 'unknown' && route?.tools) {
1251
1361
  const routeTool = route.tools.find((t) => t.id === toolId || t.name === toolId);
1252
1362
  if (routeTool) foundScope = 'route';
1253
1363
  }
1254
-
1364
+
1255
1365
  // Check agent scope
1256
1366
  if (foundScope === 'unknown' && this.agent) {
1257
1367
  const agentTools = this.agent.getTools();
1258
1368
  const agentTool = agentTools.find((t) => t.id === toolId || t.name === toolId);
1259
1369
  if (agentTool) foundScope = 'agent';
1260
1370
  }
1261
-
1371
+
1262
1372
  // Check registry
1263
1373
  if (foundScope === 'unknown' && this.toolRegistry.has(toolId)) {
1264
1374
  foundScope = 'registry';
@@ -1293,7 +1403,7 @@ export class ToolManager<TContext = unknown, TData = unknown> {
1293
1403
 
1294
1404
  for (const toolId of toolIds) {
1295
1405
  const info = this.getToolInfo(toolId, ToolScope.ALL, step, route);
1296
-
1406
+
1297
1407
  if (info.found) {
1298
1408
  found.push(toolId);
1299
1409
  details.push({ id: toolId, found: true, scope: info.scope });
@@ -1324,10 +1434,10 @@ export class ToolManager<TContext = unknown, TData = unknown> {
1324
1434
  const registeredToolIds = Array.from(this.toolRegistry.keys());
1325
1435
  const agentTools = this.agent ? this.agent.getTools() : [];
1326
1436
  const agentToolIds = agentTools.map((t) => t.id);
1327
-
1437
+
1328
1438
  // Find duplicate IDs between registry and agent
1329
1439
  const duplicateIds = registeredToolIds.filter(id => agentToolIds.includes(id));
1330
-
1440
+
1331
1441
  const allAvailable = this.getAvailable();
1332
1442
 
1333
1443
  return {
@@ -1368,7 +1478,7 @@ export class ToolManager<TContext = unknown, TData = unknown> {
1368
1478
  if (!tool.handler || typeof tool.handler !== 'function') {
1369
1479
  issues.push(`Tool '${id}' has invalid or missing handler`);
1370
1480
  }
1371
-
1481
+
1372
1482
  if (!tool.id || tool.id.trim() === '') {
1373
1483
  issues.push(`Tool has empty or invalid ID: ${JSON.stringify(tool)}`);
1374
1484
  }
package/src/index.ts CHANGED
@@ -21,6 +21,10 @@ export { SessionManager } from "./core/SessionManager";
21
21
  export { ToolManager, ToolCreationError, ToolExecutionError } from "./core/ToolManager";
22
22
  export { BatchExecutor, needsInput, type NeedsInputStep, type DetermineBatchParams } from "./core/BatchExecutor";
23
23
  export { BatchPromptBuilder, type BuildBatchPromptParams, type BatchPromptResult } from "./core/BatchPromptBuilder";
24
+ export { CompactionEngine } from "./core/CompactionEngine";
25
+ export { StreamingToolExecutor } from "./core/StreamingToolExecutor";
26
+ export { PromptSectionCache } from "./core/PromptSectionCache";
27
+ export type { PromptSectionType, PromptCacheConfig, SectionCompute } from "./core/PromptSectionCache";
24
28
 
25
29
  // Providers
26
30
  export { GeminiProvider } from "./providers/GeminiProvider";
@@ -94,6 +98,7 @@ export {
94
98
  // Types
95
99
  export type {
96
100
  AgentOptions,
101
+ AgentCompactionConfig,
97
102
  AgentResponse,
98
103
  Term,
99
104
  Guideline,
@@ -119,6 +124,15 @@ export type {
119
124
  ToolHandler,
120
125
  Tool,
121
126
 
127
+ EnhancedTool,
128
+ ToolValidationResult,
129
+ ToolPermissionResult,
130
+ ToolCallRequest,
131
+ ToolExecutionUpdate,
132
+
133
+ CompactionOptions,
134
+ CompactionResult,
135
+
122
136
  DataEnrichmentConfig,
123
137
  ValidationConfig,
124
138
  ValidationError,