@ai-development-environment/control-agent 0.0.138 → 0.0.139

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.
@@ -9314,7 +9314,7 @@ function worktreeGitInspectPayload(value) {
9314
9314
  `Unexpected worktree Git inspect payload field: ${unexpected}`
9315
9315
  );
9316
9316
  }
9317
- if (payload.action !== "STATE" && payload.action !== "STASH_DIFF") {
9317
+ if (payload.action !== "STATE" && payload.action !== "REFRESH" && payload.action !== "STASH_DIFF") {
9318
9318
  throw new Error("worktree Git inspect payload.action is invalid");
9319
9319
  }
9320
9320
  const common = {
@@ -9332,9 +9332,9 @@ function worktreeGitInspectPayload(value) {
9332
9332
  "worktree Git inspect payload.expectedOrigin"
9333
9333
  )
9334
9334
  };
9335
- if (payload.action === "STATE") {
9335
+ if (payload.action === "STATE" || payload.action === "REFRESH") {
9336
9336
  if (payload.stashOid !== void 0) {
9337
- throw new Error("STATE inspection cannot include stashOid");
9337
+ throw new Error(`${payload.action} inspection cannot include stashOid`);
9338
9338
  }
9339
9339
  return { action: payload.action, ...common };
9340
9340
  }
@@ -11565,7 +11565,7 @@ function tailscaleServeRemovePayload(value) {
11565
11565
  // package.json
11566
11566
  var package_default = {
11567
11567
  name: "@ai-development-environment/control-agent",
11568
- version: "0.0.138",
11568
+ version: "0.0.139",
11569
11569
  description: "Control agent for the AI Development Environment",
11570
11570
  license: "MIT",
11571
11571
  repository: {
@@ -45340,7 +45340,11 @@ var RepositoryCoordinator = class {
45340
45340
  run(key, task, signal2) {
45341
45341
  return this.enqueue(key, "exclusive", () => task(), signal2);
45342
45342
  }
45343
- /** Only read-only worktree inspection jobs may overlap reconciliation. */
45343
+ /** Keep source files stable during builds while allowing live inspections. */
45344
+ runBuild(key, task, signal2) {
45345
+ return this.enqueue(key, "build", () => task(), signal2);
45346
+ }
45347
+ /** Read-only worktree inspections may overlap builds and reconciliation. */
45344
45348
  runInspection(key, task, signal2) {
45345
45349
  return this.enqueue(key, "inspection", () => task(), signal2);
45346
45350
  }
@@ -45388,6 +45392,7 @@ var RepositoryCoordinator = class {
45388
45392
  inspections: 0,
45389
45393
  reconciliation: false,
45390
45394
  exclusive: false,
45395
+ build: false,
45391
45396
  exclusiveReconciliationPhase: null,
45392
45397
  pending: []
45393
45398
  };
@@ -45400,6 +45405,7 @@ var RepositoryCoordinator = class {
45400
45405
  if (kind === "inspection") repositoryQueue.inspections -= 1;
45401
45406
  else if (kind === "reconciliation")
45402
45407
  repositoryQueue.reconciliation = false;
45408
+ else if (kind === "build") repositoryQueue.build = false;
45403
45409
  else repositoryQueue.exclusive = false;
45404
45410
  this.drain(key, repositoryQueue);
45405
45411
  };
@@ -45446,18 +45452,31 @@ var RepositoryCoordinator = class {
45446
45452
  }
45447
45453
  return;
45448
45454
  }
45449
- while (!queue.exclusive && queue.pending.length) {
45455
+ while (!queue.exclusive && !queue.build && queue.pending.length) {
45450
45456
  const next = queue.pending[0];
45451
- if (next.kind === "exclusive" && (queue.inspections > 0 || queue.reconciliation) || next.kind === "reconciliation" && queue.reconciliation) {
45457
+ if (next.kind === "exclusive" && (queue.inspections > 0 || queue.reconciliation) || next.kind === "build" && queue.reconciliation || next.kind === "reconciliation" && queue.reconciliation) {
45452
45458
  return;
45453
45459
  }
45454
45460
  queue.pending.shift();
45455
45461
  if (next.kind === "inspection") queue.inspections += 1;
45456
45462
  else if (next.kind === "reconciliation") queue.reconciliation = true;
45463
+ else if (next.kind === "build") queue.build = true;
45457
45464
  else queue.exclusive = true;
45458
45465
  next.start();
45459
45466
  }
45460
- if (!queue.exclusive && !queue.reconciliation && queue.inspections === 0 && queue.pending.length === 0) {
45467
+ if (queue.build) {
45468
+ const inspections = queue.pending.filter(
45469
+ (operation) => operation.kind === "inspection"
45470
+ );
45471
+ queue.pending = queue.pending.filter(
45472
+ (operation) => operation.kind !== "inspection"
45473
+ );
45474
+ for (const inspection of inspections) {
45475
+ queue.inspections += 1;
45476
+ inspection.start();
45477
+ }
45478
+ }
45479
+ if (!queue.exclusive && !queue.build && !queue.reconciliation && queue.inspections === 0 && queue.pending.length === 0) {
45461
45480
  this.queues.delete(key);
45462
45481
  }
45463
45482
  }
@@ -52005,6 +52024,62 @@ async function rebaseInProgress(folder, timeoutMs, signal2) {
52005
52024
  }
52006
52025
  return false;
52007
52026
  }
52027
+ async function gitStatePathExists(folder, name, timeoutMs, signal2) {
52028
+ const result = requireSuccess4(
52029
+ await git4(
52030
+ folder,
52031
+ ["rev-parse", "--path-format=absolute", "--git-path", name],
52032
+ timeoutMs,
52033
+ signal2
52034
+ ),
52035
+ `Could not resolve Git state path ${name}`
52036
+ );
52037
+ const candidate = result.stdout.trim();
52038
+ if (!candidate || result.outputTruncated) {
52039
+ throw new Error(`Could not resolve Git state path ${name}`);
52040
+ }
52041
+ try {
52042
+ await stat11(candidate);
52043
+ return true;
52044
+ } catch (error) {
52045
+ if (error instanceof Error && "code" in error && error.code === "ENOENT") {
52046
+ return false;
52047
+ }
52048
+ throw error;
52049
+ }
52050
+ }
52051
+ async function inspectWorktreeRefreshState(folder, timeoutMs, signal2) {
52052
+ const [status2, rebaseMerge, rebaseApply, mergeInProgress] = await Promise.all(
52053
+ [
52054
+ git4(
52055
+ folder,
52056
+ [
52057
+ "--no-optional-locks",
52058
+ "status",
52059
+ "--porcelain=v1",
52060
+ "-z",
52061
+ "--untracked-files=all",
52062
+ "--ignore-submodules=none"
52063
+ ],
52064
+ timeoutMs,
52065
+ signal2
52066
+ ),
52067
+ gitStatePathExists(folder, "rebase-merge", timeoutMs, signal2),
52068
+ gitStatePathExists(folder, "rebase-apply", timeoutMs, signal2),
52069
+ gitStatePathExists(folder, "MERGE_HEAD", timeoutMs, signal2)
52070
+ ]
52071
+ );
52072
+ requireSuccess4(status2, "Could not refresh worktree Git status");
52073
+ if (status2.outputTruncated) {
52074
+ throw new Error("Worktree Git status exceeded the output limit");
52075
+ }
52076
+ return {
52077
+ dirty: Boolean(status2.stdout),
52078
+ hasConflicts: statusChangeState(status2.stdout).hasConflicts,
52079
+ rebaseInProgress: rebaseMerge || rebaseApply,
52080
+ mergeInProgress
52081
+ };
52082
+ }
52008
52083
  async function rebaseBranch(folder, timeoutMs, signal2) {
52009
52084
  for (const name of ["rebase-merge/head-name", "rebase-apply/head-name"]) {
52010
52085
  const pathResult = await git4(
@@ -53145,10 +53220,10 @@ var inspectWorktree = async (payload, timeoutMs, signal2) => {
53145
53220
  var inspectWorktreeGit = async (payload, timeoutMs, signal2) => {
53146
53221
  const input = worktreeGitInspectPayload(payload);
53147
53222
  const folder = await validateWorktree2(input, timeoutMs, signal2);
53148
- if (input.action === "STATE") {
53223
+ if (input.action !== "STASH_DIFF") {
53149
53224
  return {
53150
53225
  ...successfulProcess9,
53151
- state: await inspectCodebaseGitState(folder, timeoutMs, signal2)
53226
+ state: input.action === "REFRESH" ? await inspectWorktreeRefreshState(folder, timeoutMs, signal2) : await inspectCodebaseGitState(folder, timeoutMs, signal2)
53152
53227
  };
53153
53228
  }
53154
53229
  return {
@@ -55345,7 +55420,13 @@ var JobExecutor = class {
55345
55420
  };
55346
55421
  const codebaseId = claimed.payload && typeof claimed.payload === "object" && !Array.isArray(claimed.payload) && typeof claimed.payload.codebaseId === "string" ? String(claimed.payload.codebaseId) : null;
55347
55422
  if (!codebaseId) result = await runHandler();
55348
- else if (claimed.kind === WORKTREE_INSPECT_JOB_KIND || claimed.kind === WORKTREE_DIFF_JOB_KIND || claimed.kind === WORKTREE_DIFF_ASSET_JOB_KIND || claimed.kind === WORKTREE_GIT_INSPECT_JOB_KIND || claimed.kind === CODEBASE_GIT_INSPECT_JOB_KIND) {
55423
+ else if (claimed.kind === IOS_BUILD_JOB_KIND) {
55424
+ result = await this.repositoryCoordinator.runBuild(
55425
+ codebaseId,
55426
+ runHandler,
55427
+ controller.signal
55428
+ );
55429
+ } else if (claimed.kind === WORKTREE_INSPECT_JOB_KIND || claimed.kind === WORKTREE_DIFF_JOB_KIND || claimed.kind === WORKTREE_DIFF_ASSET_JOB_KIND || claimed.kind === WORKTREE_GIT_INSPECT_JOB_KIND || claimed.kind === CODEBASE_GIT_INSPECT_JOB_KIND) {
55349
55430
  result = await this.repositoryCoordinator.runInspection(
55350
55431
  codebaseId,
55351
55432
  runHandler,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-development-environment/control-agent",
3
- "version": "0.0.138",
3
+ "version": "0.0.139",
4
4
  "description": "Control agent for the AI Development Environment",
5
5
  "license": "MIT",
6
6
  "repository": {