@ai.ntellect/core 0.8.1 → 0.8.3
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 +190 -118
- package/dist/graph/controller.d.ts +4 -5
- package/dist/graph/controller.d.ts.map +1 -1
- package/dist/graph/controller.js +10 -10
- package/dist/graph/controller.js.map +1 -1
- package/dist/graph/event-manager.d.ts.map +1 -1
- package/dist/graph/event-manager.js +4 -4
- package/dist/graph/event-manager.js.map +1 -1
- package/dist/graph/index.d.ts +5 -16
- package/dist/graph/index.d.ts.map +1 -1
- package/dist/graph/index.js +32 -52
- package/dist/graph/index.js.map +1 -1
- package/dist/graph/node.d.ts +1 -10
- package/dist/graph/node.d.ts.map +1 -1
- package/dist/graph/node.js +7 -36
- package/dist/graph/node.js.map +1 -1
- package/dist/graph/observer.d.ts +4 -0
- package/dist/graph/observer.d.ts.map +1 -1
- package/dist/graph/observer.js +27 -1
- package/dist/graph/observer.js.map +1 -1
- package/dist/modules/agent/agent.d.ts.map +1 -1
- package/dist/modules/agent/agent.js +3 -6
- package/dist/modules/agent/agent.js.map +1 -1
- package/dist/modules/agent/generic-assistant.d.ts.map +1 -1
- package/dist/modules/agent/generic-assistant.js +3 -3
- package/dist/modules/agent/generic-assistant.js.map +1 -1
- package/dist/modules/agent/generic-executor.d.ts +1 -0
- package/dist/modules/agent/generic-executor.d.ts.map +1 -1
- package/dist/modules/agent/generic-executor.js +24 -35
- package/dist/modules/agent/generic-executor.js.map +1 -1
- package/dist/modules/agent/llm-factory.d.ts.map +1 -1
- package/dist/types/index.d.ts +90 -25
- package/dist/types/index.d.ts.map +1 -1
- package/graph/controller.ts +10 -11
- package/graph/event-manager.ts +2 -14
- package/graph/index.ts +37 -67
- package/graph/node.ts +5 -39
- package/graph/observer.ts +35 -5
- package/modules/agent/agent.ts +7 -8
- package/modules/agent/generic-assistant.ts +7 -5
- package/modules/agent/generic-executor.ts +33 -40
- package/package.json +1 -1
- package/test/graph/controller.test.ts +62 -17
- package/test/graph/index.test.ts +128 -133
- package/test/graph/node.test.ts +38 -233
- package/test/graph/observer.test.ts +18 -23
- package/types/index.ts +91 -28
package/graph/node.ts
CHANGED
@@ -86,7 +86,6 @@ export class GraphNode<T extends ZodSchema> {
|
|
86
86
|
public async executeNode(
|
87
87
|
nodeName: string,
|
88
88
|
context: GraphContext<T>,
|
89
|
-
params: any,
|
90
89
|
triggeredByEvent: boolean = false
|
91
90
|
): Promise<void> {
|
92
91
|
const node = this.nodes.get(nodeName);
|
@@ -120,11 +119,11 @@ export class GraphNode<T extends ZodSchema> {
|
|
120
119
|
},
|
121
120
|
});
|
122
121
|
|
123
|
-
if (node.condition && !node.condition(contextProxy
|
122
|
+
if (node.condition && !node.condition(contextProxy)) {
|
124
123
|
return;
|
125
124
|
}
|
126
125
|
|
127
|
-
await this.executeWithRetry(node, contextProxy, nodeName
|
126
|
+
await this.executeWithRetry(node, contextProxy, nodeName);
|
128
127
|
this.emitEvent("nodeCompleted", { name: nodeName, context: nodeContext });
|
129
128
|
|
130
129
|
if (!triggeredByEvent && node.next) {
|
@@ -151,7 +150,7 @@ export class GraphNode<T extends ZodSchema> {
|
|
151
150
|
|
152
151
|
// Sinon, exécuter les autres nœuds valides
|
153
152
|
for (const nextNode of validNextNodes) {
|
154
|
-
await this.executeNode(nextNode.name, context,
|
153
|
+
await this.executeNode(nextNode.name, context, false);
|
155
154
|
}
|
156
155
|
}
|
157
156
|
} catch (error) {
|
@@ -164,34 +163,6 @@ export class GraphNode<T extends ZodSchema> {
|
|
164
163
|
}
|
165
164
|
}
|
166
165
|
|
167
|
-
/**
|
168
|
-
* Validates the params for a node using its schema
|
169
|
-
* @param node - The node whose params need validation
|
170
|
-
* @param params - The input data to validate
|
171
|
-
* @param nodeName - The name of the node (for error messages)
|
172
|
-
* @throws Error if validation fails
|
173
|
-
* @private
|
174
|
-
*/
|
175
|
-
private async validateParams(
|
176
|
-
node: GraphNodeConfig<T, any>,
|
177
|
-
params: any,
|
178
|
-
nodeName: string
|
179
|
-
): Promise<void> {
|
180
|
-
// Si pas de schéma de validation ou si le schéma est optionnel, accepter n'importe quels params
|
181
|
-
if (!node.params || node.params.isOptional?.()) return;
|
182
|
-
|
183
|
-
// Vérifier les params uniquement si un schéma est défini et non optionnel
|
184
|
-
if (!params) {
|
185
|
-
throw new Error(`Params required for node "${nodeName}"`);
|
186
|
-
}
|
187
|
-
|
188
|
-
try {
|
189
|
-
return node.params.parse(params);
|
190
|
-
} catch (error: any) {
|
191
|
-
throw error;
|
192
|
-
}
|
193
|
-
}
|
194
|
-
|
195
166
|
/**
|
196
167
|
* Executes a node with retry logic
|
197
168
|
* @param node - The node to execute
|
@@ -205,19 +176,14 @@ export class GraphNode<T extends ZodSchema> {
|
|
205
176
|
private async executeWithRetry(
|
206
177
|
node: GraphNodeConfig<T, any>,
|
207
178
|
contextProxy: GraphContext<T>,
|
208
|
-
nodeName: string
|
209
|
-
params?: NodeParams
|
179
|
+
nodeName: string
|
210
180
|
): Promise<void> {
|
211
181
|
let attempts = 0;
|
212
182
|
let lastError: Error = new Error("Unknown error");
|
213
183
|
|
214
184
|
while (attempts < (node.retry?.maxAttempts || 1)) {
|
215
185
|
try {
|
216
|
-
|
217
|
-
await this.validateParams(node, params, nodeName);
|
218
|
-
}
|
219
|
-
|
220
|
-
await node.execute(contextProxy, params, {
|
186
|
+
await node.execute(contextProxy, {
|
221
187
|
eventEmitter: this.eventEmitter,
|
222
188
|
});
|
223
189
|
return;
|
package/graph/observer.ts
CHANGED
@@ -125,17 +125,47 @@ export class GraphObserver<T extends ZodSchema> {
|
|
125
125
|
|
126
126
|
/**
|
127
127
|
* Waits for correlated events to occur and validates them using a correlation function
|
128
|
+
* @param eventTypes - Array of event types to wait for
|
129
|
+
* @param timeoutMs - Timeout in milliseconds
|
130
|
+
* @param correlationFn - Function to validate event correlation
|
131
|
+
* @returns Promise that resolves with the correlated events
|
128
132
|
*/
|
129
133
|
waitForCorrelatedEvents(
|
130
134
|
eventTypes: string[],
|
131
135
|
timeoutMs: number,
|
132
136
|
correlationFn: (events: GraphEvent<T>[]) => boolean
|
133
137
|
): Promise<GraphEvent<T>[]> {
|
134
|
-
return
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
138
|
+
return new Promise((resolve, reject) => {
|
139
|
+
const events: GraphEvent<T>[] = [];
|
140
|
+
const timeout = setTimeout(() => {
|
141
|
+
reject(
|
142
|
+
new Error(
|
143
|
+
`Timeout waiting for correlated events: ${eventTypes.join(", ")}`
|
144
|
+
)
|
145
|
+
);
|
146
|
+
}, timeoutMs);
|
147
|
+
|
148
|
+
const subscription = this.eventSubject
|
149
|
+
.pipe(
|
150
|
+
filter((event) => eventTypes.includes(event.type)),
|
151
|
+
takeUntil(this.destroySubject)
|
152
|
+
)
|
153
|
+
.subscribe({
|
154
|
+
next: (event) => {
|
155
|
+
events.push(event);
|
156
|
+
if (events.length === eventTypes.length && correlationFn(events)) {
|
157
|
+
clearTimeout(timeout);
|
158
|
+
subscription.unsubscribe();
|
159
|
+
resolve(events);
|
160
|
+
}
|
161
|
+
},
|
162
|
+
error: (error) => {
|
163
|
+
clearTimeout(timeout);
|
164
|
+
subscription.unsubscribe();
|
165
|
+
reject(error);
|
166
|
+
},
|
167
|
+
});
|
168
|
+
});
|
139
169
|
}
|
140
170
|
|
141
171
|
/**
|
package/modules/agent/agent.ts
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
import { GraphContext } from "@/types";
|
1
2
|
import { GraphFlow } from "../../graph/index";
|
2
3
|
import {
|
3
4
|
AgentConfig,
|
@@ -51,31 +52,29 @@ export class Agent {
|
|
51
52
|
* @returns {GraphFlow<typeof AgentContextSchema>} The configured workflow
|
52
53
|
*/
|
53
54
|
private setupWorkflow(): GraphFlow<typeof AgentContextSchema> {
|
54
|
-
return new GraphFlow(
|
55
|
+
return new GraphFlow({
|
55
56
|
name: "assistant",
|
56
57
|
schema: AgentContextSchema,
|
57
58
|
context: {
|
58
59
|
input: { raw: "" },
|
59
60
|
actions: [],
|
60
61
|
response: "",
|
61
|
-
executedActions: [],
|
62
62
|
},
|
63
63
|
nodes: [
|
64
64
|
{
|
65
65
|
name: "process",
|
66
|
-
execute: async (context) => {
|
66
|
+
execute: async (context: GraphContext<typeof AgentContextSchema>) => {
|
67
67
|
const agentContext = context as unknown as AgentContext;
|
68
68
|
const decision = await this.executor.makeDecision(agentContext);
|
69
69
|
context.actions = decision.actions;
|
70
70
|
context.response = decision.response;
|
71
71
|
},
|
72
|
-
next: (context
|
72
|
+
next: (context: GraphContext<typeof AgentContextSchema>) =>
|
73
|
+
context.actions.length > 0 ? ["execute"] : [],
|
73
74
|
},
|
74
75
|
{
|
75
76
|
name: "execute",
|
76
|
-
execute: async (context) => {
|
77
|
-
console.log(`Executing actions:`);
|
78
|
-
console.log(context.actions);
|
77
|
+
execute: async (context: GraphContext<typeof AgentContextSchema>) => {
|
79
78
|
const timestamp = new Date().toISOString();
|
80
79
|
context.knowledge = `Date: ${timestamp}\n${JSON.stringify(
|
81
80
|
context.actions
|
@@ -97,7 +96,7 @@ export class Agent {
|
|
97
96
|
* @returns {Promise<AgentContext>} The resulting context after processing
|
98
97
|
*/
|
99
98
|
public async process(input: string): Promise<AgentContext> {
|
100
|
-
await this.workflow.execute("process",
|
99
|
+
await this.workflow.execute("process", {
|
101
100
|
input: { raw: input },
|
102
101
|
actions: [],
|
103
102
|
response: "",
|
@@ -1,3 +1,4 @@
|
|
1
|
+
import { GraphContext } from "@/types";
|
1
2
|
import { GraphFlow } from "../../graph/index";
|
2
3
|
import {
|
3
4
|
AgentConfig,
|
@@ -41,7 +42,7 @@ export class Agent {
|
|
41
42
|
}
|
42
43
|
|
43
44
|
private setupWorkflow(): GraphFlow<typeof AgentContextSchema> {
|
44
|
-
return new GraphFlow(
|
45
|
+
return new GraphFlow({
|
45
46
|
name: "assistant",
|
46
47
|
schema: AgentContextSchema,
|
47
48
|
context: {
|
@@ -53,17 +54,18 @@ export class Agent {
|
|
53
54
|
nodes: [
|
54
55
|
{
|
55
56
|
name: "process",
|
56
|
-
execute: async (context) => {
|
57
|
+
execute: async (context: GraphContext<typeof AgentContextSchema>) => {
|
57
58
|
const agentContext = context as unknown as AgentContext;
|
58
59
|
const decision = await this.executor.makeDecision(agentContext);
|
59
60
|
context.actions = decision.actions;
|
60
61
|
context.response = decision.response;
|
61
62
|
},
|
62
|
-
next: (context
|
63
|
+
next: (context: GraphContext<typeof AgentContextSchema>) =>
|
64
|
+
context.actions.length > 0 ? ["execute"] : [],
|
63
65
|
},
|
64
66
|
{
|
65
67
|
name: "execute",
|
66
|
-
execute: async (context) => {
|
68
|
+
execute: async (context: GraphContext<typeof AgentContextSchema>) => {
|
67
69
|
console.log(`Executing actions:`);
|
68
70
|
console.log(context.actions);
|
69
71
|
|
@@ -79,7 +81,7 @@ export class Agent {
|
|
79
81
|
}
|
80
82
|
|
81
83
|
public async process(input: string): Promise<AgentContext> {
|
82
|
-
await this.workflow.execute("process",
|
84
|
+
await this.workflow.execute("process", {
|
83
85
|
input: { raw: input },
|
84
86
|
actions: [],
|
85
87
|
response: "",
|
@@ -10,6 +10,7 @@ import {
|
|
10
10
|
import { BaseAgent } from "./base";
|
11
11
|
import { AgentExecutor } from "./base/executor";
|
12
12
|
import { LLMFactory } from "./llm-factory";
|
13
|
+
import { PromptBuilder } from "./prompt-builder";
|
13
14
|
|
14
15
|
/**
|
15
16
|
* Generic executor that handles the interaction between the agent and LLM
|
@@ -96,6 +97,33 @@ ${graph
|
|
96
97
|
.join("\n\n");
|
97
98
|
}
|
98
99
|
|
100
|
+
private async buildSystemPrompt(context: AgentContext): Promise<string> {
|
101
|
+
return new PromptBuilder()
|
102
|
+
.addSection("ROLE", this.agent.getRole())
|
103
|
+
.addSection("GOAL", this.agent.getGoal())
|
104
|
+
.addSection("BACKSTORY", this.agent.getBackstory())
|
105
|
+
.addSection(
|
106
|
+
"RECENT ACTIONS (check this before deciding what to do)",
|
107
|
+
context.knowledge || "None"
|
108
|
+
)
|
109
|
+
.addSection(
|
110
|
+
"AVAILABLE ACTIONS (only if you need)",
|
111
|
+
this.generateActionSchema()
|
112
|
+
)
|
113
|
+
.addSection(
|
114
|
+
"INSTRUCTIONS",
|
115
|
+
`
|
116
|
+
- Never take actions if an recent action matches the user's input
|
117
|
+
- If you need to take actions, structure parameters according to the action's schema
|
118
|
+
- If goal is achieved, explain that you achieved for examples:
|
119
|
+
- "I have achieved the goal"
|
120
|
+
- "I have done what I needed to do"
|
121
|
+
- "I have completed the task"
|
122
|
+
`
|
123
|
+
)
|
124
|
+
.build(context);
|
125
|
+
}
|
126
|
+
|
99
127
|
/**
|
100
128
|
* Makes a decision based on the current context using the LLM
|
101
129
|
* @param {AgentContext} context - The context to base the decision on
|
@@ -107,50 +135,16 @@ ${graph
|
|
107
135
|
chalk.dim("Analyzing context and available actions...")
|
108
136
|
);
|
109
137
|
|
110
|
-
const
|
111
|
-
if (memories.length > 0) {
|
112
|
-
this.log("info", chalk.dim("Retrieved relevant memories:"));
|
113
|
-
memories.forEach((m) => this.log("info", chalk.dim(`- ${m.content}`)));
|
114
|
-
|
115
|
-
context.knowledge =
|
116
|
-
(context.knowledge || "") +
|
117
|
-
"\n" +
|
118
|
-
memories.map((m) => m.content).join("\n");
|
119
|
-
}
|
120
|
-
|
121
|
-
const systemPrompt = `
|
122
|
-
## ROLE
|
123
|
-
${this.agent.getRole()}
|
124
|
-
|
125
|
-
## GOAL
|
126
|
-
${this.agent.getGoal()}
|
127
|
-
|
128
|
-
## BACKSTORY
|
129
|
-
${this.agent.getBackstory()}
|
130
|
-
|
131
|
-
## RECENT ACTIONS
|
132
|
-
${context.knowledge ? `${context.knowledge}\n` : "None"}
|
133
|
-
|
134
|
-
## AVAILABLE ACTIONS
|
135
|
-
${this.generateActionSchema()}
|
136
|
-
|
137
|
-
## INSTRUCTIONS
|
138
|
-
- Analyze the user input and what you have done (if no action is needed, just return an empty array)
|
139
|
-
- Choose appropriate actions based on their parameters
|
140
|
-
- Structure parameters according to the action's schema
|
141
|
-
- Look at the goal and the actions you have done, if you have achieved the goal, STOP
|
142
|
-
`;
|
138
|
+
const systemPrompt = await this.buildSystemPrompt(context);
|
143
139
|
|
140
|
+
console.log({ systemPrompt });
|
144
141
|
this.log("info", chalk.dim("Generating response..."));
|
145
142
|
|
146
143
|
const result = await this.llm.generate(
|
147
144
|
{
|
148
145
|
system: systemPrompt,
|
149
|
-
user: `User
|
150
|
-
|
151
|
-
context.executedActions
|
152
|
-
?.map((a) => `\n- ${a.name} => ${JSON.stringify(a.result)}`)
|
153
|
-
.join("") || "None"
|
146
|
+
user: `User sent you this message at ${new Date().toISOString()}\n${
|
147
|
+
context.input.raw
|
154
148
|
}`,
|
155
149
|
},
|
156
150
|
z.object({
|
@@ -168,7 +162,6 @@ ${graph
|
|
168
162
|
response: z.string(),
|
169
163
|
})
|
170
164
|
);
|
171
|
-
|
172
165
|
if (result.object.actions.length > 0) {
|
173
166
|
this.log("success", chalk.green("Decided to take actions:"));
|
174
167
|
result.object.actions.forEach(
|
@@ -239,7 +232,7 @@ ${graph
|
|
239
232
|
// Execute with merged context
|
240
233
|
const result = await workflow.execute(
|
241
234
|
startNode,
|
242
|
-
|
235
|
+
|
243
236
|
workflowContext
|
244
237
|
);
|
245
238
|
|
package/package.json
CHANGED
@@ -2,21 +2,29 @@ import { expect } from "chai";
|
|
2
2
|
import { z } from "zod";
|
3
3
|
import { GraphController } from "../../graph/controller";
|
4
4
|
import { GraphFlow } from "../../graph/index";
|
5
|
-
import { GraphNodeConfig } from "../../types";
|
5
|
+
import { GraphContext, GraphNodeConfig } from "../../types";
|
6
6
|
|
7
7
|
describe("GraphController", () => {
|
8
8
|
const TestSchema = z.object({
|
9
9
|
counter: z.number(),
|
10
10
|
message: z.string(),
|
11
|
+
value: z.number().optional(),
|
12
|
+
prefix: z.string().optional(),
|
11
13
|
});
|
12
14
|
|
13
15
|
const createTestGraph = (name: string): GraphFlow<typeof TestSchema> => {
|
14
16
|
const nodes: GraphNodeConfig<typeof TestSchema>[] = [
|
15
17
|
{
|
16
18
|
name: "start",
|
17
|
-
execute: async (context
|
18
|
-
context.
|
19
|
-
|
19
|
+
execute: async (context) => {
|
20
|
+
if (context.value !== undefined) {
|
21
|
+
context.counter = context.value;
|
22
|
+
}
|
23
|
+
if (context.prefix) {
|
24
|
+
context.message = `${context.prefix}-${name}`;
|
25
|
+
} else {
|
26
|
+
context.message = name;
|
27
|
+
}
|
20
28
|
},
|
21
29
|
},
|
22
30
|
{
|
@@ -27,7 +35,7 @@ describe("GraphController", () => {
|
|
27
35
|
},
|
28
36
|
];
|
29
37
|
|
30
|
-
return new GraphFlow(
|
38
|
+
return new GraphFlow({
|
31
39
|
name,
|
32
40
|
nodes,
|
33
41
|
schema: TestSchema,
|
@@ -36,23 +44,21 @@ describe("GraphController", () => {
|
|
36
44
|
};
|
37
45
|
|
38
46
|
describe("Sequential Execution", () => {
|
39
|
-
it("should execute graphs sequentially with different
|
47
|
+
it("should execute graphs sequentially with different contexts", async () => {
|
40
48
|
const graph1 = createTestGraph("graph1");
|
41
49
|
const graph2 = createTestGraph("graph2");
|
42
50
|
const graph3 = createTestGraph("graph3");
|
43
51
|
|
44
|
-
const
|
45
|
-
|
46
|
-
|
47
|
-
{ prefix: "
|
48
|
-
{ prefix: "test2" },
|
49
|
-
{ prefix: "test3" },
|
52
|
+
const contexts = [
|
53
|
+
{ value: 10, prefix: "test1" },
|
54
|
+
{ value: 20, prefix: "test2" },
|
55
|
+
{ value: 30, prefix: "test3" },
|
50
56
|
];
|
51
57
|
|
52
58
|
const results = await GraphController.executeSequential(
|
53
59
|
[graph1, graph2, graph3],
|
54
60
|
["start", "start", "start"],
|
55
|
-
|
61
|
+
contexts
|
56
62
|
);
|
57
63
|
|
58
64
|
expect(results).to.have.length(3);
|
@@ -66,7 +72,7 @@ describe("GraphController", () => {
|
|
66
72
|
expect(results[0].nodeName).to.equal("start");
|
67
73
|
});
|
68
74
|
|
69
|
-
it("should handle missing
|
75
|
+
it("should handle missing contexts gracefully", async () => {
|
70
76
|
const graph1 = createTestGraph("graph1");
|
71
77
|
const graph2 = createTestGraph("graph2");
|
72
78
|
|
@@ -89,7 +95,7 @@ describe("GraphController", () => {
|
|
89
95
|
createTestGraph(`graph${i + 1}`)
|
90
96
|
);
|
91
97
|
|
92
|
-
const
|
98
|
+
const contexts = Array.from({ length: 5 }, (_, i) => ({
|
93
99
|
value: (i + 1) * 10,
|
94
100
|
prefix: `test${i + 1}`,
|
95
101
|
}));
|
@@ -106,7 +112,7 @@ describe("GraphController", () => {
|
|
106
112
|
graphs,
|
107
113
|
Array(5).fill("start"),
|
108
114
|
2,
|
109
|
-
|
115
|
+
contexts
|
110
116
|
);
|
111
117
|
const executionTime = Date.now() - startTime;
|
112
118
|
|
@@ -119,7 +125,7 @@ describe("GraphController", () => {
|
|
119
125
|
});
|
120
126
|
|
121
127
|
it("should handle errors in parallel execution", async () => {
|
122
|
-
const errorGraph = new GraphFlow(
|
128
|
+
const errorGraph = new GraphFlow({
|
123
129
|
name: "errorGraph",
|
124
130
|
nodes: [
|
125
131
|
{
|
@@ -188,4 +194,43 @@ describe("GraphController", () => {
|
|
188
194
|
]);
|
189
195
|
});
|
190
196
|
});
|
197
|
+
|
198
|
+
it("should wait for correlated events", async function () {
|
199
|
+
const graph = new GraphFlow({
|
200
|
+
name: "test",
|
201
|
+
schema: TestSchema,
|
202
|
+
nodes: [
|
203
|
+
{
|
204
|
+
name: "correlatedEventsNode",
|
205
|
+
when: {
|
206
|
+
events: ["eventA", "eventB"],
|
207
|
+
timeout: 1000,
|
208
|
+
strategy: {
|
209
|
+
type: "correlate",
|
210
|
+
correlation: (events) => {
|
211
|
+
const eventA = events.find((e) => e.type === "eventA");
|
212
|
+
const eventB = events.find((e) => e.type === "eventB");
|
213
|
+
return eventA?.payload?.id === eventB?.payload?.id;
|
214
|
+
},
|
215
|
+
},
|
216
|
+
},
|
217
|
+
execute: async (context: GraphContext<typeof TestSchema>) => {
|
218
|
+
context.message = "Correlated events received";
|
219
|
+
},
|
220
|
+
},
|
221
|
+
],
|
222
|
+
context: { value: 0, counter: 0, message: "" },
|
223
|
+
});
|
224
|
+
|
225
|
+
const execution = graph.execute("correlatedEventsNode");
|
226
|
+
|
227
|
+
// Émettre les événements corrélés
|
228
|
+
setTimeout(() => {
|
229
|
+
graph.emit("eventA", { id: "123", status: "completed" });
|
230
|
+
graph.emit("eventB", { id: "123", status: "available" });
|
231
|
+
}, 100);
|
232
|
+
|
233
|
+
await execution;
|
234
|
+
expect(graph.getContext().message).to.equal("Correlated events received");
|
235
|
+
});
|
191
236
|
});
|