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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/alan-agent.cjs +2220 -334
  2. package/alan-holder.cjs +206 -61
  3. package/package.json +1 -1
package/alan-agent.cjs CHANGED
@@ -20782,7 +20782,11 @@ var init_github_proxy = __esm({
20782
20782
  ];
20783
20783
  gitHubProxyUpstreamSchema = external_exports.enum(GITHUB_PROXY_UPSTREAMS);
20784
20784
  GITHUB_PROXY_PLACEHOLDER_TOKEN = "proxy-injected";
20785
- GITHUB_PROXY_REFUSAL_CODES = ["host_not_proxied", "machine_not_allowed"];
20785
+ GITHUB_PROXY_REFUSAL_CODES = [
20786
+ "host_not_proxied",
20787
+ "machine_not_allowed",
20788
+ "github_not_connected"
20789
+ ];
20786
20790
  gitHubProxyErrorSchema = external_exports.object({
20787
20791
  message: external_exports.string().min(1),
20788
20792
  documentation_url: external_exports.string(),
@@ -21762,6 +21766,9 @@ For any UI or design work, read and follow the \`uiux\` skill in \`.agents/skill
21762
21766
  });
21763
21767
 
21764
21768
  // ../shared/dist/agent/attachment-mention.js
21769
+ function attachmentMentionPattern() {
21770
+ return /@\[attachment:([^:\]\s]+):(.*?)\](?=[.,;:!?)]*(?:\s|$))/gi;
21771
+ }
21765
21772
  var init_attachment_mention = __esm({
21766
21773
  "../shared/dist/agent/attachment-mention.js"() {
21767
21774
  "use strict";
@@ -22238,6 +22245,22 @@ var init_agent = __esm({
22238
22245
  }
22239
22246
  });
22240
22247
 
22248
+ // ../shared/dist/agent/transcript/preview.js
22249
+ function toPreviewText(value2, limit) {
22250
+ 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();
22251
+ if (text2.length <= limit)
22252
+ return text2;
22253
+ const clipped = text2.slice(0, limit - 1);
22254
+ const lastSpace = clipped.lastIndexOf(" ");
22255
+ const body = lastSpace > limit * 0.6 ? clipped.slice(0, lastSpace) : clipped;
22256
+ return `${body.trimEnd()}\u2026`;
22257
+ }
22258
+ var init_preview = __esm({
22259
+ "../shared/dist/agent/transcript/preview.js"() {
22260
+ "use strict";
22261
+ }
22262
+ });
22263
+
22241
22264
  // ../shared/dist/agent/transcript/index.js
22242
22265
  var init_transcript = __esm({
22243
22266
  "../shared/dist/agent/transcript/index.js"() {
@@ -22344,23 +22367,31 @@ var init_chunk_YXWJW7I5 = __esm({
22344
22367
  }
22345
22368
  });
22346
22369
 
22347
- // ../agent-core/dist/chunk-J4T6L5LX.js
22370
+ // ../agent-core/dist/chunk-M6YHY2EZ.js
22348
22371
  function windowsEnvValue(env, name) {
22349
22372
  const wanted = name.toLowerCase();
22350
- for (const [key, value2] of Object.entries(env)) {
22373
+ for (const [key, value2] of Object.entries(env).reverse()) {
22351
22374
  if (key.toLowerCase() === wanted) return value2;
22352
22375
  }
22353
22376
  return void 0;
22354
22377
  }
22378
+ function canonicalWindowsEnvironment(env) {
22379
+ const unique2 = /* @__PURE__ */ new Map();
22380
+ for (const [name, value2] of Object.entries(env)) {
22381
+ unique2.set(name.toLowerCase(), [name.toLowerCase() === "path" ? "PATH" : name, value2]);
22382
+ }
22383
+ return Object.fromEntries(unique2.values());
22384
+ }
22355
22385
  function hasExtension(name, extensions) {
22356
22386
  const ext = import_path.win32.extname(name).toLowerCase();
22357
22387
  return ext.length > 0 && extensions.includes(ext);
22358
22388
  }
22359
22389
  function candidates(base, extensions) {
22360
- return hasExtension(base, extensions) ? [base] : extensions.map((ext) => `${base}${ext}`);
22390
+ const extension = import_path.win32.extname(base).toLowerCase();
22391
+ return extension === ".exe" || extension === ".com" || hasExtension(base, extensions) ? [base] : extensions.map((ext) => `${base}${ext}`);
22361
22392
  }
22362
22393
  function resolveWindowsCommand(command, env, files) {
22363
- const extensions = (windowsEnvValue(env, "PATHEXT") ?? DEFAULT_PATHEXT).split(";").map((ext) => ext.trim().toLowerCase()).filter((ext) => ext.startsWith("."));
22394
+ const extensions = (windowsEnvValue(env, "PATHEXT") ?? DEFAULT_PATHEXT).split(";").map((ext) => ext.trim().toLowerCase()).filter((ext) => LAUNCHABLE_EXTENSIONS.has(ext));
22364
22395
  if (/[\\/]/.test(command)) {
22365
22396
  return candidates(command, extensions).find((path4) => files.isFile(path4));
22366
22397
  }
@@ -22373,6 +22404,18 @@ function resolveWindowsCommand(command, env, files) {
22373
22404
  }
22374
22405
  return void 0;
22375
22406
  }
22407
+ function unwrapNativeShim(shim, args, files) {
22408
+ const lines2 = files.readShim(shim)?.split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
22409
+ if (lines2?.length !== NATIVE_SHIM_LINES.length + 1) return void 0;
22410
+ if (!NATIVE_SHIM_LINES.every((pattern, index) => pattern.test(lines2[index] ?? ""))) {
22411
+ return void 0;
22412
+ }
22413
+ const target = NATIVE_SHIM_ENTRY.exec(lines2.at(-1) ?? "")?.[1];
22414
+ if (target === void 0) return void 0;
22415
+ const directory = import_path.win32.dirname(shim);
22416
+ const file2 = import_path.win32.resolve(directory, target.replace(/^%dp0%\\/i, ""));
22417
+ return files.isFile(file2) ? { kind: "native", file: file2, args } : void 0;
22418
+ }
22376
22419
  function isSimpleNodeShim(text2) {
22377
22420
  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
22421
  }
@@ -22398,7 +22441,7 @@ function planWindowsLaunch(command, args, env, files) {
22398
22441
  const file2 = resolveWindowsCommand(command, env, files);
22399
22442
  if (file2 === void 0) return void 0;
22400
22443
  if (!/\.(cmd|bat)$/i.test(file2)) return { kind: "native", file: file2, args };
22401
- return unwrapNodeShim(file2, args, env, files) ?? { kind: "batch", file: file2, args };
22444
+ return unwrapNativeShim(file2, args, files) ?? unwrapNodeShim(file2, args, env, files) ?? { kind: "batch", file: file2, args };
22402
22445
  }
22403
22446
  function quoteWindowsArgument(value2) {
22404
22447
  if (value2.length === 0) return '""';
@@ -22900,11 +22943,12 @@ function onCliSpawned(listener) {
22900
22943
  }
22901
22944
  function spawnCli(options) {
22902
22945
  const platform3 = options.platform ?? process.platform;
22903
- const plan2 = planSpawn({ ...options, platform: platform3 });
22904
- if (plan2.commandLine !== null) return spawnInWindowsJob(plan2, options);
22946
+ const env = platform3 === "win32" ? canonicalWindowsEnvironment(options.env) : options.env;
22947
+ const plan2 = planSpawn({ ...options, env, platform: platform3 });
22948
+ if (plan2.commandLine !== null) return spawnInWindowsJob(plan2, { ...options, env });
22905
22949
  const child = (0, import_child_process5.spawn)(plan2.file, [...plan2.args], {
22906
22950
  cwd: options.cwd,
22907
- env: { ...options.env },
22951
+ env: { ...env },
22908
22952
  stdio: ["pipe", "pipe", "pipe"],
22909
22953
  shell: false,
22910
22954
  detached: true
@@ -22931,9 +22975,9 @@ function waitForSpawn(child, command) {
22931
22975
  child.once("error", onError);
22932
22976
  });
22933
22977
  }
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"() {
22978
+ 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;
22979
+ var init_chunk_M6YHY2EZ = __esm({
22980
+ "../agent-core/dist/chunk-M6YHY2EZ.js"() {
22937
22981
  "use strict";
22938
22982
  init_chunk_YXWJW7I5();
22939
22983
  import_child_process = require("child_process");
@@ -22954,6 +22998,7 @@ var init_chunk_J4T6L5LX = __esm({
22954
22998
  CMD_MAX_COMMAND_LINE = 8191;
22955
22999
  MAX_COMMAND_LINE = 32766;
22956
23000
  DEFAULT_PATHEXT = ".COM;.EXE;.BAT;.CMD";
23001
+ LAUNCHABLE_EXTENSIONS = /* @__PURE__ */ new Set([".com", ".exe", ".bat", ".cmd"]);
22957
23002
  nodeWindowsFiles = {
22958
23003
  isFile: (path4) => {
22959
23004
  try {
@@ -22972,6 +23017,17 @@ var init_chunk_J4T6L5LX = __esm({
22972
23017
  }
22973
23018
  };
22974
23019
  NODE_SHIM_ENTRY = /"(%_prog%|[^"\r\n]*node(?:\.exe)?)"\s+"([^"\r\n]+\.(?:c?js|mjs))"\s+%\*/i;
23020
+ NATIVE_SHIM_LINES = [
23021
+ /^@echo off$/i,
23022
+ /^goto start$/i,
23023
+ /^:find_dp0$/i,
23024
+ /^set dp0=%~dp0$/i,
23025
+ /^exit \/b$/i,
23026
+ /^:start$/i,
23027
+ /^setlocal$/i,
23028
+ /^call :find_dp0$/i
23029
+ ];
23030
+ NATIVE_SHIM_ENTRY = /^"(%dp0%\\(?:\.\.\\)?(?:node_modules\\)?[\w@.-]+(?:\\[\w@.-]+)*\.exe)"\s+%\*$/i;
22975
23031
  CMD_META = /([()\][%!^"`<>&|;, *?])/g;
22976
23032
  NEVER_STARTED = { stdout: "", stderr: "", exitCode: void 0 };
22977
23033
  HIDDEN_FLAG_PROBE_VALUE = "__alan_probe__";
@@ -23729,29 +23785,209 @@ var init_constants = __esm({
23729
23785
  });
23730
23786
 
23731
23787
  // ../shared/dist/agent/acp/transcript-http.js
23788
+ var TRANSCRIPT_TOOL_RESPONSE_ID_META, TRANSCRIPT_TURN_ID_META;
23732
23789
  var init_transcript_http = __esm({
23733
23790
  "../shared/dist/agent/acp/transcript-http.js"() {
23734
23791
  "use strict";
23792
+ TRANSCRIPT_TOOL_RESPONSE_ID_META = "alan.dev/transcriptToolResponseId";
23793
+ TRANSCRIPT_TURN_ID_META = "alan.dev/transcriptTurnId";
23735
23794
  }
23736
23795
  });
23737
23796
 
23738
23797
  // ../shared/dist/agent/acp/ask.js
23798
+ function asRecord2(value2) {
23799
+ return value2 && typeof value2 === "object" && !Array.isArray(value2) ? value2 : void 0;
23800
+ }
23801
+ function readOptions(value2) {
23802
+ if (!Array.isArray(value2))
23803
+ return [];
23804
+ const options = [];
23805
+ for (const raw of value2) {
23806
+ const option2 = asRecord2(raw);
23807
+ const label = typeof option2?.label === "string" ? option2.label : void 0;
23808
+ if (!label)
23809
+ continue;
23810
+ options.push({
23811
+ label,
23812
+ description: typeof option2?.description === "string" ? option2.description : void 0
23813
+ });
23814
+ }
23815
+ return options;
23816
+ }
23817
+ function readQuestions(input2) {
23818
+ const record2 = asRecord2(input2);
23819
+ const raw = record2?.questions;
23820
+ if (!Array.isArray(raw))
23821
+ return [];
23822
+ const questions = [];
23823
+ for (const item of raw) {
23824
+ const entry = asRecord2(item);
23825
+ const question = typeof entry?.question === "string" ? entry.question : void 0;
23826
+ if (!question)
23827
+ continue;
23828
+ questions.push({
23829
+ question,
23830
+ header: typeof entry?.header === "string" ? entry.header : void 0,
23831
+ options: readOptions(entry?.options),
23832
+ multiSelect: entry?.multiSelect === true
23833
+ });
23834
+ }
23835
+ return questions;
23836
+ }
23837
+ function isAskToolCall(entry) {
23838
+ const name = entry.title || entry.toolKind;
23839
+ return isAskUserQuestionTool(name, entry.rawInput);
23840
+ }
23841
+ function findPendingAsk(entries, answeredIds = /* @__PURE__ */ new Set()) {
23842
+ for (let index = entries.length - 1; index >= 0; index -= 1) {
23843
+ const entry = entries[index];
23844
+ if (!entry || entry.kind !== "tool_call")
23845
+ continue;
23846
+ if (entry.status === "completed" || entry.status === "failed" || entry.status === "cancelled") {
23847
+ continue;
23848
+ }
23849
+ if (answeredIds.has(entry.id))
23850
+ continue;
23851
+ if (!isAskToolCall(entry))
23852
+ continue;
23853
+ const questions = readQuestions(entry.rawInput);
23854
+ if (questions.length === 0)
23855
+ continue;
23856
+ return { toolCallId: entry.id, questions, rawInput: asRecord2(entry.rawInput) ?? {} };
23857
+ }
23858
+ return null;
23859
+ }
23739
23860
  var init_ask = __esm({
23740
23861
  "../shared/dist/agent/acp/ask.js"() {
23741
23862
  "use strict";
23863
+ init_agent();
23742
23864
  }
23743
23865
  });
23744
23866
 
23745
23867
  // ../shared/dist/agent/acp/background-task.js
23746
- var BACKGROUND_TASK_META_KEY;
23868
+ function oneOf(values, value2) {
23869
+ return typeof value2 === "string" && values.some((candidate) => candidate === value2);
23870
+ }
23871
+ function isRecord6(value2) {
23872
+ return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
23873
+ }
23874
+ function optionalString(value2) {
23875
+ return typeof value2 === "string" && value2.length > 0 ? value2 : void 0;
23876
+ }
23877
+ function readBackgroundTaskMeta(meta3) {
23878
+ if (!isRecord6(meta3))
23879
+ return null;
23880
+ const raw = meta3[BACKGROUND_TASK_META_KEY];
23881
+ if (!isRecord6(raw))
23882
+ return null;
23883
+ const taskId = optionalString(raw.taskId);
23884
+ if (!taskId)
23885
+ return null;
23886
+ const kind = oneOf(KINDS, raw.kind) ? raw.kind : void 0;
23887
+ const stop = oneOf(STRATEGIES, raw.stop) ? raw.stop : void 0;
23888
+ const status = oneOf(STATUSES, raw.status) ? raw.status : void 0;
23889
+ const label = optionalString(raw.label);
23890
+ const subagentType = optionalString(raw.subagentType);
23891
+ const taskType = optionalString(raw.taskType);
23892
+ return {
23893
+ taskId,
23894
+ backgrounded: raw.backgrounded === true,
23895
+ ...kind ? { kind } : {},
23896
+ ...label ? { label } : {},
23897
+ ...typeof raw.startedAt === "number" ? { startedAt: raw.startedAt } : {},
23898
+ ...stop ? { stop } : {},
23899
+ ...status ? { status } : {},
23900
+ ...raw.stoppedByUser === true ? { stoppedByUser: true } : {},
23901
+ ...subagentType ? { subagentType } : {},
23902
+ ...taskType ? { taskType } : {},
23903
+ ...typeof raw.spawnDepth === "number" ? { spawnDepth: raw.spawnDepth } : {},
23904
+ ...raw.ownedBySubagent === true ? { ownedBySubagent: true } : {}
23905
+ };
23906
+ }
23907
+ var BACKGROUND_TASK_META_KEY, KINDS, STRATEGIES, STATUSES;
23747
23908
  var init_background_task = __esm({
23748
23909
  "../shared/dist/agent/acp/background-task.js"() {
23749
23910
  "use strict";
23750
23911
  BACKGROUND_TASK_META_KEY = "alan.dev/backgroundTask";
23912
+ KINDS = ["shell", "agent"];
23913
+ STRATEGIES = [
23914
+ "native",
23915
+ "pid",
23916
+ "none"
23917
+ ];
23918
+ STATUSES = [
23919
+ "running",
23920
+ "stopping",
23921
+ "stopped",
23922
+ "completed",
23923
+ "failed"
23924
+ ];
23751
23925
  }
23752
23926
  });
23753
23927
 
23754
23928
  // ../shared/dist/agent/acp/presentation/terminal-events.js
23929
+ function isRecord7(value2) {
23930
+ return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
23931
+ }
23932
+ function foldPreview(events) {
23933
+ const output2 = [];
23934
+ const slots = /* @__PURE__ */ new Map();
23935
+ for (const event of events) {
23936
+ const update = event.update;
23937
+ const kind = canonicalKind(update.sessionUpdate);
23938
+ const identity = update.messageId ?? update.toolCallId ?? update.terminalId ?? update.planId;
23939
+ const singleton = [
23940
+ "state_update",
23941
+ "usage_update",
23942
+ "session_info_update",
23943
+ "available_commands_update",
23944
+ "config_option_update",
23945
+ "_alan/thinking_tokens"
23946
+ ].includes(kind);
23947
+ const key = identity !== void 0 || singleton ? JSON.stringify([event.sessionId ?? "", kind, identity ?? "session"]) : void 0;
23948
+ const slot = key ? slots.get(key) : void 0;
23949
+ const previous = slot === void 0 ? void 0 : output2[slot];
23950
+ const merged = {
23951
+ ...previous?.update,
23952
+ ...update,
23953
+ sessionUpdate: kind
23954
+ };
23955
+ if (update.sessionUpdate === "terminal_output_chunk") {
23956
+ const before = previous && isRecord7(previous.update.output) ? previous.update.output.data : "";
23957
+ merged.output = { data: String(before ?? "") + String(update.data ?? "") };
23958
+ } else if (update.sessionUpdate.endsWith("_chunk")) {
23959
+ const before = previous && Array.isArray(previous.update.content) ? previous.update.content : [];
23960
+ merged.content = [
23961
+ ...before,
23962
+ ...Array.isArray(update.content) ? update.content : update.content ? [update.content] : []
23963
+ ];
23964
+ }
23965
+ if (isRecord7(update._meta))
23966
+ merged._meta = {
23967
+ ...isRecord7(previous?.update._meta) ? previous.update._meta : {},
23968
+ ...update._meta
23969
+ };
23970
+ if (kind === "state_update")
23971
+ merged.stopReason = update.state === "idle" ? update.stopReason : void 0;
23972
+ if (kind === "tool_call_update" && ["completed", "failed", "cancelled"].includes(String(previous?.update.status)))
23973
+ merged.status = previous?.update.status;
23974
+ const next = { ...event, line: previous?.line ?? event.line, update: merged };
23975
+ if (slot === void 0) {
23976
+ if (key)
23977
+ slots.set(key, output2.length);
23978
+ output2.push(next);
23979
+ } else
23980
+ output2[slot] = next;
23981
+ }
23982
+ return output2;
23983
+ }
23984
+ function canonicalKind(kind) {
23985
+ if (kind === "tool_call_content_chunk")
23986
+ return "tool_call_update";
23987
+ if (kind === "terminal_output_chunk")
23988
+ return "terminal_update";
23989
+ return kind.replace(/_chunk$/, "");
23990
+ }
23755
23991
  var init_terminal_events = __esm({
23756
23992
  "../shared/dist/agent/acp/presentation/terminal-events.js"() {
23757
23993
  "use strict";
@@ -23759,23 +23995,357 @@ var init_terminal_events = __esm({
23759
23995
  });
23760
23996
 
23761
23997
  // ../shared/dist/agent/acp/presentation/file-edits.js
23998
+ function diffRows(patch) {
23999
+ let oldLine = 0;
24000
+ let newLine = 0;
24001
+ let oldRemaining = 0;
24002
+ let newRemaining = 0;
24003
+ const lines2 = patch.split("\n");
24004
+ if (lines2.at(-1) === "")
24005
+ lines2.pop();
24006
+ return lines2.map((line) => {
24007
+ const hunk = /^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/.exec(line);
24008
+ if (hunk) {
24009
+ oldLine = Number(hunk[1]);
24010
+ newLine = Number(hunk[3]);
24011
+ oldRemaining = Number(hunk[2] ?? 1);
24012
+ newRemaining = Number(hunk[4] ?? 1);
24013
+ return { kind: "hunk", text: line };
24014
+ }
24015
+ if (newRemaining > 0 && line.startsWith("+")) {
24016
+ newRemaining--;
24017
+ return { kind: "add", text: line.slice(1), newLine: newLine++ };
24018
+ }
24019
+ if (oldRemaining > 0 && line.startsWith("-")) {
24020
+ oldRemaining--;
24021
+ return { kind: "remove", text: line.slice(1), oldLine: oldLine++ };
24022
+ }
24023
+ if (oldRemaining > 0 && newRemaining > 0 && line.startsWith(" ")) {
24024
+ oldRemaining--;
24025
+ newRemaining--;
24026
+ return { kind: "context", text: line.slice(1), oldLine: oldLine++, newLine: newLine++ };
24027
+ }
24028
+ return { kind: "meta", text: line };
24029
+ });
24030
+ }
24031
+ function patchForPath(text2, path4, count) {
24032
+ if (count === 1)
24033
+ return text2;
24034
+ const normalized2 = path4.replace(/^\/+/, "");
24035
+ return text2.split(/(?=^diff --git )/m).find((part) => {
24036
+ const names = [...part.matchAll(/^(?:---|\+\+\+) (?:[ab]\/)?([^\t\n]+)/gm)];
24037
+ return names.some((match) => match[1].replace(/^\/+/, "") === normalized2);
24038
+ });
24039
+ }
24040
+ function readDiff(value2, id) {
24041
+ if (!isRecord7(value2) || !Array.isArray(value2.changes))
24042
+ return [];
24043
+ const patch = isRecord7(value2.patch) && typeof value2.patch.text === "string" ? value2.patch : void 0;
24044
+ const changes = value2.changes;
24045
+ return changes.flatMap((change, index) => {
24046
+ if (!isRecord7(change) || typeof change.path !== "string" || typeof change.operation !== "string")
24047
+ return [];
24048
+ const text2 = patch ? patchForPath(String(patch.text), change.path, changes.length) : void 0;
24049
+ const rows = text2 && patch?.format !== "text" ? diffRows(text2) : [];
24050
+ const counted = rows.some((row) => row.kind === "hunk");
24051
+ return [
24052
+ {
24053
+ id: `${id}:${index}`,
24054
+ path: change.path,
24055
+ operation: change.operation,
24056
+ ...typeof change.oldPath === "string" ? { oldPath: change.oldPath } : {},
24057
+ patch: text2,
24058
+ rows,
24059
+ ...counted ? {
24060
+ additions: rows.filter((row) => row.kind === "add").length,
24061
+ deletions: rows.filter((row) => row.kind === "remove").length
24062
+ } : {}
24063
+ }
24064
+ ];
24065
+ });
24066
+ }
24067
+ function toolEdits(node2) {
24068
+ const content = node2.event.update.content;
24069
+ if (!Array.isArray(content))
24070
+ return [];
24071
+ return content.flatMap((block, index) => isRecord7(block) && block.type === "diff" ? readDiff(block.diff, `${node2.key}:${index}`) : []);
24072
+ }
24073
+ function collectEditedFiles(nodes) {
24074
+ const files = /* @__PURE__ */ new Map();
24075
+ const seen = /* @__PURE__ */ new Set();
24076
+ function visit2(node2) {
24077
+ if (seen.has(node2.key))
24078
+ return;
24079
+ seen.add(node2.key);
24080
+ if (node2.event.update.sessionUpdate === "tool_call_update" && node2.event.update.status === "completed") {
24081
+ for (const edit of toolEdits(node2)) {
24082
+ const previous = files.get(edit.path);
24083
+ const edits = [...previous?.edits ?? [], edit];
24084
+ const counted = edits.every((item) => item.additions !== void 0 && item.deletions !== void 0);
24085
+ files.set(edit.path, {
24086
+ path: edit.path,
24087
+ edits,
24088
+ ...counted ? {
24089
+ additions: edits.reduce((sum, item) => sum + (item.additions ?? 0), 0),
24090
+ deletions: edits.reduce((sum, item) => sum + (item.deletions ?? 0), 0)
24091
+ } : {}
24092
+ });
24093
+ }
24094
+ }
24095
+ node2.children.forEach(visit2);
24096
+ }
24097
+ nodes.forEach(visit2);
24098
+ return [...files.values()];
24099
+ }
23762
24100
  var init_file_edits = __esm({
23763
24101
  "../shared/dist/agent/acp/presentation/file-edits.js"() {
23764
24102
  "use strict";
24103
+ init_terminal_events();
23765
24104
  }
23766
24105
  });
23767
24106
 
23768
24107
  // ../shared/dist/agent/acp/presentation/notice-visibility.js
24108
+ function isConversationNotice({ message: message2, kind, meta: meta3 }) {
24109
+ const category = kind ?? (isRecord7(meta3) ? meta3["alan.dev/noticeKind"] : void 0);
24110
+ 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));
24111
+ }
24112
+ function uniqueNotices(notices) {
24113
+ const seen = /* @__PURE__ */ new Set();
24114
+ return notices.filter((notice2) => {
24115
+ const key = `${notice2.message}`;
24116
+ if (seen.has(key))
24117
+ return false;
24118
+ seen.add(key);
24119
+ return true;
24120
+ });
24121
+ }
23769
24122
  var init_notice_visibility = __esm({
23770
24123
  "../shared/dist/agent/acp/presentation/notice-visibility.js"() {
23771
24124
  "use strict";
24125
+ init_terminal_events();
23772
24126
  }
23773
24127
  });
23774
24128
 
23775
24129
  // ../shared/dist/agent/acp/presentation/prepare-conversation-turns.js
24130
+ function entryNode(entry, index) {
24131
+ const prepared = preparedEntries.get(entry);
24132
+ if (prepared?.index === index && prepared.lastUpdateIndex === entry.lastUpdateIndex) {
24133
+ return { key: prepared.key, event: prepared.event, children: [] };
24134
+ }
24135
+ const update = entry.kind === "message" ? {
24136
+ sessionUpdate: entry.role === "user" ? "user_message" : entry.role === "thought" ? "agent_thought" : "agent_message",
24137
+ messageId: entry.id,
24138
+ content: Array.isArray(entry.content) ? entry.content : [],
24139
+ _meta: entry._meta
24140
+ } : {
24141
+ sessionUpdate: "tool_call_update",
24142
+ toolCallId: entry.id,
24143
+ name: entry.name ?? entry.title,
24144
+ title: entry.title,
24145
+ kind: entry.toolKind,
24146
+ status: entry.status,
24147
+ content: entry.content,
24148
+ locations: entry.locations,
24149
+ rawInput: entry.rawInput,
24150
+ rawOutput: entry.rawOutput,
24151
+ _meta: entry._meta
24152
+ };
24153
+ const clientId = entry._meta?.["alan.dev/clientMessageId"];
24154
+ const identity = entry.kind === "message" && entry.role === "user" && typeof clientId === "string" ? clientId : entry.id;
24155
+ const key = entry.kind === "message" ? `message:${entry.role}:${identity}` : `tool:${entry.id}`;
24156
+ const event = { id: key, line: index, seq: entry.lastUpdateIndex, update };
24157
+ preparedEntries.set(entry, { index, lastUpdateIndex: entry.lastUpdateIndex, key, event });
24158
+ return { key, event, children: [] };
24159
+ }
24160
+ function attachChildren(nodes) {
24161
+ const tools = /* @__PURE__ */ new Map();
24162
+ const terminals = /* @__PURE__ */ new Map();
24163
+ for (const node2 of nodes) {
24164
+ const u = node2.event.update;
24165
+ if (typeof u.toolCallId === "string")
24166
+ tools.set(u.toolCallId, node2);
24167
+ for (const block of Array.isArray(u.content) ? u.content : []) {
24168
+ if (isRecord7(block) && block.type === "terminal" && typeof block.terminalId === "string")
24169
+ terminals.set(block.terminalId, node2);
24170
+ }
24171
+ }
24172
+ const parents = /* @__PURE__ */ new Map();
24173
+ for (const node2 of nodes) {
24174
+ const u = node2.event.update;
24175
+ const parentId = isRecord7(u._meta) ? u._meta["alan.dev/parentToolCallId"] : void 0;
24176
+ const parent = typeof parentId === "string" ? tools.get(parentId) : typeof u.terminalId === "string" ? terminals.get(u.terminalId) : void 0;
24177
+ if (parent)
24178
+ parents.set(node2, parent);
24179
+ else if (typeof parentId === "string")
24180
+ node2.issue = `Waiting for parent tool ${parentId}`;
24181
+ }
24182
+ return nodes.filter((node2) => {
24183
+ let ancestor = parents.get(node2);
24184
+ const seen = /* @__PURE__ */ new Set([node2]);
24185
+ while (ancestor) {
24186
+ if (seen.has(ancestor)) {
24187
+ node2.issue = "Cyclic parent reference; shown at root";
24188
+ return true;
24189
+ }
24190
+ seen.add(ancestor);
24191
+ ancestor = parents.get(ancestor);
24192
+ }
24193
+ const parent = parents.get(node2);
24194
+ if (!parent)
24195
+ return true;
24196
+ parent.children.push(node2);
24197
+ return false;
24198
+ });
24199
+ }
24200
+ function turnStart(turn) {
24201
+ if (turn.users[0])
24202
+ return turn.users[0].event.line;
24203
+ return turn.working[0]?.event.line;
24204
+ }
24205
+ function hasAnswerContent(node2) {
24206
+ const content = node2.event.update.content;
24207
+ return Array.isArray(content) && content.some((block) => isRecord7(block) && (block.type !== "text" || typeof block.text === "string" && block.text.trim().length > 0));
24208
+ }
24209
+ function messageText(node2) {
24210
+ const content = node2.event.update.content;
24211
+ return Array.isArray(content) ? content.flatMap((block) => isRecord7(block) && block.type === "text" && typeof block.text === "string" ? [block.text] : []).join("") : "";
24212
+ }
24213
+ function prepareConversationTurns(transcript, streaming, previousTurns = []) {
24214
+ const entries = Array.isArray(transcript.entries) ? transcript.entries : [];
24215
+ const nodes = entries.map(entryNode);
24216
+ 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 } }] : []);
24217
+ for (const event of foldPreview(terminals))
24218
+ nodes.push({ key: event.id, event, children: [] });
24219
+ 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] : []));
24220
+ const visible = nodes.filter((node2) => !isThought(node2));
24221
+ const roots = attachChildren(visible).filter((node2, index, all) => {
24222
+ const previous = all[index - 1];
24223
+ if (previous?.event.update.sessionUpdate !== "agent_message" || node2.event.update.sessionUpdate !== "agent_message" || !nestedThoughtIds.has(String(node2.event.update.messageId)))
24224
+ return true;
24225
+ const previousText = messageText(previous);
24226
+ return !(previousText.length > 0 && previousText === messageText(node2));
24227
+ });
24228
+ const turns = [];
24229
+ for (const node2 of roots) {
24230
+ const user = node2.event.update.sessionUpdate === "user_message";
24231
+ let turn = turns.at(-1);
24232
+ if (!turn || user) {
24233
+ turn = { key: node2.key, users: [], working: [], activity: { key: node2.key, state: "idle" } };
24234
+ turns.push(turn);
24235
+ }
24236
+ if (user)
24237
+ turn.users.push(node2);
24238
+ else
24239
+ turn.working.push(node2);
24240
+ }
24241
+ const activities = [...transcript.activities ?? []].sort((left, right) => left.firstEntryIndex - right.firstEntryIndex);
24242
+ for (const [turnIndex, turn] of turns.entries()) {
24243
+ const last = turn === turns.at(-1);
24244
+ const firstEntryIndex = turnStart(turn);
24245
+ const next = turns[turnIndex + 1];
24246
+ const nextStart = (next && turnStart(next)) ?? Number.POSITIVE_INFINITY;
24247
+ const runs = firstEntryIndex === void 0 ? [] : activities.filter((activity) => activity.firstEntryIndex >= firstEntryIndex && activity.firstEntryIndex < nextStart);
24248
+ const recorded = runs.at(-1);
24249
+ turn.activity.state = last && transcript.state === "requires_action" ? "requires_action" : last && streaming ? "running" : (
24250
+ // Bytes cut off mid-run are history once the thread is not live; they are not still working.
24251
+ recorded?.state === "running" ? "idle" : recorded?.state ?? "idle"
24252
+ );
24253
+ turn.activity.stopReason = turn.activity.state === "running" ? void 0 : recorded?.stopReason ?? (last ? transcript.stopReason : void 0);
24254
+ const captured = runs.reduce((total, run2) => {
24255
+ const duration3 = run2.startedAt !== void 0 ? Math.max(0, (run2.endedAt ?? run2.updatedAt) - run2.startedAt) : run2.durationMs;
24256
+ return duration3 === void 0 ? total : (total ?? 0) + duration3;
24257
+ }, void 0);
24258
+ if (captured !== void 0)
24259
+ turn.activity.capturedMs = captured;
24260
+ const startedAt = runs.find((run2) => run2.startedAt !== void 0)?.startedAt;
24261
+ if (startedAt !== void 0)
24262
+ turn.activity.startedAt = startedAt;
24263
+ if (turn.activity.state !== "running" && recorded?.endedAt !== void 0)
24264
+ turn.activity.endedAt = recorded.endedAt;
24265
+ turn.activity.neverStarted = recorded?.state === "idle" && recorded.stopReason === "cancelled" && captured === void 0;
24266
+ if (last && streaming && turn.activity.state === "running") {
24267
+ const anchor2 = Math.max(recorded?.startedAt ?? 0, transcript.userMessageAt ?? 0);
24268
+ if (anchor2 > 0)
24269
+ turn.activity.liveStartedAt = anchor2;
24270
+ }
24271
+ const tail = turn.working.reduce((latest, node2) => !latest || (node2.event.seq ?? node2.event.line) > (latest.event.seq ?? latest.event.line) ? node2 : latest, void 0);
24272
+ turn.working = turn.working.filter((node2) => !isThought(node2));
24273
+ 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;
24274
+ if (final)
24275
+ turn.final = final;
24276
+ }
24277
+ const noticesByEntry = /* @__PURE__ */ new Map();
24278
+ for (const notice2 of uniqueNotices(transcript.notices)) {
24279
+ if (notice2.firstEntryIndex === void 0 || !isConversationNotice(notice2))
24280
+ continue;
24281
+ const group = noticesByEntry.get(notice2.firstEntryIndex);
24282
+ if (group)
24283
+ group.push(notice2);
24284
+ else
24285
+ noticesByEntry.set(notice2.firstEntryIndex, [notice2]);
24286
+ }
24287
+ for (const turn of turns) {
24288
+ const firstEntryIndex = turnStart(turn);
24289
+ const notices = firstEntryIndex === void 0 ? void 0 : noticesByEntry.get(firstEntryIndex);
24290
+ if (notices)
24291
+ turn.notices = notices;
24292
+ }
24293
+ const startedTurn = turns[0];
24294
+ if (transcript.cloudStart && startedTurn?.users.length) {
24295
+ startedTurn.cloudStart = transcript.cloudStart;
24296
+ }
24297
+ const previousByKey = new Map(previousTurns.map((turn) => [turn.key, turn]));
24298
+ return turns.map((turn) => retainTurn(turn, previousByKey.get(turn.key)));
24299
+ }
24300
+ function sameNotices(left, right) {
24301
+ if (left === right)
24302
+ return true;
24303
+ if (!left || !right || left.length !== right.length)
24304
+ return false;
24305
+ return left.every((notice2, index) => notice2.kind === right[index].kind && notice2.level === right[index].level && notice2.message === right[index].message);
24306
+ }
24307
+ function sameFields(left, right) {
24308
+ const keys = Object.keys(left);
24309
+ return keys.length === Object.keys(right).length && keys.every((key) => Reflect.get(left, key) === Reflect.get(right, key));
24310
+ }
24311
+ function retainNodes(nodes, previous) {
24312
+ const byKey = new Map(previous.map((node2) => [node2.key, node2]));
24313
+ const retained = nodes.map((node2) => {
24314
+ const before = byKey.get(node2.key);
24315
+ if (!before)
24316
+ return node2;
24317
+ node2.children = retainNodes(node2.children, before.children);
24318
+ 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;
24319
+ });
24320
+ return retained.length === previous.length && retained.every((node2, index) => node2 === previous[index]) ? previous : retained;
24321
+ }
24322
+ function retainTurn(turn, previous) {
24323
+ if (previous) {
24324
+ turn.users = retainNodes(turn.users, previous.users);
24325
+ turn.working = retainNodes(turn.working, previous.working);
24326
+ if (turn.final && previous.final)
24327
+ turn.final = retainNodes([turn.final], [previous.final])[0];
24328
+ if (sameFields(turn.activity, previous.activity))
24329
+ turn.activity = previous.activity;
24330
+ if (sameNotices(turn.notices, previous.notices))
24331
+ turn.notices = previous.notices;
24332
+ if (turn.cloudStart && previous.cloudStart && sameFields(turn.cloudStart, previous.cloudStart))
24333
+ turn.cloudStart = previous.cloudStart;
24334
+ }
24335
+ turn.editedFiles = previous && turn.working === previous.working && turn.activity === previous.activity ? previous.editedFiles : turn.activity.state === "idle" ? collectEditedFiles(turn.working) : [];
24336
+ 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;
24337
+ }
24338
+ function isThought(node2) {
24339
+ return ["agent_thought", "agent_thought_chunk"].includes(node2.event.update.sessionUpdate);
24340
+ }
24341
+ var preparedEntries;
23776
24342
  var init_prepare_conversation_turns = __esm({
23777
24343
  "../shared/dist/agent/acp/presentation/prepare-conversation-turns.js"() {
23778
24344
  "use strict";
24345
+ init_file_edits();
24346
+ init_notice_visibility();
24347
+ init_terminal_events();
24348
+ preparedEntries = /* @__PURE__ */ new WeakMap();
23779
24349
  }
23780
24350
  });
