@tarcisiopgs/lisa 1.39.1 → 1.40.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.
|
@@ -1138,6 +1138,13 @@ async function checkoutBaseBranches(config, workspace) {
|
|
|
1138
1138
|
function sleep(ms) {
|
|
1139
1139
|
return new Promise((resolve12) => setTimeout(resolve12, ms));
|
|
1140
1140
|
}
|
|
1141
|
+
async function interruptibleSleep(ms) {
|
|
1142
|
+
const end = Date.now() + ms;
|
|
1143
|
+
while (Date.now() < end) {
|
|
1144
|
+
if (isShuttingDown() || hasUserQuitFromWatchPrompt()) return;
|
|
1145
|
+
await sleep(Math.min(1e3, end - Date.now()));
|
|
1146
|
+
}
|
|
1147
|
+
}
|
|
1141
1148
|
async function waitIfPaused() {
|
|
1142
1149
|
while (isLoopPaused()) {
|
|
1143
1150
|
await sleep(500);
|
|
@@ -1191,24 +1198,56 @@ function emptyCommitFailure(result) {
|
|
|
1191
1198
|
async function pullBaseBranch(config) {
|
|
1192
1199
|
const workspace = resolve3(config.workspace);
|
|
1193
1200
|
const baseBranch = config.base_branch;
|
|
1194
|
-
const repoPaths = [
|
|
1201
|
+
const repoPaths = [];
|
|
1195
1202
|
if (config.repos.length > 0) {
|
|
1196
1203
|
for (const repo of config.repos) {
|
|
1197
1204
|
repoPaths.push(resolve3(workspace, repo.path));
|
|
1198
1205
|
}
|
|
1206
|
+
} else {
|
|
1207
|
+
repoPaths.push(workspace);
|
|
1199
1208
|
}
|
|
1200
1209
|
for (const repoPath of repoPaths) {
|
|
1201
1210
|
try {
|
|
1211
|
+
await execa("git", ["checkout", baseBranch], {
|
|
1212
|
+
cwd: repoPath,
|
|
1213
|
+
reject: true,
|
|
1214
|
+
timeout: 15e3
|
|
1215
|
+
});
|
|
1202
1216
|
await execa("git", ["pull", "--ff-only", "origin", baseBranch], {
|
|
1203
1217
|
cwd: repoPath,
|
|
1204
1218
|
reject: true,
|
|
1205
1219
|
timeout: 3e4
|
|
1206
1220
|
});
|
|
1207
|
-
} catch
|
|
1208
|
-
|
|
1221
|
+
} catch {
|
|
1222
|
+
try {
|
|
1223
|
+
await execa("git", ["fetch", "origin", baseBranch], {
|
|
1224
|
+
cwd: repoPath,
|
|
1225
|
+
reject: true,
|
|
1226
|
+
timeout: 3e4
|
|
1227
|
+
});
|
|
1228
|
+
await execa("git", ["reset", "--hard", `origin/${baseBranch}`], {
|
|
1229
|
+
cwd: repoPath,
|
|
1230
|
+
reject: true,
|
|
1231
|
+
timeout: 15e3
|
|
1232
|
+
});
|
|
1233
|
+
} catch (err) {
|
|
1234
|
+
warn(`Failed to pull ${baseBranch} in ${repoPath}: ${formatError(err)}`);
|
|
1235
|
+
}
|
|
1209
1236
|
}
|
|
1210
1237
|
}
|
|
1211
1238
|
}
|
|
1239
|
+
async function autoMergePr(prUrl, issueId, config) {
|
|
1240
|
+
if (!config.pr?.auto_merge) return;
|
|
1241
|
+
log(`Auto-merging PR for ${issueId}...`);
|
|
1242
|
+
const { mergePr } = await import("./merge-NWSEV3FR.js");
|
|
1243
|
+
const result = await mergePr(prUrl);
|
|
1244
|
+
if (result.success) {
|
|
1245
|
+
ok(`Auto-merged: ${prUrl}`);
|
|
1246
|
+
kanbanEmitter.emit("issue:merged", issueId);
|
|
1247
|
+
} else {
|
|
1248
|
+
warn(`Auto-merge failed for ${issueId}: ${result.error}`);
|
|
1249
|
+
}
|
|
1250
|
+
}
|
|
1212
1251
|
function appendSessionLog(logFile, result) {
|
|
1213
1252
|
try {
|
|
1214
1253
|
appendFileSync(
|
|
@@ -1450,6 +1489,7 @@ async function recoverOrphanIssues(source, config) {
|
|
|
1450
1489
|
);
|
|
1451
1490
|
try {
|
|
1452
1491
|
await source.updateStatus(orphan.id, config.source_config.pick_from, config.source_config);
|
|
1492
|
+
kanbanEmitter.emit("issue:reverted", orphan.id);
|
|
1453
1493
|
ok(`Recovered orphan ${orphan.id}`);
|
|
1454
1494
|
} catch (err) {
|
|
1455
1495
|
error(`Failed to recover orphan ${orphan.id}: ${formatError(err)}`);
|
|
@@ -3213,6 +3253,7 @@ async function runNativeWorktreeSession(config, issue, logFile, session, models,
|
|
|
3213
3253
|
}
|
|
3214
3254
|
}
|
|
3215
3255
|
if (worktreePath) await cleanupWorktree(repoPath, worktreePath);
|
|
3256
|
+
await autoMergePr(prUrl, issue.id, config);
|
|
3216
3257
|
await reporter.finish([prUrl]);
|
|
3217
3258
|
ok(`Session ${session} complete for ${issue.id}`);
|
|
3218
3259
|
return {
|
|
@@ -3490,6 +3531,7 @@ async function runManualWorktreeSession(config, issue, logFile, session, models,
|
|
|
3490
3531
|
}
|
|
3491
3532
|
await executeHook("before_remove", config.hooks, worktreePath, hookEnv);
|
|
3492
3533
|
await cleanupWorktree(repoPath, worktreePath);
|
|
3534
|
+
await autoMergePr(prUrl, issue.id, config);
|
|
3493
3535
|
await reporter.finish([prUrl]);
|
|
3494
3536
|
updateSessionState(workspace, issue.id, "done");
|
|
3495
3537
|
removeSessionRecord(workspace, issue.id);
|
|
@@ -3648,7 +3690,11 @@ async function runConcurrentLoop(config, source, models, workspace, opts) {
|
|
|
3648
3690
|
);
|
|
3649
3691
|
kanbanEmitter.emit("work:watching");
|
|
3650
3692
|
setTitle("Lisa \u2014 watching...");
|
|
3651
|
-
await
|
|
3693
|
+
await interruptibleSleep(WATCH_POLL_INTERVAL_MS);
|
|
3694
|
+
if (hasUserQuitFromWatchPrompt() || isShuttingDown()) {
|
|
3695
|
+
noMoreIssues = true;
|
|
3696
|
+
break;
|
|
3697
|
+
}
|
|
3652
3698
|
kanbanEmitter.emit("work:watch-resume");
|
|
3653
3699
|
}
|
|
3654
3700
|
break;
|
|
@@ -4019,6 +4065,7 @@ async function runBranchSession(config, issue, logFile, session, models, source,
|
|
|
4019
4065
|
}
|
|
4020
4066
|
}
|
|
4021
4067
|
}
|
|
4068
|
+
await autoMergePr(prUrl, issue.id, config);
|
|
4022
4069
|
await reporter.finish([prUrl]);
|
|
4023
4070
|
ok(`Session ${session} complete for ${issue.id}`);
|
|
4024
4071
|
return {
|
|
@@ -4121,7 +4168,10 @@ async function runSequentialLoop(config, source, models, workspace, opts) {
|
|
|
4121
4168
|
ok(`Resuming watch mode (polling every ${WATCH_POLL_INTERVAL_MS / 1e3}s)...`);
|
|
4122
4169
|
kanbanEmitter.emit("work:watching");
|
|
4123
4170
|
setTitle("Lisa \u2014 watching...");
|
|
4124
|
-
await
|
|
4171
|
+
await interruptibleSleep(WATCH_POLL_INTERVAL_MS);
|
|
4172
|
+
if (hasUserQuitFromWatchPrompt() || isShuttingDown()) {
|
|
4173
|
+
break;
|
|
4174
|
+
}
|
|
4125
4175
|
kanbanEmitter.emit("work:watch-resume");
|
|
4126
4176
|
session--;
|
|
4127
4177
|
continue;
|
|
@@ -4131,7 +4181,10 @@ async function runSequentialLoop(config, source, models, workspace, opts) {
|
|
|
4131
4181
|
);
|
|
4132
4182
|
kanbanEmitter.emit("work:watching");
|
|
4133
4183
|
setTitle("Lisa \u2014 watching...");
|
|
4134
|
-
await
|
|
4184
|
+
await interruptibleSleep(WATCH_POLL_INTERVAL_MS);
|
|
4185
|
+
if (hasUserQuitFromWatchPrompt() || isShuttingDown()) {
|
|
4186
|
+
break;
|
|
4187
|
+
}
|
|
4135
4188
|
kanbanEmitter.emit("work:watch-resume");
|
|
4136
4189
|
session--;
|
|
4137
4190
|
continue;
|
package/dist/index.js
CHANGED
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
runLoop,
|
|
15
15
|
saveConfig,
|
|
16
16
|
validateConfig
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-C2Y2NO6I.js";
|
|
18
18
|
import {
|
|
19
19
|
CliError,
|
|
20
20
|
buildExecutionWaves,
|
|
@@ -708,6 +708,12 @@ This will cause Lisa to re-pick the issue on recovery. Consider using a differen
|
|
|
708
708
|
});
|
|
709
709
|
prReviewers = Array.isArray(reviewerValue) ? reviewerValue : reviewerValue.split(",").map((s) => s.trim()).filter(Boolean);
|
|
710
710
|
}
|
|
711
|
+
const wantAutoMerge = await clack.confirm({
|
|
712
|
+
message: "Auto-merge PRs after CI passes?",
|
|
713
|
+
initialValue: initial?.pr?.auto_merge ?? false
|
|
714
|
+
});
|
|
715
|
+
if (clack.isCancel(wantAutoMerge)) return process.exit(0);
|
|
716
|
+
const autoMerge = wantAutoMerge === true;
|
|
711
717
|
const cfg = {
|
|
712
718
|
provider: providerName,
|
|
713
719
|
provider_options: {
|
|
@@ -734,7 +740,12 @@ This will cause Lisa to re-pick the issue on recovery. Consider using a differen
|
|
|
734
740
|
repos,
|
|
735
741
|
loop: { cooldown: 10, max_sessions: 0 },
|
|
736
742
|
...reviewMonitorEnabled ? { review_monitor: { enabled: true } } : {},
|
|
737
|
-
...prReviewers.length
|
|
743
|
+
...prReviewers.length || autoMerge ? {
|
|
744
|
+
pr: {
|
|
745
|
+
...prReviewers.length ? { reviewers: prReviewers } : {},
|
|
746
|
+
...autoMerge ? { auto_merge: true } : {}
|
|
747
|
+
}
|
|
748
|
+
} : {}
|
|
738
749
|
};
|
|
739
750
|
saveConfig(cfg);
|
|
740
751
|
clack.outro(
|
|
@@ -1850,7 +1861,7 @@ async function reviewAndCreate(plan2, planPath, opts) {
|
|
|
1850
1861
|
log("Run `lisa run` when ready.");
|
|
1851
1862
|
return;
|
|
1852
1863
|
}
|
|
1853
|
-
const { runLoop: runLoop2 } = await import("./loop-
|
|
1864
|
+
const { runLoop: runLoop2 } = await import("./loop-Y6YS76TH.js");
|
|
1854
1865
|
const waves = buildExecutionWaves(plan2.issues);
|
|
1855
1866
|
const maxWaveSize = Math.max(...waves.map((w) => w.length));
|
|
1856
1867
|
await runLoop2(config2, {
|