agentikit 0.0.9 → 0.0.13
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.
- package/README.md +139 -208
- package/dist/index.d.ts +8 -2
- package/dist/index.js +4 -1
- package/dist/src/asset-spec.d.ts +2 -0
- package/dist/src/asset-spec.js +22 -3
- package/dist/src/asset-type-handler.d.ts +27 -0
- package/dist/src/asset-type-handler.js +33 -0
- package/dist/src/cli.js +201 -75
- package/dist/src/common.d.ts +6 -1
- package/dist/src/common.js +18 -4
- package/dist/src/config-cli.d.ts +9 -0
- package/dist/src/config-cli.js +473 -0
- package/dist/src/config.d.ts +19 -6
- package/dist/src/config.js +139 -29
- package/dist/src/db.d.ts +46 -0
- package/dist/src/db.js +299 -0
- package/dist/src/embedder.js +12 -7
- package/dist/src/github.d.ts +4 -0
- package/dist/src/github.js +19 -0
- package/dist/src/handlers/agent-handler.d.ts +2 -0
- package/dist/src/handlers/agent-handler.js +26 -0
- package/dist/src/handlers/command-handler.d.ts +2 -0
- package/dist/src/handlers/command-handler.js +23 -0
- package/dist/src/handlers/index.d.ts +6 -0
- package/dist/src/handlers/index.js +23 -0
- package/dist/src/handlers/knowledge-handler.d.ts +2 -0
- package/dist/src/handlers/knowledge-handler.js +56 -0
- package/dist/src/handlers/markdown-helpers.d.ts +7 -0
- package/dist/src/handlers/markdown-helpers.js +15 -0
- package/dist/src/handlers/script-handler.d.ts +2 -0
- package/dist/src/handlers/script-handler.js +78 -0
- package/dist/src/handlers/skill-handler.d.ts +2 -0
- package/dist/src/handlers/skill-handler.js +30 -0
- package/dist/src/handlers/tool-handler.d.ts +2 -0
- package/dist/src/handlers/tool-handler.js +58 -0
- package/dist/src/indexer.d.ts +1 -23
- package/dist/src/indexer.js +162 -155
- package/dist/src/init.d.ts +2 -2
- package/dist/src/init.js +21 -9
- package/dist/src/llm.js +4 -3
- package/dist/src/metadata.d.ts +0 -1
- package/dist/src/metadata.js +6 -64
- package/dist/src/origin-resolve.d.ts +19 -0
- package/dist/src/origin-resolve.js +53 -0
- package/dist/src/registry-install.d.ts +2 -2
- package/dist/src/registry-install.js +142 -35
- package/dist/src/registry-resolve.js +90 -22
- package/dist/src/registry-search.d.ts +22 -0
- package/dist/src/registry-search.js +231 -97
- package/dist/src/registry-types.d.ts +9 -2
- package/dist/src/stash-add.js +4 -4
- package/dist/src/stash-clone.d.ts +22 -0
- package/dist/src/stash-clone.js +83 -0
- package/dist/src/stash-ref.d.ts +27 -3
- package/dist/src/stash-ref.js +63 -24
- package/dist/src/stash-registry.js +12 -12
- package/dist/src/stash-resolve.js +3 -0
- package/dist/src/stash-search.js +168 -164
- package/dist/src/stash-show.d.ts +1 -1
- package/dist/src/stash-show.js +28 -96
- package/dist/src/stash-source.d.ts +24 -0
- package/dist/src/stash-source.js +81 -0
- package/dist/src/stash-types.d.ts +14 -4
- package/dist/src/stash.d.ts +6 -0
- package/dist/src/stash.js +3 -0
- package/dist/src/tool-runner.d.ts +1 -1
- package/dist/src/tool-runner.js +18 -5
- package/package.json +7 -2
- package/src/asset-spec.ts +20 -4
- package/src/asset-type-handler.ts +77 -0
- package/src/cli.ts +213 -82
- package/src/common.ts +23 -5
- package/src/config-cli.ts +499 -0
- package/src/config.ts +160 -38
- package/src/db.ts +411 -0
- package/src/embedder.ts +22 -11
- package/src/github.ts +21 -0
- package/src/handlers/agent-handler.ts +32 -0
- package/src/handlers/command-handler.ts +29 -0
- package/src/handlers/index.ts +25 -0
- package/src/handlers/knowledge-handler.ts +62 -0
- package/src/handlers/markdown-helpers.ts +19 -0
- package/src/handlers/script-handler.ts +92 -0
- package/src/handlers/skill-handler.ts +37 -0
- package/src/handlers/tool-handler.ts +71 -0
- package/src/indexer.ts +208 -187
- package/src/init.ts +17 -9
- package/src/llm.ts +4 -3
- package/src/metadata.ts +5 -65
- package/src/origin-resolve.ts +67 -0
- package/src/registry-install.ts +158 -42
- package/src/registry-resolve.ts +92 -23
- package/src/registry-search.ts +288 -98
- package/src/registry-types.ts +10 -2
- package/src/stash-add.ts +14 -17
- package/src/stash-clone.ts +127 -0
- package/src/stash-ref.ts +84 -26
- package/src/stash-registry.ts +12 -12
- package/src/stash-resolve.ts +3 -0
- package/src/stash-search.ts +202 -184
- package/src/stash-show.ts +33 -90
- package/src/stash-source.ts +103 -0
- package/src/stash-types.ts +14 -4
- package/src/stash.ts +8 -0
- package/src/tool-runner.ts +18 -5
- package/dist/src/similarity.d.ts +0 -34
- package/dist/src/similarity.js +0 -211
- package/src/similarity.ts +0 -271
package/src/embedder.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { EmbeddingConnectionConfig } from "./config"
|
|
2
|
+
import { fetchWithTimeout } from "./common"
|
|
2
3
|
|
|
3
4
|
// ── Types ───────────────────────────────────────────────────────────────────
|
|
4
5
|
|
|
@@ -6,22 +7,27 @@ export type EmbeddingVector = number[]
|
|
|
6
7
|
|
|
7
8
|
// ── Singleton local embedder ────────────────────────────────────────────────
|
|
8
9
|
|
|
9
|
-
|
|
10
|
+
interface TransformerPipeline {
|
|
11
|
+
(text: string, options: { pooling: string; normalize: boolean }): Promise<{ data: Float32Array }>
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
let localEmbedder: TransformerPipeline | undefined
|
|
10
15
|
|
|
11
|
-
async function getLocalEmbedder(): Promise<
|
|
16
|
+
async function getLocalEmbedder(): Promise<TransformerPipeline> {
|
|
12
17
|
if (!localEmbedder) {
|
|
13
|
-
let pipeline:
|
|
18
|
+
let pipeline: unknown
|
|
14
19
|
try {
|
|
15
20
|
const mod = await import("@xenova/transformers")
|
|
16
|
-
pipeline = mod.pipeline
|
|
21
|
+
pipeline = mod.pipeline as unknown
|
|
17
22
|
} catch {
|
|
18
23
|
throw new Error(
|
|
19
24
|
"Semantic search requires @xenova/transformers. Install it with: npm install @xenova/transformers",
|
|
20
25
|
)
|
|
21
26
|
}
|
|
22
|
-
|
|
27
|
+
const pipelineFn = pipeline as (task: string, model: string) => Promise<TransformerPipeline>
|
|
28
|
+
localEmbedder = await pipelineFn("feature-extraction", "Xenova/all-MiniLM-L6-v2")
|
|
23
29
|
}
|
|
24
|
-
return localEmbedder
|
|
30
|
+
return localEmbedder!
|
|
25
31
|
}
|
|
26
32
|
|
|
27
33
|
async function embedLocal(text: string): Promise<EmbeddingVector> {
|
|
@@ -41,13 +47,18 @@ async function embedRemote(
|
|
|
41
47
|
headers["Authorization"] = `Bearer ${config.apiKey}`
|
|
42
48
|
}
|
|
43
49
|
|
|
44
|
-
const
|
|
50
|
+
const body: { input: string; model: string; dimensions?: number } = {
|
|
51
|
+
input: text,
|
|
52
|
+
model: config.model,
|
|
53
|
+
}
|
|
54
|
+
if (config.dimension) {
|
|
55
|
+
body.dimensions = config.dimension
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const response = await fetchWithTimeout(config.endpoint, {
|
|
45
59
|
method: "POST",
|
|
46
60
|
headers,
|
|
47
|
-
body: JSON.stringify(
|
|
48
|
-
input: text,
|
|
49
|
-
model: config.model,
|
|
50
|
-
}),
|
|
61
|
+
body: JSON.stringify(body),
|
|
51
62
|
})
|
|
52
63
|
|
|
53
64
|
if (!response.ok) {
|
package/src/github.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export const GITHUB_API_BASE = "https://api.github.com"
|
|
2
|
+
|
|
3
|
+
export function githubHeaders(): HeadersInit {
|
|
4
|
+
const token = process.env.GITHUB_TOKEN?.trim()
|
|
5
|
+
const headers: Record<string, string> = {
|
|
6
|
+
Accept: "application/vnd.github+json",
|
|
7
|
+
"User-Agent": "agentikit-registry",
|
|
8
|
+
}
|
|
9
|
+
if (token) headers.Authorization = `Bearer ${token}`
|
|
10
|
+
return headers
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function asRecord(value: unknown): Record<string, unknown> {
|
|
14
|
+
return typeof value === "object" && value !== null && !Array.isArray(value)
|
|
15
|
+
? value as Record<string, unknown>
|
|
16
|
+
: {}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function asString(value: unknown): string | undefined {
|
|
20
|
+
return typeof value === "string" && value ? value : undefined
|
|
21
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { parseFrontmatter, toStringOrUndefined } from "../frontmatter"
|
|
2
|
+
import { isMarkdownFile, markdownCanonicalName, markdownAssetPath } from "./markdown-helpers"
|
|
3
|
+
import type { AssetTypeHandler, ShowInput } from "../asset-type-handler"
|
|
4
|
+
import type { ShowResponse } from "../stash-types"
|
|
5
|
+
|
|
6
|
+
export const agentHandler: AssetTypeHandler = {
|
|
7
|
+
typeName: "agent",
|
|
8
|
+
stashDir: "agents",
|
|
9
|
+
|
|
10
|
+
isRelevantFile: isMarkdownFile,
|
|
11
|
+
toCanonicalName: markdownCanonicalName,
|
|
12
|
+
toAssetPath: markdownAssetPath,
|
|
13
|
+
|
|
14
|
+
buildShowResponse(input: ShowInput): ShowResponse {
|
|
15
|
+
const parsedMd = parseFrontmatter(input.content)
|
|
16
|
+
return {
|
|
17
|
+
type: "agent",
|
|
18
|
+
name: input.name,
|
|
19
|
+
path: input.path,
|
|
20
|
+
description: toStringOrUndefined(parsedMd.data.description),
|
|
21
|
+
prompt: "Dispatching prompt must include the agent's full prompt content verbatim; summaries are non-compliant. \n\n"
|
|
22
|
+
+ parsedMd.content,
|
|
23
|
+
toolPolicy: parsedMd.data.tools,
|
|
24
|
+
modelHint: parsedMd.data.model,
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
|
|
28
|
+
defaultUsageGuide: [
|
|
29
|
+
"Read the .md file and dispatch an agent using the content of the file. Use modelHint/toolPolicy when present to run the agent with compatible settings.",
|
|
30
|
+
"Use with `akm show <openRef>` to get the full prompt payload.",
|
|
31
|
+
],
|
|
32
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { parseFrontmatter, toStringOrUndefined } from "../frontmatter"
|
|
2
|
+
import { isMarkdownFile, markdownCanonicalName, markdownAssetPath } from "./markdown-helpers"
|
|
3
|
+
import type { AssetTypeHandler, ShowInput } from "../asset-type-handler"
|
|
4
|
+
import type { ShowResponse } from "../stash-types"
|
|
5
|
+
|
|
6
|
+
export const commandHandler: AssetTypeHandler = {
|
|
7
|
+
typeName: "command",
|
|
8
|
+
stashDir: "commands",
|
|
9
|
+
|
|
10
|
+
isRelevantFile: isMarkdownFile,
|
|
11
|
+
toCanonicalName: markdownCanonicalName,
|
|
12
|
+
toAssetPath: markdownAssetPath,
|
|
13
|
+
|
|
14
|
+
buildShowResponse(input: ShowInput): ShowResponse {
|
|
15
|
+
const parsedMd = parseFrontmatter(input.content)
|
|
16
|
+
return {
|
|
17
|
+
type: "command",
|
|
18
|
+
name: input.name,
|
|
19
|
+
path: input.path,
|
|
20
|
+
description: toStringOrUndefined(parsedMd.data.description),
|
|
21
|
+
template: parsedMd.content,
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
|
|
25
|
+
defaultUsageGuide: [
|
|
26
|
+
"Read the .md file, fill placeholders, and run it in the current repo context.",
|
|
27
|
+
"Use `akm show <openRef>` to retrieve the command template body.",
|
|
28
|
+
],
|
|
29
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { registerAssetType } from "../asset-type-handler"
|
|
2
|
+
import { toolHandler } from "./tool-handler"
|
|
3
|
+
import { skillHandler } from "./skill-handler"
|
|
4
|
+
import { commandHandler } from "./command-handler"
|
|
5
|
+
import { agentHandler } from "./agent-handler"
|
|
6
|
+
import { knowledgeHandler } from "./knowledge-handler"
|
|
7
|
+
import { scriptHandler } from "./script-handler"
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Register all built-in asset type handlers.
|
|
11
|
+
* This must be called (imported) before any handler lookups.
|
|
12
|
+
*/
|
|
13
|
+
registerAssetType(toolHandler)
|
|
14
|
+
registerAssetType(skillHandler)
|
|
15
|
+
registerAssetType(commandHandler)
|
|
16
|
+
registerAssetType(agentHandler)
|
|
17
|
+
registerAssetType(knowledgeHandler)
|
|
18
|
+
registerAssetType(scriptHandler)
|
|
19
|
+
|
|
20
|
+
export { toolHandler } from "./tool-handler"
|
|
21
|
+
export { skillHandler } from "./skill-handler"
|
|
22
|
+
export { commandHandler } from "./command-handler"
|
|
23
|
+
export { agentHandler } from "./agent-handler"
|
|
24
|
+
export { knowledgeHandler } from "./knowledge-handler"
|
|
25
|
+
export { scriptHandler } from "./script-handler"
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import fs from "node:fs"
|
|
2
|
+
import { parseMarkdownToc, extractSection, extractLineRange, extractFrontmatterOnly, formatToc } from "../markdown"
|
|
3
|
+
import { isMarkdownFile, markdownCanonicalName, markdownAssetPath } from "./markdown-helpers"
|
|
4
|
+
import type { AssetTypeHandler, ShowInput } from "../asset-type-handler"
|
|
5
|
+
import type { ShowResponse } from "../stash-types"
|
|
6
|
+
import type { StashEntry } from "../metadata"
|
|
7
|
+
|
|
8
|
+
export const knowledgeHandler: AssetTypeHandler = {
|
|
9
|
+
typeName: "knowledge",
|
|
10
|
+
stashDir: "knowledge",
|
|
11
|
+
|
|
12
|
+
isRelevantFile: isMarkdownFile,
|
|
13
|
+
toCanonicalName: markdownCanonicalName,
|
|
14
|
+
toAssetPath: markdownAssetPath,
|
|
15
|
+
|
|
16
|
+
buildShowResponse(input: ShowInput): ShowResponse {
|
|
17
|
+
const v = input.view ?? { mode: "full" }
|
|
18
|
+
switch (v.mode) {
|
|
19
|
+
case "toc": {
|
|
20
|
+
const toc = parseMarkdownToc(input.content)
|
|
21
|
+
return { type: "knowledge", name: input.name, path: input.path, content: formatToc(toc) }
|
|
22
|
+
}
|
|
23
|
+
case "frontmatter": {
|
|
24
|
+
const fm = extractFrontmatterOnly(input.content)
|
|
25
|
+
return { type: "knowledge", name: input.name, path: input.path, content: fm ?? "(no frontmatter)" }
|
|
26
|
+
}
|
|
27
|
+
case "section": {
|
|
28
|
+
const section = extractSection(input.content, v.heading)
|
|
29
|
+
if (!section) {
|
|
30
|
+
return {
|
|
31
|
+
type: "knowledge",
|
|
32
|
+
name: input.name,
|
|
33
|
+
path: input.path,
|
|
34
|
+
content: `Section "${v.heading}" not found in ${input.name}. Try --view toc to discover available headings.`,
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return { type: "knowledge", name: input.name, path: input.path, content: section.content }
|
|
38
|
+
}
|
|
39
|
+
case "lines": {
|
|
40
|
+
return { type: "knowledge", name: input.name, path: input.path, content: extractLineRange(input.content, v.start, v.end) }
|
|
41
|
+
}
|
|
42
|
+
default: {
|
|
43
|
+
return { type: "knowledge", name: input.name, path: input.path, content: input.content }
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
|
|
48
|
+
defaultUsageGuide: [
|
|
49
|
+
"Use `akm show <openRef>` to read the document; start with `--view toc` for large files.",
|
|
50
|
+
"Use `--view section` or `--view lines` to load only the part you need.",
|
|
51
|
+
],
|
|
52
|
+
|
|
53
|
+
extractTypeMetadata(entry: StashEntry, file: string): void {
|
|
54
|
+
try {
|
|
55
|
+
const mdContent = fs.readFileSync(file, "utf8")
|
|
56
|
+
const toc = parseMarkdownToc(mdContent)
|
|
57
|
+
if (toc.headings.length > 0) entry.toc = toc.headings
|
|
58
|
+
} catch {
|
|
59
|
+
// Non-fatal: skip TOC if file can't be read
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import path from "node:path"
|
|
2
|
+
import { toPosix } from "../common"
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Shared file-system helpers for markdown-based asset types
|
|
6
|
+
* (command, agent, knowledge).
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export function isMarkdownFile(fileName: string): boolean {
|
|
10
|
+
return path.extname(fileName).toLowerCase() === ".md"
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function markdownCanonicalName(typeRoot: string, filePath: string): string | undefined {
|
|
14
|
+
return toPosix(path.relative(typeRoot, filePath))
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function markdownAssetPath(typeRoot: string, name: string): string {
|
|
18
|
+
return path.join(typeRoot, name)
|
|
19
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import path from "node:path"
|
|
2
|
+
import { SCRIPT_EXTENSIONS, SCRIPT_EXTENSIONS_BROAD } from "../asset-spec"
|
|
3
|
+
import { hasErrnoCode, toPosix } from "../common"
|
|
4
|
+
import { buildToolInfo } from "../tool-runner"
|
|
5
|
+
import { extractDescriptionFromComments } from "../metadata"
|
|
6
|
+
import type { AssetTypeHandler, ShowInput } from "../asset-type-handler"
|
|
7
|
+
import type { ShowResponse, LocalSearchHit } from "../stash-types"
|
|
8
|
+
import type { StashEntry } from "../metadata"
|
|
9
|
+
|
|
10
|
+
/** Extensions that buildToolInfo can handle (tool-runner supported) */
|
|
11
|
+
const RUNNABLE_EXTENSIONS = SCRIPT_EXTENSIONS
|
|
12
|
+
|
|
13
|
+
export const scriptHandler: AssetTypeHandler = {
|
|
14
|
+
typeName: "script",
|
|
15
|
+
stashDir: "scripts",
|
|
16
|
+
|
|
17
|
+
isRelevantFile(fileName: string): boolean {
|
|
18
|
+
return SCRIPT_EXTENSIONS_BROAD.has(path.extname(fileName).toLowerCase())
|
|
19
|
+
},
|
|
20
|
+
|
|
21
|
+
toCanonicalName(typeRoot: string, filePath: string): string | undefined {
|
|
22
|
+
return toPosix(path.relative(typeRoot, filePath))
|
|
23
|
+
},
|
|
24
|
+
|
|
25
|
+
toAssetPath(typeRoot: string, name: string): string {
|
|
26
|
+
return path.join(typeRoot, name)
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
buildShowResponse(input: ShowInput): ShowResponse {
|
|
30
|
+
const ext = path.extname(input.path).toLowerCase()
|
|
31
|
+
|
|
32
|
+
// For extensions supported by tool-runner, show runCmd
|
|
33
|
+
if (RUNNABLE_EXTENSIONS.has(ext)) {
|
|
34
|
+
const stashDirs = input.stashDirs ?? []
|
|
35
|
+
const assetStashDir = stashDirs.find((d) =>
|
|
36
|
+
path.resolve(input.path).startsWith(path.resolve(d) + path.sep),
|
|
37
|
+
) ?? stashDirs[0]
|
|
38
|
+
|
|
39
|
+
if (assetStashDir) {
|
|
40
|
+
try {
|
|
41
|
+
const toolInfo = buildToolInfo(assetStashDir, input.path)
|
|
42
|
+
return {
|
|
43
|
+
type: "script",
|
|
44
|
+
name: input.name,
|
|
45
|
+
path: input.path,
|
|
46
|
+
runCmd: toolInfo.runCmd,
|
|
47
|
+
kind: toolInfo.kind,
|
|
48
|
+
}
|
|
49
|
+
} catch {
|
|
50
|
+
// Fall through to content display
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// For other extensions or when buildToolInfo fails, show file content
|
|
56
|
+
return {
|
|
57
|
+
type: "script",
|
|
58
|
+
name: input.name,
|
|
59
|
+
path: input.path,
|
|
60
|
+
content: input.content,
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
|
|
64
|
+
enrichSearchHit(hit: LocalSearchHit, stashDir: string): void {
|
|
65
|
+
const ext = path.extname(hit.path).toLowerCase()
|
|
66
|
+
if (!RUNNABLE_EXTENSIONS.has(ext)) return
|
|
67
|
+
|
|
68
|
+
try {
|
|
69
|
+
const toolInfo = buildToolInfo(stashDir, hit.path)
|
|
70
|
+
hit.runCmd = toolInfo.runCmd
|
|
71
|
+
hit.kind = toolInfo.kind
|
|
72
|
+
} catch (error: unknown) {
|
|
73
|
+
if (!hasErrnoCode(error, "ENOENT")) throw error
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
|
|
77
|
+
defaultUsageGuide: [
|
|
78
|
+
"Use the hit's runCmd for execution when available, or run the script directly with the appropriate interpreter.",
|
|
79
|
+
"Use `akm show <openRef>` to inspect the script before running it.",
|
|
80
|
+
],
|
|
81
|
+
|
|
82
|
+
extractTypeMetadata(entry: StashEntry, file: string, ext: string): void {
|
|
83
|
+
if (ext !== ".md") {
|
|
84
|
+
const commentDesc = extractDescriptionFromComments(file)
|
|
85
|
+
if (commentDesc && !entry.description) {
|
|
86
|
+
entry.description = commentDesc
|
|
87
|
+
entry.source = "comments"
|
|
88
|
+
entry.confidence = 0.7
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import path from "node:path"
|
|
2
|
+
import { toPosix } from "../common"
|
|
3
|
+
import type { AssetTypeHandler, ShowInput } from "../asset-type-handler"
|
|
4
|
+
import type { ShowResponse } from "../stash-types"
|
|
5
|
+
|
|
6
|
+
export const skillHandler: AssetTypeHandler = {
|
|
7
|
+
typeName: "skill",
|
|
8
|
+
stashDir: "skills",
|
|
9
|
+
|
|
10
|
+
isRelevantFile(fileName: string): boolean {
|
|
11
|
+
return fileName === "SKILL.md"
|
|
12
|
+
},
|
|
13
|
+
|
|
14
|
+
toCanonicalName(typeRoot: string, filePath: string): string | undefined {
|
|
15
|
+
const relDir = toPosix(path.dirname(path.relative(typeRoot, filePath)))
|
|
16
|
+
if (!relDir || relDir === ".") return undefined
|
|
17
|
+
return relDir
|
|
18
|
+
},
|
|
19
|
+
|
|
20
|
+
toAssetPath(typeRoot: string, name: string): string {
|
|
21
|
+
return path.join(typeRoot, name, "SKILL.md")
|
|
22
|
+
},
|
|
23
|
+
|
|
24
|
+
buildShowResponse(input: ShowInput): ShowResponse {
|
|
25
|
+
return {
|
|
26
|
+
type: "skill",
|
|
27
|
+
name: input.name,
|
|
28
|
+
path: input.path,
|
|
29
|
+
content: input.content,
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
defaultUsageGuide: [
|
|
34
|
+
"Read and apply the skill instructions as written, then adapt examples to your current repo state and task.",
|
|
35
|
+
"Use `akm show <openRef>` to read the full SKILL.md for required steps and constraints.",
|
|
36
|
+
],
|
|
37
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import path from "node:path"
|
|
2
|
+
import { SCRIPT_EXTENSIONS } from "../asset-spec"
|
|
3
|
+
import { hasErrnoCode, toPosix } from "../common"
|
|
4
|
+
import { buildToolInfo } from "../tool-runner"
|
|
5
|
+
import { extractDescriptionFromComments } from "../metadata"
|
|
6
|
+
import type { AssetTypeHandler, ShowInput } from "../asset-type-handler"
|
|
7
|
+
import type { ShowResponse, LocalSearchHit } from "../stash-types"
|
|
8
|
+
import type { StashEntry } from "../metadata"
|
|
9
|
+
|
|
10
|
+
export const toolHandler: AssetTypeHandler = {
|
|
11
|
+
typeName: "tool",
|
|
12
|
+
stashDir: "tools",
|
|
13
|
+
|
|
14
|
+
isRelevantFile(fileName: string): boolean {
|
|
15
|
+
return SCRIPT_EXTENSIONS.has(path.extname(fileName).toLowerCase())
|
|
16
|
+
},
|
|
17
|
+
|
|
18
|
+
toCanonicalName(typeRoot: string, filePath: string): string | undefined {
|
|
19
|
+
return toPosix(path.relative(typeRoot, filePath))
|
|
20
|
+
},
|
|
21
|
+
|
|
22
|
+
toAssetPath(typeRoot: string, name: string): string {
|
|
23
|
+
return path.join(typeRoot, name)
|
|
24
|
+
},
|
|
25
|
+
|
|
26
|
+
buildShowResponse(input: ShowInput): ShowResponse {
|
|
27
|
+
const stashDirs = input.stashDirs ?? []
|
|
28
|
+
const assetStashDir = stashDirs.find((d) =>
|
|
29
|
+
path.resolve(input.path).startsWith(path.resolve(d) + path.sep),
|
|
30
|
+
) ?? stashDirs[0]
|
|
31
|
+
|
|
32
|
+
if (!assetStashDir) {
|
|
33
|
+
return { type: "tool", name: input.name, path: input.path, content: input.content }
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const toolInfo = buildToolInfo(assetStashDir, input.path)
|
|
37
|
+
return {
|
|
38
|
+
type: "tool",
|
|
39
|
+
name: input.name,
|
|
40
|
+
path: input.path,
|
|
41
|
+
runCmd: toolInfo.runCmd,
|
|
42
|
+
kind: toolInfo.kind,
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
|
|
46
|
+
enrichSearchHit(hit: LocalSearchHit, stashDir: string): void {
|
|
47
|
+
try {
|
|
48
|
+
const toolInfo = buildToolInfo(stashDir, hit.path)
|
|
49
|
+
hit.runCmd = toolInfo.runCmd
|
|
50
|
+
hit.kind = toolInfo.kind
|
|
51
|
+
} catch (error: unknown) {
|
|
52
|
+
if (!hasErrnoCode(error, "ENOENT")) throw error
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
|
|
56
|
+
defaultUsageGuide: [
|
|
57
|
+
"Use the hit's runCmd for execution so runtime and working directory stay correct.",
|
|
58
|
+
"Use `akm show <openRef>` to inspect the tool before running it.",
|
|
59
|
+
],
|
|
60
|
+
|
|
61
|
+
extractTypeMetadata(entry: StashEntry, file: string, ext: string): void {
|
|
62
|
+
if (SCRIPT_EXTENSIONS.has(ext) && ext !== ".md") {
|
|
63
|
+
const commentDesc = extractDescriptionFromComments(file)
|
|
64
|
+
if (commentDesc && !entry.description) {
|
|
65
|
+
entry.description = commentDesc
|
|
66
|
+
entry.source = "comments"
|
|
67
|
+
entry.confidence = 0.7
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
}
|