tuna-agent 0.1.72 → 0.1.74
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.
|
@@ -33,11 +33,6 @@ export declare class ClaudeCodeAdapter implements AgentAdapter {
|
|
|
33
33
|
private metricsMap;
|
|
34
34
|
private learnedRulesMap;
|
|
35
35
|
private agentFolderMap;
|
|
36
|
-
private currentAgentId;
|
|
37
|
-
/** Folder basename of current agent (e.g. "co-founder"). Used as Mem0 user_id. */
|
|
38
|
-
private currentAgentName;
|
|
39
|
-
/** Returns metrics for the currently active agent, initializing if needed. */
|
|
40
|
-
private get metrics();
|
|
41
36
|
/** Returns metrics for a specific agent by ID (safe for parallel execution). */
|
|
42
37
|
getMetricsForAgent(agentId: string): AgentMetrics;
|
|
43
38
|
constructor(config: AgentConfig);
|
|
@@ -79,14 +74,14 @@ export declare class ClaudeCodeAdapter implements AgentAdapter {
|
|
|
79
74
|
private static extractKeyPhrases;
|
|
80
75
|
/** Check if two rules are semantically similar (>40% key phrase overlap). */
|
|
81
76
|
private static isSimilarRule;
|
|
82
|
-
runSelfImprovement(cwd: string, agentId
|
|
77
|
+
runSelfImprovement(cwd: string, agentId: string): Promise<void>;
|
|
83
78
|
/**
|
|
84
79
|
* Parse "## Learned Rules" section from CLAUDE.md and store in learnedRulesMap.
|
|
85
80
|
* Rule format: `- Rule text (confidence: 0.7)`
|
|
86
81
|
*/
|
|
87
82
|
private parseLearnedRules;
|
|
88
83
|
/** Track task completion metrics (public for daemon resume path). */
|
|
89
|
-
trackMetricsPublic(status: 'done' | 'failed', durationMs: number, agentId
|
|
84
|
+
trackMetricsPublic(status: 'done' | 'failed', durationMs: number, agentId: string): void;
|
|
90
85
|
/** Track task completion metrics. */
|
|
91
86
|
private trackMetrics;
|
|
92
87
|
dispose(): Promise<void>;
|
|
@@ -18,13 +18,6 @@ export class ClaudeCodeAdapter {
|
|
|
18
18
|
metricsMap = new Map();
|
|
19
19
|
learnedRulesMap = new Map();
|
|
20
20
|
agentFolderMap = new Map(); // agentId -> folder path
|
|
21
|
-
currentAgentId = '';
|
|
22
|
-
/** Folder basename of current agent (e.g. "co-founder"). Used as Mem0 user_id. */
|
|
23
|
-
currentAgentName = '';
|
|
24
|
-
/** Returns metrics for the currently active agent, initializing if needed. */
|
|
25
|
-
get metrics() {
|
|
26
|
-
return this.getMetricsForAgent(this.currentAgentId);
|
|
27
|
-
}
|
|
28
21
|
/** Returns metrics for a specific agent by ID (safe for parallel execution). */
|
|
29
22
|
getMetricsForAgent(agentId) {
|
|
30
23
|
if (!this.metricsMap.has(agentId)) {
|
|
@@ -65,10 +58,7 @@ export class ClaudeCodeAdapter {
|
|
|
65
58
|
getMetrics() {
|
|
66
59
|
// Re-parse rules from CLAUDE.md for all known agents
|
|
67
60
|
this.agentFolderMap.forEach((folder, agentId) => {
|
|
68
|
-
|
|
69
|
-
this.currentAgentId = agentId;
|
|
70
|
-
this.parseLearnedRules(ClaudeCodeAdapter.resolveClaudeMdPath(folder));
|
|
71
|
-
this.currentAgentId = savedId;
|
|
61
|
+
this.parseLearnedRules(ClaudeCodeAdapter.resolveClaudeMdPath(folder), agentId);
|
|
72
62
|
});
|
|
73
63
|
const agentMetricsMap = {};
|
|
74
64
|
// Include agents from metricsMap
|
|
@@ -103,12 +93,10 @@ export class ClaudeCodeAdapter {
|
|
|
103
93
|
try {
|
|
104
94
|
const count = await fetchMem0Count(agentName);
|
|
105
95
|
if (count > 0) {
|
|
106
|
-
const
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
this.metrics.memoryCount = count;
|
|
96
|
+
const m = this.getMetricsForAgent(agentId);
|
|
97
|
+
if (count > m.memoryCount) {
|
|
98
|
+
m.memoryCount = count;
|
|
110
99
|
}
|
|
111
|
-
this.currentAgentId = savedId;
|
|
112
100
|
console.log(`[Metrics] Seeded memoryCount=${count} for "${agentName}"`);
|
|
113
101
|
}
|
|
114
102
|
}
|
|
@@ -149,13 +137,10 @@ export class ClaudeCodeAdapter {
|
|
|
149
137
|
: undefined;
|
|
150
138
|
// Default mode: direct chat with Claude CLI (no PM layer)
|
|
151
139
|
// Only use PM planning when mode is explicitly 'tuna'
|
|
152
|
-
// Capture agent context as LOCAL variables
|
|
140
|
+
// Capture agent context as LOCAL variables — no shared mutable state
|
|
153
141
|
const localAgentId = task.agentId || '';
|
|
154
142
|
const defaultWorkspaceEarly = path.join(os.homedir(), 'tuna-workspace');
|
|
155
143
|
const localAgentName = path.basename(task.repoPath || defaultWorkspaceEarly);
|
|
156
|
-
// Also set instance vars for backward compat (metrics getter, heartbeat, etc.)
|
|
157
|
-
this.currentAgentId = localAgentId;
|
|
158
|
-
this.currentAgentName = localAgentName;
|
|
159
144
|
// Track agent folder for rules parsing in heartbeat
|
|
160
145
|
const cwd = task.repoPath || defaultWorkspaceEarly;
|
|
161
146
|
this.agentFolderMap.set(localAgentId, cwd);
|
|
@@ -396,7 +381,7 @@ export class ClaudeCodeAdapter {
|
|
|
396
381
|
this.trackMetrics('done', totalDurationMs, localAgentId);
|
|
397
382
|
const timeoutOutput = lastTaskOutput || 'Task completed (no follow-up)';
|
|
398
383
|
this.runReflection(task, timeoutOutput, 'done', task.repoPath)
|
|
399
|
-
.then(() => this.runSelfImprovement(task.repoPath,
|
|
384
|
+
.then(() => this.runSelfImprovement(task.repoPath, localAgentId))
|
|
400
385
|
.catch(() => { });
|
|
401
386
|
return;
|
|
402
387
|
}
|
|
@@ -431,7 +416,7 @@ export class ClaudeCodeAdapter {
|
|
|
431
416
|
console.log(`[ClaudeCode] Agent Team task ${task.id} completed (${(totalDurationMs / 1000).toFixed(1)}s)`);
|
|
432
417
|
// Post-task reflection with actual output (non-blocking)
|
|
433
418
|
this.runReflection(task, lastTaskOutput || 'Task completed without text output', 'done', task.repoPath)
|
|
434
|
-
.then(() => this.runSelfImprovement(task.repoPath,
|
|
419
|
+
.then(() => this.runSelfImprovement(task.repoPath, localAgentId))
|
|
435
420
|
.catch(() => { });
|
|
436
421
|
}
|
|
437
422
|
finally {
|
|
@@ -824,9 +809,8 @@ export class ClaudeCodeAdapter {
|
|
|
824
809
|
const MIN_DESCRIPTION_LENGTH = 20;
|
|
825
810
|
if (task.description.length < MIN_DESCRIPTION_LENGTH)
|
|
826
811
|
return;
|
|
827
|
-
|
|
828
|
-
const
|
|
829
|
-
const agentId = task.agentId || this.currentAgentId;
|
|
812
|
+
const agentName = path.basename(cwd);
|
|
813
|
+
const agentId = task.agentId || '';
|
|
830
814
|
try {
|
|
831
815
|
// Step 1: Generate AI-powered reflection via Ollama
|
|
832
816
|
console.log(`[Reflection] Generating AI reflection for task ${task.id} (${status}), input: ${resultSummary.substring(0, 150)}...`);
|
|
@@ -877,7 +861,7 @@ export class ClaudeCodeAdapter {
|
|
|
877
861
|
try {
|
|
878
862
|
console.log(`[Rating→Mem0] Storing rating for task "${data.taskTitle}" (${data.score > 0 ? '👍' : '👎'})`);
|
|
879
863
|
const { callMem0AddMemory } = await import('../mcp/setup.js');
|
|
880
|
-
const agentName = path.basename(data.cwd)
|
|
864
|
+
const agentName = path.basename(data.cwd);
|
|
881
865
|
await callMem0AddMemory(memoryText, agentName);
|
|
882
866
|
console.log(`[Rating→Mem0] Rating stored successfully`);
|
|
883
867
|
}
|
|
@@ -916,7 +900,7 @@ export class ClaudeCodeAdapter {
|
|
|
916
900
|
try {
|
|
917
901
|
console.log(`[Self-Improve] Running pattern detection (every ${ClaudeCodeAdapter.PATTERN_CHECK_INTERVAL} tasks, count=${this.taskCount})`);
|
|
918
902
|
const { callMem0Patterns } = await import('../mcp/setup.js');
|
|
919
|
-
const agentName = path.basename(cwd)
|
|
903
|
+
const agentName = path.basename(cwd);
|
|
920
904
|
const patterns = await callMem0Patterns(agentName, 2);
|
|
921
905
|
if (patterns.length === 0) {
|
|
922
906
|
console.log(`[Self-Improve] No patterns detected yet`);
|
|
@@ -986,10 +970,11 @@ export class ClaudeCodeAdapter {
|
|
|
986
970
|
const separator = existingContent.endsWith('\n') ? '\n' : '\n\n';
|
|
987
971
|
fs.writeFileSync(claudeMdPath, existingContent + separator + `${SECTION_HEADER}\n${rulesBlock}\n`);
|
|
988
972
|
}
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
973
|
+
const m = this.getMetricsForAgent(agentId);
|
|
974
|
+
m.patternsLearnedCount += toAdd.length;
|
|
975
|
+
m.rulesCount += toAdd.length;
|
|
976
|
+
m.lastPatternAt = new Date().toISOString();
|
|
977
|
+
m.latestLearnedRule = toAdd[toAdd.length - 1].rule.substring(0, 500);
|
|
993
978
|
console.log(`[Self-Improve] Added ${toAdd.length} new rules to CLAUDE.md:`);
|
|
994
979
|
toAdd.forEach(p => console.log(`[Self-Improve] - ${p.rule}`));
|
|
995
980
|
// Sync learned rules to heartbeat metrics
|
|
@@ -1048,9 +1033,8 @@ export class ClaudeCodeAdapter {
|
|
|
1048
1033
|
});
|
|
1049
1034
|
}
|
|
1050
1035
|
if (rules.length > 0) {
|
|
1051
|
-
|
|
1052
|
-
this.
|
|
1053
|
-
this.getMetricsForAgent(resolvedAgentId).rulesCount = rules.length;
|
|
1036
|
+
this.learnedRulesMap.set(agentId, rules);
|
|
1037
|
+
this.getMetricsForAgent(agentId).rulesCount = rules.length;
|
|
1054
1038
|
console.log(`[Self-Improve] Parsed ${rules.length} rules from CLAUDE.md for heartbeat sync`);
|
|
1055
1039
|
}
|
|
1056
1040
|
}
|
|
@@ -1064,7 +1048,7 @@ export class ClaudeCodeAdapter {
|
|
|
1064
1048
|
}
|
|
1065
1049
|
/** Track task completion metrics. */
|
|
1066
1050
|
trackMetrics(status, durationMs, agentId) {
|
|
1067
|
-
const m =
|
|
1051
|
+
const m = this.getMetricsForAgent(agentId);
|
|
1068
1052
|
m.taskCount++;
|
|
1069
1053
|
if (status === 'done')
|
|
1070
1054
|
m.successCount++;
|
package/dist/daemon/index.js
CHANGED
|
@@ -778,7 +778,7 @@ ${skillContent.slice(0, 15000)}`;
|
|
|
778
778
|
outputFormat: 'stream-json',
|
|
779
779
|
includePartialMessages: true,
|
|
780
780
|
agentTeam: true,
|
|
781
|
-
maxTurns:
|
|
781
|
+
maxTurns: 200,
|
|
782
782
|
resumeSessionId: sessionId,
|
|
783
783
|
signal: abort.signal,
|
|
784
784
|
inputFiles: currentInputFiles,
|
|
@@ -813,6 +813,24 @@ ${skillContent.slice(0, 15000)}`;
|
|
|
813
813
|
if (data.type === 'system' && data.subtype === 'init') {
|
|
814
814
|
sessionId = data.session_id;
|
|
815
815
|
}
|
|
816
|
+
// Patch missing stream chunks from assistant message (same as handleTask)
|
|
817
|
+
if (data.type === 'assistant' && data.message) {
|
|
818
|
+
const msg = data.message;
|
|
819
|
+
const content = msg.content;
|
|
820
|
+
if (content) {
|
|
821
|
+
const fullText = content
|
|
822
|
+
.filter(b => b.type === 'text' && b.text)
|
|
823
|
+
.map(b => b.text)
|
|
824
|
+
.join('');
|
|
825
|
+
if (fullText && fullText.length > turnAccumulatedText.length) {
|
|
826
|
+
const missed = fullText.slice(turnAccumulatedText.length);
|
|
827
|
+
if (missed.length > 0) {
|
|
828
|
+
turnAccumulatedText = fullText;
|
|
829
|
+
wsClient.sendPMStream(taskId, missed);
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
}
|
|
816
834
|
},
|
|
817
835
|
});
|
|
818
836
|
wsClient.sendPMStreamEnd(taskId, streamMsgId);
|
|
@@ -867,8 +885,8 @@ ${skillContent.slice(0, 15000)}`;
|
|
|
867
885
|
// Track metrics + reflection on the adapter
|
|
868
886
|
if (adapter.type === 'claude-code') {
|
|
869
887
|
const ccAdapter = adapter;
|
|
870
|
-
ccAdapter.trackMetricsPublic('done', totalDurationMs,
|
|
871
|
-
ccAdapter.runReflection({ id: taskId, description: firstMessage, repoPath: cwd, enableReflection: true }, lastResumeOutput || 'Task completed (no follow-up)', 'done', cwd).then(() => ccAdapter.runSelfImprovement(cwd)).catch(() => { });
|
|
888
|
+
ccAdapter.trackMetricsPublic('done', totalDurationMs, agentId);
|
|
889
|
+
ccAdapter.runReflection({ id: taskId, description: firstMessage, repoPath: cwd, enableReflection: true }, lastResumeOutput || 'Task completed (no follow-up)', 'done', cwd).then(() => ccAdapter.runSelfImprovement(cwd, agentId)).catch(() => { });
|
|
872
890
|
}
|
|
873
891
|
return;
|
|
874
892
|
}
|