@alan-ai-hq/agent-manager-darwin-arm64 0.1.151 → 0.1.153

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.
Files changed (3) hide show
  1. package/alan-agent.cjs +812 -1015
  2. package/alan-holder.cjs +284 -769
  3. package/package.json +1 -1
package/alan-agent.cjs CHANGED
@@ -19801,6 +19801,10 @@ var init_agent_context = __esm({
19801
19801
  installCommand: external_exports.string().max(8192).nullable(),
19802
19802
  startCommand: external_exports.string().max(8192).nullable(),
19803
19803
  imageBuildId: external_exports.guid().nullable(),
19804
+ /** The repository whose `.alan/` the image build reads; a branch build swaps only its branch. */
19805
+ primaryRepository: machinePathSchema.optional(),
19806
+ /** Where install steps and the start command run: the repository, or the workspace with several. */
19807
+ setupDirectory: machinePathSchema.optional(),
19804
19808
  /** The newest build when it is not the one sessions boot from. */
19805
19809
  pendingBuild: agentContextBuildSchema.optional(),
19806
19810
  /** Saved variable names; values never leave the API. */
@@ -20371,7 +20375,7 @@ var init_run_context = __esm({
20371
20375
  });
20372
20376
 
20373
20377
  // ../shared/dist/runtime-v2/desired-state.js
20374
- var repoLocalPathSchema, requestedCheckoutSchema, runSpecSchema, desiredRunSchema, desiredStateSchema;
20378
+ var repoLocalPathSchema, requestedCheckoutSchema, runSpecSchema, desiredRunSchema, pendingUploadSchema, desiredStateSchema;
20375
20379
  var init_desired_state = __esm({
20376
20380
  "../shared/dist/runtime-v2/desired-state.js"() {
20377
20381
  "use strict";
@@ -20441,10 +20445,17 @@ var init_desired_state = __esm({
20441
20445
  spec: runSpecSchema,
20442
20446
  abortRequested: external_exports.boolean()
20443
20447
  });
20448
+ pendingUploadSchema = external_exports.object({
20449
+ runId: runIdSchema,
20450
+ conversationId: conversationIdSchema,
20451
+ admittedOffset: external_exports.number().int().nonnegative()
20452
+ });
20444
20453
  desiredStateSchema = external_exports.object({
20445
20454
  runs: external_exports.array(desiredRunSchema),
20446
20455
  /** The machine's saved workspaces; replaces the previous server list on every read. */
20447
- approvedWorkspacePaths: external_exports.array(machinePathSchema).max(2e3).optional()
20456
+ approvedWorkspacePaths: external_exports.array(machinePathSchema).max(2e3).optional(),
20457
+ /** Absent from an older server: the runtime then uploads only on its own doorbell. */
20458
+ pendingUploads: external_exports.array(pendingUploadSchema).optional()
20448
20459
  });
20449
20460
  }
20450
20461
  });
@@ -22720,7 +22731,7 @@ function plan(command, args, options) {
22720
22731
  function captureOutput(command, args, options) {
22721
22732
  const launch = plan(command, args, options);
22722
22733
  if (launch === void 0) return Promise.resolve(NEVER_STARTED);
22723
- return new Promise((resolve14) => {
22734
+ return new Promise((resolve13) => {
22724
22735
  (0, import_child_process.execFile)(
22725
22736
  launch.file,
22726
22737
  [...launch.args],
@@ -22734,7 +22745,7 @@ function captureOutput(command, args, options) {
22734
22745
  },
22735
22746
  (error61, stdout, stderr) => {
22736
22747
  const code = error61 && typeof error61.code === "number" ? error61.code : error61 ? void 0 : 0;
22737
- resolve14({ stdout, stderr, exitCode: code });
22748
+ resolve13({ stdout, stderr, exitCode: code });
22738
22749
  }
22739
22750
  );
22740
22751
  });
@@ -22776,18 +22787,18 @@ function decode3(bytes, start, end) {
22776
22787
  }
22777
22788
  async function linuxStartTicks(pid) {
22778
22789
  try {
22779
- const stat23 = await (0, import_promises9.readFile)(`/proc/${pid}/stat`, "utf8");
22780
- const fields = stat23.slice(stat23.lastIndexOf(")") + 2).split(" ");
22790
+ const stat22 = await (0, import_promises9.readFile)(`/proc/${pid}/stat`, "utf8");
22791
+ const fields = stat22.slice(stat22.lastIndexOf(")") + 2).split(" ");
22781
22792
  return fields[19];
22782
22793
  } catch {
22783
22794
  return void 0;
22784
22795
  }
22785
22796
  }
22786
22797
  function psStartTime(pid) {
22787
- return new Promise((resolve14) => {
22798
+ return new Promise((resolve13) => {
22788
22799
  (0, import_child_process2.execFile)("ps", ["-o", "lstart=", "-p", String(pid)], { timeout: 2e3 }, (error61, stdout) => {
22789
22800
  const text3 = stdout.trim();
22790
- resolve14(error61 || !text3 ? void 0 : text3);
22801
+ resolve13(error61 || !text3 ? void 0 : text3);
22791
22802
  });
22792
22803
  });
22793
22804
  }
@@ -22816,12 +22827,12 @@ function parseProcessList(text3) {
22816
22827
  }
22817
22828
  function listProcesses(platform3 = process.platform) {
22818
22829
  if (platform3 === "win32") return Promise.resolve([]);
22819
- return new Promise((resolve14) => {
22830
+ return new Promise((resolve13) => {
22820
22831
  (0, import_child_process3.execFile)(
22821
22832
  "ps",
22822
22833
  ["-A", "-o", "pid=,ppid=,pgid=,lstart="],
22823
22834
  { timeout: 5e3, maxBuffer: 8 * 1024 * 1024 },
22824
- (error61, stdout) => resolve14(error61 ? [] : parseProcessList(stdout))
22835
+ (error61, stdout) => resolve13(error61 ? [] : parseProcessList(stdout))
22825
22836
  );
22826
22837
  });
22827
22838
  }
@@ -22861,11 +22872,11 @@ async function taskkill(pid, options) {
22861
22872
  stdio: "ignore",
22862
22873
  windowsHide: true
22863
22874
  });
22864
- const exited = new Promise((resolve14) => {
22865
- killer.once("error", (error210) => resolve14(error210));
22875
+ const exited = new Promise((resolve13) => {
22876
+ killer.once("error", (error210) => resolve13(error210));
22866
22877
  killer.once(
22867
22878
  "exit",
22868
- (code, signal) => resolve14(code === 0 ? void 0 : new Error(`taskkill failed: exit ${code}, signal ${signal}`))
22879
+ (code, signal) => resolve13(code === 0 ? void 0 : new Error(`taskkill failed: exit ${code}, signal ${signal}`))
22869
22880
  );
22870
22881
  });
22871
22882
  const timedOut = clock.sleep(options.timeoutMs ?? DEFAULT_TASKKILL_TIMEOUT_MS, timeout.signal).then(() => new Error("taskkill timed out")).catch(() => void 0);
@@ -22908,9 +22919,9 @@ function signalGroup(pgid, signal, onError) {
22908
22919
  if (!isAlreadyDead(error61)) onError?.("group", error61);
22909
22920
  }
22910
22921
  }
22911
- function liveEscapedGroups(snapshot2, rootPid, remembered) {
22912
- const leaders = new Map(snapshot2.map((entry) => [entry.pid, entry.startedAt]));
22913
- const groups = new Set(escapedGroups(snapshot2, rootPid).map((group) => group.pgid));
22922
+ function liveEscapedGroups(snapshot, rootPid, remembered) {
22923
+ const leaders = new Map(snapshot.map((entry) => [entry.pid, entry.startedAt]));
22924
+ const groups = new Set(escapedGroups(snapshot, rootPid).map((group) => group.pgid));
22914
22925
  for (const [pgid, startedAt] of remembered) {
22915
22926
  if (leaders.get(pgid) === startedAt) groups.add(pgid);
22916
22927
  }
@@ -23121,10 +23132,10 @@ function spawnCli(options) {
23121
23132
  function waitForSpawn(child, command) {
23122
23133
  if (isWindowsJob(child)) return waitForWindowsJob(child, command);
23123
23134
  if (child.pid !== void 0) return Promise.resolve();
23124
- return new Promise((resolve14, reject) => {
23135
+ return new Promise((resolve13, reject) => {
23125
23136
  const onSpawn = () => {
23126
23137
  child.off("error", onError);
23127
- resolve14();
23138
+ resolve13();
23128
23139
  };
23129
23140
  const onError = (error61) => {
23130
23141
  child.off("spawn", onSpawn);
@@ -24903,6 +24914,7 @@ function settleOpenToolCalls(state) {
24903
24914
  if (outlivesTheTurn(entry))
24904
24915
  continue;
24905
24916
  entry.status = "cancelled";
24917
+ entry.lastUpdateIndex = state.updateCount;
24906
24918
  }
24907
24919
  }
24908
24920
  function applyTool(state, index, update) {
@@ -25614,15 +25626,6 @@ var init_transcript_fold = __esm({
25614
25626
  }
25615
25627
  });
25616
25628
 
25617
- // ../shared/dist/agent/acp/transcript-live.js
25618
- var TRANSCRIPT_LIVE_BATCH_BYTES;
25619
- var init_transcript_live = __esm({
25620
- "../shared/dist/agent/acp/transcript-live.js"() {
25621
- "use strict";
25622
- TRANSCRIPT_LIVE_BATCH_BYTES = 32 * 1024;
25623
- }
25624
- });
25625
-
25626
25629
  // ../shared/dist/agent/acp/index.js
25627
25630
  var init_acp = __esm({
25628
25631
  "../shared/dist/agent/acp/index.js"() {
@@ -25643,7 +25646,6 @@ var init_acp = __esm({
25643
25646
  init_transcript_fold();
25644
25647
  init_transcript_http();
25645
25648
  init_transcript_ingestion();
25646
- init_transcript_live();
25647
25649
  init_types2();
25648
25650
  }
25649
25651
  });
@@ -26780,8 +26782,8 @@ function readMediaFiles(candidates2, cwd, mimeByExt, maxBytes) {
26780
26782
  seen.add(path4);
26781
26783
  const mimeType = mimeByExt[(0, import_path3.extname)(path4).toLowerCase()];
26782
26784
  if (!mimeType) continue;
26783
- const stat23 = (0, import_fs4.statSync)(path4);
26784
- if (!stat23.isFile() || stat23.size <= 0 || stat23.size > maxBytes) continue;
26785
+ const stat22 = (0, import_fs4.statSync)(path4);
26786
+ if (!stat22.isFile() || stat22.size <= 0 || stat22.size > maxBytes) continue;
26785
26787
  files.push({ path: path4, mimeType, buffer: (0, import_fs4.readFileSync)(path4) });
26786
26788
  }
26787
26789
  return files;
@@ -26856,8 +26858,8 @@ function createJsonRpcPeer(writer, handlers) {
26856
26858
  },
26857
26859
  request: (method, params = {}) => {
26858
26860
  const id = counter.next++;
26859
- return new Promise((resolve14, reject) => {
26860
- pending.set(id, { method, resolve: resolve14, reject });
26861
+ return new Promise((resolve13, reject) => {
26862
+ pending.set(id, { method, resolve: resolve13, reject });
26861
26863
  writer.write({ id, method, params }).catch((error61) => {
26862
26864
  pending.delete(id);
26863
26865
  reject(error61 instanceof Error ? error61 : new Error(String(error61)));
@@ -26970,7 +26972,7 @@ function createNdjsonWriter(stream) {
26970
26972
  get writable() {
26971
26973
  return stream.writable && !stream.destroyed && failure6.error === void 0;
26972
26974
  },
26973
- write: (value2) => new Promise((resolve14, reject) => {
26975
+ write: (value2) => new Promise((resolve13, reject) => {
26974
26976
  if (failure6.error) {
26975
26977
  reject(failure6.error);
26976
26978
  return;
@@ -26982,7 +26984,7 @@ function createNdjsonWriter(stream) {
26982
26984
  stream.write(`${JSON.stringify(value2)}
26983
26985
  `, (error61) => {
26984
26986
  if (error61) reject(error61);
26985
- else resolve14();
26987
+ else resolve13();
26986
26988
  });
26987
26989
  }),
26988
26990
  end: () => {
@@ -26998,7 +27000,7 @@ function hostProcess(child, tree, options, handlers) {
26998
27000
  lastScan: Number.NEGATIVE_INFINITY,
26999
27001
  lastOutputAt: void 0
27000
27002
  };
27001
- const terminate = () => tree.terminate({ graceMs: options.terminateGraceMs });
27003
+ const terminate2 = () => tree.terminate({ graceMs: options.terminateGraceMs });
27002
27004
  const heard = () => {
27003
27005
  flags.lastOutputAt = options.clock.monotonic();
27004
27006
  };
@@ -27014,11 +27016,11 @@ function hostProcess(child, tree, options, handlers) {
27014
27016
  });
27015
27017
  child.stderr.on("data", (chunk) => stderr.push(chunk));
27016
27018
  child.stderr.once("end", () => stderr.flush());
27017
- const processExit = new Promise((resolve14) => {
27018
- child.once("exit", (code, signal) => resolve14({ code, signal }));
27019
+ const processExit = new Promise((resolve13) => {
27020
+ child.once("exit", (code, signal) => resolve13({ code, signal }));
27019
27021
  });
27020
- const outputEnded = new Promise((resolve14) => {
27021
- child.stdout.once("close", () => resolve14());
27022
+ const outputEnded = new Promise((resolve13) => {
27023
+ child.stdout.once("close", () => resolve13());
27022
27024
  });
27023
27025
  const watch = async () => {
27024
27026
  const { clock, stdoutDrainMs, log, name } = options;
@@ -27029,14 +27031,14 @@ function hostProcess(child, tree, options, handlers) {
27029
27031
  if (first === "eof" && !await settlesWithin(processExit, clock, stdoutDrainMs)) {
27030
27032
  flags.outputClosedEarly = !flags.closing;
27031
27033
  log.warn(`${name}.stdout_closed_while_running`, { pid: child.pid });
27032
- await terminate();
27034
+ await terminate2();
27033
27035
  }
27034
27036
  if (first === "exit" && !await settlesWithin(outputEnded, clock, stdoutDrainMs)) {
27035
27037
  log.warn(`${name}.stdout_held_after_exit`, { pid: child.pid });
27036
- await terminate();
27038
+ await terminate2();
27037
27039
  }
27038
27040
  const exit = await processExit;
27039
- await terminate();
27041
+ await terminate2();
27040
27042
  child.stdout.destroy();
27041
27043
  child.stderr.destroy();
27042
27044
  child.stdin.destroy();
@@ -27049,7 +27051,7 @@ function hostProcess(child, tree, options, handlers) {
27049
27051
  },
27050
27052
  writer,
27051
27053
  exited: watch(),
27052
- terminate,
27054
+ terminate: terminate2,
27053
27055
  scanDescendants: (force) => {
27054
27056
  const now = options.clock.monotonic();
27055
27057
  if (!force && now - flags.lastScan < options.descendantScanMs) return;
@@ -27315,13 +27317,13 @@ var init_chunk_A2TG6ROT = __esm({
27315
27317
  const turnId = input2.turnId;
27316
27318
  let finish = () => {
27317
27319
  };
27318
- const done = new Promise((resolve14) => {
27320
+ const done = new Promise((resolve13) => {
27319
27321
  finish = (outcome2) => {
27320
27322
  if (this.#current?.id !== turnId) return;
27321
27323
  this.#current = void 0;
27322
27324
  if (this.#state === "busy") this.#state = "idle";
27323
27325
  this.#emit({ type: "turn_ended", turnId, outcome: outcome2 });
27324
- resolve14({ turnId, outcome: outcome2, providerSessionId: this.#sessionId });
27326
+ resolve13({ turnId, outcome: outcome2, providerSessionId: this.#sessionId });
27325
27327
  };
27326
27328
  });
27327
27329
  const pending = {
@@ -27550,7 +27552,7 @@ var init_chunk_J2KTV5FP = __esm({
27550
27552
  }
27551
27553
  });
27552
27554
 
27553
- // ../agent-core/dist/chunk-GI3ZGXTY.js
27555
+ // ../agent-core/dist/chunk-GW6CC6A3.js
27554
27556
  function repositories(input2, context) {
27555
27557
  const problems = new Map(input2.problems.map((problem) => [problem.path, problem]));
27556
27558
  const listed = context?.repositories ?? [];
@@ -27611,7 +27613,12 @@ function environmentInstructions(environment, cwd) {
27611
27613
  );
27612
27614
  } else if (build?.status === "failed") {
27613
27615
  lines2.push(
27614
- `The latest image build (${build.id}) failed; sessions still boot from the previous image.`
27616
+ environment.imageBuildId ? `The latest image build (${build.id}) failed; sessions still boot from the previous image.` : `The latest image build (${build.id}) failed; this environment has no image yet.`
27617
+ );
27618
+ }
27619
+ if (environment.primaryRepository && environment.setupDirectory) {
27620
+ lines2.push(
27621
+ `Image builds read .alan/ from ${environment.primaryRepository}; install steps and the start command run from ${environment.setupDirectory}.`
27615
27622
  );
27616
27623
  }
27617
27624
  if (environment.variables.length > 0) {
@@ -27619,18 +27626,18 @@ function environmentInstructions(environment, cwd) {
27619
27626
  }
27620
27627
  return lines2;
27621
27628
  }
27622
- function instructionsFor(snapshot2) {
27623
- const cwd = snapshot2.workspace.cwd ?? snapshot2.workspace.root ?? "the workspace";
27629
+ function instructionsFor(snapshot) {
27630
+ const cwd = snapshot.workspace.cwd ?? snapshot.workspace.root ?? "the workspace";
27624
27631
  return [
27625
- ...snapshot2.session.trigger === "image_build" ? ["Alan sent this turn, not the user: it reports an image build result."] : [],
27626
- ...snapshot2.environment ? environmentInstructions(snapshot2.environment, cwd) : []
27632
+ ...snapshot.session.trigger === "image_build" ? ["Alan sent this turn, not the user: it reports an image build result."] : [],
27633
+ ...snapshot.environment ? environmentInstructions(snapshot.environment, cwd) : []
27627
27634
  ];
27628
27635
  }
27629
- function startingInstructions(snapshot2) {
27630
- const cwd = snapshot2.workspace.cwd ?? snapshot2.workspace.root;
27636
+ function startingInstructions(snapshot) {
27637
+ const cwd = snapshot.workspace.cwd ?? snapshot.workspace.root;
27631
27638
  return [
27632
27639
  ...cwd ? [`Work from ${cwd}.`] : [],
27633
- ...snapshot2.workspace.repositories.flatMap(repositoryInstructions)
27640
+ ...snapshot.workspace.repositories.flatMap(repositoryInstructions)
27634
27641
  ];
27635
27642
  }
27636
27643
  function sessionKind(input2, context) {
@@ -27638,6 +27645,12 @@ function sessionKind(input2, context) {
27638
27645
  if (input2.spec.workflowExecutionId) return "workflow";
27639
27646
  return input2.spec.taskId ? "task" : "chat";
27640
27647
  }
27648
+ function setupPathsOf(environment) {
27649
+ return {
27650
+ ...environment.primaryRepository ? { primaryRepository: environment.primaryRepository } : {},
27651
+ ...environment.setupDirectory ? { setupDirectory: environment.setupDirectory } : {}
27652
+ };
27653
+ }
27641
27654
  function environmentOf(input2, context) {
27642
27655
  const environment = context?.environment;
27643
27656
  if (!environment) return void 0;
@@ -27648,22 +27661,23 @@ function environmentOf(input2, context) {
27648
27661
  installCommand: environment.installCommand,
27649
27662
  startCommand: environment.startCommand,
27650
27663
  imageBuildId: environment.imageBuildId,
27664
+ ...setupPathsOf(environment),
27651
27665
  ...environment.pendingBuild ? { pendingBuild: environment.pendingBuild } : {},
27652
27666
  variables: environment.variables,
27653
27667
  ...start ? { start: start.state === "not_configured" ? start : { ...start, log: input2.startLogPath } } : {}
27654
27668
  };
27655
27669
  }
27656
- function knownContext(snapshot2) {
27657
- const organizationId = snapshot2?.session.organizationId;
27658
- if (!snapshot2 || !organizationId) return void 0;
27659
- const environment = snapshot2.environment;
27670
+ function knownContext(snapshot) {
27671
+ const organizationId = snapshot?.session.organizationId;
27672
+ if (!snapshot || !organizationId) return void 0;
27673
+ const environment = snapshot.environment;
27660
27674
  return {
27661
- kind: snapshot2.session.kind,
27675
+ kind: snapshot.session.kind,
27662
27676
  trigger: "user",
27663
27677
  organizationId,
27664
- ...snapshot2.task ? { taskWorkingBranch: snapshot2.task.workingBranch } : {},
27665
- ...snapshot2.pullRequest ? { pullRequest: snapshot2.pullRequest } : {},
27666
- repositories: snapshot2.workspace.repositories.flatMap(
27678
+ ...snapshot.task ? { taskWorkingBranch: snapshot.task.workingBranch } : {},
27679
+ ...snapshot.pullRequest ? { pullRequest: snapshot.pullRequest } : {},
27680
+ repositories: snapshot.workspace.repositories.flatMap(
27667
27681
  ({ path: path4, name, url: url3, branch, branchSource, base }) => name && url3 && branch && branchSource && base ? [{ path: path4, name, url: url3, branch, branchSource, base }] : []
27668
27682
  ),
27669
27683
  ...environment ? {
@@ -27673,6 +27687,7 @@ function knownContext(snapshot2) {
27673
27687
  installCommand: environment.installCommand,
27674
27688
  startCommand: environment.startCommand,
27675
27689
  imageBuildId: environment.imageBuildId,
27690
+ ...setupPathsOf(environment),
27676
27691
  ...environment.pendingBuild ? { pendingBuild: environment.pendingBuild } : {},
27677
27692
  variables: environment.variables
27678
27693
  }
@@ -27710,7 +27725,7 @@ function isScalar(value2) {
27710
27725
  }
27711
27726
  function scalar(value2) {
27712
27727
  if (typeof value2 !== "string") return String(value2);
27713
- return PLAIN_SCALAR.test(value2) ? value2 : JSON.stringify(value2);
27728
+ return PLAIN_SCALAR.test(value2) ? value2 : JSON.stringify(value2).replaceAll("<", "\\u003c");
27714
27729
  }
27715
27730
  function snakeCase(key) {
27716
27731
  return key.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);
@@ -27790,15 +27805,15 @@ function updateBody(previous, next) {
27790
27805
  if (Object.keys(facts).length === 0) return void 0;
27791
27806
  return next.session.trigger === "user" ? facts : { session: { trigger: next.session.trigger }, ...facts };
27792
27807
  }
27793
- function renderAgentContext(snapshot2, previous) {
27808
+ function renderAgentContext(snapshot, previous) {
27794
27809
  const full = block("alan_agent_context", {
27795
- ...snapshot2,
27796
- ...snapshot2.environment ? { environment: withCommandPreviews(snapshot2.environment) } : {},
27797
- instructions: [...startingInstructions(snapshot2), ...snapshot2.instructions]
27810
+ ...snapshot,
27811
+ ...snapshot.environment ? { environment: withCommandPreviews(snapshot.environment) } : {},
27812
+ instructions: [...startingInstructions(snapshot), ...snapshot.instructions]
27798
27813
  });
27799
- const update = previous ? updateBody(previous, snapshot2) : void 0;
27814
+ const update = previous ? updateBody(previous, snapshot) : void 0;
27800
27815
  return {
27801
- snapshot: snapshot2,
27816
+ snapshot,
27802
27817
  full,
27803
27818
  ...update ? { update: block("alan_agent_context_update", update) } : {}
27804
27819
  };
@@ -28164,8 +28179,8 @@ ${body}` : body;
28164
28179
  return spec.mode === "plan" ? planModePrefix(prefixed) : prefixed;
28165
28180
  }
28166
28181
  var startCommandStateSchema, repositorySnapshotSchema, environmentSnapshotSchema, agentContextSnapshotSchema, BRANCH_REASONS, PLAIN_SCALAR, COMMAND_PREVIEW_CHARS, MAX_PARSED_ATTACHMENTS, MAX_PARSED_ATTACHMENT_CHARS, MAX_METADATA_CHARS, UNAVAILABLE, READ_ONLY_MODES, AGENT_MODES;
28167
- var init_chunk_GI3ZGXTY = __esm({
28168
- "../agent-core/dist/chunk-GI3ZGXTY.js"() {
28182
+ var init_chunk_GW6CC6A3 = __esm({
28183
+ "../agent-core/dist/chunk-GW6CC6A3.js"() {
28169
28184
  "use strict";
28170
28185
  init_runtime_v2();
28171
28186
  init_zod();
@@ -28194,6 +28209,8 @@ var init_chunk_GI3ZGXTY = __esm({
28194
28209
  installCommand: external_exports.string().nullable(),
28195
28210
  startCommand: external_exports.string().nullable(),
28196
28211
  imageBuildId: external_exports.string().nullable(),
28212
+ primaryRepository: external_exports.string().optional(),
28213
+ setupDirectory: external_exports.string().optional(),
28197
28214
  pendingBuild: agentContextBuildSchema.optional(),
28198
28215
  variables: external_exports.array(external_exports.string()),
28199
28216
  start: external_exports.intersection(startCommandStateSchema, external_exports.object({ log: external_exports.string().optional() })).optional()
@@ -29218,18 +29235,24 @@ function realCwd(cwd) {
29218
29235
  return cwd;
29219
29236
  }
29220
29237
  }
29238
+ function projectDirs(projectsRoot) {
29239
+ try {
29240
+ return (0, import_fs5.readdirSync)(projectsRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
29241
+ } catch {
29242
+ return [];
29243
+ }
29244
+ }
29221
29245
  function claudeSessionLogExists(query) {
29222
29246
  if (!query.sessionId || !query.cwd) return false;
29223
- for (const cwd of /* @__PURE__ */ new Set([query.cwd, realCwd(query.cwd)])) {
29224
- const log = (0, import_path5.join)(
29225
- query.claudeHome,
29226
- "projects",
29227
- encodeProjectDir(cwd),
29228
- `${query.sessionId}.jsonl`
29229
- );
29230
- if ((0, import_fs5.existsSync)(log)) return true;
29231
- }
29232
- return false;
29247
+ const projectsRoot = (0, import_path5.join)(query.claudeHome, "projects");
29248
+ const fileName = `${query.sessionId}.jsonl`;
29249
+ const here = new Set([query.cwd, realCwd(query.cwd)].map(encodeProjectDir));
29250
+ for (const dir of here) {
29251
+ if ((0, import_fs5.existsSync)((0, import_path5.join)(projectsRoot, dir, fileName))) return true;
29252
+ }
29253
+ return projectDirs(projectsRoot).some(
29254
+ (dir) => !here.has(dir) && (0, import_fs5.existsSync)((0, import_path5.join)(projectsRoot, dir, fileName))
29255
+ );
29233
29256
  }
29234
29257
  function envDigest(env) {
29235
29258
  const hash2 = (0, import_crypto7.createHash)("sha256");
@@ -29505,7 +29528,7 @@ var init_claude = __esm({
29505
29528
  init_chunk_ZCTKXKYY();
29506
29529
  init_chunk_J2KTV5FP();
29507
29530
  init_chunk_XE7BX6YP();
29508
- init_chunk_GI3ZGXTY();
29531
+ init_chunk_GW6CC6A3();
29509
29532
  init_chunk_YXWJW7I5();
29510
29533
  init_effort();
29511
29534
  import_crypto6 = require("crypto");
@@ -30231,8 +30254,8 @@ var init_claude = __esm({
30231
30254
  }
30232
30255
  async #awaitTaskStop(requestId, taskId) {
30233
30256
  const timer = new AbortController();
30234
- const answered = new Promise((resolve14) => {
30235
- this.#taskStops.set(requestId, resolve14);
30257
+ const answered = new Promise((resolve13) => {
30258
+ this.#taskStops.set(requestId, resolve13);
30236
30259
  });
30237
30260
  const timeoutMs = this.#options.stopTaskTimeoutMs;
30238
30261
  const timedOut = this.#options.clock.sleep(timeoutMs, timer.signal).then(
@@ -30305,17 +30328,17 @@ var init_claude = __esm({
30305
30328
  };
30306
30329
  let markStarted = () => {
30307
30330
  };
30308
- const whenStarted = new Promise((resolve14) => {
30309
- markStarted = resolve14;
30331
+ const whenStarted = new Promise((resolve13) => {
30332
+ markStarted = resolve13;
30310
30333
  });
30311
- const done = new Promise((resolve14) => {
30334
+ const done = new Promise((resolve13) => {
30312
30335
  finish = (outcome2) => {
30313
30336
  if (this.#current?.id !== id) return;
30314
30337
  this.#current = void 0;
30315
30338
  this.#lastTurn = turn;
30316
30339
  if (this.#state === "busy") this.#state = "idle";
30317
30340
  this.#emit({ type: "turn_ended", turnId: id, outcome: outcome2 });
30318
- resolve14({ turnId: id, outcome: outcome2, providerSessionId: this.#providerSessionId });
30341
+ resolve13({ turnId: id, outcome: outcome2, providerSessionId: this.#providerSessionId });
30319
30342
  };
30320
30343
  });
30321
30344
  const active = {
@@ -30433,8 +30456,8 @@ var init_claude = __esm({
30433
30456
  void removeLaunchFiles(this.#launchFiles).catch((error61) => {
30434
30457
  this.#options.log.warn("claude.launch_files_cleanup_failed", { error: error61 });
30435
30458
  });
30436
- for (const resolve14 of this.#taskStops.values()) {
30437
- resolve14({ ok: false, reason: "runtime_unavailable", message: "Claude Code exited." });
30459
+ for (const resolve13 of this.#taskStops.values()) {
30460
+ resolve13({ ok: false, reason: "runtime_unavailable", message: "Claude Code exited." });
30438
30461
  }
30439
30462
  const active = this.#current;
30440
30463
  if (active) {
@@ -32367,7 +32390,7 @@ var init_codex = __esm({
32367
32390
  init_chunk_ZCTKXKYY();
32368
32391
  init_chunk_J2KTV5FP();
32369
32392
  init_chunk_XE7BX6YP();
32370
- init_chunk_GI3ZGXTY();
32393
+ init_chunk_GW6CC6A3();
32371
32394
  init_chunk_YXWJW7I5();
32372
32395
  import_fs6 = require("fs");
32373
32396
  import_path6 = require("path");
@@ -32575,7 +32598,7 @@ var init_codex = __esm({
32575
32598
  const buckets = asRecord(response?.rateLimitsByLimitId);
32576
32599
  if (buckets) {
32577
32600
  return Object.entries(buckets).flatMap(
32578
- ([limitId, snapshot2]) => this.#update(snapshot2, limitId)
32601
+ ([limitId, snapshot]) => this.#update(snapshot, limitId)
32579
32602
  );
32580
32603
  }
32581
32604
  return this.#update(response?.rateLimits);
@@ -32584,16 +32607,16 @@ var init_codex = __esm({
32584
32607
  return this.#update(params.rateLimits);
32585
32608
  }
32586
32609
  #update(value2, bucketId) {
32587
- const snapshot2 = asRecord(value2);
32588
- if (!snapshot2) return [];
32589
- const primary = windowPatch(snapshot2.primary);
32590
- const secondary = windowPatch(snapshot2.secondary);
32591
- const spend = spendPatch(snapshot2.individualLimit, snapshot2.spendControlReached);
32592
- const credits = creditsPatch(snapshot2.credits);
32593
- const planType = snapshot2.planType === null ? null : asString(snapshot2.planType) || void 0;
32610
+ const snapshot = asRecord(value2);
32611
+ if (!snapshot) return [];
32612
+ const primary = windowPatch(snapshot.primary);
32613
+ const secondary = windowPatch(snapshot.secondary);
32614
+ const spend = spendPatch(snapshot.individualLimit, snapshot.spendControlReached);
32615
+ const credits = creditsPatch(snapshot.credits);
32616
+ const planType = snapshot.planType === null ? null : asString(snapshot.planType) || void 0;
32594
32617
  const parsed = runCodexRateLimitsUpdateSchema.safeParse({
32595
32618
  sessionUpdate: "_alan/codex.rate_limits",
32596
- limitId: bucketId ?? (asString(snapshot2.limitId) || "codex"),
32619
+ limitId: bucketId ?? (asString(snapshot.limitId) || "codex"),
32597
32620
  ...primary === void 0 ? {} : { primary },
32598
32621
  ...secondary === void 0 ? {} : { secondary },
32599
32622
  ...spend === void 0 ? {} : { spend },
@@ -33039,10 +33062,10 @@ var init_codex = __esm({
33039
33062
  };
33040
33063
  let identify = () => {
33041
33064
  };
33042
- const identified = new Promise((resolve14) => {
33043
- identify = resolve14;
33065
+ const identified = new Promise((resolve13) => {
33066
+ identify = resolve13;
33044
33067
  });
33045
- const done = new Promise((resolve14) => {
33068
+ const done = new Promise((resolve13) => {
33046
33069
  finish = (outcome2) => {
33047
33070
  if (this.#current?.id !== id) return;
33048
33071
  this.#current = void 0;
@@ -33050,7 +33073,7 @@ var init_codex = __esm({
33050
33073
  if (this.#state === "busy") this.#state = "idle";
33051
33074
  this.#host.scanDescendants(true);
33052
33075
  this.#emit({ type: "turn_ended", turnId: id, outcome: outcome2 });
33053
- resolve14({ turnId: id, outcome: outcome2, providerSessionId: this.#threadId });
33076
+ resolve13({ turnId: id, outcome: outcome2, providerSessionId: this.#threadId });
33054
33077
  };
33055
33078
  });
33056
33079
  const active = {
@@ -33606,7 +33629,7 @@ function alanCodeConfigContent(existing, input2) {
33606
33629
  });
33607
33630
  }
33608
33631
  function readBody2(response) {
33609
- return new Promise((resolve14, reject) => {
33632
+ return new Promise((resolve13, reject) => {
33610
33633
  const chunks = [];
33611
33634
  let size = 0;
33612
33635
  response.on("data", (chunk) => {
@@ -33614,7 +33637,7 @@ function readBody2(response) {
33614
33637
  if (size > MAX_CATALOG_BYTES) response.destroy(new Error("catalog too large"));
33615
33638
  else chunks.push(chunk);
33616
33639
  });
33617
- response.on("end", () => resolve14(Buffer.concat(chunks).toString("utf8")));
33640
+ response.on("end", () => resolve13(Buffer.concat(chunks).toString("utf8")));
33618
33641
  response.on("error", reject);
33619
33642
  });
33620
33643
  }
@@ -33630,13 +33653,13 @@ function parseResponseBody(text3, status) {
33630
33653
  }
33631
33654
  function getJson(url3, headers, timeout, signal) {
33632
33655
  const request2 = url3.protocol === "https:" ? import_https.request : import_http9.request;
33633
- return new Promise((resolve14, reject) => {
33656
+ return new Promise((resolve13, reject) => {
33634
33657
  const outgoing = request2(url3, { method: "GET", headers, timeout, signal }, (response) => {
33635
33658
  const status = response.statusCode ?? 0;
33636
33659
  readBody2(response).then((text3) => {
33637
33660
  const body = parseResponseBody(text3, status);
33638
33661
  if (status < 200 || status >= 300) reject(new CatalogResponseError(status, body));
33639
- else resolve14(body);
33662
+ else resolve13(body);
33640
33663
  }).catch(reject);
33641
33664
  });
33642
33665
  outgoing.on("timeout", () => outgoing.destroy(new Error("catalog timed out")));
@@ -42513,8 +42536,8 @@ var require_streamx = __commonJS({
42513
42536
  return this;
42514
42537
  },
42515
42538
  next() {
42516
- return new Promise(function(resolve14, reject) {
42517
- promiseResolve = resolve14;
42539
+ return new Promise(function(resolve13, reject) {
42540
+ promiseResolve = resolve13;
42518
42541
  promiseReject = reject;
42519
42542
  const data = stream.read();
42520
42543
  if (data !== null) ondata(data);
@@ -42547,11 +42570,11 @@ var require_streamx = __commonJS({
42547
42570
  }
42548
42571
  function destroy(err) {
42549
42572
  stream.destroy(err);
42550
- return new Promise((resolve14, reject) => {
42551
- if (stream._duplexState & DESTROYED) return resolve14({ value: void 0, done: true });
42573
+ return new Promise((resolve13, reject) => {
42574
+ if (stream._duplexState & DESTROYED) return resolve13({ value: void 0, done: true });
42552
42575
  stream.once("close", function() {
42553
42576
  if (err) reject(err);
42554
- else resolve14({ value: void 0, done: true });
42577
+ else resolve13({ value: void 0, done: true });
42555
42578
  });
42556
42579
  });
42557
42580
  }
@@ -42595,8 +42618,8 @@ var require_streamx = __commonJS({
42595
42618
  const writes = pending + (ws._duplexState & WRITE_WRITING ? 1 : 0);
42596
42619
  if (writes === 0) return Promise.resolve(true);
42597
42620
  if (state.drains === null) state.drains = [];
42598
- return new Promise((resolve14) => {
42599
- state.drains.push({ writes, resolve: resolve14 });
42621
+ return new Promise((resolve13) => {
42622
+ state.drains.push({ writes, resolve: resolve13 });
42600
42623
  });
42601
42624
  }
42602
42625
  write(data) {
@@ -42701,10 +42724,10 @@ var require_streamx = __commonJS({
42701
42724
  cb(null);
42702
42725
  }
42703
42726
  function pipelinePromise(...streams) {
42704
- return new Promise((resolve14, reject) => {
42727
+ return new Promise((resolve13, reject) => {
42705
42728
  return pipeline(...streams, (err) => {
42706
42729
  if (err) return reject(err);
42707
- resolve14();
42730
+ resolve13();
42708
42731
  });
42709
42732
  });
42710
42733
  }
@@ -42827,9 +42850,9 @@ var require_streamx = __commonJS({
42827
42850
  }
42828
42851
  });
42829
42852
 
42830
- // ../../node_modules/tar-stream/headers.js
42853
+ // ../shared/node_modules/tar-stream/headers.js
42831
42854
  var require_headers = __commonJS({
42832
- "../../node_modules/tar-stream/headers.js"(exports2) {
42855
+ "../shared/node_modules/tar-stream/headers.js"(exports2) {
42833
42856
  "use strict";
42834
42857
  var b4a = require_b4a();
42835
42858
  var ZEROS = "0000000000000000000";
@@ -43090,9 +43113,9 @@ var require_headers = __commonJS({
43090
43113
  }
43091
43114
  });
43092
43115
 
43093
- // ../../node_modules/tar-stream/extract.js
43116
+ // ../shared/node_modules/tar-stream/extract.js
43094
43117
  var require_extract = __commonJS({
43095
- "../../node_modules/tar-stream/extract.js"(exports2, module2) {
43118
+ "../shared/node_modules/tar-stream/extract.js"(exports2, module2) {
43096
43119
  "use strict";
43097
43120
  var { Writable, Readable: Readable2, getStreamError } = require_streamx();
43098
43121
  var FIFO = require_fast_fifo();
@@ -43376,16 +43399,16 @@ var require_extract = __commonJS({
43376
43399
  entryCallback = null;
43377
43400
  cb(err);
43378
43401
  }
43379
- function onnext(resolve14, reject) {
43402
+ function onnext(resolve13, reject) {
43380
43403
  if (error61) {
43381
43404
  return reject(error61);
43382
43405
  }
43383
43406
  if (entryStream) {
43384
- resolve14({ value: entryStream, done: false });
43407
+ resolve13({ value: entryStream, done: false });
43385
43408
  entryStream = null;
43386
43409
  return;
43387
43410
  }
43388
- promiseResolve = resolve14;
43411
+ promiseResolve = resolve13;
43389
43412
  promiseReject = reject;
43390
43413
  consumeCallback(null);
43391
43414
  if (extract2._finished && promiseResolve) {
@@ -43413,11 +43436,11 @@ var require_extract = __commonJS({
43413
43436
  function destroy(err) {
43414
43437
  extract2.destroy(err);
43415
43438
  consumeCallback(err);
43416
- return new Promise((resolve14, reject) => {
43417
- if (extract2.destroyed) return resolve14({ value: void 0, done: true });
43439
+ return new Promise((resolve13, reject) => {
43440
+ if (extract2.destroyed) return resolve13({ value: void 0, done: true });
43418
43441
  extract2.once("close", function() {
43419
43442
  if (err) reject(err);
43420
- else resolve14({ value: void 0, done: true });
43443
+ else resolve13({ value: void 0, done: true });
43421
43444
  });
43422
43445
  });
43423
43446
  }
@@ -43435,9 +43458,9 @@ var require_extract = __commonJS({
43435
43458
  }
43436
43459
  });
43437
43460
 
43438
- // ../../node_modules/tar-stream/constants.js
43461
+ // ../shared/node_modules/tar-stream/constants.js
43439
43462
  var require_constants = __commonJS({
43440
- "../../node_modules/tar-stream/constants.js"(exports2, module2) {
43463
+ "../shared/node_modules/tar-stream/constants.js"(exports2, module2) {
43441
43464
  "use strict";
43442
43465
  var constants5 = {
43443
43466
  // just for envs without fs
@@ -43456,9 +43479,9 @@ var require_constants = __commonJS({
43456
43479
  }
43457
43480
  });
43458
43481
 
43459
- // ../../node_modules/tar-stream/pack.js
43482
+ // ../shared/node_modules/tar-stream/pack.js
43460
43483
  var require_pack = __commonJS({
43461
- "../../node_modules/tar-stream/pack.js"(exports2, module2) {
43484
+ "../shared/node_modules/tar-stream/pack.js"(exports2, module2) {
43462
43485
  "use strict";
43463
43486
  var { Readable: Readable2, Writable, getStreamError } = require_streamx();
43464
43487
  var b4a = require_b4a();
@@ -43691,9 +43714,9 @@ var require_pack = __commonJS({
43691
43714
  }
43692
43715
  });
43693
43716
 
43694
- // ../../node_modules/tar-stream/index.js
43717
+ // ../shared/node_modules/tar-stream/index.js
43695
43718
  var require_tar_stream = __commonJS({
43696
- "../../node_modules/tar-stream/index.js"(exports2) {
43719
+ "../shared/node_modules/tar-stream/index.js"(exports2) {
43697
43720
  "use strict";
43698
43721
  exports2.extract = require_extract();
43699
43722
  exports2.pack = require_pack();
@@ -44305,12 +44328,12 @@ function shellStart(update, sessionId) {
44305
44328
  ];
44306
44329
  }
44307
44330
  function shellEnd(update) {
44308
- const snapshot2 = asRecord(update.task_snapshot);
44309
- const taskId = optional2(snapshot2?.task_id);
44310
- if (!snapshot2 || !taskId) return [];
44311
- const killed = snapshot2.explicitly_killed === true;
44312
- const exitCode = snapshot2.exit_code;
44313
- const failed = typeof exitCode === "number" && exitCode !== 0 || optional2(snapshot2.signal) !== void 0;
44331
+ const snapshot = asRecord(update.task_snapshot);
44332
+ const taskId = optional2(snapshot?.task_id);
44333
+ if (!snapshot || !taskId) return [];
44334
+ const killed = snapshot.explicitly_killed === true;
44335
+ const exitCode = snapshot.exit_code;
44336
+ const failed = typeof exitCode === "number" && exitCode !== 0 || optional2(snapshot.signal) !== void 0;
44314
44337
  const ending = killed ? "stopped" : failed ? "failed" : "completed";
44315
44338
  return [{ type: "end", taskId, ending }];
44316
44339
  }
@@ -44456,7 +44479,7 @@ var init_acp3 = __esm({
44456
44479
  init_chunk_ZCTKXKYY();
44457
44480
  init_chunk_J2KTV5FP();
44458
44481
  init_chunk_XE7BX6YP();
44459
- init_chunk_GI3ZGXTY();
44482
+ init_chunk_GW6CC6A3();
44460
44483
  init_chunk_YXWJW7I5();
44461
44484
  import_promises50 = require("fs/promises");
44462
44485
  import_path9 = require("path");
@@ -44982,7 +45005,7 @@ var init_acp3 = __esm({
44982
45005
  const turn = new AcpTurn(`acp-${this.#turns}-${id}`, this.#profile);
44983
45006
  let finish = () => {
44984
45007
  };
44985
- const done = new Promise((resolve14) => {
45008
+ const done = new Promise((resolve13) => {
44986
45009
  finish = (outcome2) => {
44987
45010
  if (this.#current?.id !== id) return;
44988
45011
  this.#current = void 0;
@@ -44990,7 +45013,7 @@ var init_acp3 = __esm({
44990
45013
  if (this.#state === "busy") this.#state = "idle";
44991
45014
  this.#host.scanDescendants(true);
44992
45015
  this.#emit({ type: "turn_ended", turnId: id, outcome: outcome2 });
44993
- resolve14({ turnId: id, outcome: outcome2, providerSessionId: this.#sessionId });
45016
+ resolve13({ turnId: id, outcome: outcome2, providerSessionId: this.#sessionId });
44994
45017
  };
44995
45018
  });
44996
45019
  const active = { id, turn, done, finish, cancelRequested: false };
@@ -45575,12 +45598,11 @@ function createPersistentDriver(provider4, options) {
45575
45598
  log.warn("holder.history_rejected", { harness: provider4.harness });
45576
45599
  await session.suspend();
45577
45600
  };
45578
- const respond = async (request2, mayWrite) => {
45601
+ const respond = async (request2) => {
45579
45602
  const turn = live.turn;
45580
45603
  if (turn === void 0 || turn.runId !== request2.runId) return "unknown_run";
45581
45604
  const isWaiting = () => live.turn === turn && turn.waiting.has(request2.toolCallId);
45582
45605
  if (!isWaiting() || turn.session.respond === void 0) return "not_waiting";
45583
- if (!await mayWrite() || !isWaiting()) return "not_waiting";
45584
45606
  turn.waiting.delete(request2.toolCallId);
45585
45607
  try {
45586
45608
  await turn.session.respond(request2.toolCallId, request2.answer);
@@ -46322,7 +46344,7 @@ var init_opencode = __esm({
46322
46344
  init_chunk_ZCTKXKYY();
46323
46345
  init_chunk_J2KTV5FP();
46324
46346
  init_chunk_XE7BX6YP();
46325
- init_chunk_GI3ZGXTY();
46347
+ init_chunk_GW6CC6A3();
46326
46348
  init_chunk_YXWJW7I5();
46327
46349
  import_http10 = require("http");
46328
46350
  init_runtime_v2();
@@ -47806,8 +47828,8 @@ function createDroidPeer(writer, handlers) {
47806
47828
  },
47807
47829
  request: (method, params = {}) => {
47808
47830
  const id = `alan-${counter.next++}`;
47809
- return new Promise((resolve14, reject) => {
47810
- pending.set(id, { method, resolve: resolve14, reject });
47831
+ return new Promise((resolve13, reject) => {
47832
+ pending.set(id, { method, resolve: resolve13, reject });
47811
47833
  writer.write(envelope("request", { id, method, params })).catch((error61) => {
47812
47834
  pending.delete(id);
47813
47835
  reject(error61 instanceof Error ? error61 : new Error(String(error61)));
@@ -48156,7 +48178,7 @@ var init_droid = __esm({
48156
48178
  init_chunk_ZCTKXKYY();
48157
48179
  init_chunk_J2KTV5FP();
48158
48180
  init_chunk_XE7BX6YP();
48159
- init_chunk_GI3ZGXTY();
48181
+ init_chunk_GW6CC6A3();
48160
48182
  init_chunk_YXWJW7I5();
48161
48183
  init_runtime_v2();
48162
48184
  import_crypto16 = require("crypto");
@@ -48435,14 +48457,14 @@ var init_droid = __esm({
48435
48457
  const turn = new DroidTurn(sessionId, this.#memory);
48436
48458
  let finish = () => {
48437
48459
  };
48438
- const done = new Promise((resolve14) => {
48460
+ const done = new Promise((resolve13) => {
48439
48461
  finish = (outcome2) => {
48440
48462
  if (this.#current?.id !== id) return;
48441
48463
  this.#current = void 0;
48442
48464
  if (this.#state === "busy") this.#state = "idle";
48443
48465
  this.#host.scanDescendants(true);
48444
48466
  this.#emit({ type: "turn_ended", turnId: id, outcome: outcome2 });
48445
- resolve14({ turnId: id, outcome: outcome2, providerSessionId: this.#sessionId });
48467
+ resolve13({ turnId: id, outcome: outcome2, providerSessionId: this.#sessionId });
48446
48468
  };
48447
48469
  });
48448
48470
  const active = { id, turn, done, finish, cancelRequested: false };
@@ -49265,7 +49287,7 @@ var init_antigravity = __esm({
49265
49287
  init_chunk_XC5676SG();
49266
49288
  init_chunk_ZCTKXKYY();
49267
49289
  init_chunk_XE7BX6YP();
49268
- init_chunk_GI3ZGXTY();
49290
+ init_chunk_GW6CC6A3();
49269
49291
  init_chunk_YXWJW7I5();
49270
49292
  import_promises54 = require("fs/promises");
49271
49293
  import_path12 = require("path");
@@ -49970,7 +49992,7 @@ var init_command_code = __esm({
49970
49992
  init_chunk_ZCTKXKYY();
49971
49993
  init_chunk_J2KTV5FP();
49972
49994
  init_chunk_XE7BX6YP();
49973
- init_chunk_GI3ZGXTY();
49995
+ init_chunk_GW6CC6A3();
49974
49996
  init_chunk_YXWJW7I5();
49975
49997
  import_promises55 = require("fs/promises");
49976
49998
  import_path15 = require("path");
@@ -55368,7 +55390,7 @@ var require_websocket_server = __commonJS({
55368
55390
  // package.json
55369
55391
  var package_default = {
55370
55392
  name: "@alan-ai-hq/agent-manager",
55371
- version: "0.1.151",
55393
+ version: "0.1.153",
55372
55394
  private: true,
55373
55395
  type: "module",
55374
55396
  description: "Alan machine runtime (alan-agent): identity, link, reconciler, session holders, run log, uploader, local API",
@@ -55418,7 +55440,7 @@ var package_default = {
55418
55440
 
55419
55441
  // src/cli/commands/compat.ts
55420
55442
  var import_node_crypto32 = require("crypto");
55421
- var import_promises71 = require("fs/promises");
55443
+ var import_promises69 = require("fs/promises");
55422
55444
  init_runtime_v2();
55423
55445
  init_zod();
55424
55446
 
@@ -55577,8 +55599,8 @@ async function writeJsonFileAtomic(path4, value2) {
55577
55599
  var LIFECYCLE_DRAIN_MS = 5e3;
55578
55600
  function createGate() {
55579
55601
  const opened = {};
55580
- const promise2 = new Promise((resolve14) => {
55581
- opened.resolve = resolve14;
55602
+ const promise2 = new Promise((resolve13) => {
55603
+ opened.resolve = resolve13;
55582
55604
  });
55583
55605
  return { promise: promise2, open: () => opened.resolve?.() };
55584
55606
  }
@@ -55805,7 +55827,7 @@ function transportFailure(request2, error61) {
55805
55827
  });
55806
55828
  }
55807
55829
  function readBody(incoming, url3, maxBytes) {
55808
- return new Promise((resolve14, reject) => {
55830
+ return new Promise((resolve13, reject) => {
55809
55831
  const declared = Number(incoming.headers["content-length"] ?? "0");
55810
55832
  if (maxBytes !== void 0 && declared > maxBytes) {
55811
55833
  incoming.destroy();
@@ -55824,7 +55846,7 @@ function readBody(incoming, url3, maxBytes) {
55824
55846
  chunks.push(chunk);
55825
55847
  });
55826
55848
  incoming.on("error", reject);
55827
- incoming.on("end", () => resolve14(Buffer.concat(chunks)));
55849
+ incoming.on("end", () => resolve13(Buffer.concat(chunks)));
55828
55850
  });
55829
55851
  }
55830
55852
  function isConnectionReset(error61) {
@@ -55832,7 +55854,7 @@ function isConnectionReset(error61) {
55832
55854
  }
55833
55855
  function exchange(request2, agents, attempt2 = 0) {
55834
55856
  const { signal, url: url3 } = request2;
55835
- return new Promise((resolve14, reject) => {
55857
+ return new Promise((resolve13, reject) => {
55836
55858
  if (signal.aborted) {
55837
55859
  reject(signal.reason);
55838
55860
  return;
@@ -55859,7 +55881,7 @@ function exchange(request2, agents, attempt2 = 0) {
55859
55881
  const stale = outgoing.reusedSocket && !responded && isConnectionReset(error61);
55860
55882
  if (stale && attempt2 < STALE_SOCKET_RETRIES && !signal.aborted) {
55861
55883
  settle();
55862
- resolve14(exchange(request2, agents, attempt2 + 1));
55884
+ resolve13(exchange(request2, agents, attempt2 + 1));
55863
55885
  return;
55864
55886
  }
55865
55887
  fail(error61);
@@ -55872,7 +55894,7 @@ function exchange(request2, agents, attempt2 = 0) {
55872
55894
  readBody(incoming, url3, isRedirect(status) ? void 0 : request2.maxBodyBytes).then(
55873
55895
  (body) => {
55874
55896
  settle();
55875
- resolve14({ status, headers: incoming.headers, body });
55897
+ resolve13({ status, headers: incoming.headers, body });
55876
55898
  },
55877
55899
  fail
55878
55900
  );
@@ -56117,8 +56139,8 @@ function isBodyless(method) {
56117
56139
  return method === "GET" || method === "HEAD";
56118
56140
  }
56119
56141
  function exchange2(send2, options, input2) {
56120
- return new Promise((resolve14, reject) => {
56121
- const outgoing = send2({ ...options, method: input2.method, signal: input2.signal }, resolve14);
56142
+ return new Promise((resolve13, reject) => {
56143
+ const outgoing = send2({ ...options, method: input2.method, signal: input2.signal }, resolve13);
56122
56144
  outgoing.on("error", reject);
56123
56145
  if (isBodyless(input2.method)) {
56124
56146
  input2.body.resume();
@@ -57595,7 +57617,7 @@ function createGitRunner(options) {
57595
57617
  const stderr = new OutputBuffer();
57596
57618
  const total = { bytes: 0 };
57597
57619
  const closed = new AbortController();
57598
- const terminate = async () => {
57620
+ const terminate2 = async () => {
57599
57621
  await killProcessTree(child.pid, { signal: "SIGTERM", child, platform: platform3 });
57600
57622
  try {
57601
57623
  await systemClock.sleep(killGraceMs, closed.signal);
@@ -57604,12 +57626,12 @@ function createGitRunner(options) {
57604
57626
  }
57605
57627
  await killProcessTree(child.pid, { signal: "SIGKILL", child, platform: platform3 });
57606
57628
  };
57607
- return new Promise((resolve14, reject) => {
57629
+ return new Promise((resolve13, reject) => {
57608
57630
  let ending = null;
57609
57631
  const stop = (next) => {
57610
57632
  if (ending !== null) return;
57611
57633
  ending = next;
57612
- if (next.kind !== "exited" && next.kind !== "spawn_failed") void terminate();
57634
+ if (next.kind !== "exited" && next.kind !== "spawn_failed") void terminate2();
57613
57635
  };
57614
57636
  const onTimeout = () => stop({ kind: "timed_out" });
57615
57637
  const onAbort = () => stop({ kind: "aborted" });
@@ -57629,7 +57651,7 @@ function createGitRunner(options) {
57629
57651
  signal.removeEventListener("abort", onAbort);
57630
57652
  const final = ending ?? last;
57631
57653
  if (final.kind === "exited") {
57632
- resolve14({ exitCode: final.exitCode, stdout: stdout.text(), stderr: stderr.text() });
57654
+ resolve13({ exitCode: final.exitCode, stdout: stdout.text(), stderr: stderr.text() });
57633
57655
  } else {
57634
57656
  reject(faultFor(final, command));
57635
57657
  }
@@ -57771,35 +57793,35 @@ async function checkOne(path4, deps, signal) {
57771
57793
  await write({ state: "checking", path: path4 });
57772
57794
  const read = await readSnapshot(deps.git, path4, signal);
57773
57795
  if (read.kind !== "snapshot") return write({ state: read.kind, path: path4, reason: read.reason });
57774
- const { snapshot: snapshot2 } = read;
57796
+ const { snapshot } = read;
57775
57797
  const advertised = await deps.git.run(
57776
57798
  {
57777
57799
  cwd: path4,
57778
- args: ["ls-remote", "--exit-code", REMOTE, `refs/heads/${snapshot2.base}`],
57800
+ args: ["ls-remote", "--exit-code", REMOTE, `refs/heads/${snapshot.base}`],
57779
57801
  network: true,
57780
57802
  readOnly: true
57781
57803
  },
57782
57804
  signal
57783
57805
  );
57784
57806
  if (advertised.exitCode !== 0) {
57785
- return write({ state: "failed", path: path4, snapshot: snapshot2, reason: gitError(advertised, "ls-remote") });
57807
+ return write({ state: "failed", path: path4, snapshot, reason: gitError(advertised, "ls-remote") });
57786
57808
  }
57787
57809
  const tip = advertised.stdout.split(/\s+/)[0] ?? "";
57788
- if (tip === snapshot2.head) return write({ state: "current", path: path4, snapshot: snapshot2 });
57789
- if (tip === snapshot2.published) {
57790
- return write({ state: "behind", path: path4, snapshot: snapshot2, tip, fetched: true });
57810
+ if (tip === snapshot.head) return write({ state: "current", path: path4, snapshot });
57811
+ if (tip === snapshot.published) {
57812
+ return write({ state: "behind", path: path4, snapshot, tip, fetched: true });
57791
57813
  }
57792
- await write({ state: "behind", path: path4, snapshot: snapshot2, tip, fetched: false });
57793
- const depth = snapshot2.shallow ? ["--depth=1"] : [];
57814
+ await write({ state: "behind", path: path4, snapshot, tip, fetched: false });
57815
+ const depth = snapshot.shallow ? ["--depth=1"] : [];
57794
57816
  const fetched = await deps.git.run(
57795
57817
  {
57796
57818
  cwd: path4,
57797
- args: ["fetch", "--no-tags", "--quiet", ...depth, REMOTE, snapshot2.base],
57819
+ args: ["fetch", "--no-tags", "--quiet", ...depth, REMOTE, snapshot.base],
57798
57820
  network: true
57799
57821
  },
57800
57822
  signal
57801
57823
  );
57802
- return fetched.exitCode === 0 ? write({ state: "behind", path: path4, snapshot: snapshot2, tip, fetched: true }) : write({ state: "failed", path: path4, snapshot: snapshot2, reason: gitError(fetched, "fetch") });
57824
+ return fetched.exitCode === 0 ? write({ state: "behind", path: path4, snapshot, tip, fetched: true }) : write({ state: "failed", path: path4, snapshot, reason: gitError(fetched, "fetch") });
57803
57825
  }
57804
57826
  async function isCheckout(path4) {
57805
57827
  return (0, import_promises11.stat)((0, import_node_path7.join)(path4, ".git")).then(
@@ -57853,6 +57875,20 @@ async function readCheckoutFreshness(dir, path4) {
57853
57875
  }
57854
57876
  }
57855
57877
 
57878
+ // ../shared/dist/git-hosts.js
57879
+ var EXACT_HOSTS = {
57880
+ "github.com": "github",
57881
+ "www.github.com": "github",
57882
+ // Alan's GitLab credential is a gitlab.com OAuth token; no other GitLab host may receive it.
57883
+ "gitlab.com": "gitlab",
57884
+ "www.gitlab.com": "gitlab",
57885
+ "bitbucket.org": "bitbucket",
57886
+ "www.bitbucket.org": "bitbucket",
57887
+ "dev.azure.com": "azure-devops",
57888
+ "ssh.dev.azure.com": "azure-devops"
57889
+ };
57890
+ var GIT_GATEWAY_HTTPS_HOSTS = Object.keys(EXACT_HOSTS).filter((host) => !host.startsWith("ssh."));
57891
+
57856
57892
  // src/capabilities/git/credential-config.ts
57857
57893
  init_runtime_v2();
57858
57894
  var PROACTIVE_AUTH_MIN_VERSION = [2, 46];
@@ -57894,14 +57930,16 @@ async function configureGitCredentialHelper(input2) {
57894
57930
  await git(["config", "--global", "--add", `credential.${scope}.helper`, ""]);
57895
57931
  await git(["config", "--global", "--add", `credential.${scope}.helper`, helper]);
57896
57932
  await git(["config", "--global", `credential.${scope}.useHttpPath`, "true"]);
57897
- await unset(`url.${scope}github.com/.insteadOf`);
57898
- await git([
57899
- "config",
57900
- "--global",
57901
- "--add",
57902
- `url.${scope}github.com/.insteadOf`,
57903
- "https://github.com/"
57904
- ]);
57933
+ for (const host of GIT_GATEWAY_HTTPS_HOSTS) {
57934
+ await unset(`url.${scope}${host}/.insteadOf`);
57935
+ await git([
57936
+ "config",
57937
+ "--global",
57938
+ "--add",
57939
+ `url.${scope}${host}/.insteadOf`,
57940
+ `https://${host}/`
57941
+ ]);
57942
+ }
57905
57943
  const version2 = parseGitVersion((await git(["version"])).stdout);
57906
57944
  const proactiveAuth = supportsProactiveAuth(version2);
57907
57945
  if (proactiveAuth) {
@@ -58167,9 +58205,9 @@ function isProcessAlive(pid) {
58167
58205
  }
58168
58206
  }
58169
58207
  async function linuxStartTime(pid) {
58170
- const stat23 = await (0, import_promises13.readFile)(`/proc/${pid}/stat`, "utf8").catch(() => null);
58171
- if (stat23 === null) return null;
58172
- const fields = stat23.slice(stat23.lastIndexOf(")") + 2).split(" ");
58208
+ const stat22 = await (0, import_promises13.readFile)(`/proc/${pid}/stat`, "utf8").catch(() => null);
58209
+ if (stat22 === null) return null;
58210
+ const fields = stat22.slice(stat22.lastIndexOf(")") + 2).split(" ");
58173
58211
  return fields[19] ?? null;
58174
58212
  }
58175
58213
  async function linuxCommand(pid) {
@@ -58601,6 +58639,99 @@ function removeStaleEndpoint(endpoint) {
58601
58639
  if (!endpoint.startsWith("\\\\.\\pipe\\")) (0, import_node_fs6.rmSync)(endpoint, { force: true });
58602
58640
  }
58603
58641
 
58642
+ // src/platform/legacy-daemons.ts
58643
+ var LIST_TIMEOUT_MS = 15e3;
58644
+ var WINDOWS_PROCESS_QUERY = "Get-CimInstance Win32_Process | Select-Object ProcessId,ParentProcessId,CommandLine | ConvertTo-Json -Compress";
58645
+ var LEGACY_ENTRY = /(?:[\\/]agent-manager[\\/]dist[\\/]index\.cjs|[\\/]alan-agent[\\/]index\.cjs|[\\/]bin[\\/]alan-agent)["']?(?=\s)/i;
58646
+ var DAEMON_VERB = /\s["']?daemon["']?(?=\s|$)/;
58647
+ var PROFILE_FLAG = /\s--profile(?:=|\s+)["']?([\w-]+)/;
58648
+ var RUNTIME_V2 = /alan-agent\.cjs|alan-agent(?:-[\w-]+)?\.cmd/i;
58649
+ function parsePsOutput(stdout) {
58650
+ const processes = [];
58651
+ for (const line of stdout.split("\n")) {
58652
+ const match = /^\s*(\d+)\s+(\d+)\s+(.+)$/.exec(line);
58653
+ if (match?.[1] === void 0 || match[2] === void 0 || match[3] === void 0) continue;
58654
+ processes.push({ pid: Number(match[1]), ppid: Number(match[2]), command: match[3].trim() });
58655
+ }
58656
+ return processes;
58657
+ }
58658
+ function isWindowsProcessRow(value2) {
58659
+ return typeof value2 === "object" && value2 !== null;
58660
+ }
58661
+ function parseWindowsProcesses(stdout) {
58662
+ let parsed;
58663
+ try {
58664
+ parsed = JSON.parse(stdout);
58665
+ } catch {
58666
+ return [];
58667
+ }
58668
+ const rows = Array.isArray(parsed) ? parsed : [parsed];
58669
+ const processes = [];
58670
+ for (const row of rows) {
58671
+ if (!isWindowsProcessRow(row)) continue;
58672
+ const { ProcessId: pid, ParentProcessId: ppid, CommandLine: command } = row;
58673
+ if (typeof pid !== "number" || typeof ppid !== "number" || typeof command !== "string") {
58674
+ continue;
58675
+ }
58676
+ processes.push({ pid, ppid, command });
58677
+ }
58678
+ return processes;
58679
+ }
58680
+ async function listProcesses2(exec, platform3) {
58681
+ if (platform3 === "win32") {
58682
+ const result2 = await exec({
58683
+ command: "powershell.exe",
58684
+ args: ["-NoProfile", "-NonInteractive", "-Command", WINDOWS_PROCESS_QUERY],
58685
+ timeoutMs: LIST_TIMEOUT_MS
58686
+ });
58687
+ return result2.status === 0 ? parseWindowsProcesses(result2.stdout) : [];
58688
+ }
58689
+ const result = await exec({
58690
+ command: "ps",
58691
+ args: ["-axww", "-o", "pid=,ppid=,command="],
58692
+ timeoutMs: LIST_TIMEOUT_MS
58693
+ });
58694
+ return result.status === 0 ? parsePsOutput(result.stdout) : [];
58695
+ }
58696
+ function isLegacyDaemonCommand(command) {
58697
+ if (RUNTIME_V2.test(command)) return false;
58698
+ const entry = LEGACY_ENTRY.exec(command);
58699
+ if (entry === null) return false;
58700
+ return DAEMON_VERB.test(command.slice(entry.index + entry[0].length));
58701
+ }
58702
+ function legacyDaemonProfile(command) {
58703
+ return PROFILE_FLAG.exec(command)?.[1] ?? "production";
58704
+ }
58705
+ function legacyProfileClass(profile) {
58706
+ return profile === "production" || profile === "staging" ? profile : "development";
58707
+ }
58708
+ function hasRuntimeV2Descendant(pid, processes, seen = /* @__PURE__ */ new Set()) {
58709
+ for (const child of processes) {
58710
+ if (child.ppid !== pid || seen.has(child.pid)) continue;
58711
+ seen.add(child.pid);
58712
+ if (RUNTIME_V2.test(child.command) || hasRuntimeV2Descendant(child.pid, processes, seen)) {
58713
+ return true;
58714
+ }
58715
+ }
58716
+ return false;
58717
+ }
58718
+ function findLegacyDaemons(processes, options) {
58719
+ const profile = legacyProfileClass(options.profile);
58720
+ return processes.filter(
58721
+ (entry) => !options.exclude.has(entry.pid) && isLegacyDaemonCommand(entry.command) && legacyProfileClass(legacyDaemonProfile(entry.command)) === profile && !hasRuntimeV2Descendant(entry.pid, processes)
58722
+ );
58723
+ }
58724
+ function signalProcess(pid, signal) {
58725
+ try {
58726
+ process.kill(pid, signal);
58727
+ return true;
58728
+ } catch (error61) {
58729
+ const code = errnoCode(error61);
58730
+ if (code === "ESRCH" || code === "EPERM") return false;
58731
+ throw error61;
58732
+ }
58733
+ }
58734
+
58604
58735
  // src/platform/node-flags.ts
58605
58736
  var SERVICE_NODE_FLAGS = [
58606
58737
  "--max-semi-space-size=1",
@@ -59149,7 +59280,7 @@ function statusOf(error61) {
59149
59280
  }
59150
59281
  return 1;
59151
59282
  }
59152
- var systemExec = (request2) => new Promise((resolve14) => {
59283
+ var systemExec = (request2) => new Promise((resolve13) => {
59153
59284
  const child = (0, import_node_child_process6.execFile)(
59154
59285
  request2.command,
59155
59286
  [...request2.args],
@@ -59160,7 +59291,7 @@ var systemExec = (request2) => new Promise((resolve14) => {
59160
59291
  windowsHide: true
59161
59292
  },
59162
59293
  (error61, stdout, stderr) => {
59163
- resolve14({ status: statusOf(error61), stdout, stderr });
59294
+ resolve13({ status: statusOf(error61), stdout, stderr });
59164
59295
  }
59165
59296
  );
59166
59297
  child.stdin?.on("error", () => {
@@ -60354,11 +60485,11 @@ async function startGitCredentialServer(options) {
60354
60485
  });
60355
60486
  });
60356
60487
  removeStaleEndpoint(options.endpoint);
60357
- await new Promise((resolve14, reject) => {
60488
+ await new Promise((resolve13, reject) => {
60358
60489
  server.once("error", reject);
60359
60490
  server.listen(options.endpoint, () => {
60360
60491
  server.off("error", reject);
60361
- resolve14();
60492
+ resolve13();
60362
60493
  });
60363
60494
  });
60364
60495
  options.log.info("git.credential_server_listening", { endpoint: options.endpoint });
@@ -60366,7 +60497,7 @@ async function startGitCredentialServer(options) {
60366
60497
  endpoint: options.endpoint,
60367
60498
  [Symbol.asyncDispose]: async () => {
60368
60499
  closing.abort();
60369
- await new Promise((resolve14) => server.close(() => resolve14()));
60500
+ await new Promise((resolve13) => server.close(() => resolve13()));
60370
60501
  removeStaleEndpoint(options.endpoint);
60371
60502
  }
60372
60503
  };
@@ -60440,13 +60571,13 @@ authorityKeyIdentifier = keyid
60440
60571
  `;
60441
60572
  }
60442
60573
  function openssl(args, cwd) {
60443
- return new Promise((resolve14, reject) => {
60574
+ return new Promise((resolve13, reject) => {
60444
60575
  (0, import_node_child_process9.execFile)(
60445
60576
  "openssl",
60446
60577
  [...args],
60447
60578
  { cwd, timeout: OPENSSL_TIMEOUT_MS },
60448
60579
  (error61, _stdout, stderr) => {
60449
- if (error61 === null) resolve14();
60580
+ if (error61 === null) resolve13();
60450
60581
  else
60451
60582
  reject(new Error(`openssl ${args[0] ?? ""} failed: ${stderr.trim() || error61.message}`));
60452
60583
  }
@@ -60623,21 +60754,21 @@ function relayTo(forward, log) {
60623
60754
  };
60624
60755
  }
60625
60756
  function listen(server, target) {
60626
- return new Promise((resolve14, reject) => {
60757
+ return new Promise((resolve13, reject) => {
60627
60758
  server.once("error", reject);
60628
60759
  const done = () => {
60629
60760
  server.off("error", reject);
60630
- resolve14();
60761
+ resolve13();
60631
60762
  };
60632
60763
  if (typeof target === "string") server.listen(target, done);
60633
60764
  else server.listen(target.port, target.host, done);
60634
60765
  });
60635
60766
  }
60636
60767
  function close(server, sockets = /* @__PURE__ */ new Set()) {
60637
- return new Promise((resolve14) => {
60768
+ return new Promise((resolve13) => {
60638
60769
  for (const socket of sockets) socket.destroy();
60639
60770
  server.closeAllConnections();
60640
- server.close(() => resolve14());
60771
+ server.close(() => resolve13());
60641
60772
  });
60642
60773
  }
60643
60774
  function portOf(server) {
@@ -62771,8 +62902,8 @@ async function openNativeSessionStore(stateDir, maxEntries = MAX_NATIVE_SESSION_
62771
62902
  sessions.delete(sessionKey(entry.provider, entry.externalSessionId));
62772
62903
  }
62773
62904
  }
62774
- const snapshot2 = { version: 1, sessions: [...sessions.values()] };
62775
- writing = writing.catch(() => void 0).then(() => writeJsonFileAtomic(path4, snapshot2));
62905
+ const snapshot = { version: 1, sessions: [...sessions.values()] };
62906
+ writing = writing.catch(() => void 0).then(() => writeJsonFileAtomic(path4, snapshot));
62776
62907
  return writing;
62777
62908
  };
62778
62909
  return {
@@ -63420,7 +63551,7 @@ async function startNativeIngest(deps) {
63420
63551
  };
63421
63552
  const settleIdle = () => {
63422
63553
  if (workers.size > 0) return;
63423
- for (const resolve14 of idleWaiters) resolve14();
63554
+ for (const resolve13 of idleWaiters) resolve13();
63424
63555
  idleWaiters.clear();
63425
63556
  };
63426
63557
  const retryDelay = (worker) => {
@@ -63663,7 +63794,7 @@ async function startNativeIngest(deps) {
63663
63794
  sweep: sweep2,
63664
63795
  whenIdle: () => {
63665
63796
  if (workers.size === 0) return Promise.resolve();
63666
- return new Promise((resolve14) => idleWaiters.add(resolve14));
63797
+ return new Promise((resolve13) => idleWaiters.add(resolve13));
63667
63798
  },
63668
63799
  [Symbol.asyncDispose]: async () => {
63669
63800
  shutdown.abort();
@@ -63811,7 +63942,7 @@ function captureProbe(command, args, options) {
63811
63942
  const launch = directLaunch(command, args, options);
63812
63943
  if (launch === void 0) return Promise.resolve({ stdout: "", stderr: "", exitCode: void 0 });
63813
63944
  const env = platform3 === "win32" ? withWindowsHelper(canonicalWindowsEnvironment(options.env)) : options.env;
63814
- return new Promise((resolve14) => {
63945
+ return new Promise((resolve13) => {
63815
63946
  const limit = options.maxBufferBytes ?? DEFAULT_MAX_BYTES;
63816
63947
  const stdout = [];
63817
63948
  const stderr = [];
@@ -63829,7 +63960,7 @@ function captureProbe(command, args, options) {
63829
63960
  windowsVerbatimArguments: launch.windowsVerbatimArguments
63830
63961
  });
63831
63962
  child.stdin?.end();
63832
- const terminate = () => {
63963
+ const terminate2 = () => {
63833
63964
  if (platform3 !== "win32" && child.pid !== void 0) {
63834
63965
  try {
63835
63966
  process.kill(-child.pid, "SIGKILL");
@@ -63846,7 +63977,7 @@ function captureProbe(command, args, options) {
63846
63977
  settled2 = true;
63847
63978
  deadlineController.abort();
63848
63979
  options.signal?.removeEventListener("abort", abort);
63849
- resolve14({
63980
+ resolve13({
63850
63981
  stdout: Buffer.concat(stdout).toString("utf8"),
63851
63982
  stderr: Buffer.concat(stderr).toString("utf8"),
63852
63983
  exitCode
@@ -63854,7 +63985,7 @@ function captureProbe(command, args, options) {
63854
63985
  };
63855
63986
  void systemClock.sleep(options.timeoutMs ?? DEFAULT_TIMEOUT_MS2, deadlineController.signal).then(
63856
63987
  () => {
63857
- terminate();
63988
+ terminate2();
63858
63989
  child.stdout.destroy();
63859
63990
  child.stderr.destroy();
63860
63991
  finish(void 0);
@@ -63862,7 +63993,7 @@ function captureProbe(command, args, options) {
63862
63993
  () => void 0
63863
63994
  );
63864
63995
  const abort = () => {
63865
- terminate();
63996
+ terminate2();
63866
63997
  child.stdout.destroy();
63867
63998
  child.stderr.destroy();
63868
63999
  finish(void 0);
@@ -63873,7 +64004,7 @@ function captureProbe(command, args, options) {
63873
64004
  bytes += chunk.length;
63874
64005
  if (bytes > limit) {
63875
64006
  overflowed = true;
63876
- terminate();
64007
+ terminate2();
63877
64008
  finish(void 0);
63878
64009
  return;
63879
64010
  }
@@ -63979,7 +64110,7 @@ function cursorAccountLabel(output2) {
63979
64110
  function waitForAbort(signal) {
63980
64111
  if (signal.aborted) return Promise.resolve();
63981
64112
  return new Promise(
63982
- (resolve14) => signal.addEventListener("abort", () => resolve14(), { once: true })
64113
+ (resolve13) => signal.addEventListener("abort", () => resolve13(), { once: true })
63983
64114
  );
63984
64115
  }
63985
64116
  function idlePrompt(signal) {
@@ -64057,14 +64188,14 @@ async function codexLabel(executable, env) {
64057
64188
  windowsVerbatimArguments: launch.windowsVerbatimArguments
64058
64189
  });
64059
64190
  const timeout = AbortSignal.timeout(ACCOUNT_TIMEOUT_MS);
64060
- return new Promise((resolve14) => {
64191
+ return new Promise((resolve13) => {
64061
64192
  let finished = false;
64062
64193
  let buffer = "";
64063
64194
  const finish = (label) => {
64064
64195
  if (finished) return;
64065
64196
  finished = true;
64066
64197
  child.kill();
64067
- resolve14(label);
64198
+ resolve13(label);
64068
64199
  };
64069
64200
  const send2 = (value2) => {
64070
64201
  child.stdin.write(`${JSON.stringify(value2)}
@@ -64207,7 +64338,7 @@ function createProbeQueue(capture, env, limit) {
64207
64338
  active += 1;
64208
64339
  return Promise.resolve();
64209
64340
  }
64210
- return new Promise((resolve14) => waiting.push(resolve14));
64341
+ return new Promise((resolve13) => waiting.push(resolve13));
64211
64342
  };
64212
64343
  const release2 = () => {
64213
64344
  const next = waiting.shift();
@@ -64647,11 +64778,11 @@ async function resolveCliEnvironment(options) {
64647
64778
  }
64648
64779
  async function openCliEnvironment(options) {
64649
64780
  const decorate = options.decorate ?? ((env) => env);
64650
- const resolve14 = async () => {
64781
+ const resolve13 = async () => {
64651
64782
  const resolved = await resolveCliEnvironmentDetailed(options);
64652
64783
  return { env: decorate(resolved.env), source: resolved.source };
64653
64784
  };
64654
- let state = await resolve14();
64785
+ let state = await resolve13();
64655
64786
  let retryAt = options.clock.now() + DEGRADED_RETRY_MS;
64656
64787
  return {
64657
64788
  current: () => state.env,
@@ -64660,7 +64791,7 @@ async function openCliEnvironment(options) {
64660
64791
  if (state.source === "login_shell" || options.platform === "win32") return false;
64661
64792
  if (options.clock.now() < retryAt) return false;
64662
64793
  retryAt = options.clock.now() + DEGRADED_RETRY_MS;
64663
- const next = await resolve14();
64794
+ const next = await resolve13();
64664
64795
  const changed2 = envValue(next.env, "PATH") !== envValue(state.env, "PATH");
64665
64796
  state = next;
64666
64797
  return changed2;
@@ -64737,11 +64868,11 @@ async function installVersion2(backendKind, requested, options, signal) {
64737
64868
  }
64738
64869
  return exact;
64739
64870
  }
64740
- const resolve14 = options.resolveVersion;
64741
- if (resolve14 === void 0) throw new Error("Latest version lookup is unavailable");
64871
+ const resolve13 = options.resolveVersion;
64872
+ if (resolve13 === void 0) throw new Error("Latest version lookup is unavailable");
64742
64873
  const packageName = packageFor(backendKind).name;
64743
64874
  return checkedVersion(
64744
- await resolve14(backendKind === "opencode_serve" ? `${packageName}@1` : packageName, signal)
64875
+ await resolve13(backendKind === "opencode_serve" ? `${packageName}@1` : packageName, signal)
64745
64876
  );
64746
64877
  }
64747
64878
  function selection(root, backendKind, version2) {
@@ -66308,8 +66439,8 @@ async function collectStream(stream) {
66308
66439
  return import_node_buffer2.Buffer.concat(chunks);
66309
66440
  }
66310
66441
  function addArchiveEntry(archive, header, bytes) {
66311
- return new Promise((resolve14, reject) => {
66312
- archive.entry(header, bytes, (error61) => error61 ? reject(error61) : resolve14());
66442
+ return new Promise((resolve13, reject) => {
66443
+ archive.entry(header, bytes, (error61) => error61 ? reject(error61) : resolve13());
66313
66444
  });
66314
66445
  }
66315
66446
  async function decompressBounded(archiveBytes) {
@@ -66335,7 +66466,7 @@ async function extractTar(tarBytes, destination) {
66335
66466
  const extractor = (0, import_tar_stream.extract)();
66336
66467
  let fileCount = 0;
66337
66468
  let totalBytes = 0;
66338
- const completion = new Promise((resolve14, reject) => {
66469
+ const completion = new Promise((resolve13, reject) => {
66339
66470
  extractor.on("entry", (header, stream, next) => {
66340
66471
  void extractEntry(header, stream, destination, {
66341
66472
  addFile(size) {
@@ -66350,7 +66481,7 @@ async function extractTar(tarBytes, destination) {
66350
66481
  }
66351
66482
  }).then(next, (error61) => extractor.destroy(error61 instanceof Error ? error61 : new Error(String(error61))));
66352
66483
  });
66353
- extractor.once("finish", resolve14);
66484
+ extractor.once("finish", resolve13);
66354
66485
  extractor.once("error", reject);
66355
66486
  });
66356
66487
  import_node_stream.Readable.from(tarBytes).pipe(extractor);
@@ -66833,9 +66964,9 @@ async function syncOnce(env, local, onRecorded, signal) {
66833
66964
  return report2;
66834
66965
  }
66835
66966
  function aborted2(signal) {
66836
- return new Promise((resolve14) => {
66837
- if (signal.aborted) resolve14(null);
66838
- else signal.addEventListener("abort", () => resolve14(null), { once: true });
66967
+ return new Promise((resolve13) => {
66968
+ if (signal.aborted) resolve13(null);
66969
+ else signal.addEventListener("abort", () => resolve13(null), { once: true });
66839
66970
  });
66840
66971
  }
66841
66972
  function openMachineSkills(options) {
@@ -66924,11 +67055,11 @@ function openMachineSkills(options) {
66924
67055
  if ((await resolveSkillInvocations(layout, named, "exact")).kind === "resolved") return;
66925
67056
  }
66926
67057
  };
66927
- const recordedUntilResolved = (named, until) => new Promise((resolve14) => {
67058
+ const recordedUntilResolved = (named, until) => new Promise((resolve13) => {
66928
67059
  const done = () => {
66929
67060
  recordWatchers.delete(check3);
66930
67061
  until.removeEventListener("abort", done);
66931
- resolve14();
67062
+ resolve13();
66932
67063
  };
66933
67064
  const check3 = () => {
66934
67065
  void resolveSkillInvocations(layout, named, "exact").then((resolution) => {
@@ -66936,7 +67067,7 @@ function openMachineSkills(options) {
66936
67067
  });
66937
67068
  };
66938
67069
  if (until.aborted) {
66939
- resolve14();
67070
+ resolve13();
66940
67071
  return;
66941
67072
  }
66942
67073
  recordWatchers.add(check3);
@@ -67432,7 +67563,7 @@ async function openWorkspaces(options) {
67432
67563
 
67433
67564
  // src/cli/config.ts
67434
67565
  var import_node_os11 = require("os");
67435
- var import_node_path70 = require("path");
67566
+ var import_node_path68 = require("path");
67436
67567
  init_zod();
67437
67568
 
67438
67569
  // src/client/contract.ts
@@ -67850,8 +67981,8 @@ function nextOffsetOf(response) {
67850
67981
  async function pause(ms, signal) {
67851
67982
  const either = AbortSignal.any([signal, AbortSignal.timeout(ms)]);
67852
67983
  if (either.aborted) return;
67853
- await new Promise((resolve14) => {
67854
- either.addEventListener("abort", () => resolve14(), { once: true });
67984
+ await new Promise((resolve13) => {
67985
+ either.addEventListener("abort", () => resolve13(), { once: true });
67855
67986
  });
67856
67987
  }
67857
67988
  function jittered(backoff, failures) {
@@ -68160,9 +68291,9 @@ async function sendNativeHookSignal(discoveryPath, hookSignal, signal) {
68160
68291
 
68161
68292
  // src/sessions/index.ts
68162
68293
  var import_node_crypto31 = require("crypto");
68163
- var import_promises69 = require("fs/promises");
68294
+ var import_promises67 = require("fs/promises");
68164
68295
  var import_node_os10 = require("os");
68165
- var import_node_path69 = require("path");
68296
+ var import_node_path67 = require("path");
68166
68297
  init_runtime_v2();
68167
68298
 
68168
68299
  // src/holder/control-client.ts
@@ -68213,8 +68344,8 @@ function isReply(message2) {
68213
68344
  async function connectHolder(endpoint, token, onEvent) {
68214
68345
  const socket = (0, import_node_net2.connect)(endpoint);
68215
68346
  const pending = /* @__PURE__ */ new Map();
68216
- const closed = new Promise((resolve14) => socket.once("close", () => resolve14()));
68217
- const ready = new Promise((resolve14, reject) => {
68347
+ const closed = new Promise((resolve13) => socket.once("close", () => resolve13()));
68348
+ const ready = new Promise((resolve13, reject) => {
68218
68349
  socket.once("error", reject);
68219
68350
  socket.once(
68220
68351
  "close",
@@ -68222,7 +68353,7 @@ async function connectHolder(endpoint, token, onEvent) {
68222
68353
  );
68223
68354
  readMessages(socket, holderMessageSchema, {
68224
68355
  onMessage: (message2) => {
68225
- if (message2.type === "ready") resolve14(message2.pid);
68356
+ if (message2.type === "ready") resolve13(message2.pid);
68226
68357
  else if (isReply(message2)) {
68227
68358
  const id = message2.id;
68228
68359
  if (id === null) return;
@@ -68237,13 +68368,13 @@ async function connectHolder(endpoint, token, onEvent) {
68237
68368
  const pid = await ready;
68238
68369
  const request2 = (body) => {
68239
68370
  const id = (0, import_node_crypto26.randomUUID)();
68240
- return new Promise((resolve14, reject) => {
68371
+ return new Promise((resolve13, reject) => {
68241
68372
  const timer = AbortSignal.timeout(REQUEST_TIMEOUT_MS7);
68242
68373
  timer.addEventListener("abort", () => {
68243
68374
  pending.delete(id);
68244
68375
  reject(new RuntimeFault("io_failed", "Holder did not answer"));
68245
68376
  });
68246
- pending.set(id, resolve14);
68377
+ pending.set(id, resolve13);
68247
68378
  writeMessage(socket, { ...body, id });
68248
68379
  });
68249
68380
  };
@@ -68274,9 +68405,9 @@ function selectDriver(persistent, fallback) {
68274
68405
  suspend: async () => {
68275
68406
  await Promise.all([...drivers].map((driver) => driver.suspend?.()));
68276
68407
  },
68277
- respond: async (request2, mayWrite) => {
68408
+ respond: async (request2) => {
68278
68409
  for (const driver of drivers) {
68279
- const status = await driver.respond?.(request2, mayWrite);
68410
+ const status = await driver.respond?.(request2);
68280
68411
  if (status !== void 0 && status !== "unknown_run") return status;
68281
68412
  }
68282
68413
  return "unknown_run";
@@ -68316,9 +68447,9 @@ function createLazyDriver(load) {
68316
68447
  suspend: async () => {
68317
68448
  if (loaded.driver !== void 0) await (await loaded.driver).suspend?.();
68318
68449
  },
68319
- respond: async (request2, mayWrite) => {
68450
+ respond: async (request2) => {
68320
68451
  if (loaded.driver === void 0) return "unknown_run";
68321
- return await (await loaded.driver).respond?.(request2, mayWrite) ?? "unknown_run";
68452
+ return await (await loaded.driver).respond?.(request2) ?? "unknown_run";
68322
68453
  },
68323
68454
  stopTask: async (taskId) => {
68324
68455
  if (loaded.driver === void 0) return TASK_NOT_FOUND;
@@ -68580,14 +68711,14 @@ async function prepareRunInputs(spec, { source, tmpDir, signal, skills = [] }) {
68580
68711
  var import_node_crypto30 = require("crypto");
68581
68712
  var import_node_fs22 = require("fs");
68582
68713
  var import_node_net3 = require("net");
68583
- var import_node_path68 = require("path");
68714
+ var import_node_path66 = require("path");
68584
68715
  init_runtime_v2();
68585
68716
 
68586
68717
  // src/holder/admission.ts
68587
68718
  var import_node_fs19 = require("fs");
68588
- var import_promises63 = require("fs/promises");
68719
+ var import_promises61 = require("fs/promises");
68589
68720
  var import_node_os9 = require("os");
68590
- var import_node_path62 = require("path");
68721
+ var import_node_path60 = require("path");
68591
68722
  init_constants();
68592
68723
 
68593
68724
  // ../shared/dist/node/local-workspace.js
@@ -68598,88 +68729,16 @@ function resolveAlanDefaultWorkspacePath(homeDirectory = (0, import_node_os8.hom
68598
68729
  return (0, import_node_path55.join)(homeDirectory, ".alan", "workspace");
68599
68730
  }
68600
68731
 
68601
- // src/holder/admission-relocation.ts
68732
+ // src/holder/agent-context.ts
68602
68733
  var import_promises58 = require("fs/promises");
68603
68734
  var import_node_path56 = require("path");
68604
- var MAX_RELOCATION_CANDIDATES = 200;
68605
- var RELOCATION_BUDGET_MS = 2e4;
68606
- function repositoryIdentity(url3) {
68607
- const trimmed4 = url3.trim().replace(/\/+$/, "").replace(/\.git$/i, "");
68608
- if (trimmed4.length === 0) return null;
68609
- const scp = /^(?:[^@/]+@)?([^:/]+):(.+)$/.exec(trimmed4);
68610
- if (scp !== null && !trimmed4.includes("://")) {
68611
- return `${scp[1]}/${scp[2]}`.toLowerCase();
68612
- }
68613
- try {
68614
- const parsed = new URL(trimmed4);
68615
- return `${parsed.hostname}${parsed.pathname}`.replace(/\/+$/, "").toLowerCase();
68616
- } catch {
68617
- return null;
68618
- }
68619
- }
68620
- function repositoryIdentities(urls) {
68621
- return new Set(
68622
- urls.map(repositoryIdentity).filter((identity) => identity !== null)
68623
- );
68624
- }
68625
- async function originIdentity(git, path4, signal) {
68626
- try {
68627
- const output2 = await git.run(
68628
- { cwd: path4, args: ["config", "--get", "remote.origin.url"], readOnly: true },
68629
- signal
68630
- );
68631
- return output2.exitCode === 0 ? repositoryIdentity(output2.stdout) : null;
68632
- } catch {
68633
- return null;
68634
- }
68635
- }
68636
- async function childDirectories(parent, limit) {
68637
- try {
68638
- const entries = await (0, import_promises58.readdir)(parent, { withFileTypes: true });
68639
- return entries.filter((entry) => entry.isDirectory()).slice(0, limit).map((entry) => (0, import_node_path56.join)(parent, entry.name));
68640
- } catch {
68641
- return [];
68642
- }
68643
- }
68644
- async function candidateFolders(search) {
68645
- const roots = /* @__PURE__ */ new Map();
68646
- for (const path4 of [search.missingPath, ...search.approvedWorkspacePaths]) {
68647
- const parent = (0, import_node_path56.dirname)((0, import_node_path56.resolve)(path4));
68648
- roots.set(comparablePath(parent, search.platform), parent);
68649
- }
68650
- const candidates2 = /* @__PURE__ */ new Map();
68651
- for (const root of roots.values()) {
68652
- const remaining = MAX_RELOCATION_CANDIDATES - candidates2.size;
68653
- if (remaining <= 0) break;
68654
- for (const child of await childDirectories(root, remaining)) {
68655
- candidates2.set(comparablePath(child, search.platform), child);
68656
- }
68657
- }
68658
- return [...candidates2.values()];
68659
- }
68660
- async function discoverRelocatedWorkspace(search) {
68661
- if (search.expected.size === 0) return null;
68662
- const signal = AbortSignal.any([search.signal, AbortSignal.timeout(RELOCATION_BUDGET_MS)]);
68663
- const matches = [];
68664
- for (const candidate of await candidateFolders(search)) {
68665
- if (signal.aborted) return null;
68666
- const identity = await originIdentity(search.git, candidate, signal);
68667
- if (identity !== null && search.expected.has(identity)) matches.push(candidate);
68668
- if (matches.length > 1) return null;
68669
- }
68670
- return matches[0] ?? null;
68671
- }
68672
-
68673
- // src/holder/agent-context.ts
68674
- var import_promises59 = require("fs/promises");
68675
- var import_node_path57 = require("path");
68676
68735
 
68677
68736
  // ../agent-core/dist/prompt.js
68678
- init_chunk_GI3ZGXTY();
68737
+ init_chunk_GW6CC6A3();
68679
68738
 
68680
68739
  // src/holder/agent-context.ts
68681
68740
  async function readText4(path4) {
68682
- return (0, import_promises59.readFile)(path4, "utf8").then(
68741
+ return (0, import_promises58.readFile)(path4, "utf8").then(
68683
68742
  (text3) => text3.trim(),
68684
68743
  () => null
68685
68744
  );
@@ -68694,15 +68753,15 @@ async function startCommandState(statusPath) {
68694
68753
  return code === 0 ? { state: "exited_ok" } : { state: "failed", exitCode: code };
68695
68754
  }
68696
68755
  function createAgentContext(deps) {
68697
- const statusPath = (0, import_node_path57.join)(deps.homeDir, ".alan", "start-commands.status");
68698
- const logPath = (0, import_node_path57.join)(deps.homeDir, ".alan", "start-commands.log");
68756
+ const statusPath = (0, import_node_path56.join)(deps.homeDir, ".alan", "start-commands.status");
68757
+ const logPath = (0, import_node_path56.join)(deps.homeDir, ".alan", "start-commands.log");
68699
68758
  return async (spec, problems) => {
68700
- const file2 = (0, import_node_path57.join)(deps.dir, `${spec.conversationId}.json`);
68759
+ const file2 = (0, import_node_path56.join)(deps.dir, `${spec.conversationId}.json`);
68701
68760
  const saved = await readJsonFile(file2, agentContextSnapshotSchema);
68702
68761
  const known = saved.kind === "ok" ? saved.value : void 0;
68703
68762
  const hasEnvironment = (spec.agentContext ?? known)?.environment !== void 0;
68704
68763
  const start = hasEnvironment ? await startCommandState(statusPath) : void 0;
68705
- const snapshot2 = agentContextSnapshot({
68764
+ const snapshot = agentContextSnapshot({
68706
68765
  spec,
68707
68766
  ...spec.approvedWorkspacePaths?.[0] ? { workspaceRoot: spec.approvedWorkspacePaths[0] } : {},
68708
68767
  problems,
@@ -68710,39 +68769,39 @@ function createAgentContext(deps) {
68710
68769
  startLogPath: logPath,
68711
68770
  ...known ? { known } : {}
68712
68771
  });
68713
- if (snapshot2 === null) return void 0;
68714
- const rendered = renderAgentContext(snapshot2, known);
68772
+ if (snapshot === null) return void 0;
68773
+ const rendered = renderAgentContext(snapshot, known);
68715
68774
  return {
68716
68775
  full: rendered.full,
68717
68776
  ...rendered.update ? { update: rendered.update } : {},
68718
- save: () => writeJsonFileAtomic(file2, snapshot2)
68777
+ save: () => writeJsonFileAtomic(file2, snapshot)
68719
68778
  };
68720
68779
  };
68721
68780
  }
68722
68781
 
68723
68782
  // src/holder/checkout-refresh.ts
68724
- var import_node_path60 = require("path");
68783
+ var import_node_path59 = require("path");
68725
68784
 
68726
68785
  // src/holder/claim-once.ts
68727
68786
  var import_node_crypto28 = require("crypto");
68728
- var import_promises60 = require("fs/promises");
68729
- var import_node_path58 = require("path");
68787
+ var import_promises59 = require("fs/promises");
68788
+ var import_node_path57 = require("path");
68730
68789
  async function claimOnce(dir, name) {
68731
68790
  try {
68732
- await (0, import_promises60.mkdir)(dir, { recursive: true, mode: 448 });
68733
- await (await (0, import_promises60.open)((0, import_node_path58.join)(dir, name), "wx")).close();
68791
+ await (0, import_promises59.mkdir)(dir, { recursive: true, mode: 448 });
68792
+ await (await (0, import_promises59.open)((0, import_node_path57.join)(dir, name), "wx")).close();
68734
68793
  return true;
68735
68794
  } catch {
68736
68795
  return false;
68737
68796
  }
68738
68797
  }
68739
68798
  function claimFirstLease(freshnessDir, path4) {
68740
- return claimOnce((0, import_node_path58.join)(freshnessDir, "leased"), (0, import_node_crypto28.createHash)("sha256").update(path4).digest("hex"));
68799
+ return claimOnce((0, import_node_path57.join)(freshnessDir, "leased"), (0, import_node_crypto28.createHash)("sha256").update(path4).digest("hex"));
68741
68800
  }
68742
68801
 
68743
68802
  // src/holder/requested-checkout.ts
68744
- var import_promises61 = require("fs/promises");
68745
- var import_node_path59 = require("path");
68803
+ var import_promises60 = require("fs/promises");
68804
+ var import_node_path58 = require("path");
68746
68805
  var REMOTE2 = "origin";
68747
68806
  var REASON_MAX_CHARS = 200;
68748
68807
  function firstLine3(text3) {
@@ -68763,8 +68822,8 @@ function notSwitched(checkout, current, reason) {
68763
68822
  );
68764
68823
  }
68765
68824
  async function clone2(checkout, deps, signal) {
68766
- const parent = (0, import_node_path59.dirname)(checkout.path);
68767
- await (0, import_promises61.mkdir)(parent, { recursive: true });
68825
+ const parent = (0, import_node_path58.dirname)(checkout.path);
68826
+ await (0, import_promises60.mkdir)(parent, { recursive: true });
68768
68827
  await assertValidBranch(deps.git, parent, checkout.branch, signal);
68769
68828
  const output2 = await deps.git.run(
68770
68829
  {
@@ -68916,9 +68975,9 @@ async function applyRequestedCheckout(checkout, spec, deps, signal) {
68916
68975
  function short(sha) {
68917
68976
  return sha.slice(0, 12);
68918
68977
  }
68919
- function staleCheckout(path4, snapshot2, tip) {
68920
- const checkout = snapshot2 === void 0 ? "is the environment snapshot's checkout" : `is the environment snapshot's checkout of ${snapshot2.branch} (commit ${short(snapshot2.head)})`;
68921
- const base = snapshot2 === void 0 ? "its upstream" : `origin/${snapshot2.base}`;
68978
+ function staleCheckout(path4, snapshot, tip) {
68979
+ const checkout = snapshot === void 0 ? "is the environment snapshot's checkout" : `is the environment snapshot's checkout of ${snapshot.branch} (commit ${short(snapshot.head)})`;
68980
+ const base = snapshot === void 0 ? "its upstream" : `origin/${snapshot.base}`;
68922
68981
  const remote = tip === void 0 ? "may be ahead" : `is ahead at ${short(tip)}`;
68923
68982
  return {
68924
68983
  path: path4,
@@ -68929,18 +68988,18 @@ function staleCheckout(path4, snapshot2, tip) {
68929
68988
  async function fastForward(freshness, operationId, deps, signal) {
68930
68989
  var _stack = [];
68931
68990
  try {
68932
- const { path: cwd, snapshot: snapshot2, tip } = freshness;
68933
- const attempt2 = await deps.locks.tryExclusive(snapshot2.commonDir, operationId);
68991
+ const { path: cwd, snapshot, tip } = freshness;
68992
+ const attempt2 = await deps.locks.tryExclusive(snapshot.commonDir, operationId);
68934
68993
  if (attempt2.kind === "busy") return false;
68935
68994
  const _lock = __using(_stack, attempt2.lock, true);
68936
68995
  const now = await readCheckoutStatus(deps.git, cwd, signal);
68937
- if (now === null || now.dirty || now.head !== snapshot2.head || now.branch !== snapshot2.branch) {
68996
+ if (now === null || now.dirty || now.head !== snapshot.head || now.branch !== snapshot.branch) {
68938
68997
  return false;
68939
68998
  }
68940
68999
  const git = (args) => deps.git.run({ cwd, args }, signal);
68941
69000
  if ((await git(["switch", "--quiet", "--detach", tip])).exitCode !== 0) return false;
68942
- const moved = await git(["update-ref", `refs/heads/${snapshot2.branch}`, tip, snapshot2.head]);
68943
- const back = await git(["switch", "--quiet", snapshot2.branch]);
69001
+ const moved = await git(["update-ref", `refs/heads/${snapshot.branch}`, tip, snapshot.head]);
69002
+ const back = await git(["switch", "--quiet", snapshot.branch]);
68944
69003
  return moved.exitCode === 0 && back.exitCode === 0;
68945
69004
  } catch (_) {
68946
69005
  var _error = _, _hasError = true;
@@ -68972,9 +69031,8 @@ function problemFor(freshness) {
68972
69031
  return staleCheckout(freshness.path, void 0);
68973
69032
  }
68974
69033
  }
68975
- async function checkoutsOf(spec, leaseTargets) {
68976
- if (leaseTargets.length > 0 || spec.projectPath === void 0) return [...leaseTargets];
68977
- return checkoutsUnder(spec.projectPath);
69034
+ async function checkoutsOf(spec) {
69035
+ return spec.projectPath === void 0 ? [] : checkoutsUnder(spec.projectPath);
68978
69036
  }
68979
69037
  function requestedCheckoutsOf(spec, log) {
68980
69038
  const roots = spec.approvedWorkspacePaths ?? [];
@@ -69002,7 +69060,7 @@ async function applyRequestedCheckouts(spec, deps, signal) {
69002
69060
  ...outcome2.kind === "moved" ? { how: outcome2.how } : {}
69003
69061
  });
69004
69062
  if (outcome2.kind === "on_branch") continue;
69005
- settled2.add((0, import_node_path60.resolve)(checkout.path));
69063
+ settled2.add((0, import_node_path59.resolve)(checkout.path));
69006
69064
  if (outcome2.kind === "noted") {
69007
69065
  problems.push({ path: checkout.path, problem: outcome2.problem, action: outcome2.action });
69008
69066
  }
@@ -69012,7 +69070,7 @@ async function applyRequestedCheckouts(spec, deps, signal) {
69012
69070
  async function refreshSnapshotCheckouts(spec, targets, settled2, deps, signal) {
69013
69071
  const problems = [];
69014
69072
  for (const target of targets) {
69015
- if (settled2.has((0, import_node_path60.resolve)(target))) continue;
69073
+ if (settled2.has((0, import_node_path59.resolve)(target))) continue;
69016
69074
  const freshness = await readCheckoutFreshness(deps.dir, target);
69017
69075
  if (freshness === null) continue;
69018
69076
  const outcome2 = await atFirstLease(freshness, spec, deps, signal).catch(
@@ -69029,11 +69087,11 @@ async function refreshSnapshotCheckouts(spec, targets, settled2, deps, signal) {
69029
69087
  return problems;
69030
69088
  }
69031
69089
  function createCheckoutRefresh(deps) {
69032
- return async (spec, leaseTargets, signal) => {
69090
+ return async (spec, signal) => {
69033
69091
  if (spec.providerSessionId !== void 0) return [];
69034
- if (!await claimOnce((0, import_node_path60.join)(deps.dir, "conversations"), spec.conversationId)) return [];
69092
+ if (!await claimOnce((0, import_node_path59.join)(deps.dir, "conversations"), spec.conversationId)) return [];
69035
69093
  const requested = await applyRequestedCheckouts(spec, deps, signal);
69036
- const targets = await checkoutsOf(spec, leaseTargets);
69094
+ const targets = await checkoutsOf(spec);
69037
69095
  return [
69038
69096
  ...requested.problems,
69039
69097
  ...await refreshSnapshotCheckouts(spec, targets, requested.settled, deps, signal)
@@ -69041,207 +69099,6 @@ function createCheckoutRefresh(deps) {
69041
69099
  };
69042
69100
  }
69043
69101
 
69044
- // src/holder/lease.ts
69045
- var import_promises62 = require("fs/promises");
69046
- var import_node_path61 = require("path");
69047
- var LEASE_CHECK_EVERY_MS = 5e3;
69048
- var MAX_TRANSIENT_FAILURES = 3;
69049
- var BACKOFF_BASE_MS = 1e3;
69050
- var BACKOFF_MAX_MS = 15e3;
69051
- var MESSAGES = {
69052
- workspace_lease_unavailable: "The workspace or Git checkout became unavailable while the run was active. Restore it and start a new run.",
69053
- workspace_lease_path_changed: "The selected workspace folder changed while the run was active. The run stopped before continuing; choose the correct folder and start a new run.",
69054
- workspace_lease_repository_changed: "The workspace now points to a different repository or worktree. The run stopped before continuing; restore the original checkout and start a new run."
69055
- };
69056
- function identityFailure(code, workspacePath) {
69057
- return { code, problemCode: "app.workspace.missing", message: MESSAGES[code], workspacePath };
69058
- }
69059
- async function fileIdentity(path4) {
69060
- const canonical = await (0, import_promises62.realpath)(path4);
69061
- const info = await (0, import_promises62.stat)(canonical, { bigint: true });
69062
- return `${canonical}:${info.dev}:${info.ino}`;
69063
- }
69064
- async function snapshot(git, path4, signal) {
69065
- try {
69066
- const output2 = await git.run(
69067
- {
69068
- cwd: path4,
69069
- args: ["rev-parse", "--path-format=absolute", "--git-dir", "--git-common-dir"],
69070
- readOnly: true
69071
- },
69072
- signal
69073
- );
69074
- const [gitDir, commonDir] = output2.stdout.trim().split("\n");
69075
- if (output2.exitCode !== 0 || !gitDir || !commonDir) return null;
69076
- return {
69077
- workspace: await fileIdentity(path4),
69078
- repository: await fileIdentity(commonDir),
69079
- worktree: await fileIdentity(gitDir),
69080
- commonDir: await (0, import_promises62.realpath)(commonDir)
69081
- };
69082
- } catch {
69083
- return null;
69084
- }
69085
- }
69086
- async function gitValue(git, path4, args, signal) {
69087
- const output2 = await git.run({ cwd: path4, args, readOnly: true }, signal).catch(() => null);
69088
- const value2 = output2?.exitCode === 0 ? output2.stdout.trim() : "";
69089
- return value2.length > 0 ? value2 : null;
69090
- }
69091
- async function pathExists(path4) {
69092
- try {
69093
- await (0, import_promises62.stat)(path4);
69094
- return true;
69095
- } catch (error61) {
69096
- return errnoCode(error61) !== "ENOENT" && errnoCode(error61) !== "ENOTDIR";
69097
- }
69098
- }
69099
- async function hasGitMarker(path4) {
69100
- let directory;
69101
- try {
69102
- directory = await (0, import_promises62.realpath)(path4);
69103
- } catch {
69104
- return true;
69105
- }
69106
- for (; ; ) {
69107
- try {
69108
- await (0, import_promises62.stat)((0, import_node_path61.join)(directory, ".git"));
69109
- return true;
69110
- } catch (error61) {
69111
- const code = errnoCode(error61);
69112
- if (code !== "ENOENT" && code !== "ENOTDIR") return true;
69113
- }
69114
- const parent = (0, import_node_path61.dirname)(directory);
69115
- if (parent === directory) return false;
69116
- directory = parent;
69117
- }
69118
- }
69119
- async function probeCheckout(git, path4, captured, signal) {
69120
- const current = await snapshot(git, path4, signal);
69121
- if (current === null) {
69122
- const failure6 = identityFailure("workspace_lease_unavailable", path4);
69123
- return await pathExists(path4) ? { kind: "transient", failure: failure6 } : { kind: "failed", failure: failure6 };
69124
- }
69125
- if (current.workspace !== captured.workspace) {
69126
- return { kind: "failed", failure: identityFailure("workspace_lease_path_changed", path4) };
69127
- }
69128
- if (current.repository !== captured.repository || current.worktree !== captured.worktree) {
69129
- return { kind: "failed", failure: identityFailure("workspace_lease_repository_changed", path4) };
69130
- }
69131
- return { kind: "ok" };
69132
- }
69133
- async function releaseAll(locks) {
69134
- for (const lock of locks) await lock[Symbol.asyncDispose]();
69135
- }
69136
- async function captureOne(git, path4, signal) {
69137
- const identity = await snapshot(git, path4, signal);
69138
- if (identity === null) return identityFailure("workspace_lease_unavailable", path4);
69139
- const branch = await gitValue(git, path4, ["symbolic-ref", "-q", "--short", "HEAD"], signal);
69140
- const head = await gitValue(git, path4, ["rev-parse", "-q", "--verify", "HEAD"], signal);
69141
- return { path: path4, identity, checkout: { path: path4, commonDir: identity.commonDir, branch, head } };
69142
- }
69143
- async function captureWorkspaceLease(runId, paths, deps, signal) {
69144
- const captured = [];
69145
- const locks = [];
69146
- const locked = /* @__PURE__ */ new Set();
69147
- for (const path4 of paths) {
69148
- const one = await captureOne(deps.git, path4, signal);
69149
- if (!("identity" in one)) {
69150
- await releaseAll(locks);
69151
- return { kind: "failed", failure: one };
69152
- }
69153
- const key = comparablePath(one.identity.commonDir, deps.platform);
69154
- if (!locked.has(key)) {
69155
- const attempt2 = await deps.locks.tryShared(one.identity.commonDir, runId);
69156
- if (attempt2.kind === "busy") {
69157
- await releaseAll(locks);
69158
- return {
69159
- kind: "failed",
69160
- failure: {
69161
- code: "workspace_busy",
69162
- problemCode: null,
69163
- message: "Alan is committing or pushing in this repository for a checkout switch. Try again when it finishes.",
69164
- workspacePath: path4
69165
- }
69166
- };
69167
- }
69168
- locked.add(key);
69169
- locks.push(attempt2.lock);
69170
- }
69171
- captured.push(one);
69172
- }
69173
- return { kind: "held", lease: holdLease(captured, locks, deps) };
69174
- }
69175
- function holdLease(captured, locks, deps) {
69176
- const lifetime = new AbortController();
69177
- const lost = new AbortController();
69178
- const state = { failure: null, inFlight: null, transientStreak: 0, nextCheckAt: 0 };
69179
- const probeOnce = async () => {
69180
- for (const { path: path4, identity } of captured) {
69181
- const probe = await probeCheckout(deps.git, path4, identity, lifetime.signal);
69182
- if (probe.kind !== "ok") return probe;
69183
- }
69184
- return { kind: "ok" };
69185
- };
69186
- const lose = (failure6) => {
69187
- if (state.failure !== null) return;
69188
- state.failure = failure6;
69189
- deps.log.warn("holder.workspace_lease_lost", {
69190
- code: failure6.code,
69191
- workspacePath: failure6.workspacePath
69192
- });
69193
- lost.abort(failure6);
69194
- };
69195
- const apply = (probe) => {
69196
- if (probe.kind === "ok") {
69197
- state.transientStreak = 0;
69198
- state.nextCheckAt = 0;
69199
- } else if (probe.kind === "failed") {
69200
- lose(probe.failure);
69201
- } else {
69202
- state.transientStreak += 1;
69203
- if (state.transientStreak >= MAX_TRANSIENT_FAILURES) lose(probe.failure);
69204
- else {
69205
- const backoff = BACKOFF_BASE_MS * 2 ** (state.transientStreak - 1);
69206
- state.nextCheckAt = deps.clock.monotonic() + Math.min(backoff, BACKOFF_MAX_MS);
69207
- }
69208
- }
69209
- return state.failure === null;
69210
- };
69211
- const check3 = () => {
69212
- if (state.failure !== null) return Promise.resolve(false);
69213
- state.inFlight ??= probeOnce().then((probe) => lifetime.signal.aborted ? state.failure === null : apply(probe)).finally(() => {
69214
- state.inFlight = null;
69215
- });
69216
- return state.inFlight;
69217
- };
69218
- const monitor = captured.length === 0 ? null : startMaintenance({
69219
- everyMs: deps.everyMs ?? LEASE_CHECK_EVERY_MS,
69220
- jobs: [
69221
- {
69222
- name: "holder.workspace_lease",
69223
- run: async () => {
69224
- if (state.failure !== null || deps.clock.monotonic() < state.nextCheckAt) return;
69225
- await check3();
69226
- }
69227
- }
69228
- ],
69229
- clock: deps.clock,
69230
- log: deps.log
69231
- });
69232
- return {
69233
- checkouts: captured.map((entry) => entry.checkout),
69234
- lost: lost.signal,
69235
- failure: () => state.failure,
69236
- verify: check3,
69237
- [Symbol.asyncDispose]: async () => {
69238
- lifetime.abort();
69239
- await monitor?.[Symbol.asyncDispose]();
69240
- await releaseAll(locks);
69241
- }
69242
- };
69243
- }
69244
-
69245
69102
  // src/holder/admission.ts
69246
69103
  var VOLUME_ERRORS = /* @__PURE__ */ new Set([
69247
69104
  "EIO",
@@ -69250,13 +69107,12 @@ var VOLUME_ERRORS = /* @__PURE__ */ new Set([
69250
69107
  "ENXIO",
69251
69108
  "ESTALE"
69252
69109
  ]);
69253
- var MESSAGES2 = {
69110
+ var MESSAGES = {
69254
69111
  missing: "This project folder was moved or removed. Locate it before starting the run.",
69255
69112
  permission: "Alan needs permission to access this project folder.",
69256
69113
  volume: "The drive containing this project is unavailable. Connect it and try again.",
69257
69114
  pinnedMissing: "This run must use exactly this project folder, and it was moved or removed. Restore it or choose another folder.",
69258
- notApproved: "This folder is not one of the workspaces approved on this computer.",
69259
- mismatch: "This folder belongs to a different repository. Choose the correct project folder and try again."
69115
+ notApproved: "This folder is not one of the workspaces approved on this computer."
69260
69116
  };
69261
69117
  function rejected(rejection2, message2) {
69262
69118
  return { kind: "rejected", rejection: rejection2, message: message2 };
@@ -69275,7 +69131,7 @@ function volumeRoot(path4) {
69275
69131
  }
69276
69132
  async function exists4(path4) {
69277
69133
  try {
69278
- await (0, import_promises63.stat)(path4);
69134
+ await (0, import_promises61.stat)(path4);
69279
69135
  return true;
69280
69136
  } catch {
69281
69137
  return false;
@@ -69283,30 +69139,23 @@ async function exists4(path4) {
69283
69139
  }
69284
69140
  async function inspectReadiness(path4) {
69285
69141
  try {
69286
- if (!(await (0, import_promises63.stat)(path4)).isDirectory()) {
69287
- return { ready: false, missing: true, message: MESSAGES2.missing };
69142
+ if (!(await (0, import_promises61.stat)(path4)).isDirectory()) {
69143
+ return { ready: false, missing: true, message: MESSAGES.missing };
69288
69144
  }
69289
- await (0, import_promises63.access)(path4, import_node_fs19.constants.R_OK | import_node_fs19.constants.W_OK | import_node_fs19.constants.X_OK);
69145
+ await (0, import_promises61.access)(path4, import_node_fs19.constants.R_OK | import_node_fs19.constants.W_OK | import_node_fs19.constants.X_OK);
69290
69146
  return { ready: true };
69291
69147
  } catch (error61) {
69292
69148
  const code = errnoCode(error61) ?? "";
69293
69149
  if (code === "EACCES" || code === "EPERM") {
69294
- return { ready: false, missing: false, message: MESSAGES2.permission };
69150
+ return { ready: false, missing: false, message: MESSAGES.permission };
69295
69151
  }
69296
69152
  const root = volumeRoot(path4);
69297
69153
  if (VOLUME_ERRORS.has(code) || code === "ENOENT" && root !== null && !await exists4(root)) {
69298
- return { ready: false, missing: false, message: MESSAGES2.volume };
69154
+ return { ready: false, missing: false, message: MESSAGES.volume };
69299
69155
  }
69300
- return { ready: false, missing: true, message: MESSAGES2.missing };
69156
+ return { ready: false, missing: true, message: MESSAGES.missing };
69301
69157
  }
69302
69158
  }
69303
- function expectedRepositoryUrls(spec, projectPath, platform3) {
69304
- const folder = comparablePath(projectPath, platform3);
69305
- return [
69306
- ...(spec.repoLocalPaths ?? []).filter((repo) => comparablePath(repo.localPath, platform3) === folder).map((repo) => repo.repoUrl),
69307
- ...spec.localRepoUrls ?? []
69308
- ];
69309
- }
69310
69159
  function resolveSelectedSkills(spec, context) {
69311
69160
  const invocations = spec.skillInvocations ?? [];
69312
69161
  if (context.skills === void 0) {
@@ -69333,51 +69182,18 @@ async function checkProvider(spec, context) {
69333
69182
  `The ${provider4.name} CLI (\`${provider4.command}\`) is not installed on this computer, or it is not on the PATH Alan uses. Install it and try again.`
69334
69183
  );
69335
69184
  }
69336
- async function locateWorkspace(spec, projectPath, expected, context, signal) {
69337
- const readiness2 = await inspectReadiness(projectPath);
69338
- if (readiness2.ready) return { cwd: projectPath, relocated: null };
69339
- if (!readiness2.missing) return rejected("workspace_unavailable", readiness2.message);
69340
- if (spec.workspacePathPinned === true) {
69341
- return rejected("workspace_pinned_missing", MESSAGES2.pinnedMissing);
69342
- }
69343
- const found = await discoverRelocatedWorkspace({
69344
- missingPath: projectPath,
69345
- approvedWorkspacePaths: spec.approvedWorkspacePaths ?? [],
69346
- expected,
69347
- git: context.git,
69348
- platform: context.platform,
69349
- signal
69350
- });
69351
- if (found === null) return rejected("workspace_unavailable", readiness2.message);
69352
- const moved = await inspectReadiness(found);
69353
- if (!moved.ready) return rejected("workspace_unavailable", moved.message);
69354
- return {
69355
- cwd: found,
69356
- relocated: {
69357
- sessionUpdate: "_alan/run.workspace_relocated",
69358
- previousPath: projectPath,
69359
- canonicalPath: found
69360
- }
69361
- };
69362
- }
69363
69185
  async function admitDefaultWorkspace(spec, context, skills) {
69364
69186
  const { env } = context;
69365
69187
  const path4 = resolveAlanDefaultWorkspacePath(env.HOME || env.USERPROFILE || (0, import_node_os9.homedir)());
69366
69188
  try {
69367
- await (0, import_promises63.mkdir)(path4, { recursive: true, mode: 448 });
69368
- await (0, import_promises63.access)(path4, import_node_fs19.constants.R_OK | import_node_fs19.constants.W_OK | import_node_fs19.constants.X_OK);
69369
- return {
69370
- kind: "admitted",
69371
- spec: { ...spec, projectPath: path4 },
69372
- relocated: null,
69373
- leaseTargets: [],
69374
- skills
69375
- };
69189
+ await (0, import_promises61.mkdir)(path4, { recursive: true, mode: 448 });
69190
+ await (0, import_promises61.access)(path4, import_node_fs19.constants.R_OK | import_node_fs19.constants.W_OK | import_node_fs19.constants.X_OK);
69191
+ return { kind: "admitted", spec: { ...spec, projectPath: path4 }, skills };
69376
69192
  } catch (error61) {
69377
69193
  const code = errnoCode(error61);
69378
69194
  return rejected(
69379
69195
  "workspace_unavailable",
69380
- code === "EACCES" || code === "EPERM" ? MESSAGES2.permission : MESSAGES2.missing
69196
+ code === "EACCES" || code === "EPERM" ? MESSAGES.permission : MESSAGES.missing
69381
69197
  );
69382
69198
  }
69383
69199
  }
@@ -69391,7 +69207,7 @@ async function withInstalledCloudSkills(spec, context) {
69391
69207
  }
69392
69208
  };
69393
69209
  }
69394
- async function admitRun(spec, context, signal) {
69210
+ async function admitRun(spec, context) {
69395
69211
  const provider4 = await checkProvider(spec, context);
69396
69212
  if (provider4 !== null) return provider4;
69397
69213
  const selected = await resolveSelectedSkills(spec, context);
@@ -69404,50 +69220,30 @@ async function admitRun(spec, context, signal) {
69404
69220
  const skills = selected.skills;
69405
69221
  spec = await withInstalledCloudSkills(spec, context);
69406
69222
  const projectPath = spec.projectPath;
69407
- if (projectPath === void 0) {
69408
- return { kind: "admitted", spec, relocated: null, leaseTargets: [], skills };
69409
- }
69223
+ if (projectPath === void 0) return { kind: "admitted", spec, skills };
69410
69224
  if (isAlanDefaultWorkspace(projectPath)) return admitDefaultWorkspace(spec, context, skills);
69411
- const { platform: platform3 } = context;
69412
- const expected = repositoryIdentities(expectedRepositoryUrls(spec, projectPath, platform3));
69413
- const located = await locateWorkspace(spec, projectPath, expected, context, signal);
69414
- if ("kind" in located) return located;
69415
- const { cwd, relocated } = located;
69225
+ const readiness2 = await inspectReadiness(projectPath);
69226
+ if (!readiness2.ready) {
69227
+ return readiness2.missing && spec.workspacePathPinned === true ? rejected("workspace_pinned_missing", MESSAGES.pinnedMissing) : rejected("workspace_unavailable", readiness2.message);
69228
+ }
69416
69229
  const roots = [
69417
69230
  ...await context.approvedRoots(),
69418
69231
  projectPath,
69419
69232
  ...spec.approvedWorkspacePaths ?? [],
69420
- ...(spec.repoLocalPaths ?? []).map((repo) => repo.localPath),
69421
- ...relocated === null ? [] : [relocated.canonicalPath]
69233
+ ...(spec.repoLocalPaths ?? []).map((repo) => repo.localPath)
69422
69234
  ];
69423
- if (!await isApprovedPath(cwd, roots, platform3)) {
69424
- return rejected("workspace_unavailable", MESSAGES2.notApproved);
69235
+ if (!await isApprovedPath(projectPath, roots, context.platform)) {
69236
+ return rejected("workspace_unavailable", MESSAGES.notApproved);
69425
69237
  }
69426
- if (expected.size > 0) {
69427
- const identity = await originIdentity(context.git, cwd, signal);
69428
- if (identity === null || !expected.has(identity)) {
69429
- return rejected("workspace_repository_mismatch", MESSAGES2.mismatch);
69430
- }
69431
- }
69432
- return {
69433
- kind: "admitted",
69434
- spec: relocated === null ? spec : { ...spec, projectPath: cwd },
69435
- relocated,
69436
- leaseTargets: await hasGitMarker(cwd) ? [cwd] : [],
69437
- skills
69438
- };
69238
+ return { kind: "admitted", spec, skills };
69439
69239
  }
69440
- var PROBE_TIMEOUT_MS2 = 5e3;
69441
69240
  var CHECKOUT_LOCAL_TIMEOUT_MS = 6e4;
69442
69241
  var CHECKOUT_NETWORK_TIMEOUT_MS = 12e4;
69443
69242
  function createHolderWorkspace(machine, clock, log) {
69444
69243
  const platform3 = machine.platform ?? process.platform;
69445
- const git = createGitRunner({ env: machine.env, platform: platform3, localTimeoutMs: PROBE_TIMEOUT_MS2 });
69446
- const locks = openRepositoryLocks({ dir: (0, import_node_path62.join)(machine.stateDir, "locks"), clock, platform: platform3 });
69447
69244
  return {
69448
69245
  admission: {
69449
69246
  env: machine.env,
69450
- git,
69451
69247
  platform: platform3,
69452
69248
  skills: skillsLayout(
69453
69249
  machine.stateDir,
@@ -69455,14 +69251,13 @@ function createHolderWorkspace(machine, clock, log) {
69455
69251
  ),
69456
69252
  approvedRoots: async () => {
69457
69253
  const approved = await openApprovedPaths({
69458
- file: (0, import_node_path62.join)(machine.stateDir, "workspaces.json"),
69254
+ file: (0, import_node_path60.join)(machine.stateDir, "workspaces.json"),
69459
69255
  log,
69460
69256
  platform: platform3
69461
69257
  });
69462
69258
  return approved.roots();
69463
69259
  }
69464
69260
  },
69465
- lease: { git, locks, clock, log, platform: platform3 },
69466
69261
  ...machine.refreshesFirstCheckout === true ? {
69467
69262
  refreshFirstCheckout: createCheckoutRefresh({
69468
69263
  git: createGitRunner({
@@ -69471,12 +69266,12 @@ function createHolderWorkspace(machine, clock, log) {
69471
69266
  localTimeoutMs: CHECKOUT_LOCAL_TIMEOUT_MS,
69472
69267
  networkTimeoutMs: CHECKOUT_NETWORK_TIMEOUT_MS
69473
69268
  }),
69474
- locks,
69269
+ locks: openRepositoryLocks({ dir: (0, import_node_path60.join)(machine.stateDir, "locks"), clock, platform: platform3 }),
69475
69270
  log,
69476
- dir: (0, import_node_path62.join)(machine.stateDir, "checkout-freshness")
69271
+ dir: (0, import_node_path60.join)(machine.stateDir, "checkout-freshness")
69477
69272
  }),
69478
69273
  prepareAgentContext: createAgentContext({
69479
- dir: (0, import_node_path62.join)(machine.stateDir, "agent-context"),
69274
+ dir: (0, import_node_path60.join)(machine.stateDir, "agent-context"),
69480
69275
  homeDir: machine.env.HOME || (0, import_node_os9.homedir)()
69481
69276
  })
69482
69277
  } : {}
@@ -69484,28 +69279,14 @@ function createHolderWorkspace(machine, clock, log) {
69484
69279
  }
69485
69280
 
69486
69281
  // src/holder/respond.ts
69487
- function createAnswerGate() {
69488
- const state = { lease: null };
69489
- return {
69490
- allows: () => state.lease?.verify() ?? Promise.resolve(true),
69491
- guard: (lease) => {
69492
- state.lease = lease;
69493
- return {
69494
- [Symbol.dispose]: () => {
69495
- if (state.lease === lease) state.lease = null;
69496
- }
69497
- };
69498
- }
69499
- };
69500
- }
69501
- async function respondToTurn(runningRunId, gate, driver, request2) {
69282
+ async function respondToTurn(runningRunId, driver, request2) {
69502
69283
  if (runningRunId !== request2.runId) return "unknown_run";
69503
69284
  if (driver.respond === void 0) return "not_waiting";
69504
- return driver.respond(request2, () => gate.allows());
69285
+ return driver.respond(request2);
69505
69286
  }
69506
69287
 
69507
69288
  // src/holder/session-facts.ts
69508
- var import_promises64 = require("fs/promises");
69289
+ var import_promises62 = require("fs/promises");
69509
69290
  var CLI_RSS_CACHE_MS = 1e4;
69510
69291
  var LOGIN_PROBLEM_PREFIX = "cli.auth.";
69511
69292
  function isLoginFailure(result) {
@@ -69531,8 +69312,8 @@ function createSessionFacts(options) {
69531
69312
  const path4 = await resolveCommandOnPath(command, env, platform3);
69532
69313
  if (path4 === null) return null;
69533
69314
  try {
69534
- const real = await (0, import_promises64.realpath)(path4);
69535
- const info = await (0, import_promises64.stat)(real);
69315
+ const real = await (0, import_promises62.realpath)(path4);
69316
+ const info = await (0, import_promises62.stat)(real);
69536
69317
  return { command, key: `${real}:${info.ino}:${info.size}:${info.mtimeMs}` };
69537
69318
  } catch {
69538
69319
  return null;
@@ -69619,12 +69400,12 @@ function createSessionFacts(options) {
69619
69400
  init_acp2();
69620
69401
 
69621
69402
  // src/run-log/archive.ts
69622
- var import_promises65 = require("fs/promises");
69623
- var import_node_path63 = require("path");
69403
+ var import_promises63 = require("fs/promises");
69404
+ var import_node_path61 = require("path");
69624
69405
  init_runtime_v2();
69625
69406
  async function openRunArchive(runsDir) {
69626
- const path4 = (0, import_node_path63.join)((0, import_node_path63.dirname)(runsDir), "archived-runs.txt");
69627
- const text3 = await (0, import_promises65.readFile)(path4, "utf8").catch((error61) => {
69407
+ const path4 = (0, import_node_path61.join)((0, import_node_path61.dirname)(runsDir), "archived-runs.txt");
69408
+ const text3 = await (0, import_promises63.readFile)(path4, "utf8").catch((error61) => {
69628
69409
  if (errnoCode(error61) === "ENOENT") return "";
69629
69410
  throw error61;
69630
69411
  });
@@ -69638,7 +69419,7 @@ async function openRunArchive(runsDir) {
69638
69419
  add: async (runIds) => {
69639
69420
  const added = runIds.filter((runId) => !archived.has(runId));
69640
69421
  if (added.length === 0) return;
69641
- await (0, import_promises65.appendFile)(path4, `
69422
+ await (0, import_promises63.appendFile)(path4, `
69642
69423
  ${added.join("\n")}
69643
69424
  `, { mode: 384 });
69644
69425
  for (const runId of added) archived.add(runId);
@@ -69649,11 +69430,11 @@ ${added.join("\n")}
69649
69430
  // src/run-log/complete.ts
69650
69431
  var import_node_crypto29 = require("crypto");
69651
69432
  var import_node_fs20 = require("fs");
69652
- var import_node_path65 = require("path");
69433
+ var import_node_path63 = require("path");
69653
69434
 
69654
69435
  // src/run-log/directory.ts
69655
- var import_promises66 = require("fs/promises");
69656
- var import_node_path64 = require("path");
69436
+ var import_promises64 = require("fs/promises");
69437
+ var import_node_path62 = require("path");
69657
69438
  init_runtime_v2();
69658
69439
  init_zod();
69659
69440
  var runMetaSchema = external_exports.object({
@@ -69679,17 +69460,17 @@ async function readRunMeta(path4) {
69679
69460
  return read.kind === "ok" ? read.value : null;
69680
69461
  }
69681
69462
  function runDirectory(runsDir, runId) {
69682
- const dir = (0, import_node_path64.join)(runsDir, runId);
69463
+ const dir = (0, import_node_path62.join)(runsDir, runId);
69683
69464
  return {
69684
69465
  dir,
69685
- log: (0, import_node_path64.join)(dir, "log.jsonl"),
69686
- upload: (0, import_node_path64.join)(dir, "upload.json"),
69687
- meta: (0, import_node_path64.join)(dir, "run.json")
69466
+ log: (0, import_node_path62.join)(dir, "log.jsonl"),
69467
+ upload: (0, import_node_path62.join)(dir, "upload.json"),
69468
+ meta: (0, import_node_path62.join)(dir, "run.json")
69688
69469
  };
69689
69470
  }
69690
69471
  async function isRunClaimed(runsDir, runId) {
69691
69472
  try {
69692
- return (await (0, import_promises66.stat)(runDirectory(runsDir, runId).log)).size > 0;
69473
+ return (await (0, import_promises64.stat)(runDirectory(runsDir, runId).log)).size > 0;
69693
69474
  } catch (error61) {
69694
69475
  if (errnoCode(error61) === "ENOENT") return false;
69695
69476
  throw error61;
@@ -69698,7 +69479,7 @@ async function isRunClaimed(runsDir, runId) {
69698
69479
 
69699
69480
  // src/run-log/complete.ts
69700
69481
  function writeLogFile(path4, dir, text3) {
69701
- const temp = (0, import_node_path65.join)(dir, `.log.${(0, import_node_crypto29.randomUUID)()}.tmp`);
69482
+ const temp = (0, import_node_path63.join)(dir, `.log.${(0, import_node_crypto29.randomUUID)()}.tmp`);
69702
69483
  const fd = (0, import_node_fs20.openSync)(temp, "wx", 384);
69703
69484
  try {
69704
69485
  (0, import_node_fs20.writeSync)(fd, text3);
@@ -69727,8 +69508,8 @@ async function writeCompleteRunLog(runsDir, meta3, records) {
69727
69508
  }
69728
69509
 
69729
69510
  // src/run-log/conversation-index.ts
69730
- var import_promises67 = require("fs/promises");
69731
- var import_node_path66 = require("path");
69511
+ var import_promises65 = require("fs/promises");
69512
+ var import_node_path64 = require("path");
69732
69513
  init_runtime_v2();
69733
69514
  init_zod();
69734
69515
  var ORDINALS_PER_SHARD = 1e3;
@@ -69745,13 +69526,13 @@ var coverageSchema = external_exports.object({
69745
69526
  nextExpectedOrdinal: external_exports.number().int().positive()
69746
69527
  });
69747
69528
  function conversationsDirectory(runsDir) {
69748
- return (0, import_node_path66.join)((0, import_node_path66.dirname)(runsDir), "conversations");
69529
+ return (0, import_node_path64.join)((0, import_node_path64.dirname)(runsDir), "conversations");
69749
69530
  }
69750
69531
  function indexDirectory(runsDir, conversationId) {
69751
- return (0, import_node_path66.join)(conversationsDirectory(runsDir), conversationId, "turn-index");
69532
+ return (0, import_node_path64.join)(conversationsDirectory(runsDir), conversationId, "turn-index");
69752
69533
  }
69753
69534
  function shardPath(runsDir, conversationId, ordinal) {
69754
- return (0, import_node_path66.join)(
69535
+ return (0, import_node_path64.join)(
69755
69536
  indexDirectory(runsDir, conversationId),
69756
69537
  `${Math.floor(ordinal / ORDINALS_PER_SHARD)}.jsonl`
69757
69538
  );
@@ -69760,10 +69541,10 @@ async function indexConversationRun(runsDir, conversationId, ordinal, assistantO
69760
69541
  const nextOrdinal = assistantOrdinal + 1;
69761
69542
  if (nextOrdinal <= ordinal) throw new Error("Assistant order must follow the prompt");
69762
69543
  const path4 = shardPath(runsDir, conversationId, ordinal);
69763
- await (0, import_promises67.mkdir)((0, import_node_path66.dirname)(path4), { recursive: true, mode: 448 });
69764
- await (0, import_promises67.appendFile)(path4, `${JSON.stringify({ ordinal, nextOrdinal, runId })}
69544
+ await (0, import_promises65.mkdir)((0, import_node_path64.dirname)(path4), { recursive: true, mode: 448 });
69545
+ await (0, import_promises65.appendFile)(path4, `${JSON.stringify({ ordinal, nextOrdinal, runId })}
69765
69546
  `, { mode: 384 });
69766
- const coveragePath = (0, import_node_path66.join)((0, import_node_path66.dirname)((0, import_node_path66.dirname)(path4)), "coverage.json");
69547
+ const coveragePath = (0, import_node_path64.join)((0, import_node_path64.dirname)((0, import_node_path64.dirname)(path4)), "coverage.json");
69767
69548
  const coverage = await readJsonFile(coveragePath, coverageSchema);
69768
69549
  const current = coverage.kind === "ok" ? coverage.value : null;
69769
69550
  const next = nextCoverage(current, ordinal, nextOrdinal);
@@ -69778,13 +69559,13 @@ function nextCoverage(current, ordinal, nextOrdinal) {
69778
69559
  return null;
69779
69560
  }
69780
69561
  async function readConversationIndexCoverage(runsDir, conversationId) {
69781
- const path4 = (0, import_node_path66.join)((0, import_node_path66.dirname)(indexDirectory(runsDir, conversationId)), "coverage.json");
69562
+ const path4 = (0, import_node_path64.join)((0, import_node_path64.dirname)(indexDirectory(runsDir, conversationId)), "coverage.json");
69782
69563
  const result = await readJsonFile(path4, coverageSchema);
69783
69564
  return result.kind === "ok" ? result.value : null;
69784
69565
  }
69785
69566
  async function readConversationRunIndex(runsDir, conversationId, before, limit) {
69786
69567
  const directory = indexDirectory(runsDir, conversationId);
69787
- const names = await (0, import_promises67.readdir)(directory).catch((error61) => {
69568
+ const names = await (0, import_promises65.readdir)(directory).catch((error61) => {
69788
69569
  if (error61.code === "ENOENT") return [];
69789
69570
  throw error61;
69790
69571
  });
@@ -69793,7 +69574,7 @@ async function readConversationRunIndex(runsDir, conversationId, before, limit)
69793
69574
  ).sort((left, right) => right - left);
69794
69575
  const selected = [];
69795
69576
  for (const shard of shards) {
69796
- const text3 = await (0, import_promises67.readFile)((0, import_node_path66.join)(directory, `${shard}.jsonl`), "utf8");
69577
+ const text3 = await (0, import_promises65.readFile)((0, import_node_path64.join)(directory, `${shard}.jsonl`), "utf8");
69797
69578
  const records = text3.split("\n").flatMap((line) => {
69798
69579
  if (!line) return [];
69799
69580
  const parsed = indexRecordSchema.parse(JSON.parse(line));
@@ -69818,7 +69599,7 @@ async function readIndexableRun(runsDir, name) {
69818
69599
  return { conversationId: meta3.conversationId, ordinal, assistantOrdinal, runId: runId.data };
69819
69600
  }
69820
69601
  async function readIndexableRuns(runsDir) {
69821
- const names = await (0, import_promises67.readdir)(runsDir).catch(() => []);
69602
+ const names = await (0, import_promises65.readdir)(runsDir).catch(() => []);
69822
69603
  const byConversation = /* @__PURE__ */ new Map();
69823
69604
  let next = 0;
69824
69605
  const worker = async () => {
@@ -69848,21 +69629,21 @@ async function writeConversationIndex(directory, runs) {
69848
69629
  else lines2.push(line);
69849
69630
  coverage = nextCoverage(coverage, run2.ordinal, nextOrdinal) ?? coverage;
69850
69631
  }
69851
- await (0, import_promises67.mkdir)((0, import_node_path66.join)(directory, "turn-index"), { recursive: true, mode: 448 });
69632
+ await (0, import_promises65.mkdir)((0, import_node_path64.join)(directory, "turn-index"), { recursive: true, mode: 448 });
69852
69633
  for (const [shard, lines2] of shards) {
69853
- await (0, import_promises67.writeFile)((0, import_node_path66.join)(directory, "turn-index", `${shard}.jsonl`), `${lines2.join("\n")}
69634
+ await (0, import_promises65.writeFile)((0, import_node_path64.join)(directory, "turn-index", `${shard}.jsonl`), `${lines2.join("\n")}
69854
69635
  `, {
69855
69636
  mode: 384
69856
69637
  });
69857
69638
  }
69858
- await (0, import_promises67.writeFile)((0, import_node_path66.join)(directory, "coverage.json"), `${JSON.stringify(coverage)}
69639
+ await (0, import_promises65.writeFile)((0, import_node_path64.join)(directory, "coverage.json"), `${JSON.stringify(coverage)}
69859
69640
  `, {
69860
69641
  mode: 384
69861
69642
  });
69862
69643
  }
69863
69644
  async function rebuildConversationIndexes(runsDir) {
69864
69645
  const root = conversationsDirectory(runsDir);
69865
- const exists6 = await (0, import_promises67.stat)(root).then(
69646
+ const exists6 = await (0, import_promises65.stat)(root).then(
69866
69647
  () => true,
69867
69648
  (error61) => {
69868
69649
  if (errnoCode(error61) === "ENOENT") return false;
@@ -69871,18 +69652,18 @@ async function rebuildConversationIndexes(runsDir) {
69871
69652
  );
69872
69653
  if (exists6) return 0;
69873
69654
  const building = `${root}.rebuilding`;
69874
- await (0, import_promises67.rm)(building, { recursive: true, force: true });
69875
- await (0, import_promises67.mkdir)(building, { recursive: true, mode: 448 });
69655
+ await (0, import_promises65.rm)(building, { recursive: true, force: true });
69656
+ await (0, import_promises65.mkdir)(building, { recursive: true, mode: 448 });
69876
69657
  const byConversation = await readIndexableRuns(runsDir);
69877
69658
  for (const [conversationId, runs] of byConversation) {
69878
- await writeConversationIndex((0, import_node_path66.join)(building, conversationId), runs);
69659
+ await writeConversationIndex((0, import_node_path64.join)(building, conversationId), runs);
69879
69660
  }
69880
- await (0, import_promises67.rename)(building, root);
69661
+ await (0, import_promises65.rename)(building, root);
69881
69662
  return byConversation.size;
69882
69663
  }
69883
69664
 
69884
69665
  // src/run-log/reader.ts
69885
- var import_promises68 = require("fs/promises");
69666
+ var import_promises66 = require("fs/promises");
69886
69667
  init_runtime_v2();
69887
69668
 
69888
69669
  // src/run-log/tail.ts
@@ -69905,7 +69686,7 @@ function firstRecordLength(bytes) {
69905
69686
  return bytes.indexOf(RUN_LOG_RECORD_SEPARATOR) + 1;
69906
69687
  }
69907
69688
  async function openRunLogReader(path4) {
69908
- const handle = await (0, import_promises68.open)(path4, "r");
69689
+ const handle = await (0, import_promises66.open)(path4, "r");
69909
69690
  const readAt = async (position, length) => {
69910
69691
  const buffer = Buffer.alloc(length);
69911
69692
  const { bytesRead } = await handle.read(buffer, 0, length, position);
@@ -69939,7 +69720,7 @@ async function openRunLogReader(path4) {
69939
69720
  };
69940
69721
  }
69941
69722
  async function readLastRecord(path4) {
69942
- const handle = await (0, import_promises68.open)(path4, "r").catch(() => null);
69723
+ const handle = await (0, import_promises66.open)(path4, "r").catch(() => null);
69943
69724
  if (handle === null) return null;
69944
69725
  try {
69945
69726
  const { size } = await handle.stat();
@@ -69973,7 +69754,7 @@ var decoder = new TextDecoder();
69973
69754
 
69974
69755
  // src/run-log/writer.ts
69975
69756
  var import_node_fs21 = require("fs");
69976
- var import_node_path67 = require("path");
69757
+ var import_node_path65 = require("path");
69977
69758
  init_runtime_v2();
69978
69759
  function lastSeq(fd, size) {
69979
69760
  for (const length of tailWindows(size)) {
@@ -69989,7 +69770,7 @@ function lastSeq(fd, size) {
69989
69770
  throw new RuntimeFault("record_too_large", "Run log tail record is larger than any record");
69990
69771
  }
69991
69772
  function openRunLog(path4, clock) {
69992
- (0, import_node_fs21.mkdirSync)((0, import_node_path67.dirname)(path4), { recursive: true, mode: 448 });
69773
+ (0, import_node_fs21.mkdirSync)((0, import_node_path65.dirname)(path4), { recursive: true, mode: 448 });
69993
69774
  const fd = (0, import_node_fs21.openSync)(path4, "a+", 384);
69994
69775
  let size = (0, import_node_fs21.fstatSync)(fd).size;
69995
69776
  let seq = lastSeq(fd, size);
@@ -70026,107 +69807,6 @@ function openRunLog(path4, clock) {
70026
69807
  };
70027
69808
  }
70028
69809
 
70029
- // src/holder/lease-gate.ts
70030
- init_acp();
70031
- var READ_ONLY_TOOL_KINDS = /* @__PURE__ */ new Set([
70032
- "read",
70033
- "search",
70034
- "think",
70035
- "fetch",
70036
- "switch_mode"
70037
- ]);
70038
- function gateWorkspaceWrites(sink, lease) {
70039
- const kinds = /* @__PURE__ */ new Map();
70040
- const state = { tail: Promise.resolve(), pending: 0, gate: null, blocked: 0 };
70041
- const writesFiles = (update) => {
70042
- if (!isUpdate(update, "tool_call_update")) return false;
70043
- if (typeof update.kind === "string") kinds.set(update.toolCallId, update.kind);
70044
- const kind = kinds.get(update.toolCallId);
70045
- return kind === void 0 || !READ_ONLY_TOOL_KINDS.has(kind);
70046
- };
70047
- const deliver = (event) => {
70048
- if (lease.failure() === null) {
70049
- sink.onEvent(event);
70050
- return;
70051
- }
70052
- if (event.update.sessionUpdate === "tool_call_update") state.blocked += 1;
70053
- };
70054
- const enqueue = (event, gate) => {
70055
- state.pending += 1;
70056
- state.tail = state.tail.then(async () => {
70057
- if (gate === null || await gate) deliver(event);
70058
- else if (event.update.sessionUpdate === "tool_call_update") state.blocked += 1;
70059
- }).finally(() => {
70060
- state.pending -= 1;
70061
- if (state.pending === 0) state.gate = null;
70062
- });
70063
- };
70064
- return {
70065
- onSpawned: (pid) => sink.onSpawned(pid),
70066
- onEvent: (event) => {
70067
- const write = writesFiles(event.update);
70068
- if (!write && state.pending === 0) {
70069
- deliver(event);
70070
- return;
70071
- }
70072
- if (write) state.gate ??= lease.verify();
70073
- enqueue(event, state.gate);
70074
- },
70075
- drain: async () => {
70076
- while (state.pending > 0) await state.tail;
70077
- },
70078
- blocked: () => state.blocked
70079
- };
70080
- }
70081
-
70082
- // src/holder/lease-turn.ts
70083
- function leaseNotice(failure6, blocked) {
70084
- const withheld = blocked === 0 ? "" : ` ${blocked} tool ${blocked === 1 ? "update was" : "updates were"} withheld.`;
70085
- return {
70086
- sessionUpdate: "notice",
70087
- severity: "error",
70088
- title: "The workspace changed while the agent was working",
70089
- description: `${failure6.message}${withheld}`,
70090
- _meta: {
70091
- "alan.dev/noticeKind": "workspace_lease_lost",
70092
- ...failure6.problemCode === null ? {} : { "alan.dev/problem": { domain: "application", code: failure6.problemCode } }
70093
- }
70094
- };
70095
- }
70096
- async function runLeased(spec, paths, turn, sink, signal, run2) {
70097
- var _stack = [];
70098
- try {
70099
- const capture = await captureWorkspaceLease(spec.runId, paths, turn.lease, signal);
70100
- if (capture.kind === "failed") {
70101
- turn.log.warn("holder.workspace_lease_refused", {
70102
- runId: spec.runId,
70103
- code: capture.failure.code
70104
- });
70105
- return { outcome: "failed", message: capture.failure.message };
70106
- }
70107
- const lease = __using(_stack, capture.lease, true);
70108
- const _answers = __using(_stack, turn.answerGate?.guard(lease));
70109
- turn.log.info("holder.workspace_leased", { runId: spec.runId, checkouts: lease.checkouts });
70110
- const gated = gateWorkspaceWrites(sink, lease);
70111
- const result = await run2(gated, AbortSignal.any([signal, lease.lost]));
70112
- await gated.drain();
70113
- const failure6 = lease.failure();
70114
- if (failure6 === null) return result;
70115
- sink.onEvent({ seq: 0, at: turn.clock.now(), update: leaseNotice(failure6, gated.blocked()) });
70116
- await turn.driver.suspend?.().catch((error61) => turn.log.warn("holder.driver_suspend_failed", { error: error61 }));
70117
- return {
70118
- outcome: "failed",
70119
- message: failure6.message,
70120
- ...result.providerSessionId === void 0 ? {} : { providerSessionId: result.providerSessionId }
70121
- };
70122
- } catch (_) {
70123
- var _error = _, _hasError = true;
70124
- } finally {
70125
- var _promise2 = __callDispose(_stack, _error, _hasError);
70126
- _promise2 && await _promise2;
70127
- }
70128
- }
70129
-
70130
69810
  // src/holder/record-fit.ts
70131
69811
  init_acp2();
70132
69812
  init_runtime_v2();
@@ -70164,11 +69844,11 @@ function fitForRunLog(update) {
70164
69844
  }
70165
69845
 
70166
69846
  // src/holder/turn.ts
70167
- async function runWithInputs({ spec, leaseTargets, skills }, context, sink, signal) {
69847
+ async function runWithInputs({ spec, skills }, context, sink, signal) {
70168
69848
  var _stack = [];
70169
69849
  try {
70170
69850
  const workspace = context.workspace;
70171
- const sessionContext = (workspace?.refreshFirstCheckout?.(spec, leaseTargets, signal) ?? Promise.resolve([])).catch((error61) => {
69851
+ const sessionContext = (workspace?.refreshFirstCheckout?.(spec, signal) ?? Promise.resolve([])).catch((error61) => {
70172
69852
  context.log.warn("workspace.refresh_failed", { runId: spec.runId, error: error61 });
70173
69853
  return [];
70174
69854
  }).then((problems) => workspace?.prepareAgentContext?.(spec, problems)).catch((error61) => {
@@ -70187,35 +69867,24 @@ async function runWithInputs({ spec, leaseTargets, skills }, context, sink, sign
70187
69867
  }
70188
69868
  const agentContext = await sessionContext;
70189
69869
  const prepared = __using(_stack, inputs, true);
70190
- const run2 = async (turnSink, turnSignal) => {
70191
- const result = await context.driver.runTurn(
70192
- spec,
70193
- turnSink,
70194
- turnSignal,
70195
- agentContext === void 0 ? prepared : {
70196
- ...prepared,
70197
- agentContext: {
70198
- full: agentContext.full,
70199
- ...agentContext.update ? { update: agentContext.update } : {}
70200
- }
70201
- }
70202
- );
70203
- if (agentContext !== void 0 && result.outcome !== "rejected") {
70204
- await agentContext.save().catch((error61) => {
70205
- context.log.warn("holder.agent_context_save_failed", { runId: spec.runId, error: error61 });
70206
- });
70207
- }
70208
- return result;
70209
- };
70210
- if (workspace === void 0) return await run2(sink, signal);
70211
- return await runLeased(
69870
+ const result = await context.driver.runTurn(
70212
69871
  spec,
70213
- leaseTargets,
70214
- { ...context, lease: workspace.lease },
70215
69872
  sink,
70216
69873
  signal,
70217
- run2
69874
+ agentContext === void 0 ? prepared : {
69875
+ ...prepared,
69876
+ agentContext: {
69877
+ full: agentContext.full,
69878
+ ...agentContext.update ? { update: agentContext.update } : {}
69879
+ }
69880
+ }
70218
69881
  );
69882
+ if (agentContext !== void 0 && result.outcome !== "rejected") {
69883
+ await agentContext.save().catch((error61) => {
69884
+ context.log.warn("holder.agent_context_save_failed", { runId: spec.runId, error: error61 });
69885
+ });
69886
+ }
69887
+ return result;
70219
69888
  } catch (_) {
70220
69889
  var _error = _, _hasError = true;
70221
69890
  } finally {
@@ -70223,7 +69892,7 @@ async function runWithInputs({ spec, leaseTargets, skills }, context, sink, sign
70223
69892
  _promise2 && await _promise2;
70224
69893
  }
70225
69894
  }
70226
- async function admitAndRun(spec, context, append, sink, signal) {
69895
+ async function admitAndRun(spec, context, sink, signal) {
70227
69896
  if (context.workspace === void 0) {
70228
69897
  if (spec.skillInvocations?.length) {
70229
69898
  return {
@@ -70232,14 +69901,13 @@ async function admitAndRun(spec, context, append, sink, signal) {
70232
69901
  message: "Selected skills need this computer's skill sync, which this holder does not have."
70233
69902
  };
70234
69903
  }
70235
- return runWithInputs({ spec, leaseTargets: [], skills: [] }, context, sink, signal);
69904
+ return runWithInputs({ spec, skills: [] }, context, sink, signal);
70236
69905
  }
70237
- const admission = await admitRun(spec, context.workspace.admission, signal);
69906
+ const admission = await admitRun(spec, context.workspace.admission);
70238
69907
  if (admission.kind === "rejected") {
70239
69908
  context.log.info("holder.run_rejected", { runId: spec.runId, rejection: admission.rejection });
70240
69909
  return { outcome: "rejected", rejection: admission.rejection, message: admission.message };
70241
69910
  }
70242
- if (admission.relocated !== null) append(admission.relocated);
70243
69911
  return runWithInputs(admission, context, sink, signal);
70244
69912
  }
70245
69913
  async function claimRun(spec, context) {
@@ -70286,7 +69954,6 @@ async function runClaimedTurn(spec, claimed, context, signal) {
70286
69954
  result = await admitAndRun(
70287
69955
  spec,
70288
69956
  context,
70289
- append,
70290
69957
  {
70291
69958
  onSpawned: (pid) => append(runStarted({ pid })),
70292
69959
  // Base64 media in provider payloads and tool output never reaches the log (main 13590db369).
@@ -70349,12 +70016,11 @@ async function runHolder({
70349
70016
  try {
70350
70017
  const identity = await readProcessIdentity(process.pid);
70351
70018
  if (identity === null) throw new RuntimeFault("internal", "Cannot read own process identity");
70352
- const _engines = __using(_stack, recordSpawnedEngines(engineRecordsPath((0, import_node_path68.dirname)(launch.statusPath)), clock, log));
70019
+ const _engines = __using(_stack, recordSpawnedEngines(engineRecordsPath((0, import_node_path66.dirname)(launch.statusPath)), clock, log));
70353
70020
  const holder = {
70354
70021
  state: "idle",
70355
70022
  runId: null,
70356
70023
  turn: null,
70357
- answerGate: createAnswerGate(),
70358
70024
  clients: /* @__PURE__ */ new Set()
70359
70025
  };
70360
70026
  const exit = new AbortController();
@@ -70412,8 +70078,7 @@ async function runHolder({
70412
70078
  log,
70413
70079
  onAppended: (runId, offset) => broadcast({ type: "appended", runId, offset }),
70414
70080
  ...inputs === void 0 ? {} : { inputs },
70415
- ...workspace === void 0 ? {} : { workspace },
70416
- answerGate: holder.answerGate
70081
+ ...workspace === void 0 ? {} : { workspace }
70417
70082
  };
70418
70083
  claimRun(spec, context).then(
70419
70084
  (claimed) => {
@@ -70445,7 +70110,7 @@ async function runHolder({
70445
70110
  );
70446
70111
  };
70447
70112
  const respond = (request2, client) => {
70448
- respondToTurn(holder.runId, holder.answerGate, driver, request2).then((status) => {
70113
+ respondToTurn(holder.runId, driver, request2).then((status) => {
70449
70114
  log.info("holder.responded", { runId: request2.runId, status });
70450
70115
  writeMessage(client, { type: "responded", id: request2.id, status });
70451
70116
  }).catch((error61) => {
@@ -70491,12 +70156,12 @@ async function runHolder({
70491
70156
  return;
70492
70157
  case "status":
70493
70158
  void facts.snapshot().then(
70494
- (snapshot2) => writeMessage(client, {
70159
+ (snapshot) => writeMessage(client, {
70495
70160
  type: "status",
70496
70161
  id: request2.id,
70497
70162
  state: holder.state,
70498
70163
  runId: holder.runId,
70499
- facts: snapshot2
70164
+ facts: snapshot
70500
70165
  })
70501
70166
  );
70502
70167
  return;
@@ -70545,16 +70210,16 @@ async function runHolder({
70545
70210
  client.on("error", () => holder.clients.delete(client));
70546
70211
  });
70547
70212
  removeStaleEndpoint(launch.endpoint);
70548
- await new Promise((resolve14, reject) => {
70213
+ await new Promise((resolve13, reject) => {
70549
70214
  server.once("error", reject);
70550
- server.listen(launch.endpoint, () => resolve14());
70215
+ server.listen(launch.endpoint, () => resolve13());
70551
70216
  });
70552
70217
  await writeStatus();
70553
70218
  log.info("holder.ready", { conversationId: launch.conversationId, pid: identity.pid });
70554
- await new Promise((resolve14) => exit.signal.addEventListener("abort", () => resolve14()));
70219
+ await new Promise((resolve13) => exit.signal.addEventListener("abort", () => resolve13()));
70555
70220
  await driver.suspend?.().catch((error61) => log.warn("holder.driver_suspend_failed", { error: error61 }));
70556
70221
  for (const client of holder.clients) client.end();
70557
- await new Promise((resolve14) => server.close(() => resolve14()));
70222
+ await new Promise((resolve13) => server.close(() => resolve13()));
70558
70223
  (0, import_node_fs22.rmSync)(launch.statusPath, { force: true });
70559
70224
  log.info("holder.suspended", { conversationId: launch.conversationId });
70560
70225
  } catch (_) {
@@ -70643,7 +70308,7 @@ var DEFAULT_MAX_ACTIVE_RUNS = 32;
70643
70308
  var HOLDER_BUSY = "busy";
70644
70309
  async function listIds(dir, schema) {
70645
70310
  const ids = [];
70646
- for (const name of await (0, import_promises69.readdir)(dir).catch(() => [])) {
70311
+ for (const name of await (0, import_promises67.readdir)(dir).catch(() => [])) {
70647
70312
  const parsed = schema.safeParse(name);
70648
70313
  if (parsed.success) ids.push(parsed.data);
70649
70314
  }
@@ -70657,14 +70322,14 @@ function holderIdentity(status) {
70657
70322
  return command === void 0 ? { pid, startedAt } : { pid, startedAt, command };
70658
70323
  }
70659
70324
  function sessionFiles(paths, conversationId) {
70660
- const dir = (0, import_node_path69.join)(paths.sessions, conversationId);
70661
- return { dir, launch: (0, import_node_path69.join)(dir, "launch.json"), status: (0, import_node_path69.join)(dir, "holder.json") };
70325
+ const dir = (0, import_node_path67.join)(paths.sessions, conversationId);
70326
+ return { dir, launch: (0, import_node_path67.join)(dir, "launch.json"), status: (0, import_node_path67.join)(dir, "holder.json") };
70662
70327
  }
70663
70328
  async function removeHolderFiles(files) {
70664
70329
  for (const path4 of [files.launch, files.status, engineRecordsPath(files.dir)]) {
70665
- await (0, import_promises69.rm)(path4, { force: true });
70330
+ await (0, import_promises67.rm)(path4, { force: true });
70666
70331
  }
70667
- await (0, import_promises69.rmdir)(files.dir).catch((error61) => {
70332
+ await (0, import_promises67.rmdir)(files.dir).catch((error61) => {
70668
70333
  if (!["ENOENT", "ENOTEMPTY", "EEXIST"].includes(errnoCode(error61) ?? "")) throw error61;
70669
70334
  });
70670
70335
  }
@@ -70854,7 +70519,7 @@ async function openSessions(deps) {
70854
70519
  const meta3 = await readRunMeta(dir.meta);
70855
70520
  const last = await readLastRecord(dir.log);
70856
70521
  if (meta3 === null || last === null) return null;
70857
- const logged = await (0, import_promises69.stat)(dir.log).catch((error61) => {
70522
+ const logged = await (0, import_promises67.stat)(dir.log).catch((error61) => {
70858
70523
  if (errnoCode(error61) === "ENOENT") return null;
70859
70524
  throw error61;
70860
70525
  });
@@ -71166,7 +70831,7 @@ function loadRuntimeConfig(env = process.env, totalMemoryBytes = (0, import_node
71166
70831
  providerProbes: ALAN_RUNTIME_PROVIDER_PROBES === "on",
71167
70832
  providerToolchain: ALAN_RUNTIME_PROVIDER_NODE !== void 0 && ALAN_RUNTIME_PROVIDER_NPM_CLI !== void 0 ? { node: ALAN_RUNTIME_PROVIDER_NODE, npmCli: ALAN_RUNTIME_PROVIDER_NPM_CLI } : null,
71168
70833
  home,
71169
- configHome: XDG_CONFIG_HOME ?? (0, import_node_path70.join)(home, ".config"),
70834
+ configHome: XDG_CONFIG_HOME ?? (0, import_node_path68.join)(home, ".config"),
71170
70835
  codexHome: resolveCodexHome(CODEX_HOME, home),
71171
70836
  ...githubProxyConfig({ ALAN_RUNTIME_GITHUB_PROXY, XDG_CONFIG_HOME, GH_CONFIG_DIR }, home),
71172
70837
  gitGatewayUrl: ALAN_RUNTIME_GIT_GATEWAY_URL ?? null,
@@ -71176,13 +70841,13 @@ function loadRuntimeConfig(env = process.env, totalMemoryBytes = (0, import_node
71176
70841
  };
71177
70842
  }
71178
70843
  function resolveCodexHome(configuredHome, home) {
71179
- return configuredHome ?? (0, import_node_path70.join)(home, ".codex");
70844
+ return configuredHome ?? (0, import_node_path68.join)(home, ".codex");
71180
70845
  }
71181
70846
  function githubProxyConfig(env, home) {
71182
- const configHome = env.XDG_CONFIG_HOME ?? (0, import_node_path70.join)(home, ".config");
70847
+ const configHome = env.XDG_CONFIG_HOME ?? (0, import_node_path68.join)(home, ".config");
71183
70848
  return {
71184
70849
  githubProxy: env.ALAN_RUNTIME_GITHUB_PROXY === "on",
71185
- ghConfigDir: env.GH_CONFIG_DIR ?? (0, import_node_path70.join)(configHome, "gh")
70850
+ ghConfigDir: env.GH_CONFIG_DIR ?? (0, import_node_path68.join)(configHome, "gh")
71186
70851
  };
71187
70852
  }
71188
70853
  function serviceEnvironment2(env, profile) {
@@ -71240,9 +70905,9 @@ function takeEnrollmentCodeFromEnv(env = process.env) {
71240
70905
  }
71241
70906
 
71242
70907
  // src/cli/context.ts
71243
- var import_promises70 = require("fs/promises");
70908
+ var import_promises68 = require("fs/promises");
71244
70909
  var import_node_os12 = require("os");
71245
- var import_node_path71 = require("path");
70910
+ var import_node_path69 = require("path");
71246
70911
  var DESKTOP_BUNDLE_IDS = {
71247
70912
  production: ["com.alan-ai.desktop"],
71248
70913
  staging: ["com.alan-ai.desktop.staging"],
@@ -71282,7 +70947,7 @@ function serviceSpec({ config: config2, paths, self }) {
71282
70947
  profile: config2.profile,
71283
70948
  program: serviceCommand(config2.host, self, launcher),
71284
70949
  environment: config2.serviceEnvironment,
71285
- logPath: (0, import_node_path71.join)(paths.logs, "service.log"),
70950
+ logPath: (0, import_node_path69.join)(paths.logs, "service.log"),
71286
70951
  associatedBundleIds: DESKTOP_BUNDLE_IDS[config2.profile]
71287
70952
  };
71288
70953
  }
@@ -71290,7 +70955,7 @@ async function installedServiceSpec(ctx) {
71290
70955
  const spec = serviceSpec(ctx);
71291
70956
  if (ctx.config.host === "app") return spec;
71292
70957
  const layout = installLayout(ctx.config.installDir, ctx.config.profile);
71293
- const installed = await (0, import_promises70.access)(layout.launcher).then(
70958
+ const installed = await (0, import_promises68.access)(layout.launcher).then(
71294
70959
  () => true,
71295
70960
  () => false
71296
70961
  );
@@ -71418,7 +71083,7 @@ var manifestRevisionSchema = external_exports.object({ revision: external_export
71418
71083
  async function manifestRevision(path4) {
71419
71084
  let raw;
71420
71085
  try {
71421
- raw = JSON.parse(await (0, import_promises71.readFile)(path4, "utf8"));
71086
+ raw = JSON.parse(await (0, import_promises69.readFile)(path4, "utf8"));
71422
71087
  } catch (error61) {
71423
71088
  throw new RuntimeFault("invalid_file", `Cannot read the skill manifest at ${path4}`, {
71424
71089
  cause: error61
@@ -71472,8 +71137,8 @@ async function runSkills(argv) {
71472
71137
  }
71473
71138
 
71474
71139
  // src/cli/commands/doctor.ts
71475
- var import_promises74 = require("fs/promises");
71476
- var import_node_path75 = require("path");
71140
+ var import_promises72 = require("fs/promises");
71141
+ var import_node_path73 = require("path");
71477
71142
  init_runtime_v2();
71478
71143
 
71479
71144
  // src/identity/credential.ts
@@ -71482,7 +71147,7 @@ init_zod();
71482
71147
 
71483
71148
  // src/identity/installation.ts
71484
71149
  var import_node_crypto33 = require("crypto");
71485
- var import_node_path72 = require("path");
71150
+ var import_node_path70 = require("path");
71486
71151
  init_runtime_v2();
71487
71152
  init_zod();
71488
71153
  var installationFileSchema = external_exports.object({
@@ -71490,7 +71155,7 @@ var installationFileSchema = external_exports.object({
71490
71155
  machineId: machineIdSchema.optional()
71491
71156
  });
71492
71157
  function installationPath(paths) {
71493
- return (0, import_node_path72.join)(paths.stateDir, "installation.json");
71158
+ return (0, import_node_path70.join)(paths.stateDir, "installation.json");
71494
71159
  }
71495
71160
  async function readInstallation(paths) {
71496
71161
  const result = await readJsonFile(installationPath(paths), installationFileSchema);
@@ -71681,7 +71346,7 @@ async function authorizeDevice(input2) {
71681
71346
  }
71682
71347
 
71683
71348
  // src/identity/enroll.ts
71684
- var import_promises72 = require("fs/promises");
71349
+ var import_promises70 = require("fs/promises");
71685
71350
  init_runtime_v2();
71686
71351
  async function enrollMachine(input2) {
71687
71352
  const machineId = input2.machineId ?? (await readMachineFile(input2.paths))?.machineId ?? (await readInstallation(input2.paths))?.machineId;
@@ -71764,17 +71429,19 @@ async function enrollFromGrantFile(input2) {
71764
71429
  clock: input2.clock,
71765
71430
  access: input2.access
71766
71431
  });
71767
- await (0, import_promises72.rm)(input2.grantPath, { force: true });
71432
+ await (0, import_promises70.rm)(input2.grantPath, { force: true });
71768
71433
  return machine;
71769
71434
  }
71770
71435
 
71771
71436
  // src/identity/migrate-v1.ts
71772
- var import_promises73 = require("fs/promises");
71773
- var import_node_path73 = require("path");
71437
+ var import_promises71 = require("fs/promises");
71438
+ var import_node_path71 = require("path");
71774
71439
  init_runtime_v2();
71775
71440
  init_zod();
71776
71441
  var EXIT_POLL_MS = 200;
71777
71442
  var LEGACY_EXIT_WAIT_MS = 15e3;
71443
+ var TERMINATE_GRACE_MS = 5e3;
71444
+ var KILL_SETTLE_MS = 2e3;
71778
71445
  var SCRUBBED_KEYS = [
71779
71446
  "runtimeToken",
71780
71447
  "runtimeRenewalToken",
@@ -71791,37 +71458,70 @@ var ownerLeaseSchema = external_exports.looseObject({ pid: external_exports.numb
71791
71458
  function legacyConfigPath(home, profile) {
71792
71459
  switch (profile) {
71793
71460
  case "production":
71794
- return (0, import_node_path73.join)(home, ".alan", "agent", "config.json");
71461
+ return (0, import_node_path71.join)(home, ".alan", "agent", "config.json");
71795
71462
  case "staging":
71796
- return (0, import_node_path73.join)(home, ".alan-staging", "agent", "config.json");
71463
+ return (0, import_node_path71.join)(home, ".alan-staging", "agent", "config.json");
71797
71464
  default:
71798
- return (0, import_node_path73.join)(home, ".alan-dev", "agent", "config.json");
71465
+ return (0, import_node_path71.join)(home, ".alan-dev", "agent", "config.json");
71799
71466
  }
71800
71467
  }
71801
71468
  async function findLegacyInstall(home, profile) {
71802
71469
  const configPath = legacyConfigPath(home, profile);
71803
71470
  const config2 = await readJsonFile(configPath, legacyConfigSchema);
71804
71471
  if (config2.kind !== "ok") return null;
71805
- return { configPath, ownerLeasePath: `${configPath}.daemon-owner.json`, config: config2.value };
71472
+ return {
71473
+ profile,
71474
+ configPath,
71475
+ ownerLeasePath: `${configPath}.daemon-owner.json`,
71476
+ config: config2.value
71477
+ };
71806
71478
  }
71807
71479
  async function readOwnerPid(path4) {
71808
71480
  const lease = await readJsonFile(path4, ownerLeaseSchema);
71809
71481
  return lease.kind === "ok" ? lease.value.pid : null;
71810
71482
  }
71811
- async function waitForExit(pid, deps) {
71812
- const deadline = deps.clock.monotonic() + (deps.exitWaitMs ?? LEGACY_EXIT_WAIT_MS);
71813
- while (deps.isProcessAlive(pid)) {
71483
+ async function waitForExit(pids, waitMs, deps) {
71484
+ const deadline = deps.clock.monotonic() + waitMs;
71485
+ while (pids.some((pid) => deps.isProcessAlive(pid))) {
71814
71486
  if (deps.clock.monotonic() >= deadline) return false;
71815
71487
  await deps.clock.sleep(EXIT_POLL_MS, deps.signal);
71816
71488
  }
71817
71489
  return true;
71818
71490
  }
71491
+ function strayDaemons(processes, install2) {
71492
+ const exclude = /* @__PURE__ */ new Set([process.pid, process.ppid]);
71493
+ return findLegacyDaemons(processes, { profile: install2.profile, exclude }).map(
71494
+ (entry) => entry.pid
71495
+ );
71496
+ }
71497
+ async function terminate(pids, deps) {
71498
+ deps.log.warn("legacy.stopping_v1", { pids });
71499
+ for (const pid of pids) deps.signalProcess(pid, "SIGTERM");
71500
+ if (await waitForExit(pids, TERMINATE_GRACE_MS, deps)) return null;
71501
+ for (const pid of pids) {
71502
+ if (deps.isProcessAlive(pid)) deps.signalProcess(pid, "SIGKILL");
71503
+ }
71504
+ await waitForExit(pids, KILL_SETTLE_MS, deps);
71505
+ return pids.find((pid) => deps.isProcessAlive(pid)) ?? null;
71506
+ }
71507
+ async function stopLegacyDaemons(deps, leasePid) {
71508
+ const leaseRunning = leasePid !== null && !await waitForExit([leasePid], deps.exitWaitMs ?? LEGACY_EXIT_WAIT_MS, deps);
71509
+ const processes = await deps.listProcesses();
71510
+ const targets = strayDaemons(processes, deps.install);
71511
+ if (leaseRunning && !targets.includes(leasePid)) {
71512
+ const listed = processes.find((entry) => entry.pid === leasePid);
71513
+ if (listed === void 0) return deps.isProcessAlive(leasePid) ? leasePid : null;
71514
+ if (isLegacyDaemonCommand(listed.command)) targets.push(leasePid);
71515
+ else deps.log.info("legacy.lease_pid_reused", { pid: leasePid });
71516
+ }
71517
+ return targets.length === 0 ? null : terminate(targets, deps);
71518
+ }
71819
71519
  async function scrubLegacyInstall(install2) {
71820
71520
  const scrubbed = { ...install2.config, migratedToRuntimeV2: true };
71821
71521
  for (const key of SCRUBBED_KEYS) delete scrubbed[key];
71822
71522
  await writeJsonFileAtomic(`${install2.configPath}.migrated-v1`, scrubbed);
71823
- await (0, import_promises73.rm)(install2.configPath, { force: true });
71824
- await (0, import_promises73.rm)(install2.ownerLeasePath, { force: true });
71523
+ await (0, import_promises71.rm)(install2.configPath, { force: true });
71524
+ await (0, import_promises71.rm)(install2.ownerLeasePath, { force: true });
71825
71525
  }
71826
71526
  async function exchangeCredential(deps) {
71827
71527
  const { config: config2 } = deps.install;
@@ -71846,12 +71546,16 @@ async function migrateFromV1(deps) {
71846
71546
  const { install: install2, log } = deps;
71847
71547
  const pid = await readOwnerPid(install2.ownerLeasePath);
71848
71548
  if (deps.dryRun === true) {
71549
+ const strays = strayDaemons(await deps.listProcesses(), install2).filter(
71550
+ (stray) => stray !== pid
71551
+ );
71849
71552
  return {
71850
71553
  kind: "planned",
71851
71554
  steps: [
71852
71555
  `check that ${install2.config.apiUrl} serves the v2 machine routes`,
71853
71556
  "remove the v1 service",
71854
- pid === null ? "no v1 daemon lease" : `wait for v1 pid ${pid} to exit`,
71557
+ pid === null ? "no v1 daemon lease" : `wait for v1 pid ${pid} to exit, then stop it (SIGTERM, then SIGKILL)`,
71558
+ strays.length === 0 ? "no other v1 daemon running" : `stop the other v1 daemons (pids ${strays.join(", ")}): SIGTERM, then SIGKILL`,
71855
71559
  deps.setup === void 0 ? `renew the v1 credential of machine ${install2.config.runtimeId}` : `register machine ${install2.config.runtimeId} with the setup token`,
71856
71560
  "write machine.json and the credential",
71857
71561
  `scrub ${install2.configPath}`
@@ -71864,9 +71568,10 @@ async function migrateFromV1(deps) {
71864
71568
  }
71865
71569
  const removal = await deps.removeService();
71866
71570
  log.info("legacy.service_removed", { found: removal.found });
71867
- if (pid !== null && !await waitForExit(pid, deps)) {
71868
- log.warn("legacy.v1_still_running", { pid });
71869
- return { kind: "v1_still_running", pid };
71571
+ const running = await stopLegacyDaemons(deps, pid);
71572
+ if (running !== null) {
71573
+ log.warn("legacy.v1_still_running", { pid: running });
71574
+ return { kind: "v1_still_running", pid: running };
71870
71575
  }
71871
71576
  const grant = await exchangeCredential(deps);
71872
71577
  if (typeof grant === "string") {
@@ -71930,7 +71635,7 @@ async function loadIdentity(paths, options = {}) {
71930
71635
  }
71931
71636
 
71932
71637
  // src/cli/commands/status.ts
71933
- var import_node_path74 = require("path");
71638
+ var import_node_path72 = require("path");
71934
71639
  async function serviceStatus(ctx) {
71935
71640
  try {
71936
71641
  return await createServiceManager(ctx.host, ctx.config.profile).status();
@@ -71957,7 +71662,7 @@ async function runtimeState(ctx) {
71957
71662
  const running = await readRunningRuntime(ctx.paths.lock);
71958
71663
  if (running === null) return { state: "offline", pid: null, localApi: null };
71959
71664
  const discovery = await readJsonFile(
71960
- (0, import_node_path74.join)(ctx.paths.stateDir, LOCAL_API_DISCOVERY_FILE),
71665
+ (0, import_node_path72.join)(ctx.paths.stateDir, LOCAL_API_DISCOVERY_FILE),
71961
71666
  localApiDiscoverySchema
71962
71667
  );
71963
71668
  const localApi = discovery.kind === "ok" && discovery.value.pid === running.pid ? {
@@ -72002,7 +71707,7 @@ async function runStatus(argv, ctx = cliContext()) {
72002
71707
  }
72003
71708
 
72004
71709
  // src/cli/commands/doctor.ts
72005
- var PROBE_TIMEOUT_MS3 = 1e4;
71710
+ var PROBE_TIMEOUT_MS2 = 1e4;
72006
71711
  var LOCAL_TIMEOUT_MS = 3e3;
72007
71712
  var DISK_WARN_BYTES = 1024 ** 3;
72008
71713
  var DISK_FAIL_BYTES = 100 * 1024 ** 2;
@@ -72094,7 +71799,7 @@ async function credentialCheck(ctx) {
72094
71799
  async function serverCheck(facts) {
72095
71800
  const api = createApiClient({ apiUrl: facts.apiUrl, accessToken: () => facts.accessToken });
72096
71801
  try {
72097
- const desired = await api.fetchDesired(AbortSignal.timeout(PROBE_TIMEOUT_MS3));
71802
+ const desired = await api.fetchDesired(AbortSignal.timeout(PROBE_TIMEOUT_MS2));
72098
71803
  return check2("server", "ok", `${facts.apiUrl} accepts this machine's credential`, {
72099
71804
  machineId: facts.machineId,
72100
71805
  desiredRuns: desired.runs.length
@@ -72120,7 +71825,7 @@ function isStale(machine, now) {
72120
71825
  async function machinesCheck(facts) {
72121
71826
  const api = createApiClient({ apiUrl: facts.apiUrl, accessToken: () => facts.accessToken });
72122
71827
  try {
72123
- const machines = await api.listSiblings(AbortSignal.timeout(PROBE_TIMEOUT_MS3));
71828
+ const machines = await api.listSiblings(AbortSignal.timeout(PROBE_TIMEOUT_MS2));
72124
71829
  if (machines === null) {
72125
71830
  return check2("machines", "skipped", `${facts.apiUrl} does not list machines`);
72126
71831
  }
@@ -72150,7 +71855,7 @@ async function releaseCheck(ctx, facts) {
72150
71855
  const apiUrl = facts?.apiUrl ?? ctx.config.apiUrl;
72151
71856
  const api = createApiClient({ apiUrl, accessToken: () => facts?.accessToken ?? "" });
72152
71857
  try {
72153
- const release2 = await api.currentRelease(AbortSignal.timeout(PROBE_TIMEOUT_MS3));
71858
+ const release2 = await api.currentRelease(AbortSignal.timeout(PROBE_TIMEOUT_MS2));
72154
71859
  const layout = installLayout(ctx.config.installDir, ctx.config.profile);
72155
71860
  const plan2 = planUpdate({
72156
71861
  current: package_default.version,
@@ -72178,7 +71883,7 @@ async function runtimeCheck(ctx, status) {
72178
71883
  return check2("runtime", "warn", "No runtime is running for this profile");
72179
71884
  }
72180
71885
  const client = createRuntimeClient({
72181
- discoveryPath: (0, import_node_path75.join)(ctx.paths.stateDir, LOCAL_API_DISCOVERY_FILE)
71886
+ discoveryPath: (0, import_node_path73.join)(ctx.paths.stateDir, LOCAL_API_DISCOVERY_FILE)
72182
71887
  });
72183
71888
  try {
72184
71889
  const live = await client.status(AbortSignal.timeout(LOCAL_TIMEOUT_MS));
@@ -72205,7 +71910,7 @@ async function runtimeCheck(ctx, status) {
72205
71910
  }
72206
71911
  }
72207
71912
  async function probeHolder(dir, conversationId) {
72208
- const launch = await readJsonFile((0, import_node_path75.join)(dir, "launch.json"), holderLaunchSchema);
71913
+ const launch = await readJsonFile((0, import_node_path73.join)(dir, "launch.json"), holderLaunchSchema);
72209
71914
  if (launch.kind !== "ok") return null;
72210
71915
  try {
72211
71916
  const reply2 = await withTimeout(
@@ -72230,8 +71935,8 @@ async function probeHolder(dir, conversationId) {
72230
71935
  }
72231
71936
  }
72232
71937
  async function holdersCheck(ctx) {
72233
- const names = await (0, import_promises74.readdir)(ctx.paths.sessions).catch(() => []);
72234
- const holders = (await Promise.all(names.map((name) => probeHolder((0, import_node_path75.join)(ctx.paths.sessions, name), name)))).filter((facts) => facts !== null);
71938
+ const names = await (0, import_promises72.readdir)(ctx.paths.sessions).catch(() => []);
71939
+ const holders = (await Promise.all(names.map((name) => probeHolder((0, import_node_path73.join)(ctx.paths.sessions, name), name)))).filter((facts) => facts !== null);
72235
71940
  const dead = holders.filter((holder) => !holder.alive).length;
72236
71941
  return check2(
72237
71942
  "holders",
@@ -72242,10 +71947,10 @@ async function holdersCheck(ctx) {
72242
71947
  }
72243
71948
  async function freeBytesAt(path4) {
72244
71949
  try {
72245
- const stats = await (0, import_promises74.statfs)(path4);
71950
+ const stats = await (0, import_promises72.statfs)(path4);
72246
71951
  return { path: path4, freeBytes: stats.bavail * stats.bsize };
72247
71952
  } catch (error61) {
72248
- const parent = (0, import_node_path75.dirname)(path4);
71953
+ const parent = (0, import_node_path73.dirname)(path4);
72249
71954
  if (parent === path4) throw error61;
72250
71955
  return freeBytesAt(parent);
72251
71956
  }
@@ -72263,9 +71968,9 @@ async function diskCheck(ctx) {
72263
71968
  }
72264
71969
  }
72265
71970
  var resolveFromLoginShell = (own2) => resolveCliEnvironment({ env: own2, platform: process.platform });
72266
- async function cliDiscoveryCheck(resolve14) {
71971
+ async function cliDiscoveryCheck(resolve13) {
72267
71972
  const own2 = readCliEnvironment();
72268
- const env = await resolve14(own2);
71973
+ const env = await resolve13(own2);
72269
71974
  const delimiter = process.platform === "win32" ? ";" : ":";
72270
71975
  const ownDirs = new Set((own2.PATH ?? "").split(delimiter));
72271
71976
  const added = (env.PATH ?? "").split(delimiter).filter((dir) => dir.length > 0 && !ownDirs.has(dir));
@@ -72381,7 +72086,7 @@ async function runDoctor(argv, context = cliContext) {
72381
72086
  }
72382
72087
 
72383
72088
  // src/cli/commands/git-credential.ts
72384
- var import_promises75 = require("fs/promises");
72089
+ var import_promises73 = require("fs/promises");
72385
72090
  var import_node_net4 = require("net");
72386
72091
  var MAX_RESPONSE_BYTES = 64 * 1024;
72387
72092
  async function readAll(stream) {
@@ -72399,7 +72104,7 @@ function processIo() {
72399
72104
  };
72400
72105
  }
72401
72106
  function askGitCredentialSocket(endpoint, request2, signal) {
72402
- return new Promise((resolve14, reject) => {
72107
+ return new Promise((resolve13, reject) => {
72403
72108
  const socket = (0, import_node_net4.createConnection)(endpoint);
72404
72109
  let buffered = "";
72405
72110
  const fail = (error61) => {
@@ -72426,7 +72131,7 @@ function askGitCredentialSocket(endpoint, request2, signal) {
72426
72131
  signal.removeEventListener("abort", onAbort);
72427
72132
  try {
72428
72133
  const line = buffered.split("\n", 1)[0] ?? "";
72429
- resolve14(gitCredentialSocketResponseSchema.parse(JSON.parse(line)));
72134
+ resolve13(gitCredentialSocketResponseSchema.parse(JSON.parse(line)));
72430
72135
  } catch (error61) {
72431
72136
  reject(
72432
72137
  new RuntimeFault("io_failed", "the Alan runtime sent an invalid reply", { cause: error61 })
@@ -72491,7 +72196,7 @@ async function configure(argv) {
72491
72196
  }
72492
72197
  async function configureGitGateway(config2, gatewayUrl, signal) {
72493
72198
  const { launcher } = installLayout(config2.installDir, config2.profile);
72494
- const installed = await (0, import_promises75.access)(launcher).then(
72199
+ const installed = await (0, import_promises73.access)(launcher).then(
72495
72200
  () => true,
72496
72201
  () => false
72497
72202
  );
@@ -72518,7 +72223,7 @@ async function runGitCredential(argv) {
72518
72223
  }
72519
72224
 
72520
72225
  // src/cli/commands/hold.ts
72521
- var import_node_path76 = require("path");
72226
+ var import_node_path74 = require("path");
72522
72227
  init_agent2();
72523
72228
  init_runtime_v2();
72524
72229
  async function machineAccess(paths, log, conversationId, transport) {
@@ -72576,7 +72281,7 @@ async function runHold(argv) {
72576
72281
  const config2 = loadRuntimeConfig();
72577
72282
  const paths = runtimePaths(config2.stateDir);
72578
72283
  const log = __using(_stack, openFileLog(
72579
- (0, import_node_path76.join)(paths.logs, `holder-${launch.value.conversationId}.jsonl`),
72284
+ (0, import_node_path74.join)(paths.logs, `holder-${launch.value.conversationId}.jsonl`),
72580
72285
  config2.logLevel,
72581
72286
  systemClock
72582
72287
  ));
@@ -72587,7 +72292,7 @@ async function runHold(argv) {
72587
72292
  );
72588
72293
  const transport = __using(_stack, createHttpTransport());
72589
72294
  const access7 = await machineAccess(paths, log, launch.value.conversationId, transport);
72590
- const credentialPath = (0, import_node_path76.join)(paths.tmp, "mcp", `${launch.value.conversationId}.json`);
72295
+ const credentialPath = (0, import_node_path74.join)(paths.tmp, "mcp", `${launch.value.conversationId}.json`);
72591
72296
  const managedMcp = __using(_stack, access7.managedMcp === void 0 ? void 0 : createHelperMcpAccess({
72592
72297
  managedMcp: access7.managedMcp,
72593
72298
  conversationId: launch.value.conversationId,
@@ -72628,7 +72333,7 @@ async function runHold(argv) {
72628
72333
  }
72629
72334
 
72630
72335
  // src/cli/commands/hook.ts
72631
- var import_node_path77 = require("path");
72336
+ var import_node_path75 = require("path");
72632
72337
  var RUNTIME_ANSWER_MS = 2e3;
72633
72338
  var DEBUG_VARIABLE = "ALAN_HOOK_DEBUG";
72634
72339
  function flag(argv, name) {
@@ -72660,7 +72365,7 @@ async function forwardHook(argv, io) {
72660
72365
  return "transcript outside provider root";
72661
72366
  }
72662
72367
  const verdict = await io.send(
72663
- (0, import_node_path77.join)(io.stateDir, LOCAL_API_DISCOVERY_FILE),
72368
+ (0, import_node_path75.join)(io.stateDir, LOCAL_API_DISCOVERY_FILE),
72664
72369
  hookSignal,
72665
72370
  AbortSignal.timeout(RUNTIME_ANSWER_MS)
72666
72371
  );
@@ -72696,7 +72401,7 @@ async function runHook(argv, overrides = {}) {
72696
72401
  }
72697
72402
 
72698
72403
  // src/cli/commands/ingestion-hooks.ts
72699
- var import_promises76 = require("fs/promises");
72404
+ var import_promises74 = require("fs/promises");
72700
72405
  var CODEX_TRUST_NOTE = "Codex runs new hooks only after you review them: open /hooks in Codex.";
72701
72406
  function isAction(value2) {
72702
72407
  return value2 === "enable" || value2 === "disable" || value2 === "status";
@@ -72719,7 +72424,7 @@ function errorMessage2(error61) {
72719
72424
  return error61 instanceof Error ? error61.message : String(error61);
72720
72425
  }
72721
72426
  async function exists5(path4) {
72722
- return (0, import_promises76.access)(path4).then(
72427
+ return (0, import_promises74.access)(path4).then(
72723
72428
  () => true,
72724
72429
  () => false
72725
72430
  );
@@ -72822,10 +72527,10 @@ async function runIntegrationsCommand(argv) {
72822
72527
  }
72823
72528
 
72824
72529
  // src/cli/commands/legacy.ts
72825
- var import_node_path79 = require("path");
72530
+ var import_node_path77 = require("path");
72826
72531
 
72827
72532
  // src/cli/commands/setup.ts
72828
- var import_node_path78 = require("path");
72533
+ var import_node_path76 = require("path");
72829
72534
  init_zod();
72830
72535
 
72831
72536
  // src/cli/legacy.ts
@@ -72837,6 +72542,8 @@ async function adoptLegacyInstall(ctx, deps, adoption) {
72837
72542
  install: install2,
72838
72543
  removeService: () => removeLegacyService(ctx.host, ctx.config.profile),
72839
72544
  isProcessAlive: deps.isProcessAlive,
72545
+ listProcesses: () => listProcesses2(ctx.host.exec, ctx.host.platform),
72546
+ signalProcess,
72840
72547
  enrollment: deps.enrollment(install2.config.apiUrl),
72841
72548
  saveGrant: async (grant) => {
72842
72549
  await saveGrant({
@@ -72907,7 +72614,7 @@ async function grantFileCredential(argv, grantPath, ctx, deps) {
72907
72614
  return enrollFromGrantFile({
72908
72615
  paths: ctx.paths,
72909
72616
  storeKind: credentialStoreFlag(argv) ?? ctx.config.credentialStore,
72910
- grantPath: (0, import_node_path78.resolve)(grantPath),
72617
+ grantPath: (0, import_node_path76.resolve)(grantPath),
72911
72618
  clock: deps.clock,
72912
72619
  access: ctx.access
72913
72620
  });
@@ -72983,7 +72690,7 @@ async function runSetup(argv, signal) {
72983
72690
  var _stack = [];
72984
72691
  try {
72985
72692
  const ctx = cliContext();
72986
- const log = __using(_stack, openFileLog((0, import_node_path78.join)(ctx.paths.logs, "cli.jsonl"), ctx.config.logLevel, systemClock));
72693
+ const log = __using(_stack, openFileLog((0, import_node_path76.join)(ctx.paths.logs, "cli.jsonl"), ctx.config.logLevel, systemClock));
72987
72694
  const result = await setupMachine(argv, ctx, {
72988
72695
  enrollment: (apiUrl) => createEnrollmentClient({ apiUrl }),
72989
72696
  isProcessAlive,
@@ -73066,7 +72773,7 @@ async function runToken(argv, signal) {
73066
72773
  );
73067
72774
  }
73068
72775
  const ctx = cliContext();
73069
- const log = __using(_stack, openFileLog((0, import_node_path79.join)(ctx.paths.logs, "cli.jsonl"), ctx.config.logLevel, systemClock));
72776
+ const log = __using(_stack, openFileLog((0, import_node_path77.join)(ctx.paths.logs, "cli.jsonl"), ctx.config.logLevel, systemClock));
73070
72777
  const result = await rotateMachineCredential(ctx, { clock: systemClock, log, signal });
73071
72778
  process.stdout.write(`${rotationMessage(result)}
73072
72779
  `);
@@ -73078,8 +72785,8 @@ async function runToken(argv, signal) {
73078
72785
  }
73079
72786
 
73080
72787
  // src/cli/commands/logout.ts
73081
- var import_promises77 = require("fs/promises");
73082
- var import_node_path80 = require("path");
72788
+ var import_promises75 = require("fs/promises");
72789
+ var import_node_path78 = require("path");
73083
72790
  init_runtime_v2();
73084
72791
  var RUNTIME_EXIT_WAIT_MS = 35e3;
73085
72792
  var TURN_END_WAIT_MS = 3e4;
@@ -73138,9 +72845,9 @@ async function stopHolder(launch, deps, outcome2) {
73138
72845
  }
73139
72846
  async function stopHeldRuns(ctx, deps, outcome2 = "aborted") {
73140
72847
  const stopped = [];
73141
- for (const name of await (0, import_promises77.readdir)(ctx.paths.sessions).catch(() => [])) {
72848
+ for (const name of await (0, import_promises75.readdir)(ctx.paths.sessions).catch(() => [])) {
73142
72849
  const launch = await readJsonFile(
73143
- (0, import_node_path80.join)(ctx.paths.sessions, name, "launch.json"),
72850
+ (0, import_node_path78.join)(ctx.paths.sessions, name, "launch.json"),
73144
72851
  holderLaunchSchema
73145
72852
  );
73146
72853
  if (launch.kind !== "ok") continue;
@@ -73177,13 +72884,13 @@ async function forgetMachineLocally(ctx) {
73177
72884
  const machine = await readMachineFile(ctx.paths);
73178
72885
  if (machine === null) return;
73179
72886
  await credentialStoreFor(ctx.paths, machine.credentialStore, ctx.access).clear();
73180
- await (0, import_promises77.rm)(ctx.paths.machine, { force: true });
72887
+ await (0, import_promises75.rm)(ctx.paths.machine, { force: true });
73181
72888
  }
73182
72889
  async function runLogout(argv, signal) {
73183
72890
  var _stack = [];
73184
72891
  try {
73185
72892
  const ctx = cliContext();
73186
- const log = __using(_stack, openFileLog((0, import_node_path80.join)(ctx.paths.logs, "cli.jsonl"), ctx.config.logLevel, systemClock));
72893
+ const log = __using(_stack, openFileLog((0, import_node_path78.join)(ctx.paths.logs, "cli.jsonl"), ctx.config.logLevel, systemClock));
73187
72894
  const result = await logoutMachine(argv, ctx, {
73188
72895
  api: (apiUrl, accessToken) => createApiClient({ apiUrl, accessToken }),
73189
72896
  stopHeldRuns,
@@ -73201,7 +72908,7 @@ async function runLogout(argv, signal) {
73201
72908
 
73202
72909
  // src/cli/commands/run.ts
73203
72910
  var import_node_fs24 = require("fs");
73204
- var import_node_path84 = require("path");
72911
+ var import_node_path82 = require("path");
73205
72912
 
73206
72913
  // src/local-api/app-attachments.ts
73207
72914
  function createAppAttachments(clock) {
@@ -73241,7 +72948,7 @@ function createRunAppends() {
73241
72948
  const pending = waiters.get(runId);
73242
72949
  if (pending === void 0) return;
73243
72950
  waiters.delete(runId);
73244
- for (const resolve14 of pending) resolve14();
72951
+ for (const resolve13 of pending) resolve13();
73245
72952
  };
73246
72953
  return {
73247
72954
  notify: wake,
@@ -73259,13 +72966,13 @@ function createRunAppends() {
73259
72966
  },
73260
72967
  nextAppend: (runId, signal) => {
73261
72968
  if (signal.aborted) return Promise.resolve();
73262
- return new Promise((resolve14) => {
72969
+ return new Promise((resolve13) => {
73263
72970
  const done = () => {
73264
72971
  signal.removeEventListener("abort", done);
73265
72972
  const pending2 = waiters.get(runId);
73266
72973
  pending2?.delete(done);
73267
72974
  if (pending2?.size === 0) waiters.delete(runId);
73268
- resolve14();
72975
+ resolve13();
73269
72976
  };
73270
72977
  const pending = waiters.get(runId) ?? /* @__PURE__ */ new Set();
73271
72978
  pending.add(done);
@@ -73278,9 +72985,9 @@ function createRunAppends() {
73278
72985
 
73279
72986
  // src/local-api/server.ts
73280
72987
  var import_node_crypto35 = require("crypto");
73281
- var import_promises78 = require("fs/promises");
72988
+ var import_promises76 = require("fs/promises");
73282
72989
  var import_node_http4 = require("http");
73283
- var import_node_path81 = require("path");
72990
+ var import_node_path79 = require("path");
73284
72991
 
73285
72992
  // src/local-api/guard.ts
73286
72993
  var import_node_crypto34 = require("crypto");
@@ -73357,11 +73064,11 @@ id: ${event.id}
73357
73064
  ${data}
73358
73065
  `);
73359
73066
  if (accepted || res.destroyed) return;
73360
- await new Promise((resolve14) => {
73067
+ await new Promise((resolve13) => {
73361
73068
  const done = () => {
73362
73069
  res.off("drain", done);
73363
73070
  res.off("close", done);
73364
- resolve14();
73071
+ resolve13();
73365
73072
  };
73366
73073
  res.once("drain", done);
73367
73074
  res.once("close", done);
@@ -73467,7 +73174,7 @@ async function openLocalTurnProjection(runsDir, runId, conversationId, ordinal)
73467
73174
  if (!reader) return null;
73468
73175
  let offset = toByteOffset(0);
73469
73176
  let ended = false;
73470
- let snapshot2;
73177
+ let snapshot;
73471
73178
  let prepared;
73472
73179
  const merge2 = /* @__PURE__ */ new Map();
73473
73180
  const decoder3 = new TextDecoder();
@@ -73479,13 +73186,13 @@ async function openLocalTurnProjection(runsDir, runId, conversationId, ordinal)
73479
73186
  if (applyLogChunk(decoder3.decode(chunk.bytes), assistantMessageId, state)) ended = true;
73480
73187
  offset = chunk.to;
73481
73188
  }
73482
- if (offset === priorOffset && snapshot2) return snapshot2;
73189
+ if (offset === priorOffset && snapshot) return snapshot;
73483
73190
  if (ended) state.state = "idle";
73484
- snapshot2 = mergeTranscriptMessages(
73191
+ snapshot = mergeTranscriptMessages(
73485
73192
  [{ messageId: assistantMessageId, turnOrdinal: ordinal, role: "assistant", state }],
73486
73193
  merge2
73487
73194
  );
73488
- return snapshot2;
73195
+ return snapshot;
73489
73196
  };
73490
73197
  return {
73491
73198
  runId,
@@ -73589,9 +73296,9 @@ async function readChangedTurn(deps, conversationId, runId, slot) {
73589
73296
  }
73590
73297
  async function nextChangedRuns(bell, signal) {
73591
73298
  if (bell.pending.size === 0) {
73592
- await new Promise((resolve14) => {
73593
- bell.wake = resolve14;
73594
- if (signal.aborted || bell.pending.size > 0) resolve14();
73299
+ await new Promise((resolve13) => {
73300
+ bell.wake = resolve13;
73301
+ if (signal.aborted || bell.pending.size > 0) resolve13();
73595
73302
  });
73596
73303
  bell.wake = void 0;
73597
73304
  }
@@ -73891,12 +73598,12 @@ function activeRunIds(runs) {
73891
73598
  var streamStatus = async ({ feed, appAttachments }, { res, signal }) => {
73892
73599
  var _stack = [];
73893
73600
  try {
73894
- const snapshot2 = await feed.refresh(signal);
73601
+ const snapshot = await feed.refresh(signal);
73895
73602
  const _attachment = __using(_stack, appAttachments.attach());
73896
73603
  startEventStream(res);
73897
73604
  const send2 = (name, event) => writeEvent(res, { name, id: String(event.seq), dataLines: [JSON.stringify(event)] });
73898
73605
  let latest = null;
73899
- let writing = send2("snapshot", snapshot2);
73606
+ let writing = send2("snapshot", snapshot);
73900
73607
  const flush = async () => {
73901
73608
  while (latest !== null && !res.destroyed) {
73902
73609
  const next = latest;
@@ -73908,9 +73615,9 @@ var streamStatus = async ({ feed, appAttachments }, { res, signal }) => {
73908
73615
  latest = event;
73909
73616
  writing = writing.then(flush);
73910
73617
  }));
73911
- await new Promise((resolve14) => {
73912
- if (signal.aborted) resolve14();
73913
- signal.addEventListener("abort", () => resolve14(), { once: true });
73618
+ await new Promise((resolve13) => {
73619
+ if (signal.aborted) resolve13();
73620
+ signal.addEventListener("abort", () => resolve13(), { once: true });
73914
73621
  });
73915
73622
  await writing;
73916
73623
  } catch (_) {
@@ -74233,11 +73940,11 @@ function localRequestSignal(path4, closed) {
74233
73940
  ]);
74234
73941
  }
74235
73942
  async function listenOnLoopback(server) {
74236
- await new Promise((resolve14, reject) => {
73943
+ await new Promise((resolve13, reject) => {
74237
73944
  server.once("error", reject);
74238
73945
  server.listen(0, "127.0.0.1", () => {
74239
73946
  server.off("error", reject);
74240
- resolve14();
73947
+ resolve13();
74241
73948
  });
74242
73949
  }).catch((error61) => {
74243
73950
  throw new RuntimeFault("io_failed", "The local API could not listen on loopback", {
@@ -74252,7 +73959,7 @@ async function listenOnLoopback(server) {
74252
73959
  }
74253
73960
  async function closeServer(server) {
74254
73961
  server.closeAllConnections();
74255
- await new Promise((resolve14) => server.close(() => resolve14()));
73962
+ await new Promise((resolve13) => server.close(() => resolve13()));
74256
73963
  }
74257
73964
  async function serveLocalApi(deps) {
74258
73965
  const limits = { ...DEFAULT_LIMITS, ...deps.limits };
@@ -74323,7 +74030,7 @@ async function serveLocalApi(deps) {
74323
74030
  startedAtMs,
74324
74031
  runtimeVersion: deps.runtimeVersion
74325
74032
  };
74326
- const discoveryPath = (0, import_node_path81.join)(deps.stateDir, LOCAL_API_DISCOVERY_FILE);
74033
+ const discoveryPath = (0, import_node_path79.join)(deps.stateDir, LOCAL_API_DISCOVERY_FILE);
74327
74034
  await writeJsonFileAtomic(discoveryPath, discovery);
74328
74035
  const followers = startMaintenance({
74329
74036
  everyMs: limits.refreshEveryMs,
@@ -74357,7 +74064,7 @@ async function serveLocalApi(deps) {
74357
74064
  await watchedStatus[Symbol.asyncDispose]();
74358
74065
  const current = await readJsonFile(discoveryPath, localApiDiscoverySchema);
74359
74066
  if (current.kind === "ok" && current.value.token === token) {
74360
- await (0, import_promises78.rm)(discoveryPath, { force: true });
74067
+ await (0, import_promises76.rm)(discoveryPath, { force: true });
74361
74068
  }
74362
74069
  await closeServer(server);
74363
74070
  log.info("local_api.closed", {});
@@ -74442,7 +74149,7 @@ function machineFeatureActions(deps) {
74442
74149
  }
74443
74150
 
74444
74151
  // src/cli/commands/machine-plane.ts
74445
- var import_node_path83 = require("path");
74152
+ var import_node_path81 = require("path");
74446
74153
 
74447
74154
  // src/link/index.ts
74448
74155
  init_runtime_v2();
@@ -77009,9 +76716,9 @@ var Socket2 = class extends Emitter {
77009
76716
  * @return a Promise that will be fulfilled when the server acknowledges the event
77010
76717
  */
77011
76718
  emitWithAck(ev, ...args) {
77012
- return new Promise((resolve14, reject) => {
76719
+ return new Promise((resolve13, reject) => {
77013
76720
  const fn = (arg1, arg2) => {
77014
- return arg1 ? reject(arg1) : resolve14(arg2);
76721
+ return arg1 ? reject(arg1) : resolve13(arg2);
77015
76722
  };
77016
76723
  fn.withError = true;
77017
76724
  args.push(fn);
@@ -78110,10 +77817,10 @@ function refusalFailure(refusal2) {
78110
77817
  }
78111
77818
 
78112
77819
  // src/link/probe.ts
78113
- var import_promises79 = require("dns/promises");
77820
+ var import_promises77 = require("dns/promises");
78114
77821
  var import_node_net5 = require("net");
78115
77822
  var import_node_tls2 = require("tls");
78116
- var PROBE_TIMEOUT_MS4 = 5e3;
77823
+ var PROBE_TIMEOUT_MS3 = 5e3;
78117
77824
  function openSocket(url3) {
78118
77825
  const secure = url3.protocol === "https:" || url3.protocol === "wss:";
78119
77826
  const host = url3.hostname;
@@ -78130,11 +77837,11 @@ async function connectOnce(url3, clock) {
78130
77837
  const timer = new AbortController();
78131
77838
  try {
78132
77839
  return await Promise.race([
78133
- new Promise((resolve14) => {
78134
- socket.once(ready, () => resolve14(null));
78135
- socket.once("error", (error61) => resolve14(classifyTransportFailure(error61)));
77840
+ new Promise((resolve13) => {
77841
+ socket.once(ready, () => resolve13(null));
77842
+ socket.once("error", (error61) => resolve13(classifyTransportFailure(error61)));
78136
77843
  }),
78137
- clock.sleep(PROBE_TIMEOUT_MS4, timer.signal).then(
77844
+ clock.sleep(PROBE_TIMEOUT_MS3, timer.signal).then(
78138
77845
  () => "connection_timeout",
78139
77846
  () => null
78140
77847
  )
@@ -78146,7 +77853,7 @@ async function connectOnce(url3, clock) {
78146
77853
  }
78147
77854
  async function probeEndpoint(url3, clock) {
78148
77855
  try {
78149
- await (0, import_promises79.lookup)(url3.hostname);
77856
+ await (0, import_promises77.lookup)(url3.hostname);
78150
77857
  } catch (error61) {
78151
77858
  const reason = classifyTransportFailure(error61);
78152
77859
  return reason === "other" ? "dns" : reason;
@@ -78433,13 +78140,13 @@ function connectLink(options) {
78433
78140
  socket.disconnect();
78434
78141
  socket.connect();
78435
78142
  };
78436
- const hearsServer = (timeoutMs) => new Promise((resolve14) => {
78143
+ const hearsServer = (timeoutMs) => new Promise((resolve13) => {
78437
78144
  const waiting = new AbortController();
78438
78145
  const settle = (alive) => {
78439
78146
  waiting.abort();
78440
78147
  socket.io.off("ping", onPing);
78441
78148
  socket.off("disconnect", onDrop);
78442
- resolve14(alive);
78149
+ resolve13(alive);
78443
78150
  };
78444
78151
  const onPing = () => settle(true);
78445
78152
  const onDrop = () => settle(false);
@@ -78637,12 +78344,13 @@ function createReconciler(host, lifecycle, log, signal) {
78637
78344
  }
78638
78345
 
78639
78346
  // src/uploader/index.ts
78640
- var import_promises80 = require("fs/promises");
78347
+ var import_promises78 = require("fs/promises");
78641
78348
  init_runtime_v2();
78642
78349
  init_zod();
78643
78350
  var RETRY_DELAYS_MS = [250, 500, 1e3, 2e3, 5e3, 1e4, 3e4];
78644
78351
  var PARK_MS = 5 * 6e4;
78645
78352
  var UNAUTHORIZED = 401;
78353
+ var RETRY_JITTER = 0.2;
78646
78354
  var uploadProgressSchema = external_exports.object({
78647
78355
  admittedOffset: external_exports.number().int().nonnegative(),
78648
78356
  sealed: external_exports.boolean(),
@@ -78650,16 +78358,50 @@ var uploadProgressSchema = external_exports.object({
78650
78358
  parkedUntil: external_exports.number().int().nonnegative().optional()
78651
78359
  });
78652
78360
  function progressFromReceipt(receipt) {
78653
- return { admittedOffset: receipt?.admittedOffset ?? 0, sealed: receipt?.finalized ?? false };
78361
+ return {
78362
+ admittedOffset: receipt?.admittedOffset ?? 0,
78363
+ sealed: receipt !== null && (receipt.finalized || receipt.finalOffset !== null)
78364
+ };
78654
78365
  }
78655
- function startUploader({ api, runsDir, clock, log, archive }) {
78366
+ function startUploader({
78367
+ api,
78368
+ runsDir,
78369
+ clock,
78370
+ log,
78371
+ archive,
78372
+ random = Math.random,
78373
+ onUnauthorized
78374
+ }) {
78656
78375
  const controller = new AbortController();
78657
78376
  const active = /* @__PURE__ */ new Map();
78658
78377
  const again = /* @__PURE__ */ new Set();
78659
78378
  const sealed = /* @__PURE__ */ new Set();
78379
+ const receiptBackoff = /* @__PURE__ */ new Map();
78380
+ let pendingRuns = /* @__PURE__ */ new Map();
78381
+ const retrying = /* @__PURE__ */ new Set();
78382
+ let renewing = null;
78383
+ const retryDelay = (failures) => {
78384
+ const base = RETRY_DELAYS_MS[Math.min(failures, RETRY_DELAYS_MS.length - 1)] ?? 3e4;
78385
+ return Math.round(base * (1 - RETRY_JITTER + 2 * RETRY_JITTER * random()));
78386
+ };
78387
+ const renewCredential = () => {
78388
+ if (onUnauthorized === void 0) return Promise.resolve();
78389
+ renewing ??= onUnauthorized().catch((error61) => log.warn("upload.renew_failed", { error: error61 })).finally(() => {
78390
+ renewing = null;
78391
+ });
78392
+ return renewing;
78393
+ };
78394
+ const deferReceipt = (runId) => {
78395
+ const failures = (receiptBackoff.get(runId)?.failures ?? 0) + 1;
78396
+ receiptBackoff.set(runId, { failures, notBefore: clock.now() + retryDelay(failures) });
78397
+ };
78660
78398
  const reject = async (runId, progressPath, progress, rejection2) => {
78661
78399
  log.error("upload.rejected", { runId, status: rejection2.status, message: rejection2.message });
78662
- if (rejection2.status === UNAUTHORIZED) return;
78400
+ if (rejection2.status === UNAUTHORIZED) {
78401
+ await renewCredential();
78402
+ deferReceipt(runId);
78403
+ return;
78404
+ }
78663
78405
  const parkedUntil = clock.now() + PARK_MS;
78664
78406
  await writeJsonFileAtomic(progressPath, { ...progress, parkedUntil });
78665
78407
  log.warn("upload.parked", { runId, parkedUntil });
@@ -78667,22 +78409,31 @@ function startUploader({ api, runsDir, clock, log, archive }) {
78667
78409
  const progressOf = async (runId, target, path4) => {
78668
78410
  const stored = await readJsonFile(path4, uploadProgressSchema);
78669
78411
  if (stored.kind === "ok") return stored.value;
78412
+ const listed = pendingRuns.get(runId);
78413
+ if (listed !== void 0) {
78414
+ const progress = { admittedOffset: listed.admittedOffset, sealed: false };
78415
+ await writeJsonFileAtomic(path4, progress);
78416
+ return progress;
78417
+ }
78670
78418
  const receipt = await api.readReceipt(target, controller.signal);
78671
78419
  switch (receipt.kind) {
78672
78420
  case "read": {
78421
+ receiptBackoff.delete(runId);
78673
78422
  log.debug("upload.resumed", {
78674
78423
  runId,
78675
78424
  admittedOffset: receipt.receipt?.admittedOffset ?? 0
78676
78425
  });
78677
78426
  const progress = progressFromReceipt(receipt.receipt);
78678
- if (progress.sealed) await writeJsonFileAtomic(path4, progress);
78427
+ await writeJsonFileAtomic(path4, progress);
78679
78428
  return progress;
78680
78429
  }
78681
78430
  case "rejected":
78682
78431
  await reject(runId, path4, progressFromReceipt(null), receipt);
78683
78432
  return null;
78684
- case "retry":
78433
+ case "retry": {
78434
+ deferReceipt(runId);
78685
78435
  throw new RuntimeFault("io_failed", `Receipt request failed: ${receipt.status}`);
78436
+ }
78686
78437
  default:
78687
78438
  return assertNever2(receipt);
78688
78439
  }
@@ -78708,7 +78459,9 @@ function startUploader({ api, runsDir, clock, log, archive }) {
78708
78459
  case "offset_conflict": {
78709
78460
  const receipt = await api.readReceipt(upload2.target, controller.signal);
78710
78461
  if (receipt.kind === "read") {
78711
- return { kind: "advanced", progress: progressFromReceipt(receipt.receipt) };
78462
+ const next = progressFromReceipt(receipt.receipt);
78463
+ await writeJsonFileAtomic(upload2.progressPath, next);
78464
+ return { kind: "advanced", progress: next };
78712
78465
  }
78713
78466
  return receipt.kind === "retry" ? receipt : { kind: "rejected", rejection: receipt };
78714
78467
  }
@@ -78721,7 +78474,7 @@ function startUploader({ api, runsDir, clock, log, archive }) {
78721
78474
  }
78722
78475
  };
78723
78476
  const backOff = async (runId, status, failures) => {
78724
- const delay4 = RETRY_DELAYS_MS[Math.min(failures, RETRY_DELAYS_MS.length - 1)] ?? 3e4;
78477
+ const delay4 = retryDelay(failures);
78725
78478
  log.warn("upload.retrying", { runId, status, delayMs: delay4 });
78726
78479
  await clock.sleep(delay4, controller.signal);
78727
78480
  };
@@ -78731,10 +78484,10 @@ function startUploader({ api, runsDir, clock, log, archive }) {
78731
78484
  let failures = 0;
78732
78485
  while (!controller.signal.aborted) {
78733
78486
  const step = await sendNext(runUpload, progress);
78734
- if (step.kind === "caught_up") return;
78487
+ if (step.kind === "caught_up") return "settled";
78735
78488
  if (step.kind === "rejected") {
78736
78489
  await reject(runId, runUpload.progressPath, progress, step.rejection);
78737
- return;
78490
+ return "retry_later";
78738
78491
  }
78739
78492
  if (step.kind === "retry") {
78740
78493
  await backOff(runId, step.status, failures);
@@ -78742,27 +78495,40 @@ function startUploader({ api, runsDir, clock, log, archive }) {
78742
78495
  continue;
78743
78496
  }
78744
78497
  failures = 0;
78498
+ receiptBackoff.delete(runId);
78745
78499
  progress = step.progress;
78746
78500
  if (progress.sealed) {
78747
78501
  sealed.add(runId);
78748
78502
  log.info("upload.sealed", { runId, bytes: progress.admittedOffset });
78749
- return;
78503
+ return "settled";
78750
78504
  }
78751
78505
  }
78506
+ return "settled";
78752
78507
  };
78753
78508
  const upload = async (runId) => {
78754
78509
  var _stack = [];
78755
78510
  try {
78756
78511
  const dir = runDirectory(runsDir, runId);
78757
78512
  const meta3 = await readRunMeta(dir.meta);
78758
- if (meta3 === null) return;
78513
+ if (meta3 === null) return "settled";
78759
78514
  const target = { conversationId: meta3.conversationId, runId };
78515
+ const backoff = receiptBackoff.get(runId);
78516
+ if (backoff !== void 0 && backoff.notBefore > clock.now()) return "retry_later";
78760
78517
  const progress = await progressOf(runId, target, dir.upload);
78761
- if (progress?.sealed) sealed.add(runId);
78762
- if (progress === null || progress.sealed) return;
78763
- if (progress.parkedUntil !== void 0 && progress.parkedUntil > clock.now()) return;
78518
+ if (progress === null) return "retry_later";
78519
+ if (progress.sealed) {
78520
+ sealed.add(runId);
78521
+ return "settled";
78522
+ }
78523
+ if (progress.parkedUntil !== void 0 && progress.parkedUntil > clock.now()) {
78524
+ return "retry_later";
78525
+ }
78764
78526
  const reader = __using(_stack, await openRunLogReader(dir.log), true);
78765
- await drain({ target, reader, logPath: dir.log, progressPath: dir.upload }, progress);
78527
+ const attempt2 = await drain(
78528
+ { target, reader, logPath: dir.log, progressPath: dir.upload },
78529
+ progress
78530
+ );
78531
+ return attempt2;
78766
78532
  } catch (_) {
78767
78533
  var _error = _, _hasError = true;
78768
78534
  } finally {
@@ -78775,7 +78541,11 @@ function startUploader({ api, runsDir, clock, log, archive }) {
78775
78541
  again.add(runId);
78776
78542
  return;
78777
78543
  }
78778
- const task = upload(runId).catch((error61) => {
78544
+ const task = upload(runId).then((attempt2) => {
78545
+ if (attempt2 === "settled") retrying.delete(runId);
78546
+ else retrying.add(runId);
78547
+ }).catch((error61) => {
78548
+ retrying.add(runId);
78779
78549
  if (!controller.signal.aborted) log.warn("upload.failed", { runId, error: error61 });
78780
78550
  }).finally(() => {
78781
78551
  active.delete(runId);
@@ -78783,30 +78553,38 @@ function startUploader({ api, runsDir, clock, log, archive }) {
78783
78553
  });
78784
78554
  active.set(runId, task);
78785
78555
  };
78556
+ const isDone = (runId) => sealed.has(runId) || archive?.has(runId) === true;
78786
78557
  const unsealedRunIds = async () => {
78787
78558
  const runIds = [];
78788
- for (const name of await (0, import_promises80.readdir)(runsDir).catch(() => [])) {
78559
+ for (const name of await (0, import_promises78.readdir)(runsDir).catch(() => [])) {
78789
78560
  const runId = runIdSchema.safeParse(name);
78790
- if (runId.success && !sealed.has(runId.data) && !archive?.has(runId.data))
78791
- runIds.push(runId.data);
78561
+ if (runId.success && !isDone(runId.data)) runIds.push(runId.data);
78792
78562
  }
78793
78563
  return runIds;
78794
78564
  };
78565
+ const hasProgress = async (runId) => await (0, import_promises78.stat)(runDirectory(runsDir, runId).upload).catch(() => null) !== null;
78795
78566
  const sweep2 = async () => {
78796
- for (const runId of await unsealedRunIds()) run2(runId);
78567
+ for (const runId of await unsealedRunIds()) {
78568
+ if (!await hasProgress(runId)) run2(runId);
78569
+ }
78570
+ };
78571
+ const retryPending = () => {
78572
+ for (const runId of /* @__PURE__ */ new Set([...pendingRuns.keys(), ...retrying])) {
78573
+ if (!isDone(runId)) run2(runId);
78574
+ }
78797
78575
  };
78798
78576
  const isArchivable = async (runId, options) => {
78799
78577
  if (options.keep.has(runId) || active.has(runId)) return false;
78800
78578
  const dir = runDirectory(runsDir, runId);
78801
78579
  const progress = await readJsonFile(dir.upload, uploadProgressSchema);
78802
78580
  if (progress.kind !== "ok" || !progress.value.sealed) return false;
78803
- const sealedAt = (await (0, import_promises80.stat)(dir.upload)).mtimeMs;
78581
+ const sealedAt = (await (0, import_promises78.stat)(dir.upload)).mtimeMs;
78804
78582
  if (clock.now() - sealedAt < options.sealedForMs) return false;
78805
78583
  return (await readLastRecord(dir.log))?.update.sessionUpdate === "_alan/run.ended";
78806
78584
  };
78807
78585
  const archivable = async (options) => {
78808
78586
  const found = [];
78809
- for (const name of await (0, import_promises80.readdir)(runsDir).catch(() => [])) {
78587
+ for (const name of await (0, import_promises78.readdir)(runsDir).catch(() => [])) {
78810
78588
  const runId = runIdSchema.safeParse(name);
78811
78589
  if (!runId.success || archive?.has(runId.data)) continue;
78812
78590
  try {
@@ -78820,9 +78598,15 @@ function startUploader({ api, runsDir, clock, log, archive }) {
78820
78598
  return {
78821
78599
  notify: run2,
78822
78600
  sweep: sweep2,
78601
+ pending: (uploads) => {
78602
+ pendingRuns = new Map(
78603
+ uploads.map((upload2) => [upload2.runId, upload2])
78604
+ );
78605
+ },
78606
+ retryPending,
78823
78607
  archivable,
78824
78608
  flush: async () => {
78825
- await sweep2();
78609
+ for (const runId of await unsealedRunIds()) run2(runId);
78826
78610
  while (active.size > 0 && !controller.signal.aborted) {
78827
78611
  await Promise.allSettled([...active.values()]);
78828
78612
  }
@@ -79008,12 +78792,12 @@ async function startMachineNativeIngest(deps) {
79008
78792
  }
79009
78793
 
79010
78794
  // src/cli/commands/run-updates.ts
79011
- var import_node_path82 = require("path");
78795
+ var import_node_path80 = require("path");
79012
78796
  init_runtime_v2();
79013
78797
  var UPDATE_CHECK_EVERY_MS = 6 * 60 * 60 * 1e3;
79014
78798
  var DEFERRED_RETRY_MS = 5 * 60 * 1e3;
79015
78799
  function isInstalledBundle(layout, bundlePath) {
79016
- return (0, import_node_path82.resolve)((0, import_node_path82.dirname)((0, import_node_path82.dirname)(bundlePath))) === (0, import_node_path82.resolve)(layout.versions);
78800
+ return (0, import_node_path80.resolve)((0, import_node_path80.dirname)((0, import_node_path80.dirname)(bundlePath))) === (0, import_node_path80.resolve)(layout.versions);
79017
78801
  }
79018
78802
  async function settleUpgradeOnStart({
79019
78803
  layout,
@@ -79120,7 +78904,7 @@ function startRuntimeUpdates(options) {
79120
78904
  layout,
79121
78905
  release: npmRelease,
79122
78906
  tarball: await options.downloader.download(npmRelease.dist.tarball, signal),
79123
- tmpDir: (0, import_node_path82.join)(layout.root, ".downloads")
78907
+ tmpDir: (0, import_node_path80.join)(layout.root, ".downloads")
79124
78908
  });
79125
78909
  await lifecycle.exclusive("upgrade", async () => {
79126
78910
  await recordPendingUpgrade(layout, currentVersion2, version2, clock.now());
@@ -79171,7 +78955,7 @@ var CAPABILITY_MAX_AGE_MS = 6e4;
79171
78955
  var RUN_ARCHIVE_EVERY_MS = 6 * 60 * 6e4;
79172
78956
  var SEALED_RUN_ARCHIVE_MS = 7 * 24 * 60 * 6e4;
79173
78957
  var DESIRED_RESYNC_TICK_MS = 5e3;
79174
- var UPLOAD_SWEEP_EVERY_MS = 3e4;
78958
+ var UPLOAD_RETRY_EVERY_MS = 3e4;
79175
78959
  function setupFor(state) {
79176
78960
  if (state.kind !== "stopped") return "ready";
79177
78961
  switch (state.failure.reason) {
@@ -79212,6 +78996,13 @@ async function startMachinePlane(deps) {
79212
78996
  accessToken: identity.accessToken,
79213
78997
  transport
79214
78998
  });
78999
+ const renewAfterRejection = async () => {
79000
+ const renewal = await lifecycle.exclusive(
79001
+ "renew",
79002
+ () => identity.renewAfterRejection(stopped.signal)
79003
+ );
79004
+ if (renewal.kind === "revoked") deps.onRevoked();
79005
+ };
79215
79006
  const sessionsOpened = Promise.withResolvers();
79216
79007
  const planeOpened = Promise.withResolvers();
79217
79008
  const boot = { sessionsMs: 0, openedMs: 0 };
@@ -79232,7 +79023,8 @@ async function startMachinePlane(deps) {
79232
79023
  void skills.sync();
79233
79024
  desiredSync.received({
79234
79025
  runs: ack.desired.runs,
79235
- ...ack.approvedWorkspacePaths === void 0 ? {} : { approvedWorkspacePaths: ack.approvedWorkspacePaths }
79026
+ ...ack.approvedWorkspacePaths === void 0 ? {} : { approvedWorkspacePaths: ack.approvedWorkspacePaths },
79027
+ ...ack.desired.pendingUploads === void 0 ? {} : { pendingUploads: ack.desired.pendingUploads }
79236
79028
  });
79237
79029
  },
79238
79030
  onPoke: (poke) => {
@@ -79252,13 +79044,7 @@ async function startMachinePlane(deps) {
79252
79044
  refreshDesired();
79253
79045
  },
79254
79046
  onConnectRefused: (error61) => updates.connectRefused(error61),
79255
- refreshCredential: async () => {
79256
- const renewal = await lifecycle.exclusive(
79257
- "renew",
79258
- () => identity.renewAfterRejection(stopped.signal)
79259
- );
79260
- if (renewal.kind === "revoked") deps.onRevoked();
79261
- },
79047
+ refreshCredential: renewAfterRejection,
79262
79048
  onStateChange: deps.onStatusChange,
79263
79049
  answerWorkspaceQuery: (request2) => workspaces.answer(request2),
79264
79050
  respond: (request2) => sessions.respond(request2),
@@ -79312,7 +79098,16 @@ async function startMachinePlane(deps) {
79312
79098
  (error61) => log.warn("conversation_index.rebuild_failed", { error: error61 })
79313
79099
  );
79314
79100
  const archive = await openRunArchive(paths.runs);
79315
- const uploader = stack.use(startUploader({ api, runsDir: paths.runs, clock, log, archive }));
79101
+ const uploader = stack.use(
79102
+ startUploader({
79103
+ api,
79104
+ runsDir: paths.runs,
79105
+ clock,
79106
+ log,
79107
+ archive,
79108
+ onUnauthorized: renewAfterRejection
79109
+ })
79110
+ );
79316
79111
  const nativeIngest = stack.use(
79317
79112
  await startMachineNativeIngest({
79318
79113
  stateDir: paths.stateDir,
@@ -79353,7 +79148,7 @@ async function startMachinePlane(deps) {
79353
79148
  [ALAN_MANAGED_SESSION_ENV]: "1"
79354
79149
  },
79355
79150
  cwd: paths.stateDir,
79356
- outputPath: (0, import_node_path83.join)(paths.logs, "holders.log")
79151
+ outputPath: (0, import_node_path81.join)(paths.logs, "holders.log")
79357
79152
  },
79358
79153
  deps.holderIsolation
79359
79154
  );
@@ -79390,7 +79185,7 @@ async function startMachinePlane(deps) {
79390
79185
  }),
79391
79186
  local: { home: config2.home, machineId: identity.machineId },
79392
79187
  // Only a cloud sandbox's runtime has a git gateway; a person's own ~/.codex is theirs.
79393
- ...config2.gitGatewayUrl === null ? {} : { codexSkillsDir: (0, import_node_path83.join)(config2.codexHome, "skills") },
79188
+ ...config2.gitGatewayUrl === null ? {} : { codexSkillsDir: (0, import_node_path81.join)(config2.codexHome, "skills") },
79394
79189
  log
79395
79190
  })
79396
79191
  );
@@ -79486,8 +79281,8 @@ async function startMachinePlane(deps) {
79486
79281
  );
79487
79282
  stack.use(
79488
79283
  startMaintenance({
79489
- everyMs: UPLOAD_SWEEP_EVERY_MS,
79490
- jobs: [{ name: "uploader.sweep", run: () => uploader.sweep() }],
79284
+ everyMs: UPLOAD_RETRY_EVERY_MS,
79285
+ jobs: [{ name: "uploader.retry_pending", run: () => uploader.retryPending() }],
79491
79286
  clock,
79492
79287
  log
79493
79288
  })
@@ -79592,7 +79387,7 @@ async function startMachinePlane(deps) {
79592
79387
  git: createGitRunner({ env: cliEnvironment }),
79593
79388
  clock,
79594
79389
  log,
79595
- dir: (0, import_node_path83.join)(paths.stateDir, "checkout-freshness")
79390
+ dir: (0, import_node_path81.join)(paths.stateDir, "checkout-freshness")
79596
79391
  },
79597
79392
  stopped.signal
79598
79393
  );
@@ -79601,6 +79396,7 @@ async function startMachinePlane(deps) {
79601
79396
  const desiredSync = createDesiredSync({
79602
79397
  read: (etag, signal) => api.fetchDesiredIfChanged(etag, signal),
79603
79398
  apply: (desired) => {
79399
+ uploader.pending(desired.pendingUploads ?? []);
79604
79400
  void workspaces.learn(desired.runs, desired.approvedWorkspacePaths);
79605
79401
  void reconciler.reconcile(desired.runs);
79606
79402
  },
@@ -79855,11 +79651,11 @@ function createMachineSlot(deps) {
79855
79651
 
79856
79652
  // src/cli/commands/run-exit.ts
79857
79653
  function firstAborted(signals) {
79858
- return new Promise((resolve14) => {
79654
+ return new Promise((resolve13) => {
79859
79655
  for (const reason of ["stop", "restart"]) {
79860
79656
  const signal = signals[reason];
79861
- if (signal.aborted) resolve14(reason);
79862
- signal.addEventListener("abort", () => resolve14(reason), { once: true });
79657
+ if (signal.aborted) resolve13(reason);
79658
+ signal.addEventListener("abort", () => resolve13(reason), { once: true });
79863
79659
  }
79864
79660
  });
79865
79661
  }
@@ -79887,7 +79683,7 @@ function lockWaitMs(argv) {
79887
79683
  }
79888
79684
  async function openManagedProviders(config2, paths) {
79889
79685
  const providerEnv = readCliEnvironment();
79890
- const bundledNpm = (0, import_node_path84.join)((0, import_node_path84.dirname)(process.execPath), "npm", "bin", "npm-cli.js");
79686
+ const bundledNpm = (0, import_node_path82.join)((0, import_node_path82.dirname)(process.execPath), "npm", "bin", "npm-cli.js");
79891
79687
  const providerToolchain = config2.providerToolchain ?? (process.platform === "win32" && (0, import_node_fs24.existsSync)(bundledNpm) ? { node: process.execPath, npmCli: bundledNpm } : null);
79892
79688
  const npmPath = providerToolchain?.node ?? await resolveCommandOnPath("npm", providerEnv, process.platform);
79893
79689
  const npmOptions = npmPath === null || process.platform === "win32" && providerToolchain === null ? null : {
@@ -79895,7 +79691,7 @@ async function openManagedProviders(config2, paths) {
79895
79691
  ...providerToolchain === null ? {} : { argsBeforeNpm: [providerToolchain.npmCli] },
79896
79692
  env: providerEnv
79897
79693
  };
79898
- const providerNodeDir = providerToolchain?.node === void 0 ? void 0 : (0, import_node_path84.dirname)(providerToolchain.node);
79694
+ const providerNodeDir = providerToolchain?.node === void 0 ? void 0 : (0, import_node_path82.dirname)(providerToolchain.node);
79899
79695
  const probeEnv = providerNodeDir === void 0 ? providerEnv : {
79900
79696
  ...providerEnv,
79901
79697
  PATH: `${providerNodeDir}${pathDelimiter(process.platform)}${envValue(providerEnv, "PATH")}`
@@ -79905,7 +79701,7 @@ async function openManagedProviders(config2, paths) {
79905
79701
  throw new Error("Provider installer is unavailable on this computer");
79906
79702
  };
79907
79703
  const managed = createManagedProviderClis({
79908
- root: (0, import_node_path84.join)(paths.stateDir, "provider-clis"),
79704
+ root: (0, import_node_path82.join)(paths.stateDir, "provider-clis"),
79909
79705
  resolveVersion: npmOptions === null ? unavailable : createNpmVersionResolver(npmOptions),
79910
79706
  installPackage: npmOptions === null ? unavailable : createNpmPackageInstaller(npmOptions),
79911
79707
  probe: (executable, backendKind) => probeManagedProvider(executable, backendKind, canonicalProbeEnv)
@@ -79937,7 +79733,7 @@ async function runService(argv, stop, restart = new AbortController().signal) {
79937
79733
  waitMs: lockWaitMs(argv),
79938
79734
  signal: stop
79939
79735
  }));
79940
- const log = __using(_stack, openFileLog((0, import_node_path84.join)(paths.logs, "runtime.jsonl"), config2.logLevel, clock));
79736
+ const log = __using(_stack, openFileLog((0, import_node_path82.join)(paths.logs, "runtime.jsonl"), config2.logLevel, clock));
79941
79737
  const lifecycle = createLifecycleQueue({ clock, log });
79942
79738
  const install2 = installLayout(config2.installDir, config2.profile);
79943
79739
  const bundlePath = process.argv[1] ?? "";
@@ -79971,7 +79767,7 @@ async function runService(argv, stop, restart = new AbortController().signal) {
79971
79767
  openCliEnvironment({
79972
79768
  env: readCliEnvironment(),
79973
79769
  platform: process.platform,
79974
- lastKnownGoodFile: (0, import_node_path84.join)(paths.stateDir, "login-path.json"),
79770
+ lastKnownGoodFile: (0, import_node_path82.join)(paths.stateDir, "login-path.json"),
79975
79771
  clock,
79976
79772
  decorate: (env) => withPackagedAlanCodeEngine(env, bundlePath, process.platform)
79977
79773
  })
@@ -80148,17 +79944,17 @@ async function runServiceCommand(argv, ctx = cliContext()) {
80148
79944
  }
80149
79945
 
80150
79946
  // src/cli/commands/upgrade.ts
80151
- var import_promises81 = require("fs/promises");
80152
- var import_node_path85 = require("path");
79947
+ var import_promises79 = require("fs/promises");
79948
+ var import_node_path83 = require("path");
80153
79949
  function isNotNewer(version2, installed) {
80154
79950
  return installed !== null && isReleaseVersion(version2) && isReleaseVersion(installed) && compareVersions(version2, installed) <= 0;
80155
79951
  }
80156
79952
  async function installFromSource(source) {
80157
79953
  const { layout, from, ifNewer } = source;
80158
- const isTarball = (await (0, import_promises81.stat)(from)).isFile();
80159
- const downloads = (0, import_node_path85.join)(layout.root, ".downloads");
80160
- if (isTarball) await (0, import_promises81.mkdir)(downloads, { recursive: true, mode: 448 });
80161
- const scratch = isTarball ? await (0, import_promises81.mkdtemp)((0, import_node_path85.join)(downloads, "upgrade-")) : null;
79954
+ const isTarball = (await (0, import_promises79.stat)(from)).isFile();
79955
+ const downloads = (0, import_node_path83.join)(layout.root, ".downloads");
79956
+ if (isTarball) await (0, import_promises79.mkdir)(downloads, { recursive: true, mode: 448 });
79957
+ const scratch = isTarball ? await (0, import_promises79.mkdtemp)((0, import_node_path83.join)(downloads, "upgrade-")) : null;
80162
79958
  try {
80163
79959
  const sourceDir = scratch === null ? from : await extractPackageTarball(from, scratch);
80164
79960
  const version2 = await readPackageVersion(sourceDir);
@@ -80166,7 +79962,7 @@ async function installFromSource(source) {
80166
79962
  if (ifNewer && isNotNewer(version2, installed)) return { kind: "skipped", version: version2, installed };
80167
79963
  return { kind: "installed", ...await installVersion(layout, sourceDir) };
80168
79964
  } finally {
80169
- if (scratch !== null) await (0, import_promises81.rm)(scratch, { recursive: true, force: true });
79965
+ if (scratch !== null) await (0, import_promises79.rm)(scratch, { recursive: true, force: true });
80170
79966
  }
80171
79967
  }
80172
79968
  async function runUpgrade(argv) {
@@ -80178,7 +79974,7 @@ async function runUpgrade(argv) {
80178
79974
  const layout = installLayout(config2.installDir, config2.profile);
80179
79975
  const outcome2 = await installFromSource({
80180
79976
  layout,
80181
- from: (0, import_node_path85.resolve)(from),
79977
+ from: (0, import_node_path83.resolve)(from),
80182
79978
  ifNewer: hasFlag(argv, "--if-newer")
80183
79979
  });
80184
79980
  if (outcome2.kind === "skipped") {
@@ -80241,8 +80037,9 @@ the code matches, and approve. Setup waits (polling every 5 s, slower if Alan as
80241
80037
  continues once approved; the code expires after 10 minutes and works once.
80242
80038
 
80243
80039
  A previous Alan agent (v1, \`ai.tryalan.agent\`) is moved over first, once its API is
80244
- confirmed to serve this runtime: its service is stopped and removed, setup waits until
80245
- its process has exited, and only then renews its credential, so a v1 daemon can never
80040
+ confirmed to serve this runtime: its service is stopped and removed, setup waits up to
80041
+ 15 s for its process to exit, then stops it and any other v1 daemon of the profile
80042
+ (SIGTERM, then SIGKILL), and only then renews its credential, so a v1 daemon can never
80246
80043
  trip the server's reuse detection. Its config.json is kept as config.json.migrated-v1
80247
80044
  with the tokens removed. Without --token, a v1 install is moved by renewing its
80248
80045
  credential, and a computer that is already set up just gets its service re-installed.