@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
@@ -1,5 +1,5 @@
1
- // sys_claude_35_sonnet.js
2
- // override handler for claude-35-sonnet
1
+ // sys_openai_chat_gpt4_omni.js
2
+ // override handler for gpt-4-omni
3
3
 
4
4
  import { Prompt } from '../../../server/prompt.js';
5
5
 
@@ -12,8 +12,10 @@ export default {
12
12
  ],
13
13
  inputParameters: {
14
14
  messages: [{role: '', content: []}],
15
+ tools: '',
16
+ tool_choice: 'auto',
15
17
  },
16
- model: 'claude-35-sonnet-vertex',
18
+ model: 'oai-gpt4o',
17
19
  useInputChunking: false,
18
- emulateOpenAIChatModel: 'claude-3.5-sonnet',
20
+ emulateOpenAIChatModel: 'gpt-4o',
19
21
  }
@@ -0,0 +1,21 @@
1
+ // sys_openai_chat_gpt4_omni_mini.js
2
+ // override handler for gpt-4-omni-mini
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: [{role: '', content: []}],
15
+ tools: '',
16
+ tool_choice: 'auto',
17
+ },
18
+ model: 'oai-gpt4o-mini',
19
+ useInputChunking: false,
20
+ emulateOpenAIChatModel: 'gpt-4o-mini',
21
+ }
@@ -1,5 +1,5 @@
1
- // sys_claude_3_haiku.js
2
- // override handler for claude-3-haiku
1
+ // sys_openai_chat_gpt5.js
2
+ // override handler for gpt-5
3
3
 
4
4
  import { Prompt } from '../../../server/prompt.js';
5
5
 
@@ -12,8 +12,10 @@ export default {
12
12
  ],
13
13
  inputParameters: {
14
14
  messages: [{role: '', content: []}],
15
+ tools: '',
16
+ tool_choice: 'auto',
15
17
  },
16
- model: 'claude-3-haiku-vertex',
18
+ model: 'oai-gpt5',
17
19
  useInputChunking: false,
18
- emulateOpenAIChatModel: 'claude-3-haiku',
19
- }
20
+ emulateOpenAIChatModel: 'gpt-5',
21
+ }
@@ -0,0 +1,21 @@
1
+ // sys_openai_chat_gpt5_chat.js
2
+ // override handler for gpt-5-chat
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: [{role: '', content: []}],
15
+ tools: '',
16
+ tool_choice: 'auto',
17
+ },
18
+ model: 'oai-gpt5-chat',
19
+ useInputChunking: false,
20
+ emulateOpenAIChatModel: 'gpt-5-chat',
21
+ }
@@ -0,0 +1,21 @@
1
+ // sys_openai_chat_gpt5_mini.js
2
+ // override handler for gpt-5-mini
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: [{role: '', content: []}],
15
+ tools: '',
16
+ tool_choice: 'auto',
17
+ },
18
+ model: 'oai-gpt5-mini',
19
+ useInputChunking: false,
20
+ emulateOpenAIChatModel: 'gpt-5-mini',
21
+ }
@@ -0,0 +1,21 @@
1
+ // sys_openai_chat_gpt5_nano.js
2
+ // override handler for gpt-5-nano
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: [{role: '', content: []}],
15
+ tools: '',
16
+ tool_choice: 'auto',
17
+ },
18
+ model: 'oai-gpt5-nano',
19
+ useInputChunking: false,
20
+ emulateOpenAIChatModel: 'gpt-5-nano',
21
+ }
@@ -1,4 +1,4 @@
1
- // sys_openai_chat_o1.js
1
+ // sys_openai_chat_o3.js
2
2
 
3
3
  import { Prompt } from '../../../server/prompt.js';
4
4
 
@@ -11,9 +11,12 @@ export default {
11
11
  ],
12
12
  inputParameters: {
13
13
  messages: [{role: '', content: []}],
14
+ functions: '',
15
+ tools: '',
16
+ tool_choice: 'auto',
14
17
  },