23781
24351
 
@@ -23790,23 +24360,510 @@ var init_event = __esm({
23790
24360
  function isUpdate(update, kind) {
23791
24361
  return update.sessionUpdate === kind;
23792
24362
  }
24363
+ function isContentUpdate(update) {
24364
+ 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";
24365
+ }
24366
+ function isToolUpdate(update) {
24367
+ return update.sessionUpdate === "tool_call_update" || update.sessionUpdate === "tool_call_content_chunk";
24368
+ }
24369
+ var MEDIA_SESSION_UPDATE_KINDS;
23793
24370
  var init_types2 = __esm({
23794
24371
  "../shared/dist/agent/acp/types.js"() {
23795
24372
  "use strict";
24373
+ MEDIA_SESSION_UPDATE_KINDS = /* @__PURE__ */ new Set([
24374
+ "_alan/generated_image",
24375
+ "_alan/session_media"
24376
+ ]);
23796
24377
  }
23797
24378
  });
23798
24379
 
23799
24380
  // ../shared/dist/agent/acp/reduce.js
24381
+ function emptyTranscript() {
24382
+ return { entries: [], state: "idle", notices: [], unknown: [] };
24383
+ }
24384
+ function applySessionEvent(state, event) {
24385
+ applyUpdate(state, event.update);
24386
+ const update = event.update;
24387
+ if (update._meta && typeof update._meta === "object" && "alan.dev/parentToolCallId" in update._meta && typeof update._meta["alan.dev/parentToolCallId"] === "string")
24388
+ return state;
24389
+ if ((update.sessionUpdate === "user_message" || update.sessionUpdate === "user_message_chunk") && Number.isFinite(event.at))
24390
+ state.userMessageAt = event.at;
24391
+ const lifecycle = isUpdate(update, "state_update");
24392
+ const activities = state.activities ?? [];
24393
+ let activity = activities.at(-1);
24394
+ if (lifecycle) {
24395
+ let userIndex = -1;
24396
+ for (let index = state.entries.length - 1; index >= 0; index -= 1) {
24397
+ const entry = state.entries[index];
24398
+ if (entry.kind === "message" && entry.role === "user") {
24399
+ userIndex = index;
24400
+ break;
24401
+ }
24402
+ }
24403
+ if (!activity || activity.endedAt !== void 0 && (update.state === "running" || userIndex > activity.firstEntryIndex)) {
24404
+ const firstEntryIndex = userIndex >= 0 && (!activity || userIndex > activity.firstEntryIndex) ? userIndex : activity ? state.entries.length : 0;
24405
+ activity = { firstEntryIndex, state: update.state, updatedAt: event.at };
24406
+ activities.push(activity);
24407
+ state.activities = activities;
24408
+ }
24409
+ }
24410
+ if (!activity)
24411
+ return state;
24412
+ const usage = isUpdate(update, "usage_update") ? update._meta?.["alan.dev/usage"] : void 0;
24413
+ if (typeof usage === "object" && usage !== null && "durationMs" in usage && typeof usage.durationMs === "number" && Number.isFinite(usage.durationMs))
24414
+ activity.durationMs = Math.max(0, usage.durationMs);
24415
+ if (activity.endedAt === void 0)
24416
+ activity.updatedAt = event.at;
24417
+ if (lifecycle) {
24418
+ activity.state = update.state;
24419
+ activity.stopReason = update.state === "idle" ? update.stopReason ?? void 0 : void 0;
24420
+ if (update.state === "running" && activity.startedAt === void 0)
24421
+ activity.startedAt = event.at;
24422
+ if (update.state === "idle" && activity.endedAt === void 0)
24423
+ activity.endedAt = event.at;
24424
+ }
24425
+ return state;
24426
+ }
24427
+ function entryIndex(state) {
24428
+ const cached2 = entryIndexes.get(state);
24429
+ if (cached2 && cached2.entries === state.entries && cached2.size === state.entries.length && cached2.last === state.entries.at(-1))
24430
+ return cached2;
24431
+ const byKey = /* @__PURE__ */ new Map();
24432
+ for (const entry of state.entries)
24433
+ byKey.set(entryKey(entry), entry);
24434
+ const index = {
24435
+ entries: state.entries,
24436
+ size: state.entries.length,
24437
+ last: state.entries.at(-1),
24438
+ byKey
24439
+ };
24440
+ entryIndexes.set(state, index);
24441
+ return index;
24442
+ }
24443
+ function applyUpdate(state, update) {
24444
+ const index = entryIndex(state);
24445
+ applyOne(state, index.byKey, update);
24446
+ index.size = state.entries.length;
24447
+ index.last = state.entries.at(-1);
24448
+ return state;
24449
+ }
24450
+ function awaitingToolCallIds(meta3) {
24451
+ const ids = meta3?.[AWAITING_TOOL_CALLS_META];
24452
+ return Array.isArray(ids) ? ids.filter((id) => typeof id === "string") : [];
24453
+ }
24454
+ function entryKey(entry) {
24455
+ return entry.kind === "message" ? `m:${entry.role}:${entry.id}` : `t:${entry.id}`;
24456
+ }
24457
+ function applyOne(state, index, update) {
24458
+ state.updateCount = (state.updateCount ?? 0) + 1;
24459
+ if (isContentUpdate(update)) {
24460
+ applyContent(state, index, update);
24461
+ return;
24462
+ }
24463
+ if (isToolUpdate(update)) {
24464
+ applyTool(state, index, update);
24465
+ return;
24466
+ }
24467
+ if (update.sessionUpdate === "_alan/log" || update.sessionUpdate === "_alan/unhandled")
24468
+ return;
24469
+ if (update._meta && typeof update._meta === "object" && "alan.dev/parentToolCallId" in update._meta && typeof update._meta["alan.dev/parentToolCallId"] === "string") {
24470
+ state.unknown.push(update);
24471
+ return;
24472
+ }
24473
+ switch (update.sessionUpdate) {
24474
+ case "state_update": {
24475
+ if (!isUpdate(update, "state_update"))
24476
+ return;
24477
+ if (update.state === "running" && state.state === "idle")
24478
+ delete state.thinkingTokens;
24479
+ state.state = update.state;
24480
+ if (update.state !== "idle")
24481
+ state.stopReason = void 0;
24482
+ else if (update.stopReason)
24483
+ state.stopReason = update.stopReason;
24484
+ if (update.state === "requires_action")
24485
+ state.awaitingToolCallIds = awaitingToolCallIds(update._meta);
24486
+ else
24487
+ delete state.awaitingToolCallIds;
24488
+ if (update.state === "idle")
24489
+ settleOpenToolCalls(state);
24490
+ return;
24491
+ }
24492
+ case "plan_update": {
24493
+ if (!isUpdate(update, "plan_update"))
24494
+ return;
24495
+ state.plan = { planId: update.planId, entries: update.entries };
24496
+ return;
24497
+ }
24498
+ case "usage_update": {
24499
+ if (!isUpdate(update, "usage_update"))
24500
+ return;
24501
+ state.usage = {
24502
+ used: update.used,
24503
+ size: update.size,
24504
+ ...update.cost ? { cost: update.cost } : {}
24505
+ };
24506
+ delete state.thinkingTokens;
24507
+ return;
24508
+ }
24509
+ case "session_info_update": {
24510
+ if (!isUpdate(update, "session_info_update"))
24511
+ return;
24512
+ if (update.title !== void 0)
24513
+ state.title = update.title ?? void 0;
24514
+ return;
24515
+ }
24516
+ case "notice": {
24517
+ if (!isUpdate(update, "notice"))
24518
+ return;
24519
+ const notice2 = {
24520
+ level: update.severity,
24521
+ kind: noticeKind(update.severity, update._meta),
24522
+ message: update.description ? `${update.title}
24523
+ ${update.description}` : update.title,
24524
+ ...update._meta ? { _meta: update._meta } : {}
24525
+ };
24526
+ const seen = state.notices.some((existing) => existing.level === notice2.level && existing.message === notice2.message);
24527
+ if (!seen)
24528
+ state.notices.push(notice2);
24529
+ return;
24530
+ }
24531
+ case "_alan/thinking_tokens": {
24532
+ if (!isUpdate(update, "_alan/thinking_tokens"))
24533
+ return;
24534
+ state.thinkingTokens = update.estimated;
24535
+ return;
24536
+ }
24537
+ // Owned by the tool call that references it, but kept so a terminal-aware
24538
+ // renderer can still consume the raw update.
24539
+ case "terminal_update":
24540
+ case "terminal_output_chunk":
24541
+ state.unknown.push(update);
24542
+ return;
24543
+ // ACP: preserve a variant this build does not know rather than dropping it.
24544
+ default:
24545
+ state.unknown.push(update);
24546
+ }
24547
+ }
24548
+ function noticeKind(severity, meta3) {
24549
+ const kind = meta3?.["alan.dev/noticeKind"];
24550
+ return typeof kind === "string" ? kind : severity;
24551
+ }
24552
+ function applyContent(state, index, update) {
24553
+ const role = ROLE_BY_KIND[update.sessionUpdate];
24554
+ if (!role)
24555
+ return;
24556
+ const key = `m:${role}:${update.messageId}`;
24557
+ let entry = index.get(key);
24558
+ if (!entry) {
24559
+ entry = { kind: "message", id: update.messageId, role, content: [] };
24560
+ index.set(key, entry);
24561
+ state.entries.push(entry);
24562
+ }
24563
+ entry.lastUpdateIndex = state.updateCount;
24564
+ if (update.sessionUpdate.endsWith("_chunk")) {
24565
+ const block = update.content;
24566
+ if (block)
24567
+ entry.content.push(block);
24568
+ } else {
24569
+ const content = update.content;
24570
+ if (content !== void 0) {
24571
+ entry.content = content === null ? [] : Array.isArray(content) ? content : [content];
24572
+ }
24573
+ }
24574
+ if (update._meta !== void 0) {
24575
+ entry._meta = update._meta === null ? void 0 : { ...entry._meta, ...update._meta };
24576
+ }
24577
+ }
24578
+ function isSettled(status) {
24579
+ return SETTLED.has(status);
24580
+ }
24581
+ function outlivesTheTurn(entry) {
24582
+ if (readBackgroundTaskMeta(entry._meta))
24583
+ return true;
24584
+ const input2 = entry.rawInput;
24585
+ return entry.name?.toLowerCase() === "bash" && typeof input2 === "object" && input2 !== null && input2.run_in_background === true;
24586
+ }
24587
+ function settleOpenToolCalls(state) {
24588
+ for (const entry of state.entries) {
24589
+ if (entry.kind !== "tool_call" || isSettled(entry.status))
24590
+ continue;
24591
+ if (outlivesTheTurn(entry))
24592
+ continue;
24593
+ entry.status = "cancelled";
24594
+ }
24595
+ }
24596
+ function applyTool(state, index, update) {
24597
+ const key = `t:${update.toolCallId}`;
24598
+ let entry = index.get(key);
24599
+ if (!entry) {
24600
+ entry = {
24601
+ kind: "tool_call",
24602
+ id: update.toolCallId,
24603
+ toolKind: "other",
24604
+ status: "pending",
24605
+ content: [],
24606
+ locations: []
24607
+ };
24608
+ index.set(key, entry);
24609
+ state.entries.push(entry);
24610
+ }
24611
+ entry.lastUpdateIndex = state.updateCount;
24612
+ if (update.sessionUpdate === "tool_call_content_chunk") {
24613
+ const block = update.content;
24614
+ if (block)
24615
+ entry.content.push(block);
24616
+ return;
24617
+ }
24618
+ const u = update;
24619
+ if (u.name !== void 0)
24620
+ entry.name = u.name ?? void 0;
24621
+ if (u.title !== void 0)
24622
+ entry.title = u.title ?? void 0;
24623
+ if (!entry.title && typeof u.name === "string" && u.name.length > 0)
24624
+ entry.title = u.name;
24625
+ if (u.kind !== void 0)
24626
+ entry.toolKind = u.kind ?? "other";
24627
+ if (u.status !== void 0 && !isSettled(entry.status))
24628
+ entry.status = u.status ?? "pending";
24629
+ if (u.content !== void 0)
24630
+ entry.content = u.content ?? [];
24631
+ if (u.locations !== void 0)
24632
+ entry.locations = u.locations ?? [];
24633
+ if (u.rawInput !== void 0)
24634
+ entry.rawInput = u.rawInput;
24635
+ if (u.rawOutput !== void 0)
24636
+ entry.rawOutput = u.rawOutput;
24637
+ if (u._meta !== void 0) {
24638
+ entry._meta = u._meta === null ? void 0 : { ...entry._meta, ...u._meta };
24639
+ }
24640
+ }
24641
+ function messageText2(entry) {
24642
+ return entry.content.filter((b) => b.type === "text").map((b) => b.text).join("");
24643
+ }
24644
+ var ROLE_BY_KIND, entryIndexes, AWAITING_TOOL_CALLS_META, SETTLED;
23800
24645
  var init_reduce = __esm({
23801
24646
  "../shared/dist/agent/acp/reduce.js"() {
23802
24647
  "use strict";
24648
+ init_background_task();
24649
+ init_types2();
24650
+ ROLE_BY_KIND = {
24651
+ user_message: "user",
24652
+ user_message_chunk: "user",
24653
+ agent_message: "agent",
24654
+ agent_message_chunk: "agent",
24655
+ agent_thought: "thought",
24656
+ agent_thought_chunk: "thought"
24657
+ };
24658
+ entryIndexes = /* @__PURE__ */ new WeakMap();
24659
+ AWAITING_TOOL_CALLS_META = "alan.dev/awaitingToolCallIds";
24660
+ SETTLED = /* @__PURE__ */ new Set(["completed", "failed", "cancelled"]);
23803
24661
  }
23804
24662
  });
23805
24663
 
23806
24664
  // ../shared/dist/agent/acp/conversation-messages.js
24665
+ function compactConversationMessageTurns(turns, keepNewestEntries) {
24666
+ return turns.map((turn, index) => ({
24667
+ ...turn,
24668
+ display: turn.display.map((displayTurn) => {
24669
+ if (!displayTurn.final)
24670
+ return displayTurn;
24671
+ return {
24672
+ ...displayTurn,
24673
+ working: displayTurn.working.map((node2) => node2.key === displayTurn.final?.key ? {
24674
+ ...node2,
24675
+ children: [],
24676
+ event: {
24677
+ ...node2.event,
24678
+ update: { ...node2.event.update, content: [] }
24679
+ }
24680
+ } : node2)
24681
+ };
24682
+ }),
24683
+ state: {
24684
+ ...turn.state,
24685
+ entries: index === 0 && keepNewestEntries ? turn.state.entries.map((entry) => {
24686
+ if (entry.kind === "message")
24687
+ return entry.role === "user" ? entry : { ...entry, content: [] };
24688
+ const ask = isAskUserQuestionTool(entry.title || entry.toolKind, entry.rawInput);
24689
+ return {
24690
+ ...entry,
24691
+ content: [],
24692
+ locations: [],
24693
+ rawInput: ask ? entry.rawInput : void 0,
24694
+ rawOutput: void 0
24695
+ };
24696
+ }) : []
24697
+ }
24698
+ }));
24699
+ }
24700
+ function prepareConversationTurnRead(state) {
24701
+ const prompts = [];
24702
+ const navigation = [];
24703
+ const interactiveTools = [];
24704
+ let modeChange = null;
24705
+ let latestAgentMessageId = null;
24706
+ for (const entry of state.entries) {
24707
+ if (entry.kind === "message" && entry.role === "user") {
24708
+ const meta3 = entry._meta ?? {};
24709
+ if (typeof meta3["alan.dev/parentToolCallId"] !== "string") {
24710
+ const clientMessageId = meta3["alan.dev/clientMessageId"];
24711
+ prompts.push({
24712
+ entryId: entry.id,
24713
+ ...typeof clientMessageId === "string" ? { clientMessageId } : {},
24714
+ content: messageText2(entry),
24715
+ agentMode: typeof meta3["alan.dev/agentMode"] === "string" ? meta3["alan.dev/agentMode"] : null,
24716
+ attachmentIds: Array.isArray(meta3["alan.dev/attachmentIds"]) ? meta3["alan.dev/attachmentIds"] : void 0,
24717
+ references: Array.isArray(meta3["alan.dev/references"]) ? meta3["alan.dev/references"] : void 0
24718
+ });
24719
+ }
24720
+ const title = toPreviewText(messageText2(entry).slice(0, 960).replace(attachmentMentionPattern(), ""), 240);
24721
+ navigation.push({ id: entry.id, title: title || "Message with attachments" });
24722
+ continue;
24723
+ }
24724
+ if (entry.kind === "message" && entry.role === "agent" && navigation.length > 0) {
24725
+ latestAgentMessageId = entry.id;
24726
+ if (typeof entry._meta?.["alan.dev/parentToolCallId"] === "string")
24727
+ continue;
24728
+ const content = messageText2(entry);
24729
+ if (!/\S/.test(content))
24730
+ continue;
24731
+ const preview = toPreviewText(content.slice(0, 960).replace(attachmentMentionPattern(), ""), 240);
24732
+ if (preview)
24733
+ navigation[navigation.length - 1].preview = preview;
24734
+ continue;
24735
+ }
24736
+ if (entry.kind === "message" && entry.role === "agent") {
24737
+ latestAgentMessageId = entry.id;
24738
+ continue;
24739
+ }
24740
+ if (entry.kind !== "tool_call")
24741
+ continue;
24742
+ const name = entry.name || entry.title || entry.toolKind;
24743
+ const responseToolId = entry._meta?.[TRANSCRIPT_TOOL_RESPONSE_ID_META];
24744
+ interactiveTools.push({
24745
+ id: entry.id,
24746
+ name,
24747
+ ...(entry.status === "pending" || entry.status === "in_progress") && {
24748
+ input: entry.rawInput
24749
+ },
24750
+ ...typeof responseToolId === "string" ? { responseToolId } : {}
24751
+ });
24752
+ const toolName2 = (entry.name || entry.title)?.trim().toLowerCase();
24753
+ if (toolName2 === "enterplanmode") {
24754
+ modeChange = "plan";
24755
+ continue;
24756
+ }
24757
+ if (toolName2 !== "exitplanmode")
24758
+ continue;
24759
+ if (entry.status !== "completed" && entry.status !== "failed")
24760
+ continue;
24761
+ const output2 = typeof entry.rawOutput === "string" ? entry.rawOutput : entry.content.flatMap((item) => item.type === "content" && item.content.type === "text" ? [item.content.text] : []).join("\n");
24762
+ const response = output2.trim().toLowerCase();
24763
+ if (response === "accepted" && entry.status === "completed")
24764
+ modeChange = "agent";
24765
+ else if (response === "rejected")
24766
+ modeChange = "plan";
24767
+ }
24768
+ return {
24769
+ entryCount: state.entries.length,
24770
+ latestAgentMessageId,
24771
+ prompts,
24772
+ navigation,
24773
+ modeChange,
24774
+ pendingAsk: findPendingAsk(state.entries),
24775
+ interactiveTools
24776
+ };
24777
+ }
24778
+ function conversationTurnView(ordinal, state, previousDisplay = []) {
24779
+ return {
24780
+ ordinal,
24781
+ state,
24782
+ display: prepareConversationTurns(state, state.state === "running", previousDisplay),
24783
+ read: prepareConversationTurnRead(state)
24784
+ };
24785
+ }
24786
+ function diffArray(previous, next) {
24787
+ const changes = [];
24788
+ for (const [index, value2] of next.entries()) {
24789
+ if (previous[index] !== value2)
24790
+ changes.push({ index, value: value2 });
24791
+ }
24792
+ return { length: next.length, changes };
24793
+ }
24794
+ function stateFields(state) {
24795
+ const { entries: _entries, unknown: _unknown2, presentation: _presentation, ...fields } = state;
24796
+ return fields;
24797
+ }
24798
+ function diffTranscriptState(previous, next) {
24799
+ return {
24800
+ entries: diffArray(previous.entries, next.entries),
24801
+ unknown: diffArray(previous.unknown, next.unknown),
24802
+ fields: stateFields(next)
24803
+ };
24804
+ }
24805
+ function createLiveTurnFrameEncoder() {
24806
+ const sent = /* @__PURE__ */ new Map();
24807
+ return (ordinal, state) => {
24808
+ const previous = sent.get(ordinal);
24809
+ sent.delete(ordinal);
24810
+ sent.set(ordinal, state);
24811
+ for (const oldest of sent.keys()) {
24812
+ if (sent.size <= SENT_LIVE_TURNS)
24813
+ break;
24814
+ sent.delete(oldest);
24815
+ }
24816
+ return previous ? { kind: "patch", ordinal, patch: diffTranscriptState(previous, state) } : { kind: "snapshot", ordinal, state };
24817
+ };
24818
+ }
24819
+ function isRecord8(value2) {
24820
+ return value2 !== null && typeof value2 === "object" && !Array.isArray(value2);
24821
+ }
24822
+ function isTranscriptState(value2) {
24823
+ return isRecord8(value2) && typeof value2.state === "string" && Array.isArray(value2.entries) && Array.isArray(value2.notices) && Array.isArray(value2.unknown);
24824
+ }
24825
+ function isArrayPatch(value2) {
24826
+ return isRecord8(value2) && Number.isSafeInteger(value2.length) && Array.isArray(value2.changes) && value2.changes.every((change) => isRecord8(change) && Number.isSafeInteger(change.index) && "value" in change);
24827
+ }
24828
+ function isTranscriptStatePatch(value2) {
24829
+ return isRecord8(value2) && isArrayPatch(value2.entries) && isArrayPatch(value2.unknown) && isRecord8(value2.fields) && typeof value2.fields.state === "string" && Array.isArray(value2.fields.notices);
24830
+ }
24831
+ function isLiveTurnFrame(value2) {
24832
+ if (!isRecord8(value2) || !Number.isSafeInteger(value2.ordinal))
24833
+ return false;
24834
+ if (value2.kind === "snapshot")
24835
+ return isTranscriptState(value2.state);
24836
+ return value2.kind === "patch" && isTranscriptStatePatch(value2.patch);
24837
+ }
24838
+ function isPendingAsk(value2) {
24839
+ 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")));
24840
+ }
24841
+ function isInteractiveTool(value2) {
24842
+ return isRecord8(value2) && typeof value2.id === "string" && typeof value2.name === "string" && (value2.responseToolId === void 0 || typeof value2.responseToolId === "string");
24843
+ }
24844
+ function isConversationTurnRead(value2) {
24845
+ 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);
24846
+ }
24847
+ function isConversationMessageTurn(value2) {
24848
+ 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));
24849
+ }
24850
+ function isConversationMessagesPage(value2) {
24851
+ 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);
24852
+ }
24853
+ var LIVE_TURN_FRAMES, LIVE_TURN_EVENT, SENT_LIVE_TURNS;
23807
24854
  var init_conversation_messages = __esm({
23808
24855
  "../shared/dist/agent/acp/conversation-messages.js"() {
23809
24856
  "use strict";
24857
+ init_agent();
24858
+ init_attachment_mention();
24859
+ init_preview();
24860
+ init_ask();
24861
+ init_prepare_conversation_turns();
24862
+ init_reduce();
24863
+ init_transcript_http();
24864
+ LIVE_TURN_FRAMES = "patch";
24865
+ LIVE_TURN_EVENT = "live_turn";
24866
+ SENT_LIVE_TURNS = 8;
23810
24867
  }
23811
24868
  });
