@alan-ai-hq/agent-manager-darwin-arm64 0.1.142 → 0.1.144

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 +908 -639
  2. package/alan-holder.cjs +433 -371
  3. package/package.json +1 -1
package/alan-agent.cjs CHANGED
@@ -21524,37 +21524,15 @@ Platform Documents are the default destination and source of truth for PM work.
21524
21524
 
21525
21525
  Do NOT call \`create_plan\`, \`create_document_artifact\`, or another artifact-creation tool unless the user explicitly asks for an **artifact**. If \`create_document\` is unavailable or fails, report that blocker; do not silently substitute an artifact.
21526
21526
 
21527
- ## Platform knowledge lookups
21527
+ ## Evidence and source selection
21528
21528
 
21529
- The Alan platform is where product truth lives: tasks, subtasks, decisions, events, sessions, artifacts, context, and Documents. For that platform knowledge, local files and shell commands are a **last resort**, not a starting point. Browser and computer use remain available for authorized UI inspection and QA.
21529
+ Follow the shared tool-choice guidance. Use platform Documents for team requirements, PRDs, specifications, and decisions: resolve named records with \`find_records\`, browse with \`list_documents\`, and read with \`get_document\`. Use task, session, and artifact tools for their respective records.
21530
21530
 
21531
- **Before every platform knowledge lookup, ask: does the platform know this?** If a platform MCP tool could plausibly answer the question, you MUST call it before any \`Read\`, \`Glob\`, \`Grep\`, or \`Bash\`. Reaching for a local tool first is a mistake even when it would be faster or you already know the file path. Inspecting transient UI state is product QA, not a platform knowledge lookup.
21531
+ Use browser and computer tools to inspect live interfaces, and local read-only tools for repository documentation, source, logs, and version history when relevant. Prefer the source the user names. Words such as "notes" or "docs" alone do not forbid repository inspection; use the available context to identify the likely source.
21532
21532
 
21533
- | What you want | Use this | Not this |
21534
- |---|---|---|
21535
- | Requirements, PRDs, specs, notes, any written knowledge | \`list_documents\`, \`find_records\`, \`get_document\` | reading \`docs/\`, \`notes/\`, \`README.md\` |
21536
- | Scope, status, priority, or history of work | \`get_task\`, \`list_subtasks\`, \`list_tasks\` | \`git log\`, commit messages |
21537
- | What was decided and why | \`list_task_decisions\`, \`list_task_events\` | code comments, in-repo ADRs |
21538
- | What an agent did or is doing | \`list_sessions\`, \`get_session_context\` | \`git log\`, diffing the worktree |
21539
- | Prior agent context | \`list_task_events\`, \`get_session_context\` | scratch files |
21540
- | Outputs of completed work | \`list_artifacts\`, \`get_artifact\` | build output, generated files |
21541
- | Where code lives or how it works | \`search_code_context\` first, then \`Read\` the cited files | \`Grep\`/\`Glob\` sweeps |
21533
+ When a platform search is empty or unavailable, continue with other relevant permitted sources and state any evidence gap. Do not treat repository evidence as proof of a missing platform record, and do not bypass denied platform actions. Ask one targeted question only when the ambiguity prevents useful progress.
21542
21534
 
21543
- **If you do fall back to a local tool, say so out loud** \u2014 name the platform tool you tried and what it returned (nothing, unavailable, insufficient). A silent local read is a violation of this rule. If no platform tool was tried, you have not earned the local read.
21544
-
21545
- Code is the exception that proves the rule: understanding how something works legitimately ends in reading source. Even then, start with \`search_code_context\` and read only the files it cites.
21546
-
21547
- **Default for written knowledge: platform Documents.** Any request to find, check, consult, review, summarize, or answer from written knowledge resolves against platform Documents \u2014 use \`list_documents\` or \`find_records\` with \`kinds=["document"]\` to locate it, then \`get_document\` to read it. If a document ID is already known, call \`get_document\` directly.
21548
-
21549
- This applies no matter which word the user uses. Treat all of these as the same request: docs, documentation, documents, notes, PRD, spec, requirements, design doc, plan, proposal, RFC, wiki, runbook, onboarding, guidelines, "what did we decide", "what did we write down", "what do we have on X". The noun never changes where you look.
21550
-
21551
- **Local repository files are off-limits for knowledge lookup** unless the user unambiguously points you at the repository. Do not read \`README.md\`, \`AGENTS.md\`, \`notes/\`, \`docs/\`, or any other in-repo file as a fallback, as corroboration, because no platform document matched, or because the user's wording happens to match a directory name.
21552
-
21553
- A bare noun is never a pointer to the repository. "Check the notes" means platform Documents, not \`notes/\`. "Check the docs" means platform Documents, not \`docs/\`. Only these count as pointing at the repository:
21554
- - an explicit location \u2014 "in the repo", "in the codebase", "local files", "on disk", "in the worktree"
21555
- - a concrete path or filename \u2014 \`notes/foo.md\`, \`AGENTS.md\`, "the readme"
21556
-
21557
- When platform Documents do not cover the question, stop and say so, then offer to check the repository. Do not read local files first, and do not guess. Cite which document answered the question.
21535
+ For team code discovery, follow the shared \`search_code_context\` guidance, verify cited files locally, and use focused local searches when needed.
21558
21536
 
21559
21537
  ## Your primary tools
21560
21538
 
@@ -22066,18 +22044,23 @@ var init_system_prompt = __esm({
22066
22044
  init_agent_definitions();
22067
22045
  ALAN_CONTEXT_SEARCH_PROMPT = `## Memory (non-code context)
22068
22046
 
22069
- The codebase records what the system does. It does not record why it is that way, what was ruled out, what an outside constraint forbids, or what someone was left owed. That record lives in \`search_context\` \u2014 this team's decisions, constraints, procedures, ownership, rejected approaches and unfinished work.
22047
+ Use \`search_context\` first for team-specific decisions, constraints, ownership, history, or unfinished work when the exact source is unknown. Skip it for source-code questions, general knowledge, fully specified mechanical work, or a known record ID.
22070
22048
 
22071
- Before answering or acting on a question about a past decision, ownership, history, or unfinished work whose exact source is unknown, call \`search_context\` first.
22049
+ Apply relevant retrieved decisions and cite their source. Compare them with current evidence; retrieved context can be incomplete or stale. If search is empty or unavailable, continue with other relevant permitted sources and explain any remaining evidence gap.
22072
22050
 
22073
- So when a turn depends on something the repository cannot tell you \u2014 a value chosen rather than tuned, an approach that may already have been tried, a boundary another team owns, work someone else left half-done \u2014 recover it before you answer or act. Reading the code, or the document someone named, does not settle it: those answer a different question, and one turn can need both.
22051
+ For questions about recent activity, inspect available evidence for the relevant time window. Use records for task history, browser tools for live interfaces, and source, logs, or version history for implementation changes. A reference to "recently" or "a few days ago" calls for evidence, not an answer from memory.`;
22052
+ ALAN_PLATFORM_TOOL_ROUTING_PROMPT = `## Tool choice
22074
22053
 
22075
- What comes back is the answer, not a step towards it. Carry its specifics into what you write or change \u2014 the value, the constraint, the reason, the person \u2014 and say plainly when the evidence contradicts what was asked for. Retrieving a decision and then producing work that ignores it is worse than never having searched, because it looks informed.
22054
+ Choose tools by the evidence or action the request needs, whether the agent runs locally or in the cloud:
22055
+ - Use Alan MCP for canonical Alan records (tasks, sessions, documents, artifacts, and their relationships), platform actions such as managing runs or machines, and actions through a provider identity connected to Alan.
22056
+ - Use computer use and browser tools for live websites and interfaces, including the authenticated Alan app, transient DOM and CSS state, and product QA in development or test environments. When the user asks you to inspect a website or interface, use the available browser or computer tools without asking for permission again for ordinary inspection.
22057
+ - Use local file, shell, and diagnostic tools for repository source, version history, processes, logs, and runtime behavior. MCP is not a prerequisite for browser inspection or local diagnostics. Follow the codebase-index guidance for team code discovery.
22076
22058
 
22077
- Skip it when nothing team-specific is at stake: source-code questions, general knowledge, mechanical work fully specified in the request, or an exact ID already in hand.`;
22078
- ALAN_PLATFORM_TOOL_ROUTING_PROMPT = `## Alan platform and GitHub
22059
+ Use the available repository tools for GitHub work, including git and gh when useful. If a cloud GitHub request reports github_not_connected, call request_github_connection in the current conversation and end the turn. The chat will offer GitHub authorization and resume after the user connects. Continue other independent work when possible.
22079
22060
 
22080
- Use Alan MCP tools for canonical Alan records and platform actions: tasks, sessions, documents, artifacts, runs, and machines. Use the available repository tools for GitHub work, including git and gh when useful. If a cloud GitHub request reports github_not_connected, call request_github_connection in the current conversation and end the turn. The chat will offer GitHub authorization and resume after the user connects. Continue other independent work when possible.`;
22061
+ An empty search result is not a permission denial. Continue gathering evidence from relevant permitted sources rather than refusing the request because one source cannot answer. Distinguish observed facts from inference and name remaining evidence gaps.
22062
+
22063
+ If a needed tool is not exposed, use the host's tool-discovery mechanism once when available before claiming the capability is unavailable. If a canonical platform action remains unavailable or unauthorized, report it and stop that platform action only; continue independent debugging and testing. Do not use a shell CLI, browser, raw HTTP, or local files to bypass that action or its identity and authorization requirements. Do not bypass a workflow or role tool allowlist.`;
22081
22064
  ALAN_IDENTITY_PROMPT = `You are Alan, the software factory agent. Alan ships software end to end \u2014 plan, write, review, test, deploy.
22082
22065
 
22083
22066
  ## How Alan is structured
@@ -22101,7 +22084,7 @@ Team
22101
22084
  - Listen first. Don't jump to solutions. One question at a time, not a list.
22102
22085
  - Scan available context (task, subtasks, code, history) before asking questions you can answer yourself.
22103
22086
  - Challenge when off \u2014 never silently implement the wrong thing.
22104
- - Human leads, you propose. Proactive on reversible actions. Consequential decisions \u2192 propose first, execute after confirmation.
22087
+ - Act on the user's request and make reasonable implementation and tool choices within its scope. Do not ask again for permission already granted. Ask only when essential information is missing or an action requires additional authority.
22105
22088
  - Own mistakes. Wrong ID, jumped too fast \u2014 say so and fix it.
22106
22089
  - Write for a human reader. Task, subtask and epic descriptions, documents, artifacts and comments are read by people in the app, not parsed by agents. Lead with the outcome in one sentence, then short sections with headings and bullet lists. Spell out internal shorthand, and keep commit hashes, IDs and migration numbers out of sentences \u2014 put them in a trailing "References" list when they matter.
22107
22090
  - Think visually, proactively \u2014 not only when asked. Mermaid over paragraphs for architecture, flows, state, and schema. The same applies to data: when you're about to present a comparison, trend, breakdown, or status across several items, reach for a \`\`\`chart fence instead of a paragraph of numbers or a markdown table, even if the user never said the word "chart."
@@ -22554,7 +22537,7 @@ function plan(command, args, options) {
22554
22537
  function captureOutput(command, args, options) {
22555
22538
  const launch = plan(command, args, options);
22556
22539
  if (launch === void 0) return Promise.resolve(NEVER_STARTED);
22557
- return new Promise((resolve12) => {
22540
+ return new Promise((resolve13) => {
22558
22541
  (0, import_child_process.execFile)(
22559
22542
  launch.file,
22560
22543
  [...launch.args],
@@ -22568,7 +22551,7 @@ function captureOutput(command, args, options) {
22568
22551
  },
22569
22552
  (error61, stdout, stderr) => {
22570
22553
  const code = error61 && typeof error61.code === "number" ? error61.code : error61 ? void 0 : 0;
22571
- resolve12({ stdout, stderr, exitCode: code });
22554
+ resolve13({ stdout, stderr, exitCode: code });
22572
22555
  }
22573
22556
  );
22574
22557
  });
@@ -22618,10 +22601,10 @@ async function linuxStartTicks(pid) {
22618
22601
  }
22619
22602
  }
22620
22603
  function psStartTime(pid) {
22621
- return new Promise((resolve12) => {
22604
+ return new Promise((resolve13) => {
22622
22605
  (0, import_child_process2.execFile)("ps", ["-o", "lstart=", "-p", String(pid)], { timeout: 2e3 }, (error61, stdout) => {
22623
22606
  const text2 = stdout.trim();
22624
- resolve12(error61 || !text2 ? void 0 : text2);
22607
+ resolve13(error61 || !text2 ? void 0 : text2);
22625
22608
  });
22626
22609
  });
22627
22610
  }
@@ -22650,12 +22633,12 @@ function parseProcessList(text2) {
22650
22633
  }
22651
22634
  function listProcesses(platform3 = process.platform) {
22652
22635
  if (platform3 === "win32") return Promise.resolve([]);
22653
- return new Promise((resolve12) => {
22636
+ return new Promise((resolve13) => {
22654
22637
  (0, import_child_process3.execFile)(
22655
22638
  "ps",
22656
22639
  ["-A", "-o", "pid=,ppid=,pgid=,lstart="],
22657
22640
  { timeout: 5e3, maxBuffer: 8 * 1024 * 1024 },
22658
- (error61, stdout) => resolve12(error61 ? [] : parseProcessList(stdout))
22641
+ (error61, stdout) => resolve13(error61 ? [] : parseProcessList(stdout))
22659
22642
  );
22660
22643
  });
22661
22644
  }
@@ -22695,11 +22678,11 @@ async function taskkill(pid, options) {
22695
22678
  stdio: "ignore",
22696
22679
  windowsHide: true
22697
22680
  });
22698
- const exited = new Promise((resolve12) => {
22699
- killer.once("error", (error210) => resolve12(error210));
22681
+ const exited = new Promise((resolve13) => {
22682
+ killer.once("error", (error210) => resolve13(error210));
22700
22683
  killer.once(
22701
22684
  "exit",
22702
- (code, signal) => resolve12(code === 0 ? void 0 : new Error(`taskkill failed: exit ${code}, signal ${signal}`))
22685
+ (code, signal) => resolve13(code === 0 ? void 0 : new Error(`taskkill failed: exit ${code}, signal ${signal}`))
22703
22686
  );
22704
22687
  });
22705
22688
  const timedOut = clock.sleep(options.timeoutMs ?? DEFAULT_TASKKILL_TIMEOUT_MS, timeout.signal).then(() => new Error("taskkill timed out")).catch(() => void 0);
@@ -22955,10 +22938,10 @@ function spawnCli(options) {
22955
22938
  function waitForSpawn(child, command) {
22956
22939
  if (isWindowsJob(child)) return waitForWindowsJob(child, command);
22957
22940
  if (child.pid !== void 0) return Promise.resolve();
22958
- return new Promise((resolve12, reject) => {
22941
+ return new Promise((resolve13, reject) => {
22959
22942
  const onSpawn = () => {
22960
22943
  child.off("error", onError);
22961
- resolve12();
22944
+ resolve13();
22962
22945
  };
22963
22946
  const onError = (error61) => {
22964
22947
  child.off("spawn", onSpawn);
@@ -23349,69 +23332,47 @@ var init_models = __esm({
23349
23332
  maxOutputTokens: 16384
23350
23333
  },
23351
23334
  {
23352
- id: "z-ai/glm-4.7-flash",
23353
- name: "GLM 4.7 Flash",
23354
- description: "Fast GLM coding via Alan",
23335
+ id: "z-ai/glm-5.3",
23336
+ name: "GLM 5.3",
23337
+ description: "Z.ai's flagship for coding, agents and long-horizon work",
23355
23338
  enabled: true,
23356
23339
  isDefault: false,
23357
23340
  sortOrder: 30,
23358
- upstreamModelId: "z-ai/glm-4.7-flash",
23359
- contextWindow: 2e5,
23360
- maxOutputTokens: 8192
23361
- },
23362
- {
23363
- id: "z-ai/glm-4.7",
23364
- name: "GLM 4.7",
23365
- description: "GLM coding and multi-step agent work",
23366
- enabled: true,
23367
- isDefault: false,
23368
- sortOrder: 40,
23369
- upstreamModelId: "z-ai/glm-4.7",
23370
- contextWindow: 2e5,
23341
+ upstreamModelId: "z-ai/glm-5.3",
23342
+ contextWindow: 1048576,
23371
23343
  maxOutputTokens: 16384
23372
23344
  },
23373
23345
  {
23374
- id: "qwen/qwen3-coder-flash",
23375
- name: "Qwen3 Coder Flash",
23376
- description: "Fast Qwen coder via Alan",
23346
+ id: "z-ai/glm-5.3-flash",
23347
+ name: "GLM 5.3 Flash",
23348
+ description: "Fast multimodal GLM via Alan",
23377
23349
  enabled: true,
23378
23350
  isDefault: false,
23379
- sortOrder: 50,
23380
- upstreamModelId: "qwen/qwen3-coder-flash",
23381
- contextWindow: 128e3,
23382
- maxOutputTokens: 8192
23383
- },
23384
- {
23385
- id: "qwen/qwen3-coder",
23386
- name: "Qwen3 Coder",
23387
- description: "Open-weight oriented coding",
23388
- enabled: true,
23389
- isDefault: false,
23390
- sortOrder: 60,
23391
- upstreamModelId: "qwen/qwen3-coder",
23392
- contextWindow: 128e3,
23351
+ sortOrder: 40,
23352
+ upstreamModelId: "z-ai/glm-5.3-flash",
23353
+ contextWindow: 1048576,
23393
23354
  maxOutputTokens: 8192
23394
23355
  },
23395
23356
  {
23396
- id: "moonshotai/kimi-k2.6",
23397
- name: "Kimi K2.6",
23398
- description: "Fast Kimi for long-horizon coding",
23357
+ id: "qwen/qwen3.8-27b",
23358
+ name: "Qwen3.8 27B",
23359
+ description: "Qwen3.8 open-weight coding and agentic work",
23399
23360
  enabled: true,
23400
23361
  isDefault: false,
23401
- sortOrder: 70,
23402
- upstreamModelId: "moonshotai/kimi-k2.6",
23403
- contextWindow: 262144,
23362
+ sortOrder: 50,
23363
+ upstreamModelId: "qwen/qwen3.8-27b",
23364
+ contextWindow: 1e6,
23404
23365
  maxOutputTokens: 16384
23405
23366
  },
23406
23367
  {
23407
- id: "moonshotai/kimi-k2.7-code",
23408
- name: "Kimi K2.7 Code",
23409
- description: "Kimi coding specialist",
23368
+ id: "moonshotai/kimi-k3",
23369
+ name: "Kimi K3",
23370
+ description: "Moonshot's 2.8T open-weight flagship",
23410
23371
  enabled: true,
23411
23372
  isDefault: false,
23412
- sortOrder: 80,
23413
- upstreamModelId: "moonshotai/kimi-k2.7-code",
23414
- contextWindow: 262144,
23373
+ sortOrder: 60,
23374
+ upstreamModelId: "moonshotai/kimi-k3",
23375
+ contextWindow: 1048576,
23415
23376
  maxOutputTokens: 16384
23416
23377
  },
23417
23378
  {
@@ -23420,7 +23381,7 @@ var init_models = __esm({
23420
23381
  description: "Fast Nemotron via Alan",
23421
23382
  enabled: true,
23422
23383
  isDefault: false,
23423
- sortOrder: 90,
23384
+ sortOrder: 70,
23424
23385
  upstreamModelId: "nvidia/nemotron-3-nano-30b-a3b",
23425
23386
  contextWindow: 262144,
23426
23387
  maxOutputTokens: 8192
@@ -23431,7 +23392,7 @@ var init_models = __esm({
23431
23392
  description: "Mid-tier Nemotron via Alan",
23432
23393
  enabled: true,
23433
23394
  isDefault: false,
23434
- sortOrder: 100,
23395
+ sortOrder: 80,
23435
23396
  upstreamModelId: "nvidia/nemotron-3-super-120b-a12b",
23436
23397
  contextWindow: 262144,
23437
23398
  maxOutputTokens: 16384
@@ -23442,18 +23403,29 @@ var init_models = __esm({
23442
23403
  description: "Largest Nemotron via Alan",
23443
23404
  enabled: true,
23444
23405
  isDefault: false,
23445
- sortOrder: 110,
23406
+ sortOrder: 90,
23446
23407
  upstreamModelId: "nvidia/nemotron-3-ultra-550b-a55b",
23447
23408
  contextWindow: 262144,
23448
23409
  maxOutputTokens: 16384
23449
23410
  },
23411
+ {
23412
+ id: "nvidia/nemotron-3.5-lightning",
23413
+ name: "Nemotron 3.5 Lightning",
23414
+ description: "Small, fast Nemotron for high-volume work",
23415
+ enabled: true,
23416
+ isDefault: false,
23417
+ sortOrder: 100,
23418
+ upstreamModelId: "nvidia/nemotron-3.5-lightning",
23419
+ contextWindow: 262144,
23420
+ maxOutputTokens: 8192
23421
+ },
23450
23422
  {
23451
23423
  id: "meta/muse-spark-1.3-contributor",
23452
23424
  name: "Muse Spark 1.3 Contributor",
23453
23425
  description: "Cost-efficient Muse Spark (contributor tier)",
23454
23426
  enabled: true,
23455
23427
  isDefault: false,
23456
- sortOrder: 120,
23428
+ sortOrder: 110,
23457
23429
  upstreamModelId: "meta/muse-spark-1.3-contributor",
23458
23430
  contextWindow: 1048576,
23459
23431
  maxOutputTokens: 16384
@@ -23464,7 +23436,7 @@ var init_models = __esm({
23464
23436
  description: "Meta Muse Spark multimodal agentic coding",
23465
23437
  enabled: true,
23466
23438
  isDefault: false,
23467
- sortOrder: 130,
23439
+ sortOrder: 120,
23468
23440
  upstreamModelId: "meta/muse-spark-1.3",
23469
23441
  contextWindow: 1048576,
23470
23442
  maxOutputTokens: 16384
@@ -23475,7 +23447,7 @@ var init_models = __esm({
23475
23447
  description: "Prior Muse Spark contributor tier",
23476
23448
  enabled: true,
23477
23449
  isDefault: false,
23478
- sortOrder: 140,
23450
+ sortOrder: 130,
23479
23451
  upstreamModelId: "meta/muse-spark-1.2-contributor",
23480
23452
  contextWindow: 1048576,
23481
23453
  maxOutputTokens: 16384
@@ -26388,8 +26360,8 @@ function createJsonRpcPeer(writer, handlers) {
26388
26360
  },
26389
26361
  request: (method, params = {}) => {
26390
26362
  const id = counter.next++;
26391
- return new Promise((resolve12, reject) => {
26392
- pending.set(id, { method, resolve: resolve12, reject });
26363
+ return new Promise((resolve13, reject) => {
26364
+ pending.set(id, { method, resolve: resolve13, reject });
26393
26365
  writer.write({ id, method, params }).catch((error61) => {
26394
26366
  pending.delete(id);
26395
26367
  reject(error61 instanceof Error ? error61 : new Error(String(error61)));
@@ -26502,7 +26474,7 @@ function createNdjsonWriter(stream) {
26502
26474
  get writable() {
26503
26475
  return stream.writable && !stream.destroyed && failure6.error === void 0;
26504
26476
  },
26505
- write: (value2) => new Promise((resolve12, reject) => {
26477
+ write: (value2) => new Promise((resolve13, reject) => {
26506
26478
  if (failure6.error) {
26507
26479
  reject(failure6.error);
26508
26480
  return;
@@ -26514,7 +26486,7 @@ function createNdjsonWriter(stream) {
26514
26486
  stream.write(`${JSON.stringify(value2)}
26515
26487
  `, (error61) => {
26516
26488
  if (error61) reject(error61);
26517
- else resolve12();
26489
+ else resolve13();
26518
26490
  });
26519
26491
  }),
26520
26492
  end: () => {
@@ -26530,11 +26502,11 @@ function hostProcess(child, tree, options, handlers) {
26530
26502
  const stderr = new LineSplitter((line) => handlers.onStderrLine(line));
26531
26503
  child.stderr.on("data", (chunk) => stderr.push(chunk));
26532
26504
  child.stderr.once("end", () => stderr.flush());
26533
- const processExit = new Promise((resolve12) => {
26534
- child.once("exit", (code, signal) => resolve12({ code, signal }));
26505
+ const processExit = new Promise((resolve13) => {
26506
+ child.once("exit", (code, signal) => resolve13({ code, signal }));
26535
26507
  });
26536
- const outputEnded = new Promise((resolve12) => {
26537
- child.stdout.once("close", () => resolve12());
26508
+ const outputEnded = new Promise((resolve13) => {
26509
+ child.stdout.once("close", () => resolve13());
26538
26510
  });
26539
26511
  const watch = async () => {
26540
26512
  const { clock, stdoutDrainMs, log, name } = options;
@@ -26823,13 +26795,13 @@ var init_chunk_VMGVHPBB = __esm({
26823
26795
  const turnId = input2.turnId;
26824
26796
  let finish = () => {
26825
26797
  };
26826
- const done = new Promise((resolve12) => {
26798
+ const done = new Promise((resolve13) => {
26827
26799
  finish = (outcome2) => {
26828
26800
  if (this.#current?.id !== turnId) return;
26829
26801
  this.#current = void 0;
26830
26802
  if (this.#state === "busy") this.#state = "idle";
26831
26803
  this.#emit({ type: "turn_ended", turnId, outcome: outcome2 });
26832
- resolve12({ turnId, outcome: outcome2, providerSessionId: this.#sessionId });
26804
+ resolve13({ turnId, outcome: outcome2, providerSessionId: this.#sessionId });
26833
26805
  };
26834
26806
  });
26835
26807
  const pending = {
@@ -27057,7 +27029,7 @@ var init_chunk_J2KTV5FP = __esm({
27057
27029
  }
27058
27030
  });
27059
27031
 
27060
- // ../agent-core/dist/chunk-ITTV3UIM.js
27032
+ // ../agent-core/dist/chunk-VX6QVMKD.js
27061
27033
  function truncate(value2, limit) {
27062
27034
  const normalized2 = Array.from(value2, (character) => {
27063
27035
  const code = character.charCodeAt(0);
@@ -27146,7 +27118,7 @@ function currentUserSection(user, visibility) {
27146
27118
  if (user.name) lines2.push(`- **Name**: ${user.name}`);
27147
27119
  lines2.push(`- **Email**: ${user.email}`, `- **User ID**: ${user.id}`, "");
27148
27120
  lines2.push(
27149
- visibility === "team" ? "This session is shared with the team. When creating tasks or assigning work, create them on this team. The person above started the session." : visibility === "private" ? "This session is private to this person. When creating tasks or assigning work, default to assigning to this user unless explicitly instructed otherwise." : "This is the person who initiated this conversation. When creating tasks or assigning work, default to assigning to this user unless explicitly instructed otherwise."
27121
+ visibility === "team" ? "This session is shared with the team. The person above sent the current request. When creating tasks or assigning work, create them on this team." : visibility === "private" ? "This session is private to this person. When creating tasks or assigning work, default to assigning to this user unless explicitly instructed otherwise." : "This is the person who initiated this conversation. When creating tasks or assigning work, default to assigning to this user unless explicitly instructed otherwise."
27150
27122
  );
27151
27123
  return lines2.join("\n");
27152
27124
  }
@@ -27418,8 +27390,8 @@ ${body}` : body;
27418
27390
  return spec.mode === "plan" ? planModePrefix(prefixed) : prefixed;
27419
27391
  }
27420
27392
  var MAX_PARSED_ATTACHMENTS, MAX_PARSED_ATTACHMENT_CHARS, MAX_METADATA_CHARS, UNAVAILABLE, READ_ONLY_MODES, AGENT_MODES;
