@aj-archipelago/cortex 1.3.62 → 1.3.64

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 (215) hide show
  1. package/.github/workflows/cortex-file-handler-test.yml +61 -0
  2. package/README.md +31 -7
  3. package/config/default.example.json +15 -0
  4. package/config.js +133 -12
  5. package/helper-apps/cortex-autogen2/DigiCertGlobalRootCA.crt.pem +22 -0
  6. package/helper-apps/cortex-autogen2/Dockerfile +31 -0
  7. package/helper-apps/cortex-autogen2/Dockerfile.worker +41 -0
  8. package/helper-apps/cortex-autogen2/README.md +183 -0
  9. package/helper-apps/cortex-autogen2/__init__.py +1 -0
  10. package/helper-apps/cortex-autogen2/agents.py +131 -0
  11. package/helper-apps/cortex-autogen2/docker-compose.yml +20 -0
  12. package/helper-apps/cortex-autogen2/function_app.py +55 -0
  13. package/helper-apps/cortex-autogen2/host.json +15 -0
  14. package/helper-apps/cortex-autogen2/main.py +126 -0
  15. package/helper-apps/cortex-autogen2/poetry.lock +3652 -0
  16. package/helper-apps/cortex-autogen2/pyproject.toml +36 -0
  17. package/helper-apps/cortex-autogen2/requirements.txt +20 -0
  18. package/helper-apps/cortex-autogen2/send_task.py +105 -0
  19. package/helper-apps/cortex-autogen2/services/__init__.py +1 -0
  20. package/helper-apps/cortex-autogen2/services/azure_queue.py +85 -0
  21. package/helper-apps/cortex-autogen2/services/redis_publisher.py +153 -0
  22. package/helper-apps/cortex-autogen2/task_processor.py +488 -0
  23. package/helper-apps/cortex-autogen2/tools/__init__.py +24 -0
  24. package/helper-apps/cortex-autogen2/tools/azure_blob_tools.py +175 -0
  25. package/helper-apps/cortex-autogen2/tools/azure_foundry_agents.py +601 -0
  26. package/helper-apps/cortex-autogen2/tools/coding_tools.py +72 -0
  27. package/helper-apps/cortex-autogen2/tools/download_tools.py +48 -0
  28. package/helper-apps/cortex-autogen2/tools/file_tools.py +545 -0
  29. package/helper-apps/cortex-autogen2/tools/search_tools.py +646 -0
  30. package/helper-apps/cortex-azure-cleaner/README.md +36 -0
  31. package/helper-apps/cortex-file-converter/README.md +93 -0
  32. package/helper-apps/cortex-file-converter/key_to_pdf.py +104 -0
  33. package/helper-apps/cortex-file-converter/list_blob_extensions.py +89 -0
  34. package/helper-apps/cortex-file-converter/process_azure_keynotes.py +181 -0
  35. package/helper-apps/cortex-file-converter/requirements.txt +1 -0
  36. package/helper-apps/cortex-file-handler/.env.test.azure.ci +7 -0
  37. package/helper-apps/cortex-file-handler/.env.test.azure.sample +1 -1
  38. package/helper-apps/cortex-file-handler/.env.test.gcs.ci +10 -0
  39. package/helper-apps/cortex-file-handler/.env.test.gcs.sample +2 -2
  40. package/helper-apps/cortex-file-handler/INTERFACE.md +41 -0
  41. package/helper-apps/cortex-file-handler/package.json +1 -1
  42. package/helper-apps/cortex-file-handler/scripts/setup-azure-container.js +41 -17
  43. package/helper-apps/cortex-file-handler/scripts/setup-test-containers.js +30 -15
  44. package/helper-apps/cortex-file-handler/scripts/test-azure.sh +32 -6
  45. package/helper-apps/cortex-file-handler/scripts/test-gcs.sh +24 -2
  46. package/helper-apps/cortex-file-handler/scripts/validate-env.js +128 -0
  47. package/helper-apps/cortex-file-handler/src/blobHandler.js +161 -51
  48. package/helper-apps/cortex-file-handler/src/constants.js +3 -0
  49. package/helper-apps/cortex-file-handler/src/fileChunker.js +10 -8
  50. package/helper-apps/cortex-file-handler/src/index.js +116 -9
  51. package/helper-apps/cortex-file-handler/src/redis.js +61 -1
  52. package/helper-apps/cortex-file-handler/src/services/ConversionService.js +11 -8
  53. package/helper-apps/cortex-file-handler/src/services/FileConversionService.js +2 -2
  54. package/helper-apps/cortex-file-handler/src/services/storage/AzureStorageProvider.js +88 -6
  55. package/helper-apps/cortex-file-handler/src/services/storage/GCSStorageProvider.js +58 -0
  56. package/helper-apps/cortex-file-handler/src/services/storage/StorageFactory.js +25 -5
  57. package/helper-apps/cortex-file-handler/src/services/storage/StorageProvider.js +9 -0
  58. package/helper-apps/cortex-file-handler/src/services/storage/StorageService.js +120 -16
  59. package/helper-apps/cortex-file-handler/src/start.js +27 -17
  60. package/helper-apps/cortex-file-handler/tests/FileConversionService.test.js +52 -1
  61. package/helper-apps/cortex-file-handler/tests/blobHandler.test.js +40 -0
  62. package/helper-apps/cortex-file-handler/tests/checkHashShortLived.test.js +553 -0
  63. package/helper-apps/cortex-file-handler/tests/cleanup.test.js +46 -52
  64. package/helper-apps/cortex-file-handler/tests/containerConversionFlow.test.js +451 -0
  65. package/helper-apps/cortex-file-handler/tests/containerNameParsing.test.js +229 -0
  66. package/helper-apps/cortex-file-handler/tests/containerParameterFlow.test.js +392 -0
  67. package/helper-apps/cortex-file-handler/tests/conversionResilience.test.js +7 -2
  68. package/helper-apps/cortex-file-handler/tests/deleteOperations.test.js +348 -0
  69. package/helper-apps/cortex-file-handler/tests/fileChunker.test.js +23 -2
  70. package/helper-apps/cortex-file-handler/tests/fileUpload.test.js +11 -5
  71. package/helper-apps/cortex-file-handler/tests/getOperations.test.js +58 -24
  72. package/helper-apps/cortex-file-handler/tests/postOperations.test.js +11 -4
  73. package/helper-apps/cortex-file-handler/tests/shortLivedUrlConversion.test.js +225 -0
  74. package/helper-apps/cortex-file-handler/tests/start.test.js +8 -12
  75. package/helper-apps/cortex-file-handler/tests/storage/StorageFactory.test.js +80 -0
  76. package/helper-apps/cortex-file-handler/tests/storage/StorageService.test.js +388 -22
  77. package/helper-apps/cortex-file-handler/tests/testUtils.helper.js +74 -0
  78. package/lib/cortexResponse.js +153 -0
  79. package/lib/entityConstants.js +21 -3
  80. package/lib/logger.js +21 -4
  81. package/lib/pathwayTools.js +28 -9
  82. package/lib/util.js +49 -0
  83. package/package.json +1 -1
  84. package/pathways/basePathway.js +1 -0
  85. package/pathways/bing_afagent.js +54 -1
  86. package/pathways/call_tools.js +2 -3
  87. package/pathways/chat_jarvis.js +1 -1
  88. package/pathways/google_cse.js +27 -0
  89. package/pathways/grok_live_search.js +18 -0
  90. package/pathways/system/entity/memory/shared/sys_memory_helpers.js +1 -1
  91. package/pathways/system/entity/memory/sys_memory_lookup_required.js +1 -0
  92. package/pathways/system/entity/memory/sys_memory_manager.js +1 -1
  93. package/pathways/system/entity/memory/sys_memory_required.js +1 -0
  94. package/pathways/system/entity/memory/sys_search_memory.js +1 -0
  95. package/pathways/system/entity/sys_entity_agent.js +72 -7
  96. package/pathways/system/entity/sys_generator_quick.js +1 -0
  97. package/pathways/system/entity/sys_generator_results.js +1 -1
  98. package/pathways/system/entity/tools/sys_tool_bing_search_afagent.js +26 -0
  99. package/pathways/system/entity/tools/sys_tool_google_search.js +141 -0
  100. package/pathways/system/entity/tools/sys_tool_grok_x_search.js +237 -0
  101. package/pathways/system/entity/tools/sys_tool_image.js +1 -1
  102. package/pathways/system/rest_streaming/sys_claude_37_sonnet.js +21 -0
  103. package/pathways/system/rest_streaming/sys_claude_41_opus.js +21 -0
  104. package/pathways/system/rest_streaming/sys_claude_4_sonnet.js +21 -0
  105. package/pathways/system/rest_streaming/sys_google_gemini_25_flash.js +25 -0
  106. package/pathways/system/rest_streaming/{sys_google_gemini_chat.js → sys_google_gemini_25_pro.js} +6 -4
  107. package/pathways/system/rest_streaming/sys_grok_4.js +23 -0
  108. package/pathways/system/rest_streaming/sys_grok_4_fast_non_reasoning.js +23 -0
  109. package/pathways/system/rest_streaming/sys_grok_4_fast_reasoning.js +23 -0
  110. package/pathways/system/rest_streaming/sys_openai_chat.js +3 -0
  111. package/pathways/system/rest_streaming/sys_openai_chat_gpt41.js +22 -0
  112. package/pathways/system/rest_streaming/sys_openai_chat_gpt41_mini.js +21 -0
  113. package/pathways/system/rest_streaming/sys_openai_chat_gpt41_nano.js +21 -0
  114. package/pathways/system/rest_streaming/{sys_claude_35_sonnet.js → sys_openai_chat_gpt4_omni.js} +6 -4
  115. package/pathways/system/rest_streaming/sys_openai_chat_gpt4_omni_mini.js +21 -0
  116. package/pathways/system/rest_streaming/{sys_claude_3_haiku.js → sys_openai_chat_gpt5.js} +7 -5
  117. package/pathways/system/rest_streaming/sys_openai_chat_gpt5_chat.js +21 -0
  118. package/pathways/system/rest_streaming/sys_openai_chat_gpt5_mini.js +21 -0
  119. package/pathways/system/rest_streaming/sys_openai_chat_gpt5_nano.js +21 -0
  120. package/pathways/system/rest_streaming/{sys_openai_chat_o1.js → sys_openai_chat_o3.js} +6 -3
  121. package/pathways/system/rest_streaming/sys_openai_chat_o3_mini.js +3 -0
  122. package/pathways/system/workspaces/run_workspace_prompt.js +99 -0
  123. package/pathways/vision.js +1 -1
  124. package/server/graphql.js +1 -1
  125. package/server/modelExecutor.js +8 -0
  126. package/server/pathwayResolver.js +166 -16
  127. package/server/pathwayResponseParser.js +16 -8
  128. package/server/plugins/azureFoundryAgentsPlugin.js +1 -1
  129. package/server/plugins/claude3VertexPlugin.js +193 -45
  130. package/server/plugins/gemini15ChatPlugin.js +21 -0
  131. package/server/plugins/gemini15VisionPlugin.js +362 -0
  132. package/server/plugins/googleCsePlugin.js +94 -0
  133. package/server/plugins/grokVisionPlugin.js +365 -0
  134. package/server/plugins/modelPlugin.js +3 -1
  135. package/server/plugins/openAiChatPlugin.js +106 -13
  136. package/server/plugins/openAiVisionPlugin.js +45 -31
  137. package/server/resolver.js +28 -4
  138. package/server/rest.js +270 -53
  139. package/server/typeDef.js +1 -0
  140. package/tests/{mocks.js → helpers/mocks.js} +5 -2
  141. package/tests/{server.js → helpers/server.js} +2 -2
  142. package/tests/helpers/sseAssert.js +23 -0
  143. package/tests/helpers/sseClient.js +73 -0
  144. package/tests/helpers/subscriptionAssert.js +11 -0
  145. package/tests/helpers/subscriptions.js +113 -0
  146. package/tests/{sublong.srt → integration/features/translate/sublong.srt} +4543 -4543
  147. package/tests/integration/features/translate/translate_chunking_stream.test.js +100 -0
  148. package/tests/{translate_srt.test.js → integration/features/translate/translate_srt.test.js} +2 -2
  149. package/tests/integration/graphql/async/stream/agentic.test.js +477 -0
  150. package/tests/integration/graphql/async/stream/subscription_streaming.test.js +62 -0
  151. package/tests/integration/graphql/async/stream/sys_entity_start_streaming.test.js +71 -0
  152. package/tests/integration/graphql/async/stream/vendors/claude_streaming.test.js +56 -0
  153. package/tests/integration/graphql/async/stream/vendors/gemini_streaming.test.js +66 -0
  154. package/tests/integration/graphql/async/stream/vendors/grok_streaming.test.js +56 -0
  155. package/tests/integration/graphql/async/stream/vendors/openai_streaming.test.js +72 -0
  156. package/tests/integration/graphql/features/google/sysToolGoogleSearch.test.js +96 -0
  157. package/tests/integration/graphql/features/grok/grok.test.js +688 -0
  158. package/tests/integration/graphql/features/grok/grok_x_search_tool.test.js +354 -0
  159. package/tests/{main.test.js → integration/graphql/features/main.test.js} +1 -1
  160. package/tests/{call_tools.test.js → integration/graphql/features/tools/call_tools.test.js} +2 -2
  161. package/tests/{vision.test.js → integration/graphql/features/vision/vision.test.js} +1 -1
  162. package/tests/integration/graphql/subscriptions/connection.test.js +26 -0
  163. package/tests/{openai_api.test.js → integration/rest/oai/openai_api.test.js} +63 -238
  164. package/tests/integration/rest/oai/tool_calling_api.test.js +343 -0
  165. package/tests/integration/rest/oai/tool_calling_streaming.test.js +85 -0
  166. package/tests/integration/rest/vendors/claude_streaming.test.js +47 -0
  167. package/tests/integration/rest/vendors/claude_tool_calling_streaming.test.js +75 -0
  168. package/tests/integration/rest/vendors/gemini_streaming.test.js +47 -0
  169. package/tests/integration/rest/vendors/gemini_tool_calling_streaming.test.js +75 -0
  170. package/tests/integration/rest/vendors/grok_streaming.test.js +55 -0
  171. package/tests/integration/rest/vendors/grok_tool_calling_streaming.test.js +75 -0
  172. package/tests/{azureAuthTokenHelper.test.js → unit/core/azureAuthTokenHelper.test.js} +1 -1
  173. package/tests/{chunkfunction.test.js → unit/core/chunkfunction.test.js} +2 -2
  174. package/tests/{config.test.js → unit/core/config.test.js} +3 -3
  175. package/tests/{encodeCache.test.js → unit/core/encodeCache.test.js} +1 -1
  176. package/tests/{fastLruCache.test.js → unit/core/fastLruCache.test.js} +1 -1
  177. package/tests/{handleBars.test.js → unit/core/handleBars.test.js} +1 -1
  178. package/tests/{memoryfunction.test.js → unit/core/memoryfunction.test.js} +2 -2
  179. package/tests/unit/core/mergeResolver.test.js +952 -0
  180. package/tests/{parser.test.js → unit/core/parser.test.js} +3 -3
  181. package/tests/unit/core/pathwayResolver.test.js +187 -0
  182. package/tests/{requestMonitor.test.js → unit/core/requestMonitor.test.js} +1 -1
  183. package/tests/{requestMonitorDurationEstimator.test.js → unit/core/requestMonitorDurationEstimator.test.js} +1 -1
  184. package/tests/{truncateMessages.test.js → unit/core/truncateMessages.test.js} +3 -3
  185. package/tests/{util.test.js → unit/core/util.test.js} +1 -1
  186. package/tests/{apptekTranslatePlugin.test.js → unit/plugins/apptekTranslatePlugin.test.js} +3 -3
  187. package/tests/{azureFoundryAgents.test.js → unit/plugins/azureFoundryAgents.test.js} +136 -1
  188. package/tests/{claude3VertexPlugin.test.js → unit/plugins/claude3VertexPlugin.test.js} +32 -10
  189. package/tests/{claude3VertexToolConversion.test.js → unit/plugins/claude3VertexToolConversion.test.js} +3 -3
  190. package/tests/unit/plugins/googleCsePlugin.test.js +111 -0
  191. package/tests/unit/plugins/grokVisionPlugin.test.js +1392 -0
  192. package/tests/{modelPlugin.test.js → unit/plugins/modelPlugin.test.js} +3 -3
  193. package/tests/{multimodal_conversion.test.js → unit/plugins/multimodal_conversion.test.js} +4 -4
  194. package/tests/{openAiChatPlugin.test.js → unit/plugins/openAiChatPlugin.test.js} +13 -4
  195. package/tests/{openAiToolPlugin.test.js → unit/plugins/openAiToolPlugin.test.js} +35 -27
  196. package/tests/{tokenHandlingTests.test.js → unit/plugins/tokenHandlingTests.test.js} +5 -5
  197. package/tests/unit/plugins/toolCallBufferFiltering.test.js +297 -0
  198. package/tests/{translate_apptek.test.js → unit/plugins/translate_apptek.test.js} +3 -3
  199. package/tests/{streaming.test.js → unit/plugins.streaming/plugin_stream_events.test.js} +19 -58
  200. package/helper-apps/mogrt-handler/tests/test-files/test.gif +0 -1
  201. package/helper-apps/mogrt-handler/tests/test-files/test.mogrt +0 -1
  202. package/helper-apps/mogrt-handler/tests/test-files/test.mp4 +0 -1
  203. package/pathways/system/rest_streaming/sys_openai_chat_gpt4.js +0 -19
  204. package/pathways/system/rest_streaming/sys_openai_chat_gpt4_32.js +0 -19
  205. package/pathways/system/rest_streaming/sys_openai_chat_gpt4_turbo.js +0 -19
  206. package/pathways/system/workspaces/run_claude35_sonnet.js +0 -21
  207. package/pathways/system/workspaces/run_claude3_haiku.js +0 -20
  208. package/pathways/system/workspaces/run_gpt35turbo.js +0 -20
  209. package/pathways/system/workspaces/run_gpt4.js +0 -20
  210. package/pathways/system/workspaces/run_gpt4_32.js +0 -20
  211. package/tests/agentic.test.js +0 -256
  212. package/tests/pathwayResolver.test.js +0 -78
  213. package/tests/subscription.test.js +0 -387
  214. /package/tests/{subchunk.srt → integration/features/translate/subchunk.srt} +0 -0
  215. /package/tests/{subhorizontal.srt → integration/features/translate/subhorizontal.srt} +0 -0
