@ai-development-environment/control-agent 0.0.52 → 0.0.53
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/control-agent.js +149 -34
- package/package.json +1 -1
package/dist/control-agent.js
CHANGED
|
@@ -5980,6 +5980,8 @@ var WORKTREE_OPERATIONS = [
|
|
|
5980
5980
|
"OPEN_EDITOR",
|
|
5981
5981
|
"FORCE_PUSH",
|
|
5982
5982
|
"SYNC",
|
|
5983
|
+
"REBASE",
|
|
5984
|
+
"CANCEL_REBASE",
|
|
5983
5985
|
"PUSH",
|
|
5984
5986
|
"RESET",
|
|
5985
5987
|
"STASH_ALL",
|
|
@@ -13422,7 +13424,7 @@ var runWorkflowGitCheckpoint = async (payloadValue, _timeoutMs, signal) => {
|
|
|
13422
13424
|
import { createWriteStream as createWriteStream2, watch } from "node:fs";
|
|
13423
13425
|
import { mkdtemp as mkdtemp5, open as open2, readFile as readFile7, realpath as realpath6, rm as rm8, stat as stat8 } from "node:fs/promises";
|
|
13424
13426
|
import { tmpdir as tmpdir5 } from "node:os";
|
|
13425
|
-
import { basename as basename4, dirname as dirname6, join as join10, relative as relative5 } from "node:path";
|
|
13427
|
+
import { basename as basename4, dirname as dirname6, isAbsolute as isAbsolute5, join as join10, relative as relative5 } from "node:path";
|
|
13426
13428
|
import { spawn as spawn5 } from "node:child_process";
|
|
13427
13429
|
var successfulProcess7 = {
|
|
13428
13430
|
exitCode: 0,
|
|
@@ -13446,9 +13448,13 @@ function statusChangeState(value) {
|
|
|
13446
13448
|
const entries = value.split("\0").filter(Boolean);
|
|
13447
13449
|
let hasStagedChanges = false;
|
|
13448
13450
|
let hasUnstagedChanges = false;
|
|
13451
|
+
let hasConflicts = false;
|
|
13449
13452
|
for (let index = 0; index < entries.length; index += 1) {
|
|
13450
13453
|
const code = entries[index].slice(0, 2);
|
|
13451
13454
|
const untracked = code === "??";
|
|
13455
|
+
if (["DD", "AU", "UD", "UA", "DU", "AA", "UU"].includes(code)) {
|
|
13456
|
+
hasConflicts = true;
|
|
13457
|
+
}
|
|
13452
13458
|
if (!untracked && code[0] !== " " && code[0] !== "?" && code[0] !== "!") {
|
|
13453
13459
|
hasStagedChanges = true;
|
|
13454
13460
|
}
|
|
@@ -13459,7 +13465,50 @@ function statusChangeState(value) {
|
|
|
13459
13465
|
index += 1;
|
|
13460
13466
|
}
|
|
13461
13467
|
}
|
|
13462
|
-
return { hasStagedChanges, hasUnstagedChanges };
|
|
13468
|
+
return { hasStagedChanges, hasUnstagedChanges, hasConflicts };
|
|
13469
|
+
}
|
|
13470
|
+
async function rebaseInProgress(folder, timeoutMs, signal) {
|
|
13471
|
+
for (const name of ["rebase-merge", "rebase-apply"]) {
|
|
13472
|
+
const pathResult = await git3(
|
|
13473
|
+
folder,
|
|
13474
|
+
["rev-parse", "--git-path", name],
|
|
13475
|
+
timeoutMs,
|
|
13476
|
+
signal
|
|
13477
|
+
);
|
|
13478
|
+
if (pathResult.exitCode !== 0) continue;
|
|
13479
|
+
const candidate = pathResult.stdout.trim();
|
|
13480
|
+
if (!candidate) continue;
|
|
13481
|
+
try {
|
|
13482
|
+
await stat8(isAbsolute5(candidate) ? candidate : join10(folder, candidate));
|
|
13483
|
+
return true;
|
|
13484
|
+
} catch {
|
|
13485
|
+
}
|
|
13486
|
+
}
|
|
13487
|
+
return false;
|
|
13488
|
+
}
|
|
13489
|
+
async function rebaseBranch(folder, timeoutMs, signal) {
|
|
13490
|
+
for (const name of ["rebase-merge/head-name", "rebase-apply/head-name"]) {
|
|
13491
|
+
const pathResult = await git3(
|
|
13492
|
+
folder,
|
|
13493
|
+
["rev-parse", "--git-path", name],
|
|
13494
|
+
timeoutMs,
|
|
13495
|
+
signal
|
|
13496
|
+
);
|
|
13497
|
+
if (pathResult.exitCode !== 0) continue;
|
|
13498
|
+
const candidate = pathResult.stdout.trim();
|
|
13499
|
+
if (!candidate) continue;
|
|
13500
|
+
try {
|
|
13501
|
+
const headName = (await readFile7(
|
|
13502
|
+
isAbsolute5(candidate) ? candidate : join10(folder, candidate),
|
|
13503
|
+
"utf8"
|
|
13504
|
+
)).trim();
|
|
13505
|
+
if (headName.startsWith("refs/heads/")) {
|
|
13506
|
+
return headName.slice("refs/heads/".length);
|
|
13507
|
+
}
|
|
13508
|
+
} catch {
|
|
13509
|
+
}
|
|
13510
|
+
}
|
|
13511
|
+
return null;
|
|
13463
13512
|
}
|
|
13464
13513
|
function closeWorktreeWatch(entry) {
|
|
13465
13514
|
if (entry.timer) clearTimeout(entry.timer);
|
|
@@ -13483,39 +13532,44 @@ async function flushWorktreeActivity(entry) {
|
|
|
13483
13532
|
entry.pending = false;
|
|
13484
13533
|
try {
|
|
13485
13534
|
const signal = new AbortController().signal;
|
|
13486
|
-
const [status2, branchResult, headResult, codeStateHash] = await Promise.all(
|
|
13487
|
-
|
|
13488
|
-
|
|
13489
|
-
|
|
13490
|
-
|
|
13491
|
-
|
|
13492
|
-
|
|
13493
|
-
|
|
13494
|
-
|
|
13495
|
-
|
|
13496
|
-
|
|
13497
|
-
|
|
13498
|
-
|
|
13499
|
-
|
|
13500
|
-
|
|
13501
|
-
|
|
13502
|
-
|
|
13503
|
-
|
|
13504
|
-
|
|
13505
|
-
|
|
13506
|
-
|
|
13507
|
-
|
|
13508
|
-
|
|
13509
|
-
);
|
|
13510
|
-
const branch =
|
|
13535
|
+
const [status2, branchResult, headResult, codeStateHash, rebasing] = await Promise.all([
|
|
13536
|
+
git3(
|
|
13537
|
+
entry.folder,
|
|
13538
|
+
[
|
|
13539
|
+
"--no-optional-locks",
|
|
13540
|
+
"status",
|
|
13541
|
+
"--porcelain=v1",
|
|
13542
|
+
"-z",
|
|
13543
|
+
"--untracked-files=all"
|
|
13544
|
+
],
|
|
13545
|
+
entry.timeoutMs,
|
|
13546
|
+
signal
|
|
13547
|
+
),
|
|
13548
|
+
git3(
|
|
13549
|
+
entry.folder,
|
|
13550
|
+
["symbolic-ref", "--short", "-q", "HEAD"],
|
|
13551
|
+
entry.timeoutMs,
|
|
13552
|
+
signal
|
|
13553
|
+
),
|
|
13554
|
+
git3(entry.folder, ["rev-parse", "HEAD"], entry.timeoutMs, signal),
|
|
13555
|
+
worktreeCodeStateHash(entry.folder, entry.timeoutMs, signal),
|
|
13556
|
+
rebaseInProgress(entry.folder, entry.timeoutMs, signal)
|
|
13557
|
+
]);
|
|
13558
|
+
const symbolicBranch = branchResult.exitCode === 0 ? branchResult.stdout.trim() : null;
|
|
13559
|
+
const branch = symbolicBranch ?? (rebasing ? await rebaseBranch(entry.folder, entry.timeoutMs, signal) : null);
|
|
13511
13560
|
const headSha = headResult.exitCode === 0 ? headResult.stdout.trim() : null;
|
|
13512
13561
|
const headIdentity = headSha ? `${branch ?? ""}\0${headSha}` : null;
|
|
13513
|
-
const changes = status2.exitCode === 0 ? statusChangeState(status2.stdout) : {
|
|
13562
|
+
const changes = status2.exitCode === 0 ? statusChangeState(status2.stdout) : {
|
|
13563
|
+
hasStagedChanges: false,
|
|
13564
|
+
hasUnstagedChanges: false,
|
|
13565
|
+
hasConflicts: false
|
|
13566
|
+
};
|
|
13514
13567
|
const report = {
|
|
13515
13568
|
codebaseId: entry.codebaseId,
|
|
13516
13569
|
gitDirectory: entry.gitDirectory,
|
|
13517
13570
|
codeStateHash,
|
|
13518
13571
|
...changes,
|
|
13572
|
+
rebaseInProgress: rebasing,
|
|
13519
13573
|
pushStatus: await worktreePushStatus(
|
|
13520
13574
|
entry.folder,
|
|
13521
13575
|
branch,
|
|
@@ -13686,9 +13740,14 @@ async function inspectWorktreeItem(folderValue2, rootFolder, baseBranch, primary
|
|
|
13686
13740
|
const checkedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
13687
13741
|
try {
|
|
13688
13742
|
const folder = await realpath6(folderValue2);
|
|
13689
|
-
const [gitDir, branchResult, headResult, statusResult] = await Promise.all([
|
|
13743
|
+
const [gitDir, branchResult, headResult, statusResult, rebasing] = await Promise.all([
|
|
13690
13744
|
gitDirectory(folder, timeoutMs, signal),
|
|
13691
|
-
git3(
|
|
13745
|
+
git3(
|
|
13746
|
+
folder,
|
|
13747
|
+
["symbolic-ref", "--short", "-q", "HEAD"],
|
|
13748
|
+
timeoutMs,
|
|
13749
|
+
signal
|
|
13750
|
+
),
|
|
13692
13751
|
git3(folder, ["rev-parse", "HEAD"], timeoutMs, signal),
|
|
13693
13752
|
git3(
|
|
13694
13753
|
folder,
|
|
@@ -13701,9 +13760,11 @@ async function inspectWorktreeItem(folderValue2, rootFolder, baseBranch, primary
|
|
|
13701
13760
|
],
|
|
13702
13761
|
timeoutMs,
|
|
13703
13762
|
signal
|
|
13704
|
-
)
|
|
13763
|
+
),
|
|
13764
|
+
rebaseInProgress(folder, timeoutMs, signal)
|
|
13705
13765
|
]);
|
|
13706
|
-
const
|
|
13766
|
+
const symbolicBranch = branchResult.exitCode === 0 ? branchResult.stdout.trim() : null;
|
|
13767
|
+
const branch = symbolicBranch ?? (rebasing ? await rebaseBranch(folder, timeoutMs, signal) : null);
|
|
13707
13768
|
const upstreamResult = branch ? await git3(
|
|
13708
13769
|
folder,
|
|
13709
13770
|
["rev-parse", "--abbrev-ref", "--symbolic-full-name", "@{upstream}"],
|
|
@@ -13719,7 +13780,11 @@ async function inspectWorktreeItem(folderValue2, rootFolder, baseBranch, primary
|
|
|
13719
13780
|
signal
|
|
13720
13781
|
) : { ahead: null, behind: null };
|
|
13721
13782
|
const syncState = worktreeSyncState(branch, upstream, upstreamCounts);
|
|
13722
|
-
const changes = statusResult.exitCode === 0 ? statusChangeState(statusResult.stdout) : {
|
|
13783
|
+
const changes = statusResult.exitCode === 0 ? statusChangeState(statusResult.stdout) : {
|
|
13784
|
+
hasStagedChanges: false,
|
|
13785
|
+
hasUnstagedChanges: false,
|
|
13786
|
+
hasConflicts: false
|
|
13787
|
+
};
|
|
13723
13788
|
return {
|
|
13724
13789
|
gitDirectory: gitDir,
|
|
13725
13790
|
folder,
|
|
@@ -13735,6 +13800,7 @@ async function inspectWorktreeItem(folderValue2, rootFolder, baseBranch, primary
|
|
|
13735
13800
|
baseAhead: baseCounts.ahead,
|
|
13736
13801
|
baseBehind: baseCounts.behind,
|
|
13737
13802
|
...changes,
|
|
13803
|
+
rebaseInProgress: rebasing,
|
|
13738
13804
|
pushStatus: await worktreePushStatus(
|
|
13739
13805
|
folder,
|
|
13740
13806
|
branch,
|
|
@@ -13763,6 +13829,8 @@ async function inspectWorktreeItem(folderValue2, rootFolder, baseBranch, primary
|
|
|
13763
13829
|
baseBehind: null,
|
|
13764
13830
|
hasStagedChanges: false,
|
|
13765
13831
|
hasUnstagedChanges: false,
|
|
13832
|
+
rebaseInProgress: false,
|
|
13833
|
+
hasConflicts: false,
|
|
13766
13834
|
pushStatus: "UNKNOWN",
|
|
13767
13835
|
availability: "ERROR",
|
|
13768
13836
|
error: cleanError3(error),
|
|
@@ -15239,12 +15307,59 @@ var operateWorktree = async (payload, timeoutMs, signal) => {
|
|
|
15239
15307
|
signal
|
|
15240
15308
|
);
|
|
15241
15309
|
if (rebase.exitCode !== 0) {
|
|
15242
|
-
await git3(
|
|
15310
|
+
const status2 = await git3(
|
|
15311
|
+
folder,
|
|
15312
|
+
["status", "--porcelain=v1", "-z"],
|
|
15313
|
+
timeoutMs,
|
|
15314
|
+
signal
|
|
15315
|
+
);
|
|
15316
|
+
const conflicts = status2.exitCode === 0 && statusChangeState(status2.stdout).hasConflicts;
|
|
15317
|
+
if (!(conflicts && await rebaseInProgress(folder, timeoutMs, signal))) {
|
|
15318
|
+
await git3(folder, ["rebase", "--abort"], timeoutMs, signal);
|
|
15319
|
+
}
|
|
15243
15320
|
throw new Error(cleanError3(rebase.stderr || "Rebase failed"));
|
|
15244
15321
|
}
|
|
15245
15322
|
await runGit(["push", "--force-with-lease"], "Sync push failed");
|
|
15246
15323
|
break;
|
|
15247
15324
|
}
|
|
15325
|
+
case "REBASE": {
|
|
15326
|
+
if (!branch) throw new Error("Rebase requires a branch");
|
|
15327
|
+
if (!input.baseBranch) throw new Error("Rebase requires a base branch");
|
|
15328
|
+
const statusResult = await runGit(
|
|
15329
|
+
["status", "--porcelain"],
|
|
15330
|
+
"Could not inspect worktree changes"
|
|
15331
|
+
);
|
|
15332
|
+
if (statusResult.stdout.trim())
|
|
15333
|
+
throw new Error("Stash or commit changes before rebasing");
|
|
15334
|
+
await runGit(["fetch", "origin"], "Could not fetch origin");
|
|
15335
|
+
const rebase = await git3(
|
|
15336
|
+
folder,
|
|
15337
|
+
["rebase", `refs/remotes/origin/${input.baseBranch}`],
|
|
15338
|
+
timeoutMs,
|
|
15339
|
+
signal
|
|
15340
|
+
);
|
|
15341
|
+
if (rebase.exitCode !== 0) {
|
|
15342
|
+
const status2 = await git3(
|
|
15343
|
+
folder,
|
|
15344
|
+
["status", "--porcelain=v1", "-z"],
|
|
15345
|
+
timeoutMs,
|
|
15346
|
+
signal
|
|
15347
|
+
);
|
|
15348
|
+
const conflicts = status2.exitCode === 0 && statusChangeState(status2.stdout).hasConflicts;
|
|
15349
|
+
if (!(conflicts && await rebaseInProgress(folder, timeoutMs, signal))) {
|
|
15350
|
+
await git3(folder, ["rebase", "--abort"], timeoutMs, signal);
|
|
15351
|
+
}
|
|
15352
|
+
throw new Error(cleanError3(rebase.stderr || "Rebase failed"));
|
|
15353
|
+
}
|
|
15354
|
+
break;
|
|
15355
|
+
}
|
|
15356
|
+
case "CANCEL_REBASE": {
|
|
15357
|
+
if (!await rebaseInProgress(folder, timeoutMs, signal)) {
|
|
15358
|
+
throw new Error("No rebase is in progress");
|
|
15359
|
+
}
|
|
15360
|
+
await runGit(["rebase", "--abort"], "Could not cancel rebase");
|
|
15361
|
+
break;
|
|
15362
|
+
}
|
|
15248
15363
|
case "PUSH":
|
|
15249
15364
|
if (!branch) throw new Error("Push requires a branch");
|
|
15250
15365
|
await runGit(
|