@autonome-research/thread-phase 3.0.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/LICENSE +21 -0
- package/README.md +226 -0
- package/dist/agent/index.d.ts +28 -0
- package/dist/agent/index.d.ts.map +1 -0
- package/dist/agent/index.js +28 -0
- package/dist/agent/index.js.map +1 -0
- package/dist/agent/openai-adapter.d.ts +15 -0
- package/dist/agent/openai-adapter.d.ts.map +1 -0
- package/dist/agent/openai-adapter.js +57 -0
- package/dist/agent/openai-adapter.js.map +1 -0
- package/dist/agent/parse-json.d.ts +12 -0
- package/dist/agent/parse-json.d.ts.map +1 -0
- package/dist/agent/parse-json.js +31 -0
- package/dist/agent/parse-json.js.map +1 -0
- package/dist/agent/retry.d.ts +15 -0
- package/dist/agent/retry.d.ts.map +1 -0
- package/dist/agent/retry.js +35 -0
- package/dist/agent/retry.js.map +1 -0
- package/dist/agent/runner.d.ts +25 -0
- package/dist/agent/runner.d.ts.map +1 -0
- package/dist/agent/runner.js +270 -0
- package/dist/agent/runner.js.map +1 -0
- package/dist/agent/stream-consumer.d.ts +57 -0
- package/dist/agent/stream-consumer.d.ts.map +1 -0
- package/dist/agent/stream-consumer.js +126 -0
- package/dist/agent/stream-consumer.js.map +1 -0
- package/dist/agent/types.d.ts +135 -0
- package/dist/agent/types.d.ts.map +1 -0
- package/dist/agent/types.js +9 -0
- package/dist/agent/types.js.map +1 -0
- package/dist/agent-runner.d.ts +10 -0
- package/dist/agent-runner.d.ts.map +1 -0
- package/dist/agent-runner.js +10 -0
- package/dist/agent-runner.js.map +1 -0
- package/dist/agents/capability.d.ts +36 -0
- package/dist/agents/capability.d.ts.map +1 -0
- package/dist/agents/capability.js +51 -0
- package/dist/agents/capability.js.map +1 -0
- package/dist/agents/event-bus.d.ts +20 -0
- package/dist/agents/event-bus.d.ts.map +1 -0
- package/dist/agents/event-bus.js +40 -0
- package/dist/agents/event-bus.js.map +1 -0
- package/dist/agents/index.d.ts +23 -0
- package/dist/agents/index.d.ts.map +1 -0
- package/dist/agents/index.js +33 -0
- package/dist/agents/index.js.map +1 -0
- package/dist/agents/inference-adapter.d.ts +52 -0
- package/dist/agents/inference-adapter.d.ts.map +1 -0
- package/dist/agents/inference-adapter.js +209 -0
- package/dist/agents/inference-adapter.js.map +1 -0
- package/dist/agents/job-store-bridge.d.ts +44 -0
- package/dist/agents/job-store-bridge.d.ts.map +1 -0
- package/dist/agents/job-store-bridge.js +58 -0
- package/dist/agents/job-store-bridge.js.map +1 -0
- package/dist/agents/memory.d.ts +40 -0
- package/dist/agents/memory.d.ts.map +1 -0
- package/dist/agents/memory.js +14 -0
- package/dist/agents/memory.js.map +1 -0
- package/dist/agents/protocol.d.ts +302 -0
- package/dist/agents/protocol.d.ts.map +1 -0
- package/dist/agents/protocol.js +36 -0
- package/dist/agents/protocol.js.map +1 -0
- package/dist/agents/run-helpers.d.ts +70 -0
- package/dist/agents/run-helpers.d.ts.map +1 -0
- package/dist/agents/run-helpers.js +131 -0
- package/dist/agents/run-helpers.js.map +1 -0
- package/dist/agents/serialize-error.d.ts +18 -0
- package/dist/agents/serialize-error.d.ts.map +1 -0
- package/dist/agents/serialize-error.js +27 -0
- package/dist/agents/serialize-error.js.map +1 -0
- package/dist/agents/structured-output.d.ts +90 -0
- package/dist/agents/structured-output.d.ts.map +1 -0
- package/dist/agents/structured-output.js +101 -0
- package/dist/agents/structured-output.js.map +1 -0
- package/dist/agents/test-utils/conformance.d.ts +59 -0
- package/dist/agents/test-utils/conformance.d.ts.map +1 -0
- package/dist/agents/test-utils/conformance.js +207 -0
- package/dist/agents/test-utils/conformance.js.map +1 -0
- package/dist/agents/test-utils/index.d.ts +12 -0
- package/dist/agents/test-utils/index.d.ts.map +1 -0
- package/dist/agents/test-utils/index.js +12 -0
- package/dist/agents/test-utils/index.js.map +1 -0
- package/dist/agents/test-utils/mock-agent.d.ts +66 -0
- package/dist/agents/test-utils/mock-agent.d.ts.map +1 -0
- package/dist/agents/test-utils/mock-agent.js +244 -0
- package/dist/agents/test-utils/mock-agent.js.map +1 -0
- package/dist/agents/thread.d.ts +57 -0
- package/dist/agents/thread.d.ts.map +1 -0
- package/dist/agents/thread.js +128 -0
- package/dist/agents/thread.js.map +1 -0
- package/dist/agents/turn-accumulator.d.ts +94 -0
- package/dist/agents/turn-accumulator.d.ts.map +1 -0
- package/dist/agents/turn-accumulator.js +150 -0
- package/dist/agents/turn-accumulator.js.map +1 -0
- package/dist/agents/with-memory.d.ts +55 -0
- package/dist/agents/with-memory.d.ts.map +1 -0
- package/dist/agents/with-memory.js +155 -0
- package/dist/agents/with-memory.js.map +1 -0
- package/dist/agents/with-thread.d.ts +45 -0
- package/dist/agents/with-thread.d.ts.map +1 -0
- package/dist/agents/with-thread.js +70 -0
- package/dist/agents/with-thread.js.map +1 -0
- package/dist/cache.d.ts +47 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/cache.js +81 -0
- package/dist/cache.js.map +1 -0
- package/dist/context/compressor.d.ts +36 -0
- package/dist/context/compressor.d.ts.map +1 -0
- package/dist/context/compressor.js +158 -0
- package/dist/context/compressor.js.map +1 -0
- package/dist/context/index.d.ts +4 -0
- package/dist/context/index.d.ts.map +1 -0
- package/dist/context/index.js +4 -0
- package/dist/context/index.js.map +1 -0
- package/dist/context/result-capper.d.ts +32 -0
- package/dist/context/result-capper.d.ts.map +1 -0
- package/dist/context/result-capper.js +50 -0
- package/dist/context/result-capper.js.map +1 -0
- package/dist/context/token-budget.d.ts +81 -0
- package/dist/context/token-budget.d.ts.map +1 -0
- package/dist/context/token-budget.js +99 -0
- package/dist/context/token-budget.js.map +1 -0
- package/dist/helpers/caller.d.ts +18 -0
- package/dist/helpers/caller.d.ts.map +1 -0
- package/dist/helpers/caller.js +40 -0
- package/dist/helpers/caller.js.map +1 -0
- package/dist/helpers/hook.d.ts +73 -0
- package/dist/helpers/hook.d.ts.map +1 -0
- package/dist/helpers/hook.js +244 -0
- package/dist/helpers/hook.js.map +1 -0
- package/dist/helpers/index.d.ts +12 -0
- package/dist/helpers/index.d.ts.map +1 -0
- package/dist/helpers/index.js +11 -0
- package/dist/helpers/index.js.map +1 -0
- package/dist/helpers/one-shot.d.ts +27 -0
- package/dist/helpers/one-shot.d.ts.map +1 -0
- package/dist/helpers/one-shot.js +43 -0
- package/dist/helpers/one-shot.js.map +1 -0
- package/dist/helpers/schedule.d.ts +59 -0
- package/dist/helpers/schedule.d.ts.map +1 -0
- package/dist/helpers/schedule.js +118 -0
- package/dist/helpers/schedule.js.map +1 -0
- package/dist/helpers/types.d.ts +34 -0
- package/dist/helpers/types.d.ts.map +1 -0
- package/dist/helpers/types.js +11 -0
- package/dist/helpers/types.js.map +1 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +37 -0
- package/dist/index.js.map +1 -0
- package/dist/inference.d.ts +27 -0
- package/dist/inference.d.ts.map +1 -0
- package/dist/inference.js +34 -0
- package/dist/inference.js.map +1 -0
- package/dist/messages.d.ts +64 -0
- package/dist/messages.d.ts.map +1 -0
- package/dist/messages.js +17 -0
- package/dist/messages.js.map +1 -0
- package/dist/orchestrator.d.ts +56 -0
- package/dist/orchestrator.d.ts.map +1 -0
- package/dist/orchestrator.js +62 -0
- package/dist/orchestrator.js.map +1 -0
- package/dist/patterns/bounded-fanout-of.d.ts +61 -0
- package/dist/patterns/bounded-fanout-of.d.ts.map +1 -0
- package/dist/patterns/bounded-fanout-of.js +142 -0
- package/dist/patterns/bounded-fanout-of.js.map +1 -0
- package/dist/patterns/bounded-fanout.d.ts +111 -0
- package/dist/patterns/bounded-fanout.d.ts.map +1 -0
- package/dist/patterns/bounded-fanout.js +151 -0
- package/dist/patterns/bounded-fanout.js.map +1 -0
- package/dist/patterns/index.d.ts +14 -0
- package/dist/patterns/index.d.ts.map +1 -0
- package/dist/patterns/index.js +13 -0
- package/dist/patterns/index.js.map +1 -0
- package/dist/patterns/intent-gate.d.ts +27 -0
- package/dist/patterns/intent-gate.d.ts.map +1 -0
- package/dist/patterns/intent-gate.js +32 -0
- package/dist/patterns/intent-gate.js.map +1 -0
- package/dist/patterns/match.d.ts +30 -0
- package/dist/patterns/match.d.ts.map +1 -0
- package/dist/patterns/match.js +58 -0
- package/dist/patterns/match.js.map +1 -0
- package/dist/patterns/parallel-fanout.d.ts +28 -0
- package/dist/patterns/parallel-fanout.d.ts.map +1 -0
- package/dist/patterns/parallel-fanout.js +24 -0
- package/dist/patterns/parallel-fanout.js.map +1 -0
- package/dist/patterns/parallel-phases.d.ts +27 -0
- package/dist/patterns/parallel-phases.d.ts.map +1 -0
- package/dist/patterns/parallel-phases.js +77 -0
- package/dist/patterns/parallel-phases.js.map +1 -0
- package/dist/patterns/preflight-confidence.d.ts +20 -0
- package/dist/patterns/preflight-confidence.d.ts.map +1 -0
- package/dist/patterns/preflight-confidence.js +38 -0
- package/dist/patterns/preflight-confidence.js.map +1 -0
- package/dist/patterns/spot-check.d.ts +19 -0
- package/dist/patterns/spot-check.d.ts.map +1 -0
- package/dist/patterns/spot-check.js +33 -0
- package/dist/patterns/spot-check.js.map +1 -0
- package/dist/patterns/sub-pipeline.d.ts +84 -0
- package/dist/patterns/sub-pipeline.d.ts.map +1 -0
- package/dist/patterns/sub-pipeline.js +90 -0
- package/dist/patterns/sub-pipeline.js.map +1 -0
- package/dist/patterns/synthesize-with-followup.d.ts +35 -0
- package/dist/patterns/synthesize-with-followup.d.ts.map +1 -0
- package/dist/patterns/synthesize-with-followup.js +45 -0
- package/dist/patterns/synthesize-with-followup.js.map +1 -0
- package/dist/patterns/while-condition.d.ts +31 -0
- package/dist/patterns/while-condition.d.ts.map +1 -0
- package/dist/patterns/while-condition.js +59 -0
- package/dist/patterns/while-condition.js.map +1 -0
- package/dist/patterns/with-retry.d.ts +37 -0
- package/dist/patterns/with-retry.d.ts.map +1 -0
- package/dist/patterns/with-retry.js +73 -0
- package/dist/patterns/with-retry.js.map +1 -0
- package/dist/phase.d.ts +78 -0
- package/dist/phase.d.ts.map +1 -0
- package/dist/phase.js +36 -0
- package/dist/phase.js.map +1 -0
- package/dist/session/index.d.ts +5 -0
- package/dist/session/index.d.ts.map +1 -0
- package/dist/session/index.js +4 -0
- package/dist/session/index.js.map +1 -0
- package/dist/session/job-runner.d.ts +67 -0
- package/dist/session/job-runner.d.ts.map +1 -0
- package/dist/session/job-runner.js +131 -0
- package/dist/session/job-runner.js.map +1 -0
- package/dist/session/job-store.d.ts +98 -0
- package/dist/session/job-store.d.ts.map +1 -0
- package/dist/session/job-store.js +37 -0
- package/dist/session/job-store.js.map +1 -0
- package/dist/session/sqlite-job-store.d.ts +40 -0
- package/dist/session/sqlite-job-store.d.ts.map +1 -0
- package/dist/session/sqlite-job-store.js +200 -0
- package/dist/session/sqlite-job-store.js.map +1 -0
- package/dist/session/sse.d.ts +60 -0
- package/dist/session/sse.d.ts.map +1 -0
- package/dist/session/sse.js +97 -0
- package/dist/session/sse.js.map +1 -0
- package/dist/tools/index.d.ts +2 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +2 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/registry.d.ts +44 -0
- package/dist/tools/registry.d.ts.map +1 -0
- package/dist/tools/registry.js +74 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/triggers/index.d.ts +15 -0
- package/dist/triggers/index.d.ts.map +1 -0
- package/dist/triggers/index.js +14 -0
- package/dist/triggers/index.js.map +1 -0
- package/dist/triggers/run-trigger.d.ts +86 -0
- package/dist/triggers/run-trigger.d.ts.map +1 -0
- package/dist/triggers/run-trigger.js +146 -0
- package/dist/triggers/run-trigger.js.map +1 -0
- package/dist/triggers/timer-trigger.d.ts +46 -0
- package/dist/triggers/timer-trigger.d.ts.map +1 -0
- package/dist/triggers/timer-trigger.js +74 -0
- package/dist/triggers/timer-trigger.js.map +1 -0
- package/dist/triggers/types.d.ts +61 -0
- package/dist/triggers/types.d.ts.map +1 -0
- package/dist/triggers/types.js +23 -0
- package/dist/triggers/types.js.map +1 -0
- package/package.json +64 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* parallel-phases — run several phases concurrently as one composite phase.
|
|
3
|
+
*
|
|
4
|
+
* The framework treats pipelines as an ordered array, which covers linear
|
|
5
|
+
* flow, conditional skip (`intentGate`), and self-iteration
|
|
6
|
+
* (`whileCondition`). The one DAG shape it doesn't natively express is
|
|
7
|
+
* "run two independent branches at the same time, then continue when
|
|
8
|
+
* both finish." That's what this pattern is for.
|
|
9
|
+
*
|
|
10
|
+
* Semantics:
|
|
11
|
+
* - Sub-phases share the parent `ctx`. If two branches both write to the
|
|
12
|
+
* same field, last-write-wins. Keep branches' ctx writes disjoint.
|
|
13
|
+
* - Events from all branches interleave into the composite phase's
|
|
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).
|
|
17
|
+
* - If a sub-phase sets `ctx.stop`, sibling branches still run to
|
|
18
|
+
* completion. The orchestrator's stop check fires AFTER the composite
|
|
19
|
+
* phase returns, halting subsequent top-level phases.
|
|
20
|
+
*
|
|
21
|
+
* For data-dependent fan-in, write each branch's output to a distinct ctx
|
|
22
|
+
* field; a downstream phase reads them all via `requireCtx`. That's a
|
|
23
|
+
* complete DAG-edge expression without a graph framework.
|
|
24
|
+
*/
|
|
25
|
+
export function parallelPhases(phaseName, phases) {
|
|
26
|
+
return {
|
|
27
|
+
name: phaseName,
|
|
28
|
+
async *run(ctx) {
|
|
29
|
+
if (phases.length === 0)
|
|
30
|
+
return;
|
|
31
|
+
// Producer/consumer: each sub-phase pushes events into a shared queue;
|
|
32
|
+
// the composite generator drains the queue and yields downstream.
|
|
33
|
+
const queue = [];
|
|
34
|
+
let resolveWaiter = null;
|
|
35
|
+
const wake = () => {
|
|
36
|
+
const fn = resolveWaiter;
|
|
37
|
+
resolveWaiter = null;
|
|
38
|
+
fn?.();
|
|
39
|
+
};
|
|
40
|
+
const wait = () => new Promise((r) => (resolveWaiter = r));
|
|
41
|
+
let errored = null;
|
|
42
|
+
let running = phases.length;
|
|
43
|
+
const drain = async (phase) => {
|
|
44
|
+
try {
|
|
45
|
+
for await (const ev of phase.run(ctx)) {
|
|
46
|
+
queue.push(ev);
|
|
47
|
+
wake();
|
|
48
|
+
if (errored)
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
catch (err) {
|
|
53
|
+
if (!errored)
|
|
54
|
+
errored = err;
|
|
55
|
+
}
|
|
56
|
+
finally {
|
|
57
|
+
running--;
|
|
58
|
+
wake();
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
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;
|
|
68
|
+
}
|
|
69
|
+
yield queue.shift();
|
|
70
|
+
}
|
|
71
|
+
await allDone;
|
|
72
|
+
if (errored)
|
|
73
|
+
throw errored;
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=parallel-phases.js.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* preflight-confidence — assess feasibility before spending big-model tokens.
|
|
3
|
+
*
|
|
4
|
+
* Run a fast, cheap check (often a metadata read or small LLM call) that
|
|
5
|
+
* returns a typed score. The pipeline can either surface the score and
|
|
6
|
+
* continue, or stop on insufficient signal.
|
|
7
|
+
*/
|
|
8
|
+
import type { BasePipelineContext, Phase } from '../phase.js';
|
|
9
|
+
export interface PreflightOptions<TCtx extends BasePipelineContext, TScore> {
|
|
10
|
+
/** Compute the score. May be an LLM call, metadata read, or pure logic. */
|
|
11
|
+
assess: (ctx: TCtx) => Promise<TScore>;
|
|
12
|
+
/** Stash the score on ctx (typed by the caller's context type). */
|
|
13
|
+
writeTo: (ctx: TCtx, score: TScore) => void;
|
|
14
|
+
/** Optional: human-readable description appended as a `content` event. */
|
|
15
|
+
describe?: (score: TScore) => string;
|
|
16
|
+
/** Optional: return a non-null reason to halt the pipeline. */
|
|
17
|
+
stopIf?: (score: TScore) => string | null;
|
|
18
|
+
}
|
|
19
|
+
export declare function preflightConfidence<TCtx extends BasePipelineContext, TScore>(phaseName: string, options: PreflightOptions<TCtx, TScore>): Phase<TCtx>;
|
|
20
|
+
//# sourceMappingURL=preflight-confidence.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preflight-confidence.d.ts","sourceRoot":"","sources":["../../src/patterns/preflight-confidence.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAE9D,MAAM,WAAW,gBAAgB,CAAC,IAAI,SAAS,mBAAmB,EAAE,MAAM;IACxE,2EAA2E;IAC3E,MAAM,EAAE,CAAC,GAAG,EAAE,IAAI,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACvC,mEAAmE;IACnE,OAAO,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IACrC,+DAA+D;IAC/D,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;CAC3C;AAED,wBAAgB,mBAAmB,CAAC,IAAI,SAAS,mBAAmB,EAAE,MAAM,EAC1E,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,gBAAgB,CAAC,IAAI,EAAE,MAAM,CAAC,GACtC,KAAK,CAAC,IAAI,CAAC,CAgCb"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* preflight-confidence — assess feasibility before spending big-model tokens.
|
|
3
|
+
*
|
|
4
|
+
* Run a fast, cheap check (often a metadata read or small LLM call) that
|
|
5
|
+
* returns a typed score. The pipeline can either surface the score and
|
|
6
|
+
* continue, or stop on insufficient signal.
|
|
7
|
+
*/
|
|
8
|
+
export function preflightConfidence(phaseName, options) {
|
|
9
|
+
return {
|
|
10
|
+
name: phaseName,
|
|
11
|
+
async *run(ctx) {
|
|
12
|
+
let score;
|
|
13
|
+
try {
|
|
14
|
+
score = await options.assess(ctx);
|
|
15
|
+
}
|
|
16
|
+
catch (err) {
|
|
17
|
+
const e = err;
|
|
18
|
+
yield {
|
|
19
|
+
type: 'agent_activity',
|
|
20
|
+
agent: phaseName,
|
|
21
|
+
action: 'error',
|
|
22
|
+
detail: e.message?.slice(0, 120),
|
|
23
|
+
};
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
options.writeTo(ctx, score);
|
|
27
|
+
yield { type: 'data', key: phaseName, value: score };
|
|
28
|
+
if (options.describe) {
|
|
29
|
+
yield { type: 'content', content: `${options.describe(score)}\n` };
|
|
30
|
+
}
|
|
31
|
+
const stopReason = options.stopIf?.(score);
|
|
32
|
+
if (stopReason !== null && stopReason !== undefined) {
|
|
33
|
+
ctx.stop = { reason: stopReason };
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=preflight-confidence.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preflight-confidence.js","sourceRoot":"","sources":["../../src/patterns/preflight-confidence.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAeH,MAAM,UAAU,mBAAmB,CACjC,SAAiB,EACjB,OAAuC;IAEvC,OAAO;QACL,IAAI,EAAE,SAAS;QACf,KAAK,CAAC,CAAC,GAAG,CAAC,GAAG;YACZ,IAAI,KAAa,CAAC;YAClB,IAAI,CAAC;gBACH,KAAK,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACpC,CAAC;YAAC,OAAO,GAAY,EAAE,CAAC;gBACtB,MAAM,CAAC,GAAG,GAA2B,CAAC;gBACtC,MAAM;oBACJ,IAAI,EAAE,gBAAgB;oBACtB,KAAK,EAAE,SAAS;oBAChB,MAAM,EAAE,OAAO;oBACf,MAAM,EAAE,CAAC,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;iBACjC,CAAC;gBACF,OAAO;YACT,CAAC;YAED,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;YAE5B,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;YAErD,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;gBACrB,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;YACrE,CAAC;YAED,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC;YAC3C,IAAI,UAAU,KAAK,IAAI,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;gBACpD,GAAG,CAAC,IAAI,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;YACpC,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* spot-check — verify a sample of typed claims from a prior phase.
|
|
3
|
+
*
|
|
4
|
+
* Pattern: extract a list of claims from an upstream artifact (synthesis,
|
|
5
|
+
* report, draft), verify a capped subset in parallel, stash the results.
|
|
6
|
+
*/
|
|
7
|
+
import type { BasePipelineContext, Phase } from '../phase.js';
|
|
8
|
+
export interface SpotCheckOptions<TCtx extends BasePipelineContext, TClaim, TResult> {
|
|
9
|
+
/** Pull the candidate claims from ctx (typically off a prior phase's output). */
|
|
10
|
+
extractClaims: (ctx: TCtx) => TClaim[];
|
|
11
|
+
/** Verify a single claim. Often runs an agent with read-only tools. */
|
|
12
|
+
verify: (claim: TClaim, ctx: TCtx) => Promise<TResult>;
|
|
13
|
+
/** Stash results on ctx. */
|
|
14
|
+
writeTo: (ctx: TCtx, results: TResult[]) => void;
|
|
15
|
+
/** Cap concurrent verifications. Default 5. */
|
|
16
|
+
maxClaims?: number;
|
|
17
|
+
}
|
|
18
|
+
export declare function spotCheck<TCtx extends BasePipelineContext, TClaim, TResult>(phaseName: string, options: SpotCheckOptions<TCtx, TClaim, TResult>): Phase<TCtx>;
|
|
19
|
+
//# sourceMappingURL=spot-check.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spot-check.d.ts","sourceRoot":"","sources":["../../src/patterns/spot-check.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAG9D,MAAM,WAAW,gBAAgB,CAAC,IAAI,SAAS,mBAAmB,EAAE,MAAM,EAAE,OAAO;IACjF,iFAAiF;IACjF,aAAa,EAAE,CAAC,GAAG,EAAE,IAAI,KAAK,MAAM,EAAE,CAAC;IACvC,uEAAuE;IACvE,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACvD,4BAA4B;IAC5B,OAAO,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC;IACjD,+CAA+C;IAC/C,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,SAAS,CAAC,IAAI,SAAS,mBAAmB,EAAE,MAAM,EAAE,OAAO,EACzE,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,GAC/C,KAAK,CAAC,IAAI,CAAC,CA4Bb"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* spot-check — verify a sample of typed claims from a prior phase.
|
|
3
|
+
*
|
|
4
|
+
* Pattern: extract a list of claims from an upstream artifact (synthesis,
|
|
5
|
+
* report, draft), verify a capped subset in parallel, stash the results.
|
|
6
|
+
*/
|
|
7
|
+
import { parallelFanout } from './parallel-fanout.js';
|
|
8
|
+
export function spotCheck(phaseName, options) {
|
|
9
|
+
return {
|
|
10
|
+
name: phaseName,
|
|
11
|
+
async *run(ctx) {
|
|
12
|
+
const allClaims = options.extractClaims(ctx);
|
|
13
|
+
const max = options.maxClaims ?? 5;
|
|
14
|
+
const claims = allClaims.slice(0, max);
|
|
15
|
+
yield {
|
|
16
|
+
type: 'phase',
|
|
17
|
+
phase: phaseName,
|
|
18
|
+
detail: `Verifying ${claims.length}/${allClaims.length} claim(s)`,
|
|
19
|
+
counts: { claims: claims.length, total: allClaims.length },
|
|
20
|
+
};
|
|
21
|
+
if (claims.length === 0) {
|
|
22
|
+
options.writeTo(ctx, []);
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
const results = await parallelFanout({
|
|
26
|
+
items: claims,
|
|
27
|
+
runner: (claim) => options.verify(claim, ctx),
|
|
28
|
+
});
|
|
29
|
+
options.writeTo(ctx, results);
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=spot-check.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spot-check.js","sourceRoot":"","sources":["../../src/patterns/spot-check.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAatD,MAAM,UAAU,SAAS,CACvB,SAAiB,EACjB,OAAgD;IAEhD,OAAO;QACL,IAAI,EAAE,SAAS;QACf,KAAK,CAAC,CAAC,GAAG,CAAC,GAAG;YACZ,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;YAC7C,MAAM,GAAG,GAAG,OAAO,CAAC,SAAS,IAAI,CAAC,CAAC;YACnC,MAAM,MAAM,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;YAEvC,MAAM;gBACJ,IAAI,EAAE,OAAO;gBACb,KAAK,EAAE,SAAS;gBAChB,MAAM,EAAE,aAAa,MAAM,CAAC,MAAM,IAAI,SAAS,CAAC,MAAM,WAAW;gBACjE,MAAM,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,EAAE,SAAS,CAAC,MAAM,EAAE;aAC3D,CAAC;YAEF,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACxB,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;gBACzB,OAAO;YACT,CAAC;YAED,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC;gBACnC,KAAK,EAAE,MAAM;gBACb,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC;aAC9C,CAAC,CAAC;YAEH,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QAChC,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* subPipeline — compose a registered (or inline) pipeline as a phase
|
|
3
|
+
* inside another pipeline.
|
|
4
|
+
*
|
|
5
|
+
* Two surface forms:
|
|
6
|
+
*
|
|
7
|
+
* - **`subPipeline(name, options)`** — higher-order pattern returning a
|
|
8
|
+
* `Phase<TOuterCtx>`. Compose like any other phase.
|
|
9
|
+
* - **`runSubPipeline(spec, options)`** — free function for imperative
|
|
10
|
+
* use inside phase bodies. Returns `{ ctx, summary }`.
|
|
11
|
+
*
|
|
12
|
+
* The inner pipeline gets:
|
|
13
|
+
* - a fresh `PipelineCache` (cache scopes are isolated)
|
|
14
|
+
* - the outer ctx's `signal` (cancellation propagates down)
|
|
15
|
+
*
|
|
16
|
+
* Events from the inner pipeline flatten into the outer event stream
|
|
17
|
+
* via `yield*` — JobStore consumers, SSE listeners, and the orchestrator
|
|
18
|
+
* see one continuous stream.
|
|
19
|
+
*/
|
|
20
|
+
import type { BasePipelineContext, Phase } from '../phase.js';
|
|
21
|
+
/**
|
|
22
|
+
* The inner pipeline spec. Either a direct `{ phases, ctx }` object, or a
|
|
23
|
+
* lazy resolver returning one (or `undefined` if not found). The CLI uses
|
|
24
|
+
* the resolver form to look up registered pipelines by name without making
|
|
25
|
+
* the core depend on the Registry.
|
|
26
|
+
*/
|
|
27
|
+
export type SubPipelineSource<TInnerCtx extends BasePipelineContext> = {
|
|
28
|
+
phases: ReadonlyArray<Phase<TInnerCtx>>;
|
|
29
|
+
ctx: TInnerCtx;
|
|
30
|
+
} | (() => {
|
|
31
|
+
phases: ReadonlyArray<Phase<TInnerCtx>>;
|
|
32
|
+
ctx: TInnerCtx;
|
|
33
|
+
} | undefined);
|
|
34
|
+
export interface SubPipelineOptions<TOuterCtx extends BasePipelineContext, TInnerCtx extends BasePipelineContext> {
|
|
35
|
+
/** Inner pipeline source: direct object or lazy resolver. */
|
|
36
|
+
pipeline: SubPipelineSource<TInnerCtx>;
|
|
37
|
+
/**
|
|
38
|
+
* Map outer ctx to the inner pipeline's starting ctx. Optional — if
|
|
39
|
+
* omitted, the inner pipeline starts with its own ctx as supplied by the
|
|
40
|
+
* source (the outer's `signal` is still wired in either way).
|
|
41
|
+
*/
|
|
42
|
+
mapInput?: (outer: TOuterCtx) => TInnerCtx;
|
|
43
|
+
/**
|
|
44
|
+
* Merge the inner pipeline's terminal state back into outer ctx. Optional
|
|
45
|
+
* — if omitted, the inner's outputs are discarded.
|
|
46
|
+
*/
|
|
47
|
+
mapOutput?: (outer: TOuterCtx, inner: TInnerCtx) => void;
|
|
48
|
+
}
|
|
49
|
+
/** A higher-order pattern returning a `Phase<TOuterCtx>`. */
|
|
50
|
+
export declare function subPipeline<TOuterCtx extends BasePipelineContext, TInnerCtx extends BasePipelineContext>(name: string, options: SubPipelineOptions<TOuterCtx, TInnerCtx>): Phase<TOuterCtx>;
|
|
51
|
+
/**
|
|
52
|
+
* Type-inferred convenience over `subPipeline` for the direct-object case.
|
|
53
|
+
* `TInnerCtx` is inferred from `source.ctx`, so callers only spell the outer
|
|
54
|
+
* ctx generic (and often not even that):
|
|
55
|
+
*
|
|
56
|
+
* subPipelineOf('inner', innerSpec, { mapOutput: ... })
|
|
57
|
+
*
|
|
58
|
+
* vs. the more verbose `subPipeline<MyOuter, MyInner>(...)`. For the lazy
|
|
59
|
+
* registry-lookup case, use `subPipeline` directly — the resolver form needs
|
|
60
|
+
* explicit generics anyway.
|
|
61
|
+
*/
|
|
62
|
+
export declare function subPipelineOf<TInnerCtx extends BasePipelineContext, TOuterCtx extends BasePipelineContext = BasePipelineContext>(name: string, source: {
|
|
63
|
+
phases: ReadonlyArray<Phase<TInnerCtx>>;
|
|
64
|
+
ctx: TInnerCtx;
|
|
65
|
+
}, mapping?: Omit<SubPipelineOptions<TOuterCtx, TInnerCtx>, 'pipeline'>): Phase<TOuterCtx>;
|
|
66
|
+
/**
|
|
67
|
+
* Imperative form: invoke an inner pipeline from inside a phase body.
|
|
68
|
+
* Returns the inner ctx (post-run) and the pipeline summary. Phase
|
|
69
|
+
* exceptions in the inner pipeline propagate as rejections.
|
|
70
|
+
*/
|
|
71
|
+
export declare function runSubPipeline<TInnerCtx extends BasePipelineContext>(source: SubPipelineSource<TInnerCtx>, options?: {
|
|
72
|
+
/** Optional outer signal to propagate into the inner pipeline's ctx. */
|
|
73
|
+
signal?: AbortSignal;
|
|
74
|
+
/** Optional override of the inner ctx (otherwise source's ctx is used). */
|
|
75
|
+
ctx?: TInnerCtx;
|
|
76
|
+
}): Promise<{
|
|
77
|
+
ctx: TInnerCtx;
|
|
78
|
+
summary: {
|
|
79
|
+
status: 'completed' | 'stopped';
|
|
80
|
+
reason?: string;
|
|
81
|
+
eventCount: number;
|
|
82
|
+
};
|
|
83
|
+
}>;
|
|
84
|
+
//# sourceMappingURL=sub-pipeline.d.ts.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* subPipeline — compose a registered (or inline) pipeline as a phase
|
|
3
|
+
* inside another pipeline.
|
|
4
|
+
*
|
|
5
|
+
* Two surface forms:
|
|
6
|
+
*
|
|
7
|
+
* - **`subPipeline(name, options)`** — higher-order pattern returning a
|
|
8
|
+
* `Phase<TOuterCtx>`. Compose like any other phase.
|
|
9
|
+
* - **`runSubPipeline(spec, options)`** — free function for imperative
|
|
10
|
+
* use inside phase bodies. Returns `{ ctx, summary }`.
|
|
11
|
+
*
|
|
12
|
+
* The inner pipeline gets:
|
|
13
|
+
* - a fresh `PipelineCache` (cache scopes are isolated)
|
|
14
|
+
* - the outer ctx's `signal` (cancellation propagates down)
|
|
15
|
+
*
|
|
16
|
+
* Events from the inner pipeline flatten into the outer event stream
|
|
17
|
+
* via `yield*` — JobStore consumers, SSE listeners, and the orchestrator
|
|
18
|
+
* see one continuous stream.
|
|
19
|
+
*/
|
|
20
|
+
import { runPipeline } from '../orchestrator.js';
|
|
21
|
+
import { PipelineCache } from '../cache.js';
|
|
22
|
+
/** A higher-order pattern returning a `Phase<TOuterCtx>`. */
|
|
23
|
+
export function subPipeline(name, options) {
|
|
24
|
+
return {
|
|
25
|
+
name,
|
|
26
|
+
async *run(outer) {
|
|
27
|
+
const source = typeof options.pipeline === 'function'
|
|
28
|
+
? options.pipeline()
|
|
29
|
+
: options.pipeline;
|
|
30
|
+
if (!source) {
|
|
31
|
+
throw new Error(`subPipeline "${name}": pipeline resolver returned undefined`);
|
|
32
|
+
}
|
|
33
|
+
const inner = options.mapInput
|
|
34
|
+
? options.mapInput(outer)
|
|
35
|
+
: source.ctx;
|
|
36
|
+
// Isolate the inner pipeline's cache; propagate the outer's signal.
|
|
37
|
+
inner.cache = new PipelineCache();
|
|
38
|
+
inner.signal = outer.signal;
|
|
39
|
+
yield* runPipeline(source.phases, inner);
|
|
40
|
+
options.mapOutput?.(outer, inner);
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Type-inferred convenience over `subPipeline` for the direct-object case.
|
|
46
|
+
* `TInnerCtx` is inferred from `source.ctx`, so callers only spell the outer
|
|
47
|
+
* ctx generic (and often not even that):
|
|
48
|
+
*
|
|
49
|
+
* subPipelineOf('inner', innerSpec, { mapOutput: ... })
|
|
50
|
+
*
|
|
51
|
+
* vs. the more verbose `subPipeline<MyOuter, MyInner>(...)`. For the lazy
|
|
52
|
+
* registry-lookup case, use `subPipeline` directly — the resolver form needs
|
|
53
|
+
* explicit generics anyway.
|
|
54
|
+
*/
|
|
55
|
+
export function subPipelineOf(name, source, mapping) {
|
|
56
|
+
return subPipeline(name, {
|
|
57
|
+
pipeline: source,
|
|
58
|
+
...mapping,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Imperative form: invoke an inner pipeline from inside a phase body.
|
|
63
|
+
* Returns the inner ctx (post-run) and the pipeline summary. Phase
|
|
64
|
+
* exceptions in the inner pipeline propagate as rejections.
|
|
65
|
+
*/
|
|
66
|
+
export async function runSubPipeline(source, options = {}) {
|
|
67
|
+
const resolved = typeof source === 'function' ? source() : source;
|
|
68
|
+
if (!resolved) {
|
|
69
|
+
throw new Error('runSubPipeline: pipeline resolver returned undefined');
|
|
70
|
+
}
|
|
71
|
+
const inner = options.ctx ?? resolved.ctx;
|
|
72
|
+
inner.cache = new PipelineCache();
|
|
73
|
+
if (options.signal)
|
|
74
|
+
inner.signal = options.signal;
|
|
75
|
+
let eventCount = 0;
|
|
76
|
+
let stopReason;
|
|
77
|
+
for await (const event of runPipeline(resolved.phases, inner)) {
|
|
78
|
+
eventCount++;
|
|
79
|
+
if (event.type === 'done') {
|
|
80
|
+
stopReason = event.reason;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return {
|
|
84
|
+
ctx: inner,
|
|
85
|
+
summary: stopReason !== undefined
|
|
86
|
+
? { status: 'stopped', reason: stopReason, eventCount }
|
|
87
|
+
: { status: 'completed', eventCount },
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=sub-pipeline.js.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* synthesize-with-followup — synthesizer reviews its own output and may
|
|
3
|
+
* request another round of upstream work.
|
|
4
|
+
*
|
|
5
|
+
* Loop:
|
|
6
|
+
* 1. Synthesizer produces draft text (typically streaming).
|
|
7
|
+
* 2. extractFollowUp inspects the draft for explicit "I need more on X".
|
|
8
|
+
* 3. If present and budget allows, doFollowUp runs whatever upstream phases
|
|
9
|
+
* need to re-run, then we loop.
|
|
10
|
+
* 4. Otherwise the loop exits and the final text is written to ctx.
|
|
11
|
+
*/
|
|
12
|
+
import type { BasePipelineContext, Phase, PipelineEvent } from '../phase.js';
|
|
13
|
+
export interface SynthesizeWithFollowupOptions<TCtx extends BasePipelineContext, TFollowUp> {
|
|
14
|
+
/**
|
|
15
|
+
* Run the synthesizer. May yield events (typically streamed `content`).
|
|
16
|
+
* Returns the final text via the generator's return value.
|
|
17
|
+
*/
|
|
18
|
+
synthesize: (ctx: TCtx, iteration: number) => AsyncGenerator<PipelineEvent, string, void>;
|
|
19
|
+
/**
|
|
20
|
+
* Inspect the synthesizer output. Return null if synthesis is complete,
|
|
21
|
+
* or a typed follow-up directive if more work is needed.
|
|
22
|
+
*/
|
|
23
|
+
extractFollowUp: (output: string) => TFollowUp | null;
|
|
24
|
+
/**
|
|
25
|
+
* Run whatever extra work the follow-up requested (often re-runs of
|
|
26
|
+
* upstream phases). May yield events.
|
|
27
|
+
*/
|
|
28
|
+
doFollowUp: (ctx: TCtx, followUp: TFollowUp, iteration: number) => AsyncGenerator<PipelineEvent, void, void>;
|
|
29
|
+
/** Stash the final synthesized text on ctx. */
|
|
30
|
+
writeTo: (ctx: TCtx, text: string) => void;
|
|
31
|
+
/** Cap iterations. Default 2 (one synthesis + one follow-up). */
|
|
32
|
+
maxIterations?: number;
|
|
33
|
+
}
|
|
34
|
+
export declare function synthesizeWithFollowup<TCtx extends BasePipelineContext, TFollowUp>(phaseName: string, options: SynthesizeWithFollowupOptions<TCtx, TFollowUp>): Phase<TCtx>;
|
|
35
|
+
//# sourceMappingURL=synthesize-with-followup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"synthesize-with-followup.d.ts","sourceRoot":"","sources":["../../src/patterns/synthesize-with-followup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE7E,MAAM,WAAW,6BAA6B,CAAC,IAAI,SAAS,mBAAmB,EAAE,SAAS;IACxF;;;OAGG;IACH,UAAU,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,KAAK,cAAc,CAAC,aAAa,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC;IAC1F;;;OAGG;IACH,eAAe,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,SAAS,GAAG,IAAI,CAAC;IACtD;;;OAGG;IACH,UAAU,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,KAAK,cAAc,CAAC,aAAa,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;IAC7G,+CAA+C;IAC/C,OAAO,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,iEAAiE;IACjE,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,wBAAgB,sBAAsB,CAAC,IAAI,SAAS,mBAAmB,EAAE,SAAS,EAChF,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,6BAA6B,CAAC,IAAI,EAAE,SAAS,CAAC,GACtD,KAAK,CAAC,IAAI,CAAC,CAmCb"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* synthesize-with-followup — synthesizer reviews its own output and may
|
|
3
|
+
* request another round of upstream work.
|
|
4
|
+
*
|
|
5
|
+
* Loop:
|
|
6
|
+
* 1. Synthesizer produces draft text (typically streaming).
|
|
7
|
+
* 2. extractFollowUp inspects the draft for explicit "I need more on X".
|
|
8
|
+
* 3. If present and budget allows, doFollowUp runs whatever upstream phases
|
|
9
|
+
* need to re-run, then we loop.
|
|
10
|
+
* 4. Otherwise the loop exits and the final text is written to ctx.
|
|
11
|
+
*/
|
|
12
|
+
export function synthesizeWithFollowup(phaseName, options) {
|
|
13
|
+
return {
|
|
14
|
+
name: phaseName,
|
|
15
|
+
async *run(ctx) {
|
|
16
|
+
const max = options.maxIterations ?? 2;
|
|
17
|
+
let finalText = '';
|
|
18
|
+
for (let iter = 0; iter < max; iter++) {
|
|
19
|
+
const synthGen = options.synthesize(ctx, iter);
|
|
20
|
+
let stepText = '';
|
|
21
|
+
while (true) {
|
|
22
|
+
const next = await synthGen.next();
|
|
23
|
+
if (next.done) {
|
|
24
|
+
stepText = next.value;
|
|
25
|
+
break;
|
|
26
|
+
}
|
|
27
|
+
yield next.value;
|
|
28
|
+
}
|
|
29
|
+
finalText = stepText;
|
|
30
|
+
const followUp = options.extractFollowUp(stepText);
|
|
31
|
+
if (!followUp || iter === max - 1)
|
|
32
|
+
break;
|
|
33
|
+
yield {
|
|
34
|
+
type: 'agent_activity',
|
|
35
|
+
agent: phaseName,
|
|
36
|
+
action: 'follow_up',
|
|
37
|
+
detail: `iteration ${iter + 1} requested more work`,
|
|
38
|
+
};
|
|
39
|
+
yield* options.doFollowUp(ctx, followUp, iter);
|
|
40
|
+
}
|
|
41
|
+
options.writeTo(ctx, finalText);
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=synthesize-with-followup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"synthesize-with-followup.js","sourceRoot":"","sources":["../../src/patterns/synthesize-with-followup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AA0BH,MAAM,UAAU,sBAAsB,CACpC,SAAiB,EACjB,OAAuD;IAEvD,OAAO;QACL,IAAI,EAAE,SAAS;QACf,KAAK,CAAC,CAAC,GAAG,CAAC,GAAG;YACZ,MAAM,GAAG,GAAG,OAAO,CAAC,aAAa,IAAI,CAAC,CAAC;YACvC,IAAI,SAAS,GAAG,EAAE,CAAC;YAEnB,KAAK,IAAI,IAAI,GAAG,CAAC,EAAE,IAAI,GAAG,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC;gBACtC,MAAM,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;gBAC/C,IAAI,QAAQ,GAAG,EAAE,CAAC;gBAClB,OAAO,IAAI,EAAE,CAAC;oBACZ,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;oBACnC,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;wBACd,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC;wBACtB,MAAM;oBACR,CAAC;oBACD,MAAM,IAAI,CAAC,KAAK,CAAC;gBACnB,CAAC;gBACD,SAAS,GAAG,QAAQ,CAAC;gBAErB,MAAM,QAAQ,GAAG,OAAO,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;gBACnD,IAAI,CAAC,QAAQ,IAAI,IAAI,KAAK,GAAG,GAAG,CAAC;oBAAE,MAAM;gBAEzC,MAAM;oBACJ,IAAI,EAAE,gBAAgB;oBACtB,KAAK,EAAE,SAAS;oBAChB,MAAM,EAAE,WAAW;oBACnB,MAAM,EAAE,aAAa,IAAI,GAAG,CAAC,sBAAsB;iBACpD,CAAC;gBACF,KAAK,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;YACjD,CAAC;YAED,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QAClC,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* while-condition — a general convergence loop.
|
|
3
|
+
*
|
|
4
|
+
* Runs `body` repeatedly while `predicate(ctx)` is true, capped at
|
|
5
|
+
* `maxIterations`. Predicate is async and runs *before* each iteration —
|
|
6
|
+
* an immediately-false predicate produces zero body executions, like a
|
|
7
|
+
* standard `while` loop.
|
|
8
|
+
*
|
|
9
|
+
* Exits via one of:
|
|
10
|
+
* - predicate returns false → emits a `data` event with key
|
|
11
|
+
* `${name}.converged` and value
|
|
12
|
+
* `{ iterations }`.
|
|
13
|
+
* - maxIterations reached → sets ctx.stop with a reason naming
|
|
14
|
+
* the pattern; emits `data` event
|
|
15
|
+
* `${name}.max-iterations`.
|
|
16
|
+
* - body sets ctx.stop → propagates immediately.
|
|
17
|
+
*
|
|
18
|
+
* Body composition: pass a list of phases — they run in order each
|
|
19
|
+
* iteration, sharing ctx. Use `parallelPhases` if you want them concurrent.
|
|
20
|
+
*/
|
|
21
|
+
import type { BasePipelineContext, Phase } from '../phase.js';
|
|
22
|
+
export interface WhileConditionOptions<TCtx extends BasePipelineContext> {
|
|
23
|
+
/** Predicate evaluated before each iteration. Loop continues while true. */
|
|
24
|
+
predicate: (ctx: TCtx) => boolean | Promise<boolean>;
|
|
25
|
+
/** Phases to run each iteration. */
|
|
26
|
+
body: Phase<TCtx>[];
|
|
27
|
+
/** Hard cap on iterations to prevent runaway loops. Default: 10. */
|
|
28
|
+
maxIterations?: number;
|
|
29
|
+
}
|
|
30
|
+
export declare function whileCondition<TCtx extends BasePipelineContext>(phaseName: string, options: WhileConditionOptions<TCtx>): Phase<TCtx>;
|
|
31
|
+
//# sourceMappingURL=while-condition.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"while-condition.d.ts","sourceRoot":"","sources":["../../src/patterns/while-condition.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,KAAK,EAAiB,MAAM,aAAa,CAAC;AAE7E,MAAM,WAAW,qBAAqB,CAAC,IAAI,SAAS,mBAAmB;IACrE,4EAA4E;IAC5E,SAAS,EAAE,CAAC,GAAG,EAAE,IAAI,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACrD,oCAAoC;IACpC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;IACpB,oEAAoE;IACpE,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,wBAAgB,cAAc,CAAC,IAAI,SAAS,mBAAmB,EAC7D,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,qBAAqB,CAAC,IAAI,CAAC,GACnC,KAAK,CAAC,IAAI,CAAC,CA0Cb"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* while-condition — a general convergence loop.
|
|
3
|
+
*
|
|
4
|
+
* Runs `body` repeatedly while `predicate(ctx)` is true, capped at
|
|
5
|
+
* `maxIterations`. Predicate is async and runs *before* each iteration —
|
|
6
|
+
* an immediately-false predicate produces zero body executions, like a
|
|
7
|
+
* standard `while` loop.
|
|
8
|
+
*
|
|
9
|
+
* Exits via one of:
|
|
10
|
+
* - predicate returns false → emits a `data` event with key
|
|
11
|
+
* `${name}.converged` and value
|
|
12
|
+
* `{ iterations }`.
|
|
13
|
+
* - maxIterations reached → sets ctx.stop with a reason naming
|
|
14
|
+
* the pattern; emits `data` event
|
|
15
|
+
* `${name}.max-iterations`.
|
|
16
|
+
* - body sets ctx.stop → propagates immediately.
|
|
17
|
+
*
|
|
18
|
+
* Body composition: pass a list of phases — they run in order each
|
|
19
|
+
* iteration, sharing ctx. Use `parallelPhases` if you want them concurrent.
|
|
20
|
+
*/
|
|
21
|
+
export function whileCondition(phaseName, options) {
|
|
22
|
+
const max = options.maxIterations ?? 10;
|
|
23
|
+
return {
|
|
24
|
+
name: phaseName,
|
|
25
|
+
async *run(ctx) {
|
|
26
|
+
let iterations = 0;
|
|
27
|
+
while (iterations < max) {
|
|
28
|
+
const shouldContinue = await options.predicate(ctx);
|
|
29
|
+
if (!shouldContinue) {
|
|
30
|
+
yield {
|
|
31
|
+
type: 'data',
|
|
32
|
+
key: `${phaseName}.converged`,
|
|
33
|
+
value: { iterations },
|
|
34
|
+
};
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
yield {
|
|
38
|
+
type: 'agent_activity',
|
|
39
|
+
agent: phaseName,
|
|
40
|
+
action: 'iteration',
|
|
41
|
+
detail: `${iterations + 1}/${max}`,
|
|
42
|
+
};
|
|
43
|
+
for (const phase of options.body) {
|
|
44
|
+
yield* phase.run(ctx);
|
|
45
|
+
if (ctx.stop)
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
iterations++;
|
|
49
|
+
}
|
|
50
|
+
yield {
|
|
51
|
+
type: 'data',
|
|
52
|
+
key: `${phaseName}.max-iterations`,
|
|
53
|
+
value: { iterations },
|
|
54
|
+
};
|
|
55
|
+
ctx.stop = { reason: `${phaseName}: max iterations (${max}) reached` };
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=while-condition.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"while-condition.js","sourceRoot":"","sources":["../../src/patterns/while-condition.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAaH,MAAM,UAAU,cAAc,CAC5B,SAAiB,EACjB,OAAoC;IAEpC,MAAM,GAAG,GAAG,OAAO,CAAC,aAAa,IAAI,EAAE,CAAC;IAExC,OAAO;QACL,IAAI,EAAE,SAAS;QACf,KAAK,CAAC,CAAC,GAAG,CAAC,GAAG;YACZ,IAAI,UAAU,GAAG,CAAC,CAAC;YAEnB,OAAO,UAAU,GAAG,GAAG,EAAE,CAAC;gBACxB,MAAM,cAAc,GAAG,MAAM,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;gBACpD,IAAI,CAAC,cAAc,EAAE,CAAC;oBACpB,MAAM;wBACJ,IAAI,EAAE,MAAM;wBACZ,GAAG,EAAE,GAAG,SAAS,YAAY;wBAC7B,KAAK,EAAE,EAAE,UAAU,EAAE;qBACtB,CAAC;oBACF,OAAO;gBACT,CAAC;gBAED,MAAM;oBACJ,IAAI,EAAE,gBAAgB;oBACtB,KAAK,EAAE,SAAS;oBAChB,MAAM,EAAE,WAAW;oBACnB,MAAM,EAAE,GAAG,UAAU,GAAG,CAAC,IAAI,GAAG,EAAE;iBACnC,CAAC;gBAEF,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;oBACjC,KAAK,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;oBACtB,IAAI,GAAG,CAAC,IAAI;wBAAE,OAAO;gBACvB,CAAC;gBAED,UAAU,EAAE,CAAC;YACf,CAAC;YAED,MAAM;gBACJ,IAAI,EAAE,MAAM;gBACZ,GAAG,EAAE,GAAG,SAAS,iBAAiB;gBAClC,KAAK,EAAE,EAAE,UAAU,EAAE;aACtB,CAAC;YACF,GAAG,CAAC,IAAI,GAAG,EAAE,MAAM,EAAE,GAAG,SAAS,qBAAqB,GAAG,WAAW,EAAE,CAAC;QACzE,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* with-retry — higher-order phase wrapper for retrying flaky work.
|
|
3
|
+
*
|
|
4
|
+
* Wraps any `Phase` and retries it on failure. Failure means either:
|
|
5
|
+
* - the inner phase throws an exception, OR
|
|
6
|
+
* - the inner phase yields then sets `ctx.stop` (a clean failure signal)
|
|
7
|
+
*
|
|
8
|
+
* Both default to retryable. Override with `isFailure(ctx, error?)` if a
|
|
9
|
+
* specific `ctx.stop.reason` should *not* trigger a retry (e.g. user
|
|
10
|
+
* cancellation, terminal validation error).
|
|
11
|
+
*
|
|
12
|
+
* Retries are bounded by `maxAttempts` (default 3) and spaced with
|
|
13
|
+
* exponential backoff starting at `baseDelayMs` (default 1000).
|
|
14
|
+
*
|
|
15
|
+
* Idempotence is the caller's responsibility. The wrapper does NOT
|
|
16
|
+
* snapshot/restore ctx between attempts — a partially-applied mutation
|
|
17
|
+
* from a failed attempt is visible to the retry. Pass `resetState` if
|
|
18
|
+
* you need to undo partial work before each retry.
|
|
19
|
+
*
|
|
20
|
+
* Events emitted by the inner phase pass through unmodified. The wrapper
|
|
21
|
+
* additionally emits `data` events with key `${phase.name}.attempt`.
|
|
22
|
+
*/
|
|
23
|
+
import type { BasePipelineContext, Phase } from '../phase.js';
|
|
24
|
+
export interface WithRetryOptions<TCtx extends BasePipelineContext> {
|
|
25
|
+
/** Maximum total attempts including the first. Default: 3. */
|
|
26
|
+
maxAttempts?: number;
|
|
27
|
+
/** Base delay for exponential backoff, in milliseconds. Default: 1000. */
|
|
28
|
+
baseDelayMs?: number;
|
|
29
|
+
/** Decide whether the most recent attempt counts as a failure. Default: ctx.stop is set OR an error was thrown. */
|
|
30
|
+
isFailure?: (ctx: TCtx, error?: unknown) => boolean;
|
|
31
|
+
/** Called before each retry (not before the first attempt). */
|
|
32
|
+
onRetry?: (ctx: TCtx, attempt: number, error?: unknown) => void;
|
|
33
|
+
/** Called between attempts. Use to undo partial mutations from the failed attempt. */
|
|
34
|
+
resetState?: (ctx: TCtx) => void;
|
|
35
|
+
}
|
|
36
|
+
export declare function withRetry<TCtx extends BasePipelineContext>(phase: Phase<TCtx>, options?: WithRetryOptions<TCtx>): Phase<TCtx>;
|
|
37
|
+
//# sourceMappingURL=with-retry.d.ts.map
|
|
@@ -0,0 +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"}
|