agentikit 0.0.8 → 0.0.9
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 +110 -7
- package/dist/index.d.ts +7 -3
- package/dist/index.js +4 -1
- package/dist/src/cli.js +156 -47
- package/dist/src/config.d.ts +6 -0
- package/dist/src/config.js +50 -0
- package/dist/src/metadata.d.ts +1 -0
- package/dist/src/metadata.js +16 -0
- package/dist/src/registry-install.d.ts +11 -0
- package/dist/src/registry-install.js +208 -0
- package/dist/src/registry-resolve.d.ts +3 -0
- package/dist/src/registry-resolve.js +231 -0
- package/dist/src/registry-search.d.ts +5 -0
- package/dist/src/registry-search.js +129 -0
- package/dist/src/registry-types.d.ts +55 -0
- package/dist/src/registry-types.js +1 -0
- package/dist/src/stash-add.d.ts +4 -0
- package/dist/src/stash-add.js +59 -0
- package/dist/src/stash-registry.d.ts +18 -0
- package/dist/src/stash-registry.js +221 -0
- package/dist/src/stash-search.d.ts +3 -1
- package/dist/src/stash-search.js +236 -21
- package/dist/src/stash-show.js +10 -3
- package/dist/src/stash-types.d.ts +165 -1
- package/dist/src/stash.d.ts +3 -1
- package/dist/src/stash.js +2 -0
- package/package.json +1 -1
- package/src/cli.ts +166 -46
- package/src/config.ts +59 -0
- package/src/metadata.ts +16 -0
- package/src/registry-install.ts +245 -0
- package/src/registry-resolve.ts +272 -0
- package/src/registry-search.ts +145 -0
- package/src/registry-types.ts +64 -0
- package/src/stash-add.ts +66 -0
- package/src/stash-registry.ts +259 -0
- package/src/stash-search.ts +275 -23
- package/src/stash-show.ts +10 -2
- package/src/stash-types.ts +176 -1
- package/src/stash.ts +15 -0
package/src/stash-search.ts
CHANGED
|
@@ -7,8 +7,17 @@ import { TfIdfAdapter, type ScoredEntry } from "./similarity"
|
|
|
7
7
|
import { buildToolInfo } from "./tool-runner"
|
|
8
8
|
import { walkStash } from "./walker"
|
|
9
9
|
import { makeOpenRef } from "./stash-ref"
|
|
10
|
-
import type {
|
|
10
|
+
import type {
|
|
11
|
+
AgentikitSearchType,
|
|
12
|
+
LocalSearchHit,
|
|
13
|
+
RegistrySearchResultHit,
|
|
14
|
+
SearchHit,
|
|
15
|
+
SearchResponse,
|
|
16
|
+
SearchSource,
|
|
17
|
+
SearchUsageMode,
|
|
18
|
+
} from "./stash-types"
|
|
11
19
|
import { loadConfig } from "./config"
|
|
20
|
+
import { searchRegistry } from "./registry-search"
|
|
12
21
|
|
|
13
22
|
type IndexedAsset = {
|
|
14
23
|
type: AgentikitAssetType
|
|
@@ -18,18 +27,121 @@ type IndexedAsset = {
|
|
|
18
27
|
|
|
19
28
|
const DEFAULT_LIMIT = 20
|
|
20
29
|
|
|
30
|
+
const DEFAULT_USAGE_GUIDE_BY_TYPE: Record<AgentikitAssetType, string[]> = {
|
|
31
|
+
tool: [
|
|
32
|
+
"Use the hit's runCmd for execution so runtime and working directory stay correct.",
|
|
33
|
+
"Use `akm show <openRef>` to inspect the tool before running it.",
|
|
34
|
+
],
|
|
35
|
+
skill: [
|
|
36
|
+
"Read and apply the skill instructions as written, then adapt examples to your current repo state and task.",
|
|
37
|
+
"Use `akm show <openRef>` to read the full SKILL.md for required steps and constraints.",
|
|
38
|
+
],
|
|
39
|
+
command: [
|
|
40
|
+
"Read the .md file, fill placeholders, and run it in the current repo context.",
|
|
41
|
+
"Use `akm show <openRef>` to retrieve the command template body.",
|
|
42
|
+
],
|
|
43
|
+
agent: [
|
|
44
|
+
"Read the .md file and dispatch and agent using the content of the file. Use modelHint/toolPolicy when present to run the agent with compatible settings.",
|
|
45
|
+
"Use with `akm show <openRef>` to get the full prompt payload.",
|
|
46
|
+
],
|
|
47
|
+
knowledge: [
|
|
48
|
+
"Use `akm show <openRef>` to read the document; start with `--view toc` for large files.",
|
|
49
|
+
"Use `--view section` or `--view lines` to load only the part you need.",
|
|
50
|
+
],
|
|
51
|
+
}
|
|
52
|
+
|
|
21
53
|
export async function agentikitSearch(input: {
|
|
22
54
|
query: string
|
|
23
55
|
type?: AgentikitSearchType
|
|
24
56
|
limit?: number
|
|
57
|
+
usage?: SearchUsageMode
|
|
58
|
+
source?: SearchSource
|
|
25
59
|
}): Promise<SearchResponse> {
|
|
26
60
|
const t0 = Date.now()
|
|
27
|
-
const query = input.query.trim()
|
|
61
|
+
const query = input.query.trim()
|
|
62
|
+
const normalizedQuery = query.toLowerCase()
|
|
28
63
|
const searchType = input.type ?? "any"
|
|
29
64
|
const limit = normalizeLimit(input.limit)
|
|
65
|
+
const usageMode = parseSearchUsageMode(input.usage)
|
|
66
|
+
const source = parseSearchSource(input.source)
|
|
30
67
|
const stashDir = resolveStashDir()
|
|
31
|
-
const
|
|
68
|
+
const localResult = source === "registry"
|
|
69
|
+
? undefined
|
|
70
|
+
: await searchLocal({
|
|
71
|
+
query: normalizedQuery,
|
|
72
|
+
searchType,
|
|
73
|
+
limit,
|
|
74
|
+
usageMode,
|
|
75
|
+
stashDir,
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
const registryResult = source === "local"
|
|
79
|
+
? undefined
|
|
80
|
+
: await searchRegistry(query, { limit })
|
|
81
|
+
|
|
82
|
+
if (source === "local") {
|
|
83
|
+
return {
|
|
84
|
+
stashDir,
|
|
85
|
+
source,
|
|
86
|
+
hits: localResult?.hits ?? [],
|
|
87
|
+
usageGuide: localResult?.usageGuide,
|
|
88
|
+
tip: localResult?.tip,
|
|
89
|
+
timing: { totalMs: Date.now() - t0, rankMs: localResult?.rankMs, embedMs: localResult?.embedMs },
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const registryHits = (registryResult?.hits ?? []).map((hit): RegistrySearchResultHit => {
|
|
94
|
+
const installRef = hit.source === "npm" ? `npm:${hit.ref}` : `github:${hit.ref}`
|
|
95
|
+
return {
|
|
96
|
+
hitSource: "registry",
|
|
97
|
+
type: "registry",
|
|
98
|
+
name: hit.title,
|
|
99
|
+
id: hit.id,
|
|
100
|
+
registrySource: hit.source,
|
|
101
|
+
ref: hit.ref,
|
|
102
|
+
description: hit.description,
|
|
103
|
+
homepage: hit.homepage,
|
|
104
|
+
score: hit.score,
|
|
105
|
+
metadata: hit.metadata,
|
|
106
|
+
installRef,
|
|
107
|
+
installCmd: `akm add ${installRef}`,
|
|
108
|
+
}
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
if (source === "registry") {
|
|
112
|
+
const hits = registryHits.slice(0, limit)
|
|
113
|
+
return {
|
|
114
|
+
stashDir,
|
|
115
|
+
source,
|
|
116
|
+
hits,
|
|
117
|
+
tip: hits.length === 0 ? "No matching registry entries were found." : undefined,
|
|
118
|
+
warnings: registryResult?.warnings.length ? registryResult.warnings : undefined,
|
|
119
|
+
timing: { totalMs: Date.now() - t0 },
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const mergedHits = mergeSearchHits(localResult?.hits ?? [], registryHits, limit)
|
|
32
124
|
|
|
125
|
+
return {
|
|
126
|
+
stashDir,
|
|
127
|
+
source,
|
|
128
|
+
hits: mergedHits,
|
|
129
|
+
usageGuide: localResult?.usageGuide,
|
|
130
|
+
tip: mergedHits.length === 0 ? "No matching stash assets or registry entries were found." : undefined,
|
|
131
|
+
warnings: registryResult?.warnings.length ? registryResult.warnings : undefined,
|
|
132
|
+
timing: { totalMs: Date.now() - t0 },
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
async function searchLocal(input: {
|
|
137
|
+
query: string
|
|
138
|
+
searchType: AgentikitSearchType
|
|
139
|
+
limit: number
|
|
140
|
+
usageMode: SearchUsageMode
|
|
141
|
+
stashDir: string
|
|
142
|
+
}): Promise<{ hits: LocalSearchHit[]; usageGuide?: Partial<Record<AgentikitAssetType, string[]>>; tip?: string; embedMs?: number; rankMs?: number }> {
|
|
143
|
+
const { query, searchType, limit, usageMode, stashDir } = input
|
|
144
|
+
const config = loadConfig(stashDir)
|
|
33
145
|
const allStashDirs = [
|
|
34
146
|
stashDir,
|
|
35
147
|
...config.additionalStashDirs.filter((d) => {
|
|
@@ -37,28 +149,26 @@ export async function agentikitSearch(input: {
|
|
|
37
149
|
}),
|
|
38
150
|
]
|
|
39
151
|
|
|
40
|
-
// Try indexed search (single unified pipeline: embedding + TF-IDF as weighted features)
|
|
41
152
|
const index = loadSearchIndex()
|
|
42
153
|
if (index && index.entries && index.entries.length > 0 && index.stashDir === stashDir) {
|
|
43
|
-
const { hits, embedMs, rankMs } = await searchIndex(index, query, searchType, limit, stashDir, allStashDirs, config)
|
|
154
|
+
const { hits, usageGuide, embedMs, rankMs } = await searchIndex(index, query, searchType, limit, stashDir, allStashDirs, config, usageMode)
|
|
44
155
|
return {
|
|
45
|
-
stashDir,
|
|
46
156
|
hits,
|
|
157
|
+
usageGuide,
|
|
47
158
|
tip: hits.length === 0 ? "No matching stash assets were found. Try running 'akm index' to rebuild." : undefined,
|
|
48
|
-
|
|
159
|
+
embedMs,
|
|
160
|
+
rankMs,
|
|
49
161
|
}
|
|
50
162
|
}
|
|
51
163
|
|
|
52
|
-
// No index: fall back to filesystem walk + substring match across all stash dirs
|
|
53
164
|
const hits = allStashDirs
|
|
54
165
|
.flatMap((dir) => substringSearch(query, searchType, limit, dir))
|
|
55
166
|
.slice(0, limit)
|
|
56
|
-
|
|
167
|
+
const usageGuide = shouldIncludeUsageGuide(usageMode) ? buildUsageGuide(hits.map((hit) => hit.type), searchType) : undefined
|
|
57
168
|
return {
|
|
58
|
-
stashDir,
|
|
59
169
|
hits,
|
|
170
|
+
usageGuide,
|
|
60
171
|
tip: hits.length === 0 ? "No matching stash assets were found. Try running 'akm index' to rebuild." : undefined,
|
|
61
|
-
timing: { totalMs: Date.now() - t0 },
|
|
62
172
|
}
|
|
63
173
|
}
|
|
64
174
|
|
|
@@ -72,20 +182,42 @@ async function searchIndex(
|
|
|
72
182
|
stashDir: string,
|
|
73
183
|
allStashDirs: string[],
|
|
74
184
|
config: import("./config").AgentikitConfig,
|
|
75
|
-
|
|
185
|
+
usageMode: SearchUsageMode,
|
|
186
|
+
): Promise<{ hits: LocalSearchHit[]; usageGuide?: Partial<Record<AgentikitAssetType, string[]>>; embedMs?: number; rankMs?: number }> {
|
|
76
187
|
// Filter candidates by type
|
|
77
188
|
let candidates = index.entries
|
|
78
189
|
if (searchType !== "any") {
|
|
79
190
|
candidates = candidates.filter((ie) => ie.entry.type === searchType)
|
|
80
191
|
}
|
|
81
192
|
|
|
82
|
-
if (candidates.length === 0)
|
|
193
|
+
if (candidates.length === 0) {
|
|
194
|
+
return {
|
|
195
|
+
hits: [],
|
|
196
|
+
usageGuide: shouldIncludeUsageGuide(usageMode) ? buildUsageGuide([], searchType) : undefined,
|
|
197
|
+
}
|
|
198
|
+
}
|
|
83
199
|
|
|
84
200
|
// Empty query: return all entries (no scoring needed)
|
|
85
201
|
if (!query) {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
202
|
+
const selectedCandidates = candidates.slice(0, limit)
|
|
203
|
+
const hits = selectedCandidates.map((ie) =>
|
|
204
|
+
buildIndexedHit({
|
|
205
|
+
entry: ie.entry,
|
|
206
|
+
path: ie.path,
|
|
207
|
+
score: 1,
|
|
208
|
+
query,
|
|
209
|
+
rankingMode: "tfidf",
|
|
210
|
+
defaultStashDir: stashDir,
|
|
211
|
+
allStashDirs,
|
|
212
|
+
includeItemUsage: shouldIncludeItemUsage(usageMode),
|
|
213
|
+
}),
|
|
214
|
+
)
|
|
215
|
+
return {
|
|
216
|
+
hits,
|
|
217
|
+
usageGuide: shouldIncludeUsageGuide(usageMode)
|
|
218
|
+
? buildUsageGuideFromEntries(selectedCandidates.map((candidate) => candidate.entry), searchType)
|
|
219
|
+
: undefined,
|
|
220
|
+
}
|
|
89
221
|
}
|
|
90
222
|
|
|
91
223
|
// Score each candidate using available signals
|
|
@@ -115,7 +247,8 @@ async function searchIndex(
|
|
|
115
247
|
scored.sort((a, b) => b.score - a.score)
|
|
116
248
|
const rankMs = Date.now() - tRank0
|
|
117
249
|
|
|
118
|
-
|
|
250
|
+
const selected = scored.slice(0, limit)
|
|
251
|
+
const hits = selected.map(({ ie, score, rankingMode }) =>
|
|
119
252
|
buildIndexedHit({
|
|
120
253
|
entry: ie.entry,
|
|
121
254
|
path: ie.path,
|
|
@@ -124,8 +257,18 @@ async function searchIndex(
|
|
|
124
257
|
rankingMode,
|
|
125
258
|
defaultStashDir: stashDir,
|
|
126
259
|
allStashDirs,
|
|
260
|
+
includeItemUsage: shouldIncludeItemUsage(usageMode),
|
|
127
261
|
}),
|
|
128
|
-
)
|
|
262
|
+
)
|
|
263
|
+
|
|
264
|
+
return {
|
|
265
|
+
embedMs,
|
|
266
|
+
rankMs,
|
|
267
|
+
hits,
|
|
268
|
+
usageGuide: shouldIncludeUsageGuide(usageMode)
|
|
269
|
+
? buildUsageGuideFromEntries(selected.map((item) => item.ie.entry), searchType)
|
|
270
|
+
: undefined,
|
|
271
|
+
}
|
|
129
272
|
}
|
|
130
273
|
|
|
131
274
|
// ── Embedding scorer ────────────────────────────────────────────────────────
|
|
@@ -189,13 +332,13 @@ function substringSearch(
|
|
|
189
332
|
searchType: AgentikitSearchType,
|
|
190
333
|
limit: number,
|
|
191
334
|
stashDir: string,
|
|
192
|
-
):
|
|
335
|
+
): LocalSearchHit[] {
|
|
193
336
|
const assets = indexAssets(stashDir, searchType)
|
|
194
337
|
return assets
|
|
195
338
|
.filter((asset) => asset.name.toLowerCase().includes(query))
|
|
196
339
|
.sort(compareAssets)
|
|
197
340
|
.slice(0, limit)
|
|
198
|
-
.map((asset)
|
|
341
|
+
.map((asset) => assetToSearchHit(asset, stashDir))
|
|
199
342
|
}
|
|
200
343
|
|
|
201
344
|
// ── Hit building ────────────────────────────────────────────────────────────
|
|
@@ -216,7 +359,8 @@ function buildIndexedHit(input: {
|
|
|
216
359
|
rankingMode: "semantic" | "tfidf"
|
|
217
360
|
defaultStashDir: string
|
|
218
361
|
allStashDirs: string[]
|
|
219
|
-
|
|
362
|
+
includeItemUsage: boolean
|
|
363
|
+
}): LocalSearchHit {
|
|
220
364
|
const entryStashDir = findStashDirForPath(input.path, input.allStashDirs) ?? input.defaultStashDir
|
|
221
365
|
const typeRoot = path.join(entryStashDir, TYPE_DIRS[input.entry.type])
|
|
222
366
|
const openRefName = deriveCanonicalAssetName(input.entry.type, typeRoot, input.path)
|
|
@@ -228,7 +372,8 @@ function buildIndexedHit(input: {
|
|
|
228
372
|
|
|
229
373
|
const whyMatched = buildWhyMatched(input.entry, input.query, input.rankingMode, qualityBoost, confidenceBoost)
|
|
230
374
|
|
|
231
|
-
const hit:
|
|
375
|
+
const hit: LocalSearchHit = {
|
|
376
|
+
hitSource: "local",
|
|
232
377
|
type: input.entry.type,
|
|
233
378
|
name: input.entry.name,
|
|
234
379
|
path: input.path,
|
|
@@ -239,6 +384,10 @@ function buildIndexedHit(input: {
|
|
|
239
384
|
whyMatched,
|
|
240
385
|
}
|
|
241
386
|
|
|
387
|
+
if (input.includeItemUsage && input.entry.usage && input.entry.usage.length > 0) {
|
|
388
|
+
hit.usage = input.entry.usage
|
|
389
|
+
}
|
|
390
|
+
|
|
242
391
|
if (input.entry.type === "tool") {
|
|
243
392
|
try {
|
|
244
393
|
const toolInfo = buildToolInfo(entryStashDir, input.path)
|
|
@@ -288,9 +437,10 @@ function toScoredEntries(entries: IndexedEntry[]): ScoredEntry[] {
|
|
|
288
437
|
}))
|
|
289
438
|
}
|
|
290
439
|
|
|
291
|
-
function assetToSearchHit(asset: IndexedAsset, stashDir: string):
|
|
440
|
+
function assetToSearchHit(asset: IndexedAsset, stashDir: string): LocalSearchHit {
|
|
292
441
|
if (asset.type !== "tool") {
|
|
293
442
|
return {
|
|
443
|
+
hitSource: "local",
|
|
294
444
|
type: asset.type,
|
|
295
445
|
name: asset.name,
|
|
296
446
|
path: asset.path,
|
|
@@ -299,6 +449,7 @@ function assetToSearchHit(asset: IndexedAsset, stashDir: string): SearchHit {
|
|
|
299
449
|
}
|
|
300
450
|
const toolInfo = buildToolInfo(stashDir, asset.path)
|
|
301
451
|
return {
|
|
452
|
+
hitSource: "local",
|
|
302
453
|
type: "tool",
|
|
303
454
|
name: asset.name,
|
|
304
455
|
path: asset.path,
|
|
@@ -315,6 +466,107 @@ function normalizeLimit(limit?: number): number {
|
|
|
315
466
|
return Math.min(Math.floor(limit), 200)
|
|
316
467
|
}
|
|
317
468
|
|
|
469
|
+
function parseSearchUsageMode(mode: SearchUsageMode | undefined): SearchUsageMode {
|
|
470
|
+
if (mode === "none" || mode === "both" || mode === "item" || mode === "guide") {
|
|
471
|
+
return mode
|
|
472
|
+
}
|
|
473
|
+
if (typeof mode === "undefined") return "both"
|
|
474
|
+
throw new Error(`Invalid usage mode: ${String(mode)}. Expected one of: none|both|item|guide`)
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
function parseSearchSource(source: SearchSource | undefined): SearchSource {
|
|
478
|
+
if (source === "local" || source === "registry" || source === "both") return source
|
|
479
|
+
if (typeof source === "undefined") return "local"
|
|
480
|
+
throw new Error(`Invalid search source: ${String(source)}. Expected one of: local|registry|both`)
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
function mergeSearchHits(localHits: LocalSearchHit[], registryHits: RegistrySearchResultHit[], limit: number): SearchHit[] {
|
|
484
|
+
const merged: SearchHit[] = []
|
|
485
|
+
let localIndex = 0
|
|
486
|
+
let registryIndex = 0
|
|
487
|
+
|
|
488
|
+
while (merged.length < limit && (localIndex < localHits.length || registryIndex < registryHits.length)) {
|
|
489
|
+
if (localIndex < localHits.length) {
|
|
490
|
+
merged.push(localHits[localIndex])
|
|
491
|
+
localIndex += 1
|
|
492
|
+
if (merged.length >= limit) break
|
|
493
|
+
}
|
|
494
|
+
if (registryIndex < registryHits.length) {
|
|
495
|
+
merged.push(registryHits[registryIndex])
|
|
496
|
+
registryIndex += 1
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
return merged
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
function shouldIncludeUsageGuide(mode: SearchUsageMode): boolean {
|
|
504
|
+
return mode === "both" || mode === "guide"
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
function shouldIncludeItemUsage(mode: SearchUsageMode): boolean {
|
|
508
|
+
return mode === "both" || mode === "item"
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
function buildUsageGuideFromEntries(
|
|
512
|
+
entries: IndexedEntry["entry"][],
|
|
513
|
+
searchType: AgentikitSearchType,
|
|
514
|
+
): Partial<Record<AgentikitAssetType, string[]>> | undefined {
|
|
515
|
+
const types = entries.map((entry) => entry.type)
|
|
516
|
+
const fallbackGuide = buildUsageGuide(types, searchType)
|
|
517
|
+
const metadataByType = new Map<AgentikitAssetType, string[]>()
|
|
518
|
+
|
|
519
|
+
for (const entry of entries) {
|
|
520
|
+
if (!entry.usage || entry.usage.length === 0) continue
|
|
521
|
+
const current = metadataByType.get(entry.type) ?? []
|
|
522
|
+
for (const item of entry.usage) {
|
|
523
|
+
const trimmed = item.trim()
|
|
524
|
+
if (trimmed && !current.includes(trimmed)) current.push(trimmed)
|
|
525
|
+
}
|
|
526
|
+
if (current.length > 0) metadataByType.set(entry.type, current)
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
if (!fallbackGuide && metadataByType.size === 0) return undefined
|
|
530
|
+
|
|
531
|
+
const result: Partial<Record<AgentikitAssetType, string[]>> = {}
|
|
532
|
+
for (const assetType of resolveGuideTypes(types, searchType)) {
|
|
533
|
+
const lines: string[] = []
|
|
534
|
+
const metadataLines = metadataByType.get(assetType)
|
|
535
|
+
if (metadataLines && metadataLines.length > 0) {
|
|
536
|
+
lines.push(...metadataLines)
|
|
537
|
+
}
|
|
538
|
+
const fallbackLines = fallbackGuide?.[assetType]
|
|
539
|
+
if (fallbackLines && fallbackLines.length > 0) {
|
|
540
|
+
for (const line of fallbackLines) {
|
|
541
|
+
if (!lines.includes(line)) lines.push(line)
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
if (lines.length > 0) result[assetType] = lines
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
return Object.keys(result).length > 0 ? result : undefined
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
function buildUsageGuide(
|
|
551
|
+
hitTypes: AgentikitAssetType[],
|
|
552
|
+
searchType: AgentikitSearchType,
|
|
553
|
+
): Partial<Record<AgentikitAssetType, string[]>> | undefined {
|
|
554
|
+
const result: Partial<Record<AgentikitAssetType, string[]>> = {}
|
|
555
|
+
for (const assetType of resolveGuideTypes(hitTypes, searchType)) {
|
|
556
|
+
result[assetType] = usageGuideByType(assetType)
|
|
557
|
+
}
|
|
558
|
+
return Object.keys(result).length > 0 ? result : undefined
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
function resolveGuideTypes(hitTypes: AgentikitAssetType[], searchType: AgentikitSearchType): AgentikitAssetType[] {
|
|
562
|
+
if (searchType !== "any") return [searchType]
|
|
563
|
+
return Array.from(new Set(hitTypes))
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
function usageGuideByType(type: AgentikitAssetType): string[] {
|
|
567
|
+
return DEFAULT_USAGE_GUIDE_BY_TYPE[type]
|
|
568
|
+
}
|
|
569
|
+
|
|
318
570
|
function fileToAsset(assetType: AgentikitAssetType, root: string, file: string): IndexedAsset | undefined {
|
|
319
571
|
const name = deriveCanonicalAssetName(assetType, root, file)
|
|
320
572
|
if (!name) return undefined
|
package/src/stash-show.ts
CHANGED
|
@@ -60,7 +60,8 @@ export function agentikitShow(input: { ref: string; view?: KnowledgeView }): Sho
|
|
|
60
60
|
name: parsed.name,
|
|
61
61
|
path: assetPath,
|
|
62
62
|
description: toStringOrUndefined(parsedMd.data.description),
|
|
63
|
-
prompt:
|
|
63
|
+
prompt: "Dispatching prompt must include the agent's full prompt content verbatim; summaries are non-compliant. \n\n"
|
|
64
|
+
+ parsedMd.content,
|
|
64
65
|
toolPolicy: parsedMd.data.tools,
|
|
65
66
|
modelHint: parsedMd.data.model,
|
|
66
67
|
}
|
|
@@ -89,7 +90,14 @@ export function agentikitShow(input: { ref: string; view?: KnowledgeView }): Sho
|
|
|
89
90
|
}
|
|
90
91
|
case "section": {
|
|
91
92
|
const section = extractSection(content, v.heading)
|
|
92
|
-
if (!section)
|
|
93
|
+
if (!section) {
|
|
94
|
+
return {
|
|
95
|
+
type: "knowledge",
|
|
96
|
+
name: parsed.name,
|
|
97
|
+
path: assetPath,
|
|
98
|
+
content: `Section "${v.heading}" not found in ${parsed.name}. Try --view toc to discover available headings.`,
|
|
99
|
+
}
|
|
100
|
+
}
|
|
93
101
|
return { type: "knowledge", name: parsed.name, path: assetPath, content: section.content }
|
|
94
102
|
}
|
|
95
103
|
case "lines": {
|
package/src/stash-types.ts
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import type { AgentikitAssetType } from "./common"
|
|
2
|
+
import type { RegistrySource } from "./registry-types"
|
|
2
3
|
import type { ToolKind } from "./tool-runner"
|
|
3
4
|
|
|
4
5
|
export type AgentikitSearchType = AgentikitAssetType | "any"
|
|
6
|
+
export type SearchUsageMode = "none" | "both" | "item" | "guide"
|
|
7
|
+
export type SearchSource = "local" | "registry" | "both"
|
|
5
8
|
|
|
6
|
-
export interface
|
|
9
|
+
export interface LocalSearchHit {
|
|
10
|
+
hitSource: "local"
|
|
7
11
|
type: AgentikitAssetType
|
|
8
12
|
name: string
|
|
9
13
|
path: string
|
|
@@ -14,16 +18,187 @@ export interface SearchHit {
|
|
|
14
18
|
whyMatched?: string[]
|
|
15
19
|
runCmd?: string
|
|
16
20
|
kind?: ToolKind
|
|
21
|
+
usage?: string[]
|
|
17
22
|
}
|
|
18
23
|
|
|
24
|
+
export interface RegistrySearchResultHit {
|
|
25
|
+
hitSource: "registry"
|
|
26
|
+
type: "registry"
|
|
27
|
+
name: string
|
|
28
|
+
path?: string
|
|
29
|
+
openRef?: string
|
|
30
|
+
id: string
|
|
31
|
+
registrySource: RegistrySource
|
|
32
|
+
ref: string
|
|
33
|
+
description?: string
|
|
34
|
+
tags?: string[]
|
|
35
|
+
homepage?: string
|
|
36
|
+
score?: number
|
|
37
|
+
whyMatched?: string[]
|
|
38
|
+
runCmd?: string
|
|
39
|
+
kind?: ToolKind
|
|
40
|
+
usage?: string[]
|
|
41
|
+
metadata?: Record<string, string>
|
|
42
|
+
installRef: string
|
|
43
|
+
installCmd: string
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export type SearchHit = LocalSearchHit | RegistrySearchResultHit
|
|
47
|
+
|
|
19
48
|
export interface SearchResponse {
|
|
20
49
|
stashDir: string
|
|
50
|
+
source: SearchSource
|
|
21
51
|
hits: SearchHit[]
|
|
52
|
+
usageGuide?: Partial<Record<AgentikitAssetType, string[]>>
|
|
22
53
|
tip?: string
|
|
54
|
+
warnings?: string[]
|
|
23
55
|
/** Timing counters in milliseconds */
|
|
24
56
|
timing?: { totalMs: number; rankMs?: number; embedMs?: number }
|
|
25
57
|
}
|
|
26
58
|
|
|
59
|
+
export interface AddResponse {
|
|
60
|
+
stashDir: string
|
|
61
|
+
ref: string
|
|
62
|
+
installed: {
|
|
63
|
+
id: string
|
|
64
|
+
source: RegistrySource
|
|
65
|
+
ref: string
|
|
66
|
+
artifactUrl: string
|
|
67
|
+
resolvedVersion?: string
|
|
68
|
+
resolvedRevision?: string
|
|
69
|
+
stashRoot: string
|
|
70
|
+
cacheDir: string
|
|
71
|
+
extractedDir: string
|
|
72
|
+
installedAt: string
|
|
73
|
+
}
|
|
74
|
+
config: {
|
|
75
|
+
additionalStashDirs: string[]
|
|
76
|
+
installedRegistryCount: number
|
|
77
|
+
}
|
|
78
|
+
index: {
|
|
79
|
+
mode: "full" | "incremental"
|
|
80
|
+
totalEntries: number
|
|
81
|
+
directoriesScanned: number
|
|
82
|
+
directoriesSkipped: number
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export interface RegistryInstallStatus {
|
|
87
|
+
id: string
|
|
88
|
+
source: RegistrySource
|
|
89
|
+
ref: string
|
|
90
|
+
artifactUrl: string
|
|
91
|
+
resolvedVersion?: string
|
|
92
|
+
resolvedRevision?: string
|
|
93
|
+
stashRoot: string
|
|
94
|
+
cacheDir: string
|
|
95
|
+
extractedDir: string
|
|
96
|
+
installedAt: string
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export interface RegistryListEntry {
|
|
100
|
+
id: string
|
|
101
|
+
source: RegistrySource
|
|
102
|
+
ref: string
|
|
103
|
+
artifactUrl: string
|
|
104
|
+
resolvedVersion?: string
|
|
105
|
+
resolvedRevision?: string
|
|
106
|
+
stashRoot: string
|
|
107
|
+
cacheDir: string
|
|
108
|
+
installedAt: string
|
|
109
|
+
status: {
|
|
110
|
+
cacheDirExists: boolean
|
|
111
|
+
stashRootExists: boolean
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export interface ListResponse {
|
|
116
|
+
stashDir: string
|
|
117
|
+
installed: RegistryListEntry[]
|
|
118
|
+
totalInstalled: number
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export interface RemoveResponse {
|
|
122
|
+
stashDir: string
|
|
123
|
+
target: string
|
|
124
|
+
removed: {
|
|
125
|
+
id: string
|
|
126
|
+
source: RegistrySource
|
|
127
|
+
ref: string
|
|
128
|
+
cacheDir: string
|
|
129
|
+
stashRoot: string
|
|
130
|
+
}
|
|
131
|
+
config: {
|
|
132
|
+
additionalStashDirs: string[]
|
|
133
|
+
installedRegistryCount: number
|
|
134
|
+
}
|
|
135
|
+
index: {
|
|
136
|
+
mode: "full" | "incremental"
|
|
137
|
+
totalEntries: number
|
|
138
|
+
directoriesScanned: number
|
|
139
|
+
directoriesSkipped: number
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export interface ReinstallResultItem {
|
|
144
|
+
id: string
|
|
145
|
+
source: RegistrySource
|
|
146
|
+
ref: string
|
|
147
|
+
previousCacheDir: string
|
|
148
|
+
installed: RegistryInstallStatus
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export interface ReinstallResponse {
|
|
152
|
+
stashDir: string
|
|
153
|
+
target?: string
|
|
154
|
+
all: boolean
|
|
155
|
+
processed: ReinstallResultItem[]
|
|
156
|
+
config: {
|
|
157
|
+
additionalStashDirs: string[]
|
|
158
|
+
installedRegistryCount: number
|
|
159
|
+
}
|
|
160
|
+
index: {
|
|
161
|
+
mode: "full" | "incremental"
|
|
162
|
+
totalEntries: number
|
|
163
|
+
directoriesScanned: number
|
|
164
|
+
directoriesSkipped: number
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
export interface UpdateResultItem {
|
|
169
|
+
id: string
|
|
170
|
+
source: RegistrySource
|
|
171
|
+
ref: string
|
|
172
|
+
previous: {
|
|
173
|
+
resolvedVersion?: string
|
|
174
|
+
resolvedRevision?: string
|
|
175
|
+
cacheDir: string
|
|
176
|
+
}
|
|
177
|
+
installed: RegistryInstallStatus
|
|
178
|
+
changed: {
|
|
179
|
+
version: boolean
|
|
180
|
+
revision: boolean
|
|
181
|
+
any: boolean
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
export interface UpdateResponse {
|
|
186
|
+
stashDir: string
|
|
187
|
+
target?: string
|
|
188
|
+
all: boolean
|
|
189
|
+
processed: UpdateResultItem[]
|
|
190
|
+
config: {
|
|
191
|
+
additionalStashDirs: string[]
|
|
192
|
+
installedRegistryCount: number
|
|
193
|
+
}
|
|
194
|
+
index: {
|
|
195
|
+
mode: "full" | "incremental"
|
|
196
|
+
totalEntries: number
|
|
197
|
+
directoriesScanned: number
|
|
198
|
+
directoriesSkipped: number
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
27
202
|
export interface ShowResponse {
|
|
28
203
|
type: AgentikitAssetType
|
|
29
204
|
name: string
|
package/src/stash.ts
CHANGED
|
@@ -6,11 +6,26 @@ export type { ToolKind } from "./tool-runner"
|
|
|
6
6
|
|
|
7
7
|
export { agentikitSearch } from "./stash-search"
|
|
8
8
|
export { agentikitShow } from "./stash-show"
|
|
9
|
+
export { agentikitAdd } from "./stash-add"
|
|
10
|
+
export { agentikitList, agentikitRemove, agentikitReinstall, agentikitUpdate } from "./stash-registry"
|
|
9
11
|
|
|
10
12
|
export type {
|
|
13
|
+
AddResponse,
|
|
11
14
|
AgentikitSearchType,
|
|
15
|
+
LocalSearchHit,
|
|
16
|
+
RegistrySearchResultHit,
|
|
17
|
+
SearchSource,
|
|
18
|
+
SearchUsageMode,
|
|
12
19
|
SearchHit,
|
|
13
20
|
SearchResponse,
|
|
14
21
|
ShowResponse,
|
|
15
22
|
KnowledgeView,
|
|
23
|
+
ListResponse,
|
|
24
|
+
RemoveResponse,
|
|
25
|
+
ReinstallResponse,
|
|
26
|
+
UpdateResponse,
|
|
27
|
+
RegistryListEntry,
|
|
28
|
+
RegistryInstallStatus,
|
|
29
|
+
ReinstallResultItem,
|
|
30
|
+
UpdateResultItem,
|
|
16
31
|
} from "./stash-types"
|