@tarcisiopgs/lisa 1.39.2 → 1.40.1

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.
@@ -212,10 +212,12 @@ function parsePrConfig(raw) {
212
212
  if (!raw) return void 0;
213
213
  const reviewers = isStringArray(raw.reviewers) ? raw.reviewers.filter(isValidPrUsername) : void 0;
214
214
  const assignees = isStringArray(raw.assignees) ? raw.assignees.filter(isValidPrUsername) : void 0;
215
- if (!reviewers?.length && !assignees?.length) return void 0;
215
+ const autoMerge = raw.auto_merge === true;
216
+ if (!reviewers?.length && !assignees?.length && !autoMerge) return void 0;
216
217
  return {
217
218
  reviewers: reviewers?.length ? reviewers : void 0,
218
- assignees: assignees?.length ? assignees : void 0
219
+ assignees: assignees?.length ? assignees : void 0,
220
+ auto_merge: autoMerge || void 0
219
221
  };
220
222
  }
221
223
  function loadConfig(cwd = process.cwd()) {
@@ -1138,6 +1140,13 @@ async function checkoutBaseBranches(config, workspace) {
1138
1140
  function sleep(ms) {
1139
1141
  return new Promise((resolve12) => setTimeout(resolve12, ms));
1140
1142
  }
1143
+ async function interruptibleSleep(ms) {
1144
+ const end = Date.now() + ms;
1145
+ while (Date.now() < end) {
1146
+ if (isShuttingDown() || hasUserQuitFromWatchPrompt()) return;
1147
+ await sleep(Math.min(1e3, end - Date.now()));
1148
+ }
1149
+ }
1141
1150
  async function waitIfPaused() {
1142
1151
  while (isLoopPaused()) {
1143
1152
  await sleep(500);
@@ -1229,6 +1238,18 @@ async function pullBaseBranch(config) {
1229
1238
  }
1230
1239
  }
1231
1240
  }
1241
+ async function autoMergePr(prUrl, issueId, config) {
1242
+ if (!config.pr?.auto_merge) return;
1243
+ log(`Auto-merging PR for ${issueId}...`);
1244
+ const { mergePr } = await import("./merge-NWSEV3FR.js");
1245
+ const result = await mergePr(prUrl);
1246
+ if (result.success) {
1247
+ ok(`Auto-merged: ${prUrl}`);
1248
+ kanbanEmitter.emit("issue:merged", issueId);
1249
+ } else {
1250
+ warn(`Auto-merge failed for ${issueId}: ${result.error}`);
1251
+ }
1252
+ }
1232
1253
  function appendSessionLog(logFile, result) {
1233
1254
  try {
1234
1255
  appendFileSync(
@@ -3234,6 +3255,7 @@ async function runNativeWorktreeSession(config, issue, logFile, session, models,
3234
3255
  }
3235
3256
  }
3236
3257
  if (worktreePath) await cleanupWorktree(repoPath, worktreePath);
3258
+ await autoMergePr(prUrl, issue.id, config);
3237
3259
  await reporter.finish([prUrl]);
3238
3260
  ok(`Session ${session} complete for ${issue.id}`);
3239
3261
  return {
@@ -3511,6 +3533,7 @@ async function runManualWorktreeSession(config, issue, logFile, session, models,
3511
3533
  }
3512
3534
  await executeHook("before_remove", config.hooks, worktreePath, hookEnv);
3513
3535
  await cleanupWorktree(repoPath, worktreePath);
3536
+ await autoMergePr(prUrl, issue.id, config);
3514
3537
  await reporter.finish([prUrl]);
3515
3538
  updateSessionState(workspace, issue.id, "done");
3516
3539
  removeSessionRecord(workspace, issue.id);
@@ -3669,7 +3692,11 @@ async function runConcurrentLoop(config, source, models, workspace, opts) {
3669
3692
  );
3670
3693
  kanbanEmitter.emit("work:watching");
3671
3694
  setTitle("Lisa \u2014 watching...");
3672
- await sleep(WATCH_POLL_INTERVAL_MS);
3695
+ await interruptibleSleep(WATCH_POLL_INTERVAL_MS);
3696
+ if (hasUserQuitFromWatchPrompt() || isShuttingDown()) {
3697
+ noMoreIssues = true;
3698
+ break;
3699
+ }
3673
3700
  kanbanEmitter.emit("work:watch-resume");
3674
3701
  }
3675
3702
  break;
@@ -4040,6 +4067,7 @@ async function runBranchSession(config, issue, logFile, session, models, source,
4040
4067
  }
4041
4068
  }
4042
4069
  }
4070
+ await autoMergePr(prUrl, issue.id, config);
4043
4071
  await reporter.finish([prUrl]);
4044
4072
  ok(`Session ${session} complete for ${issue.id}`);
4045
4073
  return {
@@ -4142,7 +4170,10 @@ async function runSequentialLoop(config, source, models, workspace, opts) {
4142
4170
  ok(`Resuming watch mode (polling every ${WATCH_POLL_INTERVAL_MS / 1e3}s)...`);
4143
4171
  kanbanEmitter.emit("work:watching");
4144
4172
  setTitle("Lisa \u2014 watching...");
4145
- await sleep(WATCH_POLL_INTERVAL_MS);
4173
+ await interruptibleSleep(WATCH_POLL_INTERVAL_MS);
4174
+ if (hasUserQuitFromWatchPrompt() || isShuttingDown()) {
4175
+ break;
4176
+ }
4146
4177
  kanbanEmitter.emit("work:watch-resume");
4147
4178
  session--;
4148
4179
  continue;
@@ -4152,7 +4183,10 @@ async function runSequentialLoop(config, source, models, workspace, opts) {
4152
4183
  );
4153
4184
  kanbanEmitter.emit("work:watching");
4154
4185
  setTitle("Lisa \u2014 watching...");
4155
- await sleep(WATCH_POLL_INTERVAL_MS);
4186
+ await interruptibleSleep(WATCH_POLL_INTERVAL_MS);
4187
+ if (hasUserQuitFromWatchPrompt() || isShuttingDown()) {
4188
+ break;
4189
+ }
4156
4190
  kanbanEmitter.emit("work:watch-resume");
4157
4191
  session--;
4158
4192
  continue;
package/dist/index.js CHANGED
@@ -14,7 +14,7 @@ import {
14
14
  runLoop,
15
15
  saveConfig,
16
16
  validateConfig
17
- } from "./chunk-FJ6YGFS2.js";
17
+ } from "./chunk-V65N7YWX.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 ? { pr: { reviewers: prReviewers } } : {}
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-XXHTAE2N.js");
1864
+ const { runLoop: runLoop2 } = await import("./loop-CSJRDKQU.js");
1854
1865
  const waves = buildExecutionWaves(plan2.issues);
1855
1866
  const maxWaveSize = Math.max(...waves.map((w) => w.length));
1856
1867
  await runLoop2(config2, {
@@ -4,7 +4,7 @@ import {
4
4
  cleanupEventListeners,
5
5
  runDemoLoop,
6
6
  runLoop
7
- } from "./chunk-FJ6YGFS2.js";
7
+ } from "./chunk-V65N7YWX.js";
8
8
  import {
9
9
  WATCH_POLL_INTERVAL_MS
10
10
  } from "./chunk-YTUZFCU2.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tarcisiopgs/lisa",
3
- "version": "1.39.2",
3
+ "version": "1.40.1",
4
4
  "description": "Autonomous issue resolver",
5
5
  "keywords": [
6
6
  "loop",