@multiplayer-app/ai-agent-node 0.1.0-beta.5 → 0.1.0-beta.50

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 (274) hide show
  1. package/README.md +2 -2
  2. package/dist/cjs/config.cjs +88 -37
  3. package/dist/cjs/config.cjs.map +1 -1
  4. package/dist/cjs/config.d.ts +57 -23
  5. package/dist/cjs/config.d.ts.map +1 -1
  6. package/dist/cjs/helpers/AIHelper.cjs +127 -65
  7. package/dist/cjs/helpers/AIHelper.cjs.map +1 -1
  8. package/dist/cjs/helpers/AIHelper.d.ts +22 -16
  9. package/dist/cjs/helpers/AIHelper.d.ts.map +1 -1
  10. package/dist/cjs/helpers/AIHelper.test.cjs +22 -15
  11. package/dist/cjs/helpers/AIHelper.test.cjs.map +1 -1
  12. package/dist/cjs/helpers/ConfigHelper.cjs +15 -6
  13. package/dist/cjs/helpers/ConfigHelper.cjs.map +1 -1
  14. package/dist/cjs/helpers/ConfigHelper.d.ts.map +1 -1
  15. package/dist/cjs/helpers/FileHelper.cjs +131 -151
  16. package/dist/cjs/helpers/FileHelper.cjs.map +1 -1
  17. package/dist/cjs/helpers/FileHelper.d.ts +19 -25
  18. package/dist/cjs/helpers/FileHelper.d.ts.map +1 -1
  19. package/dist/cjs/helpers/index.cjs +0 -1
  20. package/dist/cjs/helpers/index.cjs.map +1 -1
  21. package/dist/cjs/helpers/index.d.ts +0 -1
  22. package/dist/cjs/helpers/index.d.ts.map +1 -1
  23. package/dist/cjs/index.cjs +120 -28
  24. package/dist/cjs/index.cjs.map +1 -1
  25. package/dist/cjs/index.d.ts +43 -11
  26. package/dist/cjs/index.d.ts.map +1 -1
  27. package/dist/cjs/libs/index.cjs +0 -1
  28. package/dist/cjs/libs/index.cjs.map +1 -1
  29. package/dist/cjs/libs/index.d.ts +0 -1
  30. package/dist/cjs/libs/index.d.ts.map +1 -1
  31. package/dist/cjs/libs/s3/index.cjs +3 -39
  32. package/dist/cjs/libs/s3/index.cjs.map +1 -1
  33. package/dist/cjs/libs/s3/index.d.ts +1 -2
  34. package/dist/cjs/libs/s3/index.d.ts.map +1 -1
  35. package/dist/cjs/libs/s3/s3.lib.cjs +173 -186
  36. package/dist/cjs/libs/s3/s3.lib.cjs.map +1 -1
  37. package/dist/cjs/libs/s3/s3.lib.d.ts +29 -22
  38. package/dist/cjs/libs/s3/s3.lib.d.ts.map +1 -1
  39. package/dist/cjs/processors/ActivityProcessor.cjs +39 -0
  40. package/dist/cjs/processors/ActivityProcessor.cjs.map +1 -0
  41. package/dist/cjs/processors/ActivityProcessor.d.ts +32 -0
  42. package/dist/cjs/processors/ActivityProcessor.d.ts.map +1 -0
  43. package/dist/cjs/processors/ActivityProcessor.test.cjs +84 -0
  44. package/dist/cjs/processors/ActivityProcessor.test.cjs.map +1 -0
  45. package/dist/cjs/processors/ActivityProcessor.test.d.ts +2 -0
  46. package/dist/cjs/processors/ActivityProcessor.test.d.ts.map +1 -0
  47. package/dist/cjs/processors/AgentProcessor.cjs +46 -0
  48. package/dist/cjs/processors/AgentProcessor.cjs.map +1 -0
  49. package/dist/cjs/processors/AgentProcessor.d.ts +25 -0
  50. package/dist/cjs/processors/AgentProcessor.d.ts.map +1 -0
  51. package/dist/cjs/processors/AgentProcessor.test.cjs +103 -0
  52. package/dist/cjs/processors/AgentProcessor.test.cjs.map +1 -0
  53. package/dist/cjs/processors/AgentProcessor.test.d.ts +2 -0
  54. package/dist/cjs/processors/AgentProcessor.test.d.ts.map +1 -0
  55. package/dist/cjs/processors/ChatProcessor.cjs +355 -122
  56. package/dist/cjs/processors/ChatProcessor.cjs.map +1 -1
  57. package/dist/cjs/processors/ChatProcessor.d.ts +71 -11
  58. package/dist/cjs/processors/ChatProcessor.d.ts.map +1 -1
  59. package/dist/cjs/processors/ChatProcessor.test.cjs +762 -0
  60. package/dist/cjs/processors/ChatProcessor.test.cjs.map +1 -0
  61. package/dist/cjs/processors/ChatProcessor.test.d.ts +2 -0
  62. package/dist/cjs/processors/ChatProcessor.test.d.ts.map +1 -0
  63. package/dist/cjs/processors/index.cjs +2 -0
  64. package/dist/cjs/processors/index.cjs.map +1 -1
  65. package/dist/cjs/processors/index.d.ts +2 -0
  66. package/dist/cjs/processors/index.d.ts.map +1 -1
  67. package/dist/cjs/services/AIService.cjs +87 -21
  68. package/dist/cjs/services/AIService.cjs.map +1 -1
  69. package/dist/cjs/services/AIService.d.ts +19 -7
  70. package/dist/cjs/services/AIService.d.ts.map +1 -1
  71. package/dist/cjs/services/InternalEventsHandler.cjs +3 -3
  72. package/dist/cjs/services/InternalEventsHandler.cjs.map +1 -1
  73. package/dist/cjs/services/InternalEventsHandler.d.ts +3 -1
  74. package/dist/cjs/services/InternalEventsHandler.d.ts.map +1 -1
  75. package/dist/cjs/services/ModelFetcher.cjs +2 -8
  76. package/dist/cjs/services/ModelFetcher.cjs.map +1 -1
  77. package/dist/cjs/services/ModelFetcher.d.ts +2 -7
  78. package/dist/cjs/services/ModelFetcher.d.ts.map +1 -1
  79. package/dist/cjs/services/RedisService.cjs +20 -16
  80. package/dist/cjs/services/RedisService.cjs.map +1 -1
  81. package/dist/cjs/services/RedisService.d.ts +5 -2
  82. package/dist/cjs/services/RedisService.d.ts.map +1 -1
  83. package/dist/cjs/services/SocketService.cjs +8 -8
  84. package/dist/cjs/services/SocketService.cjs.map +1 -1
  85. package/dist/cjs/services/SocketService.d.ts +9 -6
  86. package/dist/cjs/services/SocketService.d.ts.map +1 -1
  87. package/dist/cjs/services/index.cjs +0 -1
  88. package/dist/cjs/services/index.cjs.map +1 -1
  89. package/dist/cjs/services/index.d.ts +0 -1
  90. package/dist/cjs/services/index.d.ts.map +1 -1
  91. package/dist/cjs/store/AgentStore.cjs +3 -4
  92. package/dist/cjs/store/AgentStore.cjs.map +1 -1
  93. package/dist/cjs/store/AgentStore.d.ts +2 -1
  94. package/dist/cjs/store/AgentStore.d.ts.map +1 -1
  95. package/dist/cjs/store/ConfigStore.cjs +7 -3
  96. package/dist/cjs/store/ConfigStore.cjs.map +1 -1
  97. package/dist/cjs/store/ConfigStore.d.ts +1 -0
  98. package/dist/cjs/store/ConfigStore.d.ts.map +1 -1
  99. package/dist/cjs/tools/generateChartTool.d.ts +2 -2
  100. package/dist/cjs/tools/proposeFormValuesTool.d.ts +2 -2
  101. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  102. package/dist/esm/config.d.ts +57 -23
  103. package/dist/esm/config.d.ts.map +1 -1
  104. package/dist/esm/config.js +88 -35
  105. package/dist/esm/config.js.map +1 -1
  106. package/dist/esm/helpers/AIHelper.d.ts +22 -16
  107. package/dist/esm/helpers/AIHelper.d.ts.map +1 -1
  108. package/dist/esm/helpers/AIHelper.js +134 -70
  109. package/dist/esm/helpers/AIHelper.js.map +1 -1
  110. package/dist/esm/helpers/AIHelper.test.js +22 -15
  111. package/dist/esm/helpers/AIHelper.test.js.map +1 -1
  112. package/dist/esm/helpers/ConfigHelper.d.ts.map +1 -1
  113. package/dist/esm/helpers/ConfigHelper.js +15 -6
  114. package/dist/esm/helpers/ConfigHelper.js.map +1 -1
  115. package/dist/esm/helpers/FileHelper.d.ts +19 -25
  116. package/dist/esm/helpers/FileHelper.d.ts.map +1 -1
  117. package/dist/esm/helpers/FileHelper.js +131 -146
  118. package/dist/esm/helpers/FileHelper.js.map +1 -1
  119. package/dist/esm/helpers/index.d.ts +0 -1
  120. package/dist/esm/helpers/index.d.ts.map +1 -1
  121. package/dist/esm/helpers/index.js +0 -1
  122. package/dist/esm/helpers/index.js.map +1 -1
  123. package/dist/esm/index.d.ts +43 -11
  124. package/dist/esm/index.d.ts.map +1 -1
  125. package/dist/esm/index.js +92 -11
  126. package/dist/esm/index.js.map +1 -1
  127. package/dist/esm/libs/index.d.ts +0 -1
  128. package/dist/esm/libs/index.d.ts.map +1 -1
  129. package/dist/esm/libs/index.js +0 -1
  130. package/dist/esm/libs/index.js.map +1 -1
  131. package/dist/esm/libs/s3/index.d.ts +1 -2
  132. package/dist/esm/libs/s3/index.d.ts.map +1 -1
  133. package/dist/esm/libs/s3/index.js +1 -2
  134. package/dist/esm/libs/s3/index.js.map +1 -1
  135. package/dist/esm/libs/s3/s3.lib.d.ts +29 -22
  136. package/dist/esm/libs/s3/s3.lib.d.ts.map +1 -1
  137. package/dist/esm/libs/s3/s3.lib.js +177 -172
  138. package/dist/esm/libs/s3/s3.lib.js.map +1 -1
  139. package/dist/esm/processors/ActivityProcessor.d.ts +32 -0
  140. package/dist/esm/processors/ActivityProcessor.d.ts.map +1 -0
  141. package/dist/esm/processors/ActivityProcessor.js +36 -0
  142. package/dist/esm/processors/ActivityProcessor.js.map +1 -0
  143. package/dist/esm/processors/ActivityProcessor.test.d.ts +2 -0
  144. package/dist/esm/processors/ActivityProcessor.test.d.ts.map +1 -0
  145. package/dist/esm/processors/ActivityProcessor.test.js +82 -0
  146. package/dist/esm/processors/ActivityProcessor.test.js.map +1 -0
  147. package/dist/esm/processors/AgentProcessor.d.ts +25 -0
  148. package/dist/esm/processors/AgentProcessor.d.ts.map +1 -0
  149. package/dist/esm/processors/AgentProcessor.js +43 -0
  150. package/dist/esm/processors/AgentProcessor.js.map +1 -0
  151. package/dist/esm/processors/AgentProcessor.test.d.ts +2 -0
  152. package/dist/esm/processors/AgentProcessor.test.d.ts.map +1 -0
  153. package/dist/esm/processors/AgentProcessor.test.js +101 -0
  154. package/dist/esm/processors/AgentProcessor.test.js.map +1 -0
  155. package/dist/esm/processors/ChatProcessor.d.ts +71 -11
  156. package/dist/esm/processors/ChatProcessor.d.ts.map +1 -1
  157. package/dist/esm/processors/ChatProcessor.js +366 -126
  158. package/dist/esm/processors/ChatProcessor.js.map +1 -1
  159. package/dist/esm/processors/ChatProcessor.test.d.ts +2 -0
  160. package/dist/esm/processors/ChatProcessor.test.d.ts.map +1 -0
  161. package/dist/esm/processors/ChatProcessor.test.js +760 -0
  162. package/dist/esm/processors/ChatProcessor.test.js.map +1 -0
  163. package/dist/esm/processors/index.d.ts +2 -0
  164. package/dist/esm/processors/index.d.ts.map +1 -1
  165. package/dist/esm/processors/index.js +2 -0
  166. package/dist/esm/processors/index.js.map +1 -1
  167. package/dist/esm/services/AIService.d.ts +19 -7
  168. package/dist/esm/services/AIService.d.ts.map +1 -1
  169. package/dist/esm/services/AIService.js +91 -24
  170. package/dist/esm/services/AIService.js.map +1 -1
  171. package/dist/esm/services/InternalEventsHandler.d.ts +3 -1
  172. package/dist/esm/services/InternalEventsHandler.d.ts.map +1 -1
  173. package/dist/esm/services/InternalEventsHandler.js +4 -3
  174. package/dist/esm/services/InternalEventsHandler.js.map +1 -1
  175. package/dist/esm/services/ModelFetcher.d.ts +2 -7
  176. package/dist/esm/services/ModelFetcher.d.ts.map +1 -1
  177. package/dist/esm/services/ModelFetcher.js +2 -8
  178. package/dist/esm/services/ModelFetcher.js.map +1 -1
  179. package/dist/esm/services/RedisService.d.ts +5 -2
  180. package/dist/esm/services/RedisService.d.ts.map +1 -1
  181. package/dist/esm/services/RedisService.js +21 -14
  182. package/dist/esm/services/RedisService.js.map +1 -1
  183. package/dist/esm/services/SocketService.d.ts +9 -6
  184. package/dist/esm/services/SocketService.d.ts.map +1 -1
  185. package/dist/esm/services/SocketService.js +10 -6
  186. package/dist/esm/services/SocketService.js.map +1 -1
  187. package/dist/esm/services/index.d.ts +0 -1
  188. package/dist/esm/services/index.d.ts.map +1 -1
  189. package/dist/esm/services/index.js +0 -1
  190. package/dist/esm/services/index.js.map +1 -1
  191. package/dist/esm/store/AgentStore.d.ts +2 -1
  192. package/dist/esm/store/AgentStore.d.ts.map +1 -1
  193. package/dist/esm/store/AgentStore.js +4 -2
  194. package/dist/esm/store/AgentStore.js.map +1 -1
  195. package/dist/esm/store/ConfigStore.d.ts +1 -0
  196. package/dist/esm/store/ConfigStore.d.ts.map +1 -1
  197. package/dist/esm/store/ConfigStore.js +7 -3
  198. package/dist/esm/store/ConfigStore.js.map +1 -1
  199. package/dist/esm/tools/generateChartTool.d.ts +2 -2
  200. package/dist/esm/tools/proposeFormValuesTool.d.ts +2 -2
  201. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
  202. package/package.json +12 -12
  203. package/dist/cjs/helpers/SetupHelper.cjs +0 -37
  204. package/dist/cjs/helpers/SetupHelper.cjs.map +0 -1
  205. package/dist/cjs/helpers/SetupHelper.d.ts +0 -5
  206. package/dist/cjs/helpers/SetupHelper.d.ts.map +0 -1
  207. package/dist/cjs/libs/kafka/config.cjs +0 -8
  208. package/dist/cjs/libs/kafka/config.cjs.map +0 -1
  209. package/dist/cjs/libs/kafka/config.d.ts +0 -5
  210. package/dist/cjs/libs/kafka/config.d.ts.map +0 -1
  211. package/dist/cjs/libs/kafka/consumer.cjs +0 -131
  212. package/dist/cjs/libs/kafka/consumer.cjs.map +0 -1
  213. package/dist/cjs/libs/kafka/consumer.d.ts +0 -16
  214. package/dist/cjs/libs/kafka/consumer.d.ts.map +0 -1
  215. package/dist/cjs/libs/kafka/index.cjs +0 -19
  216. package/dist/cjs/libs/kafka/index.cjs.map +0 -1
  217. package/dist/cjs/libs/kafka/index.d.ts +0 -3
  218. package/dist/cjs/libs/kafka/index.d.ts.map +0 -1
  219. package/dist/cjs/libs/kafka/kafka.cjs +0 -27
  220. package/dist/cjs/libs/kafka/kafka.cjs.map +0 -1
  221. package/dist/cjs/libs/kafka/kafka.d.ts +0 -3
  222. package/dist/cjs/libs/kafka/kafka.d.ts.map +0 -1
  223. package/dist/cjs/libs/kafka/producer.cjs +0 -48
  224. package/dist/cjs/libs/kafka/producer.cjs.map +0 -1
  225. package/dist/cjs/libs/kafka/producer.d.ts +0 -11
  226. package/dist/cjs/libs/kafka/producer.d.ts.map +0 -1
  227. package/dist/cjs/libs/logger/config.cjs +0 -8
  228. package/dist/cjs/libs/logger/config.cjs.map +0 -1
  229. package/dist/cjs/libs/logger/config.d.ts +0 -5
  230. package/dist/cjs/libs/logger/config.d.ts.map +0 -1
  231. package/dist/cjs/libs/s3/config.cjs +0 -10
  232. package/dist/cjs/libs/s3/config.cjs.map +0 -1
  233. package/dist/cjs/libs/s3/config.d.ts +0 -7
  234. package/dist/cjs/libs/s3/config.d.ts.map +0 -1
  235. package/dist/cjs/services/KafkaService.cjs +0 -122
  236. package/dist/cjs/services/KafkaService.cjs.map +0 -1
  237. package/dist/cjs/services/KafkaService.d.ts +0 -35
  238. package/dist/cjs/services/KafkaService.d.ts.map +0 -1
  239. package/dist/esm/helpers/SetupHelper.d.ts +0 -5
  240. package/dist/esm/helpers/SetupHelper.d.ts.map +0 -1
  241. package/dist/esm/helpers/SetupHelper.js +0 -32
  242. package/dist/esm/helpers/SetupHelper.js.map +0 -1
  243. package/dist/esm/libs/kafka/config.d.ts +0 -5
  244. package/dist/esm/libs/kafka/config.d.ts.map +0 -1
  245. package/dist/esm/libs/kafka/config.js +0 -5
  246. package/dist/esm/libs/kafka/config.js.map +0 -1
  247. package/dist/esm/libs/kafka/consumer.d.ts +0 -16
  248. package/dist/esm/libs/kafka/consumer.d.ts.map +0 -1
  249. package/dist/esm/libs/kafka/consumer.js +0 -125
  250. package/dist/esm/libs/kafka/consumer.js.map +0 -1
  251. package/dist/esm/libs/kafka/index.d.ts +0 -3
  252. package/dist/esm/libs/kafka/index.d.ts.map +0 -1
  253. package/dist/esm/libs/kafka/index.js +0 -3
  254. package/dist/esm/libs/kafka/index.js.map +0 -1
  255. package/dist/esm/libs/kafka/kafka.d.ts +0 -3
  256. package/dist/esm/libs/kafka/kafka.d.ts.map +0 -1
  257. package/dist/esm/libs/kafka/kafka.js +0 -24
  258. package/dist/esm/libs/kafka/kafka.js.map +0 -1
  259. package/dist/esm/libs/kafka/producer.d.ts +0 -11
  260. package/dist/esm/libs/kafka/producer.d.ts.map +0 -1
  261. package/dist/esm/libs/kafka/producer.js +0 -45
  262. package/dist/esm/libs/kafka/producer.js.map +0 -1
  263. package/dist/esm/libs/logger/config.d.ts +0 -5
  264. package/dist/esm/libs/logger/config.d.ts.map +0 -1
  265. package/dist/esm/libs/logger/config.js +0 -5
  266. package/dist/esm/libs/logger/config.js.map +0 -1
  267. package/dist/esm/libs/s3/config.d.ts +0 -7
  268. package/dist/esm/libs/s3/config.d.ts.map +0 -1
  269. package/dist/esm/libs/s3/config.js +0 -7
  270. package/dist/esm/libs/s3/config.js.map +0 -1
  271. package/dist/esm/services/KafkaService.d.ts +0 -35
  272. package/dist/esm/services/KafkaService.d.ts.map +0 -1
  273. package/dist/esm/services/KafkaService.js +0 -123
  274. package/dist/esm/services/KafkaService.js.map +0 -1
