From e7b4be6939047d6a6bac037f1b97524bd594c7f3 Mon Sep 17 00:00:00 2001 From: snakajima Date: Thu, 9 May 2024 12:51:25 -0700 Subject: [PATCH 1/9] version in parseNodeName --- src/graphai.ts | 4 ++-- src/node.ts | 6 +++--- src/utils/utils.ts | 2 +- src/validators/relation_validator.ts | 4 ++-- tests/units/test_utils.ts | 16 ++++++++-------- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/graphai.ts b/src/graphai.ts index 1bd1e0a8e..a97334576 100644 --- a/src/graphai.ts +++ b/src/graphai.ts @@ -13,7 +13,7 @@ type GraphNodes = Record; const defaultConcurrency = 8; export class GraphAI { - private readonly version: number; + public readonly version: number; private readonly graphId: string; private readonly data: GraphData; private readonly loop?: LoopData; @@ -62,7 +62,7 @@ export class GraphAI { } private getValueFromResults(key: string, results: ResultDataDictonary) { - const source = parseNodeName(key); + const source = parseNodeName(key, this.version); return getDataFromSource(source.nodeId ? results[source.nodeId] : undefined, source); } diff --git a/src/node.ts b/src/node.ts index 96b89b309..5b84b1efb 100644 --- a/src/node.ts +++ b/src/node.ts @@ -92,10 +92,10 @@ export class ComputedNode extends Node { this.priority = data.priority ?? 0; this.anyInput = data.anyInput ?? false; - this.dataSources = (data.inputs ?? []).map((input) => parseNodeName(input)); + this.dataSources = (data.inputs ?? []).map((input) => parseNodeName(input, graph.version)); this.pendings = new Set(this.dataSources.filter((source) => source.nodeId).map((source) => source.nodeId!)); if (data.if) { - this.ifSource = parseNodeName(data.if); + this.ifSource = parseNodeName(data.if, graph.version); assert(!!this.ifSource.nodeId, `Invalid data source ${data.if}`); this.pendings.add(this.ifSource.nodeId); } @@ -104,7 +104,7 @@ export class ComputedNode extends Node { const value = this.params[key]; const match = typeof value === "string" ? value.match(regex) : null; if (match) { - const dataSource = parseNodeName(match[1]); + const dataSource = parseNodeName(match[1], graph.version); tmp[key] = dataSource; assert(!!dataSource.nodeId, `Invalid data source ${key}:${value}`); this.pendings.add(dataSource.nodeId); diff --git a/src/utils/utils.ts b/src/utils/utils.ts index 3056eb106..71e1ad64c 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -4,7 +4,7 @@ export const sleep = async (milliseconds: number) => { return await new Promise((resolve) => setTimeout(resolve, milliseconds)); }; -export const parseNodeName = (inputNodeId: any): DataSource => { +export const parseNodeName = (inputNodeId: any, version: number): DataSource => { if (typeof inputNodeId === "string") { const regex = /^"(.*)"$/; const match = inputNodeId.match(regex); diff --git a/src/validators/relation_validator.ts b/src/validators/relation_validator.ts index 267095dd5..5530e3ff7 100644 --- a/src/validators/relation_validator.ts +++ b/src/validators/relation_validator.ts @@ -13,7 +13,7 @@ export const relationValidator = (data: GraphData, staticNodeIds: string[], comp pendings[computedNodeId] = new Set(); if ("inputs" in nodeData && nodeData && nodeData.inputs) { nodeData.inputs.forEach((inputNodeId) => { - const sourceNodeId = parseNodeName(inputNodeId).nodeId; + const sourceNodeId = parseNodeName(inputNodeId, data.version ?? 0.02).nodeId; if (sourceNodeId) { if (!nodeIds.has(sourceNodeId)) { throw new Error(`Inputs not match: NodeId ${computedNodeId}, Inputs: ${sourceNodeId}`); @@ -31,7 +31,7 @@ export const relationValidator = (data: GraphData, staticNodeIds: string[], comp const nodeData = data.nodes[staticNodeId]; if ("value" in nodeData && nodeData.update) { const update = nodeData.update; - const updateNodeId = parseNodeName(update).nodeId; + const updateNodeId = parseNodeName(update, data.version ?? 0.02).nodeId; if (!updateNodeId) { throw new Error("Update it a literal"); } diff --git a/tests/units/test_utils.ts b/tests/units/test_utils.ts index d519263bd..aeb18d385 100644 --- a/tests/units/test_utils.ts +++ b/tests/units/test_utils.ts @@ -8,7 +8,7 @@ test("test getDataFromSource", async () => { const result = { data: "123" }; const data = { data: "123" }; - const source = parseNodeName(inputId); + const source = parseNodeName(inputId, 0.02); const res = getDataFromSource(result, source); assert.deepStrictEqual(res, data); }); @@ -18,7 +18,7 @@ test("test getDataFromSource parseId", async () => { const result = { data: "123" }; const data = "123"; - const source = parseNodeName(inputId); + const source = parseNodeName(inputId, 0.02); const res = getDataFromSource(result, source); assert.deepStrictEqual(res, data); }); @@ -28,7 +28,7 @@ test("test getDataFromSource array", async () => { const result = ["123"]; const data = ["123"]; - const source = parseNodeName(inputId); + const source = parseNodeName(inputId, 0.02); const res = getDataFromSource(result, source); assert.deepStrictEqual(res, data); }); @@ -38,7 +38,7 @@ test("test getDataFromSource array $0", async () => { const result = ["000", "111"]; const data = "000"; - const source = parseNodeName(inputId); + const source = parseNodeName(inputId, 0.02); const res = getDataFromSource(result, source); assert.deepStrictEqual(res, data); }); @@ -48,7 +48,7 @@ test("test getDataFromSource array $1", async () => { const result = ["000", "111"]; const data = "111"; - const source = parseNodeName(inputId); + const source = parseNodeName(inputId, 0.02); const res = getDataFromSource(result, source); assert.deepStrictEqual(res, data); }); @@ -60,7 +60,7 @@ test("test getDataFromSource nested object", async () => { const result = { data: { sample: "123" } }; const data = "123"; - const source = parseNodeName(inputId); + const source = parseNodeName(inputId, 0.02); const res = getDataFromSource(result, source); assert.deepStrictEqual(res, data); }); @@ -70,7 +70,7 @@ test("test getDataFromSource nested array", async () => { const result = { data: { sample: [0, 1, 2, 3] } }; const data = 2; - const source = parseNodeName(inputId); + const source = parseNodeName(inputId, 0.02); const res = getDataFromSource(result, source); assert.deepStrictEqual(res, data); }); @@ -80,7 +80,7 @@ test("test getDataFromSource nested array last", async () => { const result = { data: { sample: [0, 1, 2, 3] } }; const data = 3; - const source = parseNodeName(inputId); + const source = parseNodeName(inputId, 0.02); const res = getDataFromSource(result, source); assert.deepStrictEqual(res, data); }); From 44c6d4441b7412c38ba0f53393942ca96e6efb4a Mon Sep 17 00:00:00 2001 From: snakajima Date: Thu, 9 May 2024 12:58:02 -0700 Subject: [PATCH 2/9] version 0.3 parser --- src/utils/utils.ts | 21 ++++++++++++++++++++- tests/units/test_utils.ts | 16 ++++++++-------- 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/src/utils/utils.ts b/src/utils/utils.ts index 71e1ad64c..d763af43f 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -4,7 +4,7 @@ export const sleep = async (milliseconds: number) => { return await new Promise((resolve) => setTimeout(resolve, milliseconds)); }; -export const parseNodeName = (inputNodeId: any, version: number): DataSource => { +const parseNodeName_02 = (inputNodeId: any) => { if (typeof inputNodeId === "string") { const regex = /^"(.*)"$/; const match = inputNodeId.match(regex); @@ -18,6 +18,25 @@ export const parseNodeName = (inputNodeId: any, version: number): DataSource => return { nodeId: parts[0], propIds: parts.slice(1) }; } return { value: inputNodeId }; // non-string literal +} + +export const parseNodeName = (inputNodeId: any, version: number): DataSource => { + if (version === 0.2) { + return parseNodeName_02(inputNodeId); + } + if (typeof inputNodeId === "string") { + const regex = /^:(.*)$/; + const match = inputNodeId.match(regex); + if (!match) { + return { value: inputNodeId }; // string literal + } + const parts = match[1].split("."); + if (parts.length == 1) { + return { nodeId: parts[0] }; + } + return { nodeId: parts[0], propIds: parts.slice(1) }; + } + return { value: inputNodeId }; // non-string literal }; export function assert(condition: boolean, message: string, isWarn: boolean = false): asserts condition { diff --git a/tests/units/test_utils.ts b/tests/units/test_utils.ts index aeb18d385..56bcc1bcc 100644 --- a/tests/units/test_utils.ts +++ b/tests/units/test_utils.ts @@ -8,7 +8,7 @@ test("test getDataFromSource", async () => { const result = { data: "123" }; const data = { data: "123" }; - const source = parseNodeName(inputId, 0.02); + const source = parseNodeName(inputId, 0.2); const res = getDataFromSource(result, source); assert.deepStrictEqual(res, data); }); @@ -18,7 +18,7 @@ test("test getDataFromSource parseId", async () => { const result = { data: "123" }; const data = "123"; - const source = parseNodeName(inputId, 0.02); + const source = parseNodeName(inputId, 0.2); const res = getDataFromSource(result, source); assert.deepStrictEqual(res, data); }); @@ -28,7 +28,7 @@ test("test getDataFromSource array", async () => { const result = ["123"]; const data = ["123"]; - const source = parseNodeName(inputId, 0.02); + const source = parseNodeName(inputId, 0.2); const res = getDataFromSource(result, source); assert.deepStrictEqual(res, data); }); @@ -38,7 +38,7 @@ test("test getDataFromSource array $0", async () => { const result = ["000", "111"]; const data = "000"; - const source = parseNodeName(inputId, 0.02); + const source = parseNodeName(inputId, 0.2); const res = getDataFromSource(result, source); assert.deepStrictEqual(res, data); }); @@ -48,7 +48,7 @@ test("test getDataFromSource array $1", async () => { const result = ["000", "111"]; const data = "111"; - const source = parseNodeName(inputId, 0.02); + const source = parseNodeName(inputId, 0.2); const res = getDataFromSource(result, source); assert.deepStrictEqual(res, data); }); @@ -60,7 +60,7 @@ test("test getDataFromSource nested object", async () => { const result = { data: { sample: "123" } }; const data = "123"; - const source = parseNodeName(inputId, 0.02); + const source = parseNodeName(inputId, 0.2); const res = getDataFromSource(result, source); assert.deepStrictEqual(res, data); }); @@ -70,7 +70,7 @@ test("test getDataFromSource nested array", async () => { const result = { data: { sample: [0, 1, 2, 3] } }; const data = 2; - const source = parseNodeName(inputId, 0.02); + const source = parseNodeName(inputId, 0.2); const res = getDataFromSource(result, source); assert.deepStrictEqual(res, data); }); @@ -80,7 +80,7 @@ test("test getDataFromSource nested array last", async () => { const result = { data: { sample: [0, 1, 2, 3] } }; const data = 3; - const source = parseNodeName(inputId, 0.02); + const source = parseNodeName(inputId, 0.2); const res = getDataFromSource(result, source); assert.deepStrictEqual(res, data); }); From cbeba47be0bc52428e0df991a0da00e96d390019 Mon Sep 17 00:00:00 2001 From: snakajima Date: Thu, 9 May 2024 13:01:23 -0700 Subject: [PATCH 3/9] version 0.3 test cases --- tests/graphs/test_base.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/graphs/test_base.yml b/tests/graphs/test_base.yml index bcdb16bd6..51b5c1b05 100644 --- a/tests/graphs/test_base.yml +++ b/tests/graphs/test_base.yml @@ -1,4 +1,4 @@ -version: 0.2 +version: 0.3 nodes: node1: agent: sleeperAgent @@ -18,18 +18,18 @@ nodes: duration: 500 value: node3: output - inputs: [node1, node2] + inputs: [:node1, :node2] node4: agent: sleeperAgent params: duration: 100 value: node4: output - inputs: [node3] + inputs: [:node3] node5: agent: sleeperAgent params: duration: 500 value: node5: output - inputs: [node2, node4] + inputs: [:node2, :node4] From 2c59fa3f6f11d8cf07b5166f763c50c9c9dddec1 Mon Sep 17 00:00:00 2001 From: snakajima Date: Thu, 9 May 2024 13:31:40 -0700 Subject: [PATCH 4/9] dynamic params --- src/node.ts | 8 ++------ tests/graphai/test_params.ts | 14 +++++++------- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/src/node.ts b/src/node.ts index 5b84b1efb..ed124f760 100644 --- a/src/node.ts +++ b/src/node.ts @@ -99,14 +99,10 @@ export class ComputedNode extends Node { assert(!!this.ifSource.nodeId, `Invalid data source ${data.if}`); this.pendings.add(this.ifSource.nodeId); } - const regex = /^\$\{([^{}]+)\}$/; this.dynamicParams = Object.keys(this.params).reduce((tmp: Record, key) => { - const value = this.params[key]; - const match = typeof value === "string" ? value.match(regex) : null; - if (match) { - const dataSource = parseNodeName(match[1], graph.version); + const dataSource = parseNodeName(this.params[key], graph.version); + if (dataSource.nodeId) { tmp[key] = dataSource; - assert(!!dataSource.nodeId, `Invalid data source ${key}:${value}`); this.pendings.add(dataSource.nodeId); } return tmp; diff --git a/tests/graphai/test_params.ts b/tests/graphai/test_params.ts index f5c28bbc1..4e0245ddd 100644 --- a/tests/graphai/test_params.ts +++ b/tests/graphai/test_params.ts @@ -10,7 +10,7 @@ const testAgent: AgentFunction, any> = async ({ params }) = }; const graphData_literal = { - version: 0.2, + version: 0.3, nodes: { source1: { value: { apple: "red" }, @@ -20,28 +20,28 @@ const graphData_literal = { }, delayed1: { agent: "sleeperAgent", - inputs: ["source1"], + inputs: [":source1"], }, delayed2: { agent: "sleeperAgent", params: { duration: 100, }, - inputs: ["source2"], + inputs: [":source2"], }, test1: { agent: "testAgent", params: { - fruit: "${source1}", - color: "${source2.lemon}", + fruit: ":source1", + color: ":source2.lemon", }, isResult: true, }, test2: { agent: "testAgent", params: { - fruit: "${delayed1}", - color: "${delayed2.lemon}", + fruit: ":delayed1", + color: ":delayed2.lemon", }, isResult: true, }, From 73c91fd28a7c6971e9f9ae9d5c80f22d1f49d71a Mon Sep 17 00:00:00 2001 From: snakajima Date: Thu, 9 May 2024 13:36:34 -0700 Subject: [PATCH 5/9] fix test --- src/node.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/node.ts b/src/node.ts index ed124f760..8fdcb2b99 100644 --- a/src/node.ts +++ b/src/node.ts @@ -100,7 +100,7 @@ export class ComputedNode extends Node { this.pendings.add(this.ifSource.nodeId); } this.dynamicParams = Object.keys(this.params).reduce((tmp: Record, key) => { - const dataSource = parseNodeName(this.params[key], graph.version); + const dataSource = parseNodeName(this.params[key], graph.version < 0.3 ? 0.3 : graph.version); if (dataSource.nodeId) { tmp[key] = dataSource; this.pendings.add(dataSource.nodeId); From d999c08e9d180db88cd36110da335c82f16a7792 Mon Sep 17 00:00:00 2001 From: snakajima Date: Thu, 9 May 2024 13:40:46 -0700 Subject: [PATCH 6/9] version in interaction.ts --- samples/interaction.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/samples/interaction.ts b/samples/interaction.ts index 8026f6114..a2676430b 100644 --- a/samples/interaction.ts +++ b/samples/interaction.ts @@ -5,6 +5,7 @@ import { graphDataTestRunner } from "~/utils/runner"; import { interactiveInputTextAgent } from "./agents/interactiveInputAgent"; const graph_data = { + version: 0.2, loop: { count: 3, }, From 6a8b13346409e111bb92fc2c9f23dc6d48a97971 Mon Sep 17 00:00:00 2001 From: snakajima Date: Thu, 9 May 2024 13:41:29 -0700 Subject: [PATCH 7/9] version 0.3 for interactions.ts --- samples/interaction.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/samples/interaction.ts b/samples/interaction.ts index a2676430b..5d9c70583 100644 --- a/samples/interaction.ts +++ b/samples/interaction.ts @@ -5,20 +5,20 @@ import { graphDataTestRunner } from "~/utils/runner"; import { interactiveInputTextAgent } from "./agents/interactiveInputAgent"; const graph_data = { - version: 0.2, + version: 0.3, loop: { count: 3, }, nodes: { node1: { value: {}, - update: "node3", + update: ":node3", }, node2: { agent: "input", }, node3: { - inputs: ["node1", "node2"], + inputs: [":node1", ":node2"], agent: "merge", }, }, From 65ec294fef1be587112c8366e14bde87cac58e52 Mon Sep 17 00:00:00 2001 From: snakajima Date: Thu, 9 May 2024 13:44:12 -0700 Subject: [PATCH 8/9] version warning --- src/graphai.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/graphai.ts b/src/graphai.ts index a97334576..539e98744 100644 --- a/src/graphai.ts +++ b/src/graphai.ts @@ -96,6 +96,9 @@ export class GraphAI { console.log("------------ no version"); } this.version = data.version ?? 0.2; + if (this.version < 0.3) { + console.log("------------ upgrade to 0.3!"); + } this.retryLimit = data.retry; // optional this.graphId = URL.createObjectURL(new Blob()).slice(-36); this.data = data; From 7e1ac48cfc6008da214c235a86fe5127c27f17f8 Mon Sep 17 00:00:00 2001 From: snakajima Date: Thu, 9 May 2024 13:45:18 -0700 Subject: [PATCH 9/9] format --- src/type.ts | 2 +- src/utils/utils.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/type.ts b/src/type.ts index 932438a37..718037c3c 100644 --- a/src/type.ts +++ b/src/type.ts @@ -31,7 +31,7 @@ export type StaticNodeData = { update?: string; // nodeId (+.propId) to get value after a loop isResult?: boolean; }; -export type AgentNamelessFunction = (...param: any[]) => unknown +export type AgentNamelessFunction = (...param: any[]) => unknown; export type ComputedNodeData = { agent: string | AgentNamelessFunction; diff --git a/src/utils/utils.ts b/src/utils/utils.ts index d763af43f..3306154c5 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -18,7 +18,7 @@ const parseNodeName_02 = (inputNodeId: any) => { return { nodeId: parts[0], propIds: parts.slice(1) }; } return { value: inputNodeId }; // non-string literal -} +}; export const parseNodeName = (inputNodeId: any, version: number): DataSource => { if (version === 0.2) {