@falai/agent 0.9.2 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +281 -42
- 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 +16 -1
- package/dist/cjs/core/Agent.d.ts.map +1 -0
- package/dist/cjs/{src/core → core}/Agent.js +63 -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 +850 -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 +217 -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 +211 -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 +752 -74
- 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 +15 -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 +16 -1
- package/dist/core/Agent.d.ts.map +1 -0
- package/dist/{src/core → core}/Agent.js +64 -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 +845 -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 +213 -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 +207 -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 +752 -74
- 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 +15 -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/README.md +1 -0
- package/docs/api/README.md +237 -12
- package/docs/api/overview.md +206 -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 +156 -5
- package/docs/core/agent/rules-and-prohibitions.md +113 -0
- 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 +27 -0
- package/docs/guides/migration/flexible-routing-conditions.md +375 -0
- package/docs/guides/migration/multi-step-execution.md +373 -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 +78 -2
- package/src/core/BatchExecutor.ts +1166 -0
- package/src/core/BatchPromptBuilder.ts +293 -0
- package/src/core/PromptComposer.ts +53 -16
- package/src/core/ResponseEngine.ts +168 -29
- package/src/core/ResponseModal.ts +954 -74
- 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 +15 -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
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { enterRoute, mergeCollected } from "../utils";
|
|
2
2
|
import { PromptComposer } from "./PromptComposer";
|
|
3
|
-
import { getLastMessageFromHistory } from "../utils/event";
|
|
4
|
-
import { logger } from "../utils/logger";
|
|
5
|
-
import { render } from "../utils/template";
|
|
6
3
|
import { END_ROUTE_ID } from "../constants";
|
|
4
|
+
import { createTemplateContext, getLastMessageFromHistory, logger } from "../utils";
|
|
7
5
|
export class RoutingEngine {
|
|
8
6
|
constructor(options) {
|
|
9
7
|
this.options = options;
|
|
@@ -36,21 +34,26 @@ export class RoutingEngine {
|
|
|
36
34
|
const updatedSession = this.enterRouteIfNeeded(session, route);
|
|
37
35
|
// Check if this single route is complete (use updated session data)
|
|
38
36
|
const completedRoutes = route.isComplete(updatedSession.data || {}) ? [route] : [];
|
|
39
|
-
// Get candidate steps
|
|
37
|
+
// Get candidate steps using new condition evaluation
|
|
38
|
+
const templateContext = createTemplateContext({
|
|
39
|
+
context,
|
|
40
|
+
session: updatedSession,
|
|
41
|
+
history,
|
|
42
|
+
data: updatedSession.data
|
|
43
|
+
});
|
|
40
44
|
const currentStep = updatedSession.currentStep
|
|
41
45
|
? route.getStep(updatedSession.currentStep.id)
|
|
42
46
|
: undefined;
|
|
43
|
-
const candidates = this.
|
|
47
|
+
const candidates = await this.getCandidateStepsWithConditions(route, currentStep, templateContext);
|
|
44
48
|
if (candidates.length === 0) {
|
|
45
49
|
logger.warn(`[RoutingEngine] Single-route: No valid steps found`);
|
|
46
50
|
return { selectedRoute, session: updatedSession };
|
|
47
51
|
}
|
|
48
|
-
// If only one candidate,
|
|
52
|
+
// If only one candidate, check if it's a completion marker
|
|
49
53
|
if (candidates.length === 1) {
|
|
50
54
|
const candidate = candidates[0];
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
logger.debug(`[RoutingEngine] Single-route: Route complete - all data collected, END_ROUTE reached`);
|
|
55
|
+
if (candidate.isRouteComplete) {
|
|
56
|
+
logger.debug(`[RoutingEngine] Single-route: Route complete - all required fields collected or END_ROUTE reached`);
|
|
54
57
|
// Don't return a selectedStep when route is complete - there's no step to enter
|
|
55
58
|
return {
|
|
56
59
|
selectedRoute,
|
|
@@ -73,17 +76,27 @@ export class RoutingEngine {
|
|
|
73
76
|
}
|
|
74
77
|
// No candidates means route is likely complete or has no valid next steps
|
|
75
78
|
if (candidates.length === 0) {
|
|
76
|
-
|
|
79
|
+
const dataComplete = route.isComplete(updatedSession.data || {});
|
|
80
|
+
logger.debug(`[RoutingEngine] Single-route: No valid steps found - ` +
|
|
81
|
+
`(data: ${dataComplete ? 'complete' : 'incomplete'}, marking as ${dataComplete ? 'complete' : 'incomplete'})`);
|
|
77
82
|
return {
|
|
78
83
|
selectedRoute,
|
|
79
84
|
selectedStep: undefined,
|
|
80
85
|
session: updatedSession,
|
|
81
|
-
isRouteComplete:
|
|
86
|
+
isRouteComplete: dataComplete,
|
|
82
87
|
completedRoutes,
|
|
83
88
|
};
|
|
84
89
|
}
|
|
85
90
|
// Multiple candidates - use AI to select best step
|
|
86
91
|
const lastUserMessage = getLastMessageFromHistory(history);
|
|
92
|
+
// Collect AI context strings from step conditions
|
|
93
|
+
const stepConditionContext = [];
|
|
94
|
+
for (const candidate of candidates) {
|
|
95
|
+
const whenResult = await candidate.step.evaluateWhen(templateContext);
|
|
96
|
+
stepConditionContext.push(...whenResult.aiContextStrings);
|
|
97
|
+
}
|
|
98
|
+
// Check if any candidate is a completion marker (isRouteComplete = true)
|
|
99
|
+
const hasCompletionOption = candidates.some(c => c.isRouteComplete);
|
|
87
100
|
const stepPrompt = await this.buildStepSelectionPrompt({
|
|
88
101
|
route,
|
|
89
102
|
currentStep,
|
|
@@ -94,8 +107,10 @@ export class RoutingEngine {
|
|
|
94
107
|
agentOptions,
|
|
95
108
|
context,
|
|
96
109
|
session: updatedSession,
|
|
110
|
+
stepConditionContext,
|
|
111
|
+
includeEndRoute: hasCompletionOption,
|
|
97
112
|
});
|
|
98
|
-
const stepSchema = this.buildStepSelectionSchema(candidates.map((c) => c.step));
|
|
113
|
+
const stepSchema = this.buildStepSelectionSchema(candidates.filter(c => !c.isRouteComplete).map((c) => c.step), hasCompletionOption);
|
|
99
114
|
const stepResult = await provider.generateMessage({
|
|
100
115
|
prompt: stepPrompt,
|
|
101
116
|
history,
|
|
@@ -107,6 +122,19 @@ export class RoutingEngine {
|
|
|
107
122
|
},
|
|
108
123
|
});
|
|
109
124
|
const selectedStepId = stepResult.structured?.selectedStepId;
|
|
125
|
+
// Check if AI selected END_ROUTE
|
|
126
|
+
if (selectedStepId === END_ROUTE_ID) {
|
|
127
|
+
logger.debug(`[RoutingEngine] Single-route: AI selected END_ROUTE - completing route`);
|
|
128
|
+
logger.debug(`[RoutingEngine] Single-route: Reasoning: ${stepResult.structured?.reasoning}`);
|
|
129
|
+
return {
|
|
130
|
+
selectedRoute,
|
|
131
|
+
selectedStep: undefined,
|
|
132
|
+
responseDirectives: stepResult.structured?.responseDirectives,
|
|
133
|
+
session: updatedSession,
|
|
134
|
+
isRouteComplete: true,
|
|
135
|
+
completedRoutes,
|
|
136
|
+
};
|
|
137
|
+
}
|
|
110
138
|
const selectedStep = candidates.find((c) => c.step.id === selectedStepId);
|
|
111
139
|
if (selectedStep) {
|
|
112
140
|
logger.debug(`[RoutingEngine] Single-route: AI selected step: ${selectedStep.step.id}`);
|
|
@@ -124,16 +152,17 @@ export class RoutingEngine {
|
|
|
124
152
|
};
|
|
125
153
|
}
|
|
126
154
|
/**
|
|
127
|
-
* Recursively traverse step chain to find first non-skipped step or END_ROUTE
|
|
155
|
+
* Recursively traverse step chain to find first non-skipped step or END_ROUTE using new condition evaluation
|
|
128
156
|
* @private
|
|
129
157
|
*/
|
|
130
|
-
|
|
158
|
+
async findFirstValidStepRecursiveWithConditions(currentStep, templateContext, visited) {
|
|
131
159
|
// Prevent infinite loops
|
|
132
160
|
if (visited.has(currentStep.id)) {
|
|
133
|
-
return {};
|
|
161
|
+
return { aiContextStrings: [] };
|
|
134
162
|
}
|
|
135
163
|
visited.add(currentStep.id);
|
|
136
164
|
const transitions = currentStep.getTransitions();
|
|
165
|
+
const allAiContextStrings = [];
|
|
137
166
|
for (const transition of transitions) {
|
|
138
167
|
const target = transition;
|
|
139
168
|
// Check for END_ROUTE transition
|
|
@@ -141,40 +170,69 @@ export class RoutingEngine {
|
|
|
141
170
|
// Found END_ROUTE - route is complete
|
|
142
171
|
return {
|
|
143
172
|
isRouteComplete: true,
|
|
173
|
+
aiContextStrings: allAiContextStrings,
|
|
144
174
|
};
|
|
145
175
|
}
|
|
146
176
|
if (!target)
|
|
147
177
|
continue;
|
|
178
|
+
// Evaluate skipIf condition using new system
|
|
179
|
+
const skipResult = await target.evaluateSkipIf(templateContext);
|
|
180
|
+
allAiContextStrings.push(...skipResult.aiContextStrings);
|
|
148
181
|
// If target should NOT be skipped, we found our step
|
|
149
|
-
if (!
|
|
182
|
+
if (!skipResult.shouldSkip) {
|
|
150
183
|
logger.debug(`[RoutingEngine] Found valid step after skipping: ${target.id}`);
|
|
151
184
|
return {
|
|
152
185
|
step: target,
|
|
153
186
|
isRouteComplete: false,
|
|
187
|
+
aiContextStrings: allAiContextStrings,
|
|
154
188
|
};
|
|
155
189
|
}
|
|
156
190
|
// Target should be skipped too - recurse deeper
|
|
157
191
|
logger.debug(`[RoutingEngine] Skipping step ${target.id} (skipIf condition met), continuing traversal...`);
|
|
158
|
-
const result = this.
|
|
192
|
+
const result = await this.findFirstValidStepRecursiveWithConditions(target, templateContext, visited);
|
|
193
|
+
// Collect AI context from recursive call
|
|
194
|
+
if (result.aiContextStrings) {
|
|
195
|
+
allAiContextStrings.push(...result.aiContextStrings);
|
|
196
|
+
}
|
|
159
197
|
// If we found something (a valid step or END_ROUTE), return it
|
|
160
198
|
if (result.step || result.isRouteComplete) {
|
|
161
|
-
return
|
|
199
|
+
return {
|
|
200
|
+
...result,
|
|
201
|
+
aiContextStrings: allAiContextStrings,
|
|
202
|
+
};
|
|
162
203
|
}
|
|
163
204
|
}
|
|
164
205
|
// No valid steps or END_ROUTE found in this branch
|
|
165
|
-
return {};
|
|
206
|
+
return { aiContextStrings: allAiContextStrings };
|
|
166
207
|
}
|
|
167
208
|
/**
|
|
168
|
-
* Identify valid next candidate steps
|
|
209
|
+
* Identify valid next candidate steps using new condition evaluation system
|
|
169
210
|
* Returns step with isRouteComplete flag if route is complete (all steps skipped + has END_ROUTE transition)
|
|
211
|
+
*
|
|
212
|
+
* NEW: Automatically completes route when all required fields are collected
|
|
170
213
|
*/
|
|
171
|
-
|
|
214
|
+
async getCandidateStepsWithConditions(route, currentStep, templateContext) {
|
|
172
215
|
const candidates = [];
|
|
216
|
+
const data = templateContext.data || {};
|
|
217
|
+
// Check if all required fields are collected
|
|
218
|
+
const allRequiredFieldsCollected = route.isComplete(data);
|
|
173
219
|
if (!currentStep) {
|
|
220
|
+
// Entering route for the first time
|
|
221
|
+
// If all required fields already collected, route is immediately complete
|
|
222
|
+
if (allRequiredFieldsCollected) {
|
|
223
|
+
logger.debug(`[RoutingEngine] Route ${route.title} complete on entry: all required fields already collected`);
|
|
224
|
+
// Return a completion marker - use initial step with completion flag
|
|
225
|
+
candidates.push({
|
|
226
|
+
step: route.initialStep,
|
|
227
|
+
isRouteComplete: true,
|
|
228
|
+
});
|
|
229
|
+
return candidates;
|
|
230
|
+
}
|
|
174
231
|
const initialStep = route.initialStep;
|
|
175
|
-
|
|
232
|
+
const skipResult = await initialStep.evaluateSkipIf(templateContext);
|
|
233
|
+
if (skipResult.shouldSkip) {
|
|
176
234
|
// Initial step should be skipped - recursively traverse to find first non-skipped step or END_ROUTE
|
|
177
|
-
const result = this.
|
|
235
|
+
const result = await this.findFirstValidStepRecursiveWithConditions(initialStep, templateContext, new Set());
|
|
178
236
|
if (result.isRouteComplete) {
|
|
179
237
|
// All steps are skipped and we reached END_ROUTE
|
|
180
238
|
logger.debug(`[RoutingEngine] Route complete on entry: all steps skipped, END_ROUTE reached`);
|
|
@@ -200,6 +258,55 @@ export class RoutingEngine {
|
|
|
200
258
|
}
|
|
201
259
|
return candidates;
|
|
202
260
|
}
|
|
261
|
+
// Check if all required fields are now collected (may have been collected during this step)
|
|
262
|
+
if (allRequiredFieldsCollected) {
|
|
263
|
+
// Required fields are complete - check if we should continue for optional fields
|
|
264
|
+
const transitions = currentStep.getTransitions();
|
|
265
|
+
const optionalFieldCandidates = [];
|
|
266
|
+
for (const transition of transitions) {
|
|
267
|
+
const target = transition;
|
|
268
|
+
// Check for END_ROUTE transition
|
|
269
|
+
if (target && target.id === END_ROUTE_ID) {
|
|
270
|
+
continue;
|
|
271
|
+
}
|
|
272
|
+
if (!target)
|
|
273
|
+
continue;
|
|
274
|
+
// Check if this step collects only optional fields
|
|
275
|
+
const collectsOnlyOptional = target.collect && target.collect.length > 0 &&
|
|
276
|
+
target.collect.every(field => route.optionalFields?.includes(field));
|
|
277
|
+
if (collectsOnlyOptional) {
|
|
278
|
+
// This step collects optional fields - it's a candidate
|
|
279
|
+
const skipResult = await target.evaluateSkipIf(templateContext);
|
|
280
|
+
if (!skipResult.shouldSkip) {
|
|
281
|
+
optionalFieldCandidates.push({
|
|
282
|
+
step: target,
|
|
283
|
+
isRouteComplete: false,
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
// If we have optional field candidates, include them along with END_ROUTE option
|
|
289
|
+
if (optionalFieldCandidates.length > 0) {
|
|
290
|
+
logger.debug(`[RoutingEngine] Required fields complete, but ${optionalFieldCandidates.length} optional field steps available`);
|
|
291
|
+
// Add optional field steps as candidates
|
|
292
|
+
candidates.push(...optionalFieldCandidates);
|
|
293
|
+
// Also add END_ROUTE as a candidate (AI can choose to skip optional fields)
|
|
294
|
+
candidates.push({
|
|
295
|
+
step: currentStep,
|
|
296
|
+
isRouteComplete: true,
|
|
297
|
+
});
|
|
298
|
+
return candidates;
|
|
299
|
+
}
|
|
300
|
+
// No optional fields to collect - route is complete
|
|
301
|
+
logger.debug(`[RoutingEngine] Route ${route.title} complete: all required fields collected, no optional fields remain`);
|
|
302
|
+
return [
|
|
303
|
+
{
|
|
304
|
+
step: currentStep,
|
|
305
|
+
isRouteComplete: true,
|
|
306
|
+
},
|
|
307
|
+
];
|
|
308
|
+
}
|
|
309
|
+
// Required fields not yet complete - continue normal step progression
|
|
203
310
|
const transitions = currentStep.getTransitions();
|
|
204
311
|
let hasEndRoute = false;
|
|
205
312
|
for (const transition of transitions) {
|
|
@@ -211,10 +318,11 @@ export class RoutingEngine {
|
|
|
211
318
|
}
|
|
212
319
|
if (!target)
|
|
213
320
|
continue;
|
|
214
|
-
|
|
321
|
+
const skipResult = await target.evaluateSkipIf(templateContext);
|
|
322
|
+
if (skipResult.shouldSkip) {
|
|
215
323
|
logger.debug(`[RoutingEngine] Skipping step ${target.id} (skipIf condition met)`);
|
|
216
324
|
// Recursively traverse to find next valid step or END_ROUTE
|
|
217
|
-
const result = this.
|
|
325
|
+
const result = await this.findFirstValidStepRecursiveWithConditions(target, templateContext, new Set([currentStep.id]) // Already visited current step
|
|
218
326
|
);
|
|
219
327
|
if (result.isRouteComplete) {
|
|
220
328
|
hasEndRoute = true;
|
|
@@ -247,7 +355,8 @@ export class RoutingEngine {
|
|
|
247
355
|
];
|
|
248
356
|
}
|
|
249
357
|
// Otherwise, stay in current step if it's still valid
|
|
250
|
-
|
|
358
|
+
const currentSkipResult = await currentStep.evaluateSkipIf(templateContext);
|
|
359
|
+
if (!currentSkipResult.shouldSkip) {
|
|
251
360
|
candidates.push({
|
|
252
361
|
step: currentStep,
|
|
253
362
|
isRouteComplete: hasEndRoute || false,
|
|
@@ -291,38 +400,69 @@ export class RoutingEngine {
|
|
|
291
400
|
};
|
|
292
401
|
}
|
|
293
402
|
const lastUserMessage = getLastMessageFromHistory(history);
|
|
403
|
+
const templateContext = createTemplateContext({
|
|
404
|
+
context,
|
|
405
|
+
session,
|
|
406
|
+
history,
|
|
407
|
+
data: session.data
|
|
408
|
+
});
|
|
409
|
+
// Apply route filtering with new condition evaluation system
|
|
410
|
+
const skipIfResult = await this.filterRoutesBySkipIf(routes, templateContext);
|
|
411
|
+
const whenResult = await this.filterRoutesByWhen(skipIfResult.eligibleRoutes, templateContext);
|
|
412
|
+
// Collect all AI context strings from route conditions
|
|
413
|
+
const routeConditionContext = [...skipIfResult.aiContextStrings, ...whenResult.aiContextStrings];
|
|
414
|
+
// Use filtered routes for further processing
|
|
415
|
+
const eligibleRoutes = whenResult.eligibleRoutes;
|
|
416
|
+
logger.debug(`[RoutingEngine] Route filtering: ${routes.length} total → ${skipIfResult.eligibleRoutes.length} after skipIf → ${eligibleRoutes.length} after when`);
|
|
294
417
|
let activeRouteSteps;
|
|
295
418
|
let activeRoute;
|
|
296
419
|
let isRouteComplete = false;
|
|
420
|
+
let updatedSession = session;
|
|
297
421
|
if (session.currentRoute) {
|
|
298
|
-
activeRoute =
|
|
422
|
+
activeRoute = eligibleRoutes.find((r) => r.id === session.currentRoute?.id);
|
|
299
423
|
if (activeRoute) {
|
|
300
424
|
const currentStep = session.currentStep
|
|
301
425
|
? activeRoute.getStep(session.currentStep.id)
|
|
302
426
|
: undefined;
|
|
303
|
-
const
|
|
427
|
+
const activeTemplateContext = createTemplateContext({
|
|
428
|
+
...templateContext,
|
|
429
|
+
session: updatedSession,
|
|
430
|
+
data: updatedSession.data
|
|
431
|
+
});
|
|
432
|
+
const candidates = await this.getCandidateStepsWithConditions(activeRoute, currentStep, activeTemplateContext);
|
|
304
433
|
// Check if route is complete
|
|
434
|
+
// getCandidateStepsWithConditions now automatically handles completion when required fields are collected
|
|
305
435
|
if (candidates.length === 1 && candidates[0].isRouteComplete) {
|
|
306
436
|
isRouteComplete = true;
|
|
307
|
-
logger.debug(`[RoutingEngine] Route ${activeRoute.title} is complete - all
|
|
437
|
+
logger.debug(`[RoutingEngine] Route ${activeRoute.title} is complete - all required fields collected or END_ROUTE reached`);
|
|
308
438
|
// Don't include steps in routing if route is complete
|
|
309
439
|
activeRouteSteps = undefined;
|
|
310
440
|
}
|
|
441
|
+
else if (candidates.length === 0) {
|
|
442
|
+
// No candidates - check if data is complete
|
|
443
|
+
const dataComplete = activeRoute.isComplete(updatedSession.data || {});
|
|
444
|
+
isRouteComplete = dataComplete;
|
|
445
|
+
logger.debug(`[RoutingEngine] Route ${activeRoute.title} has no valid steps - ` +
|
|
446
|
+
`marking as ${isRouteComplete ? 'complete' : 'incomplete'}`);
|
|
447
|
+
activeRouteSteps = undefined;
|
|
448
|
+
}
|
|
311
449
|
else {
|
|
450
|
+
// Multiple candidates or single non-complete candidate
|
|
312
451
|
activeRouteSteps = candidates.map((c) => c.step);
|
|
313
452
|
logger.debug(`[RoutingEngine] Found ${activeRouteSteps.length} candidate steps for active route`);
|
|
314
453
|
}
|
|
315
454
|
}
|
|
316
455
|
}
|
|
317
|
-
const routingSchema = this.buildDynamicRoutingSchema(
|
|
456
|
+
const routingSchema = this.buildDynamicRoutingSchema(eligibleRoutes, undefined, activeRouteSteps);
|
|
318
457
|
const routingPrompt = await this.buildRoutingPrompt({
|
|
319
458
|
history,
|
|
320
|
-
routes,
|
|
459
|
+
routes: eligibleRoutes,
|
|
321
460
|
lastMessage: lastUserMessage,
|
|
322
461
|
agentOptions,
|
|
323
462
|
session,
|
|
324
463
|
activeRouteSteps,
|
|
325
464
|
context,
|
|
465
|
+
routeConditionContext, // Pass AI context strings from route conditions
|
|
326
466
|
});
|
|
327
467
|
const routingResult = await provider.generateMessage({
|
|
328
468
|
prompt: routingPrompt,
|
|
@@ -337,19 +477,26 @@ export class RoutingEngine {
|
|
|
337
477
|
let selectedRoute;
|
|
338
478
|
let selectedStep;
|
|
339
479
|
let responseDirectives;
|
|
340
|
-
let updatedSession = session;
|
|
341
480
|
if (routingResult.structured?.routes) {
|
|
342
481
|
// Use cross-route completion evaluation to select optimal route
|
|
343
|
-
const optimalRoute = this.selectOptimalRoute(
|
|
344
|
-
//
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
routes
|
|
349
|
-
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
|
|
482
|
+
const optimalRoute = this.selectOptimalRoute(eligibleRoutes, updatedSession.data || {}, routingResult.structured.routes);
|
|
483
|
+
// If no optimal route found, check why
|
|
484
|
+
if (!optimalRoute) {
|
|
485
|
+
if (eligibleRoutes.length === 0) {
|
|
486
|
+
// No routes passed filtering
|
|
487
|
+
logger.debug(`[RoutingEngine] No eligible routes available - all routes filtered out`);
|
|
488
|
+
selectedRoute = undefined;
|
|
489
|
+
}
|
|
490
|
+
else {
|
|
491
|
+
// Routes exist but selectOptimalRoute returned undefined
|
|
492
|
+
// This means all routes are 100% complete
|
|
493
|
+
logger.debug(`[RoutingEngine] No optimal route found - all ${eligibleRoutes.length} eligible routes are complete`);
|
|
494
|
+
selectedRoute = undefined;
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
else {
|
|
498
|
+
selectedRoute = optimalRoute;
|
|
499
|
+
}
|
|
353
500
|
responseDirectives = routingResult.structured.responseDirectives;
|
|
354
501
|
if (selectedRoute === activeRoute &&
|
|
355
502
|
routingResult.structured.selectedStepId &&
|
|
@@ -374,6 +521,52 @@ export class RoutingEngine {
|
|
|
374
521
|
completedRoutes,
|
|
375
522
|
};
|
|
376
523
|
}
|
|
524
|
+
/**
|
|
525
|
+
* Filter routes based on skipIf conditions
|
|
526
|
+
* @param routes - All available routes
|
|
527
|
+
* @param templateContext - Context for condition evaluation
|
|
528
|
+
* @returns Object with eligible routes and collected AI context strings
|
|
529
|
+
*/
|
|
530
|
+
async filterRoutesBySkipIf(routes, templateContext) {
|
|
531
|
+
const eligibleRoutes = [];
|
|
532
|
+
const aiContextStrings = [];
|
|
533
|
+
for (const route of routes) {
|
|
534
|
+
const skipResult = await route.evaluateSkipIf(templateContext);
|
|
535
|
+
// Collect AI context strings from skipIf conditions
|
|
536
|
+
aiContextStrings.push(...skipResult.aiContextStrings);
|
|
537
|
+
// If route should not be skipped, it's eligible
|
|
538
|
+
if (!skipResult.programmaticResult) {
|
|
539
|
+
eligibleRoutes.push(route);
|
|
540
|
+
}
|
|
541
|
+
else {
|
|
542
|
+
logger.debug(`[RoutingEngine] Skipping route ${route.title} (skipIf condition met)`);
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
return { eligibleRoutes, aiContextStrings };
|
|
546
|
+
}
|
|
547
|
+
/**
|
|
548
|
+
* Filter routes based on when conditions
|
|
549
|
+
* @param routes - Routes that passed skipIf filtering
|
|
550
|
+
* @param templateContext - Context for condition evaluation
|
|
551
|
+
* @returns Object with eligible routes and collected AI context strings
|
|
552
|
+
*/
|
|
553
|
+
async filterRoutesByWhen(routes, templateContext) {
|
|
554
|
+
const eligibleRoutes = [];
|
|
555
|
+
const aiContextStrings = [];
|
|
556
|
+
for (const route of routes) {
|
|
557
|
+
const whenResult = await route.evaluateWhen(templateContext);
|
|
558
|
+
// Collect AI context strings from when conditions
|
|
559
|
+
aiContextStrings.push(...whenResult.aiContextStrings);
|
|
560
|
+
// If route has no programmatic conditions or they evaluate to true, it's eligible
|
|
561
|
+
if (!whenResult.hasProgrammaticConditions || whenResult.programmaticResult) {
|
|
562
|
+
eligibleRoutes.push(route);
|
|
563
|
+
}
|
|
564
|
+
else {
|
|
565
|
+
logger.debug(`[RoutingEngine] Route ${route.title} not eligible (when condition not met)`);
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
return { eligibleRoutes, aiContextStrings };
|
|
569
|
+
}
|
|
377
570
|
/**
|
|
378
571
|
* Evaluate all routes for completion based on collected data
|
|
379
572
|
* @param routes - All available routes
|
|
@@ -400,6 +593,7 @@ export class RoutingEngine {
|
|
|
400
593
|
/**
|
|
401
594
|
* Find the best route to continue based on completion status and user intent
|
|
402
595
|
* Prioritizes routes that are partially complete but not finished
|
|
596
|
+
* IMPORTANT: Completed routes are excluded to prevent re-entering finished tasks
|
|
403
597
|
* @param routes - All available routes
|
|
404
598
|
* @param data - Currently collected agent-level data
|
|
405
599
|
* @param routeScores - AI-generated route scores from routing decision
|
|
@@ -412,8 +606,10 @@ export class RoutingEngine {
|
|
|
412
606
|
for (const route of routes) {
|
|
413
607
|
const aiScore = routeScores[route.id] || 0;
|
|
414
608
|
const completionProgress = completionStatus.get(route.id) || 0;
|
|
415
|
-
//
|
|
416
|
-
|
|
609
|
+
// ALWAYS skip fully completed routes to prevent re-entering finished tasks
|
|
610
|
+
// Users should not be forced back into completed routes
|
|
611
|
+
if (completionProgress >= 1.0) {
|
|
612
|
+
logger.debug(`[RoutingEngine] Excluding completed route: ${route.title} (100% complete)`);
|
|
417
613
|
continue;
|
|
418
614
|
}
|
|
419
615
|
// Boost partially complete routes that match user intent
|
|
@@ -440,8 +636,8 @@ export class RoutingEngine {
|
|
|
440
636
|
* @private
|
|
441
637
|
*/
|
|
442
638
|
async buildStepSelectionPrompt(params) {
|
|
443
|
-
const { route, currentStep, candidates, data, history, lastMessage, agentOptions, context, session, } = params;
|
|
444
|
-
const templateContext = { context, session, history };
|
|
639
|
+
const { route, currentStep, candidates, data, history, lastMessage, agentOptions, context, session, stepConditionContext, includeEndRoute = false, } = params;
|
|
640
|
+
const templateContext = createTemplateContext({ context, session, history });
|
|
445
641
|
const pc = new PromptComposer(templateContext);
|
|
446
642
|
// Add agent metadata
|
|
447
643
|
if (agentOptions) {
|
|
@@ -466,7 +662,7 @@ export class RoutingEngine {
|
|
|
466
662
|
// Add conversation history
|
|
467
663
|
await pc.addInteractionHistory(history);
|
|
468
664
|
await pc.addLastMessage(lastMessage);
|
|
469
|
-
// Add candidate steps
|
|
665
|
+
// Add candidate steps with condition context
|
|
470
666
|
const stepDescriptions = [];
|
|
471
667
|
for (const candidate of candidates) {
|
|
472
668
|
const idx = candidates.indexOf(candidate);
|
|
@@ -474,9 +670,15 @@ export class RoutingEngine {
|
|
|
474
670
|
`${idx + 1}. Step ID: ${candidate.step.id}`,
|
|
475
671
|
` Description: ${candidate.step.description || "N/A"}`,
|
|
476
672
|
];
|
|
673
|
+
// Add when condition context
|
|
477
674
|
if (candidate.step.when) {
|
|
478
|
-
const
|
|
479
|
-
|
|
675
|
+
const whenResult = await candidate.step.evaluateWhen(templateContext);
|
|
676
|
+
if (whenResult.aiContextStrings.length > 0) {
|
|
677
|
+
parts.push(` When conditions: ${whenResult.aiContextStrings.join(", ")}`);
|
|
678
|
+
}
|
|
679
|
+
else if (typeof candidate.step.when === 'string') {
|
|
680
|
+
parts.push(` When this step should be completed: ${candidate.step.when}`);
|
|
681
|
+
}
|
|
480
682
|
}
|
|
481
683
|
if (candidate.step.requires && candidate.step.requires.length > 0) {
|
|
482
684
|
parts.push(` Required Data: ${candidate.step.requires.join(", ")}`);
|
|
@@ -487,8 +689,18 @@ export class RoutingEngine {
|
|
|
487
689
|
stepDescriptions.push(parts.join("\n"));
|
|
488
690
|
}
|
|
489
691
|
await pc.addInstruction(`Available Steps to Transition To:\n${stepDescriptions.join("\n\n")}`);
|
|
692
|
+
// Add step condition context if available
|
|
693
|
+
if (stepConditionContext && stepConditionContext.length > 0) {
|
|
694
|
+
await pc.addInstruction([
|
|
695
|
+
"",
|
|
696
|
+
"Additional step context from conditions:",
|
|
697
|
+
...stepConditionContext.map(ctx => `- ${ctx}`),
|
|
698
|
+
"",
|
|
699
|
+
"Consider this context when selecting the most appropriate step.",
|
|
700
|
+
].join("\n"));
|
|
701
|
+
}
|
|
490
702
|
// Add decision prompt
|
|
491
|
-
|
|
703
|
+
const decisionRules = [
|
|
492
704
|
"Task: Decide which step to transition to based on:",
|
|
493
705
|
"1. The user's current message and intent",
|
|
494
706
|
"2. The conversation history and context",
|
|
@@ -501,16 +713,24 @@ export class RoutingEngine {
|
|
|
501
713
|
"- If a step requires data we don't have, consider if we should collect it now",
|
|
502
714
|
"- Choose the step that makes the most sense for moving the conversation forward",
|
|
503
715
|
"- Steps with skipIf conditions that are met have already been filtered out",
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
716
|
+
];
|
|
717
|
+
if (includeEndRoute) {
|
|
718
|
+
decisionRules.push("", `- You can select '${END_ROUTE_ID}' to complete this route if:`, " * All required data has been collected", " * The user's intent suggests they're done with this task", " * No further steps are needed to fulfill the user's request");
|
|
719
|
+
}
|
|
720
|
+
decisionRules.push("", "Return ONLY JSON matching the provided schema.");
|
|
721
|
+
await pc.addInstruction(decisionRules.join("\n"));
|
|
507
722
|
return pc.build();
|
|
508
723
|
}
|
|
509
724
|
/**
|
|
510
725
|
* Build schema for step selection
|
|
511
726
|
* @private
|
|
512
727
|
*/
|
|
513
|
-
buildStepSelectionSchema(validSteps) {
|
|
728
|
+
buildStepSelectionSchema(validSteps, includeEndRoute = false) {
|
|
729
|
+
const stepIds = validSteps.map((s) => s.id);
|
|
730
|
+
// Add END_ROUTE as an option if requested (when required fields are complete)
|
|
731
|
+
if (includeEndRoute) {
|
|
732
|
+
stepIds.push(END_ROUTE_ID);
|
|
733
|
+
}
|
|
514
734
|
return {
|
|
515
735
|
description: "Step transition decision based on conversation context and collected data",
|
|
516
736
|
type: "object",
|
|
@@ -523,8 +743,10 @@ export class RoutingEngine {
|
|
|
523
743
|
selectedStepId: {
|
|
524
744
|
type: "string",
|
|
525
745
|
nullable: false,
|
|
526
|
-
description:
|
|
527
|
-
|
|
746
|
+
description: includeEndRoute
|
|
747
|
+
? `The ID of the selected step to transition to, or '${END_ROUTE_ID}' to complete the route`
|
|
748
|
+
: "The ID of the selected step to transition to",
|
|
749
|
+
enum: stepIds,
|
|
528
750
|
},
|
|
529
751
|
responseDirectives: {
|
|
530
752
|
type: "array",
|
|
@@ -600,8 +822,8 @@ export class RoutingEngine {
|
|
|
600
822
|
return base;
|
|
601
823
|
}
|
|
602
824
|
async buildRoutingPrompt(params) {
|
|
603
|
-
const { history, routes, lastMessage, agentOptions, session, activeRouteSteps, context, } = params;
|
|
604
|
-
const templateContext = { context, session, history };
|
|
825
|
+
const { history, routes, lastMessage, agentOptions, session, activeRouteSteps, context, routeConditionContext, } = params;
|
|
826
|
+
const templateContext = createTemplateContext({ context, session, history });
|
|
605
827
|
const pc = new PromptComposer(templateContext);
|
|
606
828
|
if (agentOptions) {
|
|
607
829
|
await pc.addAgentMeta(agentOptions);
|
|
@@ -653,15 +875,23 @@ export class RoutingEngine {
|
|
|
653
875
|
"",
|
|
654
876
|
"Available steps in active route (choose one to transition to):",
|
|
655
877
|
];
|
|
878
|
+
const activeStepConditionContext = [];
|
|
656
879
|
for (const step of activeRouteSteps) {
|
|
657
880
|
const idx = activeRouteSteps.indexOf(step);
|
|
658
881
|
stepInfo.push(`${idx + 1}. Step: ${step.id}`);
|
|
659
882
|
if (step.description) {
|
|
660
883
|
stepInfo.push(` Description: ${step.description}`);
|
|
661
884
|
}
|
|
662
|
-
|
|
885
|
+
// Collect AI context from step conditions
|
|
663
886
|
if (step.when) {
|
|
664
|
-
|
|
887
|
+
const whenResult = await step.evaluateWhen(templateContext);
|
|
888
|
+
if (whenResult.aiContextStrings.length > 0) {
|
|
889
|
+
stepInfo.push(` When conditions: ${whenResult.aiContextStrings.join(", ")}`);
|
|
890
|
+
activeStepConditionContext.push(...whenResult.aiContextStrings);
|
|
891
|
+
}
|
|
892
|
+
else if (typeof step.when === 'string') {
|
|
893
|
+
stepInfo.push(` When this step should be completed: ${step.when}`);
|
|
894
|
+
}
|
|
665
895
|
}
|
|
666
896
|
if (step.requires && step.requires.length > 0) {
|
|
667
897
|
stepInfo.push(` Required data: ${step.requires.join(", ")}`);
|
|
@@ -677,11 +907,31 @@ export class RoutingEngine {
|
|
|
677
907
|
stepInfo.push("- The logical next step in the conversation");
|
|
678
908
|
stepInfo.push("- Whether conditions for steps are met");
|
|
679
909
|
await pc.addInstruction(stepInfo.join("\n"));
|
|
910
|
+
// Add active step condition context if available
|
|
911
|
+
if (activeStepConditionContext.length > 0) {
|
|
912
|
+
await pc.addInstruction([
|
|
913
|
+
"",
|
|
914
|
+
"Additional context from step conditions:",
|
|
915
|
+
...activeStepConditionContext.map(ctx => `- ${ctx}`),
|
|
916
|
+
"",
|
|
917
|
+
"Use this context to inform your step selection decision.",
|
|
918
|
+
].join("\n"));
|
|
919
|
+
}
|
|
680
920
|
}
|
|
681
921
|
}
|
|
682
922
|
await pc.addInteractionHistory(history);
|
|
683
923
|
await pc.addLastMessage(lastMessage);
|
|
684
924
|
await pc.addRoutingOverview(routes);
|
|
925
|
+
// Add route condition context if available
|
|
926
|
+
if (routeConditionContext && routeConditionContext.length > 0) {
|
|
927
|
+
await pc.addInstruction([
|
|
928
|
+
"",
|
|
929
|
+
"Additional routing context from route conditions:",
|
|
930
|
+
...routeConditionContext.map(ctx => `- ${ctx}`),
|
|
931
|
+
"",
|
|
932
|
+
"Consider this context when scoring routes for relevance.",
|
|
933
|
+
].join("\n"));
|
|
934
|
+
}
|
|
685
935
|
await pc.addInstruction([
|
|
686
936
|
"Scoring rules:",
|
|
687
937
|
"- 90-100: explicit keywords + clear intent",
|