agentikit 0.0.13 → 0.0.15

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 (156) hide show
  1. package/LICENSE +385 -0
  2. package/README.md +187 -110
  3. package/dist/{src/asset-spec.js → asset-spec.js} +11 -2
  4. package/dist/{src/asset-type-handler.js → asset-type-handler.js} +4 -3
  5. package/dist/cli.js +709 -0
  6. package/dist/common.js +192 -0
  7. package/dist/{src/config-cli.js → config-cli.js} +36 -30
  8. package/dist/{src/config.js → config.js} +95 -25
  9. package/dist/{src/db.js → db.js} +123 -51
  10. package/dist/{src/embedder.js → embedder.js} +57 -2
  11. package/dist/errors.js +28 -0
  12. package/dist/file-context.js +188 -0
  13. package/dist/{src/frontmatter.js → frontmatter.js} +1 -1
  14. package/dist/{src/github.js → github.js} +1 -3
  15. package/dist/handlers/agent-handler.js +19 -0
  16. package/dist/handlers/command-handler.js +20 -0
  17. package/dist/handlers/handler-bridge.js +51 -0
  18. package/dist/handlers/index.js +19 -0
  19. package/dist/handlers/knowledge-handler.js +32 -0
  20. package/dist/handlers/script-handler.js +42 -0
  21. package/dist/{src/handlers → handlers}/skill-handler.js +5 -6
  22. package/dist/{src/handlers → handlers}/tool-handler.js +8 -24
  23. package/dist/{src/indexer.js → indexer.js} +50 -26
  24. package/dist/init.js +43 -0
  25. package/dist/{src/llm.js → llm.js} +6 -11
  26. package/dist/lockfile.js +60 -0
  27. package/dist/matchers.js +163 -0
  28. package/dist/{src/metadata.js → metadata.js} +36 -16
  29. package/dist/{src/origin-resolve.js → origin-resolve.js} +10 -9
  30. package/dist/paths.js +83 -0
  31. package/dist/{src/registry-install.js → registry-install.js} +151 -19
  32. package/dist/{src/registry-resolve.js → registry-resolve.js} +190 -26
  33. package/dist/{src/registry-search.js → registry-search.js} +13 -21
  34. package/dist/renderers.js +286 -0
  35. package/dist/{src/ripgrep-install.js → ripgrep-install.js} +8 -27
  36. package/dist/{src/ripgrep-resolve.js → ripgrep-resolve.js} +21 -11
  37. package/dist/ripgrep.js +2 -0
  38. package/dist/self-update.js +226 -0
  39. package/dist/{src/stash-add.js → stash-add.js} +14 -4
  40. package/dist/stash-clone.js +115 -0
  41. package/dist/{src/stash-ref.js → stash-ref.js} +10 -9
  42. package/dist/{src/stash-registry.js → stash-registry.js} +21 -46
  43. package/dist/{src/stash-resolve.js → stash-resolve.js} +10 -9
  44. package/dist/{src/stash-search.js → stash-search.js} +89 -74
  45. package/dist/stash-show.js +74 -0
  46. package/dist/stash-source.js +127 -0
  47. package/dist/submit.js +557 -0
  48. package/dist/{src/tool-runner.js → tool-runner.js} +1 -5
  49. package/dist/{src/walker.js → walker.js} +38 -0
  50. package/dist/warn.js +20 -0
  51. package/package.json +13 -18
  52. package/dist/index.d.ts +0 -28
  53. package/dist/index.js +0 -15
  54. package/dist/src/asset-spec.d.ts +0 -16
  55. package/dist/src/asset-type-handler.d.ts +0 -27
  56. package/dist/src/cli.d.ts +0 -2
  57. package/dist/src/cli.js +0 -399
  58. package/dist/src/common.d.ts +0 -13
  59. package/dist/src/common.js +0 -60
  60. package/dist/src/config-cli.d.ts +0 -9
  61. package/dist/src/config.d.ts +0 -50
  62. package/dist/src/db.d.ts +0 -46
  63. package/dist/src/embedder.d.ts +0 -10
  64. package/dist/src/frontmatter.d.ts +0 -30
  65. package/dist/src/github.d.ts +0 -4
  66. package/dist/src/handlers/agent-handler.d.ts +0 -2
  67. package/dist/src/handlers/agent-handler.js +0 -26
  68. package/dist/src/handlers/command-handler.d.ts +0 -2
  69. package/dist/src/handlers/command-handler.js +0 -23
  70. package/dist/src/handlers/index.d.ts +0 -6
  71. package/dist/src/handlers/index.js +0 -23
  72. package/dist/src/handlers/knowledge-handler.d.ts +0 -2
  73. package/dist/src/handlers/knowledge-handler.js +0 -56
  74. package/dist/src/handlers/markdown-helpers.d.ts +0 -7
  75. package/dist/src/handlers/script-handler.d.ts +0 -2
  76. package/dist/src/handlers/script-handler.js +0 -78
  77. package/dist/src/handlers/skill-handler.d.ts +0 -2
  78. package/dist/src/handlers/tool-handler.d.ts +0 -2
  79. package/dist/src/indexer.d.ts +0 -22
  80. package/dist/src/init.d.ts +0 -19
  81. package/dist/src/init.js +0 -99
  82. package/dist/src/llm.d.ts +0 -15
  83. package/dist/src/markdown.d.ts +0 -18
  84. package/dist/src/metadata.d.ts +0 -41
  85. package/dist/src/origin-resolve.d.ts +0 -19
  86. package/dist/src/registry-install.d.ts +0 -11
  87. package/dist/src/registry-resolve.d.ts +0 -3
  88. package/dist/src/registry-search.d.ts +0 -27
  89. package/dist/src/registry-types.d.ts +0 -62
  90. package/dist/src/ripgrep-install.d.ts +0 -12
  91. package/dist/src/ripgrep-resolve.d.ts +0 -13
  92. package/dist/src/ripgrep.d.ts +0 -3
  93. package/dist/src/ripgrep.js +0 -2
  94. package/dist/src/stash-add.d.ts +0 -4
  95. package/dist/src/stash-clone.d.ts +0 -22
  96. package/dist/src/stash-clone.js +0 -83
  97. package/dist/src/stash-ref.d.ts +0 -31
  98. package/dist/src/stash-registry.d.ts +0 -18
  99. package/dist/src/stash-resolve.d.ts +0 -2
  100. package/dist/src/stash-search.d.ts +0 -8
  101. package/dist/src/stash-show.d.ts +0 -5
  102. package/dist/src/stash-show.js +0 -46
  103. package/dist/src/stash-source.d.ts +0 -24
  104. package/dist/src/stash-source.js +0 -81
  105. package/dist/src/stash-types.d.ts +0 -227
  106. package/dist/src/stash.d.ts +0 -16
  107. package/dist/src/stash.js +0 -9
  108. package/dist/src/tool-runner.d.ts +0 -35
  109. package/dist/src/walker.d.ts +0 -19
  110. package/src/asset-spec.ts +0 -85
  111. package/src/asset-type-handler.ts +0 -77
  112. package/src/cli.ts +0 -427
  113. package/src/common.ts +0 -76
  114. package/src/config-cli.ts +0 -499
  115. package/src/config.ts +0 -305
  116. package/src/db.ts +0 -411
  117. package/src/embedder.ts +0 -128
  118. package/src/frontmatter.ts +0 -95
  119. package/src/github.ts +0 -21
  120. package/src/handlers/agent-handler.ts +0 -32
  121. package/src/handlers/command-handler.ts +0 -29
  122. package/src/handlers/index.ts +0 -25
  123. package/src/handlers/knowledge-handler.ts +0 -62
  124. package/src/handlers/markdown-helpers.ts +0 -19
  125. package/src/handlers/script-handler.ts +0 -92
  126. package/src/handlers/skill-handler.ts +0 -37
  127. package/src/handlers/tool-handler.ts +0 -71
  128. package/src/indexer.ts +0 -392
  129. package/src/init.ts +0 -114
  130. package/src/llm.ts +0 -125
  131. package/src/markdown.ts +0 -106
  132. package/src/metadata.ts +0 -333
  133. package/src/origin-resolve.ts +0 -67
  134. package/src/registry-install.ts +0 -361
  135. package/src/registry-resolve.ts +0 -341
  136. package/src/registry-search.ts +0 -335
  137. package/src/registry-types.ts +0 -72
  138. package/src/ripgrep-install.ts +0 -200
  139. package/src/ripgrep-resolve.ts +0 -72
  140. package/src/ripgrep.ts +0 -3
  141. package/src/stash-add.ts +0 -63
  142. package/src/stash-clone.ts +0 -127
  143. package/src/stash-ref.ts +0 -99
  144. package/src/stash-registry.ts +0 -259
  145. package/src/stash-resolve.ts +0 -50
  146. package/src/stash-search.ts +0 -613
  147. package/src/stash-show.ts +0 -55
  148. package/src/stash-source.ts +0 -103
  149. package/src/stash-types.ts +0 -231
  150. package/src/stash.ts +0 -39
  151. package/src/tool-runner.ts +0 -142
  152. package/src/walker.ts +0 -53
  153. /package/dist/{src/handlers → handlers}/markdown-helpers.js +0 -0
  154. /package/dist/{src/markdown.js → markdown.js} +0 -0
  155. /package/dist/{src/registry-types.js → registry-types.js} +0 -0
  156. /package/dist/{src/stash-types.js → stash-types.js} +0 -0
