graphai 0.5.3 → 0.5.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/lib/graphai.d.ts CHANGED
@@ -46,6 +46,7 @@ export declare class GraphAI {
46
46
  updateLog(log: TransactionLog): void;
47
47
  transactionLogs(): TransactionLog[];
48
48
  injectValue(nodeId: string, value: ResultData, injectFrom?: string): void;
49
- resultsOf(sources: Array<DataSource>): ResultData[];
49
+ resultsOf(sources: Record<string, DataSource | DataSource[]>): Record<string, ResultData>;
50
+ resultOf(source: DataSource): ResultData;
50
51
  }
51
52
  export {};
package/lib/graphai.js CHANGED
@@ -253,10 +253,23 @@ class GraphAI {
253
253
  }
254
254
  }
255
255
  resultsOf(sources) {
256
- return sources.map((source) => {
257
- const { result } = source.nodeId ? this.nodes[source.nodeId] : { result: undefined };
258
- return (0, utils_1.getDataFromSource)(result, source);
256
+ const ret = {};
257
+ Object.keys(sources).forEach((key) => {
258
+ const source = sources[key];
259
+ if (Array.isArray(source)) {
260
+ ret[key] = source.map((s) => {
261
+ return this.resultOf(s);
262
+ });
263
+ }
264
+ else {
265
+ ret[key] = this.resultOf(source);
266
+ }
259
267
  });
268
+ return ret;
269
+ }
270
+ resultOf(source) {
271
+ const { result } = source.nodeId ? this.nodes[source.nodeId] : { result: undefined };
272
+ return (0, utils_1.getDataFromSource)(result, source);
260
273
  }
261
274
  }
262
275
  exports.GraphAI = GraphAI;
package/lib/node.d.ts CHANGED
@@ -28,7 +28,8 @@ export declare class ComputedNode extends Node {
28
28
  error?: Error;
29
29
  transactionId: undefined | number;
30
30
  readonly anyInput: boolean;
31
- dataSources: Array<DataSource>;
31
+ dataSources: Record<string, DataSource | DataSource[]>;
32
+ private inputs?;
32
33
  inputNames?: Array<string>;
33
34
  pendings: Set<string>;
34
35
  private ifSource?;
@@ -38,6 +39,7 @@ export declare class ComputedNode extends Node {
38
39
  readonly isComputedNode = true;
39
40
  constructor(graphId: string, nodeId: string, data: ComputedNodeData, graph: GraphAI);
40
41
  getAgentId(): string;
42
+ private addPengindNode;
41
43
  isReadyNode(): boolean;
42
44
  private retry;
43
45
  private checkDataAvailability;
@@ -50,6 +52,9 @@ export declare class ComputedNode extends Node {
50
52
  execute(): Promise<void>;
51
53
  private prepareExecute;
52
54
  private errorProcess;
55
+ private getNamedInput;
56
+ private getInputs;
57
+ private getDebugInfo;
53
58
  }
54
59
  export declare class StaticNode extends Node {
55
60
  value?: ResultData;
package/lib/node.js CHANGED
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.StaticNode = exports.ComputedNode = exports.Node = void 0;
4
4
  const utils_1 = require("./utils/utils");
5
+ const nodeUtils_1 = require("./utils/nodeUtils");
5
6
  const type_1 = require("./type");
6
7
  const utils_2 = require("./utils/utils");
7
8
  const transaction_log_1 = require("./transaction_log");
@@ -34,6 +35,7 @@ class ComputedNode extends Node {
34
35
  constructor(graphId, nodeId, data, graph) {
35
36
  super(nodeId, graph);
36
37
  this.retryCount = 0;
38
+ this.dataSources = {}; // data sources.
37
39
  this.isStaticNode = false;
38
40
  this.isComputedNode = true;
39
41
  this.graphId = graphId;
@@ -45,19 +47,20 @@ class ComputedNode extends Node {
45
47
  this.isResult = data.isResult ?? false;
46
48
  this.priority = data.priority ?? 0;
47
49
  this.anyInput = data.anyInput ?? false;
48
- if (!data.inputs) {
49
- this.dataSources = [];
50
- }
51
- else if (Array.isArray(data.inputs)) {
52
- this.dataSources = (data.inputs ?? []).map((input) => (0, utils_2.parseNodeName)(input, graph.version));
53
- }
54
- else {
55
- const inputs = data.inputs;
56
- const keys = Object.keys(inputs);
57
- this.inputNames = keys;
58
- this.dataSources = keys.map((key) => (0, utils_2.parseNodeName)(inputs[key], graph.version));
50
+ if (data.inputs) {
51
+ if (Array.isArray(data.inputs)) {
52
+ this.inputs = data.inputs;
53
+ this.dataSources = (0, nodeUtils_1.inputs2dataSources)(data.inputs, graph.version);
54
+ }
55
+ else {
56
+ this.inputNames = Object.keys(data.inputs);
57
+ this.dataSources = (0, nodeUtils_1.namedInputs2dataSources)(data.inputs, graph.version);
58
+ }
59
59
  }
60
- this.pendings = new Set(this.dataSources.filter((source) => source.nodeId).map((source) => source.nodeId));
60
+ this.pendings = new Set(Object.values(this.dataSources)
61
+ .flat()
62
+ .filter((source) => source.nodeId)
63
+ .map((source) => source.nodeId));
61
64
  if (typeof data.agent === "string") {
62
65
  this.agentId = data.agent;
63
66
  }
@@ -76,23 +79,16 @@ class ComputedNode extends Node {
76
79
  }
77
80
  }
78
81
  if (typeof data.graph === "string") {
79
- const source = (0, utils_2.parseNodeName)(data.graph, graph.version);
80
- (0, utils_2.assert)(!!source.nodeId, `Invalid data source ${data.graph}`);
81
- this.pendings.add(source.nodeId);
82
- this.nestedGraph = source;
82
+ this.nestedGraph = this.addPengindNode(data.graph);
83
83
  }
84
84
  else if (data.graph) {
85
85
  this.nestedGraph = data.graph;
86
86
  }
87
87
  if (data.if) {
88
- this.ifSource = (0, utils_2.parseNodeName)(data.if, graph.version);
89
- (0, utils_2.assert)(!!this.ifSource.nodeId, `Invalid data source ${data.if}`);
90
- this.pendings.add(this.ifSource.nodeId);
88
+ this.ifSource = this.addPengindNode(data.if);
91
89
  }
92
90
  if (data.unless) {
93
- this.unlessSource = (0, utils_2.parseNodeName)(data.unless, graph.version);
94
- (0, utils_2.assert)(!!this.unlessSource.nodeId, `Invalid data source ${data.unless}`);
95
- this.pendings.add(this.unlessSource.nodeId);
91
+ this.unlessSource = this.addPengindNode(data.unless);
96
92
  }
97
93
  this.dynamicParams = Object.keys(this.params).reduce((tmp, key) => {
98
94
  const dataSource = (0, utils_2.parseNodeName)(this.params[key], graph.version < 0.3 ? 0.3 : graph.version);
@@ -108,36 +104,29 @@ class ComputedNode extends Node {
108
104
  getAgentId() {
109
105
  return this.agentId ?? "__custom__function"; // only for display purpose in the log.
110
106
  }
107
+ addPengindNode(nodeId) {
108
+ const source = (0, utils_2.parseNodeName)(nodeId, this.graph.version);
109
+ (0, utils_2.assert)(!!source.nodeId, `Invalid data source ${nodeId}`);
110
+ this.pendings.add(source.nodeId);
111
+ return source;
112
+ }
111
113
  isReadyNode() {
112
- if (this.state === type_1.NodeState.Waiting && this.pendings.size === 0) {
113
- // Count the number of data actually available.
114
- // We care it only when this.anyInput is true.
115
- // Notice that this logic enables dynamic data-flows.
116
- const counter = this.dataSources.reduce((count, source) => {
117
- const [result] = this.graph.resultsOf([source]);
118
- return result === undefined ? count : count + 1;
119
- }, 0);
120
- if (!this.anyInput || counter > 0) {
121
- if (this.ifSource) {
122
- const [condition] = this.graph.resultsOf([this.ifSource]);
123
- if (!(0, utils_2.isLogicallyTrue)(condition)) {
124
- this.state = type_1.NodeState.Skipped;
125
- this.log.onSkipped(this, this.graph);
126
- return false;
127
- }
128
- }
129
- if (this.unlessSource) {
130
- const [condition] = this.graph.resultsOf([this.unlessSource]);
131
- if ((0, utils_2.isLogicallyTrue)(condition)) {
132
- this.state = type_1.NodeState.Skipped;
133
- this.log.onSkipped(this, this.graph);
134
- return false;
135
- }
136
- }
137
- return true;
138
- }
114
+ if (this.state !== type_1.NodeState.Waiting || this.pendings.size !== 0) {
115
+ return false;
116
+ }
117
+ // Count the number of data actually available.
118
+ // We care it only when this.anyInput is true.
119
+ // Notice that this logic enables dynamic data-flows.
120
+ if (this.anyInput && !this.checkDataAvailability(false)) {
121
+ return false;
139
122
  }
140
- return false;
123
+ if ((this.ifSource && !(0, utils_2.isLogicallyTrue)(this.graph.resultOf(this.ifSource))) ||
124
+ (this.unlessSource && (0, utils_2.isLogicallyTrue)(this.graph.resultOf(this.unlessSource)))) {
125
+ this.state = type_1.NodeState.Skipped;
126
+ this.log.onSkipped(this, this.graph);
127
+ return false;
128
+ }
129
+ return true;
141
130
  }
142
131
  // This private method (only called while executing execute()) performs
143
132
  // the "retry" if specified. The transaction log must be updated before
@@ -156,12 +145,13 @@ class ComputedNode extends Node {
156
145
  this.graph.onExecutionComplete(this);
157
146
  }
158
147
  }
159
- checkDataAvailability() {
160
- (0, utils_2.assert)(this.anyInput, "checkDataAvailability should be called only for anyInput case");
161
- const results = this.graph.resultsOf(this.dataSources).filter((result) => {
162
- return result !== undefined;
163
- });
164
- return results.length > 0;
148
+ checkDataAvailability(checkAnyInput = true) {
149
+ if (checkAnyInput) {
150
+ (0, utils_2.assert)(this.anyInput, "checkDataAvailability should be called only for anyInput case");
151
+ }
152
+ return Object.values(this.graph.resultsOf(this.dataSources))
153
+ .flat()
154
+ .some((result) => result !== undefined);
165
155
  }
166
156
  // This method is called right before the Graph add this node to the task manager.
167
157
  beforeAddTask() {
@@ -228,12 +218,9 @@ class ComputedNode extends Node {
228
218
  // then it removes itself from the "running node" list of the graph.
229
219
  // Notice that setting the result of this node may make other nodes ready to run.
230
220
  async execute() {
231
- const previousResults = this.graph.resultsOf(this.dataSources).filter((result) => {
232
- // Remove undefined if anyInput flag is set.
233
- return !this.anyInput || result !== undefined;
234
- });
221
+ const previousResults = this.graph.resultsOf(this.dataSources);
235
222
  const transactionId = Date.now();
236
- this.prepareExecute(transactionId, previousResults);
223
+ this.prepareExecute(transactionId, Object.values(previousResults));
237
224
  if (this.timeout && this.timeout > 0) {
238
225
  setTimeout(() => {
239
226
  this.executeTimeout(transactionId);
@@ -243,34 +230,21 @@ class ComputedNode extends Node {
243
230
  const agentFunction = this.agentFunction ?? this.graph.getAgentFunctionInfo(this.agentId).agent;
244
231
  const localLog = [];
245
232
  const params = Object.keys(this.dynamicParams).reduce((tmp, key) => {
246
- const [result] = this.graph.resultsOf([this.dynamicParams[key]]);
233
+ const result = this.graph.resultOf(this.dynamicParams[key]);
247
234
  tmp[key] = result;
248
235
  return tmp;
249
236
  }, { ...this.params });
250
237
  const context = {
251
238
  params: params,
252
- inputs: previousResults,
239
+ inputs: this.getInputs(previousResults),
240
+ namedInputs: this.getNamedInput(previousResults),
253
241
  inputSchema: this.agentFunction ? undefined : this.graph.getAgentFunctionInfo(this.agentId)?.inputs,
254
- namedInputs: {},
255
- debugInfo: {
256
- nodeId: this.nodeId,
257
- agentId: this.agentId,
258
- retry: this.retryCount,
259
- verbose: this.graph.verbose,
260
- version: this.graph.version,
261
- },
242
+ debugInfo: this.getDebugInfo(),
262
243
  filterParams: this.filterParams,
263
244
  agentFilters: this.graph.agentFilters,
264
245
  config: this.graph.config,
265
246
  log: localLog,
266
247
  };
267
- if (this.inputNames) {
268
- context.namedInputs = this.inputNames.reduce((tmp, name, index) => {
269
- tmp[name] = previousResults[index];
270
- return tmp;
271
- }, {});
272
- context.inputs = [];
273
- }
274
248
  // NOTE: We use the existence of graph object in the agent-specific params to determine
275
249
  // if this is a nested agent or not.
276
250
  if (this.nestedGraph) {
@@ -280,7 +254,7 @@ class ComputedNode extends Node {
280
254
  context.graphData = this.nestedGraph;
281
255
  }
282
256
  else {
283
- const [graphData] = this.graph.resultsOf([this.nestedGraph]);
257
+ const graphData = this.graph.resultOf(this.nestedGraph);
284
258
  context.graphData = graphData; // HACK: compiler work-around
285
259
  }
286
260
  context.agents = this.graph.agentFunctionInfoDictionary;
@@ -339,6 +313,32 @@ class ComputedNode extends Node {
339
313
  this.retry(type_1.NodeState.Failed, Error("Unknown"));
340
314
  }
341
315
  }
316
+ getNamedInput(previousResults) {
317
+ if (this.inputNames) {
318
+ return this.inputNames.reduce((tmp, name) => {
319
+ if (!this.anyInput || previousResults[name]) {
320
+ tmp[name] = previousResults[name];
321
+ }
322
+ return tmp;
323
+ }, {});
324
+ }
325
+ return {};
326
+ }
327
+ getInputs(previousResults) {
328
+ if (this.inputNames) {
329
+ return [];
330
+ }
331
+ return (this.inputs ?? []).map((key) => previousResults[String(key)]).filter(a => !this.anyInput || a);
332
+ }
333
+ getDebugInfo() {
334
+ return {
335
+ nodeId: this.nodeId,
336
+ agentId: this.agentId,
337
+ retry: this.retryCount,
338
+ verbose: this.graph.verbose,
339
+ version: this.graph.version,
340
+ };
341
+ }
342
342
  }
343
343
  exports.ComputedNode = ComputedNode;
344
344
  class StaticNode extends Node {
@@ -43,7 +43,10 @@ class TransactionLog {
43
43
  this.state = node.state;
44
44
  this.retryCount = node.retryCount > 0 ? node.retryCount : undefined;
45
45
  this.startTime = transactionId;
46
- this.inputs = node.dataSources.filter((source) => source.nodeId).map((source) => source.nodeId);
46
+ this.inputs = Object.values(node.dataSources)
47
+ .flat()
48
+ .filter((source) => source.nodeId)
49
+ .map((source) => source.nodeId);
47
50
  this.inputsData = inputs.length > 0 ? inputs : undefined;
48
51
  graph.setLoopLog(this);
49
52
  graph.appendLog(this);
@@ -0,0 +1,3 @@
1
+ import { DataSource } from "../type";
2
+ export declare const inputs2dataSources: (inputs: string[], graphVersion: number) => Record<string, DataSource>;
3
+ export declare const namedInputs2dataSources: (inputs: Record<string, any>, graphVersion: number) => Record<string, DataSource | DataSource[]>;
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.namedInputs2dataSources = exports.inputs2dataSources = void 0;
4
+ const utils_1 = require("./utils");
5
+ const inputs2dataSources = (inputs, graphVersion) => {
6
+ return inputs.reduce((tmp, input) => {
7
+ tmp[input] = (0, utils_1.parseNodeName)(input, graphVersion);
8
+ return tmp;
9
+ }, {});
10
+ };
11
+ exports.inputs2dataSources = inputs2dataSources;
12
+ const namedInputs2dataSources = (inputs, graphVersion) => {
13
+ return Object.keys(inputs).reduce((tmp, key) => {
14
+ const input = inputs[key];
15
+ if (Array.isArray(input)) {
16
+ tmp[key] = input.map((inp) => (0, utils_1.parseNodeName)(inp, graphVersion));
17
+ }
18
+ else {
19
+ tmp[key] = (0, utils_1.parseNodeName)(input, graphVersion);
20
+ }
21
+ return tmp;
22
+ }, {});
23
+ };
24
+ exports.namedInputs2dataSources = namedInputs2dataSources;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "graphai",
3
- "version": "0.5.3",
3
+ "version": "0.5.4",
4
4
  "description": "Asynchronous data flow execution engine for agentic AI apps.",
5
5
  "main": "lib/index.js",
6
6
  "files": [