@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.
- package/.github/workflows/cortex-file-handler-test.yml +61 -0
- package/README.md +31 -7
- package/config/default.example.json +15 -0
- package/config.js +133 -12
- package/helper-apps/cortex-autogen2/DigiCertGlobalRootCA.crt.pem +22 -0
- package/helper-apps/cortex-autogen2/Dockerfile +31 -0
- package/helper-apps/cortex-autogen2/Dockerfile.worker +41 -0
- package/helper-apps/cortex-autogen2/README.md +183 -0
- package/helper-apps/cortex-autogen2/__init__.py +1 -0
- package/helper-apps/cortex-autogen2/agents.py +131 -0
- package/helper-apps/cortex-autogen2/docker-compose.yml +20 -0
- package/helper-apps/cortex-autogen2/function_app.py +55 -0
- package/helper-apps/cortex-autogen2/host.json +15 -0
- package/helper-apps/cortex-autogen2/main.py +126 -0
- package/helper-apps/cortex-autogen2/poetry.lock +3652 -0
- package/helper-apps/cortex-autogen2/pyproject.toml +36 -0
- package/helper-apps/cortex-autogen2/requirements.txt +20 -0
- package/helper-apps/cortex-autogen2/send_task.py +105 -0
- package/helper-apps/cortex-autogen2/services/__init__.py +1 -0
- package/helper-apps/cortex-autogen2/services/azure_queue.py +85 -0
- package/helper-apps/cortex-autogen2/services/redis_publisher.py +153 -0
- package/helper-apps/cortex-autogen2/task_processor.py +488 -0
- package/helper-apps/cortex-autogen2/tools/__init__.py +24 -0
- package/helper-apps/cortex-autogen2/tools/azure_blob_tools.py +175 -0
- package/helper-apps/cortex-autogen2/tools/azure_foundry_agents.py +601 -0
- package/helper-apps/cortex-autogen2/tools/coding_tools.py +72 -0
- package/helper-apps/cortex-autogen2/tools/download_tools.py +48 -0
- package/helper-apps/cortex-autogen2/tools/file_tools.py +545 -0
- package/helper-apps/cortex-autogen2/tools/search_tools.py +646 -0
- package/helper-apps/cortex-azure-cleaner/README.md +36 -0
- package/helper-apps/cortex-file-converter/README.md +93 -0
- package/helper-apps/cortex-file-converter/key_to_pdf.py +104 -0
- package/helper-apps/cortex-file-converter/list_blob_extensions.py +89 -0
- package/helper-apps/cortex-file-converter/process_azure_keynotes.py +181 -0
- package/helper-apps/cortex-file-converter/requirements.txt +1 -0
- package/helper-apps/cortex-file-handler/.env.test.azure.ci +7 -0
- package/helper-apps/cortex-file-handler/.env.test.azure.sample +1 -1
- package/helper-apps/cortex-file-handler/.env.test.gcs.ci +10 -0
- package/helper-apps/cortex-file-handler/.env.test.gcs.sample +2 -2
- package/helper-apps/cortex-file-handler/INTERFACE.md +41 -0
- package/helper-apps/cortex-file-handler/package.json +1 -1
- package/helper-apps/cortex-file-handler/scripts/setup-azure-container.js +41 -17
- package/helper-apps/cortex-file-handler/scripts/setup-test-containers.js +30 -15
- package/helper-apps/cortex-file-handler/scripts/test-azure.sh +32 -6
- package/helper-apps/cortex-file-handler/scripts/test-gcs.sh +24 -2
- package/helper-apps/cortex-file-handler/scripts/validate-env.js +128 -0
- package/helper-apps/cortex-file-handler/src/blobHandler.js +161 -51
- package/helper-apps/cortex-file-handler/src/constants.js +3 -0
- package/helper-apps/cortex-file-handler/src/fileChunker.js +10 -8
- package/helper-apps/cortex-file-handler/src/index.js +116 -9
- package/helper-apps/cortex-file-handler/src/redis.js +61 -1
- package/helper-apps/cortex-file-handler/src/services/ConversionService.js +11 -8
- package/helper-apps/cortex-file-handler/src/services/FileConversionService.js +2 -2
- package/helper-apps/cortex-file-handler/src/services/storage/AzureStorageProvider.js +88 -6
- package/helper-apps/cortex-file-handler/src/services/storage/GCSStorageProvider.js +58 -0
- package/helper-apps/cortex-file-handler/src/services/storage/StorageFactory.js +25 -5
- package/helper-apps/cortex-file-handler/src/services/storage/StorageProvider.js +9 -0
- package/helper-apps/cortex-file-handler/src/services/storage/StorageService.js +120 -16
- package/helper-apps/cortex-file-handler/src/start.js +27 -17
- package/helper-apps/cortex-file-handler/tests/FileConversionService.test.js +52 -1
- package/helper-apps/cortex-file-handler/tests/blobHandler.test.js +40 -0
- package/helper-apps/cortex-file-handler/tests/checkHashShortLived.test.js +553 -0
- package/helper-apps/cortex-file-handler/tests/cleanup.test.js +46 -52
- package/helper-apps/cortex-file-handler/tests/containerConversionFlow.test.js +451 -0
- package/helper-apps/cortex-file-handler/tests/containerNameParsing.test.js +229 -0
- package/helper-apps/cortex-file-handler/tests/containerParameterFlow.test.js +392 -0
- package/helper-apps/cortex-file-handler/tests/conversionResilience.test.js +7 -2
- package/helper-apps/cortex-file-handler/tests/deleteOperations.test.js +348 -0
- package/helper-apps/cortex-file-handler/tests/fileChunker.test.js +23 -2
- package/helper-apps/cortex-file-handler/tests/fileUpload.test.js +11 -5
- package/helper-apps/cortex-file-handler/tests/getOperations.test.js +58 -24
- package/helper-apps/cortex-file-handler/tests/postOperations.test.js +11 -4
- package/helper-apps/cortex-file-handler/tests/shortLivedUrlConversion.test.js +225 -0
- package/helper-apps/cortex-file-handler/tests/start.test.js +8 -12
- package/helper-apps/cortex-file-handler/tests/storage/StorageFactory.test.js +80 -0
- package/helper-apps/cortex-file-handler/tests/storage/StorageService.test.js +388 -22
- package/helper-apps/cortex-file-handler/tests/testUtils.helper.js +74 -0
- package/lib/cortexResponse.js +153 -0
- package/lib/entityConstants.js +21 -3
- package/lib/logger.js +21 -4
- package/lib/pathwayTools.js +28 -9
- package/lib/util.js +49 -0
- package/package.json +1 -1
- package/pathways/basePathway.js +1 -0
- package/pathways/bing_afagent.js +54 -1
- package/pathways/call_tools.js +2 -3
- package/pathways/chat_jarvis.js +1 -1
- package/pathways/google_cse.js +27 -0
- package/pathways/grok_live_search.js +18 -0
- package/pathways/system/entity/memory/sys_memory_lookup_required.js +1 -0
- package/pathways/system/entity/memory/sys_memory_required.js +1 -0
- package/pathways/system/entity/memory/sys_search_memory.js +1 -0
- package/pathways/system/entity/sys_entity_agent.js +56 -4
- package/pathways/system/entity/sys_generator_quick.js +1 -0
- package/pathways/system/entity/tools/sys_tool_bing_search_afagent.js +26 -0
- package/pathways/system/entity/tools/sys_tool_google_search.js +141 -0
- package/pathways/system/entity/tools/sys_tool_grok_x_search.js +237 -0
- package/pathways/system/entity/tools/sys_tool_image.js +1 -1
- package/pathways/system/rest_streaming/sys_claude_37_sonnet.js +21 -0
- package/pathways/system/rest_streaming/sys_claude_41_opus.js +21 -0
- package/pathways/system/rest_streaming/sys_claude_4_sonnet.js +21 -0
- package/pathways/system/rest_streaming/sys_google_gemini_25_flash.js +25 -0
- package/pathways/system/rest_streaming/{sys_google_gemini_chat.js → sys_google_gemini_25_pro.js} +6 -4
- package/pathways/system/rest_streaming/sys_grok_4.js +23 -0
- package/pathways/system/rest_streaming/sys_grok_4_fast_non_reasoning.js +23 -0
- package/pathways/system/rest_streaming/sys_grok_4_fast_reasoning.js +23 -0
- package/pathways/system/rest_streaming/sys_openai_chat.js +3 -0
- package/pathways/system/rest_streaming/sys_openai_chat_gpt41.js +22 -0
- package/pathways/system/rest_streaming/sys_openai_chat_gpt41_mini.js +21 -0
- package/pathways/system/rest_streaming/sys_openai_chat_gpt41_nano.js +21 -0
- package/pathways/system/rest_streaming/{sys_claude_35_sonnet.js → sys_openai_chat_gpt4_omni.js} +6 -4
- package/pathways/system/rest_streaming/sys_openai_chat_gpt4_omni_mini.js +21 -0
- package/pathways/system/rest_streaming/{sys_claude_3_haiku.js → sys_openai_chat_gpt5.js} +7 -5
- package/pathways/system/rest_streaming/sys_openai_chat_gpt5_chat.js +21 -0
- package/pathways/system/rest_streaming/sys_openai_chat_gpt5_mini.js +21 -0
- package/pathways/system/rest_streaming/sys_openai_chat_gpt5_nano.js +21 -0
- package/pathways/system/rest_streaming/{sys_openai_chat_o1.js → sys_openai_chat_o3.js} +6 -3
- package/pathways/system/rest_streaming/sys_openai_chat_o3_mini.js +3 -0
- package/pathways/system/workspaces/run_workspace_prompt.js +99 -0
- package/pathways/vision.js +1 -1
- package/server/graphql.js +1 -1
- package/server/modelExecutor.js +8 -0
- package/server/pathwayResolver.js +166 -16
- package/server/pathwayResponseParser.js +16 -8
- package/server/plugins/azureFoundryAgentsPlugin.js +1 -1
- package/server/plugins/claude3VertexPlugin.js +193 -45
- package/server/plugins/gemini15ChatPlugin.js +21 -0
- package/server/plugins/gemini15VisionPlugin.js +360 -0
- package/server/plugins/googleCsePlugin.js +94 -0
- package/server/plugins/grokVisionPlugin.js +365 -0
- package/server/plugins/modelPlugin.js +3 -1
- package/server/plugins/openAiChatPlugin.js +106 -13
- package/server/plugins/openAiVisionPlugin.js +42 -30
- package/server/resolver.js +28 -4
- package/server/rest.js +270 -53
- package/server/typeDef.js +1 -0
- package/tests/{mocks.js → helpers/mocks.js} +5 -2
- package/tests/{server.js → helpers/server.js} +2 -2
- package/tests/helpers/sseAssert.js +23 -0
- package/tests/helpers/sseClient.js +73 -0
- package/tests/helpers/subscriptionAssert.js +11 -0
- package/tests/helpers/subscriptions.js +113 -0
- package/tests/{sublong.srt → integration/features/translate/sublong.srt} +4543 -4543
- package/tests/integration/features/translate/translate_chunking_stream.test.js +100 -0
- package/tests/{translate_srt.test.js → integration/features/translate/translate_srt.test.js} +2 -2
- package/tests/integration/graphql/async/stream/agentic.test.js +477 -0
- package/tests/integration/graphql/async/stream/subscription_streaming.test.js +62 -0
- package/tests/integration/graphql/async/stream/sys_entity_start_streaming.test.js +71 -0
- package/tests/integration/graphql/async/stream/vendors/claude_streaming.test.js +56 -0
- package/tests/integration/graphql/async/stream/vendors/gemini_streaming.test.js +66 -0
- package/tests/integration/graphql/async/stream/vendors/grok_streaming.test.js +56 -0
- package/tests/integration/graphql/async/stream/vendors/openai_streaming.test.js +72 -0
- package/tests/integration/graphql/features/google/sysToolGoogleSearch.test.js +96 -0
- package/tests/integration/graphql/features/grok/grok.test.js +688 -0
- package/tests/integration/graphql/features/grok/grok_x_search_tool.test.js +354 -0
- package/tests/{main.test.js → integration/graphql/features/main.test.js} +1 -1
- package/tests/{call_tools.test.js → integration/graphql/features/tools/call_tools.test.js} +2 -2
- package/tests/{vision.test.js → integration/graphql/features/vision/vision.test.js} +1 -1
- package/tests/integration/graphql/subscriptions/connection.test.js +26 -0
- package/tests/{openai_api.test.js → integration/rest/oai/openai_api.test.js} +63 -238
- package/tests/integration/rest/oai/tool_calling_api.test.js +343 -0
- package/tests/integration/rest/oai/tool_calling_streaming.test.js +85 -0
- package/tests/integration/rest/vendors/claude_streaming.test.js +47 -0
- package/tests/integration/rest/vendors/claude_tool_calling_streaming.test.js +75 -0
- package/tests/integration/rest/vendors/gemini_streaming.test.js +47 -0
- package/tests/integration/rest/vendors/gemini_tool_calling_streaming.test.js +75 -0
- package/tests/integration/rest/vendors/grok_streaming.test.js +55 -0
- package/tests/integration/rest/vendors/grok_tool_calling_streaming.test.js +75 -0
- package/tests/{azureAuthTokenHelper.test.js → unit/core/azureAuthTokenHelper.test.js} +1 -1
- package/tests/{chunkfunction.test.js → unit/core/chunkfunction.test.js} +2 -2
- package/tests/{config.test.js → unit/core/config.test.js} +3 -3
- package/tests/{encodeCache.test.js → unit/core/encodeCache.test.js} +1 -1
- package/tests/{fastLruCache.test.js → unit/core/fastLruCache.test.js} +1 -1
- package/tests/{handleBars.test.js → unit/core/handleBars.test.js} +1 -1
- package/tests/{memoryfunction.test.js → unit/core/memoryfunction.test.js} +2 -2
- package/tests/unit/core/mergeResolver.test.js +952 -0
- package/tests/{parser.test.js → unit/core/parser.test.js} +3 -3
- package/tests/unit/core/pathwayResolver.test.js +187 -0
- package/tests/{requestMonitor.test.js → unit/core/requestMonitor.test.js} +1 -1
- package/tests/{requestMonitorDurationEstimator.test.js → unit/core/requestMonitorDurationEstimator.test.js} +1 -1
- package/tests/{truncateMessages.test.js → unit/core/truncateMessages.test.js} +3 -3
- package/tests/{util.test.js → unit/core/util.test.js} +1 -1
- package/tests/{apptekTranslatePlugin.test.js → unit/plugins/apptekTranslatePlugin.test.js} +3 -3
- package/tests/{azureFoundryAgents.test.js → unit/plugins/azureFoundryAgents.test.js} +136 -1
- package/tests/{claude3VertexPlugin.test.js → unit/plugins/claude3VertexPlugin.test.js} +32 -10
- package/tests/{claude3VertexToolConversion.test.js → unit/plugins/claude3VertexToolConversion.test.js} +3 -3
- package/tests/unit/plugins/googleCsePlugin.test.js +111 -0
- package/tests/unit/plugins/grokVisionPlugin.test.js +1392 -0
- package/tests/{modelPlugin.test.js → unit/plugins/modelPlugin.test.js} +3 -3
- package/tests/{multimodal_conversion.test.js → unit/plugins/multimodal_conversion.test.js} +4 -4
- package/tests/{openAiChatPlugin.test.js → unit/plugins/openAiChatPlugin.test.js} +13 -4
- package/tests/{openAiToolPlugin.test.js → unit/plugins/openAiToolPlugin.test.js} +35 -27
- package/tests/{tokenHandlingTests.test.js → unit/plugins/tokenHandlingTests.test.js} +5 -5
- package/tests/{translate_apptek.test.js → unit/plugins/translate_apptek.test.js} +3 -3
- package/tests/{streaming.test.js → unit/plugins.streaming/plugin_stream_events.test.js} +19 -58
- package/helper-apps/mogrt-handler/tests/test-files/test.gif +0 -1
- package/helper-apps/mogrt-handler/tests/test-files/test.mogrt +0 -1
- package/helper-apps/mogrt-handler/tests/test-files/test.mp4 +0 -1
- package/pathways/system/rest_streaming/sys_openai_chat_gpt4.js +0 -19
- package/pathways/system/rest_streaming/sys_openai_chat_gpt4_32.js +0 -19
- package/pathways/system/rest_streaming/sys_openai_chat_gpt4_turbo.js +0 -19
- package/pathways/system/workspaces/run_claude35_sonnet.js +0 -21
- package/pathways/system/workspaces/run_claude3_haiku.js +0 -20
- package/pathways/system/workspaces/run_gpt35turbo.js +0 -20
- package/pathways/system/workspaces/run_gpt4.js +0 -20
- package/pathways/system/workspaces/run_gpt4_32.js +0 -20
- package/tests/agentic.test.js +0 -256
- package/tests/pathwayResolver.test.js +0 -78
- package/tests/subscription.test.js +0 -387
- /package/tests/{subchunk.srt → integration/features/translate/subchunk.srt} +0 -0
- /package/tests/{subhorizontal.srt → integration/features/translate/subhorizontal.srt} +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import test from "ava";
|
|
2
2
|
import { StorageService } from "../../src/services/storage/StorageService.js";
|
|
3
3
|
import { StorageFactory } from "../../src/services/storage/StorageFactory.js";
|
|
4
|
+
import { getFileStoreMap, setFileStoreMap, removeFromFileStoreMap } from "../../src/redis.js";
|
|
4
5
|
import path from "path";
|
|
5
6
|
import os from "os";
|
|
6
7
|
import fs from "fs";
|
|
@@ -46,20 +47,30 @@ test("should upload file to primary storage", async (t) => {
|
|
|
46
47
|
test("should upload file to backup storage", async (t) => {
|
|
47
48
|
const factory = new StorageFactory();
|
|
48
49
|
const service = new StorageService(factory);
|
|
49
|
-
const provider = service.getBackupProvider();
|
|
50
|
+
const provider = await service.getBackupProvider();
|
|
50
51
|
if (!provider) {
|
|
51
|
-
t.log("
|
|
52
|
+
t.log("Backup provider not configured, skipping test");
|
|
52
53
|
t.pass();
|
|
53
54
|
return;
|
|
54
55
|
}
|
|
55
|
-
|
|
56
|
-
|
|
56
|
+
|
|
57
|
+
try {
|
|
58
|
+
const testContent = "test content";
|
|
59
|
+
const buffer = Buffer.from(testContent);
|
|
57
60
|
|
|
58
|
-
|
|
59
|
-
|
|
61
|
+
const result = await service.uploadFileToBackup(buffer, "test.txt");
|
|
62
|
+
t.truthy(result.url);
|
|
60
63
|
|
|
61
|
-
|
|
62
|
-
|
|
64
|
+
// Cleanup
|
|
65
|
+
await service.deleteFileFromBackup(result.url);
|
|
66
|
+
} catch (error) {
|
|
67
|
+
if (error.message === "Backup provider not configured") {
|
|
68
|
+
t.log("Backup provider not configured, skipping test");
|
|
69
|
+
t.pass();
|
|
70
|
+
} else {
|
|
71
|
+
throw error;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
63
74
|
});
|
|
64
75
|
|
|
65
76
|
test("should download file from primary storage", async (t) => {
|
|
@@ -82,32 +93,387 @@ test("should download file from primary storage", async (t) => {
|
|
|
82
93
|
test("should download file from backup storage", async (t) => {
|
|
83
94
|
const factory = new StorageFactory();
|
|
84
95
|
const service = new StorageService(factory);
|
|
85
|
-
const provider = service.getBackupProvider();
|
|
96
|
+
const provider = await service.getBackupProvider();
|
|
86
97
|
if (!provider) {
|
|
87
|
-
t.log("
|
|
98
|
+
t.log("Backup provider not configured, skipping test");
|
|
88
99
|
t.pass();
|
|
89
100
|
return;
|
|
90
101
|
}
|
|
91
|
-
|
|
102
|
+
|
|
103
|
+
try {
|
|
104
|
+
const testContent = "test content";
|
|
105
|
+
const buffer = Buffer.from(testContent);
|
|
106
|
+
|
|
107
|
+
// Upload first
|
|
108
|
+
const uploadResult = await service.uploadFileToBackup(buffer, "test.txt");
|
|
109
|
+
|
|
110
|
+
// Create temp file for download
|
|
111
|
+
const tempFile = path.join(os.tmpdir(), "test-download.txt");
|
|
112
|
+
try {
|
|
113
|
+
// Download
|
|
114
|
+
await service.downloadFileFromBackup(uploadResult.url, tempFile);
|
|
115
|
+
const downloadedContent = await fs.promises.readFile(tempFile);
|
|
116
|
+
t.deepEqual(downloadedContent, buffer);
|
|
117
|
+
|
|
118
|
+
// Cleanup
|
|
119
|
+
await service.deleteFileFromBackup(uploadResult.url);
|
|
120
|
+
} finally {
|
|
121
|
+
// Cleanup temp file
|
|
122
|
+
if (fs.existsSync(tempFile)) {
|
|
123
|
+
fs.unlinkSync(tempFile);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
} catch (error) {
|
|
127
|
+
if (error.message === "Backup provider not configured") {
|
|
128
|
+
t.log("Backup provider not configured, skipping test");
|
|
129
|
+
t.pass();
|
|
130
|
+
} else {
|
|
131
|
+
throw error;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
test("should delete file by hash", async (t) => {
|
|
137
|
+
const factory = new StorageFactory();
|
|
138
|
+
const service = new StorageService(factory);
|
|
139
|
+
const testContent = "test content for hash deletion";
|
|
92
140
|
const buffer = Buffer.from(testContent);
|
|
141
|
+
const testHash = "test-hash-123";
|
|
93
142
|
|
|
94
|
-
|
|
95
|
-
|
|
143
|
+
try {
|
|
144
|
+
// Upload file first
|
|
145
|
+
const uploadResult = await service.uploadFile(buffer, "test-hash-delete.txt");
|
|
146
|
+
t.truthy(uploadResult.url);
|
|
147
|
+
|
|
148
|
+
// Store file info in Redis map
|
|
149
|
+
const fileInfo = {
|
|
150
|
+
url: uploadResult.url,
|
|
151
|
+
filename: "test-hash-delete.txt",
|
|
152
|
+
hash: testHash,
|
|
153
|
+
timestamp: new Date().toISOString()
|
|
154
|
+
};
|
|
155
|
+
await setFileStoreMap(testHash, fileInfo);
|
|
156
|
+
|
|
157
|
+
// Verify file exists in map
|
|
158
|
+
const storedInfo = await getFileStoreMap(testHash);
|
|
159
|
+
t.truthy(storedInfo);
|
|
160
|
+
t.is(storedInfo.url, uploadResult.url);
|
|
161
|
+
|
|
162
|
+
// Delete file by hash
|
|
163
|
+
const deleteResult = await service.deleteFileByHash(testHash);
|
|
164
|
+
t.truthy(deleteResult);
|
|
165
|
+
t.is(deleteResult.hash, testHash);
|
|
166
|
+
t.is(deleteResult.filename, "test-hash-delete.txt");
|
|
167
|
+
t.truthy(deleteResult.deleted);
|
|
168
|
+
t.true(Array.isArray(deleteResult.deleted));
|
|
169
|
+
|
|
170
|
+
// Verify file is removed from Redis map
|
|
171
|
+
const removedInfo = await getFileStoreMap(testHash);
|
|
172
|
+
t.falsy(removedInfo);
|
|
173
|
+
|
|
174
|
+
} catch (error) {
|
|
175
|
+
// Cleanup in case of error
|
|
176
|
+
try {
|
|
177
|
+
await removeFromFileStoreMap(testHash);
|
|
178
|
+
} catch (cleanupError) {
|
|
179
|
+
// Ignore cleanup errors
|
|
180
|
+
}
|
|
181
|
+
throw error;
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
test("should handle delete file by hash when file not found", async (t) => {
|
|
186
|
+
const factory = new StorageFactory();
|
|
187
|
+
const service = new StorageService(factory);
|
|
188
|
+
const nonExistentHash = "non-existent-hash-456";
|
|
189
|
+
|
|
190
|
+
try {
|
|
191
|
+
await service.deleteFileByHash(nonExistentHash);
|
|
192
|
+
t.fail("Should have thrown an error for non-existent hash");
|
|
193
|
+
} catch (error) {
|
|
194
|
+
t.true(error.message.includes("not found"));
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
test("should handle delete file by hash with missing hash parameter", async (t) => {
|
|
199
|
+
const factory = new StorageFactory();
|
|
200
|
+
const service = new StorageService(factory);
|
|
201
|
+
|
|
202
|
+
try {
|
|
203
|
+
await service.deleteFileByHash("");
|
|
204
|
+
t.fail("Should have thrown an error for empty hash");
|
|
205
|
+
} catch (error) {
|
|
206
|
+
t.true(error.message.includes("Missing hash parameter"));
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
try {
|
|
210
|
+
await service.deleteFileByHash(null);
|
|
211
|
+
t.fail("Should have thrown an error for null hash");
|
|
212
|
+
} catch (error) {
|
|
213
|
+
t.true(error.message.includes("Missing hash parameter"));
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
try {
|
|
217
|
+
await service.deleteFileByHash(undefined);
|
|
218
|
+
t.fail("Should have thrown an error for undefined hash");
|
|
219
|
+
} catch (error) {
|
|
220
|
+
t.true(error.message.includes("Missing hash parameter"));
|
|
221
|
+
}
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
test("should delete file by hash with backup storage", async (t) => {
|
|
225
|
+
const factory = new StorageFactory();
|
|
226
|
+
const service = new StorageService(factory);
|
|
227
|
+
const testContent = "test content for backup deletion";
|
|
228
|
+
const buffer = Buffer.from(testContent);
|
|
229
|
+
const testHash = "test-hash-backup-456";
|
|
230
|
+
|
|
231
|
+
try {
|
|
232
|
+
// Upload file first
|
|
233
|
+
const uploadResult = await service.uploadFile(buffer, "test-backup-delete.txt");
|
|
234
|
+
t.truthy(uploadResult.url);
|
|
235
|
+
|
|
236
|
+
// Store file info in Redis map with backup URL
|
|
237
|
+
const fileInfo = {
|
|
238
|
+
url: uploadResult.url,
|
|
239
|
+
gcs: "gs://test-bucket/test-backup-file.txt", // Mock backup URL
|
|
240
|
+
filename: "test-backup-delete.txt",
|
|
241
|
+
hash: testHash,
|
|
242
|
+
timestamp: new Date().toISOString()
|
|
243
|
+
};
|
|
244
|
+
await setFileStoreMap(testHash, fileInfo);
|
|
245
|
+
|
|
246
|
+
// Delete file by hash
|
|
247
|
+
const deleteResult = await service.deleteFileByHash(testHash);
|
|
248
|
+
t.truthy(deleteResult);
|
|
249
|
+
t.is(deleteResult.hash, testHash);
|
|
250
|
+
t.is(deleteResult.filename, "test-backup-delete.txt");
|
|
251
|
+
t.truthy(deleteResult.deleted);
|
|
252
|
+
t.true(Array.isArray(deleteResult.deleted));
|
|
253
|
+
|
|
254
|
+
// Should have attempted both primary and backup deletion
|
|
255
|
+
const deletionResults = deleteResult.deleted;
|
|
256
|
+
t.true(deletionResults.length >= 1, "Should have at least primary deletion result");
|
|
257
|
+
|
|
258
|
+
// Verify file is removed from Redis map
|
|
259
|
+
const removedInfo = await getFileStoreMap(testHash);
|
|
260
|
+
t.falsy(removedInfo);
|
|
261
|
+
|
|
262
|
+
} catch (error) {
|
|
263
|
+
// Cleanup in case of error
|
|
264
|
+
try {
|
|
265
|
+
await removeFromFileStoreMap(testHash);
|
|
266
|
+
} catch (cleanupError) {
|
|
267
|
+
// Ignore cleanup errors
|
|
268
|
+
}
|
|
269
|
+
throw error;
|
|
270
|
+
}
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
test("should handle delete file by hash when Redis map is corrupted", async (t) => {
|
|
274
|
+
const factory = new StorageFactory();
|
|
275
|
+
const service = new StorageService(factory);
|
|
276
|
+
const testHash = "test-hash-corrupted-789";
|
|
277
|
+
|
|
278
|
+
try {
|
|
279
|
+
// Store corrupted data in Redis map
|
|
280
|
+
const corruptedInfo = {
|
|
281
|
+
// Missing required fields like url
|
|
282
|
+
corrupted: true,
|
|
283
|
+
timestamp: new Date().toISOString()
|
|
284
|
+
};
|
|
285
|
+
await setFileStoreMap(testHash, corruptedInfo);
|
|
286
|
+
|
|
287
|
+
// Delete file by hash should handle corrupted data gracefully
|
|
288
|
+
const deleteResult = await service.deleteFileByHash(testHash);
|
|
289
|
+
t.truthy(deleteResult);
|
|
290
|
+
t.is(deleteResult.hash, testHash);
|
|
291
|
+
t.truthy(deleteResult.deleted);
|
|
292
|
+
t.true(Array.isArray(deleteResult.deleted));
|
|
293
|
+
|
|
294
|
+
// Should have removed the corrupted entry from Redis
|
|
295
|
+
const removedInfo = await getFileStoreMap(testHash);
|
|
296
|
+
t.falsy(removedInfo);
|
|
297
|
+
|
|
298
|
+
} catch (error) {
|
|
299
|
+
// Cleanup in case of error
|
|
300
|
+
try {
|
|
301
|
+
await removeFromFileStoreMap(testHash);
|
|
302
|
+
} catch (cleanupError) {
|
|
303
|
+
// Ignore cleanup errors
|
|
304
|
+
}
|
|
305
|
+
throw error;
|
|
306
|
+
}
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
test("should handle delete file by hash with empty URL in Redis", async (t) => {
|
|
310
|
+
const factory = new StorageFactory();
|
|
311
|
+
const service = new StorageService(factory);
|
|
312
|
+
const testHash = "test-hash-empty-url-654";
|
|
96
313
|
|
|
97
|
-
// Create temp file for download
|
|
98
|
-
const tempFile = path.join(os.tmpdir(), "test-download.txt");
|
|
99
314
|
try {
|
|
100
|
-
//
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
315
|
+
// Store file info in Redis map with empty/null URL
|
|
316
|
+
const fileInfo = {
|
|
317
|
+
url: null,
|
|
318
|
+
filename: "test-empty-url-delete.txt",
|
|
319
|
+
hash: testHash,
|
|
320
|
+
timestamp: new Date().toISOString()
|
|
321
|
+
};
|
|
322
|
+
await setFileStoreMap(testHash, fileInfo);
|
|
323
|
+
|
|
324
|
+
// Verify the hash exists in Redis before deletion (skip lazy cleanup)
|
|
325
|
+
const storedInfo = await getFileStoreMap(testHash, true);
|
|
326
|
+
t.truthy(storedInfo, "Hash should exist in Redis before deletion");
|
|
327
|
+
|
|
328
|
+
// Delete file by hash - should handle missing URL gracefully
|
|
329
|
+
const deleteResult = await service.deleteFileByHash(testHash);
|
|
330
|
+
t.truthy(deleteResult);
|
|
331
|
+
t.is(deleteResult.hash, testHash);
|
|
332
|
+
t.is(deleteResult.filename, "test-empty-url-delete.txt");
|
|
333
|
+
t.truthy(deleteResult.deleted);
|
|
334
|
+
t.true(Array.isArray(deleteResult.deleted));
|
|
335
|
+
|
|
336
|
+
// Should still remove from Redis map even if no actual file to delete
|
|
337
|
+
const removedInfo = await getFileStoreMap(testHash);
|
|
338
|
+
t.falsy(removedInfo);
|
|
339
|
+
|
|
340
|
+
} catch (error) {
|
|
341
|
+
// Cleanup in case of error
|
|
342
|
+
try {
|
|
343
|
+
await removeFromFileStoreMap(testHash);
|
|
344
|
+
} catch (cleanupError) {
|
|
345
|
+
// Ignore cleanup errors
|
|
346
|
+
}
|
|
347
|
+
throw error;
|
|
348
|
+
}
|
|
349
|
+
});
|
|
104
350
|
|
|
351
|
+
// Container-specific tests
|
|
352
|
+
test("should upload file with specific container name", async (t) => {
|
|
353
|
+
if (!process.env.AZURE_STORAGE_CONNECTION_STRING) {
|
|
354
|
+
t.pass("Skipping test - Azure not configured");
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
const factory = new StorageFactory();
|
|
359
|
+
const service = new StorageService(factory);
|
|
360
|
+
|
|
361
|
+
// Create a temporary file
|
|
362
|
+
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "test-"));
|
|
363
|
+
const testFile = path.join(tempDir, "test.txt");
|
|
364
|
+
fs.writeFileSync(testFile, "test content");
|
|
365
|
+
|
|
366
|
+
try {
|
|
367
|
+
// Mock environment to have multiple containers
|
|
368
|
+
const originalEnv = process.env.AZURE_STORAGE_CONTAINER_NAME;
|
|
369
|
+
process.env.AZURE_STORAGE_CONTAINER_NAME = "test1,test2,test3";
|
|
370
|
+
|
|
371
|
+
try {
|
|
372
|
+
// Test upload with specific container
|
|
373
|
+
const result = await service.uploadFileWithProviders(
|
|
374
|
+
{ log: () => {} }, // mock context
|
|
375
|
+
testFile,
|
|
376
|
+
"test-request",
|
|
377
|
+
null,
|
|
378
|
+
"test2"
|
|
379
|
+
);
|
|
380
|
+
|
|
381
|
+
t.truthy(result.url);
|
|
382
|
+
t.truthy(result.url.includes("test2") || result.url.includes("/test2/"));
|
|
383
|
+
|
|
384
|
+
// Cleanup
|
|
385
|
+
await service.deleteFiles("test-request");
|
|
386
|
+
} finally {
|
|
387
|
+
// Restore original env
|
|
388
|
+
if (originalEnv) {
|
|
389
|
+
process.env.AZURE_STORAGE_CONTAINER_NAME = originalEnv;
|
|
390
|
+
} else {
|
|
391
|
+
delete process.env.AZURE_STORAGE_CONTAINER_NAME;
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
} finally {
|
|
395
|
+
// Cleanup temp file
|
|
396
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
397
|
+
}
|
|
398
|
+
});
|
|
399
|
+
|
|
400
|
+
test("should use default container when no container specified", async (t) => {
|
|
401
|
+
if (!process.env.AZURE_STORAGE_CONNECTION_STRING) {
|
|
402
|
+
t.pass("Skipping test - Azure not configured");
|
|
403
|
+
return;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
const factory = new StorageFactory();
|
|
407
|
+
const service = new StorageService(factory);
|
|
408
|
+
|
|
409
|
+
// Create a temporary file
|
|
410
|
+
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "test-"));
|
|
411
|
+
const testFile = path.join(tempDir, "test.txt");
|
|
412
|
+
fs.writeFileSync(testFile, "test content");
|
|
413
|
+
|
|
414
|
+
try {
|
|
415
|
+
// Test upload without container (should use default)
|
|
416
|
+
const result = await service.uploadFileWithProviders(
|
|
417
|
+
{ log: () => {} }, // mock context
|
|
418
|
+
testFile,
|
|
419
|
+
"test-request",
|
|
420
|
+
null,
|
|
421
|
+
null // no container specified
|
|
422
|
+
);
|
|
423
|
+
|
|
424
|
+
t.truthy(result.url);
|
|
425
|
+
|
|
105
426
|
// Cleanup
|
|
106
|
-
await service.
|
|
427
|
+
await service.deleteFiles("test-request");
|
|
107
428
|
} finally {
|
|
108
429
|
// Cleanup temp file
|
|
109
|
-
|
|
110
|
-
|
|
430
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
431
|
+
}
|
|
432
|
+
});
|
|
433
|
+
|
|
434
|
+
test("should pass container parameter through uploadFile method", async (t) => {
|
|
435
|
+
if (!process.env.AZURE_STORAGE_CONNECTION_STRING) {
|
|
436
|
+
t.pass("Skipping test - Azure not configured");
|
|
437
|
+
return;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
const factory = new StorageFactory();
|
|
441
|
+
const service = new StorageService(factory);
|
|
442
|
+
|
|
443
|
+
// Create a temporary file
|
|
444
|
+
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "test-"));
|
|
445
|
+
const testFile = path.join(tempDir, "test.txt");
|
|
446
|
+
fs.writeFileSync(testFile, "test content");
|
|
447
|
+
|
|
448
|
+
try {
|
|
449
|
+
// Mock environment to have multiple containers
|
|
450
|
+
const originalEnv = process.env.AZURE_STORAGE_CONTAINER_NAME;
|
|
451
|
+
process.env.AZURE_STORAGE_CONTAINER_NAME = "test1,test2,test3";
|
|
452
|
+
|
|
453
|
+
try {
|
|
454
|
+
// Test upload using the uploadFile method with container parameter
|
|
455
|
+
const result = await service.uploadFile(
|
|
456
|
+
{ log: () => {} }, // context
|
|
457
|
+
testFile, // filePath
|
|
458
|
+
"test-request", // requestId
|
|
459
|
+
null, // hash
|
|
460
|
+
"test3" // containerName
|
|
461
|
+
);
|
|
462
|
+
|
|
463
|
+
t.truthy(result.url);
|
|
464
|
+
|
|
465
|
+
// Cleanup
|
|
466
|
+
await service.deleteFiles("test-request");
|
|
467
|
+
} finally {
|
|
468
|
+
// Restore original env
|
|
469
|
+
if (originalEnv) {
|
|
470
|
+
process.env.AZURE_STORAGE_CONTAINER_NAME = originalEnv;
|
|
471
|
+
} else {
|
|
472
|
+
delete process.env.AZURE_STORAGE_CONTAINER_NAME;
|
|
473
|
+
}
|
|
111
474
|
}
|
|
475
|
+
} finally {
|
|
476
|
+
// Cleanup temp file
|
|
477
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
112
478
|
}
|
|
113
479
|
});
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import axios from "axios";
|
|
2
2
|
import { execSync } from "child_process";
|
|
3
3
|
import fs from "fs/promises";
|
|
4
|
+
import path from "path";
|
|
5
|
+
|
|
6
|
+
import { app, port } from "../src/start.js";
|
|
4
7
|
|
|
5
8
|
export async function cleanupHashAndFile(hash, uploadedUrl, baseUrl) {
|
|
6
9
|
// Only perform hash operations if hash is provided
|
|
@@ -87,3 +90,74 @@ export async function createTestMediaFile(filepath, durationSeconds = 10) {
|
|
|
87
90
|
throw error;
|
|
88
91
|
}
|
|
89
92
|
}
|
|
93
|
+
|
|
94
|
+
// Test server management helpers
|
|
95
|
+
let server;
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Starts the test server and waits for it to be ready
|
|
99
|
+
* @param {Object} options - Optional configuration
|
|
100
|
+
* @param {Function} options.beforeReady - Optional callback to run after server starts but before ready check
|
|
101
|
+
* @returns {Promise<Object>} - Server instance
|
|
102
|
+
*/
|
|
103
|
+
export async function startTestServer(options = {}) {
|
|
104
|
+
if (server) {
|
|
105
|
+
throw new Error("Test server is already running");
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Start the server for tests
|
|
109
|
+
server = app.listen(port, () => {
|
|
110
|
+
console.log(`Test server started on port ${port}`);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
// Wait for server to be ready
|
|
114
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
115
|
+
|
|
116
|
+
// Run any pre-ready setup if provided
|
|
117
|
+
if (options.beforeReady) {
|
|
118
|
+
await options.beforeReady();
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Verify server is responding
|
|
122
|
+
try {
|
|
123
|
+
await axios.get(`http://localhost:${port}/files`);
|
|
124
|
+
} catch (error) {
|
|
125
|
+
// 404 is fine, it means server is running but directory is empty
|
|
126
|
+
if (error.response?.status !== 404) {
|
|
127
|
+
throw new Error("Server not ready");
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return server;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Stops the test server
|
|
136
|
+
* @param {Function} beforeClose - Optional callback to run before closing server
|
|
137
|
+
* @returns {Promise<void>}
|
|
138
|
+
*/
|
|
139
|
+
export async function stopTestServer(beforeClose) {
|
|
140
|
+
if (beforeClose) {
|
|
141
|
+
await beforeClose();
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (server) {
|
|
145
|
+
server.close();
|
|
146
|
+
server = null;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Creates a test directory and sets up context for AVA tests
|
|
152
|
+
* @param {Object} t - AVA test context
|
|
153
|
+
* @param {string} dirName - Optional directory name (defaults to "test-files")
|
|
154
|
+
* @returns {Promise<string>} - Path to created test directory
|
|
155
|
+
*/
|
|
156
|
+
export async function setupTestDirectory(t, dirName = "test-files") {
|
|
157
|
+
const testDir = path.join(process.cwd(), "tests", dirName);
|
|
158
|
+
await fs.mkdir(testDir, { recursive: true });
|
|
159
|
+
if (t && t.context) {
|
|
160
|
+
t.context.testDir = testDir;
|
|
161
|
+
}
|
|
162
|
+
return testDir;
|
|
163
|
+
}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
class CortexResponse {
|
|
2
|
+
constructor({
|
|
3
|
+
output_text = "",
|
|
4
|
+
output = null,
|
|
5
|
+
finishReason = 'stop',
|
|
6
|
+
toolCalls = null,
|
|
7
|
+
functionCall = null,
|
|
8
|
+
citations = null,
|
|
9
|
+
searchQueries = null,
|
|
10
|
+
searchResults = null,
|
|
11
|
+
realTimeData = null,
|
|
12
|
+
artifacts = null,
|
|
13
|
+
usage = null,
|
|
14
|
+
metadata = {},
|
|
15
|
+
error = null
|
|
16
|
+
} = {}) {
|
|
17
|
+
this._output_text = output_text;
|
|
18
|
+
this._output = output;
|
|
19
|
+
this._finishReason = finishReason;
|
|
20
|
+
this._toolCalls = toolCalls;
|
|
21
|
+
this._functionCall = functionCall;
|
|
22
|
+
this._citations = citations;
|
|
23
|
+
this._searchQueries = searchQueries;
|
|
24
|
+
this._searchResults = searchResults;
|
|
25
|
+
this._realTimeData = realTimeData;
|
|
26
|
+
this._artifacts = artifacts;
|
|
27
|
+
this._usage = usage;
|
|
28
|
+
this._metadata = {
|
|
29
|
+
timestamp: new Date().toISOString(),
|
|
30
|
+
...metadata
|
|
31
|
+
};
|
|
32
|
+
this._error = error;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Getters
|
|
36
|
+
get output_text() { return this._output_text; }
|
|
37
|
+
get output() { return this._output; }
|
|
38
|
+
get finishReason() { return this._finishReason; }
|
|
39
|
+
get toolCalls() { return this._toolCalls; }
|
|
40
|
+
get tool_calls() { return this._toolCalls; } // For legacy compatibility
|
|
41
|
+
get functionCall() { return this._functionCall; }
|
|
42
|
+
get citations() { return this._citations; }
|
|
43
|
+
get searchQueries() { return this._searchQueries; }
|
|
44
|
+
get searchResults() { return this._searchResults; }
|
|
45
|
+
get realTimeData() { return this._realTimeData; }
|
|
46
|
+
get artifacts() { return this._artifacts; }
|
|
47
|
+
get usage() { return this._usage; }
|
|
48
|
+
get metadata() { return this._metadata; }
|
|
49
|
+
get error() { return this._error; }
|
|
50
|
+
|
|
51
|
+
// Setters
|
|
52
|
+
set output_text(value) { this._output_text = value; }
|
|
53
|
+
set output(value) { this._output = value; }
|
|
54
|
+
set finishReason(value) { this._finishReason = value; }
|
|
55
|
+
set toolCalls(value) {
|
|
56
|
+
this._toolCalls = value;
|
|
57
|
+
if (value && value.length > 0) {
|
|
58
|
+
this._finishReason = 'tool_calls';
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
set functionCall(value) {
|
|
62
|
+
this._functionCall = value;
|
|
63
|
+
if (value) {
|
|
64
|
+
this._finishReason = 'function_call';
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
set citations(value) { this._citations = value; }
|
|
68
|
+
set searchQueries(value) { this._searchQueries = value; }
|
|
69
|
+
set searchResults(value) { this._searchResults = value; }
|
|
70
|
+
set realTimeData(value) { this._realTimeData = value; }
|
|
71
|
+
set artifacts(value) { this._artifacts = value; }
|
|
72
|
+
set usage(value) { this._usage = value; }
|
|
73
|
+
set metadata(value) { this._metadata = { ...this._metadata, ...value }; }
|
|
74
|
+
set error(value) { this._error = value; }
|
|
75
|
+
|
|
76
|
+
// Utility methods
|
|
77
|
+
hasToolCalls() {
|
|
78
|
+
return this._toolCalls && this._toolCalls.length > 0;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
hasCitations() {
|
|
82
|
+
return this._citations && this._citations.length > 0;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
hasSearchResults() {
|
|
86
|
+
return this._searchResults && this._searchResults.length > 0;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
hasArtifacts() {
|
|
90
|
+
return this._artifacts && this._artifacts.length > 0;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
isError() {
|
|
94
|
+
return this._error !== null;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
hasOutput() {
|
|
98
|
+
return this._output && this._output.length > 0;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
hasOutputText() {
|
|
102
|
+
return this._output_text && this._output_text.length > 0;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Get text content from output array (OpenAI format)
|
|
106
|
+
getTextFromOutput() {
|
|
107
|
+
if (!this._output || !Array.isArray(this._output)) {
|
|
108
|
+
return this._output_text || "";
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Extract text from output items that have text content
|
|
112
|
+
const textItems = this._output
|
|
113
|
+
.filter(item => item && item.text)
|
|
114
|
+
.map(item => item.text);
|
|
115
|
+
|
|
116
|
+
return textItems.join("");
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
// String compatibility methods
|
|
121
|
+
toString() {
|
|
122
|
+
return this._output_text;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
valueOf() {
|
|
126
|
+
return this._output_text;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
toJSON() {
|
|
130
|
+
return this._output_text;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Convert to plain object
|
|
134
|
+
toObject() {
|
|
135
|
+
return {
|
|
136
|
+
output_text: this._output_text,
|
|
137
|
+
output: this._output,
|
|
138
|
+
finishReason: this._finishReason,
|
|
139
|
+
toolCalls: this._toolCalls,
|
|
140
|
+
functionCall: this._functionCall,
|
|
141
|
+
citations: this._citations,
|
|
142
|
+
searchQueries: this._searchQueries,
|
|
143
|
+
searchResults: this._searchResults,
|
|
144
|
+
realTimeData: this._realTimeData,
|
|
145
|
+
artifacts: this._artifacts,
|
|
146
|
+
usage: this._usage,
|
|
147
|
+
metadata: this._metadata,
|
|
148
|
+
error: this._error
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export default CortexResponse;
|