@yolk-sdk/vercel-workflows 0.1.0-canary.73 → 0.1.0-canary.75

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -152,7 +152,13 @@ application outcome; platform `completed` alone does not prove application succe
152
152
  hosts await that child outcome; background hosts return an accepted handle and continue.
153
153
 
154
154
  `awaitWorkflowChild({ read, sleep })` polls short durable read steps with a host-provided Workflow
155
- `sleep` between reads. Do not hold a step open awaiting a long `run.returnValue` poll.
155
+ `sleep` between reads. Both callbacks receive the same zero-based attempt index, so hosts can
156
+ apply capped backoff and end an observation after a bounded number of reads. At that ceiling,
157
+ `read` should return `{ done: true, value: stillRunningObservation }`; this ends polling, not the
158
+ child lifecycle. Preserve an owned handle for eventual result lookup. Existing zero-argument
159
+ callbacks remain supported and the helper has no implicit budget. Hosts must explicitly bound
160
+ long waits to avoid unbounded durable event accumulation. Do not hold a step open awaiting a long
161
+ `run.returnValue` poll.
156
162
 
157
163
  Hosts own immutable logical reservations, admission/CAS, ownership checks, storage, bounded
158
164
  fanout, safe errors, credentials, and cancellation policy. Parent completion/failure must not
@@ -1,15 +1,17 @@
1
1
  //#region src/workflow-children.d.ts
2
2
  /** Workflow orchestration only. Callbacks must be durable steps (sleep must be Workflow sleep).
3
3
  * A read is short-lived; never put a long returnValue poll inside a step.
4
+ * Both callbacks receive a deterministic zero-based attempt for host budgets/backoff.
5
+ * Defaults remain unbounded: hosts end observation at their ceiling by returning done + value.
4
6
  */
