@ai.ntellect/core 0.6.21 → 0.7.1

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.
Files changed (41) hide show
  1. package/.mocharc.json +2 -1
  2. package/README.md +61 -85
  3. package/graph/controller.ts +1 -1
  4. package/graph/event-manager.ts +288 -0
  5. package/graph/index.ts +153 -367
  6. package/graph/logger.ts +70 -0
  7. package/graph/node.ts +398 -0
  8. package/graph/observer.ts +361 -0
  9. package/interfaces/index.ts +102 -1
  10. package/modules/agenda/index.ts +3 -16
  11. package/modules/memory/adapters/in-memory/index.ts +6 -2
  12. package/modules/memory/adapters/meilisearch/index.ts +6 -2
  13. package/modules/memory/adapters/redis/index.ts +2 -2
  14. package/modules/memory/index.ts +1 -1
  15. package/package.json +10 -5
  16. package/test/graph/index.test.ts +244 -113
  17. package/test/graph/observer.test.ts +398 -0
  18. package/test/modules/agenda/node-cron.test.ts +37 -16
  19. package/test/modules/memory/adapters/in-memory.test.ts +2 -2
  20. package/test/modules/memory/adapters/meilisearch.test.ts +28 -24
  21. package/test/modules/memory/base.test.ts +3 -3
  22. package/tsconfig.json +4 -2
  23. package/types/index.ts +24 -3
  24. package/dist/graph/controller.js +0 -72
  25. package/dist/graph/index.js +0 -501
  26. package/dist/index.js +0 -41
  27. package/dist/interfaces/index.js +0 -17
  28. package/dist/modules/agenda/adapters/node-cron/index.js +0 -29
  29. package/dist/modules/agenda/index.js +0 -140
  30. package/dist/modules/embedding/adapters/ai/index.js +0 -57
  31. package/dist/modules/embedding/index.js +0 -59
  32. package/dist/modules/memory/adapters/in-memory/index.js +0 -210
  33. package/dist/modules/memory/adapters/meilisearch/index.js +0 -320
  34. package/dist/modules/memory/adapters/redis/index.js +0 -158
  35. package/dist/modules/memory/index.js +0 -103
  36. package/dist/types/index.js +0 -2
  37. package/dist/utils/generate-action-schema.js +0 -43
  38. package/dist/utils/header-builder.js +0 -34
  39. package/test/modules/embedding/ai.test.ts +0 -78
  40. package/test/modules/memory/adapters/redis.test.ts +0 -169
  41. package/test/services/agenda.test.ts +0 -279
