graphai 0.0.12 → 0.1.1

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.
Files changed (98) hide show
  1. package/README.md +14 -10
  2. package/lib/experimental_agents/array_agents/index.d.ts +3 -0
  3. package/lib/experimental_agents/array_agents/index.js +9 -0
  4. package/lib/experimental_agents/array_agents/pop_agent.d.ts +2 -0
  5. package/lib/experimental_agents/array_agents/pop_agent.js +15 -0
  6. package/lib/experimental_agents/array_agents/push_agent.d.ts +2 -0
  7. package/lib/experimental_agents/array_agents/push_agent.js +14 -0
  8. package/lib/experimental_agents/array_agents/shift_agent.d.ts +2 -0
  9. package/lib/experimental_agents/{array_agents.js → array_agents/shift_agent.js} +2 -17
  10. package/lib/experimental_agents/data_agents/data_object_merge_template_agent.d.ts +2 -0
  11. package/lib/experimental_agents/data_agents/data_object_merge_template_agent.js +13 -0
  12. package/lib/experimental_agents/data_agents/data_sum_template_agent.d.ts +17 -0
  13. package/lib/experimental_agents/data_agents/data_sum_template_agent.js +30 -0
  14. package/lib/experimental_agents/data_agents/index.d.ts +3 -0
  15. package/lib/experimental_agents/data_agents/index.js +9 -0
  16. package/lib/experimental_agents/data_agents/total_agent.d.ts +46 -0
  17. package/lib/experimental_agents/data_agents/total_agent.js +51 -0
  18. package/lib/experimental_agents/embedding_agent.d.ts +6 -0
  19. package/lib/experimental_agents/embedding_agent.js +43 -0
  20. package/lib/experimental_agents/index.d.ts +8 -3
  21. package/lib/experimental_agents/index.js +8 -3
  22. package/lib/experimental_agents/map_agent.d.ts +4 -0
  23. package/lib/experimental_agents/map_agent.js +46 -0
  24. package/lib/experimental_agents/matrix_agent.d.ts +9 -0
  25. package/lib/experimental_agents/matrix_agent.js +50 -0
  26. package/lib/experimental_agents/nested_agent.d.ts +2 -2
  27. package/lib/experimental_agents/nested_agent.js +14 -8
  28. package/lib/experimental_agents/slashgpt_agent.d.ts +1 -1
  29. package/lib/experimental_agents/slashgpt_agent.js +2 -7
  30. package/lib/experimental_agents/sleeper_agents/index.d.ts +2 -0
  31. package/lib/experimental_agents/sleeper_agents/index.js +7 -0
  32. package/lib/experimental_agents/sleeper_agents/sleeper_agent.d.ts +5 -0
  33. package/lib/experimental_agents/sleeper_agents/sleeper_agent.js +16 -0
  34. package/lib/experimental_agents/sleeper_agents/sleeper_agent_debug.d.ts +6 -0
  35. package/lib/experimental_agents/{sleeper_agent.js → sleeper_agents/sleeper_agent_debug.js} +4 -13
  36. package/lib/experimental_agents/string_agents/index.d.ts +2 -0
  37. package/lib/experimental_agents/string_agents/index.js +7 -0
  38. package/lib/experimental_agents/string_agents/string_splitter_agent.d.ts +7 -0
  39. package/lib/experimental_agents/string_agents/string_splitter_agent.js +24 -0
  40. package/lib/experimental_agents/string_agents/string_template_agent.d.ts +4 -0
  41. package/lib/experimental_agents/{string_agent.js → string_agents/string_template_agent.js} +2 -5
  42. package/lib/experimental_agents/test_agents/bypass_agent.d.ts +2 -0
  43. package/lib/experimental_agents/test_agents/bypass_agent.js +10 -0
  44. package/lib/experimental_agents/test_agents/copy_message_agent.d.ts +2 -0
  45. package/lib/experimental_agents/test_agents/copy_message_agent.js +11 -0
  46. package/lib/experimental_agents/test_agents/counting_agent.d.ts +2 -0
  47. package/lib/experimental_agents/test_agents/counting_agent.js +11 -0
  48. package/lib/experimental_agents/test_agents/echo_agent.d.ts +2 -0
  49. package/lib/experimental_agents/test_agents/echo_agent.js +7 -0
  50. package/lib/experimental_agents/test_agents/echo_fork_index_agent.d.ts +2 -0
  51. package/lib/experimental_agents/test_agents/echo_fork_index_agent.js +7 -0
  52. package/lib/experimental_agents/test_agents/index.d.ts +5 -0
  53. package/lib/experimental_agents/test_agents/index.js +13 -0
  54. package/lib/experimental_agents/test_agents/merge_node_id_agent.d.ts +2 -0
  55. package/lib/experimental_agents/test_agents/merge_node_id_agent.js +10 -0
  56. package/lib/experimental_agents/token_agent.d.ts +6 -0
  57. package/lib/experimental_agents/token_agent.js +33 -0
  58. package/lib/graphai.d.ts +28 -111
  59. package/lib/graphai.js +140 -322
  60. package/lib/index.d.ts +2 -0
  61. package/lib/log.d.ts +22 -0
  62. package/lib/log.js +49 -0
  63. package/lib/node.d.ts +50 -0
  64. package/lib/node.js +218 -0
  65. package/lib/task.d.ts +18 -0
  66. package/lib/task.js +63 -0
  67. package/lib/task_manager.d.ts +20 -0
  68. package/lib/task_manager.js +69 -0
  69. package/lib/transaction_log.d.ts +27 -0
  70. package/lib/transaction_log.js +56 -0
  71. package/lib/type.d.ts +77 -0
  72. package/lib/type.js +14 -0
  73. package/lib/utils/utils.d.ts +4 -0
  74. package/lib/utils/utils.js +22 -1
  75. package/lib/validator.d.ts +2 -0
  76. package/lib/validator.js +28 -0
  77. package/lib/validators/agent_validator.d.ts +1 -0
  78. package/lib/validators/agent_validator.js +12 -0
  79. package/lib/validators/common.d.ts +3 -0
  80. package/lib/validators/common.js +6 -0
  81. package/lib/validators/computed_node_validator.d.ts +2 -0
  82. package/lib/validators/computed_node_validator.js +13 -0
  83. package/lib/validators/graph_data_validator.d.ts +3 -0
  84. package/lib/validators/graph_data_validator.js +43 -0
  85. package/lib/validators/nodeValidator.d.ts +2 -0
  86. package/lib/validators/nodeValidator.js +13 -0
  87. package/lib/validators/relation_validator.d.ts +2 -0
  88. package/lib/validators/relation_validator.js +62 -0
  89. package/lib/validators/static_node_validator.d.ts +2 -0
  90. package/lib/validators/static_node_validator.js +13 -0
  91. package/package.json +3 -5
  92. package/lib/experimental_agents/array_agents.d.ts +0 -4
  93. package/lib/experimental_agents/data_agent.d.ts +0 -3
  94. package/lib/experimental_agents/data_agent.js +0 -25
  95. package/lib/experimental_agents/sleeper_agent.d.ts +0 -10
  96. package/lib/experimental_agents/string_agent.d.ts +0 -7
  97. package/lib/graphai_cli.d.ts +0 -2
  98. package/lib/graphai_cli.js +0 -37