@@ -1,8 +1,8 @@
1
1
  // test/ModelPlugin.test.js
2
2
  import test from 'ava';
3
- import ModelPlugin from '../server/plugins/modelPlugin.js';
4
- import HandleBars from '../lib/handleBars.js';
5
- import { mockConfig, mockPathwayString, mockPathwayFunction, mockPathwayMessages, mockPathwayResolverString } from './mocks.js';
3
+ import ModelPlugin from '../../../server/plugins/modelPlugin.js';
4
+ import HandleBars from '../../../lib/handleBars.js';
5
+ import { mockConfig, mockPathwayString, mockPathwayFunction, mockPathwayMessages, mockPathwayResolverString } from '../../helpers/mocks.js';
6
6
 
7
7
  const DEFAULT_MAX_TOKENS = 4096;
8
8
  const DEFAULT_PROMPT_TOKEN_RATIO = 1.0;
@@ -1,8 +1,8 @@
1
1
  import test from 'ava';
2
- import OpenAIVisionPlugin from '../server/plugins/openAiVisionPlugin.js';
3
- import Claude3VertexPlugin from '../server/plugins/claude3VertexPlugin.js';
4
- import Gemini15VisionPlugin from '../server/plugins/gemini15VisionPlugin.js';
5
- import GeminiVisionPlugin from '../server/plugins/geminiVisionPlugin.js';
2
+ import OpenAIVisionPlugin from '../../../server/plugins/openAiVisionPlugin.js';
3
+ import Claude3VertexPlugin from '../../../server/plugins/claude3VertexPlugin.js';
4
+ import Gemini15VisionPlugin from '../../../server/plugins/gemini15VisionPlugin.js';
5
+ import GeminiVisionPlugin from '../../../server/plugins/geminiVisionPlugin.js';
6
6
 
