chat-flow-ardymalihi 1.0.2 → 3.0.2

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.
Files changed (359) hide show
  1. package/README.md +2 -0
  2. package/dist/{adapters → src/adapters}/intent/IntentMatcher.d.ts +16 -0
  3. package/dist/src/adapters/intent/IntentMatcher.d.ts.map +1 -0
  4. package/dist/src/adapters/intent/IntentMatcher.js +167 -0
  5. package/dist/src/adapters/intent/IntentMatcher.js.map +1 -0
  6. package/dist/{adapters → src/adapters}/intent/IntentService.d.ts +4 -5
  7. package/dist/src/adapters/intent/IntentService.d.ts.map +1 -0
  8. package/dist/{adapters → src/adapters}/intent/IntentService.js +15 -9
  9. package/dist/src/adapters/intent/IntentService.js.map +1 -0
  10. package/dist/src/adapters/intent/MockIntentService.d.ts +7 -0
  11. package/dist/src/adapters/intent/MockIntentService.d.ts.map +1 -0
  12. package/dist/{intent → src/adapters/intent}/MockIntentService.js +9 -3
  13. package/dist/src/adapters/intent/MockIntentService.js.map +1 -0
  14. package/dist/src/adapters/llm/GeminiLLMAdapter.d.ts.map +1 -0
  15. package/dist/src/adapters/llm/GeminiLLMAdapter.js.map +1 -0
  16. package/dist/src/adapters/llm/MockLLMAdapter.d.ts.map +1 -0
  17. package/dist/src/adapters/llm/MockLLMAdapter.js.map +1 -0
  18. package/dist/src/adapters/llm/OllamaLLMAdapter.d.ts +9 -0
  19. package/dist/src/adapters/llm/OllamaLLMAdapter.d.ts.map +1 -0
  20. package/dist/src/adapters/llm/OllamaLLMAdapter.js +74 -0
  21. package/dist/src/adapters/llm/OllamaLLMAdapter.js.map +1 -0
  22. package/dist/src/adapters/logger/ConsoleLogger.d.ts +12 -0
  23. package/dist/src/adapters/logger/ConsoleLogger.d.ts.map +1 -0
  24. package/dist/src/adapters/logger/ConsoleLogger.js +37 -0
  25. package/dist/src/adapters/logger/ConsoleLogger.js.map +1 -0
  26. package/dist/src/adapters/repository/InMemoryRepository.d.ts +57 -0
  27. package/dist/src/adapters/repository/InMemoryRepository.d.ts.map +1 -0
  28. package/dist/src/adapters/repository/InMemoryRepository.js +269 -0
  29. package/dist/src/adapters/repository/InMemoryRepository.js.map +1 -0
  30. package/dist/src/adapters/repository/RedisRepository.d.ts +72 -0
  31. package/dist/src/adapters/repository/RedisRepository.d.ts.map +1 -0
  32. package/dist/src/adapters/repository/RedisRepository.js +700 -0
  33. package/dist/src/adapters/repository/RedisRepository.js.map +1 -0
  34. package/dist/src/adapters/repository/SupabaseRepository.d.ts +60 -0
  35. package/dist/src/adapters/repository/SupabaseRepository.d.ts.map +1 -0
  36. package/dist/src/adapters/repository/SupabaseRepository.js +774 -0
  37. package/dist/src/adapters/repository/SupabaseRepository.js.map +1 -0
  38. package/dist/src/adapters/storage/RedisAudioStorageAdapter.d.ts +33 -0
  39. package/dist/src/adapters/storage/RedisAudioStorageAdapter.d.ts.map +1 -0
  40. package/dist/src/adapters/storage/RedisAudioStorageAdapter.js +121 -0
  41. package/dist/src/adapters/storage/RedisAudioStorageAdapter.js.map +1 -0
  42. package/dist/src/adapters/voice/GoogleVoiceAdapter.d.ts +33 -0
  43. package/dist/src/adapters/voice/GoogleVoiceAdapter.d.ts.map +1 -0
  44. package/dist/src/adapters/voice/GoogleVoiceAdapter.js +155 -0
  45. package/dist/src/adapters/voice/GoogleVoiceAdapter.js.map +1 -0
  46. package/dist/src/adapters/voice/LanguageVoiceMapper.d.ts +60 -0
  47. package/dist/src/adapters/voice/LanguageVoiceMapper.d.ts.map +1 -0
  48. package/dist/src/adapters/voice/LanguageVoiceMapper.js +130 -0
  49. package/dist/src/adapters/voice/LanguageVoiceMapper.js.map +1 -0
  50. package/dist/src/adapters/voice/VertexVoiceAdapter.d.ts +32 -0
  51. package/dist/src/adapters/voice/VertexVoiceAdapter.d.ts.map +1 -0
  52. package/dist/src/adapters/voice/VertexVoiceAdapter.js +179 -0
  53. package/dist/src/adapters/voice/VertexVoiceAdapter.js.map +1 -0
  54. package/dist/src/adapters/webhook/WebhookService.d.ts +47 -0
  55. package/dist/src/adapters/webhook/WebhookService.d.ts.map +1 -0
  56. package/dist/src/adapters/webhook/WebhookService.js +265 -0
  57. package/dist/src/adapters/webhook/WebhookService.js.map +1 -0
  58. package/dist/src/adapters/workflow/MockWorkflowAdapter.d.ts.map +1 -0
  59. package/dist/{workflow → src/adapters/workflow}/MockWorkflowAdapter.js +12 -1
  60. package/dist/src/adapters/workflow/MockWorkflowAdapter.js.map +1 -0
  61. package/dist/src/adapters/workflow/WorkflowAdapter.d.ts +55 -0
  62. package/dist/src/adapters/workflow/WorkflowAdapter.d.ts.map +1 -0
  63. package/dist/src/adapters/workflow/WorkflowAdapter.js +203 -0
  64. package/dist/src/adapters/workflow/WorkflowAdapter.js.map +1 -0
  65. package/dist/src/adapters/workflow/actions/index.d.ts +6 -0
  66. package/dist/src/adapters/workflow/actions/index.d.ts.map +1 -0
  67. package/dist/src/adapters/workflow/actions/index.js +22 -0
  68. package/dist/src/adapters/workflow/actions/index.js.map +1 -0
  69. package/dist/src/adapters/workflow/actions/pushOutputResultAction.d.ts +11 -0
  70. package/dist/src/adapters/workflow/actions/pushOutputResultAction.d.ts.map +1 -0
  71. package/dist/src/adapters/workflow/actions/pushOutputResultAction.js +31 -0
  72. package/dist/src/adapters/workflow/actions/pushOutputResultAction.js.map +1 -0
  73. package/dist/src/adapters/workflow/engine/constants.d.ts +3 -0
  74. package/dist/src/adapters/workflow/engine/constants.d.ts.map +1 -0
  75. package/dist/src/adapters/workflow/engine/constants.js +6 -0
  76. package/dist/src/adapters/workflow/engine/constants.js.map +1 -0
  77. package/dist/src/adapters/workflow/engine/engine.d.ts +32 -0
  78. package/dist/src/adapters/workflow/engine/engine.d.ts.map +1 -0
  79. package/dist/src/adapters/workflow/engine/engine.js +622 -0
  80. package/dist/src/adapters/workflow/engine/engine.js.map +1 -0
  81. package/dist/src/adapters/workflow/engine/event-registry.d.ts +12 -0
  82. package/dist/src/adapters/workflow/engine/event-registry.d.ts.map +1 -0
  83. package/dist/src/adapters/workflow/engine/event-registry.js +33 -0
  84. package/dist/src/adapters/workflow/engine/event-registry.js.map +1 -0
  85. package/dist/src/adapters/workflow/engine/interpolator.d.ts +11 -0
  86. package/dist/src/adapters/workflow/engine/interpolator.d.ts.map +1 -0
  87. package/dist/src/adapters/workflow/engine/interpolator.js +93 -0
  88. package/dist/src/adapters/workflow/engine/interpolator.js.map +1 -0
  89. package/dist/src/adapters/workflow/engine/registry.d.ts +12 -0
  90. package/dist/src/adapters/workflow/engine/registry.d.ts.map +1 -0
  91. package/dist/src/adapters/workflow/engine/registry.js +39 -0
  92. package/dist/src/adapters/workflow/engine/registry.js.map +1 -0
  93. package/dist/src/adapters/workflow/engine/template-registry.d.ts +60 -0
  94. package/dist/src/adapters/workflow/engine/template-registry.d.ts.map +1 -0
  95. package/dist/src/adapters/workflow/engine/template-registry.js +92 -0
  96. package/dist/src/adapters/workflow/engine/template-registry.js.map +1 -0
  97. package/dist/src/adapters/workflow/engine/utils/format-utils.d.ts +43 -0
  98. package/dist/src/adapters/workflow/engine/utils/format-utils.d.ts.map +1 -0
  99. package/dist/src/adapters/workflow/engine/utils/format-utils.js +137 -0
  100. package/dist/src/adapters/workflow/engine/utils/format-utils.js.map +1 -0
  101. package/dist/src/adapters/workflow/engine/utils/layout-calculator.d.ts +7 -0
  102. package/dist/src/adapters/workflow/engine/utils/layout-calculator.d.ts.map +1 -0
  103. package/dist/src/adapters/workflow/engine/utils/layout-calculator.js +87 -0
  104. package/dist/src/adapters/workflow/engine/utils/layout-calculator.js.map +1 -0
  105. package/dist/src/adapters/workflow/engine/utils/slugify.d.ts +2 -0
  106. package/dist/src/adapters/workflow/engine/utils/slugify.d.ts.map +1 -0
  107. package/dist/src/adapters/workflow/engine/utils/slugify.js +41 -0
  108. package/dist/src/adapters/workflow/engine/utils/slugify.js.map +1 -0
  109. package/dist/src/adapters/workflow/engine/validator.d.ts +9 -0
  110. package/dist/src/adapters/workflow/engine/validator.d.ts.map +1 -0
  111. package/dist/src/adapters/workflow/engine/validator.js +425 -0
  112. package/dist/src/adapters/workflow/engine/validator.js.map +1 -0
  113. package/dist/src/api/router.d.ts +3 -0
  114. package/dist/src/api/router.d.ts.map +1 -0
  115. package/dist/src/api/router.js +27 -0
  116. package/dist/src/api/router.js.map +1 -0
  117. package/dist/src/api/routes/configs.d.ts +3 -0
  118. package/dist/src/api/routes/configs.d.ts.map +1 -0
  119. package/dist/src/api/routes/configs.js +110 -0
  120. package/dist/src/api/routes/configs.js.map +1 -0
  121. package/dist/src/api/routes/executions.d.ts +3 -0
  122. package/dist/src/api/routes/executions.d.ts.map +1 -0
  123. package/dist/src/api/routes/executions.js +77 -0
  124. package/dist/src/api/routes/executions.js.map +1 -0
  125. package/dist/src/api/routes/intents.d.ts +3 -0
  126. package/dist/src/api/routes/intents.d.ts.map +1 -0
  127. package/dist/src/api/routes/intents.js +128 -0
  128. package/dist/src/api/routes/intents.js.map +1 -0
  129. package/dist/src/api/routes/sessions.d.ts +3 -0
  130. package/dist/src/api/routes/sessions.d.ts.map +1 -0
  131. package/dist/src/api/routes/sessions.js +105 -0
  132. package/dist/src/api/routes/sessions.js.map +1 -0
  133. package/dist/src/api/routes/users.d.ts +3 -0
  134. package/dist/src/api/routes/users.d.ts.map +1 -0
  135. package/dist/src/api/routes/users.js +51 -0
  136. package/dist/src/api/routes/users.js.map +1 -0
  137. package/dist/src/api/routes/workflows.d.ts +3 -0
  138. package/dist/src/api/routes/workflows.d.ts.map +1 -0
  139. package/dist/src/api/routes/workflows.js +132 -0
  140. package/dist/src/api/routes/workflows.js.map +1 -0
  141. package/dist/{config → src/config}/ChatFlowConfig.d.ts +7 -0
  142. package/dist/src/config/ChatFlowConfig.d.ts.map +1 -0
  143. package/dist/{config → src/config}/ChatFlowConfig.js +5 -0
  144. package/dist/src/config/ChatFlowConfig.js.map +1 -0
  145. package/dist/src/config/index.d.ts.map +1 -0
  146. package/dist/src/config/index.js.map +1 -0
  147. package/dist/src/config/swagger.d.ts +2 -0
  148. package/dist/src/config/swagger.d.ts.map +1 -0
  149. package/dist/src/config/swagger.js +136 -0
  150. package/dist/src/config/swagger.js.map +1 -0
  151. package/dist/src/core/entities/ConversationSession.d.ts +58 -0
  152. package/dist/src/core/entities/ConversationSession.d.ts.map +1 -0
  153. package/dist/src/core/entities/ConversationSession.js +160 -0
  154. package/dist/src/core/entities/ConversationSession.js.map +1 -0
  155. package/dist/{core → src/core}/entities/Message.d.ts +5 -2
  156. package/dist/src/core/entities/Message.d.ts.map +1 -0
  157. package/dist/{core → src/core}/entities/Message.js +2 -0
  158. package/dist/src/core/entities/Message.js.map +1 -0
  159. package/dist/src/core/errors/ChatFlowError.d.ts.map +1 -0
  160. package/dist/src/core/errors/ChatFlowError.js.map +1 -0
  161. package/dist/src/core/errors/index.d.ts.map +1 -0
  162. package/dist/src/core/errors/index.js.map +1 -0
  163. package/dist/src/core/utils/AudioUtils.d.ts +41 -0
  164. package/dist/src/core/utils/AudioUtils.d.ts.map +1 -0
  165. package/dist/src/core/utils/AudioUtils.js +188 -0
  166. package/dist/src/core/utils/AudioUtils.js.map +1 -0
  167. package/dist/src/core/utils/LanguageDetector.d.ts +52 -0
  168. package/dist/src/core/utils/LanguageDetector.d.ts.map +1 -0
  169. package/dist/src/core/utils/LanguageDetector.js +173 -0
  170. package/dist/src/core/utils/LanguageDetector.js.map +1 -0
  171. package/dist/src/demo/cli-demo.d.ts.map +1 -0
  172. package/dist/{demo → src/demo}/cli-demo.js +10 -6
  173. package/dist/src/demo/cli-demo.js.map +1 -0
  174. package/dist/src/demo/console-chat.d.ts.map +1 -0
  175. package/dist/{demo → src/demo}/console-chat.js +10 -6
  176. package/dist/src/demo/console-chat.js.map +1 -0
  177. package/dist/{index.d.ts → src/index.d.ts} +10 -5
  178. package/dist/src/index.d.ts.map +1 -0
  179. package/dist/{index.js → src/index.js} +25 -8
  180. package/dist/src/index.js.map +1 -0
  181. package/dist/src/interfaces.d.ts +663 -0
  182. package/dist/src/interfaces.d.ts.map +1 -0
  183. package/dist/src/interfaces.js +36 -0
  184. package/dist/src/interfaces.js.map +1 -0
  185. package/dist/src/orchestrator/Orchestrator.d.ts +62 -0
  186. package/dist/src/orchestrator/Orchestrator.d.ts.map +1 -0
  187. package/dist/src/orchestrator/Orchestrator.js +697 -0
  188. package/dist/src/orchestrator/Orchestrator.js.map +1 -0
  189. package/dist/src/scripts/debug-redis.d.ts.map +1 -0
  190. package/dist/src/scripts/debug-redis.js.map +1 -0
  191. package/dist/src/scripts/seed-collaborative-intents.d.ts +2 -0
  192. package/dist/src/scripts/seed-collaborative-intents.d.ts.map +1 -0
  193. package/dist/src/scripts/seed-collaborative-intents.js +90 -0
  194. package/dist/src/scripts/seed-collaborative-intents.js.map +1 -0
  195. package/dist/src/scripts/test-isolated-config.d.ts +2 -0
  196. package/dist/src/scripts/test-isolated-config.d.ts.map +1 -0
  197. package/dist/src/scripts/test-isolated-config.js +80 -0
  198. package/dist/src/scripts/test-isolated-config.js.map +1 -0
  199. package/dist/src/scripts/verify_memory_intents.d.ts.map +1 -0
  200. package/dist/src/scripts/verify_memory_intents.js.map +1 -0
  201. package/dist/src/scripts/verify_redis_intents.d.ts.map +1 -0
  202. package/dist/{scripts → src/scripts}/verify_redis_intents.js +4 -2
  203. package/dist/src/scripts/verify_redis_intents.js.map +1 -0
  204. package/dist/src/server/ChatFlowWebSocketServer.d.ts +42 -0
  205. package/dist/src/server/ChatFlowWebSocketServer.d.ts.map +1 -0
  206. package/dist/src/server/ChatFlowWebSocketServer.js +355 -0
  207. package/dist/src/server/ChatFlowWebSocketServer.js.map +1 -0
  208. package/dist/src/utils/crypto.d.ts +7 -0
  209. package/dist/src/utils/crypto.d.ts.map +1 -0
  210. package/dist/src/utils/crypto.js +35 -0
  211. package/dist/src/utils/crypto.js.map +1 -0
  212. package/dist/src/utils/encryption-helpers.d.ts +14 -0
  213. package/dist/src/utils/encryption-helpers.d.ts.map +1 -0
  214. package/dist/src/utils/encryption-helpers.js +49 -0
  215. package/dist/src/utils/encryption-helpers.js.map +1 -0
  216. package/dist/web/seed-demo-data.d.ts +2 -0
  217. package/dist/web/seed-demo-data.d.ts.map +1 -0
  218. package/dist/web/seed-demo-data.js +267 -0
  219. package/dist/web/seed-demo-data.js.map +1 -0
  220. package/dist/web/web-server.d.ts +2 -0
  221. package/dist/web/web-server.d.ts.map +1 -0
  222. package/dist/web/web-server.js +165 -0
  223. package/dist/web/web-server.js.map +1 -0
  224. package/package.json +32 -3
  225. package/dist/adapters/db/InMemorySessionRepository.js +0 -15
  226. package/dist/adapters/db/RedisSessionRepository.js +0 -41
  227. package/dist/adapters/intent/IntentMatcher.d.ts.map +0 -1
  228. package/dist/adapters/intent/IntentMatcher.js +0 -89
  229. package/dist/adapters/intent/IntentMatcher.js.map +0 -1
  230. package/dist/adapters/intent/IntentService.d.ts.map +0 -1
  231. package/dist/adapters/intent/IntentService.js.map +0 -1
  232. package/dist/adapters/intent/MockIntentAdapter.js +0 -29
  233. package/dist/adapters/llm/GeminiLLMAdapter.d.ts.map +0 -1
  234. package/dist/adapters/llm/GeminiLLMAdapter.js.map +0 -1
  235. package/dist/adapters/llm/MockLLMAdapter.d.ts.map +0 -1
  236. package/dist/adapters/llm/MockLLMAdapter.js.map +0 -1
  237. package/dist/adapters/memory/InMemorySessionRepository.js +0 -15
  238. package/dist/adapters/redis/RedisSessionRepository.js +0 -41
  239. package/dist/adapters/repository/InMemoryRepository.d.ts +0 -15
  240. package/dist/adapters/repository/InMemoryRepository.d.ts.map +0 -1
  241. package/dist/adapters/repository/InMemoryRepository.js +0 -41
  242. package/dist/adapters/repository/InMemoryRepository.js.map +0 -1
  243. package/dist/adapters/repository/IntentRepository.d.ts +0 -15
  244. package/dist/adapters/repository/IntentRepository.d.ts.map +0 -1
  245. package/dist/adapters/repository/IntentRepository.js +0 -28
  246. package/dist/adapters/repository/IntentRepository.js.map +0 -1
  247. package/dist/adapters/repository/RedisRepository.d.ts +0 -16
  248. package/dist/adapters/repository/RedisRepository.d.ts.map +0 -1
  249. package/dist/adapters/repository/RedisRepository.js +0 -87
  250. package/dist/adapters/repository/RedisRepository.js.map +0 -1
  251. package/dist/adapters/workflow/MockWorkflowAdapter.d.ts.map +0 -1
  252. package/dist/adapters/workflow/MockWorkflowAdapter.js +0 -162
  253. package/dist/adapters/workflow/MockWorkflowAdapter.js.map +0 -1
  254. package/dist/application/ConversationSession.d.ts +0 -23
  255. package/dist/application/ConversationSession.d.ts.map +0 -1
  256. package/dist/application/ConversationSession.js +0 -83
  257. package/dist/application/ConversationSession.js.map +0 -1
  258. package/dist/application/Message.d.ts +0 -11
  259. package/dist/application/Message.d.ts.map +0 -1
  260. package/dist/application/Message.js +0 -30
  261. package/dist/application/Message.js.map +0 -1
  262. package/dist/application/Orchestrator.d.ts +0 -18
  263. package/dist/application/Orchestrator.d.ts.map +0 -1
  264. package/dist/application/Orchestrator.js +0 -80
  265. package/dist/application/Orchestrator.js.map +0 -1
  266. package/dist/application/SessionState.js +0 -2
  267. package/dist/application/usecases/CreateSession.js +0 -20
  268. package/dist/application/usecases/HandleUserMessage.js +0 -69
  269. package/dist/config/ChatFlowConfig.d.ts.map +0 -1
  270. package/dist/config/ChatFlowConfig.js.map +0 -1
  271. package/dist/config/index.d.ts.map +0 -1
  272. package/dist/config/index.js.map +0 -1
  273. package/dist/core/entities/ConversationSession.d.ts +0 -23
  274. package/dist/core/entities/ConversationSession.d.ts.map +0 -1
  275. package/dist/core/entities/ConversationSession.js +0 -83
  276. package/dist/core/entities/ConversationSession.js.map +0 -1
  277. package/dist/core/entities/Message.d.ts.map +0 -1
  278. package/dist/core/entities/Message.js.map +0 -1
  279. package/dist/core/errors/ChatFlowError.d.ts.map +0 -1
  280. package/dist/core/errors/ChatFlowError.js.map +0 -1
  281. package/dist/core/errors/index.d.ts.map +0 -1
  282. package/dist/core/errors/index.js.map +0 -1
  283. package/dist/db/InMemoryRepository.d.ts +0 -15
  284. package/dist/db/InMemoryRepository.d.ts.map +0 -1
  285. package/dist/db/InMemoryRepository.js +0 -41
  286. package/dist/db/InMemoryRepository.js.map +0 -1
  287. package/dist/db/RedisRepository.d.ts +0 -16
  288. package/dist/db/RedisRepository.d.ts.map +0 -1
  289. package/dist/db/RedisRepository.js +0 -87
  290. package/dist/db/RedisRepository.js.map +0 -1
  291. package/dist/demo/cli-demo.d.ts.map +0 -1
  292. package/dist/demo/cli-demo.js.map +0 -1
  293. package/dist/demo/console-chat.d.ts.map +0 -1
  294. package/dist/demo/console-chat.js.map +0 -1
  295. package/dist/domain/conversation/ConversationSession.js +0 -82
  296. package/dist/domain/conversation/Message.js +0 -33
  297. package/dist/domain/conversation/SessionState.js +0 -10
  298. package/dist/index.d.ts.map +0 -1
  299. package/dist/index.js.map +0 -1
  300. package/dist/intent/IntentService.d.ts +0 -17
  301. package/dist/intent/IntentService.d.ts.map +0 -1
  302. package/dist/intent/IntentService.js +0 -51
  303. package/dist/intent/IntentService.js.map +0 -1
  304. package/dist/intent/MockIntentService.d.ts +0 -6
  305. package/dist/intent/MockIntentService.d.ts.map +0 -1
  306. package/dist/intent/MockIntentService.js.map +0 -1
  307. package/dist/interfaces.d.ts +0 -108
  308. package/dist/interfaces.d.ts.map +0 -1
  309. package/dist/interfaces.js +0 -18
  310. package/dist/interfaces.js.map +0 -1
  311. package/dist/llm/GeminiLLMAdapter.d.ts +0 -10
  312. package/dist/llm/GeminiLLMAdapter.d.ts.map +0 -1
  313. package/dist/llm/GeminiLLMAdapter.js +0 -102
  314. package/dist/llm/GeminiLLMAdapter.js.map +0 -1
  315. package/dist/llm/MockLLMAdapter.d.ts +0 -5
  316. package/dist/llm/MockLLMAdapter.d.ts.map +0 -1
  317. package/dist/llm/MockLLMAdapter.js +0 -31
  318. package/dist/llm/MockLLMAdapter.js.map +0 -1
  319. package/dist/orchestrator/Orchestrator.d.ts +0 -18
  320. package/dist/orchestrator/Orchestrator.d.ts.map +0 -1
  321. package/dist/orchestrator/Orchestrator.js +0 -80
  322. package/dist/orchestrator/Orchestrator.js.map +0 -1
  323. package/dist/ports/IIntentRepository.d.ts +0 -27
  324. package/dist/ports/IIntentRepository.d.ts.map +0 -1
  325. package/dist/ports/IIntentRepository.js +0 -3
  326. package/dist/ports/IIntentRepository.js.map +0 -1
  327. package/dist/ports/IntentPort.js +0 -2
  328. package/dist/ports/LLMPort.js +0 -2
  329. package/dist/ports/SessionRepository.js +0 -2
  330. package/dist/ports/WorkflowPort.js +0 -2
  331. package/dist/scripts/debug-redis.d.ts.map +0 -1
  332. package/dist/scripts/debug-redis.js.map +0 -1
  333. package/dist/scripts/verify_memory_intents.d.ts.map +0 -1
  334. package/dist/scripts/verify_memory_intents.js.map +0 -1
  335. package/dist/scripts/verify_redis_intents.d.ts.map +0 -1
  336. package/dist/scripts/verify_redis_intents.js.map +0 -1
  337. package/dist/verify_memory_intents.js +0 -44
  338. package/dist/verify_redis_intents.js +0 -49
  339. package/dist/workflow/MockWorkflowAdapter.d.ts +0 -5
  340. package/dist/workflow/MockWorkflowAdapter.d.ts.map +0 -1
  341. package/dist/workflow/MockWorkflowAdapter.js.map +0 -1
  342. /package/dist/{adapters → src/adapters}/llm/GeminiLLMAdapter.d.ts +0 -0
  343. /package/dist/{adapters → src/adapters}/llm/GeminiLLMAdapter.js +0 -0
  344. /package/dist/{adapters → src/adapters}/llm/MockLLMAdapter.d.ts +0 -0
  345. /package/dist/{adapters → src/adapters}/llm/MockLLMAdapter.js +0 -0
  346. /package/dist/{adapters → src/adapters}/workflow/MockWorkflowAdapter.d.ts +0 -0
  347. /package/dist/{config → src/config}/index.d.ts +0 -0
  348. /package/dist/{config → src/config}/index.js +0 -0
  349. /package/dist/{core → src/core}/errors/ChatFlowError.d.ts +0 -0
  350. /package/dist/{core → src/core}/errors/ChatFlowError.js +0 -0
  351. /package/dist/{core → src/core}/errors/index.d.ts +0 -0
  352. /package/dist/{core → src/core}/errors/index.js +0 -0
  353. /package/dist/{demo → src/demo}/cli-demo.d.ts +0 -0
  354. /package/dist/{demo → src/demo}/console-chat.d.ts +0 -0
  355. /package/dist/{scripts → src/scripts}/debug-redis.d.ts +0 -0
  356. /package/dist/{scripts → src/scripts}/debug-redis.js +0 -0
  357. /package/dist/{scripts → src/scripts}/verify_memory_intents.d.ts +0 -0
  358. /package/dist/{scripts → src/scripts}/verify_memory_intents.js +0 -0
  359. /package/dist/{scripts → src/scripts}/verify_redis_intents.d.ts +0 -0
