@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
|
@@ -5,15 +5,14 @@ import type {
|
|
|
5
5
|
RoutingDecision,
|
|
6
6
|
SessionState,
|
|
7
7
|
AiProvider,
|
|
8
|
+
TemplateContext,
|
|
8
9
|
} from "../types";
|
|
9
10
|
import { enterRoute, mergeCollected } from "../utils";
|
|
10
11
|
import type { Route } from "./Route";
|
|
11
12
|
import type { Step } from "./Step";
|
|
12
13
|
import { PromptComposer } from "./PromptComposer";
|
|
13
|
-
import { getLastMessageFromHistory } from "../utils/event";
|
|
14
|
-
import { logger } from "../utils/logger";
|
|
15
|
-
import { render } from "../utils/template";
|
|
16
14
|
import { END_ROUTE_ID } from "../constants";
|
|
15
|
+
import { createTemplateContext, getLastMessageFromHistory, logger } from "../utils";
|
|
17
16
|
|
|
18
17
|
export interface CandidateStep<TContext = unknown, TData = unknown> {
|
|
19
18
|
step: Step<TContext, TData>;
|
|
@@ -55,6 +54,7 @@ export interface BuildStepSelectionPromptParams<
|
|
|
55
54
|
agentOptions?: AgentOptions<TContext, TData>;
|
|
56
55
|
context?: TContext;
|
|
57
56
|
session?: SessionState<TData>;
|
|
57
|
+
stepConditionContext?: string[]; // AI context strings from step conditions
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
export interface BuildRoutingPromptParams<TContext = unknown, TData = unknown> {
|
|
@@ -65,6 +65,7 @@ export interface BuildRoutingPromptParams<TContext = unknown, TData = unknown> {
|
|
|
65
65
|
session?: SessionState<TData>;
|
|
66
66
|
activeRouteSteps?: Step<TContext, TData>[];
|
|
67
67
|
context?: TContext;
|
|
68
|
+
routeConditionContext?: string[]; // AI context strings from route conditions
|
|
68
69
|
}
|
|
69
70
|
|
|
70
71
|
export class RoutingEngine<TContext = unknown, TData = unknown> {
|
|
@@ -125,14 +126,20 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
|
|
|
125
126
|
// Check if this single route is complete (use updated session data)
|
|
126
127
|
const completedRoutes = route.isComplete(updatedSession.data || {}) ? [route] : [];
|
|
127
128
|
|
|
128
|
-
// Get candidate steps
|
|
129
|
+
// Get candidate steps using new condition evaluation
|
|
130
|
+
const templateContext = createTemplateContext({
|
|
131
|
+
context,
|
|
132
|
+
session: updatedSession,
|
|
133
|
+
history,
|
|
134
|
+
data: updatedSession.data
|
|
135
|
+
});
|
|
129
136
|
const currentStep = updatedSession.currentStep
|
|
130
137
|
? route.getStep(updatedSession.currentStep.id)
|
|
131
138
|
: undefined;
|
|
132
|
-
const candidates = this.
|
|
139
|
+
const candidates = await this.getCandidateStepsWithConditions(
|
|
133
140
|
route,
|
|
134
141
|
currentStep,
|
|
135
|
-
|
|
142
|
+
templateContext
|
|
136
143
|
);
|
|
137
144
|
|
|
138
145
|
if (candidates.length === 0) {
|
|
@@ -140,14 +147,13 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
|
|
|
140
147
|
return { selectedRoute, session: updatedSession };
|
|
141
148
|
}
|
|
142
149
|
|
|
143
|
-
// If only one candidate,
|
|
150
|
+
// If only one candidate, check if it's a completion marker
|
|
144
151
|
if (candidates.length === 1) {
|
|
145
152
|
const candidate = candidates[0];
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
if (isRouteComplete) {
|
|
153
|
+
|
|
154
|
+
if (candidate.isRouteComplete) {
|
|
149
155
|
logger.debug(
|
|
150
|
-
`[RoutingEngine] Single-route: Route complete - all
|
|
156
|
+
`[RoutingEngine] Single-route: Route complete - all required fields collected or END_ROUTE reached`
|
|
151
157
|
);
|
|
152
158
|
// Don't return a selectedStep when route is complete - there's no step to enter
|
|
153
159
|
return {
|
|
@@ -173,18 +179,33 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
|
|
|
173
179
|
|
|
174
180
|
// No candidates means route is likely complete or has no valid next steps
|
|
175
181
|
if (candidates.length === 0) {
|
|
176
|
-
|
|
182
|
+
const dataComplete = route.isComplete(updatedSession.data || {});
|
|
183
|
+
logger.debug(
|
|
184
|
+
`[RoutingEngine] Single-route: No valid steps found - ` +
|
|
185
|
+
`(data: ${dataComplete ? 'complete' : 'incomplete'}, marking as ${dataComplete ? 'complete' : 'incomplete'})`
|
|
186
|
+
);
|
|
177
187
|
return {
|
|
178
188
|
selectedRoute,
|
|
179
189
|
selectedStep: undefined,
|
|
180
190
|
session: updatedSession,
|
|
181
|
-
isRouteComplete:
|
|
191
|
+
isRouteComplete: dataComplete,
|
|
182
192
|
completedRoutes,
|
|
183
193
|
};
|
|
184
194
|
}
|
|
185
195
|
|
|
186
196
|
// Multiple candidates - use AI to select best step
|
|
187
197
|
const lastUserMessage = getLastMessageFromHistory(history);
|
|
198
|
+
|
|
199
|
+
// Collect AI context strings from step conditions
|
|
200
|
+
const stepConditionContext: string[] = [];
|
|
201
|
+
for (const candidate of candidates) {
|
|
202
|
+
const whenResult = await candidate.step.evaluateWhen(templateContext);
|
|
203
|
+
stepConditionContext.push(...whenResult.aiContextStrings);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// Check if any candidate is a completion marker (isRouteComplete = true)
|
|
207
|
+
const hasCompletionOption = candidates.some(c => c.isRouteComplete);
|
|
208
|
+
|
|
188
209
|
const stepPrompt = await this.buildStepSelectionPrompt({
|
|
189
210
|
route,
|
|
190
211
|
currentStep,
|
|
@@ -195,10 +216,13 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
|
|
|
195
216
|
agentOptions,
|
|
196
217
|
context,
|
|
197
218
|
session: updatedSession,
|
|
219
|
+
stepConditionContext,
|
|
220
|
+
includeEndRoute: hasCompletionOption,
|
|
198
221
|
});
|
|
199
222
|
|
|
200
223
|
const stepSchema = this.buildStepSelectionSchema(
|
|
201
|
-
candidates.map((c) => c.step)
|
|
224
|
+
candidates.filter(c => !c.isRouteComplete).map((c) => c.step),
|
|
225
|
+
hasCompletionOption
|
|
202
226
|
);
|
|
203
227
|
|
|
204
228
|
const stepResult = await provider.generateMessage<
|
|
@@ -220,6 +244,25 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
|
|
|
220
244
|
});
|
|
221
245
|
|
|
222
246
|
const selectedStepId = stepResult.structured?.selectedStepId;
|
|
247
|
+
|
|
248
|
+
// Check if AI selected END_ROUTE
|
|
249
|
+
if (selectedStepId === END_ROUTE_ID) {
|
|
250
|
+
logger.debug(
|
|
251
|
+
`[RoutingEngine] Single-route: AI selected END_ROUTE - completing route`
|
|
252
|
+
);
|
|
253
|
+
logger.debug(
|
|
254
|
+
`[RoutingEngine] Single-route: Reasoning: ${stepResult.structured?.reasoning}`
|
|
255
|
+
);
|
|
256
|
+
return {
|
|
257
|
+
selectedRoute,
|
|
258
|
+
selectedStep: undefined,
|
|
259
|
+
responseDirectives: stepResult.structured?.responseDirectives,
|
|
260
|
+
session: updatedSession,
|
|
261
|
+
isRouteComplete: true,
|
|
262
|
+
completedRoutes,
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
|
|
223
266
|
const selectedStep = candidates.find((c) => c.step.id === selectedStepId);
|
|
224
267
|
|
|
225
268
|
if (selectedStep) {
|
|
@@ -245,24 +288,26 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
|
|
|
245
288
|
}
|
|
246
289
|
|
|
247
290
|
/**
|
|
248
|
-
* Recursively traverse step chain to find first non-skipped step or END_ROUTE
|
|
291
|
+
* Recursively traverse step chain to find first non-skipped step or END_ROUTE using new condition evaluation
|
|
249
292
|
* @private
|
|
250
293
|
*/
|
|
251
|
-
private
|
|
294
|
+
private async findFirstValidStepRecursiveWithConditions(
|
|
252
295
|
currentStep: Step<TContext, TData>,
|
|
253
|
-
|
|
296
|
+
templateContext: TemplateContext<TContext, TData>,
|
|
254
297
|
visited: Set<string>
|
|
255
|
-
): {
|
|
298
|
+
): Promise<{
|
|
256
299
|
step?: Step<TContext, TData>;
|
|
257
300
|
isRouteComplete?: boolean;
|
|
258
|
-
|
|
301
|
+
aiContextStrings?: string[];
|
|
302
|
+
}> {
|
|
259
303
|
// Prevent infinite loops
|
|
260
304
|
if (visited.has(currentStep.id)) {
|
|
261
|
-
return {};
|
|
305
|
+
return { aiContextStrings: [] };
|
|
262
306
|
}
|
|
263
307
|
visited.add(currentStep.id);
|
|
264
308
|
|
|
265
309
|
const transitions = currentStep.getTransitions();
|
|
310
|
+
const allAiContextStrings: string[] = [];
|
|
266
311
|
|
|
267
312
|
for (const transition of transitions) {
|
|
268
313
|
const target = transition;
|
|
@@ -272,19 +317,25 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
|
|
|
272
317
|
// Found END_ROUTE - route is complete
|
|
273
318
|
return {
|
|
274
319
|
isRouteComplete: true,
|
|
320
|
+
aiContextStrings: allAiContextStrings,
|
|
275
321
|
};
|
|
276
322
|
}
|
|
277
323
|
|
|
278
324
|
if (!target) continue;
|
|
279
325
|
|
|
326
|
+
// Evaluate skipIf condition using new system
|
|
327
|
+
const skipResult = await target.evaluateSkipIf(templateContext);
|
|
328
|
+
allAiContextStrings.push(...skipResult.aiContextStrings);
|
|
329
|
+
|
|
280
330
|
// If target should NOT be skipped, we found our step
|
|
281
|
-
if (!
|
|
331
|
+
if (!skipResult.shouldSkip) {
|
|
282
332
|
logger.debug(
|
|
283
333
|
`[RoutingEngine] Found valid step after skipping: ${target.id}`
|
|
284
334
|
);
|
|
285
335
|
return {
|
|
286
336
|
step: target,
|
|
287
337
|
isRouteComplete: false,
|
|
338
|
+
aiContextStrings: allAiContextStrings,
|
|
288
339
|
};
|
|
289
340
|
}
|
|
290
341
|
|
|
@@ -292,36 +343,69 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
|
|
|
292
343
|
logger.debug(
|
|
293
344
|
`[RoutingEngine] Skipping step ${target.id} (skipIf condition met), continuing traversal...`
|
|
294
345
|
);
|
|
295
|
-
const result = this.
|
|
346
|
+
const result = await this.findFirstValidStepRecursiveWithConditions(target, templateContext, visited);
|
|
347
|
+
|
|
348
|
+
// Collect AI context from recursive call
|
|
349
|
+
if (result.aiContextStrings) {
|
|
350
|
+
allAiContextStrings.push(...result.aiContextStrings);
|
|
351
|
+
}
|
|
296
352
|
|
|
297
353
|
// If we found something (a valid step or END_ROUTE), return it
|
|
298
354
|
if (result.step || result.isRouteComplete) {
|
|
299
|
-
return
|
|
355
|
+
return {
|
|
356
|
+
...result,
|
|
357
|
+
aiContextStrings: allAiContextStrings,
|
|
358
|
+
};
|
|
300
359
|
}
|
|
301
360
|
}
|
|
302
361
|
|
|
303
362
|
// No valid steps or END_ROUTE found in this branch
|
|
304
|
-
return {};
|
|
363
|
+
return { aiContextStrings: allAiContextStrings };
|
|
305
364
|
}
|
|
306
365
|
|
|
366
|
+
|
|
367
|
+
|
|
307
368
|
/**
|
|
308
|
-
* Identify valid next candidate steps
|
|
369
|
+
* Identify valid next candidate steps using new condition evaluation system
|
|
309
370
|
* Returns step with isRouteComplete flag if route is complete (all steps skipped + has END_ROUTE transition)
|
|
371
|
+
*
|
|
372
|
+
* NEW: Automatically completes route when all required fields are collected
|
|
310
373
|
*/
|
|
311
|
-
|
|
374
|
+
async getCandidateStepsWithConditions(
|
|
312
375
|
route: Route<TContext, TData>,
|
|
313
376
|
currentStep: Step<TContext, TData> | undefined,
|
|
314
|
-
|
|
315
|
-
): CandidateStep<TContext, TData>[] {
|
|
377
|
+
templateContext: TemplateContext<TContext, TData>
|
|
378
|
+
): Promise<CandidateStep<TContext, TData>[]> {
|
|
316
379
|
const candidates: CandidateStep<TContext, TData>[] = [];
|
|
380
|
+
const data = templateContext.data || {};
|
|
381
|
+
|
|
382
|
+
// Check if all required fields are collected
|
|
383
|
+
const allRequiredFieldsCollected = route.isComplete(data);
|
|
317
384
|
|
|
318
385
|
if (!currentStep) {
|
|
386
|
+
// Entering route for the first time
|
|
387
|
+
|
|
388
|
+
// If all required fields already collected, route is immediately complete
|
|
389
|
+
if (allRequiredFieldsCollected) {
|
|
390
|
+
logger.debug(
|
|
391
|
+
`[RoutingEngine] Route ${route.title} complete on entry: all required fields already collected`
|
|
392
|
+
);
|
|
393
|
+
// Return a completion marker - use initial step with completion flag
|
|
394
|
+
candidates.push({
|
|
395
|
+
step: route.initialStep,
|
|
396
|
+
isRouteComplete: true,
|
|
397
|
+
});
|
|
398
|
+
return candidates;
|
|
399
|
+
}
|
|
400
|
+
|
|
319
401
|
const initialStep = route.initialStep;
|
|
320
|
-
|
|
402
|
+
const skipResult = await initialStep.evaluateSkipIf(templateContext);
|
|
403
|
+
|
|
404
|
+
if (skipResult.shouldSkip) {
|
|
321
405
|
// Initial step should be skipped - recursively traverse to find first non-skipped step or END_ROUTE
|
|
322
|
-
const result = this.
|
|
406
|
+
const result = await this.findFirstValidStepRecursiveWithConditions(
|
|
323
407
|
initialStep,
|
|
324
|
-
|
|
408
|
+
templateContext,
|
|
325
409
|
new Set<string>()
|
|
326
410
|
);
|
|
327
411
|
|
|
@@ -351,6 +435,68 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
|
|
|
351
435
|
return candidates;
|
|
352
436
|
}
|
|
353
437
|
|
|
438
|
+
// Check if all required fields are now collected (may have been collected during this step)
|
|
439
|
+
if (allRequiredFieldsCollected) {
|
|
440
|
+
// Required fields are complete - check if we should continue for optional fields
|
|
441
|
+
const transitions = currentStep.getTransitions();
|
|
442
|
+
const optionalFieldCandidates: CandidateStep<TContext, TData>[] = [];
|
|
443
|
+
|
|
444
|
+
for (const transition of transitions) {
|
|
445
|
+
const target = transition;
|
|
446
|
+
|
|
447
|
+
// Check for END_ROUTE transition
|
|
448
|
+
if (target && target.id === END_ROUTE_ID) {
|
|
449
|
+
continue;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
if (!target) continue;
|
|
453
|
+
|
|
454
|
+
// Check if this step collects only optional fields
|
|
455
|
+
const collectsOnlyOptional = target.collect && target.collect.length > 0 &&
|
|
456
|
+
target.collect.every(field =>
|
|
457
|
+
route.optionalFields?.includes(field)
|
|
458
|
+
);
|
|
459
|
+
|
|
460
|
+
if (collectsOnlyOptional) {
|
|
461
|
+
// This step collects optional fields - it's a candidate
|
|
462
|
+
const skipResult = await target.evaluateSkipIf(templateContext);
|
|
463
|
+
if (!skipResult.shouldSkip) {
|
|
464
|
+
optionalFieldCandidates.push({
|
|
465
|
+
step: target,
|
|
466
|
+
isRouteComplete: false,
|
|
467
|
+
});
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
// If we have optional field candidates, include them along with END_ROUTE option
|
|
473
|
+
if (optionalFieldCandidates.length > 0) {
|
|
474
|
+
logger.debug(
|
|
475
|
+
`[RoutingEngine] Required fields complete, but ${optionalFieldCandidates.length} optional field steps available`
|
|
476
|
+
);
|
|
477
|
+
// Add optional field steps as candidates
|
|
478
|
+
candidates.push(...optionalFieldCandidates);
|
|
479
|
+
// Also add END_ROUTE as a candidate (AI can choose to skip optional fields)
|
|
480
|
+
candidates.push({
|
|
481
|
+
step: currentStep,
|
|
482
|
+
isRouteComplete: true,
|
|
483
|
+
});
|
|
484
|
+
return candidates;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
// No optional fields to collect - route is complete
|
|
488
|
+
logger.debug(
|
|
489
|
+
`[RoutingEngine] Route ${route.title} complete: all required fields collected, no optional fields remain`
|
|
490
|
+
);
|
|
491
|
+
return [
|
|
492
|
+
{
|
|
493
|
+
step: currentStep,
|
|
494
|
+
isRouteComplete: true,
|
|
495
|
+
},
|
|
496
|
+
];
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
// Required fields not yet complete - continue normal step progression
|
|
354
500
|
const transitions = currentStep.getTransitions();
|
|
355
501
|
let hasEndRoute = false;
|
|
356
502
|
|
|
@@ -365,15 +511,17 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
|
|
|
365
511
|
|
|
366
512
|
if (!target) continue;
|
|
367
513
|
|
|
368
|
-
|
|
514
|
+
const skipResult = await target.evaluateSkipIf(templateContext);
|
|
515
|
+
|
|
516
|
+
if (skipResult.shouldSkip) {
|
|
369
517
|
logger.debug(
|
|
370
518
|
`[RoutingEngine] Skipping step ${target.id} (skipIf condition met)`
|
|
371
519
|
);
|
|
372
520
|
|
|
373
521
|
// Recursively traverse to find next valid step or END_ROUTE
|
|
374
|
-
const result = this.
|
|
522
|
+
const result = await this.findFirstValidStepRecursiveWithConditions(
|
|
375
523
|
target,
|
|
376
|
-
|
|
524
|
+
templateContext,
|
|
377
525
|
new Set<string>([currentStep.id]) // Already visited current step
|
|
378
526
|
);
|
|
379
527
|
|
|
@@ -412,7 +560,8 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
|
|
|
412
560
|
}
|
|
413
561
|
|
|
414
562
|
// Otherwise, stay in current step if it's still valid
|
|
415
|
-
|
|
563
|
+
const currentSkipResult = await currentStep.evaluateSkipIf(templateContext);
|
|
564
|
+
if (!currentSkipResult.shouldSkip) {
|
|
416
565
|
candidates.push({
|
|
417
566
|
step: currentStep,
|
|
418
567
|
isRouteComplete: hasEndRoute || false,
|
|
@@ -488,32 +637,67 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
|
|
|
488
637
|
}
|
|
489
638
|
|
|
490
639
|
const lastUserMessage = getLastMessageFromHistory(history);
|
|
640
|
+
const templateContext = createTemplateContext({
|
|
641
|
+
context,
|
|
642
|
+
session,
|
|
643
|
+
history,
|
|
644
|
+
data: session.data
|
|
645
|
+
});
|
|
646
|
+
|
|
647
|
+
// Apply route filtering with new condition evaluation system
|
|
648
|
+
const skipIfResult = await this.filterRoutesBySkipIf(routes, templateContext);
|
|
649
|
+
const whenResult = await this.filterRoutesByWhen(skipIfResult.eligibleRoutes, templateContext);
|
|
650
|
+
|
|
651
|
+
// Collect all AI context strings from route conditions
|
|
652
|
+
const routeConditionContext = [...skipIfResult.aiContextStrings, ...whenResult.aiContextStrings];
|
|
653
|
+
|
|
654
|
+
// Use filtered routes for further processing
|
|
655
|
+
const eligibleRoutes = whenResult.eligibleRoutes;
|
|
656
|
+
|
|
657
|
+
logger.debug(`[RoutingEngine] Route filtering: ${routes.length} total → ${skipIfResult.eligibleRoutes.length} after skipIf → ${eligibleRoutes.length} after when`);
|
|
491
658
|
|
|
492
659
|
let activeRouteSteps: Step<TContext, TData>[] | undefined;
|
|
493
660
|
let activeRoute: Route<TContext, TData> | undefined;
|
|
494
661
|
let isRouteComplete = false;
|
|
662
|
+
let updatedSession = session;
|
|
495
663
|
|
|
496
664
|
if (session.currentRoute) {
|
|
497
|
-
activeRoute =
|
|
665
|
+
activeRoute = eligibleRoutes.find((r) => r.id === session.currentRoute?.id);
|
|
498
666
|
if (activeRoute) {
|
|
499
667
|
const currentStep = session.currentStep
|
|
500
668
|
? activeRoute.getStep(session.currentStep.id)
|
|
501
669
|
: undefined;
|
|
502
|
-
const
|
|
670
|
+
const activeTemplateContext = createTemplateContext({
|
|
671
|
+
...templateContext,
|
|
672
|
+
session: updatedSession,
|
|
673
|
+
data: updatedSession.data
|
|
674
|
+
});
|
|
675
|
+
const candidates = await this.getCandidateStepsWithConditions(
|
|
503
676
|
activeRoute,
|
|
504
677
|
currentStep,
|
|
505
|
-
|
|
678
|
+
activeTemplateContext
|
|
506
679
|
);
|
|
507
680
|
|
|
508
681
|
// Check if route is complete
|
|
682
|
+
// getCandidateStepsWithConditions now automatically handles completion when required fields are collected
|
|
509
683
|
if (candidates.length === 1 && candidates[0].isRouteComplete) {
|
|
510
684
|
isRouteComplete = true;
|
|
511
685
|
logger.debug(
|
|
512
|
-
`[RoutingEngine] Route ${activeRoute.title} is complete - all
|
|
686
|
+
`[RoutingEngine] Route ${activeRoute.title} is complete - all required fields collected or END_ROUTE reached`
|
|
513
687
|
);
|
|
514
688
|
// Don't include steps in routing if route is complete
|
|
515
689
|
activeRouteSteps = undefined;
|
|
690
|
+
} else if (candidates.length === 0) {
|
|
691
|
+
// No candidates - check if data is complete
|
|
692
|
+
const dataComplete = activeRoute.isComplete(updatedSession.data || {});
|
|
693
|
+
isRouteComplete = dataComplete;
|
|
694
|
+
logger.debug(
|
|
695
|
+
`[RoutingEngine] Route ${activeRoute.title} has no valid steps - ` +
|
|
696
|
+
`marking as ${isRouteComplete ? 'complete' : 'incomplete'}`
|
|
697
|
+
);
|
|
698
|
+
activeRouteSteps = undefined;
|
|
516
699
|
} else {
|
|
700
|
+
// Multiple candidates or single non-complete candidate
|
|
517
701
|
activeRouteSteps = candidates.map((c) => c.step);
|
|
518
702
|
logger.debug(
|
|
519
703
|
`[RoutingEngine] Found ${activeRouteSteps.length} candidate steps for active route`
|
|
@@ -523,19 +707,20 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
|
|
|
523
707
|
}
|
|
524
708
|
|
|
525
709
|
const routingSchema = this.buildDynamicRoutingSchema(
|
|
526
|
-
|
|
710
|
+
eligibleRoutes,
|
|
527
711
|
undefined,
|
|
528
712
|
activeRouteSteps
|
|
529
713
|
);
|
|
530
714
|
|
|
531
715
|
const routingPrompt = await this.buildRoutingPrompt({
|
|
532
716
|
history,
|
|
533
|
-
routes,
|
|
717
|
+
routes: eligibleRoutes,
|
|
534
718
|
lastMessage: lastUserMessage,
|
|
535
719
|
agentOptions,
|
|
536
720
|
session,
|
|
537
721
|
activeRouteSteps,
|
|
538
722
|
context,
|
|
723
|
+
routeConditionContext, // Pass AI context strings from route conditions
|
|
539
724
|
});
|
|
540
725
|
|
|
541
726
|
const routingResult = await provider.generateMessage<
|
|
@@ -555,25 +740,34 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
|
|
|
555
740
|
let selectedRoute: Route<TContext, TData> | undefined;
|
|
556
741
|
let selectedStep: Step<TContext, TData> | undefined;
|
|
557
742
|
let responseDirectives: string[] | undefined;
|
|
558
|
-
let updatedSession = session;
|
|
559
743
|
|
|
560
744
|
if (routingResult.structured?.routes) {
|
|
561
745
|
// Use cross-route completion evaluation to select optimal route
|
|
562
746
|
const optimalRoute = this.selectOptimalRoute(
|
|
563
|
-
|
|
747
|
+
eligibleRoutes,
|
|
564
748
|
updatedSession.data || {},
|
|
565
749
|
routingResult.structured.routes
|
|
566
750
|
);
|
|
567
751
|
|
|
568
|
-
//
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
752
|
+
// If no optimal route found, check why
|
|
753
|
+
if (!optimalRoute) {
|
|
754
|
+
if (eligibleRoutes.length === 0) {
|
|
755
|
+
// No routes passed filtering
|
|
756
|
+
logger.debug(
|
|
757
|
+
`[RoutingEngine] No eligible routes available - all routes filtered out`
|
|
758
|
+
);
|
|
759
|
+
selectedRoute = undefined;
|
|
760
|
+
} else {
|
|
761
|
+
// Routes exist but selectOptimalRoute returned undefined
|
|
762
|
+
// This means all routes are 100% complete
|
|
763
|
+
logger.debug(
|
|
764
|
+
`[RoutingEngine] No optimal route found - all ${eligibleRoutes.length} eligible routes are complete`
|
|
765
|
+
);
|
|
766
|
+
selectedRoute = undefined;
|
|
767
|
+
}
|
|
768
|
+
} else {
|
|
769
|
+
selectedRoute = optimalRoute;
|
|
770
|
+
}
|
|
577
771
|
|
|
578
772
|
responseDirectives = routingResult.structured.responseDirectives;
|
|
579
773
|
|
|
@@ -611,6 +805,72 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
|
|
|
611
805
|
};
|
|
612
806
|
}
|
|
613
807
|
|
|
808
|
+
/**
|
|
809
|
+
* Filter routes based on skipIf conditions
|
|
810
|
+
* @param routes - All available routes
|
|
811
|
+
* @param templateContext - Context for condition evaluation
|
|
812
|
+
* @returns Object with eligible routes and collected AI context strings
|
|
813
|
+
*/
|
|
814
|
+
async filterRoutesBySkipIf(
|
|
815
|
+
routes: Route<TContext, TData>[],
|
|
816
|
+
templateContext: TemplateContext<TContext, TData>
|
|
817
|
+
): Promise<{
|
|
818
|
+
eligibleRoutes: Route<TContext, TData>[];
|
|
819
|
+
aiContextStrings: string[];
|
|
820
|
+
}> {
|
|
821
|
+
const eligibleRoutes: Route<TContext, TData>[] = [];
|
|
822
|
+
const aiContextStrings: string[] = [];
|
|
823
|
+
|
|
824
|
+
for (const route of routes) {
|
|
825
|
+
const skipResult = await route.evaluateSkipIf(templateContext);
|
|
826
|
+
|
|
827
|
+
// Collect AI context strings from skipIf conditions
|
|
828
|
+
aiContextStrings.push(...skipResult.aiContextStrings);
|
|
829
|
+
|
|
830
|
+
// If route should not be skipped, it's eligible
|
|
831
|
+
if (!skipResult.programmaticResult) {
|
|
832
|
+
eligibleRoutes.push(route);
|
|
833
|
+
} else {
|
|
834
|
+
logger.debug(`[RoutingEngine] Skipping route ${route.title} (skipIf condition met)`);
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
return { eligibleRoutes, aiContextStrings };
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
/**
|
|
842
|
+
* Filter routes based on when conditions
|
|
843
|
+
* @param routes - Routes that passed skipIf filtering
|
|
844
|
+
* @param templateContext - Context for condition evaluation
|
|
845
|
+
* @returns Object with eligible routes and collected AI context strings
|
|
846
|
+
*/
|
|
847
|
+
async filterRoutesByWhen(
|
|
848
|
+
routes: Route<TContext, TData>[],
|
|
849
|
+
templateContext: TemplateContext<TContext, TData>
|
|
850
|
+
): Promise<{
|
|
851
|
+
eligibleRoutes: Route<TContext, TData>[];
|
|
852
|
+
aiContextStrings: string[];
|
|
853
|
+
}> {
|
|
854
|
+
const eligibleRoutes: Route<TContext, TData>[] = [];
|
|
855
|
+
const aiContextStrings: string[] = [];
|
|
856
|
+
|
|
857
|
+
for (const route of routes) {
|
|
858
|
+
const whenResult = await route.evaluateWhen(templateContext);
|
|
859
|
+
|
|
860
|
+
// Collect AI context strings from when conditions
|
|
861
|
+
aiContextStrings.push(...whenResult.aiContextStrings);
|
|
862
|
+
|
|
863
|
+
// If route has no programmatic conditions or they evaluate to true, it's eligible
|
|
864
|
+
if (!whenResult.hasProgrammaticConditions || whenResult.programmaticResult) {
|
|
865
|
+
eligibleRoutes.push(route);
|
|
866
|
+
} else {
|
|
867
|
+
logger.debug(`[RoutingEngine] Route ${route.title} not eligible (when condition not met)`);
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
return { eligibleRoutes, aiContextStrings };
|
|
872
|
+
}
|
|
873
|
+
|
|
614
874
|
/**
|
|
615
875
|
* Evaluate all routes for completion based on collected data
|
|
616
876
|
* @param routes - All available routes
|
|
@@ -641,6 +901,7 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
|
|
|
641
901
|
/**
|
|
642
902
|
* Find the best route to continue based on completion status and user intent
|
|
643
903
|
* Prioritizes routes that are partially complete but not finished
|
|
904
|
+
* IMPORTANT: Completed routes are excluded to prevent re-entering finished tasks
|
|
644
905
|
* @param routes - All available routes
|
|
645
906
|
* @param data - Currently collected agent-level data
|
|
646
907
|
* @param routeScores - AI-generated route scores from routing decision
|
|
@@ -660,8 +921,12 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
|
|
|
660
921
|
const aiScore = routeScores[route.id] || 0;
|
|
661
922
|
const completionProgress = completionStatus.get(route.id) || 0;
|
|
662
923
|
|
|
663
|
-
//
|
|
664
|
-
|
|
924
|
+
// ALWAYS skip fully completed routes to prevent re-entering finished tasks
|
|
925
|
+
// Users should not be forced back into completed routes
|
|
926
|
+
if (completionProgress >= 1.0) {
|
|
927
|
+
logger.debug(
|
|
928
|
+
`[RoutingEngine] Excluding completed route: ${route.title} (100% complete)`
|
|
929
|
+
);
|
|
665
930
|
continue;
|
|
666
931
|
}
|
|
667
932
|
|
|
@@ -696,7 +961,7 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
|
|
|
696
961
|
* @private
|
|
697
962
|
*/
|
|
698
963
|
private async buildStepSelectionPrompt(
|
|
699
|
-
params: BuildStepSelectionPromptParams<TContext, TData>
|
|
964
|
+
params: BuildStepSelectionPromptParams<TContext, TData> & { includeEndRoute?: boolean }
|
|
700
965
|
): Promise<string> {
|
|
701
966
|
const {
|
|
702
967
|
route,
|
|
@@ -708,8 +973,10 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
|
|
|
708
973
|
agentOptions,
|
|
709
974
|
context,
|
|
710
975
|
session,
|
|
976
|
+
stepConditionContext,
|
|
977
|
+
includeEndRoute = false,
|
|
711
978
|
} = params;
|
|
712
|
-
const templateContext = { context, session, history };
|
|
979
|
+
const templateContext = createTemplateContext({ context, session, history });
|
|
713
980
|
const pc = new PromptComposer<TContext, TData>(templateContext);
|
|
714
981
|
|
|
715
982
|
// Add agent metadata
|
|
@@ -745,7 +1012,7 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
|
|
|
745
1012
|
await pc.addInteractionHistory(history);
|
|
746
1013
|
await pc.addLastMessage(lastMessage);
|
|
747
1014
|
|
|
748
|
-
// Add candidate steps
|
|
1015
|
+
// Add candidate steps with condition context
|
|
749
1016
|
const stepDescriptions = [];
|
|
750
1017
|
for (const candidate of candidates) {
|
|
751
1018
|
const idx = candidates.indexOf(candidate);
|
|
@@ -754,9 +1021,14 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
|
|
|
754
1021
|
` Description: ${candidate.step.description || "N/A"}`,
|
|
755
1022
|
];
|
|
756
1023
|
|
|
1024
|
+
// Add when condition context
|
|
757
1025
|
if (candidate.step.when) {
|
|
758
|
-
const
|
|
759
|
-
|
|
1026
|
+
const whenResult = await candidate.step.evaluateWhen(templateContext);
|
|
1027
|
+
if (whenResult.aiContextStrings.length > 0) {
|
|
1028
|
+
parts.push(` When conditions: ${whenResult.aiContextStrings.join(", ")}`);
|
|
1029
|
+
} else if (typeof candidate.step.when === 'string') {
|
|
1030
|
+
parts.push(` When this step should be completed: ${candidate.step.when}`);
|
|
1031
|
+
}
|
|
760
1032
|
}
|
|
761
1033
|
|
|
762
1034
|
if (candidate.step.requires && candidate.step.requires.length > 0) {
|
|
@@ -774,26 +1046,52 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
|
|
|
774
1046
|
`Available Steps to Transition To:\n${stepDescriptions.join("\n\n")}`
|
|
775
1047
|
);
|
|
776
1048
|
|
|
1049
|
+
// Add step condition context if available
|
|
1050
|
+
if (stepConditionContext && stepConditionContext.length > 0) {
|
|
1051
|
+
await pc.addInstruction(
|
|
1052
|
+
[
|
|
1053
|
+
"",
|
|
1054
|
+
"Additional step context from conditions:",
|
|
1055
|
+
...stepConditionContext.map(ctx => `- ${ctx}`),
|
|
1056
|
+
"",
|
|
1057
|
+
"Consider this context when selecting the most appropriate step.",
|
|
1058
|
+
].join("\n")
|
|
1059
|
+
);
|
|
1060
|
+
}
|
|
1061
|
+
|
|
777
1062
|
// Add decision prompt
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
1063
|
+
const decisionRules = [
|
|
1064
|
+
"Task: Decide which step to transition to based on:",
|
|
1065
|
+
"1. The user's current message and intent",
|
|
1066
|
+
"2. The conversation history and context",
|
|
1067
|
+
"3. The collected data we already have",
|
|
1068
|
+
"4. The conditions and requirements of each step",
|
|
1069
|
+
"5. The logical flow of the conversation",
|
|
1070
|
+
"",
|
|
1071
|
+
"Rules:",
|
|
1072
|
+
"- If a step has a condition, evaluate whether it's met based on context",
|
|
1073
|
+
"- If a step requires data we don't have, consider if we should collect it now",
|
|
1074
|
+
"- Choose the step that makes the most sense for moving the conversation forward",
|
|
1075
|
+
"- Steps with skipIf conditions that are met have already been filtered out",
|
|
1076
|
+
];
|
|
1077
|
+
|
|
1078
|
+
if (includeEndRoute) {
|
|
1079
|
+
decisionRules.push(
|
|
786
1080
|
"",
|
|
787
|
-
|
|
788
|
-
"
|
|
789
|
-
"
|
|
790
|
-
"
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
1081
|
+
`- You can select '${END_ROUTE_ID}' to complete this route if:`,
|
|
1082
|
+
" * All required data has been collected",
|
|
1083
|
+
" * The user's intent suggests they're done with this task",
|
|
1084
|
+
" * No further steps are needed to fulfill the user's request"
|
|
1085
|
+
);
|
|
1086
|
+
}
|
|
1087
|
+
|
|
1088
|
+
decisionRules.push(
|
|
1089
|
+
"",
|
|
1090
|
+
"Return ONLY JSON matching the provided schema."
|
|
795
1091
|
);
|
|
796
1092
|
|
|
1093
|
+
await pc.addInstruction(decisionRules.join("\n"));
|
|
1094
|
+
|
|
797
1095
|
return pc.build();
|
|
798
1096
|
}
|
|
799
1097
|
|
|
@@ -802,8 +1100,16 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
|
|
|
802
1100
|
* @private
|
|
803
1101
|
*/
|
|
804
1102
|
private buildStepSelectionSchema(
|
|
805
|
-
validSteps: Step<TContext, TData>[]
|
|
1103
|
+
validSteps: Step<TContext, TData>[],
|
|
1104
|
+
includeEndRoute: boolean = false
|
|
806
1105
|
): StructuredSchema {
|
|
1106
|
+
const stepIds = validSteps.map((s) => s.id);
|
|
1107
|
+
|
|
1108
|
+
// Add END_ROUTE as an option if requested (when required fields are complete)
|
|
1109
|
+
if (includeEndRoute) {
|
|
1110
|
+
stepIds.push(END_ROUTE_ID);
|
|
1111
|
+
}
|
|
1112
|
+
|
|
807
1113
|
return {
|
|
808
1114
|
description:
|
|
809
1115
|
"Step transition decision based on conversation context and collected data",
|
|
@@ -817,8 +1123,10 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
|
|
|
817
1123
|
selectedStepId: {
|
|
818
1124
|
type: "string",
|
|
819
1125
|
nullable: false,
|
|
820
|
-
description:
|
|
821
|
-
|
|
1126
|
+
description: includeEndRoute
|
|
1127
|
+
? `The ID of the selected step to transition to, or '${END_ROUTE_ID}' to complete the route`
|
|
1128
|
+
: "The ID of the selected step to transition to",
|
|
1129
|
+
enum: stepIds,
|
|
822
1130
|
},
|
|
823
1131
|
responseDirectives: {
|
|
824
1132
|
type: "array",
|
|
@@ -918,8 +1226,9 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
|
|
|
918
1226
|
session,
|
|
919
1227
|
activeRouteSteps,
|
|
920
1228
|
context,
|
|
1229
|
+
routeConditionContext,
|
|
921
1230
|
} = params;
|
|
922
|
-
const templateContext = { context, session, history };
|
|
1231
|
+
const templateContext = createTemplateContext({ context, session, history });
|
|
923
1232
|
const pc = new PromptComposer<TContext, TData>(templateContext);
|
|
924
1233
|
if (agentOptions) {
|
|
925
1234
|
await pc.addAgentMeta(agentOptions);
|
|
@@ -989,18 +1298,26 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
|
|
|
989
1298
|
"",
|
|
990
1299
|
"Available steps in active route (choose one to transition to):",
|
|
991
1300
|
];
|
|
1301
|
+
const activeStepConditionContext: string[] = [];
|
|
1302
|
+
|
|
992
1303
|
for (const step of activeRouteSteps) {
|
|
993
1304
|
const idx = activeRouteSteps.indexOf(step);
|
|
994
1305
|
stepInfo.push(`${idx + 1}. Step: ${step.id}`);
|
|
995
1306
|
if (step.description) {
|
|
996
1307
|
stepInfo.push(` Description: ${step.description}`);
|
|
997
1308
|
}
|
|
998
|
-
|
|
1309
|
+
|
|
1310
|
+
// Collect AI context from step conditions
|
|
999
1311
|
if (step.when) {
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1312
|
+
const whenResult = await step.evaluateWhen(templateContext);
|
|
1313
|
+
if (whenResult.aiContextStrings.length > 0) {
|
|
1314
|
+
stepInfo.push(` When conditions: ${whenResult.aiContextStrings.join(", ")}`);
|
|
1315
|
+
activeStepConditionContext.push(...whenResult.aiContextStrings);
|
|
1316
|
+
} else if (typeof step.when === 'string') {
|
|
1317
|
+
stepInfo.push(` When this step should be completed: ${step.when}`);
|
|
1318
|
+
}
|
|
1003
1319
|
}
|
|
1320
|
+
|
|
1004
1321
|
if (step.requires && step.requires.length > 0) {
|
|
1005
1322
|
stepInfo.push(` Required data: ${step.requires.join(", ")}`);
|
|
1006
1323
|
}
|
|
@@ -1017,12 +1334,38 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
|
|
|
1017
1334
|
stepInfo.push("- The logical next step in the conversation");
|
|
1018
1335
|
stepInfo.push("- Whether conditions for steps are met");
|
|
1019
1336
|
await pc.addInstruction(stepInfo.join("\n"));
|
|
1337
|
+
|
|
1338
|
+
// Add active step condition context if available
|
|
1339
|
+
if (activeStepConditionContext.length > 0) {
|
|
1340
|
+
await pc.addInstruction(
|
|
1341
|
+
[
|
|
1342
|
+
"",
|
|
1343
|
+
"Additional context from step conditions:",
|
|
1344
|
+
...activeStepConditionContext.map(ctx => `- ${ctx}`),
|
|
1345
|
+
"",
|
|
1346
|
+
"Use this context to inform your step selection decision.",
|
|
1347
|
+
].join("\n")
|
|
1348
|
+
);
|
|
1349
|
+
}
|
|
1020
1350
|
}
|
|
1021
1351
|
}
|
|
1022
1352
|
|
|
1023
1353
|
await pc.addInteractionHistory(history);
|
|
1024
1354
|
await pc.addLastMessage(lastMessage);
|
|
1025
1355
|
await pc.addRoutingOverview(routes);
|
|
1356
|
+
|
|
1357
|
+
// Add route condition context if available
|
|
1358
|
+
if (routeConditionContext && routeConditionContext.length > 0) {
|
|
1359
|
+
await pc.addInstruction(
|
|
1360
|
+
[
|
|
1361
|
+
"",
|
|
1362
|
+
"Additional routing context from route conditions:",
|
|
1363
|
+
...routeConditionContext.map(ctx => `- ${ctx}`),
|
|
1364
|
+
"",
|
|
1365
|
+
"Consider this context when scoring routes for relevance.",
|
|
1366
|
+
].join("\n")
|
|
1367
|
+
);
|
|
1368
|
+
}
|
|
1026
1369
|
await pc.addInstruction(
|
|
1027
1370
|
[
|
|
1028
1371
|
"Scoring rules:",
|