@alan-ai-hq/agent-manager-linux-arm64 0.1.134 → 0.1.135

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 +1876 -1194
  2. package/alan-holder.cjs +926 -583
  3. package/package.json +1 -1
package/alan-holder.cjs CHANGED
@@ -20379,7 +20379,7 @@ function runProviderCredentialPath(runId) {
20379
20379
  function runAttachmentPath(runId, attachmentId) {
20380
20380
  return `/public/machines/me/runs/${encodeURIComponent(runId)}/attachments/${encodeURIComponent(attachmentId)}`;
20381
20381
  }
20382
- var machineEndpointsSchema, machineCredentialGrantSchema, MACHINE_PATHS, machinePlatformSchema, machineRegisterRequestSchema, machineRenewRequestSchema, machineRenewReusedSchema, deviceAuthorizationSchema, machineDeviceAuthorizationRequestSchema, machineDeviceTokenRequestSchema, machineDeviceTokenSchema, DEVICE_TOKEN_ERRORS, machineDeviceTokenErrorSchema, machineMcpCredentialRequestSchema, machineMcpCredentialSchema, runtimeReleaseSchema, machineSiblingSchema, MACHINE_SIBLINGS_LIMIT, machineSiblingsResponseSchema, runProviderCredentialSchema;
20382
+ var machineEndpointsSchema, machineCredentialGrantSchema, MACHINE_PATHS, machinePlatformSchema, machineRegisterRequestSchema, machineEnrollRequestSchema, machineRenewRequestSchema, machineRenewReusedSchema, deviceAuthorizationSchema, machineDeviceAuthorizationRequestSchema, machineDeviceTokenRequestSchema, machineDeviceTokenSchema, DEVICE_TOKEN_ERRORS, machineDeviceTokenErrorSchema, machineMcpCredentialRequestSchema, machineMcpCredentialSchema, runtimeReleaseSchema, machineSiblingSchema, MACHINE_SIBLINGS_LIMIT, machineSiblingsResponseSchema, runProviderCredentialSchema;
20383
20383
  var init_machine_identity = __esm({
20384
20384
  "../shared/dist/runtime-v2/machine-identity.js"() {
20385
20385
  "use strict";
@@ -20399,6 +20399,8 @@ var init_machine_identity = __esm({
20399
20399
  MACHINE_PATHS = {
20400
20400
  /** POST with a one-time setup grant (what `install --setup-token` / `setup` send). */
20401
20401
  register: "/public/machines/register",
20402
+ /** POST with a cloud sandbox's one-time enrollment code from `ALAN_RUNTIME_ENROLLMENT_CODE`. */
20403
+ enroll: "/public/machines/enroll",
20402
20404
  /** POST with the current renewal token; the response carries a new one and the old dies. */
20403
20405
  renew: "/public/machines/me/renew",
20404
20406
  /** POST by the machine itself on logout/uninstall. */
@@ -20435,6 +20437,7 @@ var init_machine_identity = __esm({
20435
20437
  /** Chosen by the install before its first registration, so a credential lost locally still maps to its row. */
20436
20438
  installationId: external_exports.guid().optional()
20437
20439
  });
20440
+ machineEnrollRequestSchema = external_exports.object({ enrollmentCode: external_exports.string().min(1) });
20438
20441
  machineRenewRequestSchema = external_exports.object({ renewalToken: external_exports.string().min(1) });
20439
20442
  machineRenewReusedSchema = external_exports.object({
20440
20443
  error: external_exports.literal("renewal_token_reused"),
@@ -21349,11 +21352,12 @@ function isReadOnlyAgent(agentId) {
21349
21352
  const agent = getBuiltinAgentDefinition(agentId);
21350
21353
  return !agent.capabilities.canEditFiles;
21351
21354
  }
21352
- var COORDINATOR_PROMPT, PM_PROMPT, GENERAL_PROMPT, REVIEW_PROMPT, DESIGNER_PROMPT, BUILTIN_AGENT_DEFINITIONS, BUILTIN_AGENT_BY_ID, LEGACY_AGENT_ID_ALIASES;
21355
+ var SETUP_AGENT_ID, COORDINATOR_PROMPT, PM_PROMPT, GENERAL_PROMPT, REVIEW_PROMPT, DESIGNER_PROMPT, BUILTIN_AGENT_DEFINITIONS, BUILTIN_AGENT_BY_ID, LEGACY_AGENT_ID_ALIASES;
21353
21356
  var init_agent_definitions = __esm({
21354
21357
  "../shared/dist/agent/agent-definitions.js"() {
21355
21358
  "use strict";
21356
21359
  init_task_duplicate();
21360
+ SETUP_AGENT_ID = "setup";
21357
21361
  COORDINATOR_PROMPT = `## You are the Orchestrator
21358
21362
 
21359
21363
  You are the **Orchestrator** for this task or session. When asked "who are you?", "what agent are you?", "are you the coordinator?", "are you the orchestrator?", or anything similar \u2014 identify yourself plainly as the Orchestrator. Do not say "I'm Alan" alone; say "I'm the Orchestrator (an Alan agent profile)."
@@ -21647,6 +21651,21 @@ For any UI or design work, read and follow the \`uiux\` skill in \`.agents/skill
21647
21651
  canManageSubtasks: false
21648
21652
  },
21649
21653
  systemPrompt: DESIGNER_PROMPT
21654
+ },
21655
+ {
21656
+ id: SETUP_AGENT_ID,
21657
+ name: "Setup Agent",
21658
+ description: "Sets up and verifies cloud environments",
21659
+ iconKey: "hard-drive",
21660
+ defaultMode: "agent",
21661
+ capabilities: {
21662
+ canEditFiles: true,
21663
+ canRunCommands: true,
21664
+ canCreateArtifacts: true,
21665
+ canStartSessions: false,
21666
+ canManageSubtasks: false
21667
+ },
21668
+ systemPrompt: ""
21650
21669
  }
21651
21670
  ];
21652
21671
  BUILTIN_AGENT_BY_ID = new Map(BUILTIN_AGENT_DEFINITIONS.map((agent) => [agent.id, agent]));
@@ -21657,9 +21676,7 @@ For any UI or design work, read and follow the \`uiux\` skill in \`.agents/skill
21657
21676
  implementer: "general",
21658
21677
  implementor: "general",
21659
21678
  "ui-designer": "designer",
21660
- verifier: "general",
21661
- // Former reserved Setup Agent profile \u2014 env setup is now a normal session kickoff.
21662
- setup: "general"
21679
+ verifier: "general"
21663
21680
  };
21664
21681
  }
21665
21682
  });
@@ -21679,21 +21696,9 @@ var init_browser_surface = __esm({
21679
21696
  });
21680
21697
 
21681
21698
  // ../shared/dist/agent/gated-mcp-tools.js
21682
- var CODE_INDEX_MCP_TOOLS, CONTEXT_GRAPH_MCP_TOOLS, ENTITLEMENT_GATED_MCP_TOOLS;
21683
21699
  var init_gated_mcp_tools = __esm({
21684
21700
  "../shared/dist/agent/gated-mcp-tools.js"() {
21685
21701
  "use strict";
21686
- CODE_INDEX_MCP_TOOLS = [
21687
- "search_code_context",
21688
- "code_context_status",
21689
- "code_graph_query",
21690
- "code_lsp_diagnostics"
21691
- ];
21692
- CONTEXT_GRAPH_MCP_TOOLS = ["search_context"];
21693
- ENTITLEMENT_GATED_MCP_TOOLS = [
21694
- ...CODE_INDEX_MCP_TOOLS,
21695
- ...CONTEXT_GRAPH_MCP_TOOLS
21696
- ];
21697
21702
  }
21698
21703
  });
21699
21704
 
@@ -22202,7 +22207,7 @@ var init_chunk_YXWJW7I5 = __esm({
22202
22207
  }
22203
22208
  });
22204
22209
 
22205
- // ../agent-core/dist/chunk-6GPS6OKU.js
22210
+ // ../agent-core/dist/chunk-J4T6L5LX.js
22206
22211
  function windowsEnvValue(env, name) {
22207
22212
  const wanted = name.toLowerCase();
22208
22213
  for (const [key, value] of Object.entries(env)) {
@@ -22373,7 +22378,7 @@ function plan(command, args, options) {
22373
22378
  function captureOutput(command, args, options) {
22374
22379
  const launch = plan(command, args, options);
22375
22380
  if (launch === void 0) return Promise.resolve(NEVER_STARTED);
22376
- return new Promise((resolve5) => {
22381
+ return new Promise((resolve6) => {
22377
22382
  (0, import_child_process.execFile)(
22378
22383
  launch.file,
22379
22384
  [...launch.args],
@@ -22387,7 +22392,7 @@ function captureOutput(command, args, options) {
22387
22392
  },
22388
22393
  (error61, stdout, stderr) => {
22389
22394
  const code = error61 && typeof error61.code === "number" ? error61.code : error61 ? void 0 : 0;
22390
- resolve5({ stdout, stderr, exitCode: code });
22395
+ resolve6({ stdout, stderr, exitCode: code });
22391
22396
  }
22392
22397
  );
22393
22398
  });
@@ -22429,18 +22434,18 @@ function decode3(bytes, start, end) {
22429
22434
  }
22430
22435
  async function linuxStartTicks(pid) {
22431
22436
  try {
22432
- const stat13 = await (0, import_promises5.readFile)(`/proc/${pid}/stat`, "utf8");
22433
- const fields = stat13.slice(stat13.lastIndexOf(")") + 2).split(" ");
22437
+ const stat14 = await (0, import_promises5.readFile)(`/proc/${pid}/stat`, "utf8");
22438
+ const fields = stat14.slice(stat14.lastIndexOf(")") + 2).split(" ");
22434
22439
  return fields[19];
22435
22440
  } catch {
22436
22441
  return void 0;
22437
22442
  }
22438
22443
  }
22439
22444
  function psStartTime(pid) {
22440
- return new Promise((resolve5) => {
22445
+ return new Promise((resolve6) => {
22441
22446
  (0, import_child_process2.execFile)("ps", ["-o", "lstart=", "-p", String(pid)], { timeout: 2e3 }, (error61, stdout) => {
22442
22447
  const text2 = stdout.trim();
22443
- resolve5(error61 || !text2 ? void 0 : text2);
22448
+ resolve6(error61 || !text2 ? void 0 : text2);
22444
22449
  });
22445
22450
  });
22446
22451
  }
@@ -22469,12 +22474,12 @@ function parseProcessList(text2) {
22469
22474
  }
22470
22475
  function listProcesses(platform = process.platform) {
22471
22476
  if (platform === "win32") return Promise.resolve([]);
22472
- return new Promise((resolve5) => {
22477
+ return new Promise((resolve6) => {
22473
22478
  (0, import_child_process3.execFile)(
22474
22479
  "ps",
22475
22480
  ["-A", "-o", "pid=,ppid=,pgid=,lstart="],
22476
22481
  { timeout: 5e3, maxBuffer: 8 * 1024 * 1024 },
22477
- (error61, stdout) => resolve5(error61 ? [] : parseProcessList(stdout))
22482
+ (error61, stdout) => resolve6(error61 ? [] : parseProcessList(stdout))
22478
22483
  );
22479
22484
  });
22480
22485
  }
@@ -22514,11 +22519,11 @@ async function taskkill(pid, options) {
22514
22519
  stdio: "ignore",
22515
22520
  windowsHide: true
22516
22521
  });
22517
- const exited = new Promise((resolve5) => {
22518
- killer.once("error", (error210) => resolve5(error210));
22522
+ const exited = new Promise((resolve6) => {
22523
+ killer.once("error", (error210) => resolve6(error210));
22519
22524
  killer.once(
22520
22525
  "exit",
22521
- (code, signal) => resolve5(code === 0 ? void 0 : new Error(`taskkill failed: exit ${code}, signal ${signal}`))
22526
+ (code, signal) => resolve6(code === 0 ? void 0 : new Error(`taskkill failed: exit ${code}, signal ${signal}`))
22522
22527
  );
22523
22528
  });
22524
22529
  const timedOut = clock.sleep(options.timeoutMs ?? DEFAULT_TASKKILL_TIMEOUT_MS, timeout.signal).then(() => new Error("taskkill timed out")).catch(() => void 0);
@@ -22748,25 +22753,35 @@ async function waitForWindowsJob(child, command) {
22748
22753
  await (0, import_promises6.rm)(status.directory, { recursive: true, force: true });
22749
22754
  }
22750
22755
  }
22756
+ function onCliSpawned(listener) {
22757
+ spawnListeners.add(listener);
22758
+ return {
22759
+ [Symbol.dispose]: () => {
22760
+ spawnListeners.delete(listener);
22761
+ }
22762
+ };
22763
+ }
22751
22764
  function spawnCli(options) {
22752
22765
  const platform = options.platform ?? process.platform;
22753
22766
  const plan2 = planSpawn({ ...options, platform });
22754
22767
  if (plan2.commandLine !== null) return spawnInWindowsJob(plan2, options);
22755
- return (0, import_child_process5.spawn)(plan2.file, [...plan2.args], {
22768
+ const child = (0, import_child_process5.spawn)(plan2.file, [...plan2.args], {
22756
22769
  cwd: options.cwd,
22757
22770
  env: { ...options.env },
22758
22771
  stdio: ["pipe", "pipe", "pipe"],
22759
22772
  shell: false,
22760
22773
  detached: true
22761
22774
  });
22775
+ for (const listener of spawnListeners) listener(child);
22776
+ return child;
22762
22777
  }
22763
22778
  function waitForSpawn(child, command) {
22764
22779
  if (isWindowsJob(child)) return waitForWindowsJob(child, command);
22765
22780
  if (child.pid !== void 0) return Promise.resolve();
22766
- return new Promise((resolve5, reject) => {
22781
+ return new Promise((resolve6, reject) => {
22767
22782
  const onSpawn = () => {
22768
22783
  child.off("error", onError);
22769
- resolve5();
22784
+ resolve6();
22770
22785
  };
22771
22786
  const onError = (error61) => {
22772
22787
  child.off("spawn", onSpawn);
@@ -22779,9 +22794,9 @@ function waitForSpawn(child, command) {
22779
22794
  child.once("error", onError);
22780
22795
  });
22781
22796
  }
22782
- var import_child_process, import_fs, import_path, import_child_process2, import_promises5, import_child_process3, import_child_process4, import_child_process5, import_child_process6, import_crypto, import_fs2, import_promises6, 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;
22783
- var init_chunk_6GPS6OKU = __esm({
22784
- "../agent-core/dist/chunk-6GPS6OKU.js"() {
22797
+ var import_child_process, import_fs, import_path, import_child_process2, import_promises5, import_child_process3, import_child_process4, import_child_process5, import_child_process6, import_crypto, import_fs2, import_promises6, 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;
22798
+ var init_chunk_J4T6L5LX = __esm({
22799
+ "../agent-core/dist/chunk-J4T6L5LX.js"() {
22785
22800
  "use strict";
22786
22801
  init_chunk_YXWJW7I5();
22787
22802
  import_child_process = require("child_process");
@@ -22870,6 +22885,7 @@ var init_chunk_6GPS6OKU = __esm({
22870
22885
  DEFAULT_TASKKILL_TIMEOUT_MS = 5e3;
22871
22886
  statuses = /* @__PURE__ */ new WeakMap();
22872
22887
  START_TIMEOUT_MS = 1e4;
22888
+ spawnListeners = /* @__PURE__ */ new Set();
22873
22889
  }
22874
22890
  });
22875
22891
 
@@ -23575,26 +23591,26 @@ var init_constants = __esm({
23575
23591
  }
23576
23592
  });
23577
23593
 
23578
- // ../shared/dist/agent/acp/background-task.js
23579
- var BACKGROUND_TASK_META_KEY;
23580
- var init_background_task = __esm({
23581
- "../shared/dist/agent/acp/background-task.js"() {
23594
+ // ../shared/dist/agent/acp/transcript-http.js
23595
+ var init_transcript_http = __esm({
23596
+ "../shared/dist/agent/acp/transcript-http.js"() {
23582
23597
  "use strict";
23583
- BACKGROUND_TASK_META_KEY = "alan.dev/backgroundTask";
23584
23598
  }
23585
23599
  });
23586
23600
 
23587
- // ../shared/dist/agent/acp/conversation-messages.js
23588
- var init_conversation_messages = __esm({
23589
- "../shared/dist/agent/acp/conversation-messages.js"() {
23601
+ // ../shared/dist/agent/acp/ask.js
23602
+ var init_ask = __esm({
23603
+ "../shared/dist/agent/acp/ask.js"() {
23590
23604
  "use strict";
23591
23605
  }
23592
23606
  });
23593
23607
 
23594
- // ../shared/dist/agent/acp/event.js
23595
- var init_event = __esm({
23596
- "../shared/dist/agent/acp/event.js"() {
23608
+ // ../shared/dist/agent/acp/background-task.js
23609
+ var BACKGROUND_TASK_META_KEY;
23610
+ var init_background_task = __esm({
23611
+ "../shared/dist/agent/acp/background-task.js"() {
23597
23612
  "use strict";
23613
+ BACKGROUND_TASK_META_KEY = "alan.dev/backgroundTask";
23598
23614
  }
23599
23615
  });
23600
23616
 
@@ -23626,9 +23642,9 @@ var init_prepare_conversation_turns = __esm({
23626
23642
  }
23627
23643
  });
23628
23644
 
23629
- // ../shared/dist/agent/acp/presentation/types.js
23630
- var init_types2 = __esm({
23631
- "../shared/dist/agent/acp/presentation/types.js"() {
23645
+ // ../shared/dist/agent/acp/event.js
23646
+ var init_event = __esm({
23647
+ "../shared/dist/agent/acp/event.js"() {
23632
23648
  "use strict";
23633
23649
  }
23634
23650
  });
@@ -23637,7 +23653,7 @@ var init_types2 = __esm({
23637
23653
  function isUpdate(update, kind) {
23638
23654
  return update.sessionUpdate === kind;
23639
23655
  }
23640
- var init_types3 = __esm({
23656
+ var init_types2 = __esm({
23641
23657
  "../shared/dist/agent/acp/types.js"() {
23642
23658
  "use strict";
23643
23659
  }
@@ -23650,6 +23666,20 @@ var init_reduce = __esm({
23650
23666
  }
23651
23667
  });
23652
23668
 
23669
+ // ../shared/dist/agent/acp/conversation-messages.js
23670
+ var init_conversation_messages = __esm({
23671
+ "../shared/dist/agent/acp/conversation-messages.js"() {
23672
+ "use strict";
23673
+ }
23674
+ });
23675
+
23676
+ // ../shared/dist/agent/acp/presentation/types.js
23677
+ var init_types3 = __esm({
23678
+ "../shared/dist/agent/acp/presentation/types.js"() {
23679
+ "use strict";
23680
+ }
23681
+ });
23682
+
23653
23683
  // ../shared/dist/agent/acp/read.js
23654
23684
  var init_read = __esm({
23655
23685
  "../shared/dist/agent/acp/read.js"() {
@@ -23664,13 +23694,6 @@ var init_transcript_byte_decoder = __esm({
23664
23694
  }
23665
23695
  });
23666
23696
 
23667
- // ../shared/dist/agent/acp/transcript-http.js
23668
- var init_transcript_http = __esm({
23669
- "../shared/dist/agent/acp/transcript-http.js"() {
23670
- "use strict";
23671
- }
23672
- });
23673
-
23674
23697
  // ../shared/dist/agent/acp/transcript-fold.js
23675
23698
  var init_transcript_fold = __esm({
23676
23699
  "../shared/dist/agent/acp/transcript-fold.js"() {
@@ -23691,6 +23714,7 @@ var init_transcript_live = __esm({
23691
23714
  var init_acp = __esm({
23692
23715
  "../shared/dist/agent/acp/index.js"() {
23693
23716
  "use strict";
23717
+ init_ask();
23694
23718
  init_background_task();
23695
23719
  init_conversation_messages();
23696
23720
  init_event();
@@ -23698,7 +23722,7 @@ var init_acp = __esm({
23698
23722
  init_notice_visibility();
23699
23723
  init_prepare_conversation_turns();
23700
23724
  init_terminal_events();
23701
- init_types2();
23725
+ init_types3();
23702
23726
  init_read();
23703
23727
  init_reduce();
23704
23728
  init_transcript_byte_decoder();
@@ -23706,7 +23730,7 @@ var init_acp = __esm({
23706
23730
  init_transcript_http();
23707
23731
  init_transcript_ingestion();
23708
23732
  init_transcript_live();
23709
- init_types3();
23733
+ init_types2();
23710
23734
  }
23711
23735
  });
23712
23736
 
@@ -24078,7 +24102,7 @@ var init_chunk_DALFHI4B = __esm({
24078
24102
  }
24079
24103
  });
24080
24104
 
24081
- // ../agent-core/dist/chunk-BR4I6MQF.js
24105
+ // ../agent-core/dist/chunk-R6R6ORR2.js
24082
24106
  function specForErrorKind(errorKind) {
24083
24107
  const spec = ERROR_SPECS[errorKind];
24084
24108
  return { message: spec.message, errorKind, recoveryClass: spec.recoveryClass };
@@ -24192,6 +24216,7 @@ function statusKind(status) {
24192
24216
  }
24193
24217
  function mapProviderApiError(errorCode, apiStatus) {
24194
24218
  if (apiStatus === 403) return "access_denied";
24219
+ if (apiStatus === 402) return "payment_required";
24195
24220
  if (apiStatus === 401) return "auth_invalid";
24196
24221
  const code = errorCode?.trim().toLowerCase();
24197
24222
  const byCode = code ? CODE_RULES.find((rule) => rule.pattern.test(code))?.kind : void 0;
@@ -24205,6 +24230,11 @@ function classifyProviderApiError(input2) {
24205
24230
  if (fromText && TEXT_REFINES[structured]?.has(fromText.errorKind)) return fromText;
24206
24231
  return specForErrorKind(structured);
24207
24232
  }
24233
+ function withPaymentRemedy(classified, message) {
24234
+ if (classified.errorKind !== "payment_required") return classified;
24235
+ const remedy = message.replace(STATUS_LEAD, "").trim();
24236
+ return remedy ? { ...classified, message: remedy.slice(0, 300) } : classified;
24237
+ }
24208
24238
  function classifyProviderError(text2, hints = {}) {
24209
24239
  const detail = readProviderErrorDetail(text2);
24210
24240
  const errorCode = hints.errorCode ?? detail.type;
@@ -24214,7 +24244,7 @@ function classifyProviderError(text2, hints = {}) {
24214
24244
  ...status === void 0 ? {} : { status },
24215
24245
  text: detail.message
24216
24246
  }) ?? classifyProviderTerminalText(text2);
24217
- if (classified) return classified;
24247
+ if (classified) return withPaymentRemedy(classified, detail.message);
24218
24248
  const message = detail.message.slice(0, 200);
24219
24249
  return message ? { message, errorKind: "unknown_cli_error", recoveryClass: "unknown" } : specForErrorKind("unknown_cli_error");
24220
24250
  }
@@ -24265,9 +24295,9 @@ function createCliProblem(classified, options) {
24265
24295
  ...classified.resetsAt ? { resetsAt: classified.resetsAt } : {}
24266
24296
  });
24267
24297
  }
24268
- var import_crypto2, ERROR_SPECS, AGENT_ERROR_KINDS, STATUS_PREFIX, TEXT_RULES, CODEX_TIMEOUT_MESSAGE, CODEX_EXPIRED_MESSAGE, EPOCH_RESET, WORDED_RESET, COMMAND_NOT_FOUND, CODE_RULES, TEXT_REFINES, CLI_PROBLEM_CODE_BY_ERROR_KIND, KEY_REJECTION_KINDS;
24269
- var init_chunk_BR4I6MQF = __esm({
24270
- "../agent-core/dist/chunk-BR4I6MQF.js"() {
24298
+ var import_crypto2, ERROR_SPECS, AGENT_ERROR_KINDS, STATUS_PREFIX, TEXT_RULES, CODEX_TIMEOUT_MESSAGE, CODEX_EXPIRED_MESSAGE, EPOCH_RESET, WORDED_RESET, COMMAND_NOT_FOUND, CODE_RULES, TEXT_REFINES, STATUS_LEAD, CLI_PROBLEM_CODE_BY_ERROR_KIND, KEY_REJECTION_KINDS;
24299
+ var init_chunk_R6R6ORR2 = __esm({
24300
+ "../agent-core/dist/chunk-R6R6ORR2.js"() {
24271
24301
  "use strict";
24272
24302
  init_chunk_YXWJW7I5();
24273
24303
  import_crypto2 = require("crypto");
@@ -24301,6 +24331,10 @@ var init_chunk_BR4I6MQF = __esm({
24301
24331
  message: "This model requires a paid subscription. Switch to a supported model or upgrade your plan.",
24302
24332
  recoveryClass: "user_fixable"
24303
24333
  },
24334
+ payment_required: {
24335
+ message: "The account behind this model has no active plan or credits. Ask an admin to check billing, or switch to a model from your own provider, then retry.",
24336
+ recoveryClass: "user_fixable"
24337
+ },
24304
24338
  quota_exceeded: {
24305
24339
  message: "API quota exceeded. Wait for it to reset or check your billing, then retry.",
24306
24340
  recoveryClass: "user_fixable"
@@ -24477,6 +24511,7 @@ var init_chunk_BR4I6MQF = __esm({
24477
24511
  rate_limited: /* @__PURE__ */ new Set(["usage_limit", "quota_exceeded"]),
24478
24512
  auth_invalid: /* @__PURE__ */ new Set(["auth_expired", "not_logged_in", "not_authenticated"])
24479
24513
  };
24514
+ STATUS_LEAD = /^(?:api error|status|http)[:\s]+\d{3}\b[:\s]*/i;
24480
24515
  CLI_PROBLEM_CODE_BY_ERROR_KIND = {
24481
24516
  model_mismatch: "cli.model.unavailable",
24482
24517
  auth_invalid: "cli.auth.invalid",
@@ -24485,6 +24520,7 @@ var init_chunk_BR4I6MQF = __esm({
24485
24520
  not_authenticated: "cli.auth.invalid",
24486
24521
  auth_expired: "cli.auth.expired",
24487
24522
  subscription_required: "cli.entitlement.required",
24523
+ payment_required: "cli.entitlement.required",
24488
24524
  quota_exceeded: "cli.quota_exceeded",
24489
24525
  usage_limit: "cli.quota_exceeded",
24490
24526
  context_length: "cli.context_exhausted",
@@ -24511,7 +24547,7 @@ var init_chunk_BR4I6MQF = __esm({
24511
24547
  }
24512
24548
  });
24513
24549
 
24514
- // ../agent-core/dist/chunk-UKUTSW3L.js
24550
+ // ../agent-core/dist/chunk-W3QH4J4A.js
24515
24551
  function collectStrings(value, out) {
24516
24552
  if (typeof value === "string") out.push(value);
24517
24553
  else if (Array.isArray(value)) for (const item of value) collectStrings(item, out);
@@ -24603,8 +24639,8 @@ function readMediaFiles(candidates2, cwd, mimeByExt, maxBytes) {
24603
24639
  seen.add(path);
24604
24640
  const mimeType = mimeByExt[(0, import_path3.extname)(path).toLowerCase()];
24605
24641
  if (!mimeType) continue;
24606
- const stat13 = (0, import_fs4.statSync)(path);
24607
- if (!stat13.isFile() || stat13.size <= 0 || stat13.size > maxBytes) continue;
24642
+ const stat14 = (0, import_fs4.statSync)(path);
24643
+ if (!stat14.isFile() || stat14.size <= 0 || stat14.size > maxBytes) continue;
24608
24644
  files.push({ path, mimeType, buffer: (0, import_fs4.readFileSync)(path) });
24609
24645
  }
24610
24646
  return files;
@@ -24679,8 +24715,8 @@ function createJsonRpcPeer(writer, handlers) {
24679
24715
  },
24680
24716
  request: (method, params = {}) => {
24681
24717
  const id = counter.next++;
24682
- return new Promise((resolve5, reject) => {
24683
- pending.set(id, { method, resolve: resolve5, reject });
24718
+ return new Promise((resolve6, reject) => {
24719
+ pending.set(id, { method, resolve: resolve6, reject });
24684
24720
  writer.write({ id, method, params }).catch((error61) => {
24685
24721
  pending.delete(id);
24686
24722
  reject(error61 instanceof Error ? error61 : new Error(String(error61)));
@@ -24793,7 +24829,7 @@ function createNdjsonWriter(stream) {
24793
24829
  get writable() {
24794
24830
  return stream.writable && !stream.destroyed && failure5.error === void 0;
24795
24831
  },
24796
- write: (value) => new Promise((resolve5, reject) => {
24832
+ write: (value) => new Promise((resolve6, reject) => {
24797
24833
  if (failure5.error) {
24798
24834
  reject(failure5.error);
24799
24835
  return;
@@ -24805,7 +24841,7 @@ function createNdjsonWriter(stream) {
24805
24841
  stream.write(`${JSON.stringify(value)}
24806
24842
  `, (error61) => {
24807
24843
  if (error61) reject(error61);
24808
- else resolve5();
24844
+ else resolve6();
24809
24845
  });
24810
24846
  }),
24811
24847
  end: () => {
@@ -24821,11 +24857,11 @@ function hostProcess(child, tree, options, handlers) {
24821
24857
  const stderr = new LineSplitter((line) => handlers.onStderrLine(line));
24822
24858
  child.stderr.on("data", (chunk) => stderr.push(chunk));
24823
24859
  child.stderr.once("end", () => stderr.flush());
24824
- const processExit = new Promise((resolve5) => {
24825
- child.once("exit", (code, signal) => resolve5({ code, signal }));
24860
+ const processExit = new Promise((resolve6) => {
24861
+ child.once("exit", (code, signal) => resolve6({ code, signal }));
24826
24862
  });
24827
- const outputEnded = new Promise((resolve5) => {
24828
- child.stdout.once("close", () => resolve5());
24863
+ const outputEnded = new Promise((resolve6) => {
24864
+ child.stdout.once("close", () => resolve6());
24829
24865
  });
24830
24866
  const watch = async () => {
24831
24867
  const { clock, stdoutDrainMs, log, name } = options;
@@ -24881,12 +24917,12 @@ function silentStartError(name, timeoutMs) {
24881
24917
  };
24882
24918
  }
24883
24919
  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;
24884
- var init_chunk_UKUTSW3L = __esm({
24885
- "../agent-core/dist/chunk-UKUTSW3L.js"() {
24920
+ var init_chunk_W3QH4J4A = __esm({
24921
+ "../agent-core/dist/chunk-W3QH4J4A.js"() {
24886
24922
  "use strict";
24887
24923
  init_chunk_UGRKZTAD();
24888
- init_chunk_BR4I6MQF();
24889
- init_chunk_6GPS6OKU();
24924
+ init_chunk_R6R6ORR2();
24925
+ init_chunk_J4T6L5LX();
24890
24926
  init_chunk_YXWJW7I5();
24891
24927
  import_crypto3 = require("crypto");
24892
24928
  import_fs4 = require("fs");
@@ -25114,13 +25150,13 @@ var init_chunk_UKUTSW3L = __esm({
25114
25150
  const turnId = input2.turnId;
25115
25151
  let finish = () => {
25116
25152
  };
25117
- const done = new Promise((resolve5) => {
25153
+ const done = new Promise((resolve6) => {
25118
25154
  finish = (outcome2) => {
25119
25155
  if (this.#current?.id !== turnId) return;
25120
25156
  this.#current = void 0;
25121
25157
  if (this.#state === "busy") this.#state = "idle";
25122
25158
  this.#emit({ type: "turn_ended", turnId, outcome: outcome2 });
25123
- resolve5({ turnId, outcome: outcome2, providerSessionId: this.#sessionId });
25159
+ resolve6({ turnId, outcome: outcome2, providerSessionId: this.#sessionId });
25124
25160
  };
25125
25161
  });
25126
25162
  const pending = {
@@ -25316,20 +25352,20 @@ function canonicalizeManagedMcpToolName(toolName) {
25316
25352
  return flattened ? `mcp__${MANAGED_MCP_SERVER_NAME}__${flattened[1]}` : toolName;
25317
25353
  }
25318
25354
  async function writeSecretFile(name, contents) {
25319
- const dir = await (0, import_promises12.mkdtemp)((0, import_path4.join)((0, import_os2.tmpdir)(), "alan-mcp-"));
25355
+ const dir = await (0, import_promises13.mkdtemp)((0, import_path4.join)((0, import_os2.tmpdir)(), "alan-mcp-"));
25320
25356
  const path = (0, import_path4.join)(dir, name);
25321
25357
  const remove = async () => {
25322
- await (0, import_promises12.rm)(dir, { recursive: true, force: true });
25358
+ await (0, import_promises13.rm)(dir, { recursive: true, force: true });
25323
25359
  };
25324
25360
  try {
25325
- await (0, import_promises12.writeFile)(path, contents, { mode: 384, flag: "wx" });
25361
+ await (0, import_promises13.writeFile)(path, contents, { mode: 384, flag: "wx" });
25326
25362
  } catch (error61) {
25327
25363
  await remove();
25328
25364
  throw error61;
25329
25365
  }
25330
25366
  return { path, remove, [Symbol.asyncDispose]: remove };
25331
25367
  }
25332
- var import_crypto4, import_crypto5, import_promises12, import_os2, import_path4, MANAGED_MCP_SERVER_NAME, RUN_SCOPED_SERVER, NAMESPACED_RUN_TOOL, FLATTENED_RUN_TOOL;
25368
+ var import_crypto4, import_crypto5, import_promises13, import_os2, import_path4, MANAGED_MCP_SERVER_NAME, RUN_SCOPED_SERVER, NAMESPACED_RUN_TOOL, FLATTENED_RUN_TOOL;
25333
25369
  var init_chunk_J2KTV5FP = __esm({
25334
25370
  "../agent-core/dist/chunk-J2KTV5FP.js"() {
25335
25371
  "use strict";
@@ -25338,7 +25374,7 @@ var init_chunk_J2KTV5FP = __esm({
25338
25374
  import_crypto5 = require("crypto");
25339
25375
  init_agent2();
25340
25376
  init_runtime_v2();
25341
- import_promises12 = require("fs/promises");
25377
+ import_promises13 = require("fs/promises");
25342
25378
  import_os2 = require("os");
25343
25379
  import_path4 = require("path");
25344
25380
  MANAGED_MCP_SERVER_NAME = "alan";
@@ -26253,9 +26289,12 @@ function resultMessageId(state) {
26253
26289
  state.resultMessageId ??= synthId(state, "claude-result");
26254
26290
  return state.resultMessageId;
26255
26291
  }
26292
+ function isErrorResult(event) {
26293
+ return asString(event.subtype).startsWith("error") || event.is_error === true || event.terminal_reason === "api_error" || typeof event.api_error_status === "number";
26294
+ }
26256
26295
  function parseResult(event, state) {
26257
26296
  const stopReason = stopReasonFor(asString(event.stop_reason), event.is_error === true);
26258
- const resultText2 = asString(event.result);
26297
+ const resultText2 = isErrorResult(event) ? "" : asString(event.result);
26259
26298
  const updates = [];
26260
26299
  const streamed = state.lastForegroundText;
26261
26300
  if (resultText2) {
@@ -26736,21 +26775,21 @@ async function claudeTurnInput(run, context) {
26736
26775
  const encoded = await Promise.all(
26737
26776
  images.map(async (image) => ({
26738
26777
  mimeType: image.mimeType,
26739
- data: (await (0, import_promises13.readFile)(image.path)).toString("base64")
26778
+ data: (await (0, import_promises14.readFile)(image.path)).toString("base64")
26740
26779
  }))
26741
26780
  );
26742
26781
  return { turnId: run.runId, text: text2, ...encoded.length ? { images: encoded } : {} };
26743
26782
  }
26744
- var import_crypto6, import_fs5, import_path5, import_crypto7, import_promises13, EDIT_TOOLS, ThoughtBlocks, UNDERSTOOD_SYSTEM_SUBTYPES, RATE_LIMIT_WARN_AT, CLAUDE_GRAMMAR_NAME, SUBAGENT_TOOL_NAMES, PLAN_ENTRY_STATUSES, controlResponseSchema, STOPPED_STATUSES, TaskRecords, TERMINAL_BACKGROUND_STATUSES, NON_TERMINAL_BACKGROUND_STATUSES, ASYNC_LAUNCH_ACK, BackgroundTasks, FAILED_STATUSES, STOPPED_BY_USER_TEXT, ClaudeTurn, STDERR_TAIL_LINES2, MAX_EARLY_LINES, UNSUPPORTED_STOP, OUTPUT_CLOSED_REASON, ClaudeSession, DEFAULTS, READ_ONLY_DISALLOWED_TOOLS, DEFAULT_MCP_TIMEOUT_MS;
26783
+ var import_crypto6, import_fs5, import_path5, import_crypto7, import_promises14, EDIT_TOOLS, ThoughtBlocks, UNDERSTOOD_SYSTEM_SUBTYPES, RATE_LIMIT_WARN_AT, CLAUDE_GRAMMAR_NAME, SUBAGENT_TOOL_NAMES, PLAN_ENTRY_STATUSES, controlResponseSchema, STOPPED_STATUSES, TaskRecords, TERMINAL_BACKGROUND_STATUSES, NON_TERMINAL_BACKGROUND_STATUSES, ASYNC_LAUNCH_ACK, BackgroundTasks, FAILED_STATUSES, STOPPED_BY_USER_TEXT, ClaudeTurn, STDERR_TAIL_LINES2, MAX_EARLY_LINES, UNSUPPORTED_STOP, OUTPUT_CLOSED_REASON, ClaudeSession, DEFAULTS, READ_ONLY_DISALLOWED_TOOLS, DEFAULT_MCP_TIMEOUT_MS;
26745
26784
  var init_claude = __esm({
26746
26785
  "../agent-core/dist/providers/claude.js"() {
26747
26786
  "use strict";
26748
26787
  init_chunk_DALFHI4B();
26749
- init_chunk_UKUTSW3L();
26788
+ init_chunk_W3QH4J4A();
26750
26789
  init_chunk_UGRKZTAD();
26751
- init_chunk_BR4I6MQF();
26790
+ init_chunk_R6R6ORR2();
26752
26791
  init_chunk_J2KTV5FP();
26753
- init_chunk_6GPS6OKU();
26792
+ init_chunk_J4T6L5LX();
26754
26793
  init_chunk_6WN2R725();
26755
26794
  init_chunk_YXWJW7I5();
26756
26795
  init_effort();
@@ -26764,7 +26803,7 @@ var init_claude = __esm({
26764
26803
  import_fs5 = require("fs");
26765
26804
  import_path5 = require("path");
26766
26805
  import_crypto7 = require("crypto");
26767
- import_promises13 = require("fs/promises");
26806
+ import_promises14 = require("fs/promises");
26768
26807
  init_agent2();
26769
26808
  EDIT_TOOLS = /* @__PURE__ */ new Set([
26770
26809
  "Edit",
@@ -27463,8 +27502,8 @@ var init_claude = __esm({
27463
27502
  }
27464
27503
  async #awaitTaskStop(requestId, taskId) {
27465
27504
  const timer = new AbortController();
27466
- const answered = new Promise((resolve5) => {
27467
- this.#taskStops.set(requestId, resolve5);
27505
+ const answered = new Promise((resolve6) => {
27506
+ this.#taskStops.set(requestId, resolve6);
27468
27507
  });
27469
27508
  const timeoutMs = this.#options.stopTaskTimeoutMs;
27470
27509
  const timedOut = this.#options.clock.sleep(timeoutMs, timer.signal).then(
@@ -27537,17 +27576,17 @@ var init_claude = __esm({
27537
27576
  };
27538
27577
  let markStarted = () => {
27539
27578
  };
27540
- const whenStarted = new Promise((resolve5) => {
27541
- markStarted = resolve5;
27579
+ const whenStarted = new Promise((resolve6) => {
27580
+ markStarted = resolve6;
27542
27581
  });
27543
- const done = new Promise((resolve5) => {
27582
+ const done = new Promise((resolve6) => {
27544
27583
  finish = (outcome2) => {
27545
27584
  if (this.#current?.id !== id) return;
27546
27585
  this.#current = void 0;
27547
27586
  this.#lastTurn = turn;
27548
27587
  if (this.#state === "busy") this.#state = "idle";
27549
27588
  this.#emit({ type: "turn_ended", turnId: id, outcome: outcome2 });
27550
- resolve5({ turnId: id, outcome: outcome2, providerSessionId: this.#providerSessionId });
27589
+ resolve6({ turnId: id, outcome: outcome2, providerSessionId: this.#providerSessionId });
27551
27590
  };
27552
27591
  });
27553
27592
  const active = {
@@ -27665,8 +27704,8 @@ var init_claude = __esm({
27665
27704
  void removeLaunchFiles(this.#launchFiles).catch((error61) => {
27666
27705
  this.#options.log.warn("claude.launch_files_cleanup_failed", { error: error61 });
27667
27706
  });
27668
- for (const resolve5 of this.#taskStops.values()) {
27669
- resolve5({ ok: false, reason: "runtime_unavailable", message: "Claude Code exited." });
27707
+ for (const resolve6 of this.#taskStops.values()) {
27708
+ resolve6({ ok: false, reason: "runtime_unavailable", message: "Claude Code exited." });
27670
27709
  }
27671
27710
  const active = this.#current;
27672
27711
  if (active) {
@@ -28878,11 +28917,11 @@ var init_codex = __esm({
28878
28917
  "../agent-core/dist/providers/codex.js"() {
28879
28918
  "use strict";
28880
28919
  init_chunk_DALFHI4B();
28881
- init_chunk_UKUTSW3L();
28920
+ init_chunk_W3QH4J4A();
28882
28921
  init_chunk_UGRKZTAD();
28883
- init_chunk_BR4I6MQF();
28922
+ init_chunk_R6R6ORR2();
28884
28923
  init_chunk_J2KTV5FP();
28885
- init_chunk_6GPS6OKU();
28924
+ init_chunk_J4T6L5LX();
28886
28925
  init_chunk_6WN2R725();
28887
28926
  init_chunk_YXWJW7I5();
28888
28927
  import_fs6 = require("fs");
@@ -29502,10 +29541,10 @@ var init_codex = __esm({
29502
29541
  };
29503
29542
  let identify = () => {
29504
29543
  };
29505
- const identified = new Promise((resolve5) => {
29506
- identify = resolve5;
29544
+ const identified = new Promise((resolve6) => {
29545
+ identify = resolve6;
29507
29546
  });
29508
- const done = new Promise((resolve5) => {
29547
+ const done = new Promise((resolve6) => {
29509
29548
  finish = (outcome2) => {
29510
29549
  if (this.#current?.id !== id) return;
29511
29550
  this.#current = void 0;
@@ -29513,7 +29552,7 @@ var init_codex = __esm({
29513
29552
  if (this.#state === "busy") this.#state = "idle";
29514
29553
  this.#host.scanDescendants(true);
29515
29554
  this.#emit({ type: "turn_ended", turnId: id, outcome: outcome2 });
29516
- resolve5({ turnId: id, outcome: outcome2, providerSessionId: this.#threadId });
29555
+ resolve6({ turnId: id, outcome: outcome2, providerSessionId: this.#threadId });
29517
29556
  };
29518
29557
  });
29519
29558
  const active = {
@@ -29986,7 +30025,7 @@ function alanCodeConfigContent(existing, input2) {
29986
30025
  });
29987
30026
  }
29988
30027
  function readBody2(response) {
29989
- return new Promise((resolve5, reject) => {
30028
+ return new Promise((resolve6, reject) => {
29990
30029
  const chunks = [];
29991
30030
  let size = 0;
29992
30031
  response.on("data", (chunk) => {
@@ -29994,7 +30033,7 @@ function readBody2(response) {
29994
30033
  if (size > MAX_CATALOG_BYTES) response.destroy(new Error("catalog too large"));
29995
30034
  else chunks.push(chunk);
29996
30035
  });
29997
- response.on("end", () => resolve5(Buffer.concat(chunks).toString("utf8")));
30036
+ response.on("end", () => resolve6(Buffer.concat(chunks).toString("utf8")));
29998
30037
  response.on("error", reject);
29999
30038
  });
30000
30039
  }
@@ -30010,13 +30049,13 @@ function parseResponseBody(text2, status) {
30010
30049
  }
30011
30050
  function getJson(url2, headers, timeout, signal) {
30012
30051
  const request2 = url2.protocol === "https:" ? import_https.request : import_http3.request;
30013
- return new Promise((resolve5, reject) => {
30052
+ return new Promise((resolve6, reject) => {
30014
30053
  const outgoing = request2(url2, { method: "GET", headers, timeout, signal }, (response) => {
30015
30054
  const status = response.statusCode ?? 0;
30016
30055
  readBody2(response).then((text2) => {
30017
30056
  const body = parseResponseBody(text2, status);
30018
30057
  if (status < 200 || status >= 300) reject(new CatalogResponseError(status, body));
30019
- else resolve5(body);
30058
+ else resolve6(body);
30020
30059
  }).catch(reject);
30021
30060
  });
30022
30061
  outgoing.on("timeout", () => outgoing.destroy(new Error("catalog timed out")));
@@ -30233,15 +30272,15 @@ async function writePlugin(directory, apiOrigin) {
30233
30272
  const origin = (0, import_crypto11.createHash)("sha256").update(apiOrigin).digest("hex").slice(0, 12);
30234
30273
  const target = (0, import_path8.join)(directory, `engine-plugin-v${ALAN_CODE_ENGINE_PLUGIN_VERSION}-${origin}.mjs`);
30235
30274
  const temporary = `${target}.${(0, import_crypto11.randomUUID)()}.tmp`;
30236
- await (0, import_promises14.mkdir)(directory, { recursive: true, mode: 448 });
30237
- await (0, import_promises14.writeFile)(temporary, alanCodeEnginePluginSource(apiOrigin), { mode: 384 });
30238
- await (0, import_promises14.rename)(temporary, target);
30275
+ await (0, import_promises15.mkdir)(directory, { recursive: true, mode: 448 });
30276
+ await (0, import_promises15.writeFile)(temporary, alanCodeEnginePluginSource(apiOrigin), { mode: 384 });
30277
+ await (0, import_promises15.rename)(temporary, target);
30239
30278
  return (0, import_url.pathToFileURL)(target).href;
30240
30279
  }
30241
30280
  async function prepareAlanCodeProfile(input2) {
30242
30281
  const directories = Object.values(alanCodeEngineDirectories(input2.engineRoot));
30243
30282
  await Promise.all(
30244
- directories.map((directory) => (0, import_promises14.mkdir)(directory, { recursive: true, mode: 448 }))
30283
+ directories.map((directory) => (0, import_promises15.mkdir)(directory, { recursive: true, mode: 448 }))
30245
30284
  );
30246
30285
  const [pluginUrl, models] = await Promise.all([
30247
30286
  writePlugin((0, import_path8.join)(input2.engineRoot, "plugin"), input2.access.apiOrigin),
@@ -30264,7 +30303,7 @@ function alanCodeSystemPrompt(alanSystemPrompt) {
30264
30303
 
30265
30304
  ${instructions}` : ALAN_CODE_TOOL_NAMING_PROMPT;
30266
30305
  }
30267
- var import_http3, import_https, import_fs7, import_path7, import_crypto11, import_promises14, import_path8, import_url, ALAN_CODE_BASELINE_PROMPT, ALAN_CODE_ENGINE_PROVIDER_ID, DEFAULT_CONTEXT_WINDOW, DEFAULT_MAX_OUTPUT_TOKENS, ALAN_CODE_API_KEY_ENV, ALAN_CODE_CONVERSATION_ID_ENV, ALAN_CODE_PROXY_PATH, ALAN_CODE_WEBSEARCH_PATH, ALAN_CODE_CATALOG_PATH, CATALOG_TIMEOUT_MS, MAX_CATALOG_BYTES, ACTIVATION_WAIT_MS, ACTIVATION_POLL_MS, CatalogResponseError, ALAN_CODE_ENGINE_PATH_ENV, ALAN_CODE_ENGINE_COMMAND, ALAN_CODE_ENGINE_NAME, WINDOWS_RUNNABLE_EXTENSION, ALAN_CODE_ENGINE_PLUGIN_VERSION, ALAN_CODE_TOOL_NAMING_PROMPT;
30306
+ var import_http3, import_https, import_fs7, import_path7, import_crypto11, import_promises15, import_path8, import_url, ALAN_CODE_BASELINE_PROMPT, ALAN_CODE_ENGINE_PROVIDER_ID, DEFAULT_CONTEXT_WINDOW, DEFAULT_MAX_OUTPUT_TOKENS, ALAN_CODE_API_KEY_ENV, ALAN_CODE_CONVERSATION_ID_ENV, ALAN_CODE_PROXY_PATH, ALAN_CODE_WEBSEARCH_PATH, ALAN_CODE_CATALOG_PATH, CATALOG_TIMEOUT_MS, MAX_CATALOG_BYTES, ACTIVATION_WAIT_MS, ACTIVATION_POLL_MS, CatalogResponseError, ALAN_CODE_ENGINE_PATH_ENV, ALAN_CODE_ENGINE_COMMAND, ALAN_CODE_ENGINE_NAME, WINDOWS_RUNNABLE_EXTENSION, ALAN_CODE_ENGINE_PLUGIN_VERSION, ALAN_CODE_TOOL_NAMING_PROMPT;
30268
30307
  var init_alan_code = __esm({
30269
30308
  "../agent-core/dist/providers/alan-code.js"() {
30270
30309
  "use strict";
@@ -30278,7 +30317,7 @@ var init_alan_code = __esm({
30278
30317
  import_path7 = require("path");
30279
30318
  init_runtime_v2();
30280
30319
  import_crypto11 = require("crypto");
30281
- import_promises14 = require("fs/promises");
30320
+ import_promises15 = require("fs/promises");
30282
30321
  import_path8 = require("path");
30283
30322
  import_url = require("url");
30284
30323
  ALAN_CODE_BASELINE_PROMPT = "You are alan-code, an interactive CLI coding agent that helps users with software engineering tasks. Use the instructions below and the tools available to you to assist the user.\n\nDo not invent URLs. Use verified URLs or ones supplied by the user or project.\n\nIf the user asks for help or wants to give feedback, inform them of the following:\n- `--harness-help` / harness help: learn how to run alan-code\n- For product feedback or bugs, report through the Alan / Supatest issue channels used by this repository\n\nWhen the user directly asks about alan-code capabilities (for example \"can alan-code\u2026\", \"does the harness have\u2026\") or asks in second person about your abilities, answer from the tools and instructions available in this session. If a docs/fetch tool is available and project docs URLs are known, use them; otherwise inspect local README / AGENTS.md rather than inventing product claims.\n\n# Personality\n\nYour default personality and tone is concise, direct, and friendly. You communicate efficiently, always keeping the user clearly informed about ongoing actions without unnecessary detail. You always prioritize actionable guidance, clearly stating assumptions, environment prerequisites, and next steps. Unless explicitly asked, you avoid excessively verbose explanations about your work.\n\n# Tone and style\n\nYou should be concise, direct, and to the point. When you run a non-trivial bash command, you should explain what the command does and why you are running it, so the user understands what you are doing (especially important for commands that change their system).\nRemember that your output will be displayed on a command line interface. Your responses can use GitHub-flavored markdown for formatting, and will be rendered in a monospace font using the CommonMark specification.\nOutput text to communicate with the user; all text you output outside of tool use is displayed to the user. Only use tools to complete tasks. Never use tools like Bash or code comments as means to communicate with the user during the session.\nIf you cannot or will not help the user with something, do not lecture about why. Offer helpful alternatives if possible; otherwise keep the response to 1-2 sentences.\nOnly use emojis if the user explicitly requests it. Avoid emojis in all communication unless asked.\nIMPORTANT: Minimize output tokens while staying helpful, correct, and accurate. Only address the specific query or task. Avoid tangential information unless it is critical to completing the request. If you can answer in 1-3 sentences or a short paragraph, do that.\nAnswer the user's question directly. One-word answers are best when they suffice. Avoid text before/after your response such as \"The answer is <answer>.\", \"Here is the content of the file\u2026\", \"Based on the information provided\u2026\", or \"Here is what I will do next\u2026\". Examples of appropriate verbosity:\n<example>\nuser: what is 2+2?\nassistant: 4\n</example>\n\n<example>\nuser: is 11 a prime number?\nassistant: Yes\n</example>\n\n<example>\nuser: what command should I run to list files in the current directory?\nassistant: ls\n</example>\n\n<example>\nuser: what command should I run to watch files in the current directory?\nassistant: [use tools to inspect the project, then answer]\nnpm run dev\n</example>\n\n<example>\nuser: what files are in the directory src/?\nassistant: [lists files and sees foo.c, bar.c, baz.c]\nuser: which file contains the implementation of foo?\nassistant: src/foo.c\n</example>\n\n<example>\nuser: write tests for new feature\nassistant: [searches for similar tests, reads relevant files concurrently, edits/writes tests]\n</example>\n\n# Responsiveness\n\n## Preamble messages\n\nBefore making tool calls, send a brief preamble to the user explaining what you're about to do. When sending preamble messages, follow these principles and examples:\n\n- **Logically group related actions**: if you're about to run several related commands, describe them together in one preamble rather than sending a separate note for each.\n- **Keep it concise**: be no more than 1-2 sentences, focused on immediate, tangible next steps. (8\u201312 words for quick updates).\n- **Build on prior context**: if this is not your first tool call, use the preamble message to connect the dots with what's been done so far and create a sense of momentum and clarity for the user to understand your next actions.\n- **Keep your tone light, friendly and curious**: add small touches of personality in preambles feel collaborative and engaging.\n- **Exception**: Avoid adding a preamble for every trivial read (e.g., `cat` a single file) unless it's part of a larger grouped action.\n\nExamples:\n\n- \"I've explored the repo; now checking the API route definitions.\"\n- \"Next, I'll patch the config and update the related tests.\"\n- \"I'm about to scaffold the CLI commands and helper functions.\"\n- \"Ok cool, so I've wrapped my head around the repo. Now digging into the API routes.\"\n- \"Config's looking tidy. Next up is patching helpers to keep things in sync.\"\n- \"Finished poking at the DB gateway. I will now chase down error handling.\"\n- \"Alright, build pipeline order is interesting. Checking how it reports failures.\"\n- \"Spotted a clever caching util; now hunting where it gets used.\"\n\n# Planning\n\nIf a planning tool is available, use it when it helps track complex work. Keep the plan brief and update it as work progresses.\n\nNote that plans are not for padding out simple work with filler steps or stating the obvious. The content of your plan should not involve doing anything that you aren't capable of doing (i.e. don't try to test things that you can't test). Do not use plans for simple or single-step queries that you can just do or answer immediately.\n\nWhen a planning tool displays the plan, summarize only what changed or what comes next.\n\nKeep any active plan aligned with the work completed and remaining.\n\nUse a plan when:\n\n- The task is non-trivial and will require multiple actions over a long time horizon.\n- There are logical phases or dependencies where sequencing matters.\n- The work has ambiguity that benefits from outlining high-level goals.\n- You want intermediate checkpoints for feedback and validation.\n- When the user asked you to do more than one thing in a single prompt\n- The user has asked you to use the plan tool (aka \"TODOs\")\n- You generate additional steps while working, and plan to do them before yielding to the user\n\n## Examples\n\n**High-quality plans**\n\nExample 1:\n\n1. Add CLI entry with file args\n2. Parse Markdown via CommonMark library\n3. Apply semantic HTML template\n4. Handle code blocks, images, links\n5. Add error handling for invalid files\n\nExample 2:\n\n1. Define CSS variables for colors\n2. Add toggle with localStorage state\n3. Refactor components to use variables\n4. Verify all views for readability\n5. Add smooth theme-change transition\n\nExample 3:\n\n1. Set up Node.js + WebSocket server\n2. Add join/leave broadcast events\n3. Implement messaging with timestamps\n4. Add usernames + mention highlighting\n5. Persist messages in lightweight DB\n6. Add typing indicators + unread count\n\n**Low-quality plans**\n\nExample 1:\n\n1. Create CLI tool\n2. Add Markdown parser\n3. Convert to HTML\n\nExample 2:\n\n1. Add dark mode toggle\n2. Save preference\n3. Make styles look good\n\nExample 3:\n\n1. Create single-file HTML game\n2. Run quick sanity check\n3. Summarize usage instructions\n\nIf you need to write a plan, only write high quality plans, not low quality ones.\n\n## Plan mode and clarification (harness specifics)\n\n- When the session is in plan mode, inspect without making changes and produce a concrete plan. Outside plan mode, proceed with authorized work and ask for approval only when the action requires it.\n- Prefer the durable plan file path over relying on chat memory after compaction.\n- When requirements are ambiguous, ask a targeted question using an available user-input tool instead of guessing.\n- An execution checklist is not a substitute for a durable plan when the task requires one.\n\n# Task execution\n\nYou are a coding agent. Please keep going until the query is completely resolved, before ending your turn and yielding back to the user. Only terminate your turn when you are sure that the problem is solved. Autonomously resolve the query to the best of your ability, using the tools available to you, before coming back to the user. Do NOT guess or make up an answer.\n\nYou MUST adhere to the following criteria when solving queries:\n\n- Working on the repo(s) in the current environment is allowed, even if they are proprietary.\n- Analyzing code for vulnerabilities is allowed.\n- Showing user code and tool call details is allowed.\n- Use the editing tools available in the current host to modify files. Do not assume a particular tool name.\n\nIf completing the user's task requires writing or modifying files, your code and final answer should follow these coding guidelines, though user instructions (i.e. AGENTS.md) may override these guidelines:\n\n- Fix the problem at the root cause rather than applying surface-level patches, when possible.\n- Avoid unneeded complexity in your solution.\n- Do not attempt to fix unrelated bugs or broken tests. It is not your responsibility to fix them. (You may mention them to the user in your final message though.)\n- Update documentation as necessary.\n- Keep changes consistent with the style of the existing codebase. Changes should be minimal and focused on the task.\n- Use `git log` and `git blame` to search the history of the codebase if additional context is required.\n- NEVER add copyright or license headers unless specifically requested.\n- Do not waste tokens by re-reading files after editing them. The tool call will fail if it didn't work. The same goes for making folders, deleting folders, etc.\n- Do not `git commit` your changes or create new git branches unless explicitly requested.\n- Add comments when they explain a non-obvious invariant or reason for a decision.\n- Do not use one-letter variable names unless explicitly requested.\n- NEVER output inline citations like \"\u3010F:README.md\u2020L5-L14\u3011\" in your outputs. The CLI is not able to render these so they will just be broken in the UI. Instead, if you output valid filepaths, users will be able to click on them to open the files in their editor.\n\n# Validating your work\n\nIf the codebase has tests or the ability to build or run, consider using them to verify that your work is complete.\n\nWhen testing, your philosophy should be to start as specific as possible to the code you changed so that you can catch issues efficiently, then make your way to broader tests as you build confidence. If there's no test for the code you changed, and if the adjacent patterns in the codebases show that there's a logical place for you to add a test, you may do so. However, do not add tests to codebases with no tests.\n\nSimilarly, once you're confident in correctness, you can suggest or use formatting commands to ensure that your code is well formatted. If there are issues you can iterate up to 3 times to get formatting right, but if you still can't manage it's better to save the user time and present them a correct solution where you call out the formatting in your final message. If the codebase does not have a formatter configured, do not add one.\n\nFor all of testing, running, building, and formatting, do not attempt to fix unrelated bugs. It is not your responsibility to fix them. (You may mention them to the user in your final message though.)\n\nBe mindful of whether to run validation commands proactively. In the absence of behavioral guidance:\n\n- When running in a non-interactive mode where edits are auto-approved (print/headless, or the `allow edits` permission mode), proactively run tests, lint and do whatever you need to ensure you've completed the task.\n- In plan mode, stay read-only. Otherwise, run focused checks after changes when the host permits them.\n- When working on test-related tasks, such as adding tests, fixing tests, or reproducing a bug to verify behavior, you may proactively run tests regardless of permission mode. Use your judgement to decide whether this is a test-related task.\n\n# Ambition vs. precision\n\nFor tasks that have no prior context (i.e. the user is starting something brand new), you should feel free to be ambitious and demonstrate creativity with your implementation.\n\nIf you're operating in an existing codebase, you should make sure you do exactly what the user asks with surgical precision. Treat the surrounding codebase with respect, and don't overstep (i.e. changing filenames or variables unnecessarily). You should balance being sufficiently ambitious and proactive when completing tasks of this nature.\n\nYou should use judicious initiative to decide on the right level of detail and complexity to deliver based on the user's needs. This means showing good judgment that you're capable of doing the right extras without gold-plating. This might be demonstrated by high-value, creative touches when scope of the task is vague; while being surgical and targeted when scope is tightly specified.\n\n# Sharing progress updates\n\nFor especially longer tasks that you work on (i.e. requiring many tool calls, or a plan with multiple steps), you should provide progress updates back to the user at reasonable intervals. These updates should be structured as a concise sentence or two (no more than 8-10 words long) recapping progress so far in plain language: this update demonstrates your understanding of what needs to be done, progress so far (i.e. files explores, subtasks complete), and where you're going next.\n\nBefore doing large chunks of work that may incur latency as experienced by the user (i.e. writing a new file), you should send a concise message to the user with an update indicating what you're about to do to ensure they know what you're spending time on. Don't start editing or writing large files before informing the user what you are doing and why.\n\nThe messages you send before tool calls should describe what is immediately about to be done next in very concise language. If there was previous work done, this preamble message should also include a note about the work done so far to bring the user along.\n\n# Presenting your work and final message\n\nYour final message should read naturally, like an update from a concise teammate. For casual conversation, brainstorming tasks, or quick questions from the user, respond in a friendly, conversational tone. You should ask questions, suggest ideas, and adapt to the user's style. If you've finished a large amount of work, when describing what you've done to the user, you should follow the final answer formatting guidelines to communicate substantive changes. You don't need to add structured formatting for one-word answers, greetings, or purely conversational exchanges.\n\nYou can skip heavy formatting for single, simple actions or confirmations. In these cases, respond in plain sentences with any relevant next step or quick option. Reserve multi-section structured responses for results that need grouping or explanation.\n\nThe user is working on the same computer as you, and has access to your work. As such there's no need to show the full contents of large files you have already written unless the user explicitly asks for them. Similarly, if you've created or modified files, there's no need to tell users to \"save the file\" or \"copy the code into a file\"\u2014just reference the file path.\n\nComplete authorized next steps, including relevant tests. Ask before a consequential action that needs approval, and briefly report anything you could not verify.\n\nBrevity is very important as a default. You should be very concise (i.e. no more than 10 lines), but can relax this requirement for tasks where additional detail and comprehensiveness is important for the user's understanding.\n\n## Final answer structure and style guidelines\n\nYou are producing plain text that will later be styled by the CLI. Follow these rules exactly. Formatting should make results easy to scan, but not feel mechanical. Use judgment to decide how much structure adds value.\n\n**Section Headers**\n\n- Use only when they improve clarity \u2014 they are not mandatory for every answer.\n- Choose descriptive names that fit the content\n- Keep headers short (1\u20133 words) and in `**Title Case**`. Always start headers with `**` and end with `**`\n- Use the blank lines required by the renderer for headings and lists.\n- Section headers should only be used where they genuinely improve scanability; avoid fragmenting the answer.\n\n**Bullets**\n\n- Use `-` followed by a space for every bullet.\n- Merge related points when possible; avoid a bullet for every trivial detail.\n- Keep bullets to one line unless breaking for clarity is unavoidable.\n- Group into short lists (4\u20136 bullets) ordered by importance.\n- Use consistent keyword phrasing and formatting across sections.\n\n**Monospace**\n\n- Wrap all commands, file paths, env vars, and code identifiers in backticks (`` `...` ``).\n- Apply to inline examples and to bullet keywords if the keyword itself is a literal file/command.\n- Never mix monospace and bold markers; choose one based on whether it's a keyword (`**`) or inline code/path (`` ` ``).\n\n**File References**\n\nWhen referencing files in your response, make sure to include the relevant start line and always follow the below rules:\n\n- Use inline code to make file paths clickable.\n- Each reference should have a stand alone path. Even if it's the same file.\n- Accepted: absolute, workspace\u2011relative, a/ or b/ diff prefixes, or bare filename/suffix.\n- Line/column (1\u2011based, optional): :line[:column] or #Lline[Ccolumn] (column defaults to 1).\n- Do not use URIs like file://, vscode://, or https://.\n- Do not provide range of lines\n- Examples: src/app.ts, src/app.ts:42, b/server/index.js#L10, C:\\repo\\project\\main.rs:12:5\n\n**Structure**\n\n- Place related bullets together; don't mix unrelated concepts in the same section.\n- Order sections from general \u2192 specific \u2192 supporting info.\n- For subsections (e.g., \"Binaries\" under \"Rust Workspace\"), introduce with a bolded keyword bullet, then list items under it.\n- Match structure to complexity:\n - Multi-part or detailed results \u2192 use clear headers and grouped bullets.\n - Simple results \u2192 minimal headers, possibly just a short list or paragraph.\n\n**Tone**\n\n- Keep the voice collaborative and natural, like a coding partner handing off work.\n- Be concise and factual \u2014 no filler or conversational commentary and avoid unnecessary repetition\n- Use present tense and active voice (e.g., \"Runs tests\" not \"This will run tests\").\n- Keep descriptions self-contained; don't refer to \"above\" or \"below\".\n- Use parallel structure in lists for consistency.\n\n**Don't**\n\n- Don't use literal words \"bold\" or \"monospace\" in the content.\n- Don't nest bullets or create deep hierarchies.\n- Don't output ANSI escape codes directly \u2014 the CLI renderer applies them.\n- Don't cram unrelated keywords into a single bullet; split for clarity.\n- Don't let keyword lists run long \u2014 wrap or reformat for scanability.\n\nGenerally, ensure your final answers adapt their shape and depth to the request. For example, answers to code explanations should have a precise, structured explanation with code references that answer the question directly. For tasks with a simple implementation, lead with the outcome and supplement only with what's needed for clarity. Larger changes can be presented as a logical walkthrough of your approach, grouping related steps, explaining rationale where it adds value, and highlighting next actions to accelerate the user. Your answers should provide the right level of detail while being easily scannable.\n\nFor casual greetings, acknowledgements, or other one-off conversational messages that are not delivering substantive information or structured results, respond naturally without section headers or bullet formatting.\n\n# Professional objectivity\n\nPrioritize technical accuracy and truthfulness over validating the user's beliefs. Focus on facts and problem-solving. Be direct and objective without unnecessary praise or emotional validation. Disagree when needed. When uncertain, investigate before confirming the user's assumptions.\n\n# Proactiveness\n\nProactively complete work that follows from the user's request. Avoid unrelated actions that would surprise the user. Strike a balance between:\n\n1. Doing the right thing when asked, including follow-up actions\n2. Not surprising the user with unrequested actions\n For example, if the user asks how to approach something, answer first; do not immediately jump into edits.\n\n# Following conventions\n\nWhen changing files, first understand the file's conventions. Mimic code style, use existing libraries and utilities, and follow existing patterns.\n\n- NEVER assume a library is available, even if it is well known. Whenever you write code that uses a library or framework, first check that this codebase already uses it (neighboring files, package.json, cargo.toml, go.mod, etc.).\n- When creating a new component, first look at existing components for framework choice, naming, typing, and other conventions.\n- When editing code, first look at surrounding context (especially imports) to understand chosen frameworks/libraries, then make the change idiomatically.\n- Always follow security best practices. Never introduce code that exposes or logs secrets and keys. Never commit secrets or keys to the repository.\n\n# Doing tasks\n\nThe user will primarily request software engineering tasks: bugs, features, refactors, explanations, and more. Recommended steps:\n\n- Use available search/read tools extensively to understand the codebase and the query (in parallel when independent).\n- Implement the solution with the tools available to you.\n- Prefer editing existing files. Create documentation when the task or project instructions require it.\n- Verify when possible with tests. NEVER assume a specific test framework or script \u2014 check README / AGENTS.md or search the repo.\n- Run lint and typecheck commands (for example npm run lint, npm run typecheck, ruff, pnpm lint) if they were provided to you \u2014 see Validating your work for when to run them proactively vs. when to hold off. If you cannot find the correct command, ask the user, and if they supply it, proactively suggest writing it to AGENTS.md so you know next time.\n\n- Tool results and user messages may include <system-reminder> tags. Those tags contain useful reminders. They are NOT part of the user's provided input or the tool result.\n\n# Tool usage policy\n\n- Prefer specialized file tools over shell for reading, editing, writing, listing, and searching when those tools are available. Use the `grep`, `glob`, and `list` tools instead of bash for search and listing \u2014 they are ripgrep-backed and return structured, length-capped results. Use shell for real system commands (git, package managers, builds, tests, process control).\n- When doing broad codebase exploration, use the available search tools and delegate only when the task benefits from independent work.\n- You can call multiple tools in one response. When multiple independent pieces of information are needed, batch tool calls for performance. When making multiple bash tool calls, send a single message with multiple tool calls so they can run in parallel (for example git status and git diff together).\n- Match edit old-text exactly, including whitespace.\n- If a tool call is denied by policy, adapt: use an allowed approach or ask the user. Do not retry the same blocked call in a loop.\n\n## Shell commands\n\nWhen using the shell, you must adhere to the following guidelines:\n\n- When searching for text or files, prefer using `rg` or `rg --files` respectively because `rg` is much faster than alternatives like `grep` and `find`. (If the `rg` command is not found, then use alternatives.) Reach for the shell only when the `grep`/`glob` tools cannot express the query \u2014 for example counting matches, or piping results into another command.\n- Search narrow first: use `rg -l` or `rg -c` to find which files match, then read only those files. Do not dump full match bodies across a repo into context.\n- Never pipe a large file into your context. Do not `cat` a big file; use the `read` tool with an offset/limit, or `sed -n 'START,ENDp'` for a specific range.\n- Do not use python scripts to attempt to output larger chunks of a file.\n\nIMPORTANT: Before you begin work, think about what the code you're editing is supposed to do based on the filenames and directory structure.\n\n# AGENTS.md spec\n\n- Repos often contain AGENTS.md files. These files can appear anywhere within the repository.\n- These files are a way for humans to give you (the agent) instructions or tips for working within the container.\n- Some examples might be: coding conventions, info about how code is organized, or instructions for how to run or test code.\n- Instructions in AGENTS.md files:\n - The scope of an AGENTS.md file is the entire directory tree rooted at the folder that contains it.\n - For every file you touch in the final change, you must obey instructions in any AGENTS.md file whose scope includes that file.\n - Instructions about code style, structure, naming, etc. apply only to code within the AGENTS.md file's scope, unless the file states otherwise.\n - More-deeply-nested AGENTS.md files take precedence in the case of conflicting instructions.\n - Direct system/developer/user instructions (as part of a prompt) take precedence over AGENTS.md instructions.\n- The contents of the AGENTS.md file at the root of the repo and the project directory are loaded into your context automatically and don't need to be re-read. AGENTS.md files in subdirectories are NOT loaded automatically: when working in a subdirectory, or a directory outside the CWD, check for any AGENTS.md files that may be applicable.\n\n# Permissions and safety\n\n- Never commit secrets or keys.\n- Never create a git commit unless the user explicitly asks.\n- Do not run destructive commands (mass delete, force-push, hard reset) unless the user clearly requested them.\n";
@@ -37647,10 +37686,10 @@ var require_dist = __commonJS({
37647
37686
  var init_dist = __esm({
37648
37687
  "../agent-core/dist/index.js"() {
37649
37688
  "use strict";
37650
- init_chunk_UKUTSW3L();
37689
+ init_chunk_W3QH4J4A();
37651
37690
  init_chunk_UGRKZTAD();
37652
- init_chunk_BR4I6MQF();
37653
- init_chunk_6GPS6OKU();
37691
+ init_chunk_R6R6ORR2();
37692
+ init_chunk_J4T6L5LX();
37654
37693
  init_chunk_YXWJW7I5();
37655
37694
  }
37656
37695
  });
@@ -37742,7 +37781,7 @@ function within(root, path) {
37742
37781
  }
37743
37782
  async function resolveReal(path) {
37744
37783
  try {
37745
- return await (0, import_promises21.realpath)(path);
37784
+ return await (0, import_promises22.realpath)(path);
37746
37785
  } catch {
37747
37786
  const parent = (0, import_path9.dirname)(path);
37748
37787
  if (parent === path) return path;
@@ -37771,14 +37810,14 @@ function createWorkspaceFs(roots, writable) {
37771
37810
  return {
37772
37811
  read: async (params) => {
37773
37812
  const path = await confined(params);
37774
- const bytes = await (0, import_promises21.readFile)(path);
37813
+ const bytes = await (0, import_promises22.readFile)(path);
37775
37814
  if (bytes.byteLength > MAX_READ_BYTES) throw new FsDenied(`${path} is too large to read`);
37776
37815
  return { content: sliceLines(bytes.toString("utf8"), params) };
37777
37816
  },
37778
37817
  write: async (params) => {
37779
37818
  if (!writable) throw new FsDenied("This session is read-only");
37780
37819
  const path = await confined(params);
37781
- await (0, import_promises21.writeFile)(path, asString(params.content));
37820
+ await (0, import_promises22.writeFile)(path, asString(params.content));
37782
37821
  return {};
37783
37822
  }
37784
37823
  };
@@ -38381,7 +38420,7 @@ async function acpTurnInput(run, context) {
38381
38420
  const encoded = await Promise.all(
38382
38421
  images.map(async (image) => ({
38383
38422
  mimeType: image.mimeType,
38384
- data: (await (0, import_promises22.readFile)(image.path)).toString("base64")
38423
+ data: (await (0, import_promises23.readFile)(image.path)).toString("base64")
38385
38424
  }))
38386
38425
  );
38387
38426
  return {
@@ -38390,23 +38429,23 @@ async function acpTurnInput(run, context) {
38390
38429
  ...encoded.length ? { images: encoded, imagePaths: images.map((image) => image.path) } : {}
38391
38430
  };
38392
38431
  }
38393
- var import_promises21, import_path9, import_crypto12, import_promises22, 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;
38432
+ var import_promises22, import_path9, import_crypto12, import_promises23, 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;
38394
38433
  var init_acp3 = __esm({
38395
38434
  "../agent-core/dist/providers/acp.js"() {
38396
38435
  "use strict";
38397
- init_chunk_UKUTSW3L();
38436
+ init_chunk_W3QH4J4A();
38398
38437
  init_chunk_UGRKZTAD();
38399
- init_chunk_BR4I6MQF();
38438
+ init_chunk_R6R6ORR2();
38400
38439
  init_chunk_J2KTV5FP();
38401
- init_chunk_6GPS6OKU();
38440
+ init_chunk_J4T6L5LX();
38402
38441
  init_chunk_6WN2R725();
38403
38442
  init_chunk_YXWJW7I5();
38404
- import_promises21 = require("fs/promises");
38443
+ import_promises22 = require("fs/promises");
38405
38444
  import_path9 = require("path");
38406
38445
  init_effort();
38407
38446
  init_acp();
38408
38447
  import_crypto12 = require("crypto");
38409
- import_promises22 = require("fs/promises");
38448
+ import_promises23 = require("fs/promises");
38410
38449
  init_agent2();
38411
38450
  CURSOR_ASK_QUESTION = "cursor/ask_question";
38412
38451
  copilotAcpProfile = {
@@ -38922,7 +38961,7 @@ var init_acp3 = __esm({
38922
38961
  const turn = new AcpTurn(`acp-${this.#turns}-${id}`, this.#profile);
38923
38962
  let finish = () => {
38924
38963
  };
38925
- const done = new Promise((resolve5) => {
38964
+ const done = new Promise((resolve6) => {
38926
38965
  finish = (outcome2) => {
38927
38966
  if (this.#current?.id !== id) return;
38928
38967
  this.#current = void 0;
@@ -38930,7 +38969,7 @@ var init_acp3 = __esm({
38930
38969
  if (this.#state === "busy") this.#state = "idle";
38931
38970
  this.#host.scanDescendants(true);
38932
38971
  this.#emit({ type: "turn_ended", turnId: id, outcome: outcome2 });
38933
- resolve5({ turnId: id, outcome: outcome2, providerSessionId: this.#sessionId });
38972
+ resolve6({ turnId: id, outcome: outcome2, providerSessionId: this.#sessionId });
38934
38973
  };
38935
38974
  });
38936
38975
  const active = { id, turn, done, finish, cancelRequested: false };
@@ -39211,7 +39250,7 @@ var init_acp3 = __esm({
39211
39250
  var init_classify = __esm({
39212
39251
  "../agent-core/dist/classify.js"() {
39213
39252
  "use strict";
39214
- init_chunk_BR4I6MQF();
39253
+ init_chunk_R6R6ORR2();
39215
39254
  init_chunk_YXWJW7I5();
39216
39255
  }
39217
39256
  });
@@ -39375,7 +39414,8 @@ function createPersistentDriver(provider4, options) {
39375
39414
  };
39376
39415
  signal.addEventListener("abort", onAbort, { once: true });
39377
39416
  try {
39378
- const input2 = await provider4.turnInput(spec, inputs, opened.contextPrefix);
39417
+ const contextPrefix = [inputs.turnContext, opened.contextPrefix].filter((part) => part !== void 0).join("\n\n");
39418
+ const input2 = await provider4.turnInput(spec, inputs, contextPrefix || void 0);
39379
39419
  if (signal.aborted) return { outcome: "aborted" };
39380
39420
  const result = await session.sendTurn(input2);
39381
39421
  live.providerSessionId = result.providerSessionId ?? live.providerSessionId;
@@ -39567,10 +39607,10 @@ function parseSseBlock(block) {
39567
39607
  return { type, properties: asRecord(record2.properties) ?? {} };
39568
39608
  }
39569
39609
  function readText(incoming) {
39570
- return new Promise((resolve5, reject) => {
39610
+ return new Promise((resolve23, reject) => {
39571
39611
  const chunks = [];
39572
39612
  incoming.on("data", (chunk) => chunks.push(chunk));
39573
- incoming.on("end", () => resolve5(Buffer.concat(chunks).toString("utf8")));
39613
+ incoming.on("end", () => resolve23(Buffer.concat(chunks).toString("utf8")));
39574
39614
  incoming.on("error", reject);
39575
39615
  });
39576
39616
  }
@@ -39813,7 +39853,7 @@ function notice(kind, message) {
39813
39853
  function promptParts2(input2) {
39814
39854
  const files = (input2.imagePaths ?? []).map((path, index) => ({
39815
39855
  type: "file",
39816
- mime: input2.images?.[index]?.mimeType ?? IMAGE_TYPES[(0, import_path10.extname)(path).toLowerCase()] ?? "application/octet-stream",
39856
+ mime: input2.images?.[index]?.mimeType ?? IMAGE_TYPES[(0, import_path11.extname)(path).toLowerCase()] ?? "application/octet-stream",
39817
39857
  filename: path.split(/[\\/]/).at(-1) ?? path,
39818
39858
  url: (0, import_url2.pathToFileURL)(path).href
39819
39859
  }));
@@ -39905,6 +39945,34 @@ async function startServer(spec, password, options, attempt) {
39905
39945
  }
39906
39946
  }
39907
39947
  }
39948
+ async function canResume(client, sessionId, log) {
39949
+ const stored = await client.readSession(sessionId);
39950
+ if (!stored) {
39951
+ log.warn("opencode.resume_failed", { sessionId, reason: "missing" });
39952
+ return false;
39953
+ }
39954
+ if (!stored.directory) return true;
39955
+ const directory = await client.directory();
39956
+ if (await sameDirectory(stored.directory, directory)) return true;
39957
+ log.warn("opencode.resume_failed", {
39958
+ sessionId,
39959
+ reason: "directory_changed",
39960
+ sessionDirectory: stored.directory,
39961
+ serverDirectory: directory
39962
+ });
39963
+ return false;
39964
+ }
39965
+ async function sameDirectory(left, right) {
39966
+ const [a, b] = await Promise.all([canonicalDirectory(left), canonicalDirectory(right)]);
39967
+ return process.platform === "win32" ? a.toLowerCase() === b.toLowerCase() : a === b;
39968
+ }
39969
+ async function canonicalDirectory(directory) {
39970
+ try {
39971
+ return await (0, import_promises24.realpath)(directory);
39972
+ } catch {
39973
+ return (0, import_path10.resolve)(directory);
39974
+ }
39975
+ }
39908
39976
  async function openSession(session, client, spec, log) {
39909
39977
  const health = await client.health();
39910
39978
  const verdict = judgeOpenCodeVersion(health.version);
@@ -39920,11 +39988,8 @@ async function openSession(session, client, spec, log) {
39920
39988
  }
39921
39989
  await session.connect(client);
39922
39990
  const resumeId = spec.resumeSessionId;
39923
- if (resumeId && await client.hasSession(resumeId)) return { id: resumeId, resumed: true };
39924
- if (resumeId) {
39925
- log.warn("opencode.resume_failed", { sessionId: resumeId });
39926
- session.resumeFailed = true;
39927
- }
39991
+ if (resumeId && await canResume(client, resumeId, log)) return { id: resumeId, resumed: true };
39992
+ if (resumeId) session.resumeFailed = true;
39928
39993
  const id = await client.createSession({ title: spec.title, permission: NON_INTERACTIVE_RULES });
39929
39994
  return { id, resumed: false };
39930
39995
  }
@@ -40075,22 +40140,24 @@ function openCodeTurnInput(run, context) {
40075
40140
  ...images.length ? { imagePaths: images.map((image) => image.path) } : {}
40076
40141
  };
40077
40142
  }
40078
- var import_http4, import_crypto13, import_path10, import_url2, import_crypto14, IDLE_SOCKET_MS2, OpenCodeHttpError, OpenCodeClient, OPENCODE_CONFIG_ENV, OPENCODE_ENGINE, TEXT_PARTS, STEP_PARTS, STOPPED_BY_USER, OpenCodeSubagents, NAMED_KINDS, OPENCODE_ABORTED_ERROR, PROVIDER_EVENT_META, TASK_TOOL_NAME, TASK_RESULT_TAG, TASK_ERROR_TAG, PERMISSION_DENIED, FILE_OPERATIONS, PartReader, NOTHING, NON_INTERACTIVE_PERMISSIONS, CONTENT_FILTER_FINISHES, OUTPUT_PARTS, OpenCodeTurn, LISTENING, OUTPUT_TAIL_LINES, IMAGE_TYPES, OpenCodeSession, OPENCODE_MIN_VERSION, OPENCODE_REQUIREMENT, OPENCODE_TESTED_LINE, OPENCODE_SUPPORTED_MAJOR, DEFAULTS4, STORE_LOCKED, NON_INTERACTIVE_RULES, TITLE_LENGTH, MAX_VARIANT_LENGTH;
40143
+ var import_http4, import_crypto13, import_promises24, import_path10, import_path11, import_url2, import_crypto14, IDLE_SOCKET_MS2, OpenCodeHttpError, OpenCodeClient, OPENCODE_CONFIG_ENV, OPENCODE_ENGINE, TEXT_PARTS, STEP_PARTS, STOPPED_BY_USER, OpenCodeSubagents, NAMED_KINDS, OPENCODE_ABORTED_ERROR, PROVIDER_EVENT_META, TASK_TOOL_NAME, TASK_RESULT_TAG, TASK_ERROR_TAG, PERMISSION_DENIED, FILE_OPERATIONS, PartReader, NOTHING, NON_INTERACTIVE_PERMISSIONS, CONTENT_FILTER_FINISHES, OUTPUT_PARTS, OpenCodeTurn, LISTENING, OUTPUT_TAIL_LINES, IMAGE_TYPES, OpenCodeSession, OPENCODE_MIN_VERSION, OPENCODE_REQUIREMENT, OPENCODE_TESTED_LINE, OPENCODE_SUPPORTED_MAJOR, DEFAULTS4, STORE_LOCKED, NON_INTERACTIVE_RULES, TITLE_LENGTH, MAX_VARIANT_LENGTH;
40079
40144
  var init_opencode = __esm({
40080
40145
  "../agent-core/dist/providers/opencode.js"() {
40081
40146
  "use strict";
40082
- init_chunk_UKUTSW3L();
40147
+ init_chunk_W3QH4J4A();
40083
40148
  init_chunk_UGRKZTAD();
40084
- init_chunk_BR4I6MQF();
40149
+ init_chunk_R6R6ORR2();
40085
40150
  init_chunk_J2KTV5FP();
40086
- init_chunk_6GPS6OKU();
40151
+ init_chunk_J4T6L5LX();
40087
40152
  init_chunk_6WN2R725();
40088
40153
  init_chunk_YXWJW7I5();
40089
40154
  import_http4 = require("http");
40090
40155
  init_runtime_v2();
40091
40156
  import_crypto13 = require("crypto");
40092
- init_agent2();
40157
+ import_promises24 = require("fs/promises");
40093
40158
  import_path10 = require("path");
40159
+ init_agent2();
40160
+ import_path11 = require("path");
40094
40161
  import_url2 = require("url");
40095
40162
  init_acp();
40096
40163
  import_crypto14 = require("crypto");
@@ -40117,11 +40184,11 @@ var init_opencode = __esm({
40117
40184
  this.#engine = engine;
40118
40185
  }
40119
40186
  #open(call) {
40120
- return new Promise((resolve5, reject) => {
40187
+ return new Promise((resolve23, reject) => {
40121
40188
  const outgoing = (0, import_http4.request)(
40122
40189
  `${this.baseUrl}${call.path}`,
40123
40190
  { method: call.method, headers: call.headers, agent: this.#agent },
40124
- resolve5
40191
+ resolve23
40125
40192
  );
40126
40193
  outgoing.on("error", reject);
40127
40194
  outgoing.end(call.body);
@@ -40158,18 +40225,25 @@ var init_opencode = __esm({
40158
40225
  return id;
40159
40226
  }
40160
40227
  /**
40161
- * Whether the server's store still has this session. Only a 404 means it does not: any
40162
- * other failure raises, so a server hiccup never silently replaces the conversation.
40228
+ * The stored session, or undefined when the server's store does not have it. Only a 404
40229
+ * means that: any other failure raises, so a server hiccup never silently replaces the
40230
+ * conversation.
40163
40231
  */
40164
- async hasSession(sessionId) {
40232
+ async readSession(sessionId) {
40165
40233
  try {
40166
- await this.#call("session read", "GET", `/session/${encodeURIComponent(sessionId)}`);
40167
- return true;
40234
+ const body = asRecord(
40235
+ await this.#call("session read", "GET", `/session/${encodeURIComponent(sessionId)}`)
40236
+ );
40237
+ return { directory: asString(body?.directory) };
40168
40238
  } catch (error61) {
40169
- if (error61 instanceof OpenCodeHttpError && error61.status === 404) return false;
40239
+ if (error61 instanceof OpenCodeHttpError && error61.status === 404) return void 0;
40170
40240
  throw error61;
40171
40241
  }
40172
40242
  }
40243
+ /** The directory the server serves when a request names none: its own cwd. */
40244
+ async directory() {
40245
+ return asString(asRecord(await this.#call("path read", "GET", "/path"))?.directory);
40246
+ }
40173
40247
  /** Answers 204 at once; the turn itself arrives on `/event`. */
40174
40248
  async promptAsync(sessionId, body) {
40175
40249
  await this.#call("prompt", "POST", `/session/${encodeURIComponent(sessionId)}/prompt_async`, {
@@ -40855,8 +40929,8 @@ var init_opencode = __esm({
40855
40929
  onExit: (exit) => this.#onExit(exit)
40856
40930
  }
40857
40931
  );
40858
- this.#listening = new Promise((resolve5, reject) => {
40859
- this.#announce = resolve5;
40932
+ this.#listening = new Promise((resolve23, reject) => {
40933
+ this.#announce = resolve23;
40860
40934
  void this.#host.exited.then(
40861
40935
  () => reject(
40862
40936
  new CoreFault(
@@ -40945,12 +41019,8 @@ var init_opencode = __esm({
40945
41019
  await client.promptAsync(sessionId, body);
40946
41020
  } catch (error61) {
40947
41021
  if (this.#state === "closed") return;
41022
+ if (this.#current?.id !== active.id) return;
40948
41023
  const message = error61 instanceof Error ? error61.message : String(error61);
40949
- this.#emit({
40950
- type: "update",
40951
- turnId: active.id,
40952
- update: noticeUpdate("error", "provider", message)
40953
- });
40954
41024
  active.finish({ status: "failed", error: classifyProviderError(message) });
40955
41025
  }
40956
41026
  }
@@ -41021,7 +41091,7 @@ var init_opencode = __esm({
41021
41091
  );
41022
41092
  let finish = () => {
41023
41093
  };
41024
- const done = new Promise((resolve5) => {
41094
+ const done = new Promise((resolve23) => {
41025
41095
  finish = (outcome2) => {
41026
41096
  if (this.#current?.id !== id) return;
41027
41097
  this.#current = void 0;
@@ -41029,7 +41099,7 @@ var init_opencode = __esm({
41029
41099
  if (outcome2.status !== "completed") this.#repairPending = true;
41030
41100
  this.#host.scanDescendants(true);
41031
41101
  this.#emit({ type: "turn_ended", turnId: id, outcome: outcome2 });
41032
- resolve5({ turnId: id, outcome: outcome2, providerSessionId: this.#sessionId });
41102
+ resolve23({ turnId: id, outcome: outcome2, providerSessionId: this.#sessionId });
41033
41103
  };
41034
41104
  });
41035
41105
  const active = {
@@ -41209,7 +41279,7 @@ function createAlanCodeHolderDriver(options) {
41209
41279
  const engine = resolveAlanCodeEngine({ env, platform, packaged: [] });
41210
41280
  const engineRoot = alanCodeEngineRoot(env.HOME?.trim() || (0, import_node_os2.homedir)());
41211
41281
  options.log.info("alan_code.engine", { command: engine.command, source: engine.source });
41212
- const open3 = async (planned) => {
41282
+ const open4 = async (planned) => {
41213
41283
  if (planned.profile === void 0) throw refuseWithoutCredential();
41214
41284
  const { opencode } = planned;
41215
41285
  const profile = await prepareAlanCodeProfile({
@@ -41266,7 +41336,7 @@ function createAlanCodeHolderDriver(options) {
41266
41336
  };
41267
41337
  },
41268
41338
  canResume: () => true,
41269
- open: open3,
41339
+ open: open4,
41270
41340
  turnInput: async (spec, inputs, contextPrefix) => openCodeTurnInput(spec, {
41271
41341
  attachments: inputs.attachments,
41272
41342
  skills: [],
@@ -41493,8 +41563,8 @@ function createDroidPeer(writer, handlers) {
41493
41563
  },
41494
41564
  request: (method, params = {}) => {
41495
41565
  const id = `alan-${counter.next++}`;
41496
- return new Promise((resolve5, reject) => {
41497
- pending.set(id, { method, resolve: resolve5, reject });
41566
+ return new Promise((resolve6, reject) => {
41567
+ pending.set(id, { method, resolve: resolve6, reject });
41498
41568
  writer.write(envelope("request", { id, method, params })).catch((error61) => {
41499
41569
  pending.delete(id);
41500
41570
  reject(error61 instanceof Error ? error61 : new Error(String(error61)));
@@ -41829,25 +41899,25 @@ async function droidTurnInput(run, context) {
41829
41899
  const encoded = await Promise.all(
41830
41900
  images.map(async (image) => ({
41831
41901
  mimeType: image.mimeType,
41832
- data: (await (0, import_promises23.readFile)(image.path)).toString("base64")
41902
+ data: (await (0, import_promises25.readFile)(image.path)).toString("base64")
41833
41903
  }))
41834
41904
  );
41835
41905
  return { turnId: run.runId, text: text2, ...encoded.length ? { images: encoded } : {} };
41836
41906
  }
41837
- var import_crypto15, import_promises23, FACTORY_API_VERSION, FACTORY_PROTOCOL_VERSION, SUBAGENT_TOOLS, TASK_OUTPUT_TOOLS, TASK_STOP_TOOLS, SILENT2, DroidTurn, STDERR_TAIL_LINES5, UNSUPPORTED_REQUEST2, DroidSession, DEFAULTS5, DROID_REQUIREMENT, DROID_JSONRPC_ARGS;
41907
+ var import_crypto15, import_promises25, FACTORY_API_VERSION, FACTORY_PROTOCOL_VERSION, SUBAGENT_TOOLS, TASK_OUTPUT_TOOLS, TASK_STOP_TOOLS, SILENT2, DroidTurn, STDERR_TAIL_LINES5, UNSUPPORTED_REQUEST2, DroidSession, DEFAULTS5, DROID_REQUIREMENT, DROID_JSONRPC_ARGS;
41838
41908
  var init_droid = __esm({
41839
41909
  "../agent-core/dist/providers/droid.js"() {
41840
41910
  "use strict";
41841
- init_chunk_UKUTSW3L();
41911
+ init_chunk_W3QH4J4A();
41842
41912
  init_chunk_UGRKZTAD();
41843
- init_chunk_BR4I6MQF();
41913
+ init_chunk_R6R6ORR2();
41844
41914
  init_chunk_J2KTV5FP();
41845
- init_chunk_6GPS6OKU();
41915
+ init_chunk_J4T6L5LX();
41846
41916
  init_chunk_6WN2R725();
41847
41917
  init_chunk_YXWJW7I5();
41848
41918
  init_runtime_v2();
41849
41919
  import_crypto15 = require("crypto");
41850
- import_promises23 = require("fs/promises");
41920
+ import_promises25 = require("fs/promises");
41851
41921
  init_agent2();
41852
41922
  FACTORY_API_VERSION = "1.0.0";
41853
41923
  FACTORY_PROTOCOL_VERSION = "1.187.0";
@@ -42119,14 +42189,14 @@ var init_droid = __esm({
42119
42189
  const turn = new DroidTurn(sessionId, this.#memory);
42120
42190
  let finish = () => {
42121
42191
  };
42122
- const done = new Promise((resolve5) => {
42192
+ const done = new Promise((resolve6) => {
42123
42193
  finish = (outcome2) => {
42124
42194
  if (this.#current?.id !== id) return;
42125
42195
  this.#current = void 0;
42126
42196
  if (this.#state === "busy") this.#state = "idle";
42127
42197
  this.#host.scanDescendants(true);
42128
42198
  this.#emit({ type: "turn_ended", turnId: id, outcome: outcome2 });
42129
- resolve5({ turnId: id, outcome: outcome2, providerSessionId: this.#sessionId });
42199
+ resolve6({ turnId: id, outcome: outcome2, providerSessionId: this.#sessionId });
42130
42200
  };
42131
42201
  });
42132
42202
  const active = { id, turn, done, finish, cancelRequested: false };
@@ -42351,21 +42421,21 @@ function antigravityArgs(input2, capabilities, prompt) {
42351
42421
  ];
42352
42422
  }
42353
42423
  function workspaceRoot(cwd) {
42354
- for (let current = (0, import_path11.resolve)(cwd); ; current = (0, import_path11.dirname)(current)) {
42355
- if ((0, import_fs8.existsSync)((0, import_path11.join)(current, ".git"))) return current;
42356
- if ((0, import_path11.dirname)(current) === current) return (0, import_path11.resolve)(cwd);
42424
+ for (let current = (0, import_path12.resolve)(cwd); ; current = (0, import_path12.dirname)(current)) {
42425
+ if ((0, import_fs8.existsSync)((0, import_path12.join)(current, ".git"))) return current;
42426
+ if ((0, import_path12.dirname)(current) === current) return (0, import_path12.resolve)(cwd);
42357
42427
  }
42358
42428
  }
42359
42429
  function instructionPaths(cwd) {
42360
42430
  const root = workspaceRoot(cwd);
42361
42431
  const paths = [];
42362
- for (let current = (0, import_path11.resolve)(cwd); ; current = (0, import_path11.dirname)(current)) {
42363
- const path = (0, import_path11.join)(current, INSTRUCTIONS_FILE);
42432
+ for (let current = (0, import_path12.resolve)(cwd); ; current = (0, import_path12.dirname)(current)) {
42433
+ const path = (0, import_path12.join)(current, INSTRUCTIONS_FILE);
42364
42434
  try {
42365
42435
  if ((0, import_fs8.existsSync)(path) && (0, import_fs8.statSync)(path).isFile()) paths.unshift(path);
42366
42436
  } catch {
42367
42437
  }
42368
- if (current === root || (0, import_path11.dirname)(current) === current) return paths;
42438
+ if (current === root || (0, import_path12.dirname)(current) === current) return paths;
42369
42439
  }
42370
42440
  }
42371
42441
  function antigravityWorkspaceInstructions(cwd, maxChars = MAX_INSTRUCTION_CHARS) {
@@ -42619,7 +42689,7 @@ function normalizeAntigravityFrame(event) {
42619
42689
  }
42620
42690
  function antigravityBrainRoot(env) {
42621
42691
  const home = env.HOME?.trim() || env.USERPROFILE?.trim();
42622
- return home ? (0, import_path12.resolve)(home, ".gemini", "antigravity-cli", "brain") : void 0;
42692
+ return home ? (0, import_path13.resolve)(home, ".gemini", "antigravity-cli", "brain") : void 0;
42623
42693
  }
42624
42694
  function parseEntry(text2) {
42625
42695
  try {
@@ -42657,14 +42727,14 @@ function childTranscriptPath(root, frame) {
42657
42727
  try {
42658
42728
  const url2 = new URL(logUri);
42659
42729
  if (url2.protocol !== "file:") return void 0;
42660
- path = (0, import_path12.resolve)((0, import_url3.fileURLToPath)(url2));
42730
+ path = (0, import_path13.resolve)((0, import_url3.fileURLToPath)(url2));
42661
42731
  } catch {
42662
42732
  return void 0;
42663
42733
  }
42664
- const fromRoot = (0, import_path12.relative)(root, path);
42665
- if (!fromRoot || (0, import_path12.isAbsolute)(fromRoot) || fromRoot.split(import_path12.sep).includes("..")) return void 0;
42734
+ const fromRoot = (0, import_path13.relative)(root, path);
42735
+ if (!fromRoot || (0, import_path13.isAbsolute)(fromRoot) || fromRoot.split(import_path13.sep).includes("..")) return void 0;
42666
42736
  const expected = [conversationId, ...LOG_DIRS, TRANSCRIPT_FILE];
42667
- const segments = fromRoot.split(import_path12.sep);
42737
+ const segments = fromRoot.split(import_path13.sep);
42668
42738
  const matches = segments.length === expected.length && segments.every((segment, index) => segment === expected[index]);
42669
42739
  return matches ? path : void 0;
42670
42740
  }
@@ -42903,21 +42973,21 @@ function antigravityTurnInput(run, context) {
42903
42973
  });
42904
42974
  return { turnId: run.runId, text: appendImagePathReferences(text2, images) };
42905
42975
  }
42906
- var import_fs8, import_path11, import_path12, import_url3, import_crypto16, NO_ANTIGRAVITY_CAPABILITIES, INSTRUCTIONS_FILE, MAX_INSTRUCTION_CHARS, SHORTENED_NOTE, DIFF_BLOCK_START, DIFF_BLOCK_END, HUNK_HEADER, TRANSCRIPT_FILE, FULL_TRANSCRIPT_FILE, LOG_DIRS, TOOL_RESULT_TYPES, BrainTranscript, AntigravityTranscripts, ANTIGRAVITY_GRAMMAR_NAME, AntigravityGrammar, ignored, HANDLERS, SUCCESSFUL_STATUSES, SESSION_START_TYPES, RESULT_TYPES, SUBAGENT_START_TYPES, RESUME_FORKED, EXITED_WITHOUT_RESULT, AntigravityTurn, DEFAULTS6, AntigravitySession, WINDOWS_LINE_MARGIN;
42976
+ var import_fs8, import_path12, import_path13, import_url3, import_crypto16, NO_ANTIGRAVITY_CAPABILITIES, INSTRUCTIONS_FILE, MAX_INSTRUCTION_CHARS, SHORTENED_NOTE, DIFF_BLOCK_START, DIFF_BLOCK_END, HUNK_HEADER, TRANSCRIPT_FILE, FULL_TRANSCRIPT_FILE, LOG_DIRS, TOOL_RESULT_TYPES, BrainTranscript, AntigravityTranscripts, ANTIGRAVITY_GRAMMAR_NAME, AntigravityGrammar, ignored, HANDLERS, SUCCESSFUL_STATUSES, SESSION_START_TYPES, RESULT_TYPES, SUBAGENT_START_TYPES, RESUME_FORKED, EXITED_WITHOUT_RESULT, AntigravityTurn, DEFAULTS6, AntigravitySession, WINDOWS_LINE_MARGIN;
42907
42977
  var init_antigravity = __esm({
42908
42978
  "../agent-core/dist/providers/antigravity.js"() {
42909
42979
  "use strict";
42910
42980
  init_chunk_DALFHI4B();
42911
- init_chunk_UKUTSW3L();
42981
+ init_chunk_W3QH4J4A();
42912
42982
  init_chunk_UGRKZTAD();
42913
- init_chunk_BR4I6MQF();
42914
- init_chunk_6GPS6OKU();
42983
+ init_chunk_R6R6ORR2();
42984
+ init_chunk_J4T6L5LX();
42915
42985
  init_chunk_6WN2R725();
42916
42986
  init_chunk_YXWJW7I5();
42917
42987
  import_fs8 = require("fs");
42918
- import_path11 = require("path");
42919
- init_effort();
42920
42988
  import_path12 = require("path");
42989
+ init_effort();
42990
+ import_path13 = require("path");
42921
42991
  import_url3 = require("url");
42922
42992
  import_crypto16 = require("crypto");
42923
42993
  init_agent2();
@@ -42957,7 +43027,7 @@ var init_antigravity = __esm({
42957
43027
  #full;
42958
43028
  constructor(path) {
42959
43029
  this.#cursor = new TranscriptCursor(path);
42960
- this.#fullPath = (0, import_path12.resolve)((0, import_path12.dirname)(path), FULL_TRANSCRIPT_FILE);
43030
+ this.#fullPath = (0, import_path13.resolve)((0, import_path13.dirname)(path), FULL_TRANSCRIPT_FILE);
42961
43031
  }
42962
43032
  skipExisting() {
42963
43033
  this.#cursor.read();
@@ -43005,7 +43075,7 @@ var init_antigravity = __esm({
43005
43075
  /** A conversation this turn did not resume was created by it, so it is read whole. */
43006
43076
  trackParent(conversationId) {
43007
43077
  if (this.#parent?.conversationId === conversationId) return;
43008
- const path = (0, import_path12.resolve)(this.#root, conversationId, ...LOG_DIRS, TRANSCRIPT_FILE);
43078
+ const path = (0, import_path13.resolve)(this.#root, conversationId, ...LOG_DIRS, TRANSCRIPT_FILE);
43009
43079
  this.#parent = { conversationId, transcript: new BrainTranscript(path) };
43010
43080
  }
43011
43081
  /** A launcher keeps the first valid transcript it names; later frames change nothing. */
@@ -43410,8 +43480,8 @@ function parseConfig(raw) {
43410
43480
  }
43411
43481
  }
43412
43482
  async function writeCommandCodeProjectMcp(cwd, mcp) {
43413
- const path = (0, import_path13.join)(cwd, ".mcp.json");
43414
- const original = await (0, import_promises24.readFile)(path, "utf8").catch(() => null);
43483
+ const path = (0, import_path14.join)(cwd, ".mcp.json");
43484
+ const original = await (0, import_promises26.readFile)(path, "utf8").catch(() => null);
43415
43485
  const config2 = parseConfig(original);
43416
43486
  const next = {
43417
43487
  ...config2,
@@ -43428,12 +43498,12 @@ async function writeCommandCodeProjectMcp(cwd, mcp) {
43428
43498
  }
43429
43499
  }
43430
43500
  };
43431
- await (0, import_promises24.mkdir)(cwd, { recursive: true });
43432
- await (0, import_promises24.writeFile)(path, `${JSON.stringify(next, null, 2)}
43501
+ await (0, import_promises26.mkdir)(cwd, { recursive: true });
43502
+ await (0, import_promises26.writeFile)(path, `${JSON.stringify(next, null, 2)}
43433
43503
  `);
43434
43504
  return async () => {
43435
- if (original === null) await (0, import_promises24.rm)(path, { force: true });
43436
- else await (0, import_promises24.writeFile)(path, original);
43505
+ if (original === null) await (0, import_promises26.rm)(path, { force: true });
43506
+ else await (0, import_promises26.writeFile)(path, original);
43437
43507
  };
43438
43508
  }
43439
43509
  function commandCodeString(value) {
@@ -43605,19 +43675,19 @@ function commandCodeTurnInput(run, context) {
43605
43675
  });
43606
43676
  return { turnId: run.runId, text: appendImagePathReferences(text2, images) };
43607
43677
  }
43608
- var import_promises24, import_path13, import_crypto17, COMMAND_CODE_GRAMMAR_NAME, SILENT3, CommandCodeGrammar, SHELL_TOOL, STOP_TOOLS, REPORTED_STATUS, SHELL_STATUS, SWEEP_INTERVAL_MS, CommandCodeBackgroundTasks, EXITED_WITHOUT_RESULT2, CommandCodeTurn, COMMAND_CODE_MAX_TURNS, DEFAULTS7, CommandCodeSession;
43678
+ var import_promises26, import_path14, import_crypto17, COMMAND_CODE_GRAMMAR_NAME, SILENT3, CommandCodeGrammar, SHELL_TOOL, STOP_TOOLS, REPORTED_STATUS, SHELL_STATUS, SWEEP_INTERVAL_MS, CommandCodeBackgroundTasks, EXITED_WITHOUT_RESULT2, CommandCodeTurn, COMMAND_CODE_MAX_TURNS, DEFAULTS7, CommandCodeSession;
43609
43679
  var init_command_code = __esm({
43610
43680
  "../agent-core/dist/providers/command-code.js"() {
43611
43681
  "use strict";
43612
- init_chunk_UKUTSW3L();
43682
+ init_chunk_W3QH4J4A();
43613
43683
  init_chunk_UGRKZTAD();
43614
- init_chunk_BR4I6MQF();
43684
+ init_chunk_R6R6ORR2();
43615
43685
  init_chunk_J2KTV5FP();
43616
- init_chunk_6GPS6OKU();
43686
+ init_chunk_J4T6L5LX();
43617
43687
  init_chunk_6WN2R725();
43618
43688
  init_chunk_YXWJW7I5();
43619
- import_promises24 = require("fs/promises");
43620
- import_path13 = require("path");
43689
+ import_promises26 = require("fs/promises");
43690
+ import_path14 = require("path");
43621
43691
  init_agent2();
43622
43692
  init_runtime_v2();
43623
43693
  init_acp();
@@ -44478,7 +44548,7 @@ function transportFailure(request2, error61) {
44478
44548
  });
44479
44549
  }
44480
44550
  function readBody(incoming, url2, maxBytes) {
44481
- return new Promise((resolve5, reject) => {
44551
+ return new Promise((resolve6, reject) => {
44482
44552
  const declared = Number(incoming.headers["content-length"] ?? "0");
44483
44553
  if (maxBytes !== void 0 && declared > maxBytes) {
44484
44554
  incoming.destroy();
@@ -44497,7 +44567,7 @@ function readBody(incoming, url2, maxBytes) {
44497
44567
  chunks.push(chunk);
44498
44568
  });
44499
44569
  incoming.on("error", reject);
44500
- incoming.on("end", () => resolve5(Buffer.concat(chunks)));
44570
+ incoming.on("end", () => resolve6(Buffer.concat(chunks)));
44501
44571
  });
44502
44572
  }
44503
44573
  function isConnectionReset(error61) {
@@ -44505,7 +44575,7 @@ function isConnectionReset(error61) {
44505
44575
  }
44506
44576
  function exchange(request2, agents, attempt = 0) {
44507
44577
  const { signal, url: url2 } = request2;
44508
- return new Promise((resolve5, reject) => {
44578
+ return new Promise((resolve6, reject) => {
44509
44579
  if (signal.aborted) {
44510
44580
  reject(signal.reason);
44511
44581
  return;
@@ -44532,7 +44602,7 @@ function exchange(request2, agents, attempt = 0) {
44532
44602
  const stale = outgoing.reusedSocket && !responded && isConnectionReset(error61);
44533
44603
  if (stale && attempt < STALE_SOCKET_RETRIES && !signal.aborted) {
44534
44604
  settle();
44535
- resolve5(exchange(request2, agents, attempt + 1));
44605
+ resolve6(exchange(request2, agents, attempt + 1));
44536
44606
  return;
44537
44607
  }
44538
44608
  fail(error61);
@@ -44545,7 +44615,7 @@ function exchange(request2, agents, attempt = 0) {
44545
44615
  readBody(incoming, url2, isRedirect(status) ? void 0 : request2.maxBodyBytes).then(
44546
44616
  (body) => {
44547
44617
  settle();
44548
- resolve5({ status, headers: incoming.headers, body });
44618
+ resolve6({ status, headers: incoming.headers, body });
44549
44619
  },
44550
44620
  fail
44551
44621
  );
@@ -44695,7 +44765,7 @@ var GitFault = class extends Error {
44695
44765
  var import_node_child_process = require("child_process");
44696
44766
 
44697
44767
  // ../agent-core/dist/process.js
44698
- init_chunk_6GPS6OKU();
44768
+ init_chunk_J4T6L5LX();
44699
44769
  init_chunk_YXWJW7I5();
44700
44770
 
44701
44771
  // src/capabilities/git/run-git.ts
@@ -44827,7 +44897,7 @@ function createGitRunner(options) {
44827
44897
  }
44828
44898
  await killProcessTree(child.pid, { signal: "SIGKILL", child, platform });
44829
44899
  };
44830
- return new Promise((resolve5, reject) => {
44900
+ return new Promise((resolve6, reject) => {
44831
44901
  let ending = null;
44832
44902
  const stop = (next) => {
44833
44903
  if (ending !== null) return;
@@ -44852,7 +44922,7 @@ function createGitRunner(options) {
44852
44922
  signal.removeEventListener("abort", onAbort);
44853
44923
  const final = ending ?? last;
44854
44924
  if (final.kind === "exited") {
44855
- resolve5({ exitCode: final.exitCode, stdout: stdout.text(), stderr: stderr.text() });
44925
+ resolve6({ exitCode: final.exitCode, stdout: stdout.text(), stderr: stderr.text() });
44856
44926
  } else {
44857
44927
  reject(faultFor(final, command));
44858
44928
  }
@@ -44874,9 +44944,97 @@ function createGitRunner(options) {
44874
44944
  };
44875
44945
  }
44876
44946
 
44877
- // src/platform/credential-store/credential-store.ts
44947
+ // src/capabilities/git/checkout-freshness.ts
44878
44948
  var import_node_crypto3 = require("crypto");
44879
44949
  var import_promises7 = require("fs/promises");
44950
+ var import_node_path3 = require("path");
44951
+ init_zod();
44952
+ var REMOTE = "origin";
44953
+ var snapshotSchema = external_exports.object({
44954
+ branch: external_exports.string().min(1),
44955
+ base: external_exports.string().min(1),
44956
+ head: external_exports.string().min(1),
44957
+ published: external_exports.string(),
44958
+ shallow: external_exports.boolean(),
44959
+ commonDir: external_exports.string().min(1)
44960
+ });
44961
+ var freshnessSchema = external_exports.discriminatedUnion("state", [
44962
+ external_exports.object({ state: external_exports.literal("checking"), path: external_exports.string() }),
44963
+ external_exports.object({ state: external_exports.literal("kept"), path: external_exports.string(), reason: external_exports.string() }),
44964
+ external_exports.object({ state: external_exports.literal("current"), path: external_exports.string(), snapshot: snapshotSchema }),
44965
+ external_exports.object({
44966
+ state: external_exports.literal("behind"),
44967
+ path: external_exports.string(),
44968
+ snapshot: snapshotSchema,
44969
+ tip: external_exports.string().min(1),
44970
+ fetched: external_exports.boolean()
44971
+ }),
44972
+ external_exports.object({
44973
+ state: external_exports.literal("failed"),
44974
+ path: external_exports.string(),
44975
+ snapshot: snapshotSchema.optional(),
44976
+ reason: external_exports.string()
44977
+ })
44978
+ ]);
44979
+ function freshnessFile(dir, path) {
44980
+ return (0, import_node_path3.join)(dir, `${(0, import_node_crypto3.createHash)("sha256").update(path).digest("hex").slice(0, 32)}.json`);
44981
+ }
44982
+ function parseStatus(stdout) {
44983
+ const lines = stdout.split("\n").filter((line) => line.length > 0);
44984
+ const header = /* @__PURE__ */ new Map();
44985
+ for (const line of lines) {
44986
+ const [hash2, key, value] = line.split(" ");
44987
+ if (hash2 === "#" && key !== void 0 && value !== void 0) header.set(key, value);
44988
+ }
44989
+ const head = header.get("branch.oid");
44990
+ const branch = header.get("branch.head");
44991
+ const upstream = header.get("branch.upstream") ?? "";
44992
+ return {
44993
+ head: head === void 0 || head === "(initial)" ? null : head,
44994
+ branch: branch === void 0 || branch === "(detached)" ? null : branch,
44995
+ base: upstream.startsWith(`${REMOTE}/`) ? upstream.slice(REMOTE.length + 1) : null,
44996
+ ahead: Number(header.get("branch.ab")?.slice(1) ?? 0),
44997
+ dirty: lines.some((line) => !line.startsWith("# "))
44998
+ };
44999
+ }
45000
+ async function readCheckoutStatus(git, cwd, signal) {
45001
+ const output2 = await git.run(
45002
+ {
45003
+ cwd,
45004
+ args: ["status", "--porcelain=v2", "--branch", "--untracked-files=no"],
45005
+ readOnly: true
45006
+ },
45007
+ signal
45008
+ );
45009
+ return output2.exitCode === 0 ? parseStatus(output2.stdout) : null;
45010
+ }
45011
+ async function isCheckout(path) {
45012
+ return (0, import_promises7.stat)((0, import_node_path3.join)(path, ".git")).then(
45013
+ () => true,
45014
+ () => false
45015
+ );
45016
+ }
45017
+ async function checkoutsUnder(root) {
45018
+ if (await isCheckout(root)) return [root];
45019
+ const entries = await (0, import_promises7.readdir)(root, { withFileTypes: true }).catch(() => []);
45020
+ const found = await Promise.all(
45021
+ entries.filter((entry) => entry.isDirectory()).map(
45022
+ async (entry) => await isCheckout((0, import_node_path3.join)(root, entry.name)) ? (0, import_node_path3.join)(root, entry.name) : null
45023
+ )
45024
+ );
45025
+ return found.filter((path) => path !== null);
45026
+ }
45027
+ async function readCheckoutFreshness(dir, path) {
45028
+ for (let current = path; ; current = (0, import_node_path3.dirname)(current)) {
45029
+ const read = await readJsonFile(freshnessFile(dir, current), freshnessSchema);
45030
+ if (read.kind === "ok") return read.value;
45031
+ if ((0, import_node_path3.dirname)(current) === current) return null;
45032
+ }
45033
+ }
45034
+
45035
+ // src/platform/credential-store/credential-store.ts
45036
+ var import_node_crypto4 = require("crypto");
45037
+ var import_promises8 = require("fs/promises");
44880
45038
 
44881
45039
  // src/platform/credential-store/parse.ts
44882
45040
  function parseStoredJson(text2, schema) {
@@ -44892,16 +45050,16 @@ function parseStoredJson(text2, schema) {
44892
45050
 
44893
45051
  // src/platform/windows-helper.ts
44894
45052
  var import_node_fs3 = require("fs");
44895
- var import_node_path3 = require("path");
45053
+ var import_node_path4 = require("path");
44896
45054
  var import_node_url = require("url");
44897
45055
  var import_meta = {};
44898
45056
  function windowsHelperPath(entry = process.argv[1]) {
44899
- const packaged = entry === void 0 ? null : (0, import_node_path3.join)((0, import_node_path3.dirname)((0, import_node_path3.resolve)(entry)), "alan-winhelper.exe");
45057
+ const packaged = entry === void 0 ? null : (0, import_node_path4.join)((0, import_node_path4.dirname)((0, import_node_path4.resolve)(entry)), "alan-winhelper.exe");
44900
45058
  if (entry !== void 0) {
44901
45059
  if (packaged !== null && (0, import_node_fs3.existsSync)(packaged)) return packaged;
44902
45060
  }
44903
45061
  try {
44904
- const local = (0, import_node_path3.resolve)((0, import_node_path3.dirname)((0, import_node_url.fileURLToPath)(import_meta.url)), "../../dist/alan-winhelper.exe");
45062
+ const local = (0, import_node_path4.resolve)((0, import_node_path4.dirname)((0, import_node_url.fileURLToPath)(import_meta.url)), "../../dist/alan-winhelper.exe");
44905
45063
  return (0, import_node_fs3.existsSync)(local) ? local : packaged;
44906
45064
  } catch {
44907
45065
  return packaged;
@@ -44969,13 +45127,13 @@ function createFileCredentialStore(path) {
44969
45127
  kind: "file",
44970
45128
  read: (schema) => readJsonFile(path, schema),
44971
45129
  write: (value) => writeJsonFileAtomic(path, value),
44972
- clear: () => (0, import_promises7.rm)(path, { force: true })
45130
+ clear: () => (0, import_promises8.rm)(path, { force: true })
44973
45131
  };
44974
45132
  }
44975
45133
  var KEYCHAIN_SERVICE = "ai.tryalan.runtime";
44976
45134
  var KEYCHAIN_NOT_FOUND = 44;
44977
45135
  function keychainAccount(stateDir) {
44978
- return `state-${(0, import_node_crypto3.createHash)("sha256").update(stateDir).digest("hex").slice(0, 16)}`;
45136
+ return `state-${(0, import_node_crypto4.createHash)("sha256").update(stateDir).digest("hex").slice(0, 16)}`;
44979
45137
  }
44980
45138
  function windowsCredentialTarget(stateDir) {
44981
45139
  return `${KEYCHAIN_SERVICE}/${keychainAccount(stateDir.toLowerCase())}`;
@@ -45062,16 +45220,16 @@ function defaultCredentialStoreKind(platform) {
45062
45220
 
45063
45221
  // src/platform/install.ts
45064
45222
  var import_node_child_process3 = require("child_process");
45065
- var import_node_crypto4 = require("crypto");
45223
+ var import_node_crypto5 = require("crypto");
45066
45224
  var import_node_fs4 = require("fs");
45067
- var import_promises9 = require("fs/promises");
45068
- var import_node_path4 = require("path");
45225
+ var import_promises10 = require("fs/promises");
45226
+ var import_node_path5 = require("path");
45069
45227
  var import_node_util2 = require("util");
45070
45228
  init_zod();
45071
45229
 
45072
45230
  // src/platform/process-identity.ts
45073
45231
  var import_node_child_process2 = require("child_process");
45074
- var import_promises8 = require("fs/promises");
45232
+ var import_promises9 = require("fs/promises");
45075
45233
  var import_node_util = require("util");
45076
45234
  var execFileAsync = (0, import_node_util.promisify)(import_node_child_process2.execFile);
45077
45235
  function isProcessAlive(pid) {
@@ -45083,13 +45241,13 @@ function isProcessAlive(pid) {
45083
45241
  }
45084
45242
  }
45085
45243
  async function linuxStartTime(pid) {
45086
- const stat13 = await (0, import_promises8.readFile)(`/proc/${pid}/stat`, "utf8").catch(() => null);
45087
- if (stat13 === null) return null;
45088
- const fields = stat13.slice(stat13.lastIndexOf(")") + 2).split(" ");
45244
+ const stat14 = await (0, import_promises9.readFile)(`/proc/${pid}/stat`, "utf8").catch(() => null);
45245
+ if (stat14 === null) return null;
45246
+ const fields = stat14.slice(stat14.lastIndexOf(")") + 2).split(" ");
45089
45247
  return fields[19] ?? null;
45090
45248
  }
45091
45249
  async function linuxCommand(pid) {
45092
- const raw = await (0, import_promises8.readFile)(`/proc/${pid}/cmdline`, "utf8").catch(() => null);
45250
+ const raw = await (0, import_promises9.readFile)(`/proc/${pid}/cmdline`, "utf8").catch(() => null);
45093
45251
  return raw === null ? null : normalizeCommand(raw.replaceAll("\0", " "));
45094
45252
  }
45095
45253
  async function darwinCommand(pid) {
@@ -45183,11 +45341,11 @@ async function mayBeSameProcess(expected, probe = systemProcessProbe) {
45183
45341
  var execFileAsync2 = (0, import_node_util2.promisify)(import_node_child_process3.execFile);
45184
45342
  var packageJsonSchema = external_exports.object({ version: external_exports.string().min(1) });
45185
45343
  function markVersionInUse(bundlePath) {
45186
- const versionDir = (0, import_node_path4.dirname)(bundlePath);
45187
- if ((0, import_node_path4.basename)((0, import_node_path4.dirname)(versionDir)) !== "versions") return { [Symbol.dispose]: () => {
45344
+ const versionDir = (0, import_node_path5.dirname)(bundlePath);
45345
+ if ((0, import_node_path5.basename)((0, import_node_path5.dirname)(versionDir)) !== "versions") return { [Symbol.dispose]: () => {
45188
45346
  } };
45189
- const marker = (0, import_node_path4.join)(versionDir, ".running", String(process.pid));
45190
- (0, import_node_fs4.mkdirSync)((0, import_node_path4.dirname)(marker), { recursive: true, mode: 448 });
45347
+ const marker = (0, import_node_path5.join)(versionDir, ".running", String(process.pid));
45348
+ (0, import_node_fs4.mkdirSync)((0, import_node_path5.dirname)(marker), { recursive: true, mode: 448 });
45191
45349
  (0, import_node_fs4.writeFileSync)(marker, "");
45192
45350
  const remove = () => (0, import_node_fs4.rmSync)(marker, { force: true });
45193
45351
  process.once("exit", remove);
@@ -45200,39 +45358,39 @@ function markVersionInUse(bundlePath) {
45200
45358
  }
45201
45359
 
45202
45360
  // src/platform/ipc-endpoint.ts
45203
- var import_node_crypto5 = require("crypto");
45361
+ var import_node_crypto6 = require("crypto");
45204
45362
  var import_node_fs5 = require("fs");
45205
45363
  var import_node_os = require("os");
45206
- var import_node_path5 = require("path");
45364
+ var import_node_path6 = require("path");
45207
45365
  function removeStaleEndpoint(endpoint) {
45208
45366
  if (!endpoint.startsWith("\\\\.\\pipe\\")) (0, import_node_fs5.rmSync)(endpoint, { force: true });
45209
45367
  }
45210
45368
 
45211
45369
  // src/platform/paths.ts
45212
- var import_node_path6 = require("path");
45370
+ var import_node_path7 = require("path");
45213
45371
  function runtimePaths(stateDir) {
45214
45372
  return {
45215
45373
  stateDir,
45216
- lock: (0, import_node_path6.join)(stateDir, "runtime.lock"),
45217
- machine: (0, import_node_path6.join)(stateDir, "machine.json"),
45218
- credential: (0, import_node_path6.join)(stateDir, "credential.json"),
45219
- runs: (0, import_node_path6.join)(stateDir, "runs"),
45220
- sessions: (0, import_node_path6.join)(stateDir, "sessions"),
45221
- sockets: (0, import_node_path6.join)(stateDir, "s"),
45222
- logs: (0, import_node_path6.join)(stateDir, "logs"),
45223
- tmp: (0, import_node_path6.join)(stateDir, "tmp")
45374
+ lock: (0, import_node_path7.join)(stateDir, "runtime.lock"),
45375
+ machine: (0, import_node_path7.join)(stateDir, "machine.json"),
45376
+ credential: (0, import_node_path7.join)(stateDir, "credential.json"),
45377
+ runs: (0, import_node_path7.join)(stateDir, "runs"),
45378
+ sessions: (0, import_node_path7.join)(stateDir, "sessions"),
45379
+ sockets: (0, import_node_path7.join)(stateDir, "s"),
45380
+ logs: (0, import_node_path7.join)(stateDir, "logs"),
45381
+ tmp: (0, import_node_path7.join)(stateDir, "tmp")
45224
45382
  };
45225
45383
  }
45226
45384
 
45227
45385
  // src/platform/process-memory.ts
45228
45386
  var import_node_child_process4 = require("child_process");
45229
- var import_promises10 = require("fs/promises");
45387
+ var import_promises11 = require("fs/promises");
45230
45388
  var import_node_util3 = require("util");
45231
45389
  var execFileAsync3 = (0, import_node_util3.promisify)(import_node_child_process4.execFile);
45232
45390
  var PROBE_TIMEOUT_MS = 2e3;
45233
45391
  async function readProcessRss(pid) {
45234
45392
  if (process.platform === "linux") {
45235
- const status = await (0, import_promises10.readFile)(`/proc/${pid}/status`, "utf8").catch(() => null);
45393
+ const status = await (0, import_promises11.readFile)(`/proc/${pid}/status`, "utf8").catch(() => null);
45236
45394
  const kilobytes = status === null ? void 0 : /^VmRSS:\s+(\d+)\s+kB$/m.exec(status)?.[1];
45237
45395
  return kilobytes === void 0 ? null : Number(kilobytes) * 1024;
45238
45396
  }
@@ -45249,7 +45407,7 @@ async function readProcessRss(pid) {
45249
45407
  }
45250
45408
 
45251
45409
  // src/platform/runtime-host.ts
45252
- var import_promises11 = require("fs/promises");
45410
+ var import_promises12 = require("fs/promises");
45253
45411
  var RUNTIME_HOST_KINDS = ["app", "standalone"];
45254
45412
 
45255
45413
  // src/platform/service/exec.ts
@@ -45264,7 +45422,7 @@ function statusOf(error61) {
45264
45422
  }
45265
45423
  return 1;
45266
45424
  }
45267
- var systemExec = (request2) => new Promise((resolve5) => {
45425
+ var systemExec = (request2) => new Promise((resolve6) => {
45268
45426
  const child = (0, import_node_child_process5.execFile)(
45269
45427
  request2.command,
45270
45428
  [...request2.args],
@@ -45275,7 +45433,7 @@ var systemExec = (request2) => new Promise((resolve5) => {
45275
45433
  windowsHide: true
45276
45434
  },
45277
45435
  (error61, stdout, stderr) => {
45278
- resolve5({ status: statusOf(error61), stdout, stderr });
45436
+ resolve6({ status: statusOf(error61), stdout, stderr });
45279
45437
  }
45280
45438
  );
45281
45439
  child.stdin?.on("error", () => {
@@ -45288,8 +45446,8 @@ init_alan_code();
45288
45446
 
45289
45447
  // src/capabilities/providers/commands.ts
45290
45448
  var import_node_fs6 = require("fs");
45291
- var import_promises15 = require("fs/promises");
45292
- var import_node_path7 = require("path");
45449
+ var import_promises16 = require("fs/promises");
45450
+ var import_node_path8 = require("path");
45293
45451
  var PROVIDER_COMMANDS = [
45294
45452
  // The engine, not a CLI of its own: `resolveProviderExecutable` finds the bundled one first.
45295
45453
  { backendKind: "alan_code", command: "opencode", name: "Alan Code" },
@@ -45322,8 +45480,8 @@ function pathDelimiter(platform) {
45322
45480
  }
45323
45481
  async function isRunnable(path, platform) {
45324
45482
  try {
45325
- if (!(await (0, import_promises15.stat)(path)).isFile()) return false;
45326
- if (platform !== "win32") await (0, import_promises15.access)(path, import_node_fs6.constants.X_OK);
45483
+ if (!(await (0, import_promises16.stat)(path)).isFile()) return false;
45484
+ if (platform !== "win32") await (0, import_promises16.access)(path, import_node_fs6.constants.X_OK);
45327
45485
  return true;
45328
45486
  } catch {
45329
45487
  return false;
@@ -45339,7 +45497,7 @@ async function resolveCommandOnPath(command, env, platform) {
45339
45497
  const extensions = platform === "win32" ? windowsExtensions(command, env) : [""];
45340
45498
  for (const directory of directories) {
45341
45499
  for (const extension of extensions) {
45342
- const candidate = (0, import_node_path7.join)(directory, `${command}${extension}`);
45500
+ const candidate = (0, import_node_path8.join)(directory, `${command}${extension}`);
45343
45501
  if (await isRunnable(candidate, platform)) return candidate;
45344
45502
  }
45345
45503
  }
@@ -45374,15 +45532,15 @@ function resolveProviderExecutable(provider4, env, platform) {
45374
45532
 
45375
45533
  // src/capabilities/providers/managed.ts
45376
45534
  var import_node_child_process6 = require("child_process");
45377
- var import_node_crypto6 = require("crypto");
45378
- var import_promises16 = require("fs/promises");
45379
- var import_node_path8 = require("path");
45535
+ var import_node_crypto7 = require("crypto");
45536
+ var import_promises17 = require("fs/promises");
45537
+ var import_node_path9 = require("path");
45380
45538
  init_zod();
45381
45539
  var VERSION = /^[0-9]+\.[0-9]+\.[0-9]+(?:[-+][0-9A-Za-z.-]+)?$/;
45382
45540
  var selectedSchema = external_exports.record(external_exports.string(), external_exports.string());
45383
45541
  async function readManagedProviderVersion(file2, backendKind) {
45384
45542
  try {
45385
- const selected = selectedSchema.parse(JSON.parse(await (0, import_promises16.readFile)(file2, "utf8")));
45543
+ const selected = selectedSchema.parse(JSON.parse(await (0, import_promises17.readFile)(file2, "utf8")));
45386
45544
  const version2 = selected[backendKind];
45387
45545
  return version2 !== void 0 && VERSION.test(version2) ? version2 : null;
45388
45546
  } catch {
@@ -45392,9 +45550,9 @@ async function readManagedProviderVersion(file2, backendKind) {
45392
45550
 
45393
45551
  // ../shared/dist/node/skill-package.js
45394
45552
  var import_node_buffer = require("buffer");
45395
- var import_node_crypto7 = require("crypto");
45396
- var import_promises17 = require("fs/promises");
45397
- var import_node_path9 = require("path");
45553
+ var import_node_crypto8 = require("crypto");
45554
+ var import_promises18 = require("fs/promises");
45555
+ var import_node_path10 = require("path");
45398
45556
  var import_yaml = __toESM(require_dist(), 1);
45399
45557
  init_contracts();
45400
45558
  init_domain();
@@ -45465,7 +45623,7 @@ async function inspectSkillPackage(packageRoot, options = {}) {
45465
45623
  }
45466
45624
  const inspectedFiles = await Promise.all(files.map(readPackageFile));
45467
45625
  inspectedFiles.sort(comparePackageFiles);
45468
- const parsedMetadata = parseSkillMetadata(inspectedFiles.find((file2) => file2.manifest.path === "SKILL.md")?.bytes, options.expectedName === void 0 ? (0, import_node_path9.basename)(root) : options.expectedName);
45626
+ const parsedMetadata = parseSkillMetadata(inspectedFiles.find((file2) => file2.manifest.path === "SKILL.md")?.bytes, options.expectedName === void 0 ? (0, import_node_path10.basename)(root) : options.expectedName);
45469
45627
  const manifestFiles = inspectedFiles.map((file2) => file2.manifest);
45470
45628
  const diagnostics = [
45471
45629
  ...parsedMetadata.conformance,
@@ -45483,11 +45641,11 @@ async function inspectSkillPackage(packageRoot, options = {}) {
45483
45641
  };
45484
45642
  }
45485
45643
  async function requirePackageRoot(packageRoot) {
45486
- const root = await (0, import_promises17.realpath)((0, import_node_path9.resolve)(packageRoot)).catch(() => null);
45644
+ const root = await (0, import_promises18.realpath)((0, import_node_path10.resolve)(packageRoot)).catch(() => null);
45487
45645
  if (!root) {
45488
45646
  throw new SkillPackageError("INVALID_PACKAGE_ROOT", "Skill package directory does not exist");
45489
45647
  }
45490
- const rootStat = await (0, import_promises17.lstat)(root);
45648
+ const rootStat = await (0, import_promises18.lstat)(root);
45491
45649
  if (!rootStat.isDirectory()) {
45492
45650
  throw new SkillPackageError("INVALID_PACKAGE_ROOT", "Skill package root must be a directory");
45493
45651
  }
@@ -45507,13 +45665,13 @@ async function walkPackage(root, ignoredPaths) {
45507
45665
  }
45508
45666
  return files;
45509
45667
  async function walkDirectory(directory) {
45510
- const entries = await (0, import_promises17.readdir)(directory, { withFileTypes: true });
45668
+ const entries = await (0, import_promises18.readdir)(directory, { withFileTypes: true });
45511
45669
  for (const entry of entries) {
45512
- const absolutePath = (0, import_node_path9.resolve)(directory, entry.name);
45670
+ const absolutePath = (0, import_node_path10.resolve)(directory, entry.name);
45513
45671
  const normalizedPath = normalizeRelativePath(root, absolutePath);
45514
45672
  if (isIgnored(normalizedPath, entry.name, entry.isDirectory(), ignored2))
45515
45673
  continue;
45516
- const entryStat = await (0, import_promises17.lstat)(absolutePath);
45674
+ const entryStat = await (0, import_promises18.lstat)(absolutePath);
45517
45675
  if (entryStat.isSymbolicLink()) {
45518
45676
  throw new SkillPackageError("SYMLINK_BLOCKED", `Nested symbolic links are not allowed in Skill packages: ${normalizedPath}`, normalizedPath);
45519
45677
  }
@@ -45576,12 +45734,12 @@ function globToRegExp(pattern) {
45576
45734
  return new RegExp(`${source}(?:/.*)?$`);
45577
45735
  }
45578
45736
  function normalizeRelativePath(root, absolutePath) {
45579
- const nativeRelativePath = (0, import_node_path9.relative)(root, absolutePath);
45580
- if (!nativeRelativePath || nativeRelativePath.startsWith(`..${import_node_path9.sep}`) || nativeRelativePath === "..") {
45737
+ const nativeRelativePath = (0, import_node_path10.relative)(root, absolutePath);
45738
+ if (!nativeRelativePath || nativeRelativePath.startsWith(`..${import_node_path10.sep}`) || nativeRelativePath === "..") {
45581
45739
  throw new SkillPackageError("INVALID_PATH", "Skill package path escapes its root");
45582
45740
  }
45583
- const normalized2 = nativeRelativePath.split(import_node_path9.sep).join("/").normalize("NFC");
45584
- if (normalized2.includes("\0") || normalized2.includes("\uFFFD") || import_node_path9.posix.isAbsolute(normalized2)) {
45741
+ const normalized2 = nativeRelativePath.split(import_node_path10.sep).join("/").normalize("NFC");
45742
+ if (normalized2.includes("\0") || normalized2.includes("\uFFFD") || import_node_path10.posix.isAbsolute(normalized2)) {
45585
45743
  throw new SkillPackageError("INVALID_PATH", `Invalid Skill package path: ${normalized2}`);
45586
45744
  }
45587
45745
  return normalized2;
@@ -45616,13 +45774,13 @@ function requireSafeFile(path, size, normalizedPaths) {
45616
45774
  }
45617
45775
  }
45618
45776
  function isSecretPath(path) {
45619
- const name = import_node_path9.posix.basename(path).toLowerCase();
45777
+ const name = import_node_path10.posix.basename(path).toLowerCase();
45620
45778
  if (SECRET_BASENAMES.has(name) || name.startsWith(".env."))
45621
45779
  return true;
45622
45780
  return name.endsWith(".private-key.pem") || name.endsWith(".private-key.key");
45623
45781
  }
45624
45782
  async function readPackageFile(file2) {
45625
- const bytes = await (0, import_promises17.readFile)(file2.absolutePath);
45783
+ const bytes = await (0, import_promises18.readFile)(file2.absolutePath);
45626
45784
  return {
45627
45785
  bytes,
45628
45786
  manifest: {
@@ -45644,12 +45802,12 @@ function classifyFileKind(path) {
45644
45802
  return "reference";
45645
45803
  if (path.startsWith("assets/"))
45646
45804
  return "asset";
45647
- if (/^(?:licen[cs]e|copying|notice)(?:\.|$)/i.test(import_node_path9.posix.basename(path)))
45805
+ if (/^(?:licen[cs]e|copying|notice)(?:\.|$)/i.test(import_node_path10.posix.basename(path)))
45648
45806
  return "license";
45649
45807
  return "other";
45650
45808
  }
45651
45809
  function classifyPreview(path, bytes) {
45652
- const extension = import_node_path9.posix.extname(path).toLowerCase();
45810
+ const extension = import_node_path10.posix.extname(path).toLowerCase();
45653
45811
  if (IMAGE_EXTENSIONS2.has(extension))
45654
45812
  return "image";
45655
45813
  if (bytes.includes(0))
@@ -45753,7 +45911,7 @@ function normalizePackageReference(value) {
45753
45911
  const withoutSuffix = trimmed4.split(/[?#]/, 1)[0];
45754
45912
  if (!withoutSuffix)
45755
45913
  return null;
45756
- const normalized2 = import_node_path9.posix.normalize(withoutSuffix).replace(/^\.\//, "").normalize("NFC");
45914
+ const normalized2 = import_node_path10.posix.normalize(withoutSuffix).replace(/^\.\//, "").normalize("NFC");
45757
45915
  if (normalized2 === ".." || normalized2.startsWith("../"))
45758
45916
  return null;
45759
45917
  return normalized2;
@@ -45765,7 +45923,7 @@ function comparePackageFiles(left, right) {
45765
45923
  return import_node_buffer.Buffer.compare(import_node_buffer.Buffer.from(left.manifest.path, "utf8"), import_node_buffer.Buffer.from(right.manifest.path, "utf8"));
45766
45924
  }
45767
45925
  function hashPackageTree(files) {
45768
- const hash2 = (0, import_node_crypto7.createHash)("sha256");
45926
+ const hash2 = (0, import_node_crypto8.createHash)("sha256");
45769
45927
  hash2.update(TREE_HASH_PREFIX);
45770
45928
  for (const file2 of files) {
45771
45929
  const path = import_node_buffer.Buffer.from(file2.path, "utf8");
@@ -45778,7 +45936,7 @@ function hashPackageTree(files) {
45778
45936
  return `sha256:${hash2.digest("hex")}`;
45779
45937
  }
45780
45938
  function sha256(bytes) {
45781
- return `sha256:${(0, import_node_crypto7.createHash)("sha256").update(bytes).digest("hex")}`;
45939
+ return `sha256:${(0, import_node_crypto8.createHash)("sha256").update(bytes).digest("hex")}`;
45782
45940
  }
45783
45941
  function uint322(value) {
45784
45942
  const buffer = import_node_buffer.Buffer.allocUnsafe(4);
@@ -45792,22 +45950,22 @@ function uint642(value) {
45792
45950
  }
45793
45951
 
45794
45952
  // src/capabilities/skills/store.ts
45795
- var import_promises18 = require("fs/promises");
45796
- var import_node_path10 = require("path");
45953
+ var import_promises19 = require("fs/promises");
45954
+ var import_node_path11 = require("path");
45797
45955
  init_runtime_v2();
45798
45956
  init_zod();
45799
45957
  function skillsLayout(stateDir) {
45800
- const root = (0, import_node_path10.join)(stateDir, "skills");
45958
+ const root = (0, import_node_path11.join)(stateDir, "skills");
45801
45959
  return {
45802
45960
  root,
45803
- installedFile: (0, import_node_path10.join)(root, "installed.json"),
45804
- localFile: (0, import_node_path10.join)(root, "local.json"),
45805
- versionsDir: (0, import_node_path10.join)(root, "versions"),
45806
- tmpDir: (0, import_node_path10.join)(root, "tmp")
45961
+ installedFile: (0, import_node_path11.join)(root, "installed.json"),
45962
+ localFile: (0, import_node_path11.join)(root, "local.json"),
45963
+ versionsDir: (0, import_node_path11.join)(root, "versions"),
45964
+ tmpDir: (0, import_node_path11.join)(root, "tmp")
45807
45965
  };
45808
45966
  }
45809
45967
  function packageDirectory(layout, versionId) {
45810
- return (0, import_node_path10.join)(layout.versionsDir, versionId);
45968
+ return (0, import_node_path11.join)(layout.versionsDir, versionId);
45811
45969
  }
45812
45970
  var installedFileSchema = external_exports.object({ skills: external_exports.array(desiredMachineSkillSchema) });
45813
45971
  async function readInstalledSkills(layout) {
@@ -45834,7 +45992,7 @@ async function readLocalSkills(layout) {
45834
45992
  async function isLocalSkillCurrent(entry, contentHash, ignoredPaths) {
45835
45993
  if (entry.contentHash !== contentHash) return false;
45836
45994
  try {
45837
- if (await (0, import_promises18.realpath)(entry.path) !== entry.path) return false;
45995
+ if (await (0, import_promises19.realpath)(entry.path) !== entry.path) return false;
45838
45996
  const inspected = await inspectSkillPackage(entry.path, { expectedName: null, ignoredPaths });
45839
45997
  return inspected.contentHash === contentHash;
45840
45998
  } catch {
@@ -45849,7 +46007,7 @@ async function resolveLocalSkill(local, invocation) {
45849
46007
  }
45850
46008
  async function hasSkillFile(directory) {
45851
46009
  try {
45852
- return (await (0, import_promises18.stat)((0, import_node_path10.join)(directory, "SKILL.md"))).isFile();
46010
+ return (await (0, import_promises19.stat)((0, import_node_path11.join)(directory, "SKILL.md"))).isFile();
45853
46011
  } catch {
45854
46012
  return false;
45855
46013
  }
@@ -45890,14 +46048,14 @@ async function resolveSkillInvocations(layout, invocations) {
45890
46048
  }
45891
46049
 
45892
46050
  // src/capabilities/workspace/index.ts
45893
- var import_node_path13 = require("path");
46051
+ var import_node_path14 = require("path");
45894
46052
 
45895
46053
  // src/capabilities/workspace/approved-paths.ts
45896
- var import_promises19 = require("fs/promises");
46054
+ var import_promises20 = require("fs/promises");
45897
46055
  init_zod();
45898
46056
 
45899
46057
  // src/capabilities/workspace/paths.ts
45900
- var import_node_path11 = require("path");
46058
+ var import_node_path12 = require("path");
45901
46059
  function stripWin32Namespace(path) {
45902
46060
  if (/^\\\\\?\\UNC\\/i.test(path)) return `\\\\${path.slice(8)}`;
45903
46061
  if (path.startsWith("\\\\?\\")) return path.slice(4);
@@ -45905,15 +46063,15 @@ function stripWin32Namespace(path) {
45905
46063
  }
45906
46064
  function comparablePath(path, platform) {
45907
46065
  if (platform === "win32") {
45908
- const normalized3 = import_node_path11.win32.normalize(stripWin32Namespace(path).replaceAll("/", "\\"));
46066
+ const normalized3 = import_node_path12.win32.normalize(stripWin32Namespace(path).replaceAll("/", "\\"));
45909
46067
  const trimmed4 = normalized3.length > 3 || !/^[a-z]:\\$/i.test(normalized3) ? normalized3.replace(/\\+$/, "") : normalized3;
45910
46068
  return trimmed4.toLowerCase();
45911
46069
  }
45912
- const normalized2 = import_node_path11.posix.normalize(path);
46070
+ const normalized2 = import_node_path12.posix.normalize(path);
45913
46071
  return normalized2.length > 1 ? normalized2.replace(/\/+$/, "") : normalized2;
45914
46072
  }
45915
46073
  function isAbsoluteFor(path, platform) {
45916
- return platform === "win32" ? import_node_path11.win32.isAbsolute(path) : import_node_path11.posix.isAbsolute(path);
46074
+ return platform === "win32" ? import_node_path12.win32.isAbsolute(path) : import_node_path12.posix.isAbsolute(path);
45917
46075
  }
45918
46076
  function isWithin(root, candidate, platform) {
45919
46077
  const separator = platform === "win32" ? "\\" : "/";
@@ -45931,7 +46089,7 @@ var storeSchema = external_exports.object({
45931
46089
  });
45932
46090
  async function realpathOrNull(path) {
45933
46091
  try {
45934
- return await (0, import_promises19.realpath)(path);
46092
+ return await (0, import_promises20.realpath)(path);
45935
46093
  } catch (error61) {
45936
46094
  const code = errnoCode(error61);
45937
46095
  if (code === "ENOENT" || code === "ENOTDIR" || code === "EACCES" || code === "EPERM") {
@@ -45990,9 +46148,9 @@ async function openApprovedPaths(options) {
45990
46148
  }
45991
46149
 
45992
46150
  // src/capabilities/workspace/locks.ts
45993
- var import_node_crypto8 = require("crypto");
45994
- var import_promises20 = require("fs/promises");
45995
- var import_node_path12 = require("path");
46151
+ var import_node_crypto9 = require("crypto");
46152
+ var import_promises21 = require("fs/promises");
46153
+ var import_node_path13 = require("path");
45996
46154
  init_zod();
45997
46155
  var LOCK_FORMAT = 1;
45998
46156
  var EXCLUSIVE_FILE = "exclusive.json";
@@ -46007,12 +46165,12 @@ var ownerSchema = external_exports.object({
46007
46165
  since: external_exports.number().int().nonnegative()
46008
46166
  });
46009
46167
  function repositoryLockKey(commonDir, platform) {
46010
- return (0, import_node_crypto8.createHash)("sha256").update(comparablePath(commonDir, platform)).digest("hex").slice(0, 32);
46168
+ return (0, import_node_crypto9.createHash)("sha256").update(comparablePath(commonDir, platform)).digest("hex").slice(0, 32);
46011
46169
  }
46012
46170
  async function readOwner(path) {
46013
46171
  let text2;
46014
46172
  try {
46015
- text2 = await (0, import_promises20.readFile)(path, "utf8");
46173
+ text2 = await (0, import_promises21.readFile)(path, "utf8");
46016
46174
  } catch (error61) {
46017
46175
  if (errnoCode(error61) === "ENOENT") return { kind: "missing" };
46018
46176
  return { kind: "unreadable" };
@@ -46033,7 +46191,7 @@ async function removeIfSame(path, expected) {
46033
46191
  if (current.kind !== "owner" || current.owner.since !== expected.since) return;
46034
46192
  if (current.owner.pid !== expected.pid || current.owner.holder !== expected.holder) return;
46035
46193
  }
46036
- await (0, import_promises20.unlink)(path).catch((error61) => {
46194
+ await (0, import_promises21.unlink)(path).catch((error61) => {
46037
46195
  if (errnoCode(error61) !== "ENOENT") throw error61;
46038
46196
  });
46039
46197
  }
@@ -46058,7 +46216,7 @@ function openRepositoryLocks(options) {
46058
46216
  await removeIfSame(path, read.owner);
46059
46217
  return null;
46060
46218
  }
46061
- const age = await (0, import_promises20.stat)(path).then(
46219
+ const age = await (0, import_promises21.stat)(path).then(
46062
46220
  (info) => clock.now() - info.mtimeMs,
46063
46221
  () => 0
46064
46222
  );
@@ -46072,13 +46230,13 @@ function openRepositoryLocks(options) {
46072
46230
  });
46073
46231
  const folder = async (commonDir) => {
46074
46232
  const key = repositoryLockKey(commonDir, platform);
46075
- const dir = (0, import_node_path12.join)(options.dir, key);
46076
- await (0, import_promises20.mkdir)(dir, { recursive: true, mode: 448 });
46233
+ const dir = (0, import_node_path13.join)(options.dir, key);
46234
+ await (0, import_promises21.mkdir)(dir, { recursive: true, mode: 448 });
46077
46235
  return { key, dir };
46078
46236
  };
46079
46237
  const createExclusive = async (path, owner) => {
46080
46238
  try {
46081
- const handle = await (0, import_promises20.open)(path, "wx", 384);
46239
+ const handle = await (0, import_promises21.open)(path, "wx", 384);
46082
46240
  try {
46083
46241
  await handle.writeFile(JSON.stringify(owner));
46084
46242
  } finally {
@@ -46091,10 +46249,10 @@ function openRepositoryLocks(options) {
46091
46249
  }
46092
46250
  };
46093
46251
  const liveRun = async (dir) => {
46094
- const entries = await (0, import_promises20.readdir)(dir);
46252
+ const entries = await (0, import_promises21.readdir)(dir);
46095
46253
  for (const entry of entries) {
46096
46254
  if (!entry.startsWith(RUN_FILE_PREFIX)) continue;
46097
- const holder = await heldBy((0, import_node_path12.join)(dir, entry));
46255
+ const holder = await heldBy((0, import_node_path13.join)(dir, entry));
46098
46256
  if (holder !== null) return holder;
46099
46257
  }
46100
46258
  return null;
@@ -46102,7 +46260,7 @@ function openRepositoryLocks(options) {
46102
46260
  return {
46103
46261
  tryExclusive: async (commonDir, operationId) => {
46104
46262
  const { key, dir } = await folder(commonDir);
46105
- const path = (0, import_node_path12.join)(dir, EXCLUSIVE_FILE);
46263
+ const path = (0, import_node_path13.join)(dir, EXCLUSIVE_FILE);
46106
46264
  const owner = await self(operationId);
46107
46265
  if (!await createExclusive(path, owner)) {
46108
46266
  const holder = await heldBy(path);
@@ -46120,11 +46278,11 @@ function openRepositoryLocks(options) {
46120
46278
  },
46121
46279
  tryShared: async (commonDir, runId) => {
46122
46280
  const { key, dir } = await folder(commonDir);
46123
- const file2 = `${RUN_FILE_PREFIX}${(0, import_node_crypto8.createHash)("sha256").update(runId).digest("hex").slice(0, 32)}.json`;
46124
- const path = (0, import_node_path12.join)(dir, file2);
46281
+ const file2 = `${RUN_FILE_PREFIX}${(0, import_node_crypto9.createHash)("sha256").update(runId).digest("hex").slice(0, 32)}.json`;
46282
+ const path = (0, import_node_path13.join)(dir, file2);
46125
46283
  const owner = await self(runId);
46126
46284
  await writeJsonFileAtomic(path, owner);
46127
- const operation = await heldBy((0, import_node_path12.join)(dir, EXCLUSIVE_FILE));
46285
+ const operation = await heldBy((0, import_node_path13.join)(dir, EXCLUSIVE_FILE));
46128
46286
  if (operation !== null) {
46129
46287
  await removeIfSame(path, owner);
46130
46288
  return { kind: "busy", holder: operation };
@@ -46136,33 +46294,33 @@ function openRepositoryLocks(options) {
46136
46294
 
46137
46295
  // src/cli/config.ts
46138
46296
  var import_node_os7 = require("os");
46139
- var import_node_path23 = require("path");
46297
+ var import_node_path27 = require("path");
46140
46298
  init_zod();
46141
46299
 
46142
46300
  // src/client/locate.ts
46143
- var import_node_path14 = require("path");
46301
+ var import_node_path15 = require("path");
46144
46302
  var RUNTIME_PROFILES = ["production", "staging", "development", "local"];
46145
46303
  function defaultStateDir({ profile, platform, home, env }) {
46146
46304
  if (platform === "win32") {
46147
- return (0, import_node_path14.join)(env.LOCALAPPDATA ?? (0, import_node_path14.join)(home, "AppData", "Local"), "Alan", profile);
46305
+ return (0, import_node_path15.join)(env.LOCALAPPDATA ?? (0, import_node_path15.join)(home, "AppData", "Local"), "Alan", profile);
46148
46306
  }
46149
- return (0, import_node_path14.join)(env.XDG_STATE_HOME ?? (0, import_node_path14.join)(home, ".local", "state"), "alan", profile);
46307
+ return (0, import_node_path15.join)(env.XDG_STATE_HOME ?? (0, import_node_path15.join)(home, ".local", "state"), "alan", profile);
46150
46308
  }
46151
46309
  function defaultInstallDir({ platform, home, env }) {
46152
46310
  if (platform === "win32") {
46153
- return (0, import_node_path14.join)(env.LOCALAPPDATA ?? (0, import_node_path14.join)(home, "AppData", "Local"), "Alan", "runtime");
46311
+ return (0, import_node_path15.join)(env.LOCALAPPDATA ?? (0, import_node_path15.join)(home, "AppData", "Local"), "Alan", "runtime");
46154
46312
  }
46155
- return (0, import_node_path14.join)(env.XDG_DATA_HOME ?? (0, import_node_path14.join)(home, ".local", "share"), "alan", "runtime");
46313
+ return (0, import_node_path15.join)(env.XDG_DATA_HOME ?? (0, import_node_path15.join)(home, ".local", "share"), "alan", "runtime");
46156
46314
  }
46157
46315
 
46158
46316
  // src/sessions/index.ts
46159
- var import_node_crypto11 = require("crypto");
46160
- var import_promises31 = require("fs/promises");
46317
+ var import_node_crypto13 = require("crypto");
46318
+ var import_promises34 = require("fs/promises");
46161
46319
  var import_node_os6 = require("os");
46162
- var import_node_path22 = require("path");
46320
+ var import_node_path26 = require("path");
46163
46321
 
46164
46322
  // src/holder/control-client.ts
46165
- var import_node_crypto9 = require("crypto");
46323
+ var import_node_crypto10 = require("crypto");
46166
46324
  var import_node_net = require("net");
46167
46325
 
46168
46326
  // src/holder/ndjson.ts
@@ -46325,12 +46483,48 @@ function createProviderDrivers(options) {
46325
46483
  );
46326
46484
  }
46327
46485
 
46486
+ // src/holder/engine-records.ts
46487
+ var import_node_path16 = require("path");
46488
+ init_zod();
46489
+ var ENGINES_FILE = "engines.json";
46490
+ var engineRecordSchema = external_exports.object({
46491
+ pid: external_exports.number().int().positive(),
46492
+ startedAt: external_exports.string().min(1),
46493
+ spawnedAt: external_exports.number().int().nonnegative()
46494
+ });
46495
+ var engineRecordsSchema = external_exports.object({ engines: external_exports.array(engineRecordSchema) });
46496
+ function engineRecordsPath(sessionDir) {
46497
+ return (0, import_node_path16.join)(sessionDir, ENGINES_FILE);
46498
+ }
46499
+ function recordSpawnedEngines(path, clock, log) {
46500
+ const live = /* @__PURE__ */ new Map();
46501
+ let writes = Promise.resolve();
46502
+ const save = () => {
46503
+ const engines = [...live.values()];
46504
+ writes = writes.then(() => writeJsonFileAtomic(path, { engines })).catch((error61) => log.warn("holder.engine_record_failed", { error: error61 }));
46505
+ };
46506
+ return onCliSpawned((child) => {
46507
+ const pid = child.pid;
46508
+ if (pid === void 0) return;
46509
+ const spawnedAt = clock.now();
46510
+ const exited = () => child.exitCode !== null || child.signalCode !== null;
46511
+ child.once("exit", () => {
46512
+ if (live.delete(pid)) save();
46513
+ });
46514
+ void readProcessIdentity(pid).then((identity) => {
46515
+ if (identity === null || exited()) return;
46516
+ live.set(pid, { pid, startedAt: identity.startedAt, spawnedAt });
46517
+ save();
46518
+ });
46519
+ });
46520
+ }
46521
+
46328
46522
  // src/holder/mcp-credential.ts
46329
46523
  function createConversationMcpAuthorization(options) {
46330
46524
  let held;
46331
- return async (signal) => {
46525
+ let minting;
46526
+ const mint = async (signal) => {
46332
46527
  const now = options.now();
46333
- if (held !== void 0 && now < held.refreshAt) return held.authorization;
46334
46528
  try {
46335
46529
  const credential = await options.mint(signal);
46336
46530
  const expiresAt = Date.parse(credential.expiresAt);
@@ -46345,11 +46539,18 @@ function createConversationMcpAuthorization(options) {
46345
46539
  return held !== void 0 && now < held.expiresAt ? held.authorization : void 0;
46346
46540
  }
46347
46541
  };
46542
+ return async (signal) => {
46543
+ if (held !== void 0 && options.now() < held.refreshAt) return held.authorization;
46544
+ minting ??= mint(signal).finally(() => {
46545
+ minting = void 0;
46546
+ });
46547
+ return minting;
46548
+ };
46348
46549
  }
46349
46550
 
46350
46551
  // src/holder/run-inputs.ts
46351
- var import_promises25 = require("fs/promises");
46352
- var import_node_path15 = require("path");
46552
+ var import_promises27 = require("fs/promises");
46553
+ var import_node_path17 = require("path");
46353
46554
  var NO_RUN_INPUTS = {
46354
46555
  attachments: [],
46355
46556
  providerEnv: {},
@@ -46362,18 +46563,18 @@ function safeFilename(filename) {
46362
46563
  return safe || "attachment";
46363
46564
  }
46364
46565
  async function prepareRunInputs(spec, { source, tmpDir, signal, skills = [] }) {
46365
- const dir = (0, import_node_path15.join)(tmpDir, "runs", spec.runId);
46566
+ const dir = (0, import_node_path17.join)(tmpDir, "runs", spec.runId);
46366
46567
  const cleanup = async () => {
46367
- await (0, import_promises25.rm)(dir, { recursive: true, force: true });
46568
+ await (0, import_promises27.rm)(dir, { recursive: true, force: true });
46368
46569
  };
46369
46570
  try {
46370
46571
  const credential = await source.fetchProviderCredential(spec.runId, signal);
46371
46572
  const attachments = [];
46372
- if (spec.attachments?.length) await (0, import_promises25.mkdir)(dir, { recursive: true, mode: 448 });
46573
+ if (spec.attachments?.length) await (0, import_promises27.mkdir)(dir, { recursive: true, mode: 448 });
46373
46574
  for (const [index, attachment] of (spec.attachments ?? []).entries()) {
46374
46575
  const bytes = await source.downloadAttachment(spec.runId, attachment.id, signal);
46375
- const path = (0, import_node_path15.join)(dir, `${index}-${safeFilename(attachment.filename)}`);
46376
- await (0, import_promises25.writeFile)(path, bytes, { mode: 384 });
46576
+ const path = (0, import_node_path17.join)(dir, `${index}-${safeFilename(attachment.filename)}`);
46577
+ await (0, import_promises27.writeFile)(path, bytes, { mode: 384 });
46377
46578
  attachments.push({
46378
46579
  id: attachment.id,
46379
46580
  kind: attachment.kind,
@@ -46394,29 +46595,30 @@ async function prepareRunInputs(spec, { source, tmpDir, signal, skills = [] }) {
46394
46595
  }
46395
46596
 
46396
46597
  // src/holder/serve.ts
46397
- var import_node_crypto10 = require("crypto");
46598
+ var import_node_crypto12 = require("crypto");
46398
46599
  var import_node_fs10 = require("fs");
46399
46600
  var import_node_net2 = require("net");
46601
+ var import_node_path25 = require("path");
46400
46602
  init_runtime_v2();
46401
46603
 
46402
46604
  // src/holder/admission.ts
46403
46605
  var import_node_fs8 = require("fs");
46404
- var import_promises28 = require("fs/promises");
46606
+ var import_promises31 = require("fs/promises");
46405
46607
  var import_node_os5 = require("os");
46406
- var import_node_path19 = require("path");
46608
+ var import_node_path22 = require("path");
46407
46609
  init_constants();
46408
46610
 
46409
46611
  // ../shared/dist/node/local-workspace.js
46410
46612
  var import_node_fs7 = require("fs");
46411
46613
  var import_node_os4 = require("os");
46412
- var import_node_path16 = require("path");
46614
+ var import_node_path18 = require("path");
46413
46615
  function resolveAlanDefaultWorkspacePath(homeDirectory = (0, import_node_os4.homedir)()) {
46414
- return (0, import_node_path16.join)(homeDirectory, ".alan", "workspace");
46616
+ return (0, import_node_path18.join)(homeDirectory, ".alan", "workspace");
46415
46617
  }
46416
46618
 
46417
46619
  // src/holder/admission-relocation.ts
46418
- var import_promises26 = require("fs/promises");
46419
- var import_node_path17 = require("path");
46620
+ var import_promises28 = require("fs/promises");
46621
+ var import_node_path19 = require("path");
46420
46622
  var MAX_RELOCATION_CANDIDATES = 200;
46421
46623
  var RELOCATION_BUDGET_MS = 2e4;
46422
46624
  function repositoryIdentity(url2) {
@@ -46451,8 +46653,8 @@ async function originIdentity(git, path, signal) {
46451
46653
  }
46452
46654
  async function childDirectories(parent, limit) {
46453
46655
  try {
46454
- const entries = await (0, import_promises26.readdir)(parent, { withFileTypes: true });
46455
- return entries.filter((entry) => entry.isDirectory()).slice(0, limit).map((entry) => (0, import_node_path17.join)(parent, entry.name));
46656
+ const entries = await (0, import_promises28.readdir)(parent, { withFileTypes: true });
46657
+ return entries.filter((entry) => entry.isDirectory()).slice(0, limit).map((entry) => (0, import_node_path19.join)(parent, entry.name));
46456
46658
  } catch {
46457
46659
  return [];
46458
46660
  }
@@ -46460,7 +46662,7 @@ async function childDirectories(parent, limit) {
46460
46662
  async function candidateFolders(search) {
46461
46663
  const roots = /* @__PURE__ */ new Map();
46462
46664
  for (const path of [search.missingPath, ...search.approvedWorkspacePaths]) {
46463
- const parent = (0, import_node_path17.dirname)((0, import_node_path17.resolve)(path));
46665
+ const parent = (0, import_node_path19.dirname)((0, import_node_path19.resolve)(path));
46464
46666
  roots.set(comparablePath(parent, search.platform), parent);
46465
46667
  }
46466
46668
  const candidates2 = /* @__PURE__ */ new Map();
@@ -46486,9 +46688,107 @@ async function discoverRelocatedWorkspace(search) {
46486
46688
  return matches[0] ?? null;
46487
46689
  }
46488
46690
 
46691
+ // src/holder/checkout-refresh.ts
46692
+ var import_node_crypto11 = require("crypto");
46693
+ var import_promises29 = require("fs/promises");
46694
+ var import_node_path20 = require("path");
46695
+ function short(sha) {
46696
+ return sha.slice(0, 12);
46697
+ }
46698
+ function staleLine(path, snapshot2, tip) {
46699
+ const checkout = snapshot2 === void 0 ? "is the environment snapshot's checkout" : `is the environment snapshot's checkout of ${snapshot2.branch} (commit ${short(snapshot2.head)})`;
46700
+ const base = snapshot2 === void 0 ? "its upstream" : `origin/${snapshot2.base}`;
46701
+ const remote = tip === void 0 ? "may be ahead" : `is ahead at ${short(tip)}`;
46702
+ return `Note: ${path} ${checkout}; ${base} ${remote}. Run \`git pull --ff-only\` there before relying on its files.`;
46703
+ }
46704
+ async function claimOnce(dir, name) {
46705
+ try {
46706
+ await (0, import_promises29.mkdir)(dir, { recursive: true, mode: 448 });
46707
+ await (await (0, import_promises29.open)((0, import_node_path20.join)(dir, name), "wx")).close();
46708
+ return true;
46709
+ } catch {
46710
+ return false;
46711
+ }
46712
+ }
46713
+ async function fastForward(freshness, operationId, deps, signal) {
46714
+ var _stack = [];
46715
+ try {
46716
+ const { path: cwd, snapshot: snapshot2, tip } = freshness;
46717
+ const attempt = await deps.locks.tryExclusive(snapshot2.commonDir, operationId);
46718
+ if (attempt.kind === "busy") return false;
46719
+ const _lock = __using(_stack, attempt.lock, true);
46720
+ const now = await readCheckoutStatus(deps.git, cwd, signal);
46721
+ if (now === null || now.dirty || now.head !== snapshot2.head || now.branch !== snapshot2.branch) {
46722
+ return false;
46723
+ }
46724
+ const git = (args) => deps.git.run({ cwd, args }, signal);
46725
+ if ((await git(["switch", "--quiet", "--detach", tip])).exitCode !== 0) return false;
46726
+ const moved = await git(["update-ref", `refs/heads/${snapshot2.branch}`, tip, snapshot2.head]);
46727
+ const back = await git(["switch", "--quiet", snapshot2.branch]);
46728
+ return moved.exitCode === 0 && back.exitCode === 0;
46729
+ } catch (_) {
46730
+ var _error = _, _hasError = true;
46731
+ } finally {
46732
+ var _promise2 = __callDispose(_stack, _error, _hasError);
46733
+ _promise2 && await _promise2;
46734
+ }
46735
+ }
46736
+ async function atFirstLease(freshness, spec, deps, signal) {
46737
+ const first = await claimOnce(
46738
+ (0, import_node_path20.join)(deps.dir, "leased"),
46739
+ (0, import_node_crypto11.createHash)("sha256").update(freshness.path).digest("hex")
46740
+ );
46741
+ switch (freshness.state) {
46742
+ case "current":
46743
+ case "kept":
46744
+ return "none";
46745
+ case "checking":
46746
+ case "failed":
46747
+ return "noted";
46748
+ case "behind":
46749
+ return first && freshness.fetched && await fastForward(freshness, `refresh-${spec.runId}`, deps, signal) ? "moved" : "noted";
46750
+ }
46751
+ }
46752
+ function lineFor(freshness) {
46753
+ switch (freshness.state) {
46754
+ case "behind":
46755
+ return staleLine(freshness.path, freshness.snapshot, freshness.tip);
46756
+ case "failed":
46757
+ return staleLine(freshness.path, freshness.snapshot);
46758
+ default:
46759
+ return staleLine(freshness.path, void 0);
46760
+ }
46761
+ }
46762
+ async function checkoutsOf(spec, leaseTargets) {
46763
+ if (leaseTargets.length > 0 || spec.projectPath === void 0) return [...leaseTargets];
46764
+ return checkoutsUnder(spec.projectPath);
46765
+ }
46766
+ function createCheckoutRefresh(deps) {
46767
+ return async (spec, leaseTargets, signal) => {
46768
+ if (spec.providerSessionId !== void 0) return void 0;
46769
+ if (!await claimOnce((0, import_node_path20.join)(deps.dir, "conversations"), spec.conversationId)) return void 0;
46770
+ const lines = [];
46771
+ for (const target of await checkoutsOf(spec, leaseTargets)) {
46772
+ const freshness = await readCheckoutFreshness(deps.dir, target);
46773
+ if (freshness === null) continue;
46774
+ const outcome2 = await atFirstLease(freshness, spec, deps, signal).catch(
46775
+ () => "noted"
46776
+ );
46777
+ if (outcome2 === "noted") lines.push(lineFor(freshness));
46778
+ deps.log.info("workspace.refresh", {
46779
+ runId: spec.runId,
46780
+ path: freshness.path,
46781
+ state: freshness.state,
46782
+ outcome: outcome2
46783
+ });
46784
+ }
46785
+ return lines.length === 0 ? void 0 : lines.join("\n");
46786
+ };
46787
+ }
46788
+
46489
46789
  // src/holder/lease.ts
46490
- var import_promises27 = require("fs/promises");
46491
- var import_node_path18 = require("path");
46790
+ var import_promises30 = require("fs/promises");
46791
+ var import_node_path21 = require("path");
46492
46792
  var LEASE_CHECK_EVERY_MS = 5e3;
46493
46793
  var MAX_TRANSIENT_FAILURES = 3;
46494
46794
  var BACKOFF_BASE_MS = 1e3;
@@ -46502,8 +46802,8 @@ function identityFailure(code, workspacePath) {
46502
46802
  return { code, problemCode: "app.workspace.missing", message: MESSAGES[code], workspacePath };
46503
46803
  }
46504
46804
  async function fileIdentity(path) {
46505
- const canonical = await (0, import_promises27.realpath)(path);
46506
- const info = await (0, import_promises27.stat)(canonical, { bigint: true });
46805
+ const canonical = await (0, import_promises30.realpath)(path);
46806
+ const info = await (0, import_promises30.stat)(canonical, { bigint: true });
46507
46807
  return `${canonical}:${info.dev}:${info.ino}`;
46508
46808
  }
46509
46809
  async function snapshot(git, path, signal) {
@@ -46522,7 +46822,7 @@ async function snapshot(git, path, signal) {
46522
46822
  workspace: await fileIdentity(path),
46523
46823
  repository: await fileIdentity(commonDir),
46524
46824
  worktree: await fileIdentity(gitDir),
46525
- commonDir: await (0, import_promises27.realpath)(commonDir)
46825
+ commonDir: await (0, import_promises30.realpath)(commonDir)
46526
46826
  };
46527
46827
  } catch {
46528
46828
  return null;
@@ -46535,7 +46835,7 @@ async function gitValue(git, path, args, signal) {
46535
46835
  }
46536
46836
  async function pathExists(path) {
46537
46837
  try {
46538
- await (0, import_promises27.stat)(path);
46838
+ await (0, import_promises30.stat)(path);
46539
46839
  return true;
46540
46840
  } catch (error61) {
46541
46841
  return errnoCode(error61) !== "ENOENT" && errnoCode(error61) !== "ENOTDIR";
@@ -46544,19 +46844,19 @@ async function pathExists(path) {
46544
46844
  async function hasGitMarker(path) {
46545
46845
  let directory;
46546
46846
  try {
46547
- directory = await (0, import_promises27.realpath)(path);
46847
+ directory = await (0, import_promises30.realpath)(path);
46548
46848
  } catch {
46549
46849
  return true;
46550
46850
  }
46551
46851
  for (; ; ) {
46552
46852
  try {
46553
- await (0, import_promises27.stat)((0, import_node_path18.join)(directory, ".git"));
46853
+ await (0, import_promises30.stat)((0, import_node_path21.join)(directory, ".git"));
46554
46854
  return true;
46555
46855
  } catch (error61) {
46556
46856
  const code = errnoCode(error61);
46557
46857
  if (code !== "ENOENT" && code !== "ENOTDIR") return true;
46558
46858
  }
46559
- const parent = (0, import_node_path18.dirname)(directory);
46859
+ const parent = (0, import_node_path21.dirname)(directory);
46560
46860
  if (parent === directory) return false;
46561
46861
  directory = parent;
46562
46862
  }
@@ -46720,7 +47020,7 @@ function volumeRoot(path) {
46720
47020
  }
46721
47021
  async function exists(path) {
46722
47022
  try {
46723
- await (0, import_promises28.stat)(path);
47023
+ await (0, import_promises31.stat)(path);
46724
47024
  return true;
46725
47025
  } catch {
46726
47026
  return false;
@@ -46728,10 +47028,10 @@ async function exists(path) {
46728
47028
  }
46729
47029
  async function inspectReadiness(path) {
46730
47030
  try {
46731
- if (!(await (0, import_promises28.stat)(path)).isDirectory()) {
47031
+ if (!(await (0, import_promises31.stat)(path)).isDirectory()) {
46732
47032
  return { ready: false, missing: true, message: MESSAGES2.missing };
46733
47033
  }
46734
- await (0, import_promises28.access)(path, import_node_fs8.constants.R_OK | import_node_fs8.constants.W_OK | import_node_fs8.constants.X_OK);
47034
+ await (0, import_promises31.access)(path, import_node_fs8.constants.R_OK | import_node_fs8.constants.W_OK | import_node_fs8.constants.X_OK);
46735
47035
  return { ready: true };
46736
47036
  } catch (error61) {
46737
47037
  const code = errnoCode(error61) ?? "";
@@ -46809,8 +47109,8 @@ async function admitDefaultWorkspace(spec, context, skills) {
46809
47109
  const { env } = context;
46810
47110
  const path = resolveAlanDefaultWorkspacePath(env.HOME || env.USERPROFILE || (0, import_node_os5.homedir)());
46811
47111
  try {
46812
- await (0, import_promises28.mkdir)(path, { recursive: true, mode: 448 });
46813
- await (0, import_promises28.access)(path, import_node_fs8.constants.R_OK | import_node_fs8.constants.W_OK | import_node_fs8.constants.X_OK);
47112
+ await (0, import_promises31.mkdir)(path, { recursive: true, mode: 448 });
47113
+ await (0, import_promises31.access)(path, import_node_fs8.constants.R_OK | import_node_fs8.constants.W_OK | import_node_fs8.constants.X_OK);
46814
47114
  return {
46815
47115
  kind: "admitted",
46816
47116
  spec: { ...spec, projectPath: path },
@@ -46875,6 +47175,7 @@ var PROBE_TIMEOUT_MS2 = 5e3;
46875
47175
  function createHolderWorkspace(machine, clock, log) {
46876
47176
  const platform = machine.platform ?? process.platform;
46877
47177
  const git = createGitRunner({ env: machine.env, platform, localTimeoutMs: PROBE_TIMEOUT_MS2 });
47178
+ const locks = openRepositoryLocks({ dir: (0, import_node_path22.join)(machine.stateDir, "locks"), clock, platform });
46878
47179
  return {
46879
47180
  admission: {
46880
47181
  env: machine.env,
@@ -46883,20 +47184,22 @@ function createHolderWorkspace(machine, clock, log) {
46883
47184
  skills: skillsLayout(machine.stateDir),
46884
47185
  approvedRoots: async () => {
46885
47186
  const approved = await openApprovedPaths({
46886
- file: (0, import_node_path19.join)(machine.stateDir, "workspaces.json"),
47187
+ file: (0, import_node_path22.join)(machine.stateDir, "workspaces.json"),
46887
47188
  log,
46888
47189
  platform
46889
47190
  });
46890
47191
  return approved.roots();
46891
47192
  }
46892
47193
  },
46893
- lease: {
46894
- git,
46895
- locks: openRepositoryLocks({ dir: (0, import_node_path19.join)(machine.stateDir, "locks"), clock, platform }),
46896
- clock,
46897
- log,
46898
- platform
46899
- }
47194
+ lease: { git, locks, clock, log, platform },
47195
+ ...machine.refreshesFirstCheckout === true ? {
47196
+ refreshFirstCheckout: createCheckoutRefresh({
47197
+ git,
47198
+ locks,
47199
+ log,
47200
+ dir: (0, import_node_path22.join)(machine.stateDir, "checkout-freshness")
47201
+ })
47202
+ } : {}
46900
47203
  };
46901
47204
  }
46902
47205
 
@@ -46922,7 +47225,7 @@ async function respondToTurn(runningRunId, gate, driver, request2) {
46922
47225
  }
46923
47226
 
46924
47227
  // src/holder/session-facts.ts
46925
- var import_promises29 = require("fs/promises");
47228
+ var import_promises32 = require("fs/promises");
46926
47229
  var CLI_RSS_CACHE_MS = 1e4;
46927
47230
  var LOGIN_PROBLEM_PREFIX = "cli.auth.";
46928
47231
  function isLoginFailure(result) {
@@ -46948,8 +47251,8 @@ function createSessionFacts(options) {
46948
47251
  const path = await resolveCommandOnPath(command, env, platform);
46949
47252
  if (path === null) return null;
46950
47253
  try {
46951
- const real = await (0, import_promises29.realpath)(path);
46952
- const info = await (0, import_promises29.stat)(real);
47254
+ const real = await (0, import_promises32.realpath)(path);
47255
+ const info = await (0, import_promises32.stat)(real);
46953
47256
  return { command, key: `${real}:${info.ino}:${info.size}:${info.mtimeMs}` };
46954
47257
  } catch {
46955
47258
  return null;
@@ -47036,23 +47339,23 @@ function createSessionFacts(options) {
47036
47339
  init_acp2();
47037
47340
 
47038
47341
  // src/run-log/directory.ts
47039
- var import_promises30 = require("fs/promises");
47040
- var import_node_path20 = require("path");
47342
+ var import_promises33 = require("fs/promises");
47343
+ var import_node_path23 = require("path");
47041
47344
  init_runtime_v2();
47042
47345
  init_zod();
47043
47346
  var runMetaSchema = external_exports.object({ runId: runIdSchema, conversationId: conversationIdSchema });
47044
47347
  function runDirectory(runsDir, runId) {
47045
- const dir = (0, import_node_path20.join)(runsDir, runId);
47348
+ const dir = (0, import_node_path23.join)(runsDir, runId);
47046
47349
  return {
47047
47350
  dir,
47048
- log: (0, import_node_path20.join)(dir, "log.jsonl"),
47049
- upload: (0, import_node_path20.join)(dir, "upload.json"),
47050
- meta: (0, import_node_path20.join)(dir, "run.json")
47351
+ log: (0, import_node_path23.join)(dir, "log.jsonl"),
47352
+ upload: (0, import_node_path23.join)(dir, "upload.json"),
47353
+ meta: (0, import_node_path23.join)(dir, "run.json")
47051
47354
  };
47052
47355
  }
47053
47356
  async function isRunClaimed(runsDir, runId) {
47054
47357
  try {
47055
- return (await (0, import_promises30.stat)(runDirectory(runsDir, runId).log)).size > 0;
47358
+ return (await (0, import_promises33.stat)(runDirectory(runsDir, runId).log)).size > 0;
47056
47359
  } catch (error61) {
47057
47360
  if (errnoCode(error61) === "ENOENT") return false;
47058
47361
  throw error61;
@@ -47088,7 +47391,7 @@ var decoder = new TextDecoder();
47088
47391
 
47089
47392
  // src/run-log/writer.ts
47090
47393
  var import_node_fs9 = require("fs");
47091
- var import_node_path21 = require("path");
47394
+ var import_node_path24 = require("path");
47092
47395
  init_runtime_v2();
47093
47396
  function lastSeq(fd, size) {
47094
47397
  for (const length of tailWindows(size)) {
@@ -47104,7 +47407,7 @@ function lastSeq(fd, size) {
47104
47407
  throw new RuntimeFault("record_too_large", "Run log tail record is larger than any record");
47105
47408
  }
47106
47409
  function openRunLog(path, clock) {
47107
- (0, import_node_fs9.mkdirSync)((0, import_node_path21.dirname)(path), { recursive: true, mode: 448 });
47410
+ (0, import_node_fs9.mkdirSync)((0, import_node_path24.dirname)(path), { recursive: true, mode: 448 });
47108
47411
  const fd = (0, import_node_fs9.openSync)(path, "a+", 384);
47109
47412
  let size = (0, import_node_fs9.fstatSync)(fd).size;
47110
47413
  let seq = lastSeq(fd, size);
@@ -47282,6 +47585,10 @@ function fitForRunLog(update) {
47282
47585
  async function runWithInputs({ spec, leaseTargets, skills }, context, sink, signal) {
47283
47586
  var _stack = [];
47284
47587
  try {
47588
+ const refreshed = context.workspace?.refreshFirstCheckout?.(spec, leaseTargets, signal).catch((error61) => {
47589
+ context.log.warn("workspace.refresh_failed", { runId: spec.runId, error: error61 });
47590
+ return void 0;
47591
+ });
47285
47592
  let inputs;
47286
47593
  try {
47287
47594
  inputs = context.inputs ? await prepareRunInputs(spec, { ...context.inputs, signal, skills }) : { ...NO_RUN_INPUTS, skills };
@@ -47292,8 +47599,14 @@ async function runWithInputs({ spec, leaseTargets, skills }, context, sink, sign
47292
47599
  message: `Could not fetch this run's attachments or provider credential: ${error61 instanceof Error ? error61.message : String(error61)}`
47293
47600
  };
47294
47601
  }
47602
+ const turnContext = await refreshed;
47295
47603
  const prepared = __using(_stack, inputs, true);
47296
- const run = (turnSink, turnSignal) => context.driver.runTurn(spec, turnSink, turnSignal, prepared);
47604
+ const run = (turnSink, turnSignal) => context.driver.runTurn(
47605
+ spec,
47606
+ turnSink,
47607
+ turnSignal,
47608
+ turnContext === void 0 ? prepared : { ...prepared, turnContext }
47609
+ );
47297
47610
  if (context.workspace === void 0) return await run(sink, signal);
47298
47611
  const leased = { ...context, lease: context.workspace.lease };
47299
47612
  return await runLeased(spec, leaseTargets, leased, sink, signal, run);
@@ -47391,12 +47704,12 @@ var TASK_UNSUPPORTED = {
47391
47704
  message: "This agent cannot stop one background task."
47392
47705
  };
47393
47706
  function sha2562(value) {
47394
- return (0, import_node_crypto10.createHash)("sha256").update(value).digest("hex");
47707
+ return (0, import_node_crypto12.createHash)("sha256").update(value).digest("hex");
47395
47708
  }
47396
47709
  function tokenMatches(expected, presented) {
47397
47710
  const a = Buffer.from(sha2562(expected), "hex");
47398
47711
  const b = Buffer.from(sha2562(presented), "hex");
47399
- return (0, import_node_crypto10.timingSafeEqual)(a, b);
47712
+ return (0, import_node_crypto12.timingSafeEqual)(a, b);
47400
47713
  }
47401
47714
  async function runHolder({
47402
47715
  launch,
@@ -47406,215 +47719,223 @@ async function runHolder({
47406
47719
  inputs,
47407
47720
  machine
47408
47721
  }) {
47409
- const identity = await readProcessIdentity(process.pid);
47410
- if (identity === null) throw new RuntimeFault("internal", "Cannot read own process identity");
47411
- const holder = {
47412
- state: "idle",
47413
- runId: null,
47414
- turn: null,
47415
- answerGate: createAnswerGate(),
47416
- clients: /* @__PURE__ */ new Set()
47417
- };
47418
- const exit = new AbortController();
47419
- const workspace = machine === void 0 ? void 0 : createHolderWorkspace(machine, clock, log);
47420
- const facts = createSessionFacts({
47421
- clock,
47422
- env: machine?.env ?? {},
47423
- ...machine?.platform === void 0 ? {} : { platform: machine.platform }
47424
- });
47425
- const observed = facts.observe(driver);
47426
- const writeStatus = () => writeJsonFileAtomic(launch.statusPath, {
47427
- protocol: HOLDER_PROTOCOL,
47428
- conversationId: launch.conversationId,
47429
- pid: identity.pid,
47430
- startedAt: identity.startedAt,
47431
- ...identity.command === void 0 ? {} : { command: identity.command },
47432
- endpoint: launch.endpoint,
47433
- tokenSha256: sha2562(launch.token),
47434
- state: holder.state,
47435
- runId: holder.runId,
47436
- updatedAt: clock.now()
47437
- });
47438
- const broadcast = (message) => {
47439
- for (const client of holder.clients) writeMessage(client, message);
47440
- };
47441
- const settle = () => {
47442
- holder.state = "idle";
47443
- holder.runId = null;
47444
- holder.turn = null;
47445
- void writeStatus();
47446
- };
47447
- const startTurn = (id, spec, client) => {
47448
- if (holder.runId === spec.runId) {
47449
- writeMessage(client, {
47450
- type: "error",
47451
- id,
47452
- code: HOLDER_ALREADY_STARTED,
47453
- message: "The run is already running"
47454
- });
47455
- return;
47456
- }
47457
- if (holder.state !== "idle") {
47458
- writeMessage(client, { type: "error", id, code: "busy", message: "A turn is running" });
47459
- return;
47460
- }
47461
- const turn = new AbortController();
47462
- holder.state = "running";
47463
- holder.runId = spec.runId;
47464
- holder.turn = turn;
47465
- const context = {
47466
- runsDir: launch.runsDir,
47467
- machineId: launch.machineId,
47468
- driver: observed,
47722
+ var _stack = [];
47723
+ try {
47724
+ const identity = await readProcessIdentity(process.pid);
47725
+ if (identity === null) throw new RuntimeFault("internal", "Cannot read own process identity");
47726
+ const _engines = __using(_stack, recordSpawnedEngines(engineRecordsPath((0, import_node_path25.dirname)(launch.statusPath)), clock, log));
47727
+ const holder = {
47728
+ state: "idle",
47729
+ runId: null,
47730
+ turn: null,
47731
+ answerGate: createAnswerGate(),
47732
+ clients: /* @__PURE__ */ new Set()
47733
+ };
47734
+ const exit = new AbortController();
47735
+ const workspace = machine === void 0 ? void 0 : createHolderWorkspace(machine, clock, log);
47736
+ const facts = createSessionFacts({
47469
47737
  clock,
47470
- log,
47471
- onAppended: (runId, offset) => broadcast({ type: "appended", runId, offset }),
47472
- ...inputs === void 0 ? {} : { inputs },
47473
- ...workspace === void 0 ? {} : { workspace },
47474
- answerGate: holder.answerGate
47475
- };
47476
- claimRun(spec, context).then(
47477
- (claimed) => {
47478
- if (claimed === null) {
47479
- log.warn("holder.start_already_claimed", { runId: spec.runId });
47738
+ env: machine?.env ?? {},
47739
+ ...machine?.platform === void 0 ? {} : { platform: machine.platform }
47740
+ });
47741
+ const observed = facts.observe(driver);
47742
+ const writeStatus = () => writeJsonFileAtomic(launch.statusPath, {
47743
+ protocol: HOLDER_PROTOCOL,
47744
+ conversationId: launch.conversationId,
47745
+ pid: identity.pid,
47746
+ startedAt: identity.startedAt,
47747
+ ...identity.command === void 0 ? {} : { command: identity.command },
47748
+ endpoint: launch.endpoint,
47749
+ tokenSha256: sha2562(launch.token),
47750
+ state: holder.state,
47751
+ runId: holder.runId,
47752
+ updatedAt: clock.now()
47753
+ });
47754
+ const broadcast = (message) => {
47755
+ for (const client of holder.clients) writeMessage(client, message);
47756
+ };
47757
+ const settle = () => {
47758
+ holder.state = "idle";
47759
+ holder.runId = null;
47760
+ holder.turn = null;
47761
+ void writeStatus();
47762
+ };
47763
+ const startTurn = (id, spec, client) => {
47764
+ if (holder.runId === spec.runId) {
47765
+ writeMessage(client, {
47766
+ type: "error",
47767
+ id,
47768
+ code: HOLDER_ALREADY_STARTED,
47769
+ message: "The run is already running"
47770
+ });
47771
+ return;
47772
+ }
47773
+ if (holder.state !== "idle") {
47774
+ writeMessage(client, { type: "error", id, code: "busy", message: "A turn is running" });
47775
+ return;
47776
+ }
47777
+ const turn = new AbortController();
47778
+ holder.state = "running";
47779
+ holder.runId = spec.runId;
47780
+ holder.turn = turn;
47781
+ const context = {
47782
+ runsDir: launch.runsDir,
47783
+ machineId: launch.machineId,
47784
+ driver: observed,
47785
+ clock,
47786
+ log,
47787
+ onAppended: (runId, offset) => broadcast({ type: "appended", runId, offset }),
47788
+ ...inputs === void 0 ? {} : { inputs },
47789
+ ...workspace === void 0 ? {} : { workspace },
47790
+ answerGate: holder.answerGate
47791
+ };
47792
+ claimRun(spec, context).then(
47793
+ (claimed) => {
47794
+ if (claimed === null) {
47795
+ log.warn("holder.start_already_claimed", { runId: spec.runId });
47796
+ settle();
47797
+ writeMessage(client, {
47798
+ type: "error",
47799
+ id,
47800
+ code: HOLDER_ALREADY_STARTED,
47801
+ message: "The run was already started"
47802
+ });
47803
+ return;
47804
+ }
47805
+ writeMessage(client, { type: "ack", id });
47806
+ void writeStatus();
47807
+ runClaimedTurn(spec, claimed, context, turn.signal).then((outcome2) => broadcast({ type: "turn_ended", runId: spec.runId, outcome: outcome2 })).catch((error61) => log.error("holder.turn_crashed", { runId: spec.runId, error: error61 })).finally(settle);
47808
+ },
47809
+ (error61) => {
47810
+ log.error("holder.claim_failed", { runId: spec.runId, error: error61 });
47480
47811
  settle();
47481
47812
  writeMessage(client, {
47482
47813
  type: "error",
47483
47814
  id,
47484
- code: HOLDER_ALREADY_STARTED,
47485
- message: "The run was already started"
47815
+ code: "claim_failed",
47816
+ message: "The run log could not be written"
47486
47817
  });
47487
- return;
47488
47818
  }
47489
- writeMessage(client, { type: "ack", id });
47490
- void writeStatus();
47491
- runClaimedTurn(spec, claimed, context, turn.signal).then((outcome2) => broadcast({ type: "turn_ended", runId: spec.runId, outcome: outcome2 })).catch((error61) => log.error("holder.turn_crashed", { runId: spec.runId, error: error61 })).finally(settle);
47492
- },
47493
- (error61) => {
47494
- log.error("holder.claim_failed", { runId: spec.runId, error: error61 });
47495
- settle();
47819
+ );
47820
+ };
47821
+ const respond = (request2, client) => {
47822
+ respondToTurn(holder.runId, holder.answerGate, driver, request2).then((status) => {
47823
+ log.info("holder.responded", { runId: request2.runId, status });
47824
+ writeMessage(client, { type: "responded", id: request2.id, status });
47825
+ }).catch((error61) => {
47826
+ log.warn("holder.respond_crashed", { runId: request2.runId, error: error61 });
47496
47827
  writeMessage(client, {
47497
47828
  type: "error",
47498
- id,
47499
- code: "claim_failed",
47500
- message: "The run log could not be written"
47829
+ id: request2.id,
47830
+ code: "respond_failed",
47831
+ message: "The answer could not be delivered"
47501
47832
  });
47502
- }
47503
- );
47504
- };
47505
- const respond = (request2, client) => {
47506
- respondToTurn(holder.runId, holder.answerGate, driver, request2).then((status) => {
47507
- log.info("holder.responded", { runId: request2.runId, status });
47508
- writeMessage(client, { type: "responded", id: request2.id, status });
47509
- }).catch((error61) => {
47510
- log.warn("holder.respond_crashed", { runId: request2.runId, error: error61 });
47511
- writeMessage(client, {
47512
- type: "error",
47513
- id: request2.id,
47514
- code: "respond_failed",
47515
- message: "The answer could not be delivered"
47516
47833
  });
47517
- });
47518
- };
47519
- const stopTask = (request2, client) => {
47520
- const stopping = driver.stopTask?.(request2.taskId) ?? Promise.resolve(TASK_UNSUPPORTED);
47521
- stopping.then((result) => {
47522
- log.info("holder.task_stop", { runId: request2.runId, taskId: request2.taskId, result });
47523
- writeMessage(client, { type: "task_stopped", id: request2.id, result });
47524
- }).catch((error61) => {
47525
- log.warn("holder.task_stop_crashed", { runId: request2.runId, error: error61 });
47526
- writeMessage(client, {
47527
- type: "task_stopped",
47528
- id: request2.id,
47529
- result: { ok: false, reason: "failed", message: "The task could not be stopped" }
47834
+ };
47835
+ const stopTask = (request2, client) => {
47836
+ const stopping = driver.stopTask?.(request2.taskId) ?? Promise.resolve(TASK_UNSUPPORTED);
47837
+ stopping.then((result) => {
47838
+ log.info("holder.task_stop", { runId: request2.runId, taskId: request2.taskId, result });
47839
+ writeMessage(client, { type: "task_stopped", id: request2.id, result });
47840
+ }).catch((error61) => {
47841
+ log.warn("holder.task_stop_crashed", { runId: request2.runId, error: error61 });
47842
+ writeMessage(client, {
47843
+ type: "task_stopped",
47844
+ id: request2.id,
47845
+ result: { ok: false, reason: "failed", message: "The task could not be stopped" }
47846
+ });
47530
47847
  });
47531
- });
47532
- };
47533
- const handle = (request2, client) => {
47534
- switch (request2.type) {
47535
- case "auth":
47536
- return;
47537
- case "start_turn":
47538
- startTurn(request2.id, request2.spec, client);
47539
- return;
47540
- case "respond":
47541
- respond(request2, client);
47542
- return;
47543
- case "stop_task":
47544
- stopTask(request2, client);
47545
- return;
47546
- case "abort":
47547
- if (holder.runId === request2.runId) holder.turn?.abort(request2.outcome ?? "aborted");
47548
- writeMessage(client, { type: "ack", id: request2.id });
47549
- return;
47550
- case "status":
47551
- void facts.snapshot().then(
47552
- (snapshot2) => writeMessage(client, {
47553
- type: "status",
47554
- id: request2.id,
47555
- state: holder.state,
47556
- runId: holder.runId,
47557
- facts: snapshot2
47558
- })
47559
- );
47560
- return;
47561
- case "suspend":
47562
- if (holder.state === "running") {
47563
- writeMessage(client, {
47564
- type: "error",
47565
- id: request2.id,
47566
- code: "busy",
47567
- message: "A turn is running; it is never killed to suspend"
47568
- });
47848
+ };
47849
+ const handle = (request2, client) => {
47850
+ switch (request2.type) {
47851
+ case "auth":
47569
47852
  return;
47570
- }
47571
- holder.state = "suspending";
47572
- writeMessage(client, { type: "ack", id: request2.id });
47573
- exit.abort();
47574
- return;
47575
- default:
47576
- assertNever2(request2);
47577
- }
47578
- };
47579
- const server = (0, import_node_net2.createServer)((client) => {
47580
- let authenticated = false;
47581
- readMessages(client, holderRequestSchema, {
47582
- onMessage: (request2) => {
47583
- if (!authenticated) {
47584
- if (request2.type !== "auth" || !tokenMatches(launch.token, request2.token)) {
47585
- client.destroy();
47853
+ case "start_turn":
47854
+ startTurn(request2.id, request2.spec, client);
47855
+ return;
47856
+ case "respond":
47857
+ respond(request2, client);
47858
+ return;
47859
+ case "stop_task":
47860
+ stopTask(request2, client);
47861
+ return;
47862
+ case "abort":
47863
+ if (holder.runId === request2.runId) holder.turn?.abort(request2.outcome ?? "aborted");
47864
+ writeMessage(client, { type: "ack", id: request2.id });
47865
+ return;
47866
+ case "status":
47867
+ void facts.snapshot().then(
47868
+ (snapshot2) => writeMessage(client, {
47869
+ type: "status",
47870
+ id: request2.id,
47871
+ state: holder.state,
47872
+ runId: holder.runId,
47873
+ facts: snapshot2
47874
+ })
47875
+ );
47876
+ return;
47877
+ case "suspend":
47878
+ if (holder.state === "running") {
47879
+ writeMessage(client, {
47880
+ type: "error",
47881
+ id: request2.id,
47882
+ code: "busy",
47883
+ message: "A turn is running; it is never killed to suspend"
47884
+ });
47586
47885
  return;
47587
47886
  }
47588
- authenticated = true;
47589
- holder.clients.add(client);
47590
- writeMessage(client, {
47591
- type: "ready",
47592
- protocol: HOLDER_PROTOCOL,
47593
- conversationId: launch.conversationId,
47594
- pid: identity.pid
47595
- });
47887
+ holder.state = "suspending";
47888
+ writeMessage(client, { type: "ack", id: request2.id });
47889
+ exit.abort();
47596
47890
  return;
47597
- }
47598
- handle(request2, client);
47599
- },
47600
- onInvalid: (reason) => log.warn("holder.request_invalid", { reason })
47601
- });
47602
- client.on("close", () => holder.clients.delete(client));
47603
- client.on("error", () => holder.clients.delete(client));
47604
- });
47605
- removeStaleEndpoint(launch.endpoint);
47606
- await new Promise((resolve5, reject) => {
47607
- server.once("error", reject);
47608
- server.listen(launch.endpoint, () => resolve5());
47609
- });
47610
- await writeStatus();
47611
- log.info("holder.ready", { conversationId: launch.conversationId, pid: identity.pid });
47612
- await new Promise((resolve5) => exit.signal.addEventListener("abort", () => resolve5()));
47613
- await driver.suspend?.().catch((error61) => log.warn("holder.driver_suspend_failed", { error: error61 }));
47614
- for (const client of holder.clients) client.end();
47615
- await new Promise((resolve5) => server.close(() => resolve5()));
47616
- (0, import_node_fs10.rmSync)(launch.statusPath, { force: true });
47617
- log.info("holder.suspended", { conversationId: launch.conversationId });
47891
+ default:
47892
+ assertNever2(request2);
47893
+ }
47894
+ };
47895
+ const server = (0, import_node_net2.createServer)((client) => {
47896
+ let authenticated = false;
47897
+ readMessages(client, holderRequestSchema, {
47898
+ onMessage: (request2) => {
47899
+ if (!authenticated) {
47900
+ if (request2.type !== "auth" || !tokenMatches(launch.token, request2.token)) {
47901
+ client.destroy();
47902
+ return;
47903
+ }
47904
+ authenticated = true;
47905
+ holder.clients.add(client);
47906
+ writeMessage(client, {
47907
+ type: "ready",
47908
+ protocol: HOLDER_PROTOCOL,
47909
+ conversationId: launch.conversationId,
47910
+ pid: identity.pid
47911
+ });
47912
+ return;
47913
+ }
47914
+ handle(request2, client);
47915
+ },
47916
+ onInvalid: (reason) => log.warn("holder.request_invalid", { reason })
47917
+ });
47918
+ client.on("close", () => holder.clients.delete(client));
47919
+ client.on("error", () => holder.clients.delete(client));
47920
+ });
47921
+ removeStaleEndpoint(launch.endpoint);
47922
+ await new Promise((resolve6, reject) => {
47923
+ server.once("error", reject);
47924
+ server.listen(launch.endpoint, () => resolve6());
47925
+ });
47926
+ await writeStatus();
47927
+ log.info("holder.ready", { conversationId: launch.conversationId, pid: identity.pid });
47928
+ await new Promise((resolve6) => exit.signal.addEventListener("abort", () => resolve6()));
47929
+ await driver.suspend?.().catch((error61) => log.warn("holder.driver_suspend_failed", { error: error61 }));
47930
+ for (const client of holder.clients) client.end();
47931
+ await new Promise((resolve6) => server.close(() => resolve6()));
47932
+ (0, import_node_fs10.rmSync)(launch.statusPath, { force: true });
47933
+ log.info("holder.suspended", { conversationId: launch.conversationId });
47934
+ } catch (_) {
47935
+ var _error = _, _hasError = true;
47936
+ } finally {
47937
+ __callDispose(_stack, _error, _hasError);
47938
+ }
47618
47939
  }
47619
47940
 
47620
47941
  // src/sessions/suspend-policy.ts
@@ -47657,6 +47978,8 @@ var envSchema = external_exports.object({
47657
47978
  ALAN_RUNTIME_PROVIDER_NPM_CLI: external_exports.string().min(1).optional(),
47658
47979
  ALAN_RUNTIME_HOST: external_exports.enum(RUNTIME_HOST_KINDS).default("standalone"),
47659
47980
  ALAN_RUNTIME_GITHUB_PROXY: external_exports.enum(["on", "off"]).default("off"),
47981
+ ALAN_RUNTIME_GIT_GATEWAY_URL: external_exports.url().optional(),
47982
+ ALAN_RUNTIME_WORKSPACE_ROOT: external_exports.string().min(1).optional(),
47660
47983
  XDG_CONFIG_HOME: external_exports.string().min(1).optional(),
47661
47984
  GH_CONFIG_DIR: external_exports.string().min(1).optional()
47662
47985
  });
@@ -47677,6 +48000,11 @@ var RUNTIME_ENV_PREFIX = "ALAN_RUNTIME_";
47677
48000
  var MAX_ACTIVE_RUNS_VARIABLE = "ALAN_MAX_ACTIVE_RUNS";
47678
48001
  var MAX_ACTIVE_RUNS_RANGE = { min: 1, max: 32 };
47679
48002
  var SETUP_TOKEN_VARIABLE = "ALAN_RUNTIME_SETUP_TOKEN";
48003
+ var ENROLLMENT_CODE_VARIABLE = "ALAN_RUNTIME_ENROLLMENT_CODE";
48004
+ var SECRET_VARIABLES = /* @__PURE__ */ new Set([
48005
+ SETUP_TOKEN_VARIABLE,
48006
+ ENROLLMENT_CODE_VARIABLE
48007
+ ]);
47680
48008
  var ALAN_CODE_ENGINE_VARIABLE = "ALAN_CODE_ENGINE_PATH";
47681
48009
  function loadRuntimeConfig(env = process.env, totalMemoryBytes = (0, import_node_os7.totalmem)()) {
47682
48010
  const parsed = envSchema.safeParse(env);
@@ -47703,6 +48031,8 @@ function loadRuntimeConfig(env = process.env, totalMemoryBytes = (0, import_node
47703
48031
  ALAN_RUNTIME_PROVIDER_NPM_CLI,
47704
48032
  ALAN_RUNTIME_HOST,
47705
48033
  ALAN_RUNTIME_GITHUB_PROXY,
48034
+ ALAN_RUNTIME_GIT_GATEWAY_URL,
48035
+ ALAN_RUNTIME_WORKSPACE_ROOT,
47706
48036
  XDG_CONFIG_HOME,
47707
48037
  GH_CONFIG_DIR
47708
48038
  } = parsed.data;
@@ -47736,24 +48066,26 @@ function loadRuntimeConfig(env = process.env, totalMemoryBytes = (0, import_node
47736
48066
  providerProbes: ALAN_RUNTIME_PROVIDER_PROBES === "on",
47737
48067
  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,
47738
48068
  home,
47739
- configHome: XDG_CONFIG_HOME ?? (0, import_node_path23.join)(home, ".config"),
48069
+ configHome: XDG_CONFIG_HOME ?? (0, import_node_path27.join)(home, ".config"),
47740
48070
  ...githubProxyConfig({ ALAN_RUNTIME_GITHUB_PROXY, XDG_CONFIG_HOME, GH_CONFIG_DIR }, home),
48071
+ gitGatewayUrl: ALAN_RUNTIME_GIT_GATEWAY_URL ?? null,
48072
+ workspaceRoot: ALAN_RUNTIME_WORKSPACE_ROOT ?? null,
47741
48073
  serviceEnvironment: serviceEnvironment(env, ALAN_RUNTIME_PROFILE),
47742
48074
  adoptsLegacyInstall: ALAN_RUNTIME_STATE_DIR === void 0
47743
48075
  };
47744
48076
  }
47745
48077
  function githubProxyConfig(env, home) {
47746
- const configHome = env.XDG_CONFIG_HOME ?? (0, import_node_path23.join)(home, ".config");
48078
+ const configHome = env.XDG_CONFIG_HOME ?? (0, import_node_path27.join)(home, ".config");
47747
48079
  return {
47748
48080
  githubProxy: env.ALAN_RUNTIME_GITHUB_PROXY === "on",
47749
- ghConfigDir: env.GH_CONFIG_DIR ?? (0, import_node_path23.join)(configHome, "gh")
48081
+ ghConfigDir: env.GH_CONFIG_DIR ?? (0, import_node_path27.join)(configHome, "gh")
47750
48082
  };
47751
48083
  }
47752
48084
  function serviceEnvironment(env, profile) {
47753
48085
  const result = { ALAN_RUNTIME_PROFILE: profile };
47754
48086
  for (const [key, value] of Object.entries(env)) {
47755
48087
  const copied = key.startsWith(RUNTIME_ENV_PREFIX) || key === MAX_ACTIVE_RUNS_VARIABLE || key === ALAN_CODE_ENGINE_VARIABLE;
47756
- if (!copied || key === SETUP_TOKEN_VARIABLE) continue;
48088
+ if (!copied || SECRET_VARIABLES.has(key)) continue;
47757
48089
  if (value !== void 0 && value.length > 0) result[key] = value;
47758
48090
  }
47759
48091
  return result;
@@ -47786,7 +48118,10 @@ var ELECTRON_ENV_PREFIX = "ELECTRON_";
47786
48118
  function readCliEnvironment(env = process.env) {
47787
48119
  const result = {};
47788
48120
  for (const [key, value] of Object.entries(env)) {
47789
- if (value !== void 0 && !key.startsWith(ELECTRON_ENV_PREFIX)) result[key] = value;
48121
+ if (value === void 0 || key.startsWith(ELECTRON_ENV_PREFIX) || SECRET_VARIABLES.has(key)) {
48122
+ continue;
48123
+ }
48124
+ result[key] = value;
47790
48125
  }
47791
48126
  return result;
47792
48127
  }
@@ -47842,7 +48177,7 @@ async function loadStoredAccess(paths, access3 = { exec: systemExec }) {
47842
48177
  }
47843
48178
 
47844
48179
  // src/cli/commands/hold.ts
47845
- var import_node_path24 = require("path");
48180
+ var import_node_path28 = require("path");
47846
48181
  init_runtime_v2();
47847
48182
  async function machineAccess(paths, log, conversationId, transport) {
47848
48183
  const initial = await loadStoredAccess(paths).catch(
@@ -47859,10 +48194,6 @@ async function machineAccess(paths, log, conversationId, transport) {
47859
48194
  transport
47860
48195
  });
47861
48196
  };
47862
- const source = {
47863
- downloadAttachment: async (runId, id, signal) => (await api()).downloadAttachment(runId, id, signal),
47864
- fetchProviderCredential: async (runId, signal) => (await api()).fetchProviderCredential(runId, signal)
47865
- };
47866
48197
  const apiUrl = initial?.endpoints.apiUrl;
47867
48198
  const managedMcp = apiUrl === void 0 ? void 0 : {
47868
48199
  url: new URL("/mcp", apiUrl).href,
@@ -47872,6 +48203,13 @@ async function machineAccess(paths, log, conversationId, transport) {
47872
48203
  log
47873
48204
  })
47874
48205
  };
48206
+ const source = {
48207
+ downloadAttachment: async (runId, id, signal) => (await api()).downloadAttachment(runId, id, signal),
48208
+ fetchProviderCredential: async (runId, signal) => {
48209
+ void managedMcp?.authorization(signal);
48210
+ return (await api()).fetchProviderCredential(runId, signal);
48211
+ }
48212
+ };
47875
48213
  return { source, managedMcp };
47876
48214
  }
47877
48215
  async function runHold(argv) {
@@ -47889,7 +48227,7 @@ async function runHold(argv) {
47889
48227
  const config2 = loadRuntimeConfig();
47890
48228
  const paths = runtimePaths(config2.stateDir);
47891
48229
  const log = __using(_stack, openFileLog(
47892
- (0, import_node_path24.join)(paths.logs, `holder-${launch.value.conversationId}.jsonl`),
48230
+ (0, import_node_path28.join)(paths.logs, `holder-${launch.value.conversationId}.jsonl`),
47893
48231
  config2.logLevel,
47894
48232
  systemClock
47895
48233
  ));
@@ -47912,7 +48250,12 @@ async function runHold(argv) {
47912
48250
  clock: systemClock,
47913
48251
  log,
47914
48252
  inputs: { source: access3.source, tmpDir: paths.tmp },
47915
- machine: { env: cliEnvironment, stateDir: paths.stateDir }
48253
+ machine: {
48254
+ env: cliEnvironment,
48255
+ stateDir: paths.stateDir,
48256
+ // Only a cloud sandbox's runtime has a git gateway.
48257
+ refreshesFirstCheckout: config2.gitGatewayUrl !== null
48258
+ }
47916
48259
  });
47917
48260
  } catch (_) {
47918
48261
  var _error = _, _hasError = true;