@falai/agent 0.9.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +304 -72
- package/dist/adapters/MemoryAdapter.d.ts.map +1 -0
- package/dist/adapters/MemoryAdapter.js.map +1 -0
- package/dist/adapters/MongoAdapter.d.ts.map +1 -0
- package/dist/adapters/MongoAdapter.js.map +1 -0
- package/dist/adapters/OpenSearchAdapter.d.ts.map +1 -0
- package/dist/adapters/OpenSearchAdapter.js.map +1 -0
- package/dist/adapters/PostgreSQLAdapter.d.ts.map +1 -0
- package/dist/adapters/PostgreSQLAdapter.js.map +1 -0
- package/dist/adapters/PrismaAdapter.d.ts.map +1 -0
- package/dist/{src/adapters → adapters}/PrismaAdapter.js +3 -2
- package/dist/adapters/PrismaAdapter.js.map +1 -0
- package/dist/adapters/RedisAdapter.d.ts.map +1 -0
- package/dist/{src/adapters → adapters}/RedisAdapter.js +3 -3
- package/dist/adapters/RedisAdapter.js.map +1 -0
- package/dist/adapters/SQLiteAdapter.d.ts.map +1 -0
- package/dist/adapters/SQLiteAdapter.js.map +1 -0
- package/dist/adapters/index.d.ts.map +1 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/cjs/adapters/MemoryAdapter.js.map +1 -0
- package/dist/cjs/adapters/MongoAdapter.js.map +1 -0
- package/dist/cjs/adapters/OpenSearchAdapter.js.map +1 -0
- package/dist/cjs/adapters/PostgreSQLAdapter.js.map +1 -0
- package/dist/{src → cjs}/adapters/PrismaAdapter.d.ts.map +1 -1
- package/dist/cjs/{src/adapters → adapters}/PrismaAdapter.js +3 -2
- package/dist/cjs/adapters/PrismaAdapter.js.map +1 -0
- package/dist/cjs/{src/adapters → adapters}/RedisAdapter.js +2 -2
- package/dist/cjs/adapters/RedisAdapter.js.map +1 -0
- package/dist/cjs/adapters/SQLiteAdapter.js.map +1 -0
- package/dist/cjs/adapters/index.js.map +1 -0
- package/dist/cjs/constants/index.js.map +1 -0
- package/dist/{src → cjs}/core/Agent.d.ts +25 -6
- package/dist/cjs/core/Agent.d.ts.map +1 -0
- package/dist/cjs/{src/core → core}/Agent.js +121 -37
- package/dist/cjs/core/Agent.js.map +1 -0
- package/dist/cjs/core/BatchExecutor.d.ts +353 -0
- package/dist/cjs/core/BatchExecutor.d.ts.map +1 -0
- package/dist/cjs/core/BatchExecutor.js +842 -0
- package/dist/cjs/core/BatchExecutor.js.map +1 -0
- package/dist/cjs/core/BatchPromptBuilder.d.ts +86 -0
- package/dist/cjs/core/BatchPromptBuilder.d.ts.map +1 -0
- package/dist/cjs/core/BatchPromptBuilder.js +201 -0
- package/dist/cjs/core/BatchPromptBuilder.js.map +1 -0
- package/dist/cjs/core/Events.js.map +1 -0
- package/dist/cjs/core/PersistenceManager.js.map +1 -0
- package/dist/{src → cjs}/core/PromptComposer.d.ts +1 -1
- package/dist/cjs/core/PromptComposer.d.ts.map +1 -0
- package/dist/cjs/{src/core → core}/PromptComposer.js +44 -7
- package/dist/cjs/core/PromptComposer.js.map +1 -0
- package/dist/{src → cjs}/core/ResponseEngine.d.ts.map +1 -1
- package/dist/cjs/core/ResponseEngine.js +202 -0
- package/dist/cjs/core/ResponseEngine.js.map +1 -0
- package/dist/{src → cjs}/core/ResponseModal.d.ts +54 -3
- package/dist/cjs/core/ResponseModal.d.ts.map +1 -0
- package/dist/cjs/{src/core → core}/ResponseModal.js +807 -121
- package/dist/cjs/core/ResponseModal.js.map +1 -0
- package/dist/{src → cjs}/core/ResponsePipeline.d.ts +10 -6
- package/dist/cjs/core/ResponsePipeline.d.ts.map +1 -0
- package/dist/cjs/{src/core → core}/ResponsePipeline.js +60 -25
- package/dist/cjs/core/ResponsePipeline.js.map +1 -0
- package/dist/{src → cjs}/core/Route.d.ts +46 -10
- package/dist/cjs/core/Route.d.ts.map +1 -0
- package/dist/cjs/core/Route.js +541 -0
- package/dist/cjs/core/Route.js.map +1 -0
- package/dist/cjs/{src/core → core}/RoutingEngine.d.ts +35 -5
- package/dist/cjs/core/RoutingEngine.d.ts.map +1 -0
- package/dist/cjs/{src/core → core}/RoutingEngine.js +360 -98
- package/dist/cjs/core/RoutingEngine.js.map +1 -0
- package/dist/{src → cjs}/core/SessionManager.d.ts +9 -1
- package/dist/cjs/core/SessionManager.d.ts.map +1 -0
- package/dist/cjs/{src/core → core}/SessionManager.js +27 -5
- package/dist/cjs/core/SessionManager.js.map +1 -0
- package/dist/cjs/core/Step.d.ts +170 -0
- package/dist/cjs/core/Step.d.ts.map +1 -0
- package/dist/cjs/core/Step.js +448 -0
- package/dist/cjs/core/Step.js.map +1 -0
- package/dist/cjs/core/ToolManager.d.ts +234 -0
- package/dist/cjs/core/ToolManager.d.ts.map +1 -0
- package/dist/cjs/core/ToolManager.js +1117 -0
- package/dist/cjs/core/ToolManager.js.map +1 -0
- package/dist/{src → cjs}/index.d.ts +5 -3
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/{src/index.js → index.js} +16 -3
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/{src/providers → providers}/AnthropicProvider.js +18 -18
- package/dist/cjs/providers/AnthropicProvider.js.map +1 -0
- package/dist/{src → cjs}/providers/GeminiProvider.d.ts.map +1 -1
- package/dist/cjs/{src/providers → providers}/GeminiProvider.js +123 -51
- package/dist/cjs/providers/GeminiProvider.js.map +1 -0
- package/dist/cjs/{src/providers → providers}/OpenAIProvider.js +19 -19
- package/dist/cjs/providers/OpenAIProvider.js.map +1 -0
- package/dist/cjs/{src/providers → providers}/OpenRouterProvider.js +19 -19
- package/dist/cjs/providers/OpenRouterProvider.js.map +1 -0
- package/dist/cjs/providers/index.js.map +1 -0
- package/dist/cjs/{src/types → types}/agent.d.ts +12 -4
- package/dist/cjs/types/agent.d.ts.map +1 -0
- package/dist/cjs/types/agent.js.map +1 -0
- package/dist/{src → cjs}/types/ai.js.map +1 -1
- package/dist/cjs/types/history.js.map +1 -0
- package/dist/cjs/{src/types → types}/index.d.ts +5 -3
- package/dist/{src → cjs}/types/index.d.ts.map +1 -1
- package/dist/cjs/{src/types → types}/index.js +8 -1
- package/dist/cjs/types/index.js.map +1 -0
- package/dist/cjs/types/persistence.js.map +1 -0
- package/dist/cjs/{src/types → types}/route.d.ts +116 -15
- package/dist/cjs/types/route.d.ts.map +1 -0
- package/dist/cjs/{src/types → types}/route.js.map +1 -1
- package/dist/cjs/types/session.js.map +1 -0
- package/dist/cjs/types/template.d.ts +88 -0
- package/dist/cjs/types/template.d.ts.map +1 -0
- package/dist/cjs/types/tool.d.ts +130 -0
- package/dist/cjs/types/tool.d.ts.map +1 -0
- package/dist/cjs/types/tool.js +19 -0
- package/dist/cjs/types/tool.js.map +1 -0
- package/dist/cjs/utils/clone.js.map +1 -0
- package/dist/cjs/utils/condition.d.ts +38 -0
- package/dist/cjs/utils/condition.d.ts.map +1 -0
- package/dist/cjs/utils/condition.js +168 -0
- package/dist/cjs/utils/condition.js.map +1 -0
- package/dist/cjs/utils/event.js.map +1 -0
- package/dist/cjs/utils/history.js.map +1 -0
- package/dist/cjs/utils/id.js.map +1 -0
- package/dist/cjs/{src/utils → utils}/index.d.ts +3 -1
- package/dist/cjs/utils/index.d.ts.map +1 -0
- package/dist/cjs/{src/utils → utils}/index.js +12 -1
- package/dist/cjs/utils/index.js.map +1 -0
- package/dist/cjs/utils/json.d.ts +16 -0
- package/dist/cjs/utils/json.d.ts.map +1 -0
- package/dist/cjs/utils/json.js +47 -0
- package/dist/cjs/utils/json.js.map +1 -0
- package/dist/cjs/utils/logger.js.map +1 -0
- package/dist/{src → cjs}/utils/retry.d.ts +0 -3
- package/dist/cjs/utils/retry.d.ts.map +1 -0
- package/dist/cjs/{src/utils → utils}/retry.js +8 -7
- package/dist/cjs/utils/retry.js.map +1 -0
- package/dist/cjs/utils/session.js.map +1 -0
- package/dist/{src → cjs}/utils/template.d.ts +48 -0
- package/dist/cjs/utils/template.d.ts.map +1 -0
- package/dist/cjs/{src/utils → utils}/template.js +100 -0
- package/dist/cjs/utils/template.js.map +1 -0
- package/dist/constants/index.d.ts.map +1 -0
- package/dist/constants/index.js.map +1 -0
- package/dist/{cjs/src/core → core}/Agent.d.ts +25 -6
- package/dist/core/Agent.d.ts.map +1 -0
- package/dist/{src/core → core}/Agent.js +122 -38
- package/dist/core/Agent.js.map +1 -0
- package/dist/core/BatchExecutor.d.ts +353 -0
- package/dist/core/BatchExecutor.d.ts.map +1 -0
- package/dist/core/BatchExecutor.js +837 -0
- package/dist/core/BatchExecutor.js.map +1 -0
- package/dist/core/BatchPromptBuilder.d.ts +86 -0
- package/dist/core/BatchPromptBuilder.d.ts.map +1 -0
- package/dist/core/BatchPromptBuilder.js +197 -0
- package/dist/core/BatchPromptBuilder.js.map +1 -0
- package/dist/core/Events.d.ts.map +1 -0
- package/dist/core/Events.js.map +1 -0
- package/dist/core/PersistenceManager.d.ts.map +1 -0
- package/dist/core/PersistenceManager.js.map +1 -0
- package/dist/{cjs/src/core → core}/PromptComposer.d.ts +1 -1
- package/dist/core/PromptComposer.d.ts.map +1 -0
- package/dist/{src/core → core}/PromptComposer.js +45 -8
- package/dist/core/PromptComposer.js.map +1 -0
- package/dist/core/ResponseEngine.d.ts.map +1 -0
- package/dist/core/ResponseEngine.js +198 -0
- package/dist/core/ResponseEngine.js.map +1 -0
- package/dist/{cjs/src/core → core}/ResponseModal.d.ts +54 -3
- package/dist/core/ResponseModal.d.ts.map +1 -0
- package/dist/{src/core → core}/ResponseModal.js +807 -121
- package/dist/core/ResponseModal.js.map +1 -0
- package/dist/{cjs/src/core → core}/ResponsePipeline.d.ts +10 -6
- package/dist/core/ResponsePipeline.d.ts.map +1 -0
- package/dist/{src/core → core}/ResponsePipeline.js +60 -25
- package/dist/core/ResponsePipeline.js.map +1 -0
- package/dist/{cjs/src/core → core}/Route.d.ts +46 -10
- package/dist/core/Route.d.ts.map +1 -0
- package/dist/core/Route.js +537 -0
- package/dist/core/Route.js.map +1 -0
- package/dist/{src/core → core}/RoutingEngine.d.ts +35 -5
- package/dist/core/RoutingEngine.d.ts.map +1 -0
- package/dist/{src/core → core}/RoutingEngine.js +343 -81
- package/dist/core/RoutingEngine.js.map +1 -0
- package/dist/{cjs/src/core → core}/SessionManager.d.ts +9 -1
- package/dist/core/SessionManager.d.ts.map +1 -0
- package/dist/{src/core → core}/SessionManager.js +27 -5
- package/dist/core/SessionManager.js.map +1 -0
- package/dist/core/Step.d.ts +170 -0
- package/dist/core/Step.d.ts.map +1 -0
- package/dist/core/Step.js +444 -0
- package/dist/core/Step.js.map +1 -0
- package/dist/core/ToolManager.d.ts +234 -0
- package/dist/core/ToolManager.d.ts.map +1 -0
- package/dist/core/ToolManager.js +1111 -0
- package/dist/core/ToolManager.js.map +1 -0
- package/dist/{cjs/src/index.d.ts → index.d.ts} +5 -3
- package/dist/index.d.ts.map +1 -0
- package/dist/{src/index.js → index.js} +4 -1
- package/dist/index.js.map +1 -0
- package/dist/providers/AnthropicProvider.d.ts.map +1 -0
- package/dist/{src/providers → providers}/AnthropicProvider.js +17 -17
- package/dist/providers/AnthropicProvider.js.map +1 -0
- package/dist/providers/GeminiProvider.d.ts.map +1 -0
- package/dist/{src/providers → providers}/GeminiProvider.js +123 -51
- package/dist/providers/GeminiProvider.js.map +1 -0
- package/dist/providers/OpenAIProvider.d.ts.map +1 -0
- package/dist/{src/providers → providers}/OpenAIProvider.js +18 -18
- package/dist/providers/OpenAIProvider.js.map +1 -0
- package/dist/providers/OpenRouterProvider.d.ts.map +1 -0
- package/dist/{src/providers → providers}/OpenRouterProvider.js +18 -18
- package/dist/providers/OpenRouterProvider.js.map +1 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/{src/types → types}/agent.d.ts +12 -4
- package/dist/types/agent.d.ts.map +1 -0
- package/dist/types/agent.js.map +1 -0
- package/dist/types/ai.d.ts.map +1 -0
- package/dist/types/ai.js.map +1 -0
- package/dist/types/history.d.ts.map +1 -0
- package/dist/types/history.js.map +1 -0
- package/dist/{src/types → types}/index.d.ts +5 -3
- package/dist/types/index.d.ts.map +1 -0
- package/dist/{src/types → types}/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/persistence.d.ts.map +1 -0
- package/dist/types/persistence.js.map +1 -0
- package/dist/{src/types → types}/route.d.ts +116 -15
- package/dist/types/route.d.ts.map +1 -0
- package/dist/{src/types → types}/route.js.map +1 -1
- package/dist/types/routing.d.ts.map +1 -0
- package/dist/{cjs/src/types → types}/routing.js.map +1 -1
- package/dist/types/schema.d.ts.map +1 -0
- package/dist/{cjs/src/types → types}/schema.js.map +1 -1
- package/dist/types/session.d.ts.map +1 -0
- package/dist/{src/types → types}/session.js.map +1 -1
- package/dist/types/template.d.ts +88 -0
- package/dist/types/template.d.ts.map +1 -0
- package/dist/{cjs/src/types → types}/template.js.map +1 -1
- package/dist/types/tool.d.ts +130 -0
- package/dist/types/tool.d.ts.map +1 -0
- package/dist/types/tool.js +16 -0
- package/dist/types/tool.js.map +1 -0
- package/dist/utils/clone.d.ts.map +1 -0
- package/dist/utils/clone.js.map +1 -0
- package/dist/utils/condition.d.ts +38 -0
- package/dist/utils/condition.d.ts.map +1 -0
- package/dist/utils/condition.js +161 -0
- package/dist/utils/condition.js.map +1 -0
- package/dist/utils/event.d.ts.map +1 -0
- package/dist/utils/event.js.map +1 -0
- package/dist/utils/history.d.ts.map +1 -0
- package/dist/utils/history.js.map +1 -0
- package/dist/utils/id.d.ts.map +1 -0
- package/dist/utils/id.js.map +1 -0
- package/dist/{src/utils → utils}/index.d.ts +3 -1
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/{src/utils → utils}/index.js +5 -1
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/json.d.ts +16 -0
- package/dist/utils/json.d.ts.map +1 -0
- package/dist/utils/json.js +43 -0
- package/dist/utils/json.js.map +1 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/{cjs/src/utils → utils}/retry.d.ts +0 -3
- package/dist/utils/retry.d.ts.map +1 -0
- package/dist/{src/utils → utils}/retry.js +5 -4
- package/dist/utils/retry.js.map +1 -0
- package/dist/utils/session.d.ts.map +1 -0
- package/dist/utils/session.js.map +1 -0
- package/dist/{cjs/src/utils → utils}/template.d.ts +48 -0
- package/dist/utils/template.d.ts.map +1 -0
- package/dist/{src/utils → utils}/template.js +98 -0
- package/dist/utils/template.js.map +1 -0
- package/docs/CONTRIBUTING.md +40 -0
- package/docs/README.md +12 -5
- package/docs/api/README.md +295 -56
- package/docs/api/overview.md +272 -31
- package/docs/architecture/data-extraction-flow.md +363 -0
- package/docs/architecture/multi-step-execution.md +243 -0
- package/docs/core/agent/README.md +120 -5
- package/docs/core/agent/session-management.md +153 -6
- package/docs/core/ai-integration/prompt-composition.md +135 -0
- package/docs/core/ai-integration/response-processing.md +261 -4
- package/docs/core/conversation-flows/data-collection.md +143 -0
- package/docs/core/conversation-flows/routes.md +132 -2
- package/docs/core/conversation-flows/step-transitions.md +132 -0
- package/docs/core/conversation-flows/steps.md +112 -0
- package/docs/core/error-handling.md +831 -0
- package/docs/core/routing/intelligent-routing.md +118 -0
- package/docs/core/tools/tool-definition.md +684 -60
- package/docs/core/tools/tool-scoping.md +244 -53
- package/docs/guides/error-handling-patterns.md +578 -0
- package/docs/guides/getting-started/README.md +423 -31
- package/docs/guides/migration/README.md +23 -0
- package/docs/guides/migration/flexible-routing-conditions.md +375 -0
- package/docs/guides/migration/multi-step-execution.md +303 -0
- package/examples/advanced-patterns/knowledge-based-agent.ts +107 -30
- package/examples/advanced-patterns/persistent-onboarding.ts +70 -48
- package/examples/advanced-patterns/route-lifecycle-hooks.ts +82 -12
- package/examples/advanced-patterns/streaming-responses.ts +2 -2
- package/examples/ai-providers/anthropic-integration.ts +13 -9
- package/examples/ai-providers/openai-integration.ts +12 -8
- package/examples/condition-patterns/function-only-conditions.ts +365 -0
- package/examples/condition-patterns/mixed-array-conditions.ts +477 -0
- package/examples/condition-patterns/route-skipif-patterns.ts +468 -0
- package/examples/condition-patterns/step-skipif-patterns.ts +0 -0
- package/examples/condition-patterns/string-only-conditions.ts +296 -0
- package/examples/conversation-flows/completion-transitions.ts +48 -7
- package/examples/core-concepts/basic-agent.ts +158 -98
- package/examples/core-concepts/schema-driven-extraction.ts +43 -16
- package/examples/core-concepts/session-management.ts +117 -29
- package/examples/integrations/database-integration.ts +6 -6
- package/examples/integrations/healthcare-integration.ts +25 -39
- package/examples/integrations/search-integration.ts +8 -8
- package/examples/integrations/server-session-management.ts +11 -11
- package/examples/persistence/database-persistence.ts +15 -15
- package/examples/persistence/memory-sessions.ts +6 -6
- package/examples/persistence/redis-persistence.ts +7 -9
- package/examples/tools/basic-tools.ts +293 -89
- package/examples/tools/data-enrichment-tools.ts +189 -79
- package/package.json +6 -4
- package/src/adapters/PrismaAdapter.ts +3 -2
- package/src/adapters/RedisAdapter.ts +3 -3
- package/src/core/Agent.ts +152 -46
- package/src/core/BatchExecutor.ts +1156 -0
- package/src/core/BatchPromptBuilder.ts +275 -0
- package/src/core/PromptComposer.ts +53 -16
- package/src/core/ResponseEngine.ts +143 -4
- package/src/core/ResponseModal.ts +1035 -137
- package/src/core/ResponsePipeline.ts +99 -65
- package/src/core/Route.ts +262 -34
- package/src/core/RoutingEngine.ts +467 -120
- package/src/core/SessionManager.ts +39 -7
- package/src/core/Step.ts +338 -32
- package/src/core/ToolManager.ts +1394 -0
- package/src/index.ts +27 -3
- package/src/providers/AnthropicProvider.ts +17 -17
- package/src/providers/GeminiProvider.ts +129 -60
- package/src/providers/OpenAIProvider.ts +18 -18
- package/src/providers/OpenRouterProvider.ts +18 -18
- package/src/types/agent.ts +12 -4
- package/src/types/index.ts +25 -3
- package/src/types/route.ts +136 -15
- package/src/types/template.ts +70 -2
- package/src/types/tool.ts +116 -25
- package/src/utils/condition.ts +190 -0
- package/src/utils/index.ts +12 -0
- package/src/utils/json.ts +46 -0
- package/src/utils/retry.ts +5 -4
- package/src/utils/template.ts +109 -0
- package/dist/cjs/src/adapters/MemoryAdapter.d.ts.map +0 -1
- package/dist/cjs/src/adapters/MemoryAdapter.js.map +0 -1
- package/dist/cjs/src/adapters/MongoAdapter.d.ts.map +0 -1
- package/dist/cjs/src/adapters/MongoAdapter.js.map +0 -1
- package/dist/cjs/src/adapters/OpenSearchAdapter.d.ts.map +0 -1
- package/dist/cjs/src/adapters/OpenSearchAdapter.js.map +0 -1
- package/dist/cjs/src/adapters/PostgreSQLAdapter.d.ts.map +0 -1
- package/dist/cjs/src/adapters/PostgreSQLAdapter.js.map +0 -1
- package/dist/cjs/src/adapters/PrismaAdapter.d.ts.map +0 -1
- package/dist/cjs/src/adapters/PrismaAdapter.js.map +0 -1
- package/dist/cjs/src/adapters/RedisAdapter.d.ts.map +0 -1
- package/dist/cjs/src/adapters/RedisAdapter.js.map +0 -1
- package/dist/cjs/src/adapters/SQLiteAdapter.d.ts.map +0 -1
- package/dist/cjs/src/adapters/SQLiteAdapter.js.map +0 -1
- package/dist/cjs/src/adapters/index.d.ts.map +0 -1
- package/dist/cjs/src/adapters/index.js.map +0 -1
- package/dist/cjs/src/constants/index.d.ts.map +0 -1
- package/dist/cjs/src/constants/index.js.map +0 -1
- package/dist/cjs/src/core/Agent.d.ts.map +0 -1
- package/dist/cjs/src/core/Agent.js.map +0 -1
- package/dist/cjs/src/core/Events.d.ts.map +0 -1
- package/dist/cjs/src/core/Events.js.map +0 -1
- package/dist/cjs/src/core/PersistenceManager.d.ts.map +0 -1
- package/dist/cjs/src/core/PersistenceManager.js.map +0 -1
- package/dist/cjs/src/core/PromptComposer.d.ts.map +0 -1
- package/dist/cjs/src/core/PromptComposer.js.map +0 -1
- package/dist/cjs/src/core/ResponseEngine.d.ts.map +0 -1
- package/dist/cjs/src/core/ResponseEngine.js +0 -84
- package/dist/cjs/src/core/ResponseEngine.js.map +0 -1
- package/dist/cjs/src/core/ResponseModal.d.ts.map +0 -1
- package/dist/cjs/src/core/ResponseModal.js.map +0 -1
- package/dist/cjs/src/core/ResponsePipeline.d.ts.map +0 -1
- package/dist/cjs/src/core/ResponsePipeline.js.map +0 -1
- package/dist/cjs/src/core/Route.d.ts.map +0 -1
- package/dist/cjs/src/core/Route.js +0 -343
- package/dist/cjs/src/core/Route.js.map +0 -1
- package/dist/cjs/src/core/RoutingEngine.d.ts.map +0 -1
- package/dist/cjs/src/core/RoutingEngine.js.map +0 -1
- package/dist/cjs/src/core/SessionManager.d.ts.map +0 -1
- package/dist/cjs/src/core/SessionManager.js.map +0 -1
- package/dist/cjs/src/core/Step.d.ts +0 -96
- package/dist/cjs/src/core/Step.d.ts.map +0 -1
- package/dist/cjs/src/core/Step.js +0 -206
- package/dist/cjs/src/core/Step.js.map +0 -1
- package/dist/cjs/src/core/ToolExecutor.d.ts +0 -45
- package/dist/cjs/src/core/ToolExecutor.d.ts.map +0 -1
- package/dist/cjs/src/core/ToolExecutor.js +0 -84
- package/dist/cjs/src/core/ToolExecutor.js.map +0 -1
- package/dist/cjs/src/index.d.ts.map +0 -1
- package/dist/cjs/src/index.js.map +0 -1
- package/dist/cjs/src/providers/AnthropicProvider.d.ts.map +0 -1
- package/dist/cjs/src/providers/AnthropicProvider.js.map +0 -1
- package/dist/cjs/src/providers/GeminiProvider.d.ts.map +0 -1
- package/dist/cjs/src/providers/GeminiProvider.js.map +0 -1
- package/dist/cjs/src/providers/OpenAIProvider.d.ts.map +0 -1
- package/dist/cjs/src/providers/OpenAIProvider.js.map +0 -1
- package/dist/cjs/src/providers/OpenRouterProvider.d.ts.map +0 -1
- package/dist/cjs/src/providers/OpenRouterProvider.js.map +0 -1
- package/dist/cjs/src/providers/index.d.ts.map +0 -1
- package/dist/cjs/src/providers/index.js.map +0 -1
- package/dist/cjs/src/types/agent.d.ts.map +0 -1
- package/dist/cjs/src/types/agent.js.map +0 -1
- package/dist/cjs/src/types/ai.d.ts.map +0 -1
- package/dist/cjs/src/types/ai.js.map +0 -1
- package/dist/cjs/src/types/history.d.ts.map +0 -1
- package/dist/cjs/src/types/history.js.map +0 -1
- package/dist/cjs/src/types/index.d.ts.map +0 -1
- package/dist/cjs/src/types/index.js.map +0 -1
- package/dist/cjs/src/types/persistence.d.ts.map +0 -1
- package/dist/cjs/src/types/persistence.js.map +0 -1
- package/dist/cjs/src/types/route.d.ts.map +0 -1
- package/dist/cjs/src/types/routing.d.ts.map +0 -1
- package/dist/cjs/src/types/schema.d.ts.map +0 -1
- package/dist/cjs/src/types/session.d.ts.map +0 -1
- package/dist/cjs/src/types/session.js.map +0 -1
- package/dist/cjs/src/types/template.d.ts +0 -30
- package/dist/cjs/src/types/template.d.ts.map +0 -1
- package/dist/cjs/src/types/tool.d.ts +0 -60
- package/dist/cjs/src/types/tool.d.ts.map +0 -1
- package/dist/cjs/src/types/tool.js +0 -6
- package/dist/cjs/src/types/tool.js.map +0 -1
- package/dist/cjs/src/utils/clone.d.ts.map +0 -1
- package/dist/cjs/src/utils/clone.js.map +0 -1
- package/dist/cjs/src/utils/event.d.ts.map +0 -1
- package/dist/cjs/src/utils/event.js.map +0 -1
- package/dist/cjs/src/utils/history.d.ts.map +0 -1
- package/dist/cjs/src/utils/history.js.map +0 -1
- package/dist/cjs/src/utils/id.d.ts.map +0 -1
- package/dist/cjs/src/utils/id.js.map +0 -1
- package/dist/cjs/src/utils/index.d.ts.map +0 -1
- package/dist/cjs/src/utils/index.js.map +0 -1
- package/dist/cjs/src/utils/logger.d.ts.map +0 -1
- package/dist/cjs/src/utils/logger.js.map +0 -1
- package/dist/cjs/src/utils/retry.d.ts.map +0 -1
- package/dist/cjs/src/utils/retry.js.map +0 -1
- package/dist/cjs/src/utils/session.d.ts.map +0 -1
- package/dist/cjs/src/utils/session.js.map +0 -1
- package/dist/cjs/src/utils/template.d.ts.map +0 -1
- package/dist/cjs/src/utils/template.js.map +0 -1
- package/dist/src/adapters/MemoryAdapter.js.map +0 -1
- package/dist/src/adapters/MongoAdapter.js.map +0 -1
- package/dist/src/adapters/OpenSearchAdapter.js.map +0 -1
- package/dist/src/adapters/PostgreSQLAdapter.js.map +0 -1
- package/dist/src/adapters/PrismaAdapter.js.map +0 -1
- package/dist/src/adapters/RedisAdapter.js.map +0 -1
- package/dist/src/adapters/SQLiteAdapter.js.map +0 -1
- package/dist/src/adapters/index.js.map +0 -1
- package/dist/src/constants/index.js.map +0 -1
- package/dist/src/core/Agent.d.ts.map +0 -1
- package/dist/src/core/Agent.js.map +0 -1
- package/dist/src/core/Events.js.map +0 -1
- package/dist/src/core/PersistenceManager.js.map +0 -1
- package/dist/src/core/PromptComposer.d.ts.map +0 -1
- package/dist/src/core/PromptComposer.js.map +0 -1
- package/dist/src/core/ResponseEngine.js +0 -80
- package/dist/src/core/ResponseEngine.js.map +0 -1
- package/dist/src/core/ResponseModal.d.ts.map +0 -1
- package/dist/src/core/ResponseModal.js.map +0 -1
- package/dist/src/core/ResponsePipeline.d.ts.map +0 -1
- package/dist/src/core/ResponsePipeline.js.map +0 -1
- package/dist/src/core/Route.d.ts.map +0 -1
- package/dist/src/core/Route.js +0 -339
- package/dist/src/core/Route.js.map +0 -1
- package/dist/src/core/RoutingEngine.d.ts.map +0 -1
- package/dist/src/core/RoutingEngine.js.map +0 -1
- package/dist/src/core/SessionManager.d.ts.map +0 -1
- package/dist/src/core/SessionManager.js.map +0 -1
- package/dist/src/core/Step.d.ts +0 -96
- package/dist/src/core/Step.d.ts.map +0 -1
- package/dist/src/core/Step.js +0 -202
- package/dist/src/core/Step.js.map +0 -1
- package/dist/src/core/ToolExecutor.d.ts +0 -45
- package/dist/src/core/ToolExecutor.d.ts.map +0 -1
- package/dist/src/core/ToolExecutor.js +0 -80
- package/dist/src/core/ToolExecutor.js.map +0 -1
- package/dist/src/index.d.ts.map +0 -1
- package/dist/src/index.js.map +0 -1
- package/dist/src/providers/AnthropicProvider.js.map +0 -1
- package/dist/src/providers/GeminiProvider.js.map +0 -1
- package/dist/src/providers/OpenAIProvider.js.map +0 -1
- package/dist/src/providers/OpenRouterProvider.js.map +0 -1
- package/dist/src/providers/index.js.map +0 -1
- package/dist/src/types/agent.d.ts.map +0 -1
- package/dist/src/types/agent.js.map +0 -1
- package/dist/src/types/history.js.map +0 -1
- package/dist/src/types/index.js.map +0 -1
- package/dist/src/types/persistence.js.map +0 -1
- package/dist/src/types/route.d.ts.map +0 -1
- package/dist/src/types/template.d.ts +0 -30
- package/dist/src/types/template.d.ts.map +0 -1
- package/dist/src/types/tool.d.ts +0 -60
- package/dist/src/types/tool.d.ts.map +0 -1
- package/dist/src/types/tool.js +0 -5
- package/dist/src/types/tool.js.map +0 -1
- package/dist/src/utils/clone.js.map +0 -1
- package/dist/src/utils/event.js.map +0 -1
- package/dist/src/utils/history.js.map +0 -1
- package/dist/src/utils/id.js.map +0 -1
- package/dist/src/utils/index.d.ts.map +0 -1
- package/dist/src/utils/index.js.map +0 -1
- package/dist/src/utils/logger.js.map +0 -1
- package/dist/src/utils/retry.d.ts.map +0 -1
- package/dist/src/utils/retry.js.map +0 -1
- package/dist/src/utils/session.js.map +0 -1
- package/dist/src/utils/template.d.ts.map +0 -1
- package/dist/src/utils/template.js.map +0 -1
- package/docs/core/tools/tool-execution.md +0 -815
- package/src/core/ToolExecutor.ts +0 -126
- /package/dist/{cjs/src/adapters → adapters}/MemoryAdapter.d.ts +0 -0
- /package/dist/{src/adapters → adapters}/MemoryAdapter.js +0 -0
- /package/dist/{cjs/src/adapters → adapters}/MongoAdapter.d.ts +0 -0
- /package/dist/{src/adapters → adapters}/MongoAdapter.js +0 -0
- /package/dist/{cjs/src/adapters → adapters}/OpenSearchAdapter.d.ts +0 -0
- /package/dist/{src/adapters → adapters}/OpenSearchAdapter.js +0 -0
- /package/dist/{cjs/src/adapters → adapters}/PostgreSQLAdapter.d.ts +0 -0
- /package/dist/{src/adapters → adapters}/PostgreSQLAdapter.js +0 -0
- /package/dist/{cjs/src/adapters → adapters}/PrismaAdapter.d.ts +0 -0
- /package/dist/{cjs/src/adapters → adapters}/RedisAdapter.d.ts +0 -0
- /package/dist/{cjs/src/adapters → adapters}/SQLiteAdapter.d.ts +0 -0
- /package/dist/{src/adapters → adapters}/SQLiteAdapter.js +0 -0
- /package/dist/{cjs/src/adapters → adapters}/index.d.ts +0 -0
- /package/dist/{src/adapters → adapters}/index.js +0 -0
- /package/dist/{src → cjs}/adapters/MemoryAdapter.d.ts +0 -0
- /package/dist/{src → cjs}/adapters/MemoryAdapter.d.ts.map +0 -0
- /package/dist/cjs/{src/adapters → adapters}/MemoryAdapter.js +0 -0
- /package/dist/{src → cjs}/adapters/MongoAdapter.d.ts +0 -0
- /package/dist/{src → cjs}/adapters/MongoAdapter.d.ts.map +0 -0
- /package/dist/cjs/{src/adapters → adapters}/MongoAdapter.js +0 -0
- /package/dist/{src → cjs}/adapters/OpenSearchAdapter.d.ts +0 -0
- /package/dist/{src → cjs}/adapters/OpenSearchAdapter.d.ts.map +0 -0
- /package/dist/cjs/{src/adapters → adapters}/OpenSearchAdapter.js +0 -0
- /package/dist/{src → cjs}/adapters/PostgreSQLAdapter.d.ts +0 -0
- /package/dist/{src → cjs}/adapters/PostgreSQLAdapter.d.ts.map +0 -0
- /package/dist/cjs/{src/adapters → adapters}/PostgreSQLAdapter.js +0 -0
- /package/dist/{src → cjs}/adapters/PrismaAdapter.d.ts +0 -0
- /package/dist/{src → cjs}/adapters/RedisAdapter.d.ts +0 -0
- /package/dist/{src → cjs}/adapters/RedisAdapter.d.ts.map +0 -0
- /package/dist/{src → cjs}/adapters/SQLiteAdapter.d.ts +0 -0
- /package/dist/{src → cjs}/adapters/SQLiteAdapter.d.ts.map +0 -0
- /package/dist/cjs/{src/adapters → adapters}/SQLiteAdapter.js +0 -0
- /package/dist/{src → cjs}/adapters/index.d.ts +0 -0
- /package/dist/{src → cjs}/adapters/index.d.ts.map +0 -0
- /package/dist/cjs/{src/adapters → adapters}/index.js +0 -0
- /package/dist/cjs/{src/constants → constants}/index.d.ts +0 -0
- /package/dist/{src → cjs}/constants/index.d.ts.map +0 -0
- /package/dist/cjs/{src/constants → constants}/index.js +0 -0
- /package/dist/cjs/{src/core → core}/Events.d.ts +0 -0
- /package/dist/{src → cjs}/core/Events.d.ts.map +0 -0
- /package/dist/cjs/{src/core → core}/Events.js +0 -0
- /package/dist/cjs/{src/core → core}/PersistenceManager.d.ts +0 -0
- /package/dist/{src → cjs}/core/PersistenceManager.d.ts.map +0 -0
- /package/dist/cjs/{src/core → core}/PersistenceManager.js +0 -0
- /package/dist/cjs/{src/core → core}/ResponseEngine.d.ts +0 -0
- /package/dist/cjs/{src/providers → providers}/AnthropicProvider.d.ts +0 -0
- /package/dist/{src → cjs}/providers/AnthropicProvider.d.ts.map +0 -0
- /package/dist/cjs/{src/providers → providers}/GeminiProvider.d.ts +0 -0
- /package/dist/cjs/{src/providers → providers}/OpenAIProvider.d.ts +0 -0
- /package/dist/{src → cjs}/providers/OpenAIProvider.d.ts.map +0 -0
- /package/dist/cjs/{src/providers → providers}/OpenRouterProvider.d.ts +0 -0
- /package/dist/{src → cjs}/providers/OpenRouterProvider.d.ts.map +0 -0
- /package/dist/cjs/{src/providers → providers}/index.d.ts +0 -0
- /package/dist/{src → cjs}/providers/index.d.ts.map +0 -0
- /package/dist/cjs/{src/providers → providers}/index.js +0 -0
- /package/dist/cjs/{src/types → types}/agent.js +0 -0
- /package/dist/cjs/{src/types → types}/ai.d.ts +0 -0
- /package/dist/{src → cjs}/types/ai.d.ts.map +0 -0
- /package/dist/cjs/{src/types → types}/ai.js +0 -0
- /package/dist/cjs/{src/types → types}/history.d.ts +0 -0
- /package/dist/{src → cjs}/types/history.d.ts.map +0 -0
- /package/dist/cjs/{src/types → types}/history.js +0 -0
- /package/dist/cjs/{src/types → types}/persistence.d.ts +0 -0
- /package/dist/{src → cjs}/types/persistence.d.ts.map +0 -0
- /package/dist/cjs/{src/types → types}/persistence.js +0 -0
- /package/dist/cjs/{src/types → types}/route.js +0 -0
- /package/dist/cjs/{src/types → types}/routing.d.ts +0 -0
- /package/dist/{src → cjs}/types/routing.d.ts.map +0 -0
- /package/dist/cjs/{src/types → types}/routing.js +0 -0
- /package/dist/{src → cjs}/types/routing.js.map +0 -0
- /package/dist/cjs/{src/types → types}/schema.d.ts +0 -0
- /package/dist/{src → cjs}/types/schema.d.ts.map +0 -0
- /package/dist/cjs/{src/types → types}/schema.js +0 -0
- /package/dist/{src → cjs}/types/schema.js.map +0 -0
- /package/dist/cjs/{src/types → types}/session.d.ts +0 -0
- /package/dist/{src → cjs}/types/session.d.ts.map +0 -0
- /package/dist/cjs/{src/types → types}/session.js +0 -0
- /package/dist/cjs/{src/types → types}/template.js +0 -0
- /package/dist/{src → cjs}/types/template.js.map +0 -0
- /package/dist/cjs/{src/utils → utils}/clone.d.ts +0 -0
- /package/dist/{src → cjs}/utils/clone.d.ts.map +0 -0
- /package/dist/cjs/{src/utils → utils}/clone.js +0 -0
- /package/dist/cjs/{src/utils → utils}/event.d.ts +0 -0
- /package/dist/{src → cjs}/utils/event.d.ts.map +0 -0
- /package/dist/cjs/{src/utils → utils}/event.js +0 -0
- /package/dist/cjs/{src/utils → utils}/history.d.ts +0 -0
- /package/dist/{src → cjs}/utils/history.d.ts.map +0 -0
- /package/dist/cjs/{src/utils → utils}/history.js +0 -0
- /package/dist/cjs/{src/utils → utils}/id.d.ts +0 -0
- /package/dist/{src → cjs}/utils/id.d.ts.map +0 -0
- /package/dist/cjs/{src/utils → utils}/id.js +0 -0
- /package/dist/cjs/{src/utils → utils}/logger.d.ts +0 -0
- /package/dist/{src → cjs}/utils/logger.d.ts.map +0 -0
- /package/dist/cjs/{src/utils → utils}/logger.js +0 -0
- /package/dist/cjs/{src/utils → utils}/session.d.ts +0 -0
- /package/dist/{src → cjs}/utils/session.d.ts.map +0 -0
- /package/dist/cjs/{src/utils → utils}/session.js +0 -0
- /package/dist/{src/constants → constants}/index.d.ts +0 -0
- /package/dist/{src/constants → constants}/index.js +0 -0
- /package/dist/{src/core → core}/Events.d.ts +0 -0
- /package/dist/{src/core → core}/Events.js +0 -0
- /package/dist/{src/core → core}/PersistenceManager.d.ts +0 -0
- /package/dist/{src/core → core}/PersistenceManager.js +0 -0
- /package/dist/{src/core → core}/ResponseEngine.d.ts +0 -0
- /package/dist/{src/providers → providers}/AnthropicProvider.d.ts +0 -0
- /package/dist/{src/providers → providers}/GeminiProvider.d.ts +0 -0
- /package/dist/{src/providers → providers}/OpenAIProvider.d.ts +0 -0
- /package/dist/{src/providers → providers}/OpenRouterProvider.d.ts +0 -0
- /package/dist/{src/providers → providers}/index.d.ts +0 -0
- /package/dist/{src/providers → providers}/index.js +0 -0
- /package/dist/{src/types → types}/agent.js +0 -0
- /package/dist/{src/types → types}/ai.d.ts +0 -0
- /package/dist/{src/types → types}/ai.js +0 -0
- /package/dist/{src/types → types}/history.d.ts +0 -0
- /package/dist/{src/types → types}/history.js +0 -0
- /package/dist/{src/types → types}/persistence.d.ts +0 -0
- /package/dist/{src/types → types}/persistence.js +0 -0
- /package/dist/{src/types → types}/route.js +0 -0
- /package/dist/{src/types → types}/routing.d.ts +0 -0
- /package/dist/{src/types → types}/routing.js +0 -0
- /package/dist/{src/types → types}/schema.d.ts +0 -0
- /package/dist/{src/types → types}/schema.js +0 -0
- /package/dist/{src/types → types}/session.d.ts +0 -0
- /package/dist/{src/types → types}/session.js +0 -0
- /package/dist/{src/types → types}/template.js +0 -0
- /package/dist/{src/utils → utils}/clone.d.ts +0 -0
- /package/dist/{src/utils → utils}/clone.js +0 -0
- /package/dist/{src/utils → utils}/event.d.ts +0 -0
- /package/dist/{src/utils → utils}/event.js +0 -0
- /package/dist/{src/utils → utils}/history.d.ts +0 -0
- /package/dist/{src/utils → utils}/history.js +0 -0
- /package/dist/{src/utils → utils}/id.d.ts +0 -0
- /package/dist/{src/utils → utils}/id.js +0 -0
- /package/dist/{src/utils → utils}/logger.d.ts +0 -0
- /package/dist/{src/utils → utils}/logger.js +0 -0
- /package/dist/{src/utils → utils}/session.d.ts +0 -0
- /package/dist/{src/utils → utils}/session.js +0 -0
|
@@ -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,11 +65,35 @@ 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> {
|
|
71
72
|
constructor(private readonly options?: RoutingEngineOptions) { }
|
|
72
73
|
|
|
74
|
+
/**
|
|
75
|
+
* Enter a route if not already in it, merging initial data
|
|
76
|
+
* @private
|
|
77
|
+
*/
|
|
78
|
+
private enterRouteIfNeeded(
|
|
79
|
+
session: SessionState<TData>,
|
|
80
|
+
route: Route<TContext, TData>
|
|
81
|
+
): SessionState<TData> {
|
|
82
|
+
if (!session.currentRoute || session.currentRoute.id !== route.id) {
|
|
83
|
+
let updatedSession = enterRoute(session, route.id, route.title);
|
|
84
|
+
if (route.initialData) {
|
|
85
|
+
updatedSession = mergeCollected(updatedSession, route.initialData);
|
|
86
|
+
logger.debug(
|
|
87
|
+
`[RoutingEngine] Merged initial data for route ${route.title}:`,
|
|
88
|
+
route.initialData
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
logger.debug(`[RoutingEngine] Entered route: ${route.title}`);
|
|
92
|
+
return updatedSession;
|
|
93
|
+
}
|
|
94
|
+
return session;
|
|
95
|
+
}
|
|
96
|
+
|
|
73
97
|
/**
|
|
74
98
|
* Optimized decision for single-route scenarios
|
|
75
99
|
* Skips route scoring and only does step selection
|
|
@@ -94,35 +118,28 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
|
|
|
94
118
|
const { route, session, history, agentOptions, provider, context, signal } =
|
|
95
119
|
params;
|
|
96
120
|
|
|
97
|
-
let updatedSession = session;
|
|
98
121
|
const selectedRoute = route;
|
|
99
122
|
|
|
100
|
-
//
|
|
101
|
-
const
|
|
123
|
+
// Enter route if not already in it (this may merge initial data)
|
|
124
|
+
const updatedSession = this.enterRouteIfNeeded(session, route);
|
|
102
125
|
|
|
103
|
-
//
|
|
104
|
-
|
|
105
|
-
updatedSession = enterRoute(session, route.id, route.title);
|
|
106
|
-
if (route.initialData) {
|
|
107
|
-
updatedSession = mergeCollected(updatedSession, route.initialData);
|
|
108
|
-
logger.debug(
|
|
109
|
-
`[RoutingEngine] Single-route: Merged initial data:`,
|
|
110
|
-
route.initialData
|
|
111
|
-
);
|
|
112
|
-
}
|
|
113
|
-
logger.debug(
|
|
114
|
-
`[RoutingEngine] Single-route: Entered route: ${route.title}`
|
|
115
|
-
);
|
|
116
|
-
}
|
|
126
|
+
// Check if this single route is complete (use updated session data)
|
|
127
|
+
const completedRoutes = route.isComplete(updatedSession.data || {}) ? [route] : [];
|
|
117
128
|
|
|
118
|
-
// 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
|
+
});
|
|
119
136
|
const currentStep = updatedSession.currentStep
|
|
120
137
|
? route.getStep(updatedSession.currentStep.id)
|
|
121
138
|
: undefined;
|
|
122
|
-
const candidates = this.
|
|
139
|
+
const candidates = await this.getCandidateStepsWithConditions(
|
|
123
140
|
route,
|
|
124
141
|
currentStep,
|
|
125
|
-
|
|
142
|
+
templateContext
|
|
126
143
|
);
|
|
127
144
|
|
|
128
145
|
if (candidates.length === 0) {
|
|
@@ -130,12 +147,13 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
|
|
|
130
147
|
return { selectedRoute, session: updatedSession };
|
|
131
148
|
}
|
|
132
149
|
|
|
133
|
-
// If only one candidate, check if
|
|
150
|
+
// If only one candidate, check if it's a completion marker
|
|
134
151
|
if (candidates.length === 1) {
|
|
135
|
-
const
|
|
136
|
-
|
|
152
|
+
const candidate = candidates[0];
|
|
153
|
+
|
|
154
|
+
if (candidate.isRouteComplete) {
|
|
137
155
|
logger.debug(
|
|
138
|
-
`[RoutingEngine] Single-route: Route complete - all
|
|
156
|
+
`[RoutingEngine] Single-route: Route complete - all required fields collected or END_ROUTE reached`
|
|
139
157
|
);
|
|
140
158
|
// Don't return a selectedStep when route is complete - there's no step to enter
|
|
141
159
|
return {
|
|
@@ -147,11 +165,11 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
|
|
|
147
165
|
};
|
|
148
166
|
} else {
|
|
149
167
|
logger.debug(
|
|
150
|
-
`[RoutingEngine] Single-route: Only one valid step: ${
|
|
168
|
+
`[RoutingEngine] Single-route: Only one valid step: ${candidate.step.id}`
|
|
151
169
|
);
|
|
152
170
|
return {
|
|
153
171
|
selectedRoute,
|
|
154
|
-
selectedStep:
|
|
172
|
+
selectedStep: candidate.step,
|
|
155
173
|
session: updatedSession,
|
|
156
174
|
isRouteComplete: false,
|
|
157
175
|
completedRoutes,
|
|
@@ -159,8 +177,35 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
|
|
|
159
177
|
}
|
|
160
178
|
}
|
|
161
179
|
|
|
180
|
+
// No candidates means route is likely complete or has no valid next steps
|
|
181
|
+
if (candidates.length === 0) {
|
|
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
|
+
);
|
|
187
|
+
return {
|
|
188
|
+
selectedRoute,
|
|
189
|
+
selectedStep: undefined,
|
|
190
|
+
session: updatedSession,
|
|
191
|
+
isRouteComplete: dataComplete,
|
|
192
|
+
completedRoutes,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
|
|
162
196
|
// Multiple candidates - use AI to select best step
|
|
163
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
|
+
|
|
164
209
|
const stepPrompt = await this.buildStepSelectionPrompt({
|
|
165
210
|
route,
|
|
166
211
|
currentStep,
|
|
@@ -171,10 +216,13 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
|
|
|
171
216
|
agentOptions,
|
|
172
217
|
context,
|
|
173
218
|
session: updatedSession,
|
|
219
|
+
stepConditionContext,
|
|
220
|
+
includeEndRoute: hasCompletionOption,
|
|
174
221
|
});
|
|
175
222
|
|
|
176
223
|
const stepSchema = this.buildStepSelectionSchema(
|
|
177
|
-
candidates.map((c) => c.step)
|
|
224
|
+
candidates.filter(c => !c.isRouteComplete).map((c) => c.step),
|
|
225
|
+
hasCompletionOption
|
|
178
226
|
);
|
|
179
227
|
|
|
180
228
|
const stepResult = await provider.generateMessage<
|
|
@@ -196,6 +244,25 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
|
|
|
196
244
|
});
|
|
197
245
|
|
|
198
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
|
+
|
|
199
266
|
const selectedStep = candidates.find((c) => c.step.id === selectedStepId);
|
|
200
267
|
|
|
201
268
|
if (selectedStep) {
|
|
@@ -221,24 +288,26 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
|
|
|
221
288
|
}
|
|
222
289
|
|
|
223
290
|
/**
|
|
224
|
-
* 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
|
|
225
292
|
* @private
|
|
226
293
|
*/
|
|
227
|
-
private
|
|
294
|
+
private async findFirstValidStepRecursiveWithConditions(
|
|
228
295
|
currentStep: Step<TContext, TData>,
|
|
229
|
-
|
|
296
|
+
templateContext: TemplateContext<TContext, TData>,
|
|
230
297
|
visited: Set<string>
|
|
231
|
-
): {
|
|
298
|
+
): Promise<{
|
|
232
299
|
step?: Step<TContext, TData>;
|
|
233
300
|
isRouteComplete?: boolean;
|
|
234
|
-
|
|
301
|
+
aiContextStrings?: string[];
|
|
302
|
+
}> {
|
|
235
303
|
// Prevent infinite loops
|
|
236
304
|
if (visited.has(currentStep.id)) {
|
|
237
|
-
return {};
|
|
305
|
+
return { aiContextStrings: [] };
|
|
238
306
|
}
|
|
239
307
|
visited.add(currentStep.id);
|
|
240
308
|
|
|
241
309
|
const transitions = currentStep.getTransitions();
|
|
310
|
+
const allAiContextStrings: string[] = [];
|
|
242
311
|
|
|
243
312
|
for (const transition of transitions) {
|
|
244
313
|
const target = transition;
|
|
@@ -248,19 +317,25 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
|
|
|
248
317
|
// Found END_ROUTE - route is complete
|
|
249
318
|
return {
|
|
250
319
|
isRouteComplete: true,
|
|
320
|
+
aiContextStrings: allAiContextStrings,
|
|
251
321
|
};
|
|
252
322
|
}
|
|
253
323
|
|
|
254
324
|
if (!target) continue;
|
|
255
325
|
|
|
326
|
+
// Evaluate skipIf condition using new system
|
|
327
|
+
const skipResult = await target.evaluateSkipIf(templateContext);
|
|
328
|
+
allAiContextStrings.push(...skipResult.aiContextStrings);
|
|
329
|
+
|
|
256
330
|
// If target should NOT be skipped, we found our step
|
|
257
|
-
if (!
|
|
331
|
+
if (!skipResult.shouldSkip) {
|
|
258
332
|
logger.debug(
|
|
259
333
|
`[RoutingEngine] Found valid step after skipping: ${target.id}`
|
|
260
334
|
);
|
|
261
335
|
return {
|
|
262
336
|
step: target,
|
|
263
337
|
isRouteComplete: false,
|
|
338
|
+
aiContextStrings: allAiContextStrings,
|
|
264
339
|
};
|
|
265
340
|
}
|
|
266
341
|
|
|
@@ -268,36 +343,69 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
|
|
|
268
343
|
logger.debug(
|
|
269
344
|
`[RoutingEngine] Skipping step ${target.id} (skipIf condition met), continuing traversal...`
|
|
270
345
|
);
|
|
271
|
-
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
|
+
}
|
|
272
352
|
|
|
273
353
|
// If we found something (a valid step or END_ROUTE), return it
|
|
274
354
|
if (result.step || result.isRouteComplete) {
|
|
275
|
-
return
|
|
355
|
+
return {
|
|
356
|
+
...result,
|
|
357
|
+
aiContextStrings: allAiContextStrings,
|
|
358
|
+
};
|
|
276
359
|
}
|
|
277
360
|
}
|
|
278
361
|
|
|
279
362
|
// No valid steps or END_ROUTE found in this branch
|
|
280
|
-
return {};
|
|
363
|
+
return { aiContextStrings: allAiContextStrings };
|
|
281
364
|
}
|
|
282
365
|
|
|
366
|
+
|
|
367
|
+
|
|
283
368
|
/**
|
|
284
|
-
* Identify valid next candidate steps
|
|
369
|
+
* Identify valid next candidate steps using new condition evaluation system
|
|
285
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
|
|
286
373
|
*/
|
|
287
|
-
|
|
374
|
+
async getCandidateStepsWithConditions(
|
|
288
375
|
route: Route<TContext, TData>,
|
|
289
376
|
currentStep: Step<TContext, TData> | undefined,
|
|
290
|
-
|
|
291
|
-
): CandidateStep<TContext, TData>[] {
|
|
377
|
+
templateContext: TemplateContext<TContext, TData>
|
|
378
|
+
): Promise<CandidateStep<TContext, TData>[]> {
|
|
292
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);
|
|
293
384
|
|
|
294
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
|
+
|
|
295
401
|
const initialStep = route.initialStep;
|
|
296
|
-
|
|
402
|
+
const skipResult = await initialStep.evaluateSkipIf(templateContext);
|
|
403
|
+
|
|
404
|
+
if (skipResult.shouldSkip) {
|
|
297
405
|
// Initial step should be skipped - recursively traverse to find first non-skipped step or END_ROUTE
|
|
298
|
-
const result = this.
|
|
406
|
+
const result = await this.findFirstValidStepRecursiveWithConditions(
|
|
299
407
|
initialStep,
|
|
300
|
-
|
|
408
|
+
templateContext,
|
|
301
409
|
new Set<string>()
|
|
302
410
|
);
|
|
303
411
|
|
|
@@ -327,6 +435,68 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
|
|
|
327
435
|
return candidates;
|
|
328
436
|
}
|
|
329
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
|
|
330
500
|
const transitions = currentStep.getTransitions();
|
|
331
501
|
let hasEndRoute = false;
|
|
332
502
|
|
|
@@ -341,15 +511,17 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
|
|
|
341
511
|
|
|
342
512
|
if (!target) continue;
|
|
343
513
|
|
|
344
|
-
|
|
514
|
+
const skipResult = await target.evaluateSkipIf(templateContext);
|
|
515
|
+
|
|
516
|
+
if (skipResult.shouldSkip) {
|
|
345
517
|
logger.debug(
|
|
346
518
|
`[RoutingEngine] Skipping step ${target.id} (skipIf condition met)`
|
|
347
519
|
);
|
|
348
520
|
|
|
349
521
|
// Recursively traverse to find next valid step or END_ROUTE
|
|
350
|
-
const result = this.
|
|
522
|
+
const result = await this.findFirstValidStepRecursiveWithConditions(
|
|
351
523
|
target,
|
|
352
|
-
|
|
524
|
+
templateContext,
|
|
353
525
|
new Set<string>([currentStep.id]) // Already visited current step
|
|
354
526
|
);
|
|
355
527
|
|
|
@@ -388,7 +560,8 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
|
|
|
388
560
|
}
|
|
389
561
|
|
|
390
562
|
// Otherwise, stay in current step if it's still valid
|
|
391
|
-
|
|
563
|
+
const currentSkipResult = await currentStep.evaluateSkipIf(templateContext);
|
|
564
|
+
if (!currentSkipResult.shouldSkip) {
|
|
392
565
|
candidates.push({
|
|
393
566
|
step: currentStep,
|
|
394
567
|
isRouteComplete: hasEndRoute || false,
|
|
@@ -464,32 +637,67 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
|
|
|
464
637
|
}
|
|
465
638
|
|
|
466
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`);
|
|
467
658
|
|
|
468
659
|
let activeRouteSteps: Step<TContext, TData>[] | undefined;
|
|
469
660
|
let activeRoute: Route<TContext, TData> | undefined;
|
|
470
661
|
let isRouteComplete = false;
|
|
662
|
+
let updatedSession = session;
|
|
471
663
|
|
|
472
664
|
if (session.currentRoute) {
|
|
473
|
-
activeRoute =
|
|
665
|
+
activeRoute = eligibleRoutes.find((r) => r.id === session.currentRoute?.id);
|
|
474
666
|
if (activeRoute) {
|
|
475
667
|
const currentStep = session.currentStep
|
|
476
668
|
? activeRoute.getStep(session.currentStep.id)
|
|
477
669
|
: undefined;
|
|
478
|
-
const
|
|
670
|
+
const activeTemplateContext = createTemplateContext({
|
|
671
|
+
...templateContext,
|
|
672
|
+
session: updatedSession,
|
|
673
|
+
data: updatedSession.data
|
|
674
|
+
});
|
|
675
|
+
const candidates = await this.getCandidateStepsWithConditions(
|
|
479
676
|
activeRoute,
|
|
480
677
|
currentStep,
|
|
481
|
-
|
|
678
|
+
activeTemplateContext
|
|
482
679
|
);
|
|
483
680
|
|
|
484
681
|
// Check if route is complete
|
|
682
|
+
// getCandidateStepsWithConditions now automatically handles completion when required fields are collected
|
|
485
683
|
if (candidates.length === 1 && candidates[0].isRouteComplete) {
|
|
486
684
|
isRouteComplete = true;
|
|
487
685
|
logger.debug(
|
|
488
|
-
`[RoutingEngine] Route ${activeRoute.title} is complete - all
|
|
686
|
+
`[RoutingEngine] Route ${activeRoute.title} is complete - all required fields collected or END_ROUTE reached`
|
|
489
687
|
);
|
|
490
688
|
// Don't include steps in routing if route is complete
|
|
491
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;
|
|
492
699
|
} else {
|
|
700
|
+
// Multiple candidates or single non-complete candidate
|
|
493
701
|
activeRouteSteps = candidates.map((c) => c.step);
|
|
494
702
|
logger.debug(
|
|
495
703
|
`[RoutingEngine] Found ${activeRouteSteps.length} candidate steps for active route`
|
|
@@ -499,19 +707,20 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
|
|
|
499
707
|
}
|
|
500
708
|
|
|
501
709
|
const routingSchema = this.buildDynamicRoutingSchema(
|
|
502
|
-
|
|
710
|
+
eligibleRoutes,
|
|
503
711
|
undefined,
|
|
504
712
|
activeRouteSteps
|
|
505
713
|
);
|
|
506
714
|
|
|
507
715
|
const routingPrompt = await this.buildRoutingPrompt({
|
|
508
716
|
history,
|
|
509
|
-
routes,
|
|
717
|
+
routes: eligibleRoutes,
|
|
510
718
|
lastMessage: lastUserMessage,
|
|
511
719
|
agentOptions,
|
|
512
720
|
session,
|
|
513
721
|
activeRouteSteps,
|
|
514
722
|
context,
|
|
723
|
+
routeConditionContext, // Pass AI context strings from route conditions
|
|
515
724
|
});
|
|
516
725
|
|
|
517
726
|
const routingResult = await provider.generateMessage<
|
|
@@ -531,25 +740,34 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
|
|
|
531
740
|
let selectedRoute: Route<TContext, TData> | undefined;
|
|
532
741
|
let selectedStep: Step<TContext, TData> | undefined;
|
|
533
742
|
let responseDirectives: string[] | undefined;
|
|
534
|
-
let updatedSession = session;
|
|
535
743
|
|
|
536
744
|
if (routingResult.structured?.routes) {
|
|
537
745
|
// Use cross-route completion evaluation to select optimal route
|
|
538
746
|
const optimalRoute = this.selectOptimalRoute(
|
|
539
|
-
|
|
747
|
+
eligibleRoutes,
|
|
540
748
|
updatedSession.data || {},
|
|
541
749
|
routingResult.structured.routes
|
|
542
750
|
);
|
|
543
751
|
|
|
544
|
-
//
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
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
|
+
}
|
|
553
771
|
|
|
554
772
|
responseDirectives = routingResult.structured.responseDirectives;
|
|
555
773
|
|
|
@@ -573,27 +791,7 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
|
|
|
573
791
|
|
|
574
792
|
if (selectedRoute) {
|
|
575
793
|
logger.debug(`[RoutingEngine] Selected route: ${selectedRoute.title}`);
|
|
576
|
-
|
|
577
|
-
!session.currentRoute ||
|
|
578
|
-
session.currentRoute.id !== selectedRoute.id
|
|
579
|
-
) {
|
|
580
|
-
updatedSession = enterRoute(
|
|
581
|
-
session,
|
|
582
|
-
selectedRoute.id,
|
|
583
|
-
selectedRoute.title
|
|
584
|
-
);
|
|
585
|
-
if (selectedRoute.initialData) {
|
|
586
|
-
updatedSession = mergeCollected(
|
|
587
|
-
updatedSession,
|
|
588
|
-
selectedRoute.initialData
|
|
589
|
-
);
|
|
590
|
-
logger.debug(
|
|
591
|
-
`[RoutingEngine] Merged initial data:`,
|
|
592
|
-
selectedRoute.initialData
|
|
593
|
-
);
|
|
594
|
-
}
|
|
595
|
-
logger.debug(`[RoutingEngine] Entered route: ${selectedRoute.title}`);
|
|
596
|
-
}
|
|
794
|
+
updatedSession = this.enterRouteIfNeeded(updatedSession, selectedRoute);
|
|
597
795
|
}
|
|
598
796
|
}
|
|
599
797
|
|
|
@@ -607,6 +805,72 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
|
|
|
607
805
|
};
|
|
608
806
|
}
|
|
609
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
|
+
|
|
610
874
|
/**
|
|
611
875
|
* Evaluate all routes for completion based on collected data
|
|
612
876
|
* @param routes - All available routes
|
|
@@ -637,6 +901,7 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
|
|
|
637
901
|
/**
|
|
638
902
|
* Find the best route to continue based on completion status and user intent
|
|
639
903
|
* Prioritizes routes that are partially complete but not finished
|
|
904
|
+
* IMPORTANT: Completed routes are excluded to prevent re-entering finished tasks
|
|
640
905
|
* @param routes - All available routes
|
|
641
906
|
* @param data - Currently collected agent-level data
|
|
642
907
|
* @param routeScores - AI-generated route scores from routing decision
|
|
@@ -656,8 +921,12 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
|
|
|
656
921
|
const aiScore = routeScores[route.id] || 0;
|
|
657
922
|
const completionProgress = completionStatus.get(route.id) || 0;
|
|
658
923
|
|
|
659
|
-
//
|
|
660
|
-
|
|
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
|
+
);
|
|
661
930
|
continue;
|
|
662
931
|
}
|
|
663
932
|
|
|
@@ -692,7 +961,7 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
|
|
|
692
961
|
* @private
|
|
693
962
|
*/
|
|
694
963
|
private async buildStepSelectionPrompt(
|
|
695
|
-
params: BuildStepSelectionPromptParams<TContext, TData>
|
|
964
|
+
params: BuildStepSelectionPromptParams<TContext, TData> & { includeEndRoute?: boolean }
|
|
696
965
|
): Promise<string> {
|
|
697
966
|
const {
|
|
698
967
|
route,
|
|
@@ -704,8 +973,10 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
|
|
|
704
973
|
agentOptions,
|
|
705
974
|
context,
|
|
706
975
|
session,
|
|
976
|
+
stepConditionContext,
|
|
977
|
+
includeEndRoute = false,
|
|
707
978
|
} = params;
|
|
708
|
-
const templateContext = { context, session, history };
|
|
979
|
+
const templateContext = createTemplateContext({ context, session, history });
|
|
709
980
|
const pc = new PromptComposer<TContext, TData>(templateContext);
|
|
710
981
|
|
|
711
982
|
// Add agent metadata
|
|
@@ -741,7 +1012,7 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
|
|
|
741
1012
|
await pc.addInteractionHistory(history);
|
|
742
1013
|
await pc.addLastMessage(lastMessage);
|
|
743
1014
|
|
|
744
|
-
// Add candidate steps
|
|
1015
|
+
// Add candidate steps with condition context
|
|
745
1016
|
const stepDescriptions = [];
|
|
746
1017
|
for (const candidate of candidates) {
|
|
747
1018
|
const idx = candidates.indexOf(candidate);
|
|
@@ -750,9 +1021,14 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
|
|
|
750
1021
|
` Description: ${candidate.step.description || "N/A"}`,
|
|
751
1022
|
];
|
|
752
1023
|
|
|
1024
|
+
// Add when condition context
|
|
753
1025
|
if (candidate.step.when) {
|
|
754
|
-
const
|
|
755
|
-
|
|
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
|
+
}
|
|
756
1032
|
}
|
|
757
1033
|
|
|
758
1034
|
if (candidate.step.requires && candidate.step.requires.length > 0) {
|
|
@@ -770,26 +1046,52 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
|
|
|
770
1046
|
`Available Steps to Transition To:\n${stepDescriptions.join("\n\n")}`
|
|
771
1047
|
);
|
|
772
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
|
+
|
|
773
1062
|
// Add decision prompt
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
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(
|
|
788
1080
|
"",
|
|
789
|
-
|
|
790
|
-
|
|
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."
|
|
791
1091
|
);
|
|
792
1092
|
|
|
1093
|
+
await pc.addInstruction(decisionRules.join("\n"));
|
|
1094
|
+
|
|
793
1095
|
return pc.build();
|
|
794
1096
|
}
|
|
795
1097
|
|
|
@@ -798,8 +1100,16 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
|
|
|
798
1100
|
* @private
|
|
799
1101
|
*/
|
|
800
1102
|
private buildStepSelectionSchema(
|
|
801
|
-
validSteps: Step<TContext, TData>[]
|
|
1103
|
+
validSteps: Step<TContext, TData>[],
|
|
1104
|
+
includeEndRoute: boolean = false
|
|
802
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
|
+
|
|
803
1113
|
return {
|
|
804
1114
|
description:
|
|
805
1115
|
"Step transition decision based on conversation context and collected data",
|
|
@@ -813,8 +1123,10 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
|
|
|
813
1123
|
selectedStepId: {
|
|
814
1124
|
type: "string",
|
|
815
1125
|
nullable: false,
|
|
816
|
-
description:
|
|
817
|
-
|
|
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,
|
|
818
1130
|
},
|
|
819
1131
|
responseDirectives: {
|
|
820
1132
|
type: "array",
|
|
@@ -914,8 +1226,9 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
|
|
|
914
1226
|
session,
|
|
915
1227
|
activeRouteSteps,
|
|
916
1228
|
context,
|
|
1229
|
+
routeConditionContext,
|
|
917
1230
|
} = params;
|
|
918
|
-
const templateContext = { context, session, history };
|
|
1231
|
+
const templateContext = createTemplateContext({ context, session, history });
|
|
919
1232
|
const pc = new PromptComposer<TContext, TData>(templateContext);
|
|
920
1233
|
if (agentOptions) {
|
|
921
1234
|
await pc.addAgentMeta(agentOptions);
|
|
@@ -985,18 +1298,26 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
|
|
|
985
1298
|
"",
|
|
986
1299
|
"Available steps in active route (choose one to transition to):",
|
|
987
1300
|
];
|
|
1301
|
+
const activeStepConditionContext: string[] = [];
|
|
1302
|
+
|
|
988
1303
|
for (const step of activeRouteSteps) {
|
|
989
1304
|
const idx = activeRouteSteps.indexOf(step);
|
|
990
1305
|
stepInfo.push(`${idx + 1}. Step: ${step.id}`);
|
|
991
1306
|
if (step.description) {
|
|
992
1307
|
stepInfo.push(` Description: ${step.description}`);
|
|
993
1308
|
}
|
|
994
|
-
|
|
1309
|
+
|
|
1310
|
+
// Collect AI context from step conditions
|
|
995
1311
|
if (step.when) {
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
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
|
+
}
|
|
999
1319
|
}
|
|
1320
|
+
|
|
1000
1321
|
if (step.requires && step.requires.length > 0) {
|
|
1001
1322
|
stepInfo.push(` Required data: ${step.requires.join(", ")}`);
|
|
1002
1323
|
}
|
|
@@ -1013,12 +1334,38 @@ export class RoutingEngine<TContext = unknown, TData = unknown> {
|
|
|
1013
1334
|
stepInfo.push("- The logical next step in the conversation");
|
|
1014
1335
|
stepInfo.push("- Whether conditions for steps are met");
|
|
1015
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
|
+
}
|
|
1016
1350
|
}
|
|
1017
1351
|
}
|
|
1018
1352
|
|
|
1019
1353
|
await pc.addInteractionHistory(history);
|
|
1020
1354
|
await pc.addLastMessage(lastMessage);
|
|
1021
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
|
+
}
|
|
1022
1369
|
await pc.addInstruction(
|
|
1023
1370
|
[
|
|
1024
1371
|
"Scoring rules:",
|