agentwheel 0.14.6 → 0.14.8

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/README.md +3 -2
  2. package/dist/index.js +513 -281
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -10,9 +10,9 @@ import {
10
10
 
11
11
  // src/cli/index.ts
12
12
  import { existsSync } from "fs";
13
- import { mkdir as mkdir20, rm as rm11, writeFile as writeFile19 } from "fs/promises";
13
+ import { mkdir as mkdir21, rm as rm11, writeFile as writeFile20 } from "fs/promises";
14
14
  import { homedir as homedir9 } from "os";
15
- import { dirname as dirname28, join as join40, resolve as resolve20 } from "path";
15
+ import { dirname as dirname30, join as join41, resolve as resolve20 } from "path";
16
16
  import { fileURLToPath as fileURLToPath3 } from "url";
17
17
  import { Command } from "commander";
18
18
 
@@ -111,6 +111,7 @@ var targetMappingSchema = z2.object({
111
111
  "codex-plugin",
112
112
  "hermes-plugin",
113
113
  "copilot-plugin",
114
+ "openclaw-subagent",
114
115
  "codex-subagent",
115
116
  "copilot-instruction",
116
117
  "copilot-prompt",
@@ -142,6 +143,20 @@ function supportedInstallationTypes(adapter, artifactType) {
142
143
  }
143
144
  return [...types].sort((a, b) => a.localeCompare(b));
144
145
  }
146
+ function adapterTargetSupport(adapter, artifactType, installationType) {
147
+ if (artifactType === "fragments") return { ok: true };
148
+ const registry = adapter.targets[artifactType];
149
+ const supported = supportedInstallationTypes(adapter, artifactType);
150
+ if (!registry) {
151
+ return { ok: false, reason: "adapter-target-unsupported", supportedInstallationTypes: supported };
152
+ }
153
+ const target = registry[installationType];
154
+ if (target?.enabled) return { ok: true };
155
+ if (target && !target.enabled) {
156
+ return { ok: false, reason: "adapter-target-disabled", supportedInstallationTypes: supported };
157
+ }
158
+ return { ok: false, reason: "adapter-target-unsupported", supportedInstallationTypes: supported };
159
+ }
145
160
  function resolveInstallationTypeForArtifacts(adapter, artifactTypes, requested) {
146
161
  const installableTypes = [...new Set(artifactTypes.filter((type) => type !== "fragments"))];
147
162
  if (installableTypes.length === 0) {
@@ -376,6 +391,9 @@ var openClawAdapter = {
376
391
  local: { enabled: true, dest: "skills" },
377
392
  user: { enabled: true, root: "home", dest: ".openclaw/skills" }
378
393
  },
394
+ subagents: {
395
+ user: { enabled: true, root: "home", dest: ".openclaw/workspace-subagents", semantic: "openclaw-subagent" }
396
+ },
379
397
  mcp: {
380
398
  user: { enabled: true, root: "home", dest: ".openclaw/openclaw.json", merge: "openclaw-json-deep" }
381
399
  },
@@ -469,7 +487,7 @@ async function resolveAdapter(options) {
469
487
  import { execFile as execFile3 } from "child_process";
470
488
  import { mkdtemp as mkdtemp2, rm as rm4, writeFile as writeFile9 } from "fs/promises";
471
489
  import { tmpdir as tmpdir3 } from "os";
472
- import { basename as basename3, join as join5 } from "path";
490
+ import { basename as basename3, dirname as dirname10, join as join5 } from "path";
473
491
  import { promisify as promisify3 } from "util";
474
492
 
475
493
  // src/model/graph-lock.ts
@@ -892,11 +910,33 @@ async function mergeOpenClawJsonFile(sourcePath, destPath) {
892
910
  sourcePath
893
911
  );
894
912
  const current = await pathExists(destPath) ? JSON.parse(await readFile6(destPath, "utf8")) : {};
895
- const merged = deepMerge(current, source);
913
+ const merged = mergeOpenClawJson(current, source);
896
914
  await mkdir4(dirname5(destPath), { recursive: true });
897
915
  await writeFile5(destPath, `${JSON.stringify(merged, null, 2)}
898
916
  `, "utf8");
899
917
  }
918
+ function mergeOpenClawJson(base, incoming, path = []) {
919
+ if (isMcpServerCodexAgentsPath(path) && Array.isArray(incoming)) {
920
+ return incoming;
921
+ }
922
+ if (path.join(".") === "agents.list" && Array.isArray(base) && Array.isArray(incoming)) {
923
+ return mergeOpenClawAgentsById(base, incoming);
924
+ }
925
+ if (Array.isArray(base) && Array.isArray(incoming)) {
926
+ return deepMerge(base, incoming);
927
+ }
928
+ if (isRecord(base) && isRecord(incoming)) {
929
+ const out = { ...base };
930
+ for (const [key, value] of Object.entries(incoming)) {
931
+ out[key] = key in out ? mergeOpenClawJson(out[key], value, [...path, key]) : value;
932
+ }
933
+ return out;
934
+ }
935
+ return incoming;
936
+ }
937
+ function isMcpServerCodexAgentsPath(path) {
938
+ return path.length === 5 && path[0] === "mcp" && path[1] === "servers" && path[3] === "codex" && path[4] === "agents";
939
+ }
900
940
  function expandEnvPlaceholders(value, sourcePath) {
901
941
  if (typeof value === "string") {
902
942
  return value.replace(/\$\{([A-Za-z_][A-Za-z0-9_]*)\}/g, (_match, name) => {
@@ -934,6 +974,24 @@ function normalizeOpenClawMcpServer(server) {
934
974
  delete out.type;
935
975
  return out;
936
976
  }
977
+ function mergeOpenClawAgentsById(base, incoming) {
978
+ const out = [...base];
979
+ const indexById = /* @__PURE__ */ new Map();
980
+ for (const [index, value] of out.entries()) {
981
+ const id = isRecord(value) && typeof value.id === "string" ? value.id : void 0;
982
+ if (id) indexById.set(id, index);
983
+ }
984
+ for (const value of incoming) {
985
+ const id = isRecord(value) && typeof value.id === "string" ? value.id : void 0;
986
+ if (!id || !indexById.has(id)) {
987
+ out.push(value);
988
+ if (id) indexById.set(id, out.length - 1);
989
+ continue;
990
+ }
991
+ out[indexById.get(id)] = value;
992
+ }
993
+ return out;
994
+ }
937
995
 
938
996
  // src/install/manifest.ts
939
997
  import { createHash as createHash2 } from "crypto";
@@ -1908,7 +1966,7 @@ async function applyOperation(operation, context) {
1908
1966
  if (operation.mergeStrategy === "json-deep") {
1909
1967
  await mergeWithTransport(operation.sourcePath, operation.destPath, transport, mergeJsonFile);
1910
1968
  } else if (operation.mergeStrategy === "openclaw-json-deep") {
1911
- await mergeWithTransport(operation.sourcePath, operation.destPath, transport, mergeOpenClawJsonFile);
1969
+ await mergeOpenClawJsonWithTransport(operation.sourcePath, operation.destPath, transport);
1912
1970
  } else if (operation.mergeStrategy === "yaml-deep") {
1913
1971
  await mergeWithTransport(operation.sourcePath, operation.destPath, transport, mergeYamlFile);
1914
1972
  } else if (operation.mergeStrategy === "codex-toml-mcp") {
@@ -2258,13 +2316,58 @@ async function mergeWithTransport(sourcePath, destPath, transport, merge) {
2258
2316
  await rm4(tempRoot, { recursive: true, force: true });
2259
2317
  }
2260
2318
  }
2319
+ async function mergeOpenClawJsonWithTransport(sourcePath, destPath, transport) {
2320
+ const tempRoot = await mkdtemp2(join5(tmpdir3(), "agentwheel-openclaw-merge-"));
2321
+ const localDest = join5(tempRoot, basename3(destPath) || "openclaw.json");
2322
+ const validationPath = transport.kind === "local" ? localDest : `${destPath}.validate-agentwheel-${process.pid}-${Date.now()}`;
2323
+ try {
2324
+ if (await transport.pathExists(destPath)) {
2325
+ await writeFile9(localDest, await transport.readFile(destPath), "utf8");
2326
+ }
2327
+ await mergeOpenClawJsonFile(sourcePath, localDest);
2328
+ if (transport.kind !== "local") {
2329
+ await transport.atomicCopy(localDest, validationPath, "file");
2330
+ }
2331
+ await validateOpenClawConfig(validationPath, destPath, transport);
2332
+ await transport.atomicCopy(localDest, destPath, "file");
2333
+ } finally {
2334
+ if (transport.kind !== "local") await transport.rm(validationPath);
2335
+ await rm4(tempRoot, { recursive: true, force: true });
2336
+ }
2337
+ }
2338
+ async function validateOpenClawConfig(configPath, destPath, transport) {
2339
+ if (!transport.execFile) {
2340
+ throw new Error(`Cannot validate OpenClaw config over ${transport.description}: transport does not support command execution.`);
2341
+ }
2342
+ const openClawHome = dirname10(destPath);
2343
+ const bundledBin = join5(openClawHome, "npm", "node_modules", ".bin", "openclaw");
2344
+ const script = String.raw`
2345
+ set -euo pipefail
2346
+ cfg=$1
2347
+ bundled_bin=$2
2348
+ if [ -x "$bundled_bin" ]; then
2349
+ bin="$bundled_bin"
2350
+ elif command -v openclaw >/dev/null 2>&1; then
2351
+ bin="openclaw"
2352
+ else
2353
+ echo "OpenClaw binary not found; cannot validate $cfg" >&2
2354
+ exit 127
2355
+ fi
2356
+ out=$(OPENCLAW_CONFIG_PATH="$cfg" "$bin" config validate --json 2>&1) || {
2357
+ printf '%s\n' "$out" >&2
2358
+ exit 1
2359
+ }
2360
+ printf '%s' "$out" | node -e 'let s=""; process.stdin.on("data", c => s += c); process.stdin.on("end", () => { const data = JSON.parse(s); if (!data.valid) { console.error(JSON.stringify(data, null, 2)); process.exit(1); } });'
2361
+ `;
2362
+ await transport.execFile("bash", ["-lc", script, "agentwheel-openclaw-validate", configPath, bundledBin]);
2363
+ }
2261
2364
 
2262
2365
  // src/install/plan.ts
2263
- import { basename as basename7, join as join15, relative as relative3 } from "path";
2366
+ import { basename as basename8, join as join16, relative as relative3 } from "path";
2264
2367
 
2265
2368
  // src/staging/codex-subagents.ts
2266
2369
  import { mkdir as mkdir8, readFile as readFile10, writeFile as writeFile10 } from "fs/promises";
2267
- import { basename as basename4, dirname as dirname10, join as join6 } from "path";
2370
+ import { basename as basename4, dirname as dirname11, join as join6 } from "path";
2268
2371
  var requiredCodexAgentFields = ["name", "description", "developer_instructions"];
2269
2372
  async function renderCodexSubagents(artifacts, stageRoot, adapter) {
2270
2373
  if (adapter?.name !== "codex") return artifacts;
@@ -2309,7 +2412,7 @@ async function renderCodexSubagent(artifact, stageRoot) {
2309
2412
  }
2310
2413
  const markdown = await readFile10(markdownPath, "utf8");
2311
2414
  const toml = markdownToCodexAgentToml(agentName, markdown);
2312
- await mkdir8(dirname10(renderedPath), { recursive: true });
2415
+ await mkdir8(dirname11(renderedPath), { recursive: true });
2313
2416
  await writeFile10(renderedPath, toml, "utf8");
2314
2417
  return {
2315
2418
  ...artifact,
@@ -2379,7 +2482,7 @@ function escapeRegExp(value) {
2379
2482
 
2380
2483
  // src/staging/copilot-artifacts.ts
2381
2484
  import { mkdir as mkdir9, readFile as readFile11, writeFile as writeFile11 } from "fs/promises";
2382
- import { basename as basename5, dirname as dirname11, join as join7 } from "path";
2485
+ import { basename as basename5, dirname as dirname12, join as join7 } from "path";
2383
2486
  async function renderCopilotArtifacts(artifacts, stageRoot, adapter) {
2384
2487
  if (adapter?.name !== "copilot") return artifacts;
2385
2488
  const names = /* @__PURE__ */ new Set();
@@ -2410,7 +2513,7 @@ async function renderCopilotSubagent(artifact, stageRoot) {
2410
2513
  throw new Error(`Copilot subagent ${artifact.relativePath} must be a .md file or directory containing AGENTS.md.`);
2411
2514
  }
2412
2515
  const markdown = await readFile11(markdownPath, "utf8");
2413
- await mkdir9(dirname11(renderedPath), { recursive: true });
2516
+ await mkdir9(dirname12(renderedPath), { recursive: true });
2414
2517
  await writeFile11(renderedPath, ensureCopilotAgentDescription(agentName, markdown), "utf8");
2415
2518
  return {
2416
2519
  ...artifact,
@@ -2463,15 +2566,84 @@ function yamlString(value) {
2463
2566
  return JSON.stringify(value);
2464
2567
  }
2465
2568
 
2569
+ // src/staging/openclaw-subagents.ts
2570
+ import { mkdir as mkdir10, readFile as readFile12, writeFile as writeFile12 } from "fs/promises";
2571
+ import { basename as basename6, dirname as dirname13, join as join8 } from "path";
2572
+ async function renderOpenClawSubagents(artifacts, stageRoot, adapter) {
2573
+ if (adapter?.name !== "openclaw") return artifacts;
2574
+ const names = /* @__PURE__ */ new Set();
2575
+ const rendered = [];
2576
+ for (const artifact of artifacts) {
2577
+ if (artifact.type !== "subagents") {
2578
+ rendered.push(artifact);
2579
+ continue;
2580
+ }
2581
+ const next = await renderOpenClawSubagent(artifact, stageRoot);
2582
+ if (names.has(next.name)) {
2583
+ throw new Error(`OpenClaw subagents produce duplicate agent id '${next.name}'.`);
2584
+ }
2585
+ names.add(next.name);
2586
+ rendered.push(next);
2587
+ }
2588
+ return rendered;
2589
+ }
2590
+ async function renderOpenClawSubagent(artifact, stageRoot) {
2591
+ const sourcePath = artifact.stagedPath ?? artifact.sourcePath;
2592
+ const agentId = openClawAgentId(artifact);
2593
+ const markdownPath = artifact.kind === "dir" ? join8(sourcePath, "AGENTS.md") : sourcePath;
2594
+ if (artifact.kind === "dir" && !await pathExists(markdownPath)) {
2595
+ throw new Error(`OpenClaw subagent directory ${artifact.relativePath} must contain AGENTS.md.`);
2596
+ }
2597
+ if (artifact.kind === "file" && !artifact.name.toLowerCase().endsWith(".md") && !sourcePath.toLowerCase().endsWith(".md")) {
2598
+ throw new Error(`OpenClaw subagent ${artifact.relativePath} must be a .md file or directory containing AGENTS.md.`);
2599
+ }
2600
+ const parsed = splitFrontmatter3(await readFile12(markdownPath, "utf8"));
2601
+ const body = parsed.body.trim().length > 0 ? parsed.body.trim() : `# ${titleFromAgentId(agentId)}
2602
+
2603
+ ${parsed.description ?? `OpenClaw subagent ${agentId}.`}`;
2604
+ const renderedPath = join8(stageRoot, ".agentwheel-rendered", "openclaw-subagents", agentId, "AGENTS.md");
2605
+ await mkdir10(dirname13(renderedPath), { recursive: true });
2606
+ await writeFile12(renderedPath, `${body}
2607
+ `, "utf8");
2608
+ const renderedDir = dirname13(renderedPath);
2609
+ return {
2610
+ ...artifact,
2611
+ name: agentId,
2612
+ sourcePath: renderedDir,
2613
+ stagedPath: renderedDir,
2614
+ relativePath: join8("subagents", agentId),
2615
+ kind: "dir",
2616
+ hash: await hashPath(renderedDir)
2617
+ };
2618
+ }
2619
+ function openClawAgentId(artifact) {
2620
+ const raw = artifact.kind === "dir" ? artifact.name : basename6(artifact.name);
2621
+ return raw.replace(/\.agent\.md$/i, "").replace(/\.md$/i, "");
2622
+ }
2623
+ function splitFrontmatter3(markdown) {
2624
+ const match = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?/.exec(markdown);
2625
+ if (!match) return { body: markdown };
2626
+ const frontmatter = match[1] ?? "";
2627
+ const body = markdown.slice(match[0].length);
2628
+ const description = frontmatter.split(/\r?\n/).map((line) => /^description:\s*(?:"([^"]*)"|'([^']*)'|(.+))\s*$/.exec(line.trim())).find((item) => item !== null);
2629
+ return {
2630
+ body,
2631
+ description: description ? (description[1] ?? description[2] ?? description[3] ?? "").trim() : void 0
2632
+ };
2633
+ }
2634
+ function titleFromAgentId(agentId) {
2635
+ return agentId.split(/[-_]/g).filter(Boolean).map((part) => `${part.slice(0, 1).toUpperCase()}${part.slice(1)}`).join(" ");
2636
+ }
2637
+
2466
2638
  // src/targets/plugins/claude.ts
2467
- import { join as join9 } from "path";
2639
+ import { join as join10 } from "path";
2468
2640
 
2469
2641
  // src/targets/plugins/common.ts
2470
- import { readFile as readFile12 } from "fs/promises";
2471
- import { join as join8 } from "path";
2642
+ import { readFile as readFile13 } from "fs/promises";
2643
+ import { join as join9 } from "path";
2472
2644
  import { parseDocument } from "yaml";
2473
2645
  function pluginStateRoot(request) {
2474
- return join8(
2646
+ return join9(
2475
2647
  request.targetRoot,
2476
2648
  ".agentwheel",
2477
2649
  "plugins",
@@ -2489,16 +2661,16 @@ function safeNameSegment(value) {
2489
2661
  return normalized.length > 0 ? normalized : "unnamed";
2490
2662
  }
2491
2663
  async function jsonPluginName(root, relativeManifestPath, fallback) {
2492
- const manifestPath = join8(root, relativeManifestPath);
2664
+ const manifestPath = join9(root, relativeManifestPath);
2493
2665
  if (!await pathExists(manifestPath)) return fallback;
2494
- const parsed = JSON.parse(await readFile12(manifestPath, "utf8"));
2666
+ const parsed = JSON.parse(await readFile13(manifestPath, "utf8"));
2495
2667
  return typeof parsed.name === "string" && parsed.name.trim().length > 0 ? parsed.name.trim() : fallback;
2496
2668
  }
2497
2669
  async function yamlPluginName(root, relativeManifestPaths, fallback) {
2498
2670
  for (const relativeManifestPath of relativeManifestPaths) {
2499
- const manifestPath = join8(root, relativeManifestPath);
2671
+ const manifestPath = join9(root, relativeManifestPath);
2500
2672
  if (!await pathExists(manifestPath)) continue;
2501
- const document = parseDocument(await readFile12(manifestPath, "utf8"));
2673
+ const document = parseDocument(await readFile13(manifestPath, "utf8"));
2502
2674
  const parsed = document.toJSON();
2503
2675
  if (!isRecord4(parsed)) continue;
2504
2676
  for (const key of ["name", "module", "package"]) {
@@ -2527,7 +2699,7 @@ async function claudePluginSpec(request) {
2527
2699
  packageName: request.artifact.packageName,
2528
2700
  installName: request.installName
2529
2701
  });
2530
- const marketplaceRoot = join9(stateRoot, "marketplace");
2702
+ const marketplaceRoot = join10(stateRoot, "marketplace");
2531
2703
  const scope = claudeScope(request.installationType);
2532
2704
  const selector = `${pluginName}@${marketplaceName}`;
2533
2705
  return {
@@ -2552,7 +2724,7 @@ function claudeScope(installationType) {
2552
2724
  }
2553
2725
 
2554
2726
  // src/targets/plugins/codex.ts
2555
- import { join as join10 } from "path";
2727
+ import { join as join11 } from "path";
2556
2728
  async function codexPluginSpec(request) {
2557
2729
  const pluginName = await jsonPluginName(request.sourcePath, ".codex-plugin/plugin.json", request.installName);
2558
2730
  const marketplaceName = agentwheelMarketplaceName(request.artifact.packageName, pluginName);
@@ -2563,7 +2735,7 @@ async function codexPluginSpec(request) {
2563
2735
  packageName: request.artifact.packageName,
2564
2736
  installName: request.installName
2565
2737
  });
2566
- const marketplaceRoot = join10(stateRoot, "marketplace");
2738
+ const marketplaceRoot = join11(stateRoot, "marketplace");
2567
2739
  const selector = `${pluginName}@${marketplaceName}`;
2568
2740
  return {
2569
2741
  runtime: "codex",
@@ -2582,7 +2754,7 @@ async function codexPluginSpec(request) {
2582
2754
  }
2583
2755
 
2584
2756
  // src/targets/plugins/copilot.ts
2585
- import { join as join11 } from "path";
2757
+ import { join as join12 } from "path";
2586
2758
  async function copilotPluginSpec(request) {
2587
2759
  if (request.installationType !== "user") {
2588
2760
  throw new Error("Copilot plugins are persistent user-level installs only; pass --installation-type user.");
@@ -2595,7 +2767,7 @@ async function copilotPluginSpec(request) {
2595
2767
  packageName: request.artifact.packageName,
2596
2768
  installName: request.installName
2597
2769
  });
2598
- const pluginRoot = join11(stateRoot, "plugin");
2770
+ const pluginRoot = join12(stateRoot, "plugin");
2599
2771
  return {
2600
2772
  runtime: "copilot",
2601
2773
  pluginName,
@@ -2606,7 +2778,7 @@ async function copilotPluginSpec(request) {
2606
2778
  }
2607
2779
 
2608
2780
  // src/targets/plugins/hermes.ts
2609
- import { join as join12 } from "path";
2781
+ import { join as join13 } from "path";
2610
2782
  async function hermesPluginSpec(request) {
2611
2783
  if (request.installationType !== "user") {
2612
2784
  throw new Error("Hermes plugins are user-level installs only; pass --installation-type user.");
@@ -2619,7 +2791,7 @@ async function hermesPluginSpec(request) {
2619
2791
  packageName: request.artifact.packageName,
2620
2792
  installName: request.installName
2621
2793
  });
2622
- const repoRoot = join12(stateRoot, "repo");
2794
+ const repoRoot = join13(stateRoot, "repo");
2623
2795
  return {
2624
2796
  runtime: "hermes",
2625
2797
  pluginName,
@@ -2630,8 +2802,8 @@ async function hermesPluginSpec(request) {
2630
2802
  }
2631
2803
 
2632
2804
  // src/targets/plugins/openclaw.ts
2633
- import { readFile as readFile13 } from "fs/promises";
2634
- import { join as join13 } from "path";
2805
+ import { readFile as readFile14 } from "fs/promises";
2806
+ import { join as join14 } from "path";
2635
2807
  function openClawPluginInstallCommand(request) {
2636
2808
  return ["openclaw", "plugins", "install", "--force", request.path];
2637
2809
  }
@@ -2658,19 +2830,19 @@ async function openClawPluginSpec(request) {
2658
2830
  }
2659
2831
  async function openClawPluginName(root, fallback) {
2660
2832
  for (const manifestName of ["plugin.json", "openclaw.plugin.json"]) {
2661
- const manifestPath = join13(root, manifestName);
2833
+ const manifestPath = join14(root, manifestName);
2662
2834
  if (!await pathExists(manifestPath)) continue;
2663
- const parsed = JSON.parse(await readFile13(manifestPath, "utf8"));
2835
+ const parsed = JSON.parse(await readFile14(manifestPath, "utf8"));
2664
2836
  if (typeof parsed.name === "string" && parsed.name.trim().length > 0) return parsed.name.trim();
2665
2837
  }
2666
2838
  return fallback;
2667
2839
  }
2668
2840
  async function openClawClawHubPluginMetadata(root, fallback) {
2669
- const metadataPath = join13(root, "clawhub.json");
2841
+ const metadataPath = join14(root, "clawhub.json");
2670
2842
  if (!await pathExists(metadataPath)) {
2671
2843
  throw new Error("OpenClaw ClawHub plugins must contain clawhub.json");
2672
2844
  }
2673
- const parsed = JSON.parse(await readFile13(metadataPath, "utf8"));
2845
+ const parsed = JSON.parse(await readFile14(metadataPath, "utf8"));
2674
2846
  const installSpec = stringField(parsed.installSpec);
2675
2847
  if (!installSpec?.startsWith("clawhub:")) {
2676
2848
  throw new Error("OpenClaw ClawHub plugin metadata must declare installSpec starting with clawhub:");
@@ -2709,11 +2881,6 @@ async function semanticPluginSpecForArtifact(request) {
2709
2881
  return void 0;
2710
2882
  }
2711
2883
 
2712
- // src/validation/artifacts.ts
2713
- import { readFile as readFile14 } from "fs/promises";
2714
- import { basename as basename6, join as join14 } from "path";
2715
- import { parseDocument as parseDocument2 } from "yaml";
2716
-
2717
2884
  // src/model/selection.ts
2718
2885
  function artifactSelectorKey(artifact) {
2719
2886
  return `${artifact.type}/${artifact.name}`;
@@ -2764,7 +2931,51 @@ function subagentBaseName(name) {
2764
2931
  return name.replace(/\.agent\.md$/i, "").replace(/\.toml$/i, "").replace(/\.md$/i, "");
2765
2932
  }
2766
2933
 
2934
+ // src/validation/adapter-targets.ts
2935
+ function filterArtifactsByAdapterTargets(artifacts, adapter, installationType, options = {}) {
2936
+ const skipped = [];
2937
+ const installable = artifacts.filter((artifact) => {
2938
+ if (artifact.type === "fragments") return true;
2939
+ const support = adapterTargetSupport(adapter, artifact.type, installationType);
2940
+ if (support.ok) return true;
2941
+ const selector = artifactSelectorKey(artifact);
2942
+ skipped.push({ selector, artifactType: artifact.type, support });
2943
+ options.warn?.(skipWarning(selector, adapter, installationType, artifact.type, support));
2944
+ return false;
2945
+ });
2946
+ const before = artifacts.filter((artifact) => artifact.type !== "fragments");
2947
+ const after = installable.filter((artifact) => artifact.type !== "fragments");
2948
+ if (before.length > 0 && after.length === 0) {
2949
+ throw new Error(
2950
+ `${unsupportedSummary(adapter, installationType, skipped)} No installable artifacts remain for adapter ${adapter.name}/${installationType} after skipping unsupported targets: ${skipped.map((item) => item.selector).join(", ")}`
2951
+ );
2952
+ }
2953
+ return installable;
2954
+ }
2955
+ function unsupportedSummary(adapter, installationType, skipped) {
2956
+ const types = [...new Set(skipped.map((item) => item.artifactType))].sort((a, b) => a.localeCompare(b));
2957
+ if (types.length !== 1) {
2958
+ return `Adapter ${adapter.name} does not support selected artifact targets for installation type '${installationType}'.`;
2959
+ }
2960
+ const type = types[0];
2961
+ const supported = [...new Set(skipped.flatMap((item) => item.support.supportedInstallationTypes))].sort((a, b) => a.localeCompare(b));
2962
+ if (supported.length > 0) {
2963
+ return `Adapter ${adapter.name} does not support ${type} artifacts for installation type '${installationType}'. Supported: ${supported.join(", ")}.`;
2964
+ }
2965
+ return `Adapter ${adapter.name} does not support ${type} artifacts for any installation type.`;
2966
+ }
2967
+ function skipWarning(selector, adapter, installationType, artifactType, support) {
2968
+ if (support.reason === "adapter-target-disabled") {
2969
+ return `skip ${selector} (selected but adapter-target-disabled: ${adapter.name}/${installationType} disables ${artifactType})`;
2970
+ }
2971
+ const suffix = support.supportedInstallationTypes.length > 0 ? `; supported installation types: ${support.supportedInstallationTypes.join(", ")}` : "";
2972
+ return `skip ${selector} (selected but adapter-target-unsupported: ${adapter.name}/${installationType} has no enabled target for ${artifactType}${suffix})`;
2973
+ }
2974
+
2767
2975
  // src/validation/artifacts.ts
2976
+ import { readFile as readFile15 } from "fs/promises";
2977
+ import { basename as basename7, join as join15 } from "path";
2978
+ import { parseDocument as parseDocument2 } from "yaml";
2768
2979
  var behavioralRuleFormats = ["markdown-rule", "claude-markdown-rule", "copilot-instruction-rule"];
2769
2980
  var pluginFormats = ["claude-plugin", "codex-plugin", "hermes-plugin", "copilot-plugin", "openclaw-plugin", "openclaw-clawhub-plugin"];
2770
2981
  async function filterArtifactsByInstallFormat(artifacts, adapter, installationType, options = {}) {
@@ -2875,7 +3086,7 @@ async function inferArtifactFormat(artifact, target) {
2875
3086
  return void 0;
2876
3087
  }
2877
3088
  if (artifact.type === "plugins" && target.semantic === "openclaw-plugin") {
2878
- if (artifact.kind === "dir" && await pathExists(join14(artifactPath(artifact), "clawhub.json"))) return "openclaw-clawhub-plugin";
3089
+ if (artifact.kind === "dir" && await pathExists(join15(artifactPath(artifact), "clawhub.json"))) return "openclaw-clawhub-plugin";
2879
3090
  if (artifact.kind === "dir" && (await openClawPluginManifestPaths(artifact)).length > 0) return "openclaw-plugin";
2880
3091
  }
2881
3092
  return void 0;
@@ -2927,7 +3138,7 @@ async function validateGenericStructure(artifact, target) {
2927
3138
  const issues = [];
2928
3139
  if (artifact.type === "skills") {
2929
3140
  if (artifact.kind === "dir") {
2930
- const skillMd = join14(artifactPath(artifact), "SKILL.md");
3141
+ const skillMd = join15(artifactPath(artifact), "SKILL.md");
2931
3142
  if (!await pathExists(skillMd)) {
2932
3143
  issues.push({ artifact, message: "skill directory must contain SKILL.md" });
2933
3144
  } else {
@@ -2939,10 +3150,17 @@ async function validateGenericStructure(artifact, target) {
2939
3150
  issues.push(...await validateSkillFrontmatter(artifact, artifactPath(artifact)));
2940
3151
  }
2941
3152
  }
2942
- if (target.merge === "json-deep") {
3153
+ if (target.merge === "json-deep" || target.merge === "openclaw-json-deep") {
2943
3154
  const parsed = await parseJsonObjectArtifact(artifact);
2944
3155
  if (!parsed.ok) issues.push({ artifact, message: parsed.message });
2945
3156
  }
3157
+ if (artifact.type === "subagents" && target.semantic === "openclaw-subagent") {
3158
+ if (artifact.kind !== "dir") {
3159
+ issues.push({ artifact, message: "OpenClaw subagent artifacts must render to a workspace directory containing AGENTS.md" });
3160
+ } else if (!await pathExists(join15(artifactPath(artifact), "AGENTS.md"))) {
3161
+ issues.push({ artifact, message: "OpenClaw subagent workspace directory must contain AGENTS.md" });
3162
+ }
3163
+ }
2946
3164
  if (target.merge === "yaml-deep") {
2947
3165
  const parsed = await parseYamlObjectArtifact(artifact);
2948
3166
  if (!parsed.ok) issues.push({ artifact, message: parsed.message });
@@ -2960,7 +3178,7 @@ async function validateGenericStructure(artifact, target) {
2960
3178
  async function validateSkillFrontmatter(artifact, skillMdPath) {
2961
3179
  let content;
2962
3180
  try {
2963
- content = await readFile14(skillMdPath, "utf8");
3181
+ content = await readFile15(skillMdPath, "utf8");
2964
3182
  } catch (error) {
2965
3183
  return [{ artifact, message: `could not read SKILL.md: ${errorMessage(error)}` }];
2966
3184
  }
@@ -3013,7 +3231,7 @@ function validatePluginArtifact(artifact, format) {
3013
3231
  async function validateJsonPluginDescriptor(artifact, relativeManifestPath, label) {
3014
3232
  const generic = validatePluginArtifact(artifact, `${label.toLowerCase()}-plugin`);
3015
3233
  if (generic.length > 0) return generic;
3016
- const manifestPath = join14(artifactPath(artifact), relativeManifestPath);
3234
+ const manifestPath = join15(artifactPath(artifact), relativeManifestPath);
3017
3235
  if (!await pathExists(manifestPath)) {
3018
3236
  return [{ artifact, message: `${label} plugins must contain ${relativeManifestPath}` }];
3019
3237
  }
@@ -3024,26 +3242,26 @@ async function validateHermesPlugin(artifact) {
3024
3242
  const generic = validatePluginArtifact(artifact, "hermes-plugin");
3025
3243
  if (generic.length > 0) return generic;
3026
3244
  const root = artifactPath(artifact);
3027
- const manifestPaths = [join14(root, "plugin.yaml"), join14(root, "plugin.yml")];
3245
+ const manifestPaths = [join15(root, "plugin.yaml"), join15(root, "plugin.yml")];
3028
3246
  const manifestPath = await firstExistingPath(manifestPaths);
3029
3247
  if (!manifestPath) {
3030
3248
  return [{ artifact, message: "Hermes plugins must contain plugin.yaml or plugin.yml" }];
3031
3249
  }
3032
3250
  try {
3033
- const document = parseDocument2(await readFile14(manifestPath, "utf8"));
3251
+ const document = parseDocument2(await readFile15(manifestPath, "utf8"));
3034
3252
  if (document.errors.length > 0) {
3035
- return [{ artifact, message: `Hermes ${basename6(manifestPath)} must be valid YAML: ${document.errors[0]?.message ?? "parse error"}` }];
3253
+ return [{ artifact, message: `Hermes ${basename7(manifestPath)} must be valid YAML: ${document.errors[0]?.message ?? "parse error"}` }];
3036
3254
  }
3037
3255
  const parsed = document.toJSON();
3038
3256
  if (!isUnknownRecord(parsed)) {
3039
- return [{ artifact, message: `Hermes ${basename6(manifestPath)} must contain a YAML object` }];
3257
+ return [{ artifact, message: `Hermes ${basename7(manifestPath)} must contain a YAML object` }];
3040
3258
  }
3041
3259
  if (!hasStringField(parsed, "name") && !hasStringField(parsed, "module") && !hasStringField(parsed, "package") && !hasNestedPackageName(parsed)) {
3042
- return [{ artifact, message: `Hermes ${basename6(manifestPath)} must declare a non-empty name, module, or package name` }];
3260
+ return [{ artifact, message: `Hermes ${basename7(manifestPath)} must declare a non-empty name, module, or package name` }];
3043
3261
  }
3044
3262
  return [];
3045
3263
  } catch (error) {
3046
- return [{ artifact, message: `Hermes ${basename6(manifestPath)} must be valid YAML: ${errorMessage(error)}` }];
3264
+ return [{ artifact, message: `Hermes ${basename7(manifestPath)} must be valid YAML: ${errorMessage(error)}` }];
3047
3265
  }
3048
3266
  }
3049
3267
  async function firstExistingPath(paths) {
@@ -3054,16 +3272,16 @@ async function firstExistingPath(paths) {
3054
3272
  }
3055
3273
  async function parseJsonPluginManifest(manifestPath, label) {
3056
3274
  try {
3057
- const parsed = JSON.parse(await readFile14(manifestPath, "utf8"));
3275
+ const parsed = JSON.parse(await readFile15(manifestPath, "utf8"));
3058
3276
  if (!isRecord5(parsed)) {
3059
- return { ok: false, message: `${label} ${basename6(manifestPath)} must be a JSON object` };
3277
+ return { ok: false, message: `${label} ${basename7(manifestPath)} must be a JSON object` };
3060
3278
  }
3061
3279
  if (typeof parsed.name !== "string" || parsed.name.trim().length === 0) {
3062
- return { ok: false, message: `${label} ${basename6(manifestPath)} must declare a non-empty name` };
3280
+ return { ok: false, message: `${label} ${basename7(manifestPath)} must declare a non-empty name` };
3063
3281
  }
3064
3282
  return { ok: true, name: parsed.name.trim() };
3065
3283
  } catch (error) {
3066
- return { ok: false, message: `${label} ${basename6(manifestPath)} must be valid JSON: ${errorMessage(error)}` };
3284
+ return { ok: false, message: `${label} ${basename7(manifestPath)} must be valid JSON: ${errorMessage(error)}` };
3067
3285
  }
3068
3286
  }
3069
3287
  async function validateOpenClawPlugin(artifact) {
@@ -3096,12 +3314,12 @@ async function validateOpenClawClawHubPlugin(artifact) {
3096
3314
  if (artifact.kind !== "dir") {
3097
3315
  return [{ artifact, message: "OpenClaw ClawHub plugins must be directory artifacts" }];
3098
3316
  }
3099
- const metadataPath = join14(artifactPath(artifact), "clawhub.json");
3317
+ const metadataPath = join15(artifactPath(artifact), "clawhub.json");
3100
3318
  if (!await pathExists(metadataPath)) {
3101
3319
  return [{ artifact, message: "OpenClaw ClawHub plugins must contain clawhub.json" }];
3102
3320
  }
3103
3321
  try {
3104
- const parsed = JSON.parse(await readFile14(metadataPath, "utf8"));
3322
+ const parsed = JSON.parse(await readFile15(metadataPath, "utf8"));
3105
3323
  if (!isRecord5(parsed)) {
3106
3324
  return [{ artifact, message: "OpenClaw ClawHub clawhub.json must be a JSON object" }];
3107
3325
  }
@@ -3118,14 +3336,14 @@ async function validateOpenClawClawHubPlugin(artifact) {
3118
3336
  }
3119
3337
  async function openClawPluginManifestPaths(artifact) {
3120
3338
  const root = artifactPath(artifact);
3121
- const candidates = [join14(root, "plugin.json"), join14(root, "openclaw.plugin.json")];
3339
+ const candidates = [join15(root, "plugin.json"), join15(root, "openclaw.plugin.json")];
3122
3340
  const existing = await Promise.all(candidates.map(async (candidate) => await pathExists(candidate) ? candidate : void 0));
3123
3341
  return existing.filter((candidate) => candidate !== void 0);
3124
3342
  }
3125
3343
  async function parseOpenClawPluginManifest(manifestPath) {
3126
- const manifestName = basename6(manifestPath);
3344
+ const manifestName = basename7(manifestPath);
3127
3345
  try {
3128
- const parsed = JSON.parse(await readFile14(manifestPath, "utf8"));
3346
+ const parsed = JSON.parse(await readFile15(manifestPath, "utf8"));
3129
3347
  if (!isRecord5(parsed)) {
3130
3348
  return { ok: false, path: manifestPath, message: `OpenClaw ${manifestName} must be a JSON object` };
3131
3349
  }
@@ -3142,7 +3360,7 @@ async function parseJsonObjectArtifact(artifact) {
3142
3360
  return { ok: false, message: "merge artifacts must be JSON files" };
3143
3361
  }
3144
3362
  try {
3145
- const parsed = JSON.parse(await readFile14(artifactPath(artifact), "utf8"));
3363
+ const parsed = JSON.parse(await readFile15(artifactPath(artifact), "utf8"));
3146
3364
  if (!isRecord5(parsed)) return { ok: false, message: "merge artifacts must contain a JSON object" };
3147
3365
  return { ok: true, value: parsed };
3148
3366
  } catch (error) {
@@ -3154,7 +3372,7 @@ async function parseYamlObjectArtifact(artifact) {
3154
3372
  return { ok: false, message: "merge artifacts must be YAML files" };
3155
3373
  }
3156
3374
  try {
3157
- const document = parseDocument2(await readFile14(artifactPath(artifact), "utf8"));
3375
+ const document = parseDocument2(await readFile15(artifactPath(artifact), "utf8"));
3158
3376
  if (document.errors.length > 0) {
3159
3377
  return { ok: false, message: `merge artifact must be valid YAML: ${document.errors[0]?.message ?? "parse error"}` };
3160
3378
  }
@@ -3181,7 +3399,7 @@ function artifactLabel(artifact) {
3181
3399
  return `${owner}${artifact.type}/${artifact.name}`;
3182
3400
  }
3183
3401
  function hasExtension(artifact, extension) {
3184
- return basename6(artifact.name).toLowerCase().endsWith(extension) || basename6(artifactPath(artifact)).toLowerCase().endsWith(extension);
3402
+ return basename7(artifact.name).toLowerCase().endsWith(extension) || basename7(artifactPath(artifact)).toLowerCase().endsWith(extension);
3185
3403
  }
3186
3404
  function isPluginFormat(value) {
3187
3405
  return value !== void 0 && pluginFormats.includes(value);
@@ -3215,7 +3433,10 @@ function errorMessage(error) {
3215
3433
  // src/install/plan.ts
3216
3434
  async function createCombinedInstallPlan(desiredArtifacts, adapter, targetRoot, manifest, transport = localTransport, options = {}) {
3217
3435
  const requestedInstallationType = options.installationType ?? defaultInstallationType;
3218
- const installableArtifacts = await filterArtifactsByInstallFormat(desiredArtifacts, adapter, requestedInstallationType, { warn: options.warn });
3436
+ const formatCompatibleArtifacts = await filterArtifactsByInstallFormat(desiredArtifacts, adapter, requestedInstallationType, { warn: options.warn });
3437
+ const installableArtifacts = filterArtifactsByAdapterTargets(formatCompatibleArtifacts, adapter, requestedInstallationType, {
3438
+ warn: options.suppressAdapterTargetWarnings ? void 0 : options.warn
3439
+ });
3219
3440
  const installationType = resolveInstallationTypeForArtifacts(adapter, installableArtifacts.map((artifact) => artifact.type), requestedInstallationType);
3220
3441
  const installRoot = installRootForArtifacts(adapter, targetRoot, installationType, installableArtifacts.map((artifact) => artifact.type), transport.kind === "ssh");
3221
3442
  await validateArtifactsForInstall(installableArtifacts, adapter, installationType);
@@ -3359,7 +3580,7 @@ async function createPlanFromOperations(desiredOps, adapter, targetRoot, manifes
3359
3580
  for (const entry of effectiveEntries) {
3360
3581
  if (desired.has(entry.path)) continue;
3361
3582
  const semanticPlugin = entry.semanticPlugin;
3362
- const destPath = semanticPlugin ? targetRoot : join15(targetRoot, entry.path);
3583
+ const destPath = semanticPlugin ? targetRoot : join16(targetRoot, entry.path);
3363
3584
  if (!semanticPlugin && !await transport.pathExists(destPath)) continue;
3364
3585
  const currentHash = semanticPlugin ? entry.hash : await currentEntryHash(entry, destPath, transport);
3365
3586
  if (workspaceOwner && !entryOwnedByWorkspace(entry, workspaceOwner)) {
@@ -3508,15 +3729,15 @@ async function prepareManagedBlockOperations(desiredOps, adapter, targetRoot, tr
3508
3729
  return prepared;
3509
3730
  }
3510
3731
  async function shouldSkipClaudeBridge(adapter, op, targetRoot, transport) {
3511
- if (adapter.name !== "claude" || op.artifactType !== "instructions" || basename7(op.destPath).toLowerCase() !== "claude.md") {
3732
+ if (adapter.name !== "claude" || op.artifactType !== "instructions" || basename8(op.destPath).toLowerCase() !== "claude.md") {
3512
3733
  return false;
3513
3734
  }
3514
- const agentsPath = join15(targetRoot, "AGENTS.md");
3735
+ const agentsPath = join16(targetRoot, "AGENTS.md");
3515
3736
  return claudeInstructionBridgesAgents(op.destPath, agentsPath, transport);
3516
3737
  }
3517
3738
  async function warnOnCopilotDoubleRead(adapter, op, targetRoot, transport, options) {
3518
- if (adapter.name !== "claude" || op.artifactType !== "instructions" || basename7(op.destPath).toLowerCase() !== "claude.md") return;
3519
- const agentsPath = join15(targetRoot, "AGENTS.md");
3739
+ if (adapter.name !== "claude" || op.artifactType !== "instructions" || basename8(op.destPath).toLowerCase() !== "claude.md") return;
3740
+ const agentsPath = join16(targetRoot, "AGENTS.md");
3520
3741
  if (!await transport.pathExists(agentsPath)) return;
3521
3742
  if (await claudeInstructionBridgesAgents(op.destPath, agentsPath, transport)) return;
3522
3743
  options.warn?.("CLAUDE.md and AGENTS.md are separate instruction files; if Copilot is active it may read the managed instructions twice.");
@@ -3600,7 +3821,7 @@ async function canStrictlyAdoptLegacyEntry(entry, op, targetRoot, transport) {
3600
3821
  if (entry.artifactType !== op.artifactType || entry.artifactName !== op.artifactName) return false;
3601
3822
  if (!op.desiredHash || entry.sourceHash !== op.desiredHash) return false;
3602
3823
  if (!packageIdentityMatches(entry, op)) return false;
3603
- const destPath = join15(targetRoot, entry.path);
3824
+ const destPath = join16(targetRoot, entry.path);
3604
3825
  if (!await transport.pathExists(destPath)) return false;
3605
3826
  return await transport.hashPath(destPath) === entry.hash;
3606
3827
  }
@@ -3731,7 +3952,7 @@ function keepForeignManifestEntryOperation(entry, targetRoot, workspaceOwner, op
3731
3952
  artifactType: entry.artifactType,
3732
3953
  artifactName: entry.artifactName,
3733
3954
  kind: entry.kind,
3734
- destPath: operation?.destPath ?? join15(targetRoot, entry.path),
3955
+ destPath: operation?.destPath ?? join16(targetRoot, entry.path),
3735
3956
  relativeDestPath: entry.path,
3736
3957
  desiredHash: entry.sourceHash,
3737
3958
  currentHash: currentHash ?? operation?.currentHash ?? entry.hash,
@@ -3799,7 +4020,7 @@ async function operationForArtifact(artifact, adapter, targetRoot, installationT
3799
4020
  }
3800
4021
  }
3801
4022
  if (artifact.type === "subagents" && target.semantic === "codex-subagent") {
3802
- const destPath2 = join15(targetRoot, target.dest, `${installName.replace(/\.toml$/i, "")}.toml`);
4023
+ const destPath2 = join16(targetRoot, target.dest, `${installName.replace(/\.toml$/i, "")}.toml`);
3803
4024
  return {
3804
4025
  action: "create",
3805
4026
  artifactType: artifact.type,
@@ -3817,7 +4038,7 @@ async function operationForArtifact(artifact, adapter, targetRoot, installationT
3817
4038
  installName: installName.replace(/\.toml$/i, "")
3818
4039
  };
3819
4040
  }
3820
- const destPath = artifact.type === "instructions" || artifact.type === "settings" || isFileTarget(target.dest) ? join15(targetRoot, target.dest) : join15(targetRoot, target.dest, installName);
4041
+ const destPath = artifact.type === "instructions" || artifact.type === "settings" || isFileTarget(target.dest) ? join16(targetRoot, target.dest) : join16(targetRoot, target.dest, installName);
3821
4042
  return {
3822
4043
  action: "create",
3823
4044
  artifactType: artifact.type,
@@ -3896,12 +4117,12 @@ function isPendingInstallOperation(operation) {
3896
4117
  }
3897
4118
 
3898
4119
  // src/install/uninstall.ts
3899
- import { join as join16 } from "path";
4120
+ import { join as join17 } from "path";
3900
4121
  async function createUninstallPlan(manifest, transport = localTransport) {
3901
4122
  const operations = [];
3902
4123
  for (const entry of manifest.entries) {
3903
4124
  const semanticPlugin = "semanticPlugin" in entry ? entry.semanticPlugin : void 0;
3904
- const destPath = semanticPlugin ? manifest.targetRoot : join16(manifest.targetRoot, entry.path);
4125
+ const destPath = semanticPlugin ? manifest.targetRoot : join17(manifest.targetRoot, entry.path);
3905
4126
  if (!semanticPlugin && !await transport.pathExists(destPath)) continue;
3906
4127
  const currentHash = semanticPlugin ? entry.hash : await currentEntryHash2(entry, destPath, transport);
3907
4128
  if (currentHash !== entry.hash) {
@@ -3972,7 +4193,7 @@ async function createOwnershipUninstallPlan(manifest, remainingDesired, adapter,
3972
4193
  const operations = [];
3973
4194
  for (const entry of manifest.entries) {
3974
4195
  const semanticPlugin = "semanticPlugin" in entry ? entry.semanticPlugin : void 0;
3975
- const destPath = semanticPlugin ? manifest.targetRoot : join16(manifest.targetRoot, entry.path);
4196
+ const destPath = semanticPlugin ? manifest.targetRoot : join17(manifest.targetRoot, entry.path);
3976
4197
  if (!semanticPlugin && !await transport.pathExists(destPath)) continue;
3977
4198
  const currentHash = semanticPlugin ? entry.hash : await currentEntryHash2(entry, destPath, transport);
3978
4199
  const remainingOwners = ownersByPath.get(entry.path) ?? [];
@@ -4291,17 +4512,17 @@ function ownerChains(lock, nodeId) {
4291
4512
  }
4292
4513
 
4293
4514
  // src/source/clawhub.ts
4294
- import { mkdir as mkdir10, rm as rm5, writeFile as writeFile12 } from "fs/promises";
4295
- import { basename as basename9, dirname as dirname12, join as join19, resolve as resolve6 } from "path";
4515
+ import { mkdir as mkdir11, rm as rm5, writeFile as writeFile13 } from "fs/promises";
4516
+ import { basename as basename10, dirname as dirname14, join as join20, resolve as resolve6 } from "path";
4296
4517
 
4297
4518
  // src/source/local.ts
4298
4519
  import { createHash as createHash4 } from "crypto";
4299
4520
  import { readdir, stat as stat3 } from "fs/promises";
4300
- import { basename as basename8, join as join18, relative as relative4, resolve as resolve5 } from "path";
4521
+ import { basename as basename9, join as join19, relative as relative4, resolve as resolve5 } from "path";
4301
4522
 
4302
4523
  // src/model/package.ts
4303
- import { readFile as readFile15 } from "fs/promises";
4304
- import { join as join17 } from "path";
4524
+ import { readFile as readFile16 } from "fs/promises";
4525
+ import { join as join18 } from "path";
4305
4526
  import { parse as parse3, printParseErrorCode as printParseErrorCode2 } from "jsonc-parser";
4306
4527
  import { z as z5 } from "zod";
4307
4528
  var legacyArtifactTypeSchema = z5.enum([
@@ -4384,7 +4605,7 @@ var packageManifestNames = [...openPackManifestNames, ...legacyPackageManifestNa
4384
4605
  var warnedLegacyManifestPaths = /* @__PURE__ */ new Set();
4385
4606
  async function findPackageManifestPath(root, options = {}) {
4386
4607
  for (const name of packageManifestNames) {
4387
- const candidate = join17(root, name);
4608
+ const candidate = join18(root, name);
4388
4609
  if (!await pathExists(candidate)) continue;
4389
4610
  if (isLegacyPackageManifestName(name) && options.warnLegacy !== false && !warnedLegacyManifestPaths.has(candidate)) {
4390
4611
  warnedLegacyManifestPaths.add(candidate);
@@ -4397,7 +4618,7 @@ async function findPackageManifestPath(root, options = {}) {
4397
4618
  async function readPackageManifest(root) {
4398
4619
  const path = await findPackageManifestPath(root);
4399
4620
  if (!path) return void 0;
4400
- const content = await readFile15(path, "utf8");
4621
+ const content = await readFile16(path, "utf8");
4401
4622
  const errors = [];
4402
4623
  const parsed = parse3(content, errors, { allowTrailingComma: true, disallowComments: false });
4403
4624
  if (errors.length > 0) {
@@ -4480,29 +4701,29 @@ var LocalSourceDriver = class {
4480
4701
  }
4481
4702
  const artifacts = [];
4482
4703
  const root = resolved.resolvedPath;
4483
- const instructions = await firstExisting([join18(root, "instructions.md"), join18(root, "AGENTS.md")]);
4704
+ const instructions = await firstExisting([join19(root, "instructions.md"), join19(root, "AGENTS.md")]);
4484
4705
  if (instructions) {
4485
4706
  artifacts.push({
4486
4707
  type: "instructions",
4487
- name: basename8(instructions),
4708
+ name: basename9(instructions),
4488
4709
  sourcePath: instructions,
4489
- relativePath: basename8(instructions),
4710
+ relativePath: basename9(instructions),
4490
4711
  kind: "file",
4491
4712
  hash: await hashPath(instructions),
4492
4713
  packageName: resolved.packageName,
4493
4714
  channel: "managed"
4494
4715
  });
4495
4716
  }
4496
- const rulesDir = join18(root, "rules");
4717
+ const rulesDir = join19(root, "rules");
4497
4718
  if (await pathExists(rulesDir)) {
4498
4719
  for (const entry of await sortedDirEntries(rulesDir)) {
4499
- const full = join18(rulesDir, entry.name);
4720
+ const full = join19(rulesDir, entry.name);
4500
4721
  if (entry.isFile()) {
4501
4722
  artifacts.push({
4502
4723
  type: "rules",
4503
4724
  name: entry.name,
4504
4725
  sourcePath: full,
4505
- relativePath: join18("rules", entry.name),
4726
+ relativePath: join19("rules", entry.name),
4506
4727
  kind: "file",
4507
4728
  hash: await hashPath(full),
4508
4729
  packageName: resolved.packageName,
@@ -4511,16 +4732,16 @@ var LocalSourceDriver = class {
4511
4732
  }
4512
4733
  }
4513
4734
  }
4514
- const fragmentsDir = join18(root, "fragments");
4735
+ const fragmentsDir = join19(root, "fragments");
4515
4736
  if (await pathExists(fragmentsDir)) {
4516
4737
  for (const entry of await sortedDirEntries(fragmentsDir)) {
4517
- const full = join18(fragmentsDir, entry.name);
4738
+ const full = join19(fragmentsDir, entry.name);
4518
4739
  if (entry.isFile()) {
4519
4740
  artifacts.push({
4520
4741
  type: "fragments",
4521
4742
  name: entry.name,
4522
4743
  sourcePath: full,
4523
- relativePath: join18("fragments", entry.name),
4744
+ relativePath: join19("fragments", entry.name),
4524
4745
  kind: "file",
4525
4746
  hash: await hashPath(full),
4526
4747
  packageName: resolved.packageName,
@@ -4529,16 +4750,16 @@ var LocalSourceDriver = class {
4529
4750
  }
4530
4751
  }
4531
4752
  }
4532
- const skillsDir = join18(root, "skills");
4753
+ const skillsDir = join19(root, "skills");
4533
4754
  if (await pathExists(skillsDir)) {
4534
4755
  for (const entry of await sortedDirEntries(skillsDir)) {
4535
- const full = join18(skillsDir, entry.name);
4756
+ const full = join19(skillsDir, entry.name);
4536
4757
  if (entry.isDirectory()) {
4537
4758
  artifacts.push({
4538
4759
  type: "skills",
4539
4760
  name: entry.name,
4540
4761
  sourcePath: full,
4541
- relativePath: join18("skills", entry.name),
4762
+ relativePath: join19("skills", entry.name),
4542
4763
  kind: "dir",
4543
4764
  hash: await hashPath(full),
4544
4765
  packageName: resolved.packageName,
@@ -4549,7 +4770,7 @@ var LocalSourceDriver = class {
4549
4770
  type: "skills",
4550
4771
  name: entry.name.replace(/\.md$/, ""),
4551
4772
  sourcePath: full,
4552
- relativePath: join18("skills", entry.name),
4773
+ relativePath: join19("skills", entry.name),
4553
4774
  kind: "file",
4554
4775
  hash: await hashPath(full),
4555
4776
  packageName: resolved.packageName,
@@ -4559,7 +4780,7 @@ var LocalSourceDriver = class {
4559
4780
  }
4560
4781
  }
4561
4782
  for (const type of ["commands", "subagents", "mcp", "hooks", "settings", "plugins"]) {
4562
- const dir = join18(root, type);
4783
+ const dir = join19(root, type);
4563
4784
  if (!await pathExists(dir)) continue;
4564
4785
  artifacts.push(...await listGenericArtifacts(type, dir, type, resolved.packageName));
4565
4786
  }
@@ -4575,7 +4796,7 @@ var LocalSourceDriver = class {
4575
4796
  findings.push({ level: "warning", message: "No instructions.md or AGENTS.md found", path: resolved.resolvedPath });
4576
4797
  }
4577
4798
  for (const artifact of artifacts.filter((item) => item.type === "skills" && item.kind === "dir")) {
4578
- if (!await pathExists(join18(artifact.sourcePath, "SKILL.md"))) {
4799
+ if (!await pathExists(join19(artifact.sourcePath, "SKILL.md"))) {
4579
4800
  findings.push({ level: "warning", message: `Skill directory has no SKILL.md: ${artifact.name}`, path: artifact.sourcePath });
4580
4801
  }
4581
4802
  }
@@ -4599,7 +4820,7 @@ async function hashLocalSource(root, manifest) {
4599
4820
  }
4600
4821
  const provides = [...manifest.provides].sort((a, b) => `${a.type}\0${a.path}`.localeCompare(`${b.type}\0${b.path}`));
4601
4822
  for (const provide of provides) {
4602
- const full = join18(root, provide.path);
4823
+ const full = join19(root, provide.path);
4603
4824
  if (!await pathExists(full)) continue;
4604
4825
  hash.update("provide\0");
4605
4826
  hash.update(provide.type).update("\0");
@@ -4622,27 +4843,27 @@ async function listFromManifest(root, packageName) {
4622
4843
  if (!manifest) return [];
4623
4844
  const artifacts = [];
4624
4845
  for (const provide of manifest.provides) {
4625
- const full = join18(root, provide.path);
4846
+ const full = join19(root, provide.path);
4626
4847
  if (!await pathExists(full)) continue;
4627
4848
  const stats = await stat3(full);
4628
4849
  if (provide.type === "instructions") {
4629
4850
  if (stats.isFile()) {
4630
- artifacts.push(await artifactForFile(provide.type, basename8(full), full, provide.path, packageName, provide, manifest, basename8(full)));
4851
+ artifacts.push(await artifactForFile(provide.type, basename9(full), full, provide.path, packageName, provide, manifest, basename9(full)));
4631
4852
  }
4632
4853
  continue;
4633
4854
  }
4634
4855
  if (stats.isDirectory()) {
4635
4856
  for (const entry of await sortedDirEntries(full)) {
4636
- const child = join18(full, entry.name);
4857
+ const child = join19(full, entry.name);
4637
4858
  if ((provide.type === "skills" || provide.type === "plugins" || provide.type === "subagents") && entry.isDirectory()) {
4638
- artifacts.push(await artifactForDir(provide.type, entry.name, child, join18(provide.path, entry.name), packageName, provide, manifest, entry.name));
4859
+ artifacts.push(await artifactForDir(provide.type, entry.name, child, join19(provide.path, entry.name), packageName, provide, manifest, entry.name));
4639
4860
  } else if (entry.isFile()) {
4640
4861
  const name = provide.type === "rules" && entry.name.endsWith(".md") ? entry.name : entry.name;
4641
- artifacts.push(await artifactForFile(provide.type, name, child, join18(provide.path, entry.name), packageName, provide, manifest, name));
4862
+ artifacts.push(await artifactForFile(provide.type, name, child, join19(provide.path, entry.name), packageName, provide, manifest, name));
4642
4863
  }
4643
4864
  }
4644
4865
  } else if (stats.isFile()) {
4645
- artifacts.push(await artifactForFile(provide.type, basename8(full), full, provide.path, packageName, provide, manifest, basename8(full)));
4866
+ artifacts.push(await artifactForFile(provide.type, basename9(full), full, provide.path, packageName, provide, manifest, basename9(full)));
4646
4867
  }
4647
4868
  }
4648
4869
  return artifacts;
@@ -4650,11 +4871,11 @@ async function listFromManifest(root, packageName) {
4650
4871
  async function listGenericArtifacts(type, dir, relativeRoot, packageName) {
4651
4872
  const artifacts = [];
4652
4873
  for (const entry of await sortedDirEntries(dir)) {
4653
- const full = join18(dir, entry.name);
4874
+ const full = join19(dir, entry.name);
4654
4875
  if (entry.isDirectory()) {
4655
- artifacts.push(await artifactForDir(type, entry.name, full, join18(relativeRoot, entry.name), packageName));
4876
+ artifacts.push(await artifactForDir(type, entry.name, full, join19(relativeRoot, entry.name), packageName));
4656
4877
  } else if (entry.isFile()) {
4657
- artifacts.push(await artifactForFile(type, entry.name, full, join18(relativeRoot, entry.name), packageName));
4878
+ artifacts.push(await artifactForFile(type, entry.name, full, join19(relativeRoot, entry.name), packageName));
4658
4879
  }
4659
4880
  }
4660
4881
  return artifacts;
@@ -4771,7 +4992,7 @@ var ClawHubSourceDriver = class {
4771
4992
  return this.local.list({ ...resolved, driver: "local" });
4772
4993
  }
4773
4994
  async scan(resolved) {
4774
- if (!await pathExists(join19(resolved.resolvedPath, "plugins"))) {
4995
+ if (!await pathExists(join20(resolved.resolvedPath, "plugins"))) {
4775
4996
  return { ok: false, findings: [{ level: "error", message: "ClawHub source has no generated plugin artifact" }] };
4776
4997
  }
4777
4998
  return { ok: true, findings: [] };
@@ -4823,10 +5044,10 @@ async function writeGeneratedPackage(root, packageInfo) {
4823
5044
  artifact: packageInfo.artifact,
4824
5045
  verification: packageInfo.verification
4825
5046
  };
4826
- const pluginPath = join19(root, "plugins", pluginId, "clawhub.json");
5047
+ const pluginPath = join20(root, "plugins", pluginId, "clawhub.json");
4827
5048
  await rm5(root, { recursive: true, force: true });
4828
- await mkdir10(dirname12(pluginPath), { recursive: true });
4829
- await writeFile12(join19(root, "openpack.json"), `${JSON.stringify({
5049
+ await mkdir11(dirname14(pluginPath), { recursive: true });
5050
+ await writeFile13(join20(root, "openpack.json"), `${JSON.stringify({
4830
5051
  schemaVersion: 2,
4831
5052
  name: `clawhub/${name}`,
4832
5053
  version: packageInfo.latestVersion ?? "latest",
@@ -4842,23 +5063,23 @@ async function writeGeneratedPackage(root, packageInfo) {
4842
5063
  ]
4843
5064
  }, null, 2)}
4844
5065
  `, "utf8");
4845
- await writeFile12(pluginPath, `${JSON.stringify(plugin, null, 2)}
5066
+ await writeFile13(pluginPath, `${JSON.stringify(plugin, null, 2)}
4846
5067
  `, "utf8");
4847
5068
  }
4848
5069
  function installNameFor2(value) {
4849
- return basename9(value).replace(/[^a-z0-9._-]+/gi, "-").replace(/^-+|-+$/g, "") || "clawhub-plugin";
5070
+ return basename10(value).replace(/[^a-z0-9._-]+/gi, "-").replace(/^-+|-+$/g, "") || "clawhub-plugin";
4850
5071
  }
4851
5072
  function cachePathFor(packageName, cacheRoot) {
4852
- const root = cacheRoot ? resolve6(cacheRoot) : join19(process.env.HOME ?? ".", ".agentwheel", "cache");
5073
+ const root = cacheRoot ? resolve6(cacheRoot) : join20(process.env.HOME ?? ".", ".agentwheel", "cache");
4853
5074
  const slug2 = `clawhub-${packageName}`.replace(/[^a-z0-9._-]+/gi, "-").replace(/^-+|-+$/g, "");
4854
- return join19(root, slug2 || "clawhub-package");
5075
+ return join20(root, slug2 || "clawhub-package");
4855
5076
  }
4856
5077
 
4857
5078
  // src/source/git.ts
4858
5079
  import { execFile as execFile4 } from "child_process";
4859
- import { cp as cp2, mkdir as mkdir11, rename as rename3, rm as rm6, writeFile as writeFile13 } from "fs/promises";
5080
+ import { cp as cp2, mkdir as mkdir12, rename as rename3, rm as rm6, writeFile as writeFile14 } from "fs/promises";
4860
5081
  import { homedir as homedir2 } from "os";
4861
- import { basename as basename10, dirname as dirname13, join as join20, resolve as resolve7 } from "path";
5082
+ import { basename as basename11, dirname as dirname15, join as join21, resolve as resolve7 } from "path";
4862
5083
  import { promisify as promisify4 } from "util";
4863
5084
  var execFileAsync4 = promisify4(execFile4);
4864
5085
  var GitSourceDriver = class {
@@ -4881,8 +5102,8 @@ var GitSourceDriver = class {
4881
5102
  async fetch(resolved) {
4882
5103
  return withFilesystemLock(`${resolved.resolvedPath}.lock`, resolved.cacheLockTimeoutMs ?? 3e4, async () => {
4883
5104
  const parsed = parseGitSource(resolved.source);
4884
- await mkdir11(resolve7(resolved.resolvedPath, ".."), { recursive: true });
4885
- if (!await pathExists(join20(resolved.resolvedPath, ".git"))) {
5105
+ await mkdir12(resolve7(resolved.resolvedPath, ".."), { recursive: true });
5106
+ if (!await pathExists(join21(resolved.resolvedPath, ".git"))) {
4886
5107
  if (resolved.frozenLock) {
4887
5108
  throw new Error(`Frozen lock requires cached git checkout at ${resolved.resolvedPath}`);
4888
5109
  }
@@ -4949,20 +5170,20 @@ function parseGitSource(source) {
4949
5170
  throw new Error(`Invalid git source: ${source}`);
4950
5171
  }
4951
5172
  function cachePathFor2(url, cacheRoot) {
4952
- const root = cacheRoot ? resolve7(cacheRoot) : join20(homedir2(), ".agentwheel", "cache");
5173
+ const root = cacheRoot ? resolve7(cacheRoot) : join21(homedir2(), ".agentwheel", "cache");
4953
5174
  const slug2 = url.replace(/^[a-z]+:\/\//i, "").replace(/\.git$/i, "").replace(/[^a-z0-9._-]+/gi, "-").replace(/^-+|-+$/g, "");
4954
- return join20(root, slug2 || basename10(url));
5175
+ return join21(root, slug2 || basename11(url));
4955
5176
  }
4956
5177
  async function git(args) {
4957
5178
  return execFileAsync4("git", args, { maxBuffer: 1024 * 1024 * 10 });
4958
5179
  }
4959
5180
  async function snapshotCheckout(checkoutPath, commit) {
4960
- const snapshotPath = join20(dirname13(checkoutPath), `${basename10(checkoutPath)}-${commit.slice(0, 12)}`);
5181
+ const snapshotPath = join21(dirname15(checkoutPath), `${basename11(checkoutPath)}-${commit.slice(0, 12)}`);
4961
5182
  if (await pathExists(snapshotPath)) return snapshotPath;
4962
- const tempPath = join20(dirname13(checkoutPath), `${basename10(snapshotPath)}.tmp-${process.pid}-${Date.now()}`);
5183
+ const tempPath = join21(dirname15(checkoutPath), `${basename11(snapshotPath)}.tmp-${process.pid}-${Date.now()}`);
4963
5184
  await rm6(tempPath, { recursive: true, force: true });
4964
5185
  await cp2(checkoutPath, tempPath, { recursive: true, dereference: true });
4965
- await rm6(join20(tempPath, ".git"), { recursive: true, force: true });
5186
+ await rm6(join21(tempPath, ".git"), { recursive: true, force: true });
4966
5187
  try {
4967
5188
  await rename3(tempPath, snapshotPath);
4968
5189
  } catch (error) {
@@ -4973,12 +5194,12 @@ async function snapshotCheckout(checkoutPath, commit) {
4973
5194
  return snapshotPath;
4974
5195
  }
4975
5196
  async function withFilesystemLock(lockPath, timeoutMs, fn) {
4976
- await mkdir11(dirname13(lockPath), { recursive: true });
5197
+ await mkdir12(dirname15(lockPath), { recursive: true });
4977
5198
  const started = Date.now();
4978
5199
  while (true) {
4979
5200
  try {
4980
- await mkdir11(lockPath);
4981
- await writeFile13(join20(lockPath, "owner.json"), JSON.stringify({ pid: process.pid, createdAt: (/* @__PURE__ */ new Date()).toISOString() }), "utf8");
5201
+ await mkdir12(lockPath);
5202
+ await writeFile14(join21(lockPath, "owner.json"), JSON.stringify({ pid: process.pid, createdAt: (/* @__PURE__ */ new Date()).toISOString() }), "utf8");
4982
5203
  break;
4983
5204
  } catch (error) {
4984
5205
  if (!isAlreadyExists2(error)) throw error;
@@ -4999,8 +5220,8 @@ function isAlreadyExists2(error) {
4999
5220
  }
5000
5221
 
5001
5222
  // src/source/mcp-registry.ts
5002
- import { mkdir as mkdir12, writeFile as writeFile14 } from "fs/promises";
5003
- import { basename as basename11, dirname as dirname14, join as join21, resolve as resolve8 } from "path";
5223
+ import { mkdir as mkdir13, writeFile as writeFile15 } from "fs/promises";
5224
+ import { basename as basename12, dirname as dirname16, join as join22, resolve as resolve8 } from "path";
5004
5225
  var registryBaseUrl = "https://registry.modelcontextprotocol.io/v0.1";
5005
5226
  var sourcePrefix2 = "mcp-registry:";
5006
5227
  var McpRegistrySourceDriver = class {
@@ -5066,7 +5287,7 @@ var McpRegistrySourceDriver = class {
5066
5287
  return this.local.list({ ...resolved, driver: "local" });
5067
5288
  }
5068
5289
  async scan(resolved) {
5069
- if (!await pathExists(join21(resolved.resolvedPath, "mcp"))) {
5290
+ if (!await pathExists(join22(resolved.resolvedPath, "mcp"))) {
5070
5291
  return { ok: false, findings: [{ level: "error", message: "MCP registry source has no generated mcp artifact" }] };
5071
5292
  }
5072
5293
  return { ok: true, findings: [] };
@@ -5106,16 +5327,16 @@ function isSafeHttpUrl(value) {
5106
5327
  }
5107
5328
  async function writeGeneratedPackage2(root, server) {
5108
5329
  const serverId = installNameFor3(server.serverName);
5109
- const mcpPath = join21(root, "mcp", `${serverId}.json`);
5110
- await mkdir12(dirname14(mcpPath), { recursive: true });
5111
- await writeFile14(join21(root, "openpack.json"), `${JSON.stringify({
5330
+ const mcpPath = join22(root, "mcp", `${serverId}.json`);
5331
+ await mkdir13(dirname16(mcpPath), { recursive: true });
5332
+ await writeFile15(join22(root, "openpack.json"), `${JSON.stringify({
5112
5333
  schemaVersion: 2,
5113
5334
  name: `mcp-registry/${server.serverName}`,
5114
5335
  version: server.version ?? "latest",
5115
5336
  provides: [{ type: "mcp", path: "mcp" }]
5116
5337
  }, null, 2)}
5117
5338
  `, "utf8");
5118
- await writeFile14(mcpPath, `${JSON.stringify({
5339
+ await writeFile15(mcpPath, `${JSON.stringify({
5119
5340
  mcpServers: {
5120
5341
  [serverId]: {
5121
5342
  type: "streamable-http",
@@ -5126,23 +5347,23 @@ async function writeGeneratedPackage2(root, server) {
5126
5347
  `, "utf8");
5127
5348
  }
5128
5349
  function installNameFor3(serverName) {
5129
- return basename11(serverName).replace(/[^a-z0-9._-]+/gi, "-").replace(/^-+|-+$/g, "") || "mcp-server";
5350
+ return basename12(serverName).replace(/[^a-z0-9._-]+/gi, "-").replace(/^-+|-+$/g, "") || "mcp-server";
5130
5351
  }
5131
5352
  function cachePathFor3(serverName, cacheRoot) {
5132
- const root = cacheRoot ? resolve8(cacheRoot) : join21(process.env.HOME ?? ".", ".agentwheel", "cache");
5353
+ const root = cacheRoot ? resolve8(cacheRoot) : join22(process.env.HOME ?? ".", ".agentwheel", "cache");
5133
5354
  const slug2 = `mcp-registry-${serverName}`.replace(/[^a-z0-9._-]+/gi, "-").replace(/^-+|-+$/g, "");
5134
- return join21(root, slug2 || "mcp-registry-server");
5355
+ return join22(root, slug2 || "mcp-registry-server");
5135
5356
  }
5136
5357
 
5137
5358
  // src/source/skillkit.ts
5138
- import { cp as cp3, mkdir as mkdir13, readFile as readFile16, rm as rm7 } from "fs/promises";
5359
+ import { cp as cp3, mkdir as mkdir14, readFile as readFile17, rm as rm7 } from "fs/promises";
5139
5360
  import { homedir as homedir3 } from "os";
5140
- import { basename as basename13, dirname as dirname16, join as join23, resolve as resolve9 } from "path";
5361
+ import { basename as basename14, dirname as dirname18, join as join24, resolve as resolve9 } from "path";
5141
5362
  import * as defaultSkillKit from "@skillkit/core";
5142
5363
 
5143
5364
  // src/source/skill-artifacts.ts
5144
5365
  import { readdir as readdir2, stat as stat4 } from "fs/promises";
5145
- import { basename as basename12, dirname as dirname15, extname as extname2, join as join22 } from "path";
5366
+ import { basename as basename13, dirname as dirname17, extname as extname2, join as join23 } from "path";
5146
5367
  async function artifactsFromSkillPaths(paths, packageName) {
5147
5368
  const artifacts = [];
5148
5369
  const seen = /* @__PURE__ */ new Set();
@@ -5164,28 +5385,28 @@ async function discoverSkillPaths(root) {
5164
5385
  async function artifactFromSkillPath(item, packageName) {
5165
5386
  const stats = await stat4(item.path);
5166
5387
  if (stats.isDirectory()) {
5167
- const skillMd = join22(item.path, "SKILL.md");
5388
+ const skillMd = join23(item.path, "SKILL.md");
5168
5389
  if (!await pathExists(skillMd)) return void 0;
5169
- const name = sanitizeSkillName(item.name ?? basename12(item.path));
5390
+ const name = sanitizeSkillName(item.name ?? basename13(item.path));
5170
5391
  return {
5171
5392
  type: "skills",
5172
5393
  name,
5173
5394
  sourcePath: item.path,
5174
- relativePath: join22("skills", name),
5395
+ relativePath: join23("skills", name),
5175
5396
  kind: "dir",
5176
5397
  hash: await hashPath(item.path),
5177
5398
  packageName,
5178
5399
  channel: "managed"
5179
5400
  };
5180
5401
  }
5181
- if (stats.isFile() && basename12(item.path).toLowerCase() === "skill.md") {
5182
- const dir = dirname15(item.path);
5183
- const name = sanitizeSkillName(item.name ?? basename12(dir));
5402
+ if (stats.isFile() && basename13(item.path).toLowerCase() === "skill.md") {
5403
+ const dir = dirname17(item.path);
5404
+ const name = sanitizeSkillName(item.name ?? basename13(dir));
5184
5405
  return {
5185
5406
  type: "skills",
5186
5407
  name,
5187
5408
  sourcePath: dir,
5188
- relativePath: join22("skills", name),
5409
+ relativePath: join23("skills", name),
5189
5410
  kind: "dir",
5190
5411
  hash: await hashPath(dir),
5191
5412
  packageName,
@@ -5193,12 +5414,12 @@ async function artifactFromSkillPath(item, packageName) {
5193
5414
  };
5194
5415
  }
5195
5416
  if (stats.isFile() && extname2(item.path).toLowerCase() === ".md") {
5196
- const name = sanitizeSkillName(item.name ?? basename12(item.path, ".md"));
5417
+ const name = sanitizeSkillName(item.name ?? basename13(item.path, ".md"));
5197
5418
  return {
5198
5419
  type: "skills",
5199
5420
  name,
5200
5421
  sourcePath: item.path,
5201
- relativePath: join22("skills", `${name}.md`),
5422
+ relativePath: join23("skills", `${name}.md`),
5202
5423
  kind: "file",
5203
5424
  hash: await hashPath(item.path),
5204
5425
  packageName,
@@ -5216,7 +5437,7 @@ async function walk(dir, paths) {
5216
5437
  }
5217
5438
  for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {
5218
5439
  if (!entry.isDirectory() || entry.name === ".git" || entry.name === "node_modules") continue;
5219
- await walk(join22(dir, entry.name), paths);
5440
+ await walk(join23(dir, entry.name), paths);
5220
5441
  }
5221
5442
  }
5222
5443
  function sanitizeSkillName(name) {
@@ -5238,7 +5459,7 @@ var SkillKitSourceDriver = class {
5238
5459
  driver: this.name,
5239
5460
  source,
5240
5461
  resolvedPath,
5241
- packageName: `skillkit/${basename13(resolvedPath)}`,
5462
+ packageName: `skillkit/${basename14(resolvedPath)}`,
5242
5463
  mode: options.mode ?? "pinned",
5243
5464
  sourceHash: await hashPath(resolvedPath)
5244
5465
  };
@@ -5272,7 +5493,7 @@ var SkillKitSourceDriver = class {
5272
5493
  if (!provider?.clone) {
5273
5494
  throw new Error("SkillKit provider API unavailable or cannot resolve source. Expected @skillkit/core detectProvider().clone().");
5274
5495
  }
5275
- await mkdir13(dirname16(resolved.resolvedPath), { recursive: true });
5496
+ await mkdir14(dirname18(resolved.resolvedPath), { recursive: true });
5276
5497
  const result = await provider.clone(providerSpec, resolved.resolvedPath, {});
5277
5498
  if (!result.success || !result.path) {
5278
5499
  throw new Error(`SkillKit provider failed to fetch ${spec}: ${result.error ?? "unknown error"}`);
@@ -5316,9 +5537,9 @@ var SkillKitSourceDriver = class {
5316
5537
  throw new Error("SkillKit translateSkill API unavailable");
5317
5538
  }
5318
5539
  for (const skill of this.discover(resolved.resolvedPath)) {
5319
- const skillMd = join23(skill.path, "SKILL.md");
5540
+ const skillMd = join24(skill.path, "SKILL.md");
5320
5541
  if (await pathExists(skillMd)) {
5321
- this.core.translateSkill(await readFile16(skillMd, "utf8"), "openclaw", { sourceFilename: "SKILL.md" });
5542
+ this.core.translateSkill(await readFile17(skillMd, "utf8"), "openclaw", { sourceFilename: "SKILL.md" });
5322
5543
  }
5323
5544
  }
5324
5545
  return resolved;
@@ -5347,8 +5568,8 @@ function normalizeProviderSource(spec) {
5347
5568
  return spec;
5348
5569
  }
5349
5570
  function cachePathFor4(spec, cacheRoot) {
5350
- const root = cacheRoot ? resolve9(cacheRoot) : join23(homedir3(), ".agentwheel", "cache");
5351
- return join23(root, "skillkit", packageSlug(spec));
5571
+ const root = cacheRoot ? resolve9(cacheRoot) : join24(homedir3(), ".agentwheel", "cache");
5572
+ return join24(root, "skillkit", packageSlug(spec));
5352
5573
  }
5353
5574
  function packageSlug(spec) {
5354
5575
  return spec.replace(/^[a-z]+:\/\//i, "").replace(/[^a-z0-9._-]+/gi, "-").replace(/^-+|-+$/g, "") || "source";
@@ -5361,7 +5582,7 @@ function mapSeverity(severity) {
5361
5582
 
5362
5583
  // src/source/vercel-skills.ts
5363
5584
  import { stat as stat5 } from "fs/promises";
5364
- import { basename as basename14, join as join24, relative as relative5, resolve as resolve10 } from "path";
5585
+ import { basename as basename15, join as join25, relative as relative5, resolve as resolve10 } from "path";
5365
5586
  var VercelSkillsSourceDriver = class {
5366
5587
  name = "vercel-skills";
5367
5588
  git = new GitSourceDriver();
@@ -5376,7 +5597,7 @@ var VercelSkillsSourceDriver = class {
5376
5597
  driver: this.name,
5377
5598
  source,
5378
5599
  resolvedPath,
5379
- packageName: `vercel/${basename14(resolvedPath)}`,
5600
+ packageName: `vercel/${basename15(resolvedPath)}`,
5380
5601
  mode: options.mode ?? "pinned",
5381
5602
  sourceHash: await hashPath(resolvedPath)
5382
5603
  };
@@ -5424,7 +5645,7 @@ var VercelSkillsSourceDriver = class {
5424
5645
  };
5425
5646
  async function resolveVercelSkillSubpath(root, subpath) {
5426
5647
  if (!subpath) return root;
5427
- const candidates = [join24(root, subpath), join24(root, "skills", subpath)];
5648
+ const candidates = [join25(root, subpath), join25(root, "skills", subpath)];
5428
5649
  for (const candidate of candidates) {
5429
5650
  if (await pathExists(candidate)) return candidate;
5430
5651
  }
@@ -5494,14 +5715,14 @@ function getSourceDriver(name = "local") {
5494
5715
  }
5495
5716
 
5496
5717
  // src/staging/staging.ts
5497
- import { chmod, cp as cp5, mkdir as mkdir15, mkdtemp as mkdtemp3, readdir as readdir5, stat as stat8 } from "fs/promises";
5498
- import { basename as basename17, dirname as dirname19, join as join27, relative as relative7, resolve as resolve12, sep as sep2 } from "path";
5718
+ import { chmod, cp as cp5, mkdir as mkdir16, mkdtemp as mkdtemp3, readdir as readdir5, stat as stat8 } from "fs/promises";
5719
+ import { basename as basename18, dirname as dirname21, join as join28, relative as relative7, resolve as resolve12, sep as sep2 } from "path";
5499
5720
  import { tmpdir as tmpdir4 } from "os";
5500
5721
 
5501
5722
  // src/compose/markdown.ts
5502
5723
  import { createHash as createHash5 } from "crypto";
5503
- import { readdir as readdir3, readFile as readFile17, stat as stat6, writeFile as writeFile15 } from "fs/promises";
5504
- import { basename as basename15, dirname as dirname17, extname as extname3, join as join25, relative as relative6, resolve as resolve11, sep } from "path";
5724
+ import { readdir as readdir3, readFile as readFile18, stat as stat6, writeFile as writeFile16 } from "fs/promises";
5725
+ import { basename as basename16, dirname as dirname19, extname as extname3, join as join26, relative as relative6, resolve as resolve11, sep } from "path";
5505
5726
  var includePattern = /<!--\s*openpack:include(\?)?\s+([^>]+?)\s*-->/g;
5506
5727
  var escapedIncludePattern = /<!--\s*openpack\\:include(\?)?\s+([^>]+?)\s*-->/g;
5507
5728
  var generatedPattern = /<!--\s*(?:BEGIN|END)\s+openpack:include\b/;
@@ -5516,7 +5737,7 @@ async function expandMarkdownIncludes(artifacts, packageRoot, options = {}) {
5516
5737
  const composedFrom = [];
5517
5738
  for (const file of files) {
5518
5739
  const result = await expandFile(file, packageRoot, composeEntriesForFile(artifact, file), artifactPaths, options);
5519
- if (result.changed) await writeFile15(file, result.content, "utf8");
5740
+ if (result.changed) await writeFile16(file, result.content, "utf8");
5520
5741
  composedFrom.push(...result.composedFrom);
5521
5742
  }
5522
5743
  const stagedPath = artifact.stagedPath ?? artifact.sourcePath;
@@ -5538,7 +5759,7 @@ async function validateMarkdownIncludes(artifacts, packageRoot, options = {}) {
5538
5759
  }
5539
5760
  }
5540
5761
  async function expandFile(file, packageRoot, appendEntries, artifactPaths, options) {
5541
- const raw = await readFile17(file, "utf8");
5762
+ const raw = await readFile18(file, "utf8");
5542
5763
  const owner = ownerSelector(packageRoot, file, options.nodeId);
5543
5764
  const expanded = await expandContent(raw, packageRoot, [owner], artifactPaths, options);
5544
5765
  let content = expanded.content;
@@ -5631,7 +5852,7 @@ async function expandInclude(selector, packageRoot, artifactPaths, options) {
5631
5852
  if (!stats.isFile()) {
5632
5853
  throw new Error(`OpenPack include is not a file: ${displaySelector}`);
5633
5854
  }
5634
- const raw = sourceContent ?? await readFile17(sourcePath, "utf8");
5855
+ const raw = sourceContent ?? await readFile18(sourcePath, "utf8");
5635
5856
  const { optional: _optional, markers: _markers, chain: _chain, ...childOptions } = options;
5636
5857
  const expanded = await expandContent(raw, includePackageRoot, [...options.chain, displaySelector], includeArtifactPaths, {
5637
5858
  ...childOptions,
@@ -5707,7 +5928,7 @@ async function listMarkdownFiles(root) {
5707
5928
  const out = [];
5708
5929
  async function walk2(dir) {
5709
5930
  for (const entry of (await readdir3(dir, { withFileTypes: true })).sort((a, b) => a.name.localeCompare(b.name))) {
5710
- const full = join25(dir, entry.name);
5931
+ const full = join26(dir, entry.name);
5711
5932
  if (entry.isDirectory()) {
5712
5933
  await walk2(full);
5713
5934
  } else if (entry.isFile() && extname3(entry.name).toLowerCase() === ".md") {
@@ -5721,7 +5942,7 @@ async function listMarkdownFiles(root) {
5721
5942
  function composeEntriesForFile(artifact, file) {
5722
5943
  if (!artifact.compose?.length) return [];
5723
5944
  if (artifact.kind === "file") return [resolve11(artifact.stagedPath ?? artifact.sourcePath), resolve11(file)].every(Boolean) && resolve11(artifact.stagedPath ?? artifact.sourcePath) === resolve11(file) ? artifact.compose : [];
5724
- return basename15(file) === "SKILL.md" && dirname17(file) === resolve11(artifact.stagedPath ?? artifact.sourcePath) ? artifact.compose : [];
5945
+ return basename16(file) === "SKILL.md" && dirname19(file) === resolve11(artifact.stagedPath ?? artifact.sourcePath) ? artifact.compose : [];
5725
5946
  }
5726
5947
  function orderedForExpansion(artifacts) {
5727
5948
  return [...artifacts].sort((a, b) => Number(a.type === "fragments") - Number(b.type === "fragments"));
@@ -5767,8 +5988,8 @@ function artifactPathMap(artifacts) {
5767
5988
  }
5768
5989
 
5769
5990
  // src/staging/customize.ts
5770
- import { cp as cp4, mkdir as mkdir14, readdir as readdir4, readFile as readFile18, writeFile as writeFile16 } from "fs/promises";
5771
- import { dirname as dirname18, join as join26 } from "path";
5991
+ import { cp as cp4, mkdir as mkdir15, readdir as readdir4, readFile as readFile19, writeFile as writeFile17 } from "fs/promises";
5992
+ import { dirname as dirname20, join as join27 } from "path";
5772
5993
  async function applyCustomizations(artifacts, options) {
5773
5994
  let next = [...artifacts];
5774
5995
  next = await applyReplacements2(next, options, "override", installableArtifactTypes());
@@ -5784,16 +6005,16 @@ async function applyFragmentCustomizations(artifacts, options) {
5784
6005
  return next.sort((a, b) => `${a.type}:${a.name}:${a.channel}`.localeCompare(`${b.type}:${b.name}:${b.channel}`));
5785
6006
  }
5786
6007
  async function applyInstructionOverlay(artifacts, options) {
5787
- const overlayPath = join26(options.workspaceRoot, ".agentwheel", "overlays", options.adapter.name, "instructions.local.md");
6008
+ const overlayPath = join27(options.workspaceRoot, ".agentwheel", "overlays", options.adapter.name, "instructions.local.md");
5788
6009
  if (!await pathExists(overlayPath)) return artifacts;
5789
6010
  const index = artifacts.findIndex((artifact2) => artifact2.type === "instructions");
5790
6011
  if (index < 0) return artifacts;
5791
6012
  const artifact = artifacts[index];
5792
- const managed = await readFile18(artifact.stagedPath ?? artifact.sourcePath, "utf8");
5793
- const local = await readFile18(overlayPath, "utf8");
5794
- const composedPath = join26(options.stageRoot, ".agentwheel-composed", "instructions", "AGENTS.md");
5795
- await mkdir14(dirname18(composedPath), { recursive: true });
5796
- await writeFile16(
6013
+ const managed = await readFile19(artifact.stagedPath ?? artifact.sourcePath, "utf8");
6014
+ const local = await readFile19(overlayPath, "utf8");
6015
+ const composedPath = join27(options.stageRoot, ".agentwheel-composed", "instructions", "AGENTS.md");
6016
+ await mkdir15(dirname20(composedPath), { recursive: true });
6017
+ await writeFile17(
5797
6018
  composedPath,
5798
6019
  [
5799
6020
  "<!-- BEGIN agentwheel managed: upstream -->",
@@ -5819,19 +6040,19 @@ async function applyInstructionOverlay(artifacts, options) {
5819
6040
  return [...artifacts.slice(0, index), updated, ...artifacts.slice(index + 1)];
5820
6041
  }
5821
6042
  async function applyAdditions(artifacts, options) {
5822
- const additionsRoot = join26(options.workspaceRoot, ".agentwheel", "additions");
5823
- const rulesRoot = join26(additionsRoot, "rules");
6043
+ const additionsRoot = join27(options.workspaceRoot, ".agentwheel", "additions");
6044
+ const rulesRoot = join27(additionsRoot, "rules");
5824
6045
  if (!await pathExists(rulesRoot)) return artifacts;
5825
6046
  const additions = [];
5826
6047
  for (const entry of await sortedDirEntries2(rulesRoot)) {
5827
- const full = join26(rulesRoot, entry.name);
6048
+ const full = join27(rulesRoot, entry.name);
5828
6049
  if (!entry.isFile()) continue;
5829
6050
  additions.push({
5830
6051
  type: "rules",
5831
6052
  name: entry.name,
5832
6053
  sourcePath: full,
5833
6054
  stagedPath: full,
5834
- relativePath: join26("additions", "rules", entry.name),
6055
+ relativePath: join27("additions", "rules", entry.name),
5835
6056
  kind: "file",
5836
6057
  hash: await hashPath(full),
5837
6058
  packageName: options.packageName,
@@ -5855,17 +6076,17 @@ async function applyReplacements2(artifacts, options, channel, artifactTypes) {
5855
6076
  );
5856
6077
  }
5857
6078
  for (const type of artifactTypes) {
5858
- const typeRoot = join26(root, type);
6079
+ const typeRoot = join27(root, type);
5859
6080
  if (!await pathExists(typeRoot)) continue;
5860
6081
  for (const entry of await sortedDirEntries2(typeRoot)) {
5861
6082
  const artifactMapKey = `${type}:${entry.name}`;
5862
6083
  if (seen.has(artifactMapKey)) continue;
5863
6084
  seen.add(artifactMapKey);
5864
- const full = join26(typeRoot, entry.name);
6085
+ const full = join27(typeRoot, entry.name);
5865
6086
  const artifactKind = entry.isDirectory() ? "dir" : "file";
5866
6087
  const existing = byKey.get(artifactMapKey);
5867
- const stagedPath = join26(options.stageRoot, ".agentwheel-composed", channel, type, entry.name);
5868
- await mkdir14(dirname18(stagedPath), { recursive: true });
6088
+ const stagedPath = join27(options.stageRoot, ".agentwheel-composed", channel, type, entry.name);
6089
+ await mkdir15(dirname20(stagedPath), { recursive: true });
5869
6090
  await cp4(full, stagedPath, { recursive: artifactKind === "dir", dereference: true });
5870
6091
  byKey.set(artifactMapKey, {
5871
6092
  ...existing,
@@ -5873,7 +6094,7 @@ async function applyReplacements2(artifacts, options, channel, artifactTypes) {
5873
6094
  name: entry.name,
5874
6095
  sourcePath: full,
5875
6096
  stagedPath,
5876
- relativePath: existing?.relativePath ?? join26(type, entry.name),
6097
+ relativePath: existing?.relativePath ?? join27(type, entry.name),
5877
6098
  kind: artifactKind,
5878
6099
  hash: await hashPath(stagedPath),
5879
6100
  packageName,
@@ -5888,13 +6109,13 @@ function replacementRoots(options, channel) {
5888
6109
  const stateDir = channel === "override" ? "overrides" : "ejected";
5889
6110
  const roots = [];
5890
6111
  if (options.graphNodeId) {
5891
- roots.push({ root: join26(options.workspaceRoot, ".agentwheel", stateDir, ...options.graphNodeId.split("/")), kind: "node" });
6112
+ roots.push({ root: join27(options.workspaceRoot, ".agentwheel", stateDir, ...options.graphNodeId.split("/")), kind: "node" });
5892
6113
  }
5893
6114
  if (options.packageName && options.packageVersion) {
5894
- roots.push({ root: join26(options.workspaceRoot, ".agentwheel", stateDir, ...`${options.packageName}@${options.packageVersion}`.split("/")), kind: "version" });
6115
+ roots.push({ root: join27(options.workspaceRoot, ".agentwheel", stateDir, ...`${options.packageName}@${options.packageVersion}`.split("/")), kind: "version" });
5895
6116
  }
5896
6117
  if (options.packageName) {
5897
- roots.push({ root: join26(options.workspaceRoot, ".agentwheel", stateDir, ...options.packageName.split("/")), kind: "package" });
6118
+ roots.push({ root: join27(options.workspaceRoot, ".agentwheel", stateDir, ...options.packageName.split("/")), kind: "package" });
5898
6119
  }
5899
6120
  return roots;
5900
6121
  }
@@ -5921,15 +6142,15 @@ async function stageResolvedSourceRaw(driver, resolved) {
5921
6142
  return stageResolvedArtifactsRaw(resolved, artifacts);
5922
6143
  }
5923
6144
  async function stageResolvedArtifactsRaw(resolved, artifacts) {
5924
- const root = await mkdtemp3(join27(tmpdir4(), "agentwheel-stage-"));
6145
+ const root = await mkdtemp3(join28(tmpdir4(), "agentwheel-stage-"));
5925
6146
  const stagedArtifacts = [];
5926
6147
  for (const artifact of artifacts) {
5927
- const stagedPath = join27(root, artifact.relativePath);
5928
- await mkdir15(dirname19(stagedPath), { recursive: true });
6148
+ const stagedPath = join28(root, artifact.relativePath);
6149
+ await mkdir16(dirname21(stagedPath), { recursive: true });
5929
6150
  await cp5(artifact.sourcePath, stagedPath, {
5930
6151
  recursive: artifact.kind === "dir",
5931
6152
  dereference: true,
5932
- filter: (path) => !isIgnoredGeneratedEntry(basename17(path))
6153
+ filter: (path) => !isIgnoredGeneratedEntry(basename18(path))
5933
6154
  });
5934
6155
  await composeAssets(artifact, resolved.resolvedPath, stagedPath);
5935
6156
  stagedArtifacts.push({
@@ -5958,7 +6179,8 @@ async function renderStagedBundle(bundle, options = {}) {
5958
6179
  const runtimeSelectedSet = new Set(normalizeArtifactSelectors(options.select, options.skills) ?? []);
5959
6180
  const runtimeArtifacts = options.adapter ? filterArtifactsByRuntime(selectedArtifacts, options.adapter.name, runtimeSelectedSet) : selectedArtifacts;
5960
6181
  const codexRenderedArtifacts = await renderCodexSubagents(runtimeArtifacts, root, options.adapter);
5961
- const renderedArtifacts = await renderCopilotArtifacts(codexRenderedArtifacts, root, options.adapter);
6182
+ const openClawRenderedArtifacts = await renderOpenClawSubagents(codexRenderedArtifacts, root, options.adapter);
6183
+ const renderedArtifacts = await renderCopilotArtifacts(openClawRenderedArtifacts, root, options.adapter);
5962
6184
  const finalArtifacts = options.workspaceRoot && options.adapter ? await applyCustomizations(renderedArtifacts, {
5963
6185
  workspaceRoot: options.workspaceRoot,
5964
6186
  adapter: options.adapter,
@@ -6010,16 +6232,16 @@ async function composeAssets(artifact, packageRoot, stagedPath) {
6010
6232
  }
6011
6233
  for (const asset of artifact.assets) {
6012
6234
  const source = resolvePackagePath(packageRoot, asset.from);
6013
- const dest = join27(stagedPath, asset.into);
6235
+ const dest = join28(stagedPath, asset.into);
6014
6236
  await copyAsset(asset, source, dest);
6015
6237
  }
6016
6238
  }
6017
6239
  async function copyAsset(asset, source, dest) {
6018
6240
  const sourceStats = await stat8(source);
6019
6241
  if (sourceStats.isFile()) {
6020
- if (matchesAny(basename17(source), asset.include)) {
6021
- await mkdir15(dest, { recursive: true });
6022
- await copyAssetFile(source, join27(dest, basename17(source)), asset);
6242
+ if (matchesAny(basename18(source), asset.include)) {
6243
+ await mkdir16(dest, { recursive: true });
6244
+ await copyAssetFile(source, join28(dest, basename18(source)), asset);
6023
6245
  }
6024
6246
  return;
6025
6247
  }
@@ -6027,19 +6249,19 @@ async function copyAsset(asset, source, dest) {
6027
6249
  throw new Error(`Asset include source is not a file or directory: ${source}`);
6028
6250
  }
6029
6251
  if (!asset.include?.length) {
6030
- await mkdir15(dirname19(dest), { recursive: true });
6252
+ await mkdir16(dirname21(dest), { recursive: true });
6031
6253
  await cp5(source, dest, { recursive: true, dereference: true });
6032
6254
  if (asset.mode === "copy") await normalizeCopiedModes(dest);
6033
6255
  return;
6034
6256
  }
6035
6257
  for (const file of await listFiles(source)) {
6036
6258
  const rel = relative7(source, file).replaceAll("\\", "/");
6037
- if (!matchesAny(rel, asset.include) && !matchesAny(basename17(file), asset.include)) continue;
6038
- await copyAssetFile(file, join27(dest, rel), asset);
6259
+ if (!matchesAny(rel, asset.include) && !matchesAny(basename18(file), asset.include)) continue;
6260
+ await copyAssetFile(file, join28(dest, rel), asset);
6039
6261
  }
6040
6262
  }
6041
6263
  async function copyAssetFile(source, dest, asset) {
6042
- await mkdir15(dirname19(dest), { recursive: true });
6264
+ await mkdir16(dirname21(dest), { recursive: true });
6043
6265
  await cp5(source, dest, { dereference: true });
6044
6266
  if (asset.mode === "copy") await chmod(dest, 420);
6045
6267
  }
@@ -6055,7 +6277,7 @@ async function listFiles(root) {
6055
6277
  const out = [];
6056
6278
  async function walk2(dir) {
6057
6279
  for (const entry of (await readdir5(dir, { withFileTypes: true })).sort((a, b) => a.name.localeCompare(b.name))) {
6058
- const full = join27(dir, entry.name);
6280
+ const full = join28(dir, entry.name);
6059
6281
  if (entry.isDirectory()) {
6060
6282
  await walk2(full);
6061
6283
  } else if (entry.isFile()) {
@@ -6074,7 +6296,7 @@ async function normalizeCopiedModes(path) {
6074
6296
  }
6075
6297
  if (!stats.isDirectory()) return;
6076
6298
  for (const entry of await readdir5(path, { withFileTypes: true })) {
6077
- await normalizeCopiedModes(join27(path, entry.name));
6299
+ await normalizeCopiedModes(join28(path, entry.name));
6078
6300
  }
6079
6301
  }
6080
6302
  function matchesAny(path, patterns) {
@@ -6087,9 +6309,9 @@ function matchesGlob(path, pattern) {
6087
6309
  }
6088
6310
 
6089
6311
  // src/model/workspace.ts
6090
- import { readFile as readFile19 } from "fs/promises";
6312
+ import { readFile as readFile20 } from "fs/promises";
6091
6313
  import { homedir as homedir4 } from "os";
6092
- import { dirname as dirname20, join as join28, resolve as resolve13 } from "path";
6314
+ import { dirname as dirname22, join as join29, resolve as resolve13 } from "path";
6093
6315
  import { z as z6 } from "zod";
6094
6316
  var workspacePackageSchema = z6.object({
6095
6317
  name: z6.string().min(1),
@@ -6133,6 +6355,8 @@ var workspaceTrustSchema = z6.object({
6133
6355
  }).default({});
6134
6356
  var workspaceAgentSchema = z6.object({
6135
6357
  adapter: z6.string().min(1),
6358
+ adapterConfig: z6.string().min(1).optional(),
6359
+ adapterModule: z6.string().min(1).optional(),
6136
6360
  root: z6.string().min(1),
6137
6361
  installationType: installationTypeSchema.optional(),
6138
6362
  transport: z6.enum(["local", "ssh"]).default("local"),
@@ -6160,12 +6384,12 @@ var workspaceConfigSchema = z6.object({
6160
6384
  agents: z6.record(z6.string(), workspaceAgentSchema).default({})
6161
6385
  });
6162
6386
  function workspaceConfigPath(workspaceRoot) {
6163
- return join28(workspaceRoot, ".agentwheel", "config.json");
6387
+ return join29(workspaceRoot, ".agentwheel", "config.json");
6164
6388
  }
6165
6389
  async function readWorkspaceConfig(workspaceRoot) {
6166
6390
  const path = workspaceConfigPath(workspaceRoot);
6167
6391
  if (!await pathExists(path)) return emptyWorkspaceConfig();
6168
- return workspaceConfigSchema.parse(JSON.parse(await readFile19(path, "utf8")));
6392
+ return workspaceConfigSchema.parse(JSON.parse(await readFile20(path, "utf8")));
6169
6393
  }
6170
6394
  async function writeWorkspaceConfig(workspaceRoot, config) {
6171
6395
  await writeJsonAtomic(workspaceConfigPath(workspaceRoot), workspaceConfigSchema.parse(config));
@@ -6178,13 +6402,13 @@ function upsertPackage(config, entry) {
6178
6402
  return { schemaVersion: 1, packages, bootstrapSkills: parsed.bootstrapSkills, registry: parsed.registry ?? {}, trust: parsed.trust ?? {}, profiles: parsed.profiles ?? {}, agents: parsed.agents ?? {} };
6179
6403
  }
6180
6404
  function globalWorkspaceConfigPath(globalRoot = homedir4()) {
6181
- return join28(globalRoot, ".agentwheel", "config.json");
6405
+ return join29(globalRoot, ".agentwheel", "config.json");
6182
6406
  }
6183
6407
  async function findWorkspaceRoot(start = process.cwd()) {
6184
6408
  let current = resolve13(start);
6185
6409
  while (true) {
6186
6410
  if (await pathExists(workspaceConfigPath(current))) return current;
6187
- const parent = dirname20(current);
6411
+ const parent = dirname22(current);
6188
6412
  if (parent === current) return resolve13(start);
6189
6413
  current = parent;
6190
6414
  }
@@ -6220,7 +6444,7 @@ function emptyWorkspaceConfig() {
6220
6444
  }
6221
6445
  async function readConfigPath(path) {
6222
6446
  if (!await pathExists(path)) return emptyWorkspaceConfig();
6223
- return workspaceConfigSchema.parse(JSON.parse(await readFile19(path, "utf8")));
6447
+ return workspaceConfigSchema.parse(JSON.parse(await readFile20(path, "utf8")));
6224
6448
  }
6225
6449
  function mergeWorkspaceTrust(global, project) {
6226
6450
  return {
@@ -6235,23 +6459,23 @@ function sortedUnique2(values) {
6235
6459
  }
6236
6460
 
6237
6461
  // src/lifecycle/customization.ts
6238
- import { appendFile, cp as cp6, mkdir as mkdir16, rm as rm9 } from "fs/promises";
6239
- import { dirname as dirname22, join as join31 } from "path";
6462
+ import { appendFile, cp as cp6, mkdir as mkdir17, rm as rm9 } from "fs/promises";
6463
+ import { dirname as dirname24, join as join32 } from "path";
6240
6464
 
6241
6465
  // src/resolve/graph.ts
6242
6466
  import { createHash as createHash6 } from "crypto";
6243
- import { mkdtemp as mkdtemp4, readdir as readdir6, readFile as readFile21, stat as stat10 } from "fs/promises";
6467
+ import { mkdtemp as mkdtemp4, readdir as readdir6, readFile as readFile22, stat as stat10 } from "fs/promises";
6244
6468
  import { tmpdir as tmpdir5 } from "os";
6245
- import { basename as basename18, extname as extname4, join as join30 } from "path";
6469
+ import { basename as basename19, extname as extname4, join as join31 } from "path";
6246
6470
 
6247
6471
  // src/resolve/identity.ts
6248
6472
  import { homedir as homedir6 } from "os";
6249
6473
  import { resolve as resolve15 } from "path";
6250
6474
 
6251
6475
  // src/registry/client.ts
6252
- import { readFile as readFile20, rm as rm8, stat as stat9 } from "fs/promises";
6476
+ import { readFile as readFile21, rm as rm8, stat as stat9 } from "fs/promises";
6253
6477
  import { homedir as homedir5 } from "os";
6254
- import { dirname as dirname21, join as join29, resolve as resolve14 } from "path";
6478
+ import { dirname as dirname23, join as join30, resolve as resolve14 } from "path";
6255
6479
  import { fileURLToPath } from "url";
6256
6480
 
6257
6481
  // src/model/registry.ts
@@ -6355,7 +6579,7 @@ var RegistryClient = class {
6355
6579
  }
6356
6580
  async readCache() {
6357
6581
  if (!await pathExists(this.cachePath)) return void 0;
6358
- return registryCacheSchema.parse(JSON.parse(await readFile20(this.cachePath, "utf8")));
6582
+ return registryCacheSchema.parse(JSON.parse(await readFile21(this.cachePath, "utf8")));
6359
6583
  }
6360
6584
  isExpired(cache, ttlMs) {
6361
6585
  return this.now().getTime() - new Date(cache.fetchedAt).getTime() > ttlMs;
@@ -6374,10 +6598,10 @@ var RegistryClient = class {
6374
6598
  if (await pathExists(filePath)) {
6375
6599
  const fullPath = resolve14(filePath);
6376
6600
  const stats = await stat9(fullPath);
6377
- return readFile20(stats.isDirectory() ? join29(fullPath, "index.json") : fullPath, "utf8");
6601
+ return readFile21(stats.isDirectory() ? join30(fullPath, "index.json") : fullPath, "utf8");
6378
6602
  }
6379
- const resolved = await this.git.fetch(await this.git.resolve(source, { cacheRoot: join29(dirname21(this.cachePath), "registry-repos") }));
6380
- return readFile20(join29(resolved.resolvedPath, "index.json"), "utf8");
6603
+ const resolved = await this.git.fetch(await this.git.resolve(source, { cacheRoot: join30(dirname23(this.cachePath), "registry-repos") }));
6604
+ return readFile21(join30(resolved.resolvedPath, "index.json"), "utf8");
6381
6605
  }
6382
6606
  warnCompatibility(entries) {
6383
6607
  for (const entry of entries) {
@@ -6415,7 +6639,7 @@ function mergeIndexes(indexes) {
6415
6639
  return [...merged.values()].sort((a, b) => a.name.localeCompare(b.name));
6416
6640
  }
6417
6641
  function defaultRegistryCachePath() {
6418
- return join29(homedir5(), ".agentwheel", "registry-cache.json");
6642
+ return join30(homedir5(), ".agentwheel", "registry-cache.json");
6419
6643
  }
6420
6644
  function sameSources(a, b) {
6421
6645
  return a.length === b.length && a.every((source, index) => source === b[index]);
@@ -6665,7 +6889,7 @@ function compareSemver(a, b) {
6665
6889
  var cacheLocks = /* @__PURE__ */ new Map();
6666
6890
  async function resolveDependencyGraph(roots, options) {
6667
6891
  if (roots.length === 0) throw new Error("At least one graph root is required.");
6668
- const graphRoot = await mkdtemp4(join30(tmpdir5(), "agentwheel-graph-"));
6892
+ const graphRoot = await mkdtemp4(join31(tmpdir5(), "agentwheel-graph-"));
6669
6893
  const fetchCache = /* @__PURE__ */ new Map();
6670
6894
  const nodesByKey = /* @__PURE__ */ new Map();
6671
6895
  const rootResults = [];
@@ -7128,7 +7352,7 @@ async function collectIncludeNeeds(artifact, artifactsByRelativePath) {
7128
7352
  const file = stack.shift();
7129
7353
  if (scanned.has(file)) continue;
7130
7354
  scanned.add(file);
7131
- const content = await readFile21(file, "utf8");
7355
+ const content = await readFile22(file, "utf8");
7132
7356
  for (const include of extractOpenPackIncludeSelectors(content)) {
7133
7357
  await collectIncludeSelector(include.raw, include.optional, artifactsByRelativePath, scanned, stack, needs);
7134
7358
  }
@@ -7171,7 +7395,7 @@ async function listMarkdownFiles2(root) {
7171
7395
  const out = [];
7172
7396
  async function walk2(dir) {
7173
7397
  for (const entry of (await readdir6(dir, { withFileTypes: true })).sort((a, b) => a.name.localeCompare(b.name))) {
7174
- const full = join30(dir, entry.name);
7398
+ const full = join31(dir, entry.name);
7175
7399
  if (entry.isDirectory()) {
7176
7400
  await walk2(full);
7177
7401
  } else if (entry.isFile() && extname4(entry.name).toLowerCase() === ".md") {
@@ -7206,7 +7430,7 @@ async function fetchPackage(normalized, mode, options, fetchCache, refOverride)
7206
7430
  const promise = (async () => {
7207
7431
  const driver = getSourceDriver(normalized.driver);
7208
7432
  const resolved = await driver.resolve(normalized.source, {
7209
- cacheRoot: options.cacheRoot ?? join30(options.workspaceRoot, ".agentwheel", "cache"),
7433
+ cacheRoot: options.cacheRoot ?? join31(options.workspaceRoot, ".agentwheel", "cache"),
7210
7434
  mode,
7211
7435
  ref: refOverride ?? normalized.requestedRef,
7212
7436
  frozenLock: hardLockedCheckout
@@ -7216,7 +7440,7 @@ async function fetchPackage(normalized, mode, options, fetchCache, refOverride)
7216
7440
  const exported = await driver.export(translated);
7217
7441
  const manifest = await readPackageManifest(exported.resolvedPath);
7218
7442
  const artifacts = await driver.list(exported);
7219
- const name = manifest?.name ?? exported.packageName ?? basename18(exported.resolvedPath);
7443
+ const name = manifest?.name ?? exported.packageName ?? basename19(exported.resolvedPath);
7220
7444
  const version = manifest?.version ?? exported.packageVersion ?? "0.0.0";
7221
7445
  const sourceHash = exported.sourceHash ?? await hashPath(exported.resolvedPath);
7222
7446
  return {
@@ -7413,8 +7637,8 @@ async function mapLimit(items, limit, fn) {
7413
7637
 
7414
7638
  // src/lifecycle/customization.ts
7415
7639
  async function remember(workspaceRoot, runtime, text) {
7416
- const overlayPath = join31(workspaceRoot, ".agentwheel", "overlays", runtime, "instructions.local.md");
7417
- await mkdir16(dirname22(overlayPath), { recursive: true });
7640
+ const overlayPath = join32(workspaceRoot, ".agentwheel", "overlays", runtime, "instructions.local.md");
7641
+ await mkdir17(dirname24(overlayPath), { recursive: true });
7418
7642
  await appendFile(overlayPath, `${text.trim()}
7419
7643
  `, "utf8");
7420
7644
  return { overlayPath };
@@ -7437,8 +7661,8 @@ async function ejectArtifact(workspaceRoot, item) {
7437
7661
  throw new Error(`Artifact not found: ${item}`);
7438
7662
  }
7439
7663
  const ejectedIdentity = parsed.packageIdentity === parsed.packageName ? parsed.packageIdentity : candidate.nodeId === parsed.packageIdentity ? candidate.nodeId : `${candidate.packageName}@${candidate.packageVersion}`;
7440
- const ejectedPath = join31(workspaceRoot, ".agentwheel", "ejected", ...ejectedIdentity.split("/"), parsed.type, parsed.name);
7441
- await mkdir16(dirname22(ejectedPath), { recursive: true });
7664
+ const ejectedPath = join32(workspaceRoot, ".agentwheel", "ejected", ...ejectedIdentity.split("/"), parsed.type, parsed.name);
7665
+ await mkdir17(dirname24(ejectedPath), { recursive: true });
7442
7666
  await rm9(ejectedPath, { recursive: true, force: true });
7443
7667
  await cp6(artifact.stagedPath ?? artifact.sourcePath, ejectedPath, { recursive: artifact.kind === "dir", dereference: true });
7444
7668
  return {
@@ -7480,7 +7704,7 @@ async function stageEjectCandidate(workspaceRoot, pkg) {
7480
7704
  const adapter = pkg.adapterConfig ? await loadAdapterConfig(pkg.adapterConfig) : getAdapter(pkg.adapter);
7481
7705
  const bundle = await stageSource(driver, normalized.source, {
7482
7706
  adapter,
7483
- cacheRoot: join31(workspaceRoot, ".agentwheel", "cache"),
7707
+ cacheRoot: join32(workspaceRoot, ".agentwheel", "cache"),
7484
7708
  mode: pkg.mode,
7485
7709
  ref: normalized.requestedRef ?? pkg.requestedRef
7486
7710
  });
@@ -7531,8 +7755,8 @@ import { rm as rm10 } from "fs/promises";
7531
7755
 
7532
7756
  // src/lifecycle/source-plan.ts
7533
7757
  import { createHash as createHash8 } from "crypto";
7534
- import { mkdir as mkdir18 } from "fs/promises";
7535
- import { dirname as dirname24, join as join34, resolve as resolve16 } from "path";
7758
+ import { mkdir as mkdir19 } from "fs/promises";
7759
+ import { dirname as dirname26, join as join35, resolve as resolve16 } from "path";
7536
7760
 
7537
7761
  // src/resolve/graph-diff.ts
7538
7762
  function diffGraphLocks(previous, next) {
@@ -7654,11 +7878,11 @@ function short(hash) {
7654
7878
 
7655
7879
  // src/resolve/render.ts
7656
7880
  import { createHash as createHash7 } from "crypto";
7657
- import { readFile as readFile22, mkdtemp as mkdtemp5 } from "fs/promises";
7881
+ import { readFile as readFile23, mkdtemp as mkdtemp5 } from "fs/promises";
7658
7882
  import { tmpdir as tmpdir6 } from "os";
7659
- import { join as join32 } from "path";
7883
+ import { join as join33 } from "path";
7660
7884
  async function renderGraphForTarget(graph, targetContext = {}) {
7661
- const root = await mkdtemp5(join32(tmpdir6(), "agentwheel-render-"));
7885
+ const root = await mkdtemp5(join33(tmpdir6(), "agentwheel-render-"));
7662
7886
  const artifacts = [];
7663
7887
  const stagedNodes = /* @__PURE__ */ new Map();
7664
7888
  const includeEdges = /* @__PURE__ */ new Map();
@@ -7731,7 +7955,8 @@ async function renderGraphForTarget(graph, targetContext = {}) {
7731
7955
  const runtimeSelectedSet = new Set(normalizeArtifactSelectors(rawNode.node.selected) ?? []);
7732
7956
  const runtimeArtifacts = targetContext.adapter ? filterArtifactsByRuntime2(selectedArtifacts, targetContext.adapter.name, runtimeSelectedSet) : selectedArtifacts;
7733
7957
  const codexRenderedArtifacts = await renderCodexSubagents(runtimeArtifacts, staged.root, targetContext.adapter);
7734
- const runtimeRenderedArtifacts = await renderCopilotArtifacts(codexRenderedArtifacts, staged.root, targetContext.adapter);
7958
+ const openClawRenderedArtifacts = await renderOpenClawSubagents(codexRenderedArtifacts, staged.root, targetContext.adapter);
7959
+ const runtimeRenderedArtifacts = await renderCopilotArtifacts(openClawRenderedArtifacts, staged.root, targetContext.adapter);
7735
7960
  const renderedArtifacts = targetContext.workspaceRoot && targetContext.adapter ? await applyCustomizations(runtimeRenderedArtifacts, {
7736
7961
  workspaceRoot: targetContext.workspaceRoot,
7737
7962
  adapter: targetContext.adapter,
@@ -7778,7 +8003,7 @@ async function artifactContentMap(artifacts) {
7778
8003
  const out = /* @__PURE__ */ new Map();
7779
8004
  for (const artifact of artifacts) {
7780
8005
  if (artifact.kind !== "file") continue;
7781
- out.set(artifact.relativePath.replaceAll("\\", "/"), await readFile22(artifact.stagedPath ?? artifact.sourcePath, "utf8"));
8006
+ out.set(artifact.relativePath.replaceAll("\\", "/"), await readFile23(artifact.stagedPath ?? artifact.sourcePath, "utf8"));
7782
8007
  }
7783
8008
  return out;
7784
8009
  }
@@ -8041,9 +8266,9 @@ function lockArtifactFor(artifact) {
8041
8266
  }
8042
8267
 
8043
8268
  // src/lifecycle/trust.ts
8044
- import { mkdir as mkdir17, readFile as readFile23 } from "fs/promises";
8269
+ import { mkdir as mkdir18, readFile as readFile24 } from "fs/promises";
8045
8270
  import { homedir as homedir7 } from "os";
8046
- import { dirname as dirname23, join as join33 } from "path";
8271
+ import { dirname as dirname25, join as join34 } from "path";
8047
8272
  import { z as z8 } from "zod";
8048
8273
  var trustStoreSchema = z8.object({
8049
8274
  version: z8.literal(1),
@@ -8117,14 +8342,14 @@ function sortedUnique4(values) {
8117
8342
  }
8118
8343
  async function readTrustStore(path) {
8119
8344
  if (!await pathExists(path)) return { version: 1, acceptedSources: [] };
8120
- return trustStoreSchema.parse(JSON.parse(await readFile23(path, "utf8")));
8345
+ return trustStoreSchema.parse(JSON.parse(await readFile24(path, "utf8")));
8121
8346
  }
8122
8347
  async function writeTrustStore(path, store) {
8123
- await mkdir17(dirname23(path), { recursive: true });
8348
+ await mkdir18(dirname25(path), { recursive: true });
8124
8349
  await writeJsonAtomic(path, trustStoreSchema.parse(store));
8125
8350
  }
8126
8351
  function defaultTrustStorePath() {
8127
- return process.env.AGENTWHEEL_TRUST_STORE ?? join33(homedir7(), ".agentwheel", "trust.json");
8352
+ return process.env.AGENTWHEEL_TRUST_STORE ?? join34(homedir7(), ".agentwheel", "trust.json");
8128
8353
  }
8129
8354
 
8130
8355
  // src/lifecycle/source-plan.ts
@@ -8162,7 +8387,7 @@ async function createGraphSourcePlan(options) {
8162
8387
  const registryClient = new RegistryClient({ workspaceRoot, offline: lockMode, offlineLabel: lockLabel, warn });
8163
8388
  const graph = await resolveDependencyGraph(options.roots, {
8164
8389
  workspaceRoot,
8165
- cacheRoot: join34(workspaceRoot, ".agentwheel", "cache"),
8390
+ cacheRoot: join35(workspaceRoot, ".agentwheel", "cache"),
8166
8391
  registryClient,
8167
8392
  noDeps: options.noDeps,
8168
8393
  includeSuggestions: options.includeSuggestions,
@@ -8187,7 +8412,12 @@ async function createGraphSourcePlan(options) {
8187
8412
  targetFingerprint,
8188
8413
  warn
8189
8414
  });
8190
- const desiredArtifacts = desiredArtifactsFromGraphBundle(bundle);
8415
+ const desiredArtifacts = filterArtifactsByAdapterTargets(
8416
+ desiredArtifactsFromGraphBundle(bundle),
8417
+ options.adapter,
8418
+ installationType,
8419
+ { warn }
8420
+ );
8191
8421
  const resolvedInstallationType = resolveInstallationTypeForArtifacts(options.adapter, desiredArtifacts.map((artifact) => artifact.type), installationType);
8192
8422
  const resolvedInstallRoot = installRootForArtifacts(options.adapter, options.targetRoot, resolvedInstallationType, desiredArtifacts.map((artifact) => artifact.type), transport.kind === "ssh");
8193
8423
  const graphLockDigest = digestGraphLock(bundle.graphLock);
@@ -8262,7 +8492,7 @@ async function readExistingGraphLock(path) {
8262
8492
  return readGraphLock(path);
8263
8493
  }
8264
8494
  function pathForGraphLock(workspaceRoot, targetKey, adapter, targetFingerprint) {
8265
- return join34(workspaceRoot, ".agentwheel", "locks", sanitizePathSegment(targetKey), sanitizePathSegment(adapter), `${targetFingerprint}.graph-lock.json`);
8495
+ return join35(workspaceRoot, ".agentwheel", "locks", sanitizePathSegment(targetKey), sanitizePathSegment(adapter), `${targetFingerprint}.graph-lock.json`);
8266
8496
  }
8267
8497
  function sanitizePathSegment(value) {
8268
8498
  return value.replace(/[^a-z0-9._-]+/gi, "-").replace(/^-+|-+$/g, "") || "default";
@@ -8326,7 +8556,7 @@ ${sources.map((source) => `- ${source}`).join("\n")}`);
8326
8556
  }
8327
8557
 
8328
8558
  // src/runtime/target.ts
8329
- import { basename as basename19, dirname as dirname25, join as join35, resolve as resolve17 } from "path";
8559
+ import { basename as basename20, dirname as dirname27, join as join36, resolve as resolve17 } from "path";
8330
8560
  var runtimeMarkers = [
8331
8561
  { adapter: "openclaw", dirs: [".openclaw", ".clawdbot", ".moltbot"] },
8332
8562
  { adapter: "claude", dirs: [".claude"] },
@@ -8437,9 +8667,9 @@ async function detectRuntimeTargets(cwd = process.cwd(), adapterFilter) {
8437
8667
  for (const marker of runtimeMarkers) {
8438
8668
  if (adapterFilter && marker.adapter !== adapterFilter) continue;
8439
8669
  for (const dir of marker.dirs) {
8440
- if (basename19(root) === dir) {
8441
- matches.push({ adapter: marker.adapter, targetRoot: dirname25(root) });
8442
- } else if (await pathExists(join35(root, dir))) {
8670
+ if (basename20(root) === dir) {
8671
+ matches.push({ adapter: marker.adapter, targetRoot: dirname27(root) });
8672
+ } else if (await pathExists(join36(root, dir))) {
8443
8673
  matches.push({ adapter: marker.adapter, targetRoot: root });
8444
8674
  }
8445
8675
  }
@@ -8455,6 +8685,8 @@ function targetFromAgent(name, config, workspaceRoot, installationType) {
8455
8685
  agentName: name,
8456
8686
  targetKey: name,
8457
8687
  adapter: agent.adapter,
8688
+ adapterConfig: agent.adapterConfig,
8689
+ adapterModule: agent.adapterModule,
8458
8690
  installationType: installationType ?? agent.installationType,
8459
8691
  targetRoot: agent.transport === "ssh" ? agent.root : resolveConfigPath(agent.root, workspaceRoot),
8460
8692
  workspaceRoot,
@@ -8478,7 +8710,7 @@ function dedupeTargets(matches) {
8478
8710
  function runtimeScanRoot(request) {
8479
8711
  const root = resolve17(request.targetRoot ?? request.cwd ?? process.cwd());
8480
8712
  if (request.targetRoot) return root;
8481
- return runtimeMarkers.some((marker) => marker.dirs.includes(basename19(root))) ? dirname25(root) : root;
8713
+ return runtimeMarkers.some((marker) => marker.dirs.includes(basename20(root))) ? dirname27(root) : root;
8482
8714
  }
8483
8715
 
8484
8716
  // src/lifecycle/profile.ts
@@ -8762,9 +8994,9 @@ function shellQuoteArg(value) {
8762
8994
  }
8763
8995
 
8764
8996
  // src/cli/update-check.ts
8765
- import { mkdir as mkdir19, readFile as readFile24, writeFile as writeFile17 } from "fs/promises";
8997
+ import { mkdir as mkdir20, readFile as readFile25, writeFile as writeFile18 } from "fs/promises";
8766
8998
  import { homedir as homedir8 } from "os";
8767
- import { dirname as dirname26, join as join36 } from "path";
8999
+ import { dirname as dirname28, join as join37 } from "path";
8768
9000
  var DEFAULT_TTL_MS = 24 * 60 * 60 * 1e3;
8769
9001
  var DEFAULT_TIMEOUT_MS = 300;
8770
9002
  var REGISTRY_URL = "https://registry.npmjs.org/agentwheel";
@@ -8772,7 +9004,7 @@ async function maybeCheckForUpdate(options) {
8772
9004
  if (isDisabled(options)) return;
8773
9005
  const now = options.now?.() ?? /* @__PURE__ */ new Date();
8774
9006
  const ttlMs = options.ttlMs ?? DEFAULT_TTL_MS;
8775
- const cachePath = options.cachePath ?? join36(homedir8(), ".agentwheel", "update-check.json");
9007
+ const cachePath = options.cachePath ?? join37(homedir8(), ".agentwheel", "update-check.json");
8776
9008
  try {
8777
9009
  const cached = await readCache(cachePath);
8778
9010
  if (cached && now.getTime() - Date.parse(cached.checkedAt) < ttlMs) {
@@ -8809,7 +9041,7 @@ async function fetchLatestVersion(fetchImpl, timeoutMs) {
8809
9041
  }
8810
9042
  async function readCache(path) {
8811
9043
  try {
8812
- const parsed = JSON.parse(await readFile24(path, "utf8"));
9044
+ const parsed = JSON.parse(await readFile25(path, "utf8"));
8813
9045
  if (typeof parsed.checkedAt !== "string" || typeof parsed.latest !== "string") return void 0;
8814
9046
  return { checkedAt: parsed.checkedAt, latest: parsed.latest };
8815
9047
  } catch {
@@ -8817,8 +9049,8 @@ async function readCache(path) {
8817
9049
  }
8818
9050
  }
8819
9051
  async function writeCache(path, cache) {
8820
- await mkdir19(dirname26(path), { recursive: true });
8821
- await writeFile17(path, `${JSON.stringify(cache, null, 2)}
9052
+ await mkdir20(dirname28(path), { recursive: true });
9053
+ await writeFile18(path, `${JSON.stringify(cache, null, 2)}
8822
9054
  `, "utf8");
8823
9055
  }
8824
9056
  function warnIfNewer(latest, current, stderr = process.stderr) {
@@ -8981,13 +9213,13 @@ function isCrossPackageSelector(value) {
8981
9213
  }
8982
9214
 
8983
9215
  // src/model/package-migrate.ts
8984
- import { readFile as readFile25, rename as rename4, writeFile as writeFile18 } from "fs/promises";
8985
- import { join as join38, resolve as resolve19 } from "path";
9216
+ import { readFile as readFile26, rename as rename4, writeFile as writeFile19 } from "fs/promises";
9217
+ import { join as join39, resolve as resolve19 } from "path";
8986
9218
  import { applyEdits, modify, parse as parse4 } from "jsonc-parser";
8987
9219
  async function migratePackageManifest(root) {
8988
9220
  const packageRoot = resolve19(root);
8989
9221
  for (const name of openPackManifestNames) {
8990
- const path = join38(packageRoot, name);
9222
+ const path = join39(packageRoot, name);
8991
9223
  if (await pathExists(path)) {
8992
9224
  return { changed: false, to: path, message: `Package already uses ${name}.` };
8993
9225
  }
@@ -8996,18 +9228,18 @@ async function migratePackageManifest(root) {
8996
9228
  if (!legacyName) {
8997
9229
  throw new Error(`No legacy package manifest found at ${packageRoot}`);
8998
9230
  }
8999
- const from = join38(packageRoot, legacyName);
9231
+ const from = join39(packageRoot, legacyName);
9000
9232
  const toName = legacyName.endsWith(".jsonc") ? "openpack.jsonc" : "openpack.json";
9001
- const to = join38(packageRoot, toName);
9002
- const content = await readFile25(from, "utf8");
9233
+ const to = join39(packageRoot, toName);
9234
+ const content = await readFile26(from, "utf8");
9003
9235
  const updated = updateSchemaVersion(content);
9004
9236
  await rename4(from, to);
9005
- await writeFile18(to, updated, "utf8");
9237
+ await writeFile19(to, updated, "utf8");
9006
9238
  return { changed: true, from, to, message: `Migrated ${legacyName} to ${toName}.` };
9007
9239
  }
9008
9240
  async function firstExistingLegacyManifest(root) {
9009
9241
  for (const name of legacyPackageManifestNames) {
9010
- if (await pathExists(join38(root, name))) return name;
9242
+ if (await pathExists(join39(root, name))) return name;
9011
9243
  }
9012
9244
  return void 0;
9013
9245
  }
@@ -9025,20 +9257,20 @@ function updateSchemaVersion(content) {
9025
9257
 
9026
9258
  // src/cli/version.ts
9027
9259
  import { readFileSync } from "fs";
9028
- import { dirname as dirname27, join as join39 } from "path";
9260
+ import { dirname as dirname29, join as join40 } from "path";
9029
9261
  import { fileURLToPath as fileURLToPath2 } from "url";
9030
9262
  var FALLBACK_VERSION = "0.0.0";
9031
9263
  function resolveCliVersion() {
9032
- let dir = dirname27(fileURLToPath2(import.meta.url));
9264
+ let dir = dirname29(fileURLToPath2(import.meta.url));
9033
9265
  while (true) {
9034
9266
  try {
9035
- const pkg = JSON.parse(readFileSync(join39(dir, "package.json"), "utf8"));
9267
+ const pkg = JSON.parse(readFileSync(join40(dir, "package.json"), "utf8"));
9036
9268
  if (pkg.name === "agentwheel" && typeof pkg.version === "string") {
9037
9269
  return pkg.version;
9038
9270
  }
9039
9271
  } catch {
9040
9272
  }
9041
- const parent = dirname27(dir);
9273
+ const parent = dirname29(dir);
9042
9274
  if (parent === dir) return FALLBACK_VERSION;
9043
9275
  dir = parent;
9044
9276
  }
@@ -9086,7 +9318,7 @@ program.command("list").description("list artifacts exposed by a package source"
9086
9318
  const resolvedInput = await resolvePackageSource(source, targetRoot);
9087
9319
  const selectedArtifacts = selectedArtifactsFromOptionsOrRegistry(options, resolvedInput.registryEntry);
9088
9320
  const driver = getSourceDriver(options.driver ?? inferSourceDriverName(resolvedInput.source));
9089
- const resolved = await driver.export(await driver.translate(await driver.fetch(await driver.resolve(resolvedInput.source, { cacheRoot: join40(targetRoot, ".agentwheel", "cache") }))));
9321
+ const resolved = await driver.export(await driver.translate(await driver.fetch(await driver.resolve(resolvedInput.source, { cacheRoot: join41(targetRoot, ".agentwheel", "cache") }))));
9090
9322
  const artifacts = filterArtifactsBySelection(await driver.list(resolved), selectedArtifacts);
9091
9323
  for (const artifact of artifacts) {
9092
9324
  console.log(`${artifact.type} ${artifact.name} ${artifact.relativePath}`);
@@ -9096,7 +9328,7 @@ program.command("scan").description("scan a package source for validation findin
9096
9328
  const targetRoot = normalizeTargetRoot(options.targetRoot);
9097
9329
  const resolvedInput = await resolvePackageSource(source, targetRoot);
9098
9330
  const driver = getSourceDriver(options.driver ?? inferSourceDriverName(resolvedInput.source));
9099
- const resolved = await driver.export(await driver.translate(await driver.fetch(await driver.resolve(resolvedInput.source, { cacheRoot: join40(targetRoot, ".agentwheel", "cache") }))));
9331
+ const resolved = await driver.export(await driver.translate(await driver.fetch(await driver.resolve(resolvedInput.source, { cacheRoot: join41(targetRoot, ".agentwheel", "cache") }))));
9100
9332
  const result = await driver.scan(resolved);
9101
9333
  if (result.findings.length === 0) {
9102
9334
  console.log("Scan ok: no findings");
@@ -9393,7 +9625,7 @@ async function packageEntryFromSource(source, targetRoot, options) {
9393
9625
  const bundle = await stageSource(driver, resolvedSource, {
9394
9626
  workspaceRoot: targetRoot,
9395
9627
  adapter,
9396
- cacheRoot: join40(targetRoot, ".agentwheel", "cache"),
9628
+ cacheRoot: join41(targetRoot, ".agentwheel", "cache"),
9397
9629
  mode: options.mode,
9398
9630
  frozenLock: lockMode,
9399
9631
  select: selectedArtifacts
@@ -9751,7 +9983,7 @@ function keepManifestEntryOperation(entry, targetRoot, rootId, operation, option
9751
9983
  artifactType: entry.artifactType,
9752
9984
  artifactName: entry.artifactName,
9753
9985
  kind: entry.kind,
9754
- destPath: operation?.destPath ?? join40(targetRoot, entry.path),
9986
+ destPath: operation?.destPath ?? join41(targetRoot, entry.path),
9755
9987
  relativeDestPath: entry.path,
9756
9988
  desiredHash: entry.sourceHash,
9757
9989
  currentHash: operation?.currentHash ?? entry.hash,
@@ -10011,12 +10243,12 @@ async function printDoctor(target, options) {
10011
10243
  const requestedSkills = doctorSkillRequests(target, options);
10012
10244
  const skills = [];
10013
10245
  for (const request of requestedSkills) {
10014
- const skillPath = join40(state.installRoot, targetMapping.dest, request.name);
10246
+ const skillPath = join41(state.installRoot, targetMapping.dest, request.name);
10015
10247
  const exists = await pathExists(skillPath);
10016
10248
  const manifestEntry = manifest?.entries.find((entry) => {
10017
10249
  if (entry.artifactType !== "skills") return false;
10018
10250
  const legacyInstallName = "installName" in entry && typeof entry.installName === "string" ? entry.installName : void 0;
10019
- return entry.artifactName === request.name || legacyInstallName === request.name || entry.path === join40(targetMapping.dest, request.name);
10251
+ return entry.artifactName === request.name || legacyInstallName === request.name || entry.path === join41(targetMapping.dest, request.name);
10020
10252
  });
10021
10253
  const status = manifestEntry ? "managed" : exists ? "present-unmanaged" : "missing";
10022
10254
  skills.push({
@@ -10096,7 +10328,7 @@ function doctorSkillLabel(name) {
10096
10328
  return `${name} skill`;
10097
10329
  }
10098
10330
  function isSyncwheelWorkspace(targetRoot) {
10099
- return existsSync(join40(targetRoot, ".syncwheel", "manifest.json"));
10331
+ return existsSync(join41(targetRoot, ".syncwheel", "manifest.json"));
10100
10332
  }
10101
10333
  function skillInstallCommand(adapter, installationType, options, skill, behavior = {}) {
10102
10334
  const args = [
@@ -10238,10 +10470,10 @@ function filterUninstallPlanBySelection(plan, selected) {
10238
10470
  };
10239
10471
  }
10240
10472
  async function initPackage(root) {
10241
- await mkdir20(join40(root, "instructions"), { recursive: true });
10242
- await mkdir20(join40(root, "rules"), { recursive: true });
10243
- await mkdir20(join40(root, "skills"), { recursive: true });
10244
- const manifestPath = join40(root, "openpack.json");
10473
+ await mkdir21(join41(root, "instructions"), { recursive: true });
10474
+ await mkdir21(join41(root, "rules"), { recursive: true });
10475
+ await mkdir21(join41(root, "skills"), { recursive: true });
10476
+ const manifestPath = join41(root, "openpack.json");
10245
10477
  const manifest = {
10246
10478
  schemaVersion: 2,
10247
10479
  name: "example/agentwheel-package",
@@ -10252,12 +10484,12 @@ async function initPackage(root) {
10252
10484
  { type: "skills", path: "skills" }
10253
10485
  ]
10254
10486
  };
10255
- await writeFile19(manifestPath, `${JSON.stringify(manifest, null, 2)}
10487
+ await writeFile20(manifestPath, `${JSON.stringify(manifest, null, 2)}
10256
10488
  `, "utf8");
10257
- await writeFile19(join40(root, "instructions", "AGENTS.md"), "# Agent Instructions\n", "utf8");
10489
+ await writeFile20(join41(root, "instructions", "AGENTS.md"), "# Agent Instructions\n", "utf8");
10258
10490
  }
10259
10491
  async function defaultBootstrapPackage(_root) {
10260
- const packageRoot = await findAgentwheelPackageRoot(dirname28(fileURLToPath3(import.meta.url)));
10492
+ const packageRoot = await findAgentwheelPackageRoot(dirname30(fileURLToPath3(import.meta.url)));
10261
10493
  if (!packageRoot) return void 0;
10262
10494
  return {
10263
10495
  name: "agentwheel",
@@ -10304,7 +10536,7 @@ async function findAgentwheelPackageRoot(start) {
10304
10536
  let current = resolve20(start);
10305
10537
  while (true) {
10306
10538
  if (await findPackageManifestPath(current, { warnLegacy: false })) return current;
10307
- const parent = dirname28(current);
10539
+ const parent = dirname30(current);
10308
10540
  if (parent === current) return void 0;
10309
10541
  current = parent;
10310
10542
  }