15
- model: 'oai-o1',
18
+ model: 'oai-o3',
16
19
  useInputChunking: false,
17
- emulateOpenAIChatModel: 'o1',
20
+ emulateOpenAIChatModel: 'o3',
18
21
  enableDuplicateRequests: false,
19
22
  }
@@ -11,6 +11,9 @@ export default {
11
11
  ],
12
12
  inputParameters: {
13
13
  messages: [{role: '', content: []}],
14
+ functions: '',
15
+ tools: '',
16
+ tool_choice: 'auto',
14
17
  },
15
18
  model: 'oai-o3-mini',
16
19
  useInputChunking: false,
@@ -0,0 +1,99 @@
1
+ import { config } from '../../../config.js';
2
+ import { chatArgsHasImageUrl, chatArgsHasType, getAvailableFiles, removeOldImageAndFileContent } from '../../../lib/util.js';
3
+ import { loadEntityConfig } from '../../../pathways/system/entity/tools/shared/sys_entity_tools.js';
4
+ import { Prompt } from '../../../server/prompt.js';
5
+
6
+ export default {
7
+ emulateOpenAIChatModel: 'cortex-agent',
8
+ useInputChunking: false,
9
+ enableDuplicateRequests: false,
10
+ useSingleTokenStream: false,
11
+
12
+ inputParameters: {
13
+ prompt: "",
14
+ systemPrompt: "",
15
+ chatHistory: [{role: '', content: []}],
16
+ text: "",
17
+ entityId: "labeeb",
18
+ aiName: "Jarvis",
19
+ language: "English",
20
+ model: "oai-gpt41", // Allow user to specify model
21
+ },
22
+
23
+ timeout: 600,
24
+
25
+ executePathway: async ({args, runAllPrompts, resolver}) => {
26
+ let pathwayResolver = resolver;
27
+
28
+ // Load input parameters and information into args
29
+ const { entityId, aiName, language, model } = { ...pathwayResolver.pathway.inputParameters, ...args };
30
+
31
+ const entityConfig = loadEntityConfig(entityId);
32
+
33
+ // Initialize chat history if needed
34
+ if (!args.chatHistory || args.chatHistory.length === 0) {
35
+ args.chatHistory = [];
36
+ }
37
+
38
+ // Limit the chat history to 20 messages to speed up processing
39
+ args.chatHistory = args.chatHistory.slice(-20);
40
+
41
+ // Add entity constants for template rendering
42
+ args = {
43
+ ...args,
44
+ ...config.get('entityConstants'),
45
+ entityId,
46
+ aiName,
47
+ language,
48
+ model
49
+ };
50
+
51
+ // Extract available files from chat history
52
+ const availableFiles = getAvailableFiles(args.chatHistory);
53
+
54
+ // Check for both image and file content (CSV files have type 'file', not 'image_url')
55
+ const hasImageContent = chatArgsHasImageUrl(args);
56
+ const hasFileContent = chatArgsHasType(args, 'file');
57
+ const visionContentPresent = hasImageContent || hasFileContent;
58
+
59
+ // Remove old image and file content while preserving the latest uploads
60
+ visionContentPresent && (args.chatHistory = removeOldImageAndFileContent(args.chatHistory));
61
+
62
+ const promptMessages = [
63
+ {"role": "system", "content": `${args.systemPrompt || "Assistant is an expert journalist's assistant for Al Jazeera Media Network. When a user posts a request, Assistant will come up with the best response while upholding the highest journalistic standards."}\n\n{{renderTemplate AI_TOOLS}}\n\n{{renderTemplate AI_AVAILABLE_FILES}}\n\n{{renderTemplate AI_DATETIME}}`},
64
+ "{{chatHistory}}"
65
+ ];
66
+
67
+ // Only add a user message if there's actual text or prompt content
68
+ const userContent = `${args.text || ""}\n\n${args.prompt || ""}`.trim();
69
+ if (userContent) {
70
+ promptMessages.push({"role": "user", "content": userContent});
71
+ }
72
+
73
+ pathwayResolver.pathwayPrompt = [
74
+ new Prompt({ messages: promptMessages }),
75
+ ];
76
+
77
+ pathwayResolver.args = {...args};
78
+
79
+ try {
80
+ let currentMessages = JSON.parse(JSON.stringify(args.chatHistory));
81
+
82
+ console.log("currentMessages", currentMessages);
83
+ console.log("args", args);
84
+
85
+ let response = await runAllPrompts({
86
+ ...args,
87
+ chatHistory: currentMessages,
88
+ availableFiles,
89
+ model: args.model // Pass the model from args
90
+ });
91
+
92
+ return response;
93
+
94
+ } catch (e) {
95
+ pathwayResolver.logError(e);
96
+ throw e;
97
+ }
98
+ }
99
+ };
@@ -11,9 +11,9 @@ export default {
11
11
  inputParameters: {
12
12
  chatHistory: [{role: '', content: []}],
13
13
  contextId: ``,
14
+ model: `oai-gpt41`,
14
15
  },
15
16
  max_tokens: 1024,
16
- model: 'oai-gpt41',
17
17
  useInputChunking: false,
18
18
  enableDuplicateRequests: false,
19
19
  timeout: 600,
package/server/graphql.js CHANGED
@@ -18,7 +18,7 @@ import cors from 'cors';
18
18
  import { buildModels, buildPathways } from '../config.js';
19
19
  import logger from '../lib/logger.js';
20
20
  import { buildModelEndpoints } from '../lib/requestExecutor.js';
21
- import { startTestServer } from '../tests/server.js';
21
+ import { startTestServer } from '../tests/helpers/server.js';
22
22
  import { requestState } from './requestState.js';
23
23
  import { cancelRequestResolver } from './resolver.js';
24
24
  import subscriptions from './subscriptions.js';
@@ -33,7 +33,9 @@ import ApptekTranslatePlugin from './plugins/apptekTranslatePlugin.js';
33
33
  import GoogleTranslatePlugin from './plugins/googleTranslatePlugin.js';
34
34
  import GroqChatPlugin from './plugins/groqChatPlugin.js';
35
35
  import VeoVideoPlugin from './plugins/veoVideoPlugin.js';
36
+ import GrokVisionPlugin from './plugins/grokVisionPlugin.js';
36
37
  import AzureFoundryAgentsPlugin from './plugins/azureFoundryAgentsPlugin.js';
38
+ import GoogleCsePlugin from './plugins/googleCsePlugin.js';
37
39
 
38
40
  class ModelExecutor {
39
41
  constructor(pathway, model) {
@@ -134,9 +136,15 @@ class ModelExecutor {
134
136
  case 'VEO-VIDEO':
135
137
  plugin = new VeoVideoPlugin(pathway, model);
136
138
  break;
139
+ case 'GROK-VISION':
140
+ plugin = new GrokVisionPlugin(pathway, model);
141
+ break;
137
142
  case 'AZURE-FOUNDRY-AGENTS':
138
143
  plugin = new AzureFoundryAgentsPlugin(pathway, model);
139
144
  break;
145
+ case 'GOOGLE-CSE':
146
+ plugin = new GoogleCsePlugin(pathway, model);
147
+ break;
140
148
  default:
141
149
  throw new Error(`Unsupported model type: ${model.type}`);
142
150
  }
@@ -29,7 +29,7 @@ class PathwayResolver {
29
29
  this.requestId = uuidv4();
30
30
  this.rootRequestId = null;
31
31
  this.responseParser = new PathwayResponseParser(pathway);
32
- this.tool = null;
32
+ this.pathwayResultData = {};
33
33
  this.modelName = [
34
34
  pathway.model,
35
35
  args?.model,
@@ -72,12 +72,58 @@ class PathwayResolver {
72
72
  // set up initial prompt
73
73
  this.pathwayPrompt = pathway.prompt;
74
74
  }
75
+
76
+ // Legacy 'tool' property is now stored in pathwayResultData
77
+ get tool() {
78
+ // Select fields to serialize for legacy compat, excluding undefined values
79
+ const legacyFields = Object.fromEntries(
80
+ Object.entries({
81
+ hideFromModel: this.pathwayResultData.hideFromModel,
82
+ toolCallbackName: this.pathwayResultData.toolCallbackName,
83
+ title: this.pathwayResultData.title,
84
+ search: this.pathwayResultData.search,
85
+ coding: this.pathwayResultData.coding,
86
+ codeRequestId: this.pathwayResultData.codeRequestId,
87
+ toolCallbackId: this.pathwayResultData.toolCallbackId,
88
+ toolUsed: this.pathwayResultData.toolUsed,
89
+ citations: this.pathwayResultData.citations,
90
+
91
+ }).filter(([_, value]) => value !== undefined)
92
+ );
93
+ return JSON.stringify(legacyFields);
94
+ }
95
+
96
+ set tool(value) {
97
+ // Accepts a JSON string, parses, merges into pathwayResultData
98
+ let parsed;
99
+ try {
100
+ parsed = (typeof value === 'string') ? JSON.parse(value) : value;
101
+ this.pathwayResultData = this.mergeResultData(parsed);
102
+ } catch (e) {
103
+ // Optionally warn: invalid format or merge error
104
+ console.warn('Invalid tool property assignment:', e);
105
+ }
106
+ }
75
107
 
76
108
  publishNestedRequestProgress(requestProgress) {
77
- if (requestProgress.progress === 1 && this.rootRequestId) {
78
- delete requestProgress.progress;
109
+
110
+ if (this.rootRequestId) {
111
+ // if this is a nested request, don't end the stream
112
+ if (requestProgress.progress === 1) {
113
+ delete requestProgress.progress;
114
+ }
115
+ publishRequestProgress(requestProgress);
116
+ } else {
117
+ // this is a root request, so we add the pathwayResultData to the info
118
+ // and allow the end stream message to be sent
119
+ if (requestProgress.progress === 1) {
120
+ const infoObject = { ...this.pathwayResultData || {} };
121
+ requestProgress.info = JSON.stringify(infoObject);
122
+ requestProgress.error = this.errors.join(', ') || '';
123
+ }
124
+ publishRequestProgress(requestProgress);
79
125
  }
80
- publishRequestProgress({...requestProgress, info: this.tool || '', error: this.errors.join(', ')});
126
+
81
127
  }
82
128
 
83
129
  // This code handles async and streaming responses for either long-running
@@ -120,31 +166,102 @@ class PathwayResolver {
120
166
 
121
167
  // some models don't support progress updates
122
168
  if (!modelTypesExcludedFromProgressUpdates.includes(this.model.type)) {
169
+ const infoObject = { ...this.pathwayResultData || {} };
123
170
  this.publishNestedRequestProgress({
124
171
  requestId: this.rootRequestId || this.requestId,
125
172
  progress: Math.min(completedCount, totalCount) / totalCount,
126
173
  // Clients expect these to be strings
127
174
  data: JSON.stringify(responseData || ''),
128
- info: this.tool || '',
175
+ info: JSON.stringify(infoObject) || '',
129
176
  error: this.errors.join(', ') || ''
130
177
  });
131
178
  }
132
179
  }
133
180
  }
134
181
 
135
- mergeResults(mergeData) {
136
- if (mergeData) {
137
- this.previousResult = mergeData.previousResult ? mergeData.previousResult : this.previousResult;
138
- this.warnings = [...this.warnings, ...(mergeData.warnings || [])];
139
- this.errors = [...this.errors, ...(mergeData.errors || [])];
140
- try {
141
- const mergeDataTool = typeof mergeData.tool === 'string' ? JSON.parse(mergeData.tool) : mergeData.tool || {};
142
- const thisTool = typeof this.tool === 'string' ? JSON.parse(this.tool) : this.tool || {};
143
- this.tool = JSON.stringify({ ...thisTool, ...mergeDataTool });
144
- } catch (error) {
145
- logger.warn('Error merging pathway resolver tool objects: ' + error);
182
+ mergeResolver(otherResolver) {
183
+ if (otherResolver) {
184
+ this.previousResult = otherResolver.previousResult ? otherResolver.previousResult : this.previousResult;
185
+ this.warnings = [...this.warnings, ...otherResolver.warnings];
186
+ this.errors = [...this.errors, ...otherResolver.errors];
187
+
188
+ // Use the shared mergeResultData method
189
+ this.pathwayResultData = this.mergeResultData(otherResolver.pathwayResultData);
190
+ }
191
+ }
192
+
193
+ // Merge pathwayResultData with either another pathwayResultData object or a CortexResponse
194
+ mergeResultData(newData) {
195
+ if (!newData) return this.pathwayResultData;
196
+
197
+ const currentData = this.pathwayResultData || {};
198
+
199
+ // Handle CortexResponse objects
200
+ if (newData.constructor && newData.constructor.name === 'CortexResponse') {
201
+ const cortexResponse = newData;
202
+ const cortexData = {
203
+ citations: cortexResponse.citations,
204
+ toolCalls: cortexResponse.toolCalls,
205
+ functionCall: cortexResponse.functionCall,
206
+ usage: cortexResponse.usage,
207
+ finishReason: cortexResponse.finishReason
208
+ };
209
+ newData = cortexData;
210
+ }
211
+
212
+ // Create merged result
213
+ const merged = { ...currentData, ...newData };
214
+
215
+ // Handle array fields that should be concatenated
216
+ const arrayFields = ['citations', 'toolCalls'];
217
+ for (const field of arrayFields) {
218
+ const currentArray = currentData[field] || [];
219
+ const newArray = newData[field] || [];
220
+ if (newArray.length > 0) {
221
+ merged[field] = [...currentArray, ...newArray];
222
+ } else if (currentArray.length > 0) {
223
+ merged[field] = currentArray;
146
224
  }
147
225
  }
226
+
227
+ // Handle usage and toolUsed data - convert to arrays with most recent first
228
+ const createArrayFromData = (currentValue, newValue) => {
229
+ if (!currentValue && !newValue) return null;
230
+
231
+ const array = [];
232
+
233
+ // Add new value first (most recent)
234
+ if (newValue) {
235
+ if (Array.isArray(newValue)) {
236
+ array.push(...newValue);
237
+ } else {
238
+ array.push(newValue);
239
+ }
240
+ }
241
+
242
+ // Add current value second (older)
243
+ if (currentValue) {
244
+ if (Array.isArray(currentValue)) {
245
+ array.push(...currentValue);
246
+ } else {
247
+ array.push(currentValue);
248
+ }
249
+ }
250
+
251
+ return array;
252
+ };
253
+
254
+ const usageArray = createArrayFromData(currentData.usage, newData.usage);
255
+ if (usageArray) {
256
+ merged.usage = usageArray;
257
+ }
258
+
259
+ const toolUsedArray = createArrayFromData(currentData.toolUsed, newData.toolUsed);
260
+ if (toolUsedArray) {
261
+ merged.toolUsed = toolUsedArray;
262
+ }
263
+
264
+ return merged;
148
265
  }
149
266
 
150
267
  async handleStream(response) {
@@ -251,6 +368,15 @@ class PathwayResolver {
251
368
  }
252
369
 
253
370
  async promptAndParse(args) {
371
+ // Check if model is specified in args and swap if different from current model
372
+ if (args.modelOverride && args.modelOverride !== this.modelName) {
373
+ try {
374
+ this.swapModel(args.modelOverride);
375
+ } catch (error) {
376
+ this.logError(`Failed to swap model to ${args.modelOverride}: ${error.message}`);
377
+ }
378
+ }
379
+
254
380
  // Get saved context from contextId or change contextId if needed
255
381
  const { contextId } = args;
256
382
  this.savedContextId = contextId ? contextId : uuidv4();
@@ -500,6 +626,30 @@ class PathwayResolver {
500
626
  return result;
501
627
  }
502
628
 
629
+ /**
630
+ * Swaps the model used by this PathwayResolver
631
+ * @param {string} newModelName - The name of the new model to use
632
+ * @throws {Error} If the new model is not found in the endpoints
633
+ */
634
+ swapModel(newModelName) {
635
+ // Validate that the new model exists in endpoints
636
+ if (!this.endpoints[newModelName]) {
637
+ throw new Error(`Model ${newModelName} not found in config`);
638
+ }
639
+
640
+ // Update model references
641
+ this.modelName = newModelName;
642
+ this.model = this.endpoints[newModelName];
643
+
644
+ // Create new ModelExecutor with the new model
645
+ this.modelExecutor = new ModelExecutor(this.pathway, this.model);
646
+
647
+ // Recalculate chunk max token length as it depends on the model
648
+ this.chunkMaxTokenLength = this.getChunkMaxTokenLength();
649
+
650
+ this.logWarning(`Model swapped to ${newModelName}`);
651
+ }
652
+
503
653
  async applyPrompt(prompt, text, parameters) {
504
654
  if (requestState[this.requestId].canceled) {
505
655
  return;
@@ -1,4 +1,5 @@
1
1
  import { parseNumberedList, parseNumberedObjectList, parseCommaSeparatedList, isCommaSeparatedList, isNumberedList, parseJson } from './parser.js';
2
+ import CortexResponse from '../lib/cortexResponse.js';
2
3
 
3
4
  class PathwayResponseParser {
4
5
  constructor(pathway) {
@@ -6,24 +7,31 @@ class PathwayResponseParser {
6
7
  }
7
8
 
8
9
  async parse(data) {
10
+
11
+ let dataToParse = data;
12
+
13
+ if (data instanceof CortexResponse) {
14
+ dataToParse = data.toString();
15
+ }
16
+
9
17
  if (this.pathway.parser) {
10
- return this.pathway.parser(data);
18
+ return this.pathway.parser(dataToParse);
11
19
  }
12
20
 
13
21
  if (this.pathway.list) {
14
- if (isNumberedList(data)) {
22
+ if (isNumberedList(dataToParse)) {
15
23
  if (this.pathway.format) {
16
- return await parseNumberedObjectList(data, this.pathway.format);
24
+ return await parseNumberedObjectList(dataToParse, this.pathway.format);
17
25
  }
18
- return parseNumberedList(data);
19
- } else if (isCommaSeparatedList(data)) {
20
- return parseCommaSeparatedList(data);
26
+ return parseNumberedList(dataToParse);
27
+ } else if (isCommaSeparatedList(dataToParse)) {
28
+ return parseCommaSeparatedList(dataToParse);
21
29
  }
22
- return [data];
30
+ return [dataToParse];
23
31
  }
24
32
 
25
33
  if (this.pathway.json) {
26
- return await parseJson(data);
34
+ return await parseJson(dataToParse);
27
35
  }
28
36
 
29
37
  return data;
@@ -86,7 +86,7 @@ class AzureFoundryAgentsPlugin extends ModelPlugin {
86
86
  ...(parameters.top_p && { top_p: parameters.top_p }),
87
87
  ...(parameters.tool_choice && { tool_choice: parameters.tool_choice }),
88
88
  ...(parameters.response_format && { response_format: parameters.response_format }),
89
- ...(parameters.parallel_tool_calls && { parallel_tool_calls: parameters.parallel_tool_calls }),
89
+ ...(parameters.parallel_tool_calls !== undefined && { parallel_tool_calls: parameters.parallel_tool_calls }),
90
90
  ...(parameters.truncation_strategy && { truncation_strategy: parameters.truncation_strategy })
91
91
  };
92
92