7
7
  // Mock pathway and model for plugin initialization
8
8
  const mockPathway = { name: 'test', temperature: 0.7 };
@@ -1,7 +1,7 @@
1
1
  import test from 'ava';
2
- import OpenAIChatPlugin from '../server/plugins/openAiChatPlugin.js';
3
- import { mockPathwayResolverMessages } from './mocks.js';
4
- import { config } from '../config.js';
2
+ import OpenAIChatPlugin from '../../../server/plugins/openAiChatPlugin.js';
3
+ import { mockPathwayResolverMessages } from '../../helpers/mocks.js';
4
+ import { config } from '../../../config.js';
5
5
 
6
6
  const { pathway, modelName, model } = mockPathwayResolverMessages;
7
7
 
@@ -107,7 +107,16 @@ test('parseResponse', (t) => {
107
107
  ],
108
108
  };
109
109
  const result = plugin.parseResponse(data);
110
- t.is(result, 'Sure, I can help John who is 30 years old.');
110
+
111
+ // Verify it's a CortexResponse object
112
+ t.truthy(result);
113
+ t.is(typeof result, 'object');
114
+ t.is(result.constructor.name, 'CortexResponse');
115
+
116
+
117
+ // Verify the content using string conversion (triggers toString automatically)
118
+ t.is(String(result), 'Sure, I can help John who is 30 years old.');
119
+ t.is(result.finishReason, 'stop');
111
120
  });
