minimal-agent 0.1.8 → 0.1.9
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/main.js +350 -247
- package/package.json +3 -2
- package/plugins/ralph-wiggum/.claude-plugin/plugin.json +9 -0
- package/plugins/ralph-wiggum/README.md +179 -0
- package/plugins/ralph-wiggum/commands/cancel-ralph.md +18 -0
- package/plugins/ralph-wiggum/commands/help.md +126 -0
- package/plugins/ralph-wiggum/commands/ralph-loop.md +69 -0
- package/plugins/ralph-wiggum/hooks/hooks.json +15 -0
- package/plugins/ralph-wiggum/hooks/stop-hook.sh +191 -0
- package/plugins/ralph-wiggum/scripts/setup-ralph-loop.sh +203 -0
- package/skills/config/SKILL.md +27 -1
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# Ralph Loop Setup Script
|
|
4
|
+
# Creates state file for in-session Ralph loop
|
|
5
|
+
|
|
6
|
+
set -euo pipefail
|
|
7
|
+
|
|
8
|
+
# Parse arguments
|
|
9
|
+
PROMPT_PARTS=()
|
|
10
|
+
MAX_ITERATIONS=0
|
|
11
|
+
COMPLETION_PROMISE="null"
|
|
12
|
+
|
|
13
|
+
# Parse options and positional arguments
|
|
14
|
+
while [[ $# -gt 0 ]]; do
|
|
15
|
+
case $1 in
|
|
16
|
+
-h|--help)
|
|
17
|
+
cat << 'HELP_EOF'
|
|
18
|
+
Ralph Loop - Interactive self-referential development loop
|
|
19
|
+
|
|
20
|
+
USAGE:
|
|
21
|
+
/ralph-loop [PROMPT...] [OPTIONS]
|
|
22
|
+
|
|
23
|
+
ARGUMENTS:
|
|
24
|
+
PROMPT... Initial prompt to start the loop (can be multiple words without quotes)
|
|
25
|
+
|
|
26
|
+
OPTIONS:
|
|
27
|
+
--max-iterations <n> Maximum iterations before auto-stop (default: unlimited)
|
|
28
|
+
--completion-promise '<text>' Promise phrase (USE QUOTES for multi-word)
|
|
29
|
+
-h, --help Show this help message
|
|
30
|
+
|
|
31
|
+
DESCRIPTION:
|
|
32
|
+
Starts a Ralph Wiggum loop in your CURRENT session. The stop hook prevents
|
|
33
|
+
exit and feeds your output back as input until completion or iteration limit.
|
|
34
|
+
|
|
35
|
+
To signal completion, you must output: <promise>YOUR_PHRASE</promise>
|
|
36
|
+
|
|
37
|
+
Use this for:
|
|
38
|
+
- Interactive iteration where you want to see progress
|
|
39
|
+
- Tasks requiring self-correction and refinement
|
|
40
|
+
- Learning how Ralph works
|
|
41
|
+
|
|
42
|
+
EXAMPLES:
|
|
43
|
+
/ralph-loop Build a todo API --completion-promise 'DONE' --max-iterations 20
|
|
44
|
+
/ralph-loop --max-iterations 10 Fix the auth bug
|
|
45
|
+
/ralph-loop Refactor cache layer (runs forever)
|
|
46
|
+
/ralph-loop --completion-promise 'TASK COMPLETE' Create a REST API
|
|
47
|
+
|
|
48
|
+
STOPPING:
|
|
49
|
+
Only by reaching --max-iterations or detecting --completion-promise
|
|
50
|
+
No manual stop - Ralph runs infinitely by default!
|
|
51
|
+
|
|
52
|
+
MONITORING:
|
|
53
|
+
# View current iteration:
|
|
54
|
+
grep '^iteration:' .minimal-agent/ralph-loop.local.md
|
|
55
|
+
|
|
56
|
+
# View full state:
|
|
57
|
+
head -10 .minimal-agent/ralph-loop.local.md
|
|
58
|
+
HELP_EOF
|
|
59
|
+
exit 0
|
|
60
|
+
;;
|
|
61
|
+
--max-iterations)
|
|
62
|
+
if [[ -z "${2:-}" ]]; then
|
|
63
|
+
echo "❌ Error: --max-iterations requires a number argument" >&2
|
|
64
|
+
echo "" >&2
|
|
65
|
+
echo " Valid examples:" >&2
|
|
66
|
+
echo " --max-iterations 10" >&2
|
|
67
|
+
echo " --max-iterations 50" >&2
|
|
68
|
+
echo " --max-iterations 0 (unlimited)" >&2
|
|
69
|
+
echo "" >&2
|
|
70
|
+
echo " You provided: --max-iterations (with no number)" >&2
|
|
71
|
+
exit 1
|
|
72
|
+
fi
|
|
73
|
+
if ! [[ "$2" =~ ^[0-9]+$ ]]; then
|
|
74
|
+
echo "❌ Error: --max-iterations must be a positive integer or 0, got: $2" >&2
|
|
75
|
+
echo "" >&2
|
|
76
|
+
echo " Valid examples:" >&2
|
|
77
|
+
echo " --max-iterations 10" >&2
|
|
78
|
+
echo " --max-iterations 50" >&2
|
|
79
|
+
echo " --max-iterations 0 (unlimited)" >&2
|
|
80
|
+
echo "" >&2
|
|
81
|
+
echo " Invalid: decimals (10.5), negative numbers (-5), text" >&2
|
|
82
|
+
exit 1
|
|
83
|
+
fi
|
|
84
|
+
MAX_ITERATIONS="$2"
|
|
85
|
+
shift 2
|
|
86
|
+
;;
|
|
87
|
+
--completion-promise)
|
|
88
|
+
if [[ -z "${2:-}" ]]; then
|
|
89
|
+
echo "❌ Error: --completion-promise requires a text argument" >&2
|
|
90
|
+
echo "" >&2
|
|
91
|
+
echo " Valid examples:" >&2
|
|
92
|
+
echo " --completion-promise 'DONE'" >&2
|
|
93
|
+
echo " --completion-promise 'TASK COMPLETE'" >&2
|
|
94
|
+
echo " --completion-promise 'All tests passing'" >&2
|
|
95
|
+
echo "" >&2
|
|
96
|
+
echo " You provided: --completion-promise (with no text)" >&2
|
|
97
|
+
echo "" >&2
|
|
98
|
+
echo " Note: Multi-word promises must be quoted!" >&2
|
|
99
|
+
exit 1
|
|
100
|
+
fi
|
|
101
|
+
COMPLETION_PROMISE="$2"
|
|
102
|
+
shift 2
|
|
103
|
+
;;
|
|
104
|
+
*)
|
|
105
|
+
# Non-option argument - collect all as prompt parts
|
|
106
|
+
PROMPT_PARTS+=("$1")
|
|
107
|
+
shift
|
|
108
|
+
;;
|
|
109
|
+
esac
|
|
110
|
+
done
|
|
111
|
+
|
|
112
|
+
# Join all prompt parts with spaces
|
|
113
|
+
PROMPT="${PROMPT_PARTS[*]}"
|
|
114
|
+
|
|
115
|
+
# Validate prompt is non-empty
|
|
116
|
+
if [[ -z "$PROMPT" ]]; then
|
|
117
|
+
echo "❌ Error: No prompt provided" >&2
|
|
118
|
+
echo "" >&2
|
|
119
|
+
echo " Ralph needs a task description to work on." >&2
|
|
120
|
+
echo "" >&2
|
|
121
|
+
echo " Examples:" >&2
|
|
122
|
+
echo " /ralph-loop Build a REST API for todos" >&2
|
|
123
|
+
echo " /ralph-loop Fix the auth bug --max-iterations 20" >&2
|
|
124
|
+
echo " /ralph-loop --completion-promise 'DONE' Refactor code" >&2
|
|
125
|
+
echo "" >&2
|
|
126
|
+
echo " For all options: /ralph-loop --help" >&2
|
|
127
|
+
exit 1
|
|
128
|
+
fi
|
|
129
|
+
|
|
130
|
+
# Create state file for stop hook (markdown with YAML frontmatter)
|
|
131
|
+
mkdir -p .minimal-agent
|
|
132
|
+
|
|
133
|
+
# Quote completion promise for YAML if it contains special chars or is not null
|
|
134
|
+
if [[ -n "$COMPLETION_PROMISE" ]] && [[ "$COMPLETION_PROMISE" != "null" ]]; then
|
|
135
|
+
COMPLETION_PROMISE_YAML="\"$COMPLETION_PROMISE\""
|
|
136
|
+
else
|
|
137
|
+
COMPLETION_PROMISE_YAML="null"
|
|
138
|
+
fi
|
|
139
|
+
|
|
140
|
+
cat > .minimal-agent/ralph-loop.local.md <<EOF
|
|
141
|
+
---
|
|
142
|
+
active: true
|
|
143
|
+
iteration: 1
|
|
144
|
+
max_iterations: $MAX_ITERATIONS
|
|
145
|
+
completion_promise: $COMPLETION_PROMISE_YAML
|
|
146
|
+
started_at: "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
$PROMPT
|
|
150
|
+
EOF
|
|
151
|
+
|
|
152
|
+
# Output setup message
|
|
153
|
+
cat <<EOF
|
|
154
|
+
🔄 Ralph loop activated in this session!
|
|
155
|
+
|
|
156
|
+
Iteration: 1
|
|
157
|
+
Max iterations: $(if [[ $MAX_ITERATIONS -gt 0 ]]; then echo $MAX_ITERATIONS; else echo "unlimited"; fi)
|
|
158
|
+
Completion promise: $(if [[ "$COMPLETION_PROMISE" != "null" ]]; then echo "${COMPLETION_PROMISE//\"/} (ONLY output when TRUE - do not lie!)"; else echo "none (runs forever)"; fi)
|
|
159
|
+
|
|
160
|
+
The stop hook is now active. When you try to exit, the SAME PROMPT will be
|
|
161
|
+
fed back to you. You'll see your previous work in files, creating a
|
|
162
|
+
self-referential loop where you iteratively improve on the same task.
|
|
163
|
+
|
|
164
|
+
To monitor: head -10 .minimal-agent/ralph-loop.local.md
|
|
165
|
+
|
|
166
|
+
⚠️ WARNING: This loop cannot be stopped manually! It will run infinitely
|
|
167
|
+
unless you set --max-iterations or --completion-promise.
|
|
168
|
+
|
|
169
|
+
🔄
|
|
170
|
+
EOF
|
|
171
|
+
|
|
172
|
+
# Output the initial prompt if provided
|
|
173
|
+
if [[ -n "$PROMPT" ]]; then
|
|
174
|
+
echo ""
|
|
175
|
+
echo "$PROMPT"
|
|
176
|
+
fi
|
|
177
|
+
|
|
178
|
+
# Display completion promise requirements if set
|
|
179
|
+
if [[ "$COMPLETION_PROMISE" != "null" ]]; then
|
|
180
|
+
echo ""
|
|
181
|
+
echo "═══════════════════════════════════════════════════════════"
|
|
182
|
+
echo "CRITICAL - Ralph Loop Completion Promise"
|
|
183
|
+
echo "═══════════════════════════════════════════════════════════"
|
|
184
|
+
echo ""
|
|
185
|
+
echo "To complete this loop, output this EXACT text:"
|
|
186
|
+
echo " <promise>$COMPLETION_PROMISE</promise>"
|
|
187
|
+
echo ""
|
|
188
|
+
echo "STRICT REQUIREMENTS (DO NOT VIOLATE):"
|
|
189
|
+
echo " ✓ Use <promise> XML tags EXACTLY as shown above"
|
|
190
|
+
echo " ✓ The statement MUST be completely and unequivocally TRUE"
|
|
191
|
+
echo " ✓ Do NOT output false statements to exit the loop"
|
|
192
|
+
echo " ✓ Do NOT lie even if you think you should exit"
|
|
193
|
+
echo ""
|
|
194
|
+
echo "IMPORTANT - Do not circumvent the loop:"
|
|
195
|
+
echo " Even if you believe you're stuck, the task is impossible,"
|
|
196
|
+
echo " or you've been running too long - you MUST NOT output a"
|
|
197
|
+
echo " false promise statement. The loop is designed to continue"
|
|
198
|
+
echo " until the promise is GENUINELY TRUE. Trust the process."
|
|
199
|
+
echo ""
|
|
200
|
+
echo " If the loop should stop, the promise statement will become"
|
|
201
|
+
echo " true naturally. Do not force it by lying."
|
|
202
|
+
echo "═══════════════════════════════════════════════════════════"
|
|
203
|
+
fi
|
package/skills/config/SKILL.md
CHANGED
|
@@ -38,7 +38,26 @@ Read({ file_path: "~/.minimal-agent/config.json" })
|
|
|
38
38
|
| `apiKey` | ✅ | API key(敏感信息) |
|
|
39
39
|
| `model` | ✅ | 模型 id,如 `MiniMax-M2.7` |
|
|
40
40
|
| `provider` | ⬜ | 显示名(仅用于状态栏),默认 `env` |
|
|
41
|
-
| `contextWindow` | ⬜ | 模型上下文窗口(token
|
|
41
|
+
| `contextWindow` | ⬜ | 模型上下文窗口(token 数),**推荐值见下方速查表**(按 provider+model 推断) |
|
|
42
|
+
| `tavilyApiKey` | ⬜ | Tavily key(WebSearch 工具用);可留空跳过,免费 key 申请见 https://tavily.com/ |
|
|
43
|
+
|
|
44
|
+
### Provider 默认值速查表(contextWindow)
|
|
45
|
+
|
|
46
|
+
权威值见 `src/cli/configWizard.tsx::PRESETS`;本表是它的镜像,发现不一致以代码为准。
|
|
47
|
+
|
|
48
|
+
| Provider | Model | 推荐 contextWindow |
|
|
49
|
+
|---|---|---|
|
|
50
|
+
| minimax | MiniMax-M2.7 / MiniMax-M1 / abab6.5s-chat | 204800 |
|
|
51
|
+
| deepseek | deepseek-chat / deepseek-reasoner | 128000 |
|
|
52
|
+
| openai | gpt-4o / gpt-4o-mini | 128000 |
|
|
53
|
+
| moonshot | moonshot-v1-8k | 8000 |
|
|
54
|
+
| moonshot | moonshot-v1-32k | 32000 |
|
|
55
|
+
| moonshot | moonshot-v1-128k | 128000 |
|
|
56
|
+
| 其它 / custom | — | 128000 |
|
|
57
|
+
|
|
58
|
+
⚠️ 询问 `contextWindow` 时,**先按上表给出推荐值并明确告诉用户**(例:「按你选的 `MiniMax-M2.7`,推荐 `contextWindow = 204800`,直接回车采纳」)。**不要让用户裸填 token 数**;用户主要关心 `baseURL` / `apiKey` / `model`,contextWindow 应优先按 provider+model 推断。
|
|
59
|
+
|
|
60
|
+
如果用户改了 model 但没改 contextWindow,**主动重新计算推荐值**并提示;用户旧 contextWindow 与新 model 不匹配时(如把 model 从 `moonshot-v1-8k` 改成 `moonshot-v1-128k`),明确建议同步更新。
|
|
42
61
|
|
|
43
62
|
**对话格式示例**(每次只问一个字段,等用户答完再问下一个):
|
|
44
63
|
|
|
@@ -62,6 +81,7 @@ Write({
|
|
|
62
81
|
model: <...>,
|
|
63
82
|
provider: <...>,
|
|
64
83
|
contextWindow: <...>,
|
|
84
|
+
tavilyApiKey: <... or 省略字段>,
|
|
65
85
|
savedAt: Date.now()
|
|
66
86
|
}, null, 2)
|
|
67
87
|
})
|
|
@@ -69,6 +89,12 @@ Write({
|
|
|
69
89
|
|
|
70
90
|
字段 `savedAt` 必须是当前的 unix 毫秒时间戳。
|
|
71
91
|
|
|
92
|
+
`tavilyApiKey` 字段策略:
|
|
93
|
+
- 用户没有 Tavily key → **从写入的 JSON 里删掉这个字段**(不要写空串,readSavedConfig 会拒空串)。
|
|
94
|
+
- 用户提供了 key → 写入字符串。
|
|
95
|
+
- 用户没主动改这个字段 → **保留旧值**(不要为了"格式整洁"删除)。
|
|
96
|
+
- 写入后启动注入:下次启动 minimal-agent 时 `applyToolKeysToEnv()`(`src/config.ts`)会把它注入 `process.env.TAVILY_API_KEY`,WebSearch 工具就能用了。
|
|
97
|
+
|
|
72
98
|
### Step 4: 提示重启
|
|
73
99
|
|
|
74
100
|
写入成功后,输出(中文):
|