@multiplayer-app/ai-agent-node 0.1.0-beta.7 → 0.1.0-beta.70

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 (210) hide show
  1. package/README.md +2 -2
  2. package/dist/cjs/config.cjs +87 -45
  3. package/dist/cjs/config.cjs.map +1 -1
  4. package/dist/cjs/config.d.ts +60 -29
  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 -26
  24. package/dist/cjs/index.cjs.map +1 -1
  25. package/dist/cjs/index.d.ts +43 -10
  26. package/dist/cjs/index.d.ts.map +1 -1
  27. package/dist/cjs/libs/s3/index.cjs +3 -39
  28. package/dist/cjs/libs/s3/index.cjs.map +1 -1
  29. package/dist/cjs/libs/s3/index.d.ts +1 -2
  30. package/dist/cjs/libs/s3/index.d.ts.map +1 -1
  31. package/dist/cjs/libs/s3/s3.lib.cjs +173 -186
  32. package/dist/cjs/libs/s3/s3.lib.cjs.map +1 -1
  33. package/dist/cjs/libs/s3/s3.lib.d.ts +29 -22
  34. package/dist/cjs/libs/s3/s3.lib.d.ts.map +1 -1
  35. package/dist/cjs/processors/ActivityProcessor.cjs +39 -0
  36. package/dist/cjs/processors/ActivityProcessor.cjs.map +1 -0
  37. package/dist/cjs/processors/ActivityProcessor.d.ts +32 -0
  38. package/dist/cjs/processors/ActivityProcessor.d.ts.map +1 -0
  39. package/dist/cjs/processors/ActivityProcessor.test.cjs +84 -0
  40. package/dist/cjs/processors/ActivityProcessor.test.cjs.map +1 -0
  41. package/dist/cjs/processors/ActivityProcessor.test.d.ts +2 -0
  42. package/dist/cjs/processors/ActivityProcessor.test.d.ts.map +1 -0
  43. package/dist/cjs/processors/AgentProcessor.cjs +46 -0
  44. package/dist/cjs/processors/AgentProcessor.cjs.map +1 -0
  45. package/dist/cjs/processors/AgentProcessor.d.ts +25 -0
  46. package/dist/cjs/processors/AgentProcessor.d.ts.map +1 -0
  47. package/dist/cjs/processors/AgentProcessor.test.cjs +103 -0
  48. package/dist/cjs/processors/AgentProcessor.test.cjs.map +1 -0
  49. package/dist/cjs/processors/AgentProcessor.test.d.ts +2 -0
  50. package/dist/cjs/processors/AgentProcessor.test.d.ts.map +1 -0
  51. package/dist/cjs/processors/ChatProcessor.cjs +348 -126
  52. package/dist/cjs/processors/ChatProcessor.cjs.map +1 -1
  53. package/dist/cjs/processors/ChatProcessor.d.ts +70 -11
  54. package/dist/cjs/processors/ChatProcessor.d.ts.map +1 -1
  55. package/dist/cjs/processors/ChatProcessor.test.cjs +762 -0
  56. package/dist/cjs/processors/ChatProcessor.test.cjs.map +1 -0
  57. package/dist/cjs/processors/ChatProcessor.test.d.ts +2 -0
  58. package/dist/cjs/processors/ChatProcessor.test.d.ts.map +1 -0
  59. package/dist/cjs/processors/index.cjs +2 -0
  60. package/dist/cjs/processors/index.cjs.map +1 -1
  61. package/dist/cjs/processors/index.d.ts +2 -0
  62. package/dist/cjs/processors/index.d.ts.map +1 -1
  63. package/dist/cjs/services/AIService.cjs +87 -21
  64. package/dist/cjs/services/AIService.cjs.map +1 -1
  65. package/dist/cjs/services/AIService.d.ts +19 -7
  66. package/dist/cjs/services/AIService.d.ts.map +1 -1
  67. package/dist/cjs/services/InternalEventsHandler.cjs +3 -3
  68. package/dist/cjs/services/InternalEventsHandler.cjs.map +1 -1
  69. package/dist/cjs/services/InternalEventsHandler.d.ts +3 -1
  70. package/dist/cjs/services/InternalEventsHandler.d.ts.map +1 -1
  71. package/dist/cjs/services/ModelFetcher.cjs +2 -8
  72. package/dist/cjs/services/ModelFetcher.cjs.map +1 -1
  73. package/dist/cjs/services/ModelFetcher.d.ts +2 -7
  74. package/dist/cjs/services/ModelFetcher.d.ts.map +1 -1
  75. package/dist/cjs/services/RedisService.cjs +20 -16
  76. package/dist/cjs/services/RedisService.cjs.map +1 -1
  77. package/dist/cjs/services/RedisService.d.ts +5 -2
  78. package/dist/cjs/services/RedisService.d.ts.map +1 -1
  79. package/dist/cjs/services/SocketService.cjs +7 -7
  80. package/dist/cjs/services/SocketService.cjs.map +1 -1
  81. package/dist/cjs/services/SocketService.d.ts +9 -6
  82. package/dist/cjs/services/SocketService.d.ts.map +1 -1
  83. package/dist/cjs/store/AgentStore.cjs +3 -4
  84. package/dist/cjs/store/AgentStore.cjs.map +1 -1
  85. package/dist/cjs/store/AgentStore.d.ts +2 -1
  86. package/dist/cjs/store/AgentStore.d.ts.map +1 -1
  87. package/dist/cjs/store/ConfigStore.cjs +7 -3
  88. package/dist/cjs/store/ConfigStore.cjs.map +1 -1
  89. package/dist/cjs/store/ConfigStore.d.ts +1 -0
  90. package/dist/cjs/store/ConfigStore.d.ts.map +1 -1
  91. package/dist/cjs/tools/generateChartTool.d.ts +2 -2
  92. package/dist/cjs/tools/proposeFormValuesTool.d.ts +2 -2
  93. package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
  94. package/dist/esm/config.d.ts +60 -29
  95. package/dist/esm/config.d.ts.map +1 -1
  96. package/dist/esm/config.js +87 -43
  97. package/dist/esm/config.js.map +1 -1
  98. package/dist/esm/helpers/AIHelper.d.ts +22 -16
  99. package/dist/esm/helpers/AIHelper.d.ts.map +1 -1
  100. package/dist/esm/helpers/AIHelper.js +134 -70
  101. package/dist/esm/helpers/AIHelper.js.map +1 -1
  102. package/dist/esm/helpers/AIHelper.test.js +22 -15
  103. package/dist/esm/helpers/AIHelper.test.js.map +1 -1
  104. package/dist/esm/helpers/ConfigHelper.d.ts.map +1 -1
  105. package/dist/esm/helpers/ConfigHelper.js +15 -6
  106. package/dist/esm/helpers/ConfigHelper.js.map +1 -1
  107. package/dist/esm/helpers/FileHelper.d.ts +19 -25
  108. package/dist/esm/helpers/FileHelper.d.ts.map +1 -1
  109. package/dist/esm/helpers/FileHelper.js +131 -146
  110. package/dist/esm/helpers/FileHelper.js.map +1 -1
  111. package/dist/esm/helpers/index.d.ts +0 -1
  112. package/dist/esm/helpers/index.d.ts.map +1 -1
  113. package/dist/esm/helpers/index.js +0 -1
  114. package/dist/esm/helpers/index.js.map +1 -1
  115. package/dist/esm/index.d.ts +43 -10
  116. package/dist/esm/index.d.ts.map +1 -1
  117. package/dist/esm/index.js +92 -10
  118. package/dist/esm/index.js.map +1 -1
  119. package/dist/esm/libs/s3/index.d.ts +1 -2
  120. package/dist/esm/libs/s3/index.d.ts.map +1 -1
  121. package/dist/esm/libs/s3/index.js +1 -2
  122. package/dist/esm/libs/s3/index.js.map +1 -1
  123. package/dist/esm/libs/s3/s3.lib.d.ts +29 -22
  124. package/dist/esm/libs/s3/s3.lib.d.ts.map +1 -1
  125. package/dist/esm/libs/s3/s3.lib.js +177 -172
  126. package/dist/esm/libs/s3/s3.lib.js.map +1 -1
  127. package/dist/esm/processors/ActivityProcessor.d.ts +32 -0
  128. package/dist/esm/processors/ActivityProcessor.d.ts.map +1 -0
  129. package/dist/esm/processors/ActivityProcessor.js +36 -0
  130. package/dist/esm/processors/ActivityProcessor.js.map +1 -0
  131. package/dist/esm/processors/ActivityProcessor.test.d.ts +2 -0
  132. package/dist/esm/processors/ActivityProcessor.test.d.ts.map +1 -0
  133. package/dist/esm/processors/ActivityProcessor.test.js +82 -0
  134. package/dist/esm/processors/ActivityProcessor.test.js.map +1 -0
  135. package/dist/esm/processors/AgentProcessor.d.ts +25 -0
  136. package/dist/esm/processors/AgentProcessor.d.ts.map +1 -0
  137. package/dist/esm/processors/AgentProcessor.js +43 -0
  138. package/dist/esm/processors/AgentProcessor.js.map +1 -0
  139. package/dist/esm/processors/AgentProcessor.test.d.ts +2 -0
  140. package/dist/esm/processors/AgentProcessor.test.d.ts.map +1 -0
  141. package/dist/esm/processors/AgentProcessor.test.js +101 -0
  142. package/dist/esm/processors/AgentProcessor.test.js.map +1 -0
  143. package/dist/esm/processors/ChatProcessor.d.ts +70 -11
  144. package/dist/esm/processors/ChatProcessor.d.ts.map +1 -1
  145. package/dist/esm/processors/ChatProcessor.js +359 -130
  146. package/dist/esm/processors/ChatProcessor.js.map +1 -1
  147. package/dist/esm/processors/ChatProcessor.test.d.ts +2 -0
  148. package/dist/esm/processors/ChatProcessor.test.d.ts.map +1 -0
  149. package/dist/esm/processors/ChatProcessor.test.js +760 -0
  150. package/dist/esm/processors/ChatProcessor.test.js.map +1 -0
  151. package/dist/esm/processors/index.d.ts +2 -0
  152. package/dist/esm/processors/index.d.ts.map +1 -1
  153. package/dist/esm/processors/index.js +2 -0
  154. package/dist/esm/processors/index.js.map +1 -1
  155. package/dist/esm/services/AIService.d.ts +19 -7
  156. package/dist/esm/services/AIService.d.ts.map +1 -1
  157. package/dist/esm/services/AIService.js +91 -24
  158. package/dist/esm/services/AIService.js.map +1 -1
  159. package/dist/esm/services/InternalEventsHandler.d.ts +3 -1
  160. package/dist/esm/services/InternalEventsHandler.d.ts.map +1 -1
  161. package/dist/esm/services/InternalEventsHandler.js +4 -3
  162. package/dist/esm/services/InternalEventsHandler.js.map +1 -1
  163. package/dist/esm/services/ModelFetcher.d.ts +2 -7
  164. package/dist/esm/services/ModelFetcher.d.ts.map +1 -1
  165. package/dist/esm/services/ModelFetcher.js +2 -8
  166. package/dist/esm/services/ModelFetcher.js.map +1 -1
  167. package/dist/esm/services/RedisService.d.ts +5 -2
  168. package/dist/esm/services/RedisService.d.ts.map +1 -1
  169. package/dist/esm/services/RedisService.js +21 -14
  170. package/dist/esm/services/RedisService.js.map +1 -1
  171. package/dist/esm/services/SocketService.d.ts +9 -6
  172. package/dist/esm/services/SocketService.d.ts.map +1 -1
  173. package/dist/esm/services/SocketService.js +9 -5
  174. package/dist/esm/services/SocketService.js.map +1 -1
  175. package/dist/esm/store/AgentStore.d.ts +2 -1
  176. package/dist/esm/store/AgentStore.d.ts.map +1 -1
  177. package/dist/esm/store/AgentStore.js +4 -2
  178. package/dist/esm/store/AgentStore.js.map +1 -1
  179. package/dist/esm/store/ConfigStore.d.ts +1 -0
  180. package/dist/esm/store/ConfigStore.d.ts.map +1 -1
  181. package/dist/esm/store/ConfigStore.js +7 -3
  182. package/dist/esm/store/ConfigStore.js.map +1 -1
  183. package/dist/esm/tools/generateChartTool.d.ts +2 -2
  184. package/dist/esm/tools/proposeFormValuesTool.d.ts +2 -2
  185. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
  186. package/package.json +12 -11
  187. package/dist/cjs/helpers/SetupHelper.cjs +0 -34
  188. package/dist/cjs/helpers/SetupHelper.cjs.map +0 -1
  189. package/dist/cjs/helpers/SetupHelper.d.ts +0 -4
  190. package/dist/cjs/helpers/SetupHelper.d.ts.map +0 -1
  191. package/dist/cjs/libs/logger/config.cjs +0 -9
  192. package/dist/cjs/libs/logger/config.cjs.map +0 -1
  193. package/dist/cjs/libs/logger/config.d.ts +0 -5
  194. package/dist/cjs/libs/logger/config.d.ts.map +0 -1
  195. package/dist/cjs/libs/s3/config.cjs +0 -8
  196. package/dist/cjs/libs/s3/config.cjs.map +0 -1
  197. package/dist/cjs/libs/s3/config.d.ts +0 -4
  198. package/dist/cjs/libs/s3/config.d.ts.map +0 -1
  199. package/dist/esm/helpers/SetupHelper.d.ts +0 -4
  200. package/dist/esm/helpers/SetupHelper.d.ts.map +0 -1
  201. package/dist/esm/helpers/SetupHelper.js +0 -29
  202. package/dist/esm/helpers/SetupHelper.js.map +0 -1
  203. package/dist/esm/libs/logger/config.d.ts +0 -5
  204. package/dist/esm/libs/logger/config.d.ts.map +0 -1
  205. package/dist/esm/libs/logger/config.js +0 -6
  206. package/dist/esm/libs/logger/config.js.map +0 -1
  207. package/dist/esm/libs/s3/config.d.ts +0 -4
  208. package/dist/esm/libs/s3/config.d.ts.map +0 -1
  209. package/dist/esm/libs/s3/config.js +0 -5
  210. package/dist/esm/libs/s3/config.js.map +0 -1
