@workflow/world-local 4.1.1 → 4.1.3
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/config.d.ts +6 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js.map +1 -1
- package/dist/fs.d.ts +57 -2
- package/dist/fs.d.ts.map +1 -1
- package/dist/fs.js +123 -9
- package/dist/fs.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +17 -3
- package/dist/index.js.map +1 -1
- package/dist/queue.d.ts.map +1 -1
- package/dist/queue.js +31 -1
- package/dist/queue.js.map +1 -1
- package/dist/storage/events-storage.d.ts.map +1 -1
- package/dist/storage/events-storage.js +33 -6
- package/dist/storage/events-storage.js.map +1 -1
- package/dist/storage/hooks-storage.d.ts.map +1 -1
- package/dist/storage/hooks-storage.js +2 -1
- package/dist/storage/hooks-storage.js.map +1 -1
- package/dist/storage/index.d.ts +10 -1
- package/dist/storage/index.d.ts.map +1 -1
- package/dist/storage/index.js +8 -10
- package/dist/storage/index.js.map +1 -1
- package/dist/storage/legacy.d.ts.map +1 -1
- package/dist/storage/legacy.js +8 -4
- package/dist/storage/legacy.js.map +1 -1
- package/dist/storage/runs-storage.d.ts +25 -3
- package/dist/storage/runs-storage.d.ts.map +1 -1
- package/dist/storage/runs-storage.js +5 -2
- package/dist/storage/runs-storage.js.map +1 -1
- package/dist/storage/steps-storage.d.ts.map +1 -1
- package/dist/storage/steps-storage.js +6 -1
- package/dist/storage/steps-storage.js.map +1 -1
- package/dist/streamer.d.ts.map +1 -1
- package/dist/streamer.js +44 -31
- package/dist/streamer.js.map +1 -1
- package/package.json +5 -5
package/dist/queue.js
CHANGED
|
@@ -45,6 +45,22 @@ const MAX_SAFE_TIMEOUT_MS = 2147483647;
|
|
|
45
45
|
const DEFAULT_CONCURRENCY_LIMIT = 1000;
|
|
46
46
|
const WORKFLOW_LOCAL_QUEUE_CONCURRENCY = parseInt(process.env.WORKFLOW_LOCAL_QUEUE_CONCURRENCY ?? '0', 10) ||
|
|
47
47
|
DEFAULT_CONCURRENCY_LIMIT;
|
|
48
|
+
const DETACHED_ARRAYBUFFER_ERROR = 'Cannot perform ArrayBuffer.prototype.slice on a detached ArrayBuffer';
|
|
49
|
+
const PROXY_HANDLER_DOCS_URL = 'https://workflow-sdk.dev/docs/getting-started/next#configure-proxy-handler';
|
|
50
|
+
function isDetachedArrayBufferQueueError(error) {
|
|
51
|
+
let current = error;
|
|
52
|
+
const visited = new Set();
|
|
53
|
+
while (current && typeof current === 'object' && !visited.has(current)) {
|
|
54
|
+
visited.add(current);
|
|
55
|
+
if ('message' in current &&
|
|
56
|
+
typeof current.message === 'string' &&
|
|
57
|
+
current.message.includes(DETACHED_ARRAYBUFFER_ERROR)) {
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
current = 'cause' in current ? current.cause : undefined;
|
|
61
|
+
}
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
48
64
|
function getQueueRoute(queueName) {
|
|
49
65
|
if (queueName.startsWith('__wkf_step_')) {
|
|
50
66
|
return { pathname: 'step', prefix: '__wkf_step_' };
|
|
@@ -185,7 +201,21 @@ export function createQueue(config) {
|
|
|
185
201
|
// These are expected and should not cause unhandled rejection warnings
|
|
186
202
|
const isAbortError = err?.name === 'AbortError' || err?.name === 'ResponseAborted';
|
|
187
203
|
if (!isAbortError) {
|
|
188
|
-
|
|
204
|
+
if (isDetachedArrayBufferQueueError(err)) {
|
|
205
|
+
console.error(`[local world] Queue operation failed: detected "${DETACHED_ARRAYBUFFER_ERROR}". ` +
|
|
206
|
+
"This usually means a Next.js proxy/middleware consumed Workflow's internal " +
|
|
207
|
+
'request before the executor could read it. Exclude `/.well-known/workflow/*` ' +
|
|
208
|
+
`from your matcher. See ${PROXY_HANDLER_DOCS_URL}`, {
|
|
209
|
+
queueName,
|
|
210
|
+
messageId,
|
|
211
|
+
...(runId && { runId }),
|
|
212
|
+
...(stepId && { stepId }),
|
|
213
|
+
originalError: err,
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
else {
|
|
217
|
+
console.error('[local world] Queue operation failed:', err);
|
|
218
|
+
}
|
|
189
219
|
}
|
|
190
220
|
})
|
|
191
221
|
.finally(() => {
|
package/dist/queue.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"queue.js","sourceRoot":"","sources":["../src/queue.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAElD,OAAO,EAAE,SAAS,EAAc,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACxE,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAClC,OAAO,EAAE,gBAAgB,EAAE,MAAM,MAAM,CAAC;AACxC,OAAO,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AAC/B,OAAO,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAC;AAE3B,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAE3C;;;;GAIG;AACH,MAAM,kBAAkB;IACb,WAAW,GAAG,kBAAkB,CAAC;IAE1C,SAAS,CAAC,KAAc;QACtB,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC;IAC1D,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,MAAkC;QAClD,MAAM,MAAM,GAAiB,EAAE,CAAC;QAChC,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,EAAE,CAAC;QAClC,OAAO,IAAI,EAAE,CAAC;YACZ,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;YAC5C,IAAI,IAAI;gBAAE,MAAM;YAChB,IAAI,KAAK;gBAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAChC,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,CAAC;QAC9C,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;IACvC,CAAC;CACF;AAED,mFAAmF;AACnF,+FAA+F;AAC/F,MAAM,0BAA0B,GAC9B,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,mCAAmC,IAAI,GAAG,EAAE,EAAE,CAAC;IACpE,QAAQ,CAAC;AAEX,oFAAoF;AACpF,4FAA4F;AAC5F,mFAAmF;AACnF,gEAAgE;AAChE,MAAM,mBAAmB,GAAG,UAAU,CAAC;AAEvC,mEAAmE;AACnE,oEAAoE;AACpE,MAAM,yBAAyB,GAAG,IAAI,CAAC;AACvC,MAAM,gCAAgC,GACpC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,gCAAgC,IAAI,GAAG,EAAE,EAAE,CAAC;IACjE,yBAAyB,CAAC;AAc5B,SAAS,aAAa,CAAC,SAAyB;IAI9C,IAAI,SAAS,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;QACxC,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC;IACrD,CAAC;IACD,IAAI,SAAS,CAAC,UAAU,CAAC,iBAAiB,CAAC,EAAE,CAAC;QAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,iBAAiB,EAAE,CAAC;IACzD,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,MAAuB;IACjD,wEAAwE;IACxE,gDAAgD;IAChD,wEAAwE;IACxE,uDAAuD;IACvD,0EAA0E;IAC1E,MAAM,SAAS,GAAG,IAAI,KAAK,CAAC;QAC1B,cAAc,EAAE,CAAC;QACjB,WAAW,EAAE,IAAI;QACjB,gBAAgB,EAAE,MAAM;KACzB,CAAC,CAAC;IACH,MAAM,SAAS,GAAG,IAAI,kBAAkB,EAAE,CAAC;IAC3C,MAAM,UAAU,GAAG,gBAAgB,EAAE,CAAC;IACtC,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,gCAAgC,CAAC,CAAC;IAE7D;;;OAGG;IACH,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAAqB,CAAC;IACtD,2EAA2E;IAC3E,MAAM,cAAc,GAAG,IAAI,GAAG,EAAyB,CAAC;IAExD,MAAM,KAAK,GAAmB,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE;QAC/D,MAAM,OAAO,GAAG,EAAoB,CAAC;QAErC,IAAI,IAAI,EAAE,cAAc,EAAE,CAAC;YACzB,MAAM,QAAQ,GAAG,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YAC3D,IAAI,QAAQ,EAAE,CAAC;gBACb,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC;YACjC,CAAC;QACH,CAAC;QAED,MAAM,IAAI,GAAG,SAAS,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QAC1C,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,aAAa,CAAC,SAAS,CAAC,CAAC;QACtD,MAAM,SAAS,GAAG,SAAS,CAAC,KAAK,CAAC,OAAO,UAAU,EAAE,EAAE,CAAC,CAAC;QAEzD,+DAA+D;QAC/D,iFAAiF;QACjF,MAAM,GAAG,GAAG,OAAkC,CAAC;QAC/C,MAAM,KAAK,GAAG,CAAC,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,aAAa,IAAI,SAAS,CAE7C,CAAC;QACd,MAAM,MAAM,GAAG,CAAC,GAAG,CAAC,MAAM,IAAI,SAAS,CAAuB,CAAC;QAE/D,IAAI,IAAI,EAAE,cAAc,EAAE,CAAC;YACzB,MAAM,GAAG,GAAG,IAAI,CAAC,cAAc,CAAC;YAChC,gBAAgB,CAAC,GAAG,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;YACrC,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE;gBAChB,gBAAgB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC/B,CAAC,CAAC,CAAC;QACL,CAAC;QAED,CAAC,KAAK,IAAI,EAAE;YACV,MAAM,KAAK,GAAG,SAAS,CAAC,UAAU,EAAE,CAAC;YACrC,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,OAAO,CAAC,IAAI,CACV,qCAAqC,gCAAgC,yCAAyC,CAC/G,CAAC;gBACF,MAAM,SAAS,CAAC,OAAO,EAAE,CAAC;YAC5B,CAAC;YACD,6DAA6D;YAC7D,4EAA4E;YAC5E,+EAA+E;YAC/E,MAAM,sBAAsB,GAAG,GAAG,CAAC;YACnC,IAAI,CAAC;gBACH,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,sBAAsB,EAAE,OAAO,EAAE,EAAE,CAAC;oBAClE,MAAM,OAAO,GAA2B;wBACtC,GAAG,IAAI,EAAE,OAAO;wBAChB,cAAc,EAAE,kBAAkB;wBAClC,kBAAkB,EAAE,SAAS;wBAC7B,kBAAkB,EAAE,SAAS;wBAC7B,uBAAuB,EAAE,MAAM,CAAC,OAAO,GAAG,CAAC,CAAC;qBAC7C,CAAC;oBACF,MAAM,aAAa,GAAG,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;oBACjD,IAAI,QAAkB,CAAC;oBAEvB,IAAI,aAAa,EAAE,CAAC;wBAClB,MAAM,GAAG,GAAG,IAAI,OAAO,CACrB,4CAA4C,QAAQ,EAAE,EACtD;4BACE,MAAM,EAAE,MAAM;4BACd,OAAO;4BACP,IAAI;yBACL,CACF,CAAC;wBACF,QAAQ,GAAG,MAAM,aAAa,CAAC,GAAG,CAAC,CAAC;oBACtC,CAAC;yBAAM,CAAC;wBACN,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,MAAM,CAAC,CAAC;wBAC7C,kIAAkI;wBAClI,QAAQ,GAAG,MAAM,KAAK,CACpB,GAAG,OAAO,4BAA4B,QAAQ,EAAE,EAChD;4BACE,MAAM,EAAE,MAAM;4BACd,MAAM,EAAE,MAAM;4BACd,UAAU,EAAE,SAAS;4BACrB,OAAO;4BACP,IAAI;yBACE,CACT,CAAC;oBACJ,CAAC;oBAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;oBAEnC,IAAI,QAAQ,CAAC,EAAE,EAAE,CAAC;wBAChB,IAAI,CAAC;4BACH,MAAM,cAAc,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,cAAc,CAAC,CAAC;4BAC/D,IAAI,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAC,IAAI,cAAc,IAAI,CAAC,EAAE,CAAC;gCAC3D,6EAA6E;gCAC7E,sEAAsE;gCACtE,iEAAiE;gCACjE,IAAI,cAAc,GAAG,CAAC,EAAE,CAAC;oCACvB,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CACxB,cAAc,GAAG,IAAI,EACrB,mBAAmB,CACpB,CAAC;oCACF,MAAM,UAAU,CAAC,SAAS,CAAC,CAAC;gCAC9B,CAAC;gCACD,SAAS;4BACX,CAAC;wBACH,CAAC;wBAAC,MAAM,CAAC,CAAA,CAAC;wBACV,OAAO;oBACT,CAAC;oBAED,OAAO,CAAC,KAAK,CACX,+CAA+C,OAAO,GAAG,CAAC,UAAU,QAAQ,CAAC,MAAM,GAAG,EACtF;wBACE,SAAS;wBACT,SAAS;wBACT,GAAG,CAAC,KAAK,IAAI,EAAE,KAAK,EAAE,CAAC;wBACvB,GAAG,CAAC,MAAM,IAAI,EAAE,MAAM,EAAE,CAAC;wBACzB,YAAY,EAAE,IAAI;qBACnB,CACF,CAAC;oBAEF,kEAAkE;oBAClE,kEAAkE;oBAClE,oEAAoE;oBACpE,uEAAuE;oBACvE,MAAM,UAAU,CAAC,IAAI,CAAC,CAAC;gBACzB,CAAC;gBAED,OAAO,CAAC,KAAK,CACX,uDAAuD,sBAAsB,YAAY,EACzF;oBACE,SAAS;oBACT,SAAS;oBACT,GAAG,CAAC,KAAK,IAAI,EAAE,KAAK,EAAE,CAAC;oBACvB,GAAG,CAAC,MAAM,IAAI,EAAE,MAAM,EAAE,CAAC;iBAC1B,CACF,CAAC;YACJ,CAAC;oBAAS,CAAC;gBACT,SAAS,CAAC,OAAO,EAAE,CAAC;YACtB,CAAC;QACH,CAAC,CAAC,EAAE;aACD,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;YACb,oFAAoF;YACpF,uEAAuE;YACvE,MAAM,YAAY,GAChB,GAAG,EAAE,IAAI,KAAK,YAAY,IAAI,GAAG,EAAE,IAAI,KAAK,iBAAiB,CAAC;YAChE,IAAI,CAAC,YAAY,EAAE,CAAC;gBAClB,OAAO,CAAC,KAAK,CAAC,uCAAuC,EAAE,GAAG,CAAC,CAAC;YAC9D,CAAC;QACH,CAAC,CAAC;aACD,OAAO,CAAC,GAAG,EAAE;YACZ,KAAK,MAAM,EAAE,IAAI,OAAO,EAAE,CAAC;gBACzB,EAAE,EAAE,CAAC;YACP,CAAC;QACH,CAAC,CAAC,CAAC;QAEL,OAAO,EAAE,SAAS,EAAE,CAAC;IACvB,CAAC,CAAC;IAEF,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,CAAC;QAC5B,kBAAkB,EAAE,cAAc;QAClC,kBAAkB,EAAE,SAAS;QAC7B,uBAAuB,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE;KAC3C,CAAC,CAAC;IAEH,MAAM,kBAAkB,GAAgC,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE;QAC1E,OAAO,KAAK,EAAE,GAAG,EAAE,EAAE;YACnB,MAAM,OAAO,GAAG,YAAY,CAAC,SAAS,CAAC,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;YAExE,IAAI,CAAC,OAAO,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;gBAClC,OAAO,QAAQ,CAAC,IAAI,CAClB;oBACE,KAAK,EAAE,CAAC,GAAG,CAAC,IAAI;wBACd,CAAC,CAAC,sBAAsB;wBACxB,CAAC,CAAC,0BAA0B;iBAC/B,EACD,EAAE,MAAM,EAAE,GAAG,EAAE,CAChB,CAAC;YACJ,CAAC;YAED,MAAM,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;YACnD,MAAM,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;YACnD,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;YAEtD,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;gBAClC,OAAO,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,iBAAiB,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;YACtE,CAAC;YAED,MAAM,IAAI,GAAG,MAAM,IAAI,kBAAkB,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAClE,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC,CAAC;gBAEtE,IAAI,cAAc,GAAkB,IAAI,CAAC;gBACzC,IAAI,OAAO,MAAM,EAAE,cAAc,KAAK,QAAQ,EAAE,CAAC;oBAC/C,cAAc,GAAG,IAAI,CAAC,GAAG,CACvB,MAAM,CAAC,cAAc,EACrB,0BAA0B,CAC3B,CAAC;gBACJ,CAAC;gBAED,IAAI,cAAc,IAAI,IAAI,EAAE,CAAC;oBAC3B,OAAO,QAAQ,CAAC,IAAI,CAAC,EAAE,cAAc,EAAE,CAAC,CAAC;gBAC3C,CAAC;gBAED,OAAO,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;YACrC,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;YACvD,CAAC;QACH,CAAC,CAAC;IACJ,CAAC,CAAC;IAEF,MAAM,eAAe,GAA6B,KAAK,IAAI,EAAE;QAC3D,MAAM,WAAW,GAAG,MAAM,cAAc,EAAE,CAAC;QAC3C,OAAO,aAAa,WAAW,CAAC,OAAO,EAAE,CAAC;IAC5C,CAAC,CAAC;IAEF,OAAO;QACL,KAAK;QACL,kBAAkB;QAClB,eAAe;QACf,eAAe,CACb,MAAyC,EACzC,OAAsB;YAEtB,cAAc,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACtC,CAAC;QACD,KAAK,CAAC,KAAK;YACT,MAAM,SAAS,CAAC,KAAK,EAAE,CAAC;QAC1B,CAAC;KACF,CAAC;AACJ,CAAC","sourcesContent":["import { setTimeout } from 'node:timers/promises';\nimport type { Transport } from '@vercel/queue';\nimport { MessageId, type Queue, ValidQueueName } from '@workflow/world';\nimport { Sema } from 'async-sema';\nimport { monotonicFactory } from 'ulid';\nimport { Agent } from 'undici';\nimport { z } from 'zod/v4';\nimport type { Config } from './config.js';\nimport { resolveBaseUrl } from './config.js';\nimport { jsonReplacer, jsonReviver } from './fs.js';\nimport { getPackageInfo } from './init.js';\n\n/**\n * JSON transport that preserves Uint8Array values using the same\n * replacer/reviver that world-local uses for filesystem storage.\n * Uint8Array → { __type: 'Uint8Array', data: '<base64>' } in JSON.\n */\nclass TypedJsonTransport implements Transport<unknown> {\n readonly contentType = 'application/json';\n\n serialize(value: unknown): Buffer {\n return Buffer.from(JSON.stringify(value, jsonReplacer));\n }\n\n async deserialize(stream: ReadableStream<Uint8Array>): Promise<unknown> {\n const chunks: Uint8Array[] = [];\n const reader = stream.getReader();\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n if (value) chunks.push(value);\n }\n const text = Buffer.concat(chunks).toString();\n return JSON.parse(text, jsonReviver);\n }\n}\n\n// For local queue, there is no technical limit on the message visibility lifespan,\n// but the environment variable can be used for testing purposes to set a max visibility limit.\nconst LOCAL_QUEUE_MAX_VISIBILITY =\n parseInt(process.env.WORKFLOW_LOCAL_QUEUE_MAX_VISIBILITY ?? '0', 10) ||\n Infinity;\n\n// Maximum safe delay for setTimeout in Node.js (2^31 - 1 milliseconds ≈ 24.85 days)\n// Larger values cause \"TimeoutOverflowWarning: X does not fit into a 32-bit signed integer\"\n// When the clamped timeout fires, the handler will recalculate remaining time from\n// persistent state and return another timeoutSeconds if needed.\nconst MAX_SAFE_TIMEOUT_MS = 2147483647;\n\n// The local workers share the same Node.js process and event loop,\n// so we need to limit concurrency to avoid overwhelming the system.\nconst DEFAULT_CONCURRENCY_LIMIT = 1000;\nconst WORKFLOW_LOCAL_QUEUE_CONCURRENCY =\n parseInt(process.env.WORKFLOW_LOCAL_QUEUE_CONCURRENCY ?? '0', 10) ||\n DEFAULT_CONCURRENCY_LIMIT;\n\nexport type DirectHandler = (req: Request) => Promise<Response>;\n\nexport type LocalQueue = Queue & {\n /** Close the HTTP agent and release resources. */\n close(): Promise<void>;\n /** Register a direct in-process handler for a queue prefix, bypassing HTTP. */\n registerHandler(\n prefix: '__wkf_step_' | '__wkf_workflow_',\n handler: DirectHandler\n ): void;\n};\n\nfunction getQueueRoute(queueName: ValidQueueName): {\n pathname: 'flow' | 'step';\n prefix: '__wkf_step_' | '__wkf_workflow_';\n} {\n if (queueName.startsWith('__wkf_step_')) {\n return { pathname: 'step', prefix: '__wkf_step_' };\n }\n if (queueName.startsWith('__wkf_workflow_')) {\n return { pathname: 'flow', prefix: '__wkf_workflow_' };\n }\n throw new Error('Unknown queue name prefix');\n}\n\nexport function createQueue(config: Partial<Config>): LocalQueue {\n // Create a custom agent optimized for high-concurrency local workflows:\n // - headersTimeout: 0 allows long-running steps\n // - connections: 1000 allows many parallel connections to the same host\n // - pipelining: 1 (default) for HTTP/1.1 compatibility\n // - keepAliveTimeout: 30s keeps connections warm for rapid step execution\n const httpAgent = new Agent({\n headersTimeout: 0,\n connections: 1000,\n keepAliveTimeout: 30_000,\n });\n const transport = new TypedJsonTransport();\n const generateId = monotonicFactory();\n const semaphore = new Sema(WORKFLOW_LOCAL_QUEUE_CONCURRENCY);\n\n /**\n * holds inflight messages by idempotency key to ensure\n * that we don't queue the same message multiple times\n */\n const inflightMessages = new Map<string, MessageId>();\n /** Direct in-process handlers by queue prefix, bypassing HTTP when set. */\n const directHandlers = new Map<string, DirectHandler>();\n\n const queue: Queue['queue'] = async (queueName, message, opts) => {\n const cleanup = [] as (() => void)[];\n\n if (opts?.idempotencyKey) {\n const existing = inflightMessages.get(opts.idempotencyKey);\n if (existing) {\n return { messageId: existing };\n }\n }\n\n const body = transport.serialize(message);\n const { pathname, prefix } = getQueueRoute(queueName);\n const messageId = MessageId.parse(`msg_${generateId()}`);\n\n // Extract identifiers from the message for structured logging.\n // Workflow messages have `runId`, step messages have `workflowRunId` + `stepId`.\n const msg = message as Record<string, unknown>;\n const runId = (msg.runId ?? msg.workflowRunId ?? undefined) as\n | string\n | undefined;\n const stepId = (msg.stepId ?? undefined) as string | undefined;\n\n if (opts?.idempotencyKey) {\n const key = opts.idempotencyKey;\n inflightMessages.set(key, messageId);\n cleanup.push(() => {\n inflightMessages.delete(key);\n });\n }\n\n (async () => {\n const token = semaphore.tryAcquire();\n if (!token) {\n console.warn(\n `[world-local]: concurrency limit (${WORKFLOW_LOCAL_QUEUE_CONCURRENCY}) reached, waiting for queue to free up`\n );\n await semaphore.acquire();\n }\n // Safety limit to prevent infinite loops in the local queue.\n // The actual max delivery enforcement happens in the workflow/step handlers\n // (at MAX_QUEUE_DELIVERIES = 48), so this just needs to be comfortably higher.\n const MAX_LOCAL_SAFETY_LIMIT = 256;\n try {\n for (let attempt = 0; attempt < MAX_LOCAL_SAFETY_LIMIT; attempt++) {\n const headers: Record<string, string> = {\n ...opts?.headers,\n 'content-type': 'application/json',\n 'x-vqs-queue-name': queueName,\n 'x-vqs-message-id': messageId,\n 'x-vqs-message-attempt': String(attempt + 1),\n };\n const directHandler = directHandlers.get(prefix);\n let response: Response;\n\n if (directHandler) {\n const req = new Request(\n `http://localhost/.well-known/workflow/v1/${pathname}`,\n {\n method: 'POST',\n headers,\n body,\n }\n );\n response = await directHandler(req);\n } else {\n const baseUrl = await resolveBaseUrl(config);\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- undici v7 dispatcher types don't match @types/node's RequestInit\n response = await fetch(\n `${baseUrl}/.well-known/workflow/v1/${pathname}`,\n {\n method: 'POST',\n duplex: 'half',\n dispatcher: httpAgent,\n headers,\n body,\n } as any\n );\n }\n\n const text = await response.text();\n\n if (response.ok) {\n try {\n const timeoutSeconds = Number(JSON.parse(text).timeoutSeconds);\n if (Number.isFinite(timeoutSeconds) && timeoutSeconds >= 0) {\n // Clamp to MAX_SAFE_TIMEOUT_MS to avoid Node.js setTimeout overflow warning.\n // When this fires early, the handler recalculates remaining time from\n // persistent state and returns another timeoutSeconds if needed.\n if (timeoutSeconds > 0) {\n const timeoutMs = Math.min(\n timeoutSeconds * 1000,\n MAX_SAFE_TIMEOUT_MS\n );\n await setTimeout(timeoutMs);\n }\n continue;\n }\n } catch {}\n return;\n }\n\n console.error(\n `[world-local] Queue message failed (attempt ${attempt + 1}, HTTP ${response.status})`,\n {\n queueName,\n messageId,\n ...(runId && { runId }),\n ...(stepId && { stepId }),\n handlerError: text,\n }\n );\n\n // 5s linear backoff to approximate VQS retry timing in local dev.\n // VQS uses 5s linear for attempts 1–32, then exponential, but for\n // local dev linear 5s is sufficient — the handler enforces the real\n // cap at MAX_QUEUE_DELIVERIES (48) which keeps total time under ~4min.\n await setTimeout(5000);\n }\n\n console.error(\n `[world-local] Queue message exhausted safety limit (${MAX_LOCAL_SAFETY_LIMIT} attempts)`,\n {\n queueName,\n messageId,\n ...(runId && { runId }),\n ...(stepId && { stepId }),\n }\n );\n } finally {\n semaphore.release();\n }\n })()\n .catch((err) => {\n // Silently ignore client disconnect errors (e.g., browser refresh during streaming)\n // These are expected and should not cause unhandled rejection warnings\n const isAbortError =\n err?.name === 'AbortError' || err?.name === 'ResponseAborted';\n if (!isAbortError) {\n console.error('[local world] Queue operation failed:', err);\n }\n })\n .finally(() => {\n for (const fn of cleanup) {\n fn();\n }\n });\n\n return { messageId };\n };\n\n const HeaderParser = z.object({\n 'x-vqs-queue-name': ValidQueueName,\n 'x-vqs-message-id': MessageId,\n 'x-vqs-message-attempt': z.coerce.number(),\n });\n\n const createQueueHandler: Queue['createQueueHandler'] = (prefix, handler) => {\n return async (req) => {\n const headers = HeaderParser.safeParse(Object.fromEntries(req.headers));\n\n if (!headers.success || !req.body) {\n return Response.json(\n {\n error: !req.body\n ? 'Missing request body'\n : 'Missing required headers',\n },\n { status: 400 }\n );\n }\n\n const queueName = headers.data['x-vqs-queue-name'];\n const messageId = headers.data['x-vqs-message-id'];\n const attempt = headers.data['x-vqs-message-attempt'];\n\n if (!queueName.startsWith(prefix)) {\n return Response.json({ error: 'Unhandled queue' }, { status: 400 });\n }\n\n const body = await new TypedJsonTransport().deserialize(req.body);\n try {\n const result = await handler(body, { attempt, queueName, messageId });\n\n let timeoutSeconds: number | null = null;\n if (typeof result?.timeoutSeconds === 'number') {\n timeoutSeconds = Math.min(\n result.timeoutSeconds,\n LOCAL_QUEUE_MAX_VISIBILITY\n );\n }\n\n if (timeoutSeconds != null) {\n return Response.json({ timeoutSeconds });\n }\n\n return Response.json({ ok: true });\n } catch (error) {\n return Response.json(String(error), { status: 500 });\n }\n };\n };\n\n const getDeploymentId: Queue['getDeploymentId'] = async () => {\n const packageInfo = await getPackageInfo();\n return `dpl_local@${packageInfo.version}`;\n };\n\n return {\n queue,\n createQueueHandler,\n getDeploymentId,\n registerHandler(\n prefix: '__wkf_step_' | '__wkf_workflow_',\n handler: DirectHandler\n ) {\n directHandlers.set(prefix, handler);\n },\n async close() {\n await httpAgent.close();\n },\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"queue.js","sourceRoot":"","sources":["../src/queue.ts"],"names":[],"mappings":"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","sourcesContent":["import { setTimeout } from 'node:timers/promises';\nimport type { Transport } from '@vercel/queue';\nimport { MessageId, type Queue, ValidQueueName } from '@workflow/world';\nimport { Sema } from 'async-sema';\nimport { monotonicFactory } from 'ulid';\nimport { Agent } from 'undici';\nimport { z } from 'zod/v4';\nimport type { Config } from './config.js';\nimport { resolveBaseUrl } from './config.js';\nimport { jsonReplacer, jsonReviver } from './fs.js';\nimport { getPackageInfo } from './init.js';\n\n/**\n * JSON transport that preserves Uint8Array values using the same\n * replacer/reviver that world-local uses for filesystem storage.\n * Uint8Array → { __type: 'Uint8Array', data: '<base64>' } in JSON.\n */\nclass TypedJsonTransport implements Transport<unknown> {\n readonly contentType = 'application/json';\n\n serialize(value: unknown): Buffer {\n return Buffer.from(JSON.stringify(value, jsonReplacer));\n }\n\n async deserialize(stream: ReadableStream<Uint8Array>): Promise<unknown> {\n const chunks: Uint8Array[] = [];\n const reader = stream.getReader();\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n if (value) chunks.push(value);\n }\n const text = Buffer.concat(chunks).toString();\n return JSON.parse(text, jsonReviver);\n }\n}\n\n// For local queue, there is no technical limit on the message visibility lifespan,\n// but the environment variable can be used for testing purposes to set a max visibility limit.\nconst LOCAL_QUEUE_MAX_VISIBILITY =\n parseInt(process.env.WORKFLOW_LOCAL_QUEUE_MAX_VISIBILITY ?? '0', 10) ||\n Infinity;\n\n// Maximum safe delay for setTimeout in Node.js (2^31 - 1 milliseconds ≈ 24.85 days)\n// Larger values cause \"TimeoutOverflowWarning: X does not fit into a 32-bit signed integer\"\n// When the clamped timeout fires, the handler will recalculate remaining time from\n// persistent state and return another timeoutSeconds if needed.\nconst MAX_SAFE_TIMEOUT_MS = 2147483647;\n\n// The local workers share the same Node.js process and event loop,\n// so we need to limit concurrency to avoid overwhelming the system.\nconst DEFAULT_CONCURRENCY_LIMIT = 1000;\nconst WORKFLOW_LOCAL_QUEUE_CONCURRENCY =\n parseInt(process.env.WORKFLOW_LOCAL_QUEUE_CONCURRENCY ?? '0', 10) ||\n DEFAULT_CONCURRENCY_LIMIT;\n\nexport type DirectHandler = (req: Request) => Promise<Response>;\n\nexport type LocalQueue = Queue & {\n /** Close the HTTP agent and release resources. */\n close(): Promise<void>;\n /** Register a direct in-process handler for a queue prefix, bypassing HTTP. */\n registerHandler(\n prefix: '__wkf_step_' | '__wkf_workflow_',\n handler: DirectHandler\n ): void;\n};\n\nconst DETACHED_ARRAYBUFFER_ERROR =\n 'Cannot perform ArrayBuffer.prototype.slice on a detached ArrayBuffer';\nconst PROXY_HANDLER_DOCS_URL =\n 'https://workflow-sdk.dev/docs/getting-started/next#configure-proxy-handler';\n\nfunction isDetachedArrayBufferQueueError(error: unknown): boolean {\n let current = error;\n const visited = new Set<unknown>();\n\n while (current && typeof current === 'object' && !visited.has(current)) {\n visited.add(current);\n if (\n 'message' in current &&\n typeof current.message === 'string' &&\n current.message.includes(DETACHED_ARRAYBUFFER_ERROR)\n ) {\n return true;\n }\n current = 'cause' in current ? current.cause : undefined;\n }\n\n return false;\n}\n\nfunction getQueueRoute(queueName: ValidQueueName): {\n pathname: 'flow' | 'step';\n prefix: '__wkf_step_' | '__wkf_workflow_';\n} {\n if (queueName.startsWith('__wkf_step_')) {\n return { pathname: 'step', prefix: '__wkf_step_' };\n }\n if (queueName.startsWith('__wkf_workflow_')) {\n return { pathname: 'flow', prefix: '__wkf_workflow_' };\n }\n throw new Error('Unknown queue name prefix');\n}\n\nexport function createQueue(config: Partial<Config>): LocalQueue {\n // Create a custom agent optimized for high-concurrency local workflows:\n // - headersTimeout: 0 allows long-running steps\n // - connections: 1000 allows many parallel connections to the same host\n // - pipelining: 1 (default) for HTTP/1.1 compatibility\n // - keepAliveTimeout: 30s keeps connections warm for rapid step execution\n const httpAgent = new Agent({\n headersTimeout: 0,\n connections: 1000,\n keepAliveTimeout: 30_000,\n });\n const transport = new TypedJsonTransport();\n const generateId = monotonicFactory();\n const semaphore = new Sema(WORKFLOW_LOCAL_QUEUE_CONCURRENCY);\n\n /**\n * holds inflight messages by idempotency key to ensure\n * that we don't queue the same message multiple times\n */\n const inflightMessages = new Map<string, MessageId>();\n /** Direct in-process handlers by queue prefix, bypassing HTTP when set. */\n const directHandlers = new Map<string, DirectHandler>();\n\n const queue: Queue['queue'] = async (queueName, message, opts) => {\n const cleanup = [] as (() => void)[];\n\n if (opts?.idempotencyKey) {\n const existing = inflightMessages.get(opts.idempotencyKey);\n if (existing) {\n return { messageId: existing };\n }\n }\n\n const body = transport.serialize(message);\n const { pathname, prefix } = getQueueRoute(queueName);\n const messageId = MessageId.parse(`msg_${generateId()}`);\n\n // Extract identifiers from the message for structured logging.\n // Workflow messages have `runId`, step messages have `workflowRunId` + `stepId`.\n const msg = message as Record<string, unknown>;\n const runId = (msg.runId ?? msg.workflowRunId ?? undefined) as\n | string\n | undefined;\n const stepId = (msg.stepId ?? undefined) as string | undefined;\n\n if (opts?.idempotencyKey) {\n const key = opts.idempotencyKey;\n inflightMessages.set(key, messageId);\n cleanup.push(() => {\n inflightMessages.delete(key);\n });\n }\n\n (async () => {\n const token = semaphore.tryAcquire();\n if (!token) {\n console.warn(\n `[world-local]: concurrency limit (${WORKFLOW_LOCAL_QUEUE_CONCURRENCY}) reached, waiting for queue to free up`\n );\n await semaphore.acquire();\n }\n // Safety limit to prevent infinite loops in the local queue.\n // The actual max delivery enforcement happens in the workflow/step handlers\n // (at MAX_QUEUE_DELIVERIES = 48), so this just needs to be comfortably higher.\n const MAX_LOCAL_SAFETY_LIMIT = 256;\n try {\n for (let attempt = 0; attempt < MAX_LOCAL_SAFETY_LIMIT; attempt++) {\n const headers: Record<string, string> = {\n ...opts?.headers,\n 'content-type': 'application/json',\n 'x-vqs-queue-name': queueName,\n 'x-vqs-message-id': messageId,\n 'x-vqs-message-attempt': String(attempt + 1),\n };\n const directHandler = directHandlers.get(prefix);\n let response: Response;\n\n if (directHandler) {\n const req = new Request(\n `http://localhost/.well-known/workflow/v1/${pathname}`,\n {\n method: 'POST',\n headers,\n body,\n }\n );\n response = await directHandler(req);\n } else {\n const baseUrl = await resolveBaseUrl(config);\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- undici v7 dispatcher types don't match @types/node's RequestInit\n response = await fetch(\n `${baseUrl}/.well-known/workflow/v1/${pathname}`,\n {\n method: 'POST',\n duplex: 'half',\n dispatcher: httpAgent,\n headers,\n body,\n } as any\n );\n }\n\n const text = await response.text();\n\n if (response.ok) {\n try {\n const timeoutSeconds = Number(JSON.parse(text).timeoutSeconds);\n if (Number.isFinite(timeoutSeconds) && timeoutSeconds >= 0) {\n // Clamp to MAX_SAFE_TIMEOUT_MS to avoid Node.js setTimeout overflow warning.\n // When this fires early, the handler recalculates remaining time from\n // persistent state and returns another timeoutSeconds if needed.\n if (timeoutSeconds > 0) {\n const timeoutMs = Math.min(\n timeoutSeconds * 1000,\n MAX_SAFE_TIMEOUT_MS\n );\n await setTimeout(timeoutMs);\n }\n continue;\n }\n } catch {}\n return;\n }\n\n console.error(\n `[world-local] Queue message failed (attempt ${attempt + 1}, HTTP ${response.status})`,\n {\n queueName,\n messageId,\n ...(runId && { runId }),\n ...(stepId && { stepId }),\n handlerError: text,\n }\n );\n\n // 5s linear backoff to approximate VQS retry timing in local dev.\n // VQS uses 5s linear for attempts 1–32, then exponential, but for\n // local dev linear 5s is sufficient — the handler enforces the real\n // cap at MAX_QUEUE_DELIVERIES (48) which keeps total time under ~4min.\n await setTimeout(5000);\n }\n\n console.error(\n `[world-local] Queue message exhausted safety limit (${MAX_LOCAL_SAFETY_LIMIT} attempts)`,\n {\n queueName,\n messageId,\n ...(runId && { runId }),\n ...(stepId && { stepId }),\n }\n );\n } finally {\n semaphore.release();\n }\n })()\n .catch((err) => {\n // Silently ignore client disconnect errors (e.g., browser refresh during streaming)\n // These are expected and should not cause unhandled rejection warnings\n const isAbortError =\n err?.name === 'AbortError' || err?.name === 'ResponseAborted';\n if (!isAbortError) {\n if (isDetachedArrayBufferQueueError(err)) {\n console.error(\n `[local world] Queue operation failed: detected \"${DETACHED_ARRAYBUFFER_ERROR}\". ` +\n \"This usually means a Next.js proxy/middleware consumed Workflow's internal \" +\n 'request before the executor could read it. Exclude `/.well-known/workflow/*` ' +\n `from your matcher. See ${PROXY_HANDLER_DOCS_URL}`,\n {\n queueName,\n messageId,\n ...(runId && { runId }),\n ...(stepId && { stepId }),\n originalError: err,\n }\n );\n } else {\n console.error('[local world] Queue operation failed:', err);\n }\n }\n })\n .finally(() => {\n for (const fn of cleanup) {\n fn();\n }\n });\n\n return { messageId };\n };\n\n const HeaderParser = z.object({\n 'x-vqs-queue-name': ValidQueueName,\n 'x-vqs-message-id': MessageId,\n 'x-vqs-message-attempt': z.coerce.number(),\n });\n\n const createQueueHandler: Queue['createQueueHandler'] = (prefix, handler) => {\n return async (req) => {\n const headers = HeaderParser.safeParse(Object.fromEntries(req.headers));\n\n if (!headers.success || !req.body) {\n return Response.json(\n {\n error: !req.body\n ? 'Missing request body'\n : 'Missing required headers',\n },\n { status: 400 }\n );\n }\n\n const queueName = headers.data['x-vqs-queue-name'];\n const messageId = headers.data['x-vqs-message-id'];\n const attempt = headers.data['x-vqs-message-attempt'];\n\n if (!queueName.startsWith(prefix)) {\n return Response.json({ error: 'Unhandled queue' }, { status: 400 });\n }\n\n const body = await new TypedJsonTransport().deserialize(req.body);\n try {\n const result = await handler(body, { attempt, queueName, messageId });\n\n let timeoutSeconds: number | null = null;\n if (typeof result?.timeoutSeconds === 'number') {\n timeoutSeconds = Math.min(\n result.timeoutSeconds,\n LOCAL_QUEUE_MAX_VISIBILITY\n );\n }\n\n if (timeoutSeconds != null) {\n return Response.json({ timeoutSeconds });\n }\n\n return Response.json({ ok: true });\n } catch (error) {\n return Response.json(String(error), { status: 500 });\n }\n };\n };\n\n const getDeploymentId: Queue['getDeploymentId'] = async () => {\n const packageInfo = await getPackageInfo();\n return `dpl_local@${packageInfo.version}`;\n };\n\n return {\n queue,\n createQueueHandler,\n getDeploymentId,\n registerHandler(\n prefix: '__wkf_step_' | '__wkf_workflow_',\n handler: DirectHandler\n ) {\n directHandlers.set(prefix, handler);\n },\n async close() {\n await httpAgent.close();\n },\n };\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"events-storage.d.ts","sourceRoot":"","sources":["../../src/storage/events-storage.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAMV,OAAO,EAGR,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"events-storage.d.ts","sourceRoot":"","sources":["../../src/storage/events-storage.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAMV,OAAO,EAGR,MAAM,iBAAiB,CAAC;AAmDzB;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,MAAM,EACf,GAAG,CAAC,EAAE,MAAM,GACX,OAAO,CAAC,QAAQ,CAAC,CAu/BnB"}
|
|
@@ -3,7 +3,7 @@ import path from 'node:path';
|
|
|
3
3
|
import { EntityConflictError, HookNotFoundError, RunExpiredError, RunNotSupportedError, TooEarlyError, WorkflowWorldError, } from '@workflow/errors';
|
|
4
4
|
import { EventSchema, HookSchema, isLegacySpecVersion, requiresNewerWorld, SPEC_VERSION_CURRENT, StepSchema, validateUlidTimestamp, WaitSchema, WorkflowRunSchema, } from '@workflow/world';
|
|
5
5
|
import { DEFAULT_RESOLVE_DATA_OPTION } from '../config.js';
|
|
6
|
-
import { deleteJSON, jsonReplacer, listJSONFiles, paginatedFileSystemQuery, readJSONWithFallback, taggedPath, writeExclusive, writeJSON, } from '../fs.js';
|
|
6
|
+
import { assertSafeEntityId, deleteJSON, jsonReplacer, listJSONFiles, paginatedFileSystemQuery, readJSONWithFallback, resolveWithinBase, taggedPath, writeExclusive, writeJSON, } from '../fs.js';
|
|
7
7
|
import { stripEventDataRefs } from './filters.js';
|
|
8
8
|
import { getObjectCreatedAt, hashToken, monotonicUlid } from './helpers.js';
|
|
9
9
|
import { deleteAllHooksForRun } from './hooks-storage.js';
|
|
@@ -33,6 +33,22 @@ export function createEventsStorage(basedir, tag) {
|
|
|
33
33
|
async create(runId, data, params) {
|
|
34
34
|
const eventId = `evnt_${monotonicUlid()}`;
|
|
35
35
|
const now = new Date();
|
|
36
|
+
// Validate request-supplied IDs before they're concatenated into
|
|
37
|
+
// filesystem paths. This is the primary defense against path traversal
|
|
38
|
+
// attacks where a client supplies runId / correlationId values like
|
|
39
|
+
// "../../../package" to read or write files outside the storage root.
|
|
40
|
+
//
|
|
41
|
+
// Empty `correlationId` values are also rejected here: the event
|
|
42
|
+
// schemas only require `z.string()`, so without this check a
|
|
43
|
+
// step_created / hook_created / wait_created request with
|
|
44
|
+
// `correlationId: ''` would silently be written under a malformed
|
|
45
|
+
// composite key like `${runId}-`.
|
|
46
|
+
if (runId != null && runId !== '') {
|
|
47
|
+
assertSafeEntityId('runId', runId);
|
|
48
|
+
}
|
|
49
|
+
if ('correlationId' in data && typeof data.correlationId === 'string') {
|
|
50
|
+
assertSafeEntityId('correlationId', data.correlationId);
|
|
51
|
+
}
|
|
36
52
|
// For run_created events, use client-provided runId or generate one server-side
|
|
37
53
|
let effectiveRunId;
|
|
38
54
|
if (data.eventType === 'run_created' && (!runId || runId === '')) {
|
|
@@ -277,7 +293,7 @@ export function createEventsStorage(basedir, tag) {
|
|
|
277
293
|
// duplicate event. This makes run_started idempotent for
|
|
278
294
|
// concurrent invocations. We omit preloaded events here
|
|
279
295
|
// because this is a rare race-condition path — the runtime
|
|
280
|
-
// falls back to
|
|
296
|
+
// falls back to loading events separately.
|
|
281
297
|
if (currentRun.status === 'running') {
|
|
282
298
|
return { run: currentRun };
|
|
283
299
|
}
|
|
@@ -457,7 +473,7 @@ export function createEventsStorage(basedir, tag) {
|
|
|
457
473
|
const lockName = tag
|
|
458
474
|
? `${stepCompositeKey}.terminal.${tag}`
|
|
459
475
|
: `${stepCompositeKey}.terminal`;
|
|
460
|
-
const terminalLockPath =
|
|
476
|
+
const terminalLockPath = resolveWithinBase(basedir, '.locks', 'steps', lockName);
|
|
461
477
|
const claimed = await writeExclusive(terminalLockPath, '');
|
|
462
478
|
if (!claimed) {
|
|
463
479
|
throw new EntityConflictError('Cannot modify step in terminal state');
|
|
@@ -482,7 +498,7 @@ export function createEventsStorage(basedir, tag) {
|
|
|
482
498
|
const lockName = tag
|
|
483
499
|
? `${stepCompositeKey}.terminal.${tag}`
|
|
484
500
|
: `${stepCompositeKey}.terminal`;
|
|
485
|
-
const terminalLockPath =
|
|
501
|
+
const terminalLockPath = resolveWithinBase(basedir, '.locks', 'steps', lockName);
|
|
486
502
|
const claimed = await writeExclusive(terminalLockPath, '');
|
|
487
503
|
if (!claimed) {
|
|
488
504
|
throw new EntityConflictError('Cannot modify step in terminal state');
|
|
@@ -586,7 +602,7 @@ export function createEventsStorage(basedir, tag) {
|
|
|
586
602
|
const hookLockName = tag
|
|
587
603
|
? `${data.correlationId}.disposed.${tag}`
|
|
588
604
|
: `${data.correlationId}.disposed`;
|
|
589
|
-
const lockPath =
|
|
605
|
+
const lockPath = resolveWithinBase(basedir, '.locks', 'hooks', hookLockName);
|
|
590
606
|
const claimed = await writeExclusive(lockPath, '');
|
|
591
607
|
if (!claimed) {
|
|
592
608
|
throw new EntityConflictError(`Hook "${data.correlationId}" already disposed`);
|
|
@@ -629,7 +645,7 @@ export function createEventsStorage(basedir, tag) {
|
|
|
629
645
|
const waitLockName = tag
|
|
630
646
|
? `${waitCompositeKey}.completed.${tag}`
|
|
631
647
|
: `${waitCompositeKey}.completed`;
|
|
632
|
-
const lockPath =
|
|
648
|
+
const lockPath = resolveWithinBase(basedir, '.locks', 'waits', waitLockName);
|
|
633
649
|
const claimed = await writeExclusive(lockPath, '');
|
|
634
650
|
if (!claimed) {
|
|
635
651
|
throw new EntityConflictError(`Wait "${data.correlationId}" already completed`);
|
|
@@ -660,16 +676,21 @@ export function createEventsStorage(basedir, tag) {
|
|
|
660
676
|
// For run_started: include all events so the runtime can skip
|
|
661
677
|
// the initial events.list call and reduce TTFB.
|
|
662
678
|
let events;
|
|
679
|
+
let cursor;
|
|
680
|
+
let hasMore;
|
|
663
681
|
if (data.eventType === 'run_started' && run) {
|
|
664
682
|
const allEvents = await paginatedFileSystemQuery({
|
|
665
683
|
directory: path.join(basedir, 'events'),
|
|
666
684
|
schema: EventSchema,
|
|
667
685
|
filePrefix: `${effectiveRunId}-`,
|
|
668
686
|
sortOrder: 'asc',
|
|
687
|
+
limit: 1000,
|
|
669
688
|
getCreatedAt: getObjectCreatedAt('evnt'),
|
|
670
689
|
getId: (e) => e.eventId,
|
|
671
690
|
});
|
|
672
691
|
events = allEvents.data;
|
|
692
|
+
cursor = allEvents.cursor;
|
|
693
|
+
hasMore = allEvents.hasMore;
|
|
673
694
|
}
|
|
674
695
|
// Return EventResult with event and any created/updated entity
|
|
675
696
|
return {
|
|
@@ -679,9 +700,13 @@ export function createEventsStorage(basedir, tag) {
|
|
|
679
700
|
hook,
|
|
680
701
|
wait,
|
|
681
702
|
events,
|
|
703
|
+
cursor,
|
|
704
|
+
hasMore,
|
|
682
705
|
};
|
|
683
706
|
},
|
|
684
707
|
async get(runId, eventId, params) {
|
|
708
|
+
assertSafeEntityId('runId', runId);
|
|
709
|
+
assertSafeEntityId('eventId', eventId);
|
|
685
710
|
const compositeKey = `${runId}-${eventId}`;
|
|
686
711
|
const event = await readJSONWithFallback(basedir, 'events', compositeKey, EventSchema, tag);
|
|
687
712
|
if (!event) {
|
|
@@ -692,6 +717,7 @@ export function createEventsStorage(basedir, tag) {
|
|
|
692
717
|
},
|
|
693
718
|
async list(params) {
|
|
694
719
|
const { runId } = params;
|
|
720
|
+
assertSafeEntityId('runId', runId);
|
|
695
721
|
const resolveData = params.resolveData ?? DEFAULT_RESOLVE_DATA_OPTION;
|
|
696
722
|
const result = await paginatedFileSystemQuery({
|
|
697
723
|
directory: path.join(basedir, 'events'),
|
|
@@ -716,6 +742,7 @@ export function createEventsStorage(basedir, tag) {
|
|
|
716
742
|
},
|
|
717
743
|
async listByCorrelationId(params) {
|
|
718
744
|
const correlationId = params.correlationId;
|
|
745
|
+
assertSafeEntityId('correlationId', correlationId);
|
|
719
746
|
const resolveData = params.resolveData ?? DEFAULT_RESOLVE_DATA_OPTION;
|
|
720
747
|
const result = await paginatedFileSystemQuery({
|
|
721
748
|
directory: path.join(basedir, 'events'),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"events-storage.js","sourceRoot":"","sources":["../../src/storage/events-storage.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport {\n EntityConflictError,\n HookNotFoundError,\n RunExpiredError,\n RunNotSupportedError,\n TooEarlyError,\n WorkflowWorldError,\n} from '@workflow/errors';\nimport type {\n Event,\n EventResult,\n Hook,\n SerializedData,\n Step,\n Storage,\n Wait,\n WorkflowRun,\n} from '@workflow/world';\nimport {\n EventSchema,\n HookSchema,\n isLegacySpecVersion,\n requiresNewerWorld,\n SPEC_VERSION_CURRENT,\n StepSchema,\n validateUlidTimestamp,\n WaitSchema,\n WorkflowRunSchema,\n} from '@workflow/world';\nimport { DEFAULT_RESOLVE_DATA_OPTION } from '../config.js';\nimport {\n deleteJSON,\n jsonReplacer,\n listJSONFiles,\n paginatedFileSystemQuery,\n readJSONWithFallback,\n taggedPath,\n writeExclusive,\n writeJSON,\n} from '../fs.js';\nimport { stripEventDataRefs } from './filters.js';\nimport { getObjectCreatedAt, hashToken, monotonicUlid } from './helpers.js';\nimport { deleteAllHooksForRun } from './hooks-storage.js';\nimport { handleLegacyEvent } from './legacy.js';\n\n/**\n * Helper function to delete all waits associated with a workflow run.\n * Called when a run reaches a terminal state.\n */\nasync function deleteAllWaitsForRun(\n basedir: string,\n runId: string\n): Promise<void> {\n const waitsDir = path.join(basedir, 'waits');\n const files = await listJSONFiles(waitsDir);\n\n for (const file of files) {\n // fileIds may contain tag suffixes (e.g., \"wrun_ABC-corrId.vitest-0\")\n // but startsWith still matches correctly since the tag is a suffix.\n if (file.startsWith(`${runId}-`)) {\n const waitPath = path.join(waitsDir, `${file}.json`);\n await deleteJSON(waitPath);\n }\n }\n}\n\n/**\n * Creates the events storage implementation using the filesystem.\n * Implements the Storage['events'] interface with create, list, and listByCorrelationId operations.\n */\nexport function createEventsStorage(\n basedir: string,\n tag?: string\n): Storage['events'] {\n return {\n async create(runId, data, params): Promise<EventResult> {\n const eventId = `evnt_${monotonicUlid()}`;\n const now = new Date();\n\n // For run_created events, use client-provided runId or generate one server-side\n let effectiveRunId: string;\n if (data.eventType === 'run_created' && (!runId || runId === '')) {\n effectiveRunId = `wrun_${monotonicUlid()}`;\n } else if (!runId) {\n throw new Error('runId is required for non-run_created events');\n } else {\n effectiveRunId = runId;\n }\n\n // Validate client-provided runId timestamp is within acceptable threshold\n if (data.eventType === 'run_created' && runId && runId !== '') {\n const validationError = validateUlidTimestamp(effectiveRunId, 'wrun_');\n if (validationError) {\n throw new WorkflowWorldError(validationError);\n }\n }\n\n // specVersion is always sent by the runtime, but we provide a fallback for safety\n const effectiveSpecVersion = data.specVersion ?? SPEC_VERSION_CURRENT;\n\n // Helper to check if run is in terminal state\n const isRunTerminal = (status: string) =>\n ['completed', 'failed', 'cancelled'].includes(status);\n\n // Helper to check if step is in terminal state\n const isStepTerminal = (status: string) =>\n ['completed', 'failed', 'cancelled'].includes(status);\n\n // Get current run state for validation (if not creating a new run)\n // Skip run validation for step_completed and step_retrying - they only operate\n // on running steps, and running steps are always allowed to modify regardless\n // of run state. This optimization saves filesystem reads per step event.\n let currentRun: WorkflowRun | null = null;\n const skipRunValidationEvents = ['step_completed', 'step_retrying'];\n if (\n data.eventType !== 'run_created' &&\n !skipRunValidationEvents.includes(data.eventType)\n ) {\n currentRun = await readJSONWithFallback(\n basedir,\n 'runs',\n effectiveRunId,\n WorkflowRunSchema,\n tag\n );\n\n // Resilient start: run_started on non-existent run with eventData\n // creates the run first, so the queue can bootstrap a run that\n // failed to create during start().\n if (\n data.eventType === 'run_started' &&\n !currentRun &&\n 'eventData' in data &&\n data.eventData\n ) {\n const runInputData = data.eventData as {\n deploymentId?: string;\n workflowName?: string;\n input?: any;\n executionContext?: Record<string, any>;\n };\n if (\n runInputData.deploymentId &&\n runInputData.workflowName &&\n runInputData.input !== undefined\n ) {\n // Atomically try to create the run entity. writeExclusive\n // uses O_CREAT|O_EXCL so only the first writer wins,\n // preventing a TOCTOU race where a concurrent run_created\n // from start() could overwrite a run that was already\n // transitioned to 'running'.\n const createdRun: WorkflowRun = {\n runId: effectiveRunId,\n deploymentId: runInputData.deploymentId,\n status: 'pending',\n workflowName: runInputData.workflowName,\n specVersion: effectiveSpecVersion,\n executionContext: runInputData.executionContext,\n input: runInputData.input,\n output: undefined,\n error: undefined,\n startedAt: undefined,\n completedAt: undefined,\n createdAt: now,\n updatedAt: now,\n };\n const runPath = taggedPath(basedir, 'runs', effectiveRunId, tag);\n const created = await writeExclusive(\n runPath,\n JSON.stringify(createdRun, jsonReplacer)\n );\n\n if (created) {\n // We created the run — also write the run_created event.\n const runCreatedEventId = `evnt_${monotonicUlid()}`;\n const runCreatedEvent: Event = {\n eventType: 'run_created',\n runId: effectiveRunId,\n eventId: runCreatedEventId,\n createdAt: now,\n specVersion: effectiveSpecVersion,\n eventData: {\n deploymentId: runInputData.deploymentId,\n workflowName: runInputData.workflowName,\n input: runInputData.input,\n executionContext: runInputData.executionContext,\n },\n };\n const createdCompositeKey = `${effectiveRunId}-${runCreatedEventId}`;\n await writeJSON(\n taggedPath(basedir, 'events', createdCompositeKey, tag),\n runCreatedEvent\n );\n currentRun = createdRun;\n } else {\n // Run already exists (concurrent run_created won the\n // race). Re-read it so downstream logic sees the real state.\n currentRun = await readJSONWithFallback(\n basedir,\n 'runs',\n effectiveRunId,\n WorkflowRunSchema,\n tag\n );\n }\n }\n }\n }\n\n // ============================================================\n // VERSION COMPATIBILITY: Check run spec version\n // ============================================================\n // For events that have fetched the run, check version compatibility.\n // Skip for run_created (no existing run) and runtime events (step_completed, step_retrying).\n if (currentRun) {\n // Check if run requires a newer world version\n if (requiresNewerWorld(currentRun.specVersion)) {\n throw new RunNotSupportedError(\n currentRun.specVersion!,\n SPEC_VERSION_CURRENT\n );\n }\n\n // Route to legacy handler for pre-event-sourcing runs\n if (isLegacySpecVersion(currentRun.specVersion)) {\n return handleLegacyEvent(\n basedir,\n effectiveRunId,\n data,\n currentRun,\n params\n );\n }\n }\n\n // ============================================================\n // VALIDATION: Terminal state and event ordering checks\n // ============================================================\n\n // Run terminal state validation\n if (currentRun && isRunTerminal(currentRun.status)) {\n const runTerminalEvents = [\n 'run_started',\n 'run_completed',\n 'run_failed',\n ];\n\n // Idempotent operation: run_cancelled on already cancelled run is allowed\n if (\n data.eventType === 'run_cancelled' &&\n currentRun.status === 'cancelled'\n ) {\n // Return existing state (idempotent)\n const event: Event = {\n ...data,\n runId: effectiveRunId,\n eventId,\n createdAt: now,\n specVersion: effectiveSpecVersion,\n };\n const compositeKey = `${effectiveRunId}-${eventId}`;\n await writeJSON(\n taggedPath(basedir, 'events', compositeKey, tag),\n event\n );\n const resolveData =\n params?.resolveData ?? DEFAULT_RESOLVE_DATA_OPTION;\n return {\n event: stripEventDataRefs(event, resolveData),\n run: currentRun,\n };\n }\n\n // For run_started on terminal runs, use RunExpiredError so the\n // runtime knows to exit without retrying.\n if (data.eventType === 'run_started') {\n throw new RunExpiredError(\n `Workflow run \"${effectiveRunId}\" is already in terminal state \"${currentRun.status}\"`\n );\n }\n\n // Other run state transitions are not allowed on terminal runs\n if (\n runTerminalEvents.includes(data.eventType) ||\n data.eventType === 'run_cancelled'\n ) {\n throw new EntityConflictError(\n `Cannot transition run from terminal state \"${currentRun.status}\"`\n );\n }\n\n // Creating new entities on terminal runs is not allowed\n if (\n data.eventType === 'step_created' ||\n data.eventType === 'hook_created' ||\n data.eventType === 'wait_created'\n ) {\n throw new EntityConflictError(\n `Cannot create new entities on run in terminal state \"${currentRun.status}\"`\n );\n }\n }\n\n // Step-related event validation (ordering and terminal state)\n // Store existingStep so we can reuse it later (avoid double read)\n let validatedStep: Step | null = null;\n const stepEvents = [\n 'step_started',\n 'step_completed',\n 'step_failed',\n 'step_retrying',\n ];\n if (stepEvents.includes(data.eventType) && data.correlationId) {\n const stepCompositeKey = `${effectiveRunId}-${data.correlationId}`;\n validatedStep = await readJSONWithFallback(\n basedir,\n 'steps',\n stepCompositeKey,\n StepSchema,\n tag\n );\n\n // Event ordering: step must exist before these events\n if (!validatedStep) {\n throw new WorkflowWorldError(\n `Step \"${data.correlationId}\" not found`\n );\n }\n\n // Step terminal state validation\n if (isStepTerminal(validatedStep.status)) {\n throw new EntityConflictError(\n `Cannot modify step in terminal state \"${validatedStep.status}\"`\n );\n }\n\n // On terminal runs: only allow completing/failing in-progress steps\n if (currentRun && isRunTerminal(currentRun.status)) {\n if (validatedStep.status !== 'running') {\n throw new RunExpiredError(\n `Cannot modify non-running step on run in terminal state \"${currentRun.status}\"`\n );\n }\n }\n }\n\n // Hook-related event validation (ordering)\n const hookEventsRequiringExistence = ['hook_disposed', 'hook_received'];\n if (\n hookEventsRequiringExistence.includes(data.eventType) &&\n data.correlationId\n ) {\n const existingHook = await readJSONWithFallback(\n basedir,\n 'hooks',\n data.correlationId,\n HookSchema,\n tag\n );\n\n if (!existingHook) {\n throw new HookNotFoundError(data.correlationId);\n }\n }\n const event: Event = {\n ...data,\n runId: effectiveRunId,\n eventId,\n createdAt: now,\n specVersion: effectiveSpecVersion,\n };\n // Strip eventData from run_started — it belongs on run_created only.\n if (data.eventType === 'run_started' && 'eventData' in event) {\n delete (event as any).eventData;\n }\n\n // Track entity created/updated for EventResult\n let run: WorkflowRun | undefined;\n let step: Step | undefined;\n let hook: Hook | undefined;\n let wait: Wait | undefined;\n\n // Create/update entity based on event type (event-sourced architecture)\n // Run lifecycle events\n if (data.eventType === 'run_created' && 'eventData' in data) {\n const runData = data.eventData as {\n deploymentId: string;\n workflowName: string;\n input: SerializedData;\n executionContext?: Record<string, any>;\n };\n run = {\n runId: effectiveRunId,\n deploymentId: runData.deploymentId,\n status: 'pending',\n workflowName: runData.workflowName,\n // Propagate specVersion from the event to the run entity\n specVersion: effectiveSpecVersion,\n executionContext: runData.executionContext,\n input: runData.input,\n output: undefined,\n error: undefined,\n startedAt: undefined,\n completedAt: undefined,\n createdAt: now,\n updatedAt: now,\n };\n // Use writeExclusive (O_CREAT|O_EXCL) to atomically create the\n // run entity file. This prevents a TOCTOU race with the resilient\n // start path (run_started on non-existent run) that could result\n // in duplicate run_created events in the event log.\n const runPath = taggedPath(basedir, 'runs', effectiveRunId, tag);\n const created = await writeExclusive(\n runPath,\n JSON.stringify(run, jsonReplacer, 2)\n );\n if (!created) {\n throw new EntityConflictError(\n `Workflow run \"${effectiveRunId}\" already exists`\n );\n }\n } else if (data.eventType === 'run_started') {\n // Reuse currentRun from validation (already read above)\n if (currentRun) {\n // If already running, return the run without inserting a\n // duplicate event. This makes run_started idempotent for\n // concurrent invocations. We omit preloaded events here\n // because this is a rare race-condition path — the runtime\n // falls back to getAllWorkflowRunEvents().\n if (currentRun.status === 'running') {\n return { run: currentRun };\n }\n\n run = {\n runId: currentRun.runId,\n deploymentId: currentRun.deploymentId,\n workflowName: currentRun.workflowName,\n specVersion: currentRun.specVersion,\n executionContext: currentRun.executionContext,\n input: currentRun.input,\n createdAt: currentRun.createdAt,\n expiredAt: currentRun.expiredAt,\n status: 'running',\n output: undefined,\n error: undefined,\n completedAt: undefined,\n startedAt: currentRun.startedAt ?? now,\n updatedAt: now,\n };\n await writeJSON(\n taggedPath(basedir, 'runs', effectiveRunId, tag),\n run,\n { overwrite: true }\n );\n }\n } else if (data.eventType === 'run_completed' && 'eventData' in data) {\n const completedData = data.eventData as { output?: any };\n // Reuse currentRun from validation (already read above)\n if (currentRun) {\n run = {\n runId: currentRun.runId,\n deploymentId: currentRun.deploymentId,\n workflowName: currentRun.workflowName,\n specVersion: currentRun.specVersion,\n executionContext: currentRun.executionContext,\n input: currentRun.input,\n createdAt: currentRun.createdAt,\n expiredAt: currentRun.expiredAt,\n startedAt: currentRun.startedAt,\n status: 'completed',\n output: completedData.output,\n error: undefined,\n completedAt: now,\n updatedAt: now,\n };\n await writeJSON(\n taggedPath(basedir, 'runs', effectiveRunId, tag),\n run,\n { overwrite: true }\n );\n await Promise.all([\n deleteAllHooksForRun(basedir, effectiveRunId),\n deleteAllWaitsForRun(basedir, effectiveRunId),\n ]);\n }\n } else if (data.eventType === 'run_failed' && 'eventData' in data) {\n const failedData = data.eventData as {\n error: any;\n errorCode?: string;\n };\n // Reuse currentRun from validation (already read above)\n if (currentRun) {\n run = {\n runId: currentRun.runId,\n deploymentId: currentRun.deploymentId,\n workflowName: currentRun.workflowName,\n specVersion: currentRun.specVersion,\n executionContext: currentRun.executionContext,\n input: currentRun.input,\n createdAt: currentRun.createdAt,\n expiredAt: currentRun.expiredAt,\n startedAt: currentRun.startedAt,\n status: 'failed',\n output: undefined,\n error: {\n message:\n typeof failedData.error === 'string'\n ? failedData.error\n : (failedData.error?.message ?? 'Unknown error'),\n stack: failedData.error?.stack,\n code: failedData.errorCode,\n },\n completedAt: now,\n updatedAt: now,\n };\n await writeJSON(\n taggedPath(basedir, 'runs', effectiveRunId, tag),\n run,\n { overwrite: true }\n );\n await Promise.all([\n deleteAllHooksForRun(basedir, effectiveRunId),\n deleteAllWaitsForRun(basedir, effectiveRunId),\n ]);\n }\n } else if (data.eventType === 'run_cancelled') {\n // Reuse currentRun from validation (already read above)\n if (currentRun) {\n run = {\n runId: currentRun.runId,\n deploymentId: currentRun.deploymentId,\n workflowName: currentRun.workflowName,\n specVersion: currentRun.specVersion,\n executionContext: currentRun.executionContext,\n input: currentRun.input,\n createdAt: currentRun.createdAt,\n expiredAt: currentRun.expiredAt,\n startedAt: currentRun.startedAt,\n status: 'cancelled',\n output: undefined,\n error: undefined,\n completedAt: now,\n updatedAt: now,\n };\n await writeJSON(\n taggedPath(basedir, 'runs', effectiveRunId, tag),\n run,\n { overwrite: true }\n );\n await Promise.all([\n deleteAllHooksForRun(basedir, effectiveRunId),\n deleteAllWaitsForRun(basedir, effectiveRunId),\n ]);\n }\n } else if (\n // Step lifecycle events\n data.eventType === 'step_created' &&\n 'eventData' in data\n ) {\n // step_created: Creates step entity with status 'pending', attempt=0, createdAt set\n const stepData = data.eventData as {\n stepName: string;\n input: any;\n };\n step = {\n runId: effectiveRunId,\n stepId: data.correlationId,\n stepName: stepData.stepName,\n status: 'pending',\n input: stepData.input,\n output: undefined,\n error: undefined,\n attempt: 0,\n startedAt: undefined,\n completedAt: undefined,\n createdAt: now,\n updatedAt: now,\n // Propagate specVersion from the event to the step entity\n specVersion: effectiveSpecVersion,\n };\n const stepCompositeKey = `${effectiveRunId}-${data.correlationId}`;\n await writeJSON(\n taggedPath(basedir, 'steps', stepCompositeKey, tag),\n step\n );\n } else if (data.eventType === 'step_started') {\n // step_started: Increments attempt, sets status to 'running'\n // Sets startedAt only on the first start (not updated on retries)\n // Reuse validatedStep from validation (already read above)\n if (validatedStep) {\n // Check if retryAfter timestamp hasn't been reached yet\n if (\n validatedStep.retryAfter &&\n validatedStep.retryAfter.getTime() > Date.now()\n ) {\n throw new TooEarlyError(\n `Cannot start step \"${data.correlationId}\": retryAfter timestamp has not been reached yet`,\n {\n retryAfter: Math.ceil(\n (validatedStep.retryAfter.getTime() - Date.now()) / 1000\n ),\n }\n );\n }\n\n // Best-effort guard: re-read the step entity to check if it\n // reached terminal state between the validation read and now.\n // This narrows the TOCTOU window but does not fully eliminate it\n // (the local world is single-process / dev-only; the postgres\n // world uses SQL-level atomic guards for production).\n const stepCompositeKey = `${effectiveRunId}-${data.correlationId}`;\n const freshStep = await readJSONWithFallback(\n basedir,\n 'steps',\n stepCompositeKey,\n StepSchema,\n tag\n );\n if (freshStep && isStepTerminal(freshStep.status)) {\n throw new EntityConflictError(\n `Cannot modify step in terminal state \"${freshStep.status}\"`\n );\n }\n\n step = {\n ...validatedStep,\n status: 'running',\n // Only set startedAt on the first start\n startedAt: validatedStep.startedAt ?? now,\n // Increment attempt counter on every start\n attempt: validatedStep.attempt + 1,\n // Clear retryAfter now that the step has started\n retryAfter: undefined,\n updatedAt: now,\n };\n await writeJSON(\n taggedPath(basedir, 'steps', stepCompositeKey, tag),\n step,\n { overwrite: true }\n );\n }\n } else if (data.eventType === 'step_completed' && 'eventData' in data) {\n // step_completed: Terminal state with output\n // Uses writeExclusive on a lock file to atomically prevent concurrent\n // invocations from both completing the same step (TOCTOU race).\n const completedData = data.eventData as { result: any };\n if (validatedStep) {\n const stepCompositeKey = `${effectiveRunId}-${data.correlationId}`;\n const lockName = tag\n ? `${stepCompositeKey}.terminal.${tag}`\n : `${stepCompositeKey}.terminal`;\n const terminalLockPath = path.join(\n basedir,\n '.locks',\n 'steps',\n lockName\n );\n const claimed = await writeExclusive(terminalLockPath, '');\n if (!claimed) {\n throw new EntityConflictError(\n 'Cannot modify step in terminal state'\n );\n }\n step = {\n ...validatedStep,\n status: 'completed',\n output: completedData.result,\n completedAt: now,\n updatedAt: now,\n };\n await writeJSON(\n taggedPath(basedir, 'steps', stepCompositeKey, tag),\n step,\n { overwrite: true }\n );\n }\n } else if (data.eventType === 'step_failed' && 'eventData' in data) {\n // step_failed: Terminal state with error\n // Uses writeExclusive on a lock file to atomically prevent concurrent\n // invocations from both failing the same step (TOCTOU race).\n const failedData = data.eventData as {\n error: any;\n stack?: string;\n };\n if (validatedStep) {\n const stepCompositeKey = `${effectiveRunId}-${data.correlationId}`;\n const lockName = tag\n ? `${stepCompositeKey}.terminal.${tag}`\n : `${stepCompositeKey}.terminal`;\n const terminalLockPath = path.join(\n basedir,\n '.locks',\n 'steps',\n lockName\n );\n const claimed = await writeExclusive(terminalLockPath, '');\n if (!claimed) {\n throw new EntityConflictError(\n 'Cannot modify step in terminal state'\n );\n }\n const error = {\n message:\n typeof failedData.error === 'string'\n ? failedData.error\n : (failedData.error?.message ?? 'Unknown error'),\n stack: failedData.stack,\n };\n step = {\n ...validatedStep,\n status: 'failed',\n error,\n completedAt: now,\n updatedAt: now,\n };\n await writeJSON(\n taggedPath(basedir, 'steps', stepCompositeKey, tag),\n step,\n { overwrite: true }\n );\n }\n } else if (data.eventType === 'step_retrying' && 'eventData' in data) {\n // step_retrying: Sets status back to 'pending', records error\n // Reuse validatedStep from validation (already read above)\n const retryData = data.eventData as {\n error: any;\n stack?: string;\n retryAfter?: Date;\n };\n if (validatedStep) {\n const stepCompositeKey = `${effectiveRunId}-${data.correlationId}`;\n step = {\n ...validatedStep,\n status: 'pending',\n error: {\n message:\n typeof retryData.error === 'string'\n ? retryData.error\n : (retryData.error?.message ?? 'Unknown error'),\n stack: retryData.stack,\n },\n retryAfter: retryData.retryAfter,\n updatedAt: now,\n };\n await writeJSON(\n taggedPath(basedir, 'steps', stepCompositeKey, tag),\n step,\n { overwrite: true }\n );\n }\n } else if (\n // Hook lifecycle events\n data.eventType === 'hook_created' &&\n 'eventData' in data\n ) {\n const hookData = data.eventData as {\n token: string;\n metadata?: any;\n isWebhook?: boolean;\n };\n\n // Atomically claim the token using an exclusive-create constraint file.\n // This avoids the TOCTOU race of the previous read-all-then-check approach.\n const constraintPath = path.join(\n basedir,\n 'hooks',\n 'tokens',\n `${hashToken(hookData.token)}.json`\n );\n const tokenClaimed = await writeExclusive(\n constraintPath,\n JSON.stringify({\n token: hookData.token,\n hookId: data.correlationId,\n runId: effectiveRunId,\n })\n );\n\n if (!tokenClaimed) {\n // Create hook_conflict event instead of hook_created\n // This allows the workflow to continue and fail gracefully when the hook is awaited\n const conflictEvent: Event = {\n eventType: 'hook_conflict',\n correlationId: data.correlationId,\n eventData: {\n token: hookData.token,\n },\n runId: effectiveRunId,\n eventId,\n createdAt: now,\n specVersion: effectiveSpecVersion,\n };\n\n // Store the conflict event\n const compositeKey = `${effectiveRunId}-${eventId}`;\n await writeJSON(\n taggedPath(basedir, 'events', compositeKey, tag),\n conflictEvent\n );\n\n const resolveData =\n params?.resolveData ?? DEFAULT_RESOLVE_DATA_OPTION;\n const filteredEvent = stripEventDataRefs(conflictEvent, resolveData);\n\n // Return EventResult with conflict event (no hook entity created)\n return {\n event: filteredEvent,\n run,\n step,\n hook: undefined,\n };\n }\n\n hook = {\n runId: effectiveRunId,\n hookId: data.correlationId,\n token: hookData.token,\n metadata: hookData.metadata,\n ownerId: 'local-owner',\n projectId: 'local-project',\n environment: 'local',\n createdAt: now,\n // Propagate specVersion from the event to the hook entity\n specVersion: effectiveSpecVersion,\n isWebhook: hookData.isWebhook ?? false,\n };\n await writeJSON(\n taggedPath(basedir, 'hooks', data.correlationId, tag),\n hook\n );\n } else if (data.eventType === 'hook_disposed') {\n // hook_disposed: Deletes hook entity, rejects duplicates.\n // Uses writeExclusive on a lock file to atomically prevent concurrent\n // invocations from both disposing the same hook (TOCTOU race).\n const hookLockName = tag\n ? `${data.correlationId}.disposed.${tag}`\n : `${data.correlationId}.disposed`;\n const lockPath = path.join(basedir, '.locks', 'hooks', hookLockName);\n const claimed = await writeExclusive(lockPath, '');\n if (!claimed) {\n throw new EntityConflictError(\n `Hook \"${data.correlationId}\" already disposed`\n );\n }\n // Read the hook to get its token before deleting\n const hookPath = taggedPath(basedir, 'hooks', data.correlationId, tag);\n const existingHook = await readJSONWithFallback(\n basedir,\n 'hooks',\n data.correlationId,\n HookSchema,\n tag\n );\n if (existingHook) {\n // Delete the token constraint file to free up the token for reuse\n const disposedConstraintPath = path.join(\n basedir,\n 'hooks',\n 'tokens',\n `${hashToken(existingHook.token)}.json`\n );\n await deleteJSON(disposedConstraintPath);\n }\n await deleteJSON(hookPath);\n } else if (data.eventType === 'wait_created' && 'eventData' in data) {\n // wait_created: Creates wait entity with status 'waiting'\n const waitData = data.eventData as {\n resumeAt?: Date;\n };\n const waitCompositeKey = `${effectiveRunId}-${data.correlationId}`;\n const existingWait = await readJSONWithFallback(\n basedir,\n 'waits',\n waitCompositeKey,\n WaitSchema,\n tag\n );\n if (existingWait) {\n throw new EntityConflictError(\n `Wait \"${data.correlationId}\" already exists`\n );\n }\n wait = {\n waitId: waitCompositeKey,\n runId: effectiveRunId,\n status: 'waiting',\n resumeAt: waitData.resumeAt,\n completedAt: undefined,\n createdAt: now,\n updatedAt: now,\n specVersion: effectiveSpecVersion,\n };\n await writeJSON(\n taggedPath(basedir, 'waits', waitCompositeKey, tag),\n wait\n );\n } else if (data.eventType === 'wait_completed') {\n // wait_completed: Transitions wait to 'completed', rejects duplicates.\n // Uses writeExclusive on a lock file to atomically prevent concurrent\n // invocations from both completing the same wait (TOCTOU race).\n const waitCompositeKey = `${effectiveRunId}-${data.correlationId}`;\n const waitLockName = tag\n ? `${waitCompositeKey}.completed.${tag}`\n : `${waitCompositeKey}.completed`;\n const lockPath = path.join(basedir, '.locks', 'waits', waitLockName);\n const claimed = await writeExclusive(lockPath, '');\n if (!claimed) {\n throw new EntityConflictError(\n `Wait \"${data.correlationId}\" already completed`\n );\n }\n const existingWait = await readJSONWithFallback(\n basedir,\n 'waits',\n waitCompositeKey,\n WaitSchema,\n tag\n );\n if (!existingWait) {\n // Clean up the lock file we just claimed — the wait doesn't exist\n await fs.unlink(lockPath).catch(() => {});\n throw new WorkflowWorldError(\n `Wait \"${data.correlationId}\" not found`\n );\n }\n // The lock file (writeExclusive above) already prevents concurrent\n // completions — no additional status check needed.\n wait = {\n ...existingWait,\n status: 'completed',\n completedAt: now,\n updatedAt: now,\n };\n await writeJSON(\n taggedPath(basedir, 'waits', waitCompositeKey, tag),\n wait,\n { overwrite: true }\n );\n }\n // Note: hook_received events are stored in the event log but don't\n // modify the Hook entity (which doesn't have a payload field)\n\n // Store event using composite key {runId}-{eventId}\n const compositeKey = `${effectiveRunId}-${eventId}`;\n await writeJSON(taggedPath(basedir, 'events', compositeKey, tag), event);\n\n const resolveData = params?.resolveData ?? DEFAULT_RESOLVE_DATA_OPTION;\n const filteredEvent = stripEventDataRefs(event, resolveData);\n\n // For run_started: include all events so the runtime can skip\n // the initial events.list call and reduce TTFB.\n let events: Event[] | undefined;\n if (data.eventType === 'run_started' && run) {\n const allEvents = await paginatedFileSystemQuery({\n directory: path.join(basedir, 'events'),\n schema: EventSchema,\n filePrefix: `${effectiveRunId}-`,\n sortOrder: 'asc',\n getCreatedAt: getObjectCreatedAt('evnt'),\n getId: (e) => e.eventId,\n });\n events = allEvents.data;\n }\n\n // Return EventResult with event and any created/updated entity\n return {\n event: filteredEvent,\n run,\n step,\n hook,\n wait,\n events,\n };\n },\n\n async get(runId, eventId, params) {\n const compositeKey = `${runId}-${eventId}`;\n const event = await readJSONWithFallback(\n basedir,\n 'events',\n compositeKey,\n EventSchema,\n tag\n );\n if (!event) {\n throw new Error(`Event ${eventId} in run ${runId} not found`);\n }\n const resolveData = params?.resolveData ?? DEFAULT_RESOLVE_DATA_OPTION;\n return stripEventDataRefs(event, resolveData);\n },\n\n async list(params) {\n const { runId } = params;\n const resolveData = params.resolveData ?? DEFAULT_RESOLVE_DATA_OPTION;\n const result = await paginatedFileSystemQuery({\n directory: path.join(basedir, 'events'),\n schema: EventSchema,\n filePrefix: `${runId}-`,\n // Events in chronological order (oldest first) by default,\n // different from the default for other list calls.\n sortOrder: params.pagination?.sortOrder ?? 'asc',\n limit: params.pagination?.limit,\n cursor: params.pagination?.cursor,\n getCreatedAt: getObjectCreatedAt('evnt'),\n getId: (event) => event.eventId,\n });\n\n // If resolveData is \"none\", remove eventData from events\n if (resolveData === 'none') {\n return {\n ...result,\n data: result.data.map((event) =>\n stripEventDataRefs(event, resolveData)\n ),\n };\n }\n\n return result;\n },\n\n async listByCorrelationId(params) {\n const correlationId = params.correlationId;\n const resolveData = params.resolveData ?? DEFAULT_RESOLVE_DATA_OPTION;\n const result = await paginatedFileSystemQuery({\n directory: path.join(basedir, 'events'),\n schema: EventSchema,\n // No filePrefix - search all events\n filter: (event) => event.correlationId === correlationId,\n // Events in chronological order (oldest first) by default,\n // different from the default for other list calls.\n sortOrder: params.pagination?.sortOrder ?? 'asc',\n limit: params.pagination?.limit,\n cursor: params.pagination?.cursor,\n getCreatedAt: getObjectCreatedAt('evnt'),\n getId: (event) => event.eventId,\n });\n\n // If resolveData is \"none\", remove eventData from events\n if (resolveData === 'none') {\n return {\n ...result,\n data: result.data.map((event) =>\n stripEventDataRefs(event, resolveData)\n ),\n };\n }\n\n return result;\n },\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"events-storage.js","sourceRoot":"","sources":["../../src/storage/events-storage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EACL,mBAAmB,EACnB,iBAAiB,EACjB,eAAe,EACf,oBAAoB,EACpB,aAAa,EACb,kBAAkB,GACnB,MAAM,kBAAkB,CAAC;AAW1B,OAAO,EACL,WAAW,EACX,UAAU,EACV,mBAAmB,EACnB,kBAAkB,EAClB,oBAAoB,EACpB,UAAU,EACV,qBAAqB,EACrB,UAAU,EACV,iBAAiB,GAClB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,2BAA2B,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,EACL,kBAAkB,EAClB,UAAU,EACV,YAAY,EACZ,aAAa,EACb,wBAAwB,EACxB,oBAAoB,EACpB,iBAAiB,EACjB,UAAU,EACV,cAAc,EACd,SAAS,GACV,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,kBAAkB,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC5E,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAEhD;;;GAGG;AACH,KAAK,UAAU,oBAAoB,CACjC,OAAe,EACf,KAAa;IAEb,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC7C,MAAM,KAAK,GAAG,MAAM,aAAa,CAAC,QAAQ,CAAC,CAAC;IAE5C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,sEAAsE;QACtE,oEAAoE;QACpE,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,KAAK,GAAG,CAAC,EAAE,CAAC;YACjC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,IAAI,OAAO,CAAC,CAAC;YACrD,MAAM,UAAU,CAAC,QAAQ,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CACjC,OAAe,EACf,GAAY;IAEZ,OAAO;QACL,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,MAAM;YAC9B,MAAM,OAAO,GAAG,QAAQ,aAAa,EAAE,EAAE,CAAC;YAC1C,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;YAEvB,iEAAiE;YACjE,uEAAuE;YACvE,oEAAoE;YACpE,sEAAsE;YACtE,EAAE;YACF,iEAAiE;YACjE,6DAA6D;YAC7D,0DAA0D;YAC1D,kEAAkE;YAClE,kCAAkC;YAClC,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,KAAK,EAAE,EAAE,CAAC;gBAClC,kBAAkB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;YACrC,CAAC;YACD,IAAI,eAAe,IAAI,IAAI,IAAI,OAAO,IAAI,CAAC,aAAa,KAAK,QAAQ,EAAE,CAAC;gBACtE,kBAAkB,CAAC,eAAe,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;YAC1D,CAAC;YAED,gFAAgF;YAChF,IAAI,cAAsB,CAAC;YAC3B,IAAI,IAAI,CAAC,SAAS,KAAK,aAAa,IAAI,CAAC,CAAC,KAAK,IAAI,KAAK,KAAK,EAAE,CAAC,EAAE,CAAC;gBACjE,cAAc,GAAG,QAAQ,aAAa,EAAE,EAAE,CAAC;YAC7C,CAAC;iBAAM,IAAI,CAAC,KAAK,EAAE,CAAC;gBAClB,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;YAClE,CAAC;iBAAM,CAAC;gBACN,cAAc,GAAG,KAAK,CAAC;YACzB,CAAC;YAED,0EAA0E;YAC1E,IAAI,IAAI,CAAC,SAAS,KAAK,aAAa,IAAI,KAAK,IAAI,KAAK,KAAK,EAAE,EAAE,CAAC;gBAC9D,MAAM,eAAe,GAAG,qBAAqB,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;gBACvE,IAAI,eAAe,EAAE,CAAC;oBACpB,MAAM,IAAI,kBAAkB,CAAC,eAAe,CAAC,CAAC;gBAChD,CAAC;YACH,CAAC;YAED,kFAAkF;YAClF,MAAM,oBAAoB,GAAG,IAAI,CAAC,WAAW,IAAI,oBAAoB,CAAC;YAEtE,8CAA8C;YAC9C,MAAM,aAAa,GAAG,CAAC,MAAc,EAAE,EAAE,CACvC,CAAC,WAAW,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;YAExD,+CAA+C;YAC/C,MAAM,cAAc,GAAG,CAAC,MAAc,EAAE,EAAE,CACxC,CAAC,WAAW,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;YAExD,mEAAmE;YACnE,+EAA+E;YAC/E,8EAA8E;YAC9E,yEAAyE;YACzE,IAAI,UAAU,GAAuB,IAAI,CAAC;YAC1C,MAAM,uBAAuB,GAAG,CAAC,gBAAgB,EAAE,eAAe,CAAC,CAAC;YACpE,IACE,IAAI,CAAC,SAAS,KAAK,aAAa;gBAChC,CAAC,uBAAuB,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,EACjD,CAAC;gBACD,UAAU,GAAG,MAAM,oBAAoB,CACrC,OAAO,EACP,MAAM,EACN,cAAc,EACd,iBAAiB,EACjB,GAAG,CACJ,CAAC;gBAEF,kEAAkE;gBAClE,+DAA+D;gBAC/D,mCAAmC;gBACnC,IACE,IAAI,CAAC,SAAS,KAAK,aAAa;oBAChC,CAAC,UAAU;oBACX,WAAW,IAAI,IAAI;oBACnB,IAAI,CAAC,SAAS,EACd,CAAC;oBACD,MAAM,YAAY,GAAG,IAAI,CAAC,SAKzB,CAAC;oBACF,IACE,YAAY,CAAC,YAAY;wBACzB,YAAY,CAAC,YAAY;wBACzB,YAAY,CAAC,KAAK,KAAK,SAAS,EAChC,CAAC;wBACD,0DAA0D;wBAC1D,qDAAqD;wBACrD,0DAA0D;wBAC1D,sDAAsD;wBACtD,6BAA6B;wBAC7B,MAAM,UAAU,GAAgB;4BAC9B,KAAK,EAAE,cAAc;4BACrB,YAAY,EAAE,YAAY,CAAC,YAAY;4BACvC,MAAM,EAAE,SAAS;4BACjB,YAAY,EAAE,YAAY,CAAC,YAAY;4BACvC,WAAW,EAAE,oBAAoB;4BACjC,gBAAgB,EAAE,YAAY,CAAC,gBAAgB;4BAC/C,KAAK,EAAE,YAAY,CAAC,KAAK;4BACzB,MAAM,EAAE,SAAS;4BACjB,KAAK,EAAE,SAAS;4BAChB,SAAS,EAAE,SAAS;4BACpB,WAAW,EAAE,SAAS;4BACtB,SAAS,EAAE,GAAG;4BACd,SAAS,EAAE,GAAG;yBACf,CAAC;wBACF,MAAM,OAAO,GAAG,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,GAAG,CAAC,CAAC;wBACjE,MAAM,OAAO,GAAG,MAAM,cAAc,CAClC,OAAO,EACP,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,YAAY,CAAC,CACzC,CAAC;wBAEF,IAAI,OAAO,EAAE,CAAC;4BACZ,yDAAyD;4BACzD,MAAM,iBAAiB,GAAG,QAAQ,aAAa,EAAE,EAAE,CAAC;4BACpD,MAAM,eAAe,GAAU;gCAC7B,SAAS,EAAE,aAAa;gCACxB,KAAK,EAAE,cAAc;gCACrB,OAAO,EAAE,iBAAiB;gCAC1B,SAAS,EAAE,GAAG;gCACd,WAAW,EAAE,oBAAoB;gCACjC,SAAS,EAAE;oCACT,YAAY,EAAE,YAAY,CAAC,YAAY;oCACvC,YAAY,EAAE,YAAY,CAAC,YAAY;oCACvC,KAAK,EAAE,YAAY,CAAC,KAAK;oCACzB,gBAAgB,EAAE,YAAY,CAAC,gBAAgB;iCAChD;6BACF,CAAC;4BACF,MAAM,mBAAmB,GAAG,GAAG,cAAc,IAAI,iBAAiB,EAAE,CAAC;4BACrE,MAAM,SAAS,CACb,UAAU,CAAC,OAAO,EAAE,QAAQ,EAAE,mBAAmB,EAAE,GAAG,CAAC,EACvD,eAAe,CAChB,CAAC;4BACF,UAAU,GAAG,UAAU,CAAC;wBAC1B,CAAC;6BAAM,CAAC;4BACN,qDAAqD;4BACrD,6DAA6D;4BAC7D,UAAU,GAAG,MAAM,oBAAoB,CACrC,OAAO,EACP,MAAM,EACN,cAAc,EACd,iBAAiB,EACjB,GAAG,CACJ,CAAC;wBACJ,CAAC;oBACH,CAAC;gBACH,CAAC;YACH,CAAC;YAED,+DAA+D;YAC/D,gDAAgD;YAChD,+DAA+D;YAC/D,qEAAqE;YACrE,6FAA6F;YAC7F,IAAI,UAAU,EAAE,CAAC;gBACf,8CAA8C;gBAC9C,IAAI,kBAAkB,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;oBAC/C,MAAM,IAAI,oBAAoB,CAC5B,UAAU,CAAC,WAAY,EACvB,oBAAoB,CACrB,CAAC;gBACJ,CAAC;gBAED,sDAAsD;gBACtD,IAAI,mBAAmB,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;oBAChD,OAAO,iBAAiB,CACtB,OAAO,EACP,cAAc,EACd,IAAI,EACJ,UAAU,EACV,MAAM,CACP,CAAC;gBACJ,CAAC;YACH,CAAC;YAED,+DAA+D;YAC/D,uDAAuD;YACvD,+DAA+D;YAE/D,gCAAgC;YAChC,IAAI,UAAU,IAAI,aAAa,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;gBACnD,MAAM,iBAAiB,GAAG;oBACxB,aAAa;oBACb,eAAe;oBACf,YAAY;iBACb,CAAC;gBAEF,0EAA0E;gBAC1E,IACE,IAAI,CAAC,SAAS,KAAK,eAAe;oBAClC,UAAU,CAAC,MAAM,KAAK,WAAW,EACjC,CAAC;oBACD,qCAAqC;oBACrC,MAAM,KAAK,GAAU;wBACnB,GAAG,IAAI;wBACP,KAAK,EAAE,cAAc;wBACrB,OAAO;wBACP,SAAS,EAAE,GAAG;wBACd,WAAW,EAAE,oBAAoB;qBAClC,CAAC;oBACF,MAAM,YAAY,GAAG,GAAG,cAAc,IAAI,OAAO,EAAE,CAAC;oBACpD,MAAM,SAAS,CACb,UAAU,CAAC,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,GAAG,CAAC,EAChD,KAAK,CACN,CAAC;oBACF,MAAM,WAAW,GACf,MAAM,EAAE,WAAW,IAAI,2BAA2B,CAAC;oBACrD,OAAO;wBACL,KAAK,EAAE,kBAAkB,CAAC,KAAK,EAAE,WAAW,CAAC;wBAC7C,GAAG,EAAE,UAAU;qBAChB,CAAC;gBACJ,CAAC;gBAED,+DAA+D;gBAC/D,0CAA0C;gBAC1C,IAAI,IAAI,CAAC,SAAS,KAAK,aAAa,EAAE,CAAC;oBACrC,MAAM,IAAI,eAAe,CACvB,iBAAiB,cAAc,mCAAmC,UAAU,CAAC,MAAM,GAAG,CACvF,CAAC;gBACJ,CAAC;gBAED,+DAA+D;gBAC/D,IACE,iBAAiB,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC;oBAC1C,IAAI,CAAC,SAAS,KAAK,eAAe,EAClC,CAAC;oBACD,MAAM,IAAI,mBAAmB,CAC3B,8CAA8C,UAAU,CAAC,MAAM,GAAG,CACnE,CAAC;gBACJ,CAAC;gBAED,wDAAwD;gBACxD,IACE,IAAI,CAAC,SAAS,KAAK,cAAc;oBACjC,IAAI,CAAC,SAAS,KAAK,cAAc;oBACjC,IAAI,CAAC,SAAS,KAAK,cAAc,EACjC,CAAC;oBACD,MAAM,IAAI,mBAAmB,CAC3B,wDAAwD,UAAU,CAAC,MAAM,GAAG,CAC7E,CAAC;gBACJ,CAAC;YACH,CAAC;YAED,8DAA8D;YAC9D,kEAAkE;YAClE,IAAI,aAAa,GAAgB,IAAI,CAAC;YACtC,MAAM,UAAU,GAAG;gBACjB,cAAc;gBACd,gBAAgB;gBAChB,aAAa;gBACb,eAAe;aAChB,CAAC;YACF,IAAI,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;gBAC9D,MAAM,gBAAgB,GAAG,GAAG,cAAc,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;gBACnE,aAAa,GAAG,MAAM,oBAAoB,CACxC,OAAO,EACP,OAAO,EACP,gBAAgB,EAChB,UAAU,EACV,GAAG,CACJ,CAAC;gBAEF,sDAAsD;gBACtD,IAAI,CAAC,aAAa,EAAE,CAAC;oBACnB,MAAM,IAAI,kBAAkB,CAC1B,SAAS,IAAI,CAAC,aAAa,aAAa,CACzC,CAAC;gBACJ,CAAC;gBAED,iCAAiC;gBACjC,IAAI,cAAc,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC;oBACzC,MAAM,IAAI,mBAAmB,CAC3B,yCAAyC,aAAa,CAAC,MAAM,GAAG,CACjE,CAAC;gBACJ,CAAC;gBAED,oEAAoE;gBACpE,IAAI,UAAU,IAAI,aAAa,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;oBACnD,IAAI,aAAa,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;wBACvC,MAAM,IAAI,eAAe,CACvB,4DAA4D,UAAU,CAAC,MAAM,GAAG,CACjF,CAAC;oBACJ,CAAC;gBACH,CAAC;YACH,CAAC;YAED,2CAA2C;YAC3C,MAAM,4BAA4B,GAAG,CAAC,eAAe,EAAE,eAAe,CAAC,CAAC;YACxE,IACE,4BAA4B,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC;gBACrD,IAAI,CAAC,aAAa,EAClB,CAAC;gBACD,MAAM,YAAY,GAAG,MAAM,oBAAoB,CAC7C,OAAO,EACP,OAAO,EACP,IAAI,CAAC,aAAa,EAClB,UAAU,EACV,GAAG,CACJ,CAAC;gBAEF,IAAI,CAAC,YAAY,EAAE,CAAC;oBAClB,MAAM,IAAI,iBAAiB,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;gBAClD,CAAC;YACH,CAAC;YACD,MAAM,KAAK,GAAU;gBACnB,GAAG,IAAI;gBACP,KAAK,EAAE,cAAc;gBACrB,OAAO;gBACP,SAAS,EAAE,GAAG;gBACd,WAAW,EAAE,oBAAoB;aAClC,CAAC;YACF,qEAAqE;YACrE,IAAI,IAAI,CAAC,SAAS,KAAK,aAAa,IAAI,WAAW,IAAI,KAAK,EAAE,CAAC;gBAC7D,OAAQ,KAAa,CAAC,SAAS,CAAC;YAClC,CAAC;YAED,+CAA+C;YAC/C,IAAI,GAA4B,CAAC;YACjC,IAAI,IAAsB,CAAC;YAC3B,IAAI,IAAsB,CAAC;YAC3B,IAAI,IAAsB,CAAC;YAE3B,wEAAwE;YACxE,uBAAuB;YACvB,IAAI,IAAI,CAAC,SAAS,KAAK,aAAa,IAAI,WAAW,IAAI,IAAI,EAAE,CAAC;gBAC5D,MAAM,OAAO,GAAG,IAAI,CAAC,SAKpB,CAAC;gBACF,GAAG,GAAG;oBACJ,KAAK,EAAE,cAAc;oBACrB,YAAY,EAAE,OAAO,CAAC,YAAY;oBAClC,MAAM,EAAE,SAAS;oBACjB,YAAY,EAAE,OAAO,CAAC,YAAY;oBAClC,yDAAyD;oBACzD,WAAW,EAAE,oBAAoB;oBACjC,gBAAgB,EAAE,OAAO,CAAC,gBAAgB;oBAC1C,KAAK,EAAE,OAAO,CAAC,KAAK;oBACpB,MAAM,EAAE,SAAS;oBACjB,KAAK,EAAE,SAAS;oBAChB,SAAS,EAAE,SAAS;oBACpB,WAAW,EAAE,SAAS;oBACtB,SAAS,EAAE,GAAG;oBACd,SAAS,EAAE,GAAG;iBACf,CAAC;gBACF,+DAA+D;gBAC/D,kEAAkE;gBAClE,iEAAiE;gBACjE,oDAAoD;gBACpD,MAAM,OAAO,GAAG,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,GAAG,CAAC,CAAC;gBACjE,MAAM,OAAO,GAAG,MAAM,cAAc,CAClC,OAAO,EACP,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,YAAY,EAAE,CAAC,CAAC,CACrC,CAAC;gBACF,IAAI,CAAC,OAAO,EAAE,CAAC;oBACb,MAAM,IAAI,mBAAmB,CAC3B,iBAAiB,cAAc,kBAAkB,CAClD,CAAC;gBACJ,CAAC;YACH,CAAC;iBAAM,IAAI,IAAI,CAAC,SAAS,KAAK,aAAa,EAAE,CAAC;gBAC5C,wDAAwD;gBACxD,IAAI,UAAU,EAAE,CAAC;oBACf,yDAAyD;oBACzD,0DAA0D;oBAC1D,yDAAyD;oBACzD,2DAA2D;oBAC3D,2CAA2C;oBAC3C,IAAI,UAAU,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;wBACpC,OAAO,EAAE,GAAG,EAAE,UAAU,EAAE,CAAC;oBAC7B,CAAC;oBAED,GAAG,GAAG;wBACJ,KAAK,EAAE,UAAU,CAAC,KAAK;wBACvB,YAAY,EAAE,UAAU,CAAC,YAAY;wBACrC,YAAY,EAAE,UAAU,CAAC,YAAY;wBACrC,WAAW,EAAE,UAAU,CAAC,WAAW;wBACnC,gBAAgB,EAAE,UAAU,CAAC,gBAAgB;wBAC7C,KAAK,EAAE,UAAU,CAAC,KAAK;wBACvB,SAAS,EAAE,UAAU,CAAC,SAAS;wBAC/B,SAAS,EAAE,UAAU,CAAC,SAAS;wBAC/B,MAAM,EAAE,SAAS;wBACjB,MAAM,EAAE,SAAS;wBACjB,KAAK,EAAE,SAAS;wBAChB,WAAW,EAAE,SAAS;wBACtB,SAAS,EAAE,UAAU,CAAC,SAAS,IAAI,GAAG;wBACtC,SAAS,EAAE,GAAG;qBACf,CAAC;oBACF,MAAM,SAAS,CACb,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,GAAG,CAAC,EAChD,GAAG,EACH,EAAE,SAAS,EAAE,IAAI,EAAE,CACpB,CAAC;gBACJ,CAAC;YACH,CAAC;iBAAM,IAAI,IAAI,CAAC,SAAS,KAAK,eAAe,IAAI,WAAW,IAAI,IAAI,EAAE,CAAC;gBACrE,MAAM,aAAa,GAAG,IAAI,CAAC,SAA6B,CAAC;gBACzD,wDAAwD;gBACxD,IAAI,UAAU,EAAE,CAAC;oBACf,GAAG,GAAG;wBACJ,KAAK,EAAE,UAAU,CAAC,KAAK;wBACvB,YAAY,EAAE,UAAU,CAAC,YAAY;wBACrC,YAAY,EAAE,UAAU,CAAC,YAAY;wBACrC,WAAW,EAAE,UAAU,CAAC,WAAW;wBACnC,gBAAgB,EAAE,UAAU,CAAC,gBAAgB;wBAC7C,KAAK,EAAE,UAAU,CAAC,KAAK;wBACvB,SAAS,EAAE,UAAU,CAAC,SAAS;wBAC/B,SAAS,EAAE,UAAU,CAAC,SAAS;wBAC/B,SAAS,EAAE,UAAU,CAAC,SAAS;wBAC/B,MAAM,EAAE,WAAW;wBACnB,MAAM,EAAE,aAAa,CAAC,MAAM;wBAC5B,KAAK,EAAE,SAAS;wBAChB,WAAW,EAAE,GAAG;wBAChB,SAAS,EAAE,GAAG;qBACf,CAAC;oBACF,MAAM,SAAS,CACb,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,GAAG,CAAC,EAChD,GAAG,EACH,EAAE,SAAS,EAAE,IAAI,EAAE,CACpB,CAAC;oBACF,MAAM,OAAO,CAAC,GAAG,CAAC;wBAChB,oBAAoB,CAAC,OAAO,EAAE,cAAc,CAAC;wBAC7C,oBAAoB,CAAC,OAAO,EAAE,cAAc,CAAC;qBAC9C,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;iBAAM,IAAI,IAAI,CAAC,SAAS,KAAK,YAAY,IAAI,WAAW,IAAI,IAAI,EAAE,CAAC;gBAClE,MAAM,UAAU,GAAG,IAAI,CAAC,SAGvB,CAAC;gBACF,wDAAwD;gBACxD,IAAI,UAAU,EAAE,CAAC;oBACf,GAAG,GAAG;wBACJ,KAAK,EAAE,UAAU,CAAC,KAAK;wBACvB,YAAY,EAAE,UAAU,CAAC,YAAY;wBACrC,YAAY,EAAE,UAAU,CAAC,YAAY;wBACrC,WAAW,EAAE,UAAU,CAAC,WAAW;wBACnC,gBAAgB,EAAE,UAAU,CAAC,gBAAgB;wBAC7C,KAAK,EAAE,UAAU,CAAC,KAAK;wBACvB,SAAS,EAAE,UAAU,CAAC,SAAS;wBAC/B,SAAS,EAAE,UAAU,CAAC,SAAS;wBAC/B,SAAS,EAAE,UAAU,CAAC,SAAS;wBAC/B,MAAM,EAAE,QAAQ;wBAChB,MAAM,EAAE,SAAS;wBACjB,KAAK,EAAE;4BACL,OAAO,EACL,OAAO,UAAU,CAAC,KAAK,KAAK,QAAQ;gCAClC,CAAC,CAAC,UAAU,CAAC,KAAK;gCAClB,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,EAAE,OAAO,IAAI,eAAe,CAAC;4BACpD,KAAK,EAAE,UAAU,CAAC,KAAK,EAAE,KAAK;4BAC9B,IAAI,EAAE,UAAU,CAAC,SAAS;yBAC3B;wBACD,WAAW,EAAE,GAAG;wBAChB,SAAS,EAAE,GAAG;qBACf,CAAC;oBACF,MAAM,SAAS,CACb,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,GAAG,CAAC,EAChD,GAAG,EACH,EAAE,SAAS,EAAE,IAAI,EAAE,CACpB,CAAC;oBACF,MAAM,OAAO,CAAC,GAAG,CAAC;wBAChB,oBAAoB,CAAC,OAAO,EAAE,cAAc,CAAC;wBAC7C,oBAAoB,CAAC,OAAO,EAAE,cAAc,CAAC;qBAC9C,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;iBAAM,IAAI,IAAI,CAAC,SAAS,KAAK,eAAe,EAAE,CAAC;gBAC9C,wDAAwD;gBACxD,IAAI,UAAU,EAAE,CAAC;oBACf,GAAG,GAAG;wBACJ,KAAK,EAAE,UAAU,CAAC,KAAK;wBACvB,YAAY,EAAE,UAAU,CAAC,YAAY;wBACrC,YAAY,EAAE,UAAU,CAAC,YAAY;wBACrC,WAAW,EAAE,UAAU,CAAC,WAAW;wBACnC,gBAAgB,EAAE,UAAU,CAAC,gBAAgB;wBAC7C,KAAK,EAAE,UAAU,CAAC,KAAK;wBACvB,SAAS,EAAE,UAAU,CAAC,SAAS;wBAC/B,SAAS,EAAE,UAAU,CAAC,SAAS;wBAC/B,SAAS,EAAE,UAAU,CAAC,SAAS;wBAC/B,MAAM,EAAE,WAAW;wBACnB,MAAM,EAAE,SAAS;wBACjB,KAAK,EAAE,SAAS;wBAChB,WAAW,EAAE,GAAG;wBAChB,SAAS,EAAE,GAAG;qBACf,CAAC;oBACF,MAAM,SAAS,CACb,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,GAAG,CAAC,EAChD,GAAG,EACH,EAAE,SAAS,EAAE,IAAI,EAAE,CACpB,CAAC;oBACF,MAAM,OAAO,CAAC,GAAG,CAAC;wBAChB,oBAAoB,CAAC,OAAO,EAAE,cAAc,CAAC;wBAC7C,oBAAoB,CAAC,OAAO,EAAE,cAAc,CAAC;qBAC9C,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;iBAAM;YACL,wBAAwB;YACxB,IAAI,CAAC,SAAS,KAAK,cAAc;gBACjC,WAAW,IAAI,IAAI,EACnB,CAAC;gBACD,oFAAoF;gBACpF,MAAM,QAAQ,GAAG,IAAI,CAAC,SAGrB,CAAC;gBACF,IAAI,GAAG;oBACL,KAAK,EAAE,cAAc;oBACrB,MAAM,EAAE,IAAI,CAAC,aAAa;oBAC1B,QAAQ,EAAE,QAAQ,CAAC,QAAQ;oBAC3B,MAAM,EAAE,SAAS;oBACjB,KAAK,EAAE,QAAQ,CAAC,KAAK;oBACrB,MAAM,EAAE,SAAS;oBACjB,KAAK,EAAE,SAAS;oBAChB,OAAO,EAAE,CAAC;oBACV,SAAS,EAAE,SAAS;oBACpB,WAAW,EAAE,SAAS;oBACtB,SAAS,EAAE,GAAG;oBACd,SAAS,EAAE,GAAG;oBACd,0DAA0D;oBAC1D,WAAW,EAAE,oBAAoB;iBAClC,CAAC;gBACF,MAAM,gBAAgB,GAAG,GAAG,cAAc,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;gBACnE,MAAM,SAAS,CACb,UAAU,CAAC,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,GAAG,CAAC,EACnD,IAAI,CACL,CAAC;YACJ,CAAC;iBAAM,IAAI,IAAI,CAAC,SAAS,KAAK,cAAc,EAAE,CAAC;gBAC7C,6DAA6D;gBAC7D,kEAAkE;gBAClE,2DAA2D;gBAC3D,IAAI,aAAa,EAAE,CAAC;oBAClB,wDAAwD;oBACxD,IACE,aAAa,CAAC,UAAU;wBACxB,aAAa,CAAC,UAAU,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,EAC/C,CAAC;wBACD,MAAM,IAAI,aAAa,CACrB,sBAAsB,IAAI,CAAC,aAAa,kDAAkD,EAC1F;4BACE,UAAU,EAAE,IAAI,CAAC,IAAI,CACnB,CAAC,aAAa,CAAC,UAAU,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,GAAG,IAAI,CACzD;yBACF,CACF,CAAC;oBACJ,CAAC;oBAED,4DAA4D;oBAC5D,8DAA8D;oBAC9D,iEAAiE;oBACjE,8DAA8D;oBAC9D,sDAAsD;oBACtD,MAAM,gBAAgB,GAAG,GAAG,cAAc,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;oBACnE,MAAM,SAAS,GAAG,MAAM,oBAAoB,CAC1C,OAAO,EACP,OAAO,EACP,gBAAgB,EAChB,UAAU,EACV,GAAG,CACJ,CAAC;oBACF,IAAI,SAAS,IAAI,cAAc,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;wBAClD,MAAM,IAAI,mBAAmB,CAC3B,yCAAyC,SAAS,CAAC,MAAM,GAAG,CAC7D,CAAC;oBACJ,CAAC;oBAED,IAAI,GAAG;wBACL,GAAG,aAAa;wBAChB,MAAM,EAAE,SAAS;wBACjB,wCAAwC;wBACxC,SAAS,EAAE,aAAa,CAAC,SAAS,IAAI,GAAG;wBACzC,2CAA2C;wBAC3C,OAAO,EAAE,aAAa,CAAC,OAAO,GAAG,CAAC;wBAClC,iDAAiD;wBACjD,UAAU,EAAE,SAAS;wBACrB,SAAS,EAAE,GAAG;qBACf,CAAC;oBACF,MAAM,SAAS,CACb,UAAU,CAAC,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,GAAG,CAAC,EACnD,IAAI,EACJ,EAAE,SAAS,EAAE,IAAI,EAAE,CACpB,CAAC;gBACJ,CAAC;YACH,CAAC;iBAAM,IAAI,IAAI,CAAC,SAAS,KAAK,gBAAgB,IAAI,WAAW,IAAI,IAAI,EAAE,CAAC;gBACtE,6CAA6C;gBAC7C,sEAAsE;gBACtE,gEAAgE;gBAChE,MAAM,aAAa,GAAG,IAAI,CAAC,SAA4B,CAAC;gBACxD,IAAI,aAAa,EAAE,CAAC;oBAClB,MAAM,gBAAgB,GAAG,GAAG,cAAc,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;oBACnE,MAAM,QAAQ,GAAG,GAAG;wBAClB,CAAC,CAAC,GAAG,gBAAgB,aAAa,GAAG,EAAE;wBACvC,CAAC,CAAC,GAAG,gBAAgB,WAAW,CAAC;oBACnC,MAAM,gBAAgB,GAAG,iBAAiB,CACxC,OAAO,EACP,QAAQ,EACR,OAAO,EACP,QAAQ,CACT,CAAC;oBACF,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,gBAAgB,EAAE,EAAE,CAAC,CAAC;oBAC3D,IAAI,CAAC,OAAO,EAAE,CAAC;wBACb,MAAM,IAAI,mBAAmB,CAC3B,sCAAsC,CACvC,CAAC;oBACJ,CAAC;oBACD,IAAI,GAAG;wBACL,GAAG,aAAa;wBAChB,MAAM,EAAE,WAAW;wBACnB,MAAM,EAAE,aAAa,CAAC,MAAM;wBAC5B,WAAW,EAAE,GAAG;wBAChB,SAAS,EAAE,GAAG;qBACf,CAAC;oBACF,MAAM,SAAS,CACb,UAAU,CAAC,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,GAAG,CAAC,EACnD,IAAI,EACJ,EAAE,SAAS,EAAE,IAAI,EAAE,CACpB,CAAC;gBACJ,CAAC;YACH,CAAC;iBAAM,IAAI,IAAI,CAAC,SAAS,KAAK,aAAa,IAAI,WAAW,IAAI,IAAI,EAAE,CAAC;gBACnE,yCAAyC;gBACzC,sEAAsE;gBACtE,6DAA6D;gBAC7D,MAAM,UAAU,GAAG,IAAI,CAAC,SAGvB,CAAC;gBACF,IAAI,aAAa,EAAE,CAAC;oBAClB,MAAM,gBAAgB,GAAG,GAAG,cAAc,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;oBACnE,MAAM,QAAQ,GAAG,GAAG;wBAClB,CAAC,CAAC,GAAG,gBAAgB,aAAa,GAAG,EAAE;wBACvC,CAAC,CAAC,GAAG,gBAAgB,WAAW,CAAC;oBACnC,MAAM,gBAAgB,GAAG,iBAAiB,CACxC,OAAO,EACP,QAAQ,EACR,OAAO,EACP,QAAQ,CACT,CAAC;oBACF,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,gBAAgB,EAAE,EAAE,CAAC,CAAC;oBAC3D,IAAI,CAAC,OAAO,EAAE,CAAC;wBACb,MAAM,IAAI,mBAAmB,CAC3B,sCAAsC,CACvC,CAAC;oBACJ,CAAC;oBACD,MAAM,KAAK,GAAG;wBACZ,OAAO,EACL,OAAO,UAAU,CAAC,KAAK,KAAK,QAAQ;4BAClC,CAAC,CAAC,UAAU,CAAC,KAAK;4BAClB,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,EAAE,OAAO,IAAI,eAAe,CAAC;wBACpD,KAAK,EAAE,UAAU,CAAC,KAAK;qBACxB,CAAC;oBACF,IAAI,GAAG;wBACL,GAAG,aAAa;wBAChB,MAAM,EAAE,QAAQ;wBAChB,KAAK;wBACL,WAAW,EAAE,GAAG;wBAChB,SAAS,EAAE,GAAG;qBACf,CAAC;oBACF,MAAM,SAAS,CACb,UAAU,CAAC,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,GAAG,CAAC,EACnD,IAAI,EACJ,EAAE,SAAS,EAAE,IAAI,EAAE,CACpB,CAAC;gBACJ,CAAC;YACH,CAAC;iBAAM,IAAI,IAAI,CAAC,SAAS,KAAK,eAAe,IAAI,WAAW,IAAI,IAAI,EAAE,CAAC;gBACrE,8DAA8D;gBAC9D,2DAA2D;gBAC3D,MAAM,SAAS,GAAG,IAAI,CAAC,SAItB,CAAC;gBACF,IAAI,aAAa,EAAE,CAAC;oBAClB,MAAM,gBAAgB,GAAG,GAAG,cAAc,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;oBACnE,IAAI,GAAG;wBACL,GAAG,aAAa;wBAChB,MAAM,EAAE,SAAS;wBACjB,KAAK,EAAE;4BACL,OAAO,EACL,OAAO,SAAS,CAAC,KAAK,KAAK,QAAQ;gCACjC,CAAC,CAAC,SAAS,CAAC,KAAK;gCACjB,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,EAAE,OAAO,IAAI,eAAe,CAAC;4BACnD,KAAK,EAAE,SAAS,CAAC,KAAK;yBACvB;wBACD,UAAU,EAAE,SAAS,CAAC,UAAU;wBAChC,SAAS,EAAE,GAAG;qBACf,CAAC;oBACF,MAAM,SAAS,CACb,UAAU,CAAC,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,GAAG,CAAC,EACnD,IAAI,EACJ,EAAE,SAAS,EAAE,IAAI,EAAE,CACpB,CAAC;gBACJ,CAAC;YACH,CAAC;iBAAM;YACL,wBAAwB;YACxB,IAAI,CAAC,SAAS,KAAK,cAAc;gBACjC,WAAW,IAAI,IAAI,EACnB,CAAC;gBACD,MAAM,QAAQ,GAAG,IAAI,CAAC,SAIrB,CAAC;gBAEF,wEAAwE;gBACxE,4EAA4E;gBAC5E,MAAM,cAAc,GAAG,IAAI,CAAC,IAAI,CAC9B,OAAO,EACP,OAAO,EACP,QAAQ,EACR,GAAG,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,CACpC,CAAC;gBACF,MAAM,YAAY,GAAG,MAAM,cAAc,CACvC,cAAc,EACd,IAAI,CAAC,SAAS,CAAC;oBACb,KAAK,EAAE,QAAQ,CAAC,KAAK;oBACrB,MAAM,EAAE,IAAI,CAAC,aAAa;oBAC1B,KAAK,EAAE,cAAc;iBACtB,CAAC,CACH,CAAC;gBAEF,IAAI,CAAC,YAAY,EAAE,CAAC;oBAClB,qDAAqD;oBACrD,oFAAoF;oBACpF,MAAM,aAAa,GAAU;wBAC3B,SAAS,EAAE,eAAe;wBAC1B,aAAa,EAAE,IAAI,CAAC,aAAa;wBACjC,SAAS,EAAE;4BACT,KAAK,EAAE,QAAQ,CAAC,KAAK;yBACtB;wBACD,KAAK,EAAE,cAAc;wBACrB,OAAO;wBACP,SAAS,EAAE,GAAG;wBACd,WAAW,EAAE,oBAAoB;qBAClC,CAAC;oBAEF,2BAA2B;oBAC3B,MAAM,YAAY,GAAG,GAAG,cAAc,IAAI,OAAO,EAAE,CAAC;oBACpD,MAAM,SAAS,CACb,UAAU,CAAC,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,GAAG,CAAC,EAChD,aAAa,CACd,CAAC;oBAEF,MAAM,WAAW,GACf,MAAM,EAAE,WAAW,IAAI,2BAA2B,CAAC;oBACrD,MAAM,aAAa,GAAG,kBAAkB,CAAC,aAAa,EAAE,WAAW,CAAC,CAAC;oBAErE,kEAAkE;oBAClE,OAAO;wBACL,KAAK,EAAE,aAAa;wBACpB,GAAG;wBACH,IAAI;wBACJ,IAAI,EAAE,SAAS;qBAChB,CAAC;gBACJ,CAAC;gBAED,IAAI,GAAG;oBACL,KAAK,EAAE,cAAc;oBACrB,MAAM,EAAE,IAAI,CAAC,aAAa;oBAC1B,KAAK,EAAE,QAAQ,CAAC,KAAK;oBACrB,QAAQ,EAAE,QAAQ,CAAC,QAAQ;oBAC3B,OAAO,EAAE,aAAa;oBACtB,SAAS,EAAE,eAAe;oBAC1B,WAAW,EAAE,OAAO;oBACpB,SAAS,EAAE,GAAG;oBACd,0DAA0D;oBAC1D,WAAW,EAAE,oBAAoB;oBACjC,SAAS,EAAE,QAAQ,CAAC,SAAS,IAAI,KAAK;iBACvC,CAAC;gBACF,MAAM,SAAS,CACb,UAAU,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,aAAa,EAAE,GAAG,CAAC,EACrD,IAAI,CACL,CAAC;YACJ,CAAC;iBAAM,IAAI,IAAI,CAAC,SAAS,KAAK,eAAe,EAAE,CAAC;gBAC9C,0DAA0D;gBAC1D,sEAAsE;gBACtE,+DAA+D;gBAC/D,MAAM,YAAY,GAAG,GAAG;oBACtB,CAAC,CAAC,GAAG,IAAI,CAAC,aAAa,aAAa,GAAG,EAAE;oBACzC,CAAC,CAAC,GAAG,IAAI,CAAC,aAAa,WAAW,CAAC;gBACrC,MAAM,QAAQ,GAAG,iBAAiB,CAChC,OAAO,EACP,QAAQ,EACR,OAAO,EACP,YAAY,CACb,CAAC;gBACF,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;gBACnD,IAAI,CAAC,OAAO,EAAE,CAAC;oBACb,MAAM,IAAI,mBAAmB,CAC3B,SAAS,IAAI,CAAC,aAAa,oBAAoB,CAChD,CAAC;gBACJ,CAAC;gBACD,iDAAiD;gBACjD,MAAM,QAAQ,GAAG,UAAU,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,aAAa,EAAE,GAAG,CAAC,CAAC;gBACvE,MAAM,YAAY,GAAG,MAAM,oBAAoB,CAC7C,OAAO,EACP,OAAO,EACP,IAAI,CAAC,aAAa,EAClB,UAAU,EACV,GAAG,CACJ,CAAC;gBACF,IAAI,YAAY,EAAE,CAAC;oBACjB,kEAAkE;oBAClE,MAAM,sBAAsB,GAAG,IAAI,CAAC,IAAI,CACtC,OAAO,EACP,OAAO,EACP,QAAQ,EACR,GAAG,SAAS,CAAC,YAAY,CAAC,KAAK,CAAC,OAAO,CACxC,CAAC;oBACF,MAAM,UAAU,CAAC,sBAAsB,CAAC,CAAC;gBAC3C,CAAC;gBACD,MAAM,UAAU,CAAC,QAAQ,CAAC,CAAC;YAC7B,CAAC;iBAAM,IAAI,IAAI,CAAC,SAAS,KAAK,cAAc,IAAI,WAAW,IAAI,IAAI,EAAE,CAAC;gBACpE,0DAA0D;gBAC1D,MAAM,QAAQ,GAAG,IAAI,CAAC,SAErB,CAAC;gBACF,MAAM,gBAAgB,GAAG,GAAG,cAAc,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;gBACnE,MAAM,YAAY,GAAG,MAAM,oBAAoB,CAC7C,OAAO,EACP,OAAO,EACP,gBAAgB,EAChB,UAAU,EACV,GAAG,CACJ,CAAC;gBACF,IAAI,YAAY,EAAE,CAAC;oBACjB,MAAM,IAAI,mBAAmB,CAC3B,SAAS,IAAI,CAAC,aAAa,kBAAkB,CAC9C,CAAC;gBACJ,CAAC;gBACD,IAAI,GAAG;oBACL,MAAM,EAAE,gBAAgB;oBACxB,KAAK,EAAE,cAAc;oBACrB,MAAM,EAAE,SAAS;oBACjB,QAAQ,EAAE,QAAQ,CAAC,QAAQ;oBAC3B,WAAW,EAAE,SAAS;oBACtB,SAAS,EAAE,GAAG;oBACd,SAAS,EAAE,GAAG;oBACd,WAAW,EAAE,oBAAoB;iBAClC,CAAC;gBACF,MAAM,SAAS,CACb,UAAU,CAAC,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,GAAG,CAAC,EACnD,IAAI,CACL,CAAC;YACJ,CAAC;iBAAM,IAAI,IAAI,CAAC,SAAS,KAAK,gBAAgB,EAAE,CAAC;gBAC/C,uEAAuE;gBACvE,sEAAsE;gBACtE,gEAAgE;gBAChE,MAAM,gBAAgB,GAAG,GAAG,cAAc,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;gBACnE,MAAM,YAAY,GAAG,GAAG;oBACtB,CAAC,CAAC,GAAG,gBAAgB,cAAc,GAAG,EAAE;oBACxC,CAAC,CAAC,GAAG,gBAAgB,YAAY,CAAC;gBACpC,MAAM,QAAQ,GAAG,iBAAiB,CAChC,OAAO,EACP,QAAQ,EACR,OAAO,EACP,YAAY,CACb,CAAC;gBACF,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;gBACnD,IAAI,CAAC,OAAO,EAAE,CAAC;oBACb,MAAM,IAAI,mBAAmB,CAC3B,SAAS,IAAI,CAAC,aAAa,qBAAqB,CACjD,CAAC;gBACJ,CAAC;gBACD,MAAM,YAAY,GAAG,MAAM,oBAAoB,CAC7C,OAAO,EACP,OAAO,EACP,gBAAgB,EAChB,UAAU,EACV,GAAG,CACJ,CAAC;gBACF,IAAI,CAAC,YAAY,EAAE,CAAC;oBAClB,kEAAkE;oBAClE,MAAM,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;oBAC1C,MAAM,IAAI,kBAAkB,CAC1B,SAAS,IAAI,CAAC,aAAa,aAAa,CACzC,CAAC;gBACJ,CAAC;gBACD,mEAAmE;gBACnE,mDAAmD;gBACnD,IAAI,GAAG;oBACL,GAAG,YAAY;oBACf,MAAM,EAAE,WAAW;oBACnB,WAAW,EAAE,GAAG;oBAChB,SAAS,EAAE,GAAG;iBACf,CAAC;gBACF,MAAM,SAAS,CACb,UAAU,CAAC,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,GAAG,CAAC,EACnD,IAAI,EACJ,EAAE,SAAS,EAAE,IAAI,EAAE,CACpB,CAAC;YACJ,CAAC;YACD,mEAAmE;YACnE,8DAA8D;YAE9D,oDAAoD;YACpD,MAAM,YAAY,GAAG,GAAG,cAAc,IAAI,OAAO,EAAE,CAAC;YACpD,MAAM,SAAS,CAAC,UAAU,CAAC,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,GAAG,CAAC,EAAE,KAAK,CAAC,CAAC;YAEzE,MAAM,WAAW,GAAG,MAAM,EAAE,WAAW,IAAI,2BAA2B,CAAC;YACvE,MAAM,aAAa,GAAG,kBAAkB,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;YAE7D,8DAA8D;YAC9D,gDAAgD;YAChD,IAAI,MAA2B,CAAC;YAChC,IAAI,MAAiC,CAAC;YACtC,IAAI,OAA4B,CAAC;YACjC,IAAI,IAAI,CAAC,SAAS,KAAK,aAAa,IAAI,GAAG,EAAE,CAAC;gBAC5C,MAAM,SAAS,GAAG,MAAM,wBAAwB,CAAC;oBAC/C,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC;oBACvC,MAAM,EAAE,WAAW;oBACnB,UAAU,EAAE,GAAG,cAAc,GAAG;oBAChC,SAAS,EAAE,KAAK;oBAChB,KAAK,EAAE,IAAI;oBACX,YAAY,EAAE,kBAAkB,CAAC,MAAM,CAAC;oBACxC,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO;iBACxB,CAAC,CAAC;gBACH,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC;gBACxB,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC;gBAC1B,OAAO,GAAG,SAAS,CAAC,OAAO,CAAC;YAC9B,CAAC;YAED,+DAA+D;YAC/D,OAAO;gBACL,KAAK,EAAE,aAAa;gBACpB,GAAG;gBACH,IAAI;gBACJ,IAAI;gBACJ,IAAI;gBACJ,MAAM;gBACN,MAAM;gBACN,OAAO;aACR,CAAC;QACJ,CAAC;QAED,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM;YAC9B,kBAAkB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;YACnC,kBAAkB,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;YACvC,MAAM,YAAY,GAAG,GAAG,KAAK,IAAI,OAAO,EAAE,CAAC;YAC3C,MAAM,KAAK,GAAG,MAAM,oBAAoB,CACtC,OAAO,EACP,QAAQ,EACR,YAAY,EACZ,WAAW,EACX,GAAG,CACJ,CAAC;YACF,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,MAAM,IAAI,KAAK,CAAC,SAAS,OAAO,WAAW,KAAK,YAAY,CAAC,CAAC;YAChE,CAAC;YACD,MAAM,WAAW,GAAG,MAAM,EAAE,WAAW,IAAI,2BAA2B,CAAC;YACvE,OAAO,kBAAkB,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;QAChD,CAAC;QAED,KAAK,CAAC,IAAI,CAAC,MAAM;YACf,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,CAAC;YACzB,kBAAkB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;YACnC,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,IAAI,2BAA2B,CAAC;YACtE,MAAM,MAAM,GAAG,MAAM,wBAAwB,CAAC;gBAC5C,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC;gBACvC,MAAM,EAAE,WAAW;gBACnB,UAAU,EAAE,GAAG,KAAK,GAAG;gBACvB,2DAA2D;gBAC3D,mDAAmD;gBACnD,SAAS,EAAE,MAAM,CAAC,UAAU,EAAE,SAAS,IAAI,KAAK;gBAChD,KAAK,EAAE,MAAM,CAAC,UAAU,EAAE,KAAK;gBAC/B,MAAM,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM;gBACjC,YAAY,EAAE,kBAAkB,CAAC,MAAM,CAAC;gBACxC,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO;aAChC,CAAC,CAAC;YAEH,yDAAyD;YACzD,IAAI,WAAW,KAAK,MAAM,EAAE,CAAC;gBAC3B,OAAO;oBACL,GAAG,MAAM;oBACT,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAC9B,kBAAkB,CAAC,KAAK,EAAE,WAAW,CAAC,CACvC;iBACF,CAAC;YACJ,CAAC;YAED,OAAO,MAAM,CAAC;QAChB,CAAC;QAED,KAAK,CAAC,mBAAmB,CAAC,MAAM;YAC9B,MAAM,aAAa,GAAG,MAAM,CAAC,aAAa,CAAC;YAC3C,kBAAkB,CAAC,eAAe,EAAE,aAAa,CAAC,CAAC;YACnD,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,IAAI,2BAA2B,CAAC;YACtE,MAAM,MAAM,GAAG,MAAM,wBAAwB,CAAC;gBAC5C,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC;gBACvC,MAAM,EAAE,WAAW;gBACnB,oCAAoC;gBACpC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,aAAa,KAAK,aAAa;gBACxD,2DAA2D;gBAC3D,mDAAmD;gBACnD,SAAS,EAAE,MAAM,CAAC,UAAU,EAAE,SAAS,IAAI,KAAK;gBAChD,KAAK,EAAE,MAAM,CAAC,UAAU,EAAE,KAAK;gBAC/B,MAAM,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM;gBACjC,YAAY,EAAE,kBAAkB,CAAC,MAAM,CAAC;gBACxC,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO;aAChC,CAAC,CAAC;YAEH,yDAAyD;YACzD,IAAI,WAAW,KAAK,MAAM,EAAE,CAAC;gBAC3B,OAAO;oBACL,GAAG,MAAM;oBACT,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAC9B,kBAAkB,CAAC,KAAK,EAAE,WAAW,CAAC,CACvC;iBACF,CAAC;YACJ,CAAC;YAED,OAAO,MAAM,CAAC;QAChB,CAAC;KACF,CAAC;AACJ,CAAC","sourcesContent":["import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport {\n EntityConflictError,\n HookNotFoundError,\n RunExpiredError,\n RunNotSupportedError,\n TooEarlyError,\n WorkflowWorldError,\n} from '@workflow/errors';\nimport type {\n Event,\n EventResult,\n Hook,\n SerializedData,\n Step,\n Storage,\n Wait,\n WorkflowRun,\n} from '@workflow/world';\nimport {\n EventSchema,\n HookSchema,\n isLegacySpecVersion,\n requiresNewerWorld,\n SPEC_VERSION_CURRENT,\n StepSchema,\n validateUlidTimestamp,\n WaitSchema,\n WorkflowRunSchema,\n} from '@workflow/world';\nimport { DEFAULT_RESOLVE_DATA_OPTION } from '../config.js';\nimport {\n assertSafeEntityId,\n deleteJSON,\n jsonReplacer,\n listJSONFiles,\n paginatedFileSystemQuery,\n readJSONWithFallback,\n resolveWithinBase,\n taggedPath,\n writeExclusive,\n writeJSON,\n} from '../fs.js';\nimport { stripEventDataRefs } from './filters.js';\nimport { getObjectCreatedAt, hashToken, monotonicUlid } from './helpers.js';\nimport { deleteAllHooksForRun } from './hooks-storage.js';\nimport { handleLegacyEvent } from './legacy.js';\n\n/**\n * Helper function to delete all waits associated with a workflow run.\n * Called when a run reaches a terminal state.\n */\nasync function deleteAllWaitsForRun(\n basedir: string,\n runId: string\n): Promise<void> {\n const waitsDir = path.join(basedir, 'waits');\n const files = await listJSONFiles(waitsDir);\n\n for (const file of files) {\n // fileIds may contain tag suffixes (e.g., \"wrun_ABC-corrId.vitest-0\")\n // but startsWith still matches correctly since the tag is a suffix.\n if (file.startsWith(`${runId}-`)) {\n const waitPath = path.join(waitsDir, `${file}.json`);\n await deleteJSON(waitPath);\n }\n }\n}\n\n/**\n * Creates the events storage implementation using the filesystem.\n * Implements the Storage['events'] interface with create, list, and listByCorrelationId operations.\n */\nexport function createEventsStorage(\n basedir: string,\n tag?: string\n): Storage['events'] {\n return {\n async create(runId, data, params): Promise<EventResult> {\n const eventId = `evnt_${monotonicUlid()}`;\n const now = new Date();\n\n // Validate request-supplied IDs before they're concatenated into\n // filesystem paths. This is the primary defense against path traversal\n // attacks where a client supplies runId / correlationId values like\n // \"../../../package\" to read or write files outside the storage root.\n //\n // Empty `correlationId` values are also rejected here: the event\n // schemas only require `z.string()`, so without this check a\n // step_created / hook_created / wait_created request with\n // `correlationId: ''` would silently be written under a malformed\n // composite key like `${runId}-`.\n if (runId != null && runId !== '') {\n assertSafeEntityId('runId', runId);\n }\n if ('correlationId' in data && typeof data.correlationId === 'string') {\n assertSafeEntityId('correlationId', data.correlationId);\n }\n\n // For run_created events, use client-provided runId or generate one server-side\n let effectiveRunId: string;\n if (data.eventType === 'run_created' && (!runId || runId === '')) {\n effectiveRunId = `wrun_${monotonicUlid()}`;\n } else if (!runId) {\n throw new Error('runId is required for non-run_created events');\n } else {\n effectiveRunId = runId;\n }\n\n // Validate client-provided runId timestamp is within acceptable threshold\n if (data.eventType === 'run_created' && runId && runId !== '') {\n const validationError = validateUlidTimestamp(effectiveRunId, 'wrun_');\n if (validationError) {\n throw new WorkflowWorldError(validationError);\n }\n }\n\n // specVersion is always sent by the runtime, but we provide a fallback for safety\n const effectiveSpecVersion = data.specVersion ?? SPEC_VERSION_CURRENT;\n\n // Helper to check if run is in terminal state\n const isRunTerminal = (status: string) =>\n ['completed', 'failed', 'cancelled'].includes(status);\n\n // Helper to check if step is in terminal state\n const isStepTerminal = (status: string) =>\n ['completed', 'failed', 'cancelled'].includes(status);\n\n // Get current run state for validation (if not creating a new run)\n // Skip run validation for step_completed and step_retrying - they only operate\n // on running steps, and running steps are always allowed to modify regardless\n // of run state. This optimization saves filesystem reads per step event.\n let currentRun: WorkflowRun | null = null;\n const skipRunValidationEvents = ['step_completed', 'step_retrying'];\n if (\n data.eventType !== 'run_created' &&\n !skipRunValidationEvents.includes(data.eventType)\n ) {\n currentRun = await readJSONWithFallback(\n basedir,\n 'runs',\n effectiveRunId,\n WorkflowRunSchema,\n tag\n );\n\n // Resilient start: run_started on non-existent run with eventData\n // creates the run first, so the queue can bootstrap a run that\n // failed to create during start().\n if (\n data.eventType === 'run_started' &&\n !currentRun &&\n 'eventData' in data &&\n data.eventData\n ) {\n const runInputData = data.eventData as {\n deploymentId?: string;\n workflowName?: string;\n input?: any;\n executionContext?: Record<string, any>;\n };\n if (\n runInputData.deploymentId &&\n runInputData.workflowName &&\n runInputData.input !== undefined\n ) {\n // Atomically try to create the run entity. writeExclusive\n // uses O_CREAT|O_EXCL so only the first writer wins,\n // preventing a TOCTOU race where a concurrent run_created\n // from start() could overwrite a run that was already\n // transitioned to 'running'.\n const createdRun: WorkflowRun = {\n runId: effectiveRunId,\n deploymentId: runInputData.deploymentId,\n status: 'pending',\n workflowName: runInputData.workflowName,\n specVersion: effectiveSpecVersion,\n executionContext: runInputData.executionContext,\n input: runInputData.input,\n output: undefined,\n error: undefined,\n startedAt: undefined,\n completedAt: undefined,\n createdAt: now,\n updatedAt: now,\n };\n const runPath = taggedPath(basedir, 'runs', effectiveRunId, tag);\n const created = await writeExclusive(\n runPath,\n JSON.stringify(createdRun, jsonReplacer)\n );\n\n if (created) {\n // We created the run — also write the run_created event.\n const runCreatedEventId = `evnt_${monotonicUlid()}`;\n const runCreatedEvent: Event = {\n eventType: 'run_created',\n runId: effectiveRunId,\n eventId: runCreatedEventId,\n createdAt: now,\n specVersion: effectiveSpecVersion,\n eventData: {\n deploymentId: runInputData.deploymentId,\n workflowName: runInputData.workflowName,\n input: runInputData.input,\n executionContext: runInputData.executionContext,\n },\n };\n const createdCompositeKey = `${effectiveRunId}-${runCreatedEventId}`;\n await writeJSON(\n taggedPath(basedir, 'events', createdCompositeKey, tag),\n runCreatedEvent\n );\n currentRun = createdRun;\n } else {\n // Run already exists (concurrent run_created won the\n // race). Re-read it so downstream logic sees the real state.\n currentRun = await readJSONWithFallback(\n basedir,\n 'runs',\n effectiveRunId,\n WorkflowRunSchema,\n tag\n );\n }\n }\n }\n }\n\n // ============================================================\n // VERSION COMPATIBILITY: Check run spec version\n // ============================================================\n // For events that have fetched the run, check version compatibility.\n // Skip for run_created (no existing run) and runtime events (step_completed, step_retrying).\n if (currentRun) {\n // Check if run requires a newer world version\n if (requiresNewerWorld(currentRun.specVersion)) {\n throw new RunNotSupportedError(\n currentRun.specVersion!,\n SPEC_VERSION_CURRENT\n );\n }\n\n // Route to legacy handler for pre-event-sourcing runs\n if (isLegacySpecVersion(currentRun.specVersion)) {\n return handleLegacyEvent(\n basedir,\n effectiveRunId,\n data,\n currentRun,\n params\n );\n }\n }\n\n // ============================================================\n // VALIDATION: Terminal state and event ordering checks\n // ============================================================\n\n // Run terminal state validation\n if (currentRun && isRunTerminal(currentRun.status)) {\n const runTerminalEvents = [\n 'run_started',\n 'run_completed',\n 'run_failed',\n ];\n\n // Idempotent operation: run_cancelled on already cancelled run is allowed\n if (\n data.eventType === 'run_cancelled' &&\n currentRun.status === 'cancelled'\n ) {\n // Return existing state (idempotent)\n const event: Event = {\n ...data,\n runId: effectiveRunId,\n eventId,\n createdAt: now,\n specVersion: effectiveSpecVersion,\n };\n const compositeKey = `${effectiveRunId}-${eventId}`;\n await writeJSON(\n taggedPath(basedir, 'events', compositeKey, tag),\n event\n );\n const resolveData =\n params?.resolveData ?? DEFAULT_RESOLVE_DATA_OPTION;\n return {\n event: stripEventDataRefs(event, resolveData),\n run: currentRun,\n };\n }\n\n // For run_started on terminal runs, use RunExpiredError so the\n // runtime knows to exit without retrying.\n if (data.eventType === 'run_started') {\n throw new RunExpiredError(\n `Workflow run \"${effectiveRunId}\" is already in terminal state \"${currentRun.status}\"`\n );\n }\n\n // Other run state transitions are not allowed on terminal runs\n if (\n runTerminalEvents.includes(data.eventType) ||\n data.eventType === 'run_cancelled'\n ) {\n throw new EntityConflictError(\n `Cannot transition run from terminal state \"${currentRun.status}\"`\n );\n }\n\n // Creating new entities on terminal runs is not allowed\n if (\n data.eventType === 'step_created' ||\n data.eventType === 'hook_created' ||\n data.eventType === 'wait_created'\n ) {\n throw new EntityConflictError(\n `Cannot create new entities on run in terminal state \"${currentRun.status}\"`\n );\n }\n }\n\n // Step-related event validation (ordering and terminal state)\n // Store existingStep so we can reuse it later (avoid double read)\n let validatedStep: Step | null = null;\n const stepEvents = [\n 'step_started',\n 'step_completed',\n 'step_failed',\n 'step_retrying',\n ];\n if (stepEvents.includes(data.eventType) && data.correlationId) {\n const stepCompositeKey = `${effectiveRunId}-${data.correlationId}`;\n validatedStep = await readJSONWithFallback(\n basedir,\n 'steps',\n stepCompositeKey,\n StepSchema,\n tag\n );\n\n // Event ordering: step must exist before these events\n if (!validatedStep) {\n throw new WorkflowWorldError(\n `Step \"${data.correlationId}\" not found`\n );\n }\n\n // Step terminal state validation\n if (isStepTerminal(validatedStep.status)) {\n throw new EntityConflictError(\n `Cannot modify step in terminal state \"${validatedStep.status}\"`\n );\n }\n\n // On terminal runs: only allow completing/failing in-progress steps\n if (currentRun && isRunTerminal(currentRun.status)) {\n if (validatedStep.status !== 'running') {\n throw new RunExpiredError(\n `Cannot modify non-running step on run in terminal state \"${currentRun.status}\"`\n );\n }\n }\n }\n\n // Hook-related event validation (ordering)\n const hookEventsRequiringExistence = ['hook_disposed', 'hook_received'];\n if (\n hookEventsRequiringExistence.includes(data.eventType) &&\n data.correlationId\n ) {\n const existingHook = await readJSONWithFallback(\n basedir,\n 'hooks',\n data.correlationId,\n HookSchema,\n tag\n );\n\n if (!existingHook) {\n throw new HookNotFoundError(data.correlationId);\n }\n }\n const event: Event = {\n ...data,\n runId: effectiveRunId,\n eventId,\n createdAt: now,\n specVersion: effectiveSpecVersion,\n };\n // Strip eventData from run_started — it belongs on run_created only.\n if (data.eventType === 'run_started' && 'eventData' in event) {\n delete (event as any).eventData;\n }\n\n // Track entity created/updated for EventResult\n let run: WorkflowRun | undefined;\n let step: Step | undefined;\n let hook: Hook | undefined;\n let wait: Wait | undefined;\n\n // Create/update entity based on event type (event-sourced architecture)\n // Run lifecycle events\n if (data.eventType === 'run_created' && 'eventData' in data) {\n const runData = data.eventData as {\n deploymentId: string;\n workflowName: string;\n input: SerializedData;\n executionContext?: Record<string, any>;\n };\n run = {\n runId: effectiveRunId,\n deploymentId: runData.deploymentId,\n status: 'pending',\n workflowName: runData.workflowName,\n // Propagate specVersion from the event to the run entity\n specVersion: effectiveSpecVersion,\n executionContext: runData.executionContext,\n input: runData.input,\n output: undefined,\n error: undefined,\n startedAt: undefined,\n completedAt: undefined,\n createdAt: now,\n updatedAt: now,\n };\n // Use writeExclusive (O_CREAT|O_EXCL) to atomically create the\n // run entity file. This prevents a TOCTOU race with the resilient\n // start path (run_started on non-existent run) that could result\n // in duplicate run_created events in the event log.\n const runPath = taggedPath(basedir, 'runs', effectiveRunId, tag);\n const created = await writeExclusive(\n runPath,\n JSON.stringify(run, jsonReplacer, 2)\n );\n if (!created) {\n throw new EntityConflictError(\n `Workflow run \"${effectiveRunId}\" already exists`\n );\n }\n } else if (data.eventType === 'run_started') {\n // Reuse currentRun from validation (already read above)\n if (currentRun) {\n // If already running, return the run without inserting a\n // duplicate event. This makes run_started idempotent for\n // concurrent invocations. We omit preloaded events here\n // because this is a rare race-condition path — the runtime\n // falls back to loading events separately.\n if (currentRun.status === 'running') {\n return { run: currentRun };\n }\n\n run = {\n runId: currentRun.runId,\n deploymentId: currentRun.deploymentId,\n workflowName: currentRun.workflowName,\n specVersion: currentRun.specVersion,\n executionContext: currentRun.executionContext,\n input: currentRun.input,\n createdAt: currentRun.createdAt,\n expiredAt: currentRun.expiredAt,\n status: 'running',\n output: undefined,\n error: undefined,\n completedAt: undefined,\n startedAt: currentRun.startedAt ?? now,\n updatedAt: now,\n };\n await writeJSON(\n taggedPath(basedir, 'runs', effectiveRunId, tag),\n run,\n { overwrite: true }\n );\n }\n } else if (data.eventType === 'run_completed' && 'eventData' in data) {\n const completedData = data.eventData as { output?: any };\n // Reuse currentRun from validation (already read above)\n if (currentRun) {\n run = {\n runId: currentRun.runId,\n deploymentId: currentRun.deploymentId,\n workflowName: currentRun.workflowName,\n specVersion: currentRun.specVersion,\n executionContext: currentRun.executionContext,\n input: currentRun.input,\n createdAt: currentRun.createdAt,\n expiredAt: currentRun.expiredAt,\n startedAt: currentRun.startedAt,\n status: 'completed',\n output: completedData.output,\n error: undefined,\n completedAt: now,\n updatedAt: now,\n };\n await writeJSON(\n taggedPath(basedir, 'runs', effectiveRunId, tag),\n run,\n { overwrite: true }\n );\n await Promise.all([\n deleteAllHooksForRun(basedir, effectiveRunId),\n deleteAllWaitsForRun(basedir, effectiveRunId),\n ]);\n }\n } else if (data.eventType === 'run_failed' && 'eventData' in data) {\n const failedData = data.eventData as {\n error: any;\n errorCode?: string;\n };\n // Reuse currentRun from validation (already read above)\n if (currentRun) {\n run = {\n runId: currentRun.runId,\n deploymentId: currentRun.deploymentId,\n workflowName: currentRun.workflowName,\n specVersion: currentRun.specVersion,\n executionContext: currentRun.executionContext,\n input: currentRun.input,\n createdAt: currentRun.createdAt,\n expiredAt: currentRun.expiredAt,\n startedAt: currentRun.startedAt,\n status: 'failed',\n output: undefined,\n error: {\n message:\n typeof failedData.error === 'string'\n ? failedData.error\n : (failedData.error?.message ?? 'Unknown error'),\n stack: failedData.error?.stack,\n code: failedData.errorCode,\n },\n completedAt: now,\n updatedAt: now,\n };\n await writeJSON(\n taggedPath(basedir, 'runs', effectiveRunId, tag),\n run,\n { overwrite: true }\n );\n await Promise.all([\n deleteAllHooksForRun(basedir, effectiveRunId),\n deleteAllWaitsForRun(basedir, effectiveRunId),\n ]);\n }\n } else if (data.eventType === 'run_cancelled') {\n // Reuse currentRun from validation (already read above)\n if (currentRun) {\n run = {\n runId: currentRun.runId,\n deploymentId: currentRun.deploymentId,\n workflowName: currentRun.workflowName,\n specVersion: currentRun.specVersion,\n executionContext: currentRun.executionContext,\n input: currentRun.input,\n createdAt: currentRun.createdAt,\n expiredAt: currentRun.expiredAt,\n startedAt: currentRun.startedAt,\n status: 'cancelled',\n output: undefined,\n error: undefined,\n completedAt: now,\n updatedAt: now,\n };\n await writeJSON(\n taggedPath(basedir, 'runs', effectiveRunId, tag),\n run,\n { overwrite: true }\n );\n await Promise.all([\n deleteAllHooksForRun(basedir, effectiveRunId),\n deleteAllWaitsForRun(basedir, effectiveRunId),\n ]);\n }\n } else if (\n // Step lifecycle events\n data.eventType === 'step_created' &&\n 'eventData' in data\n ) {\n // step_created: Creates step entity with status 'pending', attempt=0, createdAt set\n const stepData = data.eventData as {\n stepName: string;\n input: any;\n };\n step = {\n runId: effectiveRunId,\n stepId: data.correlationId,\n stepName: stepData.stepName,\n status: 'pending',\n input: stepData.input,\n output: undefined,\n error: undefined,\n attempt: 0,\n startedAt: undefined,\n completedAt: undefined,\n createdAt: now,\n updatedAt: now,\n // Propagate specVersion from the event to the step entity\n specVersion: effectiveSpecVersion,\n };\n const stepCompositeKey = `${effectiveRunId}-${data.correlationId}`;\n await writeJSON(\n taggedPath(basedir, 'steps', stepCompositeKey, tag),\n step\n );\n } else if (data.eventType === 'step_started') {\n // step_started: Increments attempt, sets status to 'running'\n // Sets startedAt only on the first start (not updated on retries)\n // Reuse validatedStep from validation (already read above)\n if (validatedStep) {\n // Check if retryAfter timestamp hasn't been reached yet\n if (\n validatedStep.retryAfter &&\n validatedStep.retryAfter.getTime() > Date.now()\n ) {\n throw new TooEarlyError(\n `Cannot start step \"${data.correlationId}\": retryAfter timestamp has not been reached yet`,\n {\n retryAfter: Math.ceil(\n (validatedStep.retryAfter.getTime() - Date.now()) / 1000\n ),\n }\n );\n }\n\n // Best-effort guard: re-read the step entity to check if it\n // reached terminal state between the validation read and now.\n // This narrows the TOCTOU window but does not fully eliminate it\n // (the local world is single-process / dev-only; the postgres\n // world uses SQL-level atomic guards for production).\n const stepCompositeKey = `${effectiveRunId}-${data.correlationId}`;\n const freshStep = await readJSONWithFallback(\n basedir,\n 'steps',\n stepCompositeKey,\n StepSchema,\n tag\n );\n if (freshStep && isStepTerminal(freshStep.status)) {\n throw new EntityConflictError(\n `Cannot modify step in terminal state \"${freshStep.status}\"`\n );\n }\n\n step = {\n ...validatedStep,\n status: 'running',\n // Only set startedAt on the first start\n startedAt: validatedStep.startedAt ?? now,\n // Increment attempt counter on every start\n attempt: validatedStep.attempt + 1,\n // Clear retryAfter now that the step has started\n retryAfter: undefined,\n updatedAt: now,\n };\n await writeJSON(\n taggedPath(basedir, 'steps', stepCompositeKey, tag),\n step,\n { overwrite: true }\n );\n }\n } else if (data.eventType === 'step_completed' && 'eventData' in data) {\n // step_completed: Terminal state with output\n // Uses writeExclusive on a lock file to atomically prevent concurrent\n // invocations from both completing the same step (TOCTOU race).\n const completedData = data.eventData as { result: any };\n if (validatedStep) {\n const stepCompositeKey = `${effectiveRunId}-${data.correlationId}`;\n const lockName = tag\n ? `${stepCompositeKey}.terminal.${tag}`\n : `${stepCompositeKey}.terminal`;\n const terminalLockPath = resolveWithinBase(\n basedir,\n '.locks',\n 'steps',\n lockName\n );\n const claimed = await writeExclusive(terminalLockPath, '');\n if (!claimed) {\n throw new EntityConflictError(\n 'Cannot modify step in terminal state'\n );\n }\n step = {\n ...validatedStep,\n status: 'completed',\n output: completedData.result,\n completedAt: now,\n updatedAt: now,\n };\n await writeJSON(\n taggedPath(basedir, 'steps', stepCompositeKey, tag),\n step,\n { overwrite: true }\n );\n }\n } else if (data.eventType === 'step_failed' && 'eventData' in data) {\n // step_failed: Terminal state with error\n // Uses writeExclusive on a lock file to atomically prevent concurrent\n // invocations from both failing the same step (TOCTOU race).\n const failedData = data.eventData as {\n error: any;\n stack?: string;\n };\n if (validatedStep) {\n const stepCompositeKey = `${effectiveRunId}-${data.correlationId}`;\n const lockName = tag\n ? `${stepCompositeKey}.terminal.${tag}`\n : `${stepCompositeKey}.terminal`;\n const terminalLockPath = resolveWithinBase(\n basedir,\n '.locks',\n 'steps',\n lockName\n );\n const claimed = await writeExclusive(terminalLockPath, '');\n if (!claimed) {\n throw new EntityConflictError(\n 'Cannot modify step in terminal state'\n );\n }\n const error = {\n message:\n typeof failedData.error === 'string'\n ? failedData.error\n : (failedData.error?.message ?? 'Unknown error'),\n stack: failedData.stack,\n };\n step = {\n ...validatedStep,\n status: 'failed',\n error,\n completedAt: now,\n updatedAt: now,\n };\n await writeJSON(\n taggedPath(basedir, 'steps', stepCompositeKey, tag),\n step,\n { overwrite: true }\n );\n }\n } else if (data.eventType === 'step_retrying' && 'eventData' in data) {\n // step_retrying: Sets status back to 'pending', records error\n // Reuse validatedStep from validation (already read above)\n const retryData = data.eventData as {\n error: any;\n stack?: string;\n retryAfter?: Date;\n };\n if (validatedStep) {\n const stepCompositeKey = `${effectiveRunId}-${data.correlationId}`;\n step = {\n ...validatedStep,\n status: 'pending',\n error: {\n message:\n typeof retryData.error === 'string'\n ? retryData.error\n : (retryData.error?.message ?? 'Unknown error'),\n stack: retryData.stack,\n },\n retryAfter: retryData.retryAfter,\n updatedAt: now,\n };\n await writeJSON(\n taggedPath(basedir, 'steps', stepCompositeKey, tag),\n step,\n { overwrite: true }\n );\n }\n } else if (\n // Hook lifecycle events\n data.eventType === 'hook_created' &&\n 'eventData' in data\n ) {\n const hookData = data.eventData as {\n token: string;\n metadata?: any;\n isWebhook?: boolean;\n };\n\n // Atomically claim the token using an exclusive-create constraint file.\n // This avoids the TOCTOU race of the previous read-all-then-check approach.\n const constraintPath = path.join(\n basedir,\n 'hooks',\n 'tokens',\n `${hashToken(hookData.token)}.json`\n );\n const tokenClaimed = await writeExclusive(\n constraintPath,\n JSON.stringify({\n token: hookData.token,\n hookId: data.correlationId,\n runId: effectiveRunId,\n })\n );\n\n if (!tokenClaimed) {\n // Create hook_conflict event instead of hook_created\n // This allows the workflow to continue and fail gracefully when the hook is awaited\n const conflictEvent: Event = {\n eventType: 'hook_conflict',\n correlationId: data.correlationId,\n eventData: {\n token: hookData.token,\n },\n runId: effectiveRunId,\n eventId,\n createdAt: now,\n specVersion: effectiveSpecVersion,\n };\n\n // Store the conflict event\n const compositeKey = `${effectiveRunId}-${eventId}`;\n await writeJSON(\n taggedPath(basedir, 'events', compositeKey, tag),\n conflictEvent\n );\n\n const resolveData =\n params?.resolveData ?? DEFAULT_RESOLVE_DATA_OPTION;\n const filteredEvent = stripEventDataRefs(conflictEvent, resolveData);\n\n // Return EventResult with conflict event (no hook entity created)\n return {\n event: filteredEvent,\n run,\n step,\n hook: undefined,\n };\n }\n\n hook = {\n runId: effectiveRunId,\n hookId: data.correlationId,\n token: hookData.token,\n metadata: hookData.metadata,\n ownerId: 'local-owner',\n projectId: 'local-project',\n environment: 'local',\n createdAt: now,\n // Propagate specVersion from the event to the hook entity\n specVersion: effectiveSpecVersion,\n isWebhook: hookData.isWebhook ?? false,\n };\n await writeJSON(\n taggedPath(basedir, 'hooks', data.correlationId, tag),\n hook\n );\n } else if (data.eventType === 'hook_disposed') {\n // hook_disposed: Deletes hook entity, rejects duplicates.\n // Uses writeExclusive on a lock file to atomically prevent concurrent\n // invocations from both disposing the same hook (TOCTOU race).\n const hookLockName = tag\n ? `${data.correlationId}.disposed.${tag}`\n : `${data.correlationId}.disposed`;\n const lockPath = resolveWithinBase(\n basedir,\n '.locks',\n 'hooks',\n hookLockName\n );\n const claimed = await writeExclusive(lockPath, '');\n if (!claimed) {\n throw new EntityConflictError(\n `Hook \"${data.correlationId}\" already disposed`\n );\n }\n // Read the hook to get its token before deleting\n const hookPath = taggedPath(basedir, 'hooks', data.correlationId, tag);\n const existingHook = await readJSONWithFallback(\n basedir,\n 'hooks',\n data.correlationId,\n HookSchema,\n tag\n );\n if (existingHook) {\n // Delete the token constraint file to free up the token for reuse\n const disposedConstraintPath = path.join(\n basedir,\n 'hooks',\n 'tokens',\n `${hashToken(existingHook.token)}.json`\n );\n await deleteJSON(disposedConstraintPath);\n }\n await deleteJSON(hookPath);\n } else if (data.eventType === 'wait_created' && 'eventData' in data) {\n // wait_created: Creates wait entity with status 'waiting'\n const waitData = data.eventData as {\n resumeAt?: Date;\n };\n const waitCompositeKey = `${effectiveRunId}-${data.correlationId}`;\n const existingWait = await readJSONWithFallback(\n basedir,\n 'waits',\n waitCompositeKey,\n WaitSchema,\n tag\n );\n if (existingWait) {\n throw new EntityConflictError(\n `Wait \"${data.correlationId}\" already exists`\n );\n }\n wait = {\n waitId: waitCompositeKey,\n runId: effectiveRunId,\n status: 'waiting',\n resumeAt: waitData.resumeAt,\n completedAt: undefined,\n createdAt: now,\n updatedAt: now,\n specVersion: effectiveSpecVersion,\n };\n await writeJSON(\n taggedPath(basedir, 'waits', waitCompositeKey, tag),\n wait\n );\n } else if (data.eventType === 'wait_completed') {\n // wait_completed: Transitions wait to 'completed', rejects duplicates.\n // Uses writeExclusive on a lock file to atomically prevent concurrent\n // invocations from both completing the same wait (TOCTOU race).\n const waitCompositeKey = `${effectiveRunId}-${data.correlationId}`;\n const waitLockName = tag\n ? `${waitCompositeKey}.completed.${tag}`\n : `${waitCompositeKey}.completed`;\n const lockPath = resolveWithinBase(\n basedir,\n '.locks',\n 'waits',\n waitLockName\n );\n const claimed = await writeExclusive(lockPath, '');\n if (!claimed) {\n throw new EntityConflictError(\n `Wait \"${data.correlationId}\" already completed`\n );\n }\n const existingWait = await readJSONWithFallback(\n basedir,\n 'waits',\n waitCompositeKey,\n WaitSchema,\n tag\n );\n if (!existingWait) {\n // Clean up the lock file we just claimed — the wait doesn't exist\n await fs.unlink(lockPath).catch(() => {});\n throw new WorkflowWorldError(\n `Wait \"${data.correlationId}\" not found`\n );\n }\n // The lock file (writeExclusive above) already prevents concurrent\n // completions — no additional status check needed.\n wait = {\n ...existingWait,\n status: 'completed',\n completedAt: now,\n updatedAt: now,\n };\n await writeJSON(\n taggedPath(basedir, 'waits', waitCompositeKey, tag),\n wait,\n { overwrite: true }\n );\n }\n // Note: hook_received events are stored in the event log but don't\n // modify the Hook entity (which doesn't have a payload field)\n\n // Store event using composite key {runId}-{eventId}\n const compositeKey = `${effectiveRunId}-${eventId}`;\n await writeJSON(taggedPath(basedir, 'events', compositeKey, tag), event);\n\n const resolveData = params?.resolveData ?? DEFAULT_RESOLVE_DATA_OPTION;\n const filteredEvent = stripEventDataRefs(event, resolveData);\n\n // For run_started: include all events so the runtime can skip\n // the initial events.list call and reduce TTFB.\n let events: Event[] | undefined;\n let cursor: string | null | undefined;\n let hasMore: boolean | undefined;\n if (data.eventType === 'run_started' && run) {\n const allEvents = await paginatedFileSystemQuery({\n directory: path.join(basedir, 'events'),\n schema: EventSchema,\n filePrefix: `${effectiveRunId}-`,\n sortOrder: 'asc',\n limit: 1000,\n getCreatedAt: getObjectCreatedAt('evnt'),\n getId: (e) => e.eventId,\n });\n events = allEvents.data;\n cursor = allEvents.cursor;\n hasMore = allEvents.hasMore;\n }\n\n // Return EventResult with event and any created/updated entity\n return {\n event: filteredEvent,\n run,\n step,\n hook,\n wait,\n events,\n cursor,\n hasMore,\n };\n },\n\n async get(runId, eventId, params) {\n assertSafeEntityId('runId', runId);\n assertSafeEntityId('eventId', eventId);\n const compositeKey = `${runId}-${eventId}`;\n const event = await readJSONWithFallback(\n basedir,\n 'events',\n compositeKey,\n EventSchema,\n tag\n );\n if (!event) {\n throw new Error(`Event ${eventId} in run ${runId} not found`);\n }\n const resolveData = params?.resolveData ?? DEFAULT_RESOLVE_DATA_OPTION;\n return stripEventDataRefs(event, resolveData);\n },\n\n async list(params) {\n const { runId } = params;\n assertSafeEntityId('runId', runId);\n const resolveData = params.resolveData ?? DEFAULT_RESOLVE_DATA_OPTION;\n const result = await paginatedFileSystemQuery({\n directory: path.join(basedir, 'events'),\n schema: EventSchema,\n filePrefix: `${runId}-`,\n // Events in chronological order (oldest first) by default,\n // different from the default for other list calls.\n sortOrder: params.pagination?.sortOrder ?? 'asc',\n limit: params.pagination?.limit,\n cursor: params.pagination?.cursor,\n getCreatedAt: getObjectCreatedAt('evnt'),\n getId: (event) => event.eventId,\n });\n\n // If resolveData is \"none\", remove eventData from events\n if (resolveData === 'none') {\n return {\n ...result,\n data: result.data.map((event) =>\n stripEventDataRefs(event, resolveData)\n ),\n };\n }\n\n return result;\n },\n\n async listByCorrelationId(params) {\n const correlationId = params.correlationId;\n assertSafeEntityId('correlationId', correlationId);\n const resolveData = params.resolveData ?? DEFAULT_RESOLVE_DATA_OPTION;\n const result = await paginatedFileSystemQuery({\n directory: path.join(basedir, 'events'),\n schema: EventSchema,\n // No filePrefix - search all events\n filter: (event) => event.correlationId === correlationId,\n // Events in chronological order (oldest first) by default,\n // different from the default for other list calls.\n sortOrder: params.pagination?.sortOrder ?? 'asc',\n limit: params.pagination?.limit,\n cursor: params.pagination?.cursor,\n getCreatedAt: getObjectCreatedAt('evnt'),\n getId: (event) => event.eventId,\n });\n\n // If resolveData is \"none\", remove eventData from events\n if (resolveData === 'none') {\n return {\n ...result,\n data: result.data.map((event) =>\n stripEventDataRefs(event, resolveData)\n ),\n };\n }\n\n return result;\n },\n };\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks-storage.d.ts","sourceRoot":"","sources":["../../src/storage/hooks-storage.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAKV,OAAO,EACR,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"hooks-storage.d.ts","sourceRoot":"","sources":["../../src/storage/hooks-storage.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAKV,OAAO,EACR,MAAM,iBAAiB,CAAC;AAczB;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,EACf,GAAG,CAAC,EAAE,MAAM,GACX,OAAO,CAAC,OAAO,CAAC,CAiFlB;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,IAAI,CAAC,CAkBf"}
|