@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
@@ -1,23 +1,24 @@
|
|
1
|
+
import { Persistence, RealTimeNotifier } from "@/interfaces";
|
2
|
+
import { GraphDefinition, Node, NodeRelationship, SharedState } from "@/types";
|
1
3
|
import { configDotenv } from "dotenv";
|
2
4
|
import EventEmitter from "events";
|
3
|
-
import {
|
4
|
-
mergeState,
|
5
|
-
Node,
|
6
|
-
Persistence,
|
7
|
-
RealTimeNotifier,
|
8
|
-
SharedState,
|
9
|
-
WorkflowDefinition,
|
10
|
-
} from "../types";
|
5
|
+
import { z } from "zod";
|
11
6
|
|
12
7
|
configDotenv();
|
13
8
|
|
9
|
+
interface GraphOptions<T> {
|
10
|
+
initialState?: SharedState<T>;
|
11
|
+
schema?: z.ZodSchema<T>;
|
12
|
+
autoDetectCycles?: boolean;
|
13
|
+
}
|
14
|
+
|
14
15
|
/**
|
15
16
|
* Represents a directed worflow structure capable of executing nodes in sequence or parallel.
|
16
17
|
* The worflow can handle state management, event emissions, and conditional execution paths.
|
17
18
|
*
|
18
19
|
* @template T - The type of data stored in the worflow's context
|
19
20
|
*/
|
20
|
-
export class
|
21
|
+
export class GraphEngine<T> {
|
21
22
|
/** Stores global context data accessible to all nodes */
|
22
23
|
public globalContext: Map<string, any>;
|
23
24
|
|
@@ -39,18 +40,19 @@ export class Workflow<T> {
|
|
39
40
|
/** Optional notifier for real-time updates */
|
40
41
|
private notifier: RealTimeNotifier | null;
|
41
42
|
|
43
|
+
private schema?: z.ZodSchema<T>;
|
44
|
+
|
45
|
+
private currentState: SharedState<T>;
|
46
|
+
|
42
47
|
/**
|
43
|
-
* Creates a new
|
48
|
+
* Creates a new Graph instance.
|
44
49
|
*
|
45
|
-
* @param {
|
50
|
+
* @param {GraphDefinition<T>} [definition] - Initial worflow structure and configuration
|
46
51
|
* @param {Object} [config] - Additional configuration options
|
47
52
|
* @param {boolean} [config.autoDetectCycles] - Whether to check for cycles during initialization
|
48
53
|
* @throws {Error} If cycles are detected when autoDetectCycles is true
|
49
54
|
*/
|
50
|
-
constructor(
|
51
|
-
definition?: WorkflowDefinition<T>,
|
52
|
-
config?: { autoDetectCycles?: boolean }
|
53
|
-
) {
|
55
|
+
constructor(definition?: GraphDefinition<T>, options?: GraphOptions<T>) {
|
54
56
|
this.name = definition?.name || "anonymous";
|
55
57
|
this.eventEmitter = new EventEmitter();
|
56
58
|
this.globalContext = new Map();
|
@@ -58,13 +60,19 @@ export class Workflow<T> {
|
|
58
60
|
this.executedNodes = new Set();
|
59
61
|
this.persistence = null;
|
60
62
|
this.notifier = null;
|
63
|
+
this.schema = options?.schema;
|
64
|
+
this.currentState = { context: {} } as SharedState<T>;
|
61
65
|
|
62
66
|
if (definition) {
|
63
67
|
this.loadFromDefinition(definition);
|
64
68
|
}
|
65
69
|
|
66
|
-
if (
|
67
|
-
throw new Error("Cycle detected in the
|
70
|
+
if (options?.autoDetectCycles && this.checkForCycles()) {
|
71
|
+
throw new Error("Cycle detected in the workflow");
|
72
|
+
}
|
73
|
+
|
74
|
+
if (options?.initialState) {
|
75
|
+
this.setState(options.initialState);
|
68
76
|
}
|
69
77
|
}
|
70
78
|
|
@@ -113,13 +121,13 @@ export class Workflow<T> {
|
|
113
121
|
/**
|
114
122
|
* Loads a worflow structure from a definition object.
|
115
123
|
* @private
|
116
|
-
* @param {
|
124
|
+
* @param {GraphDefinition<T>} definition - The worflow definition
|
117
125
|
*/
|
118
|
-
private loadFromDefinition(definition:
|
126
|
+
private loadFromDefinition(definition: GraphDefinition<T>): void {
|
119
127
|
Object.entries(definition.nodes).forEach(([_, nodeConfig]) => {
|
120
128
|
this.addNode(nodeConfig, {
|
121
129
|
condition: nodeConfig.condition,
|
122
|
-
|
130
|
+
relationships: nodeConfig.relationships,
|
123
131
|
});
|
124
132
|
});
|
125
133
|
}
|
@@ -142,14 +150,15 @@ export class Workflow<T> {
|
|
142
150
|
recStack.add(nodeName);
|
143
151
|
|
144
152
|
const currentNode = this.nodes.get(nodeName);
|
145
|
-
if (currentNode?.
|
146
|
-
for (const
|
153
|
+
if (currentNode?.relationships) {
|
154
|
+
for (const relation of currentNode.relationships) {
|
155
|
+
const targetNode = relation.name;
|
147
156
|
if (
|
148
|
-
!visited.has(
|
149
|
-
this.isCyclic(
|
157
|
+
!visited.has(targetNode) &&
|
158
|
+
this.isCyclic(targetNode, visited, recStack)
|
150
159
|
) {
|
151
160
|
return true;
|
152
|
-
} else if (recStack.has(
|
161
|
+
} else if (recStack.has(targetNode)) {
|
153
162
|
return true;
|
154
163
|
}
|
155
164
|
}
|
@@ -180,28 +189,27 @@ export class Workflow<T> {
|
|
180
189
|
* @param {Node<T>} node - The node to add
|
181
190
|
* @param {Object} options - Node configuration options
|
182
191
|
* @param {Function} [options.condition] - Condition function for node execution
|
183
|
-
* @param {string[]} [options.
|
192
|
+
* @param {string[]} [options.relations] - Array of relations node names
|
184
193
|
* @param {string[]} [options.events] - Array of event names to listen for
|
185
194
|
*/
|
186
195
|
addNode(
|
187
196
|
node: Node<T>,
|
188
197
|
{
|
189
198
|
condition,
|
190
|
-
|
199
|
+
relationships,
|
191
200
|
events,
|
192
201
|
}: {
|
193
202
|
condition?: (state: SharedState<T>) => boolean;
|
194
|
-
|
203
|
+
relationships?: NodeRelationship[];
|
195
204
|
events?: string[];
|
196
205
|
}
|
197
206
|
): void {
|
198
|
-
node.
|
207
|
+
node.relationships = relationships;
|
199
208
|
node.condition = condition;
|
200
209
|
|
201
210
|
if (events) {
|
202
211
|
events.forEach((event) => {
|
203
212
|
this.eventEmitter.on(event, async (data) => {
|
204
|
-
console.log(`Event "${event}" received by node "${node.name}"`);
|
205
213
|
const state = data.state || {};
|
206
214
|
await this.execute(state, node.name);
|
207
215
|
});
|
@@ -217,30 +225,24 @@ export class Workflow<T> {
|
|
217
225
|
* @param {any} data - Data to pass with the event
|
218
226
|
*/
|
219
227
|
public emit(eventName: string, data: any): void {
|
220
|
-
console.log(`Event "${eventName}" emitted with data:`, data);
|
221
228
|
this.eventEmitter.emit(eventName, data);
|
222
229
|
}
|
223
230
|
|
224
231
|
/**
|
225
232
|
* Adds a subworflow as a node in the current worflow.
|
226
|
-
* @param {
|
233
|
+
* @param {Graph<T>} subGraph - The subworflow to add
|
227
234
|
* @param {string} entryNode - The entry node name in the subworflow
|
228
235
|
* @param {string} name - The name for the subworflow node
|
229
236
|
*/
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
name: string
|
234
|
-
): void {
|
235
|
-
const subWorkflowNode: Node<T> = {
|
236
|
-
name,
|
237
|
+
addSubGraph(subGraph: GraphEngine<T>, entryNode: string, name: string): void {
|
238
|
+
const subGraphNode: Node<T> = {
|
239
|
+
name: name,
|
237
240
|
execute: async (state) => {
|
238
|
-
|
239
|
-
await subWorkflow.execute(state, entryNode);
|
241
|
+
await subGraph.execute(state, entryNode);
|
240
242
|
return state;
|
241
243
|
},
|
242
244
|
};
|
243
|
-
this.nodes.set(name,
|
245
|
+
this.nodes.set(name, subGraphNode);
|
244
246
|
}
|
245
247
|
|
246
248
|
/**
|
@@ -255,75 +257,105 @@ export class Workflow<T> {
|
|
255
257
|
startNode: string,
|
256
258
|
onStream?: (state: SharedState<T>) => void,
|
257
259
|
onError?: (error: Error, nodeName: string, state: SharedState<T>) => void
|
258
|
-
): Promise<
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
260
|
+
): Promise<SharedState<T>> {
|
261
|
+
try {
|
262
|
+
if (this.schema) {
|
263
|
+
try {
|
264
|
+
this.schema.parse(state.context);
|
265
|
+
} catch (error) {
|
266
|
+
const validationError = new Error(
|
267
|
+
`Initial state validation failed: ${
|
268
|
+
error instanceof Error ? error.message : error
|
269
|
+
}`
|
270
|
+
);
|
271
|
+
if (onError) onError(validationError, startNode, state);
|
272
|
+
throw validationError;
|
273
|
+
}
|
274
|
+
}
|
263
275
|
|
264
|
-
|
265
|
-
|
276
|
+
this.setState(state);
|
277
|
+
let currentNodeName = startNode;
|
266
278
|
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
);
|
271
|
-
break;
|
272
|
-
}
|
279
|
+
while (currentNodeName) {
|
280
|
+
this.executedNodes.add(currentNodeName);
|
281
|
+
const currentNode = this.nodes.get(currentNodeName);
|
282
|
+
if (!currentNode) throw new Error(`Node ${currentNodeName} not found.`);
|
273
283
|
|
274
|
-
|
275
|
-
|
276
|
-
this.
|
277
|
-
|
278
|
-
|
279
|
-
});
|
284
|
+
if (
|
285
|
+
currentNode.condition &&
|
286
|
+
!currentNode.condition(this.currentState)
|
287
|
+
) {
|
288
|
+
break;
|
280
289
|
}
|
281
290
|
|
282
|
-
|
283
|
-
|
284
|
-
|
291
|
+
try {
|
292
|
+
if (this.notifier) {
|
293
|
+
this.notifier.notify("nodeExecutionStarted", {
|
294
|
+
workflow: this.name,
|
295
|
+
node: currentNodeName,
|
296
|
+
});
|
297
|
+
}
|
285
298
|
|
286
|
-
|
299
|
+
const params = currentNode.schema?.parse(this.currentState);
|
300
|
+
const newState = await currentNode.execute(
|
301
|
+
params || {},
|
302
|
+
this.currentState
|
303
|
+
);
|
287
304
|
|
288
|
-
|
289
|
-
|
290
|
-
|
305
|
+
if (newState) {
|
306
|
+
this.setState(newState);
|
307
|
+
if (onStream) onStream(this.currentState);
|
308
|
+
}
|
291
309
|
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
310
|
+
if (this.persistence) {
|
311
|
+
await this.persistence.saveState(
|
312
|
+
this.name,
|
313
|
+
this.currentState,
|
314
|
+
currentNodeName
|
315
|
+
);
|
316
|
+
}
|
317
|
+
|
318
|
+
if (this.notifier) {
|
319
|
+
await this.notifier.notify("nodeExecutionCompleted", {
|
320
|
+
workflow: this.name,
|
321
|
+
node: currentNodeName,
|
322
|
+
state: this.currentState,
|
323
|
+
});
|
324
|
+
}
|
325
|
+
} catch (error) {
|
326
|
+
if (onError)
|
327
|
+
onError(error as Error, currentNodeName, this.currentState);
|
328
|
+
if (this.notifier) {
|
329
|
+
this.notifier.notify("nodeExecutionFailed", {
|
330
|
+
workflow: this.name,
|
331
|
+
node: currentNodeName,
|
332
|
+
state: this.currentState,
|
333
|
+
error,
|
334
|
+
});
|
335
|
+
}
|
336
|
+
break;
|
298
337
|
}
|
299
|
-
|
300
|
-
|
301
|
-
if (
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
338
|
+
|
339
|
+
const relationsNodes = currentNode.relationships || [];
|
340
|
+
if (relationsNodes.length > 1) {
|
341
|
+
await Promise.all(
|
342
|
+
relationsNodes.map((relation) =>
|
343
|
+
this.execute(this.currentState, relation.name, onStream, onError)
|
344
|
+
)
|
345
|
+
);
|
346
|
+
break;
|
347
|
+
} else {
|
348
|
+
currentNodeName = relationsNodes[0]?.name || "";
|
309
349
|
}
|
310
|
-
break;
|
311
350
|
}
|
312
351
|
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
this.execute(state, nextNode, onStream, onError)
|
318
|
-
)
|
319
|
-
);
|
320
|
-
break;
|
321
|
-
} else {
|
322
|
-
currentNodeName = nextNodes[0] || "";
|
352
|
+
return this.getState();
|
353
|
+
} catch (error) {
|
354
|
+
if (onError) {
|
355
|
+
onError(error as Error, startNode, state);
|
323
356
|
}
|
357
|
+
throw error;
|
324
358
|
}
|
325
|
-
|
326
|
-
console.log(`Workflow completed for node: ${startNode}`);
|
327
359
|
}
|
328
360
|
|
329
361
|
/**
|
@@ -341,8 +373,6 @@ export class Workflow<T> {
|
|
341
373
|
onStream?: (state: SharedState<T>) => void,
|
342
374
|
onError?: (error: Error, nodeName: string, state: SharedState<T>) => void
|
343
375
|
): Promise<void> {
|
344
|
-
console.log(`Executing nodes in parallel: ${nodeNames.join(", ")}`);
|
345
|
-
|
346
376
|
const executeWithLimit = async (nodeName: string) => {
|
347
377
|
await this.execute(state, nodeName, onStream, onError);
|
348
378
|
};
|
@@ -359,18 +389,19 @@ export class Workflow<T> {
|
|
359
389
|
|
360
390
|
/**
|
361
391
|
* Updates the worflow structure with a new definition.
|
362
|
-
* @param {
|
392
|
+
* @param {GraphDefinition<T>} definition - The new worflow definition
|
363
393
|
*/
|
364
|
-
|
394
|
+
updateGraph(definition: GraphDefinition<T>): void {
|
365
395
|
Object.entries(definition.nodes).forEach(([_, nodeConfig]) => {
|
366
396
|
if (this.nodes.has(nodeConfig.name)) {
|
367
397
|
const existingNode = this.nodes.get(nodeConfig.name)!;
|
368
|
-
existingNode.
|
398
|
+
existingNode.relationships =
|
399
|
+
nodeConfig.relationships || existingNode.relationships;
|
369
400
|
existingNode.condition = nodeConfig.condition || existingNode.condition;
|
370
401
|
} else {
|
371
402
|
this.addNode(nodeConfig, {
|
372
403
|
condition: nodeConfig.condition,
|
373
|
-
|
404
|
+
relationships: nodeConfig.relationships,
|
374
405
|
});
|
375
406
|
}
|
376
407
|
});
|
@@ -378,9 +409,9 @@ export class Workflow<T> {
|
|
378
409
|
|
379
410
|
/**
|
380
411
|
* Replace the worflow with a new definition.
|
381
|
-
* @param {
|
412
|
+
* @param {GraphDefinition<T>} definition - The new worflow definition
|
382
413
|
*/
|
383
|
-
|
414
|
+
replaceGraph(definition: GraphDefinition<T>): void {
|
384
415
|
this.nodes.clear();
|
385
416
|
this.loadFromDefinition(definition);
|
386
417
|
}
|
@@ -396,10 +427,10 @@ export class Workflow<T> {
|
|
396
427
|
* @returns {string} Mermaid diagram syntax representing the worflow
|
397
428
|
*/
|
398
429
|
generateMermaidDiagram(title?: string): string {
|
399
|
-
const lines: string[] = ["
|
430
|
+
const lines: string[] = ["flowchart TD"];
|
400
431
|
|
401
432
|
if (title) {
|
402
|
-
lines.push(`
|
433
|
+
lines.push(` subgraph ${title}`);
|
403
434
|
}
|
404
435
|
|
405
436
|
// Add nodes with styling
|
@@ -424,21 +455,21 @@ export class Workflow<T> {
|
|
424
455
|
|
425
456
|
// Add connections
|
426
457
|
this.nodes.forEach((node, nodeName) => {
|
427
|
-
if (node.
|
428
|
-
node.
|
458
|
+
if (node.relationships) {
|
459
|
+
node.relationships.forEach((relationsNode) => {
|
429
460
|
let connectionStyle = "";
|
430
461
|
if (node.condition) {
|
431
462
|
connectionStyle = "---|condition|"; // Add label for conditional connections
|
432
463
|
} else {
|
433
464
|
connectionStyle = "-->"; // Normal connection
|
434
465
|
}
|
435
|
-
lines.push(` ${nodeName} ${connectionStyle} ${
|
466
|
+
lines.push(` ${nodeName} ${connectionStyle} ${relationsNode}`);
|
436
467
|
});
|
437
468
|
}
|
438
469
|
|
439
470
|
// Add event connections if any
|
440
471
|
if (node.events && node.events.length > 0) {
|
441
|
-
node.events.forEach((event) => {
|
472
|
+
node.events.forEach((event: string) => {
|
442
473
|
const eventNodeId = `${event}_event`;
|
443
474
|
lines.push(` ${eventNodeId}((${event})):::event`);
|
444
475
|
lines.push(` ${eventNodeId} -.->|trigger| ${nodeName}`);
|
@@ -471,7 +502,7 @@ export class Workflow<T> {
|
|
471
502
|
console.log("```\n");
|
472
503
|
}
|
473
504
|
|
474
|
-
|
505
|
+
exportGraphToJson<T>(worflow: GraphDefinition<T>): string {
|
475
506
|
const result = {
|
476
507
|
worflowName: worflow.name,
|
477
508
|
entryNode: worflow.entryNode,
|
@@ -481,11 +512,198 @@ export class Workflow<T> {
|
|
481
512
|
description: node.description || "No description provided",
|
482
513
|
execute: node.execute.name,
|
483
514
|
condition: node.condition ? node.condition.toString() : "None",
|
484
|
-
|
515
|
+
relationships: node.relationships || [],
|
485
516
|
};
|
486
517
|
return acc;
|
487
518
|
}, {} as Record<string, any>),
|
488
519
|
};
|
489
520
|
return JSON.stringify(result, null, 2);
|
490
521
|
}
|
522
|
+
|
523
|
+
/**
|
524
|
+
* Generates a visual representation of the workflow schema.
|
525
|
+
* Displays the structure of the data expected for each node.
|
526
|
+
*
|
527
|
+
* @returns {string} A formatted string describing the workflow schema
|
528
|
+
*/
|
529
|
+
visualizeSchema(): string {
|
530
|
+
const output: string[] = [];
|
531
|
+
|
532
|
+
output.push(`📋 Graph: ${this.name}`);
|
533
|
+
output.push("=".repeat(50));
|
534
|
+
|
535
|
+
if (this.schema) {
|
536
|
+
output.push("🔷 Global Schema:");
|
537
|
+
output.push("-".repeat(30));
|
538
|
+
|
539
|
+
if (this.schema instanceof z.ZodObject) {
|
540
|
+
const shape = this.schema.shape;
|
541
|
+
Object.entries(shape).forEach(([key, value]) => {
|
542
|
+
const description = this.describeZodType(value as z.ZodType, 1);
|
543
|
+
output.push(`${key}:`);
|
544
|
+
output.push(description);
|
545
|
+
});
|
546
|
+
}
|
547
|
+
output.push("");
|
548
|
+
}
|
549
|
+
|
550
|
+
output.push("🔷 Nodes:");
|
551
|
+
output.push("-".repeat(30));
|
552
|
+
|
553
|
+
this.nodes.forEach((node, nodeName) => {
|
554
|
+
output.push(`\n📍 Node: ${nodeName}`);
|
555
|
+
output.push(
|
556
|
+
`Description: ${node.description || "No description provided"}`
|
557
|
+
);
|
558
|
+
|
559
|
+
if (node.relationships && node.relationships.length > 0) {
|
560
|
+
output.push(`Next nodes: ${node.relationships.join(", ")}`);
|
561
|
+
}
|
562
|
+
|
563
|
+
output.push("");
|
564
|
+
});
|
565
|
+
|
566
|
+
return output.join("\n");
|
567
|
+
}
|
568
|
+
|
569
|
+
/**
|
570
|
+
* Recursively describes a Zod type.
|
571
|
+
*/
|
572
|
+
public describeZodType(type: z.ZodType, indent: number = 0): string {
|
573
|
+
const padding = " ".repeat(indent);
|
574
|
+
|
575
|
+
if (type instanceof z.ZodObject) {
|
576
|
+
const shape = type.shape;
|
577
|
+
const lines: string[] = [];
|
578
|
+
|
579
|
+
Object.entries(shape).forEach(([key, value]) => {
|
580
|
+
const isOptional = value instanceof z.ZodOptional;
|
581
|
+
const actualType = isOptional
|
582
|
+
? (value as z.ZodOptional<z.ZodType<any, any, any>>).unwrap()
|
583
|
+
: (value as z.ZodType<any, any, any>);
|
584
|
+
const description = this.describeZodType(actualType, indent + 1);
|
585
|
+
|
586
|
+
lines.push(`${padding}${key}${isOptional ? "?" : ""}: ${description}`);
|
587
|
+
});
|
588
|
+
|
589
|
+
return lines.join("\n");
|
590
|
+
}
|
591
|
+
|
592
|
+
if (type instanceof z.ZodArray) {
|
593
|
+
const elementType = this.describeZodType(type.element, indent);
|
594
|
+
return `Array<${elementType}>`;
|
595
|
+
}
|
596
|
+
|
597
|
+
if (type instanceof z.ZodString) {
|
598
|
+
const checks = type._def.checks || [];
|
599
|
+
const constraints = checks
|
600
|
+
.map((check) => {
|
601
|
+
if (check.kind === "url") return "url";
|
602
|
+
if (check.kind === "email") return "email";
|
603
|
+
return check.kind;
|
604
|
+
})
|
605
|
+
.join(", ");
|
606
|
+
|
607
|
+
return constraints ? `string (${constraints})` : "string";
|
608
|
+
}
|
609
|
+
|
610
|
+
if (type instanceof z.ZodNumber) {
|
611
|
+
return "number";
|
612
|
+
}
|
613
|
+
|
614
|
+
if (type instanceof z.ZodBoolean) {
|
615
|
+
return "boolean";
|
616
|
+
}
|
617
|
+
|
618
|
+
if (type instanceof z.ZodOptional) {
|
619
|
+
return `${this.describeZodType(type.unwrap(), indent)} (optional)`;
|
620
|
+
}
|
621
|
+
|
622
|
+
return type.constructor.name.replace("Zod", "") || "unknown";
|
623
|
+
}
|
624
|
+
|
625
|
+
/**
|
626
|
+
* Updates the state of a node.
|
627
|
+
* @param {SharedState<T>} state - The current state
|
628
|
+
* @param {Partial<T>} updates - The updates to apply
|
629
|
+
* @returns {SharedState<T>} The updated state
|
630
|
+
*/
|
631
|
+
protected updateNodeState(state: SharedState<T>, updates: Partial<T>) {
|
632
|
+
return {
|
633
|
+
...state,
|
634
|
+
context: {
|
635
|
+
...(state.context || {}),
|
636
|
+
...updates,
|
637
|
+
},
|
638
|
+
};
|
639
|
+
}
|
640
|
+
|
641
|
+
/**
|
642
|
+
* Retrieves the current state of the workflow.
|
643
|
+
* @returns {SharedState<T>} The current state
|
644
|
+
*/
|
645
|
+
public getState(): SharedState<T> {
|
646
|
+
return this.currentState;
|
647
|
+
}
|
648
|
+
|
649
|
+
/**
|
650
|
+
* Sets the state of the workflow.
|
651
|
+
* @param {Partial<SharedState<T>>} state - The new state
|
652
|
+
*/
|
653
|
+
public setState(state: Partial<SharedState<T>>): void {
|
654
|
+
this.currentState = this.mergeStates(this.currentState, state);
|
655
|
+
|
656
|
+
if (state.context) {
|
657
|
+
Object.entries(state.context).forEach(([key, value]) => {
|
658
|
+
this.globalContext.set(key, value);
|
659
|
+
});
|
660
|
+
}
|
661
|
+
const currentNode = Array.from(this.executedNodes).pop();
|
662
|
+
if (currentNode) {
|
663
|
+
const node = this.nodes.get(currentNode);
|
664
|
+
if (node) {
|
665
|
+
node.state = {
|
666
|
+
...(node.state || {}),
|
667
|
+
...(state.context || {}),
|
668
|
+
};
|
669
|
+
}
|
670
|
+
}
|
671
|
+
}
|
672
|
+
|
673
|
+
/**
|
674
|
+
* Merges two states.
|
675
|
+
* @param {SharedState<T>} currentState - The current state
|
676
|
+
* @param {Partial<SharedState<T>>} newState - The new state
|
677
|
+
* @returns {SharedState<T>} The merged state
|
678
|
+
*/
|
679
|
+
private mergeStates(
|
680
|
+
currentState: SharedState<T>,
|
681
|
+
newState: Partial<SharedState<T>>
|
682
|
+
): SharedState<T> {
|
683
|
+
return {
|
684
|
+
...currentState,
|
685
|
+
context: {
|
686
|
+
...(currentState.context || {}),
|
687
|
+
...(newState.context || {}),
|
688
|
+
},
|
689
|
+
};
|
690
|
+
}
|
691
|
+
|
692
|
+
/**
|
693
|
+
* Updates the state of the workflow.
|
694
|
+
* @param {Partial<SharedState<T>>} updates - The updates to apply
|
695
|
+
* @returns {SharedState<T>} The updated state
|
696
|
+
*/
|
697
|
+
public updateState(updates: Partial<SharedState<T>>): SharedState<T> {
|
698
|
+
const currentState = this.getState();
|
699
|
+
const newState = {
|
700
|
+
...currentState,
|
701
|
+
context: {
|
702
|
+
...currentState.context,
|
703
|
+
...(updates.context || {}),
|
704
|
+
},
|
705
|
+
};
|
706
|
+
this.setState(newState);
|
707
|
+
return newState;
|
708
|
+
}
|
491
709
|
}
|
package/index.ts
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
export * from "./
|
2
|
-
export * from "./
|
3
|
-
export * from "./
|
4
|
-
export * from "./
|
5
|
-
export * from "./
|
1
|
+
export * from "./graph/controller";
|
2
|
+
export * from "./graph/engine";
|
3
|
+
export * from "./memory";
|
4
|
+
export * from "./memory/adapters/meilisearch";
|
5
|
+
export * from "./memory/adapters/redis";
|
6
6
|
|
7
|
-
export * from "./
|
8
|
-
export * from "./
|
7
|
+
export * from "./interfaces";
|
8
|
+
export * from "./types";
|