autopilot-code 0.0.6 → 0.0.8
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 +134 -37
- package/package.json +1 -1
- package/scripts/run_autopilot.py +10 -0
package/dist/cli.js
CHANGED
|
@@ -16,6 +16,26 @@ const GLOBAL_CONFIG_DIR = node_path_1.default.join(process.env.HOME || "", ".con
|
|
|
16
16
|
const GLOBAL_CONFIG_FILE = node_path_1.default.join(GLOBAL_CONFIG_DIR, "config.json");
|
|
17
17
|
const SYSTEM_DIR = "/etc/systemd/system";
|
|
18
18
|
const USER_DIR = node_path_1.default.join(process.env.HOME || "", ".config", "systemd", "user");
|
|
19
|
+
function getRepoName(dir) {
|
|
20
|
+
try {
|
|
21
|
+
const res = (0, node_child_process_1.spawnSync)("git", ["remote", "get-url", "origin"], { cwd: dir, encoding: "utf8" });
|
|
22
|
+
if (res.status !== 0)
|
|
23
|
+
return null;
|
|
24
|
+
const url = res.stdout.trim();
|
|
25
|
+
// Handle SSH: git@github.com:owner/repo.git
|
|
26
|
+
if (url.includes("@github.com:")) {
|
|
27
|
+
return url.split("@github.com:")[1].replace(".git", "");
|
|
28
|
+
}
|
|
29
|
+
// Handle HTTPS: https://github.com/owner/repo.git
|
|
30
|
+
if (url.includes("github.com/")) {
|
|
31
|
+
return url.split("github.com/")[1].replace(".git", "");
|
|
32
|
+
}
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
19
39
|
function run(cmd, args) {
|
|
20
40
|
const res = (0, node_child_process_1.spawnSync)(cmd, args, { stdio: "inherit" });
|
|
21
41
|
if (res.error)
|
|
@@ -164,8 +184,8 @@ function installSystemdService() {
|
|
|
164
184
|
const { unitPath, logPath, useSystem } = getSystemdPaths();
|
|
165
185
|
const intervalSeconds = "60";
|
|
166
186
|
if (!(0, node_fs_1.existsSync)(GLOBAL_CONFIG_FILE)) {
|
|
167
|
-
console.
|
|
168
|
-
|
|
187
|
+
console.log("Global configuration not found. Creating a basic one...");
|
|
188
|
+
saveGlobalConfig({ sourceFolders: [] });
|
|
169
189
|
}
|
|
170
190
|
if (!systemctl("--version", [], true)) {
|
|
171
191
|
console.error("systemd is not available on this system.");
|
|
@@ -254,31 +274,75 @@ function statusSystemdService() {
|
|
|
254
274
|
spawnSync("systemctl", ["status", "autopilot.service", ...daemonReloadArgs], { stdio: "inherit" });
|
|
255
275
|
}
|
|
256
276
|
async function initCommand() {
|
|
257
|
-
|
|
258
|
-
const
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
277
|
+
const cwd = process.cwd();
|
|
278
|
+
const validation = validatePath(cwd);
|
|
279
|
+
// 1. Ensure global config exists
|
|
280
|
+
let globalConfig = loadGlobalConfig();
|
|
281
|
+
if (!globalConfig) {
|
|
282
|
+
console.log("Creating new global configuration...");
|
|
283
|
+
globalConfig = { sourceFolders: [] };
|
|
284
|
+
saveGlobalConfig(globalConfig);
|
|
285
|
+
}
|
|
286
|
+
if (validation.isGit) {
|
|
287
|
+
// REPO MODE
|
|
288
|
+
console.log("🚀 Initializing Autopilot in this repository...");
|
|
289
|
+
// a) Add to global scan list if not already there
|
|
290
|
+
if (!globalConfig.sourceFolders.includes(cwd)) {
|
|
291
|
+
globalConfig.sourceFolders.push(cwd);
|
|
292
|
+
saveGlobalConfig(globalConfig);
|
|
293
|
+
}
|
|
294
|
+
// b) Create .autopilot/autopilot.json
|
|
295
|
+
const autopilotDir = node_path_1.default.join(cwd, ".autopilot");
|
|
296
|
+
const autopilotFile = node_path_1.default.join(autopilotDir, "autopilot.json");
|
|
297
|
+
if (!(0, node_fs_1.existsSync)(autopilotDir))
|
|
298
|
+
(0, node_fs_1.mkdirSync)(autopilotDir, { recursive: true });
|
|
299
|
+
if ((0, node_fs_1.existsSync)(autopilotFile)) {
|
|
300
|
+
console.log("⚠️ Autopilot config already exists in this repo.");
|
|
301
|
+
}
|
|
302
|
+
else {
|
|
303
|
+
const repoName = getRepoName(cwd) || "owner/repo";
|
|
304
|
+
const templatePath = node_path_1.default.join(repoRoot, "templates", "autopilot.json");
|
|
305
|
+
let template;
|
|
306
|
+
if ((0, node_fs_1.existsSync)(templatePath)) {
|
|
307
|
+
template = JSON.parse((0, node_fs_1.readFileSync)(templatePath, "utf8"));
|
|
308
|
+
}
|
|
309
|
+
else {
|
|
310
|
+
// Fallback internal default
|
|
311
|
+
template = {
|
|
312
|
+
enabled: true,
|
|
313
|
+
repo: repoName,
|
|
314
|
+
agent: "opencode",
|
|
315
|
+
issueLabels: {
|
|
316
|
+
queue: ["autopilot:todo"],
|
|
317
|
+
blocked: "autopilot:blocked",
|
|
318
|
+
inProgress: "autopilot:in-progress",
|
|
319
|
+
done: "autopilot:done"
|
|
320
|
+
},
|
|
321
|
+
priorityLabels: ["p0", "p1", "p2"],
|
|
322
|
+
maxParallel: 1,
|
|
323
|
+
branchPrefix: "autopilot/",
|
|
324
|
+
allowedBaseBranch: "main"
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
template.repo = repoName;
|
|
328
|
+
(0, node_fs_1.writeFileSync)(autopilotFile, JSON.stringify(template, null, 2) + "\n", "utf8");
|
|
329
|
+
console.log(`✅ Created .autopilot/autopilot.json (repo: ${repoName})`);
|
|
271
330
|
}
|
|
272
331
|
}
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
332
|
+
else {
|
|
333
|
+
// FOLDER MODE
|
|
334
|
+
console.log(`🚀 Adding directory to Autopilot scan list: ${cwd}`);
|
|
335
|
+
if (!globalConfig.sourceFolders.includes(cwd)) {
|
|
336
|
+
globalConfig.sourceFolders.push(cwd);
|
|
337
|
+
saveGlobalConfig(globalConfig);
|
|
338
|
+
console.log("✅ Added to global scan folders.");
|
|
339
|
+
}
|
|
340
|
+
else {
|
|
341
|
+
console.log("ℹ️ This folder is already in the scan list.");
|
|
342
|
+
}
|
|
343
|
+
console.log("\nNote: Autopilot will now scan all sub-folders of this directory for git repos.");
|
|
344
|
+
console.log("You must still run 'autopilot init' inside each repo you want to activate (unless it already has a config).");
|
|
345
|
+
}
|
|
282
346
|
}
|
|
283
347
|
const runnerPath = node_path_1.default.join(repoRoot, "scripts", "run_autopilot.py");
|
|
284
348
|
const program = new commander_1.Command();
|
|
@@ -309,19 +373,30 @@ program
|
|
|
309
373
|
.description("Discover autopilot-enabled repos + show next issue candidate (dry-run)")
|
|
310
374
|
.option("--root <paths...>", "Root folder(s) that contain git repos (space-separated)")
|
|
311
375
|
.option("--max-depth <number>", "Maximum depth for recursive repo discovery", "5")
|
|
376
|
+
.option("--min-priority <label>", "Minimum priority label to work (e.g. p0, p1)")
|
|
377
|
+
.option("--ignore-labels <labels...>", "Ignore issues with these labels (space-separated)")
|
|
312
378
|
.action((opts) => {
|
|
313
379
|
let rootPaths = opts.root;
|
|
314
380
|
if (!rootPaths || rootPaths.length === 0) {
|
|
315
|
-
|
|
316
|
-
if (!config
|
|
317
|
-
|
|
318
|
-
|
|
381
|
+
let config = loadGlobalConfig();
|
|
382
|
+
if (!config) {
|
|
383
|
+
config = { sourceFolders: [] };
|
|
384
|
+
saveGlobalConfig(config);
|
|
319
385
|
}
|
|
320
386
|
rootPaths = config.sourceFolders;
|
|
321
387
|
}
|
|
388
|
+
if (!rootPaths || rootPaths.length === 0) {
|
|
389
|
+
console.log("No source folders configured. Run 'autopilot init' to add some.");
|
|
390
|
+
return;
|
|
391
|
+
}
|
|
322
392
|
const args = [runnerPath, "--root", ...rootPaths];
|
|
323
393
|
if (opts.maxDepth)
|
|
324
394
|
args.push("--max-depth", opts.maxDepth);
|
|
395
|
+
if (opts.minPriority)
|
|
396
|
+
args.push("--min-priority", opts.minPriority);
|
|
397
|
+
if (opts.ignoreLabels && opts.ignoreLabels.length > 0) {
|
|
398
|
+
args.push("--ignore-labels", ...opts.ignoreLabels);
|
|
399
|
+
}
|
|
325
400
|
args.push("--dry-run");
|
|
326
401
|
run("python3", args);
|
|
327
402
|
});
|
|
@@ -330,19 +405,30 @@ program
|
|
|
330
405
|
.description("Claim exactly one issue and post a progress comment")
|
|
331
406
|
.option("--root <paths...>", "Root folder(s) that contain git repos (space-separated)")
|
|
332
407
|
.option("--max-depth <number>", "Maximum depth for recursive repo discovery", "5")
|
|
408
|
+
.option("--min-priority <label>", "Minimum priority label to work (e.g. p0, p1)")
|
|
409
|
+
.option("--ignore-labels <labels...>", "Ignore issues with these labels (space-separated)")
|
|
333
410
|
.action((opts) => {
|
|
334
411
|
let rootPaths = opts.root;
|
|
335
412
|
if (!rootPaths || rootPaths.length === 0) {
|
|
336
|
-
|
|
337
|
-
if (!config
|
|
338
|
-
|
|
339
|
-
|
|
413
|
+
let config = loadGlobalConfig();
|
|
414
|
+
if (!config) {
|
|
415
|
+
config = { sourceFolders: [] };
|
|
416
|
+
saveGlobalConfig(config);
|
|
340
417
|
}
|
|
341
418
|
rootPaths = config.sourceFolders;
|
|
342
419
|
}
|
|
420
|
+
if (!rootPaths || rootPaths.length === 0) {
|
|
421
|
+
console.log("No source folders configured. Run 'autopilot init' to add some.");
|
|
422
|
+
return;
|
|
423
|
+
}
|
|
343
424
|
const args = [runnerPath, "--root", ...rootPaths];
|
|
344
425
|
if (opts.maxDepth)
|
|
345
426
|
args.push("--max-depth", opts.maxDepth);
|
|
427
|
+
if (opts.minPriority)
|
|
428
|
+
args.push("--min-priority", opts.minPriority);
|
|
429
|
+
if (opts.ignoreLabels && opts.ignoreLabels.length > 0) {
|
|
430
|
+
args.push("--ignore-labels", ...opts.ignoreLabels);
|
|
431
|
+
}
|
|
346
432
|
run("python3", args);
|
|
347
433
|
});
|
|
348
434
|
program
|
|
@@ -352,19 +438,30 @@ program
|
|
|
352
438
|
.option("--interval-seconds <number>", "Interval between cycles in seconds", "60")
|
|
353
439
|
.option("--root <paths...>", "Root folder(s) that contain git repos (space-separated)")
|
|
354
440
|
.option("--max-depth <number>", "Maximum depth for recursive repo discovery", "5")
|
|
441
|
+
.option("--min-priority <label>", "Minimum priority label to work (e.g. p0, p1)")
|
|
442
|
+
.option("--ignore-labels <labels...>", "Ignore issues with these labels (space-separated)")
|
|
355
443
|
.action((opts) => {
|
|
356
444
|
let rootPaths = opts.root;
|
|
357
445
|
if (!rootPaths || rootPaths.length === 0) {
|
|
358
|
-
|
|
359
|
-
if (!config
|
|
360
|
-
|
|
361
|
-
|
|
446
|
+
let config = loadGlobalConfig();
|
|
447
|
+
if (!config) {
|
|
448
|
+
config = { sourceFolders: [] };
|
|
449
|
+
saveGlobalConfig(config);
|
|
362
450
|
}
|
|
363
451
|
rootPaths = config.sourceFolders;
|
|
364
452
|
}
|
|
453
|
+
if (!rootPaths || rootPaths.length === 0) {
|
|
454
|
+
console.log("No source folders configured. Run 'autopilot init' to add some.");
|
|
455
|
+
return;
|
|
456
|
+
}
|
|
365
457
|
const args = [runnerPath, "--root", ...rootPaths];
|
|
366
458
|
if (opts.maxDepth)
|
|
367
459
|
args.push("--max-depth", opts.maxDepth);
|
|
460
|
+
if (opts.minPriority)
|
|
461
|
+
args.push("--min-priority", opts.minPriority);
|
|
462
|
+
if (opts.ignoreLabels && opts.ignoreLabels.length > 0) {
|
|
463
|
+
args.push("--ignore-labels", ...opts.ignoreLabels);
|
|
464
|
+
}
|
|
368
465
|
if (opts.foreground) {
|
|
369
466
|
const interval = opts.intervalSeconds || "60";
|
|
370
467
|
args.push("--interval-seconds", interval);
|
package/package.json
CHANGED
package/scripts/run_autopilot.py
CHANGED
|
@@ -433,6 +433,8 @@ def main() -> int:
|
|
|
433
433
|
default=None,
|
|
434
434
|
help="Run in loop mode with this interval between cycles (for foreground service mode)",
|
|
435
435
|
)
|
|
436
|
+
ap.add_argument("--min-priority", help="Override minPriority for all discovered repos")
|
|
437
|
+
ap.add_argument("--ignore-labels", nargs="+", help="Override ignoreIssueLabels for all discovered repos")
|
|
436
438
|
args = ap.parse_args()
|
|
437
439
|
|
|
438
440
|
all_configs: list[RepoConfig] = []
|
|
@@ -445,6 +447,14 @@ def main() -> int:
|
|
|
445
447
|
print(f"Warning: root path {root} is not a directory, skipping")
|
|
446
448
|
continue
|
|
447
449
|
configs = discover_repos(root, max_depth=args.max_depth)
|
|
450
|
+
|
|
451
|
+
# Apply overrides
|
|
452
|
+
for cfg in configs:
|
|
453
|
+
if args.min_priority:
|
|
454
|
+
cfg.min_priority = args.min_priority
|
|
455
|
+
if args.ignore_labels:
|
|
456
|
+
cfg.ignore_issue_labels = args.ignore_labels
|
|
457
|
+
|
|
448
458
|
all_configs.extend(configs)
|
|
449
459
|
|
|
450
460
|
if not all_configs:
|