@falai/agent 0.9.2 → 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 +262 -38
- 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/cjs/{src/core → core}/Agent.d.ts +6 -1
- package/dist/cjs/core/Agent.d.ts.map +1 -0
- package/dist/cjs/{src/core → core}/Agent.js +42 -2
- 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 +45 -0
- package/dist/cjs/core/ResponseModal.d.ts.map +1 -0
- package/dist/cjs/{src/core → core}/ResponseModal.js +686 -66
- package/dist/cjs/core/ResponseModal.js.map +1 -0
- package/dist/{src → cjs}/core/ResponsePipeline.d.ts +2 -2
- package/dist/cjs/core/ResponsePipeline.d.ts.map +1 -0
- package/dist/cjs/{src/core → core}/ResponsePipeline.js +13 -6
- package/dist/cjs/core/ResponsePipeline.js.map +1 -0
- package/dist/{src → cjs}/core/Route.d.ts +34 -5
- package/dist/cjs/core/Route.d.ts.map +1 -0
- package/dist/cjs/{src/core → core}/Route.js +196 -19
- package/dist/cjs/core/Route.js.map +1 -0
- package/dist/cjs/{src/core → core}/RoutingEngine.d.ts +30 -5
- package/dist/cjs/core/RoutingEngine.d.ts.map +1 -0
- package/dist/cjs/{src/core → core}/RoutingEngine.js +330 -80
- package/dist/cjs/core/RoutingEngine.js.map +1 -0
- package/dist/cjs/core/SessionManager.js.map +1 -0
- package/dist/{src → cjs}/core/Step.d.ts +31 -10
- package/dist/cjs/core/Step.d.ts.map +1 -0
- package/dist/cjs/{src/core → core}/Step.js +105 -10
- package/dist/cjs/core/Step.js.map +1 -0
- package/dist/cjs/core/ToolManager.js.map +1 -0
- package/dist/{src → cjs}/index.d.ts +4 -1
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/{src/index.js → index.js} +12 -1
- 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 +11 -3
- 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 +2 -1
- package/dist/{src → cjs}/types/index.d.ts.map +1 -1
- package/dist/cjs/{src/types → types}/index.js +6 -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 +111 -12
- 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.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/{src/core → core}/Agent.d.ts +6 -1
- package/dist/core/Agent.d.ts.map +1 -0
- package/dist/{src/core → core}/Agent.js +43 -3
- 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 +45 -0
- package/dist/core/ResponseModal.d.ts.map +1 -0
- package/dist/{src/core → core}/ResponseModal.js +686 -66
- package/dist/core/ResponseModal.js.map +1 -0
- package/dist/{cjs/src/core → core}/ResponsePipeline.d.ts +2 -2
- package/dist/core/ResponsePipeline.d.ts.map +1 -0
- package/dist/{src/core → core}/ResponsePipeline.js +13 -6
- package/dist/core/ResponsePipeline.js.map +1 -0
- package/dist/{cjs/src/core → core}/Route.d.ts +34 -5
- package/dist/core/Route.d.ts.map +1 -0
- package/dist/{src/core → core}/Route.js +195 -18
- package/dist/core/Route.js.map +1 -0
- package/dist/{src/core → core}/RoutingEngine.d.ts +30 -5
- package/dist/core/RoutingEngine.d.ts.map +1 -0
- package/dist/{src/core → core}/RoutingEngine.js +310 -60
- package/dist/core/RoutingEngine.js.map +1 -0
- package/dist/core/SessionManager.d.ts.map +1 -0
- package/dist/core/SessionManager.js.map +1 -0
- package/dist/{cjs/src/core → core}/Step.d.ts +31 -10
- package/dist/core/Step.d.ts.map +1 -0
- package/dist/{src/core → core}/Step.js +104 -9
- package/dist/core/Step.js.map +1 -0
- package/dist/core/ToolManager.d.ts.map +1 -0
- package/dist/core/ToolManager.js.map +1 -0
- package/dist/{cjs/src/index.d.ts → index.d.ts} +4 -1
- package/dist/index.d.ts.map +1 -0
- package/dist/{src/index.js → index.js} +3 -0
- 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 +11 -3
- 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 +2 -1
- package/dist/types/index.d.ts.map +1 -0
- package/dist/{src/types → types}/index.js +1 -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 +111 -12
- 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.map +1 -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/api/README.md +221 -12
- package/docs/api/overview.md +202 -3
- 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 +1 -1
- package/docs/core/ai-integration/prompt-composition.md +135 -0
- package/docs/core/ai-integration/response-processing.md +146 -0
- package/docs/core/conversation-flows/data-collection.md +143 -0
- package/docs/core/conversation-flows/routes.md +2 -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 +193 -0
- package/docs/core/routing/intelligent-routing.md +118 -0
- package/docs/guides/getting-started/README.md +284 -3
- 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 +101 -24
- package/examples/advanced-patterns/persistent-onboarding.ts +40 -5
- 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 +4 -4
- package/examples/ai-providers/openai-integration.ts +1 -1
- 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 +54 -33
- package/examples/core-concepts/schema-driven-extraction.ts +33 -9
- package/examples/core-concepts/session-management.ts +51 -16
- package/examples/integrations/database-integration.ts +6 -6
- package/examples/integrations/healthcare-integration.ts +10 -10
- package/examples/integrations/search-integration.ts +8 -8
- package/examples/integrations/server-session-management.ts +8 -8
- package/examples/persistence/database-persistence.ts +15 -15
- package/examples/persistence/memory-sessions.ts +3 -3
- package/examples/persistence/redis-persistence.ts +7 -9
- package/examples/tools/data-enrichment-tools.ts +4 -4
- package/package.json +6 -4
- package/src/adapters/PrismaAdapter.ts +3 -2
- package/src/adapters/RedisAdapter.ts +3 -3
- package/src/core/Agent.ts +54 -2
- 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 +888 -66
- package/src/core/ResponsePipeline.ts +17 -9
- package/src/core/Route.ts +223 -22
- package/src/core/RoutingEngine.ts +426 -83
- package/src/core/Step.ts +144 -16
- package/src/index.ts +19 -0
- 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 +11 -3
- package/src/types/index.ts +12 -1
- package/src/types/route.ts +131 -12
- package/src/types/template.ts +70 -2
- 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.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.map +0 -1
- package/dist/cjs/src/core/Step.js.map +0 -1
- package/dist/cjs/src/core/ToolManager.d.ts.map +0 -1
- package/dist/cjs/src/core/ToolManager.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.map +0 -1
- 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.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.js.map +0 -1
- package/dist/src/core/Step.d.ts.map +0 -1
- package/dist/src/core/Step.js.map +0 -1
- package/dist/src/core/ToolManager.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.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/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/core → core}/SessionManager.d.ts +0 -0
- /package/dist/{src → cjs}/core/SessionManager.d.ts.map +0 -0
- /package/dist/cjs/{src/core → core}/SessionManager.js +0 -0
- /package/dist/cjs/{src/core → core}/ToolManager.d.ts +0 -0
- /package/dist/{src → cjs}/core/ToolManager.d.ts.map +0 -0
- /package/dist/cjs/{src/core → core}/ToolManager.js +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/types → types}/tool.d.ts +0 -0
- /package/dist/{src → cjs}/types/tool.d.ts.map +0 -0
- /package/dist/cjs/{src/types → types}/tool.js +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/core → core}/SessionManager.d.ts +0 -0
- /package/dist/{src/core → core}/SessionManager.js +0 -0
- /package/dist/{src/core → core}/ToolManager.d.ts +0 -0
- /package/dist/{src/core → core}/ToolManager.js +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/types → types}/tool.d.ts +0 -0
- /package/dist/{src/types → types}/tool.js +0 -0
- /package/dist/{src/utils → utils}/clone.d.ts +0 -0
- /package/dist/{src/utils → utils}/clone.js +0 -0
- /package/dist/{src/utils → utils}/event.d.ts +0 -0
- /package/dist/{src/utils → utils}/event.js +0 -0
- /package/dist/{src/utils → utils}/history.d.ts +0 -0
- /package/dist/{src/utils → utils}/history.js +0 -0
- /package/dist/{src/utils → utils}/id.d.ts +0 -0
- /package/dist/{src/utils → utils}/id.js +0 -0
- /package/dist/{src/utils → utils}/logger.d.ts +0 -0
- /package/dist/{src/utils → utils}/logger.js +0 -0
- /package/dist/{src/utils → utils}/session.d.ts +0 -0
- /package/dist/{src/utils → utils}/session.js +0 -0
|
@@ -15,6 +15,7 @@ import type {
|
|
|
15
15
|
ToolEventData,
|
|
16
16
|
AgentStructuredResponse,
|
|
17
17
|
Term,
|
|
18
|
+
StoppedReason,
|
|
18
19
|
} from "../types";
|
|
19
20
|
import { EventKind, MessageRole } from "../types";
|
|
20
21
|
import type { Agent } from "./Agent";
|
|
@@ -22,9 +23,13 @@ import type { Route } from "./Route";
|
|
|
22
23
|
import { Step } from "./Step";
|
|
23
24
|
import { ResponseEngine } from "./ResponseEngine";
|
|
24
25
|
import { ResponsePipeline } from "./ResponsePipeline";
|
|
26
|
+
import { BatchExecutor, type HookFunction } from "./BatchExecutor";
|
|
27
|
+
import { BatchPromptBuilder } from "./BatchPromptBuilder";
|
|
25
28
|
import { cloneDeep, mergeCollected, enterStep, getLastMessageFromHistory, render, logger, historyToEvents } from "../utils";
|
|
29
|
+
import { createTemplateContext } from "../utils/template";
|
|
26
30
|
import type { ToolManager } from "./ToolManager";
|
|
27
31
|
import { END_ROUTE_ID } from "../constants";
|
|
32
|
+
import type { StepOptions } from "../types/route";
|
|
28
33
|
|
|
29
34
|
/**
|
|
30
35
|
* Configuration options for ResponseModal
|
|
@@ -129,6 +134,12 @@ interface ResponseContext<TContext = unknown, TData = unknown> {
|
|
|
129
134
|
selectedStep?: Step<TContext, TData>;
|
|
130
135
|
responseDirectives?: string[];
|
|
131
136
|
isRouteComplete: boolean;
|
|
137
|
+
/** Batch of steps to execute (for multi-step execution) */
|
|
138
|
+
batchSteps?: StepOptions<TContext, TData>[];
|
|
139
|
+
/** Reason why batch determination stopped */
|
|
140
|
+
batchStoppedReason?: StoppedReason;
|
|
141
|
+
/** Step that caused batch to stop (if applicable) */
|
|
142
|
+
batchStoppedAtStep?: StepOptions<TContext, TData>;
|
|
132
143
|
}
|
|
133
144
|
|
|
134
145
|
/**
|
|
@@ -138,6 +149,8 @@ interface ResponseContext<TContext = unknown, TData = unknown> {
|
|
|
138
149
|
export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
139
150
|
private readonly responseEngine: ResponseEngine<TContext, TData>;
|
|
140
151
|
private readonly responsePipeline: ResponsePipeline<TContext, TData>;
|
|
152
|
+
private readonly batchExecutor: BatchExecutor<TContext, TData>;
|
|
153
|
+
private readonly batchPromptBuilder: BatchPromptBuilder<TContext, TData>;
|
|
141
154
|
|
|
142
155
|
constructor(
|
|
143
156
|
private readonly agent: Agent<TContext, TData>,
|
|
@@ -157,6 +170,12 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
157
170
|
this.agent.updateCollectedData.bind(this.agent),
|
|
158
171
|
this.getToolManager()
|
|
159
172
|
);
|
|
173
|
+
|
|
174
|
+
// Initialize batch executor for multi-step execution
|
|
175
|
+
this.batchExecutor = new BatchExecutor<TContext, TData>();
|
|
176
|
+
|
|
177
|
+
// Initialize batch prompt builder for combined prompts
|
|
178
|
+
this.batchPromptBuilder = new BatchPromptBuilder<TContext, TData>();
|
|
160
179
|
}
|
|
161
180
|
|
|
162
181
|
/**
|
|
@@ -418,12 +437,16 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
418
437
|
}
|
|
419
438
|
|
|
420
439
|
// PHASE 2: ROUTING + STEP SELECTION - Determine which route and step to use
|
|
440
|
+
// Also performs pre-extraction and batch determination
|
|
421
441
|
let routingResult: {
|
|
422
442
|
selectedRoute?: Route<TContext, TData>;
|
|
423
443
|
selectedStep?: Step<TContext, TData>;
|
|
424
444
|
responseDirectives?: string[];
|
|
425
445
|
session: SessionState<TData>;
|
|
426
446
|
isRouteComplete: boolean;
|
|
447
|
+
batchSteps?: StepOptions<TContext, TData>[];
|
|
448
|
+
batchStoppedReason?: StoppedReason;
|
|
449
|
+
batchStoppedAtStep?: StepOptions<TContext, TData>;
|
|
427
450
|
};
|
|
428
451
|
try {
|
|
429
452
|
routingResult = await this.handleUnifiedRoutingAndStepSelection({
|
|
@@ -444,6 +467,9 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
444
467
|
selectedStep: routingResult.selectedStep,
|
|
445
468
|
responseDirectives: routingResult.responseDirectives,
|
|
446
469
|
isRouteComplete: routingResult.isRouteComplete,
|
|
470
|
+
batchSteps: routingResult.batchSteps,
|
|
471
|
+
batchStoppedReason: routingResult.batchStoppedReason,
|
|
472
|
+
batchStoppedAtStep: routingResult.batchStoppedAtStep,
|
|
447
473
|
};
|
|
448
474
|
} catch (error) {
|
|
449
475
|
// Re-throw ResponseGenerationError as-is, wrap others
|
|
@@ -469,6 +495,12 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
469
495
|
responseDirectives?: string[];
|
|
470
496
|
session: SessionState<TData>;
|
|
471
497
|
isRouteComplete: boolean;
|
|
498
|
+
/** Batch of steps to execute (for multi-step execution) */
|
|
499
|
+
batchSteps?: StepOptions<TContext, TData>[];
|
|
500
|
+
/** Reason why batch determination stopped */
|
|
501
|
+
batchStoppedReason?: StoppedReason;
|
|
502
|
+
/** Step that caused batch to stop (if applicable) */
|
|
503
|
+
batchStoppedAtStep?: StepOptions<TContext, TData>;
|
|
472
504
|
}> {
|
|
473
505
|
try {
|
|
474
506
|
// Use the ResponsePipeline for optimized routing and step selection
|
|
@@ -480,12 +512,84 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
480
512
|
context: params.context,
|
|
481
513
|
signal: params.signal,
|
|
482
514
|
});
|
|
515
|
+
|
|
516
|
+
let updatedSession = routingResult.session;
|
|
517
|
+
let isRouteComplete = routingResult.isRouteComplete;
|
|
518
|
+
|
|
519
|
+
// PRE-EXTRACTION: If entering a route that collects data, extract data from user message first
|
|
520
|
+
// This allows us to skip steps whose data is already provided
|
|
521
|
+
// Requirement 3.1: Perform Pre_Extraction before determining the Batch
|
|
522
|
+
if (routingResult.selectedRoute && !isRouteComplete) {
|
|
523
|
+
// Always pre-extract when route collects data (not just on new route entry)
|
|
524
|
+
// This ensures batch determination has the most up-to-date data
|
|
525
|
+
if (this.shouldPreExtractData(routingResult.selectedRoute)) {
|
|
526
|
+
logger.debug(
|
|
527
|
+
`[ResponseModal] Pre-extracting data for route: ${routingResult.selectedRoute.title}`
|
|
528
|
+
);
|
|
529
|
+
|
|
530
|
+
const extractedData = await this.preExtractRouteData({
|
|
531
|
+
route: routingResult.selectedRoute,
|
|
532
|
+
history: params.history,
|
|
533
|
+
context: params.context,
|
|
534
|
+
session: updatedSession,
|
|
535
|
+
signal: params.signal,
|
|
536
|
+
});
|
|
537
|
+
|
|
538
|
+
if (extractedData && Object.keys(extractedData).length > 0) {
|
|
539
|
+
logger.debug(
|
|
540
|
+
`[ResponseModal] Pre-extracted data:`,
|
|
541
|
+
extractedData
|
|
542
|
+
);
|
|
543
|
+
// Requirement 3.3: Merge pre-extracted data into session before batch determination
|
|
544
|
+
updatedSession = mergeCollected(updatedSession, extractedData);
|
|
545
|
+
// Also update agent's collected data
|
|
546
|
+
await this.agent.updateCollectedData(extractedData);
|
|
547
|
+
|
|
548
|
+
// Re-check route completion after pre-extraction
|
|
549
|
+
const allRequiredFieldsCollected = routingResult.selectedRoute.isComplete(updatedSession.data || {});
|
|
550
|
+
if (allRequiredFieldsCollected) {
|
|
551
|
+
logger.debug(
|
|
552
|
+
`[ResponseModal] Route ${routingResult.selectedRoute.title} completed after pre-extraction`
|
|
553
|
+
);
|
|
554
|
+
isRouteComplete = true;
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
// BATCH DETERMINATION: Use BatchExecutor to determine which steps can execute together
|
|
561
|
+
// Requirement 3.4: Pre-extraction results affect batch determination
|
|
562
|
+
let batchSteps: StepOptions<TContext, TData>[] | undefined;
|
|
563
|
+
let batchStoppedReason: StoppedReason | undefined;
|
|
564
|
+
let batchStoppedAtStep: StepOptions<TContext, TData> | undefined;
|
|
565
|
+
|
|
566
|
+
if (routingResult.selectedRoute && !isRouteComplete) {
|
|
567
|
+
// Determine current step position for batch determination
|
|
568
|
+
const currentStep = routingResult.selectedStep ||
|
|
569
|
+
(updatedSession.currentStep ? routingResult.selectedRoute.getStep(updatedSession.currentStep.id) : undefined);
|
|
570
|
+
|
|
571
|
+
logger.debug(`[ResponseModal] Determining batch starting from step: ${currentStep?.id || 'initial'}`);
|
|
572
|
+
|
|
573
|
+
const batchResult = await this.batchExecutor.determineBatch({
|
|
574
|
+
route: routingResult.selectedRoute,
|
|
575
|
+
currentStep,
|
|
576
|
+
sessionData: updatedSession.data || {},
|
|
577
|
+
context: params.context,
|
|
578
|
+
});
|
|
579
|
+
|
|
580
|
+
batchSteps = batchResult.steps;
|
|
581
|
+
batchStoppedReason = batchResult.stoppedReason;
|
|
582
|
+
batchStoppedAtStep = batchResult.stoppedAtStep;
|
|
583
|
+
|
|
584
|
+
logger.debug(`[ResponseModal] Batch determined: ${batchSteps.length} steps, stopped reason: ${batchStoppedReason}`);
|
|
585
|
+
}
|
|
586
|
+
|
|
483
587
|
// Determine next step using pipeline method for consistency
|
|
484
|
-
const stepResult = this.responsePipeline.determineNextStep({
|
|
588
|
+
const stepResult = await this.responsePipeline.determineNextStep({
|
|
485
589
|
selectedRoute: routingResult.selectedRoute,
|
|
486
590
|
selectedStep: routingResult.selectedStep,
|
|
487
|
-
session:
|
|
488
|
-
isRouteComplete
|
|
591
|
+
session: updatedSession, // Use updated session with pre-extracted data
|
|
592
|
+
isRouteComplete, // Use updated completion status
|
|
489
593
|
});
|
|
490
594
|
|
|
491
595
|
return {
|
|
@@ -493,13 +597,106 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
493
597
|
selectedStep: stepResult.nextStep, // Use the determined next step
|
|
494
598
|
responseDirectives: routingResult.responseDirectives,
|
|
495
599
|
session: stepResult.session,
|
|
496
|
-
isRouteComplete
|
|
600
|
+
isRouteComplete, // Use updated completion status
|
|
601
|
+
batchSteps,
|
|
602
|
+
batchStoppedReason,
|
|
603
|
+
batchStoppedAtStep,
|
|
497
604
|
};
|
|
498
605
|
} catch (error) {
|
|
499
606
|
throw ResponseGenerationError.fromError(error, 'routing_optimization', params);
|
|
500
607
|
}
|
|
501
608
|
}
|
|
502
609
|
|
|
610
|
+
/**
|
|
611
|
+
* Check if a route should pre-extract data before determining the initial step
|
|
612
|
+
* @private
|
|
613
|
+
*/
|
|
614
|
+
private shouldPreExtractData(route: Route<TContext, TData>): boolean {
|
|
615
|
+
// Pre-extract if route has declared required or optional fields
|
|
616
|
+
if (route.requiredFields && route.requiredFields.length > 0) {
|
|
617
|
+
return true;
|
|
618
|
+
}
|
|
619
|
+
if (route.optionalFields && route.optionalFields.length > 0) {
|
|
620
|
+
return true;
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
// Pre-extract if any step in the route collects data
|
|
624
|
+
const steps = route.getAllSteps();
|
|
625
|
+
const hasDataCollectionSteps = steps.some(
|
|
626
|
+
step => step.collect && step.collect.length > 0
|
|
627
|
+
);
|
|
628
|
+
|
|
629
|
+
return hasDataCollectionSteps;
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
/**
|
|
633
|
+
* Pre-extract data from user message when entering a route
|
|
634
|
+
* This allows skipping steps whose data is already provided
|
|
635
|
+
* @private
|
|
636
|
+
*/
|
|
637
|
+
private async preExtractRouteData(params: {
|
|
638
|
+
route: Route<TContext, TData>;
|
|
639
|
+
history: Event[];
|
|
640
|
+
context: TContext;
|
|
641
|
+
session: SessionState<TData>;
|
|
642
|
+
signal?: AbortSignal;
|
|
643
|
+
}): Promise<Partial<TData>> {
|
|
644
|
+
const { route, history, context, signal } = params;
|
|
645
|
+
|
|
646
|
+
// Build a schema for data extraction based on route's fields
|
|
647
|
+
const extractionSchema = this.agent.getSchema();
|
|
648
|
+
if (!extractionSchema) {
|
|
649
|
+
logger.warn(`[ResponseModal] No schema available for pre-extraction`);
|
|
650
|
+
return {};
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
// Get last user message
|
|
654
|
+
const lastMessage = getLastMessageFromHistory(history);
|
|
655
|
+
|
|
656
|
+
// Build extraction prompt
|
|
657
|
+
const extractionPrompt = [
|
|
658
|
+
`Extract any relevant information from the user's message that matches the following data fields.`,
|
|
659
|
+
`Only extract information that is explicitly stated or clearly implied.`,
|
|
660
|
+
``,
|
|
661
|
+
`User's message: "${lastMessage}"`,
|
|
662
|
+
``,
|
|
663
|
+
`Extract data for these fields if present:`,
|
|
664
|
+
];
|
|
665
|
+
|
|
666
|
+
// Add field descriptions
|
|
667
|
+
if (route.requiredFields) {
|
|
668
|
+
extractionPrompt.push(`Required fields: ${route.requiredFields.join(', ')}`);
|
|
669
|
+
}
|
|
670
|
+
if (route.optionalFields) {
|
|
671
|
+
extractionPrompt.push(`Optional fields: ${route.optionalFields.join(', ')}`);
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
extractionPrompt.push(
|
|
675
|
+
``,
|
|
676
|
+
`Return ONLY the extracted data as JSON. If no data can be extracted, return an empty object {}.`
|
|
677
|
+
);
|
|
678
|
+
|
|
679
|
+
// Call AI to extract data
|
|
680
|
+
const agentOptions = this.agent.getAgentOptions();
|
|
681
|
+
try {
|
|
682
|
+
const result = await agentOptions.provider.generateMessage<TContext, Partial<TData>>({
|
|
683
|
+
prompt: extractionPrompt.join('\n'),
|
|
684
|
+
history,
|
|
685
|
+
context,
|
|
686
|
+
signal,
|
|
687
|
+
parameters: {
|
|
688
|
+
jsonSchema: extractionSchema,
|
|
689
|
+
schemaName: 'data_extraction',
|
|
690
|
+
},
|
|
691
|
+
});
|
|
692
|
+
|
|
693
|
+
return result.structured || {};
|
|
694
|
+
} catch (error) {
|
|
695
|
+
logger.error(`[ResponseModal] Pre-extraction failed:`, error);
|
|
696
|
+
return {};
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
|
|
503
700
|
/**
|
|
504
701
|
* Unified response generation for non-streaming responses
|
|
505
702
|
* @private
|
|
@@ -507,7 +704,17 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
507
704
|
private async generateUnifiedResponse(
|
|
508
705
|
responseContext: ResponseContext<TContext, TData>
|
|
509
706
|
): Promise<AgentResponse<TData>> {
|
|
510
|
-
const {
|
|
707
|
+
const {
|
|
708
|
+
effectiveContext,
|
|
709
|
+
session: initialSession,
|
|
710
|
+
history,
|
|
711
|
+
selectedRoute,
|
|
712
|
+
selectedStep,
|
|
713
|
+
responseDirectives,
|
|
714
|
+
isRouteComplete,
|
|
715
|
+
batchSteps,
|
|
716
|
+
batchStoppedReason,
|
|
717
|
+
} = responseContext;
|
|
511
718
|
let session = initialSession;
|
|
512
719
|
|
|
513
720
|
// Get last user message (needed for both route and completion handling)
|
|
@@ -517,42 +724,87 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
517
724
|
|
|
518
725
|
let message: string;
|
|
519
726
|
let toolCalls: Array<{ toolName: string; arguments: Record<string, unknown> }> | undefined = undefined;
|
|
727
|
+
let executedSteps: StepRef[] | undefined;
|
|
728
|
+
let stoppedReason: StoppedReason | undefined;
|
|
520
729
|
|
|
521
730
|
|
|
522
731
|
|
|
523
732
|
if (selectedRoute && !isRouteComplete) {
|
|
524
|
-
//
|
|
733
|
+
// Check if we have batch steps to execute
|
|
734
|
+
if (batchSteps && batchSteps.length > 0) {
|
|
735
|
+
// BATCH EXECUTION: Execute multiple steps in a single LLM call
|
|
736
|
+
logger.debug(`[ResponseModal] Executing batch of ${batchSteps.length} steps`);
|
|
525
737
|
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
signal: responseContext.history ? undefined : undefined, // TODO: Fix signal passing
|
|
536
|
-
});
|
|
738
|
+
const batchResult = await this.executeBatchResponse({
|
|
739
|
+
selectedRoute,
|
|
740
|
+
batchSteps,
|
|
741
|
+
responseDirectives,
|
|
742
|
+
session,
|
|
743
|
+
history,
|
|
744
|
+
context: effectiveContext,
|
|
745
|
+
historyEvents,
|
|
746
|
+
});
|
|
537
747
|
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
748
|
+
message = batchResult.message;
|
|
749
|
+
toolCalls = batchResult.toolCalls;
|
|
750
|
+
session = batchResult.session;
|
|
751
|
+
executedSteps = batchResult.executedSteps;
|
|
752
|
+
stoppedReason = batchStoppedReason;
|
|
753
|
+
|
|
754
|
+
} else {
|
|
755
|
+
// SINGLE STEP EXECUTION: Fall back to single-step processing
|
|
756
|
+
// This happens when batch determination returns empty (first step needs input)
|
|
757
|
+
const result = await this.processRouteResponse({
|
|
758
|
+
selectedRoute,
|
|
759
|
+
selectedStep,
|
|
760
|
+
responseDirectives,
|
|
761
|
+
session,
|
|
762
|
+
history,
|
|
763
|
+
context: effectiveContext,
|
|
764
|
+
lastMessageText,
|
|
765
|
+
historyEvents,
|
|
766
|
+
signal: undefined,
|
|
767
|
+
});
|
|
768
|
+
|
|
769
|
+
message = result.message;
|
|
770
|
+
toolCalls = result.toolCalls;
|
|
771
|
+
session = result.session;
|
|
772
|
+
|
|
773
|
+
// Track executed step for single-step execution
|
|
774
|
+
if (selectedStep) {
|
|
775
|
+
executedSteps = [{
|
|
776
|
+
id: selectedStep.id,
|
|
777
|
+
routeId: selectedRoute.id,
|
|
778
|
+
}];
|
|
779
|
+
}
|
|
780
|
+
stoppedReason = batchStoppedReason || 'needs_input';
|
|
781
|
+
}
|
|
541
782
|
|
|
542
783
|
} else if (isRouteComplete && selectedRoute) {
|
|
543
784
|
// Handle route completion
|
|
785
|
+
logger.debug(`[ResponseModal] Generating completion message for route: ${selectedRoute.title}`);
|
|
544
786
|
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
787
|
+
try {
|
|
788
|
+
message = await this.handleRouteCompletion({
|
|
789
|
+
selectedRoute,
|
|
790
|
+
session,
|
|
791
|
+
context: effectiveContext,
|
|
792
|
+
lastMessageText,
|
|
793
|
+
historyEvents,
|
|
794
|
+
signal: undefined,
|
|
795
|
+
});
|
|
552
796
|
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
797
|
+
// Set step to END_ROUTE marker
|
|
798
|
+
session = enterStep(session, END_ROUTE_ID, "Route completed");
|
|
799
|
+
stoppedReason = 'route_complete';
|
|
800
|
+
logger.debug(`[ResponseModal] Route ${selectedRoute.title} completed. Entered END_ROUTE step.`);
|
|
801
|
+
} catch (error) {
|
|
802
|
+
logger.error(`[ResponseModal] Error generating completion message:`, error);
|
|
803
|
+
// Fallback to simple completion message
|
|
804
|
+
message = `Thank you! I've recorded all the information for your ${selectedRoute.title.toLowerCase()}.`;
|
|
805
|
+
session = enterStep(session, END_ROUTE_ID, "Route completed");
|
|
806
|
+
stoppedReason = 'route_complete';
|
|
807
|
+
}
|
|
556
808
|
|
|
557
809
|
} else {
|
|
558
810
|
// Fallback: No routes defined, generate a simple response
|
|
@@ -562,16 +814,291 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
562
814
|
context: effectiveContext,
|
|
563
815
|
session,
|
|
564
816
|
});
|
|
817
|
+
|
|
818
|
+
// For fallback responses, set empty executedSteps and no stoppedReason
|
|
819
|
+
// since there's no route/step execution happening
|
|
820
|
+
executedSteps = [];
|
|
821
|
+
stoppedReason = undefined;
|
|
565
822
|
}
|
|
566
823
|
|
|
824
|
+
// Ensure response structure completeness (Requirement 8.1, 8.2, 8.3)
|
|
825
|
+
// - executedSteps: array of steps executed (empty array if none)
|
|
826
|
+
// - stoppedReason: why execution stopped (undefined for fallback)
|
|
827
|
+
// - session.currentStep: reflects final step position
|
|
567
828
|
return {
|
|
568
829
|
message,
|
|
569
830
|
session,
|
|
570
831
|
toolCalls,
|
|
571
832
|
isRouteComplete,
|
|
833
|
+
executedSteps: executedSteps || [],
|
|
834
|
+
stoppedReason,
|
|
835
|
+
};
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
/**
|
|
839
|
+
* Execute a batch of steps with a single LLM call
|
|
840
|
+
*
|
|
841
|
+
* This method:
|
|
842
|
+
* 1. Executes all prepare hooks for steps in the batch (in order)
|
|
843
|
+
* 2. Builds a combined prompt using BatchPromptBuilder
|
|
844
|
+
* 3. Makes a single LLM call
|
|
845
|
+
* 4. Collects data from the response for all steps
|
|
846
|
+
* 5. Executes all finalize hooks for steps in the batch (in order)
|
|
847
|
+
*
|
|
848
|
+
* @private
|
|
849
|
+
* **Validates: Requirements 1.1, 4.4, 5.1, 5.2**
|
|
850
|
+
*/
|
|
851
|
+
private async executeBatchResponse(params: {
|
|
852
|
+
selectedRoute: Route<TContext, TData>;
|
|
853
|
+
batchSteps: StepOptions<TContext, TData>[];
|
|
854
|
+
responseDirectives?: string[];
|
|
855
|
+
session: SessionState<TData>;
|
|
856
|
+
history: HistoryItem[];
|
|
857
|
+
context: TContext;
|
|
858
|
+
historyEvents: Event[];
|
|
859
|
+
signal?: AbortSignal;
|
|
860
|
+
}): Promise<{
|
|
861
|
+
message: string;
|
|
862
|
+
toolCalls?: Array<{ toolName: string; arguments: Record<string, unknown> }>;
|
|
863
|
+
session: SessionState<TData>;
|
|
864
|
+
executedSteps: StepRef[];
|
|
865
|
+
}> {
|
|
866
|
+
const { selectedRoute, batchSteps, history, context, historyEvents, signal } = params;
|
|
867
|
+
let session = params.session;
|
|
868
|
+
|
|
869
|
+
logger.debug(`[ResponseModal] Starting batch execution for ${batchSteps.length} steps`);
|
|
870
|
+
|
|
871
|
+
// Create hook executor function
|
|
872
|
+
const executeHook = async (
|
|
873
|
+
hook: HookFunction<TContext, TData>,
|
|
874
|
+
hookContext: TContext,
|
|
875
|
+
data?: Partial<TData>,
|
|
876
|
+
step?: StepOptions<TContext, TData>
|
|
877
|
+
): Promise<void> => {
|
|
878
|
+
// Find the route for this step
|
|
879
|
+
const route = selectedRoute;
|
|
880
|
+
// Convert StepOptions to Step if needed for executePrepareFinalize
|
|
881
|
+
const stepInstance = step?.id ? route.getStep(step.id) : undefined;
|
|
882
|
+
await this.executePrepareFinalize(hook, hookContext, data, route, stepInstance);
|
|
883
|
+
};
|
|
884
|
+
|
|
885
|
+
// PHASE 1: Execute all prepare hooks (Requirement 5.1)
|
|
886
|
+
logger.debug(`[ResponseModal] Executing prepare hooks for batch`);
|
|
887
|
+
const prepareResult = await this.batchExecutor.executePrepareHooks({
|
|
888
|
+
steps: batchSteps,
|
|
889
|
+
context,
|
|
890
|
+
data: session.data,
|
|
891
|
+
executeHook,
|
|
892
|
+
});
|
|
893
|
+
|
|
894
|
+
if (!prepareResult.success) {
|
|
895
|
+
// Prepare hook failed - return error response
|
|
896
|
+
logger.error(`[ResponseModal] Prepare hook failed:`, prepareResult.error);
|
|
897
|
+
throw new ResponseGenerationError(
|
|
898
|
+
`Prepare hook failed: ${prepareResult.error?.message}`,
|
|
899
|
+
{
|
|
900
|
+
phase: 'prepare_hooks',
|
|
901
|
+
context: {
|
|
902
|
+
stepId: prepareResult.error?.stepId,
|
|
903
|
+
executedSteps: prepareResult.executedSteps,
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
);
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
// PHASE 2: Build combined prompt using BatchPromptBuilder (Requirement 4.4)
|
|
910
|
+
logger.debug(`[ResponseModal] Building batch prompt`);
|
|
911
|
+
const batchPromptResult = await this.batchPromptBuilder.buildBatchPrompt({
|
|
912
|
+
steps: batchSteps,
|
|
913
|
+
route: selectedRoute,
|
|
914
|
+
history: historyEvents,
|
|
915
|
+
context,
|
|
916
|
+
session,
|
|
917
|
+
agentOptions: this.agent.getAgentOptions(),
|
|
918
|
+
});
|
|
919
|
+
|
|
920
|
+
logger.debug(`[ResponseModal] Batch prompt built with ${batchPromptResult.stepCount} steps, collecting: ${batchPromptResult.collectFields.join(', ')}`);
|
|
921
|
+
|
|
922
|
+
// Build response schema for batch (includes all collect fields)
|
|
923
|
+
const responseSchema = this.buildBatchResponseSchema(batchPromptResult.collectFields);
|
|
924
|
+
|
|
925
|
+
// Collect available tools for AI (from all steps in batch)
|
|
926
|
+
const availableTools = this.collectBatchAvailableTools(selectedRoute, batchSteps);
|
|
927
|
+
|
|
928
|
+
// PHASE 3: Make single LLM call (Requirement 4.4)
|
|
929
|
+
logger.debug(`[ResponseModal] Making LLM call for batch`);
|
|
930
|
+
const agentOptions = this.agent.getAgentOptions();
|
|
931
|
+
const result = await agentOptions.provider.generateMessage({
|
|
932
|
+
prompt: batchPromptResult.prompt,
|
|
933
|
+
history: historyEvents,
|
|
934
|
+
context,
|
|
935
|
+
tools: availableTools,
|
|
936
|
+
signal,
|
|
937
|
+
parameters: responseSchema ? { jsonSchema: responseSchema, schemaName: "batch_response" } : undefined,
|
|
938
|
+
});
|
|
939
|
+
|
|
940
|
+
let message = result.structured?.message || result.message;
|
|
941
|
+
let toolCalls = result.structured?.toolCalls;
|
|
942
|
+
|
|
943
|
+
logger.debug(`[ResponseModal] LLM response received for batch`);
|
|
944
|
+
|
|
945
|
+
// Execute tools if any
|
|
946
|
+
if (toolCalls && toolCalls.length > 0) {
|
|
947
|
+
const toolResult = await this.executeUnifiedToolLoop({
|
|
948
|
+
toolCalls,
|
|
949
|
+
context,
|
|
950
|
+
session,
|
|
951
|
+
history,
|
|
952
|
+
selectedRoute,
|
|
953
|
+
responsePrompt: batchPromptResult.prompt,
|
|
954
|
+
availableTools,
|
|
955
|
+
responseSchema,
|
|
956
|
+
signal,
|
|
957
|
+
});
|
|
958
|
+
|
|
959
|
+
session = toolResult.session;
|
|
960
|
+
toolCalls = toolResult.finalToolCalls;
|
|
961
|
+
if (toolResult.finalMessage) {
|
|
962
|
+
message = toolResult.finalMessage;
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
// PHASE 4: Collect data from response for all steps (Requirement 6.1, 6.2, 6.3)
|
|
967
|
+
logger.debug(`[ResponseModal] Collecting batch data`);
|
|
968
|
+
const collectResult = this.batchExecutor.collectBatchData({
|
|
969
|
+
steps: batchSteps,
|
|
970
|
+
llmResponse: result.structured || {},
|
|
971
|
+
session,
|
|
972
|
+
schema: this.agent.getSchema(),
|
|
973
|
+
});
|
|
974
|
+
|
|
975
|
+
session = collectResult.session;
|
|
976
|
+
|
|
977
|
+
if (collectResult.collectedData && Object.keys(collectResult.collectedData).length > 0) {
|
|
978
|
+
// Update agent's collected data
|
|
979
|
+
await this.agent.updateCollectedData(collectResult.collectedData);
|
|
980
|
+
logger.debug(`[ResponseModal] Batch collected data:`, collectResult.collectedData);
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
if (collectResult.validationErrors && collectResult.validationErrors.length > 0) {
|
|
984
|
+
logger.warn(`[ResponseModal] Batch data validation errors:`, collectResult.validationErrors);
|
|
985
|
+
}
|
|
986
|
+
|
|
987
|
+
// Update session to final step position
|
|
988
|
+
const lastStep = batchSteps[batchSteps.length - 1];
|
|
989
|
+
if (lastStep?.id) {
|
|
990
|
+
session = enterStep(session, lastStep.id, lastStep.description);
|
|
991
|
+
logger.debug(`[ResponseModal] Updated session to final batch step: ${lastStep.id}`);
|
|
992
|
+
}
|
|
993
|
+
|
|
994
|
+
// PHASE 5: Execute all finalize hooks (Requirement 5.2)
|
|
995
|
+
logger.debug(`[ResponseModal] Executing finalize hooks for batch`);
|
|
996
|
+
const finalizeResult = await this.batchExecutor.executeFinalizeHooks({
|
|
997
|
+
steps: batchSteps,
|
|
998
|
+
context,
|
|
999
|
+
data: session.data,
|
|
1000
|
+
executeHook,
|
|
1001
|
+
});
|
|
1002
|
+
|
|
1003
|
+
if (finalizeResult.errors && finalizeResult.errors.length > 0) {
|
|
1004
|
+
// Log finalize errors but don't fail (Requirement 5.5)
|
|
1005
|
+
logger.warn(`[ResponseModal] Some finalize hooks failed:`, finalizeResult.errors);
|
|
1006
|
+
}
|
|
1007
|
+
|
|
1008
|
+
// Build executed steps list
|
|
1009
|
+
const executedSteps: StepRef[] = batchSteps
|
|
1010
|
+
.filter(step => step.id)
|
|
1011
|
+
.map(step => ({
|
|
1012
|
+
id: step.id!,
|
|
1013
|
+
routeId: selectedRoute.id,
|
|
1014
|
+
}));
|
|
1015
|
+
|
|
1016
|
+
logger.debug(`[ResponseModal] Batch execution complete. Executed ${executedSteps.length} steps`);
|
|
1017
|
+
|
|
1018
|
+
return {
|
|
1019
|
+
message,
|
|
1020
|
+
toolCalls,
|
|
1021
|
+
session,
|
|
1022
|
+
executedSteps,
|
|
572
1023
|
};
|
|
573
1024
|
}
|
|
574
1025
|
|
|
1026
|
+
/**
|
|
1027
|
+
* Build response schema for batch execution
|
|
1028
|
+
* @private
|
|
1029
|
+
*/
|
|
1030
|
+
private buildBatchResponseSchema(collectFields: string[]): Record<string, unknown> {
|
|
1031
|
+
const properties: Record<string, unknown> = {
|
|
1032
|
+
message: {
|
|
1033
|
+
type: "string",
|
|
1034
|
+
description: "Your response to the user",
|
|
1035
|
+
},
|
|
1036
|
+
};
|
|
1037
|
+
|
|
1038
|
+
// Add collect fields to schema
|
|
1039
|
+
for (const field of collectFields) {
|
|
1040
|
+
properties[field] = {
|
|
1041
|
+
type: "string",
|
|
1042
|
+
description: `Collected value for ${field}`,
|
|
1043
|
+
};
|
|
1044
|
+
}
|
|
1045
|
+
|
|
1046
|
+
return {
|
|
1047
|
+
type: "object",
|
|
1048
|
+
properties,
|
|
1049
|
+
required: ["message"],
|
|
1050
|
+
additionalProperties: true,
|
|
1051
|
+
};
|
|
1052
|
+
}
|
|
1053
|
+
|
|
1054
|
+
/**
|
|
1055
|
+
* Collect available tools from all steps in the batch
|
|
1056
|
+
* @private
|
|
1057
|
+
*/
|
|
1058
|
+
private collectBatchAvailableTools(
|
|
1059
|
+
route: Route<TContext, TData>,
|
|
1060
|
+
batchSteps: StepOptions<TContext, TData>[]
|
|
1061
|
+
): Array<{
|
|
1062
|
+
id: string;
|
|
1063
|
+
name: string;
|
|
1064
|
+
description?: string;
|
|
1065
|
+
parameters?: unknown;
|
|
1066
|
+
}> {
|
|
1067
|
+
const availableTools = new Map<string, Tool<TContext, TData>>();
|
|
1068
|
+
|
|
1069
|
+
// Add agent-level tools
|
|
1070
|
+
this.agent.getTools().forEach((tool) => {
|
|
1071
|
+
availableTools.set(tool.id, tool);
|
|
1072
|
+
});
|
|
1073
|
+
|
|
1074
|
+
// Add route-level tools
|
|
1075
|
+
route.getTools().forEach((tool: Tool<TContext, TData>) => {
|
|
1076
|
+
availableTools.set(tool.id, tool);
|
|
1077
|
+
});
|
|
1078
|
+
|
|
1079
|
+
// Add step-level tools from all batch steps
|
|
1080
|
+
for (const step of batchSteps) {
|
|
1081
|
+
if (step.tools) {
|
|
1082
|
+
for (const toolRef of step.tools) {
|
|
1083
|
+
if (typeof toolRef === "string") {
|
|
1084
|
+
// Reference to registered tool - already in availableTools
|
|
1085
|
+
} else if (typeof toolRef === 'object' && 'id' in toolRef && toolRef.id) {
|
|
1086
|
+
// Inline tool definition
|
|
1087
|
+
availableTools.set(toolRef.id, toolRef);
|
|
1088
|
+
}
|
|
1089
|
+
}
|
|
1090
|
+
}
|
|
1091
|
+
}
|
|
1092
|
+
|
|
1093
|
+
// Convert to the format expected by AI providers
|
|
1094
|
+
return Array.from(availableTools.values()).map((tool) => ({
|
|
1095
|
+
id: tool.id,
|
|
1096
|
+
name: tool.name || tool.id,
|
|
1097
|
+
description: tool.description,
|
|
1098
|
+
parameters: tool.parameters,
|
|
1099
|
+
}));
|
|
1100
|
+
}
|
|
1101
|
+
|
|
575
1102
|
/**
|
|
576
1103
|
* Unified streaming response generation
|
|
577
1104
|
* @private
|
|
@@ -579,7 +1106,17 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
579
1106
|
private async *generateUnifiedStreamingResponse(
|
|
580
1107
|
responseContext: ResponseContext<TContext, TData>
|
|
581
1108
|
): AsyncGenerator<AgentResponseStreamChunk<TData>> {
|
|
582
|
-
const {
|
|
1109
|
+
const {
|
|
1110
|
+
effectiveContext,
|
|
1111
|
+
session: initialSession,
|
|
1112
|
+
history,
|
|
1113
|
+
selectedRoute,
|
|
1114
|
+
selectedStep,
|
|
1115
|
+
responseDirectives,
|
|
1116
|
+
isRouteComplete,
|
|
1117
|
+
batchSteps,
|
|
1118
|
+
batchStoppedReason,
|
|
1119
|
+
} = responseContext;
|
|
583
1120
|
const session = initialSession;
|
|
584
1121
|
|
|
585
1122
|
// Get last user message (needed for both route and completion handling)
|
|
@@ -588,17 +1125,35 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
588
1125
|
const lastMessageText = getLastMessageFromHistory(historyEvents);
|
|
589
1126
|
|
|
590
1127
|
if (selectedRoute && !isRouteComplete) {
|
|
591
|
-
//
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
1128
|
+
// Check if we have batch steps to execute
|
|
1129
|
+
if (batchSteps && batchSteps.length > 0) {
|
|
1130
|
+
// BATCH EXECUTION: Execute multiple steps with streaming
|
|
1131
|
+
// Note: For streaming, we still use batch execution but stream the response
|
|
1132
|
+
logger.debug(`[ResponseModal] Streaming batch execution for ${batchSteps.length} steps`);
|
|
1133
|
+
|
|
1134
|
+
yield* this.streamBatchResponse({
|
|
1135
|
+
selectedRoute,
|
|
1136
|
+
batchSteps,
|
|
1137
|
+
responseDirectives,
|
|
1138
|
+
session,
|
|
1139
|
+
history,
|
|
1140
|
+
context: effectiveContext,
|
|
1141
|
+
historyEvents,
|
|
1142
|
+
batchStoppedReason,
|
|
1143
|
+
});
|
|
1144
|
+
} else {
|
|
1145
|
+
// SINGLE STEP EXECUTION: Fall back to single-step streaming
|
|
1146
|
+
yield* this.processRouteStreamingResponse({
|
|
1147
|
+
selectedRoute,
|
|
1148
|
+
selectedStep,
|
|
1149
|
+
responseDirectives,
|
|
1150
|
+
session,
|
|
1151
|
+
history,
|
|
1152
|
+
context: effectiveContext,
|
|
1153
|
+
lastMessageText,
|
|
1154
|
+
historyEvents,
|
|
1155
|
+
});
|
|
1156
|
+
}
|
|
602
1157
|
|
|
603
1158
|
} else if (isRouteComplete && selectedRoute) {
|
|
604
1159
|
// Handle route completion streaming
|
|
@@ -619,6 +1174,148 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
619
1174
|
});
|
|
620
1175
|
}
|
|
621
1176
|
}
|
|
1177
|
+
|
|
1178
|
+
/**
|
|
1179
|
+
* Stream a batch response with multiple steps
|
|
1180
|
+
*
|
|
1181
|
+
* Similar to executeBatchResponse but streams the LLM response.
|
|
1182
|
+
*
|
|
1183
|
+
* @private
|
|
1184
|
+
*/
|
|
1185
|
+
private async *streamBatchResponse(params: {
|
|
1186
|
+
selectedRoute: Route<TContext, TData>;
|
|
1187
|
+
batchSteps: StepOptions<TContext, TData>[];
|
|
1188
|
+
responseDirectives?: string[];
|
|
1189
|
+
session: SessionState<TData>;
|
|
1190
|
+
history: HistoryItem[];
|
|
1191
|
+
context: TContext;
|
|
1192
|
+
historyEvents: Event[];
|
|
1193
|
+
batchStoppedReason?: StoppedReason;
|
|
1194
|
+
signal?: AbortSignal;
|
|
1195
|
+
}): AsyncGenerator<AgentResponseStreamChunk<TData>> {
|
|
1196
|
+
const { selectedRoute, batchSteps, context, historyEvents, batchStoppedReason, signal } = params;
|
|
1197
|
+
let session = params.session;
|
|
1198
|
+
|
|
1199
|
+
// Create hook executor function
|
|
1200
|
+
const executeHook = async (
|
|
1201
|
+
hook: HookFunction<TContext, TData>,
|
|
1202
|
+
hookContext: TContext,
|
|
1203
|
+
data?: Partial<TData>,
|
|
1204
|
+
step?: StepOptions<TContext, TData>
|
|
1205
|
+
): Promise<void> => {
|
|
1206
|
+
const route = selectedRoute;
|
|
1207
|
+
const stepInstance = step?.id ? route.getStep(step.id) : undefined;
|
|
1208
|
+
await this.executePrepareFinalize(hook, hookContext, data, route, stepInstance);
|
|
1209
|
+
};
|
|
1210
|
+
|
|
1211
|
+
// PHASE 1: Execute all prepare hooks
|
|
1212
|
+
const prepareResult = await this.batchExecutor.executePrepareHooks({
|
|
1213
|
+
steps: batchSteps,
|
|
1214
|
+
context,
|
|
1215
|
+
data: session.data,
|
|
1216
|
+
executeHook,
|
|
1217
|
+
});
|
|
1218
|
+
|
|
1219
|
+
if (!prepareResult.success) {
|
|
1220
|
+
// Yield error chunk
|
|
1221
|
+
yield {
|
|
1222
|
+
delta: "",
|
|
1223
|
+
accumulated: "",
|
|
1224
|
+
done: true,
|
|
1225
|
+
session,
|
|
1226
|
+
error: new ResponseGenerationError(
|
|
1227
|
+
`Prepare hook failed: ${prepareResult.error?.message}`,
|
|
1228
|
+
{ phase: 'prepare_hooks' }
|
|
1229
|
+
),
|
|
1230
|
+
};
|
|
1231
|
+
return;
|
|
1232
|
+
}
|
|
1233
|
+
|
|
1234
|
+
// PHASE 2: Build combined prompt
|
|
1235
|
+
const batchPromptResult = await this.batchPromptBuilder.buildBatchPrompt({
|
|
1236
|
+
steps: batchSteps,
|
|
1237
|
+
route: selectedRoute,
|
|
1238
|
+
history: historyEvents,
|
|
1239
|
+
context,
|
|
1240
|
+
session,
|
|
1241
|
+
agentOptions: this.agent.getAgentOptions(),
|
|
1242
|
+
});
|
|
1243
|
+
|
|
1244
|
+
const responseSchema = this.buildBatchResponseSchema(batchPromptResult.collectFields);
|
|
1245
|
+
const availableTools = this.collectBatchAvailableTools(selectedRoute, batchSteps);
|
|
1246
|
+
|
|
1247
|
+
// PHASE 3: Stream LLM response
|
|
1248
|
+
const agentOptions = this.agent.getAgentOptions();
|
|
1249
|
+
const stream = agentOptions.provider.generateMessageStream({
|
|
1250
|
+
prompt: batchPromptResult.prompt,
|
|
1251
|
+
history: historyEvents,
|
|
1252
|
+
context,
|
|
1253
|
+
tools: availableTools,
|
|
1254
|
+
signal,
|
|
1255
|
+
parameters: responseSchema ? { jsonSchema: responseSchema, schemaName: "batch_stream_response" } : undefined,
|
|
1256
|
+
});
|
|
1257
|
+
|
|
1258
|
+
// Build executed steps list
|
|
1259
|
+
const executedSteps: StepRef[] = batchSteps
|
|
1260
|
+
.filter(step => step.id)
|
|
1261
|
+
.map(step => ({
|
|
1262
|
+
id: step.id!,
|
|
1263
|
+
routeId: selectedRoute.id,
|
|
1264
|
+
}));
|
|
1265
|
+
|
|
1266
|
+
// Stream chunks
|
|
1267
|
+
for await (const chunk of stream) {
|
|
1268
|
+
// On final chunk, collect data and execute finalize hooks
|
|
1269
|
+
if (chunk.done) {
|
|
1270
|
+
// Collect data from response
|
|
1271
|
+
if (chunk.structured) {
|
|
1272
|
+
const collectResult = this.batchExecutor.collectBatchData({
|
|
1273
|
+
steps: batchSteps,
|
|
1274
|
+
llmResponse: chunk.structured,
|
|
1275
|
+
session,
|
|
1276
|
+
schema: this.agent.getSchema(),
|
|
1277
|
+
});
|
|
1278
|
+
|
|
1279
|
+
session = collectResult.session;
|
|
1280
|
+
|
|
1281
|
+
if (collectResult.collectedData && Object.keys(collectResult.collectedData).length > 0) {
|
|
1282
|
+
await this.agent.updateCollectedData(collectResult.collectedData);
|
|
1283
|
+
}
|
|
1284
|
+
}
|
|
1285
|
+
|
|
1286
|
+
// Update session to final step position
|
|
1287
|
+
const lastStep = batchSteps[batchSteps.length - 1];
|
|
1288
|
+
if (lastStep?.id) {
|
|
1289
|
+
session = enterStep(session, lastStep.id, lastStep.description);
|
|
1290
|
+
}
|
|
1291
|
+
|
|
1292
|
+
// Execute finalize hooks
|
|
1293
|
+
await this.batchExecutor.executeFinalizeHooks({
|
|
1294
|
+
steps: batchSteps,
|
|
1295
|
+
context,
|
|
1296
|
+
data: session.data,
|
|
1297
|
+
executeHook,
|
|
1298
|
+
});
|
|
1299
|
+
|
|
1300
|
+
// Finalize session
|
|
1301
|
+
await this.finalizeSession(session, context);
|
|
1302
|
+
}
|
|
1303
|
+
|
|
1304
|
+
yield {
|
|
1305
|
+
delta: chunk.delta,
|
|
1306
|
+
accumulated: chunk.accumulated,
|
|
1307
|
+
done: chunk.done,
|
|
1308
|
+
session,
|
|
1309
|
+
toolCalls: chunk.structured?.toolCalls,
|
|
1310
|
+
isRouteComplete: false,
|
|
1311
|
+
executedSteps: chunk.done ? executedSteps : undefined,
|
|
1312
|
+
stoppedReason: chunk.done ? batchStoppedReason : undefined,
|
|
1313
|
+
metadata: chunk.metadata,
|
|
1314
|
+
structured: chunk.structured,
|
|
1315
|
+
};
|
|
1316
|
+
}
|
|
1317
|
+
}
|
|
1318
|
+
|
|
622
1319
|
/**
|
|
623
1320
|
* Execute prepare function for current step if available
|
|
624
1321
|
* @private
|
|
@@ -698,12 +1395,27 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
698
1395
|
if (selectedStep) {
|
|
699
1396
|
nextStep = selectedStep;
|
|
700
1397
|
} else {
|
|
701
|
-
//
|
|
1398
|
+
// Determine current step from session if we're already in this route
|
|
1399
|
+
const isInSameRoute = session.currentRoute?.id === selectedRoute.id;
|
|
1400
|
+
const currentStep = isInSameRoute && session.currentStep
|
|
1401
|
+
? selectedRoute.getStep(session.currentStep.id)
|
|
1402
|
+
: undefined;
|
|
1403
|
+
|
|
1404
|
+
logger.debug(`[ResponseModal] Step determination: route match=${isInSameRoute}, currentRoute=${session.currentRoute?.id}, selectedRoute=${selectedRoute.id}, currentStep=${currentStep?.id || 'none'}`);
|
|
1405
|
+
|
|
1406
|
+
// Get candidate steps based on current position in the route
|
|
702
1407
|
const routingEngine = this.agent.getRoutingEngine();
|
|
703
|
-
const candidates = routingEngine.
|
|
1408
|
+
const candidates = await routingEngine.getCandidateStepsWithConditions(
|
|
1409
|
+
selectedRoute,
|
|
1410
|
+
currentStep, // Pass current step instead of undefined to maintain progression
|
|
1411
|
+
createTemplateContext({ data: session.data, session, context })
|
|
1412
|
+
);
|
|
1413
|
+
|
|
1414
|
+
logger.debug(`[ResponseModal] Found ${candidates.length} candidate steps${currentStep ? ' from current step ' + currentStep.id : ' (new route entry)'}`);
|
|
1415
|
+
|
|
704
1416
|
if (candidates.length > 0) {
|
|
705
1417
|
nextStep = candidates[0].step;
|
|
706
|
-
logger.debug(`[ResponseModal] Using first valid step: ${nextStep.id} for new route`);
|
|
1418
|
+
logger.debug(`[ResponseModal] Using first valid step: ${nextStep.id}${currentStep ? ' (progressing from ' + currentStep.id + ')' : ' for new route'}`);
|
|
707
1419
|
} else {
|
|
708
1420
|
// Fallback to initial step even if it should be skipped
|
|
709
1421
|
nextStep = selectedRoute.initialStep;
|
|
@@ -752,6 +1464,15 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
752
1464
|
let message = result.structured?.message || result.message;
|
|
753
1465
|
let toolCalls = result.structured?.toolCalls;
|
|
754
1466
|
|
|
1467
|
+
// Debug: Log initial AI response
|
|
1468
|
+
logger.debug(`[ResponseModal] Initial AI response:`, {
|
|
1469
|
+
hasMessage: !!message,
|
|
1470
|
+
messageLength: message?.length || 0,
|
|
1471
|
+
hasToolCalls: !!toolCalls,
|
|
1472
|
+
toolCallsCount: toolCalls?.length || 0,
|
|
1473
|
+
toolNames: toolCalls?.map(tc => tc.toolName) || [],
|
|
1474
|
+
});
|
|
1475
|
+
|
|
755
1476
|
// Execute tools with unified loop handling
|
|
756
1477
|
const toolResult = await this.executeUnifiedToolLoop({
|
|
757
1478
|
toolCalls,
|
|
@@ -800,11 +1521,22 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
800
1521
|
if (selectedStep) {
|
|
801
1522
|
nextStep = selectedStep;
|
|
802
1523
|
} else {
|
|
1524
|
+
// Determine current step from session if we're already in this route
|
|
1525
|
+
const currentStep = session.currentRoute?.id === selectedRoute.id && session.currentStep
|
|
1526
|
+
? selectedRoute.getStep(session.currentStep.id)
|
|
1527
|
+
: undefined;
|
|
1528
|
+
|
|
1529
|
+
// Get candidate steps based on current position in the route
|
|
803
1530
|
const routingEngine = this.agent.getRoutingEngine();
|
|
804
|
-
const candidates = routingEngine.
|
|
1531
|
+
const candidates = await routingEngine.getCandidateStepsWithConditions(
|
|
1532
|
+
selectedRoute,
|
|
1533
|
+
currentStep, // Pass current step instead of undefined to maintain progression
|
|
1534
|
+
createTemplateContext({ data: session.data, session, context })
|
|
1535
|
+
);
|
|
1536
|
+
|
|
805
1537
|
if (candidates.length > 0) {
|
|
806
1538
|
nextStep = candidates[0].step;
|
|
807
|
-
logger.debug(`[ResponseModal] Using first valid step: ${nextStep.id} for new route`);
|
|
1539
|
+
logger.debug(`[ResponseModal] Using first valid step: ${nextStep.id}${currentStep ? ' (progressing from ' + currentStep.id + ')' : ' for new route'}`);
|
|
808
1540
|
} else {
|
|
809
1541
|
nextStep = selectedRoute.initialStep;
|
|
810
1542
|
logger.warn(`[ResponseModal] No valid steps found, using initial step: ${nextStep.id}`);
|
|
@@ -887,6 +1619,10 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
887
1619
|
await this.finalizeSession(session, context);
|
|
888
1620
|
}
|
|
889
1621
|
|
|
1622
|
+
// Response structure completeness (Requirement 8.1, 8.2, 8.3)
|
|
1623
|
+
// - executedSteps: single step executed in this response
|
|
1624
|
+
// - stoppedReason: 'needs_input' for single-step execution (waiting for user input)
|
|
1625
|
+
// - session.currentStep: reflects the executed step
|
|
890
1626
|
yield {
|
|
891
1627
|
delta: chunk.delta,
|
|
892
1628
|
accumulated: chunk.accumulated,
|
|
@@ -894,6 +1630,8 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
894
1630
|
session,
|
|
895
1631
|
toolCalls,
|
|
896
1632
|
isRouteComplete: false,
|
|
1633
|
+
executedSteps: chunk.done ? [{ id: nextStep.id, routeId: selectedRoute.id }] : undefined,
|
|
1634
|
+
stoppedReason: chunk.done ? 'needs_input' : undefined,
|
|
897
1635
|
metadata: chunk.metadata,
|
|
898
1636
|
structured: chunk.structured,
|
|
899
1637
|
};
|
|
@@ -934,7 +1672,7 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
934
1672
|
|
|
935
1673
|
// Execute initial dynamic tool calls
|
|
936
1674
|
if (toolCalls && toolCalls.length > 0) {
|
|
937
|
-
logger.debug(`[ResponseModal] Executing ${toolCalls.length} dynamic tool calls
|
|
1675
|
+
logger.debug(`[ResponseModal] Executing ${toolCalls.length} dynamic tool calls:`, toolCalls.map(tc => tc.toolName));
|
|
938
1676
|
|
|
939
1677
|
for (const toolCall of toolCalls) {
|
|
940
1678
|
const tool = this.findAvailableTool(toolCall.toolName, selectedRoute);
|
|
@@ -1009,7 +1747,7 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
1009
1747
|
|
|
1010
1748
|
while (hasToolCalls && toolLoopCount < MAX_TOOL_LOOPS) {
|
|
1011
1749
|
toolLoopCount++;
|
|
1012
|
-
logger.debug(`[ResponseModal] Starting tool loop ${toolLoopCount}/${MAX_TOOL_LOOPS}`);
|
|
1750
|
+
logger.debug(`[ResponseModal] Starting tool loop ${toolLoopCount}/${MAX_TOOL_LOOPS} with ${toolCalls?.length || 0} tool calls`);
|
|
1013
1751
|
|
|
1014
1752
|
// Create tool result events with proper Event format structure
|
|
1015
1753
|
const toolResultEvents: Event<ToolEventData>[] = [];
|
|
@@ -1041,12 +1779,21 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
1041
1779
|
const updatedHistoryEvents = [...historyEvents, ...toolResultEvents];
|
|
1042
1780
|
|
|
1043
1781
|
// Make follow-up AI call to see if more tools are needed
|
|
1782
|
+
// After first iteration, don't provide tools to force a text response
|
|
1044
1783
|
const agentOptions = this.agent.getAgentOptions();
|
|
1784
|
+
const shouldProvideTools = toolLoopCount === 1;
|
|
1785
|
+
|
|
1786
|
+
logger.debug(`[ResponseModal] Making follow-up AI call (loop ${toolLoopCount}):`, {
|
|
1787
|
+
providingTools: shouldProvideTools,
|
|
1788
|
+
toolsCount: shouldProvideTools ? availableTools.length : 0,
|
|
1789
|
+
addingTextInstruction: toolLoopCount > 1,
|
|
1790
|
+
});
|
|
1791
|
+
|
|
1045
1792
|
const followUpResult = await agentOptions.provider.generateMessage({
|
|
1046
|
-
prompt: responsePrompt,
|
|
1793
|
+
prompt: responsePrompt + (toolLoopCount > 1 ? "\n\nProvide a text response to the user based on the tool results." : ""),
|
|
1047
1794
|
history: updatedHistoryEvents, // Use Event[] for AI provider
|
|
1048
1795
|
context,
|
|
1049
|
-
tools: availableTools,
|
|
1796
|
+
tools: shouldProvideTools ? availableTools : [], // Only provide tools on first iteration
|
|
1050
1797
|
parameters: responseSchema ? {
|
|
1051
1798
|
jsonSchema: responseSchema,
|
|
1052
1799
|
schemaName: "tool_followup",
|
|
@@ -1058,6 +1805,14 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
1058
1805
|
const followUpToolCalls = followUpResult.structured?.toolCalls;
|
|
1059
1806
|
hasToolCalls = followUpToolCalls && followUpToolCalls.length > 0;
|
|
1060
1807
|
|
|
1808
|
+
logger.debug(`[ResponseModal] Follow-up AI response (loop ${toolLoopCount}):`, {
|
|
1809
|
+
hasMessage: !!followUpResult.message,
|
|
1810
|
+
messageLength: followUpResult.message?.length || 0,
|
|
1811
|
+
hasToolCalls,
|
|
1812
|
+
toolCallsCount: followUpToolCalls?.length || 0,
|
|
1813
|
+
toolNames: followUpToolCalls?.map(tc => tc.toolName) || [],
|
|
1814
|
+
});
|
|
1815
|
+
|
|
1061
1816
|
if (hasToolCalls) {
|
|
1062
1817
|
logger.debug(`[ResponseModal] Follow-up call produced ${followUpToolCalls!.length} additional tool calls`);
|
|
1063
1818
|
|
|
@@ -1136,6 +1891,13 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
1136
1891
|
logger.warn(`[ResponseModal] Tool loop limit reached (${MAX_TOOL_LOOPS}), stopping`);
|
|
1137
1892
|
}
|
|
1138
1893
|
|
|
1894
|
+
logger.debug(`[ResponseModal] Tool loop completed:`, {
|
|
1895
|
+
totalIterations: toolLoopCount,
|
|
1896
|
+
hasFinalMessage: !!finalMessage,
|
|
1897
|
+
finalMessageLength: finalMessage?.length || 0,
|
|
1898
|
+
finalToolCallsCount: toolCalls?.length || 0,
|
|
1899
|
+
});
|
|
1900
|
+
|
|
1139
1901
|
return {
|
|
1140
1902
|
session,
|
|
1141
1903
|
finalToolCalls: toolCalls,
|
|
@@ -1162,15 +1924,34 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
1162
1924
|
let updatedSession = session;
|
|
1163
1925
|
|
|
1164
1926
|
// Extract collected data from final response (only for route-based interactions)
|
|
1165
|
-
if (selectedRoute && result.structured
|
|
1927
|
+
if (selectedRoute && result.structured) {
|
|
1166
1928
|
try {
|
|
1167
1929
|
const collectedData: Record<string, unknown> = {};
|
|
1168
1930
|
// AgentStructuredResponse extends Record<string, unknown>, so we can safely access properties
|
|
1169
1931
|
const structuredData = result.structured;
|
|
1170
1932
|
|
|
1171
|
-
|
|
1933
|
+
// Collect ALL route fields (required + optional) from structured response
|
|
1934
|
+
const allRouteFields = new Set<string>();
|
|
1935
|
+
|
|
1936
|
+
// Add route required fields
|
|
1937
|
+
if (selectedRoute.requiredFields) {
|
|
1938
|
+
selectedRoute.requiredFields.forEach(field => allRouteFields.add(String(field)));
|
|
1939
|
+
}
|
|
1940
|
+
|
|
1941
|
+
// Add route optional fields
|
|
1942
|
+
if (selectedRoute.optionalFields) {
|
|
1943
|
+
selectedRoute.optionalFields.forEach(field => allRouteFields.add(String(field)));
|
|
1944
|
+
}
|
|
1945
|
+
|
|
1946
|
+
// Also include current step's collect fields (in case they're not in route fields)
|
|
1947
|
+
if (nextStep?.collect) {
|
|
1948
|
+
nextStep.collect.forEach(field => allRouteFields.add(String(field)));
|
|
1949
|
+
}
|
|
1950
|
+
|
|
1951
|
+
// Extract all available fields from structured response
|
|
1952
|
+
for (const field of allRouteFields) {
|
|
1172
1953
|
const fieldKey = String(field);
|
|
1173
|
-
if (fieldKey in structuredData) {
|
|
1954
|
+
if (fieldKey in structuredData && structuredData[fieldKey] !== undefined && structuredData[fieldKey] !== null) {
|
|
1174
1955
|
collectedData[fieldKey] = structuredData[fieldKey];
|
|
1175
1956
|
}
|
|
1176
1957
|
}
|
|
@@ -1244,37 +2025,66 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
1244
2025
|
prompt: endStepSpec.prompt || "Summarize what was accomplished and confirm completion based on the conversation history and collected data",
|
|
1245
2026
|
});
|
|
1246
2027
|
|
|
1247
|
-
// Build response schema for completion
|
|
1248
|
-
const
|
|
1249
|
-
|
|
2028
|
+
// Build response schema for completion (message only, no data collection)
|
|
2029
|
+
const completionSchema = {
|
|
2030
|
+
type: "object",
|
|
2031
|
+
properties: {
|
|
2032
|
+
message: {
|
|
2033
|
+
type: "string",
|
|
2034
|
+
description: "Completion message confirming what was accomplished",
|
|
2035
|
+
},
|
|
2036
|
+
},
|
|
2037
|
+
required: ["message"],
|
|
2038
|
+
additionalProperties: false,
|
|
2039
|
+
};
|
|
2040
|
+
|
|
2041
|
+
const templateContext = createTemplateContext({ context, session, history: historyEvents });
|
|
2042
|
+
|
|
2043
|
+
// Build completion response prompt using ResponseEngine
|
|
2044
|
+
// Filter out conditional guidelines - only include always-active ones
|
|
2045
|
+
const alwaysActiveGuidelines = [
|
|
2046
|
+
...this.agent.getGuidelines().filter(g => !g.condition),
|
|
2047
|
+
...selectedRoute.getGuidelines().filter(g => !g.condition),
|
|
2048
|
+
];
|
|
2049
|
+
let completitionPrompt = "Summarize what was accomplished and confirm completion"
|
|
2050
|
+
if(endStepSpec.prompt){
|
|
2051
|
+
completitionPrompt = await render(endStepSpec.prompt, templateContext)
|
|
2052
|
+
}
|
|
1250
2053
|
|
|
1251
|
-
// Build completion response prompt
|
|
1252
2054
|
const completionPrompt = await this.responseEngine.buildResponsePrompt({
|
|
1253
2055
|
route: selectedRoute,
|
|
1254
2056
|
currentStep: completionStep,
|
|
1255
2057
|
rules: selectedRoute.getRules(),
|
|
1256
2058
|
prohibitions: selectedRoute.getProhibitions(),
|
|
1257
|
-
directives:
|
|
1258
|
-
|
|
1259
|
-
|
|
2059
|
+
directives: [
|
|
2060
|
+
`Task completed: ${selectedRoute.title}`,
|
|
2061
|
+
`Collected data: ${JSON.stringify(session.data, null, 2)}`,
|
|
2062
|
+
"Do NOT ask for more information - the task is complete",
|
|
2063
|
+
completitionPrompt,
|
|
2064
|
+
],
|
|
2065
|
+
history: historyEvents,
|
|
2066
|
+
lastMessage: lastMessageText,
|
|
1260
2067
|
agentOptions: this.agent.getAgentOptions(),
|
|
1261
|
-
combinedGuidelines:
|
|
2068
|
+
combinedGuidelines: alwaysActiveGuidelines, // Only non-conditional guidelines
|
|
1262
2069
|
combinedTerms: this.mergeTerms(this.agent.getTerms(), selectedRoute.getTerms()),
|
|
1263
2070
|
context,
|
|
1264
2071
|
session,
|
|
1265
|
-
agentSchema:
|
|
2072
|
+
agentSchema: undefined, // No data collection schema for completion
|
|
1266
2073
|
});
|
|
1267
2074
|
|
|
1268
2075
|
// Generate completion message using AI provider
|
|
1269
2076
|
const agentOptions = this.agent.getAgentOptions();
|
|
2077
|
+
logger.debug(`[ResponseModal] Calling AI provider for completion message...`);
|
|
2078
|
+
|
|
1270
2079
|
const completionResult = await agentOptions.provider.generateMessage({
|
|
1271
2080
|
prompt: completionPrompt,
|
|
1272
|
-
history: historyEvents,
|
|
2081
|
+
history: historyEvents,
|
|
1273
2082
|
context,
|
|
1274
2083
|
signal,
|
|
1275
|
-
parameters: { jsonSchema:
|
|
2084
|
+
parameters: { jsonSchema: completionSchema, schemaName: "completion_message" },
|
|
1276
2085
|
});
|
|
1277
2086
|
|
|
2087
|
+
logger.debug(`[ResponseModal] AI provider returned completion result`);
|
|
1278
2088
|
const message = completionResult.structured?.message || completionResult.message;
|
|
1279
2089
|
logger.debug(`[ResponseModal] Generated completion message for route: ${selectedRoute.title}`);
|
|
1280
2090
|
|
|
@@ -1333,7 +2143,7 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
1333
2143
|
|
|
1334
2144
|
// Build response schema for completion
|
|
1335
2145
|
const responseSchema = this.responseEngine.responseSchemaForRoute(selectedRoute, completionStep, this.agent.getSchema());
|
|
1336
|
-
const templateContext = { context, session, history: historyEvents }; // Use Event[] for template context
|
|
2146
|
+
const templateContext = createTemplateContext({ context, session, history: historyEvents }); // Use Event[] for template context
|
|
1337
2147
|
|
|
1338
2148
|
// Build completion response prompt
|
|
1339
2149
|
const completionPrompt = await this.responseEngine.buildResponsePrompt({
|
|
@@ -1401,6 +2211,10 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
1401
2211
|
await this.finalizeSession(session, context);
|
|
1402
2212
|
}
|
|
1403
2213
|
|
|
2214
|
+
// Response structure completeness (Requirement 8.1, 8.2, 8.3)
|
|
2215
|
+
// - executedSteps: empty for route completion (no new steps executed)
|
|
2216
|
+
// - stoppedReason: 'route_complete' for completed routes
|
|
2217
|
+
// - session.currentStep: set to END_ROUTE
|
|
1404
2218
|
yield {
|
|
1405
2219
|
delta: chunk.delta,
|
|
1406
2220
|
accumulated: chunk.accumulated,
|
|
@@ -1408,6 +2222,8 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
1408
2222
|
session,
|
|
1409
2223
|
toolCalls: undefined,
|
|
1410
2224
|
isRouteComplete: true,
|
|
2225
|
+
executedSteps: chunk.done ? [] : undefined,
|
|
2226
|
+
stoppedReason: chunk.done ? 'route_complete' : undefined,
|
|
1411
2227
|
metadata: chunk.metadata,
|
|
1412
2228
|
structured: chunk.structured,
|
|
1413
2229
|
};
|
|
@@ -1502,6 +2318,10 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
1502
2318
|
await this.finalizeSession(session, context);
|
|
1503
2319
|
}
|
|
1504
2320
|
|
|
2321
|
+
// Response structure completeness (Requirement 8.1, 8.2, 8.3)
|
|
2322
|
+
// - executedSteps: empty for fallback (no route/step execution)
|
|
2323
|
+
// - stoppedReason: undefined for fallback (no route context)
|
|
2324
|
+
// - session.currentStep: unchanged (no step progression)
|
|
1505
2325
|
yield {
|
|
1506
2326
|
delta: chunk.delta,
|
|
1507
2327
|
accumulated: chunk.accumulated,
|
|
@@ -1509,6 +2329,8 @@ export class ResponseModal<TContext = unknown, TData = unknown> {
|
|
|
1509
2329
|
session,
|
|
1510
2330
|
toolCalls: undefined,
|
|
1511
2331
|
isRouteComplete: false,
|
|
2332
|
+
executedSteps: chunk.done ? [] : undefined,
|
|
2333
|
+
stoppedReason: undefined,
|
|
1512
2334
|
metadata: chunk.metadata,
|
|
1513
2335
|
structured: chunk.structured,
|
|
1514
2336
|
};
|