112
121
 
113
122
  // Test the logRequestData function
@@ -1,7 +1,7 @@
1
1
  import test from 'ava';
2
- import OpenAIVisionPlugin from '../server/plugins/openAiVisionPlugin.js';
3
- import { mockPathwayResolverMessages } from './mocks.js';
4
- import { config } from '../config.js';
2
+ import OpenAIVisionPlugin from '../../../server/plugins/openAiVisionPlugin.js';
3
+ import { mockPathwayResolverMessages } from '../../helpers/mocks.js';
4
+ import { config } from '../../../config.js';
5
5
 
6
6
  const { pathway, modelName, model } = mockPathwayResolverMessages;
7
7
 
@@ -71,18 +71,22 @@ test('Tool call response handling', async (t) => {
71
71
 
72
72
  const result = plugin.parseResponse(responseData);
73
73
 
74
- t.deepEqual(result, {
75
- role: 'assistant',
76
- content: 'I will check the weather for you.',
77
- tool_calls: [{
78
- id: 'call_123',
79
- type: 'function',
80
- function: {
81
- name: 'get_weather',
82
- arguments: '{"location": "Bogotá, Colombia"}'
83
- }
84
- }]
85
- });
74
+ // Verify it's a CortexResponse object
75
+ t.truthy(result);
76
+ t.is(typeof result, 'object');
77
+ t.is(result.constructor.name, 'CortexResponse');
78
+
79
+ // Verify the content
80
+ t.is(result.output_text, 'I will check the weather for you.');
81
+ t.is(result.finishReason, 'tool_calls');
82
+
83
+ // Verify tool calls
84
+ t.truthy(result.toolCalls);
85
+ t.is(result.toolCalls.length, 1);
86
+ t.is(result.toolCalls[0].id, 'call_123');
87
+ t.is(result.toolCalls[0].type, 'function');
88
+ t.is(result.toolCalls[0].function.name, 'get_weather');
89
+ t.is(result.toolCalls[0].function.arguments, '{"location": "Bogotá, Colombia"}');
86
90
  });