package/lib/graphai.js CHANGED
@@ -1,301 +1,88 @@
1
1
  "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.GraphAI = exports.NodeState = void 0;
4
- var NodeState;
5
- (function (NodeState) {
6
- NodeState["Waiting"] = "waiting";
7
- NodeState["Executing"] = "executing";
8
- NodeState["Failed"] = "failed";
9
- NodeState["TimedOut"] = "timed-out";
10
- NodeState["Completed"] = "completed";
11
- NodeState["Injected"] = "injected";
12
- NodeState["Dispatched"] = "dispatched";
13
- })(NodeState || (exports.NodeState = NodeState = {}));
14
- const parseNodeName = (name) => {
15
- const parts = name.split(".");
16
- if (parts.length == 1) {
17
- return { sourceNodeId: parts[0] };
18
- }
19
- else {
20
- return { sourceNodeId: parts[0], propId: parts[1] };
21
- }
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
22
4
  };
23
- class Node {
24
- constructor(nodeId, forkIndex, data, graph) {
25
- this.inputProps = {}; // optional properties for input
26
- this.waitlist = new Set(); // List of nodes which need data from this node.
27
- this.state = NodeState.Waiting;
28
- this.result = undefined;
29
- this.retryCount = 0;
30
- this.nodeId = nodeId;
31
- this.forkIndex = forkIndex;
32
- this.inputs = (data.inputs ?? []).map((input) => {
33
- const { sourceNodeId, propId } = parseNodeName(input);
34
- if (propId) {
35
- this.inputProps[sourceNodeId] = propId;
36
- }
37
- return sourceNodeId;
38
- });
39
- this.pendings = new Set(this.inputs);
40
- this.params = data.params ?? {};
41
- this.agentId = data.agentId ?? graph.agentId;
42
- this.fork = data.fork;
43
- this.retryLimit = data.retry ?? 0;
44
- this.timeout = data.timeout;
45
- this.source = this.agentId === undefined;
46
- this.outputs = data.outputs;
47
- this.graph = graph;
48
- }
49
- asString() {
50
- return `${this.nodeId}: ${this.state} ${[...this.waitlist]}`;
51
- }
52
- retry(state, error) {
53
- if (this.retryCount < this.retryLimit) {
54
- this.retryCount++;
55
- this.execute();
56
- }
57
- else {
58
- this.state = state;
59
- this.result = undefined;
60
- this.error = error;
61
- this.transactionId = undefined; // This is necessary for timeout case
62
- this.graph.removeRunning(this);
63
- }
64
- }
65
- removePending(nodeId) {
66
- this.pendings.delete(nodeId);
67
- if (this.graph.isRunning) {
68
- this.pushQueueIfReady();
69
- }
70
- }
71
- pushQueueIfReady() {
72
- if (this.pendings.size === 0 && !this.source) {
73
- // If input property is specified, we need to ensure that the property value exists.
74
- Object.keys(this.inputProps).forEach((nodeId) => {
75
- const [result] = this.graph.resultsOf([nodeId]);
76
- const propId = this.inputProps[nodeId];
77
- if (!result || !(propId in result)) {
78
- return;
79
- }
80
- });
81
- this.graph.pushQueue(this);
82
- }
83
- }
84
- injectValue(value) {
85
- if (this.source) {
86
- const log = {
87
- nodeId: this.nodeId,
88
- retryCount: this.retryCount,
89
- state: NodeState.Injected,
90
- startTime: Date.now(),
91
- endTime: Date.now(),
92
- result: value,
93
- };
94
- this.graph.appendLog(log);
95
- this.setResult(value, NodeState.Injected);
96
- }
97
- else {
98
- console.error("- injectValue called on non-source node.", this.nodeId);
99
- }
100
- }
101
- setResult(result, state) {
102
- this.state = state;
103
- this.result = result;
104
- this.waitlist.forEach((nodeId) => {
105
- const node = this.graph.nodes[nodeId];
106
- // Todo: Avoid running before Run()
107
- node.removePending(this.nodeId);
108
- });
109
- }
110
- async execute() {
111
- const results = this.graph.resultsOf(this.inputs);
112
- this.inputs.forEach((nodeId, index) => {
113
- const propId = this.inputProps[nodeId];
114
- if (propId) {
115
- results[index] = results[index][propId];
116
- }
117
- });
118
- const transactionId = Date.now();
119
- const log = {
120
- nodeId: this.nodeId,
121
- retryCount: this.retryCount > 0 ? this.retryCount : undefined,
122
- state: NodeState.Executing,
123
- startTime: transactionId,
124
- agentId: this.agentId,
125
- params: this.params,
126
- inputs: results.length > 0 ? results : undefined,
127
- };
128
- this.graph.appendLog(log);
129
- this.state = NodeState.Executing;
130
- this.transactionId = transactionId;
131
- if (this.timeout && this.timeout > 0) {
132
- setTimeout(() => {
133
- if (this.state === NodeState.Executing && this.transactionId === transactionId) {
134
- console.log(`-- ${this.nodeId}: timeout ${this.timeout}`);
135
- log.errorMessage = "Timeout";
136
- log.state = NodeState.TimedOut;
137
- log.endTime = Date.now();
138
- this.retry(NodeState.TimedOut, Error("Timeout"));
139
- }
140
- }, this.timeout);
141
- }
142
- try {
143
- const callback = this.graph.getCallback(this.agentId);
144
- const localLog = [];
145
- const result = await callback({
146
- nodeId: this.nodeId,
147
- retry: this.retryCount,
148
- params: this.params,
149
- inputs: results,
150
- forkIndex: this.forkIndex,
151
- verbose: this.graph.verbose,
152
- agents: this.graph.callbackDictonary,
153
- log: localLog,
154
- });
155
- if (this.transactionId !== transactionId) {
156
- console.log(`-- ${this.nodeId}: transactionId mismatch`);
157
- return;
158
- }
159
- log.endTime = Date.now();
160
- log.result = result;
161
- if (localLog.length > 0) {
162
- log.log = localLog;
163
- }
164
- const outputs = this.outputs;
165
- if (outputs !== undefined) {
166
- Object.keys(outputs).forEach((outputId) => {
167
- const nodeId = outputs[outputId];
168
- const value = result[outputId];
169
- if (value) {
170
- this.graph.injectValue(nodeId, value);
171
- }
172
- else {
173
- console.error("-- Invalid outputId", outputId, result);
174
- }
175
- });
176
- log.state = NodeState.Dispatched;
177
- this.state = NodeState.Dispatched;
178
- this.graph.removeRunning(this);
179
- return;
180
- }
181
- log.state = NodeState.Completed;
182
- this.setResult(result, NodeState.Completed);
183
- this.graph.removeRunning(this);
184
- }
185
- catch (error) {
186
- if (this.transactionId !== transactionId) {
187
- console.log(`-- ${this.nodeId}: transactionId mismatch(error)`);
188
- return;
189
- }
190
- log.state = NodeState.Failed;
191
- log.endTime = Date.now();
192
- if (error instanceof Error) {
193
- log.errorMessage = error.message;
194
- this.retry(NodeState.Failed, error);
195
- }
196
- else {
197
- console.error(`-- ${this.nodeId}: Unexpecrted error was caught`);
198
- log.errorMessage = "Unknown";
199
- this.retry(NodeState.Failed, Error("Unknown"));
200
- }
201
- }
202
- }
203
- }
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.GraphAI = void 0;
7
+ const type_1 = require("./type");
8
+ const node_1 = require("./node");
9
+ const utils_1 = require("./utils/utils");
10
+ const validator_1 = require("./validator");
11
+ const task_manager_1 = require("./task_manager");
12
+ const crypto_1 = __importDefault(require("crypto"));
204
13
  const defaultConcurrency = 8;
