@alan-ai-hq/agent-manager 0.1.105 → 0.1.107

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 (2) hide show
  1. package/dist/index.cjs +262 -221
  2. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -15504,7 +15504,7 @@ function describeError(error61) {
15504
15504
  }
15505
15505
 
15506
15506
  // src/version.ts
15507
- var AGENT_VERSION = "0.1.105";
15507
+ var AGENT_VERSION = "0.1.107";
15508
15508
 
15509
15509
  // src/daemon-worktree.ts
15510
15510
  var import_node_child_process3 = require("child_process");
@@ -38162,20 +38162,22 @@ var import_util9 = require("util");
38162
38162
  var import_fs6 = require("fs");
38163
38163
  var import_os5 = require("os");
38164
38164
  var import_path6 = require("path");
38165
+ var import_promises = require("fs/promises");
38166
+ var import_path7 = require("path");
38165
38167
  var import_fs7 = require("fs");
38166
38168
  var import_os6 = require("os");
38167
- var import_path7 = require("path");
38169
+ var import_path8 = require("path");
38168
38170
  var import_fs8 = require("fs");
38169
38171
  var import_os7 = require("os");
38170
- var import_path8 = require("path");
38172
+ var import_path9 = require("path");
38171
38173
  var import_fs9 = require("fs");
38172
38174
  var import_os8 = require("os");
38173
- var import_path9 = require("path");
38175
+ var import_path10 = require("path");
38174
38176
  var import_readline2 = require("readline");
38175
38177
  var import_url2 = require("url");
38176
38178
  var import_crypto4 = require("crypto");
38177
38179
  var import_fs10 = require("fs");
38178
- var import_path10 = require("path");
38180
+ var import_path11 = require("path");
38179
38181
  var MAX_PARSED_ATTACHMENTS = 3;
38180
38182
  var MAX_PARSED_ATTACHMENT_CHARS = 12e3;
38181
38183
  var MAX_METADATA_CHARS = 240;
@@ -40800,6 +40802,7 @@ function planExternalMcpDelivery(config2, processEnv) {
40800
40802
  }
40801
40803
  return { servers, env, verbatim };
40802
40804
  }
40805
+ var ALAN_MCP_BEARER_TOKEN_ENV = "ALAN_MCP_BEARER_TOKEN";
40803
40806
  function requiredHeader(registration, name) {
40804
40807
  const entry = Object.entries(registration.headers).find(
40805
40808
  ([candidate]) => candidate.toLowerCase() === name
@@ -40815,6 +40818,9 @@ function requireManagedAuthorization(registration) {
40815
40818
  }
40816
40819
  return authorization;
40817
40820
  }
40821
+ function requireManagedBearerToken(registration) {
40822
+ return requireManagedAuthorization(registration).slice(7).trim();
40823
+ }
40818
40824
  function requireManagedRunId(registration) {
40819
40825
  return requiredHeader(registration, "x-alan-run-id");
40820
40826
  }
@@ -42572,7 +42578,7 @@ function buildCodexManagedMcpArgs(registration, options = {}) {
42572
42578
  "-c",
42573
42579
  `mcp_servers.alan.url=${JSON.stringify(registration.url)}`,
42574
42580
  "-c",
42575
- `mcp_servers.alan.env_http_headers.Authorization=${JSON.stringify(ALAN_MCP_AUTHORIZATION_ENV)}`,
42581
+ `mcp_servers.alan.bearer_token_env_var=${JSON.stringify(ALAN_MCP_BEARER_TOKEN_ENV)}`,
42576
42582
  "-c",
42577
42583
  `mcp_servers.alan.env_http_headers.x-alan-run-id=${JSON.stringify(ALAN_RUN_ID_ENV)}`,
42578
42584
  "-c",
@@ -42620,6 +42626,7 @@ function createCodexRuntimeBackend(command = "codex", defaultArgs = []) {
42620
42626
  ...context.env,
42621
42627
  ...externalMcp?.env,
42622
42628
  [ALAN_MCP_AUTHORIZATION_ENV]: requireManagedAuthorization(managedRegistration),
42629
+ [ALAN_MCP_BEARER_TOKEN_ENV]: requireManagedBearerToken(managedRegistration),
42623
42630
  [ALAN_RUN_ID_ENV]: requireManagedRunId(managedRegistration)
42624
42631
  }
42625
42632
  } : context;
@@ -42674,11 +42681,15 @@ function createCodexRuntimeBackend(command = "codex", defaultArgs = []) {
42674
42681
  ...permissionArgs,
42675
42682
  "exec",
42676
42683
  ...managedMcpArgs,
42684
+ // Codex scopes `-c` overrides on both `exec` and `exec resume`.
42685
+ // Keep every config override at the `exec` level: a later
42686
+ // resume-level `-c` replaces the earlier override set, which
42687
+ // silently drops Alan's managed MCP auth on continuation turns.
42688
+ ...effortArgs,
42677
42689
  "resume",
42678
42690
  "--json",
42679
42691
  "--skip-git-repo-check",
42680
42692
  ...modelArgs,
42681
- ...effortArgs,
42682
42693
  ...imageArgs,
42683
42694
  resumeId,
42684
42695
  "-"
@@ -43006,6 +43017,39 @@ function createCopilotCliBackend(command = "copilot", defaultArgs = []) {
43006
43017
  }
43007
43018
  };
43008
43019
  }
43020
+ async function withCursorProjectMcpEntry(cwd, url3, run) {
43021
+ const path2 = (0, import_path7.join)(cwd, ".cursor", "mcp.json");
43022
+ const original = await (0, import_promises.readFile)(path2, "utf8").catch(() => null);
43023
+ const config2 = parseConfig(original);
43024
+ const servers = config2.mcpServers ?? {};
43025
+ config2.mcpServers = servers;
43026
+ servers.alan = {
43027
+ type: "http",
43028
+ url: url3,
43029
+ headers: {
43030
+ Authorization: `\${env:${ALAN_MCP_AUTHORIZATION_ENV}}`,
43031
+ "x-alan-run-id": `\${env:${ALAN_RUN_ID_ENV}}`
43032
+ }
43033
+ };
43034
+ await (0, import_promises.mkdir)((0, import_path7.dirname)(path2), { recursive: true });
43035
+ await (0, import_promises.writeFile)(path2, `${JSON.stringify(config2, null, 2)}
43036
+ `);
43037
+ try {
43038
+ return await run();
43039
+ } finally {
43040
+ if (original === null) await (0, import_promises.rm)(path2, { force: true });
43041
+ else await (0, import_promises.writeFile)(path2, original);
43042
+ }
43043
+ }
43044
+ function parseConfig(raw) {
43045
+ if (!raw) return {};
43046
+ try {
43047
+ const parsed = JSON.parse(raw);
43048
+ return parsed && typeof parsed === "object" ? parsed : {};
43049
+ } catch {
43050
+ return {};
43051
+ }
43052
+ }
43009
43053
  function asRecord4(value2) {
43010
43054
  return typeof value2 === "object" && value2 !== null ? value2 : null;
43011
43055
  }
@@ -43198,10 +43242,10 @@ function emitCursorSubagentTranscript(transcriptPath, parentToolUseId, presenter
43198
43242
  function cursorTranscriptsRoot(context) {
43199
43243
  const projectKey = context.cwd.replace(/^[/\\]+/, "").replace(/[/\\]+/g, "-");
43200
43244
  const home = context.env.HOME || process.env.HOME || (0, import_os6.homedir)();
43201
- return (0, import_path7.join)(home, ".cursor", "projects", projectKey, "agent-transcripts");
43245
+ return (0, import_path8.join)(home, ".cursor", "projects", projectKey, "agent-transcripts");
43202
43246
  }
43203
43247
  function cursorTranscriptPathForAgent(context, agentId) {
43204
- return (0, import_path7.join)(cursorTranscriptsRoot(context), agentId, `${agentId}.jsonl`);
43248
+ return (0, import_path8.join)(cursorTranscriptsRoot(context), agentId, `${agentId}.jsonl`);
43205
43249
  }
43206
43250
  function resolveCursorSubagentTranscriptPath(success2, context) {
43207
43251
  const explicit = success2?.transcriptPath ?? success2?.transcript_path;
@@ -43589,84 +43633,86 @@ function createCursorAgentCliBackend(command = "cursor-agent", defaultArgs = [])
43589
43633
  [ALAN_RUN_ID_ENV]: requireManagedRunId(context.config.alanMcp)
43590
43634
  }
43591
43635
  } : context;
