experimental-ash 0.23.0 → 0.24.0

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.
Files changed (74) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/dist/docs/internals/hooks.md +13 -16
  3. package/dist/docs/internals/message-runtime.md +1 -1
  4. package/dist/docs/public/auth-and-route-protection.md +3 -3
  5. package/dist/docs/public/typescript-api.md +2 -2
  6. package/dist/src/channel/types.d.ts +10 -12
  7. package/dist/src/chunks/{dev-authored-source-watcher-d_35Mp8T.js → dev-authored-source-watcher-B4PaZGUr.js} +1 -1
  8. package/dist/src/chunks/host-DsW72Q-w.js +65 -0
  9. package/dist/src/chunks/{paths-YoCQlavu.js → paths-OknjaYR8.js} +24 -24
  10. package/dist/src/chunks/prewarm-B4YblQ5m.js +6 -0
  11. package/dist/src/cli/commands/info.js +1 -1
  12. package/dist/src/cli/run.js +1 -1
  13. package/dist/src/compiled/.vendor-stamp.json +2 -2
  14. package/dist/src/compiled/@workflow/core/classify-error.d.ts +4 -3
  15. package/dist/src/compiled/@workflow/core/encryption.d.ts +7 -1
  16. package/dist/src/compiled/@workflow/core/index.js +2 -2
  17. package/dist/src/compiled/@workflow/core/package.json +1 -1
  18. package/dist/src/compiled/@workflow/core/runtime/constants.d.ts +47 -0
  19. package/dist/src/compiled/@workflow/core/runtime/replay-budget.d.ts +98 -0
  20. package/dist/src/compiled/@workflow/core/runtime.js +27 -27
  21. package/dist/src/compiled/@workflow/core/serialization/types.d.ts +14 -0
  22. package/dist/src/compiled/@workflow/core/serialization.d.ts +8 -0
  23. package/dist/src/compiled/@workflow/core/symbols.d.ts +16 -0
  24. package/dist/src/compiled/@workflow/core/version.d.ts +1 -1
  25. package/dist/src/compiled/@workflow/core/workflow.js +1 -1
  26. package/dist/src/compiled/@workflow/errors/error-codes.d.ts +5 -1
  27. package/dist/src/compiled/@workflow/errors/index.d.ts +15 -1
  28. package/dist/src/compiled/@workflow/errors/index.js +1 -1
  29. package/dist/src/compiled/@workflow/errors/package.json +1 -1
  30. package/dist/src/compiled/_chunks/workflow/{context-errors-zbKocOyk.js → context-errors-Bbvvp-li.js} +2 -2
  31. package/dist/src/compiled/_chunks/workflow/{dist-0iNBqPYp.js → dist-C7wPwOI9.js} +2 -2
  32. package/dist/src/compiled/_chunks/workflow/{dist-D774SUM4.js → dist-C_oiE-l7.js} +1 -1
  33. package/dist/src/compiled/_chunks/workflow/resume-hook-C3VWUPii.js +12 -0
  34. package/dist/src/compiled/_chunks/workflow/sleep-QTkC1VFe.js +1 -0
  35. package/dist/src/compiled/_chunks/workflow/{symbols-D-4tVV8x.js → symbols-QezhMuLg.js} +1 -1
  36. package/dist/src/evals/cli/eval.js +1 -1
  37. package/dist/src/execution/await-authorization-orchestrator.d.ts +2 -1
  38. package/dist/src/execution/await-authorization-orchestrator.js +4 -0
  39. package/dist/src/execution/connection-auth-steps.d.ts +4 -0
  40. package/dist/src/execution/connection-auth-steps.js +9 -11
  41. package/dist/src/execution/node-step.d.ts +4 -5
  42. package/dist/src/execution/subagent-adapter.d.ts +0 -27
  43. package/dist/src/execution/subagent-adapter.js +2 -66
  44. package/dist/src/execution/subagent-hitl-proxy.d.ts +2 -2
  45. package/dist/src/execution/subagent-hitl-proxy.js +2 -2
  46. package/dist/src/execution/task-mode.d.ts +3 -3
  47. package/dist/src/execution/task-mode.js +3 -3
  48. package/dist/src/execution/turn-workflow.d.ts +41 -0
  49. package/dist/src/execution/turn-workflow.js +96 -0
  50. package/dist/src/execution/workflow-entry.js +77 -87
  51. package/dist/src/execution/workflow-errors.d.ts +14 -0
  52. package/dist/src/execution/workflow-errors.js +54 -0
  53. package/dist/src/execution/workflow-runtime.d.ts +34 -3
  54. package/dist/src/execution/workflow-runtime.js +52 -10
  55. package/dist/src/execution/workflow-steps.d.ts +27 -2
  56. package/dist/src/execution/workflow-steps.js +31 -26
  57. package/dist/src/harness/instrumentation-config.js +14 -7
  58. package/dist/src/harness/messages.d.ts +7 -7
  59. package/dist/src/harness/messages.js +4 -4
  60. package/dist/src/harness/runtime-actions.d.ts +4 -4
  61. package/dist/src/internal/application/package.js +1 -1
  62. package/dist/src/internal/workflow-bundle/workflow-builders.d.ts +1 -1
  63. package/dist/src/internal/workflow-bundle/workflow-builders.js +20 -8
  64. package/dist/src/internal/workflow-bundle/workflow-transformer.d.ts +13 -0
  65. package/dist/src/internal/workflow-bundle/workflow-transformer.js +10 -4
  66. package/package.json +4 -4
  67. package/dist/src/chunks/host-tji7W0Nn.js +0 -65
  68. package/dist/src/chunks/prewarm-6duWvvb5.js +0 -6
  69. package/dist/src/compiled/_chunks/workflow/resume-hook-CL8Ed91K.js +0 -12
  70. package/dist/src/compiled/_chunks/workflow/sleep-Dn3i9nxI.js +0 -1
  71. package/dist/src/execution/continuous-entry.d.ts +0 -59
  72. package/dist/src/execution/continuous-entry.js +0 -487
  73. package/dist/src/execution/continuous-runtime.d.ts +0 -17
  74. package/dist/src/execution/continuous-runtime.js +0 -123
