autopilot-code 0.0.17 → 0.0.19
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/cli.js +4 -0
- package/package.json +1 -1
- package/scripts/run_autopilot.py +36 -1
- package/scripts/run_opencode_issue.sh +45 -3
package/dist/cli.js
CHANGED
|
@@ -158,6 +158,8 @@ function generateSystemdUnit(logPath, intervalSeconds, useSystem) {
|
|
|
158
158
|
];
|
|
159
159
|
const user = process.env.USER || "root";
|
|
160
160
|
const home = process.env.HOME || "/root";
|
|
161
|
+
// Include current PATH so systemd can find nvm-installed binaries like opencode
|
|
162
|
+
const currentPath = process.env.PATH || "/usr/bin:/bin";
|
|
161
163
|
return `[Unit]
|
|
162
164
|
Description=Autopilot automated issue runner
|
|
163
165
|
After=network.target
|
|
@@ -173,6 +175,8 @@ StandardError=journal
|
|
|
173
175
|
SyslogIdentifier=autopilot
|
|
174
176
|
${useSystem ? `User=${user}` : ""}
|
|
175
177
|
Environment="NODE_ENV=production"
|
|
178
|
+
Environment="PATH=${currentPath}"
|
|
179
|
+
Environment="HOME=${home}"
|
|
176
180
|
|
|
177
181
|
[Install]
|
|
178
182
|
WantedBy=${useSystem ? "multi-user.target" : "default.target"}
|
package/package.json
CHANGED
package/scripts/run_autopilot.py
CHANGED
|
@@ -24,6 +24,7 @@ import time
|
|
|
24
24
|
from dataclasses import dataclass
|
|
25
25
|
from pathlib import Path
|
|
26
26
|
from typing import Any
|
|
27
|
+
import shutil
|
|
27
28
|
|
|
28
29
|
STATE_DIR = ".autopilot"
|
|
29
30
|
STATE_FILE = "state.json"
|
|
@@ -341,17 +342,51 @@ def check_pr_for_issue(cfg: RepoConfig, issue_number: int) -> dict[str, Any] | N
|
|
|
341
342
|
return None
|
|
342
343
|
|
|
343
344
|
|
|
345
|
+
def find_opencode() -> str | None:
|
|
346
|
+
"""Find opencode binary in PATH or common locations."""
|
|
347
|
+
# 1. Check PATH first
|
|
348
|
+
opencode = shutil.which("opencode")
|
|
349
|
+
if opencode:
|
|
350
|
+
return opencode
|
|
351
|
+
|
|
352
|
+
# 2. Check common nvm locations
|
|
353
|
+
home = Path.home()
|
|
354
|
+
nvm_dir = home / ".nvm" / "versions" / "node"
|
|
355
|
+
if nvm_dir.exists():
|
|
356
|
+
for node_version in sorted(nvm_dir.iterdir(), reverse=True):
|
|
357
|
+
candidate = node_version / "bin" / "opencode"
|
|
358
|
+
if candidate.exists() and candidate.is_file():
|
|
359
|
+
return str(candidate)
|
|
360
|
+
|
|
361
|
+
# 3. Other common locations
|
|
362
|
+
for path in [
|
|
363
|
+
home / ".local" / "bin" / "opencode",
|
|
364
|
+
Path("/usr/local/bin/opencode"),
|
|
365
|
+
home / ".npm-global" / "bin" / "opencode",
|
|
366
|
+
]:
|
|
367
|
+
if path.exists() and path.is_file():
|
|
368
|
+
return str(path)
|
|
369
|
+
|
|
370
|
+
return None
|
|
371
|
+
|
|
372
|
+
|
|
344
373
|
def resolve_merge_conflicts(cfg: RepoConfig, issue_number: int, pr: dict[str, Any], attempt: int) -> bool:
|
|
345
374
|
"""Attempt to resolve merge conflicts using the coding agent. Returns True if resolved."""
|
|
346
375
|
if cfg.agent != "opencode":
|
|
347
376
|
print(f"[{cfg.repo}] Cannot resolve conflicts: agent '{cfg.agent}' not supported (only 'opencode')", flush=True)
|
|
348
377
|
return False
|
|
349
378
|
|
|
379
|
+
opencode_bin = find_opencode()
|
|
380
|
+
if not opencode_bin:
|
|
381
|
+
print(f"[{cfg.repo}] Cannot resolve conflicts: opencode not found", flush=True)
|
|
382
|
+
return False
|
|
383
|
+
|
|
350
384
|
pr_number = pr["number"]
|
|
351
385
|
branch = pr.get("headRefName", f"autopilot/issue-{issue_number}")
|
|
352
386
|
worktree = Path(f"/tmp/autopilot-issue-{issue_number}")
|
|
353
387
|
|
|
354
388
|
print(f"[{cfg.repo}] Attempting to resolve merge conflicts for PR #{pr_number} (attempt {attempt}/{cfg.conflict_resolution_max_attempts})", flush=True)
|
|
389
|
+
print(f"[{cfg.repo}] Using opencode: {opencode_bin}", flush=True)
|
|
355
390
|
|
|
356
391
|
# Ensure worktree exists and is up to date
|
|
357
392
|
if not worktree.exists():
|
|
@@ -414,7 +449,7 @@ Work rules:
|
|
|
414
449
|
|
|
415
450
|
# Run opencode in the worktree
|
|
416
451
|
agent_result = subprocess.run(
|
|
417
|
-
[
|
|
452
|
+
[opencode_bin, "run", conflict_prompt],
|
|
418
453
|
cwd=str(worktree),
|
|
419
454
|
capture_output=True,
|
|
420
455
|
text=True,
|
|
@@ -21,6 +21,7 @@ if command -v jq >/dev/null 2>&1; then
|
|
|
21
21
|
AUTO_FIX_CHECKS=$(jq -r '.autoFixChecks // true' < .autopilot/autopilot.json)
|
|
22
22
|
AUTO_FIX_CHECKS_MAX_ATTEMPTS=$(jq -r '.autoFixChecksMaxAttempts // 3' < .autopilot/autopilot.json)
|
|
23
23
|
ALLOWED_USERS=$(jq -r '.allowedMergeUsers[]' < .autopilot/autopilot.json 2>/dev/null || true)
|
|
24
|
+
AGENT_PATH=$(jq -r '.agentPath // ""' < .autopilot/autopilot.json)
|
|
24
25
|
else
|
|
25
26
|
REPO=$(python3 -c 'import json; print(json.load(open(".autopilot/autopilot.json"))["repo"])')
|
|
26
27
|
AUTO_MERGE=$(python3 -c 'import json; print(json.load(open(".autopilot/autopilot.json")).get("autoMerge", True))')
|
|
@@ -30,8 +31,49 @@ else
|
|
|
30
31
|
AUTO_FIX_CHECKS=$(python3 -c 'import json; print(json.load(open(".autopilot/autopilot.json")).get("autoFixChecks", True))')
|
|
31
32
|
AUTO_FIX_CHECKS_MAX_ATTEMPTS=$(python3 -c 'import json; print(json.load(open(".autopilot/autopilot.json")).get("autoFixChecksMaxAttempts", 3))')
|
|
32
33
|
ALLOWED_USERS=$(python3 -c 'import json,sys; users=json.load(open(".autopilot/autopilot.json")).get("allowedMergeUsers", []); print("\n".join(users))' 2>/dev/null || true)
|
|
34
|
+
AGENT_PATH=$(python3 -c 'import json; print(json.load(open(".autopilot/autopilot.json")).get("agentPath", ""))' 2>/dev/null || true)
|
|
33
35
|
fi
|
|
34
36
|
|
|
37
|
+
# Find opencode binary - check config, PATH, then common locations
|
|
38
|
+
find_opencode() {
|
|
39
|
+
# 1. Config-specified path
|
|
40
|
+
if [[ -n "$AGENT_PATH" ]] && [[ -x "$AGENT_PATH" ]]; then
|
|
41
|
+
echo "$AGENT_PATH"
|
|
42
|
+
return
|
|
43
|
+
fi
|
|
44
|
+
|
|
45
|
+
# 2. Already in PATH
|
|
46
|
+
if command -v opencode >/dev/null 2>&1; then
|
|
47
|
+
command -v opencode
|
|
48
|
+
return
|
|
49
|
+
fi
|
|
50
|
+
|
|
51
|
+
# 3. Common nvm locations
|
|
52
|
+
for node_dir in "$HOME/.nvm/versions/node"/*/bin; do
|
|
53
|
+
if [[ -x "$node_dir/opencode" ]]; then
|
|
54
|
+
echo "$node_dir/opencode"
|
|
55
|
+
return
|
|
56
|
+
fi
|
|
57
|
+
done
|
|
58
|
+
|
|
59
|
+
# 4. Other common locations
|
|
60
|
+
for path in "$HOME/.local/bin/opencode" "/usr/local/bin/opencode" "$HOME/.npm-global/bin/opencode"; do
|
|
61
|
+
if [[ -x "$path" ]]; then
|
|
62
|
+
echo "$path"
|
|
63
|
+
return
|
|
64
|
+
fi
|
|
65
|
+
done
|
|
66
|
+
|
|
67
|
+
# Not found
|
|
68
|
+
return 1
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
OPENCODE_BIN=$(find_opencode) || {
|
|
72
|
+
echo "[run_opencode_issue.sh] ERROR: opencode not found. Set 'agentPath' in autopilot.json or ensure opencode is installed." >&2
|
|
73
|
+
exit 1
|
|
74
|
+
}
|
|
75
|
+
echo "[run_opencode_issue.sh] Using opencode: $OPENCODE_BIN"
|
|
76
|
+
|
|
35
77
|
WORKTREE="/tmp/autopilot-issue-$ISSUE_NUMBER"
|
|
36
78
|
BRANCH="autopilot/issue-$ISSUE_NUMBER"
|
|
37
79
|
|
|
@@ -73,7 +115,7 @@ Work rules:
|
|
|
73
115
|
- If the issue is a simple file-addition, just do it directly (no extra refactors)."
|
|
74
116
|
# 4. Run opencode inside worktree
|
|
75
117
|
cd "$WORKTREE"
|
|
76
|
-
|
|
118
|
+
"$OPENCODE_BIN" run "$PROMPT"
|
|
77
119
|
|
|
78
120
|
# 5. Commit any changes OpenCode made
|
|
79
121
|
if [[ -n "$(git status --porcelain)" ]]; then
|
|
@@ -190,7 +232,7 @@ if [[ "$AUTO_RESOLVE_CONFLICTS" == "true" ]] && [[ -n "$PR_URL" ]]; then
|
|
|
190
232
|
|
|
191
233
|
After resolving all conflicts, report the files that were resolved."
|
|
192
234
|
|
|
193
|
-
if
|
|
235
|
+
if "$OPENCODE_BIN" run "$CONFLICT_PROMPT"; then
|
|
194
236
|
# Check if there are still conflicts
|
|
195
237
|
if [[ -z "$(git diff --name-only --diff-filter=U)" ]]; then
|
|
196
238
|
echo "[run_opencode_issue.sh] Conflicts resolved by agent."
|
|
@@ -316,7 +358,7 @@ if [[ "$AUTO_MERGE" == "true" ]] && [[ -n "$PR_URL" ]]; then
|
|
|
316
358
|
|
|
317
359
|
# Run opencode to fix the issue
|
|
318
360
|
cd "$WORKTREE"
|
|
319
|
-
if
|
|
361
|
+
if "$OPENCODE_BIN" run "$REPAIR_PROMPT"; then
|
|
320
362
|
# Commit any changes
|
|
321
363
|
if [[ -n "$(git status --porcelain)" ]]; then
|
|
322
364
|
git add -A
|