@ai.ntellect/core 0.7.14 → 0.8.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/dist/graph/event-manager.d.ts +9 -1
- package/dist/graph/event-manager.d.ts.map +1 -1
- package/dist/graph/event-manager.js +115 -37
- package/dist/graph/event-manager.js.map +1 -1
- package/dist/graph/index.d.ts +20 -1
- package/dist/graph/index.d.ts.map +1 -1
- package/dist/graph/index.js +59 -10
- package/dist/graph/index.js.map +1 -1
- package/dist/graph/node.d.ts +0 -24
- package/dist/graph/node.d.ts.map +1 -1
- package/dist/graph/node.js +2 -71
- package/dist/graph/node.js.map +1 -1
- package/dist/graph/observer.d.ts +6 -87
- package/dist/graph/observer.d.ts.map +1 -1
- package/dist/graph/observer.js +3 -116
- package/dist/graph/observer.js.map +1 -1
- package/dist/index.d.ts +1 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -6
- package/dist/index.js.map +1 -1
- package/dist/interfaces/index.d.ts +10 -1
- package/dist/interfaces/index.d.ts.map +1 -1
- package/dist/interfaces/index.js.map +1 -1
- package/dist/modules/agent/agent.d.ts +35 -0
- package/dist/modules/agent/agent.d.ts.map +1 -0
- package/dist/modules/agent/agent.js +106 -0
- package/dist/modules/agent/agent.js.map +1 -0
- package/dist/modules/agent/base/executor.d.ts +51 -0
- package/dist/modules/agent/base/executor.d.ts.map +1 -0
- package/dist/modules/agent/base/executor.js +66 -0
- package/dist/modules/agent/base/executor.js.map +1 -0
- package/dist/modules/agent/base/index.d.ts +30 -0
- package/dist/modules/agent/base/index.d.ts.map +1 -0
- package/dist/modules/agent/base/index.js +100 -0
- package/dist/modules/agent/base/index.js.map +1 -0
- package/dist/modules/agent/generic-assistant.d.ts +20 -0
- package/dist/modules/agent/generic-assistant.d.ts.map +1 -0
- package/dist/modules/agent/generic-assistant.js +89 -0
- package/dist/modules/agent/generic-assistant.js.map +1 -0
- package/dist/modules/agent/generic-executor.d.ts +57 -0
- package/dist/modules/agent/generic-executor.d.ts.map +1 -0
- package/dist/modules/agent/generic-executor.js +200 -0
- package/dist/modules/agent/generic-executor.js.map +1 -0
- package/dist/modules/agent/llm-factory.d.ts +19 -0
- package/dist/modules/agent/llm-factory.d.ts.map +1 -0
- package/dist/modules/agent/llm-factory.js +56 -0
- package/dist/modules/agent/llm-factory.js.map +1 -0
- package/dist/modules/agent/prompt-builder.d.ts +35 -0
- package/dist/modules/agent/prompt-builder.d.ts.map +1 -0
- package/dist/modules/agent/prompt-builder.js +76 -0
- package/dist/modules/agent/prompt-builder.js.map +1 -0
- package/dist/modules/memory/adapters/in-memory/index.d.ts.map +1 -1
- package/dist/modules/memory/adapters/in-memory/index.js +4 -3
- package/dist/modules/memory/adapters/in-memory/index.js.map +1 -1
- package/dist/modules/memory/adapters/meilisearch/index.d.ts.map +1 -1
- package/dist/modules/memory/adapters/meilisearch/index.js +7 -4
- package/dist/modules/memory/adapters/meilisearch/index.js.map +1 -1
- package/dist/modules/memory/adapters/redis/index.d.ts.map +1 -1
- package/dist/modules/memory/adapters/redis/index.js +2 -1
- package/dist/modules/memory/adapters/redis/index.js.map +1 -1
- package/dist/modules/nlp/engine.d.ts +126 -0
- package/dist/modules/nlp/engine.d.ts.map +1 -0
- package/dist/modules/nlp/engine.js +300 -0
- package/dist/modules/nlp/engine.js.map +1 -0
- package/dist/modules/nlp/index.d.ts +27 -0
- package/dist/modules/nlp/index.d.ts.map +1 -0
- package/dist/modules/nlp/index.js +56 -0
- package/dist/modules/nlp/index.js.map +1 -0
- package/dist/types/agent.d.ts +233 -0
- package/dist/types/agent.d.ts.map +1 -0
- package/dist/types/agent.js +29 -0
- package/dist/types/agent.js.map +1 -0
- package/dist/types/index.d.ts +72 -18
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/generate-action-schema.d.ts.map +1 -1
- package/graph/event-manager.ts +135 -42
- package/graph/index.ts +57 -4
- package/graph/node.ts +2 -104
- package/graph/observer.ts +9 -215
- package/index.ts +2 -7
- package/interfaces/index.ts +12 -0
- package/modules/agent/agent.ts +108 -0
- package/modules/agent/base/executor.ts +100 -0
- package/modules/agent/base/index.ts +99 -0
- package/modules/agent/generic-assistant.ts +90 -0
- package/modules/agent/generic-executor.ts +259 -0
- package/modules/agent/llm-factory.ts +47 -0
- package/modules/agent/prompt-builder.ts +78 -0
- package/modules/memory/adapters/in-memory/index.ts +4 -3
- package/modules/memory/adapters/meilisearch/index.ts +7 -4
- package/modules/memory/adapters/redis/index.ts +2 -1
- package/modules/nlp/engine.ts +325 -0
- package/modules/nlp/index.ts +45 -0
- package/package.json +5 -2
- package/test/graph/index.test.ts +6 -4
- package/test/graph/node.test.ts +18 -14
- package/types/agent.ts +174 -0
- package/types/index.ts +74 -18
@@ -0,0 +1,325 @@
|
|
1
|
+
import { ActionHandler, NLPConfig } from "../../types";
|
2
|
+
|
3
|
+
const { dockStart } = require("@nlpjs/basic");
|
4
|
+
|
5
|
+
/**
|
6
|
+
* NLP Engine for processing natural language commands
|
7
|
+
* @example
|
8
|
+
* const engine = await NLPEngine.create({
|
9
|
+
* corpus: require('./corpus.json'),
|
10
|
+
* responses: require('./responses.json'),
|
11
|
+
* entities: require('./entities.json')
|
12
|
+
* });
|
13
|
+
*
|
14
|
+
* engine.addAction('transferTokens', async (data) => {
|
15
|
+
* // Handle transfer logic
|
16
|
+
* });
|
17
|
+
*
|
18
|
+
* const response = await engine.process('transfer 5 ETH');
|
19
|
+
*/
|
20
|
+
export class NLPEngine {
|
21
|
+
private manager: any;
|
22
|
+
private responses: Record<string, any>;
|
23
|
+
private intentHandlers: Record<string, ActionHandler> = {};
|
24
|
+
|
25
|
+
constructor() {
|
26
|
+
this.responses = {};
|
27
|
+
}
|
28
|
+
|
29
|
+
/**
|
30
|
+
* Creates and initializes a new NLP Engine
|
31
|
+
*/
|
32
|
+
static async create(config: NLPConfig): Promise<NLPEngine> {
|
33
|
+
const engine = new NLPEngine();
|
34
|
+
await engine.init(config);
|
35
|
+
return engine;
|
36
|
+
}
|
37
|
+
|
38
|
+
/**
|
39
|
+
* Initializes the NLP engine with configuration
|
40
|
+
*/
|
41
|
+
private async init({
|
42
|
+
corpus,
|
43
|
+
responses,
|
44
|
+
entities,
|
45
|
+
language = "en",
|
46
|
+
threshold = 0.5,
|
47
|
+
}: NLPConfig) {
|
48
|
+
const dock = await dockStart({
|
49
|
+
settings: {
|
50
|
+
nlp: {
|
51
|
+
forceNER: true,
|
52
|
+
languages: [language],
|
53
|
+
corpora: corpus ? [corpus] : undefined,
|
54
|
+
},
|
55
|
+
ner: { threshold },
|
56
|
+
},
|
57
|
+
use: ["Basic", "LangEn"],
|
58
|
+
});
|
59
|
+
|
60
|
+
this.manager = dock.get("nlp");
|
61
|
+
this.responses = responses || {};
|
62
|
+
|
63
|
+
if (corpus) {
|
64
|
+
await this.manager.addCorpus(corpus);
|
65
|
+
}
|
66
|
+
|
67
|
+
if (entities) {
|
68
|
+
this.registerEntities(entities);
|
69
|
+
}
|
70
|
+
|
71
|
+
await this.manager.train();
|
72
|
+
}
|
73
|
+
|
74
|
+
/**
|
75
|
+
* Registers entities for Named Entity Recognition (NER)
|
76
|
+
* @private
|
77
|
+
* @param {Record<string, any>} entities - Entity definitions
|
78
|
+
*/
|
79
|
+
private registerEntities(entities: Record<string, any>) {
|
80
|
+
Object.entries(entities).forEach(([name, data]: [string, any]) => {
|
81
|
+
if (data.options) {
|
82
|
+
Object.entries(data.options).forEach(([option, texts]) => {
|
83
|
+
this.manager.addNerRuleOptionTexts(
|
84
|
+
"en",
|
85
|
+
name,
|
86
|
+
option,
|
87
|
+
texts as string[]
|
88
|
+
);
|
89
|
+
});
|
90
|
+
} else if (data.regex) {
|
91
|
+
this.manager.addNerRegexRule("en", name, data.regex);
|
92
|
+
} else if (data.trim) {
|
93
|
+
data.trim.forEach((trimRule: any) => {
|
94
|
+
if (trimRule.position === "afterLast") {
|
95
|
+
trimRule.words.forEach((word: string) => {
|
96
|
+
this.manager.addNerAfterLastCondition("en", name, word);
|
97
|
+
});
|
98
|
+
} else if (trimRule.position === "betweenLast") {
|
99
|
+
this.manager.addNerBetweenLastCondition(
|
100
|
+
"en",
|
101
|
+
name,
|
102
|
+
trimRule.leftWords,
|
103
|
+
trimRule.rightWords
|
104
|
+
);
|
105
|
+
}
|
106
|
+
});
|
107
|
+
}
|
108
|
+
});
|
109
|
+
}
|
110
|
+
|
111
|
+
/**
|
112
|
+
* Adds an action handler for a specific intent
|
113
|
+
* @param {string} name - Intent name
|
114
|
+
* @param {ActionHandler} handler - Action handler function
|
115
|
+
*/
|
116
|
+
addAction(name: string, handler: ActionHandler): void {
|
117
|
+
this.intentHandlers[name] = handler;
|
118
|
+
}
|
119
|
+
|
120
|
+
/**
|
121
|
+
* Creates and loads a pre-trained NLP Engine
|
122
|
+
*/
|
123
|
+
static async loadFromModel(
|
124
|
+
modelPath: string,
|
125
|
+
responses?: Record<string, any>
|
126
|
+
): Promise<NLPEngine> {
|
127
|
+
const engine = new NLPEngine();
|
128
|
+
engine.responses = responses || {};
|
129
|
+
await engine.loadModel(modelPath);
|
130
|
+
return engine;
|
131
|
+
}
|
132
|
+
|
133
|
+
/**
|
134
|
+
* Loads a pre-trained model and configures default actions
|
135
|
+
*/
|
136
|
+
private async loadModel(modelPath: string) {
|
137
|
+
const dock = await dockStart({
|
138
|
+
settings: {
|
139
|
+
nlp: {
|
140
|
+
forceNER: true,
|
141
|
+
languages: ["en"],
|
142
|
+
},
|
143
|
+
},
|
144
|
+
use: ["Basic", "LangEn"],
|
145
|
+
});
|
146
|
+
|
147
|
+
this.manager = dock.get("nlp");
|
148
|
+
await this.manager.load(modelPath);
|
149
|
+
|
150
|
+
// Configure default actions handler
|
151
|
+
this.setupDefaultActions();
|
152
|
+
}
|
153
|
+
|
154
|
+
/**
|
155
|
+
* Setup default actions to handle responses
|
156
|
+
*/
|
157
|
+
private setupDefaultActions() {
|
158
|
+
this.manager.onIntent = async (data: any) => {
|
159
|
+
// Execute registered action if exists
|
160
|
+
if (data.actions?.length > 0) {
|
161
|
+
for (const actionData of data.actions) {
|
162
|
+
const result = await this.executeAction(actionData, data);
|
163
|
+
if (result) {
|
164
|
+
data.actionResult = result;
|
165
|
+
}
|
166
|
+
}
|
167
|
+
}
|
168
|
+
|
169
|
+
// Format response if answer exists
|
170
|
+
if (data.answer && this.responses[data.answer]) {
|
171
|
+
data.jsonResponse = this.formatResponse(
|
172
|
+
this.responses[data.answer],
|
173
|
+
data.actionResult || {}
|
174
|
+
);
|
175
|
+
}
|
176
|
+
|
177
|
+
return data;
|
178
|
+
};
|
179
|
+
}
|
180
|
+
|
181
|
+
/**
|
182
|
+
* Execute a single action
|
183
|
+
*/
|
184
|
+
private async executeAction(actionData: any, context: any): Promise<any> {
|
185
|
+
const { action, parameters } = actionData;
|
186
|
+
const handler = this.manager.actions[action];
|
187
|
+
if (handler) {
|
188
|
+
return handler(context);
|
189
|
+
}
|
190
|
+
return null;
|
191
|
+
}
|
192
|
+
|
193
|
+
/**
|
194
|
+
* Processes natural language input text
|
195
|
+
* @param {string} input - Input text to process
|
196
|
+
* @returns {Promise<any>} Processing result with intent, entities and response
|
197
|
+
*/
|
198
|
+
async process(input: string) {
|
199
|
+
const result = await this.manager.process("en", input);
|
200
|
+
console.log("NLP Engine Result:", result);
|
201
|
+
|
202
|
+
// Si une action est définie, exécuter le handler
|
203
|
+
if (result.intent) {
|
204
|
+
const handler = this.intentHandlers[result.intent.split(".")[1]];
|
205
|
+
if (handler) {
|
206
|
+
const handlerResult = await handler(result);
|
207
|
+
return {
|
208
|
+
...result,
|
209
|
+
...handlerResult,
|
210
|
+
};
|
211
|
+
}
|
212
|
+
}
|
213
|
+
|
214
|
+
return result;
|
215
|
+
}
|
216
|
+
|
217
|
+
/**
|
218
|
+
* Trains the NLP model with current corpus
|
219
|
+
* @returns {Promise<void>}
|
220
|
+
*/
|
221
|
+
public async train(): Promise<void> {
|
222
|
+
await this.manager.train();
|
223
|
+
}
|
224
|
+
|
225
|
+
/**
|
226
|
+
* Exports the trained model
|
227
|
+
* @param {boolean} [minified=true] - Whether to minify the exported model
|
228
|
+
* @returns {string} Exported model as string
|
229
|
+
*/
|
230
|
+
public export(minified = true): string {
|
231
|
+
return this.manager.export(minified);
|
232
|
+
}
|
233
|
+
|
234
|
+
/**
|
235
|
+
* Imports a previously trained model
|
236
|
+
* @param {string} data - Model data to import
|
237
|
+
*/
|
238
|
+
public import(data: string): void {
|
239
|
+
this.manager.import(data);
|
240
|
+
}
|
241
|
+
|
242
|
+
/**
|
243
|
+
* Saves the current model to a file
|
244
|
+
* @param {string} [path='./model.json'] - Path to save the model
|
245
|
+
* @returns {Promise<void>}
|
246
|
+
*/
|
247
|
+
public async saveModel(path = "./model.json"): Promise<void> {
|
248
|
+
this.manager.save();
|
249
|
+
this.manager.save("./model.json");
|
250
|
+
}
|
251
|
+
|
252
|
+
/**
|
253
|
+
* Formats response using template and context
|
254
|
+
*/
|
255
|
+
private formatResponse(template: any, context: any): any {
|
256
|
+
const response = JSON.parse(JSON.stringify(template));
|
257
|
+
|
258
|
+
// Format data fields
|
259
|
+
if (response.data) {
|
260
|
+
Object.keys(response.data).forEach((key) => {
|
261
|
+
if (context[key] !== undefined) {
|
262
|
+
response.data[key] = context[key];
|
263
|
+
}
|
264
|
+
});
|
265
|
+
}
|
266
|
+
|
267
|
+
return response;
|
268
|
+
}
|
269
|
+
|
270
|
+
/**
|
271
|
+
* Gets entity value from NLP result
|
272
|
+
* @param {any} data - NLP processing result
|
273
|
+
* @param {string} entityName - Name of the entity to extract
|
274
|
+
* @returns {string|undefined} Entity value if found
|
275
|
+
*/
|
276
|
+
getEntity(data: any, entityName: string): string | undefined {
|
277
|
+
const entity = data.entities?.find((e: any) => e.entity === entityName);
|
278
|
+
return entity ? entity.utteranceText : undefined;
|
279
|
+
}
|
280
|
+
|
281
|
+
/**
|
282
|
+
* Gets entity option from NLP result
|
283
|
+
* @param {any} data - NLP processing result
|
284
|
+
* @param {string} entityName - Name of the entity to extract
|
285
|
+
* @returns {string|undefined} Entity option if found
|
286
|
+
*/
|
287
|
+
getEntityOption(data: any, entityName: string): string | undefined {
|
288
|
+
const entity = data.entities?.find((e: any) => e.entity === entityName);
|
289
|
+
return entity ? entity.option : undefined;
|
290
|
+
}
|
291
|
+
|
292
|
+
/**
|
293
|
+
* Gets recipient entity from NLP result
|
294
|
+
* @param {any} data - NLP processing result
|
295
|
+
* @returns {string|undefined} Recipient value if found
|
296
|
+
*/
|
297
|
+
getRecipient(data: any): string | undefined {
|
298
|
+
const toEntity = data.entities?.find((e: any) => e.entity === "to");
|
299
|
+
return toEntity ? toEntity.utteranceText : undefined;
|
300
|
+
}
|
301
|
+
|
302
|
+
/**
|
303
|
+
* Gets current responses configuration
|
304
|
+
* @returns {Record<string, any>} Current responses
|
305
|
+
*/
|
306
|
+
public getResponses(): Record<string, any> {
|
307
|
+
return this.responses;
|
308
|
+
}
|
309
|
+
|
310
|
+
/**
|
311
|
+
* Gets current corpus configuration
|
312
|
+
* @returns {any} Current corpus
|
313
|
+
*/
|
314
|
+
public getCorpus(): any {
|
315
|
+
return this.manager.corpora;
|
316
|
+
}
|
317
|
+
|
318
|
+
/**
|
319
|
+
* Gets current entities configuration
|
320
|
+
* @returns {any} Current entities configuration
|
321
|
+
*/
|
322
|
+
public getEntities(): any {
|
323
|
+
return this.manager.nerManager?.rules || {};
|
324
|
+
}
|
325
|
+
}
|
@@ -0,0 +1,45 @@
|
|
1
|
+
import { NLPNodeConfig } from "@/interfaces";
|
2
|
+
import { ZodSchema } from "zod";
|
3
|
+
import { NLPEngine } from "./engine";
|
4
|
+
|
5
|
+
/**
|
6
|
+
* NLPNode class handles natural language processing operations with type-safe schema validation
|
7
|
+
* @template T - Zod schema type for validation
|
8
|
+
*/
|
9
|
+
export class NLPNode<T extends ZodSchema> {
|
10
|
+
private engine!: NLPEngine;
|
11
|
+
|
12
|
+
/**
|
13
|
+
* Creates an instance of NLPNode
|
14
|
+
* @param {NLPNodeConfig<T>} config - Configuration object for the NLP node
|
15
|
+
*/
|
16
|
+
constructor(private config: NLPNodeConfig<T>) {}
|
17
|
+
|
18
|
+
/**
|
19
|
+
* Initializes the NLP engine and sets up intent handlers
|
20
|
+
* @returns {Promise<void>}
|
21
|
+
*/
|
22
|
+
async initialize() {
|
23
|
+
this.engine = await NLPEngine.create(this.config.nlpConfig);
|
24
|
+
console.log("Loaded engine");
|
25
|
+
if (this.config.intentHandlers) {
|
26
|
+
Object.entries(this.config.intentHandlers).forEach(
|
27
|
+
([intent, handler]) => {
|
28
|
+
this.engine.addAction(intent, handler);
|
29
|
+
}
|
30
|
+
);
|
31
|
+
}
|
32
|
+
}
|
33
|
+
|
34
|
+
/**
|
35
|
+
* Processes the input text through the NLP engine
|
36
|
+
* @param {string} input - Text to be processed
|
37
|
+
* @returns {Promise<any>} - Processing result from the engine
|
38
|
+
*/
|
39
|
+
async process(input: string) {
|
40
|
+
console.log("NLP Node processing:", input);
|
41
|
+
const result = await this.engine.process(input);
|
42
|
+
console.log("NLP Node result:", result);
|
43
|
+
return result;
|
44
|
+
}
|
45
|
+
}
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@ai.ntellect/core",
|
3
|
-
"version": "0.
|
3
|
+
"version": "0.8.0",
|
4
4
|
"description": "",
|
5
5
|
"main": "dist/index.js",
|
6
6
|
"scripts": {
|
@@ -17,8 +17,11 @@
|
|
17
17
|
"author": "Lorcann Rauzduel",
|
18
18
|
"license": "ISC",
|
19
19
|
"dependencies": {
|
20
|
+
"@ai-sdk/openai": "^1.1.15",
|
21
|
+
"@nlpjs/basic": "5.0.0-alpha.5",
|
20
22
|
"@types/node-cron": "^3.0.11",
|
21
|
-
"ai": "^
|
23
|
+
"ai": "^4.1.46",
|
24
|
+
"chalk": "^5.4.1",
|
22
25
|
"node-cron": "^3.0.3",
|
23
26
|
"redis": "^4.7.0",
|
24
27
|
"rxjs": "^7.8.1",
|
package/test/graph/index.test.ts
CHANGED
@@ -6,7 +6,7 @@ import { z } from "zod";
|
|
6
6
|
import { GraphController } from "../../graph/controller";
|
7
7
|
import { GraphFlow } from "../../graph/index";
|
8
8
|
import { NodeParams } from "../../graph/node";
|
9
|
-
import {
|
9
|
+
import { GraphConfig, GraphContext, GraphNodeConfig } from "../../types";
|
10
10
|
|
11
11
|
use(chaiAsPromised);
|
12
12
|
|
@@ -595,14 +595,16 @@ describe("GraphFlow", function () {
|
|
595
595
|
* Tests single event waiting functionality
|
596
596
|
*/
|
597
597
|
it("should wait for a single event before continuing", async function () {
|
598
|
-
this.timeout(5000);
|
599
|
-
|
600
598
|
const waitingNode: GraphNodeConfig<TestSchema> = {
|
601
599
|
name: "waitingNode",
|
602
600
|
execute: async (context: GraphContext<typeof TestSchema>) => {
|
603
601
|
context.value = 1;
|
604
602
|
},
|
605
|
-
|
603
|
+
when: {
|
604
|
+
events: ["someEvent"],
|
605
|
+
timeout: 1000,
|
606
|
+
strategy: { type: "single" },
|
607
|
+
},
|
606
608
|
next: ["finalNode"],
|
607
609
|
};
|
608
610
|
|
package/test/graph/node.test.ts
CHANGED
@@ -512,10 +512,10 @@ describe("GraphNode", () => {
|
|
512
512
|
const nodes = new Map();
|
513
513
|
nodes.set("waitForEventsNode", {
|
514
514
|
name: "waitForEventsNode",
|
515
|
-
|
515
|
+
when: {
|
516
516
|
events: ["event1", "event2"],
|
517
517
|
timeout: 1000,
|
518
|
-
strategy: "all",
|
518
|
+
strategy: { type: "all" },
|
519
519
|
},
|
520
520
|
execute: async (context: TestContext) => {
|
521
521
|
context.message = "Events received";
|
@@ -554,10 +554,10 @@ describe("GraphNode", () => {
|
|
554
554
|
const nodes = new Map();
|
555
555
|
nodes.set("timeoutNode", {
|
556
556
|
name: "timeoutNode",
|
557
|
-
|
557
|
+
when: {
|
558
558
|
events: ["event1", "event2"],
|
559
559
|
timeout: 100,
|
560
|
-
strategy: "all",
|
560
|
+
strategy: { type: "all" },
|
561
561
|
},
|
562
562
|
execute: async (context: TestContext) => {
|
563
563
|
context.message = "Should not execute";
|
@@ -571,7 +571,6 @@ describe("GraphNode", () => {
|
|
571
571
|
eventSubject,
|
572
572
|
stateSubject
|
573
573
|
);
|
574
|
-
|
575
574
|
await expect(
|
576
575
|
node.executeNode("timeoutNode", { counter: 0, message: "Hello" }, null)
|
577
576
|
).to.be.rejectedWith("Timeout waiting for events");
|
@@ -581,10 +580,10 @@ describe("GraphNode", () => {
|
|
581
580
|
const nodes = new Map();
|
582
581
|
nodes.set("partialEventsNode", {
|
583
582
|
name: "partialEventsNode",
|
584
|
-
|
583
|
+
when: {
|
585
584
|
events: ["event1", "event2"],
|
586
585
|
timeout: 1000,
|
587
|
-
strategy: "all",
|
586
|
+
strategy: { type: "all" },
|
588
587
|
},
|
589
588
|
execute: async (context: TestContext) => {
|
590
589
|
context.message = "All events received";
|
@@ -598,14 +597,12 @@ describe("GraphNode", () => {
|
|
598
597
|
eventSubject,
|
599
598
|
stateSubject
|
600
599
|
);
|
601
|
-
|
602
600
|
const execution = node.executeNode(
|
603
601
|
"partialEventsNode",
|
604
602
|
{ counter: 0, message: "Hello" },
|
605
603
|
null
|
606
604
|
);
|
607
605
|
|
608
|
-
// N'émettre qu'un seul événement
|
609
606
|
setTimeout(() => {
|
610
607
|
eventEmitter.emit("event1", { data: "test1" });
|
611
608
|
}, 100);
|
@@ -617,13 +614,20 @@ describe("GraphNode", () => {
|
|
617
614
|
const nodes = new Map();
|
618
615
|
nodes.set("correlatedEventsNode", {
|
619
616
|
name: "correlatedEventsNode",
|
620
|
-
|
617
|
+
when: {
|
621
618
|
events: ["payment", "stock"],
|
622
619
|
timeout: 1000,
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
620
|
+
strategy: {
|
621
|
+
type: "correlate",
|
622
|
+
correlation: (events: Array<{ type: string; payload?: any }>) => {
|
623
|
+
const paymentEvent = events.find(
|
624
|
+
(e: { type: string }) => e.type === "payment"
|
625
|
+
);
|
626
|
+
const stockEvent = events.find(
|
627
|
+
(e: { type: string }) => e.type === "stock"
|
628
|
+
);
|
629
|
+
return paymentEvent?.payload?.id === stockEvent?.payload?.id;
|
630
|
+
},
|
627
631
|
},
|
628
632
|
},
|
629
633
|
execute: (context: TestContext) => {
|
package/types/agent.ts
ADDED
@@ -0,0 +1,174 @@
|
|
1
|
+
import { GraphFlow } from "@/graph";
|
2
|
+
import { z } from "zod";
|
3
|
+
|
4
|
+
/**
|
5
|
+
* Represents an action that has been executed by the agent
|
6
|
+
* @interface ExecutedAction
|
7
|
+
* @property {string} name - The name of the executed action
|
8
|
+
* @property {boolean} isExecuted - Whether the action was successfully executed
|
9
|
+
* @property {string | null} [error] - Optional error message if the action failed
|
10
|
+
* @property {any} result - The result of the action execution
|
11
|
+
* @property {string} timestamp - When the action was executed
|
12
|
+
*/
|
13
|
+
export type ExecutedAction = {
|
14
|
+
name: string;
|
15
|
+
isExecuted: boolean;
|
16
|
+
error?: string | null;
|
17
|
+
result: any;
|
18
|
+
timestamp: string;
|
19
|
+
};
|
20
|
+
|
21
|
+
/**
|
22
|
+
* Represents the context in which an agent operates
|
23
|
+
* @interface AgentContext
|
24
|
+
* @property {Object} input - The input provided to the agent
|
25
|
+
* @property {string} input.raw - The raw input text
|
26
|
+
* @property {number[]} [input.embedding] - Optional vector embedding of the input
|
27
|
+
* @property {ActionSchema[]} actions - List of actions available to the agent
|
28
|
+
* @property {string} response - The agent's response
|
29
|
+
* @property {string} [knowledge] - Optional knowledge base or context
|
30
|
+
* @property {ExecutedAction[]} executedActions - History of executed actions
|
31
|
+
*/
|
32
|
+
export type AgentContext = {
|
33
|
+
input: {
|
34
|
+
raw: string;
|
35
|
+
embedding?: number[];
|
36
|
+
};
|
37
|
+
actions: ActionSchema[];
|
38
|
+
response: string;
|
39
|
+
knowledge?: string;
|
40
|
+
executedActions: ExecutedAction[];
|
41
|
+
};
|
42
|
+
|
43
|
+
export const AgentContextSchema = z.object({
|
44
|
+
input: z.object({
|
45
|
+
raw: z.string(),
|
46
|
+
embedding: z.array(z.number()).optional(),
|
47
|
+
}),
|
48
|
+
actions: z.array(
|
49
|
+
z.object({
|
50
|
+
name: z.string(),
|
51
|
+
parameters: z.array(
|
52
|
+
z.object({
|
53
|
+
name: z.string(),
|
54
|
+
value: z.any(),
|
55
|
+
})
|
56
|
+
),
|
57
|
+
isExecuted: z.boolean().optional(),
|
58
|
+
result: z.any().optional(),
|
59
|
+
})
|
60
|
+
),
|
61
|
+
knowledge: z.string().optional(),
|
62
|
+
response: z.string(),
|
63
|
+
executedActions: z
|
64
|
+
.array(
|
65
|
+
z.object({
|
66
|
+
name: z.string(),
|
67
|
+
result: z.any(),
|
68
|
+
timestamp: z.string(),
|
69
|
+
})
|
70
|
+
)
|
71
|
+
.optional(),
|
72
|
+
});
|
73
|
+
|
74
|
+
/**
|
75
|
+
* Represents a section of the prompt with a title and content
|
76
|
+
* @interface PromptSection
|
77
|
+
* @property {string} title - The title of the prompt section
|
78
|
+
* @property {string | ((context: AgentContext) => string | Promise<string>)} content - The content or a function to generate content
|
79
|
+
*/
|
80
|
+
export type PromptSection = {
|
81
|
+
title: string;
|
82
|
+
content: string | ((context: AgentContext) => string | Promise<string>);
|
83
|
+
};
|
84
|
+
|
85
|
+
/**
|
86
|
+
* Supported LLM providers
|
87
|
+
*/
|
88
|
+
export type LLMProvider = "openai" | "anthropic" | "custom";
|
89
|
+
|
90
|
+
/**
|
91
|
+
* Supported LLM models
|
92
|
+
*/
|
93
|
+
export type LLMModel = "gpt-4" | "gpt-3.5-turbo" | "claude-2" | string;
|
94
|
+
|
95
|
+
export type ExecutorConfig = {
|
96
|
+
llmConfig: LLMConfig;
|
97
|
+
verbose?: boolean;
|
98
|
+
};
|
99
|
+
|
100
|
+
/**
|
101
|
+
* Configuration for the Agent
|
102
|
+
* @type AssistantConfig
|
103
|
+
* @extends {Omit<ExecutorConfig, "verbose">}
|
104
|
+
* @property {string} role - The function/job of the assistant (e.g., "Email Assistant")
|
105
|
+
* @property {string} goal - The specific objective the assistant tries to achieve
|
106
|
+
* @property {string} backstory - The personality and behavioral traits of the assistant
|
107
|
+
* @property {any[]} [tools] - Optional tools the assistant can use
|
108
|
+
* @property {any} [memory] - Optional memory system
|
109
|
+
* @property {boolean} [verbose] - Whether to log detailed information
|
110
|
+
*/
|
111
|
+
export type AgentConfig = {
|
112
|
+
role: string;
|
113
|
+
goal: string;
|
114
|
+
backstory: string;
|
115
|
+
tools: GraphFlow<any>[];
|
116
|
+
memory?: any;
|
117
|
+
verbose?: boolean;
|
118
|
+
llmConfig: ExecutorConfig["llmConfig"];
|
119
|
+
};
|
120
|
+
|
121
|
+
/**
|
122
|
+
* Represents the schema of an action that can be performed by the agent
|
123
|
+
* @interface ActionSchema
|
124
|
+
* @property {string} name - The name of the action
|
125
|
+
* @property {Array<{name: string, value: any}>} parameters - The parameters required for the action
|
126
|
+
*/
|
127
|
+
export type ActionSchema = {
|
128
|
+
name: string;
|
129
|
+
parameters: Array<{ name: string; value: any }>;
|
130
|
+
};
|
131
|
+
|
132
|
+
/**
|
133
|
+
* Represents the output of the agent's decision-making process
|
134
|
+
* @interface DecisionOutput
|
135
|
+
* @property {ActionSchema[]} actions - The actions to be executed
|
136
|
+
* @property {string} response - The agent's response message
|
137
|
+
*/
|
138
|
+
export type DecisionOutput = {
|
139
|
+
actions: ActionSchema[];
|
140
|
+
response: string;
|
141
|
+
};
|
142
|
+
|
143
|
+
/**
|
144
|
+
* Configuration for the Language Model
|
145
|
+
* @interface LLMConfig
|
146
|
+
* @property {LLMProvider} provider - The LLM provider to use
|
147
|
+
* @property {string} apiKey - API key for the provider
|
148
|
+
* @property {LLMModel} model - The specific model to use
|
149
|
+
* @property {number} [temperature] - Optional temperature parameter for response randomness
|
150
|
+
* @property {number} [maxTokens] - Optional maximum tokens for the response
|
151
|
+
* @property {Function} [customCall] - Optional custom implementation for API calls
|
152
|
+
*/
|
153
|
+
export type LLMConfig = {
|
154
|
+
provider: LLMProvider;
|
155
|
+
apiKey: string;
|
156
|
+
model: LLMModel;
|
157
|
+
temperature?: number;
|
158
|
+
maxTokens?: number;
|
159
|
+
customCall?: (
|
160
|
+
prompt: string | PromptInput,
|
161
|
+
schema: z.ZodType<any>
|
162
|
+
) => Promise<any>;
|
163
|
+
};
|
164
|
+
|
165
|
+
/**
|
166
|
+
* Structure for prompt input to the LLM
|
167
|
+
* @interface PromptInput
|
168
|
+
* @property {string} system - The system message/context
|
169
|
+
* @property {string} user - The user's input message
|
170
|
+
*/
|
171
|
+
export type PromptInput = {
|
172
|
+
system: string;
|
173
|
+
user: string;
|
174
|
+
};
|