@ai-development-environment/control-agent 0.0.57 → 0.0.58

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.
@@ -6026,6 +6026,7 @@ function codebaseGitOperationPayload(value) {
6026
6026
  // ../agent-contract/src/worktrees.ts
6027
6027
  var WORKTREE_INSPECT_JOB_KIND = "worktree.inspect";
6028
6028
  var WORKTREE_OPERATION_JOB_KIND = "worktree.operation";
6029
+ var WORKTREE_AUTO_SYNC_JOB_KIND = "worktree.auto-sync";
6029
6030
  var WORKTREE_GIT_INSPECT_JOB_KIND = "worktree.git.inspect";
6030
6031
  var WORKTREE_GIT_OPERATION_JOB_KIND = "worktree.git.operation";
6031
6032
  var WORKTREE_WATCH_JOB_KIND = "worktree.watch";
@@ -6038,6 +6039,7 @@ var WORKTREE_DIFF_ASSET_JOB_KIND = "worktree.diff.asset";
6038
6039
  var WORKTREE_JOB_KINDS = [
6039
6040
  WORKTREE_INSPECT_JOB_KIND,
6040
6041
  WORKTREE_OPERATION_JOB_KIND,
6042
+ WORKTREE_AUTO_SYNC_JOB_KIND,
6041
6043
  WORKTREE_GIT_INSPECT_JOB_KIND,
6042
6044
  WORKTREE_GIT_OPERATION_JOB_KIND,
6043
6045
  WORKTREE_WATCH_JOB_KIND,
@@ -6422,6 +6424,51 @@ function worktreeJobPayload(value) {
6422
6424
  ...editorVariant === void 0 ? {} : { editorVariant }
6423
6425
  };
6424
6426
  }
6427
+ function worktreeAutoSyncJobPayload(value) {
6428
+ const payload = objectValue4(value, "worktree auto sync payload");
6429
+ const allowed = /* @__PURE__ */ new Set([
6430
+ "codebaseId",
6431
+ "folder",
6432
+ "gitDirectory",
6433
+ "expectedOrigin",
6434
+ "expectedBranch",
6435
+ "baseBranch",
6436
+ "phase"
6437
+ ]);
6438
+ const unexpected = Object.keys(payload).find((key) => !allowed.has(key));
6439
+ if (unexpected) {
6440
+ throw new Error(
6441
+ `Unexpected worktree auto sync payload field: ${unexpected}`
6442
+ );
6443
+ }
6444
+ if (payload.phase !== "SYNC" && payload.phase !== "FINALIZE") {
6445
+ throw new Error("worktree auto sync payload.phase is invalid");
6446
+ }
6447
+ return {
6448
+ codebaseId: stringValue4(
6449
+ payload.codebaseId,
6450
+ "worktree auto sync payload.codebaseId"
6451
+ ),
6452
+ folder: stringValue4(payload.folder, "worktree auto sync payload.folder"),
6453
+ gitDirectory: stringValue4(
6454
+ payload.gitDirectory,
6455
+ "worktree auto sync payload.gitDirectory"
6456
+ ),
6457
+ expectedOrigin: stringValue4(
6458
+ payload.expectedOrigin,
6459
+ "worktree auto sync payload.expectedOrigin"
6460
+ ),
6461
+ expectedBranch: stringValue4(
6462
+ payload.expectedBranch,
6463
+ "worktree auto sync payload.expectedBranch"
6464
+ ),
6465
+ baseBranch: stringValue4(
6466
+ payload.baseBranch,
6467
+ "worktree auto sync payload.baseBranch"
6468
+ ),
6469
+ phase: payload.phase
6470
+ };
6471
+ }
6425
6472
  function worktreeGitInspectPayload(value) {
6426
6473
  const payload = objectValue4(value, "worktree Git inspect payload");
6427
6474
  const allowed = /* @__PURE__ */ new Set([
@@ -15838,6 +15885,230 @@ var operateWorktree = async (payload, timeoutMs, signal) => {
15838
15885
  )
15839
15886
  };
15840
15887
  };
15888
+ var autoSyncWorktree = async (payload, timeoutMs, signal) => {
15889
+ const input = worktreeAutoSyncJobPayload(payload);
15890
+ const folder = await validateWorktree2(input, timeoutMs, signal);
15891
+ const runGit = async (args, fallback) => requireSuccess3(await git3(folder, args, timeoutMs, signal), fallback);
15892
+ const branchResult = await git3(
15893
+ folder,
15894
+ ["symbolic-ref", "--short", "-q", "HEAD"],
15895
+ timeoutMs,
15896
+ signal
15897
+ );
15898
+ const symbolicBranch = branchResult.exitCode === 0 ? branchResult.stdout.trim() : null;
15899
+ const branch = symbolicBranch ?? (input.phase === "FINALIZE" ? await rebaseBranch(folder, timeoutMs, signal) : null);
15900
+ if (branch !== input.expectedBranch) {
15901
+ throw new Error(
15902
+ `Auto Sync expected branch ${input.expectedBranch}, but found ${branch ?? "detached HEAD"}`
15903
+ );
15904
+ }
15905
+ const upstreamResult = branch ? await git3(
15906
+ folder,
15907
+ ["rev-parse", "--abbrev-ref", "@{upstream}"],
15908
+ timeoutMs,
15909
+ signal
15910
+ ) : null;
15911
+ const upstream = upstreamResult?.exitCode === 0 ? upstreamResult.stdout.trim() : null;
15912
+ if (input.phase === "SYNC" && (!branch || !upstream)) {
15913
+ throw new Error("Auto Sync requires a branch with an upstream");
15914
+ }
15915
+ if (input.phase === "FINALIZE") {
15916
+ let status3 = await runGit(
15917
+ ["status", "--porcelain=v1", "-z"],
15918
+ "Could not inspect worktree changes"
15919
+ );
15920
+ let changes = statusChangeState(status3.stdout);
15921
+ const continuingRebase = await rebaseInProgress(folder, timeoutMs, signal);
15922
+ if (changes.hasConflicts && !continuingRebase) {
15923
+ return {
15924
+ ...successfulProcess7,
15925
+ outcome: "UNRESOLVED",
15926
+ worktree: await inspectWorktreeItem(
15927
+ folder,
15928
+ folder,
15929
+ input.baseBranch,
15930
+ false,
15931
+ Math.min(timeoutMs, 3e4),
15932
+ signal
15933
+ )
15934
+ };
15935
+ }
15936
+ if (continuingRebase) {
15937
+ await runGit(["add", "--all"], "Could not stage resolved conflicts");
15938
+ const continued = await command2(
15939
+ "git",
15940
+ ["-C", folder, "rebase", "--continue"],
15941
+ timeoutMs,
15942
+ signal,
15943
+ {
15944
+ ...process.env,
15945
+ GIT_EDITOR: "true",
15946
+ GIT_TERMINAL_PROMPT: "0",
15947
+ GIT_OPTIONAL_LOCKS: "0"
15948
+ }
15949
+ );
15950
+ if (continued.exitCode !== 0) {
15951
+ return {
15952
+ ...successfulProcess7,
15953
+ outcome: "UNRESOLVED",
15954
+ worktree: await inspectWorktreeItem(
15955
+ folder,
15956
+ folder,
15957
+ input.baseBranch,
15958
+ false,
15959
+ Math.min(timeoutMs, 3e4),
15960
+ signal
15961
+ )
15962
+ };
15963
+ }
15964
+ status3 = await runGit(
15965
+ ["status", "--porcelain=v1", "-z"],
15966
+ "Could not inspect resolved worktree changes"
15967
+ );
15968
+ changes = statusChangeState(status3.stdout);
15969
+ }
15970
+ if (changes.hasConflicts || changes.hasStagedChanges || changes.hasUnstagedChanges || await rebaseInProgress(folder, timeoutMs, signal)) {
15971
+ return {
15972
+ ...successfulProcess7,
15973
+ outcome: "UNRESOLVED",
15974
+ worktree: await inspectWorktreeItem(
15975
+ folder,
15976
+ folder,
15977
+ input.baseBranch,
15978
+ false,
15979
+ Math.min(timeoutMs, 3e4),
15980
+ signal
15981
+ )
15982
+ };
15983
+ }
15984
+ const finalBranch = await git3(
15985
+ folder,
15986
+ ["symbolic-ref", "--short", "-q", "HEAD"],
15987
+ timeoutMs,
15988
+ signal
15989
+ );
15990
+ const finalUpstream = finalBranch.exitCode === 0 ? await git3(
15991
+ folder,
15992
+ ["rev-parse", "--abbrev-ref", "@{upstream}"],
15993
+ timeoutMs,
15994
+ signal
15995
+ ) : null;
15996
+ if (finalBranch.exitCode !== 0 || finalBranch.stdout.trim() !== input.expectedBranch || finalUpstream?.exitCode !== 0 || !finalUpstream.stdout.trim()) {
15997
+ throw new Error(
15998
+ `Auto Sync expected branch ${input.expectedBranch} with an upstream`
15999
+ );
16000
+ }
16001
+ await runGit(["push", "--force-with-lease"], "Auto Sync push failed");
16002
+ return {
16003
+ ...successfulProcess7,
16004
+ outcome: "SYNCED",
16005
+ worktree: await inspectWorktreeItem(
16006
+ folder,
16007
+ folder,
16008
+ input.baseBranch,
16009
+ false,
16010
+ Math.min(timeoutMs, 3e4),
16011
+ signal
16012
+ )
16013
+ };
16014
+ }
16015
+ const status2 = await runGit(
16016
+ ["status", "--porcelain"],
16017
+ "Could not inspect worktree changes"
16018
+ );
16019
+ if (status2.stdout.trim()) {
16020
+ throw new Error("Stash or commit changes before Auto Sync can continue");
16021
+ }
16022
+ await runGit(["fetch", "origin"], "Could not fetch origin");
16023
+ const remoteBase = `refs/remotes/origin/${input.baseBranch}`;
16024
+ const isCurrent = await git3(
16025
+ folder,
16026
+ ["merge-base", "--is-ancestor", remoteBase, "HEAD"],
16027
+ timeoutMs,
16028
+ signal
16029
+ );
16030
+ if (isCurrent.exitCode === 0) {
16031
+ const upstreamContainsHead = await git3(
16032
+ folder,
16033
+ ["merge-base", "--is-ancestor", "HEAD", "@{upstream}"],
16034
+ timeoutMs,
16035
+ signal
16036
+ );
16037
+ if (upstreamContainsHead.exitCode !== 0 && upstreamContainsHead.exitCode !== 1) {
16038
+ throw new Error(
16039
+ cleanError3(
16040
+ upstreamContainsHead.stderr || "Could not compare the upstream branch"
16041
+ )
16042
+ );
16043
+ }
16044
+ if (upstreamContainsHead.exitCode !== 0) {
16045
+ await runGit(["push", "--force-with-lease"], "Auto Sync push failed");
16046
+ return {
16047
+ ...successfulProcess7,
16048
+ outcome: "SYNCED",
16049
+ worktree: await inspectWorktreeItem(
16050
+ folder,
16051
+ folder,
16052
+ input.baseBranch,
16053
+ false,
16054
+ Math.min(timeoutMs, 3e4),
16055
+ signal
16056
+ )
16057
+ };
16058
+ }
16059
+ return {
16060
+ ...successfulProcess7,
16061
+ outcome: "NO_CHANGE",
16062
+ worktree: await inspectWorktreeItem(
16063
+ folder,
16064
+ folder,
16065
+ input.baseBranch,
16066
+ false,
16067
+ Math.min(timeoutMs, 3e4),
16068
+ signal
16069
+ )
16070
+ };
16071
+ }
16072
+ const rebase = await git3(folder, ["rebase", remoteBase], timeoutMs, signal);
16073
+ if (rebase.exitCode !== 0) {
16074
+ const conflictStatus = await git3(
16075
+ folder,
16076
+ ["status", "--porcelain=v1", "-z"],
16077
+ timeoutMs,
16078
+ signal
16079
+ );
16080
+ const conflicts = conflictStatus.exitCode === 0 && statusChangeState(conflictStatus.stdout).hasConflicts;
16081
+ if (conflicts && await rebaseInProgress(folder, timeoutMs, signal)) {
16082
+ return {
16083
+ ...successfulProcess7,
16084
+ outcome: "CONFLICT",
16085
+ worktree: await inspectWorktreeItem(
16086
+ folder,
16087
+ folder,
16088
+ input.baseBranch,
16089
+ false,
16090
+ Math.min(timeoutMs, 3e4),
16091
+ signal
16092
+ )
16093
+ };
16094
+ }
16095
+ await git3(folder, ["rebase", "--abort"], timeoutMs, signal);
16096
+ throw new Error(cleanError3(rebase.stderr || "Auto Sync rebase failed"));
16097
+ }
16098
+ await runGit(["push", "--force-with-lease"], "Auto Sync push failed");
16099
+ return {
16100
+ ...successfulProcess7,
16101
+ outcome: "SYNCED",
16102
+ worktree: await inspectWorktreeItem(
16103
+ folder,
16104
+ folder,
16105
+ input.baseBranch,
16106
+ false,
16107
+ Math.min(timeoutMs, 3e4),
16108
+ signal
16109
+ )
16110
+ };
16111
+ };
15841
16112
 
15842
16113
  // src/handlers/index.ts
15843
16114
  var handlers = {
@@ -15853,6 +16124,7 @@ var handlers = {
15853
16124
  [CODEBASE_GIT_INSPECT_JOB_KIND]: inspectCodebaseGit,
15854
16125
  [CODEBASE_GIT_OPERATION_JOB_KIND]: operateCodebaseGit,
15855
16126
  [WORKTREE_INSPECT_JOB_KIND]: inspectWorktree,
16127
+ [WORKTREE_AUTO_SYNC_JOB_KIND]: autoSyncWorktree,
15856
16128
  [WORKTREE_BRANCH_JOB_KIND]: branchWorktree,
15857
16129
  [WORKTREE_MOVE_PUSH_JOB_KIND]: pushMovedWorktree,
15858
16130
  [WORKTREE_MOVE_CHECKOUT_JOB_KIND]: checkoutMovedWorktree,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-development-environment/control-agent",
3
- "version": "0.0.57",
3
+ "version": "0.0.58",
4
4
  "description": "Control agent for the AI Development Environment",
5
5
  "license": "MIT",
6
6
  "repository": {