87
91
 
88
92
  // Test tool result message handling
@@ -177,18 +181,22 @@ test('Error handling in tool calls', async (t) => {
177
181
 
178
182
  const result = plugin.parseResponse(responseData);
179
183
 
180
- t.deepEqual(result, {
181
- role: 'assistant',
182
- content: 'I will check the weather for you.',
183
- tool_calls: [{
184
- id: 'call_123',
185
- type: 'function',
186
- function: {
187
- name: 'get_weather',
188
- arguments: 'invalid json'
189
- }
190
- }]
191
- });
184
+ // Verify it's a CortexResponse object
185
+ t.truthy(result);
186
+ t.is(typeof result, 'object');
187
+ t.is(result.constructor.name, 'CortexResponse');
188
+
189
+ // Verify the content
190
+ t.is(result.output_text, 'I will check the weather for you.');
191
+ t.is(result.finishReason, 'tool_calls');
192
+
193
+ // Verify tool calls
194
+ t.truthy(result.toolCalls);
195
+ t.is(result.toolCalls.length, 1);
196
+ t.is(result.toolCalls[0].id, 'call_123');
197
+ t.is(result.toolCalls[0].type, 'function');
198
+ t.is(result.toolCalls[0].function.name, 'get_weather');
199
+ t.is(result.toolCalls[0].function.arguments, 'invalid json');
192
200
  });
193
201
 
194
202
  // Test multiple tool calls in sequence
@@ -1,11 +1,11 @@
1
1
  import test from 'ava';
2
2
  import fs from 'fs';
3
3
  import path from 'path';
4
- import { encode } from '../lib/encodeCache.js';
5
- import { getFirstNToken } from '../server/chunker.js';
6
- import Claude3VertexPlugin from '../server/plugins/claude3VertexPlugin.js';
7
- import ModelPlugin from '../server/plugins/modelPlugin.js';
8
- import { mockPathwayResolverMessages } from './mocks.js';
4
+ import { encode } from '../../../lib/encodeCache.js';
5
+ import { getFirstNToken } from '../../../server/chunker.js';
6
+ import Claude3VertexPlugin from '../../../server/plugins/claude3VertexPlugin.js';
7
+ import ModelPlugin from '../../../server/plugins/modelPlugin.js';
8
+ import { mockPathwayResolverMessages } from '../../helpers/mocks.js';
9
9
 
10
10
  const { pathway, model } = mockPathwayResolverMessages;
11
11
 
