flowscale 1.3.0 → 1.3.2
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 +1 -0
- package/dist/index.js +141 -46
- package/package.json +1 -1
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, errorMessage, isIntentionalError;
|
|
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 (
|
|
245
|
-
switch (
|
|
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 =
|
|
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
|
-
|
|
281
|
+
_k.sent();
|
|
282
282
|
run_status = "queued";
|
|
283
283
|
output_names = [];
|
|
284
|
-
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
314
|
-
|
|
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
|
-
|
|
322
|
+
_k.label = 9;
|
|
323
323
|
case 9:
|
|
324
|
-
if (!true) return [3 /*break*/,
|
|
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
|
-
|
|
328
|
+
_k.label = 10;
|
|
329
329
|
case 10:
|
|
330
|
-
|
|
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
|
|
376
|
-
outputResults =
|
|
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*/,
|
|
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*/,
|
|
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
|
|
447
|
-
|
|
470
|
+
case 14:
|
|
471
|
+
_k.sent();
|
|
448
472
|
return [2 /*return*/, legacyResponse];
|
|
449
|
-
case
|
|
473
|
+
case 15:
|
|
450
474
|
allOutputsResponse = {
|
|
451
475
|
status: 'success',
|
|
452
476
|
data: successfulOutputs
|
|
@@ -460,19 +484,25 @@ var FlowscaleAPI = /** @class */ (function () {
|
|
|
460
484
|
completed_outputs: successfulOutputs.map(function (output) { return output.filename; }),
|
|
461
485
|
response: allOutputsResponse,
|
|
462
486
|
})];
|
|
463
|
-
case
|
|
464
|
-
|
|
487
|
+
case 16:
|
|
488
|
+
_k.sent();
|
|
465
489
|
return [2 /*return*/, allOutputsResponse];
|
|
466
|
-
case
|
|
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
|
|
471
|
-
|
|
472
|
-
return [3 /*break*/,
|
|
473
|
-
case
|
|
474
|
-
error_1 =
|
|
475
|
-
|
|
494
|
+
case 18:
|
|
495
|
+
_k.sent();
|
|
496
|
+
return [3 /*break*/, 22];
|
|
497
|
+
case 19:
|
|
498
|
+
error_1 = _k.sent();
|
|
499
|
+
errorMessage = error_1 instanceof Error ? error_1.message : String(error_1);
|
|
500
|
+
isIntentionalError = errorMessage.includes('failed with status:') ||
|
|
501
|
+
errorMessage.includes('One or more workflow outputs failed');
|
|
502
|
+
if (isIntentionalError) {
|
|
503
|
+
throw error_1;
|
|
504
|
+
}
|
|
505
|
+
// Transient errors: log and continue polling
|
|
476
506
|
this.logWarn("Error polling for outputs (attempt ".concat(attempts, "):"), error_1);
|
|
477
507
|
return [4 /*yield*/, this.emitExecuteWorkflowAsyncIntermediateResponse(onIntermediateResponse, {
|
|
478
508
|
type: 'poll_retry',
|
|
@@ -483,22 +513,22 @@ var FlowscaleAPI = /** @class */ (function () {
|
|
|
483
513
|
output_names: output_names,
|
|
484
514
|
error: this.formatUnknownError(error_1),
|
|
485
515
|
})];
|
|
486
|
-
case
|
|
487
|
-
|
|
516
|
+
case 20:
|
|
517
|
+
_k.sent();
|
|
488
518
|
// After several failures, increase polling interval to avoid excessive requests
|
|
489
519
|
if (attempts > 5) {
|
|
490
520
|
pollIntervalMs = Math.min(pollIntervalMs * 1.5, 10000); // Increase interval, max 10s
|
|
491
521
|
}
|
|
492
522
|
// Wait before retrying
|
|
493
523
|
return [4 /*yield*/, this.sleep(pollIntervalMs)];
|
|
494
|
-
case
|
|
524
|
+
case 21:
|
|
495
525
|
// Wait before retrying
|
|
496
|
-
|
|
497
|
-
return [3 /*break*/,
|
|
498
|
-
case
|
|
526
|
+
_k.sent();
|
|
527
|
+
return [3 /*break*/, 22];
|
|
528
|
+
case 22:
|
|
499
529
|
attempts++;
|
|
500
530
|
return [3 /*break*/, 9];
|
|
501
|
-
case
|
|
531
|
+
case 23: return [2 /*return*/];
|
|
502
532
|
}
|
|
503
533
|
});
|
|
504
534
|
});
|
|
@@ -509,7 +539,7 @@ var FlowscaleAPI = /** @class */ (function () {
|
|
|
509
539
|
*/
|
|
510
540
|
FlowscaleAPI.prototype.getOutput = function (filename) {
|
|
511
541
|
return __awaiter(this, void 0, void 0, function () {
|
|
512
|
-
var error_3, axiosError;
|
|
542
|
+
var response, error_3, axiosError;
|
|
513
543
|
return __generator(this, function (_a) {
|
|
514
544
|
switch (_a.label) {
|
|
515
545
|
case 0:
|
|
@@ -520,21 +550,35 @@ var FlowscaleAPI = /** @class */ (function () {
|
|
|
520
550
|
_a.label = 1;
|
|
521
551
|
case 1:
|
|
522
552
|
_a.trys.push([1, 3, , 4]);
|
|
523
|
-
return [4 /*yield*/, this.
|
|
553
|
+
return [4 /*yield*/, this.client.get('/api/v1/runs/output', {
|
|
524
554
|
params: { filename: filename },
|
|
555
|
+
// We need to inspect HTTP status directly (204 is a valid "not ready" response).
|
|
556
|
+
validateStatus: function () { return true; },
|
|
525
557
|
})];
|
|
526
|
-
case 2:
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
axiosError = error_3;
|
|
530
|
-
if (axiosError.response && axiosError.response.status === 204) {
|
|
558
|
+
case 2:
|
|
559
|
+
response = _a.sent();
|
|
560
|
+
if (response.status === 204) {
|
|
531
561
|
return [2 /*return*/, null]; // No output found
|
|
532
562
|
}
|
|
533
|
-
else if (
|
|
563
|
+
else if (response.status === 504) {
|
|
534
564
|
this.logWarn('Received 504 Gateway Timeout, retrying...');
|
|
535
565
|
// For 504 errors specifically, we'll return null to allow the polling to continue
|
|
536
566
|
return [2 /*return*/, null];
|
|
537
567
|
}
|
|
568
|
+
else if (response.status === 408) {
|
|
569
|
+
throw new Error('Run Timeout');
|
|
570
|
+
}
|
|
571
|
+
if (response.status < 200 || response.status >= 300) {
|
|
572
|
+
throw new Error("Error: ".concat(response.status, " ").concat(response.statusText, " - ").concat(JSON.stringify(response.data)));
|
|
573
|
+
}
|
|
574
|
+
return [2 /*return*/, this.normalizeGetOutputResponse(response.data)];
|
|
575
|
+
case 3:
|
|
576
|
+
error_3 = _a.sent();
|
|
577
|
+
axiosError = error_3;
|
|
578
|
+
if (axiosError.response && axiosError.response.status === 504) {
|
|
579
|
+
this.logWarn('Received 504 Gateway Timeout, retrying...');
|
|
580
|
+
return [2 /*return*/, null];
|
|
581
|
+
}
|
|
538
582
|
else if (axiosError.response && axiosError.response.status === 408) {
|
|
539
583
|
throw new Error('Run Timeout');
|
|
540
584
|
}
|
|
@@ -641,11 +685,13 @@ var FlowscaleAPI = /** @class */ (function () {
|
|
|
641
685
|
switch (_a.label) {
|
|
642
686
|
case 0:
|
|
643
687
|
if (!callback) {
|
|
688
|
+
this.logError("No callback");
|
|
644
689
|
return [2 /*return*/];
|
|
645
690
|
}
|
|
646
691
|
_a.label = 1;
|
|
647
692
|
case 1:
|
|
648
693
|
_a.trys.push([1, 3, , 4]);
|
|
694
|
+
this.logInfo("got INTERMEDIATe UPDATE");
|
|
649
695
|
return [4 /*yield*/, callback(update)];
|
|
650
696
|
case 2:
|
|
651
697
|
_a.sent();
|
|
@@ -685,6 +731,55 @@ var FlowscaleAPI = /** @class */ (function () {
|
|
|
685
731
|
});
|
|
686
732
|
});
|
|
687
733
|
};
|
|
734
|
+
FlowscaleAPI.prototype.normalizeGetOutputResponse = function (payload) {
|
|
735
|
+
if (!payload || typeof payload !== 'object') {
|
|
736
|
+
return null;
|
|
737
|
+
}
|
|
738
|
+
if (typeof payload.status === 'string') {
|
|
739
|
+
return payload;
|
|
740
|
+
}
|
|
741
|
+
// Handle payloads that omit top-level status but still contain useful output data.
|
|
742
|
+
if (payload.data && typeof payload.data === 'object') {
|
|
743
|
+
if (payload.data.errors) {
|
|
744
|
+
return {
|
|
745
|
+
status: 'error',
|
|
746
|
+
data: {
|
|
747
|
+
errors: payload.data.errors,
|
|
748
|
+
},
|
|
749
|
+
};
|
|
750
|
+
}
|
|
751
|
+
if (payload.data.progress) {
|
|
752
|
+
return {
|
|
753
|
+
status: 'in_progress',
|
|
754
|
+
data: payload.data,
|
|
755
|
+
};
|
|
756
|
+
}
|
|
757
|
+
if (payload.data.download_url ||
|
|
758
|
+
payload.data.file_content ||
|
|
759
|
+
payload.data.generation_status) {
|
|
760
|
+
return {
|
|
761
|
+
status: 'success',
|
|
762
|
+
data: payload.data,
|
|
763
|
+
};
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
// Legacy shape fallback: response data returned directly without wrapping.
|
|
767
|
+
if (payload.download_url || payload.file_content || payload.generation_status) {
|
|
768
|
+
return {
|
|
769
|
+
status: 'success',
|
|
770
|
+
data: payload,
|
|
771
|
+
};
|
|
772
|
+
}
|
|
773
|
+
if (payload.errors) {
|
|
774
|
+
return {
|
|
775
|
+
status: 'error',
|
|
776
|
+
data: {
|
|
777
|
+
errors: payload.errors,
|
|
778
|
+
},
|
|
779
|
+
};
|
|
780
|
+
}
|
|
781
|
+
return null;
|
|
782
|
+
};
|
|
688
783
|
FlowscaleAPI.prototype.resolveGlobalFetch = function () {
|
|
689
784
|
var globalScope = typeof globalThis !== 'undefined'
|
|
690
785
|
? globalThis
|