@multiplayer-app/ai-agent-node 0.1.0-beta.4 → 0.1.0-beta.41

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 (299) hide show
  1. package/dist/cjs/config.cjs +88 -38
  2. package/dist/cjs/config.cjs.map +1 -1
  3. package/dist/cjs/config.d.ts +57 -23
  4. package/dist/cjs/config.d.ts.map +1 -1
  5. package/dist/cjs/helpers/AIHelper.cjs +160 -101
  6. package/dist/cjs/helpers/AIHelper.cjs.map +1 -1
  7. package/dist/cjs/helpers/AIHelper.d.ts +21 -13
  8. package/dist/cjs/helpers/AIHelper.d.ts.map +1 -1
  9. package/dist/cjs/helpers/AIHelper.test.cjs +22 -15
  10. package/dist/cjs/helpers/AIHelper.test.cjs.map +1 -1
  11. package/dist/cjs/helpers/ConfigHelper.cjs +19 -11
  12. package/dist/cjs/helpers/ConfigHelper.cjs.map +1 -1
  13. package/dist/cjs/helpers/ConfigHelper.d.ts.map +1 -1
  14. package/dist/cjs/helpers/ContextLimiter.cjs +2 -3
  15. package/dist/cjs/helpers/ContextLimiter.cjs.map +1 -1
  16. package/dist/cjs/helpers/FileHelper.cjs +132 -154
  17. package/dist/cjs/helpers/FileHelper.cjs.map +1 -1
  18. package/dist/cjs/helpers/FileHelper.d.ts +19 -25
  19. package/dist/cjs/helpers/FileHelper.d.ts.map +1 -1
  20. package/dist/cjs/helpers/index.cjs +4 -5
  21. package/dist/cjs/helpers/index.cjs.map +1 -1
  22. package/dist/cjs/helpers/index.d.ts +4 -5
  23. package/dist/cjs/helpers/index.d.ts.map +1 -1
  24. package/dist/cjs/index.cjs +118 -31
  25. package/dist/cjs/index.cjs.map +1 -1
  26. package/dist/cjs/index.d.ts +42 -13
  27. package/dist/cjs/index.d.ts.map +1 -1
  28. package/dist/cjs/libs/index.cjs +2 -3
  29. package/dist/cjs/libs/index.cjs.map +1 -1
  30. package/dist/cjs/libs/index.d.ts +2 -3
  31. package/dist/cjs/libs/index.d.ts.map +1 -1
  32. package/dist/cjs/libs/logger/index.cjs +5 -5
  33. package/dist/cjs/libs/logger/index.cjs.map +1 -1
  34. package/dist/cjs/libs/logger/index.d.ts +2 -2
  35. package/dist/cjs/libs/logger/index.d.ts.map +1 -1
  36. package/dist/cjs/libs/logger/kafkajs-logger-creator.cjs +2 -2
  37. package/dist/cjs/libs/logger/kafkajs-logger-creator.cjs.map +1 -1
  38. package/dist/cjs/libs/s3/index.cjs +3 -39
  39. package/dist/cjs/libs/s3/index.cjs.map +1 -1
  40. package/dist/cjs/libs/s3/index.d.ts +1 -2
  41. package/dist/cjs/libs/s3/index.d.ts.map +1 -1
  42. package/dist/cjs/libs/s3/s3.lib.cjs +174 -191
  43. package/dist/cjs/libs/s3/s3.lib.cjs.map +1 -1
  44. package/dist/cjs/libs/s3/s3.lib.d.ts +29 -22
  45. package/dist/cjs/libs/s3/s3.lib.d.ts.map +1 -1
  46. package/dist/cjs/processors/ActivityProcessor.cjs +36 -0
  47. package/dist/cjs/processors/ActivityProcessor.cjs.map +1 -0
  48. package/dist/cjs/processors/ActivityProcessor.d.ts +27 -0
  49. package/dist/cjs/processors/ActivityProcessor.d.ts.map +1 -0
  50. package/dist/cjs/processors/ActivityProcessor.test.cjs +84 -0
  51. package/dist/cjs/processors/ActivityProcessor.test.cjs.map +1 -0
  52. package/dist/cjs/processors/ActivityProcessor.test.d.ts +2 -0
  53. package/dist/cjs/processors/ActivityProcessor.test.d.ts.map +1 -0
  54. package/dist/cjs/processors/ChatProcessor.cjs +335 -163
  55. package/dist/cjs/processors/ChatProcessor.cjs.map +1 -1
  56. package/dist/cjs/processors/ChatProcessor.d.ts +56 -9
  57. package/dist/cjs/processors/ChatProcessor.d.ts.map +1 -1
  58. package/dist/cjs/processors/ChatProcessor.test.cjs +450 -0
  59. package/dist/cjs/processors/ChatProcessor.test.cjs.map +1 -0
  60. package/dist/cjs/processors/ChatProcessor.test.d.ts +2 -0
  61. package/dist/cjs/processors/ChatProcessor.test.d.ts.map +1 -0
  62. package/dist/cjs/processors/ModelsProcessor.cjs +2 -2
  63. package/dist/cjs/processors/ModelsProcessor.cjs.map +1 -1
  64. package/dist/cjs/processors/index.cjs +3 -2
  65. package/dist/cjs/processors/index.cjs.map +1 -1
  66. package/dist/cjs/processors/index.d.ts +3 -2
  67. package/dist/cjs/processors/index.d.ts.map +1 -1
  68. package/dist/cjs/services/AIService.cjs +50 -31
  69. package/dist/cjs/services/AIService.cjs.map +1 -1
  70. package/dist/cjs/services/AIService.d.ts +16 -5
  71. package/dist/cjs/services/AIService.d.ts.map +1 -1
  72. package/dist/cjs/services/InternalEventsHandler.cjs +5 -5
  73. package/dist/cjs/services/InternalEventsHandler.cjs.map +1 -1
  74. package/dist/cjs/services/InternalEventsHandler.d.ts +3 -1
  75. package/dist/cjs/services/InternalEventsHandler.d.ts.map +1 -1
  76. package/dist/cjs/services/ModelFetcher.cjs +9 -15
  77. package/dist/cjs/services/ModelFetcher.cjs.map +1 -1
  78. package/dist/cjs/services/ModelFetcher.d.ts +2 -7
  79. package/dist/cjs/services/ModelFetcher.d.ts.map +1 -1
  80. package/dist/cjs/services/RedisService.cjs +35 -32
  81. package/dist/cjs/services/RedisService.cjs.map +1 -1
  82. package/dist/cjs/services/RedisService.d.ts +5 -2
  83. package/dist/cjs/services/RedisService.d.ts.map +1 -1
  84. package/dist/cjs/services/SocketService.cjs +19 -20
  85. package/dist/cjs/services/SocketService.cjs.map +1 -1
  86. package/dist/cjs/services/SocketService.d.ts +9 -6
  87. package/dist/cjs/services/SocketService.d.ts.map +1 -1
  88. package/dist/cjs/services/index.cjs +5 -6
  89. package/dist/cjs/services/index.cjs.map +1 -1
  90. package/dist/cjs/services/index.d.ts +5 -6
  91. package/dist/cjs/services/index.d.ts.map +1 -1
  92. package/dist/cjs/store/AgentStore.cjs +4 -5
  93. package/dist/cjs/store/AgentStore.cjs.map +1 -1
  94. package/dist/cjs/store/AgentStore.d.ts +2 -1
  95. package/dist/cjs/store/AgentStore.d.ts.map +1 -1
  96. package/dist/cjs/store/ArtifactStore.cjs +2 -4
  97. package/dist/cjs/store/ArtifactStore.cjs.map +1 -1
  98. package/dist/cjs/store/ConfigStore.cjs +8 -11
  99. package/dist/cjs/store/ConfigStore.cjs.map +1 -1
  100. package/dist/cjs/store/ConfigStore.d.ts.map +1 -1
  101. package/dist/cjs/store/ConfigStore.test.cjs +2 -2
  102. package/dist/cjs/store/ConfigStore.test.cjs.map +1 -1
  103. package/dist/cjs/store/ModelStore.cjs +4 -4
  104. package/dist/cjs/store/ModelStore.cjs.map +1 -1
  105. package/dist/cjs/store/ModelStore.test.cjs +17 -17
  106. package/dist/cjs/store/ModelStore.test.cjs.map +1 -1
  107. package/dist/cjs/store/index.cjs +4 -4
  108. package/dist/cjs/store/index.cjs.map +1 -1
  109. package/dist/cjs/store/index.d.ts +4 -4
  110. package/dist/cjs/store/index.d.ts.map +1 -1
  111. package/dist/cjs/tools/proposeFormValuesTool.d.ts +2 -2
  112. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -0
  113. package/dist/esm/config.d.ts +57 -23
  114. package/dist/esm/config.d.ts.map +1 -1
  115. package/dist/esm/config.js +88 -36
  116. package/dist/esm/config.js.map +1 -1
  117. package/dist/esm/helpers/AIHelper.d.ts +21 -13
  118. package/dist/esm/helpers/AIHelper.d.ts.map +1 -1
  119. package/dist/esm/helpers/AIHelper.js +159 -98
  120. package/dist/esm/helpers/AIHelper.js.map +1 -1
  121. package/dist/esm/helpers/AIHelper.test.js +21 -14
  122. package/dist/esm/helpers/AIHelper.test.js.map +1 -1
  123. package/dist/esm/helpers/ConfigHelper.d.ts.map +1 -1
  124. package/dist/esm/helpers/ConfigHelper.js +17 -9
  125. package/dist/esm/helpers/ConfigHelper.js.map +1 -1
  126. package/dist/esm/helpers/ContextLimiter.js +2 -3
  127. package/dist/esm/helpers/ContextLimiter.js.map +1 -1
  128. package/dist/esm/helpers/FileHelper.d.ts +19 -25
  129. package/dist/esm/helpers/FileHelper.d.ts.map +1 -1
  130. package/dist/esm/helpers/FileHelper.js +132 -149
  131. package/dist/esm/helpers/FileHelper.js.map +1 -1
  132. package/dist/esm/helpers/index.d.ts +4 -5
  133. package/dist/esm/helpers/index.d.ts.map +1 -1
  134. package/dist/esm/helpers/index.js +4 -5
  135. package/dist/esm/helpers/index.js.map +1 -1
  136. package/dist/esm/index.d.ts +42 -13
  137. package/dist/esm/index.d.ts.map +1 -1
  138. package/dist/esm/index.js +87 -12
  139. package/dist/esm/index.js.map +1 -1
  140. package/dist/esm/libs/index.d.ts +2 -3
  141. package/dist/esm/libs/index.d.ts.map +1 -1
  142. package/dist/esm/libs/index.js +2 -3
  143. package/dist/esm/libs/index.js.map +1 -1
  144. package/dist/esm/libs/logger/index.d.ts +2 -2
  145. package/dist/esm/libs/logger/index.d.ts.map +1 -1
  146. package/dist/esm/libs/logger/index.js +2 -2
  147. package/dist/esm/libs/logger/index.js.map +1 -1
  148. package/dist/esm/libs/logger/kafkajs-logger-creator.js +1 -1
  149. package/dist/esm/libs/logger/kafkajs-logger-creator.js.map +1 -1
  150. package/dist/esm/libs/s3/index.d.ts +1 -2
  151. package/dist/esm/libs/s3/index.d.ts.map +1 -1
  152. package/dist/esm/libs/s3/index.js +1 -2
  153. package/dist/esm/libs/s3/index.js.map +1 -1
  154. package/dist/esm/libs/s3/s3.lib.d.ts +29 -22
  155. package/dist/esm/libs/s3/s3.lib.d.ts.map +1 -1
  156. package/dist/esm/libs/s3/s3.lib.js +178 -177
  157. package/dist/esm/libs/s3/s3.lib.js.map +1 -1
  158. package/dist/esm/processors/ActivityProcessor.d.ts +27 -0
  159. package/dist/esm/processors/ActivityProcessor.d.ts.map +1 -0
  160. package/dist/esm/processors/ActivityProcessor.js +33 -0
  161. package/dist/esm/processors/ActivityProcessor.js.map +1 -0
  162. package/dist/esm/processors/ActivityProcessor.test.d.ts +2 -0
  163. package/dist/esm/processors/ActivityProcessor.test.d.ts.map +1 -0
  164. package/dist/esm/processors/ActivityProcessor.test.js +82 -0
  165. package/dist/esm/processors/ActivityProcessor.test.js.map +1 -0
  166. package/dist/esm/processors/ChatProcessor.d.ts +56 -9
  167. package/dist/esm/processors/ChatProcessor.d.ts.map +1 -1
  168. package/dist/esm/processors/ChatProcessor.js +334 -153
  169. package/dist/esm/processors/ChatProcessor.js.map +1 -1
  170. package/dist/esm/processors/ChatProcessor.test.d.ts +2 -0
  171. package/dist/esm/processors/ChatProcessor.test.d.ts.map +1 -0
  172. package/dist/esm/processors/ChatProcessor.test.js +448 -0
  173. package/dist/esm/processors/ChatProcessor.test.js.map +1 -0
  174. package/dist/esm/processors/ModelsProcessor.js +1 -1
  175. package/dist/esm/processors/ModelsProcessor.js.map +1 -1
  176. package/dist/esm/processors/index.d.ts +3 -2
  177. package/dist/esm/processors/index.d.ts.map +1 -1
  178. package/dist/esm/processors/index.js +3 -2
  179. package/dist/esm/processors/index.js.map +1 -1
  180. package/dist/esm/services/AIService.d.ts +16 -5
  181. package/dist/esm/services/AIService.d.ts.map +1 -1
  182. package/dist/esm/services/AIService.js +53 -32
  183. package/dist/esm/services/AIService.js.map +1 -1
  184. package/dist/esm/services/InternalEventsHandler.d.ts +3 -1
  185. package/dist/esm/services/InternalEventsHandler.d.ts.map +1 -1
  186. package/dist/esm/services/InternalEventsHandler.js +10 -8
  187. package/dist/esm/services/InternalEventsHandler.js.map +1 -1
  188. package/dist/esm/services/ModelFetcher.d.ts +2 -7
  189. package/dist/esm/services/ModelFetcher.d.ts.map +1 -1
  190. package/dist/esm/services/ModelFetcher.js +4 -9
  191. package/dist/esm/services/ModelFetcher.js.map +1 -1
  192. package/dist/esm/services/RedisService.d.ts +5 -2
  193. package/dist/esm/services/RedisService.d.ts.map +1 -1
  194. package/dist/esm/services/RedisService.js +25 -21
  195. package/dist/esm/services/RedisService.js.map +1 -1
  196. package/dist/esm/services/SocketService.d.ts +9 -6
  197. package/dist/esm/services/SocketService.d.ts.map +1 -1
  198. package/dist/esm/services/SocketService.js +15 -13
  199. package/dist/esm/services/SocketService.js.map +1 -1
  200. package/dist/esm/services/index.d.ts +5 -6
  201. package/dist/esm/services/index.d.ts.map +1 -1
  202. package/dist/esm/services/index.js +5 -6
  203. package/dist/esm/services/index.js.map +1 -1
  204. package/dist/esm/store/AgentStore.d.ts +2 -1
  205. package/dist/esm/store/AgentStore.d.ts.map +1 -1
  206. package/dist/esm/store/AgentStore.js +5 -5
  207. package/dist/esm/store/AgentStore.js.map +1 -1
  208. package/dist/esm/store/ArtifactStore.js +3 -7
  209. package/dist/esm/store/ArtifactStore.js.map +1 -1
  210. package/dist/esm/store/ConfigStore.d.ts.map +1 -1
  211. package/dist/esm/store/ConfigStore.js +16 -19
  212. package/dist/esm/store/ConfigStore.js.map +1 -1
  213. package/dist/esm/store/ConfigStore.test.js +1 -1
  214. package/dist/esm/store/ConfigStore.test.js.map +1 -1
  215. package/dist/esm/store/ModelStore.js +6 -6
  216. package/dist/esm/store/ModelStore.js.map +1 -1
  217. package/dist/esm/store/ModelStore.test.js +12 -12
  218. package/dist/esm/store/ModelStore.test.js.map +1 -1
  219. package/dist/esm/store/index.d.ts +4 -4
  220. package/dist/esm/store/index.d.ts.map +1 -1
  221. package/dist/esm/store/index.js +4 -4
  222. package/dist/esm/store/index.js.map +1 -1
  223. package/dist/esm/tools/proposeFormValuesTool.d.ts +2 -2
  224. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -0
  225. package/package.json +15 -15
  226. package/dist/cjs/helpers/SetupHelper.cjs +0 -37
  227. package/dist/cjs/helpers/SetupHelper.cjs.map +0 -1
  228. package/dist/cjs/helpers/SetupHelper.d.ts +0 -5
  229. package/dist/cjs/helpers/SetupHelper.d.ts.map +0 -1
  230. package/dist/cjs/libs/kafka/config.cjs +0 -8
  231. package/dist/cjs/libs/kafka/config.cjs.map +0 -1
  232. package/dist/cjs/libs/kafka/config.d.ts +0 -5
  233. package/dist/cjs/libs/kafka/config.d.ts.map +0 -1
  234. package/dist/cjs/libs/kafka/consumer.cjs +0 -133
  235. package/dist/cjs/libs/kafka/consumer.cjs.map +0 -1
  236. package/dist/cjs/libs/kafka/consumer.d.ts +0 -16
  237. package/dist/cjs/libs/kafka/consumer.d.ts.map +0 -1
  238. package/dist/cjs/libs/kafka/index.cjs +0 -19
  239. package/dist/cjs/libs/kafka/index.cjs.map +0 -1
  240. package/dist/cjs/libs/kafka/index.d.ts +0 -3
  241. package/dist/cjs/libs/kafka/index.d.ts.map +0 -1
  242. package/dist/cjs/libs/kafka/kafka.cjs +0 -27
  243. package/dist/cjs/libs/kafka/kafka.cjs.map +0 -1
  244. package/dist/cjs/libs/kafka/kafka.d.ts +0 -3
  245. package/dist/cjs/libs/kafka/kafka.d.ts.map +0 -1
  246. package/dist/cjs/libs/kafka/producer.cjs +0 -48
  247. package/dist/cjs/libs/kafka/producer.cjs.map +0 -1
  248. package/dist/cjs/libs/kafka/producer.d.ts +0 -11
  249. package/dist/cjs/libs/kafka/producer.d.ts.map +0 -1
  250. package/dist/cjs/libs/logger/config.cjs +0 -9
  251. package/dist/cjs/libs/logger/config.cjs.map +0 -1
  252. package/dist/cjs/libs/logger/config.d.ts +0 -5
  253. package/dist/cjs/libs/logger/config.d.ts.map +0 -1
  254. package/dist/cjs/libs/s3/config.cjs +0 -10
  255. package/dist/cjs/libs/s3/config.cjs.map +0 -1
  256. package/dist/cjs/libs/s3/config.d.ts +0 -7
  257. package/dist/cjs/libs/s3/config.d.ts.map +0 -1
  258. package/dist/cjs/services/KafkaService.cjs +0 -123
  259. package/dist/cjs/services/KafkaService.cjs.map +0 -1
  260. package/dist/cjs/services/KafkaService.d.ts +0 -35
  261. package/dist/cjs/services/KafkaService.d.ts.map +0 -1
  262. package/dist/esm/helpers/SetupHelper.d.ts +0 -5
  263. package/dist/esm/helpers/SetupHelper.d.ts.map +0 -1
  264. package/dist/esm/helpers/SetupHelper.js +0 -32
  265. package/dist/esm/helpers/SetupHelper.js.map +0 -1
  266. package/dist/esm/libs/kafka/config.d.ts +0 -5
  267. package/dist/esm/libs/kafka/config.d.ts.map +0 -1
  268. package/dist/esm/libs/kafka/config.js +0 -5
  269. package/dist/esm/libs/kafka/config.js.map +0 -1
  270. package/dist/esm/libs/kafka/consumer.d.ts +0 -16
  271. package/dist/esm/libs/kafka/consumer.d.ts.map +0 -1
  272. package/dist/esm/libs/kafka/consumer.js +0 -126
  273. package/dist/esm/libs/kafka/consumer.js.map +0 -1
  274. package/dist/esm/libs/kafka/index.d.ts +0 -3
  275. package/dist/esm/libs/kafka/index.d.ts.map +0 -1
  276. package/dist/esm/libs/kafka/index.js +0 -3
  277. package/dist/esm/libs/kafka/index.js.map +0 -1
  278. package/dist/esm/libs/kafka/kafka.d.ts +0 -3
  279. package/dist/esm/libs/kafka/kafka.d.ts.map +0 -1
  280. package/dist/esm/libs/kafka/kafka.js +0 -24
  281. package/dist/esm/libs/kafka/kafka.js.map +0 -1
  282. package/dist/esm/libs/kafka/producer.d.ts +0 -11
  283. package/dist/esm/libs/kafka/producer.d.ts.map +0 -1
  284. package/dist/esm/libs/kafka/producer.js +0 -44
  285. package/dist/esm/libs/kafka/producer.js.map +0 -1
  286. package/dist/esm/libs/logger/config.d.ts +0 -5
  287. package/dist/esm/libs/logger/config.d.ts.map +0 -1
  288. package/dist/esm/libs/logger/config.js +0 -6
  289. package/dist/esm/libs/logger/config.js.map +0 -1
  290. package/dist/esm/libs/s3/config.d.ts +0 -7
  291. package/dist/esm/libs/s3/config.d.ts.map +0 -1
  292. package/dist/esm/libs/s3/config.js +0 -7
  293. package/dist/esm/libs/s3/config.js.map +0 -1
  294. package/dist/esm/services/KafkaService.d.ts +0 -35
  295. package/dist/esm/services/KafkaService.d.ts.map +0 -1
  296. package/dist/esm/services/KafkaService.js +0 -120
  297. package/dist/esm/services/KafkaService.js.map +0 -1
  298. package/dist/tsconfig.cjs.tsbuildinfo +0 -1
  299. package/dist/tsconfig.esm.tsbuildinfo +0 -1