@@ -0,0 +1,297 @@
1
+ import test from 'ava';
2
+ import OpenAIVisionPlugin from '../../../server/plugins/openAiVisionPlugin.js';
3
+ import Gemini15VisionPlugin from '../../../server/plugins/gemini15VisionPlugin.js';
4
+ import { PathwayResolver } from '../../../server/pathwayResolver.js';
5
+ import { config } from '../../../config.js';
6
+ import { requestState } from '../../../server/requestState.js';
7
+
8
+ // Mock logger to prevent issues in tests
9
+ const mockLogger = {
10
+ debug: () => {},
11
+ info: () => {},
12
+ warn: () => {},
13
+ error: () => {}
14
+ };
15
+
16
+ // Mock the logger module globally
17
+ global.logger = mockLogger;
18
+
19
+ function createResolverWithPlugin(pluginClass, modelName = 'test-model') {
20
+ const pluginToModelType = {
21
+ OpenAIVisionPlugin: 'OPENAI-VISION',
22
+ Gemini15VisionPlugin: 'GEMINI-1.5-VISION'
23
+ };
24
+
25
+ const modelType = pluginToModelType[pluginClass.name];
26
+ if (!modelType) {
27
+ throw new Error(`Unknown plugin class: ${pluginClass.name}`);
28
+ }
29
+
30
+ const pathway = {
31
+ name: 'test-pathway',
32
+ model: modelName,
33
+ prompt: 'test prompt',
34
+ toolCallback: () => {} // Mock tool callback
35
+ };
36
+
37
+ const model = {
38
+ name: modelName,
39
+ type: modelType
40
+ };
41
+
42
+ const resolver = new PathwayResolver({
43
+ config,
44
+ pathway,
45
+ args: {},
46
+ endpoints: { [modelName]: model }
47
+ });
48
+
49
+ resolver.modelExecutor.plugin = new pluginClass(pathway, model);
50
+ return resolver;
51
+ }
52
+
53
+ test('OpenAIVisionPlugin - filters undefined tool calls from buffer', async t => {
54
+ const resolver = createResolverWithPlugin(OpenAIVisionPlugin);
55
+ const plugin = resolver.modelExecutor.plugin;
56
+
57
+ // Simulate the scenario where tool calls start at index 1, leaving index 0 undefined
58
+ plugin.toolCallsBuffer[0] = undefined; // This is what causes the issue
59
+ plugin.toolCallsBuffer[1] = {
60
+ id: 'call_1_1234567890',
61
+ type: 'function',
62
+ function: {
63
+ name: 'test_tool',
64
+ arguments: '{"param": "value"}'
65
+ }
66
+ };
67
+
68
+ // Mock the tool callback to capture what gets passed
69
+ let capturedToolCalls = null;
70
+ plugin.pathwayToolCallback = (args, message, resolver) => {
71
+ capturedToolCalls = message.tool_calls;
72
+ };
73
+
74
+ // Mock requestProgress and pathwayResolver
75
+ const requestProgress = { progress: 0, started: true };
76
+ const pathwayResolver = { args: {} };
77
+
78
+ // Mock requestState to return our resolver
79
+ requestState[plugin.requestId] = { pathwayResolver };
80
+
81
+ // Simulate a tool_calls finish reason
82
+ const event = {
83
+ data: JSON.stringify({
84
+ choices: [{
85
+ finish_reason: 'tool_calls'
86
+ }]
87
+ })
88
+ };
89
+
90
+ // Process the stream event
91
+ plugin.processStreamEvent(event, requestProgress);
92
+
93
+ // Verify that undefined elements were filtered out
94
+ t.truthy(capturedToolCalls, 'Tool callback should have been called');
95
+ t.is(capturedToolCalls.length, 1, 'Should have filtered out undefined elements');
96
+ t.is(capturedToolCalls[0].function.name, 'test_tool', 'Valid tool call should be preserved');
97
+
98
+ // Clean up
99
+ delete requestState[plugin.requestId];
100
+ });
101
+
102
+ test('OpenAIVisionPlugin - handles empty buffer gracefully', async t => {
103
+ const resolver = createResolverWithPlugin(OpenAIVisionPlugin);
104
+ const plugin = resolver.modelExecutor.plugin;
105
+
106
+ // Empty buffer
107
+ plugin.toolCallsBuffer = [];
108
+
109
+ // Mock the tool callback
110
+ let callbackCalled = false;
111
+ plugin.pathwayToolCallback = () => {
112
+ callbackCalled = true;
113
+ };
114
+
115
+ // Mock requestProgress and pathwayResolver
116
+ const requestProgress = { progress: 0, started: true };
117
+ const pathwayResolver = { args: {} };
118
+
119
+ // Mock requestState
120
+ requestState[plugin.requestId] = { pathwayResolver };
121
+
122
+ // Simulate a tool_calls finish reason
123
+ const event = {
124
+ data: JSON.stringify({
125
+ choices: [{
126
+ finish_reason: 'tool_calls'
127
+ }]
128
+ })
129
+ };
130
+
131
+ // Process the stream event
132
+ plugin.processStreamEvent(event, requestProgress);
133
+
134
+ // Verify that callback was not called with empty buffer
135
+ t.falsy(callbackCalled, 'Tool callback should not be called with empty buffer');
136
+
137
+ // Clean up
138
+ delete requestState[plugin.requestId];
139
+ });
140
+
141
+ test('OpenAIVisionPlugin - filters invalid tool calls', async t => {
142
+ const resolver = createResolverWithPlugin(OpenAIVisionPlugin);
143
+ const plugin = resolver.modelExecutor.plugin;
144
+
145
+ // Create buffer with mixed valid and invalid tool calls
146
+ plugin.toolCallsBuffer[0] = undefined;
147
+ plugin.toolCallsBuffer[1] = {
148
+ id: 'call_1_1234567890',
149
+ type: 'function',
150
+ function: {
151
+ name: 'valid_tool',
152
+ arguments: '{"param": "value"}'
153
+ }
154
+ };
155
+ plugin.toolCallsBuffer[2] = {
156
+ id: 'call_2_1234567890',
157
+ type: 'function',
158
+ function: {
159
+ name: '', // Invalid: empty name
160
+ arguments: '{"param": "value"}'
161
+ }
162
+ };
163
+ plugin.toolCallsBuffer[3] = {
164
+ id: 'call_3_1234567890',
165
+ type: 'function',
166
+ function: {
167
+ name: 'another_valid_tool',
168
+ arguments: '{"param": "value"}'
169
+ }
170
+ };
171
+
172
+ // Mock the tool callback
173
+ let capturedToolCalls = null;
174
+ plugin.pathwayToolCallback = (args, message, resolver) => {
175
+ capturedToolCalls = message.tool_calls;
176
+ };
177
+
178
+ // Mock requestProgress and pathwayResolver
179
+ const requestProgress = { progress: 0, started: true };
180
+ const pathwayResolver = { args: {} };
181
+
182
+ // Mock requestState
183
+ requestState[plugin.requestId] = { pathwayResolver };
184
+
185
+ // Simulate a tool_calls finish reason
186
+ const event = {
187
+ data: JSON.stringify({
188
+ choices: [{
189
+ finish_reason: 'tool_calls'
190
+ }]
191
+ })
192
+ };
193
+
194
+ // Process the stream event
195
+ plugin.processStreamEvent(event, requestProgress);
196
+
197
+ // Verify that only valid tool calls were passed
198
+ t.truthy(capturedToolCalls, 'Tool callback should have been called');
199
+ t.is(capturedToolCalls.length, 2, 'Should have filtered out invalid elements');
200
+ t.is(capturedToolCalls[0].function.name, 'valid_tool', 'First valid tool call should be preserved');
201
+ t.is(capturedToolCalls[1].function.name, 'another_valid_tool', 'Second valid tool call should be preserved');
202
+
203
+ // Clean up
204
+ delete requestState[plugin.requestId];
205
+ });
206
+
207
+ test('Gemini15VisionPlugin - filters undefined tool calls from buffer', async t => {
208
+ const resolver = createResolverWithPlugin(Gemini15VisionPlugin);
209
+ const plugin = resolver.modelExecutor.plugin;
210
+
211
+ // Simulate buffer with undefined elements (though less likely with push method)
212
+ plugin.toolCallsBuffer = [
213
+ undefined,
214
+ {
215
+ id: 'call_1_1234567890',
216
+ type: 'function',
217
+ function: {
218
+ name: 'test_tool',
219
+ arguments: '{"param": "value"}'
220
+ }
221
+ }
222
+ ];
223
+
224
+ // Mock the tool callback
225
+ let capturedToolCalls = null;
226
+ plugin.pathwayToolCallback = (args, message, resolver) => {
227
+ capturedToolCalls = message.tool_calls;
228
+ };
229
+
230
+ // Mock requestProgress and pathwayResolver
231
+ const requestProgress = { progress: 0, started: true };
232
+ const pathwayResolver = { args: {} };
233
+
234
+ // Mock requestState
235
+ requestState[plugin.requestId] = { pathwayResolver };
236
+
237
+ // Simulate a tool_calls finish reason
238
+ const eventData = {
239
+ candidates: [{
240
+ finishReason: 'STOP'
241
+ }]
242
+ };
243
+
244
+ // Set hadToolCalls to true to trigger tool_calls finish reason
245
+ plugin.hadToolCalls = true;
246
+
247
+ // Process the stream event
248
+ plugin.processStreamEvent({ data: JSON.stringify(eventData) }, requestProgress);
249
+
250
+ // Verify that undefined elements were filtered out
251
+ t.truthy(capturedToolCalls, 'Tool callback should have been called');
252
+ t.is(capturedToolCalls.length, 1, 'Should have filtered out undefined elements');
253
+ t.is(capturedToolCalls[0].function.name, 'test_tool', 'Valid tool call should be preserved');
254
+
255
+ // Clean up
256
+ delete requestState[plugin.requestId];
257
+ });
258
+
259
+ test('Gemini15VisionPlugin - handles empty buffer gracefully', async t => {
260
+ const resolver = createResolverWithPlugin(Gemini15VisionPlugin);
261
+ const plugin = resolver.modelExecutor.plugin;
262
+
263
+ // Empty buffer
264
+ plugin.toolCallsBuffer = [];
265
+
266
+ // Mock the tool callback
267
+ let callbackCalled = false;
268
+ plugin.pathwayToolCallback = () => {
269
+ callbackCalled = true;
270
+ };
271
+
272
+ // Mock requestProgress and pathwayResolver
273
+ const requestProgress = { progress: 0, started: true };
274
+ const pathwayResolver = { args: {} };
275
+
276
+ // Mock requestState
277
+ requestState[plugin.requestId] = { pathwayResolver };
278
+
279
+ // Simulate a tool_calls finish reason
280
+ const eventData = {
281
+ candidates: [{
282
+ finishReason: 'STOP'
283
+ }]
284
+ };
285
+
286
+ // Set hadToolCalls to true
287
+ plugin.hadToolCalls = true;
288
+
289
+ // Process the stream event
290
+ plugin.processStreamEvent({ data: JSON.stringify(eventData) }, requestProgress);
291
+
292
+ // Verify that callback was not called with empty buffer
293
+ t.falsy(callbackCalled, 'Tool callback should not be called with empty buffer');
294
+
295
+ // Clean up
296
+ delete requestState[plugin.requestId];
297
+ });
@@ -1,6 +1,6 @@
1
1
  import test from 'ava';
