agentikit 0.0.12 → 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.
Files changed (146) hide show
  1. package/LICENSE +385 -0
  2. package/README.md +186 -100
  3. package/dist/cli.js +671 -0
  4. package/dist/common.js +192 -0
  5. package/dist/{src/config-cli.js → config-cli.js} +14 -6
  6. package/dist/{src/config.js → config.js} +92 -24
  7. package/dist/{src/db.js → db.js} +109 -35
  8. package/dist/{src/embedder.js → embedder.js} +57 -2
  9. package/dist/file-context.js +158 -0
  10. package/dist/{src/handlers → handlers}/command-handler.js +2 -0
  11. package/dist/{src/handlers → handlers}/index.js +0 -6
  12. package/dist/{src/indexer.js → indexer.js} +34 -10
  13. package/dist/init.js +43 -0
  14. package/dist/lockfile.js +55 -0
  15. package/dist/matchers.js +157 -0
  16. package/dist/{src/metadata.js → metadata.js} +12 -1
  17. package/dist/{src/origin-resolve.js → origin-resolve.js} +10 -9
  18. package/dist/paths.js +82 -0
  19. package/dist/{src/registry-install.js → registry-install.js} +145 -17
  20. package/dist/{src/registry-resolve.js → registry-resolve.js} +178 -18
  21. package/dist/{src/registry-search.js → registry-search.js} +8 -16
  22. package/dist/renderers.js +276 -0
  23. package/dist/{src/ripgrep-install.js → ripgrep-install.js} +5 -5
  24. package/dist/{src/ripgrep-resolve.js → ripgrep-resolve.js} +21 -11
  25. package/dist/self-update.js +220 -0
  26. package/dist/{src/stash-add.js → stash-add.js} +11 -2
  27. package/dist/stash-clone.js +115 -0
  28. package/dist/{src/stash-registry.js → stash-registry.js} +15 -41
  29. package/dist/{src/stash-search.js → stash-search.js} +67 -55
  30. package/dist/{src/stash-show.js → stash-show.js} +30 -3
  31. package/dist/{src/stash-source.js → stash-source.js} +56 -9
  32. package/dist/submit.js +552 -0
  33. package/dist/{src/walker.js → walker.js} +38 -0
  34. package/package.json +7 -16
  35. package/dist/index.d.ts +0 -28
  36. package/dist/index.js +0 -15
  37. package/dist/src/asset-spec.d.ts +0 -16
  38. package/dist/src/asset-type-handler.d.ts +0 -27
  39. package/dist/src/cli.d.ts +0 -2
  40. package/dist/src/cli.js +0 -399
  41. package/dist/src/common.d.ts +0 -13
  42. package/dist/src/common.js +0 -60
  43. package/dist/src/config-cli.d.ts +0 -9
  44. package/dist/src/config.d.ts +0 -50
  45. package/dist/src/db.d.ts +0 -46
  46. package/dist/src/embedder.d.ts +0 -10
  47. package/dist/src/frontmatter.d.ts +0 -30
  48. package/dist/src/github.d.ts +0 -4
  49. package/dist/src/handlers/agent-handler.d.ts +0 -2
  50. package/dist/src/handlers/command-handler.d.ts +0 -2
  51. package/dist/src/handlers/index.d.ts +0 -6
  52. package/dist/src/handlers/knowledge-handler.d.ts +0 -2
  53. package/dist/src/handlers/markdown-helpers.d.ts +0 -7
  54. package/dist/src/handlers/script-handler.d.ts +0 -2
  55. package/dist/src/handlers/skill-handler.d.ts +0 -2
  56. package/dist/src/handlers/tool-handler.d.ts +0 -2
  57. package/dist/src/indexer.d.ts +0 -22
  58. package/dist/src/init.d.ts +0 -19
  59. package/dist/src/init.js +0 -99
  60. package/dist/src/llm.d.ts +0 -15
  61. package/dist/src/markdown.d.ts +0 -18
  62. package/dist/src/metadata.d.ts +0 -41
  63. package/dist/src/origin-resolve.d.ts +0 -19
  64. package/dist/src/registry-install.d.ts +0 -11
  65. package/dist/src/registry-resolve.d.ts +0 -3
  66. package/dist/src/registry-search.d.ts +0 -27
  67. package/dist/src/registry-types.d.ts +0 -62
  68. package/dist/src/ripgrep-install.d.ts +0 -12
  69. package/dist/src/ripgrep-resolve.d.ts +0 -13
  70. package/dist/src/ripgrep.d.ts +0 -3
  71. package/dist/src/similarity.js +0 -211
  72. package/dist/src/stash-add.d.ts +0 -4
  73. package/dist/src/stash-clone.d.ts +0 -22
  74. package/dist/src/stash-clone.js +0 -83
  75. package/dist/src/stash-ref.d.ts +0 -31
  76. package/dist/src/stash-registry.d.ts +0 -18
  77. package/dist/src/stash-resolve.d.ts +0 -2
  78. package/dist/src/stash-search.d.ts +0 -8
  79. package/dist/src/stash-show.d.ts +0 -5
  80. package/dist/src/stash-source.d.ts +0 -24
  81. package/dist/src/stash-types.d.ts +0 -227
  82. package/dist/src/stash.d.ts +0 -16
  83. package/dist/src/stash.js +0 -9
  84. package/dist/src/tool-runner.d.ts +0 -35
  85. package/dist/src/walker.d.ts +0 -19
  86. package/src/asset-spec.ts +0 -85
  87. package/src/asset-type-handler.ts +0 -77
  88. package/src/cli.ts +0 -427
  89. package/src/common.ts +0 -76
  90. package/src/config-cli.ts +0 -499
  91. package/src/config.ts +0 -305
  92. package/src/db.ts +0 -411
  93. package/src/embedder.ts +0 -128
  94. package/src/frontmatter.ts +0 -95
  95. package/src/github.ts +0 -21
  96. package/src/handlers/agent-handler.ts +0 -32
  97. package/src/handlers/command-handler.ts +0 -29
  98. package/src/handlers/index.ts +0 -25
  99. package/src/handlers/knowledge-handler.ts +0 -62
  100. package/src/handlers/markdown-helpers.ts +0 -19
  101. package/src/handlers/script-handler.ts +0 -92
  102. package/src/handlers/skill-handler.ts +0 -37
  103. package/src/handlers/tool-handler.ts +0 -71
  104. package/src/indexer.ts +0 -392
  105. package/src/init.ts +0 -114
  106. package/src/llm.ts +0 -125
  107. package/src/markdown.ts +0 -106
  108. package/src/metadata.ts +0 -333
  109. package/src/origin-resolve.ts +0 -67
  110. package/src/registry-install.ts +0 -361
  111. package/src/registry-resolve.ts +0 -341
  112. package/src/registry-search.ts +0 -335
  113. package/src/registry-types.ts +0 -72
  114. package/src/ripgrep-install.ts +0 -200
  115. package/src/ripgrep-resolve.ts +0 -72
  116. package/src/ripgrep.ts +0 -3
  117. package/src/stash-add.ts +0 -63
  118. package/src/stash-clone.ts +0 -127
  119. package/src/stash-ref.ts +0 -99
  120. package/src/stash-registry.ts +0 -259
  121. package/src/stash-resolve.ts +0 -50
  122. package/src/stash-search.ts +0 -613
  123. package/src/stash-show.ts +0 -55
  124. package/src/stash-source.ts +0 -103
  125. package/src/stash-types.ts +0 -231
  126. package/src/stash.ts +0 -39
  127. package/src/tool-runner.ts +0 -142
  128. package/src/walker.ts +0 -53
  129. /package/dist/{src/asset-spec.js → asset-spec.js} +0 -0
  130. /package/dist/{src/asset-type-handler.js → asset-type-handler.js} +0 -0
  131. /package/dist/{src/frontmatter.js → frontmatter.js} +0 -0
  132. /package/dist/{src/github.js → github.js} +0 -0
  133. /package/dist/{src/handlers → handlers}/agent-handler.js +0 -0
  134. /package/dist/{src/handlers → handlers}/knowledge-handler.js +0 -0
  135. /package/dist/{src/handlers → handlers}/markdown-helpers.js +0 -0
  136. /package/dist/{src/handlers → handlers}/script-handler.js +0 -0
  137. /package/dist/{src/handlers → handlers}/skill-handler.js +0 -0
  138. /package/dist/{src/handlers → handlers}/tool-handler.js +0 -0
  139. /package/dist/{src/llm.js → llm.js} +0 -0
  140. /package/dist/{src/markdown.js → markdown.js} +0 -0
  141. /package/dist/{src/registry-types.js → registry-types.js} +0 -0
  142. /package/dist/{src/ripgrep.js → ripgrep.js} +0 -0
  143. /package/dist/{src/stash-ref.js → stash-ref.js} +0 -0
  144. /package/dist/{src/stash-resolve.js → stash-resolve.js} +0 -0
  145. /package/dist/{src/stash-types.js → stash-types.js} +0 -0
  146. /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
- }
@@ -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
- }
@@ -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
- }
@@ -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
- }