agentikit 0.0.9 → 0.0.12

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 (107) hide show
  1. package/README.md +129 -214
  2. package/dist/index.d.ts +8 -2
  3. package/dist/index.js +4 -1
  4. package/dist/src/asset-spec.d.ts +2 -0
  5. package/dist/src/asset-spec.js +22 -3
  6. package/dist/src/asset-type-handler.d.ts +27 -0
  7. package/dist/src/asset-type-handler.js +33 -0
  8. package/dist/src/cli.js +201 -75
  9. package/dist/src/common.d.ts +6 -1
  10. package/dist/src/common.js +18 -4
  11. package/dist/src/config-cli.d.ts +9 -0
  12. package/dist/src/config-cli.js +473 -0
  13. package/dist/src/config.d.ts +19 -6
  14. package/dist/src/config.js +139 -29
  15. package/dist/src/db.d.ts +46 -0
  16. package/dist/src/db.js +299 -0
  17. package/dist/src/embedder.js +12 -7
  18. package/dist/src/github.d.ts +4 -0
  19. package/dist/src/github.js +19 -0
  20. package/dist/src/handlers/agent-handler.d.ts +2 -0
  21. package/dist/src/handlers/agent-handler.js +26 -0
  22. package/dist/src/handlers/command-handler.d.ts +2 -0
  23. package/dist/src/handlers/command-handler.js +23 -0
  24. package/dist/src/handlers/index.d.ts +6 -0
  25. package/dist/src/handlers/index.js +23 -0
  26. package/dist/src/handlers/knowledge-handler.d.ts +2 -0
  27. package/dist/src/handlers/knowledge-handler.js +56 -0
  28. package/dist/src/handlers/markdown-helpers.d.ts +7 -0
  29. package/dist/src/handlers/markdown-helpers.js +15 -0
  30. package/dist/src/handlers/script-handler.d.ts +2 -0
  31. package/dist/src/handlers/script-handler.js +78 -0
  32. package/dist/src/handlers/skill-handler.d.ts +2 -0
  33. package/dist/src/handlers/skill-handler.js +30 -0
  34. package/dist/src/handlers/tool-handler.d.ts +2 -0
  35. package/dist/src/handlers/tool-handler.js +58 -0
  36. package/dist/src/indexer.d.ts +1 -23
  37. package/dist/src/indexer.js +162 -155
  38. package/dist/src/init.d.ts +2 -2
  39. package/dist/src/init.js +21 -9
  40. package/dist/src/llm.js +4 -3
  41. package/dist/src/metadata.d.ts +0 -1
  42. package/dist/src/metadata.js +6 -64
  43. package/dist/src/origin-resolve.d.ts +19 -0
  44. package/dist/src/origin-resolve.js +53 -0
  45. package/dist/src/registry-install.d.ts +2 -2
  46. package/dist/src/registry-install.js +142 -35
  47. package/dist/src/registry-resolve.js +90 -22
  48. package/dist/src/registry-search.d.ts +22 -0
  49. package/dist/src/registry-search.js +231 -97
  50. package/dist/src/registry-types.d.ts +9 -2
  51. package/dist/src/stash-add.js +4 -4
  52. package/dist/src/stash-clone.d.ts +22 -0
  53. package/dist/src/stash-clone.js +83 -0
  54. package/dist/src/stash-ref.d.ts +27 -3
  55. package/dist/src/stash-ref.js +63 -24
  56. package/dist/src/stash-registry.js +12 -12
  57. package/dist/src/stash-resolve.js +3 -0
  58. package/dist/src/stash-search.js +168 -164
  59. package/dist/src/stash-show.d.ts +1 -1
  60. package/dist/src/stash-show.js +28 -96
  61. package/dist/src/stash-source.d.ts +24 -0
  62. package/dist/src/stash-source.js +81 -0
  63. package/dist/src/stash-types.d.ts +14 -4
  64. package/dist/src/stash.d.ts +6 -0
  65. package/dist/src/stash.js +3 -0
  66. package/dist/src/tool-runner.d.ts +1 -1
  67. package/dist/src/tool-runner.js +18 -5
  68. package/package.json +7 -2
  69. package/src/asset-spec.ts +20 -4
  70. package/src/asset-type-handler.ts +77 -0
  71. package/src/cli.ts +213 -82
  72. package/src/common.ts +23 -5
  73. package/src/config-cli.ts +499 -0
  74. package/src/config.ts +160 -38
  75. package/src/db.ts +411 -0
  76. package/src/embedder.ts +22 -11
  77. package/src/github.ts +21 -0
  78. package/src/handlers/agent-handler.ts +32 -0
  79. package/src/handlers/command-handler.ts +29 -0
  80. package/src/handlers/index.ts +25 -0
  81. package/src/handlers/knowledge-handler.ts +62 -0
  82. package/src/handlers/markdown-helpers.ts +19 -0
  83. package/src/handlers/script-handler.ts +92 -0
  84. package/src/handlers/skill-handler.ts +37 -0
  85. package/src/handlers/tool-handler.ts +71 -0
  86. package/src/indexer.ts +208 -187
  87. package/src/init.ts +17 -9
  88. package/src/llm.ts +4 -3
  89. package/src/metadata.ts +5 -65
  90. package/src/origin-resolve.ts +67 -0
  91. package/src/registry-install.ts +158 -42
  92. package/src/registry-resolve.ts +92 -23
  93. package/src/registry-search.ts +288 -98
  94. package/src/registry-types.ts +10 -2
  95. package/src/stash-add.ts +14 -17
  96. package/src/stash-clone.ts +127 -0
  97. package/src/stash-ref.ts +84 -26
  98. package/src/stash-registry.ts +12 -12
  99. package/src/stash-resolve.ts +3 -0
  100. package/src/stash-search.ts +202 -184
  101. package/src/stash-show.ts +33 -90
  102. package/src/stash-source.ts +103 -0
  103. package/src/stash-types.ts +14 -4
  104. package/src/stash.ts +8 -0
  105. package/src/tool-runner.ts +18 -5
  106. package/dist/src/similarity.d.ts +0 -34
  107. package/src/similarity.ts +0 -271
