@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
@@ -0,0 +1,354 @@
1
+ // grok_x_search_tool.test.js
2
+ // This file contains tests for the Grok X Platform search tool
3
+
4
+ import test from 'ava';
5
+ import serverFactory from '../../../../../index.js';
6
+
7
+ let testServer;
8
+
9
+ test.before(async () => {
10
+ const { server, startServer } = await serverFactory();
11
+ startServer && await startServer();
12
+ testServer = server;
13
+ });
14
+
15
+ test.after.always('cleanup', async () => {
16
+ if (testServer) {
17
+ await testServer.stop();
18
+ }
19
+ });
20
+
21
+ // Test basic X platform search functionality through tool pathway
22
+ test('should execute SearchXPlatform tool directly', async t => {
23
+
24
+ const response = await testServer.executeOperation({
25
+ query: `
26
+ query TestSearchXPlatform($text: String, $userMessage: String) {
27
+ sys_tool_grok_x_search(text: $text, userMessage: $userMessage) {
28
+ result
29
+ errors
30
+ resultData
31
+ }
32
+ }
33
+ `,
34
+ variables: {
35
+ text: 'What are people saying about AI on X platform?',
36
+ userMessage: 'Searching X platform for AI discussions'
37
+ }
38
+ });
39
+
40
+ t.is(response.body?.singleResult?.errors, undefined);
41
+ const data = response.body?.singleResult?.data?.sys_tool_grok_x_search;
42
+ const result = data?.result;
43
+ const resultData = data?.resultData;
44
+
45
+ t.truthy(result, 'Should have a result');
46
+
47
+ // Parse the SearchResponse
48
+ let searchResponse;
49
+ try {
50
+ searchResponse = JSON.parse(result);
51
+ } catch (error) {
52
+ t.fail(`Failed to parse SearchResponse: ${error.message}`);
53
+ }
54
+
55
+ // Validate SearchResponse format
56
+ t.is(searchResponse._type, 'SearchResponse', 'Should return SearchResponse type');
57
+ t.truthy(searchResponse.value, 'Should have value array');
58
+ t.true(Array.isArray(searchResponse.value), 'Value should be an array');
59
+ t.truthy(searchResponse.text, 'Should have transformed text');
60
+
61
+ // Validate search results structure
62
+ if (searchResponse.value.length > 0) {
63
+ const firstResult = searchResponse.value[0];
64
+ t.truthy(firstResult.searchResultId, 'Should have searchResultId');
65
+ t.truthy(firstResult.title, 'Should have title');
66
+ t.truthy(firstResult.url, 'Should have url');
67
+ t.truthy(firstResult.content, 'Should have content');
68
+ t.is(firstResult.source, 'X Platform', 'Should have correct source');
69
+ }
70
+
71
+ // Check tool metadata
72
+ if (resultData) {
73
+ try {
74
+ const resultDataObject = JSON.parse(resultData);
75
+ t.is(resultDataObject.toolUsed, 'SearchXPlatform', 'Should have correct toolUsed');
76
+ } catch (error) {
77
+ t.fail('Failed to parse resultData');
78
+ }
79
+ }
80
+ });
81
+
82
+ // Test X platform search with specific handles
83
+ test('should execute SearchXPlatform with included handles', async t => {
84
+
85
+ const response = await testServer.executeOperation({
86
+ query: `
87
+ query TestSearchXPlatformWithHandles($text: String, $userMessage: String, $includedHandles: [String]) {
88
+ sys_tool_grok_x_search(text: $text, userMessage: $userMessage, includedHandles: $includedHandles) {
89
+ result
90
+ errors
91
+ resultData
92
+ }
93
+ }
94
+ `,
95
+ variables: {
96
+ text: 'What are the latest AI developments and announcements?',
97
+ userMessage: 'Searching X platform for AI developments from specific handles',
98
+ includedHandles: ['OpenAI', 'AnthropicAI', 'xai']
99
+ }
100
+ });
101
+
102
+ t.is(response.body?.singleResult?.errors, undefined);
103
+ const data = response.body?.singleResult?.data?.sys_tool_grok_x_search;
104
+ const result = data?.result;
105
+ const resultData = data?.resultData;
106
+
107
+ t.truthy(result, 'Should have a result');
108
+
109
+ // Parse and validate SearchResponse
110
+ let searchResponse;
111
+ try {
112
+ searchResponse = JSON.parse(result);
113
+ } catch (error) {
114
+ t.fail(`Failed to parse SearchResponse: ${error.message}`);
115
+ }
116
+
117
+ t.is(searchResponse._type, 'SearchResponse', 'Should return SearchResponse type');
118
+ t.truthy(searchResponse.value, 'Should have value array');
119
+ t.true(Array.isArray(searchResponse.value), 'Value should be an array');
120
+
121
+ // Check tool metadata for search parameters
122
+ if (resultData) {
123
+ try {
124
+ const resultDataObject = JSON.parse(resultData);
125
+ t.is(resultDataObject.toolUsed, 'SearchXPlatform', 'Should have correct toolUsed');
126
+ } catch (error) {
127
+ t.fail('Failed to parse resultData');
128
+ }
129
+ }
130
+ });
131
+
132
+ // Test X platform search with engagement filters
133
+ test('should execute SearchXPlatform with engagement filters', async t => {
134
+ t.timeout(60000);
135
+
136
+ const response = await testServer.executeOperation({
137
+ query: `
138
+ query TestSearchXPlatformWithEngagement($text: String, $userMessage: String, $minFavorites: Int, $minViews: Int, $maxResults: Int) {
139
+ sys_tool_grok_x_search(text: $text, userMessage: $userMessage, minFavorites: $minFavorites, minViews: $minViews, maxResults: $maxResults) {
140
+ result
141
+ errors
142
+ resultData
143
+ }
144
+ }
145
+ `,
146
+ variables: {
147
+ text: 'Popular posts about machine learning',
148
+ userMessage: 'Searching X platform for popular ML posts',
149
+ minFavorites: 500,
150
+ minViews: 5000,
151
+ maxResults: 5
152
+ }
153
+ });
154
+
155
+ t.is(response.body?.singleResult?.errors, undefined);
156
+ const data = response.body?.singleResult?.data?.sys_tool_grok_x_search;
157
+ const result = data?.result;
158
+ const resultData = data?.resultData;
159
+
160
+ t.truthy(result, 'Should have a result');
161
+
162
+ // Parse and validate SearchResponse
163
+ let searchResponse;
164
+ try {
165
+ searchResponse = JSON.parse(result);
166
+ } catch (error) {
167
+ t.fail(`Failed to parse SearchResponse: ${error.message}`);
168
+ }
169
+
170
+ t.is(searchResponse._type, 'SearchResponse', 'Should return SearchResponse type');
171
+ t.truthy(searchResponse.value, 'Should have value array');
172
+ t.true(Array.isArray(searchResponse.value), 'Value should be an array');
173
+ t.true(searchResponse.value.length <= 5, 'Should respect maxResults limit');
174
+
175
+ // Check tool metadata for engagement filters
176
+ if (resultData) {
177
+ try {
178
+ const resultDataObject = JSON.parse(resultData);
179
+ t.is(resultDataObject.toolUsed, 'SearchXPlatform', 'Should have correct toolUsed');
180
+ } catch (error) {
181
+ t.fail('Failed to parse resultData');
182
+ }
183
+ }
184
+ });
185
+
186
+ // Test X platform search with excluded handles
187
+ test('should execute SearchXPlatform with excluded handles', async t => {
188
+ t.timeout(60000);
189
+
190
+ const response = await testServer.executeOperation({
191
+ query: `
192
+ query TestSearchXPlatformWithExcludedHandles($text: String, $userMessage: String, $excludedHandles: [String]) {
193
+ sys_tool_grok_x_search(text: $text, userMessage: $userMessage, excludedHandles: $excludedHandles) {
194
+ result
195
+ errors
196
+ resultData
197
+ }
198
+ }
199
+ `,
200
+ variables: {
201
+ text: 'Recent discussions about technology',
202
+ userMessage: 'Searching X platform for tech discussions excluding spam',
203
+ excludedHandles: ['spam_account', 'bot_account']
204
+ }
205
+ });
206
+
207
+ t.is(response.body?.singleResult?.errors, undefined);
208
+ const data = response.body?.singleResult?.data?.sys_tool_grok_x_search;
209
+ const result = data?.result;
210
+ const resultData = data?.resultData;
211
+
212
+ t.truthy(result, 'Should have a result');
213
+
214
+ // Parse and validate SearchResponse
215
+ let searchResponse;
216
+ try {
217
+ searchResponse = JSON.parse(result);
218
+ } catch (error) {
219
+ t.fail(`Failed to parse SearchResponse: ${error.message}`);
220
+ }
221
+
222
+ t.is(searchResponse._type, 'SearchResponse', 'Should return SearchResponse type');
223
+ t.truthy(searchResponse.value, 'Should have value array');
224
+ t.true(Array.isArray(searchResponse.value), 'Value should be an array');
225
+
226
+ // Check tool metadata for excluded handles
227
+ if (resultData) {
228
+ try {
229
+ const resultDataObject = JSON.parse(resultData);
230
+ t.is(resultDataObject.toolUsed, 'SearchXPlatform', 'Should have correct toolUsed');
231
+ } catch (error) {
232
+ t.fail('Failed to parse resultData');
233
+ }
234
+ }
235
+ });
236
+
237
+ // Test citation handling with inline citations
238
+ test('should handle inline citations in SearchResponse', async t => {
239
+ t.timeout(60000);
240
+
241
+ // Mock a response with inline citations to test the transformation
242
+ const mockResponse = {
243
+ result: 'Here is some information about AI [1(https://x.com/example/status/123)] and more details [2(https://x.com/another/status/456)].',
244
+ citations: [
245
+ { url: 'https://x.com/example/status/123', title: 'AI Discussion Post' },
246
+ { url: 'https://x.com/another/status/456', title: 'Another AI Post' }
247
+ ]
248
+ };
249
+
250
+ // We'll test this by calling the tool and checking if citations are properly transformed
251
+ const response = await testServer.executeOperation({
252
+ query: `
253
+ query TestCitationHandling($text: String, $userMessage: String) {
254
+ sys_tool_grok_x_search(text: $text, userMessage: $userMessage) {
255
+ result
256
+ errors
257
+ resultData
258
+ }
259
+ }
260
+ `,
261
+ variables: {
262
+ text: 'Test citation handling with X platform posts',
263
+ userMessage: 'Testing citation transformation'
264
+ }
265
+ });
266
+
267
+ t.is(response.body?.singleResult?.errors, undefined);
268
+ const data = response.body?.singleResult?.data?.sys_tool_grok_x_search;
269
+ const result = data?.result;
270
+
271
+ t.truthy(result, 'Should have a result');
272
+
273
+ // Parse and validate SearchResponse
274
+ let searchResponse;
275
+ try {
276
+ searchResponse = JSON.parse(result);
277
+ } catch (error) {
278
+ t.fail(`Failed to parse SearchResponse: ${error.message}`);
279
+ }
280
+
281
+ t.is(searchResponse._type, 'SearchResponse', 'Should return SearchResponse type');
282
+ t.truthy(searchResponse.value, 'Should have value array');
283
+ t.truthy(searchResponse.text, 'Should have transformed text');
284
+
285
+ // Check that search results have proper structure
286
+ if (searchResponse.value.length > 0) {
287
+ searchResponse.value.forEach(result => {
288
+ t.truthy(result.searchResultId, 'Each result should have searchResultId');
289
+ t.truthy(result.title, 'Each result should have title');
290
+ t.truthy(result.url, 'Each result should have url');
291
+ t.is(result.source, 'X Platform', 'Each result should have correct source');
292
+ });
293
+ }
294
+
295
+ // Check that text contains proper citation format (if citations exist)
296
+ if (searchResponse.text && searchResponse.text.includes(':cd_source[')) {
297
+ t.true(searchResponse.text.includes(':cd_source['), 'Text should contain transformed citations');
298
+ }
299
+ });
300
+
301
+ // Test URL title extraction for X platform URLs
302
+ test('should extract proper titles from X platform URLs', async t => {
303
+ t.timeout(60000);
304
+
305
+ const response = await testServer.executeOperation({
306
+ query: `
307
+ query TestURLTitleExtraction($text: String, $userMessage: String) {
308
+ sys_tool_grok_x_search(text: $text, userMessage: $userMessage) {
309
+ result
310
+ errors
311
+ resultData
312
+ }
313
+ }
314
+ `,
315
+ variables: {
316
+ text: 'Find posts from @OpenAI about latest developments',
317
+ userMessage: 'Testing URL title extraction for X platform URLs'
318
+ }
319
+ });
320
+
321
+ t.is(response.body?.singleResult?.errors, undefined);
322
+ const data = response.body?.singleResult?.data?.sys_tool_grok_x_search;
323
+ const result = data?.result;
324
+
325
+ t.truthy(result, 'Should have a result');
326
+
327
+ // Parse and validate SearchResponse
328
+ let searchResponse;
329
+ try {
330
+ searchResponse = JSON.parse(result);
331
+ } catch (error) {
332
+ t.fail(`Failed to parse SearchResponse: ${error.message}`);
333
+ }
334
+
335
+ t.is(searchResponse._type, 'SearchResponse', 'Should return SearchResponse type');
336
+ t.truthy(searchResponse.value, 'Should have value array');
337
+
338
+ // Check that titles are properly extracted for X platform URLs
339
+ if (searchResponse.value.length > 0) {
340
+ searchResponse.value.forEach(result => {
341
+ if (result.url && (result.url.includes('x.com/') || result.url.includes('twitter.com/'))) {
342
+ t.truthy(result.title, 'X platform URLs should have extracted titles');
343
+ t.true(result.title.length > 0, 'Title should not be empty');
344
+ // Title should contain some indication it's from X platform
345
+ t.true(
346
+ result.title.includes('X Post') ||
347
+ result.title.includes('@') ||
348
+ result.title.includes('X Platform'),
349
+ 'Title should indicate X platform source'
350
+ );
351
+ }
352
+ });
353
+ }
354
+ });
@@ -3,7 +3,7 @@
3
3
  // It's good to execute this serially and wrap server startup and shutdown around them.