@@ -0,0 +1,361 @@
1
+ import {
2
+ BehaviorSubject,
3
+ Observable,
4
+ Subject,
5
+ combineLatest,
6
+ firstValueFrom,
7
+ } from "rxjs";
8
+ import {
9
+ distinctUntilChanged,
10
+ filter,
11
+ map,
12
+ share,
13
+ startWith,
14
+ take,
15
+ takeUntil,
16
+ timeout,
17
+ } from "rxjs/operators";
18
+ import { ZodSchema } from "zod";
19
+ import { GraphObservable } from "../interfaces";
20
+ import { GraphContext, GraphEvent } from "../types";
21
+ import { GraphFlow } from "./index";
22
+
23
+ /**
24
+ * GraphObserver class provides reactive observation capabilities for a GraphFlow instance
25
+ * It allows monitoring state changes, node updates, and specific events in the graph
26
+ * @template T - The Zod schema type that defines the structure of the graph data
27
+ */
28
+ export class GraphObserver<T extends ZodSchema> {
29
+ constructor(
30
+ private graph: GraphFlow<T>,
31
+ private eventSubject: Subject<GraphEvent<T>>,
32
+ private stateSubject: BehaviorSubject<GraphContext<T>>,
33
+ private destroySubject: Subject<void>
34
+ ) {}
35
+
36
+ /**
37
+ * Observes the entire graph state changes
38
+ * @param options Configuration options for the observation
39
+ * @param options.debounce Debounce time in milliseconds
40
+ * @param options.delay Delay between emissions in milliseconds
41
+ * @param options.stream If true, streams the specified properties letter by letter
42
+ * @param options.properties List of properties to stream
43
+ * @param options.onStreamLetter Callback for each letter emitted during streaming
44
+ * @param options.onStreamComplete Callback when streaming is complete
45
+ * @returns An Observable that emits the complete graph context whenever it changes
46
+ */
47
+ state(
48
+ options: {
49
+ debounce?: number;
50
+ delay?: number;
51
+ stream?: boolean;
52
+ properties?: (keyof GraphContext<T>)[];
53
+ onStreamLetter?: (data: { letter: string; property: string }) => void;
54
+ onStreamComplete?: () => void;
55
+ } = {}
56
+ ): GraphObservable<T> {
57
+ const baseObservable = new Observable<any>((subscriber) => {
58
+ const subscription = this.eventSubject
59
+ .pipe(
60
+ filter(
61
+ (event) =>
62
+ event.type === "nodeStateChanged" ||
63
+ event.type === "nodeStarted" ||
64
+ event.type === "nodeCompleted"
65
+ ),
66
+ map((event) => event.payload.context),
67
+ startWith(this.stateSubject.getValue()),
68
+ distinctUntilChanged(
69
+ (prev, curr) => JSON.stringify(prev) === JSON.stringify(curr)
70
+ )
71
+ )
72
+ .subscribe(subscriber);
73
+
74
+ // Stream the specified properties if specified
75
+ if (options.stream && options.properties) {
76
+ const context = this.stateSubject.getValue();
77
+ options.properties.forEach((property) => {
78
+ const message = context[property];
79
+ if (message) {
80
+ this.streamMessage(
81
+ message.toString(),
82
+ 500,
83
+ property as string
84
+ ).subscribe({
85
+ next: (data) => options.onStreamLetter?.(data),
86
+ complete: () => options.onStreamComplete?.(),
87
+ });
88
+ }
89
+ });
90
+ }
91
+
92
+ return () => subscription.unsubscribe();
93
+ });
94
+
95
+ // Extend the observable with our custom methods
96
+ return Object.assign(baseObservable, {
97
+ state: () => this.stateSubject.asObservable(),
98
+ node: (nodeName: string) =>
99
+ this.stateSubject.pipe(map((state) => ({ ...state, nodeName }))),
100
+ nodes: (nodeNames: string[]) =>
101
+ this.eventSubject.pipe(
102
+ filter(
103
+ (event) =>
104
+ event.type === "nodeStateChanged" &&
105
+ nodeNames.includes(event.payload?.name ?? "")
106
+ ),
107
+ map((event) => event.payload.context),
108
+ distinctUntilChanged(
109
+ (prev, curr) => JSON.stringify(prev) === JSON.stringify(curr)
110
+ ),
111
+ takeUntil(this.destroySubject),
112
+ share()
113
+ ),
114
+ property: (props: string | string[]) =>
115
+ this.stateSubject.pipe(
116
+ map((state) => {
117
+ const properties = Array.isArray(props) ? props : [props];
118
+ return properties.reduce(
119
+ (acc, prop) => ({
120
+ ...acc,
121
+ [prop]: state[prop],
122
+ }),
123
+ {}
124
+ );
125
+ })
126
+ ),
127
+ event: (eventName: string) =>
128
+ this.eventSubject.pipe(filter((event) => event.type === eventName)),
129
+ until: (
130
+ observable: Observable<any>,
131
+ predicate: (state: any) => boolean
132
+ ) => firstValueFrom(observable.pipe(filter(predicate), take(1))),
133
+ }) as GraphObservable<T>;
134
+ }
135
+
136
+ /**
137
+ * Observes state changes for a specific node
138
+ * @param name - The name of the node to observe
139
+ * @returns An Observable that emits the graph context when the specified node changes
140
+ */
141
+ node(name: string): Observable<GraphContext<T>> {
142
+ return this.eventSubject.pipe(
143
+ filter(
144
+ (event) =>
145
+ event.type === "nodeStateChanged" && event.payload?.name === name
146
+ ),
147
+ map((event) => event.payload.context),
148
+ distinctUntilChanged(
149
+ (prev, curr) => JSON.stringify(prev) === JSON.stringify(curr)
150
+ ),
151
+ takeUntil(this.destroySubject),
152
+ share()
153
+ );
154
+ }
155
+
156
+ /**
157
+ * Observes state changes for multiple nodes
158
+ * @param names - Array of node names to observe
159
+ * @returns An Observable that emits the graph context when any of the specified nodes change
160
+ */
161
+ nodes(names: string[]): Observable<GraphContext<T>> {
162
+ return this.eventSubject.pipe(
163
+ filter(
164
+ (event) =>
165
+ names.includes(event.payload?.name ?? "") &&
166
+ event.type === "nodeStateChanged"
167
+ ),
168
+ map(() => this.graph.getContext()),
169
+ distinctUntilChanged(
170
+ (prev, curr) => JSON.stringify(prev) === JSON.stringify(curr)
171
+ ),
172
+ takeUntil(this.destroySubject),
173
+ share()
174
+ );
175
+ }
176
+
177
+ /**
178
+ * Observes specific properties of the graph context
179
+ * @param keys - Single or multiple property keys to observe
180
+ * @returns An Observable that emits an object containing only the specified properties
181
+ * @template K - The key of the property to observe from GraphContext<T>
182
+ */
183
+ property<K extends keyof GraphContext<T>>(
184
+ keys: K | K[]
185
+ ): Observable<{ [P in K]: GraphContext<T>[P] } & { name: string }> {
186
+ const properties = Array.isArray(keys) ? keys : [keys];
187
+
188
+ return this.eventSubject.pipe(
189
+ filter(
190
+ (event) =>
191
+ event.type === "nodeStateChanged" &&
192
+ properties.some((key) => event.payload?.property === key)
193
+ ),
194
+ map((event) => ({
195
+ ...properties.reduce(
196
+ (obj, key) => ({
197
+ ...obj,
198
+ [key]: event.payload.context[key],
199
+ }),
200
+ {} as { [P in K]: GraphContext<T>[P] }
201
+ ),
202
+ name: event.payload.name as string,
203
+ })),
204
+ startWith({
205
+ ...properties.reduce(
206
+ (obj, key) => ({
207
+ ...obj,
208
+ [key]: this.stateSubject.value[key],
209
+ }),
210
+ {}
211
+ ),
212
+ name: "initial",
213
+ } as { [P in K]: GraphContext<T>[P] } & { name: string }),
214
+ distinctUntilChanged(
215
+ (prev, curr) => JSON.stringify(prev) === JSON.stringify(curr)
216
+ ),
217
+ share()
218
+ );
219
+ }
220
+
221
+ /**
222
+ * Observes specific events in the graph
223
+ * @param type - The type of event to observe
224
+ * @returns An Observable that emits events of the specified type
225
+ */
226
+ event(type: string): Observable<GraphEvent<T>> {
227
+ return this.eventSubject.pipe(
228
+ filter((event) => event.type === type),
229
+ map((event) => event),
230
+ takeUntil(this.destroySubject),
231
+ share()
232
+ );
233
+ }
234
+
235
+ /**
236
+ * Waits for a specific condition to be met on an observable
237
+ * @param observable - The Observable to watch
238
+ * @param predicate - A function that returns true when the desired condition is met
239
+ * @returns A Promise that resolves with the value when the predicate returns true
240
+ * @template R - The type of value emitted by the observable
241
+ */
242
+ until<R>(
243
+ observable: Observable<R>,
244
+ predicate: (value: R) => boolean
245
+ ): Promise<R> {
246
+ return new Promise((resolve) => {
247
+ const subscription = observable.subscribe({
248
+ next: (value) => {
249
+ if (predicate(value)) {
250
+ subscription.unsubscribe();
251
+ resolve(value);
252
+ }
253
+ },
254
+ });
255
+ });
256
+ }
257
+
258
+ /**
259
+ * Waits for correlated events to occur and validates them using a correlation function
260
+ * @param eventTypes - Array of event types to wait for
261
+ * @param timeoutMs - Timeout duration in milliseconds
262
+ * @param correlationFn - Function to validate the correlation between events
263
+ * @returns Promise that resolves when all correlated events are received
264
+ */
265
+ waitForCorrelatedEvents(
266
+ eventTypes: string[],
267
+ timeoutMs: number,
268
+ correlationFn: (events: GraphEvent<T>[]) => boolean
269
+ ): Promise<GraphEvent<T>[]> {
270
+ return new Promise((resolve, reject) => {
271
+ const eventObservables = eventTypes.map((eventType) =>
272
+ this.eventSubject.pipe(
273
+ filter((event): event is GraphEvent<T> => {
274
+ return event.type === eventType && "timestamp" in event;
275
+ }),
276
+ take(1)
277
+ )
278
+ );
279
+
280
+ combineLatest(eventObservables)
281
+ .pipe(timeout(timeoutMs), take(1))
282
+ .subscribe({
283
+ next: (events) => {
284
+ if (correlationFn(events)) {
285
+ resolve(events);
286
+ } else {
287
+ reject(new Error(`Correlation validation failed`));
288
+ }
289
+ },
290
+ error: (error) => reject(error),
291
+ });
292
+ });
293
+ }
294
+
295
+ /**
296
+ * Observes the current state of the graph
297
+ * @returns Observable that emits the current graph context
298
+ */
299
+ observeState(): Observable<GraphContext<T>> {
300
+ return this.stateSubject.asObservable().pipe(
301
+ takeUntil(this.destroySubject),
302
+ distinctUntilChanged(
303
+ (prev, curr) => JSON.stringify(prev) === JSON.stringify(curr)
304
+ )
305
+ );
306
+ }
307
+
308
+ /**
309
+ * Observes specific event types in the graph
310
+ * @param eventType - The type of event to observe
311
+ * @returns Observable that emits events of the specified type
312
+ */
313
+ observeEvents(eventType: string): Observable<GraphEvent<T>> {
314
+ return this.eventSubject.asObservable().pipe(
315
+ takeUntil(this.destroySubject),
316
+ filter((event) => event.type === eventType)
317
+ );
318
+ }
319
+
320
+ /**
321
+ * Observes state changes for a specific node
322
+ * @param nodeName - The name of the node to observe
323
+ * @returns Observable that emits the graph context when the specified node changes
324
+ */
325
+ observeNodeState(nodeName: string): Observable<GraphContext<T>> {
326
+ return this.eventSubject.asObservable().pipe(
327
+ takeUntil(this.destroySubject),
328
+ filter(
329
+ (event) =>
330
+ event.type === "nodeStateChanged" && event.payload?.name === nodeName
331
+ ),
332
+ map(() => this.stateSubject.value)
333
+ );
334
+ }
335
+
336
+ /**
337
+ * Streams a message letter by letter with a specified delay
338
+ * @param message - The message to stream
339
+ * @param delayMs - The delay in milliseconds between each letter
340
+ * @param property - The property name being streamed
341
+ * @returns An Observable that emits each letter of the message along with its property
342
+ */
343
+ streamMessage(
344
+ message: string,
345
+ delayMs: number,
346
+ property: string
347
+ ): Observable<{ letter: string; property: string }> {
348
+ return new Observable<{ letter: string; property: string }>(
349
+ (subscriber) => {
350
+ for (let i = 0; i < message.length; i++) {
351
+ setTimeout(() => {
352
+ subscriber.next({ letter: message[i], property });
353
+ if (i === message.length - 1) {
354
+ subscriber.complete();
355
+ }
356
+ }, i * delayMs);
357
+ }
358
+ }
359
+ );
360
+ }
361
+ }
@@ -1,4 +1,12 @@
1
- import { BaseMemoryType, CreateMemoryInput, ScheduledRequest } from "../types";
1
+ import { Observable } from "rxjs";
2
+ import { ZodSchema } from "zod";
3
+ import {
4
+ BaseMemoryType,
5
+ CreateMemoryInput,
6
+ GraphContext,
7
+ GraphEvent,
8
+ ScheduledRequest,
9
+ } from "../types";
2
10
 
