@gethmy/agent 1.11.1 → 1.11.2
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 +62 -15
- package/dist/index.js +62 -15
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1228,7 +1228,8 @@ function fetchBaseBranch(repoRoot, baseBranch, attempts = 3, fetchImpl = (root,
|
|
|
1228
1228
|
log.warn(TAG5, `fetch origin ${baseBranch} failed (attempt ${attempt}/${attempts})`);
|
|
1229
1229
|
}
|
|
1230
1230
|
}
|
|
1231
|
-
const
|
|
1231
|
+
const e = lastErr;
|
|
1232
|
+
const detail = e?.stderr?.toString?.().trim() || (lastErr instanceof Error ? lastErr.message : String(lastErr));
|
|
1232
1233
|
throw new WorktreeBaseError(`Could not fetch origin/${baseBranch} after ${attempts} attempts — ` + `refusing to build on a stale base. ${detail}`);
|
|
1233
1234
|
}
|
|
1234
1235
|
function createWorktree(basePath, baseBranch, branchName) {
|
|
@@ -1350,6 +1351,16 @@ var init_worktree = __esm(() => {
|
|
|
1350
1351
|
import { execFileSync as execFileSync4, execSync as execSync3 } from "node:child_process";
|
|
1351
1352
|
import { existsSync as existsSync3 } from "node:fs";
|
|
1352
1353
|
import { resolve as resolve2 } from "node:path";
|
|
1354
|
+
function gitErrorDetail(err) {
|
|
1355
|
+
const e = err;
|
|
1356
|
+
const stderr = e?.stderr?.toString?.().trim();
|
|
1357
|
+
if (stderr)
|
|
1358
|
+
return stderr;
|
|
1359
|
+
const stdout = e?.stdout?.toString?.().trim();
|
|
1360
|
+
if (stdout)
|
|
1361
|
+
return stdout;
|
|
1362
|
+
return err instanceof Error ? err.message : String(err);
|
|
1363
|
+
}
|
|
1353
1364
|
function checkoutExistingBranch(basePath, branchName) {
|
|
1354
1365
|
const repoRoot = execFileSync4("git", ["rev-parse", "--show-toplevel"], {
|
|
1355
1366
|
encoding: "utf-8"
|
|
@@ -1370,8 +1381,8 @@ function checkoutExistingBranch(basePath, branchName) {
|
|
|
1370
1381
|
cwd: repoRoot,
|
|
1371
1382
|
stdio: "pipe"
|
|
1372
1383
|
});
|
|
1373
|
-
} catch {
|
|
1374
|
-
throw new Error(`Failed to fetch remote branch
|
|
1384
|
+
} catch (err) {
|
|
1385
|
+
throw new Error(`Failed to fetch remote branch ${branchName}: ${gitErrorDetail(err)}`);
|
|
1375
1386
|
}
|
|
1376
1387
|
try {
|
|
1377
1388
|
execFileSync4("git", ["branch", "-D", branchName], {
|
|
@@ -1380,15 +1391,19 @@ function checkoutExistingBranch(basePath, branchName) {
|
|
|
1380
1391
|
});
|
|
1381
1392
|
} catch {}
|
|
1382
1393
|
log.info(TAG6, `Creating review worktree: ${worktreeDir} (branch: ${branchName})`);
|
|
1383
|
-
|
|
1384
|
-
"
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1394
|
+
try {
|
|
1395
|
+
execFileSync4("git", [
|
|
1396
|
+
"worktree",
|
|
1397
|
+
"add",
|
|
1398
|
+
"--track",
|
|
1399
|
+
"-b",
|
|
1400
|
+
branchName,
|
|
1401
|
+
worktreeDir,
|
|
1402
|
+
`origin/${branchName}`
|
|
1403
|
+
], { cwd: repoRoot, stdio: "pipe" });
|
|
1404
|
+
} catch (err) {
|
|
1405
|
+
throw new Error(`Failed to create review worktree for ${branchName}: ${gitErrorDetail(err)}`);
|
|
1406
|
+
}
|
|
1392
1407
|
log.info(TAG6, "Installing dependencies in review worktree...");
|
|
1393
1408
|
try {
|
|
1394
1409
|
execSync3(installCommand(), {
|
|
@@ -2613,6 +2628,7 @@ async function runCompletion(client, card, branchName, worktreePath, config, wor
|
|
|
2613
2628
|
reviewFindings: [],
|
|
2614
2629
|
revertWarnings: []
|
|
2615
2630
|
};
|
|
2631
|
+
commitUncommittedChanges(worktreePath, card);
|
|
2616
2632
|
const hasCommits = checkHasCommits(worktreePath, config.worktree.baseBranch);
|
|
2617
2633
|
if (!hasCommits) {
|
|
2618
2634
|
const { maxTurnsExhausted, failureSummary } = describeNoCommitFailure(sessionStats?.cost?.numTurns ?? 0, config.claude.maxTurns);
|
|
@@ -2787,6 +2803,37 @@ function readHeadSha(worktreePath) {
|
|
|
2787
2803
|
return null;
|
|
2788
2804
|
}
|
|
2789
2805
|
}
|
|
2806
|
+
function commitUncommittedChanges(worktreePath, card) {
|
|
2807
|
+
let status = "";
|
|
2808
|
+
try {
|
|
2809
|
+
status = execFileSync9("git", ["status", "--porcelain"], {
|
|
2810
|
+
cwd: worktreePath,
|
|
2811
|
+
encoding: "utf-8"
|
|
2812
|
+
}).trim();
|
|
2813
|
+
} catch (err) {
|
|
2814
|
+
log.warn(TAG14, `git status failed in ${worktreePath}: ${err instanceof Error ? err.message : err}`);
|
|
2815
|
+
return false;
|
|
2816
|
+
}
|
|
2817
|
+
if (status.length === 0)
|
|
2818
|
+
return false;
|
|
2819
|
+
const title = card.title?.trim() || "agent changes";
|
|
2820
|
+
const message = `#${card.short_id} ${title}`;
|
|
2821
|
+
try {
|
|
2822
|
+
execFileSync9("git", ["add", "-A"], {
|
|
2823
|
+
cwd: worktreePath,
|
|
2824
|
+
encoding: "utf-8"
|
|
2825
|
+
});
|
|
2826
|
+
execFileSync9("git", ["commit", "-m", message], {
|
|
2827
|
+
cwd: worktreePath,
|
|
2828
|
+
encoding: "utf-8"
|
|
2829
|
+
});
|
|
2830
|
+
log.warn(TAG14, `Auto-committed uncommitted worktree changes for #${card.short_id} — agent ended without committing`);
|
|
2831
|
+
return true;
|
|
2832
|
+
} catch (err) {
|
|
2833
|
+
log.error(TAG14, `auto-commit failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
|
|
2834
|
+
return false;
|
|
2835
|
+
}
|
|
2836
|
+
}
|
|
2790
2837
|
function checkHasCommits(worktreePath, baseBranch) {
|
|
2791
2838
|
try {
|
|
2792
2839
|
const count = execFileSync9("git", ["rev-list", "--count", `origin/${baseBranch}..HEAD`], { cwd: worktreePath, encoding: "utf-8" }).trim();
|
|
@@ -7758,7 +7805,7 @@ import { resolve as resolve3 } from "node:path";
|
|
|
7758
7805
|
function isTransientGitNetworkError(message) {
|
|
7759
7806
|
return TRANSIENT_GIT_NETWORK_ERROR.test(message);
|
|
7760
7807
|
}
|
|
7761
|
-
function
|
|
7808
|
+
function gitErrorDetail2(err) {
|
|
7762
7809
|
if (err && typeof err === "object" && "stderr" in err) {
|
|
7763
7810
|
const stderr = String(err.stderr ?? "").trim();
|
|
7764
7811
|
if (stderr)
|
|
@@ -7857,7 +7904,7 @@ function pruneFailedRemoteBranches(opts) {
|
|
|
7857
7904
|
...GIT_NETWORK_EXEC
|
|
7858
7905
|
});
|
|
7859
7906
|
} catch (err) {
|
|
7860
|
-
const detail =
|
|
7907
|
+
const detail = gitErrorDetail2(err);
|
|
7861
7908
|
if (isTransientGitNetworkError(detail)) {
|
|
7862
7909
|
log.debug(TAG33, `Remote branch GC skipped — remote unreachable: ${detail}`);
|
|
7863
7910
|
return result;
|
|
@@ -7909,7 +7956,7 @@ function pruneFailedRemoteBranches(opts) {
|
|
|
7909
7956
|
});
|
|
7910
7957
|
result.removed.push(ref);
|
|
7911
7958
|
} catch (err) {
|
|
7912
|
-
const detail =
|
|
7959
|
+
const detail = gitErrorDetail2(err);
|
|
7913
7960
|
if (isTransientGitNetworkError(detail)) {
|
|
7914
7961
|
log.debug(TAG33, `Remote branch GC interrupted — remote unreachable: ${detail}`);
|
|
7915
7962
|
break;
|
package/dist/index.js
CHANGED
|
@@ -1227,7 +1227,8 @@ function fetchBaseBranch(repoRoot, baseBranch, attempts = 3, fetchImpl = (root,
|
|
|
1227
1227
|
log.warn(TAG5, `fetch origin ${baseBranch} failed (attempt ${attempt}/${attempts})`);
|
|
1228
1228
|
}
|
|
1229
1229
|
}
|
|
1230
|
-
const
|
|
1230
|
+
const e = lastErr;
|
|
1231
|
+
const detail = e?.stderr?.toString?.().trim() || (lastErr instanceof Error ? lastErr.message : String(lastErr));
|
|
1231
1232
|
throw new WorktreeBaseError(`Could not fetch origin/${baseBranch} after ${attempts} attempts — ` + `refusing to build on a stale base. ${detail}`);
|
|
1232
1233
|
}
|
|
1233
1234
|
function createWorktree(basePath, baseBranch, branchName) {
|
|
@@ -1349,6 +1350,16 @@ var init_worktree = __esm(() => {
|
|
|
1349
1350
|
import { execFileSync as execFileSync4, execSync as execSync3 } from "node:child_process";
|
|
1350
1351
|
import { existsSync as existsSync3 } from "node:fs";
|
|
1351
1352
|
import { resolve as resolve2 } from "node:path";
|
|
1353
|
+
function gitErrorDetail(err) {
|
|
1354
|
+
const e = err;
|
|
1355
|
+
const stderr = e?.stderr?.toString?.().trim();
|
|
1356
|
+
if (stderr)
|
|
1357
|
+
return stderr;
|
|
1358
|
+
const stdout = e?.stdout?.toString?.().trim();
|
|
1359
|
+
if (stdout)
|
|
1360
|
+
return stdout;
|
|
1361
|
+
return err instanceof Error ? err.message : String(err);
|
|
1362
|
+
}
|
|
1352
1363
|
function checkoutExistingBranch(basePath, branchName) {
|
|
1353
1364
|
const repoRoot = execFileSync4("git", ["rev-parse", "--show-toplevel"], {
|
|
1354
1365
|
encoding: "utf-8"
|
|
@@ -1369,8 +1380,8 @@ function checkoutExistingBranch(basePath, branchName) {
|
|
|
1369
1380
|
cwd: repoRoot,
|
|
1370
1381
|
stdio: "pipe"
|
|
1371
1382
|
});
|
|
1372
|
-
} catch {
|
|
1373
|
-
throw new Error(`Failed to fetch remote branch
|
|
1383
|
+
} catch (err) {
|
|
1384
|
+
throw new Error(`Failed to fetch remote branch ${branchName}: ${gitErrorDetail(err)}`);
|
|
1374
1385
|
}
|
|
1375
1386
|
try {
|
|
1376
1387
|
execFileSync4("git", ["branch", "-D", branchName], {
|
|
@@ -1379,15 +1390,19 @@ function checkoutExistingBranch(basePath, branchName) {
|
|
|
1379
1390
|
});
|
|
1380
1391
|
} catch {}
|
|
1381
1392
|
log.info(TAG6, `Creating review worktree: ${worktreeDir} (branch: ${branchName})`);
|
|
1382
|
-
|
|
1383
|
-
"
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1393
|
+
try {
|
|
1394
|
+
execFileSync4("git", [
|
|
1395
|
+
"worktree",
|
|
1396
|
+
"add",
|
|
1397
|
+
"--track",
|
|
1398
|
+
"-b",
|
|
1399
|
+
branchName,
|
|
1400
|
+
worktreeDir,
|
|
1401
|
+
`origin/${branchName}`
|
|
1402
|
+
], { cwd: repoRoot, stdio: "pipe" });
|
|
1403
|
+
} catch (err) {
|
|
1404
|
+
throw new Error(`Failed to create review worktree for ${branchName}: ${gitErrorDetail(err)}`);
|
|
1405
|
+
}
|
|
1391
1406
|
log.info(TAG6, "Installing dependencies in review worktree...");
|
|
1392
1407
|
try {
|
|
1393
1408
|
execSync3(installCommand(), {
|
|
@@ -2612,6 +2627,7 @@ async function runCompletion(client, card, branchName, worktreePath, config, wor
|
|
|
2612
2627
|
reviewFindings: [],
|
|
2613
2628
|
revertWarnings: []
|
|
2614
2629
|
};
|
|
2630
|
+
commitUncommittedChanges(worktreePath, card);
|
|
2615
2631
|
const hasCommits = checkHasCommits(worktreePath, config.worktree.baseBranch);
|
|
2616
2632
|
if (!hasCommits) {
|
|
2617
2633
|
const { maxTurnsExhausted, failureSummary } = describeNoCommitFailure(sessionStats?.cost?.numTurns ?? 0, config.claude.maxTurns);
|
|
@@ -2786,6 +2802,37 @@ function readHeadSha(worktreePath) {
|
|
|
2786
2802
|
return null;
|
|
2787
2803
|
}
|
|
2788
2804
|
}
|
|
2805
|
+
function commitUncommittedChanges(worktreePath, card) {
|
|
2806
|
+
let status = "";
|
|
2807
|
+
try {
|
|
2808
|
+
status = execFileSync9("git", ["status", "--porcelain"], {
|
|
2809
|
+
cwd: worktreePath,
|
|
2810
|
+
encoding: "utf-8"
|
|
2811
|
+
}).trim();
|
|
2812
|
+
} catch (err) {
|
|
2813
|
+
log.warn(TAG14, `git status failed in ${worktreePath}: ${err instanceof Error ? err.message : err}`);
|
|
2814
|
+
return false;
|
|
2815
|
+
}
|
|
2816
|
+
if (status.length === 0)
|
|
2817
|
+
return false;
|
|
2818
|
+
const title = card.title?.trim() || "agent changes";
|
|
2819
|
+
const message = `#${card.short_id} ${title}`;
|
|
2820
|
+
try {
|
|
2821
|
+
execFileSync9("git", ["add", "-A"], {
|
|
2822
|
+
cwd: worktreePath,
|
|
2823
|
+
encoding: "utf-8"
|
|
2824
|
+
});
|
|
2825
|
+
execFileSync9("git", ["commit", "-m", message], {
|
|
2826
|
+
cwd: worktreePath,
|
|
2827
|
+
encoding: "utf-8"
|
|
2828
|
+
});
|
|
2829
|
+
log.warn(TAG14, `Auto-committed uncommitted worktree changes for #${card.short_id} — agent ended without committing`);
|
|
2830
|
+
return true;
|
|
2831
|
+
} catch (err) {
|
|
2832
|
+
log.error(TAG14, `auto-commit failed for #${card.short_id}: ${err instanceof Error ? err.message : err}`);
|
|
2833
|
+
return false;
|
|
2834
|
+
}
|
|
2835
|
+
}
|
|
2789
2836
|
function checkHasCommits(worktreePath, baseBranch) {
|
|
2790
2837
|
try {
|
|
2791
2838
|
const count = execFileSync9("git", ["rev-list", "--count", `origin/${baseBranch}..HEAD`], { cwd: worktreePath, encoding: "utf-8" }).trim();
|
|
@@ -7757,7 +7804,7 @@ import { resolve as resolve3 } from "node:path";
|
|
|
7757
7804
|
function isTransientGitNetworkError(message) {
|
|
7758
7805
|
return TRANSIENT_GIT_NETWORK_ERROR.test(message);
|
|
7759
7806
|
}
|
|
7760
|
-
function
|
|
7807
|
+
function gitErrorDetail2(err) {
|
|
7761
7808
|
if (err && typeof err === "object" && "stderr" in err) {
|
|
7762
7809
|
const stderr = String(err.stderr ?? "").trim();
|
|
7763
7810
|
if (stderr)
|
|
@@ -7856,7 +7903,7 @@ function pruneFailedRemoteBranches(opts) {
|
|
|
7856
7903
|
...GIT_NETWORK_EXEC
|
|
7857
7904
|
});
|
|
7858
7905
|
} catch (err) {
|
|
7859
|
-
const detail =
|
|
7906
|
+
const detail = gitErrorDetail2(err);
|
|
7860
7907
|
if (isTransientGitNetworkError(detail)) {
|
|
7861
7908
|
log.debug(TAG33, `Remote branch GC skipped — remote unreachable: ${detail}`);
|
|
7862
7909
|
return result;
|
|
@@ -7908,7 +7955,7 @@ function pruneFailedRemoteBranches(opts) {
|
|
|
7908
7955
|
});
|
|
7909
7956
|
result.removed.push(ref);
|
|
7910
7957
|
} catch (err) {
|
|
7911
|
-
const detail =
|
|
7958
|
+
const detail = gitErrorDetail2(err);
|
|
7912
7959
|
if (isTransientGitNetworkError(detail)) {
|
|
7913
7960
|
log.debug(TAG33, `Remote branch GC interrupted — remote unreachable: ${detail}`);
|
|
7914
7961
|
break;
|