flowscale 1.3.0 → 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.
package/dist/index.d.ts CHANGED
@@ -75,6 +75,7 @@ export declare class FlowscaleAPI {
75
75
  private emitExecuteWorkflowAsyncIntermediateResponse;
76
76
  private formatUnknownError;
77
77
  private sleep;
78
+ private normalizeGetOutputResponse;
78
79
  private resolveGlobalFetch;
79
80
  private consumeRunEventsStream;
80
81
  private safeReadResponseText;
package/dist/index.js CHANGED
@@ -236,13 +236,13 @@ var FlowscaleAPI = /** @class */ (function () {
236
236
  */
237
237
  FlowscaleAPI.prototype.executeWorkflowAsync = function (workflowId_1, data_1, groupId_1) {
238
238
  return __awaiter(this, arguments, void 0, function (workflowId, data, groupId, pollIntervalMs, timeoutMs, returnAllOutputsOrOptions) {
239
- var _a, returnAllOutputs, onIntermediateResponse, startTime, executeResponse, runId, resolvedWorkflowId, run_status, output_names, runResponse, attempts, outputPromises, outputResults, successfulOutputs, pendingOutputs, hasErrors, _i, outputResults_1, result, deprecationWarning, legacyResponse, allOutputsResponse, error_1;
239
+ var _a, returnAllOutputs, onIntermediateResponse, startTime, executeResponse, runId, resolvedWorkflowId, run_status, output_names, runResponse, attempts, runResponse, latestOutputNames, outputPromises, outputResults, successfulOutputs, pendingOutputs, hasErrors, _i, outputResults_1, result, deprecationWarning, legacyResponse, allOutputsResponse, error_1;
240
240
  var _this = this;
241
- var _b, _c, _d, _e, _f;
241
+ var _b, _c, _d, _e, _f, _g, _h, _j;
242
242
  if (pollIntervalMs === void 0) { pollIntervalMs = 2000; }
243
243
  if (timeoutMs === void 0) { timeoutMs = 600000; }
244
- return __generator(this, function (_g) {
245
- switch (_g.label) {
244
+ return __generator(this, function (_k) {
245
+ switch (_k.label) {
246
246
  case 0:
247
247
  // Validate inputs
248
248
  if (!workflowId || typeof workflowId !== 'string' || workflowId.trim() === '') {
@@ -261,7 +261,7 @@ var FlowscaleAPI = /** @class */ (function () {
261
261
  startTime = Date.now();
262
262
  return [4 /*yield*/, this.executeWorkflow(workflowId, data, groupId)];
263
263
  case 1:
264
- executeResponse = _g.sent();
264
+ executeResponse = _k.sent();
265
265
  if (!((_b = executeResponse === null || executeResponse === void 0 ? void 0 : executeResponse.data) === null || _b === void 0 ? void 0 : _b.run_id)) {
266
266
  throw new Error('No run ID returned from workflow execution');
267
267
  }
@@ -278,10 +278,10 @@ var FlowscaleAPI = /** @class */ (function () {
278
278
  response: executeResponse,
279
279
  })];
280
280
  case 2:
281
- _g.sent();
281
+ _k.sent();
282
282
  run_status = "queued";
283
283
  output_names = [];
284
- _g.label = 3;
284
+ _k.label = 3;
285
285
  case 3:
286
286
  if (!(output_names.length === 0)) return [3 /*break*/, 8];
287
287
  if (Date.now() - startTime > timeoutMs) {
@@ -289,7 +289,7 @@ var FlowscaleAPI = /** @class */ (function () {
289
289
  }
290
290
  return [4 /*yield*/, this.getRun(runId)];
291
291
  case 4:
292
- runResponse = _g.sent();
292
+ runResponse = _k.sent();
293
293
  run_status = ((_d = runResponse === null || runResponse === void 0 ? void 0 : runResponse.data) === null || _d === void 0 ? void 0 : _d.status) || "queued";
294
294
  output_names = ((_e = runResponse === null || runResponse === void 0 ? void 0 : runResponse.data) === null || _e === void 0 ? void 0 : _e.output_names) || [];
295
295
  return [4 /*yield*/, this.emitExecuteWorkflowAsyncIntermediateResponse(onIntermediateResponse, {
@@ -303,15 +303,15 @@ var FlowscaleAPI = /** @class */ (function () {
303
303
  response: runResponse,
304
304
  })];
305
305
  case 5:
306
- _g.sent();
306
+ _k.sent();
307
307
  if (run_status === 'failed' || run_status === 'cancelled') {
308
308
  throw new Error("Run ".concat(runId, " failed with status: ").concat(run_status));
309
309
  }
310
310
  if (!(output_names.length === 0)) return [3 /*break*/, 7];
311
311
  return [4 /*yield*/, this.sleep(pollIntervalMs)];
312
312
  case 6:
313
- _g.sent();
314
- _g.label = 7;
313
+ _k.sent();
314
+ _k.label = 7;
315
315
  case 7: return [3 /*break*/, 3];
316
316
  case 8:
317
317
  if (!output_names || output_names.length === 0) {
@@ -319,15 +319,39 @@ var FlowscaleAPI = /** @class */ (function () {
319
319
  }
320
320
  this.logInfo("Found ".concat(output_names.length, " outputs to wait for: ").concat(output_names.join(', ')));
321
321
  attempts = 0;
322
- _g.label = 9;
322
+ _k.label = 9;
323
323
  case 9:
324
- if (!true) return [3 /*break*/, 21];
324
+ if (!true) return [3 /*break*/, 23];
325
325
  if (Date.now() - startTime > timeoutMs) {
326
326
  throw new Error("Workflow execution timed out after ".concat(timeoutMs, "ms"));
327
327
  }
328
- _g.label = 10;
328
+ _k.label = 10;
329
329
  case 10:
330
- _g.trys.push([10, 17, , 20]);
330
+ _k.trys.push([10, 19, , 22]);
331
+ return [4 /*yield*/, this.getRun(runId)];
332
+ case 11:
333
+ runResponse = _k.sent();
334
+ run_status = ((_g = runResponse === null || runResponse === void 0 ? void 0 : runResponse.data) === null || _g === void 0 ? void 0 : _g.status) || run_status;
335
+ latestOutputNames = ((_h = runResponse === null || runResponse === void 0 ? void 0 : runResponse.data) === null || _h === void 0 ? void 0 : _h.output_names) || [];
336
+ if (latestOutputNames.length > 0) {
337
+ output_names = latestOutputNames;
338
+ }
339
+ return [4 /*yield*/, this.emitExecuteWorkflowAsyncIntermediateResponse(onIntermediateResponse, {
340
+ type: 'run_status',
341
+ timestamp: new Date().toISOString(),
342
+ run_id: runId,
343
+ workflow_id: resolvedWorkflowId,
344
+ attempt: attempts,
345
+ run_status: run_status,
346
+ output_names: output_names,
347
+ progress: ((_j = runResponse === null || runResponse === void 0 ? void 0 : runResponse.data) === null || _j === void 0 ? void 0 : _j.progress) || undefined,
348
+ response: runResponse,
349
+ })];
350
+ case 12:
351
+ _k.sent();
352
+ if (run_status === 'failed' || run_status === 'cancelled') {
353
+ throw new Error("Run ".concat(runId, " failed with status: ").concat(run_status));
354
+ }
331
355
  outputPromises = output_names.map(function (outputName) { return __awaiter(_this, void 0, void 0, function () {
332
356
  var output, error_2;
333
357
  var _a;
@@ -372,8 +396,8 @@ var FlowscaleAPI = /** @class */ (function () {
372
396
  });
373
397
  }); });
374
398
  return [4 /*yield*/, Promise.all(outputPromises)];
375
- case 11:
376
- outputResults = _g.sent();
399
+ case 13:
400
+ outputResults = _k.sent();
377
401
  successfulOutputs = [];
378
402
  pendingOutputs = [];
379
403
  hasErrors = false;
@@ -413,9 +437,9 @@ var FlowscaleAPI = /** @class */ (function () {
413
437
  if (hasErrors) {
414
438
  throw new Error('One or more workflow outputs failed');
415
439
  }
416
- if (!(pendingOutputs.length === 0)) return [3 /*break*/, 15];
440
+ if (!(pendingOutputs.length === 0)) return [3 /*break*/, 17];
417
441
  this.logInfo("All ".concat(successfulOutputs.length, " outputs completed successfully"));
418
- if (!(returnAllOutputs === false || (returnAllOutputs === undefined && successfulOutputs.length === 1))) return [3 /*break*/, 13];
442
+ if (!(returnAllOutputs === false || (returnAllOutputs === undefined && successfulOutputs.length === 1))) return [3 /*break*/, 15];
419
443
  deprecationWarning = {
420
444
  message: successfulOutputs.length > 1
421
445
  ? 'Single output format is deprecated. This workflow returned multiple outputs but only the first is shown.'
@@ -443,10 +467,10 @@ var FlowscaleAPI = /** @class */ (function () {
443
467
  completed_outputs: successfulOutputs.map(function (output) { return output.filename; }),
444
468
  response: legacyResponse,
445
469
  })];
446
- case 12:
447
- _g.sent();
470
+ case 14:
471
+ _k.sent();
448
472
  return [2 /*return*/, legacyResponse];
449
- case 13:
473
+ case 15:
450
474
  allOutputsResponse = {
451
475
  status: 'success',
452
476
  data: successfulOutputs
@@ -460,18 +484,18 @@ var FlowscaleAPI = /** @class */ (function () {
460
484
  completed_outputs: successfulOutputs.map(function (output) { return output.filename; }),
461
485
  response: allOutputsResponse,
462
486
  })];
463
- case 14:
464
- _g.sent();
487
+ case 16:
488
+ _k.sent();
465
489
  return [2 /*return*/, allOutputsResponse];
466
- case 15:
490
+ case 17:
467
491
  // If some outputs are still pending, continue polling
468
492
  this.logDebug("".concat(pendingOutputs.length, " outputs still pending: ").concat(pendingOutputs.join(', ')));
469
493
  return [4 /*yield*/, this.sleep(pollIntervalMs)];
470
- case 16:
471
- _g.sent();
472
- return [3 /*break*/, 20];
473
- case 17:
474
- error_1 = _g.sent();
494
+ case 18:
495
+ _k.sent();
496
+ return [3 /*break*/, 22];
497
+ case 19:
498
+ error_1 = _k.sent();
475
499
  // Log the error but continue polling
476
500
  this.logWarn("Error polling for outputs (attempt ".concat(attempts, "):"), error_1);
477
501
  return [4 /*yield*/, this.emitExecuteWorkflowAsyncIntermediateResponse(onIntermediateResponse, {
@@ -483,22 +507,22 @@ var FlowscaleAPI = /** @class */ (function () {
483
507
  output_names: output_names,
484
508
  error: this.formatUnknownError(error_1),
485
509
  })];
486
- case 18:
487
- _g.sent();
510
+ case 20:
511
+ _k.sent();
488
512
  // After several failures, increase polling interval to avoid excessive requests
489
513
  if (attempts > 5) {
490
514
  pollIntervalMs = Math.min(pollIntervalMs * 1.5, 10000); // Increase interval, max 10s
491
515
  }
492
516
  // Wait before retrying
493
517
  return [4 /*yield*/, this.sleep(pollIntervalMs)];
494
- case 19:
518
+ case 21:
495
519
  // Wait before retrying
496
- _g.sent();
497
- return [3 /*break*/, 20];
498
- case 20:
520
+ _k.sent();
521
+ return [3 /*break*/, 22];
522
+ case 22:
499
523
  attempts++;
500
524
  return [3 /*break*/, 9];
501
- case 21: return [2 /*return*/];
525
+ case 23: return [2 /*return*/];
502
526
  }
503
527
  });
504
528
  });
@@ -509,7 +533,7 @@ var FlowscaleAPI = /** @class */ (function () {
509
533
  */
510
534
  FlowscaleAPI.prototype.getOutput = function (filename) {
511
535
  return __awaiter(this, void 0, void 0, function () {
512
- var error_3, axiosError;
536
+ var response, error_3, axiosError;
513
537
  return __generator(this, function (_a) {
514
538
  switch (_a.label) {
515
539
  case 0:
@@ -520,21 +544,35 @@ var FlowscaleAPI = /** @class */ (function () {
520
544
  _a.label = 1;
521
545
  case 1:
522
546
  _a.trys.push([1, 3, , 4]);
523
- return [4 /*yield*/, this.makeRequest('get', '/api/v1/runs/output', {
547
+ return [4 /*yield*/, this.client.get('/api/v1/runs/output', {
524
548
  params: { filename: filename },
549
+ // We need to inspect HTTP status directly (204 is a valid "not ready" response).
550
+ validateStatus: function () { return true; },
525
551
  })];
526
- case 2: return [2 /*return*/, _a.sent()];
527
- case 3:
528
- error_3 = _a.sent();
529
- axiosError = error_3;
530
- if (axiosError.response && axiosError.response.status === 204) {
552
+ case 2:
553
+ response = _a.sent();
554
+ if (response.status === 204) {
531
555
  return [2 /*return*/, null]; // No output found
532
556
  }
533
- else if (axiosError.response && axiosError.response.status === 504) {
557
+ else if (response.status === 504) {
534
558
  this.logWarn('Received 504 Gateway Timeout, retrying...');
535
559
  // For 504 errors specifically, we'll return null to allow the polling to continue
536
560
  return [2 /*return*/, null];
537
561
  }
562
+ else if (response.status === 408) {
563
+ throw new Error('Run Timeout');
564
+ }
565
+ if (response.status < 200 || response.status >= 300) {
566
+ throw new Error("Error: ".concat(response.status, " ").concat(response.statusText, " - ").concat(JSON.stringify(response.data)));
567
+ }
568
+ return [2 /*return*/, this.normalizeGetOutputResponse(response.data)];
569
+ case 3:
570
+ error_3 = _a.sent();
571
+ axiosError = error_3;
572
+ if (axiosError.response && axiosError.response.status === 504) {
573
+ this.logWarn('Received 504 Gateway Timeout, retrying...');
574
+ return [2 /*return*/, null];
575
+ }
538
576
  else if (axiosError.response && axiosError.response.status === 408) {
539
577
  throw new Error('Run Timeout');
540
578
  }
@@ -685,6 +723,55 @@ var FlowscaleAPI = /** @class */ (function () {
685
723
  });
686
724
  });
687
725
  };
726
+ FlowscaleAPI.prototype.normalizeGetOutputResponse = function (payload) {
727
+ if (!payload || typeof payload !== 'object') {
728
+ return null;
729
+ }
730
+ if (typeof payload.status === 'string') {
731
+ return payload;
732
+ }
733
+ // Handle payloads that omit top-level status but still contain useful output data.
734
+ if (payload.data && typeof payload.data === 'object') {
735
+ if (payload.data.errors) {
736
+ return {
737
+ status: 'error',
738
+ data: {
739
+ errors: payload.data.errors,
740
+ },
741
+ };
742
+ }
743
+ if (payload.data.progress) {
744
+ return {
745
+ status: 'in_progress',
746
+ data: payload.data,
747
+ };
748
+ }
749
+ if (payload.data.download_url ||
750
+ payload.data.file_content ||
751
+ payload.data.generation_status) {
752
+ return {
753
+ status: 'success',
754
+ data: payload.data,
755
+ };
756
+ }
757
+ }
758
+ // Legacy shape fallback: response data returned directly without wrapping.
759
+ if (payload.download_url || payload.file_content || payload.generation_status) {
760
+ return {
761
+ status: 'success',
762
+ data: payload,
763
+ };
764
+ }
765
+ if (payload.errors) {
766
+ return {
767
+ status: 'error',
768
+ data: {
769
+ errors: payload.errors,
770
+ },
771
+ };
772
+ }
773
+ return null;
774
+ };
688
775
  FlowscaleAPI.prototype.resolveGlobalFetch = function () {
689
776
  var globalScope = typeof globalThis !== 'undefined'
690
777
  ? globalThis
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "flowscale",
3
- "version": "1.3.0",
3
+ "version": "1.3.1",
4
4
  "description": "An NPM library for communicating with the Flowscale APIs",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",