@alan-ai-hq/agent-manager-darwin-arm64 0.1.136 → 0.1.138

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/alan-agent.cjs +2081 -351
  2. package/alan-holder.cjs +336 -94
  3. package/package.json +1 -1
package/alan-agent.cjs CHANGED
@@ -20104,7 +20104,12 @@ var init_run_context = __esm({
20104
20104
  prMeta: pullRequestMetaSchema.optional(),
20105
20105
  currentUser: agentUserIdentitySchema.optional(),
20106
20106
  sessionVisibility: external_exports.enum(["private", "team"]).nullable().optional(),
20107
- workflowTools: external_exports.array(workflowToolRefSchema).optional()
20107
+ workflowTools: external_exports.array(workflowToolRefSchema).optional(),
20108
+ availableSkills: external_exports.array(external_exports.object({
20109
+ name: external_exports.string().min(1),
20110
+ description: external_exports.string(),
20111
+ packageDirectory: external_exports.string().min(1)
20112
+ })).max(2e3).optional()
20108
20113
  });
20109
20114
  }
20110
20115
  });
@@ -20358,6 +20363,7 @@ var init_desired_state = __esm({
20358
20363
  /** Omitted by older servers; only an explicit entitlement enables context-search guidance. */
20359
20364
  contextGraphEnabled: external_exports.boolean().optional(),
20360
20365
  cloudEnvironmentId: external_exports.guid().optional(),
20366
+ sandboxId: external_exports.string().min(1).optional(),
20361
20367
  localRepoUrls: external_exports.array(external_exports.string().min(1)).optional()
20362
20368
  // Never here: the provider API key. The holder fetches it per run (RUN_PROVIDER_CREDENTIAL_PATH).
20363
20369
  });
