@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.
- package/dist/agent/index.d.ts +1 -1
- package/dist/agent/index.d.ts.map +1 -1
- package/dist/agent/index.js +1 -1
- package/dist/agent/index.js.map +1 -1
- package/dist/agent/parse-json.d.ts +16 -0
- package/dist/agent/parse-json.d.ts.map +1 -1
- package/dist/agent/parse-json.js +82 -11
- package/dist/agent/parse-json.js.map +1 -1
- package/dist/agent/runner.d.ts.map +1 -1
- package/dist/agent/runner.js +16 -12
- package/dist/agent/runner.js.map +1 -1
- package/dist/agent-runner.d.ts +1 -1
- package/dist/agent-runner.d.ts.map +1 -1
- package/dist/agent-runner.js +1 -1
- package/dist/agent-runner.js.map +1 -1
- package/dist/agents/serialize-error.d.ts +10 -1
- package/dist/agents/serialize-error.d.ts.map +1 -1
- package/dist/agents/serialize-error.js +42 -3
- package/dist/agents/serialize-error.js.map +1 -1
- package/dist/cache.d.ts +13 -2
- package/dist/cache.d.ts.map +1 -1
- package/dist/cache.js +36 -6
- package/dist/cache.js.map +1 -1
- package/dist/helpers/hook.d.ts +34 -2
- package/dist/helpers/hook.d.ts.map +1 -1
- package/dist/helpers/hook.js +72 -5
- package/dist/helpers/hook.js.map +1 -1
- package/dist/helpers/index.d.ts +11 -1
- package/dist/helpers/index.d.ts.map +1 -1
- package/dist/helpers/index.js +11 -1
- package/dist/helpers/index.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/internal/error-message.d.ts +20 -0
- package/dist/internal/error-message.d.ts.map +1 -0
- package/dist/internal/error-message.js +57 -0
- package/dist/internal/error-message.js.map +1 -0
- package/dist/internal/sleep.d.ts +17 -0
- package/dist/internal/sleep.d.ts.map +1 -0
- package/dist/internal/sleep.js +51 -0
- package/dist/internal/sleep.js.map +1 -0
- package/dist/messages.d.ts +11 -1
- package/dist/messages.d.ts.map +1 -1
- package/dist/orchestrator.d.ts +1 -1
- package/dist/orchestrator.d.ts.map +1 -1
- package/dist/orchestrator.js +21 -2
- package/dist/orchestrator.js.map +1 -1
- package/dist/patterns/bounded-fanout-of.d.ts +2 -6
- package/dist/patterns/bounded-fanout-of.d.ts.map +1 -1
- package/dist/patterns/bounded-fanout-of.js +11 -8
- package/dist/patterns/bounded-fanout-of.js.map +1 -1
- package/dist/patterns/index.d.ts +22 -0
- package/dist/patterns/index.d.ts.map +1 -1
- package/dist/patterns/index.js +22 -0
- package/dist/patterns/index.js.map +1 -1
- package/dist/patterns/parallel-phases.d.ts +7 -2
- package/dist/patterns/parallel-phases.d.ts.map +1 -1
- package/dist/patterns/parallel-phases.js +70 -16
- package/dist/patterns/parallel-phases.js.map +1 -1
- package/dist/patterns/sub-pipeline.d.ts.map +1 -1
- package/dist/patterns/sub-pipeline.js +10 -6
- package/dist/patterns/sub-pipeline.js.map +1 -1
- package/dist/patterns/with-retry.d.ts.map +1 -1
- package/dist/patterns/with-retry.js +5 -2
- package/dist/patterns/with-retry.js.map +1 -1
- package/dist/phase.d.ts +3 -0
- package/dist/phase.d.ts.map +1 -1
- package/dist/phase.js.map +1 -1
- package/dist/session/sse.d.ts +5 -1
- package/dist/session/sse.d.ts.map +1 -1
- package/dist/session/sse.js +56 -16
- package/dist/session/sse.js.map +1 -1
- package/dist/tools/registry.d.ts +6 -1
- package/dist/tools/registry.d.ts.map +1 -1
- package/dist/tools/registry.js +2 -2
- package/dist/tools/registry.js.map +1 -1
- package/dist/triggers/run-trigger.d.ts.map +1 -1
- package/dist/triggers/run-trigger.js +4 -1
- package/dist/triggers/run-trigger.js.map +1 -1
- package/dist/triggers/timer-trigger.d.ts +13 -1
- package/dist/triggers/timer-trigger.d.ts.map +1 -1
- package/dist/triggers/timer-trigger.js +35 -3
- package/dist/triggers/timer-trigger.js.map +1 -1
- 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
|
-
*
|
|
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
|
-
|
|
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":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;
|
|
1
|
+
{"version":3,"file":"bounded-fanout-of.js","sourceRoot":"","sources":["../../src/patterns/bounded-fanout-of.ts"],"names":[],"mappings":"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"}
|
package/dist/patterns/index.d.ts
CHANGED
|
@@ -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
|
|
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"}
|
package/dist/patterns/index.js
CHANGED
|
@@ -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
|
|
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,
|
|
16
|
-
*
|
|
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
|
|
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,
|
|
16
|
-
*
|
|
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(
|
|
69
|
+
for await (const ev of phase.run(branchCtx)) {
|
|
46
70
|
queue.push(ev);
|
|
47
71
|
wake();
|
|
48
|
-
|
|
49
|
-
|
|
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
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
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
|
-
|
|
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
|
|
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,
|
|
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
|
|
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
|
-
|
|
39
|
-
|
|
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;
|
|
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;
|
|
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
|
-
|
|
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
|
-
|
|
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;
|
|
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
package/dist/phase.d.ts.map
CHANGED
|
@@ -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,
|
|
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;
|
|
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"}
|
package/dist/session/sse.d.ts
CHANGED
|
@@ -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
|
|
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"}
|
package/dist/session/sse.js
CHANGED
|
@@ -41,19 +41,30 @@ export async function streamToSSE(options) {
|
|
|
41
41
|
res.on('close', () => {
|
|
42
42
|
closed = true;
|
|
43
43
|
});
|
|
44
|
-
|
|
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
|
|
47
|
-
|
|
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
|
-
|
|
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.
|
|
66
|
-
//
|
|
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
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
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
|
|
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
|
}
|
package/dist/session/sse.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sse.js","sourceRoot":"","sources":["../../src/session/sse.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;
|
|
1
|
+
{"version":3,"file":"sse.js","sourceRoot":"","sources":["../../src/session/sse.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAqCH;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,OAA2B;IAC3D,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,GAAG,CAAC,EAAE,GAAG,OAAO,CAAC;IAC3D,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,MAAM,CAAC;IAElD,IAAI,MAAM,GAAG,KAAK,CAAC;IACnB,MAAM,KAAK,GAAG,GAAG,EAAE;QACjB,IAAI,MAAM;YAAE,OAAO;QACnB,MAAM,GAAG,IAAI,CAAC;QACd,GAAG,CAAC,GAAG,EAAE,CAAC;IACZ,CAAC,CAAC;IAEF,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;QACnB,MAAM,GAAG,IAAI,CAAC;IAChB,CAAC,CAAC,CAAC;IAEH,yEAAyE;IACzE,qEAAqE;IACrE,wEAAwE;IACxE,MAAM,qBAAqB,GAAG,KAAK,EAAE,OAAe,EAAiB,EAAE;QACrE,IAAI,MAAM;YAAE,OAAO;QACnB,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;YACxB,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;QACnE,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,UAAU,GAAG,KAAK,EAAE,EAAU,EAAE,IAAY,EAAE,IAAa,EAAiB,EAAE;QAClF,IAAI,MAAM;YAAE,OAAO;QACnB,MAAM,qBAAqB,CACzB,OAAO,EAAE,IAAI;YACX,UAAU,IAAI,IAAI;YAClB,SAAS,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CACtC,CAAC;IACJ,CAAC,CAAC;IAEF,iDAAiD;IACjD,IAAI,MAAM,GAAG,OAAO,CAAC;IACrB,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,SAAS,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IACrD,KAAK,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;QACzB,IAAI,MAAM;YAAE,OAAO;QACnB,MAAM,UAAU,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,SAAS,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;QAClD,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;IACpC,CAAC;IAED,uEAAuE;IACvE,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACtC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,KAAK,WAAW,IAAI,GAAG,CAAC,MAAM,KAAK,QAAQ,CAAC,EAAE,CAAC;QACnE,KAAK,EAAE,CAAC;QACR,OAAO;IACT,CAAC;IAED,sEAAsE;IACtE,uEAAuE;IACvE,mEAAmE;IACnE,uEAAuE;IACvE,MAAM,OAAO,GAAG,OAAO,KAAK,EAAE,CAAC;IAC/B,MAAM,UAAU,GAAgB,EAAE,CAAC;IACnC,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,MAAM,SAAS,GAAG,KAAK,IAAmB,EAAE;QAC1C,IAAI,QAAQ;YAAE,OAAO;QACrB,QAAQ,GAAG,IAAI,CAAC;QAChB,IAAI,CAAC;YACH,OAAO,CAAC,MAAM,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACxC,MAAM,GAAG,GAAG,UAAU,CAAC,KAAK,EAAG,CAAC;gBAChC,IAAI,GAAG,CAAC,EAAE,IAAI,MAAM;oBAAE,SAAS;gBAC/B,MAAM,GAAG,GAAG,CAAC,EAAE,CAAC;gBAChB,MAAM,UAAU,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,SAAS,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;gBAClD,IAAI,GAAG,CAAC,SAAS,KAAK,MAAM,IAAI,GAAG,CAAC,SAAS,KAAK,OAAO,EAAE,CAAC;oBAC1D,KAAK,EAAE,CAAC;oBACR,OAAO;gBACT,CAAC;YACH,CAAC;QACH,CAAC;gBAAS,CAAC;YACT,QAAQ,GAAG,KAAK,CAAC;QACnB,CAAC;IACH,CAAC,CAAC;IACF,MAAM,MAAM,GAAG,CAAC,GAAc,EAAQ,EAAE;QACtC,IAAI,MAAM;YAAE,OAAO;QACnB,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACrB,qEAAqE;QACrE,gEAAgE;QAChE,KAAK,SAAS,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE;YAC1B,6DAA6D;QAC/D,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;IACF,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAE3B,sEAAsE;IACtE,wEAAwE;IACxE,oEAAoE;IACpE,IAAI,SAAS,GAA0C,IAAI,CAAC;IAC5D,IAAI,WAAW,GAAG,CAAC,EAAE,CAAC;QACpB,SAAS,GAAG,WAAW,CAAC,GAAG,EAAE;YAC3B,IAAI,MAAM;gBAAE,OAAO;YACnB,+DAA+D;YAC/D,gEAAgE;YAChE,kCAAkC;YAClC,GAAG,CAAC,KAAK,CAAC,eAAe,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QAC7C,CAAC,EAAE,WAAW,CAAC,CAAC;IAClB,CAAC;IAED,oCAAoC;IACpC,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;QAClC,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC3B,CAAC,CAAC,CAAC;IAEH,IAAI,SAAS;QAAE,aAAa,CAAC,SAAS,CAAC,CAAC;IACxC,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;AAC9B,CAAC"}
|
package/dist/tools/registry.d.ts
CHANGED
|
@@ -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
|
|
47
|
+
execute(name: string, toolCallId: string, args: Record<string, unknown>, signal?: AbortSignal): Promise<ToolResult>;
|
|
43
48
|
}
|
|
44
49
|
//# sourceMappingURL=registry.d.ts.map
|