@kitnai/cli 0.1.16 → 0.1.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -4
- package/dist/index.js +208 -126
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -27,14 +27,27 @@ pnpm dlx @kitnai/cli init
|
|
|
27
27
|
Initialize kitn in your project. Creates `kitn.json`, installs the core engine and Hono routes, and sets up tsconfig path aliases.
|
|
28
28
|
|
|
29
29
|
```bash
|
|
30
|
+
# Interactive (prompts for runtime and base directory)
|
|
30
31
|
kitn init
|
|
32
|
+
|
|
33
|
+
# Non-interactive with flags
|
|
34
|
+
kitn init --runtime bun --base src/ai
|
|
35
|
+
|
|
36
|
+
# Accept all defaults (runtime=bun, base=src/ai)
|
|
37
|
+
kitn init -y
|
|
31
38
|
```
|
|
32
39
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
40
|
+
**Flags:**
|
|
41
|
+
|
|
42
|
+
| Flag | Description |
|
|
43
|
+
|------|-------------|
|
|
44
|
+
| `-r, --runtime <runtime>` | Runtime to use (`bun`, `node`, `deno`) — skips runtime prompt |
|
|
45
|
+
| `-b, --base <path>` | Base directory for components (default: `src/ai`) — skips path prompt |
|
|
46
|
+
| `-y, --yes` | Accept all defaults without prompting |
|
|
47
|
+
|
|
48
|
+
When flags are provided, the corresponding prompts are skipped. This enables scripting and CI usage.
|
|
36
49
|
|
|
37
|
-
After
|
|
50
|
+
After setup, the CLI automatically installs the core engine and HTTP routes into your project.
|
|
38
51
|
|
|
39
52
|
### `kitn add [components...]`
|
|
40
53
|
|
|
@@ -180,6 +193,16 @@ kitn build
|
|
|
180
193
|
kitn build src/components --output dist/r
|
|
181
194
|
```
|
|
182
195
|
|
|
196
|
+
### `kitn check`
|
|
197
|
+
|
|
198
|
+
Check for CLI updates.
|
|
199
|
+
|
|
200
|
+
```bash
|
|
201
|
+
kitn check
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
Shows the current version and whether a newer version is available on npm.
|
|
205
|
+
|
|
183
206
|
### `kitn registry`
|
|
184
207
|
|
|
185
208
|
Manage component registries.
|
package/dist/index.js
CHANGED
|
@@ -9,6 +9,86 @@ var __export = (target, all) => {
|
|
|
9
9
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
10
|
};
|
|
11
11
|
|
|
12
|
+
// src/utils/update-check.ts
|
|
13
|
+
import { readFile, writeFile, mkdir } from "fs/promises";
|
|
14
|
+
import { join } from "path";
|
|
15
|
+
import { homedir } from "os";
|
|
16
|
+
import pc from "picocolors";
|
|
17
|
+
async function readCache() {
|
|
18
|
+
try {
|
|
19
|
+
const raw = await readFile(CACHE_FILE, "utf-8");
|
|
20
|
+
return JSON.parse(raw);
|
|
21
|
+
} catch {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
async function writeCache(entry) {
|
|
26
|
+
try {
|
|
27
|
+
await mkdir(CACHE_DIR, { recursive: true });
|
|
28
|
+
await writeFile(CACHE_FILE, JSON.stringify(entry));
|
|
29
|
+
} catch {
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
async function fetchLatestVersion() {
|
|
33
|
+
try {
|
|
34
|
+
const controller = new AbortController();
|
|
35
|
+
const timeout = setTimeout(() => controller.abort(), 3e3);
|
|
36
|
+
const res = await fetch("https://registry.npmjs.org/@kitnai/cli/latest", {
|
|
37
|
+
signal: controller.signal
|
|
38
|
+
});
|
|
39
|
+
clearTimeout(timeout);
|
|
40
|
+
if (!res.ok) return null;
|
|
41
|
+
const data = await res.json();
|
|
42
|
+
return data.version ?? null;
|
|
43
|
+
} catch {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function isNewer(latest, current) {
|
|
48
|
+
const [lMaj, lMin, lPat] = latest.split(".").map(Number);
|
|
49
|
+
const [cMaj, cMin, cPat] = current.split(".").map(Number);
|
|
50
|
+
if (lMaj !== cMaj) return lMaj > cMaj;
|
|
51
|
+
if (lMin !== cMin) return lMin > cMin;
|
|
52
|
+
return lPat > cPat;
|
|
53
|
+
}
|
|
54
|
+
function startUpdateCheck(currentVersion) {
|
|
55
|
+
let message = "";
|
|
56
|
+
const check = (async () => {
|
|
57
|
+
const cache = await readCache();
|
|
58
|
+
let latest = null;
|
|
59
|
+
if (cache && Date.now() - cache.checkedAt < CHECK_INTERVAL) {
|
|
60
|
+
latest = cache.latest;
|
|
61
|
+
} else {
|
|
62
|
+
latest = await fetchLatestVersion();
|
|
63
|
+
if (latest) {
|
|
64
|
+
await writeCache({ latest, checkedAt: Date.now() });
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
if (latest && isNewer(latest, currentVersion)) {
|
|
68
|
+
message = [
|
|
69
|
+
"",
|
|
70
|
+
pc.yellow(` Update available: ${pc.dim(currentVersion)} \u2192 ${pc.green(latest)}`),
|
|
71
|
+
pc.dim(` Run ${pc.cyan("npx @kitnai/cli@latest")} or ${pc.cyan("npm i -g @kitnai/cli")}`),
|
|
72
|
+
""
|
|
73
|
+
].join("\n");
|
|
74
|
+
}
|
|
75
|
+
})();
|
|
76
|
+
check.catch(() => {
|
|
77
|
+
});
|
|
78
|
+
return () => {
|
|
79
|
+
if (message) process.stderr.write(message);
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
var CACHE_DIR, CACHE_FILE, CHECK_INTERVAL;
|
|
83
|
+
var init_update_check = __esm({
|
|
84
|
+
"src/utils/update-check.ts"() {
|
|
85
|
+
"use strict";
|
|
86
|
+
CACHE_DIR = join(homedir(), ".kitn");
|
|
87
|
+
CACHE_FILE = join(CACHE_DIR, "update-check.json");
|
|
88
|
+
CHECK_INTERVAL = 60 * 60 * 1e3;
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
|
|
12
92
|
// src/utils/config.ts
|
|
13
93
|
import { readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
|
|
14
94
|
import { join as join2 } from "path";
|
|
@@ -714,6 +794,13 @@ async function addCommand(components, opts) {
|
|
|
714
794
|
for (const item of resolved) {
|
|
715
795
|
if (item.dependencies) allDeps.push(...item.dependencies);
|
|
716
796
|
if (item.devDependencies) allDevDeps.push(...item.devDependencies);
|
|
797
|
+
const existingInstall = (config.installed ?? {})[item.name];
|
|
798
|
+
if (existingInstall && item.type === "kitn:package") {
|
|
799
|
+
const allContent = item.files.map((f) => f.content).join("\n");
|
|
800
|
+
if (contentHash(allContent) === existingInstall.hash) {
|
|
801
|
+
continue;
|
|
802
|
+
}
|
|
803
|
+
}
|
|
717
804
|
if (item.type === "kitn:package") {
|
|
718
805
|
const baseDir2 = config.aliases.base ?? "src/ai";
|
|
719
806
|
for (const file of item.files) {
|
|
@@ -899,7 +986,7 @@ async function addCommand(components, opts) {
|
|
|
899
986
|
}
|
|
900
987
|
}
|
|
901
988
|
if (created.length > 0) {
|
|
902
|
-
p2.log.success(`
|
|
989
|
+
p2.log.success(`Added ${created.length} file(s):
|
|
903
990
|
` + created.map((f) => ` ${pc3.green("+")} ${f}`).join("\n"));
|
|
904
991
|
}
|
|
905
992
|
if (updated.length > 0) {
|
|
@@ -917,13 +1004,14 @@ async function addCommand(components, opts) {
|
|
|
917
1004
|
p2.log.info(`${pc3.bold(item.name)}: ${item.docs}`);
|
|
918
1005
|
}
|
|
919
1006
|
}
|
|
920
|
-
const
|
|
1007
|
+
const resolvedNames = new Set(resolved.map((r) => r.name));
|
|
1008
|
+
const projectInstalled = new Set(Object.keys(config.installed ?? {}));
|
|
921
1009
|
const hints = [];
|
|
922
|
-
|
|
1010
|
+
const fw = config.framework ?? "hono";
|
|
1011
|
+
if (resolvedNames.has("core") && !resolvedNames.has(fw) && !projectInstalled.has(fw)) {
|
|
923
1012
|
hints.push(`Run ${pc3.cyan(`kitn add routes`)} to install the HTTP adapter.`);
|
|
924
1013
|
}
|
|
925
|
-
|
|
926
|
-
if (installedNames.has(fw) || installedNames.has("core") && installedNames.has(fw)) {
|
|
1014
|
+
if (resolvedNames.has(fw)) {
|
|
927
1015
|
hints.push(`Configure your AI provider in ${pc3.bold(baseDir + "/plugin.ts")}, then add to your server:`);
|
|
928
1016
|
hints.push("");
|
|
929
1017
|
hints.push(pc3.dim(` import { ai } from "./${baseDir.replace(/^src\//, "")}/plugin";`));
|
|
@@ -964,43 +1052,66 @@ import * as p3 from "@clack/prompts";
|
|
|
964
1052
|
import pc4 from "picocolors";
|
|
965
1053
|
import { mkdir as mkdir4, writeFile as writeFile7 } from "fs/promises";
|
|
966
1054
|
import { join as join8 } from "path";
|
|
967
|
-
async function initCommand() {
|
|
1055
|
+
async function initCommand(opts = {}) {
|
|
968
1056
|
p3.intro(pc4.bgCyan(pc4.black(" kitn init ")));
|
|
969
1057
|
const cwd = process.cwd();
|
|
970
1058
|
const existing = await readConfig(cwd);
|
|
971
1059
|
if (existing) {
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
1060
|
+
if (opts.yes) {
|
|
1061
|
+
p3.log.warn("kitn.json already exists \u2014 overwriting (--yes).");
|
|
1062
|
+
} else {
|
|
1063
|
+
p3.log.warn("kitn.json already exists in this directory.");
|
|
1064
|
+
const shouldContinue = await p3.confirm({
|
|
1065
|
+
message: "Overwrite existing configuration?",
|
|
1066
|
+
initialValue: false
|
|
1067
|
+
});
|
|
1068
|
+
if (p3.isCancel(shouldContinue) || !shouldContinue) {
|
|
1069
|
+
p3.cancel("Init cancelled.");
|
|
1070
|
+
process.exit(0);
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
1074
|
+
let runtime;
|
|
1075
|
+
if (opts.runtime) {
|
|
1076
|
+
if (!["bun", "node", "deno"].includes(opts.runtime)) {
|
|
1077
|
+
p3.log.error(`Invalid runtime: ${opts.runtime}. Must be bun, node, or deno.`);
|
|
1078
|
+
process.exit(1);
|
|
1079
|
+
}
|
|
1080
|
+
runtime = opts.runtime;
|
|
1081
|
+
} else if (opts.yes) {
|
|
1082
|
+
runtime = "bun";
|
|
1083
|
+
} else {
|
|
1084
|
+
const selected = await p3.select({
|
|
1085
|
+
message: "Which runtime do you use?",
|
|
1086
|
+
options: [
|
|
1087
|
+
{ value: "bun", label: "Bun", hint: "recommended" },
|
|
1088
|
+
{ value: "node", label: "Node.js" },
|
|
1089
|
+
{ value: "deno", label: "Deno" }
|
|
1090
|
+
]
|
|
976
1091
|
});
|
|
977
|
-
if (p3.isCancel(
|
|
1092
|
+
if (p3.isCancel(selected)) {
|
|
978
1093
|
p3.cancel("Init cancelled.");
|
|
979
1094
|
process.exit(0);
|
|
980
1095
|
}
|
|
1096
|
+
runtime = selected;
|
|
981
1097
|
}
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
});
|
|
999
|
-
if (p3.isCancel(base)) {
|
|
1000
|
-
p3.cancel("Init cancelled.");
|
|
1001
|
-
process.exit(0);
|
|
1098
|
+
let baseDir;
|
|
1099
|
+
if (opts.base) {
|
|
1100
|
+
baseDir = opts.base;
|
|
1101
|
+
} else if (opts.yes) {
|
|
1102
|
+
baseDir = "src/ai";
|
|
1103
|
+
} else {
|
|
1104
|
+
const base = await p3.text({
|
|
1105
|
+
message: "Where should kitn components be installed?",
|
|
1106
|
+
initialValue: "src/ai",
|
|
1107
|
+
placeholder: "src/ai"
|
|
1108
|
+
});
|
|
1109
|
+
if (p3.isCancel(base)) {
|
|
1110
|
+
p3.cancel("Init cancelled.");
|
|
1111
|
+
process.exit(0);
|
|
1112
|
+
}
|
|
1113
|
+
baseDir = base;
|
|
1002
1114
|
}
|
|
1003
|
-
const baseDir = base;
|
|
1004
1115
|
const config = {
|
|
1005
1116
|
runtime,
|
|
1006
1117
|
framework: "hono",
|
|
@@ -1047,6 +1158,15 @@ async function initCommand() {
|
|
|
1047
1158
|
].join("\n"),
|
|
1048
1159
|
"Add this to your server entry point:"
|
|
1049
1160
|
);
|
|
1161
|
+
p3.log.message(
|
|
1162
|
+
[
|
|
1163
|
+
pc4.bold("Add your first agent:"),
|
|
1164
|
+
` ${pc4.cyan("kitn add weather-agent")}`,
|
|
1165
|
+
"",
|
|
1166
|
+
pc4.bold("Browse all components:"),
|
|
1167
|
+
` ${pc4.cyan("kitn list")}`
|
|
1168
|
+
].join("\n")
|
|
1169
|
+
);
|
|
1050
1170
|
p3.outro("Done!");
|
|
1051
1171
|
}
|
|
1052
1172
|
var PLUGIN_TEMPLATE;
|
|
@@ -1458,8 +1578,8 @@ async function scanForComponents(cwd, paths) {
|
|
|
1458
1578
|
const resolvedCwd = resolve(cwd);
|
|
1459
1579
|
if (paths && paths.length > 0) {
|
|
1460
1580
|
const results = [];
|
|
1461
|
-
for (const
|
|
1462
|
-
const absPath = resolve(resolvedCwd,
|
|
1581
|
+
for (const p13 of paths) {
|
|
1582
|
+
const absPath = resolve(resolvedCwd, p13);
|
|
1463
1583
|
if (await fileExists(join11(absPath, "registry.json"))) {
|
|
1464
1584
|
results.push(absPath);
|
|
1465
1585
|
continue;
|
|
@@ -2099,6 +2219,39 @@ var init_info = __esm({
|
|
|
2099
2219
|
}
|
|
2100
2220
|
});
|
|
2101
2221
|
|
|
2222
|
+
// src/commands/check.ts
|
|
2223
|
+
var check_exports = {};
|
|
2224
|
+
__export(check_exports, {
|
|
2225
|
+
checkCommand: () => checkCommand
|
|
2226
|
+
});
|
|
2227
|
+
import * as p11 from "@clack/prompts";
|
|
2228
|
+
import pc10 from "picocolors";
|
|
2229
|
+
async function checkCommand(currentVersion) {
|
|
2230
|
+
p11.intro(pc10.bgCyan(pc10.black(" kitn check ")));
|
|
2231
|
+
p11.log.info(`kitn v${currentVersion}`);
|
|
2232
|
+
const s = p11.spinner();
|
|
2233
|
+
s.start("Checking for updates...");
|
|
2234
|
+
const latest = await fetchLatestVersion();
|
|
2235
|
+
if (!latest) {
|
|
2236
|
+
s.stop(pc10.yellow("Could not reach the npm registry"));
|
|
2237
|
+
p11.outro("Try again later.");
|
|
2238
|
+
return;
|
|
2239
|
+
}
|
|
2240
|
+
if (isNewer(latest, currentVersion)) {
|
|
2241
|
+
s.stop(pc10.yellow(`Update available: ${currentVersion} \u2192 ${latest}`));
|
|
2242
|
+
p11.log.message(` Run: ${pc10.cyan("npm i -g @kitnai/cli")}`);
|
|
2243
|
+
} else {
|
|
2244
|
+
s.stop(pc10.green("You're on the latest version"));
|
|
2245
|
+
}
|
|
2246
|
+
p11.outro("");
|
|
2247
|
+
}
|
|
2248
|
+
var init_check = __esm({
|
|
2249
|
+
"src/commands/check.ts"() {
|
|
2250
|
+
"use strict";
|
|
2251
|
+
init_update_check();
|
|
2252
|
+
}
|
|
2253
|
+
});
|
|
2254
|
+
|
|
2102
2255
|
// src/commands/registry.ts
|
|
2103
2256
|
var registry_exports = {};
|
|
2104
2257
|
__export(registry_exports, {
|
|
@@ -2106,8 +2259,8 @@ __export(registry_exports, {
|
|
|
2106
2259
|
registryListCommand: () => registryListCommand,
|
|
2107
2260
|
registryRemoveCommand: () => registryRemoveCommand
|
|
2108
2261
|
});
|
|
2109
|
-
import * as
|
|
2110
|
-
import
|
|
2262
|
+
import * as p12 from "@clack/prompts";
|
|
2263
|
+
import pc11 from "picocolors";
|
|
2111
2264
|
async function registryAddCommand(namespace, url, opts = {}) {
|
|
2112
2265
|
const cwd = opts.cwd ?? process.cwd();
|
|
2113
2266
|
const config = await readConfig(cwd);
|
|
@@ -2133,10 +2286,10 @@ async function registryAddCommand(namespace, url, opts = {}) {
|
|
|
2133
2286
|
config.registries[namespace] = url;
|
|
2134
2287
|
}
|
|
2135
2288
|
await writeConfig(cwd, config);
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
if (opts.homepage)
|
|
2139
|
-
if (opts.description)
|
|
2289
|
+
p12.log.success(`Added registry ${pc11.bold(namespace)}`);
|
|
2290
|
+
p12.log.message(pc11.dim(` ${url}`));
|
|
2291
|
+
if (opts.homepage) p12.log.message(pc11.dim(` Homepage: ${opts.homepage}`));
|
|
2292
|
+
if (opts.description) p12.log.message(pc11.dim(` ${opts.description}`));
|
|
2140
2293
|
}
|
|
2141
2294
|
async function registryRemoveCommand(namespace, opts = {}) {
|
|
2142
2295
|
const cwd = opts.cwd ?? process.cwd();
|
|
@@ -2158,10 +2311,10 @@ async function registryRemoveCommand(namespace, opts = {}) {
|
|
|
2158
2311
|
}
|
|
2159
2312
|
delete config.registries[namespace];
|
|
2160
2313
|
await writeConfig(cwd, config);
|
|
2161
|
-
|
|
2314
|
+
p12.log.success(`Removed registry ${pc11.bold(namespace)}`);
|
|
2162
2315
|
if (affectedComponents.length > 0) {
|
|
2163
|
-
|
|
2164
|
-
` + affectedComponents.map((name) => ` ${
|
|
2316
|
+
p12.log.warn(`${affectedComponents.length} installed component(s) referenced this registry:
|
|
2317
|
+
` + affectedComponents.map((name) => ` ${pc11.yellow("!")} ${name}`).join("\n"));
|
|
2165
2318
|
}
|
|
2166
2319
|
return { affectedComponents };
|
|
2167
2320
|
}
|
|
@@ -2176,15 +2329,15 @@ async function registryListCommand(opts = {}) {
|
|
|
2176
2329
|
return { namespace, url, homepage, description };
|
|
2177
2330
|
});
|
|
2178
2331
|
if (entries.length === 0) {
|
|
2179
|
-
|
|
2332
|
+
p12.log.message(pc11.dim(" No registries configured."));
|
|
2180
2333
|
} else {
|
|
2181
2334
|
const lines = [];
|
|
2182
2335
|
for (const { namespace, url, homepage, description } of entries) {
|
|
2183
|
-
lines.push(` ${
|
|
2336
|
+
lines.push(` ${pc11.bold(namespace.padEnd(16))} ${pc11.dim(url)}`);
|
|
2184
2337
|
if (description) lines.push(` ${" ".repeat(16)} ${description}`);
|
|
2185
|
-
if (homepage) lines.push(` ${" ".repeat(16)} ${
|
|
2338
|
+
if (homepage) lines.push(` ${" ".repeat(16)} ${pc11.dim(homepage)}`);
|
|
2186
2339
|
}
|
|
2187
|
-
|
|
2340
|
+
p12.log.message(lines.join("\n"));
|
|
2188
2341
|
}
|
|
2189
2342
|
return entries;
|
|
2190
2343
|
}
|
|
@@ -2196,89 +2349,14 @@ var init_registry = __esm({
|
|
|
2196
2349
|
});
|
|
2197
2350
|
|
|
2198
2351
|
// src/index.ts
|
|
2352
|
+
init_update_check();
|
|
2199
2353
|
import { Command } from "commander";
|
|
2200
|
-
|
|
2201
|
-
// src/utils/update-check.ts
|
|
2202
|
-
import { readFile, writeFile, mkdir } from "fs/promises";
|
|
2203
|
-
import { join } from "path";
|
|
2204
|
-
import { homedir } from "os";
|
|
2205
|
-
import pc from "picocolors";
|
|
2206
|
-
var CACHE_DIR = join(homedir(), ".kitn");
|
|
2207
|
-
var CACHE_FILE = join(CACHE_DIR, "update-check.json");
|
|
2208
|
-
var CHECK_INTERVAL = 60 * 60 * 1e3;
|
|
2209
|
-
async function readCache() {
|
|
2210
|
-
try {
|
|
2211
|
-
const raw = await readFile(CACHE_FILE, "utf-8");
|
|
2212
|
-
return JSON.parse(raw);
|
|
2213
|
-
} catch {
|
|
2214
|
-
return null;
|
|
2215
|
-
}
|
|
2216
|
-
}
|
|
2217
|
-
async function writeCache(entry) {
|
|
2218
|
-
try {
|
|
2219
|
-
await mkdir(CACHE_DIR, { recursive: true });
|
|
2220
|
-
await writeFile(CACHE_FILE, JSON.stringify(entry));
|
|
2221
|
-
} catch {
|
|
2222
|
-
}
|
|
2223
|
-
}
|
|
2224
|
-
async function fetchLatestVersion() {
|
|
2225
|
-
try {
|
|
2226
|
-
const controller = new AbortController();
|
|
2227
|
-
const timeout = setTimeout(() => controller.abort(), 3e3);
|
|
2228
|
-
const res = await fetch("https://registry.npmjs.org/@kitnai/cli/latest", {
|
|
2229
|
-
signal: controller.signal
|
|
2230
|
-
});
|
|
2231
|
-
clearTimeout(timeout);
|
|
2232
|
-
if (!res.ok) return null;
|
|
2233
|
-
const data = await res.json();
|
|
2234
|
-
return data.version ?? null;
|
|
2235
|
-
} catch {
|
|
2236
|
-
return null;
|
|
2237
|
-
}
|
|
2238
|
-
}
|
|
2239
|
-
function isNewer(latest, current) {
|
|
2240
|
-
const [lMaj, lMin, lPat] = latest.split(".").map(Number);
|
|
2241
|
-
const [cMaj, cMin, cPat] = current.split(".").map(Number);
|
|
2242
|
-
if (lMaj !== cMaj) return lMaj > cMaj;
|
|
2243
|
-
if (lMin !== cMin) return lMin > cMin;
|
|
2244
|
-
return lPat > cPat;
|
|
2245
|
-
}
|
|
2246
|
-
function startUpdateCheck(currentVersion) {
|
|
2247
|
-
let message = "";
|
|
2248
|
-
const check = (async () => {
|
|
2249
|
-
const cache = await readCache();
|
|
2250
|
-
let latest = null;
|
|
2251
|
-
if (cache && Date.now() - cache.checkedAt < CHECK_INTERVAL) {
|
|
2252
|
-
latest = cache.latest;
|
|
2253
|
-
} else {
|
|
2254
|
-
latest = await fetchLatestVersion();
|
|
2255
|
-
if (latest) {
|
|
2256
|
-
await writeCache({ latest, checkedAt: Date.now() });
|
|
2257
|
-
}
|
|
2258
|
-
}
|
|
2259
|
-
if (latest && isNewer(latest, currentVersion)) {
|
|
2260
|
-
message = [
|
|
2261
|
-
"",
|
|
2262
|
-
pc.yellow(` Update available: ${pc.dim(currentVersion)} \u2192 ${pc.green(latest)}`),
|
|
2263
|
-
pc.dim(` Run ${pc.cyan("npx @kitnai/cli@latest")} or ${pc.cyan("npm i -g @kitnai/cli")}`),
|
|
2264
|
-
""
|
|
2265
|
-
].join("\n");
|
|
2266
|
-
}
|
|
2267
|
-
})();
|
|
2268
|
-
check.catch(() => {
|
|
2269
|
-
});
|
|
2270
|
-
return () => {
|
|
2271
|
-
if (message) process.stderr.write(message);
|
|
2272
|
-
};
|
|
2273
|
-
}
|
|
2274
|
-
|
|
2275
|
-
// src/index.ts
|
|
2276
|
-
var VERSION = true ? "0.1.16" : "0.0.0-dev";
|
|
2354
|
+
var VERSION = true ? "0.1.17" : "0.0.0-dev";
|
|
2277
2355
|
var printUpdateNotice = startUpdateCheck(VERSION);
|
|
2278
2356
|
var program = new Command().name("kitn").description("Install AI agent components from the kitn registry").version(VERSION);
|
|
2279
|
-
program.command("init").description("Initialize kitn in your project").action(async () => {
|
|
2357
|
+
program.command("init").description("Initialize kitn in your project").option("-r, --runtime <runtime>", "runtime to use (bun, node, deno)").option("-b, --base <path>", "base directory for components (default: src/ai)").option("-y, --yes", "accept all defaults without prompting").action(async (opts) => {
|
|
2280
2358
|
const { initCommand: initCommand2 } = await Promise.resolve().then(() => (init_init(), init_exports));
|
|
2281
|
-
await initCommand2();
|
|
2359
|
+
await initCommand2(opts);
|
|
2282
2360
|
});
|
|
2283
2361
|
program.command("add").description("Add components from the kitn registry").argument("[components...]", "component names to install").option("-o, --overwrite", "overwrite existing files without prompting").option("-t, --type <type>", "filter by component type").action(async (components, opts) => {
|
|
2284
2362
|
const { addCommand: addCommand2 } = await Promise.resolve().then(() => (init_add(), add_exports));
|
|
@@ -2312,6 +2390,10 @@ program.command("info").description("Show details about a component").argument("
|
|
|
2312
2390
|
const { infoCommand: infoCommand2 } = await Promise.resolve().then(() => (init_info(), info_exports));
|
|
2313
2391
|
await infoCommand2(component);
|
|
2314
2392
|
});
|
|
2393
|
+
program.command("check").description("Check for CLI updates").action(async () => {
|
|
2394
|
+
const { checkCommand: checkCommand2 } = await Promise.resolve().then(() => (init_check(), check_exports));
|
|
2395
|
+
await checkCommand2(VERSION);
|
|
2396
|
+
});
|
|
2315
2397
|
var registry = program.command("registry").description("Manage component registries");
|
|
2316
2398
|
registry.command("add").description("Add a component registry").argument("<namespace>", "registry namespace (e.g. @myteam)").argument("<url>", "URL template with {type} and {name} placeholders").option("-o, --overwrite", "overwrite if namespace already exists").option("--homepage <url>", "registry homepage URL").option("--description <text>", "short description of the registry").action(async (namespace, url, opts) => {
|
|
2317
2399
|
const { registryAddCommand: registryAddCommand2 } = await Promise.resolve().then(() => (init_registry(), registry_exports));
|