@@ -0,0 +1,115 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { TYPE_DIRS } from "./asset-spec";
4
+ import { isRemoteOrigin, resolveSourcesForOrigin } from "./origin-resolve";
5
+ import { installRegistryRef } from "./registry-install";
6
+ import { makeAssetRef, parseAssetRef } from "./stash-ref";
7
+ import { resolveAssetPath } from "./stash-resolve";
8
+ import { findSourceForPath, getPrimarySource, resolveStashSources } from "./stash-source";
9
+ export async function agentikitClone(options) {
10
+ const parsed = parseAssetRef(options.sourceRef);
11
+ // When --dest is provided, the working stash is optional
12
+ let allSources;
13
+ try {
14
+ allSources = resolveStashSources();
15
+ }
16
+ catch (err) {
17
+ if (options.dest) {
18
+ allSources = [];
19
+ }
20
+ else {
21
+ throw err;
22
+ }
23
+ }
24
+ const primarySource = getPrimarySource(allSources);
25
+ const destRoot = options.dest ? path.resolve(options.dest) : primarySource?.path;
26
+ if (!destRoot) {
27
+ throw new Error("No working stash configured and no --dest provided. Run `akm init` or pass --dest.");
28
+ }
29
+ let searchSources = resolveSourcesForOrigin(parsed.origin, allSources);
30
+ // Remote fetch fallback: if no local source matched and origin looks remote, fetch it
31
+ let remoteFetched;
32
+ if (searchSources.length === 0 && parsed.origin && isRemoteOrigin(parsed.origin, allSources)) {
33
+ const installResult = await installRegistryRef(parsed.origin);
34
+ const syntheticSource = {
35
+ path: installResult.stashRoot,
36
+ registryId: installResult.id,
37
+ };
38
+ searchSources = [syntheticSource];
39
+ allSources = [...allSources, syntheticSource];
40
+ remoteFetched = {
41
+ origin: parsed.origin,
42
+ stashRoot: installResult.stashRoot,
43
+ cacheDir: installResult.cacheDir,
44
+ };
45
+ }
46
+ let sourcePath;
47
+ let lastError;
48
+ for (const source of searchSources) {
49
+ try {
50
+ sourcePath = resolveAssetPath(source.path, parsed.type, parsed.name);
51
+ break;
52
+ }
53
+ catch (err) {
54
+ lastError = err instanceof Error ? err : new Error(String(err));
55
+ }
56
+ }
57
+ if (!sourcePath) {
58
+ const context = remoteFetched ? ` (remote package fetched but asset not found inside it)` : "";
59
+ throw lastError ?? new Error(`Source asset not found for ref: ${options.sourceRef}${context}`);
60
+ }
61
+ const sourceSource = findSourceForPath(sourcePath, allSources);
62
+ const destName = options.newName ?? parsed.name;
63
+ const typeDir = TYPE_DIRS[parsed.type];
64
+ const destLabel = options.dest ? "at destination" : "in working stash";
65
+ // Guard against self-clone
66
+ if (parsed.type === "skill") {
67
+ const sourceSkillDir = path.resolve(path.dirname(sourcePath));
68
+ const destSkillDir = path.resolve(path.join(destRoot, typeDir, destName));
69
+ if (sourceSkillDir === destSkillDir) {
70
+ throw new Error(`Source and destination are the same path. Use --name to provide a new name for the clone.`);
71
+ }
72
+ }
73
+ else {
74
+ const resolvedSource = path.resolve(sourcePath);
75
+ const resolvedDest = path.resolve(path.join(destRoot, typeDir, destName));
76
+ if (resolvedSource === resolvedDest) {
77
+ throw new Error(`Source and destination are the same path. Use --name to provide a new name for the clone.`);
78
+ }
79
+ }
80
+ let destPath;
81
+ if (parsed.type === "skill") {
82
+ const sourceSkillDir = path.dirname(sourcePath);
83
+ const destSkillDir = path.join(destRoot, typeDir, destName);
84
+ const overwritten = fs.existsSync(destSkillDir);
85
+ if (overwritten && !options.force) {
86
+ throw new Error(`Asset already exists ${destLabel}: ${destSkillDir}. Use --force to overwrite.`);
87
+ }
88
+ if (overwritten) {
89
+ fs.rmSync(destSkillDir, { recursive: true, force: true });
90
+ }
91
+ fs.cpSync(sourceSkillDir, destSkillDir, { recursive: true });
92
+ destPath = path.join(destSkillDir, "SKILL.md");
93
+ const ref = makeAssetRef(parsed.type, destName, "local");
94
+ return {
95
+ source: { path: sourcePath, registryId: sourceSource?.registryId },
96
+ destination: { path: destPath, ref },
97
+ overwritten,
98
+ ...(remoteFetched ? { remoteFetched } : {}),
99
+ };
100
+ }
101
+ destPath = path.join(destRoot, typeDir, destName);
102
+ const overwritten = fs.existsSync(destPath);
103
+ if (overwritten && !options.force) {
104
+ throw new Error(`Asset already exists ${destLabel}: ${destPath}. Use --force to overwrite.`);
105
+ }
106
+ fs.mkdirSync(path.dirname(destPath), { recursive: true });
107
+ fs.copyFileSync(sourcePath, destPath);
108
+ const ref = makeAssetRef(parsed.type, destName, "local");
109
+ return {
110
+ source: { path: sourcePath, registryId: sourceSource?.registryId },
111
+ destination: { path: destPath, ref },
112
+ overwritten,
113
+ ...(remoteFetched ? { remoteFetched } : {}),
114
+ };
115
+ }
@@ -1,5 +1,6 @@
1
1
  import path from "node:path";
