@ai.ntellect/core 0.3.3 โ†’ 0.4.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.
Files changed (85) hide show
  1. package/.nvmrc +1 -0
  2. package/README.FR.md +201 -261
  3. package/README.md +208 -260
  4. package/agent/index.ts +199 -216
  5. package/agent/tools/get-rss.ts +64 -0
  6. package/bull.ts +5 -0
  7. package/dist/agent/index.d.ts +29 -26
  8. package/dist/agent/index.js +123 -112
  9. package/dist/agent/tools/get-rss.d.ts +16 -0
  10. package/dist/agent/tools/get-rss.js +62 -0
  11. package/dist/bull.d.ts +1 -0
  12. package/dist/bull.js +9 -0
  13. package/dist/examples/index.d.ts +2 -0
  14. package/dist/examples/index.js +89 -0
  15. package/dist/llm/interpreter/context.d.ts +5 -22
  16. package/dist/llm/interpreter/context.js +8 -9
  17. package/dist/llm/interpreter/index.d.ts +9 -5
  18. package/dist/llm/interpreter/index.js +55 -48
  19. package/dist/llm/memory-manager/context.d.ts +2 -0
  20. package/dist/llm/memory-manager/context.js +22 -0
  21. package/dist/llm/memory-manager/index.d.ts +17 -0
  22. package/dist/llm/memory-manager/index.js +107 -0
  23. package/dist/llm/orchestrator/context.d.ts +2 -10
  24. package/dist/llm/orchestrator/context.js +19 -14
  25. package/dist/llm/orchestrator/index.d.ts +36 -21
  26. package/dist/llm/orchestrator/index.js +122 -88
  27. package/dist/llm/orchestrator/types.d.ts +12 -0
  28. package/dist/llm/orchestrator/types.js +2 -0
  29. package/dist/memory/cache.d.ts +6 -5
  30. package/dist/memory/cache.js +31 -21
  31. package/dist/memory/persistent.d.ts +5 -3
  32. package/dist/memory/persistent.js +89 -73
  33. package/dist/services/redis-cache.d.ts +37 -0
  34. package/dist/services/redis-cache.js +93 -0
  35. package/dist/services/scheduler.d.ts +39 -16
  36. package/dist/services/scheduler.js +81 -103
  37. package/dist/services/telegram-monitor.d.ts +0 -15
  38. package/dist/services/telegram-monitor.js +117 -101
  39. package/dist/test.js +106 -172
  40. package/dist/types.d.ts +38 -7
  41. package/dist/utils/generate-object.d.ts +12 -0
  42. package/dist/utils/generate-object.js +90 -0
  43. package/dist/utils/header-builder.d.ts +11 -0
  44. package/dist/utils/header-builder.js +34 -0
  45. package/dist/utils/inject-actions.js +2 -2
  46. package/dist/utils/queue-item-transformer.d.ts +2 -2
  47. package/dist/utils/schema-generator.d.ts +16 -0
  48. package/dist/utils/schema-generator.js +46 -0
  49. package/examples/index.ts +103 -0
  50. package/llm/interpreter/context.ts +20 -8
  51. package/llm/interpreter/index.ts +81 -54
  52. package/llm/memory-manager/context.ts +21 -0
  53. package/llm/memory-manager/index.ts +163 -0
  54. package/llm/orchestrator/context.ts +20 -13
  55. package/llm/orchestrator/index.ts +210 -130
  56. package/llm/orchestrator/types.ts +14 -0
  57. package/memory/cache.ts +37 -31
  58. package/memory/persistent.ts +121 -99
  59. package/package.json +11 -2
  60. package/services/redis-cache.ts +128 -0
  61. package/services/scheduler.ts +102 -141
  62. package/services/telegram-monitor.ts +138 -138
  63. package/t.py +79 -0
  64. package/t.spec +38 -0
  65. package/types.ts +40 -7
  66. package/utils/generate-object.ts +105 -0
  67. package/utils/header-builder.ts +40 -0
  68. package/utils/inject-actions.ts +4 -6
  69. package/utils/queue-item-transformer.ts +2 -1
  70. package/utils/schema-generator.ts +73 -0
  71. package/agent/handlers/ActionHandler.ts +0 -48
  72. package/agent/handlers/ConfirmationHandler.ts +0 -37
  73. package/agent/handlers/EventHandler.ts +0 -35
  74. package/dist/agent/handlers/ActionHandler.d.ts +0 -8
  75. package/dist/agent/handlers/ActionHandler.js +0 -36
  76. package/dist/agent/handlers/ConfirmationHandler.d.ts +0 -7
  77. package/dist/agent/handlers/ConfirmationHandler.js +0 -31
  78. package/dist/agent/handlers/EventHandler.d.ts +0 -10
  79. package/dist/agent/handlers/EventHandler.js +0 -34
  80. package/dist/llm/evaluator/context.d.ts +0 -10
  81. package/dist/llm/evaluator/context.js +0 -24
  82. package/dist/llm/evaluator/index.d.ts +0 -16
  83. package/dist/llm/evaluator/index.js +0 -150
  84. package/llm/evaluator/context.ts +0 -21
  85. package/llm/evaluator/index.ts +0 -193
