flowneer 0.9.2 → 0.9.4
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/{FlowBuilder-G67AbbRt.d.ts → FlowBuilder-8kwREeyD.d.ts} +37 -11
- package/dist/index.d.ts +1 -1
- package/dist/index.js +13 -4
- package/dist/plugins/agent/index.d.ts +7 -1
- package/dist/plugins/dev/index.d.ts +103 -24
- package/dist/plugins/dev/index.js +117 -27
- package/dist/plugins/eval/index.d.ts +1 -1
- package/dist/plugins/graph/index.d.ts +1 -1
- package/dist/plugins/graph/index.js +7 -2
- package/dist/plugins/index.d.ts +2 -2
- package/dist/plugins/index.js +120 -77
- package/dist/plugins/llm/index.d.ts +29 -1
- package/dist/plugins/memory/index.d.ts +5 -1
- package/dist/plugins/messaging/index.d.ts +9 -1
- package/dist/plugins/observability/index.d.ts +13 -1
- package/dist/plugins/output/index.d.ts +1 -1
- package/dist/plugins/persistence/index.d.ts +168 -34
- package/dist/plugins/persistence/index.js +201 -62
- package/dist/plugins/resilience/index.d.ts +14 -1
- package/dist/plugins/telemetry/index.d.ts +1 -1
- package/dist/plugins/tools/index.d.ts +8 -1
- package/dist/presets/agent/index.d.ts +7 -1
- package/dist/presets/agent/index.js +13 -4
- package/dist/presets/config/index.d.ts +1 -1
- package/dist/presets/config/index.js +13 -4
- package/dist/presets/index.d.ts +1 -1
- package/dist/presets/index.js +13 -4
- package/dist/presets/pipeline/index.d.ts +1 -1
- package/dist/presets/pipeline/index.js +13 -4
- package/dist/presets/rag/index.d.ts +1 -1
- package/dist/presets/rag/index.js +13 -4
- package/dist/src/index.d.ts +2 -2
- package/dist/src/index.js +13 -4
- package/package.json +1 -1
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extendable shared-state interface augmented by each plugin via declaration
|
|
3
|
+
* merging. Extend your state type with this to get all plugin-provided keys
|
|
4
|
+
* typed and documented automatically — no manual `__*` declarations needed.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* import type { AugmentedState } from "flowneer";
|
|
8
|
+
* interface MyState extends AugmentedState {
|
|
9
|
+
* topic: string;
|
|
10
|
+
* results: string[];
|
|
11
|
+
* }
|
|
12
|
+
*/
|
|
13
|
+
interface AugmentedState {
|
|
14
|
+
}
|
|
1
15
|
/**
|
|
2
16
|
* Generic validator interface — structurally compatible with Zod, ArkType,
|
|
3
17
|
* Valibot, or any custom implementation that exposes `.parse(input)`.
|
|
@@ -105,8 +119,18 @@ interface FlowHooks<S = any, P extends Record<string, unknown> = Record<string,
|
|
|
105
119
|
* `fnIndex` is the position within the fns array.
|
|
106
120
|
*/
|
|
107
121
|
wrapParallelFn?: (meta: StepMeta, fnIndex: number, next: () => Promise<void>, shared: S, params: P) => Promise<void>;
|
|
108
|
-
onError?: (meta: StepMeta, error: unknown, shared: S, params: P) => void
|
|
122
|
+
onError?: (meta: StepMeta, error: unknown, shared: S, params: P) => void | Promise<void>;
|
|
109
123
|
afterFlow?: (shared: S, params: P) => void | Promise<void>;
|
|
124
|
+
/**
|
|
125
|
+
* Fires after each loop iteration completes. `iteration` is zero-based.
|
|
126
|
+
* Only fires for `.loop()` steps, not `.batch()` or `.parallel()`.
|
|
127
|
+
*/
|
|
128
|
+
onLoopIteration?: (meta: StepMeta, iteration: number, shared: S, params: P) => void | Promise<void>;
|
|
129
|
+
/**
|
|
130
|
+
* Fires when a goto jump resolves to an anchor (i.e. a step returned `"#anchorName"`).
|
|
131
|
+
* `anchorName` is the anchor label without the `#` prefix.
|
|
132
|
+
*/
|
|
133
|
+
onAnchorHit?: (anchorName: string, shared: S, params: P) => void | Promise<void>;
|
|
110
134
|
}
|
|
111
135
|
/**
|
|
112
136
|
* A plugin is an object whose keys become methods on a `FlowBuilder.extend()` subclass prototype.
|
|
@@ -120,6 +144,17 @@ interface FlowHooks<S = any, P extends Record<string, unknown> = Record<string,
|
|
|
120
144
|
* ```
|
|
121
145
|
*/
|
|
122
146
|
type FlowneerPlugin = Record<string, (this: FlowBuilder<any, any>, ...args: any[]) => any>;
|
|
147
|
+
type ResolvedHooks<S, P extends Record<string, unknown>> = {
|
|
148
|
+
beforeFlow: NonNullable<FlowHooks<S, P>["beforeFlow"]>[];
|
|
149
|
+
beforeStep: NonNullable<FlowHooks<S, P>["beforeStep"]>[];
|
|
150
|
+
wrapStep: NonNullable<FlowHooks<S, P>["wrapStep"]>[];
|
|
151
|
+
afterStep: NonNullable<FlowHooks<S, P>["afterStep"]>[];
|
|
152
|
+
wrapParallelFn: NonNullable<FlowHooks<S, P>["wrapParallelFn"]>[];
|
|
153
|
+
onError: NonNullable<FlowHooks<S, P>["onError"]>[];
|
|
154
|
+
afterFlow: NonNullable<FlowHooks<S, P>["afterFlow"]>[];
|
|
155
|
+
onLoopIteration: NonNullable<FlowHooks<S, P>["onLoopIteration"]>[];
|
|
156
|
+
onAnchorHit: NonNullable<FlowHooks<S, P>["onAnchorHit"]>[];
|
|
157
|
+
};
|
|
123
158
|
|
|
124
159
|
interface FnStep<S, P extends Record<string, unknown>> {
|
|
125
160
|
type: "fn";
|
|
@@ -196,15 +231,6 @@ interface DagStep<S, P extends Record<string, unknown>> {
|
|
|
196
231
|
}
|
|
197
232
|
type Step<S, P extends Record<string, unknown>> = FnStep<S, P> | BranchStep<S, P> | LoopStep<S, P> | BatchStep<S, P> | ParallelStep<S, P> | AnchorStep | DagStep<S, P>;
|
|
198
233
|
|
|
199
|
-
type ResolvedHooks<S, P extends Record<string, unknown>> = {
|
|
200
|
-
beforeFlow: NonNullable<FlowHooks<S, P>["beforeFlow"]>[];
|
|
201
|
-
beforeStep: NonNullable<FlowHooks<S, P>["beforeStep"]>[];
|
|
202
|
-
wrapStep: NonNullable<FlowHooks<S, P>["wrapStep"]>[];
|
|
203
|
-
afterStep: NonNullable<FlowHooks<S, P>["afterStep"]>[];
|
|
204
|
-
wrapParallelFn: NonNullable<FlowHooks<S, P>["wrapParallelFn"]>[];
|
|
205
|
-
onError: NonNullable<FlowHooks<S, P>["onError"]>[];
|
|
206
|
-
afterFlow: NonNullable<FlowHooks<S, P>["afterFlow"]>[];
|
|
207
|
-
};
|
|
208
234
|
/**
|
|
209
235
|
* Runtime context passed to every registered step handler.
|
|
210
236
|
* Full access to the builder so handlers can run sub-flows etc.
|
|
@@ -395,4 +421,4 @@ declare class FlowBuilder<S = any, P extends Record<string, unknown> = Record<st
|
|
|
395
421
|
private _addFn;
|
|
396
422
|
}
|
|
397
423
|
|
|
398
|
-
export { type AnchorStep as A, type BatchStep as B, CoreFlowBuilder as C, type DagStep as D, FlowBuilder as F, type LoopStep as L, type NodeFn as N, type ParallelStep as P, type ResolvedHooks as R, type StepFilter as S, type Validator as V, type FlowneerPlugin as a, type NodeOptions as b, type FlowHooks as c, type StepMeta as d, type
|
|
424
|
+
export { type AnchorStep as A, type BatchStep as B, CoreFlowBuilder as C, type DagStep as D, FlowBuilder as F, type LoopStep as L, type NodeFn as N, type ParallelStep as P, type ResolvedHooks as R, type StepFilter as S, type Validator as V, type FlowneerPlugin as a, type NodeOptions as b, type FlowHooks as c, type StepMeta as d, type AugmentedState as e, type BranchStep as f, type FnStep as g, type NumberOrFn as h, type RunOptions as i, type Step as j, type StepContext as k, type StepHandler as l, type StreamEvent as m };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { F as FlowBuilder, c as FlowHooks, a as FlowneerPlugin, N as NodeFn, b as NodeOptions,
|
|
1
|
+
export { F as FlowBuilder, c as FlowHooks, a as FlowneerPlugin, N as NodeFn, b as NodeOptions, h as NumberOrFn, i as RunOptions, d as StepMeta, m as StreamEvent, V as Validator } from './FlowBuilder-8kwREeyD.js';
|
|
2
2
|
export { Fragment, fragment } from './src/index.js';
|
|
3
3
|
export { F as FlowError, I as InterruptError } from './errors-u-hq7p5N.js';
|
package/dist/index.js
CHANGED
|
@@ -97,6 +97,7 @@ function applyStepFilter(hooks, filter) {
|
|
|
97
97
|
wrap("onError");
|
|
98
98
|
wrap("wrapStep", (_m, next) => next());
|
|
99
99
|
wrap("wrapParallelFn", (_m, _fi, next) => next());
|
|
100
|
+
wrap("onLoopIteration");
|
|
100
101
|
return hooks;
|
|
101
102
|
}
|
|
102
103
|
function buildHookCache(list) {
|
|
@@ -108,7 +109,9 @@ function buildHookCache(list) {
|
|
|
108
109
|
afterStep: pick("afterStep"),
|
|
109
110
|
wrapParallelFn: pick("wrapParallelFn"),
|
|
110
111
|
onError: pick("onError"),
|
|
111
|
-
afterFlow: pick("afterFlow")
|
|
112
|
+
afterFlow: pick("afterFlow"),
|
|
113
|
+
onLoopIteration: pick("onLoopIteration"),
|
|
114
|
+
onAnchorHit: pick("onAnchorHit")
|
|
112
115
|
};
|
|
113
116
|
}
|
|
114
117
|
var CoreFlowBuilder = class _CoreFlowBuilder {
|
|
@@ -325,10 +328,12 @@ var CoreFlowBuilder = class _CoreFlowBuilder {
|
|
|
325
328
|
);
|
|
326
329
|
}
|
|
327
330
|
i = target;
|
|
331
|
+
for (const h of hooks.onAnchorHit)
|
|
332
|
+
await h(gotoTarget, shared, params);
|
|
328
333
|
}
|
|
329
334
|
} catch (err) {
|
|
330
335
|
if (err instanceof InterruptError) throw err;
|
|
331
|
-
for (const h of hooks.onError) h(meta, err, shared, params);
|
|
336
|
+
for (const h of hooks.onError) await h(meta, err, shared, params);
|
|
332
337
|
if (err instanceof FlowError) throw err;
|
|
333
338
|
const labelPart = stepLabel ? `"${stepLabel}" ` : "";
|
|
334
339
|
const label = step.type === "fn" ? `${labelPart}step ${i}` : `${labelPart}${step.type} (step ${i})`;
|
|
@@ -416,12 +421,16 @@ var branchHandler = async (step, { shared, params }) => {
|
|
|
416
421
|
};
|
|
417
422
|
|
|
418
423
|
// src/core/steps/loop.ts
|
|
419
|
-
var loopHandler = async (step, { shared, params, signal, meta, builder }) => {
|
|
420
|
-
|
|
424
|
+
var loopHandler = async (step, { shared, params, signal, meta, hooks, builder }) => {
|
|
425
|
+
let iteration = 0;
|
|
426
|
+
while (await step.condition(shared, params)) {
|
|
421
427
|
await builder._runSub(
|
|
422
428
|
`loop (step ${meta.index})`,
|
|
423
429
|
() => step.body._execute(shared, params, signal)
|
|
424
430
|
);
|
|
431
|
+
for (const h of hooks.onLoopIteration)
|
|
432
|
+
await h(meta, iteration++, shared, params);
|
|
433
|
+
}
|
|
425
434
|
return void 0;
|
|
426
435
|
};
|
|
427
436
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { F as FlowBuilder, a as FlowneerPlugin } from '../../FlowBuilder-
|
|
1
|
+
import { F as FlowBuilder, a as FlowneerPlugin } from '../../FlowBuilder-8kwREeyD.js';
|
|
2
2
|
|
|
3
3
|
interface HumanNodeOptions<S = any, P extends Record<string, unknown> = Record<string, unknown>> {
|
|
4
4
|
/**
|
|
@@ -45,6 +45,12 @@ declare module "../../Flowneer" {
|
|
|
45
45
|
*/
|
|
46
46
|
humanNode(options?: HumanNodeOptions<S, P>): this;
|
|
47
47
|
}
|
|
48
|
+
interface AugmentedState {
|
|
49
|
+
/** Prompt/question for the human reviewer. Written by `.humanNode()` before interrupting. */
|
|
50
|
+
__humanPrompt?: string;
|
|
51
|
+
/** Human-provided response. Write this onto the saved shared state before calling `resumeFlow()`. */
|
|
52
|
+
__humanFeedback?: string;
|
|
53
|
+
}
|
|
48
54
|
}
|
|
49
55
|
declare const withHumanNode: FlowneerPlugin;
|
|
50
56
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as FlowneerPlugin, N as NodeFn, b as NodeOptions, S as StepFilter } from '../../FlowBuilder-
|
|
1
|
+
import { a as FlowneerPlugin, N as NodeFn, b as NodeOptions, S as StepFilter } from '../../FlowBuilder-8kwREeyD.js';
|
|
2
2
|
|
|
3
3
|
declare module "../../Flowneer" {
|
|
4
4
|
interface FlowBuilder<S, P> {
|
|
@@ -130,39 +130,118 @@ declare module "../../Flowneer" {
|
|
|
130
130
|
}
|
|
131
131
|
declare const withFlowAnalyzer: FlowneerPlugin;
|
|
132
132
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
133
|
+
/** Per-step performance snapshot recorded by `.withPerfAnalyzer()`. */
|
|
134
|
+
interface StepPerfStats {
|
|
135
|
+
/** Step index (0-based). */
|
|
136
|
+
index: number;
|
|
137
|
+
/** Step type: "fn" | "branch" | "loop" | "batch" | "parallel" | "dag". */
|
|
138
|
+
type: string;
|
|
139
|
+
/** Step label if set via `NodeOptions.label`. */
|
|
140
|
+
label?: string;
|
|
141
|
+
/** Wall-clock duration in ms (high-res via `performance.now()`). */
|
|
142
|
+
durationMs: number;
|
|
143
|
+
/** User-space CPU time consumed during this step (ms). 0 on non-Node runtimes. */
|
|
144
|
+
cpuUserMs: number;
|
|
145
|
+
/** Kernel CPU time consumed during this step (ms). 0 on non-Node runtimes. */
|
|
146
|
+
cpuSystemMs: number;
|
|
147
|
+
/** V8 heap used at step start (bytes). */
|
|
148
|
+
heapUsedBefore: number;
|
|
149
|
+
/** V8 heap used at step end (bytes). */
|
|
150
|
+
heapUsedAfter: number;
|
|
151
|
+
/**
|
|
152
|
+
* Net change in V8 heap usage (bytes, positive = allocated, negative = freed
|
|
153
|
+
* due to a GC cycle that completed during the step).
|
|
154
|
+
*/
|
|
155
|
+
heapDeltaBytes: number;
|
|
156
|
+
/** Net change in Resident Set Size (bytes). */
|
|
157
|
+
rssDeltaBytes: number;
|
|
158
|
+
/** Net change in external (C++ / Buffer) memory bound to V8 (bytes). */
|
|
159
|
+
externalDeltaBytes: number;
|
|
160
|
+
/**
|
|
161
|
+
* Number of GC events accumulated since last step end. Best-effort; see
|
|
162
|
+
* module note regarding async PerformanceObserver delivery.
|
|
163
|
+
*/
|
|
164
|
+
gcCount: number;
|
|
165
|
+
/** Total GC pause duration attributed to this step (ms). Best-effort. */
|
|
166
|
+
gcDurationMs: number;
|
|
167
|
+
/** `true` if the step threw an error (stats still recorded via finally). */
|
|
168
|
+
threw: boolean;
|
|
169
|
+
}
|
|
170
|
+
/** Flow-level performance summary written to `shared.__perfReport`. */
|
|
171
|
+
interface PerfReport {
|
|
172
|
+
/** Sum of all step `durationMs` (includes parallel overlap). */
|
|
173
|
+
totalDurationMs: number;
|
|
174
|
+
/** Sum of all step `cpuUserMs`. */
|
|
175
|
+
totalCpuUserMs: number;
|
|
176
|
+
/** Sum of all step `cpuSystemMs`. */
|
|
177
|
+
totalCpuSystemMs: number;
|
|
178
|
+
/** Sum of all GC pause durations across the flow (ms). */
|
|
179
|
+
totalGcDurationMs: number;
|
|
180
|
+
/** Total GC event count during the flow. */
|
|
181
|
+
totalGcCount: number;
|
|
182
|
+
/** Highest `heapUsedAfter` seen across all steps (bytes). */
|
|
183
|
+
peakHeapUsedBytes: number;
|
|
184
|
+
/** All per-step stats in execution order. */
|
|
185
|
+
steps: StepPerfStats[];
|
|
186
|
+
/** The step with the longest wall-clock duration, or `null` if no steps ran. */
|
|
187
|
+
slowest: StepPerfStats | null;
|
|
188
|
+
/** The step with the largest heap delta, or `null` if no steps ran. */
|
|
189
|
+
heaviest: StepPerfStats | null;
|
|
190
|
+
}
|
|
191
|
+
interface PerfAnalyzerOptions {
|
|
192
|
+
/**
|
|
193
|
+
* Track GC pause events via `PerformanceObserver`. Requires Node.js.
|
|
194
|
+
* @default true
|
|
195
|
+
*/
|
|
196
|
+
trackGc?: boolean;
|
|
197
|
+
/**
|
|
198
|
+
* Called with the final `PerfReport` in `afterFlow`.
|
|
199
|
+
* Use this to log, persist, or ship metrics — formatting is left to the caller.
|
|
200
|
+
*/
|
|
201
|
+
onReport?: (report: PerfReport) => void;
|
|
142
202
|
}
|
|
143
203
|
declare module "../../Flowneer" {
|
|
144
204
|
interface FlowBuilder<S, P> {
|
|
145
205
|
/**
|
|
146
|
-
*
|
|
147
|
-
*
|
|
206
|
+
* Profiles each step using Node.js built-in performance APIs — no external
|
|
207
|
+
* dependencies.
|
|
148
208
|
*
|
|
149
|
-
*
|
|
150
|
-
*
|
|
209
|
+
* Per step, records:
|
|
210
|
+
* - Wall-clock duration (`performance.now()`)
|
|
211
|
+
* - CPU user + system time (`process.cpuUsage()`)
|
|
212
|
+
* - Heap used delta (`process.memoryUsage().heapUsed`)
|
|
213
|
+
* - RSS and external memory delta
|
|
214
|
+
* - GC pause count + duration (`PerformanceObserver`, best-effort)
|
|
215
|
+
*
|
|
216
|
+
* Results are written to `shared.__perfStats` (array, in execution order)
|
|
217
|
+
* and `shared.__perfReport` (flow summary) when the flow completes.
|
|
151
218
|
*
|
|
152
219
|
* @example
|
|
153
|
-
*
|
|
154
|
-
*
|
|
220
|
+
* const flow = new AppFlow<State>()
|
|
221
|
+
* .withPerfAnalyzer({
|
|
222
|
+
* onReport: (r) => console.log(JSON.stringify(r, null, 2)),
|
|
223
|
+
* })
|
|
224
|
+
* .then(fetchData, { label: "fetch" })
|
|
225
|
+
* .then(callLlm, { label: "llm:generate" })
|
|
226
|
+
* .then(save, { label: "save" });
|
|
227
|
+
*
|
|
228
|
+
* await flow.run(shared);
|
|
229
|
+
* // shared.__perfReport.slowest → { label: "llm:generate", durationMs: ... }
|
|
230
|
+
* // shared.__perfStats[0] → { heapDeltaBytes: 2621440, cpuUserMs: 12 … }
|
|
155
231
|
*
|
|
156
232
|
* @example
|
|
157
|
-
* //
|
|
158
|
-
*
|
|
159
|
-
* .withDebugger(["llm:*"], { beforeStep: true, afterStep: true })
|
|
160
|
-
* .then(callLlm)
|
|
161
|
-
* .run(shared);
|
|
233
|
+
* // Profile only LLM steps
|
|
234
|
+
* flow.withPerfAnalyzer({}, ["llm:*"])
|
|
162
235
|
*/
|
|
163
|
-
|
|
236
|
+
withPerfAnalyzer(options?: PerfAnalyzerOptions, filter?: StepFilter): this;
|
|
237
|
+
}
|
|
238
|
+
interface AugmentedState {
|
|
239
|
+
/** Per-step perf stats written by `.withPerfAnalyzer()`. In execution order. */
|
|
240
|
+
__perfStats?: StepPerfStats[];
|
|
241
|
+
/** Flow-level perf summary written by `.withPerfAnalyzer()` on flow completion. */
|
|
242
|
+
__perfReport?: PerfReport;
|
|
164
243
|
}
|
|
165
244
|
}
|
|
166
|
-
declare const
|
|
245
|
+
declare const withPerfAnalyzer: FlowneerPlugin;
|
|
167
246
|
|
|
168
|
-
export { type
|
|
247
|
+
export { type PathMap, type PathNode, type PerfAnalyzerOptions, type PerfReport, type StepPerfStats, type TraceEvent, type TraceHandle, type TraceReport, withAtomicUpdates, withDryRun, withFlowAnalyzer, withMocks, withPerfAnalyzer, withStepLimit };
|
|
@@ -180,41 +180,131 @@ var withFlowAnalyzer = {
|
|
|
180
180
|
}
|
|
181
181
|
};
|
|
182
182
|
|
|
183
|
-
// plugins/dev/
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
183
|
+
// plugins/dev/withPerfAnalyzer.ts
|
|
184
|
+
import { performance, PerformanceObserver } from "perf_hooks";
|
|
185
|
+
function cpuUsage() {
|
|
186
|
+
return process.cpuUsage?.() ?? {
|
|
187
|
+
user: 0,
|
|
188
|
+
system: 0
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
function cpuUsageDelta(start) {
|
|
192
|
+
return process.cpuUsage?.(start) ?? { user: 0, system: 0 };
|
|
193
|
+
}
|
|
194
|
+
function memUsage() {
|
|
195
|
+
return process.memoryUsage?.() ?? {
|
|
196
|
+
rss: 0,
|
|
197
|
+
heapTotal: 0,
|
|
198
|
+
heapUsed: 0,
|
|
199
|
+
external: 0,
|
|
200
|
+
arrayBuffers: 0
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
var withPerfAnalyzer = {
|
|
204
|
+
withPerfAnalyzer(options = {}, filter) {
|
|
205
|
+
const { trackGc = true, onReport } = options;
|
|
206
|
+
const gcLog = [];
|
|
207
|
+
let gcObserver = null;
|
|
208
|
+
if (trackGc) {
|
|
209
|
+
try {
|
|
210
|
+
gcObserver = new PerformanceObserver((list) => {
|
|
211
|
+
for (const entry of list.getEntries()) {
|
|
212
|
+
gcLog.push({
|
|
213
|
+
startTime: entry.startTime,
|
|
214
|
+
duration: entry.duration
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
});
|
|
218
|
+
gcObserver.observe({ entryTypes: ["gc"] });
|
|
219
|
+
} catch {
|
|
220
|
+
}
|
|
208
221
|
}
|
|
209
|
-
|
|
222
|
+
const snapshots = /* @__PURE__ */ new Map();
|
|
223
|
+
this._setHooks(
|
|
224
|
+
{
|
|
225
|
+
wrapStep: async (meta, next, shared) => {
|
|
226
|
+
const gcMsBefore = gcLog.reduce((a, e) => a + e.duration, 0);
|
|
227
|
+
const t0 = performance.now();
|
|
228
|
+
const cpu0 = cpuUsage();
|
|
229
|
+
const mem0 = memUsage();
|
|
230
|
+
snapshots.set(meta.index, {
|
|
231
|
+
t0,
|
|
232
|
+
cpu0,
|
|
233
|
+
mem0,
|
|
234
|
+
gcLenBefore: gcLog.length,
|
|
235
|
+
gcMsBefore
|
|
236
|
+
});
|
|
237
|
+
let threw = false;
|
|
238
|
+
try {
|
|
239
|
+
await next();
|
|
240
|
+
} catch (e) {
|
|
241
|
+
threw = true;
|
|
242
|
+
throw e;
|
|
243
|
+
} finally {
|
|
244
|
+
const durationMs = performance.now() - t0;
|
|
245
|
+
const cpuDelta = cpuUsageDelta(cpu0);
|
|
246
|
+
const mem1 = memUsage();
|
|
247
|
+
const snap = snapshots.get(meta.index);
|
|
248
|
+
snapshots.delete(meta.index);
|
|
249
|
+
const gcMsAfter = gcLog.reduce((a, e) => a + e.duration, 0);
|
|
250
|
+
const gcCountAfter = gcLog.length;
|
|
251
|
+
const gcLenBefore = snap?.gcLenBefore ?? gcLog.length;
|
|
252
|
+
const gcMsSnap = snap?.gcMsBefore ?? gcMsAfter;
|
|
253
|
+
const stat = {
|
|
254
|
+
index: meta.index,
|
|
255
|
+
type: meta.type,
|
|
256
|
+
label: meta.label,
|
|
257
|
+
durationMs,
|
|
258
|
+
cpuUserMs: cpuDelta.user / 1e3,
|
|
259
|
+
cpuSystemMs: cpuDelta.system / 1e3,
|
|
260
|
+
heapUsedBefore: mem0.heapUsed,
|
|
261
|
+
heapUsedAfter: mem1.heapUsed,
|
|
262
|
+
heapDeltaBytes: mem1.heapUsed - mem0.heapUsed,
|
|
263
|
+
rssDeltaBytes: mem1.rss - mem0.rss,
|
|
264
|
+
externalDeltaBytes: mem1.external - mem0.external,
|
|
265
|
+
gcCount: gcCountAfter - gcLenBefore,
|
|
266
|
+
gcDurationMs: gcMsAfter - gcMsSnap,
|
|
267
|
+
threw
|
|
268
|
+
};
|
|
269
|
+
if (!shared.__perfStats) shared.__perfStats = [];
|
|
270
|
+
shared.__perfStats.push(stat);
|
|
271
|
+
}
|
|
272
|
+
},
|
|
273
|
+
afterFlow: (shared) => {
|
|
274
|
+
gcObserver?.disconnect();
|
|
275
|
+
const stats = shared.__perfStats ?? [];
|
|
276
|
+
const totalGcDurationMs = gcLog.reduce((a, e) => a + e.duration, 0);
|
|
277
|
+
const totalGcCount = gcLog.length;
|
|
278
|
+
const report = {
|
|
279
|
+
totalDurationMs: stats.reduce((a, s) => a + s.durationMs, 0),
|
|
280
|
+
totalCpuUserMs: stats.reduce((a, s) => a + s.cpuUserMs, 0),
|
|
281
|
+
totalCpuSystemMs: stats.reduce((a, s) => a + s.cpuSystemMs, 0),
|
|
282
|
+
totalGcDurationMs,
|
|
283
|
+
totalGcCount,
|
|
284
|
+
peakHeapUsedBytes: stats.reduce(
|
|
285
|
+
(a, s) => Math.max(a, s.heapUsedAfter),
|
|
286
|
+
0
|
|
287
|
+
),
|
|
288
|
+
steps: stats,
|
|
289
|
+
slowest: stats.length > 0 ? stats.reduce((a, s) => s.durationMs > a.durationMs ? s : a) : null,
|
|
290
|
+
heaviest: stats.length > 0 ? stats.reduce(
|
|
291
|
+
(a, s) => s.heapDeltaBytes > a.heapDeltaBytes ? s : a
|
|
292
|
+
) : null
|
|
293
|
+
};
|
|
294
|
+
shared.__perfReport = report;
|
|
295
|
+
onReport?.(report);
|
|
296
|
+
}
|
|
297
|
+
},
|
|
298
|
+
filter
|
|
299
|
+
);
|
|
210
300
|
return this;
|
|
211
301
|
}
|
|
212
302
|
};
|
|
213
303
|
export {
|
|
214
304
|
withAtomicUpdates,
|
|
215
|
-
withDebugger,
|
|
216
305
|
withDryRun,
|
|
217
306
|
withFlowAnalyzer,
|
|
218
307
|
withMocks,
|
|
308
|
+
withPerfAnalyzer,
|
|
219
309
|
withStepLimit
|
|
220
310
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as FlowneerPlugin, N as NodeFn, b as NodeOptions } from '../../FlowBuilder-
|
|
1
|
+
import { a as FlowneerPlugin, N as NodeFn, b as NodeOptions } from '../../FlowBuilder-8kwREeyD.js';
|
|
2
2
|
|
|
3
3
|
/** A single node entry in the exported graph. */
|
|
4
4
|
interface GraphNodeExport {
|
|
@@ -97,6 +97,7 @@ function applyStepFilter(hooks, filter) {
|
|
|
97
97
|
wrap("onError");
|
|
98
98
|
wrap("wrapStep", (_m, next) => next());
|
|
99
99
|
wrap("wrapParallelFn", (_m, _fi, next) => next());
|
|
100
|
+
wrap("onLoopIteration");
|
|
100
101
|
return hooks;
|
|
101
102
|
}
|
|
102
103
|
function buildHookCache(list) {
|
|
@@ -108,7 +109,9 @@ function buildHookCache(list) {
|
|
|
108
109
|
afterStep: pick("afterStep"),
|
|
109
110
|
wrapParallelFn: pick("wrapParallelFn"),
|
|
110
111
|
onError: pick("onError"),
|
|
111
|
-
afterFlow: pick("afterFlow")
|
|
112
|
+
afterFlow: pick("afterFlow"),
|
|
113
|
+
onLoopIteration: pick("onLoopIteration"),
|
|
114
|
+
onAnchorHit: pick("onAnchorHit")
|
|
112
115
|
};
|
|
113
116
|
}
|
|
114
117
|
var CoreFlowBuilder = class _CoreFlowBuilder {
|
|
@@ -325,10 +328,12 @@ var CoreFlowBuilder = class _CoreFlowBuilder {
|
|
|
325
328
|
);
|
|
326
329
|
}
|
|
327
330
|
i = target;
|
|
331
|
+
for (const h of hooks.onAnchorHit)
|
|
332
|
+
await h(gotoTarget, shared, params);
|
|
328
333
|
}
|
|
329
334
|
} catch (err) {
|
|
330
335
|
if (err instanceof InterruptError) throw err;
|
|
331
|
-
for (const h of hooks.onError) h(meta, err, shared, params);
|
|
336
|
+
for (const h of hooks.onError) await h(meta, err, shared, params);
|
|
332
337
|
if (err instanceof FlowError) throw err;
|
|
333
338
|
const labelPart = stepLabel ? `"${stepLabel}" ` : "";
|
|
334
339
|
const label = step.type === "fn" ? `${labelPart}step ${i}` : `${labelPart}${step.type} (step ${i})`;
|
package/dist/plugins/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { withHistory, withInterrupts, withTiming, withVerbose } from './observability/index.js';
|
|
2
2
|
export { CircuitBreakerOptions, withCircuitBreaker, withCycles, withFallback, withTimeout } from './resilience/index.js';
|
|
3
|
-
export { AuditEntry, AuditLogStore,
|
|
3
|
+
export { AuditEntry, AuditLogStore, withAuditLog, withCheckpoint, withReplay } from './persistence/index.js';
|
|
4
4
|
export { RateLimitOptions, withCostTracker, withRateLimit, withTokenBudget } from './llm/index.js';
|
|
5
5
|
export { PathMap, PathNode, TraceEvent, TraceHandle, TraceReport, withAtomicUpdates, withDryRun, withFlowAnalyzer, withMocks, withStepLimit } from './dev/index.js';
|
|
6
6
|
export { StreamSubscriber, emit, peekChannel, receiveFrom, sendTo, withChannels, withStream } from './messaging/index.js';
|
|
@@ -11,7 +11,7 @@ export { parseJsonOutput, parseListOutput, parseMarkdownTable, parseRegexOutput
|
|
|
11
11
|
export { Span, TelemetryDaemon, TelemetryExporter, TelemetryOptions, consoleExporter, otlpExporter, withTelemetry } from './telemetry/index.js';
|
|
12
12
|
export { EvalResult, EvalSummary, ScoreFn, answerRelevance, containsMatch, exactMatch, f1Score, retrievalPrecision, retrievalRecall, runEvalSuite } from './eval/index.js';
|
|
13
13
|
export { GraphEdge, GraphNode, withGraph } from './graph/index.js';
|
|
14
|
-
import { S as StepFilter, a as FlowneerPlugin, d as StepMeta, F as FlowBuilder } from '../FlowBuilder-
|
|
14
|
+
import { S as StepFilter, a as FlowneerPlugin, d as StepMeta, F as FlowBuilder } from '../FlowBuilder-8kwREeyD.js';
|
|
15
15
|
import { F as FlowError } from '../errors-u-hq7p5N.js';
|
|
16
16
|
export { validate } from './config/index.js';
|
|
17
17
|
export { F as FlowConfig, a as FnRegistry, S as StepConfig, V as ValidationError, b as ValidationResult } from '../schema-CIqQAXqY.js';
|