@stackmemoryai/stackmemory 0.3.26 → 0.4.1
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/cli/commands/ralph.js +125 -188
- package/dist/cli/commands/ralph.js.map +2 -2
- package/dist/features/tui/simple-monitor.js +112 -0
- package/dist/features/tui/simple-monitor.js.map +7 -0
- package/dist/features/tui/swarm-monitor.js +644 -0
- package/dist/features/tui/swarm-monitor.js.map +7 -0
- package/dist/integrations/ralph/bridge/ralph-stackmemory-bridge.js +254 -43
- package/dist/integrations/ralph/bridge/ralph-stackmemory-bridge.js.map +3 -3
- package/dist/integrations/ralph/coordination/enhanced-coordination.js +406 -0
- package/dist/integrations/ralph/coordination/enhanced-coordination.js.map +7 -0
- package/dist/integrations/ralph/monitoring/swarm-dashboard.js +290 -0
- package/dist/integrations/ralph/monitoring/swarm-dashboard.js.map +7 -0
- package/dist/integrations/ralph/monitoring/swarm-registry.js +95 -0
- package/dist/integrations/ralph/monitoring/swarm-registry.js.map +7 -0
- package/dist/integrations/ralph/recovery/crash-recovery.js +458 -0
- package/dist/integrations/ralph/recovery/crash-recovery.js.map +7 -0
- package/dist/integrations/ralph/swarm/git-workflow-manager.js +6 -67
- package/dist/integrations/ralph/swarm/git-workflow-manager.js.map +2 -2
- package/dist/integrations/ralph/swarm/swarm-coordinator.js +5 -139
- package/dist/integrations/ralph/swarm/swarm-coordinator.js.map +2 -2
- package/package.json +2 -1
- package/scripts/test-ralph-iteration-fix.ts +118 -0
- package/scripts/test-simple-ralph-state-sync.ts +178 -0
- package/scripts/test-swarm-tui.ts +34 -0
- package/scripts/test-tui-shortcuts.ts +66 -0
- package/scripts/validate-tui-shortcuts.ts +83 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/features/tui/swarm-monitor.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Real-time TUI for monitoring Ralph Swarm operations\n * Tracks commits, status, agents, and lines edited per agent\n */\n\nimport blessed from 'blessed';\nimport { logger } from '../../core/monitoring/logger.js';\nimport { SwarmCoordinator } from '../../integrations/ralph/swarm/swarm-coordinator.js';\nimport { SwarmDashboard } from '../../integrations/ralph/monitoring/swarm-dashboard.js';\nimport { SwarmRegistry } from '../../integrations/ralph/monitoring/swarm-registry.js';\nimport { execSync } from 'child_process';\n\nexport interface SwarmCommitMetrics {\n agentId: string;\n role: string;\n commits: Array<{\n hash: string;\n message: string;\n timestamp: number;\n linesAdded: number;\n linesDeleted: number;\n filesChanged: number;\n }>;\n totalCommits: number;\n totalLinesAdded: number;\n totalLinesDeleted: number;\n lastActivity: number;\n}\n\nexport interface SwarmStatus {\n swarmId: string;\n status: 'active' | 'idle' | 'completed' | 'error';\n startTime: number;\n uptime: number;\n agents: Array<{\n id: string;\n role: string;\n status: string;\n currentTask?: string;\n iteration: number;\n lastActivity: number;\n }>;\n performance: {\n throughput: number;\n efficiency: number;\n totalTasks: number;\n completedTasks: number;\n };\n}\n\nexport class SwarmTUI {\n private screen: blessed.Widgets.Screen;\n private commitsTable: blessed.Widgets.TableElement;\n private statusBox: blessed.Widgets.BoxElement;\n private agentsTable: blessed.Widgets.TableElement;\n private metricsBox: blessed.Widgets.BoxElement;\n private logBox: blessed.Widgets.LogElement;\n\n private swarmCoordinator: SwarmCoordinator | null = null;\n private swarmDashboard: SwarmDashboard | null = null;\n private refreshInterval: NodeJS.Timeout | null = null;\n private commitMetrics: Map<string, SwarmCommitMetrics> = new Map();\n\n constructor() {\n // Detect terminal capabilities and set safe defaults\n const isGhostty =\n process.env.TERM_PROGRAM === 'ghostty' ||\n process.env.TERM?.includes('ghostty');\n const isBasicTerm =\n process.env.TERM === 'dumb' || process.env.TERM === 'unknown';\n\n this.screen = blessed.screen({\n smartCSR: !isGhostty, // Disable smart CSR for ghostty\n title: 'Ralph Swarm Monitor',\n terminal: isGhostty ? 'xterm-256color' : undefined,\n fullUnicode: !isBasicTerm,\n dockBorders: false,\n ignoreDockContrast: true,\n useBCE: false, // Disable background color erase for compatibility\n forceUnicode: false,\n debug: false,\n });\n\n // Add error handler for terminal issues\n this.screen.on('error', (err) => {\n logger.error('TUI screen error:', err);\n console.log(\n '\u26A0\uFE0F TUI display error detected. Try setting TERM=xterm-256color'\n );\n console.log(\n ' Alternative: Use stackmemory ralph status for text-based monitoring'\n );\n });\n\n this.createUI();\n this.setupKeyHandlers();\n\n logger.info('SwarmTUI initialized');\n }\n\n private createUI(): void {\n // Main layout container\n const container = blessed.box({\n parent: this.screen,\n top: 0,\n left: 0,\n width: '100%',\n height: '100%',\n style: {\n bg: 'black',\n },\n });\n\n // Detect terminal capabilities for styling\n const isGhostty =\n process.env.TERM_PROGRAM === 'ghostty' ||\n process.env.TERM?.includes('ghostty');\n const safeColors = isGhostty;\n\n // Title bar\n blessed.box({\n parent: container,\n top: 0,\n left: 0,\n width: '100%',\n height: 3,\n content: '\uD83E\uDDBE Ralph Swarm Monitor - Real-time Swarm Operations',\n style: safeColors\n ? {\n fg: 'white',\n bold: false,\n }\n : {\n bg: 'blue',\n fg: 'white',\n bold: true,\n },\n border: {\n type: 'line',\n },\n });\n\n // Status box (top right)\n this.statusBox = blessed.box({\n parent: container,\n top: 3,\n left: '50%',\n width: '50%',\n height: 8,\n label: ' Swarm Status ',\n content: 'No active swarm',\n style: {\n bg: 'black',\n fg: 'white',\n },\n border: {\n type: 'line',\n fg: 'cyan',\n },\n });\n\n // Metrics box (top left)\n this.metricsBox = blessed.box({\n parent: container,\n top: 3,\n left: 0,\n width: '50%',\n height: 8,\n label: ' Performance Metrics ',\n content: 'Waiting for data...',\n style: {\n bg: 'black',\n fg: 'white',\n },\n border: {\n type: 'line',\n fg: 'green',\n },\n });\n\n // Agents table (middle left)\n this.agentsTable = blessed.table({\n parent: container,\n top: 11,\n left: 0,\n width: '50%',\n height: 12,\n label: ' Active Agents ',\n style: {\n bg: 'black',\n fg: 'white',\n header: {\n bg: 'blue',\n fg: 'white',\n bold: true,\n },\n cell: {\n selected: {\n bg: 'blue',\n fg: 'white',\n },\n },\n },\n border: {\n type: 'line',\n fg: 'yellow',\n },\n data: [['Role', 'Status', 'Iteration', 'Task', 'Last Active']],\n });\n\n // Commits table (middle right)\n this.commitsTable = blessed.table({\n parent: container,\n top: 11,\n left: '50%',\n width: '50%',\n height: 12,\n label: ' Recent Commits ',\n style: {\n bg: 'black',\n fg: 'white',\n header: {\n bg: 'blue',\n fg: 'white',\n bold: true,\n },\n cell: {\n selected: {\n bg: 'blue',\n fg: 'white',\n },\n },\n },\n border: {\n type: 'line',\n fg: 'magenta',\n },\n data: [['Agent', 'Message', 'Lines +/-', 'Time']],\n });\n\n // Log output (bottom)\n this.logBox = blessed.log({\n parent: container,\n top: 23,\n left: 0,\n width: '100%',\n height: '100%-23',\n label: ' Swarm Logs ',\n style: {\n bg: 'black',\n fg: 'white',\n },\n border: {\n type: 'line',\n fg: 'white',\n },\n scrollable: true,\n alwaysScroll: true,\n mouse: true,\n });\n\n // Help text\n blessed.box({\n parent: container,\n bottom: 0,\n left: 0,\n width: '100%',\n height: 1,\n content:\n 'q=quit | r=refresh | s=start swarm | t=stop swarm | h=help | c=clear logs | d=detect swarms',\n style: {\n bg: 'white',\n fg: 'black',\n },\n });\n }\n\n private setupKeyHandlers(): void {\n this.screen.key(['escape', 'q', 'C-c'], () => {\n this.cleanup();\n process.exit(0);\n });\n\n this.screen.key(['r'], () => {\n this.refreshData();\n this.logBox.log('Manual refresh triggered');\n });\n\n this.screen.key(['s'], () => {\n this.startSwarmInteractive();\n });\n\n this.screen.key(['t'], () => {\n this.stopSwarmInteractive();\n });\n\n this.screen.key(['h'], () => {\n this.showHelp();\n });\n\n this.screen.key(['c'], () => {\n this.clearLogs();\n });\n\n this.screen.key(['d'], () => {\n this.showDetectedSwarms();\n });\n }\n\n /**\n * Initialize swarm monitoring\n */\n async initialize(\n swarmCoordinator?: SwarmCoordinator,\n swarmId?: string\n ): Promise<void> {\n try {\n // Connect to existing swarm if ID provided\n if (swarmId) {\n const registry = SwarmRegistry.getInstance();\n const swarm = registry.getSwarm(swarmId);\n if (swarm) {\n this.swarmCoordinator = swarm.coordinator;\n this.logBox.log(`Connected to swarm: ${swarmId}`);\n } else {\n this.logBox.log(`Swarm not found: ${swarmId}`);\n }\n } else if (swarmCoordinator) {\n this.swarmCoordinator = swarmCoordinator;\n } else {\n // Auto-detect active swarms\n const registry = SwarmRegistry.getInstance();\n const activeSwarms = registry.listActiveSwarms();\n if (activeSwarms.length > 0) {\n this.swarmCoordinator = activeSwarms[0].coordinator;\n this.logBox.log(`Auto-connected to swarm: ${activeSwarms[0].id}`);\n }\n }\n\n if (this.swarmCoordinator) {\n this.swarmDashboard = new SwarmDashboard(this.swarmCoordinator);\n this.swarmDashboard.startMonitoring(2000); // 2 second refresh\n\n // Listen to swarm events\n this.swarmDashboard.on('metricsUpdated', (metrics) => {\n this.updateUI(metrics);\n });\n }\n\n // Start refresh interval\n this.refreshInterval = setInterval(() => {\n this.refreshData();\n }, 3000);\n\n this.logBox.log('SwarmTUI monitoring initialized');\n } catch (error: unknown) {\n logger.error('Failed to initialize SwarmTUI', error as Error);\n this.logBox.log(`Error: ${(error as Error).message}`);\n }\n }\n\n /**\n * Start the TUI display\n */\n start(): void {\n this.screen.render();\n this.logBox.log('Ralph Swarm Monitor started');\n this.logBox.log('Monitoring for active swarms...');\n }\n\n /**\n * Refresh all data\n */\n private async refreshData(): Promise<void> {\n try {\n // Update commit metrics\n await this.updateCommitMetrics();\n\n // Update swarm status if coordinator available\n if (this.swarmCoordinator) {\n const status = this.getSwarmStatus();\n this.updateStatusDisplay(status);\n } else {\n // Try to detect active swarms\n await this.detectActiveSwarms();\n }\n\n this.screen.render();\n } catch (error: unknown) {\n logger.error('Failed to refresh TUI data', error as Error);\n this.logBox.log(`Refresh error: ${(error as Error).message}`);\n }\n }\n\n /**\n * Update commit metrics for all agents\n */\n private async updateCommitMetrics(): Promise<void> {\n try {\n // Get recent commits from git log\n const gitLog = execSync(\n 'git log --oneline --since=\"1 hour ago\" --pretty=format:\"%H|%an|%s|%ct\" --numstat',\n { encoding: 'utf8', cwd: process.cwd() }\n );\n\n const commits = this.parseGitCommits(gitLog);\n this.updateCommitsTable(commits);\n } catch {\n // Git might fail if no commits, that's okay\n this.logBox.log('No recent commits found');\n }\n }\n\n /**\n * Parse git log output into commit data\n */\n private parseGitCommits(gitLog: string): Array<{\n hash: string;\n agent: string;\n message: string;\n timestamp: number;\n linesAdded: number;\n linesDeleted: number;\n }> {\n const commits = [];\n const lines = gitLog.split('\\n').filter(Boolean);\n\n let currentCommit: any = null;\n\n for (const line of lines) {\n if (line.includes('|')) {\n // Commit info line\n const [hash, author, message, timestamp] = line.split('|');\n currentCommit = {\n hash: hash.substring(0, 8),\n agent: this.extractAgentFromAuthor(author),\n message: message.substring(0, 50),\n timestamp: parseInt(timestamp),\n linesAdded: 0,\n linesDeleted: 0,\n };\n } else if (currentCommit && line.match(/^\\d+\\s+\\d+/)) {\n // Stat line (added/deleted)\n const [added, deleted] = line.split('\\t')[0].split(' ');\n currentCommit.linesAdded += parseInt(added) || 0;\n currentCommit.linesDeleted += parseInt(deleted) || 0;\n\n commits.push({ ...currentCommit });\n currentCommit = null;\n }\n }\n\n return commits.slice(0, 10); // Show last 10 commits\n }\n\n /**\n * Extract agent info from git author\n */\n private extractAgentFromAuthor(author: string): string {\n // Look for [agent_role] pattern in commit author or message\n const agentMatch = author.match(/\\[(\\w+)\\]/);\n if (agentMatch) {\n return agentMatch[1];\n }\n\n // Fallback to checking if author contains known agent roles\n const roles = [\n 'developer',\n 'tester',\n 'optimizer',\n 'documenter',\n 'architect',\n ];\n for (const role of roles) {\n if (author.toLowerCase().includes(role)) {\n return role;\n }\n }\n\n return 'user';\n }\n\n /**\n * Update commits table display\n */\n private updateCommitsTable(commits: any[]): void {\n const tableData = [['Agent', 'Message', 'Lines +/-', 'Time']];\n\n for (const commit of commits) {\n const timeAgo = this.formatTimeAgo(commit.timestamp * 1000);\n const linesChange = `+${commit.linesAdded}/-${commit.linesDeleted}`;\n\n tableData.push([commit.agent, commit.message, linesChange, timeAgo]);\n }\n\n this.commitsTable.setData(tableData);\n }\n\n /**\n * Get current swarm status\n */\n private getSwarmStatus(): SwarmStatus | null {\n if (!this.swarmCoordinator) return null;\n\n const usage = this.swarmCoordinator.getResourceUsage();\n const swarmState = (this.swarmCoordinator as any).swarmState;\n\n if (!swarmState) return null;\n\n return {\n swarmId: swarmState.id,\n status: swarmState.status,\n startTime: swarmState.startTime,\n uptime: Date.now() - swarmState.startTime,\n agents: usage.activeAgents\n ? Array.from(\n (this.swarmCoordinator as any).activeAgents?.values() || []\n ).map((agent: any) => ({\n id: agent.id,\n role: agent.role,\n status: agent.status,\n currentTask: agent.currentTask,\n iteration: agent.performance?.tasksCompleted || 0,\n lastActivity: agent.performance?.lastFreshStart || Date.now(),\n }))\n : [],\n performance: {\n throughput: swarmState.performance?.throughput || 0,\n efficiency: swarmState.performance?.efficiency || 0,\n totalTasks: swarmState.totalTaskCount || 0,\n completedTasks: swarmState.completedTaskCount || 0,\n },\n };\n }\n\n /**\n * Update status display\n */\n private updateStatusDisplay(status: SwarmStatus | null): void {\n if (!status) {\n this.statusBox.setContent('No active swarm detected');\n this.agentsTable.setData([\n ['Role', 'Status', 'Iteration', 'Task', 'Last Active'],\n ]);\n this.metricsBox.setContent('Waiting for swarm data...');\n return;\n }\n\n // Update status box\n const uptimeStr = this.formatDuration(status.uptime);\n const statusContent = `Swarm: ${status.swarmId.substring(0, 8)}\nStatus: ${status.status.toUpperCase()}\nUptime: ${uptimeStr}\nAgents: ${status.agents.length}`;\n\n this.statusBox.setContent(statusContent);\n\n // Update agents table\n const agentData = [['Role', 'Status', 'Iteration', 'Task', 'Last Active']];\n for (const agent of status.agents) {\n const lastActivity = this.formatTimeAgo(agent.lastActivity);\n const task = agent.currentTask\n ? agent.currentTask.substring(0, 20)\n : 'idle';\n\n agentData.push([\n agent.role,\n agent.status,\n agent.iteration.toString(),\n task,\n lastActivity,\n ]);\n }\n this.agentsTable.setData(agentData);\n\n // Update metrics box\n const metricsContent = `Throughput: ${status.performance.throughput.toFixed(2)} tasks/min\nEfficiency: ${(status.performance.efficiency * 100).toFixed(1)}%\nTasks: ${status.performance.completedTasks}/${status.performance.totalTasks}\nSuccess Rate: ${status.performance.efficiency > 0 ? (status.performance.efficiency * 100).toFixed(1) : 'N/A'}%`;\n\n this.metricsBox.setContent(metricsContent);\n }\n\n /**\n * Update UI with metrics from dashboard\n */\n private updateUI(metrics: any): void {\n this.logBox.log(\n `Metrics updated: ${metrics.status} - ${metrics.activeAgents} agents`\n );\n }\n\n /**\n * Detect active swarms in the system\n */\n private async detectActiveSwarms(): Promise<void> {\n try {\n const registry = SwarmRegistry.getInstance();\n const activeSwarms = registry.listActiveSwarms();\n const stats = registry.getStatistics();\n\n if (activeSwarms.length > 0) {\n let statusContent = `Available Swarms (${activeSwarms.length}):\\n`;\n for (const swarm of activeSwarms.slice(0, 3)) {\n const uptime = this.formatDuration(Date.now() - swarm.startTime);\n statusContent += `\u2022 ${swarm.id.substring(0, 8)}: ${swarm.status} (${uptime})\\n`;\n }\n if (activeSwarms.length > 3) {\n statusContent += `... and ${activeSwarms.length - 3} more`;\n }\n this.statusBox.setContent(statusContent);\n this.logBox.log(\n `Found ${activeSwarms.length} active swarms in registry`\n );\n } else {\n // Check for Ralph processes as fallback\n const ralphProcesses = execSync(\n 'ps aux | grep \"ralph\" | grep -v grep',\n { encoding: 'utf8' }\n );\n\n if (ralphProcesses.trim()) {\n this.logBox.log('Detected Ralph processes running');\n this.statusBox.setContent(\n 'External Ralph processes detected\\n(Use swarm coordinator for full monitoring)'\n );\n } else {\n this.statusBox.setContent(`No active swarms detected\nTotal swarms: ${stats.totalSwarms}\nCompleted: ${stats.completedSwarms}\n\nRun: stackmemory ralph swarm <task>`);\n }\n }\n } catch {\n // No processes found, that's fine\n }\n }\n\n /**\n * Format time ago string\n */\n private formatTimeAgo(timestamp: number): string {\n const diff = Date.now() - timestamp;\n const minutes = Math.floor(diff / 60000);\n const hours = Math.floor(minutes / 60);\n const days = Math.floor(hours / 24);\n\n if (days > 0) return `${days}d ago`;\n if (hours > 0) return `${hours}h ago`;\n if (minutes > 0) return `${minutes}m ago`;\n return 'just now';\n }\n\n /**\n * Format duration string\n */\n private formatDuration(ms: number): string {\n const seconds = Math.floor(ms / 1000);\n const minutes = Math.floor(seconds / 60);\n const hours = Math.floor(minutes / 60);\n\n if (hours > 0) return `${hours}h ${minutes % 60}m`;\n if (minutes > 0) return `${minutes}m ${seconds % 60}s`;\n return `${seconds}s`;\n }\n\n /**\n * Start swarm interactively\n */\n private startSwarmInteractive(): void {\n this.logBox.log('\uD83D\uDE80 Start Swarm Interactive Mode:');\n this.logBox.log(\n 'Example: stackmemory ralph swarm \"Implement feature\" --agents developer,tester'\n );\n this.logBox.log(\n 'Tip: Run the command in another terminal, then press \"d\" to detect it'\n );\n }\n\n /**\n * Stop swarm interactively\n */\n private stopSwarmInteractive(): void {\n if (this.swarmCoordinator) {\n this.logBox.log('\uD83D\uDED1 Stopping current swarm...');\n // In a real implementation, we'd call swarmCoordinator.stop()\n this.logBox.log(\n 'Note: Swarm stopping not yet implemented - use Ctrl+C in swarm terminal'\n );\n } else {\n this.logBox.log('\u274C No active swarm coordinator to stop');\n this.logBox.log('External Ralph processes must be stopped manually');\n }\n }\n\n /**\n * Show help dialog\n */\n private showHelp(): void {\n this.logBox.log('\uD83E\uDDBE Ralph Swarm Monitor - Help');\n this.logBox.log('');\n this.logBox.log('Keyboard Shortcuts:');\n this.logBox.log(' q, Esc, Ctrl+C - Quit TUI');\n this.logBox.log(' r - Refresh data manually');\n this.logBox.log(' s - Show start swarm commands');\n this.logBox.log(' t - Stop current swarm');\n this.logBox.log(' h - Show this help');\n this.logBox.log(' c - Clear log output');\n this.logBox.log(' d - Detect and list available swarms');\n this.logBox.log('');\n this.logBox.log('Usage:');\n this.logBox.log(\n ' stackmemory ralph tui # Auto-detect swarms'\n );\n this.logBox.log(\n ' stackmemory ralph tui --swarm-id <id> # Monitor specific swarm'\n );\n this.logBox.log('');\n this.logBox.log('Starting Swarms:');\n this.logBox.log(\n ' stackmemory ralph swarm \"Task description\" --agents developer,tester'\n );\n this.logBox.log('');\n }\n\n /**\n * Clear log output\n */\n private clearLogs(): void {\n this.logBox.setContent('');\n this.logBox.log('\uD83D\uDCDD Logs cleared - monitoring continues...');\n }\n\n /**\n * Show detected swarms\n */\n private async showDetectedSwarms(): Promise<void> {\n this.logBox.log('\uD83D\uDD0D Detecting active swarms...');\n\n try {\n const registry = SwarmRegistry.getInstance();\n const activeSwarms = registry.listActiveSwarms();\n const stats = registry.getStatistics();\n\n this.logBox.log('');\n this.logBox.log('\uD83D\uDCCA Swarm Registry Status:');\n this.logBox.log(` Total swarms: ${stats.totalSwarms}`);\n this.logBox.log(` Active swarms: ${stats.activeSwarms}`);\n this.logBox.log(` Completed swarms: ${stats.completedSwarms}`);\n\n if (activeSwarms.length > 0) {\n this.logBox.log('');\n this.logBox.log('\uD83E\uDDBE Active Swarms:');\n\n for (const swarm of activeSwarms) {\n const uptime = this.formatDuration(Date.now() - swarm.startTime);\n this.logBox.log(` \u2022 ${swarm.id}: ${swarm.description} (${uptime})`);\n }\n\n this.logBox.log('');\n this.logBox.log('\uD83D\uDCA1 Use --swarm-id to connect to specific swarm');\n } else {\n this.logBox.log('');\n this.logBox.log('\u274C No active swarms in registry');\n\n // Check for external processes\n try {\n const ralphProcesses = execSync(\n 'ps aux | grep \"ralph\" | grep -v grep',\n { encoding: 'utf8' }\n );\n if (ralphProcesses.trim()) {\n this.logBox.log('\uD83D\uDD0D External Ralph processes detected:');\n ralphProcesses\n .split('\\n')\n .filter((line) => line.trim())\n .forEach((line) => {\n const parts = line.split(/\\s+/);\n this.logBox.log(\n ` PID ${parts[1]}: ${parts.slice(10).join(' ').slice(0, 60)}`\n );\n });\n }\n } catch {\n this.logBox.log('\uD83D\uDD0D No external Ralph processes found');\n }\n\n this.logBox.log('');\n this.logBox.log(\n '\uD83D\uDCA1 Start a swarm: stackmemory ralph swarm \"Task\" --agents developer'\n );\n }\n } catch (error: unknown) {\n this.logBox.log(`\u274C Detection failed: ${(error as Error).message}`);\n }\n }\n\n /**\n * Cleanup resources\n */\n private cleanup(): void {\n if (this.refreshInterval) {\n clearInterval(this.refreshInterval);\n }\n\n if (this.swarmDashboard) {\n this.swarmDashboard.stopMonitoring();\n }\n\n logger.info('SwarmTUI cleaned up');\n }\n}\n\nexport default SwarmTUI;\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -5,10 +5,11 @@ import { execSync } from "child_process";
|
|
|
5
5
|
import { logger } from "../../../core/monitoring/logger.js";
|
|
6
6
|
import { FrameManager } from "../../../core/context/frame-manager.js";
|
|
7
7
|
import { SessionManager } from "../../../core/session/session-manager.js";
|
|
8
|
-
import { SQLiteAdapter } from "../../../core/database/sqlite-adapter.js";
|
|
9
8
|
import { ContextBudgetManager } from "../context/context-budget-manager.js";
|
|
10
9
|
import { StateReconciler } from "../state/state-reconciler.js";
|
|
11
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
IterationLifecycle
|
|
12
|
+
} from "../lifecycle/iteration-lifecycle.js";
|
|
12
13
|
import { PerformanceOptimizer } from "../performance/performance-optimizer.js";
|
|
13
14
|
class RalphStackMemoryBridge {
|
|
14
15
|
state;
|
|
@@ -46,11 +47,19 @@ class RalphStackMemoryBridge {
|
|
|
46
47
|
sessionId: options?.sessionId
|
|
47
48
|
});
|
|
48
49
|
this.state.currentSession = session;
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
50
|
+
if (session.database && session.projectId) {
|
|
51
|
+
this.frameManager = new FrameManager(
|
|
52
|
+
session.database,
|
|
53
|
+
session.projectId,
|
|
54
|
+
{
|
|
55
|
+
skipContextBridge: true
|
|
56
|
+
}
|
|
57
|
+
);
|
|
58
|
+
} else {
|
|
59
|
+
throw new Error(
|
|
60
|
+
"Session database not available for FrameManager initialization"
|
|
61
|
+
);
|
|
62
|
+
}
|
|
54
63
|
if (options?.loopId) {
|
|
55
64
|
await this.resumeLoop(options.loopId);
|
|
56
65
|
} else if (options?.task && options?.criteria) {
|
|
@@ -183,7 +192,9 @@ class RalphStackMemoryBridge {
|
|
|
183
192
|
throw new Error(`Session not found: ${sessionId}`);
|
|
184
193
|
}
|
|
185
194
|
const frames = await this.loadSessionFrames(sessionId);
|
|
186
|
-
const ralphFrames = frames.filter(
|
|
195
|
+
const ralphFrames = frames.filter(
|
|
196
|
+
(f) => f.type === "task" && f.name.startsWith("ralph-")
|
|
197
|
+
);
|
|
187
198
|
if (ralphFrames.length === 0) {
|
|
188
199
|
throw new Error("No Ralph loops found in session");
|
|
189
200
|
}
|
|
@@ -242,7 +253,9 @@ class RalphStackMemoryBridge {
|
|
|
242
253
|
async restoreFromCheckpoint(checkpointId) {
|
|
243
254
|
const lifecycle = this.getLifecycle();
|
|
244
255
|
await lifecycle.restoreFromCheckpoint(checkpointId);
|
|
245
|
-
const sources = await this.gatherStateSources(
|
|
256
|
+
const sources = await this.gatherStateSources(
|
|
257
|
+
this.state.activeLoop?.loopId || ""
|
|
258
|
+
);
|
|
246
259
|
const reconciledState = await this.state.stateReconciler.reconcile(sources);
|
|
247
260
|
this.state.activeLoop = reconciledState;
|
|
248
261
|
logger.info("Restored from checkpoint", {
|
|
@@ -256,6 +269,29 @@ class RalphStackMemoryBridge {
|
|
|
256
269
|
getPerformanceMetrics() {
|
|
257
270
|
return this.state.performanceOptimizer.getMetrics();
|
|
258
271
|
}
|
|
272
|
+
/**
|
|
273
|
+
* Start a new Ralph loop
|
|
274
|
+
*/
|
|
275
|
+
async startLoop(options) {
|
|
276
|
+
const state = await this.createNewLoop(options.task, options.criteria);
|
|
277
|
+
return state.loopId;
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Stop the active loop
|
|
281
|
+
*/
|
|
282
|
+
async stopLoop() {
|
|
283
|
+
if (!this.state.activeLoop) {
|
|
284
|
+
logger.warn("No active loop to stop");
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
this.state.activeLoop.status = "completed";
|
|
288
|
+
this.state.activeLoop.lastUpdateTime = Date.now();
|
|
289
|
+
await this.saveLoopState(this.state.activeLoop);
|
|
290
|
+
const lifecycle = this.getLifecycle();
|
|
291
|
+
await lifecycle.handleCompletion(this.state.activeLoop);
|
|
292
|
+
logger.info("Ralph loop stopped", { loopId: this.state.activeLoop.loopId });
|
|
293
|
+
this.state.activeLoop = void 0;
|
|
294
|
+
}
|
|
259
295
|
/**
|
|
260
296
|
* Cleanup resources
|
|
261
297
|
*/
|
|
@@ -357,7 +393,10 @@ class RalphStackMemoryBridge {
|
|
|
357
393
|
await fs.mkdir(this.ralphDir, { recursive: true });
|
|
358
394
|
await fs.mkdir(path.join(this.ralphDir, "history"), { recursive: true });
|
|
359
395
|
await fs.writeFile(path.join(this.ralphDir, "task.md"), state.task);
|
|
360
|
-
await fs.writeFile(
|
|
396
|
+
await fs.writeFile(
|
|
397
|
+
path.join(this.ralphDir, "completion-criteria.md"),
|
|
398
|
+
state.criteria
|
|
399
|
+
);
|
|
361
400
|
await fs.writeFile(path.join(this.ralphDir, "iteration.txt"), "0");
|
|
362
401
|
await fs.writeFile(path.join(this.ralphDir, "feedback.txt"), "");
|
|
363
402
|
await fs.writeFile(
|
|
@@ -385,12 +424,7 @@ class RalphStackMemoryBridge {
|
|
|
385
424
|
status: "started"
|
|
386
425
|
}
|
|
387
426
|
};
|
|
388
|
-
return await this.frameManager.
|
|
389
|
-
name: frame.name,
|
|
390
|
-
type: frame.type,
|
|
391
|
-
content: frame.content || "",
|
|
392
|
-
metadata: frame.metadata
|
|
393
|
-
});
|
|
427
|
+
return await this.frameManager.pushFrame(frame);
|
|
394
428
|
}
|
|
395
429
|
/**
|
|
396
430
|
* Load iteration context from StackMemory
|
|
@@ -430,29 +464,206 @@ class RalphStackMemoryBridge {
|
|
|
430
464
|
* Execute worker iteration
|
|
431
465
|
*/
|
|
432
466
|
async executeWorkerIteration(context) {
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
analysis
|
|
437
|
-
|
|
467
|
+
const iterationNumber = context.task.currentIteration + 1;
|
|
468
|
+
try {
|
|
469
|
+
const analysis = await this.analyzeCodebaseState();
|
|
470
|
+
const plan = await this.generateIterationPlan(context, analysis);
|
|
471
|
+
const changes = await this.executeIterationChanges(plan, context);
|
|
472
|
+
const validation = await this.validateIterationResults(changes);
|
|
473
|
+
logger.info("Iteration execution completed", {
|
|
474
|
+
iteration: iterationNumber,
|
|
475
|
+
changesCount: changes.length,
|
|
476
|
+
testsPass: validation.testsPass
|
|
477
|
+
});
|
|
478
|
+
return {
|
|
479
|
+
number: iterationNumber,
|
|
480
|
+
timestamp: Date.now(),
|
|
481
|
+
analysis,
|
|
482
|
+
plan,
|
|
483
|
+
changes,
|
|
484
|
+
validation
|
|
485
|
+
};
|
|
486
|
+
} catch (error) {
|
|
487
|
+
logger.error("Iteration execution failed", error);
|
|
488
|
+
return {
|
|
489
|
+
number: iterationNumber,
|
|
490
|
+
timestamp: Date.now(),
|
|
491
|
+
analysis: {
|
|
492
|
+
filesCount: 0,
|
|
493
|
+
testsPass: false,
|
|
494
|
+
testsFail: 1,
|
|
495
|
+
lastChange: `Error: ${error.message}`
|
|
496
|
+
},
|
|
497
|
+
plan: {
|
|
498
|
+
summary: "Iteration failed due to error",
|
|
499
|
+
steps: ["Investigate error", "Fix underlying issue"],
|
|
500
|
+
priority: "high"
|
|
501
|
+
},
|
|
502
|
+
changes: [],
|
|
503
|
+
validation: {
|
|
504
|
+
testsPass: false,
|
|
505
|
+
lintClean: false,
|
|
506
|
+
buildSuccess: false,
|
|
507
|
+
errors: [error.message],
|
|
508
|
+
warnings: []
|
|
509
|
+
}
|
|
510
|
+
};
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
/**
|
|
514
|
+
* Analyze current codebase state
|
|
515
|
+
*/
|
|
516
|
+
async analyzeCodebaseState() {
|
|
517
|
+
try {
|
|
518
|
+
const stats = {
|
|
519
|
+
filesCount: 0,
|
|
438
520
|
testsPass: true,
|
|
439
521
|
testsFail: 0,
|
|
440
|
-
lastChange: "
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
522
|
+
lastChange: "No recent changes"
|
|
523
|
+
};
|
|
524
|
+
try {
|
|
525
|
+
const { execSync: execSync2 } = await import("child_process");
|
|
526
|
+
const output = execSync2(
|
|
527
|
+
'find . -type f -name "*.ts" -o -name "*.js" -o -name "*.json" | grep -v node_modules | grep -v .git | wc -l',
|
|
528
|
+
{ encoding: "utf8", cwd: process.cwd() }
|
|
529
|
+
);
|
|
530
|
+
stats.filesCount = parseInt(output.trim()) || 0;
|
|
531
|
+
} catch {
|
|
532
|
+
stats.filesCount = 0;
|
|
533
|
+
}
|
|
534
|
+
try {
|
|
535
|
+
const { execSync: execSync2 } = await import("child_process");
|
|
536
|
+
const gitLog = execSync2("git log -1 --oneline", {
|
|
537
|
+
encoding: "utf8",
|
|
538
|
+
cwd: process.cwd()
|
|
539
|
+
});
|
|
540
|
+
stats.lastChange = gitLog.trim() || "No git history";
|
|
541
|
+
} catch {
|
|
542
|
+
stats.lastChange = "No git repository";
|
|
543
|
+
}
|
|
544
|
+
try {
|
|
545
|
+
const { existsSync } = await import("fs");
|
|
546
|
+
if (existsSync("package.json")) {
|
|
547
|
+
const packageJson = JSON.parse(
|
|
548
|
+
await fs.readFile("package.json", "utf8")
|
|
549
|
+
);
|
|
550
|
+
if (packageJson.scripts?.test) {
|
|
551
|
+
const { execSync: execSync2 } = await import("child_process");
|
|
552
|
+
execSync2("npm test", { stdio: "pipe", timeout: 3e4 });
|
|
553
|
+
stats.testsPass = true;
|
|
554
|
+
stats.testsFail = 0;
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
} catch {
|
|
558
|
+
stats.testsPass = false;
|
|
559
|
+
stats.testsFail = 1;
|
|
454
560
|
}
|
|
561
|
+
return stats;
|
|
562
|
+
} catch (error) {
|
|
563
|
+
return {
|
|
564
|
+
filesCount: 0,
|
|
565
|
+
testsPass: false,
|
|
566
|
+
testsFail: 1,
|
|
567
|
+
lastChange: `Analysis failed: ${error.message}`
|
|
568
|
+
};
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
/**
|
|
572
|
+
* Generate iteration plan based on context and analysis
|
|
573
|
+
*/
|
|
574
|
+
async generateIterationPlan(context, analysis) {
|
|
575
|
+
const task = context.task.task || "Complete assigned work";
|
|
576
|
+
const criteria = context.task.criteria || "Meet completion criteria";
|
|
577
|
+
const steps = [];
|
|
578
|
+
if (!analysis.testsPass) {
|
|
579
|
+
steps.push("Fix failing tests");
|
|
580
|
+
}
|
|
581
|
+
if (analysis.filesCount === 0) {
|
|
582
|
+
steps.push("Initialize project structure");
|
|
583
|
+
}
|
|
584
|
+
if (task.toLowerCase().includes("implement")) {
|
|
585
|
+
steps.push("Implement required functionality");
|
|
586
|
+
steps.push("Add appropriate tests");
|
|
587
|
+
} else if (task.toLowerCase().includes("fix")) {
|
|
588
|
+
steps.push("Identify root cause");
|
|
589
|
+
steps.push("Implement fix");
|
|
590
|
+
steps.push("Verify fix works");
|
|
591
|
+
} else {
|
|
592
|
+
steps.push("Analyze requirements");
|
|
593
|
+
steps.push("Plan implementation approach");
|
|
594
|
+
steps.push("Execute planned work");
|
|
595
|
+
}
|
|
596
|
+
steps.push("Validate changes");
|
|
597
|
+
return {
|
|
598
|
+
summary: `Iteration plan for: ${task}`,
|
|
599
|
+
steps,
|
|
600
|
+
priority: analysis.testsPass ? "medium" : "high"
|
|
601
|
+
};
|
|
602
|
+
}
|
|
603
|
+
/**
|
|
604
|
+
* Execute planned changes
|
|
605
|
+
*/
|
|
606
|
+
async executeIterationChanges(plan, context) {
|
|
607
|
+
const changes = [];
|
|
608
|
+
for (let i = 0; i < plan.steps.length; i++) {
|
|
609
|
+
const step = plan.steps[i];
|
|
610
|
+
changes.push({
|
|
611
|
+
type: "step_execution",
|
|
612
|
+
description: step,
|
|
613
|
+
timestamp: Date.now(),
|
|
614
|
+
files_affected: [],
|
|
615
|
+
success: true
|
|
616
|
+
});
|
|
617
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
618
|
+
}
|
|
619
|
+
logger.debug("Executed iteration changes", {
|
|
620
|
+
stepsCount: plan.steps.length,
|
|
621
|
+
changesCount: changes.length
|
|
622
|
+
});
|
|
623
|
+
return changes;
|
|
624
|
+
}
|
|
625
|
+
/**
|
|
626
|
+
* Validate iteration results
|
|
627
|
+
*/
|
|
628
|
+
async validateIterationResults(changes) {
|
|
629
|
+
const validation = {
|
|
630
|
+
testsPass: true,
|
|
631
|
+
lintClean: true,
|
|
632
|
+
buildSuccess: true,
|
|
633
|
+
errors: [],
|
|
634
|
+
warnings: []
|
|
455
635
|
};
|
|
636
|
+
try {
|
|
637
|
+
const { existsSync } = await import("fs");
|
|
638
|
+
if (existsSync("package.json")) {
|
|
639
|
+
const packageJson = JSON.parse(
|
|
640
|
+
await fs.readFile("package.json", "utf8")
|
|
641
|
+
);
|
|
642
|
+
if (packageJson.scripts?.lint) {
|
|
643
|
+
try {
|
|
644
|
+
const { execSync: execSync2 } = await import("child_process");
|
|
645
|
+
execSync2("npm run lint", { stdio: "pipe", timeout: 3e4 });
|
|
646
|
+
validation.lintClean = true;
|
|
647
|
+
} catch (error) {
|
|
648
|
+
validation.lintClean = false;
|
|
649
|
+
validation.warnings.push("Lint warnings detected");
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
if (packageJson.scripts?.build) {
|
|
653
|
+
try {
|
|
654
|
+
const { execSync: execSync2 } = await import("child_process");
|
|
655
|
+
execSync2("npm run build", { stdio: "pipe", timeout: 6e4 });
|
|
656
|
+
validation.buildSuccess = true;
|
|
657
|
+
} catch (error) {
|
|
658
|
+
validation.buildSuccess = false;
|
|
659
|
+
validation.errors.push("Build failed");
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
} catch (error) {
|
|
664
|
+
validation.errors.push(`Validation error: ${error.message}`);
|
|
665
|
+
}
|
|
666
|
+
return validation;
|
|
456
667
|
}
|
|
457
668
|
/**
|
|
458
669
|
* Save iteration results
|
|
@@ -490,14 +701,6 @@ class RalphStackMemoryBridge {
|
|
|
490
701
|
};
|
|
491
702
|
await this.state.performanceOptimizer.saveFrame(frame);
|
|
492
703
|
}
|
|
493
|
-
/**
|
|
494
|
-
* Get database adapter for FrameManager
|
|
495
|
-
*/
|
|
496
|
-
async getDatabaseAdapter() {
|
|
497
|
-
const dbPath = path.join(this.ralphDir, "stackmemory.db");
|
|
498
|
-
const projectId = path.basename(this.ralphDir);
|
|
499
|
-
return new SQLiteAdapter(projectId, { dbPath });
|
|
500
|
-
}
|
|
501
704
|
/**
|
|
502
705
|
* Additional helper methods
|
|
503
706
|
*/
|
|
@@ -520,6 +723,14 @@ class RalphStackMemoryBridge {
|
|
|
520
723
|
path.join(this.ralphDir, "state.json"),
|
|
521
724
|
JSON.stringify(state, null, 2)
|
|
522
725
|
);
|
|
726
|
+
await fs.writeFile(
|
|
727
|
+
path.join(this.ralphDir, "iteration.txt"),
|
|
728
|
+
state.iteration.toString()
|
|
729
|
+
);
|
|
730
|
+
logger.debug("Saved loop state", {
|
|
731
|
+
iteration: state.iteration,
|
|
732
|
+
status: state.status
|
|
733
|
+
});
|
|
523
734
|
}
|
|
524
735
|
async gatherStateSources(loopId) {
|
|
525
736
|
const sources = [];
|