@@ -0,0 +1,697 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Orchestrator = void 0;
4
+ const ConversationSession_1 = require("../core/entities/ConversationSession");
5
+ const Message_1 = require("../core/entities/Message");
6
+ const LanguageDetector_1 = require("../core/utils/LanguageDetector");
7
+ const interfaces_1 = require("../interfaces");
8
+ const errors_1 = require("../core/errors");
9
+ const config_1 = require("../config");
10
+ class Orchestrator {
11
+ constructor(repo, llm, intent, workflow, webhookService, voiceAdapter, audioStorage, config) {
12
+ this.repo = repo;
13
+ this.llm = llm;
14
+ this.intent = intent;
15
+ this.workflow = workflow;
16
+ this.webhookService = webhookService;
17
+ this.voiceAdapter = voiceAdapter;
18
+ this.audioStorage = audioStorage;
19
+ this.config = config ? { ...config_1.DEFAULT_CONFIG, ...config } : config_1.DEFAULT_CONFIG;
20
+ this.languageDetector = new LanguageDetector_1.LanguageDetector(llm);
21
+ }
22
+ async createSession(sessionId, mode, agentPrompt, userId, configId) {
23
+ // Business Rule: If userId and configId are provided, validate ownership and resolve prompt
24
+ let resolvedPrompt = agentPrompt;
25
+ let webhookConfig;
26
+ if (userId && configId) {
27
+ console.log(`[Orchestrator] Validating config '${configId}' for user '${userId}'`);
28
+ const config = await this.repo.findConversationConfig(userId, configId);
29
+ if (!config) {
30
+ console.error(`[Orchestrator] Security Alert: Config '${configId}' not found for user '${userId}'`);
31
+ throw new Error('Invalid Configuration: Config does not belong to User');
32
+ }
33
+ // Use the config's system prompt if available, otherwise fall back to passed prompt
34
+ if (config.systemPrompt) {
35
+ resolvedPrompt = config.systemPrompt;
36
+ }
37
+ webhookConfig = config.webhook;
38
+ }
39
+ // Enforce safe voice behavior: Single-turn responses, no narration of actions
40
+ let finalPrompt = resolvedPrompt;
41
+ if (mode === 'VOICE') {
42
+ finalPrompt += `
43
+
44
+ [VOICE INTERFACE INSTRUCTIONS]
45
+ - Provide the full, final answer in a single response.
46
+ - Do NOT narrate your actions (e.g., "Let me check", "One moment") unless you include the result in the same response.
47
+ - If you cannot perform a task, state it clearly immediately.
48
+ - Keep responses concise and suitable for text-to-speech.
49
+ - Do NOT ask "Is there anything else?" or generic follow-up questions. Only ask questions if you need specific information to complete the CURRENT task.
50
+ - If the user says "Thanks" or "Goodbye", just reply with a short closing (e.g., "You're welcome" or "Goodbye") and stop.`;
51
+ }
52
+ const session = new ConversationSession_1.ConversationSession({
53
+ sessionId,
54
+ userId,
55
+ configId,
56
+ mode,
57
+ agentPrompt: finalPrompt,
58
+ conversationMode: 'collaborative' // Default to collaborative mode
59
+ });
60
+ if (webhookConfig) {
61
+ session.setMetadata('webhookConfig', webhookConfig);
62
+ }
63
+ await this.repo.saveSession(session);
64
+ // Initialize Storage (Only for VOICE mode)
65
+ if (this.audioStorage && mode === 'VOICE') {
66
+ await this.audioStorage.initializeSession(sessionId, { userId, configId });
67
+ }
68
+ // Trigger session.started webhook
69
+ await this.webhookService.triggerSessionStarted(session);
70
+ return session;
71
+ }
72
+ async processMessage(sessionId, content, onIntermediateResponse) {
73
+ // 1. Load Session
74
+ const session = await this.repo.findSessionById(sessionId);
75
+ if (!session) {
76
+ throw new errors_1.SessionNotFoundError(sessionId);
77
+ }
78
+ try {
79
+ // 2. Append User Message
80
+ const userMessage = Message_1.Message.user(content);
81
+ session.addMessage(userMessage);
82
+ // 3. Safety Check: Enforce maximum conversation length (system-level protection)
83
+ const MAX_TOTAL_MSG_COUNT = parseInt(process.env.MAX_TOTAL_MSG_COUNT || '60', 10);
84
+ const totalMessages = session.messages.length;
85
+ if (totalMessages > MAX_TOTAL_MSG_COUNT) {
86
+ console.warn(`[Safety] Conversation limit exceeded for session ${sessionId}(${totalMessages} messages).Terminating.`);
87
+ throw new Error(`Conversation limit reached(${MAX_TOTAL_MSG_COUNT} messages).Please start a new session.`);
88
+ }
89
+ // 4. Content Filtering: Blacklisted words (configured per user/config)
90
+ const config = session.configId && session.userId
91
+ ? await this.repo.findConversationConfig(session.userId, session.configId)
92
+ : null;
93
+ const blacklistedWords = config?.blacklistedWords || [];
94
+ if (blacklistedWords.length > 0) {
95
+ const cleanContent = content.trim().toLowerCase();
96
+ const isBlacklisted = blacklistedWords.some(word => cleanContent.includes(word.toLowerCase()));
97
+ if (isBlacklisted) {
98
+ console.log(`[Orchestrator] Ignored blacklisted content: "${content}"`);
99
+ throw new Error('Message contains prohibited content.');
100
+ }
101
+ }
102
+ // Trigger message.user webhook (only for validated messages) - Fire-and-forget
103
+ this.webhookService.triggerUserMessage(session, userMessage).catch(e => console.error('[Orchestrator] Webhook failed:', e));
104
+ // 5. Exit Phrase Detection (universal session termination)
105
+ // Default common exit phrases (English)
106
+ const DEFAULT_EXIT_PHRASES = ['goodbye', 'bye', 'stop session', 'end session', 'quit', 'exit'];
107
+ // Use config-specific exit phrases if available, otherwise use defaults
108
+ // If config provides phrases, merge with defaults to ensure common phrases always work
109
+ const configExitPhrases = config?.exitPhrases || [];
110
+ const EXIT_PHRASES = configExitPhrases.length > 0
111
+ ? [...DEFAULT_EXIT_PHRASES, ...configExitPhrases]
112
+ : DEFAULT_EXIT_PHRASES;
113
+ const lowerContent = content.toLowerCase();
114
+ const shouldEndSession = EXIT_PHRASES.some(phrase => lowerContent.includes(phrase));
115
+ if (shouldEndSession) {
116
+ console.log(`[Orchestrator] Exit phrase detected: "${content}"`);
117
+ }
118
+ const newMessages = [];
119
+ // 6. Language Detection (Smart & Optimized) - Will run in PARALLEL with Intent Detection
120
+ let detectedLanguage;
121
+ let languageName;
122
+ let languageChanged = false;
123
+ // Check if multi-lingual mode is enabled
124
+ const multiLingualEnabled = config?.multiLingualMode !== false; // Default true if not specified
125
+ const defaultLanguage = config?.defaultLanguage || 'en';
126
+ const previousLanguage = session.currentLanguage;
127
+ // 7. Check if we're in the middle of parameter collection
128
+ if (session.isCollectingParameters()) {
129
+ return await this.handleParameterCollection(session, content, newMessages);
130
+ }
131
+ // 6 & 8. PARALLEL EXECUTION: Run Language Detection and Intent Detection concurrently
132
+ // Both are independent LLM API calls - running in parallel saves 100-300ms
133
+ console.log(`[Orchestrator] Starting parallel language detection and intent classification...`);
134
+ const [languageResult, intentResult] = await Promise.all([
135
+ // Language Detection Promise
136
+ (async () => {
137
+ if (multiLingualEnabled) {
138
+ const shouldDetect = !previousLanguage ||
139
+ this.languageDetector.hasCharacterSetChanged(content, previousLanguage);
140
+ if (shouldDetect) {
141
+ const languageHints = config?.supportedLanguages;
142
+ const detected = await this.languageDetector.detectLanguage(content, languageHints);
143
+ const name = this.languageDetector.getLanguageName(detected);
144
+ const changed = previousLanguage && previousLanguage !== detected;
145
+ if (changed) {
146
+ console.log(`[Orchestrator] Language switched: ${previousLanguage} → ${detected} (${name})`);
147
+ }
148
+ else if (!previousLanguage) {
149
+ console.log(`[Orchestrator] Language detected: ${detected} (${name})`);
150
+ }
151
+ session.setLanguage(detected);
152
+ if (session.mode === 'VOICE' && this.voiceAdapter && 'setLanguage' in this.voiceAdapter) {
153
+ this.voiceAdapter.setLanguage(detected);
154
+ }
155
+ return { detectedLanguage: detected, languageName: name, languageChanged: !!changed };
156
+ }
157
+ else {
158
+ const detected = previousLanguage;
159
+ const name = this.languageDetector.getLanguageName(detected);
160
+ console.log(`[Orchestrator] Using cached language: ${detected} (${name})`);
161
+ return { detectedLanguage: detected, languageName: name, languageChanged: false };
162
+ }
163
+ }
164
+ else {
165
+ const detected = defaultLanguage;
166
+ const name = this.languageDetector.getLanguageName(detected);
167
+ if (!session.currentLanguage) {
168
+ console.log(`[Orchestrator] Multi - lingual mode disabled.Using default: ${detected} (${name})`);
169
+ session.setLanguage(detected);
170
+ }
171
+ return { detectedLanguage: detected, languageName: name, languageChanged: false };
172
+ }
173
+ })(),
174
+ // Intent Detection Promise (runs in parallel)
175
+ this.intent.detectIntent(session.getHistory(), session.agentPrompt, session.userId)
176
+ ]);
177
+ // Extract results from parallel execution
178
+ detectedLanguage = languageResult.detectedLanguage;
179
+ languageName = languageResult.languageName;
180
+ languageChanged = languageResult.languageChanged;
181
+ // 9. Collaborative mode: handle partial intents
182
+ if (session.conversationMode === 'collaborative' &&
183
+ intentResult.intentName &&
184
+ intentResult.missingRequiredParameters &&
185
+ intentResult.missingRequiredParameters.length > 0 &&
186
+ intentResult.confidence >= this.config.intent.confidenceThreshold) {
187
+ console.log(`[Orchestrator] COLLABORATIVE: Intent '${intentResult.intentName}' detected with missing parameters: ${intentResult.missingRequiredParameters.join(', ')} `);
188
+ return await this.startParameterCollection(session, intentResult, newMessages);
189
+ }
190
+ // 10. Execute workflow if intent is complete and confident
191
+ if (intentResult.intentName && intentResult.confidence >= this.config.intent.confidenceThreshold) {
192
+ console.log(`[Orchestrator] DECISION: Execute Workflow '${intentResult.intentName}'(Confidence ${intentResult.confidence} >= ${this.config.intent.confidenceThreshold})`);
193
+ // VERBAL ACKNOWLEDGMENT (Filler Phrase)
194
+ // Fetch full intent to check for processing messages
195
+ const fullIntent = await this.repo.findIntentByName(intentResult.intentName, session.userId);
196
+ if (fullIntent?.processingMessages && fullIntent.processingMessages.length > 0 && onIntermediateResponse) {
197
+ const randomPhrase = fullIntent.processingMessages[Math.floor(Math.random() * fullIntent.processingMessages.length)];
198
+ console.log(`[Orchestrator] Sending filler phrase: "${randomPhrase}"`);
199
+ // Fire and forget? No, we should wait for it to start ensuring order?
200
+ // Actually, TTS generation takes time. We want to start it concurrently with workflow if possible,
201
+ // BUT if workflow is fast, we might get double audio overlap.
202
+ // Given the goal is "filling silence", we should probably fire it.
203
+ // However, `onIntermediateResponse` will likely queue audio.
204
+ await onIntermediateResponse(randomPhrase);
205
+ }
206
+ // Update User Message Metadata with Detected Intent
207
+ userMessage.metadata = {
208
+ ...userMessage.metadata,
209
+ intent: {
210
+ name: intentResult.intentName,
211
+ confidence: intentResult.confidence,
212
+ parameters: intentResult.payload
213
+ }
214
+ };
215
+ // Trigger intent.detected webhook - Fire-and-forget
216
+ this.webhookService.triggerIntentDetected(session, intentResult).catch(e => console.error('[Orchestrator] Webhook failed:', e));
217
+ if (fullIntent?.skipWorkflow) {
218
+ console.log(`[Orchestrator] Intent '${intentResult.intentName}' marked as skipWorkflow. Skipping execution.`);
219
+ // Inject Intent Context for LLM
220
+ const contextMessage = new Message_1.Message({
221
+ role: interfaces_1.Role.SYSTEM,
222
+ content: `[System Info: User intent '${intentResult.intentName}' detected. This intent is informational/metadata-only (No Workflow). Answer the user naturally based on this intent.]`,
223
+ timestamp: new Date()
224
+ });
225
+ // Transient history
226
+ const transientHistory = [...session.getHistory(), contextMessage];
227
+ const llmResponse = await this.llm.generateResponse(session.agentPrompt, transientHistory);
228
+ const assistantMsg = Message_1.Message.assistant(llmResponse.content);
229
+ session.addMessage(assistantMsg);
230
+ newMessages.push(assistantMsg);
231
+ // Trigger message.bot webhook
232
+ if (this.webhookService) {
233
+ this.webhookService.triggerBotMessage(session, assistantMsg).catch(e => console.error('[Orchestrator] Webhook failed:', e));
234
+ }
235
+ }
236
+ else {
237
+ // Inject userId into payload for correct workflow lookup
238
+ const workflowPayload = {
239
+ ...intentResult.payload,
240
+ userId: session.userId
241
+ };
242
+ const workflowResult = await this.workflow.executeWorkflow(intentResult.intentName, workflowPayload);
243
+ let assistantContent;
244
+ // CHECK: Did the workflow return an explicit final message?
245
+ if (workflowResult.success && workflowResult.data && workflowResult.data.message) {
246
+ console.log(`[Orchestrator] Workflow '${intentResult.intentName}' returned explicit final message. Skipping LLM generation.`);
247
+ assistantContent = workflowResult.data.message;
248
+ }
249
+ else {
250
+ // Fallback: Use LLM to generate response based on workflow result
251
+ console.log(`[Orchestrator] Workflow '${intentResult.intentName}' executed without explicit final message. Using LLM to generate response.`);
252
+ // Inject Workflow Result
253
+ const workflowContextMessage = new Message_1.Message({
254
+ role: interfaces_1.Role.SYSTEM,
255
+ content: `[System Info: Workflow detected '${intentResult.intentName}'.Execution Result: ${JSON.stringify(workflowResult.data)}. Use this to answer the user.]`,
256
+ timestamp: new Date()
257
+ });
258
+ // Transient history
259
+ const transientHistory = [...session.getHistory(), workflowContextMessage];
260
+ const llmResponse = await this.llm.generateResponse(session.agentPrompt, transientHistory);
261
+ assistantContent = llmResponse.content;
262
+ }
263
+ const assistantMsg = Message_1.Message.assistant(assistantContent);
264
+ session.addMessage(assistantMsg);
265
+ newMessages.push(assistantMsg);
266
+ // Trigger workflow webhook based on success/failure
267
+ if (workflowResult.success) {
268
+ // Update User Message Metadata with Workflow Execution
269
+ userMessage.metadata = {
270
+ ...userMessage.metadata,
271
+ workflow: {
272
+ id: intentResult.intentName,
273
+ result: workflowResult.data
274
+ }
275
+ };
276
+ // Fire-and-forget
277
+ this.webhookService.triggerWorkflowExecuted(session, {
278
+ workflowName: intentResult.intentName,
279
+ parameters: intentResult.payload,
280
+ result: workflowResult
281
+ }).catch(e => console.error('[Orchestrator] Webhook failed:', e));
282
+ }
283
+ else if (workflowResult.error === 'NO_WORKFLOW_MATCHED') {
284
+ // Smart Workflow handling:
285
+ // If no workflow matches, we treat it as "Intent detected but no specific logic".
286
+ // We do NOT fire a failure webhook, but instead let the LLM handle it naturally.
287
+ console.log(`[Orchestrator] Smart Workflow: No workflow found for '${intentResult.intentName}'. Falling back to LLM.`);
288
+ // Inject Context for LLM so it knows intent was detected but handled generically
289
+ const workflowContextMessage = new Message_1.Message({
290
+ role: interfaces_1.Role.SYSTEM,
291
+ content: `[System Info: User intent '${intentResult.intentName}' detected, but no specific workflow is configured. Answer the user naturally based on this intent.]`,
292
+ timestamp: new Date()
293
+ });
294
+ // Transient history
295
+ const transientHistory = [...session.getHistory(), workflowContextMessage];
296
+ const llmResponse = await this.llm.generateResponse(session.agentPrompt, transientHistory);
297
+ assistantContent = llmResponse.content;
298
+ // Note: We intentionally DO NOT update userMessage metadata with 'workflow'
299
+ // and DO NOT trigger workflow.failed or workflow.executed webhooks.
300
+ // This makes the lack of workflow invisible to the outside world (except for the intent detection).
301
+ }
302
+ else {
303
+ // Update User Message Metadata with Workflow Failure
304
+ userMessage.metadata = {
305
+ ...userMessage.metadata,
306
+ workflow: {
307
+ id: intentResult.intentName,
308
+ error: workflowResult.error
309
+ }
310
+ };
311
+ // Fire-and-forget
312
+ this.webhookService.triggerWorkflowFailed(session, {
313
+ workflowName: intentResult.intentName,
314
+ parameters: intentResult.payload,
315
+ error: workflowResult.error
316
+ }).catch(e => console.error('[Orchestrator] Webhook failed:', e));
317
+ }
318
+ // Trigger message.bot webhook - Fire-and-forget
319
+ if (this.webhookService) {
320
+ this.webhookService.triggerBotMessage(session, assistantMsg).catch(e => console.error('[Orchestrator] Webhook failed:', e));
321
+ }
322
+ }
323
+ }
324
+ else {
325
+ // 11. Fallback to standard LLM with language-specific prompt
326
+ if (intentResult.intentName) {
327
+ console.log(`[Orchestrator] DECISION: Skip Workflow '${intentResult.intentName}'(Confidence ${intentResult.confidence} < ${this.config.intent.confidenceThreshold}).Proceeding with Standard LLM.`);
328
+ // Trigger intent.failed webhook - Fire-and-forget
329
+ this.webhookService.triggerIntentFailed(session, intentResult).catch(e => console.error('[Orchestrator] Webhook failed:', e));
330
+ }
331
+ else {
332
+ console.log(`[Orchestrator] DECISION: No Intent Detected.Proceeding with Standard LLM.`);
333
+ }
334
+ // Inject language instruction into system prompt
335
+ const languagePrompt = `${session.agentPrompt} \n\n[LANGUAGE INSTRUCTION]\n - The user is speaking in ${languageName} (${detectedLanguage}).\n - You MUST respond in ${languageName}.\n - Match the user's language exactly.`;
336
+ const llmResponse = await this.llm.generateResponse(languagePrompt, session.getHistory());
337
+ const assistantMsg = Message_1.Message.assistant(llmResponse.content, { detectedLanguage });
338
+ session.addMessage(assistantMsg);
339
+ newMessages.push(assistantMsg);
340
+ // Trigger message.bot webhook - Fire-and-forget
341
+ this.webhookService.triggerBotMessage(session, assistantMsg).catch(e => console.error('[Orchestrator] Webhook failed:', e));
342
+ }
343
+ // 12. Save
344
+ await this.repo.saveSession(session);
345
+ return {
346
+ messages: newMessages,
347
+ metadata: {
348
+ intent: intentResult.intentName,
349
+ confidence: intentResult.confidence,
350
+ workflowExecuted: (intentResult.intentName && intentResult.confidence >= this.config.intent.confidenceThreshold) ? intentResult.intentName : null,
351
+ shouldEndSession: shouldEndSession,
352
+ detectedLanguage: detectedLanguage,
353
+ languageName: languageName,
354
+ languageChanged: languageChanged
355
+ }
356
+ };
357
+ }
358
+ catch (error) {
359
+ // Fire-and-forget error webhook
360
+ this.webhookService.triggerErrorOccurred(session, error).catch(e => console.error('[Orchestrator] Webhook failed:', e));
361
+ throw error;
362
+ }
363
+ }
364
+ /**
365
+ * Start parameter collection for a detected intent with missing parameters
366
+ */
367
+ async startParameterCollection(session, intentResult, newMessages) {
368
+ // Initialize parameter collection state
369
+ session.startParameterCollection({
370
+ intentName: intentResult.intentName,
371
+ detectedParameters: intentResult.payload || {},
372
+ missingParameters: intentResult.missingRequiredParameters,
373
+ attemptCount: 0,
374
+ initialConfidence: intentResult.confidence
375
+ });
376
+ // Generate clarifying question
377
+ const question = await this.generateClarificationQuestion(session, intentResult.intentName, intentResult.missingRequiredParameters);
378
+ const assistantMsg = Message_1.Message.assistant(question);
379
+ session.addMessage(assistantMsg);
380
+ newMessages.push(assistantMsg);
381
+ await this.repo.saveSession(session);
382
+ return {
383
+ messages: newMessages,
384
+ metadata: {
385
+ intent: intentResult.intentName,
386
+ confidence: intentResult.confidence,
387
+ collectingParameters: true,
388
+ missingParameters: intentResult.missingRequiredParameters
389
+ }
390
+ };
391
+ }
392
+ /**
393
+ * Handle parameter collection from user response
394
+ */
395
+ async handleParameterCollection(session, userResponse, newMessages) {
396
+ const collectionState = session.getParameterCollectionState();
397
+ const MAX_ATTEMPTS = 3;
398
+ // Check if max attempts reached
399
+ if (collectionState.attemptCount >= MAX_ATTEMPTS) {
400
+ console.log('[Orchestrator] Max clarification attempts reached. Falling back to LLM.');
401
+ session.clearParameterCollection();
402
+ const llmResponse = await this.llm.generateResponse(session.agentPrompt, session.getHistory());
403
+ const assistantMsg = Message_1.Message.assistant(llmResponse.content);
404
+ session.addMessage(assistantMsg);
405
+ newMessages.push(assistantMsg);
406
+ await this.repo.saveSession(session);
407
+ return {
408
+ messages: newMessages,
409
+ metadata: { maxAttemptsReached: true }
410
+ };
411
+ }
412
+ // Get the intent definition
413
+ const allIntents = await this.intent.matchIntents(collectionState.intentName, 100);
414
+ const matchedIntent = allIntents.find((m) => m.intent.name === collectionState.intentName);
415
+ if (!matchedIntent) {
416
+ session.clearParameterCollection();
417
+ throw new Error(`Intent ${collectionState.intentName} not found`);
418
+ }
419
+ const intent = matchedIntent.intent;
420
+ // Extract parameters from user response using IntentMatcher
421
+ // We need to access the matcher through the intent service
422
+ // For now, we'll use a simpler approach with the LLM directly
423
+ const extractedParams = await this.extractParametersFromResponse(userResponse, intent, collectionState.missingParameters);
424
+ // Merge with existing parameters
425
+ const allParameters = {
426
+ ...collectionState.detectedParameters,
427
+ ...extractedParams
428
+ };
429
+ // Check what's still missing
430
+ const stillMissing = collectionState.missingParameters.filter(paramName => {
431
+ const value = allParameters[paramName];
432
+ return value === null || value === undefined || value === '' ||
433
+ (Array.isArray(value) && value.length === 0);
434
+ });
435
+ if (stillMissing.length === 0) {
436
+ // All parameters collected! Execute workflow
437
+ console.log('[Orchestrator] All parameters collected. Executing workflow.');
438
+ session.clearParameterCollection();
439
+ const workflowPayload = {
440
+ ...allParameters,
441
+ userId: session.userId
442
+ };
443
+ const workflowResult = await this.workflow.executeWorkflow(collectionState.intentName, workflowPayload);
444
+ const workflowContextMessage = new Message_1.Message({
445
+ role: interfaces_1.Role.SYSTEM,
446
+ content: `[System Info: Workflow detected '${collectionState.intentName}'. Execution Result: ${JSON.stringify(workflowResult.data)}. Use this to answer the user.]`,
447
+ timestamp: new Date()
448
+ });
449
+ // Update the last user message with intent and workflow metadata
450
+ const lastUserMessage = session.messages.slice().reverse().find(m => m.role === interfaces_1.Role.USER);
451
+ if (lastUserMessage) {
452
+ lastUserMessage.metadata = {
453
+ ...lastUserMessage.metadata,
454
+ intent: {
455
+ name: collectionState.intentName,
456
+ confidence: collectionState.initialConfidence, // Use original detection confidence
457
+ originalConfidence: collectionState.initialConfidence,
458
+ parameters: allParameters
459
+ },
460
+ workflow: {
461
+ id: collectionState.intentName,
462
+ result: workflowResult.data
463
+ }
464
+ };
465
+ }
466
+ const transientHistory = [...session.getHistory(), workflowContextMessage];
467
+ const llmResponse = await this.llm.generateResponse(session.agentPrompt, transientHistory);
468
+ const assistantMsg = Message_1.Message.assistant(llmResponse.content);
469
+ session.addMessage(assistantMsg);
470
+ newMessages.push(assistantMsg);
471
+ await this.repo.saveSession(session);
472
+ return {
473
+ messages: newMessages,
474
+ metadata: {
475
+ intent: collectionState.intentName,
476
+ confidence: 1.0, // High confidence after collection
477
+ workflowExecuted: collectionState.intentName,
478
+ parametersCollected: true
479
+ }
480
+ };
481
+ }
482
+ else {
483
+ // Still missing parameters, ask again
484
+ session.updateParameterCollection(extractedParams, stillMissing);
485
+ const question = await this.generateClarificationQuestion(session, collectionState.intentName, stillMissing);
486
+ const assistantMsg = Message_1.Message.assistant(question);
487
+ session.addMessage(assistantMsg);
488
+ newMessages.push(assistantMsg);
489
+ await this.repo.saveSession(session);
490
+ return {
491
+ messages: newMessages,
492
+ metadata: {
493
+ intent: collectionState.intentName,
494
+ collectingParameters: true,
495
+ missingParameters: stillMissing,
496
+ attemptCount: collectionState.attemptCount
497
+ }
498
+ };
499
+ }
500
+ }
501
+ /**
502
+ * Generate a clarification question for missing parameters
503
+ */
504
+ async generateClarificationQuestion(session, intentName, missingParameters) {
505
+ // Get intent details for better question generation
506
+ const allIntents = await this.intent.matchIntents(intentName, 100);
507
+ const matchedIntent = allIntents.find((m) => m.intent.name === intentName);
508
+ let fieldInfo = '';
509
+ if (matchedIntent) {
510
+ const fields = [...matchedIntent.intent.required_fields, ...(matchedIntent.intent.optional_fields || [])];
511
+ fieldInfo = missingParameters.map(paramName => {
512
+ const field = fields.find(f => f.name === paramName);
513
+ if (!field)
514
+ return paramName;
515
+ const displayName = field.displayName || paramName;
516
+ const description = field.description || '';
517
+ return `${displayName}${description ? ' (' + description + ')' : ''}`;
518
+ }).join(', ');
519
+ }
520
+ else {
521
+ fieldInfo = missingParameters.join(', ');
522
+ }
523
+ const prompt = `
524
+ You are a helpful assistant collecting information from the user.
525
+ The user wants to perform: ${intentName}
526
+ You need to ask for the following missing information: ${fieldInfo}
527
+
528
+ Generate a natural, friendly question to ask the user for this information.
529
+ Be concise and conversational. Ask for the most important missing parameter first.
530
+ If there are multiple missing parameters, focus on one at a time.
531
+
532
+ Question:`;
533
+ const response = await this.llm.generateContent(prompt);
534
+ return response.trim();
535
+ }
536
+ /**
537
+ * Extract parameters from user response
538
+ */
539
+ async extractParametersFromResponse(userResponse, intent, missingParameters) {
540
+ const extractionPrompt = `
541
+ You are a parameter extraction assistant. Extract the following parameters from the user's response.
542
+
543
+ Intent: ${intent.name}
544
+ Missing Parameters: ${missingParameters.join(', ')}
545
+
546
+ User Response: "${userResponse}"
547
+
548
+ For each missing parameter, try to extract its value from the user's response.
549
+ Return ONLY a valid JSON object with the extracted parameters.
550
+ If a parameter is not found, omit it from the response.
551
+
552
+ Example:
553
+ {
554
+ "date": "2024-01-15",
555
+ "time": "14:00"
556
+ }
557
+ `;
558
+ try {
559
+ const response = await this.llm.generateResponse(extractionPrompt, []);
560
+ const content = response.content.trim();
561
+ // Try to parse JSON from the response
562
+ const jsonMatch = content.match(/\{[\s\S]*\}/);
563
+ if (jsonMatch) {
564
+ return JSON.parse(jsonMatch[0]);
565
+ }
566
+ console.warn('[Orchestrator] Could not extract JSON from LLM response:', content);
567
+ return {};
568
+ }
569
+ catch (error) {
570
+ console.error('[Orchestrator] Error extracting parameters:', error);
571
+ return {};
572
+ }
573
+ }
574
+ /**
575
+ * Handle incoming voice message (audio input)
576
+ * Converts speech to text, processes the message, and optionally returns audio response
577
+ * @param sessionId Session identifier
578
+ * @param audioBase64 Base64-encoded audio data (WAV format recommended)
579
+ * @returns Transcript, messages, and optional audio response
580
+ */
581
+ /**
582
+ * Get voice response for any text
583
+ * Useful for converting assistant messages to speech
584
+ * @param text Text to convert to speech
585
+ * @returns Audio data as Uint8Array
586
+ */
587
+ async getVoiceResponse(text) {
588
+ if (!this.voiceAdapter) {
589
+ throw new Error('Voice adapter not configured. Please provide an IVoiceAdapter when creating the Orchestrator.');
590
+ }
591
+ console.log(`[Orchestrator] Generating voice response for text: "${text.substring(0, 50)}..."`);
592
+ return await this.voiceAdapter.textToSpeech(text);
593
+ }
594
+ /**
595
+ * Transcribe audio and record it to storage
596
+ */
597
+ async transcribeAudio(sessionId, audioBase64) {
598
+ if (!this.voiceAdapter)
599
+ throw new Error('Voice adapter missing');
600
+ const transcript = await this.voiceAdapter.speechToText(audioBase64);
601
+ if (this.audioStorage) {
602
+ const buffer = Buffer.from(audioBase64, 'base64');
603
+ // Get format metadata from voice adapter (defaults to WAV if not provided)
604
+ const formatMetadata = this.voiceAdapter.getSTTInputFormat ? this.voiceAdapter.getSTTInputFormat() : { format: 'wav' };
605
+ this.audioStorage.appendAudio(sessionId, buffer, formatMetadata).catch(e => console.error('[Orchestrator] Failed to record user audio', e));
606
+ }
607
+ return transcript;
608
+ }
609
+ /**
610
+ * Synthesize audio and record it to storage
611
+ */
612
+ async synthesizeResponse(sessionId, text) {
613
+ if (!this.voiceAdapter)
614
+ throw new Error('Voice adapter missing');
615
+ const audio = await this.voiceAdapter.textToSpeech(text);
616
+ if (this.audioStorage) {
617
+ const buffer = Buffer.from(audio);
618
+ // Get format metadata from voice adapter
619
+ const formatMetadata = this.voiceAdapter.getTTSOutputFormat();
620
+ this.audioStorage.appendAudio(sessionId, buffer, formatMetadata).catch(e => console.error('[Orchestrator] Failed to record bot audio', e));
621
+ }
622
+ return audio;
623
+ }
624
+ async completeSession(sessionId, recordingUrl) {
625
+ const session = await this.repo.findSessionById(sessionId);
626
+ if (!session) {
627
+ throw new errors_1.SessionNotFoundError(sessionId);
628
+ }
629
+ // Generate Summary
630
+ const messages = session.getHistory();
631
+ if (messages.length > 0) {
632
+ // Get config to use defaultLanguage for summary
633
+ const config = session.configId && session.userId
634
+ ? await this.repo.findConversationConfig(session.userId, session.configId)
635
+ : null;
636
+ const defaultLanguage = config?.defaultLanguage || 'en';
637
+ const languageName = this.languageDetector.getLanguageName(defaultLanguage);
638
+ const transcript = messages.map(m => `${m.role}: ${m.content}`).join('\n');
639
+ const summaryPrompt = `
640
+ Please summarize the following conversation in a concise paragraph in ${languageName}.
641
+ Highlight the main user intent, key actions taken, and the final outcome.
642
+ Respond in ${languageName} language.
643
+
644
+ Conversation:
645
+ ${transcript}
646
+
647
+ Summary:`;
648
+ try {
649
+ // If generateContent is available (some adapters might not implement it), use it.
650
+ // Otherwise fallback to generateResponse.
651
+ let summaryText = '';
652
+ if (this.llm.generateContent) {
653
+ summaryText = await this.llm.generateContent(summaryPrompt);
654
+ }
655
+ else {
656
+ const response = await this.llm.generateResponse(summaryPrompt, []);
657
+ summaryText = response.content;
658
+ }
659
+ session.summary = summaryText.trim();
660
+ }
661
+ catch (error) {
662
+ console.error('[Orchestrator] Failed to generate summary:', error);
663
+ session.summary = "Summary generation failed or not supported.";
664
+ }
665
+ }
666
+ else {
667
+ session.summary = "No conversation history to summarize.";
668
+ }
669
+ // Mark as completed
670
+ session.updateStatus(interfaces_1.SessionStatus.COMPLETED);
671
+ // Save (Repository should handle permanent persistence for COMPLETED status)
672
+ await this.repo.saveSession(session);
673
+ // If recordingUrl was not passed but storage exists, try to finalize it now
674
+ if (!recordingUrl && this.audioStorage && session.mode === 'VOICE') {
675
+ try {
676
+ const url = await this.audioStorage.finalizeSession(sessionId);
677
+ console.log(`[Orchestrator] Finalized storage for session ${sessionId}. URL: ${url}`);
678
+ recordingUrl = url; // Update local variable to pass to webhook
679
+ }
680
+ catch (e) {
681
+ console.error('[Orchestrator] Failed to finalize storage', e);
682
+ }
683
+ }
684
+ // Trigger session.ended webhook (includes full transcript and summary)
685
+ await this.webhookService.triggerSessionEnded(session, recordingUrl);
686
+ console.log(`[Orchestrator] Session ${sessionId} completed and summarized.`);
687
+ return session;
688
+ }
689
+ async getSessionAudio(sessionId) {
690
+ if (this.audioStorage) {
691
+ return await this.audioStorage.getSessionAudio(sessionId);
692
+ }
693
+ return null;
694
+ }
695
+ }
696
+ exports.Orchestrator = Orchestrator;
697
+ //# sourceMappingURL=Orchestrator.js.map