@falai/agent 0.9.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +304 -72
- package/dist/adapters/MemoryAdapter.d.ts.map +1 -0
- package/dist/adapters/MemoryAdapter.js.map +1 -0
- package/dist/adapters/MongoAdapter.d.ts.map +1 -0
- package/dist/adapters/MongoAdapter.js.map +1 -0
- package/dist/adapters/OpenSearchAdapter.d.ts.map +1 -0
- package/dist/adapters/OpenSearchAdapter.js.map +1 -0
- package/dist/adapters/PostgreSQLAdapter.d.ts.map +1 -0
- package/dist/adapters/PostgreSQLAdapter.js.map +1 -0
- package/dist/adapters/PrismaAdapter.d.ts.map +1 -0
- package/dist/{src/adapters → adapters}/PrismaAdapter.js +3 -2
- package/dist/adapters/PrismaAdapter.js.map +1 -0
- package/dist/adapters/RedisAdapter.d.ts.map +1 -0
- package/dist/{src/adapters → adapters}/RedisAdapter.js +3 -3
- package/dist/adapters/RedisAdapter.js.map +1 -0
- package/dist/adapters/SQLiteAdapter.d.ts.map +1 -0
- package/dist/adapters/SQLiteAdapter.js.map +1 -0
- package/dist/adapters/index.d.ts.map +1 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/cjs/adapters/MemoryAdapter.js.map +1 -0
- package/dist/cjs/adapters/MongoAdapter.js.map +1 -0
- package/dist/cjs/adapters/OpenSearchAdapter.js.map +1 -0
- package/dist/cjs/adapters/PostgreSQLAdapter.js.map +1 -0
- package/dist/{src → cjs}/adapters/PrismaAdapter.d.ts.map +1 -1
- package/dist/cjs/{src/adapters → adapters}/PrismaAdapter.js +3 -2
- package/dist/cjs/adapters/PrismaAdapter.js.map +1 -0
- package/dist/cjs/{src/adapters → adapters}/RedisAdapter.js +2 -2
- package/dist/cjs/adapters/RedisAdapter.js.map +1 -0
- package/dist/cjs/adapters/SQLiteAdapter.js.map +1 -0
- package/dist/cjs/adapters/index.js.map +1 -0
- package/dist/cjs/constants/index.js.map +1 -0
- package/dist/{src → cjs}/core/Agent.d.ts +25 -6
- package/dist/cjs/core/Agent.d.ts.map +1 -0
- package/dist/cjs/{src/core → core}/Agent.js +121 -37
- package/dist/cjs/core/Agent.js.map +1 -0
- package/dist/cjs/core/BatchExecutor.d.ts +353 -0
- package/dist/cjs/core/BatchExecutor.d.ts.map +1 -0
- package/dist/cjs/core/BatchExecutor.js +842 -0
- package/dist/cjs/core/BatchExecutor.js.map +1 -0
- package/dist/cjs/core/BatchPromptBuilder.d.ts +86 -0
- package/dist/cjs/core/BatchPromptBuilder.d.ts.map +1 -0
- package/dist/cjs/core/BatchPromptBuilder.js +201 -0
- package/dist/cjs/core/BatchPromptBuilder.js.map +1 -0
- package/dist/cjs/core/Events.js.map +1 -0
- package/dist/cjs/core/PersistenceManager.js.map +1 -0
- package/dist/{src → cjs}/core/PromptComposer.d.ts +1 -1
- package/dist/cjs/core/PromptComposer.d.ts.map +1 -0
- package/dist/cjs/{src/core → core}/PromptComposer.js +44 -7
- package/dist/cjs/core/PromptComposer.js.map +1 -0
- package/dist/{src → cjs}/core/ResponseEngine.d.ts.map +1 -1
- package/dist/cjs/core/ResponseEngine.js +202 -0
- package/dist/cjs/core/ResponseEngine.js.map +1 -0
- package/dist/{src → cjs}/core/ResponseModal.d.ts +54 -3
- package/dist/cjs/core/ResponseModal.d.ts.map +1 -0
- package/dist/cjs/{src/core → core}/ResponseModal.js +807 -121
- package/dist/cjs/core/ResponseModal.js.map +1 -0
- package/dist/{src → cjs}/core/ResponsePipeline.d.ts +10 -6
- package/dist/cjs/core/ResponsePipeline.d.ts.map +1 -0
- package/dist/cjs/{src/core → core}/ResponsePipeline.js +60 -25
- package/dist/cjs/core/ResponsePipeline.js.map +1 -0
- package/dist/{src → cjs}/core/Route.d.ts +46 -10
- package/dist/cjs/core/Route.d.ts.map +1 -0
- package/dist/cjs/core/Route.js +541 -0
- package/dist/cjs/core/Route.js.map +1 -0
- package/dist/cjs/{src/core → core}/RoutingEngine.d.ts +35 -5
- package/dist/cjs/core/RoutingEngine.d.ts.map +1 -0
- package/dist/cjs/{src/core → core}/RoutingEngine.js +360 -98
- package/dist/cjs/core/RoutingEngine.js.map +1 -0
- package/dist/{src → cjs}/core/SessionManager.d.ts +9 -1
- package/dist/cjs/core/SessionManager.d.ts.map +1 -0
- package/dist/cjs/{src/core → core}/SessionManager.js +27 -5
- package/dist/cjs/core/SessionManager.js.map +1 -0
- package/dist/cjs/core/Step.d.ts +170 -0
- package/dist/cjs/core/Step.d.ts.map +1 -0
- package/dist/cjs/core/Step.js +448 -0
- package/dist/cjs/core/Step.js.map +1 -0
- package/dist/cjs/core/ToolManager.d.ts +234 -0
- package/dist/cjs/core/ToolManager.d.ts.map +1 -0
- package/dist/cjs/core/ToolManager.js +1117 -0
- package/dist/cjs/core/ToolManager.js.map +1 -0
- package/dist/{src → cjs}/index.d.ts +5 -3
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/{src/index.js → index.js} +16 -3
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/{src/providers → providers}/AnthropicProvider.js +18 -18
- package/dist/cjs/providers/AnthropicProvider.js.map +1 -0
- package/dist/{src → cjs}/providers/GeminiProvider.d.ts.map +1 -1
- package/dist/cjs/{src/providers → providers}/GeminiProvider.js +123 -51
- package/dist/cjs/providers/GeminiProvider.js.map +1 -0
- package/dist/cjs/{src/providers → providers}/OpenAIProvider.js +19 -19
- package/dist/cjs/providers/OpenAIProvider.js.map +1 -0
- package/dist/cjs/{src/providers → providers}/OpenRouterProvider.js +19 -19
- package/dist/cjs/providers/OpenRouterProvider.js.map +1 -0
- package/dist/cjs/providers/index.js.map +1 -0
- package/dist/cjs/{src/types → types}/agent.d.ts +12 -4
- package/dist/cjs/types/agent.d.ts.map +1 -0
- package/dist/cjs/types/agent.js.map +1 -0
- package/dist/{src → cjs}/types/ai.js.map +1 -1
- package/dist/cjs/types/history.js.map +1 -0
- package/dist/cjs/{src/types → types}/index.d.ts +5 -3
- package/dist/{src → cjs}/types/index.d.ts.map +1 -1
- package/dist/cjs/{src/types → types}/index.js +8 -1
- package/dist/cjs/types/index.js.map +1 -0
- package/dist/cjs/types/persistence.js.map +1 -0
- package/dist/cjs/{src/types → types}/route.d.ts +116 -15
- package/dist/cjs/types/route.d.ts.map +1 -0
- package/dist/cjs/{src/types → types}/route.js.map +1 -1
- package/dist/cjs/types/session.js.map +1 -0
- package/dist/cjs/types/template.d.ts +88 -0
- package/dist/cjs/types/template.d.ts.map +1 -0
- package/dist/cjs/types/tool.d.ts +130 -0
- package/dist/cjs/types/tool.d.ts.map +1 -0
- package/dist/cjs/types/tool.js +19 -0
- package/dist/cjs/types/tool.js.map +1 -0
- package/dist/cjs/utils/clone.js.map +1 -0
- package/dist/cjs/utils/condition.d.ts +38 -0
- package/dist/cjs/utils/condition.d.ts.map +1 -0
- package/dist/cjs/utils/condition.js +168 -0
- package/dist/cjs/utils/condition.js.map +1 -0
- package/dist/cjs/utils/event.js.map +1 -0
- package/dist/cjs/utils/history.js.map +1 -0
- package/dist/cjs/utils/id.js.map +1 -0
- package/dist/cjs/{src/utils → utils}/index.d.ts +3 -1
- package/dist/cjs/utils/index.d.ts.map +1 -0
- package/dist/cjs/{src/utils → utils}/index.js +12 -1
- package/dist/cjs/utils/index.js.map +1 -0
- package/dist/cjs/utils/json.d.ts +16 -0
- package/dist/cjs/utils/json.d.ts.map +1 -0
- package/dist/cjs/utils/json.js +47 -0
- package/dist/cjs/utils/json.js.map +1 -0
- package/dist/cjs/utils/logger.js.map +1 -0
- package/dist/{src → cjs}/utils/retry.d.ts +0 -3
- package/dist/cjs/utils/retry.d.ts.map +1 -0
- package/dist/cjs/{src/utils → utils}/retry.js +8 -7
- package/dist/cjs/utils/retry.js.map +1 -0
- package/dist/cjs/utils/session.js.map +1 -0
- package/dist/{src → cjs}/utils/template.d.ts +48 -0
- package/dist/cjs/utils/template.d.ts.map +1 -0
- package/dist/cjs/{src/utils → utils}/template.js +100 -0
- package/dist/cjs/utils/template.js.map +1 -0
- package/dist/constants/index.d.ts.map +1 -0
- package/dist/constants/index.js.map +1 -0
- package/dist/{cjs/src/core → core}/Agent.d.ts +25 -6
- package/dist/core/Agent.d.ts.map +1 -0
- package/dist/{src/core → core}/Agent.js +122 -38
- package/dist/core/Agent.js.map +1 -0
- package/dist/core/BatchExecutor.d.ts +353 -0
- package/dist/core/BatchExecutor.d.ts.map +1 -0
- package/dist/core/BatchExecutor.js +837 -0
- package/dist/core/BatchExecutor.js.map +1 -0
- package/dist/core/BatchPromptBuilder.d.ts +86 -0
- package/dist/core/BatchPromptBuilder.d.ts.map +1 -0
- package/dist/core/BatchPromptBuilder.js +197 -0
- package/dist/core/BatchPromptBuilder.js.map +1 -0
- package/dist/core/Events.d.ts.map +1 -0
- package/dist/core/Events.js.map +1 -0
- package/dist/core/PersistenceManager.d.ts.map +1 -0
- package/dist/core/PersistenceManager.js.map +1 -0
- package/dist/{cjs/src/core → core}/PromptComposer.d.ts +1 -1
- package/dist/core/PromptComposer.d.ts.map +1 -0
- package/dist/{src/core → core}/PromptComposer.js +45 -8
- package/dist/core/PromptComposer.js.map +1 -0
- package/dist/core/ResponseEngine.d.ts.map +1 -0
- package/dist/core/ResponseEngine.js +198 -0
- package/dist/core/ResponseEngine.js.map +1 -0
- package/dist/{cjs/src/core → core}/ResponseModal.d.ts +54 -3
- package/dist/core/ResponseModal.d.ts.map +1 -0
- package/dist/{src/core → core}/ResponseModal.js +807 -121
- package/dist/core/ResponseModal.js.map +1 -0
- package/dist/{cjs/src/core → core}/ResponsePipeline.d.ts +10 -6
- package/dist/core/ResponsePipeline.d.ts.map +1 -0
- package/dist/{src/core → core}/ResponsePipeline.js +60 -25
- package/dist/core/ResponsePipeline.js.map +1 -0
- package/dist/{cjs/src/core → core}/Route.d.ts +46 -10
- package/dist/core/Route.d.ts.map +1 -0
- package/dist/core/Route.js +537 -0
- package/dist/core/Route.js.map +1 -0
- package/dist/{src/core → core}/RoutingEngine.d.ts +35 -5
- package/dist/core/RoutingEngine.d.ts.map +1 -0
- package/dist/{src/core → core}/RoutingEngine.js +343 -81
- package/dist/core/RoutingEngine.js.map +1 -0
- package/dist/{cjs/src/core → core}/SessionManager.d.ts +9 -1
- package/dist/core/SessionManager.d.ts.map +1 -0
- package/dist/{src/core → core}/SessionManager.js +27 -5
- package/dist/core/SessionManager.js.map +1 -0
- package/dist/core/Step.d.ts +170 -0
- package/dist/core/Step.d.ts.map +1 -0
- package/dist/core/Step.js +444 -0
- package/dist/core/Step.js.map +1 -0
- package/dist/core/ToolManager.d.ts +234 -0
- package/dist/core/ToolManager.d.ts.map +1 -0
- package/dist/core/ToolManager.js +1111 -0
- package/dist/core/ToolManager.js.map +1 -0
- package/dist/{cjs/src/index.d.ts → index.d.ts} +5 -3
- package/dist/index.d.ts.map +1 -0
- package/dist/{src/index.js → index.js} +4 -1
- package/dist/index.js.map +1 -0
- package/dist/providers/AnthropicProvider.d.ts.map +1 -0
- package/dist/{src/providers → providers}/AnthropicProvider.js +17 -17
- package/dist/providers/AnthropicProvider.js.map +1 -0
- package/dist/providers/GeminiProvider.d.ts.map +1 -0
- package/dist/{src/providers → providers}/GeminiProvider.js +123 -51
- package/dist/providers/GeminiProvider.js.map +1 -0
- package/dist/providers/OpenAIProvider.d.ts.map +1 -0
- package/dist/{src/providers → providers}/OpenAIProvider.js +18 -18
- package/dist/providers/OpenAIProvider.js.map +1 -0
- package/dist/providers/OpenRouterProvider.d.ts.map +1 -0
- package/dist/{src/providers → providers}/OpenRouterProvider.js +18 -18
- package/dist/providers/OpenRouterProvider.js.map +1 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/{src/types → types}/agent.d.ts +12 -4
- package/dist/types/agent.d.ts.map +1 -0
- package/dist/types/agent.js.map +1 -0
- package/dist/types/ai.d.ts.map +1 -0
- package/dist/types/ai.js.map +1 -0
- package/dist/types/history.d.ts.map +1 -0
- package/dist/types/history.js.map +1 -0
- package/dist/{src/types → types}/index.d.ts +5 -3
- package/dist/types/index.d.ts.map +1 -0
- package/dist/{src/types → types}/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/persistence.d.ts.map +1 -0
- package/dist/types/persistence.js.map +1 -0
- package/dist/{src/types → types}/route.d.ts +116 -15
- package/dist/types/route.d.ts.map +1 -0
- package/dist/{src/types → types}/route.js.map +1 -1
- package/dist/types/routing.d.ts.map +1 -0
- package/dist/{cjs/src/types → types}/routing.js.map +1 -1
- package/dist/types/schema.d.ts.map +1 -0
- package/dist/{cjs/src/types → types}/schema.js.map +1 -1
- package/dist/types/session.d.ts.map +1 -0
- package/dist/{src/types → types}/session.js.map +1 -1
- package/dist/types/template.d.ts +88 -0
- package/dist/types/template.d.ts.map +1 -0
- package/dist/{cjs/src/types → types}/template.js.map +1 -1
- package/dist/types/tool.d.ts +130 -0
- package/dist/types/tool.d.ts.map +1 -0
- package/dist/types/tool.js +16 -0
- package/dist/types/tool.js.map +1 -0
- package/dist/utils/clone.d.ts.map +1 -0
- package/dist/utils/clone.js.map +1 -0
- package/dist/utils/condition.d.ts +38 -0
- package/dist/utils/condition.d.ts.map +1 -0
- package/dist/utils/condition.js +161 -0
- package/dist/utils/condition.js.map +1 -0
- package/dist/utils/event.d.ts.map +1 -0
- package/dist/utils/event.js.map +1 -0
- package/dist/utils/history.d.ts.map +1 -0
- package/dist/utils/history.js.map +1 -0
- package/dist/utils/id.d.ts.map +1 -0
- package/dist/utils/id.js.map +1 -0
- package/dist/{src/utils → utils}/index.d.ts +3 -1
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/{src/utils → utils}/index.js +5 -1
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/json.d.ts +16 -0
- package/dist/utils/json.d.ts.map +1 -0
- package/dist/utils/json.js +43 -0
- package/dist/utils/json.js.map +1 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/{cjs/src/utils → utils}/retry.d.ts +0 -3
- package/dist/utils/retry.d.ts.map +1 -0
- package/dist/{src/utils → utils}/retry.js +5 -4
- package/dist/utils/retry.js.map +1 -0
- package/dist/utils/session.d.ts.map +1 -0
- package/dist/utils/session.js.map +1 -0
- package/dist/{cjs/src/utils → utils}/template.d.ts +48 -0
- package/dist/utils/template.d.ts.map +1 -0
- package/dist/{src/utils → utils}/template.js +98 -0
- package/dist/utils/template.js.map +1 -0
- package/docs/CONTRIBUTING.md +40 -0
- package/docs/README.md +12 -5
- package/docs/api/README.md +295 -56
- package/docs/api/overview.md +272 -31
- package/docs/architecture/data-extraction-flow.md +363 -0
- package/docs/architecture/multi-step-execution.md +243 -0
- package/docs/core/agent/README.md +120 -5
- package/docs/core/agent/session-management.md +153 -6
- package/docs/core/ai-integration/prompt-composition.md +135 -0
- package/docs/core/ai-integration/response-processing.md +261 -4
- package/docs/core/conversation-flows/data-collection.md +143 -0
- package/docs/core/conversation-flows/routes.md +132 -2
- package/docs/core/conversation-flows/step-transitions.md +132 -0
- package/docs/core/conversation-flows/steps.md +112 -0
- package/docs/core/error-handling.md +831 -0
- package/docs/core/routing/intelligent-routing.md +118 -0
- package/docs/core/tools/tool-definition.md +684 -60
- package/docs/core/tools/tool-scoping.md +244 -53
- package/docs/guides/error-handling-patterns.md +578 -0
- package/docs/guides/getting-started/README.md +423 -31
- package/docs/guides/migration/README.md +23 -0
- package/docs/guides/migration/flexible-routing-conditions.md +375 -0
- package/docs/guides/migration/multi-step-execution.md +303 -0
- package/examples/advanced-patterns/knowledge-based-agent.ts +107 -30
- package/examples/advanced-patterns/persistent-onboarding.ts +70 -48
- package/examples/advanced-patterns/route-lifecycle-hooks.ts +82 -12
- package/examples/advanced-patterns/streaming-responses.ts +2 -2
- package/examples/ai-providers/anthropic-integration.ts +13 -9
- package/examples/ai-providers/openai-integration.ts +12 -8
- package/examples/condition-patterns/function-only-conditions.ts +365 -0
- package/examples/condition-patterns/mixed-array-conditions.ts +477 -0
- package/examples/condition-patterns/route-skipif-patterns.ts +468 -0
- package/examples/condition-patterns/step-skipif-patterns.ts +0 -0
- package/examples/condition-patterns/string-only-conditions.ts +296 -0
- package/examples/conversation-flows/completion-transitions.ts +48 -7
- package/examples/core-concepts/basic-agent.ts +158 -98
- package/examples/core-concepts/schema-driven-extraction.ts +43 -16
- package/examples/core-concepts/session-management.ts +117 -29
- package/examples/integrations/database-integration.ts +6 -6
- package/examples/integrations/healthcare-integration.ts +25 -39
- package/examples/integrations/search-integration.ts +8 -8
- package/examples/integrations/server-session-management.ts +11 -11
- package/examples/persistence/database-persistence.ts +15 -15
- package/examples/persistence/memory-sessions.ts +6 -6
- package/examples/persistence/redis-persistence.ts +7 -9
- package/examples/tools/basic-tools.ts +293 -89
- package/examples/tools/data-enrichment-tools.ts +189 -79
- package/package.json +6 -4
- package/src/adapters/PrismaAdapter.ts +3 -2
- package/src/adapters/RedisAdapter.ts +3 -3
- package/src/core/Agent.ts +152 -46
- package/src/core/BatchExecutor.ts +1156 -0
- package/src/core/BatchPromptBuilder.ts +275 -0
- package/src/core/PromptComposer.ts +53 -16
- package/src/core/ResponseEngine.ts +143 -4
- package/src/core/ResponseModal.ts +1035 -137
- package/src/core/ResponsePipeline.ts +99 -65
- package/src/core/Route.ts +262 -34
- package/src/core/RoutingEngine.ts +467 -120
- package/src/core/SessionManager.ts +39 -7
- package/src/core/Step.ts +338 -32
- package/src/core/ToolManager.ts +1394 -0
- package/src/index.ts +27 -3
- package/src/providers/AnthropicProvider.ts +17 -17
- package/src/providers/GeminiProvider.ts +129 -60
- package/src/providers/OpenAIProvider.ts +18 -18
- package/src/providers/OpenRouterProvider.ts +18 -18
- package/src/types/agent.ts +12 -4
- package/src/types/index.ts +25 -3
- package/src/types/route.ts +136 -15
- package/src/types/template.ts +70 -2
- package/src/types/tool.ts +116 -25
- package/src/utils/condition.ts +190 -0
- package/src/utils/index.ts +12 -0
- package/src/utils/json.ts +46 -0
- package/src/utils/retry.ts +5 -4
- package/src/utils/template.ts +109 -0
- package/dist/cjs/src/adapters/MemoryAdapter.d.ts.map +0 -1
- package/dist/cjs/src/adapters/MemoryAdapter.js.map +0 -1
- package/dist/cjs/src/adapters/MongoAdapter.d.ts.map +0 -1
- package/dist/cjs/src/adapters/MongoAdapter.js.map +0 -1
- package/dist/cjs/src/adapters/OpenSearchAdapter.d.ts.map +0 -1
- package/dist/cjs/src/adapters/OpenSearchAdapter.js.map +0 -1
- package/dist/cjs/src/adapters/PostgreSQLAdapter.d.ts.map +0 -1
- package/dist/cjs/src/adapters/PostgreSQLAdapter.js.map +0 -1
- package/dist/cjs/src/adapters/PrismaAdapter.d.ts.map +0 -1
- package/dist/cjs/src/adapters/PrismaAdapter.js.map +0 -1
- package/dist/cjs/src/adapters/RedisAdapter.d.ts.map +0 -1
- package/dist/cjs/src/adapters/RedisAdapter.js.map +0 -1
- package/dist/cjs/src/adapters/SQLiteAdapter.d.ts.map +0 -1
- package/dist/cjs/src/adapters/SQLiteAdapter.js.map +0 -1
- package/dist/cjs/src/adapters/index.d.ts.map +0 -1
- package/dist/cjs/src/adapters/index.js.map +0 -1
- package/dist/cjs/src/constants/index.d.ts.map +0 -1
- package/dist/cjs/src/constants/index.js.map +0 -1
- package/dist/cjs/src/core/Agent.d.ts.map +0 -1
- package/dist/cjs/src/core/Agent.js.map +0 -1
- package/dist/cjs/src/core/Events.d.ts.map +0 -1
- package/dist/cjs/src/core/Events.js.map +0 -1
- package/dist/cjs/src/core/PersistenceManager.d.ts.map +0 -1
- package/dist/cjs/src/core/PersistenceManager.js.map +0 -1
- package/dist/cjs/src/core/PromptComposer.d.ts.map +0 -1
- package/dist/cjs/src/core/PromptComposer.js.map +0 -1
- package/dist/cjs/src/core/ResponseEngine.d.ts.map +0 -1
- package/dist/cjs/src/core/ResponseEngine.js +0 -84
- package/dist/cjs/src/core/ResponseEngine.js.map +0 -1
- package/dist/cjs/src/core/ResponseModal.d.ts.map +0 -1
- package/dist/cjs/src/core/ResponseModal.js.map +0 -1
- package/dist/cjs/src/core/ResponsePipeline.d.ts.map +0 -1
- package/dist/cjs/src/core/ResponsePipeline.js.map +0 -1
- package/dist/cjs/src/core/Route.d.ts.map +0 -1
- package/dist/cjs/src/core/Route.js +0 -343
- package/dist/cjs/src/core/Route.js.map +0 -1
- package/dist/cjs/src/core/RoutingEngine.d.ts.map +0 -1
- package/dist/cjs/src/core/RoutingEngine.js.map +0 -1
- package/dist/cjs/src/core/SessionManager.d.ts.map +0 -1
- package/dist/cjs/src/core/SessionManager.js.map +0 -1
- package/dist/cjs/src/core/Step.d.ts +0 -96
- package/dist/cjs/src/core/Step.d.ts.map +0 -1
- package/dist/cjs/src/core/Step.js +0 -206
- package/dist/cjs/src/core/Step.js.map +0 -1
- package/dist/cjs/src/core/ToolExecutor.d.ts +0 -45
- package/dist/cjs/src/core/ToolExecutor.d.ts.map +0 -1
- package/dist/cjs/src/core/ToolExecutor.js +0 -84
- package/dist/cjs/src/core/ToolExecutor.js.map +0 -1
- package/dist/cjs/src/index.d.ts.map +0 -1
- package/dist/cjs/src/index.js.map +0 -1
- package/dist/cjs/src/providers/AnthropicProvider.d.ts.map +0 -1
- package/dist/cjs/src/providers/AnthropicProvider.js.map +0 -1
- package/dist/cjs/src/providers/GeminiProvider.d.ts.map +0 -1
- package/dist/cjs/src/providers/GeminiProvider.js.map +0 -1
- package/dist/cjs/src/providers/OpenAIProvider.d.ts.map +0 -1
- package/dist/cjs/src/providers/OpenAIProvider.js.map +0 -1
- package/dist/cjs/src/providers/OpenRouterProvider.d.ts.map +0 -1
- package/dist/cjs/src/providers/OpenRouterProvider.js.map +0 -1
- package/dist/cjs/src/providers/index.d.ts.map +0 -1
- package/dist/cjs/src/providers/index.js.map +0 -1
- package/dist/cjs/src/types/agent.d.ts.map +0 -1
- package/dist/cjs/src/types/agent.js.map +0 -1
- package/dist/cjs/src/types/ai.d.ts.map +0 -1
- package/dist/cjs/src/types/ai.js.map +0 -1
- package/dist/cjs/src/types/history.d.ts.map +0 -1
- package/dist/cjs/src/types/history.js.map +0 -1
- package/dist/cjs/src/types/index.d.ts.map +0 -1
- package/dist/cjs/src/types/index.js.map +0 -1
- package/dist/cjs/src/types/persistence.d.ts.map +0 -1
- package/dist/cjs/src/types/persistence.js.map +0 -1
- package/dist/cjs/src/types/route.d.ts.map +0 -1
- package/dist/cjs/src/types/routing.d.ts.map +0 -1
- package/dist/cjs/src/types/schema.d.ts.map +0 -1
- package/dist/cjs/src/types/session.d.ts.map +0 -1
- package/dist/cjs/src/types/session.js.map +0 -1
- package/dist/cjs/src/types/template.d.ts +0 -30
- package/dist/cjs/src/types/template.d.ts.map +0 -1
- package/dist/cjs/src/types/tool.d.ts +0 -60
- package/dist/cjs/src/types/tool.d.ts.map +0 -1
- package/dist/cjs/src/types/tool.js +0 -6
- package/dist/cjs/src/types/tool.js.map +0 -1
- package/dist/cjs/src/utils/clone.d.ts.map +0 -1
- package/dist/cjs/src/utils/clone.js.map +0 -1
- package/dist/cjs/src/utils/event.d.ts.map +0 -1
- package/dist/cjs/src/utils/event.js.map +0 -1
- package/dist/cjs/src/utils/history.d.ts.map +0 -1
- package/dist/cjs/src/utils/history.js.map +0 -1
- package/dist/cjs/src/utils/id.d.ts.map +0 -1
- package/dist/cjs/src/utils/id.js.map +0 -1
- package/dist/cjs/src/utils/index.d.ts.map +0 -1
- package/dist/cjs/src/utils/index.js.map +0 -1
- package/dist/cjs/src/utils/logger.d.ts.map +0 -1
- package/dist/cjs/src/utils/logger.js.map +0 -1
- package/dist/cjs/src/utils/retry.d.ts.map +0 -1
- package/dist/cjs/src/utils/retry.js.map +0 -1
- package/dist/cjs/src/utils/session.d.ts.map +0 -1
- package/dist/cjs/src/utils/session.js.map +0 -1
- package/dist/cjs/src/utils/template.d.ts.map +0 -1
- package/dist/cjs/src/utils/template.js.map +0 -1
- package/dist/src/adapters/MemoryAdapter.js.map +0 -1
- package/dist/src/adapters/MongoAdapter.js.map +0 -1
- package/dist/src/adapters/OpenSearchAdapter.js.map +0 -1
- package/dist/src/adapters/PostgreSQLAdapter.js.map +0 -1
- package/dist/src/adapters/PrismaAdapter.js.map +0 -1
- package/dist/src/adapters/RedisAdapter.js.map +0 -1
- package/dist/src/adapters/SQLiteAdapter.js.map +0 -1
- package/dist/src/adapters/index.js.map +0 -1
- package/dist/src/constants/index.js.map +0 -1
- package/dist/src/core/Agent.d.ts.map +0 -1
- package/dist/src/core/Agent.js.map +0 -1
- package/dist/src/core/Events.js.map +0 -1
- package/dist/src/core/PersistenceManager.js.map +0 -1
- package/dist/src/core/PromptComposer.d.ts.map +0 -1
- package/dist/src/core/PromptComposer.js.map +0 -1
- package/dist/src/core/ResponseEngine.js +0 -80
- package/dist/src/core/ResponseEngine.js.map +0 -1
- package/dist/src/core/ResponseModal.d.ts.map +0 -1
- package/dist/src/core/ResponseModal.js.map +0 -1
- package/dist/src/core/ResponsePipeline.d.ts.map +0 -1
- package/dist/src/core/ResponsePipeline.js.map +0 -1
- package/dist/src/core/Route.d.ts.map +0 -1
- package/dist/src/core/Route.js +0 -339
- package/dist/src/core/Route.js.map +0 -1
- package/dist/src/core/RoutingEngine.d.ts.map +0 -1
- package/dist/src/core/RoutingEngine.js.map +0 -1
- package/dist/src/core/SessionManager.d.ts.map +0 -1
- package/dist/src/core/SessionManager.js.map +0 -1
- package/dist/src/core/Step.d.ts +0 -96
- package/dist/src/core/Step.d.ts.map +0 -1
- package/dist/src/core/Step.js +0 -202
- package/dist/src/core/Step.js.map +0 -1
- package/dist/src/core/ToolExecutor.d.ts +0 -45
- package/dist/src/core/ToolExecutor.d.ts.map +0 -1
- package/dist/src/core/ToolExecutor.js +0 -80
- package/dist/src/core/ToolExecutor.js.map +0 -1
- package/dist/src/index.d.ts.map +0 -1
- package/dist/src/index.js.map +0 -1
- package/dist/src/providers/AnthropicProvider.js.map +0 -1
- package/dist/src/providers/GeminiProvider.js.map +0 -1
- package/dist/src/providers/OpenAIProvider.js.map +0 -1
- package/dist/src/providers/OpenRouterProvider.js.map +0 -1
- package/dist/src/providers/index.js.map +0 -1
- package/dist/src/types/agent.d.ts.map +0 -1
- package/dist/src/types/agent.js.map +0 -1
- package/dist/src/types/history.js.map +0 -1
- package/dist/src/types/index.js.map +0 -1
- package/dist/src/types/persistence.js.map +0 -1
- package/dist/src/types/route.d.ts.map +0 -1
- package/dist/src/types/template.d.ts +0 -30
- package/dist/src/types/template.d.ts.map +0 -1
- package/dist/src/types/tool.d.ts +0 -60
- package/dist/src/types/tool.d.ts.map +0 -1
- package/dist/src/types/tool.js +0 -5
- package/dist/src/types/tool.js.map +0 -1
- package/dist/src/utils/clone.js.map +0 -1
- package/dist/src/utils/event.js.map +0 -1
- package/dist/src/utils/history.js.map +0 -1
- package/dist/src/utils/id.js.map +0 -1
- package/dist/src/utils/index.d.ts.map +0 -1
- package/dist/src/utils/index.js.map +0 -1
- package/dist/src/utils/logger.js.map +0 -1
- package/dist/src/utils/retry.d.ts.map +0 -1
- package/dist/src/utils/retry.js.map +0 -1
- package/dist/src/utils/session.js.map +0 -1
- package/dist/src/utils/template.d.ts.map +0 -1
- package/dist/src/utils/template.js.map +0 -1
- package/docs/core/tools/tool-execution.md +0 -815
- package/src/core/ToolExecutor.ts +0 -126
- /package/dist/{cjs/src/adapters → adapters}/MemoryAdapter.d.ts +0 -0
- /package/dist/{src/adapters → adapters}/MemoryAdapter.js +0 -0
- /package/dist/{cjs/src/adapters → adapters}/MongoAdapter.d.ts +0 -0
- /package/dist/{src/adapters → adapters}/MongoAdapter.js +0 -0
- /package/dist/{cjs/src/adapters → adapters}/OpenSearchAdapter.d.ts +0 -0
- /package/dist/{src/adapters → adapters}/OpenSearchAdapter.js +0 -0
- /package/dist/{cjs/src/adapters → adapters}/PostgreSQLAdapter.d.ts +0 -0
- /package/dist/{src/adapters → adapters}/PostgreSQLAdapter.js +0 -0
- /package/dist/{cjs/src/adapters → adapters}/PrismaAdapter.d.ts +0 -0
- /package/dist/{cjs/src/adapters → adapters}/RedisAdapter.d.ts +0 -0
- /package/dist/{cjs/src/adapters → adapters}/SQLiteAdapter.d.ts +0 -0
- /package/dist/{src/adapters → adapters}/SQLiteAdapter.js +0 -0
- /package/dist/{cjs/src/adapters → adapters}/index.d.ts +0 -0
- /package/dist/{src/adapters → adapters}/index.js +0 -0
- /package/dist/{src → cjs}/adapters/MemoryAdapter.d.ts +0 -0
- /package/dist/{src → cjs}/adapters/MemoryAdapter.d.ts.map +0 -0
- /package/dist/cjs/{src/adapters → adapters}/MemoryAdapter.js +0 -0
- /package/dist/{src → cjs}/adapters/MongoAdapter.d.ts +0 -0
- /package/dist/{src → cjs}/adapters/MongoAdapter.d.ts.map +0 -0
- /package/dist/cjs/{src/adapters → adapters}/MongoAdapter.js +0 -0
- /package/dist/{src → cjs}/adapters/OpenSearchAdapter.d.ts +0 -0
- /package/dist/{src → cjs}/adapters/OpenSearchAdapter.d.ts.map +0 -0
- /package/dist/cjs/{src/adapters → adapters}/OpenSearchAdapter.js +0 -0
- /package/dist/{src → cjs}/adapters/PostgreSQLAdapter.d.ts +0 -0
- /package/dist/{src → cjs}/adapters/PostgreSQLAdapter.d.ts.map +0 -0
- /package/dist/cjs/{src/adapters → adapters}/PostgreSQLAdapter.js +0 -0
- /package/dist/{src → cjs}/adapters/PrismaAdapter.d.ts +0 -0
- /package/dist/{src → cjs}/adapters/RedisAdapter.d.ts +0 -0
- /package/dist/{src → cjs}/adapters/RedisAdapter.d.ts.map +0 -0
- /package/dist/{src → cjs}/adapters/SQLiteAdapter.d.ts +0 -0
- /package/dist/{src → cjs}/adapters/SQLiteAdapter.d.ts.map +0 -0
- /package/dist/cjs/{src/adapters → adapters}/SQLiteAdapter.js +0 -0
- /package/dist/{src → cjs}/adapters/index.d.ts +0 -0
- /package/dist/{src → cjs}/adapters/index.d.ts.map +0 -0
- /package/dist/cjs/{src/adapters → adapters}/index.js +0 -0
- /package/dist/cjs/{src/constants → constants}/index.d.ts +0 -0
- /package/dist/{src → cjs}/constants/index.d.ts.map +0 -0
- /package/dist/cjs/{src/constants → constants}/index.js +0 -0
- /package/dist/cjs/{src/core → core}/Events.d.ts +0 -0
- /package/dist/{src → cjs}/core/Events.d.ts.map +0 -0
- /package/dist/cjs/{src/core → core}/Events.js +0 -0
- /package/dist/cjs/{src/core → core}/PersistenceManager.d.ts +0 -0
- /package/dist/{src → cjs}/core/PersistenceManager.d.ts.map +0 -0
- /package/dist/cjs/{src/core → core}/PersistenceManager.js +0 -0
- /package/dist/cjs/{src/core → core}/ResponseEngine.d.ts +0 -0
- /package/dist/cjs/{src/providers → providers}/AnthropicProvider.d.ts +0 -0
- /package/dist/{src → cjs}/providers/AnthropicProvider.d.ts.map +0 -0
- /package/dist/cjs/{src/providers → providers}/GeminiProvider.d.ts +0 -0
- /package/dist/cjs/{src/providers → providers}/OpenAIProvider.d.ts +0 -0
- /package/dist/{src → cjs}/providers/OpenAIProvider.d.ts.map +0 -0
- /package/dist/cjs/{src/providers → providers}/OpenRouterProvider.d.ts +0 -0
- /package/dist/{src → cjs}/providers/OpenRouterProvider.d.ts.map +0 -0
- /package/dist/cjs/{src/providers → providers}/index.d.ts +0 -0
- /package/dist/{src → cjs}/providers/index.d.ts.map +0 -0
- /package/dist/cjs/{src/providers → providers}/index.js +0 -0
- /package/dist/cjs/{src/types → types}/agent.js +0 -0
- /package/dist/cjs/{src/types → types}/ai.d.ts +0 -0
- /package/dist/{src → cjs}/types/ai.d.ts.map +0 -0
- /package/dist/cjs/{src/types → types}/ai.js +0 -0
- /package/dist/cjs/{src/types → types}/history.d.ts +0 -0
- /package/dist/{src → cjs}/types/history.d.ts.map +0 -0
- /package/dist/cjs/{src/types → types}/history.js +0 -0
- /package/dist/cjs/{src/types → types}/persistence.d.ts +0 -0
- /package/dist/{src → cjs}/types/persistence.d.ts.map +0 -0
- /package/dist/cjs/{src/types → types}/persistence.js +0 -0
- /package/dist/cjs/{src/types → types}/route.js +0 -0
- /package/dist/cjs/{src/types → types}/routing.d.ts +0 -0
- /package/dist/{src → cjs}/types/routing.d.ts.map +0 -0
- /package/dist/cjs/{src/types → types}/routing.js +0 -0
- /package/dist/{src → cjs}/types/routing.js.map +0 -0
- /package/dist/cjs/{src/types → types}/schema.d.ts +0 -0
- /package/dist/{src → cjs}/types/schema.d.ts.map +0 -0
- /package/dist/cjs/{src/types → types}/schema.js +0 -0
- /package/dist/{src → cjs}/types/schema.js.map +0 -0
- /package/dist/cjs/{src/types → types}/session.d.ts +0 -0
- /package/dist/{src → cjs}/types/session.d.ts.map +0 -0
- /package/dist/cjs/{src/types → types}/session.js +0 -0
- /package/dist/cjs/{src/types → types}/template.js +0 -0
- /package/dist/{src → cjs}/types/template.js.map +0 -0
- /package/dist/cjs/{src/utils → utils}/clone.d.ts +0 -0
- /package/dist/{src → cjs}/utils/clone.d.ts.map +0 -0
- /package/dist/cjs/{src/utils → utils}/clone.js +0 -0
- /package/dist/cjs/{src/utils → utils}/event.d.ts +0 -0
- /package/dist/{src → cjs}/utils/event.d.ts.map +0 -0
- /package/dist/cjs/{src/utils → utils}/event.js +0 -0
- /package/dist/cjs/{src/utils → utils}/history.d.ts +0 -0
- /package/dist/{src → cjs}/utils/history.d.ts.map +0 -0
- /package/dist/cjs/{src/utils → utils}/history.js +0 -0
- /package/dist/cjs/{src/utils → utils}/id.d.ts +0 -0
- /package/dist/{src → cjs}/utils/id.d.ts.map +0 -0
- /package/dist/cjs/{src/utils → utils}/id.js +0 -0
- /package/dist/cjs/{src/utils → utils}/logger.d.ts +0 -0
- /package/dist/{src → cjs}/utils/logger.d.ts.map +0 -0
- /package/dist/cjs/{src/utils → utils}/logger.js +0 -0
- /package/dist/cjs/{src/utils → utils}/session.d.ts +0 -0
- /package/dist/{src → cjs}/utils/session.d.ts.map +0 -0
- /package/dist/cjs/{src/utils → utils}/session.js +0 -0
- /package/dist/{src/constants → constants}/index.d.ts +0 -0
- /package/dist/{src/constants → constants}/index.js +0 -0
- /package/dist/{src/core → core}/Events.d.ts +0 -0
- /package/dist/{src/core → core}/Events.js +0 -0
- /package/dist/{src/core → core}/PersistenceManager.d.ts +0 -0
- /package/dist/{src/core → core}/PersistenceManager.js +0 -0
- /package/dist/{src/core → core}/ResponseEngine.d.ts +0 -0
- /package/dist/{src/providers → providers}/AnthropicProvider.d.ts +0 -0
- /package/dist/{src/providers → providers}/GeminiProvider.d.ts +0 -0
- /package/dist/{src/providers → providers}/OpenAIProvider.d.ts +0 -0
- /package/dist/{src/providers → providers}/OpenRouterProvider.d.ts +0 -0
- /package/dist/{src/providers → providers}/index.d.ts +0 -0
- /package/dist/{src/providers → providers}/index.js +0 -0
- /package/dist/{src/types → types}/agent.js +0 -0
- /package/dist/{src/types → types}/ai.d.ts +0 -0
- /package/dist/{src/types → types}/ai.js +0 -0
- /package/dist/{src/types → types}/history.d.ts +0 -0
- /package/dist/{src/types → types}/history.js +0 -0
- /package/dist/{src/types → types}/persistence.d.ts +0 -0
- /package/dist/{src/types → types}/persistence.js +0 -0
- /package/dist/{src/types → types}/route.js +0 -0
- /package/dist/{src/types → types}/routing.d.ts +0 -0
- /package/dist/{src/types → types}/routing.js +0 -0
- /package/dist/{src/types → types}/schema.d.ts +0 -0
- /package/dist/{src/types → types}/schema.js +0 -0
- /package/dist/{src/types → types}/session.d.ts +0 -0
- /package/dist/{src/types → types}/session.js +0 -0
- /package/dist/{src/types → types}/template.js +0 -0
- /package/dist/{src/utils → utils}/clone.d.ts +0 -0
- /package/dist/{src/utils → utils}/clone.js +0 -0
- /package/dist/{src/utils → utils}/event.d.ts +0 -0
- /package/dist/{src/utils → utils}/event.js +0 -0
- /package/dist/{src/utils → utils}/history.d.ts +0 -0
- /package/dist/{src/utils → utils}/history.js +0 -0
- /package/dist/{src/utils → utils}/id.d.ts +0 -0
- /package/dist/{src/utils → utils}/id.js +0 -0
- /package/dist/{src/utils → utils}/logger.d.ts +0 -0
- /package/dist/{src/utils → utils}/logger.js +0 -0
- /package/dist/{src/utils → utils}/session.d.ts +0 -0
- /package/dist/{src/utils → utils}/session.js +0 -0
|
@@ -15,16 +15,21 @@ import type {
|
|
|
15
15
|
ToolEventData,
|
|
16
16
|
AgentStructuredResponse,
|
|
17
17
|
Term,
|
|
18
|
+
StoppedReason,
|
|
18
19
|
} from "../types";
|
|
19
20
|
import { EventKind, MessageRole } from "../types";
|
|
20
21
|
import type { Agent } from "./Agent";
|
|
21
22
|
import type { Route } from "./Route";
|
|
22
|
-
import
|
|
23
|
+
import { Step } from "./Step";
|
|
23
24
|
import { ResponseEngine } from "./ResponseEngine";
|
|
24
25
|
import { ResponsePipeline } from "./ResponsePipeline";
|
|
26
|
+
import { BatchExecutor, type HookFunction } from "./BatchExecutor";
|
|
27
|
+
import { BatchPromptBuilder } from "./BatchPromptBuilder";
|
|
25
28
|
import { cloneDeep, mergeCollected, enterStep, getLastMessageFromHistory, render, logger, historyToEvents } from "../utils";
|
|
26
|
-
import {
|
|
29
|
+
import { createTemplateContext } from "../utils/template";
|
|
30
|
+
import type { ToolManager } from "./ToolManager";
|
|
27
31
|
import { END_ROUTE_ID } from "../constants";
|
|
32
|
+
import type { StepOptions } from "../types/route";
|
|
28
33
|
|
|
29
34
|
/**
|
|
30
35
|
* Configuration options for ResponseModal
|
|
@@ -98,9 +103,9 @@ export class ResponseGenerationError extends Error {
|
|
|
98
103
|
* Create a ResponseGenerationError from an unknown error
|
|
99
104
|
*/
|
|
100
105
|
static fromError(
|
|
101
|
-
error: unknown,
|
|
102
|
-
phase: string,
|
|
103
|
-
params?: Record<string, unknown>,
|
|
106
|
+
error: unknown,
|
|
107
|
+
phase: string,
|
|
108
|
+
params?: Record<string, unknown>,
|
|
104
109
|
context?: Record<string, unknown>
|
|
105
110
|
): ResponseGenerationError {
|
|
106
111
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -129,6 +134,12 @@ interface ResponseContext<TContext = unknown, TData = unknown> {
|
|
|
129
134
|
selectedStep?: Step<TContext, TData>;
|
|
130
135
|
responseDirectives?: string[];
|
|
131
136
|
isRouteComplete: boolean;
|
|
137
|
+
/** Batch of steps to execute (for multi-step execution) */
|
|
138
|
+
batchSteps?: StepOptions<TContext, TData>[];
|
|
139
|
+
/** Reason why batch determination stopped */
|
|
140
|
+
batchStoppedReason?: StoppedReason;
|
|
141
|
+
/** Step that caused batch to stop (if applicable) */
|
|
142
|
+
batchStoppedAtStep?: StepOptions<TContext, TData>;
|
|
132
143
|
}
|
|
133
144
|
|
|
134
145
|
/**
|
|
@@ -138,6 +149,8 @@ interface ResponseContext<TContext = unknown, TData = unknown> {
|
|
|
138
149
|
export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
139
150
|
private readonly responseEngine: ResponseEngine<TContext, TData>;
|
|
140
151
|
private readonly responsePipeline: ResponsePipeline<TContext, TData>;
|
|
152
|
+
private readonly batchExecutor: BatchExecutor<TContext, TData>;
|
|
153
|
+
private readonly batchPromptBuilder: BatchPromptBuilder<TContext, TData>;
|
|
141
154
|
|
|
142
155
|
constructor(
|
|
143
156
|
private readonly agent: Agent<TContext, TData>,
|
|
@@ -149,13 +162,20 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
149
162
|
// Initialize response pipeline with agent dependencies
|
|
150
163
|
this.responsePipeline = new ResponsePipeline<TContext, TData>(
|
|
151
164
|
this.agent.getAgentOptions(),
|
|
152
|
-
this.agent.getRoutes(),
|
|
165
|
+
() => this.agent.getRoutes(), // Pass a function to get routes dynamically
|
|
153
166
|
this.agent.getTools(),
|
|
154
167
|
this.agent.getRoutingEngine(),
|
|
155
168
|
this.agent.updateContext.bind(this.agent),
|
|
156
169
|
this.agent.getUpdateDataMethod(),
|
|
157
|
-
this.agent.updateCollectedData.bind(this.agent)
|
|
170
|
+
this.agent.updateCollectedData.bind(this.agent),
|
|
171
|
+
this.getToolManager()
|
|
158
172
|
);
|
|
173
|
+
|
|
174
|
+
// Initialize batch executor for multi-step execution
|
|
175
|
+
this.batchExecutor = new BatchExecutor<TContext, TData>();
|
|
176
|
+
|
|
177
|
+
// Initialize batch prompt builder for combined prompts
|
|
178
|
+
this.batchPromptBuilder = new BatchPromptBuilder<TContext, TData>();
|
|
159
179
|
}
|
|
160
180
|
|
|
161
181
|
/**
|
|
@@ -165,7 +185,6 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
165
185
|
try {
|
|
166
186
|
// Use unified response preparation and routing
|
|
167
187
|
const responseContext = await this.prepareUnifiedResponseContext(params);
|
|
168
|
-
|
|
169
188
|
// Generate response using unified logic
|
|
170
189
|
const result = await this.generateUnifiedResponse(responseContext);
|
|
171
190
|
|
|
@@ -330,6 +349,21 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
330
349
|
return this.responsePipeline;
|
|
331
350
|
}
|
|
332
351
|
|
|
352
|
+
/**
|
|
353
|
+
* Get the ToolManager instance from the agent
|
|
354
|
+
* @private
|
|
355
|
+
*/
|
|
356
|
+
private getToolManager(): ToolManager<TContext, TData> | undefined {
|
|
357
|
+
// Check if agent has a tool property (ToolManager)
|
|
358
|
+
if (this.agent && 'tool' in this.agent && this.agent.tool) {
|
|
359
|
+
return this.agent.tool;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// Log warning if ToolManager is not available
|
|
363
|
+
logger.warn(`[ResponseModal] ToolManager not available on agent - tool execution will use fallback methods`);
|
|
364
|
+
return undefined;
|
|
365
|
+
}
|
|
366
|
+
|
|
333
367
|
// UNIFIED RESPONSE LOGIC - Consolidates common logic between streaming and non-streaming
|
|
334
368
|
// ============================================================================
|
|
335
369
|
|
|
@@ -403,12 +437,16 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
403
437
|
}
|
|
404
438
|
|
|
405
439
|
// PHASE 2: ROUTING + STEP SELECTION - Determine which route and step to use
|
|
440
|
+
// Also performs pre-extraction and batch determination
|
|
406
441
|
let routingResult: {
|
|
407
442
|
selectedRoute?: Route<TContext, TData>;
|
|
408
443
|
selectedStep?: Step<TContext, TData>;
|
|
409
|
-
|
|
444
|
+
responseDirectives?: string[];
|
|
410
445
|
session: SessionState<TData>;
|
|
411
446
|
isRouteComplete: boolean;
|
|
447
|
+
batchSteps?: StepOptions<TContext, TData>[];
|
|
448
|
+
batchStoppedReason?: StoppedReason;
|
|
449
|
+
batchStoppedAtStep?: StepOptions<TContext, TData>;
|
|
412
450
|
};
|
|
413
451
|
try {
|
|
414
452
|
routingResult = await this.handleUnifiedRoutingAndStepSelection({
|
|
@@ -429,6 +467,9 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
429
467
|
selectedStep: routingResult.selectedStep,
|
|
430
468
|
responseDirectives: routingResult.responseDirectives,
|
|
431
469
|
isRouteComplete: routingResult.isRouteComplete,
|
|
470
|
+
batchSteps: routingResult.batchSteps,
|
|
471
|
+
batchStoppedReason: routingResult.batchStoppedReason,
|
|
472
|
+
batchStoppedAtStep: routingResult.batchStoppedAtStep,
|
|
432
473
|
};
|
|
433
474
|
} catch (error) {
|
|
434
475
|
// Re-throw ResponseGenerationError as-is, wrap others
|
|
@@ -454,6 +495,12 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
454
495
|
responseDirectives?: string[];
|
|
455
496
|
session: SessionState<TData>;
|
|
456
497
|
isRouteComplete: boolean;
|
|
498
|
+
/** Batch of steps to execute (for multi-step execution) */
|
|
499
|
+
batchSteps?: StepOptions<TContext, TData>[];
|
|
500
|
+
/** Reason why batch determination stopped */
|
|
501
|
+
batchStoppedReason?: StoppedReason;
|
|
502
|
+
/** Step that caused batch to stop (if applicable) */
|
|
503
|
+
batchStoppedAtStep?: StepOptions<TContext, TData>;
|
|
457
504
|
}> {
|
|
458
505
|
try {
|
|
459
506
|
// Use the ResponsePipeline for optimized routing and step selection
|
|
@@ -466,12 +513,83 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
466
513
|
signal: params.signal,
|
|
467
514
|
});
|
|
468
515
|
|
|
516
|
+
let updatedSession = routingResult.session;
|
|
517
|
+
let isRouteComplete = routingResult.isRouteComplete;
|
|
518
|
+
|
|
519
|
+
// PRE-EXTRACTION: If entering a route that collects data, extract data from user message first
|
|
520
|
+
// This allows us to skip steps whose data is already provided
|
|
521
|
+
// Requirement 3.1: Perform Pre_Extraction before determining the Batch
|
|
522
|
+
if (routingResult.selectedRoute && !isRouteComplete) {
|
|
523
|
+
// Always pre-extract when route collects data (not just on new route entry)
|
|
524
|
+
// This ensures batch determination has the most up-to-date data
|
|
525
|
+
if (this.shouldPreExtractData(routingResult.selectedRoute)) {
|
|
526
|
+
logger.debug(
|
|
527
|
+
`[ResponseModal] Pre-extracting data for route: ${routingResult.selectedRoute.title}`
|
|
528
|
+
);
|
|
529
|
+
|
|
530
|
+
const extractedData = await this.preExtractRouteData({
|
|
531
|
+
route: routingResult.selectedRoute,
|
|
532
|
+
history: params.history,
|
|
533
|
+
context: params.context,
|
|
534
|
+
session: updatedSession,
|
|
535
|
+
signal: params.signal,
|
|
536
|
+
});
|
|
537
|
+
|
|
538
|
+
if (extractedData && Object.keys(extractedData).length > 0) {
|
|
539
|
+
logger.debug(
|
|
540
|
+
`[ResponseModal] Pre-extracted data:`,
|
|
541
|
+
extractedData
|
|
542
|
+
);
|
|
543
|
+
// Requirement 3.3: Merge pre-extracted data into session before batch determination
|
|
544
|
+
updatedSession = mergeCollected(updatedSession, extractedData);
|
|
545
|
+
// Also update agent's collected data
|
|
546
|
+
await this.agent.updateCollectedData(extractedData);
|
|
547
|
+
|
|
548
|
+
// Re-check route completion after pre-extraction
|
|
549
|
+
const allRequiredFieldsCollected = routingResult.selectedRoute.isComplete(updatedSession.data || {});
|
|
550
|
+
if (allRequiredFieldsCollected) {
|
|
551
|
+
logger.debug(
|
|
552
|
+
`[ResponseModal] Route ${routingResult.selectedRoute.title} completed after pre-extraction`
|
|
553
|
+
);
|
|
554
|
+
isRouteComplete = true;
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
// BATCH DETERMINATION: Use BatchExecutor to determine which steps can execute together
|
|
561
|
+
// Requirement 3.4: Pre-extraction results affect batch determination
|
|
562
|
+
let batchSteps: StepOptions<TContext, TData>[] | undefined;
|
|
563
|
+
let batchStoppedReason: StoppedReason | undefined;
|
|
564
|
+
let batchStoppedAtStep: StepOptions<TContext, TData> | undefined;
|
|
565
|
+
|
|
566
|
+
if (routingResult.selectedRoute && !isRouteComplete) {
|
|
567
|
+
// Determine current step position for batch determination
|
|
568
|
+
const currentStep = routingResult.selectedStep ||
|
|
569
|
+
(updatedSession.currentStep ? routingResult.selectedRoute.getStep(updatedSession.currentStep.id) : undefined);
|
|
570
|
+
|
|
571
|
+
logger.debug(`[ResponseModal] Determining batch starting from step: ${currentStep?.id || 'initial'}`);
|
|
572
|
+
|
|
573
|
+
const batchResult = await this.batchExecutor.determineBatch({
|
|
574
|
+
route: routingResult.selectedRoute,
|
|
575
|
+
currentStep,
|
|
576
|
+
sessionData: updatedSession.data || {},
|
|
577
|
+
context: params.context,
|
|
578
|
+
});
|
|
579
|
+
|
|
580
|
+
batchSteps = batchResult.steps;
|
|
581
|
+
batchStoppedReason = batchResult.stoppedReason;
|
|
582
|
+
batchStoppedAtStep = batchResult.stoppedAtStep;
|
|
583
|
+
|
|
584
|
+
logger.debug(`[ResponseModal] Batch determined: ${batchSteps.length} steps, stopped reason: ${batchStoppedReason}`);
|
|
585
|
+
}
|
|
586
|
+
|
|
469
587
|
// Determine next step using pipeline method for consistency
|
|
470
|
-
const stepResult = this.responsePipeline.determineNextStep({
|
|
588
|
+
const stepResult = await this.responsePipeline.determineNextStep({
|
|
471
589
|
selectedRoute: routingResult.selectedRoute,
|
|
472
590
|
selectedStep: routingResult.selectedStep,
|
|
473
|
-
session:
|
|
474
|
-
isRouteComplete
|
|
591
|
+
session: updatedSession, // Use updated session with pre-extracted data
|
|
592
|
+
isRouteComplete, // Use updated completion status
|
|
475
593
|
});
|
|
476
594
|
|
|
477
595
|
return {
|
|
@@ -479,13 +597,106 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
479
597
|
selectedStep: stepResult.nextStep, // Use the determined next step
|
|
480
598
|
responseDirectives: routingResult.responseDirectives,
|
|
481
599
|
session: stepResult.session,
|
|
482
|
-
isRouteComplete
|
|
600
|
+
isRouteComplete, // Use updated completion status
|
|
601
|
+
batchSteps,
|
|
602
|
+
batchStoppedReason,
|
|
603
|
+
batchStoppedAtStep,
|
|
483
604
|
};
|
|
484
605
|
} catch (error) {
|
|
485
606
|
throw ResponseGenerationError.fromError(error, 'routing_optimization', params);
|
|
486
607
|
}
|
|
487
608
|
}
|
|
488
609
|
|
|
610
|
+
/**
|
|
611
|
+
* Check if a route should pre-extract data before determining the initial step
|
|
612
|
+
* @private
|
|
613
|
+
*/
|
|
614
|
+
private shouldPreExtractData(route: Route<TContext, TData>): boolean {
|
|
615
|
+
// Pre-extract if route has declared required or optional fields
|
|
616
|
+
if (route.requiredFields && route.requiredFields.length > 0) {
|
|
617
|
+
return true;
|
|
618
|
+
}
|
|
619
|
+
if (route.optionalFields && route.optionalFields.length > 0) {
|
|
620
|
+
return true;
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
// Pre-extract if any step in the route collects data
|
|
624
|
+
const steps = route.getAllSteps();
|
|
625
|
+
const hasDataCollectionSteps = steps.some(
|
|
626
|
+
step => step.collect && step.collect.length > 0
|
|
627
|
+
);
|
|
628
|
+
|
|
629
|
+
return hasDataCollectionSteps;
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
/**
|
|
633
|
+
* Pre-extract data from user message when entering a route
|
|
634
|
+
* This allows skipping steps whose data is already provided
|
|
635
|
+
* @private
|
|
636
|
+
*/
|
|
637
|
+
private async preExtractRouteData(params: {
|
|
638
|
+
route: Route<TContext, TData>;
|
|
639
|
+
history: Event[];
|
|
640
|
+
context: TContext;
|
|
641
|
+
session: SessionState<TData>;
|
|
642
|
+
signal?: AbortSignal;
|
|
643
|
+
}): Promise<Partial<TData>> {
|
|
644
|
+
const { route, history, context, signal } = params;
|
|
645
|
+
|
|
646
|
+
// Build a schema for data extraction based on route's fields
|
|
647
|
+
const extractionSchema = this.agent.getSchema();
|
|
648
|
+
if (!extractionSchema) {
|
|
649
|
+
logger.warn(`[ResponseModal] No schema available for pre-extraction`);
|
|
650
|
+
return {};
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
// Get last user message
|
|
654
|
+
const lastMessage = getLastMessageFromHistory(history);
|
|
655
|
+
|
|
656
|
+
// Build extraction prompt
|
|
657
|
+
const extractionPrompt = [
|
|
658
|
+
`Extract any relevant information from the user's message that matches the following data fields.`,
|
|
659
|
+
`Only extract information that is explicitly stated or clearly implied.`,
|
|
660
|
+
``,
|
|
661
|
+
`User's message: "${lastMessage}"`,
|
|
662
|
+
``,
|
|
663
|
+
`Extract data for these fields if present:`,
|
|
664
|
+
];
|
|
665
|
+
|
|
666
|
+
// Add field descriptions
|
|
667
|
+
if (route.requiredFields) {
|
|
668
|
+
extractionPrompt.push(`Required fields: ${route.requiredFields.join(', ')}`);
|
|
669
|
+
}
|
|
670
|
+
if (route.optionalFields) {
|
|
671
|
+
extractionPrompt.push(`Optional fields: ${route.optionalFields.join(', ')}`);
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
extractionPrompt.push(
|
|
675
|
+
``,
|
|
676
|
+
`Return ONLY the extracted data as JSON. If no data can be extracted, return an empty object {}.`
|
|
677
|
+
);
|
|
678
|
+
|
|
679
|
+
// Call AI to extract data
|
|
680
|
+
const agentOptions = this.agent.getAgentOptions();
|
|
681
|
+
try {
|
|
682
|
+
const result = await agentOptions.provider.generateMessage<TContext, Partial<TData>>({
|
|
683
|
+
prompt: extractionPrompt.join('\n'),
|
|
684
|
+
history,
|
|
685
|
+
context,
|
|
686
|
+
signal,
|
|
687
|
+
parameters: {
|
|
688
|
+
jsonSchema: extractionSchema,
|
|
689
|
+
schemaName: 'data_extraction',
|
|
690
|
+
},
|
|
691
|
+
});
|
|
692
|
+
|
|
693
|
+
return result.structured || {};
|
|
694
|
+
} catch (error) {
|
|
695
|
+
logger.error(`[ResponseModal] Pre-extraction failed:`, error);
|
|
696
|
+
return {};
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
|
|
489
700
|
/**
|
|
490
701
|
* Unified response generation for non-streaming responses
|
|
491
702
|
* @private
|
|
@@ -493,7 +704,17 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
493
704
|
private async generateUnifiedResponse(
|
|
494
705
|
responseContext: ResponseContext<TContext, TData>
|
|
495
706
|
): Promise<AgentResponse<TData>> {
|
|
496
|
-
const {
|
|
707
|
+
const {
|
|
708
|
+
effectiveContext,
|
|
709
|
+
session: initialSession,
|
|
710
|
+
history,
|
|
711
|
+
selectedRoute,
|
|
712
|
+
selectedStep,
|
|
713
|
+
responseDirectives,
|
|
714
|
+
isRouteComplete,
|
|
715
|
+
batchSteps,
|
|
716
|
+
batchStoppedReason,
|
|
717
|
+
} = responseContext;
|
|
497
718
|
let session = initialSession;
|
|
498
719
|
|
|
499
720
|
// Get last user message (needed for both route and completion handling)
|
|
@@ -503,56 +724,381 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
503
724
|
|
|
504
725
|
let message: string;
|
|
505
726
|
let toolCalls: Array<{ toolName: string; arguments: Record<string, unknown> }> | undefined = undefined;
|
|
727
|
+
let executedSteps: StepRef[] | undefined;
|
|
728
|
+
let stoppedReason: StoppedReason | undefined;
|
|
506
729
|
|
|
730
|
+
|
|
731
|
+
|
|
507
732
|
if (selectedRoute && !isRouteComplete) {
|
|
508
|
-
//
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
responseDirectives,
|
|
513
|
-
session,
|
|
514
|
-
history,
|
|
515
|
-
context: effectiveContext,
|
|
516
|
-
lastMessageText,
|
|
517
|
-
historyEvents,
|
|
518
|
-
signal: responseContext.history ? undefined : undefined, // TODO: Fix signal passing
|
|
519
|
-
});
|
|
733
|
+
// Check if we have batch steps to execute
|
|
734
|
+
if (batchSteps && batchSteps.length > 0) {
|
|
735
|
+
// BATCH EXECUTION: Execute multiple steps in a single LLM call
|
|
736
|
+
logger.debug(`[ResponseModal] Executing batch of ${batchSteps.length} steps`);
|
|
520
737
|
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
738
|
+
const batchResult = await this.executeBatchResponse({
|
|
739
|
+
selectedRoute,
|
|
740
|
+
batchSteps,
|
|
741
|
+
responseDirectives,
|
|
742
|
+
session,
|
|
743
|
+
history,
|
|
744
|
+
context: effectiveContext,
|
|
745
|
+
historyEvents,
|
|
746
|
+
});
|
|
747
|
+
|
|
748
|
+
message = batchResult.message;
|
|
749
|
+
toolCalls = batchResult.toolCalls;
|
|
750
|
+
session = batchResult.session;
|
|
751
|
+
executedSteps = batchResult.executedSteps;
|
|
752
|
+
stoppedReason = batchStoppedReason;
|
|
753
|
+
|
|
754
|
+
} else {
|
|
755
|
+
// SINGLE STEP EXECUTION: Fall back to single-step processing
|
|
756
|
+
// This happens when batch determination returns empty (first step needs input)
|
|
757
|
+
const result = await this.processRouteResponse({
|
|
758
|
+
selectedRoute,
|
|
759
|
+
selectedStep,
|
|
760
|
+
responseDirectives,
|
|
761
|
+
session,
|
|
762
|
+
history,
|
|
763
|
+
context: effectiveContext,
|
|
764
|
+
lastMessageText,
|
|
765
|
+
historyEvents,
|
|
766
|
+
signal: undefined,
|
|
767
|
+
});
|
|
768
|
+
|
|
769
|
+
message = result.message;
|
|
770
|
+
toolCalls = result.toolCalls;
|
|
771
|
+
session = result.session;
|
|
772
|
+
|
|
773
|
+
// Track executed step for single-step execution
|
|
774
|
+
if (selectedStep) {
|
|
775
|
+
executedSteps = [{
|
|
776
|
+
id: selectedStep.id,
|
|
777
|
+
routeId: selectedRoute.id,
|
|
778
|
+
}];
|
|
779
|
+
}
|
|
780
|
+
stoppedReason = batchStoppedReason || 'needs_input';
|
|
781
|
+
}
|
|
524
782
|
|
|
525
783
|
} else if (isRouteComplete && selectedRoute) {
|
|
526
784
|
// Handle route completion
|
|
527
|
-
message
|
|
528
|
-
selectedRoute,
|
|
529
|
-
session,
|
|
530
|
-
context: effectiveContext,
|
|
531
|
-
lastMessageText,
|
|
532
|
-
historyEvents,
|
|
533
|
-
});
|
|
785
|
+
logger.debug(`[ResponseModal] Generating completion message for route: ${selectedRoute.title}`);
|
|
534
786
|
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
787
|
+
try {
|
|
788
|
+
message = await this.handleRouteCompletion({
|
|
789
|
+
selectedRoute,
|
|
790
|
+
session,
|
|
791
|
+
context: effectiveContext,
|
|
792
|
+
lastMessageText,
|
|
793
|
+
historyEvents,
|
|
794
|
+
signal: undefined,
|
|
795
|
+
});
|
|
796
|
+
|
|
797
|
+
// Set step to END_ROUTE marker
|
|
798
|
+
session = enterStep(session, END_ROUTE_ID, "Route completed");
|
|
799
|
+
stoppedReason = 'route_complete';
|
|
800
|
+
logger.debug(`[ResponseModal] Route ${selectedRoute.title} completed. Entered END_ROUTE step.`);
|
|
801
|
+
} catch (error) {
|
|
802
|
+
logger.error(`[ResponseModal] Error generating completion message:`, error);
|
|
803
|
+
// Fallback to simple completion message
|
|
804
|
+
message = `Thank you! I've recorded all the information for your ${selectedRoute.title.toLowerCase()}.`;
|
|
805
|
+
session = enterStep(session, END_ROUTE_ID, "Route completed");
|
|
806
|
+
stoppedReason = 'route_complete';
|
|
807
|
+
}
|
|
538
808
|
|
|
539
809
|
} else {
|
|
540
810
|
// Fallback: No routes defined, generate a simple response
|
|
811
|
+
|
|
541
812
|
message = await this.generateFallbackResponse({
|
|
542
813
|
history: historyEvents, // Use Event[] for fallback response
|
|
543
814
|
context: effectiveContext,
|
|
544
815
|
session,
|
|
545
816
|
});
|
|
817
|
+
|
|
818
|
+
// For fallback responses, set empty executedSteps and no stoppedReason
|
|
819
|
+
// since there's no route/step execution happening
|
|
820
|
+
executedSteps = [];
|
|
821
|
+
stoppedReason = undefined;
|
|
546
822
|
}
|
|
547
823
|
|
|
824
|
+
// Ensure response structure completeness (Requirement 8.1, 8.2, 8.3)
|
|
825
|
+
// - executedSteps: array of steps executed (empty array if none)
|
|
826
|
+
// - stoppedReason: why execution stopped (undefined for fallback)
|
|
827
|
+
// - session.currentStep: reflects final step position
|
|
548
828
|
return {
|
|
549
829
|
message,
|
|
550
830
|
session,
|
|
551
831
|
toolCalls,
|
|
552
832
|
isRouteComplete,
|
|
833
|
+
executedSteps: executedSteps || [],
|
|
834
|
+
stoppedReason,
|
|
835
|
+
};
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
/**
|
|
839
|
+
* Execute a batch of steps with a single LLM call
|
|
840
|
+
*
|
|
841
|
+
* This method:
|
|
842
|
+
* 1. Executes all prepare hooks for steps in the batch (in order)
|
|
843
|
+
* 2. Builds a combined prompt using BatchPromptBuilder
|
|
844
|
+
* 3. Makes a single LLM call
|
|
845
|
+
* 4. Collects data from the response for all steps
|
|
846
|
+
* 5. Executes all finalize hooks for steps in the batch (in order)
|
|
847
|
+
*
|
|
848
|
+
* @private
|
|
849
|
+
* **Validates: Requirements 1.1, 4.4, 5.1, 5.2**
|
|
850
|
+
*/
|
|
851
|
+
private async executeBatchResponse(params: {
|
|
852
|
+
selectedRoute: Route<TContext, TData>;
|
|
853
|
+
batchSteps: StepOptions<TContext, TData>[];
|
|
854
|
+
responseDirectives?: string[];
|
|
855
|
+
session: SessionState<TData>;
|
|
856
|
+
history: HistoryItem[];
|
|
857
|
+
context: TContext;
|
|
858
|
+
historyEvents: Event[];
|
|
859
|
+
signal?: AbortSignal;
|
|
860
|
+
}): Promise<{
|
|
861
|
+
message: string;
|
|
862
|
+
toolCalls?: Array<{ toolName: string; arguments: Record<string, unknown> }>;
|
|
863
|
+
session: SessionState<TData>;
|
|
864
|
+
executedSteps: StepRef[];
|
|
865
|
+
}> {
|
|
866
|
+
const { selectedRoute, batchSteps, history, context, historyEvents, signal } = params;
|
|
867
|
+
let session = params.session;
|
|
868
|
+
|
|
869
|
+
logger.debug(`[ResponseModal] Starting batch execution for ${batchSteps.length} steps`);
|
|
870
|
+
|
|
871
|
+
// Create hook executor function
|
|
872
|
+
const executeHook = async (
|
|
873
|
+
hook: HookFunction<TContext, TData>,
|
|
874
|
+
hookContext: TContext,
|
|
875
|
+
data?: Partial<TData>,
|
|
876
|
+
step?: StepOptions<TContext, TData>
|
|
877
|
+
): Promise<void> => {
|
|
878
|
+
// Find the route for this step
|
|
879
|
+
const route = selectedRoute;
|
|
880
|
+
// Convert StepOptions to Step if needed for executePrepareFinalize
|
|
881
|
+
const stepInstance = step?.id ? route.getStep(step.id) : undefined;
|
|
882
|
+
await this.executePrepareFinalize(hook, hookContext, data, route, stepInstance);
|
|
883
|
+
};
|
|
884
|
+
|
|
885
|
+
// PHASE 1: Execute all prepare hooks (Requirement 5.1)
|
|
886
|
+
logger.debug(`[ResponseModal] Executing prepare hooks for batch`);
|
|
887
|
+
const prepareResult = await this.batchExecutor.executePrepareHooks({
|
|
888
|
+
steps: batchSteps,
|
|
889
|
+
context,
|
|
890
|
+
data: session.data,
|
|
891
|
+
executeHook,
|
|
892
|
+
});
|
|
893
|
+
|
|
894
|
+
if (!prepareResult.success) {
|
|
895
|
+
// Prepare hook failed - return error response
|
|
896
|
+
logger.error(`[ResponseModal] Prepare hook failed:`, prepareResult.error);
|
|
897
|
+
throw new ResponseGenerationError(
|
|
898
|
+
`Prepare hook failed: ${prepareResult.error?.message}`,
|
|
899
|
+
{
|
|
900
|
+
phase: 'prepare_hooks',
|
|
901
|
+
context: {
|
|
902
|
+
stepId: prepareResult.error?.stepId,
|
|
903
|
+
executedSteps: prepareResult.executedSteps,
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
);
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
// PHASE 2: Build combined prompt using BatchPromptBuilder (Requirement 4.4)
|
|
910
|
+
logger.debug(`[ResponseModal] Building batch prompt`);
|
|
911
|
+
const batchPromptResult = await this.batchPromptBuilder.buildBatchPrompt({
|
|
912
|
+
steps: batchSteps,
|
|
913
|
+
route: selectedRoute,
|
|
914
|
+
history: historyEvents,
|
|
915
|
+
context,
|
|
916
|
+
session,
|
|
917
|
+
agentOptions: this.agent.getAgentOptions(),
|
|
918
|
+
});
|
|
919
|
+
|
|
920
|
+
logger.debug(`[ResponseModal] Batch prompt built with ${batchPromptResult.stepCount} steps, collecting: ${batchPromptResult.collectFields.join(', ')}`);
|
|
921
|
+
|
|
922
|
+
// Build response schema for batch (includes all collect fields)
|
|
923
|
+
const responseSchema = this.buildBatchResponseSchema(batchPromptResult.collectFields);
|
|
924
|
+
|
|
925
|
+
// Collect available tools for AI (from all steps in batch)
|
|
926
|
+
const availableTools = this.collectBatchAvailableTools(selectedRoute, batchSteps);
|
|
927
|
+
|
|
928
|
+
// PHASE 3: Make single LLM call (Requirement 4.4)
|
|
929
|
+
logger.debug(`[ResponseModal] Making LLM call for batch`);
|
|
930
|
+
const agentOptions = this.agent.getAgentOptions();
|
|
931
|
+
const result = await agentOptions.provider.generateMessage({
|
|
932
|
+
prompt: batchPromptResult.prompt,
|
|
933
|
+
history: historyEvents,
|
|
934
|
+
context,
|
|
935
|
+
tools: availableTools,
|
|
936
|
+
signal,
|
|
937
|
+
parameters: responseSchema ? { jsonSchema: responseSchema, schemaName: "batch_response" } : undefined,
|
|
938
|
+
});
|
|
939
|
+
|
|
940
|
+
let message = result.structured?.message || result.message;
|
|
941
|
+
let toolCalls = result.structured?.toolCalls;
|
|
942
|
+
|
|
943
|
+
logger.debug(`[ResponseModal] LLM response received for batch`);
|
|
944
|
+
|
|
945
|
+
// Execute tools if any
|
|
946
|
+
if (toolCalls && toolCalls.length > 0) {
|
|
947
|
+
const toolResult = await this.executeUnifiedToolLoop({
|
|
948
|
+
toolCalls,
|
|
949
|
+
context,
|
|
950
|
+
session,
|
|
951
|
+
history,
|
|
952
|
+
selectedRoute,
|
|
953
|
+
responsePrompt: batchPromptResult.prompt,
|
|
954
|
+
availableTools,
|
|
955
|
+
responseSchema,
|
|
956
|
+
signal,
|
|
957
|
+
});
|
|
958
|
+
|
|
959
|
+
session = toolResult.session;
|
|
960
|
+
toolCalls = toolResult.finalToolCalls;
|
|
961
|
+
if (toolResult.finalMessage) {
|
|
962
|
+
message = toolResult.finalMessage;
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
// PHASE 4: Collect data from response for all steps (Requirement 6.1, 6.2, 6.3)
|
|
967
|
+
logger.debug(`[ResponseModal] Collecting batch data`);
|
|
968
|
+
const collectResult = this.batchExecutor.collectBatchData({
|
|
969
|
+
steps: batchSteps,
|
|
970
|
+
llmResponse: result.structured || {},
|
|
971
|
+
session,
|
|
972
|
+
schema: this.agent.getSchema(),
|
|
973
|
+
});
|
|
974
|
+
|
|
975
|
+
session = collectResult.session;
|
|
976
|
+
|
|
977
|
+
if (collectResult.collectedData && Object.keys(collectResult.collectedData).length > 0) {
|
|
978
|
+
// Update agent's collected data
|
|
979
|
+
await this.agent.updateCollectedData(collectResult.collectedData);
|
|
980
|
+
logger.debug(`[ResponseModal] Batch collected data:`, collectResult.collectedData);
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
if (collectResult.validationErrors && collectResult.validationErrors.length > 0) {
|
|
984
|
+
logger.warn(`[ResponseModal] Batch data validation errors:`, collectResult.validationErrors);
|
|
985
|
+
}
|
|
986
|
+
|
|
987
|
+
// Update session to final step position
|
|
988
|
+
const lastStep = batchSteps[batchSteps.length - 1];
|
|
989
|
+
if (lastStep?.id) {
|
|
990
|
+
session = enterStep(session, lastStep.id, lastStep.description);
|
|
991
|
+
logger.debug(`[ResponseModal] Updated session to final batch step: ${lastStep.id}`);
|
|
992
|
+
}
|
|
993
|
+
|
|
994
|
+
// PHASE 5: Execute all finalize hooks (Requirement 5.2)
|
|
995
|
+
logger.debug(`[ResponseModal] Executing finalize hooks for batch`);
|
|
996
|
+
const finalizeResult = await this.batchExecutor.executeFinalizeHooks({
|
|
997
|
+
steps: batchSteps,
|
|
998
|
+
context,
|
|
999
|
+
data: session.data,
|
|
1000
|
+
executeHook,
|
|
1001
|
+
});
|
|
1002
|
+
|
|
1003
|
+
if (finalizeResult.errors && finalizeResult.errors.length > 0) {
|
|
1004
|
+
// Log finalize errors but don't fail (Requirement 5.5)
|
|
1005
|
+
logger.warn(`[ResponseModal] Some finalize hooks failed:`, finalizeResult.errors);
|
|
1006
|
+
}
|
|
1007
|
+
|
|
1008
|
+
// Build executed steps list
|
|
1009
|
+
const executedSteps: StepRef[] = batchSteps
|
|
1010
|
+
.filter(step => step.id)
|
|
1011
|
+
.map(step => ({
|
|
1012
|
+
id: step.id!,
|
|
1013
|
+
routeId: selectedRoute.id,
|
|
1014
|
+
}));
|
|
1015
|
+
|
|
1016
|
+
logger.debug(`[ResponseModal] Batch execution complete. Executed ${executedSteps.length} steps`);
|
|
1017
|
+
|
|
1018
|
+
return {
|
|
1019
|
+
message,
|
|
1020
|
+
toolCalls,
|
|
1021
|
+
session,
|
|
1022
|
+
executedSteps,
|
|
1023
|
+
};
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1026
|
+
/**
|
|
1027
|
+
* Build response schema for batch execution
|
|
1028
|
+
* @private
|
|
1029
|
+
*/
|
|
1030
|
+
private buildBatchResponseSchema(collectFields: string[]): Record<string, unknown> {
|
|
1031
|
+
const properties: Record<string, unknown> = {
|
|
1032
|
+
message: {
|
|
1033
|
+
type: "string",
|
|
1034
|
+
description: "Your response to the user",
|
|
1035
|
+
},
|
|
1036
|
+
};
|
|
1037
|
+
|
|
1038
|
+
// Add collect fields to schema
|
|
1039
|
+
for (const field of collectFields) {
|
|
1040
|
+
properties[field] = {
|
|
1041
|
+
type: "string",
|
|
1042
|
+
description: `Collected value for ${field}`,
|
|
1043
|
+
};
|
|
1044
|
+
}
|
|
1045
|
+
|
|
1046
|
+
return {
|
|
1047
|
+
type: "object",
|
|
1048
|
+
properties,
|
|
1049
|
+
required: ["message"],
|
|
1050
|
+
additionalProperties: true,
|
|
553
1051
|
};
|
|
554
1052
|
}
|
|
555
1053
|
|
|
1054
|
+
/**
|
|
1055
|
+
* Collect available tools from all steps in the batch
|
|
1056
|
+
* @private
|
|
1057
|
+
*/
|
|
1058
|
+
private collectBatchAvailableTools(
|
|
1059
|
+
route: Route<TContext, TData>,
|
|
1060
|
+
batchSteps: StepOptions<TContext, TData>[]
|
|
1061
|
+
): Array<{
|
|
1062
|
+
id: string;
|
|
1063
|
+
name: string;
|
|
1064
|
+
description?: string;
|
|
1065
|
+
parameters?: unknown;
|
|
1066
|
+
}> {
|
|
1067
|
+
const availableTools = new Map<string, Tool<TContext, TData>>();
|
|
1068
|
+
|
|
1069
|
+
// Add agent-level tools
|
|
1070
|
+
this.agent.getTools().forEach((tool) => {
|
|
1071
|
+
availableTools.set(tool.id, tool);
|
|
1072
|
+
});
|
|
1073
|
+
|
|
1074
|
+
// Add route-level tools
|
|
1075
|
+
route.getTools().forEach((tool: Tool<TContext, TData>) => {
|
|
1076
|
+
availableTools.set(tool.id, tool);
|
|
1077
|
+
});
|
|
1078
|
+
|
|
1079
|
+
// Add step-level tools from all batch steps
|
|
1080
|
+
for (const step of batchSteps) {
|
|
1081
|
+
if (step.tools) {
|
|
1082
|
+
for (const toolRef of step.tools) {
|
|
1083
|
+
if (typeof toolRef === "string") {
|
|
1084
|
+
// Reference to registered tool - already in availableTools
|
|
1085
|
+
} else if (typeof toolRef === 'object' && 'id' in toolRef && toolRef.id) {
|
|
1086
|
+
// Inline tool definition
|
|
1087
|
+
availableTools.set(toolRef.id, toolRef);
|
|
1088
|
+
}
|
|
1089
|
+
}
|
|
1090
|
+
}
|
|
1091
|
+
}
|
|
1092
|
+
|
|
1093
|
+
// Convert to the format expected by AI providers
|
|
1094
|
+
return Array.from(availableTools.values()).map((tool) => ({
|
|
1095
|
+
id: tool.id,
|
|
1096
|
+
name: tool.name || tool.id,
|
|
1097
|
+
description: tool.description,
|
|
1098
|
+
parameters: tool.parameters,
|
|
1099
|
+
}));
|
|
1100
|
+
}
|
|
1101
|
+
|
|
556
1102
|
/**
|
|
557
1103
|
* Unified streaming response generation
|
|
558
1104
|
* @private
|
|
@@ -560,7 +1106,17 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
560
1106
|
private async *generateUnifiedStreamingResponse(
|
|
561
1107
|
responseContext: ResponseContext<TContext, TData>
|
|
562
1108
|
): AsyncGenerator<AgentResponseStreamChunk<TData>> {
|
|
563
|
-
const {
|
|
1109
|
+
const {
|
|
1110
|
+
effectiveContext,
|
|
1111
|
+
session: initialSession,
|
|
1112
|
+
history,
|
|
1113
|
+
selectedRoute,
|
|
1114
|
+
selectedStep,
|
|
1115
|
+
responseDirectives,
|
|
1116
|
+
isRouteComplete,
|
|
1117
|
+
batchSteps,
|
|
1118
|
+
batchStoppedReason,
|
|
1119
|
+
} = responseContext;
|
|
564
1120
|
const session = initialSession;
|
|
565
1121
|
|
|
566
1122
|
// Get last user message (needed for both route and completion handling)
|
|
@@ -569,17 +1125,35 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
569
1125
|
const lastMessageText = getLastMessageFromHistory(historyEvents);
|
|
570
1126
|
|
|
571
1127
|
if (selectedRoute && !isRouteComplete) {
|
|
572
|
-
//
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
1128
|
+
// Check if we have batch steps to execute
|
|
1129
|
+
if (batchSteps && batchSteps.length > 0) {
|
|
1130
|
+
// BATCH EXECUTION: Execute multiple steps with streaming
|
|
1131
|
+
// Note: For streaming, we still use batch execution but stream the response
|
|
1132
|
+
logger.debug(`[ResponseModal] Streaming batch execution for ${batchSteps.length} steps`);
|
|
1133
|
+
|
|
1134
|
+
yield* this.streamBatchResponse({
|
|
1135
|
+
selectedRoute,
|
|
1136
|
+
batchSteps,
|
|
1137
|
+
responseDirectives,
|
|
1138
|
+
session,
|
|
1139
|
+
history,
|
|
1140
|
+
context: effectiveContext,
|
|
1141
|
+
historyEvents,
|
|
1142
|
+
batchStoppedReason,
|
|
1143
|
+
});
|
|
1144
|
+
} else {
|
|
1145
|
+
// SINGLE STEP EXECUTION: Fall back to single-step streaming
|
|
1146
|
+
yield* this.processRouteStreamingResponse({
|
|
1147
|
+
selectedRoute,
|
|
1148
|
+
selectedStep,
|
|
1149
|
+
responseDirectives,
|
|
1150
|
+
session,
|
|
1151
|
+
history,
|
|
1152
|
+
context: effectiveContext,
|
|
1153
|
+
lastMessageText,
|
|
1154
|
+
historyEvents,
|
|
1155
|
+
});
|
|
1156
|
+
}
|
|
583
1157
|
|
|
584
1158
|
} else if (isRouteComplete && selectedRoute) {
|
|
585
1159
|
// Handle route completion streaming
|
|
@@ -600,6 +1174,148 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
600
1174
|
});
|
|
601
1175
|
}
|
|
602
1176
|
}
|
|
1177
|
+
|
|
1178
|
+
/**
|
|
1179
|
+
* Stream a batch response with multiple steps
|
|
1180
|
+
*
|
|
1181
|
+
* Similar to executeBatchResponse but streams the LLM response.
|
|
1182
|
+
*
|
|
1183
|
+
* @private
|
|
1184
|
+
*/
|
|
1185
|
+
private async *streamBatchResponse(params: {
|
|
1186
|
+
selectedRoute: Route<TContext, TData>;
|
|
1187
|
+
batchSteps: StepOptions<TContext, TData>[];
|
|
1188
|
+
responseDirectives?: string[];
|
|
1189
|
+
session: SessionState<TData>;
|
|
1190
|
+
history: HistoryItem[];
|
|
1191
|
+
context: TContext;
|
|
1192
|
+
historyEvents: Event[];
|
|
1193
|
+
batchStoppedReason?: StoppedReason;
|
|
1194
|
+
signal?: AbortSignal;
|
|
1195
|
+
}): AsyncGenerator<AgentResponseStreamChunk<TData>> {
|
|
1196
|
+
const { selectedRoute, batchSteps, context, historyEvents, batchStoppedReason, signal } = params;
|
|
1197
|
+
let session = params.session;
|
|
1198
|
+
|
|
1199
|
+
// Create hook executor function
|
|
1200
|
+
const executeHook = async (
|
|
1201
|
+
hook: HookFunction<TContext, TData>,
|
|
1202
|
+
hookContext: TContext,
|
|
1203
|
+
data?: Partial<TData>,
|
|
1204
|
+
step?: StepOptions<TContext, TData>
|
|
1205
|
+
): Promise<void> => {
|
|
1206
|
+
const route = selectedRoute;
|
|
1207
|
+
const stepInstance = step?.id ? route.getStep(step.id) : undefined;
|
|
1208
|
+
await this.executePrepareFinalize(hook, hookContext, data, route, stepInstance);
|
|
1209
|
+
};
|
|
1210
|
+
|
|
1211
|
+
// PHASE 1: Execute all prepare hooks
|
|
1212
|
+
const prepareResult = await this.batchExecutor.executePrepareHooks({
|
|
1213
|
+
steps: batchSteps,
|
|
1214
|
+
context,
|
|
1215
|
+
data: session.data,
|
|
1216
|
+
executeHook,
|
|
1217
|
+
});
|
|
1218
|
+
|
|
1219
|
+
if (!prepareResult.success) {
|
|
1220
|
+
// Yield error chunk
|
|
1221
|
+
yield {
|
|
1222
|
+
delta: "",
|
|
1223
|
+
accumulated: "",
|
|
1224
|
+
done: true,
|
|
1225
|
+
session,
|
|
1226
|
+
error: new ResponseGenerationError(
|
|
1227
|
+
`Prepare hook failed: ${prepareResult.error?.message}`,
|
|
1228
|
+
{ phase: 'prepare_hooks' }
|
|
1229
|
+
),
|
|
1230
|
+
};
|
|
1231
|
+
return;
|
|
1232
|
+
}
|
|
1233
|
+
|
|
1234
|
+
// PHASE 2: Build combined prompt
|
|
1235
|
+
const batchPromptResult = await this.batchPromptBuilder.buildBatchPrompt({
|
|
1236
|
+
steps: batchSteps,
|
|
1237
|
+
route: selectedRoute,
|
|
1238
|
+
history: historyEvents,
|
|
1239
|
+
context,
|
|
1240
|
+
session,
|
|
1241
|
+
agentOptions: this.agent.getAgentOptions(),
|
|
1242
|
+
});
|
|
1243
|
+
|
|
1244
|
+
const responseSchema = this.buildBatchResponseSchema(batchPromptResult.collectFields);
|
|
1245
|
+
const availableTools = this.collectBatchAvailableTools(selectedRoute, batchSteps);
|
|
1246
|
+
|
|
1247
|
+
// PHASE 3: Stream LLM response
|
|
1248
|
+
const agentOptions = this.agent.getAgentOptions();
|
|
1249
|
+
const stream = agentOptions.provider.generateMessageStream({
|
|
1250
|
+
prompt: batchPromptResult.prompt,
|
|
1251
|
+
history: historyEvents,
|
|
1252
|
+
context,
|
|
1253
|
+
tools: availableTools,
|
|
1254
|
+
signal,
|
|
1255
|
+
parameters: responseSchema ? { jsonSchema: responseSchema, schemaName: "batch_stream_response" } : undefined,
|
|
1256
|
+
});
|
|
1257
|
+
|
|
1258
|
+
// Build executed steps list
|
|
1259
|
+
const executedSteps: StepRef[] = batchSteps
|
|
1260
|
+
.filter(step => step.id)
|
|
1261
|
+
.map(step => ({
|
|
1262
|
+
id: step.id!,
|
|
1263
|
+
routeId: selectedRoute.id,
|
|
1264
|
+
}));
|
|
1265
|
+
|
|
1266
|
+
// Stream chunks
|
|
1267
|
+
for await (const chunk of stream) {
|
|
1268
|
+
// On final chunk, collect data and execute finalize hooks
|
|
1269
|
+
if (chunk.done) {
|
|
1270
|
+
// Collect data from response
|
|
1271
|
+
if (chunk.structured) {
|
|
1272
|
+
const collectResult = this.batchExecutor.collectBatchData({
|
|
1273
|
+
steps: batchSteps,
|
|
1274
|
+
llmResponse: chunk.structured,
|
|
1275
|
+
session,
|
|
1276
|
+
schema: this.agent.getSchema(),
|
|
1277
|
+
});
|
|
1278
|
+
|
|
1279
|
+
session = collectResult.session;
|
|
1280
|
+
|
|
1281
|
+
if (collectResult.collectedData && Object.keys(collectResult.collectedData).length > 0) {
|
|
1282
|
+
await this.agent.updateCollectedData(collectResult.collectedData);
|
|
1283
|
+
}
|
|
1284
|
+
}
|
|
1285
|
+
|
|
1286
|
+
// Update session to final step position
|
|
1287
|
+
const lastStep = batchSteps[batchSteps.length - 1];
|
|
1288
|
+
if (lastStep?.id) {
|
|
1289
|
+
session = enterStep(session, lastStep.id, lastStep.description);
|
|
1290
|
+
}
|
|
1291
|
+
|
|
1292
|
+
// Execute finalize hooks
|
|
1293
|
+
await this.batchExecutor.executeFinalizeHooks({
|
|
1294
|
+
steps: batchSteps,
|
|
1295
|
+
context,
|
|
1296
|
+
data: session.data,
|
|
1297
|
+
executeHook,
|
|
1298
|
+
});
|
|
1299
|
+
|
|
1300
|
+
// Finalize session
|
|
1301
|
+
await this.finalizeSession(session, context);
|
|
1302
|
+
}
|
|
1303
|
+
|
|
1304
|
+
yield {
|
|
1305
|
+
delta: chunk.delta,
|
|
1306
|
+
accumulated: chunk.accumulated,
|
|
1307
|
+
done: chunk.done,
|
|
1308
|
+
session,
|
|
1309
|
+
toolCalls: chunk.structured?.toolCalls,
|
|
1310
|
+
isRouteComplete: false,
|
|
1311
|
+
executedSteps: chunk.done ? executedSteps : undefined,
|
|
1312
|
+
stoppedReason: chunk.done ? batchStoppedReason : undefined,
|
|
1313
|
+
metadata: chunk.metadata,
|
|
1314
|
+
structured: chunk.structured,
|
|
1315
|
+
};
|
|
1316
|
+
}
|
|
1317
|
+
}
|
|
1318
|
+
|
|
603
1319
|
/**
|
|
604
1320
|
* Execute prepare function for current step if available
|
|
605
1321
|
* @private
|
|
@@ -679,12 +1395,27 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
679
1395
|
if (selectedStep) {
|
|
680
1396
|
nextStep = selectedStep;
|
|
681
1397
|
} else {
|
|
682
|
-
//
|
|
1398
|
+
// Determine current step from session if we're already in this route
|
|
1399
|
+
const isInSameRoute = session.currentRoute?.id === selectedRoute.id;
|
|
1400
|
+
const currentStep = isInSameRoute && session.currentStep
|
|
1401
|
+
? selectedRoute.getStep(session.currentStep.id)
|
|
1402
|
+
: undefined;
|
|
1403
|
+
|
|
1404
|
+
logger.debug(`[ResponseModal] Step determination: route match=${isInSameRoute}, currentRoute=${session.currentRoute?.id}, selectedRoute=${selectedRoute.id}, currentStep=${currentStep?.id || 'none'}`);
|
|
1405
|
+
|
|
1406
|
+
// Get candidate steps based on current position in the route
|
|
683
1407
|
const routingEngine = this.agent.getRoutingEngine();
|
|
684
|
-
const candidates = routingEngine.
|
|
1408
|
+
const candidates = await routingEngine.getCandidateStepsWithConditions(
|
|
1409
|
+
selectedRoute,
|
|
1410
|
+
currentStep, // Pass current step instead of undefined to maintain progression
|
|
1411
|
+
createTemplateContext({ data: session.data, session, context })
|
|
1412
|
+
);
|
|
1413
|
+
|
|
1414
|
+
logger.debug(`[ResponseModal] Found ${candidates.length} candidate steps${currentStep ? ' from current step ' + currentStep.id : ' (new route entry)'}`);
|
|
1415
|
+
|
|
685
1416
|
if (candidates.length > 0) {
|
|
686
1417
|
nextStep = candidates[0].step;
|
|
687
|
-
logger.debug(`[ResponseModal] Using first valid step: ${nextStep.id} for new route`);
|
|
1418
|
+
logger.debug(`[ResponseModal] Using first valid step: ${nextStep.id}${currentStep ? ' (progressing from ' + currentStep.id + ')' : ' for new route'}`);
|
|
688
1419
|
} else {
|
|
689
1420
|
// Fallback to initial step even if it should be skipped
|
|
690
1421
|
nextStep = selectedRoute.initialStep;
|
|
@@ -733,6 +1464,15 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
733
1464
|
let message = result.structured?.message || result.message;
|
|
734
1465
|
let toolCalls = result.structured?.toolCalls;
|
|
735
1466
|
|
|
1467
|
+
// Debug: Log initial AI response
|
|
1468
|
+
logger.debug(`[ResponseModal] Initial AI response:`, {
|
|
1469
|
+
hasMessage: !!message,
|
|
1470
|
+
messageLength: message?.length || 0,
|
|
1471
|
+
hasToolCalls: !!toolCalls,
|
|
1472
|
+
toolCallsCount: toolCalls?.length || 0,
|
|
1473
|
+
toolNames: toolCalls?.map(tc => tc.toolName) || [],
|
|
1474
|
+
});
|
|
1475
|
+
|
|
736
1476
|
// Execute tools with unified loop handling
|
|
737
1477
|
const toolResult = await this.executeUnifiedToolLoop({
|
|
738
1478
|
toolCalls,
|
|
@@ -781,11 +1521,22 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
781
1521
|
if (selectedStep) {
|
|
782
1522
|
nextStep = selectedStep;
|
|
783
1523
|
} else {
|
|
1524
|
+
// Determine current step from session if we're already in this route
|
|
1525
|
+
const currentStep = session.currentRoute?.id === selectedRoute.id && session.currentStep
|
|
1526
|
+
? selectedRoute.getStep(session.currentStep.id)
|
|
1527
|
+
: undefined;
|
|
1528
|
+
|
|
1529
|
+
// Get candidate steps based on current position in the route
|
|
784
1530
|
const routingEngine = this.agent.getRoutingEngine();
|
|
785
|
-
const candidates = routingEngine.
|
|
1531
|
+
const candidates = await routingEngine.getCandidateStepsWithConditions(
|
|
1532
|
+
selectedRoute,
|
|
1533
|
+
currentStep, // Pass current step instead of undefined to maintain progression
|
|
1534
|
+
createTemplateContext({ data: session.data, session, context })
|
|
1535
|
+
);
|
|
1536
|
+
|
|
786
1537
|
if (candidates.length > 0) {
|
|
787
1538
|
nextStep = candidates[0].step;
|
|
788
|
-
logger.debug(`[ResponseModal] Using first valid step: ${nextStep.id} for new route`);
|
|
1539
|
+
logger.debug(`[ResponseModal] Using first valid step: ${nextStep.id}${currentStep ? ' (progressing from ' + currentStep.id + ')' : ' for new route'}`);
|
|
789
1540
|
} else {
|
|
790
1541
|
nextStep = selectedRoute.initialStep;
|
|
791
1542
|
logger.warn(`[ResponseModal] No valid steps found, using initial step: ${nextStep.id}`);
|
|
@@ -868,6 +1619,10 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
868
1619
|
await this.finalizeSession(session, context);
|
|
869
1620
|
}
|
|
870
1621
|
|
|
1622
|
+
// Response structure completeness (Requirement 8.1, 8.2, 8.3)
|
|
1623
|
+
// - executedSteps: single step executed in this response
|
|
1624
|
+
// - stoppedReason: 'needs_input' for single-step execution (waiting for user input)
|
|
1625
|
+
// - session.currentStep: reflects the executed step
|
|
871
1626
|
yield {
|
|
872
1627
|
delta: chunk.delta,
|
|
873
1628
|
accumulated: chunk.accumulated,
|
|
@@ -875,6 +1630,8 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
875
1630
|
session,
|
|
876
1631
|
toolCalls,
|
|
877
1632
|
isRouteComplete: false,
|
|
1633
|
+
executedSteps: chunk.done ? [{ id: nextStep.id, routeId: selectedRoute.id }] : undefined,
|
|
1634
|
+
stoppedReason: chunk.done ? 'needs_input' : undefined,
|
|
878
1635
|
metadata: chunk.metadata,
|
|
879
1636
|
structured: chunk.structured,
|
|
880
1637
|
};
|
|
@@ -915,7 +1672,7 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
915
1672
|
|
|
916
1673
|
// Execute initial dynamic tool calls
|
|
917
1674
|
if (toolCalls && toolCalls.length > 0) {
|
|
918
|
-
logger.debug(`[ResponseModal] Executing ${toolCalls.length} dynamic tool calls
|
|
1675
|
+
logger.debug(`[ResponseModal] Executing ${toolCalls.length} dynamic tool calls:`, toolCalls.map(tc => tc.toolName));
|
|
919
1676
|
|
|
920
1677
|
for (const toolCall of toolCalls) {
|
|
921
1678
|
const tool = this.findAvailableTool(toolCall.toolName, selectedRoute);
|
|
@@ -925,16 +1682,24 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
925
1682
|
}
|
|
926
1683
|
|
|
927
1684
|
try {
|
|
928
|
-
|
|
929
|
-
const
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
1685
|
+
// Use ToolManager for unified tool execution
|
|
1686
|
+
const toolManager = this.getToolManager();
|
|
1687
|
+
let toolResult;
|
|
1688
|
+
|
|
1689
|
+
if (toolManager) {
|
|
1690
|
+
toolResult = await toolManager.executeTool({
|
|
1691
|
+
tool: tool,
|
|
1692
|
+
context,
|
|
1693
|
+
updateContext: this.agent.updateContext.bind(this.agent),
|
|
1694
|
+
updateData: this.agent.updateCollectedData.bind(this.agent),
|
|
1695
|
+
history: historyEvents, // Use Event[] for tool execution
|
|
1696
|
+
data: session.data,
|
|
1697
|
+
toolArguments: toolCall.arguments,
|
|
1698
|
+
});
|
|
1699
|
+
} else {
|
|
1700
|
+
// Fallback: execute tool directly if ToolManager not available
|
|
1701
|
+
throw new Error(`ToolManager not available for tool execution: ${toolCall.toolName}`);
|
|
1702
|
+
}
|
|
938
1703
|
|
|
939
1704
|
// Check if tool execution was successful
|
|
940
1705
|
if (!toolResult.success) {
|
|
@@ -965,7 +1730,7 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
965
1730
|
}
|
|
966
1731
|
}
|
|
967
1732
|
|
|
968
|
-
logger.debug(`[ResponseModal] Executed dynamic tool: ${
|
|
1733
|
+
logger.debug(`[ResponseModal] Executed dynamic tool: ${toolCall.toolName} (success: ${toolResult.success})`);
|
|
969
1734
|
} catch (error) {
|
|
970
1735
|
logger.error(`[ResponseModal] Tool execution error for ${toolCall.toolName}:`, error);
|
|
971
1736
|
// Continue with other tools rather than failing the entire response
|
|
@@ -982,7 +1747,7 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
982
1747
|
|
|
983
1748
|
while (hasToolCalls && toolLoopCount < MAX_TOOL_LOOPS) {
|
|
984
1749
|
toolLoopCount++;
|
|
985
|
-
logger.debug(`[ResponseModal] Starting tool loop ${toolLoopCount}/${MAX_TOOL_LOOPS}`);
|
|
1750
|
+
logger.debug(`[ResponseModal] Starting tool loop ${toolLoopCount}/${MAX_TOOL_LOOPS} with ${toolCalls?.length || 0} tool calls`);
|
|
986
1751
|
|
|
987
1752
|
// Create tool result events with proper Event format structure
|
|
988
1753
|
const toolResultEvents: Event<ToolEventData>[] = [];
|
|
@@ -1014,12 +1779,21 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
1014
1779
|
const updatedHistoryEvents = [...historyEvents, ...toolResultEvents];
|
|
1015
1780
|
|
|
1016
1781
|
// Make follow-up AI call to see if more tools are needed
|
|
1782
|
+
// After first iteration, don't provide tools to force a text response
|
|
1017
1783
|
const agentOptions = this.agent.getAgentOptions();
|
|
1784
|
+
const shouldProvideTools = toolLoopCount === 1;
|
|
1785
|
+
|
|
1786
|
+
logger.debug(`[ResponseModal] Making follow-up AI call (loop ${toolLoopCount}):`, {
|
|
1787
|
+
providingTools: shouldProvideTools,
|
|
1788
|
+
toolsCount: shouldProvideTools ? availableTools.length : 0,
|
|
1789
|
+
addingTextInstruction: toolLoopCount > 1,
|
|
1790
|
+
});
|
|
1791
|
+
|
|
1018
1792
|
const followUpResult = await agentOptions.provider.generateMessage({
|
|
1019
|
-
prompt: responsePrompt,
|
|
1793
|
+
prompt: responsePrompt + (toolLoopCount > 1 ? "\n\nProvide a text response to the user based on the tool results." : ""),
|
|
1020
1794
|
history: updatedHistoryEvents, // Use Event[] for AI provider
|
|
1021
1795
|
context,
|
|
1022
|
-
tools: availableTools,
|
|
1796
|
+
tools: shouldProvideTools ? availableTools : [], // Only provide tools on first iteration
|
|
1023
1797
|
parameters: responseSchema ? {
|
|
1024
1798
|
jsonSchema: responseSchema,
|
|
1025
1799
|
schemaName: "tool_followup",
|
|
@@ -1031,6 +1805,14 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
1031
1805
|
const followUpToolCalls = followUpResult.structured?.toolCalls;
|
|
1032
1806
|
hasToolCalls = followUpToolCalls && followUpToolCalls.length > 0;
|
|
1033
1807
|
|
|
1808
|
+
logger.debug(`[ResponseModal] Follow-up AI response (loop ${toolLoopCount}):`, {
|
|
1809
|
+
hasMessage: !!followUpResult.message,
|
|
1810
|
+
messageLength: followUpResult.message?.length || 0,
|
|
1811
|
+
hasToolCalls,
|
|
1812
|
+
toolCallsCount: followUpToolCalls?.length || 0,
|
|
1813
|
+
toolNames: followUpToolCalls?.map(tc => tc.toolName) || [],
|
|
1814
|
+
});
|
|
1815
|
+
|
|
1034
1816
|
if (hasToolCalls) {
|
|
1035
1817
|
logger.debug(`[ResponseModal] Follow-up call produced ${followUpToolCalls!.length} additional tool calls`);
|
|
1036
1818
|
|
|
@@ -1043,16 +1825,24 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
1043
1825
|
}
|
|
1044
1826
|
|
|
1045
1827
|
try {
|
|
1046
|
-
|
|
1047
|
-
const
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1828
|
+
// Use ToolManager for unified tool execution
|
|
1829
|
+
const toolManager = this.getToolManager();
|
|
1830
|
+
let toolResult;
|
|
1831
|
+
|
|
1832
|
+
if (toolManager) {
|
|
1833
|
+
toolResult = await toolManager.executeTool({
|
|
1834
|
+
tool: tool,
|
|
1835
|
+
context,
|
|
1836
|
+
updateContext: this.agent.updateContext.bind(this.agent),
|
|
1837
|
+
updateData: this.agent.updateCollectedData.bind(this.agent),
|
|
1838
|
+
history: updatedHistoryEvents, // Use Event[] for tool execution
|
|
1839
|
+
data: session.data,
|
|
1840
|
+
toolArguments: toolCall.arguments,
|
|
1841
|
+
});
|
|
1842
|
+
} else {
|
|
1843
|
+
// Fallback: execute tool directly if ToolManager not available
|
|
1844
|
+
throw new Error(`ToolManager not available for follow-up tool execution: ${toolCall.toolName}`);
|
|
1845
|
+
}
|
|
1056
1846
|
|
|
1057
1847
|
// Check if tool execution was successful
|
|
1058
1848
|
if (!toolResult.success) {
|
|
@@ -1079,7 +1869,7 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
1079
1869
|
}
|
|
1080
1870
|
}
|
|
1081
1871
|
|
|
1082
|
-
logger.debug(`[ResponseModal] Executed follow-up tool: ${
|
|
1872
|
+
logger.debug(`[ResponseModal] Executed follow-up tool: ${toolCall.toolName} (success: ${toolResult.success})`);
|
|
1083
1873
|
} catch (error) {
|
|
1084
1874
|
logger.error(`[ResponseModal] Follow-up tool execution error for ${toolCall.toolName}:`, error);
|
|
1085
1875
|
continue;
|
|
@@ -1101,6 +1891,13 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
1101
1891
|
logger.warn(`[ResponseModal] Tool loop limit reached (${MAX_TOOL_LOOPS}), stopping`);
|
|
1102
1892
|
}
|
|
1103
1893
|
|
|
1894
|
+
logger.debug(`[ResponseModal] Tool loop completed:`, {
|
|
1895
|
+
totalIterations: toolLoopCount,
|
|
1896
|
+
hasFinalMessage: !!finalMessage,
|
|
1897
|
+
finalMessageLength: finalMessage?.length || 0,
|
|
1898
|
+
finalToolCallsCount: toolCalls?.length || 0,
|
|
1899
|
+
});
|
|
1900
|
+
|
|
1104
1901
|
return {
|
|
1105
1902
|
session,
|
|
1106
1903
|
finalToolCalls: toolCalls,
|
|
@@ -1127,15 +1924,34 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
1127
1924
|
let updatedSession = session;
|
|
1128
1925
|
|
|
1129
1926
|
// Extract collected data from final response (only for route-based interactions)
|
|
1130
|
-
if (selectedRoute && result.structured
|
|
1927
|
+
if (selectedRoute && result.structured) {
|
|
1131
1928
|
try {
|
|
1132
1929
|
const collectedData: Record<string, unknown> = {};
|
|
1133
1930
|
// AgentStructuredResponse extends Record<string, unknown>, so we can safely access properties
|
|
1134
1931
|
const structuredData = result.structured;
|
|
1135
1932
|
|
|
1136
|
-
|
|
1933
|
+
// Collect ALL route fields (required + optional) from structured response
|
|
1934
|
+
const allRouteFields = new Set<string>();
|
|
1935
|
+
|
|
1936
|
+
// Add route required fields
|
|
1937
|
+
if (selectedRoute.requiredFields) {
|
|
1938
|
+
selectedRoute.requiredFields.forEach(field => allRouteFields.add(String(field)));
|
|
1939
|
+
}
|
|
1940
|
+
|
|
1941
|
+
// Add route optional fields
|
|
1942
|
+
if (selectedRoute.optionalFields) {
|
|
1943
|
+
selectedRoute.optionalFields.forEach(field => allRouteFields.add(String(field)));
|
|
1944
|
+
}
|
|
1945
|
+
|
|
1946
|
+
// Also include current step's collect fields (in case they're not in route fields)
|
|
1947
|
+
if (nextStep?.collect) {
|
|
1948
|
+
nextStep.collect.forEach(field => allRouteFields.add(String(field)));
|
|
1949
|
+
}
|
|
1950
|
+
|
|
1951
|
+
// Extract all available fields from structured response
|
|
1952
|
+
for (const field of allRouteFields) {
|
|
1137
1953
|
const fieldKey = String(field);
|
|
1138
|
-
if (fieldKey in structuredData) {
|
|
1954
|
+
if (fieldKey in structuredData && structuredData[fieldKey] !== undefined && structuredData[fieldKey] !== null) {
|
|
1139
1955
|
collectedData[fieldKey] = structuredData[fieldKey];
|
|
1140
1956
|
}
|
|
1141
1957
|
}
|
|
@@ -1209,37 +2025,66 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
1209
2025
|
prompt: endStepSpec.prompt || "Summarize what was accomplished and confirm completion based on the conversation history and collected data",
|
|
1210
2026
|
});
|
|
1211
2027
|
|
|
1212
|
-
// Build response schema for completion
|
|
1213
|
-
const
|
|
1214
|
-
|
|
2028
|
+
// Build response schema for completion (message only, no data collection)
|
|
2029
|
+
const completionSchema = {
|
|
2030
|
+
type: "object",
|
|
2031
|
+
properties: {
|
|
2032
|
+
message: {
|
|
2033
|
+
type: "string",
|
|
2034
|
+
description: "Completion message confirming what was accomplished",
|
|
2035
|
+
},
|
|
2036
|
+
},
|
|
2037
|
+
required: ["message"],
|
|
2038
|
+
additionalProperties: false,
|
|
2039
|
+
};
|
|
2040
|
+
|
|
2041
|
+
const templateContext = createTemplateContext({ context, session, history: historyEvents });
|
|
2042
|
+
|
|
2043
|
+
// Build completion response prompt using ResponseEngine
|
|
2044
|
+
// Filter out conditional guidelines - only include always-active ones
|
|
2045
|
+
const alwaysActiveGuidelines = [
|
|
2046
|
+
...this.agent.getGuidelines().filter(g => !g.condition),
|
|
2047
|
+
...selectedRoute.getGuidelines().filter(g => !g.condition),
|
|
2048
|
+
];
|
|
2049
|
+
let completitionPrompt = "Summarize what was accomplished and confirm completion"
|
|
2050
|
+
if(endStepSpec.prompt){
|
|
2051
|
+
completitionPrompt = await render(endStepSpec.prompt, templateContext)
|
|
2052
|
+
}
|
|
1215
2053
|
|
|
1216
|
-
// Build completion response prompt
|
|
1217
2054
|
const completionPrompt = await this.responseEngine.buildResponsePrompt({
|
|
1218
2055
|
route: selectedRoute,
|
|
1219
2056
|
currentStep: completionStep,
|
|
1220
2057
|
rules: selectedRoute.getRules(),
|
|
1221
2058
|
prohibitions: selectedRoute.getProhibitions(),
|
|
1222
|
-
directives:
|
|
1223
|
-
|
|
1224
|
-
|
|
2059
|
+
directives: [
|
|
2060
|
+
`Task completed: ${selectedRoute.title}`,
|
|
2061
|
+
`Collected data: ${JSON.stringify(session.data, null, 2)}`,
|
|
2062
|
+
"Do NOT ask for more information - the task is complete",
|
|
2063
|
+
completitionPrompt,
|
|
2064
|
+
],
|
|
2065
|
+
history: historyEvents,
|
|
2066
|
+
lastMessage: lastMessageText,
|
|
1225
2067
|
agentOptions: this.agent.getAgentOptions(),
|
|
1226
|
-
combinedGuidelines:
|
|
2068
|
+
combinedGuidelines: alwaysActiveGuidelines, // Only non-conditional guidelines
|
|
1227
2069
|
combinedTerms: this.mergeTerms(this.agent.getTerms(), selectedRoute.getTerms()),
|
|
1228
2070
|
context,
|
|
1229
2071
|
session,
|
|
1230
|
-
agentSchema:
|
|
2072
|
+
agentSchema: undefined, // No data collection schema for completion
|
|
1231
2073
|
});
|
|
1232
2074
|
|
|
1233
2075
|
// Generate completion message using AI provider
|
|
1234
2076
|
const agentOptions = this.agent.getAgentOptions();
|
|
2077
|
+
logger.debug(`[ResponseModal] Calling AI provider for completion message...`);
|
|
2078
|
+
|
|
1235
2079
|
const completionResult = await agentOptions.provider.generateMessage({
|
|
1236
2080
|
prompt: completionPrompt,
|
|
1237
|
-
history: historyEvents,
|
|
2081
|
+
history: historyEvents,
|
|
1238
2082
|
context,
|
|
1239
2083
|
signal,
|
|
1240
|
-
parameters: { jsonSchema:
|
|
2084
|
+
parameters: { jsonSchema: completionSchema, schemaName: "completion_message" },
|
|
1241
2085
|
});
|
|
1242
2086
|
|
|
2087
|
+
logger.debug(`[ResponseModal] AI provider returned completion result`);
|
|
1243
2088
|
const message = completionResult.structured?.message || completionResult.message;
|
|
1244
2089
|
logger.debug(`[ResponseModal] Generated completion message for route: ${selectedRoute.title}`);
|
|
1245
2090
|
|
|
@@ -1298,7 +2143,7 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
1298
2143
|
|
|
1299
2144
|
// Build response schema for completion
|
|
1300
2145
|
const responseSchema = this.responseEngine.responseSchemaForRoute(selectedRoute, completionStep, this.agent.getSchema());
|
|
1301
|
-
const templateContext = { context, session, history: historyEvents }; // Use Event[] for template context
|
|
2146
|
+
const templateContext = createTemplateContext({ context, session, history: historyEvents }); // Use Event[] for template context
|
|
1302
2147
|
|
|
1303
2148
|
// Build completion response prompt
|
|
1304
2149
|
const completionPrompt = await this.responseEngine.buildResponsePrompt({
|
|
@@ -1366,6 +2211,10 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
1366
2211
|
await this.finalizeSession(session, context);
|
|
1367
2212
|
}
|
|
1368
2213
|
|
|
2214
|
+
// Response structure completeness (Requirement 8.1, 8.2, 8.3)
|
|
2215
|
+
// - executedSteps: empty for route completion (no new steps executed)
|
|
2216
|
+
// - stoppedReason: 'route_complete' for completed routes
|
|
2217
|
+
// - session.currentStep: set to END_ROUTE
|
|
1369
2218
|
yield {
|
|
1370
2219
|
delta: chunk.delta,
|
|
1371
2220
|
accumulated: chunk.accumulated,
|
|
@@ -1373,6 +2222,8 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
1373
2222
|
session,
|
|
1374
2223
|
toolCalls: undefined,
|
|
1375
2224
|
isRouteComplete: true,
|
|
2225
|
+
executedSteps: chunk.done ? [] : undefined,
|
|
2226
|
+
stoppedReason: chunk.done ? 'route_complete' : undefined,
|
|
1376
2227
|
metadata: chunk.metadata,
|
|
1377
2228
|
structured: chunk.structured,
|
|
1378
2229
|
};
|
|
@@ -1467,6 +2318,10 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
1467
2318
|
await this.finalizeSession(session, context);
|
|
1468
2319
|
}
|
|
1469
2320
|
|
|
2321
|
+
// Response structure completeness (Requirement 8.1, 8.2, 8.3)
|
|
2322
|
+
// - executedSteps: empty for fallback (no route/step execution)
|
|
2323
|
+
// - stoppedReason: undefined for fallback (no route context)
|
|
2324
|
+
// - session.currentStep: unchanged (no step progression)
|
|
1470
2325
|
yield {
|
|
1471
2326
|
delta: chunk.delta,
|
|
1472
2327
|
accumulated: chunk.accumulated,
|
|
@@ -1474,6 +2329,8 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
1474
2329
|
session,
|
|
1475
2330
|
toolCalls: undefined,
|
|
1476
2331
|
isRouteComplete: false,
|
|
2332
|
+
executedSteps: chunk.done ? [] : undefined,
|
|
2333
|
+
stoppedReason: undefined,
|
|
1477
2334
|
metadata: chunk.metadata,
|
|
1478
2335
|
structured: chunk.structured,
|
|
1479
2336
|
};
|
|
@@ -1511,19 +2368,28 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
1511
2368
|
// ============================================================================
|
|
1512
2369
|
|
|
1513
2370
|
/**
|
|
1514
|
-
* Find an available tool by name for the given route
|
|
1515
|
-
*
|
|
2371
|
+
* Find an available tool by name for the given route using ToolManager
|
|
2372
|
+
* Delegates to ToolManager for unified tool resolution
|
|
1516
2373
|
* @private
|
|
1517
2374
|
*/
|
|
1518
2375
|
private findAvailableTool(
|
|
1519
2376
|
toolName: string,
|
|
1520
2377
|
route?: Route<TContext, TData>
|
|
1521
|
-
): Tool<TContext, TData
|
|
2378
|
+
): Tool<TContext, TData> | undefined {
|
|
2379
|
+
// Use ToolManager for unified tool resolution
|
|
2380
|
+
const toolManager = this.getToolManager();
|
|
2381
|
+
if (toolManager) {
|
|
2382
|
+
return toolManager.find(toolName, undefined, undefined, route);
|
|
2383
|
+
}
|
|
2384
|
+
|
|
2385
|
+
// Fallback to legacy resolution if ToolManager not available
|
|
2386
|
+
logger.warn(`[ResponseModal] ToolManager not available, using legacy tool resolution for: ${toolName}`);
|
|
2387
|
+
|
|
1522
2388
|
// Check route-level tools first (if route provided)
|
|
1523
2389
|
if (route) {
|
|
1524
2390
|
const routeTool = route
|
|
1525
2391
|
.getTools()
|
|
1526
|
-
.find((tool: Tool<TContext, TData
|
|
2392
|
+
.find((tool: Tool<TContext, TData>) => tool.id === toolName || tool.name === toolName);
|
|
1527
2393
|
if (routeTool) return routeTool;
|
|
1528
2394
|
}
|
|
1529
2395
|
|
|
@@ -1535,7 +2401,8 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
1535
2401
|
}
|
|
1536
2402
|
|
|
1537
2403
|
/**
|
|
1538
|
-
* Collect all available tools for the given route and step context
|
|
2404
|
+
* Collect all available tools for the given route and step context using ToolManager
|
|
2405
|
+
* Delegates to ToolManager for unified tool resolution and deduplication
|
|
1539
2406
|
* @private
|
|
1540
2407
|
*/
|
|
1541
2408
|
private collectAvailableTools(
|
|
@@ -1547,7 +2414,22 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
1547
2414
|
description?: string;
|
|
1548
2415
|
parameters?: unknown;
|
|
1549
2416
|
}> {
|
|
1550
|
-
|
|
2417
|
+
// Use ToolManager for unified tool collection if available
|
|
2418
|
+
const toolManager = this.getToolManager();
|
|
2419
|
+
if (toolManager) {
|
|
2420
|
+
const availableTools = toolManager.getAvailable(undefined, step, route);
|
|
2421
|
+
return availableTools.map((tool) => ({
|
|
2422
|
+
id: tool.id,
|
|
2423
|
+
name: tool.name || tool.id,
|
|
2424
|
+
description: tool.description,
|
|
2425
|
+
parameters: tool.parameters,
|
|
2426
|
+
}));
|
|
2427
|
+
}
|
|
2428
|
+
|
|
2429
|
+
// Fallback to legacy collection logic if ToolManager not available
|
|
2430
|
+
logger.warn(`[ResponseModal] ToolManager not available, using legacy tool collection`);
|
|
2431
|
+
|
|
2432
|
+
const availableTools = new Map<string, Tool<TContext, TData>>();
|
|
1551
2433
|
|
|
1552
2434
|
// Add agent-level tools
|
|
1553
2435
|
this.agent.getTools().forEach((tool) => {
|
|
@@ -1556,7 +2438,7 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
1556
2438
|
|
|
1557
2439
|
// Add route-level tools (these take precedence)
|
|
1558
2440
|
if (route) {
|
|
1559
|
-
route.getTools().forEach((tool: Tool<TContext, TData
|
|
2441
|
+
route.getTools().forEach((tool: Tool<TContext, TData>) => {
|
|
1560
2442
|
availableTools.set(tool.id, tool);
|
|
1561
2443
|
});
|
|
1562
2444
|
}
|
|
@@ -1564,7 +2446,7 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
1564
2446
|
// Filter by step-level allowed tools if specified
|
|
1565
2447
|
if (step?.tools) {
|
|
1566
2448
|
const allowedToolIds = new Set<string>();
|
|
1567
|
-
const stepTools: Tool<TContext, TData
|
|
2449
|
+
const stepTools: Tool<TContext, TData>[] = [];
|
|
1568
2450
|
|
|
1569
2451
|
for (const toolRef of step.tools) {
|
|
1570
2452
|
if (typeof toolRef === "string") {
|
|
@@ -1581,7 +2463,7 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
1581
2463
|
|
|
1582
2464
|
// If step specifies tools, only include those
|
|
1583
2465
|
if (allowedToolIds.size > 0) {
|
|
1584
|
-
const filteredTools = new Map<string, Tool<TContext, TData
|
|
2466
|
+
const filteredTools = new Map<string, Tool<TContext, TData>>();
|
|
1585
2467
|
for (const toolId of Array.from(allowedToolIds)) {
|
|
1586
2468
|
const tool = availableTools.get(toolId);
|
|
1587
2469
|
if (tool) {
|
|
@@ -1615,7 +2497,7 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
1615
2497
|
private async executePrepareFinalize(
|
|
1616
2498
|
prepareOrFinalize:
|
|
1617
2499
|
| string
|
|
1618
|
-
| Tool<TContext, TData
|
|
2500
|
+
| Tool<TContext, TData>
|
|
1619
2501
|
| ((context: TContext, data?: Partial<TData>) => void | Promise<void>)
|
|
1620
2502
|
| undefined,
|
|
1621
2503
|
context: TContext,
|
|
@@ -1630,51 +2512,67 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
1630
2512
|
await prepareOrFinalize(context, data);
|
|
1631
2513
|
} else {
|
|
1632
2514
|
// It's a tool reference - find and execute the tool
|
|
1633
|
-
let tool: Tool<TContext, TData
|
|
2515
|
+
let tool: Tool<TContext, TData> | undefined;
|
|
1634
2516
|
|
|
1635
2517
|
if (typeof prepareOrFinalize === "string") {
|
|
1636
|
-
// Tool ID -
|
|
1637
|
-
const
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
2518
|
+
// Tool ID - use ToolManager for unified resolution
|
|
2519
|
+
const toolManager = this.getToolManager();
|
|
2520
|
+
if (toolManager) {
|
|
2521
|
+
tool = toolManager.find(prepareOrFinalize, undefined, step, route);
|
|
2522
|
+
} else {
|
|
2523
|
+
// Fallback to legacy resolution if ToolManager not available
|
|
2524
|
+
logger.warn(`[ResponseModal] ToolManager not available, using legacy tool resolution for prepare/finalize: ${prepareOrFinalize}`);
|
|
2525
|
+
|
|
2526
|
+
const availableTools = new Map<string, Tool<TContext, TData>>();
|
|
1643
2527
|
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
route.getTools().forEach((t: Tool<TContext, TData, unknown[], unknown>) => {
|
|
2528
|
+
// Add agent-level tools
|
|
2529
|
+
this.agent.getTools().forEach((t) => {
|
|
1647
2530
|
availableTools.set(t.id, t);
|
|
1648
2531
|
});
|
|
1649
|
-
}
|
|
1650
2532
|
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
2533
|
+
// Add route-level tools
|
|
2534
|
+
if (route) {
|
|
2535
|
+
route.getTools().forEach((t: Tool<TContext, TData>) => {
|
|
2536
|
+
availableTools.set(t.id, t);
|
|
2537
|
+
});
|
|
2538
|
+
}
|
|
2539
|
+
|
|
2540
|
+
// Add step-level tools
|
|
2541
|
+
if (step?.tools) {
|
|
2542
|
+
for (const toolRef of step.tools) {
|
|
2543
|
+
if (typeof toolRef === "string") {
|
|
2544
|
+
// Keep as is
|
|
2545
|
+
} else if (typeof toolRef === 'object' && 'id' in toolRef && toolRef.id) {
|
|
2546
|
+
availableTools.set(toolRef.id, toolRef);
|
|
2547
|
+
}
|
|
1658
2548
|
}
|
|
1659
2549
|
}
|
|
1660
|
-
}
|
|
1661
2550
|
|
|
1662
|
-
|
|
2551
|
+
tool = availableTools.get(prepareOrFinalize);
|
|
2552
|
+
}
|
|
1663
2553
|
} else {
|
|
1664
2554
|
// Tool object - use directly
|
|
1665
2555
|
tool = prepareOrFinalize;
|
|
1666
2556
|
}
|
|
1667
2557
|
|
|
1668
2558
|
if (tool) {
|
|
1669
|
-
|
|
1670
|
-
const
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
2559
|
+
// Use ToolManager for unified tool execution
|
|
2560
|
+
const toolManager = this.getToolManager();
|
|
2561
|
+
let result;
|
|
2562
|
+
|
|
2563
|
+
if (toolManager) {
|
|
2564
|
+
result = await toolManager.executeTool({
|
|
2565
|
+
tool,
|
|
2566
|
+
context,
|
|
2567
|
+
updateContext: this.agent.updateContext.bind(this.agent),
|
|
2568
|
+
updateData: this.agent.updateCollectedData.bind(this.agent),
|
|
2569
|
+
history: [], // Empty history for prepare/finalize
|
|
2570
|
+
data,
|
|
2571
|
+
});
|
|
2572
|
+
} else {
|
|
2573
|
+
// Fallback: execute tool directly if ToolManager not available
|
|
2574
|
+
throw new Error(`ToolManager not available for prepare/finalize tool execution: ${typeof prepareOrFinalize === "string" ? prepareOrFinalize : "inline tool"}`);
|
|
2575
|
+
}
|
|
1678
2576
|
|
|
1679
2577
|
if (!result.success) {
|
|
1680
2578
|
logger.error(
|