roe-typescript 0.1.0

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 (45) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +189 -0
  3. package/dist/api/agents.d.ts +87 -0
  4. package/dist/api/agents.js +263 -0
  5. package/dist/auth.d.ts +6 -0
  6. package/dist/auth.js +11 -0
  7. package/dist/client.d.ts +13 -0
  8. package/dist/client.js +18 -0
  9. package/dist/config.d.ts +17 -0
  10. package/dist/config.js +43 -0
  11. package/dist/exceptions.d.ts +25 -0
  12. package/dist/exceptions.js +73 -0
  13. package/dist/index.d.ts +10 -0
  14. package/dist/index.js +9 -0
  15. package/dist/integration_test.js +686 -0
  16. package/dist/models/agent.d.ts +78 -0
  17. package/dist/models/agent.js +40 -0
  18. package/dist/models/file.d.ts +30 -0
  19. package/dist/models/file.js +85 -0
  20. package/dist/models/job.d.ts +37 -0
  21. package/dist/models/job.js +133 -0
  22. package/dist/models/responses.d.ts +71 -0
  23. package/dist/models/responses.js +36 -0
  24. package/dist/models/user.d.ts +6 -0
  25. package/dist/models/user.js +1 -0
  26. package/dist/src/api/agents.js +269 -0
  27. package/dist/src/auth.js +15 -0
  28. package/dist/src/client.js +22 -0
  29. package/dist/src/config.js +47 -0
  30. package/dist/src/exceptions.js +86 -0
  31. package/dist/src/models/agent.js +45 -0
  32. package/dist/src/models/file.js +92 -0
  33. package/dist/src/models/job.js +138 -0
  34. package/dist/src/models/responses.js +42 -0
  35. package/dist/src/models/user.js +2 -0
  36. package/dist/src/utils/fileDetection.js +46 -0
  37. package/dist/src/utils/httpClient.js +236 -0
  38. package/dist/src/utils/pagination.js +18 -0
  39. package/dist/utils/fileDetection.d.ts +11 -0
  40. package/dist/utils/fileDetection.js +38 -0
  41. package/dist/utils/httpClient.d.ts +30 -0
  42. package/dist/utils/httpClient.js +229 -0
  43. package/dist/utils/pagination.d.ts +3 -0
  44. package/dist/utils/pagination.js +14 -0
  45. package/package.json +36 -0