@@ -1,7 +1,6 @@
1
- import { openai } from "@ai-sdk/openai";
2
- import { cosineSimilarity, embed, embedMany } from "ai";
1
+ import { cosineSimilarity, embed, EmbeddingModel, embedMany } from "ai";
3
2
  import { RecursiveCharacterTextSplitter } from "langchain/text_splitter";
4
- import { Memory, MemoryScope } from "../types";
3
+ import { LongTermMemory, MemoryScope } from "../types";
5
4
 
6
5
  interface SearchOptions {
7
6
  scope?: MemoryScope;
@@ -40,19 +39,31 @@ export class PersistentMemory {
40
39
  private readonly host: string;
41
40
  private readonly apiKey: string;
42
41
  private readonly INDEX_PREFIX: string;
43
-
44
- constructor(options: { host: string; apiKey: string; indexPrefix?: string }) {
42
+ private readonly embeddingModel: EmbeddingModel<string>;
43
+ constructor(options: {
44
+ host: string;
45
+ apiKey: string;
46
+ indexPrefix?: string;
47
+ embeddingModel: EmbeddingModel<string>;
48
+ }) {
45
49
  this.host = options.host;
46
50
  this.apiKey = options.apiKey;
47
51
  this.INDEX_PREFIX = options.indexPrefix || "memory";
52
+ this.embeddingModel = options.embeddingModel;
48
53
  }
49
54
 
50
55
  /**
51
56
  * Initialize indexes
52
57
  */
53
58
  async init() {
54
- // Create global index
55
- await this._getOrCreateIndex(this.INDEX_PREFIX);
59
+ try {
60
+ // Create or get main index
61
+ await this._getOrCreateIndex(this.INDEX_PREFIX);
62
+ console.log(`โœ… Index '${this.INDEX_PREFIX}' initialized successfully`);
63
+ } catch (error) {
64
+ console.error(`โŒ Failed to initialize index: ${error}`);
65
+ throw error;
66
+ }
56
67
  }
57
68
 
58
69
  /**
@@ -63,6 +74,7 @@ export class PersistentMemory {
63
74
  options: RequestInit = {}
64
75
  ): Promise<T> {
65
76
  const url = `${this.host}${path}`;
77
+ console.log("๐Ÿ” Making request to Meilisearch:", url);
66
78
  const response = await fetch(url, {
67
79
  ...options,
68
80
  headers: {
@@ -79,19 +91,27 @@ export class PersistentMemory {
79
91
 
80
92
  return response.json() as Promise<T>;
81
93
  }
94
+
82
95
  /**
83
96
  * Get or create an index with proper settings
84
97
  */
85
98
  private async _getOrCreateIndex(indexName: string) {
86
99
  try {
87
- // Try to create index
88
- await this._makeRequest("/indexes", {
89
- method: "POST",
90
- body: JSON.stringify({
91
- uid: indexName,
92
- primaryKey: "id",
93
- }),
94
- });
100
+ // Check if index exists first
101
+ const indexExists = await this._makeRequest(`/indexes/${indexName}`, {
102
+ method: "GET",
103
+ }).catch(() => false);
104
+
105
+ if (!indexExists) {
106
+ console.log(`Creating new index: ${indexName}`);
107
+ await this._makeRequest("/indexes", {
108
+ method: "POST",
109
+ body: JSON.stringify({
110
+ uid: indexName,
111
+ primaryKey: "id",
112
+ }),
113
+ });
114
+ }
95
115
 
96
116
  // Update index settings
97
117
  const settings: MeilisearchSettings = {
@@ -103,11 +123,11 @@ export class PersistentMemory {
103
123
  method: "PATCH",
104
124
  body: JSON.stringify(settings),
105
125
  });
126
+
127
+ console.log(`Index ${indexName} configured successfully`);
106
128
  } catch (error: any) {
107
- // Index might already exist, which is fine
108
- if (!error.message.includes("already exists")) {
109
- throw error;
110
- }
129
+ console.error(`Failed to configure index ${indexName}:`, error);
130
+ throw error;
111
131
  }
112
132
  }
113
133
 
@@ -120,7 +140,7 @@ export class PersistentMemory {
120
140
 
121
141
  // Generate embeddings for all chunks
122
142
  const { embeddings } = await embedMany({
123
- model: openai.embedding("text-embedding-3-small"),
143
+ model: this.embeddingModel,
124
144
  values: chunks.map((chunk) => chunk.pageContent),
125
145
  });
126
146
 
@@ -134,102 +154,104 @@ export class PersistentMemory {
134
154
  /**
135
155
  * Store a memory in the database
136
156
  */
137
- async createMemory(memory: Memory) {
138
- await this._getOrCreateIndex(memory.roomId);
139
-
140
- const chunks = await this.processContent(memory.data);
141
-
142
- const document = {
143
- ...memory,
144
- chunks,
145
- createdAt: memory.createdAt.toISOString(),
146
- };
147
-
148
- const response = await this._makeRequest(
149
- `/indexes/${this.INDEX_PREFIX}/documents`,
150
- {
151
- method: "POST",
152
- body: JSON.stringify([document]),
153
- }
154
- );
155
- console.log("Stored persistent memory response:", response);
156
- return response;
157
+ async createMemory(memory: LongTermMemory) {
158
+ try {
159
+ console.log(`๐Ÿ“ Creating memory in index: ${this.INDEX_PREFIX}`);
160
+
161
+ // Process content into chunks with embeddings
162
+ const chunks = await this.processContent(memory.data);
163
+
164
+ // Generate unique ID if not provided
165
+ const id = memory.id || crypto.randomUUID();
166
+
167
+ const document = {
168
+ ...memory,
169
+ chunks,
170
+ createdAt: memory.createdAt.toISOString(),
171
+ };
172
+
173
+ const response = await this._makeRequest(
174
+ `/indexes/${this.INDEX_PREFIX}/documents`,
175
+ {
176
+ method: "POST",
177
+ body: JSON.stringify([document]),
178
+ }
179
+ );
180
+
181
+ console.log("โœ… Memory created successfully", { id });
182
+ return response;
183
+ } catch (error) {
184
+ console.error("โŒ Failed to create memory:", error);
185
+ throw error;
186
+ }
157
187
  }
158
188
 
159
189
  /**
160
190
  * Find best matching memories
161
191
  */
162
192
  async findRelevantDocuments(query: string, options: SearchOptions = {}) {
163
- console.log("\n๐Ÿ” Searching in persistent memory");
193
+ console.log(`\n๐Ÿ” Searching in index: ${this.INDEX_PREFIX}`);
164
194
  console.log("Query:", query);
165
- console.log("Options:", JSON.stringify(options, null, 2));
166
-
167
- // Generate embedding for the query
168
- const { embedding: queryEmbedding } = await embed({
169
- model: openai.embedding("text-embedding-3-small"),
170
- value: query,
171
- });
172
195
 
173
- const searchResults = [];
174
-
175
- console.log("\n๐Ÿ“š Searching in global index:", this.INDEX_PREFIX);
176
196
  try {
177
- const globalResults = await this._makeRequest<MeilisearchResponse>(
197
+ // Generate embedding for the query
198
+ const { embedding: queryEmbedding } = await embed({
199
+ model: this.embeddingModel,
200
+ value: query,
201
+ });
202
+
203
+ // Search in the index
204
+ const searchResults = await this._makeRequest<MeilisearchResponse>(
178
205
  `/indexes/${this.INDEX_PREFIX}/search`,
179
206
  {
180
207
  method: "POST",
181
- body: JSON.stringify({ q: query }),
208
+ body: JSON.stringify({
209
+ q: query,
210
+ limit: options.maxResults || 10,
211
+ }),
182
212
  }
183
213
  );
184
- if (globalResults?.hits) {
185
- searchResults.push(...globalResults.hits);
214
+
215
+ if (!searchResults?.hits?.length) {
216
+ console.log("โŒ No matches found");
217
+ return [];
186
218
  }
187
- } catch (error) {
188
- console.error("โŒ Error searching global index:", error);
189
- }
190
219
 
191
- const totalResults = searchResults.length;
192
- console.log(`\n๐Ÿ“Š Found ${totalResults} total matches`);
193
-
194
- // Process and filter results using cosine similarity
195
- const results = searchResults
196
- .flatMap((hit) => {
197
- const chunkSimilarities = hit.chunks.map((chunk) => ({
198
- query: hit.query,
199
- data: hit.data,
200
- similarityPercentage:
201
- (cosineSimilarity(queryEmbedding, chunk.embedding) + 1) * 50,
202
- createdAt: hit.createdAt,
203
- }));
204
-
205
- return chunkSimilarities.reduce(
206
- (best, current) =>
207
- current.similarityPercentage > best.similarityPercentage
208
- ? current
209
- : best,
210
- chunkSimilarities[0]
211
- );
212
- })
213
- .filter(
214
- (match) =>
215
- match.similarityPercentage >= (options.similarityThreshold || 70)
216
- )
217
- .sort((a, b) => b.similarityPercentage - a.similarityPercentage);
218
-
219
- // Log filtered results in a more structured way
220
- if (results.length > 0) {
221
- console.log("\nโœจ Relevant matches found:");
222
- console.log("โ”€".repeat(50));
223
-
224
- results.forEach((match, index) => {
225
- console.log(`\n${index + 1}. Match Details:`);
226
- console.log(` Query: ${match.query}`);
227
- });
228
- } else {
229
- console.log("\nโŒ No relevant matches found");
230
- }
220
+ // Process and filter results using cosine similarity
221
+ const results = searchResults.hits
222
+ .flatMap((hit) => {
223
+ const chunkSimilarities = hit.chunks.map((chunk) => ({
224
+ query: hit.query,
225
+ data: hit.data,
226
+ similarityPercentage:
227
+ (cosineSimilarity(queryEmbedding, chunk.embedding) + 1) * 50,
228
+ createdAt: hit.createdAt,
229
+ }));
230
+
231
+ return chunkSimilarities.reduce(
232
+ (best, current) =>
233
+ current.similarityPercentage > best.similarityPercentage
234
+ ? current
235
+ : best,
236
+ chunkSimilarities[0]
237
+ );
238
+ })
239
+ .filter(
240
+ (match) =>
241
+ match.similarityPercentage >= (options.similarityThreshold || 70)
242
+ )
243
+ .sort((a, b) => b.similarityPercentage - a.similarityPercentage);
231
244
 
232
- return results;
245
+ console.log(`โœจ Found ${results.length} relevant matches`);
246
+ return results.map((result) => ({
247
+ query: result.query,
248
+ data: result.data,
249
+ createdAt: result.createdAt,
250
+ }));
251
+ } catch (error) {
252
+ console.error("โŒ Search failed:", error);
253
+ return [];
254
+ }
233
255
  }
234
256
 
235
257
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai.ntellect/core",
3
- "version": "0.3.3",
3
+ "version": "0.4.0",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -12,18 +12,24 @@
12
12
  "author": "Lorcann Rauzduel",
13
13
  "license": "ISC",
14
14
  "dependencies": {
15
+ "@ai-sdk/deepseek": "^0.1.0",
15
16
  "@ai-sdk/openai": "1.0.6",
17
+ "@types/node-cron": "^3.0.11",
16
18
  "ai": "^3.0.0",
17
19
  "ethers": "^6.13.5",
18
20
  "langchain": "^0.3.11",
21
+ "node-cron": "^3.0.3",
22
+ "readline": "^1.3.0",
19
23
  "redis": "^4.7.0",
20
24
  "rss-parser": "^3.13.0",
25
+ "ws": "^8.18.0",
21
26
  "zod": "^3.24.1"
22
27
  },
23
28
  "devDependencies": {
24
29
  "@jest/globals": "^29.7.0",
25
30
  "@types/chai": "^4.3.20",
26
31
  "@types/mocha": "^10.0.0",
32
+ "@types/ws": "^8.5.14",
27
33
  "chai": "^4.5.0",
28
34
  "mocha": "^10.0.0",
29
35
  "ts-node": "^10.9.0",
@@ -37,5 +43,8 @@
37
43
  "bugs": {
38
44
  "url": "https://github.com/ai-ntellect/core/issues"
39
45
  },
40
- "homepage": "https://github.com/ai-ntellect/core#readme"
46
+ "homepage": "https://github.com/ai-ntellect/core#readme",
47
+ "bin": {
48
+ "wallet-assistant": "./dist/examples/index.js"
49
+ }
41
50
  }
@@ -0,0 +1,128 @@
1
+ import Redis from "ioredis";
2
+ import cron from "node-cron";
3
+
4
+ export interface CacheConfig {
5
+ host: string;
6
+ port: number;
7
+ password?: string;
8
+ ttl?: number; // Time to live in seconds (default 30 minutes)
9
+ cleanupInterval?: string; // Cron expression (default every 30 minutes)
10
+ }
11
+
12
+ export class RedisCache {
13
+ private redis: Redis;
14
+ private readonly defaultTTL: number;
15
+ private readonly cleanupJob: cron.ScheduledTask;
16
+
17
+ constructor(config: CacheConfig) {
18
+ this.redis = new Redis({
19
+ host: config.host,
20
+ port: config.port,
21
+ password: config.password,
22
+ });
23
+
24
+ this.defaultTTL = config.ttl || 1800; // 30 minutes in seconds
25
+
26
+ // Setup cleanup job (default: every 30 minutes)
27
+ this.cleanupJob = cron.schedule(
28
+ config.cleanupInterval || "*/30 * * * *",
29
+ () => this.cleanup()
30
+ );
31
+ }
32
+
33
+ /**
34
+ * Store previous actions for a specific request
35
+ */
36
+ async storePreviousActions(requestId: string, actions: any[]): Promise<void> {
37
+ const key = `previous_actions:${requestId}`;
38
+ await this.redis.setex(
39
+ key,
40
+ this.defaultTTL,
41
+ JSON.stringify({
42
+ timestamp: new Date().toISOString(),
43
+ actions,
44
+ })
45
+ );
46
+ }
47
+
48
+ /**
49
+ * Get previous actions for a specific request
50
+ */
51
+ async getPreviousActions(requestId: string): Promise<any[]> {
52
+ const key = `previous_actions:${requestId}`;
53
+ const data = await this.redis.get(key);
54
+ if (!data) return [];
55
+
56
+ const parsed = JSON.parse(data);
57
+ return parsed.actions;
58
+ }
59
+
60
+ /**
61
+ * Store a recent message
62
+ */
63
+ async storeRecentMessage(
64
+ message: string,
65
+ metadata?: Record<string, any>
66
+ ): Promise<void> {
67
+ const id = crypto.randomUUID();
68
+ const key = `recent_messages:${id}`;
69
+ await this.redis.setex(
70
+ key,
71
+ this.defaultTTL,
72
+ JSON.stringify({
73
+ timestamp: new Date().toISOString(),
74
+ message,
75
+ metadata,
76
+ })
77
+ );
78
+ }
79
+
80
+ /**
81
+ * Get recent messages
82
+ */
83
+ async getRecentMessages(limit: number = 10): Promise<any[]> {
84
+ const keys = await this.redis.keys("recent_messages:*");
85
+ if (!keys.length) return [];
86
+
87
+ const messages = await Promise.all(
88
+ keys.map(async (key) => {
89
+ const data = await this.redis.get(key);
90
+ return data ? JSON.parse(data) : null;
91
+ })
92
+ );
93
+
94
+ return messages
95
+ .filter(Boolean)
96
+ .sort(
97
+ (a, b) =>
98
+ new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime()
99
+ )
100
+ .slice(0, limit);
101
+ }
102
+
103
+ /**
104
+ * Cleanup expired keys
105
+ */
106
+ private async cleanup(): Promise<void> {
107
+ console.log("๐Ÿงน Starting cache cleanup...");
108
+ try {
109
+ // Redis automatically removes expired keys
110
+ // This is just for logging purposes
111
+ const actionKeys = await this.redis.keys("previous_actions:*");
112
+ const messageKeys = await this.redis.keys("recent_messages:*");
113
+ console.log(
114
+ `Cache status: ${actionKeys.length} actions, ${messageKeys.length} messages`
115
+ );
116
+ } catch (error) {
117
+ console.error("โŒ Cache cleanup error:", error);
118
+ }
119
+ }
120
+
121
+ /**
122
+ * Stop the cleanup job and close Redis connection
123
+ */
124
+ async close(): Promise<void> {
125
+ this.cleanupJob.stop();
126
+ await this.redis.quit();
127
+ }
128
+ }