@alan-ai-hq/agent-manager-linux-x64 0.1.128 → 0.1.130

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 +623 -533
  2. package/alan-holder.cjs +303 -363
  3. package/package.json +1 -1
package/alan-agent.cjs CHANGED
@@ -21358,11 +21358,8 @@ var init_workflow_tools_filter = __esm({
21358
21358
  "create_test_report",
21359
21359
  "create_plan",
21360
21360
  "create_document_artifact",
21361
- "upsert_prototype_version",
21362
21361
  "list_artifacts",
21363
- "get_artifact",
21364
- "list_prototypes",
21365
- "get_prototype"
21362
+ "get_artifact"
21366
21363
  ];
21367
21364
  LEGACY_WORKFLOW_BUILTIN_TOOLS = {
21368
21365
  list_document_comments: "get_document",
@@ -22352,7 +22349,7 @@ var init_chunk_YXWJW7I5 = __esm({
22352
22349
  }
22353
22350
  });
22354
22351
 
22355
- // ../agent-core/dist/chunk-VZIZDY3T.js
22352
+ // ../agent-core/dist/chunk-NDAB5G24.js
22356
22353
  function windowsEnvValue(env, name) {
22357
22354
  const wanted = name.toLowerCase();
22358
22355
  for (const [key, value2] of Object.entries(env)) {
@@ -22476,6 +22473,12 @@ function planSpawn({ command, args, env, platform: platform3, files }) {
22476
22473
  if (launch === void 0) {
22477
22474
  throw new CoreFault("spawn_failed", `Could not start ${command} (not found on PATH)`);
22478
22475
  }
22476
+ if (launch.kind === "batch") {
22477
+ throw new CoreFault(
22478
+ "spawn_failed",
22479
+ `${command} resolves to a batch file that cannot run as a managed Windows agent; install its native executable or supported npm shim`
22480
+ );
22481
+ }
22479
22482
  return { file: launch.file, args: launch.args, commandLine: windowsCommandLine(launch, env) };
22480
22483
  }
22481
22484
  function planDirectLaunch({
@@ -22807,45 +22810,90 @@ function createProcessTree(child, options = {}) {
22807
22810
  }
22808
22811
  };
22809
22812
  }
22810
- function bridgeScript(ownerPid) {
22811
- return [
22812
- "$ErrorActionPreference = 'Stop'",
22813
- "$ProgressPreference = 'SilentlyContinue'",
22814
- `Add-Type -TypeDefinition @'
22815
- ${BRIDGE_SOURCE}
22816
- '@`,
22817
- `exit [AlanProviderJob]::Run($env:${JOB_COMMAND_VARIABLE}, ${ownerPid})`
22818
- ].join("\n");
22813
+ function providerEnvironment(env) {
22814
+ const unique2 = /* @__PURE__ */ new Map();
22815
+ for (const [name, value2] of Object.entries(env)) {
22816
+ if (/^ALAN_JOB_(FILE|COMMAND|STATUS)$/i.test(name) || /^ALAN_WINHELPER_PATH$/i.test(name))
22817
+ continue;
22818
+ unique2.set(name.toLowerCase(), [name, value2]);
22819
+ }
22820
+ return Object.fromEntries(unique2.values());
22819
22821
  }
22820
- function windowsJobBridge(commandLine, options) {
22821
- const systemRoot = windowsEnvValue(options.env, "SystemRoot") ?? "C:\\Windows";
22822
- const script = bridgeScript(options.ownerPid ?? process.pid);
22823
- return {
22824
- file: import_path2.win32.join(systemRoot, "System32", "WindowsPowerShell", "v1.0", "powershell.exe"),
22825
- args: [
22826
- "-NoLogo",
22827
- "-NoProfile",
22828
- "-NonInteractive",
22829
- "-ExecutionPolicy",
22830
- "Bypass",
22831
- "-EncodedCommand",
22832
- Buffer.from(script, "utf16le").toString("base64")
22833
- ],
22834
- env: { ...options.env, [JOB_COMMAND_VARIABLE]: commandLine }
22835
- };
22822
+ function requireStartedProvider(response, command) {
22823
+ if (response.startsWith("error:")) {
22824
+ throw new CoreFault("spawn_failed", `Could not start ${command} (${response.slice(6)})`);
22825
+ }
22826
+ if (!/^\d+$/.test(response)) {
22827
+ throw new CoreFault("spawn_failed", `Could not start ${command} (invalid helper response)`);
22828
+ }
22829
+ }
22830
+ function isWindowsJob(child) {
22831
+ return statuses.has(child);
22832
+ }
22833
+ function helperFile(env) {
22834
+ const override = Object.entries(env).find(([name]) => /^ALAN_WINHELPER_PATH$/i.test(name))?.[1];
22835
+ if (override) return override;
22836
+ const entry = process.argv[1];
22837
+ if (!entry) throw new CoreFault("spawn_failed", "Cannot locate the Windows agent helper");
22838
+ return (0, import_path2.join)((0, import_path2.dirname)(entry), "alan-winhelper.exe");
22836
22839
  }
22837
22840
  function spawnInWindowsJob(plan2, options) {
22838
22841
  if (plan2.commandLine === null) {
22839
22842
  throw new CoreFault("internal", `No Windows command line was planned for ${plan2.file}`);
22840
22843
  }
22841
- const bridge = windowsJobBridge(plan2.commandLine, options);
22842
- return (0, import_child_process6.spawn)(bridge.file, [...bridge.args], {
22844
+ const file2 = helperFile(options.env);
22845
+ const directory = (0, import_fs2.mkdtempSync)((0, import_path2.join)((0, import_os.tmpdir)(), `alan-job-${(0, import_crypto.randomUUID)()}-`));
22846
+ const path4 = (0, import_path2.join)(directory, "started");
22847
+ const child = (0, import_child_process6.spawn)(file2, [String(process.pid)], {
22843
22848
  cwd: options.cwd,
22844
- env: { ...bridge.env },
22849
+ env: {
22850
+ ...providerEnvironment(options.env),
22851
+ ALAN_JOB_FILE: plan2.file,
22852
+ ALAN_JOB_COMMAND: plan2.commandLine,
22853
+ ALAN_JOB_STATUS: path4
22854
+ },
22845
22855
  stdio: ["pipe", "pipe", "pipe"],
22846
22856
  shell: false,
22847
22857
  windowsHide: true
22848
22858
  });
22859
+ const status = { directory, path: path4 };
22860
+ child.once("error", (error61) => {
22861
+ status.error = error61;
22862
+ });
22863
+ statuses.set(child, status);
22864
+ return child;
22865
+ }
22866
+ async function waitForWindowsJob(child, command) {
22867
+ const status = statuses.get(child);
22868
+ if (!status) throw new CoreFault("internal", "Missing Windows helper startup state");
22869
+ const deadline = systemClock2.monotonic() + START_TIMEOUT_MS;
22870
+ try {
22871
+ while (systemClock2.monotonic() < deadline) {
22872
+ const providerPid = await (0, import_promises10.readFile)(status.path, "utf8").catch(() => void 0);
22873
+ if (providerPid !== void 0) {
22874
+ requireStartedProvider(providerPid, command);
22875
+ return;
22876
+ }
22877
+ if (status.error) {
22878
+ throw new CoreFault(
22879
+ "spawn_failed",
22880
+ `Could not start ${command} (${status.error.message})`,
22881
+ {
22882
+ cause: status.error
22883
+ }
22884
+ );
22885
+ }
22886
+ if (child.exitCode !== null || child.signalCode !== null) {
22887
+ throw new CoreFault("spawn_failed", `Could not start ${command} (Windows helper exited)`);
22888
+ }
22889
+ await systemClock2.sleep(25);
22890
+ }
22891
+ child.kill("SIGKILL");
22892
+ throw new CoreFault("spawn_failed", `Could not start ${command} (Windows helper timed out)`);
22893
+ } finally {
22894
+ statuses.delete(child);
22895
+ await (0, import_promises10.rm)(status.directory, { recursive: true, force: true });
22896
+ }
22849
22897
  }
22850
22898
  function spawnCli(options) {
22851
22899
  const platform3 = options.platform ?? process.platform;
@@ -22860,6 +22908,7 @@ function spawnCli(options) {
22860
22908
  });
22861
22909
  }
22862
22910
  function waitForSpawn(child, command) {
22911
+ if (isWindowsJob(child)) return waitForWindowsJob(child, command);
22863
22912
  if (child.pid !== void 0) return Promise.resolve();
22864
22913
  return new Promise((resolve10, reject) => {
22865
22914
  const onSpawn = () => {
@@ -22877,9 +22926,9 @@ function waitForSpawn(child, command) {
22877
22926
  child.once("error", onError);
22878
22927
  });
22879
22928
  }
22880
- var import_child_process, import_fs, import_path, import_child_process2, import_promises9, import_child_process3, import_child_process4, import_child_process5, import_child_process6, import_path2, SHIM_MAX_BYTES, CMD_MAX_COMMAND_LINE, MAX_COMMAND_LINE, DEFAULT_PATHEXT, nodeWindowsFiles, NODE_SHIM_ENTRY, CMD_META, NEVER_STARTED, HIDDEN_FLAG_PROBE_VALUE, NEWLINE, CARRIAGE_RETURN, EMPTY, MAX_LINE_BYTES, LineSplitter, PS_LINE, POLL_MS, DEFAULT_GRACE_MS, DEFAULT_KILL_WAIT_MS, DEFAULT_TASKKILL_TIMEOUT_MS, JOB_COMMAND_VARIABLE, BRIDGE_SOURCE;
22881
- var init_chunk_VZIZDY3T = __esm({
22882
- "../agent-core/dist/chunk-VZIZDY3T.js"() {
22929
+ var import_child_process, import_fs, import_path, import_child_process2, import_promises9, import_child_process3, import_child_process4, import_child_process5, import_child_process6, import_crypto, import_fs2, import_promises10, import_os, import_path2, SHIM_MAX_BYTES, CMD_MAX_COMMAND_LINE, MAX_COMMAND_LINE, DEFAULT_PATHEXT, nodeWindowsFiles, NODE_SHIM_ENTRY, CMD_META, NEVER_STARTED, HIDDEN_FLAG_PROBE_VALUE, NEWLINE, CARRIAGE_RETURN, EMPTY, MAX_LINE_BYTES, LineSplitter, PS_LINE, POLL_MS, DEFAULT_GRACE_MS, DEFAULT_KILL_WAIT_MS, DEFAULT_TASKKILL_TIMEOUT_MS, statuses, START_TIMEOUT_MS;
22930
+ var init_chunk_NDAB5G24 = __esm({
22931
+ "../agent-core/dist/chunk-NDAB5G24.js"() {
22883
22932
  "use strict";
22884
22933
  init_chunk_YXWJW7I5();
22885
22934
  import_child_process = require("child_process");
@@ -22891,6 +22940,10 @@ var init_chunk_VZIZDY3T = __esm({
22891
22940
  import_child_process4 = require("child_process");
22892
22941
  import_child_process5 = require("child_process");
22893
22942
  import_child_process6 = require("child_process");
22943
+ import_crypto = require("crypto");
22944
+ import_fs2 = require("fs");
22945
+ import_promises10 = require("fs/promises");
22946
+ import_os = require("os");
22894
22947
  import_path2 = require("path");
22895
22948
  SHIM_MAX_BYTES = 64 * 1024;
22896
22949
  CMD_MAX_COMMAND_LINE = 8191;
@@ -22962,87 +23015,8 @@ var init_chunk_VZIZDY3T = __esm({
22962
23015
  DEFAULT_GRACE_MS = 3e3;
22963
23016
  DEFAULT_KILL_WAIT_MS = 2e3;
22964
23017
  DEFAULT_TASKKILL_TIMEOUT_MS = 5e3;
22965
- JOB_COMMAND_VARIABLE = "ALAN_PROVIDER_JOB_COMMAND";
22966
- BRIDGE_SOURCE = `
22967
- using System;
22968
- using System.Text;
22969
- using System.Runtime.InteropServices;
22970
- using System.ComponentModel;
22971
- public static class AlanProviderJob {
22972
- [StructLayout(LayoutKind.Sequential)] struct IO { public ulong a,b,c,d,e,f; }
22973
- [StructLayout(LayoutKind.Sequential)] struct Limits {
22974
- public long perProcess, perJob; public uint flags;
22975
- public UIntPtr minWorkingSet, maxWorkingSet; public uint activeProcesses;
22976
- public UIntPtr affinity; public uint priority, scheduling;
22977
- }
22978
- [StructLayout(LayoutKind.Sequential)] struct ExtendedLimits {
22979
- public Limits basic; public IO io;
22980
- public UIntPtr processMemory, jobMemory, peakProcessMemory, peakJobMemory;
22981
- }
22982
- [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] struct Startup {
22983
- public uint cb; public string reserved, desktop, title;
22984
- public uint x,y,xSize,ySize,xChars,yChars,fill,flags;
22985
- public ushort show,reservedSize; public IntPtr reserved2, stdin, stdout, stderr;
22986
- }
22987
- [StructLayout(LayoutKind.Sequential)] struct ProcessInfo {
22988
- public IntPtr process, thread; public uint pid, tid;
22989
- }
22990
- [DllImport("kernel32.dll", SetLastError=true)] static extern IntPtr CreateJobObject(IntPtr security, string name);
22991
- [DllImport("kernel32.dll", SetLastError=true)] static extern bool SetInformationJobObject(IntPtr job, int kind, ref ExtendedLimits limits, uint size);
22992
- [DllImport("kernel32.dll", SetLastError=true)] static extern bool AssignProcessToJobObject(IntPtr job, IntPtr process);
22993
- [DllImport("kernel32.dll", SetLastError=true)] static extern bool TerminateJobObject(IntPtr job, uint code);
22994
- [DllImport("kernel32.dll", SetLastError=true)] static extern bool TerminateProcess(IntPtr process, uint code);
22995
- [DllImport("kernel32.dll", CharSet=CharSet.Unicode, SetLastError=true)] static extern bool CreateProcess(string app, StringBuilder command, IntPtr ps, IntPtr ts, bool inherit, uint flags, IntPtr env, string cwd, ref Startup si, out ProcessInfo pi);
22996
- [DllImport("kernel32.dll")] static extern IntPtr GetStdHandle(int id);
22997
- [DllImport("kernel32.dll")] static extern IntPtr GetCurrentProcess();
22998
- [DllImport("kernel32.dll", SetLastError=true)] static extern bool DuplicateHandle(IntPtr sourceProcess, IntPtr source, IntPtr targetProcess, out IntPtr target, uint access, bool inherit, uint options);
22999
- [DllImport("kernel32.dll", SetLastError=true)] static extern uint ResumeThread(IntPtr thread);
23000
- [DllImport("kernel32.dll", SetLastError=true)] static extern IntPtr OpenProcess(uint access, bool inherit, int pid);
23001
- [DllImport("kernel32.dll", SetLastError=true)] static extern uint WaitForMultipleObjects(uint count, IntPtr[] handles, bool all, uint ms);
23002
- [DllImport("kernel32.dll")] static extern bool GetExitCodeProcess(IntPtr process, out uint code);
23003
- [DllImport("kernel32.dll")] static extern bool CloseHandle(IntPtr handle);
23004
- static void Check(bool ok) { if (!ok) throw new Win32Exception(Marshal.GetLastWin32Error()); }
23005
- static IntPtr CopyStd(int id) {
23006
- IntPtr result; var self = GetCurrentProcess();
23007
- Check(DuplicateHandle(self, GetStdHandle(id), self, out result, 0, true, 2));
23008
- return result;
23009
- }
23010
- public static int Run(string command, int ownerPid) {
23011
- Environment.SetEnvironmentVariable("${JOB_COMMAND_VARIABLE}", null);
23012
- IntPtr owner = OpenProcess(0x100000, false, ownerPid);
23013
- if (owner == IntPtr.Zero) throw new Win32Exception(Marshal.GetLastWin32Error());
23014
- IntPtr job = CreateJobObject(IntPtr.Zero, null);
23015
- if (job == IntPtr.Zero) { CloseHandle(owner); throw new Win32Exception(Marshal.GetLastWin32Error()); }
23016
- ProcessInfo pi = new ProcessInfo(); Startup si = new Startup();
23017
- try {
23018
- var limits = new ExtendedLimits(); limits.basic.flags = 0x2000;
23019
- Check(SetInformationJobObject(job, 9, ref limits, (uint)Marshal.SizeOf(limits)));
23020
- si.cb = (uint)Marshal.SizeOf(si); si.flags = 0x100;
23021
- si.stdin = CopyStd(-10); si.stdout = CopyStd(-11); si.stderr = CopyStd(-12);
23022
- Check(CreateProcess(null, new StringBuilder(command), IntPtr.Zero, IntPtr.Zero, true, 0x08000004, IntPtr.Zero, null, ref si, out pi));
23023
- if (!AssignProcessToJobObject(job, pi.process)) {
23024
- int error = Marshal.GetLastWin32Error(); TerminateProcess(pi.process, 1);
23025
- throw new Win32Exception(error);
23026
- }
23027
- if (ResumeThread(pi.thread) == 0xffffffff) throw new Win32Exception(Marshal.GetLastWin32Error());
23028
- uint wait = WaitForMultipleObjects(2, new IntPtr[] { pi.process, owner }, false, 0xffffffff);
23029
- if (wait == 1) return 1;
23030
- if (wait != 0) throw new Win32Exception(Marshal.GetLastWin32Error());
23031
- uint code; Check(GetExitCodeProcess(pi.process, out code));
23032
- Check(TerminateJobObject(job, code));
23033
- return unchecked((int)code);
23034
- } finally {
23035
- CloseHandle(job);
23036
- CloseHandle(owner);
23037
- if (pi.thread != IntPtr.Zero) CloseHandle(pi.thread);
23038
- if (pi.process != IntPtr.Zero) CloseHandle(pi.process);
23039
- if (si.stdin != IntPtr.Zero) CloseHandle(si.stdin);
23040
- if (si.stdout != IntPtr.Zero) CloseHandle(si.stdout);
23041
- if (si.stderr != IntPtr.Zero) CloseHandle(si.stderr);
23042
- }
23043
- }
23044
- }
23045
- `;
23018
+ statuses = /* @__PURE__ */ new WeakMap();
23019
+ START_TIMEOUT_MS = 1e4;
23046
23020
  }
23047
23021
  });
23048
23022
 
@@ -24329,13 +24303,13 @@ function readTranscriptTurns(transcript, chunk, baseOffset, skipped = []) {
24329
24303
  });
24330
24304
  return { turns, consumedBytes: consumedEnd - baseOffset };
24331
24305
  }
24332
- var import_fs2, NEWLINE2, TranscriptCursor, TranscriptLineLookup, CONTENT_UPDATES;
24306
+ var import_fs3, NEWLINE2, TranscriptCursor, TranscriptLineLookup, CONTENT_UPDATES;
24333
24307
  var init_chunk_LR52JUGL = __esm({
24334
24308
  "../agent-core/dist/chunk-LR52JUGL.js"() {
24335
24309
  "use strict";
24336
24310
  init_chunk_OUQ7HMD3();
24337
24311
  init_chunk_YXWJW7I5();
24338
- import_fs2 = require("fs");
24312
+ import_fs3 = require("fs");
24339
24313
  NEWLINE2 = 10;
24340
24314
  TranscriptCursor = class {
24341
24315
  #path;
@@ -24353,7 +24327,7 @@ var init_chunk_LR52JUGL = __esm({
24353
24327
  try {
24354
24328
  this.#offset = Math.max(
24355
24329
  this.#offset,
24356
- (0, import_fs2.statSync)(this.#path, { throwIfNoEntry: false })?.size ?? 0
24330
+ (0, import_fs3.statSync)(this.#path, { throwIfNoEntry: false })?.size ?? 0
24357
24331
  );
24358
24332
  } catch {
24359
24333
  }
@@ -24375,15 +24349,15 @@ var init_chunk_LR52JUGL = __esm({
24375
24349
  /** Runs on the CLI's stdout path, so an unreadable file reads as no new lines. */
24376
24350
  #unread() {
24377
24351
  try {
24378
- const size = (0, import_fs2.statSync)(this.#path, { throwIfNoEntry: false })?.size ?? 0;
24352
+ const size = (0, import_fs3.statSync)(this.#path, { throwIfNoEntry: false })?.size ?? 0;
24379
24353
  if (size <= this.#offset) return void 0;
24380
24354
  const buffer = Buffer.alloc(size - this.#offset);
24381
- const fd = (0, import_fs2.openSync)(this.#path, "r");
24355
+ const fd = (0, import_fs3.openSync)(this.#path, "r");
24382
24356
  try {
24383
- const read = (0, import_fs2.readSync)(fd, buffer, 0, buffer.length, this.#offset);
24357
+ const read = (0, import_fs3.readSync)(fd, buffer, 0, buffer.length, this.#offset);
24384
24358
  return buffer.subarray(0, read);
24385
24359
  } finally {
24386
- (0, import_fs2.closeSync)(fd);
24360
+ (0, import_fs3.closeSync)(fd);
24387
24361
  }
24388
24362
  } catch {
24389
24363
  return void 0;
@@ -24581,7 +24555,7 @@ function createCliProblem(classified, options) {
24581
24555
  return createAlanProblem({
24582
24556
  domain: "agent_cli",
24583
24557
  code: problemCodeFor(classified, options),
24584
- id: options.id ?? (0, import_crypto.randomUUID)(),
24558
+ id: options.id ?? (0, import_crypto2.randomUUID)(),
24585
24559
  title: terminal2 ? "Agent CLI run failed" : "Agent CLI problem observed",
24586
24560
  detail: classified.message,
24587
24561
  occurredAt: options.occurredAt,
@@ -24602,12 +24576,12 @@ function createCliProblem(classified, options) {
24602
24576
  ...classified.resetsAt ? { resetsAt: classified.resetsAt } : {}
24603
24577
  });
24604
24578
  }
24605
- var import_crypto, ERROR_SPECS, AGENT_ERROR_KINDS, STATUS_PREFIX, TEXT_RULES, CODEX_TIMEOUT_MESSAGE, CODEX_EXPIRED_MESSAGE, EPOCH_RESET, WORDED_RESET, COMMAND_NOT_FOUND, CODE_RULES, TEXT_REFINES, CLI_PROBLEM_CODE_BY_ERROR_KIND, KEY_REJECTION_KINDS;
24579
+ var import_crypto2, ERROR_SPECS, AGENT_ERROR_KINDS, STATUS_PREFIX, TEXT_RULES, CODEX_TIMEOUT_MESSAGE, CODEX_EXPIRED_MESSAGE, EPOCH_RESET, WORDED_RESET, COMMAND_NOT_FOUND, CODE_RULES, TEXT_REFINES, CLI_PROBLEM_CODE_BY_ERROR_KIND, KEY_REJECTION_KINDS;
24606
24580
  var init_chunk_R32NAS3B = __esm({
24607
24581
  "../agent-core/dist/chunk-R32NAS3B.js"() {
24608
24582
  "use strict";
24609
24583
  init_chunk_YXWJW7I5();
24610
- import_crypto = require("crypto");
24584
+ import_crypto2 = require("crypto");
24611
24585
  init_agent2();
24612
24586
  ERROR_SPECS = {
24613
24587
  model_mismatch: {
@@ -24842,7 +24816,7 @@ var init_chunk_R32NAS3B = __esm({
24842
24816
  }
24843
24817
  });
24844
24818
 
24845
- // ../agent-core/dist/chunk-2KE6BVIX.js
24819
+ // ../agent-core/dist/chunk-BVWCFGFG.js
24846
24820
  function collectStrings(value2, out) {
24847
24821
  if (typeof value2 === "string") out.push(value2);
24848
24822
  else if (Array.isArray(value2)) for (const item of value2) collectStrings(item, out);
@@ -24930,13 +24904,13 @@ function readMediaFiles(candidates2, cwd, mimeByExt, maxBytes) {
24930
24904
  const files = [];
24931
24905
  for (const candidate of candidates2) {
24932
24906
  const path4 = normalizePath(candidate, cwd);
24933
- if (!path4 || seen.has(path4) || !(0, import_fs3.existsSync)(path4)) continue;
24907
+ if (!path4 || seen.has(path4) || !(0, import_fs4.existsSync)(path4)) continue;
24934
24908
  seen.add(path4);
24935
24909
  const mimeType = mimeByExt[(0, import_path3.extname)(path4).toLowerCase()];
24936
24910
  if (!mimeType) continue;
24937
- const stat19 = (0, import_fs3.statSync)(path4);
24911
+ const stat19 = (0, import_fs4.statSync)(path4);
24938
24912
  if (!stat19.isFile() || stat19.size <= 0 || stat19.size > maxBytes) continue;
24939
- files.push({ path: path4, mimeType, buffer: (0, import_fs3.readFileSync)(path4) });
24913
+ files.push({ path: path4, mimeType, buffer: (0, import_fs4.readFileSync)(path4) });
24940
24914
  }
24941
24915
  return files;
24942
24916
  }
@@ -25211,16 +25185,16 @@ function silentStartError(name, timeoutMs) {
25211
25185
  message: `${name} printed nothing for ${seconds}s after it started and was stopped. Send your message again.`
25212
25186
  };
25213
25187
  }
25214
- var import_crypto2, import_fs3, import_path3, IMAGE_MIME_BY_EXT, VIDEO_MIME_BY_EXT, IMAGE_EXTENSIONS, VIDEO_EXTENSIONS, MAX_IMAGE_BYTES, MAX_VIDEO_BYTES, AGENT_BROWSER_MENTION, LocalMediaReader, SessionOpenRefusal, JsonRpcError, ACP_PROTOCOL_VERSION, ACP_ERROR, STDERR_TAIL_LINES, RESULT_EXIT_GRACE_MS, PerTurnSession;
25215
- var init_chunk_2KE6BVIX = __esm({
25216
- "../agent-core/dist/chunk-2KE6BVIX.js"() {
25188
+ var import_crypto3, import_fs4, import_path3, IMAGE_MIME_BY_EXT, VIDEO_MIME_BY_EXT, IMAGE_EXTENSIONS, VIDEO_EXTENSIONS, MAX_IMAGE_BYTES, MAX_VIDEO_BYTES, AGENT_BROWSER_MENTION, LocalMediaReader, SessionOpenRefusal, JsonRpcError, ACP_PROTOCOL_VERSION, ACP_ERROR, STDERR_TAIL_LINES, RESULT_EXIT_GRACE_MS, PerTurnSession;
25189
+ var init_chunk_BVWCFGFG = __esm({
25190
+ "../agent-core/dist/chunk-BVWCFGFG.js"() {
25217
25191
  "use strict";
25218
25192
  init_chunk_OUQ7HMD3();
25219
25193
  init_chunk_R32NAS3B();
25220
- init_chunk_VZIZDY3T();
25194
+ init_chunk_NDAB5G24();
25221
25195
  init_chunk_YXWJW7I5();
25222
- import_crypto2 = require("crypto");
25223
- import_fs3 = require("fs");
25196
+ import_crypto3 = require("crypto");
25197
+ import_fs4 = require("fs");
25224
25198
  import_path3 = require("path");
25225
25199
  init_agent2();
25226
25200
  init_acp();
@@ -25281,13 +25255,13 @@ var init_chunk_2KE6BVIX = __esm({
25281
25255
  }
25282
25256
  #payloadFields(file2, toolId) {
25283
25257
  return {
25284
- id: (0, import_crypto2.randomUUID)(),
25258
+ id: (0, import_crypto3.randomUUID)(),
25285
25259
  filename: (0, import_path3.basename)(file2.path),
25286
25260
  mimeType: file2.mimeType,
25287
25261
  size: file2.buffer.length,
25288
25262
  data: file2.buffer.toString("base64"),
25289
25263
  sourcePath: file2.path,
25290
- sourceHash: (0, import_crypto2.createHash)("sha256").update(file2.buffer).digest("hex"),
25264
+ sourceHash: (0, import_crypto3.createHash)("sha256").update(file2.buffer).digest("hex"),
25291
25265
  toolId,
25292
25266
  ts: this.#clock.now()
25293
25267
  };
@@ -25571,7 +25545,7 @@ function selectExternalMcpServers(spec) {
25571
25545
  return selected;
25572
25546
  }
25573
25547
  function headerEnvName(server, header) {
25574
- const fingerprint = (0, import_crypto3.createHash)("sha256").update(`${server}\0${header}`).digest("hex").slice(0, 12);
25548
+ const fingerprint = (0, import_crypto4.createHash)("sha256").update(`${server}\0${header}`).digest("hex").slice(0, 12);
25575
25549
  return `ALAN_MCP_HEADER_${fingerprint.toUpperCase()}`;
25576
25550
  }
25577
25551
  function deliverRemote(name, server, env) {
@@ -25635,7 +25609,7 @@ function managedMcpHeaders(identity) {
25635
25609
  }
25636
25610
  function credentialDigest(authorization) {
25637
25611
  if (authorization === void 0) return void 0;
25638
- return (0, import_crypto4.createHash)("sha256").update(authorization).digest("hex").slice(0, 16);
25612
+ return (0, import_crypto5.createHash)("sha256").update(authorization).digest("hex").slice(0, 16);
25639
25613
  }
25640
25614
  function canonicalizeManagedMcpServerName(serverName) {
25641
25615
  return RUN_SCOPED_SERVER.test(serverName) ? MANAGED_MCP_SERVER_NAME : serverName;
@@ -25647,30 +25621,30 @@ function canonicalizeManagedMcpToolName(toolName2) {
25647
25621
  return flattened ? `mcp__${MANAGED_MCP_SERVER_NAME}__${flattened[1]}` : toolName2;
25648
25622
  }
25649
25623
  async function writeSecretFile(name, contents) {
25650
- const dir = await (0, import_promises28.mkdtemp)((0, import_path4.join)((0, import_os.tmpdir)(), "alan-mcp-"));
25624
+ const dir = await (0, import_promises29.mkdtemp)((0, import_path4.join)((0, import_os2.tmpdir)(), "alan-mcp-"));
25651
25625
  const path4 = (0, import_path4.join)(dir, name);
25652
25626
  const remove = async () => {
25653
- await (0, import_promises28.rm)(dir, { recursive: true, force: true });
25627
+ await (0, import_promises29.rm)(dir, { recursive: true, force: true });
25654
25628
  };
25655
25629
  try {
25656
- await (0, import_promises28.writeFile)(path4, contents, { mode: 384, flag: "wx" });
25630
+ await (0, import_promises29.writeFile)(path4, contents, { mode: 384, flag: "wx" });
25657
25631
  } catch (error61) {
25658
25632
  await remove();
25659
25633
  throw error61;
25660
25634
  }
25661
25635
  return { path: path4, remove, [Symbol.asyncDispose]: remove };
25662
25636
  }
25663
- var import_crypto3, import_crypto4, import_promises28, import_os, import_path4, MANAGED_MCP_SERVER_NAME, RUN_SCOPED_SERVER, NAMESPACED_RUN_TOOL, FLATTENED_RUN_TOOL;
25637
+ var import_crypto4, import_crypto5, import_promises29, import_os2, import_path4, MANAGED_MCP_SERVER_NAME, RUN_SCOPED_SERVER, NAMESPACED_RUN_TOOL, FLATTENED_RUN_TOOL;
25664
25638
  var init_chunk_J2KTV5FP = __esm({
25665
25639
  "../agent-core/dist/chunk-J2KTV5FP.js"() {
25666
25640
  "use strict";
25667
- import_crypto3 = require("crypto");
25668
- init_agent2();
25669
25641
  import_crypto4 = require("crypto");
25670
25642
  init_agent2();
25643
+ import_crypto5 = require("crypto");
25644
+ init_agent2();
25671
25645
  init_runtime_v2();
25672
- import_promises28 = require("fs/promises");
25673
- import_os = require("os");
25646
+ import_promises29 = require("fs/promises");
25647
+ import_os2 = require("os");
25674
25648
  import_path4 = require("path");
25675
25649
  MANAGED_MCP_SERVER_NAME = "alan";
25676
25650
  RUN_SCOPED_SERVER = /^alan-run-[a-f0-9]{16}$/;
@@ -25679,7 +25653,7 @@ var init_chunk_J2KTV5FP = __esm({
25679
25653
  }
25680
25654
  });
25681
25655
 
25682
- // ../agent-core/dist/chunk-NADPTUUJ.js
25656
+ // ../agent-core/dist/chunk-GXBS4QWA.js
25683
25657
  function truncate(value2, limit) {
25684
25658
  const normalized2 = Array.from(value2, (character) => {
25685
25659
  const code = character.charCodeAt(0);
@@ -25881,7 +25855,6 @@ function artifactIdsSection(owner) {
25881
25855
  const ids = artifactIds(owner);
25882
25856
  if (ids.length === 0) return void 0;
25883
25857
  const tools = ["create_plan", "create_document_artifact", "create_test_report"];
25884
- if (owner.taskId || owner.isWorkflowSession) tools.push("upsert_prototype_version");
25885
25858
  return [
25886
25859
  `When creating artifacts using MCP tools (${tools.join(", ")}), always pass these IDs:`,
25887
25860
  ...ids
@@ -25893,26 +25866,6 @@ function standaloneChatSection(owner) {
25893
25866
  }
25894
25867
  return "This is a standalone chat. For create_plan, create_document_artifact, and create_test_report, omit taskId and workflowId; conversationId is the artifact owner. Do not use create_document unless the user explicitly asks for a standalone team Document.";
25895
25868
  }
25896
- function prototypeScope(owner) {
25897
- if (owner.workflowId) {
25898
- return {
25899
- ids: "teamId, workflowId, workflowExecutionId, conversationId",
25900
- lookup: "list_prototypes (with workflowId) or get_prototype"
25901
- };
25902
- }
25903
- return owner.taskId ? { ids: "teamId, taskId, conversationId", lookup: "list_prototypes or get_prototype" } : void 0;
25904
- }
25905
- function prototypeSection(owner) {
25906
- if (!owner.conversationId || !owner.teamId) return void 0;
25907
- const scope = prototypeScope(owner);
25908
- if (!scope) return void 0;
25909
- return [
25910
- "## Prototype Artifacts",
25911
- "When the user asks to create, build, modify, or iterate on a prototype, do not create local prototype files such as prototype/index.html.",
25912
- `Instead, generate a Vite React TypeScript source snapshot and call the Alan MCP tool upsert_prototype_version with ${scope.ids}, title, sourceSnapshot, and packageJson.`,
25913
- `For follow-up changes to the same prototype, call ${scope.lookup} if needed, then call upsert_prototype_version again with the existing prototypeId and parentVersionId.`
25914
- ].join("\n");
25915
- }
25916
25869
  function contextSections(spec) {
25917
25870
  const owner = ownershipOf(spec);
25918
25871
  const context = spec.promptContext;
@@ -25921,8 +25874,7 @@ function contextSections(spec) {
25921
25874
  taskContextSection(context?.taskMeta),
25922
25875
  pullRequestSection(context?.prMeta),
25923
25876
  artifactIdsSection(owner),
25924
- standaloneChatSection(owner),
25925
- prototypeSection(owner)
25877
+ standaloneChatSection(owner)
25926
25878
  ].filter((section) => section !== void 0);
25927
25879
  }
25928
25880
  function taskLifecycleSection(spec) {
@@ -26028,8 +25980,8 @@ ${body}` : body;
26028
25980
  return spec.mode === "plan" ? planModePrefix(prefixed) : prefixed;
26029
25981
  }
26030
25982
  var MAX_PARSED_ATTACHMENTS, MAX_PARSED_ATTACHMENT_CHARS, MAX_METADATA_CHARS, UNAVAILABLE, READ_ONLY_MODES, AGENT_MODES;
26031
- var init_chunk_NADPTUUJ = __esm({
26032
- "../agent-core/dist/chunk-NADPTUUJ.js"() {
25983
+ var init_chunk_GXBS4QWA = __esm({
25984
+ "../agent-core/dist/chunk-GXBS4QWA.js"() {
26033
25985
  "use strict";
26034
25986
  init_agent2();
26035
25987
  MAX_PARSED_ATTACHMENTS = 3;
@@ -26351,14 +26303,8 @@ function hookResponse(event) {
26351
26303
  if (outcome2 === "success" && exitCode === 0) return [];
26352
26304
  const name = asString(event.hook_name) || "hook";
26353
26305
  const detail = asString(event.stderr) || asString(event.output) || asString(event.stdout);
26354
- return [
26355
- noticeUpdate(
26356
- "warning",
26357
- "hook_failed",
26358
- `Hook ${name} failed${exitCode ? ` (exit ${exitCode})` : ""}${outcome2 ? `: ${outcome2}` : ""}.`,
26359
- detail || void 0
26360
- )
26361
- ];
26306
+ const summary = `Hook ${name} failed${exitCode ? ` (exit ${exitCode})` : ""}${outcome2 ? `: ${outcome2}` : ""}.`;
26307
+ return [logUpdate("claude_cli/hook", detail ? `${summary} ${detail}` : summary)];
26362
26308
  }
26363
26309
  function apiRetryNotice(event) {
26364
26310
  const attempt2 = asFiniteNumber(event.attempt) ?? 0;
@@ -27013,7 +26959,7 @@ function encodeProjectDir(cwd) {
27013
26959
  }
27014
26960
  function realCwd(cwd) {
27015
26961
  try {
27016
- return (0, import_fs4.realpathSync)(cwd);
26962
+ return (0, import_fs5.realpathSync)(cwd);
27017
26963
  } catch {
27018
26964
  return cwd;
27019
26965
  }
@@ -27027,12 +26973,12 @@ function claudeSessionLogExists(query) {
27027
26973
  encodeProjectDir(cwd),
27028
26974
  `${query.sessionId}.jsonl`
27029
26975
  );
27030
- if ((0, import_fs4.existsSync)(log)) return true;
26976
+ if ((0, import_fs5.existsSync)(log)) return true;
27031
26977
  }
27032
26978
  return false;
27033
26979
  }
27034
26980
  function envDigest(env) {
27035
- const hash2 = (0, import_crypto6.createHash)("sha256");
26981
+ const hash2 = (0, import_crypto7.createHash)("sha256");
27036
26982
  for (const key of Object.keys(env).sort()) hash2.update(`${key}\0${env[key]}\0`);
27037
26983
  return hash2.digest("hex");
27038
26984
  }
@@ -27095,7 +27041,7 @@ async function claudeTurnInput(run2, context) {
27095
27041
  const encoded = await Promise.all(
27096
27042
  images.map(async (image) => ({
27097
27043
  mimeType: image.mimeType,
27098
- data: (await (0, import_promises29.readFile)(image.path)).toString("base64")
27044
+ data: (await (0, import_promises30.readFile)(image.path)).toString("base64")
27099
27045
  }))
27100
27046
  );
27101
27047
  return { turnId: run2.runId, text: text2, ...encoded.length ? { images: encoded } : {} };
@@ -27294,30 +27240,30 @@ function claudeTurnClosingUpdates(records, state) {
27294
27240
  function readClaudeTranscriptTurns(chunk, baseOffset, skipped) {
27295
27241
  return readTranscriptTurns(claudeTranscriptFile, chunk, baseOffset, skipped);
27296
27242
  }
27297
- var import_crypto5, import_fs4, import_path5, import_crypto6, import_promises29, EDIT_TOOLS, ThoughtBlocks, UNDERSTOOD_SYSTEM_SUBTYPES, RATE_LIMIT_WARN_AT, CLAUDE_GRAMMAR_NAME, SUBAGENT_TOOL_NAMES, PLAN_ENTRY_STATUSES, controlResponseSchema, STOPPED_STATUSES, TaskRecords, TERMINAL_BACKGROUND_STATUSES, NON_TERMINAL_BACKGROUND_STATUSES, ASYNC_LAUNCH_ACK, BackgroundTasks, FAILED_STATUSES, STOPPED_BY_USER_TEXT, ClaudeTurn, STDERR_TAIL_LINES2, MAX_EARLY_LINES, UNSUPPORTED_STOP, OUTPUT_CLOSED_REASON, ClaudeSession, DEFAULTS, READ_ONLY_DISALLOWED_TOOLS, DEFAULT_MCP_TIMEOUT_MS, SYNTHETIC_MODEL, INTERRUPT_MARKER, NON_PROMPT_PREFIXES, PRELUDE_TYPES, claudeTranscriptFile;
27243
+ var import_crypto6, import_fs5, import_path5, import_crypto7, import_promises30, EDIT_TOOLS, ThoughtBlocks, UNDERSTOOD_SYSTEM_SUBTYPES, RATE_LIMIT_WARN_AT, CLAUDE_GRAMMAR_NAME, SUBAGENT_TOOL_NAMES, PLAN_ENTRY_STATUSES, controlResponseSchema, STOPPED_STATUSES, TaskRecords, TERMINAL_BACKGROUND_STATUSES, NON_TERMINAL_BACKGROUND_STATUSES, ASYNC_LAUNCH_ACK, BackgroundTasks, FAILED_STATUSES, STOPPED_BY_USER_TEXT, ClaudeTurn, STDERR_TAIL_LINES2, MAX_EARLY_LINES, UNSUPPORTED_STOP, OUTPUT_CLOSED_REASON, ClaudeSession, DEFAULTS, READ_ONLY_DISALLOWED_TOOLS, DEFAULT_MCP_TIMEOUT_MS, SYNTHETIC_MODEL, INTERRUPT_MARKER, NON_PROMPT_PREFIXES, PRELUDE_TYPES, claudeTranscriptFile;
27298
27244
  var init_claude = __esm({
27299
27245
  "../agent-core/dist/providers/claude.js"() {
27300
27246
  "use strict";
27301
27247
  init_chunk_LR52JUGL();
27302
- init_chunk_2KE6BVIX();
27248
+ init_chunk_BVWCFGFG();
27303
27249
  init_chunk_OUQ7HMD3();
27304
27250
  init_chunk_R32NAS3B();
27305
27251
  init_chunk_J2KTV5FP();
27306
- init_chunk_VZIZDY3T();
27307
- init_chunk_NADPTUUJ();
27252
+ init_chunk_NDAB5G24();
27253
+ init_chunk_GXBS4QWA();
27308
27254
  init_chunk_YXWJW7I5();
27309
27255
  init_effort();
27310
- import_crypto5 = require("crypto");
27256
+ import_crypto6 = require("crypto");
27311
27257
  init_constants();
27312
27258
  init_zod();
27313
27259
  init_acp();
27314
27260
  init_acp();
27315
27261
  init_constants();
27316
27262
  init_agent2();
27317
- import_fs4 = require("fs");
27263
+ import_fs5 = require("fs");
27318
27264
  import_path5 = require("path");
27319
- import_crypto6 = require("crypto");
27320
- import_promises29 = require("fs/promises");
27265
+ import_crypto7 = require("crypto");
27266
+ import_promises30 = require("fs/promises");
27321
27267
  init_agent2();
27322
27268
  EDIT_TOOLS = /* @__PURE__ */ new Set([
27323
27269
  "Edit",
@@ -27959,7 +27905,7 @@ var init_claude = __esm({
27959
27905
  sessionId: this.#lastTurn.grammar.sessionId,
27960
27906
  taskRecords: this.#taskRecords
27961
27907
  });
27962
- const messageId = this.#replaysUserMessages ? (0, import_crypto5.randomUUID)() : void 0;
27908
+ const messageId = this.#replaysUserMessages ? (0, import_crypto6.randomUUID)() : void 0;
27963
27909
  const active = this.#startTurn(input2.turnId, turn, messageId);
27964
27910
  this.#host.writer.write(claudeUserMessage(input2, messageId)).catch((error61) => {
27965
27911
  this.#options.log.warn("claude.stdin_write_failed", { turnId: input2.turnId, error: error61 });
@@ -28377,7 +28323,7 @@ function codexHomeOf(env) {
28377
28323
  }
28378
28324
  function namesNewestFirst(dir, isDir) {
28379
28325
  try {
28380
- return (0, import_fs5.readdirSync)(dir, { withFileTypes: true }).filter((entry) => isDir ? entry.isDirectory() : entry.isFile()).map((entry) => entry.name).sort().reverse();
28326
+ return (0, import_fs6.readdirSync)(dir, { withFileTypes: true }).filter((entry) => isDir ? entry.isDirectory() : entry.isFile()).map((entry) => entry.name).sort().reverse();
28381
28327
  } catch {
28382
28328
  return [];
28383
28329
  }
@@ -28557,7 +28503,7 @@ function codexGeneratedImage(payload, ts) {
28557
28503
  const declared = asString(payload.mimeType) || asString(payload.mime_type);
28558
28504
  const mimeType = declared.startsWith("image/") ? declared : inferImageMimeType(buffer);
28559
28505
  if (!mimeType) return null;
28560
- const sourceHash = (0, import_crypto7.createHash)("sha256").update(buffer).digest("hex");
28506
+ const sourceHash = (0, import_crypto8.createHash)("sha256").update(buffer).digest("hex");
28561
28507
  const toolId = asString(payload.call_id);
28562
28508
  const id = asString(payload.id) || toolId || sourceHash;
28563
28509
  const sourcePath = asString(payload.sourcePath);
@@ -29038,6 +28984,10 @@ function isAuthStatus(error61) {
29038
28984
  const status = httpStatusOf(info);
29039
28985
  return info === "unauthorized" || status === 401 || status === 403;
29040
28986
  }
28987
+ function cliLog(method, params) {
28988
+ const text2 = [asString(params.message) || asString(params.summary), asString(params.details)].filter((part) => part.length > 0).join(" ");
28989
+ return logUpdate(`codex/${method}`, text2);
28990
+ }
29041
28991
  function pendingAnswer(pending, answer) {
29042
28992
  switch (pending.kind) {
29043
28993
  case "approval":
@@ -29287,7 +29237,6 @@ function promptFor(spec, turn, resumeId) {
29287
29237
  return [system?.trim(), turn.text.trim()].filter(Boolean).join("\n\n");
29288
29238
  }
29289
29239
  function provider(spec, clock) {
29290
- const memory = { shownWarnings: /* @__PURE__ */ new Set() };
29291
29240
  return {
29292
29241
  name: "codex-exec",
29293
29242
  launch: async (turn, resumeId) => ({
@@ -29304,7 +29253,7 @@ function provider(spec, clock) {
29304
29253
  }),
29305
29254
  stdin: promptFor(spec, turn, resumeId)
29306
29255
  }),
29307
- reader: (_turn, resumeId) => new CodexExecTurn(memory, resumeId, { codexHome: codexHomeOf(spec.env), clock })
29256
+ reader: (_turn, resumeId) => new CodexExecTurn(resumeId, { codexHome: codexHomeOf(spec.env), clock })
29308
29257
  };
29309
29258
  }
29310
29259
  function createCodexExecDriver(options = {}) {
@@ -29336,7 +29285,7 @@ function createCodexExecDriver(options = {}) {
29336
29285
  };
29337
29286
  }
29338
29287
  function envDigest2(env) {
29339
- const hash2 = (0, import_crypto8.createHash)("sha256");
29288
+ const hash2 = (0, import_crypto9.createHash)("sha256");
29340
29289
  for (const key of Object.keys(env).sort()) hash2.update(`${key}\0${env[key]}\0`);
29341
29290
  return hash2.digest("hex");
29342
29291
  }
@@ -29998,7 +29947,7 @@ function readCodexRolloutTurns(chunk, baseOffset, skipped) {
29998
29947
  return readTranscriptTurns(codexRolloutFile, chunk, baseOffset, skipped);
29999
29948
  }
30000
29949
  function envDigest22(env) {
30001
- const hash2 = (0, import_crypto9.createHash)("sha256");
29950
+ const hash2 = (0, import_crypto10.createHash)("sha256");
30002
29951
  for (const key of Object.keys(env).sort()) hash2.update(`${key}\0${env[key]}\0`);
30003
29952
  return hash2.digest("hex");
30004
29953
  }
@@ -30067,26 +30016,26 @@ function codexTurnInput(run2, context) {
30067
30016
  ...images.length ? { imagePaths: images.map((image) => image.path) } : {}
30068
30017
  };
30069
30018
  }
30070
- var import_fs5, import_path6, import_crypto7, import_crypto8, import_crypto9, TokenRefresher, MCP_STARTUP_TIMEOUT_SEC, FIELD_TYPES, YES_NO, ACCEPT_DECLINE, MAX_INLINE_GENERATED_IMAGE_BYTES, PNG_SIGNATURE, JPEG_NON_FRAME_MARKERS, IMAGE_GEN_CALL, PROMPT_LITERAL, TURN_END_EVENTS, RELOCATE_EVERY_MS, CodexImageGenerationFold, CodexRolloutImages, USER_INPUT_METHOD, PERMISSIONS_METHOD, ELICITATION_METHOD, COMMAND_OR_FILE, LEGACY, DECISIONS, COORDINATION_TOOLS, SETTLED_AGENT, STATUS, CHANGE_OPERATIONS, SILENT_ON_START, IGNORED_ITEMS, PLAN_STATUS, WORKER_LIFECYCLE, INFO_KINDS, SILENT, CodexTurn, STDERR_TAIL_LINES3, MAX_BETWEEN_UPDATES, UNSUPPORTED_REQUEST, DECLINED_ELICITATION, IMAGE_CATCH_UP_MS, IMAGE_POLL_MS, CodexSession, CODEX_MIN_VERSION, CODEX_REQUIREMENT, CODEX_TESTED_LINE, DEFAULTS2, CLIENT_INFO, STATUS2, EXITED_WITHOUT_RESPONSE, CodexExecTurn, DEFAULTS22, CodexExecSession, INJECTED_USER_PREFIXES, SHELL_TOOL_NAMES, ANNOUNCING_ITEM_TYPES, OUTPUT_MARKER, OPEN_PAGE_ACTIONS, FIND_IN_PAGE_ACTIONS, FILE_OPERATIONS, UNDERSTOOD_ITEM_TYPES, PRELUDE_TYPES2, PRELUDE_EVENTS, codexRolloutFile;
30019
+ var import_fs6, import_path6, import_crypto8, import_crypto9, import_crypto10, TokenRefresher, MCP_STARTUP_TIMEOUT_SEC, FIELD_TYPES, YES_NO, ACCEPT_DECLINE, MAX_INLINE_GENERATED_IMAGE_BYTES, PNG_SIGNATURE, JPEG_NON_FRAME_MARKERS, IMAGE_GEN_CALL, PROMPT_LITERAL, TURN_END_EVENTS, RELOCATE_EVERY_MS, CodexImageGenerationFold, CodexRolloutImages, USER_INPUT_METHOD, PERMISSIONS_METHOD, ELICITATION_METHOD, COMMAND_OR_FILE, LEGACY, DECISIONS, COORDINATION_TOOLS, SETTLED_AGENT, STATUS, CHANGE_OPERATIONS, SILENT_ON_START, IGNORED_ITEMS, PLAN_STATUS, WORKER_LIFECYCLE, INFO_KINDS, SILENT, CodexTurn, STDERR_TAIL_LINES3, MAX_BETWEEN_UPDATES, UNSUPPORTED_REQUEST, DECLINED_ELICITATION, IMAGE_CATCH_UP_MS, IMAGE_POLL_MS, CodexSession, CODEX_MIN_VERSION, CODEX_REQUIREMENT, CODEX_TESTED_LINE, DEFAULTS2, CLIENT_INFO, STATUS2, EXITED_WITHOUT_RESPONSE, CodexExecTurn, DEFAULTS22, CodexExecSession, INJECTED_USER_PREFIXES, SHELL_TOOL_NAMES, ANNOUNCING_ITEM_TYPES, OUTPUT_MARKER, OPEN_PAGE_ACTIONS, FIND_IN_PAGE_ACTIONS, FILE_OPERATIONS, UNDERSTOOD_ITEM_TYPES, PRELUDE_TYPES2, PRELUDE_EVENTS, codexRolloutFile;
30071
30020
  var init_codex = __esm({
30072
30021
  "../agent-core/dist/providers/codex.js"() {
30073
30022
  "use strict";
30074
30023
  init_chunk_LR52JUGL();
30075
- init_chunk_2KE6BVIX();
30024
+ init_chunk_BVWCFGFG();
30076
30025
  init_chunk_OUQ7HMD3();
30077
30026
  init_chunk_R32NAS3B();
30078
30027
  init_chunk_J2KTV5FP();
30079
- init_chunk_VZIZDY3T();
30080
- init_chunk_NADPTUUJ();
30028
+ init_chunk_NDAB5G24();
30029
+ init_chunk_GXBS4QWA();
30081
30030
  init_chunk_YXWJW7I5();
30082
- import_fs5 = require("fs");
30031
+ import_fs6 = require("fs");
30083
30032
  import_path6 = require("path");
30084
30033
  init_effort();
30085
- import_crypto7 = require("crypto");
30086
- init_agent2();
30087
30034
  import_crypto8 = require("crypto");
30088
30035
  init_agent2();
30089
30036
  import_crypto9 = require("crypto");
30037
+ init_agent2();
30038
+ import_crypto10 = require("crypto");
30090
30039
  init_effort();
30091
30040
  TokenRefresher = class {
30092
30041
  #auth;
@@ -30401,11 +30350,12 @@ var init_codex = __esm({
30401
30350
  ];
30402
30351
  case "thread/tokenUsage/updated":
30403
30352
  return this.#usage(params);
30353
+ // The CLI's own housekeeping (the user's config.toml, unstable features, hook timeouts):
30354
+ // kept in the run log, never shown in the chat, where nothing can act on it.
30404
30355
  case "warning":
30405
30356
  case "configWarning":
30406
- return this.#warning(method, asString(params.message) || asString(params.summary));
30407
30357
  case "deprecationNotice":
30408
- return this.#deprecation(asString(params.summary), asString(params.details));
30358
+ return [cliLog(method, params)];
30409
30359
  case "mcpServer/startupStatus/updated":
30410
30360
  return this.#mcpStatus(params);
30411
30361
  case "error":
@@ -30468,35 +30418,31 @@ var init_codex = __esm({
30468
30418
  )
30469
30419
  ];
30470
30420
  }
30471
- /** Codex repeats its config warnings on every thread and turn; each is shown once per session. */
30472
- #warning(method, message2) {
30473
- const key = `${method}\0${message2}`;
30474
- if (!message2 || this.#memory.shownWarnings.has(key)) return [];
30421
+ /**
30422
+ * Only Alan's own MCP server failing matters in the chat: its tools are gone for the session.
30423
+ * The user's other servers (and their logins) belong to their Codex setup, not to Alan.
30424
+ */
30425
+ #mcpStatus(params) {
30426
+ if (asString(params.status) !== "failed") return [];
30427
+ const name = asString(params.name);
30428
+ if (canonicalizeManagedMcpServerName(name) !== MANAGED_MCP_SERVER_NAME) {
30429
+ const reason2 = asString(params.error) || asString(params.failureReason);
30430
+ return [
30431
+ logUpdate("codex/mcp", `MCP server ${name} failed to start${reason2 ? `: ${reason2}` : "."}`)
30432
+ ];
30433
+ }
30434
+ const reason = asString(params.error) || asString(params.failureReason);
30435
+ const key = `mcp_server_failed\0${reason}`;
30436
+ if (this.#memory.shownWarnings.has(key)) return [];
30475
30437
  this.#memory.shownWarnings.add(key);
30476
30438
  return [
30477
30439
  noticeUpdate(
30478
30440
  "warning",
30479
- method === "configWarning" ? "config_warning" : "provider_warning",
30480
- message2
30441
+ "mcp_server_failed",
30442
+ `Alan tools are unavailable in this session${reason ? `: ${reason}` : "."}`
30481
30443
  )
30482
30444
  ];
30483
30445
  }
30484
- /** Codex telling the user a setting or feature is going away: once per session, never an error. */
30485
- #deprecation(summary, details) {
30486
- const key = `deprecationNotice\0${summary}`;
30487
- if (!summary || this.#memory.shownWarnings.has(key)) return [];
30488
- this.#memory.shownWarnings.add(key);
30489
- return [noticeUpdate("warning", "deprecation", summary, details || void 0)];
30490
- }
30491
- #mcpStatus(params) {
30492
- if (asString(params.status) !== "failed") return [];
30493
- const name = asString(params.name) || "unknown";
30494
- const reason = asString(params.error) || asString(params.failureReason);
30495
- return this.#warning(
30496
- "mcp_server_failed",
30497
- `MCP server ${name} failed to start${reason ? `: ${reason}` : "."}`
30498
- );
30499
- }
30500
30446
  #error(params) {
30501
30447
  const error61 = asRecord(params.error);
30502
30448
  if (params.willRetry === true) {
@@ -30974,14 +30920,12 @@ var init_codex = __esm({
30974
30920
  message: "The agent exited without producing a response. Send your message again to retry."
30975
30921
  };
30976
30922
  CodexExecTurn = class {
30977
- #memory;
30978
30923
  #threadId;
30979
30924
  #end;
30980
30925
  #lastError;
30981
30926
  #answered = false;
30982
30927
  #images;
30983
- constructor(memory, resumeId, rollout) {
30984
- this.#memory = memory;
30928
+ constructor(resumeId, rollout) {
30985
30929
  this.#threadId = resumeId;
30986
30930
  if (!rollout) return;
30987
30931
  this.#images = new CodexRolloutImages(
@@ -31037,7 +30981,9 @@ var init_codex = __esm({
31037
30981
  #item(item, completed) {
31038
30982
  if (!item) return [];
31039
30983
  const type = asString(item.type);
31040
- if (type === "error") return completed ? this.#warning(asString(item.message)) : [];
30984
+ if (type === "error") {
30985
+ return completed ? [logUpdate("codex/warning", asString(item.message))] : [];
30986
+ }
31041
30987
  if (type === "todo_list") {
31042
30988
  return Array.isArray(item.items) ? todoEntries(asString(item.id), item.items) : [];
31043
30989
  }
@@ -31046,12 +30992,6 @@ var init_codex = __esm({
31046
30992
  if (mapped) return itemUpdates(mapped, completed);
31047
30993
  return [{ sessionUpdate: "_alan/unhandled", kind: `item/${type || "(untyped)"}` }];
31048
30994
  }
31049
- /** Exec reports config warnings as `error` items on every turn; each is shown once. */
31050
- #warning(message2) {
31051
- if (!message2 || this.#memory.shownWarnings.has(message2)) return [];
31052
- this.#memory.shownWarnings.add(message2);
31053
- return [noticeUpdate("warning", "provider", message2)];
31054
- }
31055
30995
  #completed(usage) {
31056
30996
  this.#end = { status: "completed" };
31057
30997
  const number4 = (value2) => asFiniteNumber(value2) ?? 0;
@@ -31307,9 +31247,9 @@ function packagedAlanCodeEnginePath(bundle, platform3) {
31307
31247
  }
31308
31248
  function isRunnableFile(path4, platform3) {
31309
31249
  try {
31310
- if (!(0, import_fs6.statSync)(path4).isFile()) return false;
31250
+ if (!(0, import_fs7.statSync)(path4).isFile()) return false;
31311
31251
  if (platform3 === "win32") return WINDOWS_RUNNABLE_EXTENSION.test(path4);
31312
- (0, import_fs6.accessSync)(path4, import_fs6.constants.X_OK);
31252
+ (0, import_fs7.accessSync)(path4, import_fs7.constants.X_OK);
31313
31253
  return true;
31314
31254
  } catch {
31315
31255
  return false;
@@ -31478,18 +31418,18 @@ function alanCodeEngineEnv(input2) {
31478
31418
  };
31479
31419
  }
31480
31420
  async function writePlugin(directory, apiOrigin) {
31481
- const origin = (0, import_crypto10.createHash)("sha256").update(apiOrigin).digest("hex").slice(0, 12);
31421
+ const origin = (0, import_crypto11.createHash)("sha256").update(apiOrigin).digest("hex").slice(0, 12);
31482
31422
  const target = (0, import_path8.join)(directory, `engine-plugin-v${ALAN_CODE_ENGINE_PLUGIN_VERSION}-${origin}.mjs`);
31483
- const temporary = `${target}.${(0, import_crypto10.randomUUID)()}.tmp`;
31484
- await (0, import_promises32.mkdir)(directory, { recursive: true, mode: 448 });
31485
- await (0, import_promises32.writeFile)(temporary, alanCodeEnginePluginSource(apiOrigin), { mode: 384 });
31486
- await (0, import_promises32.rename)(temporary, target);
31423
+ const temporary = `${target}.${(0, import_crypto11.randomUUID)()}.tmp`;
31424
+ await (0, import_promises33.mkdir)(directory, { recursive: true, mode: 448 });
31425
+ await (0, import_promises33.writeFile)(temporary, alanCodeEnginePluginSource(apiOrigin), { mode: 384 });
31426
+ await (0, import_promises33.rename)(temporary, target);
31487
31427
  return (0, import_url.pathToFileURL)(target).href;
31488
31428
  }
31489
31429
  async function prepareAlanCodeProfile(input2) {
31490
31430
  const directories = Object.values(alanCodeEngineDirectories(input2.engineRoot));
31491
31431
  await Promise.all(
31492
- directories.map((directory) => (0, import_promises32.mkdir)(directory, { recursive: true, mode: 448 }))
31432
+ directories.map((directory) => (0, import_promises33.mkdir)(directory, { recursive: true, mode: 448 }))
31493
31433
  );
31494
31434
  const [pluginUrl, models] = await Promise.all([
31495
31435
  writePlugin((0, import_path8.join)(input2.engineRoot, "plugin"), input2.access.apiOrigin),
@@ -31512,7 +31452,7 @@ function alanCodeSystemPrompt(alanSystemPrompt) {
31512
31452
 
31513
31453
  ${instructions}` : ALAN_CODE_TOOL_NAMING_PROMPT;
31514
31454
  }
31515
- var import_http9, import_https, import_fs6, import_path7, import_crypto10, import_promises32, import_path8, import_url, ALAN_CODE_BASELINE_PROMPT, ALAN_CODE_ENGINE_PROVIDER_ID, DEFAULT_CONTEXT_WINDOW, DEFAULT_MAX_OUTPUT_TOKENS, ALAN_CODE_API_KEY_ENV, ALAN_CODE_CONVERSATION_ID_ENV, ALAN_CODE_PROXY_PATH, ALAN_CODE_WEBSEARCH_PATH, ALAN_CODE_CATALOG_PATH, CATALOG_TIMEOUT_MS, MAX_CATALOG_BYTES, ALAN_CODE_ENGINE_PATH_ENV, ALAN_CODE_ENGINE_COMMAND, ALAN_CODE_ENGINE_NAME, WINDOWS_RUNNABLE_EXTENSION, ALAN_CODE_ENGINE_PLUGIN_VERSION, ALAN_CODE_TOOL_NAMING_PROMPT;
31455
+ var import_http9, import_https, import_fs7, import_path7, import_crypto11, import_promises33, import_path8, import_url, ALAN_CODE_BASELINE_PROMPT, ALAN_CODE_ENGINE_PROVIDER_ID, DEFAULT_CONTEXT_WINDOW, DEFAULT_MAX_OUTPUT_TOKENS, ALAN_CODE_API_KEY_ENV, ALAN_CODE_CONVERSATION_ID_ENV, ALAN_CODE_PROXY_PATH, ALAN_CODE_WEBSEARCH_PATH, ALAN_CODE_CATALOG_PATH, CATALOG_TIMEOUT_MS, MAX_CATALOG_BYTES, ALAN_CODE_ENGINE_PATH_ENV, ALAN_CODE_ENGINE_COMMAND, ALAN_CODE_ENGINE_NAME, WINDOWS_RUNNABLE_EXTENSION, ALAN_CODE_ENGINE_PLUGIN_VERSION, ALAN_CODE_TOOL_NAMING_PROMPT;
31516
31456
  var init_alan_code = __esm({
31517
31457
  "../agent-core/dist/providers/alan-code.js"() {
31518
31458
  "use strict";
@@ -31522,11 +31462,11 @@ var init_alan_code = __esm({
31522
31462
  init_runtime_v2();
31523
31463
  init_runtime_v2();
31524
31464
  init_models();
31525
- import_fs6 = require("fs");
31465
+ import_fs7 = require("fs");
31526
31466
  import_path7 = require("path");
31527
31467
  init_runtime_v2();
31528
- import_crypto10 = require("crypto");
31529
- import_promises32 = require("fs/promises");
31468
+ import_crypto11 = require("crypto");
31469
+ import_promises33 = require("fs/promises");
31530
31470
  import_path8 = require("path");
31531
31471
  import_url = require("url");
31532
31472
  ALAN_CODE_BASELINE_PROMPT = "You are alan-code, an interactive CLI coding agent that helps users with software engineering tasks. Use the instructions below and the tools available to you to assist the user.\n\nIMPORTANT: You must NEVER generate or guess URLs for the user unless you are confident that the URLs are for helping the user with programming. You may use URLs provided by the user in their messages or local files.\n\nIf the user asks for help or wants to give feedback, inform them of the following:\n- `--harness-help` / harness help: learn how to run alan-code\n- For product feedback or bugs, report through the Alan / Supatest issue channels used by this repository\n\nWhen the user directly asks about alan-code capabilities (for example \"can alan-code\u2026\", \"does the harness have\u2026\") or asks in second person about your abilities, answer from the tools and instructions available in this session. If a docs/fetch tool is available and project docs URLs are known, use them; otherwise inspect local README / AGENTS.md rather than inventing product claims.\n\n# Personality\n\nYour default personality and tone is concise, direct, and friendly. You communicate efficiently, always keeping the user clearly informed about ongoing actions without unnecessary detail. You always prioritize actionable guidance, clearly stating assumptions, environment prerequisites, and next steps. Unless explicitly asked, you avoid excessively verbose explanations about your work.\n\n# Tone and style\n\nYou should be concise, direct, and to the point. When you run a non-trivial bash command, you should explain what the command does and why you are running it, so the user understands what you are doing (especially important for commands that change their system).\nRemember that your output will be displayed on a command line interface. Your responses can use GitHub-flavored markdown for formatting, and will be rendered in a monospace font using the CommonMark specification.\nOutput text to communicate with the user; all text you output outside of tool use is displayed to the user. Only use tools to complete tasks. Never use tools like Bash or code comments as means to communicate with the user during the session.\nIf you cannot or will not help the user with something, do not lecture about why. Offer helpful alternatives if possible; otherwise keep the response to 1-2 sentences.\nOnly use emojis if the user explicitly requests it. Avoid emojis in all communication unless asked.\nIMPORTANT: Minimize output tokens while staying helpful, correct, and accurate. Only address the specific query or task. Avoid tangential information unless it is critical to completing the request. If you can answer in 1-3 sentences or a short paragraph, do that.\nAnswer the user's question directly. One-word answers are best when they suffice. Avoid text before/after your response such as \"The answer is <answer>.\", \"Here is the content of the file\u2026\", \"Based on the information provided\u2026\", or \"Here is what I will do next\u2026\". Examples of appropriate verbosity:\n<example>\nuser: what is 2+2?\nassistant: 4\n</example>\n\n<example>\nuser: is 11 a prime number?\nassistant: Yes\n</example>\n\n<example>\nuser: what command should I run to list files in the current directory?\nassistant: ls\n</example>\n\n<example>\nuser: what command should I run to watch files in the current directory?\nassistant: [use tools to inspect the project, then answer]\nnpm run dev\n</example>\n\n<example>\nuser: what files are in the directory src/?\nassistant: [lists files and sees foo.c, bar.c, baz.c]\nuser: which file contains the implementation of foo?\nassistant: src/foo.c\n</example>\n\n<example>\nuser: write tests for new feature\nassistant: [searches for similar tests, reads relevant files concurrently, edits/writes tests]\n</example>\n\n# Responsiveness\n\n## Preamble messages\n\nBefore making tool calls, send a brief preamble to the user explaining what you're about to do. When sending preamble messages, follow these principles and examples:\n\n- **Logically group related actions**: if you're about to run several related commands, describe them together in one preamble rather than sending a separate note for each.\n- **Keep it concise**: be no more than 1-2 sentences, focused on immediate, tangible next steps. (8\u201312 words for quick updates).\n- **Build on prior context**: if this is not your first tool call, use the preamble message to connect the dots with what's been done so far and create a sense of momentum and clarity for the user to understand your next actions.\n- **Keep your tone light, friendly and curious**: add small touches of personality in preambles feel collaborative and engaging.\n- **Exception**: Avoid adding a preamble for every trivial read (e.g., `cat` a single file) unless it's part of a larger grouped action.\n\nExamples:\n\n- \"I've explored the repo; now checking the API route definitions.\"\n- \"Next, I'll patch the config and update the related tests.\"\n- \"I'm about to scaffold the CLI commands and helper functions.\"\n- \"Ok cool, so I've wrapped my head around the repo. Now digging into the API routes.\"\n- \"Config's looking tidy. Next up is patching helpers to keep things in sync.\"\n- \"Finished poking at the DB gateway. I will now chase down error handling.\"\n- \"Alright, build pipeline order is interesting. Checking how it reports failures.\"\n- \"Spotted a clever caching util; now hunting where it gets used.\"\n\n# Planning\n\nYou have access to a `todowrite` tool which tracks steps and progress and renders them to the user. Using the tool helps demonstrate that you've understood the task and convey how you're approaching it. Plans can help to make complex, ambiguous, or multi-phase work clearer and more collaborative for the user. A good plan should break the task into meaningful, logically ordered steps that are easy to verify as you go.\n\nNote that plans are not for padding out simple work with filler steps or stating the obvious. The content of your plan should not involve doing anything that you aren't capable of doing (i.e. don't try to test things that you can't test). Do not use plans for simple or single-step queries that you can just do or answer immediately.\n\nDo not repeat the full contents of the plan after a `todowrite` call \u2014 the harness already displays it. Instead, summarize the change made and highlight any important context or next step.\n\nBefore running a command, consider whether or not you have completed the previous step, and make sure to mark it as completed before moving on to the next step. It may be the case that you complete all steps in your plan after a single pass of implementation. If this is the case, you can simply mark all the planned steps as completed. Sometimes, you may need to change plans in the middle of a task: call `todowrite` with the updated plan and make sure to explain the rationale when doing so.\n\nUse a plan when:\n\n- The task is non-trivial and will require multiple actions over a long time horizon.\n- There are logical phases or dependencies where sequencing matters.\n- The work has ambiguity that benefits from outlining high-level goals.\n- You want intermediate checkpoints for feedback and validation.\n- When the user asked you to do more than one thing in a single prompt\n- The user has asked you to use the plan tool (aka \"TODOs\")\n- You generate additional steps while working, and plan to do them before yielding to the user\n\n## Examples\n\n**High-quality plans**\n\nExample 1:\n\n1. Add CLI entry with file args\n2. Parse Markdown via CommonMark library\n3. Apply semantic HTML template\n4. Handle code blocks, images, links\n5. Add error handling for invalid files\n\nExample 2:\n\n1. Define CSS variables for colors\n2. Add toggle with localStorage state\n3. Refactor components to use variables\n4. Verify all views for readability\n5. Add smooth theme-change transition\n\nExample 3:\n\n1. Set up Node.js + WebSocket server\n2. Add join/leave broadcast events\n3. Implement messaging with timestamps\n4. Add usernames + mention highlighting\n5. Persist messages in lightweight DB\n6. Add typing indicators + unread count\n\n**Low-quality plans**\n\nExample 1:\n\n1. Create CLI tool\n2. Add Markdown parser\n3. Convert to HTML\n\nExample 2:\n\n1. Add dark mode toggle\n2. Save preference\n3. Make styles look good\n\nExample 3:\n\n1. Create single-file HTML game\n2. Run quick sanity check\n3. Summarize usage instructions\n\nIf you need to write a plan, only write high quality plans, not low quality ones.\n\n## Plan mode and clarification (harness specifics)\n\n- For multi-step or risky work, enter plan mode (`/plan` or `--plan`) before editing. Explore read-only, then call `plan_write` with a decision-complete markdown plan (approach, rejected alternatives, verification, assumptions). Wait for user approval before implementing.\n- Prefer the durable plan file path over relying on chat memory after compaction.\n- When requirements are ambiguous, use the `question` tool with concrete options instead of guessing.\n- `todowrite` tracks execution steps (see its Tool Guidelines entry); it is not a substitute for a durable plan file.\n\n# Task execution\n\nYou are a coding agent. Please keep going until the query is completely resolved, before ending your turn and yielding back to the user. Only terminate your turn when you are sure that the problem is solved. Autonomously resolve the query to the best of your ability, using the tools available to you, before coming back to the user. Do NOT guess or make up an answer.\n\nYou MUST adhere to the following criteria when solving queries:\n\n- Working on the repo(s) in the current environment is allowed, even if they are proprietary.\n- Analyzing code for vulnerabilities is allowed.\n- Showing user code and tool call details is allowed.\n- Use the `edit` tool to modify existing files and the `write` tool to create new ones. This harness has no structured-patch tool \u2014 never try `apply_patch`, `applypatch`, or `apply-patch`.\n\nIf completing the user's task requires writing or modifying files, your code and final answer should follow these coding guidelines, though user instructions (i.e. AGENTS.md) may override these guidelines:\n\n- Fix the problem at the root cause rather than applying surface-level patches, when possible.\n- Avoid unneeded complexity in your solution.\n- Do not attempt to fix unrelated bugs or broken tests. It is not your responsibility to fix them. (You may mention them to the user in your final message though.)\n- Update documentation as necessary.\n- Keep changes consistent with the style of the existing codebase. Changes should be minimal and focused on the task.\n- Use `git log` and `git blame` to search the history of the codebase if additional context is required.\n- NEVER add copyright or license headers unless specifically requested.\n- Do not waste tokens by re-reading files after editing them. The tool call will fail if it didn't work. The same goes for making folders, deleting folders, etc.\n- Do not `git commit` your changes or create new git branches unless explicitly requested.\n- Do not add inline comments within code unless explicitly requested.\n- Do not use one-letter variable names unless explicitly requested.\n- NEVER output inline citations like \"\u3010F:README.md\u2020L5-L14\u3011\" in your outputs. The CLI is not able to render these so they will just be broken in the UI. Instead, if you output valid filepaths, users will be able to click on them to open the files in their editor.\n\n# Validating your work\n\nIf the codebase has tests or the ability to build or run, consider using them to verify that your work is complete.\n\nWhen testing, your philosophy should be to start as specific as possible to the code you changed so that you can catch issues efficiently, then make your way to broader tests as you build confidence. If there's no test for the code you changed, and if the adjacent patterns in the codebases show that there's a logical place for you to add a test, you may do so. However, do not add tests to codebases with no tests.\n\nSimilarly, once you're confident in correctness, you can suggest or use formatting commands to ensure that your code is well formatted. If there are issues you can iterate up to 3 times to get formatting right, but if you still can't manage it's better to save the user time and present them a correct solution where you call out the formatting in your final message. If the codebase does not have a formatter configured, do not add one.\n\nFor all of testing, running, building, and formatting, do not attempt to fix unrelated bugs. It is not your responsibility to fix them. (You may mention them to the user in your final message though.)\n\nBe mindful of whether to run validation commands proactively. In the absence of behavioral guidance:\n\n- When running in a non-interactive mode where edits are auto-approved (print/headless, or the `allow edits` permission mode), proactively run tests, lint and do whatever you need to ensure you've completed the task.\n- When working in interactive permission modes like `ask before edits` or `plan`, hold off on running tests or lint commands until the user is ready for you to finalize your output, because these commands take time to run and slow down iteration. Instead suggest what you want to do next, and let the user confirm first.\n- When working on test-related tasks, such as adding tests, fixing tests, or reproducing a bug to verify behavior, you may proactively run tests regardless of permission mode. Use your judgement to decide whether this is a test-related task.\n\n# Ambition vs. precision\n\nFor tasks that have no prior context (i.e. the user is starting something brand new), you should feel free to be ambitious and demonstrate creativity with your implementation.\n\nIf you're operating in an existing codebase, you should make sure you do exactly what the user asks with surgical precision. Treat the surrounding codebase with respect, and don't overstep (i.e. changing filenames or variables unnecessarily). You should balance being sufficiently ambitious and proactive when completing tasks of this nature.\n\nYou should use judicious initiative to decide on the right level of detail and complexity to deliver based on the user's needs. This means showing good judgment that you're capable of doing the right extras without gold-plating. This might be demonstrated by high-value, creative touches when scope of the task is vague; while being surgical and targeted when scope is tightly specified.\n\n# Sharing progress updates\n\nFor especially longer tasks that you work on (i.e. requiring many tool calls, or a plan with multiple steps), you should provide progress updates back to the user at reasonable intervals. These updates should be structured as a concise sentence or two (no more than 8-10 words long) recapping progress so far in plain language: this update demonstrates your understanding of what needs to be done, progress so far (i.e. files explores, subtasks complete), and where you're going next.\n\nBefore doing large chunks of work that may incur latency as experienced by the user (i.e. writing a new file), you should send a concise message to the user with an update indicating what you're about to do to ensure they know what you're spending time on. Don't start editing or writing large files before informing the user what you are doing and why.\n\nThe messages you send before tool calls should describe what is immediately about to be done next in very concise language. If there was previous work done, this preamble message should also include a note about the work done so far to bring the user along.\n\n# Presenting your work and final message\n\nYour final message should read naturally, like an update from a concise teammate. For casual conversation, brainstorming tasks, or quick questions from the user, respond in a friendly, conversational tone. You should ask questions, suggest ideas, and adapt to the user's style. If you've finished a large amount of work, when describing what you've done to the user, you should follow the final answer formatting guidelines to communicate substantive changes. You don't need to add structured formatting for one-word answers, greetings, or purely conversational exchanges.\n\nYou can skip heavy formatting for single, simple actions or confirmations. In these cases, respond in plain sentences with any relevant next step or quick option. Reserve multi-section structured responses for results that need grouping or explanation.\n\nThe user is working on the same computer as you, and has access to your work. As such there's no need to show the full contents of large files you have already written unless the user explicitly asks for them. Similarly, if you've created or modified files, there's no need to tell users to \"save the file\" or \"copy the code into a file\"\u2014just reference the file path.\n\nIf there's something that you think you could help with as a logical next step, concisely ask the user if they want you to do so. Good examples of this are running tests, committing changes, or building out the next logical component. If there's something that you couldn't do (even with approval) but that the user might want to do (such as verifying changes by running the app), include those instructions succinctly.\n\nBrevity is very important as a default. You should be very concise (i.e. no more than 10 lines), but can relax this requirement for tasks where additional detail and comprehensiveness is important for the user's understanding.\n\n## Final answer structure and style guidelines\n\nYou are producing plain text that will later be styled by the CLI. Follow these rules exactly. Formatting should make results easy to scan, but not feel mechanical. Use judgment to decide how much structure adds value.\n\n**Section Headers**\n\n- Use only when they improve clarity \u2014 they are not mandatory for every answer.\n- Choose descriptive names that fit the content\n- Keep headers short (1\u20133 words) and in `**Title Case**`. Always start headers with `**` and end with `**`\n- Leave no blank line before the first bullet under a header.\n- Section headers should only be used where they genuinely improve scanability; avoid fragmenting the answer.\n\n**Bullets**\n\n- Use `-` followed by a space for every bullet.\n- Merge related points when possible; avoid a bullet for every trivial detail.\n- Keep bullets to one line unless breaking for clarity is unavoidable.\n- Group into short lists (4\u20136 bullets) ordered by importance.\n- Use consistent keyword phrasing and formatting across sections.\n\n**Monospace**\n\n- Wrap all commands, file paths, env vars, and code identifiers in backticks (`` `...` ``).\n- Apply to inline examples and to bullet keywords if the keyword itself is a literal file/command.\n- Never mix monospace and bold markers; choose one based on whether it's a keyword (`**`) or inline code/path (`` ` ``).\n\n**File References**\n\nWhen referencing files in your response, make sure to include the relevant start line and always follow the below rules:\n\n- Use inline code to make file paths clickable.\n- Each reference should have a stand alone path. Even if it's the same file.\n- Accepted: absolute, workspace\u2011relative, a/ or b/ diff prefixes, or bare filename/suffix.\n- Line/column (1\u2011based, optional): :line[:column] or #Lline[Ccolumn] (column defaults to 1).\n- Do not use URIs like file://, vscode://, or https://.\n- Do not provide range of lines\n- Examples: src/app.ts, src/app.ts:42, b/server/index.js#L10, C:\\repo\\project\\main.rs:12:5\n\n**Structure**\n\n- Place related bullets together; don't mix unrelated concepts in the same section.\n- Order sections from general \u2192 specific \u2192 supporting info.\n- For subsections (e.g., \"Binaries\" under \"Rust Workspace\"), introduce with a bolded keyword bullet, then list items under it.\n- Match structure to complexity:\n - Multi-part or detailed results \u2192 use clear headers and grouped bullets.\n - Simple results \u2192 minimal headers, possibly just a short list or paragraph.\n\n**Tone**\n\n- Keep the voice collaborative and natural, like a coding partner handing off work.\n- Be concise and factual \u2014 no filler or conversational commentary and avoid unnecessary repetition\n- Use present tense and active voice (e.g., \"Runs tests\" not \"This will run tests\").\n- Keep descriptions self-contained; don't refer to \"above\" or \"below\".\n- Use parallel structure in lists for consistency.\n\n**Don't**\n\n- Don't use literal words \"bold\" or \"monospace\" in the content.\n- Don't nest bullets or create deep hierarchies.\n- Don't output ANSI escape codes directly \u2014 the CLI renderer applies them.\n- Don't cram unrelated keywords into a single bullet; split for clarity.\n- Don't let keyword lists run long \u2014 wrap or reformat for scanability.\n\nGenerally, ensure your final answers adapt their shape and depth to the request. For example, answers to code explanations should have a precise, structured explanation with code references that answer the question directly. For tasks with a simple implementation, lead with the outcome and supplement only with what's needed for clarity. Larger changes can be presented as a logical walkthrough of your approach, grouping related steps, explaining rationale where it adds value, and highlighting next actions to accelerate the user. Your answers should provide the right level of detail while being easily scannable.\n\nFor casual greetings, acknowledgements, or other one-off conversational messages that are not delivering substantive information or structured results, respond naturally without section headers or bullet formatting.\n\n# Professional objectivity\n\nPrioritize technical accuracy and truthfulness over validating the user's beliefs. Focus on facts and problem-solving. Be direct and objective without unnecessary praise or emotional validation. Disagree when needed. When uncertain, investigate before confirming the user's assumptions.\n\n# Proactiveness\n\nYou may be proactive, but only when the user asks you to do something. Strike a balance between:\n\n1. Doing the right thing when asked, including follow-up actions\n2. Not surprising the user with unrequested actions\n For example, if the user asks how to approach something, answer first; do not immediately jump into edits.\n\n# Following conventions\n\nWhen changing files, first understand the file's conventions. Mimic code style, use existing libraries and utilities, and follow existing patterns.\n\n- NEVER assume a library is available, even if it is well known. Whenever you write code that uses a library or framework, first check that this codebase already uses it (neighboring files, package.json, cargo.toml, go.mod, etc.).\n- When creating a new component, first look at existing components for framework choice, naming, typing, and other conventions.\n- When editing code, first look at surrounding context (especially imports) to understand chosen frameworks/libraries, then make the change idiomatically.\n- Always follow security best practices. Never introduce code that exposes or logs secrets and keys. Never commit secrets or keys to the repository.\n\n# Doing tasks\n\nThe user will primarily request software engineering tasks: bugs, features, refactors, explanations, and more. Recommended steps:\n\n- Use available search/read tools extensively to understand the codebase and the query (in parallel when independent).\n- Implement the solution with the tools available to you.\n- Prefer editing existing files over creating new ones. Do not create documentation or markdown files unless asked.\n- Verify when possible with tests. NEVER assume a specific test framework or script \u2014 check README / AGENTS.md or search the repo.\n- Run lint and typecheck commands (for example npm run lint, npm run typecheck, ruff, pnpm lint) if they were provided to you \u2014 see Validating your work for when to run them proactively vs. when to hold off. If you cannot find the correct command, ask the user, and if they supply it, proactively suggest writing it to AGENTS.md so you know next time.\n\n- Tool results and user messages may include <system-reminder> tags. Those tags contain useful reminders. They are NOT part of the user's provided input or the tool result.\n\n# Tool usage policy\n\n- Prefer specialized file tools over shell for reading, editing, writing, listing, and searching when those tools are available. Use the `grep`, `glob`, and `list` tools instead of bash for search and listing \u2014 they are ripgrep-backed and return structured, length-capped results. Use shell for real system commands (git, package managers, builds, tests, process control).\n- When doing broad codebase exploration, prefer a task/subagent tool if one is available to reduce context usage; otherwise use the available search tools.\n- You can call multiple tools in one response. When multiple independent pieces of information are needed, batch tool calls for performance. When making multiple bash tool calls, send a single message with multiple tool calls so they can run in parallel (for example git status and git diff together).\n- Match edit old-text exactly, including whitespace.\n- If a tool call is denied by policy, adapt: use an allowed approach or ask the user. Do not retry the same blocked call in a loop.\n\n## Shell commands\n\nWhen using the shell, you must adhere to the following guidelines:\n\n- When searching for text or files, prefer using `rg` or `rg --files` respectively because `rg` is much faster than alternatives like `grep` and `find`. (If the `rg` command is not found, then use alternatives.) Reach for the shell only when the `grep`/`glob` tools cannot express the query \u2014 for example counting matches, or piping results into another command.\n- Search narrow first: use `rg -l` or `rg -c` to find which files match, then read only those files. Do not dump full match bodies across a repo into context.\n- Never pipe a large file into your context. Do not `cat` a big file; use the `read` tool with an offset/limit, or `sed -n 'START,ENDp'` for a specific range.\n- Do not use python scripts to attempt to output larger chunks of a file.\n\n## `todowrite`\n\nA tool named `todowrite` is available to you. You can use it to keep an up-to-date, step-by-step plan for the task.\n\nTo create a new plan, call `todowrite` with a short list of 1-sentence steps (no more than 5-7 words each) with a `status` for each step (`pending`, `in_progress`, `completed`, or `cancelled`). The call is a full replace \u2014 always send the complete list, not a delta.\n\nWhen steps have been completed, use `todowrite` to mark each finished step as `completed` and the next step you are working on as `in_progress`. There should always be exactly one `in_progress` step until everything is done. You can mark multiple items as complete in a single `todowrite` call.\n\nIf all steps are complete, ensure you call `todowrite` to mark all steps as `completed`.\n\nIMPORTANT: Before you begin work, think about what the code you're editing is supposed to do based on the filenames and directory structure.\n\n# AGENTS.md spec\n\n- Repos often contain AGENTS.md files. These files can appear anywhere within the repository.\n- These files are a way for humans to give you (the agent) instructions or tips for working within the container.\n- Some examples might be: coding conventions, info about how code is organized, or instructions for how to run or test code.\n- Instructions in AGENTS.md files:\n - The scope of an AGENTS.md file is the entire directory tree rooted at the folder that contains it.\n - For every file you touch in the final change, you must obey instructions in any AGENTS.md file whose scope includes that file.\n - Instructions about code style, structure, naming, etc. apply only to code within the AGENTS.md file's scope, unless the file states otherwise.\n - More-deeply-nested AGENTS.md files take precedence in the case of conflicting instructions.\n - Direct system/developer/user instructions (as part of a prompt) take precedence over AGENTS.md instructions.\n- The contents of the AGENTS.md file at the root of the repo and the project directory are loaded into your context automatically and don't need to be re-read. AGENTS.md files in subdirectories are NOT loaded automatically: when working in a subdirectory, or a directory outside the CWD, check for any AGENTS.md files that may be applicable.\n\n# Permissions and safety\n\n- Never commit secrets or keys.\n- Never create a git commit unless the user explicitly asks.\n- Do not run destructive commands (mass delete, force-push, hard reset) unless the user clearly requested them.\n";
@@ -41321,10 +41261,10 @@ var require_tar_stream = __commonJS({
41321
41261
  var init_dist = __esm({
41322
41262
  "../agent-core/dist/index.js"() {
41323
41263
  "use strict";
41324
- init_chunk_2KE6BVIX();
41264
+ init_chunk_BVWCFGFG();
41325
41265
  init_chunk_OUQ7HMD3();
41326
41266
  init_chunk_R32NAS3B();
41327
- init_chunk_VZIZDY3T();
41267
+ init_chunk_NDAB5G24();
41328
41268
  init_chunk_YXWJW7I5();
41329
41269
  }
41330
41270
  });
@@ -41416,7 +41356,7 @@ function within(root, path4) {
41416
41356
  }
41417
41357
  async function resolveReal(path4) {
41418
41358
  try {
41419
- return await (0, import_promises45.realpath)(path4);
41359
+ return await (0, import_promises46.realpath)(path4);
41420
41360
  } catch {
41421
41361
  const parent = (0, import_path9.dirname)(path4);
41422
41362
  if (parent === path4) return path4;
@@ -41445,14 +41385,14 @@ function createWorkspaceFs(roots, writable) {
41445
41385
  return {
41446
41386
  read: async (params) => {
41447
41387
  const path4 = await confined(params);
41448
- const bytes = await (0, import_promises45.readFile)(path4);
41388
+ const bytes = await (0, import_promises46.readFile)(path4);
41449
41389
  if (bytes.byteLength > MAX_READ_BYTES) throw new FsDenied(`${path4} is too large to read`);
41450
41390
  return { content: sliceLines(bytes.toString("utf8"), params) };
41451
41391
  },
41452
41392
  write: async (params) => {
41453
41393
  if (!writable) throw new FsDenied("This session is read-only");
41454
41394
  const path4 = await confined(params);
41455
- await (0, import_promises45.writeFile)(path4, asString(params.content));
41395
+ await (0, import_promises46.writeFile)(path4, asString(params.content));
41456
41396
  return {};
41457
41397
  }
41458
41398
  };
@@ -41997,7 +41937,7 @@ function isAcpBackendKind(value2) {
41997
41937
  return Object.hasOwn(ACP_PROFILES, value2);
41998
41938
  }
41999
41939
  function envDigest3(env) {
42000
- const hash2 = (0, import_crypto11.createHash)("sha256");
41940
+ const hash2 = (0, import_crypto12.createHash)("sha256");
42001
41941
  for (const key of Object.keys(env).sort()) hash2.update(`${key}\0${env[key]}\0`);
42002
41942
  return hash2.digest("hex");
42003
41943
  }
@@ -42055,7 +41995,7 @@ async function acpTurnInput(run2, context) {
42055
41995
  const encoded = await Promise.all(
42056
41996
  images.map(async (image) => ({
42057
41997
  mimeType: image.mimeType,
42058
- data: (await (0, import_promises46.readFile)(image.path)).toString("base64")
41998
+ data: (await (0, import_promises47.readFile)(image.path)).toString("base64")
42059
41999
  }))
42060
42000
  );
42061
42001
  return {
@@ -42064,23 +42004,23 @@ async function acpTurnInput(run2, context) {
42064
42004
  ...encoded.length ? { images: encoded, imagePaths: images.map((image) => image.path) } : {}
42065
42005
  };
42066
42006
  }
42067
- var import_promises45, import_path9, import_crypto11, import_promises46, CURSOR_ASK_QUESTION, copilotAcpProfile, cursorAcpProfile, MODEL_REJECTED, MAX_READ_BYTES, FsDenied, ENV_REFERENCE, AcpBackgroundTasks, CURSOR_CREATE_PLAN, STATUSES, READ_KINDS, ALLOW_KINDS, REJECT_KINDS, CANCELLED_PERMISSION, STOP_REASONS, CHUNKS, ECHOES, AcpTurn, STDERR_TAIL_LINES4, MAX_BETWEEN_UPDATES2, AcpSession, DEFAULTS3, CLIENT_INFO2, TASK_BACKGROUNDED, TASK_COMPLETED, SESSION_NOTIFICATION, KILLED_STATUSES, SUCCESS_STATUSES, SUBAGENT_ID, grokTaskDialect, grokAcpProfile, kimiAcpProfile, ACP_PROFILES, ACP_MODES;
42007
+ var import_promises46, import_path9, import_crypto12, import_promises47, CURSOR_ASK_QUESTION, copilotAcpProfile, cursorAcpProfile, MODEL_REJECTED, MAX_READ_BYTES, FsDenied, ENV_REFERENCE, AcpBackgroundTasks, CURSOR_CREATE_PLAN, STATUSES, READ_KINDS, ALLOW_KINDS, REJECT_KINDS, CANCELLED_PERMISSION, STOP_REASONS, CHUNKS, ECHOES, AcpTurn, STDERR_TAIL_LINES4, MAX_BETWEEN_UPDATES2, AcpSession, DEFAULTS3, CLIENT_INFO2, TASK_BACKGROUNDED, TASK_COMPLETED, SESSION_NOTIFICATION, KILLED_STATUSES, SUCCESS_STATUSES, SUBAGENT_ID, grokTaskDialect, grokAcpProfile, kimiAcpProfile, ACP_PROFILES, ACP_MODES;
42068
42008
  var init_acp3 = __esm({
42069
42009
  "../agent-core/dist/providers/acp.js"() {
42070
42010
  "use strict";
42071
- init_chunk_2KE6BVIX();
42011
+ init_chunk_BVWCFGFG();
42072
42012
  init_chunk_OUQ7HMD3();
42073
42013
  init_chunk_R32NAS3B();
42074
42014
  init_chunk_J2KTV5FP();
42075
- init_chunk_VZIZDY3T();
42076
- init_chunk_NADPTUUJ();
42015
+ init_chunk_NDAB5G24();
42016
+ init_chunk_GXBS4QWA();
42077
42017
  init_chunk_YXWJW7I5();
42078
- import_promises45 = require("fs/promises");
42018
+ import_promises46 = require("fs/promises");
42079
42019
  import_path9 = require("path");
42080
42020
  init_effort();
42081
42021
  init_acp();
42082
- import_crypto11 = require("crypto");
42083
- import_promises46 = require("fs/promises");
42022
+ import_crypto12 = require("crypto");
42023
+ import_promises47 = require("fs/promises");
42084
42024
  init_agent2();
42085
42025
  CURSOR_ASK_QUESTION = "cursor/ask_question";
42086
42026
  copilotAcpProfile = {
@@ -43604,7 +43544,7 @@ function createOpenCodeDriver(options = {}) {
43604
43544
  await authorization?.remove();
43605
43545
  };
43606
43546
  const spec = { ...planned, env: launchEnv(planned, authorization) };
43607
- const password = options.password?.() ?? (0, import_crypto12.randomBytes)(24).toString("base64url");
43547
+ const password = options.password?.() ?? (0, import_crypto13.randomBytes)(24).toString("base64url");
43608
43548
  const attempt2 = { abandoned: false };
43609
43549
  const { session, url: url3 } = await withDeadline3(
43610
43550
  startServer(spec, password, resolved, attempt2),
@@ -43648,7 +43588,7 @@ function createOpenCodeDriver(options = {}) {
43648
43588
  };
43649
43589
  }
43650
43590
  function envDigest4(env) {
43651
- const hash2 = (0, import_crypto13.createHash)("sha256");
43591
+ const hash2 = (0, import_crypto14.createHash)("sha256");
43652
43592
  for (const key of Object.keys(env).sort()) hash2.update(`${key}\0${env[key]}\0`);
43653
43593
  return hash2.digest("hex");
43654
43594
  }
@@ -43728,25 +43668,25 @@ function openCodeTurnInput(run2, context) {
43728
43668
  ...images.length ? { imagePaths: images.map((image) => image.path) } : {}
43729
43669
  };
43730
43670
  }
43731
- var import_http10, import_crypto12, import_path10, import_url2, import_crypto13, IDLE_SOCKET_MS3, OpenCodeHttpError, OpenCodeClient, OPENCODE_CONFIG_ENV, OPENCODE_ENGINE, TEXT_PARTS, STEP_PARTS, STOPPED_BY_USER, OpenCodeSubagents, NAMED_KINDS, OPENCODE_ABORTED_ERROR, PROVIDER_EVENT_META, TASK_TOOL_NAME, TASK_RESULT_TAG, TASK_ERROR_TAG, PERMISSION_DENIED, FILE_OPERATIONS2, PartReader, NOTHING, NON_INTERACTIVE_PERMISSIONS, CONTENT_FILTER_FINISHES, OUTPUT_PARTS, OpenCodeTurn, LISTENING, OUTPUT_TAIL_LINES, IMAGE_TYPES, OpenCodeSession, OPENCODE_MIN_VERSION, OPENCODE_REQUIREMENT, OPENCODE_TESTED_LINE, OPENCODE_SUPPORTED_MAJOR, DEFAULTS4, STORE_LOCKED, NON_INTERACTIVE_RULES, TITLE_LENGTH, MAX_VARIANT_LENGTH;
43671
+ var import_http10, import_crypto13, import_path10, import_url2, import_crypto14, IDLE_SOCKET_MS3, OpenCodeHttpError, OpenCodeClient, OPENCODE_CONFIG_ENV, OPENCODE_ENGINE, TEXT_PARTS, STEP_PARTS, STOPPED_BY_USER, OpenCodeSubagents, NAMED_KINDS, OPENCODE_ABORTED_ERROR, PROVIDER_EVENT_META, TASK_TOOL_NAME, TASK_RESULT_TAG, TASK_ERROR_TAG, PERMISSION_DENIED, FILE_OPERATIONS2, PartReader, NOTHING, NON_INTERACTIVE_PERMISSIONS, CONTENT_FILTER_FINISHES, OUTPUT_PARTS, OpenCodeTurn, LISTENING, OUTPUT_TAIL_LINES, IMAGE_TYPES, OpenCodeSession, OPENCODE_MIN_VERSION, OPENCODE_REQUIREMENT, OPENCODE_TESTED_LINE, OPENCODE_SUPPORTED_MAJOR, DEFAULTS4, STORE_LOCKED, NON_INTERACTIVE_RULES, TITLE_LENGTH, MAX_VARIANT_LENGTH;
43732
43672
  var init_opencode = __esm({
43733
43673
  "../agent-core/dist/providers/opencode.js"() {
43734
43674
  "use strict";
43735
- init_chunk_2KE6BVIX();
43675
+ init_chunk_BVWCFGFG();
43736
43676
  init_chunk_OUQ7HMD3();
43737
43677
  init_chunk_R32NAS3B();
43738
43678
  init_chunk_J2KTV5FP();
43739
- init_chunk_VZIZDY3T();
43740
- init_chunk_NADPTUUJ();
43679
+ init_chunk_NDAB5G24();
43680
+ init_chunk_GXBS4QWA();
43741
43681
  init_chunk_YXWJW7I5();
43742
43682
  import_http10 = require("http");
43743
43683
  init_runtime_v2();
43744
- import_crypto12 = require("crypto");
43684
+ import_crypto13 = require("crypto");
43745
43685
  init_agent2();
43746
43686
  import_path10 = require("path");
43747
43687
  import_url2 = require("url");
43748
43688
  init_acp();
43749
- import_crypto13 = require("crypto");
43689
+ import_crypto14 = require("crypto");
43750
43690
  init_agent2();
43751
43691
  IDLE_SOCKET_MS3 = 4e3;
43752
43692
  OpenCodeHttpError = class extends Error {
@@ -45427,7 +45367,7 @@ function createDroidDriver(options = {}) {
45427
45367
  };
45428
45368
  }
45429
45369
  function envDigest5(env) {
45430
- const hash2 = (0, import_crypto14.createHash)("sha256");
45370
+ const hash2 = (0, import_crypto15.createHash)("sha256");
45431
45371
  for (const key of Object.keys(env).sort()) hash2.update(`${key}\0${env[key]}\0`);
45432
45372
  return hash2.digest("hex");
45433
45373
  }
@@ -45482,25 +45422,25 @@ async function droidTurnInput(run2, context) {
45482
45422
  const encoded = await Promise.all(
45483
45423
  images.map(async (image) => ({
45484
45424
  mimeType: image.mimeType,
45485
- data: (await (0, import_promises47.readFile)(image.path)).toString("base64")
45425
+ data: (await (0, import_promises48.readFile)(image.path)).toString("base64")
45486
45426
  }))
45487
45427
  );
45488
45428
  return { turnId: run2.runId, text: text2, ...encoded.length ? { images: encoded } : {} };
45489
45429
  }
45490
- var import_crypto14, import_promises47, FACTORY_API_VERSION, FACTORY_PROTOCOL_VERSION, SUBAGENT_TOOLS, TASK_OUTPUT_TOOLS, TASK_STOP_TOOLS, SILENT2, DroidTurn, STDERR_TAIL_LINES5, UNSUPPORTED_REQUEST2, DroidSession, DEFAULTS5, DROID_REQUIREMENT, DROID_JSONRPC_ARGS;
45430
+ var import_crypto15, import_promises48, FACTORY_API_VERSION, FACTORY_PROTOCOL_VERSION, SUBAGENT_TOOLS, TASK_OUTPUT_TOOLS, TASK_STOP_TOOLS, SILENT2, DroidTurn, STDERR_TAIL_LINES5, UNSUPPORTED_REQUEST2, DroidSession, DEFAULTS5, DROID_REQUIREMENT, DROID_JSONRPC_ARGS;
45491
45431
  var init_droid = __esm({
45492
45432
  "../agent-core/dist/providers/droid.js"() {
45493
45433
  "use strict";
45494
- init_chunk_2KE6BVIX();
45434
+ init_chunk_BVWCFGFG();
45495
45435
  init_chunk_OUQ7HMD3();
45496
45436
  init_chunk_R32NAS3B();
45497
45437
  init_chunk_J2KTV5FP();
45498
- init_chunk_VZIZDY3T();
45499
- init_chunk_NADPTUUJ();
45438
+ init_chunk_NDAB5G24();
45439
+ init_chunk_GXBS4QWA();
45500
45440
  init_chunk_YXWJW7I5();
45501
45441
  init_runtime_v2();
45502
- import_crypto14 = require("crypto");
45503
- import_promises47 = require("fs/promises");
45442
+ import_crypto15 = require("crypto");
45443
+ import_promises48 = require("fs/promises");
45504
45444
  init_agent2();
45505
45445
  FACTORY_API_VERSION = "1.0.0";
45506
45446
  FACTORY_PROTOCOL_VERSION = "1.187.0";
@@ -46005,7 +45945,7 @@ function antigravityArgs(input2, capabilities, prompt) {
46005
45945
  }
46006
45946
  function workspaceRoot(cwd) {
46007
45947
  for (let current = (0, import_path11.resolve)(cwd); ; current = (0, import_path11.dirname)(current)) {
46008
- if ((0, import_fs7.existsSync)((0, import_path11.join)(current, ".git"))) return current;
45948
+ if ((0, import_fs8.existsSync)((0, import_path11.join)(current, ".git"))) return current;
46009
45949
  if ((0, import_path11.dirname)(current) === current) return (0, import_path11.resolve)(cwd);
46010
45950
  }
46011
45951
  }
@@ -46015,7 +45955,7 @@ function instructionPaths(cwd) {
46015
45955
  for (let current = (0, import_path11.resolve)(cwd); ; current = (0, import_path11.dirname)(current)) {
46016
45956
  const path4 = (0, import_path11.join)(current, INSTRUCTIONS_FILE);
46017
45957
  try {
46018
- if ((0, import_fs7.existsSync)(path4) && (0, import_fs7.statSync)(path4).isFile()) paths.unshift(path4);
45958
+ if ((0, import_fs8.existsSync)(path4) && (0, import_fs8.statSync)(path4).isFile()) paths.unshift(path4);
46019
45959
  } catch {
46020
45960
  }
46021
45961
  if (current === root || (0, import_path11.dirname)(current) === current) return paths;
@@ -46029,7 +45969,7 @@ function antigravityWorkspaceInstructions(cwd, maxChars = MAX_INSTRUCTION_CHARS)
46029
45969
  if (remaining <= 0) break;
46030
45970
  let content;
46031
45971
  try {
46032
- content = (0, import_fs7.readFileSync)(path4, "utf8").trim();
45972
+ content = (0, import_fs8.readFileSync)(path4, "utf8").trim();
46033
45973
  } catch {
46034
45974
  continue;
46035
45975
  }
@@ -46510,7 +46450,7 @@ ${output2.stderr}`).join("\n")
46510
46450
  };
46511
46451
  }
46512
46452
  function envDigest6(env) {
46513
- const hash2 = (0, import_crypto15.createHash)("sha256");
46453
+ const hash2 = (0, import_crypto16.createHash)("sha256");
46514
46454
  for (const key of Object.keys(env).sort()) hash2.update(`${key}\0${env[key]}\0`);
46515
46455
  return hash2.digest("hex");
46516
46456
  }
@@ -46556,23 +46496,23 @@ function antigravityTurnInput(run2, context) {
46556
46496
  });
46557
46497
  return { turnId: run2.runId, text: appendImagePathReferences(text2, images) };
46558
46498
  }
46559
- var import_fs7, import_path11, import_path12, import_url3, import_crypto15, NO_ANTIGRAVITY_CAPABILITIES, INSTRUCTIONS_FILE, MAX_INSTRUCTION_CHARS, SHORTENED_NOTE, DIFF_BLOCK_START, DIFF_BLOCK_END, HUNK_HEADER, TRANSCRIPT_FILE, FULL_TRANSCRIPT_FILE, LOG_DIRS, TOOL_RESULT_TYPES, BrainTranscript, AntigravityTranscripts, ANTIGRAVITY_GRAMMAR_NAME, AntigravityGrammar, ignored, HANDLERS, SUCCESSFUL_STATUSES, SESSION_START_TYPES, RESULT_TYPES, SUBAGENT_START_TYPES, RESUME_FORKED, AntigravityTurn, DEFAULTS6, AntigravitySession, WINDOWS_LINE_MARGIN;
46499
+ var import_fs8, import_path11, import_path12, import_url3, import_crypto16, NO_ANTIGRAVITY_CAPABILITIES, INSTRUCTIONS_FILE, MAX_INSTRUCTION_CHARS, SHORTENED_NOTE, DIFF_BLOCK_START, DIFF_BLOCK_END, HUNK_HEADER, TRANSCRIPT_FILE, FULL_TRANSCRIPT_FILE, LOG_DIRS, TOOL_RESULT_TYPES, BrainTranscript, AntigravityTranscripts, ANTIGRAVITY_GRAMMAR_NAME, AntigravityGrammar, ignored, HANDLERS, SUCCESSFUL_STATUSES, SESSION_START_TYPES, RESULT_TYPES, SUBAGENT_START_TYPES, RESUME_FORKED, AntigravityTurn, DEFAULTS6, AntigravitySession, WINDOWS_LINE_MARGIN;
46560
46500
  var init_antigravity = __esm({
46561
46501
  "../agent-core/dist/providers/antigravity.js"() {
46562
46502
  "use strict";
46563
46503
  init_chunk_LR52JUGL();
46564
- init_chunk_2KE6BVIX();
46504
+ init_chunk_BVWCFGFG();
46565
46505
  init_chunk_OUQ7HMD3();
46566
46506
  init_chunk_R32NAS3B();
46567
- init_chunk_VZIZDY3T();
46568
- init_chunk_NADPTUUJ();
46507
+ init_chunk_NDAB5G24();
46508
+ init_chunk_GXBS4QWA();
46569
46509
  init_chunk_YXWJW7I5();
46570
- import_fs7 = require("fs");
46510
+ import_fs8 = require("fs");
46571
46511
  import_path11 = require("path");
46572
46512
  init_effort();
46573
46513
  import_path12 = require("path");
46574
46514
  import_url3 = require("url");
46575
- import_crypto15 = require("crypto");
46515
+ import_crypto16 = require("crypto");
46576
46516
  init_agent2();
46577
46517
  NO_ANTIGRAVITY_CAPABILITIES = {
46578
46518
  structuredPrint: false,
@@ -47058,7 +46998,7 @@ function parseConfig(raw) {
47058
46998
  }
47059
46999
  async function writeCommandCodeProjectMcp(cwd, mcp) {
47060
47000
  const path4 = (0, import_path13.join)(cwd, ".mcp.json");
47061
- const original = await (0, import_promises48.readFile)(path4, "utf8").catch(() => null);
47001
+ const original = await (0, import_promises49.readFile)(path4, "utf8").catch(() => null);
47062
47002
  const config2 = parseConfig(original);
47063
47003
  const next = {
47064
47004
  ...config2,
@@ -47075,12 +47015,12 @@ async function writeCommandCodeProjectMcp(cwd, mcp) {
47075
47015
  }
47076
47016
  }
47077
47017
  };
47078
- await (0, import_promises48.mkdir)(cwd, { recursive: true });
47079
- await (0, import_promises48.writeFile)(path4, `${JSON.stringify(next, null, 2)}
47018
+ await (0, import_promises49.mkdir)(cwd, { recursive: true });
47019
+ await (0, import_promises49.writeFile)(path4, `${JSON.stringify(next, null, 2)}
47080
47020
  `);
47081
47021
  return async () => {
47082
- if (original === null) await (0, import_promises48.rm)(path4, { force: true });
47083
- else await (0, import_promises48.writeFile)(path4, original);
47022
+ if (original === null) await (0, import_promises49.rm)(path4, { force: true });
47023
+ else await (0, import_promises49.writeFile)(path4, original);
47084
47024
  };
47085
47025
  }
47086
47026
  function commandCodeString(value2) {
@@ -47189,7 +47129,7 @@ function createCommandCodeDriver(options = {}) {
47189
47129
  };
47190
47130
  }
47191
47131
  function envDigest7(env) {
47192
- const hash2 = (0, import_crypto16.createHash)("sha256");
47132
+ const hash2 = (0, import_crypto17.createHash)("sha256");
47193
47133
  for (const key of Object.keys(env).sort()) hash2.update(`${key}\0${env[key]}\0`);
47194
47134
  return hash2.digest("hex");
47195
47135
  }
@@ -47241,22 +47181,22 @@ function commandCodeTurnInput(run2, context) {
47241
47181
  });
47242
47182
  return { turnId: run2.runId, text: appendImagePathReferences(text2, images) };
47243
47183
  }
47244
- var import_promises48, import_path13, import_crypto16, COMMAND_CODE_GRAMMAR_NAME, SILENT3, CommandCodeGrammar, CommandCodeTurn, COMMAND_CODE_MAX_TURNS, DEFAULTS7, CommandCodeSession;
47184
+ var import_promises49, import_path13, import_crypto17, COMMAND_CODE_GRAMMAR_NAME, SILENT3, CommandCodeGrammar, CommandCodeTurn, COMMAND_CODE_MAX_TURNS, DEFAULTS7, CommandCodeSession;
47245
47185
  var init_command_code = __esm({
47246
47186
  "../agent-core/dist/providers/command-code.js"() {
47247
47187
  "use strict";
47248
- init_chunk_2KE6BVIX();
47188
+ init_chunk_BVWCFGFG();
47249
47189
  init_chunk_OUQ7HMD3();
47250
47190
  init_chunk_R32NAS3B();
47251
47191
  init_chunk_J2KTV5FP();
47252
- init_chunk_VZIZDY3T();
47253
- init_chunk_NADPTUUJ();
47192
+ init_chunk_NDAB5G24();
47193
+ init_chunk_GXBS4QWA();
47254
47194
  init_chunk_YXWJW7I5();
47255
- import_promises48 = require("fs/promises");
47195
+ import_promises49 = require("fs/promises");
47256
47196
  import_path13 = require("path");
47257
47197
  init_agent2();
47258
47198
  init_runtime_v2();
47259
- import_crypto16 = require("crypto");
47199
+ import_crypto17 = require("crypto");
47260
47200
  init_agent2();
47261
47201
  COMMAND_CODE_GRAMMAR_NAME = "command_code_cli";
47262
47202
  SILENT3 = /* @__PURE__ */ new Set([
@@ -52445,7 +52385,7 @@ var require_websocket_server = __commonJS({
52445
52385
  // package.json
52446
52386
  var package_default = {
52447
52387
  name: "@alan-ai-hq/agent-manager",
52448
- version: "0.1.128",
52388
+ version: "0.1.130",
52449
52389
  private: true,
52450
52390
  type: "module",
52451
52391
  description: "Alan machine runtime (alan-agent): identity, link, reconciler, session holders, run log, uploader, local API",
@@ -52492,7 +52432,7 @@ var package_default = {
52492
52432
 
52493
52433
  // src/cli/commands/compat.ts
52494
52434
  var import_node_crypto25 = require("crypto");
52495
- var import_promises58 = require("fs/promises");
52435
+ var import_promises59 = require("fs/promises");
52496
52436
  init_runtime_v2();
52497
52437
  init_zod();
52498
52438
 
@@ -54507,7 +54447,7 @@ async function push(context, request2) {
54507
54447
  var import_node_child_process = require("child_process");
54508
54448
 
54509
54449
  // ../agent-core/dist/process.js
54510
- init_chunk_VZIZDY3T();
54450
+ init_chunk_NDAB5G24();
54511
54451
  init_chunk_YXWJW7I5();
54512
54452
 
54513
54453
  // src/capabilities/git/run-git.ts
@@ -54793,7 +54733,7 @@ var import_node_net = require("net");
54793
54733
 
54794
54734
  // src/platform/credential-store/credential-store.ts
54795
54735
  var import_node_crypto4 = require("crypto");
54796
- var import_promises10 = require("fs/promises");
54736
+ var import_promises11 = require("fs/promises");
54797
54737
 
54798
54738
  // src/platform/credential-store/parse.ts
54799
54739
  function parseStoredJson(text2, schema) {
@@ -54942,7 +54882,7 @@ function createFileCredentialStore(path4) {
54942
54882
  kind: "file",
54943
54883
  read: (schema) => readJsonFile(path4, schema),
54944
54884
  write: (value2) => writeJsonFileAtomic(path4, value2),
54945
- clear: () => (0, import_promises10.rm)(path4, { force: true })
54885
+ clear: () => (0, import_promises11.rm)(path4, { force: true })
54946
54886
  };
54947
54887
  }
54948
54888
  var KEYCHAIN_SERVICE = "ai.tryalan.runtime";
@@ -55037,14 +54977,14 @@ function defaultCredentialStoreKind(platform3) {
55037
54977
  var import_node_child_process3 = require("child_process");
55038
54978
  var import_node_crypto5 = require("crypto");
55039
54979
  var import_node_fs3 = require("fs");
55040
- var import_promises12 = require("fs/promises");
54980
+ var import_promises13 = require("fs/promises");
55041
54981
  var import_node_path7 = require("path");
55042
54982
  var import_node_util2 = require("util");
55043
54983
  init_zod();
55044
54984
 
55045
54985
  // src/platform/process-identity.ts
55046
54986
  var import_node_child_process2 = require("child_process");
55047
- var import_promises11 = require("fs/promises");
54987
+ var import_promises12 = require("fs/promises");
55048
54988
  var import_node_util = require("util");
55049
54989
  var execFileAsync = (0, import_node_util.promisify)(import_node_child_process2.execFile);
55050
54990
  function isProcessAlive(pid) {
@@ -55056,13 +54996,13 @@ function isProcessAlive(pid) {
55056
54996
  }
55057
54997
  }
55058
54998
  async function linuxStartTime(pid) {
55059
- const stat19 = await (0, import_promises11.readFile)(`/proc/${pid}/stat`, "utf8").catch(() => null);
54999
+ const stat19 = await (0, import_promises12.readFile)(`/proc/${pid}/stat`, "utf8").catch(() => null);
55060
55000
  if (stat19 === null) return null;
55061
55001
  const fields = stat19.slice(stat19.lastIndexOf(")") + 2).split(" ");
55062
55002
  return fields[19] ?? null;
55063
55003
  }
55064
55004
  async function linuxCommand(pid) {
55065
- const raw = await (0, import_promises11.readFile)(`/proc/${pid}/cmdline`, "utf8").catch(() => null);
55005
+ const raw = await (0, import_promises12.readFile)(`/proc/${pid}/cmdline`, "utf8").catch(() => null);
55066
55006
  return raw === null ? null : normalizeCommand(raw.replaceAll("\0", " "));
55067
55007
  }
55068
55008
  async function darwinCommand(pid) {
@@ -55252,23 +55192,23 @@ async function reportedVersion(versionDir) {
55252
55192
  return stdout.trim();
55253
55193
  }
55254
55194
  async function switchLauncher(layout, version2) {
55255
- await (0, import_promises12.mkdir)(layout.bin, { recursive: true, mode: 448 });
55195
+ await (0, import_promises13.mkdir)(layout.bin, { recursive: true, mode: 448 });
55256
55196
  const staged = (0, import_node_path7.join)(layout.bin, `.${(0, import_node_path7.basename)(layout.launcher)}.${(0, import_node_crypto5.randomUUID)()}`);
55257
55197
  if (process.platform === "win32") {
55258
55198
  (0, import_node_fs3.writeFileSync)(staged, `@"%~dp0..\\versions\\${version2}\\alan-agent.cmd" %*\r
55259
55199
  `);
55260
55200
  } else {
55261
- await (0, import_promises12.symlink)((0, import_node_path7.join)("..", "versions", version2, "alan-agent"), staged);
55201
+ await (0, import_promises13.symlink)((0, import_node_path7.join)("..", "versions", version2, "alan-agent"), staged);
55262
55202
  }
55263
- await (0, import_promises12.rename)(staged, layout.launcher);
55203
+ await (0, import_promises13.rename)(staged, layout.launcher);
55264
55204
  }
55265
55205
  async function launcherVersion(launcher) {
55266
55206
  try {
55267
55207
  if (process.platform === "win32") {
55268
- const match = /versions\\([^\\]+)\\/.exec(await (0, import_promises12.readFile)(launcher, "utf8"));
55208
+ const match = /versions\\([^\\]+)\\/.exec(await (0, import_promises13.readFile)(launcher, "utf8"));
55269
55209
  return match?.[1] ?? null;
55270
55210
  }
55271
- return (0, import_node_path7.basename)((0, import_node_path7.dirname)(await (0, import_promises12.readlink)(launcher)));
55211
+ return (0, import_node_path7.basename)((0, import_node_path7.dirname)(await (0, import_promises13.readlink)(launcher)));
55272
55212
  } catch (error61) {
55273
55213
  if (errnoCode(error61) === "ENOENT") return null;
55274
55214
  throw error61;
@@ -55279,7 +55219,7 @@ function currentVersion(layout) {
55279
55219
  }
55280
55220
  async function launcherVersions(layout) {
55281
55221
  const versions = [];
55282
- for (const name of await (0, import_promises12.readdir)(layout.bin).catch(() => [])) {
55222
+ for (const name of await (0, import_promises13.readdir)(layout.bin).catch(() => [])) {
55283
55223
  if (!name.startsWith(LAUNCHER_STEM)) continue;
55284
55224
  const version2 = await launcherVersion((0, import_node_path7.join)(layout.bin, name)).catch(() => null);
55285
55225
  if (version2 !== null) versions.push(version2);
@@ -55311,7 +55251,7 @@ function assertUsableVersion(version2) {
55311
55251
  }
55312
55252
  }
55313
55253
  async function exists(path4) {
55314
- return (0, import_promises12.stat)(path4).then(
55254
+ return (0, import_promises13.stat)(path4).then(
55315
55255
  () => true,
55316
55256
  () => false
55317
55257
  );
@@ -55322,7 +55262,7 @@ function isVersionInstalled(layout, version2) {
55322
55262
  async function stageVersion(layout, sourceDir, expectedVersion) {
55323
55263
  var _stack = [];
55324
55264
  try {
55325
- await (0, import_promises12.mkdir)(layout.versions, { recursive: true, mode: 448 });
55265
+ await (0, import_promises13.mkdir)(layout.versions, { recursive: true, mode: 448 });
55326
55266
  const _lock = __using(_stack, takeInstallLock(layout.lock));
55327
55267
  const version2 = await readPackageVersion(sourceDir);
55328
55268
  if (expectedVersion !== void 0 && version2 !== expectedVersion) {
@@ -55335,17 +55275,17 @@ async function stageVersion(layout, sourceDir, expectedVersion) {
55335
55275
  const target = (0, import_node_path7.join)(layout.versions, version2);
55336
55276
  if (await exists(target)) return version2;
55337
55277
  const staging = (0, import_node_path7.join)(layout.versions, `.${version2}`);
55338
- await (0, import_promises12.rm)(staging, { recursive: true, force: true });
55278
+ await (0, import_promises13.rm)(staging, { recursive: true, force: true });
55339
55279
  try {
55340
- await (0, import_promises12.cp)(sourceDir, staging, { recursive: true });
55280
+ await (0, import_promises13.cp)(sourceDir, staging, { recursive: true });
55341
55281
  if (await reportedVersion(staging) !== version2) {
55342
55282
  throw new RuntimeFault("invalid_file", `Staged runtime ${version2} does not start`);
55343
55283
  }
55344
55284
  } catch (error61) {
55345
- await (0, import_promises12.rm)(staging, { recursive: true, force: true });
55285
+ await (0, import_promises13.rm)(staging, { recursive: true, force: true });
55346
55286
  throw error61;
55347
55287
  }
55348
- await (0, import_promises12.rename)(staging, target);
55288
+ await (0, import_promises13.rename)(staging, target);
55349
55289
  return version2;
55350
55290
  } catch (_) {
55351
55291
  var _error = _, _hasError = true;
@@ -55362,19 +55302,19 @@ async function installVersion(layout, sourceDir) {
55362
55302
  async function hasLiveMarker(versionDir) {
55363
55303
  const markers = (0, import_node_path7.join)(versionDir, ".running");
55364
55304
  let live = false;
55365
- for (const name of await (0, import_promises12.readdir)(markers).catch(() => [])) {
55305
+ for (const name of await (0, import_promises13.readdir)(markers).catch(() => [])) {
55366
55306
  if (isProcessAlive(Number(name))) live = true;
55367
- else await (0, import_promises12.rm)((0, import_node_path7.join)(markers, name), { force: true });
55307
+ else await (0, import_promises13.rm)((0, import_node_path7.join)(markers, name), { force: true });
55368
55308
  }
55369
55309
  return live;
55370
55310
  }
55371
55311
  async function collectOldVersions(layout) {
55372
- const entries = await (0, import_promises12.readdir)(layout.versions, { withFileTypes: true }).catch(() => []);
55312
+ const entries = await (0, import_promises13.readdir)(layout.versions, { withFileTypes: true }).catch(() => []);
55373
55313
  const versions = await Promise.all(
55374
55314
  entries.filter((entry) => entry.isDirectory() && !entry.name.startsWith(".")).map(async (entry) => ({
55375
55315
  name: entry.name,
55376
55316
  // The launcher, not the directory: `.running` markers touch the directory's mtime.
55377
- installedAtMs: (await (0, import_promises12.stat)(launcherIn((0, import_node_path7.join)(layout.versions, entry.name)))).mtimeMs
55317
+ installedAtMs: (await (0, import_promises13.stat)(launcherIn((0, import_node_path7.join)(layout.versions, entry.name)))).mtimeMs
55378
55318
  }))
55379
55319
  );
55380
55320
  const keep = new Set(
@@ -55385,7 +55325,7 @@ async function collectOldVersions(layout) {
55385
55325
  for (const { name } of versions) {
55386
55326
  const dir = (0, import_node_path7.join)(layout.versions, name);
55387
55327
  if (keep.has(name) || await hasLiveMarker(dir)) continue;
55388
- await (0, import_promises12.rm)(dir, { recursive: true, force: true });
55328
+ await (0, import_promises13.rm)(dir, { recursive: true, force: true });
55389
55329
  removed.push(name);
55390
55330
  }
55391
55331
  return removed;
@@ -55409,7 +55349,7 @@ function markVersionInUse(bundlePath) {
55409
55349
 
55410
55350
  // src/platform/instance-lock.ts
55411
55351
  var import_node_fs4 = require("fs");
55412
- var import_promises13 = require("fs/promises");
55352
+ var import_promises14 = require("fs/promises");
55413
55353
  var import_node_path8 = require("path");
55414
55354
  init_zod();
55415
55355
  var LOCK_POLL_MS = 100;
@@ -55466,7 +55406,7 @@ async function attempt(path4, self, probe) {
55466
55406
  return tryCreate(path4, self) ? { kind: "acquired" } : attempt(path4, self, probe);
55467
55407
  }
55468
55408
  async function acquireInstanceLock(path4, { clock, waitMs, signal, probe = systemProcessProbe }) {
55469
- await (0, import_promises13.mkdir)((0, import_node_path8.dirname)(path4), { recursive: true, mode: 448 });
55409
+ await (0, import_promises14.mkdir)((0, import_node_path8.dirname)(path4), { recursive: true, mode: 448 });
55470
55410
  const self = await readProcessIdentity(process.pid);
55471
55411
  if (self === null) throw new RuntimeFault("internal", "Cannot read this process's identity");
55472
55412
  const deadline = clock.monotonic() + waitMs;
@@ -55497,13 +55437,15 @@ var import_node_os = require("os");
55497
55437
  var import_node_path9 = require("path");
55498
55438
  var MAX_SOCKET_PATH_BYTES = 100;
55499
55439
  function windowsPipeName(socketsDir, id) {
55500
- const scope = (0, import_node_crypto6.createHash)("sha256").update(socketsDir.toLowerCase()).digest("hex").slice(0, 12);
55501
- return `\\\\.\\pipe\\alan-${scope}-${id}`;
55440
+ return `\\\\.\\pipe\\alan-${socketsScope(socketsDir)}-${id}`;
55441
+ }
55442
+ function socketsScope(socketsDir) {
55443
+ return (0, import_node_crypto6.createHash)("sha256").update(socketsDir.toLowerCase()).digest("hex").slice(0, 12);
55502
55444
  }
55503
55445
  function ipcEndpoint(socketsDir, id, platform3 = process.platform) {
55504
55446
  if (platform3 === "win32") return windowsPipeName(socketsDir, id);
55505
55447
  const preferred = (0, import_node_path9.join)(socketsDir, `${id}.sock`);
55506
- const dir = Buffer.byteLength(preferred) <= MAX_SOCKET_PATH_BYTES ? socketsDir : (0, import_node_path9.join)("/tmp", `alan-${(0, import_node_os.userInfo)().uid}`);
55448
+ const dir = Buffer.byteLength(preferred) <= MAX_SOCKET_PATH_BYTES ? socketsDir : (0, import_node_path9.join)("/tmp", `alan-${(0, import_node_os.userInfo)().uid}-${socketsScope(socketsDir)}`);
55507
55449
  (0, import_node_fs5.mkdirSync)(dir, { recursive: true, mode: 448 });
55508
55450
  return (0, import_node_path9.join)(dir, `${id}.sock`);
55509
55451
  }
@@ -55620,13 +55562,13 @@ function runtimePaths(stateDir) {
55620
55562
 
55621
55563
  // src/platform/process-memory.ts
55622
55564
  var import_node_child_process4 = require("child_process");
55623
- var import_promises14 = require("fs/promises");
55565
+ var import_promises15 = require("fs/promises");
55624
55566
  var import_node_util3 = require("util");
55625
55567
  var execFileAsync3 = (0, import_node_util3.promisify)(import_node_child_process4.execFile);
55626
55568
  var PROBE_TIMEOUT_MS = 2e3;
55627
55569
  async function readProcessRss(pid) {
55628
55570
  if (process.platform === "linux") {
55629
- const status = await (0, import_promises14.readFile)(`/proc/${pid}/status`, "utf8").catch(() => null);
55571
+ const status = await (0, import_promises15.readFile)(`/proc/${pid}/status`, "utf8").catch(() => null);
55630
55572
  const kilobytes = status === null ? void 0 : /^VmRSS:\s+(\d+)\s+kB$/m.exec(status)?.[1];
55631
55573
  return kilobytes === void 0 ? null : Number(kilobytes) * 1024;
55632
55574
  }
@@ -55658,7 +55600,7 @@ async function darwinPressure() {
55658
55600
  var PSI_WARN_SOME_AVG10 = 20;
55659
55601
  var PSI_CRITICAL_FULL_AVG10 = 10;
55660
55602
  async function linuxPressure() {
55661
- const psi = await (0, import_promises14.readFile)("/proc/pressure/memory", "utf8").catch(() => null);
55603
+ const psi = await (0, import_promises15.readFile)("/proc/pressure/memory", "utf8").catch(() => null);
55662
55604
  if (psi === null) return "normal";
55663
55605
  const avg10 = (kind) => Number(new RegExp(`^${kind} avg10=([\\d.]+)`, "m").exec(psi)?.[1] ?? 0);
55664
55606
  if (avg10("full") >= PSI_CRITICAL_FULL_AVG10) return "critical";
@@ -55745,7 +55687,7 @@ function planUpdate(input2) {
55745
55687
  // src/platform/release-apply.ts
55746
55688
  var import_node_child_process5 = require("child_process");
55747
55689
  var import_node_crypto9 = require("crypto");
55748
- var import_promises15 = require("fs/promises");
55690
+ var import_promises16 = require("fs/promises");
55749
55691
  var import_node_path11 = require("path");
55750
55692
  var import_node_util4 = require("util");
55751
55693
  init_zod();
@@ -55769,7 +55711,7 @@ function npmReleaseFrom(bytes, request2) {
55769
55711
  return resolved.release;
55770
55712
  }
55771
55713
  async function extractPackageTarball(tarballPath, destination) {
55772
- await (0, import_promises15.mkdir)(destination, { recursive: true, mode: 448 });
55714
+ await (0, import_promises16.mkdir)(destination, { recursive: true, mode: 448 });
55773
55715
  await execFileAsync4("tar", ["-xzf", tarballPath, "-C", destination]);
55774
55716
  return (0, import_node_path11.join)(destination, "package");
55775
55717
  }
@@ -55782,14 +55724,14 @@ async function stageNpmTarball({
55782
55724
  const integrity = verifyNpmIntegrity(tarball, release2.dist);
55783
55725
  if (!integrity.ok) throw new RuntimeFault("invalid_file", integrity.reason);
55784
55726
  const scratch = (0, import_node_path11.join)(tmpDir, (0, import_node_crypto9.randomUUID)());
55785
- await (0, import_promises15.mkdir)(scratch, { recursive: true, mode: 448 });
55727
+ await (0, import_promises16.mkdir)(scratch, { recursive: true, mode: 448 });
55786
55728
  try {
55787
55729
  const tarballPath = (0, import_node_path11.join)(scratch, "package.tgz");
55788
- await (0, import_promises15.writeFile)(tarballPath, tarball, { mode: 384 });
55730
+ await (0, import_promises16.writeFile)(tarballPath, tarball, { mode: 384 });
55789
55731
  const packageDir = await extractPackageTarball(tarballPath, (0, import_node_path11.join)(scratch, "unpacked"));
55790
55732
  return await stageVersion(layout, packageDir, release2.version);
55791
55733
  } finally {
55792
- await (0, import_promises15.rm)(scratch, { recursive: true, force: true });
55734
+ await (0, import_promises16.rm)(scratch, { recursive: true, force: true });
55793
55735
  }
55794
55736
  }
55795
55737
  var pendingUpgradeSchema = external_exports.object({
@@ -55814,7 +55756,7 @@ async function recordPendingUpgrade(layout, from, to, now) {
55814
55756
  await writeJsonFileAtomic(layout.pendingUpgrade, { from, to, startedAt: now, starts: 0 });
55815
55757
  }
55816
55758
  async function clearPendingUpgrade(layout) {
55817
- await (0, import_promises15.rm)(layout.pendingUpgrade, { force: true });
55759
+ await (0, import_promises16.rm)(layout.pendingUpgrade, { force: true });
55818
55760
  }
55819
55761
  async function rollBackUpgrade(layout, pending, now) {
55820
55762
  const installed = await currentVersion(layout);
@@ -55846,7 +55788,7 @@ async function settlePendingUpgrade(layout, runningVersion, now) {
55846
55788
  }
55847
55789
 
55848
55790
  // src/platform/runtime-host.ts
55849
- var import_promises16 = require("fs/promises");
55791
+ var import_promises17 = require("fs/promises");
55850
55792
  var RUNTIME_HOST_KINDS = ["app", "standalone"];
55851
55793
  var APP_HOST_ENVIRONMENT = {
55852
55794
  ELECTRON_RUN_AS_NODE: "1"
@@ -55884,7 +55826,7 @@ function serviceCommand(kind, proc, launcher) {
55884
55826
  }
55885
55827
  async function fileStamp(path4) {
55886
55828
  try {
55887
- const stats = await (0, import_promises16.stat)(path4);
55829
+ const stats = await (0, import_promises17.stat)(path4);
55888
55830
  return `${stats.dev}:${stats.ino}:${stats.size}:${stats.mtimeMs}`;
55889
55831
  } catch {
55890
55832
  return null;
@@ -56078,11 +56020,11 @@ var systemExec = (request2) => new Promise((resolve10) => {
56078
56020
  });
56079
56021
 
56080
56022
  // src/platform/service/legacy.ts
56081
- var import_promises18 = require("fs/promises");
56023
+ var import_promises19 = require("fs/promises");
56082
56024
  var import_node_path15 = require("path");
56083
56025
 
56084
56026
  // src/platform/service/windows-service.ts
56085
- var import_promises17 = require("fs/promises");
56027
+ var import_promises18 = require("fs/promises");
56086
56028
  var import_node_path14 = require("path");
56087
56029
 
56088
56030
  // src/platform/service/runtime-process.ts
@@ -56290,7 +56232,7 @@ async function readUserSid(exec) {
56290
56232
  }
56291
56233
  async function readBytes(path4) {
56292
56234
  try {
56293
- return await (0, import_promises17.readFile)(path4);
56235
+ return await (0, import_promises18.readFile)(path4);
56294
56236
  } catch (error61) {
56295
56237
  if (errnoCode(error61) === "ENOENT") return null;
56296
56238
  throw error61;
@@ -56298,8 +56240,8 @@ async function readBytes(path4) {
56298
56240
  }
56299
56241
  async function writeIfChanged(path4, contents) {
56300
56242
  if ((await readBytes(path4))?.equals(contents) === true) return false;
56301
- await (0, import_promises17.mkdir)((0, import_node_path14.dirname)(path4), { recursive: true });
56302
- await (0, import_promises17.writeFile)(path4, contents);
56243
+ await (0, import_promises18.mkdir)((0, import_node_path14.dirname)(path4), { recursive: true });
56244
+ await (0, import_promises18.writeFile)(path4, contents);
56303
56245
  return true;
56304
56246
  }
56305
56247
  async function run(exec, request2) {
@@ -56381,7 +56323,7 @@ function windowsManager(host, profile) {
56381
56323
  name: files.runValue,
56382
56324
  definitionPath: files.script,
56383
56325
  install: async (spec, { restart }) => {
56384
- await (0, import_promises17.mkdir)((0, import_node_path14.dirname)(spec.logPath), { recursive: true });
56326
+ await (0, import_promises18.mkdir)((0, import_node_path14.dirname)(spec.logPath), { recursive: true });
56385
56327
  const script = renderWindowsSupervisorScript(spec, files);
56386
56328
  const xml2 = renderWindowsTaskXml({ spec, files, userSid: await userSid() });
56387
56329
  const scriptChanged = await writeIfChanged(
@@ -56422,7 +56364,7 @@ function windowsManager(host, profile) {
56422
56364
  const defined = await readBytes(files.script) !== null;
56423
56365
  await Promise.all(
56424
56366
  [files.script, files.taskXml, files.supervisorRecord].map(
56425
- (path4) => (0, import_promises17.rm)(path4, { force: true })
56367
+ (path4) => (0, import_promises18.rm)(path4, { force: true })
56426
56368
  )
56427
56369
  );
56428
56370
  return {
@@ -56474,7 +56416,7 @@ function legacyServiceNames(profile) {
56474
56416
  };
56475
56417
  }
56476
56418
  async function exists2(path4) {
56477
- return (0, import_promises18.stat)(path4).then(
56419
+ return (0, import_promises19.stat)(path4).then(
56478
56420
  () => true,
56479
56421
  () => false
56480
56422
  );
@@ -56485,7 +56427,7 @@ async function removeLaunchd(host, label) {
56485
56427
  const loaded = (await host.exec({ command: "launchctl", args: ["print", target] })).status === 0;
56486
56428
  if (loaded) await host.exec({ command: "launchctl", args: ["bootout", target] });
56487
56429
  const defined = await exists2(plist);
56488
- await (0, import_promises18.rm)(plist, { force: true });
56430
+ await (0, import_promises19.rm)(plist, { force: true });
56489
56431
  return { found: loaded || defined };
56490
56432
  }
56491
56433
  async function removeSystemd(exec, configHome, unit) {
@@ -56494,7 +56436,7 @@ async function removeSystemd(exec, configHome, unit) {
56494
56436
  const active = (await exec({ command: "systemctl", args: ["--user", "is-active", "--quiet", unit] })).status === 0;
56495
56437
  if (!defined && !active) return { found: false };
56496
56438
  await exec({ command: "systemctl", args: ["--user", "disable", "--now", unit] });
56497
- await (0, import_promises18.rm)(unitPath, { force: true });
56439
+ await (0, import_promises19.rm)(unitPath, { force: true });
56498
56440
  await exec({ command: "systemctl", args: ["--user", "daemon-reload"] });
56499
56441
  return { found: true };
56500
56442
  }
@@ -56521,15 +56463,15 @@ async function removeLegacyService(host, profile) {
56521
56463
  }
56522
56464
 
56523
56465
  // src/platform/service/service-manager.ts
56524
- var import_promises21 = require("fs/promises");
56466
+ var import_promises22 = require("fs/promises");
56525
56467
  var import_node_path18 = require("path");
56526
56468
 
56527
56469
  // src/platform/service/service-files.ts
56528
- var import_promises19 = require("fs/promises");
56470
+ var import_promises20 = require("fs/promises");
56529
56471
  var import_node_path16 = require("path");
56530
56472
  async function readText(path4) {
56531
56473
  try {
56532
- return await (0, import_promises19.readFile)(path4, "utf8");
56474
+ return await (0, import_promises20.readFile)(path4, "utf8");
56533
56475
  } catch (error61) {
56534
56476
  if (errnoCode(error61) === "ENOENT") return null;
56535
56477
  throw error61;
@@ -56537,15 +56479,15 @@ async function readText(path4) {
56537
56479
  }
56538
56480
  async function writeDefinition(path4, contents, mode = 420) {
56539
56481
  if (await readText(path4) === contents) return false;
56540
- await (0, import_promises19.mkdir)((0, import_node_path16.dirname)(path4), { recursive: true });
56482
+ await (0, import_promises20.mkdir)((0, import_node_path16.dirname)(path4), { recursive: true });
56541
56483
  const staged = `${path4}.${process.pid}.tmp`;
56542
- await (0, import_promises19.writeFile)(staged, contents, { mode });
56543
- await (0, import_promises19.rename)(staged, path4);
56484
+ await (0, import_promises20.writeFile)(staged, contents, { mode });
56485
+ await (0, import_promises20.rename)(staged, path4);
56544
56486
  return true;
56545
56487
  }
56546
56488
  async function removeDefinition(path4) {
56547
56489
  const existed = await readText(path4) !== null;
56548
- await (0, import_promises19.rm)(path4, { force: true });
56490
+ await (0, import_promises20.rm)(path4, { force: true });
56549
56491
  return existed;
56550
56492
  }
56551
56493
  async function runChecked(exec, request2) {
@@ -56673,7 +56615,7 @@ function systemdManager(host, profile) {
56673
56615
  }
56674
56616
 
56675
56617
  // src/platform/service/xdg-autostart.ts
56676
- var import_promises20 = require("fs/promises");
56618
+ var import_promises21 = require("fs/promises");
56677
56619
  var import_node_path17 = require("path");
56678
56620
  var AUTOSTART_PREFIX = "alan-runtime";
56679
56621
  var ALREADY_RUNNING_EXIT_STATUS2 = 73;
@@ -56789,7 +56731,7 @@ function xdgAutostartManager(host, profile) {
56789
56731
  name: files.name,
56790
56732
  definitionPath: files.entry,
56791
56733
  install: async (spec, { restart }) => {
56792
- await (0, import_promises20.mkdir)((0, import_node_path17.dirname)(spec.logPath), { recursive: true, mode: 448 });
56734
+ await (0, import_promises21.mkdir)((0, import_node_path17.dirname)(spec.logPath), { recursive: true, mode: 448 });
56793
56735
  const scriptChanged = await writeDefinition(
56794
56736
  files.script,
56795
56737
  renderSupervisorScript(spec, files),
@@ -56816,7 +56758,7 @@ function xdgAutostartManager(host, profile) {
56816
56758
  removeDefinition(files.entry),
56817
56759
  removeDefinition(files.script)
56818
56760
  ]);
56819
- await (0, import_promises20.rm)(files.supervisorRecord, { force: true });
56761
+ await (0, import_promises21.rm)(files.supervisorRecord, { force: true });
56820
56762
  return { manager: "xdg-autostart", name: files.name, removed: entry || script };
56821
56763
  },
56822
56764
  status: async () => {
@@ -56860,7 +56802,7 @@ function launchdManager(host, profile) {
56860
56802
  name: label,
56861
56803
  definitionPath: plist,
56862
56804
  install: async (spec, { restart }) => {
56863
- await (0, import_promises21.mkdir)((0, import_node_path18.dirname)(spec.logPath), { recursive: true, mode: 448 });
56805
+ await (0, import_promises22.mkdir)((0, import_node_path18.dirname)(spec.logPath), { recursive: true, mode: 448 });
56864
56806
  const changed = await writeDefinition(plist, renderLaunchdPlist(spec));
56865
56807
  const loaded = await isLoaded();
56866
56808
  if (loaded && !changed) {
@@ -56920,7 +56862,7 @@ function linuxManager(host, profile) {
56920
56862
  if (manager === systemd) {
56921
56863
  if (await readText(autostart.definitionPath) !== null) await autostart.uninstall();
56922
56864
  } else {
56923
- await (0, import_promises21.rm)(staleUnitPath, { force: true });
56865
+ await (0, import_promises22.rm)(staleUnitPath, { force: true });
56924
56866
  }
56925
56867
  return manager.install(spec, options);
56926
56868
  },
@@ -57394,7 +57336,7 @@ function createGit(options) {
57394
57336
  // src/capabilities/github-proxy/certificates.ts
57395
57337
  var import_node_child_process9 = require("child_process");
57396
57338
  var import_node_crypto11 = require("crypto");
57397
- var import_promises22 = require("fs/promises");
57339
+ var import_promises23 = require("fs/promises");
57398
57340
  var import_node_path20 = require("path");
57399
57341
  var OPENSSL_TIMEOUT_MS = 1e4;
57400
57342
  var VALIDITY_DAYS = "30";
@@ -57432,13 +57374,13 @@ function openssl(args, cwd) {
57432
57374
  }
57433
57375
  async function createGitHubProxyCertificates(stateDir) {
57434
57376
  const work = (0, import_node_path20.join)(stateDir, "github-proxy");
57435
- await (0, import_promises22.rm)(work, { recursive: true, force: true });
57436
- await (0, import_promises22.mkdir)(work, { recursive: true, mode: 448 });
57377
+ await (0, import_promises23.rm)(work, { recursive: true, force: true });
57378
+ await (0, import_promises23.mkdir)(work, { recursive: true, mode: 448 });
57437
57379
  try {
57438
- await (0, import_promises22.writeFile)((0, import_node_path20.join)(work, "ca.cnf"), opensslConfig("Alan sandbox GitHub proxy CA"), {
57380
+ await (0, import_promises23.writeFile)((0, import_node_path20.join)(work, "ca.cnf"), opensslConfig("Alan sandbox GitHub proxy CA"), {
57439
57381
  mode: 384
57440
57382
  });
57441
- await (0, import_promises22.writeFile)((0, import_node_path20.join)(work, "leaf.cnf"), opensslConfig("github.com"), { mode: 384 });
57383
+ await (0, import_promises23.writeFile)((0, import_node_path20.join)(work, "leaf.cnf"), opensslConfig("github.com"), { mode: 384 });
57442
57384
  const curve = ["ecparam", "-name", "prime256v1", "-genkey", "-noout"];
57443
57385
  await openssl([...curve, "-out", "ca.key"], work);
57444
57386
  await openssl(
@@ -57462,19 +57404,19 @@ async function createGitHubProxyCertificates(stateDir) {
57462
57404
  work
57463
57405
  );
57464
57406
  const caPath = (0, import_node_path20.join)(stateDir, "github-ca.pem");
57465
- await (0, import_promises22.writeFile)(caPath, await (0, import_promises22.readFile)((0, import_node_path20.join)(work, "ca.pem")), { mode: 384 });
57407
+ await (0, import_promises23.writeFile)(caPath, await (0, import_promises23.readFile)((0, import_node_path20.join)(work, "ca.pem")), { mode: 384 });
57466
57408
  return {
57467
57409
  caPath,
57468
- leafKeyPem: await (0, import_promises22.readFile)((0, import_node_path20.join)(work, "leaf.key"), "utf8"),
57469
- leafCertPem: await (0, import_promises22.readFile)((0, import_node_path20.join)(work, "leaf.pem"), "utf8")
57410
+ leafKeyPem: await (0, import_promises23.readFile)((0, import_node_path20.join)(work, "leaf.key"), "utf8"),
57411
+ leafCertPem: await (0, import_promises23.readFile)((0, import_node_path20.join)(work, "leaf.pem"), "utf8")
57470
57412
  };
57471
57413
  } finally {
57472
- await (0, import_promises22.rm)(work, { recursive: true, force: true });
57414
+ await (0, import_promises23.rm)(work, { recursive: true, force: true });
57473
57415
  }
57474
57416
  }
57475
57417
 
57476
57418
  // src/capabilities/github-proxy/config.ts
57477
- var import_promises23 = require("fs/promises");
57419
+ var import_promises24 = require("fs/promises");
57478
57420
  var import_node_path21 = require("path");
57479
57421
  init_runtime_v2();
57480
57422
  var GITHUB_URL = "https://github.com/";
@@ -57491,10 +57433,10 @@ function withGhConfigKey(yaml, key, value2) {
57491
57433
  `;
57492
57434
  }
57493
57435
  async function configureGh(ghConfigDir, socketPath) {
57494
- await (0, import_promises23.mkdir)(ghConfigDir, { recursive: true, mode: 448 });
57436
+ await (0, import_promises24.mkdir)(ghConfigDir, { recursive: true, mode: 448 });
57495
57437
  const path4 = (0, import_node_path21.join)(ghConfigDir, "config.yml");
57496
- const current = await (0, import_promises23.readFile)(path4, "utf8").catch(() => "");
57497
- await (0, import_promises23.writeFile)(path4, withGhConfigKey(current, GH_SOCKET_KEY, socketPath), { mode: 384 });
57438
+ const current = await (0, import_promises24.readFile)(path4, "utf8").catch(() => "");
57439
+ await (0, import_promises24.writeFile)(path4, withGhConfigKey(current, GH_SOCKET_KEY, socketPath), { mode: 384 });
57498
57440
  }
57499
57441
  async function configureGit(input2, git) {
57500
57442
  const run2 = async (args, allowedExitCodes = [0]) => {
@@ -57524,7 +57466,7 @@ async function configureGitHubProxyClients(input2) {
57524
57466
  }
57525
57467
 
57526
57468
  // src/capabilities/github-proxy/server.ts
57527
- var import_promises24 = require("fs/promises");
57469
+ var import_promises25 = require("fs/promises");
57528
57470
  var import_node_http3 = require("http");
57529
57471
  var import_node_tls = require("tls");
57530
57472
  init_runtime_v2();
@@ -57666,7 +57608,7 @@ async function startGitHubProxy(options) {
57666
57608
  });
57667
57609
  removeStaleEndpoint(options.socketPath);
57668
57610
  await listen(gh, options.socketPath);
57669
- await (0, import_promises24.chmod)(options.socketPath, 384);
57611
+ await (0, import_promises25.chmod)(options.socketPath, 384);
57670
57612
  const git = options.certificates === null ? null : await startGitListener(options.certificates, relay);
57671
57613
  options.log.info("github_proxy.listening", {
57672
57614
  socketPath: options.socketPath,
@@ -57685,7 +57627,7 @@ async function startGitHubProxy(options) {
57685
57627
 
57686
57628
  // src/capabilities/mcp-config/mcp-config.ts
57687
57629
  var import_node_crypto12 = require("crypto");
57688
- var import_promises25 = require("fs/promises");
57630
+ var import_promises26 = require("fs/promises");
57689
57631
  var import_node_path22 = require("path");
57690
57632
 
57691
57633
  // ../../node_modules/smol-toml/dist/error.js
@@ -58527,6 +58469,7 @@ var MCP_CLIS = [
58527
58469
  guardDir: "",
58528
58470
  configPath: ".claude.json",
58529
58471
  section: "mcpServers",
58472
+ writesEntry: true,
58530
58473
  entry: (url3) => ({ type: "http", url: url3, headers: {} })
58531
58474
  },
58532
58475
  {
@@ -58535,6 +58478,9 @@ var MCP_CLIS = [
58535
58478
  guardDir: ".codex",
58536
58479
  configPath: ".codex/config.toml",
58537
58480
  section: "mcp_servers",
58481
+ // ChatGPT.app's bundled Codex reads this file too and never completes MCP OAuth, so a
58482
+ // credential-free entry only loops 401s; Alan runs pass their own per-thread config.
58483
+ writesEntry: false,
58538
58484
  entry: (url3) => ({ url: url3 })
58539
58485
  },
58540
58486
  {
@@ -58543,6 +58489,7 @@ var MCP_CLIS = [
58543
58489
  guardDir: ".cursor",
58544
58490
  configPath: ".cursor/mcp.json",
58545
58491
  section: "mcpServers",
58492
+ writesEntry: true,
58546
58493
  entry: (url3) => ({ type: "http", url: url3, headers: {} })
58547
58494
  },
58548
58495
  {
@@ -58551,6 +58498,7 @@ var MCP_CLIS = [
58551
58498
  guardDir: ".kimi",
58552
58499
  configPath: ".kimi/mcp.json",
58553
58500
  section: "mcpServers",
58501
+ writesEntry: true,
58554
58502
  entry: (url3) => ({ url: url3, headers: {} })
58555
58503
  },
58556
58504
  {
@@ -58559,6 +58507,7 @@ var MCP_CLIS = [
58559
58507
  guardDir: ".commandcode",
58560
58508
  configPath: ".commandcode/mcp.json",
58561
58509
  section: "mcpServers",
58510
+ writesEntry: true,
58562
58511
  entry: (url3) => ({ transport: "http", enabled: true, url: url3 })
58563
58512
  },
58564
58513
  {
@@ -58567,6 +58516,7 @@ var MCP_CLIS = [
58567
58516
  guardDir: ".config/opencode",
58568
58517
  configPath: ".config/opencode/opencode.json",
58569
58518
  section: "mcp",
58519
+ writesEntry: true,
58570
58520
  entry: (url3) => ({ type: "remote", url: url3, headers: {} })
58571
58521
  },
58572
58522
  {
@@ -58575,6 +58525,7 @@ var MCP_CLIS = [
58575
58525
  guardDir: ".factory",
58576
58526
  configPath: ".factory/mcp.json",
58577
58527
  section: "mcpServers",
58528
+ writesEntry: true,
58578
58529
  entry: (url3) => ({ type: "http", url: url3, disabled: false })
58579
58530
  },
58580
58531
  {
@@ -58583,6 +58534,7 @@ var MCP_CLIS = [
58583
58534
  guardDir: ".copilot",
58584
58535
  configPath: ".copilot/mcp-config.json",
58585
58536
  section: "mcpServers",
58537
+ writesEntry: true,
58586
58538
  entry: (url3) => ({ type: "http", url: url3, tools: ["*"], headers: {} })
58587
58539
  },
58588
58540
  {
@@ -58591,6 +58543,7 @@ var MCP_CLIS = [
58591
58543
  guardDir: ".grok",
58592
58544
  configPath: ".grok/config.toml",
58593
58545
  section: "mcp_servers",
58546
+ writesEntry: true,
58594
58547
  entry: (url3) => ({ url: url3 })
58595
58548
  }
58596
58549
  ];
@@ -58619,9 +58572,12 @@ function isAlanEntry(entry, endpoint) {
58619
58572
  if (url3.pathname.replace(/\/+$/, "") !== "/mcp") return false;
58620
58573
  return url3.origin === endpoint.origin || url3.hostname.endsWith(ALAN_HOST_SUFFIX);
58621
58574
  }
58575
+ function isCredentialFreeAlanEntry(entry, endpoint) {
58576
+ return isAlanEntry(entry, endpoint) && isRecord2(entry) && Object.keys(entry).every((key) => URL_KEYS.includes(key));
58577
+ }
58622
58578
  async function isInstalled(cli, home) {
58623
58579
  try {
58624
- return (await (0, import_promises25.stat)((0, import_node_path22.join)(home, cli.guardDir))).isDirectory();
58580
+ return (await (0, import_promises26.stat)((0, import_node_path22.join)(home, cli.guardDir))).isDirectory();
58625
58581
  } catch (error61) {
58626
58582
  if (errorCode2(error61) === "ENOENT") return false;
58627
58583
  throw error61;
@@ -58629,7 +58585,7 @@ async function isInstalled(cli, home) {
58629
58585
  }
58630
58586
  async function readText2(path4) {
58631
58587
  try {
58632
- return await (0, import_promises25.readFile)(path4, "utf8");
58588
+ return await (0, import_promises26.readFile)(path4, "utf8");
58633
58589
  } catch (error61) {
58634
58590
  if (errorCode2(error61) === "ENOENT") return null;
58635
58591
  throw error61;
@@ -58656,10 +58612,10 @@ async function readConfig(cli, home) {
58656
58612
  async function writeConfig(path4, text2) {
58657
58613
  const temporary = `${path4}.alan-${(0, import_node_crypto12.randomUUID)()}.tmp`;
58658
58614
  try {
58659
- await (0, import_promises25.writeFile)(temporary, text2, { encoding: "utf8", mode: 384, flag: "wx" });
58660
- await (0, import_promises25.rename)(temporary, path4);
58615
+ await (0, import_promises26.writeFile)(temporary, text2, { encoding: "utf8", mode: 384, flag: "wx" });
58616
+ await (0, import_promises26.rename)(temporary, path4);
58661
58617
  } finally {
58662
- await (0, import_promises25.rm)(temporary, { force: true });
58618
+ await (0, import_promises26.rm)(temporary, { force: true });
58663
58619
  }
58664
58620
  }
58665
58621
  async function editCli(cli, home, endpoint, edit) {
@@ -58687,6 +58643,13 @@ async function editInstalledClis(home, apiUrl, edit) {
58687
58643
  }
58688
58644
  function syncAlanMcp(options) {
58689
58645
  return editInstalledClis(options.home, options.apiUrl, (servers, endpoint, cli) => {
58646
+ if (!cli.writesEntry) {
58647
+ const stale = [ALAN_MCP_SERVER_NAME, ...options.legacyServerNames].filter(
58648
+ (name) => isCredentialFreeAlanEntry(servers.get(name), endpoint)
58649
+ );
58650
+ for (const name of stale) servers.delete(name);
58651
+ return stale.length > 0;
58652
+ }
58690
58653
  const current = servers.get(ALAN_MCP_SERVER_NAME);
58691
58654
  if (current !== void 0 && !isAlanEntry(current, endpoint)) {
58692
58655
  throw new Error(`an entry that is not Alan's already uses the name ${ALAN_MCP_SERVER_NAME}`);
@@ -58730,7 +58693,7 @@ async function inspectAlanMcp(options) {
58730
58693
  }
58731
58694
 
58732
58695
  // src/capabilities/models/opencode-models.ts
58733
- var import_promises26 = require("fs/promises");
58696
+ var import_promises27 = require("fs/promises");
58734
58697
  var import_node_path23 = require("path");
58735
58698
  init_runtime_v2();
58736
58699
  init_zod();
@@ -59046,7 +59009,7 @@ async function readOpenCodeCatalogueCache(env) {
59046
59009
  const home = env.HOME?.trim();
59047
59010
  const cacheHome = env.XDG_CACHE_HOME?.trim() || (home ? (0, import_node_path23.join)(home, ".cache") : "");
59048
59011
  if (cacheHome === "") return null;
59049
- const text2 = await (0, import_promises26.readFile)((0, import_node_path23.join)(cacheHome, ...CATALOGUE_CACHE_SEGMENTS), "utf8").catch(
59012
+ const text2 = await (0, import_promises27.readFile)((0, import_node_path23.join)(cacheHome, ...CATALOGUE_CACHE_SEGMENTS), "utf8").catch(
59050
59013
  () => void 0
59051
59014
  );
59052
59015
  if (text2 === void 0) return null;
@@ -59165,7 +59128,7 @@ async function discoverModels(backendKind, executable, env, capture) {
59165
59128
  }
59166
59129
 
59167
59130
  // src/capabilities/models/opencode-entitlement.ts
59168
- var import_promises27 = require("fs/promises");
59131
+ var import_promises28 = require("fs/promises");
59169
59132
  var import_node_os2 = require("os");
59170
59133
  var import_node_path24 = require("path");
59171
59134
  init_agent2();
@@ -59175,7 +59138,7 @@ async function readOpenCodeZenCredential(env) {
59175
59138
  const injected = env.OPENCODE_AUTH_CONTENT?.trim();
59176
59139
  if (injected) return readZenCredentialFromAuthDocument(injected);
59177
59140
  const dataHome = env.XDG_DATA_HOME?.trim() || (0, import_node_path24.join)(env.HOME?.trim() || (0, import_node_os2.homedir)(), ".local", "share");
59178
- const document2 = await (0, import_promises27.readFile)((0, import_node_path24.join)(dataHome, "opencode", "auth.json"), "utf8").catch(
59141
+ const document2 = await (0, import_promises28.readFile)((0, import_node_path24.join)(dataHome, "opencode", "auth.json"), "utf8").catch(
59179
59142
  () => void 0
59180
59143
  );
59181
59144
  return readZenCredentialFromAuthDocument(document2);
@@ -59618,7 +59581,7 @@ function nextAlanBoundary(entry, inFlightFrom) {
59618
59581
  }
59619
59582
 
59620
59583
  // src/capabilities/native-ingest/pass.ts
59621
- var import_promises31 = require("fs/promises");
59584
+ var import_promises32 = require("fs/promises");
59622
59585
 
59623
59586
  // src/capabilities/native-ingest/ports.ts
59624
59587
  var NativeRequestFailure = class extends Error {
@@ -59756,7 +59719,7 @@ function reconcileTranscriptIdentity(entry, transcriptPath, identity, size) {
59756
59719
 
59757
59720
  // src/capabilities/native-ingest/transcript-window.ts
59758
59721
  var import_node_crypto13 = require("crypto");
59759
- var import_promises30 = require("fs/promises");
59722
+ var import_promises31 = require("fs/promises");
59760
59723
  init_acp2();
59761
59724
  init_claude();
59762
59725
  init_codex();
@@ -59811,7 +59774,7 @@ async function findRecordEnd(handle, from, size) {
59811
59774
  return null;
59812
59775
  }
59813
59776
  async function readTranscriptWindow(path4, offset, limits) {
59814
- const handle = await (0, import_promises30.open)(path4, "r");
59777
+ const handle = await (0, import_promises31.open)(path4, "r");
59815
59778
  try {
59816
59779
  const stats = await handle.stat({ bigint: true });
59817
59780
  const size = Number(stats.size);
@@ -60264,7 +60227,7 @@ async function runPass(ctx, worker) {
60264
60227
  });
60265
60228
  if (signal.ending) ctx.log.info("native_ingest.closed", workerFields(worker));
60266
60229
  }
60267
- const current = await (0, import_promises31.stat)(worker.latest.transcriptPath).catch(() => void 0);
60230
+ const current = await (0, import_promises32.stat)(worker.latest.transcriptPath).catch(() => void 0);
60268
60231
  return { grewDuringPass: current !== void 0 && current.size > state.lastSize };
60269
60232
  }
60270
60233
 
@@ -60621,7 +60584,7 @@ init_alan_code();
60621
60584
 
60622
60585
  // src/capabilities/providers/commands.ts
60623
60586
  var import_node_fs10 = require("fs");
60624
- var import_promises33 = require("fs/promises");
60587
+ var import_promises34 = require("fs/promises");
60625
60588
  var import_node_path30 = require("path");
60626
60589
  var PROVIDER_COMMANDS = [
60627
60590
  // The engine, not a CLI of its own: `resolveProviderExecutable` finds the bundled one first.
@@ -60655,8 +60618,8 @@ function pathDelimiter(platform3) {
60655
60618
  }
60656
60619
  async function isRunnable(path4, platform3) {
60657
60620
  try {
60658
- if (!(await (0, import_promises33.stat)(path4)).isFile()) return false;
60659
- if (platform3 !== "win32") await (0, import_promises33.access)(path4, import_node_fs10.constants.X_OK);
60621
+ if (!(await (0, import_promises34.stat)(path4)).isFile()) return false;
60622
+ if (platform3 !== "win32") await (0, import_promises34.access)(path4, import_node_fs10.constants.X_OK);
60660
60623
  return true;
60661
60624
  } catch {
60662
60625
  return false;
@@ -61199,13 +61162,13 @@ async function openCliEnvironment(options) {
61199
61162
  }
61200
61163
 
61201
61164
  // src/capabilities/skills/local-preview.ts
61202
- var import_promises38 = require("fs/promises");
61165
+ var import_promises39 = require("fs/promises");
61203
61166
  var import_node_path39 = __toESM(require("path"));
61204
61167
 
61205
61168
  // ../shared/dist/node/skill-package.js
61206
61169
  var import_node_buffer = require("buffer");
61207
61170
  var import_node_crypto15 = require("crypto");
61208
- var import_promises34 = require("fs/promises");
61171
+ var import_promises35 = require("fs/promises");
61209
61172
  var import_node_path35 = require("path");
61210
61173
  var import_yaml = __toESM(require_dist(), 1);
61211
61174
  init_contracts();
@@ -61301,11 +61264,11 @@ async function readSkillPackageFile(packageRoot, path4, expectedSha256) {
61301
61264
  if (!normalizedPath || normalizedPath !== path4 || normalizedPath.includes("\\") || components.some((component) => !component || component === "." || component === "..")) {
61302
61265
  throw new SkillPackageError("INVALID_PATH", `Invalid Skill package path: ${path4}`, path4);
61303
61266
  }
61304
- const absolutePath = await (0, import_promises34.realpath)((0, import_node_path35.resolve)(root, ...components)).catch(() => null);
61267
+ const absolutePath = await (0, import_promises35.realpath)((0, import_node_path35.resolve)(root, ...components)).catch(() => null);
61305
61268
  if (!absolutePath || normalizeRelativePath(root, absolutePath) !== normalizedPath) {
61306
61269
  throw new SkillPackageError("INVALID_PATH", `Skill package file was not found: ${path4}`, path4);
61307
61270
  }
61308
- const entryStat = await (0, import_promises34.lstat)(absolutePath);
61271
+ const entryStat = await (0, import_promises35.lstat)(absolutePath);
61309
61272
  if (!entryStat.isFile()) {
61310
61273
  throw new SkillPackageError("SPECIAL_FILE_BLOCKED", `Only regular files are allowed in Skill packages: ${path4}`, path4);
61311
61274
  }
@@ -61322,11 +61285,11 @@ async function readSkillPackageFile(packageRoot, path4, expectedSha256) {
61322
61285
  return { file: read.manifest, bytes: read.bytes };
61323
61286
  }
61324
61287
  async function requirePackageRoot(packageRoot) {
61325
- const root = await (0, import_promises34.realpath)((0, import_node_path35.resolve)(packageRoot)).catch(() => null);
61288
+ const root = await (0, import_promises35.realpath)((0, import_node_path35.resolve)(packageRoot)).catch(() => null);
61326
61289
  if (!root) {
61327
61290
  throw new SkillPackageError("INVALID_PACKAGE_ROOT", "Skill package directory does not exist");
61328
61291
  }
61329
- const rootStat = await (0, import_promises34.lstat)(root);
61292
+ const rootStat = await (0, import_promises35.lstat)(root);
61330
61293
  if (!rootStat.isDirectory()) {
61331
61294
  throw new SkillPackageError("INVALID_PACKAGE_ROOT", "Skill package root must be a directory");
61332
61295
  }
@@ -61346,13 +61309,13 @@ async function walkPackage(root, ignoredPaths) {
61346
61309
  }
61347
61310
  return files;
61348
61311
  async function walkDirectory(directory) {
61349
- const entries = await (0, import_promises34.readdir)(directory, { withFileTypes: true });
61312
+ const entries = await (0, import_promises35.readdir)(directory, { withFileTypes: true });
61350
61313
  for (const entry of entries) {
61351
61314
  const absolutePath = (0, import_node_path35.resolve)(directory, entry.name);
61352
61315
  const normalizedPath = normalizeRelativePath(root, absolutePath);
61353
61316
  if (isIgnored(normalizedPath, entry.name, entry.isDirectory(), ignored2))
61354
61317
  continue;
61355
- const entryStat = await (0, import_promises34.lstat)(absolutePath);
61318
+ const entryStat = await (0, import_promises35.lstat)(absolutePath);
61356
61319
  if (entryStat.isSymbolicLink()) {
61357
61320
  throw new SkillPackageError("SYMLINK_BLOCKED", `Nested symbolic links are not allowed in Skill packages: ${normalizedPath}`, normalizedPath);
61358
61321
  }
@@ -61461,7 +61424,7 @@ function isSecretPath(path4) {
61461
61424
  return name.endsWith(".private-key.pem") || name.endsWith(".private-key.key");
61462
61425
  }
61463
61426
  async function readPackageFile(file2) {
61464
- const bytes = await (0, import_promises34.readFile)(file2.absolutePath);
61427
+ const bytes = await (0, import_promises35.readFile)(file2.absolutePath);
61465
61428
  return {
61466
61429
  bytes,
61467
61430
  manifest: {
@@ -61632,13 +61595,13 @@ function uint642(value2) {
61632
61595
 
61633
61596
  // src/capabilities/skills/local-sources.ts
61634
61597
  var import_node_crypto17 = require("crypto");
61635
- var import_promises36 = require("fs/promises");
61598
+ var import_promises37 = require("fs/promises");
61636
61599
  var import_node_path37 = __toESM(require("path"));
61637
61600
  init_type_guards();
61638
61601
 
61639
61602
  // src/capabilities/skills/local-scan.ts
61640
61603
  var import_node_crypto16 = require("crypto");
61641
- var import_promises35 = require("fs/promises");
61604
+ var import_promises36 = require("fs/promises");
61642
61605
  var import_node_path36 = __toESM(require("path"));
61643
61606
  var MAX_CANDIDATES = 2e3;
61644
61607
  var MAX_DIAGNOSTICS = 100;
@@ -61758,7 +61721,7 @@ function invalid(resolvedRoot, name, error61) {
61758
61721
  }
61759
61722
  async function scanRootAsPackage(pass, resolvedRoot) {
61760
61723
  if (!await exists3(import_node_path36.default.join(resolvedRoot.directory, "SKILL.md"))) return null;
61761
- const canonical = await (0, import_promises35.realpath)(resolvedRoot.directory).catch(() => resolvedRoot.directory);
61724
+ const canonical = await (0, import_promises36.realpath)(resolvedRoot.directory).catch(() => resolvedRoot.directory);
61762
61725
  try {
61763
61726
  const inspected = await inspectCached(pass, canonical, null);
61764
61727
  return {
@@ -61787,7 +61750,7 @@ async function scanRoot(pass, resolvedRoot) {
61787
61750
  if (asPackage !== null) return asPackage;
61788
61751
  let entries;
61789
61752
  try {
61790
- entries = await (0, import_promises35.readdir)(resolvedRoot.directory, { withFileTypes: true });
61753
+ entries = await (0, import_promises36.readdir)(resolvedRoot.directory, { withFileTypes: true });
61791
61754
  } catch (error61) {
61792
61755
  const code = errnoCode(error61);
61793
61756
  if (code === "ENOENT" || code === "ENOTDIR") {
@@ -61805,7 +61768,7 @@ async function scanRoot(pass, resolvedRoot) {
61805
61768
  incomplete: true
61806
61769
  };
61807
61770
  }
61808
- const canonicalRoot = await (0, import_promises35.realpath)(resolvedRoot.directory).catch(() => resolvedRoot.directory);
61771
+ const canonicalRoot = await (0, import_promises36.realpath)(resolvedRoot.directory).catch(() => resolvedRoot.directory);
61809
61772
  const scan = { candidates: [], diagnostics: [], incomplete: false };
61810
61773
  for (const entry of entries) {
61811
61774
  if (!entry.isDirectory() && !entry.isSymbolicLink()) continue;
@@ -61817,7 +61780,7 @@ async function scanRoot(pass, resolvedRoot) {
61817
61780
  }
61818
61781
  async function scanEntry(pass, resolvedRoot, canonicalRoot, name) {
61819
61782
  const rootLabel = resolvedRoot.root.label;
61820
- const canonical = await (0, import_promises35.realpath)(import_node_path36.default.join(resolvedRoot.directory, name)).catch(() => null);
61783
+ const canonical = await (0, import_promises36.realpath)(import_node_path36.default.join(resolvedRoot.directory, name)).catch(() => null);
61821
61784
  if (canonical === null) {
61822
61785
  const message2 = `Could not resolve Skill ${name}`;
61823
61786
  return { kind: "diagnostic", diagnostic: { code: "SOURCE_UNREADABLE", message: message2, rootLabel } };
@@ -61901,12 +61864,12 @@ function deduplicateByContent(candidates2) {
61901
61864
  async function fingerprintPackage(root) {
61902
61865
  const hash2 = (0, import_node_crypto16.createHash)("sha256").update("alan-skill-stat-fingerprint-v1\0");
61903
61866
  const visit2 = async (directory, relativeDirectory) => {
61904
- const entries = await (0, import_promises35.readdir)(directory, { withFileTypes: true });
61867
+ const entries = await (0, import_promises36.readdir)(directory, { withFileTypes: true });
61905
61868
  entries.sort((left, right) => Buffer.compare(Buffer.from(left.name), Buffer.from(right.name)));
61906
61869
  for (const entry of entries) {
61907
61870
  const relative5 = relativeDirectory ? `${relativeDirectory}/${entry.name}` : entry.name;
61908
61871
  const absolute = import_node_path36.default.join(directory, entry.name);
61909
- const metadata = await (0, import_promises35.lstat)(absolute);
61872
+ const metadata = await (0, import_promises36.lstat)(absolute);
61910
61873
  const kind = entryKind(entry);
61911
61874
  hash2.update(relative5.normalize("NFC")).update(`\0${kind}\0${metadata.size}\0${metadata.mtimeMs}\0${metadata.mode & 511}\0`);
61912
61875
  if (entry.isDirectory()) await visit2(absolute, relative5);
@@ -61922,7 +61885,7 @@ function entryKind(entry) {
61922
61885
  }
61923
61886
  async function canonicalDirectories(directories) {
61924
61887
  const canonical = await Promise.all(
61925
- directories.map((directory) => (0, import_promises35.realpath)(directory).catch(() => directory))
61888
+ directories.map((directory) => (0, import_promises36.realpath)(directory).catch(() => directory))
61926
61889
  );
61927
61890
  return [...new Set(canonical)];
61928
61891
  }
@@ -61932,7 +61895,7 @@ function isWithinDirectory2(parent, candidate) {
61932
61895
  }
61933
61896
  async function exists3(candidate) {
61934
61897
  try {
61935
- await (0, import_promises35.access)(candidate);
61898
+ await (0, import_promises36.access)(candidate);
61936
61899
  return true;
61937
61900
  } catch {
61938
61901
  return false;
@@ -61940,7 +61903,7 @@ async function exists3(candidate) {
61940
61903
  }
61941
61904
  async function isDirectory3(candidate) {
61942
61905
  try {
61943
- return (await (0, import_promises35.lstat)(candidate)).isDirectory();
61906
+ return (await (0, import_promises36.lstat)(candidate)).isDirectory();
61944
61907
  } catch {
61945
61908
  return false;
61946
61909
  }
@@ -62028,7 +61991,7 @@ async function resolveLocalScanInput(home, context, mode) {
62028
61991
  async function readSkillSourceConfig(home) {
62029
61992
  let content;
62030
61993
  try {
62031
- content = await (0, import_promises36.readFile)(skillSourceConfigPath(home), "utf8");
61994
+ content = await (0, import_promises37.readFile)(skillSourceConfigPath(home), "utf8");
62032
61995
  } catch (error61) {
62033
61996
  if (errnoCode(error61) !== "ENOENT") {
62034
61997
  return { kind: "invalid_config", diagnostic: "~/.alan/config.toml could not be read" };
@@ -62145,7 +62108,7 @@ async function scanLocalSkills(home, context, cache2, mode = "incremental") {
62145
62108
  }
62146
62109
 
62147
62110
  // src/capabilities/skills/store.ts
62148
- var import_promises37 = require("fs/promises");
62111
+ var import_promises38 = require("fs/promises");
62149
62112
  var import_node_path38 = require("path");
62150
62113
  init_runtime_v2();
62151
62114
  init_zod();
@@ -62193,7 +62156,7 @@ function writeLocalSkills(layout, file2) {
62193
62156
  async function isLocalSkillCurrent(entry, contentHash, ignoredPaths) {
62194
62157
  if (entry.contentHash !== contentHash) return false;
62195
62158
  try {
62196
- if (await (0, import_promises37.realpath)(entry.path) !== entry.path) return false;
62159
+ if (await (0, import_promises38.realpath)(entry.path) !== entry.path) return false;
62197
62160
  const inspected = await inspectSkillPackage(entry.path, { expectedName: null, ignoredPaths });
62198
62161
  return inspected.contentHash === contentHash;
62199
62162
  } catch {
@@ -62208,7 +62171,7 @@ async function resolveLocalSkill(local, invocation) {
62208
62171
  }
62209
62172
  async function hasSkillFile(directory) {
62210
62173
  try {
62211
- return (await (0, import_promises37.stat)((0, import_node_path38.join)(directory, "SKILL.md"))).isFile();
62174
+ return (await (0, import_promises38.stat)((0, import_node_path38.join)(directory, "SKILL.md"))).isFile();
62212
62175
  } catch {
62213
62176
  return false;
62214
62177
  }
@@ -62309,7 +62272,7 @@ async function readLocalSkillFile(layout, ref) {
62309
62272
  }
62310
62273
  async function isDirectory4(candidate) {
62311
62274
  try {
62312
- return (await (0, import_promises38.stat)(candidate)).isDirectory();
62275
+ return (await (0, import_promises39.stat)(candidate)).isDirectory();
62313
62276
  } catch {
62314
62277
  return false;
62315
62278
  }
@@ -62322,21 +62285,21 @@ async function addSkillSource(home, input2) {
62322
62285
  return { state: "invalid", diagnostic: `${sourcePath} is not a folder` };
62323
62286
  }
62324
62287
  const configPath = skillSourceConfigPath(home);
62325
- await (0, import_promises38.mkdir)(import_node_path39.default.dirname(configPath), { recursive: true, mode: 448 });
62326
- await (0, import_promises38.writeFile)(configPath, DEFAULT_SKILL_CONFIG, { flag: "wx", mode: 384 }).catch(
62288
+ await (0, import_promises39.mkdir)(import_node_path39.default.dirname(configPath), { recursive: true, mode: 448 });
62289
+ await (0, import_promises39.writeFile)(configPath, DEFAULT_SKILL_CONFIG, { flag: "wx", mode: 384 }).catch(
62327
62290
  (error61) => {
62328
62291
  if (errnoCode(error61) !== "EEXIST") throw error61;
62329
62292
  }
62330
62293
  );
62331
62294
  const loaded = await readSkillSourceConfig(home);
62332
62295
  if (loaded.kind === "invalid_config") return { state: "invalid", diagnostic: loaded.diagnostic };
62333
- const canonical = await (0, import_promises38.realpath)(sourcePath).catch(() => sourcePath);
62296
+ const canonical = await (0, import_promises39.realpath)(sourcePath).catch(() => sourcePath);
62334
62297
  for (const source of loaded.config.sources) {
62335
- if (await (0, import_promises38.realpath)(source.path).catch(() => source.path) === canonical) {
62298
+ if (await (0, import_promises39.realpath)(source.path).catch(() => source.path) === canonical) {
62336
62299
  return { state: "already_present", label: source.label };
62337
62300
  }
62338
62301
  }
62339
- const current = await (0, import_promises38.readFile)(configPath, "utf8");
62302
+ const current = await (0, import_promises39.readFile)(configPath, "utf8");
62340
62303
  const block = [
62341
62304
  "",
62342
62305
  "[[skills.sources]]",
@@ -62344,7 +62307,7 @@ async function addSkillSource(home, input2) {
62344
62307
  `label = ${JSON.stringify(label)}`,
62345
62308
  ""
62346
62309
  ].join("\n");
62347
- await (0, import_promises38.writeFile)(configPath, `${current.replace(/\n*$/, "\n")}${block}`, { mode: 384 });
62310
+ await (0, import_promises39.writeFile)(configPath, `${current.replace(/\n*$/, "\n")}${block}`, { mode: 384 });
62348
62311
  const reloaded = await readSkillSourceConfig(home);
62349
62312
  if (reloaded.kind === "invalid_config") {
62350
62313
  return { state: "invalid", diagnostic: reloaded.diagnostic };
@@ -62353,12 +62316,12 @@ async function addSkillSource(home, input2) {
62353
62316
  }
62354
62317
 
62355
62318
  // src/capabilities/skills/local-upload.ts
62356
- var import_promises40 = require("fs/promises");
62319
+ var import_promises41 = require("fs/promises");
62357
62320
 
62358
62321
  // ../shared/dist/node/skill-bundle.js
62359
62322
  var import_node_buffer2 = require("buffer");
62360
62323
  var import_node_crypto18 = require("crypto");
62361
- var import_promises39 = require("fs/promises");
62324
+ var import_promises40 = require("fs/promises");
62362
62325
  var import_node_path40 = require("path");
62363
62326
  var import_node_stream = require("stream");
62364
62327
  var import_node_zlib = require("zlib");
@@ -62369,7 +62332,7 @@ async function createSkillBundle(packageRoot, options = {}) {
62369
62332
  const archive = (0, import_tar_stream.pack)();
62370
62333
  const tarPromise = collectStream(archive);
62371
62334
  for (const file2 of before.files) {
62372
- const bytes2 = await (0, import_promises39.readFile)((0, import_node_path40.join)(packageRoot, ...file2.path.split("/")));
62335
+ const bytes2 = await (0, import_promises40.readFile)((0, import_node_path40.join)(packageRoot, ...file2.path.split("/")));
62373
62336
  await addArchiveEntry(archive, {
62374
62337
  name: file2.path,
62375
62338
  type: "file",
@@ -62401,7 +62364,7 @@ async function extractSkillBundle(archiveBytes, destination, expected) {
62401
62364
  throw new Error("Skill archive hash does not match the expected immutable Version");
62402
62365
  }
62403
62366
  const tarBytes = await decompressBounded(archiveBytes);
62404
- await (0, import_promises39.mkdir)(destination, { recursive: false, mode: 448 });
62367
+ await (0, import_promises40.mkdir)(destination, { recursive: false, mode: 448 });
62405
62368
  try {
62406
62369
  await extractTar(tarBytes, destination);
62407
62370
  const inspected = await inspectSkillPackage(destination, { expectedName: null });
@@ -62409,7 +62372,7 @@ async function extractSkillBundle(archiveBytes, destination, expected) {
62409
62372
  throw new Error("Extracted Skill package hash does not match the expected immutable Version");
62410
62373
  }
62411
62374
  } catch (error61) {
62412
- await (0, import_promises39.rm)(destination, { recursive: true, force: true });
62375
+ await (0, import_promises40.rm)(destination, { recursive: true, force: true });
62413
62376
  throw error61;
62414
62377
  }
62415
62378
  }
@@ -62485,8 +62448,8 @@ async function extractEntry(header, stream, destination, limits) {
62485
62448
  throw new Error(`Skill archive file size is invalid: ${path4}`);
62486
62449
  }
62487
62450
  const outputPath = (0, import_node_path40.join)(destination, ...path4.split("/"));
62488
- await (0, import_promises39.mkdir)((0, import_node_path40.dirname)(outputPath), { recursive: true, mode: 448 });
62489
- await (0, import_promises39.writeFile)(outputPath, bytes, { mode: (header.mode ?? 420) & 73 ? 493 : 420 });
62451
+ await (0, import_promises40.mkdir)((0, import_node_path40.dirname)(outputPath), { recursive: true, mode: 448 });
62452
+ await (0, import_promises40.writeFile)(outputPath, bytes, { mode: (header.mode ?? 420) & 73 ? 493 : 420 });
62490
62453
  }
62491
62454
  function requireSafeArchivePath(value2) {
62492
62455
  const normalized2 = value2.replaceAll("\\", "/").normalize("NFC");
@@ -62512,8 +62475,8 @@ async function publishLocalSkill(options) {
62512
62475
  if (Date.parse(request2.uploadGrant.expiresAt) <= (options.now ?? Date.now())) {
62513
62476
  throw new RuntimeFault("invalid_file", "Skill upload grant expired");
62514
62477
  }
62515
- const folder = await (0, import_promises40.lstat)(entry.path);
62516
- if (!folder.isDirectory() || await (0, import_promises40.realpath)(entry.path) !== entry.path) {
62478
+ const folder = await (0, import_promises41.lstat)(entry.path);
62479
+ if (!folder.isDirectory() || await (0, import_promises41.realpath)(entry.path) !== entry.path) {
62517
62480
  throw new RuntimeFault("invalid_file", "Skill folder moved since the last scan");
62518
62481
  }
62519
62482
  const bundle = await createSkillBundle(entry.path, {
@@ -62541,31 +62504,31 @@ async function publishLocalSkill(options) {
62541
62504
 
62542
62505
  // src/capabilities/skills/sync.ts
62543
62506
  var import_node_crypto19 = require("crypto");
62544
- var import_promises41 = require("fs/promises");
62507
+ var import_promises42 = require("fs/promises");
62545
62508
  var import_node_path41 = require("path");
62546
62509
  var SKILL_PREPARE_WAIT_MS = 15e3;
62547
62510
  async function install(layout, source, skill, download, signal) {
62548
62511
  const bytes = await source.download(download.url, signal);
62549
- await (0, import_promises41.mkdir)(layout.tmpDir, { recursive: true, mode: 448 });
62512
+ await (0, import_promises42.mkdir)(layout.tmpDir, { recursive: true, mode: 448 });
62550
62513
  const staging = (0, import_node_path41.join)(layout.tmpDir, (0, import_node_crypto19.randomUUID)());
62551
62514
  await extractSkillBundle(Buffer.from(bytes), staging, {
62552
62515
  expectedArchiveHash: download.archiveHash,
62553
62516
  expectedContentHash: skill.contentHash
62554
62517
  });
62555
62518
  const target = packageDirectory(layout, skill.versionId);
62556
- await (0, import_promises41.mkdir)(layout.versionsDir, { recursive: true, mode: 448 });
62557
- await (0, import_promises41.rm)(target, { recursive: true, force: true });
62558
- await (0, import_promises41.rename)(staging, target);
62519
+ await (0, import_promises42.mkdir)(layout.versionsDir, { recursive: true, mode: 448 });
62520
+ await (0, import_promises42.rm)(target, { recursive: true, force: true });
62521
+ await (0, import_promises42.rename)(staging, target);
62559
62522
  }
62560
62523
  async function sweep(layout, keep) {
62561
62524
  const kept = new Set(keep.map((skill) => skill.versionId));
62562
- const stale = (await (0, import_promises41.readdir)(layout.versionsDir).catch(() => [])).filter(
62525
+ const stale = (await (0, import_promises42.readdir)(layout.versionsDir).catch(() => [])).filter(
62563
62526
  (name) => !kept.has(name)
62564
62527
  );
62565
62528
  await Promise.all(
62566
- stale.map((name) => (0, import_promises41.rm)((0, import_node_path41.join)(layout.versionsDir, name), { recursive: true, force: true }))
62529
+ stale.map((name) => (0, import_promises42.rm)((0, import_node_path41.join)(layout.versionsDir, name), { recursive: true, force: true }))
62567
62530
  );
62568
- await (0, import_promises41.rm)(layout.tmpDir, { recursive: true, force: true });
62531
+ await (0, import_promises42.rm)(layout.tmpDir, { recursive: true, force: true });
62569
62532
  return stale.length;
62570
62533
  }
62571
62534
  async function intactSkills(layout) {
@@ -62800,7 +62763,7 @@ var import_node_path44 = require("path");
62800
62763
  init_runtime_v2();
62801
62764
 
62802
62765
  // src/capabilities/workspace/approved-paths.ts
62803
- var import_promises42 = require("fs/promises");
62766
+ var import_promises43 = require("fs/promises");
62804
62767
  init_zod();
62805
62768
 
62806
62769
  // src/capabilities/workspace/paths.ts
@@ -62838,7 +62801,7 @@ var storeSchema = external_exports.object({
62838
62801
  });
62839
62802
  async function realpathOrNull(path4) {
62840
62803
  try {
62841
- return await (0, import_promises42.realpath)(path4);
62804
+ return await (0, import_promises43.realpath)(path4);
62842
62805
  } catch (error61) {
62843
62806
  const code = errnoCode(error61);
62844
62807
  if (code === "ENOENT" || code === "ENOTDIR" || code === "EACCES" || code === "EPERM") {
@@ -62898,7 +62861,7 @@ async function openApprovedPaths(options) {
62898
62861
 
62899
62862
  // src/capabilities/workspace/locks.ts
62900
62863
  var import_node_crypto20 = require("crypto");
62901
- var import_promises43 = require("fs/promises");
62864
+ var import_promises44 = require("fs/promises");
62902
62865
  var import_node_path43 = require("path");
62903
62866
  init_zod();
62904
62867
  var LOCK_FORMAT = 1;
@@ -62919,7 +62882,7 @@ function repositoryLockKey(commonDir, platform3) {
62919
62882
  async function readOwner2(path4) {
62920
62883
  let text2;
62921
62884
  try {
62922
- text2 = await (0, import_promises43.readFile)(path4, "utf8");
62885
+ text2 = await (0, import_promises44.readFile)(path4, "utf8");
62923
62886
  } catch (error61) {
62924
62887
  if (errnoCode(error61) === "ENOENT") return { kind: "missing" };
62925
62888
  return { kind: "unreadable" };
@@ -62940,7 +62903,7 @@ async function removeIfSame(path4, expected) {
62940
62903
  if (current.kind !== "owner" || current.owner.since !== expected.since) return;
62941
62904
  if (current.owner.pid !== expected.pid || current.owner.holder !== expected.holder) return;
62942
62905
  }
62943
- await (0, import_promises43.unlink)(path4).catch((error61) => {
62906
+ await (0, import_promises44.unlink)(path4).catch((error61) => {
62944
62907
  if (errnoCode(error61) !== "ENOENT") throw error61;
62945
62908
  });
62946
62909
  }
@@ -62965,7 +62928,7 @@ function openRepositoryLocks(options) {
62965
62928
  await removeIfSame(path4, read.owner);
62966
62929
  return null;
62967
62930
  }
62968
- const age = await (0, import_promises43.stat)(path4).then(
62931
+ const age = await (0, import_promises44.stat)(path4).then(
62969
62932
  (info) => clock.now() - info.mtimeMs,
62970
62933
  () => 0
62971
62934
  );
@@ -62980,12 +62943,12 @@ function openRepositoryLocks(options) {
62980
62943
  const folder = async (commonDir) => {
62981
62944
  const key = repositoryLockKey(commonDir, platform3);
62982
62945
  const dir = (0, import_node_path43.join)(options.dir, key);
62983
- await (0, import_promises43.mkdir)(dir, { recursive: true, mode: 448 });
62946
+ await (0, import_promises44.mkdir)(dir, { recursive: true, mode: 448 });
62984
62947
  return { key, dir };
62985
62948
  };
62986
62949
  const createExclusive = async (path4, owner) => {
62987
62950
  try {
62988
- const handle = await (0, import_promises43.open)(path4, "wx", 384);
62951
+ const handle = await (0, import_promises44.open)(path4, "wx", 384);
62989
62952
  try {
62990
62953
  await handle.writeFile(JSON.stringify(owner));
62991
62954
  } finally {
@@ -62998,7 +62961,7 @@ function openRepositoryLocks(options) {
62998
62961
  }
62999
62962
  };
63000
62963
  const liveRun = async (dir) => {
63001
- const entries = await (0, import_promises43.readdir)(dir);
62964
+ const entries = await (0, import_promises44.readdir)(dir);
63002
62965
  for (const entry of entries) {
63003
62966
  if (!entry.startsWith(RUN_FILE_PREFIX)) continue;
63004
62967
  const holder = await heldBy((0, import_node_path43.join)(dir, entry));
@@ -63284,6 +63247,7 @@ var LOCAL_API_ROUTES = {
63284
63247
  setup: "/v2/setup",
63285
63248
  logout: "/v2/logout",
63286
63249
  redial: "/v2/link/redial",
63250
+ quit: "/v2/quit",
63287
63251
  prepareUpdate: "/v2/runtime/prepare-update",
63288
63252
  nativeHook: "/v2/native/hook",
63289
63253
  localSkillInspect: "/v2/skills/local/inspect",
@@ -63376,6 +63340,9 @@ var logoutResponseSchema = external_exports.object({
63376
63340
  var redialResponseSchema = external_exports.object({
63377
63341
  accepted: external_exports.literal(true)
63378
63342
  });
63343
+ var quitResponseSchema = external_exports.object({
63344
+ stopping: external_exports.literal(true)
63345
+ });
63379
63346
  var MAX_PREPARE_UPDATE_WAIT_MS = 25e3;
63380
63347
  var prepareUpdateRequestSchema = external_exports.object({
63381
63348
  waitMs: external_exports.number().int().min(0).max(MAX_PREPARE_UPDATE_WAIT_MS)
@@ -63502,7 +63469,7 @@ var mcpConfigResultSchema = external_exports.object({
63502
63469
  });
63503
63470
 
63504
63471
  // src/client/runtime-client.ts
63505
- var import_promises44 = require("fs/promises");
63472
+ var import_promises45 = require("fs/promises");
63506
63473
  init_runtime_v2();
63507
63474
 
63508
63475
  // src/client/sse.ts
@@ -63558,7 +63525,7 @@ var DEFAULT_BACKOFF = { initialMs: 250, maxMs: 3e4 };
63558
63525
  async function readDiscovery(path4) {
63559
63526
  let text2;
63560
63527
  try {
63561
- text2 = await (0, import_promises44.readFile)(path4, "utf8");
63528
+ text2 = await (0, import_promises45.readFile)(path4, "utf8");
63562
63529
  } catch (error61) {
63563
63530
  throw new RuntimeClientError("unavailable", "The runtime is not running", { cause: error61 });
63564
63531
  }
@@ -63777,6 +63744,13 @@ function createRuntimeClient(options) {
63777
63744
  parseWith(logoutResponseSchema, await response.json(), "logout response");
63778
63745
  return { kind: "revoked" };
63779
63746
  },
63747
+ quit: async (signal) => {
63748
+ await json2(
63749
+ { method: "POST", path: LOCAL_API_ROUTES.quit, body: {} },
63750
+ quitResponseSchema,
63751
+ signal
63752
+ );
63753
+ },
63780
63754
  redial: async (signal) => {
63781
63755
  await json2(
63782
63756
  { method: "POST", path: LOCAL_API_ROUTES.redial, body: {} },
@@ -63856,7 +63830,7 @@ async function sendNativeHookSignal(discoveryPath, hookSignal, signal) {
63856
63830
 
63857
63831
  // src/sessions/index.ts
63858
63832
  var import_node_crypto24 = require("crypto");
63859
- var import_promises56 = require("fs/promises");
63833
+ var import_promises57 = require("fs/promises");
63860
63834
  var import_node_os10 = require("os");
63861
63835
  var import_node_path56 = require("path");
63862
63836
  init_runtime_v2();
@@ -64110,7 +64084,7 @@ function createConversationMcpAuthorization(options) {
64110
64084
  }
64111
64085
 
64112
64086
  // src/holder/run-inputs.ts
64113
- var import_promises49 = require("fs/promises");
64087
+ var import_promises50 = require("fs/promises");
64114
64088
  var import_node_path48 = require("path");
64115
64089
  var NO_RUN_INPUTS = {
64116
64090
  attachments: [],
@@ -64126,16 +64100,16 @@ function safeFilename(filename) {
64126
64100
  async function prepareRunInputs(spec, { source, tmpDir, signal, skills = [] }) {
64127
64101
  const dir = (0, import_node_path48.join)(tmpDir, "runs", spec.runId);
64128
64102
  const cleanup = async () => {
64129
- await (0, import_promises49.rm)(dir, { recursive: true, force: true });
64103
+ await (0, import_promises50.rm)(dir, { recursive: true, force: true });
64130
64104
  };
64131
64105
  try {
64132
64106
  const credential = await source.fetchProviderCredential(spec.runId, signal);
64133
64107
  const attachments = [];
64134
- if (spec.attachments?.length) await (0, import_promises49.mkdir)(dir, { recursive: true, mode: 448 });
64108
+ if (spec.attachments?.length) await (0, import_promises50.mkdir)(dir, { recursive: true, mode: 448 });
64135
64109
  for (const [index, attachment] of (spec.attachments ?? []).entries()) {
64136
64110
  const bytes = await source.downloadAttachment(spec.runId, attachment.id, signal);
64137
64111
  const path4 = (0, import_node_path48.join)(dir, `${index}-${safeFilename(attachment.filename)}`);
64138
- await (0, import_promises49.writeFile)(path4, bytes, { mode: 384 });
64112
+ await (0, import_promises50.writeFile)(path4, bytes, { mode: 384 });
64139
64113
  attachments.push({
64140
64114
  id: attachment.id,
64141
64115
  kind: attachment.kind,
@@ -64163,7 +64137,7 @@ init_runtime_v2();
64163
64137
 
64164
64138
  // src/holder/admission.ts
64165
64139
  var import_node_fs15 = require("fs");
64166
- var import_promises52 = require("fs/promises");
64140
+ var import_promises53 = require("fs/promises");
64167
64141
  var import_node_os9 = require("os");
64168
64142
  var import_node_path52 = require("path");
64169
64143
  init_constants();
@@ -64177,7 +64151,7 @@ function resolveAlanDefaultWorkspacePath(homeDirectory = (0, import_node_os8.hom
64177
64151
  }
64178
64152
 
64179
64153
  // src/holder/admission-relocation.ts
64180
- var import_promises50 = require("fs/promises");
64154
+ var import_promises51 = require("fs/promises");
64181
64155
  var import_node_path50 = require("path");
64182
64156
  var MAX_RELOCATION_CANDIDATES = 200;
64183
64157
  var RELOCATION_BUDGET_MS = 2e4;
@@ -64213,7 +64187,7 @@ async function originIdentity(git, path4, signal) {
64213
64187
  }
64214
64188
  async function childDirectories(parent, limit) {
64215
64189
  try {
64216
- const entries = await (0, import_promises50.readdir)(parent, { withFileTypes: true });
64190
+ const entries = await (0, import_promises51.readdir)(parent, { withFileTypes: true });
64217
64191
  return entries.filter((entry) => entry.isDirectory()).slice(0, limit).map((entry) => (0, import_node_path50.join)(parent, entry.name));
64218
64192
  } catch {
64219
64193
  return [];
@@ -64249,7 +64223,7 @@ async function discoverRelocatedWorkspace(search) {
64249
64223
  }
64250
64224
 
64251
64225
  // src/holder/lease.ts
64252
- var import_promises51 = require("fs/promises");
64226
+ var import_promises52 = require("fs/promises");
64253
64227
  var import_node_path51 = require("path");
64254
64228
  var LEASE_CHECK_EVERY_MS = 5e3;
64255
64229
  var MAX_TRANSIENT_FAILURES = 3;
@@ -64264,8 +64238,8 @@ function identityFailure(code, workspacePath) {
64264
64238
  return { code, problemCode: "app.workspace.missing", message: MESSAGES[code], workspacePath };
64265
64239
  }
64266
64240
  async function fileIdentity(path4) {
64267
- const canonical = await (0, import_promises51.realpath)(path4);
64268
- const info = await (0, import_promises51.stat)(canonical, { bigint: true });
64241
+ const canonical = await (0, import_promises52.realpath)(path4);
64242
+ const info = await (0, import_promises52.stat)(canonical, { bigint: true });
64269
64243
  return `${canonical}:${info.dev}:${info.ino}`;
64270
64244
  }
64271
64245
  async function snapshot(git, path4, signal) {
@@ -64284,7 +64258,7 @@ async function snapshot(git, path4, signal) {
64284
64258
  workspace: await fileIdentity(path4),
64285
64259
  repository: await fileIdentity(commonDir),
64286
64260
  worktree: await fileIdentity(gitDir),
64287
- commonDir: await (0, import_promises51.realpath)(commonDir)
64261
+ commonDir: await (0, import_promises52.realpath)(commonDir)
64288
64262
  };
64289
64263
  } catch {
64290
64264
  return null;
@@ -64297,7 +64271,7 @@ async function gitValue(git, path4, args, signal) {
64297
64271
  }
64298
64272
  async function pathExists(path4) {
64299
64273
  try {
64300
- await (0, import_promises51.stat)(path4);
64274
+ await (0, import_promises52.stat)(path4);
64301
64275
  return true;
64302
64276
  } catch (error61) {
64303
64277
  return errnoCode(error61) !== "ENOENT" && errnoCode(error61) !== "ENOTDIR";
@@ -64306,13 +64280,13 @@ async function pathExists(path4) {
64306
64280
  async function hasGitMarker(path4) {
64307
64281
  let directory;
64308
64282
  try {
64309
- directory = await (0, import_promises51.realpath)(path4);
64283
+ directory = await (0, import_promises52.realpath)(path4);
64310
64284
  } catch {
64311
64285
  return true;
64312
64286
  }
64313
64287
  for (; ; ) {
64314
64288
  try {
64315
- await (0, import_promises51.stat)((0, import_node_path51.join)(directory, ".git"));
64289
+ await (0, import_promises52.stat)((0, import_node_path51.join)(directory, ".git"));
64316
64290
  return true;
64317
64291
  } catch (error61) {
64318
64292
  const code = errnoCode(error61);
@@ -64482,7 +64456,7 @@ function volumeRoot(path4) {
64482
64456
  }
64483
64457
  async function exists4(path4) {
64484
64458
  try {
64485
- await (0, import_promises52.stat)(path4);
64459
+ await (0, import_promises53.stat)(path4);
64486
64460
  return true;
64487
64461
  } catch {
64488
64462
  return false;
@@ -64490,10 +64464,10 @@ async function exists4(path4) {
64490
64464
  }
64491
64465
  async function inspectReadiness(path4) {
64492
64466
  try {
64493
- if (!(await (0, import_promises52.stat)(path4)).isDirectory()) {
64467
+ if (!(await (0, import_promises53.stat)(path4)).isDirectory()) {
64494
64468
  return { ready: false, missing: true, message: MESSAGES2.missing };
64495
64469
  }
64496
- await (0, import_promises52.access)(path4, import_node_fs15.constants.R_OK | import_node_fs15.constants.W_OK | import_node_fs15.constants.X_OK);
64470
+ await (0, import_promises53.access)(path4, import_node_fs15.constants.R_OK | import_node_fs15.constants.W_OK | import_node_fs15.constants.X_OK);
64497
64471
  return { ready: true };
64498
64472
  } catch (error61) {
64499
64473
  const code = errnoCode(error61) ?? "";
@@ -64571,8 +64545,8 @@ async function admitDefaultWorkspace(spec, context, skills) {
64571
64545
  const { env } = context;
64572
64546
  const path4 = resolveAlanDefaultWorkspacePath(env.HOME || env.USERPROFILE || (0, import_node_os9.homedir)());
64573
64547
  try {
64574
- await (0, import_promises52.mkdir)(path4, { recursive: true, mode: 448 });
64575
- await (0, import_promises52.access)(path4, import_node_fs15.constants.R_OK | import_node_fs15.constants.W_OK | import_node_fs15.constants.X_OK);
64548
+ await (0, import_promises53.mkdir)(path4, { recursive: true, mode: 448 });
64549
+ await (0, import_promises53.access)(path4, import_node_fs15.constants.R_OK | import_node_fs15.constants.W_OK | import_node_fs15.constants.X_OK);
64576
64550
  return {
64577
64551
  kind: "admitted",
64578
64552
  spec: { ...spec, projectPath: path4 },
@@ -64684,7 +64658,7 @@ async function respondToTurn(runningRunId, gate, driver, request2) {
64684
64658
  }
64685
64659
 
64686
64660
  // src/holder/session-facts.ts
64687
- var import_promises53 = require("fs/promises");
64661
+ var import_promises54 = require("fs/promises");
64688
64662
  var CLI_RSS_CACHE_MS = 1e4;
64689
64663
  var LOGIN_PROBLEM_PREFIX = "cli.auth.";
64690
64664
  function isLoginFailure(result) {
@@ -64708,8 +64682,8 @@ function createSessionFacts(options) {
64708
64682
  const path4 = await resolveCommandOnPath(command, env, platform3);
64709
64683
  if (path4 === null) return null;
64710
64684
  try {
64711
- const real = await (0, import_promises53.realpath)(path4);
64712
- const info = await (0, import_promises53.stat)(real);
64685
+ const real = await (0, import_promises54.realpath)(path4);
64686
+ const info = await (0, import_promises54.stat)(real);
64713
64687
  return { command, key: `${real}:${info.ino}:${info.size}:${info.mtimeMs}` };
64714
64688
  } catch {
64715
64689
  return null;
@@ -64790,7 +64764,7 @@ var import_node_fs16 = require("fs");
64790
64764
  var import_node_path54 = require("path");
64791
64765
 
64792
64766
  // src/run-log/directory.ts
64793
- var import_promises54 = require("fs/promises");
64767
+ var import_promises55 = require("fs/promises");
64794
64768
  var import_node_path53 = require("path");
64795
64769
  init_runtime_v2();
64796
64770
  init_zod();
@@ -64810,7 +64784,7 @@ function runDirectory(runsDir, runId) {
64810
64784
  }
64811
64785
  async function isRunClaimed(runsDir, runId) {
64812
64786
  try {
64813
- return (await (0, import_promises54.stat)(runDirectory(runsDir, runId).log)).size > 0;
64787
+ return (await (0, import_promises55.stat)(runDirectory(runsDir, runId).log)).size > 0;
64814
64788
  } catch (error61) {
64815
64789
  if (errnoCode(error61) === "ENOENT") return false;
64816
64790
  throw error61;
@@ -64848,7 +64822,7 @@ async function writeCompleteRunLog(runsDir, meta3, records) {
64848
64822
  }
64849
64823
 
64850
64824
  // src/run-log/reader.ts
64851
- var import_promises55 = require("fs/promises");
64825
+ var import_promises56 = require("fs/promises");
64852
64826
  init_runtime_v2();
64853
64827
 
64854
64828
  // src/run-log/tail.ts
@@ -64871,7 +64845,7 @@ function firstRecordLength(bytes) {
64871
64845
  return bytes.indexOf(RUN_LOG_RECORD_SEPARATOR) + 1;
64872
64846
  }
64873
64847
  async function openRunLogReader(path4) {
64874
- const handle = await (0, import_promises55.open)(path4, "r");
64848
+ const handle = await (0, import_promises56.open)(path4, "r");
64875
64849
  const readAt = async (position, length) => {
64876
64850
  const buffer = Buffer.alloc(length);
64877
64851
  const { bytesRead } = await handle.read(buffer, 0, length, position);
@@ -64905,7 +64879,7 @@ async function openRunLogReader(path4) {
64905
64879
  };
64906
64880
  }
64907
64881
  async function readLastRecord(path4) {
64908
- const handle = await (0, import_promises55.open)(path4, "r").catch(() => null);
64882
+ const handle = await (0, import_promises56.open)(path4, "r").catch(() => null);
64909
64883
  if (handle === null) return null;
64910
64884
  try {
64911
64885
  const { size } = await handle.stat();
@@ -65544,7 +65518,7 @@ var DEFAULT_MAX_ACTIVE_RUNS = 32;
65544
65518
  var HOLDER_BUSY = "busy";
65545
65519
  async function listIds(dir, schema) {
65546
65520
  const ids = [];
65547
- for (const name of await (0, import_promises56.readdir)(dir).catch(() => [])) {
65521
+ for (const name of await (0, import_promises57.readdir)(dir).catch(() => [])) {
65548
65522
  const parsed = schema.safeParse(name);
65549
65523
  if (parsed.success) ids.push(parsed.data);
65550
65524
  }
@@ -65605,7 +65579,7 @@ async function openSessions(deps) {
65605
65579
  }
65606
65580
  await clock.sleep(HOLDER_READY_POLL_MS, AbortSignal.timeout(HOLDER_EXIT_GRACE_MS));
65607
65581
  }
65608
- await (0, import_promises56.rm)(files.dir, { recursive: true, force: true });
65582
+ await (0, import_promises57.rm)(files.dir, { recursive: true, force: true });
65609
65583
  for (const [runId, owner] of launched) if (owner === conversationId) launched.delete(runId);
65610
65584
  for (const runId of await listIds(paths.runs, runIdSchema)) {
65611
65585
  const meta3 = await readRunMeta(runDirectory(paths.runs, runId).meta);
@@ -65654,7 +65628,7 @@ async function openSessions(deps) {
65654
65628
  if (!await waitForExit2(holder)) return false;
65655
65629
  }
65656
65630
  legacy.delete(conversationId);
65657
- await (0, import_promises56.rm)(sessionFiles(paths, conversationId).dir, { recursive: true, force: true });
65631
+ await (0, import_promises57.rm)(sessionFiles(paths, conversationId).dir, { recursive: true, force: true });
65658
65632
  for (const runId of await unendedRunsOf(conversationId)) await markInterrupted(runId);
65659
65633
  log.info("sessions.legacy_holder_retired", { conversationId });
65660
65634
  return true;
@@ -65680,7 +65654,7 @@ async function openSessions(deps) {
65680
65654
  log.info("sessions.reattached", { conversationId });
65681
65655
  return;
65682
65656
  }
65683
- await (0, import_promises56.rm)(files.dir, { recursive: true, force: true });
65657
+ await (0, import_promises57.rm)(files.dir, { recursive: true, force: true });
65684
65658
  };
65685
65659
  const busyRunIds = async () => {
65686
65660
  const busy = /* @__PURE__ */ new Set();
@@ -65734,7 +65708,7 @@ async function openSessions(deps) {
65734
65708
  const meta3 = await readRunMeta(dir.meta);
65735
65709
  const last = await readLastRecord(dir.log);
65736
65710
  if (meta3 === null || last === null) return null;
65737
- const logged = await (0, import_promises56.stat)(dir.log).catch((error61) => {
65711
+ const logged = await (0, import_promises57.stat)(dir.log).catch((error61) => {
65738
65712
  if (errnoCode(error61) === "ENOENT") return null;
65739
65713
  throw error61;
65740
65714
  });
@@ -66086,7 +66060,7 @@ function readCliEnvironment(env = process.env) {
66086
66060
  }
66087
66061
 
66088
66062
  // src/cli/context.ts
66089
- var import_promises57 = require("fs/promises");
66063
+ var import_promises58 = require("fs/promises");
66090
66064
  var import_node_os12 = require("os");
66091
66065
  var import_node_path58 = require("path");
66092
66066
  var DESKTOP_BUNDLE_IDS = {
@@ -66136,7 +66110,7 @@ async function installedServiceSpec(ctx) {
66136
66110
  const spec = serviceSpec(ctx);
66137
66111
  if (ctx.config.host === "app") return spec;
66138
66112
  const layout = installLayout(ctx.config.installDir, ctx.config.profile);
66139
- const installed = await (0, import_promises57.access)(layout.launcher).then(
66113
+ const installed = await (0, import_promises58.access)(layout.launcher).then(
66140
66114
  () => true,
66141
66115
  () => false
66142
66116
  );
@@ -66263,7 +66237,7 @@ var manifestRevisionSchema = external_exports.object({ revision: external_export
66263
66237
  async function manifestRevision(path4) {
66264
66238
  let raw;
66265
66239
  try {
66266
- raw = JSON.parse(await (0, import_promises58.readFile)(path4, "utf8"));
66240
+ raw = JSON.parse(await (0, import_promises59.readFile)(path4, "utf8"));
66267
66241
  } catch (error61) {
66268
66242
  throw new RuntimeFault("invalid_file", `Cannot read the skill manifest at ${path4}`, {
66269
66243
  cause: error61
@@ -66317,7 +66291,7 @@ async function runSkills(argv) {
66317
66291
  }
66318
66292
 
66319
66293
  // src/cli/commands/doctor.ts
66320
- var import_promises61 = require("fs/promises");
66294
+ var import_promises62 = require("fs/promises");
66321
66295
  var import_node_path62 = require("path");
66322
66296
  init_runtime_v2();
66323
66297
 
@@ -66495,7 +66469,7 @@ async function authorizeDevice(input2) {
66495
66469
  }
66496
66470
 
66497
66471
  // src/identity/enroll.ts
66498
- var import_promises59 = require("fs/promises");
66472
+ var import_promises60 = require("fs/promises");
66499
66473
  init_runtime_v2();
66500
66474
 
66501
66475
  // src/identity/installation.ts
@@ -66566,12 +66540,12 @@ async function enrollFromGrantFile(input2) {
66566
66540
  clock: input2.clock,
66567
66541
  access: input2.access
66568
66542
  });
66569
- await (0, import_promises59.rm)(input2.grantPath, { force: true });
66543
+ await (0, import_promises60.rm)(input2.grantPath, { force: true });
66570
66544
  return machine;
66571
66545
  }
66572
66546
 
66573
66547
  // src/identity/migrate-v1.ts
66574
- var import_promises60 = require("fs/promises");
66548
+ var import_promises61 = require("fs/promises");
66575
66549
  var import_node_path60 = require("path");
66576
66550
  init_runtime_v2();
66577
66551
  init_zod();
@@ -66622,8 +66596,8 @@ async function scrubLegacyInstall(install2) {
66622
66596
  const scrubbed = { ...install2.config, migratedToRuntimeV2: true };
66623
66597
  for (const key of SCRUBBED_KEYS) delete scrubbed[key];
66624
66598
  await writeJsonFileAtomic(`${install2.configPath}.migrated-v1`, scrubbed);
66625
- await (0, import_promises60.rm)(install2.configPath, { force: true });
66626
- await (0, import_promises60.rm)(install2.ownerLeasePath, { force: true });
66599
+ await (0, import_promises61.rm)(install2.configPath, { force: true });
66600
+ await (0, import_promises61.rm)(install2.ownerLeasePath, { force: true });
66627
66601
  }
66628
66602
  async function exchangeCredential(deps) {
66629
66603
  const { config: config2 } = deps.install;
@@ -67032,7 +67006,7 @@ async function probeHolder(dir, conversationId) {
67032
67006
  }
67033
67007
  }
67034
67008
  async function holdersCheck(ctx) {
67035
- const names = await (0, import_promises61.readdir)(ctx.paths.sessions).catch(() => []);
67009
+ const names = await (0, import_promises62.readdir)(ctx.paths.sessions).catch(() => []);
67036
67010
  const holders = (await Promise.all(names.map((name) => probeHolder((0, import_node_path62.join)(ctx.paths.sessions, name), name)))).filter((facts) => facts !== null);
67037
67011
  const dead = holders.filter((holder) => !holder.alive).length;
67038
67012
  return check2(
@@ -67044,7 +67018,7 @@ async function holdersCheck(ctx) {
67044
67018
  }
67045
67019
  async function freeBytesAt(path4) {
67046
67020
  try {
67047
- const stats = await (0, import_promises61.statfs)(path4);
67021
+ const stats = await (0, import_promises62.statfs)(path4);
67048
67022
  return { path: path4, freeBytes: stats.bavail * stats.bsize };
67049
67023
  } catch (error61) {
67050
67024
  const parent = (0, import_node_path62.dirname)(path4);
@@ -67183,7 +67157,7 @@ async function runDoctor(argv, context = cliContext) {
67183
67157
  }
67184
67158
 
67185
67159
  // src/cli/commands/git-credential.ts
67186
- var import_promises62 = require("fs/promises");
67160
+ var import_promises63 = require("fs/promises");
67187
67161
  var import_node_net4 = require("net");
67188
67162
  var MAX_RESPONSE_BYTES = 64 * 1024;
67189
67163
  async function readAll(stream) {
@@ -67288,7 +67262,7 @@ async function configure(argv) {
67288
67262
  }
67289
67263
  const config2 = loadRuntimeConfig();
67290
67264
  const { launcher } = installLayout(config2.installDir, config2.profile);
67291
- const installed = await (0, import_promises62.access)(launcher).then(
67265
+ const installed = await (0, import_promises63.access)(launcher).then(
67292
67266
  () => true,
67293
67267
  () => false
67294
67268
  );
@@ -67465,7 +67439,7 @@ async function runHook(argv, overrides = {}) {
67465
67439
  }
67466
67440
 
67467
67441
  // src/cli/commands/ingestion-hooks.ts
67468
- var import_promises63 = require("fs/promises");
67442
+ var import_promises64 = require("fs/promises");
67469
67443
  var CODEX_TRUST_NOTE = "Codex runs new hooks only after you review them: open /hooks in Codex.";
67470
67444
  function isAction(value2) {
67471
67445
  return value2 === "enable" || value2 === "disable" || value2 === "status";
@@ -67488,7 +67462,7 @@ function errorMessage2(error61) {
67488
67462
  return error61 instanceof Error ? error61.message : String(error61);
67489
67463
  }
67490
67464
  async function exists5(path4) {
67491
- return (0, import_promises63.access)(path4).then(
67465
+ return (0, import_promises64.access)(path4).then(
67492
67466
  () => true,
67493
67467
  () => false
67494
67468
  );
@@ -67847,7 +67821,7 @@ async function runToken(argv, signal) {
67847
67821
  }
67848
67822
 
67849
67823
  // src/cli/commands/logout.ts
67850
- var import_promises64 = require("fs/promises");
67824
+ var import_promises65 = require("fs/promises");
67851
67825
  var import_node_path67 = require("path");
67852
67826
  init_runtime_v2();
67853
67827
  var RUNTIME_EXIT_WAIT_MS = 35e3;
@@ -67907,7 +67881,7 @@ async function stopHolder(launch, deps, outcome2) {
67907
67881
  }
67908
67882
  async function stopHeldRuns(ctx, deps, outcome2 = "aborted") {
67909
67883
  const stopped = [];
67910
- for (const name of await (0, import_promises64.readdir)(ctx.paths.sessions).catch(() => [])) {
67884
+ for (const name of await (0, import_promises65.readdir)(ctx.paths.sessions).catch(() => [])) {
67911
67885
  const launch = await readJsonFile(
67912
67886
  (0, import_node_path67.join)(ctx.paths.sessions, name, "launch.json"),
67913
67887
  holderLaunchSchema
@@ -67946,7 +67920,7 @@ async function forgetMachineLocally(ctx) {
67946
67920
  const machine = await readMachineFile(ctx.paths);
67947
67921
  if (machine === null) return;
67948
67922
  await credentialStoreFor(ctx.paths, machine.credentialStore, ctx.access).clear();
67949
- await (0, import_promises64.rm)(ctx.paths.machine, { force: true });
67923
+ await (0, import_promises65.rm)(ctx.paths.machine, { force: true });
67950
67924
  }
67951
67925
  async function runLogout(argv, signal) {
67952
67926
  var _stack = [];
@@ -67971,6 +67945,35 @@ async function runLogout(argv, signal) {
67971
67945
  // src/cli/commands/run.ts
67972
67946
  var import_node_path71 = require("path");
67973
67947
 
67948
+ // src/local-api/app-attachments.ts
67949
+ function createAppAttachments(clock) {
67950
+ const state = {
67951
+ open: 0,
67952
+ quit: false,
67953
+ lostSinceMs: null
67954
+ };
67955
+ return {
67956
+ attach: () => {
67957
+ state.open += 1;
67958
+ state.lostSinceMs = null;
67959
+ const stream = { closed: false };
67960
+ return {
67961
+ [Symbol.dispose]: () => {
67962
+ if (stream.closed) return;
67963
+ stream.closed = true;
67964
+ state.open -= 1;
67965
+ if (state.open === 0) state.lostSinceMs = clock.monotonic();
67966
+ }
67967
+ };
67968
+ },
67969
+ quit: () => {
67970
+ state.quit = true;
67971
+ },
67972
+ quitRequested: () => state.quit,
67973
+ lostSinceMs: () => state.open === 0 ? state.lostSinceMs : null
67974
+ };
67975
+ }
67976
+
67974
67977
  // src/local-api/run-appends.ts
67975
67978
  function createRunAppends() {
67976
67979
  const waiters = /* @__PURE__ */ new Map();
@@ -68006,7 +68009,7 @@ function createRunAppends() {
68006
68009
 
68007
68010
  // src/local-api/server.ts
68008
68011
  var import_node_crypto28 = require("crypto");
68009
- var import_promises65 = require("fs/promises");
68012
+ var import_promises66 = require("fs/promises");
68010
68013
  var import_node_http4 = require("http");
68011
68014
  var import_node_path68 = require("path");
68012
68015
 
@@ -68326,10 +68329,11 @@ var emptyBodySchema = external_exports.object({});
68326
68329
  function activeRunIds(runs) {
68327
68330
  return runs.filter((run2) => run2.state !== "ended").map((run2) => run2.runId);
68328
68331
  }
68329
- var streamStatus = async ({ feed }, { res, signal }) => {
68332
+ var streamStatus = async ({ feed, appAttachments }, { res, signal }) => {
68330
68333
  var _stack = [];
68331
68334
  try {
68332
68335
  const snapshot2 = await feed.refresh(signal);
68336
+ const _attachment = __using(_stack, appAttachments.attach());
68333
68337
  startEventStream(res);
68334
68338
  const send2 = (name, event) => writeEvent(res, { name, id: String(event.seq), dataLines: [JSON.stringify(event)] });
68335
68339
  let latest = null;
@@ -68425,6 +68429,12 @@ var redial = async ({ actions }, request2) => {
68425
68429
  const result = { accepted: true };
68426
68430
  sendJson(request2.res, 202, result);
68427
68431
  };
68432
+ var quit = async ({ appAttachments }, request2) => {
68433
+ if (await readBody3(request2, emptyBodySchema) === null) return;
68434
+ appAttachments.quit();
68435
+ const result = { stopping: true };
68436
+ sendJson(request2.res, 202, result);
68437
+ };
68428
68438
  var nativeHook = async ({ actions }, request2) => {
68429
68439
  const body = await readBody3(request2, nativeHookSignalSchema);
68430
68440
  if (body === null) return;
@@ -68455,6 +68465,7 @@ var FIXED_ROUTES = new Map([
68455
68465
  [LOCAL_API_ROUTES.setup, { method: "POST", handle: setup }],
68456
68466
  [LOCAL_API_ROUTES.logout, { method: "POST", handle: logout }],
68457
68467
  [LOCAL_API_ROUTES.redial, { method: "POST", handle: redial }],
68468
+ [LOCAL_API_ROUTES.quit, { method: "POST", handle: quit }],
68458
68469
  [LOCAL_API_ROUTES.prepareUpdate, { method: "POST", handle: prepareUpdate }],
68459
68470
  [LOCAL_API_ROUTES.nativeHook, { method: "POST", handle: nativeHook }],
68460
68471
  ...machineFeatureRoutes
@@ -68580,8 +68591,10 @@ async function serveLocalApi(deps) {
68580
68591
  const port = await listenOnLoopback(server);
68581
68592
  const token = (0, import_node_crypto28.randomBytes)(32).toString("base64url");
68582
68593
  const guard = createRequestGuard({ token, port, rateLimit: limits.rateLimit, clock });
68594
+ const appAttachments = createAppAttachments(clock);
68583
68595
  const routeDeps = {
68584
68596
  feed,
68597
+ appAttachments,
68585
68598
  actions: deps.actions,
68586
68599
  runsDir: deps.runsDir,
68587
68600
  appends: deps.appends,
@@ -68649,12 +68662,13 @@ async function serveLocalApi(deps) {
68649
68662
  refreshStatus: async () => {
68650
68663
  if (feed.subscriberCount() > 0) await feed.refresh(AbortSignal.timeout(ACTION_TIMEOUT_MS));
68651
68664
  },
68665
+ appAttachments,
68652
68666
  [Symbol.asyncDispose]: async () => {
68653
68667
  await followers[Symbol.asyncDispose]();
68654
68668
  await watchedStatus[Symbol.asyncDispose]();
68655
68669
  const current = await readJsonFile(discoveryPath, localApiDiscoverySchema);
68656
68670
  if (current.kind === "ok" && current.value.token === token) {
68657
- await (0, import_promises65.rm)(discoveryPath, { force: true });
68671
+ await (0, import_promises66.rm)(discoveryPath, { force: true });
68658
68672
  }
68659
68673
  await closeServer(server);
68660
68674
  log.info("local_api.closed", {});
@@ -68662,6 +68676,43 @@ async function serveLocalApi(deps) {
68662
68676
  };
68663
68677
  }
68664
68678
 
68679
+ // src/cli/commands/app-gone.ts
68680
+ var APP_GONE_CHECK_MS = 1e3;
68681
+ var APP_GONE_GRACE_MS = 1e4;
68682
+ function watchAppGone(options) {
68683
+ const { appAttachments, clock, lifecycle, log } = options;
68684
+ const graceMs = options.graceMs ?? APP_GONE_GRACE_MS;
68685
+ const stop = new AbortController();
68686
+ const goneFor = () => {
68687
+ const lostSinceMs = appAttachments.lostSinceMs();
68688
+ return lostSinceMs === null ? null : clock.monotonic() - lostSinceMs;
68689
+ };
68690
+ const check3 = async (signal) => {
68691
+ if (stop.signal.aborted) return;
68692
+ const quit2 = appAttachments.quitRequested();
68693
+ const gone = goneFor();
68694
+ if (!quit2 && (gone === null || gone < graceMs)) return;
68695
+ const stopped = await lifecycle.exclusive("stop_app_gone", async () => {
68696
+ if (!quit2 && goneFor() === null) return false;
68697
+ await options.interruptAllRuns(signal);
68698
+ return true;
68699
+ });
68700
+ if (!stopped) return;
68701
+ log.info(quit2 ? "runtime.app_quit" : "runtime.app_gone_stop", { goneMs: gone });
68702
+ stop.abort();
68703
+ };
68704
+ const maintenance = startMaintenance({
68705
+ everyMs: options.everyMs ?? APP_GONE_CHECK_MS,
68706
+ jobs: [{ name: "runtime.app_gone_check", run: check3 }],
68707
+ clock,
68708
+ log
68709
+ });
68710
+ return {
68711
+ stopRequested: stop.signal,
68712
+ [Symbol.asyncDispose]: () => maintenance[Symbol.asyncDispose]()
68713
+ };
68714
+ }
68715
+
68665
68716
  // src/cli/commands/machine-features.ts
68666
68717
  async function skillRead(read) {
68667
68718
  try {
@@ -72370,7 +72421,7 @@ function refusalFailure(refusal2) {
72370
72421
  }
72371
72422
 
72372
72423
  // src/link/probe.ts
72373
- var import_promises66 = require("dns/promises");
72424
+ var import_promises67 = require("dns/promises");
72374
72425
  var import_node_net5 = require("net");
72375
72426
  var import_node_tls2 = require("tls");
72376
72427
  var PROBE_TIMEOUT_MS4 = 5e3;
@@ -72406,7 +72457,7 @@ async function connectOnce(url3, clock) {
72406
72457
  }
72407
72458
  async function probeEndpoint(url3, clock) {
72408
72459
  try {
72409
- await (0, import_promises66.lookup)(url3.hostname);
72460
+ await (0, import_promises67.lookup)(url3.hostname);
72410
72461
  } catch (error61) {
72411
72462
  const reason = classifyTransportFailure(error61);
72412
72463
  return reason === "other" ? "dns" : reason;
@@ -72842,7 +72893,7 @@ function createReconciler(host, lifecycle, log, signal) {
72842
72893
  }
72843
72894
 
72844
72895
  // src/uploader/index.ts
72845
- var import_promises67 = require("fs/promises");
72896
+ var import_promises68 = require("fs/promises");
72846
72897
  init_runtime_v2();
72847
72898
  init_zod();
72848
72899
  var RETRY_DELAYS_MS = [250, 500, 1e3, 2e3, 5e3, 1e4, 3e4];
@@ -72982,23 +73033,29 @@ function startUploader({ api, runsDir, clock, log }) {
72982
73033
  });
72983
73034
  active.set(runId, task);
72984
73035
  };
73036
+ const sweep2 = async () => {
73037
+ for (const name of await (0, import_promises68.readdir)(runsDir).catch(() => [])) {
73038
+ const runId = runIdSchema.safeParse(name);
73039
+ if (runId.success) run2(runId.data);
73040
+ }
73041
+ };
72985
73042
  const isPrunable = async (runId, options) => {
72986
73043
  if (options.keep.has(runId) || active.has(runId)) return false;
72987
73044
  const dir = runDirectory(runsDir, runId);
72988
73045
  const progress = await readJsonFile(dir.upload, uploadProgressSchema);
72989
73046
  if (progress.kind !== "ok" || !progress.value.sealed) return false;
72990
- const sealedAt = (await (0, import_promises67.stat)(dir.upload)).mtimeMs;
73047
+ const sealedAt = (await (0, import_promises68.stat)(dir.upload)).mtimeMs;
72991
73048
  if (clock.now() - sealedAt < options.sealedForMs) return false;
72992
73049
  return (await readLastRecord(dir.log))?.update.sessionUpdate === "_alan/run.ended";
72993
73050
  };
72994
73051
  const prune = async (options) => {
72995
73052
  let removed = 0;
72996
- for (const name of await (0, import_promises67.readdir)(runsDir).catch(() => [])) {
73053
+ for (const name of await (0, import_promises68.readdir)(runsDir).catch(() => [])) {
72997
73054
  const runId = runIdSchema.safeParse(name);
72998
73055
  if (!runId.success) continue;
72999
73056
  try {
73000
73057
  if (!await isPrunable(runId.data, options)) continue;
73001
- await (0, import_promises67.rm)(runDirectory(runsDir, runId.data).dir, { recursive: true, force: true });
73058
+ await (0, import_promises68.rm)(runDirectory(runsDir, runId.data).dir, { recursive: true, force: true });
73002
73059
  removed += 1;
73003
73060
  } catch (error61) {
73004
73061
  log.warn("upload.prune_failed", { runId: runId.data, error: error61 });
@@ -73009,10 +73066,11 @@ function startUploader({ api, runsDir, clock, log }) {
73009
73066
  return {
73010
73067
  notify: run2,
73011
73068
  prune,
73012
- sweep: async () => {
73013
- for (const name of await (0, import_promises67.readdir)(runsDir).catch(() => [])) {
73014
- const runId = runIdSchema.safeParse(name);
73015
- if (runId.success) run2(runId.data);
73069
+ sweep: sweep2,
73070
+ flush: async () => {
73071
+ await sweep2();
73072
+ while (active.size > 0 && !controller.signal.aborted) {
73073
+ await Promise.allSettled([...active.values()]);
73016
73074
  }
73017
73075
  },
73018
73076
  [Symbol.asyncDispose]: async () => {
@@ -73767,7 +73825,7 @@ async function startMachinePlane(deps) {
73767
73825
  const result = await workspaces.answer({ method: "workspace.status", path: path4 });
73768
73826
  return result.ok ? { ok: true } : { ok: false, message: result.error.message };
73769
73827
  },
73770
- flushUploads: () => uploader.sweep(),
73828
+ flushUploads: () => uploader.flush(),
73771
73829
  nativeHook: (hookSignal) => nativeIngest.accept(hookSignal),
73772
73830
  rescanLocalSkills: () => skills.rescan(),
73773
73831
  apiUrl: identity.endpoints.apiUrl,
@@ -73783,6 +73841,10 @@ async function startMachinePlane(deps) {
73783
73841
 
73784
73842
  // src/cli/commands/machine-slot.ts
73785
73843
  var NOT_SET_UP_LINK = { state: "stopped" };
73844
+ var FINAL_UPLOAD_WAIT_MS = 2e4;
73845
+ function sameOrigin(requested, configured) {
73846
+ return URL.canParse(requested) && new URL(requested).origin === new URL(configured).origin;
73847
+ }
73786
73848
  function faultMessage(error61) {
73787
73849
  return error61 instanceof Error ? error61.message : String(error61);
73788
73850
  }
@@ -73857,6 +73919,13 @@ function createMachineSlot(deps) {
73857
73919
  message: "This computer is already set up; log out first"
73858
73920
  };
73859
73921
  }
73922
+ if (!sameOrigin(request2.apiUrl, ctx.config.apiUrl)) {
73923
+ return {
73924
+ kind: "refused",
73925
+ code: "setup_failed",
73926
+ message: `This computer's ${ctx.config.profile} runtime serves ${ctx.config.apiUrl}, not ${request2.apiUrl}`
73927
+ };
73928
+ }
73860
73929
  await close2();
73861
73930
  const setupCtx = cliContext({ ...ctx.config, apiUrl: request2.apiUrl });
73862
73931
  try {
@@ -73892,9 +73961,23 @@ function createMachineSlot(deps) {
73892
73961
  throw error61;
73893
73962
  }
73894
73963
  };
73964
+ const interruptAllRuns = async (signal) => {
73965
+ const plane = slot.plane;
73966
+ if (plane === null) return;
73967
+ const stopped = await stopHeldRuns(ctx, logoutDeps(signal), "interrupted");
73968
+ const waited = new AbortController();
73969
+ await Promise.race([
73970
+ plane.flushUploads().catch((error61) => log.warn("runtime.flush_failed", { error: error61 })),
73971
+ clock.sleep(FINAL_UPLOAD_WAIT_MS, AbortSignal.any([signal, waited.signal])).catch(() => {
73972
+ })
73973
+ ]);
73974
+ waited.abort();
73975
+ log.info("runtime.runs_interrupted", { stopped });
73976
+ };
73895
73977
  return {
73896
73978
  open: open5,
73897
73979
  plane: () => slot.plane,
73980
+ interruptAllRuns,
73898
73981
  facts: () => {
73899
73982
  const plane = slot.plane;
73900
73983
  if (plane === null) return { machineId: null, setup: "none", link: NOT_SET_UP_LINK };
@@ -74051,6 +74134,13 @@ async function runService(argv, stop, restart = new AbortController().signal) {
74051
74134
  clock,
74052
74135
  log
74053
74136
  }), true);
74137
+ const appGone = __using(_stack, watchAppGone({
74138
+ appAttachments: localApi.appAttachments,
74139
+ lifecycle,
74140
+ interruptAllRuns: (signal) => machine.interruptAllRuns(signal),
74141
+ clock,
74142
+ log
74143
+ }), true);
74054
74144
  log.info("runtime.started", {
74055
74145
  machineId: machine.facts().machineId,
74056
74146
  setup: machine.facts().setup,
@@ -74059,7 +74149,7 @@ async function runService(argv, stop, restart = new AbortController().signal) {
74059
74149
  });
74060
74150
  return await awaitRuntimeExit(
74061
74151
  {
74062
- stop: AbortSignal.any([stop, stopForUpdate.signal]),
74152
+ stop: AbortSignal.any([stop, stopForUpdate.signal, appGone.stopRequested]),
74063
74153
  restart: AbortSignal.any([
74064
74154
  restart,
74065
74155
  updateInstalled.signal,
@@ -74115,17 +74205,17 @@ async function runServiceCommand(argv, ctx = cliContext()) {
74115
74205
  }
74116
74206
 
74117
74207
  // src/cli/commands/upgrade.ts
74118
- var import_promises68 = require("fs/promises");
74208
+ var import_promises69 = require("fs/promises");
74119
74209
  var import_node_path72 = require("path");
74120
74210
  function isNotNewer(version2, installed) {
74121
74211
  return installed !== null && isReleaseVersion(version2) && isReleaseVersion(installed) && compareVersions(version2, installed) <= 0;
74122
74212
  }
74123
74213
  async function installFromSource(source) {
74124
74214
  const { layout, from, ifNewer } = source;
74125
- const isTarball = (await (0, import_promises68.stat)(from)).isFile();
74215
+ const isTarball = (await (0, import_promises69.stat)(from)).isFile();
74126
74216
  const downloads = (0, import_node_path72.join)(layout.root, ".downloads");
74127
- if (isTarball) await (0, import_promises68.mkdir)(downloads, { recursive: true, mode: 448 });
74128
- const scratch = isTarball ? await (0, import_promises68.mkdtemp)((0, import_node_path72.join)(downloads, "upgrade-")) : null;
74217
+ if (isTarball) await (0, import_promises69.mkdir)(downloads, { recursive: true, mode: 448 });
74218
+ const scratch = isTarball ? await (0, import_promises69.mkdtemp)((0, import_node_path72.join)(downloads, "upgrade-")) : null;
74129
74219
  try {
74130
74220
  const sourceDir = scratch === null ? from : await extractPackageTarball(from, scratch);
74131
74221
  const version2 = await readPackageVersion(sourceDir);
@@ -74133,7 +74223,7 @@ async function installFromSource(source) {
74133
74223
  if (ifNewer && isNotNewer(version2, installed)) return { kind: "skipped", version: version2, installed };
74134
74224
  return { kind: "installed", ...await installVersion(layout, sourceDir) };
74135
74225
  } finally {
74136
- if (scratch !== null) await (0, import_promises68.rm)(scratch, { recursive: true, force: true });
74226
+ if (scratch !== null) await (0, import_promises69.rm)(scratch, { recursive: true, force: true });
74137
74227
  }
74138
74228
  }
74139
74229
  async function runUpgrade(argv) {