graphai 0.6.19 → 0.6.21

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/lib/graphai.d.ts CHANGED
@@ -6,7 +6,7 @@ export declare const defaultConcurrency = 8;
6
6
  export declare const graphDataLatestVersion = 0.5;
7
7
  export declare class GraphAI {
8
8
  readonly version: number;
9
- private readonly graphId;
9
+ readonly graphId: string;
10
10
  private readonly graphData;
11
11
  private readonly loop?;
12
12
  private readonly logs;
@@ -42,6 +42,8 @@ export declare class GraphAI {
42
42
  pushQueueIfReadyAndRunning(node: ComputedNode): void;
43
43
  pushQueue(node: ComputedNode): void;
44
44
  run<T = DefaultResultData>(all?: boolean): Promise<ResultDataDictionary<T>>;
45
+ abort(): void;
46
+ resetPending(): void;
45
47
  isRunning(): boolean;
46
48
  onExecutionComplete(node: ComputedNode): void;
47
49
  private processLoopIfNecessary;
package/lib/graphai.js CHANGED
@@ -16,7 +16,7 @@ class GraphAI {
16
16
  createNodes(graphData) {
17
17
  const nodes = Object.keys(graphData.nodes).reduce((_nodes, nodeId) => {
18
18
  const nodeData = graphData.nodes[nodeId];
19
- if ("agent" in nodeData) {
19
+ if ((0, utils_1.isComputedNodeData)(nodeData)) {
20
20
  _nodes[nodeId] = new node_1.ComputedNode(this.graphId, nodeId, nodeData, this);
21
21
  }
22
22
  else {
@@ -109,7 +109,7 @@ class GraphAI {
109
109
  this.graphLoader = options.graphLoader;
110
110
  this.loop = graphData.loop;
111
111
  this.verbose = graphData.verbose === true;
112
- this.onComplete = () => {
112
+ this.onComplete = (__isAbort) => {
113
113
  throw new Error("SOMETHING IS WRONG: onComplete is called without run()");
114
114
  };
115
115
  (0, validator_1.validateGraphData)(graphData, [...Object.keys(agentFunctionInfoDictionary), ...this.bypassAgentIds]);
@@ -206,10 +206,10 @@ class GraphAI {
206
206
  return {};
207
207
  }
208
208
  return new Promise((resolve, reject) => {
209
- this.onComplete = () => {
209
+ this.onComplete = (isAbort = false) => {
210
210
  const errors = this.errors();
211
211
  const nodeIds = Object.keys(errors);
212
- if (nodeIds.length > 0) {
212
+ if (nodeIds.length > 0 || isAbort) {
213
213
  reject(errors[nodeIds[0]]);
214
214
  }
215
215
  else {
@@ -218,6 +218,19 @@ class GraphAI {
218
218
  };
219
219
  });
220
220
  }
221
+ abort() {
222
+ if (this.isRunning()) {
223
+ this.resetPending();
224
+ }
225
+ this.onComplete(this.isRunning());
226
+ }
227
+ resetPending() {
228
+ Object.values(this.nodes).map((node) => {
229
+ if (node.isComputedNode) {
230
+ node.resetPending();
231
+ }
232
+ });
233
+ }
221
234
  // Public only for testing
222
235
  isRunning() {
223
236
  return this.taskManager.isRunning(this.graphId);
@@ -228,7 +241,7 @@ class GraphAI {
228
241
  if (this.isRunning() || this.processLoopIfNecessary()) {
229
242
  return; // continue running
230
243
  }
231
- this.onComplete(); // Nothing to run. Finish it.
244
+ this.onComplete(false); // Nothing to run. Finish it.
232
245
  }
233
246
  // Must be called only from onExecutionComplete righ after removeRunning
234
247
  // Check if there is any running computed nodes.
package/lib/index.d.ts CHANGED
@@ -2,6 +2,6 @@ export { GraphAI, defaultConcurrency, graphDataLatestVersion } from "./graphai";
2
2
  export type { AgentFunction, AgentFunctionInfo, AgentFunctionInfoDictionary, AgentFunctionInfoSample, AgentFunctionContext, GraphData, ResultDataDictionary, ResultData, AgentFilterFunction, AgentFilterInfo, NodeData, StaticNodeData, ComputedNodeData, DefaultResultData, DefaultInputData, DefaultParamsType, GraphDataLoaderOption, GraphDataLoader, ConfigDataDictionary, DefaultConfigData, } from "./type";
3
3
  export { NodeState } from "./type";
4
4
  export type { TransactionLog } from "./transaction_log";
5
- export { defaultAgentInfo, agentInfoWrapper, defaultTestContext, strIntentionalError, assert, sleep, isObject, parseNodeName, debugResultKey, } from "./utils/utils";
5
+ export { defaultAgentInfo, agentInfoWrapper, defaultTestContext, strIntentionalError, assert, sleep, isObject, parseNodeName, debugResultKey, isComputedNodeData, isStaticNodeData, } from "./utils/utils";
6
6
  export { inputs2dataSources } from "./utils/nodeUtils";
7
7
  export { ValidationError } from "./validators/common";
package/lib/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ValidationError = exports.inputs2dataSources = exports.debugResultKey = exports.parseNodeName = exports.isObject = exports.sleep = exports.assert = exports.strIntentionalError = exports.defaultTestContext = exports.agentInfoWrapper = exports.defaultAgentInfo = exports.NodeState = exports.graphDataLatestVersion = exports.defaultConcurrency = exports.GraphAI = void 0;
3
+ exports.ValidationError = exports.inputs2dataSources = exports.isStaticNodeData = exports.isComputedNodeData = exports.debugResultKey = exports.parseNodeName = exports.isObject = exports.sleep = exports.assert = exports.strIntentionalError = exports.defaultTestContext = exports.agentInfoWrapper = exports.defaultAgentInfo = exports.NodeState = exports.graphDataLatestVersion = exports.defaultConcurrency = exports.GraphAI = void 0;
4
4
  var graphai_1 = require("./graphai");
5
5
  Object.defineProperty(exports, "GraphAI", { enumerable: true, get: function () { return graphai_1.GraphAI; } });
6
6
  Object.defineProperty(exports, "defaultConcurrency", { enumerable: true, get: function () { return graphai_1.defaultConcurrency; } });
@@ -17,6 +17,8 @@ Object.defineProperty(exports, "sleep", { enumerable: true, get: function () { r
17
17
  Object.defineProperty(exports, "isObject", { enumerable: true, get: function () { return utils_1.isObject; } });
18
18
  Object.defineProperty(exports, "parseNodeName", { enumerable: true, get: function () { return utils_1.parseNodeName; } });
19
19
  Object.defineProperty(exports, "debugResultKey", { enumerable: true, get: function () { return utils_1.debugResultKey; } });
20
+ Object.defineProperty(exports, "isComputedNodeData", { enumerable: true, get: function () { return utils_1.isComputedNodeData; } });
21
+ Object.defineProperty(exports, "isStaticNodeData", { enumerable: true, get: function () { return utils_1.isStaticNodeData; } });
20
22
  var nodeUtils_1 = require("./utils/nodeUtils");
21
23
  Object.defineProperty(exports, "inputs2dataSources", { enumerable: true, get: function () { return nodeUtils_1.inputs2dataSources; } });
22
24
  var common_1 = require("./validators/common");
package/lib/node.d.ts CHANGED
@@ -38,12 +38,15 @@ export declare class ComputedNode extends Node {
38
38
  private unlessSource?;
39
39
  private defaultValue?;
40
40
  private isSkip;
41
+ private debugInfo?;
41
42
  readonly isStaticNode = false;
42
43
  readonly isComputedNode = true;
43
44
  constructor(graphId: string, nodeId: string, data: ComputedNodeData, graph: GraphAI);
44
45
  getAgentId(): string;
45
46
  private getConfig;
46
47
  private addPendingNode;
48
+ private updateState;
49
+ resetPending(): void;
47
50
  isReadyNode(): boolean;
48
51
  private retry;
49
52
  private checkDataAvailability;
package/lib/node.js CHANGED
@@ -126,6 +126,21 @@ class ComputedNode extends Node {
126
126
  this.pendings.add(source.nodeId);
127
127
  return source;
128
128
  }
129
+ updateState(state) {
130
+ this.state = state;
131
+ if (this.debugInfo) {
132
+ this.debugInfo.state = state;
133
+ }
134
+ }
135
+ resetPending() {
136
+ this.pendings.clear();
137
+ if (this.state === type_1.NodeState.Executing) {
138
+ this.updateState(type_1.NodeState.Abort);
139
+ }
140
+ if (this.debugInfo && this.debugInfo.subGraphs) {
141
+ this.debugInfo.subGraphs.forEach((graph) => graph.abort());
142
+ }
143
+ }
129
144
  isReadyNode() {
130
145
  if (this.state !== type_1.NodeState.Waiting || this.pendings.size !== 0) {
131
146
  return false;
@@ -133,7 +148,7 @@ class ComputedNode extends Node {
133
148
  this.isSkip = !!((this.ifSource && !(0, utils_2.isLogicallyTrue)(this.graph.resultOf(this.ifSource))) ||
134
149
  (this.unlessSource && (0, utils_2.isLogicallyTrue)(this.graph.resultOf(this.unlessSource))));
135
150
  if (this.isSkip && this.defaultValue === undefined) {
136
- this.state = type_1.NodeState.Skipped;
151
+ this.updateState(type_1.NodeState.Skipped);
137
152
  this.log.onSkipped(this, this.graph);
138
153
  return false;
139
154
  }
@@ -143,7 +158,7 @@ class ComputedNode extends Node {
143
158
  // the "retry" if specified. The transaction log must be updated before
144
159
  // callling this method.
145
160
  retry(state, error) {
146
- this.state = state; // this.execute() will update to NodeState.Executing
161
+ this.updateState(state); // this.execute() will update to NodeState.Executing
147
162
  this.log.onError(this, this.graph, error.message);
148
163
  if (this.retryCount < this.retryLimit) {
149
164
  this.retryCount++;
@@ -163,7 +178,7 @@ class ComputedNode extends Node {
163
178
  }
164
179
  // This method is called right before the Graph add this node to the task manager.
165
180
  beforeAddTask() {
166
- this.state = type_1.NodeState.Queued;
181
+ this.updateState(type_1.NodeState.Queued);
167
182
  this.log.beforeAddTask(this, this.graph);
168
183
  }
169
184
  // This method is called when the data became available on one of nodes,
@@ -289,7 +304,10 @@ class ComputedNode extends Node {
289
304
  }
290
305
  }
291
306
  afterExecute(result, localLog) {
292
- this.state = type_1.NodeState.Completed;
307
+ if (this.state == type_1.NodeState.Abort) {
308
+ return;
309
+ }
310
+ this.updateState(type_1.NodeState.Completed);
293
311
  this.result = this.getResult(result);
294
312
  if (this.output) {
295
313
  this.result = (0, result_1.resultsOf)(this.output, { self: this }, this.graph.propFunctions, true);
@@ -301,7 +319,7 @@ class ComputedNode extends Node {
301
319
  // This private method (called only by execute()) prepares the ComputedNode object
302
320
  // for execution, and create a new transaction to record it.
303
321
  prepareExecute(transactionId, inputs) {
304
- this.state = type_1.NodeState.Executing;
322
+ this.updateState(type_1.NodeState.Executing);
305
323
  this.log.beforeExecute(this, this.graph, transactionId, inputs);
306
324
  this.transactionId = transactionId;
307
325
  }
@@ -328,11 +346,14 @@ class ComputedNode extends Node {
328
346
  }
329
347
  }
330
348
  getContext(previousResults, localLog, agentId, config) {
349
+ // Pass debugInfo by reference, and the state of this node will be received by agent/agentFilter.
350
+ // From graphAgent(nested, map), set the instance of graphai, and use abort on the child graphai.
351
+ this.debugInfo = this.getDebugInfo(agentId);
331
352
  const context = {
332
353
  params: this.graph.resultsOf(this.params),
333
354
  namedInputs: previousResults,
334
355
  inputSchema: this.agentFunction ? undefined : this.graph.getAgentFunctionInfo(agentId)?.inputs,
335
- debugInfo: this.getDebugInfo(agentId),
356
+ debugInfo: this.debugInfo,
336
357
  cacheType: this.agentFunction ? undefined : this.graph.getAgentFunctionInfo(agentId)?.cacheType,
337
358
  filterParams: this.filterParams,
338
359
  agentFilters: this.graph.agentFilters,
@@ -357,6 +378,8 @@ class ComputedNode extends Node {
357
378
  nodeId: this.nodeId,
358
379
  agentId,
359
380
  retry: this.retryCount,
381
+ state: this.state,
382
+ subGraphs: new Map(),
360
383
  verbose: this.graph.verbose,
361
384
  version: this.graph.version,
362
385
  isResult: this.isResult,
package/lib/type.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import type { TransactionLog } from "./transaction_log";
2
2
  import type { TaskManager } from "./task_manager";
3
+ import type { GraphAI } from "./graphai";
3
4
  export declare enum NodeState {
4
5
  Waiting = "waiting",
5
6
  Queued = "queued",
@@ -7,6 +8,7 @@ export declare enum NodeState {
7
8
  ExecutingServer = "executing-server",
8
9
  Failed = "failed",
9
10
  TimedOut = "timed-out",
11
+ Abort = "abort",
10
12
  Completed = "completed",
11
13
  Injected = "injected",
12
14
  Skipped = "skipped"
@@ -85,20 +87,23 @@ export type GraphOptions = {
85
87
  graphLoader?: GraphDataLoader;
86
88
  };
87
89
  export type CacheTypes = "pureAgent" | "impureAgent";
90
+ export type AgentFunctionContextDebugInfo = {
91
+ verbose: boolean;
92
+ nodeId: string;
93
+ state: string;
94
+ subGraphs: Map<string, GraphAI>;
95
+ retry: number;
96
+ agentId?: string;
97
+ version?: number;
98
+ isResult?: boolean;
99
+ };
88
100
  export type AgentFunctionContext<ParamsType = DefaultParamsType, NamedInputDataType = DefaultInputData, ConfigType = DefaultConfigData> = {
89
101
  params: NodeDataParams<ParamsType>;
90
102
  inputSchema?: any;
91
103
  namedInputs: NamedInputDataType;
92
- debugInfo: {
93
- verbose: boolean;
94
- nodeId: string;
95
- retry: number;
96
- agentId?: string;
97
- version?: number;
98
- isResult?: boolean;
99
- };
104
+ debugInfo: AgentFunctionContextDebugInfo;
100
105
  forNestedGraph?: {
101
- graphData: GraphData;
106
+ graphData?: GraphData;
102
107
  agents: AgentFunctionInfoDictionary;
103
108
  graphOptions: GraphOptions;
104
109
  onLogCallback?: (log: TransactionLog, isUpdate: boolean) => void;
package/lib/type.js CHANGED
@@ -9,6 +9,7 @@ var NodeState;
9
9
  NodeState["ExecutingServer"] = "executing-server";
10
10
  NodeState["Failed"] = "failed";
11
11
  NodeState["TimedOut"] = "timed-out";
12
+ NodeState["Abort"] = "abort";
12
13
  NodeState["Completed"] = "completed";
13
14
  NodeState["Injected"] = "injected";
14
15
  NodeState["Skipped"] = "skipped";
@@ -1,4 +1,4 @@
1
- import { DataSource, AgentFunction, DefaultInputData } from "../type";
1
+ import { DataSource, AgentFunction, AgentFunctionInfo, DefaultInputData, NodeData, StaticNodeData, ComputedNodeData, NodeState } from "../type";
2
2
  export declare const sleep: (milliseconds: number) => Promise<unknown>;
3
3
  export declare const parseNodeName: (inputNodeId: any, isSelfNode?: boolean) => DataSource;
4
4
  export declare function assert(condition: boolean, message: string, isWarn?: boolean): asserts condition;
@@ -18,21 +18,7 @@ export declare const defaultAgentInfo: {
18
18
  repository: string;
19
19
  license: string;
20
20
  };
21
- export declare const agentInfoWrapper: (agent: AgentFunction<any, any, any, any>) => {
22
- name: string;
23
- samples: {
24
- inputs: never[];
25
- params: {};
26
- result: {};
27
- }[];
28
- description: string;
29
- category: never[];
30
- author: string;
31
- repository: string;
32
- license: string;
33
- agent: AgentFunction<any, any, any, any>;
34
- mock: AgentFunction<any, any, any, any>;
35
- };
21
+ export declare const agentInfoWrapper: (agent: AgentFunction<any, any, any, any>) => AgentFunctionInfo;
36
22
  export declare const debugResultKey: (agentId: string, result: any) => string[];
37
23
  export declare const isLogicallyTrue: (value: any) => boolean;
38
24
  export declare const defaultTestContext: {
@@ -40,6 +26,8 @@ export declare const defaultTestContext: {
40
26
  nodeId: string;
41
27
  retry: number;
42
28
  verbose: boolean;
29
+ state: NodeState;
30
+ subGraphs: Map<any, any>;
43
31
  };
44
32
  params: {};
45
33
  filterParams: {};
@@ -47,3 +35,5 @@ export declare const defaultTestContext: {
47
35
  log: never[];
48
36
  };
49
37
  export declare const isNamedInputs: <NamedInput = DefaultInputData>(namedInputs: NamedInput) => boolean;
38
+ export declare const isComputedNodeData: (node: NodeData) => node is ComputedNodeData;
39
+ export declare const isStaticNodeData: (node: NodeData) => node is StaticNodeData;
@@ -1,7 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isNamedInputs = exports.defaultTestContext = exports.isLogicallyTrue = exports.debugResultKey = exports.agentInfoWrapper = exports.defaultAgentInfo = exports.strIntentionalError = exports.isNull = exports.isObject = exports.parseNodeName = exports.sleep = void 0;
3
+ exports.isStaticNodeData = exports.isComputedNodeData = exports.isNamedInputs = exports.defaultTestContext = exports.isLogicallyTrue = exports.debugResultKey = exports.agentInfoWrapper = exports.defaultAgentInfo = exports.strIntentionalError = exports.isNull = exports.isObject = exports.parseNodeName = exports.sleep = void 0;
4
4
  exports.assert = assert;
5
+ const type_1 = require("../type");
5
6
  const sleep = async (milliseconds) => {
6
7
  return await new Promise((resolve) => setTimeout(resolve, milliseconds));
7
8
  };
@@ -118,6 +119,8 @@ exports.defaultTestContext = {
118
119
  nodeId: "test",
119
120
  retry: 0,
120
121
  verbose: true,
122
+ state: type_1.NodeState.Executing,
123
+ subGraphs: new Map(),
121
124
  },
122
125
  params: {},
123
126
  filterParams: {},
@@ -128,3 +131,11 @@ const isNamedInputs = (namedInputs) => {
128
131
  return (0, exports.isObject)(namedInputs) && !Array.isArray(namedInputs) && Object.keys(namedInputs || {}).length > 0;
129
132
  };
130
133
  exports.isNamedInputs = isNamedInputs;
134
+ const isComputedNodeData = (node) => {
135
+ return "agent" in node;
136
+ };
137
+ exports.isComputedNodeData = isComputedNodeData;
138
+ const isStaticNodeData = (node) => {
139
+ return !("agent" in node);
140
+ };
141
+ exports.isStaticNodeData = isStaticNodeData;
package/lib/validator.js CHANGED
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.validateAgent = exports.validateGraphData = void 0;
4
+ const utils_1 = require("./utils/utils");
4
5
  const graph_data_validator_1 = require("./validators/graph_data_validator");
5
6
  const nodeValidator_1 = require("./validators/nodeValidator");
6
7
  const static_node_validator_1 = require("./validators/static_node_validator");
@@ -16,7 +17,7 @@ const validateGraphData = (data, agentIds) => {
16
17
  const graphAgentIds = new Set();
17
18
  Object.keys(data.nodes).forEach((nodeId) => {
18
19
  const node = data.nodes[nodeId];
19
- const isStaticNode = !("agent" in node);
20
+ const isStaticNode = (0, utils_1.isStaticNodeData)(node);
20
21
  (0, nodeValidator_1.nodeValidator)(node);
21
22
  const agentId = isStaticNode ? "" : node.agent;
22
23
  isStaticNode && (0, static_node_validator_1.staticNodeValidator)(node) && staticNodeIds.push(nodeId);
@@ -24,7 +24,7 @@ const relationValidator = (graphData, staticNodeIds, computedNodeIds) => {
24
24
  }
25
25
  });
26
26
  };
27
- if ("agent" in nodeData && nodeData) {
27
+ if (nodeData && (0, utils_1.isComputedNodeData)(nodeData)) {
28
28
  if (nodeData.inputs) {
29
29
  const sourceNodeIds = (0, nodeUtils_1.dataSourceNodeIds)((0, nodeUtils_1.inputs2dataSources)(nodeData.inputs));
30
30
  dataSourceValidator("Inputs", sourceNodeIds);
@@ -54,7 +54,7 @@ const relationValidator = (graphData, staticNodeIds, computedNodeIds) => {
54
54
  // TODO. validate update
55
55
  staticNodeIds.forEach((staticNodeId) => {
56
56
  const nodeData = graphData.nodes[staticNodeId];
57
- if ("value" in nodeData && nodeData.update) {
57
+ if ((0, utils_1.isStaticNodeData)(nodeData) && nodeData.update) {
58
58
  const update = nodeData.update;
59
59
  const updateNodeId = (0, utils_1.parseNodeName)(update).nodeId;
60
60
  if (!updateNodeId) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "graphai",
3
- "version": "0.6.19",
3
+ "version": "0.6.21",
4
4
  "description": "Asynchronous data flow execution engine for agentic AI apps.",
5
5
  "main": "lib/bundle.cjs.js",
6
6
  "module": "lib/bundle.esm.js",