23812
24869
 
@@ -23832,9 +24889,172 @@ var init_transcript_byte_decoder = __esm({
23832
24889
  });
23833
24890
 
23834
24891
  // ../shared/dist/agent/acp/transcript-fold.js
24892
+ function isRecord9(value2) {
24893
+ return value2 !== null && typeof value2 === "object" && !Array.isArray(value2);
24894
+ }
24895
+ function scopedContent(value2, turnId) {
24896
+ if (!Array.isArray(value2))
24897
+ return value2;
24898
+ return value2.map((block) => isRecord9(block) && block.type === "terminal" && typeof block.terminalId === "string" ? { ...block, terminalId: `${turnId}:${block.terminalId}` } : block);
24899
+ }
24900
+ function scopeTranscriptEvent(value2) {
24901
+ if (!isRecord9(value2) || !Number.isSafeInteger(value2.seq) || !Number.isFinite(value2.at))
24902
+ return null;
24903
+ if (!isRecord9(value2.update) || typeof value2.update.sessionUpdate !== "string")
24904
+ return null;
24905
+ const update = value2.update;
24906
+ const turnId = typeof value2.turnId === "string" ? value2.turnId : void 0;
24907
+ const event = {
24908
+ seq: Number(value2.seq),
24909
+ at: Number(value2.at),
24910
+ ...typeof value2.sessionId === "string" ? { sessionId: value2.sessionId } : {},
24911
+ update
24912
+ };
24913
+ if (!turnId)
24914
+ return event;
24915
+ const meta3 = isRecord9(update._meta) ? { ...update._meta } : {};
24916
+ const parent = meta3["alan.dev/parentToolCallId"];
24917
+ if (typeof parent === "string")
24918
+ meta3["alan.dev/parentToolCallId"] = `${turnId}:${parent}`;
24919
+ if (typeof update.toolCallId === "string")
24920
+ meta3[TRANSCRIPT_TOOL_RESPONSE_ID_META] = update.toolCallId;
24921
+ if (typeof update.sessionUpdate === "string" && MEDIA_SESSION_UPDATE_KINDS.has(update.sessionUpdate))
24922
+ meta3[TRANSCRIPT_TURN_ID_META] = turnId;
24923
+ const scoped = { ...update, _meta: meta3 };
24924
+ for (const key of ["messageId", "toolCallId", "terminalId", "planId"]) {
24925
+ if (typeof update[key] === "string")
24926
+ scoped[key] = `${turnId}:${update[key]}`;
24927
+ }
24928
+ if ("content" in update)
24929
+ scoped.content = scopedContent(update.content, turnId);
24930
+ return { ...event, update: scoped };
24931
+ }
24932
+ function placeMessage(cache2, message2, updateOffset, entryOffset, startsWithPrompt) {
24933
+ const cached2 = cache2.get(message2.messageId);
24934
+ const source = message2.state;
24935
+ const sameSource = cached2?.source === source;
24936
+ if (sameSource && cached2.updateCount === source.updateCount && cached2.updateOffset === updateOffset && cached2.entryOffset === entryOffset && cached2.startsWithPrompt === startsWithPrompt)
24937
+ return cached2.state;
24938
+ const replacedEntries = cached2 && !sameSource ? cached2.source.entries : void 0;
24939
+ const entries = source.entries.map((entry, index) => {
24940
+ const previous = cached2?.state.entries[index];
24941
+ const lastUpdateIndex = entry.lastUpdateIndex === void 0 ? void 0 : entry.lastUpdateIndex + updateOffset;
24942
+ if (previous && cached2.updateOffset === updateOffset && previous.id === entry.id && previous.kind === entry.kind && (sameSource ? entry.lastUpdateIndex !== void 0 && previous.lastUpdateIndex === lastUpdateIndex : replacedEntries?.[index] === entry))
24943
+ return previous;
24944
+ return entry.kind === "message" ? { ...entry, lastUpdateIndex, content: [...entry.content] } : {
24945
+ ...entry,
24946
+ lastUpdateIndex,
24947
+ content: [...entry.content],
24948
+ locations: [...entry.locations]
24949
+ };
24950
+ });
24951
+ const state = {
24952
+ ...source,
24953
+ entries,
24954
+ notices: [...source.notices],
24955
+ unknown: [...source.unknown],
24956
+ ...source.activities ? {
24957
+ activities: source.activities.map((activity) => ({
24958
+ ...activity,
24959
+ firstEntryIndex: entryOffset + activity.firstEntryIndex - (startsWithPrompt && activity.firstEntryIndex === 0 ? 1 : 0)
24960
+ }))
24961
+ } : {}
24962
+ };
24963
+ cache2.set(message2.messageId, {
24964
+ source,
24965
+ updateCount: source.updateCount,
24966
+ updateOffset,
24967
+ entryOffset,
24968
+ startsWithPrompt,
24969
+ state
24970
+ });
24971
+ return state;
24972
+ }
24973
+ function anchoredUpdateOffset(ordered, cache2) {
24974
+ let natural = 0;
24975
+ for (const message2 of ordered) {
24976
+ const placed = cache2.get(message2.messageId);
24977
+ if (placed)
24978
+ return natural - placed.updateOffset;
24979
+ natural += message2.state.updateCount ?? 0;
24980
+ }
24981
+ return 0;
24982
+ }
24983
+ function mergeTranscriptMessages(messages, cache2) {
24984
+ const merged = emptyTranscript();
24985
+ const ordered = [...messages].sort((left, right) => (left.turnOrdinal ?? 0) - (right.turnOrdinal ?? 0) || left.messageId.localeCompare(right.messageId));
24986
+ let updateOffset = -anchoredUpdateOffset(ordered, cache2);
24987
+ const seenToolIds = /* @__PURE__ */ new Set();
24988
+ const seenNotices = /* @__PURE__ */ new Set();
24989
+ for (const message2 of ordered) {
24990
+ const entryOffset = merged.entries.length;
24991
+ const previous = merged.entries.at(-1);
24992
+ const startsWithPrompt = message2.role !== "user" && previous?.kind === "message" && previous.role === "user";
24993
+ const state = placeMessage(cache2, message2, updateOffset, entryOffset, startsWithPrompt);
24994
+ const removedBefore = [0];
24995
+ const duplicateToolIds = /* @__PURE__ */ new Set();
24996
+ for (const entry of state.entries) {
24997
+ const parentId = entry._meta?.["alan.dev/parentToolCallId"];
24998
+ const rawId = entry._meta?.[TRANSCRIPT_TOOL_RESPONSE_ID_META];
24999
+ const providerEvent = entry._meta?.["alan.dev/providerEvent"];
25000
+ const providerEventId = providerEvent && typeof providerEvent === "object" && "id" in providerEvent ? providerEvent.id : void 0;
25001
+ const toolId = entry.kind === "tool_call" && typeof rawId === "string" && typeof providerEventId === "string" ? `${rawId}:${providerEventId}` : void 0;
25002
+ const duplicate = toolId !== void 0 && seenToolIds.has(toolId) || typeof parentId === "string" && duplicateToolIds.has(parentId);
25003
+ if (!duplicate) {
25004
+ merged.entries.push(entry);
25005
+ if (toolId)
25006
+ seenToolIds.add(toolId);
25007
+ }
25008
+ if (duplicate && toolId)
25009
+ duplicateToolIds.add(entry.id);
25010
+ removedBefore.push((removedBefore.at(-1) ?? 0) + Number(duplicate));
25011
+ }
25012
+ if (state.activities?.length) {
25013
+ merged.activities ??= [];
25014
+ merged.activities.push(...state.activities.map((activity, index) => ({
25015
+ ...activity,
25016
+ firstEntryIndex: activity.firstEntryIndex - (removedBefore[message2.state.activities?.[index]?.firstEntryIndex ?? 0] ?? 0)
25017
+ })));
25018
+ }
25019
+ for (const notice2 of state.notices) {
25020
+ const key = JSON.stringify([notice2.level, notice2.message]);
25021
+ if (seenNotices.has(key))
25022
+ continue;
25023
+ seenNotices.add(key);
25024
+ merged.notices.push({
25025
+ ...notice2,
25026
+ firstEntryIndex: startsWithPrompt ? entryOffset - 1 : entryOffset
25027
+ });
25028
+ }
25029
+ merged.unknown.push(...state.unknown);
25030
+ if (state.userMessageAt !== void 0)
25031
+ merged.userMessageAt = Math.max(merged.userMessageAt ?? state.userMessageAt, state.userMessageAt);
25032
+ if (message2.role !== "user") {
25033
+ merged.state = state.state;
25034
+ merged.stopReason = state.stopReason;
25035
+ merged.thinkingTokens = state.thinkingTokens;
25036
+ if (state.awaitingToolCallIds)
25037
+ merged.awaitingToolCallIds = state.awaitingToolCallIds;
25038
+ else
25039
+ delete merged.awaitingToolCallIds;
25040
+ }
25041
+ if (state.plan)
25042
+ merged.plan = state.plan;
25043
+ if (state.usage)
25044
+ merged.usage = state.usage;
25045
+ if (state.title)
25046
+ merged.title = state.title;
25047
+ updateOffset += state.updateCount ?? 0;
25048
+ }
25049
+ merged.updateCount = updateOffset;
25050
+ return merged;
25051
+ }
23835
25052
  var init_transcript_fold = __esm({
23836
25053
  "../shared/dist/agent/acp/transcript-fold.js"() {
23837
25054
  "use strict";
25055
+ init_reduce();
25056
+ init_transcript_http();
25057
+ init_types2();
23838
25058
  }
23839
25059
  });
23840
25060
 
@@ -24101,7 +25321,7 @@ function withoutInlineMedia(update) {
24101
25321
  ...nextRawOutput === rawOutput ? {} : { rawOutput: nextRawOutput }
24102
25322
  };
