@aj-archipelago/cortex 1.3.21 → 1.3.23

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 (44) hide show
  1. package/README.md +64 -0
  2. package/config.js +26 -1
  3. package/helper-apps/cortex-realtime-voice-server/src/cortex/memory.ts +2 -2
  4. package/helper-apps/cortex-realtime-voice-server/src/realtime/client.ts +9 -4
  5. package/helper-apps/cortex-realtime-voice-server/src/realtime/realtimeTypes.ts +1 -0
  6. package/lib/util.js +5 -25
  7. package/package.json +5 -2
  8. package/pathways/system/entity/memory/shared/sys_memory_helpers.js +228 -0
  9. package/pathways/system/entity/memory/sys_memory_format.js +30 -0
  10. package/pathways/system/entity/memory/sys_memory_manager.js +85 -27
  11. package/pathways/system/entity/memory/sys_memory_process.js +154 -0
  12. package/pathways/system/entity/memory/sys_memory_required.js +4 -2
  13. package/pathways/system/entity/memory/sys_memory_topic.js +22 -0
  14. package/pathways/system/entity/memory/sys_memory_update.js +50 -150
  15. package/pathways/system/entity/memory/sys_read_memory.js +67 -69
  16. package/pathways/system/entity/memory/sys_save_memory.js +1 -1
  17. package/pathways/system/entity/memory/sys_search_memory.js +1 -1
  18. package/pathways/system/entity/sys_entity_start.js +9 -6
  19. package/pathways/system/entity/sys_generator_image.js +5 -41
  20. package/pathways/system/entity/sys_generator_memory.js +3 -1
  21. package/pathways/system/entity/sys_generator_reasoning.js +1 -1
  22. package/pathways/system/entity/sys_router_tool.js +3 -4
  23. package/pathways/system/rest_streaming/sys_claude_35_sonnet.js +1 -1
  24. package/pathways/system/rest_streaming/sys_claude_3_haiku.js +1 -1
  25. package/pathways/system/rest_streaming/sys_google_gemini_chat.js +1 -1
  26. package/pathways/system/rest_streaming/sys_ollama_chat.js +21 -0
  27. package/pathways/system/rest_streaming/sys_ollama_completion.js +14 -0
  28. package/pathways/system/rest_streaming/sys_openai_chat_o1.js +1 -1
  29. package/pathways/system/rest_streaming/sys_openai_chat_o3_mini.js +1 -1
  30. package/pathways/transcribe_gemini.js +525 -0
  31. package/server/modelExecutor.js +8 -0
  32. package/server/pathwayResolver.js +13 -8
  33. package/server/plugins/claude3VertexPlugin.js +150 -18
  34. package/server/plugins/gemini15ChatPlugin.js +90 -1
  35. package/server/plugins/gemini15VisionPlugin.js +16 -3
  36. package/server/plugins/modelPlugin.js +12 -9
  37. package/server/plugins/ollamaChatPlugin.js +158 -0
  38. package/server/plugins/ollamaCompletionPlugin.js +147 -0
  39. package/server/rest.js +70 -8
  40. package/tests/claude3VertexToolConversion.test.js +411 -0
  41. package/tests/memoryfunction.test.js +560 -46
  42. package/tests/multimodal_conversion.test.js +169 -0
  43. package/tests/openai_api.test.js +332 -0
  44. package/tests/transcribe_gemini.test.js +217 -0
