wile 0.6.1 → 0.6.2
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/agent/entrypoint.sh +23 -5
- package/dist/agent/scripts/mock-claude.sh +50 -0
- package/dist/agent/scripts/prompt-compact.md +41 -0
- package/dist/agent/scripts/validate-compact.js +121 -0
- package/dist/agent/scripts/wile-compact.sh +96 -0
- package/dist/agent/scripts/wile.sh +3 -8
- package/dist/cli.js +70 -7
- package/package.json +1 -1
package/dist/agent/entrypoint.sh
CHANGED
|
@@ -274,13 +274,21 @@ mkdir -p .wile/screenshots
|
|
|
274
274
|
|
|
275
275
|
echo ""
|
|
276
276
|
echo "══════════════════════════════════════════════════════"
|
|
277
|
-
|
|
277
|
+
if [ "${WILE_MODE:-}" = "compact" ]; then
|
|
278
|
+
echo " Starting Wile Compact"
|
|
279
|
+
else
|
|
280
|
+
echo " Starting Wile Loop"
|
|
281
|
+
fi
|
|
278
282
|
echo "══════════════════════════════════════════════════════"
|
|
279
283
|
echo ""
|
|
280
284
|
|
|
281
|
-
# Run the main loop
|
|
285
|
+
# Run the main loop or compact flow
|
|
282
286
|
EXIT_CODE=0
|
|
283
|
-
"$
|
|
287
|
+
if [ "${WILE_MODE:-}" = "compact" ]; then
|
|
288
|
+
"$SCRIPT_DIR/wile-compact.sh" || EXIT_CODE=$?
|
|
289
|
+
else
|
|
290
|
+
"$SCRIPT_DIR/wile.sh" "$MAX_ITERATIONS" || EXIT_CODE=$?
|
|
291
|
+
fi
|
|
284
292
|
|
|
285
293
|
echo ""
|
|
286
294
|
echo "══════════════════════════════════════════════════════"
|
|
@@ -290,8 +298,18 @@ echo "════════════════════════
|
|
|
290
298
|
# Handle completion/partial completion
|
|
291
299
|
if [ $EXIT_CODE -eq 0 ]; then
|
|
292
300
|
echo "All tasks completed successfully!"
|
|
293
|
-
|
|
294
|
-
|
|
301
|
+
if [ "${WILE_MODE:-}" = "compact" ]; then
|
|
302
|
+
if ! git diff --quiet || ! git diff --staged --quiet; then
|
|
303
|
+
git add -A
|
|
304
|
+
git commit -m "chore: compact wile prd and progress"
|
|
305
|
+
git push || true
|
|
306
|
+
else
|
|
307
|
+
git push || true
|
|
308
|
+
fi
|
|
309
|
+
else
|
|
310
|
+
# Ensure final state is pushed
|
|
311
|
+
git push || true
|
|
312
|
+
fi
|
|
295
313
|
elif [ $EXIT_CODE -eq 1 ]; then
|
|
296
314
|
echo "Max iterations reached. Committing partial work..."
|
|
297
315
|
|
|
@@ -1,6 +1,56 @@
|
|
|
1
1
|
#!/bin/sh
|
|
2
2
|
set -e
|
|
3
3
|
|
|
4
|
+
if [ "${WILE_MODE:-}" = "compact" ]; then
|
|
5
|
+
node - <<'NODE'
|
|
6
|
+
const fs = require("fs");
|
|
7
|
+
|
|
8
|
+
const prdPath = ".wile/prd.json";
|
|
9
|
+
const progressPath = ".wile/progress.txt";
|
|
10
|
+
const prd = JSON.parse(fs.readFileSync(prdPath, "utf8"));
|
|
11
|
+
const stories = Array.isArray(prd.userStories) ? prd.userStories : [];
|
|
12
|
+
const firstStory = stories[0] || {};
|
|
13
|
+
const lastStory = stories[stories.length - 1] || {};
|
|
14
|
+
const priority = typeof firstStory.priority === "number" ? firstStory.priority : 1;
|
|
15
|
+
const taskIds = `From ${firstStory.id || "TASK-001"} to ${lastStory.id || "TASK-001"}`;
|
|
16
|
+
|
|
17
|
+
const compactStory = {
|
|
18
|
+
id: "GROUP-001",
|
|
19
|
+
title: "summary of everything done here",
|
|
20
|
+
tasks: [
|
|
21
|
+
"High level of what was accomplished here",
|
|
22
|
+
"Should NOT have all tasks in here, should be very summarized"
|
|
23
|
+
],
|
|
24
|
+
taskIds,
|
|
25
|
+
priority,
|
|
26
|
+
passes: true,
|
|
27
|
+
notes: "Don't repeat task ids when starting the next one."
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
fs.writeFileSync(prdPath, JSON.stringify({ userStories: [compactStory] }, null, 2) + "\n");
|
|
31
|
+
|
|
32
|
+
const progressLines = [
|
|
33
|
+
"# Wile Progress Log",
|
|
34
|
+
"",
|
|
35
|
+
"## Codebase Patterns",
|
|
36
|
+
"- Summarized key learnings for future agents.",
|
|
37
|
+
"",
|
|
38
|
+
"---",
|
|
39
|
+
"",
|
|
40
|
+
"Compacted the progress log to highlight the most important work and patterns.",
|
|
41
|
+
"Kept only high-level details to preserve context without noise.",
|
|
42
|
+
""
|
|
43
|
+
];
|
|
44
|
+
|
|
45
|
+
fs.writeFileSync(progressPath, progressLines.join("\n"));
|
|
46
|
+
NODE
|
|
47
|
+
|
|
48
|
+
cat <<'JSON'
|
|
49
|
+
{"type":"assistant","message":{"content":[{"type":"text","text":"{\"id\":\"GROUP-001\",\"title\":\"summary of everything done here\",\"tasks\":[\"High level of what was accomplished here\",\"Should NOT have all tasks in here, should be very summarized\"],\"taskIds\":\"From TASK-001 to TASK-029\",\"priority\":1,\"passes\":true,\"notes\":\"Don't repeat task ids when starting the next one.\"}\n"}]}}
|
|
50
|
+
JSON
|
|
51
|
+
exit 0
|
|
52
|
+
fi
|
|
53
|
+
|
|
4
54
|
COUNT_FILE="/tmp/wile-claude-mock-count"
|
|
5
55
|
if [ ! -f "$COUNT_FILE" ]; then
|
|
6
56
|
echo "0" > "$COUNT_FILE"
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
You are running a one-shot compaction task.
|
|
2
|
+
|
|
3
|
+
Goal: compact both `.wile/prd.json` and `.wile/progress.txt` while preserving important information.
|
|
4
|
+
|
|
5
|
+
Steps:
|
|
6
|
+
1. Read `.wile/prd.json` and `.wile/progress.txt`.
|
|
7
|
+
2. Update `.wile/prd.json` to:
|
|
8
|
+
- Keep every story where `passes` is `false` exactly as-is.
|
|
9
|
+
- Replace all stories where `passes` is `true` with a single grouped story.
|
|
10
|
+
- The final structure must be: `{ "userStories": [ { ...GROUP-001... }, ...all-passes-false-stories ] }`.
|
|
11
|
+
- The grouped story must use `id: "GROUP-001"`.
|
|
12
|
+
- `title`: a concise summary of everything done.
|
|
13
|
+
- `tasks`: 2-4 short bullet items derived from the summary tasks.
|
|
14
|
+
- `taskIds`: a single string in the form `From TASK-001 to TASK-029` using the first and last task IDs you find.
|
|
15
|
+
- `priority`: copy the priority from the first story in the original file.
|
|
16
|
+
- `passes`: `true` (hardcoded).
|
|
17
|
+
- `notes`: `Don't repeat task ids when starting the next one.` (exact text).
|
|
18
|
+
3. Update `.wile/progress.txt`:
|
|
19
|
+
- Keep the header `# Wile Progress Log` and `## Codebase Patterns`.
|
|
20
|
+
- Add bullet points at the top under `## Codebase Patterns` for any important learnings that would help future agents.
|
|
21
|
+
- Replace the rest of the log with a short, high-level summary in a few paragraphs.
|
|
22
|
+
- Do not lose important info, but avoid detailed step-by-step logs.
|
|
23
|
+
- Ignore preflight failures in the history.
|
|
24
|
+
|
|
25
|
+
Response format:
|
|
26
|
+
- Your response must end with a single-line JSON object and nothing after it (no trailing text).
|
|
27
|
+
- The final non-empty line of output must be valid JSON exactly matching this shape:
|
|
28
|
+
{
|
|
29
|
+
"id": "GROUP-001",
|
|
30
|
+
"title": "summary of everything done here",
|
|
31
|
+
"tasks": [
|
|
32
|
+
"High level of what was accomplished here",
|
|
33
|
+
"Should NOT have all tasks in here, should be very summarized"
|
|
34
|
+
],
|
|
35
|
+
"taskIds": "From TASK-001 to TASK-029",
|
|
36
|
+
"priority": 1,
|
|
37
|
+
"passes": true,
|
|
38
|
+
"notes": "Don't repeat task ids when starting the next one."
|
|
39
|
+
}
|
|
40
|
+
- Do not wrap the JSON in code fences.
|
|
41
|
+
- Ensure nothing appears after the JSON line.
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const fs = require("node:fs");
|
|
3
|
+
|
|
4
|
+
const prdPath = ".wile/prd.json";
|
|
5
|
+
const progressPath = ".wile/progress.txt";
|
|
6
|
+
const prdOriginalPath = ".wile/prd.json.original";
|
|
7
|
+
|
|
8
|
+
if (!fs.existsSync(prdPath)) {
|
|
9
|
+
console.error("Missing .wile/prd.json after compact.");
|
|
10
|
+
process.exit(1);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if (!fs.existsSync(progressPath)) {
|
|
14
|
+
console.error("Missing .wile/progress.txt after compact.");
|
|
15
|
+
process.exit(1);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
let payload;
|
|
19
|
+
try {
|
|
20
|
+
payload = JSON.parse(fs.readFileSync(prdPath, "utf8"));
|
|
21
|
+
} catch {
|
|
22
|
+
console.error("Compacted .wile/prd.json is not valid JSON.");
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (!payload || !Array.isArray(payload.userStories) || payload.userStories.length === 0) {
|
|
27
|
+
console.error("Compacted .wile/prd.json must contain at least one user story.");
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const groupStory = payload.userStories.find((story) => story?.id === "GROUP-001");
|
|
32
|
+
if (!groupStory) {
|
|
33
|
+
console.error('Compacted .wile/prd.json must include a GROUP-001 story.');
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const requiredKeys = ["id", "title", "tasks", "taskIds", "priority", "passes", "notes"];
|
|
38
|
+
for (const key of requiredKeys) {
|
|
39
|
+
if (!(key in groupStory)) {
|
|
40
|
+
console.error(`Compact output missing key: ${key}`);
|
|
41
|
+
process.exit(1);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (groupStory.id !== "GROUP-001") {
|
|
46
|
+
console.error('Compact output "id" must be GROUP-001.');
|
|
47
|
+
process.exit(1);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (typeof groupStory.title !== "string" || groupStory.title.trim().length === 0) {
|
|
51
|
+
console.error('Compact output "title" must be a non-empty string.');
|
|
52
|
+
process.exit(1);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (!Array.isArray(groupStory.tasks) || groupStory.tasks.length === 0) {
|
|
56
|
+
console.error('Compact output "tasks" must be a non-empty array.');
|
|
57
|
+
process.exit(1);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (!groupStory.tasks.every((task) => typeof task === "string" && task.trim().length > 0)) {
|
|
61
|
+
console.error('Compact output "tasks" must contain only non-empty strings.');
|
|
62
|
+
process.exit(1);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (typeof groupStory.taskIds !== "string" || groupStory.taskIds.trim().length === 0) {
|
|
66
|
+
console.error('Compact output "taskIds" must be a non-empty string.');
|
|
67
|
+
process.exit(1);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (typeof groupStory.priority !== "number" || !Number.isFinite(groupStory.priority)) {
|
|
71
|
+
console.error('Compact output "priority" must be a number.');
|
|
72
|
+
process.exit(1);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (groupStory.passes !== true) {
|
|
76
|
+
console.error('Compact output "passes" must be true.');
|
|
77
|
+
process.exit(1);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (groupStory.notes !== "Don't repeat task ids when starting the next one.") {
|
|
81
|
+
console.error('Compact output "notes" must match the required text.');
|
|
82
|
+
process.exit(1);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (fs.existsSync(prdOriginalPath)) {
|
|
86
|
+
let original;
|
|
87
|
+
try {
|
|
88
|
+
original = JSON.parse(fs.readFileSync(prdOriginalPath, "utf8"));
|
|
89
|
+
} catch {
|
|
90
|
+
console.error("Original .wile/prd.json.original is not valid JSON.");
|
|
91
|
+
process.exit(1);
|
|
92
|
+
}
|
|
93
|
+
if (!original || !Array.isArray(original.userStories)) {
|
|
94
|
+
console.error("Original .wile/prd.json.original is missing userStories.");
|
|
95
|
+
process.exit(1);
|
|
96
|
+
}
|
|
97
|
+
const originalPending = original.userStories.filter((story) => story?.passes === false);
|
|
98
|
+
const currentPending = payload.userStories.filter((story) => story?.passes === false);
|
|
99
|
+
if (originalPending.length !== currentPending.length) {
|
|
100
|
+
console.error("Compaction must preserve all passes:false stories.");
|
|
101
|
+
process.exit(1);
|
|
102
|
+
}
|
|
103
|
+
const missingPending = originalPending.filter(
|
|
104
|
+
(story) => !currentPending.some((current) => current?.id === story?.id)
|
|
105
|
+
);
|
|
106
|
+
if (missingPending.length > 0) {
|
|
107
|
+
console.error("Compaction removed passes:false stories.");
|
|
108
|
+
process.exit(1);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const progressText = fs.readFileSync(progressPath, "utf8");
|
|
113
|
+
if (!progressText.startsWith("# Wile Progress Log")) {
|
|
114
|
+
console.error("Compacted progress log must start with # Wile Progress Log.");
|
|
115
|
+
process.exit(1);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (!progressText.includes("## Codebase Patterns")) {
|
|
119
|
+
console.error("Compacted progress log must include ## Codebase Patterns.");
|
|
120
|
+
process.exit(1);
|
|
121
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
#
|
|
3
|
+
# Wile - Compact PRD/Progress
|
|
4
|
+
#
|
|
5
|
+
|
|
6
|
+
set -e
|
|
7
|
+
|
|
8
|
+
CODING_AGENT=${CODING_AGENT:-CC}
|
|
9
|
+
CLAUDE_MODEL=${CC_CLAUDE_MODEL:-sonnet}
|
|
10
|
+
OC_PROVIDER=${OC_PROVIDER:-native}
|
|
11
|
+
OC_MODEL=${OC_MODEL:-opencode/grok-code}
|
|
12
|
+
|
|
13
|
+
# For openrouter provider, prepend vendor prefix if missing
|
|
14
|
+
if [ "$OC_PROVIDER" = "openrouter" ] && [[ "$OC_MODEL" != */* ]]; then
|
|
15
|
+
OC_MODEL="z-ai/$OC_MODEL"
|
|
16
|
+
fi
|
|
17
|
+
|
|
18
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
19
|
+
PROMPT_FILE="$SCRIPT_DIR/prompt-compact.md"
|
|
20
|
+
ADDITIONAL_PROMPT_FILE="${WILE_ADDITIONAL_INSTRUCTIONS:-}"
|
|
21
|
+
TEE_TARGET="${WILE_TEE_TARGET:-/dev/stderr}"
|
|
22
|
+
if ! ( : > "$TEE_TARGET" ) 2>/dev/null; then
|
|
23
|
+
TEE_TARGET="/dev/null"
|
|
24
|
+
fi
|
|
25
|
+
|
|
26
|
+
echo "══════════════════════════════════════════════════════"
|
|
27
|
+
echo " 🌵 WILE - Compact PRD & Progress"
|
|
28
|
+
echo "══════════════════════════════════════════════════════"
|
|
29
|
+
echo " Agent: $CODING_AGENT"
|
|
30
|
+
if [ "$CODING_AGENT" = "OC" ]; then
|
|
31
|
+
echo " Provider: $OC_PROVIDER"
|
|
32
|
+
echo " Model: $OC_MODEL"
|
|
33
|
+
else
|
|
34
|
+
echo " Model: $CLAUDE_MODEL"
|
|
35
|
+
fi
|
|
36
|
+
echo " Prompt file: $PROMPT_FILE"
|
|
37
|
+
echo "══════════════════════════════════════════════════════"
|
|
38
|
+
echo ""
|
|
39
|
+
|
|
40
|
+
if [ -n "$ADDITIONAL_PROMPT_FILE" ] && [ -f "$ADDITIONAL_PROMPT_FILE" ]; then
|
|
41
|
+
if [ -s "$ADDITIONAL_PROMPT_FILE" ]; then
|
|
42
|
+
STRIPPED_CONTENT=$(sed '/<!--/,/-->/d' "$ADDITIONAL_PROMPT_FILE" | tr -d '[:space:]')
|
|
43
|
+
if [ -n "$STRIPPED_CONTENT" ]; then
|
|
44
|
+
PROMPT_FILE="/tmp/wile-prompt-compact.md"
|
|
45
|
+
cat "$SCRIPT_DIR/prompt-compact.md" > "$PROMPT_FILE"
|
|
46
|
+
printf "\n\n## Additional Instructions\n\n" >> "$PROMPT_FILE"
|
|
47
|
+
cat "$ADDITIONAL_PROMPT_FILE" >> "$PROMPT_FILE"
|
|
48
|
+
echo " Extra: Using additional instructions"
|
|
49
|
+
echo " Prompt file: $PROMPT_FILE"
|
|
50
|
+
echo ""
|
|
51
|
+
fi
|
|
52
|
+
fi
|
|
53
|
+
fi
|
|
54
|
+
|
|
55
|
+
run_claude() {
|
|
56
|
+
local prompt_path="$1"
|
|
57
|
+
cat "$prompt_path" \
|
|
58
|
+
| claude --model "$CLAUDE_MODEL" --print --output-format stream-json --verbose --dangerously-skip-permissions \
|
|
59
|
+
| node "$SCRIPT_DIR/claude-stream.js"
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
run_opencode() {
|
|
63
|
+
local prompt_path="$1"
|
|
64
|
+
local model_arg="$OC_MODEL"
|
|
65
|
+
if [ "$OC_PROVIDER" = "openrouter" ]; then
|
|
66
|
+
model_arg="openrouter/$OC_MODEL"
|
|
67
|
+
fi
|
|
68
|
+
cat "$prompt_path" \
|
|
69
|
+
| opencode run --format json --model "$model_arg" \
|
|
70
|
+
| node "$SCRIPT_DIR/opencode-stream.js"
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
run_agent() {
|
|
74
|
+
local prompt_path="$1"
|
|
75
|
+
if [ "$CODING_AGENT" = "OC" ]; then
|
|
76
|
+
run_opencode "$prompt_path"
|
|
77
|
+
else
|
|
78
|
+
run_claude "$prompt_path"
|
|
79
|
+
fi
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
# Snapshot original PRD for validation of passes:false preservation.
|
|
83
|
+
if [ -f ".wile/prd.json" ]; then
|
|
84
|
+
cp ".wile/prd.json" ".wile/prd.json.original"
|
|
85
|
+
fi
|
|
86
|
+
|
|
87
|
+
echo "Running compact agent..."
|
|
88
|
+
OUTPUT=$(run_agent "$PROMPT_FILE" | tee "$TEE_TARGET") || true
|
|
89
|
+
|
|
90
|
+
# Validate the resulting files instead of the response format.
|
|
91
|
+
node "$SCRIPT_DIR/validate-compact.js"
|
|
92
|
+
|
|
93
|
+
echo ""
|
|
94
|
+
echo "══════════════════════════════════════════════════════"
|
|
95
|
+
echo " ✅ COMPACT COMPLETE"
|
|
96
|
+
echo "══════════════════════════════════════════════════════"
|
|
@@ -134,20 +134,15 @@ for i in $(seq 1 $MAX_ITERATIONS); do
|
|
|
134
134
|
# Capture output while also displaying it (tee to stderr)
|
|
135
135
|
OUTPUT=$(run_agent "$PROMPT_FILE" | tee "$TEE_TARGET") || true
|
|
136
136
|
|
|
137
|
-
# Check for completion signal (tag must be
|
|
137
|
+
# Check for completion signal (tag must be the final non-empty line)
|
|
138
138
|
CLEAN_OUTPUT=$(printf '%s' "$OUTPUT" | tr -d '\r' | sed -e 's/[[:space:]]*$//')
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
:
|
|
142
|
-
elif printf '%s' "$CLEAN_OUTPUT" | grep -F '`<promise>ALL_STORIES_COMPLETED</promise>`' >/dev/null 2>&1; then
|
|
143
|
-
:
|
|
144
|
-
else
|
|
139
|
+
FINAL_LINE=$(printf '%s\n' "$CLEAN_OUTPUT" | awk 'NF { last=$0 } END { print last }')
|
|
140
|
+
if printf '%s\n' "$FINAL_LINE" | grep -q -E '^[[:space:]]*<promise>ALL_STORIES_COMPLETED</promise>[[:space:]]*$'; then
|
|
145
141
|
echo ""
|
|
146
142
|
echo "══════════════════════════════════════════════════════"
|
|
147
143
|
echo " ✅ ALL TASKS COMPLETE"
|
|
148
144
|
echo "══════════════════════════════════════════════════════"
|
|
149
145
|
exit 0
|
|
150
|
-
fi
|
|
151
146
|
fi
|
|
152
147
|
|
|
153
148
|
echo ""
|
package/dist/cli.js
CHANGED
|
@@ -7681,7 +7681,7 @@ var runConfig = async () => {
|
|
|
7681
7681
|
{ title: "opus", value: "opus" },
|
|
7682
7682
|
{ title: "haiku", value: "haiku" }
|
|
7683
7683
|
],
|
|
7684
|
-
initial: existingEnv.CC_CLAUDE_MODEL === "
|
|
7684
|
+
initial: existingEnv.CC_CLAUDE_MODEL === "sonnet" ? 0 : existingEnv.CC_CLAUDE_MODEL === "haiku" ? 2 : 1
|
|
7685
7685
|
});
|
|
7686
7686
|
} else {
|
|
7687
7687
|
const providerDefault = existingEnv.OC_PROVIDER === "openrouter" ? "openrouter" : "native";
|
|
@@ -7874,11 +7874,9 @@ Wile config complete.`);
|
|
|
7874
7874
|
}
|
|
7875
7875
|
};
|
|
7876
7876
|
|
|
7877
|
-
// src/commands/
|
|
7878
|
-
import { existsSync as
|
|
7879
|
-
import {
|
|
7880
|
-
import { resolve as resolve2, join as join3, dirname } from "node:path";
|
|
7881
|
-
import { fileURLToPath } from "node:url";
|
|
7877
|
+
// src/commands/compact.ts
|
|
7878
|
+
import { existsSync as existsSync4, mkdirSync as mkdirSync2, writeFileSync as writeFileSync2 } from "node:fs";
|
|
7879
|
+
import { join as join4 } from "node:path";
|
|
7882
7880
|
|
|
7883
7881
|
// src/lib/config.ts
|
|
7884
7882
|
var import_dotenv2 = __toESM(require_main(), 1);
|
|
@@ -7974,6 +7972,10 @@ var readWileConfig = (options = {}) => {
|
|
|
7974
7972
|
};
|
|
7975
7973
|
|
|
7976
7974
|
// src/commands/run.ts
|
|
7975
|
+
import { existsSync as existsSync3, readFileSync as readFileSync2, mkdirSync, createWriteStream, writeFileSync } from "node:fs";
|
|
7976
|
+
import { spawn, spawnSync } from "node:child_process";
|
|
7977
|
+
import { resolve as resolve2, join as join3, dirname } from "node:path";
|
|
7978
|
+
import { fileURLToPath } from "node:url";
|
|
7977
7979
|
var findAgentDir = (startDir) => {
|
|
7978
7980
|
let current = startDir;
|
|
7979
7981
|
while (true) {
|
|
@@ -8085,7 +8087,7 @@ var runDockerWithLogging = (args, logPath) => new Promise((resolvePromise, rejec
|
|
|
8085
8087
|
resolvePromise();
|
|
8086
8088
|
});
|
|
8087
8089
|
});
|
|
8088
|
-
var buildDockerArgs = (options, config, paths, cwd) => {
|
|
8090
|
+
var buildDockerArgs = (options, config, paths, cwd, extraEnv = []) => {
|
|
8089
8091
|
const dockerArgs = ["run", "--rm"];
|
|
8090
8092
|
if (options.test) {
|
|
8091
8093
|
dockerArgs.push("-e", "WILE_TEST=true", "-e", "WILE_TEST_REPO_PATH=/home/wile/workspace/repo", "-v", `${cwd}:/home/wile/workspace/repo`);
|
|
@@ -8106,6 +8108,9 @@ var buildDockerArgs = (options, config, paths, cwd) => {
|
|
|
8106
8108
|
for (const envFile of envFiles) {
|
|
8107
8109
|
dockerArgs.push("--env-file", envFile);
|
|
8108
8110
|
}
|
|
8111
|
+
for (const envEntry of extraEnv) {
|
|
8112
|
+
dockerArgs.push("-e", envEntry);
|
|
8113
|
+
}
|
|
8109
8114
|
const additionalInstructionsPath = join3(paths.wileDir, "additional-instructions.md");
|
|
8110
8115
|
if (existsSync3(additionalInstructionsPath)) {
|
|
8111
8116
|
dockerArgs.push("-e", `WILE_ADDITIONAL_INSTRUCTIONS=${additionalInstructionsPath}`);
|
|
@@ -8177,6 +8182,61 @@ var runWile = async (options) => {
|
|
|
8177
8182
|
writeFileSync(logPath, finishMessage, { flag: "a" });
|
|
8178
8183
|
};
|
|
8179
8184
|
|
|
8185
|
+
// src/commands/compact.ts
|
|
8186
|
+
var runCompact = async (options) => {
|
|
8187
|
+
const cwd = process.cwd();
|
|
8188
|
+
let paths;
|
|
8189
|
+
let config;
|
|
8190
|
+
try {
|
|
8191
|
+
const result = readWileConfig({ cwd, validate: !options.test });
|
|
8192
|
+
paths = result.paths;
|
|
8193
|
+
config = result.config;
|
|
8194
|
+
} catch (error) {
|
|
8195
|
+
console.error(error.message);
|
|
8196
|
+
process.exit(1);
|
|
8197
|
+
}
|
|
8198
|
+
if (options.debug) {
|
|
8199
|
+
const initCwd = process.env.INIT_CWD ?? "(unset)";
|
|
8200
|
+
console.log("Debug:");
|
|
8201
|
+
console.log(`- cwd: ${cwd}`);
|
|
8202
|
+
console.log(`- INIT_CWD: ${initCwd}`);
|
|
8203
|
+
console.log(`- WILE_AGENT_DIR: ${process.env.WILE_AGENT_DIR ?? "(unset)"}`);
|
|
8204
|
+
console.log(`- codingAgent: ${config.codingAgent}`);
|
|
8205
|
+
console.log(`- repoSource: ${config.repoSource}`);
|
|
8206
|
+
console.log(`- githubRepoUrl: ${config.githubRepoUrl || "(empty)"}`);
|
|
8207
|
+
console.log(`- branchName: ${config.branchName || "(empty)"}`);
|
|
8208
|
+
}
|
|
8209
|
+
try {
|
|
8210
|
+
validateGitignore(paths.gitignorePath);
|
|
8211
|
+
} catch (error) {
|
|
8212
|
+
console.error(error.message);
|
|
8213
|
+
process.exit(1);
|
|
8214
|
+
}
|
|
8215
|
+
if (!existsSync4(paths.prdPath)) {
|
|
8216
|
+
console.error("Missing .wile/prd.json. Run 'bunx wile config'.");
|
|
8217
|
+
process.exit(1);
|
|
8218
|
+
}
|
|
8219
|
+
const progressPath = join4(paths.wileDir, "progress.txt");
|
|
8220
|
+
if (!existsSync4(progressPath)) {
|
|
8221
|
+
console.error("Missing .wile/progress.txt. Run 'bunx wile config'.");
|
|
8222
|
+
process.exit(1);
|
|
8223
|
+
}
|
|
8224
|
+
const agentDir = resolveAgentDir();
|
|
8225
|
+
const resolvedIterations = options.maxIterations || "1";
|
|
8226
|
+
buildAgentImage(agentDir);
|
|
8227
|
+
const dockerArgs = buildDockerArgs({ ...options, maxIterations: resolvedIterations }, config, paths, cwd, ["WILE_MODE=compact"]);
|
|
8228
|
+
const logsDir = join4(paths.wileDir, "logs");
|
|
8229
|
+
mkdirSync2(logsDir, { recursive: true });
|
|
8230
|
+
const logPath = join4(logsDir, `compact-${getTimestamp()}.log`);
|
|
8231
|
+
writeFileSync2(logPath, "", { flag: "w" });
|
|
8232
|
+
try {
|
|
8233
|
+
await runDockerWithLogging(dockerArgs, logPath);
|
|
8234
|
+
} catch (error) {
|
|
8235
|
+
console.error(error.message);
|
|
8236
|
+
process.exit(1);
|
|
8237
|
+
}
|
|
8238
|
+
};
|
|
8239
|
+
|
|
8180
8240
|
// src/cli.ts
|
|
8181
8241
|
var packageJsonPath = resolve3(new URL("../package.json", import.meta.url).pathname);
|
|
8182
8242
|
var packageJson = JSON.parse(readFileSync3(packageJsonPath, "utf8"));
|
|
@@ -8188,4 +8248,7 @@ program2.command("config").description("Configure the current project for Wile")
|
|
|
8188
8248
|
program2.command("run").description("Run Wile on a repository").option("--repo <repo>", "Repository URL or local path").option("--max-iterations <count>", "Maximum iterations").option("--test", "Run in test mode").option("--debug", "Print debug info before running").action(async (options) => {
|
|
8189
8249
|
await runWile(options);
|
|
8190
8250
|
});
|
|
8251
|
+
program2.command("compact").description("Compact .wile/prd.json and .wile/progress.txt with an agent").option("--repo <repo>", "Repository URL or local path").option("--max-iterations <count>", "Maximum iterations (default: 1)").option("--test", "Run in test mode").option("--debug", "Print debug info before running").action(async (options) => {
|
|
8252
|
+
await runCompact(options);
|
|
8253
|
+
});
|
|
8191
8254
|
program2.parse(process.argv);
|