5
7
  declare function awaitWorkflowChild<A>(input: {
6
- readonly read: () => Promise<{
8
+ readonly read: (attempt: number) => Promise<{
7
9
  readonly done: false;
8
10
  } | {
9
11
  readonly done: true;
10
12
  readonly value: A;
11
13
  }>;
12
- readonly sleep: () => Promise<void>;
14
+ readonly sleep: (attempt: number) => Promise<void>;
13
15
  }): Promise<A>;
14
16
  /** Preflight fences the entire batch. On rejection, stop dispatching new work, settle already
15
17
  * active siblings, and return their ordered progress alongside failures. Hosts must handle failures.
@@ -1 +1 @@
1
- {"version":3,"file":"workflow-children.d.mts","names":[],"sources":["../src/workflow-children.ts"],"mappings":";;AAGA;;iBAAsB,kBAAA,GAAA,CAAsB,KAAA;EAAA,SACjC,IAAA,QAAY,OAAA;IAAA,SACR,IAAA;EAAA;IAAA,SAA2B,IAAA;IAAA,SAAqB,KAAA,EAAO,CAAA;EAAA;EAAA,SAE3D,KAAA,QAAa,OAAA;AAAA,IACpB,OAAA,CAAQ,CAAA;;;;iBAYU,4BAAA,qBAAA,CAAkD,KAAA;EAAA,SAC7D,KAAA,EAAO,aAAA,CAAc,IAAA;EAAA,SACrB,WAAA;EAAA,SACA,SAAA,QAAiB,OAAA;IAAA,SACb,KAAA;EAAA;IAAA,SAA2B,KAAA;IAAA,SAAuB,KAAA,EAAO,KAAA;EAAA;EAAA,SAE7D,OAAA,GAAU,IAAA,EAAM,IAAA,EAAM,KAAA,aAAkB,OAAA,CAAQ,MAAA;AAAA,IACvD,OAAA;EAAA,SAEW,KAAA;EAAA,SACA,OAAA,EAAS,aAAA,CAAc,MAAA;EAAA,SACvB,QAAA,GAAW,aAAA;IAAA,SAAyB,KAAA;IAAA,SAAwB,KAAA;EAAA;AAAA;EAAA,SAE5D,KAAA;EAAA,SAAuB,KAAA,EAAO,KAAA;AAAA"}
1
+ {"version":3,"file":"workflow-children.d.mts","names":[],"sources":["../src/workflow-children.ts"],"mappings":";;AAKA;;;;iBAAsB,kBAAA,GAAA,CAAsB,KAAA;EAAA,SACjC,IAAA,GACP,OAAA,aACG,OAAA;IAAA,SAAmB,IAAA;EAAA;IAAA,SAA2B,IAAA;IAAA,SAAqB,KAAA,EAAO,CAAA;EAAA;EAAA,SACtE,KAAA,GAAQ,OAAA,aAAoB,OAAA;AAAA,IACnC,OAAA,CAAQ,CAAA;;;;iBAYU,4BAAA,qBAAA,CAAkD,KAAA;EAAA,SAC7D,KAAA,EAAO,aAAA,CAAc,IAAA;EAAA,SACrB,WAAA;EAAA,SACA,SAAA,QAAiB,OAAA;IAAA,SACb,KAAA;EAAA;IAAA,SAA2B,KAAA;IAAA,SAAuB,KAAA,EAAO,KAAA;EAAA;EAAA,SAE7D,OAAA,GAAU,IAAA,EAAM,IAAA,EAAM,KAAA,aAAkB,OAAA,CAAQ,MAAA;AAAA,IACvD,OAAA;EAAA,SAEW,KAAA;EAAA,SACA,OAAA,EAAS,aAAA,CAAc,MAAA;EAAA,SACvB,QAAA,GAAW,aAAA;IAAA,SAAyB,KAAA;IAAA,SAAwB,KAAA;EAAA;AAAA;EAAA,SAE5D,KAAA;EAAA,SAAuB,KAAA,EAAO,KAAA;AAAA"}
@@ -1,13 +1,15 @@
1
1
  //#region src/workflow-children.ts
2
2
  /** Workflow orchestration only. Callbacks must be durable steps (sleep must be Workflow sleep).
3
3
  * A read is short-lived; never put a long returnValue poll inside a step.
4
+ * Both callbacks receive a deterministic zero-based attempt for host budgets/backoff.
5
+ * Defaults remain unbounded: hosts end observation at their ceiling by returning done + value.
4
6
  */
5
7
  async function awaitWorkflowChild(input) {
6
8
  const { read, sleep } = input;
7
- for (;;) {
8
- const state = await read();
9
+ for (let attempt = 0;; attempt++) {
10
+ const state = await read(attempt);
9
11
  if (state.done) return state.value;
10
- await sleep();
12
+ await sleep(attempt);
11
13
  }
12
14
  }
13
15
  /** Preflight fences the entire batch. On rejection, stop dispatching new work, settle already
@@ -1 +1 @@
1
- {"version":3,"file":"workflow-children.mjs","names":[],"sources":["../src/workflow-children.ts"],"sourcesContent":["/** Workflow orchestration only. Callbacks must be durable steps (sleep must be Workflow sleep).\n * A read is short-lived; never put a long returnValue poll inside a step.\n */\nexport async function awaitWorkflowChild<A>(input: {\n readonly read: () => Promise<\n { readonly done: false } | { readonly done: true; readonly value: A }\n >\n readonly sleep: () => Promise<void>\n}): Promise<A> {\n const { read, sleep } = input\n for (;;) {\n const state = await read()\n if (state.done) return state.value\n await sleep()\n }\n}\n\n/** Preflight fences the entire batch. On rejection, stop dispatching new work, settle already\n * active siblings, and return their ordered progress alongside failures. Hosts must handle failures.\n */\nexport async function orchestrateWorkflowToolBatch<Call, Result, Pause>(input: {\n readonly calls: ReadonlyArray<Call>\n readonly concurrency: number\n readonly preflight: () => Promise<\n { readonly ready: true } | { readonly ready: false; readonly value: Pause }\n >\n readonly execute: (call: Call, index: number) => Promise<Result>\n}): Promise<\n | {\n readonly ready: true\n readonly results: ReadonlyArray<Result>\n readonly failures?: ReadonlyArray<{ readonly index: number; readonly error: unknown }>\n }\n | { readonly ready: false; readonly value: Pause }\n> {\n const { calls, concurrency, preflight, execute } = input\n const prepared = await preflight()\n if (!prepared.ready) return prepared\n const width = Number.isFinite(concurrency) ? Math.max(1, Math.floor(concurrency)) : 1\n const entries = calls.map((call, index) => ({ call, index }))\n let next = 0\n const results = new Map<number, Result>()\n const failures: Array<{ readonly index: number; readonly error: unknown }> = []\n await Promise.all(\n Array.from({ length: Math.min(width, calls.length) }, async () => {\n while (failures.length === 0) {\n const entry = entries[next++]\n if (entry === undefined) return\n try {\n results.set(entry.index, await execute(entry.call, entry.index))\n } catch (error) {\n failures.push({ index: entry.index, error })\n }\n }\n })\n )\n return {\n ready: true,\n results: [...results.entries()].sort(([a], [b]) => a - b).map(([, result]) => result),\n ...(failures.length === 0 ? {} : { failures: failures.sort((a, b) => a.index - b.index) })\n }\n}\n"],"mappings":";;;;AAGA,eAAsB,mBAAsB,OAK7B;CACb,MAAM,EAAE,MAAM,UAAU;CACxB,SAAS;EACP,MAAM,QAAQ,MAAM,KAAK;EACzB,IAAI,MAAM,MAAM,OAAO,MAAM;EAC7B,MAAM,MAAM;CACd;AACF;;;;AAKA,eAAsB,6BAAkD,OActE;CACA,MAAM,EAAE,OAAO,aAAa,WAAW,YAAY;CACnD,MAAM,WAAW,MAAM,UAAU;CACjC,IAAI,CAAC,SAAS,OAAO,OAAO;CAC5B,MAAM,QAAQ,OAAO,SAAS,WAAW,IAAI,KAAK,IAAI,GAAG,KAAK,MAAM,WAAW,CAAC,IAAI;CACpF,MAAM,UAAU,MAAM,KAAK,MAAM,WAAW;EAAE;EAAM;CAAM,EAAE;CAC5D,IAAI,OAAO;CACX,MAAM,0BAAU,IAAI,IAAoB;CACxC,MAAM,WAAuE,CAAC;CAC9E,MAAM,QAAQ,IACZ,MAAM,KAAK,EAAE,QAAQ,KAAK,IAAI,OAAO,MAAM,MAAM,EAAE,GAAG,YAAY;EAChE,OAAO,SAAS,WAAW,GAAG;GAC5B,MAAM,QAAQ,QAAQ;GACtB,IAAI,UAAU,KAAA,GAAW;GACzB,IAAI;IACF,QAAQ,IAAI,MAAM,OAAO,MAAM,QAAQ,MAAM,MAAM,MAAM,KAAK,CAAC;GACjE,SAAS,OAAO;IACd,SAAS,KAAK;KAAE,OAAO,MAAM;KAAO;IAAM,CAAC;GAC7C;EACF;CACF,CAAC,CACH;CACA,OAAO;EACL,OAAO;EACP,SAAS,CAAC,GAAG,QAAQ,QAAQ,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,EAAE,KAAK,GAAG,YAAY,MAAM;EACpF,GAAI,SAAS,WAAW,IAAI,CAAC,IAAI,EAAE,UAAU,SAAS,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE;CAC1F;AACF"}
1
+ {"version":3,"file":"workflow-children.mjs","names":[],"sources":["../src/workflow-children.ts"],"sourcesContent":["/** Workflow orchestration only. Callbacks must be durable steps (sleep must be Workflow sleep).\n * A read is short-lived; never put a long returnValue poll inside a step.\n * Both callbacks receive a deterministic zero-based attempt for host budgets/backoff.\n * Defaults remain unbounded: hosts end observation at their ceiling by returning done + value.\n */\nexport async function awaitWorkflowChild<A>(input: {\n readonly read: (\n attempt: number\n ) => Promise<{ readonly done: false } | { readonly done: true; readonly value: A }>\n readonly sleep: (attempt: number) => Promise<void>\n}): Promise<A> {\n const { read, sleep } = input\n for (let attempt = 0; ; attempt++) {\n const state = await read(attempt)\n if (state.done) return state.value\n await sleep(attempt)\n }\n}\n\n/** Preflight fences the entire batch. On rejection, stop dispatching new work, settle already\n * active siblings, and return their ordered progress alongside failures. Hosts must handle failures.\n */\nexport async function orchestrateWorkflowToolBatch<Call, Result, Pause>(input: {\n readonly calls: ReadonlyArray<Call>\n readonly concurrency: number\n readonly preflight: () => Promise<\n { readonly ready: true } | { readonly ready: false; readonly value: Pause }\n >\n readonly execute: (call: Call, index: number) => Promise<Result>\n}): Promise<\n | {\n readonly ready: true\n readonly results: ReadonlyArray<Result>\n readonly failures?: ReadonlyArray<{ readonly index: number; readonly error: unknown }>\n }\n | { readonly ready: false; readonly value: Pause }\n> {\n const { calls, concurrency, preflight, execute } = input\n const prepared = await preflight()\n if (!prepared.ready) return prepared\n const width = Number.isFinite(concurrency) ? Math.max(1, Math.floor(concurrency)) : 1\n const entries = calls.map((call, index) => ({ call, index }))\n let next = 0\n const results = new Map<number, Result>()\n const failures: Array<{ readonly index: number; readonly error: unknown }> = []\n await Promise.all(\n Array.from({ length: Math.min(width, calls.length) }, async () => {\n while (failures.length === 0) {\n const entry = entries[next++]\n if (entry === undefined) return\n try {\n results.set(entry.index, await execute(entry.call, entry.index))\n } catch (error) {\n failures.push({ index: entry.index, error })\n }\n }\n })\n )\n return {\n ready: true,\n results: [...results.entries()].sort(([a], [b]) => a - b).map(([, result]) => result),\n ...(failures.length === 0 ? {} : { failures: failures.sort((a, b) => a.index - b.index) })\n }\n}\n"],"mappings":";;;;;;AAKA,eAAsB,mBAAsB,OAK7B;CACb,MAAM,EAAE,MAAM,UAAU;CACxB,KAAK,IAAI,UAAU,IAAK,WAAW;EACjC,MAAM,QAAQ,MAAM,KAAK,OAAO;EAChC,IAAI,MAAM,MAAM,OAAO,MAAM;EAC7B,MAAM,MAAM,OAAO;CACrB;AACF;;;;AAKA,eAAsB,6BAAkD,OActE;CACA,MAAM,EAAE,OAAO,aAAa,WAAW,YAAY;CACnD,MAAM,WAAW,MAAM,UAAU;CACjC,IAAI,CAAC,SAAS,OAAO,OAAO;CAC5B,MAAM,QAAQ,OAAO,SAAS,WAAW,IAAI,KAAK,IAAI,GAAG,KAAK,MAAM,WAAW,CAAC,IAAI;CACpF,MAAM,UAAU,MAAM,KAAK,MAAM,WAAW;EAAE;EAAM;CAAM,EAAE;CAC5D,IAAI,OAAO;CACX,MAAM,0BAAU,IAAI,IAAoB;CACxC,MAAM,WAAuE,CAAC;CAC9E,MAAM,QAAQ,IACZ,MAAM,KAAK,EAAE,QAAQ,KAAK,IAAI,OAAO,MAAM,MAAM,EAAE,GAAG,YAAY;EAChE,OAAO,SAAS,WAAW,GAAG;GAC5B,MAAM,QAAQ,QAAQ;GACtB,IAAI,UAAU,KAAA,GAAW;GACzB,IAAI;IACF,QAAQ,IAAI,MAAM,OAAO,MAAM,QAAQ,MAAM,MAAM,MAAM,KAAK,CAAC;GACjE,SAAS,OAAO;IACd,SAAS,KAAK;KAAE,OAAO,MAAM;KAAO;IAAM,CAAC;GAC7C;EACF;CACF,CAAC,CACH;CACA,OAAO;EACL,OAAO;EACP,SAAS,CAAC,GAAG,QAAQ,QAAQ,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,EAAE,KAAK,GAAG,YAAY,MAAM;EACpF,GAAI,SAAS,WAAW,IAAI,CAAC,IAAI,EAAE,UAAU,SAAS,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE;CAC1F;AACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yolk-sdk/vercel-workflows",
3
- "version": "0.1.0-canary.73",
3
+ "version": "0.1.0-canary.75",
4
4
  "description": "Vercel Workflow orchestration primitives for Yolk agent loops.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -1,17 +1,19 @@
1
1
  /** Workflow orchestration only. Callbacks must be durable steps (sleep must be Workflow sleep).
2
2
  * A read is short-lived; never put a long returnValue poll inside a step.
3
+ * Both callbacks receive a deterministic zero-based attempt for host budgets/backoff.
4
+ * Defaults remain unbounded: hosts end observation at their ceiling by returning done + value.
3
5
  */
4
6
  export async function awaitWorkflowChild<A>(input: {
5
- readonly read: () => Promise<
6
- { readonly done: false } | { readonly done: true; readonly value: A }
7
- >
8
- readonly sleep: () => Promise<void>
7
+ readonly read: (
8
+ attempt: number
9
+ ) => Promise<{ readonly done: false } | { readonly done: true; readonly value: A }>
10
+ readonly sleep: (attempt: number) => Promise<void>
9
11
  }): Promise<A> {
10
12
  const { read, sleep } = input
11
- for (;;) {
12
- const state = await read()
13
+ for (let attempt = 0; ; attempt++) {
14
+ const state = await read(attempt)
13
15
  if (state.done) return state.value
14
- await sleep()
16
+ await sleep(attempt)
15
17
  }
16
18
  }
17
19