@kitnai/cli 0.1.24 → 0.1.26
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 +4 -3
- package/dist/index.js +83 -69
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -140,7 +140,7 @@ Outputs a unified diff for each file in the component. Shows "up to date" if the
|
|
|
140
140
|
|
|
141
141
|
### `kitn remove <component>`
|
|
142
142
|
|
|
143
|
-
Remove an installed component. Deletes files and removes tracking from `kitn.
|
|
143
|
+
Remove an installed component. Deletes files and removes tracking from `kitn.lock`.
|
|
144
144
|
|
|
145
145
|
```bash
|
|
146
146
|
kitn remove weather-agent
|
|
@@ -279,7 +279,8 @@ Created by `kitn init`. Controls where components are installed and which regist
|
|
|
279
279
|
| `framework` | `hono` |
|
|
280
280
|
| `aliases` | Directory paths for each component type |
|
|
281
281
|
| `registries` | Named registries — each value is a URL string or an object with `url`, `homepage`, `description` |
|
|
282
|
-
|
|
282
|
+
|
|
283
|
+
> Installed component tracking (file paths, content hashes, versions) is stored separately in `kitn.lock`. This file is auto-managed — don't edit it manually.
|
|
283
284
|
|
|
284
285
|
### Registry entries
|
|
285
286
|
|
|
@@ -313,7 +314,7 @@ The CLI automatically detects your package manager by checking for lockfiles in
|
|
|
313
314
|
|
|
314
315
|
Components are **source code**, not packages. `kitn add` copies TypeScript files directly into your project. You own the code and can modify it freely.
|
|
315
316
|
|
|
316
|
-
The CLI tracks what it installed in `kitn.
|
|
317
|
+
The CLI tracks what it installed in `kitn.lock`, storing file paths and content hashes. This enables `kitn diff` to detect local changes and `kitn update` to apply registry updates.
|
|
317
318
|
|
|
318
319
|
### Hosting your own registry
|
|
319
320
|
|
package/dist/index.js
CHANGED
|
@@ -157,7 +157,7 @@ var init_update_check = __esm({
|
|
|
157
157
|
});
|
|
158
158
|
|
|
159
159
|
// src/utils/config.ts
|
|
160
|
-
import { readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
|
|
160
|
+
import { readFile as readFile2, writeFile as writeFile2, unlink } from "fs/promises";
|
|
161
161
|
import { join as join3 } from "path";
|
|
162
162
|
import { z } from "zod";
|
|
163
163
|
function getRegistryUrl(entry) {
|
|
@@ -179,6 +179,24 @@ async function writeConfig(projectDir, config) {
|
|
|
179
179
|
const data = { $schema: "https://kitn.dev/schema/config.json", ...config };
|
|
180
180
|
await writeFile2(join3(projectDir, CONFIG_FILE), JSON.stringify(data, null, 2) + "\n");
|
|
181
181
|
}
|
|
182
|
+
async function readLock(projectDir) {
|
|
183
|
+
try {
|
|
184
|
+
const raw = await readFile2(join3(projectDir, LOCK_FILE), "utf-8");
|
|
185
|
+
return lockSchema.parse(JSON.parse(raw));
|
|
186
|
+
} catch {
|
|
187
|
+
return {};
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
async function writeLock(projectDir, lock) {
|
|
191
|
+
if (Object.keys(lock).length === 0) {
|
|
192
|
+
try {
|
|
193
|
+
await unlink(join3(projectDir, LOCK_FILE));
|
|
194
|
+
} catch {
|
|
195
|
+
}
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
await writeFile2(join3(projectDir, LOCK_FILE), JSON.stringify(lock, null, 2) + "\n");
|
|
199
|
+
}
|
|
182
200
|
function getInstallPath(config, type, fileName, namespace) {
|
|
183
201
|
const aliasKey = typeToAliasKey[type];
|
|
184
202
|
const base = config.aliases[aliasKey];
|
|
@@ -188,14 +206,14 @@ function getInstallPath(config, type, fileName, namespace) {
|
|
|
188
206
|
}
|
|
189
207
|
return join3(base, fileName);
|
|
190
208
|
}
|
|
191
|
-
var componentType, installedComponentSchema, registryEntrySchema, registryValueSchema, configSchema, FRAMEWORK_TO_ADAPTER, CONFIG_FILE, typeToAliasKey;
|
|
209
|
+
var componentType, installedComponentSchema, registryEntrySchema, registryValueSchema, configSchema, FRAMEWORK_TO_ADAPTER, CONFIG_FILE, LOCK_FILE, lockSchema, typeToAliasKey;
|
|
192
210
|
var init_config = __esm({
|
|
193
211
|
"src/utils/config.ts"() {
|
|
194
212
|
"use strict";
|
|
195
213
|
componentType = z.enum(["kitn:agent", "kitn:tool", "kitn:skill", "kitn:storage", "kitn:package"]);
|
|
196
214
|
installedComponentSchema = z.object({
|
|
197
215
|
registry: z.string().optional(),
|
|
198
|
-
type: componentType,
|
|
216
|
+
type: componentType.optional(),
|
|
199
217
|
slot: z.string().optional(),
|
|
200
218
|
version: z.string(),
|
|
201
219
|
installedAt: z.string(),
|
|
@@ -220,8 +238,7 @@ var init_config = __esm({
|
|
|
220
238
|
skills: z.string(),
|
|
221
239
|
storage: z.string()
|
|
222
240
|
}),
|
|
223
|
-
registries: z.record(z.string(), registryValueSchema)
|
|
224
|
-
installed: z.record(z.string(), installedComponentSchema).optional()
|
|
241
|
+
registries: z.record(z.string(), registryValueSchema)
|
|
225
242
|
});
|
|
226
243
|
FRAMEWORK_TO_ADAPTER = {
|
|
227
244
|
hono: "hono",
|
|
@@ -229,6 +246,8 @@ var init_config = __esm({
|
|
|
229
246
|
elysia: "elysia"
|
|
230
247
|
};
|
|
231
248
|
CONFIG_FILE = "kitn.json";
|
|
249
|
+
LOCK_FILE = "kitn.lock";
|
|
250
|
+
lockSchema = z.record(z.string(), installedComponentSchema);
|
|
232
251
|
typeToAliasKey = {
|
|
233
252
|
"kitn:agent": "agents",
|
|
234
253
|
"kitn:tool": "tools",
|
|
@@ -830,7 +849,7 @@ import * as p2 from "@clack/prompts";
|
|
|
830
849
|
import pc3 from "picocolors";
|
|
831
850
|
import { join as join7, dirname as dirname3 } from "path";
|
|
832
851
|
import { existsSync } from "fs";
|
|
833
|
-
import { readFile as readFile6, writeFile as writeFile6, mkdir as mkdir3, unlink } from "fs/promises";
|
|
852
|
+
import { readFile as readFile6, writeFile as writeFile6, mkdir as mkdir3, unlink as unlink2 } from "fs/promises";
|
|
834
853
|
import { relative as relative2 } from "path";
|
|
835
854
|
async function addCommand(components, opts) {
|
|
836
855
|
p2.intro(pc3.bgCyan(pc3.black(" kitn add ")));
|
|
@@ -840,6 +859,7 @@ async function addCommand(components, opts) {
|
|
|
840
859
|
p2.log.error("No kitn.json found. Run `kitn init` first.");
|
|
841
860
|
process.exit(1);
|
|
842
861
|
}
|
|
862
|
+
const lock = await readLock(cwd);
|
|
843
863
|
if (components.length === 0) {
|
|
844
864
|
const fetcher2 = new RegistryFetcher(config.registries);
|
|
845
865
|
const s2 = p2.spinner();
|
|
@@ -859,7 +879,7 @@ async function addCommand(components, opts) {
|
|
|
859
879
|
p2.log.warn("No components found in configured registries.");
|
|
860
880
|
process.exit(0);
|
|
861
881
|
}
|
|
862
|
-
const installed = new Set(Object.keys(
|
|
882
|
+
const installed = new Set(Object.keys(lock));
|
|
863
883
|
const typeLabels = {
|
|
864
884
|
"kitn:agent": "Agents",
|
|
865
885
|
"kitn:tool": "Tools",
|
|
@@ -1056,7 +1076,7 @@ async function addCommand(components, opts) {
|
|
|
1056
1076
|
const slotReplacements = /* @__PURE__ */ new Map();
|
|
1057
1077
|
for (const item of resolved) {
|
|
1058
1078
|
if (!item.slot) continue;
|
|
1059
|
-
const existing = Object.entries(
|
|
1079
|
+
const existing = Object.entries(lock).find(
|
|
1060
1080
|
([key, entry]) => key !== item.name && entry.slot === item.slot
|
|
1061
1081
|
);
|
|
1062
1082
|
if (!existing) continue;
|
|
@@ -1079,11 +1099,11 @@ async function addCommand(components, opts) {
|
|
|
1079
1099
|
if (slotReplacements.size > 0) {
|
|
1080
1100
|
const baseDir2 = config.aliases.base ?? "src/ai";
|
|
1081
1101
|
for (const [oldKey] of slotReplacements) {
|
|
1082
|
-
const oldEntry =
|
|
1102
|
+
const oldEntry = lock[oldKey];
|
|
1083
1103
|
if (!oldEntry) continue;
|
|
1084
1104
|
for (const filePath of oldEntry.files) {
|
|
1085
1105
|
try {
|
|
1086
|
-
await
|
|
1106
|
+
await unlink2(join7(cwd, filePath));
|
|
1087
1107
|
} catch {
|
|
1088
1108
|
}
|
|
1089
1109
|
}
|
|
@@ -1111,7 +1131,7 @@ async function addCommand(components, opts) {
|
|
|
1111
1131
|
await writeFile6(barrelPath2, barrelContent);
|
|
1112
1132
|
}
|
|
1113
1133
|
}
|
|
1114
|
-
delete
|
|
1134
|
+
delete lock[oldKey];
|
|
1115
1135
|
p2.log.info(`Replaced ${pc3.dim(oldKey)} \u2192 ${pc3.cyan(slotReplacements.get(oldKey))}`);
|
|
1116
1136
|
}
|
|
1117
1137
|
}
|
|
@@ -1128,7 +1148,7 @@ async function addCommand(components, opts) {
|
|
|
1128
1148
|
for (const item of resolved) {
|
|
1129
1149
|
if (item.dependencies) allDeps.push(...item.dependencies);
|
|
1130
1150
|
if (item.devDependencies) allDevDeps.push(...item.devDependencies);
|
|
1131
|
-
const existingInstall =
|
|
1151
|
+
const existingInstall = lock[item.name];
|
|
1132
1152
|
if (existingInstall && item.type === "kitn:package") {
|
|
1133
1153
|
const allContent = item.files.map((f) => f.content).join("\n");
|
|
1134
1154
|
if (contentHash(allContent) === existingInstall.hash) {
|
|
@@ -1174,11 +1194,10 @@ async function addCommand(components, opts) {
|
|
|
1174
1194
|
break;
|
|
1175
1195
|
}
|
|
1176
1196
|
}
|
|
1177
|
-
const installed = config.installed ?? {};
|
|
1178
1197
|
const allContent = item.files.map((f) => f.content).join("\n");
|
|
1179
1198
|
const ref = refs.find((r) => r.name === item.name) ?? { namespace: "@kitn", name: item.name, version: void 0 };
|
|
1180
1199
|
const installedKey = ref.namespace === "@kitn" ? item.name : `${ref.namespace}/${item.name}`;
|
|
1181
|
-
|
|
1200
|
+
lock[installedKey] = {
|
|
1182
1201
|
registry: ref.namespace,
|
|
1183
1202
|
type: item.type,
|
|
1184
1203
|
...item.slot && { slot: item.slot },
|
|
@@ -1188,7 +1207,6 @@ async function addCommand(components, opts) {
|
|
|
1188
1207
|
hash: contentHash(allContent),
|
|
1189
1208
|
registryDependencies: item.registryDependencies
|
|
1190
1209
|
};
|
|
1191
|
-
config.installed = installed;
|
|
1192
1210
|
} else {
|
|
1193
1211
|
const ref = refs.find((r) => r.name === item.name) ?? { namespace: "@kitn", name: item.name, version: void 0 };
|
|
1194
1212
|
const ns = ref.namespace;
|
|
@@ -1244,13 +1262,12 @@ async function addCommand(components, opts) {
|
|
|
1244
1262
|
break;
|
|
1245
1263
|
}
|
|
1246
1264
|
}
|
|
1247
|
-
const installed = config.installed ?? {};
|
|
1248
1265
|
const allContent = item.files.map((f) => {
|
|
1249
1266
|
const fn = f.path.split("/").pop();
|
|
1250
1267
|
return rewriteKitnImports(f.content, item.type, fn, config.aliases);
|
|
1251
1268
|
}).join("\n");
|
|
1252
1269
|
const installedKey = ns === "@kitn" ? item.name : `${ns}/${item.name}`;
|
|
1253
|
-
|
|
1270
|
+
lock[installedKey] = {
|
|
1254
1271
|
registry: ns,
|
|
1255
1272
|
type: item.type,
|
|
1256
1273
|
...item.slot && { slot: item.slot },
|
|
@@ -1263,7 +1280,6 @@ async function addCommand(components, opts) {
|
|
|
1263
1280
|
hash: contentHash(allContent),
|
|
1264
1281
|
registryDependencies: item.registryDependencies
|
|
1265
1282
|
};
|
|
1266
|
-
config.installed = installed;
|
|
1267
1283
|
}
|
|
1268
1284
|
}
|
|
1269
1285
|
const BARREL_ELIGIBLE = /* @__PURE__ */ new Set(["kitn:agent", "kitn:tool", "kitn:skill"]);
|
|
@@ -1299,7 +1315,7 @@ async function addCommand(components, opts) {
|
|
|
1299
1315
|
if (!barrelExisted) {
|
|
1300
1316
|
p2.note(
|
|
1301
1317
|
[
|
|
1302
|
-
`import { ai } from "
|
|
1318
|
+
`import { ai } from "@kitn/plugin";`,
|
|
1303
1319
|
``,
|
|
1304
1320
|
`app.route("/api", ai.router);`
|
|
1305
1321
|
].join("\n"),
|
|
@@ -1308,6 +1324,7 @@ async function addCommand(components, opts) {
|
|
|
1308
1324
|
}
|
|
1309
1325
|
}
|
|
1310
1326
|
await writeConfig(cwd, config);
|
|
1327
|
+
await writeLock(cwd, lock);
|
|
1311
1328
|
const uniqueDeps = [...new Set(allDeps)];
|
|
1312
1329
|
const uniqueDevDeps = [...new Set(allDevDeps)].filter((d) => !uniqueDeps.includes(d));
|
|
1313
1330
|
const totalDeps = uniqueDeps.length + uniqueDevDeps.length;
|
|
@@ -1344,7 +1361,7 @@ async function addCommand(components, opts) {
|
|
|
1344
1361
|
}
|
|
1345
1362
|
}
|
|
1346
1363
|
const resolvedNames = new Set(resolved.map((r) => r.name));
|
|
1347
|
-
const projectInstalled = new Set(Object.keys(
|
|
1364
|
+
const projectInstalled = new Set(Object.keys(lock));
|
|
1348
1365
|
const hints = [];
|
|
1349
1366
|
const adapterName = resolveRoutesAlias(config);
|
|
1350
1367
|
if (resolvedNames.has("core") && !resolvedNames.has(adapterName) && !projectInstalled.has(adapterName)) {
|
|
@@ -1530,7 +1547,7 @@ async function initCommand(opts = {}) {
|
|
|
1530
1547
|
const mountCode = framework === "elysia" ? `app.use(ai.router);` : `app.route("/api", ai.router);`;
|
|
1531
1548
|
p3.note(
|
|
1532
1549
|
[
|
|
1533
|
-
`import { ai } from "
|
|
1550
|
+
`import { ai } from "@kitn/plugin";`,
|
|
1534
1551
|
``,
|
|
1535
1552
|
mountCode
|
|
1536
1553
|
].join("\n"),
|
|
@@ -1606,7 +1623,7 @@ async function listCommand(typeFilter, opts) {
|
|
|
1606
1623
|
for (const e of errors) {
|
|
1607
1624
|
p4.log.warn(`${pc5.yellow("\u26A0")} Failed to fetch ${e}`);
|
|
1608
1625
|
}
|
|
1609
|
-
const installed =
|
|
1626
|
+
const installed = await readLock(cwd);
|
|
1610
1627
|
const typeGroups = /* @__PURE__ */ new Map();
|
|
1611
1628
|
for (const item of allItems) {
|
|
1612
1629
|
const group = item.type.replace("kitn:", "");
|
|
@@ -1699,8 +1716,9 @@ async function diffCommand(componentName) {
|
|
|
1699
1716
|
}
|
|
1700
1717
|
const input = componentName === "routes" ? resolveRoutesAlias(config) : componentName;
|
|
1701
1718
|
const ref = parseComponentRef(input);
|
|
1719
|
+
const lock = await readLock(cwd);
|
|
1702
1720
|
const installedKey = ref.namespace === "@kitn" ? ref.name : `${ref.namespace}/${ref.name}`;
|
|
1703
|
-
const installed =
|
|
1721
|
+
const installed = lock[installedKey];
|
|
1704
1722
|
if (!installed) {
|
|
1705
1723
|
p5.log.error(`Component '${ref.name}' is not installed.`);
|
|
1706
1724
|
process.exit(1);
|
|
@@ -1779,15 +1797,15 @@ __export(remove_exports, {
|
|
|
1779
1797
|
import * as p6 from "@clack/prompts";
|
|
1780
1798
|
import pc6 from "picocolors";
|
|
1781
1799
|
import { join as join10, relative as relative3, dirname as dirname4 } from "path";
|
|
1782
|
-
import { unlink as
|
|
1800
|
+
import { unlink as unlink3, readFile as readFile7, writeFile as writeFile8 } from "fs/promises";
|
|
1783
1801
|
import { existsSync as existsSync2 } from "fs";
|
|
1784
|
-
async function removeSingleComponent(installedKey, config, cwd) {
|
|
1785
|
-
const
|
|
1786
|
-
if (!
|
|
1802
|
+
async function removeSingleComponent(installedKey, lock, config, cwd) {
|
|
1803
|
+
const entry = lock[installedKey];
|
|
1804
|
+
if (!entry) return;
|
|
1787
1805
|
const deleted = [];
|
|
1788
|
-
for (const filePath of
|
|
1806
|
+
for (const filePath of entry.files) {
|
|
1789
1807
|
try {
|
|
1790
|
-
await
|
|
1808
|
+
await unlink3(join10(cwd, filePath));
|
|
1791
1809
|
deleted.push(filePath);
|
|
1792
1810
|
} catch {
|
|
1793
1811
|
p6.log.warn(`Could not delete ${filePath} (may have been moved or renamed)`);
|
|
@@ -1819,26 +1837,25 @@ async function removeSingleComponent(installedKey, config, cwd) {
|
|
|
1819
1837
|
p6.log.info(`Updated barrel file: ${join10(baseDir, "index.ts")}`);
|
|
1820
1838
|
}
|
|
1821
1839
|
}
|
|
1822
|
-
delete
|
|
1840
|
+
delete lock[installedKey];
|
|
1823
1841
|
if (deleted.length > 0) {
|
|
1824
1842
|
p6.log.success(`Removed ${installedKey}:
|
|
1825
1843
|
` + deleted.map((f) => ` ${pc6.red("-")} ${f}`).join("\n"));
|
|
1826
1844
|
}
|
|
1827
1845
|
}
|
|
1828
|
-
async function offerOrphanRemoval(removedDeps, config, cwd) {
|
|
1846
|
+
async function offerOrphanRemoval(removedDeps, lock, config, cwd) {
|
|
1829
1847
|
if (removedDeps.size === 0) return;
|
|
1830
|
-
const remaining = Object.entries(
|
|
1848
|
+
const remaining = Object.entries(lock);
|
|
1831
1849
|
const neededDeps = /* @__PURE__ */ new Set();
|
|
1832
1850
|
for (const [, entry] of remaining) {
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
for (const dep of deps) {
|
|
1851
|
+
if (entry.registryDependencies) {
|
|
1852
|
+
for (const dep of entry.registryDependencies) {
|
|
1836
1853
|
neededDeps.add(dep);
|
|
1837
1854
|
}
|
|
1838
1855
|
}
|
|
1839
1856
|
}
|
|
1840
1857
|
const orphans = [...removedDeps].filter(
|
|
1841
|
-
(dep) => dep !== "core" && !neededDeps.has(dep) &&
|
|
1858
|
+
(dep) => dep !== "core" && !neededDeps.has(dep) && lock[dep]
|
|
1842
1859
|
);
|
|
1843
1860
|
if (orphans.length === 0) return;
|
|
1844
1861
|
const selected = await p6.multiselect({
|
|
@@ -1846,14 +1863,14 @@ async function offerOrphanRemoval(removedDeps, config, cwd) {
|
|
|
1846
1863
|
options: orphans.map((dep) => ({
|
|
1847
1864
|
value: dep,
|
|
1848
1865
|
label: dep,
|
|
1849
|
-
hint: `${
|
|
1866
|
+
hint: `${lock[dep].files.length} file(s)`
|
|
1850
1867
|
})),
|
|
1851
1868
|
initialValues: orphans
|
|
1852
1869
|
// all checked by default
|
|
1853
1870
|
});
|
|
1854
1871
|
if (p6.isCancel(selected)) return;
|
|
1855
1872
|
for (const key of selected) {
|
|
1856
|
-
await removeSingleComponent(key, config, cwd);
|
|
1873
|
+
await removeSingleComponent(key, lock, config, cwd);
|
|
1857
1874
|
}
|
|
1858
1875
|
}
|
|
1859
1876
|
async function removeCommand(componentName) {
|
|
@@ -1863,9 +1880,9 @@ async function removeCommand(componentName) {
|
|
|
1863
1880
|
p6.log.error("No kitn.json found. Run `kitn init` first.");
|
|
1864
1881
|
process.exit(1);
|
|
1865
1882
|
}
|
|
1883
|
+
const lock = await readLock(cwd);
|
|
1866
1884
|
if (!componentName) {
|
|
1867
|
-
const
|
|
1868
|
-
const installedKeys = Object.keys(installed2);
|
|
1885
|
+
const installedKeys = Object.keys(lock);
|
|
1869
1886
|
if (installedKeys.length === 0) {
|
|
1870
1887
|
p6.log.warn("No components installed.");
|
|
1871
1888
|
process.exit(0);
|
|
@@ -1875,7 +1892,7 @@ async function removeCommand(componentName) {
|
|
|
1875
1892
|
options: installedKeys.map((key) => ({
|
|
1876
1893
|
value: key,
|
|
1877
1894
|
label: key,
|
|
1878
|
-
hint: `${
|
|
1895
|
+
hint: `${lock[key].files.length} file(s)`
|
|
1879
1896
|
}))
|
|
1880
1897
|
});
|
|
1881
1898
|
if (p6.isCancel(selected)) {
|
|
@@ -1887,46 +1904,43 @@ async function removeCommand(componentName) {
|
|
|
1887
1904
|
p6.log.warn("No components selected.");
|
|
1888
1905
|
process.exit(0);
|
|
1889
1906
|
}
|
|
1890
|
-
for (const key of selectedKeys) {
|
|
1891
|
-
await removeSingleComponent(key, config, cwd);
|
|
1892
|
-
}
|
|
1893
1907
|
const allRemovedDeps = /* @__PURE__ */ new Set();
|
|
1894
1908
|
for (const key of selectedKeys) {
|
|
1895
|
-
const
|
|
1896
|
-
if (
|
|
1897
|
-
for (const dep of
|
|
1909
|
+
const entry2 = lock[key];
|
|
1910
|
+
if (entry2?.registryDependencies) {
|
|
1911
|
+
for (const dep of entry2.registryDependencies) {
|
|
1898
1912
|
allRemovedDeps.add(dep);
|
|
1899
1913
|
}
|
|
1900
1914
|
}
|
|
1901
1915
|
}
|
|
1902
|
-
|
|
1903
|
-
|
|
1916
|
+
for (const key of selectedKeys) {
|
|
1917
|
+
await removeSingleComponent(key, lock, config, cwd);
|
|
1918
|
+
}
|
|
1919
|
+
await offerOrphanRemoval(allRemovedDeps, lock, config, cwd);
|
|
1920
|
+
await writeLock(cwd, lock);
|
|
1904
1921
|
p6.outro(pc6.green("Done!"));
|
|
1905
1922
|
return;
|
|
1906
1923
|
}
|
|
1907
1924
|
const input = componentName === "routes" ? resolveRoutesAlias(config) : componentName;
|
|
1908
1925
|
const ref = parseComponentRef(input);
|
|
1909
1926
|
const installedKey = ref.namespace === "@kitn" ? ref.name : `${ref.namespace}/${ref.name}`;
|
|
1910
|
-
const
|
|
1911
|
-
if (!
|
|
1927
|
+
const entry = lock[installedKey];
|
|
1928
|
+
if (!entry) {
|
|
1912
1929
|
p6.log.error(`Component '${ref.name}' is not installed.`);
|
|
1913
1930
|
process.exit(1);
|
|
1914
1931
|
}
|
|
1915
1932
|
const shouldRemove = await p6.confirm({
|
|
1916
|
-
message: `Remove ${ref.name}? This will delete ${
|
|
1933
|
+
message: `Remove ${ref.name}? This will delete ${entry.files.length} file(s).`,
|
|
1917
1934
|
initialValue: false
|
|
1918
1935
|
});
|
|
1919
1936
|
if (p6.isCancel(shouldRemove) || !shouldRemove) {
|
|
1920
1937
|
p6.cancel("Remove cancelled.");
|
|
1921
1938
|
process.exit(0);
|
|
1922
1939
|
}
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
await offerOrphanRemoval(removedDeps, config, cwd);
|
|
1926
|
-
|
|
1927
|
-
delete config.installed;
|
|
1928
|
-
}
|
|
1929
|
-
await writeConfig(cwd, config);
|
|
1940
|
+
const removedDeps = new Set(entry.registryDependencies ?? []);
|
|
1941
|
+
await removeSingleComponent(installedKey, lock, config, cwd);
|
|
1942
|
+
await offerOrphanRemoval(removedDeps, lock, config, cwd);
|
|
1943
|
+
await writeLock(cwd, lock);
|
|
1930
1944
|
}
|
|
1931
1945
|
var init_remove = __esm({
|
|
1932
1946
|
"src/commands/remove.ts"() {
|
|
@@ -1951,12 +1965,12 @@ async function updateCommand(components) {
|
|
|
1951
1965
|
p7.log.error("No kitn.json found. Run `kitn init` first.");
|
|
1952
1966
|
process.exit(1);
|
|
1953
1967
|
}
|
|
1954
|
-
const
|
|
1955
|
-
if (
|
|
1968
|
+
const lock = await readLock(cwd);
|
|
1969
|
+
if (Object.keys(lock).length === 0) {
|
|
1956
1970
|
p7.log.info("No installed components to update.");
|
|
1957
1971
|
return;
|
|
1958
1972
|
}
|
|
1959
|
-
components = Object.keys(
|
|
1973
|
+
components = Object.keys(lock);
|
|
1960
1974
|
}
|
|
1961
1975
|
await addCommand(components, { overwrite: true });
|
|
1962
1976
|
}
|
|
@@ -2232,7 +2246,8 @@ async function infoCommand(component) {
|
|
|
2232
2246
|
if (fileCount > maxShown) {
|
|
2233
2247
|
console.log(` ${pc8.dim(`... and ${fileCount - maxShown} more`)}`);
|
|
2234
2248
|
}
|
|
2235
|
-
const
|
|
2249
|
+
const lock = await readLock(cwd);
|
|
2250
|
+
const installed = lock[item.name];
|
|
2236
2251
|
if (installed) {
|
|
2237
2252
|
console.log();
|
|
2238
2253
|
console.log(
|
|
@@ -2355,12 +2370,11 @@ async function registryRemoveCommand(namespace, opts = {}) {
|
|
|
2355
2370
|
if (namespace === "@kitn" && !opts.force) {
|
|
2356
2371
|
throw new Error("Cannot remove the default @kitn registry. Use --force to override.");
|
|
2357
2372
|
}
|
|
2373
|
+
const lock = await readLock(cwd);
|
|
2358
2374
|
const affectedComponents = [];
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
affectedComponents.push(name);
|
|
2363
|
-
}
|
|
2375
|
+
for (const [name, entry] of Object.entries(lock)) {
|
|
2376
|
+
if (entry.registry === namespace) {
|
|
2377
|
+
affectedComponents.push(name);
|
|
2364
2378
|
}
|
|
2365
2379
|
}
|
|
2366
2380
|
delete config.registries[namespace];
|
|
@@ -2405,7 +2419,7 @@ var init_registry = __esm({
|
|
|
2405
2419
|
// src/index.ts
|
|
2406
2420
|
init_update_check();
|
|
2407
2421
|
import { Command } from "commander";
|
|
2408
|
-
var VERSION = true ? "0.1.
|
|
2422
|
+
var VERSION = true ? "0.1.26" : "0.0.0-dev";
|
|
2409
2423
|
var printUpdateNotice = startUpdateCheck(VERSION);
|
|
2410
2424
|
var program = new Command().name("kitn").description("Install AI agent components from the kitn registry").version(VERSION);
|
|
2411
2425
|
program.command("init").description("Initialize kitn in your project").option("-r, --runtime <runtime>", "runtime to use (bun, node, deno)").option("-f, --framework <framework>", "HTTP framework (hono, hono-openapi, elysia)").option("-b, --base <path>", "base directory for components (default: src/ai)").option("-y, --yes", "accept all defaults without prompting").action(async (opts) => {
|