43592
- try {
43593
- return await createGenericCliBackend({
43594
- kind: "cursor_agent_cli",
43595
- supportTier: "structured",
43596
- command,
43597
- args: [],
43598
- buildArgs: (ctx, _prompt) => {
43599
- const args = [
43600
- "--print",
43601
- "--output-format",
43602
- "stream-json",
43603
- "--trust",
43604
- "--workspace",
43605
- ctx.cwd
43606
- ];
43607
- if (approveMcps) {
43608
- args.push("--approve-mcps");
43609
- }
43610
- const resumeId = ctx.config.runtimeSessionId?.trim() || ctx.config.providerSessionId?.trim();
43611
- if (shouldForceCursorAgent(ctx.config)) args.push("--force");
43612
- if (ctx.config.mode === "plan" || ctx.config.mode === "review") {
43613
- args.push("--mode", "plan");
43614
- } else if (ctx.config.mode === "ask") {
43615
- args.push("--mode", "ask");
43616
- } else if (shouldUseReadOnlyRuntimePermissions(ctx.config)) {
43617
- args.push("--mode", "plan");
43618
- }
43619
- if (resumeId) {
43620
- args.push("--resume", resumeId);
43621
- logResumeObservability("agent_resume_requested", {
43622
- backendKind: "cursor_agent_cli",
43623
- requestedResumeId: resumeId
43624
- });
43625
- }
43626
- const model = ctx.config.selectedModel?.trim();
43627
- if (model && isDispatchableCursorModel(model)) {
43628
- const modelDef = findModelDef("cursor_agent_cli", model) ?? findModelDef("cursor_agent_cli", model.replace(/-fast$/, ""));
43629
- args.push(
43630
- "--model",
43631
- buildCursorAgentModelArg(model, {
43632
- selectedEffortLevel: ctx.config.selectedEffortLevel,
43633
- selectedContextWindow: ctx.config.selectedContextWindow,
43634
- effortLevels: modelDef?.capabilities?.effortLevels,
43635
- contextWindows: modelDef?.capabilities?.contextWindows
43636
- })
43637
- );
43638
- }
43639
- return [...args, ...defaultArgs];
43640
- },
43641
- // Prompt over stdin with immediate EOF (verified live on cursor-agent
43642
- // 2026.07.09): vibe-kanban's mitigation for cursor-agent's documented
43643
- // headless hangs. The result-race/grace-kill stays active via
43644
- // keepStdinOpen; closeStdinAfterPrompt only skips holding stdin open,
43645
- // which cursor never reads after the prompt anyway.
43646
- promptViaStdin: true,
43647
- keepStdinOpen: true,
43648
- closeStdinAfterPrompt: true,
43649
- // cursor-agent headless has a documented failure mode of hanging at startup
43650
- // with zero output; without this watchdog only the 30-min server reaper
43651
- // would end the run.
43652
- startupTimeoutMs: 18e4,
43653
- // Post-startup hang bound: cursor's asks use the non-blocking MCP model and it
43654
- // never populates the idle timer's ask/background fire conditions, so a cursor
43655
- // process that produced output then went silent (no result event) is otherwise
43656
- // bounded only by the ~30-min external reaper. Poll every 5 min; kill after 15
43657
- // min of continuous silence.
43658
- resultIdleTimeoutMs: 5 * 6e4,
43659
- postStartupSilenceTimeoutMs: 15 * 6e4,
43660
- augmentPrompt: (ctx) => {
43661
- const isResume = Boolean(
43662
- ctx.config.runtimeSessionId?.trim() || ctx.config.providerSessionId?.trim()
43636
+ const runBackend = () => createGenericCliBackend({
43637
+ kind: "cursor_agent_cli",
43638
+ supportTier: "structured",
43639
+ command,
43640
+ args: [],
43641
+ buildArgs: (ctx, _prompt) => {
43642
+ const args = [
43643
+ "--print",
43644
+ "--output-format",
43645
+ "stream-json",
43646
+ "--trust",
43647
+ "--workspace",
43648
+ ctx.cwd
43649
+ ];
43650
+ if (approveMcps) {
43651
+ args.push("--approve-mcps");
43652
+ }
43653
+ const resumeId = ctx.config.runtimeSessionId?.trim() || ctx.config.providerSessionId?.trim();
43654
+ if (shouldForceCursorAgent(ctx.config)) args.push("--force");
43655
+ if (ctx.config.mode === "plan" || ctx.config.mode === "review") {
43656
+ args.push("--mode", "plan");
43657
+ } else if (ctx.config.mode === "ask") {
43658
+ args.push("--mode", "ask");
43659
+ } else if (shouldUseReadOnlyRuntimePermissions(ctx.config)) {
43660
+ args.push("--mode", "plan");
43661
+ }
43662
+ if (resumeId) {
43663
+ args.push("--resume", resumeId);
43664
+ logResumeObservability("agent_resume_requested", {
43665
+ backendKind: "cursor_agent_cli",
43666
+ requestedResumeId: resumeId
43667
+ });
43668
+ }
43669
+ const model = ctx.config.selectedModel?.trim();
43670
+ if (model && isDispatchableCursorModel(model)) {
43671
+ const modelDef = findModelDef("cursor_agent_cli", model) ?? findModelDef("cursor_agent_cli", model.replace(/-fast$/, ""));
43672
+ args.push(
43673
+ "--model",
43674
+ buildCursorAgentModelArg(model, {
43675
+ selectedEffortLevel: ctx.config.selectedEffortLevel,
43676
+ selectedContextWindow: ctx.config.selectedContextWindow,
43677
+ effortLevels: modelDef?.capabilities?.effortLevels,
43678
+ contextWindows: modelDef?.capabilities?.contextWindows
43679
+ })
43663
43680
  );
43664
- const base = buildResumeAwarePrompt(ctx.config, ctx.promptText, { isResume });
43665
- const prompt = ctx.config.mode === "plan" ? buildPlanModePrefix(base) : base;
43666
- return appendImagePathReferences(prompt, imageFiles);
43667
- },
43668
- parseStructuredLine: parseCursorStructuredLine
43669
- }).run(runContext);
43681
+ }
43682
+ return [...args, ...defaultArgs];
43683
+ },
43684
+ // Prompt over stdin with immediate EOF (verified live on cursor-agent
43685
+ // 2026.07.09): vibe-kanban's mitigation for cursor-agent's documented
43686
+ // headless hangs. The result-race/grace-kill stays active via
43687
+ // keepStdinOpen; closeStdinAfterPrompt only skips holding stdin open,
43688
+ // which cursor never reads after the prompt anyway.
43689
+ promptViaStdin: true,
43690
+ keepStdinOpen: true,
43691
+ closeStdinAfterPrompt: true,
43692
+ // cursor-agent headless has a documented failure mode of hanging at startup
43693
+ // with zero output; without this watchdog only the 30-min server reaper
43694
+ // would end the run.
43695
+ startupTimeoutMs: 18e4,
43696
+ // Post-startup hang bound: cursor's asks use the non-blocking MCP model and it
43697
+ // never populates the idle timer's ask/background fire conditions, so a cursor
43698
+ // process that produced output then went silent (no result event) is otherwise
43699
+ // bounded only by the ~30-min external reaper. Poll every 5 min; kill after 15
43700
+ // min of continuous silence.
43701
+ resultIdleTimeoutMs: 5 * 6e4,
43702
+ postStartupSilenceTimeoutMs: 15 * 6e4,
43703
+ augmentPrompt: (ctx) => {
43704
+ const isResume = Boolean(
43705
+ ctx.config.runtimeSessionId?.trim() || ctx.config.providerSessionId?.trim()
43706
+ );
43707
+ const base = buildResumeAwarePrompt(ctx.config, ctx.promptText, { isResume });
43708
+ const prompt = ctx.config.mode === "plan" ? buildPlanModePrefix(base) : base;
43709
+ return appendImagePathReferences(prompt, imageFiles);
43710
+ },
43711
+ parseStructuredLine: parseCursorStructuredLine
43712
+ }).run(runContext);
43713
+ const managed = context.config.alanMcp;
43714
+ try {
43715
+ return await (managed ? withCursorProjectMcpEntry(context.cwd, managed.url, runBackend) : runBackend());
43670
43716
  } finally {
43671
43717
  cleanup();
43672
43718
  }
@@ -44420,9 +44466,9 @@ function buildGrokAgentArgs(config2, defaultArgs = []) {
44420
44466
  return args;
44421
44467
  }
44422
44468
  var DEFAULT_SKILL_ROOTS = [
44423
- (0, import_path9.join)((0, import_os8.homedir)(), ".agents", "skills"),
44424
- (0, import_path9.join)((0, import_os8.homedir)(), ".claude", "skills"),
44425
- (0, import_path9.join)((0, import_os8.homedir)(), ".config", "opencode", "skills")
44469
+ (0, import_path10.join)((0, import_os8.homedir)(), ".agents", "skills"),
44470
+ (0, import_path10.join)((0, import_os8.homedir)(), ".claude", "skills"),
44471
+ (0, import_path10.join)((0, import_os8.homedir)(), ".config", "opencode", "skills")
44426
44472
  ];
44427
44473
  function parseFrontmatter(content) {
44428
44474
  if (!content.startsWith("---\n")) return {};
@@ -44442,7 +44488,7 @@ function listSkillFiles(root) {
44442
44488
  const files = [];
44443
44489
  for (const entry of (0, import_fs9.readdirSync)(root, { withFileTypes: true })) {
44444
44490
  if (!entry.isDirectory()) continue;
44445
- const skillPath = (0, import_path9.join)(root, entry.name, "SKILL.md");
44491
+ const skillPath = (0, import_path10.join)(root, entry.name, "SKILL.md");
44446
44492
  if ((0, import_fs9.existsSync)(skillPath)) files.push(skillPath);
44447
44493
  }
44448
44494
  return files;
@@ -44753,8 +44799,8 @@ function createKimiCliBackend(command = "kimi-cli", defaultArgs = []) {
44753
44799
  supportTier: "structured",
44754
44800
  async run(context) {
44755
44801
  const registration = context.config.alanMcp;
44756
- const mcpDirectory = registration ? (0, import_fs8.mkdtempSync)((0, import_path8.join)((0, import_os7.tmpdir)(), "alan-kimi-mcp-")) : null;
44757
- const mcpConfigPath = mcpDirectory ? (0, import_path8.join)(mcpDirectory, "mcp.json") : null;
44802
+ const mcpDirectory = registration ? (0, import_fs8.mkdtempSync)((0, import_path9.join)((0, import_os7.tmpdir)(), "alan-kimi-mcp-")) : null;
44803
+ const mcpConfigPath = mcpDirectory ? (0, import_path9.join)(mcpDirectory, "mcp.json") : null;
44758
44804
  if (registration && mcpConfigPath) {
44759
44805
  (0, import_fs8.writeFileSync)(
44760
44806
  mcpConfigPath,
@@ -46712,14 +46758,14 @@ function normalizePath(candidate, cwd) {
46712
46758
  } catch {
46713
46759
  }
46714
46760
  if (path2.startsWith("~/")) return null;
46715
- if ((0, import_path10.isAbsolute)(path2)) return path2;
46716
- return cwd ? (0, import_path10.join)(cwd, path2) : null;
46761
+ if ((0, import_path11.isAbsolute)(path2)) return path2;
46762
+ return cwd ? (0, import_path11.join)(cwd, path2) : null;
46717
46763
  }
46718
46764
  function resolveToolCwd(cwd, toolInput) {
46719
46765
  if (!isRecord(toolInput)) return cwd;
46720
46766
  const raw = typeof toolInput.cwd === "string" ? toolInput.cwd : typeof toolInput.workdir === "string" ? toolInput.workdir : typeof toolInput.workingDirectory === "string" ? toolInput.workingDirectory : null;
46721
46767
  if (!raw) return cwd;
46722
- return (0, import_path10.isAbsolute)(raw) || !cwd ? raw : (0, import_path10.join)(cwd, raw);
46768
+ return (0, import_path11.isAbsolute)(raw) || !cwd ? raw : (0, import_path11.join)(cwd, raw);
46723
46769
  }
46724
46770
  function extractBrowserMediaPathHints(content, cwd, toolName, options = {}, kind = "video") {
46725
46771
  if (!isAgentBrowserMediaInvocation(toolName, content, options.toolInput, kind)) return [];
@@ -46764,7 +46810,7 @@ function extractGeneratedImagesFromToolResult(toolId, content, cwd, toolName, op
46764
46810
  const path2 = normalizePath(candidate, effectiveCwd);
46765
46811
  if (!path2 || seen.has(path2) || !(0, import_fs10.existsSync)(path2)) continue;
46766
46812
  seen.add(path2);
46767
- const ext = (0, import_path10.extname)(path2).toLowerCase();
46813
+ const ext = (0, import_path11.extname)(path2).toLowerCase();
46768
46814
  const mimeType = IMAGE_MIME_BY_EXT[ext];
46769
46815
  if (!mimeType) continue;
46770
46816
  const stat2 = (0, import_fs10.statSync)(path2);
@@ -46774,7 +46820,7 @@ function extractGeneratedImagesFromToolResult(toolId, content, cwd, toolName, op
46774
46820
  images.push({
46775
46821
  type: "generated_image",
46776
46822
  id: (0, import_crypto4.randomUUID)(),
46777
- filename: (0, import_path10.basename)(path2),
46823
+ filename: (0, import_path11.basename)(path2),
46778
46824
  mimeType,
46779
46825
  size: buffer.length,
46780
46826
  width,
@@ -46803,7 +46849,7 @@ function extractSessionMediaFromToolResult(toolId, content, cwd, toolName, optio
46803
46849
  const path2 = normalizePath(candidate, effectiveCwd);
46804
46850
  if (!path2 || seen.has(path2) || !(0, import_fs10.existsSync)(path2)) continue;
46805
46851
  seen.add(path2);
46806
- const ext = (0, import_path10.extname)(path2).toLowerCase();
46852
+ const ext = (0, import_path11.extname)(path2).toLowerCase();
46807
46853
  const mimeType = mimeByExt[ext];
46808
46854
  if (!mimeType) continue;
46809
46855
  const stat2 = (0, import_fs10.statSync)(path2);
@@ -46814,7 +46860,7 @@ function extractSessionMediaFromToolResult(toolId, content, cwd, toolName, optio
46814
46860
  type: "session_media",
46815
46861
  kind,
46816
46862
  id: (0, import_crypto4.randomUUID)(),
46817
- filename: (0, import_path10.basename)(path2),
46863
+ filename: (0, import_path11.basename)(path2),
46818
46864
  mimeType,
46819
46865
  size: buffer.length,
46820
46866
  width: dimensions?.width,
@@ -55675,6 +55721,8 @@ var CoreAgent = class _CoreAgent extends BaseMachineAgent {
55675
55721
  else delete augmented.ALAN_RUN_ID;
55676
55722
  if (this.runtimeToken) augmented.ALAN_MCP_AUTHORIZATION = `Bearer ${this.runtimeToken}`;
55677
55723
  else delete augmented.ALAN_MCP_AUTHORIZATION;
55724
+ if (this.runtimeToken) augmented[ALAN_MCP_BEARER_TOKEN_ENV] = this.runtimeToken;
55725
+ else delete augmented[ALAN_MCP_BEARER_TOKEN_ENV];
55678
55726
  const backendKind = this.runtime.backendKind ?? "";
55679
55727
  const providerApiKey = this.providerApiKey ?? "";
55680
55728
  if (backendKind === "antigravity_cli" && providerApiKey.trim()) {
@@ -58254,13 +58302,13 @@ async function handoffRuntimeSetupGrant(input2) {
58254
58302
  // src/skills/local-skill-source.ts
58255
58303
  var import_node_buffer2 = require("buffer");
58256
58304
  var import_node_crypto14 = require("crypto");
58257
- var import_promises2 = require("fs/promises");
58305
+ var import_promises3 = require("fs/promises");
58258
58306
  var import_node_path20 = __toESM(require("path"), 1);
58259
58307
 
58260
58308
  // ../shared/dist/node/skill-package.js
58261
58309
  var import_node_buffer = require("buffer");
58262
58310
  var import_node_crypto13 = require("crypto");
58263
- var import_promises = require("fs/promises");
58311
+ var import_promises2 = require("fs/promises");
58264
58312
  var import_node_path19 = require("path");
58265
58313
  var import_yaml = __toESM(require_dist(), 1);
58266
58314
  var TREE_HASH_PREFIX = import_node_buffer.Buffer.from("alan-skill-tree-v1\0", "utf8");
@@ -58353,11 +58401,11 @@ async function readSkillPackageFile(packageRoot, path2, expectedSha256) {
58353
58401
  if (!normalizedPath || normalizedPath !== path2 || normalizedPath.includes("\\") || components.some((component) => !component || component === "." || component === "..")) {
58354
58402
  throw new SkillPackageError("INVALID_PATH", `Invalid Skill package path: ${path2}`, path2);
58355
58403
  }
58356
- const absolutePath = await (0, import_promises.realpath)((0, import_node_path19.resolve)(root, ...components)).catch(() => null);
58404
+ const absolutePath = await (0, import_promises2.realpath)((0, import_node_path19.resolve)(root, ...components)).catch(() => null);
58357
58405
  if (!absolutePath || normalizeRelativePath(root, absolutePath) !== normalizedPath) {
58358
58406
  throw new SkillPackageError("INVALID_PATH", `Skill package file was not found: ${path2}`, path2);
58359
58407
  }
58360
- const entryStat = await (0, import_promises.lstat)(absolutePath);
58408
+ const entryStat = await (0, import_promises2.lstat)(absolutePath);
58361
58409
  if (!entryStat.isFile()) {
58362
58410
  throw new SkillPackageError("SPECIAL_FILE_BLOCKED", `Only regular files are allowed in Skill packages: ${path2}`, path2);
58363
58411
  }
@@ -58374,11 +58422,11 @@ async function readSkillPackageFile(packageRoot, path2, expectedSha256) {
58374
58422
  return { file: read.manifest, bytes: read.bytes };
58375
58423
  }
58376
58424
  async function requirePackageRoot(packageRoot) {
58377
- const root = await (0, import_promises.realpath)((0, import_node_path19.resolve)(packageRoot)).catch(() => null);
58425
+ const root = await (0, import_promises2.realpath)((0, import_node_path19.resolve)(packageRoot)).catch(() => null);
58378
58426
  if (!root) {
58379
58427
  throw new SkillPackageError("INVALID_PACKAGE_ROOT", "Skill package directory does not exist");
58380
58428
  }
58381
- const rootStat = await (0, import_promises.lstat)(root);
58429
+ const rootStat = await (0, import_promises2.lstat)(root);
58382
58430
  if (!rootStat.isDirectory()) {
58383
58431
  throw new SkillPackageError("INVALID_PACKAGE_ROOT", "Skill package root must be a directory");
58384
58432
  }
@@ -58398,13 +58446,13 @@ async function walkPackage(root, ignoredPaths) {
58398
58446
  }
58399
58447
  return files;
58400
58448
  async function walkDirectory(directory) {
58401
- const entries = await (0, import_promises.readdir)(directory, { withFileTypes: true });
58449
+ const entries = await (0, import_promises2.readdir)(directory, { withFileTypes: true });
58402
58450
  for (const entry of entries) {
58403
58451
  const absolutePath = (0, import_node_path19.resolve)(directory, entry.name);
58404
58452
  const normalizedPath = normalizeRelativePath(root, absolutePath);
58405
58453
  if (isIgnored(normalizedPath, entry.name, entry.isDirectory(), ignored))
58406
58454
  continue;
58407
- const entryStat = await (0, import_promises.lstat)(absolutePath);
58455
+ const entryStat = await (0, import_promises2.lstat)(absolutePath);
58408
58456
  if (entryStat.isSymbolicLink()) {
58409
58457
  throw new SkillPackageError("SYMLINK_BLOCKED", `Nested symbolic links are not allowed in Skill packages: ${normalizedPath}`, normalizedPath);
58410
58458
  }
@@ -58513,7 +58561,7 @@ function isSecretPath(path2) {
58513
58561
  return name.endsWith(".private-key.pem") || name.endsWith(".private-key.key");
58514
58562
  }
58515
58563
  async function readPackageFile(file2) {
58516
- const bytes = await (0, import_promises.readFile)(file2.absolutePath);
58564
+ const bytes = await (0, import_promises2.readFile)(file2.absolutePath);
58517
58565
  return {
58518
58566
  bytes,
58519
58567
  manifest: {
@@ -59640,7 +59688,7 @@ var LocalSkillSource = class {
59640
59688
  async scanRootAsPackage(resolvedRoot, ignoredPaths, mode) {
59641
59689
  const directory = resolvedRoot.directory;
59642
59690
  if (!await pathExists((0, import_node_path20.join)(directory, "SKILL.md"))) return null;
59643
- const canonicalRoot = await (0, import_promises2.realpath)(directory).catch(() => directory);
59691
+ const canonicalRoot = await (0, import_promises3.realpath)(directory).catch(() => directory);
59644
59692
  const name = import_node_path20.default.basename(canonicalRoot);
59645
59693
  try {
59646
59694
  const fingerprint = await fingerprintPackage(canonicalRoot);
@@ -59689,7 +59737,7 @@ var LocalSkillSource = class {
59689
59737
  if (rootPackage) return rootPackage;
59690
59738
  let entries;
59691
59739
  try {
59692
- entries = await (0, import_promises2.readdir)(resolvedRoot.directory, { withFileTypes: true });
59740
+ entries = await (0, import_promises3.readdir)(resolvedRoot.directory, { withFileTypes: true });
59693
59741
  } catch (error61) {
59694
59742
  if (isAbsentDirectory(error61)) return { candidates: [], diagnostics: [], incomplete: false };
59695
59743
  return {
@@ -59706,13 +59754,13 @@ var LocalSkillSource = class {
59706
59754
  }
59707
59755
  const candidates = [];
59708
59756
  const diagnostics = [];
59709
- const canonicalRoot = await (0, import_promises2.realpath)(resolvedRoot.directory).catch(
59757
+ const canonicalRoot = await (0, import_promises3.realpath)(resolvedRoot.directory).catch(
59710
59758
  () => resolvedRoot.directory
59711
59759
  );
59712
59760
  for (const entry of entries) {
59713
59761
  if (!entry.isDirectory() && !entry.isSymbolicLink()) continue;
59714
59762
  const candidatePath = (0, import_node_path20.join)(resolvedRoot.directory, entry.name);
59715
- const canonicalPath = await (0, import_promises2.realpath)(candidatePath).catch(() => null);
59763
+ const canonicalPath = await (0, import_promises3.realpath)(candidatePath).catch(() => null);
59716
59764
  if (!canonicalPath) {
59717
59765
  diagnostics.push({
59718
59766
  code: "SOURCE_UNREADABLE",
@@ -59773,12 +59821,12 @@ async function fingerprintPackage(root) {
59773
59821
  await visit2(root, "");
59774
59822
  return `sha256:${hash2.digest("hex")}`;
59775
59823
  async function visit2(directory, relativeDirectory) {
59776
- const entries = await (0, import_promises2.readdir)(directory, { withFileTypes: true });
59824
+ const entries = await (0, import_promises3.readdir)(directory, { withFileTypes: true });
59777
59825
  entries.sort((left, right) => import_node_buffer2.Buffer.compare(import_node_buffer2.Buffer.from(left.name), import_node_buffer2.Buffer.from(right.name)));
59778
59826
  for (const entry of entries) {
59779
59827
  const path2 = relativeDirectory ? `${relativeDirectory}/${entry.name}` : entry.name;
59780
59828
  const absolutePath = (0, import_node_path20.join)(directory, entry.name);
59781
- const metadata = await (0, import_promises2.lstat)(absolutePath);
59829
+ const metadata = await (0, import_promises3.lstat)(absolutePath);
59782
59830
  hash2.update(path2.normalize("NFC")).update("\0").update(
59783
59831
  entry.isDirectory() ? "d" : entry.isFile() ? "f" : entry.isSymbolicLink() ? "l" : "o"
59784
59832
  ).update("\0").update(String(metadata.size)).update("\0").update(String(metadata.mtimeMs)).update("\0").update(String(metadata.mode & 511)).update("\0");
@@ -59797,7 +59845,7 @@ function staleCodexDeclaration(relativeDirectory, label, providerKinds) {
59797
59845
  }
59798
59846
  async function canonicalDirectories(directories) {
59799
59847
  const canonical = await Promise.all(
59800
- directories.map((directory) => (0, import_promises2.realpath)(directory).catch(() => directory))
59848
+ directories.map((directory) => (0, import_promises3.realpath)(directory).catch(() => directory))
59801
59849
  );
59802
59850
  return [...new Set(canonical)];
59803
59851
  }
@@ -59808,10 +59856,10 @@ function isWithinDirectory(parent, candidate) {
59808
59856
  async function loadSkillSourceConfig(homeDirectory2) {
59809
59857
  const configDirectory = (0, import_node_path20.join)(homeDirectory2, ".alan");
59810
59858
  const configPath = (0, import_node_path20.join)(configDirectory, "config.toml");
59811
- await (0, import_promises2.mkdir)(configDirectory, { recursive: true, mode: 448 });
59859
+ await (0, import_promises3.mkdir)(configDirectory, { recursive: true, mode: 448 });
59812
59860
  let created = false;
59813
59861
  try {
59814
- await (0, import_promises2.writeFile)(configPath, DEFAULT_SKILL_CONFIG, {
59862
+ await (0, import_promises3.writeFile)(configPath, DEFAULT_SKILL_CONFIG, {
59815
59863
  encoding: "utf8",
59816
59864
  flag: "wx",
59817
59865
  mode: 384
@@ -59820,7 +59868,7 @@ async function loadSkillSourceConfig(homeDirectory2) {
59820
59868
  } catch (error61) {
59821
59869
  if (!isAlreadyPresent(error61)) throw error61;
59822
59870
  }
59823
- const content = await (0, import_promises2.readFile)(configPath, "utf8");
59871
+ const content = await (0, import_promises3.readFile)(configPath, "utf8");
59824
59872
  try {
59825
59873
  return { state: "ready", config: parseSkillSourceConfig(content, homeDirectory2), created };
59826
59874
  } catch (error61) {
@@ -60006,7 +60054,7 @@ function deduplicateCandidatesByContent(candidates) {
60006
60054
  }
60007
60055
  async function pathExists(candidate) {
60008
60056
  try {
60009
- await (0, import_promises2.access)(candidate);
60057
+ await (0, import_promises3.access)(candidate);
60010
60058
  return true;
60011
60059
  } catch {
60012
60060
  return false;
@@ -60014,7 +60062,7 @@ async function pathExists(candidate) {
60014
60062
  }
60015
60063
  async function hasManagedMarker(directory) {
60016
60064
  try {
60017
- await (0, import_promises2.access)((0, import_node_path20.join)(directory, ".alan-managed.json"));
60065
+ await (0, import_promises3.access)((0, import_node_path20.join)(directory, ".alan-managed.json"));
60018
60066
  return true;
60019
60067
  } catch {
60020
60068
  return false;
@@ -60022,7 +60070,7 @@ async function hasManagedMarker(directory) {
60022
60070
  }
60023
60071
  async function isDirectory(path2) {
60024
60072
  try {
60025
- return (await (0, import_promises2.lstat)(path2)).isDirectory();
60073
+ return (await (0, import_promises3.lstat)(path2)).isDirectory();
60026
60074
  } catch {
60027
60075
  return false;
60028
60076
  }
@@ -60193,12 +60241,12 @@ var RuntimeSkillCoordinator = class {
60193
60241
  // src/skills/runtime-skill-manager.ts
60194
60242
  var import_node_buffer5 = require("buffer");
60195
60243
  var import_node_crypto17 = require("crypto");
60196
- var import_promises5 = require("fs/promises");
60244
+ var import_promises6 = require("fs/promises");
60197
60245
  var import_node_path23 = require("path");
60198
60246
 
60199
60247
  // src/skills/managed-skill-store.ts
60200
60248
  var import_node_crypto15 = require("crypto");
60201
- var import_promises3 = require("fs/promises");
60249
+ var import_promises4 = require("fs/promises");
60202
60250
  var import_node_path21 = require("path");
60203
60251
  var EMPTY_STATE = {
60204
60252
  version: 1,
@@ -60216,9 +60264,9 @@ var ManagedSkillStore = class _ManagedSkillStore {
60216
60264
  integrity;
60217
60265
  canRemoveManagedFiles;
60218
60266
  static async open(baseDirectory) {
60219
- await (0, import_promises3.mkdir)(baseDirectory, { recursive: true, mode: 448 });
60267
+ await (0, import_promises4.mkdir)(baseDirectory, { recursive: true, mode: 448 });
60220
60268
  try {
60221
- const parsed = JSON.parse(await (0, import_promises3.readFile)((0, import_node_path21.join)(baseDirectory, "state.json"), "utf8"));
60269
+ const parsed = JSON.parse(await (0, import_promises4.readFile)((0, import_node_path21.join)(baseDirectory, "state.json"), "utf8"));
60222
60270
  return new _ManagedSkillStore(baseDirectory, parseState(parsed), "verified");
60223
60271
  } catch (error61) {
60224
60272
  if (isMissingPath(error61)) {
@@ -60284,15 +60332,15 @@ var ManagedSkillStore = class _ManagedSkillStore {
60284
60332
  `.state.json.pending-${process.pid}-${(0, import_node_crypto15.randomBytes)(6).toString("hex")}`
60285
60333
  );
60286
60334
  try {
60287
- await (0, import_promises3.writeFile)(pendingPath, `${JSON.stringify(this.state, null, 2)}
60335
+ await (0, import_promises4.writeFile)(pendingPath, `${JSON.stringify(this.state, null, 2)}
60288
60336
  `, {
60289
60337
  encoding: "utf8",
60290
60338
  flag: "wx",
60291
60339
  mode: 384
60292
60340
  });
60293
- await (0, import_promises3.rename)(pendingPath, statePath);
60341
+ await (0, import_promises4.rename)(pendingPath, statePath);
60294
60342
  } finally {
60295
- await (0, import_promises3.rm)(pendingPath, { force: true });
60343
+ await (0, import_promises4.rm)(pendingPath, { force: true });
60296
60344
  }
60297
60345
  }
60298
60346
  };
@@ -60350,7 +60398,7 @@ function isMissingPath(error61) {
60350
60398
  // ../shared/dist/node/skill-bundle.js
60351
60399
  var import_node_buffer3 = require("buffer");
60352
60400
  var import_node_crypto16 = require("crypto");
60353
- var import_promises4 = require("fs/promises");
60401
+ var import_promises5 = require("fs/promises");
60354
60402
  var import_node_path22 = require("path");
60355
60403
  var import_node_stream = require("stream");
60356
60404
  var import_node_zlib = require("zlib");
@@ -60360,7 +60408,7 @@ async function createSkillBundle(packageRoot, options = {}) {
60360
60408
  const archive = (0, import_tar_stream.pack)();
60361
60409
  const tarPromise = collectStream(archive);
60362
60410
  for (const file2 of before.files) {
60363
- const bytes2 = await (0, import_promises4.readFile)((0, import_node_path22.join)(packageRoot, ...file2.path.split("/")));
60411
+ const bytes2 = await (0, import_promises5.readFile)((0, import_node_path22.join)(packageRoot, ...file2.path.split("/")));
60364
60412
  await addArchiveEntry(archive, {
60365
60413
  name: file2.path,
60366
60414
  type: "file",
@@ -60392,7 +60440,7 @@ async function extractSkillBundle(archiveBytes, destination, expected) {
60392
60440
  throw new Error("Skill archive hash does not match the expected immutable Version");
60393
60441
  }
60394
60442
  const tarBytes = await decompressBounded(archiveBytes);
60395
- await (0, import_promises4.mkdir)(destination, { recursive: false, mode: 448 });
60443
+ await (0, import_promises5.mkdir)(destination, { recursive: false, mode: 448 });
60396
60444
  try {
60397
60445
  await extractTar(tarBytes, destination);
60398
60446
  const inspected = await inspectSkillPackage(destination, { expectedName: null });
@@ -60400,7 +60448,7 @@ async function extractSkillBundle(archiveBytes, destination, expected) {
60400
60448
  throw new Error("Extracted Skill package hash does not match the expected immutable Version");
60401
60449
  }
60402
60450
  } catch (error61) {
60403
- await (0, import_promises4.rm)(destination, { recursive: true, force: true });
60451
+ await (0, import_promises5.rm)(destination, { recursive: true, force: true });
60404
60452
  throw error61;
60405
60453
  }
60406
60454
  }
@@ -60476,8 +60524,8 @@ async function extractEntry(header, stream, destination, limits) {
60476
60524
  throw new Error(`Skill archive file size is invalid: ${path2}`);
60477
60525
  }
60478
60526
  const outputPath = (0, import_node_path22.join)(destination, ...path2.split("/"));
60479
- await (0, import_promises4.mkdir)((0, import_node_path22.dirname)(outputPath), { recursive: true, mode: 448 });
60480
- await (0, import_promises4.writeFile)(outputPath, bytes, { mode: (header.mode ?? 420) & 73 ? 493 : 420 });
60527
+ await (0, import_promises5.mkdir)((0, import_node_path22.dirname)(outputPath), { recursive: true, mode: 448 });
60528
+ await (0, import_promises5.writeFile)(outputPath, bytes, { mode: (header.mode ?? 420) & 73 ? 493 : 420 });
60481
60529
  }
60482
60530
  function requireSafeArchivePath(value2) {
60483
60531
  const normalized = value2.replaceAll("\\", "/").normalize("NFC");
@@ -60737,12 +60785,12 @@ var RuntimeSkillManager = class _RuntimeSkillManager {
60737
60785
  }
60738
60786
  async reconcileUnlocked(manifest) {
60739
60787
  const desired = desiredSkillManifestSchema.parse(manifest);
60740
- await (0, import_promises5.mkdir)(this.managedSkillsDirectory, { recursive: true, mode: 448 });
60741
- await (0, import_promises5.mkdir)((0, import_node_path23.join)(this.skillsStateDirectory, "cache", "sha256"), {
60788
+ await (0, import_promises6.mkdir)(this.managedSkillsDirectory, { recursive: true, mode: 448 });
60789
+ await (0, import_promises6.mkdir)((0, import_node_path23.join)(this.skillsStateDirectory, "cache", "sha256"), {
60742
60790
  recursive: true,
60743
60791
  mode: 448
60744
60792
  });
60745
- await (0, import_promises5.mkdir)((0, import_node_path23.join)(this.skillsStateDirectory, "tmp"), { recursive: true, mode: 448 });
60793
+ await (0, import_promises6.mkdir)((0, import_node_path23.join)(this.skillsStateDirectory, "tmp"), { recursive: true, mode: 448 });
60746
60794
  const results = [];
60747
60795
  const nextProjections = {};
60748
60796
  for (const entry of desired.skills) {
@@ -60865,52 +60913,52 @@ var RuntimeSkillManager = class _RuntimeSkillManager {
60865
60913
  let sourceMoved = false;
60866
60914
  let destinationInstalled = false;
60867
60915
  try {
60868
- await (0, import_promises5.rename)(source, backup);
60916
+ await (0, import_promises6.rename)(source, backup);
60869
60917
  sourceMoved = true;
60870
- await (0, import_promises5.cp)(backup, pending, { recursive: true, errorOnExist: true, force: false });
60918
+ await (0, import_promises6.cp)(backup, pending, { recursive: true, errorOnExist: true, force: false });
60871
60919
  const skillMarkdown = (0, import_node_path23.join)(pending, "SKILL.md");
60872
- await (0, import_promises5.writeFile)(
60920
+ await (0, import_promises6.writeFile)(
60873
60921
  skillMarkdown,
60874
- rewriteSkillMarkdownName(await (0, import_promises5.readFile)(skillMarkdown, "utf8"), name),
60922
+ rewriteSkillMarkdownName(await (0, import_promises6.readFile)(skillMarkdown, "utf8"), name),
60875
60923
  {
60876
60924
  encoding: "utf8",
60877
60925
  mode: 420
60878
60926
  }
60879
60927
  );
60880
60928
  await inspectSkillPackage(pending, { expectedName: name });
60881
- await (0, import_promises5.rename)(pending, destination);
60929
+ await (0, import_promises6.rename)(pending, destination);
60882
60930
  destinationInstalled = true;
60883
- await (0, import_promises5.rm)(backup, { recursive: true, force: true });
60931
+ await (0, import_promises6.rm)(backup, { recursive: true, force: true });
60884
60932
  } catch (error61) {
60885
- if (destinationInstalled) await (0, import_promises5.rm)(destination, { recursive: true, force: true });
60933
+ if (destinationInstalled) await (0, import_promises6.rm)(destination, { recursive: true, force: true });
60886
60934
  if (sourceMoved && await pathExists2(backup) && !await pathExists2(source)) {
60887
- await (0, import_promises5.rename)(backup, source);
60935
+ await (0, import_promises6.rename)(backup, source);
60888
60936
  }
60889
60937
  throw error61;
60890
60938
  } finally {
60891
- await (0, import_promises5.rm)(pending, { recursive: true, force: true });
60939
+ await (0, import_promises6.rm)(pending, { recursive: true, force: true });
60892
60940
  if (!sourceMoved || destinationInstalled) {
60893
- await (0, import_promises5.rm)(backup, { recursive: true, force: true });
60941
+ await (0, import_promises6.rm)(backup, { recursive: true, force: true });
60894
60942
  }
60895
60943
  }
60896
60944
  }
60897
60945
  async overwriteLocalConflict(input2, entry, conflict, manifest) {
60898
60946
  const source = this.conflictDirectory(entry.runtimeDirectory, conflict.kind);
60899
60947
  const backup = `${source}.overwrite-backup-${process.pid}-${(0, import_node_crypto17.randomBytes)(8).toString("hex")}`;
60900
- await (0, import_promises5.rename)(source, backup);
60948
+ await (0, import_promises6.rename)(source, backup);
60901
60949
  try {
60902
60950
  const reconciled = await this.reconcileUnlocked(manifest);
60903
60951
  const result = resolutionFromReconcile(input2, reconciled);
60904
60952
  if (result.state !== "applied") {
60905
60953
  await this.removeResolvedProjection(entry, conflict.kind);
60906
- await (0, import_promises5.rename)(backup, source);
60954
+ await (0, import_promises6.rename)(backup, source);
60907
60955
  return result;
60908
60956
  }
60909
- await (0, import_promises5.rm)(backup, { recursive: true, force: true });
60957
+ await (0, import_promises6.rm)(backup, { recursive: true, force: true });
60910
60958
  return result;
60911
60959
  } catch (error61) {
60912
60960
  await this.removeResolvedProjection(entry, conflict.kind).catch(() => void 0);
60913
- if (!await pathExists2(source) && await pathExists2(backup)) await (0, import_promises5.rename)(backup, source);
60961
+ if (!await pathExists2(source) && await pathExists2(backup)) await (0, import_promises6.rename)(backup, source);
60914
60962
  throw error61;
60915
60963
  }
60916
60964
  }
@@ -60920,7 +60968,7 @@ var RuntimeSkillManager = class _RuntimeSkillManager {
60920
60968
  if (conflictKind === "managed_destination") {
60921
60969
  const marker = await readMarker(destination);
60922
60970
  if (marker?.skillId === entry.skillId && marker.versionId === entry.versionId && marker.contentHash === entry.contentHash) {
60923
- await (0, import_promises5.rm)(destination, { recursive: true, force: true });
60971
+ await (0, import_promises6.rm)(destination, { recursive: true, force: true });
60924
60972
  }
60925
60973
  return;
60926
60974
  }
@@ -60952,16 +61000,16 @@ var RuntimeSkillManager = class _RuntimeSkillManager {
60952
61000
  if (!await legacyFileMatches(source, legacy.hash) || !await packageMatches(source, entry.contentHash)) {
60953
61001
  return;
60954
61002
  }
60955
- await (0, import_promises5.rename)(source, destination);
61003
+ await (0, import_promises6.rename)(source, destination);
60956
61004
  try {
60957
- await (0, import_promises5.writeFile)(
61005
+ await (0, import_promises6.writeFile)(
60958
61006
  (0, import_node_path23.join)(destination, ".alan-managed.json"),
60959
61007
  `${JSON.stringify(markerFor(entry), null, 2)}
60960
61008
  `,
60961
61009
  { encoding: "utf8", flag: "wx", mode: 384 }
60962
61010
  );
60963
61011
  } catch (error61) {
60964
- await (0, import_promises5.rename)(destination, source).catch(() => void 0);
61012
+ await (0, import_promises6.rename)(destination, source).catch(() => void 0);
60965
61013
  throw error61;
60966
61014
  }
60967
61015
  await removeExactLegacySkill((0, import_node_path23.join)(this.compatibilitySkillsDirectory, entry.slug), legacy.hash);
@@ -60974,7 +61022,7 @@ var RuntimeSkillManager = class _RuntimeSkillManager {
60974
61022
  await removeExactLegacySkill((0, import_node_path23.join)(this.managedSkillsDirectory, command), entry.hash);
60975
61023
  await removeExactLegacySkill((0, import_node_path23.join)(this.compatibilitySkillsDirectory, command), entry.hash);
60976
61024
  }
60977
- await (0, import_promises5.rm)(this.legacyManifestPath, { force: true });
61025
+ await (0, import_promises6.rm)(this.legacyManifestPath, { force: true });
60978
61026
  }
60979
61027
  async ensureCached(entry) {
60980
61028
  const cacheDirectory = (0, import_node_path23.join)(
@@ -60984,7 +61032,7 @@ var RuntimeSkillManager = class _RuntimeSkillManager {
60984
61032
  entry.contentHash.slice("sha256:".length)
60985
61033
  );
60986
61034
  if (await packageMatches(cacheDirectory, entry.contentHash)) return cacheDirectory;
60987
- await (0, import_promises5.rm)(cacheDirectory, { recursive: true, force: true });
61035
+ await (0, import_promises6.rm)(cacheDirectory, { recursive: true, force: true });
60988
61036
  const bytes = await this.downloadBundle(entry);
60989
61037
  if (bytes.byteLength !== entry.compressedBytes) {
60990
61038
  throw new Error(
@@ -61002,12 +61050,12 @@ var RuntimeSkillManager = class _RuntimeSkillManager {
61002
61050
  expectedContentHash: entry.contentHash
61003
61051
  });
61004
61052
  try {
61005
- await (0, import_promises5.rename)(pendingDirectory, cacheDirectory);
61053
+ await (0, import_promises6.rename)(pendingDirectory, cacheDirectory);
61006
61054
  } catch (error61) {
61007
61055
  if (!await packageMatches(cacheDirectory, entry.contentHash)) throw error61;
61008
61056
  }
61009
61057
  } finally {
61010
- await (0, import_promises5.rm)(pendingDirectory, { recursive: true, force: true });
61058
+ await (0, import_promises6.rm)(pendingDirectory, { recursive: true, force: true });
61011
61059
  }
61012
61060
  return cacheDirectory;
61013
61061
  }
@@ -61025,8 +61073,8 @@ var RuntimeSkillManager = class _RuntimeSkillManager {
61025
61073
  let installedPending = false;
61026
61074
  let completed = false;
61027
61075
  try {
61028
- await (0, import_promises5.cp)(cacheDirectory, pending, { recursive: true, errorOnExist: true, force: false });
61029
- await (0, import_promises5.writeFile)(
61076
+ await (0, import_promises6.cp)(cacheDirectory, pending, { recursive: true, errorOnExist: true, force: false });
61077
+ await (0, import_promises6.writeFile)(
61030
61078
  (0, import_node_path23.join)(pending, ".alan-managed.json"),
61031
61079
  `${JSON.stringify(markerFor(entry), null, 2)}
61032
61080
  `,
@@ -61036,14 +61084,14 @@ var RuntimeSkillManager = class _RuntimeSkillManager {
61036
61084
  throw new Error("Pending managed Skill projection failed content verification");
61037
61085
  }
61038
61086
  if (await pathExists2(destination)) {
61039
- await (0, import_promises5.rename)(destination, backup);
61087
+ await (0, import_promises6.rename)(destination, backup);
61040
61088
  movedExisting = true;
61041
61089
  }
61042
61090
  try {
61043
- await (0, import_promises5.rename)(pending, destination);
61091
+ await (0, import_promises6.rename)(pending, destination);
61044
61092
  installedPending = true;
61045
61093
  } catch (error61) {
61046
- if (movedExisting) await (0, import_promises5.rename)(backup, destination);
61094
+ if (movedExisting) await (0, import_promises6.rename)(backup, destination);
61047
61095
  throw error61;
61048
61096
  }
61049
61097
  const inspected = await inspectSkillPackage(destination, { expectedName: null });
@@ -61052,18 +61100,18 @@ var RuntimeSkillManager = class _RuntimeSkillManager {
61052
61100
  }
61053
61101
  await this.ensureCompatibilityProjection(entry, destination);
61054
61102
  completed = true;
61055
- await (0, import_promises5.rm)(backup, { recursive: true, force: true });
61103
+ await (0, import_promises6.rm)(backup, { recursive: true, force: true });
61056
61104
  return inspected.contentHash;
61057
61105
  } catch (error61) {
61058
61106
  if (!completed && installedPending) {
61059
- await (0, import_promises5.rm)(destination, { recursive: true, force: true });
61060
- if (movedExisting && await pathExists2(backup)) await (0, import_promises5.rename)(backup, destination);
61107
+ await (0, import_promises6.rm)(destination, { recursive: true, force: true });
61108
+ if (movedExisting && await pathExists2(backup)) await (0, import_promises6.rename)(backup, destination);
61061
61109
  }
61062
61110
  throw error61;
61063
61111
  } finally {
61064
- await (0, import_promises5.rm)(pending, { recursive: true, force: true });
61112
+ await (0, import_promises6.rm)(pending, { recursive: true, force: true });
61065
61113
  if (completed || !movedExisting) {
61066
- await (0, import_promises5.rm)(backup, { recursive: true, force: true });
61114
+ await (0, import_promises6.rm)(backup, { recursive: true, force: true });
61067
61115
  }
61068
61116
  }
61069
61117
  }
@@ -61104,7 +61152,7 @@ var RuntimeSkillManager = class _RuntimeSkillManager {
61104
61152
  });
61105
61153
  continue;
61106
61154
  }
61107
- await (0, import_promises5.rm)(destination, { recursive: true, force: true });
61155
+ await (0, import_promises6.rm)(destination, { recursive: true, force: true });
61108
61156
  } else {
61109
61157
  failures.push({
61110
61158
  skillId: recorded.skillId,
@@ -61119,7 +61167,7 @@ var RuntimeSkillManager = class _RuntimeSkillManager {
61119
61167
  return failures;
61120
61168
  }
61121
61169
  async ensureCompatibilityProjection(entry, canonicalDirectory) {
61122
- await (0, import_promises5.mkdir)(this.compatibilitySkillsDirectory, { recursive: true, mode: 448 });
61170
+ await (0, import_promises6.mkdir)(this.compatibilitySkillsDirectory, { recursive: true, mode: 448 });
61123
61171
  const destination = (0, import_node_path23.join)(
61124
61172
  this.compatibilitySkillsDirectory,
61125
61173
  this.projectionDirectoryName(entry.runtimeDirectory)
@@ -61129,23 +61177,23 @@ var RuntimeSkillManager = class _RuntimeSkillManager {
61129
61177
  throw unmanagedCompatibilityConflict(entry.runtimeDirectory);
61130
61178
  }
61131
61179
  try {
61132
- await (0, import_promises5.symlink)(canonicalDirectory, destination, "dir");
61180
+ await (0, import_promises6.symlink)(canonicalDirectory, destination, "dir");
61133
61181
  return;
61134
61182
  } catch (error61) {
61135
61183
  if (!isSymlinkUnsupported(error61)) throw error61;
61136
61184
  }
61137
61185
  const pending = `${destination}.pending-${process.pid}-${(0, import_node_crypto17.randomBytes)(6).toString("hex")}`;
61138
61186
  try {
61139
- await (0, import_promises5.cp)(canonicalDirectory, pending, { recursive: true, errorOnExist: true, force: false });
61140
- await (0, import_promises5.writeFile)(
61187
+ await (0, import_promises6.cp)(canonicalDirectory, pending, { recursive: true, errorOnExist: true, force: false });
61188
+ await (0, import_promises6.writeFile)(
61141
61189
  (0, import_node_path23.join)(pending, ".alan-compatibility.json"),
61142
61190
  `${JSON.stringify({ ...markerFor(entry), canonicalDirectory }, null, 2)}
61143
61191
  `,
61144
61192
  { encoding: "utf8", flag: "wx", mode: 384 }
61145
61193
  );
61146
- await (0, import_promises5.rename)(pending, destination);
61194
+ await (0, import_promises6.rename)(pending, destination);
61147
61195
  } finally {
61148
- await (0, import_promises5.rm)(pending, { recursive: true, force: true });
61196
+ await (0, import_promises6.rm)(pending, { recursive: true, force: true });
61149
61197
  }
61150
61198
  }
61151
61199
  async runExclusively(work) {
@@ -61169,29 +61217,29 @@ var RuntimeSkillManager = class _RuntimeSkillManager {
61169
61217
  return this.storageNamespace ? `${runtimeDirectory}--alan-${this.storageNamespace}` : runtimeDirectory;
61170
61218
  }
61171
61219
  async withMachineLock(work) {
61172
- await (0, import_promises5.mkdir)(this.skillsStateDirectory, { recursive: true, mode: 448 });
61220
+ await (0, import_promises6.mkdir)(this.skillsStateDirectory, { recursive: true, mode: 448 });
61173
61221
  const lockDirectory = (0, import_node_path23.join)(this.skillsStateDirectory, "manager.lock");
61174
61222
  const deadline = Date.now() + 3e4;
61175
61223
  while (true) {
61176
61224
  try {
61177
- await (0, import_promises5.mkdir)(lockDirectory, { mode: 448 });
61225
+ await (0, import_promises6.mkdir)(lockDirectory, { mode: 448 });
61178
61226
  try {
61179
- await (0, import_promises5.writeFile)(
61227
+ await (0, import_promises6.writeFile)(
61180
61228
  (0, import_node_path23.join)(lockDirectory, "owner.json"),
61181
61229
  `${JSON.stringify({ pid: process.pid, acquiredAt: (/* @__PURE__ */ new Date()).toISOString() })}
61182
61230
  `,
61183
61231
  { encoding: "utf8", flag: "wx", mode: 384 }
61184
61232
  );
61185
61233
  } catch (error61) {
61186
- await (0, import_promises5.rm)(lockDirectory, { recursive: true, force: true });
61234
+ await (0, import_promises6.rm)(lockDirectory, { recursive: true, force: true });
61187
61235
  throw error61;
61188
61236
  }
61189
61237
  break;
61190
61238
  } catch (error61) {
61191
61239
  if (!isAlreadyPresent2(error61)) throw error61;
61192
- const ageMs = await (0, import_promises5.stat)(lockDirectory).then((metadata) => Date.now() - metadata.mtimeMs).catch(() => 0);
61240
+ const ageMs = await (0, import_promises6.stat)(lockDirectory).then((metadata) => Date.now() - metadata.mtimeMs).catch(() => 0);
61193
61241
  if (ageMs > 15 * 6e4) {
61194
- await (0, import_promises5.rm)(lockDirectory, { recursive: true, force: true });
61242
+ await (0, import_promises6.rm)(lockDirectory, { recursive: true, force: true });
61195
61243
  continue;
61196
61244
  }
61197
61245
  if (Date.now() >= deadline) {
@@ -61205,7 +61253,7 @@ var RuntimeSkillManager = class _RuntimeSkillManager {
61205
61253
  try {
61206
61254
  return await work();
61207
61255
  } finally {
61208
- await (0, import_promises5.rm)(lockDirectory, { recursive: true, force: true });
61256
+ await (0, import_promises6.rm)(lockDirectory, { recursive: true, force: true });
61209
61257
  }
61210
61258
  }
61211
61259
  };
@@ -61227,7 +61275,7 @@ async function packageMatches(directory, expectedHash) {
61227
61275
  async function readMarker(directory) {
61228
61276
  try {
61229
61277
  const value2 = JSON.parse(
61230
- await (0, import_promises5.readFile)((0, import_node_path23.join)(directory, ".alan-managed.json"), "utf8")
61278
+ await (0, import_promises6.readFile)((0, import_node_path23.join)(directory, ".alan-managed.json"), "utf8")
61231
61279
  );
61232
61280
  if (typeof value2 !== "object" || value2 === null || !("protocolVersion" in value2) || value2.protocolVersion !== SKILLS_PROTOCOL_VERSION || !("skillId" in value2) || typeof value2.skillId !== "string" || !("versionId" in value2) || typeof value2.versionId !== "string" || !("contentHash" in value2) || typeof value2.contentHash !== "string" || !/^sha256:[a-f0-9]{64}$/.test(value2.contentHash)) {
61233
61281
  return null;
@@ -61238,9 +61286,9 @@ async function readMarker(directory) {
61238
61286
  }
61239
61287
  }
61240
61288
  async function compatibilityProjectionMatches(destination, canonicalDirectory, entry) {
61241
- const metadata = await (0, import_promises5.lstat)(destination);
61289
+ const metadata = await (0, import_promises6.lstat)(destination);
61242
61290
  if (metadata.isSymbolicLink()) {
61243
- const target = await (0, import_promises5.readlink)(destination);
61291
+ const target = await (0, import_promises6.readlink)(destination);
61244
61292
  return (0, import_node_path23.resolve)((0, import_node_path23.dirname)(destination), target) === (0, import_node_path23.resolve)(canonicalDirectory);
61245
61293
  }
61246
61294
  if (!metadata.isDirectory()) return false;
@@ -61249,22 +61297,22 @@ async function compatibilityProjectionMatches(destination, canonicalDirectory, e
61249
61297
  }
61250
61298
  async function removeCompatibilityProjection(destination, canonicalDirectory, projection) {
61251
61299
  if (!await pathExists2(destination)) return true;
61252
- const metadata = await (0, import_promises5.lstat)(destination);
61300
+ const metadata = await (0, import_promises6.lstat)(destination);
61253
61301
  if (metadata.isSymbolicLink()) {
61254
- const target = await (0, import_promises5.readlink)(destination);
61302
+ const target = await (0, import_promises6.readlink)(destination);
61255
61303
  if ((0, import_node_path23.resolve)((0, import_node_path23.dirname)(destination), target) !== (0, import_node_path23.resolve)(canonicalDirectory)) return false;
61256
- await (0, import_promises5.rm)(destination, { force: true });
61304
+ await (0, import_promises6.rm)(destination, { force: true });
61257
61305
  return true;
61258
61306
  }
61259
61307
  const marker = await readCompatibilityMarker(destination);
61260
61308
  if (!marker || !markerMatchesProjection(marker, projection)) return false;
61261
- await (0, import_promises5.rm)(destination, { recursive: true, force: true });
61309
+ await (0, import_promises6.rm)(destination, { recursive: true, force: true });
61262
61310
  return true;
61263
61311
  }
61264
61312
  async function readCompatibilityMarker(directory) {
61265
61313
  try {
61266
61314
  const value2 = JSON.parse(
61267
- await (0, import_promises5.readFile)((0, import_node_path23.join)(directory, ".alan-compatibility.json"), "utf8")
61315
+ await (0, import_promises6.readFile)((0, import_node_path23.join)(directory, ".alan-compatibility.json"), "utf8")
61268
61316
  );
61269
61317
  if (value2.protocolVersion !== SKILLS_PROTOCOL_VERSION || typeof value2.skillId !== "string" || typeof value2.versionId !== "string" || !/^sha256:[a-f0-9]{64}$/.test(value2.contentHash) || typeof value2.canonicalDirectory !== "string") {
61270
61318
  return null;
@@ -61284,7 +61332,7 @@ function markerFor(entry) {
61284
61332
  }
61285
61333
  async function readLegacyManifest(path2) {
61286
61334
  try {
61287
- const value2 = JSON.parse(await (0, import_promises5.readFile)(path2, "utf8"));
61335
+ const value2 = JSON.parse(await (0, import_promises6.readFile)(path2, "utf8"));
61288
61336
  if (!value2 || typeof value2 !== "object" || !("skills" in value2)) return null;
61289
61337
  const skillsValue = value2.skills;
61290
61338
  if (!skillsValue || typeof skillsValue !== "object" || Array.isArray(skillsValue)) return null;
@@ -61302,9 +61350,9 @@ async function readLegacyManifest(path2) {
61302
61350
  }
61303
61351
  async function legacyFileMatches(directory, expectedHash) {
61304
61352
  try {
61305
- const metadata = await (0, import_promises5.lstat)(directory);
61353
+ const metadata = await (0, import_promises6.lstat)(directory);
61306
61354
  if (!metadata.isDirectory() || metadata.isSymbolicLink()) return false;
61307
- const content = await (0, import_promises5.readFile)((0, import_node_path23.join)(directory, "SKILL.md"));
61355
+ const content = await (0, import_promises6.readFile)((0, import_node_path23.join)(directory, "SKILL.md"));
61308
61356
  return (0, import_node_crypto17.createHash)("sha256").update(content).digest("hex").slice(0, 16) === expectedHash;
61309
61357
  } catch {
61310
61358
  return false;
@@ -61312,9 +61360,9 @@ async function legacyFileMatches(directory, expectedHash) {
61312
61360
  }
61313
61361
  async function removeExactLegacySkill(directory, expectedHash) {
61314
61362
  if (!await legacyFileMatches(directory, expectedHash)) return;
61315
- await (0, import_promises5.rm)((0, import_node_path23.join)(directory, "SKILL.md"), { force: true });
61316
- const remaining = await (0, import_promises5.readdir)(directory);
61317
- if (remaining.length === 0) await (0, import_promises5.rm)(directory, { recursive: true, force: true });
61363
+ await (0, import_promises6.rm)((0, import_node_path23.join)(directory, "SKILL.md"), { force: true });
61364
+ const remaining = await (0, import_promises6.readdir)(directory);
61365
+ if (remaining.length === 0) await (0, import_promises6.rm)(directory, { recursive: true, force: true });
61318
61366
  }
61319
61367
  function markerMatchesProjection(marker, projection) {
61320
61368
  return marker.skillId === projection.skillId && marker.versionId === projection.versionId && marker.contentHash === projection.contentHash;
@@ -61407,7 +61455,7 @@ function localTextMediaType(path2) {
61407
61455
  }
61408
61456
  async function pathExists2(path2) {
61409
61457
  try {
61410
- await (0, import_promises5.lstat)(path2);
61458
+ await (0, import_promises6.lstat)(path2);
61411
61459
  return true;
61412
61460
  } catch (error61) {
61413
61461
  if (isMissingPath2(error61)) return false;
@@ -63220,7 +63268,7 @@ async function printDoctor(args = []) {
63220
63268
  }
63221
63269
 
63222
63270
  // src/install-command.ts
63223
- var import_promises6 = require("timers/promises");
63271
+ var import_promises7 = require("timers/promises");
63224
63272
 
63225
63273
  // src/mcp-config-adapters.ts
63226
63274
  var import_node_crypto20 = require("crypto");
@@ -63393,10 +63441,7 @@ var cursorAdapter = {
63393
63441
  mcpServers[s.name] = {
63394
63442
  type: "http",
63395
63443
  url: s.url,
63396
- headers: s.name === "alan" ? {
63397
- Authorization: `\${env:ALAN_MCP_AUTHORIZATION}`,
63398
- "x-alan-run-id": `\${env:ALAN_RUN_ID}`
63399
- } : s.headers
63444
+ headers: s.headers
63400
63445
  };
63401
63446
  } else {
63402
63447
  mcpServers[s.name] = {
@@ -63946,11 +63991,7 @@ function buildAlanMcpServers(apiUrl) {
63946
63991
  return {
63947
63992
  alan: {
63948
63993
  type: "http",
63949
- url: new URL("/mcp", apiUrl).toString(),
63950
- headers: {
63951
- Authorization: `\${ALAN_MCP_AUTHORIZATION}`,
63952
- "x-alan-run-id": `\${ALAN_RUN_ID}`
63953
- }
63994
+ url: new URL("/mcp", apiUrl).toString()
63954
63995
  }
63955
63996
  };
63956
63997
  }
@@ -65542,7 +65583,7 @@ async function setupWindowsRuntime(commandArgs) {
65542
65583
  throw new Error("Windows runtime setup completed without a local readiness endpoint");
65543
65584
  }
65544
65585
  const probe = () => probeLocalDaemon(localApiPort, localApiToken, Math.min(250, remainingMs()));
65545
- const poll = () => (0, import_promises6.setTimeout)(Math.min(100, remainingMs()), void 0, { signal: controller.signal });
65586
+ const poll = () => (0, import_promises7.setTimeout)(Math.min(100, remainingMs()), void 0, { signal: controller.signal });
65546
65587
  if (runtimeIdentityChanged) {
65547
65588
  while (true) {
65548
65589
  const status = await probe();
@@ -66887,7 +66928,7 @@ function cgroupDirectory(text) {
66887
66928
  }
66888
66929
  async function collectAgentResourceDiagnostics(options = {}) {
66889
66930
  const platform6 = options.platform ?? process.platform;
66890
- const readFile7 = async (path2) => {
66931
+ const readFile8 = async (path2) => {
66891
66932
  try {
66892
66933
  return await (options.readFile ?? readResourceFile)(path2);
66893
66934
  } catch {
@@ -66904,11 +66945,11 @@ async function collectAgentResourceDiagnostics(options = {}) {
66904
66945
  };
66905
66946
  if (platform6 !== "linux") return sample;
66906
66947
  const [meminfo, memoryPsi, cpuPsi, ioPsi, cgroup] = await Promise.all([
66907
- readFile7("/proc/meminfo"),
66908
- readFile7("/proc/pressure/memory"),
66909
- readFile7("/proc/pressure/cpu"),
66910
- readFile7("/proc/pressure/io"),
66911
- readFile7("/proc/self/cgroup")
66948
+ readFile8("/proc/meminfo"),
66949
+ readFile8("/proc/pressure/memory"),
66950
+ readFile8("/proc/pressure/cpu"),
66951
+ readFile8("/proc/pressure/io"),
66952
+ readFile8("/proc/self/cgroup")
66912
66953
  ]);
66913
66954
  sample.memoryAvailableBytes = meminfoBytes(meminfo, "MemAvailable");
66914
66955
  sample.swapTotalBytes = meminfoBytes(meminfo, "SwapTotal");
@@ -66920,9 +66961,9 @@ async function collectAgentResourceDiagnostics(options = {}) {
66920
66961
  const directory = cgroupDirectory(cgroup);
66921
66962
  if (!directory) return sample;
66922
66963
  const [current, limit, events] = await Promise.all([
66923
- readFile7(`${directory}/memory.current`),
66924
- readFile7(`${directory}/memory.max`),
66925
- readFile7(`${directory}/memory.events`)
66964
+ readFile8(`${directory}/memory.current`),
66965
+ readFile8(`${directory}/memory.max`),
66966
+ readFile8(`${directory}/memory.events`)
66926
66967
  ]);
66927
66968
  sample.cgroupMemoryCurrentBytes = counter(current?.trim());
66928
66969
  sample.cgroupMemoryLimitBytes = counter(limit?.trim());
@@ -67931,7 +67972,7 @@ async function runSandbox(config2) {
67931
67972
  }
67932
67973
 
67933
67974
  // src/skills/skill-cli.ts
67934
- var import_promises7 = require("fs/promises");
67975
+ var import_promises8 = require("fs/promises");
67935
67976
  var import_node_os20 = require("os");
67936
67977
  var import_node_path31 = require("path");
67937
67978
  async function runSkillsCommand(args) {
@@ -67978,7 +68019,7 @@ async function defaultScanInput(homeDirectory2) {
67978
68019
  }
67979
68020
  async function readProtectedJson(path2) {
67980
68021
  const absolutePath = (0, import_node_path31.resolve)(path2);
67981
- const stat2 = await (0, import_promises7.lstat)(absolutePath);
68022
+ const stat2 = await (0, import_promises8.lstat)(absolutePath);
67982
68023
  if (!stat2.isFile()) throw new Error(`Skill input is not a regular file: ${absolutePath}`);
67983
68024
  if (process.platform !== "win32" && (stat2.mode & 63) !== 0) {
67984
68025
  throw new Error(`Skill input must not be accessible by group or other users: ${absolutePath}`);
@@ -67987,7 +68028,7 @@ async function readProtectedJson(path2) {
67987
68028
  throw new Error(`Skill input must be owned by the current user: ${absolutePath}`);
67988
68029
  }
67989
68030
  if (stat2.size > 2 * 1024 * 1024) throw new Error("Skill input exceeds 2 MiB");
67990
- return JSON.parse(await (0, import_promises7.readFile)(absolutePath, "utf8"));
68031
+ return JSON.parse(await (0, import_promises8.readFile)(absolutePath, "utf8"));
67991
68032
  }
67992
68033
  function option(args, name) {
67993
68034
  const index = args.indexOf(name);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alan-ai-hq/agent-manager",
3
- "version": "0.1.105",
3
+ "version": "0.1.107",
4
4
  "type": "module",
5
5
  "description": "Alan agent runtime — cloud sandbox and local daemon (alan-agent CLI)",
6
6
  "bin": {