agentikit 0.0.13 → 0.0.15
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 +187 -110
- package/dist/{src/asset-spec.js → asset-spec.js} +11 -2
- package/dist/{src/asset-type-handler.js → asset-type-handler.js} +4 -3
- package/dist/cli.js +709 -0
- package/dist/common.js +192 -0
- package/dist/{src/config-cli.js → config-cli.js} +36 -30
- package/dist/{src/config.js → config.js} +95 -25
- package/dist/{src/db.js → db.js} +123 -51
- package/dist/{src/embedder.js → embedder.js} +57 -2
- package/dist/errors.js +28 -0
- package/dist/file-context.js +188 -0
- package/dist/{src/frontmatter.js → frontmatter.js} +1 -1
- package/dist/{src/github.js → github.js} +1 -3
- package/dist/handlers/agent-handler.js +19 -0
- package/dist/handlers/command-handler.js +20 -0
- package/dist/handlers/handler-bridge.js +51 -0
- package/dist/handlers/index.js +19 -0
- package/dist/handlers/knowledge-handler.js +32 -0
- package/dist/handlers/script-handler.js +42 -0
- package/dist/{src/handlers → handlers}/skill-handler.js +5 -6
- package/dist/{src/handlers → handlers}/tool-handler.js +8 -24
- package/dist/{src/indexer.js → indexer.js} +50 -26
- package/dist/init.js +43 -0
- package/dist/{src/llm.js → llm.js} +6 -11
- package/dist/lockfile.js +60 -0
- package/dist/matchers.js +163 -0
- package/dist/{src/metadata.js → metadata.js} +36 -16
- package/dist/{src/origin-resolve.js → origin-resolve.js} +10 -9
- package/dist/paths.js +83 -0
- package/dist/{src/registry-install.js → registry-install.js} +151 -19
- package/dist/{src/registry-resolve.js → registry-resolve.js} +190 -26
- package/dist/{src/registry-search.js → registry-search.js} +13 -21
- package/dist/renderers.js +286 -0
- package/dist/{src/ripgrep-install.js → ripgrep-install.js} +8 -27
- package/dist/{src/ripgrep-resolve.js → ripgrep-resolve.js} +21 -11
- package/dist/ripgrep.js +2 -0
- package/dist/self-update.js +226 -0
- package/dist/{src/stash-add.js → stash-add.js} +14 -4
- package/dist/stash-clone.js +115 -0
- package/dist/{src/stash-ref.js → stash-ref.js} +10 -9
- package/dist/{src/stash-registry.js → stash-registry.js} +21 -46
- package/dist/{src/stash-resolve.js → stash-resolve.js} +10 -9
- package/dist/{src/stash-search.js → stash-search.js} +89 -74
- package/dist/stash-show.js +74 -0
- package/dist/stash-source.js +127 -0
- package/dist/submit.js +557 -0
- package/dist/{src/tool-runner.js → tool-runner.js} +1 -5
- package/dist/{src/walker.js → walker.js} +38 -0
- package/dist/warn.js +20 -0
- package/package.json +13 -18
- 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/agent-handler.js +0 -26
- package/dist/src/handlers/command-handler.d.ts +0 -2
- package/dist/src/handlers/command-handler.js +0 -23
- package/dist/src/handlers/index.d.ts +0 -6
- package/dist/src/handlers/index.js +0 -23
- package/dist/src/handlers/knowledge-handler.d.ts +0 -2
- package/dist/src/handlers/knowledge-handler.js +0 -56
- package/dist/src/handlers/markdown-helpers.d.ts +0 -7
- package/dist/src/handlers/script-handler.d.ts +0 -2
- package/dist/src/handlers/script-handler.js +0 -78
- 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/ripgrep.js +0 -2
- 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-show.js +0 -46
- package/dist/src/stash-source.d.ts +0 -24
- package/dist/src/stash-source.js +0 -81
- 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/handlers → handlers}/markdown-helpers.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/stash-types.js → stash-types.js} +0 -0
package/dist/cli.js
ADDED
|
@@ -0,0 +1,709 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { defineCommand, runMain } from "citty";
|
|
5
|
+
import { resolveStashDir } from "./common";
|
|
6
|
+
import { getConfigPath, loadConfig, saveConfig } from "./config";
|
|
7
|
+
import { getConfigValue, listConfig, listProviders, parseConfigValue, setConfigValue, unsetConfigValue, useProvider, } from "./config-cli";
|
|
8
|
+
import { ConfigError, NotFoundError, UsageError } from "./errors";
|
|
9
|
+
import { agentikitIndex } from "./indexer";
|
|
10
|
+
import { agentikitInit } from "./init";
|
|
11
|
+
import { getCacheDir, getDbPath, getDefaultStashDir } from "./paths";
|
|
12
|
+
import { checkForUpdate, performUpgrade } from "./self-update";
|
|
13
|
+
import { agentikitAdd } from "./stash-add";
|
|
14
|
+
import { agentikitClone } from "./stash-clone";
|
|
15
|
+
import { agentikitList, agentikitRemove, agentikitUpdate } from "./stash-registry";
|
|
16
|
+
import { agentikitSearch } from "./stash-search";
|
|
17
|
+
import { agentikitShow } from "./stash-show";
|
|
18
|
+
import { resolveStashSources } from "./stash-source";
|
|
19
|
+
import { agentikitSubmit } from "./submit";
|
|
20
|
+
import { setQuiet, warn } from "./warn";
|
|
21
|
+
// Version: prefer compile-time define, then package.json, then fallback
|
|
22
|
+
const pkgVersion = (() => {
|
|
23
|
+
// Injected at compile time via `bun build --define`
|
|
24
|
+
if (typeof AKM_VERSION !== "undefined")
|
|
25
|
+
return AKM_VERSION;
|
|
26
|
+
try {
|
|
27
|
+
const pkgPath = path.resolve(import.meta.dir ?? __dirname, "../package.json");
|
|
28
|
+
if (fs.existsSync(pkgPath)) {
|
|
29
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
|
|
30
|
+
if (typeof pkg.version === "string")
|
|
31
|
+
return pkg.version;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
// swallow — running as compiled binary without package.json
|
|
36
|
+
}
|
|
37
|
+
return "0.0.0-dev";
|
|
38
|
+
})();
|
|
39
|
+
/** Check whether --json flag is present in argv */
|
|
40
|
+
function isJsonMode() {
|
|
41
|
+
return process.argv.includes("--json");
|
|
42
|
+
}
|
|
43
|
+
function hasBunYAML(b) {
|
|
44
|
+
// biome-ignore lint/suspicious/noExplicitAny: type guard for runtime feature detection
|
|
45
|
+
return typeof b.YAML?.stringify === "function";
|
|
46
|
+
}
|
|
47
|
+
/** Try Bun.YAML.stringify; fall back to JSON if the API is unavailable */
|
|
48
|
+
function yamlStringify(obj) {
|
|
49
|
+
if (hasBunYAML(Bun)) {
|
|
50
|
+
return Bun.YAML.stringify(obj);
|
|
51
|
+
}
|
|
52
|
+
warn("YAML output not available, using JSON");
|
|
53
|
+
return JSON.stringify(obj, null, 2);
|
|
54
|
+
}
|
|
55
|
+
/** Output result: JSON if --json flag set, otherwise YAML (default) */
|
|
56
|
+
function output(command, result) {
|
|
57
|
+
if (isJsonMode()) {
|
|
58
|
+
console.log(JSON.stringify(result, null, 2));
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
// Some commands output plain text messages rather than structured data
|
|
62
|
+
const plain = formatPlain(command, result);
|
|
63
|
+
if (plain != null) {
|
|
64
|
+
console.log(plain);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
console.log(yamlStringify(result));
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Return a plain-text string for commands that are better as short messages,
|
|
71
|
+
* or null to fall through to YAML output.
|
|
72
|
+
*/
|
|
73
|
+
function formatPlain(command, result) {
|
|
74
|
+
const r = result;
|
|
75
|
+
switch (command) {
|
|
76
|
+
case "init": {
|
|
77
|
+
let out = `Stash initialized at ${r.stashDir ?? "unknown"}`;
|
|
78
|
+
if (r.configPath)
|
|
79
|
+
out += `\nConfig saved to ${r.configPath}`;
|
|
80
|
+
return out;
|
|
81
|
+
}
|
|
82
|
+
case "index": {
|
|
83
|
+
return `Indexed ${r.totalEntries ?? 0} entries from ${r.directoriesScanned ?? 0} directories (mode: ${r.mode ?? "unknown"})`;
|
|
84
|
+
}
|
|
85
|
+
case "show": {
|
|
86
|
+
if (r.content != null)
|
|
87
|
+
return String(r.content);
|
|
88
|
+
if (r.runCmd != null)
|
|
89
|
+
return String(r.runCmd);
|
|
90
|
+
if (r.prompt != null)
|
|
91
|
+
return String(r.prompt);
|
|
92
|
+
return null; // fall through to YAML
|
|
93
|
+
}
|
|
94
|
+
case "add": {
|
|
95
|
+
const installed = r.installed;
|
|
96
|
+
const indexed = installed?.indexed ?? r.indexed ?? 0;
|
|
97
|
+
return `Installed ${r.ref} (${indexed} assets indexed)`;
|
|
98
|
+
}
|
|
99
|
+
case "remove": {
|
|
100
|
+
const target = r.target ?? r.ref ?? "";
|
|
101
|
+
const ok = r.ok !== false ? "OK" : "FAILED";
|
|
102
|
+
return `remove: ${target} ${ok}`;
|
|
103
|
+
}
|
|
104
|
+
case "update": {
|
|
105
|
+
const processed = r.processed;
|
|
106
|
+
if (!processed?.length)
|
|
107
|
+
return `update: nothing to update`;
|
|
108
|
+
const lines = processed.map((item) => {
|
|
109
|
+
const changed = item.changed;
|
|
110
|
+
const installed = item.installed;
|
|
111
|
+
const previous = item.previous;
|
|
112
|
+
if (changed?.any) {
|
|
113
|
+
const prev = previous?.resolvedVersion ?? "unknown";
|
|
114
|
+
const next = installed?.resolvedVersion ?? "unknown";
|
|
115
|
+
return `update: ${item.id} v${prev} → v${next}`;
|
|
116
|
+
}
|
|
117
|
+
return `update: ${item.id} (unchanged)`;
|
|
118
|
+
});
|
|
119
|
+
return lines.join("\n");
|
|
120
|
+
}
|
|
121
|
+
case "upgrade": {
|
|
122
|
+
if (r.upgraded === true) {
|
|
123
|
+
return `akm upgraded: v${r.currentVersion} → v${r.newVersion}`;
|
|
124
|
+
}
|
|
125
|
+
if (r.updateAvailable === true) {
|
|
126
|
+
return `akm v${r.currentVersion} → v${r.latestVersion} available (run 'akm upgrade' to install)`;
|
|
127
|
+
}
|
|
128
|
+
if (r.updateAvailable === false && r.latestVersion) {
|
|
129
|
+
return `akm v${r.currentVersion} is already the latest version`;
|
|
130
|
+
}
|
|
131
|
+
if (r.message)
|
|
132
|
+
return String(r.message);
|
|
133
|
+
return null;
|
|
134
|
+
}
|
|
135
|
+
case "clone": {
|
|
136
|
+
const dst = r.destination?.path ?? "unknown";
|
|
137
|
+
const remote = r.remoteFetched ? " (fetched from remote)" : "";
|
|
138
|
+
const over = r.overwritten ? " (overwritten)" : "";
|
|
139
|
+
return `Cloned${remote} → ${dst}${over}`;
|
|
140
|
+
}
|
|
141
|
+
case "submit": {
|
|
142
|
+
const entry = r.entry;
|
|
143
|
+
const pr = r.pr;
|
|
144
|
+
const commands = r.commands ?? [];
|
|
145
|
+
if (r.dryRun) {
|
|
146
|
+
const lines = [
|
|
147
|
+
`Dry run: prepared registry entry ${entry?.name ?? entry?.id ?? "unknown"}`,
|
|
148
|
+
"",
|
|
149
|
+
yamlStringify(entry),
|
|
150
|
+
];
|
|
151
|
+
if (commands.length > 0) {
|
|
152
|
+
lines.push("", "Would run:");
|
|
153
|
+
lines.push(...commands.map((command) => ` ${command}`));
|
|
154
|
+
}
|
|
155
|
+
return lines.join("\n");
|
|
156
|
+
}
|
|
157
|
+
const prUrl = typeof pr?.url === "string" ? pr.url : "unknown";
|
|
158
|
+
const fork = r.fork;
|
|
159
|
+
const cleanupCmd = typeof fork?.cleanupCommand === "string" ? fork.cleanupCommand : undefined;
|
|
160
|
+
const lines = [`Submitted ${entry?.name ?? entry?.id ?? "registry entry"}.`, `PR: ${prUrl}`];
|
|
161
|
+
if (cleanupCmd) {
|
|
162
|
+
lines.push(`\nAfter the PR is merged, clean up the fork with:\n ${cleanupCmd}`);
|
|
163
|
+
}
|
|
164
|
+
return lines.join("\n");
|
|
165
|
+
}
|
|
166
|
+
default:
|
|
167
|
+
return null; // fall through to YAML
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
const initCommand = defineCommand({
|
|
171
|
+
meta: {
|
|
172
|
+
name: "init",
|
|
173
|
+
description: "Initialize Agent-i-Kit's working stash directory and persist stashDir in config",
|
|
174
|
+
},
|
|
175
|
+
args: {
|
|
176
|
+
dir: { type: "string", description: "Custom stash directory path (default: ~/agentikit)" },
|
|
177
|
+
},
|
|
178
|
+
async run({ args }) {
|
|
179
|
+
await runWithJsonErrors(async () => {
|
|
180
|
+
const result = await agentikitInit({ dir: args.dir });
|
|
181
|
+
output("init", result);
|
|
182
|
+
});
|
|
183
|
+
},
|
|
184
|
+
});
|
|
185
|
+
const indexCommand = defineCommand({
|
|
186
|
+
meta: { name: "index", description: "Build search index (incremental by default; --full forces full reindex)" },
|
|
187
|
+
args: {
|
|
188
|
+
full: { type: "boolean", description: "Force full reindex", default: false },
|
|
189
|
+
},
|
|
190
|
+
async run({ args }) {
|
|
191
|
+
await runWithJsonErrors(async () => {
|
|
192
|
+
const result = await agentikitIndex({ full: args.full });
|
|
193
|
+
output("index", result);
|
|
194
|
+
});
|
|
195
|
+
},
|
|
196
|
+
});
|
|
197
|
+
const searchCommand = defineCommand({
|
|
198
|
+
meta: { name: "search", description: "Search the stash" },
|
|
199
|
+
args: {
|
|
200
|
+
query: { type: "positional", description: "Search query", required: false, default: "" },
|
|
201
|
+
type: { type: "string", description: "Asset type filter (tool|skill|command|agent|knowledge|script|any)" },
|
|
202
|
+
limit: { type: "string", description: "Maximum number of results" },
|
|
203
|
+
usage: { type: "string", description: "Usage metadata mode (none|both|item|guide)", default: "both" },
|
|
204
|
+
source: { type: "string", description: "Search source (local|registry|both)", default: "local" },
|
|
205
|
+
},
|
|
206
|
+
async run({ args }) {
|
|
207
|
+
await runWithJsonErrors(async () => {
|
|
208
|
+
const type = args.type;
|
|
209
|
+
const limit = args.limit ? parseInt(args.limit, 10) : undefined;
|
|
210
|
+
const usage = parseSearchUsageMode(args.usage);
|
|
211
|
+
const source = parseSearchSource(args.source);
|
|
212
|
+
const result = await agentikitSearch({ query: args.query, type, limit, usage, source });
|
|
213
|
+
output("search", result);
|
|
214
|
+
});
|
|
215
|
+
},
|
|
216
|
+
});
|
|
217
|
+
const addCommand = defineCommand({
|
|
218
|
+
meta: { name: "add", description: "Install a kit from npm, GitHub, any git host, or a local directory" },
|
|
219
|
+
args: {
|
|
220
|
+
ref: {
|
|
221
|
+
type: "positional",
|
|
222
|
+
description: "Registry ref (npm package, owner/repo, git URL, or local directory)",
|
|
223
|
+
required: true,
|
|
224
|
+
},
|
|
225
|
+
},
|
|
226
|
+
async run({ args }) {
|
|
227
|
+
await runWithJsonErrors(async () => {
|
|
228
|
+
const result = await agentikitAdd({ ref: args.ref });
|
|
229
|
+
output("add", result);
|
|
230
|
+
});
|
|
231
|
+
},
|
|
232
|
+
});
|
|
233
|
+
const listCommand = defineCommand({
|
|
234
|
+
meta: { name: "list", description: "List installed registry packages from config" },
|
|
235
|
+
async run() {
|
|
236
|
+
await runWithJsonErrors(async () => {
|
|
237
|
+
const result = await agentikitList();
|
|
238
|
+
output("list", result);
|
|
239
|
+
});
|
|
240
|
+
},
|
|
241
|
+
});
|
|
242
|
+
const removeCommand = defineCommand({
|
|
243
|
+
meta: { name: "remove", description: "Remove an installed registry package by id or ref" },
|
|
244
|
+
args: {
|
|
245
|
+
target: { type: "positional", description: "Installed target (id or ref)", required: true },
|
|
246
|
+
},
|
|
247
|
+
async run({ args }) {
|
|
248
|
+
await runWithJsonErrors(async () => {
|
|
249
|
+
const result = await agentikitRemove({ target: args.target });
|
|
250
|
+
output("remove", result);
|
|
251
|
+
});
|
|
252
|
+
},
|
|
253
|
+
});
|
|
254
|
+
const updateCommand = defineCommand({
|
|
255
|
+
meta: { name: "update", description: "Update one or all installed registry packages" },
|
|
256
|
+
args: {
|
|
257
|
+
target: { type: "positional", description: "Installed target (id or ref)", required: false },
|
|
258
|
+
all: { type: "boolean", description: "Update all installed entries", default: false },
|
|
259
|
+
force: { type: "boolean", description: "Force fresh download even if version is unchanged", default: false },
|
|
260
|
+
},
|
|
261
|
+
async run({ args }) {
|
|
262
|
+
await runWithJsonErrors(async () => {
|
|
263
|
+
const result = await agentikitUpdate({ target: args.target, all: args.all, force: args.force });
|
|
264
|
+
output("update", result);
|
|
265
|
+
});
|
|
266
|
+
},
|
|
267
|
+
});
|
|
268
|
+
const upgradeCommand = defineCommand({
|
|
269
|
+
meta: { name: "upgrade", description: "Upgrade akm to the latest release" },
|
|
270
|
+
args: {
|
|
271
|
+
check: { type: "boolean", description: "Check for updates without installing", default: false },
|
|
272
|
+
force: { type: "boolean", description: "Force upgrade even if on latest", default: false },
|
|
273
|
+
},
|
|
274
|
+
async run({ args }) {
|
|
275
|
+
await runWithJsonErrors(async () => {
|
|
276
|
+
const check = await checkForUpdate(pkgVersion);
|
|
277
|
+
if (args.check) {
|
|
278
|
+
output("upgrade", check);
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
const result = await performUpgrade(check, { force: args.force });
|
|
282
|
+
output("upgrade", result);
|
|
283
|
+
});
|
|
284
|
+
},
|
|
285
|
+
});
|
|
286
|
+
const showCommand = defineCommand({
|
|
287
|
+
meta: { name: "show", description: "Show a stash asset by ref (e.g. agent:bunjs-typescript-coder.md)" },
|
|
288
|
+
args: {
|
|
289
|
+
ref: { type: "positional", description: "Asset ref (type:name)", required: true },
|
|
290
|
+
view: { type: "string", description: "Knowledge view mode (full|toc|frontmatter|section|lines)" },
|
|
291
|
+
heading: { type: "string", description: "Section heading (for --view section)" },
|
|
292
|
+
start: { type: "string", description: "Start line (for --view lines)" },
|
|
293
|
+
end: { type: "string", description: "End line (for --view lines)" },
|
|
294
|
+
},
|
|
295
|
+
async run({ args }) {
|
|
296
|
+
await runWithJsonErrors(async () => {
|
|
297
|
+
let view;
|
|
298
|
+
if (args.view) {
|
|
299
|
+
switch (args.view) {
|
|
300
|
+
case "section":
|
|
301
|
+
view = { mode: "section", heading: args.heading ?? "" };
|
|
302
|
+
break;
|
|
303
|
+
case "lines":
|
|
304
|
+
view = {
|
|
305
|
+
mode: "lines",
|
|
306
|
+
start: Number(args.start ?? "1"),
|
|
307
|
+
end: args.end ? parseInt(args.end, 10) : Number.MAX_SAFE_INTEGER,
|
|
308
|
+
};
|
|
309
|
+
break;
|
|
310
|
+
case "toc":
|
|
311
|
+
case "frontmatter":
|
|
312
|
+
case "full":
|
|
313
|
+
view = { mode: args.view };
|
|
314
|
+
break;
|
|
315
|
+
default:
|
|
316
|
+
throw new UsageError(`Unknown view mode: ${args.view}. Expected one of: full|toc|frontmatter|section|lines`);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
const result = await agentikitShow({ ref: args.ref, view });
|
|
320
|
+
output("show", result);
|
|
321
|
+
});
|
|
322
|
+
},
|
|
323
|
+
});
|
|
324
|
+
const configCommand = defineCommand({
|
|
325
|
+
meta: { name: "config", description: "Show configuration, get/set keys, and manage embedding/LLM providers" },
|
|
326
|
+
args: {
|
|
327
|
+
list: { type: "boolean", description: "List current configuration with effective defaults", default: false },
|
|
328
|
+
get: { type: "string", description: "Get a configuration value by key" },
|
|
329
|
+
unset: { type: "string", description: "Unset an optional configuration key or whole embedding/llm section" },
|
|
330
|
+
set: { type: "string", description: "Back-compat alias for updating a key (key=value format)" },
|
|
331
|
+
},
|
|
332
|
+
subCommands: {
|
|
333
|
+
path: defineCommand({
|
|
334
|
+
meta: { name: "path", description: "Show paths to config, stash, cache, and index" },
|
|
335
|
+
args: {
|
|
336
|
+
all: { type: "boolean", description: "Show all paths (config, stash, cache, index)", default: false },
|
|
337
|
+
},
|
|
338
|
+
run({ args }) {
|
|
339
|
+
return runWithJsonErrors(() => {
|
|
340
|
+
const configPath = getConfigPath();
|
|
341
|
+
if (args.all) {
|
|
342
|
+
let stashDir;
|
|
343
|
+
try {
|
|
344
|
+
stashDir = resolveStashDir({ readOnly: true });
|
|
345
|
+
}
|
|
346
|
+
catch {
|
|
347
|
+
stashDir = getDefaultStashDir() + " (not initialized)";
|
|
348
|
+
}
|
|
349
|
+
const cacheDir = getCacheDir();
|
|
350
|
+
const result = {
|
|
351
|
+
config: configPath,
|
|
352
|
+
stash: stashDir,
|
|
353
|
+
cache: cacheDir,
|
|
354
|
+
index: getDbPath(),
|
|
355
|
+
};
|
|
356
|
+
output("config", result);
|
|
357
|
+
}
|
|
358
|
+
else {
|
|
359
|
+
console.log(configPath);
|
|
360
|
+
}
|
|
361
|
+
});
|
|
362
|
+
},
|
|
363
|
+
}),
|
|
364
|
+
list: defineCommand({
|
|
365
|
+
meta: { name: "list", description: "List current configuration with effective embedding/LLM settings" },
|
|
366
|
+
run() {
|
|
367
|
+
return runWithJsonErrors(() => {
|
|
368
|
+
output("config", listConfig(loadConfig()));
|
|
369
|
+
});
|
|
370
|
+
},
|
|
371
|
+
}),
|
|
372
|
+
get: defineCommand({
|
|
373
|
+
meta: { name: "get", description: "Get a configuration value by key" },
|
|
374
|
+
args: {
|
|
375
|
+
key: { type: "positional", required: true, description: "Config key (for example: embedding.provider)" },
|
|
376
|
+
},
|
|
377
|
+
run({ args }) {
|
|
378
|
+
return runWithJsonErrors(() => {
|
|
379
|
+
output("config", getConfigValue(loadConfig(), args.key));
|
|
380
|
+
});
|
|
381
|
+
},
|
|
382
|
+
}),
|
|
383
|
+
set: defineCommand({
|
|
384
|
+
meta: { name: "set", description: "Set a configuration value by key" },
|
|
385
|
+
args: {
|
|
386
|
+
key: { type: "positional", required: true, description: "Config key (for example: llm.temperature)" },
|
|
387
|
+
value: { type: "positional", required: true, description: "Config value" },
|
|
388
|
+
},
|
|
389
|
+
run({ args }) {
|
|
390
|
+
return runWithJsonErrors(() => {
|
|
391
|
+
const updated = setConfigValue(loadConfig(), args.key, args.value);
|
|
392
|
+
saveConfig(updated);
|
|
393
|
+
output("config", listConfig(updated));
|
|
394
|
+
});
|
|
395
|
+
},
|
|
396
|
+
}),
|
|
397
|
+
unset: defineCommand({
|
|
398
|
+
meta: { name: "unset", description: "Unset an optional configuration key or whole embedding/llm section" },
|
|
399
|
+
args: {
|
|
400
|
+
key: { type: "positional", required: true, description: "Config key to unset" },
|
|
401
|
+
},
|
|
402
|
+
run({ args }) {
|
|
403
|
+
return runWithJsonErrors(() => {
|
|
404
|
+
const updated = unsetConfigValue(loadConfig(), args.key);
|
|
405
|
+
saveConfig(updated);
|
|
406
|
+
output("config", listConfig(updated));
|
|
407
|
+
});
|
|
408
|
+
},
|
|
409
|
+
}),
|
|
410
|
+
providers: defineCommand({
|
|
411
|
+
meta: { name: "providers", description: "List available embedding or LLM providers" },
|
|
412
|
+
args: {
|
|
413
|
+
scope: { type: "positional", required: true, description: "Provider scope: embedding or llm" },
|
|
414
|
+
},
|
|
415
|
+
run({ args }) {
|
|
416
|
+
return runWithJsonErrors(() => {
|
|
417
|
+
const scope = parseProviderScope(args.scope);
|
|
418
|
+
output("config", listProviders(scope, loadConfig()));
|
|
419
|
+
});
|
|
420
|
+
},
|
|
421
|
+
}),
|
|
422
|
+
use: defineCommand({
|
|
423
|
+
meta: { name: "use", description: "Switch the default embedding or LLM provider" },
|
|
424
|
+
args: {
|
|
425
|
+
scope: { type: "positional", required: true, description: "Provider scope: embedding or llm" },
|
|
426
|
+
provider: { type: "positional", required: true, description: "Provider name" },
|
|
427
|
+
},
|
|
428
|
+
run({ args }) {
|
|
429
|
+
return runWithJsonErrors(() => {
|
|
430
|
+
const scope = parseProviderScope(args.scope);
|
|
431
|
+
const updated = useProvider(loadConfig(), scope, args.provider);
|
|
432
|
+
saveConfig(updated);
|
|
433
|
+
output("config", listConfig(updated));
|
|
434
|
+
});
|
|
435
|
+
},
|
|
436
|
+
}),
|
|
437
|
+
},
|
|
438
|
+
run({ args }) {
|
|
439
|
+
return runWithJsonErrors(() => {
|
|
440
|
+
if (hasConfigSubcommand(args))
|
|
441
|
+
return;
|
|
442
|
+
if (args.list) {
|
|
443
|
+
output("config", listConfig(loadConfig()));
|
|
444
|
+
return;
|
|
445
|
+
}
|
|
446
|
+
if (args.get) {
|
|
447
|
+
output("config", getConfigValue(loadConfig(), args.get));
|
|
448
|
+
return;
|
|
449
|
+
}
|
|
450
|
+
if (args.unset) {
|
|
451
|
+
const updated = unsetConfigValue(loadConfig(), args.unset);
|
|
452
|
+
saveConfig(updated);
|
|
453
|
+
output("config", listConfig(updated));
|
|
454
|
+
return;
|
|
455
|
+
}
|
|
456
|
+
if (args.set) {
|
|
457
|
+
const eqIndex = args.set.indexOf("=");
|
|
458
|
+
if (eqIndex === -1) {
|
|
459
|
+
throw new UsageError("--set expects key=value format");
|
|
460
|
+
}
|
|
461
|
+
const key = args.set.slice(0, eqIndex);
|
|
462
|
+
const value = args.set.slice(eqIndex + 1);
|
|
463
|
+
const partial = parseConfigValue(key, value);
|
|
464
|
+
const config = { ...loadConfig(), ...partial };
|
|
465
|
+
saveConfig(config);
|
|
466
|
+
output("config", listConfig(config));
|
|
467
|
+
}
|
|
468
|
+
else {
|
|
469
|
+
output("config", listConfig(loadConfig()));
|
|
470
|
+
}
|
|
471
|
+
});
|
|
472
|
+
},
|
|
473
|
+
});
|
|
474
|
+
const cloneCommand = defineCommand({
|
|
475
|
+
meta: {
|
|
476
|
+
name: "clone",
|
|
477
|
+
description: "Clone an asset from any stash source into the working stash or a custom destination",
|
|
478
|
+
},
|
|
479
|
+
args: {
|
|
480
|
+
ref: { type: "positional", description: "Asset ref (e.g. @installed:pkg/tool:script.sh)", required: true },
|
|
481
|
+
name: { type: "string", description: "New name for the cloned asset" },
|
|
482
|
+
force: { type: "boolean", description: "Overwrite if asset already exists in working stash", default: false },
|
|
483
|
+
dest: { type: "string", description: "Destination directory (default: working stash)" },
|
|
484
|
+
},
|
|
485
|
+
async run({ args }) {
|
|
486
|
+
await runWithJsonErrors(async () => {
|
|
487
|
+
const result = await agentikitClone({
|
|
488
|
+
sourceRef: args.ref,
|
|
489
|
+
newName: args.name,
|
|
490
|
+
force: args.force,
|
|
491
|
+
dest: args.dest,
|
|
492
|
+
});
|
|
493
|
+
output("clone", result);
|
|
494
|
+
});
|
|
495
|
+
},
|
|
496
|
+
});
|
|
497
|
+
const submitCommand = defineCommand({
|
|
498
|
+
meta: { name: "submit", description: "Submit a kit to agentikit-registry by opening a pull request" },
|
|
499
|
+
args: {
|
|
500
|
+
ref: {
|
|
501
|
+
type: "positional",
|
|
502
|
+
description: "Public ref to submit (npm package, owner/repo, or local kit directory)",
|
|
503
|
+
required: false,
|
|
504
|
+
},
|
|
505
|
+
name: { type: "string", description: "Display name for the registry entry" },
|
|
506
|
+
description: { type: "string", description: "Short description for the registry entry" },
|
|
507
|
+
tags: { type: "string", description: "Comma-separated tags" },
|
|
508
|
+
"asset-types": { type: "string", description: "Comma-separated asset types" },
|
|
509
|
+
author: { type: "string", description: "Author name" },
|
|
510
|
+
license: { type: "string", description: "License identifier" },
|
|
511
|
+
homepage: { type: "string", description: "Homepage URL" },
|
|
512
|
+
"dry-run": {
|
|
513
|
+
type: "boolean",
|
|
514
|
+
description: "Preview the entry and gh commands without creating a pull request",
|
|
515
|
+
default: false,
|
|
516
|
+
},
|
|
517
|
+
"cleanup-fork": {
|
|
518
|
+
type: "boolean",
|
|
519
|
+
description: "Show the fork cleanup command after the pull request is created (run it after the PR is merged)",
|
|
520
|
+
default: false,
|
|
521
|
+
},
|
|
522
|
+
},
|
|
523
|
+
async run({ args }) {
|
|
524
|
+
await runWithJsonErrors(async () => {
|
|
525
|
+
const result = await agentikitSubmit({
|
|
526
|
+
ref: args.ref,
|
|
527
|
+
name: args.name,
|
|
528
|
+
description: args.description,
|
|
529
|
+
tags: args.tags,
|
|
530
|
+
assetTypes: args["asset-types"],
|
|
531
|
+
author: args.author,
|
|
532
|
+
license: args.license,
|
|
533
|
+
homepage: args.homepage,
|
|
534
|
+
dryRun: args["dry-run"],
|
|
535
|
+
cleanupFork: args["cleanup-fork"],
|
|
536
|
+
progress: isJsonMode() ? undefined : (message) => console.error(`• ${message}`),
|
|
537
|
+
});
|
|
538
|
+
output("submit", result);
|
|
539
|
+
});
|
|
540
|
+
},
|
|
541
|
+
});
|
|
542
|
+
const sourcesCommand = defineCommand({
|
|
543
|
+
meta: { name: "sources", description: "List all stash search paths and their status" },
|
|
544
|
+
run() {
|
|
545
|
+
return runWithJsonErrors(() => {
|
|
546
|
+
const sources = resolveStashSources();
|
|
547
|
+
output("sources", { sources });
|
|
548
|
+
});
|
|
549
|
+
},
|
|
550
|
+
});
|
|
551
|
+
const main = defineCommand({
|
|
552
|
+
meta: {
|
|
553
|
+
name: "akm",
|
|
554
|
+
version: pkgVersion,
|
|
555
|
+
description: "CLI tool to search, open, and manage assets from Agent-i-Kit stash.",
|
|
556
|
+
},
|
|
557
|
+
args: {
|
|
558
|
+
json: { type: "boolean", description: "Output in JSON format", default: false },
|
|
559
|
+
quiet: { type: "boolean", alias: "q", description: "Suppress stderr warnings", default: false },
|
|
560
|
+
},
|
|
561
|
+
subCommands: {
|
|
562
|
+
init: initCommand,
|
|
563
|
+
index: indexCommand,
|
|
564
|
+
add: addCommand,
|
|
565
|
+
list: listCommand,
|
|
566
|
+
remove: removeCommand,
|
|
567
|
+
update: updateCommand,
|
|
568
|
+
upgrade: upgradeCommand,
|
|
569
|
+
search: searchCommand,
|
|
570
|
+
show: showCommand,
|
|
571
|
+
clone: cloneCommand,
|
|
572
|
+
submit: submitCommand,
|
|
573
|
+
sources: sourcesCommand,
|
|
574
|
+
config: configCommand,
|
|
575
|
+
},
|
|
576
|
+
});
|
|
577
|
+
const SEARCH_USAGE_MODES = ["none", "both", "item", "guide"];
|
|
578
|
+
const SEARCH_SOURCES = ["local", "registry", "both"];
|
|
579
|
+
const CONFIG_SUBCOMMAND_SET = new Set(["path", "list", "get", "set", "unset", "providers", "use"]);
|
|
580
|
+
// citty reads process.argv directly and does not accept a custom argv array,
|
|
581
|
+
// so we must replace process.argv with the normalized version before runMain.
|
|
582
|
+
process.argv = normalizeConfigArgv(process.argv);
|
|
583
|
+
runMain(main);
|
|
584
|
+
function parseSearchUsageMode(value) {
|
|
585
|
+
if (SEARCH_USAGE_MODES.includes(value))
|
|
586
|
+
return value;
|
|
587
|
+
throw new UsageError(`Invalid value for --usage: ${value}. Expected one of: ${SEARCH_USAGE_MODES.join("|")}`);
|
|
588
|
+
}
|
|
589
|
+
function parseSearchSource(value) {
|
|
590
|
+
if (SEARCH_SOURCES.includes(value))
|
|
591
|
+
return value;
|
|
592
|
+
throw new UsageError(`Invalid value for --source: ${value}. Expected one of: ${SEARCH_SOURCES.join("|")}`);
|
|
593
|
+
}
|
|
594
|
+
// ── Exit codes ──────────────────────────────────────────────────────────────
|
|
595
|
+
const EXIT_GENERAL = 1;
|
|
596
|
+
const EXIT_USAGE = 2;
|
|
597
|
+
const EXIT_CONFIG = 78;
|
|
598
|
+
function classifyExitCode(error) {
|
|
599
|
+
if (error instanceof UsageError)
|
|
600
|
+
return EXIT_USAGE;
|
|
601
|
+
if (error instanceof ConfigError)
|
|
602
|
+
return EXIT_CONFIG;
|
|
603
|
+
if (error instanceof NotFoundError)
|
|
604
|
+
return EXIT_GENERAL;
|
|
605
|
+
return EXIT_GENERAL;
|
|
606
|
+
}
|
|
607
|
+
async function runWithJsonErrors(fn) {
|
|
608
|
+
try {
|
|
609
|
+
// Apply --quiet flag early so warnings inside the command are suppressed
|
|
610
|
+
if (process.argv.includes("--quiet") || process.argv.includes("-q")) {
|
|
611
|
+
setQuiet(true);
|
|
612
|
+
}
|
|
613
|
+
await fn();
|
|
614
|
+
}
|
|
615
|
+
catch (error) {
|
|
616
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
617
|
+
const hint = buildHint(message);
|
|
618
|
+
const exitCode = classifyExitCode(error);
|
|
619
|
+
console.error(JSON.stringify({ ok: false, error: message, hint }, null, 2));
|
|
620
|
+
process.exit(exitCode);
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
function buildHint(message) {
|
|
624
|
+
if (message.includes("No stash directory found"))
|
|
625
|
+
return "Run `akm init` to create the default stash, or set stashDir in your config.";
|
|
626
|
+
if (message.includes("Either <target> or --all is required"))
|
|
627
|
+
return "Use `akm update --all` or pass a target like `akm update npm:@scope/pkg`.";
|
|
628
|
+
if (message.includes("Specify either <target> or --all"))
|
|
629
|
+
return "Use only one: a positional target or `--all`.";
|
|
630
|
+
if (message.includes("No installed registry entry matched target"))
|
|
631
|
+
return "Run `akm list` to view installed ids/refs, then retry with one of those values.";
|
|
632
|
+
if (message.includes("remote package fetched but asset not found"))
|
|
633
|
+
return "The remote package was fetched but doesn't contain the requested asset. Check the asset name and type.";
|
|
634
|
+
if (message.includes("Invalid value for --source"))
|
|
635
|
+
return "Pick one of: local, registry, both.";
|
|
636
|
+
if (message.includes("Invalid value for --usage"))
|
|
637
|
+
return "Pick one of: none, both, item, guide.";
|
|
638
|
+
if (message.includes("gh CLI is required"))
|
|
639
|
+
return buildGhInstallHint();
|
|
640
|
+
if (message.includes("gh CLI is not authenticated"))
|
|
641
|
+
return "Run `gh auth login` and then retry `akm submit`.";
|
|
642
|
+
if (message.includes("not publicly accessible"))
|
|
643
|
+
return "Check that the npm package is published or the GitHub repository is public, then retry.";
|
|
644
|
+
if (message.includes("already exists in agentikit-registry"))
|
|
645
|
+
return "Update the existing registry entry instead of creating a duplicate, or choose a different public ref.";
|
|
646
|
+
if (message.includes("Unable to infer a public npm or GitHub ref") ||
|
|
647
|
+
message.includes("Unable to infer a publicly accessible npm package or GitHub repository")) {
|
|
648
|
+
return "Run `akm submit <package-or-owner/repo>` explicitly, or add name/repository metadata to package.json.";
|
|
649
|
+
}
|
|
650
|
+
if (message.includes("expected JSON object with endpoint and model")) {
|
|
651
|
+
return 'Quote JSON values in your shell, for example: akm config set embedding \'{"endpoint":"http://localhost:11434/v1/embeddings","model":"nomic-embed-text"}\'.';
|
|
652
|
+
}
|
|
653
|
+
return undefined;
|
|
654
|
+
}
|
|
655
|
+
function buildGhInstallHint() {
|
|
656
|
+
if (process.platform === "darwin")
|
|
657
|
+
return "Install GitHub CLI with Homebrew: `brew install gh`.";
|
|
658
|
+
if (process.platform === "win32")
|
|
659
|
+
return "Install GitHub CLI with winget: `winget install --id GitHub.cli`.";
|
|
660
|
+
return "Install GitHub CLI from https://cli.github.com/ or your package manager (for Debian/Ubuntu: `sudo apt install gh`).";
|
|
661
|
+
}
|
|
662
|
+
function parseProviderScope(value) {
|
|
663
|
+
if (value === "embedding" || value === "llm")
|
|
664
|
+
return value;
|
|
665
|
+
throw new UsageError(`Invalid provider scope: ${value}. Expected one of: embedding|llm`);
|
|
666
|
+
}
|
|
667
|
+
function hasConfigSubcommand(args) {
|
|
668
|
+
const command = Array.isArray(args._) ? args._[0] : undefined;
|
|
669
|
+
return typeof command === "string" && CONFIG_SUBCOMMAND_SET.has(command);
|
|
670
|
+
}
|
|
671
|
+
/**
|
|
672
|
+
* Normalize argv before citty parses it so git-style config forms like
|
|
673
|
+
* `akm config llm.maxTokens 512` and `akm config --get llm.maxTokens`
|
|
674
|
+
* are normalized into the existing config subcommands.
|
|
675
|
+
*
|
|
676
|
+
* Returns a new array; the input is never modified.
|
|
677
|
+
*/
|
|
678
|
+
function normalizeConfigArgv(argv) {
|
|
679
|
+
// Global flags (like --json, --quiet) should not be treated as config subcommand arguments.
|
|
680
|
+
// We strip them from the analysis portion, normalize, then re-append them.
|
|
681
|
+
const GLOBAL_FLAGS = new Set(["--json", "--quiet", "-q"]);
|
|
682
|
+
const globalFlags = argv.slice(3).filter((a) => GLOBAL_FLAGS.has(a));
|
|
683
|
+
const configArgs = argv.slice(3).filter((a) => !GLOBAL_FLAGS.has(a));
|
|
684
|
+
const [command, argAfterCommand, argAfterKey, ...rest] = [argv[2], ...configArgs];
|
|
685
|
+
if (command !== "config")
|
|
686
|
+
return argv;
|
|
687
|
+
if (!argAfterCommand)
|
|
688
|
+
return argv;
|
|
689
|
+
const prefix = argv.slice(0, 3);
|
|
690
|
+
const buildResult = (...newArgs) => [...prefix, ...newArgs, ...globalFlags];
|
|
691
|
+
if (argAfterCommand === "--list") {
|
|
692
|
+
return buildResult("list");
|
|
693
|
+
}
|
|
694
|
+
if (argAfterCommand === "--get" && argAfterKey) {
|
|
695
|
+
return buildResult("get", argAfterKey, ...rest);
|
|
696
|
+
}
|
|
697
|
+
if (argAfterCommand === "--unset" && argAfterKey) {
|
|
698
|
+
return buildResult("unset", argAfterKey, ...rest);
|
|
699
|
+
}
|
|
700
|
+
if (argAfterCommand.startsWith("-"))
|
|
701
|
+
return argv;
|
|
702
|
+
if (CONFIG_SUBCOMMAND_SET.has(argAfterCommand))
|
|
703
|
+
return argv;
|
|
704
|
+
// A single arg after `config` behaves like `git config <key>` and reads the value.
|
|
705
|
+
if (argAfterKey === undefined) {
|
|
706
|
+
return buildResult("get", argAfterCommand);
|
|
707
|
+
}
|
|
708
|
+
return buildResult("set", argAfterCommand, argAfterKey, ...rest);
|
|
709
|
+
}
|