@@ -1,2 +1,2 @@
1
- import{D as e,b as t,t as n,v as r,y as i}from"../../chunks/paths-YoCQlavu.js";import{d as a,f as o,h as s}from"../../chunks/types-MZUhN0Zy.js";import{createCliTheme as c,renderCliBanner as l,renderCliSection as u}from"../ui/output.js";async function d(e){let t=await f(e);return{application:n(t?.project.appRoot??e),compiledState:t,messaging:{createSessionRoutePath:o,continueSessionRoutePattern:a,streamRoutePattern:s}}}async function f(n){try{return await i({startPath:n})}catch(n){if(n instanceof r)return n.result;if(n instanceof e||n instanceof t)return null;throw n}}function p(e,t){return`${e} ${t}${e===1?``:`s`}`}function m(e,t){return`${`${e} error${e===1?``:`s`}`}, ${`${t} warning${t===1?``:`s`}`}`}function h(e){switch(e){case`ready`:return`success`;case`failed`:return`danger`;default:return`warning`}}async function g(e,t){let n=await d(t),r=n.compiledState,i=n.application,a=c(),o=[{label:`App Root`,value:i.appRoot}],s=[{label:`Workflow Build`,value:i.workflowBuildDir},{label:`Output`,value:i.outputDir}],f=[];r===null?o.push({label:`Compile`,tone:`warning`,value:`unavailable`}):(o.push({label:`Agent Root`,value:r.project.agentRoot},{label:`Layout`,value:r.project.layout},{label:`Compile`,tone:h(r.metadata.status),value:r.metadata.status},{label:`Diagnostics`,tone:r.metadata.discovery.summary.errors>0?`danger`:r.metadata.discovery.summary.warnings>0?`warning`:`success`,value:m(r.metadata.discovery.summary.errors,r.metadata.discovery.summary.warnings)},{label:`Instructions`,value:r.manifest.instructions?.logicalPath??`none`},{label:`Skills`,value:p(r.manifest.skills.length,`skill`)}),s.unshift({label:`Compiled Manifest`,value:r.paths.compiledManifestPath},{label:`Discovery Manifest`,value:r.paths.discoveryManifestPath},{label:`Diagnostics`,value:r.paths.diagnosticsPath},{label:`Module Map`,value:r.paths.moduleMapPath},{label:`Metadata`,value:r.paths.compileMetadataPath}),f.push(r.manifest.instructions===void 0?{label:`Instructions`,value:`No instructions prompt discovered.`}:{label:`Instructions`,value:r.manifest.instructions.logicalPath})),e.log([l(a,{subtitle:`Resolved application paths and the active message contract.`,title:`Ash Info`}),``,u(a,{rows:o,title:`Application`}),``,u(a,{rows:s,title:`Artifacts`}),...r===null?[]:[``,u(a,{rows:f,title:`Instructions`})],``,u(a,{rows:[{label:`Workflow ID`,value:i.workflowId},{label:`Source Dir`,value:i.workflowSourceDir},{label:`Create`,tone:`info`,value:`POST ${n.messaging.createSessionRoutePath}`},{label:`Continue`,tone:`info`,value:`POST ${n.messaging.continueSessionRoutePattern}`},{label:`Stream`,tone:`info`,value:`GET ${n.messaging.streamRoutePattern}`}],title:`Messaging`})].join(`
1
+ import{O as e,b as t,t as n,x as r,y as i}from"../../chunks/paths-OknjaYR8.js";import{d as a,f as o,h as s}from"../../chunks/types-MZUhN0Zy.js";import{createCliTheme as c,renderCliBanner as l,renderCliSection as u}from"../ui/output.js";async function d(e){let t=await f(e);return{application:n(t?.project.appRoot??e),compiledState:t,messaging:{createSessionRoutePath:o,continueSessionRoutePattern:a,streamRoutePattern:s}}}async function f(n){try{return await t({startPath:n})}catch(t){if(t instanceof i)return t.result;if(t instanceof e||t instanceof r)return null;throw t}}function p(e,t){return`${e} ${t}${e===1?``:`s`}`}function m(e,t){return`${`${e} error${e===1?``:`s`}`}, ${`${t} warning${t===1?``:`s`}`}`}function h(e){switch(e){case`ready`:return`success`;case`failed`:return`danger`;default:return`warning`}}async function g(e,t){let n=await d(t),r=n.compiledState,i=n.application,a=c(),o=[{label:`App Root`,value:i.appRoot}],s=[{label:`Workflow Build`,value:i.workflowBuildDir},{label:`Output`,value:i.outputDir}],f=[];r===null?o.push({label:`Compile`,tone:`warning`,value:`unavailable`}):(o.push({label:`Agent Root`,value:r.project.agentRoot},{label:`Layout`,value:r.project.layout},{label:`Compile`,tone:h(r.metadata.status),value:r.metadata.status},{label:`Diagnostics`,tone:r.metadata.discovery.summary.errors>0?`danger`:r.metadata.discovery.summary.warnings>0?`warning`:`success`,value:m(r.metadata.discovery.summary.errors,r.metadata.discovery.summary.warnings)},{label:`Instructions`,value:r.manifest.instructions?.logicalPath??`none`},{label:`Skills`,value:p(r.manifest.skills.length,`skill`)}),s.unshift({label:`Compiled Manifest`,value:r.paths.compiledManifestPath},{label:`Discovery Manifest`,value:r.paths.discoveryManifestPath},{label:`Diagnostics`,value:r.paths.diagnosticsPath},{label:`Module Map`,value:r.paths.moduleMapPath},{label:`Metadata`,value:r.paths.compileMetadataPath}),f.push(r.manifest.instructions===void 0?{label:`Instructions`,value:`No instructions prompt discovered.`}:{label:`Instructions`,value:r.manifest.instructions.logicalPath})),e.log([l(a,{subtitle:`Resolved application paths and the active message contract.`,title:`Ash Info`}),``,u(a,{rows:o,title:`Application`}),``,u(a,{rows:s,title:`Artifacts`}),...r===null?[]:[``,u(a,{rows:f,title:`Instructions`})],``,u(a,{rows:[{label:`Workflow ID`,value:i.workflowId},{label:`Source Dir`,value:i.workflowSourceDir},{label:`Create`,tone:`info`,value:`POST ${n.messaging.createSessionRoutePath}`},{label:`Continue`,tone:`info`,value:`POST ${n.messaging.continueSessionRoutePattern}`},{label:`Stream`,tone:`info`,value:`GET ${n.messaging.streamRoutePattern}`}],title:`Messaging`})].join(`
2
2
  `))}export{g as printApplicationInfo};
@@ -1,3 +1,3 @@
1
- import{t as e}from"../chunks/package-DmsQgn4v.js";import{createCliTheme as t,renderCliTaggedLine as n}from"./ui/output.js";import{i as r,n as i,r as a,t as o}from"../chunks/url-BVRhVE2O.js";import{resolve as s}from"node:path";async function c(){return(await import(`../chunks/host-tji7W0Nn.js`).then(e=>e.t)).buildHost}async function l(){return(await import(`./commands/info.js`)).printApplicationInfo}async function u(){return(await import(`./dev/repl.js`)).runDevelopmentRepl}async function d(){return(await import(`../evals/cli/eval.js`)).runEvalCommand}async function f(){return(await import(`../chunks/host-tji7W0Nn.js`).then(e=>e.t)).startHost}function p(e=process.cwd()){return s(e)}function m(e){return`Ash (v${e})`}function h(e){return e.name()===`info`||e.name()===`dev`}async function g(e){await new Promise((t,n)=>{let r=!1,i=()=>{process.off(`SIGINT`,a),process.off(`SIGTERM`,a)},a=()=>{r||(r=!0,i(),e.close().then(t,n))};process.once(`SIGINT`,a),process.once(`SIGTERM`,a)})}function _(e){if(!/^-?\d+$/.test(e))throw new r(`Expected a numeric port, received "${e}".`);let t=Number(e);if(!Number.isInteger(t))throw new r(`Expected a numeric port, received "${e}".`);if(t<0||t>65535)throw new r(`Expected a port between 0 and 65535, received "${e}".`);return t}function v(){return!!(process.stdin.isTTY&&process.stdout.isTTY)}function y(e){let t=e[1];return e[0]!==`dev`||e.length!==2||t===void 0||t.startsWith(`-`)?[...e]:[`dev`,`--url`,t]}function b(e){if(e.url){if(e.host!==void 0)throw new r(`The --host option cannot be used with --url.`);if(e.port!==void 0)throw new r(`The --port option cannot be used with --url.`);if(e.repl===!1)throw new r(`The --no-repl option cannot be used with --url.`);return e.url}}function x(r,a){let s=p(),y=e().version,x=new i,S=t();return x.name(`ash`).description(`Build and run an Ash application.`).version(y).showHelpAfterError().exitOverride().hook(`preAction`,(e,t)=>{h(t)&&r.log(m(y))}).configureOutput({writeErr:e=>{r.error(e.trimEnd())},writeOut:e=>{r.log(e.trimEnd())}}),x.command(`build`).description(`Build the current Ash application.`).action(async()=>{let{loadDevelopmentEnvironmentFiles:e}=await import(`./dev/environment.js`);e(s);let t=await(a.buildHost??await c())(s);r.log(n(S,{message:`built output at ${t}`,tag:`build`,tone:`success`}))}),x.command(`dev`).description(`Start the Ash development server or connect the REPL to an existing URL.`).option(`--host <host>`,`Host interface to bind`).option(`--no-repl`,`Start the server without the interactive REPL`).option(`--port <port>`,`Port to listen on (defaults to $PORT, then 3000)`,_).option(`--schedules`,`Run scheduled tasks during development (off by default)`).option(`-u, --url <url>`,`Connect the REPL to an existing server URL`,o).addHelpText(`after`,`
1
+ import{t as e}from"../chunks/package-DmsQgn4v.js";import{createCliTheme as t,renderCliTaggedLine as n}from"./ui/output.js";import{i as r,n as i,r as a,t as o}from"../chunks/url-BVRhVE2O.js";import{resolve as s}from"node:path";async function c(){return(await import(`../chunks/host-DsW72Q-w.js`).then(e=>e.t)).buildHost}async function l(){return(await import(`./commands/info.js`)).printApplicationInfo}async function u(){return(await import(`./dev/repl.js`)).runDevelopmentRepl}async function d(){return(await import(`../evals/cli/eval.js`)).runEvalCommand}async function f(){return(await import(`../chunks/host-DsW72Q-w.js`).then(e=>e.t)).startHost}function p(e=process.cwd()){return s(e)}function m(e){return`Ash (v${e})`}function h(e){return e.name()===`info`||e.name()===`dev`}async function g(e){await new Promise((t,n)=>{let r=!1,i=()=>{process.off(`SIGINT`,a),process.off(`SIGTERM`,a)},a=()=>{r||(r=!0,i(),e.close().then(t,n))};process.once(`SIGINT`,a),process.once(`SIGTERM`,a)})}function _(e){if(!/^-?\d+$/.test(e))throw new r(`Expected a numeric port, received "${e}".`);let t=Number(e);if(!Number.isInteger(t))throw new r(`Expected a numeric port, received "${e}".`);if(t<0||t>65535)throw new r(`Expected a port between 0 and 65535, received "${e}".`);return t}function v(){return!!(process.stdin.isTTY&&process.stdout.isTTY)}function y(e){let t=e[1];return e[0]!==`dev`||e.length!==2||t===void 0||t.startsWith(`-`)?[...e]:[`dev`,`--url`,t]}function b(e){if(e.url){if(e.host!==void 0)throw new r(`The --host option cannot be used with --url.`);if(e.port!==void 0)throw new r(`The --port option cannot be used with --url.`);if(e.repl===!1)throw new r(`The --no-repl option cannot be used with --url.`);return e.url}}function x(r,a){let s=p(),y=e().version,x=new i,S=t();return x.name(`ash`).description(`Build and run an Ash application.`).version(y).showHelpAfterError().exitOverride().hook(`preAction`,(e,t)=>{h(t)&&r.log(m(y))}).configureOutput({writeErr:e=>{r.error(e.trimEnd())},writeOut:e=>{r.log(e.trimEnd())}}),x.command(`build`).description(`Build the current Ash application.`).action(async()=>{let{loadDevelopmentEnvironmentFiles:e}=await import(`./dev/environment.js`);e(s);let t=await(a.buildHost??await c())(s);r.log(n(S,{message:`built output at ${t}`,tag:`build`,tone:`success`}))}),x.command(`dev`).description(`Start the Ash development server or connect the REPL to an existing URL.`).option(`--host <host>`,`Host interface to bind`).option(`--no-repl`,`Start the server without the interactive REPL`).option(`--port <port>`,`Port to listen on (defaults to $PORT, then 3000)`,_).option(`--schedules`,`Run scheduled tasks during development (off by default)`).option(`-u, --url <url>`,`Connect the REPL to an existing server URL`,o).addHelpText(`after`,`
2
2
  You can also pass a bare URL as the only argument, for example: ash dev https://example.com
3
3
  `).action(async e=>{let t=b(e),{loadDevelopmentEnvironmentFiles:i}=await import(`./dev/environment.js`);if(i(s),t){if(r.log(n(S,{message:`REPL connecting to ${t}`,tag:`dev`,tone:`info`})),!v()){r.log(n(S,{message:`Interactive REPL disabled because the current terminal is not a TTY.`,tag:`dev`,tone:`warning`}));return}r.log(``),await(a.runDevelopmentRepl??await u())({serverUrl:t});return}let o=await(a.startHost??await f())(s,{host:e.host,port:e.port,schedules:e.schedules===!0}),c=!1,l=async()=>{c||(c=!0,await o.close())};try{if(r.log(n(S,{message:`server listening at ${o.url}`,tag:`dev`,tone:`success`})),e.repl===!1)return await g({close:l});if(!v())return r.log(n(S,{message:`Interactive REPL disabled because the current terminal is not a TTY.`,tag:`dev`,tone:`warning`})),await g({close:l});r.log(``),await(a.runDevelopmentRepl??await u())({serverUrl:o.url})}finally{await l()}}),x.command(`info`).description(`Print resolved application information.`).action(async()=>{await(a.printApplicationInfo??await l())(r,s)}),x.command(`eval`).description(`Run eval suites against an Ash agent.`).option(`--suite <id...>`,`Suite IDs to run (repeatable)`).option(`--all`,`Run all discovered suites`).option(`--url <url>`,`Remote agent URL (skip local host startup)`).option(`--timeout <ms>`,`Per-case timeout in milliseconds`).option(`--max-concurrency <n>`,`Max concurrent case executions per suite`).option(`--json`,`Output results as JSON`).option(`--list-suites`,`List discovered suites and exit`).option(`--skip-report`,`Skip suite-defined reporters (e.g. Braintrust)`).action(async e=>{await(a.runEvalCommand??await d())(e,r)}),x}async function S(e=process.argv.slice(2),t=console,n={}){let r=x(t,n),i=e.length===0?[`info`]:y(e);try{await r.parseAsync(i,{from:`user`})}catch(e){if(e instanceof a){if(e.exitCode===0)return;throw Error(e.message)}throw e}}export{S as runCli};
@@ -15,8 +15,8 @@
15
15
  "@standard-schema/spec": "1.1.0",
16
16
  "turndown": "7.2.4",
17
17
  "@vercel/sandbox": "2.0.0-beta.14",
18
- "@workflow/core": "5.0.0-beta.5",
19
- "@workflow/errors": "5.0.0-beta.2",
18
+ "@workflow/core": "5.0.0-beta.7",
19
+ "@workflow/errors": "5.0.0-beta.4",
20
20
  "zod": "4.4.3",
21
21
  "zod-validation-error": "5.0.0"
22
22
  },
@@ -1,12 +1,12 @@
1
- import { type RunErrorCode } from '#compiled/@workflow/errors/index.js';
1
+ import { type RunErrorCode, WorkflowWorldError } from '#compiled/@workflow/errors/index.js';
2
2
  /**
3
3
  * Classify an error that caused a workflow run to fail.
4
4
  *
5
5
  * After the structural separation of infrastructure vs user code error
6
6
  * handling, the only errors that reach the `run_failed` try/catch are:
7
7
  * - User code errors (throws from workflow functions, propagated step failures)
8
- * - WorkflowRuntimeError and subclasses (corrupted event log, missing
9
- * timestamps, workflow/step not registered, etc.)
8
+ * - WorkflowRuntimeError and subclasses (missing timestamps, workflow/step
9
+ * not registered, corrupted event log, etc.)
10
10
  *
11
11
  * Uses each subclass's `.is()` static (a name-based duck check) instead of
12
12
  * a single `instanceof` check because workflows execute in a separate
@@ -15,5 +15,6 @@ import { type RunErrorCode } from '#compiled/@workflow/errors/index.js';
15
15
  * thrown inside the workflow VM and we'd misclassify genuine runtime
16
16
  * errors as user errors.
17
17
  */
18
+ export declare function isWorldContractError(err: unknown): err is WorkflowWorldError;
18
19
  export declare function classifyRunError(err: unknown): RunErrorCode;
19
20
  //# sourceMappingURL=classify-error.d.ts.map
@@ -22,10 +22,16 @@ export type CryptoKey = import('node:crypto').webcrypto.CryptoKey;
22
22
  * Callers should call this once per run (after `getEncryptionKeyForRun()`)
23
23
  * and pass the resulting `CryptoKey` to all subsequent encrypt/decrypt calls.
24
24
  *
25
+ * Pass `usages: ['encrypt']` (or `['decrypt']`) for cross-run scenarios
26
+ * where the caller should not be able to perform the inverse operation
27
+ * with the key — for example a child workflow writing into a parent
28
+ * run's forwarded WritableStream only needs to encrypt, never decrypt.
29
+ *
25
30
  * @param raw - Raw 32-byte AES-256 key (from World.getEncryptionKeyForRun)
31
+ * @param usages - Key usages. Defaults to `['encrypt', 'decrypt']`.
26
32
  * @returns CryptoKey ready for AES-GCM operations
27
33
  */
28
- export declare function importKey(raw: Uint8Array): Promise<import("crypto").webcrypto.CryptoKey>;
34
+ export declare function importKey(raw: Uint8Array, usages?: ReadonlyArray<'encrypt' | 'decrypt'>): Promise<import("crypto").webcrypto.CryptoKey>;
29
35
  /**
30
36
  * Encrypt data using AES-256-GCM.
31
37
  *
@@ -1,2 +1,2 @@
1
- import{o as e,r as t}from"../../_chunks/workflow/dist-0iNBqPYp.js";import{i as n,n as r,r as i}from"../../_chunks/workflow/context-errors-zbKocOyk.js";import{Bt as a,Ht as o,L as s,S as c,Vt as l,h as u,n as d,w as f,z as p}from"../../_chunks/workflow/resume-hook-CL8Ed91K.js";import{t as m}from"../../_chunks/workflow/sleep-Dn3i9nxI.js";function h(e){i(`createHook()`,`https://workflow-sdk.dev/docs/api-reference/workflow/create-hook`,h)}function g(e){i(`createWebhook()`,`https://workflow-sdk.dev/docs/api-reference/workflow/create-webhook`,g)}function _({schema:e}={}){function t(e){i(`defineHook().create()`,`https://workflow-sdk.dev/docs/api-reference/workflow/define-hook`,t)}return{create:t,async resume(t,n){if(!e?.[`~standard`])return await d(t,n);let r=e[`~standard`].validate(n);if(r instanceof Promise&&(r=await r),r.issues){let e=r.issues.map(e=>{let t=e.path?.map(e=>String(typeof e==`object`&&e?e.key:e)).join(`.`);return t?` at "${t}": ${e.message}`:` ${e.message}`});throw Error(`Hook payload did not match the defined schema:\n${e.join(`
2
- `)}`)}return await d(t,r.value)}}}function v(){let e=p.getStore();return e||r(`getStepMetadata()`,`https://workflow-sdk.dev/docs/api-reference/workflow/get-step-metadata`,v),e.stepMetadata}function y(){let e=p.getStore();return e||n(`getWorkflowMetadata()`,`https://workflow-sdk.dev/docs/api-reference/workflow/get-workflow-metadata`,y),e.workflowMetadata}function b(e={}){let t=p.getStore();t||n(`getWritable()`,`https://workflow-sdk.dev/docs/api-reference/workflow/get-writable`,b);let{namespace:r}=e,i=t.workflowMetadata.workflowRunId,d=s(i,r),m=f(c(globalThis,t.ops,i,t.encryptionKey),t.encryptionKey),h=new u(i,d),g=a();return t.ops.push(g.promise),l(m.readable,h,g).catch(()=>{}),o(m.writable,g),m.writable}export{t as FatalError,e as RetryableError,h as createHook,g as createWebhook,_ as defineHook,v as getStepMetadata,y as getWorkflowMetadata,b as getWritable,m as sleep};
1
+ import{i as e,s as t}from"../../_chunks/workflow/dist-C7wPwOI9.js";import{i as n,n as r,r as i}from"../../_chunks/workflow/context-errors-Bbvvp-li.js";import{c as a,s as o}from"../../_chunks/workflow/symbols-QezhMuLg.js";import{Bt as s,Ht as c,L as l,S as u,Vt as d,h as f,n as p,w as m,z as h}from"../../_chunks/workflow/resume-hook-C3VWUPii.js";import{t as g}from"../../_chunks/workflow/sleep-QTkC1VFe.js";function _(e){i(`createHook()`,`https://workflow-sdk.dev/docs/api-reference/workflow/create-hook`,_)}function v(e){i(`createWebhook()`,`https://workflow-sdk.dev/docs/api-reference/workflow/create-webhook`,v)}function y({schema:e}={}){function t(e){i(`defineHook().create()`,`https://workflow-sdk.dev/docs/api-reference/workflow/define-hook`,t)}return{create:t,async resume(t,n){if(!e?.[`~standard`])return await p(t,n);let r=e[`~standard`].validate(n);if(r instanceof Promise&&(r=await r),r.issues){let e=r.issues.map(e=>{let t=e.path?.map(e=>String(typeof e==`object`&&e?e.key:e)).join(`.`);return t?` at "${t}": ${e.message}`:` ${e.message}`});throw Error(`Hook payload did not match the defined schema:\n${e.join(`
2
+ `)}`)}return await p(t,r.value)}}}function b(){let e=h.getStore();return e||r(`getStepMetadata()`,`https://workflow-sdk.dev/docs/api-reference/workflow/get-step-metadata`,b),e.stepMetadata}function x(){let e=h.getStore();return e||n(`getWorkflowMetadata()`,`https://workflow-sdk.dev/docs/api-reference/workflow/get-workflow-metadata`,x),e.workflowMetadata}function S(e={}){let t=h.getStore();t||n(`getWritable()`,`https://workflow-sdk.dev/docs/api-reference/workflow/get-writable`,S);let{namespace:r}=e,i=t.workflowMetadata.workflowRunId,p=l(i,r),g=m(u(globalThis,t.ops,i,t.encryptionKey),t.encryptionKey),_=new f(i,p),v=s();return t.ops.push(v.promise),d(g.readable,_,v).catch(()=>{}),c(g.writable,v),Object.defineProperty(g.writable,o,{value:p,writable:!1}),Object.defineProperty(g.writable,a,{value:i,writable:!1}),g.writable}export{e as FatalError,t as RetryableError,_ as createHook,v as createWebhook,y as defineHook,b as getStepMetadata,x as getWorkflowMetadata,S as getWritable,g as sleep};
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "experimental-ash-compiled-workflow-core",
3
- "version": "5.0.0-beta.5",
3
+ "version": "5.0.0-beta.7",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "license": "Apache-2.0"
@@ -1,4 +1,51 @@
1
1
  export declare const MAX_QUEUE_DELIVERIES = 48;
2
+ /**
3
+ * Default maximum time allowed for the *replay* portion of a single workflow
4
+ * handler invocation (in ms). This budget only covers deterministic-replay
5
+ * and workflow-VM execution between step boundaries — inline step bodies
6
+ * (`"use step"` functions invoked via `executeStep`) do NOT count against
7
+ * it. Step bodies are bounded separately by the platform's function
8
+ * `maxDuration` (e.g. 800s on Vercel Pro Fluid) and `NO_INLINE_REPLAY_AFTER_MS`.
9
+ *
10
+ * If the non-step ("replay") time within a single invocation exceeds this
11
+ * budget, the handler exits so the queue can retry. After
12
+ * `REPLAY_TIMEOUT_MAX_RETRIES` exhausted attempts the run is failed with
13
+ * `RUN_ERROR_CODES.REPLAY_TIMEOUT`.
14
+ *
15
+ * Note that on Vercel Hobby (standard functions), the platform `maxDuration`
16
+ * is 60s — well below this budget, so the platform SIGTERM will fire first
17
+ * and the queue will re-deliver until the visibility window expires. With
18
+ * Fluid Compute on Hobby the per-function ceiling rises to 300s, still
19
+ * under the default budget.
20
+ *
21
+ * Override via the `WORKFLOW_REPLAY_TIMEOUT_MS` env var (clamped to
22
+ * `MIN_REPLAY_TIMEOUT_MS`..`MAX_REPLAY_TIMEOUT_MS`).
23
+ */
2
24
  export declare const REPLAY_TIMEOUT_MS = 240000;
25
+ /** Lower bound for the replay-timeout env var override. */
26
+ export declare const MIN_REPLAY_TIMEOUT_MS = 30000;
27
+ /**
28
+ * Upper bound for the replay-timeout env var override. 780s leaves ≥20s of
29
+ * headroom under Vercel Pro Fluid's 800s function ceiling so the handler
30
+ * can write `run_failed` before SIGTERM.
31
+ */
32
+ export declare const MAX_REPLAY_TIMEOUT_MS = 780000;
33
+ /**
34
+ * Resolve the effective replay-timeout budget for the current process.
35
+ *
36
+ * Reads `process.env.WORKFLOW_REPLAY_TIMEOUT_MS` lazily so tests and
37
+ * deployments can override per invocation. Invalid / out-of-range values
38
+ * fall back to a safe value (no throw — the env var is an escape hatch,
39
+ * not a hard requirement) and emit a one-time warning so misconfiguration
40
+ * is observable.
41
+ */
42
+ export declare function getReplayTimeoutMs(): number;
43
+ /**
44
+ * Reset the warn-once cache. Test-only — exported so unit tests can
45
+ * exercise the warn path repeatedly without sharing state.
46
+ *
47
+ * @internal
48
+ */
49
+ export declare function _resetReplayTimeoutWarnCacheForTests(): void;
3
50
  export declare const REPLAY_TIMEOUT_MAX_RETRIES = 3;
4
51
  //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Per-invocation accounting of the *non-step* portion of a workflow
3
+ * handler run: deterministic event-log replay, workflow-VM execution
4
+ * between step boundaries, suspension handling, queue round-trips, etc.
5
+ * Inline step bodies (`"use step"` functions invoked via `executeStep`)
6
+ * are intentionally excluded — they are bounded by the platform's
7
+ * function `maxDuration` and the `NO_INLINE_REPLAY_AFTER_MS` early-return
8
+ * guard.
9
+ *
10
+ * Usage:
11
+ *
12
+ * ```ts
13
+ * const budget = new ReplayBudget();
14
+ * // …non-step work happens here, accumulates against the budget…
15
+ * budget.pause();
16
+ * try {
17
+ * await executeStep(...); // not charged
18
+ * } finally {
19
+ * budget.resume();
20
+ * }
21
+ * // back to charging
22
+ * if (budget.isExhausted()) { ... }
23
+ * ```
24
+ *
25
+ * Implementation notes:
26
+ *
27
+ * - `pause()` and `resume()` are idempotent: calling `pause()` while
28
+ * already paused (or `resume()` while already resumed) is a no-op.
29
+ * This protects against double-counting in future refactors that nest
30
+ * step execution or take an early-return path between a `pause()` and
31
+ * the matching `resume()`.
32
+ * - `isExhausted()` is checked at loop boundaries by the caller — the
33
+ * budget itself does not arm any timers. This means an in-flight
34
+ * pathological `runWorkflow` call (e.g. a huge event-log replay) can
35
+ * overshoot the budget by up to one iteration's worth of work before
36
+ * the next check fires. In practice the 20s headroom built into
37
+ * `MAX_REPLAY_TIMEOUT_MS` (and the function `maxDuration` ceiling)
38
+ * gives us slack; the old `setTimeout`-based approach also ultimately
39
+ * relied on the platform SIGTERM as the hard backstop.
40
+ */
41
+ export declare class ReplayBudget {
42
+ private readonly limitMs;
43
+ private elapsedMs;
44
+ private intervalStart;
45
+ constructor(limitMs?: number);
46
+ /**
47
+ * The configured replay-timeout limit, in ms. Useful for log messages.
48
+ */
49
+ get configuredLimitMs(): number;
50
+ /**
51
+ * Total non-step time accumulated so far, in ms. Includes the
52
+ * currently-active interval if the budget is not paused.
53
+ */
54
+ elapsed(): number;
55
+ /**
56
+ * Stop counting elapsed time toward the budget. Idempotent — safe to
57
+ * call multiple times in a row; subsequent calls are no-ops until
58
+ * `resume()` reopens an interval.
59
+ */
60
+ pause(): void;
61
+ /**
62
+ * Resume counting elapsed time toward the budget. Idempotent — safe to
63
+ * call multiple times in a row; subsequent calls re-anchor the
64
+ * interval start to `now()`, which is fine because no time accrues
65
+ * between back-to-back `resume()` calls.
66
+ */
67
+ resume(): void;
68
+ /**
69
+ * True if the budget has been exhausted (`elapsed() >= limitMs`).
70
+ * Callers should invoke `handleExhausted(...)` afterward and return
71
+ * from the handler.
72
+ */
73
+ isExhausted(): boolean;
74
+ }
75
+ /**
76
+ * Fail the run (or retry, on early attempts) when the replay budget is
77
+ * exhausted. The handling depends on whether the underlying World
78
+ * supports `process.exit(1)` as a queue redelivery signal (see
79
+ * `World.processExitTriggersQueueRedelivery`):
80
+ *
81
+ * - **Managed-platform Worlds** (`world-vercel`): on attempts <=
82
+ * `REPLAY_TIMEOUT_MAX_RETRIES` exit the process so the platform fails
83
+ * the invocation and the queue redelivers; on the next attempt write
84
+ * `run_failed` with `RUN_ERROR_CODES.REPLAY_TIMEOUT` and exit.
85
+ *
86
+ * - **In-process Worlds** (`world-local`, dev servers): calling
87
+ * `process.exit()` would terminate the host (e.g. `pnpm dev`), so
88
+ * instead log a warning, write `run_failed` best-effort, and return.
89
+ * The framework completes the request normally.
90
+ */
91
+ export declare function handleReplayBudgetExhausted(args: {
92
+ runId: string;
93
+ workflowName: string;
94
+ requestId: string | undefined;
95
+ attempt: number;
96
+ limitMs: number;
97
+ }): Promise<void>;
98
+ //# sourceMappingURL=replay-budget.d.ts.map