2
2
  import { isAssetType } from "./common";
3
+ import { UsageError } from "./errors";
3
4
  // ── Construction ────────────────────────────────────────────────────────────
4
5
  /**
5
6
  * Build a ref string from components.
@@ -29,7 +30,7 @@ export function makeAssetRef(type, name, origin) {
29
30
  export function parseAssetRef(ref) {
30
31
  const trimmed = ref.trim();
31
32
  if (!trimmed)
32
- throw new Error("Empty ref.");
33
+ throw new UsageError("Empty ref.");
33
34
  let origin;
34
35
  let body = trimmed;
35
36
  const boundary = trimmed.indexOf("//");
@@ -37,16 +38,16 @@ export function parseAssetRef(ref) {
37
38
  origin = trimmed.slice(0, boundary);
38
39
  body = trimmed.slice(boundary + 2);
39
40
  if (!origin)
40
- throw new Error("Empty origin in ref.");
41
+ throw new UsageError("Empty origin in ref.");
41
42
  }
42
43
  const colon = body.indexOf(":");
43
44
  if (colon <= 0) {
44
- throw new Error(`Invalid ref "${trimmed}". Expected [origin//]type:name`);
45
+ throw new UsageError(`Invalid ref "${trimmed}". Expected [origin//]type:name`);
45
46
  }
46
47
  const rawType = body.slice(0, colon);
47
48
  const rawName = body.slice(colon + 1);
48
49
  if (!isAssetType(rawType)) {
49
- throw new Error(`Invalid asset type: "${rawType}".`);
50
+ throw new UsageError(`Invalid asset type: "${rawType}".`);
50
51
  }
51
52
  validateName(rawName);
52
53
  const name = normalizeName(rawName);
@@ -55,16 +56,16 @@ export function parseAssetRef(ref) {
55
56
  // ── Validation ──────────────────────────────────────────────────────────────
56
57
  function validateName(name) {
57
58
  if (!name)
58
- throw new Error("Empty asset name.");
59
+ throw new UsageError("Empty asset name.");
59
60
  if (name.includes("\0"))
60
- throw new Error("Null byte in asset name.");
61
+ throw new UsageError("Null byte in asset name.");
61
62
  if (/^[A-Za-z]:/.test(name))
62
- throw new Error("Windows drive path in asset name.");
63
+ throw new UsageError("Windows drive path in asset name.");
63
64
  const normalized = path.posix.normalize(name.replace(/\\/g, "/"));
64
65
  if (path.posix.isAbsolute(normalized))
65
- throw new Error("Absolute path in asset name.");
66
+ throw new UsageError("Absolute path in asset name.");
66
67
  if (normalized === ".." || normalized.startsWith("../")) {
67
- throw new Error("Path traversal in asset name.");
68
+ throw new UsageError("Path traversal in asset name.");
68
69
  }
69
70
  }
70
71
  function normalizeName(name) {
@@ -1,8 +1,10 @@
1
1
  import fs from "node:fs";
2
2
  import { resolveStashDir } from "./common";
3
3
  import { loadConfig } from "./config";
4
+ import { NotFoundError, UsageError } from "./errors";
4
5
  import { agentikitIndex } from "./indexer";
5
- import { installRegistryRef, removeInstalledRegistryEntry, upsertInstalledRegistryEntry, } from "./registry-install";
6
+ import { removeLockEntry, upsertLockEntry } from "./lockfile";
7
+ import { installRegistryRef, removeInstalledRegistryEntry, upsertInstalledRegistryEntry } from "./registry-install";
6
8
  import { parseRegistryRef } from "./registry-resolve";
7
9
  export async function agentikitList(input) {
8
10
  const stashDir = input?.stashDir ?? resolveStashDir();
@@ -23,12 +25,13 @@ export async function agentikitList(input) {
23
25
  export async function agentikitRemove(input) {
24
26
  const target = input.target.trim();
25
27
  if (!target)
26
- throw new Error("Target is required.");
28
+ throw new UsageError("Target is required.");
27
29
  const stashDir = input.stashDir ?? resolveStashDir();
28
30
  const config = loadConfig();
29
31
  const installed = config.registry?.installed ?? [];
30
32
  const entry = resolveInstalledTarget(installed, target);
31
33
  const updatedConfig = removeInstalledRegistryEntry(entry.id);
34
+ removeLockEntry(entry.id);
32
35
  cleanupDirectoryBestEffort(entry.cacheDir);
33
36
  const index = await agentikitIndex({ stashDir });
34
37
  return {
@@ -42,7 +45,7 @@ export async function agentikitRemove(input) {
42
45
  stashRoot: entry.stashRoot,
43
46
  },
44
47
  config: {
45
- mountedStashDirs: updatedConfig.mountedStashDirs,
48
+ searchPaths: updatedConfig.searchPaths,
46
49
  installedRegistryCount: updatedConfig.registry?.installed.length ?? 0,
47
50
  },
48
51
  index: {
@@ -53,56 +56,28 @@ export async function agentikitRemove(input) {
53
56
  },
54
57
  };
55
58
  }
56
- export async function agentikitReinstall(input) {
59
+ export async function agentikitUpdate(input) {
57
60
  const stashDir = input?.stashDir ?? resolveStashDir();
58
61
  const target = input?.target?.trim();
59
62
  const all = input?.all === true;
63
+ const force = input?.force === true;
60
64
  const installedEntries = loadConfig().registry?.installed ?? [];
61
65
  const selectedEntries = selectTargets(installedEntries, target, all);
62
66
  const processed = [];
63
67
  for (const entry of selectedEntries) {
64
- const installed = await installRegistryRef(entry.ref);
65
- upsertInstalledRegistryEntry(toInstalledEntry(installed));
66
- if (entry.cacheDir !== installed.cacheDir) {
68
+ if (force) {
67
69
  cleanupDirectoryBestEffort(entry.cacheDir);
68
70
  }
69
- processed.push({
70
- id: entry.id,
71
- source: entry.source,
72
- ref: entry.ref,
73
- previousCacheDir: entry.cacheDir,
74
- installed: toInstallStatus(installed),
75
- });
76
- }
77
- const index = await agentikitIndex({ stashDir });
78
- const config = loadConfig();
79
- return {
80
- stashDir,
81
- target,
82
- all,
83
- processed,
84
- config: {
85
- mountedStashDirs: config.mountedStashDirs,
86
- installedRegistryCount: config.registry?.installed.length ?? 0,
87
- },
88
- index: {
89
- mode: index.mode,
90
- totalEntries: index.totalEntries,
91
- directoriesScanned: index.directoriesScanned,
92
- directoriesSkipped: index.directoriesSkipped,
93
- },
94
- };
95
- }
96
- export async function agentikitUpdate(input) {
97
- const stashDir = input?.stashDir ?? resolveStashDir();
98
- const target = input?.target?.trim();
99
- const all = input?.all === true;
100
- const installedEntries = loadConfig().registry?.installed ?? [];
101
- const selectedEntries = selectTargets(installedEntries, target, all);
102
- const processed = [];
103
- for (const entry of selectedEntries) {
104
71
  const installed = await installRegistryRef(entry.ref);
105
72
  upsertInstalledRegistryEntry(toInstalledEntry(installed));
73
+ upsertLockEntry({
74
+ id: installed.id,
75
+ source: installed.source,
76
+ ref: installed.ref,
77
+ resolvedVersion: installed.resolvedVersion,
78
+ resolvedRevision: installed.resolvedRevision,
79
+ integrity: installed.integrity ?? (installed.source === "local" ? "local" : undefined),
80
+ });
106
81
  if (entry.cacheDir !== installed.cacheDir) {
107
82
  cleanupDirectoryBestEffort(entry.cacheDir);
108
83
  }
@@ -133,7 +108,7 @@ export async function agentikitUpdate(input) {
133
108
  all,
134
109
  processed,
135
110
  config: {
136
- mountedStashDirs: config.mountedStashDirs,
111
+ searchPaths: config.searchPaths,
137
112
  installedRegistryCount: config.registry?.installed.length ?? 0,
138
113
  },
139
114
  index: {
@@ -146,12 +121,12 @@ export async function agentikitUpdate(input) {
146
121
  }
147
122
  function selectTargets(installed, target, all) {
148
123
  if (all && target) {
149
- throw new Error("Specify either <target> or --all, not both.");
124
+ throw new UsageError("Specify either <target> or --all, not both.");
150
125
  }
151
126
  if (all)
152
127
  return installed;
153
128
  if (!target) {
154
- throw new Error("Either <target> or --all is required.");
129
+ throw new UsageError("Either <target> or --all is required.");
155
130
  }
156
131
  return [resolveInstalledTarget(installed, target)];
157
132
  }
@@ -174,7 +149,7 @@ function resolveInstalledTarget(installed, target) {
174
149
  if (byParsedId)
175
150
  return byParsedId;
176
151
  }
177
- throw new Error(`No installed registry entry matched target: ${target}`);
152
+ throw new NotFoundError(`No installed registry entry matched target: ${target}`);
178
153
  }
179
154
  function toInstalledEntry(status) {
180
155
  return {
@@ -1,37 +1,38 @@
1
1
  import fs from "node:fs";
2
2
  import path from "node:path";
3
+ import { isRelevantAssetFile, resolveAssetPathFromName, TYPE_DIRS } from "./asset-spec";
3
4
  import { hasErrnoCode, isWithin } from "./common";
4
- import { TYPE_DIRS, isRelevantAssetFile, resolveAssetPathFromName } from "./asset-spec";
5
+ import { NotFoundError, UsageError } from "./errors";
5
6
  export function resolveAssetPath(stashDir, type, name) {
6
7
  const root = path.join(stashDir, TYPE_DIRS[type]);
7
8
  const target = resolveAssetPathFromName(type, root, name);
8
9
  const resolvedRoot = resolveAndValidateTypeRoot(root, type, name);
9
10
  const resolvedTarget = path.resolve(target);
10
11
  if (!isWithin(resolvedTarget, resolvedRoot)) {
11
- throw new Error("Ref resolves outside the stash root.");
12
+ throw new UsageError("Ref resolves outside the stash root.");
12
13
  }
13
14
  if (!fs.existsSync(resolvedTarget) || !fs.statSync(resolvedTarget).isFile()) {
14
- throw new Error(`Stash asset not found for ref: ${type}:${name}`);
15
+ throw new NotFoundError(`Stash asset not found for ref: ${type}:${name}`);
15
16
  }
16
17
  const realTarget = fs.realpathSync(resolvedTarget);
17
18
  if (!isWithin(realTarget, resolvedRoot)) {
18
- throw new Error("Ref resolves outside the stash root.");
19
+ throw new UsageError("Ref resolves outside the stash root.");
19
20
  }
20
21
  if (!isRelevantAssetFile(type, path.basename(resolvedTarget))) {
21
22
  if (type === "tool") {
22
- throw new Error("Tool ref must resolve to a .sh, .ts, .js, .ps1, .cmd, or .bat file.");
23
+ throw new NotFoundError("Tool ref must resolve to a .sh, .ts, .js, .ps1, .cmd, or .bat file.");
23
24
  }
24
25
  if (type === "script") {
25
- throw new Error("Script ref must resolve to a file with a supported script extension. Refer to the Agentikit documentation for the complete list of supported script extensions.");
26
+ throw new NotFoundError("Script ref must resolve to a file with a supported script extension. Refer to the Agentikit documentation for the complete list of supported script extensions.");
26
27
  }
27
- throw new Error(`Stash asset not found for ref: ${type}:${name}`);
28
+ throw new NotFoundError(`Stash asset not found for ref: ${type}:${name}`);
28
29
  }
29
30
  return realTarget;
30
31
  }
31
32
  function resolveAndValidateTypeRoot(root, type, name) {
32
33
  const rootStat = readTypeRootStat(root, type, name);
33
34
  if (!rootStat.isDirectory()) {
34
- throw new Error(`Stash type root is not a directory for ref: ${type}:${name}`);
35
+ throw new NotFoundError(`Stash type root is not a directory for ref: ${type}:${name}`);
35
36
  }
36
37
  return fs.realpathSync(root);
37
38
  }
@@ -41,7 +42,7 @@ function readTypeRootStat(root, type, name) {
41
42
  }
42
43
  catch (error) {
43
44
  if (hasErrnoCode(error, "ENOENT")) {
44
- throw new Error(`Stash type root not found for ref: ${type}:${name}`);
45
+ throw new NotFoundError(`Stash type root not found for ref: ${type}:${name}`);
45
46
  }
46
47
  throw error;
47
48
  }