akm-cli 0.0.16 → 0.0.17

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.
@@ -1,47 +1,12 @@
1
1
  import fs from "node:fs";
2
2
  import path from "node:path";
3
3
  import { isRelevantAssetFile, resolveAssetPathFromName, TYPE_DIRS } from "./asset-spec";
4
- import { hasErrnoCode, isWithin, normalizeAssetType } from "./common";
4
+ import { hasErrnoCode, isWithin } from "./common";
5
5
  import { NotFoundError, UsageError } from "./errors";
6
6
  /**
7
7
  * Resolve an asset path from a stash directory, type, and name.
8
- *
9
- * When `type` is "script" or "tool" (which is a transparent alias for "script"),
10
- * resolution tries both the primary type directory and the alias directory:
11
- * - script → tries scripts/ then tools/
12
- * - tool → tries tools/ then scripts/
13
- * This ensures that `script:deploy.sh` can find files in either `scripts/` or `tools/`.
14
8
  */
15
9
  export function resolveAssetPath(stashDir, type, name) {
16
- // For script/tool, try the primary directory first, then the alias directory.
17
- if (type === "script" || type === "tool") {
18
- const primaryDir = TYPE_DIRS[type];
19
- const aliasDir = type === "script" ? "tools" : "scripts";
20
- const dirsToTry = [primaryDir, aliasDir];
21
- let primaryError;
22
- let lastError;
23
- for (let i = 0; i < dirsToTry.length; i++) {
24
- try {
25
- return resolveInTypeDir(stashDir, dirsToTry[i], type, name);
26
- }
27
- catch (err) {
28
- const error = err instanceof Error ? err : new Error(String(err));
29
- if (i === 0)
30
- primaryError = error;
31
- lastError = error;
32
- // Only fall through on NotFoundError -- rethrow security/usage errors immediately
33
- if (err instanceof UsageError)
34
- throw err;
35
- }
36
- }
37
- // Prefer the primary directory's error when it's about extension validation
38
- // (i.e., the file was found but had the wrong extension) over a generic
39
- // "not found" from the alias directory.
40
- const errorToThrow = primaryError?.message.includes("supported script extension")
41
- ? primaryError
42
- : (lastError ?? new NotFoundError(`Stash asset not found for ref: ${normalizeAssetType(type)}:${name}`));
43
- throw errorToThrow;
44
- }
45
10
  return resolveInTypeDir(stashDir, TYPE_DIRS[type], type, name);
46
11
  }