3
11
  /* ======================== EMBEDDING SERVICE ======================== */
4
12
 
@@ -151,6 +159,15 @@ export interface IMemoryService {
151
159
  * @returns {Promise<void>}
152
160
  */
153
161
  clearAllMemories(): Promise<void>;
162
+
163
+ saveJob(id: string, job: any): Promise<void>;
164
+ saveRequest(id: string, request: any): Promise<void>;
165
+ getJob(id: string): Promise<any>;
166
+ getRequest(id: string): Promise<any>;
167
+ deleteJob(id: string): Promise<void>;
168
+ deleteRequest(id: string): Promise<void>;
169
+ getAllRequests(): Promise<any[]>;
170
+ clear(): Promise<void>;
154
171
  }
155
172
 
156
173
  /**
@@ -297,6 +314,38 @@ export abstract class BaseMemory implements IMemoryService {
297
314
  abstract getAllMemories(roomId: string): Promise<BaseMemoryType[]>;
298
315
  abstract clearMemoryById(id: string, roomId: string): Promise<void>;
299
316
  abstract clearAllMemories(): Promise<void>;
317
+
318
+ async saveJob(id: string, job: any): Promise<void> {
319
+ await this.adapter.saveJob?.(id, job);
320
+ }
321
+
322
+ async saveRequest(id: string, request: any): Promise<void> {
323
+ await this.adapter.saveRequest?.(id, request);
324
+ }
325
+
326
+ async getJob(id: string): Promise<any> {
327
+ return this.adapter.getJob?.(id);
328
+ }
329
+
330
+ async getRequest(id: string): Promise<any> {
331
+ return this.adapter.getRequest?.(id);
332
+ }
333
+
334
+ async deleteJob(id: string): Promise<void> {
335
+ await this.adapter.deleteJob?.(id);
336
+ }
337
+
338
+ async deleteRequest(id: string): Promise<void> {
339
+ await this.adapter.deleteRequest?.(id);
340
+ }
341
+
342
+ async getAllRequests(): Promise<any[]> {
343
+ return this.adapter.getAllRequests?.() || [];
344
+ }
345
+
346
+ async clear(): Promise<void> {
347
+ await this.adapter.clear?.();
348
+ }
300
349
  }
301
350
 
302
351
  /**
@@ -338,6 +387,13 @@ export interface IEventEmitter {
338
387
  * @param {Function} listener - Event handler
339
388
  */