24103
25323
  }
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;
25324
+ 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
25325
  var init_chunk_UGRKZTAD = __esm({
24106
25326
  "../agent-core/dist/chunk-UGRKZTAD.js"() {
24107
25327
  "use strict";
@@ -24119,7 +25339,7 @@ var init_chunk_UGRKZTAD = __esm({
24119
25339
  NOTICE_KIND_META = "alan.dev/noticeKind";
24120
25340
  ASK_USER_QUESTIONS_META = "alan.dev/askUserQuestions";
24121
25341
  USER_ANSWER_META = "alan.dev/userAnswer";
24122
- AWAITING_TOOL_CALLS_META = "alan.dev/awaitingToolCallIds";
25342
+ AWAITING_TOOL_CALLS_META2 = "alan.dev/awaitingToolCallIds";
24123
25343
  EXIT_PLAN_MODE_INPUT_META = "alan.dev/exitPlanModeInput";
24124
25344
  BACKGROUND_TASK_META = BACKGROUND_TASK_META_KEY;
24125
25345
  TASK_PROGRESS_META = "alan.dev/taskProgress";
@@ -24893,7 +26113,7 @@ var init_chunk_54ZRJOQP = __esm({
24893
26113
  }
24894
26114
  });
24895
26115
 
24896
- // ../agent-core/dist/chunk-YPYC4VBL.js
26116
+ // ../agent-core/dist/chunk-KHYYC5IN.js
24897
26117
  function collectStrings(value2, out) {
24898
26118
  if (typeof value2 === "string") out.push(value2);
24899
26119
  else if (Array.isArray(value2)) for (const item of value2) collectStrings(item, out);
@@ -25263,12 +26483,12 @@ function silentStartError(name, timeoutMs) {
25263
26483
  };
25264
26484
  }
25265
26485
  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"() {
26486
+ var init_chunk_KHYYC5IN = __esm({
26487
+ "../agent-core/dist/chunk-KHYYC5IN.js"() {
25268
26488
  "use strict";
25269
26489
  init_chunk_UGRKZTAD();
25270
26490
  init_chunk_54ZRJOQP();
25271
- init_chunk_J4T6L5LX();
26491
+ init_chunk_M6YHY2EZ();
25272
26492
  init_chunk_YXWJW7I5();
25273
26493
  import_crypto3 = require("crypto");
25274
26494
  import_fs4 = require("fs");
@@ -26759,7 +27979,7 @@ function launcherLabel(update) {
26759
27979
  const description = asRecord(update.rawInput)?.description;
26760
27980
  return nonEmpty(description) ?? nonEmpty(update.title);
26761
27981
  }
26762
- function isSettled(update) {
27982
+ function isSettled2(update) {
26763
27983
  return update.status === "completed" || update.status === "failed" || update.status === "cancelled";
26764
27984
  }
26765
27985
  function isRunningTask(record2) {
@@ -26931,7 +28151,10 @@ function classifyResultError(event, context) {
26931
28151
  if (classified.errorKind !== "unknown_cli_error" || !isApiError) return classified;
26932
28152
  return { ...specForErrorKind("provider_error"), message: classified.message };
26933
28153
  }
26934
- function isSettled2(update) {
28154
+ function isIdleUpdate(update) {
28155
+ return isUpdate(update, "state_update") && update.state === "idle";
28156
+ }
28157
+ function isSettled22(update) {
26935
28158
  return update.status === "completed" || update.status === "failed" || update.status === "cancelled";
26936
28159
  }
26937
28160
  function parentToolUseId(event) {
@@ -27359,11 +28582,11 @@ var init_claude = __esm({
27359
28582
  "../agent-core/dist/providers/claude.js"() {
27360
28583
  "use strict";
27361
28584
  init_chunk_DALFHI4B();
27362
- init_chunk_YPYC4VBL();
28585
+ init_chunk_KHYYC5IN();
27363
28586
  init_chunk_UGRKZTAD();
27364
28587
  init_chunk_54ZRJOQP();
27365
28588
  init_chunk_J2KTV5FP();
27366
- init_chunk_J4T6L5LX();
28589
+ init_chunk_M6YHY2EZ();
27367
28590
  init_chunk_ITTV3UIM();
27368
28591
  init_chunk_YXWJW7I5();
27369
28592
  init_effort();
@@ -27520,7 +28743,7 @@ var init_claude = __esm({
27520
28743
  if (!record2) return update;
27521
28744
  const remembered = record2.meta.label ?? this.#labels.get(update.toolCallId);
27522
28745
  if (!record2.meta.label && remembered) record2.meta = { ...record2.meta, label: remembered };
27523
- if (isSettled(update) && record2.meta.kind === "agent" && isRunningTask(record2)) {
28746
+ if (isSettled2(update) && record2.meta.kind === "agent" && isRunningTask(record2)) {
27524
28747
  this.settle(record2, update.status ?? void 0, update.status !== "completed");
27525
28748
  }
27526
28749
  return { ...update, _meta: { ...update._meta, [BACKGROUND_TASK_META_KEY]: record2.meta } };
@@ -27667,6 +28890,7 @@ var init_claude = __esm({
27667
28890
  #failure;
27668
28891
  #authFailure;
27669
28892
  #resultSeen = false;
28893
+ #heldIdle;
27670
28894
  constructor(options = {}) {
27671
28895
  this.#options = options;
27672
28896
  this.taskRecords = options.taskRecords ?? new TaskRecords(options.now ?? (() => systemClock2.now()));
@@ -27714,7 +28938,17 @@ var init_claude = __esm({
27714
28938
  readEvent(event) {
27715
28939
  const parsed = this.#revise(parseClaudeEvent(event, this.grammar), event);
27716
28940
  parsed.push(...this.#handle(event));
27717
- const updates = parsed.map((update) => this.taskRecords.stamp(update));
28941
+ const kept = parsed.filter((update) => {
28942
+ if (!isIdleUpdate(update)) return true;
28943
+ if (this.#finalized) return true;
28944
+ this.#heldIdle = update;
28945
+ return false;
28946
+ });
28947
+ if (this.#finalized && this.#heldIdle !== void 0) {
28948
+ if (!kept.some(isIdleUpdate)) kept.push(this.#heldIdle);
28949
+ this.#heldIdle = void 0;
28950
+ }
28951
+ const updates = kept.map((update) => this.taskRecords.stamp(update));
27718
28952
  for (const update of updates) this.#applyRunState(update);
27719
28953
  return updates;
27720
28954
  }
@@ -27941,7 +29175,7 @@ var init_claude = __esm({
27941
29175
  this.#announced.add(id);
27942
29176
  if (isLauncher) this.#registerLauncher(update, meta3);
27943
29177
  }
27944
- if (isLauncher && isSettled2(update)) this.tasks.clear([id]);
29178
+ if (isLauncher && isSettled22(update)) this.tasks.clear([id]);
27945
29179
  }
27946
29180
  #registerLauncher(update, meta3) {
27947
29181
  this.tasks.registerLauncher(update.toolCallId);
@@ -30136,11 +31370,11 @@ var init_codex = __esm({
30136
31370
  "../agent-core/dist/providers/codex.js"() {
30137
31371
  "use strict";
30138
31372
  init_chunk_DALFHI4B();
30139
- init_chunk_YPYC4VBL();
31373
+ init_chunk_KHYYC5IN();
30140
31374
  init_chunk_UGRKZTAD();
30141
31375
  init_chunk_54ZRJOQP();
30142
31376
  init_chunk_J2KTV5FP();
30143
- init_chunk_J4T6L5LX();
31377
+ init_chunk_M6YHY2EZ();
30144
31378
  init_chunk_ITTV3UIM();
30145
31379
  init_chunk_YXWJW7I5();
30146
31380
  import_fs6 = require("fs");
@@ -41406,10 +42640,10 @@ var require_tar_stream = __commonJS({
41406
42640
  var init_dist = __esm({
41407
42641
  "../agent-core/dist/index.js"() {
41408
42642
  "use strict";
41409
- init_chunk_YPYC4VBL();
42643
+ init_chunk_KHYYC5IN();
41410
42644
  init_chunk_UGRKZTAD();
41411
42645
  init_chunk_54ZRJOQP();
41412
- init_chunk_J4T6L5LX();
42646
+ init_chunk_M6YHY2EZ();
41413
42647
  init_chunk_YXWJW7I5();
41414
42648
  }
41415
42649
  });
@@ -41645,7 +42879,7 @@ function isRunning(task) {
41645
42879
  return task.meta.status === "running" || task.meta.status === "stopping";
41646
42880
  }
41647
42881
  function isPlanStatus(value2) {
41648
- return STATUSES.has(value2);
42882
+ return STATUSES2.has(value2);
41649
42883
  }
41650
42884
  function todoEntries2(todos) {
41651
42885
  return asArray(todos).flatMap((raw) => {
@@ -42149,15 +43383,15 @@ async function acpTurnInput(run2, context) {
42149
43383
  ...encoded.length ? { images: encoded, imagePaths: images.map((image) => image.path) } : {}
42150
43384
  };
42151
43385
  }
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;
43386
+ 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
43387
  var init_acp3 = __esm({
42154
43388
  "../agent-core/dist/providers/acp.js"() {
42155
43389
  "use strict";
42156
- init_chunk_YPYC4VBL();
43390
+ init_chunk_KHYYC5IN();
42157
43391
  init_chunk_UGRKZTAD();
42158
43392
  init_chunk_54ZRJOQP();
42159
43393
  init_chunk_J2KTV5FP();
42160
- init_chunk_J4T6L5LX();
43394
+ init_chunk_M6YHY2EZ();
42161
43395
  init_chunk_ITTV3UIM();
42162
43396
  init_chunk_YXWJW7I5();
42163
43397
  import_promises48 = require("fs/promises");
@@ -42364,7 +43598,7 @@ var init_acp3 = __esm({
42364
43598
  }
42365
43599
  };
42366
43600
  CURSOR_CREATE_PLAN = "cursor/create_plan";
42367
- STATUSES = /* @__PURE__ */ new Set(["pending", "in_progress", "completed", "cancelled"]);
43601
+ STATUSES2 = /* @__PURE__ */ new Set(["pending", "in_progress", "completed", "cancelled"]);
42368
43602
  READ_KINDS = /* @__PURE__ */ new Set(["read", "search", "think", "fetch"]);
42369
43603
  ALLOW_KINDS = ["allow_once", "allow", "allow_always"];
42370
43604
  REJECT_KINDS = ["reject_once", "reject", "deny", "reject_always"];
@@ -43038,15 +44272,16 @@ function createPersistentDriver(provider4, options) {
43038
44272
  return void 0;
43039
44273
  };
43040
44274
  const resumeNotice = (spec, session, sink) => {
44275
+ if (spec.resumeFallbackContext) {
44276
+ log.info("holder.session_resume_fallback", { harness: provider4.harness, runId: spec.runId });
44277
+ return { session, contextPrefix: spec.resumeFallbackContext };
44278
+ }
43041
44279
  sink.onEvent({
43042
44280
  seq: 0,
43043
44281
  at: clock.now(),
43044
44282
  update: noticeUpdate("warning", "session_resume_failed", RESUME_UNAVAILABLE)
43045
44283
  });
43046
- return {
43047
- session,
43048
- ...spec.resumeFallbackContext ? { contextPrefix: spec.resumeFallbackContext } : {}
43049
- };
44284
+ return { session };
43050
44285
  };
43051
44286
  const managedMcpAccess = async (signal) => {
43052
44287
  const managed = options.managedMcp;
@@ -43121,6 +44356,7 @@ function createPersistentDriver(provider4, options) {
43121
44356
  };
43122
44357
  const _events = __using(_stack, session.onEvent(forward));
43123
44358
  live.turn = turn;
44359
+ record2({ sessionUpdate: "state_update", state: "running" });
43124
44360
  if (session.pid !== void 0) sink.onSpawned(session.pid);
43125
44361
  const onAbort = () => {
43126
44362
  void session.cancel();
@@ -43231,7 +44467,7 @@ function awaitingUpdate(waiting) {
43231
44467
  return {
43232
44468
  sessionUpdate: "state_update",
43233
44469
  state: "requires_action",
43234
- _meta: { [AWAITING_TOOL_CALLS_META]: [...waiting] }
44470
+ _meta: { [AWAITING_TOOL_CALLS_META2]: [...waiting] }
43235
44471
  };
43236
44472
  }
43237
44473
  var RESUME_UNAVAILABLE;
@@ -43857,11 +45093,11 @@ var import_http10, import_crypto13, import_promises50, import_path10, import_pat
43857
45093
  var init_opencode = __esm({
43858
45094
  "../agent-core/dist/providers/opencode.js"() {
43859
45095
  "use strict";
43860
- init_chunk_YPYC4VBL();
45096
+ init_chunk_KHYYC5IN();
43861
45097
  init_chunk_UGRKZTAD();
43862
45098
  init_chunk_54ZRJOQP();
43863
45099
  init_chunk_J2KTV5FP();
43864
- init_chunk_J4T6L5LX();
45100
+ init_chunk_M6YHY2EZ();
43865
45101
  init_chunk_ITTV3UIM();
43866
45102
  init_chunk_YXWJW7I5();
43867
45103
  import_http10 = require("http");
@@ -45052,7 +46288,7 @@ function createAlanCodeHolderDriver(options) {
45052
46288
  open: open6,
45053
46289
  turnInput: async (spec, inputs, contextPrefix) => openCodeTurnInput(spec, {
45054
46290
  attachments: inputs.attachments,
45055
- skills: [],
46291
+ skills: inputs.skills,
45056
46292
  ...contextPrefix === void 0 ? {} : { contextPrefix }
45057
46293
  })
45058
46294
  },
@@ -45134,7 +46370,7 @@ __export(codex_exports, {
45134
46370
  createCodexHolderDriver: () => createCodexHolderDriver
45135
46371
  });
45136
46372
  function sha2563(value2) {
45137
- return (0, import_node_crypto25.createHash)("sha256").update(value2).digest("hex");
46373
+ return (0, import_node_crypto26.createHash)("sha256").update(value2).digest("hex");
45138
46374
  }
45139
46375
  function createCodexLogin(broker) {
45140
46376
  const state = {};
@@ -45209,11 +46445,11 @@ function createCodexHolderDriver(options) {
45209
46445
  }
45210
46446
  );
45211
46447
  }
45212
- var import_node_crypto25;
46448
+ var import_node_crypto26;
45213
46449
  var init_codex2 = __esm({
45214
46450
  "src/holder/drivers/codex.ts"() {
45215
46451
  "use strict";
45216
- import_node_crypto25 = require("crypto");
46452
+ import_node_crypto26 = require("crypto");
45217
46453
  init_dist();
45218
46454
  init_codex();
45219
46455
  init_persistent();
@@ -45665,11 +46901,11 @@ var import_crypto15, import_promises51, FACTORY_API_VERSION, FACTORY_PROTOCOL_VE
45665
46901
  var init_droid = __esm({
45666
46902
  "../agent-core/dist/providers/droid.js"() {
45667
46903
  "use strict";
45668
- init_chunk_YPYC4VBL();
46904
+ init_chunk_KHYYC5IN();
45669
46905
  init_chunk_UGRKZTAD();
45670
46906
  init_chunk_54ZRJOQP();
45671
46907
  init_chunk_J2KTV5FP();
45672
- init_chunk_J4T6L5LX();
46908
+ init_chunk_M6YHY2EZ();
45673
46909
  init_chunk_ITTV3UIM();
45674
46910
  init_chunk_YXWJW7I5();
45675
46911
  init_runtime_v2();
@@ -46068,7 +47304,7 @@ function createDroidHolderDriver(options) {
46068
47304
  },
46069
47305
  turnInput: (spec, inputs, contextPrefix) => droidTurnInput(spec, {
46070
47306
  attachments: inputs.attachments,
46071
- skills: [],
47307
+ skills: inputs.skills,
46072
47308
  ...contextPrefix === void 0 ? {} : { contextPrefix }
46073
47309
  })
46074
47310
  },
@@ -46116,7 +47352,7 @@ function createOpenCodeHolderDriver(options) {
46116
47352
  },
46117
47353
  turnInput: async (spec, inputs, contextPrefix) => openCodeTurnInput(spec, {
46118
47354
  attachments: inputs.attachments,
46119
- skills: [],
47355
+ skills: inputs.skills,
46120
47356
  ...contextPrefix === void 0 ? {} : { contextPrefix }
46121
47357
  })
46122
47358
  },
@@ -46768,10 +48004,10 @@ var init_antigravity = __esm({
46768
48004
  "../agent-core/dist/providers/antigravity.js"() {
46769
48005
  "use strict";
46770
48006
  init_chunk_DALFHI4B();
46771
- init_chunk_YPYC4VBL();
48007
+ init_chunk_KHYYC5IN();
46772
48008
  init_chunk_UGRKZTAD();
46773
48009
  init_chunk_54ZRJOQP();
46774
- init_chunk_J4T6L5LX();
48010
+ init_chunk_M6YHY2EZ();
46775
48011
  init_chunk_ITTV3UIM();
46776
48012
  init_chunk_YXWJW7I5();
46777
48013
  import_promises52 = require("fs/promises");
@@ -47472,11 +48708,11 @@ var import_promises53, import_path15, import_crypto17, COMMAND_CODE_GRAMMAR_NAME
47472
48708
  var init_command_code = __esm({
47473
48709
  "../agent-core/dist/providers/command-code.js"() {
47474
48710
  "use strict";
47475
- init_chunk_YPYC4VBL();
48711
+ init_chunk_KHYYC5IN();
47476
48712
  init_chunk_UGRKZTAD();
47477
48713
  init_chunk_54ZRJOQP();
47478
48714
  init_chunk_J2KTV5FP();
47479
- init_chunk_J4T6L5LX();
48715
+ init_chunk_M6YHY2EZ();
47480
48716
  init_chunk_ITTV3UIM();
47481
48717
  init_chunk_YXWJW7I5();
47482
48718
  import_promises53 = require("fs/promises");
@@ -48098,7 +49334,7 @@ var require_XMLHttpRequest = __commonJS({
48098
49334
  "use strict";
48099
49335
  var fs = require("fs");
48100
49336
  var Url = require("url");
48101
- var spawn11 = require("child_process").spawn;
49337
+ var spawn10 = require("child_process").spawn;
48102
49338
  module2.exports = XMLHttpRequest3;
48103
49339
  XMLHttpRequest3.XMLHttpRequest = XMLHttpRequest3;
48104
49340
  function XMLHttpRequest3(opts) {
@@ -48394,7 +49630,7 @@ var require_XMLHttpRequest = __commonJS({
48394
49630
  var syncFile = ".node-xmlhttprequest-sync-" + process.pid;
48395
49631
  fs.writeFileSync(syncFile, "", "utf8");
48396
49632
  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]);
49633
+ var syncProc = spawn10(process.argv[0], ["-e", execString]);
48398
49634
  var statusText;
48399
49635
  while (fs.existsSync(syncFile)) {
48400
49636
  }
@@ -52875,7 +54111,7 @@ var require_websocket_server = __commonJS({
52875
54111
  // package.json
52876
54112
  var package_default = {
52877
54113
  name: "@alan-ai-hq/agent-manager",
52878
- version: "0.1.137",
54114
+ version: "0.1.139",
52879
54115
  private: true,
52880
54116
  type: "module",
52881
54117
  description: "Alan machine runtime (alan-agent): identity, link, reconciler, session holders, run log, uploader, local API",
@@ -52924,8 +54160,8 @@ var package_default = {
52924
54160
  };
52925
54161
 
52926
54162
  // src/cli/commands/compat.ts
52927
- var import_node_crypto30 = require("crypto");
52928
- var import_promises65 = require("fs/promises");
54163
+ var import_node_crypto31 = require("crypto");
54164
+ var import_promises66 = require("fs/promises");
52929
54165
  init_runtime_v2();
52930
54166
  init_zod();
52931
54167
 
@@ -53769,7 +55005,8 @@ var openTurnResponseSchema = external_exports.object({
53769
55005
  runId: external_exports.string().min(1),
53770
55006
  userMessageId: external_exports.string().min(1),
53771
55007
  assistantMessageId: external_exports.string().min(1),
53772
- created: external_exports.boolean()
55008
+ created: external_exports.boolean(),
55009
+ turnOrdinals: external_exports.object({ user: external_exports.number().int().nonnegative(), assistant: external_exports.number().int().nonnegative() }).optional()
53773
55010
  });
53774
55011
  var errorBodySchema2 = external_exports.object({ code: external_exports.string() });
53775
55012
  function createNativeSessionsClient({
@@ -54961,7 +56198,7 @@ async function push(context, request2) {
54961
56198
  var import_node_child_process = require("child_process");
54962
56199
 
54963
56200
  // ../agent-core/dist/process.js
54964
- init_chunk_J4T6L5LX();
56201
+ init_chunk_M6YHY2EZ();
54965
56202
  init_chunk_YXWJW7I5();
54966
56203
 
54967
56204
  // src/capabilities/git/run-git.ts
@@ -55969,6 +57206,7 @@ function markVersionInUse(bundlePath) {
55969
57206
  }
55970
57207
 
55971
57208
  // src/platform/instance-lock.ts
57209
+ var import_node_crypto7 = require("crypto");
55972
57210
  var import_node_fs5 = require("fs");
55973
57211
  var import_promises15 = require("fs/promises");
55974
57212
  var import_node_path10 = require("path");
@@ -55997,17 +57235,22 @@ function inodeOf(path4) {
55997
57235
  }
55998
57236
  }
55999
57237
  function tryCreate(path4, self) {
57238
+ const staged = `${path4}.${(0, import_node_crypto7.randomUUID)()}.candidate`;
56000
57239
  try {
56001
- const fd = (0, import_node_fs5.openSync)(path4, "wx", 384);
57240
+ const fd = (0, import_node_fs5.openSync)(staged, "wx", 384);
56002
57241
  try {
56003
57242
  (0, import_node_fs5.writeSync)(fd, JSON.stringify(self));
56004
57243
  } finally {
56005
57244
  (0, import_node_fs5.closeSync)(fd);
56006
57245
  }
56007
- return true;
57246
+ const inode = (0, import_node_fs5.statSync)(staged).ino;
57247
+ (0, import_node_fs5.linkSync)(staged, path4);
57248
+ return inode;
56008
57249
  } catch (error61) {
56009
- if (errnoCode(error61) === "EEXIST") return false;
57250
+ if (errnoCode(error61) === "EEXIST") return null;
56010
57251
  throw error61;
57252
+ } finally {
57253
+ (0, import_node_fs5.rmSync)(staged, { force: true });
56011
57254
  }
56012
57255
  }
56013
57256
  function removeStale(path4, inode) {
@@ -56019,21 +57262,26 @@ function removeStale(path4, inode) {
56019
57262
  }
56020
57263
  }
56021
57264
  async function attempt(path4, self, probe) {
56022
- if (tryCreate(path4, self)) return { kind: "acquired" };
57265
+ const created = tryCreate(path4, self);
57266
+ if (created !== null) return { kind: "acquired", inode: created };
56023
57267
  const inode = inodeOf(path4);
56024
57268
  const owner = readOwner(path4);
56025
57269
  if (owner !== null && await mayBeSameProcess(owner, probe)) return { kind: "held", owner };
56026
57270
  if (inode !== null) removeStale(path4, inode);
56027
- return tryCreate(path4, self) ? { kind: "acquired" } : attempt(path4, self, probe);
57271
+ return attempt(path4, self, probe);
56028
57272
  }
56029
57273
  async function acquireInstanceLock(path4, { clock, waitMs, signal, probe = systemProcessProbe }) {
56030
57274
  await (0, import_promises15.mkdir)((0, import_node_path10.dirname)(path4), { recursive: true, mode: 448 });
56031
57275
  const self = await readProcessIdentity(process.pid);
56032
57276
  if (self === null) throw new RuntimeFault("internal", "Cannot read this process's identity");
56033
57277
  const deadline = clock.monotonic() + waitMs;
57278
+ let heldInode = null;
56034
57279
  for (; ; ) {
56035
57280
  const result = await attempt(path4, self, probe);
56036
- if (result.kind === "acquired") break;
57281
+ if (result.kind === "acquired") {
57282
+ heldInode = result.inode;
57283
+ break;
57284
+ }
56037
57285
  if (clock.monotonic() >= deadline) {
56038
57286
  throw new RuntimeFault(
56039
57287
  "already_running",
@@ -56046,13 +57294,15 @@ async function acquireInstanceLock(path4, { clock, waitMs, signal, probe = syste
56046
57294
  owner: self,
56047
57295
  [Symbol.dispose]: () => {
56048
57296
  const owner = readOwner(path4);
56049
- if (owner?.pid === self.pid && owner.startedAt === self.startedAt) (0, import_node_fs5.unlinkSync)(path4);
57297
+ if (inodeOf(path4) === heldInode && owner?.pid === self.pid && owner.startedAt === self.startedAt) {
57298
+ (0, import_node_fs5.unlinkSync)(path4);
57299
+ }
56050
57300
  }
56051
57301
  };
56052
57302
  }
56053
57303
 
56054
57304
  // src/platform/ipc-endpoint.ts
56055
- var import_node_crypto7 = require("crypto");
57305
+ var import_node_crypto8 = require("crypto");
56056
57306
  var import_node_fs6 = require("fs");
56057
57307
  var import_node_os = require("os");
56058
57308
  var import_node_path11 = require("path");
@@ -56061,7 +57311,7 @@ function windowsPipeName(socketsDir, id) {
56061
57311
  return `\\\\.\\pipe\\alan-${socketsScope(socketsDir)}-${id}`;
56062
57312
  }
56063
57313
  function socketsScope(socketsDir) {
56064
- return (0, import_node_crypto7.createHash)("sha256").update(socketsDir.toLowerCase()).digest("hex").slice(0, 12);
57314
+ return (0, import_node_crypto8.createHash)("sha256").update(socketsDir.toLowerCase()).digest("hex").slice(0, 12);
56065
57315
  }
56066
57316
  function ipcEndpoint(socketsDir, id, platform3 = process.platform) {
56067
57317
  if (platform3 === "win32") return windowsPipeName(socketsDir, id);
@@ -56084,11 +57334,12 @@ var HOLDER_JITLESS_FLAG = "--jitless";
56084
57334
  var HOLDER_NODE_FLAGS = [
56085
57335
  "--max-semi-space-size=1",
56086
57336
  "--max-old-space-size=1024",
57337
+ "--use-system-ca",
56087
57338
  HOLDER_JITLESS_FLAG
56088
57339
  ];
56089
57340
 
56090
57341
  // src/platform/npm-release.ts
56091
- var import_node_crypto8 = require("crypto");
57342
+ var import_node_crypto9 = require("crypto");
56092
57343
  init_zod();
56093
57344
  var RELEASE_TARGETS = [
56094
57345
  "darwin-arm64",
@@ -56156,11 +57407,11 @@ function verifyNpmIntegrity(bytes, dist) {
56156
57407
  if (expected.length === 0) {
56157
57408
  return { ok: false, reason: "the registry's integrity has no sha512 digest" };
56158
57409
  }
56159
- const actual = (0, import_node_crypto8.createHash)("sha512").update(bytes).digest("base64");
57410
+ const actual = (0, import_node_crypto9.createHash)("sha512").update(bytes).digest("base64");
56160
57411
  return expected.includes(actual) ? { ok: true, algorithm: "sha512" } : { ok: false, reason: "the tarball does not match the registry's sha512 integrity" };
56161
57412
  }
56162
57413
  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" };
57414
+ 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
57415
  }
56165
57416
  return { ok: false, reason: "the registry lists no integrity for the tarball" };
56166
57417
  }
@@ -56234,7 +57485,7 @@ function readMemoryPressure() {
56234
57485
  }
56235
57486
 
56236
57487
  // src/platform/release.ts
56237
- var import_node_crypto9 = require("crypto");
57488
+ var import_node_crypto10 = require("crypto");
56238
57489
  var REJECTED_VERSION_RETRY_MS = 24 * 60 * 60 * 1e3;
56239
57490
  function parseVersion(version2) {
56240
57491
  if (!releaseVersionSchema.safeParse(version2).success) return null;
@@ -56277,7 +57528,7 @@ function compareVersions(a, b) {
56277
57528
  return comparePrerelease(left.prerelease, right.prerelease);
56278
57529
  }
56279
57530
  function rolloutBucket(machineId, version2) {
56280
- return (0, import_node_crypto9.createHash)("sha256").update(`${machineId}
57531
+ return (0, import_node_crypto10.createHash)("sha256").update(`${machineId}
56281
57532
  ${version2}`).digest().readUInt32BE(0) % 100;
56282
57533
  }
56283
57534
  function hostReleaseTarget(platform3 = process.platform, arch2 = process.arch) {
@@ -56307,7 +57558,7 @@ function planUpdate(input2) {
56307
57558
 
56308
57559
  // src/platform/release-apply.ts
56309
57560
  var import_node_child_process5 = require("child_process");
56310
- var import_node_crypto10 = require("crypto");
57561
+ var import_node_crypto11 = require("crypto");
56311
57562
  var import_promises17 = require("fs/promises");
56312
57563
  var import_node_path13 = require("path");
56313
57564
  var import_node_util4 = require("util");
@@ -56344,7 +57595,7 @@ async function stageNpmTarball({
56344
57595
  }) {
56345
57596
  const integrity = verifyNpmIntegrity(tarball, release2.dist);
56346
57597
  if (!integrity.ok) throw new RuntimeFault("invalid_file", integrity.reason);
56347
- const scratch = (0, import_node_path13.join)(tmpDir, (0, import_node_crypto10.randomUUID)());
57598
+ const scratch = (0, import_node_path13.join)(tmpDir, (0, import_node_crypto11.randomUUID)());
56348
57599
  await (0, import_promises17.mkdir)(scratch, { recursive: true, mode: 448 });
56349
57600
  try {
56350
57601
  const tarballPath = (0, import_node_path13.join)(scratch, "package.tgz");
@@ -57452,19 +58703,21 @@ function createServiceManager(host, profile) {
57452
58703
  // src/platform/sleep.ts
57453
58704
  var import_node_child_process7 = require("child_process");
57454
58705
  var WAKE_THRESHOLD_MS = 3e4;
57455
- function createWakeDetector(clock, thresholdMs = WAKE_THRESHOLD_MS) {
57456
- const last = { drift: clock.now() - clock.monotonic() };
58706
+ function createWakeDetector(clock, thresholdMs = WAKE_THRESHOLD_MS, platform3 = process.platform) {
58707
+ const last = { wall: clock.now(), drift: clock.now() - clock.monotonic() };
57457
58708
  return {
57458
58709
  check: () => {
57459
- const drift = clock.now() - clock.monotonic();
57460
- const slept = drift - last.drift;
58710
+ const wall = clock.now();
58711
+ const drift = wall - clock.monotonic();
58712
+ const slept = platform3 === "win32" ? wall - last.wall : drift - last.drift;
58713
+ last.wall = wall;
57461
58714
  last.drift = drift;
57462
58715
  return slept >= thresholdMs ? slept : 0;
57463
58716
  }
57464
58717
  };
57465
58718
  }
57466
- function wakeJob(clock, onWake, thresholdMs = WAKE_THRESHOLD_MS) {
57467
- const detector = createWakeDetector(clock, thresholdMs);
58719
+ function wakeJob(clock, onWake, thresholdMs = WAKE_THRESHOLD_MS, platform3 = process.platform) {
58720
+ const detector = createWakeDetector(clock, thresholdMs, platform3);
57468
58721
  return {
57469
58722
  name: "wake.detect",
57470
58723
  run: () => {
@@ -57554,7 +58807,7 @@ function systemAssertionSpawner(log) {
57554
58807
 
57555
58808
  // src/platform/spawn-detached.ts
57556
58809
  var import_node_child_process8 = require("child_process");
57557
- var import_node_crypto11 = require("crypto");
58810
+ var import_node_crypto12 = require("crypto");
57558
58811
  var import_node_fs8 = require("fs");
57559
58812
  var import_node_path21 = require("path");
57560
58813
  var WINDOWS_UNSAFE_ENV = "NODE_PENDING_PIPE_INSTANCES";
@@ -57591,7 +58844,7 @@ async function probeHolderIsolation(platform3, exec, env) {
57591
58844
  }
57592
58845
  const probe = await exec({
57593
58846
  command: SYSTEMD_RUN,
57594
- args: [...scopeArguments(`${SCOPE_PREFIX}-probe-${(0, import_node_crypto11.randomBytes)(4).toString("hex")}`), "true"],
58847
+ args: [...scopeArguments(`${SCOPE_PREFIX}-probe-${(0, import_node_crypto12.randomBytes)(4).toString("hex")}`), "true"],
57595
58848
  timeoutMs: SCOPE_PROBE_TIMEOUT_MS
57596
58849
  });
57597
58850
  if (probe.status === 0) return { kind: "systemd-scope" };
@@ -57603,7 +58856,7 @@ async function probeHolderIsolation(platform3, exec, env) {
57603
58856
  }
57604
58857
  function isolatedCommand(request2, isolation) {
57605
58858
  if (isolation.kind === "detached") return { command: request2.command, args: [...request2.args] };
57606
- const unit = `${SCOPE_PREFIX}-${(0, import_node_crypto11.randomBytes)(6).toString("hex")}`;
58859
+ const unit = `${SCOPE_PREFIX}-${(0, import_node_crypto12.randomBytes)(6).toString("hex")}`;
57607
58860
  return {
57608
58861
  command: SYSTEMD_RUN,
57609
58862
  args: [...scopeArguments(unit), request2.command, ...request2.args]
@@ -57881,7 +59134,7 @@ function createGit(options) {
57881
59134
 
57882
59135
  // src/capabilities/github-proxy/certificates.ts
57883
59136
  var import_node_child_process9 = require("child_process");
57884
- var import_node_crypto12 = require("crypto");
59137
+ var import_node_crypto13 = require("crypto");
57885
59138
  var import_promises24 = require("fs/promises");
57886
59139
  var import_node_path22 = require("path");
57887
59140
  var OPENSSL_TIMEOUT_MS = 1e4;
@@ -57946,7 +59199,7 @@ async function createGitHubProxyCertificates(stateDir) {
57946
59199
  work
57947
59200
  );
57948
59201
  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"]),
59202
+ ["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
59203
  work
57951
59204
  );
57952
59205
  const caPath = (0, import_node_path22.join)(stateDir, "github-ca.pem");
@@ -58172,7 +59425,7 @@ async function startGitHubProxy(options) {
58172
59425
  }
58173
59426
 
58174
59427
  // src/capabilities/mcp-config/mcp-config.ts
58175
- var import_node_crypto13 = require("crypto");
59428
+ var import_node_crypto14 = require("crypto");
58176
59429
  var import_promises27 = require("fs/promises");
58177
59430
  var import_node_path24 = require("path");
58178
59431
 
@@ -59156,7 +60409,7 @@ async function readConfig(cli, home) {
59156
60409
  }
59157
60410
  }
59158
60411
  async function writeConfig(path4, text2) {
59159
- const temporary = `${path4}.alan-${(0, import_node_crypto13.randomUUID)()}.tmp`;
60412
+ const temporary = `${path4}.alan-${(0, import_node_crypto14.randomUUID)()}.tmp`;
59160
60413
  try {
59161
60414
  await (0, import_promises27.writeFile)(temporary, text2, { encoding: "utf8", mode: 384, flag: "wx" });
59162
60415
  await (0, import_promises27.rename)(temporary, path4);
@@ -60264,7 +61517,7 @@ function reconcileTranscriptIdentity(entry, transcriptPath, identity, size) {
60264
61517
  }
60265
61518
 
60266
61519
  // src/capabilities/native-ingest/transcript-window.ts
60267
- var import_node_crypto14 = require("crypto");
61520
+ var import_node_crypto15 = require("crypto");
60268
61521
  var import_promises32 = require("fs/promises");
60269
61522
  init_acp2();
60270
61523
  init_claude();
@@ -60414,7 +61667,7 @@ function lastMatchingTurnIndex(turns, target) {
60414
61667
  function signalDigest(target) {
60415
61668
  const fingerprint = target.assistantFingerprint;
60416
61669
  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;
61670
+ return basis ? (0, import_node_crypto15.createHash)("sha256").update(basis).digest("hex") : null;
60418
61671
  }
60419
61672
  function lastForegroundStop(updates) {
60420
61673
  for (let index = updates.length - 1; index >= 0; index -= 1) {
@@ -60529,9 +61782,23 @@ async function ingestTurn(ctx, worker, entry, turn) {
60529
61782
  },
60530
61783
  ctx.shutdown
60531
61784
  );
61785
+ const ordinals = opened.turnOrdinals;
60532
61786
  await ctx.publisher.publish({
60533
61787
  runId: opened.runId,
60534
61788
  conversationId: entry.conversationId,
61789
+ ...ordinals ? {
61790
+ userMessage: {
61791
+ id: opened.userMessageId,
61792
+ content: userMessage,
61793
+ turnOrdinal: ordinals.user,
61794
+ createdAt: startedAt
61795
+ },
61796
+ assistantMessage: {
61797
+ id: opened.assistantMessageId,
61798
+ turnOrdinal: ordinals.assistant,
61799
+ createdAt: startedAt
61800
+ }
61801
+ } : {},
60535
61802
  records: nativeTurnRecords({
60536
61803
  updates: withTerminalIdle(turn.updates, startedAt),
60537
61804
  startedAt,
@@ -61156,7 +62423,9 @@ function providerCommandFor(backendKind) {
61156
62423
  return BY_BACKEND.get(backendKind)?.command;
61157
62424
  }
61158
62425
  function envValue(env, name) {
61159
- const key = Object.keys(env).find((candidate) => candidate.toUpperCase() === name);
62426
+ const key = Object.keys(env).findLast(
62427
+ (candidate) => candidate.toUpperCase() === name.toUpperCase()
62428
+ );
61160
62429
  return key === void 0 ? "" : env[key] ?? "";
61161
62430
  }
61162
62431
  function pathDelimiter(platform3) {
@@ -61172,12 +62441,18 @@ async function isRunnable(path4, platform3) {
61172
62441
  }
61173
62442
  }
61174
62443
  function windowsExtensions(command, env) {
61175
- const extensions = (envValue(env, "PATHEXT") || ".COM;.EXE;.BAT;.CMD").split(";").filter((extension) => extension.startsWith("."));
62444
+ const extensions = (envValue(env, "PATHEXT") || ".COM;.EXE;.BAT;.CMD").split(";").map((extension) => extension.trim()).filter((extension) => [".COM", ".EXE", ".BAT", ".CMD"].includes(extension.toUpperCase()));
61176
62445
  const named = command.toLowerCase();
61177
- return extensions.some((extension) => named.endsWith(extension.toLowerCase())) ? [""] : extensions;
62446
+ return [".com", ".exe", ...extensions.map((extension) => extension.toLowerCase())].some(
62447
+ (extension) => named.endsWith(extension)
62448
+ ) ? [""] : extensions;
61178
62449
  }
61179
62450
  async function resolveCommandOnPath(command, env, platform3) {
61180
- const directories = envValue(env, "PATH").split(pathDelimiter(platform3)).filter((directory) => directory.length > 0);
62451
+ const directories = envValue(env, "PATH").split(pathDelimiter(platform3)).map(
62452
+ (directory) => platform3 === "win32" ? directory.trim().replace(/^"(.*)"$/, "$1") : directory
62453
+ ).filter(
62454
+ (directory) => platform3 === "win32" ? import_node_path32.win32.isAbsolute(directory) : directory.length > 0
62455
+ );
61181
62456
  const extensions = platform3 === "win32" ? windowsExtensions(command, env) : [""];
61182
62457
  for (const directory of directories) {
61183
62458
  for (const extension of extensions) {
@@ -61224,8 +62499,21 @@ function alanCodeProviderModels() {
61224
62499
  var import_node_child_process10 = require("child_process");
61225
62500
  var DEFAULT_TIMEOUT_MS2 = 5e3;
61226
62501
  var DEFAULT_MAX_BYTES = 1024 * 1024;
62502
+ function withWindowsHelper(env) {
62503
+ const helper = windowsHelperPath();
62504
+ return helper === null ? env : { ...env, ALAN_WINHELPER_PATH: helper };
62505
+ }
61227
62506
  function directLaunch(command, args, options) {
61228
62507
  try {
62508
+ if ((options.platform ?? process.platform) === "win32") {
62509
+ const plan2 = planSpawn({
62510
+ command,
62511
+ args,
62512
+ env: canonicalWindowsEnvironment(options.env),
62513
+ platform: "win32"
62514
+ });
62515
+ return { file: plan2.file, args: plan2.args, windowsVerbatimArguments: false };
62516
+ }
61229
62517
  return planDirectLaunch({
61230
62518
  command,
61231
62519
  args,
@@ -61237,42 +62525,88 @@ function directLaunch(command, args, options) {
61237
62525
  }
61238
62526
  }
61239
62527
  function captureProbe(command, args, options) {
62528
+ const platform3 = options.platform ?? process.platform;
61240
62529
  const launch = directLaunch(command, args, options);
61241
62530
  if (launch === void 0) return Promise.resolve({ stdout: "", stderr: "", exitCode: void 0 });
62531
+ const env = platform3 === "win32" ? withWindowsHelper(canonicalWindowsEnvironment(options.env)) : options.env;
61242
62532
  return new Promise((resolve12) => {
61243
62533
  const limit = options.maxBufferBytes ?? DEFAULT_MAX_BYTES;
61244
62534
  const stdout = [];
61245
62535
  const stderr = [];
61246
62536
  let bytes = 0;
61247
62537
  let overflowed = false;
61248
- const child = (0, import_node_child_process10.spawn)(launch.file, [...launch.args], {
61249
- env: { ...options.env },
62538
+ const windowsChild = platform3 === "win32" ? spawnInWindowsJob(planSpawn({ command, args, env, platform: platform3 }), {
62539
+ cwd: process.cwd(),
62540
+ env
62541
+ }) : void 0;
62542
+ const child = windowsChild ?? (0, import_node_child_process10.spawn)(launch.file, [...launch.args], {
62543
+ env: { ...env },
61250
62544
  stdio: ["ignore", "pipe", "pipe"],
61251
- timeout: options.timeoutMs ?? DEFAULT_TIMEOUT_MS2,
62545
+ detached: true,
61252
62546
  windowsHide: true,
61253
62547
  windowsVerbatimArguments: launch.windowsVerbatimArguments
61254
62548
  });
62549
+ child.stdin?.end();
62550
+ const terminate = () => {
62551
+ if (platform3 !== "win32" && child.pid !== void 0) {
62552
+ try {
62553
+ process.kill(-child.pid, "SIGKILL");
62554
+ return;
62555
+ } catch {
62556
+ }
62557
+ }
62558
+ child.kill("SIGKILL");
62559
+ };
62560
+ let settled2 = false;
62561
+ const deadlineController = new AbortController();
62562
+ const finish = (exitCode) => {
62563
+ if (settled2) return;
62564
+ settled2 = true;
62565
+ deadlineController.abort();
62566
+ options.signal?.removeEventListener("abort", abort);
62567
+ resolve12({
62568
+ stdout: Buffer.concat(stdout).toString("utf8"),
62569
+ stderr: Buffer.concat(stderr).toString("utf8"),
62570
+ exitCode
62571
+ });
62572
+ };
62573
+ void systemClock.sleep(options.timeoutMs ?? DEFAULT_TIMEOUT_MS2, deadlineController.signal).then(
62574
+ () => {
62575
+ terminate();
62576
+ child.stdout.destroy();
62577
+ child.stderr.destroy();
62578
+ finish(void 0);
62579
+ },
62580
+ () => void 0
62581
+ );
62582
+ const abort = () => {
62583
+ terminate();
62584
+ child.stdout.destroy();
62585
+ child.stderr.destroy();
62586
+ finish(void 0);
62587
+ };
62588
+ options.signal?.addEventListener("abort", abort, { once: true });
62589
+ if (options.signal?.aborted) abort();
61255
62590
  const collect = (into) => (chunk) => {
61256
62591
  bytes += chunk.length;
61257
62592
  if (bytes > limit) {
61258
62593
  overflowed = true;
61259
- child.kill("SIGKILL");
62594
+ terminate();
62595
+ finish(void 0);
61260
62596
  return;
61261
62597
  }
61262
62598
  into.push(chunk);
61263
62599
  };
61264
62600
  child.stdout.on("data", collect(stdout));
61265
62601
  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
62602
  child.once("error", () => finish(void 0));
61272
62603
  child.once(
61273
62604
  "close",
61274
62605
  (code, signal) => finish(overflowed || signal !== null || code === null ? void 0 : code)
61275
62606
  );
62607
+ if (windowsChild !== void 0) {
62608
+ void waitForWindowsJob(windowsChild, command).catch(() => finish(void 0));
62609
+ }
61276
62610
  });
61277
62611
  }
61278
62612
 
@@ -61719,7 +63053,7 @@ var import_node_path37 = require("path");
61719
63053
 
61720
63054
  // ../shared/dist/node/shell-environment.js
61721
63055
  var import_node_child_process12 = require("child_process");
61722
- var import_node_crypto15 = require("crypto");
63056
+ var import_node_crypto16 = require("crypto");
61723
63057
  var import_node_fs15 = require("fs");
61724
63058
  var import_node_os5 = require("os");
61725
63059
  var import_node_path36 = require("path");
@@ -61863,6 +63197,15 @@ function installerDirectories(home, platform3) {
61863
63197
  const system = platform3 === "darwin" ? ["/opt/homebrew/bin", "/usr/local/bin"] : ["/usr/local/bin"];
61864
63198
  return [...user, ...system];
61865
63199
  }
63200
+ function windowsInstallerDirectories(env) {
63201
+ const home = envValue(env, "USERPROFILE") || envValue(env, "HOME");
63202
+ const hasHome = import_node_path37.win32.isAbsolute(home);
63203
+ const appData = envValue(env, "APPDATA") || (hasHome ? import_node_path37.win32.join(home, "AppData", "Roaming") : "");
63204
+ return [
63205
+ ...hasHome ? [import_node_path37.win32.join(home, ".local", "bin")] : [],
63206
+ ...import_node_path37.win32.isAbsolute(appData) ? [import_node_path37.win32.join(appData, "npm")] : []
63207
+ ];
63208
+ }
61866
63209
  function printPathCommand() {
61867
63210
  return `printf '${MARKER}%s${MARKER}' "$PATH"`;
61868
63211
  }
@@ -61915,7 +63258,14 @@ async function rememberLastKnownGood(file2, path4) {
61915
63258
  }
61916
63259
  async function resolveCliEnvironmentDetailed(options) {
61917
63260
  const { env, platform: platform3 } = options;
61918
- if (platform3 === "win32") return { env: { ...env }, source: "none" };
63261
+ if (platform3 === "win32") {
63262
+ const path4 = appendPathDirectories(
63263
+ envValue(env, "PATH"),
63264
+ windowsInstallerDirectories(env),
63265
+ ";"
63266
+ );
63267
+ return { env: canonicalWindowsEnvironment({ ...env, PATH: path4 }), source: "none" };
63268
+ }
61919
63269
  const loginPath = await readLoginShellPath(env, options.capture ?? captureProbe);
61920
63270
  if (loginPath !== null) await rememberLastKnownGood(options.lastKnownGoodFile, loginPath);
61921
63271
  const lastKnownGood = loginPath === null ? await readLastKnownGood(options.lastKnownGoodFile) : null;
@@ -61962,8 +63312,7 @@ async function openCliEnvironment(options) {
61962
63312
  }
61963
63313
 
61964
63314
  // src/capabilities/providers/managed.ts
61965
- var import_node_child_process13 = require("child_process");
61966
- var import_node_crypto16 = require("crypto");
63315
+ var import_node_crypto17 = require("crypto");
61967
63316
  var import_promises36 = require("fs/promises");
61968
63317
  var import_node_path38 = require("path");
61969
63318
  init_zod();
@@ -61992,9 +63341,10 @@ function withManagedProviderPaths(manager, env, nodeDirectory, platform3 = proce
61992
63341
  const path4 = [
61993
63342
  ...manager.selections().map((item) => item.binDir),
61994
63343
  ...nodeDirectory === void 0 ? [] : [nodeDirectory],
61995
- env.PATH ?? ""
63344
+ envValue(env, "PATH")
61996
63345
  ].filter(Boolean);
61997
- return { ...env, PATH: path4.join(pathDelimiter(platform3)) };
63346
+ const merged = { ...env, PATH: path4.join(pathDelimiter(platform3)) };
63347
+ return platform3 === "win32" ? canonicalWindowsEnvironment(merged) : merged;
61998
63348
  }
61999
63349
  function packageFor(backendKind) {
62000
63350
  const provider4 = PACKAGES[backendKind];
@@ -62091,7 +63441,7 @@ function createManagedProviderClis(options) {
62091
63441
  };
62092
63442
  const persist = async () => {
62093
63443
  await (0, import_promises36.mkdir)(options.root, { recursive: true, mode: 448 });
62094
- const staged = `${file2}.${(0, import_node_crypto16.randomUUID)()}`;
63444
+ const staged = `${file2}.${(0, import_node_crypto17.randomUUID)()}`;
62095
63445
  try {
62096
63446
  await (0, import_promises36.writeFile)(staged, JSON.stringify(state), { mode: 384 });
62097
63447
  await (0, import_promises36.rename)(staged, file2);
@@ -62126,7 +63476,7 @@ function createManagedProviderClis(options) {
62126
63476
  try {
62127
63477
  parsed = selectedSchema.parse(JSON.parse(raw));
62128
63478
  } catch {
62129
- await (0, import_promises36.rename)(file2, `${file2}.invalid.${(0, import_node_crypto16.randomUUID)()}`).catch(() => void 0);
63479
+ await (0, import_promises36.rename)(file2, `${file2}.invalid.${(0, import_node_crypto17.randomUUID)()}`).catch(() => void 0);
62130
63480
  return;
62131
63481
  }
62132
63482
  for (const [backendKind, version2] of Object.entries(parsed)) {
@@ -62184,7 +63534,7 @@ function createManagedProviderClis(options) {
62184
63534
  const existing = selection(options.root, backendKind, exact);
62185
63535
  if (!await runnable(existing.executable) || !await options.probe(existing.executable, backendKind)) {
62186
63536
  await (0, import_promises36.mkdir)((0, import_node_path38.dirname)(target), { recursive: true, mode: 448 });
62187
- const staged = `${target}.${(0, import_node_crypto16.randomUUID)()}`;
63537
+ const staged = `${target}.${(0, import_node_crypto17.randomUUID)()}`;
62188
63538
  try {
62189
63539
  await options.installPackage(provider4.name, exact, staged, provider4.command, signal);
62190
63540
  const built = (0, import_node_path38.join)(staged, "node_modules", ".bin", provider4.command);
@@ -62214,9 +63564,18 @@ function createManagedProviderClis(options) {
62214
63564
  })
62215
63565
  };
62216
63566
  }
63567
+ function withInstallerPath(options) {
63568
+ const platform3 = options.platform ?? process.platform;
63569
+ const path4 = [
63570
+ platform3 === "win32" ? import_node_path38.win32.dirname(options.command) : (0, import_node_path38.dirname)(options.command),
63571
+ envValue(options.env, "PATH")
63572
+ ].filter(Boolean).join(pathDelimiter(platform3));
63573
+ const env = { ...options.env, PATH: path4 };
63574
+ return platform3 === "win32" ? canonicalWindowsEnvironment(env) : env;
63575
+ }
62217
63576
  function createNpmPackageInstaller(options) {
62218
- return (packageName, version2, destination, _command, signal) => new Promise((resolve12, reject) => {
62219
- const child = (0, import_node_child_process13.spawn)(
63577
+ return async (packageName, version2, destination, _command, signal) => {
63578
+ const result = await captureProbe(
62220
63579
  options.command,
62221
63580
  [
62222
63581
  ...options.argsBeforeNpm ?? [],
@@ -62228,53 +63587,35 @@ function createNpmPackageInstaller(options) {
62228
63587
  `${packageName}@${version2}`
62229
63588
  ],
62230
63589
  {
62231
- env: { ...options.env, PATH: `${(0, import_node_path38.dirname)(options.command)}:${options.env.PATH ?? ""}` },
63590
+ env: withInstallerPath(options),
62232
63591
  signal,
62233
- stdio: ["ignore", "pipe", "pipe"]
63592
+ timeoutMs: 10 * 6e4,
63593
+ maxBufferBytes: 1024 * 1024
62234
63594
  }
62235
63595
  );
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
- });
63596
+ if (result.exitCode !== 0) {
63597
+ const output2 = `${result.stdout}
63598
+ ${result.stderr}`.trim().slice(-8e3);
63599
+ throw new Error(
63600
+ `npm install failed (${result.exitCode ?? "timeout, cancellation or launch"}): ${output2}`
63601
+ );
62241
63602
  }
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
- });
63603
+ };
62248
63604
  }
62249
63605
  function createNpmVersionResolver(options) {
62250
- return (packageName, signal) => new Promise((resolve12, reject) => {
62251
- const child = (0, import_node_child_process13.spawn)(
63606
+ return async (packageName, signal) => {
63607
+ const result = await captureProbe(
62252
63608
  options.command,
62253
63609
  [...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
- }
63610
+ { env: withInstallerPath(options), signal, timeoutMs: 3e4, maxBufferBytes: 1e5 }
62262
63611
  );
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
- });
63612
+ if (result.exitCode !== 0) {
63613
+ throw new Error(
63614
+ `Cannot look up ${packageName} version: ${result.stderr.trim().slice(-2e3)}`
63615
+ );
63616
+ }
63617
+ return parseNpmVersion(result.stdout, packageName);
63618
+ };
62278
63619
  }
62279
63620
  function parseNpmVersion(output2, packageName) {
62280
63621
  const versions = external_exports.union([external_exports.string(), external_exports.array(external_exports.string())]).parse(JSON.parse(output2));
@@ -62311,7 +63652,7 @@ var import_node_path43 = __toESM(require("path"));
62311
63652
 
62312
63653
  // ../shared/dist/node/skill-package.js
62313
63654
  var import_node_buffer = require("buffer");
62314
- var import_node_crypto17 = require("crypto");
63655
+ var import_node_crypto18 = require("crypto");
62315
63656
  var import_promises37 = require("fs/promises");
62316
63657
  var import_node_path39 = require("path");
62317
63658
  var import_yaml = __toESM(require_dist(), 1);
@@ -62711,7 +64052,7 @@ function comparePackageFiles(left, right) {
62711
64052
  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
64053
  }
62713
64054
  function hashPackageTree(files) {
62714
- const hash2 = (0, import_node_crypto17.createHash)("sha256");
64055
+ const hash2 = (0, import_node_crypto18.createHash)("sha256");
62715
64056
  hash2.update(TREE_HASH_PREFIX);
62716
64057
  for (const file2 of files) {
62717
64058
  const path4 = import_node_buffer.Buffer.from(file2.path, "utf8");
@@ -62724,7 +64065,7 @@ function hashPackageTree(files) {
62724
64065
  return `sha256:${hash2.digest("hex")}`;
62725
64066
  }
62726
64067
  function sha256(bytes) {
62727
- return `sha256:${(0, import_node_crypto17.createHash)("sha256").update(bytes).digest("hex")}`;
64068
+ return `sha256:${(0, import_node_crypto18.createHash)("sha256").update(bytes).digest("hex")}`;
62728
64069
  }
62729
64070
  function uint322(value2) {
62730
64071
  const buffer = import_node_buffer.Buffer.allocUnsafe(4);
@@ -62738,13 +64079,13 @@ function uint642(value2) {
62738
64079
  }
62739
64080
 
62740
64081
  // src/capabilities/skills/local-sources.ts
62741
- var import_node_crypto19 = require("crypto");
64082
+ var import_node_crypto20 = require("crypto");
62742
64083
  var import_promises39 = require("fs/promises");
62743
64084
  var import_node_path41 = __toESM(require("path"));
62744
64085
  init_type_guards();
62745
64086
 
62746
64087
  // src/capabilities/skills/local-scan.ts
62747
- var import_node_crypto18 = require("crypto");
64088
+ var import_node_crypto19 = require("crypto");
62748
64089
  var import_promises38 = require("fs/promises");
62749
64090
  var import_node_path40 = __toESM(require("path"));
62750
64091
  var MAX_CANDIDATES = 2e3;
@@ -62753,7 +64094,7 @@ function createLocalSkillScanCache() {
62753
64094
  return { inspections: /* @__PURE__ */ new Map(), lastCompleteRevision: null };
62754
64095
  }
62755
64096
  async function scanSkillRoots(input2, cache2) {
62756
- const attemptId = (0, import_node_crypto18.randomUUID)();
64097
+ const attemptId = (0, import_node_crypto19.randomUUID)();
62757
64098
  const ignoredPaths = input2.ignoredPaths ?? [];
62758
64099
  const resolvedRoots = resolveScanRoots(input2.roots, input2.enabledProviderKinds ?? []);
62759
64100
  const pass = {
@@ -62818,7 +64159,7 @@ function failedLocalSkillScan(cache2, code, message2) {
62818
64159
  return {
62819
64160
  outcome: {
62820
64161
  status: "failed",
62821
- attemptId: (0, import_node_crypto18.randomUUID)(),
64162
+ attemptId: (0, import_node_crypto19.randomUUID)(),
62822
64163
  retainedInventoryRevision: cache2.lastCompleteRevision,
62823
64164
  diagnostics: [{ code, message: message2.slice(0, 2048) }]
62824
64165
  },
@@ -62982,11 +64323,11 @@ function candidateOrigin(root) {
62982
64323
  }
62983
64324
  function createLocalKey(root, skillName) {
62984
64325
  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");
64326
+ 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
64327
  return `local:${digest}`;
62987
64328
  }
62988
64329
  function hashInventory(candidates2) {
62989
- const hash2 = (0, import_node_crypto18.createHash)("sha256").update("alan-skill-inventory-v1\0");
64330
+ const hash2 = (0, import_node_crypto19.createHash)("sha256").update("alan-skill-inventory-v1\0");
62990
64331
  for (const candidate of candidates2) {
62991
64332
  hash2.update(candidate.localKey).update("\0");
62992
64333
  hash2.update(candidate.contentHash).update("\0");
@@ -63006,7 +64347,7 @@ function deduplicateByContent(candidates2) {
63006
64347
  return candidates2.filter((located) => winners.has(located));
63007
64348
  }
63008
64349
  async function fingerprintPackage(root) {
63009
- const hash2 = (0, import_node_crypto18.createHash)("sha256").update("alan-skill-stat-fingerprint-v1\0");
64350
+ const hash2 = (0, import_node_crypto19.createHash)("sha256").update("alan-skill-stat-fingerprint-v1\0");
63010
64351
  const visit2 = async (directory, relativeDirectory) => {
63011
64352
  const entries = await (0, import_promises38.readdir)(directory, { withFileTypes: true });
63012
64353
  entries.sort((left, right) => Buffer.compare(Buffer.from(left.name), Buffer.from(right.name)));
@@ -63209,7 +64550,7 @@ function staleCodexDeclaration(relativeDirectory, label, providerKinds) {
63209
64550
  return ownedByCursor || label === "Legacy Cursor-compatible skills";
63210
64551
  }
63211
64552
  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);
64553
+ const digest = (0, import_node_crypto20.createHash)("sha256").update("alan-skill-source-v1\0").update(sourcePath.normalize("NFC")).digest("hex").slice(0, 24);
63213
64554
  return `source-${digest}`;
63214
64555
  }
63215
64556
  function requiredSourceId(value2, field3) {
@@ -63256,10 +64597,10 @@ var import_promises40 = require("fs/promises");
63256
64597
  var import_node_path42 = require("path");
63257
64598
 
63258
64599
  // ../shared/dist/node/alan-skill-identity.js
63259
- var import_node_crypto20 = require("crypto");
64600
+ var import_node_crypto21 = require("crypto");
63260
64601
  var ALAN_SKILL_NAMESPACE = "ec71d99b-d207-4ca2-a9eb-3a7bed4a73fd";
63261
64602
  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);
64603
+ const bytes = (0, import_node_crypto21.createHash)("sha1").update(Buffer.from(namespace.replaceAll("-", ""), "hex")).update(name, "utf8").digest().subarray(0, 16);
63263
64604
  bytes[6] = bytes[6] & 15 | 80;
63264
64605
  bytes[8] = bytes[8] & 63 | 128;
63265
64606
  const hex3 = bytes.toString("hex");
@@ -63526,7 +64867,7 @@ var import_promises43 = require("fs/promises");
63526
64867
 
63527
64868
  // ../shared/dist/node/skill-bundle.js
63528
64869
  var import_node_buffer2 = require("buffer");
63529
- var import_node_crypto21 = require("crypto");
64870
+ var import_node_crypto22 = require("crypto");
63530
64871
  var import_promises42 = require("fs/promises");
63531
64872
  var import_node_path44 = require("path");
63532
64873
  var import_node_stream = require("stream");
@@ -63665,7 +65006,7 @@ function requireSafeArchivePath(value2) {
63665
65006
  return normalized2;
63666
65007
  }
63667
65008
  function sha2562(bytes) {
63668
- return `sha256:${(0, import_node_crypto21.createHash)("sha256").update(bytes).digest("hex")}`;
65009
+ return `sha256:${(0, import_node_crypto22.createHash)("sha256").update(bytes).digest("hex")}`;
63669
65010
  }
63670
65011
 
63671
65012
  // src/capabilities/skills/local-upload.ts
@@ -63709,14 +65050,14 @@ async function publishLocalSkill(options) {
63709
65050
  }
63710
65051
 
63711
65052
  // src/capabilities/skills/sync.ts
63712
- var import_node_crypto22 = require("crypto");
65053
+ var import_node_crypto23 = require("crypto");
63713
65054
  var import_promises44 = require("fs/promises");
63714
65055
  var import_node_path45 = require("path");
63715
65056
  var SKILL_PREPARE_WAIT_MS = 15e3;
63716
65057
  async function install(layout, source, skill, download, signal) {
63717
65058
  const bytes = await source.download(download.url, signal);
63718
65059
  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)());
65060
+ const staging = (0, import_node_path45.join)(layout.tmpDir, (0, import_node_crypto23.randomUUID)());
63720
65061
  await extractSkillBundle(Buffer.from(bytes), staging, {
63721
65062
  expectedArchiveHash: download.archiveHash,
63722
65063
  expectedContentHash: skill.contentHash
@@ -64129,7 +65470,7 @@ async function openApprovedPaths(options) {
64129
65470
  }
64130
65471
 
64131
65472
  // src/capabilities/workspace/locks.ts
64132
- var import_node_crypto23 = require("crypto");
65473
+ var import_node_crypto24 = require("crypto");
64133
65474
  var import_promises46 = require("fs/promises");
64134
65475
  var import_node_path47 = require("path");
64135
65476
  init_zod();
@@ -64146,7 +65487,7 @@ var ownerSchema = external_exports.object({
64146
65487
  since: external_exports.number().int().nonnegative()
64147
65488
  });
64148
65489
  function repositoryLockKey(commonDir, platform3) {
64149
- return (0, import_node_crypto23.createHash)("sha256").update(comparablePath(commonDir, platform3)).digest("hex").slice(0, 32);
65490
+ return (0, import_node_crypto24.createHash)("sha256").update(comparablePath(commonDir, platform3)).digest("hex").slice(0, 32);
64150
65491
  }
64151
65492
  async function readOwner2(path4) {
64152
65493
  let text2;
@@ -64259,7 +65600,7 @@ function openRepositoryLocks(options) {
64259
65600
  },
64260
65601
  tryShared: async (commonDir, runId) => {
64261
65602
  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`;
65603
+ const file2 = `${RUN_FILE_PREFIX}${(0, import_node_crypto24.createHash)("sha256").update(runId).digest("hex").slice(0, 32)}.json`;
64263
65604
  const path4 = (0, import_node_path47.join)(dir, file2);
64264
65605
  const owner = await self(runId);
64265
65606
  await writeJsonFileAtomic(path4, owner);
@@ -64495,7 +65836,7 @@ async function openWorkspaces(options) {
64495
65836
 
64496
65837
  // src/cli/config.ts
64497
65838
  var import_node_os11 = require("os");
64498
- var import_node_path64 = require("path");
65839
+ var import_node_path65 = require("path");
64499
65840
  init_zod();
64500
65841
 
64501
65842
  // src/client/contract.ts
@@ -64780,6 +66121,7 @@ var mcpConfigResultSchema = external_exports.object({
64780
66121
 
64781
66122
  // src/client/runtime-client.ts
64782
66123
  var import_promises47 = require("fs/promises");
66124
+ init_acp();
64783
66125
  init_runtime_v2();
64784
66126
 
64785
66127
  // src/client/sse.ts
@@ -64797,14 +66139,18 @@ function applyField(pending, line) {
64797
66139
  }
64798
66140
  async function* readServerSentEvents(body) {
64799
66141
  const decoder3 = new TextDecoder();
64800
- let buffer = "";
66142
+ let partial2 = [];
64801
66143
  let pending = emptyEvent();
64802
66144
  for await (const chunk of body) {
64803
- buffer += decoder3.decode(chunk, { stream: true });
64804
- let newline = buffer.indexOf("\n");
66145
+ const text2 = decoder3.decode(chunk, { stream: true });
66146
+ let start = 0;
66147
+ let newline = text2.indexOf("\n");
64805
66148
  while (newline !== -1) {
64806
- const line = buffer.slice(0, newline).replace(/\r$/, "");
64807
- buffer = buffer.slice(newline + 1);
66149
+ partial2.push(text2.slice(start, newline));
66150
+ const line = partial2.join("").replace(/\r$/, "");
66151
+ partial2 = [];
66152
+ start = newline + 1;
66153
+ newline = text2.indexOf("\n", start);
64808
66154
  if (line.length === 0) {
64809
66155
  if (pending.data.length > 0) {
64810
66156
  yield { event: pending.event, id: pending.id, data: pending.data.join("\n") };
@@ -64813,8 +66159,8 @@ async function* readServerSentEvents(body) {
64813
66159
  } else if (!line.startsWith(":")) {
64814
66160
  applyField(pending, line);
64815
66161
  }
64816
- newline = buffer.indexOf("\n");
64817
66162
  }
66163
+ if (start < text2.length) partial2.push(text2.slice(start));
64818
66164
  }
64819
66165
  }
64820
66166
 
@@ -64851,6 +66197,23 @@ async function readDiscovery(path4) {
64851
66197
  }
64852
66198
  return parsed.data;
64853
66199
  }
66200
+ function conversationQuery(query) {
66201
+ return {
66202
+ limit: String(query.limit),
66203
+ ...query.before ? { before: query.before } : {},
66204
+ ...query.runtimeId ? { runtimeId: query.runtimeId } : {}
66205
+ };
66206
+ }
66207
+ function conversationUpdate(event) {
66208
+ const value2 = JSON.parse(event.data);
66209
+ if (event.event === "snapshot" && isConversationMessagesPage(value2))
66210
+ return { kind: "snapshot", page: value2 };
66211
+ if (event.event === "turn" && isConversationMessageTurn(value2))
66212
+ return { kind: "turn", turn: value2 };
66213
+ if (event.event === LIVE_TURN_EVENT && isLiveTurnFrame(value2))
66214
+ return { kind: "live_turn", frame: value2 };
66215
+ throw new RuntimeClientError("protocol", "Invalid local conversation update");
66216
+ }
64854
66217
  function parseWith(schema, raw, what) {
64855
66218
  const parsed = schema.safeParse(raw);
64856
66219
  if (!parsed.success) {
@@ -64996,11 +66359,44 @@ function createRuntimeClient(options) {
64996
66359
  throw new RuntimeClientError("unavailable", "The run log stream closed before the run ended");
64997
66360
  }
64998
66361
  const runs = async (signal) => (await json2({ path: LOCAL_API_ROUTES.runs }, runsResponseSchema, signal)).runs;
66362
+ async function* followConversationMessages(query, signal) {
66363
+ const stopped = new AbortController();
66364
+ try {
66365
+ const body = await openStream(
66366
+ {
66367
+ path: `/v2/conversations/${encodeURIComponent(query.conversationId)}/messages/sse`,
66368
+ query: { ...conversationQuery(query), frames: LIVE_TURN_FRAMES }
66369
+ },
66370
+ AbortSignal.any([signal, stopped.signal])
66371
+ );
66372
+ for await (const event of readServerSentEvents(body)) yield conversationUpdate(event);
66373
+ if (!signal.aborted)
66374
+ throw new RuntimeClientError("unavailable", "The local conversation stream closed");
66375
+ } finally {
66376
+ stopped.abort();
66377
+ }
66378
+ }
64999
66379
  return {
65000
66380
  status: (signal) => json2({ path: LOCAL_API_ROUTES.status }, runtimeStatusSchema, signal),
65001
66381
  watchStatus,
66382
+ followConversationMessages,
65002
66383
  runs,
65003
66384
  conversationRuns: async (conversationId, signal) => (await runs(signal)).filter((run2) => run2.conversationId === conversationId),
66385
+ readConversationMessages: async (query, signal) => {
66386
+ const response = await send2(
66387
+ {
66388
+ path: `/v2/conversations/${encodeURIComponent(query.conversationId)}/messages`,
66389
+ query: conversationQuery(query)
66390
+ },
66391
+ signal
66392
+ );
66393
+ if (response.status === 404) return null;
66394
+ if (!response.ok) throw await rejection(response);
66395
+ const page = await response.json();
66396
+ if (!isConversationMessagesPage(page))
66397
+ throw new RuntimeClientError("protocol", "Invalid local conversation page");
66398
+ return page;
66399
+ },
65004
66400
  readRunLog: async (runId, query, signal) => {
65005
66401
  const response = await send2(
65006
66402
  {
@@ -65166,14 +66562,14 @@ async function sendNativeHookSignal(discoveryPath, hookSignal, signal) {
65166
66562
  }
65167
66563
 
65168
66564
  // src/sessions/index.ts
65169
- var import_node_crypto29 = require("crypto");
65170
- var import_promises63 = require("fs/promises");
66565
+ var import_node_crypto30 = require("crypto");
66566
+ var import_promises64 = require("fs/promises");
65171
66567
  var import_node_os10 = require("os");
65172
- var import_node_path63 = require("path");
66568
+ var import_node_path64 = require("path");
65173
66569
  init_runtime_v2();
65174
66570
 
65175
66571
  // src/holder/control-client.ts
65176
- var import_node_crypto24 = require("crypto");
66572
+ var import_node_crypto25 = require("crypto");
65177
66573
  var import_node_net2 = require("net");
65178
66574
  init_runtime_v2();
65179
66575
 
@@ -65243,7 +66639,7 @@ async function connectHolder(endpoint, token, onEvent) {
65243
66639
  });
65244
66640
  const pid = await ready;
65245
66641
  const request2 = (body) => {
65246
- const id = (0, import_node_crypto24.randomUUID)();
66642
+ const id = (0, import_node_crypto25.randomUUID)();
65247
66643
  return new Promise((resolve12, reject) => {
65248
66644
  const timer = AbortSignal.timeout(REQUEST_TIMEOUT_MS7);
65249
66645
  timer.addEventListener("abort", () => {
@@ -65582,10 +66978,10 @@ async function prepareRunInputs(spec, { source, tmpDir, signal, skills = [] }) {
65582
66978
  }
65583
66979
 
65584
66980
  // src/holder/serve.ts
65585
- var import_node_crypto28 = require("crypto");
66981
+ var import_node_crypto29 = require("crypto");
65586
66982
  var import_node_fs21 = require("fs");
65587
66983
  var import_node_net3 = require("net");
65588
- var import_node_path62 = require("path");
66984
+ var import_node_path63 = require("path");
65589
66985
  init_runtime_v2();
65590
66986
 
65591
66987
  // src/holder/admission.ts
@@ -65676,7 +67072,7 @@ async function discoverRelocatedWorkspace(search) {
65676
67072
  }
65677
67073
 
65678
67074
  // src/holder/checkout-refresh.ts
65679
- var import_node_crypto26 = require("crypto");
67075
+ var import_node_crypto27 = require("crypto");
65680
67076
  var import_promises57 = require("fs/promises");
65681
67077
  var import_node_path56 = require("path");
65682
67078
  function short(sha) {
@@ -65723,7 +67119,7 @@ async function fastForward(freshness, operationId, deps, signal) {
65723
67119
  async function atFirstLease(freshness, spec, deps, signal) {
65724
67120
  const first = await claimOnce(
65725
67121
  (0, import_node_path56.join)(deps.dir, "leased"),
65726
- (0, import_node_crypto26.createHash)("sha256").update(freshness.path).digest("hex")
67122
+ (0, import_node_crypto27.createHash)("sha256").update(freshness.path).digest("hex")
65727
67123
  );
65728
67124
  switch (freshness.state) {
65729
67125
  case "current":
@@ -66340,7 +67736,7 @@ function createSessionFacts(options) {
66340
67736
  init_acp2();
66341
67737
 
66342
67738
  // src/run-log/complete.ts
66343
- var import_node_crypto27 = require("crypto");
67739
+ var import_node_crypto28 = require("crypto");
66344
67740
  var import_node_fs19 = require("fs");
66345
67741
  var import_node_path60 = require("path");
66346
67742
 
@@ -66349,7 +67745,24 @@ var import_promises61 = require("fs/promises");
66349
67745
  var import_node_path59 = require("path");
66350
67746
  init_runtime_v2();
66351
67747
  init_zod();
66352
- var runMetaSchema = external_exports.object({ runId: runIdSchema, conversationId: conversationIdSchema });
67748
+ var runMetaSchema = external_exports.object({
67749
+ runId: runIdSchema,
67750
+ conversationId: conversationIdSchema,
67751
+ agentMode: external_exports.string().optional(),
67752
+ userMessage: external_exports.object({
67753
+ id: external_exports.string(),
67754
+ content: external_exports.string(),
67755
+ turnOrdinal: external_exports.number().int().nullable(),
67756
+ createdAt: external_exports.string(),
67757
+ clientMessageId: external_exports.string().optional(),
67758
+ attachmentIds: external_exports.array(external_exports.string()).optional()
67759
+ }).optional(),
67760
+ assistantMessage: external_exports.object({
67761
+ id: external_exports.string(),
67762
+ turnOrdinal: external_exports.number().int().nullable(),
67763
+ createdAt: external_exports.string()
67764
+ }).optional()
67765
+ });
66353
67766
  async function readRunMeta(path4) {
66354
67767
  const read = await readJsonFile(path4, runMetaSchema);
66355
67768
  return read.kind === "ok" ? read.value : null;
@@ -66374,7 +67787,7 @@ async function isRunClaimed(runsDir, runId) {
66374
67787
 
66375
67788
  // src/run-log/complete.ts
66376
67789
  function writeLogFile(path4, dir, text2) {
66377
- const temp = (0, import_node_path60.join)(dir, `.log.${(0, import_node_crypto27.randomUUID)()}.tmp`);
67790
+ const temp = (0, import_node_path60.join)(dir, `.log.${(0, import_node_crypto28.randomUUID)()}.tmp`);
66378
67791
  const fd = (0, import_node_fs19.openSync)(temp, "wx", 384);
66379
67792
  try {
66380
67793
  (0, import_node_fs19.writeSync)(fd, text2);
@@ -66402,8 +67815,86 @@ async function writeCompleteRunLog(runsDir, meta3, records) {
66402
67815
  if (await readRunMeta(paths.meta) === null) await writeJsonFileAtomic(paths.meta, meta3);
66403
67816
  }
66404
67817
 
66405
- // src/run-log/reader.ts
67818
+ // src/run-log/conversation-index.ts
66406
67819
  var import_promises62 = require("fs/promises");
67820
+ var import_node_path61 = require("path");
67821
+ init_runtime_v2();
67822
+ init_zod();
67823
+ var ORDINALS_PER_SHARD = 1e3;
67824
+ var indexRecordSchema = external_exports.object({
67825
+ ordinal: external_exports.number().int().nonnegative(),
67826
+ nextOrdinal: external_exports.number().int().positive(),
67827
+ runId: runIdSchema
67828
+ });
67829
+ var coverageSchema = external_exports.object({
67830
+ // Files written before ranges could start mid-conversation always started at turn 0.
67831
+ lowestOrdinal: external_exports.number().int().nonnegative().default(0),
67832
+ highestOrdinal: external_exports.number().int().nonnegative(),
67833
+ nextExpectedOrdinal: external_exports.number().int().positive()
67834
+ });
67835
+ function indexDirectory(runsDir, conversationId) {
67836
+ return (0, import_node_path61.join)((0, import_node_path61.dirname)(runsDir), "sessions", conversationId, "turn-index");
67837
+ }
67838
+ function shardPath(runsDir, conversationId, ordinal) {
67839
+ return (0, import_node_path61.join)(
67840
+ indexDirectory(runsDir, conversationId),
67841
+ `${Math.floor(ordinal / ORDINALS_PER_SHARD)}.jsonl`
67842
+ );
67843
+ }
67844
+ async function indexConversationRun(runsDir, conversationId, ordinal, assistantOrdinal, runId) {
67845
+ const nextOrdinal = assistantOrdinal + 1;
67846
+ if (nextOrdinal <= ordinal) throw new Error("Assistant order must follow the prompt");
67847
+ const path4 = shardPath(runsDir, conversationId, ordinal);
67848
+ await (0, import_promises62.mkdir)((0, import_node_path61.dirname)(path4), { recursive: true, mode: 448 });
67849
+ await (0, import_promises62.appendFile)(path4, `${JSON.stringify({ ordinal, nextOrdinal, runId })}
67850
+ `, { mode: 384 });
67851
+ const coveragePath = (0, import_node_path61.join)((0, import_node_path61.dirname)((0, import_node_path61.dirname)(path4)), "coverage.json");
67852
+ const coverage = await readJsonFile(coveragePath, coverageSchema);
67853
+ const current = coverage.kind === "ok" ? coverage.value : null;
67854
+ const next = nextCoverage(current, ordinal, nextOrdinal);
67855
+ if (next) await writeJsonFileAtomic(coveragePath, next);
67856
+ }
67857
+ function nextCoverage(current, ordinal, nextOrdinal) {
67858
+ if (current === null || ordinal > current.nextExpectedOrdinal)
67859
+ return { lowestOrdinal: ordinal, highestOrdinal: ordinal, nextExpectedOrdinal: nextOrdinal };
67860
+ if (ordinal === current.nextExpectedOrdinal)
67861
+ return { ...current, highestOrdinal: ordinal, nextExpectedOrdinal: nextOrdinal };
67862
+ if (ordinal === current.highestOrdinal) return { ...current, nextExpectedOrdinal: nextOrdinal };
67863
+ return null;
67864
+ }
67865
+ async function readConversationIndexCoverage(runsDir, conversationId) {
67866
+ const path4 = (0, import_node_path61.join)((0, import_node_path61.dirname)(indexDirectory(runsDir, conversationId)), "coverage.json");
67867
+ const result = await readJsonFile(path4, coverageSchema);
67868
+ return result.kind === "ok" ? result.value : null;
67869
+ }
67870
+ async function readConversationRunIndex(runsDir, conversationId, before, limit) {
67871
+ const directory = indexDirectory(runsDir, conversationId);
67872
+ const names = await (0, import_promises62.readdir)(directory).catch((error61) => {
67873
+ if (error61.code === "ENOENT") return [];
67874
+ throw error61;
67875
+ });
67876
+ const shards = names.map((name) => /^\d+\.jsonl$/.test(name) ? Number(name.slice(0, -6)) : NaN).filter((shard) => Number.isSafeInteger(shard)).filter(
67877
+ (shard) => before === void 0 || shard <= Math.floor((before - 1) / ORDINALS_PER_SHARD)
67878
+ ).sort((left, right) => right - left);
67879
+ const selected = [];
67880
+ for (const shard of shards) {
67881
+ const text2 = await (0, import_promises62.readFile)((0, import_node_path61.join)(directory, `${shard}.jsonl`), "utf8");
67882
+ const records = text2.split("\n").flatMap((line) => {
67883
+ if (!line) return [];
67884
+ const parsed = indexRecordSchema.parse(JSON.parse(line));
67885
+ return [parsed];
67886
+ }).filter((record2) => before === void 0 || record2.ordinal < before).reverse().sort((left, right) => right.ordinal - left.ordinal);
67887
+ for (const record2 of records) {
67888
+ if (selected.some((entry) => entry.ordinal === record2.ordinal)) continue;
67889
+ selected.push(record2);
67890
+ if (selected.length >= limit) return selected;
67891
+ }
67892
+ }
67893
+ return selected;
67894
+ }
67895
+
67896
+ // src/run-log/reader.ts
67897
+ var import_promises63 = require("fs/promises");
66407
67898
  init_runtime_v2();
66408
67899
 
66409
67900
  // src/run-log/tail.ts
@@ -66426,7 +67917,7 @@ function firstRecordLength(bytes) {
66426
67917
  return bytes.indexOf(RUN_LOG_RECORD_SEPARATOR) + 1;
66427
67918
  }
66428
67919
  async function openRunLogReader(path4) {
66429
- const handle = await (0, import_promises62.open)(path4, "r");
67920
+ const handle = await (0, import_promises63.open)(path4, "r");
66430
67921
  const readAt = async (position, length) => {
66431
67922
  const buffer = Buffer.alloc(length);
66432
67923
  const { bytesRead } = await handle.read(buffer, 0, length, position);
@@ -66460,7 +67951,7 @@ async function openRunLogReader(path4) {
66460
67951
  };
66461
67952
  }
66462
67953
  async function readLastRecord(path4) {
66463
- const handle = await (0, import_promises62.open)(path4, "r").catch(() => null);
67954
+ const handle = await (0, import_promises63.open)(path4, "r").catch(() => null);
66464
67955
  if (handle === null) return null;
66465
67956
  try {
66466
67957
  const { size } = await handle.stat();
@@ -66494,7 +67985,7 @@ var decoder = new TextDecoder();
66494
67985
 
66495
67986
  // src/run-log/writer.ts
66496
67987
  var import_node_fs20 = require("fs");
66497
- var import_node_path61 = require("path");
67988
+ var import_node_path62 = require("path");
66498
67989
  init_runtime_v2();
66499
67990
  function lastSeq(fd, size) {
66500
67991
  for (const length of tailWindows(size)) {
@@ -66510,7 +68001,7 @@ function lastSeq(fd, size) {
66510
68001
  throw new RuntimeFault("record_too_large", "Run log tail record is larger than any record");
66511
68002
  }
66512
68003
  function openRunLog(path4, clock) {
66513
- (0, import_node_fs20.mkdirSync)((0, import_node_path61.dirname)(path4), { recursive: true, mode: 448 });
68004
+ (0, import_node_fs20.mkdirSync)((0, import_node_path62.dirname)(path4), { recursive: true, mode: 448 });
66514
68005
  const fd = (0, import_node_fs20.openSync)(path4, "a+", 384);
66515
68006
  let size = (0, import_node_fs20.fstatSync)(fd).size;
66516
68007
  let seq = lastSeq(fd, size);
@@ -66742,10 +68233,30 @@ async function admitAndRun(spec, context, append, sink, signal) {
66742
68233
  async function claimRun(spec, context) {
66743
68234
  if (await isRunClaimed(context.runsDir, spec.runId)) return null;
66744
68235
  const paths = runDirectory(context.runsDir, spec.runId);
66745
- await writeJsonFileAtomic(paths.meta, { runId: spec.runId, conversationId: spec.conversationId });
68236
+ await writeJsonFileAtomic(paths.meta, {
68237
+ runId: spec.runId,
68238
+ conversationId: spec.conversationId,
68239
+ ...spec.mode ? { agentMode: spec.mode } : {},
68240
+ ...spec.userMessage ? { userMessage: spec.userMessage } : {},
68241
+ ...spec.assistantMessage ? { assistantMessage: spec.assistantMessage } : {}
68242
+ });
66746
68243
  const log = openRunLog(paths.log, context.clock);
66747
68244
  const offset = log.append(runAccepted(context.machineId, context.clock.now()));
66748
68245
  context.onAppended(spec.runId, offset);
68246
+ if (spec.userMessage?.turnOrdinal !== null && spec.userMessage?.turnOrdinal !== void 0 && spec.assistantMessage?.turnOrdinal !== null && spec.assistantMessage?.turnOrdinal !== void 0) {
68247
+ try {
68248
+ await indexConversationRun(
68249
+ context.runsDir,
68250
+ spec.conversationId,
68251
+ spec.userMessage.turnOrdinal,
68252
+ spec.assistantMessage.turnOrdinal,
68253
+ spec.runId
68254
+ );
68255
+ context.onAppended(spec.runId, offset);
68256
+ } catch (error61) {
68257
+ context.log.warn("holder.conversation_index_failed", { runId: spec.runId, error: error61 });
68258
+ }
68259
+ }
66749
68260
  return log;
66750
68261
  }
66751
68262
  async function runClaimedTurn(spec, claimed, context, signal) {
@@ -66807,12 +68318,12 @@ var TASK_UNSUPPORTED = {
66807
68318
  message: "This agent cannot stop one background task."
66808
68319
  };
66809
68320
  function sha2564(value2) {
66810
- return (0, import_node_crypto28.createHash)("sha256").update(value2).digest("hex");
68321
+ return (0, import_node_crypto29.createHash)("sha256").update(value2).digest("hex");
66811
68322
  }
66812
68323
  function tokenMatches(expected, presented) {
66813
68324
  const a = Buffer.from(sha2564(expected), "hex");
66814
68325
  const b = Buffer.from(sha2564(presented), "hex");
66815
- return (0, import_node_crypto28.timingSafeEqual)(a, b);
68326
+ return (0, import_node_crypto29.timingSafeEqual)(a, b);
66816
68327
  }
66817
68328
  async function runHolder({
66818
68329
  launch,
@@ -66826,7 +68337,7 @@ async function runHolder({
66826
68337
  try {
66827
68338
  const identity = await readProcessIdentity(process.pid);
66828
68339
  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));
68340
+ const _engines = __using(_stack, recordSpawnedEngines(engineRecordsPath((0, import_node_path63.dirname)(launch.statusPath)), clock, log));
66830
68341
  const holder = {
66831
68342
  state: "idle",
66832
68343
  runId: null,
@@ -67120,7 +68631,7 @@ var DEFAULT_MAX_ACTIVE_RUNS = 32;
67120
68631
  var HOLDER_BUSY = "busy";
67121
68632
  async function listIds(dir, schema) {
67122
68633
  const ids = [];
67123
- for (const name of await (0, import_promises63.readdir)(dir).catch(() => [])) {
68634
+ for (const name of await (0, import_promises64.readdir)(dir).catch(() => [])) {
67124
68635
  const parsed = schema.safeParse(name);
67125
68636
  if (parsed.success) ids.push(parsed.data);
67126
68637
  }
@@ -67134,8 +68645,8 @@ function holderIdentity(status) {
67134
68645
  return command === void 0 ? { pid, startedAt } : { pid, startedAt, command };
67135
68646
  }
67136
68647
  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") };
68648
+ const dir = (0, import_node_path64.join)(paths.sessions, conversationId);
68649
+ return { dir, launch: (0, import_node_path64.join)(dir, "launch.json"), status: (0, import_node_path64.join)(dir, "holder.json") };
67139
68650
  }
67140
68651
  async function openSessions(deps) {
67141
68652
  const { paths, clock, log } = deps;
@@ -67176,7 +68687,7 @@ async function openSessions(deps) {
67176
68687
  await reapLeftoverEngines(engineRecordsPath(dir), { clock, log, conversationId }).catch(
67177
68688
  (error61) => log.warn("sessions.engine_reap_failed", { conversationId, error: error61 })
67178
68689
  );
67179
- await (0, import_promises63.rm)(dir, { recursive: true, force: true });
68690
+ await (0, import_promises64.rm)(dir, { recursive: true, force: true });
67180
68691
  };
67181
68692
  const retireIfGone = async (conversationId) => {
67182
68693
  const files = sessionFiles(paths, conversationId);
@@ -67264,7 +68775,7 @@ async function openSessions(deps) {
67264
68775
  log.info("sessions.reattached", { conversationId });
67265
68776
  return;
67266
68777
  }
67267
- if (alive) await (0, import_promises63.rm)(files.dir, { recursive: true, force: true });
68778
+ if (alive) await (0, import_promises64.rm)(files.dir, { recursive: true, force: true });
67268
68779
  else await discardSession(conversationId);
67269
68780
  };
67270
68781
  const busyRunIds = async () => {
@@ -67289,14 +68800,14 @@ async function openSessions(deps) {
67289
68800
  if (!busy.has(runId)) await markInterrupted(runId);
67290
68801
  }
67291
68802
  };
67292
- const spawn11 = async (conversationId) => {
68803
+ const spawn10 = async (conversationId) => {
67293
68804
  const files = sessionFiles(paths, conversationId);
67294
68805
  const launch = {
67295
68806
  protocol: HOLDER_PROTOCOL,
67296
68807
  conversationId,
67297
68808
  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"),
68809
+ endpoint: ipcEndpoint(paths.sockets, (0, import_node_crypto30.randomUUID)().slice(0, 8)),
68810
+ token: (0, import_node_crypto30.randomBytes)(32).toString("hex"),
67300
68811
  runsDir: paths.runs,
67301
68812
  statusPath: files.status
67302
68813
  };
@@ -67322,7 +68833,7 @@ async function openSessions(deps) {
67322
68833
  const meta3 = await readRunMeta(dir.meta);
67323
68834
  const last = await readLastRecord(dir.log);
67324
68835
  if (meta3 === null || last === null) return null;
67325
- const logged = await (0, import_promises63.stat)(dir.log).catch((error61) => {
68836
+ const logged = await (0, import_promises64.stat)(dir.log).catch((error61) => {
67326
68837
  if (errnoCode(error61) === "ENOENT") return null;
67327
68838
  throw error61;
67328
68839
  });
@@ -67433,7 +68944,7 @@ async function openSessions(deps) {
67433
68944
  return "started";
67434
68945
  }
67435
68946
  if (await activeRunsOtherThan(run2.runId) >= maxActiveRuns) return "waiting";
67436
- if (!connections.has(run2.conversationId)) await spawn11(run2.conversationId);
68947
+ if (!connections.has(run2.conversationId)) await spawn10(run2.conversationId);
67437
68948
  const connection = connections.get(run2.conversationId);
67438
68949
  if (connection === void 0) {
67439
68950
  throw new RuntimeFault("internal", "Holder connection missing");
@@ -67632,7 +69143,7 @@ function loadRuntimeConfig(env = process.env, totalMemoryBytes = (0, import_node
67632
69143
  providerProbes: ALAN_RUNTIME_PROVIDER_PROBES === "on",
67633
69144
  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
69145
  home,
67635
- configHome: XDG_CONFIG_HOME ?? (0, import_node_path64.join)(home, ".config"),
69146
+ configHome: XDG_CONFIG_HOME ?? (0, import_node_path65.join)(home, ".config"),
67636
69147
  ...githubProxyConfig({ ALAN_RUNTIME_GITHUB_PROXY, XDG_CONFIG_HOME, GH_CONFIG_DIR }, home),
67637
69148
  gitGatewayUrl: ALAN_RUNTIME_GIT_GATEWAY_URL ?? null,
67638
69149
  workspaceRoot: ALAN_RUNTIME_WORKSPACE_ROOT ?? null,
@@ -67641,10 +69152,10 @@ function loadRuntimeConfig(env = process.env, totalMemoryBytes = (0, import_node
67641
69152
  };
67642
69153
  }
67643
69154
  function githubProxyConfig(env, home) {
67644
- const configHome = env.XDG_CONFIG_HOME ?? (0, import_node_path64.join)(home, ".config");
69155
+ const configHome = env.XDG_CONFIG_HOME ?? (0, import_node_path65.join)(home, ".config");
67645
69156
  return {
67646
69157
  githubProxy: env.ALAN_RUNTIME_GITHUB_PROXY === "on",
67647
- ghConfigDir: env.GH_CONFIG_DIR ?? (0, import_node_path64.join)(configHome, "gh")
69158
+ ghConfigDir: env.GH_CONFIG_DIR ?? (0, import_node_path65.join)(configHome, "gh")
67648
69159
  };
67649
69160
  }
67650
69161
  function serviceEnvironment2(env, profile) {
@@ -67702,9 +69213,9 @@ function takeEnrollmentCodeFromEnv(env = process.env) {
67702
69213
  }
67703
69214
 
67704
69215
  // src/cli/context.ts
67705
- var import_promises64 = require("fs/promises");
69216
+ var import_promises65 = require("fs/promises");
67706
69217
  var import_node_os12 = require("os");
67707
- var import_node_path65 = require("path");
69218
+ var import_node_path66 = require("path");
67708
69219
  var DESKTOP_BUNDLE_IDS = {
67709
69220
  production: ["com.alan-ai.desktop"],
67710
69221
  staging: ["com.alan-ai.desktop.staging"],
@@ -67744,7 +69255,7 @@ function serviceSpec({ config: config2, paths, self }) {
67744
69255
  profile: config2.profile,
67745
69256
  program: serviceCommand(config2.host, self, launcher),
67746
69257
  environment: config2.serviceEnvironment,
67747
- logPath: (0, import_node_path65.join)(paths.logs, "service.log"),
69258
+ logPath: (0, import_node_path66.join)(paths.logs, "service.log"),
67748
69259
  associatedBundleIds: DESKTOP_BUNDLE_IDS[config2.profile]
67749
69260
  };
67750
69261
  }
@@ -67752,7 +69263,7 @@ async function installedServiceSpec(ctx) {
67752
69263
  const spec = serviceSpec(ctx);
67753
69264
  if (ctx.config.host === "app") return spec;
67754
69265
  const layout = installLayout(ctx.config.installDir, ctx.config.profile);
67755
- const installed = await (0, import_promises64.access)(layout.launcher).then(
69266
+ const installed = await (0, import_promises65.access)(layout.launcher).then(
67756
69267
  () => true,
67757
69268
  () => false
67758
69269
  );
@@ -67880,7 +69391,7 @@ var manifestRevisionSchema = external_exports.object({ revision: external_export
67880
69391
  async function manifestRevision(path4) {
67881
69392
  let raw;
67882
69393
  try {
67883
- raw = JSON.parse(await (0, import_promises65.readFile)(path4, "utf8"));
69394
+ raw = JSON.parse(await (0, import_promises66.readFile)(path4, "utf8"));
67884
69395
  } catch (error61) {
67885
69396
  throw new RuntimeFault("invalid_file", `Cannot read the skill manifest at ${path4}`, {
67886
69397
  cause: error61
@@ -67898,7 +69409,7 @@ async function runSkills(argv) {
67898
69409
  case "scan":
67899
69410
  writeJson({
67900
69411
  status: "failed",
67901
- attemptId: (0, import_node_crypto30.randomUUID)(),
69412
+ attemptId: (0, import_node_crypto31.randomUUID)(),
67902
69413
  retainedInventoryRevision: null,
67903
69414
  diagnostics: [
67904
69415
  { code: "RUNTIME_SKILL_SCAN_UNSUPPORTED", message: SKILLS_SYNCED_BY_RUNTIME }
@@ -67914,7 +69425,7 @@ async function runSkills(argv) {
67914
69425
  );
67915
69426
  }
67916
69427
  writeJson({
67917
- attemptId: (0, import_node_crypto30.randomUUID)(),
69428
+ attemptId: (0, import_node_crypto31.randomUUID)(),
67918
69429
  desiredRevision: await manifestRevision(manifest),
67919
69430
  skills: []
67920
69431
  });
@@ -67934,8 +69445,8 @@ async function runSkills(argv) {
67934
69445
  }
67935
69446
 
67936
69447
  // src/cli/commands/doctor.ts
67937
- var import_promises68 = require("fs/promises");
67938
- var import_node_path69 = require("path");
69448
+ var import_promises69 = require("fs/promises");
69449
+ var import_node_path70 = require("path");
67939
69450
  init_runtime_v2();
67940
69451
 
67941
69452
  // src/identity/credential.ts
@@ -68112,24 +69623,24 @@ async function authorizeDevice(input2) {
68112
69623
  }
68113
69624
 
68114
69625
  // src/identity/enroll.ts
68115
- var import_promises66 = require("fs/promises");
69626
+ var import_promises67 = require("fs/promises");
68116
69627
  init_runtime_v2();
68117
69628
 
68118
69629
  // src/identity/installation.ts
68119
- var import_node_crypto31 = require("crypto");
68120
- var import_node_path66 = require("path");
69630
+ var import_node_crypto32 = require("crypto");
69631
+ var import_node_path67 = require("path");
68121
69632
  init_zod();
68122
69633
  var installationFileSchema = external_exports.object({
68123
69634
  installationId: external_exports.uuid()
68124
69635
  });
68125
69636
  function installationPath(paths) {
68126
- return (0, import_node_path66.join)(paths.stateDir, "installation.json");
69637
+ return (0, import_node_path67.join)(paths.stateDir, "installation.json");
68127
69638
  }
68128
69639
  async function ensureInstallationId(paths) {
68129
69640
  const path4 = installationPath(paths);
68130
69641
  const existing = await readJsonFile(path4, installationFileSchema);
68131
69642
  if (existing.kind === "ok") return existing.value.installationId;
68132
- const created = { installationId: (0, import_node_crypto31.randomUUID)() };
69643
+ const created = { installationId: (0, import_node_crypto32.randomUUID)() };
68133
69644
  await writeJsonFileAtomic(path4, created);
68134
69645
  return created.installationId;
68135
69646
  }
@@ -68216,13 +69727,13 @@ async function enrollFromGrantFile(input2) {
68216
69727
  clock: input2.clock,
68217
69728
  access: input2.access
68218
69729
  });
68219
- await (0, import_promises66.rm)(input2.grantPath, { force: true });
69730
+ await (0, import_promises67.rm)(input2.grantPath, { force: true });
68220
69731
  return machine;
68221
69732
  }
68222
69733
 
68223
69734
  // src/identity/migrate-v1.ts
68224
- var import_promises67 = require("fs/promises");
68225
- var import_node_path67 = require("path");
69735
+ var import_promises68 = require("fs/promises");
69736
+ var import_node_path68 = require("path");
68226
69737
  init_runtime_v2();
68227
69738
  init_zod();
68228
69739
  var EXIT_POLL_MS = 200;
@@ -68243,11 +69754,11 @@ var ownerLeaseSchema = external_exports.looseObject({ pid: external_exports.numb
68243
69754
  function legacyConfigPath(home, profile) {
68244
69755
  switch (profile) {
68245
69756
  case "production":
68246
- return (0, import_node_path67.join)(home, ".alan", "agent", "config.json");
69757
+ return (0, import_node_path68.join)(home, ".alan", "agent", "config.json");
68247
69758
  case "staging":
68248
- return (0, import_node_path67.join)(home, ".alan-staging", "agent", "config.json");
69759
+ return (0, import_node_path68.join)(home, ".alan-staging", "agent", "config.json");
68249
69760
  default:
68250
- return (0, import_node_path67.join)(home, ".alan-dev", "agent", "config.json");
69761
+ return (0, import_node_path68.join)(home, ".alan-dev", "agent", "config.json");
68251
69762
  }
68252
69763
  }
68253
69764
  async function findLegacyInstall(home, profile) {
@@ -68272,8 +69783,8 @@ async function scrubLegacyInstall(install2) {
68272
69783
  const scrubbed = { ...install2.config, migratedToRuntimeV2: true };
68273
69784
  for (const key of SCRUBBED_KEYS) delete scrubbed[key];
68274
69785
  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 });
69786
+ await (0, import_promises68.rm)(install2.configPath, { force: true });
69787
+ await (0, import_promises68.rm)(install2.ownerLeasePath, { force: true });
68277
69788
  }
68278
69789
  async function exchangeCredential(deps) {
68279
69790
  const { config: config2 } = deps.install;
@@ -68382,7 +69893,7 @@ async function loadIdentity(paths, options = {}) {
68382
69893
  }
68383
69894
 
68384
69895
  // src/cli/commands/status.ts
68385
- var import_node_path68 = require("path");
69896
+ var import_node_path69 = require("path");
68386
69897
  async function serviceStatus(ctx) {
68387
69898
  try {
68388
69899
  return await createServiceManager(ctx.host, ctx.config.profile).status();
@@ -68409,7 +69920,7 @@ async function runtimeState(ctx) {
68409
69920
  const running = await readRunningRuntime(ctx.paths.lock);
68410
69921
  if (running === null) return { state: "offline", pid: null, localApi: null };
68411
69922
  const discovery = await readJsonFile(
68412
- (0, import_node_path68.join)(ctx.paths.stateDir, LOCAL_API_DISCOVERY_FILE),
69923
+ (0, import_node_path69.join)(ctx.paths.stateDir, LOCAL_API_DISCOVERY_FILE),
68413
69924
  localApiDiscoverySchema
68414
69925
  );
68415
69926
  const localApi = discovery.kind === "ok" && discovery.value.pid === running.pid ? {
@@ -68630,7 +70141,7 @@ async function runtimeCheck(ctx, status) {
68630
70141
  return check2("runtime", "warn", "No runtime is running for this profile");
68631
70142
  }
68632
70143
  const client = createRuntimeClient({
68633
- discoveryPath: (0, import_node_path69.join)(ctx.paths.stateDir, LOCAL_API_DISCOVERY_FILE)
70144
+ discoveryPath: (0, import_node_path70.join)(ctx.paths.stateDir, LOCAL_API_DISCOVERY_FILE)
68634
70145
  });
68635
70146
  try {
68636
70147
  const live = await client.status(AbortSignal.timeout(LOCAL_TIMEOUT_MS));
@@ -68657,7 +70168,7 @@ async function runtimeCheck(ctx, status) {
68657
70168
  }
68658
70169
  }
68659
70170
  async function probeHolder(dir, conversationId) {
68660
- const launch = await readJsonFile((0, import_node_path69.join)(dir, "launch.json"), holderLaunchSchema);
70171
+ const launch = await readJsonFile((0, import_node_path70.join)(dir, "launch.json"), holderLaunchSchema);
68661
70172
  if (launch.kind !== "ok") return null;
68662
70173
  try {
68663
70174
  const reply2 = await withTimeout(
@@ -68682,8 +70193,8 @@ async function probeHolder(dir, conversationId) {
68682
70193
  }
68683
70194
  }
68684
70195
  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);
70196
+ const names = await (0, import_promises69.readdir)(ctx.paths.sessions).catch(() => []);
70197
+ const holders = (await Promise.all(names.map((name) => probeHolder((0, import_node_path70.join)(ctx.paths.sessions, name), name)))).filter((facts) => facts !== null);
68687
70198
  const dead = holders.filter((holder) => !holder.alive).length;
68688
70199
  return check2(
68689
70200
  "holders",
@@ -68694,10 +70205,10 @@ async function holdersCheck(ctx) {
68694
70205
  }
68695
70206
  async function freeBytesAt(path4) {
68696
70207
  try {
68697
- const stats = await (0, import_promises68.statfs)(path4);
70208
+ const stats = await (0, import_promises69.statfs)(path4);
68698
70209
  return { path: path4, freeBytes: stats.bavail * stats.bsize };
68699
70210
  } catch (error61) {
68700
- const parent = (0, import_node_path69.dirname)(path4);
70211
+ const parent = (0, import_node_path70.dirname)(path4);
68701
70212
  if (parent === path4) throw error61;
68702
70213
  return freeBytesAt(parent);
68703
70214
  }
@@ -68833,7 +70344,7 @@ async function runDoctor(argv, context = cliContext) {
68833
70344
  }
68834
70345
 
68835
70346
  // src/cli/commands/git-credential.ts
68836
- var import_promises69 = require("fs/promises");
70347
+ var import_promises70 = require("fs/promises");
68837
70348
  var import_node_net4 = require("net");
68838
70349
  var MAX_RESPONSE_BYTES = 64 * 1024;
68839
70350
  async function readAll(stream) {
@@ -68943,7 +70454,7 @@ async function configure(argv) {
68943
70454
  }
68944
70455
  async function configureGitGateway(config2, gatewayUrl, signal) {
68945
70456
  const { launcher } = installLayout(config2.installDir, config2.profile);
68946
- const installed = await (0, import_promises69.access)(launcher).then(
70457
+ const installed = await (0, import_promises70.access)(launcher).then(
68947
70458
  () => true,
68948
70459
  () => false
68949
70460
  );
@@ -68970,7 +70481,7 @@ async function runGitCredential(argv) {
68970
70481
  }
68971
70482
 
68972
70483
  // src/cli/commands/hold.ts
68973
- var import_node_path70 = require("path");
70484
+ var import_node_path71 = require("path");
68974
70485
  init_agent2();
68975
70486
  init_runtime_v2();
68976
70487
  async function machineAccess(paths, log, conversationId, transport) {
@@ -69028,7 +70539,7 @@ async function runHold(argv) {
69028
70539
  const config2 = loadRuntimeConfig();
69029
70540
  const paths = runtimePaths(config2.stateDir);
69030
70541
  const log = __using(_stack, openFileLog(
69031
- (0, import_node_path70.join)(paths.logs, `holder-${launch.value.conversationId}.jsonl`),
70542
+ (0, import_node_path71.join)(paths.logs, `holder-${launch.value.conversationId}.jsonl`),
69032
70543
  config2.logLevel,
69033
70544
  systemClock
69034
70545
  ));
@@ -69039,7 +70550,7 @@ async function runHold(argv) {
69039
70550
  );
69040
70551
  const transport = __using(_stack, createHttpTransport());
69041
70552
  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`);
70553
+ const credentialPath = (0, import_node_path71.join)(paths.tmp, "mcp", `${launch.value.conversationId}.json`);
69043
70554
  const managedMcp = __using(_stack, access7.managedMcp === void 0 ? void 0 : createHelperMcpAccess({
69044
70555
  managedMcp: access7.managedMcp,
69045
70556
  conversationId: launch.value.conversationId,
@@ -69079,7 +70590,7 @@ async function runHold(argv) {
69079
70590
  }
69080
70591
 
69081
70592
  // src/cli/commands/hook.ts
69082
- var import_node_path71 = require("path");
70593
+ var import_node_path72 = require("path");
69083
70594
  var RUNTIME_ANSWER_MS = 2e3;
69084
70595
  var DEBUG_VARIABLE = "ALAN_HOOK_DEBUG";
69085
70596
  function flag(argv, name) {
@@ -69111,7 +70622,7 @@ async function forwardHook(argv, io) {
69111
70622
  return "transcript outside provider root";
69112
70623
  }
69113
70624
  const verdict = await io.send(
69114
- (0, import_node_path71.join)(io.stateDir, LOCAL_API_DISCOVERY_FILE),
70625
+ (0, import_node_path72.join)(io.stateDir, LOCAL_API_DISCOVERY_FILE),
69115
70626
  hookSignal,
69116
70627
  AbortSignal.timeout(RUNTIME_ANSWER_MS)
69117
70628
  );
@@ -69147,7 +70658,7 @@ async function runHook(argv, overrides = {}) {
69147
70658
  }
69148
70659
 
69149
70660
  // src/cli/commands/ingestion-hooks.ts
69150
- var import_promises70 = require("fs/promises");
70661
+ var import_promises71 = require("fs/promises");
69151
70662
  var CODEX_TRUST_NOTE = "Codex runs new hooks only after you review them: open /hooks in Codex.";
69152
70663
  function isAction(value2) {
69153
70664
  return value2 === "enable" || value2 === "disable" || value2 === "status";
@@ -69170,7 +70681,7 @@ function errorMessage2(error61) {
69170
70681
  return error61 instanceof Error ? error61.message : String(error61);
69171
70682
  }
69172
70683
  async function exists5(path4) {
69173
- return (0, import_promises70.access)(path4).then(
70684
+ return (0, import_promises71.access)(path4).then(
69174
70685
  () => true,
69175
70686
  () => false
69176
70687
  );
@@ -69273,10 +70784,10 @@ async function runIntegrationsCommand(argv) {
69273
70784
  }
69274
70785
 
69275
70786
  // src/cli/commands/legacy.ts
69276
- var import_node_path73 = require("path");
70787
+ var import_node_path74 = require("path");
69277
70788
 
69278
70789
  // src/cli/commands/setup.ts
69279
- var import_node_path72 = require("path");
70790
+ var import_node_path73 = require("path");
69280
70791
  init_zod();
69281
70792
 
69282
70793
  // src/cli/legacy.ts
@@ -69358,7 +70869,7 @@ async function grantFileCredential(argv, grantPath, ctx, deps) {
69358
70869
  return enrollFromGrantFile({
69359
70870
  paths: ctx.paths,
69360
70871
  storeKind: credentialStoreFlag(argv) ?? ctx.config.credentialStore,
69361
- grantPath: (0, import_node_path72.resolve)(grantPath),
70872
+ grantPath: (0, import_node_path73.resolve)(grantPath),
69362
70873
  clock: deps.clock,
69363
70874
  access: ctx.access
69364
70875
  });
@@ -69434,7 +70945,7 @@ async function runSetup(argv, signal) {
69434
70945
  var _stack = [];
69435
70946
  try {
69436
70947
  const ctx = cliContext();
69437
- const log = __using(_stack, openFileLog((0, import_node_path72.join)(ctx.paths.logs, "cli.jsonl"), ctx.config.logLevel, systemClock));
70948
+ const log = __using(_stack, openFileLog((0, import_node_path73.join)(ctx.paths.logs, "cli.jsonl"), ctx.config.logLevel, systemClock));
69438
70949
  const result = await setupMachine(argv, ctx, {
69439
70950
  enrollment: (apiUrl) => createEnrollmentClient({ apiUrl }),
69440
70951
  isProcessAlive,
@@ -69517,7 +71028,7 @@ async function runToken(argv, signal) {
69517
71028
  );
69518
71029
  }
69519
71030
  const ctx = cliContext();
69520
- const log = __using(_stack, openFileLog((0, import_node_path73.join)(ctx.paths.logs, "cli.jsonl"), ctx.config.logLevel, systemClock));
71031
+ const log = __using(_stack, openFileLog((0, import_node_path74.join)(ctx.paths.logs, "cli.jsonl"), ctx.config.logLevel, systemClock));
69521
71032
  const result = await rotateMachineCredential(ctx, { clock: systemClock, log, signal });
69522
71033
  process.stdout.write(`${rotationMessage(result)}
69523
71034
  `);
@@ -69529,8 +71040,8 @@ async function runToken(argv, signal) {
69529
71040
  }
69530
71041
 
69531
71042
  // src/cli/commands/logout.ts
69532
- var import_promises71 = require("fs/promises");
69533
- var import_node_path74 = require("path");
71043
+ var import_promises72 = require("fs/promises");
71044
+ var import_node_path75 = require("path");
69534
71045
  init_runtime_v2();
69535
71046
  var RUNTIME_EXIT_WAIT_MS = 35e3;
69536
71047
  var TURN_END_WAIT_MS = 3e4;
@@ -69589,9 +71100,9 @@ async function stopHolder(launch, deps, outcome2) {
69589
71100
  }
69590
71101
  async function stopHeldRuns(ctx, deps, outcome2 = "aborted") {
69591
71102
  const stopped = [];
69592
- for (const name of await (0, import_promises71.readdir)(ctx.paths.sessions).catch(() => [])) {
71103
+ for (const name of await (0, import_promises72.readdir)(ctx.paths.sessions).catch(() => [])) {
69593
71104
  const launch = await readJsonFile(
69594
- (0, import_node_path74.join)(ctx.paths.sessions, name, "launch.json"),
71105
+ (0, import_node_path75.join)(ctx.paths.sessions, name, "launch.json"),
69595
71106
  holderLaunchSchema
69596
71107
  );
69597
71108
  if (launch.kind !== "ok") continue;
@@ -69628,13 +71139,13 @@ async function forgetMachineLocally(ctx) {
69628
71139
  const machine = await readMachineFile(ctx.paths);
69629
71140
  if (machine === null) return;
69630
71141
  await credentialStoreFor(ctx.paths, machine.credentialStore, ctx.access).clear();
69631
- await (0, import_promises71.rm)(ctx.paths.machine, { force: true });
71142
+ await (0, import_promises72.rm)(ctx.paths.machine, { force: true });
69632
71143
  }
69633
71144
  async function runLogout(argv, signal) {
69634
71145
  var _stack = [];
69635
71146
  try {
69636
71147
  const ctx = cliContext();
69637
- const log = __using(_stack, openFileLog((0, import_node_path74.join)(ctx.paths.logs, "cli.jsonl"), ctx.config.logLevel, systemClock));
71148
+ const log = __using(_stack, openFileLog((0, import_node_path75.join)(ctx.paths.logs, "cli.jsonl"), ctx.config.logLevel, systemClock));
69638
71149
  const result = await logoutMachine(argv, ctx, {
69639
71150
  api: (apiUrl, accessToken) => createApiClient({ apiUrl, accessToken }),
69640
71151
  stopHeldRuns,
@@ -69651,7 +71162,8 @@ async function runLogout(argv, signal) {
69651
71162
  }
69652
71163
 
69653
71164
  // src/cli/commands/run.ts
69654
- var import_node_path78 = require("path");
71165
+ var import_node_fs23 = require("fs");
71166
+ var import_node_path79 = require("path");
69655
71167
 
69656
71168
  // src/local-api/app-attachments.ts
69657
71169
  function createAppAttachments(clock) {
@@ -69685,7 +71197,9 @@ function createAppAttachments(clock) {
69685
71197
  // src/local-api/run-appends.ts
69686
71198
  function createRunAppends() {
69687
71199
  const waiters = /* @__PURE__ */ new Map();
71200
+ const listeners = /* @__PURE__ */ new Set();
69688
71201
  const wake = (runId) => {
71202
+ for (const listener of listeners) listener(runId);
69689
71203
  const pending = waiters.get(runId);
69690
71204
  if (pending === void 0) return;
69691
71205
  waiters.delete(runId);
@@ -69693,8 +71207,17 @@ function createRunAppends() {
69693
71207
  };
69694
71208
  return {
69695
71209
  notify: wake,
71210
+ subscribe: (listener) => {
71211
+ listeners.add(listener);
71212
+ return {
71213
+ [Symbol.dispose]: () => {
71214
+ listeners.delete(listener);
71215
+ }
71216
+ };
71217
+ },
69696
71218
  notifyAll: () => {
69697
71219
  for (const runId of [...waiters.keys()]) wake(runId);
71220
+ for (const listener of listeners) listener(null);
69698
71221
  },
69699
71222
  nextAppend: (runId, signal) => {
69700
71223
  if (signal.aborted) return Promise.resolve();
@@ -69716,18 +71239,18 @@ function createRunAppends() {
69716
71239
  }
69717
71240
 
69718
71241
  // src/local-api/server.ts
69719
- var import_node_crypto33 = require("crypto");
69720
- var import_promises72 = require("fs/promises");
71242
+ var import_node_crypto34 = require("crypto");
71243
+ var import_promises73 = require("fs/promises");
69721
71244
  var import_node_http4 = require("http");
69722
- var import_node_path75 = require("path");
71245
+ var import_node_path76 = require("path");
69723
71246
 
69724
71247
  // src/local-api/guard.ts
69725
- var import_node_crypto32 = require("crypto");
71248
+ var import_node_crypto33 = require("crypto");
69726
71249
  var ALLOWED = { kind: "allowed" };
69727
71250
  function tokenMatches2(expected, header) {
69728
71251
  if (header === void 0 || !header.startsWith("Bearer ")) return false;
69729
71252
  const presented = Buffer.from(header.slice("Bearer ".length));
69730
- return presented.length === expected.length && (0, import_node_crypto32.timingSafeEqual)(presented, expected);
71253
+ return presented.length === expected.length && (0, import_node_crypto33.timingSafeEqual)(presented, expected);
69731
71254
  }
69732
71255
  function isBrowserReachable(req, allowedHosts) {
69733
71256
  if (req.headers.origin !== void 0 || req.headers.referer !== void 0) return true;
@@ -69835,6 +71358,283 @@ function requestSignal(res) {
69835
71358
  init_runtime_v2();
69836
71359
  init_zod();
69837
71360
 
71361
+ // src/local-api/conversation-messages.ts
71362
+ init_acp();
71363
+ init_runtime_v2();
71364
+ function applyLogLine(line, assistantMessageId, state) {
71365
+ const raw = JSON.parse(line);
71366
+ const record2 = runLogRecordSchema.safeParse(raw);
71367
+ if (!record2.success) return null;
71368
+ const kind = record2.data.update.sessionUpdate;
71369
+ if (isRunLifecycleKind(kind)) {
71370
+ const lifecycle = runLifecycleUpdateSchema.parse(record2.data.update);
71371
+ if (lifecycle.sessionUpdate === "_alan/run.accepted") {
71372
+ state.state = "running";
71373
+ return false;
71374
+ }
71375
+ const ended = lifecycle.sessionUpdate === "_alan/run.ended";
71376
+ applySessionEvent(state, {
71377
+ seq: record2.data.seq,
71378
+ at: record2.data.at,
71379
+ update: {
71380
+ sessionUpdate: "state_update",
71381
+ state: ended ? "idle" : "running",
71382
+ ...ended && {
71383
+ stopReason: lifecycle.outcome === "aborted" || lifecycle.outcome === "interrupted" ? "cancelled" : "end_turn"
71384
+ }
71385
+ }
71386
+ });
71387
+ return ended;
71388
+ }
71389
+ const event = scopeTranscriptEvent({ ...record2.data, turnId: assistantMessageId });
71390
+ if (!event) return null;
71391
+ applySessionEvent(state, event);
71392
+ return false;
71393
+ }
71394
+ function applyLogChunk(text2, assistantMessageId, state) {
71395
+ let ended = false;
71396
+ for (const line of text2.trimEnd().split("\n")) {
71397
+ const applied = applyLogLine(line, assistantMessageId, state);
71398
+ if (applied === null) throw new Error("Invalid local transcript record");
71399
+ if (applied) ended = true;
71400
+ }
71401
+ return ended;
71402
+ }
71403
+ async function openLocalTurnProjection(runsDir, runId, conversationId, ordinal) {
71404
+ const paths = runDirectory(runsDir, runId);
71405
+ const meta3 = await readRunMeta(paths.meta);
71406
+ if (!meta3?.userMessage || !meta3.assistantMessage || meta3.conversationId !== conversationId || meta3.userMessage.turnOrdinal !== ordinal)
71407
+ return null;
71408
+ const assistantMessageId = meta3.assistantMessage.id;
71409
+ const state = emptyTranscript();
71410
+ const promptAt = Date.parse(meta3.userMessage.createdAt);
71411
+ applySessionEvent(state, {
71412
+ seq: 0,
71413
+ at: Number.isFinite(promptAt) ? promptAt : 0,
71414
+ update: {
71415
+ sessionUpdate: "user_message",
71416
+ messageId: meta3.userMessage.id,
71417
+ content: [{ type: "text", text: meta3.userMessage.content }],
71418
+ _meta: {
71419
+ ...meta3.userMessage.clientMessageId ? { "alan.dev/clientMessageId": meta3.userMessage.clientMessageId } : {},
71420
+ ...meta3.agentMode ? { "alan.dev/agentMode": meta3.agentMode } : {},
71421
+ ...meta3.userMessage.attachmentIds?.length ? { "alan.dev/attachmentIds": meta3.userMessage.attachmentIds } : {}
71422
+ }
71423
+ }
71424
+ });
71425
+ const reader = await openRunLogReader(paths.log).catch((error61) => {
71426
+ if (error61.code === "ENOENT") return null;
71427
+ throw error61;
71428
+ });
71429
+ if (!reader) return null;
71430
+ let offset = toByteOffset(0);
71431
+ let ended = false;
71432
+ let snapshot2;
71433
+ let prepared;
71434
+ const merge2 = /* @__PURE__ */ new Map();
71435
+ const decoder3 = new TextDecoder();
71436
+ const readState = async () => {
71437
+ const priorOffset = offset;
71438
+ for (; ; ) {
71439
+ const chunk = await reader.readFrom(offset, DEFAULT_RUN_LOG_LIMIT);
71440
+ if (chunk.bytes.length === 0) break;
71441
+ if (applyLogChunk(decoder3.decode(chunk.bytes), assistantMessageId, state)) ended = true;
71442
+ offset = chunk.to;
71443
+ }
71444
+ if (offset === priorOffset && snapshot2) return snapshot2;
71445
+ if (ended) state.state = "idle";
71446
+ snapshot2 = mergeTranscriptMessages(
71447
+ [{ messageId: assistantMessageId, turnOrdinal: ordinal, role: "assistant", state }],
71448
+ merge2
71449
+ );
71450
+ return snapshot2;
71451
+ };
71452
+ return {
71453
+ runId,
71454
+ ordinal,
71455
+ readState,
71456
+ read: async () => {
71457
+ const current = await readState();
71458
+ if (prepared?.state !== current)
71459
+ prepared = { ...conversationTurnView(ordinal, current, prepared?.display), markdown: "" };
71460
+ return prepared;
71461
+ },
71462
+ [Symbol.asyncDispose]: async () => {
71463
+ await reader[Symbol.asyncDispose]();
71464
+ }
71465
+ };
71466
+ }
71467
+ async function projectLocalRun(runsDir, runId, conversationId, ordinal) {
71468
+ var _stack = [];
71469
+ try {
71470
+ const projection = __using(_stack, await openLocalTurnProjection(runsDir, runId, conversationId, ordinal), true);
71471
+ return projection ? await projection.read() : null;
71472
+ } catch (_) {
71473
+ var _error = _, _hasError = true;
71474
+ } finally {
71475
+ var _promise2 = __callDispose(_stack, _error, _hasError);
71476
+ _promise2 && await _promise2;
71477
+ }
71478
+ }
71479
+ async function readLocalConversationMessages(runsDir, conversationId, limit, before, projection) {
71480
+ const coverage = await readConversationIndexCoverage(runsDir, conversationId);
71481
+ if (coverage === null || before !== void 0 && before <= coverage.lowestOrdinal) return null;
71482
+ const indexed = (await readConversationRunIndex(runsDir, conversationId, before, limit + 1)).filter((entry) => entry.ordinal >= coverage.lowestOrdinal);
71483
+ if (before === void 0 && indexed[0]?.ordinal !== coverage.highestOrdinal) return null;
71484
+ if (before !== void 0 && indexed[0]?.nextOrdinal !== before) return null;
71485
+ if (indexed.some((entry, index) => index > 0 && entry.nextOrdinal !== indexed[index - 1].ordinal))
71486
+ return null;
71487
+ if (indexed.length < limit && indexed.at(-1)?.ordinal !== coverage.lowestOrdinal) return null;
71488
+ const selected = indexed.slice(0, limit);
71489
+ if (selected.length === 0) return null;
71490
+ const turns = await Promise.all(
71491
+ selected.map(
71492
+ (entry) => entry.runId === projection?.runId ? projection.read() : projectLocalRun(runsDir, entry.runId, conversationId, entry.ordinal)
71493
+ )
71494
+ );
71495
+ if (turns.some((turn) => turn === null)) return null;
71496
+ const completeTurns = turns.filter((turn) => turn !== null);
71497
+ return {
71498
+ turns: compactConversationMessageTurns(completeTurns, before === void 0),
71499
+ before: selected.at(-1)?.ordinal === 0 ? null : String(selected.at(-1)?.ordinal),
71500
+ revision: `local-${selected[0].runId}`,
71501
+ streamCursor: ""
71502
+ };
71503
+ }
71504
+
71505
+ // src/local-api/conversation-messages-stream.ts
71506
+ init_acp();
71507
+ async function readChangedTurn(deps, conversationId, runId, slot) {
71508
+ const meta3 = await readRunMeta(runDirectory(deps.runsDir, runId).meta);
71509
+ if (meta3?.conversationId !== conversationId || meta3.userMessage?.turnOrdinal == null) return null;
71510
+ if (slot.current?.ordinal === meta3.userMessage.turnOrdinal && slot.current.runId !== runId) {
71511
+ const [latest] = await readConversationRunIndex(
71512
+ deps.runsDir,
71513
+ conversationId,
71514
+ meta3.userMessage.turnOrdinal + 1,
71515
+ 1
71516
+ );
71517
+ if (latest?.runId !== runId) return null;
71518
+ }
71519
+ if (slot.current && meta3.userMessage.turnOrdinal < slot.current.ordinal) {
71520
+ const previous = await openLocalTurnProjection(
71521
+ deps.runsDir,
71522
+ runId,
71523
+ conversationId,
71524
+ meta3.userMessage.turnOrdinal
71525
+ );
71526
+ if (!previous) return null;
71527
+ return {
71528
+ projection: previous,
71529
+ changed: { ordinal: previous.ordinal, state: await previous.readState() }
71530
+ };
71531
+ }
71532
+ if (slot.current?.runId !== runId) {
71533
+ const next = await openLocalTurnProjection(
71534
+ deps.runsDir,
71535
+ runId,
71536
+ conversationId,
71537
+ meta3.userMessage.turnOrdinal
71538
+ );
71539
+ await slot.current?.[Symbol.asyncDispose]();
71540
+ slot.current = next;
71541
+ }
71542
+ if (!slot.current) throw new Error("Local transcript metadata is incomplete");
71543
+ return {
71544
+ projection: slot.current,
71545
+ changed: { ordinal: slot.current.ordinal, state: await slot.current.readState() }
71546
+ };
71547
+ }
71548
+ async function nextChangedRuns(bell, signal) {
71549
+ if (bell.pending.size === 0) {
71550
+ await new Promise((resolve12) => {
71551
+ bell.wake = resolve12;
71552
+ if (signal.aborted || bell.pending.size > 0) resolve12();
71553
+ });
71554
+ bell.wake = void 0;
71555
+ }
71556
+ if (signal.aborted) return [];
71557
+ await systemClock.sleep(50, signal);
71558
+ const changed = [...bell.pending];
71559
+ bell.pending.clear();
71560
+ return changed;
71561
+ }
71562
+ async function writeChangedTurn(writer, runId, read) {
71563
+ const { ordinal, state } = read.changed;
71564
+ if (state === writer.lastState) return;
71565
+ writer.lastState = state;
71566
+ const patch = writer.frames === "patch";
71567
+ const data = patch ? JSON.stringify(writer.encode(ordinal, state)) : JSON.stringify(await read.projection.read());
71568
+ await writeEvent(writer.res, {
71569
+ name: patch ? LIVE_TURN_EVENT : "turn",
71570
+ id: `${runId}`,
71571
+ dataLines: [data]
71572
+ });
71573
+ }
71574
+ async function streamLocalConversationMessages(deps, conversationId, limit, frames, res, signal) {
71575
+ var _stack = [];
71576
+ try {
71577
+ const bell = { pending: /* @__PURE__ */ new Set(), wake: void 0 };
71578
+ const slot = { current: null };
71579
+ const _subscription = __using(_stack, deps.appends.subscribe((runId) => {
71580
+ const changed = runId ?? slot.current?.runId;
71581
+ if (changed) bell.pending.add(changed);
71582
+ bell.wake?.();
71583
+ }));
71584
+ signal.addEventListener("abort", () => bell.wake?.(), { once: true });
71585
+ try {
71586
+ const [newest] = await readConversationRunIndex(deps.runsDir, conversationId, void 0, 1);
71587
+ if (newest)
71588
+ slot.current = await openLocalTurnProjection(
71589
+ deps.runsDir,
71590
+ newest.runId,
71591
+ conversationId,
71592
+ newest.ordinal
71593
+ );
71594
+ const writer = {
71595
+ frames,
71596
+ encode: createLiveTurnFrameEncoder(),
71597
+ res,
71598
+ lastState: await slot.current?.readState()
71599
+ };
71600
+ const page = await readLocalConversationMessages(
71601
+ deps.runsDir,
71602
+ conversationId,
71603
+ limit,
71604
+ void 0,
71605
+ slot.current ?? void 0
71606
+ );
71607
+ if (!page) {
71608
+ sendError(res, 404, "not_found", "This computer has no complete local page");
71609
+ return;
71610
+ }
71611
+ startEventStream(res);
71612
+ await writeEvent(res, {
71613
+ name: "snapshot",
71614
+ id: page.revision,
71615
+ dataLines: [JSON.stringify(page)]
71616
+ });
71617
+ while (!signal.aborted) {
71618
+ for (const runId of await nextChangedRuns(bell, signal)) {
71619
+ const read = await readChangedTurn(deps, conversationId, runId, slot);
71620
+ if (!read) continue;
71621
+ try {
71622
+ await writeChangedTurn(writer, runId, read);
71623
+ } finally {
71624
+ if (read.projection !== slot.current) await read.projection[Symbol.asyncDispose]();
71625
+ }
71626
+ }
71627
+ }
71628
+ } finally {
71629
+ await slot.current?.[Symbol.asyncDispose]();
71630
+ }
71631
+ } catch (_) {
71632
+ var _error = _, _hasError = true;
71633
+ } finally {
71634
+ __callDispose(_stack, _error, _hasError);
71635
+ }
71636
+ }
71637
+
69838
71638
  // src/local-api/request.ts
69839
71639
  async function readBody3(request2, schema) {
69840
71640
  const body = await readJsonBody(request2.req);
@@ -70033,6 +71833,13 @@ async function followRunLogRoute(deps, runId, url3, res, signal) {
70033
71833
 
70034
71834
  // src/local-api/routes.ts
70035
71835
  var RUN_PATH = /^\/v2\/runs\/([^/]+)\/(log|log\/stream|abort)$/;
71836
+ var CONVERSATION_MESSAGES_PATH = /^\/v2\/conversations\/([^/]+)\/messages(\/sse)?$/;
71837
+ var conversationMessagesQuerySchema = external_exports.object({
71838
+ limit: external_exports.coerce.number().int().min(1).max(100).default(10),
71839
+ before: external_exports.coerce.number().int().nonnegative().optional(),
71840
+ runtimeId: external_exports.string().uuid().optional(),
71841
+ frames: external_exports.enum(["turn", "patch"]).default("turn")
71842
+ });
70036
71843
  var emptyBodySchema = external_exports.object({});
70037
71844
  function activeRunIds(runs) {
70038
71845
  return runs.filter((run2) => run2.state !== "ended").map((run2) => run2.runId);
@@ -70252,6 +72059,44 @@ var FIXED_ROUTES = new Map([
70252
72059
  [LOCAL_API_ROUTES.providerExternal, { method: "POST", handle: providerExternal }],
70253
72060
  ...machineFeatureRoutes
70254
72061
  ]);
72062
+ async function routeConversationMessages(deps, request2, conversationMatch) {
72063
+ if (request2.req.method !== "GET") {
72064
+ sendError(request2.res, 405, "method_not_allowed", "Use GET");
72065
+ return;
72066
+ }
72067
+ const conversationId = conversationIdSchema.safeParse(conversationMatch[1]);
72068
+ const query = conversationMessagesQuerySchema.safeParse(
72069
+ Object.fromEntries(request2.url.searchParams)
72070
+ );
72071
+ if (!conversationId.success || !query.success) {
72072
+ sendError(request2.res, 400, "invalid_request", "Invalid conversation messages request");
72073
+ return;
72074
+ }
72075
+ if (query.data.runtimeId && query.data.runtimeId !== deps.readFacts().machineId) {
72076
+ sendError(request2.res, 404, "not_found", "This conversation runs on another computer");
72077
+ return;
72078
+ }
72079
+ if (conversationMatch[2])
72080
+ return streamLocalConversationMessages(
72081
+ deps,
72082
+ conversationId.data,
72083
+ query.data.limit,
72084
+ query.data.frames,
72085
+ request2.res,
72086
+ request2.signal
72087
+ );
72088
+ const page = await readLocalConversationMessages(
72089
+ deps.runsDir,
72090
+ conversationId.data,
72091
+ query.data.limit,
72092
+ query.data.before
72093
+ );
72094
+ if (page === null) {
72095
+ sendError(request2.res, 404, "not_found", "This computer has no complete local page");
72096
+ return;
72097
+ }
72098
+ sendJson(request2.res, 200, page);
72099
+ }
70255
72100
  async function routeRun(deps, request2, match) {
70256
72101
  const runId = runIdSchema.safeParse(match[1]);
70257
72102
  const action = match[2];
@@ -70279,6 +72124,9 @@ async function route(deps, request2) {
70279
72124
  }
70280
72125
  const match = RUN_PATH.exec(request2.url.pathname);
70281
72126
  if (match !== null) return routeRun(deps, request2, match);
72127
+ const conversationMatch = CONVERSATION_MESSAGES_PATH.exec(request2.url.pathname);
72128
+ if (conversationMatch !== null)
72129
+ return routeConversationMessages(deps, request2, conversationMatch);
70282
72130
  sendError(request2.res, 404, "not_found", "Not found");
70283
72131
  }
70284
72132
 
@@ -70328,6 +72176,15 @@ var REQUEST_TIMEOUT_MS8 = 1e4;
70328
72176
  var KEEP_ALIVE_TIMEOUT_MS = 2e3;
70329
72177
  var ACTION_TIMEOUT_MS = 3e4;
70330
72178
  var PROVIDER_INSTALL_TIMEOUT_MS = 10 * 6e4;
72179
+ function localRequestSignal(path4, closed) {
72180
+ if (path4.endsWith("/stream") || path4.endsWith("/sse")) return closed;
72181
+ return AbortSignal.any([
72182
+ closed,
72183
+ AbortSignal.timeout(
72184
+ path4 === LOCAL_API_ROUTES.providerInstall ? PROVIDER_INSTALL_TIMEOUT_MS : ACTION_TIMEOUT_MS
72185
+ )
72186
+ ]);
72187
+ }
70331
72188
  async function listenOnLoopback(server) {
70332
72189
  await new Promise((resolve12, reject) => {
70333
72190
  server.once("error", reject);
@@ -70372,11 +72229,12 @@ async function serveLocalApi(deps) {
70372
72229
  server.keepAliveTimeout = KEEP_ALIVE_TIMEOUT_MS;
70373
72230
  server.maxConnections = HARD_MAX_CONNECTIONS;
70374
72231
  const port = await listenOnLoopback(server);
70375
- const token = (0, import_node_crypto33.randomBytes)(32).toString("base64url");
72232
+ const token = (0, import_node_crypto34.randomBytes)(32).toString("base64url");
70376
72233
  const guard = createRequestGuard({ token, port, rateLimit: limits.rateLimit, clock });
70377
72234
  const appAttachments = createAppAttachments(clock);
70378
72235
  const routeDeps = {
70379
72236
  feed,
72237
+ readFacts: deps.readFacts,
70380
72238
  appAttachments,
70381
72239
  actions: deps.actions,
70382
72240
  runsDir: deps.runsDir,
@@ -70398,15 +72256,11 @@ async function serveLocalApi(deps) {
70398
72256
  inFlight += 1;
70399
72257
  const url3 = new URL(req.url ?? "/", `http://127.0.0.1:${port}`);
70400
72258
  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
- ]);
72259
+ const signal = localRequestSignal(url3.pathname, closed);
70407
72260
  try {
70408
72261
  await route(routeDeps, { req, res, url: url3, signal });
70409
72262
  } catch (error61) {
72263
+ if (closed.aborted) return;
70410
72264
  log.warn("local_api.request_failed", { path: url3.pathname, error: error61 });
70411
72265
  sendError(res, 500, "internal", "The runtime could not complete the request");
70412
72266
  } finally {
@@ -70422,7 +72276,7 @@ async function serveLocalApi(deps) {
70422
72276
  startedAtMs,
70423
72277
  runtimeVersion: deps.runtimeVersion
70424
72278
  };
70425
- const discoveryPath = (0, import_node_path75.join)(deps.stateDir, LOCAL_API_DISCOVERY_FILE);
72279
+ const discoveryPath = (0, import_node_path76.join)(deps.stateDir, LOCAL_API_DISCOVERY_FILE);
70426
72280
  await writeJsonFileAtomic(discoveryPath, discovery);
70427
72281
  const followers = startMaintenance({
70428
72282
  everyMs: limits.refreshEveryMs,
@@ -70456,7 +72310,7 @@ async function serveLocalApi(deps) {
70456
72310
  await watchedStatus[Symbol.asyncDispose]();
70457
72311
  const current = await readJsonFile(discoveryPath, localApiDiscoverySchema);
70458
72312
  if (current.kind === "ok" && current.value.token === token) {
70459
- await (0, import_promises72.rm)(discoveryPath, { force: true });
72313
+ await (0, import_promises73.rm)(discoveryPath, { force: true });
70460
72314
  }
70461
72315
  await closeServer(server);
70462
72316
  log.info("local_api.closed", {});
@@ -70541,7 +72395,7 @@ function machineFeatureActions(deps) {
70541
72395
  }
70542
72396
 
70543
72397
  // src/cli/commands/machine-plane.ts
70544
- var import_node_path77 = require("path");
72398
+ var import_node_path78 = require("path");
70545
72399
 
70546
72400
  // src/link/index.ts
70547
72401
  init_runtime_v2();
@@ -74209,7 +76063,7 @@ function refusalFailure(refusal2) {
74209
76063
  }
74210
76064
 
74211
76065
  // src/link/probe.ts
74212
- var import_promises73 = require("dns/promises");
76066
+ var import_promises74 = require("dns/promises");
74213
76067
  var import_node_net5 = require("net");
74214
76068
  var import_node_tls2 = require("tls");
74215
76069
  var PROBE_TIMEOUT_MS4 = 5e3;
@@ -74245,7 +76099,7 @@ async function connectOnce(url3, clock) {
74245
76099
  }
74246
76100
  async function probeEndpoint(url3, clock) {
74247
76101
  try {
74248
- await (0, import_promises73.lookup)(url3.hostname);
76102
+ await (0, import_promises74.lookup)(url3.hostname);
74249
76103
  } catch (error61) {
74250
76104
  const reason = classifyTransportFailure(error61);
74251
76105
  return reason === "other" ? "dns" : reason;
@@ -74368,8 +76222,12 @@ function connectLink(options) {
74368
76222
  const hello = await options.hello(connectEpoch);
74369
76223
  const ack = await socket.timeout(HELLO_TIMEOUT_MS).emitWithAck("hello", hello);
74370
76224
  await ready;
74371
- if (connectEpoch !== epoch) return;
76225
+ if (connectEpoch !== epoch || !socket.connected) return;
74372
76226
  options.onHelloAck(helloAckSchema.parse(ack), connectEpoch);
76227
+ retry.attempt = 0;
76228
+ retry.credentialFailures = 0;
76229
+ setState({ kind: "connected", epoch: connectEpoch });
76230
+ log.info("link.connected", { epoch: connectEpoch });
74373
76231
  };
74374
76232
  const setState = (next) => {
74375
76233
  current = next;
@@ -74439,12 +76297,16 @@ function connectLink(options) {
74439
76297
  };
74440
76298
  socket.on("connect", () => {
74441
76299
  epoch += 1;
74442
- retry.attempt = 0;
74443
- retry.credentialFailures = 0;
76300
+ const connectEpoch = epoch;
74444
76301
  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 }));
76302
+ setState({ kind: "connecting", lastFailure: null });
76303
+ greet(connectEpoch).catch((error61) => {
76304
+ if (connectEpoch !== epoch || current.kind === "stopped" || !socket.connected) return;
76305
+ log.warn("link.hello_failed", { epoch: connectEpoch, error: error61 });
76306
+ recordTransportFailure("other", "The backend did not acknowledge this runtime");
76307
+ socket.disconnect();
76308
+ redialAfter(redialDelayMs(retry.attempt++));
76309
+ });
74448
76310
  });
74449
76311
  socket.on("disconnect", (reason) => {
74450
76312
  log.info("link.disconnected", { reason });
@@ -74498,7 +76360,7 @@ function connectLink(options) {
74498
76360
  void ready.then(() => answerModelsScan(raw, options.scanModels, log)).then((result) => ack(result));
74499
76361
  });
74500
76362
  const pushCapabilities = async (capabilities) => {
74501
- if (!socket.connected) return false;
76363
+ if (current.kind !== "connected" || !socket.connected) return false;
74502
76364
  try {
74503
76365
  const ack = await socket.timeout(CAPABILITIES_ACK_TIMEOUT_MS).emitWithAck("capabilities", capabilities);
74504
76366
  const parsed = capabilitiesAckSchema.safeParse(ack);
@@ -74547,9 +76409,9 @@ function planReconcile(desired, held) {
74547
76409
  }
74548
76410
 
74549
76411
  // src/reconciler/desired-sync.ts
74550
- var import_node_crypto34 = require("crypto");
76412
+ var import_node_crypto35 = require("crypto");
74551
76413
  function fingerprintOf(desired) {
74552
- return (0, import_node_crypto34.createHash)("sha256").update(JSON.stringify(desired)).digest("hex");
76414
+ return (0, import_node_crypto35.createHash)("sha256").update(JSON.stringify(desired)).digest("hex");
74553
76415
  }
74554
76416
  var FAILED_READ_RETRY_MS = 3e4;
74555
76417
  function createDesiredSync(deps) {
@@ -74686,7 +76548,7 @@ function createReconciler(host, lifecycle, log, signal) {
74686
76548
  }
74687
76549
 
74688
76550
  // src/uploader/index.ts
74689
- var import_promises74 = require("fs/promises");
76551
+ var import_promises75 = require("fs/promises");
74690
76552
  init_runtime_v2();
74691
76553
  init_zod();
74692
76554
  var RETRY_DELAYS_MS = [250, 500, 1e3, 2e3, 5e3, 1e4, 3e4];
@@ -74717,12 +76579,15 @@ function startUploader({ api, runsDir, clock, log }) {
74717
76579
  if (stored.kind === "ok") return stored.value;
74718
76580
  const receipt = await api.readReceipt(target, controller.signal);
74719
76581
  switch (receipt.kind) {
74720
- case "read":
76582
+ case "read": {
74721
76583
  log.debug("upload.resumed", {
74722
76584
  runId,
74723
76585
  admittedOffset: receipt.receipt?.admittedOffset ?? 0
74724
76586
  });
74725
- return progressFromReceipt(receipt.receipt);
76587
+ const progress = progressFromReceipt(receipt.receipt);
76588
+ if (progress.sealed) await writeJsonFileAtomic(path4, progress);
76589
+ return progress;
76590
+ }
74726
76591
  case "rejected":
74727
76592
  await reject(runId, path4, progressFromReceipt(null), receipt);
74728
76593
  return null;
@@ -74827,7 +76692,7 @@ function startUploader({ api, runsDir, clock, log }) {
74827
76692
  active.set(runId, task);
74828
76693
  };
74829
76694
  const sweep2 = async () => {
74830
- for (const name of await (0, import_promises74.readdir)(runsDir).catch(() => [])) {
76695
+ for (const name of await (0, import_promises75.readdir)(runsDir).catch(() => [])) {
74831
76696
  const runId = runIdSchema.safeParse(name);
74832
76697
  if (runId.success) run2(runId.data);
74833
76698
  }
@@ -74837,18 +76702,18 @@ function startUploader({ api, runsDir, clock, log }) {
74837
76702
  const dir = runDirectory(runsDir, runId);
74838
76703
  const progress = await readJsonFile(dir.upload, uploadProgressSchema);
74839
76704
  if (progress.kind !== "ok" || !progress.value.sealed) return false;
74840
- const sealedAt = (await (0, import_promises74.stat)(dir.upload)).mtimeMs;
76705
+ const sealedAt = (await (0, import_promises75.stat)(dir.upload)).mtimeMs;
74841
76706
  if (clock.now() - sealedAt < options.sealedForMs) return false;
74842
76707
  return (await readLastRecord(dir.log))?.update.sessionUpdate === "_alan/run.ended";
74843
76708
  };
74844
76709
  const prune = async (options) => {
74845
76710
  let removed = 0;
74846
- for (const name of await (0, import_promises74.readdir)(runsDir).catch(() => [])) {
76711
+ for (const name of await (0, import_promises75.readdir)(runsDir).catch(() => [])) {
74847
76712
  const runId = runIdSchema.safeParse(name);
74848
76713
  if (!runId.success) continue;
74849
76714
  try {
74850
76715
  if (!await isPrunable(runId.data, options)) continue;
74851
- await (0, import_promises74.rm)(runDirectory(runsDir, runId.data).dir, { recursive: true, force: true });
76716
+ await (0, import_promises75.rm)(runDirectory(runsDir, runId.data).dir, { recursive: true, force: true });
74852
76717
  removed += 1;
74853
76718
  } catch (error61) {
74854
76719
  log.warn("upload.prune_failed", { runId: runId.data, error: error61 });
@@ -74972,6 +76837,28 @@ function unwrap(outcome2, what) {
74972
76837
  outcome2.code
74973
76838
  );
74974
76839
  }
76840
+ async function writeNativeTurnRun(runsDir, run2, log) {
76841
+ const runId = runIdSchema.parse(run2.runId);
76842
+ const conversationId = conversationIdSchema.parse(run2.conversationId);
76843
+ const { userMessage, assistantMessage } = run2;
76844
+ await writeCompleteRunLog(
76845
+ runsDir,
76846
+ { runId, conversationId, userMessage, assistantMessage },
76847
+ run2.records
76848
+ );
76849
+ if (userMessage?.turnOrdinal != null && assistantMessage?.turnOrdinal != null) {
76850
+ await indexConversationRun(
76851
+ runsDir,
76852
+ conversationId,
76853
+ userMessage.turnOrdinal,
76854
+ assistantMessage.turnOrdinal,
76855
+ runId
76856
+ ).catch(
76857
+ (error61) => log.warn("native_ingest.conversation_index_failed", { runId, error: error61 })
76858
+ );
76859
+ }
76860
+ return runId;
76861
+ }
74975
76862
  async function startMachineNativeIngest(deps) {
74976
76863
  const client = createNativeSessionsClient({
74977
76864
  apiUrl: deps.apiUrl,
@@ -74988,13 +76875,7 @@ async function startMachineNativeIngest(deps) {
74988
76875
  api,
74989
76876
  publisher: {
74990
76877
  publish: async (run2) => {
74991
- const runId = runIdSchema.parse(run2.runId);
74992
- await writeCompleteRunLog(
74993
- deps.runsDir,
74994
- { runId, conversationId: conversationIdSchema.parse(run2.conversationId) },
74995
- run2.records
74996
- );
74997
- deps.onPublished(runId);
76878
+ deps.onPublished(await writeNativeTurnRun(deps.runsDir, run2, deps.log));
74998
76879
  }
74999
76880
  },
75000
76881
  clock: deps.clock,
@@ -75030,12 +76911,12 @@ async function startMachineNativeIngest(deps) {
75030
76911
  }
75031
76912
 
75032
76913
  // src/cli/commands/run-updates.ts
75033
- var import_node_path76 = require("path");
76914
+ var import_node_path77 = require("path");
75034
76915
  init_runtime_v2();
75035
76916
  var UPDATE_CHECK_EVERY_MS = 6 * 60 * 60 * 1e3;
75036
76917
  var DEFERRED_RETRY_MS = 5 * 60 * 1e3;
75037
76918
  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);
76919
+ 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
76920
  }
75040
76921
  async function settleUpgradeOnStart({
75041
76922
  layout,
@@ -75142,7 +77023,7 @@ function startRuntimeUpdates(options) {
75142
77023
  layout,
75143
77024
  release: npmRelease,
75144
77025
  tarball: await options.downloader.download(npmRelease.dist.tarball, signal),
75145
- tmpDir: (0, import_node_path76.join)(layout.root, ".downloads")
77026
+ tmpDir: (0, import_node_path77.join)(layout.root, ".downloads")
75146
77027
  });
75147
77028
  await lifecycle.exclusive("upgrade", async () => {
75148
77029
  await recordPendingUpgrade(layout, currentVersion2, version2, clock.now());
@@ -75367,7 +77248,7 @@ async function startMachinePlane(deps) {
75367
77248
  [ALAN_MANAGED_SESSION_ENV]: "1"
75368
77249
  },
75369
77250
  cwd: paths.stateDir,
75370
- outputPath: (0, import_node_path77.join)(paths.logs, "holders.log")
77251
+ outputPath: (0, import_node_path78.join)(paths.logs, "holders.log")
75371
77252
  },
75372
77253
  deps.holderIsolation
75373
77254
  );
@@ -75598,7 +77479,7 @@ async function startMachinePlane(deps) {
75598
77479
  git: createGitRunner({ env: cliEnvironment }),
75599
77480
  clock,
75600
77481
  log,
75601
- dir: (0, import_node_path77.join)(paths.stateDir, "checkout-freshness")
77482
+ dir: (0, import_node_path78.join)(paths.stateDir, "checkout-freshness")
75602
77483
  },
75603
77484
  stopped.signal
75604
77485
  );
@@ -75892,23 +77773,28 @@ function lockWaitMs(argv) {
75892
77773
  }
75893
77774
  async function openManagedProviders(config2, paths) {
75894
77775
  const providerEnv = readCliEnvironment();
75895
- const npmPath = config2.providerToolchain?.node ?? await resolveCommandOnPath("npm", providerEnv, process.platform);
75896
- const npmOptions = npmPath === null ? null : {
77776
+ const bundledNpm = (0, import_node_path79.join)((0, import_node_path79.dirname)(process.execPath), "npm", "bin", "npm-cli.js");
77777
+ const providerToolchain = config2.providerToolchain ?? (process.platform === "win32" && (0, import_node_fs23.existsSync)(bundledNpm) ? { node: process.execPath, npmCli: bundledNpm } : null);
77778
+ const npmPath = providerToolchain?.node ?? await resolveCommandOnPath("npm", providerEnv, process.platform);
77779
+ const npmOptions = npmPath === null || process.platform === "win32" && providerToolchain === null ? null : {
75897
77780
  command: npmPath,
75898
- ...config2.providerToolchain === null ? {} : { argsBeforeNpm: [config2.providerToolchain.npmCli] },
77781
+ ...providerToolchain === null ? {} : { argsBeforeNpm: [providerToolchain.npmCli] },
75899
77782
  env: providerEnv
75900
77783
  };
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 ?? ""}` };
77784
+ const providerNodeDir = providerToolchain?.node === void 0 ? void 0 : (0, import_node_path79.dirname)(providerToolchain.node);
77785
+ const probeEnv = providerNodeDir === void 0 ? providerEnv : {
77786
+ ...providerEnv,
77787
+ PATH: `${providerNodeDir}${pathDelimiter(process.platform)}${envValue(providerEnv, "PATH")}`
77788
+ };
77789
+ const canonicalProbeEnv = process.platform === "win32" ? canonicalWindowsEnvironment(probeEnv) : probeEnv;
77790
+ const unavailable = async () => {
77791
+ throw new Error("Provider installer is unavailable on this computer");
77792
+ };
75903
77793
  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)
77794
+ root: (0, import_node_path79.join)(paths.stateDir, "provider-clis"),
77795
+ resolveVersion: npmOptions === null ? unavailable : createNpmVersionResolver(npmOptions),
77796
+ installPackage: npmOptions === null ? unavailable : createNpmPackageInstaller(npmOptions),
77797
+ probe: (executable, backendKind) => probeManagedProvider(executable, backendKind, canonicalProbeEnv)
75912
77798
  });
75913
77799
  await managed.load();
75914
77800
  return { managed, providerNodeDir };
@@ -75937,7 +77823,7 @@ async function runService(argv, stop, restart = new AbortController().signal) {
75937
77823
  waitMs: lockWaitMs(argv),
75938
77824
  signal: stop
75939
77825
  }));
75940
- const log = __using(_stack, openFileLog((0, import_node_path78.join)(paths.logs, "runtime.jsonl"), config2.logLevel, clock));
77826
+ const log = __using(_stack, openFileLog((0, import_node_path79.join)(paths.logs, "runtime.jsonl"), config2.logLevel, clock));
75941
77827
  const lifecycle = createLifecycleQueue({ clock, log });
75942
77828
  const install2 = installLayout(config2.installDir, config2.profile);
75943
77829
  const bundlePath = process.argv[1] ?? "";
@@ -75971,7 +77857,7 @@ async function runService(argv, stop, restart = new AbortController().signal) {
75971
77857
  openCliEnvironment({
75972
77858
  env: readCliEnvironment(),
75973
77859
  platform: process.platform,
75974
- lastKnownGoodFile: (0, import_node_path78.join)(paths.stateDir, "login-path.json"),
77860
+ lastKnownGoodFile: (0, import_node_path79.join)(paths.stateDir, "login-path.json"),
75975
77861
  clock,
75976
77862
  decorate: (env) => withPackagedAlanCodeEngine(env, bundlePath, process.platform)
75977
77863
  })
@@ -76148,17 +78034,17 @@ async function runServiceCommand(argv, ctx = cliContext()) {
76148
78034
  }
76149
78035
 
76150
78036
  // src/cli/commands/upgrade.ts
76151
- var import_promises75 = require("fs/promises");
76152
- var import_node_path79 = require("path");
78037
+ var import_promises76 = require("fs/promises");
78038
+ var import_node_path80 = require("path");
76153
78039
  function isNotNewer(version2, installed) {
76154
78040
  return installed !== null && isReleaseVersion(version2) && isReleaseVersion(installed) && compareVersions(version2, installed) <= 0;
76155
78041
  }
76156
78042
  async function installFromSource(source) {
76157
78043
  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;
78044
+ const isTarball = (await (0, import_promises76.stat)(from)).isFile();
78045
+ const downloads = (0, import_node_path80.join)(layout.root, ".downloads");
78046
+ if (isTarball) await (0, import_promises76.mkdir)(downloads, { recursive: true, mode: 448 });
78047
+ const scratch = isTarball ? await (0, import_promises76.mkdtemp)((0, import_node_path80.join)(downloads, "upgrade-")) : null;
76162
78048
  try {
76163
78049
  const sourceDir = scratch === null ? from : await extractPackageTarball(from, scratch);
76164
78050
  const version2 = await readPackageVersion(sourceDir);
@@ -76166,7 +78052,7 @@ async function installFromSource(source) {
76166
78052
  if (ifNewer && isNotNewer(version2, installed)) return { kind: "skipped", version: version2, installed };
76167
78053
  return { kind: "installed", ...await installVersion(layout, sourceDir) };
76168
78054
  } finally {
76169
- if (scratch !== null) await (0, import_promises75.rm)(scratch, { recursive: true, force: true });
78055
+ if (scratch !== null) await (0, import_promises76.rm)(scratch, { recursive: true, force: true });
76170
78056
  }
76171
78057
  }
76172
78058
  async function runUpgrade(argv) {
@@ -76178,7 +78064,7 @@ async function runUpgrade(argv) {
76178
78064
  const layout = installLayout(config2.installDir, config2.profile);
76179
78065
  const outcome2 = await installFromSource({
76180
78066
  layout,
76181
- from: (0, import_node_path79.resolve)(from),
78067
+ from: (0, import_node_path80.resolve)(from),
76182
78068
  ifNewer: hasFlag(argv, "--if-newer")
76183
78069
  });
76184
78070
  if (outcome2.kind === "skipped") {