27421
- var init_chunk_ITTV3UIM = __esm({
27422
- "../agent-core/dist/chunk-ITTV3UIM.js"() {
27393
+ var init_chunk_VX6QVMKD = __esm({
27394
+ "../agent-core/dist/chunk-VX6QVMKD.js"() {
27423
27395
  "use strict";
27424
27396
  init_agent2();
27425
27397
  MAX_PARSED_ATTACHMENTS = 3;
@@ -27535,6 +27507,7 @@ function buildClaudeArgs(input2) {
27535
27507
  ...capabilities.supportsThinkingDisplay ? ["--thinking-display", "summarized"] : [],
27536
27508
  // Without it the whole answer lands in one frame at turn end.
27537
27509
  ...capabilities.supportsPartialMessages ? ["--include-partial-messages"] : [],
27510
+ ...capabilities.supportsPluginDir ? (input2.pluginDirs ?? []).flatMap((dir) => ["--plugin-dir", dir]) : [],
27538
27511
  ...option("--resume", input2.resumeId),
27539
27512
  "--chrome",
27540
27513
  ...input2.extraArgs ?? []
@@ -27547,18 +27520,21 @@ function createClaudeCapabilityProbe(probe = createFlagProbe()) {
27547
27520
  supportsApproveMcps,
27548
27521
  supportsThinkingDisplay,
27549
27522
  supportsPartialMessages,
27550
- supportsReplayUserMessages
27523
+ supportsReplayUserMessages,
27524
+ supportsPluginDir
27551
27525
  ] = await Promise.all([
27552
27526
  needsApproveMcps ? probe.supportsFlag(command, "--approve-mcps", env) : false,
27553
27527
  probe.supportsHiddenChoiceFlag(command, "--thinking-display", env),
27554
27528
  probe.supportsFlag(command, "--include-partial-messages", env),
27555
- probe.supportsFlag(command, "--replay-user-messages", env)
27529
+ probe.supportsFlag(command, "--replay-user-messages", env),
27530
+ probe.supportsFlag(command, "--plugin-dir", env)
27556
27531
  ]);
27557
27532
  return {
27558
27533
  supportsApproveMcps,
27559
27534
  supportsThinkingDisplay,
27560
27535
  supportsPartialMessages,
27561
- supportsReplayUserMessages
27536
+ supportsReplayUserMessages,
27537
+ supportsPluginDir
27562
27538
  };
27563
27539
  }
27564
27540
  };
@@ -28446,6 +28422,7 @@ function planClaudeSession(run2, context) {
28446
28422
  ...run2.selectedEffortLevel === void 0 ? {} : { effortLevel: run2.selectedEffortLevel },
28447
28423
  ...prompts.systemPrompt === void 0 ? {} : { systemPrompt: prompts.systemPrompt },
28448
28424
  ...prompts.systemPromptAppend === void 0 ? {} : { appendSystemPrompt: prompts.systemPromptAppend },
28425
+ ...context.pluginDirs?.length ? { pluginDirs: context.pluginDirs } : {},
28449
28426
  ...context.managedMcp === void 0 ? {} : {
28450
28427
  mcp: {
28451
28428
  alanMcpUrl: context.managedMcp.url,
@@ -28694,7 +28671,7 @@ var init_claude = __esm({
28694
28671
  init_chunk_54ZRJOQP();
28695
28672
  init_chunk_J2KTV5FP();
28696
28673
  init_chunk_M6YHY2EZ();
28697
- init_chunk_ITTV3UIM();
28674
+ init_chunk_VX6QVMKD();
28698
28675
  init_chunk_YXWJW7I5();
28699
28676
  init_effort();
28700
28677
  import_crypto6 = require("crypto");
@@ -29417,8 +29394,8 @@ var init_claude = __esm({
29417
29394
  }
29418
29395
  async #awaitTaskStop(requestId, taskId) {
29419
29396
  const timer = new AbortController();
29420
- const answered = new Promise((resolve12) => {
29421
- this.#taskStops.set(requestId, resolve12);
29397
+ const answered = new Promise((resolve13) => {
29398
+ this.#taskStops.set(requestId, resolve13);
29422
29399
  });
29423
29400
  const timeoutMs = this.#options.stopTaskTimeoutMs;
29424
29401
  const timedOut = this.#options.clock.sleep(timeoutMs, timer.signal).then(
@@ -29491,17 +29468,17 @@ var init_claude = __esm({
29491
29468
  };
29492
29469
  let markStarted = () => {
29493
29470
  };
29494
- const whenStarted = new Promise((resolve12) => {
29495
- markStarted = resolve12;
29471
+ const whenStarted = new Promise((resolve13) => {
29472
+ markStarted = resolve13;
29496
29473
  });
29497
- const done = new Promise((resolve12) => {
29474
+ const done = new Promise((resolve13) => {
29498
29475
  finish = (outcome2) => {
29499
29476
  if (this.#current?.id !== id) return;
29500
29477
  this.#current = void 0;
29501
29478
  this.#lastTurn = turn;
29502
29479
  if (this.#state === "busy") this.#state = "idle";
29503
29480
  this.#emit({ type: "turn_ended", turnId: id, outcome: outcome2 });
29504
- resolve12({ turnId: id, outcome: outcome2, providerSessionId: this.#providerSessionId });
29481
+ resolve13({ turnId: id, outcome: outcome2, providerSessionId: this.#providerSessionId });
29505
29482
  };
29506
29483
  });
29507
29484
  const active = {
@@ -29619,8 +29596,8 @@ var init_claude = __esm({
29619
29596
  void removeLaunchFiles(this.#launchFiles).catch((error61) => {
29620
29597
  this.#options.log.warn("claude.launch_files_cleanup_failed", { error: error61 });
29621
29598
  });
29622
- for (const resolve12 of this.#taskStops.values()) {
29623
- resolve12({ ok: false, reason: "runtime_unavailable", message: "Claude Code exited." });
29599
+ for (const resolve13 of this.#taskStops.values()) {
29600
+ resolve13({ ok: false, reason: "runtime_unavailable", message: "Claude Code exited." });
29624
29601
  }
29625
29602
  const active = this.#current;
29626
29603
  if (active) {
@@ -31482,7 +31459,7 @@ var init_codex = __esm({
31482
31459
  init_chunk_54ZRJOQP();
31483
31460
  init_chunk_J2KTV5FP();
31484
31461
  init_chunk_M6YHY2EZ();
31485
- init_chunk_ITTV3UIM();
31462
+ init_chunk_VX6QVMKD();
31486
31463
  init_chunk_YXWJW7I5();
31487
31464
  import_fs6 = require("fs");
31488
31465
  import_path6 = require("path");
@@ -32101,10 +32078,10 @@ var init_codex = __esm({
32101
32078
  };
32102
32079
  let identify = () => {
32103
32080
  };
32104
- const identified = new Promise((resolve12) => {
32105
- identify = resolve12;
32081
+ const identified = new Promise((resolve13) => {
32082
+ identify = resolve13;
32106
32083
  });
32107
- const done = new Promise((resolve12) => {
32084
+ const done = new Promise((resolve13) => {
32108
32085
  finish = (outcome2) => {
32109
32086
  if (this.#current?.id !== id) return;
32110
32087
  this.#current = void 0;
@@ -32112,7 +32089,7 @@ var init_codex = __esm({
32112
32089
  if (this.#state === "busy") this.#state = "idle";
32113
32090
  this.#host.scanDescendants(true);
32114
32091
  this.#emit({ type: "turn_ended", turnId: id, outcome: outcome2 });
32115
- resolve12({ turnId: id, outcome: outcome2, providerSessionId: this.#threadId });
32092
+ resolve13({ turnId: id, outcome: outcome2, providerSessionId: this.#threadId });
32116
32093
  };
32117
32094
  });
32118
32095
  const active = {
@@ -32625,6 +32602,11 @@ function alanCodeConfigContent(existing, input2) {
32625
32602
  return JSON.stringify({
32626
32603
  $schema: "https://opencode.ai/config.json",
32627
32604
  ...config2,
32605
+ // OpenCode writes a whole working-tree diff into every user message summary and re-persists
32606
+ // the message on each update, so a large diff lands in the shared store many times over:
32607
+ // 3.4 GB of a dev machine's engine database was these patches, against 82 sessions. Alan
32608
+ // does not use the engine's undo/revert, so the tracking stays off.
32609
+ snapshot: false,
32628
32610
  model: `${ALAN_CODE_ENGINE_PROVIDER_ID}/${input2.modelId}`,
32629
32611
  enabled_providers: [ALAN_CODE_ENGINE_PROVIDER_ID],
32630
32612
  provider: {
@@ -32650,7 +32632,7 @@ function alanCodeConfigContent(existing, input2) {
32650
32632
  });
32651
32633
  }
32652
32634
  function readBody2(response) {
32653
- return new Promise((resolve12, reject) => {
32635
+ return new Promise((resolve13, reject) => {
32654
32636
  const chunks = [];
32655
32637
  let size = 0;
32656
32638
  response.on("data", (chunk) => {
@@ -32658,7 +32640,7 @@ function readBody2(response) {
32658
32640
  if (size > MAX_CATALOG_BYTES) response.destroy(new Error("catalog too large"));
32659
32641
  else chunks.push(chunk);
32660
32642
  });
32661
- response.on("end", () => resolve12(Buffer.concat(chunks).toString("utf8")));
32643
+ response.on("end", () => resolve13(Buffer.concat(chunks).toString("utf8")));
32662
32644
  response.on("error", reject);
32663
32645
  });
32664
32646
  }
@@ -32674,13 +32656,13 @@ function parseResponseBody(text2, status) {
32674
32656
  }
32675
32657
  function getJson(url3, headers, timeout, signal) {
32676
32658
  const request2 = url3.protocol === "https:" ? import_https.request : import_http9.request;
32677
- return new Promise((resolve12, reject) => {
32659
+ return new Promise((resolve13, reject) => {
32678
32660
  const outgoing = request2(url3, { method: "GET", headers, timeout, signal }, (response) => {
32679
32661
  const status = response.statusCode ?? 0;
32680
32662
  readBody2(response).then((text2) => {
32681
32663
  const body = parseResponseBody(text2, status);
32682
32664
  if (status < 200 || status >= 300) reject(new CatalogResponseError(status, body));
32683
- else resolve12(body);
32665
+ else resolve13(body);
32684
32666
  }).catch(reject);
32685
32667
  });
32686
32668
  outgoing.on("timeout", () => outgoing.destroy(new Error("catalog timed out")));
@@ -41556,8 +41538,8 @@ var require_streamx = __commonJS({
41556
41538
  return this;
41557
41539
  },
41558
41540
  next() {
41559
- return new Promise(function(resolve12, reject) {
41560
- promiseResolve = resolve12;
41541
+ return new Promise(function(resolve13, reject) {
41542
+ promiseResolve = resolve13;
41561
41543
  promiseReject = reject;
41562
41544
  const data = stream.read();
41563
41545
  if (data !== null) ondata(data);
@@ -41590,11 +41572,11 @@ var require_streamx = __commonJS({
41590
41572
  }
41591
41573
  function destroy(err) {
41592
41574
  stream.destroy(err);
41593
- return new Promise((resolve12, reject) => {
41594
- if (stream._duplexState & DESTROYED) return resolve12({ value: void 0, done: true });
41575
+ return new Promise((resolve13, reject) => {
41576
+ if (stream._duplexState & DESTROYED) return resolve13({ value: void 0, done: true });
41595
41577
  stream.once("close", function() {
41596
41578
  if (err) reject(err);
41597
- else resolve12({ value: void 0, done: true });
41579
+ else resolve13({ value: void 0, done: true });
41598
41580
  });
41599
41581
  });
41600
41582
  }
@@ -41638,8 +41620,8 @@ var require_streamx = __commonJS({
41638
41620
  const writes = pending + (ws._duplexState & WRITE_WRITING ? 1 : 0);
41639
41621
  if (writes === 0) return Promise.resolve(true);
41640
41622
  if (state.drains === null) state.drains = [];
41641
- return new Promise((resolve12) => {
41642
- state.drains.push({ writes, resolve: resolve12 });
41623
+ return new Promise((resolve13) => {
41624
+ state.drains.push({ writes, resolve: resolve13 });
41643
41625
  });
41644
41626
  }
41645
41627
  write(data) {
@@ -41744,10 +41726,10 @@ var require_streamx = __commonJS({
41744
41726
  cb(null);
41745
41727
  }
41746
41728
  function pipelinePromise(...streams) {
41747
- return new Promise((resolve12, reject) => {
41729
+ return new Promise((resolve13, reject) => {
41748
41730
  return pipeline(...streams, (err) => {
41749
41731
  if (err) return reject(err);
41750
- resolve12();
41732
+ resolve13();
41751
41733
  });
41752
41734
  });
41753
41735
  }
@@ -42419,16 +42401,16 @@ var require_extract = __commonJS({
42419
42401
  entryCallback = null;
42420
42402
  cb(err);
42421
42403
  }
42422
- function onnext(resolve12, reject) {
42404
+ function onnext(resolve13, reject) {
42423
42405
  if (error61) {
42424
42406
  return reject(error61);
42425
42407
  }
42426
42408
  if (entryStream) {
42427
- resolve12({ value: entryStream, done: false });
42409
+ resolve13({ value: entryStream, done: false });
42428
42410
  entryStream = null;
42429
42411
  return;
42430
42412
  }
42431
- promiseResolve = resolve12;
42413
+ promiseResolve = resolve13;
42432
42414
  promiseReject = reject;
42433
42415
  consumeCallback(null);
42434
42416
  if (extract2._finished && promiseResolve) {
@@ -42456,11 +42438,11 @@ var require_extract = __commonJS({
42456
42438
  function destroy(err) {
42457
42439
  extract2.destroy(err);
42458
42440
  consumeCallback(err);
42459
- return new Promise((resolve12, reject) => {
42460
- if (extract2.destroyed) return resolve12({ value: void 0, done: true });
42441
+ return new Promise((resolve13, reject) => {
42442
+ if (extract2.destroyed) return resolve13({ value: void 0, done: true });
42461
42443
  extract2.once("close", function() {
42462
42444
  if (err) reject(err);
42463
- else resolve12({ value: void 0, done: true });
42445
+ else resolve13({ value: void 0, done: true });
42464
42446
  });
42465
42447
  });
42466
42448
  }
@@ -42842,7 +42824,7 @@ function within(root, path4) {
42842
42824
  }
42843
42825
  async function resolveReal(path4) {
42844
42826
  try {
42845
- return await (0, import_promises48.realpath)(path4);
42827
+ return await (0, import_promises49.realpath)(path4);
42846
42828
  } catch {
42847
42829
  const parent = (0, import_path9.dirname)(path4);
42848
42830
  if (parent === path4) return path4;
@@ -42871,14 +42853,14 @@ function createWorkspaceFs(roots, writable) {
42871
42853
  return {
42872
42854
  read: async (params) => {
42873
42855
  const path4 = await confined(params);
42874
- const bytes = await (0, import_promises48.readFile)(path4);
42856
+ const bytes = await (0, import_promises49.readFile)(path4);
42875
42857
  if (bytes.byteLength > MAX_READ_BYTES) throw new FsDenied(`${path4} is too large to read`);
42876
42858
  return { content: sliceLines(bytes.toString("utf8"), params) };
42877
42859
  },
42878
42860
  write: async (params) => {
42879
42861
  if (!writable) throw new FsDenied("This session is read-only");
42880
42862
  const path4 = await confined(params);
42881
- await (0, import_promises48.writeFile)(path4, asString(params.content));
42863
+ await (0, import_promises49.writeFile)(path4, asString(params.content));
42882
42864
  return {};
42883
42865
  }
42884
42866
  };
@@ -43481,7 +43463,7 @@ async function acpTurnInput(run2, context) {
43481
43463
  const encoded = await Promise.all(
43482
43464
  images.map(async (image) => ({
43483
43465
  mimeType: image.mimeType,
43484
- data: (await (0, import_promises49.readFile)(image.path)).toString("base64")
43466
+ data: (await (0, import_promises50.readFile)(image.path)).toString("base64")
43485
43467
  }))
43486
43468
  );
43487
43469
  return {
@@ -43490,7 +43472,7 @@ async function acpTurnInput(run2, context) {
43490
43472
  ...encoded.length ? { images: encoded, imagePaths: images.map((image) => image.path) } : {}
43491
43473
  };
43492
43474
  }
43493
- var import_promises48, import_path9, import_crypto12, import_promises49, CURSOR_ASK_QUESTION, copilotAcpProfile, cursorAcpProfile, MODEL_REJECTED, MAX_READ_BYTES, FsDenied, ENV_REFERENCE, AcpBackgroundTasks, CURSOR_CREATE_PLAN, STATUSES2, READ_KINDS, ALLOW_KINDS, REJECT_KINDS, CANCELLED_PERMISSION, STOP_REASONS, CHUNKS, ECHOES, AcpTurn, STDERR_TAIL_LINES4, MAX_BETWEEN_UPDATES2, AcpSession, DEFAULTS3, CLIENT_INFO2, TASK_BACKGROUNDED, TASK_COMPLETED, SESSION_NOTIFICATION, KILLED_STATUSES, SUCCESS_STATUSES, SUBAGENT_ID, grokTaskDialect, grokAcpProfile, kimiAcpProfile, ACP_PROFILES, ACP_MODES;
43475
+ var import_promises49, import_path9, import_crypto12, import_promises50, CURSOR_ASK_QUESTION, copilotAcpProfile, cursorAcpProfile, MODEL_REJECTED, MAX_READ_BYTES, FsDenied, ENV_REFERENCE, AcpBackgroundTasks, CURSOR_CREATE_PLAN, STATUSES2, READ_KINDS, ALLOW_KINDS, REJECT_KINDS, CANCELLED_PERMISSION, STOP_REASONS, CHUNKS, ECHOES, AcpTurn, STDERR_TAIL_LINES4, MAX_BETWEEN_UPDATES2, AcpSession, DEFAULTS3, CLIENT_INFO2, TASK_BACKGROUNDED, TASK_COMPLETED, SESSION_NOTIFICATION, KILLED_STATUSES, SUCCESS_STATUSES, SUBAGENT_ID, grokTaskDialect, grokAcpProfile, kimiAcpProfile, ACP_PROFILES, ACP_MODES;
43494
43476
  var init_acp3 = __esm({
43495
43477
  "../agent-core/dist/providers/acp.js"() {
43496
43478
  "use strict";
@@ -43499,14 +43481,14 @@ var init_acp3 = __esm({
43499
43481
  init_chunk_54ZRJOQP();
43500
43482
  init_chunk_J2KTV5FP();
43501
43483
  init_chunk_M6YHY2EZ();
43502
- init_chunk_ITTV3UIM();
43484
+ init_chunk_VX6QVMKD();
43503
43485
  init_chunk_YXWJW7I5();
43504
- import_promises48 = require("fs/promises");
43486
+ import_promises49 = require("fs/promises");
43505
43487
  import_path9 = require("path");
43506
43488
  init_effort();
43507
43489
  init_acp();
43508
43490
  import_crypto12 = require("crypto");
43509
- import_promises49 = require("fs/promises");
43491
+ import_promises50 = require("fs/promises");
43510
43492
  init_agent2();
43511
43493
  CURSOR_ASK_QUESTION = "cursor/ask_question";
43512
43494
  copilotAcpProfile = {
@@ -44022,7 +44004,7 @@ var init_acp3 = __esm({
44022
44004
  const turn = new AcpTurn(`acp-${this.#turns}-${id}`, this.#profile);
44023
44005
  let finish = () => {
44024
44006
  };
44025
- const done = new Promise((resolve12) => {
44007
+ const done = new Promise((resolve13) => {
44026
44008
  finish = (outcome2) => {
44027
44009
  if (this.#current?.id !== id) return;
44028
44010
  this.#current = void 0;
@@ -44030,7 +44012,7 @@ var init_acp3 = __esm({
44030
44012
  if (this.#state === "busy") this.#state = "idle";
44031
44013
  this.#host.scanDescendants(true);
44032
44014
  this.#emit({ type: "turn_ended", turnId: id, outcome: outcome2 });
44033
- resolve12({ turnId: id, outcome: outcome2, providerSessionId: this.#sessionId });
44015
+ resolve13({ turnId: id, outcome: outcome2, providerSessionId: this.#sessionId });
44034
44016
  };
44035
44017
  });
44036
44018
  const active = { id, turn, done, finish, cancelRequested: false };
@@ -44726,10 +44708,14 @@ function openCodeConfigContent(input2) {
44726
44708
  enabled: true
44727
44709
  };
44728
44710
  }
44711
+ const skills = asRecord(config2.skills) ?? {};
44712
+ const ownPaths = Array.isArray(skills.paths) ? skills.paths : [];
44713
+ const skillPaths = input2.skillPaths ?? [];
44729
44714
  return JSON.stringify({
44730
44715
  ...config2,
44731
44716
  ...input2.readOnly ? {} : { permission: "allow" },
44732
- ...Object.keys(mcp).length ? { mcp } : {}
44717
+ ...Object.keys(mcp).length ? { mcp } : {},
44718
+ ...skillPaths.length ? { skills: { ...skills, paths: [...ownPaths, ...skillPaths] } } : {}
44733
44719
  });
44734
44720
  }
44735
44721
  function storedParts(message2) {
@@ -45024,7 +45010,7 @@ async function sameDirectory(left, right) {
45024
45010
  }
45025
45011
  async function canonicalDirectory(directory) {
45026
45012
  try {
45027
- return await (0, import_promises50.realpath)(directory);
45013
+ return await (0, import_promises51.realpath)(directory);
45028
45014
  } catch {
45029
45015
  return (0, import_path10.resolve)(directory);
45030
45016
  }
@@ -45049,6 +45035,57 @@ async function openSession(session, client, spec, log) {
45049
45035
  const id = await client.createSession({ title: spec.title, permission: NON_INTERACTIVE_RULES });
45050
45036
  return { id, resumed: false };
45051
45037
  }
45038
+ function isOpenTimeout(error61) {
45039
+ return error61 instanceof CoreFault && error61.code === "protocol_violation";
45040
+ }
45041
+ async function openOnce(spec, password, options) {
45042
+ const attempt2 = { abandoned: false };
45043
+ const { session, url: url3 } = await withDeadline3(
45044
+ startServer(spec, password, options, attempt2),
45045
+ options.clock,
45046
+ options.openTimeoutMs,
45047
+ "report a listening URL"
45048
+ ).catch(async (error61) => {
45049
+ attempt2.abandoned = true;
45050
+ await attempt2.current?.suspend().catch(() => void 0);
45051
+ throw error61;
45052
+ });
45053
+ try {
45054
+ const client = new OpenCodeClient(url3, password, options.engine.label);
45055
+ const opened = await withDeadline3(
45056
+ openSession(session, client, spec, options.log),
45057
+ options.clock,
45058
+ options.openTimeoutMs,
45059
+ "open a session"
45060
+ );
45061
+ session.attach(
45062
+ opened.id,
45063
+ spec.prompt,
45064
+ expiredSignInNotices(spec.env, options.clock.now()),
45065
+ opened.resumed
45066
+ );
45067
+ } catch (error61) {
45068
+ await session.suspend().catch(() => void 0);
45069
+ throw error61;
45070
+ }
45071
+ options.log.info("opencode.opened", {
45072
+ pid: session.pid,
45073
+ sessionId: session.providerSessionId,
45074
+ resumeFailed: session.resumeFailed
45075
+ });
45076
+ return session;
45077
+ }
45078
+ async function openWithRetries(spec, password, options) {
45079
+ for (let tries = 1; ; tries += 1) {
45080
+ try {
45081
+ return await openOnce(spec, password, options);
45082
+ } catch (error61) {
45083
+ if (!isOpenTimeout(error61) || tries >= options.openAttempts) throw error61;
45084
+ options.log.warn("opencode.open_retry", { tries });
45085
+ await options.clock.sleep(options.reconnectDelayMs);
45086
+ }
45087
+ }
45088
+ }
45052
45089
  function createOpenCodeDriver(options = {}) {
45053
45090
  const resolved = {
45054
45091
  clock: options.clock ?? systemClock2,
@@ -45058,6 +45095,7 @@ function createOpenCodeDriver(options = {}) {
45058
45095
  stdoutDrainMs: options.stdoutDrainMs ?? DEFAULTS4.stdoutDrainMs,
45059
45096
  descendantScanMs: options.descendantScanMs ?? DEFAULTS4.descendantScanMs,
45060
45097
  openTimeoutMs: options.openTimeoutMs ?? DEFAULTS4.openTimeoutMs,
45098
+ openAttempts: options.openAttempts ?? DEFAULTS4.openAttempts,
45061
45099
  startAttempts: options.startAttempts ?? DEFAULTS4.startAttempts,
45062
45100
  reconnectAttempts: options.reconnectAttempts ?? DEFAULTS4.reconnectAttempts,
45063
45101
  reconnectDelayMs: options.reconnectDelayMs ?? DEFAULTS4.reconnectDelayMs,
@@ -45073,45 +45111,16 @@ function createOpenCodeDriver(options = {}) {
45073
45111
  };
45074
45112
  const spec = { ...planned, env: launchEnv(planned, authorization) };
45075
45113
  const password = options.password?.() ?? (0, import_crypto13.randomBytes)(24).toString("base64url");
45076
- const attempt2 = { abandoned: false };
45077
- const { session, url: url3 } = await withDeadline3(
45078
- startServer(spec, password, resolved, attempt2),
45079
- resolved.clock,
45080
- resolved.openTimeoutMs,
45081
- "report a listening URL"
45082
- ).catch(async (error61) => {
45083
- attempt2.abandoned = true;
45084
- await attempt2.current?.suspend().catch(() => void 0);
45085
- await removeAuthorization();
45086
- throw error61;
45087
- });
45088
- void session.exited.then(removeAuthorization).catch((error61) => {
45089
- resolved.log.warn("opencode.authorization_cleanup_failed", { error: error61 });
45090
- });
45091
45114
  try {
45092
- const client = new OpenCodeClient(url3, password, resolved.engine.label);
45093
- const opened = await withDeadline3(
45094
- openSession(session, client, spec, resolved.log),
45095
- resolved.clock,
45096
- resolved.openTimeoutMs,
45097
- "open a session"
45098
- );
45099
- session.attach(
45100
- opened.id,
45101
- spec.prompt,
45102
- expiredSignInNotices(spec.env, resolved.clock.now()),
45103
- opened.resumed
45104
- );
45115
+ const session = await openWithRetries(spec, password, resolved);
45116
+ void session.exited.then(removeAuthorization).catch((error61) => {
45117
+ resolved.log.warn("opencode.authorization_cleanup_failed", { error: error61 });
45118
+ });
45119
+ return session;
45105
45120
  } catch (error61) {
45106
- await session.suspend().catch(() => void 0);
45121
+ await removeAuthorization();
45107
45122
  throw error61;
45108
45123
  }
45109
- resolved.log.info("opencode.opened", {
45110
- pid: session.pid,
45111
- sessionId: session.providerSessionId,
45112
- resumeFailed: session.resumeFailed
45113
- });
45114
- return session;
45115
45124
  }
45116
45125
  };
45117
45126
  }
@@ -45144,6 +45153,7 @@ function planOpenCodeSession(run2, context) {
45144
45153
  const config2 = {
45145
45154
  existing: baseEnv[OPENCODE_CONFIG_ENV],
45146
45155
  readOnly,
45156
+ ...context.skillPaths?.length ? { skillPaths: context.skillPaths } : {},
45147
45157
  mcp: {
45148
45158
  conversationId: run2.conversationId,
45149
45159
  externalServers: mcp.servers,
@@ -45196,7 +45206,7 @@ function openCodeTurnInput(run2, context) {
45196
45206
  ...images.length ? { imagePaths: images.map((image) => image.path) } : {}
45197
45207
  };
45198
45208
  }
45199
- var import_http10, import_crypto13, import_promises50, import_path10, import_path11, import_url2, import_crypto14, IDLE_SOCKET_MS3, OpenCodeHttpError, OpenCodeClient, OPENCODE_CONFIG_ENV, OPENCODE_ENGINE, TEXT_PARTS, STEP_PARTS, STOPPED_BY_USER, OpenCodeSubagents, NAMED_KINDS, OPENCODE_ABORTED_ERROR, PROVIDER_EVENT_META, TASK_TOOL_NAME, TASK_RESULT_TAG, TASK_ERROR_TAG, PERMISSION_DENIED, FILE_OPERATIONS2, PartReader, NOTHING, NON_INTERACTIVE_PERMISSIONS, CONTENT_FILTER_FINISHES, OUTPUT_PARTS, OpenCodeTurn, LISTENING, OUTPUT_TAIL_LINES, IMAGE_TYPES, OpenCodeSession, OPENCODE_MIN_VERSION, OPENCODE_REQUIREMENT, OPENCODE_TESTED_LINE, OPENCODE_SUPPORTED_MAJOR, DEFAULTS4, STORE_LOCKED, NON_INTERACTIVE_RULES, TITLE_LENGTH, MAX_VARIANT_LENGTH;
45209
+ var import_http10, import_crypto13, import_promises51, import_path10, import_path11, import_url2, import_crypto14, IDLE_SOCKET_MS3, OpenCodeHttpError, OpenCodeClient, OPENCODE_CONFIG_ENV, OPENCODE_ENGINE, TEXT_PARTS, STEP_PARTS, STOPPED_BY_USER, OpenCodeSubagents, NAMED_KINDS, OPENCODE_ABORTED_ERROR, PROVIDER_EVENT_META, TASK_TOOL_NAME, TASK_RESULT_TAG, TASK_ERROR_TAG, PERMISSION_DENIED, FILE_OPERATIONS2, PartReader, NOTHING, NON_INTERACTIVE_PERMISSIONS, CONTENT_FILTER_FINISHES, OUTPUT_PARTS, OpenCodeTurn, LISTENING, OUTPUT_TAIL_LINES, IMAGE_TYPES, OpenCodeSession, OPENCODE_MIN_VERSION, OPENCODE_REQUIREMENT, OPENCODE_TESTED_LINE, OPENCODE_SUPPORTED_MAJOR, DEFAULTS4, STORE_LOCKED, NON_INTERACTIVE_RULES, TITLE_LENGTH, MAX_VARIANT_LENGTH;
45200
45210
  var init_opencode = __esm({
45201
45211
  "../agent-core/dist/providers/opencode.js"() {
45202
45212
  "use strict";
@@ -45205,12 +45215,12 @@ var init_opencode = __esm({
45205
45215
  init_chunk_54ZRJOQP();
45206
45216
  init_chunk_J2KTV5FP();
45207
45217
  init_chunk_M6YHY2EZ();
45208
- init_chunk_ITTV3UIM();
45218
+ init_chunk_VX6QVMKD();
45209
45219
  init_chunk_YXWJW7I5();
45210
45220
  import_http10 = require("http");
45211
45221
  init_runtime_v2();
45212
45222
  import_crypto13 = require("crypto");
45213
- import_promises50 = require("fs/promises");
45223
+ import_promises51 = require("fs/promises");
45214
45224
  import_path10 = require("path");
45215
45225
  init_agent2();
45216
45226
  import_path11 = require("path");
@@ -46296,6 +46306,7 @@ var init_opencode = __esm({
46296
46306
  stdoutDrainMs: 2e3,
46297
46307
  descendantScanMs: 5e3,
46298
46308
  openTimeoutMs: 6e4,
46309
+ openAttempts: 2,
46299
46310
  startAttempts: 3,
46300
46311
  reconnectAttempts: 3,
46301
46312
  reconnectDelayMs: 500,
@@ -46374,6 +46385,7 @@ function createAlanCodeHolderDriver(options) {
46374
46385
  engineRoot,
46375
46386
  requestedModel: spec.model
46376
46387
  };
46388
+ const skills = options.installedSkills?.() ?? null;
46377
46389
  const planned = planOpenCodeSession(spec, {
46378
46390
  command: engine.command,
46379
46391
  cwd: spec.projectPath ?? options.defaultCwd,
@@ -46383,7 +46395,8 @@ function createAlanCodeHolderDriver(options) {
46383
46395
  },
46384
46396
  providerEnv: inputs.providerEnv,
46385
46397
  ...managedMcp === void 0 ? {} : { managedMcp },
46386
- ...resumeId === void 0 ? {} : { resumeSessionId: resumeId }
46398
+ ...resumeId === void 0 ? {} : { resumeSessionId: resumeId },
46399
+ ...skills === null ? {} : { skillPaths: [skills.skillsDir] }
46387
46400
  });
46388
46401
  return {
46389
46402
  spec: { opencode: planned.spec, profile },
@@ -46434,14 +46447,18 @@ function createClaudeHolderDriver(options) {
46434
46447
  {
46435
46448
  harness: "claude_cli",
46436
46449
  displayName: "Claude CLI",
46437
- plan: (spec, inputs, resumeId, managedMcp) => planClaudeSession(spec, {
46438
- command: options.command ?? "claude",
46439
- cwd: spec.projectPath ?? options.defaultCwd,
46440
- cliEnv: options.cliEnvironment,
46441
- providerEnv: inputs.providerEnv,
46442
- ...managedMcp === void 0 ? {} : { managedMcp },
46443
- ...resumeId === void 0 ? {} : { resumeId }
46444
- }),
46450
+ plan: (spec, inputs, resumeId, managedMcp) => {
46451
+ const skills = options.installedSkills?.() ?? null;
46452
+ return planClaudeSession(spec, {
46453
+ command: options.command ?? "claude",
46454
+ cwd: spec.projectPath ?? options.defaultCwd,
46455
+ cliEnv: options.cliEnvironment,
46456
+ providerEnv: inputs.providerEnv,
46457
+ ...managedMcp === void 0 ? {} : { managedMcp },
46458
+ ...resumeId === void 0 ? {} : { resumeId },
46459
+ ...skills === null ? {} : { pluginDirs: [skills.pluginDir] }
46460
+ });
46461
+ },
46445
46462
  canResume: (planned, resumeId) => claudeSessionLogExists({
46446
46463
  sessionId: resumeId,
46447
46464
  cwd: planned.spec.cwd,
@@ -46478,7 +46495,7 @@ __export(codex_exports, {
46478
46495
  createCodexHolderDriver: () => createCodexHolderDriver
46479
46496
  });
46480
46497
  function sha2563(value2) {
46481
- return (0, import_node_crypto26.createHash)("sha256").update(value2).digest("hex");
46498
+ return (0, import_node_crypto27.createHash)("sha256").update(value2).digest("hex");
46482
46499
  }
46483
46500
  function createCodexLogin(broker) {
46484
46501
  const state = {};
@@ -46553,11 +46570,11 @@ function createCodexHolderDriver(options) {
46553
46570
  }
46554
46571
  );
46555
46572
  }
46556
- var import_node_crypto26;
46573
+ var import_node_crypto27;
46557
46574
  var init_codex2 = __esm({
46558
46575
  "src/holder/drivers/codex.ts"() {
46559
46576
  "use strict";
46560
- import_node_crypto26 = require("crypto");
46577
+ import_node_crypto27 = require("crypto");
46561
46578
  init_dist();
46562
46579
  init_codex();
46563
46580
  init_persistent();
@@ -46664,8 +46681,8 @@ function createDroidPeer(writer, handlers) {
46664
46681
  },
46665
46682
  request: (method, params = {}) => {
46666
46683
  const id = `alan-${counter.next++}`;
46667
- return new Promise((resolve12, reject) => {
46668
- pending.set(id, { method, resolve: resolve12, reject });
46684
+ return new Promise((resolve13, reject) => {
46685
+ pending.set(id, { method, resolve: resolve13, reject });
46669
46686
  writer.write(envelope("request", { id, method, params })).catch((error61) => {
46670
46687
  pending.delete(id);
46671
46688
  reject(error61 instanceof Error ? error61 : new Error(String(error61)));
@@ -47000,12 +47017,12 @@ async function droidTurnInput(run2, context) {
47000
47017
  const encoded = await Promise.all(
47001
47018
  images.map(async (image) => ({
47002
47019
  mimeType: image.mimeType,
47003
- data: (await (0, import_promises51.readFile)(image.path)).toString("base64")
47020
+ data: (await (0, import_promises52.readFile)(image.path)).toString("base64")
47004
47021
  }))
47005
47022
  );
47006
47023
  return { turnId: run2.runId, text: text2, ...encoded.length ? { images: encoded } : {} };
47007
47024
  }
47008
- var import_crypto15, import_promises51, 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;
47025
+ var import_crypto15, import_promises52, 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;
47009
47026
  var init_droid = __esm({
47010
47027
  "../agent-core/dist/providers/droid.js"() {
47011
47028
  "use strict";
@@ -47014,11 +47031,11 @@ var init_droid = __esm({
47014
47031
  init_chunk_54ZRJOQP();
47015
47032
  init_chunk_J2KTV5FP();
47016
47033
  init_chunk_M6YHY2EZ();
47017
- init_chunk_ITTV3UIM();
47034
+ init_chunk_VX6QVMKD();
47018
47035
  init_chunk_YXWJW7I5();
47019
47036
  init_runtime_v2();
47020
47037
  import_crypto15 = require("crypto");
47021
- import_promises51 = require("fs/promises");
47038
+ import_promises52 = require("fs/promises");
47022
47039
  init_agent2();
47023
47040
  FACTORY_API_VERSION = "1.0.0";
47024
47041
  FACTORY_PROTOCOL_VERSION = "1.187.0";
@@ -47290,14 +47307,14 @@ var init_droid = __esm({
47290
47307
  const turn = new DroidTurn(sessionId, this.#memory);
47291
47308
  let finish = () => {
47292
47309
  };
47293
- const done = new Promise((resolve12) => {
47310
+ const done = new Promise((resolve13) => {
47294
47311
  finish = (outcome2) => {
47295
47312
  if (this.#current?.id !== id) return;
47296
47313
  this.#current = void 0;
47297
47314
  if (this.#state === "busy") this.#state = "idle";
47298
47315
  this.#host.scanDescendants(true);
47299
47316
  this.#emit({ type: "turn_ended", turnId: id, outcome: outcome2 });
47300
- resolve12({ turnId: id, outcome: outcome2, providerSessionId: this.#sessionId });
47317
+ resolve13({ turnId: id, outcome: outcome2, providerSessionId: this.#sessionId });
47301
47318
  };
47302
47319
  });
47303
47320
  const active = { id, turn, done, finish, cancelRequested: false };
@@ -47445,14 +47462,18 @@ function createOpenCodeHolderDriver(options) {
47445
47462
  {
47446
47463
  harness: "opencode_serve",
47447
47464
  displayName: "OpenCode server",
47448
- plan: (spec, inputs, resumeId, managedMcp) => planOpenCodeSession(spec, {
47449
- command: options.command ?? "opencode",
47450
- cwd: spec.projectPath ?? options.defaultCwd,
47451
- cliEnv: options.cliEnvironment,
47452
- providerEnv: inputs.providerEnv,
47453
- ...managedMcp === void 0 ? {} : { managedMcp },
47454
- ...resumeId === void 0 ? {} : { resumeSessionId: resumeId }
47455
- }),
47465
+ plan: (spec, inputs, resumeId, managedMcp) => {
47466
+ const skills = options.installedSkills?.() ?? null;
47467
+ return planOpenCodeSession(spec, {
47468
+ command: options.command ?? "opencode",
47469
+ cwd: spec.projectPath ?? options.defaultCwd,
47470
+ cliEnv: options.cliEnvironment,
47471
+ providerEnv: inputs.providerEnv,
47472
+ ...managedMcp === void 0 ? {} : { managedMcp },
47473
+ ...resumeId === void 0 ? {} : { resumeSessionId: resumeId },
47474
+ ...skills === null ? {} : { skillPaths: [skills.skillsDir] }
47475
+ });
47476
+ },
47456
47477
  canResume: () => true,
47457
47478
  open: async (spec) => {
47458
47479
  const session = await sessions.open(spec);
@@ -47489,7 +47510,7 @@ function settingsPath(env) {
47489
47510
  async function readSettings2(path4) {
47490
47511
  let raw;
47491
47512
  try {
47492
- raw = (await (0, import_promises52.readFile)(path4, "utf8")).trim();
47513
+ raw = (await (0, import_promises53.readFile)(path4, "utf8")).trim();
47493
47514
  } catch {
47494
47515
  return {};
47495
47516
  }
@@ -47507,8 +47528,8 @@ async function selectAntigravityApiKeyMode(env) {
47507
47528
  const settings2 = await readSettings2(path4);
47508
47529
  if (settings2 === "malformed") return "malformed";
47509
47530
  if (settings2.modelProvider === "gemini") return "already_selected";
47510
- await (0, import_promises52.mkdir)((0, import_path12.dirname)(path4), { recursive: true });
47511
- await (0, import_promises52.writeFile)(path4, JSON.stringify({ ...settings2, modelProvider: "gemini" }), { mode: 384 });
47531
+ await (0, import_promises53.mkdir)((0, import_path12.dirname)(path4), { recursive: true });
47532
+ await (0, import_promises53.writeFile)(path4, JSON.stringify({ ...settings2, modelProvider: "gemini" }), { mode: 384 });
47512
47533
  return "selected";
47513
47534
  }
47514
47535
  function readAntigravityCapabilities(version2, help) {
@@ -48107,7 +48128,7 @@ function antigravityTurnInput(run2, context) {
48107
48128
  });
48108
48129
  return { turnId: run2.runId, text: appendImagePathReferences(text2, images) };
48109
48130
  }
48110
- var import_promises52, import_path12, import_fs8, import_path13, import_path14, 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;
48131
+ var import_promises53, import_path12, import_fs8, import_path13, import_path14, 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;
48111
48132
  var init_antigravity = __esm({
48112
48133
  "../agent-core/dist/providers/antigravity.js"() {
48113
48134
  "use strict";
@@ -48116,9 +48137,9 @@ var init_antigravity = __esm({
48116
48137
  init_chunk_XC5676SG();
48117
48138
  init_chunk_54ZRJOQP();
48118
48139
  init_chunk_M6YHY2EZ();
48119
- init_chunk_ITTV3UIM();
48140
+ init_chunk_VX6QVMKD();
48120
48141
  init_chunk_YXWJW7I5();
48121
- import_promises52 = require("fs/promises");
48142
+ import_promises53 = require("fs/promises");
48122
48143
  import_path12 = require("path");
48123
48144
  init_type_guards();
48124
48145
  import_fs8 = require("fs");
@@ -48618,7 +48639,7 @@ function parseConfig(raw) {
48618
48639
  }
48619
48640
  async function writeCommandCodeProjectMcp(cwd, mcp) {
48620
48641
  const path4 = (0, import_path15.join)(cwd, ".mcp.json");
48621
- const original = await (0, import_promises53.readFile)(path4, "utf8").catch(() => null);
48642
+ const original = await (0, import_promises54.readFile)(path4, "utf8").catch(() => null);
48622
48643
  const config2 = parseConfig(original);
48623
48644
  const next = {
48624
48645
  ...config2,
@@ -48635,12 +48656,12 @@ async function writeCommandCodeProjectMcp(cwd, mcp) {
48635
48656
  }
48636
48657
  }
48637
48658
  };
48638
- await (0, import_promises53.mkdir)(cwd, { recursive: true });
48639
- await (0, import_promises53.writeFile)(path4, `${JSON.stringify(next, null, 2)}
48659
+ await (0, import_promises54.mkdir)(cwd, { recursive: true });
48660
+ await (0, import_promises54.writeFile)(path4, `${JSON.stringify(next, null, 2)}
48640
48661
  `);
48641
48662
  return async () => {
48642
- if (original === null) await (0, import_promises53.rm)(path4, { force: true });
48643
- else await (0, import_promises53.writeFile)(path4, original);
48663
+ if (original === null) await (0, import_promises54.rm)(path4, { force: true });
48664
+ else await (0, import_promises54.writeFile)(path4, original);
48644
48665
  };
48645
48666
  }
48646
48667
  function commandCodeString(value2) {
@@ -48812,7 +48833,7 @@ function commandCodeTurnInput(run2, context) {
48812
48833
  });
48813
48834
  return { turnId: run2.runId, text: appendImagePathReferences(text2, images) };
48814
48835
  }
48815
- var import_promises53, import_path15, 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;
48836
+ var import_promises54, import_path15, 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;
48816
48837
  var init_command_code = __esm({
48817
48838
  "../agent-core/dist/providers/command-code.js"() {
48818
48839
  "use strict";
@@ -48821,9 +48842,9 @@ var init_command_code = __esm({
48821
48842
  init_chunk_54ZRJOQP();
48822
48843
  init_chunk_J2KTV5FP();
48823
48844
  init_chunk_M6YHY2EZ();
48824
- init_chunk_ITTV3UIM();
48845
+ init_chunk_VX6QVMKD();
48825
48846
  init_chunk_YXWJW7I5();
48826
- import_promises53 = require("fs/promises");
48847
+ import_promises54 = require("fs/promises");
48827
48848
  import_path15 = require("path");
48828
48849
  init_agent2();
48829
48850
  init_runtime_v2();
@@ -54219,7 +54240,7 @@ var require_websocket_server = __commonJS({
54219
54240
  // package.json
54220
54241
  var package_default = {
54221
54242
  name: "@alan-ai-hq/agent-manager",
54222
- version: "0.1.142",
54243
+ version: "0.1.144",
54223
54244
  private: true,
54224
54245
  type: "module",
54225
54246
  description: "Alan machine runtime (alan-agent): identity, link, reconciler, session holders, run log, uploader, local API",
@@ -54268,8 +54289,8 @@ var package_default = {
54268
54289
  };
54269
54290
 
54270
54291
  // src/cli/commands/compat.ts
54271
- var import_node_crypto31 = require("crypto");
54272
- var import_promises67 = require("fs/promises");
54292
+ var import_node_crypto32 = require("crypto");
54293
+ var import_promises68 = require("fs/promises");
54273
54294
  init_runtime_v2();
54274
54295
  init_zod();
54275
54296
 
@@ -54428,8 +54449,8 @@ async function writeJsonFileAtomic(path4, value2) {
54428
54449
  var LIFECYCLE_DRAIN_MS = 5e3;
54429
54450
  function createGate() {
54430
54451
  const opened = {};
54431
- const promise2 = new Promise((resolve12) => {
54432
- opened.resolve = resolve12;
54452
+ const promise2 = new Promise((resolve13) => {
54453
+ opened.resolve = resolve13;
54433
54454
  });
54434
54455
  return { promise: promise2, open: () => opened.resolve?.() };
54435
54456
  }
@@ -54656,7 +54677,7 @@ function transportFailure(request2, error61) {
54656
54677
  });
54657
54678
  }
54658
54679
  function readBody(incoming, url3, maxBytes) {
54659
- return new Promise((resolve12, reject) => {
54680
+ return new Promise((resolve13, reject) => {
54660
54681
  const declared = Number(incoming.headers["content-length"] ?? "0");
54661
54682
  if (maxBytes !== void 0 && declared > maxBytes) {
54662
54683
  incoming.destroy();
@@ -54675,7 +54696,7 @@ function readBody(incoming, url3, maxBytes) {
54675
54696
  chunks.push(chunk);
54676
54697
  });
54677
54698
  incoming.on("error", reject);
54678
- incoming.on("end", () => resolve12(Buffer.concat(chunks)));
54699
+ incoming.on("end", () => resolve13(Buffer.concat(chunks)));
54679
54700
  });
54680
54701
  }
54681
54702
  function isConnectionReset(error61) {
@@ -54683,7 +54704,7 @@ function isConnectionReset(error61) {
54683
54704
  }
54684
54705
  function exchange(request2, agents, attempt2 = 0) {
54685
54706
  const { signal, url: url3 } = request2;
54686
- return new Promise((resolve12, reject) => {
54707
+ return new Promise((resolve13, reject) => {
54687
54708
  if (signal.aborted) {
54688
54709
  reject(signal.reason);
54689
54710
  return;
@@ -54710,7 +54731,7 @@ function exchange(request2, agents, attempt2 = 0) {
54710
54731
  const stale = outgoing.reusedSocket && !responded && isConnectionReset(error61);
54711
54732
  if (stale && attempt2 < STALE_SOCKET_RETRIES && !signal.aborted) {
54712
54733
  settle();
54713
- resolve12(exchange(request2, agents, attempt2 + 1));
54734
+ resolve13(exchange(request2, agents, attempt2 + 1));
54714
54735
  return;
54715
54736
  }
54716
54737
  fail(error61);
@@ -54723,7 +54744,7 @@ function exchange(request2, agents, attempt2 = 0) {
54723
54744
  readBody(incoming, url3, isRedirect(status) ? void 0 : request2.maxBodyBytes).then(
54724
54745
  (body) => {
54725
54746
  settle();
54726
- resolve12({ status, headers: incoming.headers, body });
54747
+ resolve13({ status, headers: incoming.headers, body });
54727
54748
  },
54728
54749
  fail
54729
54750
  );
@@ -54968,8 +54989,8 @@ function isBodyless(method) {
54968
54989
  return method === "GET" || method === "HEAD";
54969
54990
  }
54970
54991
  function exchange2(send2, options, input2) {
54971
- return new Promise((resolve12, reject) => {
54972
- const outgoing = send2({ ...options, method: input2.method, signal: input2.signal }, resolve12);
54992
+ return new Promise((resolve13, reject) => {
54993
+ const outgoing = send2({ ...options, method: input2.method, signal: input2.signal }, resolve13);
54973
54994
  outgoing.on("error", reject);
54974
54995
  if (isBodyless(input2.method)) {
54975
54996
  input2.body.resume();
@@ -56438,7 +56459,7 @@ function createGitRunner(options) {
56438
56459
  }
56439
56460
  await killProcessTree(child.pid, { signal: "SIGKILL", child, platform: platform3 });
56440
56461
  };
56441
- return new Promise((resolve12, reject) => {
56462
+ return new Promise((resolve13, reject) => {
56442
56463
  let ending = null;
56443
56464
  const stop = (next) => {
56444
56465
  if (ending !== null) return;
@@ -56463,7 +56484,7 @@ function createGitRunner(options) {
56463
56484
  signal.removeEventListener("abort", onAbort);
56464
56485
  const final = ending ?? last;
56465
56486
  if (final.kind === "exited") {
56466
- resolve12({ exitCode: final.exitCode, stdout: stdout.text(), stderr: stderr.text() });
56487
+ resolve13({ exitCode: final.exitCode, stdout: stdout.text(), stderr: stderr.text() });
56467
56488
  } else {
56468
56489
  reject(faultFor(final, command));
56469
56490
  }
@@ -57980,7 +58001,7 @@ function statusOf(error61) {
57980
58001
  }
57981
58002
  return 1;
57982
58003
  }
57983
- var systemExec = (request2) => new Promise((resolve12) => {
58004
+ var systemExec = (request2) => new Promise((resolve13) => {
57984
58005
  const child = (0, import_node_child_process6.execFile)(
57985
58006
  request2.command,
57986
58007
  [...request2.args],
@@ -57991,7 +58012,7 @@ var systemExec = (request2) => new Promise((resolve12) => {
57991
58012
  windowsHide: true
57992
58013
  },
57993
58014
  (error61, stdout, stderr) => {
57994
- resolve12({ status: statusOf(error61), stdout, stderr });
58015
+ resolve13({ status: statusOf(error61), stdout, stderr });
57995
58016
  }
57996
58017
  );
57997
58018
  child.stdin?.on("error", () => {
@@ -59181,11 +59202,11 @@ async function startGitCredentialServer(options) {
59181
59202
  });
59182
59203
  });
59183
59204
  removeStaleEndpoint(options.endpoint);
59184
- await new Promise((resolve12, reject) => {
59205
+ await new Promise((resolve13, reject) => {
59185
59206
  server.once("error", reject);
59186
59207
  server.listen(options.endpoint, () => {
59187
59208
  server.off("error", reject);
59188
- resolve12();
59209
+ resolve13();
59189
59210
  });
59190
59211
  });
59191
59212
  options.log.info("git.credential_server_listening", { endpoint: options.endpoint });
@@ -59193,7 +59214,7 @@ async function startGitCredentialServer(options) {
59193
59214
  endpoint: options.endpoint,
59194
59215
  [Symbol.asyncDispose]: async () => {
59195
59216
  closing.abort();
59196
- await new Promise((resolve12) => server.close(() => resolve12()));
59217
+ await new Promise((resolve13) => server.close(() => resolve13()));
59197
59218
  removeStaleEndpoint(options.endpoint);
59198
59219
  }
59199
59220
  };
@@ -59267,13 +59288,13 @@ authorityKeyIdentifier = keyid
59267
59288
  `;
59268
59289
  }
59269
59290
  function openssl(args, cwd) {
59270
- return new Promise((resolve12, reject) => {
59291
+ return new Promise((resolve13, reject) => {
59271
59292
  (0, import_node_child_process9.execFile)(
59272
59293
  "openssl",
59273
59294
  [...args],
59274
59295
  { cwd, timeout: OPENSSL_TIMEOUT_MS },
59275
59296
  (error61, _stdout, stderr) => {
59276
- if (error61 === null) resolve12();
59297
+ if (error61 === null) resolve13();
59277
59298
  else
59278
59299
  reject(new Error(`openssl ${args[0] ?? ""} failed: ${stderr.trim() || error61.message}`));
59279
59300
  }
@@ -59450,21 +59471,21 @@ function relayTo(forward, log) {
59450
59471
  };
59451
59472
  }
59452
59473
  function listen(server, target) {
59453
- return new Promise((resolve12, reject) => {
59474
+ return new Promise((resolve13, reject) => {
59454
59475
  server.once("error", reject);
59455
59476
  const done = () => {
59456
59477
  server.off("error", reject);
59457
- resolve12();
59478
+ resolve13();
59458
59479
  };
59459
59480
  if (typeof target === "string") server.listen(target, done);
59460
59481
  else server.listen(target.port, target.host, done);
59461
59482
  });
59462
59483
  }
59463
59484
  function close(server, sockets = /* @__PURE__ */ new Set()) {
59464
- return new Promise((resolve12) => {
59485
+ return new Promise((resolve13) => {
59465
59486
  for (const socket of sockets) socket.destroy();
59466
59487
  server.closeAllConnections();
59467
- server.close(() => resolve12());
59488
+ server.close(() => resolve13());
59468
59489
  });
59469
59490
  }
59470
59491
  function portOf(server) {
@@ -62247,7 +62268,7 @@ async function startNativeIngest(deps) {
62247
62268
  };
62248
62269
  const settleIdle = () => {
62249
62270
  if (workers.size > 0) return;
62250
- for (const resolve12 of idleWaiters) resolve12();
62271
+ for (const resolve13 of idleWaiters) resolve13();
62251
62272
  idleWaiters.clear();
62252
62273
  };
62253
62274
  const retryDelay = (worker) => {
@@ -62490,7 +62511,7 @@ async function startNativeIngest(deps) {
62490
62511
  sweep: sweep2,
62491
62512
  whenIdle: () => {
62492
62513
  if (workers.size === 0) return Promise.resolve();
62493
- return new Promise((resolve12) => idleWaiters.add(resolve12));
62514
+ return new Promise((resolve13) => idleWaiters.add(resolve13));
62494
62515
  },
62495
62516
  [Symbol.asyncDispose]: async () => {
62496
62517
  shutdown.abort();
@@ -62638,7 +62659,7 @@ function captureProbe(command, args, options) {
62638
62659
  const launch = directLaunch(command, args, options);
62639
62660
  if (launch === void 0) return Promise.resolve({ stdout: "", stderr: "", exitCode: void 0 });
62640
62661
  const env = platform3 === "win32" ? withWindowsHelper(canonicalWindowsEnvironment(options.env)) : options.env;
62641
- return new Promise((resolve12) => {
62662
+ return new Promise((resolve13) => {
62642
62663
  const limit = options.maxBufferBytes ?? DEFAULT_MAX_BYTES;
62643
62664
  const stdout = [];
62644
62665
  const stderr = [];
@@ -62673,7 +62694,7 @@ function captureProbe(command, args, options) {
62673
62694
  settled2 = true;
62674
62695
  deadlineController.abort();
62675
62696
  options.signal?.removeEventListener("abort", abort);
62676
- resolve12({
62697
+ resolve13({
62677
62698
  stdout: Buffer.concat(stdout).toString("utf8"),
62678
62699
  stderr: Buffer.concat(stderr).toString("utf8"),
62679
62700
  exitCode
@@ -62805,7 +62826,7 @@ function cursorAccountLabel(output2) {
62805
62826
  function waitForAbort(signal) {
62806
62827
  if (signal.aborted) return Promise.resolve();
62807
62828
  return new Promise(
62808
- (resolve12) => signal.addEventListener("abort", () => resolve12(), { once: true })
62829
+ (resolve13) => signal.addEventListener("abort", () => resolve13(), { once: true })
62809
62830
  );
62810
62831
  }
62811
62832
  function idlePrompt(signal) {
@@ -62883,14 +62904,14 @@ async function codexLabel(executable, env) {
62883
62904
  windowsVerbatimArguments: launch.windowsVerbatimArguments
62884
62905
  });
62885
62906
  const timeout = AbortSignal.timeout(ACCOUNT_TIMEOUT_MS);
62886
- return new Promise((resolve12) => {
62907
+ return new Promise((resolve13) => {
62887
62908
  let finished = false;
62888
62909
  let buffer = "";
62889
62910
  const finish = (label) => {
62890
62911
  if (finished) return;
62891
62912
  finished = true;
62892
62913
  child.kill();
62893
- resolve12(label);
62914
+ resolve13(label);
62894
62915
  };
62895
62916
  const send2 = (value2) => {
62896
62917
  child.stdin.write(`${JSON.stringify(value2)}
@@ -63399,11 +63420,11 @@ async function resolveCliEnvironment(options) {
63399
63420
  }
63400
63421
  async function openCliEnvironment(options) {
63401
63422
  const decorate = options.decorate ?? ((env) => env);
63402
- const resolve12 = async () => {
63423
+ const resolve13 = async () => {
63403
63424
  const resolved = await resolveCliEnvironmentDetailed(options);
63404
63425
  return { env: decorate(resolved.env), source: resolved.source };
63405
63426
  };
63406
- let state = await resolve12();
63427
+ let state = await resolve13();
63407
63428
  let retryAt = options.clock.now() + DEGRADED_RETRY_MS;
63408
63429
  return {
63409
63430
  current: () => state.env,
@@ -63412,7 +63433,7 @@ async function openCliEnvironment(options) {
63412
63433
  if (state.source === "login_shell" || options.platform === "win32") return false;
63413
63434
  if (options.clock.now() < retryAt) return false;
63414
63435
  retryAt = options.clock.now() + DEGRADED_RETRY_MS;
63415
- const next = await resolve12();
63436
+ const next = await resolve13();
63416
63437
  const changed = envValue(next.env, "PATH") !== envValue(state.env, "PATH");
63417
63438
  state = next;
63418
63439
  return changed;
@@ -63489,11 +63510,11 @@ async function installVersion2(backendKind, requested, options, signal) {
63489
63510
  }
63490
63511
  return exact;
63491
63512
  }
63492
- const resolve12 = options.resolveVersion;
63493
- if (resolve12 === void 0) throw new Error("Latest version lookup is unavailable");
63513
+ const resolve13 = options.resolveVersion;
63514
+ if (resolve13 === void 0) throw new Error("Latest version lookup is unavailable");
63494
63515
  const packageName = packageFor(backendKind).name;
63495
63516
  return checkedVersion(
63496
- await resolve12(backendKind === "opencode_serve" ? `${packageName}@1` : packageName, signal)
63517
+ await resolve13(backendKind === "opencode_serve" ? `${packageName}@1` : packageName, signal)
63497
63518
  );
63498
63519
  }
63499
63520
  function selection(root, backendKind, version2) {
@@ -63942,10 +63963,10 @@ function createIgnoreMatcher(path4) {
63942
63963
  const expression = globToRegExp(pattern);
63943
63964
  return (candidate) => expression.test(candidate) || expression.test(`${candidate}/`);
63944
63965
  }
63945
- function isIgnored(normalizedPath, basename10, isDirectory5, configured) {
63946
- if (isDirectory5 && ALWAYS_IGNORED_DIRECTORIES.has(basename10))
63966
+ function isIgnored(normalizedPath, basename11, isDirectory5, configured) {
63967
+ if (isDirectory5 && ALWAYS_IGNORED_DIRECTORIES.has(basename11))
63947
63968
  return true;
63948
- if (!isDirectory5 && ALWAYS_IGNORED_FILES.has(basename10))
63969
+ if (!isDirectory5 && ALWAYS_IGNORED_FILES.has(basename11))
63949
63970
  return true;
63950
63971
  return configured.some((matches) => matches(normalizedPath));
63951
63972
  }
@@ -64202,7 +64223,7 @@ var MAX_DIAGNOSTICS = 100;
64202
64223
  function createLocalSkillScanCache() {
64203
64224
  return { inspections: /* @__PURE__ */ new Map(), lastCompleteRevision: null };
64204
64225
  }
64205
- async function scanSkillRoots(input2, cache2) {
64226
+ async function scanSkillRoots(input2, cache2, managedRoots = []) {
64206
64227
  const attemptId = (0, import_node_crypto19.randomUUID)();
64207
64228
  const ignoredPaths = input2.ignoredPaths ?? [];
64208
64229
  const resolvedRoots = resolveScanRoots(input2.roots, input2.enabledProviderKinds ?? []);
@@ -64210,7 +64231,8 @@ async function scanSkillRoots(input2, cache2) {
64210
64231
  input: input2,
64211
64232
  cache: cache2,
64212
64233
  visited: /* @__PURE__ */ new Set(),
64213
- declaredRoots: await canonicalDirectories(resolvedRoots.map((root) => root.directory))
64234
+ declaredRoots: await canonicalDirectories(resolvedRoots.map((root) => root.directory)),
64235
+ managedRoots: await canonicalDirectories(managedRoots)
64214
64236
  };
64215
64237
  const candidates2 = [];
64216
64238
  const diagnostics = [];
@@ -64316,6 +64338,7 @@ function invalid(resolvedRoot, name, error61) {
64316
64338
  async function scanRootAsPackage(pass, resolvedRoot) {
64317
64339
  if (!await exists3(import_node_path40.default.join(resolvedRoot.directory, "SKILL.md"))) return null;
64318
64340
  const canonical = await (0, import_promises38.realpath)(resolvedRoot.directory).catch(() => resolvedRoot.directory);
64341
+ if (isManaged(pass, canonical)) return { candidates: [], diagnostics: [], incomplete: false };
64319
64342
  try {
64320
64343
  const inspected = await inspectCached(pass, canonical, null);
64321
64344
  return {
@@ -64379,6 +64402,7 @@ async function scanEntry(pass, resolvedRoot, canonicalRoot, name) {
64379
64402
  const message2 = `Could not resolve Skill ${name}`;
64380
64403
  return { kind: "diagnostic", diagnostic: { code: "SOURCE_UNREADABLE", message: message2, rootLabel } };
64381
64404
  }
64405
+ if (isManaged(pass, canonical)) return null;
64382
64406
  const roots = pass.declaredRoots.length > 0 ? pass.declaredRoots : [canonicalRoot];
64383
64407
  if (!roots.some((root) => isWithinDirectory2(root, canonical))) {
64384
64408
  const message2 = `Skill ${name} resolves outside every declared Skill source`;
@@ -64405,12 +64429,12 @@ function resolveScanRoots(roots, enabledProviderKinds) {
64405
64429
  const resolved = [];
64406
64430
  for (const root of roots) {
64407
64431
  if (root.kind === "repository") {
64408
- for (const [index, relative5] of skillRepositorySourceDirectories(
64432
+ for (const [index, relative6] of skillRepositorySourceDirectories(
64409
64433
  enabledProviderKinds
64410
64434
  ).entries()) {
64411
64435
  resolved.push({
64412
64436
  root,
64413
- directory: import_node_path40.default.join(root.path, relative5),
64437
+ directory: import_node_path40.default.join(root.path, relative6),
64414
64438
  order: `1:${root.repositoryId}:${String(index).padStart(2, "0")}`
64415
64439
  });
64416
64440
  }
@@ -64461,12 +64485,12 @@ async function fingerprintPackage(root) {
64461
64485
  const entries = await (0, import_promises38.readdir)(directory, { withFileTypes: true });
64462
64486
  entries.sort((left, right) => Buffer.compare(Buffer.from(left.name), Buffer.from(right.name)));
64463
64487
  for (const entry of entries) {
64464
- const relative5 = relativeDirectory ? `${relativeDirectory}/${entry.name}` : entry.name;
64488
+ const relative6 = relativeDirectory ? `${relativeDirectory}/${entry.name}` : entry.name;
64465
64489
  const absolute = import_node_path40.default.join(directory, entry.name);
64466
64490
  const metadata = await (0, import_promises38.lstat)(absolute);
64467
64491
  const kind = entryKind(entry);
64468
- hash2.update(relative5.normalize("NFC")).update(`\0${kind}\0${metadata.size}\0${metadata.mtimeMs}\0${metadata.mode & 511}\0`);
64469
- if (entry.isDirectory()) await visit2(absolute, relative5);
64492
+ hash2.update(relative6.normalize("NFC")).update(`\0${kind}\0${metadata.size}\0${metadata.mtimeMs}\0${metadata.mode & 511}\0`);
64493
+ if (entry.isDirectory()) await visit2(absolute, relative6);
64470
64494
  }
64471
64495
  };
64472
64496
  await visit2(root, "");
@@ -64483,9 +64507,12 @@ async function canonicalDirectories(directories) {
64483
64507
  );
64484
64508
  return [...new Set(canonical)];
64485
64509
  }
64510
+ function isManaged(pass, canonical) {
64511
+ return pass.managedRoots.some((root) => isWithinDirectory2(root, canonical));
64512
+ }
64486
64513
  function isWithinDirectory2(parent, candidate) {
64487
- const relative5 = import_node_path40.default.relative(parent, candidate);
64488
- return relative5 !== ".." && !relative5.startsWith(`..${import_node_path40.default.sep}`) && !import_node_path40.default.isAbsolute(relative5);
64514
+ const relative6 = import_node_path40.default.relative(parent, candidate);
64515
+ return relative6 !== ".." && !relative6.startsWith(`..${import_node_path40.default.sep}`) && !import_node_path40.default.isAbsolute(relative6);
64489
64516
  }
64490
64517
  async function exists3(candidate) {
64491
64518
  try {
@@ -64689,7 +64716,7 @@ function optionalStringArray(value2, field3) {
64689
64716
  }
64690
64717
  return value2;
64691
64718
  }
64692
- async function scanLocalSkills(home, context, cache2, mode = "incremental") {
64719
+ async function scanLocalSkills(home, context, cache2, mode = "incremental", managedRoots = []) {
64693
64720
  const resolved = await resolveLocalScanInput(home, context, mode);
64694
64721
  if (resolved.kind === "invalid_config") {
64695
64722
  return failedLocalSkillScan(
@@ -64698,7 +64725,7 @@ async function scanLocalSkills(home, context, cache2, mode = "incremental") {
64698
64725
  `Invalid Skill source configuration: ${resolved.diagnostic}`
64699
64726
  );
64700
64727
  }
64701
- return scanSkillRoots(resolved.input, cache2);
64728
+ return scanSkillRoots(resolved.input, cache2, managedRoots);
64702
64729
  }
64703
64730
 
64704
64731
  // src/capabilities/skills/store.ts
@@ -64718,6 +64745,9 @@ function uuidV5(name, namespace) {
64718
64745
  function alanSkillId(slug) {
64719
64746
  return uuidV5(`alan:${slug}`, ALAN_SKILL_NAMESPACE);
64720
64747
  }
64748
+ function alanSkillVersionId(slug, contentHash) {
64749
+ return uuidV5(`alan:${slug}:${contentHash}`, ALAN_SKILL_NAMESPACE);
64750
+ }
64721
64751
 
64722
64752
  // src/capabilities/skills/store.ts
64723
64753
  init_runtime_v2();
@@ -64727,9 +64757,12 @@ function skillsLayout(stateDir, home) {
64727
64757
  return {
64728
64758
  root,
64729
64759
  installedFile: (0, import_node_path42.join)(root, "installed.json"),
64760
+ retiredFile: (0, import_node_path42.join)(root, "retired.json"),
64730
64761
  localFile: (0, import_node_path42.join)(root, "local.json"),
64731
64762
  versionsDir: (0, import_node_path42.join)(root, "versions"),
64732
64763
  tmpDir: (0, import_node_path42.join)(root, "tmp"),
64764
+ pluginDir: (0, import_node_path42.join)(root, "alan-plugin"),
64765
+ pluginSkillsDir: (0, import_node_path42.join)(root, "alan-plugin", "skills"),
64733
64766
  nativeDir: home === void 0 || home === "" ? null : (0, import_node_path42.join)(home, ".agents", "skills")
64734
64767
  };
64735
64768
  }
@@ -64797,18 +64830,20 @@ async function isIntact(layout, skill) {
64797
64830
  return false;
64798
64831
  }
64799
64832
  }
64800
- async function resolveNativeBuiltIn(layout, invocation) {
64833
+ async function resolveNativeBuiltIn(layout, invocation, baked) {
64801
64834
  const slug = invocation.displayName;
64802
64835
  if (layout.nativeDir === null || invocation.skillId !== alanSkillId(slug)) return null;
64803
64836
  const directory = (0, import_node_path42.join)(layout.nativeDir, slug);
64804
64837
  try {
64805
- await inspectSkillPackage(directory, { expectedName: slug });
64838
+ const inspected = await inspectSkillPackage(directory, { expectedName: slug });
64839
+ if (baked === "exact" && alanSkillVersionId(slug, inspected.contentHash) !== invocation.versionId)
64840
+ return null;
64806
64841
  return { packageDirectory: directory };
64807
64842
  } catch {
64808
64843
  return null;
64809
64844
  }
64810
64845
  }
64811
- async function resolveSkillInvocations(layout, invocations) {
64846
+ async function resolveSkillInvocations(layout, invocations, baked = "any") {
64812
64847
  if (invocations.length === 0) return { kind: "resolved", skills: [] };
64813
64848
  const installed = await readInstalledSkills(layout);
64814
64849
  const local = invocations.some((invocation) => invocation.kind === "local_skill") ? await readLocalSkills(layout) : null;
@@ -64828,7 +64863,7 @@ async function resolveSkillInvocations(layout, invocations) {
64828
64863
  resolved.push({ packageDirectory: packageDirectory(layout, skill.versionId) });
64829
64864
  continue;
64830
64865
  }
64831
- const native = await resolveNativeBuiltIn(layout, invocation);
64866
+ const native = await resolveNativeBuiltIn(layout, invocation, baked);
64832
64867
  if (native === null) missing.push(invocation.displayName);
64833
64868
  else resolved.push(native);
64834
64869
  }
@@ -64850,12 +64885,19 @@ async function availableSkillIndex(layout) {
64850
64885
  candidates2.push({ directory: (0, import_node_path42.join)(layout.nativeDir, entry.name) });
64851
64886
  }
64852
64887
  }
64853
- for (const candidate of candidates2.slice(0, 2e3)) {
64854
- const skill = await inspectIndexedSkill(candidate.directory, candidate.contentHash);
64855
- if (skill !== null && !found.has(skill.name)) found.set(skill.name, skill);
64888
+ const bounded = candidates2.slice(0, 2e3);
64889
+ for (let start = 0; start < bounded.length; start += INDEX_CONCURRENCY) {
64890
+ const batch = bounded.slice(start, start + INDEX_CONCURRENCY);
64891
+ const inspected = await Promise.all(
64892
+ batch.map((candidate) => inspectIndexedSkill(candidate.directory, candidate.contentHash))
64893
+ );
64894
+ for (const skill of inspected) {
64895
+ if (skill !== null && !found.has(skill.name)) found.set(skill.name, skill);
64896
+ }
64856
64897
  }
64857
64898
  return [...found.values()].sort((a, b) => a.name.localeCompare(b.name));
64858
64899
  }
64900
+ var INDEX_CONCURRENCY = 8;
64859
64901
  async function inspectIndexedSkill(directory, contentHash) {
64860
64902
  try {
64861
64903
  const inspected = await inspectSkillPackage(directory, { expectedName: null });
@@ -65039,8 +65081,8 @@ async function collectStream(stream) {
65039
65081
  return import_node_buffer2.Buffer.concat(chunks);
65040
65082
  }
65041
65083
  function addArchiveEntry(archive, header, bytes) {
65042
- return new Promise((resolve12, reject) => {
65043
- archive.entry(header, bytes, (error61) => error61 ? reject(error61) : resolve12());
65084
+ return new Promise((resolve13, reject) => {
65085
+ archive.entry(header, bytes, (error61) => error61 ? reject(error61) : resolve13());
65044
65086
  });
65045
65087
  }
65046
65088
  async function decompressBounded(archiveBytes) {
@@ -65066,7 +65108,7 @@ async function extractTar(tarBytes, destination) {
65066
65108
  const extractor = (0, import_tar_stream.extract)();
65067
65109
  let fileCount = 0;
65068
65110
  let totalBytes = 0;
65069
- const completion = new Promise((resolve12, reject) => {
65111
+ const completion = new Promise((resolve13, reject) => {
65070
65112
  extractor.on("entry", (header, stream, next) => {
65071
65113
  void extractEntry(header, stream, destination, {
65072
65114
  addFile(size) {
@@ -65081,7 +65123,7 @@ async function extractTar(tarBytes, destination) {
65081
65123
  }
65082
65124
  }).then(next, (error61) => extractor.destroy(error61 instanceof Error ? error61 : new Error(String(error61))));
65083
65125
  });
65084
- extractor.once("finish", resolve12);
65126
+ extractor.once("finish", resolve13);
65085
65127
  extractor.once("error", reject);
65086
65128
  });
65087
65129
  import_node_stream.Readable.from(tarBytes).pipe(extractor);
@@ -65158,34 +65200,222 @@ async function publishLocalSkill(options) {
65158
65200
  };
65159
65201
  }
65160
65202
 
65161
- // src/capabilities/skills/sync.ts
65203
+ // src/capabilities/skills/native-index.ts
65162
65204
  var import_node_crypto23 = require("crypto");
65205
+ var import_node_fs16 = require("fs");
65163
65206
  var import_promises44 = require("fs/promises");
65164
65207
  var import_node_path45 = require("path");
65208
+ var ALAN_SKILLS_PLUGIN_NAME = "alan";
65209
+ var PLUGIN_MANIFEST = `${JSON.stringify(
65210
+ {
65211
+ name: ALAN_SKILLS_PLUGIN_NAME,
65212
+ description: "Skills Alan installed on this machine for you and your team."
65213
+ },
65214
+ null,
65215
+ 2
65216
+ )}
65217
+ `;
65218
+ async function entryKind2(path4) {
65219
+ try {
65220
+ return (await (0, import_promises44.lstat)(path4)).isSymbolicLink() ? "link" : "other";
65221
+ } catch (error61) {
65222
+ if (errnoCode(error61) === "ENOENT") return "missing";
65223
+ throw error61;
65224
+ }
65225
+ }
65226
+ async function linkTarget(path4) {
65227
+ return (0, import_promises44.readlink)(path4).catch(() => null);
65228
+ }
65229
+ async function removeLink(path4) {
65230
+ try {
65231
+ await (0, import_promises44.unlink)(path4);
65232
+ } catch (error61) {
65233
+ const code = errnoCode(error61);
65234
+ if (code === "ENOENT") return;
65235
+ if (code !== "EPERM" && code !== "EISDIR") throw error61;
65236
+ await (0, import_promises44.rmdir)(path4);
65237
+ }
65238
+ }
65239
+ async function placeLink(plan2, platform3) {
65240
+ if (await linkTarget(plan2.path) === plan2.target) return false;
65241
+ const staged = (0, import_node_path45.join)((0, import_node_path45.dirname)(plan2.path), `.${(0, import_node_path45.basename)(plan2.path)}.${(0, import_node_crypto23.randomUUID)()}.tmp`);
65242
+ await (0, import_promises44.symlink)(plan2.target, staged, platform3 === "win32" ? "junction" : "dir");
65243
+ try {
65244
+ if (platform3 === "win32") await removeLink(plan2.path);
65245
+ await (0, import_promises44.rename)(staged, plan2.path);
65246
+ } catch (error61) {
65247
+ await removeLink(staged).catch(() => void 0);
65248
+ throw error61;
65249
+ }
65250
+ return true;
65251
+ }
65252
+ function versionTarget(layout, versionId, platform3) {
65253
+ const absolute = (0, import_node_path45.join)(layout.versionsDir, versionId);
65254
+ return platform3 === "win32" ? absolute : (0, import_node_path45.relative)(layout.pluginSkillsDir, absolute);
65255
+ }
65256
+ async function writeManifest(layout) {
65257
+ const manifest = (0, import_node_path45.join)(layout.pluginDir, ".claude-plugin", "plugin.json");
65258
+ if (await (0, import_promises44.readFile)(manifest, "utf8").catch(() => null) === PLUGIN_MANIFEST) return;
65259
+ await (0, import_promises44.mkdir)((0, import_node_path45.dirname)(manifest), { recursive: true, mode: 448 });
65260
+ const staged = `${manifest}.${(0, import_node_crypto23.randomUUID)()}.tmp`;
65261
+ await (0, import_promises44.writeFile)(staged, PLUGIN_MANIFEST, { mode: 384 });
65262
+ await (0, import_promises44.rename)(staged, manifest);
65263
+ }
65264
+ async function reconcilePluginSkills(layout, installed, platform3) {
65265
+ await (0, import_promises44.mkdir)(layout.pluginSkillsDir, { recursive: true, mode: 448 });
65266
+ const wanted = new Map(installed.map((skill) => [skill.slug, skill]));
65267
+ let linked = 0;
65268
+ for (const skill of installed) {
65269
+ const plan2 = {
65270
+ path: (0, import_node_path45.join)(layout.pluginSkillsDir, skill.slug),
65271
+ target: versionTarget(layout, skill.versionId, platform3)
65272
+ };
65273
+ if (await entryKind2(plan2.path) === "other") {
65274
+ await (0, import_promises44.rm)(plan2.path, { recursive: true, force: true });
65275
+ }
65276
+ if (await placeLink(plan2, platform3)) linked += 1;
65277
+ }
65278
+ let unlinked = 0;
65279
+ for (const name of await (0, import_promises44.readdir)(layout.pluginSkillsDir)) {
65280
+ if (wanted.has(name)) continue;
65281
+ const path4 = (0, import_node_path45.join)(layout.pluginSkillsDir, name);
65282
+ if (await entryKind2(path4) === "link") await removeLink(path4);
65283
+ else await (0, import_promises44.rm)(path4, { recursive: true, force: true });
65284
+ unlinked += 1;
65285
+ }
65286
+ return { linked, unlinked };
65287
+ }
65288
+ async function isOwnCodexLink(layout, path4) {
65289
+ const target = await linkTarget(path4);
65290
+ if (target === null) return false;
65291
+ const absolute = (0, import_node_path45.isAbsolute)(target) ? target : (0, import_node_path45.resolve)((0, import_node_path45.dirname)(path4), target);
65292
+ return isWithinDirectory2(layout.pluginSkillsDir, absolute);
65293
+ }
65294
+ async function isForeignPackage(layout, path4) {
65295
+ const resolved = await (0, import_promises44.realpath)(path4).catch(() => null);
65296
+ if (resolved === null) return false;
65297
+ const root = await (0, import_promises44.realpath)(layout.root).catch(() => layout.root);
65298
+ return !isWithinDirectory2(root, resolved);
65299
+ }
65300
+ async function codexSlot(layout, path4, slug) {
65301
+ const baked = layout.nativeDir !== null && await isForeignPackage(layout, (0, import_node_path45.join)(layout.nativeDir, slug));
65302
+ const kind = await entryKind2(path4);
65303
+ if (kind === "other") return "taken";
65304
+ const ours = kind === "link" && await isOwnCodexLink(layout, path4);
65305
+ if (kind === "link" && !ours) return "taken";
65306
+ if (baked) {
65307
+ if (ours) await removeLink(path4);
65308
+ return "taken";
65309
+ }
65310
+ return ours ? "ours" : "free";
65311
+ }
65312
+ async function unlinkStaleCodexEntries(layout, codexSkillsDir, wanted) {
65313
+ let unlinked = 0;
65314
+ for (const name of await (0, import_promises44.readdir)(codexSkillsDir)) {
65315
+ const path4 = (0, import_node_path45.join)(codexSkillsDir, name);
65316
+ if (wanted.has(name) && !name.endsWith(".tmp")) continue;
65317
+ if (await entryKind2(path4) !== "link" || !await isOwnCodexLink(layout, path4)) continue;
65318
+ await removeLink(path4);
65319
+ unlinked += 1;
65320
+ }
65321
+ return unlinked;
65322
+ }
65323
+ async function reconcileCodexSkills(layout, installed, codexSkillsDir, platform3) {
65324
+ await (0, import_promises44.mkdir)(codexSkillsDir, { recursive: true, mode: 448 });
65325
+ const report2 = { linked: 0, unlinked: 0, skipped: [] };
65326
+ for (const skill of installed) {
65327
+ const path4 = (0, import_node_path45.join)(codexSkillsDir, skill.slug);
65328
+ if (await codexSlot(layout, path4, skill.slug) === "taken") {
65329
+ report2.skipped.push(skill.slug);
65330
+ continue;
65331
+ }
65332
+ const target = (0, import_node_path45.join)(layout.pluginSkillsDir, skill.slug);
65333
+ if (await placeLink({ path: path4, target }, platform3)) report2.linked += 1;
65334
+ }
65335
+ const wanted = new Set(installed.map((skill) => skill.slug));
65336
+ report2.unlinked = await unlinkStaleCodexEntries(layout, codexSkillsDir, wanted);
65337
+ return report2;
65338
+ }
65339
+ async function reconcileNativeIndex(layout, installed, options) {
65340
+ await writeManifest(layout);
65341
+ const plugin = await reconcilePluginSkills(layout, installed, options.platform);
65342
+ if (options.codexSkillsDir === null) return { ...plugin, skipped: [] };
65343
+ const codex = await reconcileCodexSkills(
65344
+ layout,
65345
+ installed,
65346
+ options.codexSkillsDir,
65347
+ options.platform
65348
+ );
65349
+ return {
65350
+ linked: plugin.linked + codex.linked,
65351
+ unlinked: plugin.unlinked + codex.unlinked,
65352
+ skipped: codex.skipped
65353
+ };
65354
+ }
65355
+ function installedSkillFolders(layout) {
65356
+ return (0, import_node_fs16.existsSync)((0, import_node_path45.join)(layout.pluginDir, ".claude-plugin", "plugin.json")) ? { pluginDir: layout.pluginDir, skillsDir: layout.pluginSkillsDir } : null;
65357
+ }
65358
+
65359
+ // src/capabilities/skills/sync.ts
65360
+ var import_node_crypto24 = require("crypto");
65361
+ var import_promises45 = require("fs/promises");
65362
+ var import_node_path46 = require("path");
65363
+ init_zod();
65165
65364
  var SKILL_PREPARE_WAIT_MS = 15e3;
65166
- async function install(layout, source, skill, download, signal) {
65365
+ var RETIRED_VERSION_RETENTION_MS = 24 * 60 * 60 * 1e3;
65366
+ async function makeFilesReadOnly(directory, platform3) {
65367
+ if (platform3 === "win32") return;
65368
+ for (const entry of await (0, import_promises45.readdir)(directory, { withFileTypes: true })) {
65369
+ const path4 = (0, import_node_path46.join)(directory, entry.name);
65370
+ if (entry.isDirectory()) await makeFilesReadOnly(path4, platform3);
65371
+ else if (entry.isFile()) {
65372
+ const executable = ((await (0, import_promises45.lstat)(path4)).mode & 64) !== 0;
65373
+ await (0, import_promises45.chmod)(path4, executable ? 365 : 292);
65374
+ }
65375
+ }
65376
+ }
65377
+ async function install(env, skill, download, signal) {
65378
+ const { layout, source, platform: platform3 } = env;
65167
65379
  const bytes = await source.download(download.url, signal);
65168
- await (0, import_promises44.mkdir)(layout.tmpDir, { recursive: true, mode: 448 });
65169
- const staging = (0, import_node_path45.join)(layout.tmpDir, (0, import_node_crypto23.randomUUID)());
65380
+ await (0, import_promises45.mkdir)(layout.tmpDir, { recursive: true, mode: 448 });
65381
+ const staging = (0, import_node_path46.join)(layout.tmpDir, (0, import_node_crypto24.randomUUID)());
65170
65382
  await extractSkillBundle(Buffer.from(bytes), staging, {
65171
65383
  expectedArchiveHash: download.archiveHash,
65172
65384
  expectedContentHash: skill.contentHash
65173
65385
  });
65174
65386
  const target = packageDirectory(layout, skill.versionId);
65175
- await (0, import_promises44.mkdir)(layout.versionsDir, { recursive: true, mode: 448 });
65176
- await (0, import_promises44.rm)(target, { recursive: true, force: true });
65177
- await (0, import_promises44.rename)(staging, target);
65178
- }
65179
- async function sweep(layout, keep) {
65387
+ await (0, import_promises45.mkdir)(layout.versionsDir, { recursive: true, mode: 448 });
65388
+ await (0, import_promises45.rm)(target, { recursive: true, force: true });
65389
+ await (0, import_promises45.rename)(staging, target);
65390
+ await makeFilesReadOnly(target, platform3);
65391
+ }
65392
+ var retiredFileSchema = external_exports.record(external_exports.string(), external_exports.number());
65393
+ async function sweep(env, keep) {
65394
+ const { layout } = env;
65180
65395
  const kept = new Set(keep.map((skill) => skill.versionId));
65181
- const stale = (await (0, import_promises44.readdir)(layout.versionsDir).catch(() => [])).filter(
65182
- (name) => !kept.has(name)
65183
- );
65184
- await Promise.all(
65185
- stale.map((name) => (0, import_promises44.rm)((0, import_node_path45.join)(layout.versionsDir, name), { recursive: true, force: true }))
65396
+ const read = await readJsonFile(layout.retiredFile, retiredFileSchema).catch(() => null);
65397
+ const retired = read?.kind === "ok" ? read.value : {};
65398
+ const now = env.now();
65399
+ const stillRetired = {};
65400
+ const expired = [];
65401
+ for (const name of await (0, import_promises45.readdir)(layout.versionsDir).catch(() => [])) {
65402
+ if (kept.has(name)) continue;
65403
+ const since = retired[name] ?? now;
65404
+ if (now - since >= RETIRED_VERSION_RETENTION_MS) expired.push(name);
65405
+ else stillRetired[name] = since;
65406
+ }
65407
+ const results = await Promise.allSettled(
65408
+ expired.map((name) => (0, import_promises45.rm)((0, import_node_path46.join)(layout.versionsDir, name), { recursive: true, force: true }))
65186
65409
  );
65187
- await (0, import_promises44.rm)(layout.tmpDir, { recursive: true, force: true });
65188
- return stale.length;
65410
+ results.forEach((result, index) => {
65411
+ const name = expired[index];
65412
+ if (result.status === "rejected" && name !== void 0) stillRetired[name] = now;
65413
+ });
65414
+ if (JSON.stringify(stillRetired) !== JSON.stringify(retired)) {
65415
+ await writeJsonFileAtomic(layout.retiredFile, stillRetired);
65416
+ }
65417
+ await (0, import_promises45.rm)(layout.tmpDir, { recursive: true, force: true });
65418
+ return results.filter((result) => result.status === "fulfilled").length;
65189
65419
  }
65190
65420
  async function intactSkills(layout) {
65191
65421
  const installed = await readInstalledSkills(layout);
@@ -65211,18 +65441,24 @@ function installedRecorder(layout, present2, onRecorded) {
65211
65441
  present2.map((skill) => [skill.skillId, skill])
65212
65442
  );
65213
65443
  let chain = Promise.resolve();
65444
+ let queued = null;
65214
65445
  return {
65215
65446
  record: (skill) => {
65216
65447
  ready.set(skill.skillId, skill);
65217
- const snapshot2 = [...ready.values()];
65218
- const write = chain.then(() => writeInstalledSkills(layout, snapshot2)).then(onRecorded);
65448
+ if (queued !== null) return queued;
65449
+ const write = chain.then(() => {
65450
+ queued = null;
65451
+ return writeInstalledSkills(layout, [...ready.values()]);
65452
+ }).then(onRecorded);
65453
+ queued = write;
65219
65454
  chain = write.catch(() => void 0);
65220
65455
  return write;
65221
65456
  },
65222
65457
  settled: () => chain
65223
65458
  };
65224
65459
  }
65225
- async function applyDesired(layout, source, log, present2, response, onRecorded, signal) {
65460
+ async function applyDesired(env, present2, response, onRecorded, signal) {
65461
+ const { layout, log } = env;
65226
65462
  const held = new Map(present2.map((skill) => [skill.skillId, skill]));
65227
65463
  const downloads = new Map(
65228
65464
  response.downloads.map((download) => [download.skillId, download])
@@ -65236,21 +65472,34 @@ async function applyDesired(layout, source, log, present2, response, onRecorded,
65236
65472
  return kept ? "kept" : "failed";
65237
65473
  }
65238
65474
  try {
65239
- await install(layout, source, skill, download, signal);
65240
- await recorder.record(skill);
65241
- return "downloaded";
65475
+ await install(env, skill, download, signal);
65242
65476
  } catch (error61) {
65243
65477
  log.warn("skills.install_failed", { skillId: skill.skillId, slug: skill.slug, error: error61 });
65244
65478
  return "failed";
65245
65479
  }
65480
+ await recorder.record(skill).catch((error61) => {
65481
+ log.warn("skills.record_failed", { skillId: skill.skillId, error: error61 });
65482
+ });
65483
+ return "downloaded";
65246
65484
  };
65247
65485
  const outcomes = await mapBounded(response.skills, INSTALL_CONCURRENCY, installOne);
65248
- const installed = response.skills.filter((_, index) => outcomes[index] !== "failed");
65486
+ const installed = response.skills.flatMap((skill, index) => {
65487
+ if (outcomes[index] !== "failed") return [skill];
65488
+ const kept = held.get(skill.skillId);
65489
+ return kept === void 0 ? [] : [kept];
65490
+ });
65249
65491
  const failed = response.skills.filter((_, index) => outcomes[index] === "failed").map((skill) => skill.slug);
65250
65492
  const downloaded = outcomes.filter((outcome2) => outcome2 === "downloaded").length;
65251
65493
  await recorder.settled();
65494
+ if (signal.aborted) return { installed: installed.length, downloaded, removed: 0, failed };
65252
65495
  await writeInstalledSkills(layout, installed);
65253
- const removed = await sweep(layout, installed);
65496
+ await reconcileNativeIndex(layout, installed, {
65497
+ codexSkillsDir: env.codexSkillsDir,
65498
+ platform: env.platform
65499
+ }).catch((error61) => {
65500
+ log.warn("skills.native_index_failed", { error: error61 });
65501
+ });
65502
+ const removed = await sweep(env, installed);
65254
65503
  return { installed: installed.length, downloaded, removed, failed };
65255
65504
  }
65256
65505
  var MAX_EXCHANGES = 4;
@@ -65269,7 +65518,9 @@ async function scanLocal(layout, local) {
65269
65518
  local.scans += 1;
65270
65519
  const sequence = local.scans;
65271
65520
  const context = local.context;
65272
- const scan = await scanLocalSkills(local.options.home, context, local.cache);
65521
+ const scan = await scanLocalSkills(local.options.home, context, local.cache, "incremental", [
65522
+ layout.root
65523
+ ]);
65273
65524
  const scanned = { scan, context, key: reportKey(scan, context) };
65274
65525
  if (local.latest !== null && local.latest.sequence > sequence) return scanned;
65275
65526
  local.latest = { ...scanned, sequence };
@@ -65339,14 +65590,15 @@ async function settleLocal(layout, source, log, local, exchange3, response, sign
65339
65590
  const uploads = await uploadRequested(layout, source, log, local, response.uploads ?? [], signal);
65340
65591
  return serverLost || uploads > 0;
65341
65592
  }
65342
- async function syncOnce(layout, source, log, local, onRecorded, signal) {
65593
+ async function syncOnce(env, local, onRecorded, signal) {
65594
+ const { layout, source, log } = env;
65343
65595
  let report2 = { installed: 0, downloaded: 0, removed: 0, failed: [] };
65344
65596
  if (local !== null) await loadContext(layout, local);
65345
65597
  for (let exchange3 = 0; exchange3 < MAX_EXCHANGES; exchange3 += 1) {
65346
65598
  const present2 = await intactSkills(layout);
65347
65599
  const pending = local === null ? null : localExchange(local);
65348
65600
  const response = await source.sync(syncRequest(present2, pending), signal);
65349
- report2 = await applyDesired(layout, source, log, present2, response, onRecorded, signal);
65601
+ report2 = await applyDesired(env, present2, response, onRecorded, signal);
65350
65602
  if (local === null || pending === null) return report2;
65351
65603
  const again = await settleLocal(layout, source, log, local, pending, response, signal);
65352
65604
  if (!again) return report2;
@@ -65354,14 +65606,22 @@ async function syncOnce(layout, source, log, local, onRecorded, signal) {
65354
65606
  return report2;
65355
65607
  }
65356
65608
  function aborted2(signal) {
65357
- return new Promise((resolve12) => {
65358
- if (signal.aborted) resolve12(null);
65359
- else signal.addEventListener("abort", () => resolve12(null), { once: true });
65609
+ return new Promise((resolve13) => {
65610
+ if (signal.aborted) resolve13(null);
65611
+ else signal.addEventListener("abort", () => resolve13(null), { once: true });
65360
65612
  });
65361
65613
  }
65362
65614
  function openMachineSkills(options) {
65363
65615
  const layout = skillsLayout(options.stateDir, options.local?.home);
65364
65616
  const { source, log } = options;
65617
+ const env = {
65618
+ layout,
65619
+ source,
65620
+ log,
65621
+ codexSkillsDir: options.codexSkillsDir ?? null,
65622
+ platform: options.platform ?? process.platform,
65623
+ now: options.now ?? Date.now
65624
+ };
65365
65625
  const local = options.local === void 0 ? null : {
65366
65626
  options: options.local,
65367
65627
  cache: createLocalSkillScanCache(),
@@ -65396,7 +65656,7 @@ function openMachineSkills(options) {
65396
65656
  return task;
65397
65657
  };
65398
65658
  const run2 = () => {
65399
- const running = syncOnce(layout, source, log, local, recorded, lifetime.signal).then((report2) => {
65659
+ const running = syncOnce(env, local, recorded, lifetime.signal).then((report2) => {
65400
65660
  log.info("skills.synced", { ...report2 });
65401
65661
  return report2;
65402
65662
  }).catch((error61) => {
@@ -65427,29 +65687,29 @@ function openMachineSkills(options) {
65427
65687
  const running = flight.running;
65428
65688
  if (running !== void 0) {
65429
65689
  await running;
65430
- if ((await resolveSkillInvocations(layout, named)).kind === "resolved") return;
65690
+ if ((await resolveSkillInvocations(layout, named, "exact")).kind === "resolved") return;
65431
65691
  }
65432
65692
  await exchange3();
65433
65693
  };
65434
65694
  const rescanUntilResolved = async (named) => {
65435
65695
  for (let pass = 0; pass < 2; pass += 1) {
65436
65696
  await rescan();
65437
- if ((await resolveSkillInvocations(layout, named)).kind === "resolved") return;
65697
+ if ((await resolveSkillInvocations(layout, named, "exact")).kind === "resolved") return;
65438
65698
  }
65439
65699
  };
65440
- const recordedUntilResolved = (named, until) => new Promise((resolve12) => {
65700
+ const recordedUntilResolved = (named, until) => new Promise((resolve13) => {
65441
65701
  const done = () => {
65442
65702
  recordWatchers.delete(check3);
65443
65703
  until.removeEventListener("abort", done);
65444
- resolve12();
65704
+ resolve13();
65445
65705
  };
65446
65706
  const check3 = () => {
65447
- void resolveSkillInvocations(layout, named).then((resolution) => {
65707
+ void resolveSkillInvocations(layout, named, "exact").then((resolution) => {
65448
65708
  if (resolution.kind === "resolved") done();
65449
65709
  });
65450
65710
  };
65451
65711
  if (until.aborted) {
65452
- resolve12();
65712
+ resolve13();
65453
65713
  return;
65454
65714
  }
65455
65715
  recordWatchers.add(check3);
@@ -65461,7 +65721,7 @@ function openMachineSkills(options) {
65461
65721
  rescan,
65462
65722
  prepare: async (invocations, signal) => {
65463
65723
  const named = invocations ?? [];
65464
- if ((await resolveSkillInvocations(layout, named)).kind === "resolved") return;
65724
+ if ((await resolveSkillInvocations(layout, named, "exact")).kind === "resolved") return;
65465
65725
  const picksLocal = named.some((invocation) => invocation.kind === "local_skill");
65466
65726
  const settled2 = new AbortController();
65467
65727
  const until = AbortSignal.any([signal, AbortSignal.timeout(waitMs), settled2.signal]);
@@ -65478,15 +65738,15 @@ function openMachineSkills(options) {
65478
65738
  }
65479
65739
 
65480
65740
  // src/capabilities/workspace/index.ts
65481
- var import_node_path48 = require("path");
65741
+ var import_node_path49 = require("path");
65482
65742
  init_runtime_v2();
65483
65743
 
65484
65744
  // src/capabilities/workspace/approved-paths.ts
65485
- var import_promises45 = require("fs/promises");
65745
+ var import_promises46 = require("fs/promises");
65486
65746
  init_zod();
65487
65747
 
65488
65748
  // src/capabilities/workspace/paths.ts
65489
- var import_node_path46 = require("path");
65749
+ var import_node_path47 = require("path");
65490
65750
  function stripWin32Namespace(path4) {
65491
65751
  if (/^\\\\\?\\UNC\\/i.test(path4)) return `\\\\${path4.slice(8)}`;
65492
65752
  if (path4.startsWith("\\\\?\\")) return path4.slice(4);
@@ -65494,15 +65754,15 @@ function stripWin32Namespace(path4) {
65494
65754
  }
65495
65755
  function comparablePath(path4, platform3) {
65496
65756
  if (platform3 === "win32") {
65497
- const normalized3 = import_node_path46.win32.normalize(stripWin32Namespace(path4).replaceAll("/", "\\"));
65757
+ const normalized3 = import_node_path47.win32.normalize(stripWin32Namespace(path4).replaceAll("/", "\\"));
65498
65758
  const trimmed4 = normalized3.length > 3 || !/^[a-z]:\\$/i.test(normalized3) ? normalized3.replace(/\\+$/, "") : normalized3;
65499
65759
  return trimmed4.toLowerCase();
65500
65760
  }
65501
- const normalized2 = import_node_path46.posix.normalize(path4);
65761
+ const normalized2 = import_node_path47.posix.normalize(path4);
65502
65762
  return normalized2.length > 1 ? normalized2.replace(/\/+$/, "") : normalized2;
65503
65763
  }
65504
65764
  function isAbsoluteFor(path4, platform3) {
65505
- return platform3 === "win32" ? import_node_path46.win32.isAbsolute(path4) : import_node_path46.posix.isAbsolute(path4);
65765
+ return platform3 === "win32" ? import_node_path47.win32.isAbsolute(path4) : import_node_path47.posix.isAbsolute(path4);
65506
65766
  }
65507
65767
  function isWithin(root, candidate, platform3) {
65508
65768
  const separator = platform3 === "win32" ? "\\" : "/";
@@ -65520,7 +65780,7 @@ var storeSchema = external_exports.object({
65520
65780
  });
65521
65781
  async function realpathOrNull(path4) {
65522
65782
  try {
65523
- return await (0, import_promises45.realpath)(path4);
65783
+ return await (0, import_promises46.realpath)(path4);
65524
65784
  } catch (error61) {
65525
65785
  const code = errnoCode(error61);
65526
65786
  if (code === "ENOENT" || code === "ENOTDIR" || code === "EACCES" || code === "EPERM") {
@@ -65579,9 +65839,9 @@ async function openApprovedPaths(options) {
65579
65839
  }
65580
65840
 
65581
65841
  // src/capabilities/workspace/locks.ts
65582
- var import_node_crypto24 = require("crypto");
65583
- var import_promises46 = require("fs/promises");
65584
- var import_node_path47 = require("path");
65842
+ var import_node_crypto25 = require("crypto");
65843
+ var import_promises47 = require("fs/promises");
65844
+ var import_node_path48 = require("path");
65585
65845
  init_zod();
65586
65846
  var LOCK_FORMAT = 1;
65587
65847
  var EXCLUSIVE_FILE = "exclusive.json";
@@ -65596,12 +65856,12 @@ var ownerSchema = external_exports.object({
65596
65856
  since: external_exports.number().int().nonnegative()
65597
65857
  });
65598
65858
  function repositoryLockKey(commonDir, platform3) {
65599
- return (0, import_node_crypto24.createHash)("sha256").update(comparablePath(commonDir, platform3)).digest("hex").slice(0, 32);
65859
+ return (0, import_node_crypto25.createHash)("sha256").update(comparablePath(commonDir, platform3)).digest("hex").slice(0, 32);
65600
65860
  }
65601
65861
  async function readOwner2(path4) {
65602
65862
  let text2;
65603
65863
  try {
65604
- text2 = await (0, import_promises46.readFile)(path4, "utf8");
65864
+ text2 = await (0, import_promises47.readFile)(path4, "utf8");
65605
65865
  } catch (error61) {
65606
65866
  if (errnoCode(error61) === "ENOENT") return { kind: "missing" };
65607
65867
  return { kind: "unreadable" };
@@ -65622,7 +65882,7 @@ async function removeIfSame(path4, expected) {
65622
65882
  if (current.kind !== "owner" || current.owner.since !== expected.since) return;
65623
65883
  if (current.owner.pid !== expected.pid || current.owner.holder !== expected.holder) return;
65624
65884
  }
65625
- await (0, import_promises46.unlink)(path4).catch((error61) => {
65885
+ await (0, import_promises47.unlink)(path4).catch((error61) => {
65626
65886
  if (errnoCode(error61) !== "ENOENT") throw error61;
65627
65887
  });
65628
65888
  }
@@ -65647,7 +65907,7 @@ function openRepositoryLocks(options) {
65647
65907
  await removeIfSame(path4, read.owner);
65648
65908
  return null;
65649
65909
  }
65650
- const age = await (0, import_promises46.stat)(path4).then(
65910
+ const age = await (0, import_promises47.stat)(path4).then(
65651
65911
  (info) => clock.now() - info.mtimeMs,
65652
65912
  () => 0
65653
65913
  );
@@ -65661,13 +65921,13 @@ function openRepositoryLocks(options) {
65661
65921
  });
65662
65922
  const folder = async (commonDir) => {
65663
65923
  const key = repositoryLockKey(commonDir, platform3);
65664
- const dir = (0, import_node_path47.join)(options.dir, key);
65665
- await (0, import_promises46.mkdir)(dir, { recursive: true, mode: 448 });
65924
+ const dir = (0, import_node_path48.join)(options.dir, key);
65925
+ await (0, import_promises47.mkdir)(dir, { recursive: true, mode: 448 });
65666
65926
  return { key, dir };
65667
65927
  };
65668
65928
  const createExclusive = async (path4, owner) => {
65669
65929
  try {
65670
- const handle = await (0, import_promises46.open)(path4, "wx", 384);
65930
+ const handle = await (0, import_promises47.open)(path4, "wx", 384);
65671
65931
  try {
65672
65932
  await handle.writeFile(JSON.stringify(owner));
65673
65933
  } finally {
@@ -65680,10 +65940,10 @@ function openRepositoryLocks(options) {
65680
65940
  }
65681
65941
  };
65682
65942
  const liveRun = async (dir) => {
65683
- const entries = await (0, import_promises46.readdir)(dir);
65943
+ const entries = await (0, import_promises47.readdir)(dir);
65684
65944
  for (const entry of entries) {
65685
65945
  if (!entry.startsWith(RUN_FILE_PREFIX)) continue;
65686
- const holder = await heldBy((0, import_node_path47.join)(dir, entry));
65946
+ const holder = await heldBy((0, import_node_path48.join)(dir, entry));
65687
65947
  if (holder !== null) return holder;
65688
65948
  }
65689
65949
  return null;
@@ -65691,7 +65951,7 @@ function openRepositoryLocks(options) {
65691
65951
  return {
65692
65952
  tryExclusive: async (commonDir, operationId) => {
65693
65953
  const { key, dir } = await folder(commonDir);
65694
- const path4 = (0, import_node_path47.join)(dir, EXCLUSIVE_FILE);
65954
+ const path4 = (0, import_node_path48.join)(dir, EXCLUSIVE_FILE);
65695
65955
  const owner = await self(operationId);
65696
65956
  if (!await createExclusive(path4, owner)) {
65697
65957
  const holder = await heldBy(path4);
@@ -65709,11 +65969,11 @@ function openRepositoryLocks(options) {
65709
65969
  },
65710
65970
  tryShared: async (commonDir, runId) => {
65711
65971
  const { key, dir } = await folder(commonDir);
65712
- const file2 = `${RUN_FILE_PREFIX}${(0, import_node_crypto24.createHash)("sha256").update(runId).digest("hex").slice(0, 32)}.json`;
65713
- const path4 = (0, import_node_path47.join)(dir, file2);
65972
+ const file2 = `${RUN_FILE_PREFIX}${(0, import_node_crypto25.createHash)("sha256").update(runId).digest("hex").slice(0, 32)}.json`;
65973
+ const path4 = (0, import_node_path48.join)(dir, file2);
65714
65974
  const owner = await self(runId);
65715
65975
  await writeJsonFileAtomic(path4, owner);
65716
- const operation = await heldBy((0, import_node_path47.join)(dir, EXCLUSIVE_FILE));
65976
+ const operation = await heldBy((0, import_node_path48.join)(dir, EXCLUSIVE_FILE));
65717
65977
  if (operation !== null) {
65718
65978
  await removeIfSame(path4, owner);
65719
65979
  return { kind: "busy", holder: operation };
@@ -65813,18 +66073,18 @@ async function openWorkspaces(options) {
65813
66073
  const budgetMs = options.budgetMs ?? WORKSPACE_QUERY_BUDGET_MS;
65814
66074
  const lifetime = new AbortController();
65815
66075
  const approved = await openApprovedPaths({
65816
- file: (0, import_node_path48.join)(options.stateDir, "workspaces.json"),
66076
+ file: (0, import_node_path49.join)(options.stateDir, "workspaces.json"),
65817
66077
  log: options.log,
65818
66078
  platform: platform3
65819
66079
  });
65820
66080
  const locks = openRepositoryLocks({
65821
- dir: (0, import_node_path48.join)(options.stateDir, "locks"),
66081
+ dir: (0, import_node_path49.join)(options.stateDir, "locks"),
65822
66082
  clock: options.clock,
65823
66083
  platform: platform3
65824
66084
  });
65825
66085
  const git = createGit({
65826
66086
  env: options.env,
65827
- tmpDir: (0, import_node_path48.join)(options.stateDir, "tmp", "git"),
66087
+ tmpDir: (0, import_node_path49.join)(options.stateDir, "tmp", "git"),
65828
66088
  platform: platform3,
65829
66089
  ...options.gitPath === void 0 ? {} : { gitPath: options.gitPath },
65830
66090
  ...options.localTimeoutMs === void 0 ? {} : { localTimeoutMs: options.localTimeoutMs },
@@ -65945,11 +66205,11 @@ async function openWorkspaces(options) {
65945
66205
 
65946
66206
  // src/cli/config.ts
65947
66207
  var import_node_os11 = require("os");
65948
- var import_node_path66 = require("path");
66208
+ var import_node_path67 = require("path");
65949
66209
  init_zod();
65950
66210
 
65951
66211
  // src/client/contract.ts
65952
- var import_node_path49 = require("path");
66212
+ var import_node_path50 = require("path");
65953
66213
  init_runtime_v2();
65954
66214
  init_zod();
65955
66215
  var LOCAL_API_PROTOCOL = 1;
@@ -66122,7 +66382,7 @@ var nativeHookSignalSchema = external_exports.strictObject({
66122
66382
  provider: external_exports.enum(nativeIngestionProviders),
66123
66383
  event: external_exports.enum(nativeIngestionHookEvents),
66124
66384
  externalSessionId: external_exports.string().trim().min(1).max(200),
66125
- transcriptPath: external_exports.string().min(1).max(4096).refine(import_node_path49.isAbsolute, "transcriptPath must be absolute"),
66385
+ transcriptPath: external_exports.string().min(1).max(4096).refine(import_node_path50.isAbsolute, "transcriptPath must be absolute"),
66126
66386
  cwd: external_exports.string().max(4096).nullable(),
66127
66387
  providerTurnId: external_exports.string().max(200).nullable(),
66128
66388
  assistantFingerprint: assistantFingerprintSchema.nullable(),
@@ -66158,19 +66418,19 @@ var localApiErrorSchema = external_exports.object({
66158
66418
  });
66159
66419
 
66160
66420
  // src/client/locate.ts
66161
- var import_node_path50 = require("path");
66421
+ var import_node_path51 = require("path");
66162
66422
  var RUNTIME_PROFILES = ["production", "staging", "development", "local"];
66163
66423
  function defaultStateDir({ profile, platform: platform3, home, env }) {
66164
66424
  if (platform3 === "win32") {
66165
- return (0, import_node_path50.join)(env.LOCALAPPDATA ?? (0, import_node_path50.join)(home, "AppData", "Local"), "Alan", profile);
66425
+ return (0, import_node_path51.join)(env.LOCALAPPDATA ?? (0, import_node_path51.join)(home, "AppData", "Local"), "Alan", profile);
66166
66426
  }
66167
- return (0, import_node_path50.join)(env.XDG_STATE_HOME ?? (0, import_node_path50.join)(home, ".local", "state"), "alan", profile);
66427
+ return (0, import_node_path51.join)(env.XDG_STATE_HOME ?? (0, import_node_path51.join)(home, ".local", "state"), "alan", profile);
66168
66428
  }
66169
66429
  function defaultInstallDir({ platform: platform3, home, env }) {
66170
66430
  if (platform3 === "win32") {
66171
- return (0, import_node_path50.join)(env.LOCALAPPDATA ?? (0, import_node_path50.join)(home, "AppData", "Local"), "Alan", "runtime");
66431
+ return (0, import_node_path51.join)(env.LOCALAPPDATA ?? (0, import_node_path51.join)(home, "AppData", "Local"), "Alan", "runtime");
66172
66432
  }
66173
- return (0, import_node_path50.join)(env.XDG_DATA_HOME ?? (0, import_node_path50.join)(home, ".local", "share"), "alan", "runtime");
66433
+ return (0, import_node_path51.join)(env.XDG_DATA_HOME ?? (0, import_node_path51.join)(home, ".local", "share"), "alan", "runtime");
66174
66434
  }
66175
66435
 
66176
66436
  // src/client/machine-features-contract.ts
@@ -66229,7 +66489,7 @@ var mcpConfigResultSchema = external_exports.object({
66229
66489
  });
66230
66490
 
66231
66491
  // src/client/runtime-client.ts
66232
- var import_promises47 = require("fs/promises");
66492
+ var import_promises48 = require("fs/promises");
66233
66493
  init_acp();
66234
66494
  init_runtime_v2();
66235
66495
 
@@ -66290,7 +66550,7 @@ var DEFAULT_BACKOFF = { initialMs: 250, maxMs: 3e4 };
66290
66550
  async function readDiscovery(path4) {
66291
66551
  let text2;
66292
66552
  try {
66293
- text2 = await (0, import_promises47.readFile)(path4, "utf8");
66553
+ text2 = await (0, import_promises48.readFile)(path4, "utf8");
66294
66554
  } catch (error61) {
66295
66555
  throw new RuntimeClientError("unavailable", "The runtime is not running", { cause: error61 });
66296
66556
  }
@@ -66363,8 +66623,8 @@ function nextOffsetOf(response) {
66363
66623
  async function pause(ms, signal) {
66364
66624
  const either = AbortSignal.any([signal, AbortSignal.timeout(ms)]);
66365
66625
  if (either.aborted) return;
66366
- await new Promise((resolve12) => {
66367
- either.addEventListener("abort", () => resolve12(), { once: true });
66626
+ await new Promise((resolve13) => {
66627
+ either.addEventListener("abort", () => resolve13(), { once: true });
66368
66628
  });
66369
66629
  }
66370
66630
  function jittered(backoff, failures) {
@@ -66672,14 +66932,14 @@ async function sendNativeHookSignal(discoveryPath, hookSignal, signal) {
66672
66932
  }
66673
66933
 
66674
66934
  // src/sessions/index.ts
66675
- var import_node_crypto30 = require("crypto");
66676
- var import_promises65 = require("fs/promises");
66935
+ var import_node_crypto31 = require("crypto");
66936
+ var import_promises66 = require("fs/promises");
66677
66937
  var import_node_os10 = require("os");
66678
- var import_node_path65 = require("path");
66938
+ var import_node_path66 = require("path");
66679
66939
  init_runtime_v2();
66680
66940
 
66681
66941
  // src/holder/control-client.ts
66682
- var import_node_crypto25 = require("crypto");
66942
+ var import_node_crypto26 = require("crypto");
66683
66943
  var import_node_net2 = require("net");
66684
66944
  init_runtime_v2();
66685
66945
 
@@ -66726,8 +66986,8 @@ function isReply(message2) {
66726
66986
  async function connectHolder(endpoint, token, onEvent) {
66727
66987
  const socket = (0, import_node_net2.connect)(endpoint);
66728
66988
  const pending = /* @__PURE__ */ new Map();
66729
- const closed = new Promise((resolve12) => socket.once("close", () => resolve12()));
66730
- const ready = new Promise((resolve12, reject) => {
66989
+ const closed = new Promise((resolve13) => socket.once("close", () => resolve13()));
66990
+ const ready = new Promise((resolve13, reject) => {
66731
66991
  socket.once("error", reject);
66732
66992
  socket.once(
66733
66993
  "close",
@@ -66735,7 +66995,7 @@ async function connectHolder(endpoint, token, onEvent) {
66735
66995
  );
66736
66996
  readMessages(socket, holderMessageSchema, {
66737
66997
  onMessage: (message2) => {
66738
- if (message2.type === "ready") resolve12(message2.pid);
66998
+ if (message2.type === "ready") resolve13(message2.pid);
66739
66999
  else if (isReply(message2)) {
66740
67000
  const id = message2.id;
66741
67001
  if (id === null) return;
@@ -66749,14 +67009,14 @@ async function connectHolder(endpoint, token, onEvent) {
66749
67009
  });
66750
67010
  const pid = await ready;
66751
67011
  const request2 = (body) => {
66752
- const id = (0, import_node_crypto25.randomUUID)();
66753
- return new Promise((resolve12, reject) => {
67012
+ const id = (0, import_node_crypto26.randomUUID)();
67013
+ return new Promise((resolve13, reject) => {
66754
67014
  const timer = AbortSignal.timeout(REQUEST_TIMEOUT_MS7);
66755
67015
  timer.addEventListener("abort", () => {
66756
67016
  pending.delete(id);
66757
67017
  reject(new RuntimeFault("io_failed", "Holder did not answer"));
66758
67018
  });
66759
- pending.set(id, resolve12);
67019
+ pending.set(id, resolve13);
66760
67020
  writeMessage(socket, { ...body, id });
66761
67021
  });
66762
67022
  };
@@ -66899,7 +67159,7 @@ function createProviderDrivers(options) {
66899
67159
  }
66900
67160
 
66901
67161
  // src/holder/engine-records.ts
66902
- var import_node_path51 = require("path");
67162
+ var import_node_path52 = require("path");
66903
67163
  init_zod();
66904
67164
  var ENGINES_FILE = "engines.json";
66905
67165
  var STOP_GRACE_MS = 2e3;
@@ -66911,7 +67171,7 @@ var engineRecordSchema = external_exports.object({
66911
67171
  });
66912
67172
  var engineRecordsSchema = external_exports.object({ engines: external_exports.array(engineRecordSchema) });
66913
67173
  function engineRecordsPath(sessionDir) {
66914
- return (0, import_node_path51.join)(sessionDir, ENGINES_FILE);
67174
+ return (0, import_node_path52.join)(sessionDir, ENGINES_FILE);
66915
67175
  }
66916
67176
  function recordSpawnedEngines(path4, clock, log) {
66917
67177
  const live = /* @__PURE__ */ new Map();
@@ -66971,12 +67231,12 @@ async function reapLeftoverEngines(path4, options) {
66971
67231
  }
66972
67232
 
66973
67233
  // src/holder/launch-command.ts
66974
- var import_node_fs16 = require("fs");
66975
- var import_node_path52 = require("path");
67234
+ var import_node_fs17 = require("fs");
67235
+ var import_node_path53 = require("path");
66976
67236
  var HOLDER_BUNDLE = "alan-holder.cjs";
66977
- function holderArguments(runtimeArgs, nodeFlags, exists6 = import_node_fs16.existsSync) {
67237
+ function holderArguments(runtimeArgs, nodeFlags, exists6 = import_node_fs17.existsSync) {
66978
67238
  const bundle = runtimeArgs.at(-1);
66979
- const lean = bundle === void 0 ? void 0 : (0, import_node_path52.join)((0, import_node_path52.dirname)(bundle), HOLDER_BUNDLE);
67239
+ const lean = bundle === void 0 ? void 0 : (0, import_node_path53.join)((0, import_node_path53.dirname)(bundle), HOLDER_BUNDLE);
66980
67240
  const script = lean !== void 0 && exists6(lean) ? [...runtimeArgs.slice(0, -1), lean] : runtimeArgs;
66981
67241
  return [...nodeFlags, ...script, "hold"];
66982
67242
  }
@@ -67011,17 +67271,17 @@ function createConversationMcpAuthorization(options) {
67011
67271
  }
67012
67272
 
67013
67273
  // src/holder/mcp-helper-access.ts
67014
- var import_promises54 = require("fs/promises");
67274
+ var import_promises55 = require("fs/promises");
67015
67275
  function createHelperMcpAccess(options) {
67016
67276
  return {
67017
67277
  [Symbol.asyncDispose]: async () => {
67018
- await (0, import_promises54.rm)(options.credentialPath, { force: true });
67278
+ await (0, import_promises55.rm)(options.credentialPath, { force: true });
67019
67279
  },
67020
67280
  url: options.managedMcp.url,
67021
67281
  authorization: async (signal) => {
67022
67282
  const authorization = await options.managedMcp.authorization(signal);
67023
67283
  if (authorization === void 0 || signal.aborted) {
67024
- await (0, import_promises54.rm)(options.credentialPath, { force: true });
67284
+ await (0, import_promises55.rm)(options.credentialPath, { force: true });
67025
67285
  return void 0;
67026
67286
  }
67027
67287
  const credential = {
@@ -67036,8 +67296,8 @@ function createHelperMcpAccess(options) {
67036
67296
  }
67037
67297
 
67038
67298
  // src/holder/run-inputs.ts
67039
- var import_promises55 = require("fs/promises");
67040
- var import_node_path53 = require("path");
67299
+ var import_promises56 = require("fs/promises");
67300
+ var import_node_path54 = require("path");
67041
67301
  var NO_RUN_INPUTS = {
67042
67302
  attachments: [],
67043
67303
  providerEnv: {},
@@ -67050,18 +67310,18 @@ function safeFilename(filename) {
67050
67310
  return safe || "attachment";
67051
67311
  }
67052
67312
  async function prepareRunInputs(spec, { source, tmpDir, signal, skills = [] }) {
67053
- const dir = (0, import_node_path53.join)(tmpDir, "runs", spec.runId);
67313
+ const dir = (0, import_node_path54.join)(tmpDir, "runs", spec.runId);
67054
67314
  const cleanup = async () => {
67055
- await (0, import_promises55.rm)(dir, { recursive: true, force: true });
67315
+ await (0, import_promises56.rm)(dir, { recursive: true, force: true });
67056
67316
  };
67057
67317
  try {
67058
67318
  const credential = await source.fetchProviderCredential(spec.runId, signal);
67059
67319
  const attachments = [];
67060
- if (spec.attachments?.length) await (0, import_promises55.mkdir)(dir, { recursive: true, mode: 448 });
67320
+ if (spec.attachments?.length) await (0, import_promises56.mkdir)(dir, { recursive: true, mode: 448 });
67061
67321
  for (const [index, attachment] of (spec.attachments ?? []).entries()) {
67062
67322
  const bytes = await source.downloadAttachment(spec.runId, attachment.id, signal);
67063
- const path4 = (0, import_node_path53.join)(dir, `${index}-${safeFilename(attachment.filename)}`);
67064
- await (0, import_promises55.writeFile)(path4, bytes, { mode: 384 });
67323
+ const path4 = (0, import_node_path54.join)(dir, `${index}-${safeFilename(attachment.filename)}`);
67324
+ await (0, import_promises56.writeFile)(path4, bytes, { mode: 384 });
67065
67325
  attachments.push({
67066
67326
  id: attachment.id,
67067
67327
  kind: attachment.kind,
@@ -67088,30 +67348,30 @@ async function prepareRunInputs(spec, { source, tmpDir, signal, skills = [] }) {
67088
67348
  }
67089
67349
 
67090
67350
  // src/holder/serve.ts
67091
- var import_node_crypto29 = require("crypto");
67092
- var import_node_fs21 = require("fs");
67351
+ var import_node_crypto30 = require("crypto");
67352
+ var import_node_fs22 = require("fs");
67093
67353
  var import_node_net3 = require("net");
67094
- var import_node_path64 = require("path");
67354
+ var import_node_path65 = require("path");
67095
67355
  init_runtime_v2();
67096
67356
 
67097
67357
  // src/holder/admission.ts
67098
- var import_node_fs18 = require("fs");
67099
- var import_promises59 = require("fs/promises");
67358
+ var import_node_fs19 = require("fs");
67359
+ var import_promises60 = require("fs/promises");
67100
67360
  var import_node_os9 = require("os");
67101
- var import_node_path58 = require("path");
67361
+ var import_node_path59 = require("path");
67102
67362
  init_constants();
67103
67363
 
67104
67364
  // ../shared/dist/node/local-workspace.js
67105
- var import_node_fs17 = require("fs");
67365
+ var import_node_fs18 = require("fs");
67106
67366
  var import_node_os8 = require("os");
67107
- var import_node_path54 = require("path");
67367
+ var import_node_path55 = require("path");
67108
67368
  function resolveAlanDefaultWorkspacePath(homeDirectory = (0, import_node_os8.homedir)()) {
67109
- return (0, import_node_path54.join)(homeDirectory, ".alan", "workspace");
67369
+ return (0, import_node_path55.join)(homeDirectory, ".alan", "workspace");
67110
67370
  }
67111
67371
 
67112
67372
  // src/holder/admission-relocation.ts
67113
- var import_promises56 = require("fs/promises");
67114
- var import_node_path55 = require("path");
67373
+ var import_promises57 = require("fs/promises");
67374
+ var import_node_path56 = require("path");
67115
67375
  var MAX_RELOCATION_CANDIDATES = 200;
67116
67376
  var RELOCATION_BUDGET_MS = 2e4;
67117
67377
  function repositoryIdentity(url3) {
@@ -67146,8 +67406,8 @@ async function originIdentity(git, path4, signal) {
67146
67406
  }
67147
67407
  async function childDirectories(parent, limit) {
67148
67408
  try {
67149
- const entries = await (0, import_promises56.readdir)(parent, { withFileTypes: true });
67150
- return entries.filter((entry) => entry.isDirectory()).slice(0, limit).map((entry) => (0, import_node_path55.join)(parent, entry.name));
67409
+ const entries = await (0, import_promises57.readdir)(parent, { withFileTypes: true });
67410
+ return entries.filter((entry) => entry.isDirectory()).slice(0, limit).map((entry) => (0, import_node_path56.join)(parent, entry.name));
67151
67411
  } catch {
67152
67412
  return [];
67153
67413
  }
@@ -67155,7 +67415,7 @@ async function childDirectories(parent, limit) {
67155
67415
  async function candidateFolders(search) {
67156
67416
  const roots = /* @__PURE__ */ new Map();
67157
67417
  for (const path4 of [search.missingPath, ...search.approvedWorkspacePaths]) {
67158
- const parent = (0, import_node_path55.dirname)((0, import_node_path55.resolve)(path4));
67418
+ const parent = (0, import_node_path56.dirname)((0, import_node_path56.resolve)(path4));
67159
67419
  roots.set(comparablePath(parent, search.platform), parent);
67160
67420
  }
67161
67421
  const candidates2 = /* @__PURE__ */ new Map();
@@ -67182,9 +67442,9 @@ async function discoverRelocatedWorkspace(search) {
67182
67442
  }
67183
67443
 
67184
67444
  // src/holder/checkout-refresh.ts
67185
- var import_node_crypto27 = require("crypto");
67186
- var import_promises57 = require("fs/promises");
67187
- var import_node_path56 = require("path");
67445
+ var import_node_crypto28 = require("crypto");
67446
+ var import_promises58 = require("fs/promises");
67447
+ var import_node_path57 = require("path");
67188
67448
  function short(sha) {
67189
67449
  return sha.slice(0, 12);
67190
67450
  }
@@ -67196,8 +67456,8 @@ function staleLine(path4, snapshot2, tip) {
67196
67456
  }
67197
67457
  async function claimOnce(dir, name) {
67198
67458
  try {
67199
- await (0, import_promises57.mkdir)(dir, { recursive: true, mode: 448 });
67200
- await (await (0, import_promises57.open)((0, import_node_path56.join)(dir, name), "wx")).close();
67459
+ await (0, import_promises58.mkdir)(dir, { recursive: true, mode: 448 });
67460
+ await (await (0, import_promises58.open)((0, import_node_path57.join)(dir, name), "wx")).close();
67201
67461
  return true;
67202
67462
  } catch {
67203
67463
  return false;
@@ -67228,8 +67488,8 @@ async function fastForward(freshness, operationId, deps, signal) {
67228
67488
  }
67229
67489
  async function atFirstLease(freshness, spec, deps, signal) {
67230
67490
  const first = await claimOnce(
67231
- (0, import_node_path56.join)(deps.dir, "leased"),
67232
- (0, import_node_crypto27.createHash)("sha256").update(freshness.path).digest("hex")
67491
+ (0, import_node_path57.join)(deps.dir, "leased"),
67492
+ (0, import_node_crypto28.createHash)("sha256").update(freshness.path).digest("hex")
67233
67493
  );
67234
67494
  switch (freshness.state) {
67235
67495
  case "current":
@@ -67259,7 +67519,7 @@ async function checkoutsOf(spec, leaseTargets) {
67259
67519
  function createCheckoutRefresh(deps) {
67260
67520
  return async (spec, leaseTargets, signal) => {
67261
67521
  if (spec.providerSessionId !== void 0) return void 0;
67262
- if (!await claimOnce((0, import_node_path56.join)(deps.dir, "conversations"), spec.conversationId)) return void 0;
67522
+ if (!await claimOnce((0, import_node_path57.join)(deps.dir, "conversations"), spec.conversationId)) return void 0;
67263
67523
  const lines2 = [];
67264
67524
  for (const target of await checkoutsOf(spec, leaseTargets)) {
67265
67525
  const freshness = await readCheckoutFreshness(deps.dir, target);
@@ -67280,8 +67540,8 @@ function createCheckoutRefresh(deps) {
67280
67540
  }
67281
67541
 
67282
67542
  // src/holder/lease.ts
67283
- var import_promises58 = require("fs/promises");
67284
- var import_node_path57 = require("path");
67543
+ var import_promises59 = require("fs/promises");
67544
+ var import_node_path58 = require("path");
67285
67545
  var LEASE_CHECK_EVERY_MS = 5e3;
67286
67546
  var MAX_TRANSIENT_FAILURES = 3;
67287
67547
  var BACKOFF_BASE_MS = 1e3;
@@ -67295,8 +67555,8 @@ function identityFailure(code, workspacePath) {
67295
67555
  return { code, problemCode: "app.workspace.missing", message: MESSAGES[code], workspacePath };
67296
67556
  }
67297
67557
  async function fileIdentity(path4) {
67298
- const canonical = await (0, import_promises58.realpath)(path4);
67299
- const info = await (0, import_promises58.stat)(canonical, { bigint: true });
67558
+ const canonical = await (0, import_promises59.realpath)(path4);
67559
+ const info = await (0, import_promises59.stat)(canonical, { bigint: true });
67300
67560
  return `${canonical}:${info.dev}:${info.ino}`;
67301
67561
  }
67302
67562
  async function snapshot(git, path4, signal) {
@@ -67315,7 +67575,7 @@ async function snapshot(git, path4, signal) {
67315
67575
  workspace: await fileIdentity(path4),
67316
67576
  repository: await fileIdentity(commonDir),
67317
67577
  worktree: await fileIdentity(gitDir),
67318
- commonDir: await (0, import_promises58.realpath)(commonDir)
67578
+ commonDir: await (0, import_promises59.realpath)(commonDir)
67319
67579
  };
67320
67580
  } catch {
67321
67581
  return null;
@@ -67328,7 +67588,7 @@ async function gitValue(git, path4, args, signal) {
67328
67588
  }
67329
67589
  async function pathExists(path4) {
67330
67590
  try {
67331
- await (0, import_promises58.stat)(path4);
67591
+ await (0, import_promises59.stat)(path4);
67332
67592
  return true;
67333
67593
  } catch (error61) {
67334
67594
  return errnoCode(error61) !== "ENOENT" && errnoCode(error61) !== "ENOTDIR";
@@ -67337,19 +67597,19 @@ async function pathExists(path4) {
67337
67597
  async function hasGitMarker(path4) {
67338
67598
  let directory;
67339
67599
  try {
67340
- directory = await (0, import_promises58.realpath)(path4);
67600
+ directory = await (0, import_promises59.realpath)(path4);
67341
67601
  } catch {
67342
67602
  return true;
67343
67603
  }
67344
67604
  for (; ; ) {
67345
67605
  try {
67346
- await (0, import_promises58.stat)((0, import_node_path57.join)(directory, ".git"));
67606
+ await (0, import_promises59.stat)((0, import_node_path58.join)(directory, ".git"));
67347
67607
  return true;
67348
67608
  } catch (error61) {
67349
67609
  const code = errnoCode(error61);
67350
67610
  if (code !== "ENOENT" && code !== "ENOTDIR") return true;
67351
67611
  }
67352
- const parent = (0, import_node_path57.dirname)(directory);
67612
+ const parent = (0, import_node_path58.dirname)(directory);
67353
67613
  if (parent === directory) return false;
67354
67614
  directory = parent;
67355
67615
  }
@@ -67513,7 +67773,7 @@ function volumeRoot(path4) {
67513
67773
  }
67514
67774
  async function exists4(path4) {
67515
67775
  try {
67516
- await (0, import_promises59.stat)(path4);
67776
+ await (0, import_promises60.stat)(path4);
67517
67777
  return true;
67518
67778
  } catch {
67519
67779
  return false;
@@ -67521,10 +67781,10 @@ async function exists4(path4) {
67521
67781
  }
67522
67782
  async function inspectReadiness(path4) {
67523
67783
  try {
67524
- if (!(await (0, import_promises59.stat)(path4)).isDirectory()) {
67784
+ if (!(await (0, import_promises60.stat)(path4)).isDirectory()) {
67525
67785
  return { ready: false, missing: true, message: MESSAGES2.missing };
67526
67786
  }
67527
- await (0, import_promises59.access)(path4, import_node_fs18.constants.R_OK | import_node_fs18.constants.W_OK | import_node_fs18.constants.X_OK);
67787
+ await (0, import_promises60.access)(path4, import_node_fs19.constants.R_OK | import_node_fs19.constants.W_OK | import_node_fs19.constants.X_OK);
67528
67788
  return { ready: true };
67529
67789
  } catch (error61) {
67530
67790
  const code = errnoCode(error61) ?? "";
@@ -67602,8 +67862,8 @@ async function admitDefaultWorkspace(spec, context, skills) {
67602
67862
  const { env } = context;
67603
67863
  const path4 = resolveAlanDefaultWorkspacePath(env.HOME || env.USERPROFILE || (0, import_node_os9.homedir)());
67604
67864
  try {
67605
- await (0, import_promises59.mkdir)(path4, { recursive: true, mode: 448 });
67606
- await (0, import_promises59.access)(path4, import_node_fs18.constants.R_OK | import_node_fs18.constants.W_OK | import_node_fs18.constants.X_OK);
67865
+ await (0, import_promises60.mkdir)(path4, { recursive: true, mode: 448 });
67866
+ await (0, import_promises60.access)(path4, import_node_fs19.constants.R_OK | import_node_fs19.constants.W_OK | import_node_fs19.constants.X_OK);
67607
67867
  return {
67608
67868
  kind: "admitted",
67609
67869
  spec: { ...spec, projectPath: path4 },
@@ -67679,7 +67939,7 @@ var PROBE_TIMEOUT_MS2 = 5e3;
67679
67939
  function createHolderWorkspace(machine, clock, log) {
67680
67940
  const platform3 = machine.platform ?? process.platform;
67681
67941
  const git = createGitRunner({ env: machine.env, platform: platform3, localTimeoutMs: PROBE_TIMEOUT_MS2 });
67682
- const locks = openRepositoryLocks({ dir: (0, import_node_path58.join)(machine.stateDir, "locks"), clock, platform: platform3 });
67942
+ const locks = openRepositoryLocks({ dir: (0, import_node_path59.join)(machine.stateDir, "locks"), clock, platform: platform3 });
67683
67943
  return {
67684
67944
  admission: {
67685
67945
  env: machine.env,
@@ -67691,7 +67951,7 @@ function createHolderWorkspace(machine, clock, log) {
67691
67951
  ),
67692
67952
  approvedRoots: async () => {
67693
67953
  const approved = await openApprovedPaths({
67694
- file: (0, import_node_path58.join)(machine.stateDir, "workspaces.json"),
67954
+ file: (0, import_node_path59.join)(machine.stateDir, "workspaces.json"),
67695
67955
  log,
67696
67956
  platform: platform3
67697
67957
  });
@@ -67704,7 +67964,7 @@ function createHolderWorkspace(machine, clock, log) {
67704
67964
  git,
67705
67965
  locks,
67706
67966
  log,
67707
- dir: (0, import_node_path58.join)(machine.stateDir, "checkout-freshness")
67967
+ dir: (0, import_node_path59.join)(machine.stateDir, "checkout-freshness")
67708
67968
  })
67709
67969
  } : {}
67710
67970
  };
@@ -67732,7 +67992,7 @@ async function respondToTurn(runningRunId, gate, driver, request2) {
67732
67992
  }
67733
67993
 
67734
67994
  // src/holder/session-facts.ts
67735
- var import_promises60 = require("fs/promises");
67995
+ var import_promises61 = require("fs/promises");
67736
67996
  var CLI_RSS_CACHE_MS = 1e4;
67737
67997
  var LOGIN_PROBLEM_PREFIX = "cli.auth.";
67738
67998
  function isLoginFailure(result) {
@@ -67758,8 +68018,8 @@ function createSessionFacts(options) {
67758
68018
  const path4 = await resolveCommandOnPath(command, env, platform3);
67759
68019
  if (path4 === null) return null;
67760
68020
  try {
67761
- const real = await (0, import_promises60.realpath)(path4);
67762
- const info = await (0, import_promises60.stat)(real);
68021
+ const real = await (0, import_promises61.realpath)(path4);
68022
+ const info = await (0, import_promises61.stat)(real);
67763
68023
  return { command, key: `${real}:${info.ino}:${info.size}:${info.mtimeMs}` };
67764
68024
  } catch {
67765
68025
  return null;
@@ -67846,12 +68106,12 @@ function createSessionFacts(options) {
67846
68106
  init_acp2();
67847
68107
 
67848
68108
  // src/run-log/archive.ts
67849
- var import_promises61 = require("fs/promises");
67850
- var import_node_path59 = require("path");
68109
+ var import_promises62 = require("fs/promises");
68110
+ var import_node_path60 = require("path");
67851
68111
  init_runtime_v2();
67852
68112
  async function openRunArchive(runsDir) {
67853
- const path4 = (0, import_node_path59.join)((0, import_node_path59.dirname)(runsDir), "archived-runs.txt");
67854
- const text2 = await (0, import_promises61.readFile)(path4, "utf8").catch((error61) => {
68113
+ const path4 = (0, import_node_path60.join)((0, import_node_path60.dirname)(runsDir), "archived-runs.txt");
68114
+ const text2 = await (0, import_promises62.readFile)(path4, "utf8").catch((error61) => {
67855
68115
  if (errnoCode(error61) === "ENOENT") return "";
67856
68116
  throw error61;
67857
68117
  });
@@ -67865,7 +68125,7 @@ async function openRunArchive(runsDir) {
67865
68125
  add: async (runIds) => {
67866
68126
  const added = runIds.filter((runId) => !archived.has(runId));
67867
68127
  if (added.length === 0) return;
67868
- await (0, import_promises61.appendFile)(path4, `
68128
+ await (0, import_promises62.appendFile)(path4, `
67869
68129
  ${added.join("\n")}
67870
68130
  `, { mode: 384 });
67871
68131
  for (const runId of added) archived.add(runId);
@@ -67874,13 +68134,13 @@ ${added.join("\n")}
67874
68134
  }
67875
68135
 
67876
68136
  // src/run-log/complete.ts
67877
- var import_node_crypto28 = require("crypto");
67878
- var import_node_fs19 = require("fs");
67879
- var import_node_path61 = require("path");
68137
+ var import_node_crypto29 = require("crypto");
68138
+ var import_node_fs20 = require("fs");
68139
+ var import_node_path62 = require("path");
67880
68140
 
67881
68141
  // src/run-log/directory.ts
67882
- var import_promises62 = require("fs/promises");
67883
- var import_node_path60 = require("path");
68142
+ var import_promises63 = require("fs/promises");
68143
+ var import_node_path61 = require("path");
67884
68144
  init_runtime_v2();
67885
68145
  init_zod();
67886
68146
  var runMetaSchema = external_exports.object({
@@ -67906,17 +68166,17 @@ async function readRunMeta(path4) {
67906
68166
  return read.kind === "ok" ? read.value : null;
67907
68167
  }
67908
68168
  function runDirectory(runsDir, runId) {
67909
- const dir = (0, import_node_path60.join)(runsDir, runId);
68169
+ const dir = (0, import_node_path61.join)(runsDir, runId);
67910
68170
  return {
67911
68171
  dir,
67912
- log: (0, import_node_path60.join)(dir, "log.jsonl"),
67913
- upload: (0, import_node_path60.join)(dir, "upload.json"),
67914
- meta: (0, import_node_path60.join)(dir, "run.json")
68172
+ log: (0, import_node_path61.join)(dir, "log.jsonl"),
68173
+ upload: (0, import_node_path61.join)(dir, "upload.json"),
68174
+ meta: (0, import_node_path61.join)(dir, "run.json")
67915
68175
  };
67916
68176
  }
67917
68177
  async function isRunClaimed(runsDir, runId) {
67918
68178
  try {
67919
- return (await (0, import_promises62.stat)(runDirectory(runsDir, runId).log)).size > 0;
68179
+ return (await (0, import_promises63.stat)(runDirectory(runsDir, runId).log)).size > 0;
67920
68180
  } catch (error61) {
67921
68181
  if (errnoCode(error61) === "ENOENT") return false;
67922
68182
  throw error61;
@@ -67925,24 +68185,24 @@ async function isRunClaimed(runsDir, runId) {
67925
68185
 
67926
68186
  // src/run-log/complete.ts
67927
68187
  function writeLogFile(path4, dir, text2) {
67928
- const temp = (0, import_node_path61.join)(dir, `.log.${(0, import_node_crypto28.randomUUID)()}.tmp`);
67929
- const fd = (0, import_node_fs19.openSync)(temp, "wx", 384);
68188
+ const temp = (0, import_node_path62.join)(dir, `.log.${(0, import_node_crypto29.randomUUID)()}.tmp`);
68189
+ const fd = (0, import_node_fs20.openSync)(temp, "wx", 384);
67930
68190
  try {
67931
- (0, import_node_fs19.writeSync)(fd, text2);
67932
- (0, import_node_fs19.fsyncSync)(fd);
68191
+ (0, import_node_fs20.writeSync)(fd, text2);
68192
+ (0, import_node_fs20.fsyncSync)(fd);
67933
68193
  } finally {
67934
- (0, import_node_fs19.closeSync)(fd);
68194
+ (0, import_node_fs20.closeSync)(fd);
67935
68195
  }
67936
68196
  try {
67937
- (0, import_node_fs19.renameSync)(temp, path4);
68197
+ (0, import_node_fs20.renameSync)(temp, path4);
67938
68198
  } finally {
67939
- (0, import_node_fs19.rmSync)(temp, { force: true });
68199
+ (0, import_node_fs20.rmSync)(temp, { force: true });
67940
68200
  }
67941
68201
  }
67942
68202
  async function writeCompleteRunLog(runsDir, meta3, records) {
67943
68203
  const paths = runDirectory(runsDir, meta3.runId);
67944
68204
  if (!await isRunClaimed(runsDir, meta3.runId)) {
67945
- (0, import_node_fs19.mkdirSync)(paths.dir, { recursive: true, mode: 448 });
68205
+ (0, import_node_fs20.mkdirSync)(paths.dir, { recursive: true, mode: 448 });
67946
68206
  const text2 = records.map((record2, index) => {
67947
68207
  const line = { seq: index + 1, at: record2.at, update: record2.update };
67948
68208
  return `${JSON.stringify(line)}
@@ -67954,8 +68214,8 @@ async function writeCompleteRunLog(runsDir, meta3, records) {
67954
68214
  }
67955
68215
 
67956
68216
  // src/run-log/conversation-index.ts
67957
- var import_promises63 = require("fs/promises");
67958
- var import_node_path62 = require("path");
68217
+ var import_promises64 = require("fs/promises");
68218
+ var import_node_path63 = require("path");
67959
68219
  init_runtime_v2();
67960
68220
  init_zod();
67961
68221
  var ORDINALS_PER_SHARD = 1e3;
@@ -67972,13 +68232,13 @@ var coverageSchema = external_exports.object({
67972
68232
  nextExpectedOrdinal: external_exports.number().int().positive()
67973
68233
  });
67974
68234
  function conversationsDirectory(runsDir) {
67975
- return (0, import_node_path62.join)((0, import_node_path62.dirname)(runsDir), "conversations");
68235
+ return (0, import_node_path63.join)((0, import_node_path63.dirname)(runsDir), "conversations");
67976
68236
  }
67977
68237
  function indexDirectory(runsDir, conversationId) {
67978
- return (0, import_node_path62.join)(conversationsDirectory(runsDir), conversationId, "turn-index");
68238
+ return (0, import_node_path63.join)(conversationsDirectory(runsDir), conversationId, "turn-index");
67979
68239
  }
67980
68240
  function shardPath(runsDir, conversationId, ordinal) {
67981
- return (0, import_node_path62.join)(
68241
+ return (0, import_node_path63.join)(
67982
68242
  indexDirectory(runsDir, conversationId),
67983
68243
  `${Math.floor(ordinal / ORDINALS_PER_SHARD)}.jsonl`
67984
68244
  );
@@ -67987,10 +68247,10 @@ async function indexConversationRun(runsDir, conversationId, ordinal, assistantO
67987
68247
  const nextOrdinal = assistantOrdinal + 1;
67988
68248
  if (nextOrdinal <= ordinal) throw new Error("Assistant order must follow the prompt");
67989
68249
  const path4 = shardPath(runsDir, conversationId, ordinal);
67990
- await (0, import_promises63.mkdir)((0, import_node_path62.dirname)(path4), { recursive: true, mode: 448 });
67991
- await (0, import_promises63.appendFile)(path4, `${JSON.stringify({ ordinal, nextOrdinal, runId })}
68250
+ await (0, import_promises64.mkdir)((0, import_node_path63.dirname)(path4), { recursive: true, mode: 448 });
68251
+ await (0, import_promises64.appendFile)(path4, `${JSON.stringify({ ordinal, nextOrdinal, runId })}
67992
68252
  `, { mode: 384 });
67993
- const coveragePath = (0, import_node_path62.join)((0, import_node_path62.dirname)((0, import_node_path62.dirname)(path4)), "coverage.json");
68253
+ const coveragePath = (0, import_node_path63.join)((0, import_node_path63.dirname)((0, import_node_path63.dirname)(path4)), "coverage.json");
67994
68254
  const coverage = await readJsonFile(coveragePath, coverageSchema);
67995
68255
  const current = coverage.kind === "ok" ? coverage.value : null;
67996
68256
  const next = nextCoverage(current, ordinal, nextOrdinal);
@@ -68005,13 +68265,13 @@ function nextCoverage(current, ordinal, nextOrdinal) {
68005
68265
  return null;
68006
68266
  }
68007
68267
  async function readConversationIndexCoverage(runsDir, conversationId) {
68008
- const path4 = (0, import_node_path62.join)((0, import_node_path62.dirname)(indexDirectory(runsDir, conversationId)), "coverage.json");
68268
+ const path4 = (0, import_node_path63.join)((0, import_node_path63.dirname)(indexDirectory(runsDir, conversationId)), "coverage.json");
68009
68269
  const result = await readJsonFile(path4, coverageSchema);
68010
68270
  return result.kind === "ok" ? result.value : null;
68011
68271
  }
68012
68272
  async function readConversationRunIndex(runsDir, conversationId, before, limit) {
68013
68273
  const directory = indexDirectory(runsDir, conversationId);
68014
- const names = await (0, import_promises63.readdir)(directory).catch((error61) => {
68274
+ const names = await (0, import_promises64.readdir)(directory).catch((error61) => {
68015
68275
  if (error61.code === "ENOENT") return [];
68016
68276
  throw error61;
68017
68277
  });
@@ -68020,7 +68280,7 @@ async function readConversationRunIndex(runsDir, conversationId, before, limit)
68020
68280
  ).sort((left, right) => right - left);
68021
68281
  const selected = [];
68022
68282
  for (const shard of shards) {
68023
- const text2 = await (0, import_promises63.readFile)((0, import_node_path62.join)(directory, `${shard}.jsonl`), "utf8");
68283
+ const text2 = await (0, import_promises64.readFile)((0, import_node_path63.join)(directory, `${shard}.jsonl`), "utf8");
68024
68284
  const records = text2.split("\n").flatMap((line) => {
68025
68285
  if (!line) return [];
68026
68286
  const parsed = indexRecordSchema.parse(JSON.parse(line));
@@ -68045,7 +68305,7 @@ async function readIndexableRun(runsDir, name) {
68045
68305
  return { conversationId: meta3.conversationId, ordinal, assistantOrdinal, runId: runId.data };
68046
68306
  }
68047
68307
  async function readIndexableRuns(runsDir) {
68048
- const names = await (0, import_promises63.readdir)(runsDir).catch(() => []);
68308
+ const names = await (0, import_promises64.readdir)(runsDir).catch(() => []);
68049
68309
  const byConversation = /* @__PURE__ */ new Map();
68050
68310
  let next = 0;
68051
68311
  const worker = async () => {
@@ -68075,21 +68335,21 @@ async function writeConversationIndex(directory, runs) {
68075
68335
  else lines2.push(line);
68076
68336
  coverage = nextCoverage(coverage, run2.ordinal, nextOrdinal) ?? coverage;
68077
68337
  }
68078
- await (0, import_promises63.mkdir)((0, import_node_path62.join)(directory, "turn-index"), { recursive: true, mode: 448 });
68338
+ await (0, import_promises64.mkdir)((0, import_node_path63.join)(directory, "turn-index"), { recursive: true, mode: 448 });
68079
68339
  for (const [shard, lines2] of shards) {
68080
- await (0, import_promises63.writeFile)((0, import_node_path62.join)(directory, "turn-index", `${shard}.jsonl`), `${lines2.join("\n")}
68340
+ await (0, import_promises64.writeFile)((0, import_node_path63.join)(directory, "turn-index", `${shard}.jsonl`), `${lines2.join("\n")}
68081
68341
  `, {
68082
68342
  mode: 384
68083
68343
  });
68084
68344
  }
68085
- await (0, import_promises63.writeFile)((0, import_node_path62.join)(directory, "coverage.json"), `${JSON.stringify(coverage)}
68345
+ await (0, import_promises64.writeFile)((0, import_node_path63.join)(directory, "coverage.json"), `${JSON.stringify(coverage)}
68086
68346
  `, {
68087
68347
  mode: 384
68088
68348
  });
68089
68349
  }
68090
68350
  async function rebuildConversationIndexes(runsDir) {
68091
68351
  const root = conversationsDirectory(runsDir);
68092
- const exists6 = await (0, import_promises63.stat)(root).then(
68352
+ const exists6 = await (0, import_promises64.stat)(root).then(
68093
68353
  () => true,
68094
68354
  (error61) => {
68095
68355
  if (errnoCode(error61) === "ENOENT") return false;
@@ -68098,18 +68358,18 @@ async function rebuildConversationIndexes(runsDir) {
68098
68358
  );
68099
68359
  if (exists6) return 0;
68100
68360
  const building = `${root}.rebuilding`;
68101
- await (0, import_promises63.rm)(building, { recursive: true, force: true });
68102
- await (0, import_promises63.mkdir)(building, { recursive: true, mode: 448 });
68361
+ await (0, import_promises64.rm)(building, { recursive: true, force: true });
68362
+ await (0, import_promises64.mkdir)(building, { recursive: true, mode: 448 });
68103
68363
  const byConversation = await readIndexableRuns(runsDir);
68104
68364
  for (const [conversationId, runs] of byConversation) {
68105
- await writeConversationIndex((0, import_node_path62.join)(building, conversationId), runs);
68365
+ await writeConversationIndex((0, import_node_path63.join)(building, conversationId), runs);
68106
68366
  }
68107
- await (0, import_promises63.rename)(building, root);
68367
+ await (0, import_promises64.rename)(building, root);
68108
68368
  return byConversation.size;
68109
68369
  }
68110
68370
 
68111
68371
  // src/run-log/reader.ts
68112
- var import_promises64 = require("fs/promises");
68372
+ var import_promises65 = require("fs/promises");
68113
68373
  init_runtime_v2();
68114
68374
 
68115
68375
  // src/run-log/tail.ts
@@ -68132,7 +68392,7 @@ function firstRecordLength(bytes) {
68132
68392
  return bytes.indexOf(RUN_LOG_RECORD_SEPARATOR) + 1;
68133
68393
  }
68134
68394
  async function openRunLogReader(path4) {
68135
- const handle = await (0, import_promises64.open)(path4, "r");
68395
+ const handle = await (0, import_promises65.open)(path4, "r");
68136
68396
  const readAt = async (position, length) => {
68137
68397
  const buffer = Buffer.alloc(length);
68138
68398
  const { bytesRead } = await handle.read(buffer, 0, length, position);
@@ -68166,7 +68426,7 @@ async function openRunLogReader(path4) {
68166
68426
  };
68167
68427
  }
68168
68428
  async function readLastRecord(path4) {
68169
- const handle = await (0, import_promises64.open)(path4, "r").catch(() => null);
68429
+ const handle = await (0, import_promises65.open)(path4, "r").catch(() => null);
68170
68430
  if (handle === null) return null;
68171
68431
  try {
68172
68432
  const { size } = await handle.stat();
@@ -68199,13 +68459,13 @@ function runEnded(input2) {
68199
68459
  var decoder = new TextDecoder();
68200
68460
 
68201
68461
  // src/run-log/writer.ts
68202
- var import_node_fs20 = require("fs");
68203
- var import_node_path63 = require("path");
68462
+ var import_node_fs21 = require("fs");
68463
+ var import_node_path64 = require("path");
68204
68464
  init_runtime_v2();
68205
68465
  function lastSeq(fd, size) {
68206
68466
  for (const length of tailWindows(size)) {
68207
68467
  const buffer = Buffer.alloc(length);
68208
- (0, import_node_fs20.readSync)(fd, buffer, 0, length, size - length);
68468
+ (0, import_node_fs21.readSync)(fd, buffer, 0, length, size - length);
68209
68469
  const last = lastLine(buffer.toString("utf8").trimEnd(), length === size);
68210
68470
  if (last === void 0) continue;
68211
68471
  if (last.length === 0) return 0;
@@ -68216,13 +68476,13 @@ function lastSeq(fd, size) {
68216
68476
  throw new RuntimeFault("record_too_large", "Run log tail record is larger than any record");
68217
68477
  }
68218
68478
  function openRunLog(path4, clock) {
68219
- (0, import_node_fs20.mkdirSync)((0, import_node_path63.dirname)(path4), { recursive: true, mode: 448 });
68220
- const fd = (0, import_node_fs20.openSync)(path4, "a+", 384);
68221
- let size = (0, import_node_fs20.fstatSync)(fd).size;
68479
+ (0, import_node_fs21.mkdirSync)((0, import_node_path64.dirname)(path4), { recursive: true, mode: 448 });
68480
+ const fd = (0, import_node_fs21.openSync)(path4, "a+", 384);
68481
+ let size = (0, import_node_fs21.fstatSync)(fd).size;
68222
68482
  let seq = lastSeq(fd, size);
68223
68483
  let dirty = false;
68224
68484
  const sync = () => {
68225
- (0, import_node_fs20.fsyncSync)(fd);
68485
+ (0, import_node_fs21.fsyncSync)(fd);
68226
68486
  dirty = false;
68227
68487
  };
68228
68488
  return {
@@ -68236,7 +68496,7 @@ function openRunLog(path4, clock) {
68236
68496
  };
68237
68497
  const line = Buffer.from(`${JSON.stringify(record2)}
68238
68498
  `, "utf8");
68239
- (0, import_node_fs20.writeSync)(fd, line);
68499
+ (0, import_node_fs21.writeSync)(fd, line);
68240
68500
  size += line.length;
68241
68501
  dirty = true;
68242
68502
  if (isRunLifecycleKind(update.sessionUpdate)) sync();
@@ -68248,7 +68508,7 @@ function openRunLog(path4, clock) {
68248
68508
  },
68249
68509
  [Symbol.dispose]: () => {
68250
68510
  if (dirty) sync();
68251
- (0, import_node_fs20.closeSync)(fd);
68511
+ (0, import_node_fs21.closeSync)(fd);
68252
68512
  }
68253
68513
  };
68254
68514
  }
@@ -68533,12 +68793,12 @@ var TASK_UNSUPPORTED = {
68533
68793
  message: "This agent cannot stop one background task."
68534
68794
  };
68535
68795
  function sha2564(value2) {
68536
- return (0, import_node_crypto29.createHash)("sha256").update(value2).digest("hex");
68796
+ return (0, import_node_crypto30.createHash)("sha256").update(value2).digest("hex");
68537
68797
  }
68538
68798
  function tokenMatches(expected, presented) {
68539
68799
  const a = Buffer.from(sha2564(expected), "hex");
68540
68800
  const b = Buffer.from(sha2564(presented), "hex");
68541
- return (0, import_node_crypto29.timingSafeEqual)(a, b);
68801
+ return (0, import_node_crypto30.timingSafeEqual)(a, b);
68542
68802
  }
68543
68803
  async function runHolder({
68544
68804
  launch,
@@ -68552,7 +68812,7 @@ async function runHolder({
68552
68812
  try {
68553
68813
  const identity = await readProcessIdentity(process.pid);
68554
68814
  if (identity === null) throw new RuntimeFault("internal", "Cannot read own process identity");
68555
- const _engines = __using(_stack, recordSpawnedEngines(engineRecordsPath((0, import_node_path64.dirname)(launch.statusPath)), clock, log));
68815
+ const _engines = __using(_stack, recordSpawnedEngines(engineRecordsPath((0, import_node_path65.dirname)(launch.statusPath)), clock, log));
68556
68816
  const holder = {
68557
68817
  state: "idle",
68558
68818
  runId: null,
@@ -68748,17 +69008,17 @@ async function runHolder({
68748
69008
  client.on("error", () => holder.clients.delete(client));
68749
69009
  });
68750
69010
  removeStaleEndpoint(launch.endpoint);
68751
- await new Promise((resolve12, reject) => {
69011
+ await new Promise((resolve13, reject) => {
68752
69012
  server.once("error", reject);
68753
- server.listen(launch.endpoint, () => resolve12());
69013
+ server.listen(launch.endpoint, () => resolve13());
68754
69014
  });
68755
69015
  await writeStatus();
68756
69016
  log.info("holder.ready", { conversationId: launch.conversationId, pid: identity.pid });
68757
- await new Promise((resolve12) => exit.signal.addEventListener("abort", () => resolve12()));
69017
+ await new Promise((resolve13) => exit.signal.addEventListener("abort", () => resolve13()));
68758
69018
  await driver.suspend?.().catch((error61) => log.warn("holder.driver_suspend_failed", { error: error61 }));
68759
69019
  for (const client of holder.clients) client.end();
68760
- await new Promise((resolve12) => server.close(() => resolve12()));
68761
- (0, import_node_fs21.rmSync)(launch.statusPath, { force: true });
69020
+ await new Promise((resolve13) => server.close(() => resolve13()));
69021
+ (0, import_node_fs22.rmSync)(launch.statusPath, { force: true });
68762
69022
  log.info("holder.suspended", { conversationId: launch.conversationId });
68763
69023
  } catch (_) {
68764
69024
  var _error = _, _hasError = true;
@@ -68846,7 +69106,7 @@ var DEFAULT_MAX_ACTIVE_RUNS = 32;
68846
69106
  var HOLDER_BUSY = "busy";
68847
69107
  async function listIds(dir, schema) {
68848
69108
  const ids = [];
68849
- for (const name of await (0, import_promises65.readdir)(dir).catch(() => [])) {
69109
+ for (const name of await (0, import_promises66.readdir)(dir).catch(() => [])) {
68850
69110
  const parsed = schema.safeParse(name);
68851
69111
  if (parsed.success) ids.push(parsed.data);
68852
69112
  }
@@ -68860,14 +69120,14 @@ function holderIdentity(status) {
68860
69120
  return command === void 0 ? { pid, startedAt } : { pid, startedAt, command };
68861
69121
  }
68862
69122
  function sessionFiles(paths, conversationId) {
68863
- const dir = (0, import_node_path65.join)(paths.sessions, conversationId);
68864
- return { dir, launch: (0, import_node_path65.join)(dir, "launch.json"), status: (0, import_node_path65.join)(dir, "holder.json") };
69123
+ const dir = (0, import_node_path66.join)(paths.sessions, conversationId);
69124
+ return { dir, launch: (0, import_node_path66.join)(dir, "launch.json"), status: (0, import_node_path66.join)(dir, "holder.json") };
68865
69125
  }
68866
69126
  async function removeHolderFiles(files) {
68867
69127
  for (const path4 of [files.launch, files.status, engineRecordsPath(files.dir)]) {
68868
- await (0, import_promises65.rm)(path4, { force: true });
69128
+ await (0, import_promises66.rm)(path4, { force: true });
68869
69129
  }
68870
- await (0, import_promises65.rmdir)(files.dir).catch((error61) => {
69130
+ await (0, import_promises66.rmdir)(files.dir).catch((error61) => {
68871
69131
  if (!["ENOENT", "ENOTEMPTY", "EEXIST"].includes(errnoCode(error61) ?? "")) throw error61;
68872
69132
  });
68873
69133
  }
@@ -69030,8 +69290,8 @@ async function openSessions(deps) {
69030
69290
  protocol: HOLDER_PROTOCOL,
69031
69291
  conversationId,
69032
69292
  machineId: deps.machineId,
69033
- endpoint: ipcEndpoint(paths.sockets, (0, import_node_crypto30.randomUUID)().slice(0, 8)),
69034
- token: (0, import_node_crypto30.randomBytes)(32).toString("hex"),
69293
+ endpoint: ipcEndpoint(paths.sockets, (0, import_node_crypto31.randomUUID)().slice(0, 8)),
69294
+ token: (0, import_node_crypto31.randomBytes)(32).toString("hex"),
69035
69295
  runsDir: paths.runs,
69036
69296
  statusPath: files.status
69037
69297
  };
@@ -69057,7 +69317,7 @@ async function openSessions(deps) {
69057
69317
  const meta3 = await readRunMeta(dir.meta);
69058
69318
  const last = await readLastRecord(dir.log);
69059
69319
  if (meta3 === null || last === null) return null;
69060
- const logged = await (0, import_promises65.stat)(dir.log).catch((error61) => {
69320
+ const logged = await (0, import_promises66.stat)(dir.log).catch((error61) => {
69061
69321
  if (errnoCode(error61) === "ENOENT") return null;
69062
69322
  throw error61;
69063
69323
  });
@@ -69282,7 +69542,8 @@ var envSchema = external_exports.object({
69282
69542
  ALAN_RUNTIME_GIT_GATEWAY_URL: external_exports.url().optional(),
69283
69543
  ALAN_RUNTIME_WORKSPACE_ROOT: external_exports.string().min(1).optional(),
69284
69544
  XDG_CONFIG_HOME: external_exports.string().min(1).optional(),
69285
- GH_CONFIG_DIR: external_exports.string().min(1).optional()
69545
+ GH_CONFIG_DIR: external_exports.string().min(1).optional(),
69546
+ CODEX_HOME: external_exports.string().trim().min(1).optional()
69286
69547
  });
69287
69548
  var DEFAULT_API_URLS = {
69288
69549
  production: "https://api.tryalan.ai",
@@ -69335,7 +69596,8 @@ function loadRuntimeConfig(env = process.env, totalMemoryBytes = (0, import_node
69335
69596
  ALAN_RUNTIME_GIT_GATEWAY_URL,
69336
69597
  ALAN_RUNTIME_WORKSPACE_ROOT,
69337
69598
  XDG_CONFIG_HOME,
69338
- GH_CONFIG_DIR
69599
+ GH_CONFIG_DIR,
69600
+ CODEX_HOME
69339
69601
  } = parsed.data;
69340
69602
  const home = (0, import_node_os11.homedir)();
69341
69603
  const suspendDefaults = defaultSuspendPolicy(totalMemoryBytes);
@@ -69367,7 +69629,8 @@ function loadRuntimeConfig(env = process.env, totalMemoryBytes = (0, import_node
69367
69629
  providerProbes: ALAN_RUNTIME_PROVIDER_PROBES === "on",
69368
69630
  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,
69369
69631
  home,
69370
- configHome: XDG_CONFIG_HOME ?? (0, import_node_path66.join)(home, ".config"),
69632
+ configHome: XDG_CONFIG_HOME ?? (0, import_node_path67.join)(home, ".config"),
69633
+ codexHome: resolveCodexHome(CODEX_HOME, home),
69371
69634
  ...githubProxyConfig({ ALAN_RUNTIME_GITHUB_PROXY, XDG_CONFIG_HOME, GH_CONFIG_DIR }, home),
69372
69635
  gitGatewayUrl: ALAN_RUNTIME_GIT_GATEWAY_URL ?? null,
69373
69636
  workspaceRoot: ALAN_RUNTIME_WORKSPACE_ROOT ?? null,
@@ -69375,11 +69638,14 @@ function loadRuntimeConfig(env = process.env, totalMemoryBytes = (0, import_node
69375
69638
  adoptsLegacyInstall: ALAN_RUNTIME_STATE_DIR === void 0
69376
69639
  };
69377
69640
  }
69641
+ function resolveCodexHome(configuredHome, home) {
69642
+ return configuredHome ?? (0, import_node_path67.join)(home, ".codex");
69643
+ }
69378
69644
  function githubProxyConfig(env, home) {
69379
- const configHome = env.XDG_CONFIG_HOME ?? (0, import_node_path66.join)(home, ".config");
69645
+ const configHome = env.XDG_CONFIG_HOME ?? (0, import_node_path67.join)(home, ".config");
69380
69646
  return {
69381
69647
  githubProxy: env.ALAN_RUNTIME_GITHUB_PROXY === "on",
69382
- ghConfigDir: env.GH_CONFIG_DIR ?? (0, import_node_path66.join)(configHome, "gh")
69648
+ ghConfigDir: env.GH_CONFIG_DIR ?? (0, import_node_path67.join)(configHome, "gh")
69383
69649
  };
69384
69650
  }
69385
69651
  function serviceEnvironment2(env, profile) {
@@ -69437,9 +69703,9 @@ function takeEnrollmentCodeFromEnv(env = process.env) {
69437
69703
  }
69438
69704
 
69439
69705
  // src/cli/context.ts
69440
- var import_promises66 = require("fs/promises");
69706
+ var import_promises67 = require("fs/promises");
69441
69707
  var import_node_os12 = require("os");
69442
- var import_node_path67 = require("path");
69708
+ var import_node_path68 = require("path");
69443
69709
  var DESKTOP_BUNDLE_IDS = {
69444
69710
  production: ["com.alan-ai.desktop"],
69445
69711
  staging: ["com.alan-ai.desktop.staging"],
@@ -69479,7 +69745,7 @@ function serviceSpec({ config: config2, paths, self }) {
69479
69745
  profile: config2.profile,
69480
69746
  program: serviceCommand(config2.host, self, launcher),
69481
69747
  environment: config2.serviceEnvironment,
69482
- logPath: (0, import_node_path67.join)(paths.logs, "service.log"),
69748
+ logPath: (0, import_node_path68.join)(paths.logs, "service.log"),
69483
69749
  associatedBundleIds: DESKTOP_BUNDLE_IDS[config2.profile]
69484
69750
  };
69485
69751
  }
@@ -69487,7 +69753,7 @@ async function installedServiceSpec(ctx) {
69487
69753
  const spec = serviceSpec(ctx);
69488
69754
  if (ctx.config.host === "app") return spec;
69489
69755
  const layout = installLayout(ctx.config.installDir, ctx.config.profile);
69490
- const installed = await (0, import_promises66.access)(layout.launcher).then(
69756
+ const installed = await (0, import_promises67.access)(layout.launcher).then(
69491
69757
  () => true,
69492
69758
  () => false
69493
69759
  );
@@ -69615,7 +69881,7 @@ var manifestRevisionSchema = external_exports.object({ revision: external_export
69615
69881
  async function manifestRevision(path4) {
69616
69882
  let raw;
69617
69883
  try {
69618
- raw = JSON.parse(await (0, import_promises67.readFile)(path4, "utf8"));
69884
+ raw = JSON.parse(await (0, import_promises68.readFile)(path4, "utf8"));
69619
69885
  } catch (error61) {
69620
69886
  throw new RuntimeFault("invalid_file", `Cannot read the skill manifest at ${path4}`, {
69621
69887
  cause: error61
@@ -69633,7 +69899,7 @@ async function runSkills(argv) {
69633
69899
  case "scan":
69634
69900
  writeJson({
69635
69901
  status: "failed",
69636
- attemptId: (0, import_node_crypto31.randomUUID)(),
69902
+ attemptId: (0, import_node_crypto32.randomUUID)(),
69637
69903
  retainedInventoryRevision: null,
69638
69904
  diagnostics: [
69639
69905
  { code: "RUNTIME_SKILL_SCAN_UNSUPPORTED", message: SKILLS_SYNCED_BY_RUNTIME }
@@ -69649,7 +69915,7 @@ async function runSkills(argv) {
69649
69915
  );
69650
69916
  }
69651
69917
  writeJson({
69652
- attemptId: (0, import_node_crypto31.randomUUID)(),
69918
+ attemptId: (0, import_node_crypto32.randomUUID)(),
69653
69919
  desiredRevision: await manifestRevision(manifest),
69654
69920
  skills: []
69655
69921
  });
@@ -69669,8 +69935,8 @@ async function runSkills(argv) {
69669
69935
  }
69670
69936
 
69671
69937
  // src/cli/commands/doctor.ts
69672
- var import_promises70 = require("fs/promises");
69673
- var import_node_path71 = require("path");
69938
+ var import_promises71 = require("fs/promises");
69939
+ var import_node_path72 = require("path");
69674
69940
  init_runtime_v2();
69675
69941
 
69676
69942
  // src/identity/credential.ts
@@ -69847,24 +70113,24 @@ async function authorizeDevice(input2) {
69847
70113
  }
69848
70114
 
69849
70115
  // src/identity/enroll.ts
69850
- var import_promises68 = require("fs/promises");
70116
+ var import_promises69 = require("fs/promises");
69851
70117
  init_runtime_v2();
69852
70118
 
69853
70119
  // src/identity/installation.ts
69854
- var import_node_crypto32 = require("crypto");
69855
- var import_node_path68 = require("path");
70120
+ var import_node_crypto33 = require("crypto");
70121
+ var import_node_path69 = require("path");
69856
70122
  init_zod();
69857
70123
  var installationFileSchema = external_exports.object({
69858
70124
  installationId: external_exports.uuid()
69859
70125
  });
69860
70126
  function installationPath(paths) {
69861
- return (0, import_node_path68.join)(paths.stateDir, "installation.json");
70127
+ return (0, import_node_path69.join)(paths.stateDir, "installation.json");
69862
70128
  }
69863
70129
  async function ensureInstallationId(paths) {
69864
70130
  const path4 = installationPath(paths);
69865
70131
  const existing = await readJsonFile(path4, installationFileSchema);
69866
70132
  if (existing.kind === "ok") return existing.value.installationId;
69867
- const created = { installationId: (0, import_node_crypto32.randomUUID)() };
70133
+ const created = { installationId: (0, import_node_crypto33.randomUUID)() };
69868
70134
  await writeJsonFileAtomic(path4, created);
69869
70135
  return created.installationId;
69870
70136
  }
@@ -69951,13 +70217,13 @@ async function enrollFromGrantFile(input2) {
69951
70217
  clock: input2.clock,
69952
70218
  access: input2.access
69953
70219
  });
69954
- await (0, import_promises68.rm)(input2.grantPath, { force: true });
70220
+ await (0, import_promises69.rm)(input2.grantPath, { force: true });
69955
70221
  return machine;
69956
70222
  }
69957
70223
 
69958
70224
  // src/identity/migrate-v1.ts
69959
- var import_promises69 = require("fs/promises");
69960
- var import_node_path69 = require("path");
70225
+ var import_promises70 = require("fs/promises");
70226
+ var import_node_path70 = require("path");
69961
70227
  init_runtime_v2();
69962
70228
  init_zod();
69963
70229
  var EXIT_POLL_MS = 200;
@@ -69978,11 +70244,11 @@ var ownerLeaseSchema = external_exports.looseObject({ pid: external_exports.numb
69978
70244
  function legacyConfigPath(home, profile) {
69979
70245
  switch (profile) {
69980
70246
  case "production":
69981
- return (0, import_node_path69.join)(home, ".alan", "agent", "config.json");
70247
+ return (0, import_node_path70.join)(home, ".alan", "agent", "config.json");
69982
70248
  case "staging":
69983
- return (0, import_node_path69.join)(home, ".alan-staging", "agent", "config.json");
70249
+ return (0, import_node_path70.join)(home, ".alan-staging", "agent", "config.json");
69984
70250
  default:
69985
- return (0, import_node_path69.join)(home, ".alan-dev", "agent", "config.json");
70251
+ return (0, import_node_path70.join)(home, ".alan-dev", "agent", "config.json");
69986
70252
  }
69987
70253
  }
69988
70254
  async function findLegacyInstall(home, profile) {
@@ -70007,8 +70273,8 @@ async function scrubLegacyInstall(install2) {
70007
70273
  const scrubbed = { ...install2.config, migratedToRuntimeV2: true };
70008
70274
  for (const key of SCRUBBED_KEYS) delete scrubbed[key];
70009
70275
  await writeJsonFileAtomic(`${install2.configPath}.migrated-v1`, scrubbed);
70010
- await (0, import_promises69.rm)(install2.configPath, { force: true });
70011
- await (0, import_promises69.rm)(install2.ownerLeasePath, { force: true });
70276
+ await (0, import_promises70.rm)(install2.configPath, { force: true });
70277
+ await (0, import_promises70.rm)(install2.ownerLeasePath, { force: true });
70012
70278
  }
70013
70279
  async function exchangeCredential(deps) {
70014
70280
  const { config: config2 } = deps.install;
@@ -70117,7 +70383,7 @@ async function loadIdentity(paths, options = {}) {
70117
70383
  }
70118
70384
 
70119
70385
  // src/cli/commands/status.ts
70120
- var import_node_path70 = require("path");
70386
+ var import_node_path71 = require("path");
70121
70387
  async function serviceStatus(ctx) {
70122
70388
  try {
70123
70389
  return await createServiceManager(ctx.host, ctx.config.profile).status();
@@ -70144,7 +70410,7 @@ async function runtimeState(ctx) {
70144
70410
  const running = await readRunningRuntime(ctx.paths.lock);
70145
70411
  if (running === null) return { state: "offline", pid: null, localApi: null };
70146
70412
  const discovery = await readJsonFile(
70147
- (0, import_node_path70.join)(ctx.paths.stateDir, LOCAL_API_DISCOVERY_FILE),
70413
+ (0, import_node_path71.join)(ctx.paths.stateDir, LOCAL_API_DISCOVERY_FILE),
70148
70414
  localApiDiscoverySchema
70149
70415
  );
70150
70416
  const localApi = discovery.kind === "ok" && discovery.value.pid === running.pid ? {
@@ -70365,7 +70631,7 @@ async function runtimeCheck(ctx, status) {
70365
70631
  return check2("runtime", "warn", "No runtime is running for this profile");
70366
70632
  }
70367
70633
  const client = createRuntimeClient({
70368
- discoveryPath: (0, import_node_path71.join)(ctx.paths.stateDir, LOCAL_API_DISCOVERY_FILE)
70634
+ discoveryPath: (0, import_node_path72.join)(ctx.paths.stateDir, LOCAL_API_DISCOVERY_FILE)
70369
70635
  });
70370
70636
  try {
70371
70637
  const live = await client.status(AbortSignal.timeout(LOCAL_TIMEOUT_MS));
@@ -70392,7 +70658,7 @@ async function runtimeCheck(ctx, status) {
70392
70658
  }
70393
70659
  }
70394
70660
  async function probeHolder(dir, conversationId) {
70395
- const launch = await readJsonFile((0, import_node_path71.join)(dir, "launch.json"), holderLaunchSchema);
70661
+ const launch = await readJsonFile((0, import_node_path72.join)(dir, "launch.json"), holderLaunchSchema);
70396
70662
  if (launch.kind !== "ok") return null;
70397
70663
  try {
70398
70664
  const reply2 = await withTimeout(
@@ -70417,8 +70683,8 @@ async function probeHolder(dir, conversationId) {
70417
70683
  }
70418
70684
  }
70419
70685
  async function holdersCheck(ctx) {
70420
- const names = await (0, import_promises70.readdir)(ctx.paths.sessions).catch(() => []);
70421
- const holders = (await Promise.all(names.map((name) => probeHolder((0, import_node_path71.join)(ctx.paths.sessions, name), name)))).filter((facts) => facts !== null);
70686
+ const names = await (0, import_promises71.readdir)(ctx.paths.sessions).catch(() => []);
70687
+ const holders = (await Promise.all(names.map((name) => probeHolder((0, import_node_path72.join)(ctx.paths.sessions, name), name)))).filter((facts) => facts !== null);
70422
70688
  const dead = holders.filter((holder) => !holder.alive).length;
70423
70689
  return check2(
70424
70690
  "holders",
@@ -70429,10 +70695,10 @@ async function holdersCheck(ctx) {
70429
70695
  }
70430
70696
  async function freeBytesAt(path4) {
70431
70697
  try {
70432
- const stats = await (0, import_promises70.statfs)(path4);
70698
+ const stats = await (0, import_promises71.statfs)(path4);
70433
70699
  return { path: path4, freeBytes: stats.bavail * stats.bsize };
70434
70700
  } catch (error61) {
70435
- const parent = (0, import_node_path71.dirname)(path4);
70701
+ const parent = (0, import_node_path72.dirname)(path4);
70436
70702
  if (parent === path4) throw error61;
70437
70703
  return freeBytesAt(parent);
70438
70704
  }
@@ -70450,9 +70716,9 @@ async function diskCheck(ctx) {
70450
70716
  }
70451
70717
  }
70452
70718
  var resolveFromLoginShell = (own2) => resolveCliEnvironment({ env: own2, platform: process.platform });
70453
- async function cliDiscoveryCheck(resolve12) {
70719
+ async function cliDiscoveryCheck(resolve13) {
70454
70720
  const own2 = readCliEnvironment();
70455
- const env = await resolve12(own2);
70721
+ const env = await resolve13(own2);
70456
70722
  const delimiter = process.platform === "win32" ? ";" : ":";
70457
70723
  const ownDirs = new Set((own2.PATH ?? "").split(delimiter));
70458
70724
  const added = (env.PATH ?? "").split(delimiter).filter((dir) => dir.length > 0 && !ownDirs.has(dir));
@@ -70568,7 +70834,7 @@ async function runDoctor(argv, context = cliContext) {
70568
70834
  }
70569
70835
 
70570
70836
  // src/cli/commands/git-credential.ts
70571
- var import_promises71 = require("fs/promises");
70837
+ var import_promises72 = require("fs/promises");
70572
70838
  var import_node_net4 = require("net");
70573
70839
  var MAX_RESPONSE_BYTES = 64 * 1024;
70574
70840
  async function readAll(stream) {
@@ -70586,7 +70852,7 @@ function processIo() {
70586
70852
  };
70587
70853
  }
70588
70854
  function askGitCredentialSocket(endpoint, request2, signal) {
70589
- return new Promise((resolve12, reject) => {
70855
+ return new Promise((resolve13, reject) => {
70590
70856
  const socket = (0, import_node_net4.createConnection)(endpoint);
70591
70857
  let buffered = "";
70592
70858
  const fail = (error61) => {
@@ -70613,7 +70879,7 @@ function askGitCredentialSocket(endpoint, request2, signal) {
70613
70879
  signal.removeEventListener("abort", onAbort);
70614
70880
  try {
70615
70881
  const line = buffered.split("\n", 1)[0] ?? "";
70616
- resolve12(gitCredentialSocketResponseSchema.parse(JSON.parse(line)));
70882
+ resolve13(gitCredentialSocketResponseSchema.parse(JSON.parse(line)));
70617
70883
  } catch (error61) {
70618
70884
  reject(
70619
70885
  new RuntimeFault("io_failed", "the Alan runtime sent an invalid reply", { cause: error61 })
@@ -70678,7 +70944,7 @@ async function configure(argv) {
70678
70944
  }
70679
70945
  async function configureGitGateway(config2, gatewayUrl, signal) {
70680
70946
  const { launcher } = installLayout(config2.installDir, config2.profile);
70681
- const installed = await (0, import_promises71.access)(launcher).then(
70947
+ const installed = await (0, import_promises72.access)(launcher).then(
70682
70948
  () => true,
70683
70949
  () => false
70684
70950
  );
@@ -70705,7 +70971,7 @@ async function runGitCredential(argv) {
70705
70971
  }
70706
70972
 
70707
70973
  // src/cli/commands/hold.ts
70708
- var import_node_path72 = require("path");
70974
+ var import_node_path73 = require("path");
70709
70975
  init_agent2();
70710
70976
  init_runtime_v2();
70711
70977
  async function machineAccess(paths, log, conversationId, transport) {
@@ -70763,7 +71029,7 @@ async function runHold(argv) {
70763
71029
  const config2 = loadRuntimeConfig();
70764
71030
  const paths = runtimePaths(config2.stateDir);
70765
71031
  const log = __using(_stack, openFileLog(
70766
- (0, import_node_path72.join)(paths.logs, `holder-${launch.value.conversationId}.jsonl`),
71032
+ (0, import_node_path73.join)(paths.logs, `holder-${launch.value.conversationId}.jsonl`),
70767
71033
  config2.logLevel,
70768
71034
  systemClock
70769
71035
  ));
@@ -70774,7 +71040,7 @@ async function runHold(argv) {
70774
71040
  );
70775
71041
  const transport = __using(_stack, createHttpTransport());
70776
71042
  const access7 = await machineAccess(paths, log, launch.value.conversationId, transport);
70777
- const credentialPath = (0, import_node_path72.join)(paths.tmp, "mcp", `${launch.value.conversationId}.json`);
71043
+ const credentialPath = (0, import_node_path73.join)(paths.tmp, "mcp", `${launch.value.conversationId}.json`);
70778
71044
  const managedMcp = __using(_stack, access7.managedMcp === void 0 ? void 0 : createHelperMcpAccess({
70779
71045
  managedMcp: access7.managedMcp,
70780
71046
  conversationId: launch.value.conversationId,
@@ -70793,7 +71059,8 @@ async function runHold(argv) {
70793
71059
  timings: config2.sessionTimings,
70794
71060
  log,
70795
71061
  ...managedMcp === void 0 ? {} : { managedMcp },
70796
- codexCredentials: access7.codexCredentials
71062
+ codexCredentials: access7.codexCredentials,
71063
+ installedSkills: () => installedSkillFolders(skillsLayout(paths.stateDir))
70797
71064
  }),
70798
71065
  clock: systemClock,
70799
71066
  log,
@@ -70814,7 +71081,7 @@ async function runHold(argv) {
70814
71081
  }
70815
71082
 
70816
71083
  // src/cli/commands/hook.ts
70817
- var import_node_path73 = require("path");
71084
+ var import_node_path74 = require("path");
70818
71085
  var RUNTIME_ANSWER_MS = 2e3;
70819
71086
  var DEBUG_VARIABLE = "ALAN_HOOK_DEBUG";
70820
71087
  function flag(argv, name) {
@@ -70846,7 +71113,7 @@ async function forwardHook(argv, io) {
70846
71113
  return "transcript outside provider root";
70847
71114
  }
70848
71115
  const verdict = await io.send(
70849
- (0, import_node_path73.join)(io.stateDir, LOCAL_API_DISCOVERY_FILE),
71116
+ (0, import_node_path74.join)(io.stateDir, LOCAL_API_DISCOVERY_FILE),
70850
71117
  hookSignal,
70851
71118
  AbortSignal.timeout(RUNTIME_ANSWER_MS)
70852
71119
  );
@@ -70882,7 +71149,7 @@ async function runHook(argv, overrides = {}) {
70882
71149
  }
70883
71150
 
70884
71151
  // src/cli/commands/ingestion-hooks.ts
70885
- var import_promises72 = require("fs/promises");
71152
+ var import_promises73 = require("fs/promises");
70886
71153
  var CODEX_TRUST_NOTE = "Codex runs new hooks only after you review them: open /hooks in Codex.";
70887
71154
  function isAction(value2) {
70888
71155
  return value2 === "enable" || value2 === "disable" || value2 === "status";
@@ -70905,7 +71172,7 @@ function errorMessage2(error61) {
70905
71172
  return error61 instanceof Error ? error61.message : String(error61);
70906
71173
  }
70907
71174
  async function exists5(path4) {
70908
- return (0, import_promises72.access)(path4).then(
71175
+ return (0, import_promises73.access)(path4).then(
70909
71176
  () => true,
70910
71177
  () => false
70911
71178
  );
@@ -71008,10 +71275,10 @@ async function runIntegrationsCommand(argv) {
71008
71275
  }
71009
71276
 
71010
71277
  // src/cli/commands/legacy.ts
71011
- var import_node_path75 = require("path");
71278
+ var import_node_path76 = require("path");
71012
71279
 
71013
71280
  // src/cli/commands/setup.ts
71014
- var import_node_path74 = require("path");
71281
+ var import_node_path75 = require("path");
71015
71282
  init_zod();
71016
71283
 
71017
71284
  // src/cli/legacy.ts
@@ -71093,7 +71360,7 @@ async function grantFileCredential(argv, grantPath, ctx, deps) {
71093
71360
  return enrollFromGrantFile({
71094
71361
  paths: ctx.paths,
71095
71362
  storeKind: credentialStoreFlag(argv) ?? ctx.config.credentialStore,
71096
- grantPath: (0, import_node_path74.resolve)(grantPath),
71363
+ grantPath: (0, import_node_path75.resolve)(grantPath),
71097
71364
  clock: deps.clock,
71098
71365
  access: ctx.access
71099
71366
  });
@@ -71169,7 +71436,7 @@ async function runSetup(argv, signal) {
71169
71436
  var _stack = [];
71170
71437
  try {
71171
71438
  const ctx = cliContext();
71172
- const log = __using(_stack, openFileLog((0, import_node_path74.join)(ctx.paths.logs, "cli.jsonl"), ctx.config.logLevel, systemClock));
71439
+ const log = __using(_stack, openFileLog((0, import_node_path75.join)(ctx.paths.logs, "cli.jsonl"), ctx.config.logLevel, systemClock));
71173
71440
  const result = await setupMachine(argv, ctx, {
71174
71441
  enrollment: (apiUrl) => createEnrollmentClient({ apiUrl }),
71175
71442
  isProcessAlive,
@@ -71252,7 +71519,7 @@ async function runToken(argv, signal) {
71252
71519
  );
71253
71520
  }
71254
71521
  const ctx = cliContext();
71255
- const log = __using(_stack, openFileLog((0, import_node_path75.join)(ctx.paths.logs, "cli.jsonl"), ctx.config.logLevel, systemClock));
71522
+ const log = __using(_stack, openFileLog((0, import_node_path76.join)(ctx.paths.logs, "cli.jsonl"), ctx.config.logLevel, systemClock));
71256
71523
  const result = await rotateMachineCredential(ctx, { clock: systemClock, log, signal });
71257
71524
  process.stdout.write(`${rotationMessage(result)}
71258
71525
  `);
@@ -71264,8 +71531,8 @@ async function runToken(argv, signal) {
71264
71531
  }
71265
71532
 
71266
71533
  // src/cli/commands/logout.ts
71267
- var import_promises73 = require("fs/promises");
71268
- var import_node_path76 = require("path");
71534
+ var import_promises74 = require("fs/promises");
71535
+ var import_node_path77 = require("path");
71269
71536
  init_runtime_v2();
71270
71537
  var RUNTIME_EXIT_WAIT_MS = 35e3;
71271
71538
  var TURN_END_WAIT_MS = 3e4;
@@ -71324,9 +71591,9 @@ async function stopHolder(launch, deps, outcome2) {
71324
71591
  }
71325
71592
  async function stopHeldRuns(ctx, deps, outcome2 = "aborted") {
71326
71593
  const stopped = [];
71327
- for (const name of await (0, import_promises73.readdir)(ctx.paths.sessions).catch(() => [])) {
71594
+ for (const name of await (0, import_promises74.readdir)(ctx.paths.sessions).catch(() => [])) {
71328
71595
  const launch = await readJsonFile(
71329
- (0, import_node_path76.join)(ctx.paths.sessions, name, "launch.json"),
71596
+ (0, import_node_path77.join)(ctx.paths.sessions, name, "launch.json"),
71330
71597
  holderLaunchSchema
71331
71598
  );
71332
71599
  if (launch.kind !== "ok") continue;
@@ -71363,13 +71630,13 @@ async function forgetMachineLocally(ctx) {
71363
71630
  const machine = await readMachineFile(ctx.paths);
71364
71631
  if (machine === null) return;
71365
71632
  await credentialStoreFor(ctx.paths, machine.credentialStore, ctx.access).clear();
71366
- await (0, import_promises73.rm)(ctx.paths.machine, { force: true });
71633
+ await (0, import_promises74.rm)(ctx.paths.machine, { force: true });
71367
71634
  }
71368
71635
  async function runLogout(argv, signal) {
71369
71636
  var _stack = [];
71370
71637
  try {
71371
71638
  const ctx = cliContext();
71372
- const log = __using(_stack, openFileLog((0, import_node_path76.join)(ctx.paths.logs, "cli.jsonl"), ctx.config.logLevel, systemClock));
71639
+ const log = __using(_stack, openFileLog((0, import_node_path77.join)(ctx.paths.logs, "cli.jsonl"), ctx.config.logLevel, systemClock));
71373
71640
  const result = await logoutMachine(argv, ctx, {
71374
71641
  api: (apiUrl, accessToken) => createApiClient({ apiUrl, accessToken }),
71375
71642
  stopHeldRuns,
@@ -71386,8 +71653,8 @@ async function runLogout(argv, signal) {
71386
71653
  }
71387
71654
 
71388
71655
  // src/cli/commands/run.ts
71389
- var import_node_fs23 = require("fs");
71390
- var import_node_path80 = require("path");
71656
+ var import_node_fs24 = require("fs");
71657
+ var import_node_path81 = require("path");
71391
71658
 
71392
71659
  // src/local-api/app-attachments.ts
71393
71660
  function createAppAttachments(clock) {
@@ -71427,7 +71694,7 @@ function createRunAppends() {
71427
71694
  const pending = waiters.get(runId);
71428
71695
  if (pending === void 0) return;
71429
71696
  waiters.delete(runId);
71430
- for (const resolve12 of pending) resolve12();
71697
+ for (const resolve13 of pending) resolve13();
71431
71698
  };
71432
71699
  return {
71433
71700
  notify: wake,
@@ -71445,13 +71712,13 @@ function createRunAppends() {
71445
71712
  },
71446
71713
  nextAppend: (runId, signal) => {
71447
71714
  if (signal.aborted) return Promise.resolve();
71448
- return new Promise((resolve12) => {
71715
+ return new Promise((resolve13) => {
71449
71716
  const done = () => {
71450
71717
  signal.removeEventListener("abort", done);
71451
71718
  const pending2 = waiters.get(runId);
71452
71719
  pending2?.delete(done);
71453
71720
  if (pending2?.size === 0) waiters.delete(runId);
71454
- resolve12();
71721
+ resolve13();
71455
71722
  };
71456
71723
  const pending = waiters.get(runId) ?? /* @__PURE__ */ new Set();
71457
71724
  pending.add(done);
@@ -71463,18 +71730,18 @@ function createRunAppends() {
71463
71730
  }
71464
71731
 
71465
71732
  // src/local-api/server.ts
71466
- var import_node_crypto34 = require("crypto");
71467
- var import_promises74 = require("fs/promises");
71733
+ var import_node_crypto35 = require("crypto");
71734
+ var import_promises75 = require("fs/promises");
71468
71735
  var import_node_http4 = require("http");
71469
- var import_node_path77 = require("path");
71736
+ var import_node_path78 = require("path");
71470
71737
 
71471
71738
  // src/local-api/guard.ts
71472
- var import_node_crypto33 = require("crypto");
71739
+ var import_node_crypto34 = require("crypto");
71473
71740
  var ALLOWED = { kind: "allowed" };
71474
71741
  function tokenMatches2(expected, header) {
71475
71742
  if (header === void 0 || !header.startsWith("Bearer ")) return false;
71476
71743
  const presented = Buffer.from(header.slice("Bearer ".length));
71477
- return presented.length === expected.length && (0, import_node_crypto33.timingSafeEqual)(presented, expected);
71744
+ return presented.length === expected.length && (0, import_node_crypto34.timingSafeEqual)(presented, expected);
71478
71745
  }
71479
71746
  function isBrowserReachable(req, allowedHosts) {
71480
71747
  if (req.headers.origin !== void 0 || req.headers.referer !== void 0) return true;
@@ -71543,11 +71810,11 @@ id: ${event.id}
71543
71810
  ${data}
71544
71811
  `);
71545
71812
  if (accepted || res.destroyed) return;
71546
- await new Promise((resolve12) => {
71813
+ await new Promise((resolve13) => {
71547
71814
  const done = () => {
71548
71815
  res.off("drain", done);
71549
71816
  res.off("close", done);
71550
- resolve12();
71817
+ resolve13();
71551
71818
  };
71552
71819
  res.once("drain", done);
71553
71820
  res.once("close", done);
@@ -71775,9 +72042,9 @@ async function readChangedTurn(deps, conversationId, runId, slot) {
71775
72042
  }
71776
72043
  async function nextChangedRuns(bell, signal) {
71777
72044
  if (bell.pending.size === 0) {
71778
- await new Promise((resolve12) => {
71779
- bell.wake = resolve12;
71780
- if (signal.aborted || bell.pending.size > 0) resolve12();
72045
+ await new Promise((resolve13) => {
72046
+ bell.wake = resolve13;
72047
+ if (signal.aborted || bell.pending.size > 0) resolve13();
71781
72048
  });
71782
72049
  bell.wake = void 0;
71783
72050
  }
@@ -71941,7 +72208,7 @@ var machineFeatureRoutes = [
71941
72208
  ];
71942
72209
 
71943
72210
  // src/local-api/run-log-routes.ts
71944
- var import_node_fs22 = require("fs");
72211
+ var import_node_fs23 = require("fs");
71945
72212
  init_runtime_v2();
71946
72213
  var RUN_ENDED = "_alan/run.ended";
71947
72214
  var decoder2 = new TextDecoder();
@@ -71958,7 +72225,7 @@ async function openWhenWritten(deps, runId, res, signal) {
71958
72225
  const path4 = runDirectory(deps.runsDir, runId).log;
71959
72226
  while (!signal.aborted) {
71960
72227
  const appended = deps.appends.nextAppend(runId, signal);
71961
- if ((0, import_node_fs22.existsSync)(path4) || !await deps.isHeld(runId, signal)) return openReader(res, path4);
72228
+ if ((0, import_node_fs23.existsSync)(path4) || !await deps.isHeld(runId, signal)) return openReader(res, path4);
71962
72229
  await appended;
71963
72230
  }
71964
72231
  return null;
@@ -72094,9 +72361,9 @@ var streamStatus = async ({ feed, appAttachments }, { res, signal }) => {
72094
72361
  latest = event;
72095
72362
  writing = writing.then(flush);
72096
72363
  }));
72097
- await new Promise((resolve12) => {
72098
- if (signal.aborted) resolve12();
72099
- signal.addEventListener("abort", () => resolve12(), { once: true });
72364
+ await new Promise((resolve13) => {
72365
+ if (signal.aborted) resolve13();
72366
+ signal.addEventListener("abort", () => resolve13(), { once: true });
72100
72367
  });
72101
72368
  await writing;
72102
72369
  } catch (_) {
@@ -72419,11 +72686,11 @@ function localRequestSignal(path4, closed) {
72419
72686
  ]);
72420
72687
  }
72421
72688
  async function listenOnLoopback(server) {
72422
- await new Promise((resolve12, reject) => {
72689
+ await new Promise((resolve13, reject) => {
72423
72690
  server.once("error", reject);
72424
72691
  server.listen(0, "127.0.0.1", () => {
72425
72692
  server.off("error", reject);
72426
- resolve12();
72693
+ resolve13();
72427
72694
  });
72428
72695
  }).catch((error61) => {
72429
72696
  throw new RuntimeFault("io_failed", "The local API could not listen on loopback", {
@@ -72438,7 +72705,7 @@ async function listenOnLoopback(server) {
72438
72705
  }
72439
72706
  async function closeServer(server) {
72440
72707
  server.closeAllConnections();
72441
- await new Promise((resolve12) => server.close(() => resolve12()));
72708
+ await new Promise((resolve13) => server.close(() => resolve13()));
72442
72709
  }
72443
72710
  async function serveLocalApi(deps) {
72444
72711
  const limits = { ...DEFAULT_LIMITS, ...deps.limits };
@@ -72462,7 +72729,7 @@ async function serveLocalApi(deps) {
72462
72729
  server.keepAliveTimeout = KEEP_ALIVE_TIMEOUT_MS;
72463
72730
  server.maxConnections = HARD_MAX_CONNECTIONS;
72464
72731
  const port = await listenOnLoopback(server);
72465
- const token = (0, import_node_crypto34.randomBytes)(32).toString("base64url");
72732
+ const token = (0, import_node_crypto35.randomBytes)(32).toString("base64url");
72466
72733
  const guard = createRequestGuard({ token, port, rateLimit: limits.rateLimit, clock });
72467
72734
  const appAttachments = createAppAttachments(clock);
72468
72735
  const routeDeps = {
@@ -72509,7 +72776,7 @@ async function serveLocalApi(deps) {
72509
72776
  startedAtMs,
72510
72777
  runtimeVersion: deps.runtimeVersion
72511
72778
  };
72512
- const discoveryPath = (0, import_node_path77.join)(deps.stateDir, LOCAL_API_DISCOVERY_FILE);
72779
+ const discoveryPath = (0, import_node_path78.join)(deps.stateDir, LOCAL_API_DISCOVERY_FILE);
72513
72780
  await writeJsonFileAtomic(discoveryPath, discovery);
72514
72781
  const followers = startMaintenance({
72515
72782
  everyMs: limits.refreshEveryMs,
@@ -72543,7 +72810,7 @@ async function serveLocalApi(deps) {
72543
72810
  await watchedStatus[Symbol.asyncDispose]();
72544
72811
  const current = await readJsonFile(discoveryPath, localApiDiscoverySchema);
72545
72812
  if (current.kind === "ok" && current.value.token === token) {
72546
- await (0, import_promises74.rm)(discoveryPath, { force: true });
72813
+ await (0, import_promises75.rm)(discoveryPath, { force: true });
72547
72814
  }
72548
72815
  await closeServer(server);
72549
72816
  log.info("local_api.closed", {});
@@ -72628,7 +72895,7 @@ function machineFeatureActions(deps) {
72628
72895
  }
72629
72896
 
72630
72897
  // src/cli/commands/machine-plane.ts
72631
- var import_node_path79 = require("path");
72898
+ var import_node_path80 = require("path");
72632
72899
 
72633
72900
  // src/link/index.ts
72634
72901
  init_runtime_v2();
@@ -75195,9 +75462,9 @@ var Socket2 = class extends Emitter {
75195
75462
  * @return a Promise that will be fulfilled when the server acknowledges the event
75196
75463
  */
75197
75464
  emitWithAck(ev, ...args) {
75198
- return new Promise((resolve12, reject) => {
75465
+ return new Promise((resolve13, reject) => {
75199
75466
  const fn = (arg1, arg2) => {
75200
- return arg1 ? reject(arg1) : resolve12(arg2);
75467
+ return arg1 ? reject(arg1) : resolve13(arg2);
75201
75468
  };
75202
75469
  fn.withError = true;
75203
75470
  args.push(fn);
@@ -76296,7 +76563,7 @@ function refusalFailure(refusal2) {
76296
76563
  }
76297
76564
 
76298
76565
  // src/link/probe.ts
76299
- var import_promises75 = require("dns/promises");
76566
+ var import_promises76 = require("dns/promises");
76300
76567
  var import_node_net5 = require("net");
76301
76568
  var import_node_tls2 = require("tls");
76302
76569
  var PROBE_TIMEOUT_MS4 = 5e3;
@@ -76316,9 +76583,9 @@ async function connectOnce(url3, clock) {
76316
76583
  const timer = new AbortController();
76317
76584
  try {
76318
76585
  return await Promise.race([
76319
- new Promise((resolve12) => {
76320
- socket.once(ready, () => resolve12(null));
76321
- socket.once("error", (error61) => resolve12(classifyTransportFailure(error61)));
76586
+ new Promise((resolve13) => {
76587
+ socket.once(ready, () => resolve13(null));
76588
+ socket.once("error", (error61) => resolve13(classifyTransportFailure(error61)));
76322
76589
  }),
76323
76590
  clock.sleep(PROBE_TIMEOUT_MS4, timer.signal).then(
76324
76591
  () => "connection_timeout",
@@ -76332,7 +76599,7 @@ async function connectOnce(url3, clock) {
76332
76599
  }
76333
76600
  async function probeEndpoint(url3, clock) {
76334
76601
  try {
76335
- await (0, import_promises75.lookup)(url3.hostname);
76602
+ await (0, import_promises76.lookup)(url3.hostname);
76336
76603
  } catch (error61) {
76337
76604
  const reason = classifyTransportFailure(error61);
76338
76605
  return reason === "other" ? "dns" : reason;
@@ -76642,9 +76909,9 @@ function planReconcile(desired, held) {
76642
76909
  }
76643
76910
 
76644
76911
  // src/reconciler/desired-sync.ts
76645
- var import_node_crypto35 = require("crypto");
76912
+ var import_node_crypto36 = require("crypto");
76646
76913
  function fingerprintOf(desired) {
76647
- return (0, import_node_crypto35.createHash)("sha256").update(JSON.stringify(desired)).digest("hex");
76914
+ return (0, import_node_crypto36.createHash)("sha256").update(JSON.stringify(desired)).digest("hex");
76648
76915
  }
76649
76916
  var FAILED_READ_RETRY_MS = 3e4;
76650
76917
  function createDesiredSync(deps) {
@@ -76781,7 +77048,7 @@ function createReconciler(host, lifecycle, log, signal) {
76781
77048
  }
76782
77049
 
76783
77050
  // src/uploader/index.ts
76784
- var import_promises76 = require("fs/promises");
77051
+ var import_promises77 = require("fs/promises");
76785
77052
  init_runtime_v2();
76786
77053
  init_zod();
76787
77054
  var RETRY_DELAYS_MS = [250, 500, 1e3, 2e3, 5e3, 1e4, 3e4];
@@ -76929,7 +77196,7 @@ function startUploader({ api, runsDir, clock, log, archive }) {
76929
77196
  };
76930
77197
  const unsealedRunIds = async () => {
76931
77198
  const runIds = [];
76932
- for (const name of await (0, import_promises76.readdir)(runsDir).catch(() => [])) {
77199
+ for (const name of await (0, import_promises77.readdir)(runsDir).catch(() => [])) {
76933
77200
  const runId = runIdSchema.safeParse(name);
76934
77201
  if (runId.success && !sealed.has(runId.data) && !archive?.has(runId.data))
76935
77202
  runIds.push(runId.data);
@@ -76944,13 +77211,13 @@ function startUploader({ api, runsDir, clock, log, archive }) {
76944
77211
  const dir = runDirectory(runsDir, runId);
76945
77212
  const progress = await readJsonFile(dir.upload, uploadProgressSchema);
76946
77213
  if (progress.kind !== "ok" || !progress.value.sealed) return false;
76947
- const sealedAt = (await (0, import_promises76.stat)(dir.upload)).mtimeMs;
77214
+ const sealedAt = (await (0, import_promises77.stat)(dir.upload)).mtimeMs;
76948
77215
  if (clock.now() - sealedAt < options.sealedForMs) return false;
76949
77216
  return (await readLastRecord(dir.log))?.update.sessionUpdate === "_alan/run.ended";
76950
77217
  };
76951
77218
  const archivable = async (options) => {
76952
77219
  const found = [];
76953
- for (const name of await (0, import_promises76.readdir)(runsDir).catch(() => [])) {
77220
+ for (const name of await (0, import_promises77.readdir)(runsDir).catch(() => [])) {
76954
77221
  const runId = runIdSchema.safeParse(name);
76955
77222
  if (!runId.success || archive?.has(runId.data)) continue;
76956
77223
  try {
@@ -77151,12 +77418,12 @@ async function startMachineNativeIngest(deps) {
77151
77418
  }
77152
77419
 
77153
77420
  // src/cli/commands/run-updates.ts
77154
- var import_node_path78 = require("path");
77421
+ var import_node_path79 = require("path");
77155
77422
  init_runtime_v2();
77156
77423
  var UPDATE_CHECK_EVERY_MS = 6 * 60 * 60 * 1e3;
77157
77424
  var DEFERRED_RETRY_MS = 5 * 60 * 1e3;
77158
77425
  function isInstalledBundle(layout, bundlePath) {
77159
- return (0, import_node_path78.resolve)((0, import_node_path78.dirname)((0, import_node_path78.dirname)(bundlePath))) === (0, import_node_path78.resolve)(layout.versions);
77426
+ return (0, import_node_path79.resolve)((0, import_node_path79.dirname)((0, import_node_path79.dirname)(bundlePath))) === (0, import_node_path79.resolve)(layout.versions);
77160
77427
  }
77161
77428
  async function settleUpgradeOnStart({
77162
77429
  layout,
@@ -77263,7 +77530,7 @@ function startRuntimeUpdates(options) {
77263
77530
  layout,
77264
77531
  release: npmRelease,
77265
77532
  tarball: await options.downloader.download(npmRelease.dist.tarball, signal),
77266
- tmpDir: (0, import_node_path78.join)(layout.root, ".downloads")
77533
+ tmpDir: (0, import_node_path79.join)(layout.root, ".downloads")
77267
77534
  });
77268
77535
  await lifecycle.exclusive("upgrade", async () => {
77269
77536
  await recordPendingUpgrade(layout, currentVersion2, version2, clock.now());
@@ -77494,7 +77761,7 @@ async function startMachinePlane(deps) {
77494
77761
  [ALAN_MANAGED_SESSION_ENV]: "1"
77495
77762
  },
77496
77763
  cwd: paths.stateDir,
77497
- outputPath: (0, import_node_path79.join)(paths.logs, "holders.log")
77764
+ outputPath: (0, import_node_path80.join)(paths.logs, "holders.log")
77498
77765
  },
77499
77766
  deps.holderIsolation
77500
77767
  );
@@ -77530,6 +77797,8 @@ async function startMachinePlane(deps) {
77530
77797
  transport
77531
77798
  }),
77532
77799
  local: { home: config2.home, machineId: identity.machineId },
77800
+ // Only a cloud sandbox's runtime has a git gateway; a person's own ~/.codex is theirs.
77801
+ ...config2.gitGatewayUrl === null ? {} : { codexSkillsDir: (0, import_node_path80.join)(config2.codexHome, "skills") },
77533
77802
  log
77534
77803
  })
77535
77804
  );
@@ -77727,7 +77996,7 @@ async function startMachinePlane(deps) {
77727
77996
  git: createGitRunner({ env: cliEnvironment }),
77728
77997
  clock,
77729
77998
  log,
77730
- dir: (0, import_node_path79.join)(paths.stateDir, "checkout-freshness")
77999
+ dir: (0, import_node_path80.join)(paths.stateDir, "checkout-freshness")
77731
78000
  },
77732
78001
  stopped.signal
77733
78002
  );
@@ -77989,11 +78258,11 @@ function createMachineSlot(deps) {
77989
78258
 
77990
78259
  // src/cli/commands/run-exit.ts
77991
78260
  function firstAborted(signals) {
77992
- return new Promise((resolve12) => {
78261
+ return new Promise((resolve13) => {
77993
78262
  for (const reason of ["stop", "restart"]) {
77994
78263
  const signal = signals[reason];
77995
- if (signal.aborted) resolve12(reason);
77996
- signal.addEventListener("abort", () => resolve12(reason), { once: true });
78264
+ if (signal.aborted) resolve13(reason);
78265
+ signal.addEventListener("abort", () => resolve13(reason), { once: true });
77997
78266
  }
77998
78267
  });
77999
78268
  }
@@ -78021,15 +78290,15 @@ function lockWaitMs(argv) {
78021
78290
  }
78022
78291
  async function openManagedProviders(config2, paths) {
78023
78292
  const providerEnv = readCliEnvironment();
78024
- const bundledNpm = (0, import_node_path80.join)((0, import_node_path80.dirname)(process.execPath), "npm", "bin", "npm-cli.js");
78025
- const providerToolchain = config2.providerToolchain ?? (process.platform === "win32" && (0, import_node_fs23.existsSync)(bundledNpm) ? { node: process.execPath, npmCli: bundledNpm } : null);
78293
+ const bundledNpm = (0, import_node_path81.join)((0, import_node_path81.dirname)(process.execPath), "npm", "bin", "npm-cli.js");
78294
+ const providerToolchain = config2.providerToolchain ?? (process.platform === "win32" && (0, import_node_fs24.existsSync)(bundledNpm) ? { node: process.execPath, npmCli: bundledNpm } : null);
78026
78295
  const npmPath = providerToolchain?.node ?? await resolveCommandOnPath("npm", providerEnv, process.platform);
78027
78296
  const npmOptions = npmPath === null || process.platform === "win32" && providerToolchain === null ? null : {
78028
78297
  command: npmPath,
78029
78298
  ...providerToolchain === null ? {} : { argsBeforeNpm: [providerToolchain.npmCli] },
78030
78299
  env: providerEnv
78031
78300
  };
78032
- const providerNodeDir = providerToolchain?.node === void 0 ? void 0 : (0, import_node_path80.dirname)(providerToolchain.node);
78301
+ const providerNodeDir = providerToolchain?.node === void 0 ? void 0 : (0, import_node_path81.dirname)(providerToolchain.node);
78033
78302
  const probeEnv = providerNodeDir === void 0 ? providerEnv : {
78034
78303
  ...providerEnv,
78035
78304
  PATH: `${providerNodeDir}${pathDelimiter(process.platform)}${envValue(providerEnv, "PATH")}`
@@ -78039,7 +78308,7 @@ async function openManagedProviders(config2, paths) {
78039
78308
  throw new Error("Provider installer is unavailable on this computer");
78040
78309
  };
78041
78310
  const managed = createManagedProviderClis({
78042
- root: (0, import_node_path80.join)(paths.stateDir, "provider-clis"),
78311
+ root: (0, import_node_path81.join)(paths.stateDir, "provider-clis"),
78043
78312
  resolveVersion: npmOptions === null ? unavailable : createNpmVersionResolver(npmOptions),
78044
78313
  installPackage: npmOptions === null ? unavailable : createNpmPackageInstaller(npmOptions),
78045
78314
  probe: (executable, backendKind) => probeManagedProvider(executable, backendKind, canonicalProbeEnv)
@@ -78071,7 +78340,7 @@ async function runService(argv, stop, restart = new AbortController().signal) {
78071
78340
  waitMs: lockWaitMs(argv),
78072
78341
  signal: stop
78073
78342
  }));
78074
- const log = __using(_stack, openFileLog((0, import_node_path80.join)(paths.logs, "runtime.jsonl"), config2.logLevel, clock));
78343
+ const log = __using(_stack, openFileLog((0, import_node_path81.join)(paths.logs, "runtime.jsonl"), config2.logLevel, clock));
78075
78344
  const lifecycle = createLifecycleQueue({ clock, log });
78076
78345
  const install2 = installLayout(config2.installDir, config2.profile);
78077
78346
  const bundlePath = process.argv[1] ?? "";
@@ -78105,7 +78374,7 @@ async function runService(argv, stop, restart = new AbortController().signal) {
78105
78374
  openCliEnvironment({
78106
78375
  env: readCliEnvironment(),
78107
78376
  platform: process.platform,
78108
- lastKnownGoodFile: (0, import_node_path80.join)(paths.stateDir, "login-path.json"),
78377
+ lastKnownGoodFile: (0, import_node_path81.join)(paths.stateDir, "login-path.json"),
78109
78378
  clock,
78110
78379
  decorate: (env) => withPackagedAlanCodeEngine(env, bundlePath, process.platform)
78111
78380
  })
@@ -78282,17 +78551,17 @@ async function runServiceCommand(argv, ctx = cliContext()) {
78282
78551
  }
78283
78552
 
78284
78553
  // src/cli/commands/upgrade.ts
78285
- var import_promises77 = require("fs/promises");
78286
- var import_node_path81 = require("path");
78554
+ var import_promises78 = require("fs/promises");
78555
+ var import_node_path82 = require("path");
78287
78556
  function isNotNewer(version2, installed) {
78288
78557
  return installed !== null && isReleaseVersion(version2) && isReleaseVersion(installed) && compareVersions(version2, installed) <= 0;
78289
78558
  }
78290
78559
  async function installFromSource(source) {
78291
78560
  const { layout, from, ifNewer } = source;
78292
- const isTarball = (await (0, import_promises77.stat)(from)).isFile();
78293
- const downloads = (0, import_node_path81.join)(layout.root, ".downloads");
78294
- if (isTarball) await (0, import_promises77.mkdir)(downloads, { recursive: true, mode: 448 });
78295
- const scratch = isTarball ? await (0, import_promises77.mkdtemp)((0, import_node_path81.join)(downloads, "upgrade-")) : null;
78561
+ const isTarball = (await (0, import_promises78.stat)(from)).isFile();
78562
+ const downloads = (0, import_node_path82.join)(layout.root, ".downloads");
78563
+ if (isTarball) await (0, import_promises78.mkdir)(downloads, { recursive: true, mode: 448 });
78564
+ const scratch = isTarball ? await (0, import_promises78.mkdtemp)((0, import_node_path82.join)(downloads, "upgrade-")) : null;
78296
78565
  try {
78297
78566
  const sourceDir = scratch === null ? from : await extractPackageTarball(from, scratch);
78298
78567
  const version2 = await readPackageVersion(sourceDir);
@@ -78300,7 +78569,7 @@ async function installFromSource(source) {
78300
78569
  if (ifNewer && isNotNewer(version2, installed)) return { kind: "skipped", version: version2, installed };
78301
78570
  return { kind: "installed", ...await installVersion(layout, sourceDir) };
78302
78571
  } finally {
78303
- if (scratch !== null) await (0, import_promises77.rm)(scratch, { recursive: true, force: true });
78572
+ if (scratch !== null) await (0, import_promises78.rm)(scratch, { recursive: true, force: true });
78304
78573
  }
78305
78574
  }
78306
78575
  async function runUpgrade(argv) {
@@ -78312,7 +78581,7 @@ async function runUpgrade(argv) {
78312
78581
  const layout = installLayout(config2.installDir, config2.profile);
78313
78582
  const outcome2 = await installFromSource({
78314
78583
  layout,
78315
- from: (0, import_node_path81.resolve)(from),
78584
+ from: (0, import_node_path82.resolve)(from),
78316
78585
  ifNewer: hasFlag(argv, "--if-newer")
78317
78586
  });
78318
78587
  if (outcome2.kind === "skipped") {