205
14
  class GraphAI {
15
+ // This method is called when either the GraphAI obect was created,
16
+ // or we are about to start n-th iteration (n>2).
206
17
  createNodes(data) {
207
- const nodeId2forkedNodeIds = {};
208
- const forkedNodeId2Index = {};
209
- const nodes = Object.keys(data.nodes).reduce((nodes, nodeId) => {
210
- const fork = data.nodes[nodeId].fork;
211
- if (fork) {
212
- // For fork, change the nodeId and increase the node
213
- nodeId2forkedNodeIds[nodeId] = new Array(fork).fill(undefined).map((_, i) => {
214
- const forkedNodeId = `${nodeId}_${i}`;
215
- nodes[forkedNodeId] = new Node(forkedNodeId, i, data.nodes[nodeId], this);
216
- // Data for pending and waiting
217
- forkedNodeId2Index[forkedNodeId] = i;
218
- return forkedNodeId;
219
- });
18
+ const nodes = Object.keys(data.nodes).reduce((_nodes, nodeId) => {
19
+ const isStaticNode = "value" in data.nodes[nodeId];
20
+ if (isStaticNode) {
21
+ _nodes[nodeId] = new node_1.StaticNode(nodeId, data.nodes[nodeId], this);
220
22
  }
221
23
  else {
222
- nodes[nodeId] = new Node(nodeId, undefined, data.nodes[nodeId], this);
24
+ const nodeData = data.nodes[nodeId];
25
+ _nodes[nodeId] = new node_1.ComputedNode(this.graphId, nodeId, nodeData, this);
223
26
  }
224
- return nodes;
27
+ return _nodes;
225
28
  }, {});
226
- // Generate the waitlist for each node, and update the pendings in case of forked node.
29
+ // Generate the waitlist for each node.
227
30
  Object.keys(nodes).forEach((nodeId) => {
228
31
  const node = nodes[nodeId];
229
- node.pendings.forEach((pending) => {
230
- // If the pending(previous) node is forking
231
- if (nodeId2forkedNodeIds[pending]) {
232
- // update node.pending and pending(previous) node.wailtlist
233
- if (node.fork) {
234
- // 1:1 if current nodes are also forking.
235
- const newPendingId = nodeId2forkedNodeIds[pending][forkedNodeId2Index[nodeId]];
236
- nodes[newPendingId].waitlist.add(nodeId); // previousNode
237
- node.pendings.add(newPendingId);
238
- }
239
- else {
240
- // 1:n if current node is not forking.
241
- nodeId2forkedNodeIds[pending].forEach((newPendingId) => {
242
- nodes[newPendingId].waitlist.add(nodeId); // previousNode
243
- node.pendings.add(newPendingId);
244
- });
245
- }
246
- node.pendings.delete(pending);
247
- }
248
- else {
32
+ if (node.isComputedNode) {
33
+ node.pendings.forEach((pending) => {
249
34
  if (nodes[pending]) {
250
35
  nodes[pending].waitlist.add(nodeId); // previousNode
251
36
  }
252
37
  else {
253
38
  console.error(`--- invalid input ${pending} for node, ${nodeId}`);
254
39
  }
255
- }
256
- });
257
- node.inputs = Array.from(node.pendings); // for fork.
40
+ });
41
+ }
258
42
  });
259
43
  return nodes;
260
44
  }
261
45
  getValueFromResults(key, results) {
262
- const { sourceNodeId, propId } = parseNodeName(key);
263
- const result = results[sourceNodeId];
264
- return result ? (propId ? result[propId] : result) : undefined;
46
+ const source = (0, utils_1.parseNodeName)(key);
47
+ const result = results[source.nodeId];
48
+ return result && source.propId ? result[source.propId] : result;
265
49
  }
50
+ // for static
266
51
  initializeNodes(previousResults) {
267
52
  // If the result property is specified, inject it.
268
53
  // If the previousResults exists (indicating we are in a loop),
269
- // process the next property (nodeId or nodeId.propId).
54
+ // process the update property (nodeId or nodeId.propId).
270
55
  Object.keys(this.data.nodes).forEach((nodeId) => {
271
- const node = this.data.nodes[nodeId];
272
- const { value, next } = node;
273
- if (value) {
274
- this.injectValue(nodeId, value);
275
- }
276
- if (next && previousResults) {
277
- const result = this.getValueFromResults(next, previousResults);
278
- if (result) {
279
- this.injectValue(nodeId, result);
56
+ const node = this.nodes[nodeId];
57
+ if (node?.isStaticNode) {
58
+ const value = node?.value;
59
+ const update = node?.update;
60
+ if (value) {
61
+ this.injectValue(nodeId, value, nodeId);
62
+ }
63
+ if (update && previousResults) {
64
+ const result = this.getValueFromResults(update, previousResults);
65
+ if (result) {
66
+ this.injectValue(nodeId, result, update);
67
+ }
280
68
  }
281
69
  }
282
70
  });
283
71
  }
284
- constructor(data, callbackDictonary) {
285
- this.isRunning = false;
286
- this.runningNodes = new Set();
287
- this.nodeQueue = [];
288
- this.repeatCount = 0;
72
+ constructor(data, callbackDictonary, taskManager = undefined) {
289
73
  this.logs = [];
74
+ this.onLogCallback = (__log, __isUpdate) => { };
75
+ this.repeatCount = 0;
76
+ this.graphId = crypto_1.default.randomUUID();
290
77
  this.data = data;
291
78
  this.callbackDictonary = callbackDictonary;
292
- this.concurrency = data.concurrency ?? defaultConcurrency;
79
+ this.taskManager = taskManager ?? new task_manager_1.TaskManager(data.concurrency ?? defaultConcurrency);
293
80
  this.loop = data.loop;
294
- this.agentId = data.agentId;
295
81
  this.verbose = data.verbose === true;
296
82
  this.onComplete = () => {
297
83
  console.error("-- SOMETHING IS WRONG: onComplete is called without run()");
298
84
  };
85
+ (0, validator_1.validateGraphData)(data, Object.keys(callbackDictonary));
299
86
  this.nodes = this.createNodes(data);
300
87
  this.initializeNodes();
301
88
  }
@@ -306,14 +93,18 @@ class GraphAI {
306
93
  throw new Error("No agent: " + agentId);
307
94
  }
308
95
  asString() {
309
- return Object.keys(this.nodes)
310
- .map((nodeId) => {
311
- return this.nodes[nodeId].asString();
312
- })
96
+ return Object.values(this.nodes)
97
+ .map((node) => node.asString())
313
98
  .join("\n");
314
99
  }
315
- results() {
316
- return Object.keys(this.nodes).reduce((results, nodeId) => {
100
+ // Public API
101
+ results(all) {
102
+ return Object.keys(this.nodes)
103
+ .filter((nodeId) => {
104
+ const node = this.nodes[nodeId];
105
+ return all || node.isResult;
106
+ })
107
+ .reduce((results, nodeId) => {
317
108
  const node = this.nodes[nodeId];
318
109
  if (node.result !== undefined) {
319
110
  results[nodeId] = node.result;
@@ -321,11 +112,14 @@ class GraphAI {
321
112
  return results;
322
113
  }, {});
323
114
  }
115
+ // Public API
324
116
  errors() {
325
117
  return Object.keys(this.nodes).reduce((errors, nodeId) => {
326
118
  const node = this.nodes[nodeId];
327
- if (node.error !== undefined) {
328
- errors[nodeId] = node.error;
119
+ if (node.isComputedNode) {
120
+ if (node.error !== undefined) {
121
+ errors[nodeId] = node.error;
122
+ }
329
123
  }
330
124
  return errors;
331
125
  }, {});
@@ -334,92 +128,116 @@ class GraphAI {
334
128
  // Nodes without pending data should run immediately.
335
129
  Object.keys(this.nodes).forEach((nodeId) => {
336
130
  const node = this.nodes[nodeId];
337
- node.pushQueueIfReady();
131
+ if (node.isComputedNode) {
132
+ this.pushQueueIfReady(node);
133
+ }
338
134
  });
339
135
  }
340
- async run() {
341
- if (this.isRunning) {
136
+ pushQueueIfReady(node) {
137
+ if (node.isReadyNode()) {
138
+ this.pushQueue(node);
139
+ }
140
+ }
141
+ pushQueueIfReadyAndRunning(node) {
142
+ if (this.isRunning()) {
143
+ this.pushQueueIfReady(node);
144
+ }
145
+ }
146
+ // for computed
147
+ pushQueue(node) {
148
+ node.state = type_1.NodeState.Queued;
149
+ this.taskManager.addTask(node, this.graphId, (_node) => {
150
+ (0, utils_1.assert)(node.nodeId === _node.nodeId, "GraphAI.pushQueue node mismatch");
151
+ node.execute();
152
+ });
153
+ }
154
+ // Public API
155
+ async run(all = false) {
156
+ if (this.isRunning()) {
342
157
  console.error("-- Already Running");
343
158
  }
344
- this.isRunning = true;
345
159
  this.pushReadyNodesIntoQueue();
346
160
  return new Promise((resolve, reject) => {
347
161
  this.onComplete = () => {
348
- this.isRunning = false;
349
162
  const errors = this.errors();
350
163
  const nodeIds = Object.keys(errors);
351
164
  if (nodeIds.length > 0) {
352
165
  reject(errors[nodeIds[0]]);
353
166
  }
354
167
  else {
355
- resolve(this.results());
168
+ resolve(this.results(all));
356
169
  }
357
170
  };
358
171
  });
359
172
  }
360
- runNode(node) {
361
- this.runningNodes.add(node.nodeId);
362
- node.execute();
363
- }
364
- pushQueue(node) {
365
- if (this.runningNodes.size < this.concurrency) {
366
- this.runNode(node);
367
- }
368
- else {
369
- this.nodeQueue.push(node);
370
- }
371
- }
372
- removeRunning(node) {
373
- this.runningNodes.delete(node.nodeId);
374
- if (this.nodeQueue.length > 0) {
375
- const n = this.nodeQueue.shift();
376
- if (n) {
377
- this.runNode(n);
378
- }
379
- }
380
- if (this.runningNodes.size === 0) {
381
- this.repeatCount++;
382
- const loop = this.loop;
383
- if (loop && (loop.count === undefined || this.repeatCount < loop.count)) {
384
- const results = this.results(); // results from previous loop
385
- this.isRunning = false; // temporarily stop it
386
- this.nodes = this.createNodes(this.data);
387
- this.initializeNodes(results);
388
- const checkWhileCondition = () => {
389
- if (loop.while) {
390
- const value = this.getValueFromResults(loop.while, this.results());
391
- // NOTE: We treat an empty array as false.
392
- return Array.isArray(value) ? value.length > 0 : !!value;
393
- }
394
- return true;
395
- };
396
- if (checkWhileCondition()) {
397
- this.isRunning = true; // restore it
398
- this.pushReadyNodesIntoQueue();
399
- return;
173
+ // Public only for testing
174
+ isRunning() {
175
+ return this.taskManager.isRunning(this.graphId);
176
+ }
177
+ // callback from execute
178
+ onExecutionComplete(node) {
179
+ this.taskManager.onComplete(node);
180
+ if (this.isRunning() || this.processLoopIfNecessary()) {
181
+ return; // continue running
182
+ }
183
+ this.onComplete(); // Nothing to run. Finish it.
184
+ }
185
+ // Must be called only from onExecutionComplete righ after removeRunning
186
+ // Check if there is any running computed nodes.
187
+ // In case of no running computed note, start the another iteration if ncessary (loop)
188
+ processLoopIfNecessary() {
189
+ this.repeatCount++;
190
+ const loop = this.loop;
191
+ if (loop && (loop.count === undefined || this.repeatCount < loop.count)) {
192
+ const results = this.results(true); // results from previous loop
193
+ this.nodes = this.createNodes(this.data);
194
+ this.initializeNodes(results);
195
+ // Notice that we need to check the while condition *after* calling initializeNodes.
196
+ if (loop.while) {
197
+ const value = this.getValueFromResults(loop.while, this.results(true));
198
+ // NOTE: We treat an empty array as false.
199
+ if (Array.isArray(value) ? value.length === 0 : !value) {
200
+ return false; // while condition is not met
400
201
  }
401
202
  }
402
- this.onComplete();
203
+ this.pushReadyNodesIntoQueue();
204
+ return true; // Indicating that we are going to continue.
403
205
  }
206
+ return false;
207
+ }
208
+ setLoopLog(log) {
209
+ log.isLoop = !!this.loop;
210
+ log.repeatCount = this.repeatCount;
404
211
  }
405
212
  appendLog(log) {
406
213
  this.logs.push(log);
214
+ this.onLogCallback(log, false);
407
215
  }
216
+ updateLog(log) {
217
+ this.onLogCallback(log, true);
218
+ }
219
+ // Public API
408
220
  transactionLogs() {
409
221
  return this.logs;
410
222
  }
411
- injectValue(nodeId, value) {
223
+ // Public API
224
+ injectValue(nodeId, value, injectFrom) {
412
225
  const node = this.nodes[nodeId];
413
- if (node) {
414
- node.injectValue(value);
226
+ if (node && node.isStaticNode) {
227
+ node.injectValue(value, injectFrom);
415
228
  }
416
229
  else {
417
- console.error("-- Invalid nodeId", nodeId);
230
+ console.error("-- Inject Error: Invalid nodeId", nodeId);
231
+ console.error("InjectionTo can only specify static nodes");
418
232
  }
419
233
  }
420
- resultsOf(nodeIds) {
421
- return nodeIds.map((nodeId) => {
422
- return this.nodes[nodeId].result;
234
+ resultsOf(sources, anyInput = false) {
235
+ return sources.map((source) => {
236
+ const { result } = this.nodes[source.nodeId];
237
+ if (source.propId) {
238
+ (0, utils_1.assert)((0, utils_1.isObject)(result), `resultsOf: result is not object. nodeId ${source.nodeId}`, anyInput);
239
+ }
240
+ return result && source.propId ? result[source.propId] : result;
423
241
  });
424
242
  }
425
243
  }
package/lib/index.d.ts CHANGED
@@ -1,2 +1,4 @@
1
1
  import { GraphAI } from "./graphai";
2
2
  export { GraphAI };
3
+ export { AgentFunction, AgentFunctionDictonary, GraphData, ResultDataDictonary, ResultData } from "./type";
4
+ export type { TransactionLog } from "./transaction_log";
package/lib/log.d.ts ADDED
@@ -0,0 +1,22 @@
1
+ import { ResultData, NodeDataParams, NodeState } from "./type";
2
+ import type { GraphAI } from "./graphai";
3
+ import type { ComputedNode, StaticNode } from "./node";
4
+ export declare class TransactionLog {
5
+ nodeId: string;
6
+ state: NodeState;
7
+ startTime?: number;
8
+ endTime?: number;
9
+ retryCount?: number;
10
+ agentId?: string;
11
+ params?: NodeDataParams;
12
+ inputs?: Array<ResultData>;
13
+ errorMessage?: string;
14
+ result?: ResultData;
15
+ log?: TransactionLog[];
16
+ constructor(nodeId: string);
17
+ initForComputedNode(node: ComputedNode): void;
18
+ onInjected(node: StaticNode, graph: GraphAI): void;
19
+ onComplete(node: ComputedNode, graph: GraphAI, localLog: TransactionLog[]): void;
20
+ beforeExecute(node: ComputedNode, graph: GraphAI, transactionId: number, inputs: ResultData[]): void;
21
+ onError(node: ComputedNode, graph: GraphAI, errorMessage: string): void;
22
+ }
package/lib/log.js ADDED
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TransactionLog = void 0;
4
+ const type_1 = require("./type");
5
+ class TransactionLog {
6
+ constructor(nodeId) {
7
+ this.nodeId = nodeId;
8
+ this.state = type_1.NodeState.Waiting;
9
+ }
10
+ initForComputedNode(node) {
11
+ this.agentId = node.agentId;
12
+ this.params = node.params;
13
+ }
14
+ onInjected(node, graph) {
15
+ const isUpdating = "endTime" in this;
16
+ this.result = node.value;
17
+ this.state = node.state;
18
+ this.endTime = Date.now();
19
+ if (isUpdating) {
20
+ graph.updateLog(this);
21
+ }
22
+ else {
23
+ graph.appendLog(this);
24
+ }
25
+ }
26
+ onComplete(node, graph, localLog) {
27
+ this.result = node.result;
28
+ this.state = node.state;
29
+ this.endTime = Date.now();
30
+ if (localLog.length > 0) {
31
+ this.log = localLog;
32
+ }
33
+ graph.updateLog(this);
34
+ }
35
+ beforeExecute(node, graph, transactionId, inputs) {
36
+ this.state = node.state;
37
+ this.retryCount = node.retryCount > 0 ? node.retryCount : undefined;
38
+ this.startTime = transactionId;
39
+ this.inputs = inputs.length > 0 ? inputs : undefined;
40
+ graph.appendLog(this);
41
+ }
42
+ onError(node, graph, errorMessage) {
43
+ this.state = node.state;
44
+ this.errorMessage = errorMessage;
45
+ this.endTime = Date.now();
46
+ graph.updateLog(this);
47
+ }
48
+ }
49
+ exports.TransactionLog = TransactionLog;