47
12
  /**
@@ -56,26 +21,24 @@ function resolveInTypeDir(stashDir, typeDir, type, name) {
56
21
  throw new UsageError("Ref resolves outside the stash root.");
57
22
  }
58
23
  if (!fs.existsSync(resolvedTarget) || !fs.statSync(resolvedTarget).isFile()) {
59
- throw new NotFoundError(`Stash asset not found for ref: ${normalizeAssetType(type)}:${name}`);
24
+ throw new NotFoundError(`Stash asset not found for ref: ${type}:${name}`);
60
25
  }
61
26
  const realTarget = fs.realpathSync(resolvedTarget);
62
27
  if (!isWithin(realTarget, resolvedRoot)) {
63
28
  throw new UsageError("Ref resolves outside the stash root.");
64
29
  }
65
- // Use "script" for relevance check since tool is an alias for script
66
- const relevanceType = type === "tool" ? "script" : type;
67
- if (!isRelevantAssetFile(relevanceType, path.basename(resolvedTarget))) {
68
- if (type === "tool" || type === "script") {
30
+ if (!isRelevantAssetFile(type, path.basename(resolvedTarget))) {
31
+ if (type === "script") {
69
32
  throw new NotFoundError("Script ref must resolve to a file with a supported script extension. Refer to the akm documentation for the complete list of supported script extensions.");
70
33
  }
71
- throw new NotFoundError(`Stash asset not found for ref: ${normalizeAssetType(type)}:${name}`);
34
+ throw new NotFoundError(`Stash asset not found for ref: ${type}:${name}`);
72
35
  }
73
36
  return realTarget;
74
37
  }
75
38
  function resolveAndValidateTypeRoot(root, type, name) {
76
39
  const rootStat = readTypeRootStat(root, type, name);
77
40
  if (!rootStat.isDirectory()) {
78
- throw new NotFoundError(`Stash type root is not a directory for ref: ${normalizeAssetType(type)}:${name}`);
41
+ throw new NotFoundError(`Stash type root is not a directory for ref: ${type}:${name}`);
79
42
  }
80
43
  return fs.realpathSync(root);
81
44
  }
@@ -85,7 +48,7 @@ function readTypeRootStat(root, type, name) {
85
48
  }
86
49
  catch (error) {
87
50
  if (hasErrnoCode(error, "ENOENT")) {
88
- throw new NotFoundError(`Stash type root not found for ref: ${normalizeAssetType(type)}:${name}`);
51
+ throw new NotFoundError(`Stash type root not found for ref: ${type}:${name}`);
89
52
  }
90
53
  throw error;
91
54
  }
@@ -1,7 +1,6 @@
1
1
  import fs from "node:fs";
2
2
  import path from "node:path";
3
3
  import { deriveCanonicalAssetName, TYPE_DIRS } from "./asset-spec";
4
- import { normalizeAssetType } from "./common";
5
4
  import { loadConfig } from "./config";
6
5
  import { closeDatabase, getAllEntries, getEntryById, getEntryCount, getMeta, openDatabase, searchFts, searchVec, } from "./db";
7
6
  import { UsageError } from "./errors";
@@ -45,7 +44,7 @@ export async function agentikitSearch(input) {
45
44
  sources,
46
45
  config,
47
46
  });
48
- const registryResult = source === "local" ? undefined : await searchRegistry(query, { limit, registryUrls: config.registryUrls });
47
+ const registryResult = source === "local" ? undefined : await searchRegistry(query, { limit, registries: config.registries });
49
48
  if (source === "local") {
50
49
  return {
51
50
  schemaVersion: 1,
@@ -67,6 +66,7 @@ export async function agentikitSearch(input) {
67
66
  action: `akm add ${installRef} -> then search again`,
68
67
  score: hit.score,
69
68
  curated: hit.curated,
69
+ registryName: hit.registryName,
70
70
  };
71
71
  });
72
72
  if (source === "registry") {
@@ -315,7 +315,7 @@ function buildDbHit(input) {
315
315
  const source = findSourceForPath(input.path, input.sources);
316
316
  const editable = isEditable(input.path, input.config);
317
317
  const hit = {
318
- type: normalizeAssetType(input.entry.type),
318
+ type: input.entry.type,
319
319
  name: input.entry.name,
320
320
  path: input.path,
321
321
  ref: makeAssetRef(input.entry.type, refName, source?.registryId),
@@ -325,7 +325,7 @@ function buildDbHit(input) {
325
325
  description: input.entry.description,
326
326
  tags: input.entry.tags,
327
327
  size: deriveSize(input.entry.fileSize),
328
- action: buildLocalAction(normalizeAssetType(input.entry.type), makeAssetRef(input.entry.type, refName, source?.registryId)),
328
+ action: buildLocalAction(input.entry.type, makeAssetRef(input.entry.type, refName, source?.registryId)),
329
329
  score,
330
330
  whyMatched,
331
331
  };
@@ -364,7 +364,7 @@ function assetToSearchHit(asset, stashDir, sources, config) {
364
364
  const fileSize = readFileSize(asset.path);
365
365
  const size = deriveSize(fileSize);
366
366
  const hit = {
367
- type: normalizeAssetType(asset.entry.type),
367
+ type: asset.entry.type,
368
368
  name: asset.entry.name,
369
369
  path: asset.path,
370
370
  ref,
@@ -376,7 +376,7 @@ function assetToSearchHit(asset, stashDir, sources, config) {
376
376
  description: asset.entry.description,
377
377
  tags: asset.entry.tags,
378
378
  ...(size ? { size } : {}),
379
- action: buildLocalAction(normalizeAssetType(asset.entry.type), ref),
379
+ action: buildLocalAction(asset.entry.type, ref),
380
380
  };
381
381
  const renderer = rendererForType(asset.entry.type);
382
382
  if (renderer?.enrichSearchHit) {
@@ -404,7 +404,6 @@ function mergeSearchHits(localHits, registryHits, limit) {
404
404
  }
405
405
  /** Map asset types to their primary renderer names. */
406
406
  const TYPE_TO_RENDERER = {
407
- tool: "script-source",
408
407
  script: "script-source",
409
408
  skill: "skill-md",
410
409
  command: "command-md",
@@ -426,8 +425,6 @@ function buildLocalAction(type, ref) {
426
425
  return `akm show ${ref} -> dispatch with full prompt`;
427
426
  case "knowledge":
428
427
  return `akm show ${ref} -> read reference material`;
429
- case "tool":
430
- return `akm show ${ref} -> execute the run command`;
431
428
  }
432
429
  }
