claude-flow 3.5.3 → 3.5.5
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/helpers/README.md +1 -1
- package/.claude/helpers/adr-compliance.sh +1 -1
- package/.claude/helpers/auto-memory-hook.mjs +20 -7
- package/.claude/helpers/daemon-manager.sh +3 -3
- package/.claude/helpers/ddd-tracker.sh +1 -1
- package/.claude/helpers/guidance-hooks.sh +1 -1
- package/.claude/helpers/health-monitor.sh +1 -1
- package/.claude/helpers/hook-handler.cjs +40 -11
- package/.claude/helpers/learning-hooks.sh +2 -2
- package/.claude/helpers/learning-optimizer.sh +1 -1
- package/.claude/helpers/learning-service.mjs +2 -2
- package/.claude/helpers/metrics-db.mjs +1 -1
- package/.claude/helpers/pattern-consolidator.sh +1 -1
- package/.claude/helpers/perf-worker.sh +1 -1
- package/.claude/helpers/security-scanner.sh +1 -1
- package/.claude/helpers/swarm-comms.sh +2 -2
- package/.claude/helpers/swarm-hooks.sh +2 -2
- package/.claude/helpers/swarm-monitor.sh +2 -2
- package/.claude/helpers/sync-v3-metrics.sh +1 -1
- package/.claude/helpers/v3-quick-status.sh +1 -1
- package/.claude/helpers/v3.sh +1 -1
- package/.claude/helpers/validate-v3-config.sh +1 -1
- package/.claude/helpers/worker-manager.sh +3 -3
- package/.claude/statusline.sh +2 -2
- package/package.json +1 -1
- package/v3/@claude-flow/cli/dist/src/commands/doctor.js +6 -1
- package/v3/@claude-flow/cli/dist/src/commands/mcp.js +18 -3
- package/v3/@claude-flow/cli/dist/src/commands/status.js +9 -2
- package/v3/@claude-flow/cli/dist/src/index.d.ts +1 -1
- package/v3/@claude-flow/cli/dist/src/index.js +1 -1
- package/v3/@claude-flow/cli/dist/src/init/executor.js +3 -3
- package/v3/@claude-flow/cli/dist/src/init/helpers-generator.js +31 -8
- package/v3/@claude-flow/cli/dist/src/mcp-server.js +16 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/hooks-tools.js +20 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/system-tools.js +88 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/task-tools.js +36 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/workflow-tools.js +91 -0
- package/v3/@claude-flow/cli/dist/src/memory/memory-bridge.js +1 -0
- package/v3/@claude-flow/cli/dist/src/memory/memory-initializer.d.ts +1 -1
- package/v3/@claude-flow/cli/dist/src/memory/memory-initializer.js +1 -1
- package/v3/@claude-flow/cli/dist/src/output.js +1 -0
- package/v3/@claude-flow/cli/dist/src/plugins/store/discovery.js +1 -1
- package/v3/@claude-flow/cli/dist/src/services/container-worker-pool.js +2 -0
- package/v3/@claude-flow/cli/dist/src/services/worker-queue.js +2 -0
- package/v3/@claude-flow/cli/dist/src/types.d.ts +1 -1
- package/v3/@claude-flow/cli/dist/src/types.js +1 -1
- package/v3/@claude-flow/cli/package.json +1 -1
|
@@ -139,17 +139,30 @@ async function loadMemoryPackage() {
|
|
|
139
139
|
} catch { /* fall through */ }
|
|
140
140
|
}
|
|
141
141
|
|
|
142
|
-
// Strategy 2:
|
|
142
|
+
// Strategy 2: Use createRequire for CJS-style resolution (handles nested node_modules
|
|
143
|
+
// when installed as a transitive dependency via npx ruflo / npx claude-flow)
|
|
144
|
+
try {
|
|
145
|
+
const { createRequire } = await import('module');
|
|
146
|
+
const require = createRequire(join(PROJECT_ROOT, 'package.json'));
|
|
147
|
+
return require('@claude-flow/memory');
|
|
148
|
+
} catch { /* fall through */ }
|
|
149
|
+
|
|
150
|
+
// Strategy 3: ESM import (works when @claude-flow/memory is a direct dependency)
|
|
143
151
|
try {
|
|
144
152
|
return await import('@claude-flow/memory');
|
|
145
153
|
} catch { /* fall through */ }
|
|
146
154
|
|
|
147
|
-
// Strategy
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
155
|
+
// Strategy 4: Walk up from PROJECT_ROOT looking for @claude-flow/memory in any node_modules
|
|
156
|
+
let searchDir = PROJECT_ROOT;
|
|
157
|
+
const { parse } = await import('path');
|
|
158
|
+
while (searchDir !== parse(searchDir).root) {
|
|
159
|
+
const candidate = join(searchDir, 'node_modules', '@claude-flow', 'memory', 'dist', 'index.js');
|
|
160
|
+
if (existsSync(candidate)) {
|
|
161
|
+
try {
|
|
162
|
+
return await import(`file://${candidate}`);
|
|
163
|
+
} catch { /* fall through */ }
|
|
164
|
+
}
|
|
165
|
+
searchDir = dirname(searchDir);
|
|
153
166
|
}
|
|
154
167
|
|
|
155
168
|
return null;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
|
-
#
|
|
2
|
+
# RuFlo V3 - Daemon Manager
|
|
3
3
|
# Manages background services for real-time statusline updates
|
|
4
4
|
|
|
5
5
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
@@ -155,7 +155,7 @@ restart_all() {
|
|
|
155
155
|
show_status() {
|
|
156
156
|
echo ""
|
|
157
157
|
echo -e "${CYAN}═══════════════════════════════════════════════════${RESET}"
|
|
158
|
-
echo -e "${CYAN}
|
|
158
|
+
echo -e "${CYAN} RuFlo V3 Daemon Status${RESET}"
|
|
159
159
|
echo -e "${CYAN}═══════════════════════════════════════════════════${RESET}"
|
|
160
160
|
echo ""
|
|
161
161
|
|
|
@@ -225,7 +225,7 @@ case "${1:-status}" in
|
|
|
225
225
|
start_metrics_daemon "${2:-60}"
|
|
226
226
|
;;
|
|
227
227
|
"help"|"-h"|"--help")
|
|
228
|
-
echo "
|
|
228
|
+
echo "RuFlo V3 Daemon Manager"
|
|
229
229
|
echo ""
|
|
230
230
|
echo "Usage: $0 [command] [options]"
|
|
231
231
|
echo ""
|
|
@@ -36,7 +36,30 @@ const memory = safeRequire(path.join(helpersDir, 'memory.cjs'));
|
|
|
36
36
|
const intelligence = safeRequire(path.join(helpersDir, 'intelligence.cjs'));
|
|
37
37
|
|
|
38
38
|
const [,, command, ...args] = process.argv;
|
|
39
|
-
|
|
39
|
+
|
|
40
|
+
// Read stdin — Claude Code sends hook data as JSON via stdin
|
|
41
|
+
async function readStdin() {
|
|
42
|
+
if (process.stdin.isTTY) return '';
|
|
43
|
+
let data = '';
|
|
44
|
+
process.stdin.setEncoding('utf8');
|
|
45
|
+
for await (const chunk of process.stdin) {
|
|
46
|
+
data += chunk;
|
|
47
|
+
}
|
|
48
|
+
return data;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async function main() {
|
|
52
|
+
let stdinData = '';
|
|
53
|
+
try { stdinData = await readStdin(); } catch (e) { /* ignore stdin errors */ }
|
|
54
|
+
|
|
55
|
+
let hookInput = {};
|
|
56
|
+
if (stdinData.trim()) {
|
|
57
|
+
try { hookInput = JSON.parse(stdinData); } catch (e) { /* ignore parse errors */ }
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Merge stdin data into prompt resolution: prefer stdin fields, then env, then argv
|
|
61
|
+
const prompt = hookInput.prompt || hookInput.command || hookInput.toolInput
|
|
62
|
+
|| process.env.PROMPT || process.env.TOOL_INPUT_command || args.join(' ') || '';
|
|
40
63
|
|
|
41
64
|
const handlers = {
|
|
42
65
|
'route': () => {
|
|
@@ -63,7 +86,7 @@ const handlers = {
|
|
|
63
86
|
},
|
|
64
87
|
|
|
65
88
|
'pre-bash': () => {
|
|
66
|
-
var cmd = prompt.toLowerCase();
|
|
89
|
+
var cmd = (hookInput.command || prompt).toLowerCase();
|
|
67
90
|
var dangerous = ['rm -rf /', 'format c:', 'del /s /q c:\\', ':(){:|:&};:'];
|
|
68
91
|
for (var i = 0; i < dangerous.length; i++) {
|
|
69
92
|
if (cmd.includes(dangerous[i])) {
|
|
@@ -80,7 +103,8 @@ const handlers = {
|
|
|
80
103
|
}
|
|
81
104
|
if (intelligence && intelligence.recordEdit) {
|
|
82
105
|
try {
|
|
83
|
-
var file =
|
|
106
|
+
var file = hookInput.file_path || (hookInput.toolInput && hookInput.toolInput.file_path)
|
|
107
|
+
|| process.env.TOOL_INPUT_file_path || args[0] || '';
|
|
84
108
|
intelligence.recordEdit(file);
|
|
85
109
|
} catch (e) { /* non-fatal */ }
|
|
86
110
|
}
|
|
@@ -179,13 +203,18 @@ const handlers = {
|
|
|
179
203
|
};
|
|
180
204
|
|
|
181
205
|
if (command && handlers[command]) {
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
206
|
+
try {
|
|
207
|
+
handlers[command]();
|
|
208
|
+
} catch (e) {
|
|
209
|
+
console.log('[WARN] Hook ' + command + ' encountered an error: ' + e.message);
|
|
210
|
+
}
|
|
211
|
+
} else if (command) {
|
|
212
|
+
console.log('[OK] Hook: ' + command);
|
|
213
|
+
} else {
|
|
214
|
+
console.log('Usage: hook-handler.cjs <route|pre-bash|post-edit|session-restore|session-end|pre-task|post-task|compact-manual|compact-auto|status|stats>');
|
|
186
215
|
}
|
|
187
|
-
} else if (command) {
|
|
188
|
-
console.log('[OK] Hook: ' + command);
|
|
189
|
-
} else {
|
|
190
|
-
console.log('Usage: hook-handler.cjs <route|pre-bash|post-edit|session-restore|session-end|pre-task|post-task|compact-manual|compact-auto|status|stats>');
|
|
191
216
|
}
|
|
217
|
+
|
|
218
|
+
main().catch(function(e) {
|
|
219
|
+
console.log('[WARN] Hook handler error: ' + e.message);
|
|
220
|
+
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
|
-
#
|
|
2
|
+
# RuFlo V3 - Learning Hooks
|
|
3
3
|
# Integrates learning-service.mjs with session lifecycle
|
|
4
4
|
|
|
5
5
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
@@ -300,7 +300,7 @@ case "${1:-help}" in
|
|
|
300
300
|
;;
|
|
301
301
|
"help"|"-h"|"--help")
|
|
302
302
|
cat << 'EOF'
|
|
303
|
-
|
|
303
|
+
RuFlo V3 Learning Hooks
|
|
304
304
|
|
|
305
305
|
Usage: learning-hooks.sh <command> [args]
|
|
306
306
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
3
|
+
* RuFlo V3 - Persistent Learning Service
|
|
4
4
|
*
|
|
5
5
|
* Connects ReasoningBank to AgentDB with HNSW indexing and ONNX embeddings.
|
|
6
6
|
*
|
|
@@ -1112,7 +1112,7 @@ async function main() {
|
|
|
1112
1112
|
case 'help':
|
|
1113
1113
|
default:
|
|
1114
1114
|
console.log(`
|
|
1115
|
-
|
|
1115
|
+
RuFlo V3 Learning Service
|
|
1116
1116
|
|
|
1117
1117
|
Usage: learning-service.mjs <command> [args]
|
|
1118
1118
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
|
-
#
|
|
2
|
+
# RuFlo V3 - Optimized Swarm Communications
|
|
3
3
|
# Non-blocking, batched, priority-based inter-agent messaging
|
|
4
4
|
|
|
5
5
|
set -euo pipefail
|
|
@@ -317,7 +317,7 @@ case "${1:-help}" in
|
|
|
317
317
|
|
|
318
318
|
"help"|*)
|
|
319
319
|
cat << 'EOF'
|
|
320
|
-
|
|
320
|
+
RuFlo V3 - Optimized Swarm Communications
|
|
321
321
|
|
|
322
322
|
Non-blocking, batched, priority-based inter-agent messaging.
|
|
323
323
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
|
-
#
|
|
2
|
+
# RuFlo V3 - Swarm Communication Hooks
|
|
3
3
|
# Enables agent-to-agent messaging, pattern sharing, consensus, and task handoffs
|
|
4
4
|
#
|
|
5
5
|
# Integration with:
|
|
@@ -715,7 +715,7 @@ case "${1:-help}" in
|
|
|
715
715
|
|
|
716
716
|
"help"|"-h"|"--help")
|
|
717
717
|
cat << 'EOF'
|
|
718
|
-
|
|
718
|
+
RuFlo V3 - Swarm Communication Hooks
|
|
719
719
|
|
|
720
720
|
Usage: swarm-hooks.sh <command> [args]
|
|
721
721
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
|
-
#
|
|
2
|
+
# RuFlo V3 - Real-time Swarm Activity Monitor
|
|
3
3
|
# Continuously monitors and updates metrics based on running processes
|
|
4
4
|
|
|
5
5
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
@@ -188,7 +188,7 @@ case "${1:-check}" in
|
|
|
188
188
|
fi
|
|
189
189
|
;;
|
|
190
190
|
"help"|"-h"|"--help")
|
|
191
|
-
echo "
|
|
191
|
+
echo "RuFlo V3 Swarm Monitor"
|
|
192
192
|
echo ""
|
|
193
193
|
echo "Usage: $0 [command] [options]"
|
|
194
194
|
echo ""
|
package/.claude/helpers/v3.sh
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
|
-
#
|
|
2
|
+
# RuFlo V3 - Unified Worker Manager
|
|
3
3
|
# Orchestrates all background workers with proper scheduling
|
|
4
4
|
|
|
5
5
|
set -euo pipefail
|
|
@@ -65,7 +65,7 @@ run_daemon() {
|
|
|
65
65
|
|
|
66
66
|
status_all() {
|
|
67
67
|
echo "╔══════════════════════════════════════════════════════════════╗"
|
|
68
|
-
echo "║
|
|
68
|
+
echo "║ RuFlo V3 - Worker Status ║"
|
|
69
69
|
echo "╠══════════════════════════════════════════════════════════════╣"
|
|
70
70
|
|
|
71
71
|
for worker_def in "${WORKERS[@]}"; do
|
|
@@ -140,7 +140,7 @@ case "${1:-help}" in
|
|
|
140
140
|
;;
|
|
141
141
|
"help"|*)
|
|
142
142
|
cat << EOF
|
|
143
|
-
|
|
143
|
+
RuFlo V3 - Worker Manager
|
|
144
144
|
|
|
145
145
|
Usage: $0 <command> [options]
|
|
146
146
|
|
package/.claude/statusline.sh
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
|
-
#
|
|
2
|
+
# RuFlo V3 Development Status Line
|
|
3
3
|
# Shows DDD architecture progress, security status, and performance targets
|
|
4
4
|
|
|
5
5
|
# Read Claude Code JSON input from stdin (if available)
|
|
@@ -326,7 +326,7 @@ CURRENT_DIR=$(basename "$PROJECT_DIR" 2>/dev/null || echo "claude-flow")
|
|
|
326
326
|
OUTPUT=""
|
|
327
327
|
|
|
328
328
|
# Header Line: V3 Project + Branch + Integration Status
|
|
329
|
-
OUTPUT="${BOLD}${BRIGHT_PURPLE}▊
|
|
329
|
+
OUTPUT="${BOLD}${BRIGHT_PURPLE}▊ RuFlo V3 ${RESET}"
|
|
330
330
|
OUTPUT="${OUTPUT}${INTEGRATION_COLOR}${INTEGRATION_STATUS} ${BRIGHT_CYAN}${GH_USER}${RESET}"
|
|
331
331
|
if [ -n "$GIT_BRANCH" ]; then
|
|
332
332
|
OUTPUT="${OUTPUT} ${DIM}│${RESET} ${BRIGHT_BLUE}⎇ ${GIT_BRANCH}${RESET}"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-flow",
|
|
3
|
-
"version": "3.5.
|
|
3
|
+
"version": "3.5.5",
|
|
4
4
|
"description": "Ruflo - Enterprise AI agent orchestration for Claude Code. Deploy 60+ specialized agents in coordinated swarms with self-learning, fault-tolerant consensus, vector memory, and MCP integration",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -192,10 +192,15 @@ async function checkDiskSpace() {
|
|
|
192
192
|
if (process.platform === 'win32') {
|
|
193
193
|
return { name: 'Disk Space', status: 'pass', message: 'Check skipped on Windows' };
|
|
194
194
|
}
|
|
195
|
-
|
|
195
|
+
// Use df -Ph for POSIX mode (guarantees single-line output even with long device names)
|
|
196
|
+
const output_str = await runCommand('df -Ph . | tail -1');
|
|
196
197
|
const parts = output_str.split(/\s+/);
|
|
198
|
+
// POSIX format: Filesystem Size Used Avail Capacity Mounted
|
|
197
199
|
const available = parts[3];
|
|
198
200
|
const usePercent = parseInt(parts[4]?.replace('%', '') || '0', 10);
|
|
201
|
+
if (isNaN(usePercent)) {
|
|
202
|
+
return { name: 'Disk Space', status: 'warn', message: `${available || 'unknown'} available (unable to parse usage)` };
|
|
203
|
+
}
|
|
199
204
|
if (usePercent > 90) {
|
|
200
205
|
return { name: 'Disk Space', status: 'fail', message: `${available} available (${usePercent}% used)`, fix: 'Free up disk space' };
|
|
201
206
|
}
|
|
@@ -247,7 +247,19 @@ const statusCommand = {
|
|
|
247
247
|
description: 'Show MCP server status',
|
|
248
248
|
action: async (ctx) => {
|
|
249
249
|
try {
|
|
250
|
-
|
|
250
|
+
let status = await getMCPServerStatus();
|
|
251
|
+
// If PID-based check says not running, detect stdio mode
|
|
252
|
+
if (!status.running) {
|
|
253
|
+
const isStdio = !process.stdin.isTTY;
|
|
254
|
+
const envTransport = process.env.CLAUDE_FLOW_MCP_TRANSPORT;
|
|
255
|
+
if (isStdio || envTransport === 'stdio') {
|
|
256
|
+
status = {
|
|
257
|
+
running: true,
|
|
258
|
+
pid: process.pid,
|
|
259
|
+
transport: 'stdio',
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
}
|
|
251
263
|
if (ctx.flags.format === 'json') {
|
|
252
264
|
output.printJson(status);
|
|
253
265
|
return { success: true, data: status };
|
|
@@ -273,9 +285,12 @@ const statusCommand = {
|
|
|
273
285
|
{ metric: 'Status', value: output.success('Running') },
|
|
274
286
|
{ metric: 'PID', value: status.pid },
|
|
275
287
|
{ metric: 'Transport', value: status.transport },
|
|
276
|
-
{ metric: 'Host', value: status.host },
|
|
277
|
-
{ metric: 'Port', value: status.port },
|
|
278
288
|
];
|
|
289
|
+
// Only show host/port for non-stdio transports
|
|
290
|
+
if (status.transport !== 'stdio') {
|
|
291
|
+
displayData.push({ metric: 'Host', value: status.host });
|
|
292
|
+
displayData.push({ metric: 'Port', value: status.port });
|
|
293
|
+
}
|
|
279
294
|
if (status.uptime !== undefined) {
|
|
280
295
|
displayData.push({ metric: 'Uptime', value: formatUptime(status.uptime) });
|
|
281
296
|
}
|
|
@@ -223,7 +223,12 @@ function displayStatus(status) {
|
|
|
223
223
|
// MCP section
|
|
224
224
|
output.writeln(output.bold('MCP Server'));
|
|
225
225
|
if (status.mcp.running) {
|
|
226
|
-
|
|
226
|
+
if (status.mcp.transport === 'stdio') {
|
|
227
|
+
output.printInfo(' Running (stdio mode)');
|
|
228
|
+
}
|
|
229
|
+
else {
|
|
230
|
+
output.printInfo(` Running on port ${status.mcp.port} (${status.mcp.transport})`);
|
|
231
|
+
}
|
|
227
232
|
}
|
|
228
233
|
else {
|
|
229
234
|
output.printInfo(' Not running');
|
|
@@ -316,7 +321,9 @@ async function performHealthCheck(status) {
|
|
|
316
321
|
checks.push({
|
|
317
322
|
name: 'MCP Server',
|
|
318
323
|
status: status.mcp.running ? 'pass' : 'warn',
|
|
319
|
-
message: status.mcp.running
|
|
324
|
+
message: status.mcp.running
|
|
325
|
+
? (status.mcp.transport === 'stdio' ? 'Running (stdio mode)' : `Running on port ${status.mcp.port}`)
|
|
326
|
+
: 'Not running'
|
|
320
327
|
});
|
|
321
328
|
// Check memory backend
|
|
322
329
|
checks.push({
|
|
@@ -1028,7 +1028,7 @@ async function writeRuntimeConfig(targetDir, options, result) {
|
|
|
1028
1028
|
result.skipped.push('.claude-flow/config.yaml');
|
|
1029
1029
|
return;
|
|
1030
1030
|
}
|
|
1031
|
-
const config = `#
|
|
1031
|
+
const config = `# RuFlo V3 Runtime Configuration
|
|
1032
1032
|
# Generated: ${new Date().toISOString()}
|
|
1033
1033
|
|
|
1034
1034
|
version: "3.0.0"
|
|
@@ -1208,7 +1208,7 @@ async function writeCapabilitiesDoc(targetDir, options, result) {
|
|
|
1208
1208
|
result.skipped.push('.claude-flow/CAPABILITIES.md');
|
|
1209
1209
|
return;
|
|
1210
1210
|
}
|
|
1211
|
-
const capabilities = `#
|
|
1211
|
+
const capabilities = `# RuFlo V3 - Complete Capabilities Reference
|
|
1212
1212
|
> Generated: ${new Date().toISOString()}
|
|
1213
1213
|
> Full documentation: https://github.com/ruvnet/claude-flow
|
|
1214
1214
|
|
|
@@ -1228,7 +1228,7 @@ async function writeCapabilitiesDoc(targetDir, options, result) {
|
|
|
1228
1228
|
|
|
1229
1229
|
## Overview
|
|
1230
1230
|
|
|
1231
|
-
|
|
1231
|
+
RuFlo V3 is a domain-driven design architecture for multi-agent AI coordination with:
|
|
1232
1232
|
|
|
1233
1233
|
- **15-Agent Swarm Coordination** with hierarchical and mesh topologies
|
|
1234
1234
|
- **HNSW Vector Search** - 150x-12,500x faster pattern retrieval
|
|
@@ -794,10 +794,34 @@ const dim = (msg) => console.log(\` \${DIM}\${msg}\${RESET}\`);
|
|
|
794
794
|
// Ensure data dir
|
|
795
795
|
if (!existsSync(DATA_DIR)) mkdirSync(DATA_DIR, { recursive: true });
|
|
796
796
|
|
|
797
|
+
async function loadMemoryPackage() {
|
|
798
|
+
// Strategy 1: Use createRequire for CJS-style resolution (handles nested node_modules
|
|
799
|
+
// when installed as a transitive dependency via npx ruflo / npx claude-flow)
|
|
800
|
+
try {
|
|
801
|
+
const { createRequire } = await import('module');
|
|
802
|
+
const require = createRequire(join(PROJECT_ROOT, 'package.json'));
|
|
803
|
+
return require('@claude-flow/memory');
|
|
804
|
+
} catch { /* fall through */ }
|
|
805
|
+
|
|
806
|
+
// Strategy 2: ESM import (works when @claude-flow/memory is a direct dependency)
|
|
807
|
+
try { return await import('@claude-flow/memory'); } catch { /* fall through */ }
|
|
808
|
+
|
|
809
|
+
// Strategy 3: Walk up from PROJECT_ROOT looking for the package in any node_modules
|
|
810
|
+
let searchDir = PROJECT_ROOT;
|
|
811
|
+
const { parse } = await import('path');
|
|
812
|
+
while (searchDir !== parse(searchDir).root) {
|
|
813
|
+
const candidate = join(searchDir, 'node_modules', '@claude-flow', 'memory', 'dist', 'index.js');
|
|
814
|
+
if (existsSync(candidate)) {
|
|
815
|
+
try { return await import(\`file://\${candidate}\`); } catch { /* fall through */ }
|
|
816
|
+
}
|
|
817
|
+
searchDir = dirname(searchDir);
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
return null;
|
|
821
|
+
}
|
|
822
|
+
|
|
797
823
|
async function doImport() {
|
|
798
|
-
|
|
799
|
-
let memPkg = null;
|
|
800
|
-
try { memPkg = await import('@claude-flow/memory'); } catch {}
|
|
824
|
+
const memPkg = await loadMemoryPackage();
|
|
801
825
|
|
|
802
826
|
if (!memPkg || !memPkg.AutoMemoryBridge) {
|
|
803
827
|
dim('Memory package not available — auto memory import skipped (non-critical)');
|
|
@@ -814,8 +838,7 @@ async function doSync() {
|
|
|
814
838
|
return;
|
|
815
839
|
}
|
|
816
840
|
|
|
817
|
-
|
|
818
|
-
try { memPkg = await import('@claude-flow/memory'); } catch {}
|
|
841
|
+
const memPkg = await loadMemoryPackage();
|
|
819
842
|
|
|
820
843
|
if (!memPkg || !memPkg.AutoMemoryBridge) {
|
|
821
844
|
dim('Memory package not available — sync skipped (non-critical)');
|
|
@@ -853,7 +876,7 @@ try {
|
|
|
853
876
|
* Generate Windows PowerShell daemon manager
|
|
854
877
|
*/
|
|
855
878
|
export function generateWindowsDaemonManager() {
|
|
856
|
-
return `#
|
|
879
|
+
return `# RuFlo V3 Daemon Manager for Windows
|
|
857
880
|
# PowerShell script for managing background processes
|
|
858
881
|
|
|
859
882
|
param(
|
|
@@ -919,7 +942,7 @@ function Stop-SwarmMonitor {
|
|
|
919
942
|
|
|
920
943
|
function Show-Status {
|
|
921
944
|
Write-Host ""
|
|
922
|
-
Write-Host "
|
|
945
|
+
Write-Host "RuFlo V3 Daemon Status" -ForegroundColor Cyan
|
|
923
946
|
Write-Host "=============================" -ForegroundColor Cyan
|
|
924
947
|
|
|
925
948
|
$swarmPid = Join-Path $PidDir 'swarm-monitor.pid'
|
|
@@ -959,7 +982,7 @@ switch ($Action) {
|
|
|
959
982
|
*/
|
|
960
983
|
export function generateWindowsBatchWrapper() {
|
|
961
984
|
return `@echo off
|
|
962
|
-
REM
|
|
985
|
+
REM RuFlo V3 - Windows Batch Wrapper
|
|
963
986
|
REM Routes to PowerShell daemon manager
|
|
964
987
|
|
|
965
988
|
PowerShell -ExecutionPolicy Bypass -File "%~dp0daemon-manager.ps1" %*
|
|
@@ -142,6 +142,21 @@ export class MCPServerManager extends EventEmitter {
|
|
|
142
142
|
// Check PID file
|
|
143
143
|
const pid = await this.readPidFile();
|
|
144
144
|
if (!pid) {
|
|
145
|
+
// No PID file found. Detect if we are running in stdio mode
|
|
146
|
+
// (e.g., launched by Claude Code via `claude mcp add`).
|
|
147
|
+
const isStdio = !process.stdin.isTTY;
|
|
148
|
+
const envTransport = process.env.CLAUDE_FLOW_MCP_TRANSPORT;
|
|
149
|
+
if (isStdio || envTransport === 'stdio' || this.options.transport === 'stdio') {
|
|
150
|
+
return {
|
|
151
|
+
running: true,
|
|
152
|
+
pid: process.pid,
|
|
153
|
+
transport: 'stdio',
|
|
154
|
+
startedAt: this.startTime?.toISOString(),
|
|
155
|
+
uptime: this.startTime
|
|
156
|
+
? Math.floor((Date.now() - this.startTime.getTime()) / 1000)
|
|
157
|
+
: undefined,
|
|
158
|
+
};
|
|
159
|
+
}
|
|
145
160
|
return { running: false };
|
|
146
161
|
}
|
|
147
162
|
// Check if process is running
|
|
@@ -459,6 +474,7 @@ export class MCPServerManager extends EventEmitter {
|
|
|
459
474
|
this.emit('health-error', error);
|
|
460
475
|
}
|
|
461
476
|
}, 30000);
|
|
477
|
+
this.healthCheckInterval.unref();
|
|
462
478
|
}
|
|
463
479
|
/**
|
|
464
480
|
* Write PID file
|
|
@@ -512,12 +512,32 @@ export const hooksPostEdit = {
|
|
|
512
512
|
handler: async (params) => {
|
|
513
513
|
const filePath = params.filePath;
|
|
514
514
|
const success = params.success !== false;
|
|
515
|
+
const agent = params.agent;
|
|
516
|
+
// Wire recordFeedback through bridge (issue #1209)
|
|
517
|
+
let feedbackResult = null;
|
|
518
|
+
try {
|
|
519
|
+
const bridge = await import('../memory/memory-bridge.js');
|
|
520
|
+
feedbackResult = await bridge.bridgeRecordFeedback({
|
|
521
|
+
taskId: `edit-${filePath}-${Date.now()}`,
|
|
522
|
+
success,
|
|
523
|
+
quality: success ? 0.85 : 0.3,
|
|
524
|
+
agent,
|
|
525
|
+
});
|
|
526
|
+
}
|
|
527
|
+
catch {
|
|
528
|
+
// Bridge not available — continue with basic response
|
|
529
|
+
}
|
|
515
530
|
return {
|
|
516
531
|
recorded: true,
|
|
517
532
|
filePath,
|
|
518
533
|
success,
|
|
519
534
|
timestamp: new Date().toISOString(),
|
|
520
535
|
learningUpdate: success ? 'pattern_reinforced' : 'pattern_adjusted',
|
|
536
|
+
feedback: feedbackResult ? {
|
|
537
|
+
recorded: feedbackResult.success,
|
|
538
|
+
controller: feedbackResult.controller,
|
|
539
|
+
updates: feedbackResult.updated,
|
|
540
|
+
} : { recorded: false, controller: 'unavailable', updates: 0 },
|
|
521
541
|
};
|
|
522
542
|
},
|
|
523
543
|
};
|
|
@@ -325,5 +325,93 @@ export const systemTools = [
|
|
|
325
325
|
};
|
|
326
326
|
},
|
|
327
327
|
},
|
|
328
|
+
{
|
|
329
|
+
name: 'mcp_status',
|
|
330
|
+
description: 'Get MCP server status, including stdio mode detection',
|
|
331
|
+
category: 'system',
|
|
332
|
+
inputSchema: {
|
|
333
|
+
type: 'object',
|
|
334
|
+
properties: {},
|
|
335
|
+
},
|
|
336
|
+
handler: async () => {
|
|
337
|
+
// Detect if we are running inside an MCP stdio session.
|
|
338
|
+
// When Claude Code launches us via `claude mcp add`, stdin is piped (not a TTY)
|
|
339
|
+
// and the process IS the MCP server, so it is running.
|
|
340
|
+
const isStdio = !process.stdin.isTTY;
|
|
341
|
+
const transport = process.env.CLAUDE_FLOW_MCP_TRANSPORT || (isStdio ? 'stdio' : 'http');
|
|
342
|
+
const port = parseInt(process.env.CLAUDE_FLOW_MCP_PORT || '3000', 10);
|
|
343
|
+
if (transport === 'stdio' || isStdio) {
|
|
344
|
+
// In stdio mode the MCP server is this process itself
|
|
345
|
+
return {
|
|
346
|
+
running: true,
|
|
347
|
+
pid: process.pid,
|
|
348
|
+
transport: 'stdio',
|
|
349
|
+
port: null,
|
|
350
|
+
host: null,
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
// For HTTP/WebSocket, try to check if the server is listening
|
|
354
|
+
const host = process.env.CLAUDE_FLOW_MCP_HOST || 'localhost';
|
|
355
|
+
try {
|
|
356
|
+
const { createConnection } = await import('node:net');
|
|
357
|
+
const connected = await new Promise((resolve) => {
|
|
358
|
+
const socket = createConnection({ host, port }, () => {
|
|
359
|
+
socket.destroy();
|
|
360
|
+
resolve(true);
|
|
361
|
+
});
|
|
362
|
+
socket.on('error', () => resolve(false));
|
|
363
|
+
socket.setTimeout(2000, () => {
|
|
364
|
+
socket.destroy();
|
|
365
|
+
resolve(false);
|
|
366
|
+
});
|
|
367
|
+
});
|
|
368
|
+
return {
|
|
369
|
+
running: connected,
|
|
370
|
+
transport,
|
|
371
|
+
port,
|
|
372
|
+
host,
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
catch {
|
|
376
|
+
return {
|
|
377
|
+
running: false,
|
|
378
|
+
transport,
|
|
379
|
+
port,
|
|
380
|
+
host,
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
},
|
|
384
|
+
},
|
|
385
|
+
{
|
|
386
|
+
name: 'task_summary',
|
|
387
|
+
description: 'Get a summary of all tasks by status',
|
|
388
|
+
category: 'task',
|
|
389
|
+
inputSchema: {
|
|
390
|
+
type: 'object',
|
|
391
|
+
properties: {},
|
|
392
|
+
},
|
|
393
|
+
handler: async () => {
|
|
394
|
+
// Read from the task store file
|
|
395
|
+
const storePath = join(process.cwd(), '.claude-flow', 'tasks', 'store.json');
|
|
396
|
+
let tasks = [];
|
|
397
|
+
try {
|
|
398
|
+
if (existsSync(storePath)) {
|
|
399
|
+
const data = readFileSync(storePath, 'utf-8');
|
|
400
|
+
const store = JSON.parse(data);
|
|
401
|
+
tasks = Object.values(store.tasks || {});
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
catch {
|
|
405
|
+
// empty store
|
|
406
|
+
}
|
|
407
|
+
return {
|
|
408
|
+
total: tasks.length,
|
|
409
|
+
pending: tasks.filter(t => t.status === 'pending').length,
|
|
410
|
+
running: tasks.filter(t => t.status === 'in_progress').length,
|
|
411
|
+
completed: tasks.filter(t => t.status === 'completed').length,
|
|
412
|
+
failed: tasks.filter(t => t.status === 'failed').length,
|
|
413
|
+
};
|
|
414
|
+
},
|
|
415
|
+
},
|
|
328
416
|
];
|
|
329
417
|
//# sourceMappingURL=system-tools.js.map
|
|
@@ -263,6 +263,42 @@ export const taskTools = [
|
|
|
263
263
|
};
|
|
264
264
|
},
|
|
265
265
|
},
|
|
266
|
+
{
|
|
267
|
+
name: 'task_assign',
|
|
268
|
+
description: 'Assign a task to one or more agents',
|
|
269
|
+
category: 'task',
|
|
270
|
+
inputSchema: {
|
|
271
|
+
type: 'object',
|
|
272
|
+
properties: {
|
|
273
|
+
taskId: { type: 'string', description: 'Task ID to assign' },
|
|
274
|
+
agentIds: { type: 'array', items: { type: 'string' }, description: 'Agent IDs to assign' },
|
|
275
|
+
unassign: { type: 'boolean', description: 'Unassign all agents from task' },
|
|
276
|
+
},
|
|
277
|
+
required: ['taskId'],
|
|
278
|
+
},
|
|
279
|
+
handler: async (input) => {
|
|
280
|
+
const store = loadTaskStore();
|
|
281
|
+
const taskId = input.taskId;
|
|
282
|
+
const task = store.tasks[taskId];
|
|
283
|
+
if (!task) {
|
|
284
|
+
return { taskId, error: 'Task not found' };
|
|
285
|
+
}
|
|
286
|
+
const previouslyAssigned = [...task.assignedTo];
|
|
287
|
+
if (input.unassign) {
|
|
288
|
+
task.assignedTo = [];
|
|
289
|
+
}
|
|
290
|
+
else {
|
|
291
|
+
const agentIds = input.agentIds || [];
|
|
292
|
+
task.assignedTo = agentIds;
|
|
293
|
+
}
|
|
294
|
+
saveTaskStore(store);
|
|
295
|
+
return {
|
|
296
|
+
taskId: task.taskId,
|
|
297
|
+
assignedTo: task.assignedTo,
|
|
298
|
+
previouslyAssigned,
|
|
299
|
+
};
|
|
300
|
+
},
|
|
301
|
+
},
|
|
266
302
|
{
|
|
267
303
|
name: 'task_cancel',
|
|
268
304
|
description: 'Cancel a task',
|
|
@@ -39,6 +39,97 @@ function saveWorkflowStore(store) {
|
|
|
39
39
|
writeFileSync(getWorkflowPath(), JSON.stringify(store, null, 2), 'utf-8');
|
|
40
40
|
}
|
|
41
41
|
export const workflowTools = [
|
|
42
|
+
{
|
|
43
|
+
name: 'workflow_run',
|
|
44
|
+
description: 'Run a workflow from a template or file',
|
|
45
|
+
category: 'workflow',
|
|
46
|
+
inputSchema: {
|
|
47
|
+
type: 'object',
|
|
48
|
+
properties: {
|
|
49
|
+
template: { type: 'string', description: 'Template name to run' },
|
|
50
|
+
file: { type: 'string', description: 'Workflow file path' },
|
|
51
|
+
task: { type: 'string', description: 'Task description' },
|
|
52
|
+
options: {
|
|
53
|
+
type: 'object',
|
|
54
|
+
description: 'Workflow options',
|
|
55
|
+
properties: {
|
|
56
|
+
parallel: { type: 'boolean', description: 'Run stages in parallel' },
|
|
57
|
+
maxAgents: { type: 'number', description: 'Maximum agents to use' },
|
|
58
|
+
timeout: { type: 'number', description: 'Timeout in seconds' },
|
|
59
|
+
dryRun: { type: 'boolean', description: 'Validate without executing' },
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
handler: async (input) => {
|
|
65
|
+
const store = loadWorkflowStore();
|
|
66
|
+
const template = input.template;
|
|
67
|
+
const task = input.task;
|
|
68
|
+
const options = input.options || {};
|
|
69
|
+
const dryRun = options.dryRun;
|
|
70
|
+
// Build workflow from template or inline
|
|
71
|
+
const workflowId = `workflow-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
72
|
+
const stages = [];
|
|
73
|
+
// Generate stages based on template
|
|
74
|
+
const templateName = template || 'custom';
|
|
75
|
+
const stageNames = (() => {
|
|
76
|
+
switch (templateName) {
|
|
77
|
+
case 'feature':
|
|
78
|
+
return ['Research', 'Design', 'Implement', 'Test', 'Review'];
|
|
79
|
+
case 'bugfix':
|
|
80
|
+
return ['Investigate', 'Fix', 'Test', 'Review'];
|
|
81
|
+
case 'refactor':
|
|
82
|
+
return ['Analyze', 'Refactor', 'Test', 'Review'];
|
|
83
|
+
case 'security':
|
|
84
|
+
return ['Scan', 'Analyze', 'Report'];
|
|
85
|
+
default:
|
|
86
|
+
return ['Execute'];
|
|
87
|
+
}
|
|
88
|
+
})();
|
|
89
|
+
for (const name of stageNames) {
|
|
90
|
+
stages.push({
|
|
91
|
+
name,
|
|
92
|
+
status: dryRun ? 'validated' : 'pending',
|
|
93
|
+
agents: [],
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
if (!dryRun) {
|
|
97
|
+
// Create and save the workflow
|
|
98
|
+
const steps = stageNames.map((name, i) => ({
|
|
99
|
+
stepId: `step-${i + 1}`,
|
|
100
|
+
name,
|
|
101
|
+
type: 'task',
|
|
102
|
+
config: { task: task || name },
|
|
103
|
+
status: 'pending',
|
|
104
|
+
}));
|
|
105
|
+
const workflow = {
|
|
106
|
+
workflowId,
|
|
107
|
+
name: task || `${templateName} workflow`,
|
|
108
|
+
description: task,
|
|
109
|
+
steps,
|
|
110
|
+
status: 'running',
|
|
111
|
+
currentStep: 0,
|
|
112
|
+
variables: { template: templateName, ...options },
|
|
113
|
+
createdAt: new Date().toISOString(),
|
|
114
|
+
startedAt: new Date().toISOString(),
|
|
115
|
+
};
|
|
116
|
+
store.workflows[workflowId] = workflow;
|
|
117
|
+
saveWorkflowStore(store);
|
|
118
|
+
}
|
|
119
|
+
return {
|
|
120
|
+
workflowId,
|
|
121
|
+
template: templateName,
|
|
122
|
+
status: dryRun ? 'validated' : 'running',
|
|
123
|
+
stages,
|
|
124
|
+
metrics: {
|
|
125
|
+
totalStages: stages.length,
|
|
126
|
+
completedStages: 0,
|
|
127
|
+
agentsSpawned: 0,
|
|
128
|
+
estimatedDuration: `${stages.length * 30}s`,
|
|
129
|
+
},
|
|
130
|
+
};
|
|
131
|
+
},
|
|
132
|
+
},
|
|
42
133
|
{
|
|
43
134
|
name: 'workflow_create',
|
|
44
135
|
description: 'Create a new workflow',
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* Enhanced schema with pattern confidence, temporal decay, versioning
|
|
13
13
|
* Vector embeddings enabled for semantic search
|
|
14
14
|
*/
|
|
15
|
-
export declare const MEMORY_SCHEMA_V3 = "\n--
|
|
15
|
+
export declare const MEMORY_SCHEMA_V3 = "\n-- RuFlo V3 Memory Database\n-- Version: 3.0.0\n-- Features: Pattern learning, vector embeddings, temporal decay, migration tracking\n\nPRAGMA journal_mode = WAL;\nPRAGMA synchronous = NORMAL;\nPRAGMA foreign_keys = ON;\n\n-- ============================================\n-- CORE MEMORY TABLES\n-- ============================================\n\n-- Memory entries (main storage)\nCREATE TABLE IF NOT EXISTS memory_entries (\n id TEXT PRIMARY KEY,\n key TEXT NOT NULL,\n namespace TEXT DEFAULT 'default',\n content TEXT NOT NULL,\n type TEXT DEFAULT 'semantic' CHECK(type IN ('semantic', 'episodic', 'procedural', 'working', 'pattern')),\n\n -- Vector embedding for semantic search (stored as JSON array)\n embedding TEXT,\n embedding_model TEXT DEFAULT 'local',\n embedding_dimensions INTEGER,\n\n -- Metadata\n tags TEXT, -- JSON array\n metadata TEXT, -- JSON object\n owner_id TEXT,\n\n -- Timestamps\n created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now') * 1000),\n updated_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now') * 1000),\n expires_at INTEGER,\n last_accessed_at INTEGER,\n\n -- Access tracking for hot/cold detection\n access_count INTEGER DEFAULT 0,\n\n -- Status\n status TEXT DEFAULT 'active' CHECK(status IN ('active', 'archived', 'deleted')),\n\n UNIQUE(namespace, key)\n);\n\n-- Indexes for memory entries\nCREATE INDEX IF NOT EXISTS idx_memory_namespace ON memory_entries(namespace);\nCREATE INDEX IF NOT EXISTS idx_memory_key ON memory_entries(key);\nCREATE INDEX IF NOT EXISTS idx_memory_type ON memory_entries(type);\nCREATE INDEX IF NOT EXISTS idx_memory_status ON memory_entries(status);\nCREATE INDEX IF NOT EXISTS idx_memory_created ON memory_entries(created_at);\nCREATE INDEX IF NOT EXISTS idx_memory_accessed ON memory_entries(last_accessed_at);\nCREATE INDEX IF NOT EXISTS idx_memory_owner ON memory_entries(owner_id);\n\n-- ============================================\n-- PATTERN LEARNING TABLES\n-- ============================================\n\n-- Learned patterns with confidence scoring and versioning\nCREATE TABLE IF NOT EXISTS patterns (\n id TEXT PRIMARY KEY,\n\n -- Pattern identification\n name TEXT NOT NULL,\n pattern_type TEXT NOT NULL CHECK(pattern_type IN (\n 'task-routing', 'error-recovery', 'optimization', 'learning',\n 'coordination', 'prediction', 'code-pattern', 'workflow'\n )),\n\n -- Pattern definition\n condition TEXT NOT NULL, -- Regex or semantic match\n action TEXT NOT NULL, -- What to do when pattern matches\n description TEXT,\n\n -- Confidence scoring (0.0 - 1.0)\n confidence REAL DEFAULT 0.5,\n success_count INTEGER DEFAULT 0,\n failure_count INTEGER DEFAULT 0,\n\n -- Temporal decay\n decay_rate REAL DEFAULT 0.01, -- How fast confidence decays\n half_life_days INTEGER DEFAULT 30, -- Days until confidence halves without use\n\n -- Vector embedding for semantic pattern matching\n embedding TEXT,\n embedding_dimensions INTEGER,\n\n -- Versioning\n version INTEGER DEFAULT 1,\n parent_id TEXT REFERENCES patterns(id),\n\n -- Metadata\n tags TEXT, -- JSON array\n metadata TEXT, -- JSON object\n source TEXT, -- Where the pattern was learned from\n\n -- Timestamps\n created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now') * 1000),\n updated_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now') * 1000),\n last_matched_at INTEGER,\n last_success_at INTEGER,\n last_failure_at INTEGER,\n\n -- Status\n status TEXT DEFAULT 'active' CHECK(status IN ('active', 'archived', 'deprecated', 'experimental'))\n);\n\n-- Indexes for patterns\nCREATE INDEX IF NOT EXISTS idx_patterns_type ON patterns(pattern_type);\nCREATE INDEX IF NOT EXISTS idx_patterns_confidence ON patterns(confidence DESC);\nCREATE INDEX IF NOT EXISTS idx_patterns_status ON patterns(status);\nCREATE INDEX IF NOT EXISTS idx_patterns_last_matched ON patterns(last_matched_at);\n\n-- Pattern evolution history (for versioning)\nCREATE TABLE IF NOT EXISTS pattern_history (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n pattern_id TEXT NOT NULL REFERENCES patterns(id),\n version INTEGER NOT NULL,\n\n -- Snapshot of pattern state\n confidence REAL,\n success_count INTEGER,\n failure_count INTEGER,\n condition TEXT,\n action TEXT,\n\n -- What changed\n change_type TEXT CHECK(change_type IN ('created', 'updated', 'success', 'failure', 'decay', 'merged', 'split')),\n change_reason TEXT,\n\n created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now') * 1000)\n);\n\nCREATE INDEX IF NOT EXISTS idx_pattern_history_pattern ON pattern_history(pattern_id);\n\n-- ============================================\n-- LEARNING & TRAJECTORY TABLES\n-- ============================================\n\n-- Learning trajectories (SONA integration)\nCREATE TABLE IF NOT EXISTS trajectories (\n id TEXT PRIMARY KEY,\n session_id TEXT,\n\n -- Trajectory state\n status TEXT DEFAULT 'active' CHECK(status IN ('active', 'completed', 'failed', 'abandoned')),\n verdict TEXT CHECK(verdict IN ('success', 'failure', 'partial', NULL)),\n\n -- Context\n task TEXT,\n context TEXT, -- JSON object\n\n -- Metrics\n total_steps INTEGER DEFAULT 0,\n total_reward REAL DEFAULT 0,\n\n -- Timestamps\n started_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now') * 1000),\n ended_at INTEGER,\n\n -- Reference to extracted pattern (if any)\n extracted_pattern_id TEXT REFERENCES patterns(id)\n);\n\n-- Trajectory steps\nCREATE TABLE IF NOT EXISTS trajectory_steps (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n trajectory_id TEXT NOT NULL REFERENCES trajectories(id),\n step_number INTEGER NOT NULL,\n\n -- Step data\n action TEXT NOT NULL,\n observation TEXT,\n reward REAL DEFAULT 0,\n\n -- Metadata\n metadata TEXT, -- JSON object\n\n created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now') * 1000)\n);\n\nCREATE INDEX IF NOT EXISTS idx_steps_trajectory ON trajectory_steps(trajectory_id);\n\n-- ============================================\n-- MIGRATION STATE TRACKING\n-- ============================================\n\n-- Migration state (for resume capability)\nCREATE TABLE IF NOT EXISTS migration_state (\n id TEXT PRIMARY KEY,\n migration_type TEXT NOT NULL, -- 'v2-to-v3', 'pattern', 'memory', etc.\n\n -- Progress tracking\n status TEXT DEFAULT 'pending' CHECK(status IN ('pending', 'in_progress', 'completed', 'failed', 'rolled_back')),\n total_items INTEGER DEFAULT 0,\n processed_items INTEGER DEFAULT 0,\n failed_items INTEGER DEFAULT 0,\n skipped_items INTEGER DEFAULT 0,\n\n -- Current position (for resume)\n current_batch INTEGER DEFAULT 0,\n last_processed_id TEXT,\n\n -- Source/destination info\n source_path TEXT,\n source_type TEXT,\n destination_path TEXT,\n\n -- Backup info\n backup_path TEXT,\n backup_created_at INTEGER,\n\n -- Error tracking\n last_error TEXT,\n errors TEXT, -- JSON array of errors\n\n -- Timestamps\n started_at INTEGER,\n completed_at INTEGER,\n created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now') * 1000),\n updated_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now') * 1000)\n);\n\n-- ============================================\n-- SESSION MANAGEMENT\n-- ============================================\n\n-- Sessions for context persistence\nCREATE TABLE IF NOT EXISTS sessions (\n id TEXT PRIMARY KEY,\n\n -- Session state\n state TEXT NOT NULL, -- JSON object with full session state\n status TEXT DEFAULT 'active' CHECK(status IN ('active', 'paused', 'completed', 'expired')),\n\n -- Context\n project_path TEXT,\n branch TEXT,\n\n -- Metrics\n tasks_completed INTEGER DEFAULT 0,\n patterns_learned INTEGER DEFAULT 0,\n\n -- Timestamps\n created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now') * 1000),\n updated_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now') * 1000),\n expires_at INTEGER\n);\n\n-- ============================================\n-- VECTOR INDEX METADATA (for HNSW)\n-- ============================================\n\n-- Track HNSW index state\nCREATE TABLE IF NOT EXISTS vector_indexes (\n id TEXT PRIMARY KEY,\n name TEXT NOT NULL UNIQUE,\n\n -- Index configuration\n dimensions INTEGER NOT NULL,\n metric TEXT DEFAULT 'cosine' CHECK(metric IN ('cosine', 'euclidean', 'dot')),\n\n -- HNSW parameters\n hnsw_m INTEGER DEFAULT 16,\n hnsw_ef_construction INTEGER DEFAULT 200,\n hnsw_ef_search INTEGER DEFAULT 100,\n\n -- Quantization\n quantization_type TEXT CHECK(quantization_type IN ('none', 'scalar', 'product')),\n quantization_bits INTEGER DEFAULT 8,\n\n -- Statistics\n total_vectors INTEGER DEFAULT 0,\n last_rebuild_at INTEGER,\n\n created_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now') * 1000),\n updated_at INTEGER NOT NULL DEFAULT (strftime('%s', 'now') * 1000)\n);\n\n-- ============================================\n-- SYSTEM METADATA\n-- ============================================\n\nCREATE TABLE IF NOT EXISTS metadata (\n key TEXT PRIMARY KEY,\n value TEXT NOT NULL,\n updated_at INTEGER DEFAULT (strftime('%s', 'now') * 1000)\n);\n";
|
|
16
16
|
interface HNSWEntry {
|
|
17
17
|
id: string;
|
|
18
18
|
key: string;
|
|
@@ -31,7 +31,7 @@ async function getBridge() {
|
|
|
31
31
|
* Vector embeddings enabled for semantic search
|
|
32
32
|
*/
|
|
33
33
|
export const MEMORY_SCHEMA_V3 = `
|
|
34
|
-
--
|
|
34
|
+
-- RuFlo V3 Memory Database
|
|
35
35
|
-- Version: 3.0.0
|
|
36
36
|
-- Features: Pattern learning, vector embeddings, temporal decay, migration tracking
|
|
37
37
|
|
|
@@ -491,7 +491,7 @@ export class PluginDiscoveryService {
|
|
|
491
491
|
id: '@claude-flow/plugins',
|
|
492
492
|
name: '@claude-flow/plugins',
|
|
493
493
|
displayName: 'Plugin SDK',
|
|
494
|
-
description: 'Unified Plugin SDK for
|
|
494
|
+
description: 'Unified Plugin SDK for RuFlo V3 - Worker, Hook, and Provider Integration. Create, test, and publish RuFlo plugins.',
|
|
495
495
|
version: '3.0.0-alpha.2',
|
|
496
496
|
cid: 'bafybeipluginsdk2024xyz',
|
|
497
497
|
size: 156000,
|
|
@@ -481,6 +481,7 @@ export class ContainerWorkerPool extends EventEmitter {
|
|
|
481
481
|
this.healthCheckTimer = setInterval(async () => {
|
|
482
482
|
await this.runHealthChecks();
|
|
483
483
|
}, this.config.healthCheckIntervalMs);
|
|
484
|
+
this.healthCheckTimer.unref();
|
|
484
485
|
}
|
|
485
486
|
/**
|
|
486
487
|
* Run health checks on all containers
|
|
@@ -522,6 +523,7 @@ export class ContainerWorkerPool extends EventEmitter {
|
|
|
522
523
|
this.idleCheckTimer = setInterval(async () => {
|
|
523
524
|
await this.runIdleChecks();
|
|
524
525
|
}, 60000); // Check every minute
|
|
526
|
+
this.idleCheckTimer.unref();
|
|
525
527
|
}
|
|
526
528
|
/**
|
|
527
529
|
* Terminate idle containers above minimum
|
|
@@ -57,6 +57,7 @@ class InMemoryStore {
|
|
|
57
57
|
if (this.cleanupTimer)
|
|
58
58
|
return;
|
|
59
59
|
this.cleanupTimer = setInterval(() => this.cleanupExpired(), 60000);
|
|
60
|
+
this.cleanupTimer.unref();
|
|
60
61
|
}
|
|
61
62
|
/**
|
|
62
63
|
* Stop cleanup timer
|
|
@@ -495,6 +496,7 @@ export class WorkerQueue extends EventEmitter {
|
|
|
495
496
|
this.store.setWorker(this.workerId, registration);
|
|
496
497
|
}
|
|
497
498
|
}, this.config.heartbeatIntervalMs);
|
|
499
|
+
this.heartbeatTimer.unref();
|
|
498
500
|
}
|
|
499
501
|
/**
|
|
500
502
|
* Stop heartbeat timer
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@claude-flow/cli",
|
|
3
|
-
"version": "3.5.
|
|
3
|
+
"version": "3.5.5",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Ruflo CLI - Enterprise AI agent orchestration with 60+ specialized agents, swarm coordination, MCP server, self-learning hooks, and vector memory for Claude Code",
|
|
6
6
|
"main": "dist/src/index.js",
|