@autonome-research/thread-phase 3.2.2 → 3.4.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 (86) hide show
  1. package/dist/agent/index.d.ts +1 -1
  2. package/dist/agent/index.d.ts.map +1 -1
  3. package/dist/agent/index.js +1 -1
  4. package/dist/agent/index.js.map +1 -1
  5. package/dist/agent/parse-json.d.ts +16 -0
  6. package/dist/agent/parse-json.d.ts.map +1 -1
  7. package/dist/agent/parse-json.js +82 -11
  8. package/dist/agent/parse-json.js.map +1 -1
  9. package/dist/agent/runner.d.ts.map +1 -1
  10. package/dist/agent/runner.js +16 -12
  11. package/dist/agent/runner.js.map +1 -1
  12. package/dist/agent-runner.d.ts +1 -1
  13. package/dist/agent-runner.d.ts.map +1 -1
  14. package/dist/agent-runner.js +1 -1
  15. package/dist/agent-runner.js.map +1 -1
  16. package/dist/agents/serialize-error.d.ts +10 -1
  17. package/dist/agents/serialize-error.d.ts.map +1 -1
  18. package/dist/agents/serialize-error.js +42 -3
  19. package/dist/agents/serialize-error.js.map +1 -1
  20. package/dist/cache.d.ts +13 -2
  21. package/dist/cache.d.ts.map +1 -1
  22. package/dist/cache.js +36 -6
  23. package/dist/cache.js.map +1 -1
  24. package/dist/helpers/hook.d.ts +34 -2
  25. package/dist/helpers/hook.d.ts.map +1 -1
  26. package/dist/helpers/hook.js +72 -5
  27. package/dist/helpers/hook.js.map +1 -1
  28. package/dist/helpers/index.d.ts +11 -1
  29. package/dist/helpers/index.d.ts.map +1 -1
  30. package/dist/helpers/index.js +11 -1
  31. package/dist/helpers/index.js.map +1 -1
  32. package/dist/index.d.ts +2 -2
  33. package/dist/index.d.ts.map +1 -1
  34. package/dist/index.js +2 -2
  35. package/dist/index.js.map +1 -1
  36. package/dist/internal/error-message.d.ts +20 -0
  37. package/dist/internal/error-message.d.ts.map +1 -0
  38. package/dist/internal/error-message.js +57 -0
  39. package/dist/internal/error-message.js.map +1 -0
  40. package/dist/internal/sleep.d.ts +17 -0
  41. package/dist/internal/sleep.d.ts.map +1 -0
  42. package/dist/internal/sleep.js +51 -0
  43. package/dist/internal/sleep.js.map +1 -0
  44. package/dist/messages.d.ts +11 -1
  45. package/dist/messages.d.ts.map +1 -1
  46. package/dist/orchestrator.d.ts +1 -1
  47. package/dist/orchestrator.d.ts.map +1 -1
  48. package/dist/orchestrator.js +21 -2
  49. package/dist/orchestrator.js.map +1 -1
  50. package/dist/patterns/bounded-fanout-of.d.ts +2 -6
  51. package/dist/patterns/bounded-fanout-of.d.ts.map +1 -1
  52. package/dist/patterns/bounded-fanout-of.js +11 -8
  53. package/dist/patterns/bounded-fanout-of.js.map +1 -1
  54. package/dist/patterns/index.d.ts +22 -0
  55. package/dist/patterns/index.d.ts.map +1 -1
  56. package/dist/patterns/index.js +22 -0
  57. package/dist/patterns/index.js.map +1 -1
  58. package/dist/patterns/parallel-phases.d.ts +7 -2
  59. package/dist/patterns/parallel-phases.d.ts.map +1 -1
  60. package/dist/patterns/parallel-phases.js +70 -16
  61. package/dist/patterns/parallel-phases.js.map +1 -1
  62. package/dist/patterns/sub-pipeline.d.ts.map +1 -1
  63. package/dist/patterns/sub-pipeline.js +10 -6
  64. package/dist/patterns/sub-pipeline.js.map +1 -1
  65. package/dist/patterns/with-retry.d.ts.map +1 -1
  66. package/dist/patterns/with-retry.js +5 -2
  67. package/dist/patterns/with-retry.js.map +1 -1
  68. package/dist/phase.d.ts +3 -0
  69. package/dist/phase.d.ts.map +1 -1
  70. package/dist/phase.js.map +1 -1
  71. package/dist/session/sse.d.ts +5 -1
  72. package/dist/session/sse.d.ts.map +1 -1
  73. package/dist/session/sse.js +56 -16
  74. package/dist/session/sse.js.map +1 -1
  75. package/dist/tools/registry.d.ts +6 -1
  76. package/dist/tools/registry.d.ts.map +1 -1
  77. package/dist/tools/registry.js +2 -2
  78. package/dist/tools/registry.js.map +1 -1
  79. package/dist/triggers/run-trigger.d.ts.map +1 -1
  80. package/dist/triggers/run-trigger.js +4 -1
  81. package/dist/triggers/run-trigger.js.map +1 -1
  82. package/dist/triggers/timer-trigger.d.ts +13 -1
  83. package/dist/triggers/timer-trigger.d.ts.map +1 -1
  84. package/dist/triggers/timer-trigger.js +35 -3
  85. package/dist/triggers/timer-trigger.js.map +1 -1
  86. package/package.json +1 -1
@@ -19,7 +19,7 @@
19
19
  * form is more direct. When you have one item, just call the adapter
20
20
  * directly.
21
21
  *
22
- * @internal — exported via thread-phase/patterns
22
+ * Stable surface — exported via thread-phase/patterns; covered by semver.
23
23
  */
24
24
  /**
25
25
  * Run an adapter over N items with capped concurrency. Returns results in
@@ -27,8 +27,6 @@
27
27
  * error results (finishReason: 'error') and the batch completes. In
28
28
  * `fail-fast` (default), the first failure cancels in-flight runs and
29
29
  * the function rejects with an Error wrapping the failed item.
30
- *
31
- * @internal
32
30
  */