340
389
  once(event: string, listener: (...args: any[]) => void): void;
390
+
391
+ /**
392
+ * Removes a specific listener for an event
393
+ * @param {string} event - Event name
394
+ * @param {Function} listener - Event handler
395
+ */
396
+ removeListener(event: string, listener: (...args: any[]) => void): void;
341
397
  }
342
398
 
343
399
  /**
@@ -442,3 +498,48 @@ export interface IJobStorage {
442
498
  getAllRequests(): Promise<ScheduledRequest[]>;
443
499
  clear(): Promise<void>;
444
500
  }
501
+
502
+ /**
503
+ * Interface defining the extended functionality of a graph observable
504
+ * @template T - The Zod schema type that defines the structure of the graph data
505
+ */
506
+ export interface GraphObservable<T extends ZodSchema> extends Observable<any> {
507
+ /**
508
+ * Observes the entire graph state
509
+ */
510
+ state(): Observable<GraphContext<T>>;
511
+
512
+ /**
513
+ * Observes a specific node's state
514
+ * @param nodeName - The name of the node to observe
515
+ */
516
+ node(nodeName: string): Observable<any>;
517
+
518
+ /**
519
+ * Observes multiple nodes' states
520
+ * @param nodeNames - Array of node names to observe
521
+ */
522
+ nodes(nodeNames: string[]): Observable<any>;
523
+
524
+ /**
525
+ * Observes specific properties of the graph context
526
+ * @param prop - Property or array of properties to observe
527
+ */
528
+ property(prop: string | string[]): Observable<any>;
529
+
530
+ /**
531
+ * Observes specific events in the graph
532
+ * @param eventName - The name of the event to observe
533
+ */
534
+ event(eventName: string): Observable<GraphEvent<T>>;
535
+
536
+ /**
537
+ * Waits for a specific condition to be met
538
+ * @param observable - The observable to watch
539
+ * @param predicate - Function that determines when the condition is met
540
+ */
541
+ until(
542
+ observable: Observable<any>,
543
+ predicate: (state: any) => boolean
544
+ ): Promise<any>;
545
+ }
@@ -1,4 +1,4 @@
1
- import { ICronService, IMemoryAdapter } from "../../interfaces";
1
+ import { ICronService, IMemoryService } from "../../interfaces";
2
2
  import { ScheduledRequest } from "../../types";
