@aj-archipelago/cortex 1.3.62 → 1.3.63

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 (211) 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/sys_memory_lookup_required.js +1 -0
  91. package/pathways/system/entity/memory/sys_memory_required.js +1 -0
  92. package/pathways/system/entity/memory/sys_search_memory.js +1 -0
  93. package/pathways/system/entity/sys_entity_agent.js +56 -4
  94. package/pathways/system/entity/sys_generator_quick.js +1 -0
  95. package/pathways/system/entity/tools/sys_tool_bing_search_afagent.js +26 -0
  96. package/pathways/system/entity/tools/sys_tool_google_search.js +141 -0
  97. package/pathways/system/entity/tools/sys_tool_grok_x_search.js +237 -0
  98. package/pathways/system/entity/tools/sys_tool_image.js +1 -1
  99. package/pathways/system/rest_streaming/sys_claude_37_sonnet.js +21 -0
  100. package/pathways/system/rest_streaming/sys_claude_41_opus.js +21 -0
  101. package/pathways/system/rest_streaming/sys_claude_4_sonnet.js +21 -0
  102. package/pathways/system/rest_streaming/sys_google_gemini_25_flash.js +25 -0
  103. package/pathways/system/rest_streaming/{sys_google_gemini_chat.js → sys_google_gemini_25_pro.js} +6 -4
  104. package/pathways/system/rest_streaming/sys_grok_4.js +23 -0
  105. package/pathways/system/rest_streaming/sys_grok_4_fast_non_reasoning.js +23 -0
  106. package/pathways/system/rest_streaming/sys_grok_4_fast_reasoning.js +23 -0
  107. package/pathways/system/rest_streaming/sys_openai_chat.js +3 -0
  108. package/pathways/system/rest_streaming/sys_openai_chat_gpt41.js +22 -0
  109. package/pathways/system/rest_streaming/sys_openai_chat_gpt41_mini.js +21 -0
  110. package/pathways/system/rest_streaming/sys_openai_chat_gpt41_nano.js +21 -0
  111. package/pathways/system/rest_streaming/{sys_claude_35_sonnet.js → sys_openai_chat_gpt4_omni.js} +6 -4
  112. package/pathways/system/rest_streaming/sys_openai_chat_gpt4_omni_mini.js +21 -0
  113. package/pathways/system/rest_streaming/{sys_claude_3_haiku.js → sys_openai_chat_gpt5.js} +7 -5
  114. package/pathways/system/rest_streaming/sys_openai_chat_gpt5_chat.js +21 -0
  115. package/pathways/system/rest_streaming/sys_openai_chat_gpt5_mini.js +21 -0
  116. package/pathways/system/rest_streaming/sys_openai_chat_gpt5_nano.js +21 -0
  117. package/pathways/system/rest_streaming/{sys_openai_chat_o1.js → sys_openai_chat_o3.js} +6 -3
  118. package/pathways/system/rest_streaming/sys_openai_chat_o3_mini.js +3 -0
  119. package/pathways/system/workspaces/run_workspace_prompt.js +99 -0
  120. package/pathways/vision.js +1 -1
  121. package/server/graphql.js +1 -1
  122. package/server/modelExecutor.js +8 -0
  123. package/server/pathwayResolver.js +166 -16
  124. package/server/pathwayResponseParser.js +16 -8
  125. package/server/plugins/azureFoundryAgentsPlugin.js +1 -1
  126. package/server/plugins/claude3VertexPlugin.js +193 -45
  127. package/server/plugins/gemini15ChatPlugin.js +21 -0
  128. package/server/plugins/gemini15VisionPlugin.js +360 -0
  129. package/server/plugins/googleCsePlugin.js +94 -0
  130. package/server/plugins/grokVisionPlugin.js +365 -0
  131. package/server/plugins/modelPlugin.js +3 -1
  132. package/server/plugins/openAiChatPlugin.js +106 -13
  133. package/server/plugins/openAiVisionPlugin.js +42 -30
  134. package/server/resolver.js +28 -4
  135. package/server/rest.js +270 -53
  136. package/server/typeDef.js +1 -0
  137. package/tests/{mocks.js → helpers/mocks.js} +5 -2
  138. package/tests/{server.js → helpers/server.js} +2 -2
  139. package/tests/helpers/sseAssert.js +23 -0
  140. package/tests/helpers/sseClient.js +73 -0
  141. package/tests/helpers/subscriptionAssert.js +11 -0
  142. package/tests/helpers/subscriptions.js +113 -0
  143. package/tests/{sublong.srt → integration/features/translate/sublong.srt} +4543 -4543
  144. package/tests/integration/features/translate/translate_chunking_stream.test.js +100 -0
  145. package/tests/{translate_srt.test.js → integration/features/translate/translate_srt.test.js} +2 -2
  146. package/tests/integration/graphql/async/stream/agentic.test.js +477 -0
  147. package/tests/integration/graphql/async/stream/subscription_streaming.test.js +62 -0
  148. package/tests/integration/graphql/async/stream/sys_entity_start_streaming.test.js +71 -0
  149. package/tests/integration/graphql/async/stream/vendors/claude_streaming.test.js +56 -0
  150. package/tests/integration/graphql/async/stream/vendors/gemini_streaming.test.js +66 -0
  151. package/tests/integration/graphql/async/stream/vendors/grok_streaming.test.js +56 -0
  152. package/tests/integration/graphql/async/stream/vendors/openai_streaming.test.js +72 -0
  153. package/tests/integration/graphql/features/google/sysToolGoogleSearch.test.js +96 -0
  154. package/tests/integration/graphql/features/grok/grok.test.js +688 -0
  155. package/tests/integration/graphql/features/grok/grok_x_search_tool.test.js +354 -0
  156. package/tests/{main.test.js → integration/graphql/features/main.test.js} +1 -1
  157. package/tests/{call_tools.test.js → integration/graphql/features/tools/call_tools.test.js} +2 -2
  158. package/tests/{vision.test.js → integration/graphql/features/vision/vision.test.js} +1 -1
  159. package/tests/integration/graphql/subscriptions/connection.test.js +26 -0
  160. package/tests/{openai_api.test.js → integration/rest/oai/openai_api.test.js} +63 -238
  161. package/tests/integration/rest/oai/tool_calling_api.test.js +343 -0
  162. package/tests/integration/rest/oai/tool_calling_streaming.test.js +85 -0
  163. package/tests/integration/rest/vendors/claude_streaming.test.js +47 -0
  164. package/tests/integration/rest/vendors/claude_tool_calling_streaming.test.js +75 -0
  165. package/tests/integration/rest/vendors/gemini_streaming.test.js +47 -0
  166. package/tests/integration/rest/vendors/gemini_tool_calling_streaming.test.js +75 -0
  167. package/tests/integration/rest/vendors/grok_streaming.test.js +55 -0
  168. package/tests/integration/rest/vendors/grok_tool_calling_streaming.test.js +75 -0
  169. package/tests/{azureAuthTokenHelper.test.js → unit/core/azureAuthTokenHelper.test.js} +1 -1
  170. package/tests/{chunkfunction.test.js → unit/core/chunkfunction.test.js} +2 -2
  171. package/tests/{config.test.js → unit/core/config.test.js} +3 -3
  172. package/tests/{encodeCache.test.js → unit/core/encodeCache.test.js} +1 -1
  173. package/tests/{fastLruCache.test.js → unit/core/fastLruCache.test.js} +1 -1
  174. package/tests/{handleBars.test.js → unit/core/handleBars.test.js} +1 -1
  175. package/tests/{memoryfunction.test.js → unit/core/memoryfunction.test.js} +2 -2
  176. package/tests/unit/core/mergeResolver.test.js +952 -0
  177. package/tests/{parser.test.js → unit/core/parser.test.js} +3 -3
  178. package/tests/unit/core/pathwayResolver.test.js +187 -0
  179. package/tests/{requestMonitor.test.js → unit/core/requestMonitor.test.js} +1 -1
  180. package/tests/{requestMonitorDurationEstimator.test.js → unit/core/requestMonitorDurationEstimator.test.js} +1 -1
  181. package/tests/{truncateMessages.test.js → unit/core/truncateMessages.test.js} +3 -3
  182. package/tests/{util.test.js → unit/core/util.test.js} +1 -1
  183. package/tests/{apptekTranslatePlugin.test.js → unit/plugins/apptekTranslatePlugin.test.js} +3 -3
  184. package/tests/{azureFoundryAgents.test.js → unit/plugins/azureFoundryAgents.test.js} +136 -1
  185. package/tests/{claude3VertexPlugin.test.js → unit/plugins/claude3VertexPlugin.test.js} +32 -10
  186. package/tests/{claude3VertexToolConversion.test.js → unit/plugins/claude3VertexToolConversion.test.js} +3 -3
  187. package/tests/unit/plugins/googleCsePlugin.test.js +111 -0
  188. package/tests/unit/plugins/grokVisionPlugin.test.js +1392 -0
  189. package/tests/{modelPlugin.test.js → unit/plugins/modelPlugin.test.js} +3 -3
  190. package/tests/{multimodal_conversion.test.js → unit/plugins/multimodal_conversion.test.js} +4 -4
  191. package/tests/{openAiChatPlugin.test.js → unit/plugins/openAiChatPlugin.test.js} +13 -4
  192. package/tests/{openAiToolPlugin.test.js → unit/plugins/openAiToolPlugin.test.js} +35 -27
  193. package/tests/{tokenHandlingTests.test.js → unit/plugins/tokenHandlingTests.test.js} +5 -5
  194. package/tests/{translate_apptek.test.js → unit/plugins/translate_apptek.test.js} +3 -3
  195. package/tests/{streaming.test.js → unit/plugins.streaming/plugin_stream_events.test.js} +19 -58
  196. package/helper-apps/mogrt-handler/tests/test-files/test.gif +0 -1
  197. package/helper-apps/mogrt-handler/tests/test-files/test.mogrt +0 -1
  198. package/helper-apps/mogrt-handler/tests/test-files/test.mp4 +0 -1
  199. package/pathways/system/rest_streaming/sys_openai_chat_gpt4.js +0 -19
  200. package/pathways/system/rest_streaming/sys_openai_chat_gpt4_32.js +0 -19
  201. package/pathways/system/rest_streaming/sys_openai_chat_gpt4_turbo.js +0 -19
  202. package/pathways/system/workspaces/run_claude35_sonnet.js +0 -21
  203. package/pathways/system/workspaces/run_claude3_haiku.js +0 -20
  204. package/pathways/system/workspaces/run_gpt35turbo.js +0 -20
  205. package/pathways/system/workspaces/run_gpt4.js +0 -20
  206. package/pathways/system/workspaces/run_gpt4_32.js +0 -20
  207. package/tests/agentic.test.js +0 -256
  208. package/tests/pathwayResolver.test.js +0 -78
  209. package/tests/subscription.test.js +0 -387
  210. /package/tests/{subchunk.srt → integration/features/translate/subchunk.srt} +0 -0
  211. /package/tests/{subhorizontal.srt → integration/features/translate/subhorizontal.srt} +0 -0
