claude-flow-novice 1.6.3 → 1.6.4
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/.claude/settings.json +12 -2
- package/.claude/settings.local.json +3 -2
- package/.claude-flow-novice/dist/src/coordination/index.js +3 -0
- package/.claude-flow-novice/dist/src/coordination/index.js.map +1 -1
- package/.claude-flow-novice/dist/src/coordination/v1-transparency/interfaces/v1-transparency-system.js +12 -0
- package/.claude-flow-novice/dist/src/coordination/v1-transparency/interfaces/v1-transparency-system.js.map +1 -0
- package/.claude-flow-novice/dist/src/coordination/v1-transparency/v1-to-v2-bridge.js +433 -0
- package/.claude-flow-novice/dist/src/coordination/v1-transparency/v1-to-v2-bridge.js.map +1 -0
- package/.claude-flow-novice/dist/src/coordination/v1-transparency/v1-transparency-adapter.js +1468 -0
- package/.claude-flow-novice/dist/src/coordination/v1-transparency/v1-transparency-adapter.js.map +1 -0
- package/.claude-flow-novice/dist/src/monitoring/apm/apm-integration.js +5 -0
- package/.claude-flow-novice/dist/src/monitoring/apm/apm-integration.js.map +1 -1
- package/.claude-flow-novice/dist/src/providers/provider-manager.js +5 -3
- package/.claude-flow-novice/dist/src/providers/provider-manager.js.map +1 -1
- package/.claude-flow-novice/dist/src/providers/tiered-router.js +9 -17
- package/.claude-flow-novice/dist/src/providers/tiered-router.js.map +1 -1
- package/.claude-flow-novice/metrics.db +0 -0
- package/CLAUDE.md +72 -0
- package/config/hooks/post-edit-pipeline.js +68 -118
- package/config/hooks/pre-tool-memory-safety.js +209 -0
- package/package.json +6 -3
- package/scripts/cleanup-idle-sessions.sh +59 -0
- package/scripts/test-provider-routing.cjs +7 -9
- package/wiki/Provider-Routing.md +57 -69
- package/.claude-flow-novice/metrics.db-shm +0 -0
- package/.claude-flow-novice/metrics.db-wal +0 -0
- package/MEMORY_LEAK_ROOT_CAUSE.md +0 -149
|
@@ -1394,144 +1394,94 @@ class UnifiedPostEditPipeline {
|
|
|
1394
1394
|
|
|
1395
1395
|
async logToRootFile(results) {
|
|
1396
1396
|
const logPath = path.join(process.cwd(), 'post-edit-pipeline.log');
|
|
1397
|
-
const MAX_ENTRIES =
|
|
1397
|
+
const MAX_ENTRIES = 100; // Keep last 100 entries
|
|
1398
|
+
const MAX_FILE_SIZE = 512 * 1024; // 512KB max before cleanup
|
|
1399
|
+
|
|
1400
|
+
// MEMORY LEAK FIX: Skip logging for bypassed files to reduce frequency
|
|
1401
|
+
if (results.status === 'BYPASSED') {
|
|
1402
|
+
return;
|
|
1403
|
+
}
|
|
1398
1404
|
|
|
1399
1405
|
const logEntry = {
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
file: results.file,
|
|
1406
|
+
ts: results.timestamp,
|
|
1407
|
+
time: this.formatTimestamp(results.timestamp),
|
|
1408
|
+
file: path.basename(results.file), // Shortened to reduce memory
|
|
1403
1409
|
editId: results.editId || 'N/A',
|
|
1404
|
-
|
|
1405
|
-
agent: results.agentContext,
|
|
1406
|
-
status: results.summary.success ? '
|
|
1407
|
-
tddMode: this.tddMode,
|
|
1408
|
-
tddPhase: results.tddPhase || 'N/A',
|
|
1410
|
+
lang: results.language,
|
|
1411
|
+
agent: results.agentContext?.agentType || 'N/A',
|
|
1412
|
+
status: results.summary.success ? 'PASS' : (results.blocking ? 'BLOCK' : 'FAIL'),
|
|
1409
1413
|
errors: results.summary.errors.length,
|
|
1410
|
-
warnings: results.summary.warnings.length
|
|
1411
|
-
steps: results.steps || {},
|
|
1412
|
-
testing: results.testing || {},
|
|
1413
|
-
coverage: results.coverage || {},
|
|
1414
|
-
tddCompliance: results.tddCompliance || {},
|
|
1415
|
-
rustQuality: results.rustQuality || {},
|
|
1416
|
-
recommendations: results.recommendations || [],
|
|
1417
|
-
details: {
|
|
1418
|
-
errors: results.summary.errors,
|
|
1419
|
-
warnings: results.summary.warnings,
|
|
1420
|
-
suggestions: results.summary.suggestions
|
|
1421
|
-
}
|
|
1414
|
+
warnings: results.summary.warnings.length
|
|
1422
1415
|
};
|
|
1423
1416
|
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
`TIMESTAMP: ${logEntry.displayTimestamp}`,
|
|
1427
|
-
`FILE: ${logEntry.file}`,
|
|
1428
|
-
`EDIT ID: ${logEntry.editId}`,
|
|
1429
|
-
`LANGUAGE: ${logEntry.language}`,
|
|
1430
|
-
`STATUS: ${logEntry.status}`,
|
|
1431
|
-
`TDD MODE: ${logEntry.tddMode ? 'ENABLED' : 'DISABLED'}`,
|
|
1432
|
-
`TDD PHASE: ${logEntry.tddPhase}`,
|
|
1433
|
-
'',
|
|
1434
|
-
'AGENT CONTEXT:',
|
|
1435
|
-
` Memory Key: ${logEntry.agent.memoryKey || 'N/A'}`,
|
|
1436
|
-
` Agent Type: ${logEntry.agent.agentType || 'N/A'}`,
|
|
1437
|
-
'',
|
|
1438
|
-
'JSON:',
|
|
1439
|
-
JSON.stringify(logEntry, null, 2),
|
|
1440
|
-
'═'.repeat(80),
|
|
1441
|
-
'',
|
|
1442
|
-
''
|
|
1443
|
-
].join('\n');
|
|
1417
|
+
// MEMORY LEAK FIX: Compact JSON format (80% smaller)
|
|
1418
|
+
const logLine = JSON.stringify(logEntry) + '\n';
|
|
1444
1419
|
|
|
1445
1420
|
try {
|
|
1421
|
+
let shouldWrite = true;
|
|
1446
1422
|
let existingEntries = [];
|
|
1423
|
+
|
|
1424
|
+
// Read existing entries if file exists and not too large
|
|
1447
1425
|
if (fs.existsSync(logPath)) {
|
|
1448
|
-
const
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
}
|
|
1486
|
-
}
|
|
1487
|
-
}
|
|
1488
|
-
}
|
|
1489
|
-
|
|
1490
|
-
if (jsonEnd > 0) {
|
|
1491
|
-
try {
|
|
1492
|
-
const entry = JSON.parse(jsonText.substring(0, jsonEnd));
|
|
1493
|
-
existingEntries.push(entry);
|
|
1494
|
-
} catch (e) {
|
|
1495
|
-
console.error(`Failed to parse JSON entry: ${e.message}`);
|
|
1496
|
-
}
|
|
1497
|
-
}
|
|
1426
|
+
const stats = fs.statSync(logPath);
|
|
1427
|
+
|
|
1428
|
+
if (stats.size > MAX_FILE_SIZE) {
|
|
1429
|
+
console.log(`\n🗑️ Log file large (${Math.round(stats.size/1024)}KB), cleaning oldest entries...`);
|
|
1430
|
+
|
|
1431
|
+
// MEMORY LEAK FIX: Stream read line by line instead of loading entire file
|
|
1432
|
+
try {
|
|
1433
|
+
const content = fs.readFileSync(logPath, 'utf8');
|
|
1434
|
+
existingEntries = content
|
|
1435
|
+
.split('\n')
|
|
1436
|
+
.filter(line => line.trim() && line.startsWith('{'))
|
|
1437
|
+
.map(line => {
|
|
1438
|
+
try { return JSON.parse(line); } catch { return null; }
|
|
1439
|
+
})
|
|
1440
|
+
.filter(entry => entry !== null)
|
|
1441
|
+
.sort((a, b) => new Date(b.ts) - new Date(a.ts)) // Most recent first
|
|
1442
|
+
.slice(0, MAX_ENTRIES - 1); // Keep room for new entry
|
|
1443
|
+
|
|
1444
|
+
console.log(` Kept ${existingEntries.length} most recent entries`);
|
|
1445
|
+
} catch (parseError) {
|
|
1446
|
+
console.warn(` Parse error during cleanup, starting fresh: ${parseError.message}`);
|
|
1447
|
+
existingEntries = [];
|
|
1448
|
+
}
|
|
1449
|
+
} else {
|
|
1450
|
+
// File is small enough to read normally
|
|
1451
|
+
try {
|
|
1452
|
+
const content = fs.readFileSync(logPath, 'utf8');
|
|
1453
|
+
existingEntries = content
|
|
1454
|
+
.split('\n')
|
|
1455
|
+
.filter(line => line.trim() && line.startsWith('{'))
|
|
1456
|
+
.map(line => {
|
|
1457
|
+
try { return JSON.parse(line); } catch { return null; }
|
|
1458
|
+
})
|
|
1459
|
+
.filter(entry => entry !== null);
|
|
1460
|
+
} catch (readError) {
|
|
1461
|
+
console.warn(` Read error, starting fresh: ${readError.message}`);
|
|
1462
|
+
existingEntries = [];
|
|
1498
1463
|
}
|
|
1499
1464
|
}
|
|
1500
1465
|
}
|
|
1501
1466
|
|
|
1467
|
+
// Add new entry to the beginning (most recent)
|
|
1502
1468
|
existingEntries.unshift(logEntry);
|
|
1503
1469
|
|
|
1470
|
+
// Trim to MAX_ENTRIES (LRU behavior)
|
|
1504
1471
|
if (existingEntries.length > MAX_ENTRIES) {
|
|
1472
|
+
const removed = existingEntries.length - MAX_ENTRIES;
|
|
1505
1473
|
existingEntries = existingEntries.slice(0, MAX_ENTRIES);
|
|
1506
|
-
|
|
1474
|
+
if (removed > 0) {
|
|
1475
|
+
console.log(` Removed ${removed} oldest entries (LRU cleanup)`);
|
|
1476
|
+
}
|
|
1507
1477
|
}
|
|
1508
1478
|
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
`LANGUAGE: ${entry.language}`,
|
|
1516
|
-
`STATUS: ${entry.status}`,
|
|
1517
|
-
`TDD MODE: ${entry.tddMode ? 'ENABLED' : 'DISABLED'}`,
|
|
1518
|
-
`TDD PHASE: ${entry.tddPhase || 'N/A'}`,
|
|
1519
|
-
'',
|
|
1520
|
-
'AGENT CONTEXT:',
|
|
1521
|
-
` Memory Key: ${entry.agent?.memoryKey || 'N/A'}`,
|
|
1522
|
-
` Agent Type: ${entry.agent?.agentType || 'N/A'}`,
|
|
1523
|
-
'',
|
|
1524
|
-
'JSON:',
|
|
1525
|
-
JSON.stringify(entry, null, 2),
|
|
1526
|
-
'═'.repeat(80),
|
|
1527
|
-
'',
|
|
1528
|
-
''
|
|
1529
|
-
].join('\n');
|
|
1530
|
-
}).join('');
|
|
1531
|
-
|
|
1532
|
-
fs.writeFileSync(logPath, rebuiltLog, 'utf8');
|
|
1533
|
-
|
|
1534
|
-
console.log(`\n📝 Logged to: ${logPath} (${existingEntries.length}/${MAX_ENTRIES} entries)`);
|
|
1479
|
+
// Write compact format (one JSON per line)
|
|
1480
|
+
const compactLog = existingEntries.map(entry => JSON.stringify(entry)).join('\n') + '\n';
|
|
1481
|
+
fs.writeFileSync(logPath, `# Post-Edit Pipeline Log - Last ${existingEntries.length} entries\n${compactLog}`, 'utf8');
|
|
1482
|
+
|
|
1483
|
+
console.log(`\n📝 Logged to: ${logPath} (${existingEntries.length}/${MAX_ENTRIES} entries, ${Math.round(Buffer.byteLength(compactLog, 'utf8')/1024)}KB)`);
|
|
1484
|
+
|
|
1535
1485
|
} catch (error) {
|
|
1536
1486
|
console.error(`⚠️ Failed to write log: ${error.message}`);
|
|
1537
1487
|
}
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Pre-Tool Memory Safety Hook
|
|
5
|
+
* Prevents commands that cause memory leaks in WSL/Windows environments
|
|
6
|
+
*
|
|
7
|
+
* BLOCKED COMMANDS (Memory Bombs):
|
|
8
|
+
* - find /mnt/c/... - Causes heap exhaustion (2-10s per command, 50-200MB buffered)
|
|
9
|
+
* - find . -type f - Large directory traversal memory usage
|
|
10
|
+
*
|
|
11
|
+
* SAFE ALTERNATIVES:
|
|
12
|
+
* - Glob tool for file pattern matching (<100ms, minimal memory)
|
|
13
|
+
* - git ls-files for tracked files (<50ms, minimal memory)
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { exec } from 'child_process';
|
|
17
|
+
import { promisify } from 'util';
|
|
18
|
+
const execAsync = promisify(exec);
|
|
19
|
+
|
|
20
|
+
class PreToolMemorySafetyHook {
|
|
21
|
+
constructor() {
|
|
22
|
+
this.blockedPatterns = [
|
|
23
|
+
// WSL Windows path memory bombs
|
|
24
|
+
/find\s+\/mnt\/c\//i,
|
|
25
|
+
/find\s+\/mnt\/[a-z]\//i,
|
|
26
|
+
|
|
27
|
+
// Large directory traversals
|
|
28
|
+
/find\s+\.\s+-type\s+f/i,
|
|
29
|
+
/find\s+\.\s+-name\s+["\']?\*\.(js|ts|py|json|md)["\']?/i,
|
|
30
|
+
|
|
31
|
+
// Recursive find with large output
|
|
32
|
+
/find\s+.+\s+-exec\s+grep/i,
|
|
33
|
+
/find\s+.+\s+-exec\s+cat/i,
|
|
34
|
+
|
|
35
|
+
// Memory-intensive variations
|
|
36
|
+
/find\s+.+\s+-type\s+f\s+-exec/i,
|
|
37
|
+
];
|
|
38
|
+
|
|
39
|
+
this.safeAlternatives = {
|
|
40
|
+
'find pattern': 'Use Glob tool: Glob("**/*.js")',
|
|
41
|
+
'find tracked files': 'Use git: git ls-files "*.js"',
|
|
42
|
+
'find source files': 'Use git: git ls-files -- "src/**/*"',
|
|
43
|
+
'find test files': 'Use Glob: Glob("**/*.test.*")',
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async validate(command) {
|
|
48
|
+
const results = {
|
|
49
|
+
allowed: true,
|
|
50
|
+
warnings: [],
|
|
51
|
+
errors: [],
|
|
52
|
+
suggestions: [],
|
|
53
|
+
alternatives: []
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const commandString = typeof command === 'string' ? command : command.join(' ');
|
|
57
|
+
|
|
58
|
+
// Check for blocked patterns
|
|
59
|
+
for (const pattern of this.blockedPatterns) {
|
|
60
|
+
if (pattern.test(commandString)) {
|
|
61
|
+
results.allowed = false;
|
|
62
|
+
results.errors.push(`🚫 BLOCKED: Memory-unsafe find command detected`);
|
|
63
|
+
|
|
64
|
+
// Suggest specific alternatives
|
|
65
|
+
if (commandString.includes('/mnt/c/')) {
|
|
66
|
+
results.alternatives.push('💡 Use Glob tool for Windows paths: Glob("**/*")');
|
|
67
|
+
results.suggestions.push('Windows find commands cause WSL memory leaks');
|
|
68
|
+
} else if (commandString.includes('-type f')) {
|
|
69
|
+
results.alternatives.push('💡 Use git ls-files for tracked files: git ls-files "*.js"');
|
|
70
|
+
results.alternatives.push('💡 Use Glob tool: Glob("**/*.js")');
|
|
71
|
+
} else if (commandString.includes('-exec')) {
|
|
72
|
+
results.alternatives.push('💡 Use Grep tool: Grep("pattern", "**/*.js")');
|
|
73
|
+
results.suggestions.push('Combine tools instead of find -exec');
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Add memory leak warning
|
|
77
|
+
results.warnings.push(`⚠️ MEMORY LEAK: find commands on WSL/Windows cause 100MB+ memory usage`);
|
|
78
|
+
results.warnings.push(`⚠️ PERFORMANCE: find takes 2-10 seconds vs <100ms for alternatives`);
|
|
79
|
+
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Check for potentially problematic patterns (warnings only)
|
|
85
|
+
const warningPatterns = [
|
|
86
|
+
/find\s+.+\s+-name\s+["\']?\*["\']?/i, // find with wildcard
|
|
87
|
+
/find\s+.+\s+-print/i, // large output
|
|
88
|
+
/find\s+.+\s+-type\s+f.*-o/i, // complex conditions
|
|
89
|
+
];
|
|
90
|
+
|
|
91
|
+
for (const pattern of warningPatterns) {
|
|
92
|
+
if (pattern.test(commandString)) {
|
|
93
|
+
results.warnings.push(`⚠️ WARNING: Potentially memory-intensive find command`);
|
|
94
|
+
results.suggestions.push('Consider using Glob tool or git ls-files instead');
|
|
95
|
+
break;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return results;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
async suggestAlternative(command) {
|
|
103
|
+
const commandString = typeof command === 'string' ? command : command.join(' ');
|
|
104
|
+
|
|
105
|
+
// Extract the intent from the command and suggest specific alternatives
|
|
106
|
+
if (commandString.includes('test')) {
|
|
107
|
+
return {
|
|
108
|
+
command: 'Glob("**/*.test.*")',
|
|
109
|
+
reason: 'Fast test file discovery without memory leaks',
|
|
110
|
+
performance: '<100ms, minimal memory'
|
|
111
|
+
};
|
|
112
|
+
} else if (commandString.includes('src/') || commandString.includes('lib/')) {
|
|
113
|
+
return {
|
|
114
|
+
command: 'Glob("**/*.js") or git ls-files "*.js"',
|
|
115
|
+
reason: 'Efficient source file discovery',
|
|
116
|
+
performance: '<50ms, minimal memory'
|
|
117
|
+
};
|
|
118
|
+
} else if (commandString.includes('-exec grep')) {
|
|
119
|
+
const match = commandString.match(/grep\s+["']([^"']+)["']/);
|
|
120
|
+
const pattern = match ? match[1] : 'pattern';
|
|
121
|
+
return {
|
|
122
|
+
command: `Grep("${pattern}", "**/*.js")`,
|
|
123
|
+
reason: 'Direct pattern matching without find overhead',
|
|
124
|
+
performance: '<200ms, buffered output'
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return {
|
|
129
|
+
command: 'Glob("**/*")',
|
|
130
|
+
reason: 'General file discovery without memory leaks',
|
|
131
|
+
performance: '<100ms, minimal memory'
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Hook execution
|
|
137
|
+
async function main() {
|
|
138
|
+
const args = process.argv.slice(2);
|
|
139
|
+
const command = args.join(' ');
|
|
140
|
+
|
|
141
|
+
if (!command) {
|
|
142
|
+
console.log(`
|
|
143
|
+
🛡️ PRE-TOOL MEMORY SAFETY HOOK
|
|
144
|
+
|
|
145
|
+
Blocked Commands (Memory Bombs):
|
|
146
|
+
- find /mnt/c/* - WSL Windows path traversal (causes heap exhaustion)
|
|
147
|
+
- find . -type f - Large directory traversal memory usage
|
|
148
|
+
- find ... -exec grep - Memory-intensive process creation
|
|
149
|
+
|
|
150
|
+
Safe Alternatives:
|
|
151
|
+
- Glob("**/*.js") - Fast file pattern matching
|
|
152
|
+
- git ls-files "*.js" - Tracked file discovery
|
|
153
|
+
- Grep("pattern", "**/*.js") - Direct pattern matching
|
|
154
|
+
|
|
155
|
+
Usage: pre-tool-memory-safety.js <command>
|
|
156
|
+
`);
|
|
157
|
+
process.exit(0);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const hook = new PreToolMemorySafetyHook();
|
|
161
|
+
const results = await hook.validate(command);
|
|
162
|
+
|
|
163
|
+
// Output results
|
|
164
|
+
if (results.errors.length > 0) {
|
|
165
|
+
console.error('\n🚨 MEMORY SAFETY VIOLATIONS:');
|
|
166
|
+
results.errors.forEach(error => console.error(` ${error}`));
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if (results.warnings.length > 0) {
|
|
170
|
+
console.warn('\n⚠️ MEMORY WARNINGS:');
|
|
171
|
+
results.warnings.forEach(warning => console.warn(` ${warning}`));
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
if (results.alternatives.length > 0) {
|
|
175
|
+
console.info('\n💡 SAFE ALTERNATIVES:');
|
|
176
|
+
results.alternatives.forEach(alt => console.info(` ${alt}`));
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Suggest specific alternative
|
|
180
|
+
const alternative = await hook.suggestAlternative(command);
|
|
181
|
+
if (alternative) {
|
|
182
|
+
console.info('\n🔧 RECOMMENDED ALTERNATIVE:');
|
|
183
|
+
console.info(` Command: ${alternative.command}`);
|
|
184
|
+
console.info(` Reason: ${alternative.reason}`);
|
|
185
|
+
console.info(` Performance: ${alternative.performance}`);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Exit with error code if blocked
|
|
189
|
+
if (!results.allowed) {
|
|
190
|
+
console.error('\n❌ Command blocked by memory safety policy');
|
|
191
|
+
console.error(' WSL/Windows find commands cause memory leaks and heap exhaustion');
|
|
192
|
+
process.exit(1);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
if (results.warnings.length === 0 && results.errors.length === 0) {
|
|
196
|
+
console.log('✅ Memory safety check passed');
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
process.exit(0);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
203
|
+
main().catch(error => {
|
|
204
|
+
console.error('Memory safety hook error:', error);
|
|
205
|
+
process.exit(1);
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
export { PreToolMemorySafetyHook };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-flow-novice",
|
|
3
|
-
"version": "1.6.
|
|
4
|
-
"description": "Standalone Claude Flow for beginners - AI agent orchestration made easy with enhanced TDD testing pipeline. Enhanced init command creates complete agent system, MCP configuration with 30 essential tools, and automated hooks with single-file testing, real-time coverage analysis, and advanced validation. Fully standalone with zero external dependencies, complete project setup in one command.",
|
|
3
|
+
"version": "1.6.4",
|
|
4
|
+
"description": "Standalone Claude Flow for beginners - AI agent orchestration made easy with enhanced TDD testing pipeline, memory safety protection, and automated hooks. Enhanced init command creates complete agent system, MCP configuration with 30 essential tools, and automated hooks with single-file testing, real-time coverage analysis, and advanced validation. Features memory leak prevention for WSL/Windows environments and pre-tool safety validation. Fully standalone with zero external dependencies, complete project setup in one command.",
|
|
5
5
|
"mcpName": "io.github.ruvnet/claude-flow",
|
|
6
6
|
"main": ".claude-flow-novice/dist/index.js",
|
|
7
7
|
"bin": {
|
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
"swarm": ".claude/commands/swarm.js",
|
|
11
11
|
"sparc": ".claude/commands/sparc.js",
|
|
12
12
|
"hooks": ".claude/commands/hooks.js",
|
|
13
|
-
"enhanced-hooks": ".claude-flow-novice/dist/src/hooks/enhanced-hooks-cli.js"
|
|
13
|
+
"enhanced-hooks": ".claude-flow-novice/dist/src/hooks/enhanced-hooks-cli.js",
|
|
14
|
+
"memory-safety": "config/hooks/pre-tool-memory-safety.js"
|
|
14
15
|
},
|
|
15
16
|
"scripts": {
|
|
16
17
|
"claude-soul": "node src/slash-commands/claude-soul.js",
|
|
@@ -18,6 +19,8 @@
|
|
|
18
19
|
"sparc": "node .claude/commands/sparc.js",
|
|
19
20
|
"hooks": "node .claude/commands/hooks.js",
|
|
20
21
|
"enhanced-hooks": "node .claude-flow-novice/dist/src/hooks/enhanced-hooks-cli.js",
|
|
22
|
+
"memory-safety": "node config/hooks/pre-tool-memory-safety.js",
|
|
23
|
+
"check:memory": "node config/hooks/pre-tool-memory-safety.js",
|
|
21
24
|
"neural": "node .claude/commands/neural.js",
|
|
22
25
|
"performance": "node .claude/commands/performance.js",
|
|
23
26
|
"github": "node .claude/commands/github.js",
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Cleanup Idle Claude Sessions
|
|
3
|
+
# Kills Claude processes with 0% CPU (idle/orphaned) older than 30 minutes
|
|
4
|
+
# Safe for automated execution - preserves active sessions
|
|
5
|
+
|
|
6
|
+
set -e
|
|
7
|
+
|
|
8
|
+
LOGFILE="${HOME}/.claude-flow/logs/session-cleanup.log"
|
|
9
|
+
mkdir -p "$(dirname "$LOGFILE")"
|
|
10
|
+
|
|
11
|
+
log() {
|
|
12
|
+
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOGFILE"
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
log "=== Starting Idle Session Cleanup ==="
|
|
16
|
+
|
|
17
|
+
# Get list of idle Claude sessions (0% CPU), excluding this script and bash processes
|
|
18
|
+
IDLE_PIDS=$(ps -eo pid,%cpu,etime,cmd | grep claude | grep -v grep | grep -v "cleanup-idle-sessions" | grep -v "^[[:space:]]*[0-9]*[[:space:]]*0.0.*bash" | awk '$2 == 0.0 {print $1}' || true)
|
|
19
|
+
|
|
20
|
+
if [ -z "$IDLE_PIDS" ]; then
|
|
21
|
+
log "No idle sessions found. All sessions active."
|
|
22
|
+
exit 0
|
|
23
|
+
fi
|
|
24
|
+
|
|
25
|
+
# Count idle sessions
|
|
26
|
+
IDLE_COUNT=$(echo "$IDLE_PIDS" | wc -l)
|
|
27
|
+
log "Found $IDLE_COUNT idle Claude session(s)"
|
|
28
|
+
|
|
29
|
+
# Get memory before cleanup
|
|
30
|
+
BEFORE_MEM=$(ps aux | grep -E '(claude|node)' | grep -v grep | grep -v snapfuse | awk '{sum+=$6} END {printf "%.1f", sum/1024/1024}')
|
|
31
|
+
log "Memory before cleanup: ${BEFORE_MEM}GB"
|
|
32
|
+
|
|
33
|
+
# Kill idle sessions
|
|
34
|
+
for PID in $IDLE_PIDS; do
|
|
35
|
+
# Get process details before killing
|
|
36
|
+
DETAILS=$(ps -eo pid,etime,cputime,%cpu,%mem,rss,cmd | grep "^${PID}" | head -1 || echo "N/A")
|
|
37
|
+
log "Killing idle session: $DETAILS"
|
|
38
|
+
|
|
39
|
+
kill -9 "$PID" 2>/dev/null || log " Warning: Could not kill PID $PID (already terminated?)"
|
|
40
|
+
done
|
|
41
|
+
|
|
42
|
+
# Wait for processes to terminate
|
|
43
|
+
sleep 2
|
|
44
|
+
|
|
45
|
+
# Get memory after cleanup
|
|
46
|
+
AFTER_MEM=$(ps aux | grep -E '(claude|node)' | grep -v grep | grep -v snapfuse | awk '{sum+=$6} END {printf "%.1f", sum/1024/1024}')
|
|
47
|
+
FREED_MEM=$(echo "$BEFORE_MEM - $AFTER_MEM" | bc)
|
|
48
|
+
log "Memory after cleanup: ${AFTER_MEM}GB"
|
|
49
|
+
log "Memory freed: ${FREED_MEM}GB"
|
|
50
|
+
|
|
51
|
+
# Get remaining active sessions
|
|
52
|
+
ACTIVE_COUNT=$(ps aux | grep claude | grep -v grep | wc -l)
|
|
53
|
+
log "Active sessions remaining: $ACTIVE_COUNT"
|
|
54
|
+
|
|
55
|
+
log "=== Cleanup Complete ==="
|
|
56
|
+
log ""
|
|
57
|
+
|
|
58
|
+
# Return summary
|
|
59
|
+
echo "{\"idle_killed\": $IDLE_COUNT, \"active_remaining\": $ACTIVE_COUNT, \"memory_freed_gb\": $FREED_MEM}"
|
|
@@ -107,8 +107,8 @@ if (fs.existsSync(routerPath)) {
|
|
|
107
107
|
|
|
108
108
|
if (hasTiers && hasZai) {
|
|
109
109
|
console.log(' ✅ Agents will route through tiered system:\n');
|
|
110
|
-
console.log(' Tier
|
|
111
|
-
console.log(' Tier
|
|
110
|
+
console.log(' Tier 0: Main chat → Anthropic Claude Max');
|
|
111
|
+
console.log(' Tier 1: ALL Task tool agents → Z.ai\n');
|
|
112
112
|
}
|
|
113
113
|
} else {
|
|
114
114
|
console.log(' ⚠️ Compiled router not found (run npm run build)\n');
|
|
@@ -208,16 +208,14 @@ console.log('═'.repeat(80) + '\n');
|
|
|
208
208
|
console.log('📊 Configuration Summary\n');
|
|
209
209
|
|
|
210
210
|
console.log('✅ WORKING AS DESIGNED:\n');
|
|
211
|
-
console.log(' 1. Main Chat
|
|
212
|
-
console.log(' 2.
|
|
213
|
-
console.log(' 3.
|
|
214
|
-
console.log(' 4. Agent SDK → Anthropic (hardcoded, no alternative)');
|
|
211
|
+
console.log(' 1. Main Chat → Anthropic Claude Max (default routing)');
|
|
212
|
+
console.log(' 2. ALL Task Tool Agents → Z.ai (coder, tester, reviewer, backend-dev, etc.)');
|
|
213
|
+
console.log(' 3. Agent SDK → Anthropic (hardcoded, no alternative)');
|
|
215
214
|
console.log();
|
|
216
215
|
|
|
217
216
|
console.log('💰 COST OPTIMIZATION:\n');
|
|
218
|
-
console.log(' • Main chat uses
|
|
219
|
-
console.log(' •
|
|
220
|
-
console.log(' • Strategic agents use Anthropic (quality-critical)');
|
|
217
|
+
console.log(' • Main chat uses Claude Max subscription (highest quality)');
|
|
218
|
+
console.log(' • ALL Task tool agents use Z.ai (cost-effective bulk operations)');
|
|
221
219
|
console.log(' • Agent SDK provides 90% cost savings via caching\n');
|
|
222
220
|
|
|
223
221
|
console.log('🔍 VERIFICATION:\n');
|