@@ -2,25 +2,110 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ChatProcessor = void 0;
4
4
  const ai_agent_types_1 = require("@multiplayer-app/ai-agent-types");
5
- const services_1 = require("../services/index.cjs");
6
- const services_2 = require("../services/index.cjs");
5
+ const zod_1 = require("zod");
7
6
  const helpers_1 = require("../helpers/index.cjs");
8
7
  const store_1 = require("../store/index.cjs");
9
8
  const helpers_2 = require("../helpers/index.cjs");
10
- const config_1 = require("../config.cjs");
11
9
  const stream_1 = require("stream");
12
- const util_1 = require("util");
13
10
  const logger_1 = require("../libs/logger/index.cjs");
14
- const pipelineAsync = (0, util_1.promisify)(stream_1.pipeline);
11
+ const store_2 = require("../store/index.cjs");
15
12
  class ChatProcessor {
16
- constructor(chatRepository, messageRepository, artifactStore) {
17
- this.chatRepository = chatRepository;
18
- this.messageRepository = messageRepository;
19
- this.artifactStore = artifactStore;
13
+ constructor(params) {
14
+ this.chatRepository = params.chatRepository;
15
+ this.messageRepository = params.messageRepository;
16
+ this.artifactStore = params.artifactStore;
17
+ this.config = params.config;
18
+ this.socketService = params.socketService;
19
+ this.agentStore = params.agentStore;
20
+ this.activityRepository = params.activityRepository;
21
+ this.agentConfigRepository = params.agentConfigRepository;
22
+ const fileHelper = new helpers_1.FileHelper(params.s3Lib, this.config);
23
+ this.aiHelper = new helpers_1.AIHelper(fileHelper, this.config);
24
+ this.debug = this.config.debug;
20
25
  }
21
26
  getTemporaryTitle(contextKey) {
22
27
  return `${contextKey} session ${new Date().toISOString()}`;
23
28
  }
29
+ isTemporaryTitle(title) {
30
+ // Matches pattern: "{contextKey} session {ISO_DATE_STRING}"
31
+ // Example: "default session 2026-01-23T10:30:45.123Z"
32
+ // toISOString() always includes milliseconds, so we require them
33
+ const pattern = /^.+ session \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/;
34
+ return pattern.test(title);
35
+ }
36
+ isPlainObject(value) {
37
+ return !!value && typeof value === 'object' && !Array.isArray(value);
38
+ }
39
+ mergeMissingUsageFields(target, source) {
40
+ for (const [key, sourceValue] of Object.entries(source)) {
41
+ const targetValue = target[key];
42
+ if (targetValue === undefined) {
43
+ target[key] = sourceValue;
44
+ continue;
45
+ }
46
+ if (this.isPlainObject(targetValue) && this.isPlainObject(sourceValue)) {
47
+ this.mergeMissingUsageFields(targetValue, sourceValue);
48
+ }
49
+ }
50
+ }
51
+ extractCostUsageFields(source) {
52
+ const extracted = {};
53
+ for (const [key, value] of Object.entries(source)) {
54
+ const normalizedKey = key.toLowerCase();
55
+ if (normalizedKey.includes('cost')) {
56
+ extracted[key] = value;
57
+ continue;
58
+ }
59
+ if (this.isPlainObject(value)) {
60
+ const nestedCostFields = this.extractCostUsageFields(value);
61
+ if (Object.keys(nestedCostFields).length > 0) {
62
+ extracted[key] = nestedCostFields;
63
+ }
64
+ }
65
+ }
66
+ return extracted;
67
+ }
68
+ mergeUsageWithProviderMetadata(stepUsage, providerMetadata) {
69
+ const mergedUsage = this.isPlainObject(stepUsage) ? { ...stepUsage } : {};
70
+ let hasProviderUsage = false;
71
+ if (this.isPlainObject(providerMetadata)) {
72
+ for (const providerEntry of Object.values(providerMetadata)) {
73
+ if (!this.isPlainObject(providerEntry) || !this.isPlainObject(providerEntry.usage)) {
74
+ continue;
75
+ }
76
+ const providerCostUsage = this.extractCostUsageFields(providerEntry.usage);
77
+ if (Object.keys(providerCostUsage).length === 0) {
78
+ continue;
79
+ }
80
+ hasProviderUsage = true;
81
+ this.mergeMissingUsageFields(mergedUsage, providerCostUsage);
82
+ }
83
+ }
84
+ if (this.isPlainObject(stepUsage)) {
85
+ return mergedUsage;
86
+ }
87
+ if (hasProviderUsage) {
88
+ return mergedUsage;
89
+ }
90
+ return stepUsage;
91
+ }
92
+ async validateToolCallInput(params) {
93
+ const agentOptions = await this.aiHelper.getAgentOptions({
94
+ agentName: params.agentName,
95
+ });
96
+ const tool = agentOptions.tools?.[params.toolName] ?? undefined;
97
+ const schema = tool?.inputSchema;
98
+ if (!schema) {
99
+ throw new Error(`Tool "${params.toolName}" schema not found`);
100
+ }
101
+ if (!(schema instanceof zod_1.z.ZodType)) {
102
+ throw new Error(`Tool "${params.toolName}" inputSchema must be a Zod schema`);
103
+ }
104
+ const result = schema.safeParse(params.input);
105
+ if (!result.success) {
106
+ throw new Error(`Invalid tool input for "${params.toolName}": ${result.error.message}`);
107
+ }
108
+ }
24
109
  async listChats(params) {
25
110
  // Build filter object from params
26
111
  const filter = {};
@@ -30,33 +115,56 @@ class ChatProcessor {
30
115
  if (params?.contextKey) {
31
116
  filter.contextKey = params.contextKey;
32
117
  }
33
- // Build query options for sort and limit with defaults
118
+ // Build query options for sort and limit with defaults.
34
119
  const options = {
35
120
  sort: {
36
121
  field: params?.sortField ?? 'updatedAt',
37
122
  order: params?.sortOrder ?? ai_agent_types_1.SortOrder.Desc
38
123
  },
124
+ skip: params?.skip,
39
125
  limit: params?.limit
40
126
  };
41
- // Use aggregation to fetch chats with related messages
42
- return this.chatRepository.findWithMessages(filter, options);
127
+ const [total, data] = await Promise.all([
128
+ this.chatRepository.count(filter),
129
+ this.chatRepository.find(filter, options)
130
+ ]);
131
+ return {
132
+ cursor: {
133
+ ...(params?.skip != null ? { skip: params.skip } : {}),
134
+ ...(params?.limit != null ? { limit: params.limit } : {}),
135
+ total
136
+ },
137
+ data
138
+ };
43
139
  }
44
140
  async getChat(chatId) {
45
141
  const chat = await this.chatRepository.findById(chatId);
46
142
  if (!chat) {
47
143
  throw new Error('Chat not found');
48
144
  }
49
- const messages = await this.messageRepository.findByChatId(chatId);
50
- return {
51
- ...chat,
52
- messages
53
- };
145
+ return chat;
146
+ }
147
+ /**
148
+ * Get messages for a chat with optional cursor pagination.
149
+ * When limit is omitted, returns all messages (backward compatible).
150
+ * Messages are returned in chronological order (oldest → newest).
151
+ */
152
+ async getMessages(chatId, options) {
153
+ const chat = await this.chatRepository.findById(chatId);
154
+ if (!chat) {
155
+ throw new Error('Chat not found');
156
+ }
157
+ return this.messageRepository.findByChatIdPaginated(chatId, options);
54
158
  }
55
159
  async deleteChat(chatId) {
56
160
  const deleted = await this.chatRepository.delete(chatId);
57
161
  if (!deleted) {
58
162
  throw new Error('Chat not found');
59
163
  }
164
+ await Promise.all([
165
+ this.messageRepository.deleteByChatId(chatId),
166
+ this.activityRepository.deleteByGroupId(chatId), // todo: discuss if this is needed
167
+ ]);
60
168
  this.artifactStore.deleteArtifacts(chatId);
61
169
  }
62
170
  async upsertAndGetChat(payload, excludeSocketId) {
@@ -92,7 +200,7 @@ class ChatProcessor {
92
200
  if (!content) {
93
201
  return this.getTemporaryTitle(payload.contextKey);
94
202
  }
95
- return helpers_1.AIHelper.generateTitleForMessage(payload.contextKey, [{
203
+ return this.aiHelper.generateTitleForMessage(payload.contextKey, [{
96
204
  role: ai_agent_types_1.MessageRole.User,
97
205
  content: content
98
206
  }]);
@@ -108,7 +216,7 @@ class ChatProcessor {
108
216
  toolCalls: []
109
217
  });
110
218
  if (chat.userId) {
111
- services_1.socketService.emitMessageUpdate(chat.userId, message, excludeSocketId);
219
+ this.socketService.emitMessageUpdate(chat.userId, message, excludeSocketId);
112
220
  }
113
221
  return message;
114
222
  }
@@ -125,12 +233,7 @@ class ChatProcessor {
125
233
  metadata,
126
234
  ...(payload.model ? { model: payload.model } : {})
127
235
  });
128
- await services_2.kafkaService.sendChatTitleGenerationEvent(chat.id);
129
- const initialChatResponse = {
130
- ...chat,
131
- messages: []
132
- };
133
- services_1.socketService.emitChatUpdate(targetUserId, initialChatResponse, excludeSocketId);
236
+ this.socketService.emitChatUpdate(targetUserId, chat, excludeSocketId);
134
237
  return chat;
135
238
  }
136
239
  /**
@@ -185,33 +288,75 @@ class ChatProcessor {
185
288
  await this.messageRepository.update(message.id, { toolCalls });
186
289
  // Bump chat updatedAt so listChats ordering reflects the action.
187
290
  await this.chatRepository.update(chat.id, { updatedAt: now });
188
- services_1.socketService.emitMessageUpdate(chat.userId, updatedMessage, params.excludeSocketId);
291
+ this.socketService.emitMessageUpdate(chat.userId, updatedMessage, params.excludeSocketId);
189
292
  if (params.systemMessage) {
190
293
  //todo discuss support for system messages
191
294
  //await this.createMessage(chat, MessageRole.System, params.systemMessage, undefined, params.excludeSocketId);
192
295
  }
193
296
  return { ok: true };
194
297
  }
298
+ /**
299
+ * Update selected fields (input/output/status) on a specific tool call.
300
+ */
301
+ async updateToolCall(params) {
302
+ if (params.input === undefined && params.output === undefined && params.status === undefined) {
303
+ throw new Error('At least one of input, output, or status must be provided');
304
+ }
305
+ const chat = await this.chatRepository.findById(params.chatId);
306
+ if (!chat) {
307
+ throw new Error('Chat not found');
308
+ }
309
+ if (params.userId && chat.userId !== params.userId) {
310
+ throw new Error('Chat does not belong to this user');
311
+ }
312
+ const message = await this.messageRepository.findById(params.messageId);
313
+ if (!message || message.chat !== params.chatId) {
314
+ throw new Error('Message not found or does not belong to this chat');
315
+ }
316
+ const targetToolCall = (message.toolCalls ?? []).find((tc) => tc.id === params.toolCallId);
317
+ if (!targetToolCall) {
318
+ throw new Error('Tool call not found in message');
319
+ }
320
+ if (params.input !== undefined) {
321
+ await this.validateToolCallInput({
322
+ agentName: message.agentName,
323
+ toolName: targetToolCall.name,
324
+ input: params.input,
325
+ });
326
+ }
327
+ const updatedMessage = await this.messageRepository.updateToolCall(params.messageId, params.toolCallId, {
328
+ ...(params.input !== undefined ? { input: params.input } : {}),
329
+ ...(params.output !== undefined ? { output: params.output } : {}),
330
+ ...(params.status !== undefined ? { status: params.status } : {}),
331
+ });
332
+ if (!updatedMessage) {
333
+ throw new Error('Tool call not found in message');
334
+ }
335
+ const now = new Date().toISOString();
336
+ await this.chatRepository.update(chat.id, { updatedAt: now });
337
+ this.socketService.emitMessageUpdate(chat.userId, updatedMessage, params.excludeSocketId);
338
+ return updatedMessage;
339
+ }
195
340
  async streamMessageStep(params) {
196
341
  const { chat, assistantMessage, existingMessages, signal, excludeSocketId, agentOptions } = params;
197
342
  if (signal.aborted) {
198
343
  return;
199
344
  }
200
- const result = await helpers_1.AIHelper.streamAssistantResponse(existingMessages, signal, agentOptions);
345
+ const result = await this.aiHelper.streamAssistantResponse(existingMessages, signal, agentOptions);
201
346
  try {
202
347
  for await (const chunk of result.fullStream) {
203
348
  if (chunk.type === 'error') {
204
- await store_1.agentStore.shareAgentProcessEvent(chat.id, { type: store_1.AgentProcessEventType.Error, data: chunk.error });
349
+ await this.agentStore.shareAgentProcessEvent(chat.id, { type: store_1.AgentProcessEventType.Error, data: chunk.error });
205
350
  assistantMessage.content = chunk.error.message || 'Sorry, I cannot process you request due to the error';
206
351
  await this.messageRepository.update(assistantMessage.id, assistantMessage);
207
352
  await this.chatRepository.update(chat.id, { status: ai_agent_types_1.AgentStatus.Error });
208
353
  continue;
209
354
  }
210
355
  if (chunk.type === 'abort') {
211
- await store_1.agentStore.shareAgentProcessEvent(chat.id, { type: store_1.AgentProcessEventType.Aborted, data: undefined });
356
+ await this.agentStore.shareAgentProcessEvent(chat.id, { type: store_1.AgentProcessEventType.Aborted, data: undefined });
212
357
  await this.chatRepository.update(chat.id, { status: ai_agent_types_1.AgentStatus.Aborted });
213
358
  await this.messageRepository.update(assistantMessage.id, assistantMessage);
214
- services_1.socketService.emitMessageUpdate(chat.userId, assistantMessage, excludeSocketId);
359
+ this.socketService.emitMessageUpdate(chat.userId, assistantMessage, excludeSocketId);
215
360
  continue;
216
361
  }
217
362
  if (chunk.type === 'finish') {
@@ -229,37 +374,39 @@ class ChatProcessor {
229
374
  }
230
375
  await this.messageRepository.update(assistantMessage.id, { ...assistantMessage });
231
376
  if (chunk.finishReason === 'stop') {
232
- if (assistantMessage.toolCalls?.some(toolCall => toolCall.requiresConfirmation && toolCall.approvalId && !toolCall.output)) {
233
- await this.chatRepository.update(chat.id, { status: ai_agent_types_1.AgentStatus.WaitingForUserAction });
234
- }
235
- else if (!assistantMessage.content && assistantMessage.toolCalls?.length && assistantMessage.toolCalls[assistantMessage.toolCalls?.length - 1].output) {
236
- // handle tool-calls stop, openrouter provider does not return valid type
237
- await store_1.agentStore.shareAgentProcessEvent(chat.id, { type: store_1.AgentProcessEventType.Update, data: assistantMessage });
238
- await this.streamMessageStep(params);
239
- continue;
240
- }
241
- else {
242
- await this.chatRepository.update(chat.id, { status: ai_agent_types_1.AgentStatus.Finished });
377
+ await this.chatRepository.update(chat.id, { status: ai_agent_types_1.AgentStatus.Finished });
378
+ if (chat.title && this.isTemporaryTitle(chat.title)) {
379
+ const title = await this.aiHelper.generateTitleForMessage(chat.contextKey, existingMessages.filter(m => m.role === ai_agent_types_1.MessageRole.User), (stepResult) => {
380
+ return this.storeStepActivity({
381
+ chat,
382
+ stepResult,
383
+ name: ai_agent_types_1.ActivityOperationName.TITLE_GENERATION,
384
+ sourceId: chat.id,
385
+ sourceType: 'Chat',
386
+ tenants: params.tenants || {},
387
+ });
388
+ });
389
+ await this.chatRepository.update(chat.id, { title });
390
+ this.socketService.emitChatUpdate(chat.userId, { ...chat, title });
243
391
  }
244
- await store_1.agentStore.shareAgentProcessEvent(chat.id, { type: store_1.AgentProcessEventType.Finished, data: assistantMessage });
245
- continue;
246
392
  }
247
393
  if (chunk.finishReason === 'tool-calls') {
248
394
  if (assistantMessage.toolCalls?.some(toolCall => toolCall.requiresConfirmation && toolCall.approvalId && !toolCall.output)) {
249
395
  await this.chatRepository.update(chat.id, { status: ai_agent_types_1.AgentStatus.WaitingForUserAction });
250
- await store_1.agentStore.shareAgentProcessEvent(chat.id, { type: store_1.AgentProcessEventType.Finished, data: assistantMessage });
251
- }
252
- else {
253
- await store_1.agentStore.shareAgentProcessEvent(chat.id, {
254
- type: store_1.AgentProcessEventType.Update,
255
- data: assistantMessage
256
- });
257
- await this.streamMessageStep(params);
396
+ await this.agentStore.shareAgentProcessEvent(chat.id, { type: store_1.AgentProcessEventType.Finished, data: assistantMessage });
397
+ continue;
258
398
  }
259
- continue;
260
399
  }
261
400
  //todo: Handle other finish reasons // length, content, error, other, undefined
262
- await store_1.agentStore.shareAgentProcessEvent(chat.id, { type: store_1.AgentProcessEventType.Finished, data: assistantMessage });
401
+ await this.agentStore.shareAgentProcessEvent(chat.id, { type: store_1.AgentProcessEventType.Finished, data: assistantMessage });
402
+ if (assistantMessage.activity) {
403
+ const groupedMeta = await this.activityRepository.getGroupedMetadataByParentId(assistantMessage.activity);
404
+ await this.activityRepository.updateMetadata(assistantMessage.activity, {
405
+ usage: groupedMeta,
406
+ finishReason: chunk.finishReason,
407
+ responseTimestamp: new Date().toISOString(),
408
+ });
409
+ }
263
410
  continue;
264
411
  }
265
412
  if (chunk.type === 'text-delta') {
@@ -268,8 +415,8 @@ class ChatProcessor {
268
415
  ...assistantMessage,
269
416
  content: assistantMessage.content
270
417
  };
271
- services_1.socketService.emitMessageUpdate(chat.userId, updatedMessage, excludeSocketId);
272
- await store_1.agentStore.shareAgentProcessEvent(chat.id, { type: store_1.AgentProcessEventType.Update, data: updatedMessage });
418
+ this.socketService.emitMessageUpdate(chat.userId, updatedMessage, excludeSocketId);
419
+ await this.agentStore.shareAgentProcessEvent(chat.id, { type: store_1.AgentProcessEventType.Update, data: updatedMessage });
273
420
  await this.messageRepository.update(assistantMessage.id, { content: assistantMessage.content });
274
421
  continue;
275
422
  }
@@ -284,7 +431,7 @@ class ChatProcessor {
284
431
  });
285
432
  continue;
286
433
  }
287
- if (chunk.type === 'tool-call') { //Todo possible place to handle user-approval
434
+ if (chunk.type === 'tool-call') {
288
435
  const toolCall = assistantMessage.toolCalls?.find(toolCall => toolCall.id === chunk.toolCallId);
289
436
  if (toolCall) {
290
437
  toolCall.status = ai_agent_types_1.AgentToolCallStatus.Running;
@@ -296,7 +443,7 @@ class ChatProcessor {
296
443
  const toolCall = assistantMessage.toolCalls?.find(toolCall => toolCall.id === chunk.toolCallId);
297
444
  if (toolCall) {
298
445
  toolCall.status = ai_agent_types_1.AgentToolCallStatus.Failed;
299
- toolCall.error = JSON.stringify(chunk.error);
446
+ toolCall.error = chunk.error.message || JSON.stringify(chunk.error);
300
447
  }
301
448
  continue;
302
449
  }
@@ -305,13 +452,16 @@ class ChatProcessor {
305
452
  if (toolCall) {
306
453
  toolCall.requiresConfirmation = true;
307
454
  toolCall.approvalId = chunk.approvalId;
455
+ if (toolCall.name === ai_agent_types_1.AgentToolType.REQUEST_CLARIFICATION) {
456
+ toolCall.requiresUserAction = true;
457
+ }
308
458
  }
309
459
  continue;
310
460
  }
311
461
  if (chunk.type === 'tool-result') {
312
462
  const toolCall = assistantMessage.toolCalls?.find(toolCall => toolCall.id === chunk.toolCallId);
313
463
  if (toolCall) {
314
- if (chunk.output.requiresApproval) {
464
+ if (chunk.output?.requiresApproval) {
315
465
  toolCall.requiresConfirmation = true;
316
466
  continue;
317
467
  }
@@ -324,9 +474,9 @@ class ChatProcessor {
324
474
  if (!assistantMessage.reasoning)
325
475
  assistantMessage.reasoning = '';
326
476
  assistantMessage.reasoning += chunk.text;
327
- services_1.socketService.emitMessageUpdate(chat.userId, assistantMessage, excludeSocketId);
477
+ this.socketService.emitMessageUpdate(chat.userId, assistantMessage, excludeSocketId);
328
478
  await this.messageRepository.update(assistantMessage.id, { reasoning: assistantMessage.reasoning });
329
- await store_1.agentStore.shareAgentProcessEvent(chat.id, { type: store_1.AgentProcessEventType.Update, data: assistantMessage });
479
+ await this.agentStore.shareAgentProcessEvent(chat.id, { type: store_1.AgentProcessEventType.Update, data: assistantMessage });
330
480
  continue;
331
481
  }
332
482
  }
@@ -335,7 +485,7 @@ class ChatProcessor {
335
485
  if (streamError instanceof Error && streamError.name === 'AbortError') {
336
486
  return;
337
487
  }
338
- await store_1.agentStore.shareAgentProcessEvent(chat.id, { type: store_1.AgentProcessEventType.Error, data: streamError });
488
+ await this.agentStore.shareAgentProcessEvent(chat.id, { type: store_1.AgentProcessEventType.Error, data: streamError });
339
489
  throw streamError;
340
490
  }
341
491
  }
@@ -347,7 +497,7 @@ class ChatProcessor {
347
497
  if (!assistantMessage || assistantMessage.chat !== chat.id) {
348
498
  throw new Error(`Assistant message with id ${payload.messageId} not found`);
349
499
  }
350
- const agentOptions = await helpers_1.AIHelper.getAgentOptions({
500
+ const agentOptions = await this.aiHelper.getAgentOptions({
351
501
  agentName: assistantMessage.agentName,
352
502
  context: payload.context
353
503
  });
@@ -360,14 +510,20 @@ class ChatProcessor {
360
510
  };
361
511
  }
362
512
  toolCall.approved = payload.approved;
363
- toolCall.reason = payload.reason;
513
+ toolCall.userResponse = payload.userResponse;
364
514
  if (!toolCall.approved) {
365
515
  toolCall.output = {
366
516
  type: 'execution-denied',
367
- reason: toolCall.reason
517
+ reason: toolCall.userResponse
368
518
  };
369
519
  toolCall.status = ai_agent_types_1.AgentToolCallStatus.Failed;
370
520
  }
521
+ else if (toolCall.requiresUserAction) {
522
+ toolCall.output = {
523
+ userResponse: toolCall.userResponse
524
+ };
525
+ toolCall.status = ai_agent_types_1.AgentToolCallStatus.Succeeded;
526
+ }
371
527
  else {
372
528
  const executeFunction = agentOptions.tools?.[toolCall.name]?.execute;
373
529
  if (executeFunction) {
@@ -400,32 +556,105 @@ class ChatProcessor {
400
556
  }
401
557
  async processNewUserMessage(chat, payload, prevMessages, excludeSocketId) {
402
558
  const userMessage = await this.createMessage(chat, ai_agent_types_1.MessageRole.User, { content: payload.content, agentName: undefined }, payload.attachments);
403
- await store_1.agentStore.shareAgentProcessEvent(chat.id, { type: store_1.AgentProcessEventType.Update, data: userMessage });
404
- const agentOptions = await helpers_1.AIHelper.getAgentOptions({
559
+ await this.agentStore.shareAgentProcessEvent(chat.id, { type: store_1.AgentProcessEventType.Update, data: userMessage });
560
+ let assistantMessage = await this.createMessage(chat, ai_agent_types_1.MessageRole.Assistant, { content: '', agentName: undefined }, undefined, excludeSocketId);
561
+ const parentActivity = await this.activityRepository.create({
562
+ ownerId: chat.userId,
563
+ groupId: chat.id,
564
+ name: ai_agent_types_1.ActivityOperationName.MESSAGE_PROCESSING,
565
+ tenants: payload.tenants ?? {},
566
+ sourceId: userMessage.id,
567
+ sourceType: 'AgentMessage',
568
+ metadata: {
569
+ contextKey: chat.contextKey,
570
+ modelId: this.aiHelper.getLanguageModelId(chat.model),
571
+ },
572
+ });
573
+ const agentOptions = await this.aiHelper.getAgentOptions({
405
574
  contextKey: chat.contextKey,
406
- messages: await helpers_1.AIHelper.convertMessages([...prevMessages, userMessage], true),
575
+ messages: [...prevMessages, userMessage],
407
576
  context: payload.context,
408
577
  agentName: undefined,
409
578
  modelId: chat.model,
579
+ }, {
580
+ onStepFinish: async (stepResult) => {
581
+ await this.storeStepActivity({
582
+ chat,
583
+ parentId: parentActivity.id,
584
+ stepResult,
585
+ name: ai_agent_types_1.ActivityOperationName.AGENT_SELECTION,
586
+ sourceId: userMessage.id,
587
+ sourceType: 'AgentMessage',
588
+ tenants: payload.tenants || {},
589
+ });
590
+ }
591
+ });
592
+ const updatedAssistantMessage = await this.messageRepository.update(assistantMessage.id, {
593
+ agentName: agentOptions.name,
594
+ activity: parentActivity.id
410
595
  });
411
- const assistantMessage = await this.createMessage(chat, ai_agent_types_1.MessageRole.Assistant, { content: ' ', agentName: agentOptions.name }, undefined, excludeSocketId);
412
- assistantMessage.content = '';
596
+ await this.activityRepository.update(parentActivity.id, {
597
+ metadata: {
598
+ ...parentActivity.metadata,
599
+ agentOptions: {
600
+ name: agentOptions.name,
601
+ modelId: this.aiHelper.getLanguageModelId(agentOptions.model),
602
+ temperature: agentOptions.temperature,
603
+ maxOutputTokens: agentOptions.maxOutputTokens,
604
+ topP: agentOptions.topP,
605
+ topK: agentOptions.topK,
606
+ presencePenalty: agentOptions.presencePenalty,
607
+ frequencyPenalty: agentOptions.frequencyPenalty,
608
+ stopSequences: agentOptions.stopSequences,
609
+ seed: agentOptions.seed,
610
+ },
611
+ },
612
+ });
613
+ if (!updatedAssistantMessage) {
614
+ throw new Error(`Assistant message with id ${assistantMessage.id} not found after update`);
615
+ }
616
+ assistantMessage = updatedAssistantMessage;
413
617
  return {
414
618
  userMessage,
415
619
  assistantMessage,
416
620
  agentOptions,
417
621
  };
418
622
  }
623
+ async storeStepActivity(params) {
624
+ try {
625
+ const stepResult = params.stepResult;
626
+ const mergedUsage = this.mergeUsageWithProviderMetadata(stepResult.usage, stepResult.providerMetadata);
627
+ const activity = await this.activityRepository.create({
628
+ ownerId: params.chat.userId,
629
+ groupId: params.chat.id,
630
+ name: params.name,
631
+ tenants: params.tenants || {},
632
+ sourceId: params.sourceId,
633
+ sourceType: params.sourceType,
634
+ metadata: {
635
+ finishReason: stepResult.finishReason,
636
+ usage: mergedUsage,
637
+ responseTimestamp: stepResult.response.timestamp,
638
+ modelId: stepResult.response.modelId,
639
+ messages: this.debug ? stepResult.request?.body?.messages : undefined,
640
+ },
641
+ parentId: params.parentId,
642
+ });
643
+ }
644
+ catch (error) {
645
+ logger_1.logger.error({ error, chatId: params.chat.id, parentId: params.parentId }, 'Failed to store step activity');
646
+ }
647
+ }
419
648
  async streamMessage(chat, payload, excludeSocketId, onAgentStart) {
420
649
  try {
421
- const abortController = store_1.agentStore.registerAgentProcess(chat.id);
650
+ const abortController = this.agentStore.registerAgentProcess(chat.id);
422
651
  onAgentStart?.();
423
652
  let assistantMessage;
424
653
  let agentOptions;
425
654
  const existingMessages = await this.messageRepository.findByChatId(chat.id);
426
655
  // Limit context to prevent exceeding token limits
427
656
  const limitedMessages = helpers_2.ContextLimiter.limitContext(existingMessages, {
428
- maxMessages: config_1.config.ai.maxContextMessages,
657
+ maxMessages: this.config.ai.maxContextMessages,
429
658
  keepFirstUserMessage: true,
430
659
  keepSystemMessages: true,
431
660
  });
@@ -447,6 +676,19 @@ class ChatProcessor {
447
676
  agentOptions = result.agentOptions;
448
677
  limitedMessages.push(result.userMessage);
449
678
  }
679
+ agentOptions.onStepFinish = (stepResult) => {
680
+ return this.storeStepActivity({
681
+ chat,
682
+ parentId: assistantMessage.activity,
683
+ stepResult,
684
+ name: ai_agent_types_1.ActivityOperationName.STEP_FINISHED,
685
+ sourceId: assistantMessage.id,
686
+ sourceType: 'AgentMessage',
687
+ tenants: payload.tenants || {},
688
+ });
689
+ };
690
+ const userPreferences = await this.agentConfigRepository.findByUserIdAndAgentName(chat.userId, agentOptions.name);
691
+ agentOptions.activeTools = this.getAvailableTools(agentOptions, userPreferences);
450
692
  await this.streamMessageStep({
451
693
  chat,
452
694
  existingMessages: limitedMessages,
@@ -454,12 +696,28 @@ class ChatProcessor {
454
696
  agentOptions,
455
697
  excludeSocketId: excludeSocketId,
456
698
  signal: abortController.signal,
699
+ tenants: payload.tenants || {},
457
700
  });
458
701
  }
459
702
  catch (error) {
460
703
  throw error;
461
704
  }
462
705
  }
706
+ getAvailableTools(agentOptions, userPreferences) {
707
+ const toolNames = Object.keys(agentOptions.tools || {});
708
+ const availableToolsMap = Object.fromEntries(toolNames.map(key => [key, true]));
709
+ const agentsConfiguration = store_2.ConfigStore.getInstance().getAgentConfigByName(agentOptions.name);
710
+ agentsConfiguration.tools.forEach((tool) => {
711
+ const toolTitle = tool.data?.title || tool.type;
712
+ if (tool.disabledByDefault) {
713
+ availableToolsMap[toolTitle] = false;
714
+ }
715
+ if (tool.userConfigurable && userPreferences?.tools?.[toolTitle] !== undefined) {
716
+ availableToolsMap[toolTitle] = userPreferences.tools[toolTitle];
717
+ }
718
+ });
719
+ return Object.keys(availableToolsMap).filter(key => availableToolsMap[key]);
720
+ }
463
721
  listArtifacts(chatId) {
464
722
  return this.artifactStore.listArtifacts(chatId);
465
723
  }
@@ -490,7 +748,7 @@ class ChatProcessor {
490
748
  return null;
491
749
  }
492
750
  }
493
- getMessageStream(chatId) {
751
+ getMessageStream(chatId, signal) {
494
752
  const stream = new stream_1.PassThrough();
495
753
  let ended = false;
496
754
  const endStream = (error) => {
@@ -511,13 +769,15 @@ class ChatProcessor {
511
769
  }
512
770
  };
513
771
  const pushChunk = (chunk) => {
514
- if (ended || stream.destroyed || stream.writableEnded)
772
+ if (ended || stream.destroyed || stream.writableEnded || signal?.aborted)
515
773
  return;
516
774
  stream.write(`data: ${JSON.stringify(chunk)}\n\n`);
517
775
  };
518
776
  const listener = (event) => {
519
- if (ended)
777
+ if (signal?.aborted) {
778
+ endStream();
520
779
  return;
780
+ }
521
781
  try {
522
782
  const chunk = this.eventToChunk(event);
523
783
  if (chunk) {
@@ -527,7 +787,6 @@ class ChatProcessor {
527
787
  event.type === store_1.AgentProcessEventType.Error ||
528
788
  event.type === store_1.AgentProcessEventType.Aborted) {
529
789
  endStream();
530
- store_1.agentStore.removeListener(chatId, listener);
531
790
  }
532
791
  }
533
792
  catch (err) {
@@ -536,21 +795,18 @@ class ChatProcessor {
536
795
  error: err instanceof Error ? err.message : 'Unknown error occurred',
537
796
  });
538
797
  endStream(err);
539
- store_1.agentStore.removeListener(chatId, listener);
540
798
  }
541
799
  };
542
- // Cleanup on consumer side closing
543
800
  const closeHandler = () => {
544
- store_1.agentStore.removeListener(chatId, listener);
801
+ this.agentStore.removeListener(chatId, listener);
545
802
  };
546
803
  const errorHandler = (err) => {
547
- logger_1.logger.error({ err }, 'Readable stream error');
548
- store_1.agentStore.removeListener(chatId, listener);
804
+ signal?.removeEventListener('abort', endStream);
549
805
  endStream(err);
550
806
  };
551
807
  stream.on('close', closeHandler);
552
808
  stream.on('error', errorHandler);
553
- const listenerAttached = store_1.agentStore.addListener(chatId, listener);
809
+ const listenerAttached = this.agentStore.addListener(chatId, listener);
554
810
  if (!listenerAttached) {
555
811
  // Remove stream listeners if listener attachment failed to prevent memory leak
556
812
  stream.removeListener('close', closeHandler);
@@ -559,51 +815,28 @@ class ChatProcessor {
559
815
  }
560
816
  return stream;
561
817
  }
562
- async createMessageStream(payload, excludeSocketId) {
818
+ async createMessageStream(payload, excludeSocketId, signal) {
563
819
  const stream = new stream_1.PassThrough();
564
- (async () => {
565
- try {
566
- const chat = await this.upsertAndGetChat(payload, excludeSocketId);
567
- // Send chat metadata first
568
- if (!('chatId' in payload) && !('messageId' in payload) && chat) {
569
- stream.write(`data: ${JSON.stringify({
570
- type: ai_agent_types_1.StreamChunkType.Chat,
571
- chatId: chat.id,
572
- chat,
573
- })}\n\n`);
574
- }
575
- await this.streamMessage(chat, payload, excludeSocketId, async () => {
576
- if (stream.destroyed || stream.writableEnded) {
577
- return;
578
- }
579
- const messageStream = this.getMessageStream(chat.id);
580
- // If client disconnects, destroy inner stream
581
- stream.on('close', () => {
582
- if (!messageStream.destroyed) {
583
- messageStream.destroy();
584
- }
585
- });
586
- await pipelineAsync(messageStream, stream);
587
- });
588
- }
589
- catch (error) {
590
- logger_1.logger.error({ error }, 'createMessageStream failed');
591
- if (!stream.destroyed && !stream.writableEnded) {
592
- stream.write(`data: ${JSON.stringify({
593
- type: ai_agent_types_1.StreamChunkType.Error,
594
- error: error instanceof Error ? error.message : 'Unknown error occurred',
595
- })}\n\n`);
596
- stream.write('data: [DONE]\n\n');
597
- stream.end();
598
- }
599
- }
600
- })().catch((err) => {
601
- logger_1.logger.error({ err }, 'Unhandled stream task error');
602
- if (!stream.destroyed)
603
- stream.destroy(err);
820
+ this.runMessageStream(stream, payload, excludeSocketId, signal)
821
+ .catch(err => {
822
+ logger_1.logger.error({ err }, 'Stream task failed');
604
823
  });
605
824
  return stream;
606
825
  }
826
+ async runMessageStream(stream, payload, excludeSocketId, signal) {
827
+ const chat = await this.upsertAndGetChat(payload, excludeSocketId);
828
+ if (!('chatId' in payload) && !('messageId' in payload) && chat) {
829
+ stream.write(`data: ${JSON.stringify({
830
+ type: ai_agent_types_1.StreamChunkType.Chat,
831
+ chatId: chat.id,
832
+ chat,
833
+ })}\n\n`);
834
+ }
835
+ await this.streamMessage(chat, payload, excludeSocketId, () => {
836
+ const messageStream = this.getMessageStream(chat.id, signal);
837
+ messageStream.pipe(stream);
838
+ });
839
+ }
607
840
  }
608
841
  exports.ChatProcessor = ChatProcessor;
609
842
  //# sourceMappingURL=ChatProcessor.js.map