@@ -0,0 +1,686 @@
1
+ #!/usr/bin/env npx ts-node
2
+ "use strict";
3
+ /**
4
+ * Comprehensive integration tests for the Roe TypeScript SDK.
5
+ * Tests identical scenarios to Go and Python SDKs for cross-SDK parity verification.
6
+ *
7
+ * Run with: npx ts-node integration_test.ts
8
+ */
9
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ var desc = Object.getOwnPropertyDescriptor(m, k);
12
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
13
+ desc = { enumerable: true, get: function() { return m[k]; } };
14
+ }
15
+ Object.defineProperty(o, k2, desc);
16
+ }) : (function(o, m, k, k2) {
17
+ if (k2 === undefined) k2 = k;
18
+ o[k2] = m[k];
19
+ }));
20
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
21
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
22
+ }) : function(o, v) {
23
+ o["default"] = v;
24
+ });
25
+ var __importStar = (this && this.__importStar) || (function () {
26
+ var ownKeys = function(o) {
27
+ ownKeys = Object.getOwnPropertyNames || function (o) {
28
+ var ar = [];
29
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
30
+ return ar;
31
+ };
32
+ return ownKeys(o);
33
+ };
34
+ return function (mod) {
35
+ if (mod && mod.__esModule) return mod;
36
+ var result = {};
37
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
38
+ __setModuleDefault(result, mod);
39
+ return result;
40
+ };
41
+ })();
42
+ Object.defineProperty(exports, "__esModule", { value: true });
43
+ const fs = __importStar(require("fs"));
44
+ const https = __importStar(require("https"));
45
+ const http = __importStar(require("http"));
46
+ const path = __importStar(require("path"));
47
+ const os = __importStar(require("os"));
48
+ const client_1 = require("./src/client");
49
+ const config_1 = require("./src/config");
50
+ const file_1 = require("./src/models/file");
51
+ // Helper to get timeout in seconds from config
52
+ const getTimeoutSeconds = (config) => config.timeoutMs / 1000;
53
+ // Test configuration
54
+ const TEST_CONFIG = {
55
+ apiKey: "7jmZWLJO.QvCXpF1v7IhXebQw4TLoW5YFtG89jDJo",
56
+ organizationId: "abfad6df-ee35-4ab0-81ab-89214e9ed900",
57
+ baseUrl: "https://api.test.roe-ai.com",
58
+ samplePdfs: [
59
+ "https://www.uscis.gov/sites/default/files/document/forms/i-9.pdf",
60
+ "https://arxiv.org/pdf/2512.09941",
61
+ "https://arxiv.org/pdf/2512.09933",
62
+ "https://arxiv.org/pdf/2512.09956",
63
+ ],
64
+ sampleUrl: "https://www.roe-ai.com/",
65
+ };
66
+ class TestResults {
67
+ constructor() {
68
+ this.results = {};
69
+ this.errors = [];
70
+ }
71
+ record(testName, result) {
72
+ this.results[testName] = result;
73
+ console.log(` [PASS] ${testName}`);
74
+ }
75
+ recordError(testName, error) {
76
+ this.errors.push([testName, error.message]);
77
+ console.log(` [FAIL] ${testName}: ${error.message}`);
78
+ }
79
+ toJson() {
80
+ return JSON.stringify({
81
+ results: this.results,
82
+ errors: this.errors,
83
+ passed: Object.keys(this.results).length,
84
+ failed: this.errors.length,
85
+ }, null, 2);
86
+ }
87
+ }
88
+ /**
89
+ * Download a PDF from URL to a temp file.
90
+ */
91
+ async function downloadPdf(url, filename) {
92
+ return new Promise((resolve, reject) => {
93
+ const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "roe-test-"));
94
+ const filepath = path.join(tempDir, filename);
95
+ console.log(` Downloading ${url}...`);
96
+ const protocol = url.startsWith("https") ? https : http;
97
+ const file = fs.createWriteStream(filepath);
98
+ const request = protocol.get(url, (response) => {
99
+ // Handle redirects
100
+ if (response.statusCode === 301 || response.statusCode === 302) {
101
+ const redirectUrl = response.headers.location;
102
+ if (redirectUrl) {
103
+ file.close();
104
+ fs.unlinkSync(filepath);
105
+ fs.rmdirSync(tempDir);
106
+ downloadPdf(redirectUrl, filename).then(resolve).catch(reject);
107
+ return;
108
+ }
109
+ }
110
+ response.pipe(file);
111
+ file.on("finish", () => {
112
+ file.close();
113
+ resolve(filepath);
114
+ });
115
+ });
116
+ request.on("error", (err) => {
117
+ fs.unlink(filepath, () => { });
118
+ reject(err);
119
+ });
120
+ });
121
+ }
122
+ /**
123
+ * Cleanup temp file and directory.
124
+ */
125
+ function cleanupFile(filepath) {
126
+ try {
127
+ fs.unlinkSync(filepath);
128
+ fs.rmdirSync(path.dirname(filepath));
129
+ }
130
+ catch {
131
+ // Ignore cleanup errors
132
+ }
133
+ }
134
+ /**
135
+ * Test configuration edge cases - falsy values like timeout=0.
136
+ */
137
+ function testConfigEdgeCases() {
138
+ console.log("\n=== Testing Config Edge Cases ===");
139
+ const results = new TestResults();
140
+ // Test 1: timeout=0 should work (not fall back to default)
141
+ try {
142
+ const config = config_1.RoeConfig.fromEnv({
143
+ apiKey: TEST_CONFIG.apiKey,
144
+ organizationId: TEST_CONFIG.organizationId,
145
+ baseUrl: TEST_CONFIG.baseUrl,
146
+ timeoutSeconds: 0,
147
+ maxRetries: 0,
148
+ });
149
+ // Verify values are actually 0, not defaults
150
+ if (getTimeoutSeconds(config) !== 0) {
151
+ throw new Error(`Expected timeout=0, got ${getTimeoutSeconds(config)}`);
152
+ }
153
+ if (config.maxRetries !== 0) {
154
+ throw new Error(`Expected maxRetries=0, got ${config.maxRetries}`);
155
+ }
156
+ results.record("config_falsy_timeout", {
157
+ timeout: getTimeoutSeconds(config),
158
+ maxRetries: config.maxRetries,
159
+ });
160
+ }
161
+ catch (e) {
162
+ results.recordError("config_falsy_timeout", e);
163
+ }
164
+ // Test 2: Normal config creation
165
+ try {
166
+ const config = config_1.RoeConfig.fromEnv({
167
+ apiKey: TEST_CONFIG.apiKey,
168
+ organizationId: TEST_CONFIG.organizationId,
169
+ baseUrl: TEST_CONFIG.baseUrl,
170
+ });
171
+ if (getTimeoutSeconds(config) !== 60) {
172
+ throw new Error(`Expected default timeout=60, got ${getTimeoutSeconds(config)}`);
173
+ }
174
+ if (config.maxRetries !== 3) {
175
+ throw new Error(`Expected default maxRetries=3, got ${config.maxRetries}`);
176
+ }
177
+ results.record("config_defaults", {
178
+ timeout: getTimeoutSeconds(config),
179
+ maxRetries: config.maxRetries,
180
+ });
181
+ }
182
+ catch (e) {
183
+ results.recordError("config_defaults", e);
184
+ }
185
+ return results;
186
+ }
187
+ /**
188
+ * Test FileUpload from URL functionality.
189
+ */
190
+ async function testFileUploadFromUrl() {
191
+ console.log("\n=== Testing FileUpload from URL ===");
192
+ const results = new TestResults();
193
+ try {
194
+ const pdfPath = await downloadPdf(TEST_CONFIG.samplePdfs[1], "test_upload.pdf");
195
+ // Test FileUpload with file path
196
+ const upload = new file_1.FileUpload({ path: pdfPath });
197
+ if (upload.effectiveFilename !== "test_upload.pdf") {
198
+ throw new Error(`Expected filename 'test_upload.pdf', got '${upload.effectiveFilename}'`);
199
+ }
200
+ if (upload.effectiveMimeType !== "application/pdf") {
201
+ throw new Error(`Expected mimeType 'application/pdf', got '${upload.effectiveMimeType}'`);
202
+ }
203
+ results.record("file_upload_from_path", {
204
+ filename: upload.effectiveFilename,
205
+ mimeType: upload.effectiveMimeType,
206
+ });
207
+ cleanupFile(pdfPath);
208
+ }
209
+ catch (e) {
210
+ results.recordError("file_upload_from_path", e);
211
+ }
212
+ return results;
213
+ }
214
+ /**
215
+ * Test Document Insights (PDF Extraction) agent.
216
+ */
217
+ async function testDocInsightsAgent(client) {
218
+ console.log("\n=== Testing Doc Insights Agent ===");
219
+ const results = new TestResults();
220
+ try {
221
+ // Create a Doc Insights agent
222
+ const agent = await client.agents.create({
223
+ name: "TypeScript SDK Test - Doc Insights",
224
+ engineClassId: "PDFExtractionEngine",
225
+ inputDefinitions: [
226
+ { key: "pdf_files", data_type: "application/pdf", description: "PDF document to analyze" },
227
+ ],
228
+ engineConfig: {
229
+ model: "gpt-4.1-2025-04-14",
230
+ pdf_files: "${pdf_files}",
231
+ instructions: "Extract the document title and list the main sections.",
232
+ output_schema: {
233
+ type: "object",
234
+ properties: {
235
+ title: { type: "string", description: "Document title" },
236
+ sections: { type: "array", items: { type: "string" }, description: "Main sections" },
237
+ },
238
+ },
239
+ },
240
+ });
241
+ results.record("create_doc_insights_agent", { agent_id: agent.id, name: agent.name });
242
+ // Download and run with a PDF
243
+ const pdfPath = await downloadPdf(TEST_CONFIG.samplePdfs[0], "i9_form.pdf");
244
+ try {
245
+ // Run async job
246
+ const job = await client.agents.run({
247
+ agentId: agent.id,
248
+ inputs: { pdf_files: new file_1.FileUpload({ path: pdfPath }) },
249
+ });
250
+ results.record("submit_doc_insights_job", { job_id: job.id });
251
+ // Wait for result
252
+ const result = await job.wait({ timeoutSeconds: 300 });
253
+ results.record("doc_insights_result", {
254
+ agent_id: result.agent_id,
255
+ outputs_count: result.outputs.length,
256
+ has_output: result.outputs.length > 0,
257
+ });
258
+ // Parse and verify output
259
+ if (result.outputs.length > 0) {
260
+ const outputValue = result.outputs[0].value;
261
+ try {
262
+ const parsed = JSON.parse(outputValue);
263
+ results.record("doc_insights_parsed", {
264
+ has_title: "title" in parsed,
265
+ has_sections: "sections" in parsed,
266
+ });
267
+ }
268
+ catch {
269
+ results.record("doc_insights_parsed", { raw_output: outputValue.substring(0, 200) });
270
+ }
271
+ }
272
+ }
273
+ finally {
274
+ cleanupFile(pdfPath);
275
+ }
276
+ // Cleanup: delete the agent
277
+ await client.agents.delete(agent.id);
278
+ results.record("delete_doc_insights_agent", { deleted: true });
279
+ }
280
+ catch (e) {
281
+ results.recordError("doc_insights_agent", e);
282
+ }
283
+ return results;
284
+ }
285
+ /**
286
+ * Test Web Insights (URL Website Extraction) agent.
287
+ */
288
+ async function testWebInsightsAgent(client) {
289
+ console.log("\n=== Testing Web Insights Agent ===");
290
+ const results = new TestResults();
291
+ try {
292
+ // Create a Web Insights agent
293
+ const agent = await client.agents.create({
294
+ name: "TypeScript SDK Test - Web Insights",
295
+ engineClassId: "URLWebsiteExtractionEngine",
296
+ inputDefinitions: [
297
+ { key: "url", data_type: "text/plain", description: "Website URL to analyze" },
298
+ ],
299
+ engineConfig: {
300
+ url: "${url}",
301
+ model: "gpt-4.1-2025-04-14",
302
+ instruction: "Extract the company name and a brief description from this website.",
303
+ vision_mode: false,
304
+ crawl_config: {
305
+ save_html: true,
306
+ save_markdown: true,
307
+ },
308
+ output_schema: {
309
+ type: "object",
310
+ properties: {
311
+ company_name: { type: "string", description: "Company name" },
312
+ description: { type: "string", description: "Brief company description" },
313
+ },
314
+ },
315
+ },
316
+ });
317
+ results.record("create_web_insights_agent", { agent_id: agent.id, name: agent.name });
318
+ // Run with URL
319
+ const job = await client.agents.run({
320
+ agentId: agent.id,
321
+ inputs: { url: TEST_CONFIG.sampleUrl },
322
+ });
323
+ results.record("submit_web_insights_job", { job_id: job.id });
324
+ // Wait for result
325
+ const result = await job.wait({ timeoutSeconds: 300 });
326
+ results.record("web_insights_result", {
327
+ agent_id: result.agent_id,
328
+ outputs_count: result.outputs.length,
329
+ has_output: result.outputs.length > 0,
330
+ });
331
+ // Parse and verify output
332
+ if (result.outputs.length > 0) {
333
+ const outputValue = result.outputs[0].value;
334
+ try {
335
+ const parsed = JSON.parse(outputValue);
336
+ results.record("web_insights_parsed", {
337
+ has_company_name: "company_name" in parsed,
338
+ has_description: "description" in parsed,
339
+ company_name: parsed.company_name ?? "N/A",
340
+ });
341
+ }
342
+ catch {
343
+ results.record("web_insights_parsed", { raw_output: outputValue.substring(0, 200) });
344
+ }
345
+ }
346
+ // Cleanup
347
+ await client.agents.delete(agent.id);
348
+ results.record("delete_web_insights_agent", { deleted: true });
349
+ }
350
+ catch (e) {
351
+ results.recordError("web_insights_agent", e);
352
+ }
353
+ return results;
354
+ }
355
+ /**
356
+ * Test batch job operations with multiple inputs.
357
+ */
358
+ async function testBatchOperations(client) {
359
+ console.log("\n=== Testing Batch Operations ===");
360
+ const results = new TestResults();
361
+ try {
362
+ // Create a simple text extraction agent for batch testing
363
+ const agent = await client.agents.create({
364
+ name: "TypeScript SDK Test - Batch",
365
+ engineClassId: "MultimodalExtractionEngine",
366
+ inputDefinitions: [
367
+ { key: "text", data_type: "text/plain", description: "Text to analyze" },
368
+ ],
369
+ engineConfig: {
370
+ model: "gpt-4.1-2025-04-14",
371
+ text: "${text}",
372
+ instruction: "Count the number of words in this text.",
373
+ output_schema: {
374
+ type: "object",
375
+ properties: {
376
+ word_count: { type: "integer", description: "Number of words" },
377
+ },
378
+ },
379
+ },
380
+ });
381
+ results.record("create_batch_agent", { agent_id: agent.id });
382
+ // Run batch with multiple inputs
383
+ const batchInputs = [
384
+ { text: "Hello world" },
385
+ { text: "This is a longer sentence with more words" },
386
+ { text: "One" },
387
+ ];
388
+ const batch = await client.agents.runMany({
389
+ agentId: agent.id,
390
+ batchInputs,
391
+ });
392
+ results.record("submit_batch_jobs", { job_count: batch.jobs.length });
393
+ // Wait for all results
394
+ const batchResults = await batch.wait({ timeoutSeconds: 300 });
395
+ results.record("batch_results", {
396
+ results_count: batchResults.length,
397
+ all_have_outputs: batchResults.every((r) => r.outputs.length > 0),
398
+ });
399
+ // Cleanup
400
+ await client.agents.delete(agent.id);
401
+ results.record("delete_batch_agent", { deleted: true });
402
+ }
403
+ catch (e) {
404
+ results.recordError("batch_operations", e);
405
+ }
406
+ return results;
407
+ }
408
+ /**
409
+ * Test synchronous job execution.
410
+ */
411
+ async function testSyncExecution(client) {
412
+ console.log("\n=== Testing Sync Execution ===");
413
+ const results = new TestResults();
414
+ try {
415
+ // Create agent
416
+ const agent = await client.agents.create({
417
+ name: "TypeScript SDK Test - Sync",
418
+ engineClassId: "MultimodalExtractionEngine",
419
+ inputDefinitions: [
420
+ { key: "text", data_type: "text/plain", description: "Text input" },
421
+ ],
422
+ engineConfig: {
423
+ model: "gpt-4.1-2025-04-14",
424
+ text: "${text}",
425
+ instruction: "Echo back the input text.",
426
+ output_schema: {
427
+ type: "object",
428
+ properties: {
429
+ echo: { type: "string" },
430
+ },
431
+ },
432
+ },
433
+ });
434
+ results.record("create_sync_agent", { agent_id: agent.id });
435
+ // Run synchronously
436
+ const outputs = await client.agents.runSync(agent.id, { text: "Test input for sync" });
437
+ results.record("sync_execution", {
438
+ outputs_count: outputs.length,
439
+ has_output: outputs.length > 0,
440
+ });
441
+ // Cleanup
442
+ await client.agents.delete(agent.id);
443
+ results.record("delete_sync_agent", { deleted: true });
444
+ }
445
+ catch (e) {
446
+ results.recordError("sync_execution", e);
447
+ }
448
+ return results;
449
+ }
450
+ /**
451
+ * Test agent version management.
452
+ */
453
+ async function testVersionManagement(client) {
454
+ console.log("\n=== Testing Version Management ===");
455
+ const results = new TestResults();
456
+ try {
457
+ // Create agent
458
+ const agent = await client.agents.create({
459
+ name: "TypeScript SDK Test - Versions",
460
+ engineClassId: "MultimodalExtractionEngine",
461
+ inputDefinitions: [
462
+ { key: "text", data_type: "text/plain", description: "Text" },
463
+ ],
464
+ engineConfig: {
465
+ model: "gpt-4.1-2025-04-14",
466
+ text: "${text}",
467
+ instruction: "Version 1 instruction",
468
+ output_schema: { type: "object", properties: { result: { type: "string" } } },
469
+ },
470
+ versionName: "v1",
471
+ });
472
+ results.record("create_versioned_agent", { agent_id: agent.id });
473
+ // List versions
474
+ const versions = await client.agents.versions.list(agent.id);
475
+ results.record("list_versions", { version_count: versions.length });
476
+ // Get current version
477
+ const current = await client.agents.versions.retrieveCurrent(agent.id);
478
+ results.record("current_version", { version_id: current.id, version_name: current.version_name });
479
+ // Create new version
480
+ const v2 = await client.agents.versions.create({
481
+ agentId: agent.id,
482
+ versionName: "v2",
483
+ engineConfig: {
484
+ model: "gpt-4.1-2025-04-14",
485
+ text: "${text}",
486
+ instruction: "Version 2 instruction - updated",
487
+ output_schema: { type: "object", properties: { result: { type: "string" } } },
488
+ },
489
+ });
490
+ results.record("create_version_v2", { version_id: v2.id, version_name: v2.version_name });
491
+ // Run specific version
492
+ const job = await client.agents.runVersion({
493
+ agentId: agent.id,
494
+ versionId: v2.id,
495
+ inputs: { text: "Test" },
496
+ });
497
+ const versionResult = await job.wait({ timeoutSeconds: 120 });
498
+ results.record("run_specific_version", {
499
+ job_id: job.id,
500
+ has_output: versionResult.outputs.length > 0,
501
+ });
502
+ // Cleanup
503
+ await client.agents.delete(agent.id);
504
+ results.record("delete_versioned_agent", { deleted: true });
505
+ }
506
+ catch (e) {
507
+ results.recordError("version_management", e);
508
+ }
509
+ return results;
510
+ }
511
+ /**
512
+ * Test job status and result retrieval.
513
+ */
514
+ async function testJobManagement(client) {
515
+ console.log("\n=== Testing Job Management ===");
516
+ const results = new TestResults();
517
+ try {
518
+ // Create agent
519
+ const agent = await client.agents.create({
520
+ name: "TypeScript SDK Test - Jobs",
521
+ engineClassId: "MultimodalExtractionEngine",
522
+ inputDefinitions: [
523
+ { key: "text", data_type: "text/plain", description: "Text" },
524
+ ],
525
+ engineConfig: {
526
+ model: "gpt-4.1-2025-04-14",
527
+ text: "${text}",
528
+ instruction: "Analyze this text.",
529
+ output_schema: { type: "object", properties: { analysis: { type: "string" } } },
530
+ },
531
+ });
532
+ // Submit job
533
+ const job = await client.agents.run({
534
+ agentId: agent.id,
535
+ inputs: { text: "Test for job management" },
536
+ });
537
+ results.record("submit_job", { job_id: job.id });
538
+ // Check status
539
+ const status = await client.agents.jobs.retrieveStatus(job.id);
540
+ results.record("job_status", { status: status.status });
541
+ // Wait and get result
542
+ const result = await job.wait({ timeoutSeconds: 120 });
543
+ results.record("job_result", {
544
+ agent_id: result.agent_id,
545
+ has_outputs: result.outputs.length > 0,
546
+ });
547
+ // Retrieve result separately
548
+ const retrievedResult = await client.agents.jobs.retrieveResult(job.id);
549
+ results.record("retrieved_result", {
550
+ matches: retrievedResult.agent_id === result.agent_id,
551
+ });
552
+ // Cleanup
553
+ await client.agents.delete(agent.id);
554
+ }
555
+ catch (e) {
556
+ results.recordError("job_management", e);
557
+ }
558
+ return results;
559
+ }
560
+ /**
561
+ * Test uploading multiple different PDFs.
562
+ */
563
+ async function testMultiplePdfUploads(client) {
564
+ console.log("\n=== Testing Multiple PDF Uploads ===");
565
+ const results = new TestResults();
566
+ try {
567
+ // Create agent
568
+ const agent = await client.agents.create({
569
+ name: "TypeScript SDK Test - Multi PDF",
570
+ engineClassId: "PDFExtractionEngine",
571
+ inputDefinitions: [
572
+ { key: "pdf_files", data_type: "application/pdf", description: "PDF" },
573
+ ],
574
+ engineConfig: {
575
+ model: "gpt-4.1-2025-04-14",
576
+ pdf_files: "${pdf_files}",
577
+ instructions: "What is the title or main topic of this document?",
578
+ output_schema: {
579
+ type: "object",
580
+ properties: {
581
+ title: { type: "string" },
582
+ },
583
+ },
584
+ },
585
+ });
586
+ results.record("create_multi_pdf_agent", { agent_id: agent.id });
587
+ // Test with multiple PDFs (arxiv papers)
588
+ const pdfUrls = TEST_CONFIG.samplePdfs.slice(1, 4);
589
+ for (let i = 0; i < pdfUrls.length; i++) {
590
+ const pdfUrl = pdfUrls[i];
591
+ const pdfPath = await downloadPdf(pdfUrl, `arxiv_${i}.pdf`);
592
+ try {
593
+ const job = await client.agents.run({
594
+ agentId: agent.id,
595
+ inputs: { pdf_files: new file_1.FileUpload({ path: pdfPath }) },
596
+ });
597
+ const pdfResult = await job.wait({ timeoutSeconds: 300 });
598
+ results.record(`pdf_upload_${i}`, {
599
+ url: pdfUrl,
600
+ job_id: job.id,
601
+ has_output: pdfResult.outputs.length > 0,
602
+ });
603
+ }
604
+ finally {
605
+ cleanupFile(pdfPath);
606
+ }
607
+ }
608
+ // Cleanup
609
+ await client.agents.delete(agent.id);
610
+ results.record("delete_multi_pdf_agent", { deleted: true });
611
+ }
612
+ catch (e) {
613
+ results.recordError("multiple_pdf_uploads", e);
614
+ }
615
+ return results;
616
+ }
617
+ /**
618
+ * Main test runner.
619
+ */
620
+ async function main() {
621
+ console.log("=".repeat(60));
622
+ console.log("ROE TYPESCRIPT SDK INTEGRATION TESTS");
623
+ console.log("=".repeat(60));
624
+ console.log(`Base URL: ${TEST_CONFIG.baseUrl}`);
625
+ console.log(`Organization ID: ${TEST_CONFIG.organizationId}`);
626
+ // Create client
627
+ const client = new client_1.RoeClient({
628
+ apiKey: TEST_CONFIG.apiKey,
629
+ organizationId: TEST_CONFIG.organizationId,
630
+ baseUrl: TEST_CONFIG.baseUrl,
631
+ });
632
+ const allResults = {};
633
+ // Run all test suites
634
+ const testSuites = [
635
+ ["config_edge_cases", () => testConfigEdgeCases()],
636
+ ["file_upload_from_url", () => testFileUploadFromUrl()],
637
+ ["doc_insights_agent", () => testDocInsightsAgent(client)],
638
+ ["web_insights_agent", () => testWebInsightsAgent(client)],
639
+ ["batch_operations", () => testBatchOperations(client)],
640
+ ["sync_execution", () => testSyncExecution(client)],
641
+ ["version_management", () => testVersionManagement(client)],
642
+ ["job_management", () => testJobManagement(client)],
643
+ ["multiple_pdf_uploads", () => testMultiplePdfUploads(client)],
644
+ ];
645
+ for (const [suiteName, testFunc] of testSuites) {
646
+ try {
647
+ const result = await testFunc();
648
+ allResults[suiteName] = result.results;
649
+ if (result.errors.length > 0) {
650
+ allResults[`${suiteName}_errors`] = result.errors;
651
+ }
652
+ }
653
+ catch (e) {
654
+ allResults[suiteName] = { error: e.message };
655
+ console.log(` [FATAL] ${suiteName}: ${e.message}`);
656
+ }
657
+ }
658
+ // Summary
659
+ console.log("\n" + "=".repeat(60));
660
+ console.log("TEST SUMMARY");
661
+ console.log("=".repeat(60));
662
+ let totalPassed = 0;
663
+ let totalFailed = 0;
664
+ for (const [key, value] of Object.entries(allResults)) {
665
+ if (!key.endsWith("_errors") && typeof value === "object" && value !== null) {
666
+ totalPassed += Object.keys(value).length;
667
+ }
668
+ if (key.endsWith("_errors") && Array.isArray(value)) {
669
+ totalFailed += value.length;
670
+ }
671
+ }
672
+ console.log(`Total passed: ${totalPassed}`);
673
+ console.log(`Total failed: ${totalFailed}`);
674
+ // Save results for comparison
675
+ const outputFile = "typescript_test_results.json";
676
+ fs.writeFileSync(outputFile, JSON.stringify(allResults, null, 2));
677
+ console.log(`\nResults saved to: ${outputFile}`);
678
+ return totalFailed === 0 ? 0 : 1;
679
+ }
680
+ // Run main
681
+ main()
682
+ .then((code) => process.exit(code))
683
+ .catch((err) => {
684
+ console.error("Fatal error:", err);
685
+ process.exit(1);
686
+ });