graphai 0.5.9 → 0.5.10
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.js +2 -2
- package/lib/node.js +4 -4
- package/lib/result.d.ts +1 -1
- package/lib/result.js +8 -8
- package/lib/utils/nodeUtils.d.ts +1 -1
- package/lib/utils/nodeUtils.js +5 -5
- package/lib/utils/utils.d.ts +1 -1
- package/lib/utils/utils.js +29 -22
- package/lib/validators/relation_validator.js +28 -27
- package/package.json +2 -2
package/lib/graphai.js
CHANGED
|
@@ -228,7 +228,7 @@ class GraphAI {
|
|
|
228
228
|
this.updateStaticNodes(previousResults);
|
|
229
229
|
if (loop.count === undefined || this.repeatCount < loop.count) {
|
|
230
230
|
if (loop.while) {
|
|
231
|
-
const source = (0, utils_1.parseNodeName)(loop.while
|
|
231
|
+
const source = (0, utils_1.parseNodeName)(loop.while);
|
|
232
232
|
const value = this.getValueFromResults(source, this.results(true));
|
|
233
233
|
// NOTE: We treat an empty array as false.
|
|
234
234
|
if (!(0, utils_1.isLogicallyTrue)(value)) {
|
|
@@ -269,7 +269,7 @@ class GraphAI {
|
|
|
269
269
|
}
|
|
270
270
|
}
|
|
271
271
|
resultsOf(inputs, anyInput = false) {
|
|
272
|
-
const results = (0, result_1.resultsOf)(inputs ?? [], this.nodes
|
|
272
|
+
const results = (0, result_1.resultsOf)(inputs ?? [], this.nodes);
|
|
273
273
|
if (anyInput) {
|
|
274
274
|
return (0, result_1.cleanResult)(results);
|
|
275
275
|
}
|
package/lib/node.js
CHANGED
|
@@ -51,7 +51,7 @@ class ComputedNode extends Node {
|
|
|
51
51
|
this.anyInput = data.anyInput ?? false;
|
|
52
52
|
this.inputs = data.inputs;
|
|
53
53
|
this.isNamedInputs = (0, utils_2.isObject)(data.inputs) && !Array.isArray(data.inputs);
|
|
54
|
-
this.dataSources = data.inputs ? (0, nodeUtils_1.inputs2dataSources)(data.inputs
|
|
54
|
+
this.dataSources = data.inputs ? (0, nodeUtils_1.inputs2dataSources)(data.inputs).flat(10) : [];
|
|
55
55
|
if (data.inputs && !this.isNamedInputs) {
|
|
56
56
|
console.warn(`array inputs have been deprecated. nodeId: ${nodeId}: see https://github.com/receptron/graphai/blob/main/docs/NamedInputs.md`);
|
|
57
57
|
}
|
|
@@ -74,7 +74,7 @@ class ComputedNode extends Node {
|
|
|
74
74
|
this.unlessSource = this.addPendingNode(data.unless);
|
|
75
75
|
}
|
|
76
76
|
this.dynamicParams = Object.keys(this.params).reduce((tmp, key) => {
|
|
77
|
-
const dataSource = (0, utils_2.parseNodeName)(this.params[key]
|
|
77
|
+
const dataSource = (0, utils_2.parseNodeName)(this.params[key]);
|
|
78
78
|
if (dataSource.nodeId) {
|
|
79
79
|
(0, utils_2.assert)(!this.anyInput, "Dynamic params are not supported with anyInput");
|
|
80
80
|
tmp[key] = dataSource;
|
|
@@ -88,7 +88,7 @@ class ComputedNode extends Node {
|
|
|
88
88
|
return this.agentId ?? "__custom__function"; // only for display purpose in the log.
|
|
89
89
|
}
|
|
90
90
|
addPendingNode(nodeId) {
|
|
91
|
-
const source = (0, utils_2.parseNodeName)(nodeId
|
|
91
|
+
const source = (0, utils_2.parseNodeName)(nodeId);
|
|
92
92
|
(0, utils_2.assert)(!!source.nodeId, `Invalid data source ${nodeId}`);
|
|
93
93
|
this.pendings.add(source.nodeId);
|
|
94
94
|
return source;
|
|
@@ -340,7 +340,7 @@ class StaticNode extends Node {
|
|
|
340
340
|
this.isStaticNode = true;
|
|
341
341
|
this.isComputedNode = false;
|
|
342
342
|
this.value = data.value;
|
|
343
|
-
this.update = data.update ? (0, utils_2.parseNodeName)(data.update
|
|
343
|
+
this.update = data.update ? (0, utils_2.parseNodeName)(data.update) : undefined;
|
|
344
344
|
this.isResult = data.isResult ?? false;
|
|
345
345
|
}
|
|
346
346
|
injectValue(value, injectFrom) {
|
package/lib/result.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { DataSource, ResultData } from "./type";
|
|
2
2
|
import { GraphNodes } from "./node";
|
|
3
|
-
export declare const resultsOf: (inputs: Record<string, any> | Array<string>, nodes: GraphNodes
|
|
3
|
+
export declare const resultsOf: (inputs: Record<string, any> | Array<string>, nodes: GraphNodes) => Record<string, ResultData>;
|
|
4
4
|
export declare const resultOf: (source: DataSource, nodes: GraphNodes) => ResultData;
|
|
5
5
|
export declare const cleanResultInner: (results: ResultData) => ResultData | null;
|
|
6
6
|
export declare const cleanResult: (results: Record<string, ResultData | undefined>) => Record<string, ResultData>;
|
package/lib/result.js
CHANGED
|
@@ -2,35 +2,35 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.cleanResult = exports.cleanResultInner = exports.resultOf = exports.resultsOf = void 0;
|
|
4
4
|
const utils_1 = require("./utils/utils");
|
|
5
|
-
const resultsOfInner = (input, nodes
|
|
5
|
+
const resultsOfInner = (input, nodes) => {
|
|
6
6
|
if (Array.isArray(input)) {
|
|
7
|
-
return input.map((inp) => resultsOfInner(inp, nodes
|
|
7
|
+
return input.map((inp) => resultsOfInner(inp, nodes));
|
|
8
8
|
}
|
|
9
9
|
if ((0, utils_1.isNamedInputs)(input)) {
|
|
10
|
-
return (0, exports.resultsOf)(input, nodes
|
|
10
|
+
return (0, exports.resultsOf)(input, nodes);
|
|
11
11
|
}
|
|
12
12
|
if (typeof input === "string") {
|
|
13
13
|
const templateMatch = [...input.matchAll(/\${(:[^}]+)}/g)].map((m) => m[1]);
|
|
14
14
|
if (templateMatch.length > 0) {
|
|
15
|
-
const results = resultsOfInner(templateMatch, nodes
|
|
15
|
+
const results = resultsOfInner(templateMatch, nodes);
|
|
16
16
|
return Array.from(templateMatch.keys()).reduce((tmp, key) => {
|
|
17
17
|
return tmp.replaceAll("${" + templateMatch[key] + "}", results[key]);
|
|
18
18
|
}, input);
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
|
-
return (0, exports.resultOf)((0, utils_1.parseNodeName)(input
|
|
21
|
+
return (0, exports.resultOf)((0, utils_1.parseNodeName)(input), nodes);
|
|
22
22
|
};
|
|
23
|
-
const resultsOf = (inputs, nodes
|
|
23
|
+
const resultsOf = (inputs, nodes) => {
|
|
24
24
|
// for inputs. TODO remove if array input is not supported
|
|
25
25
|
if (Array.isArray(inputs)) {
|
|
26
26
|
return inputs.reduce((tmp, key) => {
|
|
27
|
-
tmp[key] = resultsOfInner(key, nodes
|
|
27
|
+
tmp[key] = resultsOfInner(key, nodes);
|
|
28
28
|
return tmp;
|
|
29
29
|
}, {});
|
|
30
30
|
}
|
|
31
31
|
return Object.keys(inputs).reduce((tmp, key) => {
|
|
32
32
|
const input = inputs[key];
|
|
33
|
-
tmp[key] = (0, utils_1.isNamedInputs)(input) ? (0, exports.resultsOf)(input, nodes
|
|
33
|
+
tmp[key] = (0, utils_1.isNamedInputs)(input) ? (0, exports.resultsOf)(input, nodes) : resultsOfInner(input, nodes);
|
|
34
34
|
return tmp;
|
|
35
35
|
}, {});
|
|
36
36
|
};
|
package/lib/utils/nodeUtils.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { DataSource } from "../type";
|
|
2
|
-
export declare const inputs2dataSources: (inputs: any
|
|
2
|
+
export declare const inputs2dataSources: (inputs: any) => DataSource[];
|
|
3
3
|
export declare const dataSourceNodeIds: (sources: DataSource[]) => string[];
|
package/lib/utils/nodeUtils.js
CHANGED
|
@@ -3,22 +3,22 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.dataSourceNodeIds = exports.inputs2dataSources = void 0;
|
|
4
4
|
const utils_1 = require("./utils");
|
|
5
5
|
// for dataSource
|
|
6
|
-
const inputs2dataSources = (inputs
|
|
6
|
+
const inputs2dataSources = (inputs) => {
|
|
7
7
|
if (Array.isArray(inputs)) {
|
|
8
|
-
return inputs.map((inp) => (0, exports.inputs2dataSources)(inp
|
|
8
|
+
return inputs.map((inp) => (0, exports.inputs2dataSources)(inp)).flat();
|
|
9
9
|
}
|
|
10
10
|
if ((0, utils_1.isObject)(inputs)) {
|
|
11
11
|
return Object.values(inputs)
|
|
12
|
-
.map((input) => (0, exports.inputs2dataSources)(input
|
|
12
|
+
.map((input) => (0, exports.inputs2dataSources)(input))
|
|
13
13
|
.flat();
|
|
14
14
|
}
|
|
15
15
|
if (typeof inputs === "string") {
|
|
16
16
|
const templateMatch = [...inputs.matchAll(/\${(:[^}]+)}/g)].map((m) => m[1]);
|
|
17
17
|
if (templateMatch.length > 0) {
|
|
18
|
-
return (0, exports.inputs2dataSources)(templateMatch
|
|
18
|
+
return (0, exports.inputs2dataSources)(templateMatch);
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
|
-
return (0, utils_1.parseNodeName)(inputs
|
|
21
|
+
return (0, utils_1.parseNodeName)(inputs);
|
|
22
22
|
};
|
|
23
23
|
exports.inputs2dataSources = inputs2dataSources;
|
|
24
24
|
const dataSourceNodeIds = (sources) => {
|
package/lib/utils/utils.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { DataSource, ResultData, AgentFunction, DefaultInputData } from "../type";
|
|
2
2
|
export declare const sleep: (milliseconds: number) => Promise<unknown>;
|
|
3
|
-
export declare const parseNodeName: (inputNodeId: any
|
|
3
|
+
export declare const parseNodeName: (inputNodeId: any) => DataSource;
|
|
4
4
|
export declare function assert(condition: boolean, message: string, isWarn?: boolean): asserts condition;
|
|
5
5
|
export declare const isObject: (x: unknown) => x is object;
|
|
6
6
|
export declare const isNull: (data: unknown) => data is null | undefined;
|
package/lib/utils/utils.js
CHANGED
|
@@ -6,25 +6,7 @@ const sleep = async (milliseconds) => {
|
|
|
6
6
|
return await new Promise((resolve) => setTimeout(resolve, milliseconds));
|
|
7
7
|
};
|
|
8
8
|
exports.sleep = sleep;
|
|
9
|
-
const
|
|
10
|
-
if (typeof inputNodeId === "string") {
|
|
11
|
-
const regex = /^"(.*)"$/;
|
|
12
|
-
const match = inputNodeId.match(regex);
|
|
13
|
-
if (match) {
|
|
14
|
-
return { value: match[1] }; // string literal
|
|
15
|
-
}
|
|
16
|
-
const parts = inputNodeId.split(".");
|
|
17
|
-
if (parts.length == 1) {
|
|
18
|
-
return { nodeId: parts[0] };
|
|
19
|
-
}
|
|
20
|
-
return { nodeId: parts[0], propIds: parts.slice(1) };
|
|
21
|
-
}
|
|
22
|
-
return { value: inputNodeId }; // non-string literal
|
|
23
|
-
};
|
|
24
|
-
const parseNodeName = (inputNodeId, version) => {
|
|
25
|
-
if (version === 0.2) {
|
|
26
|
-
return parseNodeName_02(inputNodeId);
|
|
27
|
-
}
|
|
9
|
+
const parseNodeName = (inputNodeId) => {
|
|
28
10
|
if (typeof inputNodeId === "string") {
|
|
29
11
|
const regex = /^:(.*)$/;
|
|
30
12
|
const match = inputNodeId.match(regex);
|
|
@@ -57,7 +39,9 @@ const isNull = (data) => {
|
|
|
57
39
|
};
|
|
58
40
|
exports.isNull = isNull;
|
|
59
41
|
const getNestedData = (result, propId) => {
|
|
42
|
+
// for array.
|
|
60
43
|
if (Array.isArray(result)) {
|
|
44
|
+
// $0, $1. array value.
|
|
61
45
|
const regex = /^\$(\d+)$/;
|
|
62
46
|
const match = propId.match(regex);
|
|
63
47
|
if (match) {
|
|
@@ -73,9 +57,13 @@ const getNestedData = (result, propId) => {
|
|
|
73
57
|
if (propId === "flat()") {
|
|
74
58
|
return result.flat();
|
|
75
59
|
}
|
|
76
|
-
|
|
60
|
+
if (propId === "toJSON()") {
|
|
61
|
+
return JSON.stringify(result);
|
|
62
|
+
}
|
|
63
|
+
// array join
|
|
64
|
+
const matchJoin = propId.match(/^join\(([,-]?)\)$/);
|
|
77
65
|
if (matchJoin && Array.isArray(matchJoin)) {
|
|
78
|
-
return result.join(matchJoin[1]);
|
|
66
|
+
return result.join(matchJoin[1] ?? "");
|
|
79
67
|
}
|
|
80
68
|
// flat, join
|
|
81
69
|
}
|
|
@@ -86,12 +74,28 @@ const getNestedData = (result, propId) => {
|
|
|
86
74
|
if (propId === "values()") {
|
|
87
75
|
return Object.values(result);
|
|
88
76
|
}
|
|
89
|
-
|
|
77
|
+
if (propId === "toJSON()") {
|
|
78
|
+
return JSON.stringify(result);
|
|
79
|
+
}
|
|
80
|
+
if (propId in result) {
|
|
81
|
+
return result[propId];
|
|
82
|
+
}
|
|
90
83
|
}
|
|
91
84
|
else if (typeof result === "string") {
|
|
92
85
|
if (propId === "jsonParse()") {
|
|
93
86
|
return JSON.parse(result);
|
|
94
87
|
}
|
|
88
|
+
if (propId === "toNumber()") {
|
|
89
|
+
const ret = Number(result);
|
|
90
|
+
if (!isNaN(ret)) {
|
|
91
|
+
return ret;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
else if (Number.isFinite(result)) {
|
|
96
|
+
if (propId === "toString()") {
|
|
97
|
+
return String(result);
|
|
98
|
+
}
|
|
95
99
|
}
|
|
96
100
|
return undefined;
|
|
97
101
|
};
|
|
@@ -99,6 +103,9 @@ const innerGetDataFromSource = (result, propIds) => {
|
|
|
99
103
|
if (result && propIds && propIds.length > 0) {
|
|
100
104
|
const propId = propIds[0];
|
|
101
105
|
const ret = getNestedData(result, propId);
|
|
106
|
+
if (ret === undefined) {
|
|
107
|
+
console.error(`prop: ${propIds.join(".")} is not hit`);
|
|
108
|
+
}
|
|
102
109
|
if (propIds.length > 1) {
|
|
103
110
|
return innerGetDataFromSource(ret, propIds.slice(1));
|
|
104
111
|
}
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.relationValidator = void 0;
|
|
4
4
|
const utils_1 = require("../utils/utils");
|
|
5
5
|
const common_1 = require("../validators/common");
|
|
6
|
+
const nodeUtils_1 = require("../utils/nodeUtils");
|
|
6
7
|
const relationValidator = (data, staticNodeIds, computedNodeIds) => {
|
|
7
8
|
const nodeIds = new Set(Object.keys(data.nodes));
|
|
8
9
|
const pendings = {};
|
|
@@ -11,34 +12,34 @@ const relationValidator = (data, staticNodeIds, computedNodeIds) => {
|
|
|
11
12
|
computedNodeIds.forEach((computedNodeId) => {
|
|
12
13
|
const nodeData = data.nodes[computedNodeId];
|
|
13
14
|
pendings[computedNodeId] = new Set();
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
if (!nodeIds.has(sourceNodeId)) {
|
|
20
|
-
throw new common_1.ValidationError(`Inputs not match: NodeId ${computedNodeId}, Inputs: ${sourceNodeId}`);
|
|
21
|
-
}
|
|
22
|
-
waitlist[sourceNodeId] === undefined && (waitlist[sourceNodeId] = new Set());
|
|
23
|
-
pendings[computedNodeId].add(sourceNodeId);
|
|
24
|
-
waitlist[sourceNodeId].add(computedNodeId);
|
|
15
|
+
const dataSourceValidator = (sourceType, sourceNodeIds) => {
|
|
16
|
+
sourceNodeIds.forEach((sourceNodeId) => {
|
|
17
|
+
if (sourceNodeId) {
|
|
18
|
+
if (!nodeIds.has(sourceNodeId)) {
|
|
19
|
+
throw new common_1.ValidationError(`${sourceType} not match: NodeId ${computedNodeId}, Inputs: ${sourceNodeId}`);
|
|
25
20
|
}
|
|
26
|
-
|
|
21
|
+
waitlist[sourceNodeId] === undefined && (waitlist[sourceNodeId] = new Set());
|
|
22
|
+
pendings[computedNodeId].add(sourceNodeId);
|
|
23
|
+
waitlist[sourceNodeId].add(computedNodeId);
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
};
|
|
27
|
+
if ("agent" in nodeData && nodeData) {
|
|
28
|
+
if (nodeData.inputs) {
|
|
29
|
+
const sourceNodeIds = (0, nodeUtils_1.dataSourceNodeIds)((0, nodeUtils_1.inputs2dataSources)(nodeData.inputs));
|
|
30
|
+
dataSourceValidator("Inputs", sourceNodeIds);
|
|
27
31
|
}
|
|
28
|
-
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
waitlist[sourceNodeId].add(computedNodeId);
|
|
40
|
-
}
|
|
41
|
-
});
|
|
32
|
+
if (nodeData.if) {
|
|
33
|
+
const sourceNodeIds = (0, nodeUtils_1.dataSourceNodeIds)((0, nodeUtils_1.inputs2dataSources)({ if: nodeData.if }));
|
|
34
|
+
dataSourceValidator("If", sourceNodeIds);
|
|
35
|
+
}
|
|
36
|
+
if (nodeData.unless) {
|
|
37
|
+
const sourceNodeIds = (0, nodeUtils_1.dataSourceNodeIds)((0, nodeUtils_1.inputs2dataSources)({ unless: nodeData.unless }));
|
|
38
|
+
dataSourceValidator("Unless", sourceNodeIds);
|
|
39
|
+
}
|
|
40
|
+
if (nodeData.graph && typeof nodeData?.graph === "string") {
|
|
41
|
+
const sourceNodeIds = (0, nodeUtils_1.dataSourceNodeIds)((0, nodeUtils_1.inputs2dataSources)({ graph: nodeData.graph }));
|
|
42
|
+
dataSourceValidator("Graph", sourceNodeIds);
|
|
42
43
|
}
|
|
43
44
|
}
|
|
44
45
|
});
|
|
@@ -47,7 +48,7 @@ const relationValidator = (data, staticNodeIds, computedNodeIds) => {
|
|
|
47
48
|
const nodeData = data.nodes[staticNodeId];
|
|
48
49
|
if ("value" in nodeData && nodeData.update) {
|
|
49
50
|
const update = nodeData.update;
|
|
50
|
-
const updateNodeId = (0, utils_1.parseNodeName)(update
|
|
51
|
+
const updateNodeId = (0, utils_1.parseNodeName)(update).nodeId;
|
|
51
52
|
if (!updateNodeId) {
|
|
52
53
|
throw new common_1.ValidationError("Update it a literal");
|
|
53
54
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "graphai",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.10",
|
|
4
4
|
"description": "Asynchronous data flow execution engine for agentic AI apps.",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"files": [
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
},
|
|
27
27
|
"homepage": "https://github.com/receptron/graphai#readme",
|
|
28
28
|
"devDependencies": {
|
|
29
|
-
"typedoc": "^0.26.
|
|
29
|
+
"typedoc": "^0.26.10"
|
|
30
30
|
},
|
|
31
31
|
"types": "./lib/index.d.ts",
|
|
32
32
|
"directories": {
|