@@ -0,0 +1,411 @@
1
+ import test from 'ava';
2
+ import Claude3VertexPlugin from '../server/plugins/claude3VertexPlugin.js';
3
+ import { mockPathwayResolverMessages } from './mocks.js';
4
+ import { config } from '../config.js';
5
+
6
+ const { pathway, modelName, model } = mockPathwayResolverMessages;
7
+
8
+ // Helper function to create a plugin instance
9
+ const createPlugin = () => new Claude3VertexPlugin(pathway, model);
10
+
11
+ // Test OpenAI tools block conversion
12
+ test('OpenAI tools block conversion', async (t) => {
13
+ const plugin = createPlugin();
14
+ const prompt = mockPathwayResolverMessages.pathway.prompt;
15
+
16
+ const parameters = {
17
+ tools: [
18
+ {
19
+ type: 'function',
20
+ function: {
21
+ name: 'get_weather',
22
+ description: 'Get current temperature for a given location.',
23
+ parameters: {
24
+ type: 'object',
25
+ properties: {
26
+ location: {
27
+ type: 'string',
28
+ description: 'City and country e.g. Bogotá, Colombia'
29
+ }
30
+ },
31
+ required: ['location'],
32
+ additionalProperties: false
33
+ },
34
+ strict: true
35
+ }
36
+ }
37
+ ]
38
+ };
39
+
40
+ const cortexRequest = { tools: parameters.tools };
41
+ const result = await plugin.getRequestParameters('test', parameters, prompt, cortexRequest);
42
+
43
+ t.deepEqual(result.tools, [{
44
+ name: 'get_weather',
45
+ description: 'Get current temperature for a given location.',
46
+ input_schema: {
47
+ type: 'object',
48
+ properties: {
49
+ location: {
50
+ type: 'string',
51
+ description: 'City and country e.g. Bogotá, Colombia'
52
+ }
53
+ },
54
+ required: ['location']
55
+ }
56
+ }]);
57
+ });
58
+
59
+ // Test tool call conversion without tools block
60
+ test('Tool call conversion without tools block', async (t) => {
61
+ const plugin = createPlugin();
62
+ const prompt = mockPathwayResolverMessages.pathway.prompt;
63
+
64
+ const messages = [
65
+ {
66
+ role: 'system',
67
+ content: 'You are a helpful assistant'
68
+ },
69
+ {
70
+ role: 'user',
71
+ content: 'What\'s in my memory?'
72
+ },
73
+ {
74
+ role: 'assistant',
75
+ content: [
76
+ {
77
+ type: 'tool_use',
78
+ id: 'tool_1',
79
+ name: 'memory_lookup',
80
+ input: 'search memory for relevant information'
81
+ }
82
+ ]
83
+ },
84
+ {
85
+ role: 'user',
86
+ content: [
87
+ {
88
+ type: 'tool_result',
89
+ tool_use_id: 'tool_1',
90
+ content: 'Memory search results here'
91
+ }
92
+ ]
93
+ }
94
+ ];
95
+
96
+ // add messages to mockPrompt.messages
97
+ prompt.messages = messages;
98
+
99
+ const cortexRequest = {};
100
+ const result = await plugin.getRequestParameters('test', {}, prompt, cortexRequest);
101
+
102
+ // Check generated tools block
103
+ t.deepEqual(result.tools, [{
104
+ name: 'memory_lookup',
105
+ description: 'Tool for memory_lookup',
106
+ input_schema: {
107
+ type: 'object',
108
+ properties: {
109
+ query: {
110
+ type: 'string',
111
+ description: 'Parameter query for memory_lookup'
112
+ }
113
+ },
114
+ required: ['query']
115
+ }
116
+ }]);
117
+
118
+ // Check converted messages
119
+ t.is(result.messages[1].role, 'assistant');
120
+ t.deepEqual(result.messages[1].content[0], {
121
+ type: 'tool_use',
122
+ id: 'tool_1',
123
+ name: 'memory_lookup',
124
+ input: { query: 'search memory for relevant information' }
125
+ });
126
+
127
+ t.is(result.messages[2].role, 'user');
128
+ t.deepEqual(result.messages[2].content[0], {
129
+ type: 'tool_result',
130
+ tool_use_id: 'tool_1',
131
+ content: 'Memory search results here'
132
+ });
133
+ });
134
+
135
+ // Test multiple tool calls in conversation
136
+ test('Multiple tool calls in conversation', async (t) => {
137
+ const plugin = createPlugin();
138
+ const prompt = mockPathwayResolverMessages.pathway.prompt;
139
+
140
+ const messages = [
141
+ {
142
+ role: 'system',
143
+ content: 'You are a helpful assistant'
144
+ },
145
+ {
146
+ role: 'user',
147
+ content: 'What\'s in my memory and what\'s the weather in San Francisco?'
148
+ },
149
+ {
150
+ role: 'assistant',
151
+ content: [
152
+ {
153
+ type: 'tool_use',
154
+ id: 'tool_1',
155
+ name: 'memory_lookup',
156
+ input: { query: 'search memory' }
157
+ }
158
+ ]
159
+ },
160
+ {
161
+ role: 'user',
162
+ content: [
163
+ {
164
+ type: 'tool_result',
165
+ tool_use_id: 'tool_1',
166
+ content: 'Memory results'
167
+ }
168
+ ]
169
+ },
170
+ {
171
+ role: 'assistant',
172
+ content: [
173
+ {
174
+ type: 'tool_use',
175
+ id: 'tool_2',
176
+ name: 'weather_lookup',
177
+ input: { location: 'San Francisco' }
178
+ }
179
+ ]
180
+ },
181
+ {
182
+ role: 'user',
183
+ content: [
184
+ {
185
+ type: 'tool_result',
186
+ tool_use_id: 'tool_2',
187
+ content: 'Weather results'
188
+ }
189
+ ]
190
+ }
191
+ ];
192
+
193
+ // add messages to mockPrompt.messages
194
+ prompt.messages = messages;
195
+
196
+ const cortexRequest = { messages };
197
+ const result = await plugin.getRequestParameters('test', {}, prompt, cortexRequest);
198
+
199
+ // Check that both tools are in the tools block
200
+ t.truthy(result.tools, 'Tools should be defined');
201
+ t.is(result.tools.length, 2, 'Should have 2 tools');
202
+ t.deepEqual(result.tools.map(t => t.name).sort(), ['memory_lookup', 'weather_lookup']);
203
+
204
+ // Check all messages are converted correctly
205
+ t.is(result.messages.length, 5);
206
+ t.deepEqual(result.messages[1].content[0].input, { query: 'search memory' });
207
+ t.deepEqual(result.messages[3].content[0].input, { location: 'San Francisco' });
208
+ });
209
+
210
+ // Test mixed conversation with tools and regular messages
211
+ test('Mixed conversation with tools and regular messages', async (t) => {
212
+ const plugin = createPlugin();
213
+ const prompt = mockPathwayResolverMessages.pathway.prompt;
214
+
215
+ const messages = [
216
+ {
217
+ role: 'system',
218
+ content: 'You are a helpful assistant'
219
+ },
220
+ {
221
+ role: 'user',
222
+ content: 'What\'s in my memory?'
223
+ },
224
+ {
225
+ role: 'assistant',
226
+ content: [
227
+ {
228
+ type: 'tool_use',
229
+ id: 'tool_1',
230
+ name: 'memory_lookup',
231
+ input: 'search memory'
232
+ }
233
+ ]
234
+ },
235
+ {
236
+ role: 'user',
237
+ content: [
238
+ {
239
+ type: 'tool_result',
240
+ tool_use_id: 'tool_1',
241
+ content: 'Memory results here'
242
+ }
243
+ ]
244
+ }
245
+ ];
246
+
247
+ // add messages to mockPrompt.messages
248
+ prompt.messages = messages;
249
+
250
+ const cortexRequest = { messages };
251
+ const result = await plugin.getRequestParameters('test', {}, prompt, cortexRequest);
252
+
253
+ // Check system message
254
+ t.is(result.system, 'You are a helpful assistant');
255
+
256
+ // Check regular messages and tool messages are converted correctly
257
+ t.is(result.messages.length, 3);
258
+ t.deepEqual(result.messages[0].content[0], { type: 'text', text: 'What\'s in my memory?' });
259
+ t.deepEqual(result.messages[1].content[0].input, { query: 'search memory' });
260
+ t.deepEqual(result.messages[2].content[0], {
261
+ type: 'tool_result',
262
+ tool_use_id: 'tool_1',
263
+ content: 'Memory results here'
264
+ });
265
+ });
266
+
267
+ // Test edge cases
268
+ test('Tool conversion edge cases', async (t) => {
269
+ const plugin = createPlugin();
270
+ const prompt = mockPathwayResolverMessages.pathway.prompt;
271
+
272
+ const messages = [
273
+ {
274
+ role: 'system',
275
+ content: 'You are a helpful assistant'
276
+ },
277
+ {
278
+ role: 'user',
279
+ content: 'What\'s in my memory?'
280
+ },
281
+ // Empty tool use
282
+ {
283
+ role: 'assistant',
284
+ content: [
285
+ {
286
+ type: 'tool_use',
287
+ id: 'tool_1',
288
+ name: 'empty_tool',
289
+ input: {}
290
+ }
291
+ ]
292
+ },
293
+ // Null input
294
+ {
295
+ role: 'assistant',
296
+ content: [
297
+ {
298
+ type: 'tool_use',
299
+ id: 'tool_2',
300
+ name: 'null_tool',
301
+ input: null
302
+ }
303
+ ]
304
+ },
305
+ // Missing tool_use_id
306
+ {
307
+ role: 'user',
308
+ content: [
309
+ {
310
+ type: 'tool_result',
311
+ content: 'Result without ID'
312
+ }
313
+ ]
314
+ },
315
+ // Empty tool result
316
+ {
317
+ role: 'user',
318
+ content: [
319
+ {
320
+ type: 'tool_result',
321
+ tool_use_id: 'tool_3',
322
+ content: ''
323
+ }
324
+ ]
325
+ }
326
+ ];
327
+
328
+ // add messages to mockPrompt.messages
329
+ prompt.messages = messages;
330
+
331
+ const cortexRequest = { messages };
332
+ const result = await plugin.getRequestParameters('test', {}, prompt, cortexRequest);
333
+
334
+ // Check tools block handles empty/null inputs
335
+ t.truthy(result.tools, 'Tools should be defined');
336
+ t.truthy(result.tools.find(t => t.name === 'empty_tool'), 'Should have empty_tool');
337
+ t.truthy(result.tools.find(t => t.name === 'null_tool'), 'Should have null_tool');
338
+ t.deepEqual(result.tools.find(t => t.name === 'empty_tool').input_schema.properties, {});
339
+ t.deepEqual(result.tools.find(t => t.name === 'null_tool').input_schema.properties, {});
340
+
341
+ // Check messages are converted without crashing
342
+ t.is(result.messages.length, 3);
343
+ });
344
+
345
+ // Test combining existing tools block with generated tools
346
+ test('Combining existing tools block with generated tools', async (t) => {
347
+ const plugin = createPlugin();
348
+ const prompt = mockPathwayResolverMessages.pathway.prompt;
349
+
350
+ const parameters = {
351
+ tools: [
352
+ {
353
+ type: 'function',
354
+ function: {
355
+ name: 'get_weather',
356
+ description: 'Get weather',
357
+ parameters: {
358
+ type: 'object',
359
+ properties: {
360
+ location: { type: 'string' }
361
+ },
362
+ required: ['location']
363
+ }
364
+ }
365
+ }
366
+ ]
367
+ };
368
+
369
+ const messages = [
370
+ {
371
+ role: 'system',
372
+ content: 'You are a helpful assistant'
373
+ },
374
+ {
375
+ role: 'user',
376
+ content: 'What\'s in my memory?'
377
+ },
378
+ {
379
+ role: 'assistant',
380
+ content: [
381
+ {
382
+ type: 'tool_use',
383
+ id: 'tool_1',
384
+ name: 'memory_lookup',
385
+ input: 'search memory'
386
+ }
387
+ ]
388
+ },
389
+ {
390
+ role: 'user',
391
+ content: [
392
+ {
393
+ type: 'tool_result',
394
+ tool_use_id: 'tool_1',
395
+ content: 'Memory results'
396
+ }
397
+ ]
398
+ }
399
+ ];
400
+
401
+ // add messages to mockPrompt.messages
402
+ prompt.messages = messages;
403
+
404
+ const cortexRequest = { messages };
405
+ const result = await plugin.getRequestParameters('test', parameters, prompt, cortexRequest);
406
+
407
+ // Check both tools are present
408
+ t.truthy(result.tools, 'Tools should be defined');
409
+ t.is(result.tools.length, 2, 'Should have 2 tools');
410
+ t.deepEqual(result.tools.map(t => t.name).sort(), ['get_weather', 'memory_lookup']);
411
+ });