@ai.ntellect/core 0.6.20 → 0.7.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 +2 -1
- package/README.md +87 -148
- package/graph/controller.ts +1 -1
- package/graph/event-manager.ts +288 -0
- package/graph/index.ts +152 -384
- package/graph/logger.ts +70 -0
- package/graph/node.ts +398 -0
- package/graph/observer.ts +361 -0
- package/interfaces/index.ts +102 -1
- package/modules/agenda/index.ts +3 -16
- package/modules/embedding/index.ts +3 -3
- package/package.json +12 -20
- package/test/graph/index.test.ts +296 -154
- package/test/graph/observer.test.ts +398 -0
- package/test/modules/agenda/node-cron.test.ts +37 -16
- package/test/modules/memory/adapters/in-memory.test.ts +2 -2
- package/test/modules/memory/adapters/meilisearch.test.ts +28 -24
- package/test/modules/memory/base.test.ts +3 -3
- package/tsconfig.json +4 -2
- package/types/index.ts +23 -2
- package/utils/generate-action-schema.ts +8 -7
- package/.env.example +0 -2
- package/dist/graph/controller.js +0 -75
- package/dist/graph/index.js +0 -402
- package/dist/index.js +0 -41
- package/dist/interfaces/index.js +0 -17
- package/dist/modules/agenda/adapters/node-cron/index.js +0 -29
- package/dist/modules/agenda/index.js +0 -140
- package/dist/modules/embedding/adapters/ai/index.js +0 -57
- package/dist/modules/embedding/index.js +0 -59
- package/dist/modules/memory/adapters/in-memory/index.js +0 -210
- package/dist/modules/memory/adapters/meilisearch/index.js +0 -320
- package/dist/modules/memory/adapters/redis/index.js +0 -158
- package/dist/modules/memory/index.js +0 -103
- package/dist/types/index.js +0 -2
- package/dist/utils/generate-action-schema.js +0 -42
- package/dist/utils/header-builder.js +0 -34
- package/graph.ts +0 -74
- package/test/modules/embedding/ai.test.ts +0 -78
- package/test/modules/memory/adapters/redis.test.ts +0 -169
- package/test/services/agenda.test.ts +0 -279
package/.mocharc.json
CHANGED
package/README.md
CHANGED
@@ -1,192 +1,131 @@
|
|
1
|
-
#
|
1
|
+
# @ai.ntellect/core
|
2
2
|
|
3
|
-
|
3
|
+
@ai.ntellect/core is a modular and event-driven framework designed to orchestrate and execute intelligent workflows using execution graphs. It enables automation of complex tasks, seamless integration with external services, and the creation of AI-driven agents in a flexible and scalable way.
|
4
4
|
|
5
|
-
|
5
|
+
## Features
|
6
6
|
|
7
|
-
|
7
|
+
- **GraphFlow** – Graph-based execution engine for automating business processes
|
8
|
+
- **Event-Driven** – Nodes can react to real-time events and trigger actions dynamically
|
9
|
+
- **Modular** – Plug-and-play modules and adapters for memory, scheduling, and external APIs
|
10
|
+
- **Extensible** – Custom nodes, adapters, and interactions with third-party services
|
11
|
+
- **Observable** – Complete state and event monitoring
|
8
12
|
|
9
|
-
|
10
|
-
- Cyclic and acyclic graph support
|
11
|
-
- Strong typing with Zod validation
|
12
|
-
- Event-driven architecture
|
13
|
-
- Built-in error handling and retries
|
14
|
-
- Conditional execution paths
|
15
|
-
- Parameter validation
|
16
|
-
- State management
|
13
|
+
## Installation
|
17
14
|
|
18
|
-
###
|
15
|
+
### Prerequisites
|
19
16
|
|
20
|
-
-
|
21
|
-
-
|
22
|
-
-
|
23
|
-
- **Decision Trees**: Implementing complex business logic with multiple branches
|
24
|
-
- **State Machines**: Managing application state transitions
|
25
|
-
- **Event Processing**: Handling and responding to system events
|
17
|
+
- Node.js (LTS version recommended)
|
18
|
+
- TypeScript
|
19
|
+
- Zod (for data validation)
|
26
20
|
|
27
|
-
|
21
|
+
Verify your installation:
|
28
22
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
- **V**: Set of nodes (vertices)
|
34
|
-
- **E**: Set of directed edges
|
35
|
-
|
36
|
-
Each node represents an executable action, and edges represent conditional transitions between actions.
|
37
|
-
|
38
|
-
#### Example Graph Structure:
|
39
|
-
|
40
|
-
```
|
41
|
-
(ValidateInput) → (ProcessData) → (SaveResult)
|
42
|
-
↓ ↑
|
43
|
-
(RetryInput) ──────────────────────
|
44
|
-
```
|
45
|
-
|
46
|
-
### **2.2 Node Types**
|
47
|
-
|
48
|
-
#### **Basic Node**
|
49
|
-
|
50
|
-
```typescript
|
51
|
-
const basicNode: Node<ContextType> = {
|
52
|
-
name: "processData",
|
53
|
-
execute: async (context) => {
|
54
|
-
// Process data
|
55
|
-
},
|
56
|
-
next: ["saveResult"],
|
57
|
-
};
|
58
|
-
```
|
59
|
-
|
60
|
-
#### **Conditional Node**
|
61
|
-
|
62
|
-
```typescript
|
63
|
-
const conditionalNode: Node<ContextType> = {
|
64
|
-
name: "validateInput",
|
65
|
-
condition: (context) => context.isValid,
|
66
|
-
execute: async (context) => {
|
67
|
-
// Validation logic
|
68
|
-
},
|
69
|
-
next: ["processData"],
|
70
|
-
};
|
23
|
+
```sh
|
24
|
+
node -v
|
25
|
+
npm -v
|
71
26
|
```
|
72
27
|
|
73
|
-
|
74
|
-
|
75
|
-
### **3.1 Event-Driven Execution**
|
76
|
-
|
77
|
-
Nodes can respond to system events:
|
28
|
+
### Installing the framework
|
78
29
|
|
79
|
-
```
|
80
|
-
|
81
|
-
name: "handleUserInput",
|
82
|
-
events: ["userSubmitted"],
|
83
|
-
execute: async (context) => {
|
84
|
-
// Handle user input
|
85
|
-
},
|
86
|
-
};
|
30
|
+
```sh
|
31
|
+
npm install @ai.ntellect/core zod
|
87
32
|
```
|
88
33
|
|
89
|
-
|
90
|
-
|
91
|
-
Built-in retry support for handling transient failures:
|
34
|
+
## Example
|
92
35
|
|
93
36
|
```typescript
|
94
|
-
|
95
|
-
|
96
|
-
retry: {
|
97
|
-
maxAttempts: 3,
|
98
|
-
delay: 1000, // ms
|
99
|
-
},
|
100
|
-
execute: async (context) => {
|
101
|
-
// API call logic
|
102
|
-
},
|
103
|
-
};
|
104
|
-
```
|
37
|
+
import { z } from "zod";
|
38
|
+
import { GraphFlow } from "@ai.ntellect/core";
|
105
39
|
|
106
|
-
|
107
|
-
|
108
|
-
|
40
|
+
// Define context schema
|
41
|
+
const ContextSchema = z.object({
|
42
|
+
message: z.string(),
|
43
|
+
counter: z.number(),
|
44
|
+
});
|
109
45
|
|
110
|
-
|
111
|
-
const
|
46
|
+
// Create graph instance
|
47
|
+
const graph = new GraphFlow<typeof ContextSchema>("MyGraph", {
|
48
|
+
name: "MyGraph",
|
49
|
+
schema: ContextSchema,
|
50
|
+
context: { message: "Hello", counter: 0 },
|
112
51
|
nodes: [
|
113
52
|
{
|
114
|
-
name: "
|
53
|
+
name: "incrementCounter",
|
115
54
|
execute: async (context) => {
|
116
|
-
context.
|
55
|
+
context.counter++;
|
117
56
|
},
|
118
|
-
next: ["
|
57
|
+
next: ["checkThreshold"],
|
119
58
|
},
|
120
59
|
{
|
121
|
-
name: "
|
60
|
+
name: "checkThreshold",
|
61
|
+
condition: (context) => context.counter < 5,
|
122
62
|
execute: async (context) => {
|
123
|
-
context.
|
63
|
+
if (context.counter >= 5) {
|
64
|
+
context.message = "Threshold reached!";
|
65
|
+
}
|
124
66
|
},
|
125
|
-
next: ["
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
execute: async (context) => {
|
130
|
-
context.response = await generateAIResponse(context);
|
67
|
+
next: ["incrementCounter"],
|
68
|
+
retry: {
|
69
|
+
maxAttempts: 3,
|
70
|
+
delay: 1000,
|
131
71
|
},
|
132
|
-
next: ["validateResponse"],
|
133
72
|
},
|
134
73
|
],
|
135
74
|
});
|
75
|
+
|
76
|
+
// Observe state changes
|
77
|
+
(async () => {
|
78
|
+
// Execute the graph
|
79
|
+
graph.execute("incrementCounter");
|
80
|
+
graph.observe().state().subscribe(console.log);
|
81
|
+
})();
|
136
82
|
```
|
137
83
|
|
138
|
-
|
84
|
+
## Features
|
85
|
+
|
86
|
+
### Event handling
|
139
87
|
|
140
88
|
```typescript
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
retry: {
|
153
|
-
maxAttempts: 3,
|
154
|
-
delay: 1000,
|
155
|
-
},
|
156
|
-
condition: (context) => context.hasSufficientFunds,
|
157
|
-
execute: async (context) => {
|
158
|
-
await processPayment(context.transactionData);
|
159
|
-
},
|
160
|
-
next: ["notifyUser"],
|
161
|
-
},
|
162
|
-
],
|
163
|
-
});
|
89
|
+
// Event-driven node
|
90
|
+
{
|
91
|
+
name: "waitForEvent",
|
92
|
+
events: ["dataReceived"],
|
93
|
+
execute: async (context, event) => {
|
94
|
+
context.data = event.payload;
|
95
|
+
}
|
96
|
+
}
|
97
|
+
|
98
|
+
// Emit events
|
99
|
+
graph.emit("dataReceived", { value: 42 });
|
164
100
|
```
|
165
101
|
|
166
|
-
|
102
|
+
### State observation
|
167
103
|
|
168
104
|
```typescript
|
169
|
-
|
170
|
-
|
171
|
-
});
|
105
|
+
// Observe specific node
|
106
|
+
graph.observe().node("myNode").subscribe(console.log);
|
172
107
|
|
173
|
-
|
174
|
-
|
175
|
-
});
|
108
|
+
// Observe specific properties
|
109
|
+
graph.observe().property("counter").subscribe(console.log);
|
176
110
|
|
177
|
-
|
178
|
-
|
179
|
-
});
|
111
|
+
// Observe events
|
112
|
+
graph.observe().event("nodeCompleted").subscribe(console.log);
|
180
113
|
```
|
181
114
|
|
182
|
-
##
|
115
|
+
## Documentation
|
116
|
+
|
117
|
+
For complete documentation, visit our [GitBook](https://ai-ntellect.gitbook.io/core).
|
118
|
+
|
119
|
+
## Contributing
|
120
|
+
|
121
|
+
Contributions are welcome! To suggest an improvement or report an issue:
|
183
122
|
|
184
|
-
|
123
|
+
- Join our [Discord community](https://discord.gg/kEc5gWXJ)
|
124
|
+
- Explore the [GitBook documentation](https://ai-ntellect.gitbook.io/core)
|
125
|
+
- Open an issue on GitHub
|
185
126
|
|
186
|
-
|
187
|
-
- Graph composition and nesting
|
188
|
-
- Real-time monitoring dashboard
|
189
|
-
- Performance analytics
|
190
|
-
- Distributed execution support
|
127
|
+
## Useful links
|
191
128
|
|
192
|
-
|
129
|
+
- Documentation: [GitBook](https://ai-ntellect.gitbook.io/core)
|
130
|
+
- Community: [Discord](https://discord.gg/kEc5gWXJ)
|
131
|
+
- GitHub Repository: [@ai.ntellect/core](https://github.com/ai-ntellect/core)
|
package/graph/controller.ts
CHANGED
@@ -6,7 +6,7 @@ import { GraphFlow } from "./index";
|
|
6
6
|
* Controller class for managing the execution of graph flows
|
7
7
|
* Handles both sequential and parallel execution of multiple graphs
|
8
8
|
*/
|
9
|
-
export class
|
9
|
+
export class GraphFlowController {
|
10
10
|
/**
|
11
11
|
* Executes multiple graphs sequentially
|
12
12
|
* @param graphs - Array of GraphFlow instances to execute
|
@@ -0,0 +1,288 @@
|
|
1
|
+
import { Observable, Subject, filter } from "rxjs";
|
2
|
+
import { ZodSchema } from "zod";
|
3
|
+
import { IEventEmitter } from "../interfaces";
|
4
|
+
import { GraphContext, GraphEvent, Node } from "../types";
|
5
|
+
import { GraphNode } from "./node";
|
6
|
+
|
7
|
+
/**
|
8
|
+
* Manages event handling and routing for a graph
|
9
|
+
* Coordinates event emission, listening, and execution of event-driven nodes
|
10
|
+
* @template T - The Zod schema type for validation
|
11
|
+
*/
|
12
|
+
export class GraphEventManager<T extends ZodSchema> {
|
13
|
+
private eventSubject: Subject<GraphEvent<T>> = new Subject();
|
14
|
+
private nodeStreams: Map<string, Observable<GraphEvent<T>>> = new Map();
|
15
|
+
private context: GraphContext<T>;
|
16
|
+
private name: string;
|
17
|
+
private graphEvents?: string[];
|
18
|
+
private entryNode?: string;
|
19
|
+
private globalErrorHandler?: (error: Error, context: GraphContext<T>) => void;
|
20
|
+
|
21
|
+
/**
|
22
|
+
* Creates a new GraphEventManager instance
|
23
|
+
* @param eventEmitter - The event emitter implementation to use
|
24
|
+
* @param nodes - Map of all nodes in the graph
|
25
|
+
* @param name - Name of the graph
|
26
|
+
* @param context - Initial graph context
|
27
|
+
* @param graphEvents - List of events the graph should listen to
|
28
|
+
* @param entryNode - Name of the entry node for graph events
|
29
|
+
* @param globalErrorHandler - Global error handling function
|
30
|
+
* @param nodeExecutor - GraphNode instance for executing nodes
|
31
|
+
*/
|
32
|
+
constructor(
|
33
|
+
private eventEmitter: IEventEmitter,
|
34
|
+
private nodes: Map<string, Node<T, any>>,
|
35
|
+
name: string,
|
36
|
+
context: GraphContext<T>,
|
37
|
+
graphEvents?: string[],
|
38
|
+
entryNode?: string,
|
39
|
+
globalErrorHandler?: (error: Error, context: GraphContext<T>) => void,
|
40
|
+
private nodeExecutor?: GraphNode<T>
|
41
|
+
) {
|
42
|
+
this.name = name;
|
43
|
+
this.context = context;
|
44
|
+
this.graphEvents = graphEvents;
|
45
|
+
this.entryNode = entryNode;
|
46
|
+
this.globalErrorHandler = globalErrorHandler;
|
47
|
+
this.setupEventStreams();
|
48
|
+
}
|
49
|
+
|
50
|
+
/**
|
51
|
+
* Sets up event streams for all nodes that listen to events
|
52
|
+
*/
|
53
|
+
public setupEventStreams(): void {
|
54
|
+
for (const [nodeName, node] of this.nodes.entries()) {
|
55
|
+
if (node.events && node.events.length > 0) {
|
56
|
+
const nodeStream = this.eventSubject.pipe(
|
57
|
+
filter((event) => node.events!.includes(event.type))
|
58
|
+
);
|
59
|
+
this.nodeStreams.set(nodeName, nodeStream);
|
60
|
+
}
|
61
|
+
}
|
62
|
+
}
|
63
|
+
|
64
|
+
/**
|
65
|
+
* Emits an event with optional payload and context
|
66
|
+
* @param type - The type of event to emit
|
67
|
+
* @param payload - Optional payload data
|
68
|
+
* @param context - Optional graph context
|
69
|
+
*/
|
70
|
+
public emitEvent<P = any>(
|
71
|
+
type: string,
|
72
|
+
payload?: P,
|
73
|
+
context?: GraphContext<T>
|
74
|
+
): void {
|
75
|
+
const event: GraphEvent<T> = { type, payload, timestamp: Date.now() };
|
76
|
+
this.eventSubject.next(event);
|
77
|
+
this.eventEmitter.emit(type, event);
|
78
|
+
}
|
79
|
+
|
80
|
+
/**
|
81
|
+
* Sets up event listeners for all nodes in the graph
|
82
|
+
* Handles cleanup and re-registration of event listeners
|
83
|
+
*/
|
84
|
+
setupEventListeners(): void {
|
85
|
+
// First remove only the existing node-based listeners that we might have created previously
|
86
|
+
// We do NOT remove, for example, "nodeStarted" or "nodeCompleted" listeners that test code added.
|
87
|
+
for (const [eventName, listener] of this.eventEmitter
|
88
|
+
.rawListeners("*")
|
89
|
+
.entries()) {
|
90
|
+
// This can be tricky—EventEmitter doesn't directly let you remove by "type" of listener.
|
91
|
+
// Alternatively, we can store references in a separate structure.
|
92
|
+
// For simplicity, let's do a full removeAllListeners() on node-specified events (only),
|
93
|
+
// then re-add them below, but keep the test-based events like "nodeStarted" or "nodeCompleted".
|
94
|
+
}
|
95
|
+
|
96
|
+
// The simplest approach: removeAllListeners for each event that is declared as a node event
|
97
|
+
// so we don't stack up duplicates:
|
98
|
+
const allEvents = new Set<string>();
|
99
|
+
for (const node of this.nodes.values()) {
|
100
|
+
if (node.events) {
|
101
|
+
node.events.forEach((evt) => allEvents.add(evt));
|
102
|
+
}
|
103
|
+
}
|
104
|
+
for (const evt of allEvents) {
|
105
|
+
// remove only those events that are used by nodes
|
106
|
+
this.eventEmitter.removeAllListeners(evt);
|
107
|
+
}
|
108
|
+
|
109
|
+
// Now re-add the node-based event triggers
|
110
|
+
for (const node of this.nodes.values()) {
|
111
|
+
if (node.events && node.events.length > 0) {
|
112
|
+
node.events.forEach((event) => {
|
113
|
+
this.eventEmitter.on(
|
114
|
+
event,
|
115
|
+
async (data?: Partial<GraphContext<T>>) => {
|
116
|
+
const freshContext = structuredClone(this.context);
|
117
|
+
if (data) Object.assign(freshContext, data);
|
118
|
+
|
119
|
+
// If triggered by an event, we pass "true" so event-driven node will skip `next`.
|
120
|
+
await this.executeNode(
|
121
|
+
node.name,
|
122
|
+
freshContext,
|
123
|
+
undefined,
|
124
|
+
/* triggeredByEvent= */ true
|
125
|
+
);
|
126
|
+
}
|
127
|
+
);
|
128
|
+
});
|
129
|
+
}
|
130
|
+
}
|
131
|
+
}
|
132
|
+
|
133
|
+
/**
|
134
|
+
* Sets up listeners for graph-level events
|
135
|
+
* Handles graph start, completion, and error events
|
136
|
+
*/
|
137
|
+
setupGraphEventListeners(): void {
|
138
|
+
if (this.graphEvents && this.graphEvents.length > 0) {
|
139
|
+
this.graphEvents.forEach((event) => {
|
140
|
+
this.eventEmitter.on(event, async (data?: Partial<GraphContext<T>>) => {
|
141
|
+
const freshContext = this.createNewContext();
|
142
|
+
if (data) Object.assign(freshContext, data);
|
143
|
+
|
144
|
+
// Emit "graphStarted"
|
145
|
+
this.eventEmitter.emit("graphStarted", { name: this.name });
|
146
|
+
|
147
|
+
try {
|
148
|
+
// Execute the graph starting from the entry node
|
149
|
+
if (!this.entryNode) {
|
150
|
+
throw new Error("No entry node defined for graph event handling");
|
151
|
+
}
|
152
|
+
|
153
|
+
await this.executeNode(
|
154
|
+
this.entryNode,
|
155
|
+
freshContext,
|
156
|
+
undefined,
|
157
|
+
false
|
158
|
+
);
|
159
|
+
|
160
|
+
// Emit "graphCompleted"
|
161
|
+
this.eventEmitter.emit("graphCompleted", {
|
162
|
+
name: this.name,
|
163
|
+
context: this.context,
|
164
|
+
});
|
165
|
+
} catch (error) {
|
166
|
+
// Emit "graphError"
|
167
|
+
this.eventEmitter.emit("graphError", { name: this.name, error });
|
168
|
+
this.globalErrorHandler?.(error as Error, freshContext);
|
169
|
+
throw error;
|
170
|
+
}
|
171
|
+
});
|
172
|
+
});
|
173
|
+
}
|
174
|
+
}
|
175
|
+
|
176
|
+
/**
|
177
|
+
* Waits for a set of events to occur within a timeout period
|
178
|
+
* @param events - Array of event names to wait for
|
179
|
+
* @param timeout - Maximum time to wait in milliseconds
|
180
|
+
* @returns Promise that resolves with array of received events
|
181
|
+
* @throws Error if timeout occurs before all events are received
|
182
|
+
*/
|
183
|
+
async waitForEvents(
|
184
|
+
events: string[],
|
185
|
+
timeout: number = 30000
|
186
|
+
): Promise<any[]> {
|
187
|
+
return new Promise((resolve, reject) => {
|
188
|
+
const receivedEvents = new Map<string, any>();
|
189
|
+
const eventHandlers = new Map();
|
190
|
+
let isResolved = false;
|
191
|
+
|
192
|
+
const cleanup = () => {
|
193
|
+
events.forEach((event) => {
|
194
|
+
const handler = eventHandlers.get(event);
|
195
|
+
if (handler) {
|
196
|
+
this.eventEmitter.removeListener(event, handler);
|
197
|
+
}
|
198
|
+
});
|
199
|
+
};
|
200
|
+
|
201
|
+
events.forEach((event) => {
|
202
|
+
const handler = (eventData: any) => {
|
203
|
+
console.log(`Received event: ${event}`, eventData);
|
204
|
+
if (!isResolved) {
|
205
|
+
receivedEvents.set(event, eventData);
|
206
|
+
console.log(
|
207
|
+
"Current received events:",
|
208
|
+
Array.from(receivedEvents.keys())
|
209
|
+
);
|
210
|
+
|
211
|
+
if (events.every((e) => receivedEvents.has(e))) {
|
212
|
+
console.log("All events received, resolving");
|
213
|
+
isResolved = true;
|
214
|
+
clearTimeout(timeoutId);
|
215
|
+
cleanup();
|
216
|
+
resolve(Array.from(receivedEvents.values()));
|
217
|
+
}
|
218
|
+
}
|
219
|
+
};
|
220
|
+
|
221
|
+
eventHandlers.set(event, handler);
|
222
|
+
this.eventEmitter.on(event, handler);
|
223
|
+
});
|
224
|
+
|
225
|
+
const timeoutId = setTimeout(() => {
|
226
|
+
if (!isResolved) {
|
227
|
+
isResolved = true;
|
228
|
+
cleanup();
|
229
|
+
reject(new Error(`Timeout waiting for events: ${events.join(", ")}`));
|
230
|
+
}
|
231
|
+
}, timeout);
|
232
|
+
});
|
233
|
+
}
|
234
|
+
|
235
|
+
/**
|
236
|
+
* Registers an event handler
|
237
|
+
* @param eventName - Name of the event to listen for
|
238
|
+
* @param handler - Function to handle the event
|
239
|
+
*/
|
240
|
+
on(eventName: string, handler: (...args: any[]) => void): void {
|
241
|
+
this.eventEmitter.on(eventName, handler);
|
242
|
+
}
|
243
|
+
|
244
|
+
/**
|
245
|
+
* Emits an event through the event emitter
|
246
|
+
* @param eventName - Name of the event to emit
|
247
|
+
* @param data - Optional data to include with the event
|
248
|
+
*/
|
249
|
+
emit(eventName: string, data?: any): void {
|
250
|
+
this.eventEmitter.emit(eventName, data);
|
251
|
+
}
|
252
|
+
|
253
|
+
/**
|
254
|
+
* Creates a new context object by cloning the current context
|
255
|
+
* @returns A new graph context instance
|
256
|
+
* @private
|
257
|
+
*/
|
258
|
+
private createNewContext(): GraphContext<T> {
|
259
|
+
return structuredClone(this.context);
|
260
|
+
}
|
261
|
+
|
262
|
+
/**
|
263
|
+
* Executes a node with the given parameters
|
264
|
+
* @param nodeName - Name of the node to execute
|
265
|
+
* @param context - Graph context for execution
|
266
|
+
* @param inputs - Input data for the node
|
267
|
+
* @param triggeredByEvent - Whether execution was triggered by an event
|
268
|
+
* @returns Promise that resolves when execution is complete
|
269
|
+
* @throws Error if nodeExecutor is not initialized
|
270
|
+
* @private
|
271
|
+
*/
|
272
|
+
private async executeNode(
|
273
|
+
nodeName: string,
|
274
|
+
context: GraphContext<T>,
|
275
|
+
inputs: any,
|
276
|
+
triggeredByEvent: boolean
|
277
|
+
): Promise<void> {
|
278
|
+
if (!this.nodeExecutor) {
|
279
|
+
throw new Error("NodeExecutor not initialized");
|
280
|
+
}
|
281
|
+
return this.nodeExecutor.executeNode(
|
282
|
+
nodeName,
|
283
|
+
context,
|
284
|
+
inputs,
|
285
|
+
triggeredByEvent
|
286
|
+
);
|
287
|
+
}
|
288
|
+
}
|