@trainly/react 1.1.3 → 1.3.1

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.
@@ -389,8 +389,176 @@ export function TrainlyProvider(_a) {
389
389
  }
390
390
  });
391
391
  }); };
392
+ var bulkUploadFiles = function (files) { return __awaiter(_this, void 0, void 0, function () {
393
+ var result, err_6, errorMessage, newToken, result, refreshError_3, error_6;
394
+ return __generator(this, function (_a) {
395
+ switch (_a.label) {
396
+ case 0:
397
+ _a.trys.push([0, 2, 10, 11]);
398
+ setIsLoading(true);
399
+ setError(null);
400
+ return [4 /*yield*/, client.bulkUploadFiles(files)];
401
+ case 1:
402
+ result = _a.sent();
403
+ return [2 /*return*/, result];
404
+ case 2:
405
+ err_6 = _a.sent();
406
+ errorMessage = err_6 instanceof Error ? err_6.message : String(err_6);
407
+ if (!(getToken &&
408
+ appId &&
409
+ (errorMessage.includes("401") ||
410
+ errorMessage.includes("authentication") ||
411
+ errorMessage.includes("Unauthorized")))) return [3 /*break*/, 9];
412
+ _a.label = 3;
413
+ case 3:
414
+ _a.trys.push([3, 8, , 9]);
415
+ console.log("🔄 Token expired during bulk upload, refreshing...");
416
+ return [4 /*yield*/, getToken()];
417
+ case 4:
418
+ newToken = _a.sent();
419
+ if (!newToken) return [3 /*break*/, 7];
420
+ return [4 /*yield*/, client.connectWithOAuthToken(newToken)];
421
+ case 5:
422
+ _a.sent();
423
+ return [4 /*yield*/, client.bulkUploadFiles(files)];
424
+ case 6:
425
+ result = _a.sent();
426
+ console.log("✅ Bulk upload succeeded after token refresh");
427
+ return [2 /*return*/, result];
428
+ case 7: return [3 /*break*/, 9];
429
+ case 8:
430
+ refreshError_3 = _a.sent();
431
+ console.error("❌ Token refresh failed during bulk upload:", refreshError_3);
432
+ return [3 /*break*/, 9];
433
+ case 9:
434
+ error_6 = {
435
+ code: "BULK_UPLOAD_FAILED",
436
+ message: "Failed to upload files",
437
+ details: err_6,
438
+ };
439
+ setError(error_6);
440
+ throw error_6;
441
+ case 10:
442
+ setIsLoading(false);
443
+ return [7 /*endfinally*/];
444
+ case 11: return [2 /*return*/];
445
+ }
446
+ });
447
+ }); };
448
+ var listFiles = function () { return __awaiter(_this, void 0, void 0, function () {
449
+ var result, err_7, errorMessage, newToken, result, refreshError_4, error_7;
450
+ return __generator(this, function (_a) {
451
+ switch (_a.label) {
452
+ case 0:
453
+ _a.trys.push([0, 2, 10, 11]);
454
+ setIsLoading(true);
455
+ setError(null);
456
+ return [4 /*yield*/, client.listFiles()];
457
+ case 1:
458
+ result = _a.sent();
459
+ return [2 /*return*/, result];
460
+ case 2:
461
+ err_7 = _a.sent();
462
+ errorMessage = err_7 instanceof Error ? err_7.message : String(err_7);
463
+ if (!(getToken &&
464
+ appId &&
465
+ (errorMessage.includes("401") ||
466
+ errorMessage.includes("authentication") ||
467
+ errorMessage.includes("Unauthorized")))) return [3 /*break*/, 9];
468
+ _a.label = 3;
469
+ case 3:
470
+ _a.trys.push([3, 8, , 9]);
471
+ console.log("🔄 Token expired during file listing, refreshing...");
472
+ return [4 /*yield*/, getToken()];
473
+ case 4:
474
+ newToken = _a.sent();
475
+ if (!newToken) return [3 /*break*/, 7];
476
+ return [4 /*yield*/, client.connectWithOAuthToken(newToken)];
477
+ case 5:
478
+ _a.sent();
479
+ return [4 /*yield*/, client.listFiles()];
480
+ case 6:
481
+ result = _a.sent();
482
+ console.log("✅ File listing succeeded after token refresh");
483
+ return [2 /*return*/, result];
484
+ case 7: return [3 /*break*/, 9];
485
+ case 8:
486
+ refreshError_4 = _a.sent();
487
+ console.error("❌ Token refresh failed:", refreshError_4);
488
+ return [3 /*break*/, 9];
489
+ case 9:
490
+ error_7 = {
491
+ code: "LIST_FILES_FAILED",
492
+ message: "Failed to list files",
493
+ details: err_7,
494
+ };
495
+ setError(error_7);
496
+ throw error_7;
497
+ case 10:
498
+ setIsLoading(false);
499
+ return [7 /*endfinally*/];
500
+ case 11: return [2 /*return*/];
501
+ }
502
+ });
503
+ }); };
504
+ var deleteFile = function (fileId) { return __awaiter(_this, void 0, void 0, function () {
505
+ var result, err_8, errorMessage, newToken, result, refreshError_5, error_8;
506
+ return __generator(this, function (_a) {
507
+ switch (_a.label) {
508
+ case 0:
509
+ _a.trys.push([0, 2, 10, 11]);
510
+ setIsLoading(true);
511
+ setError(null);
512
+ return [4 /*yield*/, client.deleteFile(fileId)];
513
+ case 1:
514
+ result = _a.sent();
515
+ return [2 /*return*/, result];
516
+ case 2:
517
+ err_8 = _a.sent();
518
+ errorMessage = err_8 instanceof Error ? err_8.message : String(err_8);
519
+ if (!(getToken &&
520
+ appId &&
521
+ (errorMessage.includes("401") ||
522
+ errorMessage.includes("authentication") ||
523
+ errorMessage.includes("Unauthorized")))) return [3 /*break*/, 9];
524
+ _a.label = 3;
525
+ case 3:
526
+ _a.trys.push([3, 8, , 9]);
527
+ console.log("🔄 Token expired during file deletion, refreshing...");
528
+ return [4 /*yield*/, getToken()];
529
+ case 4:
530
+ newToken = _a.sent();
531
+ if (!newToken) return [3 /*break*/, 7];
532
+ return [4 /*yield*/, client.connectWithOAuthToken(newToken)];
533
+ case 5:
534
+ _a.sent();
535
+ return [4 /*yield*/, client.deleteFile(fileId)];
536
+ case 6:
537
+ result = _a.sent();
538
+ console.log("✅ File deletion succeeded after token refresh");
539
+ return [2 /*return*/, result];
540
+ case 7: return [3 /*break*/, 9];
541
+ case 8:
542
+ refreshError_5 = _a.sent();
543
+ console.error("❌ Token refresh failed:", refreshError_5);
544
+ return [3 /*break*/, 9];
545
+ case 9:
546
+ error_8 = {
547
+ code: "DELETE_FILE_FAILED",
548
+ message: "Failed to delete file",
549
+ details: err_8,
550
+ };
551
+ setError(error_8);
552
+ throw error_8;
553
+ case 10:
554
+ setIsLoading(false);
555
+ return [7 /*endfinally*/];
556
+ case 11: return [2 /*return*/];
557
+ }
558
+ });
559
+ }); };
392
560
  var sendMessage = function (content) { return __awaiter(_this, void 0, void 0, function () {
393
- var userMessage, response, assistantMessage_1, err_6;
561
+ var userMessage, response, assistantMessage_1, err_9;
394
562
  return __generator(this, function (_a) {
395
563
  switch (_a.label) {
396
564
  case 0:
@@ -417,9 +585,9 @@ export function TrainlyProvider(_a) {
417
585
  setMessages(function (prev) { return __spreadArray(__spreadArray([], prev, true), [assistantMessage_1], false); });
418
586
  return [3 /*break*/, 4];
419
587
  case 3:
420
- err_6 = _a.sent();
588
+ err_9 = _a.sent();
421
589
  // Error is already set by askWithCitations
422
- console.error("Failed to send message:", err_6);
590
+ console.error("Failed to send message:", err_9);
423
591
  return [3 /*break*/, 4];
424
592
  case 4: return [2 /*return*/];
425
593
  }
@@ -432,6 +600,9 @@ export function TrainlyProvider(_a) {
432
600
  ask: ask,
433
601
  askWithCitations: askWithCitations,
434
602
  upload: upload,
603
+ bulkUploadFiles: bulkUploadFiles, // NEW: Bulk file upload method
604
+ listFiles: listFiles, // NEW: File management methods
605
+ deleteFile: deleteFile,
435
606
  connectWithOAuthToken: connectWithOAuthToken, // NEW: V1 OAuth connection method
436
607
  isLoading: isLoading,
437
608
  isConnected: isConnected,
@@ -1,4 +1,4 @@
1
- import { TrainlyConfig, Citation, UploadResult } from "../types";
1
+ import { TrainlyConfig, Citation, UploadResult, FileListResult, FileDeleteResult, BulkUploadResult } from "../types";
2
2
  interface QueryResponse {
3
3
  answer: string;
4
4
  citations?: Citation[];
@@ -19,6 +19,9 @@ export declare class TrainlyClient {
19
19
  includeCitations?: boolean;
20
20
  }): Promise<QueryResponse>;
21
21
  upload(file: File): Promise<UploadResult>;
22
+ bulkUploadFiles(files: File[]): Promise<BulkUploadResult>;
23
+ listFiles(): Promise<FileListResult>;
24
+ deleteFile(fileId: string): Promise<FileDeleteResult>;
22
25
  private extractChatId;
23
26
  private generateAnonymousId;
24
27
  }
@@ -324,6 +324,189 @@ var TrainlyClient = /** @class */ (function () {
324
324
  });
325
325
  });
326
326
  };
327
+ TrainlyClient.prototype.bulkUploadFiles = function (files) {
328
+ return __awaiter(this, void 0, void 0, function () {
329
+ var formData_1, response, error, data, results, successful_uploads, total_size_bytes, _i, files_1, file, uploadResult, error_1;
330
+ return __generator(this, function (_a) {
331
+ switch (_a.label) {
332
+ case 0:
333
+ if (!this.scopedToken) {
334
+ throw new Error("Not connected. Call connect() or connectWithOAuthToken() first.");
335
+ }
336
+ if (!files || files.length === 0) {
337
+ throw new Error("No files provided for bulk upload.");
338
+ }
339
+ if (files.length > 10) {
340
+ throw new Error("Too many files. Maximum 10 files per bulk upload.");
341
+ }
342
+ if (!(this.isV1Mode && this.config.appId)) return [3 /*break*/, 5];
343
+ formData_1 = new FormData();
344
+ // Append all files to the form data
345
+ files.forEach(function (file) {
346
+ formData_1.append("files", file);
347
+ });
348
+ return [4 /*yield*/, fetch("".concat(this.config.baseUrl, "/v1/me/chats/files/upload-bulk"), {
349
+ method: "POST",
350
+ headers: {
351
+ Authorization: "Bearer ".concat(this.scopedToken),
352
+ "X-App-ID": this.config.appId,
353
+ },
354
+ body: formData_1,
355
+ })];
356
+ case 1:
357
+ response = _a.sent();
358
+ if (!!response.ok) return [3 /*break*/, 3];
359
+ return [4 /*yield*/, response.json()];
360
+ case 2:
361
+ error = _a.sent();
362
+ throw new Error("V1 bulk upload failed: ".concat(error.detail || response.statusText));
363
+ case 3: return [4 /*yield*/, response.json()];
364
+ case 4:
365
+ data = _a.sent();
366
+ return [2 /*return*/, {
367
+ success: data.success,
368
+ total_files: data.total_files,
369
+ successful_uploads: data.successful_uploads,
370
+ failed_uploads: data.failed_uploads,
371
+ total_size_bytes: data.total_size_bytes,
372
+ chat_id: data.chat_id,
373
+ user_id: data.user_id,
374
+ results: data.results,
375
+ message: data.message,
376
+ }];
377
+ case 5:
378
+ results = [];
379
+ successful_uploads = 0;
380
+ total_size_bytes = 0;
381
+ _i = 0, files_1 = files;
382
+ _a.label = 6;
383
+ case 6:
384
+ if (!(_i < files_1.length)) return [3 /*break*/, 11];
385
+ file = files_1[_i];
386
+ _a.label = 7;
387
+ case 7:
388
+ _a.trys.push([7, 9, , 10]);
389
+ return [4 /*yield*/, this.upload(file)];
390
+ case 8:
391
+ uploadResult = _a.sent();
392
+ results.push({
393
+ filename: uploadResult.filename,
394
+ success: uploadResult.success,
395
+ error: null,
396
+ file_id: null, // Single upload doesn't return file_id
397
+ size_bytes: uploadResult.size,
398
+ processing_status: uploadResult.success ? "completed" : "failed",
399
+ message: uploadResult.message,
400
+ });
401
+ if (uploadResult.success) {
402
+ successful_uploads++;
403
+ total_size_bytes += uploadResult.size;
404
+ }
405
+ return [3 /*break*/, 10];
406
+ case 9:
407
+ error_1 = _a.sent();
408
+ results.push({
409
+ filename: file.name,
410
+ success: false,
411
+ error: error_1 instanceof Error ? error_1.message : String(error_1),
412
+ file_id: null,
413
+ size_bytes: file.size,
414
+ processing_status: "failed",
415
+ });
416
+ return [3 /*break*/, 10];
417
+ case 10:
418
+ _i++;
419
+ return [3 /*break*/, 6];
420
+ case 11: return [2 /*return*/, {
421
+ success: successful_uploads > 0,
422
+ total_files: files.length,
423
+ successful_uploads: successful_uploads,
424
+ failed_uploads: files.length - successful_uploads,
425
+ total_size_bytes: total_size_bytes,
426
+ chat_id: this.currentUserId || "",
427
+ user_id: this.currentUserId || "",
428
+ results: results,
429
+ message: "Bulk upload completed: ".concat(successful_uploads, "/").concat(files.length, " files processed successfully"),
430
+ }];
431
+ }
432
+ });
433
+ });
434
+ };
435
+ TrainlyClient.prototype.listFiles = function () {
436
+ return __awaiter(this, void 0, void 0, function () {
437
+ var response, error, data;
438
+ return __generator(this, function (_a) {
439
+ switch (_a.label) {
440
+ case 0:
441
+ if (!this.scopedToken) {
442
+ throw new Error("Not connected. Call connect() or connectWithOAuthToken() first.");
443
+ }
444
+ if (!(this.isV1Mode && this.config.appId)) return [3 /*break*/, 5];
445
+ return [4 /*yield*/, fetch("".concat(this.config.baseUrl, "/v1/me/chats/files"), {
446
+ method: "GET",
447
+ headers: {
448
+ Authorization: "Bearer ".concat(this.scopedToken),
449
+ "X-App-ID": this.config.appId,
450
+ },
451
+ })];
452
+ case 1:
453
+ response = _a.sent();
454
+ if (!!response.ok) return [3 /*break*/, 3];
455
+ return [4 /*yield*/, response.json()];
456
+ case 2:
457
+ error = _a.sent();
458
+ throw new Error("V1 list files failed: ".concat(error.detail || response.statusText));
459
+ case 3: return [4 /*yield*/, response.json()];
460
+ case 4:
461
+ data = _a.sent();
462
+ return [2 /*return*/, data];
463
+ case 5:
464
+ // For other modes, this functionality is not yet implemented
465
+ // as it requires chat-specific API endpoints
466
+ throw new Error("File listing is currently only available in V1 Trusted Issuer mode");
467
+ }
468
+ });
469
+ });
470
+ };
471
+ TrainlyClient.prototype.deleteFile = function (fileId) {
472
+ return __awaiter(this, void 0, void 0, function () {
473
+ var response, error, data;
474
+ return __generator(this, function (_a) {
475
+ switch (_a.label) {
476
+ case 0:
477
+ if (!this.scopedToken) {
478
+ throw new Error("Not connected. Call connect() or connectWithOAuthToken() first.");
479
+ }
480
+ if (!fileId) {
481
+ throw new Error("File ID is required");
482
+ }
483
+ if (!(this.isV1Mode && this.config.appId)) return [3 /*break*/, 5];
484
+ return [4 /*yield*/, fetch("".concat(this.config.baseUrl, "/v1/me/chats/files/").concat(encodeURIComponent(fileId)), {
485
+ method: "DELETE",
486
+ headers: {
487
+ Authorization: "Bearer ".concat(this.scopedToken),
488
+ "X-App-ID": this.config.appId,
489
+ },
490
+ })];
491
+ case 1:
492
+ response = _a.sent();
493
+ if (!!response.ok) return [3 /*break*/, 3];
494
+ return [4 /*yield*/, response.json()];
495
+ case 2:
496
+ error = _a.sent();
497
+ throw new Error("V1 delete file failed: ".concat(error.detail || response.statusText));
498
+ case 3: return [4 /*yield*/, response.json()];
499
+ case 4:
500
+ data = _a.sent();
501
+ return [2 /*return*/, data];
502
+ case 5:
503
+ // For other modes, this functionality is not yet implemented
504
+ // as it requires chat-specific API endpoints
505
+ throw new Error("File deletion is currently only available in V1 Trusted Issuer mode");
506
+ }
507
+ });
508
+ });
509
+ };
327
510
  TrainlyClient.prototype.extractChatId = function () {
328
511
  if (!this.config.apiKey) {
329
512
  throw new Error("API key not provided");
@@ -0,0 +1,8 @@
1
+ export interface TrainlyFileManagerProps {
2
+ className?: string;
3
+ onFileDeleted?: (fileId: string, filename: string) => void;
4
+ onError?: (error: Error) => void;
5
+ showUploadButton?: boolean;
6
+ maxFileSize?: number;
7
+ }
8
+ export declare function TrainlyFileManager({ className, onFileDeleted, onError, showUploadButton, maxFileSize, }: TrainlyFileManagerProps): import("react/jsx-runtime").JSX.Element;