2
2
  import sinon from 'sinon';
3
- import { PathwayResolver } from '../server/pathwayResolver.js';
3
+ import { PathwayResolver } from '../../../server/pathwayResolver.js';
4
4
 
5
5
  // Mock configuration
6
6
  const mockModel = {
@@ -118,7 +118,7 @@ test('resolver uses correct model', (t) => {
118
118
 
119
119
  test('pathway has fallback pathway parameter', async (t) => {
120
120
  // Import the actual pathway to test the new parameter
121
- const pathway = await import('../pathways/translate_apptek.js');
121
+ const pathway = await import('../../../pathways/translate_apptek.js');
122
122
 
123
123
  t.truthy(pathway.default.inputParameters.fallbackPathway);
124
124
  t.is(pathway.default.inputParameters.fallbackPathway, 'translate_groq');
@@ -126,7 +126,7 @@ test('pathway has fallback pathway parameter', async (t) => {
126
126
 
127
127
  test('pathway has executePathway function', async (t) => {
128
128
  // Import the actual pathway to test the executePathway function
129
- const pathway = await import('../pathways/translate_apptek.js');
129
+ const pathway = await import('../../../pathways/translate_apptek.js');
130
130
 
131
131
  t.truthy(pathway.default.executePathway);
132
132
  t.is(typeof pathway.default.executePathway, 'function');
@@ -1,30 +1,14 @@
1
1
  import test from 'ava';
2
- import serverFactory from '../index.js';
3
- import { PathwayResolver } from '../server/pathwayResolver.js';
4
- import OpenAIChatPlugin from '../server/plugins/openAiChatPlugin.js';
5
- import GeminiChatPlugin from '../server/plugins/geminiChatPlugin.js';
6
- import Gemini15ChatPlugin from '../server/plugins/gemini15ChatPlugin.js';
7
- import Claude3VertexPlugin from '../server/plugins/claude3VertexPlugin.js';
8
- import { config } from '../config.js';
2
+ import { PathwayResolver } from '../../../server/pathwayResolver.js';
3
+ import OpenAIChatPlugin from '../../../server/plugins/openAiChatPlugin.js';
4
+ import GeminiChatPlugin from '../../../server/plugins/geminiChatPlugin.js';
5
+ import Gemini15ChatPlugin from '../../../server/plugins/gemini15ChatPlugin.js';
6
+ import Claude3VertexPlugin from '../../../server/plugins/claude3VertexPlugin.js';
7
+ import { config } from '../../../config.js';
9
8
 
10
9
  let testServer;
11
10
 
12
- test.before(async () => {
13
- process.env.CORTEX_ENABLE_REST = 'true';
14
- const { server, startServer } = await serverFactory();
15
- startServer && await startServer();
16
- testServer = server;
17
- });
18
-
19
- test.after.always('cleanup', async () => {
20
- if (testServer) {
21
- await testServer.stop();
22
- }
23
- });
24
-
25
- // Helper function to create a PathwayResolver with a specific plugin
26
11
  function createResolverWithPlugin(pluginClass, modelName = 'test-model') {
27
- // Map plugin classes to their corresponding model types
28
12
  const pluginToModelType = {
29
13
  OpenAIChatPlugin: 'OPENAI-VISION',
30
14
  GeminiChatPlugin: 'GEMINI-VISION',
@@ -59,12 +43,10 @@ function createResolverWithPlugin(pluginClass, modelName = 'test-model') {
59
43
  return resolver;
60
44
  }
61
45
 
62
- // Test OpenAI Chat Plugin Streaming
63
46
  test('OpenAI Chat Plugin - processStreamEvent handles content chunks correctly', async t => {
64
47
  const resolver = createResolverWithPlugin(OpenAIChatPlugin);
65
48
  const plugin = resolver.modelExecutor.plugin;
66
49
 
67
- // Test regular content chunk
68
50
  const contentEvent = {
69
51
  data: JSON.stringify({
70
52
  id: 'test-id',
@@ -79,7 +61,6 @@ test('OpenAI Chat Plugin - processStreamEvent handles content chunks correctly',
79
61
  t.is(progress.data, contentEvent.data);
80
62
  t.falsy(progress.progress);
81
63
 
82
- // Test stream end
83
64
  const endEvent = {
84
65
  data: JSON.stringify({
85
66
  id: 'test-id',
@@ -94,39 +75,32 @@ test('OpenAI Chat Plugin - processStreamEvent handles content chunks correctly',
94
75
  t.is(progress.progress, 1);
95
76
  });
96
77
 
97
- // Test Gemini Chat Plugin Streaming
98
78
  test('Gemini Chat Plugin - processStreamEvent handles content chunks correctly', async t => {
99
79
  const resolver = createResolverWithPlugin(GeminiChatPlugin);
100
80
  const plugin = resolver.modelExecutor.plugin;
101
81
 
102
- // Test regular content chunk
103
82
  const contentEvent = {
104
83
  data: JSON.stringify({
105
84
  candidates: [{
106
- content: {
107
- parts: [{ text: 'test content' }]
108
- },
85
+ content: { parts: [{ text: 'test content' }] },
109
86
  finishReason: null
110
87
  }]
111
88
  })
112
89
  };
113
90
 
114
91
  let progress = plugin.processStreamEvent(contentEvent, {});
115
- t.truthy(progress.data, 'Should have data');
92
+ t.truthy(progress.data);
116
93
  const parsedData = JSON.parse(progress.data);
117
- t.truthy(parsedData.candidates, 'Should have candidates array');
118
- t.truthy(parsedData.candidates[0].content, 'Should have content object');
119
- t.truthy(parsedData.candidates[0].content.parts, 'Should have parts array');
120
- t.is(parsedData.candidates[0].content.parts[0].text, 'test content', 'Content should match');
94
+ t.truthy(parsedData.candidates);
95
+ t.truthy(parsedData.candidates[0].content);
96
+ t.truthy(parsedData.candidates[0].content.parts);
97
+ t.is(parsedData.candidates[0].content.parts[0].text, 'test content');
121
98
  t.falsy(progress.progress);
122
99
 
123
- // Test stream end with STOP
124
100
  const endEvent = {
125
101
  data: JSON.stringify({
126
102
  candidates: [{
127
- content: {
128
- parts: [{ text: '' }]
129
- },
103
+ content: { parts: [{ text: '' }] },
130
104
  finishReason: 'STOP'
131
105
  }]
132
106
  })
@@ -136,17 +110,13 @@ test('Gemini Chat Plugin - processStreamEvent handles content chunks correctly',
136
110
  t.is(progress.progress, 1);
137
111
  });
138
112
 
139
- // Test Gemini 15 Chat Plugin Streaming
140
113
  test('Gemini 15 Chat Plugin - processStreamEvent handles safety blocks', async t => {
141
114
  const resolver = createResolverWithPlugin(Gemini15ChatPlugin);
142
115
  const plugin = resolver.modelExecutor.plugin;
143
116
 
144
- // Test safety block
145
117
  const safetyEvent = {
146
118
  data: JSON.stringify({
147
- candidates: [{
148
- safetyRatings: [{ blocked: true }]
149
- }]
119
+ candidates: [{ safetyRatings: [{ blocked: true }] }]
150
120
  })
151
121
  };
152
122
 
@@ -155,12 +125,10 @@ test('Gemini 15 Chat Plugin - processStreamEvent handles safety blocks', async t
155
125
  t.is(progress.progress, 1);
156
126
  });
157
127
 
158
- // Test Claude 3 Vertex Plugin Streaming
159
128
  test('Claude 3 Vertex Plugin - processStreamEvent handles message types', async t => {
160
129
  const resolver = createResolverWithPlugin(Claude3VertexPlugin);
161
130
  const plugin = resolver.modelExecutor.plugin;
162
131
 
163
- // Test message start
164
132
  const startEvent = {
165
133
  data: JSON.stringify({
166
134
  type: 'message_start',
@@ -171,27 +139,20 @@ test('Claude 3 Vertex Plugin - processStreamEvent handles message types', async
171
139
  let progress = plugin.processStreamEvent(startEvent, {});
172
140
  t.true(JSON.parse(progress.data).choices[0].delta.role === 'assistant');
173
141
 
174
- // Test content block
175
142
  const contentEvent = {
176
143
  data: JSON.stringify({
177
144
  type: 'content_block_delta',
178
- delta: {
179
- type: 'text_delta',
180
- text: 'test content'
181
- }
145
+ delta: { type: 'text_delta', text: 'test content' }
182
146
  })
183
147
  };
184
148
 
185
149
  progress = plugin.processStreamEvent(contentEvent, {});
186
150
  t.true(JSON.parse(progress.data).choices[0].delta.content === 'test content');
187
151
 
188
- // Test message stop
189
- const stopEvent = {
190
- data: JSON.stringify({
191
- type: 'message_stop'
192
- })
193
- };
152
+ const stopEvent = { data: JSON.stringify({ type: 'message_stop' }) };
194
153
 
195
154
  progress = plugin.processStreamEvent(stopEvent, {});
196
155
  t.is(progress.progress, 1);
197
- });
156
+ });
157
+
158
+
@@ -1 +0,0 @@
1
- test preview gif content
@@ -1 +0,0 @@
1
- test mogrt content
@@ -1 +0,0 @@
1
- test preview mp4 content
@@ -1,19 +0,0 @@
1
- // sys_openai_chat_gpt4.js
2
- // override handler for gpt-4
3
-
4
- import { Prompt } from '../../../server/prompt.js';
5
-
6
- export default {
7
- prompt:
8
- [
9
- new Prompt({ messages: [
10
- "{{messages}}",
11
- ]}),
12
- ],
13
- inputParameters: {
14
- messages: [],
15
- },
16
- model: 'oai-gpt4',
17
- useInputChunking: false,
18
- emulateOpenAIChatModel: 'gpt-4',
19
- }