tuna-agent 0.1.19 → 0.1.20

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.
@@ -1,7 +1,7 @@
1
1
  import type { AgentConfig } from '../types/index.js';
2
2
  /**
3
- * Call Mem0 add_memory directly via MCP JSON-RPC (no Claude CLI needed).
4
- * Spawns mem0-mcp process, sends init + add_memory, reads response.
3
+ * Call Mem0 add_memory via mem0-add script (bypasses OpenMemory API).
4
+ * Calls `mem0-add <text>` directly or via SSH — simple, reliable.
5
5
  */
6
6
  export declare function callMem0AddMemory(text: string, agentName: string): Promise<void>;
7
7
  /**
package/dist/mcp/setup.js CHANGED
@@ -21,88 +21,57 @@ const MEM0_ENV_VARS = {
21
21
  MEM0_NEO4J_PASSWORD: 'mem0graph',
22
22
  };
23
23
  /**
24
- * Call Mem0 add_memory directly via MCP JSON-RPC (no Claude CLI needed).
25
- * Spawns mem0-mcp process, sends init + add_memory, reads response.
24
+ * Call Mem0 add_memory via mem0-add script (bypasses OpenMemory API).
25
+ * Calls `mem0-add <text>` directly or via SSH — simple, reliable.
26
26
  */
27
27
  export async function callMem0AddMemory(text, agentName) {
28
28
  if (!MEM0_SSH_HOST)
29
29
  throw new Error('MEM0_SSH_HOST not configured');
30
- const { spawn } = await import('child_process');
30
+ const { execFile } = await import('child_process');
31
31
  const safeAgentName = agentName.replace(/[^a-zA-Z0-9_-]/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '') || 'agent';
32
- const envWithUser = { ...MEM0_ENV_VARS, MEM0_USER_ID: safeAgentName };
33
- let cmd;
34
- let args;
35
- let spawnEnv;
36
- if (MEM0_SSH_HOST === 'local') {
37
- cmd = 'mem0-mcp';
38
- args = [];
39
- spawnEnv = { ...process.env, ...envWithUser };
40
- }
41
- else {
42
- const envString = Object.entries(envWithUser).map(([k, v]) => `${k}=${v}`).join(' ');
43
- cmd = 'ssh';
44
- args = ['-p', MEM0_SSH_PORT, '-o', 'StrictHostKeyChecking=no'];
45
- if (MEM0_SSH_KEY)
46
- args.push('-i', MEM0_SSH_KEY);
47
- args.push(MEM0_SSH_HOST, `${envString} mem0-mcp`);
48
- }
49
32
  return new Promise((resolve, reject) => {
50
- const proc = spawn(cmd, args, { stdio: ['pipe', 'pipe', 'pipe'], env: spawnEnv });
51
- let stdout = '';
52
- let resolved = false;
53
- const timer = setTimeout(() => { if (!resolved) {
54
- resolved = true;
55
- proc.kill();
56
- reject(new Error('Mem0 call timed out'));
57
- } }, 30000);
58
- proc.stderr.on('data', () => { }); // ignore stderr
59
- const initMsg = JSON.stringify({ jsonrpc: '2.0', id: 1, method: 'initialize', params: { protocolVersion: '2024-11-05', capabilities: {}, clientInfo: { name: 'tuna-agent', version: '1.0' } } });
60
- const notifyMsg = JSON.stringify({ jsonrpc: '2.0', method: 'notifications/initialized' });
61
- const addMsg = JSON.stringify({ jsonrpc: '2.0', id: 2, method: 'tools/call', params: { name: 'add_memory', arguments: { text } } });
62
- let sentAdd = false;
63
- proc.stdout.on('data', (d) => {
64
- stdout += d.toString();
65
- // After init response, send the add_memory call
66
- if (!sentAdd && stdout.includes('"id":1')) {
67
- sentAdd = true;
68
- proc.stdin.write(notifyMsg + '\n');
69
- proc.stdin.write(addMsg + '\n');
33
+ const timer = setTimeout(() => reject(new Error('Mem0 call timed out')), 30000);
34
+ let cmd;
35
+ let args;
36
+ let options = {};
37
+ if (MEM0_SSH_HOST === 'local') {
38
+ cmd = 'mem0-add';
39
+ args = [text];
40
+ options.env = { ...process.env, MEM0_USER_ID: safeAgentName };
41
+ }
42
+ else {
43
+ cmd = 'ssh';
44
+ args = ['-p', MEM0_SSH_PORT, '-o', 'StrictHostKeyChecking=no'];
45
+ if (MEM0_SSH_KEY)
46
+ args.push('-i', MEM0_SSH_KEY);
47
+ // Shell-escape text with single quotes (escape internal single quotes)
48
+ const escapedText = text.replace(/'/g, "'\\''");
49
+ args.push(MEM0_SSH_HOST, `MEM0_USER_ID=${safeAgentName} mem0-add '${escapedText}'`);
50
+ }
51
+ execFile(cmd, args, { ...options, timeout: 30000 }, (err, stdout, stderr) => {
52
+ clearTimeout(timer);
53
+ if (err) {
54
+ reject(new Error(`Mem0 add failed: ${err.message}${stderr ? ` stderr: ${stderr.substring(0, 200)}` : ''}`));
55
+ return;
70
56
  }
71
- // After add_memory response, we're done
72
- if (sentAdd && stdout.includes('"id":2')) {
73
- if (!resolved) {
74
- resolved = true;
75
- clearTimeout(timer);
76
- proc.stdin.end();
77
- proc.kill();
78
- // Check if the response contains an error
79
- const hasError = stdout.includes('"isError":true') || stdout.includes('"error"');
80
- if (hasError) {
81
- // Extract error message from response
82
- const errMatch = stdout.match(/"text"\s*:\s*"([^"]+)"/);
83
- reject(new Error(`Mem0 add_memory failed: ${errMatch?.[1] || 'unknown error'}`));
84
- }
85
- else {
86
- resolve();
87
- }
57
+ // Check response for actual results
58
+ try {
59
+ const data = JSON.parse(stdout.trim());
60
+ if (data.error) {
61
+ reject(new Error(`Mem0 add failed: ${data.error}`));
62
+ return;
63
+ }
64
+ const results = data.results || [];
65
+ const added = results.filter((r) => r.event === 'ADD' || r.event === 'UPDATE');
66
+ if (added.length === 0 && results.length > 0) {
67
+ console.log(`[Mem0] Memory deduplicated (${results.length} existing matches)`);
88
68
  }
89
69
  }
90
- });
91
- // Send init immediately
92
- proc.stdin.write(initMsg + '\n');
93
- proc.on('close', (code) => {
94
- if (!resolved) {
95
- resolved = true;
96
- clearTimeout(timer);
97
- reject(new Error(`Mem0 process exited (code ${code}) without completing add_memory. stdout: ${stdout.substring(0, 300)}`));
98
- }
99
- });
100
- proc.on('error', (err) => {
101
- if (!resolved) {
102
- resolved = true;
103
- clearTimeout(timer);
104
- reject(err);
70
+ catch {
71
+ // Non-JSON output — might be OK if exit code was 0
72
+ console.warn(`[Mem0] Unexpected output: ${stdout.substring(0, 100)}`);
105
73
  }
74
+ resolve();
106
75
  });
107
76
  });
108
77
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tuna-agent",
3
- "version": "0.1.19",
3
+ "version": "0.1.20",
4
4
  "description": "Tuna Agent - Run AI coding tasks on your machine",
5
5
  "bin": {
6
6
  "tuna-agent": "dist/cli/index.js"