@sureshsankaran/ralph-wiggum 0.1.9 → 0.1.11

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.
@@ -4,78 +4,11 @@ description: "Start Ralph Wiggum loop in current session"
4
4
 
5
5
  # Ralph Loop Command
6
6
 
7
- !`export RALPH_ARGS='$ARGUMENTS' && node -e "
8
- var args = process.env.RALPH_ARGS || '';
9
- var fs = require('fs');
10
- var path = require('path');
11
-
12
- // Unescape the CLI escaping - remove outer quotes and unescape inner quotes
13
- args = args.trim();
14
- if ((args.startsWith('\"') && args.endsWith('\"')) || (args.startsWith(\"'\") && args.endsWith(\"'\"))) {
15
- args = args.slice(1, -1);
16
- }
17
- args = args.replace(/\\\\\"/g, '\"');
18
-
19
- var maxIterations = 0;
20
- var completionPromise = 'null';
21
- var prompt = args;
22
-
23
- var maxMatch = args.match(/--max-iterations\s+(\d+)/);
24
- if (maxMatch) {
25
- maxIterations = parseInt(maxMatch[1], 10);
26
- prompt = prompt.replace(/--max-iterations\s+\d+/, '');
27
- }
28
-
29
- var cpMatch = args.match(/--completion-promise\s+\"([^\"]+)\"/);
30
- if (cpMatch) {
31
- completionPromise = cpMatch[1];
32
- prompt = prompt.replace(/--completion-promise\s+\"[^\"]+\"/, '');
33
- } else {
34
- var cpMatch2 = args.match(/--completion-promise\s+(\S+)/);
35
- if (cpMatch2) {
36
- completionPromise = cpMatch2[1];
37
- prompt = prompt.replace(/--completion-promise\s+\S+/, '');
38
- }
39
- }
40
-
41
- prompt = prompt.trim().replace(/^\"|\"$/g, '');
42
-
43
- if (!prompt) {
44
- console.log('Error: No prompt provided.');
45
- console.log('Usage: /ralph-loop \"<prompt>\" [--max-iterations N] [--completion-promise TEXT]');
46
- process.exit(1);
47
- }
48
-
49
- var configDir = process.env.XDG_CONFIG_HOME || path.join(require('os').homedir(), '.config');
50
- var dir = path.join(configDir, 'opencode', 'state');
51
- fs.mkdirSync(dir, { recursive: true });
52
-
53
- var cpYaml = completionPromise === 'null' ? 'null' : '\"' + completionPromise + '\"';
54
- var lines = [
55
- '---',
56
- 'active: true',
57
- 'iteration: 1',
58
- 'max_iterations: ' + maxIterations,
59
- 'completion_promise: ' + cpYaml,
60
- 'started_at: \"' + new Date().toISOString() + '\"',
61
- '---',
62
- '',
63
- prompt
64
- ];
65
-
66
- fs.writeFileSync(path.join(dir, 'ralph-loop.local.md'), lines.join('\n') + '\n');
67
-
68
- console.log('Ralph loop activated!');
69
- console.log('Iteration: 1');
70
- console.log('Max iterations: ' + (maxIterations > 0 ? maxIterations : 'unlimited'));
71
- console.log('Completion promise: ' + (completionPromise !== 'null' ? completionPromise : 'none'));
72
- console.log('');
73
- console.log(prompt);
74
- "`
7
+ !`node ~/.config/opencode/scripts/ralph-wiggum/setup-loop.js $ARGUMENTS`
75
8
 
76
9
  Please work on the task described above. The Ralph loop is now active.
77
10
 
78
- When the session becomes idle, the session.idle hook will feed the SAME PROMPT back to you for the next iteration. You'll see your previous work in files and git history, allowing you to iterate and improve.
11
+ When the session becomes idle, the session.stop hook will feed the SAME PROMPT back to you for the next iteration. You'll see your previous work in files and git history, allowing you to iterate and improve.
79
12
 
80
13
  CRITICAL RULE: If a completion promise is set, you may ONLY output it when the statement is completely and unequivocally TRUE. Do not output false promises to escape the loop, even if you think you're stuck or should exit for other reasons. The loop is designed to continue until genuine completion.
81
14
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sureshsankaran/ralph-wiggum",
3
- "version": "0.1.9",
3
+ "version": "0.1.11",
4
4
  "description": "Ralph Wiggum iterative AI development plugin for OpenCode - continuously loops the same prompt until task completion",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -8,12 +8,16 @@ import { fileURLToPath } from "node:url"
8
8
  const __dirname = dirname(fileURLToPath(import.meta.url))
9
9
  const packageRoot = join(__dirname, "..")
10
10
 