@@ -1,65 +1,192 @@
1
- import { AgentStatus, AgentToolCallStatus, ChatType, MessageRole, SortOrder, StreamChunkType } from '@multiplayer-app/ai-agent-types';
2
- import { socketService } from '../services/index.js';
3
- import { kafkaService } from '../services/index.js';
4
- import { AIHelper } from '../helpers/index.js';
5
- import { AgentProcessEventType, agentStore } from '../store/index.js';
6
- import { ContextLimiter } from '../helpers/index.js';
7
- import { config } from '../config.js';
8
- import { PassThrough, pipeline } from 'stream';
9
- import { promisify } from 'util';
10
- import { logger } from '../libs/logger/index.js';
11
- const pipelineAsync = promisify(pipeline);
1
+ import { AgentStatus, AgentToolCallStatus, ChatType, MessageRole, SortOrder, StreamChunkType, ActivityOperationName } from '@multiplayer-app/ai-agent-types';
2
+ import { AIHelper, FileHelper } from '../helpers';
3
+ import { AgentProcessEventType } from '../store';
4
+ import { ContextLimiter } from '../helpers';
5
+ import { PassThrough } from 'stream';
6
+ import { logger } from '../libs/logger';
12
7
  export class ChatProcessor {
13
- constructor(chatRepository, messageRepository, artifactStore) {
14
- this.chatRepository = chatRepository;
15
- this.messageRepository = messageRepository;
16
- this.artifactStore = artifactStore;
8
+ aiHelper;
9
+ chatRepository;
10
+ messageRepository;
11
+ artifactStore;
12
+ activityRepository;
13
+ config;
14
+ socketService;
15
+ agentStore;
16
+ debug;
17
+ constructor(params) {
18
+ this.chatRepository = params.chatRepository;
19
+ this.messageRepository = params.messageRepository;
20
+ this.artifactStore = params.artifactStore;
21
+ this.config = params.config;
22
+ this.socketService = params.socketService;
23
+ this.agentStore = params.agentStore;
24
+ this.activityRepository = params.activityRepository;
25
+ const fileHelper = new FileHelper(params.s3Lib, this.config);
26
+ this.aiHelper = new AIHelper(fileHelper, this.config);
27
+ this.debug = this.config.debug;
17
28
  }
18
29
  getTemporaryTitle(contextKey) {
19
30
  return `${contextKey} session ${new Date().toISOString()}`;
20
31
  }
32
+ isTemporaryTitle(title) {
33
+ // Matches pattern: "{contextKey} session {ISO_DATE_STRING}"
34
+ // Example: "default session 2026-01-23T10:30:45.123Z"
35
+ // toISOString() always includes milliseconds, so we require them
36
+ const pattern = /^.+ session \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/;
37
+ return pattern.test(title);
38
+ }
39
+ sanitizeProviderMetadata(providerMetadata) {
40
+ return this.stripReasoningMetadata(providerMetadata);
41
+ }
42
+ isPlainObject(value) {
43
+ return !!value && typeof value === 'object' && !Array.isArray(value);
44
+ }
45
+ mergeMissingUsageFields(target, source) {
46
+ for (const [key, sourceValue] of Object.entries(source)) {
47
+ const targetValue = target[key];
48
+ if (targetValue === undefined) {
49
+ target[key] = sourceValue;
50
+ continue;
51
+ }
52
+ if (this.isPlainObject(targetValue) && this.isPlainObject(sourceValue)) {
53
+ this.mergeMissingUsageFields(targetValue, sourceValue);
54
+ }
55
+ }
56
+ }
57
+ extractCostUsageFields(source) {
58
+ const extracted = {};
59
+ for (const [key, value] of Object.entries(source)) {
60
+ const normalizedKey = key.toLowerCase();
61
+ if (normalizedKey.includes('cost')) {
62
+ extracted[key] = value;
63
+ continue;
64
+ }
65
+ if (this.isPlainObject(value)) {
66
+ const nestedCostFields = this.extractCostUsageFields(value);
67
+ if (Object.keys(nestedCostFields).length > 0) {
68
+ extracted[key] = nestedCostFields;
69
+ }
70
+ }
71
+ }
72
+ return extracted;
73
+ }
74
+ mergeUsageWithProviderMetadata(stepUsage, providerMetadata) {
75
+ const mergedUsage = this.isPlainObject(stepUsage) ? { ...stepUsage } : {};
76
+ let hasProviderUsage = false;
77
+ if (this.isPlainObject(providerMetadata)) {
78
+ for (const providerEntry of Object.values(providerMetadata)) {
79
+ if (!this.isPlainObject(providerEntry) || !this.isPlainObject(providerEntry.usage)) {
80
+ continue;
81
+ }
82
+ const providerCostUsage = this.extractCostUsageFields(providerEntry.usage);
83
+ if (Object.keys(providerCostUsage).length === 0) {
84
+ continue;
85
+ }
86
+ hasProviderUsage = true;
87
+ this.mergeMissingUsageFields(mergedUsage, providerCostUsage);
88
+ }
89
+ }
90
+ if (this.isPlainObject(stepUsage)) {
91
+ return mergedUsage;
92
+ }
93
+ if (hasProviderUsage) {
94
+ return mergedUsage;
95
+ }
96
+ return stepUsage;
97
+ }
98
+ stripReasoningMetadata(value) {
99
+ if (Array.isArray(value)) {
100
+ return value
101
+ .map((entry) => this.stripReasoningMetadata(entry))
102
+ .filter((entry) => entry !== undefined);
103
+ }
104
+ if (!value || typeof value !== 'object') {
105
+ return value;
106
+ }
107
+ const record = value;
108
+ const entryType = record.type;
109
+ if (typeof entryType === 'string' && entryType.startsWith('reasoning.')) {
110
+ return undefined;
111
+ }
112
+ const sanitized = {};
113
+ for (const [key, entryValue] of Object.entries(record)) {
114
+ const normalizedKey = key.toLowerCase();
115
+ if (normalizedKey === 'reasoning_details' ||
116
+ normalizedKey === 'reasoningdetails' ||
117
+ normalizedKey === 'reasoning') {
118
+ continue;
119
+ }
120
+ const sanitizedValue = this.stripReasoningMetadata(entryValue);
121
+ if (sanitizedValue !== undefined) {
122
+ sanitized[key] = sanitizedValue;
123
+ }
124
+ }
125
+ return sanitized;
126
+ }
21
127
  async listChats(params) {
22
- var _a, _b;
23
128
  // Build filter object from params
24
129
  const filter = {};
25
- if (params === null || params === void 0 ? void 0 : params.userId) {
130
+ if (params?.userId) {
26
131
  filter.userId = params.userId;
27
132
  }
28
- if (params === null || params === void 0 ? void 0 : params.contextKey) {
133
+ if (params?.contextKey) {
29
134
  filter.contextKey = params.contextKey;
30
135
  }
31
- // Build query options for sort and limit with defaults
136
+ // Build query options for sort and limit with defaults.
32
137
  const options = {
33
138
  sort: {
34
- field: (_a = params === null || params === void 0 ? void 0 : params.sortField) !== null && _a !== void 0 ? _a : 'updatedAt',
35
- order: (_b = params === null || params === void 0 ? void 0 : params.sortOrder) !== null && _b !== void 0 ? _b : SortOrder.Desc
139
+ field: params?.sortField ?? 'updatedAt',
140
+ order: params?.sortOrder ?? SortOrder.Desc
36
141
  },
37
- limit: params === null || params === void 0 ? void 0 : params.limit
142
+ skip: params?.skip,
143
+ limit: params?.limit
144
+ };
145
+ const [total, data] = await Promise.all([
146
+ this.chatRepository.count(filter),
147
+ this.chatRepository.find(filter, options)
148
+ ]);
149
+ return {
150
+ cursor: {
151
+ ...(params?.skip != null ? { skip: params.skip } : {}),
152
+ ...(params?.limit != null ? { limit: params.limit } : {}),
153
+ total
154
+ },
155
+ data
38
156
  };
39
- // Use aggregation to fetch chats with related messages
40
- return this.chatRepository.findWithMessages(filter, options);
41
157
  }
42
158
  async getChat(chatId) {
43
159
  const chat = await this.chatRepository.findById(chatId);
44
160
  if (!chat) {
45
161
  throw new Error('Chat not found');
46
162
  }
47
- const messages = await this.messageRepository.findByChatId(chatId);
48
- return {
49
- ...chat,
50
- messages
51
- };
163
+ return chat;
164
+ }
165
+ /**
166
+ * Get messages for a chat with optional cursor pagination.
167
+ * When limit is omitted, returns all messages (backward compatible).
168
+ * Messages are returned in chronological order (oldest → newest).
169
+ */
170
+ async getMessages(chatId, options) {
171
+ const chat = await this.chatRepository.findById(chatId);
172
+ if (!chat) {
173
+ throw new Error('Chat not found');
174
+ }
175
+ return this.messageRepository.findByChatIdPaginated(chatId, options);
52
176
  }
53
177
  async deleteChat(chatId) {
54
178
  const deleted = await this.chatRepository.delete(chatId);
55
179
  if (!deleted) {
56
180
  throw new Error('Chat not found');
57
181
  }
182
+ await Promise.all([
183
+ this.messageRepository.deleteByChatId(chatId),
184
+ this.activityRepository.deleteByGroupId(chatId), // todo: discuss if this is needed
185
+ ]);
58
186
  this.artifactStore.deleteArtifacts(chatId);
59
187
  }
60
188
  async upsertAndGetChat(payload, excludeSocketId) {
61
- var _a;
62
- const targetUserId = (_a = payload.userId) !== null && _a !== void 0 ? _a : 'guest';
189
+ const targetUserId = payload.userId ?? 'guest';
63
190
  let chat = null;
64
191
  if (payload.chatId) {
65
192
  chat = await this.chatRepository.findById(payload.chatId);
@@ -91,7 +218,7 @@ export class ChatProcessor {
91
218
  if (!content) {
92
219
  return this.getTemporaryTitle(payload.contextKey);
93
220
  }
94
- return AIHelper.generateTitleForMessage(payload.contextKey, [{
221
+ return this.aiHelper.generateTitleForMessage(payload.contextKey, [{
95
222
  role: MessageRole.User,
96
223
  content: content
97
224
  }]);
@@ -102,18 +229,17 @@ export class ChatProcessor {
102
229
  role,
103
230
  content: messageData.content,
104
231
  agentName: messageData.agentName,
105
- attachments: attachments !== null && attachments !== void 0 ? attachments : [],
232
+ attachments: attachments ?? [],
106
233
  reasoning: "",
107
234
  toolCalls: []
108
235
  });
109
236
  if (chat.userId) {
110
- socketService.emitMessageUpdate(chat.userId, message, excludeSocketId);
237
+ this.socketService.emitMessageUpdate(chat.userId, message, excludeSocketId);
111
238
  }
112
239
  return message;
113
240
  }
114
241
  async createChat(payload, excludeSocketId) {
115
- var _a;
116
- const targetUserId = (_a = payload.userId) !== null && _a !== void 0 ? _a : 'guest';
242
+ const targetUserId = payload.userId ?? 'guest';
117
243
  const contextKey = 'contextKey' in payload ? payload.contextKey : 'default';
118
244
  const metadata = 'metadata' in payload ? payload.metadata : {};
119
245
  const chat = await this.chatRepository.create({
@@ -125,12 +251,7 @@ export class ChatProcessor {
125
251
  metadata,
126
252
  ...(payload.model ? { model: payload.model } : {})
127
253
  });
128
- await kafkaService.sendChatTitleGenerationEvent(chat.id);
129
- const initialChatResponse = {
130
- ...chat,
131
- messages: []
132
- };
133
- socketService.emitChatUpdate(targetUserId, initialChatResponse, excludeSocketId);
254
+ this.socketService.emitChatUpdate(targetUserId, chat, excludeSocketId);
134
255
  return chat;
135
256
  }
136
257
  /**
@@ -138,23 +259,22 @@ export class ChatProcessor {
138
259
  * This updates the message containing the tool call and optionally appends a System message.
139
260
  */
140
261
  async recordToolCallAction(params) {
141
- var _a, _b, _c, _d;
142
262
  const chat = await this.chatRepository.findById(params.chatId);
143
263
  if (!chat) {
144
264
  throw new Error('Chat not found');
145
265
  }
146
266
  const messages = await this.messageRepository.findByChatId(params.chatId);
147
- const message = messages.find((m) => { var _a; return ((_a = m.toolCalls) !== null && _a !== void 0 ? _a : []).some((c) => c.id === params.toolCallId); });
267
+ const message = messages.find((m) => (m.toolCalls ?? []).some((c) => c.id === params.toolCallId));
148
268
  if (!message) {
149
269
  throw new Error('Tool call not found');
150
270
  }
151
- const toolCalls = (_a = message.toolCalls) !== null && _a !== void 0 ? _a : [];
271
+ const toolCalls = message.toolCalls ?? [];
152
272
  const target = toolCalls.find((c) => c.id === params.toolCallId);
153
273
  if (!target) {
154
274
  throw new Error('Tool call not found');
155
275
  }
156
276
  const now = new Date().toISOString();
157
- const output = ((_b = target.output) !== null && _b !== void 0 ? _b : {});
277
+ const output = (target.output ?? {});
158
278
  const mp = (output['_mp'] && typeof output['_mp'] === 'object' && !Array.isArray(output['_mp']))
159
279
  ? output['_mp']
160
280
  : {};
@@ -164,14 +284,14 @@ export class ChatProcessor {
164
284
  lastAction: {
165
285
  action: params.action,
166
286
  at: now,
167
- data: (_c = params.data) !== null && _c !== void 0 ? _c : {},
287
+ data: params.data ?? {},
168
288
  },
169
289
  actions: [
170
290
  ...actions,
171
291
  {
172
292
  action: params.action,
173
293
  at: now,
174
- data: (_d = params.data) !== null && _d !== void 0 ? _d : {},
294
+ data: params.data ?? {},
175
295
  }
176
296
  ]
177
297
  };
@@ -186,7 +306,7 @@ export class ChatProcessor {
186
306
  await this.messageRepository.update(message.id, { toolCalls });
187
307
  // Bump chat updatedAt so listChats ordering reflects the action.
188
308
  await this.chatRepository.update(chat.id, { updatedAt: now });
189
- socketService.emitMessageUpdate(chat.userId, updatedMessage, params.excludeSocketId);
309
+ this.socketService.emitMessageUpdate(chat.userId, updatedMessage, params.excludeSocketId);
190
310
  if (params.systemMessage) {
191
311
  //todo discuss support for system messages
192
312
  //await this.createMessage(chat, MessageRole.System, params.systemMessage, undefined, params.excludeSocketId);
@@ -194,26 +314,25 @@ export class ChatProcessor {
194
314
  return { ok: true };
195
315
  }
196
316
  async streamMessageStep(params) {
197
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
198
317
  const { chat, assistantMessage, existingMessages, signal, excludeSocketId, agentOptions } = params;
199
318
  if (signal.aborted) {
200
319
  return;
201
320
  }
202
- const result = await AIHelper.streamAssistantResponse(existingMessages, signal, agentOptions);
321
+ const result = await this.aiHelper.streamAssistantResponse(existingMessages, signal, agentOptions);
203
322
  try {
204
323
  for await (const chunk of result.fullStream) {
205
324
  if (chunk.type === 'error') {
206
- await agentStore.shareAgentProcessEvent(chat.id, { type: AgentProcessEventType.Error, data: chunk.error });
325
+ await this.agentStore.shareAgentProcessEvent(chat.id, { type: AgentProcessEventType.Error, data: chunk.error });
207
326
  assistantMessage.content = chunk.error.message || 'Sorry, I cannot process you request due to the error';
208
327
  await this.messageRepository.update(assistantMessage.id, assistantMessage);
209
328
  await this.chatRepository.update(chat.id, { status: AgentStatus.Error });
210
329
  continue;
211
330
  }
212
331
  if (chunk.type === 'abort') {
213
- await agentStore.shareAgentProcessEvent(chat.id, { type: AgentProcessEventType.Aborted, data: undefined });
332
+ await this.agentStore.shareAgentProcessEvent(chat.id, { type: AgentProcessEventType.Aborted, data: undefined });
214
333
  await this.chatRepository.update(chat.id, { status: AgentStatus.Aborted });
215
334
  await this.messageRepository.update(assistantMessage.id, assistantMessage);
216
- socketService.emitMessageUpdate(chat.userId, assistantMessage, excludeSocketId);
335
+ this.socketService.emitMessageUpdate(chat.userId, assistantMessage, excludeSocketId);
217
336
  continue;
218
337
  }
219
338
  if (chunk.type === 'finish') {
@@ -226,41 +345,44 @@ export class ChatProcessor {
226
345
  }
227
346
  if (chunk.totalUsage && typeof chunk.totalUsage === 'object') {
228
347
  const totalUsage = chunk.totalUsage;
229
- assistantMessage.tokens = (_a = totalUsage.totalTokens) !== null && _a !== void 0 ? _a : (((_b = totalUsage.promptTokens) !== null && _b !== void 0 ? _b : 0) + ((_c = totalUsage.completionTokens) !== null && _c !== void 0 ? _c : 0));
348
+ assistantMessage.tokens = totalUsage.totalTokens ??
349
+ ((totalUsage.promptTokens ?? 0) + (totalUsage.completionTokens ?? 0));
230
350
  }
231
351
  await this.messageRepository.update(assistantMessage.id, { ...assistantMessage });
232
352
  if (chunk.finishReason === 'stop') {
233
- if ((_d = assistantMessage.toolCalls) === null || _d === void 0 ? void 0 : _d.some(toolCall => toolCall.requiresConfirmation && toolCall.approvalId && !toolCall.output)) {
234
- await this.chatRepository.update(chat.id, { status: AgentStatus.WaitingForUserAction });
235
- }
236
- else if (!assistantMessage.content && ((_e = assistantMessage.toolCalls) === null || _e === void 0 ? void 0 : _e.length) && assistantMessage.toolCalls[((_f = assistantMessage.toolCalls) === null || _f === void 0 ? void 0 : _f.length) - 1].output) {
237
- // handle tool-calls stop, openrouter provider does not return valid type
238
- await agentStore.shareAgentProcessEvent(chat.id, { type: AgentProcessEventType.Update, data: assistantMessage });
239
- await this.streamMessageStep(params);
240
- continue;
241
- }
242
- else {
243
- await this.chatRepository.update(chat.id, { status: AgentStatus.Finished });
353
+ await this.chatRepository.update(chat.id, { status: AgentStatus.Finished });
354
+ if (chat.title && this.isTemporaryTitle(chat.title)) {
355
+ const title = await this.aiHelper.generateTitleForMessage(chat.contextKey, existingMessages.filter(m => m.role === MessageRole.User), (stepResult) => {
356
+ return this.storeStepActivity({
357
+ chat,
358
+ stepResult,
359
+ name: ActivityOperationName.TITLE_GENERATION,
360
+ sourceId: chat.id,
361
+ sourceType: 'Chat',
362
+ tenants: params.tenants || {},
363
+ });
364
+ });
365
+ await this.chatRepository.update(chat.id, { title });
366
+ this.socketService.emitChatUpdate(chat.userId, { ...chat, title });
244
367
  }
245
- await agentStore.shareAgentProcessEvent(chat.id, { type: AgentProcessEventType.Finished, data: assistantMessage });
246
- continue;
247
368
  }
248
369
  if (chunk.finishReason === 'tool-calls') {
249
- if ((_g = assistantMessage.toolCalls) === null || _g === void 0 ? void 0 : _g.some(toolCall => toolCall.requiresConfirmation && toolCall.approvalId && !toolCall.output)) {
370
+ if (assistantMessage.toolCalls?.some(toolCall => toolCall.requiresConfirmation && toolCall.approvalId && !toolCall.output)) {
250
371
  await this.chatRepository.update(chat.id, { status: AgentStatus.WaitingForUserAction });
251
- await agentStore.shareAgentProcessEvent(chat.id, { type: AgentProcessEventType.Finished, data: assistantMessage });
252
- }
253
- else {
254
- await agentStore.shareAgentProcessEvent(chat.id, {
255
- type: AgentProcessEventType.Update,
256
- data: assistantMessage
257
- });
258
- await this.streamMessageStep(params);
372
+ await this.agentStore.shareAgentProcessEvent(chat.id, { type: AgentProcessEventType.Finished, data: assistantMessage });
373
+ continue;
259
374
  }
260
- continue;
261
375
  }
262
376
  //todo: Handle other finish reasons // length, content, error, other, undefined
263
- await agentStore.shareAgentProcessEvent(chat.id, { type: AgentProcessEventType.Finished, data: assistantMessage });
377
+ await this.agentStore.shareAgentProcessEvent(chat.id, { type: AgentProcessEventType.Finished, data: assistantMessage });
378
+ if (assistantMessage.activity) {
379
+ const groupedMeta = await this.activityRepository.getGroupedMetadataByParentId(assistantMessage.activity);
380
+ await this.activityRepository.updateMetadata(assistantMessage.activity, {
381
+ usage: groupedMeta,
382
+ finishReason: chunk.finishReason,
383
+ responseTimestamp: new Date().toISOString(),
384
+ });
385
+ }
264
386
  continue;
265
387
  }
266
388
  if (chunk.type === 'text-delta') {
@@ -269,8 +391,8 @@ export class ChatProcessor {
269
391
  ...assistantMessage,
270
392
  content: assistantMessage.content
271
393
  };
272
- socketService.emitMessageUpdate(chat.userId, updatedMessage, excludeSocketId);
273
- await agentStore.shareAgentProcessEvent(chat.id, { type: AgentProcessEventType.Update, data: updatedMessage });
394
+ this.socketService.emitMessageUpdate(chat.userId, updatedMessage, excludeSocketId);
395
+ await this.agentStore.shareAgentProcessEvent(chat.id, { type: AgentProcessEventType.Update, data: updatedMessage });
274
396
  await this.messageRepository.update(assistantMessage.id, { content: assistantMessage.content });
275
397
  continue;
276
398
  }
@@ -285,8 +407,8 @@ export class ChatProcessor {
285
407
  });
286
408
  continue;
287
409
  }
288
- if (chunk.type === 'tool-call') { //Todo possible place to handle user-approval
289
- const toolCall = (_h = assistantMessage.toolCalls) === null || _h === void 0 ? void 0 : _h.find(toolCall => toolCall.id === chunk.toolCallId);
410
+ if (chunk.type === 'tool-call') {
411
+ const toolCall = assistantMessage.toolCalls?.find(toolCall => toolCall.id === chunk.toolCallId);
290
412
  if (toolCall) {
291
413
  toolCall.status = AgentToolCallStatus.Running;
292
414
  toolCall.input = chunk.input;
@@ -294,15 +416,15 @@ export class ChatProcessor {
294
416
  continue;
295
417
  }
296
418
  if (chunk.type === 'tool-error') {
297
- const toolCall = (_j = assistantMessage.toolCalls) === null || _j === void 0 ? void 0 : _j.find(toolCall => toolCall.id === chunk.toolCallId);
419
+ const toolCall = assistantMessage.toolCalls?.find(toolCall => toolCall.id === chunk.toolCallId);
298
420
  if (toolCall) {
299
421
  toolCall.status = AgentToolCallStatus.Failed;
300
- toolCall.error = JSON.stringify(chunk.error);
422
+ toolCall.error = chunk.error.message || JSON.stringify(chunk.error);
301
423
  }
302
424
  continue;
303
425
  }
304
426
  if (chunk.type === 'tool-approval-request') {
305
- const toolCall = (_k = assistantMessage.toolCalls) === null || _k === void 0 ? void 0 : _k.find(toolCall => toolCall.id === chunk.toolCall.toolCallId);
427
+ const toolCall = assistantMessage.toolCalls?.find(toolCall => toolCall.id === chunk.toolCall.toolCallId);
306
428
  if (toolCall) {
307
429
  toolCall.requiresConfirmation = true;
308
430
  toolCall.approvalId = chunk.approvalId;
@@ -310,7 +432,7 @@ export class ChatProcessor {
310
432
  continue;
311
433
  }
312
434
  if (chunk.type === 'tool-result') {
313
- const toolCall = (_l = assistantMessage.toolCalls) === null || _l === void 0 ? void 0 : _l.find(toolCall => toolCall.id === chunk.toolCallId);
435
+ const toolCall = assistantMessage.toolCalls?.find(toolCall => toolCall.id === chunk.toolCallId);
314
436
  if (toolCall) {
315
437
  if (chunk.output.requiresApproval) {
316
438
  toolCall.requiresConfirmation = true;
@@ -325,9 +447,9 @@ export class ChatProcessor {
325
447
  if (!assistantMessage.reasoning)
326
448
  assistantMessage.reasoning = '';
327
449
  assistantMessage.reasoning += chunk.text;
328
- socketService.emitMessageUpdate(chat.userId, assistantMessage, excludeSocketId);
450
+ this.socketService.emitMessageUpdate(chat.userId, assistantMessage, excludeSocketId);
329
451
  await this.messageRepository.update(assistantMessage.id, { reasoning: assistantMessage.reasoning });
330
- await agentStore.shareAgentProcessEvent(chat.id, { type: AgentProcessEventType.Update, data: assistantMessage });
452
+ await this.agentStore.shareAgentProcessEvent(chat.id, { type: AgentProcessEventType.Update, data: assistantMessage });
331
453
  continue;
332
454
  }
333
455
  }
@@ -336,7 +458,7 @@ export class ChatProcessor {
336
458
  if (streamError instanceof Error && streamError.name === 'AbortError') {
337
459
  return;
338
460
  }
339
- await agentStore.shareAgentProcessEvent(chat.id, { type: AgentProcessEventType.Error, data: streamError });
461
+ await this.agentStore.shareAgentProcessEvent(chat.id, { type: AgentProcessEventType.Error, data: streamError });
340
462
  throw streamError;
341
463
  }
342
464
  }
@@ -344,16 +466,15 @@ export class ChatProcessor {
344
466
  return 'approvalId' in payload;
345
467
  }
346
468
  async processApprovalPayload(chat, payload) {
347
- var _a, _b, _c;
348
469
  const assistantMessage = await this.messageRepository.findById(payload.messageId);
349
470
  if (!assistantMessage || assistantMessage.chat !== chat.id) {
350
471
  throw new Error(`Assistant message with id ${payload.messageId} not found`);
351
472
  }
352
- const agentOptions = await AIHelper.getAgentOptions({
473
+ const agentOptions = await this.aiHelper.getAgentOptions({
353
474
  agentName: assistantMessage.agentName,
354
475
  context: payload.context
355
476
  });
356
- const toolCall = (_a = assistantMessage.toolCalls) === null || _a === void 0 ? void 0 : _a.find(tc => tc.approvalId === payload.approvalId);
477
+ const toolCall = assistantMessage.toolCalls?.find(tc => tc.approvalId === payload.approvalId);
357
478
  if (!toolCall) {
358
479
  // continue, tool is not found
359
480
  return {
@@ -371,7 +492,7 @@ export class ChatProcessor {
371
492
  toolCall.status = AgentToolCallStatus.Failed;
372
493
  }
373
494
  else {
374
- const executeFunction = (_c = (_b = agentOptions.tools) === null || _b === void 0 ? void 0 : _b[toolCall.name]) === null || _c === void 0 ? void 0 : _c.execute;
495
+ const executeFunction = agentOptions.tools?.[toolCall.name]?.execute;
375
496
  if (executeFunction) {
376
497
  try {
377
498
  toolCall.output = await executeFunction(toolCall.input, { toolCallId: toolCall.id, messages: [] });
@@ -402,32 +523,105 @@ export class ChatProcessor {
402
523
  }
403
524
  async processNewUserMessage(chat, payload, prevMessages, excludeSocketId) {
404
525
  const userMessage = await this.createMessage(chat, MessageRole.User, { content: payload.content, agentName: undefined }, payload.attachments);
405
- await agentStore.shareAgentProcessEvent(chat.id, { type: AgentProcessEventType.Update, data: userMessage });
406
- const agentOptions = await AIHelper.getAgentOptions({
526
+ await this.agentStore.shareAgentProcessEvent(chat.id, { type: AgentProcessEventType.Update, data: userMessage });
527
+ let assistantMessage = await this.createMessage(chat, MessageRole.Assistant, { content: '', agentName: undefined }, undefined, excludeSocketId);
528
+ const parentActivity = await this.activityRepository.create({
529
+ ownerId: chat.userId,
530
+ groupId: chat.id,
531
+ name: ActivityOperationName.MESSAGE_PROCESSING,
532
+ tenants: {}, //todo
533
+ sourceId: userMessage.id,
534
+ sourceType: 'AgentMessage',
535
+ metadata: {
536
+ contextKey: chat.contextKey,
537
+ modelId: this.aiHelper.getLanguageModelId(chat.model),
538
+ },
539
+ });
540
+ const agentOptions = await this.aiHelper.getAgentOptions({
407
541
  contextKey: chat.contextKey,
408
- messages: await AIHelper.convertMessages([...prevMessages, userMessage], true),
542
+ messages: [...prevMessages, userMessage],
409
543
  context: payload.context,
410
544
  agentName: undefined,
411
545
  modelId: chat.model,
546
+ }, {
547
+ onStepFinish: async (stepResult) => {
548
+ await this.storeStepActivity({
549
+ chat,
550
+ parentId: parentActivity.id,
551
+ stepResult,
552
+ name: ActivityOperationName.AGENT_SELECTION,
553
+ sourceId: userMessage.id,
554
+ sourceType: 'AgentMessage',
555
+ tenants: payload.tenants || {},
556
+ });
557
+ }
558
+ });
559
+ const updatedAssistantMessage = await this.messageRepository.update(assistantMessage.id, {
560
+ agentName: agentOptions.name,
561
+ activity: parentActivity.id
562
+ });
563
+ await this.activityRepository.update(parentActivity.id, {
564
+ metadata: {
565
+ ...parentActivity.metadata,
566
+ agentOptions: {
567
+ name: agentOptions.name,
568
+ modelId: this.aiHelper.getLanguageModelId(agentOptions.model),
569
+ temperature: agentOptions.temperature,
570
+ maxOutputTokens: agentOptions.maxOutputTokens,
571
+ topP: agentOptions.topP,
572
+ topK: agentOptions.topK,
573
+ presencePenalty: agentOptions.presencePenalty,
574
+ frequencyPenalty: agentOptions.frequencyPenalty,
575
+ stopSequences: agentOptions.stopSequences,
576
+ seed: agentOptions.seed,
577
+ },
578
+ },
412
579
  });
413
- const assistantMessage = await this.createMessage(chat, MessageRole.Assistant, { content: ' ', agentName: agentOptions.name }, undefined, excludeSocketId);
414
- assistantMessage.content = '';
580
+ if (!updatedAssistantMessage) {
581
+ throw new Error(`Assistant message with id ${assistantMessage.id} not found after update`);
582
+ }
583
+ assistantMessage = updatedAssistantMessage;
415
584
  return {
416
585
  userMessage,
417
586
  assistantMessage,
418
587
  agentOptions,
419
588
  };
420
589
  }
590
+ async storeStepActivity(params) {
591
+ try {
592
+ const stepResult = params.stepResult;
593
+ const mergedUsage = this.mergeUsageWithProviderMetadata(stepResult.usage, stepResult.providerMetadata);
594
+ const activity = await this.activityRepository.create({
595
+ ownerId: params.chat.userId,
596
+ groupId: params.chat.id,
597
+ name: params.name,
598
+ tenants: params.tenants || {},
599
+ sourceId: params.sourceId,
600
+ sourceType: params.sourceType,
601
+ metadata: {
602
+ finishReason: stepResult.finishReason,
603
+ usage: mergedUsage,
604
+ responseTimestamp: stepResult.response.timestamp,
605
+ modelId: stepResult.response.modelId,
606
+ messages: this.debug ? stepResult.request?.body?.messages : undefined,
607
+ },
608
+ parentId: params.parentId,
609
+ });
610
+ }
611
+ catch (error) {
612
+ logger.error({ error, chatId: params.chat.id, parentId: params.parentId }, 'Failed to store step activity');
613
+ }
614
+ }
421
615
  async streamMessage(chat, payload, excludeSocketId, onAgentStart) {
422
616
  try {
423
- const abortController = agentStore.registerAgentProcess(chat.id);
424
- onAgentStart === null || onAgentStart === void 0 ? void 0 : onAgentStart();
617
+ const abortController = this.agentStore.registerAgentProcess(chat.id);
618
+ onAgentStart?.();
425
619
  let assistantMessage;
426
620
  let agentOptions;
427
621
  const existingMessages = await this.messageRepository.findByChatId(chat.id);
428
622
  // Limit context to prevent exceeding token limits
429
623
  const limitedMessages = ContextLimiter.limitContext(existingMessages, {
430
- maxMessages: config.ai.maxContextMessages,
624
+ maxMessages: this.config.ai.maxContextMessages,
431
625
  keepFirstUserMessage: true,
432
626
  keepSystemMessages: true,
433
627
  });
@@ -449,6 +643,17 @@ export class ChatProcessor {
449
643
  agentOptions = result.agentOptions;
450
644
  limitedMessages.push(result.userMessage);
451
645
  }
646
+ agentOptions.onStepFinish = (stepResult) => {
647
+ return this.storeStepActivity({
648
+ chat,
649
+ parentId: assistantMessage.activity,
650
+ stepResult,
651
+ name: ActivityOperationName.STEP_FINISHED,
652
+ sourceId: assistantMessage.id,
653
+ sourceType: 'AgentMessage',
654
+ tenants: payload.tenants || {},
655
+ });
656
+ };
452
657
  await this.streamMessageStep({
453
658
  chat,
454
659
  existingMessages: limitedMessages,
@@ -456,6 +661,7 @@ export class ChatProcessor {
456
661
  agentOptions,
457
662
  excludeSocketId: excludeSocketId,
458
663
  signal: abortController.signal,
664
+ tenants: payload.tenants || {},
459
665
  });
460
666
  }
461
667
  catch (error) {
@@ -492,7 +698,7 @@ export class ChatProcessor {
492
698
  return null;
493
699
  }
494
700
  }
495
- getMessageStream(chatId) {
701
+ getMessageStream(chatId, signal) {
496
702
  const stream = new PassThrough();
497
703
  let ended = false;
498
704
  const endStream = (error) => {
@@ -513,13 +719,15 @@ export class ChatProcessor {
513
719
  }
514
720
  };
515
721
  const pushChunk = (chunk) => {
516
- if (ended || stream.destroyed || stream.writableEnded)
722
+ if (ended || stream.destroyed || stream.writableEnded || signal?.aborted)
517
723
  return;
518
724
  stream.write(`data: ${JSON.stringify(chunk)}\n\n`);
519
725
  };
520
726
  const listener = (event) => {
521
- if (ended)
727
+ if (signal?.aborted) {
728
+ endStream();
522
729
  return;
730
+ }
523
731
  try {
524
732
  const chunk = this.eventToChunk(event);
525
733
  if (chunk) {
@@ -529,7 +737,6 @@ export class ChatProcessor {
529
737
  event.type === AgentProcessEventType.Error ||
530
738
  event.type === AgentProcessEventType.Aborted) {
531
739
  endStream();
532
- agentStore.removeListener(chatId, listener);
533
740
  }
534
741
  }
535
742
  catch (err) {
@@ -538,21 +745,18 @@ export class ChatProcessor {
538
745
  error: err instanceof Error ? err.message : 'Unknown error occurred',
539
746
  });
540
747
  endStream(err);
541
- agentStore.removeListener(chatId, listener);
542
748
  }
543
749
  };
544
- // Cleanup on consumer side closing
545
750
  const closeHandler = () => {
546
- agentStore.removeListener(chatId, listener);
751
+ this.agentStore.removeListener(chatId, listener);
547
752
  };
548
753
  const errorHandler = (err) => {
549
- logger.error({ err }, 'Readable stream error');
550
- agentStore.removeListener(chatId, listener);
754
+ signal?.removeEventListener('abort', endStream);
551
755
  endStream(err);
552
756
  };
553
757
  stream.on('close', closeHandler);
554
758
  stream.on('error', errorHandler);
555
- const listenerAttached = agentStore.addListener(chatId, listener);
759
+ const listenerAttached = this.agentStore.addListener(chatId, listener);
556
760
  if (!listenerAttached) {
557
761
  // Remove stream listeners if listener attachment failed to prevent memory leak
558
762
  stream.removeListener('close', closeHandler);
@@ -561,50 +765,27 @@ export class ChatProcessor {
561
765
  }
562
766
  return stream;
563
767
  }
564
- async createMessageStream(payload, excludeSocketId) {
768
+ async createMessageStream(payload, excludeSocketId, signal) {
565
769
  const stream = new PassThrough();
566
- (async () => {
567
- try {
568
- const chat = await this.upsertAndGetChat(payload, excludeSocketId);
569
- // Send chat metadata first
570
- if (!('chatId' in payload) && !('messageId' in payload) && chat) {
571
- stream.write(`data: ${JSON.stringify({
572
- type: StreamChunkType.Chat,
573
- chatId: chat.id,
574
- chat,
575
- })}\n\n`);
576
- }
577
- await this.streamMessage(chat, payload, excludeSocketId, async () => {
578
- if (stream.destroyed || stream.writableEnded) {
579
- return;
580
- }
581
- const messageStream = this.getMessageStream(chat.id);
582
- // If client disconnects, destroy inner stream
583
- stream.on('close', () => {
584
- if (!messageStream.destroyed) {
585
- messageStream.destroy();
586
- }
587
- });
588
- await pipelineAsync(messageStream, stream);
589
- });
590
- }
591
- catch (error) {
592
- logger.error({ error }, 'createMessageStream failed');
593
- if (!stream.destroyed && !stream.writableEnded) {
594
- stream.write(`data: ${JSON.stringify({
595
- type: StreamChunkType.Error,
596
- error: error instanceof Error ? error.message : 'Unknown error occurred',
597
- })}\n\n`);
598
- stream.write('data: [DONE]\n\n');
599
- stream.end();
600
- }
601
- }
602
- })().catch((err) => {
603
- logger.error({ err }, 'Unhandled stream task error');
604
- if (!stream.destroyed)
605
- stream.destroy(err);
770
+ this.runMessageStream(stream, payload, excludeSocketId, signal)
771
+ .catch(err => {
772
+ logger.error({ err }, 'Stream task failed');
606
773
  });
607
774
  return stream;
608
775
  }
776
+ async runMessageStream(stream, payload, excludeSocketId, signal) {
777
+ const chat = await this.upsertAndGetChat(payload, excludeSocketId);
778
+ if (!('chatId' in payload) && !('messageId' in payload) && chat) {
779
+ stream.write(`data: ${JSON.stringify({
780
+ type: StreamChunkType.Chat,
781
+ chatId: chat.id,
782
+ chat,
783
+ })}\n\n`);
784
+ }
785
+ await this.streamMessage(chat, payload, excludeSocketId, () => {
786
+ const messageStream = this.getMessageStream(chat.id, signal);
787
+ messageStream.pipe(stream);
788
+ });
789
+ }
609
790
  }
610
791
  //# sourceMappingURL=ChatProcessor.js.map