agentikit 0.0.13 → 0.0.14
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/LICENSE +385 -0
- package/README.md +180 -110
- package/dist/cli.js +671 -0
- package/dist/common.js +192 -0
- package/dist/{src/config-cli.js → config-cli.js} +14 -6
- package/dist/{src/config.js → config.js} +92 -24
- package/dist/{src/db.js → db.js} +109 -35
- package/dist/{src/embedder.js → embedder.js} +57 -2
- package/dist/file-context.js +158 -0
- package/dist/{src/handlers → handlers}/command-handler.js +2 -0
- package/dist/{src/handlers → handlers}/index.js +0 -6
- package/dist/{src/indexer.js → indexer.js} +34 -10
- package/dist/init.js +43 -0
- package/dist/lockfile.js +55 -0
- package/dist/matchers.js +157 -0
- package/dist/{src/metadata.js → metadata.js} +12 -1
- package/dist/{src/origin-resolve.js → origin-resolve.js} +10 -9
- package/dist/paths.js +82 -0
- package/dist/{src/registry-install.js → registry-install.js} +145 -17
- package/dist/{src/registry-resolve.js → registry-resolve.js} +178 -18
- package/dist/{src/registry-search.js → registry-search.js} +8 -16
- package/dist/renderers.js +276 -0
- package/dist/{src/ripgrep-install.js → ripgrep-install.js} +5 -5
- package/dist/{src/ripgrep-resolve.js → ripgrep-resolve.js} +21 -11
- package/dist/self-update.js +220 -0
- package/dist/{src/stash-add.js → stash-add.js} +11 -2
- package/dist/stash-clone.js +115 -0
- package/dist/{src/stash-registry.js → stash-registry.js} +15 -41
- package/dist/{src/stash-search.js → stash-search.js} +67 -55
- package/dist/{src/stash-show.js → stash-show.js} +30 -3
- package/dist/{src/stash-source.js → stash-source.js} +56 -9
- package/dist/submit.js +552 -0
- package/dist/{src/walker.js → walker.js} +38 -0
- package/package.json +7 -16
- package/dist/index.d.ts +0 -28
- package/dist/index.js +0 -15
- package/dist/src/asset-spec.d.ts +0 -16
- package/dist/src/asset-type-handler.d.ts +0 -27
- package/dist/src/cli.d.ts +0 -2
- package/dist/src/cli.js +0 -399
- package/dist/src/common.d.ts +0 -13
- package/dist/src/common.js +0 -60
- package/dist/src/config-cli.d.ts +0 -9
- package/dist/src/config.d.ts +0 -50
- package/dist/src/db.d.ts +0 -46
- package/dist/src/embedder.d.ts +0 -10
- package/dist/src/frontmatter.d.ts +0 -30
- package/dist/src/github.d.ts +0 -4
- package/dist/src/handlers/agent-handler.d.ts +0 -2
- package/dist/src/handlers/command-handler.d.ts +0 -2
- package/dist/src/handlers/index.d.ts +0 -6
- package/dist/src/handlers/knowledge-handler.d.ts +0 -2
- package/dist/src/handlers/markdown-helpers.d.ts +0 -7
- package/dist/src/handlers/script-handler.d.ts +0 -2
- package/dist/src/handlers/skill-handler.d.ts +0 -2
- package/dist/src/handlers/tool-handler.d.ts +0 -2
- package/dist/src/indexer.d.ts +0 -22
- package/dist/src/init.d.ts +0 -19
- package/dist/src/init.js +0 -99
- package/dist/src/llm.d.ts +0 -15
- package/dist/src/markdown.d.ts +0 -18
- package/dist/src/metadata.d.ts +0 -41
- package/dist/src/origin-resolve.d.ts +0 -19
- package/dist/src/registry-install.d.ts +0 -11
- package/dist/src/registry-resolve.d.ts +0 -3
- package/dist/src/registry-search.d.ts +0 -27
- package/dist/src/registry-types.d.ts +0 -62
- package/dist/src/ripgrep-install.d.ts +0 -12
- package/dist/src/ripgrep-resolve.d.ts +0 -13
- package/dist/src/ripgrep.d.ts +0 -3
- package/dist/src/stash-add.d.ts +0 -4
- package/dist/src/stash-clone.d.ts +0 -22
- package/dist/src/stash-clone.js +0 -83
- package/dist/src/stash-ref.d.ts +0 -31
- package/dist/src/stash-registry.d.ts +0 -18
- package/dist/src/stash-resolve.d.ts +0 -2
- package/dist/src/stash-search.d.ts +0 -8
- package/dist/src/stash-show.d.ts +0 -5
- package/dist/src/stash-source.d.ts +0 -24
- package/dist/src/stash-types.d.ts +0 -227
- package/dist/src/stash.d.ts +0 -16
- package/dist/src/stash.js +0 -9
- package/dist/src/tool-runner.d.ts +0 -35
- package/dist/src/walker.d.ts +0 -19
- package/src/asset-spec.ts +0 -85
- package/src/asset-type-handler.ts +0 -77
- package/src/cli.ts +0 -427
- package/src/common.ts +0 -76
- package/src/config-cli.ts +0 -499
- package/src/config.ts +0 -305
- package/src/db.ts +0 -411
- package/src/embedder.ts +0 -128
- package/src/frontmatter.ts +0 -95
- package/src/github.ts +0 -21
- package/src/handlers/agent-handler.ts +0 -32
- package/src/handlers/command-handler.ts +0 -29
- package/src/handlers/index.ts +0 -25
- package/src/handlers/knowledge-handler.ts +0 -62
- package/src/handlers/markdown-helpers.ts +0 -19
- package/src/handlers/script-handler.ts +0 -92
- package/src/handlers/skill-handler.ts +0 -37
- package/src/handlers/tool-handler.ts +0 -71
- package/src/indexer.ts +0 -392
- package/src/init.ts +0 -114
- package/src/llm.ts +0 -125
- package/src/markdown.ts +0 -106
- package/src/metadata.ts +0 -333
- package/src/origin-resolve.ts +0 -67
- package/src/registry-install.ts +0 -361
- package/src/registry-resolve.ts +0 -341
- package/src/registry-search.ts +0 -335
- package/src/registry-types.ts +0 -72
- package/src/ripgrep-install.ts +0 -200
- package/src/ripgrep-resolve.ts +0 -72
- package/src/ripgrep.ts +0 -3
- package/src/stash-add.ts +0 -63
- package/src/stash-clone.ts +0 -127
- package/src/stash-ref.ts +0 -99
- package/src/stash-registry.ts +0 -259
- package/src/stash-resolve.ts +0 -50
- package/src/stash-search.ts +0 -613
- package/src/stash-show.ts +0 -55
- package/src/stash-source.ts +0 -103
- package/src/stash-types.ts +0 -231
- package/src/stash.ts +0 -39
- package/src/tool-runner.ts +0 -142
- package/src/walker.ts +0 -53
- /package/dist/{src/asset-spec.js → asset-spec.js} +0 -0
- /package/dist/{src/asset-type-handler.js → asset-type-handler.js} +0 -0
- /package/dist/{src/frontmatter.js → frontmatter.js} +0 -0
- /package/dist/{src/github.js → github.js} +0 -0
- /package/dist/{src/handlers → handlers}/agent-handler.js +0 -0
- /package/dist/{src/handlers → handlers}/knowledge-handler.js +0 -0
- /package/dist/{src/handlers → handlers}/markdown-helpers.js +0 -0
- /package/dist/{src/handlers → handlers}/script-handler.js +0 -0
- /package/dist/{src/handlers → handlers}/skill-handler.js +0 -0
- /package/dist/{src/handlers → handlers}/tool-handler.js +0 -0
- /package/dist/{src/llm.js → llm.js} +0 -0
- /package/dist/{src/markdown.js → markdown.js} +0 -0
- /package/dist/{src/registry-types.js → registry-types.js} +0 -0
- /package/dist/{src/ripgrep.js → ripgrep.js} +0 -0
- /package/dist/{src/stash-ref.js → stash-ref.js} +0 -0
- /package/dist/{src/stash-resolve.js → stash-resolve.js} +0 -0
- /package/dist/{src/stash-types.js → stash-types.js} +0 -0
- /package/dist/{src/tool-runner.js → tool-runner.js} +0 -0
package/src/stash-add.ts
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import { agentikitIndex } from "./indexer"
|
|
2
|
-
import fs from "node:fs"
|
|
3
|
-
import { resolveStashDir } from "./common"
|
|
4
|
-
import { loadConfig } from "./config"
|
|
5
|
-
import { upsertInstalledRegistryEntry, installRegistryRef } from "./registry-install"
|
|
6
|
-
import type { AddResponse } from "./stash-types"
|
|
7
|
-
|
|
8
|
-
export async function agentikitAdd(input: { ref: string }): Promise<AddResponse> {
|
|
9
|
-
const ref = input.ref.trim()
|
|
10
|
-
if (!ref) throw new Error("Install ref or local git directory is required.")
|
|
11
|
-
|
|
12
|
-
const stashDir = resolveStashDir()
|
|
13
|
-
const installed = await installRegistryRef(ref)
|
|
14
|
-
const replaced = loadConfig().registry?.installed.find((entry) => entry.id === installed.id)
|
|
15
|
-
const config = upsertInstalledRegistryEntry({
|
|
16
|
-
id: installed.id,
|
|
17
|
-
source: installed.source,
|
|
18
|
-
ref: installed.ref,
|
|
19
|
-
artifactUrl: installed.artifactUrl,
|
|
20
|
-
resolvedVersion: installed.resolvedVersion,
|
|
21
|
-
resolvedRevision: installed.resolvedRevision,
|
|
22
|
-
stashRoot: installed.stashRoot,
|
|
23
|
-
cacheDir: installed.cacheDir,
|
|
24
|
-
installedAt: installed.installedAt,
|
|
25
|
-
})
|
|
26
|
-
|
|
27
|
-
if (replaced && replaced.cacheDir !== installed.cacheDir) {
|
|
28
|
-
try {
|
|
29
|
-
fs.rmSync(replaced.cacheDir, { recursive: true, force: true })
|
|
30
|
-
} catch {
|
|
31
|
-
// Best-effort cleanup only.
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const index = await agentikitIndex({ stashDir })
|
|
36
|
-
|
|
37
|
-
return {
|
|
38
|
-
stashDir,
|
|
39
|
-
ref,
|
|
40
|
-
installed: {
|
|
41
|
-
id: installed.id,
|
|
42
|
-
source: installed.source,
|
|
43
|
-
ref: installed.ref,
|
|
44
|
-
artifactUrl: installed.artifactUrl,
|
|
45
|
-
resolvedVersion: installed.resolvedVersion,
|
|
46
|
-
resolvedRevision: installed.resolvedRevision,
|
|
47
|
-
stashRoot: installed.stashRoot,
|
|
48
|
-
cacheDir: installed.cacheDir,
|
|
49
|
-
extractedDir: installed.extractedDir,
|
|
50
|
-
installedAt: installed.installedAt,
|
|
51
|
-
},
|
|
52
|
-
config: {
|
|
53
|
-
mountedStashDirs: config.mountedStashDirs,
|
|
54
|
-
installedRegistryCount: config.registry?.installed.length ?? 0,
|
|
55
|
-
},
|
|
56
|
-
index: {
|
|
57
|
-
mode: index.mode,
|
|
58
|
-
totalEntries: index.totalEntries,
|
|
59
|
-
directoriesScanned: index.directoriesScanned,
|
|
60
|
-
directoriesSkipped: index.directoriesSkipped,
|
|
61
|
-
},
|
|
62
|
-
}
|
|
63
|
-
}
|
package/src/stash-clone.ts
DELETED
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
import fs from "node:fs"
|
|
2
|
-
import path from "node:path"
|
|
3
|
-
import { TYPE_DIRS } from "./asset-spec"
|
|
4
|
-
import { parseAssetRef, makeAssetRef } from "./stash-ref"
|
|
5
|
-
import { resolveSourcesForOrigin } from "./origin-resolve"
|
|
6
|
-
import { resolveAssetPath } from "./stash-resolve"
|
|
7
|
-
import { resolveStashSources, findSourceForPath, type StashSource, type StashSourceKind } from "./stash-source"
|
|
8
|
-
|
|
9
|
-
export interface CloneOptions {
|
|
10
|
-
/** Source ref (e.g., npm:@scope/pkg//tool:deploy.sh) */
|
|
11
|
-
sourceRef: string
|
|
12
|
-
/** Optional new name for the cloned asset */
|
|
13
|
-
newName?: string
|
|
14
|
-
/** If true, overwrite existing asset in working stash */
|
|
15
|
-
force?: boolean
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export interface CloneResponse {
|
|
19
|
-
source: {
|
|
20
|
-
path: string
|
|
21
|
-
sourceKind: StashSourceKind
|
|
22
|
-
registryId?: string
|
|
23
|
-
}
|
|
24
|
-
destination: {
|
|
25
|
-
path: string
|
|
26
|
-
ref: string
|
|
27
|
-
}
|
|
28
|
-
overwritten: boolean
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export async function agentikitClone(options: CloneOptions): Promise<CloneResponse> {
|
|
32
|
-
const parsed = parseAssetRef(options.sourceRef)
|
|
33
|
-
const allSources = resolveStashSources()
|
|
34
|
-
const workingSource = allSources.find((s) => s.kind === "working")
|
|
35
|
-
if (!workingSource) {
|
|
36
|
-
throw new Error("No working stash configured. Run `akm init` first.")
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const searchSources = resolveSourcesForOrigin(parsed.origin, allSources)
|
|
40
|
-
|
|
41
|
-
let sourcePath: string | undefined
|
|
42
|
-
let lastError: Error | undefined
|
|
43
|
-
for (const source of searchSources) {
|
|
44
|
-
try {
|
|
45
|
-
sourcePath = resolveAssetPath(source.path, parsed.type, parsed.name)
|
|
46
|
-
break
|
|
47
|
-
} catch (err) {
|
|
48
|
-
lastError = err instanceof Error ? err : new Error(String(err))
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
if (!sourcePath) {
|
|
52
|
-
throw lastError ?? new Error(`Source asset not found for ref: ${options.sourceRef}`)
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const sourceSource = findSourceForPath(sourcePath, allSources)
|
|
56
|
-
const sourceKind = sourceSource?.kind ?? "working"
|
|
57
|
-
|
|
58
|
-
const destName = options.newName ?? parsed.name
|
|
59
|
-
const typeDir = TYPE_DIRS[parsed.type]
|
|
60
|
-
const workingDir = workingSource.path
|
|
61
|
-
|
|
62
|
-
// Guard against self-clone
|
|
63
|
-
if (parsed.type === "skill") {
|
|
64
|
-
const sourceSkillDir = path.resolve(path.dirname(sourcePath))
|
|
65
|
-
const destSkillDir = path.resolve(path.join(workingDir, typeDir, destName))
|
|
66
|
-
if (sourceSkillDir === destSkillDir) {
|
|
67
|
-
throw new Error(
|
|
68
|
-
`Source and destination are the same path. Use --name to provide a new name for the clone.`,
|
|
69
|
-
)
|
|
70
|
-
}
|
|
71
|
-
} else {
|
|
72
|
-
const resolvedSource = path.resolve(sourcePath)
|
|
73
|
-
const resolvedDest = path.resolve(path.join(workingDir, typeDir, destName))
|
|
74
|
-
if (resolvedSource === resolvedDest) {
|
|
75
|
-
throw new Error(
|
|
76
|
-
`Source and destination are the same path. Use --name to provide a new name for the clone.`,
|
|
77
|
-
)
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
let destPath: string
|
|
82
|
-
if (parsed.type === "skill") {
|
|
83
|
-
const sourceSkillDir = path.dirname(sourcePath)
|
|
84
|
-
const destSkillDir = path.join(workingDir, typeDir, destName)
|
|
85
|
-
const overwritten = fs.existsSync(destSkillDir)
|
|
86
|
-
|
|
87
|
-
if (overwritten && !options.force) {
|
|
88
|
-
throw new Error(
|
|
89
|
-
`Asset already exists in working stash: ${destSkillDir}. Use --force to overwrite.`,
|
|
90
|
-
)
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
if (overwritten) {
|
|
94
|
-
fs.rmSync(destSkillDir, { recursive: true, force: true })
|
|
95
|
-
}
|
|
96
|
-
fs.cpSync(sourceSkillDir, destSkillDir, { recursive: true })
|
|
97
|
-
|
|
98
|
-
destPath = path.join(destSkillDir, "SKILL.md")
|
|
99
|
-
const ref = makeAssetRef(parsed.type, destName, "local")
|
|
100
|
-
|
|
101
|
-
return {
|
|
102
|
-
source: { path: sourcePath, sourceKind, registryId: sourceSource?.registryId },
|
|
103
|
-
destination: { path: destPath, ref },
|
|
104
|
-
overwritten,
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
destPath = path.join(workingDir, typeDir, destName)
|
|
109
|
-
const overwritten = fs.existsSync(destPath)
|
|
110
|
-
|
|
111
|
-
if (overwritten && !options.force) {
|
|
112
|
-
throw new Error(
|
|
113
|
-
`Asset already exists in working stash: ${destPath}. Use --force to overwrite.`,
|
|
114
|
-
)
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
fs.mkdirSync(path.dirname(destPath), { recursive: true })
|
|
118
|
-
fs.copyFileSync(sourcePath, destPath)
|
|
119
|
-
|
|
120
|
-
const ref = makeAssetRef(parsed.type, destName, "local")
|
|
121
|
-
|
|
122
|
-
return {
|
|
123
|
-
source: { path: sourcePath, sourceKind, registryId: sourceSource?.registryId },
|
|
124
|
-
destination: { path: destPath, ref },
|
|
125
|
-
overwritten,
|
|
126
|
-
}
|
|
127
|
-
}
|
package/src/stash-ref.ts
DELETED
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
import path from "node:path"
|
|
2
|
-
import { type AgentikitAssetType, isAssetType } from "./common"
|
|
3
|
-
|
|
4
|
-
// ── Types ───────────────────────────────────────────────────────────────────
|
|
5
|
-
|
|
6
|
-
export interface AssetRef {
|
|
7
|
-
type: AgentikitAssetType
|
|
8
|
-
name: string
|
|
9
|
-
/**
|
|
10
|
-
* Where to find this asset.
|
|
11
|
-
* - undefined: search all sources (working → mounted → installed)
|
|
12
|
-
* - "local": working stash only
|
|
13
|
-
* - registry ref: e.g. "npm:@scope/pkg", "owner/repo", "github:owner/repo#v1"
|
|
14
|
-
* - filesystem path: e.g. "/mnt/shared-stash"
|
|
15
|
-
*/
|
|
16
|
-
origin?: string
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
// ── Construction ────────────────────────────────────────────────────────────
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Build a ref string from components.
|
|
23
|
-
*
|
|
24
|
-
* Examples:
|
|
25
|
-
* makeAssetRef("tool", "deploy.sh")
|
|
26
|
-
* → "tool:deploy.sh"
|
|
27
|
-
* makeAssetRef("tool", "deploy.sh", "npm:@scope/pkg")
|
|
28
|
-
* → "npm:@scope/pkg//tool:deploy.sh"
|
|
29
|
-
* makeAssetRef("skill", "code-review", "local")
|
|
30
|
-
* → "local//skill:code-review"
|
|
31
|
-
* makeAssetRef("tool", "db/migrate/run.sh", "owner/repo")
|
|
32
|
-
* → "owner/repo//tool:db/migrate/run.sh"
|
|
33
|
-
*/
|
|
34
|
-
export function makeAssetRef(
|
|
35
|
-
type: AgentikitAssetType,
|
|
36
|
-
name: string,
|
|
37
|
-
origin?: string,
|
|
38
|
-
): string {
|
|
39
|
-
validateName(name)
|
|
40
|
-
const normalized = normalizeName(name)
|
|
41
|
-
const asset = `${type}:${normalized}`
|
|
42
|
-
if (!origin) return asset
|
|
43
|
-
return `${origin}//${asset}`
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// ── Parsing ─────────────────────────────────────────────────────────────────
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Parse a ref string in the format `[origin//]type:name`.
|
|
50
|
-
*/
|
|
51
|
-
export function parseAssetRef(ref: string): AssetRef {
|
|
52
|
-
const trimmed = ref.trim()
|
|
53
|
-
if (!trimmed) throw new Error("Empty ref.")
|
|
54
|
-
|
|
55
|
-
let origin: string | undefined
|
|
56
|
-
let body = trimmed
|
|
57
|
-
|
|
58
|
-
const boundary = trimmed.indexOf("//")
|
|
59
|
-
if (boundary >= 0) {
|
|
60
|
-
origin = trimmed.slice(0, boundary)
|
|
61
|
-
body = trimmed.slice(boundary + 2)
|
|
62
|
-
if (!origin) throw new Error("Empty origin in ref.")
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
const colon = body.indexOf(":")
|
|
66
|
-
if (colon <= 0) {
|
|
67
|
-
throw new Error(`Invalid ref "${trimmed}". Expected [origin//]type:name`)
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
const rawType = body.slice(0, colon)
|
|
71
|
-
const rawName = body.slice(colon + 1)
|
|
72
|
-
|
|
73
|
-
if (!isAssetType(rawType)) {
|
|
74
|
-
throw new Error(`Invalid asset type: "${rawType}".`)
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
validateName(rawName)
|
|
78
|
-
const name = normalizeName(rawName)
|
|
79
|
-
|
|
80
|
-
return { type: rawType, name, origin: origin || undefined }
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// ── Validation ──────────────────────────────────────────────────────────────
|
|
84
|
-
|
|
85
|
-
function validateName(name: string): void {
|
|
86
|
-
if (!name) throw new Error("Empty asset name.")
|
|
87
|
-
if (name.includes("\0")) throw new Error("Null byte in asset name.")
|
|
88
|
-
if (/^[A-Za-z]:/.test(name)) throw new Error("Windows drive path in asset name.")
|
|
89
|
-
|
|
90
|
-
const normalized = path.posix.normalize(name.replace(/\\/g, "/"))
|
|
91
|
-
if (path.posix.isAbsolute(normalized)) throw new Error("Absolute path in asset name.")
|
|
92
|
-
if (normalized === ".." || normalized.startsWith("../")) {
|
|
93
|
-
throw new Error("Path traversal in asset name.")
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
function normalizeName(name: string): string {
|
|
98
|
-
return path.posix.normalize(name.replace(/\\/g, "/"))
|
|
99
|
-
}
|
package/src/stash-registry.ts
DELETED
|
@@ -1,259 +0,0 @@
|
|
|
1
|
-
import fs from "node:fs"
|
|
2
|
-
import { resolveStashDir } from "./common"
|
|
3
|
-
import { loadConfig } from "./config"
|
|
4
|
-
import { agentikitIndex } from "./indexer"
|
|
5
|
-
import {
|
|
6
|
-
installRegistryRef,
|
|
7
|
-
removeInstalledRegistryEntry,
|
|
8
|
-
upsertInstalledRegistryEntry,
|
|
9
|
-
} from "./registry-install"
|
|
10
|
-
import { parseRegistryRef } from "./registry-resolve"
|
|
11
|
-
import type { RegistryInstalledEntry } from "./registry-types"
|
|
12
|
-
import type {
|
|
13
|
-
ListResponse,
|
|
14
|
-
RegistryInstallStatus,
|
|
15
|
-
RemoveResponse,
|
|
16
|
-
ReinstallResponse,
|
|
17
|
-
UpdateResponse,
|
|
18
|
-
} from "./stash-types"
|
|
19
|
-
|
|
20
|
-
export async function agentikitList(input?: { stashDir?: string }): Promise<ListResponse> {
|
|
21
|
-
const stashDir = input?.stashDir ?? resolveStashDir()
|
|
22
|
-
const config = loadConfig()
|
|
23
|
-
const installed = config.registry?.installed ?? []
|
|
24
|
-
|
|
25
|
-
return {
|
|
26
|
-
stashDir,
|
|
27
|
-
installed: installed.map((entry) => ({
|
|
28
|
-
...entry,
|
|
29
|
-
status: {
|
|
30
|
-
cacheDirExists: directoryExists(entry.cacheDir),
|
|
31
|
-
stashRootExists: directoryExists(entry.stashRoot),
|
|
32
|
-
},
|
|
33
|
-
})),
|
|
34
|
-
totalInstalled: installed.length,
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export async function agentikitRemove(input: { target: string; stashDir?: string }): Promise<RemoveResponse> {
|
|
39
|
-
const target = input.target.trim()
|
|
40
|
-
if (!target) throw new Error("Target is required.")
|
|
41
|
-
|
|
42
|
-
const stashDir = input.stashDir ?? resolveStashDir()
|
|
43
|
-
const config = loadConfig()
|
|
44
|
-
const installed = config.registry?.installed ?? []
|
|
45
|
-
const entry = resolveInstalledTarget(installed, target)
|
|
46
|
-
|
|
47
|
-
const updatedConfig = removeInstalledRegistryEntry(entry.id)
|
|
48
|
-
cleanupDirectoryBestEffort(entry.cacheDir)
|
|
49
|
-
const index = await agentikitIndex({ stashDir })
|
|
50
|
-
|
|
51
|
-
return {
|
|
52
|
-
stashDir,
|
|
53
|
-
target,
|
|
54
|
-
removed: {
|
|
55
|
-
id: entry.id,
|
|
56
|
-
source: entry.source,
|
|
57
|
-
ref: entry.ref,
|
|
58
|
-
cacheDir: entry.cacheDir,
|
|
59
|
-
stashRoot: entry.stashRoot,
|
|
60
|
-
},
|
|
61
|
-
config: {
|
|
62
|
-
mountedStashDirs: updatedConfig.mountedStashDirs,
|
|
63
|
-
installedRegistryCount: updatedConfig.registry?.installed.length ?? 0,
|
|
64
|
-
},
|
|
65
|
-
index: {
|
|
66
|
-
mode: index.mode,
|
|
67
|
-
totalEntries: index.totalEntries,
|
|
68
|
-
directoriesScanned: index.directoriesScanned,
|
|
69
|
-
directoriesSkipped: index.directoriesSkipped,
|
|
70
|
-
},
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
export async function agentikitReinstall(input?: {
|
|
75
|
-
target?: string
|
|
76
|
-
all?: boolean
|
|
77
|
-
stashDir?: string
|
|
78
|
-
}): Promise<ReinstallResponse> {
|
|
79
|
-
const stashDir = input?.stashDir ?? resolveStashDir()
|
|
80
|
-
const target = input?.target?.trim()
|
|
81
|
-
const all = input?.all === true
|
|
82
|
-
const installedEntries = loadConfig().registry?.installed ?? []
|
|
83
|
-
const selectedEntries = selectTargets(installedEntries, target, all)
|
|
84
|
-
|
|
85
|
-
const processed: ReinstallResponse["processed"] = []
|
|
86
|
-
for (const entry of selectedEntries) {
|
|
87
|
-
const installed = await installRegistryRef(entry.ref)
|
|
88
|
-
upsertInstalledRegistryEntry(toInstalledEntry(installed))
|
|
89
|
-
if (entry.cacheDir !== installed.cacheDir) {
|
|
90
|
-
cleanupDirectoryBestEffort(entry.cacheDir)
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
processed.push({
|
|
94
|
-
id: entry.id,
|
|
95
|
-
source: entry.source,
|
|
96
|
-
ref: entry.ref,
|
|
97
|
-
previousCacheDir: entry.cacheDir,
|
|
98
|
-
installed: toInstallStatus(installed),
|
|
99
|
-
})
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
const index = await agentikitIndex({ stashDir })
|
|
103
|
-
const config = loadConfig()
|
|
104
|
-
|
|
105
|
-
return {
|
|
106
|
-
stashDir,
|
|
107
|
-
target,
|
|
108
|
-
all,
|
|
109
|
-
processed,
|
|
110
|
-
config: {
|
|
111
|
-
mountedStashDirs: config.mountedStashDirs,
|
|
112
|
-
installedRegistryCount: config.registry?.installed.length ?? 0,
|
|
113
|
-
},
|
|
114
|
-
index: {
|
|
115
|
-
mode: index.mode,
|
|
116
|
-
totalEntries: index.totalEntries,
|
|
117
|
-
directoriesScanned: index.directoriesScanned,
|
|
118
|
-
directoriesSkipped: index.directoriesSkipped,
|
|
119
|
-
},
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
export async function agentikitUpdate(input?: {
|
|
124
|
-
target?: string
|
|
125
|
-
all?: boolean
|
|
126
|
-
stashDir?: string
|
|
127
|
-
}): Promise<UpdateResponse> {
|
|
128
|
-
const stashDir = input?.stashDir ?? resolveStashDir()
|
|
129
|
-
const target = input?.target?.trim()
|
|
130
|
-
const all = input?.all === true
|
|
131
|
-
const installedEntries = loadConfig().registry?.installed ?? []
|
|
132
|
-
const selectedEntries = selectTargets(installedEntries, target, all)
|
|
133
|
-
|
|
134
|
-
const processed: UpdateResponse["processed"] = []
|
|
135
|
-
for (const entry of selectedEntries) {
|
|
136
|
-
const installed = await installRegistryRef(entry.ref)
|
|
137
|
-
upsertInstalledRegistryEntry(toInstalledEntry(installed))
|
|
138
|
-
if (entry.cacheDir !== installed.cacheDir) {
|
|
139
|
-
cleanupDirectoryBestEffort(entry.cacheDir)
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
const versionChanged = (entry.resolvedVersion ?? "") !== (installed.resolvedVersion ?? "")
|
|
143
|
-
const revisionChanged = (entry.resolvedRevision ?? "") !== (installed.resolvedRevision ?? "")
|
|
144
|
-
|
|
145
|
-
processed.push({
|
|
146
|
-
id: entry.id,
|
|
147
|
-
source: entry.source,
|
|
148
|
-
ref: entry.ref,
|
|
149
|
-
previous: {
|
|
150
|
-
resolvedVersion: entry.resolvedVersion,
|
|
151
|
-
resolvedRevision: entry.resolvedRevision,
|
|
152
|
-
cacheDir: entry.cacheDir,
|
|
153
|
-
},
|
|
154
|
-
installed: toInstallStatus(installed),
|
|
155
|
-
changed: {
|
|
156
|
-
version: versionChanged,
|
|
157
|
-
revision: revisionChanged,
|
|
158
|
-
any: versionChanged || revisionChanged,
|
|
159
|
-
},
|
|
160
|
-
})
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
const index = await agentikitIndex({ stashDir })
|
|
164
|
-
const config = loadConfig()
|
|
165
|
-
|
|
166
|
-
return {
|
|
167
|
-
stashDir,
|
|
168
|
-
target,
|
|
169
|
-
all,
|
|
170
|
-
processed,
|
|
171
|
-
config: {
|
|
172
|
-
mountedStashDirs: config.mountedStashDirs,
|
|
173
|
-
installedRegistryCount: config.registry?.installed.length ?? 0,
|
|
174
|
-
},
|
|
175
|
-
index: {
|
|
176
|
-
mode: index.mode,
|
|
177
|
-
totalEntries: index.totalEntries,
|
|
178
|
-
directoriesScanned: index.directoriesScanned,
|
|
179
|
-
directoriesSkipped: index.directoriesSkipped,
|
|
180
|
-
},
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
function selectTargets(installed: RegistryInstalledEntry[], target: string | undefined, all: boolean): RegistryInstalledEntry[] {
|
|
185
|
-
if (all && target) {
|
|
186
|
-
throw new Error("Specify either <target> or --all, not both.")
|
|
187
|
-
}
|
|
188
|
-
if (all) return installed
|
|
189
|
-
if (!target) {
|
|
190
|
-
throw new Error("Either <target> or --all is required.")
|
|
191
|
-
}
|
|
192
|
-
return [resolveInstalledTarget(installed, target)]
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
function resolveInstalledTarget(installed: RegistryInstalledEntry[], target: string): RegistryInstalledEntry {
|
|
196
|
-
const byId = installed.find((entry) => entry.id === target)
|
|
197
|
-
if (byId) return byId
|
|
198
|
-
|
|
199
|
-
const byRef = installed.find((entry) => entry.ref === target)
|
|
200
|
-
if (byRef) return byRef
|
|
201
|
-
|
|
202
|
-
let parsedId: string | undefined
|
|
203
|
-
try {
|
|
204
|
-
parsedId = parseRegistryRef(target).id
|
|
205
|
-
} catch {
|
|
206
|
-
parsedId = undefined
|
|
207
|
-
}
|
|
208
|
-
if (parsedId) {
|
|
209
|
-
const byParsedId = installed.find((entry) => entry.id === parsedId)
|
|
210
|
-
if (byParsedId) return byParsedId
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
throw new Error(`No installed registry entry matched target: ${target}`)
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
function toInstalledEntry(status: RegistryInstallStatus): RegistryInstalledEntry {
|
|
217
|
-
return {
|
|
218
|
-
id: status.id,
|
|
219
|
-
source: status.source,
|
|
220
|
-
ref: status.ref,
|
|
221
|
-
artifactUrl: status.artifactUrl,
|
|
222
|
-
resolvedVersion: status.resolvedVersion,
|
|
223
|
-
resolvedRevision: status.resolvedRevision,
|
|
224
|
-
stashRoot: status.stashRoot,
|
|
225
|
-
cacheDir: status.cacheDir,
|
|
226
|
-
installedAt: status.installedAt,
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
function toInstallStatus(status: RegistryInstallStatus): RegistryInstallStatus {
|
|
231
|
-
return {
|
|
232
|
-
id: status.id,
|
|
233
|
-
source: status.source,
|
|
234
|
-
ref: status.ref,
|
|
235
|
-
artifactUrl: status.artifactUrl,
|
|
236
|
-
resolvedVersion: status.resolvedVersion,
|
|
237
|
-
resolvedRevision: status.resolvedRevision,
|
|
238
|
-
stashRoot: status.stashRoot,
|
|
239
|
-
cacheDir: status.cacheDir,
|
|
240
|
-
extractedDir: status.extractedDir,
|
|
241
|
-
installedAt: status.installedAt,
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
function cleanupDirectoryBestEffort(target: string): void {
|
|
246
|
-
try {
|
|
247
|
-
fs.rmSync(target, { recursive: true, force: true })
|
|
248
|
-
} catch {
|
|
249
|
-
// Best-effort cleanup only.
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
function directoryExists(target: string): boolean {
|
|
254
|
-
try {
|
|
255
|
-
return fs.statSync(target).isDirectory()
|
|
256
|
-
} catch {
|
|
257
|
-
return false
|
|
258
|
-
}
|
|
259
|
-
}
|
package/src/stash-resolve.ts
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import fs from "node:fs"
|
|
2
|
-
import path from "node:path"
|
|
3
|
-
import { type AgentikitAssetType, hasErrnoCode, isWithin } from "./common"
|
|
4
|
-
import { TYPE_DIRS, isRelevantAssetFile, resolveAssetPathFromName } from "./asset-spec"
|
|
5
|
-
|
|
6
|
-
export function resolveAssetPath(stashDir: string, type: AgentikitAssetType, name: string): string {
|
|
7
|
-
const root = path.join(stashDir, TYPE_DIRS[type])
|
|
8
|
-
const target = resolveAssetPathFromName(type, root, name)
|
|
9
|
-
const resolvedRoot = resolveAndValidateTypeRoot(root, type, name)
|
|
10
|
-
const resolvedTarget = path.resolve(target)
|
|
11
|
-
if (!isWithin(resolvedTarget, resolvedRoot)) {
|
|
12
|
-
throw new Error("Ref resolves outside the stash root.")
|
|
13
|
-
}
|
|
14
|
-
if (!fs.existsSync(resolvedTarget) || !fs.statSync(resolvedTarget).isFile()) {
|
|
15
|
-
throw new Error(`Stash asset not found for ref: ${type}:${name}`)
|
|
16
|
-
}
|
|
17
|
-
const realTarget = fs.realpathSync(resolvedTarget)
|
|
18
|
-
if (!isWithin(realTarget, resolvedRoot)) {
|
|
19
|
-
throw new Error("Ref resolves outside the stash root.")
|
|
20
|
-
}
|
|
21
|
-
if (!isRelevantAssetFile(type, path.basename(resolvedTarget))) {
|
|
22
|
-
if (type === "tool") {
|
|
23
|
-
throw new Error("Tool ref must resolve to a .sh, .ts, .js, .ps1, .cmd, or .bat file.")
|
|
24
|
-
}
|
|
25
|
-
if (type === "script") {
|
|
26
|
-
throw new Error("Script ref must resolve to a file with a supported script extension. Refer to the Agentikit documentation for the complete list of supported script extensions.");
|
|
27
|
-
}
|
|
28
|
-
throw new Error(`Stash asset not found for ref: ${type}:${name}`)
|
|
29
|
-
}
|
|
30
|
-
return realTarget
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
function resolveAndValidateTypeRoot(root: string, type: AgentikitAssetType, name: string): string {
|
|
34
|
-
const rootStat = readTypeRootStat(root, type, name)
|
|
35
|
-
if (!rootStat.isDirectory()) {
|
|
36
|
-
throw new Error(`Stash type root is not a directory for ref: ${type}:${name}`)
|
|
37
|
-
}
|
|
38
|
-
return fs.realpathSync(root)
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
function readTypeRootStat(root: string, type: AgentikitAssetType, name: string): fs.Stats {
|
|
42
|
-
try {
|
|
43
|
-
return fs.statSync(root)
|
|
44
|
-
} catch (error: unknown) {
|
|
45
|
-
if (hasErrnoCode(error, "ENOENT")) {
|
|
46
|
-
throw new Error(`Stash type root not found for ref: ${type}:${name}`)
|
|
47
|
-
}
|
|
48
|
-
throw error
|
|
49
|
-
}
|
|
50
|
-
}
|