4
4
 
5
5
  import test from 'ava';
6
- import serverFactory from '../index.js';
6
+ import serverFactory from '../../../../index.js';
7
7
  import { fileURLToPath } from 'url';
8
8
  import { dirname } from 'path';
9
9
  import fs from 'fs';
@@ -1,12 +1,12 @@
1
1
  import test from 'ava';
2
- import serverFactory from '../index.js';
2
+ import serverFactory from '../../../../../index.js';
3
3
 
4
4
  let testServer;
5
5
 
6
6
  // List of models to test - comment out models you don't want to test
7
7
  const modelsToTest = [
8
8
  'oai-gpt41-mini',
9
- 'claude-35-sonnet-vertex',
9
+ 'claude-4-sonnet-vertex',
10
10
  ];
11
11
 
12
12
  // Add timing data structure
@@ -2,7 +2,7 @@
2
2
  // This is where all the Cortex vision model tests go
3
3
 
4
4
  import test from 'ava';
5
- import serverFactory from '../index.js';
5
+ import serverFactory from '../../../../../index.js';
6
6
 
7
7
  let testServer;
8
8
 
@@ -0,0 +1,26 @@
1
+ import test from 'ava';
2
+ import serverFactory from '../../../../index.js';
3
+ import { createWsClient, ensureWsConnection } from '../../../helpers/subscriptions.js';
4
+
5
+ let testServer;
6
+ let wsClient;
7
+
8
+ test.before(async () => {
9
+ process.env.CORTEX_ENABLE_REST = 'true';
10
+ const { server, startServer } = await serverFactory();
11
+ startServer && await startServer();
12
+ testServer = server;
13
+
14
+ wsClient = createWsClient();
15
+ });
16
+
17
+ test.after.always('cleanup', async () => {
18
+ if (wsClient) wsClient.dispose();
19
+ if (testServer) await testServer.stop();
20
+ });
21
+
22
+ test('WebSocket connection can subscribe', async (t) => {
23
+ await t.notThrowsAsync(() => ensureWsConnection(wsClient));
24
+ });
25
+
26
+