433
430
  function deriveSize(bytes) {
@@ -449,7 +446,7 @@ function readFileSize(filePath) {
449
446
  }
450
447
  function indexAssets(stashDir, type) {
451
448
  const assets = [];
452
- const filterType = type === "any" ? undefined : normalizeAssetType(type);
449
+ const filterType = type === "any" ? undefined : type;
453
450
  const fileContexts = walkStashFlat(stashDir);
454
451
  const dirGroups = new Map();
455
452
  for (const ctx of fileContexts) {
@@ -478,8 +475,7 @@ function indexAssets(stashDir, type) {
478
475
  stash = generated;
479
476
  }
480
477
  for (const entry of stash.entries) {
481
- const normalizedType = normalizeAssetType(entry.type);
482
- if (filterType && normalizedType !== filterType)
478
+ if (filterType && entry.type !== filterType)
483
479
  continue;
484
480
  const entryPath = entry.filename ? path.join(dirPath, entry.filename) : files[0] || dirPath;
485
481
  assets.push({ entry, path: entryPath });
@@ -1,4 +1,3 @@
1
- import { normalizeAssetType } from "./common";
2
1
  import { loadConfig } from "./config";
3
2
  import { NotFoundError, UsageError } from "./errors";
4
3
  import { buildFileContext, buildRenderContext, getRenderer, runMatchers } from "./file-context";
@@ -8,7 +7,7 @@ import { resolveAssetPath } from "./stash-resolve";
8
7
  import { buildEditHint, findSourceForPath, isEditable, resolveStashSources } from "./stash-source";
9
8
  export async function agentikitShow(input) {
10
9
  const parsed = parseAssetRef(input.ref);
11
- const displayType = normalizeAssetType(parsed.type);
10
+ const displayType = parsed.type;
12
11
  const config = loadConfig();
13
12
  const allSources = resolveStashSources();
14
13
  const searchSources = resolveSourcesForOrigin(parsed.origin, allSources);
@@ -1,6 +1,6 @@
1
1
  import fs from "node:fs";
2
2
  import path from "node:path";
3
- import { normalizeAssetType, resolveStashDir } from "./common";
3
+ import { resolveStashDir } from "./common";
4
4
  import { loadConfig } from "./config";
5
5
  import { warn } from "./warn";
6
6
  // ── Resolution ──────────────────────────────────────────────────────────────
@@ -11,7 +11,7 @@ import { warn } from "./warn";
11
11
  * 3. Installed kit paths (cache-managed, from registry)
12
12
  *
13
13
  * The first entry is always the primary stash. Additional entries come
14
- * from `searchPaths` config and `registry.installed` entries.
14
+ * from `searchPaths` config and `installed` kit entries.
15
15
  */
16
16
  export function resolveStashSources(overrideStashDir, existingConfig) {
17
17
  const stashDir = overrideStashDir ?? resolveStashDir();
@@ -25,7 +25,7 @@ export function resolveStashSources(overrideStashDir, existingConfig) {
25
25
  sources.push({ path: dir });
26
26
  }
27
27
  }
28
- for (const entry of config.registry?.installed ?? []) {
28
+ for (const entry of config.installed ?? []) {
29
29
  if (isSuspiciousStashRoot(entry.stashRoot)) {
30
30
  warn(`Warning: stash root "${entry.stashRoot}" appears to be a system directory. This may be unintentional.`);
31
31
  }
@@ -67,7 +67,7 @@ export function getPrimarySource(sources) {
67
67
  * Determine whether a file is safe to edit in place.
68
68
  *
69
69
  * The only files that are NOT editable are those inside a cache directory
70
- * managed by the package manager (`registry.installed[].cacheDir`). These
70
+ * managed by the package manager (`installed[].cacheDir`). These
71
71
  * will be overwritten by `akm update` without warning.
72
72
  *
73
73
  * Everything else — working stash, search paths, local project dirs — is
@@ -76,7 +76,7 @@ export function getPrimarySource(sources) {
76
76
  export function isEditable(filePath, config) {
77
77
  const cfg = config ?? loadConfig();
78
78
  const resolved = path.resolve(filePath);
79
- const cacheManaged = cfg.registry?.installed ?? [];
79
+ const cacheManaged = cfg.installed ?? [];
80
80
  const isWin = process.platform === "win32";
81
81
  for (const entry of cacheManaged) {
82
82
  // Local sources reference original paths — always editable
@@ -101,8 +101,7 @@ export function isEditable(filePath, config) {
101
101
  * unconditionally returns the hint string.
102
102
  */
103
103
  export function buildEditHint(_filePath, assetType, assetName, origin) {
104
- const normalizedType = normalizeAssetType(assetType);
105
- const ref = origin ? `${origin}//${normalizedType}:${assetName}` : `${normalizedType}:${assetName}`;
104
+ const ref = origin ? `${origin}//${assetType}:${assetName}` : `${assetType}:${assetName}`;
106
105
  return `This asset is managed by akm and may be overwritten on update. To edit, run: akm clone ${ref}`;
107
106
  }
108
107
  // ── Validation ──────────────────────────────────────────────────────────────
package/dist/walker.js CHANGED
@@ -14,7 +14,7 @@ import { buildFileContext } from "./file-context";
14
14
  * Walk a type root directory and return files grouped by their parent directory.
15
15
  *
16
16
  * Only files relevant to the given `assetType` are included (e.g. `.md` for
17
- * commands, script extensions for tools, `SKILL.md` for skills).
17
+ * commands, script extensions for scripts, `SKILL.md` for skills).
18
18
  */
19
19
  export function walkStash(typeRoot, assetType) {
20
20
  if (!fs.existsSync(typeRoot))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "akm-cli",
3
- "version": "0.0.16",
3
+ "version": "0.0.17",
4
4
  "type": "module",
5
5
  "description": "CLI tool to search, open, and run extension assets from an akm stash directory.",
6
6
  "keywords": [