@aj-archipelago/cortex 1.3.55 → 1.3.57

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 (44) hide show
  1. package/.env.sample +3 -1
  2. package/config/default.example.json +2 -2
  3. package/config.js +32 -0
  4. package/helper-apps/mogrt-handler/.env.example +24 -0
  5. package/helper-apps/mogrt-handler/README.md +166 -0
  6. package/helper-apps/mogrt-handler/glossaryHandler.js +218 -0
  7. package/helper-apps/mogrt-handler/index.js +213 -0
  8. package/helper-apps/mogrt-handler/package-lock.json +7106 -0
  9. package/helper-apps/mogrt-handler/package.json +34 -0
  10. package/helper-apps/mogrt-handler/s3Handler.js +444 -0
  11. package/helper-apps/mogrt-handler/start.js +98 -0
  12. package/helper-apps/mogrt-handler/swagger.js +42 -0
  13. package/helper-apps/mogrt-handler/swagger.yaml +436 -0
  14. package/helper-apps/mogrt-handler/tests/integration/api.test.js +226 -0
  15. package/helper-apps/mogrt-handler/tests/integration/glossary.test.js +106 -0
  16. package/helper-apps/mogrt-handler/tests/setup.js +8 -0
  17. package/helper-apps/mogrt-handler/tests/test-files/test.gif +1 -0
  18. package/helper-apps/mogrt-handler/tests/test-files/test.mogrt +1 -0
  19. package/helper-apps/mogrt-handler/tests/test-files/test.mp4 +1 -0
  20. package/helper-apps/mogrt-handler/tests/unit/glossary.unit.test.js +118 -0
  21. package/helper-apps/mogrt-handler/tests/unit/index.test.js +349 -0
  22. package/helper-apps/mogrt-handler/tests/unit/s3Handler.test.js +204 -0
  23. package/helper-apps/mogrt-handler/tests/unit/sample.test.js +28 -0
  24. package/helper-apps/mogrt-handler/vitest.config.js +15 -0
  25. package/lib/entityConstants.js +1 -1
  26. package/lib/requestExecutor.js +1 -1
  27. package/package.json +1 -1
  28. package/pathways/list_translation_models.js +67 -0
  29. package/pathways/system/sys_test_response_reasonableness.js +20 -0
  30. package/pathways/system/workspaces/workspace_applet_edit.js +187 -0
  31. package/pathways/translate_apptek.js +11 -0
  32. package/pathways/translate_google.js +10 -0
  33. package/pathways/translate_groq.js +36 -0
  34. package/pathways/video_seedance.js +17 -0
  35. package/pathways/video_veo.js +31 -0
  36. package/server/modelExecutor.js +16 -0
  37. package/server/plugins/apptekTranslatePlugin.js +189 -0
  38. package/server/plugins/googleTranslatePlugin.js +121 -0
  39. package/server/plugins/groqChatPlugin.js +108 -0
  40. package/server/plugins/replicateApiPlugin.js +22 -0
  41. package/server/plugins/veoVideoPlugin.js +218 -0
  42. package/tests/apptekTranslatePlugin.test.js +228 -0
  43. package/tests/integration/apptekTranslatePlugin.integration.test.js +156 -0
  44. package/tests/translate_apptek.test.js +117 -0
