coder-config 0.44.20 → 0.44.22
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/lib/constants.js +1 -1
- package/lib/loops.js +2 -0
- package/package.json +1 -1
- package/ui/dist/assets/{index-BuO1jFRz.js → index-kIL2LVeI.js} +151 -151
- package/ui/dist/index.html +1 -1
- package/ui/routes/loops.js +133 -42
package/ui/dist/index.html
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
|
|
20
20
|
<!-- PWA Manifest -->
|
|
21
21
|
<link rel="manifest" href="/manifest.json">
|
|
22
|
-
<script type="module" crossorigin src="/assets/index-
|
|
22
|
+
<script type="module" crossorigin src="/assets/index-kIL2LVeI.js"></script>
|
|
23
23
|
<link rel="stylesheet" crossorigin href="/assets/index-DAbOgCcu.css">
|
|
24
24
|
</head>
|
|
25
25
|
<body>
|
package/ui/routes/loops.js
CHANGED
|
@@ -241,37 +241,55 @@ function recordIteration(manager, id, iteration) {
|
|
|
241
241
|
}
|
|
242
242
|
|
|
243
243
|
/**
|
|
244
|
-
* Check if loop hooks are installed
|
|
244
|
+
* Check if loop hooks are installed and registered in Claude Code settings
|
|
245
245
|
*/
|
|
246
246
|
function getLoopHookStatus() {
|
|
247
|
-
|
|
248
|
-
const
|
|
249
|
-
const
|
|
250
|
-
const
|
|
251
|
-
|
|
252
|
-
//
|
|
253
|
-
const
|
|
254
|
-
const
|
|
255
|
-
|
|
247
|
+
const claudeSettingsPath = path.join(os.homedir(), '.claude', 'settings.json');
|
|
248
|
+
const claudeHooksDir = path.join(os.homedir(), '.claude', 'hooks');
|
|
249
|
+
const stopHookPath = path.join(claudeHooksDir, 'ralph-loop-stop.sh');
|
|
250
|
+
const prepromptHookPath = path.join(claudeHooksDir, 'ralph-loop-preprompt.sh');
|
|
251
|
+
|
|
252
|
+
// Check if hook files exist
|
|
253
|
+
const stopHookFileExists = fs.existsSync(stopHookPath);
|
|
254
|
+
const prepromptHookFileExists = fs.existsSync(prepromptHookPath);
|
|
255
|
+
|
|
256
|
+
// Check if hooks are registered in settings.json
|
|
257
|
+
let stopHookRegistered = false;
|
|
258
|
+
let prepromptHookRegistered = false;
|
|
259
|
+
|
|
260
|
+
if (fs.existsSync(claudeSettingsPath)) {
|
|
261
|
+
try {
|
|
262
|
+
const settings = JSON.parse(fs.readFileSync(claudeSettingsPath, 'utf8'));
|
|
263
|
+
const hooks = settings.hooks || {};
|
|
264
|
+
|
|
265
|
+
// Check Stop hook registration
|
|
266
|
+
if (hooks.Stop) {
|
|
267
|
+
stopHookRegistered = hooks.Stop.some(entry =>
|
|
268
|
+
entry.hooks?.some(h => h.command?.includes('ralph-loop-stop.sh'))
|
|
269
|
+
);
|
|
270
|
+
}
|
|
256
271
|
|
|
257
|
-
|
|
258
|
-
|
|
272
|
+
// Check PreToolUse hook registration
|
|
273
|
+
if (hooks.PreToolUse) {
|
|
274
|
+
prepromptHookRegistered = hooks.PreToolUse.some(entry =>
|
|
275
|
+
entry.hooks?.some(h => h.command?.includes('ralph-loop-preprompt.sh'))
|
|
276
|
+
);
|
|
277
|
+
}
|
|
278
|
+
} catch (e) {
|
|
279
|
+
// Ignore parse errors
|
|
280
|
+
}
|
|
281
|
+
}
|
|
259
282
|
|
|
260
283
|
const status = {
|
|
261
|
-
// Official plugin is preferred
|
|
262
|
-
usingOfficialPlugin: officialPluginExists,
|
|
263
|
-
officialPlugin: {
|
|
264
|
-
path: officialPluginPath,
|
|
265
|
-
exists: officialPluginExists
|
|
266
|
-
},
|
|
267
284
|
stopHook: {
|
|
268
|
-
path:
|
|
269
|
-
exists:
|
|
285
|
+
path: stopHookPath,
|
|
286
|
+
exists: stopHookFileExists,
|
|
287
|
+
registered: stopHookRegistered
|
|
270
288
|
},
|
|
271
289
|
prepromptHook: {
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
290
|
+
path: prepromptHookPath,
|
|
291
|
+
exists: prepromptHookFileExists,
|
|
292
|
+
registered: prepromptHookRegistered
|
|
275
293
|
}
|
|
276
294
|
};
|
|
277
295
|
|
|
@@ -419,32 +437,105 @@ function fixRalphLoopPluginStructure() {
|
|
|
419
437
|
}
|
|
420
438
|
|
|
421
439
|
/**
|
|
422
|
-
* Install loop hooks
|
|
440
|
+
* Install loop hooks into Claude Code's settings.json
|
|
441
|
+
* Registers Stop hook that increments iteration count after each response
|
|
423
442
|
*/
|
|
424
443
|
function installLoopHooks(manager) {
|
|
425
|
-
const
|
|
426
|
-
const
|
|
444
|
+
const claudeSettingsPath = path.join(os.homedir(), '.claude', 'settings.json');
|
|
445
|
+
const claudeHooksDir = path.join(os.homedir(), '.claude', 'hooks');
|
|
446
|
+
|
|
447
|
+
// Ensure hooks directory exists
|
|
448
|
+
if (!fs.existsSync(claudeHooksDir)) {
|
|
449
|
+
fs.mkdirSync(claudeHooksDir, { recursive: true });
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
// Copy the stop hook script to ~/.claude/hooks/
|
|
453
|
+
const stopHookSource = path.join(__dirname, '..', '..', 'hooks', 'ralph-loop-stop.sh');
|
|
454
|
+
const stopHookDest = path.join(claudeHooksDir, 'ralph-loop-stop.sh');
|
|
455
|
+
|
|
456
|
+
// Also copy preprompt hook
|
|
457
|
+
const prepromptHookSource = path.join(__dirname, '..', '..', 'hooks', 'ralph-loop-preprompt.sh');
|
|
458
|
+
const prepromptHookDest = path.join(claudeHooksDir, 'ralph-loop-preprompt.sh');
|
|
459
|
+
|
|
460
|
+
try {
|
|
461
|
+
// Copy hook scripts
|
|
462
|
+
if (fs.existsSync(stopHookSource)) {
|
|
463
|
+
fs.copyFileSync(stopHookSource, stopHookDest);
|
|
464
|
+
fs.chmodSync(stopHookDest, '755');
|
|
465
|
+
}
|
|
466
|
+
if (fs.existsSync(prepromptHookSource)) {
|
|
467
|
+
fs.copyFileSync(prepromptHookSource, prepromptHookDest);
|
|
468
|
+
fs.chmodSync(prepromptHookDest, '755');
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
// Load existing settings
|
|
472
|
+
let settings = {};
|
|
473
|
+
if (fs.existsSync(claudeSettingsPath)) {
|
|
474
|
+
settings = JSON.parse(fs.readFileSync(claudeSettingsPath, 'utf8'));
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
// Initialize hooks if needed
|
|
478
|
+
if (!settings.hooks) {
|
|
479
|
+
settings.hooks = {};
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
// Add Stop hook for iteration tracking
|
|
483
|
+
const stopHookEntry = {
|
|
484
|
+
hooks: [{
|
|
485
|
+
type: 'command',
|
|
486
|
+
command: stopHookDest
|
|
487
|
+
}]
|
|
488
|
+
};
|
|
489
|
+
|
|
490
|
+
// Check if Stop hook already exists
|
|
491
|
+
if (!settings.hooks.Stop) {
|
|
492
|
+
settings.hooks.Stop = [stopHookEntry];
|
|
493
|
+
} else {
|
|
494
|
+
// Check if our hook is already registered
|
|
495
|
+
const hookExists = settings.hooks.Stop.some(entry =>
|
|
496
|
+
entry.hooks?.some(h => h.command?.includes('ralph-loop-stop.sh'))
|
|
497
|
+
);
|
|
498
|
+
if (!hookExists) {
|
|
499
|
+
settings.hooks.Stop.push(stopHookEntry);
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
// Add PreToolUse hook for context injection (optional)
|
|
504
|
+
const prepromptHookEntry = {
|
|
505
|
+
hooks: [{
|
|
506
|
+
type: 'command',
|
|
507
|
+
command: prepromptHookDest
|
|
508
|
+
}]
|
|
509
|
+
};
|
|
510
|
+
|
|
511
|
+
if (!settings.hooks.PreToolUse) {
|
|
512
|
+
settings.hooks.PreToolUse = [prepromptHookEntry];
|
|
513
|
+
} else {
|
|
514
|
+
const hookExists = settings.hooks.PreToolUse.some(entry =>
|
|
515
|
+
entry.hooks?.some(h => h.command?.includes('ralph-loop-preprompt.sh'))
|
|
516
|
+
);
|
|
517
|
+
if (!hookExists) {
|
|
518
|
+
settings.hooks.PreToolUse.push(prepromptHookEntry);
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
// Save updated settings
|
|
523
|
+
fs.writeFileSync(claudeSettingsPath, JSON.stringify(settings, null, 2) + '\n');
|
|
427
524
|
|
|
428
|
-
// Check if official plugin is already installed
|
|
429
|
-
if (fs.existsSync(officialPluginPath)) {
|
|
430
525
|
return {
|
|
431
526
|
success: true,
|
|
432
|
-
message: '
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
note: '
|
|
527
|
+
message: 'Loop hooks installed successfully',
|
|
528
|
+
stopHook: stopHookDest,
|
|
529
|
+
prepromptHook: prepromptHookDest,
|
|
530
|
+
note: 'Stop hook will increment iteration count after each Claude response when CODER_LOOP_ID is set'
|
|
531
|
+
};
|
|
532
|
+
} catch (error) {
|
|
533
|
+
return {
|
|
534
|
+
success: false,
|
|
535
|
+
error: error.message,
|
|
536
|
+
suggestion: 'Try manually copying hooks to ~/.claude/hooks/ and adding to ~/.claude/settings.json'
|
|
436
537
|
};
|
|
437
538
|
}
|
|
438
|
-
|
|
439
|
-
// Suggest installing the official plugin
|
|
440
|
-
return {
|
|
441
|
-
success: false,
|
|
442
|
-
error: 'Official ralph-loop plugin not found',
|
|
443
|
-
suggestion: 'Install the claude-plugins-official marketplace to get the ralph-loop plugin:\n' +
|
|
444
|
-
' 1. Add marketplace: coder-config marketplace add https://github.com/anthropics/claude-plugins-official\n' +
|
|
445
|
-
' 2. Or manually clone: git clone https://github.com/anthropics/claude-plugins-official ~/.claude/plugins/marketplaces/claude-plugins-official',
|
|
446
|
-
note: 'The official plugin provides /ralph-loop command with stop-hook for autonomous loops'
|
|
447
|
-
};
|
|
448
539
|
}
|
|
449
540
|
|
|
450
541
|
module.exports = {
|