agentflow-core 0.1.1 → 0.1.2

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/index.cjs CHANGED
@@ -31,11 +31,15 @@ __export(index_exports, {
31
31
  getNode: () => getNode,
32
32
  getParent: () => getParent,
33
33
  getStats: () => getStats,
34
- getSubtree: () => getSubtree
34
+ getSubtree: () => getSubtree,
35
+ getTraceTree: () => getTraceTree,
36
+ groupByTraceId: () => groupByTraceId,
37
+ stitchTrace: () => stitchTrace
35
38
  });
36
39
  module.exports = __toCommonJS(index_exports);
37
40
 
38
41
  // src/graph-builder.ts
42
+ var import_crypto = require("crypto");
39
43
  function deepFreeze(obj) {
40
44
  if (obj === null || typeof obj !== "object") return obj;
41
45
  if (obj instanceof Map) {
@@ -66,6 +70,9 @@ function createGraphBuilder(config) {
66
70
  const generateId = config?.idGenerator ?? createCounterIdGenerator();
67
71
  const agentId = config?.agentId ?? "unknown";
68
72
  const trigger = config?.trigger ?? "manual";
73
+ const spanId = (0, import_crypto.randomUUID)();
74
+ const traceId = config?.traceId ?? (typeof process !== "undefined" ? process.env?.AGENTFLOW_TRACE_ID : void 0) ?? (0, import_crypto.randomUUID)();
75
+ const parentSpanId = config?.parentSpanId ?? (typeof process !== "undefined" ? process.env?.AGENTFLOW_PARENT_SPAN_ID : void 0) ?? null;
69
76
  const graphId = generateId();
70
77
  const startTime = Date.now();
71
78
  const nodes = /* @__PURE__ */ new Map();
@@ -136,7 +143,10 @@ function createGraphBuilder(config) {
136
143
  status: graphStatus,
137
144
  trigger,
138
145
  agentId,
139
- events: [...events]
146
+ events: [...events],
147
+ traceId,
148
+ spanId,
149
+ parentSpanId
140
150
  };
141
151
  return deepFreeze(graph);
142
152
  }
@@ -144,6 +154,9 @@ function createGraphBuilder(config) {
144
154
  get graphId() {
145
155
  return graphId;
146
156
  },
157
+ get traceContext() {
158
+ return { traceId, spanId };
159
+ },
147
160
  startNode(opts) {
148
161
  assertNotBuilt();
149
162
  const id = generateId();
@@ -251,6 +264,70 @@ function createGraphBuilder(config) {
251
264
  return builder;
252
265
  }
253
266
 
267
+ // src/graph-stitch.ts
268
+ function groupByTraceId(graphs) {
269
+ const groups = /* @__PURE__ */ new Map();
270
+ for (const g of graphs) {
271
+ if (!g.traceId) continue;
272
+ const arr = groups.get(g.traceId) ?? [];
273
+ arr.push(g);
274
+ groups.set(g.traceId, arr);
275
+ }
276
+ return groups;
277
+ }
278
+ function stitchTrace(graphs) {
279
+ if (graphs.length === 0) throw new Error("No graphs to stitch");
280
+ const traceId = graphs[0].traceId ?? "";
281
+ const graphsBySpan = /* @__PURE__ */ new Map();
282
+ const childMap = /* @__PURE__ */ new Map();
283
+ let rootGraph = null;
284
+ for (const g of graphs) {
285
+ if (g.spanId) graphsBySpan.set(g.spanId, g);
286
+ if (!g.parentSpanId) {
287
+ if (!rootGraph || g.startTime < rootGraph.startTime) rootGraph = g;
288
+ }
289
+ if (g.parentSpanId) {
290
+ const siblings = childMap.get(g.parentSpanId) ?? [];
291
+ if (g.spanId) siblings.push(g.spanId);
292
+ childMap.set(g.parentSpanId, siblings);
293
+ }
294
+ }
295
+ if (!rootGraph) rootGraph = graphs[0];
296
+ let status = "completed";
297
+ let endTime = 0;
298
+ let startTime = Infinity;
299
+ for (const g of graphs) {
300
+ startTime = Math.min(startTime, g.startTime);
301
+ if (g.status === "failed") status = "failed";
302
+ else if (g.status === "running" && status !== "failed") status = "running";
303
+ if (g.endTime === null) endTime = null;
304
+ else if (endTime !== null) endTime = Math.max(endTime, g.endTime);
305
+ }
306
+ const frozenChildMap = /* @__PURE__ */ new Map();
307
+ for (const [k, v] of childMap) frozenChildMap.set(k, Object.freeze([...v]));
308
+ return Object.freeze({
309
+ traceId,
310
+ graphs: graphsBySpan,
311
+ rootGraph,
312
+ childMap: frozenChildMap,
313
+ startTime,
314
+ endTime,
315
+ status
316
+ });
317
+ }
318
+ function getTraceTree(trace) {
319
+ const result = [];
320
+ function walk(spanId) {
321
+ const graph = trace.graphs.get(spanId);
322
+ if (graph) result.push(graph);
323
+ const children = trace.childMap.get(spanId) ?? [];
324
+ for (const childSpan of children) walk(childSpan);
325
+ }
326
+ if (trace.rootGraph.spanId) walk(trace.rootGraph.spanId);
327
+ else result.push(trace.rootGraph);
328
+ return result;
329
+ }
330
+
254
331
  // src/graph-query.ts
255
332
  function getNode(graph, nodeId) {
256
333
  return graph.nodes.get(nodeId);
@@ -402,5 +479,8 @@ function getStats(graph) {
402
479
  getNode,
403
480
  getParent,
404
481
  getStats,
405
- getSubtree
482
+ getSubtree,
483
+ getTraceTree,
484
+ groupByTraceId,
485
+ stitchTrace
406
486
  });
package/dist/index.d.cts CHANGED
@@ -65,6 +65,12 @@ interface ExecutionGraph {
65
65
  readonly agentId: string;
66
66
  /** Full ordered event log for auditability. */
67
67
  readonly events: readonly TraceEvent[];
68
+ /** Distributed trace ID linking graphs across services. */
69
+ readonly traceId?: string;
70
+ /** Unique span ID for this graph within the trace. */
71
+ readonly spanId?: string;
72
+ /** Parent span ID, or null if this is the root span. */
73
+ readonly parentSpanId?: string | null;
68
74
  }
69
75
  /**
70
76
  * Configuration for AgentFlow.
@@ -100,6 +106,10 @@ interface AgentFlowConfig {
100
106
  readonly logger?: (message: string) => void;
101
107
  /** Error callback for internal failures. */
102
108
  readonly onError?: (error: unknown) => void;
109
+ /** Distributed trace ID to join an existing trace. */
110
+ readonly traceId?: string;
111
+ /** Parent span ID for linking to an upstream graph. */
112
+ readonly parentSpanId?: string;
103
113
  }
104
114
  /**
105
115
  * Output adapter interface. Writers receive the completed execution graph
@@ -161,6 +171,11 @@ interface StartNodeOptions {
161
171
  interface GraphBuilder {
162
172
  /** The graph's ID, available before `build()`. */
163
173
  readonly graphId: string;
174
+ /** Trace context for propagating distributed trace information. */
175
+ readonly traceContext: {
176
+ traceId: string;
177
+ spanId: string;
178
+ };
164
179
  /** Start a new execution node. Returns the generated node ID. */
165
180
  startNode(opts: StartNodeOptions): string;
166
181
  /** End a node. Status defaults to `'completed'`. */
@@ -204,6 +219,16 @@ interface GraphStats {
204
219
  readonly failureCount: number;
205
220
  readonly hungCount: number;
206
221
  }
222
+ /** A stitched distributed trace spanning multiple execution graphs. */
223
+ interface DistributedTrace {
224
+ readonly traceId: string;
225
+ readonly graphs: ReadonlyMap<string, ExecutionGraph>;
226
+ readonly rootGraph: ExecutionGraph;
227
+ readonly childMap: ReadonlyMap<string, readonly string[]>;
228
+ readonly startTime: number;
229
+ readonly endTime: number | null;
230
+ readonly status: GraphStatus;
231
+ }
207
232
  /** @internal Mutable version of ExecutionNode used during graph construction. */
208
233
  interface MutableExecutionNode {
209
234
  id: string;
@@ -251,6 +276,10 @@ interface MutableExecutionNode {
251
276
  */
252
277
  declare function createGraphBuilder(config?: AgentFlowConfig): GraphBuilder;
253
278
 
279
+ declare function groupByTraceId(graphs: ExecutionGraph[]): Map<string, ExecutionGraph[]>;
280
+ declare function stitchTrace(graphs: ExecutionGraph[]): DistributedTrace;
281
+ declare function getTraceTree(trace: DistributedTrace): ExecutionGraph[];
282
+
254
283
  /**
255
284
  * Pure query functions for interrogating a built `ExecutionGraph`.
256
285
  * Every function takes a frozen graph and returns derived data without mutation.
@@ -367,4 +396,4 @@ declare function getDepth(graph: ExecutionGraph): number;
367
396
  */
368
397
  declare function getStats(graph: ExecutionGraph): GraphStats;
369
398
 
370
- export { type Adapter, type AgentFlowConfig, type EdgeType, type ExecutionEdge, type ExecutionGraph, type ExecutionNode, type GraphBuilder, type GraphStats, type GraphStatus, type MutableExecutionNode, type NodeStatus, type NodeType, type StartNodeOptions, type TraceEvent, type TraceEventType, type Writer, createGraphBuilder, findWaitingOn, getChildren, getCriticalPath, getDepth, getDuration, getFailures, getHungNodes, getNode, getParent, getStats, getSubtree };
399
+ export { type Adapter, type AgentFlowConfig, type DistributedTrace, type EdgeType, type ExecutionEdge, type ExecutionGraph, type ExecutionNode, type GraphBuilder, type GraphStats, type GraphStatus, type MutableExecutionNode, type NodeStatus, type NodeType, type StartNodeOptions, type TraceEvent, type TraceEventType, type Writer, createGraphBuilder, findWaitingOn, getChildren, getCriticalPath, getDepth, getDuration, getFailures, getHungNodes, getNode, getParent, getStats, getSubtree, getTraceTree, groupByTraceId, stitchTrace };
package/dist/index.d.ts CHANGED
@@ -65,6 +65,12 @@ interface ExecutionGraph {
65
65
  readonly agentId: string;
66
66
  /** Full ordered event log for auditability. */
67
67
  readonly events: readonly TraceEvent[];
68
+ /** Distributed trace ID linking graphs across services. */
69
+ readonly traceId?: string;
70
+ /** Unique span ID for this graph within the trace. */
71
+ readonly spanId?: string;
72
+ /** Parent span ID, or null if this is the root span. */
73
+ readonly parentSpanId?: string | null;
68
74
  }
69
75
  /**
70
76
  * Configuration for AgentFlow.
@@ -100,6 +106,10 @@ interface AgentFlowConfig {
100
106
  readonly logger?: (message: string) => void;
101
107
  /** Error callback for internal failures. */
102
108
  readonly onError?: (error: unknown) => void;
109
+ /** Distributed trace ID to join an existing trace. */
110
+ readonly traceId?: string;
111
+ /** Parent span ID for linking to an upstream graph. */
112
+ readonly parentSpanId?: string;
103
113
  }
104
114
  /**
105
115
  * Output adapter interface. Writers receive the completed execution graph
@@ -161,6 +171,11 @@ interface StartNodeOptions {
161
171
  interface GraphBuilder {
162
172
  /** The graph's ID, available before `build()`. */
163
173
  readonly graphId: string;
174
+ /** Trace context for propagating distributed trace information. */
175
+ readonly traceContext: {
176
+ traceId: string;
177
+ spanId: string;
178
+ };
164
179
  /** Start a new execution node. Returns the generated node ID. */
165
180
  startNode(opts: StartNodeOptions): string;
166
181
  /** End a node. Status defaults to `'completed'`. */
@@ -204,6 +219,16 @@ interface GraphStats {
204
219
  readonly failureCount: number;
205
220
  readonly hungCount: number;
206
221
  }
222
+ /** A stitched distributed trace spanning multiple execution graphs. */
223
+ interface DistributedTrace {
224
+ readonly traceId: string;
225
+ readonly graphs: ReadonlyMap<string, ExecutionGraph>;
226
+ readonly rootGraph: ExecutionGraph;
227
+ readonly childMap: ReadonlyMap<string, readonly string[]>;
228
+ readonly startTime: number;
229
+ readonly endTime: number | null;
230
+ readonly status: GraphStatus;
231
+ }
207
232
  /** @internal Mutable version of ExecutionNode used during graph construction. */
208
233
  interface MutableExecutionNode {
209
234
  id: string;
@@ -251,6 +276,10 @@ interface MutableExecutionNode {
251
276
  */
252
277
  declare function createGraphBuilder(config?: AgentFlowConfig): GraphBuilder;
253
278
 
279
+ declare function groupByTraceId(graphs: ExecutionGraph[]): Map<string, ExecutionGraph[]>;
280
+ declare function stitchTrace(graphs: ExecutionGraph[]): DistributedTrace;
281
+ declare function getTraceTree(trace: DistributedTrace): ExecutionGraph[];
282
+
254
283
  /**
255
284
  * Pure query functions for interrogating a built `ExecutionGraph`.
256
285
  * Every function takes a frozen graph and returns derived data without mutation.
@@ -367,4 +396,4 @@ declare function getDepth(graph: ExecutionGraph): number;
367
396
  */
368
397
  declare function getStats(graph: ExecutionGraph): GraphStats;
369
398
 
370
- export { type Adapter, type AgentFlowConfig, type EdgeType, type ExecutionEdge, type ExecutionGraph, type ExecutionNode, type GraphBuilder, type GraphStats, type GraphStatus, type MutableExecutionNode, type NodeStatus, type NodeType, type StartNodeOptions, type TraceEvent, type TraceEventType, type Writer, createGraphBuilder, findWaitingOn, getChildren, getCriticalPath, getDepth, getDuration, getFailures, getHungNodes, getNode, getParent, getStats, getSubtree };
399
+ export { type Adapter, type AgentFlowConfig, type DistributedTrace, type EdgeType, type ExecutionEdge, type ExecutionGraph, type ExecutionNode, type GraphBuilder, type GraphStats, type GraphStatus, type MutableExecutionNode, type NodeStatus, type NodeType, type StartNodeOptions, type TraceEvent, type TraceEventType, type Writer, createGraphBuilder, findWaitingOn, getChildren, getCriticalPath, getDepth, getDuration, getFailures, getHungNodes, getNode, getParent, getStats, getSubtree, getTraceTree, groupByTraceId, stitchTrace };
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  // src/graph-builder.ts
2
+ import { randomUUID } from "crypto";
2
3
  function deepFreeze(obj) {
3
4
  if (obj === null || typeof obj !== "object") return obj;
4
5
  if (obj instanceof Map) {
@@ -29,6 +30,9 @@ function createGraphBuilder(config) {
29
30
  const generateId = config?.idGenerator ?? createCounterIdGenerator();
30
31
  const agentId = config?.agentId ?? "unknown";
31
32
  const trigger = config?.trigger ?? "manual";
33
+ const spanId = randomUUID();
34
+ const traceId = config?.traceId ?? (typeof process !== "undefined" ? process.env?.AGENTFLOW_TRACE_ID : void 0) ?? randomUUID();
35
+ const parentSpanId = config?.parentSpanId ?? (typeof process !== "undefined" ? process.env?.AGENTFLOW_PARENT_SPAN_ID : void 0) ?? null;
32
36
  const graphId = generateId();
33
37
  const startTime = Date.now();
34
38
  const nodes = /* @__PURE__ */ new Map();
@@ -99,7 +103,10 @@ function createGraphBuilder(config) {
99
103
  status: graphStatus,
100
104
  trigger,
101
105
  agentId,
102
- events: [...events]
106
+ events: [...events],
107
+ traceId,
108
+ spanId,
109
+ parentSpanId
103
110
  };
104
111
  return deepFreeze(graph);
105
112
  }
@@ -107,6 +114,9 @@ function createGraphBuilder(config) {
107
114
  get graphId() {
108
115
  return graphId;
109
116
  },
117
+ get traceContext() {
118
+ return { traceId, spanId };
119
+ },
110
120
  startNode(opts) {
111
121
  assertNotBuilt();
112
122
  const id = generateId();
@@ -214,6 +224,70 @@ function createGraphBuilder(config) {
214
224
  return builder;
215
225
  }
216
226
 
227
+ // src/graph-stitch.ts
228
+ function groupByTraceId(graphs) {
229
+ const groups = /* @__PURE__ */ new Map();
230
+ for (const g of graphs) {
231
+ if (!g.traceId) continue;
232
+ const arr = groups.get(g.traceId) ?? [];
233
+ arr.push(g);
234
+ groups.set(g.traceId, arr);
235
+ }
236
+ return groups;
237
+ }
238
+ function stitchTrace(graphs) {
239
+ if (graphs.length === 0) throw new Error("No graphs to stitch");
240
+ const traceId = graphs[0].traceId ?? "";
241
+ const graphsBySpan = /* @__PURE__ */ new Map();
242
+ const childMap = /* @__PURE__ */ new Map();
243
+ let rootGraph = null;
244
+ for (const g of graphs) {
245
+ if (g.spanId) graphsBySpan.set(g.spanId, g);
246
+ if (!g.parentSpanId) {
247
+ if (!rootGraph || g.startTime < rootGraph.startTime) rootGraph = g;
248
+ }
249
+ if (g.parentSpanId) {
250
+ const siblings = childMap.get(g.parentSpanId) ?? [];
251
+ if (g.spanId) siblings.push(g.spanId);
252
+ childMap.set(g.parentSpanId, siblings);
253
+ }
254
+ }
255
+ if (!rootGraph) rootGraph = graphs[0];
256
+ let status = "completed";
257
+ let endTime = 0;
258
+ let startTime = Infinity;
259
+ for (const g of graphs) {
260
+ startTime = Math.min(startTime, g.startTime);
261
+ if (g.status === "failed") status = "failed";
262
+ else if (g.status === "running" && status !== "failed") status = "running";
263
+ if (g.endTime === null) endTime = null;
264
+ else if (endTime !== null) endTime = Math.max(endTime, g.endTime);
265
+ }
266
+ const frozenChildMap = /* @__PURE__ */ new Map();
267
+ for (const [k, v] of childMap) frozenChildMap.set(k, Object.freeze([...v]));
268
+ return Object.freeze({
269
+ traceId,
270
+ graphs: graphsBySpan,
271
+ rootGraph,
272
+ childMap: frozenChildMap,
273
+ startTime,
274
+ endTime,
275
+ status
276
+ });
277
+ }
278
+ function getTraceTree(trace) {
279
+ const result = [];
280
+ function walk(spanId) {
281
+ const graph = trace.graphs.get(spanId);
282
+ if (graph) result.push(graph);
283
+ const children = trace.childMap.get(spanId) ?? [];
284
+ for (const childSpan of children) walk(childSpan);
285
+ }
286
+ if (trace.rootGraph.spanId) walk(trace.rootGraph.spanId);
287
+ else result.push(trace.rootGraph);
288
+ return result;
289
+ }
290
+
217
291
  // src/graph-query.ts
218
292
  function getNode(graph, nodeId) {
219
293
  return graph.nodes.get(nodeId);
@@ -364,5 +438,8 @@ export {
364
438
  getNode,
365
439
  getParent,
366
440
  getStats,
367
- getSubtree
441
+ getSubtree,
442
+ getTraceTree,
443
+ groupByTraceId,
444
+ stitchTrace
368
445
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentflow-core",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Universal execution tracing for AI agent systems",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",