akm-cli 0.0.21 → 0.0.22

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 (45) hide show
  1. package/README.md +8 -5
  2. package/dist/asset-spec.js +91 -10
  3. package/dist/cli.js +195 -55
  4. package/dist/common.js +15 -2
  5. package/dist/config-cli.js +65 -6
  6. package/dist/config.js +206 -22
  7. package/dist/create-provider-registry.js +18 -0
  8. package/dist/db.js +156 -53
  9. package/dist/embedder.js +36 -18
  10. package/dist/errors.js +6 -0
  11. package/dist/file-context.js +18 -19
  12. package/dist/frontmatter.js +19 -3
  13. package/dist/indexer.js +126 -89
  14. package/dist/{stash-registry.js → installed-kits.js} +16 -24
  15. package/dist/kit-include.js +108 -0
  16. package/dist/local-search.js +429 -0
  17. package/dist/lockfile.js +47 -5
  18. package/dist/matchers.js +6 -0
  19. package/dist/metadata.js +20 -10
  20. package/dist/paths.js +4 -0
  21. package/dist/providers/skills-sh.js +3 -2
  22. package/dist/providers/static-index.js +4 -9
  23. package/dist/registry-build-index.js +356 -0
  24. package/dist/registry-factory.js +19 -0
  25. package/dist/registry-install.js +114 -109
  26. package/dist/registry-resolve.js +44 -9
  27. package/dist/registry-search.js +14 -9
  28. package/dist/renderers.js +23 -7
  29. package/dist/ripgrep-install.js +9 -4
  30. package/dist/self-update.js +31 -4
  31. package/dist/stash-add.js +75 -6
  32. package/dist/stash-clone.js +1 -1
  33. package/dist/stash-provider-factory.js +52 -0
  34. package/dist/stash-provider.js +1 -0
  35. package/dist/stash-providers/filesystem.js +42 -0
  36. package/dist/stash-providers/index.js +9 -0
  37. package/dist/stash-providers/openviking.js +337 -0
  38. package/dist/stash-resolve.js +4 -4
  39. package/dist/stash-search.js +70 -401
  40. package/dist/stash-show.js +24 -5
  41. package/dist/stash-source.js +19 -11
  42. package/dist/walker.js +15 -10
  43. package/dist/warn.js +7 -0
  44. package/package.json +1 -1
  45. package/dist/provider-registry.js +0 -8
package/dist/walker.js CHANGED
@@ -5,7 +5,6 @@
5
5
  * (stash.ts) and the indexer (indexer.ts) to walk type-specific asset
6
6
  * directories and group files by parent directory.
7
7
  */
8
- import { spawnSync } from "node:child_process";
9
8
  import fs from "node:fs";
10
9
  import path from "node:path";
11
10
  import { isRelevantAssetFile } from "./asset-spec";
@@ -77,17 +76,16 @@ function walkStashGit(stashRoot) {
77
76
  if (!isInsideGitRepo(stashRoot))
78
77
  return null;
79
78
  // Get tracked + untracked (non-ignored) files
80
- const result = spawnSync("git", ["ls-files", "--cached", "--others", "--exclude-standard", "-z", "--", "."], {
79
+ const result = Bun.spawnSync(["git", "ls-files", "--cached", "--others", "--exclude-standard", "-z", "--", "."], {
81
80
  cwd: stashRoot,
82
- encoding: "utf8",
83
- timeout: 30_000,
84
- maxBuffer: 10 * 1024 * 1024, // 10MB
85
81
  });
86
- if (result.status !== 0)
82
+ // result.success is false if the process exited non-zero OR git was not found
83
+ if (!result.success)
87
84
  return null;
88
85
  const SKIP_DIRS = new Set([".git", "node_modules", "bin", ".cache"]);
89
86
  const SKIP_FILES = new Set([".stash.json", ".gitignore", ".gitattributes"]);
90
- const files = result.stdout
87
+ const stdout = Buffer.isBuffer(result.stdout) ? result.stdout.toString("utf8") : String(result.stdout ?? "");
88
+ const files = stdout
91
89
  .split("\0")
92
90
  .filter((f) => f.length > 0)
93
91
  .filter((f) => !f.startsWith("..") && !path.isAbsolute(f))
@@ -98,8 +96,7 @@ function walkStashGit(stashRoot) {
98
96
  .filter(Boolean);
99
97
  return !dirParts.some((part) => SKIP_DIRS.has(part) || part.startsWith("."));
100
98
  })
101
- .filter((f) => !SKIP_FILES.has(path.basename(f)))
102
- .filter((f) => !f.includes("/.") && !f.startsWith(".")); // skip dot-dirs/files
99
+ .filter((f) => !SKIP_FILES.has(path.basename(f)));
103
100
  const results = [];
104
101
  for (const relFile of files) {
105
102
  const absPath = path.join(stashRoot, relFile);
@@ -114,7 +111,11 @@ function walkStashGit(stashRoot) {
114
111
  }
115
112
  return results;
116
113
  }
117
- /** Check if a directory is inside a git repository by walking up to find .git. */
114
+ /**
115
+ * Check if a directory is inside a git repository by walking up to find .git.
116
+ * Intentionally walks above stashRoot so that parent repo .gitignore rules
117
+ * apply when the stash is nested inside a larger git repository.
118
+ */
118
119
  function isInsideGitRepo(dir) {
119
120
  let current = path.resolve(dir);
120
121
  const root = path.parse(current).root;
@@ -149,6 +150,10 @@ function walkStashManual(stashRoot) {
149
150
  if (entry.name === ".stash.json")
150
151
  continue;
151
152
  const fullPath = path.join(current, entry.name);
153
+ if (entry.isSymbolicLink()) {
154
+ // Skip symlinks entirely to prevent potential path traversal outside stashRoot
155
+ continue;
156
+ }
152
157
  if (entry.isDirectory()) {
153
158
  if (SKIP_DIRS.has(entry.name) || entry.name.startsWith("."))
154
159
  continue;
package/dist/warn.js CHANGED
@@ -6,6 +6,13 @@ let quiet = false;
6
6
  export function setQuiet(value) {
7
7
  quiet = value;
8
8
  }
9
+ /**
10
+ * Reset the quiet flag to false.
11
+ * Intended for test teardown to prevent quiet state from leaking between tests.
12
+ */
13
+ export function resetQuiet() {
14
+ quiet = false;
15
+ }
9
16
  export function isQuiet() {
10
17
  return quiet;
11
18
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "akm-cli",
3
- "version": "0.0.21",
3
+ "version": "0.0.22",
4
4
  "type": "module",
5
5
  "description": "CLI tool to search, open, and run extension assets from an akm stash directory.",
6
6
  "keywords": [
@@ -1,8 +0,0 @@
1
- // ── Factory map ─────────────────────────────────────────────────────────────
2
- const providers = new Map();
3
- export function registerProvider(type, factory) {
4
- providers.set(type, factory);
5
- }
6
- export function resolveProviderFactory(type) {
7
- return providers.get(type) ?? null;
8
- }