natureco-cli 5.20.4 → 5.21.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/CHANGELOG.md +779 -750
- package/README.md +608 -610
- package/bin/natureco.js +1099 -1095
- package/package.json +95 -94
- package/scripts/generate-qr.js +21 -0
- package/scripts/import-curated-skills-log.json +5 -0
- package/scripts/import-curated-skills.js +262 -0
- package/scripts/import-skills-log.json +167 -0
- package/scripts/import-skills.js +261 -0
- package/scripts/postinstall.js +125 -0
- package/src/commands/agent.js +280 -280
- package/src/commands/ask.js +4 -2
- package/src/commands/chat.js +0 -1
- package/src/commands/help.js +0 -2
- package/src/commands/naturehub.js +206 -373
- package/src/commands/repl.js +52 -62
- package/src/providers/mem0-memory.js +121 -121
- package/src/providers/supermemory-memory.js +117 -117
- package/src/tools/llm_task.js +150 -163
- package/src/tools/mac_alarm.js +199 -199
- package/src/tools/workflow.js +424 -439
- package/src/utils/api.js +1211 -1188
- package/src/utils/cost-tracker.js +361 -360
- package/src/utils/inquirer-wrapper.js +43 -31
- package/src/utils/paste-safe-input.js +346 -334
- package/src/utils/process-errors.js +129 -115
- package/src/utils/provider-detect.js +76 -72
- package/src/utils/skills.js +1 -1
- package/src/utils/system-prompt.js +136 -136
- package/src/utils/tools.js +324 -324
- package/README.md.bak +0 -565
- package/src/tools/http.js.bak +0 -78
package/src/commands/repl.js
CHANGED
|
@@ -101,7 +101,6 @@ function rebuildSystemPrompt(opts) {
|
|
|
101
101
|
|
|
102
102
|
// ── Tool Guardrails instance (Hermes-style) ─────────────────────────────
|
|
103
103
|
const guardrails = new ToolGuardrails();
|
|
104
|
-
const noopCallback = () => {};
|
|
105
104
|
|
|
106
105
|
// CLI komutları (REPL içinden çalıştırılabilir)
|
|
107
106
|
const CLI_COMMANDS = {
|
|
@@ -119,31 +118,31 @@ const CLI_COMMANDS = {
|
|
|
119
118
|
'/models': { desc: 'Modeller', run: ['models', 'list'] },
|
|
120
119
|
'/memory-ls': { desc: 'Memory dosyaları', run: ['memory', 'list'] },
|
|
121
120
|
'/seo': { desc: 'SEO denetimi (URL gerek)', needsArg: true, run: ['seo', 'audit'] },
|
|
122
|
-
'/naturehub': { desc: '
|
|
121
|
+
'/naturehub': { desc: 'Bota mesaj gönder (text gerek)', needsArg: true, run: ['naturehub', 'post'] },
|
|
123
122
|
'/dashboard': { desc: 'Web dashboard başlat (port 7421)', run: ['dashboard', 'start'] },
|
|
124
123
|
};
|
|
125
124
|
|
|
126
|
-
|
|
127
|
-
const
|
|
128
|
-
const
|
|
129
|
-
const
|
|
125
|
+
// Profil desteği: --profile <ad> ile ~/.natureco-<ad> kullanılır (config ile tutarlı)
|
|
126
|
+
const { CONFIG_DIR: PROFILE_DIR } = require('../utils/config');
|
|
127
|
+
const MEMORY_DIR = path.join(PROFILE_DIR, 'memory');
|
|
128
|
+
const SESSION_DIR = path.join(PROFILE_DIR, 'sessions');
|
|
129
|
+
const SESSIONS_INDEX = path.join(PROFILE_DIR, 'sessions.json');
|
|
130
|
+
const REPL_STATE = path.join(PROFILE_DIR, 'repl-state.json');
|
|
130
131
|
|
|
131
132
|
function ensureDir(dir) {
|
|
132
133
|
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
133
134
|
}
|
|
134
135
|
|
|
135
136
|
function getConfig() {
|
|
137
|
+
// Merkezi config'e delege — --profile desteği, backup ve validation
|
|
138
|
+
// yerel kopyada yoktu; REPL kullanıcının gerçek config'ini okuyordu
|
|
136
139
|
try {
|
|
137
|
-
return
|
|
140
|
+
return require('../utils/config').getConfig() || {};
|
|
138
141
|
} catch { return {}; }
|
|
139
142
|
}
|
|
140
143
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
}
|
|
144
|
-
function isGemini(url) {
|
|
145
|
-
return url && (url.includes('generativelanguage.googleapis.com') || url.includes('gemini'));
|
|
146
|
-
}
|
|
144
|
+
// Tek doğruluk kaynağı: provider-detect (MiniMax /v1 toleransı dahil)
|
|
145
|
+
const { isMiniMax, isGemini, buildChatEndpoint } = require('../utils/provider-detect');
|
|
147
146
|
|
|
148
147
|
function loadMemory(username) {
|
|
149
148
|
const file = path.join(MEMORY_DIR, `${(username || 'default').toLowerCase()}.json`);
|
|
@@ -197,8 +196,6 @@ function saveSession(messages, meta) {
|
|
|
197
196
|
return id;
|
|
198
197
|
}
|
|
199
198
|
|
|
200
|
-
|
|
201
|
-
|
|
202
199
|
function loadSession(id) {
|
|
203
200
|
// ID veya index
|
|
204
201
|
const idx = loadSessionsIndex();
|
|
@@ -227,12 +224,10 @@ function extractFacts(messages, currentFacts) {
|
|
|
227
224
|
|
|
228
225
|
// İsim/tercih pattern'leri
|
|
229
226
|
const patterns = [
|
|
230
|
-
{ re: /(?:benim
|
|
231
|
-
{ re: /(?:yaşıyorum|yaşadığım|
|
|
232
|
-
{ re: /(
|
|
233
|
-
{ re: /(
|
|
234
|
-
{ re: /(?:çalışıyorum|işim|mesleğim|çalışırım|I work as)\s+([A-ZÇĞİÖŞÜa-zçğıöşü\s]+)/i, val: m => `Meslek: ${m[1].trim()}` },
|
|
235
|
-
{ re: /(\d{1,3})\s*(?:yaş[ıi]nday[ıi]m|yaş[ıi]nda)/i, val: m => `Yaş: ${m[1]}` },
|
|
227
|
+
{ re: /(?:benim adım|adım|I'm called|my name is)\s+([A-ZÇĞİÖŞÜa-zçğıöşü]+)/i, val: m => `Adı: ${m[1]}` },
|
|
228
|
+
{ re: /(?:yaşıyorum|yaşadığım|I live in)\s+([A-ZÇĞİÖŞÜa-zçğıöşü\s]+)/i, val: m => `Yaşadığı yer: ${m[1].trim()}` },
|
|
229
|
+
{ re: /(?:seviyorum|severim|sevdiğim|like|love)\s+(?:şu|bu)?\s*([a-zA-ZçğıöşüÇĞİÖŞÜ\s]{2,30})/i, val: m => `Sevdiği şey: ${m[1].trim()}` },
|
|
230
|
+
{ re: /(?:çalışıyorum|işim|mesleğim|I work as)\s+([A-ZÇĞİÖŞÜa-zçğıöşü\s]+)/i, val: m => `Meslek: ${m[1].trim()}` },
|
|
236
231
|
];
|
|
237
232
|
|
|
238
233
|
for (const p of patterns) {
|
|
@@ -251,12 +246,7 @@ function extractFacts(messages, currentFacts) {
|
|
|
251
246
|
|
|
252
247
|
function apiRequest(providerUrl, providerApiKey, body, stream = false, retries = 3) {
|
|
253
248
|
return new Promise((resolve, reject) => {
|
|
254
|
-
const
|
|
255
|
-
const endpoint = isMM
|
|
256
|
-
? `${providerUrl.replace(/\/+$/, '')}/v1/text/chatcompletion_v2`
|
|
257
|
-
: isGemini(providerUrl)
|
|
258
|
-
? `${providerUrl.replace(/\/+$/, '')}/openai/chat/completions`
|
|
259
|
-
: `${providerUrl.replace(/\/+$/, '')}/chat/completions`;
|
|
249
|
+
const endpoint = buildChatEndpoint(providerUrl);
|
|
260
250
|
const doRequest = (attempt) => {
|
|
261
251
|
const req = https.request(endpoint, {
|
|
262
252
|
method: 'POST',
|
|
@@ -612,11 +602,9 @@ async function sendStreaming(providerUrl, providerApiKey, messages, model, onChu
|
|
|
612
602
|
const res = await apiRequest(providerUrl, providerApiKey, body, false);
|
|
613
603
|
const msg = res.choices?.[0]?.message || {};
|
|
614
604
|
const content = msg.content || '';
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
await new Promise(r => setTimeout(r, 8));
|
|
619
|
-
}
|
|
605
|
+
for (const char of content) {
|
|
606
|
+
onChunk(char);
|
|
607
|
+
await new Promise(r => setTimeout(r, 8));
|
|
620
608
|
}
|
|
621
609
|
fullText = content;
|
|
622
610
|
// Non-stream tool call desteği
|
|
@@ -629,13 +617,8 @@ async function sendStreaming(providerUrl, providerApiKey, messages, model, onChu
|
|
|
629
617
|
break;
|
|
630
618
|
}
|
|
631
619
|
|
|
632
|
-
// OpenAI uyumlu streaming
|
|
633
|
-
|
|
634
|
-
const endpoint = isMM
|
|
635
|
-
? `${providerUrl.replace(/\/+$/, '')}/v1/text/chatcompletion_v2`
|
|
636
|
-
: isGemini(providerUrl)
|
|
637
|
-
? `${providerUrl.replace(/\/+$/, '')}/openai/chat/completions`
|
|
638
|
-
: `${providerUrl.replace(/\/+$/, '')}/chat/completions`;
|
|
620
|
+
// OpenAI uyumlu streaming — tek doğruluk kaynağı buildChatEndpoint
|
|
621
|
+
const endpoint = buildChatEndpoint(providerUrl);
|
|
639
622
|
let result;
|
|
640
623
|
try {
|
|
641
624
|
result = await new Promise((resolve, reject) => {
|
|
@@ -803,7 +786,7 @@ async function processToolCalls(toolCalls, onToolCall, onAsk) {
|
|
|
803
786
|
const name = tc.function?.name || tc.name;
|
|
804
787
|
const argsStr = tc.function?.arguments || tc.args || '{}';
|
|
805
788
|
const id = tc.id || `call_${Date.now()}_${Math.random().toString(36).slice(2, 6)}`;
|
|
806
|
-
let args
|
|
789
|
+
let args;
|
|
807
790
|
try {
|
|
808
791
|
args = typeof argsStr === 'string' ? JSON.parse(argsStr) : argsStr;
|
|
809
792
|
} catch (e) {
|
|
@@ -1127,7 +1110,8 @@ async function startRepl(args) {
|
|
|
1127
1110
|
console.log(tui.styled(' ' + '─'.repeat(56), { color: tui.PALETTE.border }));
|
|
1128
1111
|
console.log(tui.C.muted(' Provider: ') + tui.C.brand(providerUrl.replace(/https?:\/\//, '')));
|
|
1129
1112
|
console.log(tui.C.muted(' Model: ') + tui.C.brand(model));
|
|
1130
|
-
|
|
1113
|
+
const displayUser = memory.nickname || cfg.userName || require('os').userInfo().username || 'Kullanıcı';
|
|
1114
|
+
console.log(tui.C.muted(' Kullanıcı: ') + tui.C.brand(displayUser + (memory.nickname && cfg.userName ? ` (${cfg.userName})` : '')));
|
|
1131
1115
|
console.log(tui.C.muted(' Bot: ') + tui.C.brand(memory.botName || 'Asistan'));
|
|
1132
1116
|
if (messages.length > 1) {
|
|
1133
1117
|
console.log(tui.C.muted(' Oturum: ') + tui.C.amber(`${messages.filter(m => m.role === 'user' || m.role === 'assistant').length} mesaj (resume)`));
|
|
@@ -1162,9 +1146,6 @@ async function startRepl(args) {
|
|
|
1162
1146
|
let totalInputTokens = 0;
|
|
1163
1147
|
let totalOutputTokens = 0;
|
|
1164
1148
|
|
|
1165
|
-
let _pendingCount = 0;
|
|
1166
|
-
let _closeRequested = false;
|
|
1167
|
-
|
|
1168
1149
|
enableBracketedPaste(process.stdout);
|
|
1169
1150
|
|
|
1170
1151
|
const rl = readline.createInterface({
|
|
@@ -1173,7 +1154,12 @@ async function startRepl(args) {
|
|
|
1173
1154
|
prompt: tui.styled('\n You ', { color: tui.PALETTE.primary, bold: true }),
|
|
1174
1155
|
terminal: true,
|
|
1175
1156
|
});
|
|
1176
|
-
|
|
1157
|
+
// Pipe/script kullanımında EOF, yanıt hâlâ üretilirken gelir —
|
|
1158
|
+
// aktif işlem varken kapanışı bekletmek için sayaç + kapalı-rl koruması
|
|
1159
|
+
let _busy = 0;
|
|
1160
|
+
let _rlClosed = false;
|
|
1161
|
+
const safePrompt = () => { if (!_rlClosed) rl.prompt(); };
|
|
1162
|
+
safePrompt();
|
|
1177
1163
|
|
|
1178
1164
|
const cleanup = async (exitCode = 0) => {
|
|
1179
1165
|
if (messages.length > 1) {
|
|
@@ -1273,10 +1259,18 @@ async function startRepl(args) {
|
|
|
1273
1259
|
process.on('SIGTERM', () => cleanup(0));
|
|
1274
1260
|
|
|
1275
1261
|
rl.on('line', async (input) => {
|
|
1276
|
-
|
|
1262
|
+
// BOM ve benzeri görünmez karakterleri temizle (PowerShell echo BOM'lu gönderir)
|
|
1263
|
+
const line = restoreNewlines(input).replace(/[\u200B\u200C\u200D\uFEFF]/g, '').trim();
|
|
1264
|
+
if (!line) { safePrompt(); return; }
|
|
1265
|
+
_busy++;
|
|
1277
1266
|
try {
|
|
1278
|
-
|
|
1279
|
-
|
|
1267
|
+
await handleLine(line);
|
|
1268
|
+
} finally {
|
|
1269
|
+
_busy--;
|
|
1270
|
+
}
|
|
1271
|
+
});
|
|
1272
|
+
|
|
1273
|
+
async function handleLine(line) {
|
|
1280
1274
|
|
|
1281
1275
|
// Çok satırlı paste: output filter'a echo'yu durdurma sinyalini ver
|
|
1282
1276
|
clearPasteContext();
|
|
@@ -1435,7 +1429,7 @@ async function startRepl(args) {
|
|
|
1435
1429
|
console.log(chalk.yellow(` Bilinmeyen komut: /${cmd}. /help yazın.`));
|
|
1436
1430
|
}
|
|
1437
1431
|
}
|
|
1438
|
-
|
|
1432
|
+
safePrompt();
|
|
1439
1433
|
return;
|
|
1440
1434
|
}
|
|
1441
1435
|
|
|
@@ -1530,7 +1524,7 @@ async function startRepl(args) {
|
|
|
1530
1524
|
messages,
|
|
1531
1525
|
model,
|
|
1532
1526
|
// v5.6.12: Callback bos - tam metin 'reply' olarak gelecek (non-stream mode)
|
|
1533
|
-
|
|
1527
|
+
() => {},
|
|
1534
1528
|
// Tool call callback — Hermes-style per-tool status line
|
|
1535
1529
|
((toolEvent) => {
|
|
1536
1530
|
const name = toolEvent.name;
|
|
@@ -1583,21 +1577,17 @@ async function startRepl(args) {
|
|
|
1583
1577
|
process.stdout.write('\n');
|
|
1584
1578
|
console.log(chalk.red(' ❌ ' + err.message));
|
|
1585
1579
|
}
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
_pendingCount--;
|
|
1589
|
-
if (_closeRequested && _pendingCount === 0) {
|
|
1590
|
-
await cleanup(0);
|
|
1591
|
-
}
|
|
1592
|
-
}
|
|
1593
|
-
});
|
|
1580
|
+
safePrompt();
|
|
1581
|
+
}
|
|
1594
1582
|
|
|
1595
1583
|
rl.on('close', () => {
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1584
|
+
_rlClosed = true;
|
|
1585
|
+
// EOF (pipe/script): süren yanıt varsa bitmesini bekle, sonra kapan
|
|
1586
|
+
const wait = () => {
|
|
1587
|
+
if (_busy > 0) { setTimeout(wait, 200); return; }
|
|
1599
1588
|
cleanup(0);
|
|
1600
|
-
}
|
|
1589
|
+
};
|
|
1590
|
+
wait();
|
|
1601
1591
|
});
|
|
1602
1592
|
}
|
|
1603
1593
|
|
|
@@ -1,121 +1,121 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* mem0-memory.js — Mem0 memory provider
|
|
3
|
-
*
|
|
4
|
-
* Uses the mem0ai npm package (platform API) or local OSS Memory class.
|
|
5
|
-
* Requires MEM0_API_KEY env var or config.mem0.apiKey.
|
|
6
|
-
* npm install mem0ai
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
const { MemoryProvider, registerProvider } = require('../utils/memory-provider');
|
|
10
|
-
|
|
11
|
-
class Mem0MemoryProvider extends MemoryProvider {
|
|
12
|
-
constructor(config = {}) {
|
|
13
|
-
super(config);
|
|
14
|
-
this.name = 'mem0';
|
|
15
|
-
this._client = null;
|
|
16
|
-
this._mode = 'platform'; // or 'oss'
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
_getConfig() {
|
|
20
|
-
return this.config.mem0 || this.config.Mem0 || {};
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
_apiKey() {
|
|
24
|
-
return process.env.MEM0_API_KEY || this._getConfig().apiKey || '';
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
async _ensureClient() {
|
|
28
|
-
if (this._client) return;
|
|
29
|
-
try {
|
|
30
|
-
const apiKey = this._apiKey();
|
|
31
|
-
if (apiKey) {
|
|
32
|
-
const { MemoryClient } = await import('mem0ai');
|
|
33
|
-
this._client = new MemoryClient({ apiKey });
|
|
34
|
-
this._mode = 'platform';
|
|
35
|
-
} else {
|
|
36
|
-
const { Memory } = await import('mem0ai/oss');
|
|
37
|
-
this._client = new Memory(this._getConfig().oss || {});
|
|
38
|
-
this._mode = 'oss';
|
|
39
|
-
}
|
|
40
|
-
} catch (e) {
|
|
41
|
-
throw new Error('mem0ai paketi yuklu degil. npm install mem0ai');
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
async add(userId, content, metadata = {}) {
|
|
46
|
-
await this._ensureClient();
|
|
47
|
-
const uid = userId || 'default';
|
|
48
|
-
if (this._mode === 'platform') {
|
|
49
|
-
const messages = [{ role: 'user', content }];
|
|
50
|
-
await this._client.add(messages, { userId: uid, metadata });
|
|
51
|
-
} else {
|
|
52
|
-
const messages = [
|
|
53
|
-
{ role: 'user', content },
|
|
54
|
-
{ role: 'assistant', content: 'Bilgi kaydedildi.' },
|
|
55
|
-
];
|
|
56
|
-
await this._client.add(messages, { userId: uid, metadata });
|
|
57
|
-
}
|
|
58
|
-
return { success: true, id: content, message: 'Mem0 memory added', provider: 'mem0' };
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
async search(query, options = {}) {
|
|
62
|
-
await this._ensureClient();
|
|
63
|
-
const uid = options.userId;
|
|
64
|
-
const filters = uid ? { userId: uid } : {};
|
|
65
|
-
if (options.limit) filters.limit = options.limit;
|
|
66
|
-
try {
|
|
67
|
-
const results = await this._client.search(query, { filters });
|
|
68
|
-
return { success: true, results: (results.results || results || []).map(r => ({
|
|
69
|
-
id: r.id || r.memory,
|
|
70
|
-
content: r.memory || r.content || '',
|
|
71
|
-
score: r.score || 0,
|
|
72
|
-
metadata: r.metadata || {},
|
|
73
|
-
})) };
|
|
74
|
-
} catch (e) {
|
|
75
|
-
return { success: false, error: e.message, results: [] };
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
async list(userId) {
|
|
80
|
-
await this._ensureClient();
|
|
81
|
-
const uid = userId || 'default';
|
|
82
|
-
try {
|
|
83
|
-
const memories = await this._client.getAll({ userId: uid });
|
|
84
|
-
return {
|
|
85
|
-
success: true,
|
|
86
|
-
memories: (memories || []).map(r => ({
|
|
87
|
-
id: r.id || r.memory,
|
|
88
|
-
content: r.memory || r.content || '',
|
|
89
|
-
score: r.score || 0,
|
|
90
|
-
metadata: r.metadata || {},
|
|
91
|
-
})),
|
|
92
|
-
};
|
|
93
|
-
} catch (e) {
|
|
94
|
-
return { success: false, error: e.message, memories: [] };
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
async remove(id) {
|
|
99
|
-
await this._ensureClient();
|
|
100
|
-
try {
|
|
101
|
-
await this._client.delete(id);
|
|
102
|
-
return { success: true, message: 'Mem0 memory removed' };
|
|
103
|
-
} catch (e) {
|
|
104
|
-
return { success: false, error: e.message };
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
async clear(userId) {
|
|
109
|
-
await this._ensureClient();
|
|
110
|
-
const uid = userId || 'default';
|
|
111
|
-
try {
|
|
112
|
-
await this._client.deleteAll({ userId: uid });
|
|
113
|
-
return { success: true, message: `Mem0 memory cleared for ${uid}` };
|
|
114
|
-
} catch (e) {
|
|
115
|
-
return { success: false, error: e.message };
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
registerProvider('mem0', Mem0MemoryProvider);
|
|
121
|
-
module.exports = Mem0MemoryProvider;
|
|
1
|
+
/**
|
|
2
|
+
* mem0-memory.js — Mem0 memory provider
|
|
3
|
+
*
|
|
4
|
+
* Uses the mem0ai npm package (platform API) or local OSS Memory class.
|
|
5
|
+
* Requires MEM0_API_KEY env var or config.mem0.apiKey.
|
|
6
|
+
* npm install mem0ai
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const { MemoryProvider, registerProvider } = require('../utils/memory-provider');
|
|
10
|
+
|
|
11
|
+
class Mem0MemoryProvider extends MemoryProvider {
|
|
12
|
+
constructor(config = {}) {
|
|
13
|
+
super(config);
|
|
14
|
+
this.name = 'mem0';
|
|
15
|
+
this._client = null;
|
|
16
|
+
this._mode = 'platform'; // or 'oss'
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
_getConfig() {
|
|
20
|
+
return this.config.mem0 || this.config.Mem0 || {};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
_apiKey() {
|
|
24
|
+
return process.env.MEM0_API_KEY || this._getConfig().apiKey || '';
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async _ensureClient() {
|
|
28
|
+
if (this._client) return;
|
|
29
|
+
try {
|
|
30
|
+
const apiKey = this._apiKey();
|
|
31
|
+
if (apiKey) {
|
|
32
|
+
const { MemoryClient } = await import('mem0ai');
|
|
33
|
+
this._client = new MemoryClient({ apiKey });
|
|
34
|
+
this._mode = 'platform';
|
|
35
|
+
} else {
|
|
36
|
+
const { Memory } = await import('mem0ai/oss');
|
|
37
|
+
this._client = new Memory(this._getConfig().oss || {});
|
|
38
|
+
this._mode = 'oss';
|
|
39
|
+
}
|
|
40
|
+
} catch (e) {
|
|
41
|
+
throw new Error('mem0ai paketi yuklu degil. npm install mem0ai', { cause: e });
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async add(userId, content, metadata = {}) {
|
|
46
|
+
await this._ensureClient();
|
|
47
|
+
const uid = userId || 'default';
|
|
48
|
+
if (this._mode === 'platform') {
|
|
49
|
+
const messages = [{ role: 'user', content }];
|
|
50
|
+
await this._client.add(messages, { userId: uid, metadata });
|
|
51
|
+
} else {
|
|
52
|
+
const messages = [
|
|
53
|
+
{ role: 'user', content },
|
|
54
|
+
{ role: 'assistant', content: 'Bilgi kaydedildi.' },
|
|
55
|
+
];
|
|
56
|
+
await this._client.add(messages, { userId: uid, metadata });
|
|
57
|
+
}
|
|
58
|
+
return { success: true, id: content, message: 'Mem0 memory added', provider: 'mem0' };
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async search(query, options = {}) {
|
|
62
|
+
await this._ensureClient();
|
|
63
|
+
const uid = options.userId;
|
|
64
|
+
const filters = uid ? { userId: uid } : {};
|
|
65
|
+
if (options.limit) filters.limit = options.limit;
|
|
66
|
+
try {
|
|
67
|
+
const results = await this._client.search(query, { filters });
|
|
68
|
+
return { success: true, results: (results.results || results || []).map(r => ({
|
|
69
|
+
id: r.id || r.memory,
|
|
70
|
+
content: r.memory || r.content || '',
|
|
71
|
+
score: r.score || 0,
|
|
72
|
+
metadata: r.metadata || {},
|
|
73
|
+
})) };
|
|
74
|
+
} catch (e) {
|
|
75
|
+
return { success: false, error: e.message, results: [] };
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
async list(userId) {
|
|
80
|
+
await this._ensureClient();
|
|
81
|
+
const uid = userId || 'default';
|
|
82
|
+
try {
|
|
83
|
+
const memories = await this._client.getAll({ userId: uid });
|
|
84
|
+
return {
|
|
85
|
+
success: true,
|
|
86
|
+
memories: (memories || []).map(r => ({
|
|
87
|
+
id: r.id || r.memory,
|
|
88
|
+
content: r.memory || r.content || '',
|
|
89
|
+
score: r.score || 0,
|
|
90
|
+
metadata: r.metadata || {},
|
|
91
|
+
})),
|
|
92
|
+
};
|
|
93
|
+
} catch (e) {
|
|
94
|
+
return { success: false, error: e.message, memories: [] };
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
async remove(id) {
|
|
99
|
+
await this._ensureClient();
|
|
100
|
+
try {
|
|
101
|
+
await this._client.delete(id);
|
|
102
|
+
return { success: true, message: 'Mem0 memory removed' };
|
|
103
|
+
} catch (e) {
|
|
104
|
+
return { success: false, error: e.message };
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
async clear(userId) {
|
|
109
|
+
await this._ensureClient();
|
|
110
|
+
const uid = userId || 'default';
|
|
111
|
+
try {
|
|
112
|
+
await this._client.deleteAll({ userId: uid });
|
|
113
|
+
return { success: true, message: `Mem0 memory cleared for ${uid}` };
|
|
114
|
+
} catch (e) {
|
|
115
|
+
return { success: false, error: e.message };
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
registerProvider('mem0', Mem0MemoryProvider);
|
|
121
|
+
module.exports = Mem0MemoryProvider;
|