@@ -1,27 +1,14 @@
1
1
  import fs from "node:fs";
2
- import path from "node:path";
3
- import { parseFrontmatter, toStringOrUndefined } from "./frontmatter";
4
- import { resolveStashDir } from "./common";
5
- import { parseOpenRef } from "./stash-ref";
2
+ import { parseAssetRef } from "./stash-ref";
3
+ import { resolveSourcesForOrigin } from "./origin-resolve";
6
4
  import { resolveAssetPath } from "./stash-resolve";
7
- import { parseMarkdownToc, extractSection, extractLineRange, extractFrontmatterOnly, formatToc } from "./markdown";
8
- import { buildToolInfo } from "./tool-runner";
9
- import { loadConfig } from "./config";
10
- export function agentikitShow(input) {
11
- const parsed = parseOpenRef(input.ref);
12
- const stashDir = resolveStashDir();
13
- const config = loadConfig(stashDir);
14
- const allStashDirs = [
15
- stashDir,
16
- ...config.additionalStashDirs.filter((d) => {
17
- try {
18
- return fs.statSync(d).isDirectory();
19
- }
20
- catch {
21
- return false;
22
- }
23
- }),
24
- ];
5
+ import { getHandler } from "./asset-type-handler";
6
+ import { resolveStashSources, findSourceForPath } from "./stash-source";
7
+ export async function agentikitShow(input) {
8
+ const parsed = parseAssetRef(input.ref);
9
+ const allSources = resolveStashSources();
10
+ const searchSources = resolveSourcesForOrigin(parsed.origin, allSources);
11
+ const allStashDirs = searchSources.map((s) => s.path);
25
12
  let assetPath;
26
13
  let lastError;
27
14
  for (const dir of allStashDirs) {
@@ -33,82 +20,27 @@ export function agentikitShow(input) {
33
20
  lastError = err instanceof Error ? err : new Error(String(err));
34
21
  }
35
22
  }
23
+ if (!assetPath && parsed.origin && searchSources.length === 0) {
24
+ const installCmd = `akm add ${parsed.origin}`;
25
+ throw new Error(`Stash asset not found for ref: ${parsed.type}:${parsed.name}. ` +
26
+ `Kit "${parsed.origin}" is not installed. Run: ${installCmd}`);
27
+ }
36
28
  if (!assetPath) {
37
29
  throw lastError ?? new Error(`Stash asset not found for ref: ${parsed.type}:${parsed.name}`);
38
30
  }
39
31
  const content = fs.readFileSync(assetPath, "utf8");
40
- switch (parsed.type) {
41
- case "skill":
42
- return {
43
- type: "skill",
44
- name: parsed.name,
45
- path: assetPath,
46
- content,
47
- };
48
- case "command": {
49
- const parsedMd = parseFrontmatter(content);
50
- return {
51
- type: "command",
52
- name: parsed.name,
53
- path: assetPath,
54
- description: toStringOrUndefined(parsedMd.data.description),
55
- template: parsedMd.content,
56
- };
57
- }
58
- case "agent": {
59
- const parsedMd = parseFrontmatter(content);
60
- return {
61
- type: "agent",
62
- name: parsed.name,
63
- path: assetPath,
64
- description: toStringOrUndefined(parsedMd.data.description),
65
- prompt: "Dispatching prompt must include the agent's full prompt content verbatim; summaries are non-compliant. \n\n"
66
- + parsedMd.content,
67
- toolPolicy: parsedMd.data.tools,
68
- modelHint: parsedMd.data.model,
69
- };
70
- }
71
- case "tool": {
72
- const assetStashDir = allStashDirs.find((d) => path.resolve(assetPath).startsWith(path.resolve(d) + path.sep)) ?? stashDir;
73
- const toolInfo = buildToolInfo(assetStashDir, assetPath);
74
- return {
75
- type: "tool",
76
- name: parsed.name,
77
- path: assetPath,
78
- runCmd: toolInfo.runCmd,
79
- kind: toolInfo.kind,
80
- };
81
- }
82
- case "knowledge": {
83
- const v = input.view ?? { mode: "full" };
84
- switch (v.mode) {
85
- case "toc": {
86
- const toc = parseMarkdownToc(content);
87
- return { type: "knowledge", name: parsed.name, path: assetPath, content: formatToc(toc) };
88
- }
89
- case "frontmatter": {
90
- const fm = extractFrontmatterOnly(content);
91
- return { type: "knowledge", name: parsed.name, path: assetPath, content: fm ?? "(no frontmatter)" };
92
- }
93
- case "section": {
94
- const section = extractSection(content, v.heading);
95
- if (!section) {
96
- return {
97
- type: "knowledge",
98
- name: parsed.name,
99
- path: assetPath,
100
- content: `Section "${v.heading}" not found in ${parsed.name}. Try --view toc to discover available headings.`,
101
- };
102
- }
103
- return { type: "knowledge", name: parsed.name, path: assetPath, content: section.content };
104
- }
105
- case "lines": {
106
- return { type: "knowledge", name: parsed.name, path: assetPath, content: extractLineRange(content, v.start, v.end) };
107
- }
108
- default: {
109
- return { type: "knowledge", name: parsed.name, path: assetPath, content };
110
- }
111
- }
112
- }
113
- }
32
+ const source = findSourceForPath(assetPath, allSources);
33
+ const handler = getHandler(parsed.type);
34
+ const response = handler.buildShowResponse({
35
+ name: parsed.name,
36
+ path: assetPath,
37
+ content,
38
+ view: input.view,
39
+ stashDirs: allStashDirs,
40
+ });
41
+ return {
42
+ ...response,
43
+ registryId: source?.registryId,
44
+ editable: source?.writable ?? false,
45
+ };
114
46
  }
@@ -0,0 +1,24 @@
1
+ export type StashSourceKind = "working" | "mounted" | "installed";
2
+ export interface StashSource {
3
+ kind: StashSourceKind;
4
+ path: string;
5
+ /** For installed sources, the registry entry id */
6
+ registryId?: string;
7
+ /** Whether this source is writable (only working stash) */
8
+ writable: boolean;
9
+ }
10
+ /**
11
+ * Build the ordered list of stash sources:
12
+ * 1. Working stash (writable)
13
+ * 2. Mounted stash dirs (read-only, user-configured)
14
+ * 3. Installed stash dirs (read-only, derived from registry.installed)
15
+ */
16
+ export declare function resolveStashSources(overrideStashDir?: string): StashSource[];
17
+ /**
18
+ * Convenience: returns just the directory paths, preserving priority order.
19
+ */
20
+ export declare function resolveAllStashDirs(overrideStashDir?: string): string[];
21
+ /**
22
+ * Find which source a file path belongs to.
23
+ */
24
+ export declare function findSourceForPath(filePath: string, sources: StashSource[]): StashSource | undefined;
@@ -0,0 +1,81 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { resolveStashDir } from "./common";
4
+ import { loadConfig } from "./config";
5
+ // ── Resolution ──────────────────────────────────────────────────────────────
6
+ /**
7
+ * Build the ordered list of stash sources:
8
+ * 1. Working stash (writable)
9
+ * 2. Mounted stash dirs (read-only, user-configured)
10
+ * 3. Installed stash dirs (read-only, derived from registry.installed)
11
+ */
12
+ export function resolveStashSources(overrideStashDir) {
13
+ const stashDir = overrideStashDir ?? resolveStashDir();
14
+ const config = loadConfig();
15
+ const sources = [
16
+ { kind: "working", path: stashDir, writable: true },
17
+ ];
18
+ for (const dir of config.mountedStashDirs) {
19
+ if (isSuspiciousStashRoot(dir)) {
20
+ console.warn(`Warning: stash root "${dir}" appears to be a system directory. This may be unintentional.`);
21
+ }
22
+ if (isValidDirectory(dir)) {
23
+ sources.push({ kind: "mounted", path: dir, writable: false });
24
+ }
25
+ }
26
+ for (const entry of config.registry?.installed ?? []) {
27
+ if (isSuspiciousStashRoot(entry.stashRoot)) {
28
+ console.warn(`Warning: stash root "${entry.stashRoot}" appears to be a system directory. This may be unintentional.`);
29
+ }
30
+ if (isValidDirectory(entry.stashRoot)) {
31
+ sources.push({
32
+ kind: "installed",
33
+ path: entry.stashRoot,
34
+ registryId: entry.id,
35
+ writable: false,
36
+ });
37
+ }
38
+ }
39
+ return sources;
40
+ }
41
+ /**
42
+ * Convenience: returns just the directory paths, preserving priority order.
43
+ */
44
+ export function resolveAllStashDirs(overrideStashDir) {
45
+ return resolveStashSources(overrideStashDir).map((s) => s.path);
46
+ }
47
+ /**
48
+ * Find which source a file path belongs to.
49
+ */
50
+ export function findSourceForPath(filePath, sources) {
51
+ const resolved = path.resolve(filePath);
52
+ for (const source of sources) {
53
+ if (resolved.startsWith(path.resolve(source.path) + path.sep))
54
+ return source;
55
+ }
56
+ return undefined;
57
+ }
58
+ // ── Validation ──────────────────────────────────────────────────────────────
59
+ const SUSPICIOUS_ROOTS = new Set(['/', '/etc', '/bin', '/sbin', '/usr', '/var', '/tmp', '/dev', '/proc', '/sys']);
60
+ function isSuspiciousStashRoot(dir) {
61
+ const resolved = path.resolve(dir);
62
+ const normalized = process.platform === 'win32' ? resolved.toLowerCase() : resolved;
63
+ if (SUSPICIOUS_ROOTS.has(normalized))
64
+ return true;
65
+ if (process.platform === 'win32') {
66
+ // Check for Windows system directories
67
+ const winDir = (process.env.SystemRoot || 'C:\\Windows').toLowerCase();
68
+ if (normalized === winDir || normalized.startsWith(winDir + path.sep))
69
+ return true;
70
+ }
71
+ return false;
72
+ }
73
+ // ── Helpers ─────────────────────────────────────────────────────────────────
74
+ function isValidDirectory(dir) {
75
+ try {
76
+ return fs.statSync(dir).isDirectory();
77
+ }
78
+ catch {
79
+ return false;
80
+ }
81
+ }
@@ -10,6 +10,10 @@ export interface LocalSearchHit {
10
10
  name: string;
11
11
  path: string;
12
12
  openRef: string;
13
+ /** For installed sources, the registry id */
14
+ registryId?: string;
15
+ /** Whether this asset is editable (only true for working stash) */
16
+ editable?: boolean;
13
17
  description?: string;
14
18
  tags?: string[];
15
19
  score?: number;
@@ -38,6 +42,8 @@ export interface RegistrySearchResultHit {
38
42
  metadata?: Record<string, string>;
39
43
  installRef: string;
40
44
  installCmd: string;
45
+ /** Whether this entry was manually reviewed and approved */
46
+ curated?: boolean;
41
47
  }
42
48
  export type SearchHit = LocalSearchHit | RegistrySearchResultHit;
43
49
  export interface SearchResponse {
@@ -70,7 +76,7 @@ export interface AddResponse {
70
76
  installedAt: string;
71
77
  };
72
78
  config: {
73
- additionalStashDirs: string[];
79
+ mountedStashDirs: string[];
74
80
  installedRegistryCount: number;
75
81
  };
76
82
  index: {
@@ -123,7 +129,7 @@ export interface RemoveResponse {
123
129
  stashRoot: string;
124
130
  };
125
131
  config: {
126
- additionalStashDirs: string[];
132
+ mountedStashDirs: string[];
127
133
  installedRegistryCount: number;
128
134
  };
129
135
  index: {
@@ -146,7 +152,7 @@ export interface ReinstallResponse {
146
152
  all: boolean;
147
153
  processed: ReinstallResultItem[];
148
154
  config: {
149
- additionalStashDirs: string[];
155
+ mountedStashDirs: string[];
150
156
  installedRegistryCount: number;
151
157
  };
152
158
  index: {
@@ -178,7 +184,7 @@ export interface UpdateResponse {
178
184
  all: boolean;
179
185
  processed: UpdateResultItem[];
180
186
  config: {
181
- additionalStashDirs: string[];
187
+ mountedStashDirs: string[];
182
188
  installedRegistryCount: number;
183
189
  };
184
190
  index: {
@@ -200,6 +206,10 @@ export interface ShowResponse {
200
206
  modelHint?: unknown;
201
207
  runCmd?: string;
202
208
  kind?: ToolKind;
209
+ /** For installed sources, the registry id */
210
+ registryId?: string;
211
+ /** Whether this asset is editable (only true for working stash) */
212
+ editable?: boolean;
203
213
  }
204
214
  export type KnowledgeView = {
205
215
  mode: "full";
@@ -3,8 +3,14 @@ export { resolveStashDir } from "./common";
3
3
  export { agentikitInit } from "./init";
4
4
  export type { InitResponse } from "./init";
5
5
  export type { ToolKind } from "./tool-runner";
6
+ export type { AssetTypeHandler, ShowInput } from "./asset-type-handler";
7
+ export { registerAssetType, getHandler, getAllHandlers, getRegisteredTypeNames } from "./asset-type-handler";
6
8
  export { agentikitSearch } from "./stash-search";
7
9
  export { agentikitShow } from "./stash-show";
8
10
  export { agentikitAdd } from "./stash-add";
11
+ export { agentikitClone } from "./stash-clone";
9
12
  export { agentikitList, agentikitRemove, agentikitReinstall, agentikitUpdate } from "./stash-registry";
13
+ export { resolveStashSources, resolveAllStashDirs, findSourceForPath } from "./stash-source";
14
+ export type { StashSource, StashSourceKind } from "./stash-source";
10
15
  export type { AddResponse, AgentikitSearchType, LocalSearchHit, RegistrySearchResultHit, SearchSource, SearchUsageMode, SearchHit, SearchResponse, ShowResponse, KnowledgeView, ListResponse, RemoveResponse, ReinstallResponse, UpdateResponse, RegistryListEntry, RegistryInstallStatus, ReinstallResultItem, UpdateResultItem, } from "./stash-types";
16
+ export type { CloneOptions, CloneResponse } from "./stash-clone";
package/dist/src/stash.js CHANGED
@@ -1,6 +1,9 @@
1
1
  export { resolveStashDir } from "./common";
2
2
  export { agentikitInit } from "./init";
3
+ export { registerAssetType, getHandler, getAllHandlers, getRegisteredTypeNames } from "./asset-type-handler";
3
4
  export { agentikitSearch } from "./stash-search";
4
5
  export { agentikitShow } from "./stash-show";
5
6
  export { agentikitAdd } from "./stash-add";
7
+ export { agentikitClone } from "./stash-clone";
6
8
  export { agentikitList, agentikitRemove, agentikitReinstall, agentikitUpdate } from "./stash-registry";
9
+ export { resolveStashSources, resolveAllStashDirs, findSourceForPath } from "./stash-source";
@@ -22,7 +22,7 @@ export interface ToolInfo {
22
22
  *
23
23
  * For `.ts` / `.js` files, looks up the nearest `package.json` so that
24
24
  * `bun install` can be run in the correct working directory when the
25
- * `AGENTIKIT_BUN_INSTALL` env flag is set.
25
+ * `AKM_BUN_INSTALL` env flag is set.
26
26
  */
27
27
  export declare function buildToolInfo(stashDir: string, filePath: string): ToolInfo;
28
28
  /**
@@ -13,7 +13,7 @@ import { IS_WINDOWS, isWithin } from "./common";
13
13
  *
14
14
  * For `.ts` / `.js` files, looks up the nearest `package.json` so that
15
15
  * `bun install` can be run in the correct working directory when the
16
- * `AGENTIKIT_BUN_INSTALL` env flag is set.
16
+ * `AKM_BUN_INSTALL` env flag is set.
17
17
  */
18
18
  export function buildToolInfo(stashDir, filePath) {
19
19
  const ext = path.extname(filePath).toLowerCase();
@@ -41,8 +41,17 @@ export function buildToolInfo(stashDir, filePath) {
41
41
  if (ext !== ".ts" && ext !== ".js") {
42
42
  throw new Error(`Unsupported tool extension: ${ext}`);
43
43
  }
44
- const toolsRoot = path.resolve(path.join(stashDir, "tools"));
45
- const pkgDir = findNearestPackageDir(path.dirname(filePath), toolsRoot);
44
+ // Determine the type root by checking which subdirectory contains the file
45
+ const resolvedFile = path.resolve(filePath);
46
+ let typeRoot = path.resolve(path.join(stashDir, "tools"));
47
+ for (const subdir of ["tools", "scripts"]) {
48
+ const candidate = path.resolve(path.join(stashDir, subdir));
49
+ if (resolvedFile.startsWith(candidate + path.sep)) {
50
+ typeRoot = candidate;
51
+ break;
52
+ }
53
+ }
54
+ const pkgDir = findNearestPackageDir(path.dirname(filePath), typeRoot);
46
55
  if (!pkgDir) {
47
56
  return {
48
57
  runCmd: `bun ${shellQuote(filePath)}`,
@@ -50,7 +59,7 @@ export function buildToolInfo(stashDir, filePath) {
50
59
  execute: { command: "bun", args: [filePath] },
51
60
  };
52
61
  }
53
- const installFlag = process.env.AGENTIKIT_BUN_INSTALL;
62
+ const installFlag = process.env.AKM_BUN_INSTALL;
54
63
  const shouldInstall = installFlag === "1" || installFlag === "true" || installFlag === "yes";
55
64
  const quotedPkgDir = shellQuote(pkgDir);
56
65
  const quotedFilePath = shellQuote(filePath);
@@ -73,7 +82,11 @@ export function shellQuote(input) {
73
82
  throw new Error("Unsupported control characters in stash path.");
74
83
  }
75
84
  if (IS_WINDOWS) {
76
- return `"${input.replace(/"/g, '""')}"`;
85
+ const escaped = input
86
+ .replace(/%/g, "%%")
87
+ .replace(/([\\^|&<>])/g, "^$1")
88
+ .replace(/"/g, '""');
89
+ return `"${escaped}"`;
77
90
  }
78
91
  const escaped = input
79
92
  .replace(/\\/g, "\\\\")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentikit",
3
- "version": "0.0.9",
3
+ "version": "0.0.12",
4
4
  "type": "module",
5
5
  "description": "CLI tool to search, open, and run extension assets from an agentikit stash directory.",
6
6
  "keywords": [
@@ -49,10 +49,15 @@
49
49
  },
50
50
  "devDependencies": {
51
51
  "@types/node": "^24.0.0",
52
+ "bun-types": "^1.3.10",
52
53
  "typescript": "^5.9.3"
53
54
  },
54
55
  "optionalDependencies": {
55
- "@xenova/transformers": "^2.17.0"
56
+ "@xenova/transformers": "^2.17.0",
57
+ "sqlite-vec": "^0.1.7-alpha.2"
58
+ },
59
+ "engines": {
60
+ "bun": ">=1.0.0"
56
61
  },
57
62
  "dependencies": {
58
63
  "citty": "^0.2.1"
package/src/asset-spec.ts CHANGED
@@ -1,5 +1,7 @@
1
1
  import path from "node:path"
2
2
  import type { AgentikitAssetType } from "./common"
3
+ import { toPosix } from "./common"
4
+ import { tryGetHandler } from "./asset-type-handler"
3
5
 
4
6
  export const SCRIPT_EXTENSIONS = new Set([".sh", ".ts", ".js", ".ps1", ".cmd", ".bat"])
5
7
 
@@ -16,6 +18,12 @@ const markdownSpec: Omit<AssetSpec, "stashDir"> = {
16
18
  toAssetPath: (typeRoot, name) => path.join(typeRoot, name),
17
19
  }
18
20
 
21
+ /** Extended set of script extensions for the script asset type */
22
+ export const SCRIPT_EXTENSIONS_BROAD = new Set([
23
+ ...SCRIPT_EXTENSIONS,
24
+ ".py", ".rb", ".go", ".pl", ".php", ".lua", ".r", ".swift", ".kt", ".kts",
25
+ ])
26
+
19
27
  export const ASSET_SPECS: Record<AgentikitAssetType, AssetSpec> = {
20
28
  tool: {
21
29
  stashDir: "tools",
@@ -36,6 +44,12 @@ export const ASSET_SPECS: Record<AgentikitAssetType, AssetSpec> = {
36
44
  command: { stashDir: "commands", ...markdownSpec },
37
45
  agent: { stashDir: "agents", ...markdownSpec },
38
46
  knowledge: { stashDir: "knowledge", ...markdownSpec },
47
+ script: {
48
+ stashDir: "scripts",
49
+ isRelevantFile: (fileName) => SCRIPT_EXTENSIONS_BROAD.has(path.extname(fileName).toLowerCase()),
50
+ toCanonicalName: (typeRoot, filePath) => toPosix(path.relative(typeRoot, filePath)),
51
+ toAssetPath: (typeRoot, name) => path.join(typeRoot, name),
52
+ },
39
53
  }
40
54
 
41
55
  export const ASSET_TYPES = Object.keys(ASSET_SPECS) as AgentikitAssetType[]
@@ -49,6 +63,8 @@ export const TYPE_DIRS: Record<AgentikitAssetType, string> = ASSET_TYPES.reduce(
49
63
  )
50
64
 
51
65
  export function isRelevantAssetFile(assetType: AgentikitAssetType, fileName: string): boolean {
66
+ const handler = tryGetHandler(assetType)
67
+ if (handler) return handler.isRelevantFile(fileName)
52
68
  return ASSET_SPECS[assetType].isRelevantFile(fileName)
53
69
  }
54
70
 
@@ -57,13 +73,13 @@ export function deriveCanonicalAssetName(
57
73
  typeRoot: string,
58
74
  filePath: string,
59
75
  ): string | undefined {
76
+ const handler = tryGetHandler(assetType)
77
+ if (handler) return handler.toCanonicalName(typeRoot, filePath)
60
78
  return ASSET_SPECS[assetType].toCanonicalName(typeRoot, filePath)
61
79
  }
62
80
 
63
81
  export function resolveAssetPathFromName(assetType: AgentikitAssetType, typeRoot: string, name: string): string {
82
+ const handler = tryGetHandler(assetType)
83
+ if (handler) return handler.toAssetPath(typeRoot, name)
64
84
  return ASSET_SPECS[assetType].toAssetPath(typeRoot, name)
65
85
  }
66
-
67
- function toPosix(input: string): string {
68
- return input.replace(/\\/g, "/")
69
- }
@@ -0,0 +1,77 @@
1
+ import type { StashEntry } from "./metadata"
2
+ import type { LocalSearchHit, ShowResponse, KnowledgeView } from "./stash-types"
3
+
4
+ // ── Interface ────────────────────────────────────────────────────────────────
5
+
6
+ export interface ShowInput {
7
+ name: string
8
+ path: string
9
+ content: string
10
+ view?: KnowledgeView
11
+ stashDirs?: string[]
12
+ }
13
+
14
+ export interface AssetTypeHandler {
15
+ /** The type name, e.g. "tool", "script" */
16
+ readonly typeName: string
17
+ /** Directory inside the stash root, e.g. "tools", "scripts" */
18
+ readonly stashDir: string
19
+
20
+ // -- File system spec --
21
+ isRelevantFile(fileName: string): boolean
22
+ toCanonicalName(typeRoot: string, filePath: string): string | undefined
23
+ toAssetPath(typeRoot: string, name: string): string
24
+
25
+ // -- Show behavior --
26
+ buildShowResponse(input: ShowInput): ShowResponse
27
+
28
+ // -- Search enrichment --
29
+ enrichSearchHit?(hit: LocalSearchHit, stashDir: string): void
30
+
31
+ // -- Usage guide --
32
+ readonly defaultUsageGuide: string[]
33
+
34
+ // -- Metadata generation hooks --
35
+ extractTypeMetadata?(entry: StashEntry, file: string, ext: string): void
36
+ }
37
+
38
+ // ── Registry ─────────────────────────────────────────────────────────────────
39
+
40
+ const handlers = new Map<string, AssetTypeHandler>()
41
+
42
+ let handlersInitialized = false
43
+
44
+ function ensureHandlersRegistered(): void {
45
+ if (handlersInitialized) return
46
+ handlersInitialized = true
47
+ // Import handler registrations
48
+ require("./handlers/index")
49
+ }
50
+
51
+ export function registerAssetType(handler: AssetTypeHandler): void {
52
+ handlers.set(handler.typeName, handler)
53
+ }
54
+
55
+ export function getHandler(type: string): AssetTypeHandler {
56
+ ensureHandlersRegistered()
57
+ const handler = handlers.get(type)
58
+ if (!handler) {
59
+ throw new Error(`Unknown asset type: "${type}"`)
60
+ }
61
+ return handler
62
+ }
63
+
64
+ export function tryGetHandler(type: string): AssetTypeHandler | undefined {
65
+ ensureHandlersRegistered()
66
+ return handlers.get(type)
67
+ }
68
+
69
+ export function getAllHandlers(): AssetTypeHandler[] {
70
+ ensureHandlersRegistered()
71
+ return Array.from(handlers.values())
72
+ }
73
+
74
+ export function getRegisteredTypeNames(): string[] {
75
+ ensureHandlersRegistered()
76
+ return Array.from(handlers.keys())
77
+ }