@alan-ai-hq/agent-manager-linux-arm64 0.1.137 → 0.1.138

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 +1915 -309
  2. package/alan-holder.cjs +170 -52
  3. package/package.json +1 -1
package/alan-agent.cjs CHANGED
@@ -21762,6 +21762,9 @@ For any UI or design work, read and follow the \`uiux\` skill in \`.agents/skill
21762
21762
  });
21763
21763
 
21764
21764
  // ../shared/dist/agent/attachment-mention.js
21765
+ function attachmentMentionPattern() {
21766
+ return /@\[attachment:([^:\]\s]+):(.*?)\](?=[.,;:!?)]*(?:\s|$))/gi;
21767
+ }
21765
21768
  var init_attachment_mention = __esm({
21766
21769
  "../shared/dist/agent/attachment-mention.js"() {
21767
21770
  "use strict";
@@ -22238,6 +22241,22 @@ var init_agent = __esm({
22238
22241
  }
22239
22242
  });
22240
22243
 
22244
+ // ../shared/dist/agent/transcript/preview.js
22245
+ function toPreviewText(value2, limit) {
22246
+ const text2 = value2.replace(/```[\s\S]*?```/g, (block) => block.replace(/```\w*\n?|```/g, " ")).replace(/!\[[^\]]*\]\([^)]*\)/g, "").replace(/\[([^\]]+)\]\([^)]*\)/g, "$1").replace(/`([^`]+)`/g, "$1").replace(/^\s{0,3}#{1,6}\s+/gm, "").replace(/^\s{0,3}>\s?/gm, "").replace(/^\s{0,3}(?:[-*+]|\d+\.)\s+/gm, "").replace(/^\s{0,3}(?:[-*_]\s*){3,}$/gm, "").replace(/\*\*([^*]+)\*\*/g, "$1").replace(/__([^_]+)__/g, "$1").replace(/\*([^*\n]+)\*/g, "$1").replace(/~~([^~]+)~~/g, "$1").replace(/\s+/g, " ").trim();
22247
+ if (text2.length <= limit)
22248
+ return text2;
22249
+ const clipped = text2.slice(0, limit - 1);
22250
+ const lastSpace = clipped.lastIndexOf(" ");
22251
+ const body = lastSpace > limit * 0.6 ? clipped.slice(0, lastSpace) : clipped;
22252
+ return `${body.trimEnd()}\u2026`;
22253
+ }
22254
+ var init_preview = __esm({
22255
+ "../shared/dist/agent/transcript/preview.js"() {
22256
+ "use strict";
22257
+ }
22258
+ });
22259
+
22241
22260
  // ../shared/dist/agent/transcript/index.js
22242
22261
  var init_transcript = __esm({
22243
22262
  "../shared/dist/agent/transcript/index.js"() {
@@ -22344,23 +22363,31 @@ var init_chunk_YXWJW7I5 = __esm({
22344
22363
  }
22345
22364
  });
22346
22365
 
22347
- // ../agent-core/dist/chunk-J4T6L5LX.js
22366
+ // ../agent-core/dist/chunk-M6YHY2EZ.js
22348
22367
  function windowsEnvValue(env, name) {
22349
22368
  const wanted = name.toLowerCase();
22350
- for (const [key, value2] of Object.entries(env)) {
22369
+ for (const [key, value2] of Object.entries(env).reverse()) {
22351
22370
  if (key.toLowerCase() === wanted) return value2;
22352
22371
  }
22353
22372
  return void 0;
22354
22373
  }
22374
+ function canonicalWindowsEnvironment(env) {
22375
+ const unique2 = /* @__PURE__ */ new Map();
22376
+ for (const [name, value2] of Object.entries(env)) {
22377
+ unique2.set(name.toLowerCase(), [name.toLowerCase() === "path" ? "PATH" : name, value2]);
22378
+ }
22379
+ return Object.fromEntries(unique2.values());
22380
+ }
22355
22381
  function hasExtension(name, extensions) {
22356
22382
  const ext = import_path.win32.extname(name).toLowerCase();
22357
22383
  return ext.length > 0 && extensions.includes(ext);
22358
22384
  }
22359
22385
  function candidates(base, extensions) {
22360
- return hasExtension(base, extensions) ? [base] : extensions.map((ext) => `${base}${ext}`);
22386
+ const extension = import_path.win32.extname(base).toLowerCase();
22387
+ return extension === ".exe" || extension === ".com" || hasExtension(base, extensions) ? [base] : extensions.map((ext) => `${base}${ext}`);
22361
22388
  }
22362
22389
  function resolveWindowsCommand(command, env, files) {
22363
- const extensions = (windowsEnvValue(env, "PATHEXT") ?? DEFAULT_PATHEXT).split(";").map((ext) => ext.trim().toLowerCase()).filter((ext) => ext.startsWith("."));
22390
+ const extensions = (windowsEnvValue(env, "PATHEXT") ?? DEFAULT_PATHEXT).split(";").map((ext) => ext.trim().toLowerCase()).filter((ext) => LAUNCHABLE_EXTENSIONS.has(ext));
22364
22391
  if (/[\\/]/.test(command)) {
22365
22392
  return candidates(command, extensions).find((path4) => files.isFile(path4));
22366
22393
  }
@@ -22373,6 +22400,18 @@ function resolveWindowsCommand(command, env, files) {
22373
22400
  }
22374
22401
  return void 0;
22375
22402
  }
22403
+ function unwrapNativeShim(shim, args, files) {
22404
+ const lines2 = files.readShim(shim)?.split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
22405
+ if (lines2?.length !== NATIVE_SHIM_LINES.length + 1) return void 0;
22406
+ if (!NATIVE_SHIM_LINES.every((pattern, index) => pattern.test(lines2[index] ?? ""))) {
22407
+ return void 0;
22408
+ }
22409
+ const target = NATIVE_SHIM_ENTRY.exec(lines2.at(-1) ?? "")?.[1];
22410
+ if (target === void 0) return void 0;
22411
+ const directory = import_path.win32.dirname(shim);
22412
+ const file2 = import_path.win32.resolve(directory, target.replace(/^%dp0%\\/i, ""));
22413
+ return files.isFile(file2) ? { kind: "native", file: file2, args } : void 0;
22414
+ }
22376
22415
  function isSimpleNodeShim(text2) {
22377
22416
  return text2.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0).every((line) => /^@?echo off$/i.test(line) || NODE_SHIM_ENTRY.test(line));
22378
22417
  }
@@ -22398,7 +22437,7 @@ function planWindowsLaunch(command, args, env, files) {
22398
22437
  const file2 = resolveWindowsCommand(command, env, files);
22399
22438
  if (file2 === void 0) return void 0;
22400
22439
  if (!/\.(cmd|bat)$/i.test(file2)) return { kind: "native", file: file2, args };
22401
- return unwrapNodeShim(file2, args, env, files) ?? { kind: "batch", file: file2, args };
22440
+ return unwrapNativeShim(file2, args, files) ?? unwrapNodeShim(file2, args, env, files) ?? { kind: "batch", file: file2, args };
22402
22441
  }
22403
22442
  function quoteWindowsArgument(value2) {
22404
22443
  if (value2.length === 0) return '""';
@@ -22900,11 +22939,12 @@ function onCliSpawned(listener) {
22900
22939
  }
22901
22940
  function spawnCli(options) {
22902
22941
  const platform3 = options.platform ?? process.platform;
22903
- const plan2 = planSpawn({ ...options, platform: platform3 });
22904
- if (plan2.commandLine !== null) return spawnInWindowsJob(plan2, options);
22942
+ const env = platform3 === "win32" ? canonicalWindowsEnvironment(options.env) : options.env;
22943
+ const plan2 = planSpawn({ ...options, env, platform: platform3 });
22944
+ if (plan2.commandLine !== null) return spawnInWindowsJob(plan2, { ...options, env });
22905
22945
  const child = (0, import_child_process5.spawn)(plan2.file, [...plan2.args], {
22906
22946
  cwd: options.cwd,
22907
- env: { ...options.env },
22947
+ env: { ...env },
22908
22948
  stdio: ["pipe", "pipe", "pipe"],
22909
22949
  shell: false,
22910
22950
  detached: true
@@ -22931,9 +22971,9 @@ function waitForSpawn(child, command) {
22931
22971
  child.once("error", onError);
22932
22972
  });
22933
22973
  }
22934
- 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, spawnListeners;
22935
- var init_chunk_J4T6L5LX = __esm({
22936
- "../agent-core/dist/chunk-J4T6L5LX.js"() {
22974
+ 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, LAUNCHABLE_EXTENSIONS, nodeWindowsFiles, NODE_SHIM_ENTRY, NATIVE_SHIM_LINES, NATIVE_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, spawnListeners;
22975
+ var init_chunk_M6YHY2EZ = __esm({
22976
+ "../agent-core/dist/chunk-M6YHY2EZ.js"() {
22937
22977
  "use strict";
22938
22978
  init_chunk_YXWJW7I5();
22939
22979
  import_child_process = require("child_process");
@@ -22954,6 +22994,7 @@ var init_chunk_J4T6L5LX = __esm({
22954
22994
  CMD_MAX_COMMAND_LINE = 8191;
22955
22995
  MAX_COMMAND_LINE = 32766;
22956
22996
  DEFAULT_PATHEXT = ".COM;.EXE;.BAT;.CMD";
22997
+ LAUNCHABLE_EXTENSIONS = /* @__PURE__ */ new Set([".com", ".exe", ".bat", ".cmd"]);
22957
22998
  nodeWindowsFiles = {
22958
22999
  isFile: (path4) => {
22959
23000
  try {
@@ -22972,6 +23013,17 @@ var init_chunk_J4T6L5LX = __esm({
22972
23013
  }
22973
23014
  };
22974
23015
  NODE_SHIM_ENTRY = /"(%_prog%|[^"\r\n]*node(?:\.exe)?)"\s+"([^"\r\n]+\.(?:c?js|mjs))"\s+%\*/i;
23016
+ NATIVE_SHIM_LINES = [
23017
+ /^@echo off$/i,
23018
+ /^goto start$/i,
23019
+ /^:find_dp0$/i,
23020
+ /^set dp0=%~dp0$/i,
23021
+ /^exit \/b$/i,
23022
+ /^:start$/i,
23023
+ /^setlocal$/i,
23024
+ /^call :find_dp0$/i
23025
+ ];
23026
+ NATIVE_SHIM_ENTRY = /^"(%dp0%\\(?:\.\.\\)?(?:node_modules\\)?[\w@.-]+(?:\\[\w@.-]+)*\.exe)"\s+%\*$/i;
22975
23027
  CMD_META = /([()\][%!^"`<>&|;, *?])/g;
22976
23028
  NEVER_STARTED = { stdout: "", stderr: "", exitCode: void 0 };
22977
23029
  HIDDEN_FLAG_PROBE_VALUE = "__alan_probe__";
@@ -23729,29 +23781,209 @@ var init_constants = __esm({
23729
23781
  });
23730
23782
 
23731
23783
  // ../shared/dist/agent/acp/transcript-http.js
23784
+ var TRANSCRIPT_TOOL_RESPONSE_ID_META, TRANSCRIPT_TURN_ID_META;
23732
23785
  var init_transcript_http = __esm({
23733
23786
  "../shared/dist/agent/acp/transcript-http.js"() {
23734
23787
  "use strict";
23788
+ TRANSCRIPT_TOOL_RESPONSE_ID_META = "alan.dev/transcriptToolResponseId";
23789
+ TRANSCRIPT_TURN_ID_META = "alan.dev/transcriptTurnId";
23735
23790
  }
23736
23791
  });
23737
23792
 
23738
23793
  // ../shared/dist/agent/acp/ask.js
23794
+ function asRecord2(value2) {
23795
+ return value2 && typeof value2 === "object" && !Array.isArray(value2) ? value2 : void 0;
23796
+ }
23797
+ function readOptions(value2) {
23798
+ if (!Array.isArray(value2))
23799
+ return [];
23800
+ const options = [];
23801
+ for (const raw of value2) {
23802
+ const option2 = asRecord2(raw);
23803
+ const label = typeof option2?.label === "string" ? option2.label : void 0;
23804
+ if (!label)
23805
+ continue;
23806
+ options.push({
23807
+ label,
23808
+ description: typeof option2?.description === "string" ? option2.description : void 0
23809
+ });
23810
+ }
23811
+ return options;
23812
+ }
23813
+ function readQuestions(input2) {
23814
+ const record2 = asRecord2(input2);
23815
+ const raw = record2?.questions;
23816
+ if (!Array.isArray(raw))
23817
+ return [];
23818
+ const questions = [];
23819
+ for (const item of raw) {
23820
+ const entry = asRecord2(item);
23821
+ const question = typeof entry?.question === "string" ? entry.question : void 0;
23822
+ if (!question)
23823
+ continue;
23824
+ questions.push({
23825
+ question,
23826
+ header: typeof entry?.header === "string" ? entry.header : void 0,
23827
+ options: readOptions(entry?.options),
23828
+ multiSelect: entry?.multiSelect === true
23829
+ });
23830
+ }
23831
+ return questions;
23832
+ }
23833
+ function isAskToolCall(entry) {
23834
+ const name = entry.title || entry.toolKind;
23835
+ return isAskUserQuestionTool(name, entry.rawInput);
23836
+ }
23837
+ function findPendingAsk(entries, answeredIds = /* @__PURE__ */ new Set()) {
23838
+ for (let index = entries.length - 1; index >= 0; index -= 1) {
23839
+ const entry = entries[index];
23840
+ if (!entry || entry.kind !== "tool_call")
23841
+ continue;
23842
+ if (entry.status === "completed" || entry.status === "failed" || entry.status === "cancelled") {
23843
+ continue;
23844
+ }
23845
+ if (answeredIds.has(entry.id))
23846
+ continue;
23847
+ if (!isAskToolCall(entry))
23848
+ continue;
23849
+ const questions = readQuestions(entry.rawInput);
23850
+ if (questions.length === 0)
23851
+ continue;
23852
+ return { toolCallId: entry.id, questions, rawInput: asRecord2(entry.rawInput) ?? {} };
23853
+ }
23854
+ return null;
23855
+ }
23739
23856
  var init_ask = __esm({
23740
23857
  "../shared/dist/agent/acp/ask.js"() {
23741
23858
  "use strict";
23859
+ init_agent();
23742
23860
  }
23743
23861
  });
23744
23862
 
23745
23863
  // ../shared/dist/agent/acp/background-task.js
23746
- var BACKGROUND_TASK_META_KEY;
23864
+ function oneOf(values, value2) {
23865
+ return typeof value2 === "string" && values.some((candidate) => candidate === value2);
23866
+ }
23867
+ function isRecord6(value2) {
23868
+ return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
23869
+ }
23870
+ function optionalString(value2) {
23871
+ return typeof value2 === "string" && value2.length > 0 ? value2 : void 0;
23872
+ }
23873
+ function readBackgroundTaskMeta(meta3) {
23874
+ if (!isRecord6(meta3))
23875
+ return null;
23876
+ const raw = meta3[BACKGROUND_TASK_META_KEY];
23877
+ if (!isRecord6(raw))
23878
+ return null;
23879
+ const taskId = optionalString(raw.taskId);
23880
+ if (!taskId)
23881
+ return null;
23882
+ const kind = oneOf(KINDS, raw.kind) ? raw.kind : void 0;
23883
+ const stop = oneOf(STRATEGIES, raw.stop) ? raw.stop : void 0;
23884
+ const status = oneOf(STATUSES, raw.status) ? raw.status : void 0;
23885
+ const label = optionalString(raw.label);
23886
+ const subagentType = optionalString(raw.subagentType);
23887
+ const taskType = optionalString(raw.taskType);
23888
+ return {
23889
+ taskId,
23890
+ backgrounded: raw.backgrounded === true,
23891
+ ...kind ? { kind } : {},
23892
+ ...label ? { label } : {},
23893
+ ...typeof raw.startedAt === "number" ? { startedAt: raw.startedAt } : {},
23894
+ ...stop ? { stop } : {},
23895
+ ...status ? { status } : {},
23896
+ ...raw.stoppedByUser === true ? { stoppedByUser: true } : {},
23897
+ ...subagentType ? { subagentType } : {},
23898
+ ...taskType ? { taskType } : {},
23899
+ ...typeof raw.spawnDepth === "number" ? { spawnDepth: raw.spawnDepth } : {},
23900
+ ...raw.ownedBySubagent === true ? { ownedBySubagent: true } : {}
23901
+ };
23902
+ }
23903
+ var BACKGROUND_TASK_META_KEY, KINDS, STRATEGIES, STATUSES;
23747
23904
  var init_background_task = __esm({
23748
23905
  "../shared/dist/agent/acp/background-task.js"() {
23749
23906
  "use strict";
23750
23907
  BACKGROUND_TASK_META_KEY = "alan.dev/backgroundTask";
23908
+ KINDS = ["shell", "agent"];
23909
+ STRATEGIES = [
23910
+ "native",
23911
+ "pid",
23912
+ "none"
23913
+ ];
23914
+ STATUSES = [
23915
+ "running",
23916
+ "stopping",
23917
+ "stopped",
23918
+ "completed",
23919
+ "failed"
23920
+ ];
23751
23921
  }
23752
23922
  });
23753
23923
 
23754
23924
  // ../shared/dist/agent/acp/presentation/terminal-events.js
23925
+ function isRecord7(value2) {
23926
+ return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
23927
+ }
23928
+ function foldPreview(events) {
23929
+ const output2 = [];
23930
+ const slots = /* @__PURE__ */ new Map();
23931
+ for (const event of events) {
23932
+ const update = event.update;
23933
+ const kind = canonicalKind(update.sessionUpdate);
23934
+ const identity = update.messageId ?? update.toolCallId ?? update.terminalId ?? update.planId;
23935
+ const singleton = [
23936
+ "state_update",
23937
+ "usage_update",
23938
+ "session_info_update",
23939
+ "available_commands_update",
23940
+ "config_option_update",
23941
+ "_alan/thinking_tokens"
23942
+ ].includes(kind);
23943
+ const key = identity !== void 0 || singleton ? JSON.stringify([event.sessionId ?? "", kind, identity ?? "session"]) : void 0;
23944
+ const slot = key ? slots.get(key) : void 0;
23945
+ const previous = slot === void 0 ? void 0 : output2[slot];
23946
+ const merged = {
23947
+ ...previous?.update,
23948
+ ...update,
23949
+ sessionUpdate: kind
23950
+ };
23951
+ if (update.sessionUpdate === "terminal_output_chunk") {
23952
+ const before = previous && isRecord7(previous.update.output) ? previous.update.output.data : "";
23953
+ merged.output = { data: String(before ?? "") + String(update.data ?? "") };
23954
+ } else if (update.sessionUpdate.endsWith("_chunk")) {
23955
+ const before = previous && Array.isArray(previous.update.content) ? previous.update.content : [];
23956
+ merged.content = [
23957
+ ...before,
23958
+ ...Array.isArray(update.content) ? update.content : update.content ? [update.content] : []
23959
+ ];
23960
+ }
23961
+ if (isRecord7(update._meta))
23962
+ merged._meta = {
23963
+ ...isRecord7(previous?.update._meta) ? previous.update._meta : {},
23964
+ ...update._meta
23965
+ };
23966
+ if (kind === "state_update")
23967
+ merged.stopReason = update.state === "idle" ? update.stopReason : void 0;
23968
+ if (kind === "tool_call_update" && ["completed", "failed", "cancelled"].includes(String(previous?.update.status)))
23969
+ merged.status = previous?.update.status;
23970
+ const next = { ...event, line: previous?.line ?? event.line, update: merged };
23971
+ if (slot === void 0) {
23972
+ if (key)
23973
+ slots.set(key, output2.length);
23974
+ output2.push(next);
23975
+ } else
23976
+ output2[slot] = next;
23977
+ }
23978
+ return output2;
23979
+ }
23980
+ function canonicalKind(kind) {
23981
+ if (kind === "tool_call_content_chunk")
23982
+ return "tool_call_update";
23983
+ if (kind === "terminal_output_chunk")
23984
+ return "terminal_update";
23985
+ return kind.replace(/_chunk$/, "");
23986
+ }
23755
23987
  var init_terminal_events = __esm({
23756
23988
  "../shared/dist/agent/acp/presentation/terminal-events.js"() {
23757
23989
  "use strict";
@@ -23759,23 +23991,357 @@ var init_terminal_events = __esm({
23759
23991
  });
23760
23992
 
23761
23993
  // ../shared/dist/agent/acp/presentation/file-edits.js
23994
+ function diffRows(patch) {
23995
+ let oldLine = 0;
23996
+ let newLine = 0;
23997
+ let oldRemaining = 0;
23998
+ let newRemaining = 0;
23999
+ const lines2 = patch.split("\n");
24000
+ if (lines2.at(-1) === "")
24001
+ lines2.pop();
24002
+ return lines2.map((line) => {
24003
+ const hunk = /^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/.exec(line);
24004
+ if (hunk) {
24005
+ oldLine = Number(hunk[1]);
24006
+ newLine = Number(hunk[3]);
24007
+ oldRemaining = Number(hunk[2] ?? 1);
24008
+ newRemaining = Number(hunk[4] ?? 1);
24009
+ return { kind: "hunk", text: line };
24010
+ }
24011
+ if (newRemaining > 0 && line.startsWith("+")) {
24012
+ newRemaining--;
24013
+ return { kind: "add", text: line.slice(1), newLine: newLine++ };
24014
+ }
24015
+ if (oldRemaining > 0 && line.startsWith("-")) {
24016
+ oldRemaining--;
24017
+ return { kind: "remove", text: line.slice(1), oldLine: oldLine++ };
24018
+ }
24019
+ if (oldRemaining > 0 && newRemaining > 0 && line.startsWith(" ")) {
24020
+ oldRemaining--;
24021
+ newRemaining--;
24022
+ return { kind: "context", text: line.slice(1), oldLine: oldLine++, newLine: newLine++ };
24023
+ }
24024
+ return { kind: "meta", text: line };
24025
+ });
24026
+ }
24027
+ function patchForPath(text2, path4, count) {
24028
+ if (count === 1)
24029
+ return text2;
24030
+ const normalized2 = path4.replace(/^\/+/, "");
24031
+ return text2.split(/(?=^diff --git )/m).find((part) => {
24032
+ const names = [...part.matchAll(/^(?:---|\+\+\+) (?:[ab]\/)?([^\t\n]+)/gm)];
24033
+ return names.some((match) => match[1].replace(/^\/+/, "") === normalized2);
24034
+ });
24035
+ }
24036
+ function readDiff(value2, id) {
24037
+ if (!isRecord7(value2) || !Array.isArray(value2.changes))
24038
+ return [];
24039
+ const patch = isRecord7(value2.patch) && typeof value2.patch.text === "string" ? value2.patch : void 0;
24040
+ const changes = value2.changes;
24041
+ return changes.flatMap((change, index) => {
24042
+ if (!isRecord7(change) || typeof change.path !== "string" || typeof change.operation !== "string")
24043
+ return [];
24044
+ const text2 = patch ? patchForPath(String(patch.text), change.path, changes.length) : void 0;
24045
+ const rows = text2 && patch?.format !== "text" ? diffRows(text2) : [];
24046
+ const counted = rows.some((row) => row.kind === "hunk");
24047
+ return [
24048
+ {
24049
+ id: `${id}:${index}`,
24050
+ path: change.path,
24051
+ operation: change.operation,
24052
+ ...typeof change.oldPath === "string" ? { oldPath: change.oldPath } : {},
24053
+ patch: text2,
24054
+ rows,
24055
+ ...counted ? {
24056
+ additions: rows.filter((row) => row.kind === "add").length,
24057
+ deletions: rows.filter((row) => row.kind === "remove").length
24058
+ } : {}
24059
+ }
24060
+ ];
24061
+ });
24062
+ }
24063
+ function toolEdits(node2) {
24064
+ const content = node2.event.update.content;
24065
+ if (!Array.isArray(content))
24066
+ return [];
24067
+ return content.flatMap((block, index) => isRecord7(block) && block.type === "diff" ? readDiff(block.diff, `${node2.key}:${index}`) : []);
24068
+ }
24069
+ function collectEditedFiles(nodes) {
24070
+ const files = /* @__PURE__ */ new Map();
24071
+ const seen = /* @__PURE__ */ new Set();
24072
+ function visit2(node2) {
24073
+ if (seen.has(node2.key))
24074
+ return;
24075
+ seen.add(node2.key);
24076
+ if (node2.event.update.sessionUpdate === "tool_call_update" && node2.event.update.status === "completed") {
24077
+ for (const edit of toolEdits(node2)) {
24078
+ const previous = files.get(edit.path);
24079
+ const edits = [...previous?.edits ?? [], edit];
24080
+ const counted = edits.every((item) => item.additions !== void 0 && item.deletions !== void 0);
24081
+ files.set(edit.path, {
24082
+ path: edit.path,
24083
+ edits,
24084
+ ...counted ? {
24085
+ additions: edits.reduce((sum, item) => sum + (item.additions ?? 0), 0),
24086
+ deletions: edits.reduce((sum, item) => sum + (item.deletions ?? 0), 0)
24087
+ } : {}
24088
+ });
24089
+ }
24090
+ }
24091
+ node2.children.forEach(visit2);
24092
+ }
24093
+ nodes.forEach(visit2);
24094
+ return [...files.values()];
24095
+ }
23762
24096
  var init_file_edits = __esm({
23763
24097
  "../shared/dist/agent/acp/presentation/file-edits.js"() {
23764
24098
  "use strict";
24099
+ init_terminal_events();
23765
24100
  }
23766
24101
  });
23767
24102
 
23768
24103
  // ../shared/dist/agent/acp/presentation/notice-visibility.js
24104
+ function isConversationNotice({ message: message2, kind, meta: meta3 }) {
24105
+ const category = kind ?? (isRecord7(meta3) ? meta3["alan.dev/noticeKind"] : void 0);
24106
+ return !(category === "turn_summary" || category === "task_summary" || typeof category === "string" && category.startsWith("turn_summary/") || message2.startsWith("Under-development features enabled:") || /^clamping \S+ hook timeout to /.test(message2) || message2.startsWith("Skill descriptions were shortened to fit") || /^Rate limited \(allowed(?:_warning)?\):/.test(message2));
24107
+ }
24108
+ function uniqueNotices(notices) {
24109
+ const seen = /* @__PURE__ */ new Set();
24110
+ return notices.filter((notice2) => {
24111
+ const key = `${notice2.message}`;
24112
+ if (seen.has(key))
24113
+ return false;
24114
+ seen.add(key);
24115
+ return true;
24116
+ });
24117
+ }
23769
24118
  var init_notice_visibility = __esm({
23770
24119
  "../shared/dist/agent/acp/presentation/notice-visibility.js"() {
23771
24120
  "use strict";
24121
+ init_terminal_events();
23772
24122
  }
23773
24123
  });
23774
24124
 
23775
24125
  // ../shared/dist/agent/acp/presentation/prepare-conversation-turns.js
24126
+ function entryNode(entry, index) {
24127
+ const prepared = preparedEntries.get(entry);
24128
+ if (prepared?.index === index && prepared.lastUpdateIndex === entry.lastUpdateIndex) {
24129
+ return { key: prepared.key, event: prepared.event, children: [] };
24130
+ }
24131
+ const update = entry.kind === "message" ? {
24132
+ sessionUpdate: entry.role === "user" ? "user_message" : entry.role === "thought" ? "agent_thought" : "agent_message",
24133
+ messageId: entry.id,
24134
+ content: Array.isArray(entry.content) ? entry.content : [],
24135
+ _meta: entry._meta
24136
+ } : {
24137
+ sessionUpdate: "tool_call_update",
24138
+ toolCallId: entry.id,
24139
+ name: entry.name ?? entry.title,
24140
+ title: entry.title,
24141
+ kind: entry.toolKind,
24142
+ status: entry.status,
24143
+ content: entry.content,
24144
+ locations: entry.locations,
24145
+ rawInput: entry.rawInput,
24146
+ rawOutput: entry.rawOutput,
24147
+ _meta: entry._meta
24148
+ };
24149
+ const clientId = entry._meta?.["alan.dev/clientMessageId"];
24150
+ const identity = entry.kind === "message" && entry.role === "user" && typeof clientId === "string" ? clientId : entry.id;
24151
+ const key = entry.kind === "message" ? `message:${entry.role}:${identity}` : `tool:${entry.id}`;
24152
+ const event = { id: key, line: index, seq: entry.lastUpdateIndex, update };
24153
+ preparedEntries.set(entry, { index, lastUpdateIndex: entry.lastUpdateIndex, key, event });
24154
+ return { key, event, children: [] };
24155
+ }
24156
+ function attachChildren(nodes) {
24157
+ const tools = /* @__PURE__ */ new Map();
24158
+ const terminals = /* @__PURE__ */ new Map();
24159
+ for (const node2 of nodes) {
24160
+ const u = node2.event.update;
24161
+ if (typeof u.toolCallId === "string")
24162
+ tools.set(u.toolCallId, node2);
24163
+ for (const block of Array.isArray(u.content) ? u.content : []) {
24164
+ if (isRecord7(block) && block.type === "terminal" && typeof block.terminalId === "string")
24165
+ terminals.set(block.terminalId, node2);
24166
+ }
24167
+ }
24168
+ const parents = /* @__PURE__ */ new Map();
24169
+ for (const node2 of nodes) {
24170
+ const u = node2.event.update;
24171
+ const parentId = isRecord7(u._meta) ? u._meta["alan.dev/parentToolCallId"] : void 0;
24172
+ const parent = typeof parentId === "string" ? tools.get(parentId) : typeof u.terminalId === "string" ? terminals.get(u.terminalId) : void 0;
24173
+ if (parent)
24174
+ parents.set(node2, parent);
24175
+ else if (typeof parentId === "string")
24176
+ node2.issue = `Waiting for parent tool ${parentId}`;
24177
+ }
24178
+ return nodes.filter((node2) => {
24179
+ let ancestor = parents.get(node2);
24180
+ const seen = /* @__PURE__ */ new Set([node2]);
24181
+ while (ancestor) {
24182
+ if (seen.has(ancestor)) {
24183
+ node2.issue = "Cyclic parent reference; shown at root";
24184
+ return true;
24185
+ }
24186
+ seen.add(ancestor);
24187
+ ancestor = parents.get(ancestor);
24188
+ }
24189
+ const parent = parents.get(node2);
24190
+ if (!parent)
24191
+ return true;
24192
+ parent.children.push(node2);
24193
+ return false;
24194
+ });
24195
+ }
24196
+ function turnStart(turn) {
24197
+ if (turn.users[0])
24198
+ return turn.users[0].event.line;
24199
+ return turn.working[0]?.event.line;
24200
+ }
24201
+ function hasAnswerContent(node2) {
24202
+ const content = node2.event.update.content;
24203
+ return Array.isArray(content) && content.some((block) => isRecord7(block) && (block.type !== "text" || typeof block.text === "string" && block.text.trim().length > 0));
24204
+ }
24205
+ function messageText(node2) {
24206
+ const content = node2.event.update.content;
24207
+ return Array.isArray(content) ? content.flatMap((block) => isRecord7(block) && block.type === "text" && typeof block.text === "string" ? [block.text] : []).join("") : "";
24208
+ }
24209
+ function prepareConversationTurns(transcript, streaming, previousTurns = []) {
24210
+ const entries = Array.isArray(transcript.entries) ? transcript.entries : [];
24211
+ const nodes = entries.map(entryNode);
24212
+ const terminals = transcript.unknown.flatMap((update, index) => ["terminal_update", "terminal_output_chunk"].includes(update.sessionUpdate) || isRecord7(update._meta) && typeof update._meta["alan.dev/parentToolCallId"] === "string" ? [{ id: `terminal:${index}`, line: entries.length + index, update: { ...update } }] : []);
24213
+ for (const event of foldPreview(terminals))
24214
+ nodes.push({ key: event.id, event, children: [] });
24215
+ const nestedThoughtIds = new Set(nodes.flatMap((node2) => node2.event.update.sessionUpdate === "agent_thought" && typeof node2.event.update.messageId === "string" && isRecord7(node2.event.update._meta) && typeof node2.event.update._meta["alan.dev/parentToolCallId"] === "string" ? [node2.event.update.messageId] : []));
24216
+ const visible = nodes.filter((node2) => !isThought(node2));
24217
+ const roots = attachChildren(visible).filter((node2, index, all) => {
24218
+ const previous = all[index - 1];
24219
+ if (previous?.event.update.sessionUpdate !== "agent_message" || node2.event.update.sessionUpdate !== "agent_message" || !nestedThoughtIds.has(String(node2.event.update.messageId)))
24220
+ return true;
24221
+ const previousText = messageText(previous);
24222
+ return !(previousText.length > 0 && previousText === messageText(node2));
24223
+ });
24224
+ const turns = [];
24225
+ for (const node2 of roots) {
24226
+ const user = node2.event.update.sessionUpdate === "user_message";
24227
+ let turn = turns.at(-1);
24228
+ if (!turn || user) {
24229
+ turn = { key: node2.key, users: [], working: [], activity: { key: node2.key, state: "idle" } };
24230
+ turns.push(turn);
24231
+ }
24232
+ if (user)
24233
+ turn.users.push(node2);
24234
+ else
24235
+ turn.working.push(node2);
24236
+ }
24237
+ const activities = [...transcript.activities ?? []].sort((left, right) => left.firstEntryIndex - right.firstEntryIndex);
24238
+ for (const [turnIndex, turn] of turns.entries()) {
24239
+ const last = turn === turns.at(-1);
24240
+ const firstEntryIndex = turnStart(turn);
24241
+ const next = turns[turnIndex + 1];
24242
+ const nextStart = (next && turnStart(next)) ?? Number.POSITIVE_INFINITY;
24243
+ const runs = firstEntryIndex === void 0 ? [] : activities.filter((activity) => activity.firstEntryIndex >= firstEntryIndex && activity.firstEntryIndex < nextStart);
24244
+ const recorded = runs.at(-1);
24245
+ turn.activity.state = last && transcript.state === "requires_action" ? "requires_action" : last && streaming ? "running" : (
24246
+ // Bytes cut off mid-run are history once the thread is not live; they are not still working.
24247
+ recorded?.state === "running" ? "idle" : recorded?.state ?? "idle"
24248
+ );
24249
+ turn.activity.stopReason = turn.activity.state === "running" ? void 0 : recorded?.stopReason ?? (last ? transcript.stopReason : void 0);
24250
+ const captured = runs.reduce((total, run2) => {
24251
+ const duration3 = run2.startedAt !== void 0 ? Math.max(0, (run2.endedAt ?? run2.updatedAt) - run2.startedAt) : run2.durationMs;
24252
+ return duration3 === void 0 ? total : (total ?? 0) + duration3;
24253
+ }, void 0);
24254
+ if (captured !== void 0)
24255
+ turn.activity.capturedMs = captured;
24256
+ const startedAt = runs.find((run2) => run2.startedAt !== void 0)?.startedAt;
24257
+ if (startedAt !== void 0)
24258
+ turn.activity.startedAt = startedAt;
24259
+ if (turn.activity.state !== "running" && recorded?.endedAt !== void 0)
24260
+ turn.activity.endedAt = recorded.endedAt;
24261
+ turn.activity.neverStarted = recorded?.state === "idle" && recorded.stopReason === "cancelled" && captured === void 0;
24262
+ if (last && streaming && turn.activity.state === "running") {
24263
+ const anchor2 = Math.max(recorded?.startedAt ?? 0, transcript.userMessageAt ?? 0);
24264
+ if (anchor2 > 0)
24265
+ turn.activity.liveStartedAt = anchor2;
24266
+ }
24267
+ const tail = turn.working.reduce((latest, node2) => !latest || (node2.event.seq ?? node2.event.line) > (latest.event.seq ?? latest.event.line) ? node2 : latest, void 0);
24268
+ turn.working = turn.working.filter((node2) => !isThought(node2));
24269
+ const final = turn.activity.state === "idle" && (!turn.activity.stopReason || turn.activity.stopReason === "end_turn" || turn.activity.stopReason === "cancelled") && tail?.event.update.sessionUpdate === "agent_message" && hasAnswerContent(tail) ? tail : void 0;
24270
+ if (final)
24271
+ turn.final = final;
24272
+ }
24273
+ const noticesByEntry = /* @__PURE__ */ new Map();
24274
+ for (const notice2 of uniqueNotices(transcript.notices)) {
24275
+ if (notice2.firstEntryIndex === void 0 || !isConversationNotice(notice2))
24276
+ continue;
24277
+ const group = noticesByEntry.get(notice2.firstEntryIndex);
24278
+ if (group)
24279
+ group.push(notice2);
24280
+ else
24281
+ noticesByEntry.set(notice2.firstEntryIndex, [notice2]);
24282
+ }
24283
+ for (const turn of turns) {
24284
+ const firstEntryIndex = turnStart(turn);
24285
+ const notices = firstEntryIndex === void 0 ? void 0 : noticesByEntry.get(firstEntryIndex);
24286
+ if (notices)
24287
+ turn.notices = notices;
24288
+ }
24289
+ const startedTurn = turns[0];
24290
+ if (transcript.cloudStart && startedTurn?.users.length) {
24291
+ startedTurn.cloudStart = transcript.cloudStart;
24292
+ }
24293
+ const previousByKey = new Map(previousTurns.map((turn) => [turn.key, turn]));
24294
+ return turns.map((turn) => retainTurn(turn, previousByKey.get(turn.key)));
24295
+ }
24296
+ function sameNotices(left, right) {
24297
+ if (left === right)
24298
+ return true;
24299
+ if (!left || !right || left.length !== right.length)
24300
+ return false;
24301
+ return left.every((notice2, index) => notice2.kind === right[index].kind && notice2.level === right[index].level && notice2.message === right[index].message);
24302
+ }
24303
+ function sameFields(left, right) {
24304
+ const keys = Object.keys(left);
24305
+ return keys.length === Object.keys(right).length && keys.every((key) => Reflect.get(left, key) === Reflect.get(right, key));
24306
+ }
24307
+ function retainNodes(nodes, previous) {
24308
+ const byKey = new Map(previous.map((node2) => [node2.key, node2]));
24309
+ const retained = nodes.map((node2) => {
24310
+ const before = byKey.get(node2.key);
24311
+ if (!before)
24312
+ return node2;
24313
+ node2.children = retainNodes(node2.children, before.children);
24314
+ return node2.children === before.children && node2.issue === before.issue && (node2.event === before.event || node2.event.id === before.event.id && sameFields(node2.event.update, before.event.update)) ? before : node2;
24315
+ });
24316
+ return retained.length === previous.length && retained.every((node2, index) => node2 === previous[index]) ? previous : retained;
24317
+ }
24318
+ function retainTurn(turn, previous) {
24319
+ if (previous) {
24320
+ turn.users = retainNodes(turn.users, previous.users);
24321
+ turn.working = retainNodes(turn.working, previous.working);
24322
+ if (turn.final && previous.final)
24323
+ turn.final = retainNodes([turn.final], [previous.final])[0];
24324
+ if (sameFields(turn.activity, previous.activity))
24325
+ turn.activity = previous.activity;
24326
+ if (sameNotices(turn.notices, previous.notices))
24327
+ turn.notices = previous.notices;
24328
+ if (turn.cloudStart && previous.cloudStart && sameFields(turn.cloudStart, previous.cloudStart))
24329
+ turn.cloudStart = previous.cloudStart;
24330
+ }
24331
+ turn.editedFiles = previous && turn.working === previous.working && turn.activity === previous.activity ? previous.editedFiles : turn.activity.state === "idle" ? collectEditedFiles(turn.working) : [];
24332
+ return previous && turn.users === previous.users && turn.working === previous.working && turn.final === previous.final && turn.activity === previous.activity && turn.editedFiles === previous.editedFiles && turn.notices === previous.notices && turn.cloudStart === previous.cloudStart ? previous : turn;
24333
+ }
24334
+ function isThought(node2) {
24335
+ return ["agent_thought", "agent_thought_chunk"].includes(node2.event.update.sessionUpdate);
24336
+ }
24337
+ var preparedEntries;
23776
24338
  var init_prepare_conversation_turns = __esm({
23777
24339
  "../shared/dist/agent/acp/presentation/prepare-conversation-turns.js"() {
23778
24340
  "use strict";
24341
+ init_file_edits();
24342
+ init_notice_visibility();
24343
+ init_terminal_events();
24344
+ preparedEntries = /* @__PURE__ */ new WeakMap();
23779
24345
  }
23780
24346
  });
23781
24347
 
@@ -23790,23 +24356,460 @@ var init_event = __esm({
23790
24356
  function isUpdate(update, kind) {
23791
24357
  return update.sessionUpdate === kind;
23792
24358
  }
24359
+ function isContentUpdate(update) {
24360
+ return update.sessionUpdate === "user_message" || update.sessionUpdate === "user_message_chunk" || update.sessionUpdate === "agent_message" || update.sessionUpdate === "agent_message_chunk" || update.sessionUpdate === "agent_thought" || update.sessionUpdate === "agent_thought_chunk";
24361
+ }
24362
+ function isToolUpdate(update) {
24363
+ return update.sessionUpdate === "tool_call_update" || update.sessionUpdate === "tool_call_content_chunk";
24364
+ }
24365
+ var MEDIA_SESSION_UPDATE_KINDS;
23793
24366
  var init_types2 = __esm({
23794
24367
  "../shared/dist/agent/acp/types.js"() {
23795
24368
  "use strict";
24369
+ MEDIA_SESSION_UPDATE_KINDS = /* @__PURE__ */ new Set([
24370
+ "_alan/generated_image",
24371
+ "_alan/session_media"
24372
+ ]);
23796
24373
  }
23797
24374
  });
23798
24375
 
23799
24376
  // ../shared/dist/agent/acp/reduce.js
24377
+ function emptyTranscript() {
24378
+ return { entries: [], state: "idle", notices: [], unknown: [] };
24379
+ }
24380
+ function applySessionEvent(state, event) {
24381
+ applyUpdate(state, event.update);
24382
+ const update = event.update;
24383
+ if (update._meta && typeof update._meta === "object" && "alan.dev/parentToolCallId" in update._meta && typeof update._meta["alan.dev/parentToolCallId"] === "string")
24384
+ return state;
24385
+ if ((update.sessionUpdate === "user_message" || update.sessionUpdate === "user_message_chunk") && Number.isFinite(event.at))
24386
+ state.userMessageAt = event.at;
24387
+ const lifecycle = isUpdate(update, "state_update");
24388
+ const activities = state.activities ?? [];
24389
+ let activity = activities.at(-1);
24390
+ if (lifecycle) {
24391
+ let userIndex = -1;
24392
+ for (let index = state.entries.length - 1; index >= 0; index -= 1) {
24393
+ const entry = state.entries[index];
24394
+ if (entry.kind === "message" && entry.role === "user") {
24395
+ userIndex = index;
24396
+ break;
24397
+ }
24398
+ }
24399
+ if (!activity || activity.endedAt !== void 0 && (update.state === "running" || userIndex > activity.firstEntryIndex)) {
24400
+ const firstEntryIndex = userIndex >= 0 && (!activity || userIndex > activity.firstEntryIndex) ? userIndex : activity ? state.entries.length : 0;
24401
+ activity = { firstEntryIndex, state: update.state, updatedAt: event.at };
24402
+ activities.push(activity);
24403
+ state.activities = activities;
24404
+ }
24405
+ }
24406
+ if (!activity)
24407
+ return state;
24408
+ const usage = isUpdate(update, "usage_update") ? update._meta?.["alan.dev/usage"] : void 0;
24409
+ if (typeof usage === "object" && usage !== null && "durationMs" in usage && typeof usage.durationMs === "number" && Number.isFinite(usage.durationMs))
24410
+ activity.durationMs = Math.max(0, usage.durationMs);
24411
+ if (activity.endedAt === void 0)
24412
+ activity.updatedAt = event.at;
24413
+ if (lifecycle) {
24414
+ activity.state = update.state;
24415
+ activity.stopReason = update.state === "idle" ? update.stopReason ?? void 0 : void 0;
24416
+ if (update.state === "running" && activity.startedAt === void 0)
24417
+ activity.startedAt = event.at;
24418
+ if (update.state === "idle" && activity.endedAt === void 0)
24419
+ activity.endedAt = event.at;
24420
+ }
24421
+ return state;
24422
+ }
24423
+ function entryIndex(state) {
24424
+ const cached2 = entryIndexes.get(state);
24425
+ if (cached2 && cached2.entries === state.entries && cached2.size === state.entries.length && cached2.last === state.entries.at(-1))
24426
+ return cached2;
24427
+ const byKey = /* @__PURE__ */ new Map();
24428
+ for (const entry of state.entries)
24429
+ byKey.set(entryKey(entry), entry);
24430
+ const index = {
24431
+ entries: state.entries,
24432
+ size: state.entries.length,
24433
+ last: state.entries.at(-1),
24434
+ byKey
24435
+ };
24436
+ entryIndexes.set(state, index);
24437
+ return index;
24438
+ }
24439
+ function applyUpdate(state, update) {
24440
+ const index = entryIndex(state);
24441
+ applyOne(state, index.byKey, update);
24442
+ index.size = state.entries.length;
24443
+ index.last = state.entries.at(-1);
24444
+ return state;
24445
+ }
24446
+ function awaitingToolCallIds(meta3) {
24447
+ const ids = meta3?.[AWAITING_TOOL_CALLS_META];
24448
+ return Array.isArray(ids) ? ids.filter((id) => typeof id === "string") : [];
24449
+ }
24450
+ function entryKey(entry) {
24451
+ return entry.kind === "message" ? `m:${entry.role}:${entry.id}` : `t:${entry.id}`;
24452
+ }
24453
+ function applyOne(state, index, update) {
24454
+ state.updateCount = (state.updateCount ?? 0) + 1;
24455
+ if (isContentUpdate(update)) {
24456
+ applyContent(state, index, update);
24457
+ return;
24458
+ }
24459
+ if (isToolUpdate(update)) {
24460
+ applyTool(state, index, update);
24461
+ return;
24462
+ }
24463
+ if (update.sessionUpdate === "_alan/log" || update.sessionUpdate === "_alan/unhandled")
24464
+ return;
24465
+ if (update._meta && typeof update._meta === "object" && "alan.dev/parentToolCallId" in update._meta && typeof update._meta["alan.dev/parentToolCallId"] === "string") {
24466
+ state.unknown.push(update);
24467
+ return;
24468
+ }
24469
+ switch (update.sessionUpdate) {
24470
+ case "state_update": {
24471
+ if (!isUpdate(update, "state_update"))
24472
+ return;
24473
+ if (update.state === "running" && state.state === "idle")
24474
+ delete state.thinkingTokens;
24475
+ state.state = update.state;
24476
+ if (update.state !== "idle")
24477
+ state.stopReason = void 0;
24478
+ else if (update.stopReason)
24479
+ state.stopReason = update.stopReason;
24480
+ if (update.state === "requires_action")
24481
+ state.awaitingToolCallIds = awaitingToolCallIds(update._meta);
24482
+ else
24483
+ delete state.awaitingToolCallIds;
24484
+ if (update.state === "idle")
24485
+ settleOpenToolCalls(state);
24486
+ return;
24487
+ }
24488
+ case "plan_update": {
24489
+ if (!isUpdate(update, "plan_update"))
24490
+ return;
24491
+ state.plan = { planId: update.planId, entries: update.entries };
24492
+ return;
24493
+ }
24494
+ case "usage_update": {
24495
+ if (!isUpdate(update, "usage_update"))
24496
+ return;
24497
+ state.usage = {
24498
+ used: update.used,
24499
+ size: update.size,
24500
+ ...update.cost ? { cost: update.cost } : {}
24501
+ };
24502
+ delete state.thinkingTokens;
24503
+ return;
24504
+ }
24505
+ case "session_info_update": {
24506
+ if (!isUpdate(update, "session_info_update"))
24507
+ return;
24508
+ if (update.title !== void 0)
24509
+ state.title = update.title ?? void 0;
24510
+ return;
24511
+ }
24512
+ case "notice": {
24513
+ if (!isUpdate(update, "notice"))
24514
+ return;
24515
+ const notice2 = {
24516
+ level: update.severity,
24517
+ kind: noticeKind(update.severity, update._meta),
24518
+ message: update.description ? `${update.title}
24519
+ ${update.description}` : update.title,
24520
+ ...update._meta ? { _meta: update._meta } : {}
24521
+ };
24522
+ const seen = state.notices.some((existing) => existing.level === notice2.level && existing.message === notice2.message);
24523
+ if (!seen)
24524
+ state.notices.push(notice2);
24525
+ return;
24526
+ }
24527
+ case "_alan/thinking_tokens": {
24528
+ if (!isUpdate(update, "_alan/thinking_tokens"))
24529
+ return;
24530
+ state.thinkingTokens = update.estimated;
24531
+ return;
24532
+ }
24533
+ // Owned by the tool call that references it, but kept so a terminal-aware
24534
+ // renderer can still consume the raw update.
24535
+ case "terminal_update":
24536
+ case "terminal_output_chunk":
24537
+ state.unknown.push(update);
24538
+ return;
24539
+ // ACP: preserve a variant this build does not know rather than dropping it.
24540
+ default:
24541
+ state.unknown.push(update);
24542
+ }
24543
+ }
24544
+ function noticeKind(severity, meta3) {
24545
+ const kind = meta3?.["alan.dev/noticeKind"];
24546
+ return typeof kind === "string" ? kind : severity;
24547
+ }
24548
+ function applyContent(state, index, update) {
24549
+ const role = ROLE_BY_KIND[update.sessionUpdate];
24550
+ if (!role)
24551
+ return;
24552
+ const key = `m:${role}:${update.messageId}`;
24553
+ let entry = index.get(key);
24554
+ if (!entry) {
24555
+ entry = { kind: "message", id: update.messageId, role, content: [] };
24556
+ index.set(key, entry);
24557
+ state.entries.push(entry);
24558
+ }
24559
+ entry.lastUpdateIndex = state.updateCount;
24560
+ if (update.sessionUpdate.endsWith("_chunk")) {
24561
+ const block = update.content;
24562
+ if (block)
24563
+ entry.content.push(block);
24564
+ } else {
24565
+ const content = update.content;
24566
+ if (content !== void 0) {
24567
+ entry.content = content === null ? [] : Array.isArray(content) ? content : [content];
24568
+ }
24569
+ }
24570
+ if (update._meta !== void 0) {
24571
+ entry._meta = update._meta === null ? void 0 : { ...entry._meta, ...update._meta };
24572
+ }
24573
+ }
24574
+ function isSettled(status) {
24575
+ return SETTLED.has(status);
24576
+ }
24577
+ function outlivesTheTurn(entry) {
24578
+ if (readBackgroundTaskMeta(entry._meta))
24579
+ return true;
24580
+ const input2 = entry.rawInput;
24581
+ return entry.name?.toLowerCase() === "bash" && typeof input2 === "object" && input2 !== null && input2.run_in_background === true;
24582
+ }
24583
+ function settleOpenToolCalls(state) {
24584
+ for (const entry of state.entries) {
24585
+ if (entry.kind !== "tool_call" || isSettled(entry.status))
24586
+ continue;
24587
+ if (outlivesTheTurn(entry))
24588
+ continue;
24589
+ entry.status = "cancelled";
24590
+ }
24591
+ }
24592
+ function applyTool(state, index, update) {
24593
+ const key = `t:${update.toolCallId}`;
24594
+ let entry = index.get(key);
24595
+ if (!entry) {
24596
+ entry = {
24597
+ kind: "tool_call",
24598
+ id: update.toolCallId,
24599
+ toolKind: "other",
24600
+ status: "pending",
24601
+ content: [],
24602
+ locations: []
24603
+ };
24604
+ index.set(key, entry);
24605
+ state.entries.push(entry);
24606
+ }
24607
+ entry.lastUpdateIndex = state.updateCount;
24608
+ if (update.sessionUpdate === "tool_call_content_chunk") {
24609
+ const block = update.content;
24610
+ if (block)
24611
+ entry.content.push(block);
24612
+ return;
24613
+ }
24614
+ const u = update;
24615
+ if (u.name !== void 0)
24616
+ entry.name = u.name ?? void 0;
24617
+ if (u.title !== void 0)
24618
+ entry.title = u.title ?? void 0;
24619
+ if (!entry.title && typeof u.name === "string" && u.name.length > 0)
24620
+ entry.title = u.name;
24621
+ if (u.kind !== void 0)
24622
+ entry.toolKind = u.kind ?? "other";
24623
+ if (u.status !== void 0 && !isSettled(entry.status))
24624
+ entry.status = u.status ?? "pending";
24625
+ if (u.content !== void 0)
24626
+ entry.content = u.content ?? [];
24627
+ if (u.locations !== void 0)
24628
+ entry.locations = u.locations ?? [];
24629
+ if (u.rawInput !== void 0)
24630
+ entry.rawInput = u.rawInput;
24631
+ if (u.rawOutput !== void 0)
24632
+ entry.rawOutput = u.rawOutput;
24633
+ if (u._meta !== void 0) {
24634
+ entry._meta = u._meta === null ? void 0 : { ...entry._meta, ...u._meta };
24635
+ }
24636
+ }
24637
+ function messageText2(entry) {
24638
+ return entry.content.filter((b) => b.type === "text").map((b) => b.text).join("");
24639
+ }
24640
+ var ROLE_BY_KIND, entryIndexes, AWAITING_TOOL_CALLS_META, SETTLED;
23800
24641
  var init_reduce = __esm({
23801
24642
  "../shared/dist/agent/acp/reduce.js"() {
23802
24643
  "use strict";
24644
+ init_background_task();
24645
+ init_types2();
24646
+ ROLE_BY_KIND = {
24647
+ user_message: "user",
24648
+ user_message_chunk: "user",
24649
+ agent_message: "agent",
24650
+ agent_message_chunk: "agent",
24651
+ agent_thought: "thought",
24652
+ agent_thought_chunk: "thought"
24653
+ };
24654
+ entryIndexes = /* @__PURE__ */ new WeakMap();
24655
+ AWAITING_TOOL_CALLS_META = "alan.dev/awaitingToolCallIds";
24656
+ SETTLED = /* @__PURE__ */ new Set(["completed", "failed", "cancelled"]);
23803
24657
  }
23804
24658
  });
23805
24659
 
23806
24660
  // ../shared/dist/agent/acp/conversation-messages.js
24661
+ function compactConversationMessageTurns(turns, keepNewestEntries) {
24662
+ return turns.map((turn, index) => ({
24663
+ ...turn,
24664
+ display: turn.display.map((displayTurn) => {
24665
+ if (!displayTurn.final)
24666
+ return displayTurn;
24667
+ return {
24668
+ ...displayTurn,
24669
+ working: displayTurn.working.map((node2) => node2.key === displayTurn.final?.key ? {
24670
+ ...node2,
24671
+ children: [],
24672
+ event: {
24673
+ ...node2.event,
24674
+ update: { ...node2.event.update, content: [] }
24675
+ }
24676
+ } : node2)
24677
+ };
24678
+ }),
24679
+ state: {
24680
+ ...turn.state,
24681
+ entries: index === 0 && keepNewestEntries ? turn.state.entries.map((entry) => {
24682
+ if (entry.kind === "message")
24683
+ return entry.role === "user" ? entry : { ...entry, content: [] };
24684
+ const ask = isAskUserQuestionTool(entry.title || entry.toolKind, entry.rawInput);
24685
+ return {
24686
+ ...entry,
24687
+ content: [],
24688
+ locations: [],
24689
+ rawInput: ask ? entry.rawInput : void 0,
24690
+ rawOutput: void 0
24691
+ };
24692
+ }) : []
24693
+ }
24694
+ }));
24695
+ }
24696
+ function prepareConversationTurnRead(state) {
24697
+ const prompts = [];
24698
+ const navigation = [];
24699
+ const interactiveTools = [];
24700
+ let modeChange = null;
24701
+ let latestAgentMessageId = null;
24702
+ for (const entry of state.entries) {
24703
+ if (entry.kind === "message" && entry.role === "user") {
24704
+ const meta3 = entry._meta ?? {};
24705
+ if (typeof meta3["alan.dev/parentToolCallId"] !== "string") {
24706
+ const clientMessageId = meta3["alan.dev/clientMessageId"];
24707
+ prompts.push({
24708
+ entryId: entry.id,
24709
+ ...typeof clientMessageId === "string" ? { clientMessageId } : {},
24710
+ content: messageText2(entry),
24711
+ agentMode: typeof meta3["alan.dev/agentMode"] === "string" ? meta3["alan.dev/agentMode"] : null,
24712
+ attachmentIds: Array.isArray(meta3["alan.dev/attachmentIds"]) ? meta3["alan.dev/attachmentIds"] : void 0,
24713
+ references: Array.isArray(meta3["alan.dev/references"]) ? meta3["alan.dev/references"] : void 0
24714
+ });
24715
+ }
24716
+ const title = toPreviewText(messageText2(entry).slice(0, 960).replace(attachmentMentionPattern(), ""), 240);
24717
+ navigation.push({ id: entry.id, title: title || "Message with attachments" });
24718
+ continue;
24719
+ }
24720
+ if (entry.kind === "message" && entry.role === "agent" && navigation.length > 0) {
24721
+ latestAgentMessageId = entry.id;
24722
+ if (typeof entry._meta?.["alan.dev/parentToolCallId"] === "string")
24723
+ continue;
24724
+ const content = messageText2(entry);
24725
+ if (!/\S/.test(content))
24726
+ continue;
24727
+ const preview = toPreviewText(content.slice(0, 960).replace(attachmentMentionPattern(), ""), 240);
24728
+ if (preview)
24729
+ navigation[navigation.length - 1].preview = preview;
24730
+ continue;
24731
+ }
24732
+ if (entry.kind === "message" && entry.role === "agent") {
24733
+ latestAgentMessageId = entry.id;
24734
+ continue;
24735
+ }
24736
+ if (entry.kind !== "tool_call")
24737
+ continue;
24738
+ const name = entry.name || entry.title || entry.toolKind;
24739
+ const responseToolId = entry._meta?.[TRANSCRIPT_TOOL_RESPONSE_ID_META];
24740
+ interactiveTools.push({
24741
+ id: entry.id,
24742
+ name,
24743
+ ...(entry.status === "pending" || entry.status === "in_progress") && {
24744
+ input: entry.rawInput
24745
+ },
24746
+ ...typeof responseToolId === "string" ? { responseToolId } : {}
24747
+ });
24748
+ const toolName2 = (entry.name || entry.title)?.trim().toLowerCase();
24749
+ if (toolName2 === "enterplanmode") {
24750
+ modeChange = "plan";
24751
+ continue;
24752
+ }
24753
+ if (toolName2 !== "exitplanmode")
24754
+ continue;
24755
+ if (entry.status !== "completed" && entry.status !== "failed")
24756
+ continue;
24757
+ const output2 = typeof entry.rawOutput === "string" ? entry.rawOutput : entry.content.flatMap((item) => item.type === "content" && item.content.type === "text" ? [item.content.text] : []).join("\n");
24758
+ const response = output2.trim().toLowerCase();
24759
+ if (response === "accepted" && entry.status === "completed")
24760
+ modeChange = "agent";
24761
+ else if (response === "rejected")
24762
+ modeChange = "plan";
24763
+ }
24764
+ return {
24765
+ entryCount: state.entries.length,
24766
+ latestAgentMessageId,
24767
+ prompts,
24768
+ navigation,
24769
+ modeChange,
24770
+ pendingAsk: findPendingAsk(state.entries),
24771
+ interactiveTools
24772
+ };
24773
+ }
24774
+ function conversationTurnView(ordinal, state, previousDisplay = []) {
24775
+ return {
24776
+ ordinal,
24777
+ state,
24778
+ display: prepareConversationTurns(state, state.state === "running", previousDisplay),
24779
+ read: prepareConversationTurnRead(state)
24780
+ };
24781
+ }
24782
+ function isRecord8(value2) {
24783
+ return value2 !== null && typeof value2 === "object" && !Array.isArray(value2);
24784
+ }
24785
+ function isTranscriptState(value2) {
24786
+ return isRecord8(value2) && typeof value2.state === "string" && Array.isArray(value2.entries) && Array.isArray(value2.notices) && Array.isArray(value2.unknown);
24787
+ }
24788
+ function isPendingAsk(value2) {
24789
+ return value2 === null || isRecord8(value2) && typeof value2.toolCallId === "string" && isRecord8(value2.rawInput) && Array.isArray(value2.questions) && value2.questions.every((question) => isRecord8(question) && typeof question.question === "string" && (question.header === void 0 || typeof question.header === "string") && typeof question.multiSelect === "boolean" && Array.isArray(question.options) && question.options.every((option2) => isRecord8(option2) && typeof option2.label === "string" && (option2.description === void 0 || typeof option2.description === "string")));
24790
+ }
24791
+ function isInteractiveTool(value2) {
24792
+ return isRecord8(value2) && typeof value2.id === "string" && typeof value2.name === "string" && (value2.responseToolId === void 0 || typeof value2.responseToolId === "string");
24793
+ }
24794
+ function isConversationTurnRead(value2) {
24795
+ return isRecord8(value2) && Number.isSafeInteger(value2.entryCount) && (value2.latestAgentMessageId === null || typeof value2.latestAgentMessageId === "string") && Array.isArray(value2.prompts) && value2.prompts.every((prompt) => isRecord8(prompt) && (prompt.entryId === void 0 || typeof prompt.entryId === "string") && (prompt.clientMessageId === void 0 || typeof prompt.clientMessageId === "string") && typeof prompt.content === "string" && (prompt.agentMode === null || typeof prompt.agentMode === "string")) && Array.isArray(value2.navigation) && value2.navigation.every((item) => isRecord8(item) && typeof item.id === "string" && typeof item.title === "string" && (item.preview === void 0 || typeof item.preview === "string")) && (value2.modeChange === null || value2.modeChange === "plan" || value2.modeChange === "agent") && isPendingAsk(value2.pendingAsk) && Array.isArray(value2.interactiveTools) && value2.interactiveTools.every(isInteractiveTool);
24796
+ }
24797
+ function isConversationMessageTurn(value2) {
24798
+ return isRecord8(value2) && Number.isSafeInteger(value2.ordinal) && typeof value2.markdown === "string" && isTranscriptState(value2.state) && Array.isArray(value2.display) && isConversationTurnRead(value2.read) && value2.display.every((turn) => isRecord8(turn) && typeof turn.key === "string" && Array.isArray(turn.users) && Array.isArray(turn.working) && isRecord8(turn.activity));
24799
+ }
24800
+ function isConversationMessagesPage(value2) {
24801
+ return isRecord8(value2) && typeof value2.revision === "string" && typeof value2.streamCursor === "string" && (value2.before === null || typeof value2.before === "string") && Array.isArray(value2.turns) && value2.turns.every(isConversationMessageTurn);
24802
+ }
23807
24803
  var init_conversation_messages = __esm({
23808
24804
  "../shared/dist/agent/acp/conversation-messages.js"() {
23809
24805
  "use strict";
24806
+ init_agent();
24807
+ init_attachment_mention();
24808
+ init_preview();
24809
+ init_ask();
24810
+ init_prepare_conversation_turns();
24811
+ init_reduce();
24812
+ init_transcript_http();
23810
24813
  }
23811
24814
  });
23812
24815
 
@@ -23832,9 +24835,60 @@ var init_transcript_byte_decoder = __esm({
23832
24835
  });
23833
24836
 
23834
24837
  // ../shared/dist/agent/acp/transcript-fold.js
24838
+ function snapshotTranscriptState(state) {
24839
+ return {
24840
+ ...state,
24841
+ entries: state.entries.map((entry) => entry.kind === "message" ? { ...entry, content: [...entry.content] } : { ...entry, content: [...entry.content], locations: [...entry.locations] }),
24842
+ notices: [...state.notices],
24843
+ unknown: [...state.unknown],
24844
+ ...state.activities ? { activities: state.activities.map((activity) => ({ ...activity })) } : {}
24845
+ };
24846
+ }
24847
+ function isRecord9(value2) {
24848
+ return value2 !== null && typeof value2 === "object" && !Array.isArray(value2);
24849
+ }
24850
+ function scopedContent(value2, turnId) {
24851
+ if (!Array.isArray(value2))
24852
+ return value2;
24853
+ return value2.map((block) => isRecord9(block) && block.type === "terminal" && typeof block.terminalId === "string" ? { ...block, terminalId: `${turnId}:${block.terminalId}` } : block);
24854
+ }
24855
+ function scopeTranscriptEvent(value2) {
24856
+ if (!isRecord9(value2) || !Number.isSafeInteger(value2.seq) || !Number.isFinite(value2.at))
24857
+ return null;
24858
+ if (!isRecord9(value2.update) || typeof value2.update.sessionUpdate !== "string")
24859
+ return null;
24860
+ const update = value2.update;
24861
+ const turnId = typeof value2.turnId === "string" ? value2.turnId : void 0;
24862
+ const event = {
24863
+ seq: Number(value2.seq),
24864
+ at: Number(value2.at),
24865
+ ...typeof value2.sessionId === "string" ? { sessionId: value2.sessionId } : {},
24866
+ update
24867
+ };
24868
+ if (!turnId)
24869
+ return event;
24870
+ const meta3 = isRecord9(update._meta) ? { ...update._meta } : {};
24871
+ const parent = meta3["alan.dev/parentToolCallId"];
24872
+ if (typeof parent === "string")
24873
+ meta3["alan.dev/parentToolCallId"] = `${turnId}:${parent}`;
24874
+ if (typeof update.toolCallId === "string")
24875
+ meta3[TRANSCRIPT_TOOL_RESPONSE_ID_META] = update.toolCallId;
24876
+ if (typeof update.sessionUpdate === "string" && MEDIA_SESSION_UPDATE_KINDS.has(update.sessionUpdate))
24877
+ meta3[TRANSCRIPT_TURN_ID_META] = turnId;
24878
+ const scoped = { ...update, _meta: meta3 };
24879
+ for (const key of ["messageId", "toolCallId", "terminalId", "planId"]) {
24880
+ if (typeof update[key] === "string")
24881
+ scoped[key] = `${turnId}:${update[key]}`;
24882
+ }
24883
+ if ("content" in update)
24884
+ scoped.content = scopedContent(update.content, turnId);
24885
+ return { ...event, update: scoped };
24886
+ }
23835
24887
  var init_transcript_fold = __esm({
23836
24888
  "../shared/dist/agent/acp/transcript-fold.js"() {
23837
24889
  "use strict";
24890
+ init_transcript_http();
24891
+ init_types2();
23838
24892
  }
23839
24893
  });
23840
24894
 
@@ -24101,7 +25155,7 @@ function withoutInlineMedia(update) {
24101
25155
  ...nextRawOutput === rawOutput ? {} : { rawOutput: nextRawOutput }
24102
25156
  };
24103
25157
  }
24104
- var PROVIDER_PAYLOAD_META, TOOL_RESULT_ONLY_META, PARENT_TOOL_CALL_META, SUBAGENT_LAUNCHER_META, SUBAGENT_TASK_ID_META, SUBAGENT_OUTPUT_FILE_META, USAGE_META, TODOS_META, NOTICE_KIND_META, ASK_USER_QUESTIONS_META, USER_ANSWER_META, AWAITING_TOOL_CALLS_META, EXIT_PLAN_MODE_INPUT_META, BACKGROUND_TASK_META, TASK_PROGRESS_META, RATE_LIMIT_META, MODEL_META, TOOLS_META, SLASH_COMMANDS_META, TOOL_KIND_RULES, ANSWER_PREFIX, ACCEPT_WORDS, MIN_INLINE_MEDIA_CHARS, DATA_URL_PREFIX, BASE64_BODY;
25158
+ var PROVIDER_PAYLOAD_META, TOOL_RESULT_ONLY_META, PARENT_TOOL_CALL_META, SUBAGENT_LAUNCHER_META, SUBAGENT_TASK_ID_META, SUBAGENT_OUTPUT_FILE_META, USAGE_META, TODOS_META, NOTICE_KIND_META, ASK_USER_QUESTIONS_META, USER_ANSWER_META, AWAITING_TOOL_CALLS_META2, EXIT_PLAN_MODE_INPUT_META, BACKGROUND_TASK_META, TASK_PROGRESS_META, RATE_LIMIT_META, MODEL_META, TOOLS_META, SLASH_COMMANDS_META, TOOL_KIND_RULES, ANSWER_PREFIX, ACCEPT_WORDS, MIN_INLINE_MEDIA_CHARS, DATA_URL_PREFIX, BASE64_BODY;
24105
25159
  var init_chunk_UGRKZTAD = __esm({
24106
25160
  "../agent-core/dist/chunk-UGRKZTAD.js"() {
24107
25161
  "use strict";
@@ -24119,7 +25173,7 @@ var init_chunk_UGRKZTAD = __esm({
24119
25173
  NOTICE_KIND_META = "alan.dev/noticeKind";
24120
25174
  ASK_USER_QUESTIONS_META = "alan.dev/askUserQuestions";
24121
25175
  USER_ANSWER_META = "alan.dev/userAnswer";
24122
- AWAITING_TOOL_CALLS_META = "alan.dev/awaitingToolCallIds";
25176
+ AWAITING_TOOL_CALLS_META2 = "alan.dev/awaitingToolCallIds";
24123
25177
  EXIT_PLAN_MODE_INPUT_META = "alan.dev/exitPlanModeInput";
24124
25178
  BACKGROUND_TASK_META = BACKGROUND_TASK_META_KEY;
24125
25179
  TASK_PROGRESS_META = "alan.dev/taskProgress";
@@ -24893,7 +25947,7 @@ var init_chunk_54ZRJOQP = __esm({
24893
25947
  }
24894
25948
  });
24895
25949
 
24896
- // ../agent-core/dist/chunk-YPYC4VBL.js
25950
+ // ../agent-core/dist/chunk-KHYYC5IN.js
24897
25951
  function collectStrings(value2, out) {
24898
25952
  if (typeof value2 === "string") out.push(value2);
24899
25953
  else if (Array.isArray(value2)) for (const item of value2) collectStrings(item, out);
@@ -25263,12 +26317,12 @@ function silentStartError(name, timeoutMs) {
25263
26317
  };
25264
26318
  }
25265
26319
  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;
25266
- var init_chunk_YPYC4VBL = __esm({
25267
- "../agent-core/dist/chunk-YPYC4VBL.js"() {
26320
+ var init_chunk_KHYYC5IN = __esm({
26321
+ "../agent-core/dist/chunk-KHYYC5IN.js"() {
25268
26322
  "use strict";
25269
26323
  init_chunk_UGRKZTAD();
25270
26324
  init_chunk_54ZRJOQP();
25271
- init_chunk_J4T6L5LX();
26325
+ init_chunk_M6YHY2EZ();
25272
26326
  init_chunk_YXWJW7I5();
25273
26327
  import_crypto3 = require("crypto");
25274
26328
  import_fs4 = require("fs");
@@ -26759,7 +27813,7 @@ function launcherLabel(update) {
26759
27813
  const description = asRecord(update.rawInput)?.description;
26760
27814
  return nonEmpty(description) ?? nonEmpty(update.title);
26761
27815
  }
26762
- function isSettled(update) {
27816
+ function isSettled2(update) {
26763
27817
  return update.status === "completed" || update.status === "failed" || update.status === "cancelled";
26764
27818
  }
26765
27819
  function isRunningTask(record2) {
@@ -26931,7 +27985,7 @@ function classifyResultError(event, context) {
26931
27985
  if (classified.errorKind !== "unknown_cli_error" || !isApiError) return classified;
26932
27986
  return { ...specForErrorKind("provider_error"), message: classified.message };
26933
27987
  }
26934
- function isSettled2(update) {
27988
+ function isSettled22(update) {
26935
27989
  return update.status === "completed" || update.status === "failed" || update.status === "cancelled";
26936
27990
  }
26937
27991
  function parentToolUseId(event) {
@@ -27359,11 +28413,11 @@ var init_claude = __esm({
27359
28413
  "../agent-core/dist/providers/claude.js"() {
27360
28414
  "use strict";
27361
28415
  init_chunk_DALFHI4B();
27362
- init_chunk_YPYC4VBL();
28416
+ init_chunk_KHYYC5IN();
27363
28417
  init_chunk_UGRKZTAD();
27364
28418
  init_chunk_54ZRJOQP();
27365
28419
  init_chunk_J2KTV5FP();
27366
- init_chunk_J4T6L5LX();
28420
+ init_chunk_M6YHY2EZ();
27367
28421
  init_chunk_ITTV3UIM();
27368
28422
  init_chunk_YXWJW7I5();
27369
28423
  init_effort();
@@ -27520,7 +28574,7 @@ var init_claude = __esm({
27520
28574
  if (!record2) return update;
27521
28575
  const remembered = record2.meta.label ?? this.#labels.get(update.toolCallId);
27522
28576
  if (!record2.meta.label && remembered) record2.meta = { ...record2.meta, label: remembered };
27523
- if (isSettled(update) && record2.meta.kind === "agent" && isRunningTask(record2)) {
28577
+ if (isSettled2(update) && record2.meta.kind === "agent" && isRunningTask(record2)) {
27524
28578
  this.settle(record2, update.status ?? void 0, update.status !== "completed");
27525
28579
  }
27526
28580
  return { ...update, _meta: { ...update._meta, [BACKGROUND_TASK_META_KEY]: record2.meta } };
@@ -27941,7 +28995,7 @@ var init_claude = __esm({
27941
28995
  this.#announced.add(id);
27942
28996
  if (isLauncher) this.#registerLauncher(update, meta3);
27943
28997
  }
27944
- if (isLauncher && isSettled2(update)) this.tasks.clear([id]);
28998
+ if (isLauncher && isSettled22(update)) this.tasks.clear([id]);
27945
28999
  }
27946
29000
  #registerLauncher(update, meta3) {
27947
29001
  this.tasks.registerLauncher(update.toolCallId);
@@ -30136,11 +31190,11 @@ var init_codex = __esm({
30136
31190
  "../agent-core/dist/providers/codex.js"() {
30137
31191
  "use strict";
30138
31192
  init_chunk_DALFHI4B();
30139
- init_chunk_YPYC4VBL();
31193
+ init_chunk_KHYYC5IN();
30140
31194
  init_chunk_UGRKZTAD();
30141
31195
  init_chunk_54ZRJOQP();
30142
31196
  init_chunk_J2KTV5FP();
30143
- init_chunk_J4T6L5LX();
31197
+ init_chunk_M6YHY2EZ();
30144
31198
  init_chunk_ITTV3UIM();
30145
31199
  init_chunk_YXWJW7I5();
30146
31200
  import_fs6 = require("fs");
@@ -41406,10 +42460,10 @@ var require_tar_stream = __commonJS({
41406
42460
  var init_dist = __esm({
41407
42461
  "../agent-core/dist/index.js"() {
41408
42462
  "use strict";
41409
- init_chunk_YPYC4VBL();
42463
+ init_chunk_KHYYC5IN();
41410
42464
  init_chunk_UGRKZTAD();
41411
42465
  init_chunk_54ZRJOQP();
41412
- init_chunk_J4T6L5LX();
42466
+ init_chunk_M6YHY2EZ();
41413
42467
  init_chunk_YXWJW7I5();
41414
42468
  }
41415
42469
  });
@@ -41645,7 +42699,7 @@ function isRunning(task) {
41645
42699
  return task.meta.status === "running" || task.meta.status === "stopping";
41646
42700
  }
41647
42701
  function isPlanStatus(value2) {
41648
- return STATUSES.has(value2);
42702
+ return STATUSES2.has(value2);
41649
42703
  }
41650
42704
  function todoEntries2(todos) {
41651
42705
  return asArray(todos).flatMap((raw) => {
@@ -42149,15 +43203,15 @@ async function acpTurnInput(run2, context) {
42149
43203
  ...encoded.length ? { images: encoded, imagePaths: images.map((image) => image.path) } : {}
42150
43204
  };
42151
43205
  }
42152
- var import_promises48, import_path9, import_crypto12, import_promises49, 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;
43206
+ var import_promises48, import_path9, import_crypto12, import_promises49, CURSOR_ASK_QUESTION, copilotAcpProfile, cursorAcpProfile, MODEL_REJECTED, MAX_READ_BYTES, FsDenied, ENV_REFERENCE, AcpBackgroundTasks, CURSOR_CREATE_PLAN, STATUSES2, 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;
42153
43207
  var init_acp3 = __esm({
42154
43208
  "../agent-core/dist/providers/acp.js"() {
42155
43209
  "use strict";
42156
- init_chunk_YPYC4VBL();
43210
+ init_chunk_KHYYC5IN();
42157
43211
  init_chunk_UGRKZTAD();
42158
43212
  init_chunk_54ZRJOQP();
42159
43213
  init_chunk_J2KTV5FP();
42160
- init_chunk_J4T6L5LX();
43214
+ init_chunk_M6YHY2EZ();
42161
43215
  init_chunk_ITTV3UIM();
42162
43216
  init_chunk_YXWJW7I5();
42163
43217
  import_promises48 = require("fs/promises");
@@ -42364,7 +43418,7 @@ var init_acp3 = __esm({
42364
43418
  }
42365
43419
  };
42366
43420
  CURSOR_CREATE_PLAN = "cursor/create_plan";
42367
- STATUSES = /* @__PURE__ */ new Set(["pending", "in_progress", "completed", "cancelled"]);
43421
+ STATUSES2 = /* @__PURE__ */ new Set(["pending", "in_progress", "completed", "cancelled"]);
42368
43422
  READ_KINDS = /* @__PURE__ */ new Set(["read", "search", "think", "fetch"]);
42369
43423
  ALLOW_KINDS = ["allow_once", "allow", "allow_always"];
42370
43424
  REJECT_KINDS = ["reject_once", "reject", "deny", "reject_always"];
@@ -43231,7 +44285,7 @@ function awaitingUpdate(waiting) {
43231
44285
  return {
43232
44286
  sessionUpdate: "state_update",
43233
44287
  state: "requires_action",
43234
- _meta: { [AWAITING_TOOL_CALLS_META]: [...waiting] }
44288
+ _meta: { [AWAITING_TOOL_CALLS_META2]: [...waiting] }
43235
44289
  };
43236
44290
  }
43237
44291
  var RESUME_UNAVAILABLE;
@@ -43857,11 +44911,11 @@ var import_http10, import_crypto13, import_promises50, import_path10, import_pat
43857
44911
  var init_opencode = __esm({
43858
44912
  "../agent-core/dist/providers/opencode.js"() {
43859
44913
  "use strict";
43860
- init_chunk_YPYC4VBL();
44914
+ init_chunk_KHYYC5IN();
43861
44915
  init_chunk_UGRKZTAD();
43862
44916
  init_chunk_54ZRJOQP();
43863
44917
  init_chunk_J2KTV5FP();
43864
- init_chunk_J4T6L5LX();
44918
+ init_chunk_M6YHY2EZ();
43865
44919
  init_chunk_ITTV3UIM();
43866
44920
  init_chunk_YXWJW7I5();
43867
44921
  import_http10 = require("http");
@@ -45134,7 +46188,7 @@ __export(codex_exports, {
45134
46188
  createCodexHolderDriver: () => createCodexHolderDriver
45135
46189
  });
45136
46190
  function sha2563(value2) {
45137
- return (0, import_node_crypto25.createHash)("sha256").update(value2).digest("hex");
46191
+ return (0, import_node_crypto26.createHash)("sha256").update(value2).digest("hex");
45138
46192
  }
45139
46193
  function createCodexLogin(broker) {
45140
46194
  const state = {};
@@ -45209,11 +46263,11 @@ function createCodexHolderDriver(options) {
45209
46263
  }
45210
46264
  );
45211
46265
  }
45212
- var import_node_crypto25;
46266
+ var import_node_crypto26;
45213
46267
  var init_codex2 = __esm({
45214
46268
  "src/holder/drivers/codex.ts"() {
45215
46269
  "use strict";
45216
- import_node_crypto25 = require("crypto");
46270
+ import_node_crypto26 = require("crypto");
45217
46271
  init_dist();
45218
46272
  init_codex();
45219
46273
  init_persistent();
@@ -45665,11 +46719,11 @@ var import_crypto15, import_promises51, FACTORY_API_VERSION, FACTORY_PROTOCOL_VE
45665
46719
  var init_droid = __esm({
45666
46720
  "../agent-core/dist/providers/droid.js"() {
45667
46721
  "use strict";
45668
- init_chunk_YPYC4VBL();
46722
+ init_chunk_KHYYC5IN();
45669
46723
  init_chunk_UGRKZTAD();
45670
46724
  init_chunk_54ZRJOQP();
45671
46725
  init_chunk_J2KTV5FP();
45672
- init_chunk_J4T6L5LX();
46726
+ init_chunk_M6YHY2EZ();
45673
46727
  init_chunk_ITTV3UIM();
45674
46728
  init_chunk_YXWJW7I5();
45675
46729
  init_runtime_v2();
@@ -46768,10 +47822,10 @@ var init_antigravity = __esm({
46768
47822
  "../agent-core/dist/providers/antigravity.js"() {
46769
47823
  "use strict";
46770
47824
  init_chunk_DALFHI4B();
46771
- init_chunk_YPYC4VBL();
47825
+ init_chunk_KHYYC5IN();
46772
47826
  init_chunk_UGRKZTAD();
46773
47827
  init_chunk_54ZRJOQP();
46774
- init_chunk_J4T6L5LX();
47828
+ init_chunk_M6YHY2EZ();
46775
47829
  init_chunk_ITTV3UIM();
46776
47830
  init_chunk_YXWJW7I5();
46777
47831
  import_promises52 = require("fs/promises");
@@ -47472,11 +48526,11 @@ var import_promises53, import_path15, import_crypto17, COMMAND_CODE_GRAMMAR_NAME
47472
48526
  var init_command_code = __esm({
47473
48527
  "../agent-core/dist/providers/command-code.js"() {
47474
48528
  "use strict";
47475
- init_chunk_YPYC4VBL();
48529
+ init_chunk_KHYYC5IN();
47476
48530
  init_chunk_UGRKZTAD();
47477
48531
  init_chunk_54ZRJOQP();
47478
48532
  init_chunk_J2KTV5FP();
47479
- init_chunk_J4T6L5LX();
48533
+ init_chunk_M6YHY2EZ();
47480
48534
  init_chunk_ITTV3UIM();
47481
48535
  init_chunk_YXWJW7I5();
47482
48536
  import_promises53 = require("fs/promises");
@@ -48098,7 +49152,7 @@ var require_XMLHttpRequest = __commonJS({
48098
49152
  "use strict";
48099
49153
  var fs = require("fs");
48100
49154
  var Url = require("url");
48101
- var spawn11 = require("child_process").spawn;
49155
+ var spawn10 = require("child_process").spawn;
48102
49156
  module2.exports = XMLHttpRequest3;
48103
49157
  XMLHttpRequest3.XMLHttpRequest = XMLHttpRequest3;
48104
49158
  function XMLHttpRequest3(opts) {
@@ -48394,7 +49448,7 @@ var require_XMLHttpRequest = __commonJS({
48394
49448
  var syncFile = ".node-xmlhttprequest-sync-" + process.pid;
48395
49449
  fs.writeFileSync(syncFile, "", "utf8");
48396
49450
  var execString = "var http = require('http'), https = require('https'), fs = require('fs');var doRequest = http" + (ssl ? "s" : "") + ".request;var options = " + JSON.stringify(options) + ";var responseText = '';var responseData = Buffer.alloc(0);var req = doRequest(options, function(response) {response.on('data', function(chunk) { var data = Buffer.from(chunk); responseText += data.toString('utf8'); responseData = Buffer.concat([responseData, data]);});response.on('end', function() {fs.writeFileSync('" + contentFile + "', JSON.stringify({err: null, data: {statusCode: response.statusCode, headers: response.headers, text: responseText, data: responseData.toString('base64')}}), 'utf8');fs.unlinkSync('" + syncFile + "');});response.on('error', function(error) {fs.writeFileSync('" + contentFile + "', 'NODE-XMLHTTPREQUEST-ERROR:' + JSON.stringify(error), 'utf8');fs.unlinkSync('" + syncFile + "');});}).on('error', function(error) {fs.writeFileSync('" + contentFile + "', 'NODE-XMLHTTPREQUEST-ERROR:' + JSON.stringify(error), 'utf8');fs.unlinkSync('" + syncFile + "');});" + (data ? "req.write('" + JSON.stringify(data).slice(1, -1).replace(/'/g, "\\'") + "');" : "") + "req.end();";
48397
- var syncProc = spawn11(process.argv[0], ["-e", execString]);
49451
+ var syncProc = spawn10(process.argv[0], ["-e", execString]);
48398
49452
  var statusText;
48399
49453
  while (fs.existsSync(syncFile)) {
48400
49454
  }
@@ -52875,7 +53929,7 @@ var require_websocket_server = __commonJS({
52875
53929
  // package.json
52876
53930
  var package_default = {
52877
53931
  name: "@alan-ai-hq/agent-manager",
52878
- version: "0.1.137",
53932
+ version: "0.1.138",
52879
53933
  private: true,
52880
53934
  type: "module",
52881
53935
  description: "Alan machine runtime (alan-agent): identity, link, reconciler, session holders, run log, uploader, local API",
@@ -52924,8 +53978,8 @@ var package_default = {
52924
53978
  };
52925
53979
 
52926
53980
  // src/cli/commands/compat.ts
52927
- var import_node_crypto30 = require("crypto");
52928
- var import_promises65 = require("fs/promises");
53981
+ var import_node_crypto31 = require("crypto");
53982
+ var import_promises66 = require("fs/promises");
52929
53983
  init_runtime_v2();
52930
53984
  init_zod();
52931
53985
 
@@ -54961,7 +56015,7 @@ async function push(context, request2) {
54961
56015
  var import_node_child_process = require("child_process");
54962
56016
 
54963
56017
  // ../agent-core/dist/process.js
54964
- init_chunk_J4T6L5LX();
56018
+ init_chunk_M6YHY2EZ();
54965
56019
  init_chunk_YXWJW7I5();
54966
56020
 
54967
56021
  // src/capabilities/git/run-git.ts
@@ -55969,6 +57023,7 @@ function markVersionInUse(bundlePath) {
55969
57023
  }
55970
57024
 
55971
57025
  // src/platform/instance-lock.ts
57026
+ var import_node_crypto7 = require("crypto");
55972
57027
  var import_node_fs5 = require("fs");
55973
57028
  var import_promises15 = require("fs/promises");
55974
57029
  var import_node_path10 = require("path");
@@ -55997,17 +57052,22 @@ function inodeOf(path4) {
55997
57052
  }
55998
57053
  }
55999
57054
  function tryCreate(path4, self) {
57055
+ const staged = `${path4}.${(0, import_node_crypto7.randomUUID)()}.candidate`;
56000
57056
  try {
56001
- const fd = (0, import_node_fs5.openSync)(path4, "wx", 384);
57057
+ const fd = (0, import_node_fs5.openSync)(staged, "wx", 384);
56002
57058
  try {
56003
57059
  (0, import_node_fs5.writeSync)(fd, JSON.stringify(self));
56004
57060
  } finally {
56005
57061
  (0, import_node_fs5.closeSync)(fd);
56006
57062
  }
56007
- return true;
57063
+ const inode = (0, import_node_fs5.statSync)(staged).ino;
57064
+ (0, import_node_fs5.linkSync)(staged, path4);
57065
+ return inode;
56008
57066
  } catch (error61) {
56009
- if (errnoCode(error61) === "EEXIST") return false;
57067
+ if (errnoCode(error61) === "EEXIST") return null;
56010
57068
  throw error61;
57069
+ } finally {
57070
+ (0, import_node_fs5.rmSync)(staged, { force: true });
56011
57071
  }
56012
57072
  }
56013
57073
  function removeStale(path4, inode) {
@@ -56019,21 +57079,26 @@ function removeStale(path4, inode) {
56019
57079
  }
56020
57080
  }
56021
57081
  async function attempt(path4, self, probe) {
56022
- if (tryCreate(path4, self)) return { kind: "acquired" };
57082
+ const created = tryCreate(path4, self);
57083
+ if (created !== null) return { kind: "acquired", inode: created };
56023
57084
  const inode = inodeOf(path4);
56024
57085
  const owner = readOwner(path4);
56025
57086
  if (owner !== null && await mayBeSameProcess(owner, probe)) return { kind: "held", owner };
56026
57087
  if (inode !== null) removeStale(path4, inode);
56027
- return tryCreate(path4, self) ? { kind: "acquired" } : attempt(path4, self, probe);
57088
+ return attempt(path4, self, probe);
56028
57089
  }
56029
57090
  async function acquireInstanceLock(path4, { clock, waitMs, signal, probe = systemProcessProbe }) {
56030
57091
  await (0, import_promises15.mkdir)((0, import_node_path10.dirname)(path4), { recursive: true, mode: 448 });
56031
57092
  const self = await readProcessIdentity(process.pid);
56032
57093
  if (self === null) throw new RuntimeFault("internal", "Cannot read this process's identity");
56033
57094
  const deadline = clock.monotonic() + waitMs;
57095
+ let heldInode = null;
56034
57096
  for (; ; ) {
56035
57097
  const result = await attempt(path4, self, probe);
56036
- if (result.kind === "acquired") break;
57098
+ if (result.kind === "acquired") {
57099
+ heldInode = result.inode;
57100
+ break;
57101
+ }
56037
57102
  if (clock.monotonic() >= deadline) {
56038
57103
  throw new RuntimeFault(
56039
57104
  "already_running",
@@ -56046,13 +57111,15 @@ async function acquireInstanceLock(path4, { clock, waitMs, signal, probe = syste
56046
57111
  owner: self,
56047
57112
  [Symbol.dispose]: () => {
56048
57113
  const owner = readOwner(path4);
56049
- if (owner?.pid === self.pid && owner.startedAt === self.startedAt) (0, import_node_fs5.unlinkSync)(path4);
57114
+ if (inodeOf(path4) === heldInode && owner?.pid === self.pid && owner.startedAt === self.startedAt) {
57115
+ (0, import_node_fs5.unlinkSync)(path4);
57116
+ }
56050
57117
  }
56051
57118
  };
56052
57119
  }
56053
57120
 
56054
57121
  // src/platform/ipc-endpoint.ts
56055
- var import_node_crypto7 = require("crypto");
57122
+ var import_node_crypto8 = require("crypto");
56056
57123
  var import_node_fs6 = require("fs");
56057
57124
  var import_node_os = require("os");
56058
57125
  var import_node_path11 = require("path");
@@ -56061,7 +57128,7 @@ function windowsPipeName(socketsDir, id) {
56061
57128
  return `\\\\.\\pipe\\alan-${socketsScope(socketsDir)}-${id}`;
56062
57129
  }
56063
57130
  function socketsScope(socketsDir) {
56064
- return (0, import_node_crypto7.createHash)("sha256").update(socketsDir.toLowerCase()).digest("hex").slice(0, 12);
57131
+ return (0, import_node_crypto8.createHash)("sha256").update(socketsDir.toLowerCase()).digest("hex").slice(0, 12);
56065
57132
  }
56066
57133
  function ipcEndpoint(socketsDir, id, platform3 = process.platform) {
56067
57134
  if (platform3 === "win32") return windowsPipeName(socketsDir, id);
@@ -56084,11 +57151,12 @@ var HOLDER_JITLESS_FLAG = "--jitless";
56084
57151
  var HOLDER_NODE_FLAGS = [
56085
57152
  "--max-semi-space-size=1",
56086
57153
  "--max-old-space-size=1024",
57154
+ "--use-system-ca",
56087
57155
  HOLDER_JITLESS_FLAG
56088
57156
  ];
56089
57157
 
56090
57158
  // src/platform/npm-release.ts
56091
- var import_node_crypto8 = require("crypto");
57159
+ var import_node_crypto9 = require("crypto");
56092
57160
  init_zod();
56093
57161
  var RELEASE_TARGETS = [
56094
57162
  "darwin-arm64",
@@ -56156,11 +57224,11 @@ function verifyNpmIntegrity(bytes, dist) {
56156
57224
  if (expected.length === 0) {
56157
57225
  return { ok: false, reason: "the registry's integrity has no sha512 digest" };
56158
57226
  }
56159
- const actual = (0, import_node_crypto8.createHash)("sha512").update(bytes).digest("base64");
57227
+ const actual = (0, import_node_crypto9.createHash)("sha512").update(bytes).digest("base64");
56160
57228
  return expected.includes(actual) ? { ok: true, algorithm: "sha512" } : { ok: false, reason: "the tarball does not match the registry's sha512 integrity" };
56161
57229
  }
56162
57230
  if (dist.shasum !== void 0) {
56163
- return (0, import_node_crypto8.createHash)("sha1").update(bytes).digest("hex") === dist.shasum ? { ok: true, algorithm: "sha1" } : { ok: false, reason: "the tarball does not match the registry's shasum" };
57231
+ return (0, import_node_crypto9.createHash)("sha1").update(bytes).digest("hex") === dist.shasum ? { ok: true, algorithm: "sha1" } : { ok: false, reason: "the tarball does not match the registry's shasum" };
56164
57232
  }
56165
57233
  return { ok: false, reason: "the registry lists no integrity for the tarball" };
56166
57234
  }
@@ -56234,7 +57302,7 @@ function readMemoryPressure() {
56234
57302
  }
56235
57303
 
56236
57304
  // src/platform/release.ts
56237
- var import_node_crypto9 = require("crypto");
57305
+ var import_node_crypto10 = require("crypto");
56238
57306
  var REJECTED_VERSION_RETRY_MS = 24 * 60 * 60 * 1e3;
56239
57307
  function parseVersion(version2) {
56240
57308
  if (!releaseVersionSchema.safeParse(version2).success) return null;
@@ -56277,7 +57345,7 @@ function compareVersions(a, b) {
56277
57345
  return comparePrerelease(left.prerelease, right.prerelease);
56278
57346
  }
56279
57347
  function rolloutBucket(machineId, version2) {
56280
- return (0, import_node_crypto9.createHash)("sha256").update(`${machineId}
57348
+ return (0, import_node_crypto10.createHash)("sha256").update(`${machineId}
56281
57349
  ${version2}`).digest().readUInt32BE(0) % 100;
56282
57350
  }
56283
57351
  function hostReleaseTarget(platform3 = process.platform, arch2 = process.arch) {
@@ -56307,7 +57375,7 @@ function planUpdate(input2) {
56307
57375
 
56308
57376
  // src/platform/release-apply.ts
56309
57377
  var import_node_child_process5 = require("child_process");
56310
- var import_node_crypto10 = require("crypto");
57378
+ var import_node_crypto11 = require("crypto");
56311
57379
  var import_promises17 = require("fs/promises");
56312
57380
  var import_node_path13 = require("path");
56313
57381
  var import_node_util4 = require("util");
@@ -56344,7 +57412,7 @@ async function stageNpmTarball({
56344
57412
  }) {
56345
57413
  const integrity = verifyNpmIntegrity(tarball, release2.dist);
56346
57414
  if (!integrity.ok) throw new RuntimeFault("invalid_file", integrity.reason);
56347
- const scratch = (0, import_node_path13.join)(tmpDir, (0, import_node_crypto10.randomUUID)());
57415
+ const scratch = (0, import_node_path13.join)(tmpDir, (0, import_node_crypto11.randomUUID)());
56348
57416
  await (0, import_promises17.mkdir)(scratch, { recursive: true, mode: 448 });
56349
57417
  try {
56350
57418
  const tarballPath = (0, import_node_path13.join)(scratch, "package.tgz");
@@ -57452,19 +58520,21 @@ function createServiceManager(host, profile) {
57452
58520
  // src/platform/sleep.ts
57453
58521
  var import_node_child_process7 = require("child_process");
57454
58522
  var WAKE_THRESHOLD_MS = 3e4;
57455
- function createWakeDetector(clock, thresholdMs = WAKE_THRESHOLD_MS) {
57456
- const last = { drift: clock.now() - clock.monotonic() };
58523
+ function createWakeDetector(clock, thresholdMs = WAKE_THRESHOLD_MS, platform3 = process.platform) {
58524
+ const last = { wall: clock.now(), drift: clock.now() - clock.monotonic() };
57457
58525
  return {
57458
58526
  check: () => {
57459
- const drift = clock.now() - clock.monotonic();
57460
- const slept = drift - last.drift;
58527
+ const wall = clock.now();
58528
+ const drift = wall - clock.monotonic();
58529
+ const slept = platform3 === "win32" ? wall - last.wall : drift - last.drift;
58530
+ last.wall = wall;
57461
58531
  last.drift = drift;
57462
58532
  return slept >= thresholdMs ? slept : 0;
57463
58533
  }
57464
58534
  };
57465
58535
  }
57466
- function wakeJob(clock, onWake, thresholdMs = WAKE_THRESHOLD_MS) {
57467
- const detector = createWakeDetector(clock, thresholdMs);
58536
+ function wakeJob(clock, onWake, thresholdMs = WAKE_THRESHOLD_MS, platform3 = process.platform) {
58537
+ const detector = createWakeDetector(clock, thresholdMs, platform3);
57468
58538
  return {
57469
58539
  name: "wake.detect",
57470
58540
  run: () => {
@@ -57554,7 +58624,7 @@ function systemAssertionSpawner(log) {
57554
58624
 
57555
58625
  // src/platform/spawn-detached.ts
57556
58626
  var import_node_child_process8 = require("child_process");
57557
- var import_node_crypto11 = require("crypto");
58627
+ var import_node_crypto12 = require("crypto");
57558
58628
  var import_node_fs8 = require("fs");
57559
58629
  var import_node_path21 = require("path");
57560
58630
  var WINDOWS_UNSAFE_ENV = "NODE_PENDING_PIPE_INSTANCES";
@@ -57591,7 +58661,7 @@ async function probeHolderIsolation(platform3, exec, env) {
57591
58661
  }
57592
58662
  const probe = await exec({
57593
58663
  command: SYSTEMD_RUN,
57594
- args: [...scopeArguments(`${SCOPE_PREFIX}-probe-${(0, import_node_crypto11.randomBytes)(4).toString("hex")}`), "true"],
58664
+ args: [...scopeArguments(`${SCOPE_PREFIX}-probe-${(0, import_node_crypto12.randomBytes)(4).toString("hex")}`), "true"],
57595
58665
  timeoutMs: SCOPE_PROBE_TIMEOUT_MS
57596
58666
  });
57597
58667
  if (probe.status === 0) return { kind: "systemd-scope" };
@@ -57603,7 +58673,7 @@ async function probeHolderIsolation(platform3, exec, env) {
57603
58673
  }
57604
58674
  function isolatedCommand(request2, isolation) {
57605
58675
  if (isolation.kind === "detached") return { command: request2.command, args: [...request2.args] };
57606
- const unit = `${SCOPE_PREFIX}-${(0, import_node_crypto11.randomBytes)(6).toString("hex")}`;
58676
+ const unit = `${SCOPE_PREFIX}-${(0, import_node_crypto12.randomBytes)(6).toString("hex")}`;
57607
58677
  return {
57608
58678
  command: SYSTEMD_RUN,
57609
58679
  args: [...scopeArguments(unit), request2.command, ...request2.args]
@@ -57881,7 +58951,7 @@ function createGit(options) {
57881
58951
 
57882
58952
  // src/capabilities/github-proxy/certificates.ts
57883
58953
  var import_node_child_process9 = require("child_process");
57884
- var import_node_crypto12 = require("crypto");
58954
+ var import_node_crypto13 = require("crypto");
57885
58955
  var import_promises24 = require("fs/promises");
57886
58956
  var import_node_path22 = require("path");
57887
58957
  var OPENSSL_TIMEOUT_MS = 1e4;
@@ -57946,7 +59016,7 @@ async function createGitHubProxyCertificates(stateDir) {
57946
59016
  work
57947
59017
  );
57948
59018
  await openssl(
57949
- ["x509", "-req", "-in", "leaf.csr", "-CA", "ca.pem", "-CAkey", "ca.key", "-sha256"].concat(["-set_serial", `0x${(0, import_node_crypto12.randomBytes)(16).toString("hex")}`, "-days", VALIDITY_DAYS]).concat(["-extfile", "leaf.cnf", "-extensions", "leaf", "-out", "leaf.pem"]),
59019
+ ["x509", "-req", "-in", "leaf.csr", "-CA", "ca.pem", "-CAkey", "ca.key", "-sha256"].concat(["-set_serial", `0x${(0, import_node_crypto13.randomBytes)(16).toString("hex")}`, "-days", VALIDITY_DAYS]).concat(["-extfile", "leaf.cnf", "-extensions", "leaf", "-out", "leaf.pem"]),
57950
59020
  work
57951
59021
  );
57952
59022
  const caPath = (0, import_node_path22.join)(stateDir, "github-ca.pem");
@@ -58172,7 +59242,7 @@ async function startGitHubProxy(options) {
58172
59242
  }
58173
59243
 
58174
59244
  // src/capabilities/mcp-config/mcp-config.ts
58175
- var import_node_crypto13 = require("crypto");
59245
+ var import_node_crypto14 = require("crypto");
58176
59246
  var import_promises27 = require("fs/promises");
58177
59247
  var import_node_path24 = require("path");
58178
59248
 
@@ -59156,7 +60226,7 @@ async function readConfig(cli, home) {
59156
60226
  }
59157
60227
  }
59158
60228
  async function writeConfig(path4, text2) {
59159
- const temporary = `${path4}.alan-${(0, import_node_crypto13.randomUUID)()}.tmp`;
60229
+ const temporary = `${path4}.alan-${(0, import_node_crypto14.randomUUID)()}.tmp`;
59160
60230
  try {
59161
60231
  await (0, import_promises27.writeFile)(temporary, text2, { encoding: "utf8", mode: 384, flag: "wx" });
59162
60232
  await (0, import_promises27.rename)(temporary, path4);
@@ -60264,7 +61334,7 @@ function reconcileTranscriptIdentity(entry, transcriptPath, identity, size) {
60264
61334
  }
60265
61335
 
60266
61336
  // src/capabilities/native-ingest/transcript-window.ts
60267
- var import_node_crypto14 = require("crypto");
61337
+ var import_node_crypto15 = require("crypto");
60268
61338
  var import_promises32 = require("fs/promises");
60269
61339
  init_acp2();
60270
61340
  init_claude();
@@ -60414,7 +61484,7 @@ function lastMatchingTurnIndex(turns, target) {
60414
61484
  function signalDigest(target) {
60415
61485
  const fingerprint = target.assistantFingerprint;
60416
61486
  const basis = target.providerTurnId ?? (fingerprint ? `${fingerprint.length}\0${fingerprint.head}\0${fingerprint.tail}` : null);
60417
- return basis ? (0, import_node_crypto14.createHash)("sha256").update(basis).digest("hex") : null;
61487
+ return basis ? (0, import_node_crypto15.createHash)("sha256").update(basis).digest("hex") : null;
60418
61488
  }
60419
61489
  function lastForegroundStop(updates) {
60420
61490
  for (let index = updates.length - 1; index >= 0; index -= 1) {
@@ -61156,7 +62226,9 @@ function providerCommandFor(backendKind) {
61156
62226
  return BY_BACKEND.get(backendKind)?.command;
61157
62227
  }
61158
62228
  function envValue(env, name) {
61159
- const key = Object.keys(env).find((candidate) => candidate.toUpperCase() === name);
62229
+ const key = Object.keys(env).findLast(
62230
+ (candidate) => candidate.toUpperCase() === name.toUpperCase()
62231
+ );
61160
62232
  return key === void 0 ? "" : env[key] ?? "";
61161
62233
  }
61162
62234
  function pathDelimiter(platform3) {
@@ -61172,12 +62244,18 @@ async function isRunnable(path4, platform3) {
61172
62244
  }
61173
62245
  }
61174
62246
  function windowsExtensions(command, env) {
61175
- const extensions = (envValue(env, "PATHEXT") || ".COM;.EXE;.BAT;.CMD").split(";").filter((extension) => extension.startsWith("."));
62247
+ const extensions = (envValue(env, "PATHEXT") || ".COM;.EXE;.BAT;.CMD").split(";").map((extension) => extension.trim()).filter((extension) => [".COM", ".EXE", ".BAT", ".CMD"].includes(extension.toUpperCase()));
61176
62248
  const named = command.toLowerCase();
61177
- return extensions.some((extension) => named.endsWith(extension.toLowerCase())) ? [""] : extensions;
62249
+ return [".com", ".exe", ...extensions.map((extension) => extension.toLowerCase())].some(
62250
+ (extension) => named.endsWith(extension)
62251
+ ) ? [""] : extensions;
61178
62252
  }
61179
62253
  async function resolveCommandOnPath(command, env, platform3) {
61180
- const directories = envValue(env, "PATH").split(pathDelimiter(platform3)).filter((directory) => directory.length > 0);
62254
+ const directories = envValue(env, "PATH").split(pathDelimiter(platform3)).map(
62255
+ (directory) => platform3 === "win32" ? directory.trim().replace(/^"(.*)"$/, "$1") : directory
62256
+ ).filter(
62257
+ (directory) => platform3 === "win32" ? import_node_path32.win32.isAbsolute(directory) : directory.length > 0
62258
+ );
61181
62259
  const extensions = platform3 === "win32" ? windowsExtensions(command, env) : [""];
61182
62260
  for (const directory of directories) {
61183
62261
  for (const extension of extensions) {
@@ -61224,8 +62302,21 @@ function alanCodeProviderModels() {
61224
62302
  var import_node_child_process10 = require("child_process");
61225
62303
  var DEFAULT_TIMEOUT_MS2 = 5e3;
61226
62304
  var DEFAULT_MAX_BYTES = 1024 * 1024;
62305
+ function withWindowsHelper(env) {
62306
+ const helper = windowsHelperPath();
62307
+ return helper === null ? env : { ...env, ALAN_WINHELPER_PATH: helper };
62308
+ }
61227
62309
  function directLaunch(command, args, options) {
61228
62310
  try {
62311
+ if ((options.platform ?? process.platform) === "win32") {
62312
+ const plan2 = planSpawn({
62313
+ command,
62314
+ args,
62315
+ env: canonicalWindowsEnvironment(options.env),
62316
+ platform: "win32"
62317
+ });
62318
+ return { file: plan2.file, args: plan2.args, windowsVerbatimArguments: false };
62319
+ }
61229
62320
  return planDirectLaunch({
61230
62321
  command,
61231
62322
  args,
@@ -61237,42 +62328,88 @@ function directLaunch(command, args, options) {
61237
62328
  }
61238
62329
  }
61239
62330
  function captureProbe(command, args, options) {
62331
+ const platform3 = options.platform ?? process.platform;
61240
62332
  const launch = directLaunch(command, args, options);
61241
62333
  if (launch === void 0) return Promise.resolve({ stdout: "", stderr: "", exitCode: void 0 });
62334
+ const env = platform3 === "win32" ? withWindowsHelper(canonicalWindowsEnvironment(options.env)) : options.env;
61242
62335
  return new Promise((resolve12) => {
61243
62336
  const limit = options.maxBufferBytes ?? DEFAULT_MAX_BYTES;
61244
62337
  const stdout = [];
61245
62338
  const stderr = [];
61246
62339
  let bytes = 0;
61247
62340
  let overflowed = false;
61248
- const child = (0, import_node_child_process10.spawn)(launch.file, [...launch.args], {
61249
- env: { ...options.env },
62341
+ const windowsChild = platform3 === "win32" ? spawnInWindowsJob(planSpawn({ command, args, env, platform: platform3 }), {
62342
+ cwd: process.cwd(),
62343
+ env
62344
+ }) : void 0;
62345
+ const child = windowsChild ?? (0, import_node_child_process10.spawn)(launch.file, [...launch.args], {
62346
+ env: { ...env },
61250
62347
  stdio: ["ignore", "pipe", "pipe"],
61251
- timeout: options.timeoutMs ?? DEFAULT_TIMEOUT_MS2,
62348
+ detached: true,
61252
62349
  windowsHide: true,
61253
62350
  windowsVerbatimArguments: launch.windowsVerbatimArguments
61254
62351
  });
62352
+ child.stdin?.end();
62353
+ const terminate = () => {
62354
+ if (platform3 !== "win32" && child.pid !== void 0) {
62355
+ try {
62356
+ process.kill(-child.pid, "SIGKILL");
62357
+ return;
62358
+ } catch {
62359
+ }
62360
+ }
62361
+ child.kill("SIGKILL");
62362
+ };
62363
+ let settled2 = false;
62364
+ const deadlineController = new AbortController();
62365
+ const finish = (exitCode) => {
62366
+ if (settled2) return;
62367
+ settled2 = true;
62368
+ deadlineController.abort();
62369
+ options.signal?.removeEventListener("abort", abort);
62370
+ resolve12({
62371
+ stdout: Buffer.concat(stdout).toString("utf8"),
62372
+ stderr: Buffer.concat(stderr).toString("utf8"),
62373
+ exitCode
62374
+ });
62375
+ };
62376
+ void systemClock.sleep(options.timeoutMs ?? DEFAULT_TIMEOUT_MS2, deadlineController.signal).then(
62377
+ () => {
62378
+ terminate();
62379
+ child.stdout.destroy();
62380
+ child.stderr.destroy();
62381
+ finish(void 0);
62382
+ },
62383
+ () => void 0
62384
+ );
62385
+ const abort = () => {
62386
+ terminate();
62387
+ child.stdout.destroy();
62388
+ child.stderr.destroy();
62389
+ finish(void 0);
62390
+ };
62391
+ options.signal?.addEventListener("abort", abort, { once: true });
62392
+ if (options.signal?.aborted) abort();
61255
62393
  const collect = (into) => (chunk) => {
61256
62394
  bytes += chunk.length;
61257
62395
  if (bytes > limit) {
61258
62396
  overflowed = true;
61259
- child.kill("SIGKILL");
62397
+ terminate();
62398
+ finish(void 0);
61260
62399
  return;
61261
62400
  }
61262
62401
  into.push(chunk);
61263
62402
  };
61264
62403
  child.stdout.on("data", collect(stdout));
61265
62404
  child.stderr.on("data", collect(stderr));
61266
- const finish = (exitCode) => resolve12({
61267
- stdout: Buffer.concat(stdout).toString("utf8"),
61268
- stderr: Buffer.concat(stderr).toString("utf8"),
61269
- exitCode
61270
- });
61271
62405
  child.once("error", () => finish(void 0));
61272
62406
  child.once(
61273
62407
  "close",
61274
62408
  (code, signal) => finish(overflowed || signal !== null || code === null ? void 0 : code)
61275
62409
  );
62410
+ if (windowsChild !== void 0) {
62411
+ void waitForWindowsJob(windowsChild, command).catch(() => finish(void 0));
62412
+ }
61276
62413
  });
61277
62414
  }
61278
62415
 
@@ -61719,7 +62856,7 @@ var import_node_path37 = require("path");
61719
62856
 
61720
62857
  // ../shared/dist/node/shell-environment.js
61721
62858
  var import_node_child_process12 = require("child_process");
61722
- var import_node_crypto15 = require("crypto");
62859
+ var import_node_crypto16 = require("crypto");
61723
62860
  var import_node_fs15 = require("fs");
61724
62861
  var import_node_os5 = require("os");
61725
62862
  var import_node_path36 = require("path");
@@ -61863,6 +63000,15 @@ function installerDirectories(home, platform3) {
61863
63000
  const system = platform3 === "darwin" ? ["/opt/homebrew/bin", "/usr/local/bin"] : ["/usr/local/bin"];
61864
63001
  return [...user, ...system];
61865
63002
  }
63003
+ function windowsInstallerDirectories(env) {
63004
+ const home = envValue(env, "USERPROFILE") || envValue(env, "HOME");
63005
+ const hasHome = import_node_path37.win32.isAbsolute(home);
63006
+ const appData = envValue(env, "APPDATA") || (hasHome ? import_node_path37.win32.join(home, "AppData", "Roaming") : "");
63007
+ return [
63008
+ ...hasHome ? [import_node_path37.win32.join(home, ".local", "bin")] : [],
63009
+ ...import_node_path37.win32.isAbsolute(appData) ? [import_node_path37.win32.join(appData, "npm")] : []
63010
+ ];
63011
+ }
61866
63012
  function printPathCommand() {
61867
63013
  return `printf '${MARKER}%s${MARKER}' "$PATH"`;
61868
63014
  }
@@ -61915,7 +63061,14 @@ async function rememberLastKnownGood(file2, path4) {
61915
63061
  }
61916
63062
  async function resolveCliEnvironmentDetailed(options) {
61917
63063
  const { env, platform: platform3 } = options;
61918
- if (platform3 === "win32") return { env: { ...env }, source: "none" };
63064
+ if (platform3 === "win32") {
63065
+ const path4 = appendPathDirectories(
63066
+ envValue(env, "PATH"),
63067
+ windowsInstallerDirectories(env),
63068
+ ";"
63069
+ );
63070
+ return { env: canonicalWindowsEnvironment({ ...env, PATH: path4 }), source: "none" };
63071
+ }
61919
63072
  const loginPath = await readLoginShellPath(env, options.capture ?? captureProbe);
61920
63073
  if (loginPath !== null) await rememberLastKnownGood(options.lastKnownGoodFile, loginPath);
61921
63074
  const lastKnownGood = loginPath === null ? await readLastKnownGood(options.lastKnownGoodFile) : null;
@@ -61962,8 +63115,7 @@ async function openCliEnvironment(options) {
61962
63115
  }
61963
63116
 
61964
63117
  // src/capabilities/providers/managed.ts
61965
- var import_node_child_process13 = require("child_process");
61966
- var import_node_crypto16 = require("crypto");
63118
+ var import_node_crypto17 = require("crypto");
61967
63119
  var import_promises36 = require("fs/promises");
61968
63120
  var import_node_path38 = require("path");
61969
63121
  init_zod();
@@ -61992,9 +63144,10 @@ function withManagedProviderPaths(manager, env, nodeDirectory, platform3 = proce
61992
63144
  const path4 = [
61993
63145
  ...manager.selections().map((item) => item.binDir),
61994
63146
  ...nodeDirectory === void 0 ? [] : [nodeDirectory],
61995
- env.PATH ?? ""
63147
+ envValue(env, "PATH")
61996
63148
  ].filter(Boolean);
61997
- return { ...env, PATH: path4.join(pathDelimiter(platform3)) };
63149
+ const merged = { ...env, PATH: path4.join(pathDelimiter(platform3)) };
63150
+ return platform3 === "win32" ? canonicalWindowsEnvironment(merged) : merged;
61998
63151
  }
61999
63152
  function packageFor(backendKind) {
62000
63153
  const provider4 = PACKAGES[backendKind];
@@ -62091,7 +63244,7 @@ function createManagedProviderClis(options) {
62091
63244
  };
62092
63245
  const persist = async () => {
62093
63246
  await (0, import_promises36.mkdir)(options.root, { recursive: true, mode: 448 });
62094
- const staged = `${file2}.${(0, import_node_crypto16.randomUUID)()}`;
63247
+ const staged = `${file2}.${(0, import_node_crypto17.randomUUID)()}`;
62095
63248
  try {
62096
63249
  await (0, import_promises36.writeFile)(staged, JSON.stringify(state), { mode: 384 });
62097
63250
  await (0, import_promises36.rename)(staged, file2);
@@ -62126,7 +63279,7 @@ function createManagedProviderClis(options) {
62126
63279
  try {
62127
63280
  parsed = selectedSchema.parse(JSON.parse(raw));
62128
63281
  } catch {
62129
- await (0, import_promises36.rename)(file2, `${file2}.invalid.${(0, import_node_crypto16.randomUUID)()}`).catch(() => void 0);
63282
+ await (0, import_promises36.rename)(file2, `${file2}.invalid.${(0, import_node_crypto17.randomUUID)()}`).catch(() => void 0);
62130
63283
  return;
62131
63284
  }
62132
63285
  for (const [backendKind, version2] of Object.entries(parsed)) {
@@ -62184,7 +63337,7 @@ function createManagedProviderClis(options) {
62184
63337
  const existing = selection(options.root, backendKind, exact);
62185
63338
  if (!await runnable(existing.executable) || !await options.probe(existing.executable, backendKind)) {
62186
63339
  await (0, import_promises36.mkdir)((0, import_node_path38.dirname)(target), { recursive: true, mode: 448 });
62187
- const staged = `${target}.${(0, import_node_crypto16.randomUUID)()}`;
63340
+ const staged = `${target}.${(0, import_node_crypto17.randomUUID)()}`;
62188
63341
  try {
62189
63342
  await options.installPackage(provider4.name, exact, staged, provider4.command, signal);
62190
63343
  const built = (0, import_node_path38.join)(staged, "node_modules", ".bin", provider4.command);
@@ -62214,9 +63367,18 @@ function createManagedProviderClis(options) {
62214
63367
  })
62215
63368
  };
62216
63369
  }
63370
+ function withInstallerPath(options) {
63371
+ const platform3 = options.platform ?? process.platform;
63372
+ const path4 = [
63373
+ platform3 === "win32" ? import_node_path38.win32.dirname(options.command) : (0, import_node_path38.dirname)(options.command),
63374
+ envValue(options.env, "PATH")
63375
+ ].filter(Boolean).join(pathDelimiter(platform3));
63376
+ const env = { ...options.env, PATH: path4 };
63377
+ return platform3 === "win32" ? canonicalWindowsEnvironment(env) : env;
63378
+ }
62217
63379
  function createNpmPackageInstaller(options) {
62218
- return (packageName, version2, destination, _command, signal) => new Promise((resolve12, reject) => {
62219
- const child = (0, import_node_child_process13.spawn)(
63380
+ return async (packageName, version2, destination, _command, signal) => {
63381
+ const result = await captureProbe(
62220
63382
  options.command,
62221
63383
  [
62222
63384
  ...options.argsBeforeNpm ?? [],
@@ -62228,53 +63390,35 @@ function createNpmPackageInstaller(options) {
62228
63390
  `${packageName}@${version2}`
62229
63391
  ],
62230
63392
  {
62231
- env: { ...options.env, PATH: `${(0, import_node_path38.dirname)(options.command)}:${options.env.PATH ?? ""}` },
63393
+ env: withInstallerPath(options),
62232
63394
  signal,
62233
- stdio: ["ignore", "pipe", "pipe"]
63395
+ timeoutMs: 10 * 6e4,
63396
+ maxBufferBytes: 1024 * 1024
62234
63397
  }
62235
63398
  );
62236
- let output2 = "";
62237
- for (const stream of [child.stdout, child.stderr]) {
62238
- stream?.on("data", (chunk) => {
62239
- output2 = `${output2}${chunk.toString()}`.slice(-8e3);
62240
- });
63399
+ if (result.exitCode !== 0) {
63400
+ const output2 = `${result.stdout}
63401
+ ${result.stderr}`.trim().slice(-8e3);
63402
+ throw new Error(
63403
+ `npm install failed (${result.exitCode ?? "timeout, cancellation or launch"}): ${output2}`
63404
+ );
62241
63405
  }
62242
- child.on("error", reject);
62243
- child.on("close", (code) => {
62244
- if (code === 0) resolve12();
62245
- else reject(new Error(`npm install failed (${code ?? "signal"}): ${output2.trim()}`));
62246
- });
62247
- });
63406
+ };
62248
63407
  }
62249
63408
  function createNpmVersionResolver(options) {
62250
- return (packageName, signal) => new Promise((resolve12, reject) => {
62251
- const child = (0, import_node_child_process13.spawn)(
63409
+ return async (packageName, signal) => {
63410
+ const result = await captureProbe(
62252
63411
  options.command,
62253
63412
  [...options.argsBeforeNpm ?? [], "view", packageName, "version", "--json"],
62254
- {
62255
- env: { ...options.env },
62256
- signal: AbortSignal.any([
62257
- signal ?? new AbortController().signal,
62258
- AbortSignal.timeout(3e4)
62259
- ]),
62260
- stdio: ["ignore", "pipe", "pipe"]
62261
- }
63413
+ { env: withInstallerPath(options), signal, timeoutMs: 3e4, maxBufferBytes: 1e5 }
62262
63414
  );
62263
- let output2 = "";
62264
- child.stdout.on("data", (chunk) => {
62265
- output2 = `${output2}${chunk.toString()}`;
62266
- if (output2.length > 1e5) child.kill();
62267
- });
62268
- child.on("error", reject);
62269
- child.on("close", (code) => {
62270
- if (code !== 0) return reject(new Error(`Cannot look up ${packageName} version`));
62271
- try {
62272
- resolve12(parseNpmVersion(output2, packageName));
62273
- } catch (error61) {
62274
- reject(error61);
62275
- }
62276
- });
62277
- });
63415
+ if (result.exitCode !== 0) {
63416
+ throw new Error(
63417
+ `Cannot look up ${packageName} version: ${result.stderr.trim().slice(-2e3)}`
63418
+ );
63419
+ }
63420
+ return parseNpmVersion(result.stdout, packageName);
63421
+ };
62278
63422
  }
62279
63423
  function parseNpmVersion(output2, packageName) {
62280
63424
  const versions = external_exports.union([external_exports.string(), external_exports.array(external_exports.string())]).parse(JSON.parse(output2));
@@ -62311,7 +63455,7 @@ var import_node_path43 = __toESM(require("path"));
62311
63455
 
62312
63456
  // ../shared/dist/node/skill-package.js
62313
63457
  var import_node_buffer = require("buffer");
62314
- var import_node_crypto17 = require("crypto");
63458
+ var import_node_crypto18 = require("crypto");
62315
63459
  var import_promises37 = require("fs/promises");
62316
63460
  var import_node_path39 = require("path");
62317
63461
  var import_yaml = __toESM(require_dist(), 1);
@@ -62711,7 +63855,7 @@ function comparePackageFiles(left, right) {
62711
63855
  return import_node_buffer.Buffer.compare(import_node_buffer.Buffer.from(left.manifest.path, "utf8"), import_node_buffer.Buffer.from(right.manifest.path, "utf8"));
62712
63856
  }
62713
63857
  function hashPackageTree(files) {
62714
- const hash2 = (0, import_node_crypto17.createHash)("sha256");
63858
+ const hash2 = (0, import_node_crypto18.createHash)("sha256");
62715
63859
  hash2.update(TREE_HASH_PREFIX);
62716
63860
  for (const file2 of files) {
62717
63861
  const path4 = import_node_buffer.Buffer.from(file2.path, "utf8");
@@ -62724,7 +63868,7 @@ function hashPackageTree(files) {
62724
63868
  return `sha256:${hash2.digest("hex")}`;
62725
63869
  }
62726
63870
  function sha256(bytes) {
62727
- return `sha256:${(0, import_node_crypto17.createHash)("sha256").update(bytes).digest("hex")}`;
63871
+ return `sha256:${(0, import_node_crypto18.createHash)("sha256").update(bytes).digest("hex")}`;
62728
63872
  }
62729
63873
  function uint322(value2) {
62730
63874
  const buffer = import_node_buffer.Buffer.allocUnsafe(4);
@@ -62738,13 +63882,13 @@ function uint642(value2) {
62738
63882
  }
62739
63883
 
62740
63884
  // src/capabilities/skills/local-sources.ts
62741
- var import_node_crypto19 = require("crypto");
63885
+ var import_node_crypto20 = require("crypto");
62742
63886
  var import_promises39 = require("fs/promises");
62743
63887
  var import_node_path41 = __toESM(require("path"));
62744
63888
  init_type_guards();
62745
63889
 
62746
63890
  // src/capabilities/skills/local-scan.ts
62747
- var import_node_crypto18 = require("crypto");
63891
+ var import_node_crypto19 = require("crypto");
62748
63892
  var import_promises38 = require("fs/promises");
62749
63893
  var import_node_path40 = __toESM(require("path"));
62750
63894
  var MAX_CANDIDATES = 2e3;
@@ -62753,7 +63897,7 @@ function createLocalSkillScanCache() {
62753
63897
  return { inspections: /* @__PURE__ */ new Map(), lastCompleteRevision: null };
62754
63898
  }
62755
63899
  async function scanSkillRoots(input2, cache2) {
62756
- const attemptId = (0, import_node_crypto18.randomUUID)();
63900
+ const attemptId = (0, import_node_crypto19.randomUUID)();
62757
63901
  const ignoredPaths = input2.ignoredPaths ?? [];
62758
63902
  const resolvedRoots = resolveScanRoots(input2.roots, input2.enabledProviderKinds ?? []);
62759
63903
  const pass = {
@@ -62818,7 +63962,7 @@ function failedLocalSkillScan(cache2, code, message2) {
62818
63962
  return {
62819
63963
  outcome: {
62820
63964
  status: "failed",
62821
- attemptId: (0, import_node_crypto18.randomUUID)(),
63965
+ attemptId: (0, import_node_crypto19.randomUUID)(),
62822
63966
  retainedInventoryRevision: cache2.lastCompleteRevision,
62823
63967
  diagnostics: [{ code, message: message2.slice(0, 2048) }]
62824
63968
  },
@@ -62982,11 +64126,11 @@ function candidateOrigin(root) {
62982
64126
  }
62983
64127
  function createLocalKey(root, skillName) {
62984
64128
  const rootIdentity = root.kind === "configured" ? `configured:${root.declarationId}` : root.kind === "repository" ? `repository:${root.repositoryId}` : "drafts";
62985
- const digest = (0, import_node_crypto18.createHash)("sha256").update("alan-local-skill-v1\0").update(rootIdentity).update("\0").update(skillName.normalize("NFC")).digest("hex");
64129
+ const digest = (0, import_node_crypto19.createHash)("sha256").update("alan-local-skill-v1\0").update(rootIdentity).update("\0").update(skillName.normalize("NFC")).digest("hex");
62986
64130
  return `local:${digest}`;
62987
64131
  }
62988
64132
  function hashInventory(candidates2) {
62989
- const hash2 = (0, import_node_crypto18.createHash)("sha256").update("alan-skill-inventory-v1\0");
64133
+ const hash2 = (0, import_node_crypto19.createHash)("sha256").update("alan-skill-inventory-v1\0");
62990
64134
  for (const candidate of candidates2) {
62991
64135
  hash2.update(candidate.localKey).update("\0");
62992
64136
  hash2.update(candidate.contentHash).update("\0");
@@ -63006,7 +64150,7 @@ function deduplicateByContent(candidates2) {
63006
64150
  return candidates2.filter((located) => winners.has(located));
63007
64151
  }
63008
64152
  async function fingerprintPackage(root) {
63009
- const hash2 = (0, import_node_crypto18.createHash)("sha256").update("alan-skill-stat-fingerprint-v1\0");
64153
+ const hash2 = (0, import_node_crypto19.createHash)("sha256").update("alan-skill-stat-fingerprint-v1\0");
63010
64154
  const visit2 = async (directory, relativeDirectory) => {
63011
64155
  const entries = await (0, import_promises38.readdir)(directory, { withFileTypes: true });
63012
64156
  entries.sort((left, right) => Buffer.compare(Buffer.from(left.name), Buffer.from(right.name)));
@@ -63209,7 +64353,7 @@ function staleCodexDeclaration(relativeDirectory, label, providerKinds) {
63209
64353
  return ownedByCursor || label === "Legacy Cursor-compatible skills";
63210
64354
  }
63211
64355
  function stableSourceDeclarationId(sourcePath) {
63212
- const digest = (0, import_node_crypto19.createHash)("sha256").update("alan-skill-source-v1\0").update(sourcePath.normalize("NFC")).digest("hex").slice(0, 24);
64356
+ const digest = (0, import_node_crypto20.createHash)("sha256").update("alan-skill-source-v1\0").update(sourcePath.normalize("NFC")).digest("hex").slice(0, 24);
63213
64357
  return `source-${digest}`;
63214
64358
  }
63215
64359
  function requiredSourceId(value2, field3) {
@@ -63256,10 +64400,10 @@ var import_promises40 = require("fs/promises");
63256
64400
  var import_node_path42 = require("path");
63257
64401
 
63258
64402
  // ../shared/dist/node/alan-skill-identity.js
63259
- var import_node_crypto20 = require("crypto");
64403
+ var import_node_crypto21 = require("crypto");
63260
64404
  var ALAN_SKILL_NAMESPACE = "ec71d99b-d207-4ca2-a9eb-3a7bed4a73fd";
63261
64405
  function uuidV5(name, namespace) {
63262
- const bytes = (0, import_node_crypto20.createHash)("sha1").update(Buffer.from(namespace.replaceAll("-", ""), "hex")).update(name, "utf8").digest().subarray(0, 16);
64406
+ const bytes = (0, import_node_crypto21.createHash)("sha1").update(Buffer.from(namespace.replaceAll("-", ""), "hex")).update(name, "utf8").digest().subarray(0, 16);
63263
64407
  bytes[6] = bytes[6] & 15 | 80;
63264
64408
  bytes[8] = bytes[8] & 63 | 128;
63265
64409
  const hex3 = bytes.toString("hex");
@@ -63526,7 +64670,7 @@ var import_promises43 = require("fs/promises");
63526
64670
 
63527
64671
  // ../shared/dist/node/skill-bundle.js
63528
64672
  var import_node_buffer2 = require("buffer");
63529
- var import_node_crypto21 = require("crypto");
64673
+ var import_node_crypto22 = require("crypto");
63530
64674
  var import_promises42 = require("fs/promises");
63531
64675
  var import_node_path44 = require("path");
63532
64676
  var import_node_stream = require("stream");
@@ -63665,7 +64809,7 @@ function requireSafeArchivePath(value2) {
63665
64809
  return normalized2;
63666
64810
  }
63667
64811
  function sha2562(bytes) {
63668
- return `sha256:${(0, import_node_crypto21.createHash)("sha256").update(bytes).digest("hex")}`;
64812
+ return `sha256:${(0, import_node_crypto22.createHash)("sha256").update(bytes).digest("hex")}`;
63669
64813
  }
63670
64814
 
63671
64815
  // src/capabilities/skills/local-upload.ts
@@ -63709,14 +64853,14 @@ async function publishLocalSkill(options) {
63709
64853
  }
63710
64854
 
63711
64855
  // src/capabilities/skills/sync.ts
63712
- var import_node_crypto22 = require("crypto");
64856
+ var import_node_crypto23 = require("crypto");
63713
64857
  var import_promises44 = require("fs/promises");
63714
64858
  var import_node_path45 = require("path");
63715
64859
  var SKILL_PREPARE_WAIT_MS = 15e3;
63716
64860
  async function install(layout, source, skill, download, signal) {
63717
64861
  const bytes = await source.download(download.url, signal);
63718
64862
  await (0, import_promises44.mkdir)(layout.tmpDir, { recursive: true, mode: 448 });
63719
- const staging = (0, import_node_path45.join)(layout.tmpDir, (0, import_node_crypto22.randomUUID)());
64863
+ const staging = (0, import_node_path45.join)(layout.tmpDir, (0, import_node_crypto23.randomUUID)());
63720
64864
  await extractSkillBundle(Buffer.from(bytes), staging, {
63721
64865
  expectedArchiveHash: download.archiveHash,
63722
64866
  expectedContentHash: skill.contentHash
@@ -64129,7 +65273,7 @@ async function openApprovedPaths(options) {
64129
65273
  }
64130
65274
 
64131
65275
  // src/capabilities/workspace/locks.ts
64132
- var import_node_crypto23 = require("crypto");
65276
+ var import_node_crypto24 = require("crypto");
64133
65277
  var import_promises46 = require("fs/promises");
64134
65278
  var import_node_path47 = require("path");
64135
65279
  init_zod();
@@ -64146,7 +65290,7 @@ var ownerSchema = external_exports.object({
64146
65290
  since: external_exports.number().int().nonnegative()
64147
65291
  });
64148
65292
  function repositoryLockKey(commonDir, platform3) {
64149
- return (0, import_node_crypto23.createHash)("sha256").update(comparablePath(commonDir, platform3)).digest("hex").slice(0, 32);
65293
+ return (0, import_node_crypto24.createHash)("sha256").update(comparablePath(commonDir, platform3)).digest("hex").slice(0, 32);
64150
65294
  }
64151
65295
  async function readOwner2(path4) {
64152
65296
  let text2;
@@ -64259,7 +65403,7 @@ function openRepositoryLocks(options) {
64259
65403
  },
64260
65404
  tryShared: async (commonDir, runId) => {
64261
65405
  const { key, dir } = await folder(commonDir);
64262
- const file2 = `${RUN_FILE_PREFIX}${(0, import_node_crypto23.createHash)("sha256").update(runId).digest("hex").slice(0, 32)}.json`;
65406
+ const file2 = `${RUN_FILE_PREFIX}${(0, import_node_crypto24.createHash)("sha256").update(runId).digest("hex").slice(0, 32)}.json`;
64263
65407
  const path4 = (0, import_node_path47.join)(dir, file2);
64264
65408
  const owner = await self(runId);
64265
65409
  await writeJsonFileAtomic(path4, owner);
@@ -64495,7 +65639,7 @@ async function openWorkspaces(options) {
64495
65639
 
64496
65640
  // src/cli/config.ts
64497
65641
  var import_node_os11 = require("os");
64498
- var import_node_path64 = require("path");
65642
+ var import_node_path65 = require("path");
64499
65643
  init_zod();
64500
65644
 
64501
65645
  // src/client/contract.ts
@@ -64780,6 +65924,7 @@ var mcpConfigResultSchema = external_exports.object({
64780
65924
 
64781
65925
  // src/client/runtime-client.ts
64782
65926
  var import_promises47 = require("fs/promises");
65927
+ init_acp();
64783
65928
  init_runtime_v2();
64784
65929
 
64785
65930
  // src/client/sse.ts
@@ -64996,11 +66141,51 @@ function createRuntimeClient(options) {
64996
66141
  throw new RuntimeClientError("unavailable", "The run log stream closed before the run ended");
64997
66142
  }
64998
66143
  const runs = async (signal) => (await json2({ path: LOCAL_API_ROUTES.runs }, runsResponseSchema, signal)).runs;
66144
+ async function* followConversationMessages(conversationId, limit, signal) {
66145
+ const stopped = new AbortController();
66146
+ try {
66147
+ const body = await openStream(
66148
+ {
66149
+ path: `/v2/conversations/${encodeURIComponent(conversationId)}/messages/sse`,
66150
+ query: { limit: String(limit) }
66151
+ },
66152
+ AbortSignal.any([signal, stopped.signal])
66153
+ );
66154
+ for await (const event of readServerSentEvents(body)) {
66155
+ const value2 = JSON.parse(event.data);
66156
+ if (event.event === "snapshot" && isConversationMessagesPage(value2))
66157
+ yield { kind: "snapshot", page: value2 };
66158
+ else if (event.event === "turn" && isConversationMessageTurn(value2))
66159
+ yield { kind: "turn", turn: value2 };
66160
+ else throw new RuntimeClientError("protocol", "Invalid local conversation update");
66161
+ }
66162
+ if (!signal.aborted)
66163
+ throw new RuntimeClientError("unavailable", "The local conversation stream closed");
66164
+ } finally {
66165
+ stopped.abort();
66166
+ }
66167
+ }
64999
66168
  return {
65000
66169
  status: (signal) => json2({ path: LOCAL_API_ROUTES.status }, runtimeStatusSchema, signal),
65001
66170
  watchStatus,
66171
+ followConversationMessages,
65002
66172
  runs,
65003
66173
  conversationRuns: async (conversationId, signal) => (await runs(signal)).filter((run2) => run2.conversationId === conversationId),
66174
+ readConversationMessages: async (conversationId, limit, before, signal) => {
66175
+ const response = await send2(
66176
+ {
66177
+ path: `/v2/conversations/${encodeURIComponent(conversationId)}/messages`,
66178
+ query: { limit: String(limit), ...before === null ? {} : { before } }
66179
+ },
66180
+ signal
66181
+ );
66182
+ if (response.status === 404) return null;
66183
+ if (!response.ok) throw await rejection(response);
66184
+ const page = await response.json();
66185
+ if (!isConversationMessagesPage(page))
66186
+ throw new RuntimeClientError("protocol", "Invalid local conversation page");
66187
+ return page;
66188
+ },
65004
66189
  readRunLog: async (runId, query, signal) => {
65005
66190
  const response = await send2(
65006
66191
  {
@@ -65166,14 +66351,14 @@ async function sendNativeHookSignal(discoveryPath, hookSignal, signal) {
65166
66351
  }
65167
66352
 
65168
66353
  // src/sessions/index.ts
65169
- var import_node_crypto29 = require("crypto");
65170
- var import_promises63 = require("fs/promises");
66354
+ var import_node_crypto30 = require("crypto");
66355
+ var import_promises64 = require("fs/promises");
65171
66356
  var import_node_os10 = require("os");
65172
- var import_node_path63 = require("path");
66357
+ var import_node_path64 = require("path");
65173
66358
  init_runtime_v2();
65174
66359
 
65175
66360
  // src/holder/control-client.ts
65176
- var import_node_crypto24 = require("crypto");
66361
+ var import_node_crypto25 = require("crypto");
65177
66362
  var import_node_net2 = require("net");
65178
66363
  init_runtime_v2();
65179
66364
 
@@ -65243,7 +66428,7 @@ async function connectHolder(endpoint, token, onEvent) {
65243
66428
  });
65244
66429
  const pid = await ready;
65245
66430
  const request2 = (body) => {
65246
- const id = (0, import_node_crypto24.randomUUID)();
66431
+ const id = (0, import_node_crypto25.randomUUID)();
65247
66432
  return new Promise((resolve12, reject) => {
65248
66433
  const timer = AbortSignal.timeout(REQUEST_TIMEOUT_MS7);
65249
66434
  timer.addEventListener("abort", () => {
@@ -65582,10 +66767,10 @@ async function prepareRunInputs(spec, { source, tmpDir, signal, skills = [] }) {
65582
66767
  }
65583
66768
 
65584
66769
  // src/holder/serve.ts
65585
- var import_node_crypto28 = require("crypto");
66770
+ var import_node_crypto29 = require("crypto");
65586
66771
  var import_node_fs21 = require("fs");
65587
66772
  var import_node_net3 = require("net");
65588
- var import_node_path62 = require("path");
66773
+ var import_node_path63 = require("path");
65589
66774
  init_runtime_v2();
65590
66775
 
65591
66776
  // src/holder/admission.ts
@@ -65676,7 +66861,7 @@ async function discoverRelocatedWorkspace(search) {
65676
66861
  }
65677
66862
 
65678
66863
  // src/holder/checkout-refresh.ts
65679
- var import_node_crypto26 = require("crypto");
66864
+ var import_node_crypto27 = require("crypto");
65680
66865
  var import_promises57 = require("fs/promises");
65681
66866
  var import_node_path56 = require("path");
65682
66867
  function short(sha) {
@@ -65723,7 +66908,7 @@ async function fastForward(freshness, operationId, deps, signal) {
65723
66908
  async function atFirstLease(freshness, spec, deps, signal) {
65724
66909
  const first = await claimOnce(
65725
66910
  (0, import_node_path56.join)(deps.dir, "leased"),
65726
- (0, import_node_crypto26.createHash)("sha256").update(freshness.path).digest("hex")
66911
+ (0, import_node_crypto27.createHash)("sha256").update(freshness.path).digest("hex")
65727
66912
  );
65728
66913
  switch (freshness.state) {
65729
66914
  case "current":
@@ -66340,7 +67525,7 @@ function createSessionFacts(options) {
66340
67525
  init_acp2();
66341
67526
 
66342
67527
  // src/run-log/complete.ts
66343
- var import_node_crypto27 = require("crypto");
67528
+ var import_node_crypto28 = require("crypto");
66344
67529
  var import_node_fs19 = require("fs");
66345
67530
  var import_node_path60 = require("path");
66346
67531
 
@@ -66349,7 +67534,24 @@ var import_promises61 = require("fs/promises");
66349
67534
  var import_node_path59 = require("path");
66350
67535
  init_runtime_v2();
66351
67536
  init_zod();
66352
- var runMetaSchema = external_exports.object({ runId: runIdSchema, conversationId: conversationIdSchema });
67537
+ var runMetaSchema = external_exports.object({
67538
+ runId: runIdSchema,
67539
+ conversationId: conversationIdSchema,
67540
+ agentMode: external_exports.string().optional(),
67541
+ userMessage: external_exports.object({
67542
+ id: external_exports.string(),
67543
+ content: external_exports.string(),
67544
+ turnOrdinal: external_exports.number().int().nullable(),
67545
+ createdAt: external_exports.string(),
67546
+ clientMessageId: external_exports.string().optional(),
67547
+ attachmentIds: external_exports.array(external_exports.string()).optional()
67548
+ }).optional(),
67549
+ assistantMessage: external_exports.object({
67550
+ id: external_exports.string(),
67551
+ turnOrdinal: external_exports.number().int().nullable(),
67552
+ createdAt: external_exports.string()
67553
+ }).optional()
67554
+ });
66353
67555
  async function readRunMeta(path4) {
66354
67556
  const read = await readJsonFile(path4, runMetaSchema);
66355
67557
  return read.kind === "ok" ? read.value : null;
@@ -66374,7 +67576,7 @@ async function isRunClaimed(runsDir, runId) {
66374
67576
 
66375
67577
  // src/run-log/complete.ts
66376
67578
  function writeLogFile(path4, dir, text2) {
66377
- const temp = (0, import_node_path60.join)(dir, `.log.${(0, import_node_crypto27.randomUUID)()}.tmp`);
67579
+ const temp = (0, import_node_path60.join)(dir, `.log.${(0, import_node_crypto28.randomUUID)()}.tmp`);
66378
67580
  const fd = (0, import_node_fs19.openSync)(temp, "wx", 384);
66379
67581
  try {
66380
67582
  (0, import_node_fs19.writeSync)(fd, text2);
@@ -66402,8 +67604,79 @@ async function writeCompleteRunLog(runsDir, meta3, records) {
66402
67604
  if (await readRunMeta(paths.meta) === null) await writeJsonFileAtomic(paths.meta, meta3);
66403
67605
  }
66404
67606
 
66405
- // src/run-log/reader.ts
67607
+ // src/run-log/conversation-index.ts
66406
67608
  var import_promises62 = require("fs/promises");
67609
+ var import_node_path61 = require("path");
67610
+ init_runtime_v2();
67611
+ init_zod();
67612
+ var ORDINALS_PER_SHARD = 1e3;
67613
+ var indexRecordSchema = external_exports.object({
67614
+ ordinal: external_exports.number().int().nonnegative(),
67615
+ nextOrdinal: external_exports.number().int().positive(),
67616
+ runId: runIdSchema
67617
+ });
67618
+ var coverageSchema = external_exports.object({
67619
+ highestOrdinal: external_exports.number().int().nonnegative(),
67620
+ nextExpectedOrdinal: external_exports.number().int().positive()
67621
+ });
67622
+ function indexDirectory(runsDir, conversationId) {
67623
+ return (0, import_node_path61.join)((0, import_node_path61.dirname)(runsDir), "sessions", conversationId, "turn-index");
67624
+ }
67625
+ function shardPath(runsDir, conversationId, ordinal) {
67626
+ return (0, import_node_path61.join)(
67627
+ indexDirectory(runsDir, conversationId),
67628
+ `${Math.floor(ordinal / ORDINALS_PER_SHARD)}.jsonl`
67629
+ );
67630
+ }
67631
+ async function indexConversationRun(runsDir, conversationId, ordinal, assistantOrdinal, runId) {
67632
+ const nextOrdinal = assistantOrdinal + 1;
67633
+ if (nextOrdinal <= ordinal) throw new Error("Assistant order must follow the prompt");
67634
+ const path4 = shardPath(runsDir, conversationId, ordinal);
67635
+ await (0, import_promises62.mkdir)((0, import_node_path61.dirname)(path4), { recursive: true, mode: 448 });
67636
+ await (0, import_promises62.appendFile)(path4, `${JSON.stringify({ ordinal, nextOrdinal, runId })}
67637
+ `, { mode: 384 });
67638
+ const coveragePath = (0, import_node_path61.join)((0, import_node_path61.dirname)((0, import_node_path61.dirname)(path4)), "coverage.json");
67639
+ const coverage = await readJsonFile(coveragePath, coverageSchema);
67640
+ const current = coverage.kind === "ok" ? coverage.value : null;
67641
+ if (ordinal === 0 && current === null || current?.nextExpectedOrdinal === ordinal)
67642
+ await writeJsonFileAtomic(coveragePath, {
67643
+ highestOrdinal: ordinal,
67644
+ nextExpectedOrdinal: nextOrdinal
67645
+ });
67646
+ }
67647
+ async function readConversationIndexCoverage(runsDir, conversationId) {
67648
+ const path4 = (0, import_node_path61.join)((0, import_node_path61.dirname)(indexDirectory(runsDir, conversationId)), "coverage.json");
67649
+ const result = await readJsonFile(path4, coverageSchema);
67650
+ return result.kind === "ok" ? result.value : null;
67651
+ }
67652
+ async function readConversationRunIndex(runsDir, conversationId, before, limit) {
67653
+ const directory = indexDirectory(runsDir, conversationId);
67654
+ const names = await (0, import_promises62.readdir)(directory).catch((error61) => {
67655
+ if (error61.code === "ENOENT") return [];
67656
+ throw error61;
67657
+ });
67658
+ const shards = names.map((name) => /^\d+\.jsonl$/.test(name) ? Number(name.slice(0, -6)) : NaN).filter((shard) => Number.isSafeInteger(shard)).filter(
67659
+ (shard) => before === void 0 || shard <= Math.floor((before - 1) / ORDINALS_PER_SHARD)
67660
+ ).sort((left, right) => right - left);
67661
+ const selected = [];
67662
+ for (const shard of shards) {
67663
+ const text2 = await (0, import_promises62.readFile)((0, import_node_path61.join)(directory, `${shard}.jsonl`), "utf8");
67664
+ const records = text2.split("\n").flatMap((line) => {
67665
+ if (!line) return [];
67666
+ const parsed = indexRecordSchema.parse(JSON.parse(line));
67667
+ return [parsed];
67668
+ }).filter((record2) => before === void 0 || record2.ordinal < before).reverse().sort((left, right) => right.ordinal - left.ordinal);
67669
+ for (const record2 of records) {
67670
+ if (selected.some((entry) => entry.ordinal === record2.ordinal)) continue;
67671
+ selected.push(record2);
67672
+ if (selected.length >= limit) return selected;
67673
+ }
67674
+ }
67675
+ return selected;
67676
+ }
67677
+
67678
+ // src/run-log/reader.ts
67679
+ var import_promises63 = require("fs/promises");
66407
67680
  init_runtime_v2();
66408
67681
 
66409
67682
  // src/run-log/tail.ts
@@ -66426,7 +67699,7 @@ function firstRecordLength(bytes) {
66426
67699
  return bytes.indexOf(RUN_LOG_RECORD_SEPARATOR) + 1;
66427
67700
  }
66428
67701
  async function openRunLogReader(path4) {
66429
- const handle = await (0, import_promises62.open)(path4, "r");
67702
+ const handle = await (0, import_promises63.open)(path4, "r");
66430
67703
  const readAt = async (position, length) => {
66431
67704
  const buffer = Buffer.alloc(length);
66432
67705
  const { bytesRead } = await handle.read(buffer, 0, length, position);
@@ -66460,7 +67733,7 @@ async function openRunLogReader(path4) {
66460
67733
  };
66461
67734
  }
66462
67735
  async function readLastRecord(path4) {
66463
- const handle = await (0, import_promises62.open)(path4, "r").catch(() => null);
67736
+ const handle = await (0, import_promises63.open)(path4, "r").catch(() => null);
66464
67737
  if (handle === null) return null;
66465
67738
  try {
66466
67739
  const { size } = await handle.stat();
@@ -66494,7 +67767,7 @@ var decoder = new TextDecoder();
66494
67767
 
66495
67768
  // src/run-log/writer.ts
66496
67769
  var import_node_fs20 = require("fs");
66497
- var import_node_path61 = require("path");
67770
+ var import_node_path62 = require("path");
66498
67771
  init_runtime_v2();
66499
67772
  function lastSeq(fd, size) {
66500
67773
  for (const length of tailWindows(size)) {
@@ -66510,7 +67783,7 @@ function lastSeq(fd, size) {
66510
67783
  throw new RuntimeFault("record_too_large", "Run log tail record is larger than any record");
66511
67784
  }
66512
67785
  function openRunLog(path4, clock) {
66513
- (0, import_node_fs20.mkdirSync)((0, import_node_path61.dirname)(path4), { recursive: true, mode: 448 });
67786
+ (0, import_node_fs20.mkdirSync)((0, import_node_path62.dirname)(path4), { recursive: true, mode: 448 });
66514
67787
  const fd = (0, import_node_fs20.openSync)(path4, "a+", 384);
66515
67788
  let size = (0, import_node_fs20.fstatSync)(fd).size;
66516
67789
  let seq = lastSeq(fd, size);
@@ -66742,10 +68015,30 @@ async function admitAndRun(spec, context, append, sink, signal) {
66742
68015
  async function claimRun(spec, context) {
66743
68016
  if (await isRunClaimed(context.runsDir, spec.runId)) return null;
66744
68017
  const paths = runDirectory(context.runsDir, spec.runId);
66745
- await writeJsonFileAtomic(paths.meta, { runId: spec.runId, conversationId: spec.conversationId });
68018
+ await writeJsonFileAtomic(paths.meta, {
68019
+ runId: spec.runId,
68020
+ conversationId: spec.conversationId,
68021
+ ...spec.mode ? { agentMode: spec.mode } : {},
68022
+ ...spec.userMessage ? { userMessage: spec.userMessage } : {},
68023
+ ...spec.assistantMessage ? { assistantMessage: spec.assistantMessage } : {}
68024
+ });
66746
68025
  const log = openRunLog(paths.log, context.clock);
66747
68026
  const offset = log.append(runAccepted(context.machineId, context.clock.now()));
66748
68027
  context.onAppended(spec.runId, offset);
68028
+ if (spec.userMessage?.turnOrdinal !== null && spec.userMessage?.turnOrdinal !== void 0 && spec.assistantMessage?.turnOrdinal !== null && spec.assistantMessage?.turnOrdinal !== void 0) {
68029
+ try {
68030
+ await indexConversationRun(
68031
+ context.runsDir,
68032
+ spec.conversationId,
68033
+ spec.userMessage.turnOrdinal,
68034
+ spec.assistantMessage.turnOrdinal,
68035
+ spec.runId
68036
+ );
68037
+ context.onAppended(spec.runId, offset);
68038
+ } catch (error61) {
68039
+ context.log.warn("holder.conversation_index_failed", { runId: spec.runId, error: error61 });
68040
+ }
68041
+ }
66749
68042
  return log;
66750
68043
  }
66751
68044
  async function runClaimedTurn(spec, claimed, context, signal) {
@@ -66807,12 +68100,12 @@ var TASK_UNSUPPORTED = {
66807
68100
  message: "This agent cannot stop one background task."
66808
68101
  };
66809
68102
  function sha2564(value2) {
66810
- return (0, import_node_crypto28.createHash)("sha256").update(value2).digest("hex");
68103
+ return (0, import_node_crypto29.createHash)("sha256").update(value2).digest("hex");
66811
68104
  }
66812
68105
  function tokenMatches(expected, presented) {
66813
68106
  const a = Buffer.from(sha2564(expected), "hex");
66814
68107
  const b = Buffer.from(sha2564(presented), "hex");
66815
- return (0, import_node_crypto28.timingSafeEqual)(a, b);
68108
+ return (0, import_node_crypto29.timingSafeEqual)(a, b);
66816
68109
  }
66817
68110
  async function runHolder({
66818
68111
  launch,
@@ -66826,7 +68119,7 @@ async function runHolder({
66826
68119
  try {
66827
68120
  const identity = await readProcessIdentity(process.pid);
66828
68121
  if (identity === null) throw new RuntimeFault("internal", "Cannot read own process identity");
66829
- const _engines = __using(_stack, recordSpawnedEngines(engineRecordsPath((0, import_node_path62.dirname)(launch.statusPath)), clock, log));
68122
+ const _engines = __using(_stack, recordSpawnedEngines(engineRecordsPath((0, import_node_path63.dirname)(launch.statusPath)), clock, log));
66830
68123
  const holder = {
66831
68124
  state: "idle",
66832
68125
  runId: null,
@@ -67120,7 +68413,7 @@ var DEFAULT_MAX_ACTIVE_RUNS = 32;
67120
68413
  var HOLDER_BUSY = "busy";
67121
68414
  async function listIds(dir, schema) {
67122
68415
  const ids = [];
67123
- for (const name of await (0, import_promises63.readdir)(dir).catch(() => [])) {
68416
+ for (const name of await (0, import_promises64.readdir)(dir).catch(() => [])) {
67124
68417
  const parsed = schema.safeParse(name);
67125
68418
  if (parsed.success) ids.push(parsed.data);
67126
68419
  }
@@ -67134,8 +68427,8 @@ function holderIdentity(status) {
67134
68427
  return command === void 0 ? { pid, startedAt } : { pid, startedAt, command };
67135
68428
  }
67136
68429
  function sessionFiles(paths, conversationId) {
67137
- const dir = (0, import_node_path63.join)(paths.sessions, conversationId);
67138
- return { dir, launch: (0, import_node_path63.join)(dir, "launch.json"), status: (0, import_node_path63.join)(dir, "holder.json") };
68430
+ const dir = (0, import_node_path64.join)(paths.sessions, conversationId);
68431
+ return { dir, launch: (0, import_node_path64.join)(dir, "launch.json"), status: (0, import_node_path64.join)(dir, "holder.json") };
67139
68432
  }
67140
68433
  async function openSessions(deps) {
67141
68434
  const { paths, clock, log } = deps;
@@ -67176,7 +68469,7 @@ async function openSessions(deps) {
67176
68469
  await reapLeftoverEngines(engineRecordsPath(dir), { clock, log, conversationId }).catch(
67177
68470
  (error61) => log.warn("sessions.engine_reap_failed", { conversationId, error: error61 })
67178
68471
  );
67179
- await (0, import_promises63.rm)(dir, { recursive: true, force: true });
68472
+ await (0, import_promises64.rm)(dir, { recursive: true, force: true });
67180
68473
  };
67181
68474
  const retireIfGone = async (conversationId) => {
67182
68475
  const files = sessionFiles(paths, conversationId);
@@ -67264,7 +68557,7 @@ async function openSessions(deps) {
67264
68557
  log.info("sessions.reattached", { conversationId });
67265
68558
  return;
67266
68559
  }
67267
- if (alive) await (0, import_promises63.rm)(files.dir, { recursive: true, force: true });
68560
+ if (alive) await (0, import_promises64.rm)(files.dir, { recursive: true, force: true });
67268
68561
  else await discardSession(conversationId);
67269
68562
  };
67270
68563
  const busyRunIds = async () => {
@@ -67289,14 +68582,14 @@ async function openSessions(deps) {
67289
68582
  if (!busy.has(runId)) await markInterrupted(runId);
67290
68583
  }
67291
68584
  };
67292
- const spawn11 = async (conversationId) => {
68585
+ const spawn10 = async (conversationId) => {
67293
68586
  const files = sessionFiles(paths, conversationId);
67294
68587
  const launch = {
67295
68588
  protocol: HOLDER_PROTOCOL,
67296
68589
  conversationId,
67297
68590
  machineId: deps.machineId,
67298
- endpoint: ipcEndpoint(paths.sockets, (0, import_node_crypto29.randomUUID)().slice(0, 8)),
67299
- token: (0, import_node_crypto29.randomBytes)(32).toString("hex"),
68591
+ endpoint: ipcEndpoint(paths.sockets, (0, import_node_crypto30.randomUUID)().slice(0, 8)),
68592
+ token: (0, import_node_crypto30.randomBytes)(32).toString("hex"),
67300
68593
  runsDir: paths.runs,
67301
68594
  statusPath: files.status
67302
68595
  };
@@ -67322,7 +68615,7 @@ async function openSessions(deps) {
67322
68615
  const meta3 = await readRunMeta(dir.meta);
67323
68616
  const last = await readLastRecord(dir.log);
67324
68617
  if (meta3 === null || last === null) return null;
67325
- const logged = await (0, import_promises63.stat)(dir.log).catch((error61) => {
68618
+ const logged = await (0, import_promises64.stat)(dir.log).catch((error61) => {
67326
68619
  if (errnoCode(error61) === "ENOENT") return null;
67327
68620
  throw error61;
67328
68621
  });
@@ -67433,7 +68726,7 @@ async function openSessions(deps) {
67433
68726
  return "started";
67434
68727
  }
67435
68728
  if (await activeRunsOtherThan(run2.runId) >= maxActiveRuns) return "waiting";
67436
- if (!connections.has(run2.conversationId)) await spawn11(run2.conversationId);
68729
+ if (!connections.has(run2.conversationId)) await spawn10(run2.conversationId);
67437
68730
  const connection = connections.get(run2.conversationId);
67438
68731
  if (connection === void 0) {
67439
68732
  throw new RuntimeFault("internal", "Holder connection missing");
@@ -67632,7 +68925,7 @@ function loadRuntimeConfig(env = process.env, totalMemoryBytes = (0, import_node
67632
68925
  providerProbes: ALAN_RUNTIME_PROVIDER_PROBES === "on",
67633
68926
  providerToolchain: ALAN_RUNTIME_PROVIDER_NODE !== void 0 && ALAN_RUNTIME_PROVIDER_NPM_CLI !== void 0 ? { node: ALAN_RUNTIME_PROVIDER_NODE, npmCli: ALAN_RUNTIME_PROVIDER_NPM_CLI } : null,
67634
68927
  home,
67635
- configHome: XDG_CONFIG_HOME ?? (0, import_node_path64.join)(home, ".config"),
68928
+ configHome: XDG_CONFIG_HOME ?? (0, import_node_path65.join)(home, ".config"),
67636
68929
  ...githubProxyConfig({ ALAN_RUNTIME_GITHUB_PROXY, XDG_CONFIG_HOME, GH_CONFIG_DIR }, home),
67637
68930
  gitGatewayUrl: ALAN_RUNTIME_GIT_GATEWAY_URL ?? null,
67638
68931
  workspaceRoot: ALAN_RUNTIME_WORKSPACE_ROOT ?? null,
@@ -67641,10 +68934,10 @@ function loadRuntimeConfig(env = process.env, totalMemoryBytes = (0, import_node
67641
68934
  };
67642
68935
  }
67643
68936
  function githubProxyConfig(env, home) {
67644
- const configHome = env.XDG_CONFIG_HOME ?? (0, import_node_path64.join)(home, ".config");
68937
+ const configHome = env.XDG_CONFIG_HOME ?? (0, import_node_path65.join)(home, ".config");
67645
68938
  return {
67646
68939
  githubProxy: env.ALAN_RUNTIME_GITHUB_PROXY === "on",
67647
- ghConfigDir: env.GH_CONFIG_DIR ?? (0, import_node_path64.join)(configHome, "gh")
68940
+ ghConfigDir: env.GH_CONFIG_DIR ?? (0, import_node_path65.join)(configHome, "gh")
67648
68941
  };
67649
68942
  }
67650
68943
  function serviceEnvironment2(env, profile) {
@@ -67702,9 +68995,9 @@ function takeEnrollmentCodeFromEnv(env = process.env) {
67702
68995
  }
67703
68996
 
67704
68997
  // src/cli/context.ts
67705
- var import_promises64 = require("fs/promises");
68998
+ var import_promises65 = require("fs/promises");
67706
68999
  var import_node_os12 = require("os");
67707
- var import_node_path65 = require("path");
69000
+ var import_node_path66 = require("path");
67708
69001
  var DESKTOP_BUNDLE_IDS = {
67709
69002
  production: ["com.alan-ai.desktop"],
67710
69003
  staging: ["com.alan-ai.desktop.staging"],
@@ -67744,7 +69037,7 @@ function serviceSpec({ config: config2, paths, self }) {
67744
69037
  profile: config2.profile,
67745
69038
  program: serviceCommand(config2.host, self, launcher),
67746
69039
  environment: config2.serviceEnvironment,
67747
- logPath: (0, import_node_path65.join)(paths.logs, "service.log"),
69040
+ logPath: (0, import_node_path66.join)(paths.logs, "service.log"),
67748
69041
  associatedBundleIds: DESKTOP_BUNDLE_IDS[config2.profile]
67749
69042
  };
67750
69043
  }
@@ -67752,7 +69045,7 @@ async function installedServiceSpec(ctx) {
67752
69045
  const spec = serviceSpec(ctx);
67753
69046
  if (ctx.config.host === "app") return spec;
67754
69047
  const layout = installLayout(ctx.config.installDir, ctx.config.profile);
67755
- const installed = await (0, import_promises64.access)(layout.launcher).then(
69048
+ const installed = await (0, import_promises65.access)(layout.launcher).then(
67756
69049
  () => true,
67757
69050
  () => false
67758
69051
  );
@@ -67880,7 +69173,7 @@ var manifestRevisionSchema = external_exports.object({ revision: external_export
67880
69173
  async function manifestRevision(path4) {
67881
69174
  let raw;
67882
69175
  try {
67883
- raw = JSON.parse(await (0, import_promises65.readFile)(path4, "utf8"));
69176
+ raw = JSON.parse(await (0, import_promises66.readFile)(path4, "utf8"));
67884
69177
  } catch (error61) {
67885
69178
  throw new RuntimeFault("invalid_file", `Cannot read the skill manifest at ${path4}`, {
67886
69179
  cause: error61
@@ -67898,7 +69191,7 @@ async function runSkills(argv) {
67898
69191
  case "scan":
67899
69192
  writeJson({
67900
69193
  status: "failed",
67901
- attemptId: (0, import_node_crypto30.randomUUID)(),
69194
+ attemptId: (0, import_node_crypto31.randomUUID)(),
67902
69195
  retainedInventoryRevision: null,
67903
69196
  diagnostics: [
67904
69197
  { code: "RUNTIME_SKILL_SCAN_UNSUPPORTED", message: SKILLS_SYNCED_BY_RUNTIME }
@@ -67914,7 +69207,7 @@ async function runSkills(argv) {
67914
69207
  );
67915
69208
  }
67916
69209
  writeJson({
67917
- attemptId: (0, import_node_crypto30.randomUUID)(),
69210
+ attemptId: (0, import_node_crypto31.randomUUID)(),
67918
69211
  desiredRevision: await manifestRevision(manifest),
67919
69212
  skills: []
67920
69213
  });
@@ -67934,8 +69227,8 @@ async function runSkills(argv) {
67934
69227
  }
67935
69228
 
67936
69229
  // src/cli/commands/doctor.ts
67937
- var import_promises68 = require("fs/promises");
67938
- var import_node_path69 = require("path");
69230
+ var import_promises69 = require("fs/promises");
69231
+ var import_node_path70 = require("path");
67939
69232
  init_runtime_v2();
67940
69233
 
67941
69234
  // src/identity/credential.ts
@@ -68112,24 +69405,24 @@ async function authorizeDevice(input2) {
68112
69405
  }
68113
69406
 
68114
69407
  // src/identity/enroll.ts
68115
- var import_promises66 = require("fs/promises");
69408
+ var import_promises67 = require("fs/promises");
68116
69409
  init_runtime_v2();
68117
69410
 
68118
69411
  // src/identity/installation.ts
68119
- var import_node_crypto31 = require("crypto");
68120
- var import_node_path66 = require("path");
69412
+ var import_node_crypto32 = require("crypto");
69413
+ var import_node_path67 = require("path");
68121
69414
  init_zod();
68122
69415
  var installationFileSchema = external_exports.object({
68123
69416
  installationId: external_exports.uuid()
68124
69417
  });
68125
69418
  function installationPath(paths) {
68126
- return (0, import_node_path66.join)(paths.stateDir, "installation.json");
69419
+ return (0, import_node_path67.join)(paths.stateDir, "installation.json");
68127
69420
  }
68128
69421
  async function ensureInstallationId(paths) {
68129
69422
  const path4 = installationPath(paths);
68130
69423
  const existing = await readJsonFile(path4, installationFileSchema);
68131
69424
  if (existing.kind === "ok") return existing.value.installationId;
68132
- const created = { installationId: (0, import_node_crypto31.randomUUID)() };
69425
+ const created = { installationId: (0, import_node_crypto32.randomUUID)() };
68133
69426
  await writeJsonFileAtomic(path4, created);
68134
69427
  return created.installationId;
68135
69428
  }
@@ -68216,13 +69509,13 @@ async function enrollFromGrantFile(input2) {
68216
69509
  clock: input2.clock,
68217
69510
  access: input2.access
68218
69511
  });
68219
- await (0, import_promises66.rm)(input2.grantPath, { force: true });
69512
+ await (0, import_promises67.rm)(input2.grantPath, { force: true });
68220
69513
  return machine;
68221
69514
  }
68222
69515
 
68223
69516
  // src/identity/migrate-v1.ts
68224
- var import_promises67 = require("fs/promises");
68225
- var import_node_path67 = require("path");
69517
+ var import_promises68 = require("fs/promises");
69518
+ var import_node_path68 = require("path");
68226
69519
  init_runtime_v2();
68227
69520
  init_zod();
68228
69521
  var EXIT_POLL_MS = 200;
@@ -68243,11 +69536,11 @@ var ownerLeaseSchema = external_exports.looseObject({ pid: external_exports.numb
68243
69536
  function legacyConfigPath(home, profile) {
68244
69537
  switch (profile) {
68245
69538
  case "production":
68246
- return (0, import_node_path67.join)(home, ".alan", "agent", "config.json");
69539
+ return (0, import_node_path68.join)(home, ".alan", "agent", "config.json");
68247
69540
  case "staging":
68248
- return (0, import_node_path67.join)(home, ".alan-staging", "agent", "config.json");
69541
+ return (0, import_node_path68.join)(home, ".alan-staging", "agent", "config.json");
68249
69542
  default:
68250
- return (0, import_node_path67.join)(home, ".alan-dev", "agent", "config.json");
69543
+ return (0, import_node_path68.join)(home, ".alan-dev", "agent", "config.json");
68251
69544
  }
68252
69545
  }
68253
69546
  async function findLegacyInstall(home, profile) {
@@ -68272,8 +69565,8 @@ async function scrubLegacyInstall(install2) {
68272
69565
  const scrubbed = { ...install2.config, migratedToRuntimeV2: true };
68273
69566
  for (const key of SCRUBBED_KEYS) delete scrubbed[key];
68274
69567
  await writeJsonFileAtomic(`${install2.configPath}.migrated-v1`, scrubbed);
68275
- await (0, import_promises67.rm)(install2.configPath, { force: true });
68276
- await (0, import_promises67.rm)(install2.ownerLeasePath, { force: true });
69568
+ await (0, import_promises68.rm)(install2.configPath, { force: true });
69569
+ await (0, import_promises68.rm)(install2.ownerLeasePath, { force: true });
68277
69570
  }
68278
69571
  async function exchangeCredential(deps) {
68279
69572
  const { config: config2 } = deps.install;
@@ -68382,7 +69675,7 @@ async function loadIdentity(paths, options = {}) {
68382
69675
  }
68383
69676
 
68384
69677
  // src/cli/commands/status.ts
68385
- var import_node_path68 = require("path");
69678
+ var import_node_path69 = require("path");
68386
69679
  async function serviceStatus(ctx) {
68387
69680
  try {
68388
69681
  return await createServiceManager(ctx.host, ctx.config.profile).status();
@@ -68409,7 +69702,7 @@ async function runtimeState(ctx) {
68409
69702
  const running = await readRunningRuntime(ctx.paths.lock);
68410
69703
  if (running === null) return { state: "offline", pid: null, localApi: null };
68411
69704
  const discovery = await readJsonFile(
68412
- (0, import_node_path68.join)(ctx.paths.stateDir, LOCAL_API_DISCOVERY_FILE),
69705
+ (0, import_node_path69.join)(ctx.paths.stateDir, LOCAL_API_DISCOVERY_FILE),
68413
69706
  localApiDiscoverySchema
68414
69707
  );
68415
69708
  const localApi = discovery.kind === "ok" && discovery.value.pid === running.pid ? {
@@ -68630,7 +69923,7 @@ async function runtimeCheck(ctx, status) {
68630
69923
  return check2("runtime", "warn", "No runtime is running for this profile");
68631
69924
  }
68632
69925
  const client = createRuntimeClient({
68633
- discoveryPath: (0, import_node_path69.join)(ctx.paths.stateDir, LOCAL_API_DISCOVERY_FILE)
69926
+ discoveryPath: (0, import_node_path70.join)(ctx.paths.stateDir, LOCAL_API_DISCOVERY_FILE)
68634
69927
  });
68635
69928
  try {
68636
69929
  const live = await client.status(AbortSignal.timeout(LOCAL_TIMEOUT_MS));
@@ -68657,7 +69950,7 @@ async function runtimeCheck(ctx, status) {
68657
69950
  }
68658
69951
  }
68659
69952
  async function probeHolder(dir, conversationId) {
68660
- const launch = await readJsonFile((0, import_node_path69.join)(dir, "launch.json"), holderLaunchSchema);
69953
+ const launch = await readJsonFile((0, import_node_path70.join)(dir, "launch.json"), holderLaunchSchema);
68661
69954
  if (launch.kind !== "ok") return null;
68662
69955
  try {
68663
69956
  const reply2 = await withTimeout(
@@ -68682,8 +69975,8 @@ async function probeHolder(dir, conversationId) {
68682
69975
  }
68683
69976
  }
68684
69977
  async function holdersCheck(ctx) {
68685
- const names = await (0, import_promises68.readdir)(ctx.paths.sessions).catch(() => []);
68686
- const holders = (await Promise.all(names.map((name) => probeHolder((0, import_node_path69.join)(ctx.paths.sessions, name), name)))).filter((facts) => facts !== null);
69978
+ const names = await (0, import_promises69.readdir)(ctx.paths.sessions).catch(() => []);
69979
+ const holders = (await Promise.all(names.map((name) => probeHolder((0, import_node_path70.join)(ctx.paths.sessions, name), name)))).filter((facts) => facts !== null);
68687
69980
  const dead = holders.filter((holder) => !holder.alive).length;
68688
69981
  return check2(
68689
69982
  "holders",
@@ -68694,10 +69987,10 @@ async function holdersCheck(ctx) {
68694
69987
  }
68695
69988
  async function freeBytesAt(path4) {
68696
69989
  try {
68697
- const stats = await (0, import_promises68.statfs)(path4);
69990
+ const stats = await (0, import_promises69.statfs)(path4);
68698
69991
  return { path: path4, freeBytes: stats.bavail * stats.bsize };
68699
69992
  } catch (error61) {
68700
- const parent = (0, import_node_path69.dirname)(path4);
69993
+ const parent = (0, import_node_path70.dirname)(path4);
68701
69994
  if (parent === path4) throw error61;
68702
69995
  return freeBytesAt(parent);
68703
69996
  }
@@ -68833,7 +70126,7 @@ async function runDoctor(argv, context = cliContext) {
68833
70126
  }
68834
70127
 
68835
70128
  // src/cli/commands/git-credential.ts
68836
- var import_promises69 = require("fs/promises");
70129
+ var import_promises70 = require("fs/promises");
68837
70130
  var import_node_net4 = require("net");
68838
70131
  var MAX_RESPONSE_BYTES = 64 * 1024;
68839
70132
  async function readAll(stream) {
@@ -68943,7 +70236,7 @@ async function configure(argv) {
68943
70236
  }
68944
70237
  async function configureGitGateway(config2, gatewayUrl, signal) {
68945
70238
  const { launcher } = installLayout(config2.installDir, config2.profile);
68946
- const installed = await (0, import_promises69.access)(launcher).then(
70239
+ const installed = await (0, import_promises70.access)(launcher).then(
68947
70240
  () => true,
68948
70241
  () => false
68949
70242
  );
@@ -68970,7 +70263,7 @@ async function runGitCredential(argv) {
68970
70263
  }
68971
70264
 
68972
70265
  // src/cli/commands/hold.ts
68973
- var import_node_path70 = require("path");
70266
+ var import_node_path71 = require("path");
68974
70267
  init_agent2();
68975
70268
  init_runtime_v2();
68976
70269
  async function machineAccess(paths, log, conversationId, transport) {
@@ -69028,7 +70321,7 @@ async function runHold(argv) {
69028
70321
  const config2 = loadRuntimeConfig();
69029
70322
  const paths = runtimePaths(config2.stateDir);
69030
70323
  const log = __using(_stack, openFileLog(
69031
- (0, import_node_path70.join)(paths.logs, `holder-${launch.value.conversationId}.jsonl`),
70324
+ (0, import_node_path71.join)(paths.logs, `holder-${launch.value.conversationId}.jsonl`),
69032
70325
  config2.logLevel,
69033
70326
  systemClock
69034
70327
  ));
@@ -69039,7 +70332,7 @@ async function runHold(argv) {
69039
70332
  );
69040
70333
  const transport = __using(_stack, createHttpTransport());
69041
70334
  const access7 = await machineAccess(paths, log, launch.value.conversationId, transport);
69042
- const credentialPath = (0, import_node_path70.join)(paths.tmp, "mcp", `${launch.value.conversationId}.json`);
70335
+ const credentialPath = (0, import_node_path71.join)(paths.tmp, "mcp", `${launch.value.conversationId}.json`);
69043
70336
  const managedMcp = __using(_stack, access7.managedMcp === void 0 ? void 0 : createHelperMcpAccess({
69044
70337
  managedMcp: access7.managedMcp,
69045
70338
  conversationId: launch.value.conversationId,
@@ -69079,7 +70372,7 @@ async function runHold(argv) {
69079
70372
  }
69080
70373
 
69081
70374
  // src/cli/commands/hook.ts
69082
- var import_node_path71 = require("path");
70375
+ var import_node_path72 = require("path");
69083
70376
  var RUNTIME_ANSWER_MS = 2e3;
69084
70377
  var DEBUG_VARIABLE = "ALAN_HOOK_DEBUG";
69085
70378
  function flag(argv, name) {
@@ -69111,7 +70404,7 @@ async function forwardHook(argv, io) {
69111
70404
  return "transcript outside provider root";
69112
70405
  }
69113
70406
  const verdict = await io.send(
69114
- (0, import_node_path71.join)(io.stateDir, LOCAL_API_DISCOVERY_FILE),
70407
+ (0, import_node_path72.join)(io.stateDir, LOCAL_API_DISCOVERY_FILE),
69115
70408
  hookSignal,
69116
70409
  AbortSignal.timeout(RUNTIME_ANSWER_MS)
69117
70410
  );
@@ -69147,7 +70440,7 @@ async function runHook(argv, overrides = {}) {
69147
70440
  }
69148
70441
 
69149
70442
  // src/cli/commands/ingestion-hooks.ts
69150
- var import_promises70 = require("fs/promises");
70443
+ var import_promises71 = require("fs/promises");
69151
70444
  var CODEX_TRUST_NOTE = "Codex runs new hooks only after you review them: open /hooks in Codex.";
69152
70445
  function isAction(value2) {
69153
70446
  return value2 === "enable" || value2 === "disable" || value2 === "status";
@@ -69170,7 +70463,7 @@ function errorMessage2(error61) {
69170
70463
  return error61 instanceof Error ? error61.message : String(error61);
69171
70464
  }
69172
70465
  async function exists5(path4) {
69173
- return (0, import_promises70.access)(path4).then(
70466
+ return (0, import_promises71.access)(path4).then(
69174
70467
  () => true,
69175
70468
  () => false
69176
70469
  );
@@ -69273,10 +70566,10 @@ async function runIntegrationsCommand(argv) {
69273
70566
  }
69274
70567
 
69275
70568
  // src/cli/commands/legacy.ts
69276
- var import_node_path73 = require("path");
70569
+ var import_node_path74 = require("path");
69277
70570
 
69278
70571
  // src/cli/commands/setup.ts
69279
- var import_node_path72 = require("path");
70572
+ var import_node_path73 = require("path");
69280
70573
  init_zod();
69281
70574
 
69282
70575
  // src/cli/legacy.ts
@@ -69358,7 +70651,7 @@ async function grantFileCredential(argv, grantPath, ctx, deps) {
69358
70651
  return enrollFromGrantFile({
69359
70652
  paths: ctx.paths,
69360
70653
  storeKind: credentialStoreFlag(argv) ?? ctx.config.credentialStore,
69361
- grantPath: (0, import_node_path72.resolve)(grantPath),
70654
+ grantPath: (0, import_node_path73.resolve)(grantPath),
69362
70655
  clock: deps.clock,
69363
70656
  access: ctx.access
69364
70657
  });
@@ -69434,7 +70727,7 @@ async function runSetup(argv, signal) {
69434
70727
  var _stack = [];
69435
70728
  try {
69436
70729
  const ctx = cliContext();
69437
- const log = __using(_stack, openFileLog((0, import_node_path72.join)(ctx.paths.logs, "cli.jsonl"), ctx.config.logLevel, systemClock));
70730
+ const log = __using(_stack, openFileLog((0, import_node_path73.join)(ctx.paths.logs, "cli.jsonl"), ctx.config.logLevel, systemClock));
69438
70731
  const result = await setupMachine(argv, ctx, {
69439
70732
  enrollment: (apiUrl) => createEnrollmentClient({ apiUrl }),
69440
70733
  isProcessAlive,
@@ -69517,7 +70810,7 @@ async function runToken(argv, signal) {
69517
70810
  );
69518
70811
  }
69519
70812
  const ctx = cliContext();
69520
- const log = __using(_stack, openFileLog((0, import_node_path73.join)(ctx.paths.logs, "cli.jsonl"), ctx.config.logLevel, systemClock));
70813
+ const log = __using(_stack, openFileLog((0, import_node_path74.join)(ctx.paths.logs, "cli.jsonl"), ctx.config.logLevel, systemClock));
69521
70814
  const result = await rotateMachineCredential(ctx, { clock: systemClock, log, signal });
69522
70815
  process.stdout.write(`${rotationMessage(result)}
69523
70816
  `);
@@ -69529,8 +70822,8 @@ async function runToken(argv, signal) {
69529
70822
  }
69530
70823
 
69531
70824
  // src/cli/commands/logout.ts
69532
- var import_promises71 = require("fs/promises");
69533
- var import_node_path74 = require("path");
70825
+ var import_promises72 = require("fs/promises");
70826
+ var import_node_path75 = require("path");
69534
70827
  init_runtime_v2();
69535
70828
  var RUNTIME_EXIT_WAIT_MS = 35e3;
69536
70829
  var TURN_END_WAIT_MS = 3e4;
@@ -69589,9 +70882,9 @@ async function stopHolder(launch, deps, outcome2) {
69589
70882
  }
69590
70883
  async function stopHeldRuns(ctx, deps, outcome2 = "aborted") {
69591
70884
  const stopped = [];
69592
- for (const name of await (0, import_promises71.readdir)(ctx.paths.sessions).catch(() => [])) {
70885
+ for (const name of await (0, import_promises72.readdir)(ctx.paths.sessions).catch(() => [])) {
69593
70886
  const launch = await readJsonFile(
69594
- (0, import_node_path74.join)(ctx.paths.sessions, name, "launch.json"),
70887
+ (0, import_node_path75.join)(ctx.paths.sessions, name, "launch.json"),
69595
70888
  holderLaunchSchema
69596
70889
  );
69597
70890
  if (launch.kind !== "ok") continue;
@@ -69628,13 +70921,13 @@ async function forgetMachineLocally(ctx) {
69628
70921
  const machine = await readMachineFile(ctx.paths);
69629
70922
  if (machine === null) return;
69630
70923
  await credentialStoreFor(ctx.paths, machine.credentialStore, ctx.access).clear();
69631
- await (0, import_promises71.rm)(ctx.paths.machine, { force: true });
70924
+ await (0, import_promises72.rm)(ctx.paths.machine, { force: true });
69632
70925
  }
69633
70926
  async function runLogout(argv, signal) {
69634
70927
  var _stack = [];
69635
70928
  try {
69636
70929
  const ctx = cliContext();
69637
- const log = __using(_stack, openFileLog((0, import_node_path74.join)(ctx.paths.logs, "cli.jsonl"), ctx.config.logLevel, systemClock));
70930
+ const log = __using(_stack, openFileLog((0, import_node_path75.join)(ctx.paths.logs, "cli.jsonl"), ctx.config.logLevel, systemClock));
69638
70931
  const result = await logoutMachine(argv, ctx, {
69639
70932
  api: (apiUrl, accessToken) => createApiClient({ apiUrl, accessToken }),
69640
70933
  stopHeldRuns,
@@ -69651,7 +70944,8 @@ async function runLogout(argv, signal) {
69651
70944
  }
69652
70945
 
69653
70946
  // src/cli/commands/run.ts
69654
- var import_node_path78 = require("path");
70947
+ var import_node_fs23 = require("fs");
70948
+ var import_node_path79 = require("path");
69655
70949
 
69656
70950
  // src/local-api/app-attachments.ts
69657
70951
  function createAppAttachments(clock) {
@@ -69685,7 +70979,9 @@ function createAppAttachments(clock) {
69685
70979
  // src/local-api/run-appends.ts
69686
70980
  function createRunAppends() {
69687
70981
  const waiters = /* @__PURE__ */ new Map();
70982
+ const listeners = /* @__PURE__ */ new Set();
69688
70983
  const wake = (runId) => {
70984
+ for (const listener of listeners) listener(runId);
69689
70985
  const pending = waiters.get(runId);
69690
70986
  if (pending === void 0) return;
69691
70987
  waiters.delete(runId);
@@ -69693,8 +70989,17 @@ function createRunAppends() {
69693
70989
  };
69694
70990
  return {
69695
70991
  notify: wake,
70992
+ subscribe: (listener) => {
70993
+ listeners.add(listener);
70994
+ return {
70995
+ [Symbol.dispose]: () => {
70996
+ listeners.delete(listener);
70997
+ }
70998
+ };
70999
+ },
69696
71000
  notifyAll: () => {
69697
71001
  for (const runId of [...waiters.keys()]) wake(runId);
71002
+ for (const listener of listeners) listener(null);
69698
71003
  },
69699
71004
  nextAppend: (runId, signal) => {
69700
71005
  if (signal.aborted) return Promise.resolve();
@@ -69716,18 +71021,18 @@ function createRunAppends() {
69716
71021
  }
69717
71022
 
69718
71023
  // src/local-api/server.ts
69719
- var import_node_crypto33 = require("crypto");
69720
- var import_promises72 = require("fs/promises");
71024
+ var import_node_crypto34 = require("crypto");
71025
+ var import_promises73 = require("fs/promises");
69721
71026
  var import_node_http4 = require("http");
69722
- var import_node_path75 = require("path");
71027
+ var import_node_path76 = require("path");
69723
71028
 
69724
71029
  // src/local-api/guard.ts
69725
- var import_node_crypto32 = require("crypto");
71030
+ var import_node_crypto33 = require("crypto");
69726
71031
  var ALLOWED = { kind: "allowed" };
69727
71032
  function tokenMatches2(expected, header) {
69728
71033
  if (header === void 0 || !header.startsWith("Bearer ")) return false;
69729
71034
  const presented = Buffer.from(header.slice("Bearer ".length));
69730
- return presented.length === expected.length && (0, import_node_crypto32.timingSafeEqual)(presented, expected);
71035
+ return presented.length === expected.length && (0, import_node_crypto33.timingSafeEqual)(presented, expected);
69731
71036
  }
69732
71037
  function isBrowserReachable(req, allowedHosts) {
69733
71038
  if (req.headers.origin !== void 0 || req.headers.referer !== void 0) return true;
@@ -69835,6 +71140,249 @@ function requestSignal(res) {
69835
71140
  init_runtime_v2();
69836
71141
  init_zod();
69837
71142
 
71143
+ // src/local-api/conversation-messages.ts
71144
+ init_acp();
71145
+ init_runtime_v2();
71146
+ function applyLogLine(line, assistantMessageId, state) {
71147
+ const raw = JSON.parse(line);
71148
+ const record2 = runLogRecordSchema.safeParse(raw);
71149
+ if (!record2.success) return null;
71150
+ const kind = record2.data.update.sessionUpdate;
71151
+ if (isRunLifecycleKind(kind)) {
71152
+ const lifecycle = runLifecycleUpdateSchema.parse(record2.data.update);
71153
+ if (lifecycle.sessionUpdate === "_alan/run.accepted") {
71154
+ state.state = "running";
71155
+ return false;
71156
+ }
71157
+ const ended = lifecycle.sessionUpdate === "_alan/run.ended";
71158
+ applySessionEvent(state, {
71159
+ seq: record2.data.seq,
71160
+ at: record2.data.at,
71161
+ update: {
71162
+ sessionUpdate: "state_update",
71163
+ state: ended ? "idle" : "running",
71164
+ ...ended && {
71165
+ stopReason: lifecycle.outcome === "aborted" || lifecycle.outcome === "interrupted" ? "cancelled" : "end_turn"
71166
+ }
71167
+ }
71168
+ });
71169
+ return ended;
71170
+ }
71171
+ const event = scopeTranscriptEvent({ ...record2.data, turnId: assistantMessageId });
71172
+ if (!event) return null;
71173
+ applySessionEvent(state, event);
71174
+ return false;
71175
+ }
71176
+ function applyLogChunk(text2, assistantMessageId, state) {
71177
+ let ended = false;
71178
+ for (const line of text2.trimEnd().split("\n")) {
71179
+ const applied = applyLogLine(line, assistantMessageId, state);
71180
+ if (applied === null) throw new Error("Invalid local transcript record");
71181
+ if (applied) ended = true;
71182
+ }
71183
+ return ended;
71184
+ }
71185
+ async function openLocalTurnProjection(runsDir, runId, conversationId, ordinal) {
71186
+ const paths = runDirectory(runsDir, runId);
71187
+ const meta3 = await readRunMeta(paths.meta);
71188
+ if (!meta3?.userMessage || !meta3.assistantMessage || meta3.conversationId !== conversationId || meta3.userMessage.turnOrdinal !== ordinal)
71189
+ return null;
71190
+ const assistantMessageId = meta3.assistantMessage.id;
71191
+ const state = emptyTranscript();
71192
+ const promptAt = Date.parse(meta3.userMessage.createdAt);
71193
+ applySessionEvent(state, {
71194
+ seq: 0,
71195
+ at: Number.isFinite(promptAt) ? promptAt : 0,
71196
+ update: {
71197
+ sessionUpdate: "user_message",
71198
+ messageId: meta3.userMessage.id,
71199
+ content: [{ type: "text", text: meta3.userMessage.content }],
71200
+ _meta: {
71201
+ ...meta3.userMessage.clientMessageId ? { "alan.dev/clientMessageId": meta3.userMessage.clientMessageId } : {},
71202
+ ...meta3.agentMode ? { "alan.dev/agentMode": meta3.agentMode } : {},
71203
+ ...meta3.userMessage.attachmentIds?.length ? { "alan.dev/attachmentIds": meta3.userMessage.attachmentIds } : {}
71204
+ }
71205
+ }
71206
+ });
71207
+ const reader = await openRunLogReader(paths.log).catch((error61) => {
71208
+ if (error61.code === "ENOENT") return null;
71209
+ throw error61;
71210
+ });
71211
+ if (!reader) return null;
71212
+ let offset = toByteOffset(0);
71213
+ let ended = false;
71214
+ let prepared;
71215
+ const decoder3 = new TextDecoder();
71216
+ return {
71217
+ runId,
71218
+ ordinal,
71219
+ read: async () => {
71220
+ const priorOffset = offset;
71221
+ for (; ; ) {
71222
+ const chunk = await reader.readFrom(offset, DEFAULT_RUN_LOG_LIMIT);
71223
+ if (chunk.bytes.length === 0) break;
71224
+ if (applyLogChunk(decoder3.decode(chunk.bytes), assistantMessageId, state)) ended = true;
71225
+ offset = chunk.to;
71226
+ }
71227
+ if (offset === priorOffset && prepared) return prepared;
71228
+ if (ended) state.state = "idle";
71229
+ prepared = { ...conversationTurnView(ordinal, snapshotTranscriptState(state)), markdown: "" };
71230
+ return prepared;
71231
+ },
71232
+ [Symbol.asyncDispose]: async () => {
71233
+ await reader[Symbol.asyncDispose]();
71234
+ }
71235
+ };
71236
+ }
71237
+ async function projectLocalRun(runsDir, runId, conversationId, ordinal) {
71238
+ var _stack = [];
71239
+ try {
71240
+ const projection = __using(_stack, await openLocalTurnProjection(runsDir, runId, conversationId, ordinal), true);
71241
+ return projection ? await projection.read() : null;
71242
+ } catch (_) {
71243
+ var _error = _, _hasError = true;
71244
+ } finally {
71245
+ var _promise2 = __callDispose(_stack, _error, _hasError);
71246
+ _promise2 && await _promise2;
71247
+ }
71248
+ }
71249
+ async function readLocalConversationMessages(runsDir, conversationId, limit, before, projection) {
71250
+ const indexed = await readConversationRunIndex(runsDir, conversationId, before, limit + 1);
71251
+ const coverage = await readConversationIndexCoverage(runsDir, conversationId);
71252
+ if (coverage === null || before === void 0 && indexed[0]?.ordinal !== coverage.highestOrdinal)
71253
+ return null;
71254
+ if (before !== void 0 && indexed[0]?.nextOrdinal !== before) return null;
71255
+ if (indexed.some((entry, index) => index > 0 && entry.nextOrdinal !== indexed[index - 1].ordinal))
71256
+ return null;
71257
+ if (indexed.length < limit && indexed.at(-1)?.ordinal !== 0) return null;
71258
+ const selected = indexed.slice(0, limit);
71259
+ if (selected.length === 0) return null;
71260
+ const turns = await Promise.all(
71261
+ selected.map(
71262
+ (entry) => entry.runId === projection?.runId ? projection.read() : projectLocalRun(runsDir, entry.runId, conversationId, entry.ordinal)
71263
+ )
71264
+ );
71265
+ if (turns.some((turn) => turn === null)) return null;
71266
+ const completeTurns = turns.filter((turn) => turn !== null);
71267
+ return {
71268
+ turns: compactConversationMessageTurns(completeTurns, before === void 0),
71269
+ before: selected.at(-1)?.ordinal === 0 ? null : String(selected.at(-1)?.ordinal),
71270
+ revision: `local-${selected[0].runId}`,
71271
+ streamCursor: ""
71272
+ };
71273
+ }
71274
+
71275
+ // src/local-api/conversation-messages-stream.ts
71276
+ async function readChangedTurn(deps, conversationId, runId, slot) {
71277
+ const meta3 = await readRunMeta(runDirectory(deps.runsDir, runId).meta);
71278
+ if (meta3?.conversationId !== conversationId || meta3.userMessage?.turnOrdinal == null) return null;
71279
+ if (slot.current?.ordinal === meta3.userMessage.turnOrdinal && slot.current.runId !== runId) {
71280
+ const [latest] = await readConversationRunIndex(
71281
+ deps.runsDir,
71282
+ conversationId,
71283
+ meta3.userMessage.turnOrdinal + 1,
71284
+ 1
71285
+ );
71286
+ if (latest?.runId !== runId) return null;
71287
+ }
71288
+ if (slot.current && meta3.userMessage.turnOrdinal < slot.current.ordinal) {
71289
+ var _stack = [];
71290
+ try {
71291
+ const previous = __using(_stack, await openLocalTurnProjection(
71292
+ deps.runsDir,
71293
+ runId,
71294
+ conversationId,
71295
+ meta3.userMessage.turnOrdinal
71296
+ ), true);
71297
+ return previous ? await previous.read() : null;
71298
+ } catch (_) {
71299
+ var _error = _, _hasError = true;
71300
+ } finally {
71301
+ var _promise2 = __callDispose(_stack, _error, _hasError);
71302
+ _promise2 && await _promise2;
71303
+ }
71304
+ }
71305
+ if (slot.current?.runId !== runId) {
71306
+ const next = await openLocalTurnProjection(
71307
+ deps.runsDir,
71308
+ runId,
71309
+ conversationId,
71310
+ meta3.userMessage.turnOrdinal
71311
+ );
71312
+ await slot.current?.[Symbol.asyncDispose]();
71313
+ slot.current = next;
71314
+ }
71315
+ if (!slot.current) throw new Error("Local transcript metadata is incomplete");
71316
+ return slot.current.read();
71317
+ }
71318
+ async function streamLocalConversationMessages(deps, conversationId, limit, res, signal) {
71319
+ var _stack = [];
71320
+ try {
71321
+ const pending = /* @__PURE__ */ new Set();
71322
+ let wake;
71323
+ const slot = { current: null };
71324
+ const _subscription = __using(_stack, deps.appends.subscribe((runId) => {
71325
+ const changed = runId ?? slot.current?.runId;
71326
+ if (changed) pending.add(changed);
71327
+ wake?.();
71328
+ }));
71329
+ signal.addEventListener("abort", () => wake?.(), { once: true });
71330
+ try {
71331
+ const [newest] = await readConversationRunIndex(deps.runsDir, conversationId, void 0, 1);
71332
+ if (newest)
71333
+ slot.current = await openLocalTurnProjection(
71334
+ deps.runsDir,
71335
+ newest.runId,
71336
+ conversationId,
71337
+ newest.ordinal
71338
+ );
71339
+ let lastTurn = await slot.current?.read();
71340
+ const page = await readLocalConversationMessages(
71341
+ deps.runsDir,
71342
+ conversationId,
71343
+ limit,
71344
+ void 0,
71345
+ slot.current ?? void 0
71346
+ );
71347
+ if (!page) {
71348
+ sendError(res, 404, "not_found", "This computer has no complete local page");
71349
+ return;
71350
+ }
71351
+ startEventStream(res);
71352
+ await writeEvent(res, {
71353
+ name: "snapshot",
71354
+ id: page.revision,
71355
+ dataLines: [JSON.stringify(page)]
71356
+ });
71357
+ while (!signal.aborted) {
71358
+ if (pending.size === 0) {
71359
+ await new Promise((resolve12) => {
71360
+ wake = resolve12;
71361
+ if (signal.aborted || pending.size > 0) resolve12();
71362
+ });
71363
+ wake = void 0;
71364
+ }
71365
+ if (signal.aborted) return;
71366
+ await systemClock.sleep(50, signal);
71367
+ const changed = [...pending];
71368
+ pending.clear();
71369
+ for (const runId of changed) {
71370
+ const turn = await readChangedTurn(deps, conversationId, runId, slot);
71371
+ if (!turn || turn === lastTurn) continue;
71372
+ lastTurn = turn;
71373
+ await writeEvent(res, { name: "turn", id: `${runId}`, dataLines: [JSON.stringify(turn)] });
71374
+ }
71375
+ }
71376
+ } finally {
71377
+ await slot.current?.[Symbol.asyncDispose]();
71378
+ }
71379
+ } catch (_) {
71380
+ var _error = _, _hasError = true;
71381
+ } finally {
71382
+ __callDispose(_stack, _error, _hasError);
71383
+ }
71384
+ }
71385
+
69838
71386
  // src/local-api/request.ts
69839
71387
  async function readBody3(request2, schema) {
69840
71388
  const body = await readJsonBody(request2.req);
@@ -70033,6 +71581,11 @@ async function followRunLogRoute(deps, runId, url3, res, signal) {
70033
71581
 
70034
71582
  // src/local-api/routes.ts
70035
71583
  var RUN_PATH = /^\/v2\/runs\/([^/]+)\/(log|log\/stream|abort)$/;
71584
+ var CONVERSATION_MESSAGES_PATH = /^\/v2\/conversations\/([^/]+)\/messages(\/sse)?$/;
71585
+ var conversationMessagesQuerySchema = external_exports.object({
71586
+ limit: external_exports.coerce.number().int().min(1).max(100).default(10),
71587
+ before: external_exports.coerce.number().int().nonnegative().optional()
71588
+ });
70036
71589
  var emptyBodySchema = external_exports.object({});
70037
71590
  function activeRunIds(runs) {
70038
71591
  return runs.filter((run2) => run2.state !== "ended").map((run2) => run2.runId);
@@ -70279,6 +71832,41 @@ async function route(deps, request2) {
70279
71832
  }
70280
71833
  const match = RUN_PATH.exec(request2.url.pathname);
70281
71834
  if (match !== null) return routeRun(deps, request2, match);
71835
+ const conversationMatch = CONVERSATION_MESSAGES_PATH.exec(request2.url.pathname);
71836
+ if (conversationMatch !== null) {
71837
+ if (request2.req.method !== "GET") {
71838
+ sendError(request2.res, 405, "method_not_allowed", "Use GET");
71839
+ return;
71840
+ }
71841
+ const conversationId = conversationIdSchema.safeParse(conversationMatch[1]);
71842
+ const query = conversationMessagesQuerySchema.safeParse(
71843
+ Object.fromEntries(request2.url.searchParams)
71844
+ );
71845
+ if (!conversationId.success || !query.success) {
71846
+ sendError(request2.res, 400, "invalid_request", "Invalid conversation messages request");
71847
+ return;
71848
+ }
71849
+ if (conversationMatch[2])
71850
+ return streamLocalConversationMessages(
71851
+ deps,
71852
+ conversationId.data,
71853
+ query.data.limit,
71854
+ request2.res,
71855
+ request2.signal
71856
+ );
71857
+ const page = await readLocalConversationMessages(
71858
+ deps.runsDir,
71859
+ conversationId.data,
71860
+ query.data.limit,
71861
+ query.data.before
71862
+ );
71863
+ if (page === null) {
71864
+ sendError(request2.res, 404, "not_found", "This computer has no complete local page");
71865
+ return;
71866
+ }
71867
+ sendJson(request2.res, 200, page);
71868
+ return;
71869
+ }
70282
71870
  sendError(request2.res, 404, "not_found", "Not found");
70283
71871
  }
70284
71872
 
@@ -70328,6 +71916,15 @@ var REQUEST_TIMEOUT_MS8 = 1e4;
70328
71916
  var KEEP_ALIVE_TIMEOUT_MS = 2e3;
70329
71917
  var ACTION_TIMEOUT_MS = 3e4;
70330
71918
  var PROVIDER_INSTALL_TIMEOUT_MS = 10 * 6e4;
71919
+ function localRequestSignal(path4, closed) {
71920
+ if (path4.endsWith("/stream") || path4.endsWith("/sse")) return closed;
71921
+ return AbortSignal.any([
71922
+ closed,
71923
+ AbortSignal.timeout(
71924
+ path4 === LOCAL_API_ROUTES.providerInstall ? PROVIDER_INSTALL_TIMEOUT_MS : ACTION_TIMEOUT_MS
71925
+ )
71926
+ ]);
71927
+ }
70331
71928
  async function listenOnLoopback(server) {
70332
71929
  await new Promise((resolve12, reject) => {
70333
71930
  server.once("error", reject);
@@ -70372,7 +71969,7 @@ async function serveLocalApi(deps) {
70372
71969
  server.keepAliveTimeout = KEEP_ALIVE_TIMEOUT_MS;
70373
71970
  server.maxConnections = HARD_MAX_CONNECTIONS;
70374
71971
  const port = await listenOnLoopback(server);
70375
- const token = (0, import_node_crypto33.randomBytes)(32).toString("base64url");
71972
+ const token = (0, import_node_crypto34.randomBytes)(32).toString("base64url");
70376
71973
  const guard = createRequestGuard({ token, port, rateLimit: limits.rateLimit, clock });
70377
71974
  const appAttachments = createAppAttachments(clock);
70378
71975
  const routeDeps = {
@@ -70398,15 +71995,11 @@ async function serveLocalApi(deps) {
70398
71995
  inFlight += 1;
70399
71996
  const url3 = new URL(req.url ?? "/", `http://127.0.0.1:${port}`);
70400
71997
  const closed = requestSignal(res);
70401
- const signal = url3.pathname.endsWith("/stream") ? closed : AbortSignal.any([
70402
- closed,
70403
- AbortSignal.timeout(
70404
- url3.pathname === LOCAL_API_ROUTES.providerInstall ? PROVIDER_INSTALL_TIMEOUT_MS : ACTION_TIMEOUT_MS
70405
- )
70406
- ]);
71998
+ const signal = localRequestSignal(url3.pathname, closed);
70407
71999
  try {
70408
72000
  await route(routeDeps, { req, res, url: url3, signal });
70409
72001
  } catch (error61) {
72002
+ if (closed.aborted) return;
70410
72003
  log.warn("local_api.request_failed", { path: url3.pathname, error: error61 });
70411
72004
  sendError(res, 500, "internal", "The runtime could not complete the request");
70412
72005
  } finally {
@@ -70422,7 +72015,7 @@ async function serveLocalApi(deps) {
70422
72015
  startedAtMs,
70423
72016
  runtimeVersion: deps.runtimeVersion
70424
72017
  };
70425
- const discoveryPath = (0, import_node_path75.join)(deps.stateDir, LOCAL_API_DISCOVERY_FILE);
72018
+ const discoveryPath = (0, import_node_path76.join)(deps.stateDir, LOCAL_API_DISCOVERY_FILE);
70426
72019
  await writeJsonFileAtomic(discoveryPath, discovery);
70427
72020
  const followers = startMaintenance({
70428
72021
  everyMs: limits.refreshEveryMs,
@@ -70456,7 +72049,7 @@ async function serveLocalApi(deps) {
70456
72049
  await watchedStatus[Symbol.asyncDispose]();
70457
72050
  const current = await readJsonFile(discoveryPath, localApiDiscoverySchema);
70458
72051
  if (current.kind === "ok" && current.value.token === token) {
70459
- await (0, import_promises72.rm)(discoveryPath, { force: true });
72052
+ await (0, import_promises73.rm)(discoveryPath, { force: true });
70460
72053
  }
70461
72054
  await closeServer(server);
70462
72055
  log.info("local_api.closed", {});
@@ -70541,7 +72134,7 @@ function machineFeatureActions(deps) {
70541
72134
  }
70542
72135
 
70543
72136
  // src/cli/commands/machine-plane.ts
70544
- var import_node_path77 = require("path");
72137
+ var import_node_path78 = require("path");
70545
72138
 
70546
72139
  // src/link/index.ts
70547
72140
  init_runtime_v2();
@@ -74209,7 +75802,7 @@ function refusalFailure(refusal2) {
74209
75802
  }
74210
75803
 
74211
75804
  // src/link/probe.ts
74212
- var import_promises73 = require("dns/promises");
75805
+ var import_promises74 = require("dns/promises");
74213
75806
  var import_node_net5 = require("net");
74214
75807
  var import_node_tls2 = require("tls");
74215
75808
  var PROBE_TIMEOUT_MS4 = 5e3;
@@ -74245,7 +75838,7 @@ async function connectOnce(url3, clock) {
74245
75838
  }
74246
75839
  async function probeEndpoint(url3, clock) {
74247
75840
  try {
74248
- await (0, import_promises73.lookup)(url3.hostname);
75841
+ await (0, import_promises74.lookup)(url3.hostname);
74249
75842
  } catch (error61) {
74250
75843
  const reason = classifyTransportFailure(error61);
74251
75844
  return reason === "other" ? "dns" : reason;
@@ -74368,8 +75961,12 @@ function connectLink(options) {
74368
75961
  const hello = await options.hello(connectEpoch);
74369
75962
  const ack = await socket.timeout(HELLO_TIMEOUT_MS).emitWithAck("hello", hello);
74370
75963
  await ready;
74371
- if (connectEpoch !== epoch) return;
75964
+ if (connectEpoch !== epoch || !socket.connected) return;
74372
75965
  options.onHelloAck(helloAckSchema.parse(ack), connectEpoch);
75966
+ retry.attempt = 0;
75967
+ retry.credentialFailures = 0;
75968
+ setState({ kind: "connected", epoch: connectEpoch });
75969
+ log.info("link.connected", { epoch: connectEpoch });
74373
75970
  };
74374
75971
  const setState = (next) => {
74375
75972
  current = next;
@@ -74439,12 +76036,16 @@ function connectLink(options) {
74439
76036
  };
74440
76037
  socket.on("connect", () => {
74441
76038
  epoch += 1;
74442
- retry.attempt = 0;
74443
- retry.credentialFailures = 0;
76039
+ const connectEpoch = epoch;
74444
76040
  cancelRedial();
74445
- setState({ kind: "connected", epoch });
74446
- log.info("link.connected", { epoch });
74447
- greet(epoch).catch((error61) => log.warn("link.hello_failed", { epoch, error: error61 }));
76041
+ setState({ kind: "connecting", lastFailure: null });
76042
+ greet(connectEpoch).catch((error61) => {
76043
+ if (connectEpoch !== epoch || current.kind === "stopped" || !socket.connected) return;
76044
+ log.warn("link.hello_failed", { epoch: connectEpoch, error: error61 });
76045
+ recordTransportFailure("other", "The backend did not acknowledge this runtime");
76046
+ socket.disconnect();
76047
+ redialAfter(redialDelayMs(retry.attempt++));
76048
+ });
74448
76049
  });
74449
76050
  socket.on("disconnect", (reason) => {
74450
76051
  log.info("link.disconnected", { reason });
@@ -74498,7 +76099,7 @@ function connectLink(options) {
74498
76099
  void ready.then(() => answerModelsScan(raw, options.scanModels, log)).then((result) => ack(result));
74499
76100
  });
74500
76101
  const pushCapabilities = async (capabilities) => {
74501
- if (!socket.connected) return false;
76102
+ if (current.kind !== "connected" || !socket.connected) return false;
74502
76103
  try {
74503
76104
  const ack = await socket.timeout(CAPABILITIES_ACK_TIMEOUT_MS).emitWithAck("capabilities", capabilities);
74504
76105
  const parsed = capabilitiesAckSchema.safeParse(ack);
@@ -74547,9 +76148,9 @@ function planReconcile(desired, held) {
74547
76148
  }
74548
76149
 
74549
76150
  // src/reconciler/desired-sync.ts
74550
- var import_node_crypto34 = require("crypto");
76151
+ var import_node_crypto35 = require("crypto");
74551
76152
  function fingerprintOf(desired) {
74552
- return (0, import_node_crypto34.createHash)("sha256").update(JSON.stringify(desired)).digest("hex");
76153
+ return (0, import_node_crypto35.createHash)("sha256").update(JSON.stringify(desired)).digest("hex");
74553
76154
  }
74554
76155
  var FAILED_READ_RETRY_MS = 3e4;
74555
76156
  function createDesiredSync(deps) {
@@ -74686,7 +76287,7 @@ function createReconciler(host, lifecycle, log, signal) {
74686
76287
  }
74687
76288
 
74688
76289
  // src/uploader/index.ts
74689
- var import_promises74 = require("fs/promises");
76290
+ var import_promises75 = require("fs/promises");
74690
76291
  init_runtime_v2();
74691
76292
  init_zod();
74692
76293
  var RETRY_DELAYS_MS = [250, 500, 1e3, 2e3, 5e3, 1e4, 3e4];
@@ -74827,7 +76428,7 @@ function startUploader({ api, runsDir, clock, log }) {
74827
76428
  active.set(runId, task);
74828
76429
  };
74829
76430
  const sweep2 = async () => {
74830
- for (const name of await (0, import_promises74.readdir)(runsDir).catch(() => [])) {
76431
+ for (const name of await (0, import_promises75.readdir)(runsDir).catch(() => [])) {
74831
76432
  const runId = runIdSchema.safeParse(name);
74832
76433
  if (runId.success) run2(runId.data);
74833
76434
  }
@@ -74837,18 +76438,18 @@ function startUploader({ api, runsDir, clock, log }) {
74837
76438
  const dir = runDirectory(runsDir, runId);
74838
76439
  const progress = await readJsonFile(dir.upload, uploadProgressSchema);
74839
76440
  if (progress.kind !== "ok" || !progress.value.sealed) return false;
74840
- const sealedAt = (await (0, import_promises74.stat)(dir.upload)).mtimeMs;
76441
+ const sealedAt = (await (0, import_promises75.stat)(dir.upload)).mtimeMs;
74841
76442
  if (clock.now() - sealedAt < options.sealedForMs) return false;
74842
76443
  return (await readLastRecord(dir.log))?.update.sessionUpdate === "_alan/run.ended";
74843
76444
  };
74844
76445
  const prune = async (options) => {
74845
76446
  let removed = 0;
74846
- for (const name of await (0, import_promises74.readdir)(runsDir).catch(() => [])) {
76447
+ for (const name of await (0, import_promises75.readdir)(runsDir).catch(() => [])) {
74847
76448
  const runId = runIdSchema.safeParse(name);
74848
76449
  if (!runId.success) continue;
74849
76450
  try {
74850
76451
  if (!await isPrunable(runId.data, options)) continue;
74851
- await (0, import_promises74.rm)(runDirectory(runsDir, runId.data).dir, { recursive: true, force: true });
76452
+ await (0, import_promises75.rm)(runDirectory(runsDir, runId.data).dir, { recursive: true, force: true });
74852
76453
  removed += 1;
74853
76454
  } catch (error61) {
74854
76455
  log.warn("upload.prune_failed", { runId: runId.data, error: error61 });
@@ -75030,12 +76631,12 @@ async function startMachineNativeIngest(deps) {
75030
76631
  }
75031
76632
 
75032
76633
  // src/cli/commands/run-updates.ts
75033
- var import_node_path76 = require("path");
76634
+ var import_node_path77 = require("path");
75034
76635
  init_runtime_v2();
75035
76636
  var UPDATE_CHECK_EVERY_MS = 6 * 60 * 60 * 1e3;
75036
76637
  var DEFERRED_RETRY_MS = 5 * 60 * 1e3;
75037
76638
  function isInstalledBundle(layout, bundlePath) {
75038
- return (0, import_node_path76.resolve)((0, import_node_path76.dirname)((0, import_node_path76.dirname)(bundlePath))) === (0, import_node_path76.resolve)(layout.versions);
76639
+ return (0, import_node_path77.resolve)((0, import_node_path77.dirname)((0, import_node_path77.dirname)(bundlePath))) === (0, import_node_path77.resolve)(layout.versions);
75039
76640
  }
75040
76641
  async function settleUpgradeOnStart({
75041
76642
  layout,
@@ -75142,7 +76743,7 @@ function startRuntimeUpdates(options) {
75142
76743
  layout,
75143
76744
  release: npmRelease,
75144
76745
  tarball: await options.downloader.download(npmRelease.dist.tarball, signal),
75145
- tmpDir: (0, import_node_path76.join)(layout.root, ".downloads")
76746
+ tmpDir: (0, import_node_path77.join)(layout.root, ".downloads")
75146
76747
  });
75147
76748
  await lifecycle.exclusive("upgrade", async () => {
75148
76749
  await recordPendingUpgrade(layout, currentVersion2, version2, clock.now());
@@ -75367,7 +76968,7 @@ async function startMachinePlane(deps) {
75367
76968
  [ALAN_MANAGED_SESSION_ENV]: "1"
75368
76969
  },
75369
76970
  cwd: paths.stateDir,
75370
- outputPath: (0, import_node_path77.join)(paths.logs, "holders.log")
76971
+ outputPath: (0, import_node_path78.join)(paths.logs, "holders.log")
75371
76972
  },
75372
76973
  deps.holderIsolation
75373
76974
  );
@@ -75598,7 +77199,7 @@ async function startMachinePlane(deps) {
75598
77199
  git: createGitRunner({ env: cliEnvironment }),
75599
77200
  clock,
75600
77201
  log,
75601
- dir: (0, import_node_path77.join)(paths.stateDir, "checkout-freshness")
77202
+ dir: (0, import_node_path78.join)(paths.stateDir, "checkout-freshness")
75602
77203
  },
75603
77204
  stopped.signal
75604
77205
  );
@@ -75892,23 +77493,28 @@ function lockWaitMs(argv) {
75892
77493
  }
75893
77494
  async function openManagedProviders(config2, paths) {
75894
77495
  const providerEnv = readCliEnvironment();
75895
- const npmPath = config2.providerToolchain?.node ?? await resolveCommandOnPath("npm", providerEnv, process.platform);
75896
- const npmOptions = npmPath === null ? null : {
77496
+ const bundledNpm = (0, import_node_path79.join)((0, import_node_path79.dirname)(process.execPath), "npm", "bin", "npm-cli.js");
77497
+ const providerToolchain = config2.providerToolchain ?? (process.platform === "win32" && (0, import_node_fs23.existsSync)(bundledNpm) ? { node: process.execPath, npmCli: bundledNpm } : null);
77498
+ const npmPath = providerToolchain?.node ?? await resolveCommandOnPath("npm", providerEnv, process.platform);
77499
+ const npmOptions = npmPath === null || process.platform === "win32" && providerToolchain === null ? null : {
75897
77500
  command: npmPath,
75898
- ...config2.providerToolchain === null ? {} : { argsBeforeNpm: [config2.providerToolchain.npmCli] },
77501
+ ...providerToolchain === null ? {} : { argsBeforeNpm: [providerToolchain.npmCli] },
75899
77502
  env: providerEnv
75900
77503
  };
75901
- const providerNodeDir = config2.providerToolchain?.node === void 0 ? void 0 : (0, import_node_path78.join)(config2.providerToolchain.node, "..");
75902
- const providerProbeEnv = providerNodeDir === void 0 ? providerEnv : { ...providerEnv, PATH: `${providerNodeDir}:${providerEnv.PATH ?? ""}` };
77504
+ const providerNodeDir = providerToolchain?.node === void 0 ? void 0 : (0, import_node_path79.dirname)(providerToolchain.node);
77505
+ const probeEnv = providerNodeDir === void 0 ? providerEnv : {
77506
+ ...providerEnv,
77507
+ PATH: `${providerNodeDir}${pathDelimiter(process.platform)}${envValue(providerEnv, "PATH")}`
77508
+ };
77509
+ const canonicalProbeEnv = process.platform === "win32" ? canonicalWindowsEnvironment(probeEnv) : probeEnv;
77510
+ const unavailable = async () => {
77511
+ throw new Error("Provider installer is unavailable on this computer");
77512
+ };
75903
77513
  const managed = createManagedProviderClis({
75904
- root: (0, import_node_path78.join)(paths.stateDir, "provider-clis"),
75905
- resolveVersion: npmOptions === null ? async () => {
75906
- throw new Error("Provider installer is unavailable on this computer");
75907
- } : createNpmVersionResolver(npmOptions),
75908
- installPackage: npmOptions === null ? async () => {
75909
- throw new Error("Provider installer is unavailable on this computer");
75910
- } : createNpmPackageInstaller(npmOptions),
75911
- probe: (executable, backendKind) => probeManagedProvider(executable, backendKind, providerProbeEnv)
77514
+ root: (0, import_node_path79.join)(paths.stateDir, "provider-clis"),
77515
+ resolveVersion: npmOptions === null ? unavailable : createNpmVersionResolver(npmOptions),
77516
+ installPackage: npmOptions === null ? unavailable : createNpmPackageInstaller(npmOptions),
77517
+ probe: (executable, backendKind) => probeManagedProvider(executable, backendKind, canonicalProbeEnv)
75912
77518
  });
75913
77519
  await managed.load();
75914
77520
  return { managed, providerNodeDir };
@@ -75937,7 +77543,7 @@ async function runService(argv, stop, restart = new AbortController().signal) {
75937
77543
  waitMs: lockWaitMs(argv),
75938
77544
  signal: stop
75939
77545
  }));
75940
- const log = __using(_stack, openFileLog((0, import_node_path78.join)(paths.logs, "runtime.jsonl"), config2.logLevel, clock));
77546
+ const log = __using(_stack, openFileLog((0, import_node_path79.join)(paths.logs, "runtime.jsonl"), config2.logLevel, clock));
75941
77547
  const lifecycle = createLifecycleQueue({ clock, log });
75942
77548
  const install2 = installLayout(config2.installDir, config2.profile);
75943
77549
  const bundlePath = process.argv[1] ?? "";
@@ -75971,7 +77577,7 @@ async function runService(argv, stop, restart = new AbortController().signal) {
75971
77577
  openCliEnvironment({
75972
77578
  env: readCliEnvironment(),
75973
77579
  platform: process.platform,
75974
- lastKnownGoodFile: (0, import_node_path78.join)(paths.stateDir, "login-path.json"),
77580
+ lastKnownGoodFile: (0, import_node_path79.join)(paths.stateDir, "login-path.json"),
75975
77581
  clock,
75976
77582
  decorate: (env) => withPackagedAlanCodeEngine(env, bundlePath, process.platform)
75977
77583
  })
@@ -76148,17 +77754,17 @@ async function runServiceCommand(argv, ctx = cliContext()) {
76148
77754
  }
76149
77755
 
76150
77756
  // src/cli/commands/upgrade.ts
76151
- var import_promises75 = require("fs/promises");
76152
- var import_node_path79 = require("path");
77757
+ var import_promises76 = require("fs/promises");
77758
+ var import_node_path80 = require("path");
76153
77759
  function isNotNewer(version2, installed) {
76154
77760
  return installed !== null && isReleaseVersion(version2) && isReleaseVersion(installed) && compareVersions(version2, installed) <= 0;
76155
77761
  }
76156
77762
  async function installFromSource(source) {
76157
77763
  const { layout, from, ifNewer } = source;
76158
- const isTarball = (await (0, import_promises75.stat)(from)).isFile();
76159
- const downloads = (0, import_node_path79.join)(layout.root, ".downloads");
76160
- if (isTarball) await (0, import_promises75.mkdir)(downloads, { recursive: true, mode: 448 });
76161
- const scratch = isTarball ? await (0, import_promises75.mkdtemp)((0, import_node_path79.join)(downloads, "upgrade-")) : null;
77764
+ const isTarball = (await (0, import_promises76.stat)(from)).isFile();
77765
+ const downloads = (0, import_node_path80.join)(layout.root, ".downloads");
77766
+ if (isTarball) await (0, import_promises76.mkdir)(downloads, { recursive: true, mode: 448 });
77767
+ const scratch = isTarball ? await (0, import_promises76.mkdtemp)((0, import_node_path80.join)(downloads, "upgrade-")) : null;
76162
77768
  try {
76163
77769
  const sourceDir = scratch === null ? from : await extractPackageTarball(from, scratch);
76164
77770
  const version2 = await readPackageVersion(sourceDir);
@@ -76166,7 +77772,7 @@ async function installFromSource(source) {
76166
77772
  if (ifNewer && isNotNewer(version2, installed)) return { kind: "skipped", version: version2, installed };
76167
77773
  return { kind: "installed", ...await installVersion(layout, sourceDir) };
76168
77774
  } finally {
76169
- if (scratch !== null) await (0, import_promises75.rm)(scratch, { recursive: true, force: true });
77775
+ if (scratch !== null) await (0, import_promises76.rm)(scratch, { recursive: true, force: true });
76170
77776
  }
76171
77777
  }
76172
77778
  async function runUpgrade(argv) {
@@ -76178,7 +77784,7 @@ async function runUpgrade(argv) {
76178
77784
  const layout = installLayout(config2.installDir, config2.profile);
76179
77785
  const outcome2 = await installFromSource({
76180
77786
  layout,
76181
- from: (0, import_node_path79.resolve)(from),
77787
+ from: (0, import_node_path80.resolve)(from),
76182
77788
  ifNewer: hasFlag(argv, "--if-newer")
76183
77789
  });
76184
77790
  if (outcome2.kind === "skipped") {