@@ -0,0 +1,436 @@
1
+ openapi: 3.0.0
2
+ info:
3
+ title: MOGRT Handler API
4
+ version: 1.0.0
5
+ description: API for handling MOGRT files and preview GIFs with S3 storage
6
+ servers:
7
+ - url: http://localhost:7072
8
+ description: Development server
9
+
10
+ tags:
11
+ - name: MOGRT Management
12
+ description: Endpoints for managing MOGRT files and manifests
13
+ - name: Glossary Management
14
+ description: Endpoints for managing translation glossaries
15
+ - name: Glossary Versioning
16
+ description: Endpoints for working with glossary versions
17
+
18
+ paths:
19
+ /api/MogrtHandler:
20
+ get:
21
+ tags:
22
+ - MOGRT Management
23
+ summary: Get MOGRT manifest
24
+ parameters:
25
+ - in: query
26
+ name: manifestId
27
+ schema:
28
+ type: string
29
+ description: ID of the manifest to retrieve. If not provided, returns master manifest.
30
+ responses:
31
+ '200':
32
+ description: Returns the requested manifest
33
+ '500':
34
+ description: Server error
35
+ post:
36
+ tags:
37
+ - MOGRT Management
38
+ summary: Upload MOGRT file
39
+ requestBody:
40
+ required: true
41
+ content:
42
+ multipart/form-data:
43
+ schema:
44
+ type: object
45
+ properties:
46
+ file:
47
+ type: string
48
+ format: binary
49
+ description: MOGRT file to upload
50
+ preview:
51
+ type: string
52
+ format: binary
53
+ description: Preview GIF/PNG file
54
+ name:
55
+ type: string
56
+ description: Display name for the MOGRT
57
+ id:
58
+ type: string
59
+ description: Optional ID to use (will be generated if not provided)
60
+ manifestId:
61
+ type: string
62
+ description: Optional manifest ID to add MOGRT to
63
+ responses:
64
+ '200':
65
+ description: MOGRT uploaded successfully
66
+ '400':
67
+ description: Bad request
68
+ '500':
69
+ description: Server error
70
+
71
+ /api/MogrtHandler/{id}:
72
+ delete:
73
+ tags:
74
+ - MOGRT Management
75
+ summary: Delete MOGRT from manifest
76
+ parameters:
77
+ - in: path
78
+ name: id
79
+ schema:
80
+ type: string
81
+ required: true
82
+ description: ID of the MOGRT to delete
83
+ - in: query
84
+ name: manifestId
85
+ schema:
86
+ type: string
87
+ description: Optional manifest ID to delete from (defaults to master)
88
+ responses:
89
+ '200':
90
+ description: MOGRT deleted
91
+ '404':
92
+ description: MOGRT not found
93
+ '500':
94
+ description: Server error
95
+
96
+ /api/glossary/list:
97
+ get:
98
+ tags:
99
+ - Glossary Management
100
+ summary: List all glossaries
101
+ responses:
102
+ '200':
103
+ description: Returns list of glossaries
104
+ content:
105
+ application/json:
106
+ schema:
107
+ type: object
108
+ properties:
109
+ glossaries:
110
+ type: array
111
+ items:
112
+ type: object
113
+ properties:
114
+ id:
115
+ type: string
116
+ name:
117
+ type: string
118
+ source_lang_code:
119
+ type: string
120
+ target_lang_code:
121
+ type: string
122
+ '500':
123
+ description: Server error
124
+
125
+ /api/glossary/{langPair}:
126
+ post:
127
+ tags:
128
+ - Glossary Management
129
+ summary: Create a new glossary
130
+ parameters:
131
+ - in: path
132
+ name: langPair
133
+ schema:
134
+ type: string
135
+ required: true
136
+ description: The language pair in format 'xx-xx' (e.g., 'en-es')
137
+ - in: query
138
+ name: name
139
+ schema:
140
+ type: string
141
+ description: Name of the glossary
142
+ requestBody:
143
+ required: true
144
+ content:
145
+ application/json:
146
+ schema:
147
+ type: object
148
+ required:
149
+ - source_lang_code
150
+ - target_lang_code
151
+ - entries
152
+ properties:
153
+ source_lang_code:
154
+ type: string
155
+ example: en
156
+ target_lang_code:
157
+ type: string
158
+ example: es
159
+ name:
160
+ type: string
161
+ example: My Glossary
162
+ entries:
163
+ type: array
164
+ items:
165
+ type: object
166
+ required:
167
+ - source_text
168
+ - target_text
169
+ properties:
170
+ source_text:
171
+ type: string
172
+ example: hello
173
+ target_text:
174
+ type: string
175
+ example: hola
176
+ responses:
177
+ '200':
178
+ description: Glossary created
179
+ content:
180
+ application/json:
181
+ schema:
182
+ type: object
183
+ properties:
184
+ glossary_id:
185
+ type: string
186
+ version:
187
+ type: object
188
+ properties:
189
+ versionId:
190
+ type: string
191
+ key:
192
+ type: string
193
+ '400':
194
+ description: Bad request
195
+ '500':
196
+ description: Server error
197
+
198
+ /api/glossary/{id}:
199
+ get:
200
+ tags:
201
+ - Glossary Management
202
+ summary: Get a glossary by ID
203
+ parameters:
204
+ - in: path
205
+ name: id
206
+ schema:
207
+ type: string
208
+ required: true
209
+ description: The glossary ID
210
+ responses:
211
+ '200':
212
+ description: Glossary details
213
+ content:
214
+ application/json:
215
+ schema:
216
+ type: object
217
+ properties:
218
+ glossary_id:
219
+ type: string
220
+ name:
221
+ type: string
222
+ source_lang_code:
223
+ type: string
224
+ target_lang_code:
225
+ type: string
226
+ entries:
227
+ type: array
228
+ items:
229
+ type: object
230
+ properties:
231
+ source_text:
232
+ type: string
233
+ target_text:
234
+ type: string
235
+ '404':
236
+ description: Glossary not found
237
+ '500':
238
+ description: Server error
239
+ delete:
240
+ tags:
241
+ - Glossary Management
242
+ summary: Delete a glossary by ID
243
+ parameters:
244
+ - in: path
245
+ name: id
246
+ schema:
247
+ type: string
248
+ required: true
249
+ description: The glossary ID
250
+ responses:
251
+ '200':
252
+ description: Glossary deleted
253
+ '404':
254
+ description: Glossary not found
255
+ '500':
256
+ description: Server error
257
+
258
+ /api/glossary/edit/{id}:
259
+ post:
260
+ tags:
261
+ - Glossary Management
262
+ summary: Edit a glossary by ID (delete and recreate)
263
+ parameters:
264
+ - in: path
265
+ name: id
266
+ schema:
267
+ type: string
268
+ required: true
269
+ description: The glossary ID
270
+ requestBody:
271
+ required: true
272
+ content:
273
+ application/json:
274
+ schema:
275
+ type: object
276
+ required:
277
+ - source_lang_code
278
+ - target_lang_code
279
+ - entries
280
+ properties:
281
+ source_lang_code:
282
+ type: string
283
+ example: en
284
+ target_lang_code:
285
+ type: string
286
+ example: es
287
+ name:
288
+ type: string
289
+ example: My Glossary
290
+ entries:
291
+ type: array
292
+ items:
293
+ type: object
294
+ required:
295
+ - source_text
296
+ - target_text
297
+ properties:
298
+ source_text:
299
+ type: string
300
+ example: hello
301
+ target_text:
302
+ type: string
303
+ example: hola
304
+ responses:
305
+ '200':
306
+ description: Glossary edited
307
+ content:
308
+ application/json:
309
+ schema:
310
+ type: object
311
+ properties:
312
+ glossary_id:
313
+ type: string
314
+ version:
315
+ type: object
316
+ properties:
317
+ versionId:
318
+ type: string
319
+ key:
320
+ type: string
321
+ '400':
322
+ description: Bad request
323
+ '404':
324
+ description: Glossary not found
325
+ '500':
326
+ description: Server error
327
+
328
+ /api/glossary/{langPair}/versions/{glossaryId}:
329
+ get:
330
+ tags:
331
+ - Glossary Versioning
332
+ summary: Get all versions of a glossary
333
+ parameters:
334
+ - in: path
335
+ name: langPair
336
+ schema:
337
+ type: string
338
+ required: true
339
+ description: The language pair in format 'xx-xx' (e.g., 'en-es')
340
+ - in: path
341
+ name: glossaryId
342
+ schema:
343
+ type: string
344
+ required: true
345
+ description: The glossary ID
346
+ - in: query
347
+ name: name
348
+ schema:
349
+ type: string
350
+ description: Optional name of the glossary
351
+ responses:
352
+ '200':
353
+ description: List of glossary versions
354
+ content:
355
+ application/json:
356
+ schema:
357
+ type: object
358
+ properties:
359
+ versions:
360
+ type: array
361
+ items:
362
+ type: object
363
+ properties:
364
+ versionId:
365
+ type: string
366
+ description: S3 version ID
367
+ glossaryId:
368
+ type: string
369
+ description: Glossary ID
370
+ lastModified:
371
+ type: string
372
+ format: date-time
373
+ description: Version creation timestamp
374
+ isLatest:
375
+ type: boolean
376
+ description: Whether this is the latest version
377
+ metadata:
378
+ type: object
379
+ description: Additional metadata
380
+ '500':
381
+ description: Server error
382
+
383
+ /api/glossary/{langPair}/version/{glossaryId}/{versionId}:
384
+ get:
385
+ tags:
386
+ - Glossary Versioning
387
+ summary: Get a specific version of a glossary
388
+ parameters:
389
+ - in: path
390
+ name: langPair
391
+ schema:
392
+ type: string
393
+ required: true
394
+ description: The language pair in format 'xx-xx' (e.g., 'en-es')
395
+ - in: path
396
+ name: glossaryId
397
+ schema:
398
+ type: string
399
+ required: true
400
+ description: The glossary ID
401
+ - in: path
402
+ name: versionId
403
+ schema:
404
+ type: string
405
+ required: true
406
+ description: The S3 version ID
407
+ - in: query
408
+ name: name
409
+ schema:
410
+ type: string
411
+ description: Optional name of the glossary
412
+ responses:
413
+ '200':
414
+ description: Glossary version details
415
+ content:
416
+ application/json:
417
+ schema:
418
+ type: object
419
+ properties:
420
+ versionId:
421
+ type: string
422
+ description: S3 version ID
423
+ glossaryId:
424
+ type: string
425
+ description: Glossary ID
426
+ lastModified:
427
+ type: string
428
+ format: date-time
429
+ description: Version creation timestamp
430
+ metadata:
431
+ type: object
432
+ description: Additional metadata
433
+ '404':
434
+ description: Version not found
435
+ '500':
436
+ description: Server error
@@ -0,0 +1,226 @@
1
+ import { describe, it, expect, beforeAll, beforeEach, afterAll, vi } from 'vitest';
2
+ import request from 'supertest';
3
+ import path from 'path';
4
+ import fs from 'fs';
5
+ import { fileURLToPath } from 'url';
6
+ import express from 'express';
7
+
8
+ // Create mock functions
9
+ const mockSend = vi.fn();
10
+ const mockS3Client = vi.fn();
11
+
12
+ // Mock AWS SDK modules
13
+ vi.mock('@aws-sdk/client-s3', () => {
14
+ mockS3Client.mockImplementation(() => ({ send: mockSend }));
15
+ return {
16
+ S3Client: mockS3Client,
17
+ PutObjectCommand: vi.fn(input => input),
18
+ GetObjectCommand: vi.fn(input => input)
19
+ };
20
+ });
21
+
22
+ vi.mock('@aws-sdk/s3-request-presigner', () => ({
23
+ getSignedUrl: vi.fn(() => Promise.resolve('https://mock-signed-url.com'))
24
+ }));
25
+
26
+ // Mock s3Handler module
27
+ const mockGetManifest = vi.fn();
28
+ const mockUploadToS3 = vi.fn();
29
+ const mockSaveManifest = vi.fn();
30
+
31
+ vi.mock('../../s3Handler.js', () => ({
32
+ getManifest: mockGetManifest,
33
+ uploadToS3: mockUploadToS3,
34
+ saveManifest: mockSaveManifest,
35
+ resetS3Client: vi.fn()
36
+ }));
37
+
38
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
39
+ const TEST_FILES_DIR = path.join(__dirname, '..', 'test-files');
40
+
41
+ // Create test files directory if it doesn't exist
42
+ if (!fs.existsSync(TEST_FILES_DIR)) {
43
+ fs.mkdirSync(TEST_FILES_DIR, { recursive: true });
44
+ }
45
+
46
+ // Create test files
47
+ const TEST_MOGRT_PATH = path.join(TEST_FILES_DIR, 'test.mogrt');
48
+ const TEST_PREVIEW_GIF_PATH = path.join(TEST_FILES_DIR, 'test.gif');
49
+ const TEST_PREVIEW_MP4_PATH = path.join(TEST_FILES_DIR, 'test.mp4');
50
+
51
+ fs.writeFileSync(TEST_MOGRT_PATH, 'test mogrt content');
52
+ fs.writeFileSync(TEST_PREVIEW_GIF_PATH, 'test preview gif content');
53
+ fs.writeFileSync(TEST_PREVIEW_MP4_PATH, 'test preview mp4 content');
54
+
55
+ describe('MOGRT Handler API Integration', () => {
56
+ let app;
57
+
58
+ beforeAll(async () => {
59
+ vi.setTimeout(15000); // Increase timeout for async operations
60
+
61
+ // Create express app
62
+ app = express();
63
+
64
+ // Set test AWS credentials
65
+ process.env.AWS_ACCESS_KEY_ID = 'test-key';
66
+ process.env.AWS_SECRET_ACCESS_KEY = 'test-secret';
67
+ process.env.AWS_REGION = 'us-east-1';
68
+
69
+ // Import and setup the handler
70
+ const { default: MogrtHandler } = await import('../../index.js');
71
+ app.all('/api/MogrtHandler', (req, res) => {
72
+ const context = {
73
+ log: vi.fn(),
74
+ res: {}
75
+ };
76
+
77
+ MogrtHandler(context, req)
78
+ .then(() => {
79
+ res.status(context.res.status || 200).json(context.res.body);
80
+ })
81
+ .catch(err => {
82
+ res.status(500).json({ error: err.message });
83
+ });
84
+ });
85
+ });
86
+
87
+ beforeEach(() => {
88
+ vi.clearAllMocks();
89
+
90
+ // Default successful responses
91
+ mockGetManifest.mockImplementation(async (id) => ({
92
+ id: id === 'master' ? 'test-id' : id,
93
+ mogrtFile: 'test.mogrt',
94
+ previewFile: 'test.gif',
95
+ mogrtUrl: 'signed-url-1',
96
+ previewUrl: 'signed-url-2'
97
+ }));
98
+
99
+ mockUploadToS3.mockImplementation((uploadId, fileData, filename) => {
100
+ return Promise.resolve({
101
+ key: `uploads/${uploadId}/${filename}`,
102
+ location: `https://test-bucket.s3.amazonaws.com/uploads/${uploadId}/${filename}`
103
+ });
104
+ });
105
+
106
+ mockSaveManifest.mockResolvedValue();
107
+ });
108
+
109
+ describe('GET /api/MogrtHandler', () => {
110
+ it('should return master manifest', async () => {
111
+ const response = await request(app)
112
+ .get('/api/MogrtHandler')
113
+ .expect('Content-Type', /json/)
114
+ .expect(200);
115
+
116
+ expect(mockGetManifest).toHaveBeenCalledWith('master');
117
+ expect(response.body).toEqual(expect.objectContaining({
118
+ id: 'test-id',
119
+ mogrtUrl: 'signed-url-1',
120
+ previewUrl: 'signed-url-2'
121
+ }));
122
+ });
123
+
124
+ it('should return specific manifest when manifestId provided', async () => {
125
+ const response = await request(app)
126
+ .get('/api/MogrtHandler?manifestId=specific-id')
127
+ .expect('Content-Type', /json/)
128
+ .expect(200);
129
+
130
+ expect(mockGetManifest).toHaveBeenCalledWith('specific-id');
131
+ expect(response.body).toEqual(expect.objectContaining({
132
+ id: 'specific-id',
133
+ mogrtUrl: 'signed-url-1',
134
+ previewUrl: 'signed-url-2'
135
+ }));
136
+ });
137
+
138
+ it('should handle manifest not found error', async () => {
139
+ const error = new Error('Manifest not found');
140
+ error.name = 'NoSuchKey';
141
+ mockGetManifest.mockRejectedValueOnce(error);
142
+
143
+ const response = await request(app)
144
+ .get('/api/MogrtHandler?manifestId=non-existent')
145
+ .expect('Content-Type', /json/)
146
+ .expect(500);
147
+
148
+ expect(response.body.error).toBe('Manifest not found');
149
+ });
150
+ });
151
+
152
+ describe('POST /api/MogrtHandler', () => {
153
+ test('should upload MOGRT and GIF preview files', async () => {
154
+ mockUploadToS3.mockResolvedValue({ key: 'test-key' });
155
+ mockSaveManifest.mockResolvedValue({});
156
+
157
+ const response = await request(app)
158
+ .post('/api/MogrtHandler')
159
+ .attach('mogrt', TEST_MOGRT_PATH)
160
+ .attach('preview', TEST_PREVIEW_GIF_PATH)
161
+ .expect(200);
162
+
163
+ expect(mockUploadToS3).toHaveBeenCalledTimes(2);
164
+ expect(mockSaveManifest).toHaveBeenCalled();
165
+ });
166
+
167
+ test('should upload MOGRT and MP4 preview files', async () => {
168
+ mockUploadToS3.mockResolvedValue({ key: 'test-key' });
169
+ mockSaveManifest.mockResolvedValue({});
170
+
171
+ const response = await request(app)
172
+ .post('/api/MogrtHandler')
173
+ .attach('mogrt', TEST_MOGRT_PATH)
174
+ .attach('preview', TEST_PREVIEW_MP4_PATH)
175
+ .expect(200);
176
+
177
+ expect(mockUploadToS3).toHaveBeenCalledTimes(2);
178
+ expect(mockSaveManifest).toHaveBeenCalled();
179
+ });
180
+
181
+ test('should reject invalid preview file type', async () => {
182
+ const TEST_INVALID_PATH = path.join(TEST_FILES_DIR, 'test.txt');
183
+ fs.writeFileSync(TEST_INVALID_PATH, 'invalid content');
184
+
185
+ const response = await request(app)
186
+ .post('/api/MogrtHandler')
187
+ .attach('mogrt', TEST_MOGRT_PATH)
188
+ .attach('preview', TEST_INVALID_PATH)
189
+ .expect(400);
190
+
191
+ expect(response.body.error).toContain('Invalid file type');
192
+ fs.unlinkSync(TEST_INVALID_PATH);
193
+ });
194
+
195
+ it('should reject upload with missing files', async () => {
196
+ const response = await request(app)
197
+ .post('/api/MogrtHandler')
198
+ .attach('mogrt', TEST_MOGRT_PATH)
199
+ .expect('Content-Type', /json/)
200
+ .expect(500);
201
+
202
+ expect(response.body.error).toMatch(/required/i);
203
+ });
204
+ });
205
+
206
+ describe('API Documentation', () => {
207
+ test('GET /docs should serve Swagger UI', async () => {
208
+ const response = await request(app)
209
+ .get('/docs')
210
+ .expect('Content-Type', /html/)
211
+ .expect(200);
212
+
213
+ // Swagger UI HTML should contain these key elements
214
+ expect(response.text).toContain('swagger-ui');
215
+ expect(response.text).toContain('MOGRT Handler API');
216
+ });
217
+ });
218
+
219
+ afterAll(() => {
220
+ // Clean up test files
221
+ fs.unlinkSync(TEST_MOGRT_PATH);
222
+ fs.unlinkSync(TEST_PREVIEW_GIF_PATH);
223
+ fs.unlinkSync(TEST_PREVIEW_MP4_PATH);
224
+ fs.rmdirSync(TEST_FILES_DIR);
225
+ });
226
+ });