@falai/agent 2.2.4 → 2.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/adapters/MemoryAdapter.d.ts.map +1 -1
- package/dist/adapters/MemoryAdapter.js +10 -1
- package/dist/adapters/MemoryAdapter.js.map +1 -1
- package/dist/adapters/MongoAdapter.d.ts.map +1 -1
- package/dist/adapters/MongoAdapter.js +33 -2
- package/dist/adapters/MongoAdapter.js.map +1 -1
- package/dist/adapters/OpenSearchAdapter.d.ts.map +1 -1
- package/dist/adapters/OpenSearchAdapter.js +15 -1
- package/dist/adapters/OpenSearchAdapter.js.map +1 -1
- package/dist/adapters/PostgreSQLAdapter.d.ts.map +1 -1
- package/dist/adapters/PostgreSQLAdapter.js +35 -5
- package/dist/adapters/PostgreSQLAdapter.js.map +1 -1
- package/dist/adapters/PrismaAdapter.d.ts.map +1 -1
- package/dist/adapters/PrismaAdapter.js +58 -15
- package/dist/adapters/PrismaAdapter.js.map +1 -1
- package/dist/adapters/RedisAdapter.d.ts.map +1 -1
- package/dist/adapters/RedisAdapter.js +10 -1
- package/dist/adapters/RedisAdapter.js.map +1 -1
- package/dist/adapters/SQLiteAdapter.d.ts.map +1 -1
- package/dist/adapters/SQLiteAdapter.js +38 -6
- package/dist/adapters/SQLiteAdapter.js.map +1 -1
- package/dist/cjs/adapters/MemoryAdapter.d.ts.map +1 -1
- package/dist/cjs/adapters/MemoryAdapter.js +10 -1
- package/dist/cjs/adapters/MemoryAdapter.js.map +1 -1
- package/dist/cjs/adapters/MongoAdapter.d.ts.map +1 -1
- package/dist/cjs/adapters/MongoAdapter.js +33 -2
- package/dist/cjs/adapters/MongoAdapter.js.map +1 -1
- package/dist/cjs/adapters/OpenSearchAdapter.d.ts.map +1 -1
- package/dist/cjs/adapters/OpenSearchAdapter.js +15 -1
- package/dist/cjs/adapters/OpenSearchAdapter.js.map +1 -1
- package/dist/cjs/adapters/PostgreSQLAdapter.d.ts.map +1 -1
- package/dist/cjs/adapters/PostgreSQLAdapter.js +35 -5
- package/dist/cjs/adapters/PostgreSQLAdapter.js.map +1 -1
- package/dist/cjs/adapters/PrismaAdapter.d.ts.map +1 -1
- package/dist/cjs/adapters/PrismaAdapter.js +58 -15
- package/dist/cjs/adapters/PrismaAdapter.js.map +1 -1
- package/dist/cjs/adapters/RedisAdapter.d.ts.map +1 -1
- package/dist/cjs/adapters/RedisAdapter.js +10 -1
- package/dist/cjs/adapters/RedisAdapter.js.map +1 -1
- package/dist/cjs/adapters/SQLiteAdapter.d.ts.map +1 -1
- package/dist/cjs/adapters/SQLiteAdapter.js +38 -6
- package/dist/cjs/adapters/SQLiteAdapter.js.map +1 -1
- package/dist/cjs/core/Agent.d.ts +28 -18
- package/dist/cjs/core/Agent.d.ts.map +1 -1
- package/dist/cjs/core/Agent.js +58 -68
- package/dist/cjs/core/Agent.js.map +1 -1
- package/dist/cjs/core/AutoChainExecutor.d.ts.map +1 -1
- package/dist/cjs/core/AutoChainExecutor.js +14 -20
- package/dist/cjs/core/AutoChainExecutor.js.map +1 -1
- package/dist/cjs/core/BranchEvaluator.d.ts +4 -3
- package/dist/cjs/core/BranchEvaluator.d.ts.map +1 -1
- package/dist/cjs/core/BranchEvaluator.js +18 -23
- package/dist/cjs/core/BranchEvaluator.js.map +1 -1
- package/dist/cjs/core/Flow.d.ts +2 -1
- package/dist/cjs/core/Flow.d.ts.map +1 -1
- package/dist/cjs/core/Flow.js +10 -3
- package/dist/cjs/core/Flow.js.map +1 -1
- package/dist/cjs/core/FlowRouter.d.ts +1 -0
- package/dist/cjs/core/FlowRouter.d.ts.map +1 -1
- package/dist/cjs/core/FlowRouter.js +28 -5
- package/dist/cjs/core/FlowRouter.js.map +1 -1
- package/dist/cjs/core/PersistenceManager.d.ts +3 -0
- package/dist/cjs/core/PersistenceManager.d.ts.map +1 -1
- package/dist/cjs/core/PersistenceManager.js +57 -5
- package/dist/cjs/core/PersistenceManager.js.map +1 -1
- package/dist/cjs/core/PromptComposer.d.ts.map +1 -1
- package/dist/cjs/core/PromptComposer.js +24 -10
- package/dist/cjs/core/PromptComposer.js.map +1 -1
- package/dist/cjs/core/ResponseGenerationError.d.ts +30 -0
- package/dist/cjs/core/ResponseGenerationError.d.ts.map +1 -0
- package/dist/cjs/core/ResponseGenerationError.js +37 -0
- package/dist/cjs/core/ResponseGenerationError.js.map +1 -0
- package/dist/cjs/core/ResponseModal.d.ts +43 -102
- package/dist/cjs/core/ResponseModal.d.ts.map +1 -1
- package/dist/cjs/core/ResponseModal.js +178 -1194
- package/dist/cjs/core/ResponseModal.js.map +1 -1
- package/dist/cjs/core/ResponsePipeline.d.ts +58 -152
- package/dist/cjs/core/ResponsePipeline.d.ts.map +1 -1
- package/dist/cjs/core/ResponsePipeline.js +408 -457
- package/dist/cjs/core/ResponsePipeline.js.map +1 -1
- package/dist/cjs/core/SessionFinalizer.d.ts +34 -0
- package/dist/cjs/core/SessionFinalizer.d.ts.map +1 -0
- package/dist/cjs/core/SessionFinalizer.js +61 -0
- package/dist/cjs/core/SessionFinalizer.js.map +1 -0
- package/dist/cjs/core/SessionManager.d.ts +1 -1
- package/dist/cjs/core/SessionManager.d.ts.map +1 -1
- package/dist/cjs/core/SessionManager.js +18 -7
- package/dist/cjs/core/SessionManager.js.map +1 -1
- package/dist/cjs/core/SignalCoordinator.d.ts +103 -0
- package/dist/cjs/core/SignalCoordinator.d.ts.map +1 -0
- package/dist/cjs/core/SignalCoordinator.js +207 -0
- package/dist/cjs/core/SignalCoordinator.js.map +1 -0
- package/dist/cjs/core/SignalEvaluator.d.ts +2 -2
- package/dist/cjs/core/SignalEvaluator.d.ts.map +1 -1
- package/dist/cjs/core/SignalEvaluator.js +11 -26
- package/dist/cjs/core/SignalEvaluator.js.map +1 -1
- package/dist/cjs/core/SignalProcessor.d.ts.map +1 -1
- package/dist/cjs/core/SignalProcessor.js +28 -11
- package/dist/cjs/core/SignalProcessor.js.map +1 -1
- package/dist/cjs/core/Step.d.ts +3 -1
- package/dist/cjs/core/Step.d.ts.map +1 -1
- package/dist/cjs/core/Step.js +10 -3
- package/dist/cjs/core/Step.js.map +1 -1
- package/dist/cjs/core/StepLifecycle.d.ts +33 -0
- package/dist/cjs/core/StepLifecycle.d.ts.map +1 -0
- package/dist/cjs/core/StepLifecycle.js +97 -0
- package/dist/cjs/core/StepLifecycle.js.map +1 -0
- package/dist/cjs/core/ToolLoopExecutor.d.ts +104 -0
- package/dist/cjs/core/ToolLoopExecutor.d.ts.map +1 -0
- package/dist/cjs/core/ToolLoopExecutor.js +391 -0
- package/dist/cjs/core/ToolLoopExecutor.js.map +1 -0
- package/dist/cjs/core/ToolManager.d.ts +1 -1
- package/dist/cjs/core/ToolManager.d.ts.map +1 -1
- package/dist/cjs/core/ToolManager.js.map +1 -1
- package/dist/cjs/index.d.ts +4 -5
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +7 -6
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/providers/AnthropicProvider.d.ts +2 -0
- package/dist/cjs/providers/AnthropicProvider.d.ts.map +1 -1
- package/dist/cjs/providers/AnthropicProvider.js +28 -56
- package/dist/cjs/providers/AnthropicProvider.js.map +1 -1
- package/dist/cjs/providers/DeepSeekProvider.d.ts +25 -21
- package/dist/cjs/providers/DeepSeekProvider.d.ts.map +1 -1
- package/dist/cjs/providers/DeepSeekProvider.js +48 -407
- package/dist/cjs/providers/DeepSeekProvider.js.map +1 -1
- package/dist/cjs/providers/GeminiProvider.d.ts +2 -0
- package/dist/cjs/providers/GeminiProvider.d.ts.map +1 -1
- package/dist/cjs/providers/GeminiProvider.js +27 -56
- package/dist/cjs/providers/GeminiProvider.js.map +1 -1
- package/dist/cjs/providers/OpenAICompatibleProvider.d.ts +129 -0
- package/dist/cjs/providers/OpenAICompatibleProvider.d.ts.map +1 -0
- package/dist/cjs/providers/OpenAICompatibleProvider.js +485 -0
- package/dist/cjs/providers/OpenAICompatibleProvider.js.map +1 -0
- package/dist/cjs/providers/OpenAIProvider.d.ts +9 -28
- package/dist/cjs/providers/OpenAIProvider.d.ts.map +1 -1
- package/dist/cjs/providers/OpenAIProvider.js +23 -417
- package/dist/cjs/providers/OpenAIProvider.js.map +1 -1
- package/dist/cjs/providers/OpenRouterProvider.d.ts +10 -27
- package/dist/cjs/providers/OpenRouterProvider.d.ts.map +1 -1
- package/dist/cjs/providers/OpenRouterProvider.js +28 -417
- package/dist/cjs/providers/OpenRouterProvider.js.map +1 -1
- package/dist/cjs/providers/errorClassification.d.ts +61 -0
- package/dist/cjs/providers/errorClassification.d.ts.map +1 -0
- package/dist/cjs/providers/errorClassification.js +123 -0
- package/dist/cjs/providers/errorClassification.js.map +1 -0
- package/dist/cjs/providers/index.d.ts +4 -0
- package/dist/cjs/providers/index.d.ts.map +1 -1
- package/dist/cjs/providers/index.js +7 -1
- package/dist/cjs/providers/index.js.map +1 -1
- package/dist/cjs/types/agent.d.ts +2 -1
- package/dist/cjs/types/agent.d.ts.map +1 -1
- package/dist/cjs/types/ai.d.ts +20 -0
- package/dist/cjs/types/ai.d.ts.map +1 -1
- package/dist/cjs/types/errors.d.ts +33 -0
- package/dist/cjs/types/errors.d.ts.map +1 -1
- package/dist/cjs/types/errors.js +37 -1
- package/dist/cjs/types/errors.js.map +1 -1
- package/dist/cjs/types/flow.d.ts +10 -5
- package/dist/cjs/types/flow.d.ts.map +1 -1
- package/dist/cjs/types/history.d.ts +1 -1
- package/dist/cjs/types/history.d.ts.map +1 -1
- package/dist/cjs/types/index.d.ts +5 -4
- package/dist/cjs/types/index.d.ts.map +1 -1
- package/dist/cjs/types/index.js +3 -1
- package/dist/cjs/types/index.js.map +1 -1
- package/dist/cjs/types/persistence.d.ts +43 -2
- package/dist/cjs/types/persistence.d.ts.map +1 -1
- package/dist/cjs/types/session.d.ts +8 -0
- package/dist/cjs/types/session.d.ts.map +1 -1
- package/dist/cjs/types/signals.d.ts +18 -2
- package/dist/cjs/types/signals.d.ts.map +1 -1
- package/dist/cjs/types/template.d.ts +3 -1
- package/dist/cjs/types/template.d.ts.map +1 -1
- package/dist/cjs/types/tool.d.ts +4 -4
- package/dist/cjs/types/tool.d.ts.map +1 -1
- package/dist/cjs/utils/condition.d.ts +19 -0
- package/dist/cjs/utils/condition.d.ts.map +1 -1
- package/dist/cjs/utils/condition.js +86 -15
- package/dist/cjs/utils/condition.js.map +1 -1
- package/dist/cjs/utils/session.d.ts +1 -0
- package/dist/cjs/utils/session.d.ts.map +1 -1
- package/dist/cjs/utils/session.js +1 -0
- package/dist/cjs/utils/session.js.map +1 -1
- package/dist/core/Agent.d.ts +28 -18
- package/dist/core/Agent.d.ts.map +1 -1
- package/dist/core/Agent.js +58 -68
- package/dist/core/Agent.js.map +1 -1
- package/dist/core/AutoChainExecutor.d.ts.map +1 -1
- package/dist/core/AutoChainExecutor.js +14 -20
- package/dist/core/AutoChainExecutor.js.map +1 -1
- package/dist/core/BranchEvaluator.d.ts +4 -3
- package/dist/core/BranchEvaluator.d.ts.map +1 -1
- package/dist/core/BranchEvaluator.js +18 -23
- package/dist/core/BranchEvaluator.js.map +1 -1
- package/dist/core/Flow.d.ts +2 -1
- package/dist/core/Flow.d.ts.map +1 -1
- package/dist/core/Flow.js +10 -3
- package/dist/core/Flow.js.map +1 -1
- package/dist/core/FlowRouter.d.ts +1 -0
- package/dist/core/FlowRouter.d.ts.map +1 -1
- package/dist/core/FlowRouter.js +28 -5
- package/dist/core/FlowRouter.js.map +1 -1
- package/dist/core/PersistenceManager.d.ts +3 -0
- package/dist/core/PersistenceManager.d.ts.map +1 -1
- package/dist/core/PersistenceManager.js +58 -6
- package/dist/core/PersistenceManager.js.map +1 -1
- package/dist/core/PromptComposer.d.ts.map +1 -1
- package/dist/core/PromptComposer.js +24 -10
- package/dist/core/PromptComposer.js.map +1 -1
- package/dist/core/ResponseGenerationError.d.ts +30 -0
- package/dist/core/ResponseGenerationError.d.ts.map +1 -0
- package/dist/core/ResponseGenerationError.js +33 -0
- package/dist/core/ResponseGenerationError.js.map +1 -0
- package/dist/core/ResponseModal.d.ts +43 -102
- package/dist/core/ResponseModal.d.ts.map +1 -1
- package/dist/core/ResponseModal.js +171 -1186
- package/dist/core/ResponseModal.js.map +1 -1
- package/dist/core/ResponsePipeline.d.ts +58 -152
- package/dist/core/ResponsePipeline.d.ts.map +1 -1
- package/dist/core/ResponsePipeline.js +409 -458
- package/dist/core/ResponsePipeline.js.map +1 -1
- package/dist/core/SessionFinalizer.d.ts +34 -0
- package/dist/core/SessionFinalizer.d.ts.map +1 -0
- package/dist/core/SessionFinalizer.js +57 -0
- package/dist/core/SessionFinalizer.js.map +1 -0
- package/dist/core/SessionManager.d.ts +1 -1
- package/dist/core/SessionManager.d.ts.map +1 -1
- package/dist/core/SessionManager.js +18 -7
- package/dist/core/SessionManager.js.map +1 -1
- package/dist/core/SignalCoordinator.d.ts +103 -0
- package/dist/core/SignalCoordinator.d.ts.map +1 -0
- package/dist/core/SignalCoordinator.js +203 -0
- package/dist/core/SignalCoordinator.js.map +1 -0
- package/dist/core/SignalEvaluator.d.ts +2 -2
- package/dist/core/SignalEvaluator.d.ts.map +1 -1
- package/dist/core/SignalEvaluator.js +11 -26
- package/dist/core/SignalEvaluator.js.map +1 -1
- package/dist/core/SignalProcessor.d.ts.map +1 -1
- package/dist/core/SignalProcessor.js +28 -11
- package/dist/core/SignalProcessor.js.map +1 -1
- package/dist/core/Step.d.ts +3 -1
- package/dist/core/Step.d.ts.map +1 -1
- package/dist/core/Step.js +10 -3
- package/dist/core/Step.js.map +1 -1
- package/dist/core/StepLifecycle.d.ts +33 -0
- package/dist/core/StepLifecycle.d.ts.map +1 -0
- package/dist/core/StepLifecycle.js +93 -0
- package/dist/core/StepLifecycle.js.map +1 -0
- package/dist/core/ToolLoopExecutor.d.ts +104 -0
- package/dist/core/ToolLoopExecutor.d.ts.map +1 -0
- package/dist/core/ToolLoopExecutor.js +387 -0
- package/dist/core/ToolLoopExecutor.js.map +1 -0
- package/dist/core/ToolManager.d.ts +1 -1
- package/dist/core/ToolManager.d.ts.map +1 -1
- package/dist/core/ToolManager.js.map +1 -1
- package/dist/index.d.ts +4 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/providers/AnthropicProvider.d.ts +2 -0
- package/dist/providers/AnthropicProvider.d.ts.map +1 -1
- package/dist/providers/AnthropicProvider.js +22 -50
- package/dist/providers/AnthropicProvider.js.map +1 -1
- package/dist/providers/DeepSeekProvider.d.ts +25 -21
- package/dist/providers/DeepSeekProvider.d.ts.map +1 -1
- package/dist/providers/DeepSeekProvider.js +49 -408
- package/dist/providers/DeepSeekProvider.js.map +1 -1
- package/dist/providers/GeminiProvider.d.ts +2 -0
- package/dist/providers/GeminiProvider.d.ts.map +1 -1
- package/dist/providers/GeminiProvider.js +21 -50
- package/dist/providers/GeminiProvider.js.map +1 -1
- package/dist/providers/OpenAICompatibleProvider.d.ts +129 -0
- package/dist/providers/OpenAICompatibleProvider.d.ts.map +1 -0
- package/dist/providers/OpenAICompatibleProvider.js +481 -0
- package/dist/providers/OpenAICompatibleProvider.js.map +1 -0
- package/dist/providers/OpenAIProvider.d.ts +9 -28
- package/dist/providers/OpenAIProvider.d.ts.map +1 -1
- package/dist/providers/OpenAIProvider.js +23 -417
- package/dist/providers/OpenAIProvider.js.map +1 -1
- package/dist/providers/OpenRouterProvider.d.ts +10 -27
- package/dist/providers/OpenRouterProvider.d.ts.map +1 -1
- package/dist/providers/OpenRouterProvider.js +28 -417
- package/dist/providers/OpenRouterProvider.js.map +1 -1
- package/dist/providers/errorClassification.d.ts +61 -0
- package/dist/providers/errorClassification.d.ts.map +1 -0
- package/dist/providers/errorClassification.js +116 -0
- package/dist/providers/errorClassification.js.map +1 -0
- package/dist/providers/index.d.ts +4 -0
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/index.js +2 -0
- package/dist/providers/index.js.map +1 -1
- package/dist/types/agent.d.ts +2 -1
- package/dist/types/agent.d.ts.map +1 -1
- package/dist/types/ai.d.ts +20 -0
- package/dist/types/ai.d.ts.map +1 -1
- package/dist/types/errors.d.ts +33 -0
- package/dist/types/errors.d.ts.map +1 -1
- package/dist/types/errors.js +34 -0
- package/dist/types/errors.js.map +1 -1
- package/dist/types/flow.d.ts +10 -5
- package/dist/types/flow.d.ts.map +1 -1
- package/dist/types/history.d.ts +1 -1
- package/dist/types/history.d.ts.map +1 -1
- package/dist/types/index.d.ts +5 -4
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +1 -1
- package/dist/types/index.js.map +1 -1
- package/dist/types/persistence.d.ts +43 -2
- package/dist/types/persistence.d.ts.map +1 -1
- package/dist/types/session.d.ts +8 -0
- package/dist/types/session.d.ts.map +1 -1
- package/dist/types/signals.d.ts +18 -2
- package/dist/types/signals.d.ts.map +1 -1
- package/dist/types/template.d.ts +3 -1
- package/dist/types/template.d.ts.map +1 -1
- package/dist/types/tool.d.ts +4 -4
- package/dist/types/tool.d.ts.map +1 -1
- package/dist/utils/condition.d.ts +19 -0
- package/dist/utils/condition.d.ts.map +1 -1
- package/dist/utils/condition.js +84 -15
- package/dist/utils/condition.js.map +1 -1
- package/dist/utils/session.d.ts +1 -0
- package/dist/utils/session.d.ts.map +1 -1
- package/dist/utils/session.js +1 -0
- package/dist/utils/session.js.map +1 -1
- package/docs/README.md +1 -1
- package/docs/guides/branching.md +1 -1
- package/docs/guides/compaction.md +12 -5
- package/docs/guides/conditions.md +15 -2
- package/docs/guides/error-handling.md +59 -9
- package/docs/guides/instructions.md +2 -2
- package/docs/guides/persistence.md +69 -2
- package/docs/guides/streaming.md +2 -0
- package/docs/migration/README.md +5 -1
- package/docs/migration/v2-3-to-v2-4.md +316 -0
- package/docs/reference/adapters.md +55 -7
- package/docs/reference/branches.md +2 -2
- package/docs/reference/create-agent.md +3 -3
- package/docs/reference/errors.md +66 -1
- package/docs/reference/flow.md +1 -1
- package/docs/reference/instruction.md +4 -4
- package/docs/reference/providers.md +100 -3
- package/docs/reference/signals.md +14 -3
- package/docs/reference/step.md +2 -2
- package/docs/reference/tool.md +3 -1
- package/docs/start/05-go-to-production.md +3 -0
- package/package.json +1 -1
- package/src/adapters/MemoryAdapter.ts +15 -1
- package/src/adapters/MongoAdapter.ts +41 -2
- package/src/adapters/OpenSearchAdapter.ts +24 -1
- package/src/adapters/PostgreSQLAdapter.ts +45 -5
- package/src/adapters/PrismaAdapter.ts +82 -16
- package/src/adapters/RedisAdapter.ts +19 -1
- package/src/adapters/SQLiteAdapter.ts +47 -5
- package/src/core/Agent.ts +70 -85
- package/src/core/AutoChainExecutor.ts +27 -57
- package/src/core/BranchEvaluator.ts +24 -30
- package/src/core/Flow.ts +10 -3
- package/src/core/FlowRouter.ts +36 -4
- package/src/core/PersistenceManager.ts +79 -10
- package/src/core/PromptComposer.ts +25 -12
- package/src/core/ResponseGenerationError.ts +56 -0
- package/src/core/ResponseModal.ts +233 -1482
- package/src/core/ResponsePipeline.ts +492 -662
- package/src/core/SessionFinalizer.ts +78 -0
- package/src/core/SessionManager.ts +21 -9
- package/src/core/SignalCoordinator.ts +263 -0
- package/src/core/SignalEvaluator.ts +12 -29
- package/src/core/SignalProcessor.ts +34 -11
- package/src/core/Step.ts +11 -3
- package/src/core/StepLifecycle.ts +139 -0
- package/src/core/ToolLoopExecutor.ts +492 -0
- package/src/core/ToolManager.ts +2 -1
- package/src/index.ts +7 -5
- package/src/providers/AnthropicProvider.ts +30 -72
- package/src/providers/DeepSeekProvider.ts +74 -586
- package/src/providers/GeminiProvider.ts +29 -70
- package/src/providers/OpenAICompatibleProvider.ts +738 -0
- package/src/providers/OpenAIProvider.ts +29 -602
- package/src/providers/OpenRouterProvider.ts +38 -596
- package/src/providers/errorClassification.ts +172 -0
- package/src/providers/index.ts +13 -0
- package/src/types/agent.ts +2 -1
- package/src/types/ai.ts +22 -0
- package/src/types/errors.ts +57 -0
- package/src/types/flow.ts +10 -5
- package/src/types/history.ts +1 -2
- package/src/types/index.ts +5 -1
- package/src/types/persistence.ts +50 -2
- package/src/types/session.ts +9 -0
- package/src/types/signals.ts +20 -2
- package/src/types/template.ts +3 -1
- package/src/types/tool.ts +10 -10
- package/src/utils/condition.ts +115 -18
- package/src/utils/session.ts +2 -0
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* StepLifecycle executes step `prepare` and `finalize` handlers.
|
|
3
|
+
*
|
|
4
|
+
* A handler may be a function, a registered tool id, or an inline tool.
|
|
5
|
+
* Used by the response prepare phase (prepare) and by SessionFinalizer
|
|
6
|
+
* (finalize).
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type { PrepareResult, SessionState, Tool } from "../types";
|
|
10
|
+
import type { Flow } from "./Flow";
|
|
11
|
+
import type { Step } from "./Step";
|
|
12
|
+
import type { ToolManager } from "./ToolManager";
|
|
13
|
+
import { logger } from "../utils";
|
|
14
|
+
|
|
15
|
+
export class StepLifecycle<TContext = unknown, TData = unknown> {
|
|
16
|
+
constructor(
|
|
17
|
+
private readonly deps: {
|
|
18
|
+
getFlows: () => Flow<TContext, TData>[];
|
|
19
|
+
toolManager: ToolManager<TContext, TData>;
|
|
20
|
+
updateContext: (updates: Partial<TContext>) => Promise<void>;
|
|
21
|
+
updateData: (updates: Partial<TData>) => Promise<void>;
|
|
22
|
+
}
|
|
23
|
+
) { }
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Execute prepare function for the session's current step if available.
|
|
27
|
+
* Auto-steps are skipped — their prepare is handled by AutoChainExecutor.
|
|
28
|
+
*/
|
|
29
|
+
async runPrepare(session: SessionState<TData>, context: TContext): Promise<void> {
|
|
30
|
+
if (session.currentFlow && session.currentStep) {
|
|
31
|
+
const currentFlow = this.deps.getFlows().find(
|
|
32
|
+
(r) => r.id === session.currentFlow?.id
|
|
33
|
+
);
|
|
34
|
+
if (currentFlow) {
|
|
35
|
+
const currentStep = currentFlow.getStep(session.currentStep.id);
|
|
36
|
+
// Skip auto-steps — their prepare is handled by AutoChainExecutor
|
|
37
|
+
if (currentStep?.auto) {
|
|
38
|
+
logger.debug(`[StepLifecycle] Skipping pre-routing prepare for auto-step: ${currentStep.id}`);
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
if (currentStep?.prepare) {
|
|
42
|
+
logger.debug(`[StepLifecycle] Executing prepare for step: ${currentStep.id}`);
|
|
43
|
+
await this.executePrepareFinalize(
|
|
44
|
+
currentStep.prepare,
|
|
45
|
+
context,
|
|
46
|
+
session.data,
|
|
47
|
+
currentFlow,
|
|
48
|
+
currentStep
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Execute finalize function for the session's current step if available.
|
|
57
|
+
*/
|
|
58
|
+
async runFinalize(session: SessionState<TData>, context: TContext): Promise<void> {
|
|
59
|
+
if (session.currentFlow && session.currentStep) {
|
|
60
|
+
const currentFlow = this.deps.getFlows().find(
|
|
61
|
+
(r) => r.id === session.currentFlow?.id
|
|
62
|
+
);
|
|
63
|
+
if (currentFlow) {
|
|
64
|
+
const currentStep = currentFlow.getStep(session.currentStep.id);
|
|
65
|
+
if (currentStep?.finalize) {
|
|
66
|
+
logger.debug(
|
|
67
|
+
`[StepLifecycle] Executing finalize for step: ${currentStep.id}`
|
|
68
|
+
);
|
|
69
|
+
await this.executePrepareFinalize(
|
|
70
|
+
currentStep.finalize,
|
|
71
|
+
context,
|
|
72
|
+
session.data,
|
|
73
|
+
currentFlow,
|
|
74
|
+
currentStep
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Execute a prepare or finalize function/tool.
|
|
83
|
+
*/
|
|
84
|
+
private async executePrepareFinalize(
|
|
85
|
+
prepareOrFinalize:
|
|
86
|
+
| string
|
|
87
|
+
| Tool<TContext, TData>
|
|
88
|
+
| ((context: TContext, data?: Partial<TData>) => void | PrepareResult | Promise<void | PrepareResult>)
|
|
89
|
+
| undefined,
|
|
90
|
+
context: TContext,
|
|
91
|
+
data?: Partial<TData>,
|
|
92
|
+
flow?: Flow<TContext, TData>,
|
|
93
|
+
step?: Step<TContext, TData>
|
|
94
|
+
): Promise<void> {
|
|
95
|
+
if (!prepareOrFinalize) return;
|
|
96
|
+
|
|
97
|
+
if (typeof prepareOrFinalize === "function") {
|
|
98
|
+
// It's a function - call it directly
|
|
99
|
+
await prepareOrFinalize(context, data);
|
|
100
|
+
} else {
|
|
101
|
+
// It's a tool reference - find and execute the tool
|
|
102
|
+
let tool: Tool<TContext, TData> | undefined;
|
|
103
|
+
|
|
104
|
+
if (typeof prepareOrFinalize === "string") {
|
|
105
|
+
// Tool ID - use ToolManager for unified resolution
|
|
106
|
+
tool = this.deps.toolManager.find(prepareOrFinalize, undefined, step, flow);
|
|
107
|
+
} else {
|
|
108
|
+
// Tool object - use directly
|
|
109
|
+
tool = prepareOrFinalize;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (tool) {
|
|
113
|
+
// Use ToolManager for unified tool execution
|
|
114
|
+
const result = await this.deps.toolManager.executeTool({
|
|
115
|
+
tool,
|
|
116
|
+
context,
|
|
117
|
+
updateContext: this.deps.updateContext,
|
|
118
|
+
updateData: this.deps.updateData,
|
|
119
|
+
history: [], // Empty history for prepare/finalize
|
|
120
|
+
data,
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
if (!result.success) {
|
|
124
|
+
logger.error(
|
|
125
|
+
`[StepLifecycle] Tool execution failed in prepare/finalize: ${result.error}`
|
|
126
|
+
);
|
|
127
|
+
throw new Error(`Tool execution failed: ${result.error}`);
|
|
128
|
+
}
|
|
129
|
+
} else {
|
|
130
|
+
logger.warn(
|
|
131
|
+
`[StepLifecycle] Tool not found for prepare/finalize: ${typeof prepareOrFinalize === "string"
|
|
132
|
+
? prepareOrFinalize
|
|
133
|
+
: "inline tool"
|
|
134
|
+
}`
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
@@ -0,0 +1,492 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ToolLoopExecutor owns dynamic tool execution during response generation:
|
|
3
|
+
*
|
|
4
|
+
* - `runLoop()` — the run-tools-then-ask-LLM-again follow-up loop used by the
|
|
5
|
+
* non-streaming path (and as the streaming fallback): executes the initial
|
|
6
|
+
* tool calls sequentially, asks the provider whether more tools are needed,
|
|
7
|
+
* reconstructs tool-result history items, and forces a final text response
|
|
8
|
+
* when tools ran but no message was produced.
|
|
9
|
+
* - `runStreamingBatch()` — the streaming path's initial batch execution via
|
|
10
|
+
* ToolManager.executeWithConcurrency (StreamingToolExecutor concurrency
|
|
11
|
+
* rules), yielding tool-progress chunks; falls back to `runLoop()` when
|
|
12
|
+
* concurrent execution fails.
|
|
13
|
+
*
|
|
14
|
+
* ToolManager remains the registry/resolver and single-tool executor.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import type {
|
|
18
|
+
AgentOptions,
|
|
19
|
+
AgentResponseStreamChunk,
|
|
20
|
+
AgentStructuredResponse,
|
|
21
|
+
HistoryItem,
|
|
22
|
+
SessionState,
|
|
23
|
+
ToolCallRequest,
|
|
24
|
+
} from "../types";
|
|
25
|
+
import type { Flow } from "./Flow";
|
|
26
|
+
import type { Step } from "./Step";
|
|
27
|
+
import type { ToolManager } from "./ToolManager";
|
|
28
|
+
import { ResponseGenerationError } from "./ResponseGenerationError";
|
|
29
|
+
import { historyToEvents, logger, serializeToolResult } from "../utils";
|
|
30
|
+
|
|
31
|
+
export class ToolLoopExecutor<TContext = unknown, TData = unknown> {
|
|
32
|
+
constructor(
|
|
33
|
+
private readonly deps: {
|
|
34
|
+
toolManager: ToolManager<TContext, TData>;
|
|
35
|
+
getAgentOptions: () => AgentOptions<TContext, TData>;
|
|
36
|
+
updateContext: (updates: Partial<TContext>) => Promise<void>;
|
|
37
|
+
updateCollectedData: (updates: Partial<TData>) => Promise<void>;
|
|
38
|
+
updateSessionData: (
|
|
39
|
+
session: SessionState<TData>,
|
|
40
|
+
dataUpdate: Partial<TData>
|
|
41
|
+
) => Promise<SessionState<TData>>;
|
|
42
|
+
/** Maximum number of tool loops (defaults to 5). */
|
|
43
|
+
maxToolLoops?: number;
|
|
44
|
+
}
|
|
45
|
+
) { }
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Unified tool execution logic with loop handling.
|
|
49
|
+
* Consolidates the complex tool execution logic from both streaming and
|
|
50
|
+
* non-streaming responses.
|
|
51
|
+
*/
|
|
52
|
+
async runLoop(params: {
|
|
53
|
+
toolCalls?: Array<{ toolName: string; arguments: Record<string, unknown> }>;
|
|
54
|
+
context: TContext;
|
|
55
|
+
session: SessionState<TData>;
|
|
56
|
+
history: HistoryItem[];
|
|
57
|
+
selectedFlow?: Flow<TContext, TData>;
|
|
58
|
+
responsePrompt: string;
|
|
59
|
+
availableTools: Array<{
|
|
60
|
+
id: string;
|
|
61
|
+
name: string;
|
|
62
|
+
description?: string;
|
|
63
|
+
parameters?: unknown;
|
|
64
|
+
}>;
|
|
65
|
+
responseSchema?: Record<string, unknown>;
|
|
66
|
+
signal?: AbortSignal;
|
|
67
|
+
}): Promise<{
|
|
68
|
+
session: SessionState<TData>;
|
|
69
|
+
finalToolCalls?: Array<{ toolName: string; arguments: Record<string, unknown> }>;
|
|
70
|
+
finalMessage?: string;
|
|
71
|
+
structured?: AgentStructuredResponse;
|
|
72
|
+
}> {
|
|
73
|
+
try {
|
|
74
|
+
const { context, history, selectedFlow, responsePrompt, availableTools, responseSchema, signal } = params;
|
|
75
|
+
let { toolCalls, session } = params;
|
|
76
|
+
|
|
77
|
+
// Convert HistoryItem[] to Event[] for internal processing
|
|
78
|
+
const historyEvents = historyToEvents(history);
|
|
79
|
+
|
|
80
|
+
// Map to store tool execution results for history
|
|
81
|
+
const toolResultsMap = new Map<string, string>();
|
|
82
|
+
// Map to store tool call arguments for history reconstruction
|
|
83
|
+
const toolArgsMap = new Map<string, Record<string, unknown>>();
|
|
84
|
+
|
|
85
|
+
// Execute initial dynamic tool calls
|
|
86
|
+
if (toolCalls && toolCalls.length > 0) {
|
|
87
|
+
logger.debug(`[ToolLoopExecutor] Executing ${toolCalls.length} dynamic tool calls:`, toolCalls.map(tc => tc.toolName));
|
|
88
|
+
|
|
89
|
+
for (const toolCall of toolCalls) {
|
|
90
|
+
const tool = this.findAvailableTool(toolCall.toolName, selectedFlow);
|
|
91
|
+
if (!tool) {
|
|
92
|
+
logger.warn(`[ToolExecutionError] Tool not found: "${toolCall.toolName}" is not registered in any scope. Skipping this tool call. Register the tool or check the tool name.`);
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
try {
|
|
97
|
+
// Use ToolManager for unified tool execution
|
|
98
|
+
const toolResult = await this.deps.toolManager.executeTool({
|
|
99
|
+
tool,
|
|
100
|
+
context,
|
|
101
|
+
updateContext: this.deps.updateContext,
|
|
102
|
+
updateData: this.deps.updateCollectedData,
|
|
103
|
+
history: historyEvents, // Use Event[] for tool execution
|
|
104
|
+
data: session.data,
|
|
105
|
+
toolArguments: toolCall.arguments,
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
// Store the actual tool result data for history
|
|
109
|
+
toolResultsMap.set(toolCall.toolName, serializeToolResult(toolResult));
|
|
110
|
+
toolArgsMap.set(toolCall.toolName, toolCall.arguments);
|
|
111
|
+
|
|
112
|
+
// Check if tool execution was successful
|
|
113
|
+
if (!toolResult.success) {
|
|
114
|
+
logger.error(`[ToolLoopExecutor] Tool execution failed: ${toolCall.toolName} - ${toolResult.error}`);
|
|
115
|
+
// Continue with other tools rather than failing completely
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Update context with tool results
|
|
120
|
+
if (toolResult.contextUpdate) {
|
|
121
|
+
try {
|
|
122
|
+
await this.deps.updateContext(toolResult.contextUpdate as Partial<TContext>);
|
|
123
|
+
} catch (error) {
|
|
124
|
+
logger.error(`[ToolLoopExecutor] Failed to update context from tool ${toolCall.toolName}:`, error);
|
|
125
|
+
// Continue execution but log the error
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Update collected data with tool results
|
|
130
|
+
if (toolResult.dataUpdate) {
|
|
131
|
+
try {
|
|
132
|
+
session = await this.deps.updateSessionData(session, toolResult.dataUpdate as Partial<TData>);
|
|
133
|
+
logger.debug(`[ToolLoopExecutor] Tool updated collected data:`, toolResult.dataUpdate);
|
|
134
|
+
} catch (error) {
|
|
135
|
+
logger.error(`[ToolLoopExecutor] Failed to update data from tool ${toolCall.toolName}:`, error);
|
|
136
|
+
// Continue execution but log the error
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
logger.debug(`[ToolLoopExecutor] Executed dynamic tool: ${toolCall.toolName} (success: ${toolResult.success})`);
|
|
141
|
+
} catch (error) {
|
|
142
|
+
logger.error(`[ToolLoopExecutor] Tool execution error for ${toolCall.toolName}:`, error);
|
|
143
|
+
// Continue with other tools rather than failing the entire response
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// TOOL LOOP: Allow AI to make follow-up tool calls after initial tool execution
|
|
150
|
+
const MAX_TOOL_LOOPS = this.deps.maxToolLoops || 5;
|
|
151
|
+
let toolLoopCount = 0;
|
|
152
|
+
let hasToolCalls = toolCalls && toolCalls.length > 0;
|
|
153
|
+
let finalMessage: string | undefined;
|
|
154
|
+
let followUpStructured: AgentStructuredResponse | undefined;
|
|
155
|
+
|
|
156
|
+
while (hasToolCalls && toolLoopCount < MAX_TOOL_LOOPS) {
|
|
157
|
+
toolLoopCount++;
|
|
158
|
+
logger.debug(`[ToolLoopExecutor] Starting tool loop ${toolLoopCount}/${MAX_TOOL_LOOPS} with ${toolCalls?.length || 0} tool calls`);
|
|
159
|
+
|
|
160
|
+
// Create tool result history items
|
|
161
|
+
const toolResultHistoryItems: HistoryItem[] = [];
|
|
162
|
+
for (const toolCall of toolCalls || []) {
|
|
163
|
+
const tool = this.findAvailableTool(toolCall.toolName, selectedFlow);
|
|
164
|
+
if (tool) {
|
|
165
|
+
// Create HistoryItem format for tool results
|
|
166
|
+
// Add assistant message with tool_calls
|
|
167
|
+
toolResultHistoryItems.push({
|
|
168
|
+
role: "assistant" as const,
|
|
169
|
+
content: null,
|
|
170
|
+
tool_calls: [{
|
|
171
|
+
id: toolCall.toolName,
|
|
172
|
+
name: toolCall.toolName,
|
|
173
|
+
arguments: toolCall.arguments,
|
|
174
|
+
}],
|
|
175
|
+
});
|
|
176
|
+
// Add tool result
|
|
177
|
+
toolResultHistoryItems.push({
|
|
178
|
+
role: "tool" as const,
|
|
179
|
+
tool_call_id: toolCall.toolName,
|
|
180
|
+
name: toolCall.toolName,
|
|
181
|
+
content: toolResultsMap.get(toolCall.toolName) || "Tool executed successfully",
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Create updated history with tool results
|
|
187
|
+
const updatedHistory = [...history, ...toolResultHistoryItems];
|
|
188
|
+
|
|
189
|
+
// Make follow-up AI call to see if more tools are needed
|
|
190
|
+
// After first iteration, don't provide tools to force a text response
|
|
191
|
+
const agentOptions = this.deps.getAgentOptions();
|
|
192
|
+
const shouldProvideTools = toolLoopCount === 1;
|
|
193
|
+
|
|
194
|
+
logger.debug(`[ToolLoopExecutor] Making follow-up AI call (loop ${toolLoopCount}):`, {
|
|
195
|
+
providingTools: shouldProvideTools,
|
|
196
|
+
toolsCount: shouldProvideTools ? availableTools.length : 0,
|
|
197
|
+
addingTextInstruction: toolLoopCount > 1,
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
const followUpResult = await agentOptions.provider.generateMessage({
|
|
201
|
+
prompt: responsePrompt + (toolLoopCount > 1 ? "\n\nProvide a text response to the user based on the tool results." : ""),
|
|
202
|
+
history: updatedHistory, // Use HistoryItem[] for AI provider
|
|
203
|
+
context,
|
|
204
|
+
tools: shouldProvideTools ? availableTools : [], // Only provide tools on first iteration
|
|
205
|
+
parameters: responseSchema ? {
|
|
206
|
+
jsonSchema: responseSchema,
|
|
207
|
+
schemaName: "tool_followup",
|
|
208
|
+
} : undefined,
|
|
209
|
+
signal,
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
// Check if follow-up call has more tool calls
|
|
213
|
+
const followUpToolCalls = followUpResult.structured?.toolCalls;
|
|
214
|
+
hasToolCalls = followUpToolCalls && followUpToolCalls.length > 0;
|
|
215
|
+
|
|
216
|
+
logger.debug(`[ToolLoopExecutor] Follow-up AI response (loop ${toolLoopCount}):`, {
|
|
217
|
+
hasMessage: !!followUpResult.message,
|
|
218
|
+
messageLength: followUpResult.message?.length || 0,
|
|
219
|
+
hasToolCalls,
|
|
220
|
+
toolCallsCount: followUpToolCalls?.length || 0,
|
|
221
|
+
toolNames: followUpToolCalls?.map(tc => tc.toolName) || [],
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
if (hasToolCalls) {
|
|
225
|
+
logger.debug(`[ToolLoopExecutor] Follow-up call produced ${followUpToolCalls!.length} additional tool calls`);
|
|
226
|
+
|
|
227
|
+
// Execute the follow-up tool calls
|
|
228
|
+
for (const toolCall of followUpToolCalls!) {
|
|
229
|
+
const tool = this.findAvailableTool(toolCall.toolName, selectedFlow);
|
|
230
|
+
if (!tool) {
|
|
231
|
+
logger.warn(`[ToolExecutionError] Tool not found in follow-up: "${toolCall.toolName}" is not registered in any scope. Skipping this tool call. Register the tool or check the tool name.`);
|
|
232
|
+
continue;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
try {
|
|
236
|
+
// Use ToolManager for unified tool execution
|
|
237
|
+
const toolResult = await this.deps.toolManager.executeTool({
|
|
238
|
+
tool,
|
|
239
|
+
context,
|
|
240
|
+
updateContext: this.deps.updateContext,
|
|
241
|
+
updateData: this.deps.updateCollectedData,
|
|
242
|
+
history: historyToEvents(updatedHistory), // Convert to Event[] for tool execution
|
|
243
|
+
data: session.data,
|
|
244
|
+
toolArguments: toolCall.arguments,
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
// Check if tool execution was successful
|
|
248
|
+
if (!toolResult.success) {
|
|
249
|
+
logger.error(`[ToolLoopExecutor] Follow-up tool execution failed: ${toolCall.toolName} - ${toolResult.error}`);
|
|
250
|
+
continue;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// Update context with follow-up tool results
|
|
254
|
+
if (toolResult.contextUpdate) {
|
|
255
|
+
try {
|
|
256
|
+
await this.deps.updateContext(toolResult.contextUpdate as Partial<TContext>);
|
|
257
|
+
} catch (error) {
|
|
258
|
+
logger.error(`[ToolLoopExecutor] Failed to update context from follow-up tool ${toolCall.toolName}:`, error);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
if (toolResult.dataUpdate) {
|
|
263
|
+
try {
|
|
264
|
+
session = await this.deps.updateSessionData(session, toolResult.dataUpdate as Partial<TData>);
|
|
265
|
+
logger.debug(`[ToolLoopExecutor] Follow-up tool updated collected data:`, toolResult.dataUpdate);
|
|
266
|
+
} catch (error) {
|
|
267
|
+
logger.error(`[ToolLoopExecutor] Failed to update data from follow-up tool ${toolCall.toolName}:`, error);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// Store the follow-up tool result for potential next loop iteration
|
|
272
|
+
toolResultsMap.set(toolCall.toolName, serializeToolResult(toolResult));
|
|
273
|
+
toolArgsMap.set(toolCall.toolName, toolCall.arguments);
|
|
274
|
+
|
|
275
|
+
logger.debug(`[ToolLoopExecutor] Executed follow-up tool: ${toolCall.toolName} (success: ${toolResult.success})`);
|
|
276
|
+
} catch (error) {
|
|
277
|
+
logger.error(`[ToolLoopExecutor] Follow-up tool execution error for ${toolCall.toolName}:`, error);
|
|
278
|
+
continue;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// Update toolCalls for next iteration or final response
|
|
283
|
+
toolCalls = followUpToolCalls;
|
|
284
|
+
} else {
|
|
285
|
+
logger.debug(`[ToolLoopExecutor] Tool loop completed after ${toolLoopCount} iterations`);
|
|
286
|
+
// Update final message and toolCalls from follow-up result if no more tools
|
|
287
|
+
finalMessage = followUpResult.structured?.message || followUpResult.message;
|
|
288
|
+
followUpStructured = followUpResult.structured;
|
|
289
|
+
toolCalls = followUpToolCalls || [];
|
|
290
|
+
break;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
if (toolLoopCount >= MAX_TOOL_LOOPS) {
|
|
295
|
+
logger.warn(`[ResponseGenerationError] Tool loop limit reached: ${toolLoopCount} iterations hit the cap (${MAX_TOOL_LOOPS}). Stopping tool execution. Increase MAX_TOOL_LOOPS or reduce recursive tool calls.`);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// If tools were executed but no final text message was produced,
|
|
299
|
+
// make one more LLM call to generate a proper text response from tool results.
|
|
300
|
+
// This prevents the original tool-invocation message (e.g. "Let me check...")
|
|
301
|
+
// from being returned as the final user-facing response.
|
|
302
|
+
if (!finalMessage && toolLoopCount > 0) {
|
|
303
|
+
logger.debug(`[ToolLoopExecutor] No final message after tool loop, making additional LLM call for text response`);
|
|
304
|
+
|
|
305
|
+
// Build tool result history from toolResultsMap which contains ALL
|
|
306
|
+
// tool executions (initial + follow-up). We can't use `toolCalls` here
|
|
307
|
+
// because it was reassigned to the (empty) follow-up tool calls when
|
|
308
|
+
// the while loop broke out.
|
|
309
|
+
const finalToolResultHistoryItems: HistoryItem[] = [];
|
|
310
|
+
for (const [toolName, toolResult] of toolResultsMap) {
|
|
311
|
+
finalToolResultHistoryItems.push({
|
|
312
|
+
role: "assistant" as const,
|
|
313
|
+
content: null,
|
|
314
|
+
tool_calls: [{
|
|
315
|
+
id: toolName,
|
|
316
|
+
name: toolName,
|
|
317
|
+
arguments: toolArgsMap.get(toolName) || {},
|
|
318
|
+
}],
|
|
319
|
+
});
|
|
320
|
+
finalToolResultHistoryItems.push({
|
|
321
|
+
role: "tool" as const,
|
|
322
|
+
tool_call_id: toolName,
|
|
323
|
+
name: toolName,
|
|
324
|
+
content: toolResult,
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
const finalHistory = [...history, ...finalToolResultHistoryItems];
|
|
329
|
+
const agentOptions = this.deps.getAgentOptions();
|
|
330
|
+
|
|
331
|
+
try {
|
|
332
|
+
const textResult = await agentOptions.provider.generateMessage({
|
|
333
|
+
prompt: responsePrompt + "\n\nProvide a text response to the user based on the tool results. Do not call any tools.",
|
|
334
|
+
history: finalHistory,
|
|
335
|
+
context,
|
|
336
|
+
tools: [], // No tools - force text response
|
|
337
|
+
parameters: responseSchema ? {
|
|
338
|
+
jsonSchema: responseSchema,
|
|
339
|
+
schemaName: "tool_final_text",
|
|
340
|
+
} : undefined,
|
|
341
|
+
signal,
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
finalMessage = textResult.structured?.message || textResult.message;
|
|
345
|
+
if (textResult.structured) {
|
|
346
|
+
followUpStructured = textResult.structured;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
logger.debug(`[ToolLoopExecutor] Generated final text response after tool loop:`, {
|
|
350
|
+
hasMessage: !!finalMessage,
|
|
351
|
+
messageLength: finalMessage?.length || 0,
|
|
352
|
+
});
|
|
353
|
+
} catch (error) {
|
|
354
|
+
logger.error(`[ToolLoopExecutor] Failed to generate final text response after tool loop:`, error);
|
|
355
|
+
// finalMessage remains undefined; caller will use original message as fallback
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
logger.debug(`[ToolLoopExecutor] Tool loop completed:`, {
|
|
360
|
+
totalIterations: toolLoopCount,
|
|
361
|
+
hasFinalMessage: !!finalMessage,
|
|
362
|
+
finalMessageLength: finalMessage?.length || 0,
|
|
363
|
+
finalToolCallsCount: toolCalls?.length || 0,
|
|
364
|
+
});
|
|
365
|
+
|
|
366
|
+
return {
|
|
367
|
+
session,
|
|
368
|
+
finalToolCalls: toolCalls,
|
|
369
|
+
finalMessage,
|
|
370
|
+
structured: followUpStructured,
|
|
371
|
+
};
|
|
372
|
+
} catch (error) {
|
|
373
|
+
throw ResponseGenerationError.fromError(error, 'tool_execution', params, {
|
|
374
|
+
toolCallsCount: params.toolCalls?.length || 0,
|
|
375
|
+
availableToolsCount: params.availableTools.length
|
|
376
|
+
});
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
/**
|
|
381
|
+
* Execute the streaming path's initial batch of tool calls concurrently
|
|
382
|
+
* via ToolManager.executeWithConcurrency, yielding tool-progress chunks.
|
|
383
|
+
* Falls back to `runLoop()` when concurrent execution fails.
|
|
384
|
+
*
|
|
385
|
+
* Returns the updated session and the final tool calls.
|
|
386
|
+
*/
|
|
387
|
+
async *runStreamingBatch(params: {
|
|
388
|
+
toolCalls: Array<{ toolName: string; arguments: Record<string, unknown> }>;
|
|
389
|
+
context: TContext;
|
|
390
|
+
session: SessionState<TData>;
|
|
391
|
+
history: HistoryItem[];
|
|
392
|
+
selectedFlow: Flow<TContext, TData>;
|
|
393
|
+
step: Step<TContext, TData>;
|
|
394
|
+
/** Accumulated text of the LLM's final chunk, echoed on progress chunks. */
|
|
395
|
+
accumulated: string;
|
|
396
|
+
responsePrompt: string;
|
|
397
|
+
availableTools: Array<{
|
|
398
|
+
id: string;
|
|
399
|
+
name: string;
|
|
400
|
+
description?: string;
|
|
401
|
+
parameters?: unknown;
|
|
402
|
+
}>;
|
|
403
|
+
responseSchema?: Record<string, unknown>;
|
|
404
|
+
signal?: AbortSignal;
|
|
405
|
+
}): AsyncGenerator<
|
|
406
|
+
AgentResponseStreamChunk<TData>,
|
|
407
|
+
{
|
|
408
|
+
session: SessionState<TData>;
|
|
409
|
+
toolCalls: Array<{ toolName: string; arguments: Record<string, unknown> }> | undefined;
|
|
410
|
+
}
|
|
411
|
+
> {
|
|
412
|
+
const { context, history, selectedFlow, step, accumulated, responsePrompt, availableTools, responseSchema, signal } = params;
|
|
413
|
+
let { session } = params;
|
|
414
|
+
let toolCalls: Array<{ toolName: string; arguments: Record<string, unknown> }> | undefined = params.toolCalls;
|
|
415
|
+
|
|
416
|
+
// Use concurrent execution for the initial batch of tool calls
|
|
417
|
+
const toolCallRequests: ToolCallRequest[] = params.toolCalls.map((tc, i) => ({
|
|
418
|
+
id: `${tc.toolName}-${i}-${Date.now()}`,
|
|
419
|
+
toolName: tc.toolName,
|
|
420
|
+
arguments: tc.arguments,
|
|
421
|
+
}));
|
|
422
|
+
|
|
423
|
+
const historyEvents = historyToEvents(history);
|
|
424
|
+
|
|
425
|
+
try {
|
|
426
|
+
for await (const update of this.deps.toolManager.executeWithConcurrency({
|
|
427
|
+
toolCalls: toolCallRequests,
|
|
428
|
+
context,
|
|
429
|
+
data: session.data,
|
|
430
|
+
history: historyEvents,
|
|
431
|
+
signal,
|
|
432
|
+
flow: selectedFlow,
|
|
433
|
+
step,
|
|
434
|
+
})) {
|
|
435
|
+
// Apply context updates
|
|
436
|
+
if (update.contextUpdate) {
|
|
437
|
+
try {
|
|
438
|
+
await this.deps.updateContext(update.contextUpdate as Partial<TContext>);
|
|
439
|
+
} catch (error) {
|
|
440
|
+
logger.error(`[ToolLoopExecutor] Failed to update context from concurrent tool:`, error);
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
// Apply data updates
|
|
445
|
+
if (update.dataUpdate) {
|
|
446
|
+
try {
|
|
447
|
+
session = await this.deps.updateSessionData(session, update.dataUpdate);
|
|
448
|
+
} catch (error) {
|
|
449
|
+
logger.error(`[ToolLoopExecutor] Failed to update data from concurrent tool:`, error);
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
// Yield progress updates immediately
|
|
454
|
+
if (update.progress) {
|
|
455
|
+
yield {
|
|
456
|
+
delta: '',
|
|
457
|
+
accumulated,
|
|
458
|
+
done: false,
|
|
459
|
+
session,
|
|
460
|
+
toolCalls: undefined,
|
|
461
|
+
isFlowComplete: false,
|
|
462
|
+
metadata: { toolProgress: update.progress, toolCallId: update.toolCallId },
|
|
463
|
+
};
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
logger.debug(`[ToolLoopExecutor] Concurrent tool execution completed for ${toolCallRequests.length} tools`);
|
|
468
|
+
} catch (error) {
|
|
469
|
+
logger.error(`[ToolLoopExecutor] Concurrent tool execution failed, falling back to sequential:`, error);
|
|
470
|
+
// Fall back to the unified tool loop on failure
|
|
471
|
+
const toolResult = await this.runLoop({
|
|
472
|
+
toolCalls, context, session, history, selectedFlow,
|
|
473
|
+
responsePrompt, availableTools, responseSchema, signal,
|
|
474
|
+
});
|
|
475
|
+
session = toolResult.session;
|
|
476
|
+
toolCalls = toolResult.finalToolCalls;
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
return { session, toolCalls };
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
/**
|
|
483
|
+
* Find an available tool by name for the given flow.
|
|
484
|
+
* Delegates to ToolManager for unified tool resolution.
|
|
485
|
+
*/
|
|
486
|
+
private findAvailableTool(
|
|
487
|
+
toolName: string,
|
|
488
|
+
flow?: Flow<TContext, TData>
|
|
489
|
+
) {
|
|
490
|
+
return this.deps.toolManager.find(toolName, undefined, undefined, flow);
|
|
491
|
+
}
|
|
492
|
+
}
|
package/src/core/ToolManager.ts
CHANGED
|
@@ -19,7 +19,8 @@ import type {
|
|
|
19
19
|
import type { Directive } from "../types/flow";
|
|
20
20
|
import { ToolScope } from "../types";
|
|
21
21
|
import { logger } from "../utils";
|
|
22
|
-
import
|
|
22
|
+
// Type-only import: ToolManager must not create a runtime cycle with Agent
|
|
23
|
+
import type { Agent } from "./Agent";
|
|
23
24
|
import { Flow } from "./Flow";
|
|
24
25
|
import { Step } from "./Step";
|
|
25
26
|
import { StreamingToolExecutor } from "./StreamingToolExecutor";
|