3
3
 
4
4
  /**
@@ -11,24 +11,11 @@ export class Agenda {
11
11
  /**
12
12
  * Creates an instance of Agenda
13
13
  * @param {ICronService} cronService - The cron service implementation
14
- * @param {IMemoryAdapter} storage - The storage service for jobs and requests
14
+ * @param {IMemoryService} storage - The storage service for jobs and requests
15
15
  */
16
16
  constructor(
17
17
  private readonly cronService: ICronService,
18
- private readonly storage: IMemoryAdapter &
19
- Required<
20
- Pick<
21
- IMemoryAdapter,
22
- | "saveJob"
23
- | "saveRequest"
24
- | "getJob"
25
- | "getRequest"
26
- | "deleteJob"
27
- | "deleteRequest"
28
- | "getAllRequests"
29
- | "clear"
30
- >
31
- >
18
+ private readonly storage: IMemoryService
32
19
  ) {}
33
20
 
34
21
  /**
@@ -1,5 +1,9 @@
1
- import { ICronJob, IMemoryAdapter } from "interfaces";
2
- import { BaseMemoryType, CreateMemoryInput, ScheduledRequest } from "types";
1
+ import { ICronJob, IMemoryAdapter } from "../../../../interfaces";
2
+ import {
3
+ BaseMemoryType,
4
+ CreateMemoryInput,
5
+ ScheduledRequest,
6
+ } from "../../../../types";
3
7
 
4
8
  /**
5
9
  * @module InMemoryAdapter
@@ -1,5 +1,9 @@
1
- import { IMemoryAdapter } from "interfaces";
2
- import { BaseMemoryType, CreateMemoryInput, MeilisearchConfig } from "types";
1
+ import { IMemoryAdapter } from "../../../../interfaces";
2
+ import {
3
+ BaseMemoryType,
4
+ CreateMemoryInput,
5
+ MeilisearchConfig,
6
+ } from "../../../../types";
3
7
 
4
8
  /**
5
9
  * @module MeilisearchAdapter
@@ -1,6 +1,6 @@
1
- import { IMemoryAdapter } from "interfaces";
2
1
  import { createClient } from "redis";
3
- import { BaseMemoryType, CreateMemoryInput } from "types";
2
+ import { IMemoryAdapter } from "../../../../interfaces";
3
+ import { BaseMemoryType, CreateMemoryInput } from "../../../../types";
4
4
 
5
5
  /**
6
6
  * @module RedisAdapter
@@ -1,5 +1,5 @@
1
- import { BaseMemoryType, CreateMemoryInput } from "types";
2
1
  import { BaseMemory, IMemoryAdapter } from "../../interfaces";
2
+ import { BaseMemoryType, CreateMemoryInput } from "../../types";
3
3
 
4
4
  /**
5
5
  * @module Memory
package/package.json CHANGED
@@ -1,13 +1,15 @@
1
1
  {
2
2
  "name": "@ai.ntellect/core",
3
- "version": "0.6.21",
3
+ "version": "0.7.1",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
7
7
  "build": "rm -rf dist && tsc",
8
- "test": "mocha --require ts-node/register",
8
+ "test": "mocha -r ./node_modules/ts-node/register",
9
+ "test:all": "mocha -r ./node_modules/ts-node/register 'test/**/*.test.ts'",
9
10
  "test:coverage": "nyc --reporter=text --reporter=html pnpm test",
