aiwg
Version:
Deployment tool and support utility for AI context. Copies agents, skills, commands, rules, and behaviors into the paths each AI platform reads (Claude Code, Codex, Copilot, Cursor, Warp, OpenClaw, and 6 more) so one source of truth works across 10 platfo
161 lines (132 loc) • 4.69 kB
JavaScript
/**
* Ralph Resume - Resume an interrupted loop
*
* Multi-loop support: Auto-detect single loop or require --loop-id for multiple loops.
*
* @module tools/ralph/ralph-resume
*/
import { MultiLoopStateManager } from './state-manager-sync.mjs';
function displayActiveLoops(stateManager) {
const activeLoops = stateManager.listActiveLoops();
if (activeLoops.length === 0) {
console.log('\nNo Ralph loops to resume.\n');
return;
}
console.log('\nAvailable Ralph Loops:');
console.log('─'.repeat(40));
for (const loop of activeLoops) {
const state = stateManager.getLoopState(loop.loop_id);
console.log(`${loop.loop_id}`);
console.log(` Task: ${state.task}`);
console.log(` Status: ${state.status}`);
console.log(` Iteration: ${state.currentIteration}/${state.maxIterations}`);
console.log('');
}
}
async function main() {
const args = process.argv.slice(2);
// Parse arguments
let loopId = null;
let maxIterations = null;
let timeout = null;
for (let i = 0; i < args.length; i++) {
const arg = args[i];
if (arg === '--loop-id' && args[i + 1]) {
loopId = args[++i];
} else if (arg === '--max-iterations' && args[i + 1]) {
maxIterations = parseInt(args[++i], 10);
} else if (arg === '--timeout' && args[i + 1]) {
timeout = parseInt(args[++i], 10);
}
}
const projectRoot = process.cwd();
const stateManager = new MultiLoopStateManager(projectRoot);
const activeLoops = stateManager.listActiveLoops();
// No loops available
if (activeLoops.length === 0) {
console.log('\nNo Ralph loop to resume.');
console.log('Start one with: aiwg ralph "task" --completion "criteria"\n');
return;
}
// Auto-detect single loop
if (!loopId) {
if (activeLoops.length === 1) {
loopId = activeLoops[0].loop_id;
} else {
// Multiple loops - require --loop-id
console.error(
`\nError: Multiple Ralph loops available (${activeLoops.length}). Specify --loop-id <id>\n`
);
displayActiveLoops(stateManager);
process.exit(1);
}
}
// Get and resume loop
try {
const state = stateManager.getLoopState(loopId);
// Check if loop can be resumed
if (state.status === 'success') {
console.log(`\nRalph loop ${loopId} completed successfully.`);
console.log('Start a new loop with: aiwg ralph "task" --completion "criteria"\n');
return;
}
if (state.status === 'aborted') {
console.log(`\nRalph loop ${loopId} was aborted.`);
console.log('Start fresh with: aiwg ralph "task" --completion "criteria"\n');
return;
}
// Apply overrides
const updates = {
active: true,
status: 'running',
};
if (maxIterations) {
updates.maxIterations = maxIterations;
}
if (timeout) {
updates.timeoutMinutes = timeout;
updates.timeoutMs = timeout * 60 * 1000;
// Reset timeout start to now
updates.startTimeMs = Date.now();
}
// Update state
stateManager.updateLoopState(loopId, updates);
console.log('\n═══════════════════════════════════════════');
console.log(`Resuming Ralph Loop: ${loopId}`);
console.log('═══════════════════════════════════════════\n');
console.log(`Task: ${state.task}`);
console.log(`Completion: ${state.completion}`);
console.log(`Previous iterations: ${state.currentIteration}`);
console.log(
`Remaining iterations: ${(maxIterations || state.maxIterations) - state.currentIteration}`
);
console.log('');
if (state.lastResult) {
console.log(`Last result: ${state.lastResult}`);
}
if (state.learnings) {
console.log(`Learnings so far: ${state.learnings}`);
}
// Generate skill prompt for resume
const skillPrompt = `/ralph-resume --loop-id ${loopId}${maxIterations ? ` --max-iterations ${maxIterations}` : ''}${timeout ? ` --timeout ${timeout}` : ''}`;
console.log('');
console.log('To continue in an agentic environment:');
console.log('─'.repeat(50));
console.log(skillPrompt);
console.log('─'.repeat(50));
console.log('');
} catch (err) {
console.error(`Error: ${err.message}`);
// Show available loops
if (err.message.includes('Loop not found')) {
console.log('\nAvailable loops:');
displayActiveLoops(stateManager);
}
process.exit(1);
}
}
main().catch((err) => {
console.error(`Error: ${err.message}`);
process.exit(1);
});