tuna-agent 0.1.21 → 0.1.23
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/agents/claude-code-adapter.js +24 -20
- package/dist/mcp/setup.d.ts +6 -0
- package/dist/mcp/setup.js +68 -1
- package/package.json +1 -1
|
@@ -671,29 +671,33 @@ export class ClaudeCodeAdapter {
|
|
|
671
671
|
const MIN_DESCRIPTION_LENGTH = 20;
|
|
672
672
|
if (task.description.length < MIN_DESCRIPTION_LENGTH)
|
|
673
673
|
return;
|
|
674
|
-
const taskContext = task.description.substring(0, 150);
|
|
675
|
-
const resultContext = resultSummary.substring(0, 200);
|
|
676
|
-
const statusLabel = status === 'done' ? 'COMPLETED' : 'FAILED';
|
|
677
|
-
// Structured reflection: what was asked, what happened, what to remember
|
|
678
|
-
const parts = [];
|
|
679
|
-
if (status === 'failed') {
|
|
680
|
-
parts.push(`[TASK FAILED] "${taskContext}"`);
|
|
681
|
-
parts.push(`Error: ${resultContext}`);
|
|
682
|
-
parts.push(`Lesson: This type of task failed — review approach next time`);
|
|
683
|
-
}
|
|
684
|
-
else {
|
|
685
|
-
parts.push(`[TASK ${statusLabel}] "${taskContext}"`);
|
|
686
|
-
parts.push(`Result: ${resultContext}`);
|
|
687
|
-
}
|
|
688
|
-
const memoryText = parts.join('. ');
|
|
689
674
|
try {
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
await
|
|
693
|
-
|
|
675
|
+
// Step 1: Generate AI-powered reflection via Ollama
|
|
676
|
+
console.log(`[Reflection] Generating AI reflection for task ${task.id} (${status})`);
|
|
677
|
+
const { callMem0Reflect, callMem0AddMemory } = await import('../mcp/setup.js');
|
|
678
|
+
const aiReflection = await callMem0Reflect(task.description, resultSummary, status);
|
|
679
|
+
if (!aiReflection) {
|
|
680
|
+
console.log(`[Reflection] No meaningful lesson — skipping storage for task ${task.id}`);
|
|
681
|
+
return;
|
|
682
|
+
}
|
|
683
|
+
// Step 2: Store the AI-generated reflection in Mem0
|
|
684
|
+
console.log(`[Reflection] Storing: "${aiReflection.substring(0, 100)}..."`);
|
|
685
|
+
await callMem0AddMemory(aiReflection, this.agentConfig.name);
|
|
686
|
+
console.log(`[Reflection] Stored for task ${task.id}`);
|
|
694
687
|
}
|
|
695
688
|
catch (err) {
|
|
696
|
-
|
|
689
|
+
// Fallback: store basic reflection if AI reflection fails
|
|
690
|
+
console.warn(`[Reflection] AI reflection failed, using fallback for task ${task.id}:`, err instanceof Error ? err.message : err);
|
|
691
|
+
try {
|
|
692
|
+
const fallback = status === 'failed'
|
|
693
|
+
? `Task failed: "${task.description.substring(0, 150)}". Error: ${resultSummary.substring(0, 200)}`
|
|
694
|
+
: `Task completed: "${task.description.substring(0, 150)}". Result: ${resultSummary.substring(0, 200)}`;
|
|
695
|
+
const { callMem0AddMemory } = await import('../mcp/setup.js');
|
|
696
|
+
await callMem0AddMemory(fallback, this.agentConfig.name);
|
|
697
|
+
}
|
|
698
|
+
catch {
|
|
699
|
+
// Both AI and fallback failed — give up silently
|
|
700
|
+
}
|
|
697
701
|
}
|
|
698
702
|
}
|
|
699
703
|
/**
|
package/dist/mcp/setup.d.ts
CHANGED
|
@@ -9,6 +9,12 @@ export declare function callMem0AddMemory(text: string, agentName: string): Prom
|
|
|
9
9
|
* Returns array of memory texts sorted by relevance.
|
|
10
10
|
*/
|
|
11
11
|
export declare function callMem0SearchMemory(query: string, agentName: string, limit?: number): Promise<string[]>;
|
|
12
|
+
/**
|
|
13
|
+
* Generate AI-powered reflection from task results using Ollama.
|
|
14
|
+
* Calls mem0-reflect script on relabs01 via SSH.
|
|
15
|
+
* Returns a concise lesson learned, or empty string if nothing meaningful.
|
|
16
|
+
*/
|
|
17
|
+
export declare function callMem0Reflect(taskDesc: string, resultSummary: string, status: 'done' | 'failed'): Promise<string>;
|
|
12
18
|
/**
|
|
13
19
|
* Generate MCP server config file for Claude Code.
|
|
14
20
|
* This file is auto-detected by runClaude and passed via --mcp-config.
|
package/dist/mcp/setup.js
CHANGED
|
@@ -110,7 +110,13 @@ export async function callMem0SearchMemory(query, agentName, limit = 5) {
|
|
|
110
110
|
try {
|
|
111
111
|
const data = JSON.parse(stdout.trim());
|
|
112
112
|
const results = (data.results || []);
|
|
113
|
-
|
|
113
|
+
// Only keep memories with relevance score >= 0.6
|
|
114
|
+
const relevant = results.filter(r => r.score >= 0.6);
|
|
115
|
+
if (relevant.length > 0) {
|
|
116
|
+
console.log(`[Mem0 Search] ${relevant.length}/${results.length} memories above threshold (scores: ${relevant.map(r => r.score.toFixed(2)).join(', ')})`);
|
|
117
|
+
relevant.forEach((r, i) => console.log(`[Mem0 Search] ${i + 1}. [${r.score.toFixed(2)}] ${r.text.substring(0, 100)}`));
|
|
118
|
+
}
|
|
119
|
+
resolve(relevant.map(r => r.text));
|
|
114
120
|
}
|
|
115
121
|
catch {
|
|
116
122
|
resolve([]);
|
|
@@ -118,6 +124,67 @@ export async function callMem0SearchMemory(query, agentName, limit = 5) {
|
|
|
118
124
|
});
|
|
119
125
|
});
|
|
120
126
|
}
|
|
127
|
+
/**
|
|
128
|
+
* Generate AI-powered reflection from task results using Ollama.
|
|
129
|
+
* Calls mem0-reflect script on relabs01 via SSH.
|
|
130
|
+
* Returns a concise lesson learned, or empty string if nothing meaningful.
|
|
131
|
+
*/
|
|
132
|
+
export async function callMem0Reflect(taskDesc, resultSummary, status) {
|
|
133
|
+
if (!MEM0_SSH_HOST)
|
|
134
|
+
return '';
|
|
135
|
+
const { execFile } = await import('child_process');
|
|
136
|
+
const input = JSON.stringify({
|
|
137
|
+
task: taskDesc.substring(0, 300),
|
|
138
|
+
result: resultSummary.substring(0, 500),
|
|
139
|
+
status,
|
|
140
|
+
});
|
|
141
|
+
return new Promise((resolve) => {
|
|
142
|
+
let cmd;
|
|
143
|
+
let args;
|
|
144
|
+
let options = {};
|
|
145
|
+
if (MEM0_SSH_HOST === 'local') {
|
|
146
|
+
cmd = 'mem0-reflect';
|
|
147
|
+
args = [];
|
|
148
|
+
options.env = { ...process.env };
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
cmd = 'ssh';
|
|
152
|
+
args = ['-p', MEM0_SSH_PORT, '-o', 'StrictHostKeyChecking=no'];
|
|
153
|
+
if (MEM0_SSH_KEY)
|
|
154
|
+
args.push('-i', MEM0_SSH_KEY);
|
|
155
|
+
args.push(MEM0_SSH_HOST, 'mem0-reflect');
|
|
156
|
+
}
|
|
157
|
+
const child = execFile(cmd, args, { ...options, timeout: 90000 }, (err, stdout) => {
|
|
158
|
+
if (err) {
|
|
159
|
+
console.warn(`[Mem0 Reflect] Failed: ${err.message}`);
|
|
160
|
+
resolve('');
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
try {
|
|
164
|
+
const data = JSON.parse(stdout.trim());
|
|
165
|
+
if (data.error) {
|
|
166
|
+
console.warn(`[Mem0 Reflect] Error: ${data.error}`);
|
|
167
|
+
resolve('');
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
if (data.skipped) {
|
|
171
|
+
console.log(`[Mem0 Reflect] Skipped — nothing meaningful to learn`);
|
|
172
|
+
resolve('');
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
// Clean up: remove trailing SKIP if LLM appended it
|
|
176
|
+
let reflection = (data.reflection || '').replace(/\s*SKIP\s*$/i, '').trim();
|
|
177
|
+
resolve(reflection);
|
|
178
|
+
}
|
|
179
|
+
catch {
|
|
180
|
+
resolve('');
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
// Send input via stdin
|
|
184
|
+
child.stdin?.write(input);
|
|
185
|
+
child.stdin?.end();
|
|
186
|
+
});
|
|
187
|
+
}
|
|
121
188
|
/**
|
|
122
189
|
* Build Mem0 MCP server config for an agent.
|
|
123
190
|
* - MEM0_SSH_HOST="local": run mem0-mcp directly (Mem0 infra on same machine)
|