autopilot-code 0.2.4 → 0.3.0
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
CHANGED
|
@@ -300,6 +300,15 @@ function logsSystemdService() {
|
|
|
300
300
|
(0, node_child_process_1.spawnSync)("journalctl", args, { stdio: "inherit" });
|
|
301
301
|
}
|
|
302
302
|
async function initCommand() {
|
|
303
|
+
const logo = `
|
|
304
|
+
_ _ _ _
|
|
305
|
+
(_) |_ _ ___ ___| |_ __ _| |
|
|
306
|
+
| | __| |/ _ \\/ __| __/ _\` | |
|
|
307
|
+
| | |_| | (_) \\__ \\ || (_| | |
|
|
308
|
+
|_|\\__|_|\\___/|___/\\__\\__,_|_|
|
|
309
|
+
`;
|
|
310
|
+
console.log(logo);
|
|
311
|
+
console.log();
|
|
303
312
|
const cwd = process.cwd();
|
|
304
313
|
const validation = validatePath(cwd);
|
|
305
314
|
// 1. Ensure global config exists
|
package/package.json
CHANGED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
from dataclasses import dataclass
|
|
3
|
+
from typing import Optional
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@dataclass
|
|
8
|
+
class AgentResult:
|
|
9
|
+
success: bool
|
|
10
|
+
session_id: Optional[str]
|
|
11
|
+
output: str
|
|
12
|
+
error: Optional[str] = None
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class BaseAgent(ABC):
|
|
16
|
+
def __init__(self, config: dict):
|
|
17
|
+
self.config = config
|
|
18
|
+
self._binary_path: Optional[str] = None
|
|
19
|
+
|
|
20
|
+
@property
|
|
21
|
+
@abstractmethod
|
|
22
|
+
def name(self) -> str:
|
|
23
|
+
pass
|
|
24
|
+
|
|
25
|
+
@property
|
|
26
|
+
@abstractmethod
|
|
27
|
+
def supports_sessions(self) -> bool:
|
|
28
|
+
pass
|
|
29
|
+
|
|
30
|
+
@abstractmethod
|
|
31
|
+
def find_binary(self) -> str:
|
|
32
|
+
pass
|
|
33
|
+
|
|
34
|
+
@property
|
|
35
|
+
def binary_path(self) -> str:
|
|
36
|
+
if self._binary_path is None:
|
|
37
|
+
self._binary_path = self.find_binary()
|
|
38
|
+
return self._binary_path
|
|
39
|
+
|
|
40
|
+
@abstractmethod
|
|
41
|
+
def run(
|
|
42
|
+
self, worktree: Path, prompt: str, session_id: Optional[str] = None
|
|
43
|
+
) -> AgentResult:
|
|
44
|
+
pass
|
|
45
|
+
|
|
46
|
+
def run_planning(
|
|
47
|
+
self,
|
|
48
|
+
worktree: Path,
|
|
49
|
+
issue_number: int,
|
|
50
|
+
issue_title: str,
|
|
51
|
+
issue_body: str,
|
|
52
|
+
session_id: Optional[str] = None,
|
|
53
|
+
) -> AgentResult:
|
|
54
|
+
prompt = f"""Please analyze the following GitHub issue and provide a detailed implementation plan. Do NOT make any code changes yet - only analyze and plan.
|
|
55
|
+
|
|
56
|
+
Issue #{issue_number}: {issue_title}
|
|
57
|
+
|
|
58
|
+
{issue_body}
|
|
59
|
+
|
|
60
|
+
Your task:
|
|
61
|
+
1. Analyze the issue requirements thoroughly
|
|
62
|
+
2. Explore the codebase to understand the relevant components
|
|
63
|
+
3. Identify the files that need to be modified or created
|
|
64
|
+
4. Outline the step-by-step approach for implementing this change
|
|
65
|
+
5. Note any potential issues, dependencies, or risks
|
|
66
|
+
6. List any assumptions you're making
|
|
67
|
+
|
|
68
|
+
Provide your analysis and plan in a clear, structured format."""
|
|
69
|
+
|
|
70
|
+
return self.run(worktree, prompt, session_id)
|
|
71
|
+
|
|
72
|
+
def run_implementation(
|
|
73
|
+
self,
|
|
74
|
+
worktree: Path,
|
|
75
|
+
issue_number: int,
|
|
76
|
+
issue_title: str,
|
|
77
|
+
issue_body: str,
|
|
78
|
+
branch: str,
|
|
79
|
+
session_id: Optional[str] = None,
|
|
80
|
+
) -> AgentResult:
|
|
81
|
+
prompt = f"""Please implement the following GitHub issue.
|
|
82
|
+
|
|
83
|
+
Issue #{issue_number}: {issue_title}
|
|
84
|
+
|
|
85
|
+
{issue_body}
|
|
86
|
+
|
|
87
|
+
Work rules:
|
|
88
|
+
- Make the necessary code changes.
|
|
89
|
+
- Commit with message: "autopilot: work for issue #{issue_number}".
|
|
90
|
+
- Push your changes to the remote branch {branch}.
|
|
91
|
+
- If the issue is a simple file-addition, just do it directly (no extra refactors)."""
|
|
92
|
+
|
|
93
|
+
return self.run(worktree, prompt, session_id)
|
|
94
|
+
|
|
95
|
+
def run_conflict_resolution(
|
|
96
|
+
self, worktree: Path, session_id: Optional[str] = None
|
|
97
|
+
) -> AgentResult:
|
|
98
|
+
prompt = """This PR has merge conflicts. Please resolve them:
|
|
99
|
+
|
|
100
|
+
1. Run 'git status' to see all conflicted files
|
|
101
|
+
2. For each conflicted file, examine the conflict markers (<<<<<, =======, >>>>>)
|
|
102
|
+
3. Resolve the conflicts by choosing the appropriate code
|
|
103
|
+
4. Stage the resolved files with 'git add <file>'
|
|
104
|
+
5. The goal is to make the branch mergeable with main
|
|
105
|
+
|
|
106
|
+
After resolving all conflicts, report the files that were resolved."""
|
|
107
|
+
|
|
108
|
+
return self.run(worktree, prompt, session_id)
|
|
109
|
+
|
|
110
|
+
def run_ci_fix(
|
|
111
|
+
self,
|
|
112
|
+
worktree: Path,
|
|
113
|
+
failure_context: str,
|
|
114
|
+
attempt: int,
|
|
115
|
+
max_attempts: int,
|
|
116
|
+
branch: str,
|
|
117
|
+
session_id: Optional[str] = None,
|
|
118
|
+
) -> AgentResult:
|
|
119
|
+
prompt = f"""The PR checks have failed. Please analyze the CI failures and fix the issues.
|
|
120
|
+
|
|
121
|
+
{failure_context}
|
|
122
|
+
|
|
123
|
+
Work rules:
|
|
124
|
+
- Examine the failed checks and identify the root cause
|
|
125
|
+
- Make the necessary code changes to fix the failures
|
|
126
|
+
- Commit with message: "autopilot: fix CI check failures (attempt {attempt}/{max_attempts})"
|
|
127
|
+
- Push your changes to the branch {branch}
|
|
128
|
+
- Focus only on fixing the CI failures, do not make unrelated changes"""
|
|
129
|
+
|
|
130
|
+
return self.run(worktree, prompt, session_id)
|
|
@@ -440,8 +440,31 @@ I'm monitoring the CI checks and will auto-merge once they pass. This may take a
|
|
|
440
440
|
# If mergeStateStatus is CLEAN or HAS_HOOKS and statusCheckRollup is null/empty → PASSED
|
|
441
441
|
# If mergeStateStatus is UNKNOWN → wait and retry
|
|
442
442
|
if [[ "$MERGE_STATE_STATUS" == "UNKNOWN" ]]; then
|
|
443
|
-
|
|
444
|
-
|
|
443
|
+
# Check if there are any CI checks configured
|
|
444
|
+
if command -v jq >/dev/null 2>&1; then
|
|
445
|
+
SCR_IS_NULL=$(echo "$PR_STATUS_JSON" | jq -r '.statusCheckRollup == null')
|
|
446
|
+
SCR_LENGTH=$(echo "$PR_STATUS_JSON" | jq -r '.statusCheckRollup | length // 0')
|
|
447
|
+
else
|
|
448
|
+
SCR_VALUE=$(python3 -c 'import json,sys; data=json.load(sys.stdin); print(data.get("statusCheckRollup", "null"))' <<<"$PR_STATUS_JSON")
|
|
449
|
+
SCR_IS_NULL=$([[ "$SCR_VALUE" == "null" ]] && echo "true" || echo "false")
|
|
450
|
+
SCR_LENGTH=$(python3 -c 'import json,sys; data=json.load(sys.stdin); scr=data.get("statusCheckRollup"); print(len(scr) if scr else 0)' <<<"$PR_STATUS_JSON")
|
|
451
|
+
fi
|
|
452
|
+
|
|
453
|
+
# If no checks configured, wait at most 20 seconds for them to appear
|
|
454
|
+
if [[ "$SCR_IS_NULL" == "true" ]] || [[ "$SCR_LENGTH" == "0" ]]; then
|
|
455
|
+
if [[ $POLL_ATTEMPT -lt 1 ]]; then
|
|
456
|
+
CHECK_STATUS="PENDING"
|
|
457
|
+
echo "[run_opencode_issue.sh] No CI checks configured, waiting up to 20 seconds for checks to appear..."
|
|
458
|
+
sleep 20
|
|
459
|
+
continue
|
|
460
|
+
else
|
|
461
|
+
CHECK_STATUS="PASSED"
|
|
462
|
+
echo "[run_opencode_issue.sh] No checks found after waiting 20 seconds, continuing to merge..."
|
|
463
|
+
fi
|
|
464
|
+
else
|
|
465
|
+
CHECK_STATUS="PENDING"
|
|
466
|
+
echo "[run_opencode_issue.sh] mergeStateStatus is UNKNOWN, waiting for GitHub to calculate..."
|
|
467
|
+
fi
|
|
445
468
|
elif [[ "$MERGE_STATE_STATUS" == "CLEAN" || "$MERGE_STATE_STATUS" == "HAS_HOOKS" ]]; then
|
|
446
469
|
# Check statusCheckRollup - if null/empty, no checks configured, so PASSED
|
|
447
470
|
if command -v jq >/dev/null 2>&1; then
|