@@ -2,8 +2,8 @@
2
2
 
3
3
  import test from 'ava';
4
4
  import got from 'got';
5
- import axios from 'axios';
6
- import serverFactory from '../index.js';
5
+ import serverFactory from '../../../../index.js';
6
+ import { connectToSSEEndpoint } from '../../../helpers/sseClient.js';
7
7
 
8
8
  const API_BASE = `http://localhost:${process.env.CORTEX_PORT}/v1`;
9
9
 
@@ -90,157 +90,45 @@ test('POST /chat/completions with multimodal content', async (t) => {
90
90
  t.truthy(response.body.choices[0].message.content);
91
91
  });
92
92
 
93
- async function connectToSSEEndpoint(url, endpoint, payload, t, customAssertions) {
94
- return new Promise(async (resolve, reject) => {
95
- try {
96
- const instance = axios.create({
97
- baseURL: url,
98
- responseType: 'stream',
99
- });
100
-
101
- const response = await instance.post(endpoint, payload);
102
- const responseData = response.data;
103
-
104
- const incomingMessage = Array.isArray(responseData) && responseData.length > 0 ? responseData[0] : responseData;
105
-
106
- let eventCount = 0;
107
-
108
- incomingMessage.on('data', data => {
109
- const events = data.toString().split('\n');
110
-
111
- events.forEach(event => {
112
- eventCount++;
113
-
114
- if (event.trim() === '') return;
93
+ test('POST SSE: /v1/completions should send a series of events and a [DONE] event', async (t) => {
94
+ const payload = {
95
+ model: 'gpt-3.5-turbo',
96
+ prompt: 'Word to your motha!',
97
+ stream: true,
98
+ };
115
99
 
116
- if (event.trim() === 'data: [DONE]') {
117
- t.truthy(eventCount > 1);
118
- resolve();
119
- return;
120
- }
121
-
122
- const message = event.replace(/^data: /, '');
123
- const messageJson = JSON.parse(message);
124
-
125
- customAssertions(t, messageJson);
126
- });
127
- });
128
-
129
- } catch (error) {
130
- console.error('Error connecting to SSE endpoint:', error);
131
- reject(error);
132
- }
133
- });
134
- }
100
+ const url = `http://localhost:${process.env.CORTEX_PORT}/v1`;
135
101
 
136
- test('POST SSE: /v1/completions should send a series of events and a [DONE] event', async (t) => {
137
- const payload = {
138
- model: 'gpt-3.5-turbo',
139
- prompt: 'Word to your motha!',
140
- stream: true,
141
- };
142
-
143
- const url = `http://localhost:${process.env.CORTEX_PORT}/v1`;
144
-
145
- const completionsAssertions = (t, messageJson) => {
146
- t.truthy(messageJson.id);
147
- t.is(messageJson.object, 'text_completion');
148
- t.truthy(messageJson.choices[0].finish_reason === null || messageJson.choices[0].finish_reason === 'stop');
149
- };
150
-
151
- await connectToSSEEndpoint(url, '/completions', payload, t, completionsAssertions);
102
+ await connectToSSEEndpoint(url, '/completions', payload, (messageJson) => {
103
+ t.truthy(messageJson.id);
104
+ t.is(messageJson.object, 'text_completion');
105
+ t.truthy(messageJson.choices[0].finish_reason === null || messageJson.choices[0].finish_reason === 'stop');
106
+ });
152
107
  });
153
108
 
154
109
  test('POST SSE: /v1/chat/completions should send a series of events and a [DONE] event', async (t) => {
155
- const payload = {
156
- model: 'gpt-4o',
157
- messages: [
158
- {
159
- role: 'user',
160
- content: 'Hello!',
161
- },
162
- ],
163
- stream: true,
164
- };
165
-
166
- const url = `http://localhost:${process.env.CORTEX_PORT}/v1`;
167
-
168
- const chatCompletionsAssertions = (t, messageJson) => {
169
- t.truthy(messageJson.id);
170
- t.is(messageJson.object, 'chat.completion.chunk');
171
- t.truthy(messageJson.choices[0].delta);
172
- t.truthy(messageJson.choices[0].finish_reason === null || messageJson.choices[0].finish_reason === 'stop');
173
- };
174
-
175
- await connectToSSEEndpoint(url, '/chat/completions', payload, t, chatCompletionsAssertions);
176
- });
110
+ const payload = {
111
+ model: 'gpt-4o',
112
+ messages: [
113
+ {
114
+ role: 'user',
115
+ content: 'Hello!',
116
+ },
117
+ ],
118
+ stream: true,
119
+ };
177
120
 
178
- test('POST SSE: /v1/chat/completions with multimodal content should send a series of events and a [DONE] event', async (t) => {
179
- const payload = {
180
- model: 'gpt-4o',
181
- messages: [{
182
- role: 'user',
183
- content: [
184
- {
185
- type: 'text',
186
- text: 'What do you see in this image?'
187
- },
188
- {
189
- type: 'image',
190
- image_url: {
191
- url: 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEASABIAAD/4gHYSUNDX1BST0ZJTEUAAQEAAAHIAAAAAAQwAABtbnRyUkdCIFhZWiAH4AABAAEAAAAAAABhY3NwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA9tYAAQAAAADTLQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlkZXNjAAAA8AAAACRyWFlaAAABFAAAABRnWFlaAAABKAAAABRiWFlaAAABPAAAABR3dHB0AAABUAAAABRyVFJDAAABZAAAAChnVFJDAAABZAAAAChiVFJDAAABZAAAAChjcHJ0AAABjAAAADxtbHVjAAAAAAAAAAEAAAAMZW5VUwAAAAgAAAAcAHMAUgBHAEJYWVogAAAAAAAAb6IAADj1AAADkFhZWiAAAAAAAABimQAAt4UAABjaWFlaIAAAAAAAACSgAAAPhAAAts9YWVogAAAAAAAA9tYAAQAAAADTLXBhcmEAAAAAAAQAAAACZmYAAPKnAAANWQAAE9AAAApbAAAAAAAAAABtbHVjAAAAAAAAAAEAAAAMZW5VUwAAACAAAAAcAEcAbwBvAGcAbABlACAASQBuAGMALgAgADIAMAAxADb/2wBDABQODxIPDRQSEBIXFRQdHx4eHRoaHSQrJyEwPENBMDQ4NDQ0QUJCSkNLS0tNSkpQUFFQR1BTYWNgY2FQYWFQYWj/2wBDARUXFyAeIBohHh4oIiE2LCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wAARCAAIAAoDASIAAhEBAxEB/8QAFQABAQAAAAAAAAAAAAAAAAAAAAb/xAAUEAEAAAAAAAAAAAAAAAAAAAAA/8QAFQEBAQAAAAAAAAAAAAAAAAAAAAX/xAAUEQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIRAxEAPwCdABmX/9k='
192
- }
193
- }
194
- ]
195
- }],
196
- stream: true,
197
- };
198
-
199
- const url = `http://localhost:${process.env.CORTEX_PORT}/v1`;
200
-
201
- const multimodalChatCompletionsAssertions = (t, messageJson) => {
202
- t.truthy(messageJson.id);
203
- t.is(messageJson.object, 'chat.completion.chunk');
204
- t.truthy(messageJson.choices[0].delta);
205
- if (messageJson.choices[0].finish_reason === 'stop') {
206
- t.truthy(messageJson.choices[0].delta);
207
- }
208
- };
209
-
210
- await connectToSSEEndpoint(url, '/chat/completions', payload, t, multimodalChatCompletionsAssertions);
211
- });
121
+ const url = `http://localhost:${process.env.CORTEX_PORT}/v1`;
212
122
 
213
- test('POST /chat/completions should handle multimodal content for non-multimodal model', async (t) => {
214
- const response = await got.post(`${API_BASE}/chat/completions`, {
215
- json: {
216
- model: 'gpt-4o',
217
- messages: [{
218
- role: 'user',
219
- content: [
220
- {
221
- type: 'text',
222
- text: 'What do you see in this image?'
223
- },
224
- {
225
- type: 'image',
226
- image_url: {
227
- url: 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEASABIAAD...'
228
- }
229
- }
230
- ]
231
- }],
232
- stream: false,
233
- },
234
- responseType: 'json',
123
+ await connectToSSEEndpoint(url, '/chat/completions', payload, (messageJson) => {
124
+ t.truthy(messageJson.id);
125
+ t.is(messageJson.object, 'chat.completion.chunk');
126
+ t.truthy(messageJson.choices[0].delta);
127
+ t.truthy(messageJson.choices[0].finish_reason === null || messageJson.choices[0].finish_reason === 'stop');
235
128
  });
236
-
237
- t.is(response.statusCode, 200);
238
- t.is(response.body.object, 'chat.completion');
239
- t.true(Array.isArray(response.body.choices));
240
- t.truthy(response.body.choices[0].message.content);
241
129
  });
242
130
 
243
- test('POST SSE: /v1/chat/completions should handle streaming multimodal content for non-multimodal model', async (t) => {
131
+ test('POST SSE: /v1/chat/completions with multimodal content should send a series of events and a [DONE] event', async (t) => {
244
132
  const payload = {
245
133
  model: 'gpt-4o',
246
134
  messages: [{
@@ -253,7 +141,7 @@ test('POST SSE: /v1/chat/completions should handle streaming multimodal content
253
141
  {
254
142
  type: 'image',
255
143
  image_url: {
256
- url: 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEASABIAAD...'
144
+ url: 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEASABIAAD/4gHYSUNDX1BST0ZJTEUAAQEAAAHIAAAAAAQwAABtbnRyUkdCIFhZWiAH4AABAAEAAAAAAABhY3NwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA9tYAAQAAAADTLQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlkZXNjAAAA8AAAACRyWFlaAAABFAAAABRnWFlaAAABKAAAABRiWFlaAAABPAAAABR3dHB0AAABUAAAABRyVFJDAAABZAAAAChnVFJDAAABZAAAAChiVFJDAAABZAAAAChjcHJ0AAABjAAAADxtbHVjAAAAAAAAAAEAAAAMZW5VUwAAAAgAAAAcAHMAUgBHAEJYWVogAAAAAAAAb6IAADj1AAADkFhZWiAAAAAAAABimQAAt4UAABjaWFlaIAAAAAAAACSgAAAPhAAAts9YWVogAAAAAAAA9tYAAQAAAADTLXBhcmEAAAAAAAQAAAACZmYAAPKnAAANWQAAE9AAAApbAAAAAAAAAABtbHVjAAAAAAAAAAEAAAAMZW5VUwAAACAAAAAcAEcAbwBvAGcAbABlACAASQBuAGMALgAgADIAMAAxADb/2wBDABQODxIPDRQSEBIXFRQdHx4eHRoaHSQrJyEwPENBMDQ4NDQ0QUJCSkNLS0tNSkpQUFFQR1BTYWNgY2FQYWFQYWj/2wBDARUXFyAeIBohHh4oIiE2LCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wAARCAAIAAoDASIAAhEBAxEB/8QAFQABAQAAAAAAAAAAAAAAAAAAAAb/xAAUEAEAAAAAAAAAAAAAAAAAAAAA/8QAFQEBAQAAAAAAAAAAAAAAAAAAAAX/xAAUEQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIRAxEAPwCdABmX/9k='
257
145
  }
258
146
  }
259
147
  ]
@@ -261,23 +149,17 @@ test('POST SSE: /v1/chat/completions should handle streaming multimodal content
261
149
  stream: true,
262
150
  };
263
151
 
264
- const streamingAssertions = (t, messageJson) => {
152
+ const url = `http://localhost:${process.env.CORTEX_PORT}/v1`;
153
+
154
+ await connectToSSEEndpoint(url, '/chat/completions', payload, (messageJson) => {
265
155
  t.truthy(messageJson.id);
266
156
  t.is(messageJson.object, 'chat.completion.chunk');
267
157
  t.truthy(messageJson.choices[0].delta);
268
158
  if (messageJson.choices[0].finish_reason === 'stop') {
269
159
  t.truthy(messageJson.choices[0].delta);
270
160
  }
271
- };
272
-
273
- await connectToSSEEndpoint(
274
- `http://localhost:${process.env.CORTEX_PORT}/v1`,
275
- '/chat/completions',
276
- payload,
277
- t,
278
- streamingAssertions
279
- );
280
- });
161
+ });
162
+ });
281
163
 
282
164
  test('POST /chat/completions should handle malformed multimodal content', async (t) => {
283
165
  const response = await got.post(`${API_BASE}/chat/completions`, {
@@ -340,8 +222,8 @@ test('POST /chat/completions should handle invalid image data', async (t) => {
340
222
  test('POST /completions should handle model parameters', async (t) => {
341
223
  const response = await got.post(`${API_BASE}/completions`, {
342
224
  json: {
343
- model: 'gpt-3.5-turbo',
344
- prompt: 'Say this is a test',
225
+ model: 'gpt-4o',
226
+ prompt: 'Repeat after me: Say this is a test',
345
227
  temperature: 0.7,
346
228
  max_tokens: 100,
347
229
  top_p: 1,
@@ -358,46 +240,6 @@ test('POST /completions should handle model parameters', async (t) => {
358
240
  t.truthy(response.body.choices[0].text);
359
241
  });
360
242
 
361
- test('POST /chat/completions should handle function calling', async (t) => {
362
- const response = await got.post(`${API_BASE}/chat/completions`, {
363
- json: {
364
- model: 'gpt-4o',
365
- messages: [{ role: 'user', content: 'What is the weather in Boston?' }],
366
- functions: [{
367
- name: 'get_weather',
368
- description: 'Get the current weather in a given location',
369
- parameters: {
370
- type: 'object',
371
- properties: {
372
- location: {
373
- type: 'string',
374
- description: 'The city and state, e.g. San Francisco, CA'
375
- },
376
- unit: {
377
- type: 'string',
378
- enum: ['celsius', 'fahrenheit']
379
- }
380
- },
381
- required: ['location']
382
- }
383
- }],
384
- stream: false,
385
- },
386
- responseType: 'json',
387
- });
388
-
389
- t.is(response.statusCode, 200);
390
- t.is(response.body.object, 'chat.completion');
391
- t.true(Array.isArray(response.body.choices));
392
- const choice = response.body.choices[0];
393
- t.true(['function_call', 'stop'].includes(choice.finish_reason));
394
- if (choice.finish_reason === 'function_call') {
395
- t.truthy(choice.message.function_call);
396
- t.truthy(choice.message.function_call.name);
397
- t.truthy(choice.message.function_call.arguments);
398
- }
399
- });
400
-
401
243
  test('POST /chat/completions should validate response format', async (t) => {
402
244
  const response = await got.post(`${API_BASE}/chat/completions`, {
403
245
  json: {
@@ -492,7 +334,6 @@ test('POST /chat/completions should return complete responses from gpt-4o', asyn
492
334
  t.is(response.statusCode, 200);
493
335
  t.is(response.body.object, 'chat.completion');
494
336
  t.true(Array.isArray(response.body.choices));
495
- console.log('GPT-4o Response:', JSON.stringify(response.body.choices[0].message.content));
496
337
  const content = response.body.choices[0].message.content;
497
338
  t.regex(content, /END_MARKER_XYZ$/);
498
339
  });
@@ -513,7 +354,7 @@ test('POST /chat/completions should handle array content properly', async (t) =>
513
354
  },
514
355
  {
515
356
  type: 'image',
516
- url: 'https://example.com/test.jpg'
357
+ url: 'https://static.toiimg.com/thumb/msid-102827471,width-1280,height-720,resizemode-4/102827471.jpg'
517
358
  }
518
359
  ];
519
360
 
@@ -557,68 +398,52 @@ test('POST /chat/completions should handle array content properly', async (t) =>
557
398
  }
558
399
  }
559
400
 
560
- t.log(`Using model: ${modelToUse}`);
561
401
  }
562
- } catch (modelError) {
563
- t.log('Could not get available models, using default model');
402
+ } catch (_modelError) {
403
+ // ignore model errors, fallback to default
564
404
  }
565
405
 
566
406
  // Make a direct HTTP request to the REST API
567
- const response = await axios.post(`${API_BASE}/chat/completions`, {
568
- model: modelToUse,
569
- messages: [
570
- {
571
- role: 'user',
572
- content: testContent
573
- }
574
- ]
407
+ const response = await got.post(`${API_BASE}/chat/completions`, {
408
+ json: {
409
+ model: modelToUse,
410
+ messages: [
411
+ {
412
+ role: 'user',
413
+ content: testContent
414
+ }
415
+ ],
416
+ stream: false,
417
+ },
418
+ responseType: 'json',
575
419
  });
576
420
 
577
- t.log('Response:', response.data.choices[0].message);
578
-
579
- const message = response.data.choices[0].message;
421
+ const message = response.body.choices[0].message;
580
422
 
581
- //message should not have anything similar to:
582
- //Execution failed for sys_claude_37_sonnet: HTTP error: 400 Bad Request
583
- //HTTP error:
584
423
  t.falsy(message.content.startsWith('HTTP error:'));
585
- //400 Bad Request
586
424
  t.falsy(message.content.startsWith('400 Bad Request'));
587
- //Execution failed
588
425
  t.falsy(message.content.startsWith('Execution failed'));
589
- //Invalid JSON
590
426
  t.falsy(message.content.startsWith('Invalid JSON'));
591
427
 
592
-
593
- // If the request succeeds, it means the array content was properly processed
594
- // If the JSON.stringify was not applied correctly, the request would fail
595
- t.truthy(response.data);
596
- t.pass('REST API successfully processed array content');
428
+ t.truthy(response.body);
597
429
  } catch (error) {
598
- // If there's a connection error (e.g., API not running), we'll skip this test
599
430
  if (error.code === 'ECONNREFUSED') {
600
431
  t.pass('Skipping test - REST API not available');
601
432
  } else {
602
- // Check if the error response contains useful information
603
433
  if (error.response) {
604
- // We got a response from the server, but with an error status
605
- t.log('Server responded with:', error.response.data);
606
-
607
- // Skip the test if the server is running but no pathway is configured to handle the request
608
- if (error.response.status === 404 &&
609
- error.response.data.error &&
610
- error.response.data.error.includes('not found')) {
434
+ if (error.response.statusCode === 404 &&
435
+ error.response.body &&
436
+ error.response.body.error &&
437
+ error.response.body.error.includes('not found')) {
611
438
  t.pass('Skipping test - No suitable pathway configured for this API endpoint');
612
439
  } else {
613
- t.fail(`API request failed with status ${error.response.status}: ${error.response.statusText}`);
440
+ t.fail(`API request failed with status ${error.response.statusCode}: ${error.response.statusMessage || ''}`);
614
441
  }
615
442
  } else {
616
- // No response received
617
443
  t.fail(`API request failed: ${error.message}`);
618
444
  }
619
445
  }
620
446
  }
621
- });
622
-
447
+ });
448
+
623
449
 
624
-