coder-config 0.43.27 → 0.44.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/lib/constants.js +1 -1
- package/package.json +1 -1
- package/ui/dist/assets/{index-D8VqNb3_.js → index-BmstVwHo.js} +145 -145
- package/ui/dist/index.html +1 -1
- package/ui/routes/loops.js +70 -0
- package/ui/server.cjs +11 -0
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-BmstVwHo.js"></script>
|
|
23
23
|
<link rel="stylesheet" crossorigin href="/assets/index-qZ-hWTZQ.css">
|
|
24
24
|
</head>
|
|
25
25
|
<body>
|
package/ui/routes/loops.js
CHANGED
|
@@ -278,6 +278,74 @@ function getLoopHookStatus() {
|
|
|
278
278
|
return status;
|
|
279
279
|
}
|
|
280
280
|
|
|
281
|
+
/**
|
|
282
|
+
* Check if ralph-loop plugin is installed at user scope
|
|
283
|
+
* Returns { installed: boolean, scope: string|null }
|
|
284
|
+
*/
|
|
285
|
+
function getRalphLoopPluginStatus() {
|
|
286
|
+
const installedPluginsPath = path.join(os.homedir(), '.claude', 'plugins', 'installed_plugins.json');
|
|
287
|
+
|
|
288
|
+
if (!fs.existsSync(installedPluginsPath)) {
|
|
289
|
+
return { installed: false, scope: null, needsInstall: true };
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
try {
|
|
293
|
+
const data = JSON.parse(fs.readFileSync(installedPluginsPath, 'utf8'));
|
|
294
|
+
const plugins = data.plugins || {};
|
|
295
|
+
const ralphLoop = plugins['ralph-loop@claude-plugins-official'];
|
|
296
|
+
|
|
297
|
+
if (!ralphLoop || ralphLoop.length === 0) {
|
|
298
|
+
return { installed: false, scope: null, needsInstall: true };
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// Check if any installation is at user scope
|
|
302
|
+
const userScopeInstall = ralphLoop.find(p => p.scope === 'user');
|
|
303
|
+
if (userScopeInstall) {
|
|
304
|
+
return { installed: true, scope: 'user', needsInstall: false };
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// Plugin is installed but only at project scope
|
|
308
|
+
return {
|
|
309
|
+
installed: true,
|
|
310
|
+
scope: 'project',
|
|
311
|
+
projectPath: ralphLoop[0].projectPath,
|
|
312
|
+
needsInstall: true,
|
|
313
|
+
message: 'Plugin is installed for a specific project only. Install at user scope for global access.'
|
|
314
|
+
};
|
|
315
|
+
} catch (e) {
|
|
316
|
+
return { installed: false, scope: null, needsInstall: true, error: e.message };
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* Install ralph-loop plugin at user scope via CLI
|
|
322
|
+
* Uses execFileSync with fixed args (no shell injection risk)
|
|
323
|
+
*/
|
|
324
|
+
async function installRalphLoopPlugin() {
|
|
325
|
+
const { execFileSync } = require('child_process');
|
|
326
|
+
|
|
327
|
+
try {
|
|
328
|
+
// Run claude plugin install command with execFileSync (safer than execSync)
|
|
329
|
+
// All arguments are fixed strings - no user input
|
|
330
|
+
execFileSync('claude', ['plugin', 'install', 'ralph-loop@claude-plugins-official', '--scope', 'user'], {
|
|
331
|
+
encoding: 'utf8',
|
|
332
|
+
timeout: 30000, // 30 second timeout
|
|
333
|
+
stdio: ['pipe', 'pipe', 'pipe']
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
return {
|
|
337
|
+
success: true,
|
|
338
|
+
message: 'ralph-loop plugin installed successfully at user scope'
|
|
339
|
+
};
|
|
340
|
+
} catch (e) {
|
|
341
|
+
return {
|
|
342
|
+
success: false,
|
|
343
|
+
error: e.message,
|
|
344
|
+
suggestion: 'Try running manually: claude plugin install ralph-loop@claude-plugins-official --scope user'
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
281
349
|
/**
|
|
282
350
|
* Install loop hooks (or verify official plugin is installed)
|
|
283
351
|
*/
|
|
@@ -328,4 +396,6 @@ module.exports = {
|
|
|
328
396
|
recordIteration,
|
|
329
397
|
getLoopHookStatus,
|
|
330
398
|
installLoopHooks,
|
|
399
|
+
getRalphLoopPluginStatus,
|
|
400
|
+
installRalphLoopPlugin,
|
|
331
401
|
};
|
package/ui/server.cjs
CHANGED
|
@@ -788,6 +788,17 @@ class ConfigUIServer {
|
|
|
788
788
|
if (req.method === 'POST') return this.json(res, routes.loops.installLoopHooks(this.manager));
|
|
789
789
|
break;
|
|
790
790
|
|
|
791
|
+
case '/api/loops/plugin-status':
|
|
792
|
+
if (req.method === 'GET') return this.json(res, routes.loops.getRalphLoopPluginStatus());
|
|
793
|
+
break;
|
|
794
|
+
|
|
795
|
+
case '/api/loops/install-plugin':
|
|
796
|
+
if (req.method === 'POST') {
|
|
797
|
+
const result = await routes.loops.installRalphLoopPlugin();
|
|
798
|
+
return this.json(res, result);
|
|
799
|
+
}
|
|
800
|
+
break;
|
|
801
|
+
|
|
791
802
|
case '/api/activity':
|
|
792
803
|
if (req.method === 'GET') return this.json(res, routes.activity.getActivitySummary(this.manager));
|
|
793
804
|
if (req.method === 'DELETE') return this.json(res, routes.activity.clearActivity(this.manager, body.olderThanDays || 30));
|