@ai-development-environment/control-agent 0.0.52 → 0.0.54

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.
@@ -4182,7 +4182,7 @@ var require_cross_spawn = __commonJS({
4182
4182
  var cp3 = __require("child_process");
4183
4183
  var parse2 = require_parse();
4184
4184
  var enoent = require_enoent();
4185
- function spawn7(command3, args, options) {
4185
+ function spawn8(command3, args, options) {
4186
4186
  const parsed = parse2(command3, args, options);
4187
4187
  const spawned = cp3.spawn(parsed.command, parsed.args, parsed.options);
4188
4188
  enoent.hookChildProcess(spawned, parsed);
@@ -4194,18 +4194,14 @@ var require_cross_spawn = __commonJS({
4194
4194
  result.error = result.error || enoent.verifyENOENTSync(result.status, parsed);
4195
4195
  return result;
4196
4196
  }
4197
- module.exports = spawn7;
4198
- module.exports.spawn = spawn7;
4197
+ module.exports = spawn8;
4198
+ module.exports.spawn = spawn8;
4199
4199
  module.exports.sync = spawnSync2;
4200
4200
  module.exports._parse = parse2;
4201
4201
  module.exports._enoent = enoent;
4202
4202
  }
4203
4203
  });
4204
4204
 
4205
- // src/index.ts
4206
- import { execFile as execFile5 } from "node:child_process";
4207
- import { promisify as promisify5 } from "node:util";
4208
-
4209
4205
  // src/config.ts
4210
4206
  import { chmod, mkdir, readFile, rename, writeFile } from "node:fs/promises";
4211
4207
  import { homedir } from "node:os";
@@ -4252,8 +4248,6 @@ async function saveConfig(config, path = configPath()) {
4252
4248
  }
4253
4249
 
4254
4250
  // ../agent-contract/src/index.ts
4255
- var TUNNEL_NAME_PATTERN = "[A-Za-z0-9][A-Za-z0-9_-]{0,127}";
4256
- var TUNNEL_NAME_REGEX = new RegExp(`^${TUNNEL_NAME_PATTERN}$`);
4257
4251
  var CCUSAGE_REPORT_JOB_KIND = "ccusage.report";
4258
4252
  var DEFAULT_AGENT_HEARTBEAT_INTERVAL_SECONDS = 15;
4259
4253
  var MIN_AGENT_HEARTBEAT_INTERVAL_SECONDS = 5;
@@ -5180,7 +5174,7 @@ var AgentGraphQLClient = class {
5180
5174
  { agentId }
5181
5175
  );
5182
5176
  return data.agentJobs.filter(
5183
- (job) => job.status === "QUEUED" || job.status === "RUNNING" || job.status === "CANCELLED"
5177
+ (job) => job.status === "QUEUED" || job.status === "RUNNING" || job.status === "CANCELLING" || job.status === "CANCELLED"
5184
5178
  );
5185
5179
  }
5186
5180
  async cadenceSettings(agentId) {
@@ -5236,6 +5230,14 @@ var AgentGraphQLClient = class {
5236
5230
  { jobId, logs: [log] }
5237
5231
  );
5238
5232
  }
5233
+ appendCommandOutput(jobId, attemptId, chunks) {
5234
+ return this.request(
5235
+ `mutation AppendCommandRunOutput($jobId: ID!, $attemptId: ID!, $chunks: [CommandRunOutputInput!]!) {
5236
+ appendCommandRunOutput(jobId: $jobId, attemptId: $attemptId, chunks: $chunks) { id }
5237
+ }`,
5238
+ { jobId, attemptId, chunks }
5239
+ );
5240
+ }
5239
5241
  reportBuildProgress(input) {
5240
5242
  return this.request(
5241
5243
  `mutation ReportBuildProgress($input: BuildProgressInput!) {
@@ -5244,12 +5246,12 @@ var AgentGraphQLClient = class {
5244
5246
  { input }
5245
5247
  );
5246
5248
  }
5247
- appendBuildLogs(buildId, events) {
5249
+ appendBuildLogChunks(buildId, chunks) {
5248
5250
  return this.request(
5249
- `mutation AppendBuildLogs($buildId: ID!, $events: [BuildLogEventInput!]!) {
5250
- appendBuildLogEvents(buildId: $buildId, events: $events) { id }
5251
+ `mutation AppendBuildLogChunks($buildId: ID!, $chunks: [BuildLogChunkInput!]!) {
5252
+ appendBuildLogChunks(buildId: $buildId, chunks: $chunks) { id }
5251
5253
  }`,
5252
- { buildId, events }
5254
+ { buildId, chunks }
5253
5255
  );
5254
5256
  }
5255
5257
  async uploadBuildArtifact(input) {
@@ -5980,6 +5982,8 @@ var WORKTREE_OPERATIONS = [
5980
5982
  "OPEN_EDITOR",
5981
5983
  "FORCE_PUSH",
5982
5984
  "SYNC",
5985
+ "REBASE",
5986
+ "CANCEL_REBASE",
5983
5987
  "PUSH",
5984
5988
  "RESET",
5985
5989
  "STASH_ALL",
@@ -7780,10 +7784,58 @@ function parseWorkflowGitCheckpointPayload(value) {
7780
7784
  };
7781
7785
  }
7782
7786
 
7787
+ // ../agent-contract/src/commands.ts
7788
+ var COMMAND_RUN_JOB_KIND = "command.run";
7789
+ function objectValue10(value, name) {
7790
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
7791
+ throw new Error(`${name} must be an object`);
7792
+ }
7793
+ return value;
7794
+ }
7795
+ function stringValue10(value, name, maximum) {
7796
+ if (typeof value !== "string" || !value.length || value.length > maximum) {
7797
+ throw new Error(
7798
+ `${name} must be a non-empty string of at most ${maximum} characters`
7799
+ );
7800
+ }
7801
+ return value;
7802
+ }
7803
+ function parseCommandRunPayload(value) {
7804
+ const payload = objectValue10(value, "command run payload");
7805
+ const targetKind = stringValue10(payload.targetKind, "targetKind", 20);
7806
+ if (targetKind !== "AGENT_HOME" && targetKind !== "WORKTREE") {
7807
+ throw new Error("targetKind must be AGENT_HOME or WORKTREE");
7808
+ }
7809
+ const cwd = payload.cwd === null || payload.cwd === void 0 ? null : stringValue10(payload.cwd, "cwd", 1e4);
7810
+ if (targetKind === "WORKTREE" && !cwd) {
7811
+ throw new Error("Worktree commands require cwd");
7812
+ }
7813
+ if (targetKind === "AGENT_HOME" && cwd !== null) {
7814
+ throw new Error("Agent-home commands cannot provide cwd");
7815
+ }
7816
+ const allowed = /* @__PURE__ */ new Set([
7817
+ "commandRunId",
7818
+ "attemptId",
7819
+ "targetKind",
7820
+ "cwd",
7821
+ "script"
7822
+ ]);
7823
+ const unexpected = Object.keys(payload).find((key) => !allowed.has(key));
7824
+ if (unexpected)
7825
+ throw new Error(`Unsupported command payload field: ${unexpected}`);
7826
+ return {
7827
+ commandRunId: stringValue10(payload.commandRunId, "commandRunId", 200),
7828
+ attemptId: stringValue10(payload.attemptId, "attemptId", 200),
7829
+ targetKind,
7830
+ cwd,
7831
+ script: stringValue10(payload.script, "script", 1e6)
7832
+ };
7833
+ }
7834
+
7783
7835
  // src/inventory.ts
7784
7836
  var AGENT_VERSION = "0.1.0";
7785
7837
  var AGENT_CAPABILITIES = [
7786
- "cloudflared.runTunnel",
7838
+ COMMAND_RUN_JOB_KIND,
7787
7839
  CCUSAGE_REPORT_JOB_KIND,
7788
7840
  ...BUILD_DATA_JOB_KINDS,
7789
7841
  ...CODEBASE_JOB_KINDS,
@@ -7815,148 +7867,186 @@ function collectInventory() {
7815
7867
  };
7816
7868
  }
7817
7869
 
7818
- // src/process-runner.ts
7870
+ // src/handlers/commands.ts
7819
7871
  import { spawn } from "node:child_process";
7820
- async function runProcess(options) {
7821
- return new Promise((resolve7, reject) => {
7822
- let sequence = 0;
7823
- let timedOut = false;
7824
- let cancelled = false;
7825
- let settled = false;
7826
- let logChain = Promise.resolve();
7827
- const detached = process.platform !== "win32";
7828
- const child = spawn(options.command, options.args, {
7829
- shell: false,
7830
- stdio: ["ignore", "pipe", "pipe"],
7831
- cwd: options.cwd,
7832
- env: options.env ?? process.env,
7833
- // A separate process group lets cancellation terminate scripts and all
7834
- // descendants instead of leaving a child holding stdout/stderr open.
7835
- detached
7836
- });
7837
- const emit = (stream, message) => {
7838
- const log = {
7839
- sequence: sequence++,
7840
- stream,
7841
- message,
7842
- createdAt: (/* @__PURE__ */ new Date()).toISOString()
7843
- };
7844
- logChain = logChain.then(async () => {
7872
+ import { chmod as chmod2, mkdtemp, realpath, rm as rm2, writeFile as writeFile2 } from "node:fs/promises";
7873
+ import { homedir as homedir2, tmpdir } from "node:os";
7874
+ import { join as join2 } from "node:path";
7875
+ var MAX_BATCH_BYTES = 128 * 1024;
7876
+ var FLUSH_DELAY_MS = 25;
7877
+ var runCommand = async (rawPayload, _timeoutMs, signal, _onLog, context) => {
7878
+ const payload = parseCommandRunPayload(rawPayload);
7879
+ if (!context?.appendCommandOutput) {
7880
+ throw new Error("Command output uploader is unavailable");
7881
+ }
7882
+ const directory = await mkdtemp(join2(tmpdir(), "aide-command-"));
7883
+ const scriptPath = join2(directory, "command.sh");
7884
+ await writeFile2(scriptPath, payload.script, {
7885
+ encoding: "utf8",
7886
+ mode: 384
7887
+ });
7888
+ await chmod2(scriptPath, 384);
7889
+ const cwd = payload.targetKind === "AGENT_HOME" ? homedir2() : await realpath(payload.cwd);
7890
+ let sequence = 0;
7891
+ let queuedBytes = 0;
7892
+ let pending = [];
7893
+ let timer;
7894
+ let uploadChain = Promise.resolve();
7895
+ const upload = (chunks) => {
7896
+ if (!chunks.length) return;
7897
+ const bytes = chunks.reduce((total, chunk) => total + chunk.byteLength, 0);
7898
+ uploadChain = uploadChain.then(async () => {
7899
+ let retry = 0;
7900
+ while (true) {
7845
7901
  try {
7846
- await options.onLog(log);
7902
+ await context.appendCommandOutput?.(payload.attemptId, chunks);
7903
+ queuedBytes -= bytes;
7904
+ return;
7847
7905
  } catch (error) {
7906
+ if (signal.aborted) return;
7907
+ const delay = Math.min(3e4, 500 * 2 ** Math.min(retry++, 6));
7848
7908
  console.error(
7849
- `Could not append process log ${log.sequence}:`,
7909
+ `Could not append command output; retrying in ${delay}ms:`,
7850
7910
  error instanceof Error ? error.message : error
7851
7911
  );
7912
+ await new Promise((resolve7) => {
7913
+ const onAbort = () => {
7914
+ clearTimeout(retryTimer);
7915
+ resolve7();
7916
+ };
7917
+ const retryTimer = setTimeout(() => {
7918
+ signal.removeEventListener("abort", onAbort);
7919
+ resolve7();
7920
+ }, delay);
7921
+ retryTimer.unref();
7922
+ signal.addEventListener("abort", onAbort, { once: true });
7923
+ if (signal.aborted) onAbort();
7924
+ });
7925
+ if (signal.aborted) return;
7852
7926
  }
7853
- });
7927
+ }
7928
+ });
7929
+ };
7930
+ const flush = () => {
7931
+ if (timer) clearTimeout(timer);
7932
+ timer = void 0;
7933
+ const batch = pending;
7934
+ pending = [];
7935
+ upload(batch);
7936
+ };
7937
+ const enqueue = (stream, bytes) => {
7938
+ const chunk = {
7939
+ sequence: sequence++,
7940
+ stream,
7941
+ dataBase64: bytes.toString("base64"),
7942
+ byteLength: bytes.length,
7943
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
7854
7944
  };
7855
- const attach = (stream, kind) => {
7856
- let remainder = "";
7857
- stream.setEncoding("utf8");
7858
- stream.on("data", (chunk) => {
7859
- const parts = `${remainder}${chunk}`.split(/\r?\n/);
7860
- remainder = parts.pop() ?? "";
7861
- for (const line of parts) emit(kind, line);
7945
+ pending.push(chunk);
7946
+ queuedBytes += bytes.length;
7947
+ if (pending.reduce((total, item) => total + item.byteLength, 0) >= MAX_BATCH_BYTES) {
7948
+ flush();
7949
+ } else if (!timer) {
7950
+ timer = setTimeout(flush, FLUSH_DELAY_MS);
7951
+ timer.unref();
7952
+ }
7953
+ };
7954
+ try {
7955
+ return await new Promise((resolve7, reject) => {
7956
+ let cancelled = false;
7957
+ let settled = false;
7958
+ const child = spawn(process.env.SHELL || "/bin/sh", ["-l", scriptPath], {
7959
+ cwd,
7960
+ detached: process.platform !== "win32",
7961
+ env: {
7962
+ ...process.env,
7963
+ TERM: "xterm-256color",
7964
+ COLORTERM: "truecolor",
7965
+ FORCE_COLOR: "1",
7966
+ CLICOLOR_FORCE: "1"
7967
+ },
7968
+ shell: false,
7969
+ stdio: ["ignore", "pipe", "pipe"]
7862
7970
  });
7863
- stream.on("end", () => {
7864
- if (remainder) emit(kind, remainder);
7971
+ const pauseForPressure = () => {
7972
+ if (queuedBytes < 4 * 1024 * 1024) return;
7973
+ child.stdout.pause();
7974
+ child.stderr.pause();
7975
+ void uploadChain.finally(() => {
7976
+ child.stdout.resume();
7977
+ child.stderr.resume();
7978
+ });
7979
+ };
7980
+ child.stdout.on("data", (bytes) => {
7981
+ enqueue("STDOUT", bytes);
7982
+ pauseForPressure();
7865
7983
  });
7866
- };
7867
- attach(child.stdout, "STDOUT");
7868
- attach(child.stderr, "STDERR");
7869
- const sendSignal = (signal) => {
7870
- if (detached && child.pid) {
7984
+ child.stderr.on("data", (bytes) => {
7985
+ enqueue("STDERR", bytes);
7986
+ pauseForPressure();
7987
+ });
7988
+ const sendSignal = (name) => {
7989
+ if (child.exitCode !== null) return;
7871
7990
  try {
7872
- process.kill(-child.pid, signal);
7873
- return;
7991
+ if (process.platform !== "win32" && child.pid)
7992
+ process.kill(-child.pid, name);
7993
+ else child.kill(name);
7874
7994
  } catch (error) {
7875
7995
  if (!(error instanceof Error) || !("code" in error) || error.code !== "ESRCH") {
7876
7996
  throw error;
7877
7997
  }
7878
7998
  }
7879
- }
7880
- child.kill(signal);
7881
- };
7882
- const terminate = () => {
7883
- if (child.exitCode !== null || child.killed) return;
7884
- sendSignal("SIGTERM");
7885
- const killTimer = setTimeout(() => sendSignal("SIGKILL"), 5e3);
7886
- killTimer.unref();
7887
- };
7888
- const timeout = setTimeout(() => {
7889
- timedOut = true;
7890
- emit(
7891
- "SYSTEM",
7892
- `Process exceeded its ${Math.round(options.timeoutMs / 1e3)} second timeout`
7893
- );
7894
- terminate();
7895
- }, options.timeoutMs);
7896
- timeout.unref();
7897
- const abort = () => {
7898
- cancelled = true;
7899
- emit("SYSTEM", "Cancellation requested");
7900
- terminate();
7901
- };
7902
- options.signal.addEventListener("abort", abort, { once: true });
7903
- child.once("error", (error) => {
7904
- if (settled) return;
7905
- settled = true;
7906
- clearTimeout(timeout);
7907
- options.signal.removeEventListener("abort", abort);
7908
- reject(error);
7909
- });
7910
- child.once("close", (exitCode, signal) => {
7911
- if (settled) return;
7912
- settled = true;
7913
- clearTimeout(timeout);
7914
- options.signal.removeEventListener("abort", abort);
7915
- void logChain.then(
7916
- () => resolve7({ exitCode, signal, timedOut, cancelled })
7917
- );
7999
+ };
8000
+ const abort = () => {
8001
+ if (cancelled) return;
8002
+ cancelled = true;
8003
+ enqueue("SYSTEM", Buffer.from("\r\nCancellation requested\r\n"));
8004
+ sendSignal("SIGTERM");
8005
+ const killTimer = setTimeout(() => sendSignal("SIGKILL"), 5e3);
8006
+ killTimer.unref();
8007
+ };
8008
+ signal.addEventListener("abort", abort, { once: true });
8009
+ if (signal.aborted) abort();
8010
+ child.once("error", (error) => {
8011
+ if (settled) return;
8012
+ settled = true;
8013
+ signal.removeEventListener("abort", abort);
8014
+ reject(error);
8015
+ });
8016
+ child.once("close", (exitCode, closeSignal) => {
8017
+ if (settled) return;
8018
+ settled = true;
8019
+ signal.removeEventListener("abort", abort);
8020
+ flush();
8021
+ void uploadChain.then(
8022
+ () => resolve7({
8023
+ exitCode,
8024
+ signal: closeSignal,
8025
+ timedOut: false,
8026
+ cancelled
8027
+ })
8028
+ );
8029
+ });
7918
8030
  });
7919
- });
7920
- }
7921
-
7922
- // src/handlers/cloudflared.ts
7923
- function validateCloudflaredPayload(payload) {
7924
- if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
7925
- throw new Error("Cloudflared payload must be an object");
7926
- }
7927
- const value = payload;
7928
- if (typeof value.tunnelName !== "string" || !TUNNEL_NAME_REGEX.test(value.tunnelName)) {
7929
- throw new Error("Invalid Cloudflared tunnel name");
7930
- }
7931
- if (Object.keys(value).some((key) => key !== "tunnelName")) {
7932
- throw new Error("Cloudflared payload contains an unsupported field");
8031
+ } finally {
8032
+ if (timer) clearTimeout(timer);
8033
+ await rm2(directory, { force: true, recursive: true });
7933
8034
  }
7934
- return { tunnelName: value.tunnelName };
7935
- }
7936
- function runCloudflared(payload, timeoutMs, signal, onLog) {
7937
- const { tunnelName } = validateCloudflaredPayload(payload);
7938
- return runProcess({
7939
- command: "cloudflared",
7940
- args: ["tunnel", "run", tunnelName],
7941
- timeoutMs,
7942
- signal,
7943
- onLog
7944
- });
7945
- }
8035
+ };
7946
8036
 
7947
8037
  // src/handlers/signing.ts
7948
8038
  import { createHash as createHash3, randomUUID, X509Certificate } from "node:crypto";
7949
8039
  import {
7950
8040
  mkdir as mkdir2,
7951
- mkdtemp,
8041
+ mkdtemp as mkdtemp2,
7952
8042
  readFile as readFile2,
7953
8043
  readdir,
7954
- rm as rm2,
8044
+ rm as rm3,
7955
8045
  stat as stat2,
7956
- writeFile as writeFile2
8046
+ writeFile as writeFile3
7957
8047
  } from "node:fs/promises";
7958
- import { homedir as homedir2, tmpdir } from "node:os";
7959
- import { basename, join as join2, relative, sep } from "node:path";
8048
+ import { homedir as homedir3, tmpdir as tmpdir2 } from "node:os";
8049
+ import { basename, join as join3, relative, sep } from "node:path";
7960
8050
 
7961
8051
  // ../agent-contract/src/plist.ts
7962
8052
  function xmlEscape(value) {
@@ -8191,15 +8281,15 @@ function captureCommand(options) {
8191
8281
 
8192
8282
  // src/handlers/signing.ts
8193
8283
  var PROFILE_DIRECTORIES = [
8194
- join2(
8195
- homedir2(),
8284
+ join3(
8285
+ homedir3(),
8196
8286
  "Library",
8197
8287
  "Developer",
8198
8288
  "Xcode",
8199
8289
  "UserData",
8200
8290
  "Provisioning Profiles"
8201
8291
  ),
8202
- join2(homedir2(), "Library", "MobileDevice", "Provisioning Profiles")
8292
+ join3(homedir3(), "Library", "MobileDevice", "Provisioning Profiles")
8203
8293
  ];
8204
8294
  var PROFILE_EXTENSIONS = [".mobileprovision", ".provisionprofile"];
8205
8295
  function text(value) {
@@ -8292,7 +8382,7 @@ async function readProfiles(timeoutMs, signal) {
8292
8382
  continue;
8293
8383
  signal.throwIfAborted();
8294
8384
  const raw = await decodeProfile(
8295
- join2(directory, entry),
8385
+ join3(directory, entry),
8296
8386
  timeoutMs,
8297
8387
  signal
8298
8388
  );
@@ -8326,7 +8416,7 @@ async function decodedProfiles(timeoutMs, signal, strict = false) {
8326
8416
  continue;
8327
8417
  }
8328
8418
  signal.throwIfAborted();
8329
- const path = join2(directory, entry);
8419
+ const path = join3(directory, entry);
8330
8420
  const raw = await decodeProfile(path, timeoutMs, signal, strict);
8331
8421
  if (!raw) continue;
8332
8422
  let content;
@@ -8482,7 +8572,7 @@ async function readCertificates(timeoutMs, signal, strict = false) {
8482
8572
  );
8483
8573
  }
8484
8574
  async function readArchiveBundles(archivePath, timeoutMs, signal) {
8485
- const products = join2(archivePath, "Products");
8575
+ const products = join3(archivePath, "Products");
8486
8576
  const bundles = [];
8487
8577
  const queue = [products];
8488
8578
  while (queue.length) {
@@ -8496,7 +8586,7 @@ async function readArchiveBundles(archivePath, timeoutMs, signal) {
8496
8586
  }
8497
8587
  for (const entry of entries) {
8498
8588
  if (entry.isSymbolicLink() || !entry.isDirectory()) continue;
8499
- const path = join2(current, entry.name);
8589
+ const path = join3(current, entry.name);
8500
8590
  const signable = /\.(app|appex)$/.test(entry.name);
8501
8591
  if (!signable) {
8502
8592
  if (!/\.[A-Za-z0-9]+$/.test(entry.name)) queue.push(path);
@@ -8528,7 +8618,7 @@ async function bundleIdentifier(bundlePath, timeoutMs, signal) {
8528
8618
  "raw",
8529
8619
  "-o",
8530
8620
  "-",
8531
- join2(bundlePath, "Info.plist")
8621
+ join3(bundlePath, "Info.plist")
8532
8622
  ],
8533
8623
  timeoutMs: Math.min(timeoutMs, 5e3),
8534
8624
  signal
@@ -8544,7 +8634,7 @@ async function embeddedProfile(bundlePath, timeoutMs, signal) {
8544
8634
  "embedded.mobileprovision",
8545
8635
  "embedded.provisionprofile"
8546
8636
  ]) {
8547
- const path = join2(bundlePath, name);
8637
+ const path = join3(bundlePath, name);
8548
8638
  try {
8549
8639
  await stat2(path);
8550
8640
  } catch {
@@ -8591,7 +8681,7 @@ async function inspectSigningAssets(archivePath, timeoutMs, signal) {
8591
8681
  }
8592
8682
  var inspectIosSigning = async (payload, timeoutMs, signal) => {
8593
8683
  const input = parseBuildSigningInspectPayload(payload);
8594
- const archivePath = join2(input.artifactDirectory, input.archiveRelativePath);
8684
+ const archivePath = join3(input.artifactDirectory, input.archiveRelativePath);
8595
8685
  const inspection = await inspectSigningAssets(archivePath, timeoutMs, signal);
8596
8686
  return {
8597
8687
  exitCode: 0,
@@ -8653,21 +8743,21 @@ var installSigningProfile = async (payload, timeoutMs, signal) => {
8653
8743
  const { contentBase64 } = signingProfileInstallPayload(payload);
8654
8744
  const content = Buffer.from(contentBase64, "base64");
8655
8745
  if (!content.length) throw new Error("Provisioning profile is empty");
8656
- const temporaryRoot = await mkdtemp(join2(tmpdir(), "ade-profile-"));
8657
- const temporaryPath = join2(temporaryRoot, `${randomUUID()}.mobileprovision`);
8746
+ const temporaryRoot = await mkdtemp2(join3(tmpdir2(), "ade-profile-"));
8747
+ const temporaryPath = join3(temporaryRoot, `${randomUUID()}.mobileprovision`);
8658
8748
  try {
8659
- await writeFile2(temporaryPath, content, { mode: 384 });
8749
+ await writeFile3(temporaryPath, content, { mode: 384 });
8660
8750
  const raw = await decodeProfile(temporaryPath, timeoutMs, signal);
8661
8751
  if (!raw) throw new Error("Provisioning profile is invalid or unsigned");
8662
8752
  const uuid = text(raw.UUID);
8663
8753
  if (!uuid) throw new Error("Provisioning profile UUID is missing");
8664
8754
  const directory = PROFILE_DIRECTORIES[0];
8665
8755
  await mkdir2(directory, { recursive: true, mode: 448 });
8666
- const destination = join2(directory, `${uuid}.mobileprovision`);
8667
- await writeFile2(destination, content, { mode: 384 });
8756
+ const destination = join3(directory, `${uuid}.mobileprovision`);
8757
+ await writeFile3(destination, content, { mode: 384 });
8668
8758
  return { ...successfulProcess, uuid };
8669
8759
  } finally {
8670
- await rm2(temporaryRoot, { recursive: true, force: true });
8760
+ await rm3(temporaryRoot, { recursive: true, force: true });
8671
8761
  }
8672
8762
  };
8673
8763
  var deleteSigningProfile = async (payload, timeoutMs, signal) => {
@@ -8677,7 +8767,7 @@ var deleteSigningProfile = async (payload, timeoutMs, signal) => {
8677
8767
  );
8678
8768
  for (const profile of matches) {
8679
8769
  signal.throwIfAborted();
8680
- await rm2(profile.path, { force: false });
8770
+ await rm3(profile.path, { force: false });
8681
8771
  }
8682
8772
  return { ...successfulProcess, uuid, deleted: matches.length };
8683
8773
  };
@@ -8691,10 +8781,10 @@ var importSigningIdentity = async (payload, timeoutMs, signal, _onLog, context)
8691
8781
  const hash = createHash3("sha256").update(p12).digest("hex").toUpperCase();
8692
8782
  if (hash !== input.sha256)
8693
8783
  throw new Error("Signing identity transfer changed");
8694
- const temporaryRoot = await mkdtemp(join2(tmpdir(), "ade-identity-"));
8695
- const path = join2(temporaryRoot, "identity.p12");
8784
+ const temporaryRoot = await mkdtemp2(join3(tmpdir2(), "ade-identity-"));
8785
+ const path = join3(temporaryRoot, "identity.p12");
8696
8786
  try {
8697
- await writeFile2(path, p12, { mode: 384 });
8787
+ await writeFile3(path, p12, { mode: 384 });
8698
8788
  const result = await captureCommand({
8699
8789
  command: "/usr/bin/security",
8700
8790
  args: [
@@ -8717,7 +8807,7 @@ var importSigningIdentity = async (payload, timeoutMs, signal, _onLog, context)
8717
8807
  }
8718
8808
  return { ...successfulProcess, sha256: input.sha256 };
8719
8809
  } finally {
8720
- await rm2(temporaryRoot, { recursive: true, force: true });
8810
+ await rm3(temporaryRoot, { recursive: true, force: true });
8721
8811
  }
8722
8812
  };
8723
8813
  var deleteSigningIdentity = async (payload, timeoutMs, signal) => {
@@ -8738,6 +8828,112 @@ var deleteSigningIdentity = async (payload, timeoutMs, signal) => {
8738
8828
 
8739
8829
  // src/handlers/ccusage.ts
8740
8830
  import { Buffer as Buffer2 } from "node:buffer";
8831
+
8832
+ // src/process-runner.ts
8833
+ import { spawn as spawn3 } from "node:child_process";
8834
+ async function runProcess(options) {
8835
+ return new Promise((resolve7, reject) => {
8836
+ let sequence = 0;
8837
+ let timedOut = false;
8838
+ let cancelled = false;
8839
+ let settled = false;
8840
+ let logChain = Promise.resolve();
8841
+ const detached = process.platform !== "win32";
8842
+ const child = spawn3(options.command, options.args, {
8843
+ shell: false,
8844
+ stdio: ["ignore", "pipe", "pipe"],
8845
+ cwd: options.cwd,
8846
+ env: options.env ?? process.env,
8847
+ // A separate process group lets cancellation terminate scripts and all
8848
+ // descendants instead of leaving a child holding stdout/stderr open.
8849
+ detached
8850
+ });
8851
+ const emit = (stream, message) => {
8852
+ const log = {
8853
+ sequence: sequence++,
8854
+ stream,
8855
+ message,
8856
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
8857
+ };
8858
+ logChain = logChain.then(async () => {
8859
+ try {
8860
+ await options.onLog(log);
8861
+ } catch (error) {
8862
+ console.error(
8863
+ `Could not append process log ${log.sequence}:`,
8864
+ error instanceof Error ? error.message : error
8865
+ );
8866
+ }
8867
+ });
8868
+ };
8869
+ const attach = (stream, kind) => {
8870
+ let remainder = "";
8871
+ stream.setEncoding("utf8");
8872
+ stream.on("data", (chunk) => {
8873
+ const parts = `${remainder}${chunk}`.split(/\r?\n/);
8874
+ remainder = parts.pop() ?? "";
8875
+ for (const line of parts) emit(kind, line);
8876
+ });
8877
+ stream.on("end", () => {
8878
+ if (remainder) emit(kind, remainder);
8879
+ });
8880
+ };
8881
+ attach(child.stdout, "STDOUT");
8882
+ attach(child.stderr, "STDERR");
8883
+ const sendSignal = (signal) => {
8884
+ if (detached && child.pid) {
8885
+ try {
8886
+ process.kill(-child.pid, signal);
8887
+ return;
8888
+ } catch (error) {
8889
+ if (!(error instanceof Error) || !("code" in error) || error.code !== "ESRCH") {
8890
+ throw error;
8891
+ }
8892
+ }
8893
+ }
8894
+ child.kill(signal);
8895
+ };
8896
+ const terminate = () => {
8897
+ if (child.exitCode !== null || child.killed) return;
8898
+ sendSignal("SIGTERM");
8899
+ const killTimer = setTimeout(() => sendSignal("SIGKILL"), 5e3);
8900
+ killTimer.unref();
8901
+ };
8902
+ const timeout = setTimeout(() => {
8903
+ timedOut = true;
8904
+ emit(
8905
+ "SYSTEM",
8906
+ `Process exceeded its ${Math.round(options.timeoutMs / 1e3)} second timeout`
8907
+ );
8908
+ terminate();
8909
+ }, options.timeoutMs);
8910
+ timeout.unref();
8911
+ const abort = () => {
8912
+ cancelled = true;
8913
+ emit("SYSTEM", "Cancellation requested");
8914
+ terminate();
8915
+ };
8916
+ options.signal.addEventListener("abort", abort, { once: true });
8917
+ child.once("error", (error) => {
8918
+ if (settled) return;
8919
+ settled = true;
8920
+ clearTimeout(timeout);
8921
+ options.signal.removeEventListener("abort", abort);
8922
+ reject(error);
8923
+ });
8924
+ child.once("close", (exitCode, signal) => {
8925
+ if (settled) return;
8926
+ settled = true;
8927
+ clearTimeout(timeout);
8928
+ options.signal.removeEventListener("abort", abort);
8929
+ void logChain.then(
8930
+ () => resolve7({ exitCode, signal, timedOut, cancelled })
8931
+ );
8932
+ });
8933
+ });
8934
+ }
8935
+
8936
+ // src/handlers/ccusage.ts
8741
8937
  var MAX_CCUSAGE_STDOUT_BYTES = 16 * 1024 * 1024;
8742
8938
  function validateCcusagePayload(payload) {
8743
8939
  if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
@@ -8791,9 +8987,9 @@ async function runCcusage(payload, timeoutMs, signal, onLog) {
8791
8987
  }
8792
8988
 
8793
8989
  // src/handlers/build-data.ts
8794
- import { lstat, opendir, readdir as readdir2, realpath, rm as rm3 } from "node:fs/promises";
8795
- import { homedir as homedir3 } from "node:os";
8796
- import { basename as basename2, dirname as dirname2, isAbsolute, join as join3, resolve } from "node:path";
8990
+ import { lstat, opendir, readdir as readdir2, realpath as realpath2, rm as rm4 } from "node:fs/promises";
8991
+ import { homedir as homedir4 } from "node:os";
8992
+ import { basename as basename2, dirname as dirname2, isAbsolute, join as join4, resolve } from "node:path";
8797
8993
  var successfulProcess2 = {
8798
8994
  exitCode: 0,
8799
8995
  signal: null,
@@ -8810,7 +9006,7 @@ function safeRelativePath3(value) {
8810
9006
  }
8811
9007
  async function configuredRoots(payload) {
8812
9008
  if (payload.mode === "DEFAULT") {
8813
- return [join3(homedir3(), "Library", "Developer", "Xcode", "DerivedData")];
9009
+ return [join4(homedir4(), "Library", "Developer", "Xcode", "DerivedData")];
8814
9010
  }
8815
9011
  if (payload.mode === "ABSOLUTE") {
8816
9012
  if (!payload.path || !isAbsolute(payload.path)) {
@@ -8847,7 +9043,7 @@ async function scanRoot(configuredRoot, timeoutMs, signal) {
8847
9043
  signal.throwIfAborted();
8848
9044
  let rootPath2;
8849
9045
  try {
8850
- rootPath2 = await realpath(configuredRoot);
9046
+ rootPath2 = await realpath2(configuredRoot);
8851
9047
  } catch (error) {
8852
9048
  if (error.code === "ENOENT") {
8853
9049
  return { entries: [], warning: null };
@@ -8870,9 +9066,9 @@ async function scanRoot(configuredRoot, timeoutMs, signal) {
8870
9066
  for (const child of children) {
8871
9067
  signal.throwIfAborted();
8872
9068
  if (!child.isDirectory()) continue;
8873
- const path = join3(rootPath2, child.name);
9069
+ const path = join4(rootPath2, child.name);
8874
9070
  const projectPath = await workspacePath(
8875
- join3(path, "info.plist"),
9071
+ join4(path, "info.plist"),
8876
9072
  timeoutMs,
8877
9073
  signal
8878
9074
  );
@@ -8888,14 +9084,14 @@ async function scanRoot(configuredRoot, timeoutMs, signal) {
8888
9084
  return { entries, warning: null };
8889
9085
  }
8890
9086
  async function scanDeviceSupport(signal) {
8891
- const configuredRoot = join3(
8892
- process.env.ADE_IOS_DEVICE_SUPPORT_DIRECTORY ?? homedir3(),
9087
+ const configuredRoot = join4(
9088
+ process.env.ADE_IOS_DEVICE_SUPPORT_DIRECTORY ?? homedir4(),
8893
9089
  ...process.env.ADE_IOS_DEVICE_SUPPORT_DIRECTORY ? [] : ["Library", "Developer", "Xcode", "iOS DeviceSupport"]
8894
9090
  );
8895
9091
  signal.throwIfAborted();
8896
9092
  let rootPath2;
8897
9093
  try {
8898
- rootPath2 = await realpath(configuredRoot);
9094
+ rootPath2 = await realpath2(configuredRoot);
8899
9095
  } catch (error) {
8900
9096
  if (error.code === "ENOENT") {
8901
9097
  return { entries: [], warning: null };
@@ -8909,7 +9105,7 @@ async function scanDeviceSupport(signal) {
8909
9105
  const children = await readdir2(rootPath2, { withFileTypes: true });
8910
9106
  return {
8911
9107
  entries: children.filter((child) => child.isDirectory() && !child.isSymbolicLink()).map((child) => ({
8912
- path: join3(rootPath2, child.name),
9108
+ path: join4(rootPath2, child.name),
8913
9109
  rootPath: rootPath2,
8914
9110
  name: child.name,
8915
9111
  kind: "DEVICE_SUPPORT",
@@ -8934,7 +9130,7 @@ var scanBuildData = async (rawPayload, timeoutMs, signal) => {
8934
9130
  signal.throwIfAborted();
8935
9131
  let canonical = root;
8936
9132
  try {
8937
- canonical = await realpath(root);
9133
+ canonical = await realpath2(root);
8938
9134
  } catch {
8939
9135
  }
8940
9136
  if (canonicalRoots.has(canonical)) continue;
@@ -8968,7 +9164,7 @@ async function allocatedBytes(path, signal) {
8968
9164
  try {
8969
9165
  for await (const entry of directory) {
8970
9166
  signal.throwIfAborted();
8971
- total += await allocatedBytes(join3(path, entry.name), signal);
9167
+ total += await allocatedBytes(join4(path, entry.name), signal);
8972
9168
  }
8973
9169
  } finally {
8974
9170
  await directory.close().catch(() => void 0);
@@ -8982,7 +9178,7 @@ var sizeBuildData = async (rawPayload, _timeoutMs, signal) => {
8982
9178
  signal.throwIfAborted();
8983
9179
  try {
8984
9180
  assertDirectChild(target2.rootPath, target2.path);
8985
- const rootPath2 = await realpath(target2.rootPath);
9181
+ const rootPath2 = await realpath2(target2.rootPath);
8986
9182
  if (rootPath2 !== resolve(target2.rootPath) || dirname2(resolve(target2.path)) !== rootPath2) {
8987
9183
  throw new Error("Build Data root changed since the scan");
8988
9184
  }
@@ -9013,7 +9209,7 @@ var deleteBuildData = async (rawPayload, _timeoutMs, signal) => {
9013
9209
  signal.throwIfAborted();
9014
9210
  try {
9015
9211
  assertDirectChild(target2.rootPath, target2.path);
9016
- const rootPath2 = await realpath(target2.rootPath);
9212
+ const rootPath2 = await realpath2(target2.rootPath);
9017
9213
  if (rootPath2 !== resolve(target2.rootPath) || dirname2(resolve(target2.path)) !== rootPath2) {
9018
9214
  throw new Error("Build Data root changed since the scan");
9019
9215
  }
@@ -9021,7 +9217,7 @@ var deleteBuildData = async (rawPayload, _timeoutMs, signal) => {
9021
9217
  if (!stats.isDirectory() || stats.isSymbolicLink()) {
9022
9218
  throw new Error("Build Data target is not a directory");
9023
9219
  }
9024
- await rm3(target2.path, { recursive: true, force: false, maxRetries: 3 });
9220
+ await rm4(target2.path, { recursive: true, force: false, maxRetries: 3 });
9025
9221
  deleted.push({ path: target2.path, deleted: true, error: null });
9026
9222
  } catch (error) {
9027
9223
  signal.throwIfAborted();
@@ -9036,9 +9232,9 @@ var deleteBuildData = async (rawPayload, _timeoutMs, signal) => {
9036
9232
  };
9037
9233
 
9038
9234
  // src/handlers/codebases.ts
9039
- import { readdir as readdir3, realpath as realpath2, stat as stat3 } from "node:fs/promises";
9040
- import { homedir as homedir4 } from "node:os";
9041
- import { dirname as dirname3, join as join4, resolve as resolve2 } from "node:path";
9235
+ import { readdir as readdir3, realpath as realpath3, stat as stat3 } from "node:fs/promises";
9236
+ import { homedir as homedir5 } from "node:os";
9237
+ import { dirname as dirname3, join as join5, resolve as resolve2 } from "node:path";
9042
9238
  var successfulProcess3 = {
9043
9239
  exitCode: 0,
9044
9240
  signal: null,
@@ -9115,7 +9311,7 @@ function baseSnapshot(folder) {
9115
9311
  }
9116
9312
  async function fetchedAt(commonDirectory) {
9117
9313
  try {
9118
- return (await stat3(join4(commonDirectory, "FETCH_HEAD"))).mtime.toISOString();
9314
+ return (await stat3(join5(commonDirectory, "FETCH_HEAD"))).mtime.toISOString();
9119
9315
  } catch {
9120
9316
  return null;
9121
9317
  }
@@ -9125,7 +9321,7 @@ async function inspectCodebaseProcess(selectedFolder, timeoutMs, signal, expecte
9125
9321
  const base = baseSnapshot(fallbackFolder);
9126
9322
  let selected;
9127
9323
  try {
9128
- selected = await realpath2(fallbackFolder);
9324
+ selected = await realpath3(fallbackFolder);
9129
9325
  if (!(await stat3(selected)).isDirectory())
9130
9326
  throw new Error("Folder is not a directory");
9131
9327
  } catch (error) {
@@ -9158,7 +9354,7 @@ async function inspectCodebaseProcess(selectedFolder, timeoutMs, signal, expecte
9158
9354
  }
9159
9355
  };
9160
9356
  }
9161
- const folder = await realpath2(rootResult.stdout.trim());
9357
+ const folder = await realpath3(rootResult.stdout.trim());
9162
9358
  const bare = await git(
9163
9359
  folder,
9164
9360
  ["rev-parse", "--is-bare-repository"],
@@ -9209,8 +9405,8 @@ async function inspectCodebaseProcess(selectedFolder, timeoutMs, signal, expecte
9209
9405
  };
9210
9406
  }
9211
9407
  const origin2 = normalizeGitOrigin(originResult.stdout.trim());
9212
- const gitDirectory2 = await realpath2(gitDirectoryResult.stdout.trim());
9213
- const commonDirectory = await realpath2(commonDirectoryResult.stdout.trim());
9408
+ const gitDirectory2 = await realpath3(gitDirectoryResult.stdout.trim());
9409
+ const commonDirectory = await realpath3(commonDirectoryResult.stdout.trim());
9214
9410
  const linkedWorktree = gitDirectory2 !== commonDirectory;
9215
9411
  const branchResult = await git(
9216
9412
  folder,
@@ -9294,8 +9490,8 @@ async function inspectCodebase(selectedFolder, timeoutMs, signal, expectedOrigin
9294
9490
  }
9295
9491
  var browseCodebaseDirectories = async (payload) => {
9296
9492
  const input = codebaseBrowsePayload(payload);
9297
- const homePath = await realpath2(homedir4());
9298
- const path = await realpath2(input.path ? resolve2(input.path) : homePath);
9493
+ const homePath = await realpath3(homedir5());
9494
+ const path = await realpath3(input.path ? resolve2(input.path) : homePath);
9299
9495
  if (!(await stat3(path)).isDirectory())
9300
9496
  throw new Error("Path is not a directory");
9301
9497
  const candidates = await readdir3(path, { withFileTypes: true });
@@ -9304,12 +9500,12 @@ var browseCodebaseDirectories = async (payload) => {
9304
9500
  if (candidate.isDirectory()) {
9305
9501
  entries.push({
9306
9502
  name: candidate.name,
9307
- path: join4(path, candidate.name),
9503
+ path: join5(path, candidate.name),
9308
9504
  hidden: candidate.name.startsWith(".")
9309
9505
  });
9310
9506
  } else if (candidate.isSymbolicLink()) {
9311
9507
  try {
9312
- const target2 = join4(path, candidate.name);
9508
+ const target2 = join5(path, candidate.name);
9313
9509
  if ((await stat3(target2)).isDirectory()) {
9314
9510
  entries.push({
9315
9511
  name: candidate.name,
@@ -9911,19 +10107,19 @@ import { execFile } from "node:child_process";
9911
10107
  import { randomUUID as randomUUID2 } from "node:crypto";
9912
10108
  import {
9913
10109
  access,
9914
- chmod as chmod2,
10110
+ chmod as chmod3,
9915
10111
  lstat as lstat2,
9916
10112
  mkdir as mkdir3,
9917
10113
  readFile as readFile3,
9918
- realpath as realpath3,
10114
+ realpath as realpath4,
9919
10115
  readdir as readdir4,
9920
10116
  rename as rename2,
9921
- rm as rm4,
10117
+ rm as rm5,
9922
10118
  stat as stat4,
9923
- writeFile as writeFile3
10119
+ writeFile as writeFile4
9924
10120
  } from "node:fs/promises";
9925
- import { homedir as homedir5 } from "node:os";
9926
- import { dirname as dirname4, isAbsolute as isAbsolute2, join as join5, relative as relative2, resolve as resolve3, sep as sep2 } from "node:path";
10121
+ import { homedir as homedir6 } from "node:os";
10122
+ import { dirname as dirname4, isAbsolute as isAbsolute2, join as join6, relative as relative2, resolve as resolve3, sep as sep2 } from "node:path";
9927
10123
  import { promisify } from "node:util";
9928
10124
  var executeFile = promisify(execFile);
9929
10125
  var successfulProcess4 = {
@@ -9984,17 +10180,17 @@ async function directoryExists(path) {
9984
10180
  }
9985
10181
  }
9986
10182
  async function configuredTools(tools) {
9987
- const homePath = homedir5();
10183
+ const homePath = homedir6();
9988
10184
  return Promise.all(
9989
10185
  AI_TOOLS.filter((tool) => tools.includes(tool)).map(async (tool) => ({
9990
10186
  tool,
9991
- configured: await directoryExists(join5(homePath, ...CONFIG_PATHS[tool])),
10187
+ configured: await directoryExists(join6(homePath, ...CONFIG_PATHS[tool])),
9992
10188
  homePath
9993
10189
  }))
9994
10190
  );
9995
10191
  }
9996
10192
  function rootPath(location) {
9997
- const base = location.scope === "GLOBAL" ? homedir5() : location.folder;
10193
+ const base = location.scope === "GLOBAL" ? homedir6() : location.folder;
9998
10194
  const parts = location.scope === "GLOBAL" ? GLOBAL_ROOTS[location.rootKind] : PROJECT_ROOTS[location.rootKind];
9999
10195
  const path = resolve3(base, ...parts);
10000
10196
  const normalizedBase = resolve3(base);
@@ -10011,7 +10207,7 @@ async function listPackageFiles(skillDirectory) {
10011
10207
  let totalBytes = 0;
10012
10208
  const visit = async (directory) => {
10013
10209
  for (const entry of await readdir4(directory, { withFileTypes: true })) {
10014
- const path = join5(directory, entry.name);
10210
+ const path = join6(directory, entry.name);
10015
10211
  const metadata = await lstat2(path);
10016
10212
  if (metadata.isSymbolicLink()) {
10017
10213
  throw new Error(
@@ -10047,7 +10243,7 @@ async function readPackage(directory) {
10047
10243
  const metadata = await lstat2(directory);
10048
10244
  let resolvedDirectory = directory;
10049
10245
  if (metadata.isSymbolicLink()) {
10050
- resolvedDirectory = await realpath3(directory);
10246
+ resolvedDirectory = await realpath4(directory);
10051
10247
  } else if (!metadata.isDirectory()) {
10052
10248
  throw new Error("Skill path is not a directory");
10053
10249
  }
@@ -10100,7 +10296,7 @@ async function scanRoot2(location, configured, targets, warnings) {
10100
10296
  const installations = [];
10101
10297
  for (const entry of await readdir4(root, { withFileTypes: true })) {
10102
10298
  if (!entry.isDirectory() && !entry.isSymbolicLink()) continue;
10103
- const directory = join5(root, entry.name);
10299
+ const directory = join6(root, entry.name);
10104
10300
  try {
10105
10301
  const skillPackage = await readPackage(directory);
10106
10302
  const relativeDirectory = location.folder ? relative2(location.folder, directory).split(sep2).join("/") : "";
@@ -10179,7 +10375,7 @@ var readSkills = async (payload) => {
10179
10375
  }
10180
10376
  packages.push({
10181
10377
  ...request,
10182
- package: await readPackage(join5(root, request.skillName))
10378
+ package: await readPackage(join6(root, request.skillName))
10183
10379
  });
10184
10380
  }
10185
10381
  return { ...successfulProcess4, packages };
@@ -10220,7 +10416,7 @@ async function updateManagedExclude(folder, relativeSkillPath, present) {
10220
10416
  const block = managed.size ? `${MANAGED_EXCLUDE_START}
10221
10417
  ${[...managed].sort().join("\n")}
10222
10418
  ${MANAGED_EXCLUDE_END}` : "";
10223
- await writeFile3(
10419
+ await writeFile4(
10224
10420
  excludePath,
10225
10421
  `${[before, block, after].filter(Boolean).join("\n\n")}
10226
10422
  `,
@@ -10241,11 +10437,11 @@ async function writePackage(location, skillPackage) {
10241
10437
  throw new Error("New skill copies may only be written to shared roots");
10242
10438
  }
10243
10439
  const root = rootPath(location);
10244
- const destination = join5(root, skillPackage.name);
10440
+ const destination = join6(root, skillPackage.name);
10245
10441
  await assertUntracked(location, destination);
10246
10442
  await mkdir3(root, { recursive: true });
10247
- const temporary = join5(root, `.${skillPackage.name}.${randomUUID2()}.tmp`);
10248
- const backup = join5(root, `.${skillPackage.name}.${randomUUID2()}.bak`);
10443
+ const temporary = join6(root, `.${skillPackage.name}.${randomUUID2()}.tmp`);
10444
+ const backup = join6(root, `.${skillPackage.name}.${randomUUID2()}.bak`);
10249
10445
  await mkdir3(temporary, { recursive: true });
10250
10446
  try {
10251
10447
  for (const file of skillPackage.files) {
@@ -10253,8 +10449,8 @@ async function writePackage(location, skillPackage) {
10253
10449
  if (!path.startsWith(`${temporary}${sep2}`))
10254
10450
  throw new Error("Skill file escaped temporary directory");
10255
10451
  await mkdir3(dirname4(path), { recursive: true });
10256
- await writeFile3(path, Buffer.from(file.contentsBase64, "base64"));
10257
- await chmod2(path, file.executable ? 493 : 420);
10452
+ await writeFile4(path, Buffer.from(file.contentsBase64, "base64"));
10453
+ await chmod3(path, file.executable ? 493 : 420);
10258
10454
  }
10259
10455
  let hadDestination = false;
10260
10456
  try {
@@ -10266,14 +10462,14 @@ async function writePackage(location, skillPackage) {
10266
10462
  }
10267
10463
  try {
10268
10464
  await rename2(temporary, destination);
10269
- if (hadDestination) await rm4(backup, { recursive: true, force: true });
10465
+ if (hadDestination) await rm5(backup, { recursive: true, force: true });
10270
10466
  } catch (error) {
10271
10467
  if (hadDestination) await rename2(backup, destination);
10272
10468
  throw error;
10273
10469
  }
10274
10470
  } finally {
10275
- await rm4(temporary, { recursive: true, force: true });
10276
- await rm4(backup, { recursive: true, force: true });
10471
+ await rm5(temporary, { recursive: true, force: true });
10472
+ await rm5(backup, { recursive: true, force: true });
10277
10473
  }
10278
10474
  return destination;
10279
10475
  }
@@ -10283,7 +10479,7 @@ var applySkills = async (payload) => {
10283
10479
  for (const operation of operations) {
10284
10480
  const root = rootPath(operation);
10285
10481
  const skillName = operation.kind === "WRITE" ? operation.package.name : operation.skillName;
10286
- const destination = join5(root, skillName);
10482
+ const destination = join6(root, skillName);
10287
10483
  await assertUntracked(operation, destination);
10288
10484
  if (operation.kind === "WRITE") {
10289
10485
  await writePackage(operation, operation.package);
@@ -10293,7 +10489,7 @@ var applySkills = async (payload) => {
10293
10489
  packageHash: operation.package.packageHash
10294
10490
  });
10295
10491
  } else {
10296
- await rm4(destination, { recursive: true, force: true });
10492
+ await rm5(destination, { recursive: true, force: true });
10297
10493
  results.push({
10298
10494
  kind: operation.kind,
10299
10495
  path: destination,
@@ -10313,8 +10509,8 @@ var applySkills = async (payload) => {
10313
10509
 
10314
10510
  // src/handlers/runs.ts
10315
10511
  import { readFile as readFile4, readdir as readdir5, stat as stat5 } from "node:fs/promises";
10316
- import { homedir as homedir6 } from "node:os";
10317
- import { join as join6 } from "node:path";
10512
+ import { homedir as homedir7 } from "node:os";
10513
+ import { join as join7 } from "node:path";
10318
10514
  var successfulProcess5 = {
10319
10515
  exitCode: 0,
10320
10516
  signal: null,
@@ -10329,7 +10525,7 @@ async function fileExists(path) {
10329
10525
  }
10330
10526
  }
10331
10527
  async function findClaudeSessionFile(nativeId, home) {
10332
- const projectsDir = join6(home, ".claude", "projects");
10528
+ const projectsDir = join7(home, ".claude", "projects");
10333
10529
  let entries;
10334
10530
  try {
10335
10531
  entries = await readdir5(projectsDir, { withFileTypes: true });
@@ -10339,13 +10535,13 @@ async function findClaudeSessionFile(nativeId, home) {
10339
10535
  const target2 = `${nativeId}.jsonl`;
10340
10536
  for (const entry of entries) {
10341
10537
  if (!entry.isDirectory()) continue;
10342
- const candidate = join6(projectsDir, entry.name, target2);
10538
+ const candidate = join7(projectsDir, entry.name, target2);
10343
10539
  if (await fileExists(candidate)) return candidate;
10344
10540
  }
10345
10541
  return null;
10346
10542
  }
10347
10543
  async function findCodexSessionFile(nativeId, home) {
10348
- const sessionsDir = join6(home, ".codex", "sessions");
10544
+ const sessionsDir = join7(home, ".codex", "sessions");
10349
10545
  const suffix = `-${nativeId}.jsonl`;
10350
10546
  const walk = async (dir) => {
10351
10547
  let entries;
@@ -10355,7 +10551,7 @@ async function findCodexSessionFile(nativeId, home) {
10355
10551
  return null;
10356
10552
  }
10357
10553
  for (const entry of entries) {
10358
- const path = join6(dir, entry.name);
10554
+ const path = join7(dir, entry.name);
10359
10555
  if (entry.isDirectory()) {
10360
10556
  const found = await walk(path);
10361
10557
  if (found) return found;
@@ -10372,7 +10568,7 @@ async function locateSessionFile(payload, home) {
10372
10568
  }
10373
10569
  var readRunSession = async (payload) => {
10374
10570
  const input = parseRunSessionReadPayload(payload);
10375
- const path = await locateSessionFile(input, homedir6());
10571
+ const path = await locateSessionFile(input, homedir7());
10376
10572
  if (!path) {
10377
10573
  throw new Error(
10378
10574
  `No ${input.provider === "CLAUDE" ? "Claude" : "Codex"} session file found for this run on this agent`
@@ -10394,21 +10590,21 @@ var readRunSession = async (payload) => {
10394
10590
 
10395
10591
  // src/handlers/workflows.ts
10396
10592
  import {
10397
- mkdtemp as mkdtemp4,
10593
+ mkdtemp as mkdtemp5,
10398
10594
  readFile as readFile6,
10399
- realpath as realpath5,
10400
- rm as rm7,
10595
+ realpath as realpath6,
10596
+ rm as rm8,
10401
10597
  stat as stat7,
10402
- writeFile as writeFile5
10598
+ writeFile as writeFile6
10403
10599
  } from "node:fs/promises";
10404
- import { tmpdir as tmpdir4 } from "node:os";
10405
- import { join as join9 } from "node:path";
10600
+ import { tmpdir as tmpdir5 } from "node:os";
10601
+ import { join as join10 } from "node:path";
10406
10602
 
10407
10603
  // src/runs/git-checkpoint.ts
10408
10604
  import { execFile as execFile2 } from "node:child_process";
10409
- import { copyFile, mkdtemp as mkdtemp2, rm as rm5 } from "node:fs/promises";
10410
- import { tmpdir as tmpdir2 } from "node:os";
10411
- import { join as join7 } from "node:path";
10605
+ import { copyFile, mkdtemp as mkdtemp3, rm as rm6 } from "node:fs/promises";
10606
+ import { tmpdir as tmpdir3 } from "node:os";
10607
+ import { join as join8 } from "node:path";
10412
10608
  import { promisify as promisify2 } from "node:util";
10413
10609
  var execFileAsync = promisify2(execFile2);
10414
10610
  async function git2(cwd, args, env) {
@@ -10523,12 +10719,12 @@ async function captureGitCheckpoint(cwd, runId, kind) {
10523
10719
  const manifest = await optionalGit(cwd, ["status", "--porcelain=v2", "-z"]);
10524
10720
  const staged = await optionalGit(cwd, ["diff", "--cached", "--stat", "HEAD"]);
10525
10721
  const unstaged = await optionalGit(cwd, ["diff", "--stat", "HEAD"]);
10526
- const directory = await mkdtemp2(join7(tmpdir2(), "aide-run-index-"));
10722
+ const directory = await mkdtemp3(join8(tmpdir3(), "aide-run-index-"));
10527
10723
  let worktreeTree = null;
10528
10724
  let refName = null;
10529
10725
  try {
10530
10726
  const actualIndex = await git2(cwd, ["rev-parse", "--git-path", "index"]);
10531
- const temporaryIndex = join7(directory, "index");
10727
+ const temporaryIndex = join8(directory, "index");
10532
10728
  try {
10533
10729
  await copyFile(actualIndex, temporaryIndex);
10534
10730
  } catch {
@@ -10560,7 +10756,7 @@ async function captureGitCheckpoint(cwd, runId, kind) {
10560
10756
  refName = `refs/aide/runs/${runId}/${Date.now()}-${kind.toLowerCase()}`;
10561
10757
  await git2(cwd, ["update-ref", refName, checkpointCommit]);
10562
10758
  } finally {
10563
- await rm5(directory, { recursive: true, force: true });
10759
+ await rm6(directory, { recursive: true, force: true });
10564
10760
  }
10565
10761
  return {
10566
10762
  kind,
@@ -10589,36 +10785,37 @@ import { createHash as createHash5, randomUUID as randomUUID3 } from "node:crypt
10589
10785
  import {
10590
10786
  cp,
10591
10787
  mkdir as mkdir4,
10592
- mkdtemp as mkdtemp3,
10788
+ mkdtemp as mkdtemp4,
10593
10789
  open,
10594
10790
  readdir as readdir6,
10595
10791
  readFile as readFile5,
10596
- realpath as realpath4,
10792
+ realpath as realpath5,
10597
10793
  rename as rename3,
10598
- rm as rm6,
10794
+ rm as rm7,
10599
10795
  stat as stat6,
10600
- writeFile as writeFile4
10796
+ writeFile as writeFile5
10601
10797
  } from "node:fs/promises";
10602
10798
  import { createReadStream as createReadStream3, createWriteStream } from "node:fs";
10603
- import { tmpdir as tmpdir3 } from "node:os";
10799
+ import { tmpdir as tmpdir4 } from "node:os";
10604
10800
  import { pipeline } from "node:stream/promises";
10801
+ import { StringDecoder } from "node:string_decoder";
10605
10802
  import {
10606
10803
  basename as basename3,
10607
10804
  dirname as dirname5,
10608
10805
  isAbsolute as isAbsolute4,
10609
- join as join8,
10806
+ join as join9,
10610
10807
  relative as relative4,
10611
10808
  resolve as resolve5,
10612
10809
  sep as sep4
10613
10810
  } from "node:path";
10614
- import { spawn as spawn4 } from "node:child_process";
10811
+ import { spawn as spawn5 } from "node:child_process";
10615
10812
 
10616
10813
  // src/git-code-state.ts
10617
10814
  import { createHash as createHash4 } from "node:crypto";
10618
10815
  import { createReadStream as createReadStream2 } from "node:fs";
10619
10816
  import { lstat as lstat3, readlink } from "node:fs/promises";
10620
10817
  import { isAbsolute as isAbsolute3, relative as relative3, resolve as resolve4, sep as sep3 } from "node:path";
10621
- import { spawn as spawn3 } from "node:child_process";
10818
+ import { spawn as spawn4 } from "node:child_process";
10622
10819
  function gitEnvironment() {
10623
10820
  return {
10624
10821
  ...process.env,
@@ -10641,7 +10838,7 @@ function hashGitDiff(hash, folder, timeoutMs, signal) {
10641
10838
  return new Promise((resolveResult, reject) => {
10642
10839
  let settled = false;
10643
10840
  let timedOut = false;
10644
- const child = spawn3(
10841
+ const child = spawn4(
10645
10842
  "git",
10646
10843
  [
10647
10844
  "-C",
@@ -10860,7 +11057,7 @@ function requireSuccess2(result, fallback) {
10860
11057
  return result;
10861
11058
  }
10862
11059
  async function validateWorktree(input, timeoutMs, signal) {
10863
- const folder = await realpath4(input.folder);
11060
+ const folder = await realpath5(input.folder);
10864
11061
  if (!(await stat6(folder)).isDirectory())
10865
11062
  throw new Error("Worktree is missing");
10866
11063
  const gitDirectory2 = requireSuccess2(
@@ -10874,7 +11071,7 @@ async function validateWorktree(input, timeoutMs, signal) {
10874
11071
  ),
10875
11072
  "Could not resolve the worktree Git directory"
10876
11073
  ).stdout.trim();
10877
- if (await realpath4(gitDirectory2) !== input.gitDirectory) {
11074
+ if (await realpath5(gitDirectory2) !== input.gitDirectory) {
10878
11075
  throw new Error("Worktree identity changed; refresh the page");
10879
11076
  }
10880
11077
  const origin2 = requireSuccess2(
@@ -10903,7 +11100,7 @@ function containedPath2(root, relativePath) {
10903
11100
  }
10904
11101
  async function validateSource(root, source) {
10905
11102
  const target2 = containedPath2(root, source.relativePath);
10906
- const resolved = await realpath4(target2);
11103
+ const resolved = await realpath5(target2);
10907
11104
  const difference = relative4(root, resolved);
10908
11105
  if (difference === ".." || difference.startsWith(`..${sep4}`) || isAbsolute4(difference)) {
10909
11106
  throw new Error("Build source resolves outside the worktree");
@@ -10924,7 +11121,7 @@ async function discoverSourcesInFolder(folder) {
10924
11121
  const current = queue.shift();
10925
11122
  for (const entry of await readdir6(current, { withFileTypes: true })) {
10926
11123
  if (entry.isSymbolicLink()) continue;
10927
- const absolute = join8(current, entry.name);
11124
+ const absolute = join9(current, entry.name);
10928
11125
  const path = relative4(folder, absolute).split(sep4).join("/");
10929
11126
  if (entry.isDirectory()) {
10930
11127
  if (entry.name.endsWith(".xcodeproj")) {
@@ -10995,7 +11192,7 @@ function metadataFromList(value) {
10995
11192
  };
10996
11193
  }
10997
11194
  async function workspaceProjectPaths(workspacePath2, folder) {
10998
- const contentsPath = join8(workspacePath2, "contents.xcworkspacedata");
11195
+ const contentsPath = join9(workspacePath2, "contents.xcworkspacedata");
10999
11196
  let contents;
11000
11197
  try {
11001
11198
  contents = await readFile5(contentsPath, "utf8");
@@ -11022,7 +11219,7 @@ async function workspaceProjectPaths(workspacePath2, folder) {
11022
11219
  continue;
11023
11220
  }
11024
11221
  try {
11025
- const resolved = await realpath4(candidate);
11222
+ const resolved = await realpath5(candidate);
11026
11223
  const resolvedDifference = relative4(folder, resolved);
11027
11224
  if (resolvedDifference === ".." || resolvedDifference.startsWith(`..${sep4}`) || isAbsolute4(resolvedDifference) || !(await stat6(resolved)).isDirectory()) {
11028
11225
  continue;
@@ -11215,7 +11412,7 @@ async function dependentSigningRequirements(source, absolutePath, folder, rootTa
11215
11412
  for (const project of projects.slice(0, 50)) {
11216
11413
  const converted = await command(
11217
11414
  "plutil",
11218
- ["-convert", "json", "-o", "-", join8(project, "project.pbxproj")],
11415
+ ["-convert", "json", "-o", "-", join9(project, "project.pbxproj")],
11219
11416
  Math.min(timeoutMs, 15e3),
11220
11417
  signal,
11221
11418
  folder
@@ -11452,8 +11649,8 @@ function genericBuildDestinations(action) {
11452
11649
  ];
11453
11650
  }
11454
11651
  async function listPhysicalDevices(timeoutMs, signal) {
11455
- const directory = await mkdtemp3(join8(tmpdir3(), "ade-devices-"));
11456
- const output = join8(directory, "devices.json");
11652
+ const directory = await mkdtemp4(join9(tmpdir4(), "ade-devices-"));
11653
+ const output = join9(directory, "devices.json");
11457
11654
  try {
11458
11655
  const result = await command(
11459
11656
  "xcrun",
@@ -11473,7 +11670,7 @@ async function listPhysicalDevices(timeoutMs, signal) {
11473
11670
  if (result.exitCode !== 0) return [];
11474
11671
  return physicalDestinations(JSON.parse(await readFile5(output, "utf8")));
11475
11672
  } finally {
11476
- await rm6(directory, { recursive: true, force: true });
11673
+ await rm7(directory, { recursive: true, force: true });
11477
11674
  }
11478
11675
  }
11479
11676
  var inspectBuildDestinations = async (payload, timeoutMs, signal) => {
@@ -11560,7 +11757,7 @@ function createRedactor(env) {
11560
11757
  );
11561
11758
  };
11562
11759
  }
11563
- var BuildLogger = class {
11760
+ var BuildLogger = class _BuildLogger {
11564
11761
  constructor(buildId, context, rawLogPath, env) {
11565
11762
  this.buildId = buildId;
11566
11763
  this.context = context;
@@ -11569,51 +11766,67 @@ var BuildLogger = class {
11569
11766
  }
11570
11767
  buildId;
11571
11768
  context;
11769
+ static MAX_CHUNK_BYTES = 128 * 1024;
11770
+ static MAX_BATCH_BYTES = 128 * 1024;
11572
11771
  stream;
11573
11772
  redact;
11574
11773
  sequence = 0;
11575
11774
  pending = [];
11775
+ pendingBytes = 0;
11576
11776
  flushChain = Promise.resolve();
11577
11777
  timer = null;
11578
11778
  closePromise = null;
11579
11779
  redactingPrivateKey = false;
11580
11780
  emit(phase, stream, message, scope = "BUILD", scopeId = this.buildId, extraStream) {
11781
+ this.write(phase, stream, `${message}\r
11782
+ `, scope, scopeId, extraStream);
11783
+ }
11784
+ write(phase, stream, output, scope = "BUILD", scopeId = this.buildId, extraStream) {
11785
+ const ending = output.match(/(?:\r\n|\r|\n)$/)?.[0] ?? "";
11786
+ const message = ending ? output.slice(0, -ending.length) : output;
11581
11787
  const startsPrivateKey = /-----BEGIN [^-]*PRIVATE KEY-----/i.test(message);
11582
11788
  const endsPrivateKey = /-----END [^-]*PRIVATE KEY-----/i.test(message);
11583
11789
  if (startsPrivateKey) this.redactingPrivateKey = true;
11584
11790
  const sanitized = this.redactingPrivateKey ? "[REDACTED PRIVATE KEY]" : this.redact(message);
11585
11791
  if (endsPrivateKey) this.redactingPrivateKey = false;
11586
11792
  const createdAt = (/* @__PURE__ */ new Date()).toISOString();
11587
- const line = `[${createdAt}] [${phase}] [${stream}] ${sanitized}
11588
- `;
11793
+ const terminalOutput = `${sanitized}${ending}`;
11794
+ const line = `[${createdAt}] [${phase}] [${stream}] ${sanitized}${ending || "\n"}`;
11589
11795
  this.stream.write(line);
11590
11796
  extraStream?.write(line);
11591
- this.pending.push({
11592
- scope,
11593
- scopeId,
11594
- sequence: this.sequence++,
11595
- phase,
11596
- level: stream === "STDERR" || /\berror\b/i.test(sanitized) ? "ERROR" : /\bwarning\b/i.test(sanitized) ? "WARNING" : "INFO",
11597
- stream,
11598
- message: sanitized,
11599
- createdAt
11600
- });
11601
- if (this.pending.length >= 100) this.flush();
11602
- else if (!this.timer) {
11603
- this.timer = setTimeout(() => this.flush(), 250);
11797
+ for (const data of splitUtf8(terminalOutput, _BuildLogger.MAX_CHUNK_BYTES)) {
11798
+ const bytes = Buffer.from(data, "utf8");
11799
+ this.pending.push({
11800
+ scope,
11801
+ scopeId,
11802
+ sequence: this.sequence++,
11803
+ phase,
11804
+ stream,
11805
+ dataBase64: bytes.toString("base64"),
11806
+ byteLength: bytes.byteLength,
11807
+ createdAt
11808
+ });
11809
+ this.pendingBytes += bytes.byteLength;
11810
+ if (this.pending.length >= 200 || this.pendingBytes >= _BuildLogger.MAX_BATCH_BYTES) {
11811
+ this.flush();
11812
+ }
11813
+ }
11814
+ if (this.pending.length && !this.timer) {
11815
+ this.timer = setTimeout(() => this.flush(), 25);
11604
11816
  this.timer.unref();
11605
11817
  }
11606
11818
  }
11607
11819
  flush() {
11608
11820
  if (this.timer) clearTimeout(this.timer);
11609
11821
  this.timer = null;
11610
- const events = this.pending.splice(0);
11611
- if (!events.length || !this.context?.appendBuildLogs) return;
11822
+ const chunks = this.pending.splice(0);
11823
+ this.pendingBytes = 0;
11824
+ if (!chunks.length || !this.context?.appendBuildLogChunks) return;
11612
11825
  this.flushChain = this.flushChain.then(async () => {
11613
11826
  try {
11614
- await this.context.appendBuildLogs(this.buildId, events);
11827
+ await this.context.appendBuildLogChunks(this.buildId, chunks);
11615
11828
  } catch (error) {
11616
- console.error("Could not append build logs:", cleanError2(error));
11829
+ console.error("Could not append build log chunks:", cleanError2(error));
11617
11830
  }
11618
11831
  });
11619
11832
  }
@@ -11626,6 +11839,24 @@ var BuildLogger = class {
11626
11839
  return this.closePromise;
11627
11840
  }
11628
11841
  };
11842
+ function splitUtf8(value, maximumBytes) {
11843
+ if (!value) return [];
11844
+ const parts = [];
11845
+ let part = "";
11846
+ let byteLength = 0;
11847
+ for (const character of value) {
11848
+ const characterBytes = Buffer.byteLength(character, "utf8");
11849
+ if (part && byteLength + characterBytes > maximumBytes) {
11850
+ parts.push(part);
11851
+ part = "";
11852
+ byteLength = 0;
11853
+ }
11854
+ part += character;
11855
+ byteLength += characterBytes;
11856
+ }
11857
+ if (part) parts.push(part);
11858
+ return parts;
11859
+ }
11629
11860
  function terminateProcess(child) {
11630
11861
  if (child.exitCode !== null || child.killed) return null;
11631
11862
  try {
@@ -11659,9 +11890,15 @@ function runLoggedCommand(options) {
11659
11890
  mode: 384
11660
11891
  });
11661
11892
  }
11662
- const child = spawn4(options.command, options.args, {
11893
+ const child = spawn5(options.command, options.args, {
11663
11894
  cwd: options.cwd,
11664
- env: options.env,
11895
+ env: {
11896
+ ...options.env,
11897
+ TERM: "xterm-256color",
11898
+ COLORTERM: "truecolor",
11899
+ FORCE_COLOR: "1",
11900
+ CLICOLOR_FORCE: "1"
11901
+ },
11665
11902
  shell: false,
11666
11903
  detached: true,
11667
11904
  stdio: ["ignore", "pipe", "pipe"]
@@ -11675,36 +11912,36 @@ function runLoggedCommand(options) {
11675
11912
  extraStream
11676
11913
  );
11677
11914
  const attach = (stream, kind) => {
11915
+ const decoder = new StringDecoder("utf8");
11678
11916
  let remainder = "";
11679
- stream.setEncoding("utf8");
11680
- stream.on("data", (chunk) => {
11681
- const parts = `${remainder}${chunk}`.split(/\r?\n/);
11682
- remainder = parts.pop() ?? "";
11683
- for (const line of parts) {
11684
- output = `${output}${line}
11685
- `.slice(-64e3);
11686
- options.logger.emit(
11917
+ const drain = (final = false) => {
11918
+ while (remainder) {
11919
+ const delimiter = remainder.search(/[\r\n]/);
11920
+ if (delimiter < 0 && !final) return;
11921
+ let end = delimiter < 0 ? remainder.length : delimiter + 1;
11922
+ if (remainder[delimiter] === "\r" && remainder[delimiter + 1] === "\n") {
11923
+ end += 1;
11924
+ }
11925
+ const record = remainder.slice(0, end);
11926
+ remainder = remainder.slice(end);
11927
+ output = `${output}${record}`.slice(-64e3);
11928
+ options.logger.write(
11687
11929
  options.phase,
11688
11930
  kind,
11689
- line,
11931
+ record,
11690
11932
  options.scope,
11691
11933
  options.scopeId,
11692
11934
  extraStream
11693
11935
  );
11694
11936
  }
11937
+ };
11938
+ stream.on("data", (chunk) => {
11939
+ remainder += decoder.write(chunk);
11940
+ drain();
11695
11941
  });
11696
11942
  stream.on("end", () => {
11697
- if (remainder) {
11698
- output = `${output}${remainder}`.slice(-64e3);
11699
- options.logger.emit(
11700
- options.phase,
11701
- kind,
11702
- remainder,
11703
- options.scope,
11704
- options.scopeId,
11705
- extraStream
11706
- );
11707
- }
11943
+ remainder += decoder.end();
11944
+ drain(true);
11708
11945
  });
11709
11946
  };
11710
11947
  attach(child.stdout, "STDOUT");
@@ -11851,7 +12088,7 @@ function actionArgument(action) {
11851
12088
  }[action];
11852
12089
  }
11853
12090
  function xcodeBuildArguments(input) {
11854
- const resultBundle = join8(input.artifactDirectory, "result.xcresult");
12091
+ const resultBundle = join9(input.artifactDirectory, "result.xcresult");
11855
12092
  const sourcePath = containedPath2(input.folder, input.source.relativePath);
11856
12093
  const usesCapturedTestProducts = input.action === "TEST_WITHOUT_BUILDING";
11857
12094
  const args = [
@@ -11873,13 +12110,13 @@ function xcodeBuildArguments(input) {
11873
12110
  if (input.action === "ARCHIVE") {
11874
12111
  args.push(
11875
12112
  "-archivePath",
11876
- join8(input.artifactDirectory, "archive.xcarchive")
12113
+ join9(input.artifactDirectory, "archive.xcarchive")
11877
12114
  );
11878
12115
  }
11879
12116
  if (input.action === "BUILD_FOR_TESTING") {
11880
12117
  args.push(
11881
12118
  "-testProductsPath",
11882
- join8(input.artifactDirectory, "test-products.xctestproducts")
12119
+ join9(input.artifactDirectory, "test-products.xctestproducts")
11883
12120
  );
11884
12121
  }
11885
12122
  if (input.action === "TEST_WITHOUT_BUILDING" && input.advancedSettings.priorTestProductsPath) {
@@ -11942,27 +12179,27 @@ function classifyFailure(output) {
11942
12179
  }
11943
12180
  async function runHook(options) {
11944
12181
  const phaseDirectory = options.phase === "PRE_BUILD" ? "pre" : "post";
11945
- const directory = join8(
12182
+ const directory = join9(
11946
12183
  options.input.artifactDirectory,
11947
12184
  "hooks",
11948
12185
  phaseDirectory
11949
12186
  );
11950
12187
  const prefix = `${String(options.script.position).padStart(3, "0")}-${options.script.id}`;
11951
- const file = join8(directory, `${prefix}.mjs`);
11952
- const runner = join8(directory, `${prefix}.runner.mjs`);
11953
- const log = join8(directory, `${prefix}.log`);
12188
+ const file = join9(directory, `${prefix}.mjs`);
12189
+ const runner = join9(directory, `${prefix}.runner.mjs`);
12190
+ const log = join9(directory, `${prefix}.log`);
11954
12191
  const started = Date.now();
11955
12192
  try {
11956
12193
  await mkdir4(directory, { recursive: true, mode: 448 });
11957
- await writeFile4(file, `${options.source}
12194
+ await writeFile5(file, `${options.source}
11958
12195
  `, { mode: 384 });
11959
- await writeFile4(
12196
+ await writeFile5(
11960
12197
  options.contextPath,
11961
12198
  `${JSON.stringify(options.hookContext, null, 2)}
11962
12199
  `,
11963
12200
  { mode: 384 }
11964
12201
  );
11965
- await writeFile4(
12202
+ await writeFile5(
11966
12203
  runner,
11967
12204
  `import { readFile } from "node:fs/promises";
11968
12205
  const hookModule = await import(${JSON.stringify(`./${basename3(file)}`)});
@@ -12048,7 +12285,7 @@ async function pathSize(path) {
12048
12285
  let size = 0;
12049
12286
  for (const entry of await readdir6(path, { withFileTypes: true })) {
12050
12287
  if (entry.isSymbolicLink()) continue;
12051
- size += await pathSize(join8(path, entry.name));
12288
+ size += await pathSize(join9(path, entry.name));
12052
12289
  }
12053
12290
  return size;
12054
12291
  }
@@ -12078,7 +12315,7 @@ async function plistString(plistPath, keyPath, timeoutMs, signal) {
12078
12315
  }
12079
12316
  }
12080
12317
  async function archiveApplicationProperties(archivePath, timeoutMs, signal) {
12081
- const plistPath = join8(archivePath, "Info.plist");
12318
+ const plistPath = join9(archivePath, "Info.plist");
12082
12319
  const read = (key) => plistString(plistPath, `ApplicationProperties.${key}`, timeoutMs, signal);
12083
12320
  const [bundleIdentifier2, bundleShortVersion, bundleVersion, applicationPath] = await Promise.all([
12084
12321
  read("CFBundleIdentifier"),
@@ -12237,9 +12474,9 @@ function normalizeCoverage(value) {
12237
12474
  };
12238
12475
  }
12239
12476
  async function writeJsonReport(input, kind, timeoutMs, signal) {
12240
- const resultBundle = join8(input.artifactDirectory, "result.xcresult");
12477
+ const resultBundle = join9(input.artifactDirectory, "result.xcresult");
12241
12478
  const filename = kind === "TEST_RESULTS" ? "test-results.json" : "code-coverage.json";
12242
- const destination = join8(input.artifactDirectory, filename);
12479
+ const destination = join9(input.artifactDirectory, filename);
12243
12480
  const temporary = `${destination}.tmp-${randomUUID3()}`;
12244
12481
  try {
12245
12482
  if (!await pathExists(resultBundle)) {
@@ -12283,7 +12520,7 @@ async function writeJsonReport(input, kind, timeoutMs, signal) {
12283
12520
  error: null
12284
12521
  };
12285
12522
  } catch (error) {
12286
- await rm6(temporary, { force: true });
12523
+ await rm7(temporary, { force: true });
12287
12524
  return {
12288
12525
  kind,
12289
12526
  status: "FAILED",
@@ -12374,7 +12611,7 @@ async function snapshotCoverageChanges(input, folder, timeoutMs, signal) {
12374
12611
  const types = changeTypesFromStatus(status2.stdout);
12375
12612
  for (const path of untracked.stdout.split("\0").filter(Boolean)) {
12376
12613
  try {
12377
- const contents = await readFile5(join8(folder, path));
12614
+ const contents = await readFile5(join9(folder, path));
12378
12615
  if (contents.includes(0)) continue;
12379
12616
  const lineCount = contents.length ? contents.toString("utf8").split("\n").length - (contents.toString("utf8").endsWith("\n") ? 1 : 0) : 0;
12380
12617
  lines.set(
@@ -12408,7 +12645,7 @@ async function addChangedCoverage(report, changes, input, folder, timeoutMs, sig
12408
12645
  let covered = 0;
12409
12646
  let executable = 0;
12410
12647
  if (coveragePath && change.lines.length) {
12411
- const temporary2 = join8(
12648
+ const temporary2 = join9(
12412
12649
  input.artifactDirectory,
12413
12650
  `.changed-coverage-${randomUUID3()}.json`
12414
12651
  );
@@ -12449,7 +12686,7 @@ async function addChangedCoverage(report, changes, input, folder, timeoutMs, sig
12449
12686
  }
12450
12687
  }
12451
12688
  } finally {
12452
- await rm6(temporary2, { force: true });
12689
+ await rm7(temporary2, { force: true });
12453
12690
  }
12454
12691
  }
12455
12692
  changedCoveredLines += covered;
@@ -12469,9 +12706,9 @@ async function addChangedCoverage(report, changes, input, folder, timeoutMs, sig
12469
12706
  changedLineCoverage: changedExecutableLines ? changedCoveredLines / changedExecutableLines : null
12470
12707
  };
12471
12708
  const data = { ...report.data, changedFiles };
12472
- const destination = join8(input.artifactDirectory, "worktree-coverage.json");
12709
+ const destination = join9(input.artifactDirectory, "worktree-coverage.json");
12473
12710
  const temporary = `${destination}.tmp-${randomUUID3()}`;
12474
- await writeFile4(temporary, JSON.stringify({ summary, data }, null, 2), {
12711
+ await writeFile5(temporary, JSON.stringify({ summary, data }, null, 2), {
12475
12712
  mode: 384
12476
12713
  });
12477
12714
  await rename3(temporary, destination);
@@ -12523,7 +12760,7 @@ async function findFiles(root, predicate, limit = 20) {
12523
12760
  }
12524
12761
  for (const entry of entries) {
12525
12762
  if (entry.isSymbolicLink()) continue;
12526
- const path = join8(current, entry.name);
12763
+ const path = join9(current, entry.name);
12527
12764
  if (entry.isDirectory()) queue.push(path);
12528
12765
  else if (entry.isFile() && predicate(entry.name)) results.push(path);
12529
12766
  if (results.length >= limit) break;
@@ -12533,7 +12770,7 @@ async function findFiles(root, predicate, limit = 20) {
12533
12770
  }
12534
12771
  async function captureArtifacts(input, folder, signal, includeProducts = true) {
12535
12772
  const artifacts = [];
12536
- const resultBundle = join8(input.artifactDirectory, "result.xcresult");
12773
+ const resultBundle = join9(input.artifactDirectory, "result.xcresult");
12537
12774
  if (await pathExists(resultBundle)) {
12538
12775
  const coverageProbe = await command(
12539
12776
  "xcrun",
@@ -12560,7 +12797,7 @@ async function captureArtifacts(input, folder, signal, includeProducts = true) {
12560
12797
  );
12561
12798
  }
12562
12799
  if (!includeProducts) return artifacts;
12563
- const archivePath = join8(input.artifactDirectory, "archive.xcarchive");
12800
+ const archivePath = join9(input.artifactDirectory, "archive.xcarchive");
12564
12801
  if (await pathExists(archivePath)) {
12565
12802
  artifacts.push(
12566
12803
  await artifact(input.artifactDirectory, "ARCHIVE", archivePath)
@@ -12583,12 +12820,12 @@ async function captureArtifacts(input, folder, signal, includeProducts = true) {
12583
12820
  if (apps.length === 1) {
12584
12821
  const settings = apps[0].buildSettings;
12585
12822
  const productName = settings.FULL_PRODUCT_NAME ?? settings.WRAPPER_NAME;
12586
- const source = settings.TARGET_BUILD_DIR && productName ? join8(settings.TARGET_BUILD_DIR, productName) : null;
12823
+ const source = settings.TARGET_BUILD_DIR && productName ? join9(settings.TARGET_BUILD_DIR, productName) : null;
12587
12824
  if (source && await pathExists(source)) {
12588
- const productDirectory = join8(input.artifactDirectory, "products");
12589
- const destination = join8(productDirectory, basename3(source));
12825
+ const productDirectory = join9(input.artifactDirectory, "products");
12826
+ const destination = join9(productDirectory, basename3(source));
12590
12827
  await mkdir4(productDirectory, { recursive: true, mode: 448 });
12591
- await rm6(destination, { recursive: true, force: true });
12828
+ await rm7(destination, { recursive: true, force: true });
12592
12829
  await cp(source, destination, {
12593
12830
  recursive: true,
12594
12831
  preserveTimestamps: true
@@ -12603,7 +12840,7 @@ async function captureArtifacts(input, folder, signal, includeProducts = true) {
12603
12840
  }
12604
12841
  }
12605
12842
  if (input.action === "BUILD_FOR_TESTING") {
12606
- const testDirectory = join8(
12843
+ const testDirectory = join9(
12607
12844
  input.artifactDirectory,
12608
12845
  "test-products.xctestproducts"
12609
12846
  );
@@ -12654,11 +12891,11 @@ var runIosBuild = async (payload, timeoutMs, signal, onLog, context) => {
12654
12891
  signal
12655
12892
  );
12656
12893
  await mkdir4(input.artifactDirectory, { recursive: true, mode: 448 });
12657
- const rawLog = join8(input.artifactDirectory, "build.log");
12894
+ const rawLog = join9(input.artifactDirectory, "build.log");
12658
12895
  const logger = new BuildLogger(input.buildId, context, rawLog, process.env);
12659
12896
  try {
12660
12897
  const scriptExecutions = [];
12661
- const contextPath = join8(input.artifactDirectory, "context.json");
12898
+ const contextPath = join9(input.artifactDirectory, "context.json");
12662
12899
  const baseHookContext = {
12663
12900
  buildId: input.buildId,
12664
12901
  branch: input.branch ?? null,
@@ -12917,7 +13154,7 @@ var generateIosBuildReport = async (payload, timeoutMs, signal, onLog) => {
12917
13154
  var deleteIosBuild = async (payload, _timeoutMs, signal, onLog) => {
12918
13155
  const input = parseBuildDeletePayload(payload);
12919
13156
  if (signal.aborted) return { ...successfulProcess6, cancelled: true };
12920
- await rm6(input.artifactDirectory, { recursive: true, force: true });
13157
+ await rm7(input.artifactDirectory, { recursive: true, force: true });
12921
13158
  await onLog({
12922
13159
  sequence: 0,
12923
13160
  stream: "SYSTEM",
@@ -12931,8 +13168,8 @@ var downloadIosBuildArtifact = async (payload, timeoutMs, signal, onLog, context
12931
13168
  if (!context?.uploadBuildArtifact) {
12932
13169
  throw new Error("This agent cannot upload build artifacts");
12933
13170
  }
12934
- const root = await realpath4(input.artifactDirectory);
12935
- const target2 = await realpath4(
13171
+ const root = await realpath5(input.artifactDirectory);
13172
+ const target2 = await realpath5(
12936
13173
  containedPath2(root, input.artifactRelativePath)
12937
13174
  );
12938
13175
  const difference = relative4(root, target2);
@@ -12946,8 +13183,8 @@ var downloadIosBuildArtifact = async (payload, timeoutMs, signal, onLog, context
12946
13183
  let temporaryArchive = null;
12947
13184
  try {
12948
13185
  if (information.isDirectory()) {
12949
- temporaryArchive = join8(
12950
- tmpdir3(),
13186
+ temporaryArchive = join9(
13187
+ tmpdir4(),
12951
13188
  `ade-build-artifact-${randomUUID3()}.tar.gz`
12952
13189
  );
12953
13190
  requireSuccess2(
@@ -12980,7 +13217,7 @@ var downloadIosBuildArtifact = async (payload, timeoutMs, signal, onLog, context
12980
13217
  return successfulProcess6;
12981
13218
  } finally {
12982
13219
  if (temporaryArchive) {
12983
- await rm6(temporaryArchive, { force: true });
13220
+ await rm7(temporaryArchive, { force: true });
12984
13221
  }
12985
13222
  }
12986
13223
  };
@@ -13016,24 +13253,24 @@ var deployIosBuild = async (payload, timeoutMs, signal, _onLog, context) => {
13016
13253
  if (!await pathExists(appPath) || !appPath.endsWith(".app")) {
13017
13254
  throw new Error("Runnable app artifact is missing");
13018
13255
  }
13019
- const deploymentsDirectory = join8(input.artifactDirectory, "deployments");
13256
+ const deploymentsDirectory = join9(input.artifactDirectory, "deployments");
13020
13257
  await mkdir4(deploymentsDirectory, { recursive: true, mode: 448 });
13021
13258
  const logger = new BuildLogger(
13022
13259
  input.buildId,
13023
13260
  context,
13024
- join8(deploymentsDirectory, "deployments.log"),
13261
+ join9(deploymentsDirectory, "deployments.log"),
13025
13262
  process.env
13026
13263
  );
13027
13264
  try {
13028
13265
  const outcomes = [];
13029
13266
  for (const deployment of input.deployments) {
13030
- const directory = join8(
13267
+ const directory = join9(
13031
13268
  input.artifactDirectory,
13032
13269
  "deployments",
13033
13270
  deployment.id
13034
13271
  );
13035
13272
  await mkdir4(directory, { recursive: true, mode: 448 });
13036
- const logPath = join8(directory, "deployment.log");
13273
+ const logPath = join9(directory, "deployment.log");
13037
13274
  const started = Date.now();
13038
13275
  let failure = null;
13039
13276
  try {
@@ -13248,15 +13485,15 @@ var exportIosArchive = async (payload, timeoutMs, signal, _onLog, context) => {
13248
13485
  if (!await pathExists(archivePath) || !archivePath.endsWith(".xcarchive")) {
13249
13486
  throw new Error("Archive artifact is missing");
13250
13487
  }
13251
- const exportDirectory = join8(
13488
+ const exportDirectory = join9(
13252
13489
  input.artifactDirectory,
13253
13490
  "exports",
13254
13491
  input.exportId
13255
13492
  );
13256
13493
  await mkdir4(exportDirectory, { recursive: true, mode: 448 });
13257
- const plistPath = join8(exportDirectory, "ExportOptions.plist");
13258
- const logPath = join8(exportDirectory, "export.log");
13259
- await writeFile4(plistPath, exportPlist(input.settings), { mode: 384 });
13494
+ const plistPath = join9(exportDirectory, "ExportOptions.plist");
13495
+ const logPath = join9(exportDirectory, "export.log");
13496
+ await writeFile5(plistPath, exportPlist(input.settings), { mode: 384 });
13260
13497
  const logger = new BuildLogger(input.buildId, context, logPath, process.env);
13261
13498
  try {
13262
13499
  const result = await runLoggedCommand({
@@ -13322,18 +13559,18 @@ var success = {
13322
13559
  };
13323
13560
  var runWorkflowTerminal = async (payloadValue, timeoutMs, signal, onLog, context) => {
13324
13561
  const payload = parseWorkflowTerminalPayload(payloadValue);
13325
- const cwd = await realpath5(payload.cwd);
13562
+ const cwd = await realpath6(payload.cwd);
13326
13563
  const information = await stat7(cwd);
13327
13564
  if (!information.isDirectory())
13328
13565
  throw new Error("Workflow working directory is not a directory");
13329
- const directory = await mkdtemp4(join9(tmpdir4(), "aide-workflow-"));
13566
+ const directory = await mkdtemp5(join10(tmpdir5(), "aide-workflow-"));
13330
13567
  const extension2 = payload.interpreter === "NODE" ? "mjs" : "sh";
13331
- const scriptPath = join9(directory, `step.${extension2}`);
13332
- const sessionPath = join9(directory, "session.json");
13568
+ const scriptPath = join10(directory, `step.${extension2}`);
13569
+ const sessionPath = join10(directory, "session.json");
13333
13570
  try {
13334
- await writeFile5(scriptPath, `${payload.script}
13571
+ await writeFile6(scriptPath, `${payload.script}
13335
13572
  `, { mode: 384 });
13336
- await writeFile5(
13573
+ await writeFile6(
13337
13574
  sessionPath,
13338
13575
  `${JSON.stringify(payload.sessionData, null, 2)}
13339
13576
  `,
@@ -13377,13 +13614,13 @@ var runWorkflowTerminal = async (payloadValue, timeoutMs, signal, onLog, context
13377
13614
  }
13378
13615
  return { ...result, sessionData };
13379
13616
  } finally {
13380
- await rm7(directory, { recursive: true, force: true });
13617
+ await rm8(directory, { recursive: true, force: true });
13381
13618
  }
13382
13619
  };
13383
13620
  var runWorkflowGitCheckpoint = async (payloadValue, _timeoutMs, signal) => {
13384
13621
  const payload = parseWorkflowGitCheckpointPayload(payloadValue);
13385
13622
  if (signal.aborted) return { ...success, exitCode: null, cancelled: true };
13386
- const cwd = await realpath5(payload.cwd);
13623
+ const cwd = await realpath6(payload.cwd);
13387
13624
  if (payload.operation === "CAPTURE") {
13388
13625
  const checkpoint2 = await captureGitCheckpoint(
13389
13626
  cwd,
@@ -13420,10 +13657,10 @@ var runWorkflowGitCheckpoint = async (payloadValue, _timeoutMs, signal) => {
13420
13657
 
13421
13658
  // src/handlers/worktrees.ts
13422
13659
  import { createWriteStream as createWriteStream2, watch } from "node:fs";
13423
- import { mkdtemp as mkdtemp5, open as open2, readFile as readFile7, realpath as realpath6, rm as rm8, stat as stat8 } from "node:fs/promises";
13424
- import { tmpdir as tmpdir5 } from "node:os";
13425
- import { basename as basename4, dirname as dirname6, join as join10, relative as relative5 } from "node:path";
13426
- import { spawn as spawn5 } from "node:child_process";
13660
+ import { mkdtemp as mkdtemp6, open as open2, readFile as readFile7, realpath as realpath7, rm as rm9, stat as stat8 } from "node:fs/promises";
13661
+ import { tmpdir as tmpdir6 } from "node:os";
13662
+ import { basename as basename4, dirname as dirname6, isAbsolute as isAbsolute5, join as join11, relative as relative5 } from "node:path";
13663
+ import { spawn as spawn6 } from "node:child_process";
13427
13664
  var successfulProcess7 = {
13428
13665
  exitCode: 0,
13429
13666
  signal: null,
@@ -13446,9 +13683,13 @@ function statusChangeState(value) {
13446
13683
  const entries = value.split("\0").filter(Boolean);
13447
13684
  let hasStagedChanges = false;
13448
13685
  let hasUnstagedChanges = false;
13686
+ let hasConflicts = false;
13449
13687
  for (let index = 0; index < entries.length; index += 1) {
13450
13688
  const code = entries[index].slice(0, 2);
13451
13689
  const untracked = code === "??";
13690
+ if (["DD", "AU", "UD", "UA", "DU", "AA", "UU"].includes(code)) {
13691
+ hasConflicts = true;
13692
+ }
13452
13693
  if (!untracked && code[0] !== " " && code[0] !== "?" && code[0] !== "!") {
13453
13694
  hasStagedChanges = true;
13454
13695
  }
@@ -13459,7 +13700,50 @@ function statusChangeState(value) {
13459
13700
  index += 1;
13460
13701
  }
13461
13702
  }
13462
- return { hasStagedChanges, hasUnstagedChanges };
13703
+ return { hasStagedChanges, hasUnstagedChanges, hasConflicts };
13704
+ }
13705
+ async function rebaseInProgress(folder, timeoutMs, signal) {
13706
+ for (const name of ["rebase-merge", "rebase-apply"]) {
13707
+ const pathResult = await git3(
13708
+ folder,
13709
+ ["rev-parse", "--git-path", name],
13710
+ timeoutMs,
13711
+ signal
13712
+ );
13713
+ if (pathResult.exitCode !== 0) continue;
13714
+ const candidate = pathResult.stdout.trim();
13715
+ if (!candidate) continue;
13716
+ try {
13717
+ await stat8(isAbsolute5(candidate) ? candidate : join11(folder, candidate));
13718
+ return true;
13719
+ } catch {
13720
+ }
13721
+ }
13722
+ return false;
13723
+ }
13724
+ async function rebaseBranch(folder, timeoutMs, signal) {
13725
+ for (const name of ["rebase-merge/head-name", "rebase-apply/head-name"]) {
13726
+ const pathResult = await git3(
13727
+ folder,
13728
+ ["rev-parse", "--git-path", name],
13729
+ timeoutMs,
13730
+ signal
13731
+ );
13732
+ if (pathResult.exitCode !== 0) continue;
13733
+ const candidate = pathResult.stdout.trim();
13734
+ if (!candidate) continue;
13735
+ try {
13736
+ const headName = (await readFile7(
13737
+ isAbsolute5(candidate) ? candidate : join11(folder, candidate),
13738
+ "utf8"
13739
+ )).trim();
13740
+ if (headName.startsWith("refs/heads/")) {
13741
+ return headName.slice("refs/heads/".length);
13742
+ }
13743
+ } catch {
13744
+ }
13745
+ }
13746
+ return null;
13463
13747
  }
13464
13748
  function closeWorktreeWatch(entry) {
13465
13749
  if (entry.timer) clearTimeout(entry.timer);
@@ -13483,39 +13767,44 @@ async function flushWorktreeActivity(entry) {
13483
13767
  entry.pending = false;
13484
13768
  try {
13485
13769
  const signal = new AbortController().signal;
13486
- const [status2, branchResult, headResult, codeStateHash] = await Promise.all(
13487
- [
13488
- git3(
13489
- entry.folder,
13490
- [
13491
- "--no-optional-locks",
13492
- "status",
13493
- "--porcelain=v1",
13494
- "-z",
13495
- "--untracked-files=all"
13496
- ],
13497
- entry.timeoutMs,
13498
- signal
13499
- ),
13500
- git3(
13501
- entry.folder,
13502
- ["symbolic-ref", "--short", "-q", "HEAD"],
13503
- entry.timeoutMs,
13504
- signal
13505
- ),
13506
- git3(entry.folder, ["rev-parse", "HEAD"], entry.timeoutMs, signal),
13507
- worktreeCodeStateHash(entry.folder, entry.timeoutMs, signal)
13508
- ]
13509
- );
13510
- const branch = branchResult.exitCode === 0 ? branchResult.stdout.trim() : null;
13770
+ const [status2, branchResult, headResult, codeStateHash, rebasing] = await Promise.all([
13771
+ git3(
13772
+ entry.folder,
13773
+ [
13774
+ "--no-optional-locks",
13775
+ "status",
13776
+ "--porcelain=v1",
13777
+ "-z",
13778
+ "--untracked-files=all"
13779
+ ],
13780
+ entry.timeoutMs,
13781
+ signal
13782
+ ),
13783
+ git3(
13784
+ entry.folder,
13785
+ ["symbolic-ref", "--short", "-q", "HEAD"],
13786
+ entry.timeoutMs,
13787
+ signal
13788
+ ),
13789
+ git3(entry.folder, ["rev-parse", "HEAD"], entry.timeoutMs, signal),
13790
+ worktreeCodeStateHash(entry.folder, entry.timeoutMs, signal),
13791
+ rebaseInProgress(entry.folder, entry.timeoutMs, signal)
13792
+ ]);
13793
+ const symbolicBranch = branchResult.exitCode === 0 ? branchResult.stdout.trim() : null;
13794
+ const branch = symbolicBranch ?? (rebasing ? await rebaseBranch(entry.folder, entry.timeoutMs, signal) : null);
13511
13795
  const headSha = headResult.exitCode === 0 ? headResult.stdout.trim() : null;
13512
13796
  const headIdentity = headSha ? `${branch ?? ""}\0${headSha}` : null;
13513
- const changes = status2.exitCode === 0 ? statusChangeState(status2.stdout) : { hasStagedChanges: false, hasUnstagedChanges: false };
13797
+ const changes = status2.exitCode === 0 ? statusChangeState(status2.stdout) : {
13798
+ hasStagedChanges: false,
13799
+ hasUnstagedChanges: false,
13800
+ hasConflicts: false
13801
+ };
13514
13802
  const report = {
13515
13803
  codebaseId: entry.codebaseId,
13516
13804
  gitDirectory: entry.gitDirectory,
13517
13805
  codeStateHash,
13518
13806
  ...changes,
13807
+ rebaseInProgress: rebasing,
13519
13808
  pushStatus: await worktreePushStatus(
13520
13809
  entry.folder,
13521
13810
  branch,
@@ -13628,7 +13917,7 @@ async function gitDirectory(folder, timeoutMs, signal) {
13628
13917
  ),
13629
13918
  "Could not resolve the worktree Git directory"
13630
13919
  );
13631
- return realpath6(result.stdout.trim());
13920
+ return realpath7(result.stdout.trim());
13632
13921
  }
13633
13922
  async function origin(folder, timeoutMs, signal) {
13634
13923
  const result = requireSuccess3(
@@ -13638,7 +13927,7 @@ async function origin(folder, timeoutMs, signal) {
13638
13927
  return normalizeGitOrigin(result.stdout.trim()).canonicalOrigin;
13639
13928
  }
13640
13929
  async function validateWorktree2(input, timeoutMs, signal) {
13641
- const folder = await realpath6(input.folder);
13930
+ const folder = await realpath7(input.folder);
13642
13931
  if (!(await stat8(folder)).isDirectory())
13643
13932
  throw new Error("Worktree is missing");
13644
13933
  const observedGitDirectory = await gitDirectory(folder, timeoutMs, signal);
@@ -13685,10 +13974,15 @@ async function worktreePushStatus(folder, branch, changes, timeoutMs, signal) {
13685
13974
  async function inspectWorktreeItem(folderValue2, rootFolder, baseBranch, primary, timeoutMs, signal) {
13686
13975
  const checkedAt = (/* @__PURE__ */ new Date()).toISOString();
13687
13976
  try {
13688
- const folder = await realpath6(folderValue2);
13689
- const [gitDir, branchResult, headResult, statusResult] = await Promise.all([
13977
+ const folder = await realpath7(folderValue2);
13978
+ const [gitDir, branchResult, headResult, statusResult, rebasing] = await Promise.all([
13690
13979
  gitDirectory(folder, timeoutMs, signal),
13691
- git3(folder, ["symbolic-ref", "--short", "-q", "HEAD"], timeoutMs, signal),
13980
+ git3(
13981
+ folder,
13982
+ ["symbolic-ref", "--short", "-q", "HEAD"],
13983
+ timeoutMs,
13984
+ signal
13985
+ ),
13692
13986
  git3(folder, ["rev-parse", "HEAD"], timeoutMs, signal),
13693
13987
  git3(
13694
13988
  folder,
@@ -13701,9 +13995,11 @@ async function inspectWorktreeItem(folderValue2, rootFolder, baseBranch, primary
13701
13995
  ],
13702
13996
  timeoutMs,
13703
13997
  signal
13704
- )
13998
+ ),
13999
+ rebaseInProgress(folder, timeoutMs, signal)
13705
14000
  ]);
13706
- const branch = branchResult.exitCode === 0 ? branchResult.stdout.trim() : null;
14001
+ const symbolicBranch = branchResult.exitCode === 0 ? branchResult.stdout.trim() : null;
14002
+ const branch = symbolicBranch ?? (rebasing ? await rebaseBranch(folder, timeoutMs, signal) : null);
13707
14003
  const upstreamResult = branch ? await git3(
13708
14004
  folder,
13709
14005
  ["rev-parse", "--abbrev-ref", "--symbolic-full-name", "@{upstream}"],
@@ -13719,7 +14015,11 @@ async function inspectWorktreeItem(folderValue2, rootFolder, baseBranch, primary
13719
14015
  signal
13720
14016
  ) : { ahead: null, behind: null };
13721
14017
  const syncState = worktreeSyncState(branch, upstream, upstreamCounts);
13722
- const changes = statusResult.exitCode === 0 ? statusChangeState(statusResult.stdout) : { hasStagedChanges: false, hasUnstagedChanges: false };
14018
+ const changes = statusResult.exitCode === 0 ? statusChangeState(statusResult.stdout) : {
14019
+ hasStagedChanges: false,
14020
+ hasUnstagedChanges: false,
14021
+ hasConflicts: false
14022
+ };
13723
14023
  return {
13724
14024
  gitDirectory: gitDir,
13725
14025
  folder,
@@ -13735,6 +14035,7 @@ async function inspectWorktreeItem(folderValue2, rootFolder, baseBranch, primary
13735
14035
  baseAhead: baseCounts.ahead,
13736
14036
  baseBehind: baseCounts.behind,
13737
14037
  ...changes,
14038
+ rebaseInProgress: rebasing,
13738
14039
  pushStatus: await worktreePushStatus(
13739
14040
  folder,
13740
14041
  branch,
@@ -13763,6 +14064,8 @@ async function inspectWorktreeItem(folderValue2, rootFolder, baseBranch, primary
13763
14064
  baseBehind: null,
13764
14065
  hasStagedChanges: false,
13765
14066
  hasUnstagedChanges: false,
14067
+ rebaseInProgress: false,
14068
+ hasConflicts: false,
13766
14069
  pushStatus: "UNKNOWN",
13767
14070
  availability: "ERROR",
13768
14071
  error: cleanError3(error),
@@ -13771,7 +14074,7 @@ async function inspectWorktreeItem(folderValue2, rootFolder, baseBranch, primary
13771
14074
  }
13772
14075
  }
13773
14076
  async function discoverWorktrees(rootFolderValue, baseOverrides, knownDefaultBranch, timeoutMs, signal) {
13774
- const rootFolder = await realpath6(rootFolderValue);
14077
+ const rootFolder = await realpath7(rootFolderValue);
13775
14078
  const list = requireSuccess3(
13776
14079
  await git3(
13777
14080
  rootFolder,
@@ -14077,7 +14380,7 @@ async function comparisonSides(input, folder, timeoutMs, signal) {
14077
14380
  if (!input.path) return { before: null, after: null };
14078
14381
  const path = input.path;
14079
14382
  const previousPath = input.previousPath ?? path;
14080
- const currentPath = join10(folder, path);
14383
+ const currentPath = join11(folder, path);
14081
14384
  if (input.scope === "UNTRACKED") {
14082
14385
  return { before: null, after: { kind: "FILE", path: currentPath } };
14083
14386
  }
@@ -14160,7 +14463,7 @@ async function availableSide(side, folder, timeoutMs, signal) {
14160
14463
  return gitObjectExists(folder, side.specification, timeoutMs, signal);
14161
14464
  }
14162
14465
  try {
14163
- const resolved = await realpath6(side.path);
14466
+ const resolved = await realpath7(side.path);
14164
14467
  const difference = relative5(folder, resolved);
14165
14468
  return difference !== ".." && !difference.startsWith("../") && (await stat8(resolved)).isFile();
14166
14469
  } catch {
@@ -14233,7 +14536,7 @@ async function inspectRequestedDiff(input, folder, timeoutMs, signal) {
14233
14536
  let patch;
14234
14537
  if (input.scope === "UNTRACKED") {
14235
14538
  const bounded = await readBoundedFile(
14236
- join10(folder, input.path),
14539
+ join11(folder, input.path),
14237
14540
  MAX_DIFF_BYTES
14238
14541
  );
14239
14542
  const contents = bounded.contents;
@@ -14337,7 +14640,7 @@ function imageContentType(path) {
14337
14640
  }
14338
14641
  async function writeGitObject(folder, specification, destination, timeoutMs, signal) {
14339
14642
  await new Promise((resolvePromise, rejectPromise) => {
14340
- const child = spawn5(
14643
+ const child = spawn6(
14341
14644
  "git",
14342
14645
  ["-C", folder, "cat-file", "blob", specification],
14343
14646
  { stdio: ["ignore", "pipe", "pipe"] }
@@ -14403,7 +14706,7 @@ var downloadWorktreeDiffAsset = async (payload, timeoutMs, signal, _onLog, conte
14403
14706
  let temporaryDirectory = null;
14404
14707
  try {
14405
14708
  if (selected.kind === "FILE") {
14406
- uploadPath = await realpath6(selected.path);
14709
+ uploadPath = await realpath7(selected.path);
14407
14710
  const difference = relative5(folder, uploadPath);
14408
14711
  if (difference === ".." || difference.startsWith("../")) {
14409
14712
  throw new Error("Diff image resolves outside the worktree");
@@ -14421,8 +14724,8 @@ var downloadWorktreeDiffAsset = async (payload, timeoutMs, signal, _onLog, conte
14421
14724
  if (!/^\d+$/.test(size) || Number(size) > 20 * 1024 * 1024) {
14422
14725
  throw new Error("Diff image exceeds the 20 MiB limit");
14423
14726
  }
14424
- temporaryDirectory = await mkdtemp5(join10(tmpdir5(), "ade-diff-image-"));
14425
- uploadPath = join10(temporaryDirectory, basename4(input.path));
14727
+ temporaryDirectory = await mkdtemp6(join11(tmpdir6(), "ade-diff-image-"));
14728
+ uploadPath = join11(temporaryDirectory, basename4(input.path));
14426
14729
  await writeGitObject(
14427
14730
  folder,
14428
14731
  selected.specification,
@@ -14444,7 +14747,7 @@ var downloadWorktreeDiffAsset = async (payload, timeoutMs, signal, _onLog, conte
14444
14747
  return successfulProcess7;
14445
14748
  } finally {
14446
14749
  if (temporaryDirectory) {
14447
- await rm8(temporaryDirectory, { recursive: true, force: true });
14750
+ await rm9(temporaryDirectory, { recursive: true, force: true });
14448
14751
  }
14449
14752
  }
14450
14753
  };
@@ -14621,7 +14924,7 @@ async function chooseNewBranch(folder, candidates, allowedCurrentBranch, timeout
14621
14924
  throw new Error("Every generated ticket branch name is already taken");
14622
14925
  }
14623
14926
  async function validateBranchRoot(input, timeoutMs, signal) {
14624
- const rootFolder = await realpath6(input.rootFolder);
14927
+ const rootFolder = await realpath7(input.rootFolder);
14625
14928
  if (!(await stat8(rootFolder)).isDirectory()) {
14626
14929
  throw new Error("Base repository is missing");
14627
14930
  }
@@ -14685,7 +14988,7 @@ var branchWorktree = async (payload, timeoutMs, signal) => {
14685
14988
  timeoutMs,
14686
14989
  signal
14687
14990
  ) : input.candidates[0];
14688
- const targetFolder = input.action === "CREATE" ? join10(
14991
+ const targetFolder = input.action === "CREATE" ? join11(
14689
14992
  dirname6(rootFolder),
14690
14993
  `${basename4(rootFolder)}-${branch.replaceAll("/", "-")}`
14691
14994
  ) : changeFolder;
@@ -14925,7 +15228,7 @@ var checkoutMovedWorktree = async (payload, timeoutMs, signal) => {
14925
15228
  `Branch ${input.branch} is already checked out in ${occupiedFolder}`
14926
15229
  );
14927
15230
  }
14928
- targetFolder = join10(
15231
+ targetFolder = join11(
14929
15232
  dirname6(rootFolder),
14930
15233
  `${basename4(rootFolder)}-${input.branch.replaceAll("/", "-")}`
14931
15234
  );
@@ -14976,7 +15279,7 @@ var checkoutMovedWorktree = async (payload, timeoutMs, signal) => {
14976
15279
  const targetBranch = await currentBranch(targetFolder, timeoutMs, signal);
14977
15280
  const targetChanges = await statusState(targetFolder, timeoutMs, signal);
14978
15281
  if (occupiedFolder) {
14979
- const occupied = await realpath6(occupiedFolder);
15282
+ const occupied = await realpath7(occupiedFolder);
14980
15283
  if (occupied !== targetFolder) {
14981
15284
  throw new Error(
14982
15285
  `Branch ${input.branch} is checked out in another destination worktree`
@@ -15090,7 +15393,7 @@ var checkoutMovedWorktree = async (payload, timeoutMs, signal) => {
15090
15393
  };
15091
15394
  var deleteWorktree = async (payload, timeoutMs, signal) => {
15092
15395
  const input = worktreeDeleteJobPayload(payload);
15093
- const rootFolder = await realpath6(input.rootFolder);
15396
+ const rootFolder = await realpath7(input.rootFolder);
15094
15397
  if (!(await stat8(rootFolder)).isDirectory()) {
15095
15398
  throw new Error("Base repository is missing");
15096
15399
  }
@@ -15239,12 +15542,59 @@ var operateWorktree = async (payload, timeoutMs, signal) => {
15239
15542
  signal
15240
15543
  );
15241
15544
  if (rebase.exitCode !== 0) {
15242
- await git3(folder, ["rebase", "--abort"], timeoutMs, signal);
15545
+ const status2 = await git3(
15546
+ folder,
15547
+ ["status", "--porcelain=v1", "-z"],
15548
+ timeoutMs,
15549
+ signal
15550
+ );
15551
+ const conflicts = status2.exitCode === 0 && statusChangeState(status2.stdout).hasConflicts;
15552
+ if (!(conflicts && await rebaseInProgress(folder, timeoutMs, signal))) {
15553
+ await git3(folder, ["rebase", "--abort"], timeoutMs, signal);
15554
+ }
15243
15555
  throw new Error(cleanError3(rebase.stderr || "Rebase failed"));
15244
15556
  }
15245
15557
  await runGit(["push", "--force-with-lease"], "Sync push failed");
15246
15558
  break;
15247
15559
  }
15560
+ case "REBASE": {
15561
+ if (!branch) throw new Error("Rebase requires a branch");
15562
+ if (!input.baseBranch) throw new Error("Rebase requires a base branch");
15563
+ const statusResult = await runGit(
15564
+ ["status", "--porcelain"],
15565
+ "Could not inspect worktree changes"
15566
+ );
15567
+ if (statusResult.stdout.trim())
15568
+ throw new Error("Stash or commit changes before rebasing");
15569
+ await runGit(["fetch", "origin"], "Could not fetch origin");
15570
+ const rebase = await git3(
15571
+ folder,
15572
+ ["rebase", `refs/remotes/origin/${input.baseBranch}`],
15573
+ timeoutMs,
15574
+ signal
15575
+ );
15576
+ if (rebase.exitCode !== 0) {
15577
+ const status2 = await git3(
15578
+ folder,
15579
+ ["status", "--porcelain=v1", "-z"],
15580
+ timeoutMs,
15581
+ signal
15582
+ );
15583
+ const conflicts = status2.exitCode === 0 && statusChangeState(status2.stdout).hasConflicts;
15584
+ if (!(conflicts && await rebaseInProgress(folder, timeoutMs, signal))) {
15585
+ await git3(folder, ["rebase", "--abort"], timeoutMs, signal);
15586
+ }
15587
+ throw new Error(cleanError3(rebase.stderr || "Rebase failed"));
15588
+ }
15589
+ break;
15590
+ }
15591
+ case "CANCEL_REBASE": {
15592
+ if (!await rebaseInProgress(folder, timeoutMs, signal)) {
15593
+ throw new Error("No rebase is in progress");
15594
+ }
15595
+ await runGit(["rebase", "--abort"], "Could not cancel rebase");
15596
+ break;
15597
+ }
15248
15598
  case "PUSH":
15249
15599
  if (!branch) throw new Error("Push requires a branch");
15250
15600
  await runGit(
@@ -15286,7 +15636,7 @@ var operateWorktree = async (payload, timeoutMs, signal) => {
15286
15636
 
15287
15637
  // src/handlers/index.ts
15288
15638
  var handlers = {
15289
- "cloudflared.runTunnel": runCloudflared,
15639
+ [COMMAND_RUN_JOB_KIND]: runCommand,
15290
15640
  [CCUSAGE_REPORT_JOB_KIND]: runCcusage,
15291
15641
  [BUILD_DATA_SCAN_JOB_KIND]: scanBuildData,
15292
15642
  [BUILD_DATA_SIZE_JOB_KIND]: sizeBuildData,
@@ -15374,7 +15724,9 @@ var JobExecutor = class {
15374
15724
  this.running.set(job.id, { controller, task });
15375
15725
  }
15376
15726
  cancel(jobId) {
15377
- this.running.get(jobId)?.controller.abort();
15727
+ const running = this.running.get(jobId);
15728
+ running?.controller.abort();
15729
+ return Boolean(running);
15378
15730
  }
15379
15731
  async cancelAll() {
15380
15732
  this.stopping = true;
@@ -15409,10 +15761,11 @@ var JobExecutor = class {
15409
15761
  {
15410
15762
  reportWorktreeActivity: (input) => this.client.reportWorktreeActivity(input),
15411
15763
  reportBuildProgress: (input) => this.client.reportBuildProgress(input),
15412
- appendBuildLogs: (buildId, events) => this.client.appendBuildLogs(buildId, events),
15764
+ appendBuildLogChunks: (buildId, chunks) => this.client.appendBuildLogChunks(buildId, chunks),
15413
15765
  uploadBuildArtifact: (input) => this.client.uploadBuildArtifact(input),
15414
15766
  claimSigningSecretTransfer: (transferId) => this.client.claimSigningSecretTransfer(transferId),
15415
- claimWorkflowJobSecrets: () => this.client.claimWorkflowJobSecrets(claimed.id)
15767
+ claimWorkflowJobSecrets: () => this.client.claimWorkflowJobSecrets(claimed.id),
15768
+ appendCommandOutput: (attemptId, chunks) => this.client.appendCommandOutput(claimed.id, attemptId, chunks)
15416
15769
  }
15417
15770
  );
15418
15771
  const codebaseId = claimed.payload && typeof claimed.payload === "object" && !Array.isArray(claimed.payload) && typeof claimed.payload.codebaseId === "string" ? String(claimed.payload.codebaseId) : null;
@@ -15588,8 +15941,8 @@ var CodebaseMonitor = class {
15588
15941
 
15589
15942
  // src/runs/run-manager.ts
15590
15943
  import { execFile as execFile4 } from "node:child_process";
15591
- import { mkdir as mkdir6, rm as rm12 } from "node:fs/promises";
15592
- import { dirname as dirname8, join as join14 } from "node:path";
15944
+ import { mkdir as mkdir6, rm as rm13 } from "node:fs/promises";
15945
+ import { dirname as dirname8, join as join15 } from "node:path";
15593
15946
  import { promisify as promisify4 } from "node:util";
15594
15947
 
15595
15948
  // src/runs/journal.ts
@@ -15599,10 +15952,10 @@ import {
15599
15952
  mkdir as mkdir5,
15600
15953
  readFile as readFile8,
15601
15954
  rename as rename4,
15602
- rm as rm9,
15603
- writeFile as writeFile6
15955
+ rm as rm10,
15956
+ writeFile as writeFile7
15604
15957
  } from "node:fs/promises";
15605
- import { dirname as dirname7, join as join11 } from "node:path";
15958
+ import { dirname as dirname7, join as join12 } from "node:path";
15606
15959
  var RunJournal = class {
15607
15960
  constructor(runId, attemptId) {
15608
15961
  this.runId = runId;
@@ -15621,13 +15974,13 @@ var RunJournal = class {
15621
15974
  this.attemptId = attemptId;
15622
15975
  }
15623
15976
  get directory() {
15624
- return join11(dirname7(configPath()), "runs", this.runId);
15977
+ return join12(dirname7(configPath()), "runs", this.runId);
15625
15978
  }
15626
15979
  get eventsPath() {
15627
- return join11(this.directory, "events.jsonl");
15980
+ return join12(this.directory, "events.jsonl");
15628
15981
  }
15629
15982
  get statePath() {
15630
- return join11(this.directory, "state.json");
15983
+ return join12(this.directory, "state.json");
15631
15984
  }
15632
15985
  async load() {
15633
15986
  if (this.loaded) return;
@@ -15728,10 +16081,10 @@ var RunJournal = class {
15728
16081
  const operation = this.saving.then(async () => {
15729
16082
  const temporary = `${this.statePath}.${process.pid}.${randomUUID4()}.tmp`;
15730
16083
  try {
15731
- await writeFile6(temporary, contents, { mode: 384 });
16084
+ await writeFile7(temporary, contents, { mode: 384 });
15732
16085
  await rename4(temporary, this.statePath);
15733
16086
  } catch (error) {
15734
- await rm9(temporary, { force: true }).catch(() => void 0);
16087
+ await rm10(temporary, { force: true }).catch(() => void 0);
15735
16088
  throw error;
15736
16089
  }
15737
16090
  });
@@ -24905,7 +25258,7 @@ function Yy(e) {
24905
25258
  var l = {};
24906
25259
  lt(l, { xid: () => u9, void: () => I9, uuidv7: () => n9, uuidv6: () => r9, uuidv4: () => t9, uuid: () => e9, url: () => o9, uppercase: () => Fl, unknown: () => Ke, union: () => $e, undefined: () => C9, ulid: () => l9, uint64: () => A9, uint32: () => w9, tuple: () => L9, trim: () => Wl, treeifyError: () => Yd, transform: () => jv, toUpperCase: () => Zl, toLowerCase: () => Kl, toJSONSchema: () => Js, templateLiteral: () => q9, symbol: () => O9, superRefine: () => ER, success: () => B9, stringbool: () => W9, stringFormat: () => x9, string: () => k, strictObject: () => N9, startsWith: () => Hl, size: () => $l, setErrorMap: () => J9, set: () => $9, safeParseAsync: () => gv, safeParse: () => mv, registry: () => hl, regexes: () => wo, regex: () => jl, refine: () => SR, record: () => je, readonly: () => hR, property: () => iv, promise: () => G9, prettifyError: () => Xd, preprocess: () => Km, prefault: () => lR, positive: () => tv, pipe: () => Fm, partialRecord: () => M9, parseAsync: () => fv, parse: () => dv, overwrite: () => Vn, optional: () => Ve, object: () => G, number: () => Ce, nullish: () => F9, nullable: () => zm, null: () => Bm, normalize: () => Vl, nonpositive: () => nv, nonoptional: () => uR, nonnegative: () => ov, never: () => Hm, negative: () => rv, nativeEnum: () => j9, nanoid: () => s9, nan: () => H9, multipleOf: () => wi, minSize: () => Ti, minLength: () => Ao, mime: () => Gl, maxSize: () => Ws, maxLength: () => Ks, map: () => U9, lte: () => Ur, lt: () => qn, lowercase: () => zl, looseObject: () => Bt, locales: () => Gs, literal: () => Z, length: () => Zs, lazy: () => bR, ksuid: () => p9, keyof: () => D9, jwt: () => b9, json: () => K9, iso: () => Ys, ipv6: () => f9, ipv4: () => d9, intersection: () => ru, int64: () => k9, int32: () => E9, int: () => hv, instanceof: () => V9, includes: () => Bl, guid: () => QZ, gte: () => ar, gt: () => Gn, globalRegistry: () => sr, getErrorMap: () => Y9, function: () => Dm, formatError: () => js, float64: () => S9, float32: () => v9, flattenError: () => $s, file: () => z9, enum: () => Jt, endsWith: () => ql, emoji: () => i9, email: () => XZ, e164: () => y9, discriminatedUnion: () => Vm, date: () => P9, custom: () => Hv, cuid2: () => c9, cuid: () => a9, core: () => Qr, config: () => ut, coerce: () => qv, clone: () => Ft, cidrv6: () => g9, cidrv4: () => m9, check: () => vR, catch: () => fR, boolean: () => ht, bigint: () => T9, base64url: () => _9, base64: () => h9, array: () => he, any: () => R9, _default: () => aR, _ZodString: () => _v, ZodXID: () => Tv, ZodVoid: () => JC, ZodUnknown: () => KC, ZodUnion: () => Mv, ZodUndefined: () => GC, ZodUUID: () => Wn, ZodURL: () => bv, ZodULID: () => wv, ZodType: () => de, ZodTuple: () => eR, ZodTransform: () => $v, ZodTemplateLiteral: () => _R, ZodSymbol: () => qC, ZodSuccess: () => pR, ZodStringFormat: () => Ge, ZodString: () => Xl, ZodSet: () => rR, ZodRecord: () => Uv, ZodRealError: () => Xs, ZodReadonly: () => gR, ZodPromise: () => xR, ZodPrefault: () => cR, ZodPipe: () => Bv, ZodOptional: () => zv, ZodObject: () => Gm, ZodNumberFormat: () => Qs, ZodNumber: () => Ql, ZodNullable: () => iR, ZodNull: () => VC, ZodNonOptional: () => Fv, ZodNever: () => ZC, ZodNanoID: () => vv, ZodNaN: () => mR, ZodMap: () => tR, ZodLiteral: () => nR, ZodLazy: () => yR, ZodKSUID: () => kv, ZodJWT: () => Nv, ZodIssueCode: () => Z9, ZodIntersection: () => QC, ZodISOTime: () => Um, ZodISODuration: () => $m, ZodISODateTime: () => Lm, ZodISODate: () => Mm, ZodIPv6: () => Ov, ZodIPv4: () => Av, ZodGUID: () => jm, ZodFile: () => oR, ZodError: () => JZ, ZodEnum: () => Yl, ZodEmoji: () => xv, ZodEmail: () => yv, ZodE164: () => Dv, ZodDiscriminatedUnion: () => XC, ZodDefault: () => sR, ZodDate: () => qm, ZodCustomStringFormat: () => HC, ZodCustom: () => Wm, ZodCatch: () => dR, ZodCUID2: () => Ev, ZodCUID: () => Sv, ZodCIDRv6: () => Rv, ZodCIDRv4: () => Cv, ZodBoolean: () => eu, ZodBigIntFormat: () => Lv, ZodBigInt: () => tu, ZodBase64URL: () => Pv, ZodBase64: () => Iv, ZodArray: () => YC, ZodAny: () => WC, TimePrecision: () => lm, NEVER: () => Kd, $output: () => sm, $input: () => am, $brand: () => Zd });
24907
25260
  var Qr = {};
24908
- lt(Qr, { version: () => tx, util: () => M, treeifyError: () => Yd, toJSONSchema: () => Js, toDotPath: () => yC, safeParseAsync: () => Eo, safeParse: () => So, registry: () => hl, regexes: () => wo, prettifyError: () => Xd, parseAsync: () => xi, parse: () => bi, locales: () => Gs, isValidJWT: () => MC, isValidBase64URL: () => LC, isValidBase64: () => ax, globalRegistry: () => sr, globalConfig: () => tl, function: () => Dm, formatError: () => js, flattenError: () => $s, config: () => ut, clone: () => Ft, _xid: () => Ol, _void: () => Tm, _uuidv7: () => vl, _uuidv6: () => xl, _uuidv4: () => bl, _uuid: () => yl, _url: () => Sl, _uppercase: () => Fl, _unknown: () => Ei, _union: () => OZ, _undefined: () => vm, _ulid: () => Al, _uint64: () => bm, _uint32: () => gm, _tuple: () => sv, _trim: () => Wl, _transform: () => UZ, _toUpperCase: () => Zl, _toLowerCase: () => Kl, _templateLiteral: () => VZ, _symbol: () => xm, _success: () => BZ, _stringbool: () => Im, _stringFormat: () => Pm, _string: () => cm, _startsWith: () => Hl, _size: () => $l, _set: () => DZ, _safeParseAsync: () => rf, _safeParse: () => tf, _regex: () => jl, _refine: () => Rm, _record: () => IZ, _readonly: () => GZ, _property: () => iv, _promise: () => KZ, _positive: () => tv, _pipe: () => qZ, _parseAsync: () => ef, _parse: () => Qd, _overwrite: () => Vn, _optional: () => $Z, _number: () => um, _nullable: () => jZ, _null: () => Sm, _normalize: () => Vl, _nonpositive: () => nv, _nonoptional: () => FZ, _nonnegative: () => ov, _never: () => wm, _negative: () => rv, _nativeEnum: () => LZ, _nanoid: () => wl, _nan: () => Am, _multipleOf: () => wi, _minSize: () => Ti, _minLength: () => Ao, _min: () => ar, _mime: () => Gl, _maxSize: () => Ws, _maxLength: () => Ks, _max: () => Ur, _map: () => PZ, _lte: () => Ur, _lt: () => qn, _lowercase: () => zl, _literal: () => MZ, _length: () => Zs, _lazy: () => WZ, _ksuid: () => Cl, _jwt: () => Ul, _isoTime: () => Zx, _isoDuration: () => Jx, _isoDateTime: () => Wx, _isoDate: () => Kx, _ipv6: () => Il, _ipv4: () => Rl, _intersection: () => RZ, _int64: () => ym, _int32: () => mm, _int: () => pm, _includes: () => Bl, _guid: () => Vs, _gte: () => ar, _gt: () => Gn, _float64: () => fm, _float32: () => dm, _file: () => Om, _enum: () => NZ, _endsWith: () => ql, _emoji: () => El, _email: () => _l, _e164: () => Ml, _discriminatedUnion: () => CZ, _default: () => zZ, _date: () => km, _custom: () => Cm, _cuid2: () => kl, _cuid: () => Tl, _coercedString: () => Vx, _coercedNumber: () => Yx, _coercedDate: () => ev, _coercedBoolean: () => Xx, _coercedBigint: () => Qx, _cidrv6: () => Dl, _cidrv4: () => Pl, _catch: () => HZ, _boolean: () => hm, _bigint: () => _m, _base64url: () => Ll, _base64: () => Nl, _array: () => Jl, _any: () => Em, TimePrecision: () => lm, NEVER: () => Kd, JSONSchemaGenerator: () => Nm, JSONSchema: () => zC, Doc: () => af, $output: () => sm, $input: () => am, $constructor: () => S, $brand: () => Zd, $ZodXID: () => bf, $ZodVoid: () => Uf, $ZodUnknown: () => Si, $ZodUnion: () => fl, $ZodUndefined: () => Df, $ZodUUID: () => pf, $ZodURL: () => ff, $ZodULID: () => yf, $ZodType: () => ie, $ZodTuple: () => ko, $ZodTransform: () => Hs, $ZodTemplateLiteral: () => rm10, $ZodSymbol: () => Pf, $ZodSuccess: () => Xf, $ZodStringFormat: () => Ue, $ZodString: () => To, $ZodSet: () => Hf, $ZodRegistry: () => gl, $ZodRecord: () => Ff, $ZodRealError: () => Us, $ZodReadonly: () => tm, $ZodPromise: () => nm, $ZodPrefault: () => Jf, $ZodPipe: () => qs, $ZodOptional: () => Wf, $ZodObject: () => dl, $ZodNumberFormat: () => Rf, $ZodNumber: () => ul, $ZodNullable: () => Kf, $ZodNull: () => Nf, $ZodNonOptional: () => Yf, $ZodNever: () => Mf, $ZodNanoID: () => gf, $ZodNaN: () => em, $ZodMap: () => Bf, $ZodLiteral: () => Gf, $ZodLazy: () => om, $ZodKSUID: () => xf, $ZodJWT: () => Of, $ZodIntersection: () => zf, $ZodISOTime: () => ix, $ZodISODuration: () => sx, $ZodISODateTime: () => nx, $ZodISODate: () => ox, $ZodIPv6: () => Sf, $ZodIPv4: () => vf, $ZodGUID: () => uf, $ZodFunction: () => av, $ZodFile: () => Vf, $ZodError: () => ll, $ZodEnum: () => qf, $ZodEmoji: () => mf, $ZodEmail: () => df, $ZodE164: () => Af, $ZodDiscriminatedUnion: () => jf, $ZodDefault: () => Zf, $ZodDate: () => $f, $ZodCustomStringFormat: () => Cf, $ZodCustom: () => im, $ZodCheckUpperCase: () => Kb, $ZodCheckStringFormat: () => zs, $ZodCheckStartsWith: () => Jb, $ZodCheckSizeEquals: () => Bb, $ZodCheckRegex: () => Vb, $ZodCheckProperty: () => Xb, $ZodCheckOverwrite: () => ex, $ZodCheckNumberFormat: () => $b, $ZodCheckMultipleOf: () => Ub, $ZodCheckMinSize: () => Fb, $ZodCheckMinLength: () => qb, $ZodCheckMimeType: () => Qb, $ZodCheckMaxSize: () => zb, $ZodCheckMaxLength: () => Hb, $ZodCheckLowerCase: () => Wb, $ZodCheckLessThan: () => of, $ZodCheckLengthEquals: () => Gb, $ZodCheckIncludes: () => Zb, $ZodCheckGreaterThan: () => sf, $ZodCheckEndsWith: () => Yb, $ZodCheckBigIntFormat: () => jb, $ZodCheck: () => Xe, $ZodCatch: () => Qf, $ZodCUID2: () => _f, $ZodCUID: () => hf, $ZodCIDRv6: () => wf, $ZodCIDRv4: () => Ef, $ZodBoolean: () => Fs, $ZodBigIntFormat: () => If, $ZodBigInt: () => pl, $ZodBase64URL: () => kf, $ZodBase64: () => Tf, $ZodAsyncError: () => Bn, $ZodArray: () => Bs, $ZodAny: () => Lf });
25261
+ lt(Qr, { version: () => tx, util: () => M, treeifyError: () => Yd, toJSONSchema: () => Js, toDotPath: () => yC, safeParseAsync: () => Eo, safeParse: () => So, registry: () => hl, regexes: () => wo, prettifyError: () => Xd, parseAsync: () => xi, parse: () => bi, locales: () => Gs, isValidJWT: () => MC, isValidBase64URL: () => LC, isValidBase64: () => ax, globalRegistry: () => sr, globalConfig: () => tl, function: () => Dm, formatError: () => js, flattenError: () => $s, config: () => ut, clone: () => Ft, _xid: () => Ol, _void: () => Tm, _uuidv7: () => vl, _uuidv6: () => xl, _uuidv4: () => bl, _uuid: () => yl, _url: () => Sl, _uppercase: () => Fl, _unknown: () => Ei, _union: () => OZ, _undefined: () => vm, _ulid: () => Al, _uint64: () => bm, _uint32: () => gm, _tuple: () => sv, _trim: () => Wl, _transform: () => UZ, _toUpperCase: () => Zl, _toLowerCase: () => Kl, _templateLiteral: () => VZ, _symbol: () => xm, _success: () => BZ, _stringbool: () => Im, _stringFormat: () => Pm, _string: () => cm, _startsWith: () => Hl, _size: () => $l, _set: () => DZ, _safeParseAsync: () => rf, _safeParse: () => tf, _regex: () => jl, _refine: () => Rm, _record: () => IZ, _readonly: () => GZ, _property: () => iv, _promise: () => KZ, _positive: () => tv, _pipe: () => qZ, _parseAsync: () => ef, _parse: () => Qd, _overwrite: () => Vn, _optional: () => $Z, _number: () => um, _nullable: () => jZ, _null: () => Sm, _normalize: () => Vl, _nonpositive: () => nv, _nonoptional: () => FZ, _nonnegative: () => ov, _never: () => wm, _negative: () => rv, _nativeEnum: () => LZ, _nanoid: () => wl, _nan: () => Am, _multipleOf: () => wi, _minSize: () => Ti, _minLength: () => Ao, _min: () => ar, _mime: () => Gl, _maxSize: () => Ws, _maxLength: () => Ks, _max: () => Ur, _map: () => PZ, _lte: () => Ur, _lt: () => qn, _lowercase: () => zl, _literal: () => MZ, _length: () => Zs, _lazy: () => WZ, _ksuid: () => Cl, _jwt: () => Ul, _isoTime: () => Zx, _isoDuration: () => Jx, _isoDateTime: () => Wx, _isoDate: () => Kx, _ipv6: () => Il, _ipv4: () => Rl, _intersection: () => RZ, _int64: () => ym, _int32: () => mm, _int: () => pm, _includes: () => Bl, _guid: () => Vs, _gte: () => ar, _gt: () => Gn, _float64: () => fm, _float32: () => dm, _file: () => Om, _enum: () => NZ, _endsWith: () => ql, _emoji: () => El, _email: () => _l, _e164: () => Ml, _discriminatedUnion: () => CZ, _default: () => zZ, _date: () => km, _custom: () => Cm, _cuid2: () => kl, _cuid: () => Tl, _coercedString: () => Vx, _coercedNumber: () => Yx, _coercedDate: () => ev, _coercedBoolean: () => Xx, _coercedBigint: () => Qx, _cidrv6: () => Dl, _cidrv4: () => Pl, _catch: () => HZ, _boolean: () => hm, _bigint: () => _m, _base64url: () => Ll, _base64: () => Nl, _array: () => Jl, _any: () => Em, TimePrecision: () => lm, NEVER: () => Kd, JSONSchemaGenerator: () => Nm, JSONSchema: () => zC, Doc: () => af, $output: () => sm, $input: () => am, $constructor: () => S, $brand: () => Zd, $ZodXID: () => bf, $ZodVoid: () => Uf, $ZodUnknown: () => Si, $ZodUnion: () => fl, $ZodUndefined: () => Df, $ZodUUID: () => pf, $ZodURL: () => ff, $ZodULID: () => yf, $ZodType: () => ie, $ZodTuple: () => ko, $ZodTransform: () => Hs, $ZodTemplateLiteral: () => rm11, $ZodSymbol: () => Pf, $ZodSuccess: () => Xf, $ZodStringFormat: () => Ue, $ZodString: () => To, $ZodSet: () => Hf, $ZodRegistry: () => gl, $ZodRecord: () => Ff, $ZodRealError: () => Us, $ZodReadonly: () => tm, $ZodPromise: () => nm, $ZodPrefault: () => Jf, $ZodPipe: () => qs, $ZodOptional: () => Wf, $ZodObject: () => dl, $ZodNumberFormat: () => Rf, $ZodNumber: () => ul, $ZodNullable: () => Kf, $ZodNull: () => Nf, $ZodNonOptional: () => Yf, $ZodNever: () => Mf, $ZodNanoID: () => gf, $ZodNaN: () => em, $ZodMap: () => Bf, $ZodLiteral: () => Gf, $ZodLazy: () => om, $ZodKSUID: () => xf, $ZodJWT: () => Of, $ZodIntersection: () => zf, $ZodISOTime: () => ix, $ZodISODuration: () => sx, $ZodISODateTime: () => nx, $ZodISODate: () => ox, $ZodIPv6: () => Sf, $ZodIPv4: () => vf, $ZodGUID: () => uf, $ZodFunction: () => av, $ZodFile: () => Vf, $ZodError: () => ll, $ZodEnum: () => qf, $ZodEmoji: () => mf, $ZodEmail: () => df, $ZodE164: () => Af, $ZodDiscriminatedUnion: () => jf, $ZodDefault: () => Zf, $ZodDate: () => $f, $ZodCustomStringFormat: () => Cf, $ZodCustom: () => im, $ZodCheckUpperCase: () => Kb, $ZodCheckStringFormat: () => zs, $ZodCheckStartsWith: () => Jb, $ZodCheckSizeEquals: () => Bb, $ZodCheckRegex: () => Vb, $ZodCheckProperty: () => Xb, $ZodCheckOverwrite: () => ex, $ZodCheckNumberFormat: () => $b, $ZodCheckMultipleOf: () => Ub, $ZodCheckMinSize: () => Fb, $ZodCheckMinLength: () => qb, $ZodCheckMimeType: () => Qb, $ZodCheckMaxSize: () => zb, $ZodCheckMaxLength: () => Hb, $ZodCheckLowerCase: () => Wb, $ZodCheckLessThan: () => of, $ZodCheckLengthEquals: () => Gb, $ZodCheckIncludes: () => Zb, $ZodCheckGreaterThan: () => sf, $ZodCheckEndsWith: () => Yb, $ZodCheckBigIntFormat: () => jb, $ZodCheck: () => Xe, $ZodCatch: () => Qf, $ZodCUID2: () => _f, $ZodCUID: () => hf, $ZodCIDRv6: () => wf, $ZodCIDRv4: () => Ef, $ZodBoolean: () => Fs, $ZodBigIntFormat: () => If, $ZodBigInt: () => pl, $ZodBase64URL: () => kf, $ZodBase64: () => Tf, $ZodAsyncError: () => Bn, $ZodArray: () => Bs, $ZodAny: () => Lf });
24909
25262
  var Kd = Object.freeze({ status: "aborted" });
24910
25263
  function S(e, t, r) {
24911
25264
  function n(a, c) {
@@ -26453,7 +26806,7 @@ var tm = S("$ZodReadonly", (e, t) => {
26453
26806
  function DC(e) {
26454
26807
  return e.value = Object.freeze(e.value), e;
26455
26808
  }
26456
- var rm10 = S("$ZodTemplateLiteral", (e, t) => {
26809
+ var rm11 = S("$ZodTemplateLiteral", (e, t) => {
26457
26810
  ie.init(e, t);
26458
26811
  let r = [];
26459
26812
  for (let n of t.parts) if (n instanceof ie) {
@@ -30260,7 +30613,7 @@ function hR(e) {
30260
30613
  return new gR({ type: "readonly", innerType: e });
30261
30614
  }
30262
30615
  var _R = S("ZodTemplateLiteral", (e, t) => {
30263
- rm10.init(e, t), de.init(e, t);
30616
+ rm11.init(e, t), de.init(e, t);
30264
30617
  });
30265
30618
  function q9(e, t) {
30266
30619
  return new _R({ type: "template_literal", parts: e, ...M.normalizeParams(t) });
@@ -41879,11 +42232,11 @@ var ClaudeAdapter = class {
41879
42232
  // src/runs/codex-adapter.ts
41880
42233
  import {
41881
42234
  execFile as execFile3,
41882
- spawn as spawn6
42235
+ spawn as spawn7
41883
42236
  } from "node:child_process";
41884
- import { mkdtemp as mkdtemp6, rm as rm11, writeFile as writeFile7 } from "node:fs/promises";
41885
- import { tmpdir as tmpdir6 } from "node:os";
41886
- import { join as join13 } from "node:path";
42237
+ import { mkdtemp as mkdtemp7, rm as rm12, writeFile as writeFile8 } from "node:fs/promises";
42238
+ import { tmpdir as tmpdir7 } from "node:os";
42239
+ import { join as join14 } from "node:path";
41887
42240
  import { createInterface } from "node:readline";
41888
42241
  import { promisify as promisify3 } from "node:util";
41889
42242
  var SUPPORTED_CODEX_APP_SERVER_MINORS = ["0.144", "0.145"];
@@ -41941,7 +42294,7 @@ var CodexAppServer = class {
41941
42294
  async start() {
41942
42295
  const modelCatalogPath = await this.createBundledModelCatalog();
41943
42296
  const modelCatalogDirectory = this.modelCatalogDirectory;
41944
- const child = spawn6("codex", codexAppServerArgs(modelCatalogPath), {
42297
+ const child = spawn7("codex", codexAppServerArgs(modelCatalogPath), {
41945
42298
  stdio: ["pipe", "pipe", "pipe"],
41946
42299
  env: process.env
41947
42300
  });
@@ -42010,7 +42363,7 @@ var CodexAppServer = class {
42010
42363
  }
42011
42364
  }
42012
42365
  async createBundledModelCatalog() {
42013
- const directory = await mkdtemp6(join13(tmpdir6(), "aide-codex-models-"));
42366
+ const directory = await mkdtemp7(join14(tmpdir7(), "aide-codex-models-"));
42014
42367
  try {
42015
42368
  const { stdout } = await execFileAsync2(
42016
42369
  "codex",
@@ -42020,12 +42373,12 @@ var CodexAppServer = class {
42020
42373
  maxBuffer: 16 * 1024 * 1024
42021
42374
  }
42022
42375
  );
42023
- const catalogPath = join13(directory, "models.json");
42024
- await writeFile7(catalogPath, stdout, "utf8");
42376
+ const catalogPath = join14(directory, "models.json");
42377
+ await writeFile8(catalogPath, stdout, "utf8");
42025
42378
  this.modelCatalogDirectory = directory;
42026
42379
  return catalogPath;
42027
42380
  } catch (error) {
42028
- await rm11(directory, { recursive: true, force: true }).catch(
42381
+ await rm12(directory, { recursive: true, force: true }).catch(
42029
42382
  () => void 0
42030
42383
  );
42031
42384
  throw error;
@@ -42036,7 +42389,7 @@ var CodexAppServer = class {
42036
42389
  if (this.modelCatalogDirectory === directory) {
42037
42390
  this.modelCatalogDirectory = void 0;
42038
42391
  }
42039
- await rm11(directory, { recursive: true, force: true }).catch(
42392
+ await rm12(directory, { recursive: true, force: true }).catch(
42040
42393
  () => void 0
42041
42394
  );
42042
42395
  }
@@ -48714,7 +49067,7 @@ var RunManager = class {
48714
49067
  5
48715
49068
  );
48716
49069
  await this.completeCommand(command3.id, "SUCCEEDED");
48717
- await rm12(join14(dirname8(configPath()), "runs", run.id, "attachments"), {
49070
+ await rm13(join15(dirname8(configPath()), "runs", run.id, "attachments"), {
48718
49071
  recursive: true,
48719
49072
  force: true
48720
49073
  }).catch(() => void 0);
@@ -48895,7 +49248,7 @@ var RunManager = class {
48895
49248
  this.active.delete(run.id);
48896
49249
  this.interruptionRequests.delete(run.id);
48897
49250
  this.executingCommands.delete(command3.id);
48898
- await rm12(join14(dirname8(configPath()), "runs", run.id, "attachments"), {
49251
+ await rm13(join15(dirname8(configPath()), "runs", run.id, "attachments"), {
48899
49252
  recursive: true,
48900
49253
  force: true
48901
49254
  }).catch(() => void 0);
@@ -49123,11 +49476,11 @@ var RunManager = class {
49123
49476
  }
49124
49477
  async stageAttachments(runId, attachments) {
49125
49478
  if (!attachments.length) return [];
49126
- const directory = join14(dirname8(configPath()), "runs", runId, "attachments");
49479
+ const directory = join15(dirname8(configPath()), "runs", runId, "attachments");
49127
49480
  await mkdir6(directory, { recursive: true, mode: 448 });
49128
49481
  return Promise.all(
49129
49482
  attachments.map(async (attachment) => {
49130
- const path = join14(
49483
+ const path = join15(
49131
49484
  directory,
49132
49485
  `${attachment.id}-${safeFilename(attachment.filename)}`
49133
49486
  );
@@ -49284,6 +49637,12 @@ async function runAgent(config, signal) {
49284
49637
  executor.cancel(job.id);
49285
49638
  return;
49286
49639
  }
49640
+ if (job.status === "CANCELLING") {
49641
+ if (!executor.cancel(job.id)) {
49642
+ await client2.completeJob(job.id, "CANCELLED");
49643
+ }
49644
+ return;
49645
+ }
49287
49646
  if (job.status !== "RUNNING" || !recoverInterrupted && !interruptedJobs.has(job.id)) {
49288
49647
  executor.execute(job);
49289
49648
  return;
@@ -49584,7 +49943,6 @@ function redactedRequestHeaders(headers) {
49584
49943
  }
49585
49944
 
49586
49945
  // src/index.ts
49587
- var execFileAsync4 = promisify5(execFile5);
49588
49946
  function flags(args) {
49589
49947
  const result = {};
49590
49948
  const headerValues = [];
@@ -49687,22 +50045,6 @@ async function doctor() {
49687
50045
  detail: error instanceof Error ? error.message : String(error)
49688
50046
  });
49689
50047
  }
49690
- try {
49691
- const { stdout, stderr } = await execFileAsync4("cloudflared", [
49692
- "--version"
49693
- ]);
49694
- checks.push({
49695
- check: "cloudflared",
49696
- ok: true,
49697
- detail: (stdout || stderr).trim()
49698
- });
49699
- } catch (error) {
49700
- checks.push({
49701
- check: "cloudflared",
49702
- ok: false,
49703
- detail: error instanceof Error ? error.message : String(error)
49704
- });
49705
- }
49706
50048
  for (const check of checks)
49707
50049
  console.log(
49708
50050
  `${check.ok ? "PASS" : "FAIL"} ${check.check}: ${check.detail}`
@@ -49720,21 +50062,26 @@ async function main() {
49720
50062
  if (command3 === "doctor") return doctor();
49721
50063
  if (command3 === "run" || command3 === "dev") {
49722
50064
  const controller = new AbortController();
49723
- process.once("SIGINT", () => controller.abort());
49724
- process.once("SIGTERM", () => controller.abort());
49725
- if (command3 === "dev") {
49726
- const options = flags(args).values;
49727
- const server = options.server ?? process.env.CONTROL_AGENT_DEV_SERVER ?? `http://127.0.0.1:${process.env.PORT ?? "3000"}`;
49728
- return runDevelopmentAgent(
49729
- {
49730
- server,
49731
- websocketServer: options["websocket-server"] ?? process.env.CONTROL_AGENT_DEV_WEBSOCKET_SERVER ?? process.env.NEXT_PUBLIC_AGENT_WS_URL,
49732
- name: options.name
49733
- },
49734
- controller.signal
49735
- );
50065
+ const stop2 = () => controller.abort();
50066
+ const shutdownSignals = ["SIGINT", "SIGTERM", "SIGHUP"];
50067
+ for (const signal of shutdownSignals) process.once(signal, stop2);
50068
+ try {
50069
+ if (command3 === "dev") {
50070
+ const options = flags(args).values;
50071
+ const server = options.server ?? process.env.CONTROL_AGENT_DEV_SERVER ?? `http://127.0.0.1:${process.env.PORT ?? "3000"}`;
50072
+ return await runDevelopmentAgent(
50073
+ {
50074
+ server,
50075
+ websocketServer: options["websocket-server"] ?? process.env.CONTROL_AGENT_DEV_WEBSOCKET_SERVER ?? process.env.NEXT_PUBLIC_AGENT_WS_URL,
50076
+ name: options.name
50077
+ },
50078
+ controller.signal
50079
+ );
50080
+ }
50081
+ return await runAgent(await loadConfig(), controller.signal);
50082
+ } finally {
50083
+ for (const signal of shutdownSignals) process.off(signal, stop2);
49736
50084
  }
49737
- return runAgent(await loadConfig(), controller.signal);
49738
50085
  }
49739
50086
  throw new Error(`Unknown command: ${command3}`);
49740
50087
  }