@@ -21372,6 +21378,7 @@ var init_workflow_tools_filter = __esm({
21372
21378
  WORKFLOW_ALWAYS_ALLOWED_BUILTIN_TOOLS = [
21373
21379
  "search_context",
21374
21380
  "create_test_report",
21381
+ "publish_capture",
21375
21382
  "create_plan",
21376
21383
  "create_document_artifact",
21377
21384
  "list_artifacts",
@@ -21755,6 +21762,9 @@ For any UI or design work, read and follow the \`uiux\` skill in \`.agents/skill
21755
21762
  });
21756
21763
 
21757
21764
  // ../shared/dist/agent/attachment-mention.js
21765
+ function attachmentMentionPattern() {
21766
+ return /@\[attachment:([^:\]\s]+):(.*?)\](?=[.,;:!?)]*(?:\s|$))/gi;
21767
+ }
21758
21768
  var init_attachment_mention = __esm({
21759
21769
  "../shared/dist/agent/attachment-mention.js"() {
21760
21770
  "use strict";
@@ -21853,12 +21863,14 @@ function isExternalMcpServerName(name) {
21853
21863
  function isMcpConfigKey(name) {
21854
21864
  return MCP_CONFIG_KEY.test(name);
21855
21865
  }
21856
- var ALAN_MCP_AUTHORIZATION_ENV, ALAN_RUN_ID_ENV, MCP_CONFIG_KEY;
21866
+ var ALAN_MCP_AUTHORIZATION_ENV, ALAN_RUN_ID_ENV, ALAN_MCP_URL_ENV, ALAN_MCP_CREDENTIAL_FILE_ENV, MCP_CONFIG_KEY;
21857
21867
  var init_mcp_config = __esm({
21858
21868
  "../shared/dist/agent/mcp-config.js"() {
21859
21869
  "use strict";
21860
21870
  ALAN_MCP_AUTHORIZATION_ENV = "ALAN_MCP_AUTHORIZATION";
21861
21871
  ALAN_RUN_ID_ENV = "ALAN_RUN_ID";
21872
+ ALAN_MCP_URL_ENV = "ALAN_MCP_URL";
21873
+ ALAN_MCP_CREDENTIAL_FILE_ENV = "ALAN_MCP_CREDENTIAL_FILE";
21862
21874
  MCP_CONFIG_KEY = /^[A-Za-z0-9_-]+$/;
21863
21875
  }
21864
21876
  });
@@ -22229,6 +22241,22 @@ var init_agent = __esm({
22229
22241
  }
22230
22242
  });
22231
22243
 
22244
+ // ../shared/dist/agent/transcript/preview.js
22245
+ function toPreviewText(value2, limit) {
22246
+ const text2 = value2.replace(/```[\s\S]*?```/g, (block) => block.replace(/```\w*\n?|```/g, " ")).replace(/!\[[^\]]*\]\([^)]*\)/g, "").replace(/\[([^\]]+)\]\([^)]*\)/g, "$1").replace(/`([^`]+)`/g, "$1").replace(/^\s{0,3}#{1,6}\s+/gm, "").replace(/^\s{0,3}>\s?/gm, "").replace(/^\s{0,3}(?:[-*+]|\d+\.)\s+/gm, "").replace(/^\s{0,3}(?:[-*_]\s*){3,}$/gm, "").replace(/\*\*([^*]+)\*\*/g, "$1").replace(/__([^_]+)__/g, "$1").replace(/\*([^*\n]+)\*/g, "$1").replace(/~~([^~]+)~~/g, "$1").replace(/\s+/g, " ").trim();
22247
+ if (text2.length <= limit)
22248
+ return text2;
22249
+ const clipped = text2.slice(0, limit - 1);
22250
+ const lastSpace = clipped.lastIndexOf(" ");
22251
+ const body = lastSpace > limit * 0.6 ? clipped.slice(0, lastSpace) : clipped;
22252
+ return `${body.trimEnd()}\u2026`;
22253
+ }
22254
+ var init_preview = __esm({
22255
+ "../shared/dist/agent/transcript/preview.js"() {
22256
+ "use strict";
22257
+ }
22258
+ });
22259
+
22232
22260
  // ../shared/dist/agent/transcript/index.js
22233
22261
  var init_transcript = __esm({
22234
22262
  "../shared/dist/agent/transcript/index.js"() {
@@ -22335,23 +22363,31 @@ var init_chunk_YXWJW7I5 = __esm({
22335
22363
  }
22336
22364
  });
22337
22365
 
22338
- // ../agent-core/dist/chunk-J4T6L5LX.js
22366
+ // ../agent-core/dist/chunk-M6YHY2EZ.js
22339
22367
  function windowsEnvValue(env, name) {
22340
22368
  const wanted = name.toLowerCase();
22341
- for (const [key, value2] of Object.entries(env)) {
22369
+ for (const [key, value2] of Object.entries(env).reverse()) {
22342
22370
  if (key.toLowerCase() === wanted) return value2;
22343
22371
  }
22344
22372
  return void 0;
22345
22373
  }
22374
+ function canonicalWindowsEnvironment(env) {
22375
+ const unique2 = /* @__PURE__ */ new Map();
22376
+ for (const [name, value2] of Object.entries(env)) {
22377
+ unique2.set(name.toLowerCase(), [name.toLowerCase() === "path" ? "PATH" : name, value2]);
22378
+ }
22379
+ return Object.fromEntries(unique2.values());
22380
+ }
22346
22381
  function hasExtension(name, extensions) {
22347
22382
  const ext = import_path.win32.extname(name).toLowerCase();
22348
22383
  return ext.length > 0 && extensions.includes(ext);
22349
22384
  }
22350
22385
  function candidates(base, extensions) {
22351
- return hasExtension(base, extensions) ? [base] : extensions.map((ext) => `${base}${ext}`);
22386
+ const extension = import_path.win32.extname(base).toLowerCase();
22387
+ return extension === ".exe" || extension === ".com" || hasExtension(base, extensions) ? [base] : extensions.map((ext) => `${base}${ext}`);
22352
22388
  }
22353
22389
  function resolveWindowsCommand(command, env, files) {
22354
- const extensions = (windowsEnvValue(env, "PATHEXT") ?? DEFAULT_PATHEXT).split(";").map((ext) => ext.trim().toLowerCase()).filter((ext) => ext.startsWith("."));
22390
+ const extensions = (windowsEnvValue(env, "PATHEXT") ?? DEFAULT_PATHEXT).split(";").map((ext) => ext.trim().toLowerCase()).filter((ext) => LAUNCHABLE_EXTENSIONS.has(ext));
22355
22391
  if (/[\\/]/.test(command)) {
22356
22392
  return candidates(command, extensions).find((path4) => files.isFile(path4));
22357
22393
  }
@@ -22364,6 +22400,18 @@ function resolveWindowsCommand(command, env, files) {
22364
22400
  }
22365
22401
  return void 0;
22366
22402
  }
22403
+ function unwrapNativeShim(shim, args, files) {
22404
+ const lines2 = files.readShim(shim)?.split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
22405
+ if (lines2?.length !== NATIVE_SHIM_LINES.length + 1) return void 0;
22406
+ if (!NATIVE_SHIM_LINES.every((pattern, index) => pattern.test(lines2[index] ?? ""))) {
22407
+ return void 0;
22408
+ }
22409
+ const target = NATIVE_SHIM_ENTRY.exec(lines2.at(-1) ?? "")?.[1];
22410
+ if (target === void 0) return void 0;
22411
+ const directory = import_path.win32.dirname(shim);
22412
+ const file2 = import_path.win32.resolve(directory, target.replace(/^%dp0%\\/i, ""));
22413
+ return files.isFile(file2) ? { kind: "native", file: file2, args } : void 0;
22414
+ }
22367
22415
  function isSimpleNodeShim(text2) {
22368
22416
  return text2.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0).every((line) => /^@?echo off$/i.test(line) || NODE_SHIM_ENTRY.test(line));
22369
22417
  }
@@ -22389,7 +22437,7 @@ function planWindowsLaunch(command, args, env, files) {
22389
22437
  const file2 = resolveWindowsCommand(command, env, files);
22390
22438
  if (file2 === void 0) return void 0;
22391
22439
  if (!/\.(cmd|bat)$/i.test(file2)) return { kind: "native", file: file2, args };
22392
- return unwrapNodeShim(file2, args, env, files) ?? { kind: "batch", file: file2, args };
22440
+ return unwrapNativeShim(file2, args, files) ?? unwrapNodeShim(file2, args, env, files) ?? { kind: "batch", file: file2, args };
22393
22441
  }
22394
22442
  function quoteWindowsArgument(value2) {
22395
22443
  if (value2.length === 0) return '""';
@@ -22891,11 +22939,12 @@ function onCliSpawned(listener) {
22891
22939
  }
22892
22940
  function spawnCli(options) {
22893
22941
  const platform3 = options.platform ?? process.platform;
22894
- const plan2 = planSpawn({ ...options, platform: platform3 });
22895
- if (plan2.commandLine !== null) return spawnInWindowsJob(plan2, options);
22942
+ const env = platform3 === "win32" ? canonicalWindowsEnvironment(options.env) : options.env;
22943
+ const plan2 = planSpawn({ ...options, env, platform: platform3 });
22944
+ if (plan2.commandLine !== null) return spawnInWindowsJob(plan2, { ...options, env });
22896
22945
  const child = (0, import_child_process5.spawn)(plan2.file, [...plan2.args], {
22897
22946
  cwd: options.cwd,
22898
- env: { ...options.env },
22947
+ env: { ...env },
22899
22948
  stdio: ["pipe", "pipe", "pipe"],
22900
22949
  shell: false,
22901
22950
  detached: true
@@ -22922,9 +22971,9 @@ function waitForSpawn(child, command) {
22922
22971
  child.once("error", onError);
22923
22972
  });
22924
22973
  }
22925
- 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;
22926
- var init_chunk_J4T6L5LX = __esm({
22927
- "../agent-core/dist/chunk-J4T6L5LX.js"() {
22974
+ var import_child_process, import_fs, import_path, import_child_process2, import_promises9, import_child_process3, import_child_process4, import_child_process5, import_child_process6, import_crypto, import_fs2, import_promises10, import_os, import_path2, SHIM_MAX_BYTES, CMD_MAX_COMMAND_LINE, MAX_COMMAND_LINE, DEFAULT_PATHEXT, LAUNCHABLE_EXTENSIONS, nodeWindowsFiles, NODE_SHIM_ENTRY, NATIVE_SHIM_LINES, NATIVE_SHIM_ENTRY, CMD_META, NEVER_STARTED, HIDDEN_FLAG_PROBE_VALUE, NEWLINE, CARRIAGE_RETURN, EMPTY, MAX_LINE_BYTES, LineSplitter, PS_LINE, POLL_MS, DEFAULT_GRACE_MS, DEFAULT_KILL_WAIT_MS, DEFAULT_TASKKILL_TIMEOUT_MS, statuses, START_TIMEOUT_MS, spawnListeners;
22975
+ var init_chunk_M6YHY2EZ = __esm({
22976
+ "../agent-core/dist/chunk-M6YHY2EZ.js"() {
22928
22977
  "use strict";
22929
22978
  init_chunk_YXWJW7I5();
22930
22979
  import_child_process = require("child_process");
@@ -22945,6 +22994,7 @@ var init_chunk_J4T6L5LX = __esm({
22945
22994
  CMD_MAX_COMMAND_LINE = 8191;
22946
22995
  MAX_COMMAND_LINE = 32766;
22947
22996
  DEFAULT_PATHEXT = ".COM;.EXE;.BAT;.CMD";
22997
+ LAUNCHABLE_EXTENSIONS = /* @__PURE__ */ new Set([".com", ".exe", ".bat", ".cmd"]);
22948
22998
  nodeWindowsFiles = {
22949
22999
  isFile: (path4) => {
22950
23000
  try {
@@ -22963,6 +23013,17 @@ var init_chunk_J4T6L5LX = __esm({
22963
23013
  }
22964
23014
  };
22965
23015
  NODE_SHIM_ENTRY = /"(%_prog%|[^"\r\n]*node(?:\.exe)?)"\s+"([^"\r\n]+\.(?:c?js|mjs))"\s+%\*/i;
23016
+ NATIVE_SHIM_LINES = [
23017
+ /^@echo off$/i,
23018
+ /^goto start$/i,
23019
+ /^:find_dp0$/i,
23020
+ /^set dp0=%~dp0$/i,
23021
+ /^exit \/b$/i,
23022
+ /^:start$/i,
23023
+ /^setlocal$/i,
23024
+ /^call :find_dp0$/i
23025
+ ];
23026
+ NATIVE_SHIM_ENTRY = /^"(%dp0%\\(?:\.\.\\)?(?:node_modules\\)?[\w@.-]+(?:\\[\w@.-]+)*\.exe)"\s+%\*$/i;
22966
23027
  CMD_META = /([()\][%!^"`<>&|;, *?])/g;
22967
23028
  NEVER_STARTED = { stdout: "", stderr: "", exitCode: void 0 };
22968
23029
  HIDDEN_FLAG_PROBE_VALUE = "__alan_probe__";
@@ -23720,29 +23781,209 @@ var init_constants = __esm({
23720
23781
  });
23721
23782
 
23722
23783
  // ../shared/dist/agent/acp/transcript-http.js
23784
+ var TRANSCRIPT_TOOL_RESPONSE_ID_META, TRANSCRIPT_TURN_ID_META;
23723
23785
  var init_transcript_http = __esm({
23724
23786
  "../shared/dist/agent/acp/transcript-http.js"() {
23725
23787
  "use strict";
23788
+ TRANSCRIPT_TOOL_RESPONSE_ID_META = "alan.dev/transcriptToolResponseId";
23789
+ TRANSCRIPT_TURN_ID_META = "alan.dev/transcriptTurnId";
23726
23790
  }
23727
23791
  });
23728
23792
 
23729
23793
  // ../shared/dist/agent/acp/ask.js
23794
+ function asRecord2(value2) {
23795
+ return value2 && typeof value2 === "object" && !Array.isArray(value2) ? value2 : void 0;
23796
+ }
23797
+ function readOptions(value2) {
23798
+ if (!Array.isArray(value2))
23799
+ return [];
23800
+ const options = [];
23801
+ for (const raw of value2) {
23802
+ const option2 = asRecord2(raw);
23803
+ const label = typeof option2?.label === "string" ? option2.label : void 0;
23804
+ if (!label)
23805
+ continue;
23806
+ options.push({
23807
+ label,
23808
+ description: typeof option2?.description === "string" ? option2.description : void 0
23809
+ });
23810
+ }
23811
+ return options;
23812
+ }
23813
+ function readQuestions(input2) {
23814
+ const record2 = asRecord2(input2);
23815
+ const raw = record2?.questions;
23816
+ if (!Array.isArray(raw))
23817
+ return [];
23818
+ const questions = [];
23819
+ for (const item of raw) {
23820
+ const entry = asRecord2(item);
23821
+ const question = typeof entry?.question === "string" ? entry.question : void 0;
23822
+ if (!question)
23823
+ continue;
23824
+ questions.push({
23825
+ question,
23826
+ header: typeof entry?.header === "string" ? entry.header : void 0,
23827
+ options: readOptions(entry?.options),
23828
+ multiSelect: entry?.multiSelect === true
23829
+ });
23830
+ }
23831
+ return questions;
23832
+ }
23833
+ function isAskToolCall(entry) {
23834
+ const name = entry.title || entry.toolKind;
23835
+ return isAskUserQuestionTool(name, entry.rawInput);
23836
+ }
23837
+ function findPendingAsk(entries, answeredIds = /* @__PURE__ */ new Set()) {
23838
+ for (let index = entries.length - 1; index >= 0; index -= 1) {
23839
+ const entry = entries[index];
23840
+ if (!entry || entry.kind !== "tool_call")
23841
+ continue;
23842
+ if (entry.status === "completed" || entry.status === "failed" || entry.status === "cancelled") {
23843
+ continue;
23844
+ }
23845
+ if (answeredIds.has(entry.id))
23846
+ continue;
23847
+ if (!isAskToolCall(entry))
23848
+ continue;
23849
+ const questions = readQuestions(entry.rawInput);
23850
+ if (questions.length === 0)
23851
+ continue;
23852
+ return { toolCallId: entry.id, questions, rawInput: asRecord2(entry.rawInput) ?? {} };
23853
+ }
23854
+ return null;
23855
+ }
23730
23856
  var init_ask = __esm({
23731
23857
  "../shared/dist/agent/acp/ask.js"() {
23732
23858
  "use strict";
23859
+ init_agent();
23733
23860
  }
23734
23861
  });
23735
23862
 
23736
23863
  // ../shared/dist/agent/acp/background-task.js
23737
- var BACKGROUND_TASK_META_KEY;
23864
+ function oneOf(values, value2) {
23865
+ return typeof value2 === "string" && values.some((candidate) => candidate === value2);
23866
+ }
23867
+ function isRecord6(value2) {
23868
+ return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
23869
+ }
23870
+ function optionalString(value2) {
23871
+ return typeof value2 === "string" && value2.length > 0 ? value2 : void 0;
23872
+ }
23873
+ function readBackgroundTaskMeta(meta3) {
23874
+ if (!isRecord6(meta3))
23875
+ return null;
23876
+ const raw = meta3[BACKGROUND_TASK_META_KEY];
23877
+ if (!isRecord6(raw))
23878
+ return null;
23879
+ const taskId = optionalString(raw.taskId);
23880
+ if (!taskId)
23881
+ return null;
23882
+ const kind = oneOf(KINDS, raw.kind) ? raw.kind : void 0;
23883
+ const stop = oneOf(STRATEGIES, raw.stop) ? raw.stop : void 0;
23884
+ const status = oneOf(STATUSES, raw.status) ? raw.status : void 0;
23885
+ const label = optionalString(raw.label);
23886
+ const subagentType = optionalString(raw.subagentType);
23887
+ const taskType = optionalString(raw.taskType);
23888
+ return {
23889
+ taskId,
23890
+ backgrounded: raw.backgrounded === true,
23891
+ ...kind ? { kind } : {},
23892
+ ...label ? { label } : {},
23893
+ ...typeof raw.startedAt === "number" ? { startedAt: raw.startedAt } : {},
23894
+ ...stop ? { stop } : {},
23895
+ ...status ? { status } : {},
23896
+ ...raw.stoppedByUser === true ? { stoppedByUser: true } : {},
23897
+ ...subagentType ? { subagentType } : {},
23898
+ ...taskType ? { taskType } : {},
23899
+ ...typeof raw.spawnDepth === "number" ? { spawnDepth: raw.spawnDepth } : {},
23900
+ ...raw.ownedBySubagent === true ? { ownedBySubagent: true } : {}
23901
+ };
23902
+ }
23903
+ var BACKGROUND_TASK_META_KEY, KINDS, STRATEGIES, STATUSES;
23738
23904
  var init_background_task = __esm({
23739
23905
  "../shared/dist/agent/acp/background-task.js"() {
23740
23906
  "use strict";
23741
23907
  BACKGROUND_TASK_META_KEY = "alan.dev/backgroundTask";
23908
+ KINDS = ["shell", "agent"];
23909
+ STRATEGIES = [
23910
+ "native",
23911
+ "pid",
23912
+ "none"
23913
+ ];
23914
+ STATUSES = [
23915
+ "running",
23916
+ "stopping",
23917
+ "stopped",
23918
+ "completed",
23919
+ "failed"
23920
+ ];
23742
23921
  }
23743
23922
  });
23744
23923
 
23745
23924
  // ../shared/dist/agent/acp/presentation/terminal-events.js
23925
+ function isRecord7(value2) {
23926
+ return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
23927
+ }
23928
+ function foldPreview(events) {
23929
+ const output2 = [];
23930
+ const slots = /* @__PURE__ */ new Map();
23931
+ for (const event of events) {
23932
+ const update = event.update;
23933
+ const kind = canonicalKind(update.sessionUpdate);
23934
+ const identity = update.messageId ?? update.toolCallId ?? update.terminalId ?? update.planId;
23935
+ const singleton = [
23936
+ "state_update",
23937
+ "usage_update",
23938
+ "session_info_update",
23939
+ "available_commands_update",
23940
+ "config_option_update",
23941
+ "_alan/thinking_tokens"
23942
+ ].includes(kind);
23943
+ const key = identity !== void 0 || singleton ? JSON.stringify([event.sessionId ?? "", kind, identity ?? "session"]) : void 0;
23944
+ const slot = key ? slots.get(key) : void 0;
23945
+ const previous = slot === void 0 ? void 0 : output2[slot];
23946
+ const merged = {
23947
+ ...previous?.update,
23948
+ ...update,
23949
+ sessionUpdate: kind
23950
+ };
23951
+ if (update.sessionUpdate === "terminal_output_chunk") {
23952
+ const before = previous && isRecord7(previous.update.output) ? previous.update.output.data : "";
23953
+ merged.output = { data: String(before ?? "") + String(update.data ?? "") };
23954
+ } else if (update.sessionUpdate.endsWith("_chunk")) {
23955
+ const before = previous && Array.isArray(previous.update.content) ? previous.update.content : [];
23956
+ merged.content = [
23957
+ ...before,
23958
+ ...Array.isArray(update.content) ? update.content : update.content ? [update.content] : []
23959
+ ];
23960
+ }
23961
+ if (isRecord7(update._meta))
23962
+ merged._meta = {
23963
+ ...isRecord7(previous?.update._meta) ? previous.update._meta : {},
23964
+ ...update._meta
23965
+ };
23966
+ if (kind === "state_update")
23967
+ merged.stopReason = update.state === "idle" ? update.stopReason : void 0;
23968
+ if (kind === "tool_call_update" && ["completed", "failed", "cancelled"].includes(String(previous?.update.status)))
23969
+ merged.status = previous?.update.status;
23970
+ const next = { ...event, line: previous?.line ?? event.line, update: merged };
23971
+ if (slot === void 0) {
23972
+ if (key)
23973
+ slots.set(key, output2.length);
23974
+ output2.push(next);
23975
+ } else
23976
+ output2[slot] = next;
23977
+ }
23978
+ return output2;
23979
+ }
23980
+ function canonicalKind(kind) {
23981
+ if (kind === "tool_call_content_chunk")
23982
+ return "tool_call_update";
23983
+ if (kind === "terminal_output_chunk")
23984
+ return "terminal_update";
23985
+ return kind.replace(/_chunk$/, "");
23986
+ }
23746
23987
  var init_terminal_events = __esm({
23747
23988
  "../shared/dist/agent/acp/presentation/terminal-events.js"() {
23748
23989
  "use strict";
@@ -23750,23 +23991,357 @@ var init_terminal_events = __esm({
23750
23991
  });
23751
23992
 
23752
23993
  // ../shared/dist/agent/acp/presentation/file-edits.js
23994
+ function diffRows(patch) {
23995
+ let oldLine = 0;
23996
+ let newLine = 0;
23997
+ let oldRemaining = 0;
23998
+ let newRemaining = 0;
23999
+ const lines2 = patch.split("\n");
24000
+ if (lines2.at(-1) === "")
24001
+ lines2.pop();
24002
+ return lines2.map((line) => {
24003
+ const hunk = /^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/.exec(line);
24004
+ if (hunk) {
24005
+ oldLine = Number(hunk[1]);
24006
+ newLine = Number(hunk[3]);
24007
+ oldRemaining = Number(hunk[2] ?? 1);
24008
+ newRemaining = Number(hunk[4] ?? 1);
24009
+ return { kind: "hunk", text: line };
24010
+ }
24011
+ if (newRemaining > 0 && line.startsWith("+")) {
24012
+ newRemaining--;
24013
+ return { kind: "add", text: line.slice(1), newLine: newLine++ };
24014
+ }
24015
+ if (oldRemaining > 0 && line.startsWith("-")) {
24016
+ oldRemaining--;
24017
+ return { kind: "remove", text: line.slice(1), oldLine: oldLine++ };
24018
+ }
24019
+ if (oldRemaining > 0 && newRemaining > 0 && line.startsWith(" ")) {
24020
+ oldRemaining--;
24021
+ newRemaining--;
24022
+ return { kind: "context", text: line.slice(1), oldLine: oldLine++, newLine: newLine++ };
24023
+ }
24024
+ return { kind: "meta", text: line };
24025
+ });
24026
+ }
24027
+ function patchForPath(text2, path4, count) {
24028
+ if (count === 1)
24029
+ return text2;
24030
+ const normalized2 = path4.replace(/^\/+/, "");
24031
+ return text2.split(/(?=^diff --git )/m).find((part) => {
24032
+ const names = [...part.matchAll(/^(?:---|\+\+\+) (?:[ab]\/)?([^\t\n]+)/gm)];
24033
+ return names.some((match) => match[1].replace(/^\/+/, "") === normalized2);
24034
+ });
24035
+ }
24036
+ function readDiff(value2, id) {
24037
+ if (!isRecord7(value2) || !Array.isArray(value2.changes))
24038
+ return [];
24039
+ const patch = isRecord7(value2.patch) && typeof value2.patch.text === "string" ? value2.patch : void 0;
24040
+ const changes = value2.changes;
24041
+ return changes.flatMap((change, index) => {
24042
+ if (!isRecord7(change) || typeof change.path !== "string" || typeof change.operation !== "string")
24043
+ return [];
24044
+ const text2 = patch ? patchForPath(String(patch.text), change.path, changes.length) : void 0;
24045
+ const rows = text2 && patch?.format !== "text" ? diffRows(text2) : [];
24046
+ const counted = rows.some((row) => row.kind === "hunk");
24047
+ return [
24048
+ {
24049
+ id: `${id}:${index}`,
24050
+ path: change.path,
24051
+ operation: change.operation,
24052
+ ...typeof change.oldPath === "string" ? { oldPath: change.oldPath } : {},
24053
+ patch: text2,
24054
+ rows,
24055
+ ...counted ? {
24056
+ additions: rows.filter((row) => row.kind === "add").length,
24057
+ deletions: rows.filter((row) => row.kind === "remove").length
24058
+ } : {}
24059
+ }
24060
+ ];
24061
+ });
24062
+ }
24063
+ function toolEdits(node2) {
24064
+ const content = node2.event.update.content;
24065
+ if (!Array.isArray(content))
24066
+ return [];
24067
+ return content.flatMap((block, index) => isRecord7(block) && block.type === "diff" ? readDiff(block.diff, `${node2.key}:${index}`) : []);
24068
+ }
24069
+ function collectEditedFiles(nodes) {
24070
+ const files = /* @__PURE__ */ new Map();
24071
+ const seen = /* @__PURE__ */ new Set();
24072
+ function visit2(node2) {
24073
+ if (seen.has(node2.key))
24074
+ return;
24075
+ seen.add(node2.key);
24076
+ if (node2.event.update.sessionUpdate === "tool_call_update" && node2.event.update.status === "completed") {
24077
+ for (const edit of toolEdits(node2)) {
24078
+ const previous = files.get(edit.path);
24079
+ const edits = [...previous?.edits ?? [], edit];
24080
+ const counted = edits.every((item) => item.additions !== void 0 && item.deletions !== void 0);
24081
+ files.set(edit.path, {
24082
+ path: edit.path,
24083
+ edits,
24084
+ ...counted ? {
24085
+ additions: edits.reduce((sum, item) => sum + (item.additions ?? 0), 0),
24086
+ deletions: edits.reduce((sum, item) => sum + (item.deletions ?? 0), 0)
24087
+ } : {}
24088
+ });
24089
+ }
24090
+ }
24091
+ node2.children.forEach(visit2);
24092
+ }
24093
+ nodes.forEach(visit2);
24094
+ return [...files.values()];
24095
+ }
23753
24096
  var init_file_edits = __esm({
23754
24097
  "../shared/dist/agent/acp/presentation/file-edits.js"() {
23755
24098
  "use strict";
24099
+ init_terminal_events();
23756
24100
  }
23757
24101
  });
23758
24102
 
23759
24103
  // ../shared/dist/agent/acp/presentation/notice-visibility.js
24104
+ function isConversationNotice({ message: message2, kind, meta: meta3 }) {
24105
+ const category = kind ?? (isRecord7(meta3) ? meta3["alan.dev/noticeKind"] : void 0);
24106
+ return !(category === "turn_summary" || category === "task_summary" || typeof category === "string" && category.startsWith("turn_summary/") || message2.startsWith("Under-development features enabled:") || /^clamping \S+ hook timeout to /.test(message2) || message2.startsWith("Skill descriptions were shortened to fit") || /^Rate limited \(allowed(?:_warning)?\):/.test(message2));
24107
+ }
24108
+ function uniqueNotices(notices) {
24109
+ const seen = /* @__PURE__ */ new Set();
24110
+ return notices.filter((notice2) => {
24111
+ const key = `${notice2.message}`;
24112
+ if (seen.has(key))
24113
+ return false;
24114
+ seen.add(key);
24115
+ return true;
24116
+ });
24117
+ }
23760
24118
  var init_notice_visibility = __esm({
23761
24119
  "../shared/dist/agent/acp/presentation/notice-visibility.js"() {
23762
24120
  "use strict";
24121
+ init_terminal_events();
23763
24122
  }
23764
24123
  });
23765
24124
 
23766
24125
  // ../shared/dist/agent/acp/presentation/prepare-conversation-turns.js
24126
+ function entryNode(entry, index) {
24127
+ const prepared = preparedEntries.get(entry);
24128
+ if (prepared?.index === index && prepared.lastUpdateIndex === entry.lastUpdateIndex) {
24129
+ return { key: prepared.key, event: prepared.event, children: [] };
24130
+ }
24131
+ const update = entry.kind === "message" ? {
24132
+ sessionUpdate: entry.role === "user" ? "user_message" : entry.role === "thought" ? "agent_thought" : "agent_message",
24133
+ messageId: entry.id,
24134
+ content: Array.isArray(entry.content) ? entry.content : [],
24135
+ _meta: entry._meta
24136
+ } : {
24137
+ sessionUpdate: "tool_call_update",
24138
+ toolCallId: entry.id,
24139
+ name: entry.name ?? entry.title,
24140
+ title: entry.title,
24141
+ kind: entry.toolKind,
24142
+ status: entry.status,
24143
+ content: entry.content,
24144
+ locations: entry.locations,
24145
+ rawInput: entry.rawInput,
24146
+ rawOutput: entry.rawOutput,
24147
+ _meta: entry._meta
24148
+ };
24149
+ const clientId = entry._meta?.["alan.dev/clientMessageId"];
24150
+ const identity = entry.kind === "message" && entry.role === "user" && typeof clientId === "string" ? clientId : entry.id;
24151
+ const key = entry.kind === "message" ? `message:${entry.role}:${identity}` : `tool:${entry.id}`;
24152
+ const event = { id: key, line: index, seq: entry.lastUpdateIndex, update };
24153
+ preparedEntries.set(entry, { index, lastUpdateIndex: entry.lastUpdateIndex, key, event });
24154
+ return { key, event, children: [] };
24155
+ }
24156
+ function attachChildren(nodes) {
24157
+ const tools = /* @__PURE__ */ new Map();
24158
+ const terminals = /* @__PURE__ */ new Map();
24159
+ for (const node2 of nodes) {
24160
+ const u = node2.event.update;
24161
+ if (typeof u.toolCallId === "string")
24162
+ tools.set(u.toolCallId, node2);
24163
+ for (const block of Array.isArray(u.content) ? u.content : []) {
24164
+ if (isRecord7(block) && block.type === "terminal" && typeof block.terminalId === "string")
24165
+ terminals.set(block.terminalId, node2);
24166
+ }
24167
+ }
24168
+ const parents = /* @__PURE__ */ new Map();
24169
+ for (const node2 of nodes) {
24170
+ const u = node2.event.update;
24171
+ const parentId = isRecord7(u._meta) ? u._meta["alan.dev/parentToolCallId"] : void 0;
24172
+ const parent = typeof parentId === "string" ? tools.get(parentId) : typeof u.terminalId === "string" ? terminals.get(u.terminalId) : void 0;
24173
+ if (parent)
24174
+ parents.set(node2, parent);
24175
+ else if (typeof parentId === "string")
24176
+ node2.issue = `Waiting for parent tool ${parentId}`;
24177
+ }
24178
+ return nodes.filter((node2) => {
24179
+ let ancestor = parents.get(node2);
24180
+ const seen = /* @__PURE__ */ new Set([node2]);
24181
+ while (ancestor) {
24182
+ if (seen.has(ancestor)) {
24183
+ node2.issue = "Cyclic parent reference; shown at root";
24184
+ return true;
24185
+ }
24186
+ seen.add(ancestor);
24187
+ ancestor = parents.get(ancestor);
24188
+ }
24189
+ const parent = parents.get(node2);
24190
+ if (!parent)
24191
+ return true;
24192
+ parent.children.push(node2);
24193
+ return false;
24194
+ });
24195
+ }
24196
+ function turnStart(turn) {
24197
+ if (turn.users[0])
24198
+ return turn.users[0].event.line;
24199
+ return turn.working[0]?.event.line;
24200
+ }
24201
+ function hasAnswerContent(node2) {
24202
+ const content = node2.event.update.content;
24203
+ return Array.isArray(content) && content.some((block) => isRecord7(block) && (block.type !== "text" || typeof block.text === "string" && block.text.trim().length > 0));
24204
+ }
24205
+ function messageText(node2) {
24206
+ const content = node2.event.update.content;
24207
+ return Array.isArray(content) ? content.flatMap((block) => isRecord7(block) && block.type === "text" && typeof block.text === "string" ? [block.text] : []).join("") : "";
24208
+ }
24209
+ function prepareConversationTurns(transcript, streaming, previousTurns = []) {
24210
+ const entries = Array.isArray(transcript.entries) ? transcript.entries : [];
24211
+ const nodes = entries.map(entryNode);
24212
+ const terminals = transcript.unknown.flatMap((update, index) => ["terminal_update", "terminal_output_chunk"].includes(update.sessionUpdate) || isRecord7(update._meta) && typeof update._meta["alan.dev/parentToolCallId"] === "string" ? [{ id: `terminal:${index}`, line: entries.length + index, update: { ...update } }] : []);
24213
+ for (const event of foldPreview(terminals))
24214
+ nodes.push({ key: event.id, event, children: [] });
24215
+ const nestedThoughtIds = new Set(nodes.flatMap((node2) => node2.event.update.sessionUpdate === "agent_thought" && typeof node2.event.update.messageId === "string" && isRecord7(node2.event.update._meta) && typeof node2.event.update._meta["alan.dev/parentToolCallId"] === "string" ? [node2.event.update.messageId] : []));
24216
+ const visible = nodes.filter((node2) => !isThought(node2));
24217
+ const roots = attachChildren(visible).filter((node2, index, all) => {
24218
+ const previous = all[index - 1];
24219
+ if (previous?.event.update.sessionUpdate !== "agent_message" || node2.event.update.sessionUpdate !== "agent_message" || !nestedThoughtIds.has(String(node2.event.update.messageId)))
24220
+ return true;
24221
+ const previousText = messageText(previous);
24222
+ return !(previousText.length > 0 && previousText === messageText(node2));
24223
+ });
24224
+ const turns = [];
24225
+ for (const node2 of roots) {
24226
+ const user = node2.event.update.sessionUpdate === "user_message";
24227
+ let turn = turns.at(-1);
24228
+ if (!turn || user) {
24229
+ turn = { key: node2.key, users: [], working: [], activity: { key: node2.key, state: "idle" } };
24230
+ turns.push(turn);
24231
+ }
24232
+ if (user)
24233
+ turn.users.push(node2);
24234
+ else
24235
+ turn.working.push(node2);
24236
+ }
24237
+ const activities = [...transcript.activities ?? []].sort((left, right) => left.firstEntryIndex - right.firstEntryIndex);
24238
+ for (const [turnIndex, turn] of turns.entries()) {
24239
+ const last = turn === turns.at(-1);
24240
+ const firstEntryIndex = turnStart(turn);
24241
+ const next = turns[turnIndex + 1];
24242
+ const nextStart = (next && turnStart(next)) ?? Number.POSITIVE_INFINITY;
24243
+ const runs = firstEntryIndex === void 0 ? [] : activities.filter((activity) => activity.firstEntryIndex >= firstEntryIndex && activity.firstEntryIndex < nextStart);
24244
+ const recorded = runs.at(-1);
24245
+ turn.activity.state = last && transcript.state === "requires_action" ? "requires_action" : last && streaming ? "running" : (
24246
+ // Bytes cut off mid-run are history once the thread is not live; they are not still working.
24247
+ recorded?.state === "running" ? "idle" : recorded?.state ?? "idle"
24248
+ );
24249
+ turn.activity.stopReason = turn.activity.state === "running" ? void 0 : recorded?.stopReason ?? (last ? transcript.stopReason : void 0);
24250
+ const captured = runs.reduce((total, run2) => {
24251
+ const duration3 = run2.startedAt !== void 0 ? Math.max(0, (run2.endedAt ?? run2.updatedAt) - run2.startedAt) : run2.durationMs;
24252
+ return duration3 === void 0 ? total : (total ?? 0) + duration3;
24253
+ }, void 0);
24254
+ if (captured !== void 0)
24255
+ turn.activity.capturedMs = captured;
24256
+ const startedAt = runs.find((run2) => run2.startedAt !== void 0)?.startedAt;
24257
+ if (startedAt !== void 0)
24258
+ turn.activity.startedAt = startedAt;
24259
+ if (turn.activity.state !== "running" && recorded?.endedAt !== void 0)
24260
+ turn.activity.endedAt = recorded.endedAt;
24261
+ turn.activity.neverStarted = recorded?.state === "idle" && recorded.stopReason === "cancelled" && captured === void 0;
24262
+ if (last && streaming && turn.activity.state === "running") {
24263
+ const anchor2 = Math.max(recorded?.startedAt ?? 0, transcript.userMessageAt ?? 0);
24264
+ if (anchor2 > 0)
24265
+ turn.activity.liveStartedAt = anchor2;
24266
+ }
24267
+ const tail = turn.working.reduce((latest, node2) => !latest || (node2.event.seq ?? node2.event.line) > (latest.event.seq ?? latest.event.line) ? node2 : latest, void 0);
24268
+ turn.working = turn.working.filter((node2) => !isThought(node2));
24269
+ const final = turn.activity.state === "idle" && (!turn.activity.stopReason || turn.activity.stopReason === "end_turn" || turn.activity.stopReason === "cancelled") && tail?.event.update.sessionUpdate === "agent_message" && hasAnswerContent(tail) ? tail : void 0;
24270
+ if (final)
24271
+ turn.final = final;
24272
+ }
24273
+ const noticesByEntry = /* @__PURE__ */ new Map();
24274
+ for (const notice2 of uniqueNotices(transcript.notices)) {
24275
+ if (notice2.firstEntryIndex === void 0 || !isConversationNotice(notice2))
24276
+ continue;
24277
+ const group = noticesByEntry.get(notice2.firstEntryIndex);
24278
+ if (group)
24279
+ group.push(notice2);
24280
+ else
24281
+ noticesByEntry.set(notice2.firstEntryIndex, [notice2]);
24282
+ }
24283
+ for (const turn of turns) {
24284
+ const firstEntryIndex = turnStart(turn);
24285
+ const notices = firstEntryIndex === void 0 ? void 0 : noticesByEntry.get(firstEntryIndex);
24286
+ if (notices)
24287
+ turn.notices = notices;
24288
+ }
24289
+ const startedTurn = turns[0];
24290
+ if (transcript.cloudStart && startedTurn?.users.length) {
24291
+ startedTurn.cloudStart = transcript.cloudStart;
24292
+ }
24293
+ const previousByKey = new Map(previousTurns.map((turn) => [turn.key, turn]));
24294
+ return turns.map((turn) => retainTurn(turn, previousByKey.get(turn.key)));
24295
+ }
24296
+ function sameNotices(left, right) {
24297
+ if (left === right)
24298
+ return true;
24299
+ if (!left || !right || left.length !== right.length)
24300
+ return false;
24301
+ return left.every((notice2, index) => notice2.kind === right[index].kind && notice2.level === right[index].level && notice2.message === right[index].message);
24302
+ }
24303
+ function sameFields(left, right) {
24304
+ const keys = Object.keys(left);
24305
+ return keys.length === Object.keys(right).length && keys.every((key) => Reflect.get(left, key) === Reflect.get(right, key));
24306
+ }
24307
+ function retainNodes(nodes, previous) {
24308
+ const byKey = new Map(previous.map((node2) => [node2.key, node2]));
24309
+ const retained = nodes.map((node2) => {
24310
+ const before = byKey.get(node2.key);
24311
+ if (!before)
24312
+ return node2;
24313
+ node2.children = retainNodes(node2.children, before.children);
24314
+ return node2.children === before.children && node2.issue === before.issue && (node2.event === before.event || node2.event.id === before.event.id && sameFields(node2.event.update, before.event.update)) ? before : node2;
24315
+ });
24316
+ return retained.length === previous.length && retained.every((node2, index) => node2 === previous[index]) ? previous : retained;
24317
+ }
24318
+ function retainTurn(turn, previous) {
24319
+ if (previous) {
24320
+ turn.users = retainNodes(turn.users, previous.users);
24321
+ turn.working = retainNodes(turn.working, previous.working);
24322
+ if (turn.final && previous.final)
24323
+ turn.final = retainNodes([turn.final], [previous.final])[0];
24324
+ if (sameFields(turn.activity, previous.activity))
24325
+ turn.activity = previous.activity;
24326
+ if (sameNotices(turn.notices, previous.notices))
24327
+ turn.notices = previous.notices;
24328
+ if (turn.cloudStart && previous.cloudStart && sameFields(turn.cloudStart, previous.cloudStart))
24329
+ turn.cloudStart = previous.cloudStart;
24330
+ }
24331
+ turn.editedFiles = previous && turn.working === previous.working && turn.activity === previous.activity ? previous.editedFiles : turn.activity.state === "idle" ? collectEditedFiles(turn.working) : [];
24332
+ return previous && turn.users === previous.users && turn.working === previous.working && turn.final === previous.final && turn.activity === previous.activity && turn.editedFiles === previous.editedFiles && turn.notices === previous.notices && turn.cloudStart === previous.cloudStart ? previous : turn;
24333
+ }
24334
+ function isThought(node2) {
24335
+ return ["agent_thought", "agent_thought_chunk"].includes(node2.event.update.sessionUpdate);
24336
+ }
24337
+ var preparedEntries;
23767
24338
  var init_prepare_conversation_turns = __esm({
23768
24339
  "../shared/dist/agent/acp/presentation/prepare-conversation-turns.js"() {
23769
24340
  "use strict";
24341
+ init_file_edits();
24342
+ init_notice_visibility();
24343
+ init_terminal_events();
24344
+ preparedEntries = /* @__PURE__ */ new WeakMap();
23770
24345
  }
23771
24346
  });
23772
24347
 
@@ -23781,23 +24356,460 @@ var init_event = __esm({
23781
24356
  function isUpdate(update, kind) {
23782
24357
  return update.sessionUpdate === kind;
23783
24358
  }
24359
+ function isContentUpdate(update) {
24360
+ return update.sessionUpdate === "user_message" || update.sessionUpdate === "user_message_chunk" || update.sessionUpdate === "agent_message" || update.sessionUpdate === "agent_message_chunk" || update.sessionUpdate === "agent_thought" || update.sessionUpdate === "agent_thought_chunk";
24361
+ }
24362
+ function isToolUpdate(update) {
24363
+ return update.sessionUpdate === "tool_call_update" || update.sessionUpdate === "tool_call_content_chunk";
24364
+ }
24365
+ var MEDIA_SESSION_UPDATE_KINDS;
23784
24366
  var init_types2 = __esm({
23785
24367
  "../shared/dist/agent/acp/types.js"() {
23786
24368
  "use strict";
24369
+ MEDIA_SESSION_UPDATE_KINDS = /* @__PURE__ */ new Set([
24370
+ "_alan/generated_image",
24371
+ "_alan/session_media"
24372
+ ]);
23787
24373
  }
23788
24374
  });
23789
24375
 
23790
24376
  // ../shared/dist/agent/acp/reduce.js
24377
+ function emptyTranscript() {
24378
+ return { entries: [], state: "idle", notices: [], unknown: [] };
24379
+ }
24380
+ function applySessionEvent(state, event) {
24381
+ applyUpdate(state, event.update);
24382
+ const update = event.update;
24383
+ if (update._meta && typeof update._meta === "object" && "alan.dev/parentToolCallId" in update._meta && typeof update._meta["alan.dev/parentToolCallId"] === "string")
24384
+ return state;
24385
+ if ((update.sessionUpdate === "user_message" || update.sessionUpdate === "user_message_chunk") && Number.isFinite(event.at))
24386
+ state.userMessageAt = event.at;
24387
+ const lifecycle = isUpdate(update, "state_update");
24388
+ const activities = state.activities ?? [];
24389
+ let activity = activities.at(-1);
24390
+ if (lifecycle) {
24391
+ let userIndex = -1;
24392
+ for (let index = state.entries.length - 1; index >= 0; index -= 1) {
24393
+ const entry = state.entries[index];
24394
+ if (entry.kind === "message" && entry.role === "user") {
24395
+ userIndex = index;
24396
+ break;
24397
+ }
24398
+ }
24399
+ if (!activity || activity.endedAt !== void 0 && (update.state === "running" || userIndex > activity.firstEntryIndex)) {
24400
+ const firstEntryIndex = userIndex >= 0 && (!activity || userIndex > activity.firstEntryIndex) ? userIndex : activity ? state.entries.length : 0;
24401
+ activity = { firstEntryIndex, state: update.state, updatedAt: event.at };
24402
+ activities.push(activity);
24403
+ state.activities = activities;
24404
+ }
24405
+ }
24406
+ if (!activity)
24407
+ return state;
24408
+ const usage = isUpdate(update, "usage_update") ? update._meta?.["alan.dev/usage"] : void 0;
24409
+ if (typeof usage === "object" && usage !== null && "durationMs" in usage && typeof usage.durationMs === "number" && Number.isFinite(usage.durationMs))
24410
+ activity.durationMs = Math.max(0, usage.durationMs);
24411
+ if (activity.endedAt === void 0)
24412
+ activity.updatedAt = event.at;
24413
+ if (lifecycle) {
24414
+ activity.state = update.state;
24415
+ activity.stopReason = update.state === "idle" ? update.stopReason ?? void 0 : void 0;
24416
+ if (update.state === "running" && activity.startedAt === void 0)
24417
+ activity.startedAt = event.at;
24418
+ if (update.state === "idle" && activity.endedAt === void 0)
24419
+ activity.endedAt = event.at;
24420
+ }
24421
+ return state;
24422
+ }
24423
+ function entryIndex(state) {
24424
+ const cached2 = entryIndexes.get(state);
24425
+ if (cached2 && cached2.entries === state.entries && cached2.size === state.entries.length && cached2.last === state.entries.at(-1))
24426
+ return cached2;
24427
+ const byKey = /* @__PURE__ */ new Map();
24428
+ for (const entry of state.entries)
24429
+ byKey.set(entryKey(entry), entry);
24430
+ const index = {
24431
+ entries: state.entries,
24432
+ size: state.entries.length,
24433
+ last: state.entries.at(-1),
24434
+ byKey
24435
+ };
24436
+ entryIndexes.set(state, index);
24437
+ return index;
24438
+ }
24439
+ function applyUpdate(state, update) {
24440
+ const index = entryIndex(state);
24441
+ applyOne(state, index.byKey, update);
24442
+ index.size = state.entries.length;
24443
+ index.last = state.entries.at(-1);
24444
+ return state;
24445
+ }
24446
+ function awaitingToolCallIds(meta3) {
24447
+ const ids = meta3?.[AWAITING_TOOL_CALLS_META];
24448
+ return Array.isArray(ids) ? ids.filter((id) => typeof id === "string") : [];
24449
+ }
24450
+ function entryKey(entry) {
24451
+ return entry.kind === "message" ? `m:${entry.role}:${entry.id}` : `t:${entry.id}`;
24452
+ }
24453
+ function applyOne(state, index, update) {
24454
+ state.updateCount = (state.updateCount ?? 0) + 1;
24455
+ if (isContentUpdate(update)) {
24456
+ applyContent(state, index, update);
24457
+ return;
24458
+ }
24459
+ if (isToolUpdate(update)) {
24460
+ applyTool(state, index, update);
24461
+ return;
24462
+ }
24463
+ if (update.sessionUpdate === "_alan/log" || update.sessionUpdate === "_alan/unhandled")
24464
+ return;
24465
+ if (update._meta && typeof update._meta === "object" && "alan.dev/parentToolCallId" in update._meta && typeof update._meta["alan.dev/parentToolCallId"] === "string") {
24466
+ state.unknown.push(update);
24467
+ return;
24468
+ }
24469
+ switch (update.sessionUpdate) {
24470
+ case "state_update": {
24471
+ if (!isUpdate(update, "state_update"))
24472
+ return;
24473
+ if (update.state === "running" && state.state === "idle")
24474
+ delete state.thinkingTokens;
24475
+ state.state = update.state;
24476
+ if (update.state !== "idle")
24477
+ state.stopReason = void 0;
24478
+ else if (update.stopReason)
24479
+ state.stopReason = update.stopReason;
24480
+ if (update.state === "requires_action")
24481
+ state.awaitingToolCallIds = awaitingToolCallIds(update._meta);
24482
+ else
24483
+ delete state.awaitingToolCallIds;
24484
+ if (update.state === "idle")
24485
+ settleOpenToolCalls(state);
24486
+ return;
24487
+ }
24488
+ case "plan_update": {
24489
+ if (!isUpdate(update, "plan_update"))
24490
+ return;
24491
+ state.plan = { planId: update.planId, entries: update.entries };
24492
+ return;
24493
+ }
24494
+ case "usage_update": {
24495
+ if (!isUpdate(update, "usage_update"))
24496
+ return;
24497
+ state.usage = {
24498
+ used: update.used,
24499
+ size: update.size,
24500
+ ...update.cost ? { cost: update.cost } : {}
24501
+ };
24502
+ delete state.thinkingTokens;
24503
+ return;
24504
+ }
24505
+ case "session_info_update": {
24506
+ if (!isUpdate(update, "session_info_update"))
24507
+ return;
24508
+ if (update.title !== void 0)
24509
+ state.title = update.title ?? void 0;
24510
+ return;
24511
+ }
24512
+ case "notice": {
24513
+ if (!isUpdate(update, "notice"))
24514
+ return;
24515
+ const notice2 = {
24516
+ level: update.severity,
24517
+ kind: noticeKind(update.severity, update._meta),
24518
+ message: update.description ? `${update.title}
24519
+ ${update.description}` : update.title,
24520
+ ...update._meta ? { _meta: update._meta } : {}
24521
+ };
24522
+ const seen = state.notices.some((existing) => existing.level === notice2.level && existing.message === notice2.message);
24523
+ if (!seen)
24524
+ state.notices.push(notice2);
24525
+ return;
24526
+ }
24527
+ case "_alan/thinking_tokens": {
24528
+ if (!isUpdate(update, "_alan/thinking_tokens"))
24529
+ return;
24530
+ state.thinkingTokens = update.estimated;
24531
+ return;
24532
+ }
24533
+ // Owned by the tool call that references it, but kept so a terminal-aware
24534
+ // renderer can still consume the raw update.
24535
+ case "terminal_update":
24536
+ case "terminal_output_chunk":
24537
+ state.unknown.push(update);
24538
+ return;
24539
+ // ACP: preserve a variant this build does not know rather than dropping it.
24540
+ default:
24541
+ state.unknown.push(update);
24542
+ }
24543
+ }
24544
+ function noticeKind(severity, meta3) {
24545
+ const kind = meta3?.["alan.dev/noticeKind"];
24546
+ return typeof kind === "string" ? kind : severity;
24547
+ }
24548
+ function applyContent(state, index, update) {
24549
+ const role = ROLE_BY_KIND[update.sessionUpdate];
24550
+ if (!role)
24551
+ return;
24552
+ const key = `m:${role}:${update.messageId}`;
24553
+ let entry = index.get(key);
24554
+ if (!entry) {
24555
+ entry = { kind: "message", id: update.messageId, role, content: [] };
24556
+ index.set(key, entry);
24557
+ state.entries.push(entry);
24558
+ }
24559
+ entry.lastUpdateIndex = state.updateCount;
24560
+ if (update.sessionUpdate.endsWith("_chunk")) {
24561
+ const block = update.content;
24562
+ if (block)
24563
+ entry.content.push(block);
24564
+ } else {
24565
+ const content = update.content;
24566
+ if (content !== void 0) {
24567
+ entry.content = content === null ? [] : Array.isArray(content) ? content : [content];
24568
+ }
24569
+ }
24570
+ if (update._meta !== void 0) {
24571
+ entry._meta = update._meta === null ? void 0 : { ...entry._meta, ...update._meta };
24572
+ }
24573
+ }
24574
+ function isSettled(status) {
24575
+ return SETTLED.has(status);
24576
+ }
24577
+ function outlivesTheTurn(entry) {
24578
+ if (readBackgroundTaskMeta(entry._meta))
24579
+ return true;
24580
+ const input2 = entry.rawInput;
24581
+ return entry.name?.toLowerCase() === "bash" && typeof input2 === "object" && input2 !== null && input2.run_in_background === true;
24582
+ }
24583
+ function settleOpenToolCalls(state) {
24584
+ for (const entry of state.entries) {
24585
+ if (entry.kind !== "tool_call" || isSettled(entry.status))
24586
+ continue;
24587
+ if (outlivesTheTurn(entry))
24588
+ continue;
24589
+ entry.status = "cancelled";
24590
+ }
24591
+ }
24592
+ function applyTool(state, index, update) {
24593
+ const key = `t:${update.toolCallId}`;
24594
+ let entry = index.get(key);
24595
+ if (!entry) {
24596
+ entry = {
24597
+ kind: "tool_call",
24598
+ id: update.toolCallId,
24599
+ toolKind: "other",
24600
+ status: "pending",
24601
+ content: [],
24602
+ locations: []
24603
+ };
24604
+ index.set(key, entry);
24605
+ state.entries.push(entry);
24606
+ }
24607
+ entry.lastUpdateIndex = state.updateCount;
24608
+ if (update.sessionUpdate === "tool_call_content_chunk") {
24609
+ const block = update.content;
24610
+ if (block)
24611
+ entry.content.push(block);
24612
+ return;
24613
+ }
24614
+ const u = update;
24615
+ if (u.name !== void 0)
24616
+ entry.name = u.name ?? void 0;
24617
+ if (u.title !== void 0)
24618
+ entry.title = u.title ?? void 0;
24619
+ if (!entry.title && typeof u.name === "string" && u.name.length > 0)
24620
+ entry.title = u.name;
24621
+ if (u.kind !== void 0)
24622
+ entry.toolKind = u.kind ?? "other";
24623
+ if (u.status !== void 0 && !isSettled(entry.status))
24624
+ entry.status = u.status ?? "pending";
24625
+ if (u.content !== void 0)
24626
+ entry.content = u.content ?? [];
24627
+ if (u.locations !== void 0)
24628
+ entry.locations = u.locations ?? [];
24629
+ if (u.rawInput !== void 0)
24630
+ entry.rawInput = u.rawInput;
24631
+ if (u.rawOutput !== void 0)
24632
+ entry.rawOutput = u.rawOutput;
24633
+ if (u._meta !== void 0) {
24634
+ entry._meta = u._meta === null ? void 0 : { ...entry._meta, ...u._meta };
24635
+ }
24636
+ }
24637
+ function messageText2(entry) {
24638
+ return entry.content.filter((b) => b.type === "text").map((b) => b.text).join("");
24639
+ }
24640
+ var ROLE_BY_KIND, entryIndexes, AWAITING_TOOL_CALLS_META, SETTLED;
23791
24641
  var init_reduce = __esm({
23792
24642
  "../shared/dist/agent/acp/reduce.js"() {
23793
24643
  "use strict";
24644
+ init_background_task();
24645
+ init_types2();
24646
+ ROLE_BY_KIND = {
24647
+ user_message: "user",
24648
+ user_message_chunk: "user",
24649
+ agent_message: "agent",
24650
+ agent_message_chunk: "agent",
24651
+ agent_thought: "thought",
24652
+ agent_thought_chunk: "thought"
24653
+ };
24654
+ entryIndexes = /* @__PURE__ */ new WeakMap();
24655
+ AWAITING_TOOL_CALLS_META = "alan.dev/awaitingToolCallIds";
24656
+ SETTLED = /* @__PURE__ */ new Set(["completed", "failed", "cancelled"]);
23794
24657
  }
23795
24658
  });
23796
24659
 
23797
24660
  // ../shared/dist/agent/acp/conversation-messages.js
24661
+ function compactConversationMessageTurns(turns, keepNewestEntries) {
24662
+ return turns.map((turn, index) => ({
24663
+ ...turn,
24664
+ display: turn.display.map((displayTurn) => {
24665
+ if (!displayTurn.final)
24666
+ return displayTurn;
24667
+ return {
24668
+ ...displayTurn,
24669
+ working: displayTurn.working.map((node2) => node2.key === displayTurn.final?.key ? {
24670
+ ...node2,
24671
+ children: [],
24672
+ event: {
24673
+ ...node2.event,
24674
+ update: { ...node2.event.update, content: [] }
24675
+ }
24676
+ } : node2)
24677
+ };
24678
+ }),
24679
+ state: {
24680
+ ...turn.state,
24681
+ entries: index === 0 && keepNewestEntries ? turn.state.entries.map((entry) => {
24682
+ if (entry.kind === "message")
24683
+ return entry.role === "user" ? entry : { ...entry, content: [] };
24684
+ const ask = isAskUserQuestionTool(entry.title || entry.toolKind, entry.rawInput);
24685
+ return {
24686
+ ...entry,
24687
+ content: [],
24688
+ locations: [],
24689
+ rawInput: ask ? entry.rawInput : void 0,
24690
+ rawOutput: void 0
24691
+ };
24692
+ }) : []
24693
+ }
24694
+ }));
24695
+ }
24696
+ function prepareConversationTurnRead(state) {
24697
+ const prompts = [];
24698
+ const navigation = [];
24699
+ const interactiveTools = [];
24700
+ let modeChange = null;
24701
+ let latestAgentMessageId = null;
24702
+ for (const entry of state.entries) {
24703
+ if (entry.kind === "message" && entry.role === "user") {
24704
+ const meta3 = entry._meta ?? {};
24705
+ if (typeof meta3["alan.dev/parentToolCallId"] !== "string") {
24706
+ const clientMessageId = meta3["alan.dev/clientMessageId"];
24707
+ prompts.push({
24708
+ entryId: entry.id,
24709
+ ...typeof clientMessageId === "string" ? { clientMessageId } : {},
24710
+ content: messageText2(entry),
24711
+ agentMode: typeof meta3["alan.dev/agentMode"] === "string" ? meta3["alan.dev/agentMode"] : null,
24712
+ attachmentIds: Array.isArray(meta3["alan.dev/attachmentIds"]) ? meta3["alan.dev/attachmentIds"] : void 0,
24713
+ references: Array.isArray(meta3["alan.dev/references"]) ? meta3["alan.dev/references"] : void 0
24714
+ });
24715
+ }
24716
+ const title = toPreviewText(messageText2(entry).slice(0, 960).replace(attachmentMentionPattern(), ""), 240);
24717
+ navigation.push({ id: entry.id, title: title || "Message with attachments" });
24718
+ continue;
24719
+ }
24720
+ if (entry.kind === "message" && entry.role === "agent" && navigation.length > 0) {
24721
+ latestAgentMessageId = entry.id;
24722
+ if (typeof entry._meta?.["alan.dev/parentToolCallId"] === "string")
24723
+ continue;
24724
+ const content = messageText2(entry);
24725
+ if (!/\S/.test(content))
24726
+ continue;
24727
+ const preview = toPreviewText(content.slice(0, 960).replace(attachmentMentionPattern(), ""), 240);
24728
+ if (preview)
24729
+ navigation[navigation.length - 1].preview = preview;
24730
+ continue;
24731
+ }
24732
+ if (entry.kind === "message" && entry.role === "agent") {
24733
+ latestAgentMessageId = entry.id;
24734
+ continue;
24735
+ }
24736
+ if (entry.kind !== "tool_call")
24737
+ continue;
24738
+ const name = entry.name || entry.title || entry.toolKind;
24739
+ const responseToolId = entry._meta?.[TRANSCRIPT_TOOL_RESPONSE_ID_META];
24740
+ interactiveTools.push({
24741
+ id: entry.id,
24742
+ name,
24743
+ ...(entry.status === "pending" || entry.status === "in_progress") && {
24744
+ input: entry.rawInput
24745
+ },
24746
+ ...typeof responseToolId === "string" ? { responseToolId } : {}
24747
+ });
24748
+ const toolName2 = (entry.name || entry.title)?.trim().toLowerCase();
24749
+ if (toolName2 === "enterplanmode") {
24750
+ modeChange = "plan";
24751
+ continue;
24752
+ }
24753
+ if (toolName2 !== "exitplanmode")
24754
+ continue;
24755
+ if (entry.status !== "completed" && entry.status !== "failed")
24756
+ continue;
24757
+ const output2 = typeof entry.rawOutput === "string" ? entry.rawOutput : entry.content.flatMap((item) => item.type === "content" && item.content.type === "text" ? [item.content.text] : []).join("\n");
24758
+ const response = output2.trim().toLowerCase();
24759
+ if (response === "accepted" && entry.status === "completed")
24760
+ modeChange = "agent";
24761
+ else if (response === "rejected")
24762
+ modeChange = "plan";
24763
+ }
24764
+ return {
24765
+ entryCount: state.entries.length,
24766
+ latestAgentMessageId,
24767
+ prompts,
24768
+ navigation,
24769
+ modeChange,
24770
+ pendingAsk: findPendingAsk(state.entries),
24771
+ interactiveTools
24772
+ };
24773
+ }
24774
+ function conversationTurnView(ordinal, state, previousDisplay = []) {
24775
+ return {
24776
+ ordinal,
24777
+ state,
24778
+ display: prepareConversationTurns(state, state.state === "running", previousDisplay),
24779
+ read: prepareConversationTurnRead(state)
24780
+ };
24781
+ }
24782
+ function isRecord8(value2) {
24783
+ return value2 !== null && typeof value2 === "object" && !Array.isArray(value2);
24784
+ }
24785
+ function isTranscriptState(value2) {
24786
+ return isRecord8(value2) && typeof value2.state === "string" && Array.isArray(value2.entries) && Array.isArray(value2.notices) && Array.isArray(value2.unknown);
24787
+ }
24788
+ function isPendingAsk(value2) {
24789
+ return value2 === null || isRecord8(value2) && typeof value2.toolCallId === "string" && isRecord8(value2.rawInput) && Array.isArray(value2.questions) && value2.questions.every((question) => isRecord8(question) && typeof question.question === "string" && (question.header === void 0 || typeof question.header === "string") && typeof question.multiSelect === "boolean" && Array.isArray(question.options) && question.options.every((option2) => isRecord8(option2) && typeof option2.label === "string" && (option2.description === void 0 || typeof option2.description === "string")));
24790
+ }
24791
+ function isInteractiveTool(value2) {
24792
+ return isRecord8(value2) && typeof value2.id === "string" && typeof value2.name === "string" && (value2.responseToolId === void 0 || typeof value2.responseToolId === "string");
24793
+ }
24794
+ function isConversationTurnRead(value2) {
24795
+ return isRecord8(value2) && Number.isSafeInteger(value2.entryCount) && (value2.latestAgentMessageId === null || typeof value2.latestAgentMessageId === "string") && Array.isArray(value2.prompts) && value2.prompts.every((prompt) => isRecord8(prompt) && (prompt.entryId === void 0 || typeof prompt.entryId === "string") && (prompt.clientMessageId === void 0 || typeof prompt.clientMessageId === "string") && typeof prompt.content === "string" && (prompt.agentMode === null || typeof prompt.agentMode === "string")) && Array.isArray(value2.navigation) && value2.navigation.every((item) => isRecord8(item) && typeof item.id === "string" && typeof item.title === "string" && (item.preview === void 0 || typeof item.preview === "string")) && (value2.modeChange === null || value2.modeChange === "plan" || value2.modeChange === "agent") && isPendingAsk(value2.pendingAsk) && Array.isArray(value2.interactiveTools) && value2.interactiveTools.every(isInteractiveTool);
24796
+ }
24797
+ function isConversationMessageTurn(value2) {
24798
+ return isRecord8(value2) && Number.isSafeInteger(value2.ordinal) && typeof value2.markdown === "string" && isTranscriptState(value2.state) && Array.isArray(value2.display) && isConversationTurnRead(value2.read) && value2.display.every((turn) => isRecord8(turn) && typeof turn.key === "string" && Array.isArray(turn.users) && Array.isArray(turn.working) && isRecord8(turn.activity));
24799
+ }
24800
+ function isConversationMessagesPage(value2) {
24801
+ return isRecord8(value2) && typeof value2.revision === "string" && typeof value2.streamCursor === "string" && (value2.before === null || typeof value2.before === "string") && Array.isArray(value2.turns) && value2.turns.every(isConversationMessageTurn);
24802
+ }
23798
24803
  var init_conversation_messages = __esm({
23799
24804
  "../shared/dist/agent/acp/conversation-messages.js"() {
23800
24805
  "use strict";
24806
+ init_agent();
24807
+ init_attachment_mention();
24808
+ init_preview();
24809
+ init_ask();
24810
+ init_prepare_conversation_turns();
24811
+ init_reduce();
24812
+ init_transcript_http();
23801
24813
  }
23802
24814
  });
23803
24815
 
@@ -23823,9 +24835,60 @@ var init_transcript_byte_decoder = __esm({
23823
24835
  });
23824
24836
 
23825
24837
  // ../shared/dist/agent/acp/transcript-fold.js
24838
+ function snapshotTranscriptState(state) {
24839
+ return {
24840
+ ...state,
24841
+ entries: state.entries.map((entry) => entry.kind === "message" ? { ...entry, content: [...entry.content] } : { ...entry, content: [...entry.content], locations: [...entry.locations] }),
24842
+ notices: [...state.notices],
24843
+ unknown: [...state.unknown],
24844
+ ...state.activities ? { activities: state.activities.map((activity) => ({ ...activity })) } : {}
24845
+ };
24846
+ }
24847
+ function isRecord9(value2) {
24848
+ return value2 !== null && typeof value2 === "object" && !Array.isArray(value2);
24849
+ }
24850
+ function scopedContent(value2, turnId) {
24851
+ if (!Array.isArray(value2))
24852
+ return value2;
24853
+ return value2.map((block) => isRecord9(block) && block.type === "terminal" && typeof block.terminalId === "string" ? { ...block, terminalId: `${turnId}:${block.terminalId}` } : block);
24854
+ }
24855
+ function scopeTranscriptEvent(value2) {
24856
+ if (!isRecord9(value2) || !Number.isSafeInteger(value2.seq) || !Number.isFinite(value2.at))
24857
+ return null;
24858
+ if (!isRecord9(value2.update) || typeof value2.update.sessionUpdate !== "string")
24859
+ return null;
24860
+ const update = value2.update;
24861
+ const turnId = typeof value2.turnId === "string" ? value2.turnId : void 0;
24862
+ const event = {
24863
+ seq: Number(value2.seq),
24864
+ at: Number(value2.at),
24865
+ ...typeof value2.sessionId === "string" ? { sessionId: value2.sessionId } : {},
24866
+ update
24867
+ };
24868
+ if (!turnId)
24869
+ return event;
24870
+ const meta3 = isRecord9(update._meta) ? { ...update._meta } : {};
24871
+ const parent = meta3["alan.dev/parentToolCallId"];
24872
+ if (typeof parent === "string")
24873
+ meta3["alan.dev/parentToolCallId"] = `${turnId}:${parent}`;
24874
+ if (typeof update.toolCallId === "string")
24875
+ meta3[TRANSCRIPT_TOOL_RESPONSE_ID_META] = update.toolCallId;
24876
+ if (typeof update.sessionUpdate === "string" && MEDIA_SESSION_UPDATE_KINDS.has(update.sessionUpdate))
24877
+ meta3[TRANSCRIPT_TURN_ID_META] = turnId;
24878
+ const scoped = { ...update, _meta: meta3 };
24879
+ for (const key of ["messageId", "toolCallId", "terminalId", "planId"]) {
24880
+ if (typeof update[key] === "string")
24881
+ scoped[key] = `${turnId}:${update[key]}`;
24882
+ }
24883
+ if ("content" in update)
24884
+ scoped.content = scopedContent(update.content, turnId);
24885
+ return { ...event, update: scoped };
24886
+ }
23826
24887
  var init_transcript_fold = __esm({
23827
24888
  "../shared/dist/agent/acp/transcript-fold.js"() {
23828
24889
  "use strict";
24890
+ init_transcript_http();
24891
+ init_types2();
23829
24892
  }
23830
24893
  });
23831
24894
 
@@ -24092,7 +25155,7 @@ function withoutInlineMedia(update) {
24092
25155
  ...nextRawOutput === rawOutput ? {} : { rawOutput: nextRawOutput }
24093
25156
  };
24094
25157
  }
24095
- var PROVIDER_PAYLOAD_META, TOOL_RESULT_ONLY_META, PARENT_TOOL_CALL_META, SUBAGENT_LAUNCHER_META, SUBAGENT_TASK_ID_META, SUBAGENT_OUTPUT_FILE_META, USAGE_META, TODOS_META, NOTICE_KIND_META, ASK_USER_QUESTIONS_META, USER_ANSWER_META, AWAITING_TOOL_CALLS_META, EXIT_PLAN_MODE_INPUT_META, BACKGROUND_TASK_META, TASK_PROGRESS_META, RATE_LIMIT_META, MODEL_META, TOOLS_META, SLASH_COMMANDS_META, TOOL_KIND_RULES, ANSWER_PREFIX, ACCEPT_WORDS, MIN_INLINE_MEDIA_CHARS, DATA_URL_PREFIX, BASE64_BODY;
25158
+ var PROVIDER_PAYLOAD_META, TOOL_RESULT_ONLY_META, PARENT_TOOL_CALL_META, SUBAGENT_LAUNCHER_META, SUBAGENT_TASK_ID_META, SUBAGENT_OUTPUT_FILE_META, USAGE_META, TODOS_META, NOTICE_KIND_META, ASK_USER_QUESTIONS_META, USER_ANSWER_META, AWAITING_TOOL_CALLS_META2, EXIT_PLAN_MODE_INPUT_META, BACKGROUND_TASK_META, TASK_PROGRESS_META, RATE_LIMIT_META, MODEL_META, TOOLS_META, SLASH_COMMANDS_META, TOOL_KIND_RULES, ANSWER_PREFIX, ACCEPT_WORDS, MIN_INLINE_MEDIA_CHARS, DATA_URL_PREFIX, BASE64_BODY;
24096
25159
  var init_chunk_UGRKZTAD = __esm({
24097
25160
  "../agent-core/dist/chunk-UGRKZTAD.js"() {
24098
25161
  "use strict";
@@ -24110,7 +25173,7 @@ var init_chunk_UGRKZTAD = __esm({
24110
25173
  NOTICE_KIND_META = "alan.dev/noticeKind";
24111
25174
  ASK_USER_QUESTIONS_META = "alan.dev/askUserQuestions";
24112
25175
  USER_ANSWER_META = "alan.dev/userAnswer";
24113
- AWAITING_TOOL_CALLS_META = "alan.dev/awaitingToolCallIds";
25176
+ AWAITING_TOOL_CALLS_META2 = "alan.dev/awaitingToolCallIds";
24114
25177
  EXIT_PLAN_MODE_INPUT_META = "alan.dev/exitPlanModeInput";
24115
25178
  BACKGROUND_TASK_META = BACKGROUND_TASK_META_KEY;
24116
25179
  TASK_PROGRESS_META = "alan.dev/taskProgress";
@@ -24884,7 +25947,7 @@ var init_chunk_54ZRJOQP = __esm({
24884
25947
  }
24885
25948
  });
24886
25949
 
24887
- // ../agent-core/dist/chunk-YPYC4VBL.js
25950
+ // ../agent-core/dist/chunk-KHYYC5IN.js
24888
25951
  function collectStrings(value2, out) {
24889
25952
  if (typeof value2 === "string") out.push(value2);
24890
25953
  else if (Array.isArray(value2)) for (const item of value2) collectStrings(item, out);
@@ -25254,12 +26317,12 @@ function silentStartError(name, timeoutMs) {
25254
26317
  };
25255
26318
  }
25256
26319
  var import_crypto3, import_fs4, import_path3, IMAGE_MIME_BY_EXT, VIDEO_MIME_BY_EXT, IMAGE_EXTENSIONS, VIDEO_EXTENSIONS, MAX_IMAGE_BYTES, MAX_VIDEO_BYTES, AGENT_BROWSER_MENTION, LocalMediaReader, SessionOpenRefusal, JsonRpcError, ACP_PROTOCOL_VERSION, ACP_ERROR, STDERR_TAIL_LINES, RESULT_EXIT_GRACE_MS, PerTurnSession;
25257
- var init_chunk_YPYC4VBL = __esm({
25258
- "../agent-core/dist/chunk-YPYC4VBL.js"() {
26320
+ var init_chunk_KHYYC5IN = __esm({
26321
+ "../agent-core/dist/chunk-KHYYC5IN.js"() {
25259
26322
  "use strict";
25260
26323
  init_chunk_UGRKZTAD();
25261
26324
  init_chunk_54ZRJOQP();
25262
- init_chunk_J4T6L5LX();
26325
+ init_chunk_M6YHY2EZ();
25263
26326
  init_chunk_YXWJW7I5();
25264
26327
  import_crypto3 = require("crypto");
25265
26328
  import_fs4 = require("fs");
@@ -25721,7 +26784,7 @@ var init_chunk_J2KTV5FP = __esm({
25721
26784
  }
25722
26785
  });
25723
26786
 
25724
- // ../agent-core/dist/chunk-6WN2R725.js
26787
+ // ../agent-core/dist/chunk-ITTV3UIM.js
25725
26788
  function truncate(value2, limit) {
25726
26789
  const normalized2 = Array.from(value2, (character) => {
25727
26790
  const code = character.charCodeAt(0);
@@ -25974,9 +27037,41 @@ function teamOverlay(spec) {
25974
27037
  function present(values) {
25975
27038
  return values.filter((value2) => Boolean(value2?.length));
25976
27039
  }
27040
+ function cloudExecutionSection(spec) {
27041
+ if (!spec.sandboxId && !spec.cloudEnvironmentId) return void 0;
27042
+ const lines2 = ["## Cloud execution", "You are executing inside an Alan cloud sandbox."];
27043
+ if (spec.sandboxId) lines2.push(`Sandbox ID: ${spec.sandboxId}.`);
27044
+ if (spec.cloudEnvironmentId) lines2.push(`Cloud environment ID: ${spec.cloudEnvironmentId}.`);
27045
+ lines2.push(
27046
+ "Run setup, development and validation in this sandbox. The execution location is separate from the deployment of the application you are testing; verify that application's origin before acting."
27047
+ );
27048
+ if (!isReadOnlyMode(spec.mode) && !isReadOnlyAgent(spec.agentId)) {
27049
+ lines2.push(
27050
+ "Own the authorized work end to end: inspect context, make reasonable assumptions, implement, test, review and create or update the pull request for code changes when the repository workflow calls for one. Do not stop at a plan or ask for routine implementation choices or permission already granted. Ask only for a missing secret, an essential decision you cannot derive, or an action requiring explicit approval. Respect the user's scope, repository rules and tool authorization; report a blocked capability and continue independent work."
27051
+ );
27052
+ }
27053
+ const skills = spec.promptContext?.availableSkills ?? [];
27054
+ lines2.push(
27055
+ "## Installed skills",
27056
+ "Use a matching installed skill when it helps the request. Read its SKILL.md before acting; the index is discovery metadata, not instructions. Also follow repository instructions and project skills."
27057
+ );
27058
+ if (skills.length === 0) {
27059
+ lines2.push(
27060
+ skills.length === 0 && spec.promptContext?.availableSkills !== void 0 ? "No verified installed packages were found. Do not assume a named skill is available." : "No installed skill inventory was supplied. Inspect the provider's skill index; do not assume a named package is installed."
27061
+ );
27062
+ } else {
27063
+ for (const skill of skills) {
27064
+ lines2.push(
27065
+ `- ${JSON.stringify(skill.name)}: ${JSON.stringify(skill.description)} \u2014 ${JSON.stringify(`${skill.packageDirectory}/SKILL.md`)}`
27066
+ );
27067
+ }
27068
+ }
27069
+ return lines2.join("\n");
27070
+ }
25977
27071
  function promptParts(input2) {
25978
27072
  const { spec } = input2;
25979
27073
  const overlay = teamOverlay(spec);
27074
+ const cloud = cloudExecutionSection(spec);
25980
27075
  const workspace = input2.workspacePath ? `You are working inside: ${input2.workspacePath}
25981
27076
  Prefer relative paths and keep your work scoped to this project.` : void 0;
25982
27077
  return {
@@ -25985,6 +27080,7 @@ Prefer relative paths and keep your work scoped to this project.` : void 0;
25985
27080
  spec.agentPrompt?.trim() || getAlanAgentPrompt(spec.agentId),
25986
27081
  getAlanModePrompt(agentModeOf(spec.mode)),
25987
27082
  workspace,
27083
+ cloud,
25988
27084
  taskLifecycleSection(spec),
25989
27085
  overlay,
25990
27086
  ...contextSections(spec),
@@ -25992,6 +27088,7 @@ Prefer relative paths and keep your work scoped to this project.` : void 0;
25992
27088
  ]),
25993
27089
  append: present([
25994
27090
  ALAN_PLATFORM_TOOL_ROUTING_PROMPT,
27091
+ cloud,
25995
27092
  spec.contextGraphEnabled === true ? ALAN_CONTEXT_SEARCH_PROMPT : void 0,
25996
27093
  overlay
25997
27094
  ])
@@ -26048,8 +27145,8 @@ ${body}` : body;
26048
27145
  return spec.mode === "plan" ? planModePrefix(prefixed) : prefixed;
26049
27146
  }
26050
27147
  var MAX_PARSED_ATTACHMENTS, MAX_PARSED_ATTACHMENT_CHARS, MAX_METADATA_CHARS, UNAVAILABLE, READ_ONLY_MODES, AGENT_MODES;
26051
- var init_chunk_6WN2R725 = __esm({
26052
- "../agent-core/dist/chunk-6WN2R725.js"() {
27148
+ var init_chunk_ITTV3UIM = __esm({
27149
+ "../agent-core/dist/chunk-ITTV3UIM.js"() {
26053
27150
  "use strict";
26054
27151
  init_agent2();
26055
27152
  MAX_PARSED_ATTACHMENTS = 3;
@@ -26716,7 +27813,7 @@ function launcherLabel(update) {
26716
27813
  const description = asRecord(update.rawInput)?.description;
26717
27814
  return nonEmpty(description) ?? nonEmpty(update.title);
26718
27815
  }
26719
- function isSettled(update) {
27816
+ function isSettled2(update) {
26720
27817
  return update.status === "completed" || update.status === "failed" || update.status === "cancelled";
26721
27818
  }
26722
27819
  function isRunningTask(record2) {
@@ -26888,7 +27985,7 @@ function classifyResultError(event, context) {
26888
27985
  if (classified.errorKind !== "unknown_cli_error" || !isApiError) return classified;
26889
27986
  return { ...specForErrorKind("provider_error"), message: classified.message };
26890
27987
  }
26891
- function isSettled2(update) {
27988
+ function isSettled22(update) {
26892
27989
  return update.status === "completed" || update.status === "failed" || update.status === "cancelled";
26893
27990
  }
26894
27991
  function parentToolUseId(event) {
@@ -27316,12 +28413,12 @@ var init_claude = __esm({
27316
28413
  "../agent-core/dist/providers/claude.js"() {
27317
28414
  "use strict";
27318
28415
  init_chunk_DALFHI4B();
27319
- init_chunk_YPYC4VBL();
28416
+ init_chunk_KHYYC5IN();
27320
28417
  init_chunk_UGRKZTAD();
27321
28418
  init_chunk_54ZRJOQP();
27322
28419
  init_chunk_J2KTV5FP();
27323
- init_chunk_J4T6L5LX();
27324
- init_chunk_6WN2R725();
28420
+ init_chunk_M6YHY2EZ();
28421
+ init_chunk_ITTV3UIM();
27325
28422
  init_chunk_YXWJW7I5();
27326
28423
  init_effort();
27327
28424
  import_crypto6 = require("crypto");
@@ -27477,7 +28574,7 @@ var init_claude = __esm({
27477
28574
  if (!record2) return update;
27478
28575
  const remembered = record2.meta.label ?? this.#labels.get(update.toolCallId);
27479
28576
  if (!record2.meta.label && remembered) record2.meta = { ...record2.meta, label: remembered };
27480
- if (isSettled(update) && record2.meta.kind === "agent" && isRunningTask(record2)) {
28577
+ if (isSettled2(update) && record2.meta.kind === "agent" && isRunningTask(record2)) {
27481
28578
  this.settle(record2, update.status ?? void 0, update.status !== "completed");
27482
28579
  }
27483
28580
  return { ...update, _meta: { ...update._meta, [BACKGROUND_TASK_META_KEY]: record2.meta } };
@@ -27898,7 +28995,7 @@ var init_claude = __esm({
27898
28995
  this.#announced.add(id);
27899
28996
  if (isLauncher) this.#registerLauncher(update, meta3);
27900
28997
  }
27901
- if (isLauncher && isSettled2(update)) this.tasks.clear([id]);
28998
+ if (isLauncher && isSettled22(update)) this.tasks.clear([id]);
27902
28999
  }
27903
29000
  #registerLauncher(update, meta3) {
27904
29001
  this.tasks.registerLauncher(update.toolCallId);
@@ -30093,12 +31190,12 @@ var init_codex = __esm({
30093
31190
  "../agent-core/dist/providers/codex.js"() {
30094
31191
  "use strict";
30095
31192
  init_chunk_DALFHI4B();
30096
- init_chunk_YPYC4VBL();
31193
+ init_chunk_KHYYC5IN();
30097
31194
  init_chunk_UGRKZTAD();
30098
31195
  init_chunk_54ZRJOQP();
30099
31196
  init_chunk_J2KTV5FP();
30100
- init_chunk_J4T6L5LX();
30101
- init_chunk_6WN2R725();
31197
+ init_chunk_M6YHY2EZ();
31198
+ init_chunk_ITTV3UIM();
30102
31199
  init_chunk_YXWJW7I5();
30103
31200
  import_fs6 = require("fs");
30104
31201
  import_path6 = require("path");
@@ -41363,10 +42460,10 @@ var require_tar_stream = __commonJS({
41363
42460
  var init_dist = __esm({
41364
42461
  "../agent-core/dist/index.js"() {
41365
42462
  "use strict";
41366
- init_chunk_YPYC4VBL();
42463
+ init_chunk_KHYYC5IN();
41367
42464
  init_chunk_UGRKZTAD();
41368
42465
  init_chunk_54ZRJOQP();
41369
- init_chunk_J4T6L5LX();
42466
+ init_chunk_M6YHY2EZ();
41370
42467
  init_chunk_YXWJW7I5();
41371
42468
  }
41372
42469
  });
@@ -41602,7 +42699,7 @@ function isRunning(task) {
41602
42699
  return task.meta.status === "running" || task.meta.status === "stopping";
41603
42700
  }
41604
42701
  function isPlanStatus(value2) {
41605
- return STATUSES.has(value2);
42702
+ return STATUSES2.has(value2);
41606
42703
  }
41607
42704
  function todoEntries2(todos) {
41608
42705
  return asArray(todos).flatMap((raw) => {
@@ -42106,16 +43203,16 @@ async function acpTurnInput(run2, context) {
42106
43203
  ...encoded.length ? { images: encoded, imagePaths: images.map((image) => image.path) } : {}
42107
43204
  };
42108
43205
  }
42109
- var import_promises48, import_path9, import_crypto12, import_promises49, CURSOR_ASK_QUESTION, copilotAcpProfile, cursorAcpProfile, MODEL_REJECTED, MAX_READ_BYTES, FsDenied, ENV_REFERENCE, AcpBackgroundTasks, CURSOR_CREATE_PLAN, STATUSES, READ_KINDS, ALLOW_KINDS, REJECT_KINDS, CANCELLED_PERMISSION, STOP_REASONS, CHUNKS, ECHOES, AcpTurn, STDERR_TAIL_LINES4, MAX_BETWEEN_UPDATES2, AcpSession, DEFAULTS3, CLIENT_INFO2, TASK_BACKGROUNDED, TASK_COMPLETED, SESSION_NOTIFICATION, KILLED_STATUSES, SUCCESS_STATUSES, SUBAGENT_ID, grokTaskDialect, grokAcpProfile, kimiAcpProfile, ACP_PROFILES, ACP_MODES;
43206
+ var import_promises48, import_path9, import_crypto12, import_promises49, CURSOR_ASK_QUESTION, copilotAcpProfile, cursorAcpProfile, MODEL_REJECTED, MAX_READ_BYTES, FsDenied, ENV_REFERENCE, AcpBackgroundTasks, CURSOR_CREATE_PLAN, STATUSES2, READ_KINDS, ALLOW_KINDS, REJECT_KINDS, CANCELLED_PERMISSION, STOP_REASONS, CHUNKS, ECHOES, AcpTurn, STDERR_TAIL_LINES4, MAX_BETWEEN_UPDATES2, AcpSession, DEFAULTS3, CLIENT_INFO2, TASK_BACKGROUNDED, TASK_COMPLETED, SESSION_NOTIFICATION, KILLED_STATUSES, SUCCESS_STATUSES, SUBAGENT_ID, grokTaskDialect, grokAcpProfile, kimiAcpProfile, ACP_PROFILES, ACP_MODES;
42110
43207
  var init_acp3 = __esm({
42111
43208
  "../agent-core/dist/providers/acp.js"() {
42112
43209
  "use strict";
42113
- init_chunk_YPYC4VBL();
43210
+ init_chunk_KHYYC5IN();
42114
43211
  init_chunk_UGRKZTAD();
42115
43212
  init_chunk_54ZRJOQP();
42116
43213
  init_chunk_J2KTV5FP();
42117
- init_chunk_J4T6L5LX();
42118
- init_chunk_6WN2R725();
43214
+ init_chunk_M6YHY2EZ();
43215
+ init_chunk_ITTV3UIM();
42119
43216
  init_chunk_YXWJW7I5();
42120
43217
  import_promises48 = require("fs/promises");
42121
43218
  import_path9 = require("path");
@@ -42321,7 +43418,7 @@ var init_acp3 = __esm({
42321
43418
  }
42322
43419
  };
42323
43420
  CURSOR_CREATE_PLAN = "cursor/create_plan";
42324
- STATUSES = /* @__PURE__ */ new Set(["pending", "in_progress", "completed", "cancelled"]);
43421
+ STATUSES2 = /* @__PURE__ */ new Set(["pending", "in_progress", "completed", "cancelled"]);
42325
43422
  READ_KINDS = /* @__PURE__ */ new Set(["read", "search", "think", "fetch"]);
42326
43423
  ALLOW_KINDS = ["allow_once", "allow", "allow_always"];
42327
43424
  REJECT_KINDS = ["reject_once", "reject", "deny", "reject_always"];
@@ -43188,7 +44285,7 @@ function awaitingUpdate(waiting) {
43188
44285
  return {
43189
44286
  sessionUpdate: "state_update",
43190
44287
  state: "requires_action",
43191
- _meta: { [AWAITING_TOOL_CALLS_META]: [...waiting] }
44288
+ _meta: { [AWAITING_TOOL_CALLS_META2]: [...waiting] }
43192
44289
  };
43193
44290
  }
43194
44291
  var RESUME_UNAVAILABLE;
@@ -43814,12 +44911,12 @@ var import_http10, import_crypto13, import_promises50, import_path10, import_pat
43814
44911
  var init_opencode = __esm({
43815
44912
  "../agent-core/dist/providers/opencode.js"() {
43816
44913
  "use strict";
43817
- init_chunk_YPYC4VBL();
44914
+ init_chunk_KHYYC5IN();
43818
44915
  init_chunk_UGRKZTAD();
43819
44916
  init_chunk_54ZRJOQP();
43820
44917
  init_chunk_J2KTV5FP();
43821
- init_chunk_J4T6L5LX();
43822
- init_chunk_6WN2R725();
44918
+ init_chunk_M6YHY2EZ();
44919
+ init_chunk_ITTV3UIM();
43823
44920
  init_chunk_YXWJW7I5();
43824
44921
  import_http10 = require("http");
43825
44922
  init_runtime_v2();
@@ -45091,7 +46188,7 @@ __export(codex_exports, {
45091
46188
  createCodexHolderDriver: () => createCodexHolderDriver
45092
46189
  });
45093
46190
  function sha2563(value2) {
45094
- return (0, import_node_crypto25.createHash)("sha256").update(value2).digest("hex");
46191
+ return (0, import_node_crypto26.createHash)("sha256").update(value2).digest("hex");
45095
46192
  }
45096
46193
  function createCodexLogin(broker) {
45097
46194
  const state = {};
@@ -45166,11 +46263,11 @@ function createCodexHolderDriver(options) {
45166
46263
  }
45167
46264
  );
45168
46265
  }
45169
- var import_node_crypto25;
46266
+ var import_node_crypto26;
45170
46267
  var init_codex2 = __esm({
45171
46268
  "src/holder/drivers/codex.ts"() {
45172
46269
  "use strict";
45173
- import_node_crypto25 = require("crypto");
46270
+ import_node_crypto26 = require("crypto");
45174
46271
  init_dist();
45175
46272
  init_codex();
45176
46273
  init_persistent();
@@ -45622,12 +46719,12 @@ var import_crypto15, import_promises51, FACTORY_API_VERSION, FACTORY_PROTOCOL_VE
45622
46719
  var init_droid = __esm({
45623
46720
  "../agent-core/dist/providers/droid.js"() {
45624
46721
  "use strict";
45625
- init_chunk_YPYC4VBL();
46722
+ init_chunk_KHYYC5IN();
45626
46723
  init_chunk_UGRKZTAD();
45627
46724
  init_chunk_54ZRJOQP();
45628
46725
  init_chunk_J2KTV5FP();
45629
- init_chunk_J4T6L5LX();
45630
- init_chunk_6WN2R725();
46726
+ init_chunk_M6YHY2EZ();
46727
+ init_chunk_ITTV3UIM();
45631
46728
  init_chunk_YXWJW7I5();
45632
46729
  init_runtime_v2();
45633
46730
  import_crypto15 = require("crypto");
@@ -46725,11 +47822,11 @@ var init_antigravity = __esm({
46725
47822
  "../agent-core/dist/providers/antigravity.js"() {
46726
47823
  "use strict";
46727
47824
  init_chunk_DALFHI4B();
46728
- init_chunk_YPYC4VBL();
47825
+ init_chunk_KHYYC5IN();
46729
47826
  init_chunk_UGRKZTAD();
46730
47827
  init_chunk_54ZRJOQP();
46731
- init_chunk_J4T6L5LX();
46732
- init_chunk_6WN2R725();
47828
+ init_chunk_M6YHY2EZ();
47829
+ init_chunk_ITTV3UIM();
46733
47830
  init_chunk_YXWJW7I5();
46734
47831
  import_promises52 = require("fs/promises");
46735
47832
  import_path12 = require("path");
@@ -47429,12 +48526,12 @@ var import_promises53, import_path15, import_crypto17, COMMAND_CODE_GRAMMAR_NAME
47429
48526
  var init_command_code = __esm({
47430
48527
  "../agent-core/dist/providers/command-code.js"() {
47431
48528
  "use strict";
47432
- init_chunk_YPYC4VBL();
48529
+ init_chunk_KHYYC5IN();
47433
48530
  init_chunk_UGRKZTAD();
47434
48531
  init_chunk_54ZRJOQP();
47435
48532
  init_chunk_J2KTV5FP();
47436
- init_chunk_J4T6L5LX();
47437
- init_chunk_6WN2R725();
48533
+ init_chunk_M6YHY2EZ();
48534
+ init_chunk_ITTV3UIM();
47438
48535
  init_chunk_YXWJW7I5();
47439
48536
  import_promises53 = require("fs/promises");
47440
48537
  import_path15 = require("path");
@@ -48055,7 +49152,7 @@ var require_XMLHttpRequest = __commonJS({
48055
49152
  "use strict";
48056
49153
  var fs = require("fs");
48057
49154
  var Url = require("url");
48058
- var spawn11 = require("child_process").spawn;
49155
+ var spawn10 = require("child_process").spawn;
48059
49156
  module2.exports = XMLHttpRequest3;
48060
49157
  XMLHttpRequest3.XMLHttpRequest = XMLHttpRequest3;
48061
49158
  function XMLHttpRequest3(opts) {
@@ -48351,7 +49448,7 @@ var require_XMLHttpRequest = __commonJS({
48351
49448
  var syncFile = ".node-xmlhttprequest-sync-" + process.pid;
48352
49449
  fs.writeFileSync(syncFile, "", "utf8");
48353
49450
  var execString = "var http = require('http'), https = require('https'), fs = require('fs');var doRequest = http" + (ssl ? "s" : "") + ".request;var options = " + JSON.stringify(options) + ";var responseText = '';var responseData = Buffer.alloc(0);var req = doRequest(options, function(response) {response.on('data', function(chunk) { var data = Buffer.from(chunk); responseText += data.toString('utf8'); responseData = Buffer.concat([responseData, data]);});response.on('end', function() {fs.writeFileSync('" + contentFile + "', JSON.stringify({err: null, data: {statusCode: response.statusCode, headers: response.headers, text: responseText, data: responseData.toString('base64')}}), 'utf8');fs.unlinkSync('" + syncFile + "');});response.on('error', function(error) {fs.writeFileSync('" + contentFile + "', 'NODE-XMLHTTPREQUEST-ERROR:' + JSON.stringify(error), 'utf8');fs.unlinkSync('" + syncFile + "');});}).on('error', function(error) {fs.writeFileSync('" + contentFile + "', 'NODE-XMLHTTPREQUEST-ERROR:' + JSON.stringify(error), 'utf8');fs.unlinkSync('" + syncFile + "');});" + (data ? "req.write('" + JSON.stringify(data).slice(1, -1).replace(/'/g, "\\'") + "');" : "") + "req.end();";
48354
- var syncProc = spawn11(process.argv[0], ["-e", execString]);
49451
+ var syncProc = spawn10(process.argv[0], ["-e", execString]);
48355
49452
  var statusText;
48356
49453
  while (fs.existsSync(syncFile)) {
48357
49454
  }
@@ -52832,7 +53929,7 @@ var require_websocket_server = __commonJS({
52832
53929
  // package.json
52833
53930
  var package_default = {
52834
53931
  name: "@alan-ai-hq/agent-manager",
52835
- version: "0.1.136",
53932
+ version: "0.1.138",
52836
53933
  private: true,
52837
53934
  type: "module",
52838
53935
  description: "Alan machine runtime (alan-agent): identity, link, reconciler, session holders, run log, uploader, local API",
@@ -52881,8 +53978,8 @@ var package_default = {
52881
53978
  };
52882
53979
 
52883
53980
  // src/cli/commands/compat.ts
52884
- var import_node_crypto30 = require("crypto");
52885
- var import_promises64 = require("fs/promises");
53981
+ var import_node_crypto31 = require("crypto");
53982
+ var import_promises66 = require("fs/promises");
52886
53983
  init_runtime_v2();
52887
53984
  init_zod();
52888
53985
 
@@ -54918,7 +56015,7 @@ async function push(context, request2) {
54918
56015
  var import_node_child_process = require("child_process");
54919
56016
 
54920
56017
  // ../agent-core/dist/process.js
54921
- init_chunk_J4T6L5LX();
56018
+ init_chunk_M6YHY2EZ();
54922
56019
  init_chunk_YXWJW7I5();
54923
56020
 
54924
56021
  // src/capabilities/git/run-git.ts
@@ -55926,6 +57023,7 @@ function markVersionInUse(bundlePath) {
55926
57023
  }
55927
57024
 
55928
57025
  // src/platform/instance-lock.ts
57026
+ var import_node_crypto7 = require("crypto");
55929
57027
  var import_node_fs5 = require("fs");
55930
57028
  var import_promises15 = require("fs/promises");
55931
57029
  var import_node_path10 = require("path");
@@ -55954,17 +57052,22 @@ function inodeOf(path4) {
55954
57052
  }
55955
57053
  }
55956
57054
  function tryCreate(path4, self) {
57055
+ const staged = `${path4}.${(0, import_node_crypto7.randomUUID)()}.candidate`;
55957
57056
  try {
55958
- const fd = (0, import_node_fs5.openSync)(path4, "wx", 384);
57057
+ const fd = (0, import_node_fs5.openSync)(staged, "wx", 384);
55959
57058
  try {
55960
57059
  (0, import_node_fs5.writeSync)(fd, JSON.stringify(self));
55961
57060
  } finally {
55962
57061
  (0, import_node_fs5.closeSync)(fd);
55963
57062
  }
55964
- return true;
57063
+ const inode = (0, import_node_fs5.statSync)(staged).ino;
57064
+ (0, import_node_fs5.linkSync)(staged, path4);
57065
+ return inode;
55965
57066
  } catch (error61) {
55966
- if (errnoCode(error61) === "EEXIST") return false;
57067
+ if (errnoCode(error61) === "EEXIST") return null;
55967
57068
  throw error61;
57069
+ } finally {
57070
+ (0, import_node_fs5.rmSync)(staged, { force: true });
55968
57071
  }
55969
57072
  }
55970
57073
  function removeStale(path4, inode) {
@@ -55976,21 +57079,26 @@ function removeStale(path4, inode) {
55976
57079
  }
55977
57080
  }
55978
57081
  async function attempt(path4, self, probe) {
55979
- if (tryCreate(path4, self)) return { kind: "acquired" };
57082
+ const created = tryCreate(path4, self);
57083
+ if (created !== null) return { kind: "acquired", inode: created };
55980
57084
  const inode = inodeOf(path4);
55981
57085
  const owner = readOwner(path4);
55982
57086
  if (owner !== null && await mayBeSameProcess(owner, probe)) return { kind: "held", owner };
55983
57087
  if (inode !== null) removeStale(path4, inode);
55984
- return tryCreate(path4, self) ? { kind: "acquired" } : attempt(path4, self, probe);
57088
+ return attempt(path4, self, probe);
55985
57089
  }
55986
57090
  async function acquireInstanceLock(path4, { clock, waitMs, signal, probe = systemProcessProbe }) {
55987
57091
  await (0, import_promises15.mkdir)((0, import_node_path10.dirname)(path4), { recursive: true, mode: 448 });
55988
57092
  const self = await readProcessIdentity(process.pid);
55989
57093
  if (self === null) throw new RuntimeFault("internal", "Cannot read this process's identity");
55990
57094
  const deadline = clock.monotonic() + waitMs;
57095
+ let heldInode = null;
55991
57096
  for (; ; ) {
55992
57097
  const result = await attempt(path4, self, probe);
55993
- if (result.kind === "acquired") break;
57098
+ if (result.kind === "acquired") {
57099
+ heldInode = result.inode;
57100
+ break;
57101
+ }
55994
57102
  if (clock.monotonic() >= deadline) {
55995
57103
  throw new RuntimeFault(
55996
57104
  "already_running",
@@ -56003,13 +57111,15 @@ async function acquireInstanceLock(path4, { clock, waitMs, signal, probe = syste
56003
57111
  owner: self,
56004
57112
  [Symbol.dispose]: () => {
56005
57113
  const owner = readOwner(path4);
56006
- if (owner?.pid === self.pid && owner.startedAt === self.startedAt) (0, import_node_fs5.unlinkSync)(path4);
57114
+ if (inodeOf(path4) === heldInode && owner?.pid === self.pid && owner.startedAt === self.startedAt) {
57115
+ (0, import_node_fs5.unlinkSync)(path4);
57116
+ }
56007
57117
  }
56008
57118
  };
56009
57119
  }
56010
57120
 
56011
57121
  // src/platform/ipc-endpoint.ts
56012
- var import_node_crypto7 = require("crypto");
57122
+ var import_node_crypto8 = require("crypto");
56013
57123
  var import_node_fs6 = require("fs");
56014
57124
  var import_node_os = require("os");
56015
57125
  var import_node_path11 = require("path");
@@ -56018,7 +57128,7 @@ function windowsPipeName(socketsDir, id) {
56018
57128
  return `\\\\.\\pipe\\alan-${socketsScope(socketsDir)}-${id}`;
56019
57129
  }
56020
57130
  function socketsScope(socketsDir) {
56021
- return (0, import_node_crypto7.createHash)("sha256").update(socketsDir.toLowerCase()).digest("hex").slice(0, 12);
57131
+ return (0, import_node_crypto8.createHash)("sha256").update(socketsDir.toLowerCase()).digest("hex").slice(0, 12);
56022
57132
  }
56023
57133
  function ipcEndpoint(socketsDir, id, platform3 = process.platform) {
56024
57134
  if (platform3 === "win32") return windowsPipeName(socketsDir, id);
@@ -56041,11 +57151,12 @@ var HOLDER_JITLESS_FLAG = "--jitless";
56041
57151
  var HOLDER_NODE_FLAGS = [
56042
57152
  "--max-semi-space-size=1",
56043
57153
  "--max-old-space-size=1024",
57154
+ "--use-system-ca",
56044
57155
  HOLDER_JITLESS_FLAG
56045
57156
  ];
56046
57157
 
56047
57158
  // src/platform/npm-release.ts
56048
- var import_node_crypto8 = require("crypto");
57159
+ var import_node_crypto9 = require("crypto");
56049
57160
  init_zod();
56050
57161
  var RELEASE_TARGETS = [
56051
57162
  "darwin-arm64",
@@ -56113,11 +57224,11 @@ function verifyNpmIntegrity(bytes, dist) {
56113
57224
  if (expected.length === 0) {
56114
57225
  return { ok: false, reason: "the registry's integrity has no sha512 digest" };
56115
57226
  }
56116
- const actual = (0, import_node_crypto8.createHash)("sha512").update(bytes).digest("base64");
57227
+ const actual = (0, import_node_crypto9.createHash)("sha512").update(bytes).digest("base64");
56117
57228
  return expected.includes(actual) ? { ok: true, algorithm: "sha512" } : { ok: false, reason: "the tarball does not match the registry's sha512 integrity" };
56118
57229
  }
56119
57230
  if (dist.shasum !== void 0) {
56120
- return (0, import_node_crypto8.createHash)("sha1").update(bytes).digest("hex") === dist.shasum ? { ok: true, algorithm: "sha1" } : { ok: false, reason: "the tarball does not match the registry's shasum" };
57231
+ return (0, import_node_crypto9.createHash)("sha1").update(bytes).digest("hex") === dist.shasum ? { ok: true, algorithm: "sha1" } : { ok: false, reason: "the tarball does not match the registry's shasum" };
56121
57232
  }
56122
57233
  return { ok: false, reason: "the registry lists no integrity for the tarball" };
56123
57234
  }
@@ -56191,7 +57302,7 @@ function readMemoryPressure() {
56191
57302
  }
56192
57303
 
56193
57304
  // src/platform/release.ts
56194
- var import_node_crypto9 = require("crypto");
57305
+ var import_node_crypto10 = require("crypto");
56195
57306
  var REJECTED_VERSION_RETRY_MS = 24 * 60 * 60 * 1e3;
56196
57307
  function parseVersion(version2) {
56197
57308
  if (!releaseVersionSchema.safeParse(version2).success) return null;
@@ -56234,7 +57345,7 @@ function compareVersions(a, b) {
56234
57345
  return comparePrerelease(left.prerelease, right.prerelease);
56235
57346
  }
56236
57347
  function rolloutBucket(machineId, version2) {
56237
- return (0, import_node_crypto9.createHash)("sha256").update(`${machineId}
57348
+ return (0, import_node_crypto10.createHash)("sha256").update(`${machineId}
56238
57349
  ${version2}`).digest().readUInt32BE(0) % 100;
56239
57350
  }
56240
57351
  function hostReleaseTarget(platform3 = process.platform, arch2 = process.arch) {
@@ -56264,7 +57375,7 @@ function planUpdate(input2) {
56264
57375
 
56265
57376
  // src/platform/release-apply.ts
56266
57377
  var import_node_child_process5 = require("child_process");
56267
- var import_node_crypto10 = require("crypto");
57378
+ var import_node_crypto11 = require("crypto");
56268
57379
  var import_promises17 = require("fs/promises");
56269
57380
  var import_node_path13 = require("path");
56270
57381
  var import_node_util4 = require("util");
@@ -56301,7 +57412,7 @@ async function stageNpmTarball({
56301
57412
  }) {
56302
57413
  const integrity = verifyNpmIntegrity(tarball, release2.dist);
56303
57414
  if (!integrity.ok) throw new RuntimeFault("invalid_file", integrity.reason);
56304
- const scratch = (0, import_node_path13.join)(tmpDir, (0, import_node_crypto10.randomUUID)());
57415
+ const scratch = (0, import_node_path13.join)(tmpDir, (0, import_node_crypto11.randomUUID)());
56305
57416
  await (0, import_promises17.mkdir)(scratch, { recursive: true, mode: 448 });
56306
57417
  try {
56307
57418
  const tarballPath = (0, import_node_path13.join)(scratch, "package.tgz");
@@ -57409,19 +58520,21 @@ function createServiceManager(host, profile) {
57409
58520
  // src/platform/sleep.ts
57410
58521
  var import_node_child_process7 = require("child_process");
57411
58522
  var WAKE_THRESHOLD_MS = 3e4;
57412
- function createWakeDetector(clock, thresholdMs = WAKE_THRESHOLD_MS) {
57413
- const last = { drift: clock.now() - clock.monotonic() };
58523
+ function createWakeDetector(clock, thresholdMs = WAKE_THRESHOLD_MS, platform3 = process.platform) {
58524
+ const last = { wall: clock.now(), drift: clock.now() - clock.monotonic() };
57414
58525
  return {
57415
58526
  check: () => {
57416
- const drift = clock.now() - clock.monotonic();
57417
- const slept = drift - last.drift;
58527
+ const wall = clock.now();
58528
+ const drift = wall - clock.monotonic();
58529
+ const slept = platform3 === "win32" ? wall - last.wall : drift - last.drift;
58530
+ last.wall = wall;
57418
58531
  last.drift = drift;
57419
58532
  return slept >= thresholdMs ? slept : 0;
57420
58533
  }
57421
58534
  };
57422
58535
  }
57423
- function wakeJob(clock, onWake, thresholdMs = WAKE_THRESHOLD_MS) {
57424
- const detector = createWakeDetector(clock, thresholdMs);
58536
+ function wakeJob(clock, onWake, thresholdMs = WAKE_THRESHOLD_MS, platform3 = process.platform) {
58537
+ const detector = createWakeDetector(clock, thresholdMs, platform3);
57425
58538
  return {
57426
58539
  name: "wake.detect",
57427
58540
  run: () => {
@@ -57511,7 +58624,7 @@ function systemAssertionSpawner(log) {
57511
58624
 
57512
58625
  // src/platform/spawn-detached.ts
57513
58626
  var import_node_child_process8 = require("child_process");
57514
- var import_node_crypto11 = require("crypto");
58627
+ var import_node_crypto12 = require("crypto");
57515
58628
  var import_node_fs8 = require("fs");
57516
58629
  var import_node_path21 = require("path");
57517
58630
  var WINDOWS_UNSAFE_ENV = "NODE_PENDING_PIPE_INSTANCES";
@@ -57548,7 +58661,7 @@ async function probeHolderIsolation(platform3, exec, env) {
57548
58661
  }
57549
58662
  const probe = await exec({
57550
58663
  command: SYSTEMD_RUN,
57551
- args: [...scopeArguments(`${SCOPE_PREFIX}-probe-${(0, import_node_crypto11.randomBytes)(4).toString("hex")}`), "true"],
58664
+ args: [...scopeArguments(`${SCOPE_PREFIX}-probe-${(0, import_node_crypto12.randomBytes)(4).toString("hex")}`), "true"],
57552
58665
  timeoutMs: SCOPE_PROBE_TIMEOUT_MS
57553
58666
  });
57554
58667
  if (probe.status === 0) return { kind: "systemd-scope" };
@@ -57560,7 +58673,7 @@ async function probeHolderIsolation(platform3, exec, env) {
57560
58673
  }
57561
58674
  function isolatedCommand(request2, isolation) {
57562
58675
  if (isolation.kind === "detached") return { command: request2.command, args: [...request2.args] };
57563
- const unit = `${SCOPE_PREFIX}-${(0, import_node_crypto11.randomBytes)(6).toString("hex")}`;
58676
+ const unit = `${SCOPE_PREFIX}-${(0, import_node_crypto12.randomBytes)(6).toString("hex")}`;
57564
58677
  return {
57565
58678
  command: SYSTEMD_RUN,
57566
58679
  args: [...scopeArguments(unit), request2.command, ...request2.args]
@@ -57838,7 +58951,7 @@ function createGit(options) {
57838
58951
 
57839
58952
  // src/capabilities/github-proxy/certificates.ts
57840
58953
  var import_node_child_process9 = require("child_process");
57841
- var import_node_crypto12 = require("crypto");
58954
+ var import_node_crypto13 = require("crypto");
57842
58955
  var import_promises24 = require("fs/promises");
57843
58956
  var import_node_path22 = require("path");
57844
58957
  var OPENSSL_TIMEOUT_MS = 1e4;
@@ -57903,7 +59016,7 @@ async function createGitHubProxyCertificates(stateDir) {
57903
59016
  work
57904
59017
  );
57905
59018
  await openssl(
57906
- ["x509", "-req", "-in", "leaf.csr", "-CA", "ca.pem", "-CAkey", "ca.key", "-sha256"].concat(["-set_serial", `0x${(0, import_node_crypto12.randomBytes)(16).toString("hex")}`, "-days", VALIDITY_DAYS]).concat(["-extfile", "leaf.cnf", "-extensions", "leaf", "-out", "leaf.pem"]),
59019
+ ["x509", "-req", "-in", "leaf.csr", "-CA", "ca.pem", "-CAkey", "ca.key", "-sha256"].concat(["-set_serial", `0x${(0, import_node_crypto13.randomBytes)(16).toString("hex")}`, "-days", VALIDITY_DAYS]).concat(["-extfile", "leaf.cnf", "-extensions", "leaf", "-out", "leaf.pem"]),
57907
59020
  work
57908
59021
  );
57909
59022
  const caPath = (0, import_node_path22.join)(stateDir, "github-ca.pem");
@@ -58129,7 +59242,7 @@ async function startGitHubProxy(options) {
58129
59242
  }
58130
59243
 
58131
59244
  // src/capabilities/mcp-config/mcp-config.ts
58132
- var import_node_crypto13 = require("crypto");
59245
+ var import_node_crypto14 = require("crypto");
58133
59246
  var import_promises27 = require("fs/promises");
58134
59247
  var import_node_path24 = require("path");
58135
59248
 
@@ -59113,7 +60226,7 @@ async function readConfig(cli, home) {
59113
60226
  }
59114
60227
  }
59115
60228
  async function writeConfig(path4, text2) {
59116
- const temporary = `${path4}.alan-${(0, import_node_crypto13.randomUUID)()}.tmp`;
60229
+ const temporary = `${path4}.alan-${(0, import_node_crypto14.randomUUID)()}.tmp`;
59117
60230
  try {
59118
60231
  await (0, import_promises27.writeFile)(temporary, text2, { encoding: "utf8", mode: 384, flag: "wx" });
59119
60232
  await (0, import_promises27.rename)(temporary, path4);
@@ -60221,7 +61334,7 @@ function reconcileTranscriptIdentity(entry, transcriptPath, identity, size) {
60221
61334
  }
60222
61335
 
60223
61336
  // src/capabilities/native-ingest/transcript-window.ts
60224
- var import_node_crypto14 = require("crypto");
61337
+ var import_node_crypto15 = require("crypto");
60225
61338
  var import_promises32 = require("fs/promises");
60226
61339
  init_acp2();
60227
61340
  init_claude();
@@ -60371,7 +61484,7 @@ function lastMatchingTurnIndex(turns, target) {
60371
61484
  function signalDigest(target) {
60372
61485
  const fingerprint = target.assistantFingerprint;
60373
61486
  const basis = target.providerTurnId ?? (fingerprint ? `${fingerprint.length}\0${fingerprint.head}\0${fingerprint.tail}` : null);
60374
- return basis ? (0, import_node_crypto14.createHash)("sha256").update(basis).digest("hex") : null;
61487
+ return basis ? (0, import_node_crypto15.createHash)("sha256").update(basis).digest("hex") : null;
60375
61488
  }
60376
61489
  function lastForegroundStop(updates) {
60377
61490
  for (let index = updates.length - 1; index >= 0; index -= 1) {
@@ -61113,7 +62226,9 @@ function providerCommandFor(backendKind) {
61113
62226
  return BY_BACKEND.get(backendKind)?.command;
61114
62227
  }
61115
62228
  function envValue(env, name) {
61116
- const key = Object.keys(env).find((candidate) => candidate.toUpperCase() === name);
62229
+ const key = Object.keys(env).findLast(
62230
+ (candidate) => candidate.toUpperCase() === name.toUpperCase()
62231
+ );
61117
62232
  return key === void 0 ? "" : env[key] ?? "";
61118
62233
  }
61119
62234
  function pathDelimiter(platform3) {
@@ -61129,12 +62244,18 @@ async function isRunnable(path4, platform3) {
61129
62244
  }
61130
62245
  }
61131
62246
  function windowsExtensions(command, env) {
61132
- const extensions = (envValue(env, "PATHEXT") || ".COM;.EXE;.BAT;.CMD").split(";").filter((extension) => extension.startsWith("."));
62247
+ const extensions = (envValue(env, "PATHEXT") || ".COM;.EXE;.BAT;.CMD").split(";").map((extension) => extension.trim()).filter((extension) => [".COM", ".EXE", ".BAT", ".CMD"].includes(extension.toUpperCase()));
61133
62248
  const named = command.toLowerCase();
61134
- return extensions.some((extension) => named.endsWith(extension.toLowerCase())) ? [""] : extensions;
62249
+ return [".com", ".exe", ...extensions.map((extension) => extension.toLowerCase())].some(
62250
+ (extension) => named.endsWith(extension)
62251
+ ) ? [""] : extensions;
61135
62252
  }
61136
62253
  async function resolveCommandOnPath(command, env, platform3) {
61137
- const directories = envValue(env, "PATH").split(pathDelimiter(platform3)).filter((directory) => directory.length > 0);
62254
+ const directories = envValue(env, "PATH").split(pathDelimiter(platform3)).map(
62255
+ (directory) => platform3 === "win32" ? directory.trim().replace(/^"(.*)"$/, "$1") : directory
62256
+ ).filter(
62257
+ (directory) => platform3 === "win32" ? import_node_path32.win32.isAbsolute(directory) : directory.length > 0
62258
+ );
61138
62259
  const extensions = platform3 === "win32" ? windowsExtensions(command, env) : [""];
61139
62260
  for (const directory of directories) {
61140
62261
  for (const extension of extensions) {
@@ -61181,8 +62302,21 @@ function alanCodeProviderModels() {
61181
62302
  var import_node_child_process10 = require("child_process");
61182
62303
  var DEFAULT_TIMEOUT_MS2 = 5e3;
61183
62304
  var DEFAULT_MAX_BYTES = 1024 * 1024;
62305
+ function withWindowsHelper(env) {
62306
+ const helper = windowsHelperPath();
62307
+ return helper === null ? env : { ...env, ALAN_WINHELPER_PATH: helper };
62308
+ }
61184
62309
  function directLaunch(command, args, options) {
61185
62310
  try {
62311
+ if ((options.platform ?? process.platform) === "win32") {
62312
+ const plan2 = planSpawn({
62313
+ command,
62314
+ args,
62315
+ env: canonicalWindowsEnvironment(options.env),
62316
+ platform: "win32"
62317
+ });
62318
+ return { file: plan2.file, args: plan2.args, windowsVerbatimArguments: false };
62319
+ }
61186
62320
  return planDirectLaunch({
61187
62321
  command,
61188
62322
  args,
@@ -61194,42 +62328,88 @@ function directLaunch(command, args, options) {
61194
62328
  }
61195
62329
  }
61196
62330
  function captureProbe(command, args, options) {
62331
+ const platform3 = options.platform ?? process.platform;
61197
62332
  const launch = directLaunch(command, args, options);
61198
62333
  if (launch === void 0) return Promise.resolve({ stdout: "", stderr: "", exitCode: void 0 });
62334
+ const env = platform3 === "win32" ? withWindowsHelper(canonicalWindowsEnvironment(options.env)) : options.env;
61199
62335
  return new Promise((resolve12) => {
61200
62336
  const limit = options.maxBufferBytes ?? DEFAULT_MAX_BYTES;
61201
62337
  const stdout = [];
61202
62338
  const stderr = [];
61203
62339
  let bytes = 0;
61204
62340
  let overflowed = false;
61205
- const child = (0, import_node_child_process10.spawn)(launch.file, [...launch.args], {
61206
- env: { ...options.env },
62341
+ const windowsChild = platform3 === "win32" ? spawnInWindowsJob(planSpawn({ command, args, env, platform: platform3 }), {
62342
+ cwd: process.cwd(),
62343
+ env
62344
+ }) : void 0;
62345
+ const child = windowsChild ?? (0, import_node_child_process10.spawn)(launch.file, [...launch.args], {
62346
+ env: { ...env },
61207
62347
  stdio: ["ignore", "pipe", "pipe"],
61208
- timeout: options.timeoutMs ?? DEFAULT_TIMEOUT_MS2,
62348
+ detached: true,
61209
62349
  windowsHide: true,
61210
62350
  windowsVerbatimArguments: launch.windowsVerbatimArguments
61211
62351
  });
62352
+ child.stdin?.end();
62353
+ const terminate = () => {
62354
+ if (platform3 !== "win32" && child.pid !== void 0) {
62355
+ try {
62356
+ process.kill(-child.pid, "SIGKILL");
62357
+ return;
62358
+ } catch {
62359
+ }
62360
+ }
62361
+ child.kill("SIGKILL");
62362
+ };
62363
+ let settled2 = false;
62364
+ const deadlineController = new AbortController();
62365
+ const finish = (exitCode) => {
62366
+ if (settled2) return;
62367
+ settled2 = true;
62368
+ deadlineController.abort();
62369
+ options.signal?.removeEventListener("abort", abort);
62370
+ resolve12({
62371
+ stdout: Buffer.concat(stdout).toString("utf8"),
62372
+ stderr: Buffer.concat(stderr).toString("utf8"),
62373
+ exitCode
62374
+ });
62375
+ };
62376
+ void systemClock.sleep(options.timeoutMs ?? DEFAULT_TIMEOUT_MS2, deadlineController.signal).then(
62377
+ () => {
62378
+ terminate();
62379
+ child.stdout.destroy();
62380
+ child.stderr.destroy();
62381
+ finish(void 0);
62382
+ },
62383
+ () => void 0
62384
+ );
62385
+ const abort = () => {
62386
+ terminate();
62387
+ child.stdout.destroy();
62388
+ child.stderr.destroy();
62389
+ finish(void 0);
62390
+ };
62391
+ options.signal?.addEventListener("abort", abort, { once: true });
62392
+ if (options.signal?.aborted) abort();
61212
62393
  const collect = (into) => (chunk) => {
61213
62394
  bytes += chunk.length;
61214
62395
  if (bytes > limit) {
61215
62396
  overflowed = true;
61216
- child.kill("SIGKILL");
62397
+ terminate();
62398
+ finish(void 0);
61217
62399
  return;
61218
62400
  }
61219
62401
  into.push(chunk);
61220
62402
  };
61221
62403
  child.stdout.on("data", collect(stdout));
61222
62404
  child.stderr.on("data", collect(stderr));
61223
- const finish = (exitCode) => resolve12({
61224
- stdout: Buffer.concat(stdout).toString("utf8"),
61225
- stderr: Buffer.concat(stderr).toString("utf8"),
61226
- exitCode
61227
- });
61228
62405
  child.once("error", () => finish(void 0));
61229
62406
  child.once(
61230
62407
  "close",
61231
62408
  (code, signal) => finish(overflowed || signal !== null || code === null ? void 0 : code)
61232
62409
  );
62410
+ if (windowsChild !== void 0) {
62411
+ void waitForWindowsJob(windowsChild, command).catch(() => finish(void 0));
62412
+ }
61233
62413
  });
61234
62414
  }
61235
62415
 
@@ -61676,7 +62856,7 @@ var import_node_path37 = require("path");
61676
62856
 
61677
62857
  // ../shared/dist/node/shell-environment.js
61678
62858
  var import_node_child_process12 = require("child_process");
61679
- var import_node_crypto15 = require("crypto");
62859
+ var import_node_crypto16 = require("crypto");
61680
62860
  var import_node_fs15 = require("fs");
61681
62861
  var import_node_os5 = require("os");
61682
62862
  var import_node_path36 = require("path");
@@ -61820,6 +63000,15 @@ function installerDirectories(home, platform3) {
61820
63000
  const system = platform3 === "darwin" ? ["/opt/homebrew/bin", "/usr/local/bin"] : ["/usr/local/bin"];
61821
63001
  return [...user, ...system];
61822
63002
  }
63003
+ function windowsInstallerDirectories(env) {
63004
+ const home = envValue(env, "USERPROFILE") || envValue(env, "HOME");
63005
+ const hasHome = import_node_path37.win32.isAbsolute(home);
63006
+ const appData = envValue(env, "APPDATA") || (hasHome ? import_node_path37.win32.join(home, "AppData", "Roaming") : "");
63007
+ return [
63008
+ ...hasHome ? [import_node_path37.win32.join(home, ".local", "bin")] : [],
63009
+ ...import_node_path37.win32.isAbsolute(appData) ? [import_node_path37.win32.join(appData, "npm")] : []
63010
+ ];
63011
+ }
61823
63012
  function printPathCommand() {
61824
63013
  return `printf '${MARKER}%s${MARKER}' "$PATH"`;
61825
63014
  }
@@ -61872,7 +63061,14 @@ async function rememberLastKnownGood(file2, path4) {
61872
63061
  }
61873
63062
  async function resolveCliEnvironmentDetailed(options) {
61874
63063
  const { env, platform: platform3 } = options;
61875
- if (platform3 === "win32") return { env: { ...env }, source: "none" };
63064
+ if (platform3 === "win32") {
63065
+ const path4 = appendPathDirectories(
63066
+ envValue(env, "PATH"),
63067
+ windowsInstallerDirectories(env),
63068
+ ";"
63069
+ );
63070
+ return { env: canonicalWindowsEnvironment({ ...env, PATH: path4 }), source: "none" };
63071
+ }
61876
63072
  const loginPath = await readLoginShellPath(env, options.capture ?? captureProbe);
61877
63073
  if (loginPath !== null) await rememberLastKnownGood(options.lastKnownGoodFile, loginPath);
61878
63074
  const lastKnownGood = loginPath === null ? await readLastKnownGood(options.lastKnownGoodFile) : null;
@@ -61919,8 +63115,7 @@ async function openCliEnvironment(options) {
61919
63115
  }
61920
63116
 
61921
63117
  // src/capabilities/providers/managed.ts
61922
- var import_node_child_process13 = require("child_process");
61923
- var import_node_crypto16 = require("crypto");
63118
+ var import_node_crypto17 = require("crypto");
61924
63119
  var import_promises36 = require("fs/promises");
61925
63120
  var import_node_path38 = require("path");
61926
63121
  init_zod();
@@ -61949,9 +63144,10 @@ function withManagedProviderPaths(manager, env, nodeDirectory, platform3 = proce
61949
63144
  const path4 = [
61950
63145
  ...manager.selections().map((item) => item.binDir),
61951
63146
  ...nodeDirectory === void 0 ? [] : [nodeDirectory],
61952
- env.PATH ?? ""
63147
+ envValue(env, "PATH")
61953
63148
  ].filter(Boolean);
61954
- return { ...env, PATH: path4.join(pathDelimiter(platform3)) };
63149
+ const merged = { ...env, PATH: path4.join(pathDelimiter(platform3)) };
63150
+ return platform3 === "win32" ? canonicalWindowsEnvironment(merged) : merged;
61955
63151
  }
61956
63152
  function packageFor(backendKind) {
61957
63153
  const provider4 = PACKAGES[backendKind];
@@ -62048,7 +63244,7 @@ function createManagedProviderClis(options) {
62048
63244
  };
62049
63245
  const persist = async () => {
62050
63246
  await (0, import_promises36.mkdir)(options.root, { recursive: true, mode: 448 });
62051
- const staged = `${file2}.${(0, import_node_crypto16.randomUUID)()}`;
63247
+ const staged = `${file2}.${(0, import_node_crypto17.randomUUID)()}`;
62052
63248
  try {
62053
63249
  await (0, import_promises36.writeFile)(staged, JSON.stringify(state), { mode: 384 });
62054
63250
  await (0, import_promises36.rename)(staged, file2);
@@ -62083,7 +63279,7 @@ function createManagedProviderClis(options) {
62083
63279
  try {
62084
63280
  parsed = selectedSchema.parse(JSON.parse(raw));
62085
63281
  } catch {
62086
- await (0, import_promises36.rename)(file2, `${file2}.invalid.${(0, import_node_crypto16.randomUUID)()}`).catch(() => void 0);
63282
+ await (0, import_promises36.rename)(file2, `${file2}.invalid.${(0, import_node_crypto17.randomUUID)()}`).catch(() => void 0);
62087
63283
  return;
62088
63284
  }
62089
63285
  for (const [backendKind, version2] of Object.entries(parsed)) {
@@ -62141,7 +63337,7 @@ function createManagedProviderClis(options) {
62141
63337
  const existing = selection(options.root, backendKind, exact);
62142
63338
  if (!await runnable(existing.executable) || !await options.probe(existing.executable, backendKind)) {
62143
63339
  await (0, import_promises36.mkdir)((0, import_node_path38.dirname)(target), { recursive: true, mode: 448 });
62144
- const staged = `${target}.${(0, import_node_crypto16.randomUUID)()}`;
63340
+ const staged = `${target}.${(0, import_node_crypto17.randomUUID)()}`;
62145
63341
  try {
62146
63342
  await options.installPackage(provider4.name, exact, staged, provider4.command, signal);
62147
63343
  const built = (0, import_node_path38.join)(staged, "node_modules", ".bin", provider4.command);
@@ -62171,9 +63367,18 @@ function createManagedProviderClis(options) {
62171
63367
  })
62172
63368
  };
62173
63369
  }
63370
+ function withInstallerPath(options) {
63371
+ const platform3 = options.platform ?? process.platform;
63372
+ const path4 = [
63373
+ platform3 === "win32" ? import_node_path38.win32.dirname(options.command) : (0, import_node_path38.dirname)(options.command),
63374
+ envValue(options.env, "PATH")
63375
+ ].filter(Boolean).join(pathDelimiter(platform3));
63376
+ const env = { ...options.env, PATH: path4 };
63377
+ return platform3 === "win32" ? canonicalWindowsEnvironment(env) : env;
63378
+ }
62174
63379
  function createNpmPackageInstaller(options) {
62175
- return (packageName, version2, destination, _command, signal) => new Promise((resolve12, reject) => {
62176
- const child = (0, import_node_child_process13.spawn)(
63380
+ return async (packageName, version2, destination, _command, signal) => {
63381
+ const result = await captureProbe(
62177
63382
  options.command,
62178
63383
  [
62179
63384
  ...options.argsBeforeNpm ?? [],
@@ -62185,53 +63390,35 @@ function createNpmPackageInstaller(options) {
62185
63390
  `${packageName}@${version2}`
62186
63391
  ],
62187
63392
  {
62188
- env: { ...options.env, PATH: `${(0, import_node_path38.dirname)(options.command)}:${options.env.PATH ?? ""}` },
63393
+ env: withInstallerPath(options),
62189
63394
  signal,
62190
- stdio: ["ignore", "pipe", "pipe"]
63395
+ timeoutMs: 10 * 6e4,
63396
+ maxBufferBytes: 1024 * 1024
62191
63397
  }
62192
63398
  );
62193
- let output2 = "";
62194
- for (const stream of [child.stdout, child.stderr]) {
62195
- stream?.on("data", (chunk) => {
62196
- output2 = `${output2}${chunk.toString()}`.slice(-8e3);
62197
- });
63399
+ if (result.exitCode !== 0) {
63400
+ const output2 = `${result.stdout}
63401
+ ${result.stderr}`.trim().slice(-8e3);
63402
+ throw new Error(
63403
+ `npm install failed (${result.exitCode ?? "timeout, cancellation or launch"}): ${output2}`
63404
+ );
62198
63405
  }
62199
- child.on("error", reject);
62200
- child.on("close", (code) => {
62201
- if (code === 0) resolve12();
62202
- else reject(new Error(`npm install failed (${code ?? "signal"}): ${output2.trim()}`));
62203
- });
62204
- });
63406
+ };
62205
63407
  }
62206
63408
  function createNpmVersionResolver(options) {
62207
- return (packageName, signal) => new Promise((resolve12, reject) => {
62208
- const child = (0, import_node_child_process13.spawn)(
63409
+ return async (packageName, signal) => {
63410
+ const result = await captureProbe(
62209
63411
  options.command,
62210
63412
  [...options.argsBeforeNpm ?? [], "view", packageName, "version", "--json"],
62211
- {
62212
- env: { ...options.env },
62213
- signal: AbortSignal.any([
62214
- signal ?? new AbortController().signal,
62215
- AbortSignal.timeout(3e4)
62216
- ]),
62217
- stdio: ["ignore", "pipe", "pipe"]
62218
- }
63413
+ { env: withInstallerPath(options), signal, timeoutMs: 3e4, maxBufferBytes: 1e5 }
62219
63414
  );
62220
- let output2 = "";
62221
- child.stdout.on("data", (chunk) => {
62222
- output2 = `${output2}${chunk.toString()}`;
62223
- if (output2.length > 1e5) child.kill();
62224
- });
62225
- child.on("error", reject);
62226
- child.on("close", (code) => {
62227
- if (code !== 0) return reject(new Error(`Cannot look up ${packageName} version`));
62228
- try {
62229
- resolve12(parseNpmVersion(output2, packageName));
62230
- } catch (error61) {
62231
- reject(error61);
62232
- }
62233
- });
62234
- });
63415
+ if (result.exitCode !== 0) {
63416
+ throw new Error(
63417
+ `Cannot look up ${packageName} version: ${result.stderr.trim().slice(-2e3)}`
63418
+ );
63419
+ }
63420
+ return parseNpmVersion(result.stdout, packageName);
63421
+ };
62235
63422
  }
62236
63423
  function parseNpmVersion(output2, packageName) {
62237
63424
  const versions = external_exports.union([external_exports.string(), external_exports.array(external_exports.string())]).parse(JSON.parse(output2));
@@ -62268,7 +63455,7 @@ var import_node_path43 = __toESM(require("path"));
62268
63455
 
62269
63456
  // ../shared/dist/node/skill-package.js
62270
63457
  var import_node_buffer = require("buffer");
62271
- var import_node_crypto17 = require("crypto");
63458
+ var import_node_crypto18 = require("crypto");
62272
63459
  var import_promises37 = require("fs/promises");
62273
63460
  var import_node_path39 = require("path");
62274
63461
  var import_yaml = __toESM(require_dist(), 1);
@@ -62668,7 +63855,7 @@ function comparePackageFiles(left, right) {
62668
63855
  return import_node_buffer.Buffer.compare(import_node_buffer.Buffer.from(left.manifest.path, "utf8"), import_node_buffer.Buffer.from(right.manifest.path, "utf8"));
62669
63856
  }
62670
63857
  function hashPackageTree(files) {
62671
- const hash2 = (0, import_node_crypto17.createHash)("sha256");
63858
+ const hash2 = (0, import_node_crypto18.createHash)("sha256");
62672
63859
  hash2.update(TREE_HASH_PREFIX);
62673
63860
  for (const file2 of files) {
62674
63861
  const path4 = import_node_buffer.Buffer.from(file2.path, "utf8");
@@ -62681,7 +63868,7 @@ function hashPackageTree(files) {
62681
63868
  return `sha256:${hash2.digest("hex")}`;
62682
63869
  }
62683
63870
  function sha256(bytes) {
62684
- return `sha256:${(0, import_node_crypto17.createHash)("sha256").update(bytes).digest("hex")}`;
63871
+ return `sha256:${(0, import_node_crypto18.createHash)("sha256").update(bytes).digest("hex")}`;
62685
63872
  }
62686
63873
  function uint322(value2) {
62687
63874
  const buffer = import_node_buffer.Buffer.allocUnsafe(4);
@@ -62695,13 +63882,13 @@ function uint642(value2) {
62695
63882
  }
62696
63883
 
62697
63884
  // src/capabilities/skills/local-sources.ts
62698
- var import_node_crypto19 = require("crypto");
63885
+ var import_node_crypto20 = require("crypto");
62699
63886
  var import_promises39 = require("fs/promises");
62700
63887
  var import_node_path41 = __toESM(require("path"));
62701
63888
  init_type_guards();
62702
63889
 
62703
63890
  // src/capabilities/skills/local-scan.ts
62704
- var import_node_crypto18 = require("crypto");
63891
+ var import_node_crypto19 = require("crypto");
62705
63892
  var import_promises38 = require("fs/promises");
62706
63893
  var import_node_path40 = __toESM(require("path"));
62707
63894
  var MAX_CANDIDATES = 2e3;
@@ -62710,7 +63897,7 @@ function createLocalSkillScanCache() {
62710
63897
  return { inspections: /* @__PURE__ */ new Map(), lastCompleteRevision: null };
62711
63898
  }
62712
63899
  async function scanSkillRoots(input2, cache2) {
62713
- const attemptId = (0, import_node_crypto18.randomUUID)();
63900
+ const attemptId = (0, import_node_crypto19.randomUUID)();
62714
63901
  const ignoredPaths = input2.ignoredPaths ?? [];
62715
63902
  const resolvedRoots = resolveScanRoots(input2.roots, input2.enabledProviderKinds ?? []);
62716
63903
  const pass = {
@@ -62775,7 +63962,7 @@ function failedLocalSkillScan(cache2, code, message2) {
62775
63962
  return {
62776
63963
  outcome: {
62777
63964
  status: "failed",
62778
- attemptId: (0, import_node_crypto18.randomUUID)(),
63965
+ attemptId: (0, import_node_crypto19.randomUUID)(),
62779
63966
  retainedInventoryRevision: cache2.lastCompleteRevision,
62780
63967
  diagnostics: [{ code, message: message2.slice(0, 2048) }]
62781
63968
  },
@@ -62939,11 +64126,11 @@ function candidateOrigin(root) {
62939
64126
  }
62940
64127
  function createLocalKey(root, skillName) {
62941
64128
  const rootIdentity = root.kind === "configured" ? `configured:${root.declarationId}` : root.kind === "repository" ? `repository:${root.repositoryId}` : "drafts";
62942
- const digest = (0, import_node_crypto18.createHash)("sha256").update("alan-local-skill-v1\0").update(rootIdentity).update("\0").update(skillName.normalize("NFC")).digest("hex");
64129
+ const digest = (0, import_node_crypto19.createHash)("sha256").update("alan-local-skill-v1\0").update(rootIdentity).update("\0").update(skillName.normalize("NFC")).digest("hex");
62943
64130
  return `local:${digest}`;
62944
64131
  }
62945
64132
  function hashInventory(candidates2) {
62946
- const hash2 = (0, import_node_crypto18.createHash)("sha256").update("alan-skill-inventory-v1\0");
64133
+ const hash2 = (0, import_node_crypto19.createHash)("sha256").update("alan-skill-inventory-v1\0");
62947
64134
  for (const candidate of candidates2) {
62948
64135
  hash2.update(candidate.localKey).update("\0");
62949
64136
  hash2.update(candidate.contentHash).update("\0");
@@ -62963,7 +64150,7 @@ function deduplicateByContent(candidates2) {
62963
64150
  return candidates2.filter((located) => winners.has(located));
62964
64151
  }
62965
64152
  async function fingerprintPackage(root) {
62966
- const hash2 = (0, import_node_crypto18.createHash)("sha256").update("alan-skill-stat-fingerprint-v1\0");
64153
+ const hash2 = (0, import_node_crypto19.createHash)("sha256").update("alan-skill-stat-fingerprint-v1\0");
62967
64154
  const visit2 = async (directory, relativeDirectory) => {
62968
64155
  const entries = await (0, import_promises38.readdir)(directory, { withFileTypes: true });
62969
64156
  entries.sort((left, right) => Buffer.compare(Buffer.from(left.name), Buffer.from(right.name)));
@@ -63166,7 +64353,7 @@ function staleCodexDeclaration(relativeDirectory, label, providerKinds) {
63166
64353
  return ownedByCursor || label === "Legacy Cursor-compatible skills";
63167
64354
  }
63168
64355
  function stableSourceDeclarationId(sourcePath) {
63169
- const digest = (0, import_node_crypto19.createHash)("sha256").update("alan-skill-source-v1\0").update(sourcePath.normalize("NFC")).digest("hex").slice(0, 24);
64356
+ const digest = (0, import_node_crypto20.createHash)("sha256").update("alan-skill-source-v1\0").update(sourcePath.normalize("NFC")).digest("hex").slice(0, 24);
63170
64357
  return `source-${digest}`;
63171
64358
  }
63172
64359
  function requiredSourceId(value2, field3) {
@@ -63213,10 +64400,10 @@ var import_promises40 = require("fs/promises");
63213
64400
  var import_node_path42 = require("path");
63214
64401
 
63215
64402
  // ../shared/dist/node/alan-skill-identity.js
63216
- var import_node_crypto20 = require("crypto");
64403
+ var import_node_crypto21 = require("crypto");
63217
64404
  var ALAN_SKILL_NAMESPACE = "ec71d99b-d207-4ca2-a9eb-3a7bed4a73fd";
63218
64405
  function uuidV5(name, namespace) {
63219
- const bytes = (0, import_node_crypto20.createHash)("sha1").update(Buffer.from(namespace.replaceAll("-", ""), "hex")).update(name, "utf8").digest().subarray(0, 16);
64406
+ const bytes = (0, import_node_crypto21.createHash)("sha1").update(Buffer.from(namespace.replaceAll("-", ""), "hex")).update(name, "utf8").digest().subarray(0, 16);
63220
64407
  bytes[6] = bytes[6] & 15 | 80;
63221
64408
  bytes[8] = bytes[8] & 63 | 128;
63222
64409
  const hex3 = bytes.toString("hex");
@@ -63341,6 +64528,38 @@ async function resolveSkillInvocations(layout, invocations) {
63341
64528
  }
63342
64529
  return missing.length === 0 ? { kind: "resolved", skills: resolved } : { kind: "missing", names: missing };
63343
64530
  }
64531
+ async function availableSkillIndex(layout) {
64532
+ const found = /* @__PURE__ */ new Map();
64533
+ const candidates2 = [];
64534
+ for (const skill of await readInstalledSkills(layout)) {
64535
+ candidates2.push({
64536
+ directory: packageDirectory(layout, skill.versionId),
64537
+ contentHash: skill.contentHash
64538
+ });
64539
+ }
64540
+ if (layout.nativeDir !== null) {
64541
+ const entries = await (0, import_promises40.readdir)(layout.nativeDir, { withFileTypes: true }).catch(() => []);
64542
+ for (const entry of entries) {
64543
+ if (entry.isDirectory() || entry.isSymbolicLink())
64544
+ candidates2.push({ directory: (0, import_node_path42.join)(layout.nativeDir, entry.name) });
64545
+ }
64546
+ }
64547
+ for (const candidate of candidates2.slice(0, 2e3)) {
64548
+ const skill = await inspectIndexedSkill(candidate.directory, candidate.contentHash);
64549
+ if (skill !== null && !found.has(skill.name)) found.set(skill.name, skill);
64550
+ }
64551
+ return [...found.values()].sort((a, b) => a.name.localeCompare(b.name));
64552
+ }
64553
+ async function inspectIndexedSkill(directory, contentHash) {
64554
+ try {
64555
+ const inspected = await inspectSkillPackage(directory, { expectedName: null });
64556
+ if (contentHash && inspected.contentHash !== contentHash) return null;
64557
+ const { name, description } = inspected.metadata;
64558
+ return { name, description, packageDirectory: directory };
64559
+ } catch {
64560
+ return null;
64561
+ }
64562
+ }
63344
64563
 
63345
64564
  // src/capabilities/skills/local-preview.ts
63346
64565
  var MAX_INLINE_IMAGE_BYTES = 2 * 1024 * 1024;
@@ -63451,7 +64670,7 @@ var import_promises43 = require("fs/promises");
63451
64670
 
63452
64671
  // ../shared/dist/node/skill-bundle.js
63453
64672
  var import_node_buffer2 = require("buffer");
63454
- var import_node_crypto21 = require("crypto");
64673
+ var import_node_crypto22 = require("crypto");
63455
64674
  var import_promises42 = require("fs/promises");
63456
64675
  var import_node_path44 = require("path");
63457
64676
  var import_node_stream = require("stream");
@@ -63590,7 +64809,7 @@ function requireSafeArchivePath(value2) {
63590
64809
  return normalized2;
63591
64810
  }
63592
64811
  function sha2562(bytes) {
63593
- return `sha256:${(0, import_node_crypto21.createHash)("sha256").update(bytes).digest("hex")}`;
64812
+ return `sha256:${(0, import_node_crypto22.createHash)("sha256").update(bytes).digest("hex")}`;
63594
64813
  }
63595
64814
 
63596
64815
  // src/capabilities/skills/local-upload.ts
@@ -63634,14 +64853,14 @@ async function publishLocalSkill(options) {
63634
64853
  }
63635
64854
 
63636
64855
  // src/capabilities/skills/sync.ts
63637
- var import_node_crypto22 = require("crypto");
64856
+ var import_node_crypto23 = require("crypto");
63638
64857
  var import_promises44 = require("fs/promises");
63639
64858
  var import_node_path45 = require("path");
63640
64859
  var SKILL_PREPARE_WAIT_MS = 15e3;
63641
64860
  async function install(layout, source, skill, download, signal) {
63642
64861
  const bytes = await source.download(download.url, signal);
63643
64862
  await (0, import_promises44.mkdir)(layout.tmpDir, { recursive: true, mode: 448 });
63644
- const staging = (0, import_node_path45.join)(layout.tmpDir, (0, import_node_crypto22.randomUUID)());
64863
+ const staging = (0, import_node_path45.join)(layout.tmpDir, (0, import_node_crypto23.randomUUID)());
63645
64864
  await extractSkillBundle(Buffer.from(bytes), staging, {
63646
64865
  expectedArchiveHash: download.archiveHash,
63647
64866
  expectedContentHash: skill.contentHash
@@ -64054,7 +65273,7 @@ async function openApprovedPaths(options) {
64054
65273
  }
64055
65274
 
64056
65275
  // src/capabilities/workspace/locks.ts
64057
- var import_node_crypto23 = require("crypto");
65276
+ var import_node_crypto24 = require("crypto");
64058
65277
  var import_promises46 = require("fs/promises");
64059
65278
  var import_node_path47 = require("path");
64060
65279
  init_zod();
@@ -64071,7 +65290,7 @@ var ownerSchema = external_exports.object({
64071
65290
  since: external_exports.number().int().nonnegative()
64072
65291
  });
64073
65292
  function repositoryLockKey(commonDir, platform3) {
64074
- return (0, import_node_crypto23.createHash)("sha256").update(comparablePath(commonDir, platform3)).digest("hex").slice(0, 32);
65293
+ return (0, import_node_crypto24.createHash)("sha256").update(comparablePath(commonDir, platform3)).digest("hex").slice(0, 32);
64075
65294
  }
64076
65295
  async function readOwner2(path4) {
64077
65296
  let text2;
@@ -64184,7 +65403,7 @@ function openRepositoryLocks(options) {
64184
65403
  },
64185
65404
  tryShared: async (commonDir, runId) => {
64186
65405
  const { key, dir } = await folder(commonDir);
64187
- const file2 = `${RUN_FILE_PREFIX}${(0, import_node_crypto23.createHash)("sha256").update(runId).digest("hex").slice(0, 32)}.json`;
65406
+ const file2 = `${RUN_FILE_PREFIX}${(0, import_node_crypto24.createHash)("sha256").update(runId).digest("hex").slice(0, 32)}.json`;
64188
65407
  const path4 = (0, import_node_path47.join)(dir, file2);
64189
65408
  const owner = await self(runId);
64190
65409
  await writeJsonFileAtomic(path4, owner);
@@ -64420,7 +65639,7 @@ async function openWorkspaces(options) {
64420
65639
 
64421
65640
  // src/cli/config.ts
64422
65641
  var import_node_os11 = require("os");
64423
- var import_node_path64 = require("path");
65642
+ var import_node_path65 = require("path");
64424
65643
  init_zod();
64425
65644
 
64426
65645
  // src/client/contract.ts
@@ -64705,6 +65924,7 @@ var mcpConfigResultSchema = external_exports.object({
64705
65924
 
64706
65925
  // src/client/runtime-client.ts
64707
65926
  var import_promises47 = require("fs/promises");
65927
+ init_acp();
64708
65928
  init_runtime_v2();
64709
65929
 
64710
65930
  // src/client/sse.ts
@@ -64921,11 +66141,51 @@ function createRuntimeClient(options) {
64921
66141
  throw new RuntimeClientError("unavailable", "The run log stream closed before the run ended");
64922
66142
  }
64923
66143
  const runs = async (signal) => (await json2({ path: LOCAL_API_ROUTES.runs }, runsResponseSchema, signal)).runs;
66144
+ async function* followConversationMessages(conversationId, limit, signal) {
66145
+ const stopped = new AbortController();
66146
+ try {
66147
+ const body = await openStream(
66148
+ {
66149
+ path: `/v2/conversations/${encodeURIComponent(conversationId)}/messages/sse`,
66150
+ query: { limit: String(limit) }
66151
+ },
66152
+ AbortSignal.any([signal, stopped.signal])
66153
+ );
66154
+ for await (const event of readServerSentEvents(body)) {
66155
+ const value2 = JSON.parse(event.data);
66156
+ if (event.event === "snapshot" && isConversationMessagesPage(value2))
66157
+ yield { kind: "snapshot", page: value2 };
66158
+ else if (event.event === "turn" && isConversationMessageTurn(value2))
66159
+ yield { kind: "turn", turn: value2 };
66160
+ else throw new RuntimeClientError("protocol", "Invalid local conversation update");
66161
+ }
66162
+ if (!signal.aborted)
66163
+ throw new RuntimeClientError("unavailable", "The local conversation stream closed");
66164
+ } finally {
66165
+ stopped.abort();
66166
+ }
66167
+ }
64924
66168
  return {
64925
66169
  status: (signal) => json2({ path: LOCAL_API_ROUTES.status }, runtimeStatusSchema, signal),
64926
66170
  watchStatus,
66171
+ followConversationMessages,
64927
66172
  runs,
64928
66173
  conversationRuns: async (conversationId, signal) => (await runs(signal)).filter((run2) => run2.conversationId === conversationId),
66174
+ readConversationMessages: async (conversationId, limit, before, signal) => {
66175
+ const response = await send2(
66176
+ {
66177
+ path: `/v2/conversations/${encodeURIComponent(conversationId)}/messages`,
66178
+ query: { limit: String(limit), ...before === null ? {} : { before } }
66179
+ },
66180
+ signal
66181
+ );
66182
+ if (response.status === 404) return null;
66183
+ if (!response.ok) throw await rejection(response);
66184
+ const page = await response.json();
66185
+ if (!isConversationMessagesPage(page))
66186
+ throw new RuntimeClientError("protocol", "Invalid local conversation page");
66187
+ return page;
66188
+ },
64929
66189
  readRunLog: async (runId, query, signal) => {
64930
66190
  const response = await send2(
64931
66191
  {
@@ -65091,14 +66351,14 @@ async function sendNativeHookSignal(discoveryPath, hookSignal, signal) {
65091
66351
  }
65092
66352
 
65093
66353
  // src/sessions/index.ts
65094
- var import_node_crypto29 = require("crypto");
65095
- var import_promises62 = require("fs/promises");
66354
+ var import_node_crypto30 = require("crypto");
66355
+ var import_promises64 = require("fs/promises");
65096
66356
  var import_node_os10 = require("os");
65097
- var import_node_path63 = require("path");
66357
+ var import_node_path64 = require("path");
65098
66358
  init_runtime_v2();
65099
66359
 
65100
66360
  // src/holder/control-client.ts
65101
- var import_node_crypto24 = require("crypto");
66361
+ var import_node_crypto25 = require("crypto");
65102
66362
  var import_node_net2 = require("net");
65103
66363
  init_runtime_v2();
65104
66364
 
@@ -65168,7 +66428,7 @@ async function connectHolder(endpoint, token, onEvent) {
65168
66428
  });
65169
66429
  const pid = await ready;
65170
66430
  const request2 = (body) => {
65171
- const id = (0, import_node_crypto24.randomUUID)();
66431
+ const id = (0, import_node_crypto25.randomUUID)();
65172
66432
  return new Promise((resolve12, reject) => {
65173
66433
  const timer = AbortSignal.timeout(REQUEST_TIMEOUT_MS7);
65174
66434
  timer.addEventListener("abort", () => {
@@ -65429,8 +66689,33 @@ function createConversationMcpAuthorization(options) {
65429
66689
  };
65430
66690
  }
65431
66691
 
65432
- // src/holder/run-inputs.ts
66692
+ // src/holder/mcp-helper-access.ts
65433
66693
  var import_promises54 = require("fs/promises");
66694
+ function createHelperMcpAccess(options) {
66695
+ return {
66696
+ [Symbol.asyncDispose]: async () => {
66697
+ await (0, import_promises54.rm)(options.credentialPath, { force: true });
66698
+ },
66699
+ url: options.managedMcp.url,
66700
+ authorization: async (signal) => {
66701
+ const authorization = await options.managedMcp.authorization(signal);
66702
+ if (authorization === void 0 || signal.aborted) {
66703
+ await (0, import_promises54.rm)(options.credentialPath, { force: true });
66704
+ return void 0;
66705
+ }
66706
+ const credential = {
66707
+ url: options.managedMcp.url,
66708
+ authorization,
66709
+ conversationId: options.conversationId
66710
+ };
66711
+ await writeJsonFileAtomic(options.credentialPath, credential);
66712
+ return authorization;
66713
+ }
66714
+ };
66715
+ }
66716
+
66717
+ // src/holder/run-inputs.ts
66718
+ var import_promises55 = require("fs/promises");
65434
66719
  var import_node_path53 = require("path");
65435
66720
  var NO_RUN_INPUTS = {
65436
66721
  attachments: [],
@@ -65446,16 +66731,16 @@ function safeFilename(filename) {
65446
66731
  async function prepareRunInputs(spec, { source, tmpDir, signal, skills = [] }) {
65447
66732
  const dir = (0, import_node_path53.join)(tmpDir, "runs", spec.runId);
65448
66733
  const cleanup = async () => {
65449
- await (0, import_promises54.rm)(dir, { recursive: true, force: true });
66734
+ await (0, import_promises55.rm)(dir, { recursive: true, force: true });
65450
66735
  };
65451
66736
  try {
65452
66737
  const credential = await source.fetchProviderCredential(spec.runId, signal);
65453
66738
  const attachments = [];
65454
- if (spec.attachments?.length) await (0, import_promises54.mkdir)(dir, { recursive: true, mode: 448 });
66739
+ if (spec.attachments?.length) await (0, import_promises55.mkdir)(dir, { recursive: true, mode: 448 });
65455
66740
  for (const [index, attachment] of (spec.attachments ?? []).entries()) {
65456
66741
  const bytes = await source.downloadAttachment(spec.runId, attachment.id, signal);
65457
66742
  const path4 = (0, import_node_path53.join)(dir, `${index}-${safeFilename(attachment.filename)}`);
65458
- await (0, import_promises54.writeFile)(path4, bytes, { mode: 384 });
66743
+ await (0, import_promises55.writeFile)(path4, bytes, { mode: 384 });
65459
66744
  attachments.push({
65460
66745
  id: attachment.id,
65461
66746
  kind: attachment.kind,
@@ -65482,15 +66767,15 @@ async function prepareRunInputs(spec, { source, tmpDir, signal, skills = [] }) {
65482
66767
  }
65483
66768
 
65484
66769
  // src/holder/serve.ts
65485
- var import_node_crypto28 = require("crypto");
66770
+ var import_node_crypto29 = require("crypto");
65486
66771
  var import_node_fs21 = require("fs");
65487
66772
  var import_node_net3 = require("net");
65488
- var import_node_path62 = require("path");
66773
+ var import_node_path63 = require("path");
65489
66774
  init_runtime_v2();
65490
66775
 
65491
66776
  // src/holder/admission.ts
65492
66777
  var import_node_fs18 = require("fs");
65493
- var import_promises58 = require("fs/promises");
66778
+ var import_promises59 = require("fs/promises");
65494
66779
  var import_node_os9 = require("os");
65495
66780
  var import_node_path58 = require("path");
65496
66781
  init_constants();
@@ -65504,7 +66789,7 @@ function resolveAlanDefaultWorkspacePath(homeDirectory = (0, import_node_os8.hom
65504
66789
  }
65505
66790
 
65506
66791
  // src/holder/admission-relocation.ts
65507
- var import_promises55 = require("fs/promises");
66792
+ var import_promises56 = require("fs/promises");
65508
66793
  var import_node_path55 = require("path");
65509
66794
  var MAX_RELOCATION_CANDIDATES = 200;
65510
66795
  var RELOCATION_BUDGET_MS = 2e4;
@@ -65540,7 +66825,7 @@ async function originIdentity(git, path4, signal) {
65540
66825
  }
65541
66826
  async function childDirectories(parent, limit) {
65542
66827
  try {
65543
- const entries = await (0, import_promises55.readdir)(parent, { withFileTypes: true });
66828
+ const entries = await (0, import_promises56.readdir)(parent, { withFileTypes: true });
65544
66829
  return entries.filter((entry) => entry.isDirectory()).slice(0, limit).map((entry) => (0, import_node_path55.join)(parent, entry.name));
65545
66830
  } catch {
65546
66831
  return [];
@@ -65576,8 +66861,8 @@ async function discoverRelocatedWorkspace(search) {
65576
66861
  }
65577
66862
 
65578
66863
  // src/holder/checkout-refresh.ts
65579
- var import_node_crypto26 = require("crypto");
65580
- var import_promises56 = require("fs/promises");
66864
+ var import_node_crypto27 = require("crypto");
66865
+ var import_promises57 = require("fs/promises");
65581
66866
  var import_node_path56 = require("path");
65582
66867
  function short(sha) {
65583
66868
  return sha.slice(0, 12);
@@ -65590,8 +66875,8 @@ function staleLine(path4, snapshot2, tip) {
65590
66875
  }
65591
66876
  async function claimOnce(dir, name) {
65592
66877
  try {
65593
- await (0, import_promises56.mkdir)(dir, { recursive: true, mode: 448 });
65594
- await (await (0, import_promises56.open)((0, import_node_path56.join)(dir, name), "wx")).close();
66878
+ await (0, import_promises57.mkdir)(dir, { recursive: true, mode: 448 });
66879
+ await (await (0, import_promises57.open)((0, import_node_path56.join)(dir, name), "wx")).close();
65595
66880
  return true;
65596
66881
  } catch {
65597
66882
  return false;
@@ -65623,7 +66908,7 @@ async function fastForward(freshness, operationId, deps, signal) {
65623
66908
  async function atFirstLease(freshness, spec, deps, signal) {
65624
66909
  const first = await claimOnce(
65625
66910
  (0, import_node_path56.join)(deps.dir, "leased"),
65626
- (0, import_node_crypto26.createHash)("sha256").update(freshness.path).digest("hex")
66911
+ (0, import_node_crypto27.createHash)("sha256").update(freshness.path).digest("hex")
65627
66912
  );
65628
66913
  switch (freshness.state) {
65629
66914
  case "current":
@@ -65674,7 +66959,7 @@ function createCheckoutRefresh(deps) {
65674
66959
  }
65675
66960
 
65676
66961
  // src/holder/lease.ts
65677
- var import_promises57 = require("fs/promises");
66962
+ var import_promises58 = require("fs/promises");
65678
66963
  var import_node_path57 = require("path");
65679
66964
  var LEASE_CHECK_EVERY_MS = 5e3;
65680
66965
  var MAX_TRANSIENT_FAILURES = 3;
@@ -65689,8 +66974,8 @@ function identityFailure(code, workspacePath) {
65689
66974
  return { code, problemCode: "app.workspace.missing", message: MESSAGES[code], workspacePath };
65690
66975
  }
65691
66976
  async function fileIdentity(path4) {
65692
- const canonical = await (0, import_promises57.realpath)(path4);
65693
- const info = await (0, import_promises57.stat)(canonical, { bigint: true });
66977
+ const canonical = await (0, import_promises58.realpath)(path4);
66978
+ const info = await (0, import_promises58.stat)(canonical, { bigint: true });
65694
66979
  return `${canonical}:${info.dev}:${info.ino}`;
65695
66980
  }
65696
66981
  async function snapshot(git, path4, signal) {
@@ -65709,7 +66994,7 @@ async function snapshot(git, path4, signal) {
65709
66994
  workspace: await fileIdentity(path4),
65710
66995
  repository: await fileIdentity(commonDir),
65711
66996
  worktree: await fileIdentity(gitDir),
65712
- commonDir: await (0, import_promises57.realpath)(commonDir)
66997
+ commonDir: await (0, import_promises58.realpath)(commonDir)
65713
66998
  };
65714
66999
  } catch {
65715
67000
  return null;
@@ -65722,7 +67007,7 @@ async function gitValue(git, path4, args, signal) {
65722
67007
  }
65723
67008
  async function pathExists(path4) {
65724
67009
  try {
65725
- await (0, import_promises57.stat)(path4);
67010
+ await (0, import_promises58.stat)(path4);
65726
67011
  return true;
65727
67012
  } catch (error61) {
65728
67013
  return errnoCode(error61) !== "ENOENT" && errnoCode(error61) !== "ENOTDIR";
@@ -65731,13 +67016,13 @@ async function pathExists(path4) {
65731
67016
  async function hasGitMarker(path4) {
65732
67017
  let directory;
65733
67018
  try {
65734
- directory = await (0, import_promises57.realpath)(path4);
67019
+ directory = await (0, import_promises58.realpath)(path4);
65735
67020
  } catch {
65736
67021
  return true;
65737
67022
  }
65738
67023
  for (; ; ) {
65739
67024
  try {
65740
- await (0, import_promises57.stat)((0, import_node_path57.join)(directory, ".git"));
67025
+ await (0, import_promises58.stat)((0, import_node_path57.join)(directory, ".git"));
65741
67026
  return true;
65742
67027
  } catch (error61) {
65743
67028
  const code = errnoCode(error61);
@@ -65907,7 +67192,7 @@ function volumeRoot(path4) {
65907
67192
  }
65908
67193
  async function exists4(path4) {
65909
67194
  try {
65910
- await (0, import_promises58.stat)(path4);
67195
+ await (0, import_promises59.stat)(path4);
65911
67196
  return true;
65912
67197
  } catch {
65913
67198
  return false;
@@ -65915,10 +67200,10 @@ async function exists4(path4) {
65915
67200
  }
65916
67201
  async function inspectReadiness(path4) {
65917
67202
  try {
65918
- if (!(await (0, import_promises58.stat)(path4)).isDirectory()) {
67203
+ if (!(await (0, import_promises59.stat)(path4)).isDirectory()) {
65919
67204
  return { ready: false, missing: true, message: MESSAGES2.missing };
65920
67205
  }
65921
- await (0, import_promises58.access)(path4, import_node_fs18.constants.R_OK | import_node_fs18.constants.W_OK | import_node_fs18.constants.X_OK);
67206
+ await (0, import_promises59.access)(path4, import_node_fs18.constants.R_OK | import_node_fs18.constants.W_OK | import_node_fs18.constants.X_OK);
65922
67207
  return { ready: true };
65923
67208
  } catch (error61) {
65924
67209
  const code = errnoCode(error61) ?? "";
@@ -65996,8 +67281,8 @@ async function admitDefaultWorkspace(spec, context, skills) {
65996
67281
  const { env } = context;
65997
67282
  const path4 = resolveAlanDefaultWorkspacePath(env.HOME || env.USERPROFILE || (0, import_node_os9.homedir)());
65998
67283
  try {
65999
- await (0, import_promises58.mkdir)(path4, { recursive: true, mode: 448 });
66000
- await (0, import_promises58.access)(path4, import_node_fs18.constants.R_OK | import_node_fs18.constants.W_OK | import_node_fs18.constants.X_OK);
67284
+ await (0, import_promises59.mkdir)(path4, { recursive: true, mode: 448 });
67285
+ await (0, import_promises59.access)(path4, import_node_fs18.constants.R_OK | import_node_fs18.constants.W_OK | import_node_fs18.constants.X_OK);
66001
67286
  return {
66002
67287
  kind: "admitted",
66003
67288
  spec: { ...spec, projectPath: path4 },
@@ -66013,6 +67298,16 @@ async function admitDefaultWorkspace(spec, context, skills) {
66013
67298
  );
66014
67299
  }
66015
67300
  }
67301
+ async function withInstalledCloudSkills(spec, context) {
67302
+ if (!spec.sandboxId && !spec.cloudEnvironmentId || context.skills === void 0) return spec;
67303
+ return {
67304
+ ...spec,
67305
+ promptContext: {
67306
+ ...spec.promptContext,
67307
+ availableSkills: await availableSkillIndex(context.skills)
67308
+ }
67309
+ };
67310
+ }
66016
67311
  async function admitRun(spec, context, signal) {
66017
67312
  const provider4 = await checkProvider(spec, context);
66018
67313
  if (provider4 !== null) return provider4;
@@ -66024,6 +67319,7 @@ async function admitRun(spec, context, signal) {
66024
67319
  );
66025
67320
  }
66026
67321
  const skills = selected.skills;
67322
+ spec = await withInstalledCloudSkills(spec, context);
66027
67323
  const projectPath = spec.projectPath;
66028
67324
  if (projectPath === void 0) {
66029
67325
  return { kind: "admitted", spec, relocated: null, leaseTargets: [], skills };
@@ -66115,7 +67411,7 @@ async function respondToTurn(runningRunId, gate, driver, request2) {
66115
67411
  }
66116
67412
 
66117
67413
  // src/holder/session-facts.ts
66118
- var import_promises59 = require("fs/promises");
67414
+ var import_promises60 = require("fs/promises");
66119
67415
  var CLI_RSS_CACHE_MS = 1e4;
66120
67416
  var LOGIN_PROBLEM_PREFIX = "cli.auth.";
66121
67417
  function isLoginFailure(result) {
@@ -66141,8 +67437,8 @@ function createSessionFacts(options) {
66141
67437
  const path4 = await resolveCommandOnPath(command, env, platform3);
66142
67438
  if (path4 === null) return null;
66143
67439
  try {
66144
- const real = await (0, import_promises59.realpath)(path4);
66145
- const info = await (0, import_promises59.stat)(real);
67440
+ const real = await (0, import_promises60.realpath)(path4);
67441
+ const info = await (0, import_promises60.stat)(real);
66146
67442
  return { command, key: `${real}:${info.ino}:${info.size}:${info.mtimeMs}` };
66147
67443
  } catch {
66148
67444
  return null;
@@ -66229,16 +67525,33 @@ function createSessionFacts(options) {
66229
67525
  init_acp2();
66230
67526
 
66231
67527
  // src/run-log/complete.ts
66232
- var import_node_crypto27 = require("crypto");
67528
+ var import_node_crypto28 = require("crypto");
66233
67529
  var import_node_fs19 = require("fs");
66234
67530
  var import_node_path60 = require("path");
66235
67531
 
66236
67532
  // src/run-log/directory.ts
66237
- var import_promises60 = require("fs/promises");
67533
+ var import_promises61 = require("fs/promises");
66238
67534
  var import_node_path59 = require("path");
66239
67535
  init_runtime_v2();
66240
67536
  init_zod();
66241
- var runMetaSchema = external_exports.object({ runId: runIdSchema, conversationId: conversationIdSchema });
67537
+ var runMetaSchema = external_exports.object({
67538
+ runId: runIdSchema,
67539
+ conversationId: conversationIdSchema,
67540
+ agentMode: external_exports.string().optional(),
67541
+ userMessage: external_exports.object({
67542
+ id: external_exports.string(),
67543
+ content: external_exports.string(),
67544
+ turnOrdinal: external_exports.number().int().nullable(),
67545
+ createdAt: external_exports.string(),
67546
+ clientMessageId: external_exports.string().optional(),
67547
+ attachmentIds: external_exports.array(external_exports.string()).optional()
67548
+ }).optional(),
67549
+ assistantMessage: external_exports.object({
67550
+ id: external_exports.string(),
67551
+ turnOrdinal: external_exports.number().int().nullable(),
67552
+ createdAt: external_exports.string()
67553
+ }).optional()
67554
+ });
66242
67555
  async function readRunMeta(path4) {
66243
67556
  const read = await readJsonFile(path4, runMetaSchema);
66244
67557
  return read.kind === "ok" ? read.value : null;
@@ -66254,7 +67567,7 @@ function runDirectory(runsDir, runId) {
66254
67567
  }
66255
67568
  async function isRunClaimed(runsDir, runId) {
66256
67569
  try {
66257
- return (await (0, import_promises60.stat)(runDirectory(runsDir, runId).log)).size > 0;
67570
+ return (await (0, import_promises61.stat)(runDirectory(runsDir, runId).log)).size > 0;
66258
67571
  } catch (error61) {
66259
67572
  if (errnoCode(error61) === "ENOENT") return false;
66260
67573
  throw error61;
@@ -66263,7 +67576,7 @@ async function isRunClaimed(runsDir, runId) {
66263
67576
 
66264
67577
  // src/run-log/complete.ts
66265
67578
  function writeLogFile(path4, dir, text2) {
66266
- const temp = (0, import_node_path60.join)(dir, `.log.${(0, import_node_crypto27.randomUUID)()}.tmp`);
67579
+ const temp = (0, import_node_path60.join)(dir, `.log.${(0, import_node_crypto28.randomUUID)()}.tmp`);
66267
67580
  const fd = (0, import_node_fs19.openSync)(temp, "wx", 384);
66268
67581
  try {
66269
67582
  (0, import_node_fs19.writeSync)(fd, text2);
@@ -66291,8 +67604,79 @@ async function writeCompleteRunLog(runsDir, meta3, records) {
66291
67604
  if (await readRunMeta(paths.meta) === null) await writeJsonFileAtomic(paths.meta, meta3);
66292
67605
  }
66293
67606
 
67607
+ // src/run-log/conversation-index.ts
67608
+ var import_promises62 = require("fs/promises");
67609
+ var import_node_path61 = require("path");
67610
+ init_runtime_v2();
67611
+ init_zod();
67612
+ var ORDINALS_PER_SHARD = 1e3;
67613
+ var indexRecordSchema = external_exports.object({
67614
+ ordinal: external_exports.number().int().nonnegative(),
67615
+ nextOrdinal: external_exports.number().int().positive(),
67616
+ runId: runIdSchema
67617
+ });
67618
+ var coverageSchema = external_exports.object({
67619
+ highestOrdinal: external_exports.number().int().nonnegative(),
67620
+ nextExpectedOrdinal: external_exports.number().int().positive()
67621
+ });
67622
+ function indexDirectory(runsDir, conversationId) {
67623
+ return (0, import_node_path61.join)((0, import_node_path61.dirname)(runsDir), "sessions", conversationId, "turn-index");
67624
+ }
67625
+ function shardPath(runsDir, conversationId, ordinal) {
67626
+ return (0, import_node_path61.join)(
67627
+ indexDirectory(runsDir, conversationId),
67628
+ `${Math.floor(ordinal / ORDINALS_PER_SHARD)}.jsonl`
67629
+ );
67630
+ }
67631
+ async function indexConversationRun(runsDir, conversationId, ordinal, assistantOrdinal, runId) {
67632
+ const nextOrdinal = assistantOrdinal + 1;
67633
+ if (nextOrdinal <= ordinal) throw new Error("Assistant order must follow the prompt");
67634
+ const path4 = shardPath(runsDir, conversationId, ordinal);
67635
+ await (0, import_promises62.mkdir)((0, import_node_path61.dirname)(path4), { recursive: true, mode: 448 });
67636
+ await (0, import_promises62.appendFile)(path4, `${JSON.stringify({ ordinal, nextOrdinal, runId })}
67637
+ `, { mode: 384 });
67638
+ const coveragePath = (0, import_node_path61.join)((0, import_node_path61.dirname)((0, import_node_path61.dirname)(path4)), "coverage.json");
67639
+ const coverage = await readJsonFile(coveragePath, coverageSchema);
67640
+ const current = coverage.kind === "ok" ? coverage.value : null;
67641
+ if (ordinal === 0 && current === null || current?.nextExpectedOrdinal === ordinal)
67642
+ await writeJsonFileAtomic(coveragePath, {
67643
+ highestOrdinal: ordinal,
67644
+ nextExpectedOrdinal: nextOrdinal
67645
+ });
67646
+ }
67647
+ async function readConversationIndexCoverage(runsDir, conversationId) {
67648
+ const path4 = (0, import_node_path61.join)((0, import_node_path61.dirname)(indexDirectory(runsDir, conversationId)), "coverage.json");
67649
+ const result = await readJsonFile(path4, coverageSchema);
67650
+ return result.kind === "ok" ? result.value : null;
67651
+ }
67652
+ async function readConversationRunIndex(runsDir, conversationId, before, limit) {
67653
+ const directory = indexDirectory(runsDir, conversationId);
67654
+ const names = await (0, import_promises62.readdir)(directory).catch((error61) => {
67655
+ if (error61.code === "ENOENT") return [];
67656
+ throw error61;
67657
+ });
67658
+ const shards = names.map((name) => /^\d+\.jsonl$/.test(name) ? Number(name.slice(0, -6)) : NaN).filter((shard) => Number.isSafeInteger(shard)).filter(
67659
+ (shard) => before === void 0 || shard <= Math.floor((before - 1) / ORDINALS_PER_SHARD)
67660
+ ).sort((left, right) => right - left);
67661
+ const selected = [];
67662
+ for (const shard of shards) {
67663
+ const text2 = await (0, import_promises62.readFile)((0, import_node_path61.join)(directory, `${shard}.jsonl`), "utf8");
67664
+ const records = text2.split("\n").flatMap((line) => {
67665
+ if (!line) return [];
67666
+ const parsed = indexRecordSchema.parse(JSON.parse(line));
67667
+ return [parsed];
67668
+ }).filter((record2) => before === void 0 || record2.ordinal < before).reverse().sort((left, right) => right.ordinal - left.ordinal);
67669
+ for (const record2 of records) {
67670
+ if (selected.some((entry) => entry.ordinal === record2.ordinal)) continue;
67671
+ selected.push(record2);
67672
+ if (selected.length >= limit) return selected;
67673
+ }
67674
+ }
67675
+ return selected;
67676
+ }
67677
+
66294
67678
  // src/run-log/reader.ts
66295
- var import_promises61 = require("fs/promises");
67679
+ var import_promises63 = require("fs/promises");
66296
67680
  init_runtime_v2();
66297
67681
 
66298
67682
  // src/run-log/tail.ts
@@ -66315,7 +67699,7 @@ function firstRecordLength(bytes) {
66315
67699
  return bytes.indexOf(RUN_LOG_RECORD_SEPARATOR) + 1;
66316
67700
  }
66317
67701
  async function openRunLogReader(path4) {
66318
- const handle = await (0, import_promises61.open)(path4, "r");
67702
+ const handle = await (0, import_promises63.open)(path4, "r");
66319
67703
  const readAt = async (position, length) => {
66320
67704
  const buffer = Buffer.alloc(length);
66321
67705
  const { bytesRead } = await handle.read(buffer, 0, length, position);
@@ -66349,7 +67733,7 @@ async function openRunLogReader(path4) {
66349
67733
  };
66350
67734
  }
66351
67735
  async function readLastRecord(path4) {
66352
- const handle = await (0, import_promises61.open)(path4, "r").catch(() => null);
67736
+ const handle = await (0, import_promises63.open)(path4, "r").catch(() => null);
66353
67737
  if (handle === null) return null;
66354
67738
  try {
66355
67739
  const { size } = await handle.stat();
@@ -66383,7 +67767,7 @@ var decoder = new TextDecoder();
66383
67767
 
66384
67768
  // src/run-log/writer.ts
66385
67769
  var import_node_fs20 = require("fs");
66386
- var import_node_path61 = require("path");
67770
+ var import_node_path62 = require("path");
66387
67771
  init_runtime_v2();
66388
67772
  function lastSeq(fd, size) {
66389
67773
  for (const length of tailWindows(size)) {
@@ -66399,7 +67783,7 @@ function lastSeq(fd, size) {
66399
67783
  throw new RuntimeFault("record_too_large", "Run log tail record is larger than any record");
66400
67784
  }
66401
67785
  function openRunLog(path4, clock) {
66402
- (0, import_node_fs20.mkdirSync)((0, import_node_path61.dirname)(path4), { recursive: true, mode: 448 });
67786
+ (0, import_node_fs20.mkdirSync)((0, import_node_path62.dirname)(path4), { recursive: true, mode: 448 });
66403
67787
  const fd = (0, import_node_fs20.openSync)(path4, "a+", 384);
66404
67788
  let size = (0, import_node_fs20.fstatSync)(fd).size;
66405
67789
  let seq = lastSeq(fd, size);
@@ -66631,10 +68015,30 @@ async function admitAndRun(spec, context, append, sink, signal) {
66631
68015
  async function claimRun(spec, context) {
66632
68016
  if (await isRunClaimed(context.runsDir, spec.runId)) return null;
66633
68017
  const paths = runDirectory(context.runsDir, spec.runId);
66634
- await writeJsonFileAtomic(paths.meta, { runId: spec.runId, conversationId: spec.conversationId });
68018
+ await writeJsonFileAtomic(paths.meta, {
68019
+ runId: spec.runId,
68020
+ conversationId: spec.conversationId,
68021
+ ...spec.mode ? { agentMode: spec.mode } : {},
68022
+ ...spec.userMessage ? { userMessage: spec.userMessage } : {},
68023
+ ...spec.assistantMessage ? { assistantMessage: spec.assistantMessage } : {}
68024
+ });
66635
68025
  const log = openRunLog(paths.log, context.clock);
66636
68026
  const offset = log.append(runAccepted(context.machineId, context.clock.now()));
66637
68027
  context.onAppended(spec.runId, offset);
68028
+ if (spec.userMessage?.turnOrdinal !== null && spec.userMessage?.turnOrdinal !== void 0 && spec.assistantMessage?.turnOrdinal !== null && spec.assistantMessage?.turnOrdinal !== void 0) {
68029
+ try {
68030
+ await indexConversationRun(
68031
+ context.runsDir,
68032
+ spec.conversationId,
68033
+ spec.userMessage.turnOrdinal,
68034
+ spec.assistantMessage.turnOrdinal,
68035
+ spec.runId
68036
+ );
68037
+ context.onAppended(spec.runId, offset);
68038
+ } catch (error61) {
68039
+ context.log.warn("holder.conversation_index_failed", { runId: spec.runId, error: error61 });
68040
+ }
68041
+ }
66638
68042
  return log;
66639
68043
  }
66640
68044
  async function runClaimedTurn(spec, claimed, context, signal) {
@@ -66696,12 +68100,12 @@ var TASK_UNSUPPORTED = {
66696
68100
  message: "This agent cannot stop one background task."
66697
68101
  };
66698
68102
  function sha2564(value2) {
66699
- return (0, import_node_crypto28.createHash)("sha256").update(value2).digest("hex");
68103
+ return (0, import_node_crypto29.createHash)("sha256").update(value2).digest("hex");
66700
68104
  }
66701
68105
  function tokenMatches(expected, presented) {
66702
68106
  const a = Buffer.from(sha2564(expected), "hex");
66703
68107
  const b = Buffer.from(sha2564(presented), "hex");
66704
- return (0, import_node_crypto28.timingSafeEqual)(a, b);
68108
+ return (0, import_node_crypto29.timingSafeEqual)(a, b);
66705
68109
  }
66706
68110
  async function runHolder({
66707
68111
  launch,
@@ -66715,7 +68119,7 @@ async function runHolder({
66715
68119
  try {
66716
68120
  const identity = await readProcessIdentity(process.pid);
66717
68121
  if (identity === null) throw new RuntimeFault("internal", "Cannot read own process identity");
66718
- const _engines = __using(_stack, recordSpawnedEngines(engineRecordsPath((0, import_node_path62.dirname)(launch.statusPath)), clock, log));
68122
+ const _engines = __using(_stack, recordSpawnedEngines(engineRecordsPath((0, import_node_path63.dirname)(launch.statusPath)), clock, log));
66719
68123
  const holder = {
66720
68124
  state: "idle",
66721
68125
  runId: null,
@@ -67009,7 +68413,7 @@ var DEFAULT_MAX_ACTIVE_RUNS = 32;
67009
68413
  var HOLDER_BUSY = "busy";
67010
68414
  async function listIds(dir, schema) {
67011
68415
  const ids = [];
67012
- for (const name of await (0, import_promises62.readdir)(dir).catch(() => [])) {
68416
+ for (const name of await (0, import_promises64.readdir)(dir).catch(() => [])) {
67013
68417
  const parsed = schema.safeParse(name);
67014
68418
  if (parsed.success) ids.push(parsed.data);
67015
68419
  }
@@ -67023,8 +68427,8 @@ function holderIdentity(status) {
67023
68427
  return command === void 0 ? { pid, startedAt } : { pid, startedAt, command };
67024
68428
  }
67025
68429
  function sessionFiles(paths, conversationId) {
67026
- const dir = (0, import_node_path63.join)(paths.sessions, conversationId);
67027
- return { dir, launch: (0, import_node_path63.join)(dir, "launch.json"), status: (0, import_node_path63.join)(dir, "holder.json") };
68430
+ const dir = (0, import_node_path64.join)(paths.sessions, conversationId);
68431
+ return { dir, launch: (0, import_node_path64.join)(dir, "launch.json"), status: (0, import_node_path64.join)(dir, "holder.json") };
67028
68432
  }
67029
68433
  async function openSessions(deps) {
67030
68434
  const { paths, clock, log } = deps;
@@ -67065,7 +68469,7 @@ async function openSessions(deps) {
67065
68469
  await reapLeftoverEngines(engineRecordsPath(dir), { clock, log, conversationId }).catch(
67066
68470
  (error61) => log.warn("sessions.engine_reap_failed", { conversationId, error: error61 })
67067
68471
  );
67068
- await (0, import_promises62.rm)(dir, { recursive: true, force: true });
68472
+ await (0, import_promises64.rm)(dir, { recursive: true, force: true });
67069
68473
  };
67070
68474
  const retireIfGone = async (conversationId) => {
67071
68475
  const files = sessionFiles(paths, conversationId);
@@ -67153,7 +68557,7 @@ async function openSessions(deps) {
67153
68557
  log.info("sessions.reattached", { conversationId });
67154
68558
  return;
67155
68559
  }
67156
- if (alive) await (0, import_promises62.rm)(files.dir, { recursive: true, force: true });
68560
+ if (alive) await (0, import_promises64.rm)(files.dir, { recursive: true, force: true });
67157
68561
  else await discardSession(conversationId);
67158
68562
  };
67159
68563
  const busyRunIds = async () => {
@@ -67178,14 +68582,14 @@ async function openSessions(deps) {
67178
68582
  if (!busy.has(runId)) await markInterrupted(runId);
67179
68583
  }
67180
68584
  };
67181
- const spawn11 = async (conversationId) => {
68585
+ const spawn10 = async (conversationId) => {
67182
68586
  const files = sessionFiles(paths, conversationId);
67183
68587
  const launch = {
67184
68588
  protocol: HOLDER_PROTOCOL,
67185
68589
  conversationId,
67186
68590
  machineId: deps.machineId,
67187
- endpoint: ipcEndpoint(paths.sockets, (0, import_node_crypto29.randomUUID)().slice(0, 8)),
67188
- token: (0, import_node_crypto29.randomBytes)(32).toString("hex"),
68591
+ endpoint: ipcEndpoint(paths.sockets, (0, import_node_crypto30.randomUUID)().slice(0, 8)),
68592
+ token: (0, import_node_crypto30.randomBytes)(32).toString("hex"),
67189
68593
  runsDir: paths.runs,
67190
68594
  statusPath: files.status
67191
68595
  };
@@ -67211,7 +68615,7 @@ async function openSessions(deps) {
67211
68615
  const meta3 = await readRunMeta(dir.meta);
67212
68616
  const last = await readLastRecord(dir.log);
67213
68617
  if (meta3 === null || last === null) return null;
67214
- const logged = await (0, import_promises62.stat)(dir.log).catch((error61) => {
68618
+ const logged = await (0, import_promises64.stat)(dir.log).catch((error61) => {
67215
68619
  if (errnoCode(error61) === "ENOENT") return null;
67216
68620
  throw error61;
67217
68621
  });
@@ -67322,7 +68726,7 @@ async function openSessions(deps) {
67322
68726
  return "started";
67323
68727
  }
67324
68728
  if (await activeRunsOtherThan(run2.runId) >= maxActiveRuns) return "waiting";
67325
- if (!connections.has(run2.conversationId)) await spawn11(run2.conversationId);
68729
+ if (!connections.has(run2.conversationId)) await spawn10(run2.conversationId);
67326
68730
  const connection = connections.get(run2.conversationId);
67327
68731
  if (connection === void 0) {
67328
68732
  throw new RuntimeFault("internal", "Holder connection missing");
@@ -67521,7 +68925,7 @@ function loadRuntimeConfig(env = process.env, totalMemoryBytes = (0, import_node
67521
68925
  providerProbes: ALAN_RUNTIME_PROVIDER_PROBES === "on",
67522
68926
  providerToolchain: ALAN_RUNTIME_PROVIDER_NODE !== void 0 && ALAN_RUNTIME_PROVIDER_NPM_CLI !== void 0 ? { node: ALAN_RUNTIME_PROVIDER_NODE, npmCli: ALAN_RUNTIME_PROVIDER_NPM_CLI } : null,
67523
68927
  home,
67524
- configHome: XDG_CONFIG_HOME ?? (0, import_node_path64.join)(home, ".config"),
68928
+ configHome: XDG_CONFIG_HOME ?? (0, import_node_path65.join)(home, ".config"),
67525
68929
  ...githubProxyConfig({ ALAN_RUNTIME_GITHUB_PROXY, XDG_CONFIG_HOME, GH_CONFIG_DIR }, home),
67526
68930
  gitGatewayUrl: ALAN_RUNTIME_GIT_GATEWAY_URL ?? null,
67527
68931
  workspaceRoot: ALAN_RUNTIME_WORKSPACE_ROOT ?? null,
@@ -67530,10 +68934,10 @@ function loadRuntimeConfig(env = process.env, totalMemoryBytes = (0, import_node
67530
68934
  };
67531
68935
  }
67532
68936
  function githubProxyConfig(env, home) {
67533
- const configHome = env.XDG_CONFIG_HOME ?? (0, import_node_path64.join)(home, ".config");
68937
+ const configHome = env.XDG_CONFIG_HOME ?? (0, import_node_path65.join)(home, ".config");
67534
68938
  return {
67535
68939
  githubProxy: env.ALAN_RUNTIME_GITHUB_PROXY === "on",
67536
- ghConfigDir: env.GH_CONFIG_DIR ?? (0, import_node_path64.join)(configHome, "gh")
68940
+ ghConfigDir: env.GH_CONFIG_DIR ?? (0, import_node_path65.join)(configHome, "gh")
67537
68941
  };
67538
68942
  }
67539
68943
  function serviceEnvironment2(env, profile) {
@@ -67591,9 +68995,9 @@ function takeEnrollmentCodeFromEnv(env = process.env) {
67591
68995
  }
67592
68996
 
67593
68997
  // src/cli/context.ts
67594
- var import_promises63 = require("fs/promises");
68998
+ var import_promises65 = require("fs/promises");
67595
68999
  var import_node_os12 = require("os");
67596
- var import_node_path65 = require("path");
69000
+ var import_node_path66 = require("path");
67597
69001
  var DESKTOP_BUNDLE_IDS = {
67598
69002
  production: ["com.alan-ai.desktop"],
67599
69003
  staging: ["com.alan-ai.desktop.staging"],
@@ -67633,7 +69037,7 @@ function serviceSpec({ config: config2, paths, self }) {
67633
69037
  profile: config2.profile,
67634
69038
  program: serviceCommand(config2.host, self, launcher),
67635
69039
  environment: config2.serviceEnvironment,
67636
- logPath: (0, import_node_path65.join)(paths.logs, "service.log"),
69040
+ logPath: (0, import_node_path66.join)(paths.logs, "service.log"),
67637
69041
  associatedBundleIds: DESKTOP_BUNDLE_IDS[config2.profile]
67638
69042
  };
67639
69043
  }
@@ -67641,7 +69045,7 @@ async function installedServiceSpec(ctx) {
67641
69045
  const spec = serviceSpec(ctx);
67642
69046
  if (ctx.config.host === "app") return spec;
67643
69047
  const layout = installLayout(ctx.config.installDir, ctx.config.profile);
67644
- const installed = await (0, import_promises63.access)(layout.launcher).then(
69048
+ const installed = await (0, import_promises65.access)(layout.launcher).then(
67645
69049
  () => true,
67646
69050
  () => false
67647
69051
  );
@@ -67769,7 +69173,7 @@ var manifestRevisionSchema = external_exports.object({ revision: external_export
67769
69173
  async function manifestRevision(path4) {
67770
69174
  let raw;
67771
69175
  try {
67772
- raw = JSON.parse(await (0, import_promises64.readFile)(path4, "utf8"));
69176
+ raw = JSON.parse(await (0, import_promises66.readFile)(path4, "utf8"));
67773
69177
  } catch (error61) {
67774
69178
  throw new RuntimeFault("invalid_file", `Cannot read the skill manifest at ${path4}`, {
67775
69179
  cause: error61
@@ -67787,7 +69191,7 @@ async function runSkills(argv) {
67787
69191
  case "scan":
67788
69192
  writeJson({
67789
69193
  status: "failed",
67790
- attemptId: (0, import_node_crypto30.randomUUID)(),
69194
+ attemptId: (0, import_node_crypto31.randomUUID)(),
67791
69195
  retainedInventoryRevision: null,
67792
69196
  diagnostics: [
67793
69197
  { code: "RUNTIME_SKILL_SCAN_UNSUPPORTED", message: SKILLS_SYNCED_BY_RUNTIME }
@@ -67803,7 +69207,7 @@ async function runSkills(argv) {
67803
69207
  );
67804
69208
  }
67805
69209
  writeJson({
67806
- attemptId: (0, import_node_crypto30.randomUUID)(),
69210
+ attemptId: (0, import_node_crypto31.randomUUID)(),
67807
69211
  desiredRevision: await manifestRevision(manifest),
67808
69212
  skills: []
67809
69213
  });
@@ -67823,8 +69227,8 @@ async function runSkills(argv) {
67823
69227
  }
67824
69228
 
67825
69229
  // src/cli/commands/doctor.ts
67826
- var import_promises67 = require("fs/promises");
67827
- var import_node_path69 = require("path");
69230
+ var import_promises69 = require("fs/promises");
69231
+ var import_node_path70 = require("path");
67828
69232
  init_runtime_v2();
67829
69233
 
67830
69234
  // src/identity/credential.ts
@@ -68001,24 +69405,24 @@ async function authorizeDevice(input2) {
68001
69405
  }
68002
69406
 
68003
69407
  // src/identity/enroll.ts
68004
- var import_promises65 = require("fs/promises");
69408
+ var import_promises67 = require("fs/promises");
68005
69409
  init_runtime_v2();
68006
69410
 
68007
69411
  // src/identity/installation.ts
68008
- var import_node_crypto31 = require("crypto");
68009
- var import_node_path66 = require("path");
69412
+ var import_node_crypto32 = require("crypto");
69413
+ var import_node_path67 = require("path");
68010
69414
  init_zod();
68011
69415
  var installationFileSchema = external_exports.object({
68012
69416
  installationId: external_exports.uuid()
68013
69417
  });
68014
69418
  function installationPath(paths) {
68015
- return (0, import_node_path66.join)(paths.stateDir, "installation.json");
69419
+ return (0, import_node_path67.join)(paths.stateDir, "installation.json");
68016
69420
  }
68017
69421
  async function ensureInstallationId(paths) {
68018
69422
  const path4 = installationPath(paths);
68019
69423
  const existing = await readJsonFile(path4, installationFileSchema);
68020
69424
  if (existing.kind === "ok") return existing.value.installationId;
68021
- const created = { installationId: (0, import_node_crypto31.randomUUID)() };
69425
+ const created = { installationId: (0, import_node_crypto32.randomUUID)() };
68022
69426
  await writeJsonFileAtomic(path4, created);
68023
69427
  return created.installationId;
68024
69428
  }
@@ -68105,13 +69509,13 @@ async function enrollFromGrantFile(input2) {
68105
69509
  clock: input2.clock,
68106
69510
  access: input2.access
68107
69511
  });
68108
- await (0, import_promises65.rm)(input2.grantPath, { force: true });
69512
+ await (0, import_promises67.rm)(input2.grantPath, { force: true });
68109
69513
  return machine;
68110
69514
  }
68111
69515
 
68112
69516
  // src/identity/migrate-v1.ts
68113
- var import_promises66 = require("fs/promises");
68114
- var import_node_path67 = require("path");
69517
+ var import_promises68 = require("fs/promises");
69518
+ var import_node_path68 = require("path");
68115
69519
  init_runtime_v2();
68116
69520
  init_zod();
68117
69521
  var EXIT_POLL_MS = 200;
@@ -68132,11 +69536,11 @@ var ownerLeaseSchema = external_exports.looseObject({ pid: external_exports.numb
68132
69536
  function legacyConfigPath(home, profile) {
68133
69537
  switch (profile) {
68134
69538
  case "production":
68135
- return (0, import_node_path67.join)(home, ".alan", "agent", "config.json");
69539
+ return (0, import_node_path68.join)(home, ".alan", "agent", "config.json");
68136
69540
  case "staging":
68137
- return (0, import_node_path67.join)(home, ".alan-staging", "agent", "config.json");
69541
+ return (0, import_node_path68.join)(home, ".alan-staging", "agent", "config.json");
68138
69542
  default:
68139
- return (0, import_node_path67.join)(home, ".alan-dev", "agent", "config.json");
69543
+ return (0, import_node_path68.join)(home, ".alan-dev", "agent", "config.json");
68140
69544
  }
68141
69545
  }
68142
69546
  async function findLegacyInstall(home, profile) {
@@ -68161,8 +69565,8 @@ async function scrubLegacyInstall(install2) {
68161
69565
  const scrubbed = { ...install2.config, migratedToRuntimeV2: true };
68162
69566
  for (const key of SCRUBBED_KEYS) delete scrubbed[key];
68163
69567
  await writeJsonFileAtomic(`${install2.configPath}.migrated-v1`, scrubbed);
68164
- await (0, import_promises66.rm)(install2.configPath, { force: true });
68165
- await (0, import_promises66.rm)(install2.ownerLeasePath, { force: true });
69568
+ await (0, import_promises68.rm)(install2.configPath, { force: true });
69569
+ await (0, import_promises68.rm)(install2.ownerLeasePath, { force: true });
68166
69570
  }
68167
69571
  async function exchangeCredential(deps) {
68168
69572
  const { config: config2 } = deps.install;
@@ -68271,7 +69675,7 @@ async function loadIdentity(paths, options = {}) {
68271
69675
  }
68272
69676
 
68273
69677
  // src/cli/commands/status.ts
68274
- var import_node_path68 = require("path");
69678
+ var import_node_path69 = require("path");
68275
69679
  async function serviceStatus(ctx) {
68276
69680
  try {
68277
69681
  return await createServiceManager(ctx.host, ctx.config.profile).status();
@@ -68298,7 +69702,7 @@ async function runtimeState(ctx) {
68298
69702
  const running = await readRunningRuntime(ctx.paths.lock);
68299
69703
  if (running === null) return { state: "offline", pid: null, localApi: null };
68300
69704
  const discovery = await readJsonFile(
68301
- (0, import_node_path68.join)(ctx.paths.stateDir, LOCAL_API_DISCOVERY_FILE),
69705
+ (0, import_node_path69.join)(ctx.paths.stateDir, LOCAL_API_DISCOVERY_FILE),
68302
69706
  localApiDiscoverySchema
68303
69707
  );
68304
69708
  const localApi = discovery.kind === "ok" && discovery.value.pid === running.pid ? {
@@ -68519,7 +69923,7 @@ async function runtimeCheck(ctx, status) {
68519
69923
  return check2("runtime", "warn", "No runtime is running for this profile");
68520
69924
  }
68521
69925
  const client = createRuntimeClient({
68522
- discoveryPath: (0, import_node_path69.join)(ctx.paths.stateDir, LOCAL_API_DISCOVERY_FILE)
69926
+ discoveryPath: (0, import_node_path70.join)(ctx.paths.stateDir, LOCAL_API_DISCOVERY_FILE)
68523
69927
  });
68524
69928
  try {
68525
69929
  const live = await client.status(AbortSignal.timeout(LOCAL_TIMEOUT_MS));
@@ -68546,7 +69950,7 @@ async function runtimeCheck(ctx, status) {
68546
69950
  }
68547
69951
  }
68548
69952
  async function probeHolder(dir, conversationId) {
68549
- const launch = await readJsonFile((0, import_node_path69.join)(dir, "launch.json"), holderLaunchSchema);
69953
+ const launch = await readJsonFile((0, import_node_path70.join)(dir, "launch.json"), holderLaunchSchema);
68550
69954
  if (launch.kind !== "ok") return null;
68551
69955
  try {
68552
69956
  const reply2 = await withTimeout(
@@ -68571,8 +69975,8 @@ async function probeHolder(dir, conversationId) {
68571
69975
  }
68572
69976
  }
68573
69977
  async function holdersCheck(ctx) {
68574
- const names = await (0, import_promises67.readdir)(ctx.paths.sessions).catch(() => []);
68575
- const holders = (await Promise.all(names.map((name) => probeHolder((0, import_node_path69.join)(ctx.paths.sessions, name), name)))).filter((facts) => facts !== null);
69978
+ const names = await (0, import_promises69.readdir)(ctx.paths.sessions).catch(() => []);
69979
+ const holders = (await Promise.all(names.map((name) => probeHolder((0, import_node_path70.join)(ctx.paths.sessions, name), name)))).filter((facts) => facts !== null);
68576
69980
  const dead = holders.filter((holder) => !holder.alive).length;
68577
69981
  return check2(
68578
69982
  "holders",
@@ -68583,10 +69987,10 @@ async function holdersCheck(ctx) {
68583
69987
  }
68584
69988
  async function freeBytesAt(path4) {
68585
69989
  try {
68586
- const stats = await (0, import_promises67.statfs)(path4);
69990
+ const stats = await (0, import_promises69.statfs)(path4);
68587
69991
  return { path: path4, freeBytes: stats.bavail * stats.bsize };
68588
69992
  } catch (error61) {
68589
- const parent = (0, import_node_path69.dirname)(path4);
69993
+ const parent = (0, import_node_path70.dirname)(path4);
68590
69994
  if (parent === path4) throw error61;
68591
69995
  return freeBytesAt(parent);
68592
69996
  }
@@ -68722,7 +70126,7 @@ async function runDoctor(argv, context = cliContext) {
68722
70126
  }
68723
70127
 
68724
70128
  // src/cli/commands/git-credential.ts
68725
- var import_promises68 = require("fs/promises");
70129
+ var import_promises70 = require("fs/promises");
68726
70130
  var import_node_net4 = require("net");
68727
70131
  var MAX_RESPONSE_BYTES = 64 * 1024;
68728
70132
  async function readAll(stream) {
@@ -68832,7 +70236,7 @@ async function configure(argv) {
68832
70236
  }
68833
70237
  async function configureGitGateway(config2, gatewayUrl, signal) {
68834
70238
  const { launcher } = installLayout(config2.installDir, config2.profile);
68835
- const installed = await (0, import_promises68.access)(launcher).then(
70239
+ const installed = await (0, import_promises70.access)(launcher).then(
68836
70240
  () => true,
68837
70241
  () => false
68838
70242
  );
@@ -68859,7 +70263,8 @@ async function runGitCredential(argv) {
68859
70263
  }
68860
70264
 
68861
70265
  // src/cli/commands/hold.ts
68862
- var import_node_path70 = require("path");
70266
+ var import_node_path71 = require("path");
70267
+ init_agent2();
68863
70268
  init_runtime_v2();
68864
70269
  async function machineAccess(paths, log, conversationId, transport) {
68865
70270
  const initial = await loadStoredAccess(paths).catch(
@@ -68916,7 +70321,7 @@ async function runHold(argv) {
68916
70321
  const config2 = loadRuntimeConfig();
68917
70322
  const paths = runtimePaths(config2.stateDir);
68918
70323
  const log = __using(_stack, openFileLog(
68919
- (0, import_node_path70.join)(paths.logs, `holder-${launch.value.conversationId}.jsonl`),
70324
+ (0, import_node_path71.join)(paths.logs, `holder-${launch.value.conversationId}.jsonl`),
68920
70325
  config2.logLevel,
68921
70326
  systemClock
68922
70327
  ));
@@ -68927,15 +70332,26 @@ async function runHold(argv) {
68927
70332
  );
68928
70333
  const transport = __using(_stack, createHttpTransport());
68929
70334
  const access7 = await machineAccess(paths, log, launch.value.conversationId, transport);
70335
+ const credentialPath = (0, import_node_path71.join)(paths.tmp, "mcp", `${launch.value.conversationId}.json`);
70336
+ const managedMcp = __using(_stack, access7.managedMcp === void 0 ? void 0 : createHelperMcpAccess({
70337
+ managedMcp: access7.managedMcp,
70338
+ conversationId: launch.value.conversationId,
70339
+ credentialPath
70340
+ }), true);
70341
+ const providerEnvironment2 = access7.managedMcp === void 0 ? cliEnvironment : {
70342
+ ...cliEnvironment,
70343
+ [ALAN_MCP_URL_ENV]: access7.managedMcp.url,
70344
+ [ALAN_MCP_CREDENTIAL_FILE_ENV]: credentialPath
70345
+ };
68930
70346
  await runHolder({
68931
70347
  launch: launch.value,
68932
70348
  driver: createProviderDrivers({
68933
- cliEnvironment,
70349
+ cliEnvironment: providerEnvironment2,
68934
70350
  defaultCwd: process.cwd(),
68935
70351
  timings: config2.sessionTimings,
68936
70352
  log,
68937
- codexCredentials: access7.codexCredentials,
68938
- ...access7.managedMcp === void 0 ? {} : { managedMcp: access7.managedMcp }
70353
+ ...managedMcp === void 0 ? {} : { managedMcp },
70354
+ codexCredentials: access7.codexCredentials
68939
70355
  }),
68940
70356
  clock: systemClock,
68941
70357
  log,
@@ -68950,12 +70366,13 @@ async function runHold(argv) {
68950
70366
  } catch (_) {
68951
70367
  var _error = _, _hasError = true;
68952
70368
  } finally {
68953
- __callDispose(_stack, _error, _hasError);
70369
+ var _promise2 = __callDispose(_stack, _error, _hasError);
70370
+ _promise2 && await _promise2;
68954
70371
  }
68955
70372
  }
68956
70373
 
68957
70374
  // src/cli/commands/hook.ts
68958
- var import_node_path71 = require("path");
70375
+ var import_node_path72 = require("path");
68959
70376
  var RUNTIME_ANSWER_MS = 2e3;
68960
70377
  var DEBUG_VARIABLE = "ALAN_HOOK_DEBUG";
68961
70378
  function flag(argv, name) {
@@ -68987,7 +70404,7 @@ async function forwardHook(argv, io) {
68987
70404
  return "transcript outside provider root";
68988
70405
  }
68989
70406
  const verdict = await io.send(
68990
- (0, import_node_path71.join)(io.stateDir, LOCAL_API_DISCOVERY_FILE),
70407
+ (0, import_node_path72.join)(io.stateDir, LOCAL_API_DISCOVERY_FILE),
68991
70408
  hookSignal,
68992
70409
  AbortSignal.timeout(RUNTIME_ANSWER_MS)
68993
70410
  );
@@ -69023,7 +70440,7 @@ async function runHook(argv, overrides = {}) {
69023
70440
  }
69024
70441
 
69025
70442
  // src/cli/commands/ingestion-hooks.ts
69026
- var import_promises69 = require("fs/promises");
70443
+ var import_promises71 = require("fs/promises");
69027
70444
  var CODEX_TRUST_NOTE = "Codex runs new hooks only after you review them: open /hooks in Codex.";
69028
70445
  function isAction(value2) {
69029
70446
  return value2 === "enable" || value2 === "disable" || value2 === "status";
@@ -69046,7 +70463,7 @@ function errorMessage2(error61) {
69046
70463
  return error61 instanceof Error ? error61.message : String(error61);
69047
70464
  }
69048
70465
  async function exists5(path4) {
69049
- return (0, import_promises69.access)(path4).then(
70466
+ return (0, import_promises71.access)(path4).then(
69050
70467
  () => true,
69051
70468
  () => false
69052
70469
  );
@@ -69149,10 +70566,10 @@ async function runIntegrationsCommand(argv) {
69149
70566
  }
69150
70567
 
69151
70568
  // src/cli/commands/legacy.ts
69152
- var import_node_path73 = require("path");
70569
+ var import_node_path74 = require("path");
69153
70570
 
69154
70571
  // src/cli/commands/setup.ts
69155
- var import_node_path72 = require("path");
70572
+ var import_node_path73 = require("path");
69156
70573
  init_zod();
69157
70574
 
69158
70575
  // src/cli/legacy.ts
@@ -69234,7 +70651,7 @@ async function grantFileCredential(argv, grantPath, ctx, deps) {
69234
70651
  return enrollFromGrantFile({
69235
70652
  paths: ctx.paths,
69236
70653
  storeKind: credentialStoreFlag(argv) ?? ctx.config.credentialStore,
69237
- grantPath: (0, import_node_path72.resolve)(grantPath),
70654
+ grantPath: (0, import_node_path73.resolve)(grantPath),
69238
70655
  clock: deps.clock,
69239
70656
  access: ctx.access
69240
70657
  });
@@ -69310,7 +70727,7 @@ async function runSetup(argv, signal) {
69310
70727
  var _stack = [];
69311
70728
  try {
69312
70729
  const ctx = cliContext();
69313
- const log = __using(_stack, openFileLog((0, import_node_path72.join)(ctx.paths.logs, "cli.jsonl"), ctx.config.logLevel, systemClock));
70730
+ const log = __using(_stack, openFileLog((0, import_node_path73.join)(ctx.paths.logs, "cli.jsonl"), ctx.config.logLevel, systemClock));
69314
70731
  const result = await setupMachine(argv, ctx, {
69315
70732
  enrollment: (apiUrl) => createEnrollmentClient({ apiUrl }),
69316
70733
  isProcessAlive,
@@ -69393,7 +70810,7 @@ async function runToken(argv, signal) {
69393
70810
  );
69394
70811
  }
69395
70812
  const ctx = cliContext();
69396
- const log = __using(_stack, openFileLog((0, import_node_path73.join)(ctx.paths.logs, "cli.jsonl"), ctx.config.logLevel, systemClock));
70813
+ const log = __using(_stack, openFileLog((0, import_node_path74.join)(ctx.paths.logs, "cli.jsonl"), ctx.config.logLevel, systemClock));
69397
70814
  const result = await rotateMachineCredential(ctx, { clock: systemClock, log, signal });
69398
70815
  process.stdout.write(`${rotationMessage(result)}
69399
70816
  `);
@@ -69405,8 +70822,8 @@ async function runToken(argv, signal) {
69405
70822
  }
69406
70823
 
69407
70824
  // src/cli/commands/logout.ts
69408
- var import_promises70 = require("fs/promises");
69409
- var import_node_path74 = require("path");
70825
+ var import_promises72 = require("fs/promises");
70826
+ var import_node_path75 = require("path");
69410
70827
  init_runtime_v2();
69411
70828
  var RUNTIME_EXIT_WAIT_MS = 35e3;
69412
70829
  var TURN_END_WAIT_MS = 3e4;
@@ -69465,9 +70882,9 @@ async function stopHolder(launch, deps, outcome2) {
69465
70882
  }
69466
70883
  async function stopHeldRuns(ctx, deps, outcome2 = "aborted") {
69467
70884
  const stopped = [];
69468
- for (const name of await (0, import_promises70.readdir)(ctx.paths.sessions).catch(() => [])) {
70885
+ for (const name of await (0, import_promises72.readdir)(ctx.paths.sessions).catch(() => [])) {
69469
70886
  const launch = await readJsonFile(
69470
- (0, import_node_path74.join)(ctx.paths.sessions, name, "launch.json"),
70887
+ (0, import_node_path75.join)(ctx.paths.sessions, name, "launch.json"),
69471
70888
  holderLaunchSchema
69472
70889
  );
69473
70890
  if (launch.kind !== "ok") continue;
@@ -69504,13 +70921,13 @@ async function forgetMachineLocally(ctx) {
69504
70921
  const machine = await readMachineFile(ctx.paths);
69505
70922
  if (machine === null) return;
69506
70923
  await credentialStoreFor(ctx.paths, machine.credentialStore, ctx.access).clear();
69507
- await (0, import_promises70.rm)(ctx.paths.machine, { force: true });
70924
+ await (0, import_promises72.rm)(ctx.paths.machine, { force: true });
69508
70925
  }
69509
70926
  async function runLogout(argv, signal) {
69510
70927
  var _stack = [];
69511
70928
  try {
69512
70929
  const ctx = cliContext();
69513
- const log = __using(_stack, openFileLog((0, import_node_path74.join)(ctx.paths.logs, "cli.jsonl"), ctx.config.logLevel, systemClock));
70930
+ const log = __using(_stack, openFileLog((0, import_node_path75.join)(ctx.paths.logs, "cli.jsonl"), ctx.config.logLevel, systemClock));
69514
70931
  const result = await logoutMachine(argv, ctx, {
69515
70932
  api: (apiUrl, accessToken) => createApiClient({ apiUrl, accessToken }),
69516
70933
  stopHeldRuns,
@@ -69527,7 +70944,8 @@ async function runLogout(argv, signal) {
69527
70944
  }
69528
70945
 
69529
70946
  // src/cli/commands/run.ts
69530
- var import_node_path78 = require("path");
70947
+ var import_node_fs23 = require("fs");
70948
+ var import_node_path79 = require("path");
69531
70949
 
69532
70950
  // src/local-api/app-attachments.ts
69533
70951
  function createAppAttachments(clock) {
@@ -69561,7 +70979,9 @@ function createAppAttachments(clock) {
69561
70979
  // src/local-api/run-appends.ts
69562
70980
  function createRunAppends() {
69563
70981
  const waiters = /* @__PURE__ */ new Map();
70982
+ const listeners = /* @__PURE__ */ new Set();
69564
70983
  const wake = (runId) => {
70984
+ for (const listener of listeners) listener(runId);
69565
70985
  const pending = waiters.get(runId);
69566
70986
  if (pending === void 0) return;
69567
70987
  waiters.delete(runId);
@@ -69569,8 +70989,17 @@ function createRunAppends() {
69569
70989
  };
69570
70990
  return {
69571
70991
  notify: wake,
70992
+ subscribe: (listener) => {
70993
+ listeners.add(listener);
70994
+ return {
70995
+ [Symbol.dispose]: () => {
70996
+ listeners.delete(listener);
70997
+ }
70998
+ };
70999
+ },
69572
71000
  notifyAll: () => {
69573
71001
  for (const runId of [...waiters.keys()]) wake(runId);
71002
+ for (const listener of listeners) listener(null);
69574
71003
  },
69575
71004
  nextAppend: (runId, signal) => {
69576
71005
  if (signal.aborted) return Promise.resolve();
@@ -69592,18 +71021,18 @@ function createRunAppends() {
69592
71021
  }
69593
71022
 
69594
71023
  // src/local-api/server.ts
69595
- var import_node_crypto33 = require("crypto");
69596
- var import_promises71 = require("fs/promises");
71024
+ var import_node_crypto34 = require("crypto");
71025
+ var import_promises73 = require("fs/promises");
69597
71026
  var import_node_http4 = require("http");
69598
- var import_node_path75 = require("path");
71027
+ var import_node_path76 = require("path");
69599
71028
 
69600
71029
  // src/local-api/guard.ts
69601
- var import_node_crypto32 = require("crypto");
71030
+ var import_node_crypto33 = require("crypto");
69602
71031
  var ALLOWED = { kind: "allowed" };
69603
71032
  function tokenMatches2(expected, header) {
69604
71033
  if (header === void 0 || !header.startsWith("Bearer ")) return false;
69605
71034
  const presented = Buffer.from(header.slice("Bearer ".length));
69606
- return presented.length === expected.length && (0, import_node_crypto32.timingSafeEqual)(presented, expected);
71035
+ return presented.length === expected.length && (0, import_node_crypto33.timingSafeEqual)(presented, expected);
69607
71036
  }
69608
71037
  function isBrowserReachable(req, allowedHosts) {
69609
71038
  if (req.headers.origin !== void 0 || req.headers.referer !== void 0) return true;
@@ -69711,6 +71140,249 @@ function requestSignal(res) {
69711
71140
  init_runtime_v2();
69712
71141
  init_zod();
69713
71142
 
71143
+ // src/local-api/conversation-messages.ts
71144
+ init_acp();
71145
+ init_runtime_v2();
71146
+ function applyLogLine(line, assistantMessageId, state) {
71147
+ const raw = JSON.parse(line);
71148
+ const record2 = runLogRecordSchema.safeParse(raw);
71149
+ if (!record2.success) return null;
71150
+ const kind = record2.data.update.sessionUpdate;
71151
+ if (isRunLifecycleKind(kind)) {
71152
+ const lifecycle = runLifecycleUpdateSchema.parse(record2.data.update);
71153
+ if (lifecycle.sessionUpdate === "_alan/run.accepted") {
71154
+ state.state = "running";
71155
+ return false;
71156
+ }
71157
+ const ended = lifecycle.sessionUpdate === "_alan/run.ended";
71158
+ applySessionEvent(state, {
71159
+ seq: record2.data.seq,
71160
+ at: record2.data.at,
71161
+ update: {
71162
+ sessionUpdate: "state_update",
71163
+ state: ended ? "idle" : "running",
71164
+ ...ended && {
71165
+ stopReason: lifecycle.outcome === "aborted" || lifecycle.outcome === "interrupted" ? "cancelled" : "end_turn"
71166
+ }
71167
+ }
71168
+ });
71169
+ return ended;
71170
+ }
71171
+ const event = scopeTranscriptEvent({ ...record2.data, turnId: assistantMessageId });
71172
+ if (!event) return null;
71173
+ applySessionEvent(state, event);
71174
+ return false;
71175
+ }
71176
+ function applyLogChunk(text2, assistantMessageId, state) {
71177
+ let ended = false;
71178
+ for (const line of text2.trimEnd().split("\n")) {
71179
+ const applied = applyLogLine(line, assistantMessageId, state);
71180
+ if (applied === null) throw new Error("Invalid local transcript record");
71181
+ if (applied) ended = true;
71182
+ }
71183
+ return ended;
71184
+ }
71185
+ async function openLocalTurnProjection(runsDir, runId, conversationId, ordinal) {
71186
+ const paths = runDirectory(runsDir, runId);
71187
+ const meta3 = await readRunMeta(paths.meta);
71188
+ if (!meta3?.userMessage || !meta3.assistantMessage || meta3.conversationId !== conversationId || meta3.userMessage.turnOrdinal !== ordinal)
71189
+ return null;
71190
+ const assistantMessageId = meta3.assistantMessage.id;
71191
+ const state = emptyTranscript();
71192
+ const promptAt = Date.parse(meta3.userMessage.createdAt);
71193
+ applySessionEvent(state, {
71194
+ seq: 0,
71195
+ at: Number.isFinite(promptAt) ? promptAt : 0,
71196
+ update: {
71197
+ sessionUpdate: "user_message",
71198
+ messageId: meta3.userMessage.id,
71199
+ content: [{ type: "text", text: meta3.userMessage.content }],
71200
+ _meta: {
71201
+ ...meta3.userMessage.clientMessageId ? { "alan.dev/clientMessageId": meta3.userMessage.clientMessageId } : {},
71202
+ ...meta3.agentMode ? { "alan.dev/agentMode": meta3.agentMode } : {},
71203
+ ...meta3.userMessage.attachmentIds?.length ? { "alan.dev/attachmentIds": meta3.userMessage.attachmentIds } : {}
71204
+ }
71205
+ }
71206
+ });
71207
+ const reader = await openRunLogReader(paths.log).catch((error61) => {
71208
+ if (error61.code === "ENOENT") return null;
71209
+ throw error61;
71210
+ });
71211
+ if (!reader) return null;
71212
+ let offset = toByteOffset(0);
71213
+ let ended = false;
71214
+ let prepared;
71215
+ const decoder3 = new TextDecoder();
71216
+ return {
71217
+ runId,
71218
+ ordinal,
71219
+ read: async () => {
71220
+ const priorOffset = offset;
71221
+ for (; ; ) {
71222
+ const chunk = await reader.readFrom(offset, DEFAULT_RUN_LOG_LIMIT);
71223
+ if (chunk.bytes.length === 0) break;
71224
+ if (applyLogChunk(decoder3.decode(chunk.bytes), assistantMessageId, state)) ended = true;
71225
+ offset = chunk.to;
71226
+ }
71227
+ if (offset === priorOffset && prepared) return prepared;
71228
+ if (ended) state.state = "idle";
71229
+ prepared = { ...conversationTurnView(ordinal, snapshotTranscriptState(state)), markdown: "" };
71230
+ return prepared;
71231
+ },
71232
+ [Symbol.asyncDispose]: async () => {
71233
+ await reader[Symbol.asyncDispose]();
71234
+ }
71235
+ };
71236
+ }
71237
+ async function projectLocalRun(runsDir, runId, conversationId, ordinal) {
71238
+ var _stack = [];
71239
+ try {
71240
+ const projection = __using(_stack, await openLocalTurnProjection(runsDir, runId, conversationId, ordinal), true);
71241
+ return projection ? await projection.read() : null;
71242
+ } catch (_) {
71243
+ var _error = _, _hasError = true;
71244
+ } finally {
71245
+ var _promise2 = __callDispose(_stack, _error, _hasError);
71246
+ _promise2 && await _promise2;
71247
+ }
71248
+ }
71249
+ async function readLocalConversationMessages(runsDir, conversationId, limit, before, projection) {
71250
+ const indexed = await readConversationRunIndex(runsDir, conversationId, before, limit + 1);
71251
+ const coverage = await readConversationIndexCoverage(runsDir, conversationId);
71252
+ if (coverage === null || before === void 0 && indexed[0]?.ordinal !== coverage.highestOrdinal)
71253
+ return null;
71254
+ if (before !== void 0 && indexed[0]?.nextOrdinal !== before) return null;
71255
+ if (indexed.some((entry, index) => index > 0 && entry.nextOrdinal !== indexed[index - 1].ordinal))
71256
+ return null;
71257
+ if (indexed.length < limit && indexed.at(-1)?.ordinal !== 0) return null;
71258
+ const selected = indexed.slice(0, limit);
71259
+ if (selected.length === 0) return null;
71260
+ const turns = await Promise.all(
71261
+ selected.map(
71262
+ (entry) => entry.runId === projection?.runId ? projection.read() : projectLocalRun(runsDir, entry.runId, conversationId, entry.ordinal)
71263
+ )
71264
+ );
71265
+ if (turns.some((turn) => turn === null)) return null;
71266
+ const completeTurns = turns.filter((turn) => turn !== null);
71267
+ return {
71268
+ turns: compactConversationMessageTurns(completeTurns, before === void 0),
71269
+ before: selected.at(-1)?.ordinal === 0 ? null : String(selected.at(-1)?.ordinal),
71270
+ revision: `local-${selected[0].runId}`,
71271
+ streamCursor: ""
71272
+ };
71273
+ }
71274
+
71275
+ // src/local-api/conversation-messages-stream.ts
71276
+ async function readChangedTurn(deps, conversationId, runId, slot) {
71277
+ const meta3 = await readRunMeta(runDirectory(deps.runsDir, runId).meta);
71278
+ if (meta3?.conversationId !== conversationId || meta3.userMessage?.turnOrdinal == null) return null;
71279
+ if (slot.current?.ordinal === meta3.userMessage.turnOrdinal && slot.current.runId !== runId) {
71280
+ const [latest] = await readConversationRunIndex(
71281
+ deps.runsDir,
71282
+ conversationId,
71283
+ meta3.userMessage.turnOrdinal + 1,
71284
+ 1
71285
+ );
71286
+ if (latest?.runId !== runId) return null;
71287
+ }
71288
+ if (slot.current && meta3.userMessage.turnOrdinal < slot.current.ordinal) {
71289
+ var _stack = [];
71290
+ try {
71291
+ const previous = __using(_stack, await openLocalTurnProjection(
71292
+ deps.runsDir,
71293
+ runId,
71294
+ conversationId,
71295
+ meta3.userMessage.turnOrdinal
71296
+ ), true);
71297
+ return previous ? await previous.read() : null;
71298
+ } catch (_) {
71299
+ var _error = _, _hasError = true;
71300
+ } finally {
71301
+ var _promise2 = __callDispose(_stack, _error, _hasError);
71302
+ _promise2 && await _promise2;
71303
+ }
71304
+ }
71305
+ if (slot.current?.runId !== runId) {
71306
+ const next = await openLocalTurnProjection(
71307
+ deps.runsDir,
71308
+ runId,
71309
+ conversationId,
71310
+ meta3.userMessage.turnOrdinal
71311
+ );
71312
+ await slot.current?.[Symbol.asyncDispose]();
71313
+ slot.current = next;
71314
+ }
71315
+ if (!slot.current) throw new Error("Local transcript metadata is incomplete");
71316
+ return slot.current.read();
71317
+ }
71318
+ async function streamLocalConversationMessages(deps, conversationId, limit, res, signal) {
71319
+ var _stack = [];
71320
+ try {
71321
+ const pending = /* @__PURE__ */ new Set();
71322
+ let wake;
71323
+ const slot = { current: null };
71324
+ const _subscription = __using(_stack, deps.appends.subscribe((runId) => {
71325
+ const changed = runId ?? slot.current?.runId;
71326
+ if (changed) pending.add(changed);
71327
+ wake?.();
71328
+ }));
71329
+ signal.addEventListener("abort", () => wake?.(), { once: true });
71330
+ try {
71331
+ const [newest] = await readConversationRunIndex(deps.runsDir, conversationId, void 0, 1);
71332
+ if (newest)
71333
+ slot.current = await openLocalTurnProjection(
71334
+ deps.runsDir,
71335
+ newest.runId,
71336
+ conversationId,
71337
+ newest.ordinal
71338
+ );
71339
+ let lastTurn = await slot.current?.read();
71340
+ const page = await readLocalConversationMessages(
71341
+ deps.runsDir,
71342
+ conversationId,
71343
+ limit,
71344
+ void 0,
71345
+ slot.current ?? void 0
71346
+ );
71347
+ if (!page) {
71348
+ sendError(res, 404, "not_found", "This computer has no complete local page");
71349
+ return;
71350
+ }
71351
+ startEventStream(res);
71352
+ await writeEvent(res, {
71353
+ name: "snapshot",
71354
+ id: page.revision,
71355
+ dataLines: [JSON.stringify(page)]
71356
+ });
71357
+ while (!signal.aborted) {
71358
+ if (pending.size === 0) {
71359
+ await new Promise((resolve12) => {
71360
+ wake = resolve12;
71361
+ if (signal.aborted || pending.size > 0) resolve12();
71362
+ });
71363
+ wake = void 0;
71364
+ }
71365
+ if (signal.aborted) return;
71366
+ await systemClock.sleep(50, signal);
71367
+ const changed = [...pending];
71368
+ pending.clear();
71369
+ for (const runId of changed) {
71370
+ const turn = await readChangedTurn(deps, conversationId, runId, slot);
71371
+ if (!turn || turn === lastTurn) continue;
71372
+ lastTurn = turn;
71373
+ await writeEvent(res, { name: "turn", id: `${runId}`, dataLines: [JSON.stringify(turn)] });
71374
+ }
71375
+ }
71376
+ } finally {
71377
+ await slot.current?.[Symbol.asyncDispose]();
71378
+ }
71379
+ } catch (_) {
71380
+ var _error = _, _hasError = true;
71381
+ } finally {
71382
+ __callDispose(_stack, _error, _hasError);
71383
+ }
71384
+ }
71385
+
69714
71386
  // src/local-api/request.ts
69715
71387
  async function readBody3(request2, schema) {
69716
71388
  const body = await readJsonBody(request2.req);
@@ -69909,6 +71581,11 @@ async function followRunLogRoute(deps, runId, url3, res, signal) {
69909
71581
 
69910
71582
  // src/local-api/routes.ts
69911
71583
  var RUN_PATH = /^\/v2\/runs\/([^/]+)\/(log|log\/stream|abort)$/;
71584
+ var CONVERSATION_MESSAGES_PATH = /^\/v2\/conversations\/([^/]+)\/messages(\/sse)?$/;
71585
+ var conversationMessagesQuerySchema = external_exports.object({
71586
+ limit: external_exports.coerce.number().int().min(1).max(100).default(10),
71587
+ before: external_exports.coerce.number().int().nonnegative().optional()
71588
+ });
69912
71589
  var emptyBodySchema = external_exports.object({});
69913
71590
  function activeRunIds(runs) {
69914
71591
  return runs.filter((run2) => run2.state !== "ended").map((run2) => run2.runId);
@@ -70155,6 +71832,41 @@ async function route(deps, request2) {
70155
71832
  }
70156
71833
  const match = RUN_PATH.exec(request2.url.pathname);
70157
71834
  if (match !== null) return routeRun(deps, request2, match);
71835
+ const conversationMatch = CONVERSATION_MESSAGES_PATH.exec(request2.url.pathname);
71836
+ if (conversationMatch !== null) {
71837
+ if (request2.req.method !== "GET") {
71838
+ sendError(request2.res, 405, "method_not_allowed", "Use GET");
71839
+ return;
71840
+ }
71841
+ const conversationId = conversationIdSchema.safeParse(conversationMatch[1]);
71842
+ const query = conversationMessagesQuerySchema.safeParse(
71843
+ Object.fromEntries(request2.url.searchParams)
71844
+ );
71845
+ if (!conversationId.success || !query.success) {
71846
+ sendError(request2.res, 400, "invalid_request", "Invalid conversation messages request");
71847
+ return;
71848
+ }
71849
+ if (conversationMatch[2])
71850
+ return streamLocalConversationMessages(
71851
+ deps,
71852
+ conversationId.data,
71853
+ query.data.limit,
71854
+ request2.res,
71855
+ request2.signal
71856
+ );
71857
+ const page = await readLocalConversationMessages(
71858
+ deps.runsDir,
71859
+ conversationId.data,
71860
+ query.data.limit,
71861
+ query.data.before
71862
+ );
71863
+ if (page === null) {
71864
+ sendError(request2.res, 404, "not_found", "This computer has no complete local page");
71865
+ return;
71866
+ }
71867
+ sendJson(request2.res, 200, page);
71868
+ return;
71869
+ }
70158
71870
  sendError(request2.res, 404, "not_found", "Not found");
70159
71871
  }
70160
71872
 
@@ -70204,6 +71916,15 @@ var REQUEST_TIMEOUT_MS8 = 1e4;
70204
71916
  var KEEP_ALIVE_TIMEOUT_MS = 2e3;
70205
71917
  var ACTION_TIMEOUT_MS = 3e4;
70206
71918
  var PROVIDER_INSTALL_TIMEOUT_MS = 10 * 6e4;
71919
+ function localRequestSignal(path4, closed) {
71920
+ if (path4.endsWith("/stream") || path4.endsWith("/sse")) return closed;
71921
+ return AbortSignal.any([
71922
+ closed,
71923
+ AbortSignal.timeout(
71924
+ path4 === LOCAL_API_ROUTES.providerInstall ? PROVIDER_INSTALL_TIMEOUT_MS : ACTION_TIMEOUT_MS
71925
+ )
71926
+ ]);
71927
+ }
70207
71928
  async function listenOnLoopback(server) {
70208
71929
  await new Promise((resolve12, reject) => {
70209
71930
  server.once("error", reject);
@@ -70248,7 +71969,7 @@ async function serveLocalApi(deps) {
70248
71969
  server.keepAliveTimeout = KEEP_ALIVE_TIMEOUT_MS;
70249
71970
  server.maxConnections = HARD_MAX_CONNECTIONS;
70250
71971
  const port = await listenOnLoopback(server);
70251
- const token = (0, import_node_crypto33.randomBytes)(32).toString("base64url");
71972
+ const token = (0, import_node_crypto34.randomBytes)(32).toString("base64url");
70252
71973
  const guard = createRequestGuard({ token, port, rateLimit: limits.rateLimit, clock });
70253
71974
  const appAttachments = createAppAttachments(clock);
70254
71975
  const routeDeps = {
@@ -70274,15 +71995,11 @@ async function serveLocalApi(deps) {
70274
71995
  inFlight += 1;
70275
71996
  const url3 = new URL(req.url ?? "/", `http://127.0.0.1:${port}`);
70276
71997
  const closed = requestSignal(res);
70277
- const signal = url3.pathname.endsWith("/stream") ? closed : AbortSignal.any([
70278
- closed,
70279
- AbortSignal.timeout(
70280
- url3.pathname === LOCAL_API_ROUTES.providerInstall ? PROVIDER_INSTALL_TIMEOUT_MS : ACTION_TIMEOUT_MS
70281
- )
70282
- ]);
71998
+ const signal = localRequestSignal(url3.pathname, closed);
70283
71999
  try {
70284
72000
  await route(routeDeps, { req, res, url: url3, signal });
70285
72001
  } catch (error61) {
72002
+ if (closed.aborted) return;
70286
72003
  log.warn("local_api.request_failed", { path: url3.pathname, error: error61 });
70287
72004
  sendError(res, 500, "internal", "The runtime could not complete the request");
70288
72005
  } finally {
@@ -70298,7 +72015,7 @@ async function serveLocalApi(deps) {
70298
72015
  startedAtMs,
70299
72016
  runtimeVersion: deps.runtimeVersion
70300
72017
  };
70301
- const discoveryPath = (0, import_node_path75.join)(deps.stateDir, LOCAL_API_DISCOVERY_FILE);
72018
+ const discoveryPath = (0, import_node_path76.join)(deps.stateDir, LOCAL_API_DISCOVERY_FILE);
70302
72019
  await writeJsonFileAtomic(discoveryPath, discovery);
70303
72020
  const followers = startMaintenance({
70304
72021
  everyMs: limits.refreshEveryMs,
@@ -70332,7 +72049,7 @@ async function serveLocalApi(deps) {
70332
72049
  await watchedStatus[Symbol.asyncDispose]();
70333
72050
  const current = await readJsonFile(discoveryPath, localApiDiscoverySchema);
70334
72051
  if (current.kind === "ok" && current.value.token === token) {
70335
- await (0, import_promises71.rm)(discoveryPath, { force: true });
72052
+ await (0, import_promises73.rm)(discoveryPath, { force: true });
70336
72053
  }
70337
72054
  await closeServer(server);
70338
72055
  log.info("local_api.closed", {});
@@ -70417,7 +72134,7 @@ function machineFeatureActions(deps) {
70417
72134
  }
70418
72135
 
70419
72136
  // src/cli/commands/machine-plane.ts
70420
- var import_node_path77 = require("path");
72137
+ var import_node_path78 = require("path");
70421
72138
 
70422
72139
  // src/link/index.ts
70423
72140
  init_runtime_v2();
@@ -74085,7 +75802,7 @@ function refusalFailure(refusal2) {
74085
75802
  }
74086
75803
 
74087
75804
  // src/link/probe.ts
74088
- var import_promises72 = require("dns/promises");
75805
+ var import_promises74 = require("dns/promises");
74089
75806
  var import_node_net5 = require("net");
74090
75807
  var import_node_tls2 = require("tls");
74091
75808
  var PROBE_TIMEOUT_MS4 = 5e3;
@@ -74121,7 +75838,7 @@ async function connectOnce(url3, clock) {
74121
75838
  }
74122
75839
  async function probeEndpoint(url3, clock) {
74123
75840
  try {
74124
- await (0, import_promises72.lookup)(url3.hostname);
75841
+ await (0, import_promises74.lookup)(url3.hostname);
74125
75842
  } catch (error61) {
74126
75843
  const reason = classifyTransportFailure(error61);
74127
75844
  return reason === "other" ? "dns" : reason;
@@ -74244,8 +75961,12 @@ function connectLink(options) {
74244
75961
  const hello = await options.hello(connectEpoch);
74245
75962
  const ack = await socket.timeout(HELLO_TIMEOUT_MS).emitWithAck("hello", hello);
74246
75963
  await ready;
74247
- if (connectEpoch !== epoch) return;
75964
+ if (connectEpoch !== epoch || !socket.connected) return;
74248
75965
  options.onHelloAck(helloAckSchema.parse(ack), connectEpoch);
75966
+ retry.attempt = 0;
75967
+ retry.credentialFailures = 0;
75968
+ setState({ kind: "connected", epoch: connectEpoch });
75969
+ log.info("link.connected", { epoch: connectEpoch });
74249
75970
  };
74250
75971
  const setState = (next) => {
74251
75972
  current = next;
@@ -74315,12 +76036,16 @@ function connectLink(options) {
74315
76036
  };
74316
76037
  socket.on("connect", () => {
74317
76038
  epoch += 1;
74318
- retry.attempt = 0;
74319
- retry.credentialFailures = 0;
76039
+ const connectEpoch = epoch;
74320
76040
  cancelRedial();
74321
- setState({ kind: "connected", epoch });
74322
- log.info("link.connected", { epoch });
74323
- greet(epoch).catch((error61) => log.warn("link.hello_failed", { epoch, error: error61 }));
76041
+ setState({ kind: "connecting", lastFailure: null });
76042
+ greet(connectEpoch).catch((error61) => {
76043
+ if (connectEpoch !== epoch || current.kind === "stopped" || !socket.connected) return;
76044
+ log.warn("link.hello_failed", { epoch: connectEpoch, error: error61 });
76045
+ recordTransportFailure("other", "The backend did not acknowledge this runtime");
76046
+ socket.disconnect();
76047
+ redialAfter(redialDelayMs(retry.attempt++));
76048
+ });
74324
76049
  });
74325
76050
  socket.on("disconnect", (reason) => {
74326
76051
  log.info("link.disconnected", { reason });
@@ -74374,7 +76099,7 @@ function connectLink(options) {
74374
76099
  void ready.then(() => answerModelsScan(raw, options.scanModels, log)).then((result) => ack(result));
74375
76100
  });
74376
76101
  const pushCapabilities = async (capabilities) => {
74377
- if (!socket.connected) return false;
76102
+ if (current.kind !== "connected" || !socket.connected) return false;
74378
76103
  try {
74379
76104
  const ack = await socket.timeout(CAPABILITIES_ACK_TIMEOUT_MS).emitWithAck("capabilities", capabilities);
74380
76105
  const parsed = capabilitiesAckSchema.safeParse(ack);
@@ -74423,9 +76148,9 @@ function planReconcile(desired, held) {
74423
76148
  }
74424
76149
 
74425
76150
  // src/reconciler/desired-sync.ts
74426
- var import_node_crypto34 = require("crypto");
76151
+ var import_node_crypto35 = require("crypto");
74427
76152
  function fingerprintOf(desired) {
74428
- return (0, import_node_crypto34.createHash)("sha256").update(JSON.stringify(desired)).digest("hex");
76153
+ return (0, import_node_crypto35.createHash)("sha256").update(JSON.stringify(desired)).digest("hex");
74429
76154
  }
74430
76155
  var FAILED_READ_RETRY_MS = 3e4;
74431
76156
  function createDesiredSync(deps) {
@@ -74562,7 +76287,7 @@ function createReconciler(host, lifecycle, log, signal) {
74562
76287
  }
74563
76288
 
74564
76289
  // src/uploader/index.ts
74565
- var import_promises73 = require("fs/promises");
76290
+ var import_promises75 = require("fs/promises");
74566
76291
  init_runtime_v2();
74567
76292
  init_zod();
74568
76293
  var RETRY_DELAYS_MS = [250, 500, 1e3, 2e3, 5e3, 1e4, 3e4];
@@ -74703,7 +76428,7 @@ function startUploader({ api, runsDir, clock, log }) {
74703
76428
  active.set(runId, task);
74704
76429
  };
74705
76430
  const sweep2 = async () => {
74706
- for (const name of await (0, import_promises73.readdir)(runsDir).catch(() => [])) {
76431
+ for (const name of await (0, import_promises75.readdir)(runsDir).catch(() => [])) {
74707
76432
  const runId = runIdSchema.safeParse(name);
74708
76433
  if (runId.success) run2(runId.data);
74709
76434
  }
@@ -74713,18 +76438,18 @@ function startUploader({ api, runsDir, clock, log }) {
74713
76438
  const dir = runDirectory(runsDir, runId);
74714
76439
  const progress = await readJsonFile(dir.upload, uploadProgressSchema);
74715
76440
  if (progress.kind !== "ok" || !progress.value.sealed) return false;
74716
- const sealedAt = (await (0, import_promises73.stat)(dir.upload)).mtimeMs;
76441
+ const sealedAt = (await (0, import_promises75.stat)(dir.upload)).mtimeMs;
74717
76442
  if (clock.now() - sealedAt < options.sealedForMs) return false;
74718
76443
  return (await readLastRecord(dir.log))?.update.sessionUpdate === "_alan/run.ended";
74719
76444
  };
74720
76445
  const prune = async (options) => {
74721
76446
  let removed = 0;
74722
- for (const name of await (0, import_promises73.readdir)(runsDir).catch(() => [])) {
76447
+ for (const name of await (0, import_promises75.readdir)(runsDir).catch(() => [])) {
74723
76448
  const runId = runIdSchema.safeParse(name);
74724
76449
  if (!runId.success) continue;
74725
76450
  try {
74726
76451
  if (!await isPrunable(runId.data, options)) continue;
74727
- await (0, import_promises73.rm)(runDirectory(runsDir, runId.data).dir, { recursive: true, force: true });
76452
+ await (0, import_promises75.rm)(runDirectory(runsDir, runId.data).dir, { recursive: true, force: true });
74728
76453
  removed += 1;
74729
76454
  } catch (error61) {
74730
76455
  log.warn("upload.prune_failed", { runId: runId.data, error: error61 });
@@ -74906,12 +76631,12 @@ async function startMachineNativeIngest(deps) {
74906
76631
  }
74907
76632
 
74908
76633
  // src/cli/commands/run-updates.ts
74909
- var import_node_path76 = require("path");
76634
+ var import_node_path77 = require("path");
74910
76635
  init_runtime_v2();
74911
76636
  var UPDATE_CHECK_EVERY_MS = 6 * 60 * 60 * 1e3;
74912
76637
  var DEFERRED_RETRY_MS = 5 * 60 * 1e3;
74913
76638
  function isInstalledBundle(layout, bundlePath) {
74914
- return (0, import_node_path76.resolve)((0, import_node_path76.dirname)((0, import_node_path76.dirname)(bundlePath))) === (0, import_node_path76.resolve)(layout.versions);
76639
+ return (0, import_node_path77.resolve)((0, import_node_path77.dirname)((0, import_node_path77.dirname)(bundlePath))) === (0, import_node_path77.resolve)(layout.versions);
74915
76640
  }
74916
76641
  async function settleUpgradeOnStart({
74917
76642
  layout,
@@ -75018,7 +76743,7 @@ function startRuntimeUpdates(options) {
75018
76743
  layout,
75019
76744
  release: npmRelease,
75020
76745
  tarball: await options.downloader.download(npmRelease.dist.tarball, signal),
75021
- tmpDir: (0, import_node_path76.join)(layout.root, ".downloads")
76746
+ tmpDir: (0, import_node_path77.join)(layout.root, ".downloads")
75022
76747
  });
75023
76748
  await lifecycle.exclusive("upgrade", async () => {
75024
76749
  await recordPendingUpgrade(layout, currentVersion2, version2, clock.now());
@@ -75243,7 +76968,7 @@ async function startMachinePlane(deps) {
75243
76968
  [ALAN_MANAGED_SESSION_ENV]: "1"
75244
76969
  },
75245
76970
  cwd: paths.stateDir,
75246
- outputPath: (0, import_node_path77.join)(paths.logs, "holders.log")
76971
+ outputPath: (0, import_node_path78.join)(paths.logs, "holders.log")
75247
76972
  },
75248
76973
  deps.holderIsolation
75249
76974
  );
@@ -75474,7 +77199,7 @@ async function startMachinePlane(deps) {
75474
77199
  git: createGitRunner({ env: cliEnvironment }),
75475
77200
  clock,
75476
77201
  log,
75477
- dir: (0, import_node_path77.join)(paths.stateDir, "checkout-freshness")
77202
+ dir: (0, import_node_path78.join)(paths.stateDir, "checkout-freshness")
75478
77203
  },
75479
77204
  stopped.signal
75480
77205
  );
@@ -75768,23 +77493,28 @@ function lockWaitMs(argv) {
75768
77493
  }
75769
77494
  async function openManagedProviders(config2, paths) {
75770
77495
  const providerEnv = readCliEnvironment();
75771
- const npmPath = config2.providerToolchain?.node ?? await resolveCommandOnPath("npm", providerEnv, process.platform);
75772
- const npmOptions = npmPath === null ? null : {
77496
+ const bundledNpm = (0, import_node_path79.join)((0, import_node_path79.dirname)(process.execPath), "npm", "bin", "npm-cli.js");
77497
+ const providerToolchain = config2.providerToolchain ?? (process.platform === "win32" && (0, import_node_fs23.existsSync)(bundledNpm) ? { node: process.execPath, npmCli: bundledNpm } : null);
77498
+ const npmPath = providerToolchain?.node ?? await resolveCommandOnPath("npm", providerEnv, process.platform);
77499
+ const npmOptions = npmPath === null || process.platform === "win32" && providerToolchain === null ? null : {
75773
77500
  command: npmPath,
75774
- ...config2.providerToolchain === null ? {} : { argsBeforeNpm: [config2.providerToolchain.npmCli] },
77501
+ ...providerToolchain === null ? {} : { argsBeforeNpm: [providerToolchain.npmCli] },
75775
77502
  env: providerEnv
75776
77503
  };
75777
- const providerNodeDir = config2.providerToolchain?.node === void 0 ? void 0 : (0, import_node_path78.join)(config2.providerToolchain.node, "..");
75778
- const providerProbeEnv = providerNodeDir === void 0 ? providerEnv : { ...providerEnv, PATH: `${providerNodeDir}:${providerEnv.PATH ?? ""}` };
77504
+ const providerNodeDir = providerToolchain?.node === void 0 ? void 0 : (0, import_node_path79.dirname)(providerToolchain.node);
77505
+ const probeEnv = providerNodeDir === void 0 ? providerEnv : {
77506
+ ...providerEnv,
77507
+ PATH: `${providerNodeDir}${pathDelimiter(process.platform)}${envValue(providerEnv, "PATH")}`
77508
+ };
77509
+ const canonicalProbeEnv = process.platform === "win32" ? canonicalWindowsEnvironment(probeEnv) : probeEnv;
77510
+ const unavailable = async () => {
77511
+ throw new Error("Provider installer is unavailable on this computer");
77512
+ };
75779
77513
  const managed = createManagedProviderClis({
75780
- root: (0, import_node_path78.join)(paths.stateDir, "provider-clis"),
75781
- resolveVersion: npmOptions === null ? async () => {
75782
- throw new Error("Provider installer is unavailable on this computer");
75783
- } : createNpmVersionResolver(npmOptions),
75784
- installPackage: npmOptions === null ? async () => {
75785
- throw new Error("Provider installer is unavailable on this computer");
75786
- } : createNpmPackageInstaller(npmOptions),
75787
- probe: (executable, backendKind) => probeManagedProvider(executable, backendKind, providerProbeEnv)
77514
+ root: (0, import_node_path79.join)(paths.stateDir, "provider-clis"),
77515
+ resolveVersion: npmOptions === null ? unavailable : createNpmVersionResolver(npmOptions),
77516
+ installPackage: npmOptions === null ? unavailable : createNpmPackageInstaller(npmOptions),
77517
+ probe: (executable, backendKind) => probeManagedProvider(executable, backendKind, canonicalProbeEnv)
75788
77518
  });
75789
77519
  await managed.load();
75790
77520
  return { managed, providerNodeDir };
@@ -75813,7 +77543,7 @@ async function runService(argv, stop, restart = new AbortController().signal) {
75813
77543
  waitMs: lockWaitMs(argv),
75814
77544
  signal: stop
75815
77545
  }));
75816
- const log = __using(_stack, openFileLog((0, import_node_path78.join)(paths.logs, "runtime.jsonl"), config2.logLevel, clock));
77546
+ const log = __using(_stack, openFileLog((0, import_node_path79.join)(paths.logs, "runtime.jsonl"), config2.logLevel, clock));
75817
77547
  const lifecycle = createLifecycleQueue({ clock, log });
75818
77548
  const install2 = installLayout(config2.installDir, config2.profile);
75819
77549
  const bundlePath = process.argv[1] ?? "";
@@ -75847,7 +77577,7 @@ async function runService(argv, stop, restart = new AbortController().signal) {
75847
77577
  openCliEnvironment({
75848
77578
  env: readCliEnvironment(),
75849
77579
  platform: process.platform,
75850
- lastKnownGoodFile: (0, import_node_path78.join)(paths.stateDir, "login-path.json"),
77580
+ lastKnownGoodFile: (0, import_node_path79.join)(paths.stateDir, "login-path.json"),
75851
77581
  clock,
75852
77582
  decorate: (env) => withPackagedAlanCodeEngine(env, bundlePath, process.platform)
75853
77583
  })
@@ -76024,17 +77754,17 @@ async function runServiceCommand(argv, ctx = cliContext()) {
76024
77754
  }
76025
77755
 
76026
77756
  // src/cli/commands/upgrade.ts
76027
- var import_promises74 = require("fs/promises");
76028
- var import_node_path79 = require("path");
77757
+ var import_promises76 = require("fs/promises");
77758
+ var import_node_path80 = require("path");
76029
77759
  function isNotNewer(version2, installed) {
76030
77760
  return installed !== null && isReleaseVersion(version2) && isReleaseVersion(installed) && compareVersions(version2, installed) <= 0;
76031
77761
  }
76032
77762
  async function installFromSource(source) {
76033
77763
  const { layout, from, ifNewer } = source;
76034
- const isTarball = (await (0, import_promises74.stat)(from)).isFile();
76035
- const downloads = (0, import_node_path79.join)(layout.root, ".downloads");
76036
- if (isTarball) await (0, import_promises74.mkdir)(downloads, { recursive: true, mode: 448 });
76037
- const scratch = isTarball ? await (0, import_promises74.mkdtemp)((0, import_node_path79.join)(downloads, "upgrade-")) : null;
77764
+ const isTarball = (await (0, import_promises76.stat)(from)).isFile();
77765
+ const downloads = (0, import_node_path80.join)(layout.root, ".downloads");
77766
+ if (isTarball) await (0, import_promises76.mkdir)(downloads, { recursive: true, mode: 448 });
77767
+ const scratch = isTarball ? await (0, import_promises76.mkdtemp)((0, import_node_path80.join)(downloads, "upgrade-")) : null;
76038
77768
  try {
76039
77769
  const sourceDir = scratch === null ? from : await extractPackageTarball(from, scratch);
76040
77770
  const version2 = await readPackageVersion(sourceDir);
@@ -76042,7 +77772,7 @@ async function installFromSource(source) {
76042
77772
  if (ifNewer && isNotNewer(version2, installed)) return { kind: "skipped", version: version2, installed };
76043
77773
  return { kind: "installed", ...await installVersion(layout, sourceDir) };
76044
77774
  } finally {
76045
- if (scratch !== null) await (0, import_promises74.rm)(scratch, { recursive: true, force: true });
77775
+ if (scratch !== null) await (0, import_promises76.rm)(scratch, { recursive: true, force: true });
76046
77776
  }
76047
77777
  }
76048
77778
  async function runUpgrade(argv) {
@@ -76054,7 +77784,7 @@ async function runUpgrade(argv) {
76054
77784
  const layout = installLayout(config2.installDir, config2.profile);
76055
77785
  const outcome2 = await installFromSource({
76056
77786
  layout,
76057
- from: (0, import_node_path79.resolve)(from),
77787
+ from: (0, import_node_path80.resolve)(from),
76058
77788
  ifNewer: hasFlag(argv, "--if-newer")
76059
77789
  });
76060
77790
  if (outcome2.kind === "skipped") {