graphai 0.1.1 → 0.1.2
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/README.md +43 -33
- package/lib/experimental_agents/data_agents/data_object_merge_template_agent.d.ts +26 -0
- package/lib/experimental_agents/data_agents/data_object_merge_template_agent.js +25 -0
- package/lib/experimental_agents/data_agents/data_sum_template_agent.js +1 -1
- package/lib/experimental_agents/index.d.ts +1 -1
- package/lib/experimental_agents/index.js +1 -1
- package/lib/experimental_agents/matrix_agents/dot_product_agent.d.ts +4 -0
- package/lib/experimental_agents/{matrix_agent.js → matrix_agents/dot_product_agent.js} +1 -27
- package/lib/experimental_agents/matrix_agents/index.d.ts +2 -0
- package/lib/experimental_agents/matrix_agents/index.js +7 -0
- package/lib/experimental_agents/matrix_agents/sort_by_values_agent.d.ts +6 -0
- package/lib/experimental_agents/matrix_agents/sort_by_values_agent.js +29 -0
- package/lib/experimental_agents/nested_agent.d.ts +0 -1
- package/lib/experimental_agents/nested_agent.js +13 -3
- package/lib/experimental_agents/string_agents/string_splitter_agent.d.ts +32 -0
- package/lib/experimental_agents/string_agents/string_splitter_agent.js +40 -0
- package/lib/experimental_agents/string_agents/string_template_agent.d.ts +23 -0
- package/lib/experimental_agents/string_agents/string_template_agent.js +21 -0
- package/lib/experimental_agents/test_agents/copy2array_agent.d.ts +2 -0
- package/lib/experimental_agents/test_agents/copy2array_agent.js +9 -0
- package/lib/experimental_agents/test_agents/index.d.ts +1 -0
- package/lib/experimental_agents/test_agents/index.js +3 -1
- package/lib/graphai.js +1 -5
- package/lib/node.d.ts +1 -2
- package/lib/node.js +8 -17
- package/lib/transaction_log.js +1 -1
- package/lib/utils/test_agents.d.ts +2 -0
- package/lib/utils/test_agents.js +20 -0
- package/lib/utils/test_utils.d.ts +12 -0
- package/lib/utils/test_utils.js +34 -0
- package/package.json +8 -10
- package/lib/experimental_agents/matrix_agent.d.ts +0 -9
- package/lib/experimental_agents/test_agents/echo_fork_index_agent.d.ts +0 -2
- package/lib/experimental_agents/test_agents/echo_fork_index_agent.js +0 -7
- package/lib/log.d.ts +0 -22
- package/lib/log.js +0 -49
- package/lib/task.d.ts +0 -18
- package/lib/task.js +0 -63
package/README.md
CHANGED
|
@@ -2,47 +2,57 @@
|
|
|
2
2
|
|
|
3
3
|
## Overview
|
|
4
4
|
|
|
5
|
-
GraphAI is an asynchronous data flow execution engine, which makes it easy to
|
|
5
|
+
GraphAI is an asynchronous data flow execution engine, which makes it easy to build *agentic* applications, which perform the orchestration of mutiple "AI agents".
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
*Agentic* applications need to make asynchronous API calls (such as OpenAI's chat-completion API, database query, web search, and etc.) multiple times and manage data dependencies among them, such as giving the answer from one LLM call to another LLM call as a prompt -- which will become quite difficult to manage in a traditional programing style as the complexity of the application increases, because of the asynchronous nature of those APIs.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
GraphAI allows developers to describe dependencies among those API calls in a single data flow graph (either in YAML or JSON), create a GraphAI instance with that graph, and let it run. The GraphAI engine will take care of all the complexity of concurrent asynchronous calls, data dependency management, error handling, retries and logging.
|
|
10
|
+
|
|
11
|
+
Here is an example graph, which uses the Wikipedia as the data source and perform an in-memory RAG.
|
|
10
12
|
|
|
11
13
|
```YAML
|
|
12
14
|
nodes:
|
|
13
|
-
|
|
14
|
-
|
|
15
|
+
source: // Input data to this RAG application
|
|
16
|
+
value:
|
|
17
|
+
name: Sam Bankman-Fried
|
|
18
|
+
query: describe the final sentence by the court for Sam Bank-Fried
|
|
19
|
+
wikipedia: // Retrieve data from Wikipedia。
|
|
20
|
+
agentId: wikipediaAgent
|
|
21
|
+
inputs: [source.name]
|
|
22
|
+
chunks: // Break the text from Wikipedia into chunks(2048 character each with 512 overlap)
|
|
23
|
+
agentId: stringSplitterAgent
|
|
24
|
+
inputs: [wikipedia]
|
|
25
|
+
chunkEmbeddings: // Get embedding vector of each chunk
|
|
26
|
+
agentId: stringEmbeddingsAgent
|
|
27
|
+
inputs: [chunks]
|
|
28
|
+
topicEmbedding: // Get embedding vector of the question
|
|
29
|
+
agentId: stringEmbeddingsAgent
|
|
30
|
+
inputs: [source.query]
|
|
31
|
+
similarities: // Calculate the cosine similarity of each chunk
|
|
32
|
+
agentId: dotProductAgent
|
|
33
|
+
inputs: [chunkEmbeddings, topicEmbedding]
|
|
34
|
+
sortedChunks: // Sort chunks based on the similarity
|
|
35
|
+
agentId: sortByValuesAgent
|
|
36
|
+
inputs: [chunks, similarities]
|
|
37
|
+
referenceText: // Concatenate chunks up to the token limit (5000)
|
|
38
|
+
agentId: tokenBoundStringsAgent
|
|
39
|
+
inputs: [sortedChunks]
|
|
15
40
|
params:
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
agentId:
|
|
41
|
+
limit: 5000
|
|
42
|
+
prompt: // Generate a prompt with that reference text
|
|
43
|
+
agentId: stringTemplateAgent
|
|
44
|
+
inputs: [source, referenceText]
|
|
19
45
|
params:
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
46
|
+
template: |-
|
|
47
|
+
Using the following document, ${0}
|
|
48
|
+
${1}
|
|
49
|
+
query: // retrieves the answer from GPT3.5
|
|
50
|
+
agentId: slashGPTAgent
|
|
23
51
|
params:
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
``` TypeScript
|
|
29
|
-
const sampleAgentFunction = async (context: AgentFunctionContext) => {
|
|
30
|
-
const {
|
|
31
|
-
nodeId, // taskA, taskB or taskC
|
|
32
|
-
params, // agent-specific parameters specified in the graph definition file
|
|
33
|
-
inputs // inputs from previous nodes
|
|
34
|
-
} = context;
|
|
35
|
-
// Agent-specific code (such as calling OpenAI's chat.completions API)
|
|
36
|
-
...
|
|
37
|
-
return result;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
...
|
|
41
|
-
const file = fs.readFileSync(pathToYamlFile, "utf8");
|
|
42
|
-
const graphData = YAML.parse(file);
|
|
43
|
-
const graph = new GraphAI(graphData, { sample: sampleAgentFunction });
|
|
44
|
-
const results = await graph.run();
|
|
45
|
-
return results["taskC"];
|
|
52
|
+
manifest:
|
|
53
|
+
model: gpt-3.5-turbo
|
|
54
|
+
isResult: true // indicating this is the final result
|
|
55
|
+
inputs: [prompt]
|
|
46
56
|
```
|
|
47
57
|
|
|
48
58
|
## Background
|
|
@@ -1,2 +1,28 @@
|
|
|
1
1
|
import { AgentFunction } from "../../graphai";
|
|
2
2
|
export declare const dataObjectMergeTemplateAgent: AgentFunction;
|
|
3
|
+
declare const dataObjectMergeTemplateAgentInfo: {
|
|
4
|
+
name: string;
|
|
5
|
+
agent: AgentFunction;
|
|
6
|
+
mock: AgentFunction;
|
|
7
|
+
samples: {
|
|
8
|
+
inputs: ({
|
|
9
|
+
a: number;
|
|
10
|
+
b: number;
|
|
11
|
+
c?: undefined;
|
|
12
|
+
} | {
|
|
13
|
+
a: number;
|
|
14
|
+
b: number;
|
|
15
|
+
c: number;
|
|
16
|
+
})[];
|
|
17
|
+
params: {};
|
|
18
|
+
result: {
|
|
19
|
+
a: number;
|
|
20
|
+
b: number;
|
|
21
|
+
};
|
|
22
|
+
}[];
|
|
23
|
+
description: string;
|
|
24
|
+
author: string;
|
|
25
|
+
repository: string;
|
|
26
|
+
license: string;
|
|
27
|
+
};
|
|
28
|
+
export default dataObjectMergeTemplateAgentInfo;
|
|
@@ -11,3 +11,28 @@ const dataObjectMergeTemplateAgent = async ({ inputs }) => {
|
|
|
11
11
|
}, {});
|
|
12
12
|
};
|
|
13
13
|
exports.dataObjectMergeTemplateAgent = dataObjectMergeTemplateAgent;
|
|
14
|
+
// for test and document
|
|
15
|
+
const sampleInputs = [
|
|
16
|
+
{ a: 1, b: 1 },
|
|
17
|
+
{ a: 2, b: 2 },
|
|
18
|
+
{ a: 3, b: 0, c: 5 },
|
|
19
|
+
];
|
|
20
|
+
const sampleParams = {};
|
|
21
|
+
const sampleResult = { a: 6, b: 3 };
|
|
22
|
+
const dataObjectMergeTemplateAgentInfo = {
|
|
23
|
+
name: "dataObjectMergeTemplateAgent",
|
|
24
|
+
agent: exports.dataObjectMergeTemplateAgent,
|
|
25
|
+
mock: exports.dataObjectMergeTemplateAgent,
|
|
26
|
+
samples: [
|
|
27
|
+
{
|
|
28
|
+
inputs: sampleInputs,
|
|
29
|
+
params: sampleParams,
|
|
30
|
+
result: sampleResult,
|
|
31
|
+
},
|
|
32
|
+
],
|
|
33
|
+
description: "Merge object",
|
|
34
|
+
author: "Satoshi Nakajima",
|
|
35
|
+
repository: "https://github.com/receptron/graphai",
|
|
36
|
+
license: "MIT",
|
|
37
|
+
};
|
|
38
|
+
exports.default = dataObjectMergeTemplateAgentInfo;
|
|
@@ -24,7 +24,7 @@ const dataSumTemplateAgentInfo = {
|
|
|
24
24
|
],
|
|
25
25
|
description: "Returns the sum of input values",
|
|
26
26
|
author: "Satoshi Nakajima",
|
|
27
|
-
repository: "https://github.com/
|
|
27
|
+
repository: "https://github.com/receptron/graphai",
|
|
28
28
|
license: "MIT",
|
|
29
29
|
};
|
|
30
30
|
exports.default = dataSumTemplateAgentInfo;
|
|
@@ -5,7 +5,7 @@ export * from "./data_agents";
|
|
|
5
5
|
export * from "./nested_agent";
|
|
6
6
|
export * from "./array_agents";
|
|
7
7
|
export * from "./embedding_agent";
|
|
8
|
-
export * from "./
|
|
8
|
+
export * from "./matrix_agents";
|
|
9
9
|
export * from "./token_agent";
|
|
10
10
|
export * from "./test_agents";
|
|
11
11
|
export * from "./map_agent";
|
|
@@ -21,7 +21,7 @@ __exportStar(require("./data_agents"), exports);
|
|
|
21
21
|
__exportStar(require("./nested_agent"), exports);
|
|
22
22
|
__exportStar(require("./array_agents"), exports);
|
|
23
23
|
__exportStar(require("./embedding_agent"), exports);
|
|
24
|
-
__exportStar(require("./
|
|
24
|
+
__exportStar(require("./matrix_agents"), exports);
|
|
25
25
|
__exportStar(require("./token_agent"), exports);
|
|
26
26
|
__exportStar(require("./test_agents"), exports);
|
|
27
27
|
__exportStar(require("./map_agent"), exports);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.dotProductAgent = void 0;
|
|
4
4
|
// This agent calculates the dot product of an array of vectors (A[]) and a vector (B),
|
|
5
5
|
// typically used to calculate cosine similarity of embedding vectors.
|
|
6
6
|
// Inputs:
|
|
@@ -22,29 +22,3 @@ const dotProductAgent = async ({ inputs }) => {
|
|
|
22
22
|
return { contents };
|
|
23
23
|
};
|
|
24
24
|
exports.dotProductAgent = dotProductAgent;
|
|
25
|
-
// This agent returned a sorted array of one array (A) based on another array (B).
|
|
26
|
-
// The default sorting order is "decendant".
|
|
27
|
-
//
|
|
28
|
-
// Parameters:
|
|
29
|
-
// acendant: Specifies if the sorting order should be acendant. The default is "false" (decendant).
|
|
30
|
-
// Inputs:
|
|
31
|
-
// inputs[0]: Array<any>; // array to be sorted
|
|
32
|
-
// inputs[1]: Array<number>; // array of numbers for sorting
|
|
33
|
-
//
|
|
34
|
-
const sortByValuesAgent = async ({ params, inputs }) => {
|
|
35
|
-
const direction = params?.assendant ?? false ? -1 : 1;
|
|
36
|
-
const sources = inputs[0];
|
|
37
|
-
const values = inputs[1];
|
|
38
|
-
const joined = sources.map((item, index) => {
|
|
39
|
-
return { item, value: values[index] };
|
|
40
|
-
});
|
|
41
|
-
const contents = joined
|
|
42
|
-
.sort((a, b) => {
|
|
43
|
-
return (b.value - a.value) * direction;
|
|
44
|
-
})
|
|
45
|
-
.map((a) => {
|
|
46
|
-
return a.item;
|
|
47
|
-
});
|
|
48
|
-
return { contents };
|
|
49
|
-
};
|
|
50
|
-
exports.sortByValuesAgent = sortByValuesAgent;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.sortByValuesAgent = exports.dotProductAgent = void 0;
|
|
4
|
+
var dot_product_agent_1 = require("../../experimental_agents/matrix_agents/dot_product_agent");
|
|
5
|
+
Object.defineProperty(exports, "dotProductAgent", { enumerable: true, get: function () { return dot_product_agent_1.dotProductAgent; } });
|
|
6
|
+
var sort_by_values_agent_1 = require("../../experimental_agents/matrix_agents/sort_by_values_agent");
|
|
7
|
+
Object.defineProperty(exports, "sortByValuesAgent", { enumerable: true, get: function () { return sort_by_values_agent_1.sortByValuesAgent; } });
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.sortByValuesAgent = void 0;
|
|
4
|
+
// This agent returned a sorted array of one array (A) based on another array (B).
|
|
5
|
+
// The default sorting order is "decendant".
|
|
6
|
+
//
|
|
7
|
+
// Parameters:
|
|
8
|
+
// acendant: Specifies if the sorting order should be acendant. The default is "false" (decendant).
|
|
9
|
+
// Inputs:
|
|
10
|
+
// inputs[0]: Array<any>; // array to be sorted
|
|
11
|
+
// inputs[1]: Array<number>; // array of numbers for sorting
|
|
12
|
+
//
|
|
13
|
+
const sortByValuesAgent = async ({ params, inputs }) => {
|
|
14
|
+
const direction = params?.assendant ?? false ? -1 : 1;
|
|
15
|
+
const sources = inputs[0];
|
|
16
|
+
const values = inputs[1];
|
|
17
|
+
const joined = sources.map((item, index) => {
|
|
18
|
+
return { item, value: values[index] };
|
|
19
|
+
});
|
|
20
|
+
const contents = joined
|
|
21
|
+
.sort((a, b) => {
|
|
22
|
+
return (b.value - a.value) * direction;
|
|
23
|
+
})
|
|
24
|
+
.map((a) => {
|
|
25
|
+
return a.item;
|
|
26
|
+
});
|
|
27
|
+
return { contents };
|
|
28
|
+
};
|
|
29
|
+
exports.sortByValuesAgent = sortByValuesAgent;
|
|
@@ -9,15 +9,25 @@ const nestedAgent = async ({ params, inputs, agents, log, taskManager, graphData
|
|
|
9
9
|
(0, utils_1.assert)(status.concurrency > status.running, `nestedAgent: Concurrency is too low: ${status.concurrency}`);
|
|
10
10
|
}
|
|
11
11
|
(0, utils_1.assert)(graphData !== undefined, "nestedAgent: graphData is required");
|
|
12
|
+
const injectionTo = params.injectionTo ??
|
|
13
|
+
inputs.map((__input, index) => {
|
|
14
|
+
return `$${index}`;
|
|
15
|
+
});
|
|
16
|
+
injectionTo.forEach((nodeId) => {
|
|
17
|
+
if (graphData.nodes[nodeId] === undefined) {
|
|
18
|
+
// If the input node does not exist, automatically create a static node
|
|
19
|
+
graphData.nodes[nodeId] = { value: {} };
|
|
20
|
+
}
|
|
21
|
+
});
|
|
12
22
|
const graphAI = new graphai_1.GraphAI(graphData, agents || {}, taskManager);
|
|
13
23
|
try {
|
|
14
24
|
// Inject inputs to specified source nodes
|
|
15
|
-
|
|
25
|
+
injectionTo.forEach((injectToNodeId, index) => {
|
|
16
26
|
graphAI.injectValue(injectToNodeId, inputs[index]);
|
|
17
27
|
});
|
|
18
|
-
const results = await graphAI.run(
|
|
28
|
+
const results = await graphAI.run(false);
|
|
19
29
|
log?.push(...graphAI.transactionLogs());
|
|
20
|
-
return results
|
|
30
|
+
return results;
|
|
21
31
|
}
|
|
22
32
|
catch (error) {
|
|
23
33
|
log?.push(...graphAI.transactionLogs());
|
|
@@ -5,3 +5,35 @@ export declare const stringSplitterAgent: AgentFunction<{
|
|
|
5
5
|
}, {
|
|
6
6
|
contents: Array<string>;
|
|
7
7
|
}, string>;
|
|
8
|
+
declare const stringSplitterAgentInfo: {
|
|
9
|
+
name: string;
|
|
10
|
+
agent: AgentFunction<{
|
|
11
|
+
chunkSize?: number | undefined;
|
|
12
|
+
overlap?: number | undefined;
|
|
13
|
+
}, {
|
|
14
|
+
contents: Array<string>;
|
|
15
|
+
}, string>;
|
|
16
|
+
mock: AgentFunction<{
|
|
17
|
+
chunkSize?: number | undefined;
|
|
18
|
+
overlap?: number | undefined;
|
|
19
|
+
}, {
|
|
20
|
+
contents: Array<string>;
|
|
21
|
+
}, string>;
|
|
22
|
+
samples: {
|
|
23
|
+
inputs: string[];
|
|
24
|
+
params: {
|
|
25
|
+
chunkSize: number;
|
|
26
|
+
};
|
|
27
|
+
result: {
|
|
28
|
+
contents: string[];
|
|
29
|
+
count: number;
|
|
30
|
+
chunkSize: number;
|
|
31
|
+
overlap: number;
|
|
32
|
+
};
|
|
33
|
+
}[];
|
|
34
|
+
description: string;
|
|
35
|
+
author: string;
|
|
36
|
+
repository: string;
|
|
37
|
+
license: string;
|
|
38
|
+
};
|
|
39
|
+
export default stringSplitterAgentInfo;
|
|
@@ -22,3 +22,43 @@ const stringSplitterAgent = async ({ params, inputs }) => {
|
|
|
22
22
|
return { contents, count, chunkSize, overlap };
|
|
23
23
|
};
|
|
24
24
|
exports.stringSplitterAgent = stringSplitterAgent;
|
|
25
|
+
// for test and document
|
|
26
|
+
const sampleInput = [
|
|
27
|
+
"Here's to the crazy ones, the misfits, the rebels, the troublemakers, the round pegs in the square holes ... the ones who see things differently -- they're not fond of rules, and they have no respect for the status quo. ... You can quote them, disagree with them, glorify or vilify them, but the only thing you can't do is ignore them because they change things. ... They push the human race forward, and while some may see them as the crazy ones, we see genius, because the people who are crazy enough to think that they can change the world, are the ones who do.",
|
|
28
|
+
];
|
|
29
|
+
const sampleParams = { chunkSize: 64 };
|
|
30
|
+
const sampleResult = {
|
|
31
|
+
contents: [
|
|
32
|
+
"Here's to the crazy ones, the misfits, the rebels, the troublema",
|
|
33
|
+
"roublemakers, the round pegs in the square holes ... the ones wh",
|
|
34
|
+
" ones who see things differently -- they're not fond of rules, a",
|
|
35
|
+
"rules, and they have no respect for the status quo. ... You can ",
|
|
36
|
+
"You can quote them, disagree with them, glorify or vilify them, ",
|
|
37
|
+
"y them, but the only thing you can't do is ignore them because t",
|
|
38
|
+
"ecause they change things. ... They push the human race forward,",
|
|
39
|
+
"forward, and while some may see them as the crazy ones, we see g",
|
|
40
|
+
"we see genius, because the people who are crazy enough to think ",
|
|
41
|
+
"o think that they can change the world, are the ones who do.",
|
|
42
|
+
" do.",
|
|
43
|
+
],
|
|
44
|
+
count: 11,
|
|
45
|
+
chunkSize: 64,
|
|
46
|
+
overlap: 8,
|
|
47
|
+
};
|
|
48
|
+
const stringSplitterAgentInfo = {
|
|
49
|
+
name: "stringSplitterAgent",
|
|
50
|
+
agent: exports.stringSplitterAgent,
|
|
51
|
+
mock: exports.stringSplitterAgent,
|
|
52
|
+
samples: [
|
|
53
|
+
{
|
|
54
|
+
inputs: sampleInput,
|
|
55
|
+
params: sampleParams,
|
|
56
|
+
result: sampleResult,
|
|
57
|
+
},
|
|
58
|
+
],
|
|
59
|
+
description: "This agent strip one long string into chunks using following parameters",
|
|
60
|
+
author: "Satoshi Nakajima",
|
|
61
|
+
repository: "https://github.com/receptron/graphai",
|
|
62
|
+
license: "MIT",
|
|
63
|
+
};
|
|
64
|
+
exports.default = stringSplitterAgentInfo;
|
|
@@ -2,3 +2,26 @@ import { AgentFunction } from "../../graphai";
|
|
|
2
2
|
export declare const stringTemplateAgent: AgentFunction<{
|
|
3
3
|
template: string;
|
|
4
4
|
}, Record<string, any> | string, string>;
|
|
5
|
+
declare const stringTemplateAgentInfo: {
|
|
6
|
+
name: string;
|
|
7
|
+
agent: AgentFunction<{
|
|
8
|
+
template: string;
|
|
9
|
+
}, string | Record<string, any>, string>;
|
|
10
|
+
mock: AgentFunction<{
|
|
11
|
+
template: string;
|
|
12
|
+
}, string | Record<string, any>, string>;
|
|
13
|
+
samples: {
|
|
14
|
+
inputs: string[];
|
|
15
|
+
params: {
|
|
16
|
+
template: string;
|
|
17
|
+
};
|
|
18
|
+
result: {
|
|
19
|
+
content: string;
|
|
20
|
+
};
|
|
21
|
+
}[];
|
|
22
|
+
description: string;
|
|
23
|
+
author: string;
|
|
24
|
+
repository: string;
|
|
25
|
+
license: string;
|
|
26
|
+
};
|
|
27
|
+
export default stringTemplateAgentInfo;
|
|
@@ -10,3 +10,24 @@ const stringTemplateAgent = async ({ params, inputs }) => {
|
|
|
10
10
|
return { content };
|
|
11
11
|
};
|
|
12
12
|
exports.stringTemplateAgent = stringTemplateAgent;
|
|
13
|
+
const sampleInput = ["hello", "test"];
|
|
14
|
+
const sampleParams = { template: "${0}: ${1}" };
|
|
15
|
+
const sampleResult = { content: "hello: test" };
|
|
16
|
+
// for test and document
|
|
17
|
+
const stringTemplateAgentInfo = {
|
|
18
|
+
name: "stringTemplateAgent",
|
|
19
|
+
agent: exports.stringTemplateAgent,
|
|
20
|
+
mock: exports.stringTemplateAgent,
|
|
21
|
+
samples: [
|
|
22
|
+
{
|
|
23
|
+
inputs: sampleInput,
|
|
24
|
+
params: sampleParams,
|
|
25
|
+
result: sampleResult,
|
|
26
|
+
},
|
|
27
|
+
],
|
|
28
|
+
description: "Template agent",
|
|
29
|
+
author: "Satoshi Nakajima",
|
|
30
|
+
repository: "https://github.com/receptron/graphai",
|
|
31
|
+
license: "MIT",
|
|
32
|
+
};
|
|
33
|
+
exports.default = stringTemplateAgentInfo;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.copy2ArrayAgent = void 0;
|
|
4
|
+
const copy2ArrayAgent = async ({ inputs }) => {
|
|
5
|
+
return new Array(10).fill(undefined).map(() => {
|
|
6
|
+
return inputs[0];
|
|
7
|
+
});
|
|
8
|
+
};
|
|
9
|
+
exports.copy2ArrayAgent = copy2ArrayAgent;
|
|
@@ -3,3 +3,4 @@ export { echoAgent } from "../../experimental_agents/test_agents/echo_agent";
|
|
|
3
3
|
export { copyMessageAgent } from "../../experimental_agents/test_agents/copy_message_agent";
|
|
4
4
|
export { mergeNodeIdAgent } from "../../experimental_agents/test_agents/merge_node_id_agent";
|
|
5
5
|
export { countingAgent } from "../../experimental_agents/test_agents/counting_agent";
|
|
6
|
+
export { copy2ArrayAgent } from "../../experimental_agents/test_agents/copy2array_agent";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.countingAgent = exports.mergeNodeIdAgent = exports.copyMessageAgent = exports.echoAgent = exports.bypassAgent = void 0;
|
|
3
|
+
exports.copy2ArrayAgent = exports.countingAgent = exports.mergeNodeIdAgent = exports.copyMessageAgent = exports.echoAgent = exports.bypassAgent = void 0;
|
|
4
4
|
var bypass_agent_1 = require("../../experimental_agents/test_agents/bypass_agent");
|
|
5
5
|
Object.defineProperty(exports, "bypassAgent", { enumerable: true, get: function () { return bypass_agent_1.bypassAgent; } });
|
|
6
6
|
var echo_agent_1 = require("../../experimental_agents/test_agents/echo_agent");
|
|
@@ -11,3 +11,5 @@ var merge_node_id_agent_1 = require("../../experimental_agents/test_agents/merge
|
|
|
11
11
|
Object.defineProperty(exports, "mergeNodeIdAgent", { enumerable: true, get: function () { return merge_node_id_agent_1.mergeNodeIdAgent; } });
|
|
12
12
|
var counting_agent_1 = require("../../experimental_agents/test_agents/counting_agent");
|
|
13
13
|
Object.defineProperty(exports, "countingAgent", { enumerable: true, get: function () { return counting_agent_1.countingAgent; } });
|
|
14
|
+
var copy2array_agent_1 = require("../../experimental_agents/test_agents/copy2array_agent");
|
|
15
|
+
Object.defineProperty(exports, "copy2ArrayAgent", { enumerable: true, get: function () { return copy2array_agent_1.copy2ArrayAgent; } });
|
package/lib/graphai.js
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.GraphAI = void 0;
|
|
7
4
|
const type_1 = require("./type");
|
|
@@ -9,7 +6,6 @@ const node_1 = require("./node");
|
|
|
9
6
|
const utils_1 = require("./utils/utils");
|
|
10
7
|
const validator_1 = require("./validator");
|
|
11
8
|
const task_manager_1 = require("./task_manager");
|
|
12
|
-
const crypto_1 = __importDefault(require("crypto"));
|
|
13
9
|
const defaultConcurrency = 8;
|
|
14
10
|
class GraphAI {
|
|
15
11
|
// This method is called when either the GraphAI obect was created,
|
|
@@ -73,7 +69,7 @@ class GraphAI {
|
|
|
73
69
|
this.logs = [];
|
|
74
70
|
this.onLogCallback = (__log, __isUpdate) => { };
|
|
75
71
|
this.repeatCount = 0;
|
|
76
|
-
this.graphId =
|
|
72
|
+
this.graphId = URL.createObjectURL(new Blob()).slice(-36);
|
|
77
73
|
this.data = data;
|
|
78
74
|
this.callbackDictonary = callbackDictonary;
|
|
79
75
|
this.taskManager = taskManager ?? new task_manager_1.TaskManager(data.concurrency ?? defaultConcurrency);
|
package/lib/node.d.ts
CHANGED
|
@@ -23,9 +23,8 @@ export declare class ComputedNode extends Node {
|
|
|
23
23
|
readonly timeout?: number;
|
|
24
24
|
error?: Error;
|
|
25
25
|
transactionId: undefined | number;
|
|
26
|
-
sources: Record<string, DataSource>;
|
|
27
26
|
readonly anyInput: boolean;
|
|
28
|
-
|
|
27
|
+
dataSources: Array<DataSource>;
|
|
29
28
|
pendings: Set<string>;
|
|
30
29
|
readonly isStaticNode = false;
|
|
31
30
|
readonly isComputedNode = true;
|
package/lib/node.js
CHANGED
|
@@ -33,7 +33,6 @@ class ComputedNode extends Node {
|
|
|
33
33
|
constructor(graphId, nodeId, data, graph) {
|
|
34
34
|
super(nodeId, graph);
|
|
35
35
|
this.retryCount = 0;
|
|
36
|
-
this.sources = {}; // data sources.
|
|
37
36
|
this.isStaticNode = false;
|
|
38
37
|
this.isComputedNode = true;
|
|
39
38
|
this.graphId = graphId;
|
|
@@ -44,13 +43,8 @@ class ComputedNode extends Node {
|
|
|
44
43
|
this.timeout = data.timeout;
|
|
45
44
|
this.isResult = data.isResult ?? false;
|
|
46
45
|
this.anyInput = data.anyInput ?? false;
|
|
47
|
-
this.
|
|
48
|
-
|
|
49
|
-
tmp[source.nodeId] = source;
|
|
50
|
-
return tmp;
|
|
51
|
-
}, {});
|
|
52
|
-
this.inputs = Object.keys(this.sources);
|
|
53
|
-
this.pendings = new Set(this.inputs);
|
|
46
|
+
this.dataSources = (data.inputs ?? []).map(utils_1.parseNodeName);
|
|
47
|
+
this.pendings = new Set(this.dataSources.map((source) => source.nodeId));
|
|
54
48
|
this.log.initForComputedNode(this);
|
|
55
49
|
}
|
|
56
50
|
isReadyNode() {
|
|
@@ -58,8 +52,7 @@ class ComputedNode extends Node {
|
|
|
58
52
|
// Count the number of data actually available.
|
|
59
53
|
// We care it only when this.anyInput is true.
|
|
60
54
|
// Notice that this logic enables dynamic data-flows.
|
|
61
|
-
const counter = this.
|
|
62
|
-
const source = this.sources[nodeId];
|
|
55
|
+
const counter = this.dataSources.reduce((count, source) => {
|
|
63
56
|
const [result] = this.graph.resultsOf([source], this.anyInput);
|
|
64
57
|
return result === undefined ? count : count + 1;
|
|
65
58
|
}, 0);
|
|
@@ -90,8 +83,10 @@ class ComputedNode extends Node {
|
|
|
90
83
|
// which this node needs data from.
|
|
91
84
|
removePending(nodeId) {
|
|
92
85
|
if (this.anyInput) {
|
|
93
|
-
const
|
|
94
|
-
|
|
86
|
+
const results = this.graph.resultsOf(this.dataSources, this.anyInput).filter((result) => {
|
|
87
|
+
return result !== undefined;
|
|
88
|
+
});
|
|
89
|
+
if (results.length > 0) {
|
|
95
90
|
this.pendings.clear();
|
|
96
91
|
}
|
|
97
92
|
}
|
|
@@ -116,11 +111,7 @@ class ComputedNode extends Node {
|
|
|
116
111
|
// then it removes itself from the "running node" list of the graph.
|
|
117
112
|
// Notice that setting the result of this node may make other nodes ready to run.
|
|
118
113
|
async execute() {
|
|
119
|
-
const previousResults = this.graph
|
|
120
|
-
.resultsOf(this.inputs.map((input) => {
|
|
121
|
-
return this.sources[input];
|
|
122
|
-
}), this.anyInput)
|
|
123
|
-
.filter((result) => {
|
|
114
|
+
const previousResults = this.graph.resultsOf(this.dataSources, this.anyInput).filter((result) => {
|
|
124
115
|
// Remove undefined if anyInput flag is set.
|
|
125
116
|
return !this.anyInput || result !== undefined;
|
|
126
117
|
});
|
package/lib/transaction_log.js
CHANGED
|
@@ -40,7 +40,7 @@ class TransactionLog {
|
|
|
40
40
|
this.state = node.state;
|
|
41
41
|
this.retryCount = node.retryCount > 0 ? node.retryCount : undefined;
|
|
42
42
|
this.startTime = transactionId;
|
|
43
|
-
this.inputs = node.
|
|
43
|
+
this.inputs = node.dataSources.map((source) => source.nodeId);
|
|
44
44
|
this.inputsData = inputs.length > 0 ? inputs : undefined;
|
|
45
45
|
graph.setLoopLog(this);
|
|
46
46
|
graph.appendLog(this);
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.defaultTestAgents = void 0;
|
|
4
|
+
const experimental_agents_1 = require("../experimental_agents");
|
|
5
|
+
exports.defaultTestAgents = {
|
|
6
|
+
bypassAgent: experimental_agents_1.bypassAgent,
|
|
7
|
+
echoAgent: experimental_agents_1.echoAgent,
|
|
8
|
+
copyMessageAgent: experimental_agents_1.copyMessageAgent,
|
|
9
|
+
mergeNodeIdAgent: experimental_agents_1.mergeNodeIdAgent,
|
|
10
|
+
sleeperAgent: experimental_agents_1.sleeperAgent,
|
|
11
|
+
sleeperAgentDebug: experimental_agents_1.sleeperAgentDebug,
|
|
12
|
+
stringTemplateAgent: experimental_agents_1.stringTemplateAgent,
|
|
13
|
+
nestedAgent: experimental_agents_1.nestedAgent,
|
|
14
|
+
mapAgent: experimental_agents_1.mapAgent,
|
|
15
|
+
totalAgent: experimental_agents_1.totalAgent,
|
|
16
|
+
countingAgent: experimental_agents_1.countingAgent,
|
|
17
|
+
copy2ArrayAgent: experimental_agents_1.copy2ArrayAgent,
|
|
18
|
+
pushAgent: experimental_agents_1.pushAgent,
|
|
19
|
+
popAgent: experimental_agents_1.popAgent,
|
|
20
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { AgentFunctionInfo } from "../type";
|
|
2
|
+
export declare const defaultTestContext: {
|
|
3
|
+
debugInfo: {
|
|
4
|
+
nodeId: string;
|
|
5
|
+
retry: number;
|
|
6
|
+
verbose: boolean;
|
|
7
|
+
};
|
|
8
|
+
params: {};
|
|
9
|
+
agents: {};
|
|
10
|
+
log: never[];
|
|
11
|
+
};
|
|
12
|
+
export declare const agentTestRunner: (agentInfo: AgentFunctionInfo) => Promise<void>;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.agentTestRunner = exports.defaultTestContext = void 0;
|
|
7
|
+
const node_assert_1 = __importDefault(require("node:assert"));
|
|
8
|
+
const node_test_1 = __importDefault(require("node:test"));
|
|
9
|
+
exports.defaultTestContext = {
|
|
10
|
+
debugInfo: {
|
|
11
|
+
nodeId: "test",
|
|
12
|
+
retry: 0,
|
|
13
|
+
verbose: true,
|
|
14
|
+
},
|
|
15
|
+
params: {},
|
|
16
|
+
agents: {},
|
|
17
|
+
log: [],
|
|
18
|
+
};
|
|
19
|
+
// for agent
|
|
20
|
+
const agentTestRunner = async (agentInfo) => {
|
|
21
|
+
(0, node_test_1.default)(`test ${agentInfo.name}`, async () => {
|
|
22
|
+
const { agent, samples } = agentInfo;
|
|
23
|
+
for await (const sample of samples) {
|
|
24
|
+
const { params, inputs, result } = sample;
|
|
25
|
+
const actual = await agent({
|
|
26
|
+
...exports.defaultTestContext,
|
|
27
|
+
params,
|
|
28
|
+
inputs,
|
|
29
|
+
});
|
|
30
|
+
node_assert_1.default.deepStrictEqual(result, actual);
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
exports.agentTestRunner = agentTestRunner;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "graphai",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "Asynchronous data flow execution engine
|
|
3
|
+
"version": "0.1.2",
|
|
4
|
+
"description": "Asynchronous data flow execution engine for agentic AI apps.",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"files": [
|
|
7
7
|
"./lib"
|
|
@@ -17,14 +17,14 @@
|
|
|
17
17
|
},
|
|
18
18
|
"repository": {
|
|
19
19
|
"type": "git",
|
|
20
|
-
"url": "git+https://github.com/
|
|
20
|
+
"url": "git+https://github.com/receptron/graphai"
|
|
21
21
|
},
|
|
22
|
-
"author": "Satoshi Nakajima",
|
|
22
|
+
"author": "Satoshi Nakajima, Isamu Arimoto",
|
|
23
23
|
"license": "MIT",
|
|
24
24
|
"bugs": {
|
|
25
|
-
"url": "https://github.com/
|
|
25
|
+
"url": "https://github.com/receptron/graphai/issues"
|
|
26
26
|
},
|
|
27
|
-
"homepage": "https://github.com/
|
|
27
|
+
"homepage": "https://github.com/receptron/graphai#readme",
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@inquirer/prompts": "^5.0.0",
|
|
30
30
|
"@types/express": "^4.17.21",
|
|
@@ -45,10 +45,8 @@
|
|
|
45
45
|
"tsc-alias": "^1.8.8",
|
|
46
46
|
"tsconfig-paths": "^4.2.0",
|
|
47
47
|
"typescript": "^5.2.2",
|
|
48
|
-
"wikipedia": "^2.1.2"
|
|
49
|
-
|
|
50
|
-
"dependencies": {
|
|
51
|
-
"yaml": "^2.3.3"
|
|
48
|
+
"wikipedia": "^2.1.2",
|
|
49
|
+
"yaml": "^2.4.1"
|
|
52
50
|
},
|
|
53
51
|
"types": "./lib/index.d.ts",
|
|
54
52
|
"directories": {
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { AgentFunction } from "../graphai";
|
|
2
|
-
export declare const dotProductAgent: AgentFunction<Record<string, any>, {
|
|
3
|
-
contents: Array<number>;
|
|
4
|
-
}, Array<Array<number>>>;
|
|
5
|
-
export declare const sortByValuesAgent: AgentFunction<{
|
|
6
|
-
assendant?: boolean;
|
|
7
|
-
}, {
|
|
8
|
-
contents: Array<any>;
|
|
9
|
-
}, Array<any>>;
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.echoForkIndexAgent = void 0;
|
|
4
|
-
const echoForkIndexAgent = async ({ debugInfo: { forkIndex } }) => {
|
|
5
|
-
return { forkIndex };
|
|
6
|
-
};
|
|
7
|
-
exports.echoForkIndexAgent = echoForkIndexAgent;
|
package/lib/log.d.ts
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
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
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
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;
|
package/lib/task.d.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { ComputedNode } from "./node";
|
|
2
|
-
export declare class TaskManager {
|
|
3
|
-
private concurrency;
|
|
4
|
-
private taskQueue;
|
|
5
|
-
private runningNodes;
|
|
6
|
-
constructor(concurrency: number);
|
|
7
|
-
private dequeueTaskIfPossible;
|
|
8
|
-
addTask(node: ComputedNode, callback: (node: ComputedNode) => void): void;
|
|
9
|
-
onComplete(node: ComputedNode): void;
|
|
10
|
-
prepareForNesting(): void;
|
|
11
|
-
getStatus(verbose?: boolean): {
|
|
12
|
-
runningNodes?: string[] | undefined;
|
|
13
|
-
queuedNodes?: string[] | undefined;
|
|
14
|
-
concurrency: number;
|
|
15
|
-
queue: number;
|
|
16
|
-
running: number;
|
|
17
|
-
};
|
|
18
|
-
}
|
package/lib/task.js
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.TaskManager = void 0;
|
|
4
|
-
const utils_1 = require("./utils/utils");
|
|
5
|
-
// TaskManage object controls the concurrency of ComputedNode execution.
|
|
6
|
-
//
|
|
7
|
-
// NOTE: A TaskManager instance will be shared between parent graph and its children
|
|
8
|
-
// when nested agents are involved.
|
|
9
|
-
class TaskManager {
|
|
10
|
-
constructor(concurrency) {
|
|
11
|
-
this.taskQueue = [];
|
|
12
|
-
this.runningNodes = new Set();
|
|
13
|
-
this.concurrency = concurrency;
|
|
14
|
-
}
|
|
15
|
-
// This internal method dequeus a task from the task queue
|
|
16
|
-
// and call the associated callback method, if the number of
|
|
17
|
-
// running task is lower than the spcified limit.
|
|
18
|
-
dequeueTaskIfPossible() {
|
|
19
|
-
if (this.runningNodes.size < this.concurrency) {
|
|
20
|
-
const task = this.taskQueue.shift();
|
|
21
|
-
if (task) {
|
|
22
|
-
this.runningNodes.add(task.node);
|
|
23
|
-
task.callback(task.node);
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
// Node will call this method to put itself in the execution queue.
|
|
28
|
-
// We call the associated callback function when it is dequeued.
|
|
29
|
-
addTask(node, callback) {
|
|
30
|
-
this.taskQueue.push({ node, callback });
|
|
31
|
-
this.dequeueTaskIfPossible();
|
|
32
|
-
}
|
|
33
|
-
// Node MUST call this method once the execution of agent function is completed
|
|
34
|
-
// either successfully or not.
|
|
35
|
-
onComplete(node) {
|
|
36
|
-
(0, utils_1.assert)(this.runningNodes.has(node), `TaskManager.onComplete node(${node.nodeId}) is not in list`);
|
|
37
|
-
this.runningNodes.delete(node);
|
|
38
|
-
this.dequeueTaskIfPossible();
|
|
39
|
-
}
|
|
40
|
-
// Node will call this method before it hands the task manager from the graph
|
|
41
|
-
// to a nested agent. We need to make it sure that there is enough room to run
|
|
42
|
-
// computed nodes inside the nested graph to avoid a deadlock.
|
|
43
|
-
prepareForNesting() {
|
|
44
|
-
if (this.runningNodes.size === this.concurrency) {
|
|
45
|
-
this.concurrency++;
|
|
46
|
-
console.warn("WARNING: increasing concurrenty to", this.concurrency);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
getStatus(verbose = false) {
|
|
50
|
-
return {
|
|
51
|
-
concurrency: this.concurrency,
|
|
52
|
-
queue: this.taskQueue.length,
|
|
53
|
-
running: this.runningNodes.size,
|
|
54
|
-
...(verbose
|
|
55
|
-
? {
|
|
56
|
-
runningNodes: Array.from(this.runningNodes).map((node) => node.nodeId),
|
|
57
|
-
queuedNodes: this.taskQueue.map((task) => task.node.nodeId),
|
|
58
|
-
}
|
|
59
|
-
: {}),
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
exports.TaskManager = TaskManager;
|