@upstash/workflow 0.2.21 → 0.2.22
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/README.md +39 -0
- package/astro.d.mts +2 -2
- package/astro.d.ts +2 -2
- package/astro.js +124 -71
- package/astro.mjs +1 -1
- package/{chunk-NQDNC5P4.mjs → chunk-BON2RKOR.mjs} +93 -76
- package/cloudflare.d.mts +2 -2
- package/cloudflare.d.ts +2 -2
- package/cloudflare.js +124 -71
- package/cloudflare.mjs +1 -1
- package/express.d.mts +2 -2
- package/express.d.ts +2 -2
- package/express.js +139 -23895
- package/express.mjs +8 -23805
- package/h3.d.mts +2 -2
- package/h3.d.ts +2 -2
- package/h3.js +124 -71
- package/h3.mjs +1 -1
- package/hono.d.mts +2 -2
- package/hono.d.ts +2 -2
- package/hono.js +124 -71
- package/hono.mjs +1 -1
- package/index.d.mts +10 -2
- package/index.d.ts +10 -2
- package/index.js +128 -73
- package/index.mjs +5 -3
- package/nextjs.d.mts +2 -2
- package/nextjs.d.ts +2 -2
- package/nextjs.js +126 -72
- package/nextjs.mjs +3 -2
- package/package.json +1 -1
- package/{serve-many-CXqQP3RI.d.ts → serve-many-BXDr30rl.d.ts} +1 -1
- package/{serve-many-BNusWYgt.d.mts → serve-many-CctdYIfB.d.mts} +1 -1
- package/solidjs.d.mts +1 -1
- package/solidjs.d.ts +1 -1
- package/solidjs.js +124 -71
- package/solidjs.mjs +1 -1
- package/svelte.d.mts +2 -2
- package/svelte.d.ts +2 -2
- package/svelte.js +124 -71
- package/svelte.mjs +1 -1
- package/tanstack.d.mts +2 -2
- package/tanstack.d.ts +2 -2
- package/tanstack.js +124 -71
- package/tanstack.mjs +1 -1
- package/{types-Q3dM0UlR.d.ts → types-9nCq6bRP.d.mts} +12 -1
- package/{types-Q3dM0UlR.d.mts → types-9nCq6bRP.d.ts} +12 -1
package/h3.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as h3 from 'h3';
|
|
2
|
-
import { R as RouteFunction,
|
|
3
|
-
import { s as serveManyBase } from './serve-many-
|
|
2
|
+
import { R as RouteFunction, o as PublicServeOptions, z as InvokableWorkflow } from './types-9nCq6bRP.mjs';
|
|
3
|
+
import { s as serveManyBase } from './serve-many-CctdYIfB.mjs';
|
|
4
4
|
import '@upstash/qstash';
|
|
5
5
|
import 'zod';
|
|
6
6
|
import 'ai';
|
package/h3.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as h3 from 'h3';
|
|
2
|
-
import { R as RouteFunction,
|
|
3
|
-
import { s as serveManyBase } from './serve-many-
|
|
2
|
+
import { R as RouteFunction, o as PublicServeOptions, z as InvokableWorkflow } from './types-9nCq6bRP.js';
|
|
3
|
+
import { s as serveManyBase } from './serve-many-BXDr30rl.js';
|
|
4
4
|
import '@upstash/qstash';
|
|
5
5
|
import 'zod';
|
|
6
6
|
import 'ai';
|
package/h3.js
CHANGED
|
@@ -339,7 +339,95 @@ var H3Headers = globalThis.Headers;
|
|
|
339
339
|
var H3Response = globalThis.Response;
|
|
340
340
|
|
|
341
341
|
// src/client/utils.ts
|
|
342
|
+
var import_qstash2 = require("@upstash/qstash");
|
|
343
|
+
|
|
344
|
+
// src/error.ts
|
|
342
345
|
var import_qstash = require("@upstash/qstash");
|
|
346
|
+
var WorkflowError = class extends import_qstash.QstashError {
|
|
347
|
+
constructor(message) {
|
|
348
|
+
super(message);
|
|
349
|
+
this.name = "WorkflowError";
|
|
350
|
+
}
|
|
351
|
+
};
|
|
352
|
+
var WorkflowAbort = class extends Error {
|
|
353
|
+
stepInfo;
|
|
354
|
+
stepName;
|
|
355
|
+
/**
|
|
356
|
+
* whether workflow is to be canceled on abort
|
|
357
|
+
*/
|
|
358
|
+
cancelWorkflow;
|
|
359
|
+
/**
|
|
360
|
+
*
|
|
361
|
+
* @param stepName name of the aborting step
|
|
362
|
+
* @param stepInfo step information
|
|
363
|
+
* @param cancelWorkflow
|
|
364
|
+
*/
|
|
365
|
+
constructor(stepName, stepInfo, cancelWorkflow = false) {
|
|
366
|
+
super(
|
|
367
|
+
`This is an Upstash Workflow error thrown after a step executes. It is expected to be raised. Make sure that you await for each step. Also, if you are using try/catch blocks, you should not wrap context.run/sleep/sleepUntil/call methods with try/catch. Aborting workflow after executing step '${stepName}'.`
|
|
368
|
+
);
|
|
369
|
+
this.name = "WorkflowAbort";
|
|
370
|
+
this.stepName = stepName;
|
|
371
|
+
this.stepInfo = stepInfo;
|
|
372
|
+
this.cancelWorkflow = cancelWorkflow;
|
|
373
|
+
}
|
|
374
|
+
};
|
|
375
|
+
var WorkflowNonRetryableError = class extends WorkflowAbort {
|
|
376
|
+
/**
|
|
377
|
+
* @param message error message to be displayed
|
|
378
|
+
*/
|
|
379
|
+
constructor(message) {
|
|
380
|
+
super("fail", void 0, false);
|
|
381
|
+
this.name = "WorkflowNonRetryableError";
|
|
382
|
+
if (message) this.message = message;
|
|
383
|
+
}
|
|
384
|
+
};
|
|
385
|
+
var WorkflowRetryAfterError = class extends WorkflowAbort {
|
|
386
|
+
retryAfter;
|
|
387
|
+
/**
|
|
388
|
+
* @param retryAfter time in seconds after which the workflow should be retried
|
|
389
|
+
* @param message error message to be displayed
|
|
390
|
+
*/
|
|
391
|
+
constructor(message, retryAfter) {
|
|
392
|
+
super("retry", void 0, false);
|
|
393
|
+
this.name = "WorkflowRetryAfterError";
|
|
394
|
+
this.retryAfter = retryAfter;
|
|
395
|
+
if (message) this.message = message;
|
|
396
|
+
}
|
|
397
|
+
};
|
|
398
|
+
var formatWorkflowError = (error) => {
|
|
399
|
+
return error instanceof Error ? {
|
|
400
|
+
error: error.name,
|
|
401
|
+
message: error.message,
|
|
402
|
+
stack: error.stack
|
|
403
|
+
} : {
|
|
404
|
+
error: "Error",
|
|
405
|
+
message: `An error occured while executing workflow: '${typeof error === "string" ? error : JSON.stringify(error)}'`
|
|
406
|
+
};
|
|
407
|
+
};
|
|
408
|
+
function getConstructorName(obj) {
|
|
409
|
+
if (obj === null || obj === void 0) {
|
|
410
|
+
return null;
|
|
411
|
+
}
|
|
412
|
+
const ctor = obj.constructor;
|
|
413
|
+
if (!ctor || ctor.name === "Object") {
|
|
414
|
+
return null;
|
|
415
|
+
}
|
|
416
|
+
return ctor.name;
|
|
417
|
+
}
|
|
418
|
+
function getConstructorNames(obj) {
|
|
419
|
+
const proto = Object.getPrototypeOf(obj);
|
|
420
|
+
const name = getConstructorName(proto);
|
|
421
|
+
if (name === null) {
|
|
422
|
+
return [];
|
|
423
|
+
}
|
|
424
|
+
return [name, ...getConstructorNames(proto)];
|
|
425
|
+
}
|
|
426
|
+
function isInstanceOf(v, ctor) {
|
|
427
|
+
return getConstructorNames(v).includes(ctor.name);
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
// src/client/utils.ts
|
|
343
431
|
var makeNotifyRequest = async (requester, eventId, eventData) => {
|
|
344
432
|
const result = await requester.request({
|
|
345
433
|
path: ["v2", "notify", eventId],
|
|
@@ -379,7 +467,7 @@ var getSteps = async (requester, workflowRunId, messageId, debug) => {
|
|
|
379
467
|
return { steps: filteredSteps, workflowRunEnded: false };
|
|
380
468
|
}
|
|
381
469
|
} catch (error) {
|
|
382
|
-
if (error
|
|
470
|
+
if (isInstanceOf(error, import_qstash2.QstashError) && error.status === 404) {
|
|
383
471
|
await debug?.log("WARN", "ENDPOINT_START", {
|
|
384
472
|
message: "Couldn't fetch workflow run steps. This can happen if the workflow run succesfully ends before some callback is executed.",
|
|
385
473
|
error
|
|
@@ -404,65 +492,13 @@ var WORKFLOW_PROTOCOL_VERSION_HEADER = "Upstash-Workflow-Sdk-Version";
|
|
|
404
492
|
var DEFAULT_CONTENT_TYPE = "application/json";
|
|
405
493
|
var NO_CONCURRENCY = 1;
|
|
406
494
|
var DEFAULT_RETRIES = 3;
|
|
407
|
-
var VERSION = "v0.2.
|
|
495
|
+
var VERSION = "v0.2.22";
|
|
408
496
|
var SDK_TELEMETRY = `@upstash/workflow@${VERSION}`;
|
|
409
497
|
var TELEMETRY_HEADER_SDK = "Upstash-Telemetry-Sdk";
|
|
410
498
|
var TELEMETRY_HEADER_FRAMEWORK = "Upstash-Telemetry-Framework";
|
|
411
499
|
var TELEMETRY_HEADER_RUNTIME = "Upstash-Telemetry-Runtime";
|
|
412
500
|
var TELEMETRY_HEADER_AGENT = "Upstash-Telemetry-Agent";
|
|
413
501
|
|
|
414
|
-
// src/error.ts
|
|
415
|
-
var import_qstash2 = require("@upstash/qstash");
|
|
416
|
-
var WorkflowError = class extends import_qstash2.QstashError {
|
|
417
|
-
constructor(message) {
|
|
418
|
-
super(message);
|
|
419
|
-
this.name = "WorkflowError";
|
|
420
|
-
}
|
|
421
|
-
};
|
|
422
|
-
var WorkflowAbort = class extends Error {
|
|
423
|
-
stepInfo;
|
|
424
|
-
stepName;
|
|
425
|
-
/**
|
|
426
|
-
* whether workflow is to be canceled on abort
|
|
427
|
-
*/
|
|
428
|
-
cancelWorkflow;
|
|
429
|
-
/**
|
|
430
|
-
*
|
|
431
|
-
* @param stepName name of the aborting step
|
|
432
|
-
* @param stepInfo step information
|
|
433
|
-
* @param cancelWorkflow
|
|
434
|
-
*/
|
|
435
|
-
constructor(stepName, stepInfo, cancelWorkflow = false) {
|
|
436
|
-
super(
|
|
437
|
-
`This is an Upstash Workflow error thrown after a step executes. It is expected to be raised. Make sure that you await for each step. Also, if you are using try/catch blocks, you should not wrap context.run/sleep/sleepUntil/call methods with try/catch. Aborting workflow after executing step '${stepName}'.`
|
|
438
|
-
);
|
|
439
|
-
this.name = "WorkflowAbort";
|
|
440
|
-
this.stepName = stepName;
|
|
441
|
-
this.stepInfo = stepInfo;
|
|
442
|
-
this.cancelWorkflow = cancelWorkflow;
|
|
443
|
-
}
|
|
444
|
-
};
|
|
445
|
-
var WorkflowNonRetryableError = class extends WorkflowAbort {
|
|
446
|
-
/**
|
|
447
|
-
* @param message error message to be displayed
|
|
448
|
-
*/
|
|
449
|
-
constructor(message) {
|
|
450
|
-
super("fail", void 0, false);
|
|
451
|
-
this.name = "WorkflowNonRetryableError";
|
|
452
|
-
if (message) this.message = message;
|
|
453
|
-
}
|
|
454
|
-
};
|
|
455
|
-
var formatWorkflowError = (error) => {
|
|
456
|
-
return error instanceof Error ? {
|
|
457
|
-
error: error.name,
|
|
458
|
-
message: error.message,
|
|
459
|
-
stack: error.stack
|
|
460
|
-
} : {
|
|
461
|
-
error: "Error",
|
|
462
|
-
message: `An error occured while executing workflow: '${typeof error === "string" ? error : JSON.stringify(error)}'`
|
|
463
|
-
};
|
|
464
|
-
};
|
|
465
|
-
|
|
466
502
|
// src/context/auto-executor.ts
|
|
467
503
|
var import_qstash5 = require("@upstash/qstash");
|
|
468
504
|
|
|
@@ -1022,17 +1058,17 @@ var triggerRouteFunction = async ({
|
|
|
1022
1058
|
return ok("workflow-finished");
|
|
1023
1059
|
} catch (error) {
|
|
1024
1060
|
const error_ = error;
|
|
1025
|
-
if (error
|
|
1061
|
+
if (isInstanceOf(error, import_qstash3.QstashError) && error.status === 400) {
|
|
1026
1062
|
await debug?.log("WARN", "RESPONSE_WORKFLOW", {
|
|
1027
1063
|
message: `tried to append to a cancelled workflow. exiting without publishing.`,
|
|
1028
1064
|
name: error.name,
|
|
1029
1065
|
errorMessage: error.message
|
|
1030
1066
|
});
|
|
1031
1067
|
return ok("workflow-was-finished");
|
|
1032
|
-
} else if (
|
|
1033
|
-
return err(error_);
|
|
1034
|
-
} else if (error_ instanceof WorkflowNonRetryableError) {
|
|
1068
|
+
} else if (isInstanceOf(error_, WorkflowNonRetryableError) || isInstanceOf(error_, WorkflowRetryAfterError)) {
|
|
1035
1069
|
return ok(error_);
|
|
1070
|
+
} else if (!isInstanceOf(error_, WorkflowAbort)) {
|
|
1071
|
+
return err(error_);
|
|
1036
1072
|
} else if (error_.cancelWorkflow) {
|
|
1037
1073
|
await onCancel();
|
|
1038
1074
|
return ok("workflow-finished");
|
|
@@ -2339,7 +2375,7 @@ var AutoExecutor = class _AutoExecutor {
|
|
|
2339
2375
|
});
|
|
2340
2376
|
throw new WorkflowAbort(parallelStep.stepName, resultStep);
|
|
2341
2377
|
} catch (error) {
|
|
2342
|
-
if (error
|
|
2378
|
+
if (isInstanceOf(error, WorkflowAbort) || isInstanceOf(error, import_qstash5.QstashError) && error.status === 400) {
|
|
2343
2379
|
throw error;
|
|
2344
2380
|
}
|
|
2345
2381
|
throw new WorkflowError(
|
|
@@ -2446,7 +2482,7 @@ var validateParallelSteps = (lazySteps, stepsFromRequest) => {
|
|
|
2446
2482
|
validateStep(lazySteps[index], stepFromRequest);
|
|
2447
2483
|
}
|
|
2448
2484
|
} catch (error) {
|
|
2449
|
-
if (error
|
|
2485
|
+
if (isInstanceOf(error, WorkflowError)) {
|
|
2450
2486
|
const lazyStepNames = lazySteps.map((lazyStep) => lazyStep.stepName);
|
|
2451
2487
|
const lazyStepTypes = lazySteps.map((lazyStep) => lazyStep.stepType);
|
|
2452
2488
|
const requestStepNames = stepsFromRequest.map((step) => step.stepName);
|
|
@@ -2627,7 +2663,7 @@ var fetchWithContextCall = async (context, agentCallParams, ...params) => {
|
|
|
2627
2663
|
headers: responseHeaders
|
|
2628
2664
|
});
|
|
2629
2665
|
} catch (error) {
|
|
2630
|
-
if (error instanceof Error && error
|
|
2666
|
+
if (error instanceof Error && isInstanceOf(error, WorkflowAbort)) {
|
|
2631
2667
|
throw error;
|
|
2632
2668
|
} else {
|
|
2633
2669
|
console.error("Error in fetch implementation:", error);
|
|
@@ -2729,10 +2765,10 @@ var Agent = class {
|
|
|
2729
2765
|
});
|
|
2730
2766
|
return { text: result.text };
|
|
2731
2767
|
} catch (error) {
|
|
2732
|
-
if (error
|
|
2733
|
-
if (error.cause instanceof Error && error.cause
|
|
2768
|
+
if (isInstanceOf(error, import_ai2.ToolExecutionError)) {
|
|
2769
|
+
if (error.cause instanceof Error && isInstanceOf(error.cause, WorkflowAbort)) {
|
|
2734
2770
|
throw error.cause;
|
|
2735
|
-
} else if (error.cause
|
|
2771
|
+
} else if (isInstanceOf(error.cause, import_ai2.ToolExecutionError) && isInstanceOf(error.cause.cause, WorkflowAbort)) {
|
|
2736
2772
|
throw error.cause.cause;
|
|
2737
2773
|
} else {
|
|
2738
2774
|
throw error;
|
|
@@ -3481,7 +3517,7 @@ var DisabledWorkflowContext = class _DisabledWorkflowContext extends WorkflowCon
|
|
|
3481
3517
|
try {
|
|
3482
3518
|
await routeFunction(disabledContext);
|
|
3483
3519
|
} catch (error) {
|
|
3484
|
-
if (error
|
|
3520
|
+
if (isInstanceOf(error, WorkflowAbort) && error.stepName === this.disabledMessage || isInstanceOf(error, WorkflowNonRetryableError) || isInstanceOf(error, WorkflowRetryAfterError)) {
|
|
3485
3521
|
return ok("step-found");
|
|
3486
3522
|
}
|
|
3487
3523
|
console.warn(
|
|
@@ -3734,13 +3770,24 @@ var processOptions = (options) => {
|
|
|
3734
3770
|
},
|
|
3735
3771
|
status: 489
|
|
3736
3772
|
});
|
|
3737
|
-
} else if (detailedFinishCondition?.condition === "
|
|
3738
|
-
return new Response(detailedFinishCondition.result
|
|
3739
|
-
status: 200,
|
|
3773
|
+
} else if (detailedFinishCondition?.condition === "retry-after-error") {
|
|
3774
|
+
return new Response(JSON.stringify(formatWorkflowError(detailedFinishCondition.result)), {
|
|
3740
3775
|
headers: {
|
|
3776
|
+
"Retry-After": detailedFinishCondition.result.retryAfter.toString(),
|
|
3741
3777
|
[WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION
|
|
3742
|
-
}
|
|
3778
|
+
},
|
|
3779
|
+
status: 429
|
|
3743
3780
|
});
|
|
3781
|
+
} else if (detailedFinishCondition?.condition === "failure-callback") {
|
|
3782
|
+
return new Response(
|
|
3783
|
+
JSON.stringify({ result: detailedFinishCondition.result ?? void 0 }),
|
|
3784
|
+
{
|
|
3785
|
+
status: 200,
|
|
3786
|
+
headers: {
|
|
3787
|
+
[WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION
|
|
3788
|
+
}
|
|
3789
|
+
}
|
|
3790
|
+
);
|
|
3744
3791
|
}
|
|
3745
3792
|
return new Response(JSON.stringify({ workflowRunId }), {
|
|
3746
3793
|
status: 200,
|
|
@@ -3950,12 +3997,18 @@ var serveBase = (routeFunction, telemetry2, options) => {
|
|
|
3950
3997
|
},
|
|
3951
3998
|
debug
|
|
3952
3999
|
});
|
|
3953
|
-
if (result.isOk() && result.value
|
|
4000
|
+
if (result.isOk() && isInstanceOf(result.value, WorkflowNonRetryableError)) {
|
|
3954
4001
|
return onStepFinish(workflowRunId, result.value, {
|
|
3955
4002
|
condition: "non-retryable-error",
|
|
3956
4003
|
result: result.value
|
|
3957
4004
|
});
|
|
3958
4005
|
}
|
|
4006
|
+
if (result.isOk() && isInstanceOf(result.value, WorkflowRetryAfterError)) {
|
|
4007
|
+
return onStepFinish(workflowRunId, result.value, {
|
|
4008
|
+
condition: "retry-after-error",
|
|
4009
|
+
result: result.value
|
|
4010
|
+
});
|
|
4011
|
+
}
|
|
3959
4012
|
if (result.isErr()) {
|
|
3960
4013
|
await debug?.log("ERROR", "ERROR", { error: result.error.message });
|
|
3961
4014
|
throw result.error;
|
|
@@ -3986,7 +4039,7 @@ var serveBase = (routeFunction, telemetry2, options) => {
|
|
|
3986
4039
|
const errorMessage = `Error while running onError callback: '${formattedOnErrorError.message}'.
|
|
3987
4040
|
Original error: '${formattedError.message}'`;
|
|
3988
4041
|
console.error(errorMessage);
|
|
3989
|
-
return new Response(errorMessage, {
|
|
4042
|
+
return new Response(JSON.stringify({ error: errorMessage }), {
|
|
3990
4043
|
status: 500,
|
|
3991
4044
|
headers: {
|
|
3992
4045
|
[WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION
|
package/h3.mjs
CHANGED
package/hono.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Context } from 'hono';
|
|
2
|
-
import { R as RouteFunction,
|
|
2
|
+
import { R as RouteFunction, o as PublicServeOptions, z as InvokableWorkflow } from './types-9nCq6bRP.mjs';
|
|
3
3
|
import { Variables } from 'hono/types';
|
|
4
|
-
import { s as serveManyBase } from './serve-many-
|
|
4
|
+
import { s as serveManyBase } from './serve-many-CctdYIfB.mjs';
|
|
5
5
|
import '@upstash/qstash';
|
|
6
6
|
import 'zod';
|
|
7
7
|
import 'ai';
|
package/hono.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Context } from 'hono';
|
|
2
|
-
import { R as RouteFunction,
|
|
2
|
+
import { R as RouteFunction, o as PublicServeOptions, z as InvokableWorkflow } from './types-9nCq6bRP.js';
|
|
3
3
|
import { Variables } from 'hono/types';
|
|
4
|
-
import { s as serveManyBase } from './serve-many-
|
|
4
|
+
import { s as serveManyBase } from './serve-many-BXDr30rl.js';
|
|
5
5
|
import '@upstash/qstash';
|
|
6
6
|
import 'zod';
|
|
7
7
|
import 'ai';
|
package/hono.js
CHANGED
|
@@ -27,7 +27,95 @@ __export(hono_exports, {
|
|
|
27
27
|
module.exports = __toCommonJS(hono_exports);
|
|
28
28
|
|
|
29
29
|
// src/client/utils.ts
|
|
30
|
+
var import_qstash2 = require("@upstash/qstash");
|
|
31
|
+
|
|
32
|
+
// src/error.ts
|
|
30
33
|
var import_qstash = require("@upstash/qstash");
|
|
34
|
+
var WorkflowError = class extends import_qstash.QstashError {
|
|
35
|
+
constructor(message) {
|
|
36
|
+
super(message);
|
|
37
|
+
this.name = "WorkflowError";
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
var WorkflowAbort = class extends Error {
|
|
41
|
+
stepInfo;
|
|
42
|
+
stepName;
|
|
43
|
+
/**
|
|
44
|
+
* whether workflow is to be canceled on abort
|
|
45
|
+
*/
|
|
46
|
+
cancelWorkflow;
|
|
47
|
+
/**
|
|
48
|
+
*
|
|
49
|
+
* @param stepName name of the aborting step
|
|
50
|
+
* @param stepInfo step information
|
|
51
|
+
* @param cancelWorkflow
|
|
52
|
+
*/
|
|
53
|
+
constructor(stepName, stepInfo, cancelWorkflow = false) {
|
|
54
|
+
super(
|
|
55
|
+
`This is an Upstash Workflow error thrown after a step executes. It is expected to be raised. Make sure that you await for each step. Also, if you are using try/catch blocks, you should not wrap context.run/sleep/sleepUntil/call methods with try/catch. Aborting workflow after executing step '${stepName}'.`
|
|
56
|
+
);
|
|
57
|
+
this.name = "WorkflowAbort";
|
|
58
|
+
this.stepName = stepName;
|
|
59
|
+
this.stepInfo = stepInfo;
|
|
60
|
+
this.cancelWorkflow = cancelWorkflow;
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
var WorkflowNonRetryableError = class extends WorkflowAbort {
|
|
64
|
+
/**
|
|
65
|
+
* @param message error message to be displayed
|
|
66
|
+
*/
|
|
67
|
+
constructor(message) {
|
|
68
|
+
super("fail", void 0, false);
|
|
69
|
+
this.name = "WorkflowNonRetryableError";
|
|
70
|
+
if (message) this.message = message;
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
var WorkflowRetryAfterError = class extends WorkflowAbort {
|
|
74
|
+
retryAfter;
|
|
75
|
+
/**
|
|
76
|
+
* @param retryAfter time in seconds after which the workflow should be retried
|
|
77
|
+
* @param message error message to be displayed
|
|
78
|
+
*/
|
|
79
|
+
constructor(message, retryAfter) {
|
|
80
|
+
super("retry", void 0, false);
|
|
81
|
+
this.name = "WorkflowRetryAfterError";
|
|
82
|
+
this.retryAfter = retryAfter;
|
|
83
|
+
if (message) this.message = message;
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
var formatWorkflowError = (error) => {
|
|
87
|
+
return error instanceof Error ? {
|
|
88
|
+
error: error.name,
|
|
89
|
+
message: error.message,
|
|
90
|
+
stack: error.stack
|
|
91
|
+
} : {
|
|
92
|
+
error: "Error",
|
|
93
|
+
message: `An error occured while executing workflow: '${typeof error === "string" ? error : JSON.stringify(error)}'`
|
|
94
|
+
};
|
|
95
|
+
};
|
|
96
|
+
function getConstructorName(obj) {
|
|
97
|
+
if (obj === null || obj === void 0) {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
const ctor = obj.constructor;
|
|
101
|
+
if (!ctor || ctor.name === "Object") {
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
return ctor.name;
|
|
105
|
+
}
|
|
106
|
+
function getConstructorNames(obj) {
|
|
107
|
+
const proto = Object.getPrototypeOf(obj);
|
|
108
|
+
const name = getConstructorName(proto);
|
|
109
|
+
if (name === null) {
|
|
110
|
+
return [];
|
|
111
|
+
}
|
|
112
|
+
return [name, ...getConstructorNames(proto)];
|
|
113
|
+
}
|
|
114
|
+
function isInstanceOf(v, ctor) {
|
|
115
|
+
return getConstructorNames(v).includes(ctor.name);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// src/client/utils.ts
|
|
31
119
|
var makeNotifyRequest = async (requester, eventId, eventData) => {
|
|
32
120
|
const result = await requester.request({
|
|
33
121
|
path: ["v2", "notify", eventId],
|
|
@@ -67,7 +155,7 @@ var getSteps = async (requester, workflowRunId, messageId, debug) => {
|
|
|
67
155
|
return { steps: filteredSteps, workflowRunEnded: false };
|
|
68
156
|
}
|
|
69
157
|
} catch (error) {
|
|
70
|
-
if (error
|
|
158
|
+
if (isInstanceOf(error, import_qstash2.QstashError) && error.status === 404) {
|
|
71
159
|
await debug?.log("WARN", "ENDPOINT_START", {
|
|
72
160
|
message: "Couldn't fetch workflow run steps. This can happen if the workflow run succesfully ends before some callback is executed.",
|
|
73
161
|
error
|
|
@@ -92,65 +180,13 @@ var WORKFLOW_PROTOCOL_VERSION_HEADER = "Upstash-Workflow-Sdk-Version";
|
|
|
92
180
|
var DEFAULT_CONTENT_TYPE = "application/json";
|
|
93
181
|
var NO_CONCURRENCY = 1;
|
|
94
182
|
var DEFAULT_RETRIES = 3;
|
|
95
|
-
var VERSION = "v0.2.
|
|
183
|
+
var VERSION = "v0.2.22";
|
|
96
184
|
var SDK_TELEMETRY = `@upstash/workflow@${VERSION}`;
|
|
97
185
|
var TELEMETRY_HEADER_SDK = "Upstash-Telemetry-Sdk";
|
|
98
186
|
var TELEMETRY_HEADER_FRAMEWORK = "Upstash-Telemetry-Framework";
|
|
99
187
|
var TELEMETRY_HEADER_RUNTIME = "Upstash-Telemetry-Runtime";
|
|
100
188
|
var TELEMETRY_HEADER_AGENT = "Upstash-Telemetry-Agent";
|
|
101
189
|
|
|
102
|
-
// src/error.ts
|
|
103
|
-
var import_qstash2 = require("@upstash/qstash");
|
|
104
|
-
var WorkflowError = class extends import_qstash2.QstashError {
|
|
105
|
-
constructor(message) {
|
|
106
|
-
super(message);
|
|
107
|
-
this.name = "WorkflowError";
|
|
108
|
-
}
|
|
109
|
-
};
|
|
110
|
-
var WorkflowAbort = class extends Error {
|
|
111
|
-
stepInfo;
|
|
112
|
-
stepName;
|
|
113
|
-
/**
|
|
114
|
-
* whether workflow is to be canceled on abort
|
|
115
|
-
*/
|
|
116
|
-
cancelWorkflow;
|
|
117
|
-
/**
|
|
118
|
-
*
|
|
119
|
-
* @param stepName name of the aborting step
|
|
120
|
-
* @param stepInfo step information
|
|
121
|
-
* @param cancelWorkflow
|
|
122
|
-
*/
|
|
123
|
-
constructor(stepName, stepInfo, cancelWorkflow = false) {
|
|
124
|
-
super(
|
|
125
|
-
`This is an Upstash Workflow error thrown after a step executes. It is expected to be raised. Make sure that you await for each step. Also, if you are using try/catch blocks, you should not wrap context.run/sleep/sleepUntil/call methods with try/catch. Aborting workflow after executing step '${stepName}'.`
|
|
126
|
-
);
|
|
127
|
-
this.name = "WorkflowAbort";
|
|
128
|
-
this.stepName = stepName;
|
|
129
|
-
this.stepInfo = stepInfo;
|
|
130
|
-
this.cancelWorkflow = cancelWorkflow;
|
|
131
|
-
}
|
|
132
|
-
};
|
|
133
|
-
var WorkflowNonRetryableError = class extends WorkflowAbort {
|
|
134
|
-
/**
|
|
135
|
-
* @param message error message to be displayed
|
|
136
|
-
*/
|
|
137
|
-
constructor(message) {
|
|
138
|
-
super("fail", void 0, false);
|
|
139
|
-
this.name = "WorkflowNonRetryableError";
|
|
140
|
-
if (message) this.message = message;
|
|
141
|
-
}
|
|
142
|
-
};
|
|
143
|
-
var formatWorkflowError = (error) => {
|
|
144
|
-
return error instanceof Error ? {
|
|
145
|
-
error: error.name,
|
|
146
|
-
message: error.message,
|
|
147
|
-
stack: error.stack
|
|
148
|
-
} : {
|
|
149
|
-
error: "Error",
|
|
150
|
-
message: `An error occured while executing workflow: '${typeof error === "string" ? error : JSON.stringify(error)}'`
|
|
151
|
-
};
|
|
152
|
-
};
|
|
153
|
-
|
|
154
190
|
// src/context/auto-executor.ts
|
|
155
191
|
var import_qstash5 = require("@upstash/qstash");
|
|
156
192
|
|
|
@@ -710,17 +746,17 @@ var triggerRouteFunction = async ({
|
|
|
710
746
|
return ok("workflow-finished");
|
|
711
747
|
} catch (error) {
|
|
712
748
|
const error_ = error;
|
|
713
|
-
if (error
|
|
749
|
+
if (isInstanceOf(error, import_qstash3.QstashError) && error.status === 400) {
|
|
714
750
|
await debug?.log("WARN", "RESPONSE_WORKFLOW", {
|
|
715
751
|
message: `tried to append to a cancelled workflow. exiting without publishing.`,
|
|
716
752
|
name: error.name,
|
|
717
753
|
errorMessage: error.message
|
|
718
754
|
});
|
|
719
755
|
return ok("workflow-was-finished");
|
|
720
|
-
} else if (
|
|
721
|
-
return err(error_);
|
|
722
|
-
} else if (error_ instanceof WorkflowNonRetryableError) {
|
|
756
|
+
} else if (isInstanceOf(error_, WorkflowNonRetryableError) || isInstanceOf(error_, WorkflowRetryAfterError)) {
|
|
723
757
|
return ok(error_);
|
|
758
|
+
} else if (!isInstanceOf(error_, WorkflowAbort)) {
|
|
759
|
+
return err(error_);
|
|
724
760
|
} else if (error_.cancelWorkflow) {
|
|
725
761
|
await onCancel();
|
|
726
762
|
return ok("workflow-finished");
|
|
@@ -2027,7 +2063,7 @@ var AutoExecutor = class _AutoExecutor {
|
|
|
2027
2063
|
});
|
|
2028
2064
|
throw new WorkflowAbort(parallelStep.stepName, resultStep);
|
|
2029
2065
|
} catch (error) {
|
|
2030
|
-
if (error
|
|
2066
|
+
if (isInstanceOf(error, WorkflowAbort) || isInstanceOf(error, import_qstash5.QstashError) && error.status === 400) {
|
|
2031
2067
|
throw error;
|
|
2032
2068
|
}
|
|
2033
2069
|
throw new WorkflowError(
|
|
@@ -2134,7 +2170,7 @@ var validateParallelSteps = (lazySteps, stepsFromRequest) => {
|
|
|
2134
2170
|
validateStep(lazySteps[index], stepFromRequest);
|
|
2135
2171
|
}
|
|
2136
2172
|
} catch (error) {
|
|
2137
|
-
if (error
|
|
2173
|
+
if (isInstanceOf(error, WorkflowError)) {
|
|
2138
2174
|
const lazyStepNames = lazySteps.map((lazyStep) => lazyStep.stepName);
|
|
2139
2175
|
const lazyStepTypes = lazySteps.map((lazyStep) => lazyStep.stepType);
|
|
2140
2176
|
const requestStepNames = stepsFromRequest.map((step) => step.stepName);
|
|
@@ -2315,7 +2351,7 @@ var fetchWithContextCall = async (context, agentCallParams, ...params) => {
|
|
|
2315
2351
|
headers: responseHeaders
|
|
2316
2352
|
});
|
|
2317
2353
|
} catch (error) {
|
|
2318
|
-
if (error instanceof Error && error
|
|
2354
|
+
if (error instanceof Error && isInstanceOf(error, WorkflowAbort)) {
|
|
2319
2355
|
throw error;
|
|
2320
2356
|
} else {
|
|
2321
2357
|
console.error("Error in fetch implementation:", error);
|
|
@@ -2417,10 +2453,10 @@ var Agent = class {
|
|
|
2417
2453
|
});
|
|
2418
2454
|
return { text: result.text };
|
|
2419
2455
|
} catch (error) {
|
|
2420
|
-
if (error
|
|
2421
|
-
if (error.cause instanceof Error && error.cause
|
|
2456
|
+
if (isInstanceOf(error, import_ai2.ToolExecutionError)) {
|
|
2457
|
+
if (error.cause instanceof Error && isInstanceOf(error.cause, WorkflowAbort)) {
|
|
2422
2458
|
throw error.cause;
|
|
2423
|
-
} else if (error.cause
|
|
2459
|
+
} else if (isInstanceOf(error.cause, import_ai2.ToolExecutionError) && isInstanceOf(error.cause.cause, WorkflowAbort)) {
|
|
2424
2460
|
throw error.cause.cause;
|
|
2425
2461
|
} else {
|
|
2426
2462
|
throw error;
|
|
@@ -3169,7 +3205,7 @@ var DisabledWorkflowContext = class _DisabledWorkflowContext extends WorkflowCon
|
|
|
3169
3205
|
try {
|
|
3170
3206
|
await routeFunction(disabledContext);
|
|
3171
3207
|
} catch (error) {
|
|
3172
|
-
if (error
|
|
3208
|
+
if (isInstanceOf(error, WorkflowAbort) && error.stepName === this.disabledMessage || isInstanceOf(error, WorkflowNonRetryableError) || isInstanceOf(error, WorkflowRetryAfterError)) {
|
|
3173
3209
|
return ok("step-found");
|
|
3174
3210
|
}
|
|
3175
3211
|
console.warn(
|
|
@@ -3422,13 +3458,24 @@ var processOptions = (options) => {
|
|
|
3422
3458
|
},
|
|
3423
3459
|
status: 489
|
|
3424
3460
|
});
|
|
3425
|
-
} else if (detailedFinishCondition?.condition === "
|
|
3426
|
-
return new Response(detailedFinishCondition.result
|
|
3427
|
-
status: 200,
|
|
3461
|
+
} else if (detailedFinishCondition?.condition === "retry-after-error") {
|
|
3462
|
+
return new Response(JSON.stringify(formatWorkflowError(detailedFinishCondition.result)), {
|
|
3428
3463
|
headers: {
|
|
3464
|
+
"Retry-After": detailedFinishCondition.result.retryAfter.toString(),
|
|
3429
3465
|
[WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION
|
|
3430
|
-
}
|
|
3466
|
+
},
|
|
3467
|
+
status: 429
|
|
3431
3468
|
});
|
|
3469
|
+
} else if (detailedFinishCondition?.condition === "failure-callback") {
|
|
3470
|
+
return new Response(
|
|
3471
|
+
JSON.stringify({ result: detailedFinishCondition.result ?? void 0 }),
|
|
3472
|
+
{
|
|
3473
|
+
status: 200,
|
|
3474
|
+
headers: {
|
|
3475
|
+
[WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION
|
|
3476
|
+
}
|
|
3477
|
+
}
|
|
3478
|
+
);
|
|
3432
3479
|
}
|
|
3433
3480
|
return new Response(JSON.stringify({ workflowRunId }), {
|
|
3434
3481
|
status: 200,
|
|
@@ -3638,12 +3685,18 @@ var serveBase = (routeFunction, telemetry2, options) => {
|
|
|
3638
3685
|
},
|
|
3639
3686
|
debug
|
|
3640
3687
|
});
|
|
3641
|
-
if (result.isOk() && result.value
|
|
3688
|
+
if (result.isOk() && isInstanceOf(result.value, WorkflowNonRetryableError)) {
|
|
3642
3689
|
return onStepFinish(workflowRunId, result.value, {
|
|
3643
3690
|
condition: "non-retryable-error",
|
|
3644
3691
|
result: result.value
|
|
3645
3692
|
});
|
|
3646
3693
|
}
|
|
3694
|
+
if (result.isOk() && isInstanceOf(result.value, WorkflowRetryAfterError)) {
|
|
3695
|
+
return onStepFinish(workflowRunId, result.value, {
|
|
3696
|
+
condition: "retry-after-error",
|
|
3697
|
+
result: result.value
|
|
3698
|
+
});
|
|
3699
|
+
}
|
|
3647
3700
|
if (result.isErr()) {
|
|
3648
3701
|
await debug?.log("ERROR", "ERROR", { error: result.error.message });
|
|
3649
3702
|
throw result.error;
|
|
@@ -3674,7 +3727,7 @@ var serveBase = (routeFunction, telemetry2, options) => {
|
|
|
3674
3727
|
const errorMessage = `Error while running onError callback: '${formattedOnErrorError.message}'.
|
|
3675
3728
|
Original error: '${formattedError.message}'`;
|
|
3676
3729
|
console.error(errorMessage);
|
|
3677
|
-
return new Response(errorMessage, {
|
|
3730
|
+
return new Response(JSON.stringify({ error: errorMessage }), {
|
|
3678
3731
|
status: 500,
|
|
3679
3732
|
headers: {
|
|
3680
3733
|
[WORKFLOW_PROTOCOL_VERSION_HEADER]: WORKFLOW_PROTOCOL_VERSION
|