@ai.ntellect/core 0.5.0 ā 0.6.0
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/.mocharc.json +1 -1
- package/README.md +311 -272
- package/dist/graph/controller.js +63 -0
- package/dist/graph/engine.js +563 -0
- package/dist/index.js +6 -6
- package/dist/memory/adapters/meilisearch/index.js +249 -0
- package/dist/memory/adapters/redis/index.js +96 -0
- package/dist/memory/index.js +9 -0
- package/dist/services/agenda.js +115 -0
- package/dist/services/embedding.js +40 -0
- package/dist/services/queue.js +99 -103
- package/dist/test/graph/controller.test.js +170 -0
- package/dist/test/graph/engine.test.js +465 -0
- package/dist/test/memory/adapters/meilisearch.test.js +250 -0
- package/dist/test/memory/adapters/redis.test.js +143 -0
- package/dist/test/memory/base.test.js +209 -0
- package/dist/test/services/agenda.test.js +230 -0
- package/dist/test/services/queue.test.js +258 -0
- package/dist/types/index.js +2 -0
- package/dist/utils/generate-object.js +32 -11
- package/dist/utils/inject-actions.js +2 -2
- package/dist/utils/queue-item-transformer.js +2 -2
- package/dist/utils/state-manager.js +20 -0
- package/graph/controller.ts +60 -0
- package/{services/workflow.ts ā graph/engine.ts} +331 -113
- package/index.ts +7 -7
- package/interfaces/index.ts +119 -0
- package/memory/adapters/meilisearch/index.ts +286 -0
- package/memory/adapters/redis/index.ts +103 -0
- package/memory/index.ts +22 -0
- package/package.json +7 -2
- package/services/agenda.ts +48 -43
- package/services/embedding.ts +26 -0
- package/services/queue.ts +2 -29
- package/test/.env.test +4 -0
- package/test/graph/controller.test.ts +186 -0
- package/test/graph/engine.test.ts +563 -0
- package/test/memory/adapters/meilisearch.test.ts +297 -0
- package/test/memory/adapters/redis.test.ts +160 -0
- package/test/memory/base.test.ts +229 -0
- package/test/services/agenda.test.ts +280 -0
- package/test/services/queue.test.ts +286 -44
- package/tsconfig.json +10 -10
- package/types/index.ts +270 -0
- package/utils/generate-object.js +111 -0
- package/utils/header-builder.js +34 -0
- package/utils/inject-actions.js +16 -0
- package/utils/queue-item-transformer.js +24 -0
- package/utils/queue-item-transformer.ts +8 -11
- package/utils/sanitize-results.js +60 -0
- package/utils/schema-generator.js +46 -0
- package/utils/state-manager.js +20 -0
- package/utils/state-manager.ts +17 -12
- package/.nvmrc +0 -1
- package/README.FR.md +0 -916
- package/agent/index.ts +0 -151
- package/agent/workflow/conditions.ts +0 -16
- package/agent/workflow/handlers/interpreter.handler.ts +0 -48
- package/agent/workflow/handlers/memory.handler.ts +0 -106
- package/agent/workflow/handlers/orchestrator.handler.ts +0 -23
- package/agent/workflow/handlers/queue.handler.ts +0 -34
- package/agent/workflow/handlers/scheduler.handler.ts +0 -61
- package/agent/workflow/index.ts +0 -62
- package/dist/agent/index.d.ts +0 -38
- package/dist/agent/index.js +0 -143
- package/dist/agent/tools/get-rss.d.ts +0 -16
- package/dist/agent/tools/get-rss.js +0 -62
- package/dist/bull.d.ts +0 -1
- package/dist/bull.js +0 -9
- package/dist/examples/index.d.ts +0 -2
- package/dist/examples/index.js +0 -89
- package/dist/index.d.ts +0 -7
- package/dist/llm/interpreter/context.d.ts +0 -15
- package/dist/llm/interpreter/context.js +0 -89
- package/dist/llm/interpreter/index.d.ts +0 -21
- package/dist/llm/interpreter/index.js +0 -87
- package/dist/llm/memory-manager/context.d.ts +0 -2
- package/dist/llm/memory-manager/context.js +0 -22
- package/dist/llm/memory-manager/index.d.ts +0 -17
- package/dist/llm/memory-manager/index.js +0 -107
- package/dist/llm/orchestrator/context.d.ts +0 -2
- package/dist/llm/orchestrator/context.js +0 -23
- package/dist/llm/orchestrator/index.d.ts +0 -44
- package/dist/llm/orchestrator/index.js +0 -139
- package/dist/llm/orchestrator/types.d.ts +0 -12
- package/dist/memory/cache.d.ts +0 -22
- package/dist/memory/cache.js +0 -165
- package/dist/memory/persistent.d.ts +0 -57
- package/dist/memory/persistent.js +0 -189
- package/dist/services/queue.d.ts +0 -13
- package/dist/services/redis-cache.d.ts +0 -37
- package/dist/services/redis-cache.js +0 -93
- package/dist/services/scheduler.d.ts +0 -40
- package/dist/services/scheduler.js +0 -99
- package/dist/services/telegram-monitor.d.ts +0 -0
- package/dist/services/telegram-monitor.js +0 -118
- package/dist/t.d.ts +0 -46
- package/dist/t.js +0 -102
- package/dist/test.d.ts +0 -0
- package/dist/test.js +0 -438
- package/dist/types.d.ts +0 -258
- package/dist/types.js +0 -22
- package/dist/utils/generate-object.d.ts +0 -12
- package/dist/utils/header-builder.d.ts +0 -11
- package/dist/utils/inject-actions.d.ts +0 -2
- package/dist/utils/queue-item-transformer.d.ts +0 -7
- package/dist/utils/sanitize-results.d.ts +0 -17
- package/dist/utils/schema-generator.d.ts +0 -16
- package/examples/actions/get-rss.ts +0 -71
- package/examples/index.ts +0 -98
- package/index.html +0 -42
- package/llm/dynamic-condition/example.ts +0 -36
- package/llm/dynamic-condition/index.ts +0 -108
- package/llm/interpreter/context.ts +0 -94
- package/llm/interpreter/index.ts +0 -140
- package/llm/memory-manager/context.ts +0 -19
- package/llm/memory-manager/index.ts +0 -115
- package/llm/orchestrator/context.ts +0 -19
- package/llm/orchestrator/index.ts +0 -192
- package/llm/orchestrator/types.ts +0 -14
- package/memory/cache.ts +0 -221
- package/memory/persistent.ts +0 -265
- package/script.js +0 -167
- package/services/cache.ts +0 -298
- package/services/telegram-monitor.ts +0 -138
- package/t.py +0 -79
- package/t.ts +0 -25
- package/test/llm/orchestrator.test.ts +0 -47
- package/test/llm/synthesizer.test.ts +0 -31
- package/types.ts +0 -367
- /package/dist/{llm/orchestrator/types.js ā interfaces/index.js} +0 -0
@@ -0,0 +1,63 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
9
|
+
});
|
10
|
+
};
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
12
|
+
exports.GraphController = void 0;
|
13
|
+
const engine_1 = require("./engine");
|
14
|
+
/**
|
15
|
+
* Controller responsible for executing workflows based on graph definitions.
|
16
|
+
* @template T The type representing the graph's state.
|
17
|
+
*/
|
18
|
+
class GraphController {
|
19
|
+
/**
|
20
|
+
* Executes a sequence of actions using the corresponding graph definitions.
|
21
|
+
* @param {any[]} actions - The list of actions to execute.
|
22
|
+
* @param {GraphDefinition<T>[]} graphs - The available graph definitions.
|
23
|
+
* @returns {Promise<any>} The final state of the executed workflow.
|
24
|
+
* @throws {Error} If no actions are provided or if the graph is not found.
|
25
|
+
*/
|
26
|
+
run(actions, graphs) {
|
27
|
+
return __awaiter(this, void 0, void 0, function* () {
|
28
|
+
if (actions.length === 0) {
|
29
|
+
throw new Error("No actions provided");
|
30
|
+
}
|
31
|
+
// Create a mapping of graph names to their definitions for quick lookup.
|
32
|
+
const graphMap = new Map(graphs.map((g) => [g.name, g]));
|
33
|
+
for (const action of actions) {
|
34
|
+
// Retrieve the graph definition based on the action name.
|
35
|
+
const graphDefinition = graphMap.get(action.name);
|
36
|
+
if (!graphDefinition) {
|
37
|
+
throw new Error(`Graph not found: ${action.name}`);
|
38
|
+
}
|
39
|
+
// Initialize the graph engine with the selected graph definition.
|
40
|
+
const graph = new engine_1.GraphEngine(graphDefinition, {
|
41
|
+
schema: graphDefinition.schema,
|
42
|
+
autoDetectCycles: true,
|
43
|
+
});
|
44
|
+
// Construct the initial state from action parameters.
|
45
|
+
const initialState = {
|
46
|
+
context: action.parameters.reduce((acc, param) => {
|
47
|
+
acc[param.name] = param.value;
|
48
|
+
return acc;
|
49
|
+
}, {}),
|
50
|
+
};
|
51
|
+
// Execute the graph starting from the defined entry node.
|
52
|
+
yield graph.execute(initialState, graphDefinition.entryNode);
|
53
|
+
// Retrieve the final state after execution.
|
54
|
+
const result = graph.getState();
|
55
|
+
if (!result) {
|
56
|
+
throw new Error("Workflow execution failed to return a state");
|
57
|
+
}
|
58
|
+
return result;
|
59
|
+
}
|
60
|
+
});
|
61
|
+
}
|
62
|
+
}
|
63
|
+
exports.GraphController = GraphController;
|
@@ -0,0 +1,563 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
9
|
+
});
|
10
|
+
};
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
13
|
+
};
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
15
|
+
exports.GraphEngine = void 0;
|
16
|
+
const dotenv_1 = require("dotenv");
|
17
|
+
const events_1 = __importDefault(require("events"));
|
18
|
+
const zod_1 = require("zod");
|
19
|
+
(0, dotenv_1.configDotenv)();
|
20
|
+
/**
|
21
|
+
* Represents a directed worflow structure capable of executing nodes in sequence or parallel.
|
22
|
+
* The worflow can handle state management, event emissions, and conditional execution paths.
|
23
|
+
*
|
24
|
+
* @template T - The type of data stored in the worflow's context
|
25
|
+
*/
|
26
|
+
class GraphEngine {
|
27
|
+
/**
|
28
|
+
* Creates a new Graph instance.
|
29
|
+
*
|
30
|
+
* @param {GraphDefinition<T>} [definition] - Initial worflow structure and configuration
|
31
|
+
* @param {Object} [config] - Additional configuration options
|
32
|
+
* @param {boolean} [config.autoDetectCycles] - Whether to check for cycles during initialization
|
33
|
+
* @throws {Error} If cycles are detected when autoDetectCycles is true
|
34
|
+
*/
|
35
|
+
constructor(definition, options) {
|
36
|
+
this.name = (definition === null || definition === void 0 ? void 0 : definition.name) || "anonymous";
|
37
|
+
this.eventEmitter = new events_1.default();
|
38
|
+
this.globalContext = new Map();
|
39
|
+
this.nodes = new Map();
|
40
|
+
this.executedNodes = new Set();
|
41
|
+
this.persistence = null;
|
42
|
+
this.notifier = null;
|
43
|
+
this.schema = options === null || options === void 0 ? void 0 : options.schema;
|
44
|
+
this.currentState = { context: {} };
|
45
|
+
if (definition) {
|
46
|
+
this.loadFromDefinition(definition);
|
47
|
+
}
|
48
|
+
if ((options === null || options === void 0 ? void 0 : options.autoDetectCycles) && this.checkForCycles()) {
|
49
|
+
throw new Error("Cycle detected in the workflow");
|
50
|
+
}
|
51
|
+
if (options === null || options === void 0 ? void 0 : options.initialState) {
|
52
|
+
this.setState(options.initialState);
|
53
|
+
}
|
54
|
+
}
|
55
|
+
/**
|
56
|
+
* Adds a value to the global context.
|
57
|
+
* @param {string} key - The key to store the value under
|
58
|
+
* @param {any} value - The value to store
|
59
|
+
*/
|
60
|
+
addToContext(key, value) {
|
61
|
+
this.globalContext.set(key, value);
|
62
|
+
}
|
63
|
+
/**
|
64
|
+
* Retrieves a value from the global context.
|
65
|
+
* @param {string} key - The key to retrieve
|
66
|
+
* @returns {any} The stored value, or undefined if not found
|
67
|
+
*/
|
68
|
+
getContext(key) {
|
69
|
+
return this.globalContext.get(key);
|
70
|
+
}
|
71
|
+
/**
|
72
|
+
* Removes a value from the global context.
|
73
|
+
* @param {string} key - The key to remove
|
74
|
+
*/
|
75
|
+
removeFromContext(key) {
|
76
|
+
this.globalContext.delete(key);
|
77
|
+
}
|
78
|
+
/**
|
79
|
+
* Sets the persistence layer for the worflow.
|
80
|
+
* @param {Persistence<T>} persistence - The persistence implementation
|
81
|
+
*/
|
82
|
+
setPersistence(persistence) {
|
83
|
+
this.persistence = persistence;
|
84
|
+
}
|
85
|
+
/**
|
86
|
+
* Sets the real-time notifier for the worflow.
|
87
|
+
* @param {RealTimeNotifier} notifier - The notifier implementation
|
88
|
+
*/
|
89
|
+
setNotifier(notifier) {
|
90
|
+
this.notifier = notifier;
|
91
|
+
}
|
92
|
+
/**
|
93
|
+
* Loads a worflow structure from a definition object.
|
94
|
+
* @private
|
95
|
+
* @param {GraphDefinition<T>} definition - The worflow definition
|
96
|
+
*/
|
97
|
+
loadFromDefinition(definition) {
|
98
|
+
Object.entries(definition.nodes).forEach(([_, nodeConfig]) => {
|
99
|
+
this.addNode(nodeConfig, {
|
100
|
+
condition: nodeConfig.condition,
|
101
|
+
relationships: nodeConfig.relationships,
|
102
|
+
});
|
103
|
+
});
|
104
|
+
}
|
105
|
+
/**
|
106
|
+
* Recursively checks if a node is part of a cycle.
|
107
|
+
* @private
|
108
|
+
* @param {string} nodeName - The name of the node to check
|
109
|
+
* @param {Set<string>} visited - Set of visited nodes
|
110
|
+
* @param {Set<string>} recStack - Set of nodes in the current recursion stack
|
111
|
+
* @returns {boolean} True if a cycle is detected, false otherwise
|
112
|
+
*/
|
113
|
+
isCyclic(nodeName, visited, recStack) {
|
114
|
+
if (!visited.has(nodeName)) {
|
115
|
+
visited.add(nodeName);
|
116
|
+
recStack.add(nodeName);
|
117
|
+
const currentNode = this.nodes.get(nodeName);
|
118
|
+
if (currentNode === null || currentNode === void 0 ? void 0 : currentNode.relationships) {
|
119
|
+
for (const relation of currentNode.relationships) {
|
120
|
+
const targetNode = relation.name;
|
121
|
+
if (!visited.has(targetNode) &&
|
122
|
+
this.isCyclic(targetNode, visited, recStack)) {
|
123
|
+
return true;
|
124
|
+
}
|
125
|
+
else if (recStack.has(targetNode)) {
|
126
|
+
return true;
|
127
|
+
}
|
128
|
+
}
|
129
|
+
}
|
130
|
+
}
|
131
|
+
recStack.delete(nodeName);
|
132
|
+
return false;
|
133
|
+
}
|
134
|
+
/**
|
135
|
+
* Checks if the worflow contains any cycles.
|
136
|
+
* @returns {boolean} True if cycles are detected, false otherwise
|
137
|
+
*/
|
138
|
+
checkForCycles() {
|
139
|
+
const visited = new Set();
|
140
|
+
const recStack = new Set();
|
141
|
+
for (const nodeName of this.nodes.keys()) {
|
142
|
+
if (this.isCyclic(nodeName, visited, recStack)) {
|
143
|
+
return true;
|
144
|
+
}
|
145
|
+
}
|
146
|
+
return false;
|
147
|
+
}
|
148
|
+
/**
|
149
|
+
* Adds a new node to the worflow.
|
150
|
+
* @param {Node<T>} node - The node to add
|
151
|
+
* @param {Object} options - Node configuration options
|
152
|
+
* @param {Function} [options.condition] - Condition function for node execution
|
153
|
+
* @param {string[]} [options.relations] - Array of relations node names
|
154
|
+
* @param {string[]} [options.events] - Array of event names to listen for
|
155
|
+
*/
|
156
|
+
addNode(node, { condition, relationships, events, }) {
|
157
|
+
node.relationships = relationships;
|
158
|
+
node.condition = condition;
|
159
|
+
if (events) {
|
160
|
+
events.forEach((event) => {
|
161
|
+
this.eventEmitter.on(event, (data) => __awaiter(this, void 0, void 0, function* () {
|
162
|
+
const state = data.state || {};
|
163
|
+
yield this.execute(state, node.name);
|
164
|
+
}));
|
165
|
+
});
|
166
|
+
}
|
167
|
+
this.nodes.set(node.name, node);
|
168
|
+
}
|
169
|
+
/**
|
170
|
+
* Emits an event to the worflow's event emitter.
|
171
|
+
* @param {string} eventName - Name of the event to emit
|
172
|
+
* @param {any} data - Data to pass with the event
|
173
|
+
*/
|
174
|
+
emit(eventName, data) {
|
175
|
+
this.eventEmitter.emit(eventName, data);
|
176
|
+
}
|
177
|
+
/**
|
178
|
+
* Adds a subworflow as a node in the current worflow.
|
179
|
+
* @param {Graph<T>} subGraph - The subworflow to add
|
180
|
+
* @param {string} entryNode - The entry node name in the subworflow
|
181
|
+
* @param {string} name - The name for the subworflow node
|
182
|
+
*/
|
183
|
+
addSubGraph(subGraph, entryNode, name) {
|
184
|
+
const subGraphNode = {
|
185
|
+
name: name,
|
186
|
+
execute: (state) => __awaiter(this, void 0, void 0, function* () {
|
187
|
+
yield subGraph.execute(state, entryNode);
|
188
|
+
return state;
|
189
|
+
}),
|
190
|
+
};
|
191
|
+
this.nodes.set(name, subGraphNode);
|
192
|
+
}
|
193
|
+
/**
|
194
|
+
* Executes the worflow starting from a specific node.
|
195
|
+
* @param {SharedState<T>} state - The initial state
|
196
|
+
* @param {string} startNode - The name of the starting node
|
197
|
+
* @param {Function} [onStream] - Callback for streaming state updates
|
198
|
+
* @param {Function} [onError] - Callback for handling errors
|
199
|
+
*/
|
200
|
+
execute(state, startNode, onStream, onError) {
|
201
|
+
return __awaiter(this, void 0, void 0, function* () {
|
202
|
+
var _a, _b;
|
203
|
+
try {
|
204
|
+
if (this.schema) {
|
205
|
+
try {
|
206
|
+
this.schema.parse(state.context);
|
207
|
+
}
|
208
|
+
catch (error) {
|
209
|
+
const validationError = new Error(`Initial state validation failed: ${error instanceof Error ? error.message : error}`);
|
210
|
+
if (onError)
|
211
|
+
onError(validationError, startNode, state);
|
212
|
+
throw validationError;
|
213
|
+
}
|
214
|
+
}
|
215
|
+
this.setState(state);
|
216
|
+
let currentNodeName = startNode;
|
217
|
+
while (currentNodeName) {
|
218
|
+
this.executedNodes.add(currentNodeName);
|
219
|
+
const currentNode = this.nodes.get(currentNodeName);
|
220
|
+
if (!currentNode)
|
221
|
+
throw new Error(`Node ${currentNodeName} not found.`);
|
222
|
+
if (currentNode.condition &&
|
223
|
+
!currentNode.condition(this.currentState)) {
|
224
|
+
break;
|
225
|
+
}
|
226
|
+
try {
|
227
|
+
if (this.notifier) {
|
228
|
+
this.notifier.notify("nodeExecutionStarted", {
|
229
|
+
workflow: this.name,
|
230
|
+
node: currentNodeName,
|
231
|
+
});
|
232
|
+
}
|
233
|
+
const params = (_a = currentNode.schema) === null || _a === void 0 ? void 0 : _a.parse(this.currentState);
|
234
|
+
const newState = yield currentNode.execute(params || {}, this.currentState);
|
235
|
+
if (newState) {
|
236
|
+
this.setState(newState);
|
237
|
+
if (onStream)
|
238
|
+
onStream(this.currentState);
|
239
|
+
}
|
240
|
+
if (this.persistence) {
|
241
|
+
yield this.persistence.saveState(this.name, this.currentState, currentNodeName);
|
242
|
+
}
|
243
|
+
if (this.notifier) {
|
244
|
+
yield this.notifier.notify("nodeExecutionCompleted", {
|
245
|
+
workflow: this.name,
|
246
|
+
node: currentNodeName,
|
247
|
+
state: this.currentState,
|
248
|
+
});
|
249
|
+
}
|
250
|
+
}
|
251
|
+
catch (error) {
|
252
|
+
if (onError)
|
253
|
+
onError(error, currentNodeName, this.currentState);
|
254
|
+
if (this.notifier) {
|
255
|
+
this.notifier.notify("nodeExecutionFailed", {
|
256
|
+
workflow: this.name,
|
257
|
+
node: currentNodeName,
|
258
|
+
state: this.currentState,
|
259
|
+
error,
|
260
|
+
});
|
261
|
+
}
|
262
|
+
break;
|
263
|
+
}
|
264
|
+
const relationsNodes = currentNode.relationships || [];
|
265
|
+
if (relationsNodes.length > 1) {
|
266
|
+
yield Promise.all(relationsNodes.map((relation) => this.execute(this.currentState, relation.name, onStream, onError)));
|
267
|
+
break;
|
268
|
+
}
|
269
|
+
else {
|
270
|
+
currentNodeName = ((_b = relationsNodes[0]) === null || _b === void 0 ? void 0 : _b.name) || "";
|
271
|
+
}
|
272
|
+
}
|
273
|
+
return this.getState();
|
274
|
+
}
|
275
|
+
catch (error) {
|
276
|
+
if (onError) {
|
277
|
+
onError(error, startNode, state);
|
278
|
+
}
|
279
|
+
throw error;
|
280
|
+
}
|
281
|
+
});
|
282
|
+
}
|
283
|
+
/**
|
284
|
+
* Executes multiple nodes in parallel with a concurrency limit.
|
285
|
+
* @param {SharedState<T>} state - The shared state
|
286
|
+
* @param {string[]} nodeNames - Array of node names to execute
|
287
|
+
* @param {number} [concurrencyLimit=5] - Maximum number of concurrent executions
|
288
|
+
* @param {Function} [onStream] - Callback for streaming state updates
|
289
|
+
* @param {Function} [onError] - Callback for handling errors
|
290
|
+
*/
|
291
|
+
executeParallel(state_1, nodeNames_1) {
|
292
|
+
return __awaiter(this, arguments, void 0, function* (state, nodeNames, concurrencyLimit = 5, onStream, onError) {
|
293
|
+
const executeWithLimit = (nodeName) => __awaiter(this, void 0, void 0, function* () {
|
294
|
+
yield this.execute(state, nodeName, onStream, onError);
|
295
|
+
});
|
296
|
+
const chunks = [];
|
297
|
+
for (let i = 0; i < nodeNames.length; i += concurrencyLimit) {
|
298
|
+
chunks.push(nodeNames.slice(i, i + concurrencyLimit));
|
299
|
+
}
|
300
|
+
for (const chunk of chunks) {
|
301
|
+
yield Promise.all(chunk.map(executeWithLimit));
|
302
|
+
}
|
303
|
+
});
|
304
|
+
}
|
305
|
+
/**
|
306
|
+
* Updates the worflow structure with a new definition.
|
307
|
+
* @param {GraphDefinition<T>} definition - The new worflow definition
|
308
|
+
*/
|
309
|
+
updateGraph(definition) {
|
310
|
+
Object.entries(definition.nodes).forEach(([_, nodeConfig]) => {
|
311
|
+
if (this.nodes.has(nodeConfig.name)) {
|
312
|
+
const existingNode = this.nodes.get(nodeConfig.name);
|
313
|
+
existingNode.relationships =
|
314
|
+
nodeConfig.relationships || existingNode.relationships;
|
315
|
+
existingNode.condition = nodeConfig.condition || existingNode.condition;
|
316
|
+
}
|
317
|
+
else {
|
318
|
+
this.addNode(nodeConfig, {
|
319
|
+
condition: nodeConfig.condition,
|
320
|
+
relationships: nodeConfig.relationships,
|
321
|
+
});
|
322
|
+
}
|
323
|
+
});
|
324
|
+
}
|
325
|
+
/**
|
326
|
+
* Replace the worflow with a new definition.
|
327
|
+
* @param {GraphDefinition<T>} definition - The new worflow definition
|
328
|
+
*/
|
329
|
+
replaceGraph(definition) {
|
330
|
+
this.nodes.clear();
|
331
|
+
this.loadFromDefinition(definition);
|
332
|
+
}
|
333
|
+
/**
|
334
|
+
* Generates a visual representation of the worflow using Mermaid diagram syntax.
|
335
|
+
* The diagram shows all nodes and their connections, with special highlighting for:
|
336
|
+
* - Entry nodes (green)
|
337
|
+
* - Event nodes (yellow)
|
338
|
+
* - Conditional nodes (orange)
|
339
|
+
*
|
340
|
+
* @param {string} [title] - Optional title for the diagram
|
341
|
+
* @returns {string} Mermaid diagram syntax representing the worflow
|
342
|
+
*/
|
343
|
+
generateMermaidDiagram(title) {
|
344
|
+
const lines = ["flowchart TD"];
|
345
|
+
if (title) {
|
346
|
+
lines.push(` subgraph ${title}`);
|
347
|
+
}
|
348
|
+
// Add nodes with styling
|
349
|
+
this.nodes.forEach((node, nodeName) => {
|
350
|
+
const hasEvents = node.events && node.events.length > 0;
|
351
|
+
const hasCondition = !!node.condition;
|
352
|
+
// Style nodes based on their properties
|
353
|
+
let style = "";
|
354
|
+
if (hasEvents) {
|
355
|
+
style = "style " + nodeName + " fill:#FFD700,stroke:#DAA520"; // Yellow for event nodes
|
356
|
+
}
|
357
|
+
else if (hasCondition) {
|
358
|
+
style = "style " + nodeName + " fill:#FFA500,stroke:#FF8C00"; // Orange for conditional nodes
|
359
|
+
}
|
360
|
+
// Add node definition
|
361
|
+
lines.push(` ${nodeName}[${nodeName}]`);
|
362
|
+
if (style) {
|
363
|
+
lines.push(` ${style}`);
|
364
|
+
}
|
365
|
+
});
|
366
|
+
// Add connections
|
367
|
+
this.nodes.forEach((node, nodeName) => {
|
368
|
+
if (node.relationships) {
|
369
|
+
node.relationships.forEach((relationsNode) => {
|
370
|
+
let connectionStyle = "";
|
371
|
+
if (node.condition) {
|
372
|
+
connectionStyle = "---|condition|"; // Add label for conditional connections
|
373
|
+
}
|
374
|
+
else {
|
375
|
+
connectionStyle = "-->"; // Normal connection
|
376
|
+
}
|
377
|
+
lines.push(` ${nodeName} ${connectionStyle} ${relationsNode}`);
|
378
|
+
});
|
379
|
+
}
|
380
|
+
// Add event connections if any
|
381
|
+
if (node.events && node.events.length > 0) {
|
382
|
+
node.events.forEach((event) => {
|
383
|
+
const eventNodeId = `${event}_event`;
|
384
|
+
lines.push(` ${eventNodeId}((${event})):::event`);
|
385
|
+
lines.push(` ${eventNodeId} -.->|trigger| ${nodeName}`);
|
386
|
+
});
|
387
|
+
// Add style class for event nodes
|
388
|
+
lines.push(" classDef event fill:#FFD700,stroke:#DAA520");
|
389
|
+
}
|
390
|
+
});
|
391
|
+
if (title) {
|
392
|
+
lines.push(" end");
|
393
|
+
}
|
394
|
+
return lines.join("\n");
|
395
|
+
}
|
396
|
+
/**
|
397
|
+
* Renders the worflow visualization using Mermaid syntax.
|
398
|
+
* This method can be used to visualize the worflow structure in supported environments.
|
399
|
+
*
|
400
|
+
* @param {string} [title] - Optional title for the visualization
|
401
|
+
*/
|
402
|
+
visualize(title) {
|
403
|
+
const diagram = this.generateMermaidDiagram(title);
|
404
|
+
console.log("To visualize this worflow, use a Mermaid-compatible renderer with this syntax:");
|
405
|
+
console.log("\n```mermaid");
|
406
|
+
console.log(diagram);
|
407
|
+
console.log("```\n");
|
408
|
+
}
|
409
|
+
exportGraphToJson(worflow) {
|
410
|
+
const result = {
|
411
|
+
worflowName: worflow.name,
|
412
|
+
entryNode: worflow.entryNode,
|
413
|
+
nodes: Object.entries(worflow.nodes).reduce((acc, [key, node]) => {
|
414
|
+
acc[key] = {
|
415
|
+
name: node.name,
|
416
|
+
description: node.description || "No description provided",
|
417
|
+
execute: node.execute.name,
|
418
|
+
condition: node.condition ? node.condition.toString() : "None",
|
419
|
+
relationships: node.relationships || [],
|
420
|
+
};
|
421
|
+
return acc;
|
422
|
+
}, {}),
|
423
|
+
};
|
424
|
+
return JSON.stringify(result, null, 2);
|
425
|
+
}
|
426
|
+
/**
|
427
|
+
* Generates a visual representation of the workflow schema.
|
428
|
+
* Displays the structure of the data expected for each node.
|
429
|
+
*
|
430
|
+
* @returns {string} A formatted string describing the workflow schema
|
431
|
+
*/
|
432
|
+
visualizeSchema() {
|
433
|
+
const output = [];
|
434
|
+
output.push(`š Graph: ${this.name}`);
|
435
|
+
output.push("=".repeat(50));
|
436
|
+
if (this.schema) {
|
437
|
+
output.push("š· Global Schema:");
|
438
|
+
output.push("-".repeat(30));
|
439
|
+
if (this.schema instanceof zod_1.z.ZodObject) {
|
440
|
+
const shape = this.schema.shape;
|
441
|
+
Object.entries(shape).forEach(([key, value]) => {
|
442
|
+
const description = this.describeZodType(value, 1);
|
443
|
+
output.push(`${key}:`);
|
444
|
+
output.push(description);
|
445
|
+
});
|
446
|
+
}
|
447
|
+
output.push("");
|
448
|
+
}
|
449
|
+
output.push("š· Nodes:");
|
450
|
+
output.push("-".repeat(30));
|
451
|
+
this.nodes.forEach((node, nodeName) => {
|
452
|
+
output.push(`\nš Node: ${nodeName}`);
|
453
|
+
output.push(`Description: ${node.description || "No description provided"}`);
|
454
|
+
if (node.relationships && node.relationships.length > 0) {
|
455
|
+
output.push(`Next nodes: ${node.relationships.join(", ")}`);
|
456
|
+
}
|
457
|
+
output.push("");
|
458
|
+
});
|
459
|
+
return output.join("\n");
|
460
|
+
}
|
461
|
+
/**
|
462
|
+
* Recursively describes a Zod type.
|
463
|
+
*/
|
464
|
+
describeZodType(type, indent = 0) {
|
465
|
+
const padding = " ".repeat(indent);
|
466
|
+
if (type instanceof zod_1.z.ZodObject) {
|
467
|
+
const shape = type.shape;
|
468
|
+
const lines = [];
|
469
|
+
Object.entries(shape).forEach(([key, value]) => {
|
470
|
+
const isOptional = value instanceof zod_1.z.ZodOptional;
|
471
|
+
const actualType = isOptional
|
472
|
+
? value.unwrap()
|
473
|
+
: value;
|
474
|
+
const description = this.describeZodType(actualType, indent + 1);
|
475
|
+
lines.push(`${padding}${key}${isOptional ? "?" : ""}: ${description}`);
|
476
|
+
});
|
477
|
+
return lines.join("\n");
|
478
|
+
}
|
479
|
+
if (type instanceof zod_1.z.ZodArray) {
|
480
|
+
const elementType = this.describeZodType(type.element, indent);
|
481
|
+
return `Array<${elementType}>`;
|
482
|
+
}
|
483
|
+
if (type instanceof zod_1.z.ZodString) {
|
484
|
+
const checks = type._def.checks || [];
|
485
|
+
const constraints = checks
|
486
|
+
.map((check) => {
|
487
|
+
if (check.kind === "url")
|
488
|
+
return "url";
|
489
|
+
if (check.kind === "email")
|
490
|
+
return "email";
|
491
|
+
return check.kind;
|
492
|
+
})
|
493
|
+
.join(", ");
|
494
|
+
return constraints ? `string (${constraints})` : "string";
|
495
|
+
}
|
496
|
+
if (type instanceof zod_1.z.ZodNumber) {
|
497
|
+
return "number";
|
498
|
+
}
|
499
|
+
if (type instanceof zod_1.z.ZodBoolean) {
|
500
|
+
return "boolean";
|
501
|
+
}
|
502
|
+
if (type instanceof zod_1.z.ZodOptional) {
|
503
|
+
return `${this.describeZodType(type.unwrap(), indent)} (optional)`;
|
504
|
+
}
|
505
|
+
return type.constructor.name.replace("Zod", "") || "unknown";
|
506
|
+
}
|
507
|
+
/**
|
508
|
+
* Updates the state of a node.
|
509
|
+
* @param {SharedState<T>} state - The current state
|
510
|
+
* @param {Partial<T>} updates - The updates to apply
|
511
|
+
* @returns {SharedState<T>} The updated state
|
512
|
+
*/
|
513
|
+
updateNodeState(state, updates) {
|
514
|
+
return Object.assign(Object.assign({}, state), { context: Object.assign(Object.assign({}, (state.context || {})), updates) });
|
515
|
+
}
|
516
|
+
/**
|
517
|
+
* Retrieves the current state of the workflow.
|
518
|
+
* @returns {SharedState<T>} The current state
|
519
|
+
*/
|
520
|
+
getState() {
|
521
|
+
return this.currentState;
|
522
|
+
}
|
523
|
+
/**
|
524
|
+
* Sets the state of the workflow.
|
525
|
+
* @param {Partial<SharedState<T>>} state - The new state
|
526
|
+
*/
|
527
|
+
setState(state) {
|
528
|
+
this.currentState = this.mergeStates(this.currentState, state);
|
529
|
+
if (state.context) {
|
530
|
+
Object.entries(state.context).forEach(([key, value]) => {
|
531
|
+
this.globalContext.set(key, value);
|
532
|
+
});
|
533
|
+
}
|
534
|
+
const currentNode = Array.from(this.executedNodes).pop();
|
535
|
+
if (currentNode) {
|
536
|
+
const node = this.nodes.get(currentNode);
|
537
|
+
if (node) {
|
538
|
+
node.state = Object.assign(Object.assign({}, (node.state || {})), (state.context || {}));
|
539
|
+
}
|
540
|
+
}
|
541
|
+
}
|
542
|
+
/**
|
543
|
+
* Merges two states.
|
544
|
+
* @param {SharedState<T>} currentState - The current state
|
545
|
+
* @param {Partial<SharedState<T>>} newState - The new state
|
546
|
+
* @returns {SharedState<T>} The merged state
|
547
|
+
*/
|
548
|
+
mergeStates(currentState, newState) {
|
549
|
+
return Object.assign(Object.assign({}, currentState), { context: Object.assign(Object.assign({}, (currentState.context || {})), (newState.context || {})) });
|
550
|
+
}
|
551
|
+
/**
|
552
|
+
* Updates the state of the workflow.
|
553
|
+
* @param {Partial<SharedState<T>>} updates - The updates to apply
|
554
|
+
* @returns {SharedState<T>} The updated state
|
555
|
+
*/
|
556
|
+
updateState(updates) {
|
557
|
+
const currentState = this.getState();
|
558
|
+
const newState = Object.assign(Object.assign({}, currentState), { context: Object.assign(Object.assign({}, currentState.context), (updates.context || {})) });
|
559
|
+
this.setState(newState);
|
560
|
+
return newState;
|
561
|
+
}
|
562
|
+
}
|
563
|
+
exports.GraphEngine = GraphEngine;
|
package/dist/index.js
CHANGED
@@ -14,10 +14,10 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
15
15
|
};
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
17
|
-
__exportStar(require("./
|
18
|
-
__exportStar(require("./
|
19
|
-
__exportStar(require("./
|
20
|
-
__exportStar(require("./
|
17
|
+
__exportStar(require("./graph/controller"), exports);
|
18
|
+
__exportStar(require("./graph/engine"), exports);
|
19
|
+
__exportStar(require("./memory"), exports);
|
20
|
+
__exportStar(require("./memory/adapters/meilisearch"), exports);
|
21
|
+
__exportStar(require("./memory/adapters/redis"), exports);
|
22
|
+
__exportStar(require("./interfaces"), exports);
|
21
23
|
__exportStar(require("./types"), exports);
|
22
|
-
__exportStar(require("./memory/cache"), exports);
|
23
|
-
__exportStar(require("./memory/persistent"), exports);
|