@@ -0,0 +1,762 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const vitest_1 = require("vitest");
4
+ const ChatProcessor_1 = require("./ChatProcessor.cjs");
5
+ const ai_agent_types_1 = require("@multiplayer-app/ai-agent-types");
6
+ const ConfigStore_1 = require("../store/ConfigStore.cjs");
7
+ const ModelStore_1 = require("../store/ModelStore.cjs");
8
+ const config_1 = require("../config.cjs");
9
+ const s3_1 = require("../libs/s3/index.cjs");
10
+ const zod_1 = require("zod");
11
+ (0, vitest_1.describe)('ChatProcessor.streamMessage', () => {
12
+ let chatProcessor;
13
+ let mockChatRepository;
14
+ let mockMessageRepository;
15
+ let mockAgentConfigRepository;
16
+ let mockArtifactStore;
17
+ let mockAgentStore;
18
+ let mockSocketService;
19
+ let mockActivityRepository;
20
+ let configStore;
21
+ let capturedOptions;
22
+ const userId = 'test-user-id';
23
+ (0, vitest_1.beforeEach)(() => {
24
+ vitest_1.vi.clearAllMocks();
25
+ capturedOptions = undefined;
26
+ ModelStore_1.ModelStore.getInstance().setModels([
27
+ { id: 'openai/gpt-4o', provider: 'openai', label: 'GPT-4o' }
28
+ ]);
29
+ // Mock repositories
30
+ mockChatRepository = {
31
+ findById: vitest_1.vi.fn(),
32
+ create: vitest_1.vi.fn(),
33
+ update: vitest_1.vi.fn(),
34
+ delete: vitest_1.vi.fn(),
35
+ findWithMessages: vitest_1.vi.fn(),
36
+ };
37
+ mockMessageRepository = {
38
+ findByChatId: vitest_1.vi.fn().mockResolvedValue([]),
39
+ findByChatIdPaginated: vitest_1.vi.fn().mockResolvedValue({ messages: [], hasMore: false }),
40
+ findById: vitest_1.vi.fn(),
41
+ create: vitest_1.vi.fn(),
42
+ deleteByChatId: vitest_1.vi.fn(),
43
+ update: vitest_1.vi.fn().mockImplementation(async (id, updates) => ({
44
+ id,
45
+ chat: 'test-chat-id',
46
+ role: ai_agent_types_1.MessageRole.Assistant,
47
+ content: '',
48
+ createdAt: new Date().toISOString(),
49
+ ...updates
50
+ })),
51
+ };
52
+ mockAgentConfigRepository = {
53
+ findByUserIdAndAgentName: vitest_1.vi.fn().mockResolvedValue(null),
54
+ };
55
+ // Mock artifact store
56
+ mockArtifactStore = {
57
+ listArtifacts: vitest_1.vi.fn().mockReturnValue([]),
58
+ deleteArtifacts: vitest_1.vi.fn(),
59
+ };
60
+ // Mock agent store
61
+ mockAgentStore = {
62
+ registerAgentProcess: vitest_1.vi.fn().mockReturnValue({
63
+ signal: new AbortController().signal,
64
+ }),
65
+ shareAgentProcessEvent: vitest_1.vi.fn(),
66
+ addListener: vitest_1.vi.fn(),
67
+ removeListener: vitest_1.vi.fn(),
68
+ };
69
+ // Mock socket service
70
+ mockSocketService = {
71
+ emitMessageUpdate: vitest_1.vi.fn(),
72
+ emitChatUpdate: vitest_1.vi.fn(),
73
+ };
74
+ // Setup config store with agent config
75
+ configStore = ConfigStore_1.ConfigStore.getInstance();
76
+ configStore.clear();
77
+ const agentConfig = {
78
+ name: 'test-agent',
79
+ description: 'Test agent for property verification',
80
+ defaultModel: 'openai/gpt-4o',
81
+ systemPrompt: 'You are a helpful assistant',
82
+ temperature: 0.8,
83
+ maxOutputTokens: 3000,
84
+ topP: 0.95,
85
+ topK: 50,
86
+ presencePenalty: 0.6,
87
+ frequencyPenalty: 0.4,
88
+ stopSequences: ['\n\n', '---', 'END'],
89
+ seed: 42,
90
+ tools: [],
91
+ toolChoice: 'auto',
92
+ };
93
+ // Use addAgent to bypass ConfigHelper conversion
94
+ configStore.addAgent(['test-context'], agentConfig);
95
+ const config = config_1.ConfigProvider.getInstance().getConfig();
96
+ const s3Lib = new s3_1.S3Lib(config.s3);
97
+ mockActivityRepository = {
98
+ create: vitest_1.vi.fn().mockResolvedValue({
99
+ id: 'activity-1',
100
+ ownerId: 'test-chat-id',
101
+ groupId: 'test-chat-id',
102
+ name: 'Message processing',
103
+ tenants: { userId: 'test-user-id' },
104
+ sourceId: 'user-msg-1',
105
+ sourceType: 'AgentMessage',
106
+ metadata: {}
107
+ }),
108
+ update: vitest_1.vi.fn().mockResolvedValue({
109
+ id: 'activity-1',
110
+ ownerId: 'test-chat-id',
111
+ groupId: 'test-chat-id',
112
+ name: 'Message processing',
113
+ tenants: { userId: 'test-user-id' },
114
+ sourceId: 'user-msg-1',
115
+ sourceType: 'AgentMessage',
116
+ metadata: {}
117
+ }),
118
+ deleteByGroupId: vitest_1.vi.fn().mockResolvedValue(1),
119
+ getGroupedMetadataByParentId: vitest_1.vi.fn().mockResolvedValue({}),
120
+ updateMetadata: vitest_1.vi.fn().mockResolvedValue({
121
+ id: 'activity-1',
122
+ metadata: {}
123
+ }),
124
+ };
125
+ // Create ChatProcessor
126
+ chatProcessor = new ChatProcessor_1.ChatProcessor({
127
+ chatRepository: mockChatRepository,
128
+ messageRepository: mockMessageRepository,
129
+ agentConfigRepository: mockAgentConfigRepository,
130
+ artifactStore: mockArtifactStore,
131
+ s3Lib,
132
+ config,
133
+ socketService: mockSocketService,
134
+ agentStore: mockAgentStore,
135
+ activityRepository: mockActivityRepository
136
+ });
137
+ });
138
+ (0, vitest_1.it)('should delete chat, messages, activities, and artifacts', async () => {
139
+ mockChatRepository.delete.mockResolvedValue(true);
140
+ await chatProcessor.deleteChat('chat-1');
141
+ (0, vitest_1.expect)(mockChatRepository.delete).toHaveBeenCalledWith('chat-1');
142
+ (0, vitest_1.expect)(mockMessageRepository.deleteByChatId).toHaveBeenCalledWith('chat-1');
143
+ (0, vitest_1.expect)(mockActivityRepository.deleteByGroupId).toHaveBeenCalledWith('chat-1');
144
+ (0, vitest_1.expect)(mockArtifactStore.deleteArtifacts).toHaveBeenCalledWith('chat-1');
145
+ });
146
+ (0, vitest_1.it)('should throw when chat does not exist and skip cleanup', async () => {
147
+ mockChatRepository.delete.mockResolvedValue(false);
148
+ await (0, vitest_1.expect)(chatProcessor.deleteChat('missing-chat')).rejects.toThrow('Chat not found');
149
+ (0, vitest_1.expect)(mockMessageRepository.deleteByChatId).not.toHaveBeenCalled();
150
+ (0, vitest_1.expect)(mockActivityRepository.deleteByGroupId).not.toHaveBeenCalled();
151
+ (0, vitest_1.expect)(mockArtifactStore.deleteArtifacts).not.toHaveBeenCalled();
152
+ });
153
+ (0, vitest_1.it)('should pass all agent properties correctly to streamAssistantResponse', async () => {
154
+ const chat = {
155
+ id: 'test-chat-id',
156
+ userId,
157
+ contextKey: 'test-context',
158
+ type: ai_agent_types_1.ChatType.Chat,
159
+ status: ai_agent_types_1.AgentStatus.Processing,
160
+ createdAt: new Date().toISOString(),
161
+ updatedAt: new Date().toISOString(),
162
+ };
163
+ const payload = {
164
+ chatId: chat.id,
165
+ content: 'Hello, test message',
166
+ contextKey: 'test-context',
167
+ };
168
+ // Mock chat repository
169
+ mockChatRepository.findById.mockResolvedValue(chat);
170
+ // Mock message creation
171
+ const userMessage = {
172
+ id: 'user-msg-1',
173
+ chat: chat.id,
174
+ role: ai_agent_types_1.MessageRole.User,
175
+ content: payload.content,
176
+ createdAt: new Date().toISOString(),
177
+ };
178
+ const assistantMessage = {
179
+ id: 'assistant-msg-1',
180
+ chat: chat.id,
181
+ role: ai_agent_types_1.MessageRole.Assistant,
182
+ content: '',
183
+ createdAt: new Date().toISOString(),
184
+ agentName: 'test-agent',
185
+ };
186
+ mockMessageRepository.create
187
+ .mockResolvedValueOnce(userMessage)
188
+ .mockResolvedValueOnce(assistantMessage);
189
+ // Mock stream to prevent actual API calls
190
+ const mockStream = {
191
+ fullStream: (async function* () {
192
+ yield { type: 'finish', finishReason: 'stop', text: 'Test response' };
193
+ })(),
194
+ };
195
+ // Capture options passed to streamAssistantResponse
196
+ const aiHelper = chatProcessor.aiHelper;
197
+ vitest_1.vi.spyOn(aiHelper, 'streamAssistantResponse').mockImplementation(async (messages, signal, options) => {
198
+ capturedOptions = options;
199
+ return mockStream;
200
+ });
201
+ // Call streamMessage
202
+ await chatProcessor.streamMessage(chat, payload);
203
+ // Verify options were captured
204
+ (0, vitest_1.expect)(capturedOptions).toBeDefined();
205
+ // Verify all agent properties are present in the options
206
+ if (capturedOptions) {
207
+ (0, vitest_1.expect)(capturedOptions).toHaveProperty('name', 'test-agent');
208
+ (0, vitest_1.expect)(capturedOptions).toHaveProperty('system', 'You are a helpful assistant');
209
+ (0, vitest_1.expect)(capturedOptions).toHaveProperty('temperature', 0.8);
210
+ (0, vitest_1.expect)(capturedOptions).toHaveProperty('maxOutputTokens', 3000);
211
+ (0, vitest_1.expect)(capturedOptions).toHaveProperty('topP', 0.95);
212
+ (0, vitest_1.expect)(capturedOptions).toHaveProperty('topK', 50);
213
+ (0, vitest_1.expect)(capturedOptions).toHaveProperty('presencePenalty', 0.6);
214
+ (0, vitest_1.expect)(capturedOptions).toHaveProperty('frequencyPenalty', 0.4);
215
+ (0, vitest_1.expect)(capturedOptions).toHaveProperty('stopSequences', ['\n\n', '---', 'END']);
216
+ (0, vitest_1.expect)(capturedOptions).toHaveProperty('seed', 42);
217
+ (0, vitest_1.expect)(capturedOptions).toHaveProperty('toolChoice', 'auto');
218
+ (0, vitest_1.expect)(capturedOptions).toHaveProperty('tools');
219
+ }
220
+ });
221
+ (0, vitest_1.it)('should handle optional agent properties when not provided', async () => {
222
+ configStore.clear();
223
+ const minimalAgentConfig = {
224
+ name: 'minimal-agent',
225
+ description: 'Minimal agent config',
226
+ systemPrompt: 'You are helpful',
227
+ tools: [],
228
+ };
229
+ configStore.addAgent(['test-context'], minimalAgentConfig);
230
+ const chat = {
231
+ id: 'test-chat-id-2',
232
+ userId,
233
+ contextKey: 'test-context',
234
+ type: ai_agent_types_1.ChatType.Chat,
235
+ status: ai_agent_types_1.AgentStatus.Processing,
236
+ createdAt: new Date().toISOString(),
237
+ updatedAt: new Date().toISOString(),
238
+ };
239
+ const payload = {
240
+ chatId: chat.id,
241
+ content: 'Test',
242
+ contextKey: 'test-context',
243
+ };
244
+ mockChatRepository.findById.mockResolvedValue(chat);
245
+ const userMessage = {
246
+ id: 'user-msg-2',
247
+ chat: chat.id,
248
+ role: ai_agent_types_1.MessageRole.User,
249
+ content: payload.content,
250
+ createdAt: new Date().toISOString(),
251
+ };
252
+ const assistantMessage = {
253
+ id: 'assistant-msg-2',
254
+ chat: chat.id,
255
+ role: ai_agent_types_1.MessageRole.Assistant,
256
+ content: '',
257
+ createdAt: new Date().toISOString(),
258
+ agentName: 'minimal-agent',
259
+ };
260
+ mockMessageRepository.create
261
+ .mockResolvedValueOnce(userMessage)
262
+ .mockResolvedValueOnce(assistantMessage);
263
+ const mockStream = {
264
+ fullStream: (async function* () {
265
+ yield { type: 'finish', finishReason: 'stop', text: 'Response' };
266
+ })(),
267
+ };
268
+ const aiHelper = chatProcessor.aiHelper;
269
+ vitest_1.vi.spyOn(aiHelper, 'streamAssistantResponse').mockImplementation(async (messages, signal, options) => {
270
+ capturedOptions = options;
271
+ return mockStream;
272
+ });
273
+ await chatProcessor.streamMessage(chat, payload);
274
+ // Verify required properties are present
275
+ (0, vitest_1.expect)(capturedOptions).toBeDefined();
276
+ if (capturedOptions) {
277
+ (0, vitest_1.expect)(capturedOptions).toHaveProperty('name', 'minimal-agent');
278
+ (0, vitest_1.expect)(capturedOptions).toHaveProperty('system', 'You are helpful');
279
+ (0, vitest_1.expect)(capturedOptions).toHaveProperty('tools');
280
+ }
281
+ });
282
+ (0, vitest_1.it)('should pass stopWhen condition when provided', async () => {
283
+ configStore.clear();
284
+ const stopWhenFn = vitest_1.vi.fn(() => false);
285
+ const agentConfigWithStopWhen = {
286
+ name: 'agent-with-stopwhen',
287
+ description: 'Agent with stopWhen',
288
+ systemPrompt: 'You are helpful',
289
+ tools: [],
290
+ stopWhen: stopWhenFn,
291
+ };
292
+ configStore.addAgent(['test-context'], agentConfigWithStopWhen);
293
+ const chat = {
294
+ id: 'test-chat-id-3',
295
+ userId,
296
+ contextKey: 'test-context',
297
+ type: ai_agent_types_1.ChatType.Chat,
298
+ status: ai_agent_types_1.AgentStatus.Processing,
299
+ createdAt: new Date().toISOString(),
300
+ updatedAt: new Date().toISOString(),
301
+ };
302
+ const payload = {
303
+ chatId: chat.id,
304
+ content: 'Test',
305
+ contextKey: 'test-context',
306
+ };
307
+ mockChatRepository.findById.mockResolvedValue(chat);
308
+ const userMessage = {
309
+ id: 'user-msg-3',
310
+ chat: chat.id,
311
+ role: ai_agent_types_1.MessageRole.User,
312
+ content: payload.content,
313
+ createdAt: new Date().toISOString(),
314
+ };
315
+ const assistantMessage = {
316
+ id: 'assistant-msg-3',
317
+ chat: chat.id,
318
+ role: ai_agent_types_1.MessageRole.Assistant,
319
+ content: '',
320
+ createdAt: new Date().toISOString(),
321
+ agentName: 'agent-with-stopwhen',
322
+ };
323
+ mockMessageRepository.create
324
+ .mockResolvedValueOnce(userMessage)
325
+ .mockResolvedValueOnce(assistantMessage);
326
+ const mockStream = {
327
+ fullStream: (async function* () {
328
+ yield { type: 'finish', finishReason: 'stop', text: 'Response' };
329
+ })(),
330
+ };
331
+ const aiHelper = chatProcessor.aiHelper;
332
+ vitest_1.vi.spyOn(aiHelper, 'streamAssistantResponse').mockImplementation(async (messages, signal, options) => {
333
+ capturedOptions = options;
334
+ return mockStream;
335
+ });
336
+ await chatProcessor.streamMessage(chat, payload);
337
+ // Verify stopWhen is passed
338
+ (0, vitest_1.expect)(capturedOptions).toBeDefined();
339
+ if (capturedOptions) {
340
+ (0, vitest_1.expect)(capturedOptions).toHaveProperty('stopWhen', stopWhenFn);
341
+ }
342
+ });
343
+ (0, vitest_1.it)('should merge only cost-related provider usage into stored activity metadata', async () => {
344
+ const chat = {
345
+ id: 'test-chat-id-usage',
346
+ userId,
347
+ contextKey: 'test-context',
348
+ type: ai_agent_types_1.ChatType.Chat,
349
+ status: ai_agent_types_1.AgentStatus.Processing,
350
+ createdAt: new Date().toISOString(),
351
+ updatedAt: new Date().toISOString(),
352
+ };
353
+ await chatProcessor.storeStepActivity({
354
+ chat,
355
+ stepResult: {
356
+ finishReason: 'stop',
357
+ usage: {
358
+ inputTokens: 205,
359
+ outputTokens: 3,
360
+ totalTokens: 209,
361
+ inputTokenDetails: { cacheReadTokens: 0 },
362
+ },
363
+ response: {
364
+ timestamp: new Date().toISOString(),
365
+ modelId: 'openai/gpt-4o',
366
+ },
367
+ providerMetadata: {
368
+ openrouter: {
369
+ provider: 'OpenAI',
370
+ usage: {
371
+ promptTokens: 205,
372
+ promptTokensDetails: { cachedTokens: 0 },
373
+ completionTokens: 3,
374
+ totalTokens: 208,
375
+ cost: 0.0005425,
376
+ costDetails: {
377
+ upstreamInferenceCost: 0.0005425,
378
+ },
379
+ },
380
+ },
381
+ },
382
+ },
383
+ name: 'titleGeneration',
384
+ sourceId: chat.id,
385
+ sourceType: 'Chat',
386
+ });
387
+ (0, vitest_1.expect)(mockActivityRepository.create).toHaveBeenCalledTimes(1);
388
+ const [activityPayload] = mockActivityRepository.create.mock.calls[0];
389
+ (0, vitest_1.expect)(activityPayload.metadata.usage).toMatchObject({
390
+ inputTokens: 205,
391
+ outputTokens: 3,
392
+ totalTokens: 209,
393
+ inputTokenDetails: { cacheReadTokens: 0 },
394
+ cost: 0.0005425,
395
+ costDetails: { upstreamInferenceCost: 0.0005425 },
396
+ });
397
+ (0, vitest_1.expect)(activityPayload.metadata.usage.promptTokens).toBeUndefined();
398
+ (0, vitest_1.expect)(activityPayload.metadata.usage.completionTokens).toBeUndefined();
399
+ (0, vitest_1.expect)(activityPayload.metadata.usage.promptTokensDetails).toBeUndefined();
400
+ });
401
+ });
402
+ (0, vitest_1.describe)('ChatProcessor.getMessages', () => {
403
+ let chatProcessor;
404
+ let mockChatRepository;
405
+ let mockMessageRepository;
406
+ let mockAgentConfigRepository;
407
+ let mockActivityRepository;
408
+ (0, vitest_1.beforeEach)(() => {
409
+ vitest_1.vi.clearAllMocks();
410
+ mockChatRepository = { findById: vitest_1.vi.fn() };
411
+ mockMessageRepository = {
412
+ findByChatIdPaginated: vitest_1.vi.fn().mockResolvedValue({ messages: [], hasMore: false }),
413
+ };
414
+ mockAgentConfigRepository = {
415
+ findByUserIdAndAgentName: vitest_1.vi.fn().mockResolvedValue(null),
416
+ };
417
+ mockActivityRepository = {
418
+ create: vitest_1.vi.fn(),
419
+ update: vitest_1.vi.fn(),
420
+ deleteByGroupId: vitest_1.vi.fn(),
421
+ };
422
+ const config = config_1.ConfigProvider.getInstance().getConfig();
423
+ const s3Lib = new s3_1.S3Lib(config.s3);
424
+ chatProcessor = new ChatProcessor_1.ChatProcessor({
425
+ chatRepository: mockChatRepository,
426
+ messageRepository: mockMessageRepository,
427
+ agentConfigRepository: mockAgentConfigRepository,
428
+ artifactStore: { listArtifacts: vitest_1.vi.fn().mockReturnValue([]), deleteArtifacts: vitest_1.vi.fn() },
429
+ s3Lib,
430
+ config,
431
+ socketService: { emitMessageUpdate: vitest_1.vi.fn(), emitChatUpdate: vitest_1.vi.fn() },
432
+ agentStore: {
433
+ registerAgentProcess: vitest_1.vi.fn().mockReturnValue({ signal: new AbortController().signal }),
434
+ shareAgentProcessEvent: vitest_1.vi.fn(),
435
+ addListener: vitest_1.vi.fn(),
436
+ removeListener: vitest_1.vi.fn(),
437
+ },
438
+ activityRepository: mockActivityRepository,
439
+ });
440
+ const aiHelper = chatProcessor.aiHelper;
441
+ vitest_1.vi.spyOn(aiHelper, 'getAgentOptions').mockResolvedValue({
442
+ name: 'test-agent',
443
+ tools: {
444
+ test_tool: {
445
+ inputSchema: zod_1.z.object({
446
+ foo: zod_1.z.any().optional(),
447
+ count: zod_1.z.any().optional(),
448
+ x: zod_1.z.any().optional(),
449
+ }),
450
+ },
451
+ },
452
+ });
453
+ });
454
+ (0, vitest_1.it)('returns messages page when chat exists', async () => {
455
+ const chatId = 'chat-1';
456
+ const messages = [
457
+ {
458
+ id: 'm1',
459
+ chat: chatId,
460
+ role: ai_agent_types_1.MessageRole.User,
461
+ content: 'Hi',
462
+ createdAt: new Date().toISOString(),
463
+ },
464
+ ];
465
+ mockChatRepository.findById.mockResolvedValue({ id: chatId });
466
+ mockMessageRepository.findByChatIdPaginated.mockResolvedValue({
467
+ messages,
468
+ hasMore: true,
469
+ });
470
+ const result = await chatProcessor.getMessages(chatId, { limit: 30 });
471
+ (0, vitest_1.expect)(result).toEqual({ messages, hasMore: true });
472
+ (0, vitest_1.expect)(mockMessageRepository.findByChatIdPaginated).toHaveBeenCalledWith(chatId, {
473
+ limit: 30,
474
+ before: undefined,
475
+ });
476
+ });
477
+ (0, vitest_1.it)('throws when chat not found', async () => {
478
+ mockChatRepository.findById.mockResolvedValue(null);
479
+ await (0, vitest_1.expect)(chatProcessor.getMessages('missing-chat')).rejects.toThrow('Chat not found');
480
+ (0, vitest_1.expect)(mockMessageRepository.findByChatIdPaginated).not.toHaveBeenCalled();
481
+ });
482
+ });
483
+ (0, vitest_1.describe)('ChatProcessor.updateToolCall', () => {
484
+ let chatProcessor;
485
+ let mockChatRepository;
486
+ let mockMessageRepository;
487
+ let mockAgentConfigRepository;
488
+ let mockActivityRepository;
489
+ let mockSocketService;
490
+ (0, vitest_1.beforeEach)(() => {
491
+ vitest_1.vi.clearAllMocks();
492
+ mockChatRepository = {
493
+ findById: vitest_1.vi.fn(),
494
+ update: vitest_1.vi.fn(),
495
+ };
496
+ mockMessageRepository = {
497
+ findById: vitest_1.vi.fn(),
498
+ updateToolCall: vitest_1.vi.fn(),
499
+ };
500
+ mockAgentConfigRepository = {
501
+ findByUserIdAndAgentName: vitest_1.vi.fn().mockResolvedValue(null),
502
+ };
503
+ mockActivityRepository = {
504
+ create: vitest_1.vi.fn(),
505
+ update: vitest_1.vi.fn(),
506
+ deleteByGroupId: vitest_1.vi.fn(),
507
+ };
508
+ mockSocketService = {
509
+ emitMessageUpdate: vitest_1.vi.fn(),
510
+ emitChatUpdate: vitest_1.vi.fn(),
511
+ };
512
+ const config = config_1.ConfigProvider.getInstance().getConfig();
513
+ const s3Lib = new s3_1.S3Lib(config.s3);
514
+ chatProcessor = new ChatProcessor_1.ChatProcessor({
515
+ chatRepository: mockChatRepository,
516
+ messageRepository: mockMessageRepository,
517
+ agentConfigRepository: mockAgentConfigRepository,
518
+ artifactStore: { listArtifacts: vitest_1.vi.fn().mockReturnValue([]), deleteArtifacts: vitest_1.vi.fn() },
519
+ s3Lib,
520
+ config,
521
+ socketService: mockSocketService,
522
+ agentStore: {
523
+ registerAgentProcess: vitest_1.vi.fn().mockReturnValue({ signal: new AbortController().signal }),
524
+ shareAgentProcessEvent: vitest_1.vi.fn(),
525
+ addListener: vitest_1.vi.fn(),
526
+ removeListener: vitest_1.vi.fn(),
527
+ },
528
+ activityRepository: mockActivityRepository,
529
+ });
530
+ });
531
+ (0, vitest_1.it)('updates targeted tool call input and emits update', async () => {
532
+ const chatId = 'chat-1';
533
+ const messageId = 'message-1';
534
+ const toolCallId = 'tool-call-1';
535
+ const userId = 'user-1';
536
+ const updatedInput = { foo: 'bar', count: 1 };
537
+ const now = new Date().toISOString();
538
+ mockChatRepository.findById.mockResolvedValue({
539
+ id: chatId,
540
+ userId,
541
+ });
542
+ mockMessageRepository.findById.mockResolvedValue({
543
+ id: messageId,
544
+ chat: chatId,
545
+ role: ai_agent_types_1.MessageRole.Assistant,
546
+ content: '',
547
+ createdAt: now,
548
+ toolCalls: [
549
+ {
550
+ id: toolCallId,
551
+ name: 'test_tool',
552
+ input: { foo: 'old' },
553
+ status: ai_agent_types_1.AgentToolCallStatus.Pending,
554
+ },
555
+ ],
556
+ });
557
+ mockMessageRepository.updateToolCall.mockResolvedValue({
558
+ id: messageId,
559
+ chat: chatId,
560
+ role: ai_agent_types_1.MessageRole.Assistant,
561
+ content: '',
562
+ createdAt: now,
563
+ toolCalls: [
564
+ {
565
+ id: toolCallId,
566
+ name: 'test_tool',
567
+ input: updatedInput,
568
+ status: ai_agent_types_1.AgentToolCallStatus.Pending,
569
+ },
570
+ ],
571
+ });
572
+ const aiHelper = chatProcessor.aiHelper;
573
+ vitest_1.vi.spyOn(aiHelper, 'getAgentOptions').mockResolvedValue({
574
+ name: 'test-agent',
575
+ tools: {
576
+ test_tool: {
577
+ inputSchema: zod_1.z.object({
578
+ foo: zod_1.z.any().optional(),
579
+ count: zod_1.z.any().optional(),
580
+ }),
581
+ },
582
+ },
583
+ });
584
+ const result = await chatProcessor.updateToolCall({
585
+ chatId,
586
+ messageId,
587
+ toolCallId,
588
+ input: updatedInput,
589
+ excludeSocketId: 'socket-1',
590
+ });
591
+ (0, vitest_1.expect)(mockMessageRepository.updateToolCall).toHaveBeenCalledWith(messageId, toolCallId, {
592
+ input: updatedInput,
593
+ });
594
+ (0, vitest_1.expect)(mockChatRepository.update).toHaveBeenCalledWith(chatId, vitest_1.expect.objectContaining({ updatedAt: vitest_1.expect.any(String) }));
595
+ (0, vitest_1.expect)(mockSocketService.emitMessageUpdate).toHaveBeenCalledWith(userId, result, 'socket-1');
596
+ (0, vitest_1.expect)(result.toolCalls?.[0].input).toEqual(updatedInput);
597
+ });
598
+ (0, vitest_1.it)('updates targeted tool call output and status', async () => {
599
+ const chatId = 'chat-1';
600
+ const messageId = 'message-1';
601
+ const toolCallId = 'tool-call-1';
602
+ const userId = 'user-1';
603
+ const now = new Date().toISOString();
604
+ mockChatRepository.findById.mockResolvedValue({
605
+ id: chatId,
606
+ userId,
607
+ });
608
+ mockMessageRepository.findById.mockResolvedValue({
609
+ id: messageId,
610
+ chat: chatId,
611
+ role: ai_agent_types_1.MessageRole.Assistant,
612
+ content: '',
613
+ createdAt: now,
614
+ toolCalls: [
615
+ {
616
+ id: toolCallId,
617
+ name: 'test_tool',
618
+ input: { foo: 'old' },
619
+ status: ai_agent_types_1.AgentToolCallStatus.Running,
620
+ },
621
+ ],
622
+ });
623
+ mockMessageRepository.updateToolCall.mockResolvedValue({
624
+ id: messageId,
625
+ chat: chatId,
626
+ role: ai_agent_types_1.MessageRole.Assistant,
627
+ content: '',
628
+ createdAt: now,
629
+ toolCalls: [
630
+ {
631
+ id: toolCallId,
632
+ name: 'test_tool',
633
+ input: { foo: 'old' },
634
+ output: { result: 'ok' },
635
+ status: ai_agent_types_1.AgentToolCallStatus.Succeeded,
636
+ },
637
+ ],
638
+ });
639
+ const result = await chatProcessor.updateToolCall({
640
+ chatId,
641
+ messageId,
642
+ toolCallId,
643
+ output: { result: 'ok' },
644
+ status: ai_agent_types_1.AgentToolCallStatus.Succeeded,
645
+ excludeSocketId: 'socket-1',
646
+ });
647
+ (0, vitest_1.expect)(mockMessageRepository.updateToolCall).toHaveBeenCalledWith(messageId, toolCallId, {
648
+ output: { result: 'ok' },
649
+ status: ai_agent_types_1.AgentToolCallStatus.Succeeded,
650
+ });
651
+ (0, vitest_1.expect)(mockChatRepository.update).toHaveBeenCalledWith(chatId, vitest_1.expect.objectContaining({ updatedAt: vitest_1.expect.any(String) }));
652
+ (0, vitest_1.expect)(mockSocketService.emitMessageUpdate).toHaveBeenCalledWith(userId, result, 'socket-1');
653
+ (0, vitest_1.expect)(result.toolCalls?.[0].status).toBe(ai_agent_types_1.AgentToolCallStatus.Succeeded);
654
+ (0, vitest_1.expect)(result.toolCalls?.[0].output).toEqual({ result: 'ok' });
655
+ });
656
+ (0, vitest_1.it)('throws when message is not in chat', async () => {
657
+ mockChatRepository.findById.mockResolvedValue({ id: 'chat-1', userId: 'user-1' });
658
+ mockMessageRepository.findById.mockResolvedValue({
659
+ id: 'message-1',
660
+ chat: 'other-chat',
661
+ role: ai_agent_types_1.MessageRole.Assistant,
662
+ content: '',
663
+ createdAt: new Date().toISOString(),
664
+ toolCalls: [],
665
+ });
666
+ await (0, vitest_1.expect)(chatProcessor.updateToolCall({
667
+ chatId: 'chat-1',
668
+ messageId: 'message-1',
669
+ toolCallId: 'tool-call-1',
670
+ input: { x: 1 },
671
+ })).rejects.toThrow('Message not found or does not belong to this chat');
672
+ (0, vitest_1.expect)(mockMessageRepository.updateToolCall).not.toHaveBeenCalled();
673
+ });
674
+ (0, vitest_1.it)('throws when chat does not belong to user', async () => {
675
+ mockChatRepository.findById.mockResolvedValue({ id: 'chat-1', userId: 'owner-1' });
676
+ await (0, vitest_1.expect)(chatProcessor.updateToolCall({
677
+ chatId: 'chat-1',
678
+ messageId: 'message-1',
679
+ toolCallId: 'tool-call-1',
680
+ userId: 'other-user',
681
+ input: { x: 1 },
682
+ })).rejects.toThrow('Chat does not belong to this user');
683
+ (0, vitest_1.expect)(mockMessageRepository.findById).not.toHaveBeenCalled();
684
+ (0, vitest_1.expect)(mockMessageRepository.updateToolCall).not.toHaveBeenCalled();
685
+ });
686
+ (0, vitest_1.it)('throws when tool call does not exist in message', async () => {
687
+ mockChatRepository.findById.mockResolvedValue({ id: 'chat-1', userId: 'user-1' });
688
+ mockMessageRepository.findById.mockResolvedValue({
689
+ id: 'message-1',
690
+ chat: 'chat-1',
691
+ role: ai_agent_types_1.MessageRole.Assistant,
692
+ content: '',
693
+ createdAt: new Date().toISOString(),
694
+ toolCalls: [
695
+ {
696
+ id: 'other-tool-call',
697
+ name: 'test_tool',
698
+ input: {},
699
+ status: ai_agent_types_1.AgentToolCallStatus.Pending,
700
+ },
701
+ ],
702
+ });
703
+ await (0, vitest_1.expect)(chatProcessor.updateToolCall({
704
+ chatId: 'chat-1',
705
+ messageId: 'message-1',
706
+ toolCallId: 'tool-call-1',
707
+ input: { x: 1 },
708
+ })).rejects.toThrow('Tool call not found in message');
709
+ (0, vitest_1.expect)(mockMessageRepository.updateToolCall).not.toHaveBeenCalled();
710
+ });
711
+ (0, vitest_1.it)('throws when no tool call fields are provided', async () => {
712
+ await (0, vitest_1.expect)(chatProcessor.updateToolCall({
713
+ chatId: 'chat-1',
714
+ messageId: 'message-1',
715
+ toolCallId: 'tool-call-1',
716
+ })).rejects.toThrow('At least one of input, output, or status must be provided');
717
+ });
718
+ (0, vitest_1.it)('throws when input does not match tool schema', async () => {
719
+ const chatId = 'chat-1';
720
+ const messageId = 'message-1';
721
+ const toolCallId = 'tool-call-1';
722
+ mockChatRepository.findById.mockResolvedValue({
723
+ id: chatId,
724
+ userId: 'user-1',
725
+ });
726
+ mockMessageRepository.findById.mockResolvedValue({
727
+ id: messageId,
728
+ chat: chatId,
729
+ role: ai_agent_types_1.MessageRole.Assistant,
730
+ content: '',
731
+ createdAt: new Date().toISOString(),
732
+ toolCalls: [
733
+ {
734
+ id: toolCallId,
735
+ name: 'test_tool',
736
+ input: {},
737
+ status: ai_agent_types_1.AgentToolCallStatus.Pending,
738
+ },
739
+ ],
740
+ agentName: 'test-agent',
741
+ });
742
+ const aiHelper = chatProcessor.aiHelper;
743
+ vitest_1.vi.spyOn(aiHelper, 'getAgentOptions').mockResolvedValue({
744
+ name: 'test-agent',
745
+ tools: {
746
+ test_tool: {
747
+ inputSchema: zod_1.z.object({
748
+ x: zod_1.z.number(),
749
+ }),
750
+ },
751
+ },
752
+ });
753
+ await (0, vitest_1.expect)(chatProcessor.updateToolCall({
754
+ chatId,
755
+ messageId,
756
+ toolCallId,
757
+ input: { x: 'invalid' },
758
+ })).rejects.toThrow('Invalid tool input for "test_tool"');
759
+ (0, vitest_1.expect)(mockMessageRepository.updateToolCall).not.toHaveBeenCalled();
760
+ });
761
+ });
762
+ //# sourceMappingURL=ChatProcessor.test.js.map