33
31
  export async function boundedFanoutOf(opts) {
34
32
  const items = opts.items;
@@ -40,11 +38,17 @@ export async function boundedFanoutOf(opts) {
40
38
  const inFlight = new Set();
41
39
  let failed = null;
42
40
  let cursor = 0;
43
- const abortAllInFlight = () => {
44
- for (const entry of inFlight) {
41
+ const abortAllInFlight = async () => {
42
+ const snapshot = [...inFlight];
43
+ for (const entry of snapshot) {
45
44
  entry.controller.abort();
46
45
  entry.run.abort('boundedFanoutOf fail-fast');
47
46
  }
47
+ // Wait for every aborted run's `result` to settle so adapter-side cleanup
48
+ // (timers, sockets, subprocesses) finishes before the fanout returns.
49
+ // We allSettled because the runs may reject as `aborted` and we don't
50
+ // want to mask the original failure with the abort-induced one.
51
+ await Promise.allSettled(snapshot.map((e) => e.result));
48
52
  };
49
53
  const worker = async () => {
50
54
  while (true) {
@@ -66,7 +70,7 @@ export async function boundedFanoutOf(opts) {
66
70
  eventBus: opts.eventBus,
67
71
  traceId: opts.traceId,
68
72
  });
69
- const entry = { controller: itemController, run };
73
+ const entry = { controller: itemController, run, result: run.result };
70
74
  inFlight.add(entry);
71
75
  // The adapter's events iterable is intentionally NOT consumed here.
72
76
  // The event bus is the multi-subscriber seam; double-iteration would
@@ -84,7 +88,7 @@ export async function boundedFanoutOf(opts) {
84
88
  if (!failed) {
85
89
  failed = { index: i, result };
86
90
  opts.onItemError?.(item, i, result);
87
- abortAllInFlight();
91
+ await abortAllInFlight();
88
92
  }
89
93
  return;
90
94
  }
@@ -120,7 +124,6 @@ export async function boundedFanoutOf(opts) {
120
124
  }
121
125
  return results;
122
126
  }
123
- /** @internal */
124
127
  export class BoundedFanoutOfError extends Error {
125
128
  itemIndex;
126
129
  result;
@@ -1 +1 @@
1
- {"version":3,"file":"bounded-fanout-of.js","sourceRoot":"","sources":["../../src/patterns/bounded-fanout-of.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"bounded-fanout-of.js","sourceRoot":"","sources":["../../src/patterns/bounded-fanout-of.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,28 @@
1
1
  /**
2
2
  * Reusable phase patterns. Each pattern is a small, opinionated helper that
3
3
  * captures a recurring shape — not a black-box framework. Compose freely.
4
+ *
5
+ * # API convention
6
+ *
7
+ * Patterns in this barrel use ONE of two signature shapes — pick the one
8
+ * that matches what the pattern returns:
9
+ *
10
+ * - Pattern factories: (name: string, options) => Phase<TCtx>
11
+ * parallelPhases, intentGate, match, whileCondition, subPipeline.
12
+ * Use when you return a Phase. The `name` survives into telemetry
13
+ * and event metadata.
14
+ *
15
+ * - Eager runners: (options) => Promise<T>
16
+ * boundedFanout, boundedFanoutOf.
17
+ * Use when the function executes immediately and returns a Promise.
18
+ * No `name` because there's no Phase identity to attach.
19
+ *
20
+ * `withRetry` is a Phase WRAPPER — (innerPhase, options) => Phase<TCtx> —
21
+ * a minor variant of the factory shape that takes the wrapped phase first.
22
+ *
23
+ * Registration helpers (oneShot/schedule/hook in ../helpers) form a third
24
+ * category with their own convention. See AGENTS.md "API conventions —
25
+ * three factory shapes" for the full rationale.
4
26
  */
5
27
  export { parallelPhases } from './parallel-phases.js';
6
28
  export { boundedFanout, type BoundedFanOutOptions, type ItemDoneEvent, type ItemErrorEvent, type FanOutResult, } from './bounded-fanout.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/patterns/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,OAAO,EACL,aAAa,EACb,KAAK,oBAAoB,EACzB,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,YAAY,GAClB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC/E,YAAY,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAE1F,OAAO,EACL,UAAU,EACV,KAAK,oBAAoB,EACzB,KAAK,cAAc,EACnB,KAAK,iBAAiB,GACvB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,cAAc,EACd,KAAK,qBAAqB,GAC3B,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,KAAK,EACL,KAAK,YAAY,GAClB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,SAAS,EACT,KAAK,gBAAgB,GACtB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACL,WAAW,EACX,aAAa,EACb,cAAc,EACd,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,GACvB,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/patterns/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,OAAO,EACL,aAAa,EACb,KAAK,oBAAoB,EACzB,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,YAAY,GAClB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC/E,YAAY,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAE1F,OAAO,EACL,UAAU,EACV,KAAK,oBAAoB,EACzB,KAAK,cAAc,EACnB,KAAK,iBAAiB,GACvB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,cAAc,EACd,KAAK,qBAAqB,GAC3B,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,KAAK,EACL,KAAK,YAAY,GAClB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,SAAS,EACT,KAAK,gBAAgB,GACtB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACL,WAAW,EACX,aAAa,EACb,cAAc,EACd,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,GACvB,MAAM,mBAAmB,CAAC"}
@@ -1,6 +1,28 @@
1
1
  /**
2
2
  * Reusable phase patterns. Each pattern is a small, opinionated helper that
3
3
  * captures a recurring shape — not a black-box framework. Compose freely.
4
+ *
5
+ * # API convention
6
+ *
7
+ * Patterns in this barrel use ONE of two signature shapes — pick the one
8
+ * that matches what the pattern returns:
9
+ *
10
+ * - Pattern factories: (name: string, options) => Phase<TCtx>
11
+ * parallelPhases, intentGate, match, whileCondition, subPipeline.
12
+ * Use when you return a Phase. The `name` survives into telemetry
13
+ * and event metadata.
14
+ *
15
+ * - Eager runners: (options) => Promise<T>
16
+ * boundedFanout, boundedFanoutOf.
17
+ * Use when the function executes immediately and returns a Promise.
18
+ * No `name` because there's no Phase identity to attach.
19
+ *
20
+ * `withRetry` is a Phase WRAPPER — (innerPhase, options) => Phase<TCtx> —
21
+ * a minor variant of the factory shape that takes the wrapped phase first.
22
+ *
23
+ * Registration helpers (oneShot/schedule/hook in ../helpers) form a third
24
+ * category with their own convention. See AGENTS.md "API conventions —
25
+ * three factory shapes" for the full rationale.
4
26
  */
5
27
  export { parallelPhases } from './parallel-phases.js';
6
28
  export { boundedFanout, } from './bounded-fanout.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/patterns/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,OAAO,EACL,aAAa,GAKd,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAG/E,OAAO,EACL,UAAU,GAIX,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,cAAc,GAEf,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,KAAK,GAEN,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,SAAS,GAEV,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACL,WAAW,EACX,aAAa,EACb,cAAc,GAGf,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/patterns/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,OAAO,EACL,aAAa,GAKd,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAG/E,OAAO,EACL,UAAU,GAIX,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,cAAc,GAEf,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,KAAK,GAEN,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,SAAS,GAEV,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACL,WAAW,EACX,aAAa,EACb,cAAc,GAGf,MAAM,mBAAmB,CAAC"}
@@ -12,8 +12,13 @@
12
12
  * same field, last-write-wins. Keep branches' ctx writes disjoint.
13
13
  * - Events from all branches interleave into the composite phase's
14
14
  * output stream in arrival order.
15
- * - If a sub-phase throws, the composite re-throws (after letting other
16
- * branches finish what they're doing no in-flight cancellation).
15
+ * - If a sub-phase throws, sibling branches are cooperatively cancelled
16
+ * via an internal `AbortSignal` composed onto each branch's `ctx.signal`.
17
+ * Siblings still need to OBSERVE their signal to short-circuit awaits —
18
+ * between yields they bail immediately via the queue's error flag.
19
+ * - If the outer `ctx.signal` aborts, every branch's composed signal
20
+ * aborts too. The composite then re-throws the first error encountered
21
+ * (or the outer abort).
17
22
  * - If a sub-phase sets `ctx.stop`, sibling branches still run to
18
23
  * completion. The orchestrator's stop check fires AFTER the composite
19
24
  * phase returns, halting subsequent top-level phases.
@@ -1 +1 @@
1
- {"version":3,"file":"parallel-phases.d.ts","sourceRoot":"","sources":["../../src/patterns/parallel-phases.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE7E,wBAAgB,cAAc,CAC5B,IAAI,SAAS,mBAAmB,EAChC,MAAM,GAAG,aAAa,EAEtB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,aAAa,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,GACzC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAkDrB"}
1
+ {"version":3,"file":"parallel-phases.d.ts","sourceRoot":"","sources":["../../src/patterns/parallel-phases.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE7E,wBAAgB,cAAc,CAC5B,IAAI,SAAS,mBAAmB,EAChC,MAAM,GAAG,aAAa,EAEtB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,aAAa,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,GACzC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAiFrB"}
@@ -12,8 +12,13 @@
12
12
  * same field, last-write-wins. Keep branches' ctx writes disjoint.
13
13
  * - Events from all branches interleave into the composite phase's
14
14
  * output stream in arrival order.
15
- * - If a sub-phase throws, the composite re-throws (after letting other
16
- * branches finish what they're doing no in-flight cancellation).
15
+ * - If a sub-phase throws, sibling branches are cooperatively cancelled
16
+ * via an internal `AbortSignal` composed onto each branch's `ctx.signal`.
17
+ * Siblings still need to OBSERVE their signal to short-circuit awaits —
18
+ * between yields they bail immediately via the queue's error flag.
19
+ * - If the outer `ctx.signal` aborts, every branch's composed signal
20
+ * aborts too. The composite then re-throws the first error encountered
21
+ * (or the outer abort).
17
22
  * - If a sub-phase sets `ctx.stop`, sibling branches still run to
18
23
  * completion. The orchestrator's stop check fires AFTER the composite
19
24
  * phase returns, halting subsequent top-level phases.
@@ -28,6 +33,22 @@ export function parallelPhases(phaseName, phases) {
28
33
  async *run(ctx) {
29
34
  if (phases.length === 0)
30
35
  return;
36
+ // Internal controller fans cancellation across branches. When one
37
+ // branch throws (or the outer ctx.signal aborts), every other branch
38
+ // sees its composed ctx.signal flip to aborted — they can observe it
39
+ // in their inner await loops to bail cooperatively.
40
+ const internal = new AbortController();
41
+ const outerSignal = ctx.signal;
42
+ const composedSignal = outerSignal
43
+ ? AbortSignal.any([outerSignal, internal.signal])
44
+ : internal.signal;
45
+ const onOuterAbort = () => internal.abort(outerSignal.reason);
46
+ if (outerSignal && !outerSignal.aborted) {
47
+ outerSignal.addEventListener('abort', onOuterAbort, { once: true });
48
+ }
49
+ else if (outerSignal?.aborted) {
50
+ internal.abort(outerSignal.reason);
51
+ }
31
52
  // Producer/consumer: each sub-phase pushes events into a shared queue;
32
53
  // the composite generator drains the queue and yields downstream.
33
54
  const queue = [];
@@ -41,17 +62,26 @@ export function parallelPhases(phaseName, phases) {
41
62
  let errored = null;
42
63
  let running = phases.length;
43
64
  const drain = async (phase) => {
65
+ // Each branch sees the composed signal, not the outer's directly,
66
+ // so sibling errors propagate as cancellation through ctx.signal.
67
+ const branchCtx = withSignal(ctx, composedSignal);
44
68
  try {
45
- for await (const ev of phase.run(ctx)) {
69
+ for await (const ev of phase.run(branchCtx)) {
46
70
  queue.push(ev);
47
71
  wake();
48
- if (errored)
49
- return;
72
+ // Do not short-circuit on `errored` — that would close the
73
+ // branch's generator before it had a chance to observe
74
+ // composedSignal cooperatively. Branches that check c.signal
75
+ // bail themselves; branches that don't run to completion (the
76
+ // documented cooperative-cancellation contract).
50
77
  }
51
78
  }
52
79
  catch (err) {
53
- if (!errored)
80
+ if (!errored) {
54
81
  errored = err;
82
+ // First error fires the internal abort so siblings cancel too.
83
+ internal.abort(err);
84
+ }
55
85
  }
56
86
  finally {
57
87
  running--;
@@ -59,19 +89,43 @@ export function parallelPhases(phaseName, phases) {
59
89
  }
60
90
  };
61
91
  const allDone = Promise.all(phases.map(drain));
62
- while (running > 0 || queue.length > 0) {
63
- if (errored && queue.length === 0)
64
- break;
65
- if (queue.length === 0) {
66
- await Promise.race([wait(), allDone]);
67
- continue;
92
+ try {
93
+ while (running > 0 || queue.length > 0) {
94
+ if (queue.length === 0) {
95
+ await Promise.race([wait(), allDone]);
96
+ continue;
97
+ }
98
+ yield queue.shift();
68
99
  }
69
- yield queue.shift();
100
+ await allDone;
101
+ if (errored)
102
+ throw errored;
103
+ }
104
+ finally {
105
+ if (outerSignal)
106
+ outerSignal.removeEventListener('abort', onOuterAbort);
70
107
  }
71
- await allDone;
72
- if (errored)
73
- throw errored;
74
108
  },
75
109
  };
76
110
  }
111
+ /**
112
+ * Build a per-branch ctx view whose `signal` is the composed signal.
113
+ * Other fields share the parent ctx (last-write-wins semantics preserved).
114
+ */
115
+ function withSignal(ctx, signal) {
116
+ // A Proxy keeps writes to ctx visible across all branches (the documented
117
+ // last-write-wins model) while masking `signal` to the composed value.
118
+ return new Proxy(ctx, {
119
+ get(target, prop, receiver) {
120
+ if (prop === 'signal')
121
+ return signal;
122
+ return Reflect.get(target, prop, receiver);
123
+ },
124
+ set(target, prop, value, receiver) {
125
+ if (prop === 'signal')
126
+ return true; // ignore writes to branch-local signal
127
+ return Reflect.set(target, prop, value, receiver);
128
+ },
129
+ });
130
+ }
77
131
  //# sourceMappingURL=parallel-phases.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"parallel-phases.js","sourceRoot":"","sources":["../../src/patterns/parallel-phases.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAIH,MAAM,UAAU,cAAc,CAI5B,SAAiB,EACjB,MAA0C;IAE1C,OAAO;QACL,IAAI,EAAE,SAAS;QACf,KAAK,CAAC,CAAC,GAAG,CAAC,GAAG;YACZ,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO;YAEhC,uEAAuE;YACvE,kEAAkE;YAClE,MAAM,KAAK,GAAa,EAAE,CAAC;YAC3B,IAAI,aAAa,GAAwB,IAAI,CAAC;YAC9C,MAAM,IAAI,GAAG,GAAG,EAAE;gBAChB,MAAM,EAAE,GAAG,aAAa,CAAC;gBACzB,aAAa,GAAG,IAAI,CAAC;gBACrB,EAAE,EAAE,EAAE,CAAC;YACT,CAAC,CAAC;YACF,MAAM,IAAI,GAAG,GAAG,EAAE,CAAC,IAAI,OAAO,CAAO,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,aAAa,GAAG,CAAC,CAAC,CAAC,CAAC;YAEjE,IAAI,OAAO,GAAY,IAAI,CAAC;YAC5B,IAAI,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC;YAE5B,MAAM,KAAK,GAAG,KAAK,EAAE,KAA0B,EAAiB,EAAE;gBAChE,IAAI,CAAC;oBACH,IAAI,KAAK,EAAE,MAAM,EAAE,IAAI,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;wBACtC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;wBACf,IAAI,EAAE,CAAC;wBACP,IAAI,OAAO;4BAAE,OAAO;oBACtB,CAAC;gBACH,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,IAAI,CAAC,OAAO;wBAAE,OAAO,GAAG,GAAG,CAAC;gBAC9B,CAAC;wBAAS,CAAC;oBACT,OAAO,EAAE,CAAC;oBACV,IAAI,EAAE,CAAC;gBACT,CAAC;YACH,CAAC,CAAC;YAEF,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;YAE/C,OAAO,OAAO,GAAG,CAAC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACvC,IAAI,OAAO,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;oBAAE,MAAM;gBACzC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBACvB,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC;oBACtC,SAAS;gBACX,CAAC;gBACD,MAAM,KAAK,CAAC,KAAK,EAAG,CAAC;YACvB,CAAC;YAED,MAAM,OAAO,CAAC;YACd,IAAI,OAAO;gBAAE,MAAM,OAAO,CAAC;QAC7B,CAAC;KACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"parallel-phases.js","sourceRoot":"","sources":["../../src/patterns/parallel-phases.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"sub-pipeline.d.ts","sourceRoot":"","sources":["../../src/patterns/sub-pipeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAGH,OAAO,KAAK,EACV,mBAAmB,EACnB,KAAK,EAEN,MAAM,aAAa,CAAC;AAGrB;;;;;GAKG;AACH,MAAM,MAAM,iBAAiB,CAAC,SAAS,SAAS,mBAAmB,IAC/D;IAAE,MAAM,EAAE,aAAa,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC;IAAC,GAAG,EAAE,SAAS,CAAA;CAAE,GAC3D,CAAC,MAAM;IAAE,MAAM,EAAE,aAAa,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC;IAAC,GAAG,EAAE,SAAS,CAAA;CAAE,GAAG,SAAS,CAAC,CAAC;AAEpF,MAAM,WAAW,kBAAkB,CACjC,SAAS,SAAS,mBAAmB,EACrC,SAAS,SAAS,mBAAmB;IAErC,6DAA6D;IAC7D,QAAQ,EAAE,iBAAiB,CAAC,SAAS,CAAC,CAAC;IACvC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,SAAS,CAAC;IAC3C;;;OAGG;IACH,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;CAC1D;AAED,6DAA6D;AAC7D,wBAAgB,WAAW,CACzB,SAAS,SAAS,mBAAmB,EACrC,SAAS,SAAS,mBAAmB,EAErC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,kBAAkB,CAAC,SAAS,EAAE,SAAS,CAAC,GAChD,KAAK,CAAC,SAAS,CAAC,CA8BlB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAC3B,SAAS,SAAS,mBAAmB,EACrC,SAAS,SAAS,mBAAmB,GAAG,mBAAmB,EAE3D,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE;IAAE,MAAM,EAAE,aAAa,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC;IAAC,GAAG,EAAE,SAAS,CAAA;CAAE,EACnE,OAAO,CAAC,EAAE,IAAI,CAAC,kBAAkB,CAAC,SAAS,EAAE,SAAS,CAAC,EAAE,UAAU,CAAC,GACnE,KAAK,CAAC,SAAS,CAAC,CAKlB;AAED;;;;GAIG;AACH,wBAAsB,cAAc,CAClC,SAAS,SAAS,mBAAmB,EAErC,MAAM,EAAE,iBAAiB,CAAC,SAAS,CAAC,EACpC,OAAO,GAAE;IACP,wEAAwE;IACxE,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,2EAA2E;IAC3E,GAAG,CAAC,EAAE,SAAS,CAAC;CACZ,GACL,OAAO,CAAC;IAAE,GAAG,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE;QAAE,MAAM,EAAE,WAAW,GAAG,SAAS,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAAC,CA4BhH"}
1
+ {"version":3,"file":"sub-pipeline.d.ts","sourceRoot":"","sources":["../../src/patterns/sub-pipeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAGH,OAAO,KAAK,EACV,mBAAmB,EACnB,KAAK,EAEN,MAAM,aAAa,CAAC;AAGrB;;;;;GAKG;AACH,MAAM,MAAM,iBAAiB,CAAC,SAAS,SAAS,mBAAmB,IAC/D;IAAE,MAAM,EAAE,aAAa,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC;IAAC,GAAG,EAAE,SAAS,CAAA;CAAE,GAC3D,CAAC,MAAM;IAAE,MAAM,EAAE,aAAa,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC;IAAC,GAAG,EAAE,SAAS,CAAA;CAAE,GAAG,SAAS,CAAC,CAAC;AAEpF,MAAM,WAAW,kBAAkB,CACjC,SAAS,SAAS,mBAAmB,EACrC,SAAS,SAAS,mBAAmB;IAErC,6DAA6D;IAC7D,QAAQ,EAAE,iBAAiB,CAAC,SAAS,CAAC,CAAC;IACvC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,SAAS,CAAC;IAC3C;;;OAGG;IACH,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;CAC1D;AAED,6DAA6D;AAC7D,wBAAgB,WAAW,CACzB,SAAS,SAAS,mBAAmB,EACrC,SAAS,SAAS,mBAAmB,EAErC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,kBAAkB,CAAC,SAAS,EAAE,SAAS,CAAC,GAChD,KAAK,CAAC,SAAS,CAAC,CA+BlB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAC3B,SAAS,SAAS,mBAAmB,EACrC,SAAS,SAAS,mBAAmB,GAAG,mBAAmB,EAE3D,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE;IAAE,MAAM,EAAE,aAAa,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC;IAAC,GAAG,EAAE,SAAS,CAAA;CAAE,EACnE,OAAO,CAAC,EAAE,IAAI,CAAC,kBAAkB,CAAC,SAAS,EAAE,SAAS,CAAC,EAAE,UAAU,CAAC,GACnE,KAAK,CAAC,SAAS,CAAC,CAKlB;AAED;;;;GAIG;AACH,wBAAsB,cAAc,CAClC,SAAS,SAAS,mBAAmB,EAErC,MAAM,EAAE,iBAAiB,CAAC,SAAS,CAAC,EACpC,OAAO,GAAE;IACP,wEAAwE;IACxE,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,2EAA2E;IAC3E,GAAG,CAAC,EAAE,SAAS,CAAC;CACZ,GACL,OAAO,CAAC;IAAE,GAAG,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE;QAAE,MAAM,EAAE,WAAW,GAAG,SAAS,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAAC,CA6BhH"}
@@ -33,10 +33,14 @@ export function subPipeline(name, options) {
33
33
  const inner = options.mapInput
34
34
  ? options.mapInput(outer)
35
35
  : source.ctx;
36
- // Isolate the inner pipeline's cache; propagate the outer's signal.
36
+ // Isolate the inner pipeline's cache so writes can't bleed across
37
+ // nesting levels. Signal propagation is via runPipeline's options —
38
+ // the orchestrator assigns ctx.signal canonically, which avoids the
39
+ // pre-set-then-overwritten footgun at arbitrary depth.
37
40
  inner.cache = new PipelineCache();
38
- inner.signal = outer.signal;
39
- yield* runPipeline(source.phases, inner);
41
+ yield* runPipeline(source.phases, inner, {
42
+ signal: outer.signal,
43
+ });
40
44
  options.mapOutput?.(outer, inner);
41
45
  },
42
46
  };
@@ -70,11 +74,11 @@ export async function runSubPipeline(source, options = {}) {
70
74
  }
71
75
  const inner = options.ctx ?? resolved.ctx;
72
76
  inner.cache = new PipelineCache();
73
- if (options.signal)
74
- inner.signal = options.signal;
75
77
  let eventCount = 0;
76
78
  let stopReason;
77
- for await (const event of runPipeline(resolved.phases, inner)) {
79
+ for await (const event of runPipeline(resolved.phases, inner, {
80
+ signal: options.signal,
81
+ })) {
78
82
  eventCount++;
79
83
  if (event.type === 'done') {
80
84
  stopReason = event.reason;
@@ -1 +1 @@
1
- {"version":3,"file":"sub-pipeline.js","sourceRoot":"","sources":["../../src/patterns/sub-pipeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAMjD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AA+B5C,6DAA6D;AAC7D,MAAM,UAAU,WAAW,CAIzB,IAAY,EACZ,OAAiD;IAEjD,OAAO;QACL,IAAI;QACJ,KAAK,CAAC,CAAC,GAAG,CAAC,KAAK;YACd,MAAM,MAAM,GACV,OAAO,OAAO,CAAC,QAAQ,KAAK,UAAU;gBACpC,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE;gBACpB,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC;YACvB,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,MAAM,IAAI,KAAK,CACb,gBAAgB,IAAI,yCAAyC,CAC9D,CAAC;YACJ,CAAC;YAED,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ;gBAC5B,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC;gBACzB,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;YAEf,oEAAoE;YACnE,KAAkC,CAAC,KAAK,GAAG,IAAI,aAAa,EAAE,CAAC;YAChE,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;YAE5B,KAAK,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAGtC,CAAC;YAEF,OAAO,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QACpC,CAAC;KACF,CAAC;AACJ,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,aAAa,CAI3B,IAAY,EACZ,MAAmE,EACnE,OAAoE;IAEpE,OAAO,WAAW,CAAuB,IAAI,EAAE;QAC7C,QAAQ,EAAE,MAAM;QAChB,GAAG,OAAO;KACX,CAAC,CAAC;AACL,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAGlC,MAAoC,EACpC,UAKI,EAAE;IAEN,MAAM,QAAQ,GACZ,OAAO,MAAM,KAAK,UAAU,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;IACnD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;IAC1E,CAAC;IAED,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,IAAI,QAAQ,CAAC,GAAG,CAAC;IACzC,KAAkC,CAAC,KAAK,GAAG,IAAI,aAAa,EAAE,CAAC;IAChE,IAAI,OAAO,CAAC,MAAM;QAAE,KAAK,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAElD,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,IAAI,UAA8B,CAAC;IAEnC,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,WAAW,CAAC,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC;QAC9D,UAAU,EAAE,CAAC;QACb,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YAC1B,UAAU,GAAI,KAA6B,CAAC,MAAM,CAAC;QACrD,CAAC;IACH,CAAC;IAED,OAAO;QACL,GAAG,EAAE,KAAK;QACV,OAAO,EACL,UAAU,KAAK,SAAS;YACtB,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE;YACvD,CAAC,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE;KAC1C,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"sub-pipeline.js","sourceRoot":"","sources":["../../src/patterns/sub-pipeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAMjD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AA+B5C,6DAA6D;AAC7D,MAAM,UAAU,WAAW,CAIzB,IAAY,EACZ,OAAiD;IAEjD,OAAO;QACL,IAAI;QACJ,KAAK,CAAC,CAAC,GAAG,CAAC,KAAK;YACd,MAAM,MAAM,GACV,OAAO,OAAO,CAAC,QAAQ,KAAK,UAAU;gBACpC,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE;gBACpB,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC;YACvB,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,MAAM,IAAI,KAAK,CACb,gBAAgB,IAAI,yCAAyC,CAC9D,CAAC;YACJ,CAAC;YAED,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ;gBAC5B,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC;gBACzB,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;YAEf,kEAAkE;YAClE,oEAAoE;YACpE,oEAAoE;YACpE,uDAAuD;YACtD,KAAkC,CAAC,KAAK,GAAG,IAAI,aAAa,EAAE,CAAC;YAEhE,KAAK,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,EAAE;gBACvC,MAAM,EAAE,KAAK,CAAC,MAAM;aACrB,CAAwC,CAAC;YAE1C,OAAO,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QACpC,CAAC;KACF,CAAC;AACJ,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,aAAa,CAI3B,IAAY,EACZ,MAAmE,EACnE,OAAoE;IAEpE,OAAO,WAAW,CAAuB,IAAI,EAAE;QAC7C,QAAQ,EAAE,MAAM;QAChB,GAAG,OAAO;KACX,CAAC,CAAC;AACL,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAGlC,MAAoC,EACpC,UAKI,EAAE;IAEN,MAAM,QAAQ,GACZ,OAAO,MAAM,KAAK,UAAU,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;IACnD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;IAC1E,CAAC;IAED,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,IAAI,QAAQ,CAAC,GAAG,CAAC;IACzC,KAAkC,CAAC,KAAK,GAAG,IAAI,aAAa,EAAE,CAAC;IAEhE,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,IAAI,UAA8B,CAAC;IAEnC,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,WAAW,CAAC,QAAQ,CAAC,MAAM,EAAE,KAAK,EAAE;QAC5D,MAAM,EAAE,OAAO,CAAC,MAAM;KACvB,CAAC,EAAE,CAAC;QACH,UAAU,EAAE,CAAC;QACb,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YAC1B,UAAU,GAAI,KAA6B,CAAC,MAAM,CAAC;QACrD,CAAC;IACH,CAAC;IAED,OAAO;QACL,GAAG,EAAE,KAAK;QACV,OAAO,EACL,UAAU,KAAK,SAAS;YACtB,CAAC,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE;YACvD,CAAC,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE;KAC1C,CAAC;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"with-retry.d.ts","sourceRoot":"","sources":["../../src/patterns/with-retry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,KAAK,EAAiB,MAAM,aAAa,CAAC;AAE7E,MAAM,WAAW,gBAAgB,CAAC,IAAI,SAAS,mBAAmB;IAChE,8DAA8D;IAC9D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0EAA0E;IAC1E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mHAAmH;IACnH,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,KAAK,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC;IACpD,+DAA+D;IAC/D,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IAChE,sFAAsF;IACtF,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,IAAI,KAAK,IAAI,CAAC;CAClC;AAID,wBAAgB,SAAS,CAAC,IAAI,SAAS,mBAAmB,EACxD,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,EAClB,OAAO,GAAE,gBAAgB,CAAC,IAAI,CAAM,GACnC,KAAK,CAAC,IAAI,CAAC,CAwDb"}
1
+ {"version":3,"file":"with-retry.d.ts","sourceRoot":"","sources":["../../src/patterns/with-retry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,KAAK,EAAiB,MAAM,aAAa,CAAC;AAG7E,MAAM,WAAW,gBAAgB,CAAC,IAAI,SAAS,mBAAmB;IAChE,8DAA8D;IAC9D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0EAA0E;IAC1E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mHAAmH;IACnH,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,KAAK,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC;IACpD,+DAA+D;IAC/D,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IAChE,sFAAsF;IACtF,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,IAAI,KAAK,IAAI,CAAC;CAClC;AAED,wBAAgB,SAAS,CAAC,IAAI,SAAS,mBAAmB,EACxD,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,EAClB,OAAO,GAAE,gBAAgB,CAAC,IAAI,CAAM,GACnC,KAAK,CAAC,IAAI,CAAC,CA2Db"}
@@ -20,7 +20,7 @@
20
20
  * Events emitted by the inner phase pass through unmodified. The wrapper
21
21
  * additionally emits `data` events with key `${phase.name}.attempt`.
22
22
  */
23
- const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
23
+ import { abortableSleep } from '../internal/sleep.js';
24
24
  export function withRetry(phase, options = {}) {
25
25
  const maxAttempts = options.maxAttempts ?? 3;
26
26
  const baseDelay = options.baseDelayMs ?? 1000;
@@ -65,7 +65,10 @@ export function withRetry(phase, options = {}) {
65
65
  ctx.stop = stopBefore; // restore upstream stop, if any
66
66
  options.resetState?.(ctx);
67
67
  const delay = baseDelay * 2 ** (attempt - 1);
68
- await sleep(delay);
68
+ // ctx.signal is wired by runPipeline; if the caller aborts during a
69
+ // backoff window, surface it immediately instead of waiting out the
70
+ // schedule. AbortError propagates up through runPipeline.
71
+ await abortableSleep(delay, ctx.signal);
69
72
  }
70
73
  },
71
74
  };
@@ -1 +1 @@
1
- {"version":3,"file":"with-retry.js","sourceRoot":"","sources":["../../src/patterns/with-retry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAiBH,MAAM,KAAK,GAAG,CAAC,EAAU,EAAE,EAAE,CAAC,IAAI,OAAO,CAAO,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;AAE1E,MAAM,UAAU,SAAS,CACvB,KAAkB,EAClB,UAAkC,EAAE;IAEpC,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,CAAC,CAAC;IAC7C,MAAM,SAAS,GAAG,OAAO,CAAC,WAAW,IAAI,IAAI,CAAC;IAC9C,MAAM,SAAS,GACb,OAAO,CAAC,SAAS,IAAI,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,SAAS,IAAI,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC;IAEvF,OAAO;QACL,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,KAAK,CAAC,CAAC,GAAG,CAAC,GAAG;YACZ,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,WAAW,EAAE,OAAO,EAAE,EAAE,CAAC;gBACxD,MAAM;oBACJ,IAAI,EAAE,MAAM;oBACZ,GAAG,EAAE,GAAG,KAAK,CAAC,IAAI,UAAU;oBAC5B,KAAK,EAAE,EAAE,OAAO,EAAE,WAAW,EAAE;iBAChC,CAAC;gBAEF,MAAM,UAAU,GAAG,GAAG,CAAC,IAAI,CAAC;gBAC5B,IAAI,MAAM,GAAY,SAAS,CAAC;gBAEhC,IAAI,CAAC;oBACH,kEAAkE;oBAClE,mEAAmE;oBACnE,oBAAoB;oBACpB,GAAG,CAAC,IAAI,GAAG,SAAS,CAAC;oBACrB,KAAK,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;gBACxB,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,MAAM,GAAG,GAAG,CAAC;gBACf,CAAC;gBAED,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;gBAEtC,IAAI,CAAC,MAAM,EAAE,CAAC;oBACZ,iEAAiE;oBACjE,gEAAgE;oBAChE,mCAAmC;oBACnC,OAAO;gBACT,CAAC;gBAED,IAAI,OAAO,KAAK,WAAW,EAAE,CAAC;oBAC5B,+DAA+D;oBAC/D,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;wBACzB,MAAM,MAAM,CAAC;oBACf,CAAC;oBACD,wDAAwD;oBACxD,OAAO;gBACT,CAAC;gBAED,OAAO,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;gBACxC,GAAG,CAAC,IAAI,GAAG,UAAU,CAAC,CAAC,gCAAgC;gBACvD,OAAO,CAAC,UAAU,EAAE,CAAC,GAAG,CAAC,CAAC;gBAE1B,MAAM,KAAK,GAAG,SAAS,GAAG,CAAC,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC;gBAC7C,MAAM,KAAK,CAAC,KAAK,CAAC,CAAC;YACrB,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"with-retry.js","sourceRoot":"","sources":["../../src/patterns/with-retry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAetD,MAAM,UAAU,SAAS,CACvB,KAAkB,EAClB,UAAkC,EAAE;IAEpC,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,CAAC,CAAC;IAC7C,MAAM,SAAS,GAAG,OAAO,CAAC,WAAW,IAAI,IAAI,CAAC;IAC9C,MAAM,SAAS,GACb,OAAO,CAAC,SAAS,IAAI,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,SAAS,IAAI,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC;IAEvF,OAAO;QACL,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,KAAK,CAAC,CAAC,GAAG,CAAC,GAAG;YACZ,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,WAAW,EAAE,OAAO,EAAE,EAAE,CAAC;gBACxD,MAAM;oBACJ,IAAI,EAAE,MAAM;oBACZ,GAAG,EAAE,GAAG,KAAK,CAAC,IAAI,UAAU;oBAC5B,KAAK,EAAE,EAAE,OAAO,EAAE,WAAW,EAAE;iBAChC,CAAC;gBAEF,MAAM,UAAU,GAAG,GAAG,CAAC,IAAI,CAAC;gBAC5B,IAAI,MAAM,GAAY,SAAS,CAAC;gBAEhC,IAAI,CAAC;oBACH,kEAAkE;oBAClE,mEAAmE;oBACnE,oBAAoB;oBACpB,GAAG,CAAC,IAAI,GAAG,SAAS,CAAC;oBACrB,KAAK,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;gBACxB,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,MAAM,GAAG,GAAG,CAAC;gBACf,CAAC;gBAED,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;gBAEtC,IAAI,CAAC,MAAM,EAAE,CAAC;oBACZ,iEAAiE;oBACjE,gEAAgE;oBAChE,mCAAmC;oBACnC,OAAO;gBACT,CAAC;gBAED,IAAI,OAAO,KAAK,WAAW,EAAE,CAAC;oBAC5B,+DAA+D;oBAC/D,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;wBACzB,MAAM,MAAM,CAAC;oBACf,CAAC;oBACD,wDAAwD;oBACxD,OAAO;gBACT,CAAC;gBAED,OAAO,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;gBACxC,GAAG,CAAC,IAAI,GAAG,UAAU,CAAC,CAAC,gCAAgC;gBACvD,OAAO,CAAC,UAAU,EAAE,CAAC,GAAG,CAAC,CAAC;gBAE1B,MAAM,KAAK,GAAG,SAAS,GAAG,CAAC,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC;gBAC7C,oEAAoE;gBACpE,oEAAoE;gBACpE,0DAA0D;gBAC1D,MAAM,cAAc,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;YAC1C,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC"}
package/dist/phase.d.ts CHANGED
@@ -66,6 +66,9 @@ export type PipelineEvent = {
66
66
  } | {
67
67
  type: 'done';
68
68
  reason?: string;
69
+ } | {
70
+ type: 'cancelled';
71
+ reason: string;
69
72
  } | {
70
73
  type: 'error';
71
74
  message: string;
@@ -1 +1 @@
1
- {"version":3,"file":"phase.d.ts","sourceRoot":"","sources":["../src/phase.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAOhD,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC;IAC9B,yDAAyD;IACzD,IAAI,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1B;;;;;OAKG;IACH,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAWD,MAAM,MAAM,aAAa,GACrB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,GAClF;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACpC;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAC1E;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,GACzF;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAC3D;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,GAC7C;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GACjC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAcvC,MAAM,WAAW,KAAK,CACpB,IAAI,SAAS,mBAAmB,GAAG,mBAAmB,EACtD,MAAM,GAAG,aAAa;IAEtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,GAAG,CAAC,GAAG,EAAE,IAAI,GAAG,cAAc,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;CAC9C;AAMD,wBAAgB,UAAU,CAAC,IAAI,SAAS,mBAAmB,EAAE,CAAC,SAAS,MAAM,IAAI,EAC/E,GAAG,EAAE,IAAI,EACT,GAAG,EAAE,CAAC,EACN,SAAS,EAAE,MAAM,GAChB,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAStB"}
1
+ {"version":3,"file":"phase.d.ts","sourceRoot":"","sources":["../src/phase.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAOhD,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC;IAC9B,yDAAyD;IACzD,IAAI,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1B;;;;;OAKG;IACH,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAWD,MAAM,MAAM,aAAa,GACrB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,GAClF;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACpC;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAC1E;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,GACzF;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAC3D;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,GAC7C;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAKjC;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACrC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAcvC,MAAM,WAAW,KAAK,CACpB,IAAI,SAAS,mBAAmB,GAAG,mBAAmB,EACtD,MAAM,GAAG,aAAa;IAEtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,GAAG,CAAC,GAAG,EAAE,IAAI,GAAG,cAAc,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;CAC9C;AAMD,wBAAgB,UAAU,CAAC,IAAI,SAAS,mBAAmB,EAAE,CAAC,SAAS,MAAM,IAAI,EAC/E,GAAG,EAAE,IAAI,EACT,GAAG,EAAE,CAAC,EACN,SAAS,EAAE,MAAM,GAChB,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAStB"}
package/dist/phase.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"phase.js","sourceRoot":"","sources":["../src/phase.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AA6DH,8EAA8E;AAC9E,qEAAqE;AACrE,8EAA8E;AAE9E,MAAM,UAAU,UAAU,CACxB,GAAS,EACT,GAAM,EACN,SAAiB;IAEjB,MAAM,KAAK,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;IACvB,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QAC1C,MAAM,IAAI,KAAK,CACb,IAAI,SAAS,8BAA8B,MAAM,CAAC,GAAG,CAAC,eAAe;YACnE,kEAAkE,CACrE,CAAC;IACJ,CAAC;IACD,OAAO,KAA6B,CAAC;AACvC,CAAC"}
1
+ {"version":3,"file":"phase.js","sourceRoot":"","sources":["../src/phase.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAkEH,8EAA8E;AAC9E,qEAAqE;AACrE,8EAA8E;AAE9E,MAAM,UAAU,UAAU,CACxB,GAAS,EACT,GAAM,EACN,SAAiB;IAEjB,MAAM,KAAK,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;IACvB,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QAC1C,MAAM,IAAI,KAAK,CACb,IAAI,SAAS,8BAA8B,MAAM,CAAC,GAAG,CAAC,eAAe;YACnE,kEAAkE,CACrE,CAAC;IACJ,CAAC;IACD,OAAO,KAA6B,CAAC;AACvC,CAAC"}
@@ -28,12 +28,16 @@ import type { JobStore } from './job-store.js';
28
28
  import type { JobRunner } from './job-runner.js';
29
29
  /**
30
30
  * Minimal response interface — `http.ServerResponse` and Express's `Response`
31
- * both satisfy this without modification.
31
+ * both satisfy this without modification. `once(drain)` is required for
32
+ * backpressure handling: when `write()` returns false the socket buffer is
33
+ * full and writes must pause until `drain` fires, or memory grows
34
+ * unboundedly behind a slow client.
32
35
  */
33
36
  export interface SSEResponse {
34
37
  write(chunk: string): boolean;
35
38
  end(): void;
36
39
  on(event: 'close', listener: () => void): void;
40
+ once(event: 'drain', listener: () => void): void;
37
41
  }
38
42
  export interface StreamToSSEOptions {
39
43
  runner: JobRunner;
@@ -1 +1 @@
1
- {"version":3,"file":"sse.d.ts","sourceRoot":"","sources":["../../src/session/sse.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,KAAK,EAAE,SAAS,EAAa,MAAM,iBAAiB,CAAC;AAE5D;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;IAC9B,GAAG,IAAI,IAAI,CAAC;IACZ,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI,CAAC;CAChD;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,SAAS,CAAC;IAClB,KAAK,EAAE,QAAQ,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,WAAW,CAAC;IACjB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;GAGG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAqE5E"}
1
+ {"version":3,"file":"sse.d.ts","sourceRoot":"","sources":["../../src/session/sse.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,KAAK,EAAE,SAAS,EAAa,MAAM,iBAAiB,CAAC;AAE5D;;;;;;GAMG;AACH,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;IAC9B,GAAG,IAAI,IAAI,CAAC;IACZ,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI,CAAC;IAC/C,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI,CAAC;CAClD;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,SAAS,CAAC;IAClB,KAAK,EAAE,QAAQ,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,WAAW,CAAC;IACjB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;GAGG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CA2G5E"}
@@ -41,19 +41,30 @@ export async function streamToSSE(options) {
41
41
  res.on('close', () => {
42
42
  closed = true;
43
43
  });
44
- const writeFrame = (id, type, data) => {
44
+ // Backpressure: when res.write() returns false the socket buffer is full
45
+ // and we must wait for 'drain' before continuing. Without this, slow
46
+ // clients cause unbounded Node-side memory growth as writes accumulate.
47
+ const writeWithBackpressure = async (payload) => {
45
48
  if (closed)
46
- return false;
47
- const payload = `id: ${id}\n` +
49
+ return;
50
+ if (!res.write(payload)) {
51
+ await new Promise((resolve) => res.once('drain', resolve));
52
+ }
53
+ };
54
+ const writeFrame = async (id, type, data) => {
55
+ if (closed)
56
+ return;
57
+ await writeWithBackpressure(`id: ${id}\n` +
48
58
  `event: ${type}\n` +
49
- `data: ${JSON.stringify(data)}\n\n`;
50
- return res.write(payload);
59
+ `data: ${JSON.stringify(data)}\n\n`);
51
60
  };
52
61
  // Step 1: replay anything the client has missed.
53
62
  let lastId = afterId;
54
63
  const replay = await store.getEvents(jobId, afterId);
55
64
  for (const evt of replay) {
56
- writeFrame(evt.id, evt.eventType, evt.data);
65
+ if (closed)
66
+ return;
67
+ await writeFrame(evt.id, evt.eventType, evt.data);
57
68
  lastId = Math.max(lastId, evt.id);
58
69
  }
59
70
  // If the job is already finished and replay covered everything, close.
@@ -62,27 +73,56 @@ export async function streamToSSE(options) {
62
73
  close();
63
74
  return;
64
75
  }
65
- // Step 2: subscribe to live events. Buffer events that arrived during
66
- // replay if their id is past lastId (otherwise they're already sent).
76
+ // Step 2: subscribe to live events. The EventEmitter listener is sync
77
+ // and fire-and-forget by API; we buffer events and drain them serially
78
+ // through writeFrame so backpressure stays honored and ordering is
79
+ // preserved even when multiple events arrive while a write is pending.
67
80
  const channel = `job:${jobId}`;
81
+ const liveBuffer = [];
82
+ let draining = false;
83
+ const drainLive = async () => {
84
+ if (draining)
85
+ return;
86
+ draining = true;
87
+ try {
88
+ while (!closed && liveBuffer.length > 0) {
89
+ const evt = liveBuffer.shift();
90
+ if (evt.id <= lastId)
91
+ continue;
92
+ lastId = evt.id;
93
+ await writeFrame(evt.id, evt.eventType, evt.data);
94
+ if (evt.eventType === 'done' || evt.eventType === 'error') {
95
+ close();
96
+ return;
97
+ }
98
+ }
99
+ }
100
+ finally {
101
+ draining = false;
102
+ }
103
+ };
68
104
  const onLive = (evt) => {
69
105
  if (closed)
70
106
  return;
71
- if (evt.id <= lastId)
72
- return;
73
- lastId = evt.id;
74
- writeFrame(evt.id, evt.eventType, evt.data);
75
- if (evt.eventType === 'done' || evt.eventType === 'error') {
76
- close();
77
- }
107
+ liveBuffer.push(evt);
108
+ // Promise rejection here would be unobserved by the EventEmitter, so
109
+ // catch and swallow — writes that fail close the socket anyway.
110
+ void drainLive().catch(() => {
111
+ /* connection error during drain; close listener will fire */
112
+ });
78
113
  };
79
114
  runner.on(channel, onLive);
80
- // Heartbeat: comment line every N seconds to keep proxies from idling out.
115
+ // Heartbeat: comment line every N seconds to keep proxies from idling
116
+ // out. Skip the heartbeat when the socket is back-pressured rather than
117
+ // queueing — heartbeats are advisory and stale ones are not useful.
81
118
  let heartbeat = null;
82
119
  if (heartbeatMs > 0) {
83
120
  heartbeat = setInterval(() => {
84
121
  if (closed)
85
122
  return;
123
+ // Discard the boolean intentionally: this is a hint, not data.
124
+ // Backpressure is handled by event writes, which will pause the
125
+ // pipeline once drain is pending.
86
126
  res.write(`: keepalive ${Date.now()}\n\n`);
87
127
  }, heartbeatMs);
88
128
  }
@@ -1 +1 @@
1
- {"version":3,"file":"sse.js","sourceRoot":"","sources":["../../src/session/sse.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sse.js","sourceRoot":"","sources":["../../src/session/sse.ts"],"names":[],"mappings":"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"}
@@ -19,9 +19,14 @@ import type { ToolDefinition, ToolExecutor, ToolResult } from '../messages.js';
19
19
  * Handler signature — receives parsed args plus optional context, returns the
20
20
  * tool's result content as a string. Anything string-shaped works (JSON,
21
21
  * markdown, plain text); the agent sees it raw.
22
+ *
23
+ * `context.signal` is the agent runner's AbortSignal when one was provided.
24
+ * Long-running tools (fetch, subprocess, file I/O) can observe it to cancel
25
+ * cooperatively. Synchronous or fast tools may ignore it.
22
26
  */
23
27
  export type ToolHandler = (args: Record<string, unknown>, context: {
24
28
  toolCallId: string;
29
+ signal?: AbortSignal;
25
30
  }) => Promise<string>;
26
31
  export interface ToolRegistryOptions {
27
32
  /** When false, skip schema validation. Default: true. */
@@ -39,6 +44,6 @@ export declare class ToolRegistry implements ToolExecutor {
39
44
  /** All registered tool definitions, in registration order. Hand to AgentConfig.tools. */
40
45
  definitions(): ToolDefinition[];
41
46
  has(name: string): boolean;
42
- execute(name: string, toolCallId: string, args: Record<string, unknown>): Promise<ToolResult>;
47
+ execute(name: string, toolCallId: string, args: Record<string, unknown>, signal?: AbortSignal): Promise<ToolResult>;
43
48
  }
44
49
  //# sourceMappingURL=registry.d.ts.map