10
- "test:watch": "mocha --require ts-node/register 'test/**/*.test.ts' --watch"
11
+ "test:watch": "mocha --require ./node_modules/ts-node/register 'test/**/*.test.ts' --watch --watch-files ./**/*.ts,test/**/*.ts",
12
+ "test:watch:graph": "mocha --require ./node_modules/ts-node/register 'test/graph/**/*.test.ts' --watch --watch-files ./graph/**/*.ts test/**/*.ts"
11
13
  },
12
14
  "keywords": [],
13
15
  "author": "Lorcann Rauzduel",
@@ -17,18 +19,20 @@
17
19
  "ai": "^3.0.0",
18
20
  "node-cron": "^3.0.3",
19
21
  "redis": "^4.7.0",
22
+ "rxjs": "^7.8.1",
20
23
  "zod": "^3.24.1"
21
24
  },
22
25
  "devDependencies": {
23
26
  "@types/chai": "^4.3.20",
24
27
  "@types/mocha": "^10.0.10",
28
+ "@types/node": "^20",
25
29
  "@types/sinon": "^17.0.3",
26
30
  "chai": "^4.5.0",
27
31
  "mocha": "^10.0.0",
28
32
  "nyc": "^17.1.0",
29
33
  "redis": "^4.6.13",
30
34
  "sinon": "^19.0.2",
31
- "ts-node": "^10.9.0",
35
+ "ts-node": "10.9.1",
32
36
  "typescript": "^5.7.2"
33
37
  },
34
38
  "repository": {
@@ -40,6 +44,7 @@
40
44
  },
41
45
  "homepage": "https://github.com/ai-ntellect/core#readme",
42
46
  "bin": {
43
- "wallet-assistant": "./dist/examples/index.js"
47
+ "wallet-assistant": "./dist/examples/index.js",
48
+ "workflow": "./dist/cli.js"
44
49
  }
45
50
  }