@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
|
@@ -6,8 +6,10 @@ import { EventKind, MessageRole } from "../types";
|
|
|
6
6
|
import { Step } from "./Step";
|
|
7
7
|
import { ResponseEngine } from "./ResponseEngine";
|
|
8
8
|
import { ResponsePipeline } from "./ResponsePipeline";
|
|
9
|
+
import { BatchExecutor } from "./BatchExecutor";
|
|
10
|
+
import { BatchPromptBuilder } from "./BatchPromptBuilder";
|
|
9
11
|
import { cloneDeep, mergeCollected, enterStep, getLastMessageFromHistory, render, logger, historyToEvents } from "../utils";
|
|
10
|
-
import {
|
|
12
|
+
import { createTemplateContext } from "../utils/template";
|
|
11
13
|
import { END_ROUTE_ID } from "../constants";
|
|
12
14
|
/**
|
|
13
15
|
* Error class for response generation failures
|
|
@@ -47,7 +49,12 @@ export class ResponseModal {
|
|
|
47
49
|
// Initialize response engine
|
|
48
50
|
this.responseEngine = new ResponseEngine();
|
|
49
51
|
// Initialize response pipeline with agent dependencies
|
|
50
|
-
this.responsePipeline = new ResponsePipeline(this.agent.getAgentOptions(),
|
|
52
|
+
this.responsePipeline = new ResponsePipeline(this.agent.getAgentOptions(), () => this.agent.getRoutes(), // Pass a function to get routes dynamically
|
|
53
|
+
this.agent.getTools(), this.agent.getRoutingEngine(), this.agent.updateContext.bind(this.agent), this.agent.getUpdateDataMethod(), this.agent.updateCollectedData.bind(this.agent), this.getToolManager());
|
|
54
|
+
// Initialize batch executor for multi-step execution
|
|
55
|
+
this.batchExecutor = new BatchExecutor();
|
|
56
|
+
// Initialize batch prompt builder for combined prompts
|
|
57
|
+
this.batchPromptBuilder = new BatchPromptBuilder();
|
|
51
58
|
}
|
|
52
59
|
/**
|
|
53
60
|
* Generate a non-streaming response using unified logic
|
|
@@ -191,6 +198,19 @@ export class ResponseModal {
|
|
|
191
198
|
getResponsePipeline() {
|
|
192
199
|
return this.responsePipeline;
|
|
193
200
|
}
|
|
201
|
+
/**
|
|
202
|
+
* Get the ToolManager instance from the agent
|
|
203
|
+
* @private
|
|
204
|
+
*/
|
|
205
|
+
getToolManager() {
|
|
206
|
+
// Check if agent has a tool property (ToolManager)
|
|
207
|
+
if (this.agent && 'tool' in this.agent && this.agent.tool) {
|
|
208
|
+
return this.agent.tool;
|
|
209
|
+
}
|
|
210
|
+
// Log warning if ToolManager is not available
|
|
211
|
+
logger.warn(`[ResponseModal] ToolManager not available on agent - tool execution will use fallback methods`);
|
|
212
|
+
return undefined;
|
|
213
|
+
}
|
|
194
214
|
// UNIFIED RESPONSE LOGIC - Consolidates common logic between streaming and non-streaming
|
|
195
215
|
// ============================================================================
|
|
196
216
|
/**
|
|
@@ -255,6 +275,7 @@ export class ResponseModal {
|
|
|
255
275
|
throw ResponseGenerationError.fromError(error, 'step_preparation', params, { session, effectiveContext });
|
|
256
276
|
}
|
|
257
277
|
// PHASE 2: ROUTING + STEP SELECTION - Determine which route and step to use
|
|
278
|
+
// Also performs pre-extraction and batch determination
|
|
258
279
|
let routingResult;
|
|
259
280
|
try {
|
|
260
281
|
routingResult = await this.handleUnifiedRoutingAndStepSelection({
|
|
@@ -275,6 +296,9 @@ export class ResponseModal {
|
|
|
275
296
|
selectedStep: routingResult.selectedStep,
|
|
276
297
|
responseDirectives: routingResult.responseDirectives,
|
|
277
298
|
isRouteComplete: routingResult.isRouteComplete,
|
|
299
|
+
batchSteps: routingResult.batchSteps,
|
|
300
|
+
batchStoppedReason: routingResult.batchStoppedReason,
|
|
301
|
+
batchStoppedAtStep: routingResult.batchStoppedAtStep,
|
|
278
302
|
};
|
|
279
303
|
}
|
|
280
304
|
catch (error) {
|
|
@@ -300,31 +324,156 @@ export class ResponseModal {
|
|
|
300
324
|
context: params.context,
|
|
301
325
|
signal: params.signal,
|
|
302
326
|
});
|
|
327
|
+
let updatedSession = routingResult.session;
|
|
328
|
+
let isRouteComplete = routingResult.isRouteComplete;
|
|
329
|
+
// PRE-EXTRACTION: If entering a route that collects data, extract data from user message first
|
|
330
|
+
// This allows us to skip steps whose data is already provided
|
|
331
|
+
// Requirement 3.1: Perform Pre_Extraction before determining the Batch
|
|
332
|
+
if (routingResult.selectedRoute && !isRouteComplete) {
|
|
333
|
+
// Always pre-extract when route collects data (not just on new route entry)
|
|
334
|
+
// This ensures batch determination has the most up-to-date data
|
|
335
|
+
if (this.shouldPreExtractData(routingResult.selectedRoute)) {
|
|
336
|
+
logger.debug(`[ResponseModal] Pre-extracting data for route: ${routingResult.selectedRoute.title}`);
|
|
337
|
+
const extractedData = await this.preExtractRouteData({
|
|
338
|
+
route: routingResult.selectedRoute,
|
|
339
|
+
history: params.history,
|
|
340
|
+
context: params.context,
|
|
341
|
+
session: updatedSession,
|
|
342
|
+
signal: params.signal,
|
|
343
|
+
});
|
|
344
|
+
if (extractedData && Object.keys(extractedData).length > 0) {
|
|
345
|
+
logger.debug(`[ResponseModal] Pre-extracted data:`, extractedData);
|
|
346
|
+
// Requirement 3.3: Merge pre-extracted data into session before batch determination
|
|
347
|
+
updatedSession = mergeCollected(updatedSession, extractedData);
|
|
348
|
+
// Also update agent's collected data
|
|
349
|
+
await this.agent.updateCollectedData(extractedData);
|
|
350
|
+
// Re-check route completion after pre-extraction
|
|
351
|
+
const allRequiredFieldsCollected = routingResult.selectedRoute.isComplete(updatedSession.data || {});
|
|
352
|
+
if (allRequiredFieldsCollected) {
|
|
353
|
+
logger.debug(`[ResponseModal] Route ${routingResult.selectedRoute.title} completed after pre-extraction`);
|
|
354
|
+
isRouteComplete = true;
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
// BATCH DETERMINATION: Use BatchExecutor to determine which steps can execute together
|
|
360
|
+
// Requirement 3.4: Pre-extraction results affect batch determination
|
|
361
|
+
let batchSteps;
|
|
362
|
+
let batchStoppedReason;
|
|
363
|
+
let batchStoppedAtStep;
|
|
364
|
+
if (routingResult.selectedRoute && !isRouteComplete) {
|
|
365
|
+
// Determine current step position for batch determination
|
|
366
|
+
const currentStep = routingResult.selectedStep ||
|
|
367
|
+
(updatedSession.currentStep ? routingResult.selectedRoute.getStep(updatedSession.currentStep.id) : undefined);
|
|
368
|
+
logger.debug(`[ResponseModal] Determining batch starting from step: ${currentStep?.id || 'initial'}`);
|
|
369
|
+
const batchResult = await this.batchExecutor.determineBatch({
|
|
370
|
+
route: routingResult.selectedRoute,
|
|
371
|
+
currentStep,
|
|
372
|
+
sessionData: updatedSession.data || {},
|
|
373
|
+
context: params.context,
|
|
374
|
+
});
|
|
375
|
+
batchSteps = batchResult.steps;
|
|
376
|
+
batchStoppedReason = batchResult.stoppedReason;
|
|
377
|
+
batchStoppedAtStep = batchResult.stoppedAtStep;
|
|
378
|
+
logger.debug(`[ResponseModal] Batch determined: ${batchSteps.length} steps, stopped reason: ${batchStoppedReason}`);
|
|
379
|
+
}
|
|
303
380
|
// Determine next step using pipeline method for consistency
|
|
304
|
-
const stepResult = this.responsePipeline.determineNextStep({
|
|
381
|
+
const stepResult = await this.responsePipeline.determineNextStep({
|
|
305
382
|
selectedRoute: routingResult.selectedRoute,
|
|
306
383
|
selectedStep: routingResult.selectedStep,
|
|
307
|
-
session:
|
|
308
|
-
isRouteComplete
|
|
384
|
+
session: updatedSession, // Use updated session with pre-extracted data
|
|
385
|
+
isRouteComplete, // Use updated completion status
|
|
309
386
|
});
|
|
310
387
|
return {
|
|
311
388
|
selectedRoute: routingResult.selectedRoute,
|
|
312
389
|
selectedStep: stepResult.nextStep, // Use the determined next step
|
|
313
390
|
responseDirectives: routingResult.responseDirectives,
|
|
314
391
|
session: stepResult.session,
|
|
315
|
-
isRouteComplete
|
|
392
|
+
isRouteComplete, // Use updated completion status
|
|
393
|
+
batchSteps,
|
|
394
|
+
batchStoppedReason,
|
|
395
|
+
batchStoppedAtStep,
|
|
316
396
|
};
|
|
317
397
|
}
|
|
318
398
|
catch (error) {
|
|
319
399
|
throw ResponseGenerationError.fromError(error, 'routing_optimization', params);
|
|
320
400
|
}
|
|
321
401
|
}
|
|
402
|
+
/**
|
|
403
|
+
* Check if a route should pre-extract data before determining the initial step
|
|
404
|
+
* @private
|
|
405
|
+
*/
|
|
406
|
+
shouldPreExtractData(route) {
|
|
407
|
+
// Pre-extract if route has declared required or optional fields
|
|
408
|
+
if (route.requiredFields && route.requiredFields.length > 0) {
|
|
409
|
+
return true;
|
|
410
|
+
}
|
|
411
|
+
if (route.optionalFields && route.optionalFields.length > 0) {
|
|
412
|
+
return true;
|
|
413
|
+
}
|
|
414
|
+
// Pre-extract if any step in the route collects data
|
|
415
|
+
const steps = route.getAllSteps();
|
|
416
|
+
const hasDataCollectionSteps = steps.some(step => step.collect && step.collect.length > 0);
|
|
417
|
+
return hasDataCollectionSteps;
|
|
418
|
+
}
|
|
419
|
+
/**
|
|
420
|
+
* Pre-extract data from user message when entering a route
|
|
421
|
+
* This allows skipping steps whose data is already provided
|
|
422
|
+
* @private
|
|
423
|
+
*/
|
|
424
|
+
async preExtractRouteData(params) {
|
|
425
|
+
const { route, history, context, signal } = params;
|
|
426
|
+
// Build a schema for data extraction based on route's fields
|
|
427
|
+
const extractionSchema = this.agent.getSchema();
|
|
428
|
+
if (!extractionSchema) {
|
|
429
|
+
logger.warn(`[ResponseModal] No schema available for pre-extraction`);
|
|
430
|
+
return {};
|
|
431
|
+
}
|
|
432
|
+
// Get last user message
|
|
433
|
+
const lastMessage = getLastMessageFromHistory(history);
|
|
434
|
+
// Build extraction prompt
|
|
435
|
+
const extractionPrompt = [
|
|
436
|
+
`Extract any relevant information from the user's message that matches the following data fields.`,
|
|
437
|
+
`Only extract information that is explicitly stated or clearly implied.`,
|
|
438
|
+
``,
|
|
439
|
+
`User's message: "${lastMessage}"`,
|
|
440
|
+
``,
|
|
441
|
+
`Extract data for these fields if present:`,
|
|
442
|
+
];
|
|
443
|
+
// Add field descriptions
|
|
444
|
+
if (route.requiredFields) {
|
|
445
|
+
extractionPrompt.push(`Required fields: ${route.requiredFields.join(', ')}`);
|
|
446
|
+
}
|
|
447
|
+
if (route.optionalFields) {
|
|
448
|
+
extractionPrompt.push(`Optional fields: ${route.optionalFields.join(', ')}`);
|
|
449
|
+
}
|
|
450
|
+
extractionPrompt.push(``, `Return ONLY the extracted data as JSON. If no data can be extracted, return an empty object {}.`);
|
|
451
|
+
// Call AI to extract data
|
|
452
|
+
const agentOptions = this.agent.getAgentOptions();
|
|
453
|
+
try {
|
|
454
|
+
const result = await agentOptions.provider.generateMessage({
|
|
455
|
+
prompt: extractionPrompt.join('\n'),
|
|
456
|
+
history,
|
|
457
|
+
context,
|
|
458
|
+
signal,
|
|
459
|
+
parameters: {
|
|
460
|
+
jsonSchema: extractionSchema,
|
|
461
|
+
schemaName: 'data_extraction',
|
|
462
|
+
},
|
|
463
|
+
});
|
|
464
|
+
return result.structured || {};
|
|
465
|
+
}
|
|
466
|
+
catch (error) {
|
|
467
|
+
logger.error(`[ResponseModal] Pre-extraction failed:`, error);
|
|
468
|
+
return {};
|
|
469
|
+
}
|
|
470
|
+
}
|
|
322
471
|
/**
|
|
323
472
|
* Unified response generation for non-streaming responses
|
|
324
473
|
* @private
|
|
325
474
|
*/
|
|
326
475
|
async generateUnifiedResponse(responseContext) {
|
|
327
|
-
const { effectiveContext, session: initialSession, history, selectedRoute, selectedStep, responseDirectives, isRouteComplete } = responseContext;
|
|
476
|
+
const { effectiveContext, session: initialSession, history, selectedRoute, selectedStep, responseDirectives, isRouteComplete, batchSteps, batchStoppedReason, } = responseContext;
|
|
328
477
|
let session = initialSession;
|
|
329
478
|
// Get last user message (needed for both route and completion handling)
|
|
330
479
|
// Convert HistoryItem[] to Event[] for internal processing
|
|
@@ -332,35 +481,79 @@ export class ResponseModal {
|
|
|
332
481
|
const lastMessageText = getLastMessageFromHistory(historyEvents);
|
|
333
482
|
let message;
|
|
334
483
|
let toolCalls = undefined;
|
|
484
|
+
let executedSteps;
|
|
485
|
+
let stoppedReason;
|
|
335
486
|
if (selectedRoute && !isRouteComplete) {
|
|
336
|
-
//
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
487
|
+
// Check if we have batch steps to execute
|
|
488
|
+
if (batchSteps && batchSteps.length > 0) {
|
|
489
|
+
// BATCH EXECUTION: Execute multiple steps in a single LLM call
|
|
490
|
+
logger.debug(`[ResponseModal] Executing batch of ${batchSteps.length} steps`);
|
|
491
|
+
const batchResult = await this.executeBatchResponse({
|
|
492
|
+
selectedRoute,
|
|
493
|
+
batchSteps,
|
|
494
|
+
responseDirectives,
|
|
495
|
+
session,
|
|
496
|
+
history,
|
|
497
|
+
context: effectiveContext,
|
|
498
|
+
historyEvents,
|
|
499
|
+
});
|
|
500
|
+
message = batchResult.message;
|
|
501
|
+
toolCalls = batchResult.toolCalls;
|
|
502
|
+
session = batchResult.session;
|
|
503
|
+
executedSteps = batchResult.executedSteps;
|
|
504
|
+
stoppedReason = batchStoppedReason;
|
|
505
|
+
}
|
|
506
|
+
else {
|
|
507
|
+
// SINGLE STEP EXECUTION: Fall back to single-step processing
|
|
508
|
+
// This happens when batch determination returns empty (first step needs input)
|
|
509
|
+
const result = await this.processRouteResponse({
|
|
510
|
+
selectedRoute,
|
|
511
|
+
selectedStep,
|
|
512
|
+
responseDirectives,
|
|
513
|
+
session,
|
|
514
|
+
history,
|
|
515
|
+
context: effectiveContext,
|
|
516
|
+
lastMessageText,
|
|
517
|
+
historyEvents,
|
|
518
|
+
signal: undefined,
|
|
519
|
+
});
|
|
520
|
+
message = result.message;
|
|
521
|
+
toolCalls = result.toolCalls;
|
|
522
|
+
session = result.session;
|
|
523
|
+
// Track executed step for single-step execution
|
|
524
|
+
if (selectedStep) {
|
|
525
|
+
executedSteps = [{
|
|
526
|
+
id: selectedStep.id,
|
|
527
|
+
routeId: selectedRoute.id,
|
|
528
|
+
}];
|
|
529
|
+
}
|
|
530
|
+
stoppedReason = batchStoppedReason || 'needs_input';
|
|
531
|
+
}
|
|
351
532
|
}
|
|
352
533
|
else if (isRouteComplete && selectedRoute) {
|
|
353
534
|
// Handle route completion
|
|
354
|
-
message
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
535
|
+
logger.debug(`[ResponseModal] Generating completion message for route: ${selectedRoute.title}`);
|
|
536
|
+
try {
|
|
537
|
+
message = await this.handleRouteCompletion({
|
|
538
|
+
selectedRoute,
|
|
539
|
+
session,
|
|
540
|
+
context: effectiveContext,
|
|
541
|
+
lastMessageText,
|
|
542
|
+
historyEvents,
|
|
543
|
+
signal: undefined,
|
|
544
|
+
});
|
|
545
|
+
// Set step to END_ROUTE marker
|
|
546
|
+
session = enterStep(session, END_ROUTE_ID, "Route completed");
|
|
547
|
+
stoppedReason = 'route_complete';
|
|
548
|
+
logger.debug(`[ResponseModal] Route ${selectedRoute.title} completed. Entered END_ROUTE step.`);
|
|
549
|
+
}
|
|
550
|
+
catch (error) {
|
|
551
|
+
logger.error(`[ResponseModal] Error generating completion message:`, error);
|
|
552
|
+
// Fallback to simple completion message
|
|
553
|
+
message = `Thank you! I've recorded all the information for your ${selectedRoute.title.toLowerCase()}.`;
|
|
554
|
+
session = enterStep(session, END_ROUTE_ID, "Route completed");
|
|
555
|
+
stoppedReason = 'route_complete';
|
|
556
|
+
}
|
|
364
557
|
}
|
|
365
558
|
else {
|
|
366
559
|
// Fallback: No routes defined, generate a simple response
|
|
@@ -369,37 +562,268 @@ export class ResponseModal {
|
|
|
369
562
|
context: effectiveContext,
|
|
370
563
|
session,
|
|
371
564
|
});
|
|
565
|
+
// For fallback responses, set empty executedSteps and no stoppedReason
|
|
566
|
+
// since there's no route/step execution happening
|
|
567
|
+
executedSteps = [];
|
|
568
|
+
stoppedReason = undefined;
|
|
372
569
|
}
|
|
570
|
+
// Ensure response structure completeness (Requirement 8.1, 8.2, 8.3)
|
|
571
|
+
// - executedSteps: array of steps executed (empty array if none)
|
|
572
|
+
// - stoppedReason: why execution stopped (undefined for fallback)
|
|
573
|
+
// - session.currentStep: reflects final step position
|
|
373
574
|
return {
|
|
374
575
|
message,
|
|
375
576
|
session,
|
|
376
577
|
toolCalls,
|
|
377
578
|
isRouteComplete,
|
|
579
|
+
executedSteps: executedSteps || [],
|
|
580
|
+
stoppedReason,
|
|
581
|
+
};
|
|
582
|
+
}
|
|
583
|
+
/**
|
|
584
|
+
* Execute a batch of steps with a single LLM call
|
|
585
|
+
*
|
|
586
|
+
* This method:
|
|
587
|
+
* 1. Executes all prepare hooks for steps in the batch (in order)
|
|
588
|
+
* 2. Builds a combined prompt using BatchPromptBuilder
|
|
589
|
+
* 3. Makes a single LLM call
|
|
590
|
+
* 4. Collects data from the response for all steps
|
|
591
|
+
* 5. Executes all finalize hooks for steps in the batch (in order)
|
|
592
|
+
*
|
|
593
|
+
* @private
|
|
594
|
+
* **Validates: Requirements 1.1, 4.4, 5.1, 5.2**
|
|
595
|
+
*/
|
|
596
|
+
async executeBatchResponse(params) {
|
|
597
|
+
const { selectedRoute, batchSteps, history, context, historyEvents, signal } = params;
|
|
598
|
+
let session = params.session;
|
|
599
|
+
logger.debug(`[ResponseModal] Starting batch execution for ${batchSteps.length} steps`);
|
|
600
|
+
// Create hook executor function
|
|
601
|
+
const executeHook = async (hook, hookContext, data, step) => {
|
|
602
|
+
// Find the route for this step
|
|
603
|
+
const route = selectedRoute;
|
|
604
|
+
// Convert StepOptions to Step if needed for executePrepareFinalize
|
|
605
|
+
const stepInstance = step?.id ? route.getStep(step.id) : undefined;
|
|
606
|
+
await this.executePrepareFinalize(hook, hookContext, data, route, stepInstance);
|
|
607
|
+
};
|
|
608
|
+
// PHASE 1: Execute all prepare hooks (Requirement 5.1)
|
|
609
|
+
logger.debug(`[ResponseModal] Executing prepare hooks for batch`);
|
|
610
|
+
const prepareResult = await this.batchExecutor.executePrepareHooks({
|
|
611
|
+
steps: batchSteps,
|
|
612
|
+
context,
|
|
613
|
+
data: session.data,
|
|
614
|
+
executeHook,
|
|
615
|
+
});
|
|
616
|
+
if (!prepareResult.success) {
|
|
617
|
+
// Prepare hook failed - return error response
|
|
618
|
+
logger.error(`[ResponseModal] Prepare hook failed:`, prepareResult.error);
|
|
619
|
+
throw new ResponseGenerationError(`Prepare hook failed: ${prepareResult.error?.message}`, {
|
|
620
|
+
phase: 'prepare_hooks',
|
|
621
|
+
context: {
|
|
622
|
+
stepId: prepareResult.error?.stepId,
|
|
623
|
+
executedSteps: prepareResult.executedSteps,
|
|
624
|
+
}
|
|
625
|
+
});
|
|
626
|
+
}
|
|
627
|
+
// PHASE 2: Build combined prompt using BatchPromptBuilder (Requirement 4.4)
|
|
628
|
+
logger.debug(`[ResponseModal] Building batch prompt`);
|
|
629
|
+
const batchPromptResult = await this.batchPromptBuilder.buildBatchPrompt({
|
|
630
|
+
steps: batchSteps,
|
|
631
|
+
route: selectedRoute,
|
|
632
|
+
history: historyEvents,
|
|
633
|
+
context,
|
|
634
|
+
session,
|
|
635
|
+
agentOptions: this.agent.getAgentOptions(),
|
|
636
|
+
});
|
|
637
|
+
logger.debug(`[ResponseModal] Batch prompt built with ${batchPromptResult.stepCount} steps, collecting: ${batchPromptResult.collectFields.join(', ')}`);
|
|
638
|
+
// Build response schema for batch (includes all collect fields)
|
|
639
|
+
const responseSchema = this.buildBatchResponseSchema(batchPromptResult.collectFields);
|
|
640
|
+
// Collect available tools for AI (from all steps in batch)
|
|
641
|
+
const availableTools = this.collectBatchAvailableTools(selectedRoute, batchSteps);
|
|
642
|
+
// PHASE 3: Make single LLM call (Requirement 4.4)
|
|
643
|
+
logger.debug(`[ResponseModal] Making LLM call for batch`);
|
|
644
|
+
const agentOptions = this.agent.getAgentOptions();
|
|
645
|
+
const result = await agentOptions.provider.generateMessage({
|
|
646
|
+
prompt: batchPromptResult.prompt,
|
|
647
|
+
history: historyEvents,
|
|
648
|
+
context,
|
|
649
|
+
tools: availableTools,
|
|
650
|
+
signal,
|
|
651
|
+
parameters: responseSchema ? { jsonSchema: responseSchema, schemaName: "batch_response" } : undefined,
|
|
652
|
+
});
|
|
653
|
+
let message = result.structured?.message || result.message;
|
|
654
|
+
let toolCalls = result.structured?.toolCalls;
|
|
655
|
+
logger.debug(`[ResponseModal] LLM response received for batch`);
|
|
656
|
+
// Execute tools if any
|
|
657
|
+
if (toolCalls && toolCalls.length > 0) {
|
|
658
|
+
const toolResult = await this.executeUnifiedToolLoop({
|
|
659
|
+
toolCalls,
|
|
660
|
+
context,
|
|
661
|
+
session,
|
|
662
|
+
history,
|
|
663
|
+
selectedRoute,
|
|
664
|
+
responsePrompt: batchPromptResult.prompt,
|
|
665
|
+
availableTools,
|
|
666
|
+
responseSchema,
|
|
667
|
+
signal,
|
|
668
|
+
});
|
|
669
|
+
session = toolResult.session;
|
|
670
|
+
toolCalls = toolResult.finalToolCalls;
|
|
671
|
+
if (toolResult.finalMessage) {
|
|
672
|
+
message = toolResult.finalMessage;
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
// PHASE 4: Collect data from response for all steps (Requirement 6.1, 6.2, 6.3)
|
|
676
|
+
logger.debug(`[ResponseModal] Collecting batch data`);
|
|
677
|
+
const collectResult = this.batchExecutor.collectBatchData({
|
|
678
|
+
steps: batchSteps,
|
|
679
|
+
llmResponse: result.structured || {},
|
|
680
|
+
session,
|
|
681
|
+
schema: this.agent.getSchema(),
|
|
682
|
+
});
|
|
683
|
+
session = collectResult.session;
|
|
684
|
+
if (collectResult.collectedData && Object.keys(collectResult.collectedData).length > 0) {
|
|
685
|
+
// Update agent's collected data
|
|
686
|
+
await this.agent.updateCollectedData(collectResult.collectedData);
|
|
687
|
+
logger.debug(`[ResponseModal] Batch collected data:`, collectResult.collectedData);
|
|
688
|
+
}
|
|
689
|
+
if (collectResult.validationErrors && collectResult.validationErrors.length > 0) {
|
|
690
|
+
logger.warn(`[ResponseModal] Batch data validation errors:`, collectResult.validationErrors);
|
|
691
|
+
}
|
|
692
|
+
// Update session to final step position
|
|
693
|
+
const lastStep = batchSteps[batchSteps.length - 1];
|
|
694
|
+
if (lastStep?.id) {
|
|
695
|
+
session = enterStep(session, lastStep.id, lastStep.description);
|
|
696
|
+
logger.debug(`[ResponseModal] Updated session to final batch step: ${lastStep.id}`);
|
|
697
|
+
}
|
|
698
|
+
// PHASE 5: Execute all finalize hooks (Requirement 5.2)
|
|
699
|
+
logger.debug(`[ResponseModal] Executing finalize hooks for batch`);
|
|
700
|
+
const finalizeResult = await this.batchExecutor.executeFinalizeHooks({
|
|
701
|
+
steps: batchSteps,
|
|
702
|
+
context,
|
|
703
|
+
data: session.data,
|
|
704
|
+
executeHook,
|
|
705
|
+
});
|
|
706
|
+
if (finalizeResult.errors && finalizeResult.errors.length > 0) {
|
|
707
|
+
// Log finalize errors but don't fail (Requirement 5.5)
|
|
708
|
+
logger.warn(`[ResponseModal] Some finalize hooks failed:`, finalizeResult.errors);
|
|
709
|
+
}
|
|
710
|
+
// Build executed steps list
|
|
711
|
+
const executedSteps = batchSteps
|
|
712
|
+
.filter(step => step.id)
|
|
713
|
+
.map(step => ({
|
|
714
|
+
id: step.id,
|
|
715
|
+
routeId: selectedRoute.id,
|
|
716
|
+
}));
|
|
717
|
+
logger.debug(`[ResponseModal] Batch execution complete. Executed ${executedSteps.length} steps`);
|
|
718
|
+
return {
|
|
719
|
+
message,
|
|
720
|
+
toolCalls,
|
|
721
|
+
session,
|
|
722
|
+
executedSteps,
|
|
723
|
+
};
|
|
724
|
+
}
|
|
725
|
+
/**
|
|
726
|
+
* Build response schema for batch execution
|
|
727
|
+
* @private
|
|
728
|
+
*/
|
|
729
|
+
buildBatchResponseSchema(collectFields) {
|
|
730
|
+
const properties = {
|
|
731
|
+
message: {
|
|
732
|
+
type: "string",
|
|
733
|
+
description: "Your response to the user",
|
|
734
|
+
},
|
|
735
|
+
};
|
|
736
|
+
// Add collect fields to schema
|
|
737
|
+
for (const field of collectFields) {
|
|
738
|
+
properties[field] = {
|
|
739
|
+
type: "string",
|
|
740
|
+
description: `Collected value for ${field}`,
|
|
741
|
+
};
|
|
742
|
+
}
|
|
743
|
+
return {
|
|
744
|
+
type: "object",
|
|
745
|
+
properties,
|
|
746
|
+
required: ["message"],
|
|
747
|
+
additionalProperties: true,
|
|
378
748
|
};
|
|
379
749
|
}
|
|
750
|
+
/**
|
|
751
|
+
* Collect available tools from all steps in the batch
|
|
752
|
+
* @private
|
|
753
|
+
*/
|
|
754
|
+
collectBatchAvailableTools(route, batchSteps) {
|
|
755
|
+
const availableTools = new Map();
|
|
756
|
+
// Add agent-level tools
|
|
757
|
+
this.agent.getTools().forEach((tool) => {
|
|
758
|
+
availableTools.set(tool.id, tool);
|
|
759
|
+
});
|
|
760
|
+
// Add route-level tools
|
|
761
|
+
route.getTools().forEach((tool) => {
|
|
762
|
+
availableTools.set(tool.id, tool);
|
|
763
|
+
});
|
|
764
|
+
// Add step-level tools from all batch steps
|
|
765
|
+
for (const step of batchSteps) {
|
|
766
|
+
if (step.tools) {
|
|
767
|
+
for (const toolRef of step.tools) {
|
|
768
|
+
if (typeof toolRef === "string") {
|
|
769
|
+
// Reference to registered tool - already in availableTools
|
|
770
|
+
}
|
|
771
|
+
else if (typeof toolRef === 'object' && 'id' in toolRef && toolRef.id) {
|
|
772
|
+
// Inline tool definition
|
|
773
|
+
availableTools.set(toolRef.id, toolRef);
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
// Convert to the format expected by AI providers
|
|
779
|
+
return Array.from(availableTools.values()).map((tool) => ({
|
|
780
|
+
id: tool.id,
|
|
781
|
+
name: tool.name || tool.id,
|
|
782
|
+
description: tool.description,
|
|
783
|
+
parameters: tool.parameters,
|
|
784
|
+
}));
|
|
785
|
+
}
|
|
380
786
|
/**
|
|
381
787
|
* Unified streaming response generation
|
|
382
788
|
* @private
|
|
383
789
|
*/
|
|
384
790
|
async *generateUnifiedStreamingResponse(responseContext) {
|
|
385
|
-
const { effectiveContext, session: initialSession, history, selectedRoute, selectedStep, responseDirectives, isRouteComplete } = responseContext;
|
|
791
|
+
const { effectiveContext, session: initialSession, history, selectedRoute, selectedStep, responseDirectives, isRouteComplete, batchSteps, batchStoppedReason, } = responseContext;
|
|
386
792
|
const session = initialSession;
|
|
387
793
|
// Get last user message (needed for both route and completion handling)
|
|
388
794
|
// Convert HistoryItem[] to Event[] for internal processing
|
|
389
795
|
const historyEvents = historyToEvents(history);
|
|
390
796
|
const lastMessageText = getLastMessageFromHistory(historyEvents);
|
|
391
797
|
if (selectedRoute && !isRouteComplete) {
|
|
392
|
-
//
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
798
|
+
// Check if we have batch steps to execute
|
|
799
|
+
if (batchSteps && batchSteps.length > 0) {
|
|
800
|
+
// BATCH EXECUTION: Execute multiple steps with streaming
|
|
801
|
+
// Note: For streaming, we still use batch execution but stream the response
|
|
802
|
+
logger.debug(`[ResponseModal] Streaming batch execution for ${batchSteps.length} steps`);
|
|
803
|
+
yield* this.streamBatchResponse({
|
|
804
|
+
selectedRoute,
|
|
805
|
+
batchSteps,
|
|
806
|
+
responseDirectives,
|
|
807
|
+
session,
|
|
808
|
+
history,
|
|
809
|
+
context: effectiveContext,
|
|
810
|
+
historyEvents,
|
|
811
|
+
batchStoppedReason,
|
|
812
|
+
});
|
|
813
|
+
}
|
|
814
|
+
else {
|
|
815
|
+
// SINGLE STEP EXECUTION: Fall back to single-step streaming
|
|
816
|
+
yield* this.processRouteStreamingResponse({
|
|
817
|
+
selectedRoute,
|
|
818
|
+
selectedStep,
|
|
819
|
+
responseDirectives,
|
|
820
|
+
session,
|
|
821
|
+
history,
|
|
822
|
+
context: effectiveContext,
|
|
823
|
+
lastMessageText,
|
|
824
|
+
historyEvents,
|
|
825
|
+
});
|
|
826
|
+
}
|
|
403
827
|
}
|
|
404
828
|
else if (isRouteComplete && selectedRoute) {
|
|
405
829
|
// Handle route completion streaming
|
|
@@ -420,6 +844,114 @@ export class ResponseModal {
|
|
|
420
844
|
});
|
|
421
845
|
}
|
|
422
846
|
}
|
|
847
|
+
/**
|
|
848
|
+
* Stream a batch response with multiple steps
|
|
849
|
+
*
|
|
850
|
+
* Similar to executeBatchResponse but streams the LLM response.
|
|
851
|
+
*
|
|
852
|
+
* @private
|
|
853
|
+
*/
|
|
854
|
+
async *streamBatchResponse(params) {
|
|
855
|
+
const { selectedRoute, batchSteps, context, historyEvents, batchStoppedReason, signal } = params;
|
|
856
|
+
let session = params.session;
|
|
857
|
+
// Create hook executor function
|
|
858
|
+
const executeHook = async (hook, hookContext, data, step) => {
|
|
859
|
+
const route = selectedRoute;
|
|
860
|
+
const stepInstance = step?.id ? route.getStep(step.id) : undefined;
|
|
861
|
+
await this.executePrepareFinalize(hook, hookContext, data, route, stepInstance);
|
|
862
|
+
};
|
|
863
|
+
// PHASE 1: Execute all prepare hooks
|
|
864
|
+
const prepareResult = await this.batchExecutor.executePrepareHooks({
|
|
865
|
+
steps: batchSteps,
|
|
866
|
+
context,
|
|
867
|
+
data: session.data,
|
|
868
|
+
executeHook,
|
|
869
|
+
});
|
|
870
|
+
if (!prepareResult.success) {
|
|
871
|
+
// Yield error chunk
|
|
872
|
+
yield {
|
|
873
|
+
delta: "",
|
|
874
|
+
accumulated: "",
|
|
875
|
+
done: true,
|
|
876
|
+
session,
|
|
877
|
+
error: new ResponseGenerationError(`Prepare hook failed: ${prepareResult.error?.message}`, { phase: 'prepare_hooks' }),
|
|
878
|
+
};
|
|
879
|
+
return;
|
|
880
|
+
}
|
|
881
|
+
// PHASE 2: Build combined prompt
|
|
882
|
+
const batchPromptResult = await this.batchPromptBuilder.buildBatchPrompt({
|
|
883
|
+
steps: batchSteps,
|
|
884
|
+
route: selectedRoute,
|
|
885
|
+
history: historyEvents,
|
|
886
|
+
context,
|
|
887
|
+
session,
|
|
888
|
+
agentOptions: this.agent.getAgentOptions(),
|
|
889
|
+
});
|
|
890
|
+
const responseSchema = this.buildBatchResponseSchema(batchPromptResult.collectFields);
|
|
891
|
+
const availableTools = this.collectBatchAvailableTools(selectedRoute, batchSteps);
|
|
892
|
+
// PHASE 3: Stream LLM response
|
|
893
|
+
const agentOptions = this.agent.getAgentOptions();
|
|
894
|
+
const stream = agentOptions.provider.generateMessageStream({
|
|
895
|
+
prompt: batchPromptResult.prompt,
|
|
896
|
+
history: historyEvents,
|
|
897
|
+
context,
|
|
898
|
+
tools: availableTools,
|
|
899
|
+
signal,
|
|
900
|
+
parameters: responseSchema ? { jsonSchema: responseSchema, schemaName: "batch_stream_response" } : undefined,
|
|
901
|
+
});
|
|
902
|
+
// Build executed steps list
|
|
903
|
+
const executedSteps = batchSteps
|
|
904
|
+
.filter(step => step.id)
|
|
905
|
+
.map(step => ({
|
|
906
|
+
id: step.id,
|
|
907
|
+
routeId: selectedRoute.id,
|
|
908
|
+
}));
|
|
909
|
+
// Stream chunks
|
|
910
|
+
for await (const chunk of stream) {
|
|
911
|
+
// On final chunk, collect data and execute finalize hooks
|
|
912
|
+
if (chunk.done) {
|
|
913
|
+
// Collect data from response
|
|
914
|
+
if (chunk.structured) {
|
|
915
|
+
const collectResult = this.batchExecutor.collectBatchData({
|
|
916
|
+
steps: batchSteps,
|
|
917
|
+
llmResponse: chunk.structured,
|
|
918
|
+
session,
|
|
919
|
+
schema: this.agent.getSchema(),
|
|
920
|
+
});
|
|
921
|
+
session = collectResult.session;
|
|
922
|
+
if (collectResult.collectedData && Object.keys(collectResult.collectedData).length > 0) {
|
|
923
|
+
await this.agent.updateCollectedData(collectResult.collectedData);
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
// Update session to final step position
|
|
927
|
+
const lastStep = batchSteps[batchSteps.length - 1];
|
|
928
|
+
if (lastStep?.id) {
|
|
929
|
+
session = enterStep(session, lastStep.id, lastStep.description);
|
|
930
|
+
}
|
|
931
|
+
// Execute finalize hooks
|
|
932
|
+
await this.batchExecutor.executeFinalizeHooks({
|
|
933
|
+
steps: batchSteps,
|
|
934
|
+
context,
|
|
935
|
+
data: session.data,
|
|
936
|
+
executeHook,
|
|
937
|
+
});
|
|
938
|
+
// Finalize session
|
|
939
|
+
await this.finalizeSession(session, context);
|
|
940
|
+
}
|
|
941
|
+
yield {
|
|
942
|
+
delta: chunk.delta,
|
|
943
|
+
accumulated: chunk.accumulated,
|
|
944
|
+
done: chunk.done,
|
|
945
|
+
session,
|
|
946
|
+
toolCalls: chunk.structured?.toolCalls,
|
|
947
|
+
isRouteComplete: false,
|
|
948
|
+
executedSteps: chunk.done ? executedSteps : undefined,
|
|
949
|
+
stoppedReason: chunk.done ? batchStoppedReason : undefined,
|
|
950
|
+
metadata: chunk.metadata,
|
|
951
|
+
structured: chunk.structured,
|
|
952
|
+
};
|
|
953
|
+
}
|
|
954
|
+
}
|
|
423
955
|
/**
|
|
424
956
|
* Execute prepare function for current step if available
|
|
425
957
|
* @private
|
|
@@ -465,12 +997,20 @@ export class ResponseModal {
|
|
|
465
997
|
nextStep = selectedStep;
|
|
466
998
|
}
|
|
467
999
|
else {
|
|
468
|
-
//
|
|
1000
|
+
// Determine current step from session if we're already in this route
|
|
1001
|
+
const isInSameRoute = session.currentRoute?.id === selectedRoute.id;
|
|
1002
|
+
const currentStep = isInSameRoute && session.currentStep
|
|
1003
|
+
? selectedRoute.getStep(session.currentStep.id)
|
|
1004
|
+
: undefined;
|
|
1005
|
+
logger.debug(`[ResponseModal] Step determination: route match=${isInSameRoute}, currentRoute=${session.currentRoute?.id}, selectedRoute=${selectedRoute.id}, currentStep=${currentStep?.id || 'none'}`);
|
|
1006
|
+
// Get candidate steps based on current position in the route
|
|
469
1007
|
const routingEngine = this.agent.getRoutingEngine();
|
|
470
|
-
const candidates = routingEngine.
|
|
1008
|
+
const candidates = await routingEngine.getCandidateStepsWithConditions(selectedRoute, currentStep, // Pass current step instead of undefined to maintain progression
|
|
1009
|
+
createTemplateContext({ data: session.data, session, context }));
|
|
1010
|
+
logger.debug(`[ResponseModal] Found ${candidates.length} candidate steps${currentStep ? ' from current step ' + currentStep.id : ' (new route entry)'}`);
|
|
471
1011
|
if (candidates.length > 0) {
|
|
472
1012
|
nextStep = candidates[0].step;
|
|
473
|
-
logger.debug(`[ResponseModal] Using first valid step: ${nextStep.id} for new route`);
|
|
1013
|
+
logger.debug(`[ResponseModal] Using first valid step: ${nextStep.id}${currentStep ? ' (progressing from ' + currentStep.id + ')' : ' for new route'}`);
|
|
474
1014
|
}
|
|
475
1015
|
else {
|
|
476
1016
|
// Fallback to initial step even if it should be skipped
|
|
@@ -513,6 +1053,14 @@ export class ResponseModal {
|
|
|
513
1053
|
});
|
|
514
1054
|
let message = result.structured?.message || result.message;
|
|
515
1055
|
let toolCalls = result.structured?.toolCalls;
|
|
1056
|
+
// Debug: Log initial AI response
|
|
1057
|
+
logger.debug(`[ResponseModal] Initial AI response:`, {
|
|
1058
|
+
hasMessage: !!message,
|
|
1059
|
+
messageLength: message?.length || 0,
|
|
1060
|
+
hasToolCalls: !!toolCalls,
|
|
1061
|
+
toolCallsCount: toolCalls?.length || 0,
|
|
1062
|
+
toolNames: toolCalls?.map(tc => tc.toolName) || [],
|
|
1063
|
+
});
|
|
516
1064
|
// Execute tools with unified loop handling
|
|
517
1065
|
const toolResult = await this.executeUnifiedToolLoop({
|
|
518
1066
|
toolCalls,
|
|
@@ -547,11 +1095,17 @@ export class ResponseModal {
|
|
|
547
1095
|
nextStep = selectedStep;
|
|
548
1096
|
}
|
|
549
1097
|
else {
|
|
1098
|
+
// Determine current step from session if we're already in this route
|
|
1099
|
+
const currentStep = session.currentRoute?.id === selectedRoute.id && session.currentStep
|
|
1100
|
+
? selectedRoute.getStep(session.currentStep.id)
|
|
1101
|
+
: undefined;
|
|
1102
|
+
// Get candidate steps based on current position in the route
|
|
550
1103
|
const routingEngine = this.agent.getRoutingEngine();
|
|
551
|
-
const candidates = routingEngine.
|
|
1104
|
+
const candidates = await routingEngine.getCandidateStepsWithConditions(selectedRoute, currentStep, // Pass current step instead of undefined to maintain progression
|
|
1105
|
+
createTemplateContext({ data: session.data, session, context }));
|
|
552
1106
|
if (candidates.length > 0) {
|
|
553
1107
|
nextStep = candidates[0].step;
|
|
554
|
-
logger.debug(`[ResponseModal] Using first valid step: ${nextStep.id} for new route`);
|
|
1108
|
+
logger.debug(`[ResponseModal] Using first valid step: ${nextStep.id}${currentStep ? ' (progressing from ' + currentStep.id + ')' : ' for new route'}`);
|
|
555
1109
|
}
|
|
556
1110
|
else {
|
|
557
1111
|
nextStep = selectedRoute.initialStep;
|
|
@@ -624,6 +1178,10 @@ export class ResponseModal {
|
|
|
624
1178
|
if (chunk.done) {
|
|
625
1179
|
await this.finalizeSession(session, context);
|
|
626
1180
|
}
|
|
1181
|
+
// Response structure completeness (Requirement 8.1, 8.2, 8.3)
|
|
1182
|
+
// - executedSteps: single step executed in this response
|
|
1183
|
+
// - stoppedReason: 'needs_input' for single-step execution (waiting for user input)
|
|
1184
|
+
// - session.currentStep: reflects the executed step
|
|
627
1185
|
yield {
|
|
628
1186
|
delta: chunk.delta,
|
|
629
1187
|
accumulated: chunk.accumulated,
|
|
@@ -631,6 +1189,8 @@ export class ResponseModal {
|
|
|
631
1189
|
session,
|
|
632
1190
|
toolCalls,
|
|
633
1191
|
isRouteComplete: false,
|
|
1192
|
+
executedSteps: chunk.done ? [{ id: nextStep.id, routeId: selectedRoute.id }] : undefined,
|
|
1193
|
+
stoppedReason: chunk.done ? 'needs_input' : undefined,
|
|
634
1194
|
metadata: chunk.metadata,
|
|
635
1195
|
structured: chunk.structured,
|
|
636
1196
|
};
|
|
@@ -649,7 +1209,7 @@ export class ResponseModal {
|
|
|
649
1209
|
const historyEvents = historyToEvents(history);
|
|
650
1210
|
// Execute initial dynamic tool calls
|
|
651
1211
|
if (toolCalls && toolCalls.length > 0) {
|
|
652
|
-
logger.debug(`[ResponseModal] Executing ${toolCalls.length} dynamic tool calls
|
|
1212
|
+
logger.debug(`[ResponseModal] Executing ${toolCalls.length} dynamic tool calls:`, toolCalls.map(tc => tc.toolName));
|
|
653
1213
|
for (const toolCall of toolCalls) {
|
|
654
1214
|
const tool = this.findAvailableTool(toolCall.toolName, selectedRoute);
|
|
655
1215
|
if (!tool) {
|
|
@@ -657,16 +1217,24 @@ export class ResponseModal {
|
|
|
657
1217
|
continue;
|
|
658
1218
|
}
|
|
659
1219
|
try {
|
|
660
|
-
|
|
661
|
-
const
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
1220
|
+
// Use ToolManager for unified tool execution
|
|
1221
|
+
const toolManager = this.getToolManager();
|
|
1222
|
+
let toolResult;
|
|
1223
|
+
if (toolManager) {
|
|
1224
|
+
toolResult = await toolManager.executeTool({
|
|
1225
|
+
tool: tool,
|
|
1226
|
+
context,
|
|
1227
|
+
updateContext: this.agent.updateContext.bind(this.agent),
|
|
1228
|
+
updateData: this.agent.updateCollectedData.bind(this.agent),
|
|
1229
|
+
history: historyEvents, // Use Event[] for tool execution
|
|
1230
|
+
data: session.data,
|
|
1231
|
+
toolArguments: toolCall.arguments,
|
|
1232
|
+
});
|
|
1233
|
+
}
|
|
1234
|
+
else {
|
|
1235
|
+
// Fallback: execute tool directly if ToolManager not available
|
|
1236
|
+
throw new Error(`ToolManager not available for tool execution: ${toolCall.toolName}`);
|
|
1237
|
+
}
|
|
670
1238
|
// Check if tool execution was successful
|
|
671
1239
|
if (!toolResult.success) {
|
|
672
1240
|
logger.error(`[ResponseModal] Tool execution failed: ${toolCall.toolName} - ${toolResult.error}`);
|
|
@@ -695,7 +1263,7 @@ export class ResponseModal {
|
|
|
695
1263
|
// Continue execution but log the error
|
|
696
1264
|
}
|
|
697
1265
|
}
|
|
698
|
-
logger.debug(`[ResponseModal] Executed dynamic tool: ${
|
|
1266
|
+
logger.debug(`[ResponseModal] Executed dynamic tool: ${toolCall.toolName} (success: ${toolResult.success})`);
|
|
699
1267
|
}
|
|
700
1268
|
catch (error) {
|
|
701
1269
|
logger.error(`[ResponseModal] Tool execution error for ${toolCall.toolName}:`, error);
|
|
@@ -711,7 +1279,7 @@ export class ResponseModal {
|
|
|
711
1279
|
let finalMessage;
|
|
712
1280
|
while (hasToolCalls && toolLoopCount < MAX_TOOL_LOOPS) {
|
|
713
1281
|
toolLoopCount++;
|
|
714
|
-
logger.debug(`[ResponseModal] Starting tool loop ${toolLoopCount}/${MAX_TOOL_LOOPS}`);
|
|
1282
|
+
logger.debug(`[ResponseModal] Starting tool loop ${toolLoopCount}/${MAX_TOOL_LOOPS} with ${toolCalls?.length || 0} tool calls`);
|
|
715
1283
|
// Create tool result events with proper Event format structure
|
|
716
1284
|
const toolResultEvents = [];
|
|
717
1285
|
for (const toolCall of toolCalls || []) {
|
|
@@ -740,12 +1308,19 @@ export class ResponseModal {
|
|
|
740
1308
|
// Create updated history with tool results (combine Event arrays)
|
|
741
1309
|
const updatedHistoryEvents = [...historyEvents, ...toolResultEvents];
|
|
742
1310
|
// Make follow-up AI call to see if more tools are needed
|
|
1311
|
+
// After first iteration, don't provide tools to force a text response
|
|
743
1312
|
const agentOptions = this.agent.getAgentOptions();
|
|
1313
|
+
const shouldProvideTools = toolLoopCount === 1;
|
|
1314
|
+
logger.debug(`[ResponseModal] Making follow-up AI call (loop ${toolLoopCount}):`, {
|
|
1315
|
+
providingTools: shouldProvideTools,
|
|
1316
|
+
toolsCount: shouldProvideTools ? availableTools.length : 0,
|
|
1317
|
+
addingTextInstruction: toolLoopCount > 1,
|
|
1318
|
+
});
|
|
744
1319
|
const followUpResult = await agentOptions.provider.generateMessage({
|
|
745
|
-
prompt: responsePrompt,
|
|
1320
|
+
prompt: responsePrompt + (toolLoopCount > 1 ? "\n\nProvide a text response to the user based on the tool results." : ""),
|
|
746
1321
|
history: updatedHistoryEvents, // Use Event[] for AI provider
|
|
747
1322
|
context,
|
|
748
|
-
tools: availableTools,
|
|
1323
|
+
tools: shouldProvideTools ? availableTools : [], // Only provide tools on first iteration
|
|
749
1324
|
parameters: responseSchema ? {
|
|
750
1325
|
jsonSchema: responseSchema,
|
|
751
1326
|
schemaName: "tool_followup",
|
|
@@ -755,6 +1330,13 @@ export class ResponseModal {
|
|
|
755
1330
|
// Check if follow-up call has more tool calls
|
|
756
1331
|
const followUpToolCalls = followUpResult.structured?.toolCalls;
|
|
757
1332
|
hasToolCalls = followUpToolCalls && followUpToolCalls.length > 0;
|
|
1333
|
+
logger.debug(`[ResponseModal] Follow-up AI response (loop ${toolLoopCount}):`, {
|
|
1334
|
+
hasMessage: !!followUpResult.message,
|
|
1335
|
+
messageLength: followUpResult.message?.length || 0,
|
|
1336
|
+
hasToolCalls,
|
|
1337
|
+
toolCallsCount: followUpToolCalls?.length || 0,
|
|
1338
|
+
toolNames: followUpToolCalls?.map(tc => tc.toolName) || [],
|
|
1339
|
+
});
|
|
758
1340
|
if (hasToolCalls) {
|
|
759
1341
|
logger.debug(`[ResponseModal] Follow-up call produced ${followUpToolCalls.length} additional tool calls`);
|
|
760
1342
|
// Execute the follow-up tool calls
|
|
@@ -765,16 +1347,24 @@ export class ResponseModal {
|
|
|
765
1347
|
continue;
|
|
766
1348
|
}
|
|
767
1349
|
try {
|
|
768
|
-
|
|
769
|
-
const
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
1350
|
+
// Use ToolManager for unified tool execution
|
|
1351
|
+
const toolManager = this.getToolManager();
|
|
1352
|
+
let toolResult;
|
|
1353
|
+
if (toolManager) {
|
|
1354
|
+
toolResult = await toolManager.executeTool({
|
|
1355
|
+
tool: tool,
|
|
1356
|
+
context,
|
|
1357
|
+
updateContext: this.agent.updateContext.bind(this.agent),
|
|
1358
|
+
updateData: this.agent.updateCollectedData.bind(this.agent),
|
|
1359
|
+
history: updatedHistoryEvents, // Use Event[] for tool execution
|
|
1360
|
+
data: session.data,
|
|
1361
|
+
toolArguments: toolCall.arguments,
|
|
1362
|
+
});
|
|
1363
|
+
}
|
|
1364
|
+
else {
|
|
1365
|
+
// Fallback: execute tool directly if ToolManager not available
|
|
1366
|
+
throw new Error(`ToolManager not available for follow-up tool execution: ${toolCall.toolName}`);
|
|
1367
|
+
}
|
|
778
1368
|
// Check if tool execution was successful
|
|
779
1369
|
if (!toolResult.success) {
|
|
780
1370
|
logger.error(`[ResponseModal] Follow-up tool execution failed: ${toolCall.toolName} - ${toolResult.error}`);
|
|
@@ -799,7 +1389,7 @@ export class ResponseModal {
|
|
|
799
1389
|
logger.error(`[ResponseModal] Failed to update data from follow-up tool ${toolCall.toolName}:`, error);
|
|
800
1390
|
}
|
|
801
1391
|
}
|
|
802
|
-
logger.debug(`[ResponseModal] Executed follow-up tool: ${
|
|
1392
|
+
logger.debug(`[ResponseModal] Executed follow-up tool: ${toolCall.toolName} (success: ${toolResult.success})`);
|
|
803
1393
|
}
|
|
804
1394
|
catch (error) {
|
|
805
1395
|
logger.error(`[ResponseModal] Follow-up tool execution error for ${toolCall.toolName}:`, error);
|
|
@@ -820,6 +1410,12 @@ export class ResponseModal {
|
|
|
820
1410
|
if (toolLoopCount >= MAX_TOOL_LOOPS) {
|
|
821
1411
|
logger.warn(`[ResponseModal] Tool loop limit reached (${MAX_TOOL_LOOPS}), stopping`);
|
|
822
1412
|
}
|
|
1413
|
+
logger.debug(`[ResponseModal] Tool loop completed:`, {
|
|
1414
|
+
totalIterations: toolLoopCount,
|
|
1415
|
+
hasFinalMessage: !!finalMessage,
|
|
1416
|
+
finalMessageLength: finalMessage?.length || 0,
|
|
1417
|
+
finalToolCallsCount: toolCalls?.length || 0,
|
|
1418
|
+
});
|
|
823
1419
|
return {
|
|
824
1420
|
session,
|
|
825
1421
|
finalToolCalls: toolCalls,
|
|
@@ -841,14 +1437,29 @@ export class ResponseModal {
|
|
|
841
1437
|
const { result, selectedRoute, nextStep, session } = params;
|
|
842
1438
|
let updatedSession = session;
|
|
843
1439
|
// Extract collected data from final response (only for route-based interactions)
|
|
844
|
-
if (selectedRoute && result.structured
|
|
1440
|
+
if (selectedRoute && result.structured) {
|
|
845
1441
|
try {
|
|
846
1442
|
const collectedData = {};
|
|
847
1443
|
// AgentStructuredResponse extends Record<string, unknown>, so we can safely access properties
|
|
848
1444
|
const structuredData = result.structured;
|
|
849
|
-
|
|
1445
|
+
// Collect ALL route fields (required + optional) from structured response
|
|
1446
|
+
const allRouteFields = new Set();
|
|
1447
|
+
// Add route required fields
|
|
1448
|
+
if (selectedRoute.requiredFields) {
|
|
1449
|
+
selectedRoute.requiredFields.forEach(field => allRouteFields.add(String(field)));
|
|
1450
|
+
}
|
|
1451
|
+
// Add route optional fields
|
|
1452
|
+
if (selectedRoute.optionalFields) {
|
|
1453
|
+
selectedRoute.optionalFields.forEach(field => allRouteFields.add(String(field)));
|
|
1454
|
+
}
|
|
1455
|
+
// Also include current step's collect fields (in case they're not in route fields)
|
|
1456
|
+
if (nextStep?.collect) {
|
|
1457
|
+
nextStep.collect.forEach(field => allRouteFields.add(String(field)));
|
|
1458
|
+
}
|
|
1459
|
+
// Extract all available fields from structured response
|
|
1460
|
+
for (const field of allRouteFields) {
|
|
850
1461
|
const fieldKey = String(field);
|
|
851
|
-
if (fieldKey in structuredData) {
|
|
1462
|
+
if (fieldKey in structuredData && structuredData[fieldKey] !== undefined && structuredData[fieldKey] !== null) {
|
|
852
1463
|
collectedData[fieldKey] = structuredData[fieldKey];
|
|
853
1464
|
}
|
|
854
1465
|
}
|
|
@@ -911,34 +1522,60 @@ export class ResponseModal {
|
|
|
911
1522
|
requires: endStepSpec.requires,
|
|
912
1523
|
prompt: endStepSpec.prompt || "Summarize what was accomplished and confirm completion based on the conversation history and collected data",
|
|
913
1524
|
});
|
|
914
|
-
// Build response schema for completion
|
|
915
|
-
const
|
|
916
|
-
|
|
917
|
-
|
|
1525
|
+
// Build response schema for completion (message only, no data collection)
|
|
1526
|
+
const completionSchema = {
|
|
1527
|
+
type: "object",
|
|
1528
|
+
properties: {
|
|
1529
|
+
message: {
|
|
1530
|
+
type: "string",
|
|
1531
|
+
description: "Completion message confirming what was accomplished",
|
|
1532
|
+
},
|
|
1533
|
+
},
|
|
1534
|
+
required: ["message"],
|
|
1535
|
+
additionalProperties: false,
|
|
1536
|
+
};
|
|
1537
|
+
const templateContext = createTemplateContext({ context, session, history: historyEvents });
|
|
1538
|
+
// Build completion response prompt using ResponseEngine
|
|
1539
|
+
// Filter out conditional guidelines - only include always-active ones
|
|
1540
|
+
const alwaysActiveGuidelines = [
|
|
1541
|
+
...this.agent.getGuidelines().filter(g => !g.condition),
|
|
1542
|
+
...selectedRoute.getGuidelines().filter(g => !g.condition),
|
|
1543
|
+
];
|
|
1544
|
+
let completitionPrompt = "Summarize what was accomplished and confirm completion";
|
|
1545
|
+
if (endStepSpec.prompt) {
|
|
1546
|
+
completitionPrompt = await render(endStepSpec.prompt, templateContext);
|
|
1547
|
+
}
|
|
918
1548
|
const completionPrompt = await this.responseEngine.buildResponsePrompt({
|
|
919
1549
|
route: selectedRoute,
|
|
920
1550
|
currentStep: completionStep,
|
|
921
1551
|
rules: selectedRoute.getRules(),
|
|
922
1552
|
prohibitions: selectedRoute.getProhibitions(),
|
|
923
|
-
directives:
|
|
924
|
-
|
|
925
|
-
|
|
1553
|
+
directives: [
|
|
1554
|
+
`Task completed: ${selectedRoute.title}`,
|
|
1555
|
+
`Collected data: ${JSON.stringify(session.data, null, 2)}`,
|
|
1556
|
+
"Do NOT ask for more information - the task is complete",
|
|
1557
|
+
completitionPrompt,
|
|
1558
|
+
],
|
|
1559
|
+
history: historyEvents,
|
|
1560
|
+
lastMessage: lastMessageText,
|
|
926
1561
|
agentOptions: this.agent.getAgentOptions(),
|
|
927
|
-
combinedGuidelines:
|
|
1562
|
+
combinedGuidelines: alwaysActiveGuidelines, // Only non-conditional guidelines
|
|
928
1563
|
combinedTerms: this.mergeTerms(this.agent.getTerms(), selectedRoute.getTerms()),
|
|
929
1564
|
context,
|
|
930
1565
|
session,
|
|
931
|
-
agentSchema:
|
|
1566
|
+
agentSchema: undefined, // No data collection schema for completion
|
|
932
1567
|
});
|
|
933
1568
|
// Generate completion message using AI provider
|
|
934
1569
|
const agentOptions = this.agent.getAgentOptions();
|
|
1570
|
+
logger.debug(`[ResponseModal] Calling AI provider for completion message...`);
|
|
935
1571
|
const completionResult = await agentOptions.provider.generateMessage({
|
|
936
1572
|
prompt: completionPrompt,
|
|
937
|
-
history: historyEvents,
|
|
1573
|
+
history: historyEvents,
|
|
938
1574
|
context,
|
|
939
1575
|
signal,
|
|
940
|
-
parameters: { jsonSchema:
|
|
1576
|
+
parameters: { jsonSchema: completionSchema, schemaName: "completion_message" },
|
|
941
1577
|
});
|
|
1578
|
+
logger.debug(`[ResponseModal] AI provider returned completion result`);
|
|
942
1579
|
const message = completionResult.structured?.message || completionResult.message;
|
|
943
1580
|
logger.debug(`[ResponseModal] Generated completion message for route: ${selectedRoute.title}`);
|
|
944
1581
|
// Check for onComplete transition
|
|
@@ -981,7 +1618,7 @@ export class ResponseModal {
|
|
|
981
1618
|
});
|
|
982
1619
|
// Build response schema for completion
|
|
983
1620
|
const responseSchema = this.responseEngine.responseSchemaForRoute(selectedRoute, completionStep, this.agent.getSchema());
|
|
984
|
-
const templateContext = { context, session, history: historyEvents }; // Use Event[] for template context
|
|
1621
|
+
const templateContext = createTemplateContext({ context, session, history: historyEvents }); // Use Event[] for template context
|
|
985
1622
|
// Build completion response prompt
|
|
986
1623
|
const completionPrompt = await this.responseEngine.buildResponsePrompt({
|
|
987
1624
|
route: selectedRoute,
|
|
@@ -1039,6 +1676,10 @@ export class ResponseModal {
|
|
|
1039
1676
|
if (chunk.done) {
|
|
1040
1677
|
await this.finalizeSession(session, context);
|
|
1041
1678
|
}
|
|
1679
|
+
// Response structure completeness (Requirement 8.1, 8.2, 8.3)
|
|
1680
|
+
// - executedSteps: empty for route completion (no new steps executed)
|
|
1681
|
+
// - stoppedReason: 'route_complete' for completed routes
|
|
1682
|
+
// - session.currentStep: set to END_ROUTE
|
|
1042
1683
|
yield {
|
|
1043
1684
|
delta: chunk.delta,
|
|
1044
1685
|
accumulated: chunk.accumulated,
|
|
@@ -1046,6 +1687,8 @@ export class ResponseModal {
|
|
|
1046
1687
|
session,
|
|
1047
1688
|
toolCalls: undefined,
|
|
1048
1689
|
isRouteComplete: true,
|
|
1690
|
+
executedSteps: chunk.done ? [] : undefined,
|
|
1691
|
+
stoppedReason: chunk.done ? 'route_complete' : undefined,
|
|
1049
1692
|
metadata: chunk.metadata,
|
|
1050
1693
|
structured: chunk.structured,
|
|
1051
1694
|
};
|
|
@@ -1120,6 +1763,10 @@ export class ResponseModal {
|
|
|
1120
1763
|
if (chunk.done) {
|
|
1121
1764
|
await this.finalizeSession(session, context);
|
|
1122
1765
|
}
|
|
1766
|
+
// Response structure completeness (Requirement 8.1, 8.2, 8.3)
|
|
1767
|
+
// - executedSteps: empty for fallback (no route/step execution)
|
|
1768
|
+
// - stoppedReason: undefined for fallback (no route context)
|
|
1769
|
+
// - session.currentStep: unchanged (no step progression)
|
|
1123
1770
|
yield {
|
|
1124
1771
|
delta: chunk.delta,
|
|
1125
1772
|
accumulated: chunk.accumulated,
|
|
@@ -1127,6 +1774,8 @@ export class ResponseModal {
|
|
|
1127
1774
|
session,
|
|
1128
1775
|
toolCalls: undefined,
|
|
1129
1776
|
isRouteComplete: false,
|
|
1777
|
+
executedSteps: chunk.done ? [] : undefined,
|
|
1778
|
+
stoppedReason: undefined,
|
|
1130
1779
|
metadata: chunk.metadata,
|
|
1131
1780
|
structured: chunk.structured,
|
|
1132
1781
|
};
|
|
@@ -1158,11 +1807,18 @@ export class ResponseModal {
|
|
|
1158
1807
|
// UTILITY METHODS - Helper methods for tool management and other utilities
|
|
1159
1808
|
// ============================================================================
|
|
1160
1809
|
/**
|
|
1161
|
-
* Find an available tool by name for the given route
|
|
1162
|
-
*
|
|
1810
|
+
* Find an available tool by name for the given route using ToolManager
|
|
1811
|
+
* Delegates to ToolManager for unified tool resolution
|
|
1163
1812
|
* @private
|
|
1164
1813
|
*/
|
|
1165
1814
|
findAvailableTool(toolName, route) {
|
|
1815
|
+
// Use ToolManager for unified tool resolution
|
|
1816
|
+
const toolManager = this.getToolManager();
|
|
1817
|
+
if (toolManager) {
|
|
1818
|
+
return toolManager.find(toolName, undefined, undefined, route);
|
|
1819
|
+
}
|
|
1820
|
+
// Fallback to legacy resolution if ToolManager not available
|
|
1821
|
+
logger.warn(`[ResponseModal] ToolManager not available, using legacy tool resolution for: ${toolName}`);
|
|
1166
1822
|
// Check route-level tools first (if route provided)
|
|
1167
1823
|
if (route) {
|
|
1168
1824
|
const routeTool = route
|
|
@@ -1176,10 +1832,24 @@ export class ResponseModal {
|
|
|
1176
1832
|
return agentTools.find((tool) => tool.id === toolName || tool.name === toolName);
|
|
1177
1833
|
}
|
|
1178
1834
|
/**
|
|
1179
|
-
* Collect all available tools for the given route and step context
|
|
1835
|
+
* Collect all available tools for the given route and step context using ToolManager
|
|
1836
|
+
* Delegates to ToolManager for unified tool resolution and deduplication
|
|
1180
1837
|
* @private
|
|
1181
1838
|
*/
|
|
1182
1839
|
collectAvailableTools(route, step) {
|
|
1840
|
+
// Use ToolManager for unified tool collection if available
|
|
1841
|
+
const toolManager = this.getToolManager();
|
|
1842
|
+
if (toolManager) {
|
|
1843
|
+
const availableTools = toolManager.getAvailable(undefined, step, route);
|
|
1844
|
+
return availableTools.map((tool) => ({
|
|
1845
|
+
id: tool.id,
|
|
1846
|
+
name: tool.name || tool.id,
|
|
1847
|
+
description: tool.description,
|
|
1848
|
+
parameters: tool.parameters,
|
|
1849
|
+
}));
|
|
1850
|
+
}
|
|
1851
|
+
// Fallback to legacy collection logic if ToolManager not available
|
|
1852
|
+
logger.warn(`[ResponseModal] ToolManager not available, using legacy tool collection`);
|
|
1183
1853
|
const availableTools = new Map();
|
|
1184
1854
|
// Add agent-level tools
|
|
1185
1855
|
this.agent.getTools().forEach((tool) => {
|
|
@@ -1250,45 +1920,61 @@ export class ResponseModal {
|
|
|
1250
1920
|
// It's a tool reference - find and execute the tool
|
|
1251
1921
|
let tool;
|
|
1252
1922
|
if (typeof prepareOrFinalize === "string") {
|
|
1253
|
-
// Tool ID -
|
|
1254
|
-
const
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1923
|
+
// Tool ID - use ToolManager for unified resolution
|
|
1924
|
+
const toolManager = this.getToolManager();
|
|
1925
|
+
if (toolManager) {
|
|
1926
|
+
tool = toolManager.find(prepareOrFinalize, undefined, step, route);
|
|
1927
|
+
}
|
|
1928
|
+
else {
|
|
1929
|
+
// Fallback to legacy resolution if ToolManager not available
|
|
1930
|
+
logger.warn(`[ResponseModal] ToolManager not available, using legacy tool resolution for prepare/finalize: ${prepareOrFinalize}`);
|
|
1931
|
+
const availableTools = new Map();
|
|
1932
|
+
// Add agent-level tools
|
|
1933
|
+
this.agent.getTools().forEach((t) => {
|
|
1262
1934
|
availableTools.set(t.id, t);
|
|
1263
1935
|
});
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1936
|
+
// Add route-level tools
|
|
1937
|
+
if (route) {
|
|
1938
|
+
route.getTools().forEach((t) => {
|
|
1939
|
+
availableTools.set(t.id, t);
|
|
1940
|
+
});
|
|
1941
|
+
}
|
|
1942
|
+
// Add step-level tools
|
|
1943
|
+
if (step?.tools) {
|
|
1944
|
+
for (const toolRef of step.tools) {
|
|
1945
|
+
if (typeof toolRef === "string") {
|
|
1946
|
+
// Keep as is
|
|
1947
|
+
}
|
|
1948
|
+
else if (typeof toolRef === 'object' && 'id' in toolRef && toolRef.id) {
|
|
1949
|
+
availableTools.set(toolRef.id, toolRef);
|
|
1950
|
+
}
|
|
1273
1951
|
}
|
|
1274
1952
|
}
|
|
1953
|
+
tool = availableTools.get(prepareOrFinalize);
|
|
1275
1954
|
}
|
|
1276
|
-
tool = availableTools.get(prepareOrFinalize);
|
|
1277
1955
|
}
|
|
1278
1956
|
else {
|
|
1279
1957
|
// Tool object - use directly
|
|
1280
1958
|
tool = prepareOrFinalize;
|
|
1281
1959
|
}
|
|
1282
1960
|
if (tool) {
|
|
1283
|
-
|
|
1284
|
-
const
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1961
|
+
// Use ToolManager for unified tool execution
|
|
1962
|
+
const toolManager = this.getToolManager();
|
|
1963
|
+
let result;
|
|
1964
|
+
if (toolManager) {
|
|
1965
|
+
result = await toolManager.executeTool({
|
|
1966
|
+
tool,
|
|
1967
|
+
context,
|
|
1968
|
+
updateContext: this.agent.updateContext.bind(this.agent),
|
|
1969
|
+
updateData: this.agent.updateCollectedData.bind(this.agent),
|
|
1970
|
+
history: [], // Empty history for prepare/finalize
|
|
1971
|
+
data,
|
|
1972
|
+
});
|
|
1973
|
+
}
|
|
1974
|
+
else {
|
|
1975
|
+
// Fallback: execute tool directly if ToolManager not available
|
|
1976
|
+
throw new Error(`ToolManager not available for prepare/finalize tool execution: ${typeof prepareOrFinalize === "string" ? prepareOrFinalize : "inline tool"}`);
|
|
1977
|
+
}
|
|
1292
1978
|
if (!result.success) {
|
|
1293
1979
|
logger.error(`[ResponseModal] Tool execution failed in prepare/finalize: ${result.error}`);
|
|
1294
1980
|
throw new Error(`Tool execution failed: ${result.error}`);
|