11
- const configDir = join(homedir(), ".config", "opencode", "command")
12
-
13
- // Create command directory if it doesn't exist
14
- if (!existsSync(configDir)) {
15
- mkdirSync(configDir, { recursive: true })
16
- console.log(`Created directory: ${configDir}`)
11
+ const configBase = join(homedir(), ".config", "opencode")
12
+ const commandDir = join(configBase, "command")
13
+ const scriptsDir = join(configBase, "scripts", "ralph-wiggum")
14
+
15
+ // Create directories if they don't exist
16
+ for (const dir of [commandDir, scriptsDir]) {
17
+ if (!existsSync(dir)) {
18
+ mkdirSync(dir, { recursive: true })
19
+ console.log(`Created directory: ${dir}`)
20
+ }
17
21
  }
18
22
 
19
23
  // Copy command files
@@ -22,7 +26,7 @@ const commandsDir = join(packageRoot, "commands")
22
26
 
23
27
  for (const cmd of commands) {
24
28
  const src = join(commandsDir, cmd)
25
- const dest = join(configDir, cmd)
29
+ const dest = join(commandDir, cmd)
26
30
 
27
31
  if (existsSync(src)) {
28
32
  copyFileSync(src, dest)
@@ -32,6 +36,17 @@ for (const cmd of commands) {
32
36
  }
33
37
  }
34
38
 
39
+ // Copy setup script
40
+ const setupSrc = join(packageRoot, "scripts", "setup-loop.js")
41
+ const setupDest = join(scriptsDir, "setup-loop.js")
42
+
43
+ if (existsSync(setupSrc)) {
44
+ copyFileSync(setupSrc, setupDest)
45
+ console.log(`Installed script: setup-loop.js`)
46
+ } else {
47
+ console.warn(`Warning: Script file not found: ${setupSrc}`)
48
+ }
49
+
35
50
  console.log("")
36
51
  console.log("Ralph Wiggum commands installed!")
37
52
  console.log("")
@@ -39,7 +54,7 @@ console.log("Next step: Add the plugin to your opencode config:")
39
54
  console.log("")
40
55
  console.log(" In opencode.json:")
41
56
  console.log(" {")
42
- console.log(' "plugin": ["opencode-ralph-wiggum"]')
57
+ console.log(' "plugin": ["@sureshsankaran/ralph-wiggum"]')
43
58
  console.log(" }")
44
59
  console.log("")
45
60
  console.log("Usage:")
@@ -0,0 +1,70 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Ralph Loop Setup Script
4
+ *
5
+ * Called by the ralph-loop command template to initialize the loop state.
6
+ * Arguments are passed directly to this script (not via shell substitution).
7
+ */
8
+
9
+ const fs = require("fs")
10
+ const path = require("path")
11
+ const os = require("os")
12
+
13
+ // Get arguments from command line (skip node and script name)
14
+ const rawArgs = process.argv.slice(2)
15
+
16
+ // Parse arguments
17
+ let maxIterations = 0
18
+ let completionPromise = null
19
+ let promptParts = []
20
+
21
+ for (let i = 0; i < rawArgs.length; i++) {
22
+ const arg = rawArgs[i]
23
+
24
+ if (arg === "--max-iterations" && i + 1 < rawArgs.length) {
25
+ maxIterations = parseInt(rawArgs[i + 1], 10) || 0
26
+ i++ // skip next arg
27
+ } else if (arg === "--completion-promise" && i + 1 < rawArgs.length) {
28
+ completionPromise = rawArgs[i + 1]
29
+ i++ // skip next arg
30
+ } else if (!arg.startsWith("--")) {
31
+ promptParts.push(arg)
32
+ }
33
+ }
34
+
35
+ const prompt = promptParts.join(" ").trim()
36
+
37
+ if (!prompt) {
38
+ console.log("Error: No prompt provided.")
39
+ console.log('Usage: --command ralph-loop "<prompt>" --max-iterations N --completion-promise TEXT')
40
+ process.exit(1)
41
+ }
42
+
43
+ // Determine state directory
44
+ const configDir = process.env.XDG_CONFIG_HOME || path.join(os.homedir(), ".config")
45
+ const stateDir = path.join(configDir, "opencode", "state")
46
+ fs.mkdirSync(stateDir, { recursive: true })
47
+
48
+ // Build state file content
49
+ const cpYaml = completionPromise ? `"${completionPromise}"` : "null"
50
+ const lines = [
51
+ "---",
52
+ "active: true",
53
+ "iteration: 1",
54
+ `max_iterations: ${maxIterations}`,
55
+ `completion_promise: ${cpYaml}`,
56
+ `started_at: "${new Date().toISOString()}"`,
57
+ "---",
58
+ "",
59
+ prompt,
60
+ ]
61
+
62
+ const stateFilePath = path.join(stateDir, "ralph-loop.local.md")
63
+ fs.writeFileSync(stateFilePath, lines.join("\n") + "\n")
64
+
65
+ console.log("Ralph loop activated!")
66
+ console.log(`Iteration: 1`)
67
+ console.log(`Max iterations: ${maxIterations > 0 ? maxIterations : "unlimited"}`)
68
+ console.log(`Completion promise: ${completionPromise || "none"}`)
69
+ console.log("")
70
+ console.log(prompt)