@kitnai/cli 0.1.8 → 0.1.10

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/dist/index.js CHANGED
@@ -510,6 +510,40 @@ var init_tsconfig_patcher = __esm({
510
510
  }
511
511
  });
512
512
 
513
+ // src/installers/barrel-manager.ts
514
+ function createBarrelFile() {
515
+ return `${BARREL_COMMENT}
516
+ ${EXPORT_LINE}
517
+ `;
518
+ }
519
+ function addImportToBarrel(content, importPath) {
520
+ const importLine = `import "${importPath}";`;
521
+ if (content.includes(importLine)) return content;
522
+ const exportIndex = content.indexOf(EXPORT_LINE);
523
+ if (exportIndex === -1) {
524
+ return `${content.trimEnd()}
525
+ ${importLine}
526
+ ${EXPORT_LINE}
527
+ `;
528
+ }
529
+ const before = content.slice(0, exportIndex);
530
+ const after = content.slice(exportIndex);
531
+ return `${before}${importLine}
532
+ ${after}`;
533
+ }
534
+ function removeImportFromBarrel(content, importPath) {
535
+ const importLine = `import "${importPath}";`;
536
+ return content.split("\n").filter((line) => line.trim() !== importLine).join("\n");
537
+ }
538
+ var EXPORT_LINE, BARREL_COMMENT;
539
+ var init_barrel_manager = __esm({
540
+ "src/installers/barrel-manager.ts"() {
541
+ "use strict";
542
+ EXPORT_LINE = 'export { registerWithPlugin } from "@kitnai/core";';
543
+ BARREL_COMMENT = "// Managed by kitn CLI \u2014 components auto-imported below";
544
+ }
545
+ });
546
+
513
547
  // src/utils/hash.ts
514
548
  import { createHash } from "crypto";
515
549
  function contentHash(content) {
@@ -643,6 +677,9 @@ __export(add_exports, {
643
677
  import * as p3 from "@clack/prompts";
644
678
  import pc4 from "picocolors";
645
679
  import { join as join7 } from "path";
680
+ import { existsSync } from "fs";
681
+ import { readFile as readFile6, writeFile as writeFile6, mkdir as mkdir3 } from "fs/promises";
682
+ import { relative as relative2 } from "path";
646
683
  async function addCommand(components, opts) {
647
684
  p3.intro(pc4.bgCyan(pc4.black(" kitn add ")));
648
685
  const cwd = process.cwd();
@@ -695,10 +732,10 @@ async function addCommand(components, opts) {
695
732
  for (const item of resolved) {
696
733
  if (item.dependencies) allDeps.push(...item.dependencies);
697
734
  if (item.type === "kitn:package") {
698
- const baseDir = config.aliases.base ?? "src/ai";
735
+ const baseDir2 = config.aliases.base ?? "src/ai";
699
736
  for (const file of item.files) {
700
- const targetPath = join7(cwd, baseDir, file.path);
701
- const relativePath = join7(baseDir, file.path);
737
+ const targetPath = join7(cwd, baseDir2, file.path);
738
+ const relativePath = join7(baseDir2, file.path);
702
739
  const status = await checkFileStatus(targetPath, file.content);
703
740
  switch (status) {
704
741
  case "new" /* New */:
@@ -737,7 +774,7 @@ async function addCommand(components, opts) {
737
774
  const resolvedPaths = {};
738
775
  const installDir = item.installDir ?? item.name;
739
776
  for (const [key, values] of Object.entries(item.tsconfig)) {
740
- resolvedPaths[key] = values.map((v) => `./${join7(baseDir, installDir, v)}`);
777
+ resolvedPaths[key] = values.map((v) => `./${join7(baseDir2, installDir, v)}`);
741
778
  }
742
779
  await patchProjectTsconfig(cwd, resolvedPaths);
743
780
  p3.log.info(`Patched tsconfig.json with paths: ${Object.keys(resolvedPaths).join(", ")}`);
@@ -750,7 +787,7 @@ async function addCommand(components, opts) {
750
787
  registry: ref.namespace,
751
788
  version: item.version ?? "1.0.0",
752
789
  installedAt: (/* @__PURE__ */ new Date()).toISOString(),
753
- files: item.files.map((f) => join7(baseDir, f.path)),
790
+ files: item.files.map((f) => join7(baseDir2, f.path)),
754
791
  hash: contentHash(allContent)
755
792
  };
756
793
  config.installed = installed;
@@ -838,6 +875,61 @@ async function addCommand(components, opts) {
838
875
  config.installed = installed;
839
876
  }
840
877
  }
878
+ const BARREL_ELIGIBLE = /* @__PURE__ */ new Set(["kitn:agent", "kitn:tool", "kitn:skill"]);
879
+ const baseDir = config.aliases.base ?? "src/ai";
880
+ const barrelPath = join7(cwd, baseDir, "index.ts");
881
+ const barrelDir = join7(cwd, baseDir);
882
+ const barrelImports = [];
883
+ for (const item of resolved) {
884
+ if (!BARREL_ELIGIBLE.has(item.type)) continue;
885
+ for (const file of item.files) {
886
+ const aliasKey = (() => {
887
+ switch (item.type) {
888
+ case "kitn:agent":
889
+ return "agents";
890
+ case "kitn:tool":
891
+ return "tools";
892
+ case "kitn:skill":
893
+ return "skills";
894
+ }
895
+ })();
896
+ const fileName = file.path.split("/").pop();
897
+ const filePath = join7(cwd, config.aliases[aliasKey], fileName);
898
+ const importPath = "./" + relative2(barrelDir, filePath).replace(/\\/g, "/");
899
+ barrelImports.push(importPath);
900
+ }
901
+ }
902
+ if (barrelImports.length > 0) {
903
+ const barrelExisted = existsSync(barrelPath);
904
+ let barrelContent;
905
+ if (barrelExisted) {
906
+ barrelContent = await readFile6(barrelPath, "utf-8");
907
+ } else {
908
+ await mkdir3(barrelDir, { recursive: true });
909
+ barrelContent = createBarrelFile();
910
+ }
911
+ for (const importPath of barrelImports) {
912
+ barrelContent = addImportToBarrel(barrelContent, importPath);
913
+ }
914
+ await writeFile6(barrelPath, barrelContent);
915
+ p3.log.info(`Updated barrel file: ${join7(baseDir, "index.ts")}`);
916
+ if (!barrelExisted) {
917
+ p3.note(
918
+ [
919
+ `import { createAIPlugin } from "@kitnai/hono";`,
920
+ `import { registerWithPlugin } from "./ai";`,
921
+ ``,
922
+ `const plugin = createAIPlugin({`,
923
+ ` model: (model) => yourProvider(model ?? "default-model"),`,
924
+ `});`,
925
+ ``,
926
+ `registerWithPlugin(plugin);`,
927
+ `app.route("/api", plugin.app);`
928
+ ].join("\n"),
929
+ "Add this to your app setup"
930
+ );
931
+ }
932
+ }
841
933
  await writeConfig(cwd, config);
842
934
  const uniqueDeps = [...new Set(allDeps)];
843
935
  if (uniqueDeps.length > 0) {
@@ -886,7 +978,7 @@ async function addCommand(components, opts) {
886
978
  hints.push(pc4.dim(` import { yourProvider } from "your-ai-provider";`));
887
979
  hints.push(pc4.dim(``));
888
980
  hints.push(pc4.dim(` const plugin = createAIPlugin({`));
889
- hints.push(pc4.dim(` getModel: (id) => yourProvider(id ?? "default-model"),`));
981
+ hints.push(pc4.dim(` model: (model) => yourProvider(model ?? "default-model"),`));
890
982
  hints.push(pc4.dim(` });`));
891
983
  hints.push(pc4.dim(``));
892
984
  hints.push(pc4.dim(` const app = new Hono();`));
@@ -913,6 +1005,7 @@ var init_add = __esm({
913
1005
  init_env_writer();
914
1006
  init_import_rewriter();
915
1007
  init_tsconfig_patcher();
1008
+ init_barrel_manager();
916
1009
  init_hash();
917
1010
  init_parse_ref();
918
1011
  init_schema();
@@ -926,13 +1019,19 @@ __export(list_exports, {
926
1019
  });
927
1020
  import * as p4 from "@clack/prompts";
928
1021
  import pc5 from "picocolors";
929
- async function listCommand(opts) {
1022
+ async function listCommand(typeFilter, opts) {
930
1023
  const cwd = process.cwd();
931
1024
  const config = await readConfig(cwd);
932
1025
  if (!config) {
933
1026
  p4.log.error("No kitn.json found. Run `kitn init` first.");
934
1027
  process.exit(1);
935
1028
  }
1029
+ const rawType = typeFilter ?? opts.type;
1030
+ const resolvedType = rawType ? TYPE_ALIASES[rawType.toLowerCase()] : void 0;
1031
+ if (rawType && !resolvedType) {
1032
+ p4.log.error(`Unknown type ${pc5.bold(rawType)}. Valid types: agent, tool, skill, storage, package`);
1033
+ process.exit(1);
1034
+ }
936
1035
  const fetcher = new RegistryFetcher(config.registries);
937
1036
  const namespacesToFetch = opts.registry ? [opts.registry] : Object.keys(config.registries);
938
1037
  if (opts.registry && !config.registries[opts.registry]) {
@@ -940,7 +1039,7 @@ async function listCommand(opts) {
940
1039
  process.exit(1);
941
1040
  }
942
1041
  const s = p4.spinner();
943
- s.start("Fetching registry index...");
1042
+ s.start("Fetching registry...");
944
1043
  const allItems = [];
945
1044
  const errors = [];
946
1045
  for (const namespace of namespacesToFetch) {
@@ -958,52 +1057,94 @@ async function listCommand(opts) {
958
1057
  for (const e of errors) p4.log.error(e);
959
1058
  process.exit(1);
960
1059
  }
961
- s.stop(`Found ${allItems.length} components across ${namespacesToFetch.length - errors.length} ${namespacesToFetch.length - errors.length === 1 ? "registry" : "registries"}`);
1060
+ s.stop(`Found ${allItems.length} components`);
962
1061
  for (const e of errors) {
963
1062
  p4.log.warn(`${pc5.yellow("\u26A0")} Failed to fetch ${e}`);
964
1063
  }
965
1064
  const installed = config.installed ?? {};
966
1065
  const typeGroups = /* @__PURE__ */ new Map();
967
1066
  for (const item of allItems) {
968
- if (opts.type && !item.type.endsWith(opts.type)) continue;
969
1067
  const group = item.type.replace("kitn:", "");
1068
+ if (resolvedType && group !== resolvedType) continue;
970
1069
  if (!typeGroups.has(group)) typeGroups.set(group, []);
971
1070
  typeGroups.get(group).push(item);
972
1071
  }
1072
+ let maxName = 0;
1073
+ for (const items of typeGroups.values()) {
1074
+ for (const item of items) {
1075
+ const displayName = item.namespace === "@kitn" ? item.name : `${item.namespace}/${item.name}`;
1076
+ if (displayName.length > maxName) maxName = displayName.length;
1077
+ }
1078
+ }
1079
+ const cols = process.stdout.columns ?? 80;
1080
+ const versionLen = opts.verbose ? 10 : 0;
1081
+ const prefixLen = 4 + maxName + 2 + versionLen;
973
1082
  let installedCount = 0;
974
1083
  let updateCount = 0;
1084
+ let shownCount = 0;
975
1085
  for (const [group, items] of typeGroups) {
976
- p4.log.message(pc5.bold(`
977
- ${group.charAt(0).toUpperCase() + group.slice(1)}s:`));
1086
+ items.sort((a, b) => {
1087
+ const aInst = !!(installed[a.name] ?? installed[`${a.namespace}/${a.name}`]);
1088
+ const bInst = !!(installed[b.name] ?? installed[`${b.namespace}/${b.name}`]);
1089
+ if (aInst !== bInst) return aInst ? -1 : 1;
1090
+ return a.name.localeCompare(b.name);
1091
+ });
1092
+ const label = group.charAt(0).toUpperCase() + group.slice(1) + "s";
1093
+ console.log(`
1094
+ ${pc5.bold(label)} ${pc5.dim(`(${items.length})`)}`);
978
1095
  for (const item of items) {
979
1096
  const displayName = item.namespace === "@kitn" ? item.name : `${item.namespace}/${item.name}`;
980
1097
  const inst = installed[item.name] ?? installed[displayName];
981
1098
  if (opts.installed && !inst) continue;
982
- const version = pc5.dim(`v${item.version ?? "1.0.0"}`);
1099
+ const maxDescLen = Math.max(20, cols - prefixLen);
1100
+ let desc = item.description;
1101
+ if (desc.length > maxDescLen) {
1102
+ desc = desc.slice(0, maxDescLen - 1) + "\u2026";
1103
+ }
1104
+ let line;
1105
+ const nameCol = displayName.padEnd(maxName + 2);
1106
+ const version = opts.verbose ? `${pc5.dim(`v${item.version ?? "1.0.0"}`)} ` : "";
983
1107
  if (inst) {
984
1108
  installedCount++;
985
- const status = pc5.green("\u2713");
986
1109
  const hasUpdate = item.version && inst.version !== item.version;
987
- const updateTag = hasUpdate ? pc5.yellow(` \u2B06 v${item.version} available`) : "";
988
1110
  if (hasUpdate) updateCount++;
989
- p4.log.message(` ${status} ${displayName.padEnd(20)} ${version} ${pc5.dim(item.description)}${updateTag}`);
1111
+ const updateTag = hasUpdate ? pc5.yellow(` \u2191${item.version}`) : "";
1112
+ line = ` ${pc5.green("\u2713")} ${nameCol}${version}${pc5.dim(desc)}${updateTag}`;
990
1113
  } else {
991
- const status = pc5.dim("\u25CB");
992
- p4.log.message(` ${status} ${displayName.padEnd(20)} ${version} ${pc5.dim(item.description)}`);
1114
+ line = ` ${pc5.dim("\u25CB")} ${nameCol}${version}${pc5.dim(desc)}`;
993
1115
  }
1116
+ console.log(line);
1117
+ shownCount++;
994
1118
  }
995
1119
  }
996
- const availableCount = allItems.length - installedCount;
997
- const parts = [`${installedCount} installed`, `${availableCount} available`];
998
- if (updateCount > 0) parts.push(`${updateCount} update${updateCount === 1 ? "" : "s"} available`);
999
- p4.log.message("");
1000
- p4.log.message(pc5.dim(` ${parts.join(", ")}`));
1120
+ if (shownCount === 0 && resolvedType) {
1121
+ console.log(pc5.dim(`
1122
+ No ${resolvedType} components found.`));
1123
+ }
1124
+ const parts = [`${installedCount} installed`, `${allItems.length - installedCount} available`];
1125
+ if (updateCount > 0) parts.push(pc5.yellow(`${updateCount} update${updateCount === 1 ? "" : "s"}`));
1126
+ console.log(`
1127
+ ${pc5.dim(parts.join(" \xB7 "))}
1128
+ `);
1001
1129
  }
1130
+ var TYPE_ALIASES;
1002
1131
  var init_list = __esm({
1003
1132
  "src/commands/list.ts"() {
1004
1133
  "use strict";
1005
1134
  init_config();
1006
1135
  init_fetcher();
1136
+ TYPE_ALIASES = {
1137
+ agent: "agent",
1138
+ agents: "agent",
1139
+ tool: "tool",
1140
+ tools: "tool",
1141
+ skill: "skill",
1142
+ skills: "skill",
1143
+ storage: "storage",
1144
+ storages: "storage",
1145
+ package: "package",
1146
+ packages: "package"
1147
+ };
1007
1148
  }
1008
1149
  });
1009
1150
 
@@ -1102,8 +1243,9 @@ __export(remove_exports, {
1102
1243
  });
1103
1244
  import * as p6 from "@clack/prompts";
1104
1245
  import pc6 from "picocolors";
1105
- import { join as join9 } from "path";
1106
- import { unlink } from "fs/promises";
1246
+ import { join as join9, relative as relative3, dirname as dirname3 } from "path";
1247
+ import { unlink, readFile as readFile7, writeFile as writeFile7 } from "fs/promises";
1248
+ import { existsSync as existsSync2 } from "fs";
1107
1249
  async function removeCommand(componentName) {
1108
1250
  const cwd = process.cwd();
1109
1251
  const config = await readConfig(cwd);
@@ -1136,6 +1278,32 @@ async function removeCommand(componentName) {
1136
1278
  p6.log.warn(`Could not delete ${filePath} (may have been moved or renamed)`);
1137
1279
  }
1138
1280
  }
1281
+ const baseDir = config.aliases.base ?? "src/ai";
1282
+ const barrelPath = join9(cwd, baseDir, "index.ts");
1283
+ const barrelDir = join9(cwd, baseDir);
1284
+ const barrelEligibleDirs = /* @__PURE__ */ new Set([
1285
+ config.aliases.agents,
1286
+ config.aliases.tools,
1287
+ config.aliases.skills
1288
+ ]);
1289
+ if (existsSync2(barrelPath) && deleted.length > 0) {
1290
+ let barrelContent = await readFile7(barrelPath, "utf-8");
1291
+ let barrelChanged = false;
1292
+ for (const filePath of deleted) {
1293
+ const fileDir = dirname3(filePath);
1294
+ if (!barrelEligibleDirs.has(fileDir)) continue;
1295
+ const importPath = "./" + relative3(barrelDir, join9(cwd, filePath)).replace(/\\/g, "/");
1296
+ const updated = removeImportFromBarrel(barrelContent, importPath);
1297
+ if (updated !== barrelContent) {
1298
+ barrelContent = updated;
1299
+ barrelChanged = true;
1300
+ }
1301
+ }
1302
+ if (barrelChanged) {
1303
+ await writeFile7(barrelPath, barrelContent);
1304
+ p6.log.info(`Updated barrel file: ${join9(baseDir, "index.ts")}`);
1305
+ }
1306
+ }
1139
1307
  delete config.installed[installedKey];
1140
1308
  if (Object.keys(config.installed).length === 0) {
1141
1309
  delete config.installed;
@@ -1151,6 +1319,7 @@ var init_remove = __esm({
1151
1319
  "use strict";
1152
1320
  init_config();
1153
1321
  init_parse_ref();
1322
+ init_barrel_manager();
1154
1323
  }
1155
1324
  });
1156
1325
 
@@ -1186,7 +1355,7 @@ var init_update = __esm({
1186
1355
  });
1187
1356
 
1188
1357
  // src/registry/build-output.ts
1189
- import { readdir, writeFile as writeFile6, mkdir as mkdir3, access as access4 } from "fs/promises";
1358
+ import { readdir, writeFile as writeFile8, mkdir as mkdir4, access as access4 } from "fs/promises";
1190
1359
  import { join as join10, resolve } from "path";
1191
1360
  async function fileExists(path) {
1192
1361
  try {
@@ -1261,11 +1430,11 @@ async function writeRegistryOutput(outputDir, items) {
1261
1430
  for (const item of items) {
1262
1431
  const dir = typeToDir[item.type];
1263
1432
  const typeDir = join10(resolvedOutput, dir);
1264
- await mkdir3(typeDir, { recursive: true });
1433
+ await mkdir4(typeDir, { recursive: true });
1265
1434
  const itemJson = JSON.stringify(item, null, 2);
1266
1435
  const latestPath = join10(typeDir, `${item.name}.json`);
1267
1436
  const latestRelative = `${dir}/${item.name}.json`;
1268
- await writeFile6(latestPath, itemJson, "utf-8");
1437
+ await writeFile8(latestPath, itemJson, "utf-8");
1269
1438
  written.push(latestRelative);
1270
1439
  if (item.version) {
1271
1440
  const versionedFilename = `${item.name}@${item.version}.json`;
@@ -1274,7 +1443,7 @@ async function writeRegistryOutput(outputDir, items) {
1274
1443
  if (await fileExists(versionedPath)) {
1275
1444
  skipped.push(versionedRelative);
1276
1445
  } else {
1277
- await writeFile6(versionedPath, itemJson, "utf-8");
1446
+ await writeFile8(versionedPath, itemJson, "utf-8");
1278
1447
  written.push(versionedRelative);
1279
1448
  }
1280
1449
  }
@@ -1310,7 +1479,7 @@ async function writeRegistryOutput(outputDir, items) {
1310
1479
  items: indexItems
1311
1480
  };
1312
1481
  const indexPath = join10(resolvedOutput, "registry.json");
1313
- await writeFile6(indexPath, JSON.stringify(index, null, 2), "utf-8");
1482
+ await writeFile8(indexPath, JSON.stringify(index, null, 2), "utf-8");
1314
1483
  written.push("registry.json");
1315
1484
  return { written, skipped };
1316
1485
  }
@@ -1332,8 +1501,8 @@ var init_build_output = __esm({
1332
1501
  });
1333
1502
 
1334
1503
  // src/registry/builder.ts
1335
- import { readFile as readFile7, readdir as readdir2 } from "fs/promises";
1336
- import { join as join11, relative as relative3 } from "path";
1504
+ import { readFile as readFile9, readdir as readdir2 } from "fs/promises";
1505
+ import { join as join11, relative as relative5 } from "path";
1337
1506
  function isExcludedDevDep(name) {
1338
1507
  return EXCLUDED_DEV_DEPS.has(name) || name.startsWith("@types/");
1339
1508
  }
@@ -1346,7 +1515,7 @@ async function readTsFiles(dir, baseDir, exclude) {
1346
1515
  const entries = await readdir2(dir, { withFileTypes: true });
1347
1516
  for (const entry of entries) {
1348
1517
  const fullPath = join11(dir, entry.name);
1349
- const relPath = relative3(baseDir, fullPath);
1518
+ const relPath = relative5(baseDir, fullPath);
1350
1519
  if (entry.isDirectory()) {
1351
1520
  const nested = await readTsFiles(fullPath, baseDir, exclude);
1352
1521
  results.push(...nested);
@@ -1354,7 +1523,7 @@ async function readTsFiles(dir, baseDir, exclude) {
1354
1523
  if (exclude.includes(relPath)) {
1355
1524
  continue;
1356
1525
  }
1357
- const content = await readFile7(fullPath, "utf-8");
1526
+ const content = await readFile9(fullPath, "utf-8");
1358
1527
  results.push({ relativePath: relPath, content });
1359
1528
  }
1360
1529
  }
@@ -1363,7 +1532,7 @@ async function readTsFiles(dir, baseDir, exclude) {
1363
1532
  async function buildComponent(componentDir) {
1364
1533
  let rawConfig;
1365
1534
  try {
1366
- rawConfig = await readFile7(join11(componentDir, "registry.json"), "utf-8");
1535
+ rawConfig = await readFile9(join11(componentDir, "registry.json"), "utf-8");
1367
1536
  } catch {
1368
1537
  throw new Error(
1369
1538
  `No registry.json found in ${componentDir}. Every component must have a registry.json file.`
@@ -1379,7 +1548,7 @@ async function buildComponent(componentDir) {
1379
1548
  }
1380
1549
  let pkg = null;
1381
1550
  try {
1382
- const rawPkg = await readFile7(join11(componentDir, "package.json"), "utf-8");
1551
+ const rawPkg = await readFile9(join11(componentDir, "package.json"), "utf-8");
1383
1552
  pkg = JSON.parse(rawPkg);
1384
1553
  } catch {
1385
1554
  }
@@ -1462,7 +1631,7 @@ async function buildComponent(componentDir) {
1462
1631
  const fullPath = join11(componentDir, filePath);
1463
1632
  let content;
1464
1633
  try {
1465
- content = await readFile7(fullPath, "utf-8");
1634
+ content = await readFile9(fullPath, "utf-8");
1466
1635
  } catch {
1467
1636
  throw new Error(
1468
1637
  `Cannot read file "${filePath}" referenced in registry.json for component "${name}". Make sure the file exists at ${fullPath}.`
@@ -1526,7 +1695,7 @@ __export(build_exports, {
1526
1695
  });
1527
1696
  import * as p8 from "@clack/prompts";
1528
1697
  import pc7 from "picocolors";
1529
- import { resolve as resolve2, relative as relative4 } from "path";
1698
+ import { resolve as resolve2, relative as relative6 } from "path";
1530
1699
  async function buildCommand(paths, opts) {
1531
1700
  p8.intro(pc7.bgCyan(pc7.black(" kitn build ")));
1532
1701
  const cwd = process.cwd();
@@ -1543,7 +1712,7 @@ async function buildCommand(paths, opts) {
1543
1712
  }
1544
1713
  s.stop(`Found ${componentDirs.length} component(s)`);
1545
1714
  for (const dir of componentDirs) {
1546
- p8.log.message(` ${pc7.dim(relative4(cwd, dir))}`);
1715
+ p8.log.message(` ${pc7.dim(relative6(cwd, dir))}`);
1547
1716
  }
1548
1717
  s.start("Building components...");
1549
1718
  const items = [];
@@ -1553,7 +1722,7 @@ async function buildCommand(paths, opts) {
1553
1722
  const item = await buildComponent(dir);
1554
1723
  items.push(item);
1555
1724
  } catch (err) {
1556
- errors.push({ dir: relative4(cwd, dir), error: err.message });
1725
+ errors.push({ dir: relative6(cwd, dir), error: err.message });
1557
1726
  }
1558
1727
  }
1559
1728
  if (errors.length > 0) {
@@ -1577,7 +1746,7 @@ async function buildCommand(paths, opts) {
1577
1746
  p8.log.message(` ${pc7.dim("-")} ${f}`);
1578
1747
  }
1579
1748
  }
1580
- p8.outro(`Output: ${pc7.cyan(relative4(cwd, outputDir) || ".")}`);
1749
+ p8.outro(`Output: ${pc7.cyan(relative6(cwd, outputDir) || ".")}`);
1581
1750
  }
1582
1751
  var init_build = __esm({
1583
1752
  "src/commands/build.ts"() {
@@ -1596,7 +1765,7 @@ __export(create_exports, {
1596
1765
  import * as p9 from "@clack/prompts";
1597
1766
  import pc8 from "picocolors";
1598
1767
  import { join as join12 } from "path";
1599
- import { mkdir as mkdir4, writeFile as writeFile7 } from "fs/promises";
1768
+ import { mkdir as mkdir5, writeFile as writeFile9 } from "fs/promises";
1600
1769
  function toCamelCase(str) {
1601
1770
  return str.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
1602
1771
  }
@@ -1622,24 +1791,27 @@ function generateRegistryJson(type, name, sourceFile) {
1622
1791
  }
1623
1792
  function generateAgentSource(name) {
1624
1793
  const camel = toCamelCase(name);
1625
- return `import type { AgentConfig } from "@kitnai/core";
1794
+ return `import { registerAgent } from "@kitnai/core";
1795
+
1796
+ const SYSTEM_PROMPT = "You are a helpful assistant.";
1626
1797
 
1627
- export const ${camel}Config: AgentConfig = {
1798
+ registerAgent({
1628
1799
  name: "${name}",
1629
1800
  description: "",
1630
- system: "You are a helpful assistant.",
1631
- tools: [],
1632
- };
1801
+ system: SYSTEM_PROMPT,
1802
+ tools: {},
1803
+ });
1633
1804
  `;
1634
1805
  }
1635
1806
  function generateToolSource(name) {
1636
1807
  const camel = toCamelCase(name);
1637
- return `import { tool } from "ai";
1808
+ return `import { registerTool } from "@kitnai/core";
1809
+ import { tool } from "ai";
1638
1810
  import { z } from "zod";
1639
1811
 
1640
1812
  export const ${camel} = tool({
1641
1813
  description: "",
1642
- inputSchema: z.object({
1814
+ parameters: z.object({
1643
1815
  input: z.string().describe("Input parameter"),
1644
1816
  }),
1645
1817
  execute: async ({ input }) => {
@@ -1647,6 +1819,13 @@ export const ${camel} = tool({
1647
1819
  return { result: input };
1648
1820
  },
1649
1821
  });
1822
+
1823
+ registerTool({
1824
+ name: "${name}",
1825
+ description: "",
1826
+ inputSchema: z.object({ input: z.string() }),
1827
+ tool: ${camel},
1828
+ });
1650
1829
  `;
1651
1830
  }
1652
1831
  function generateSkillSource(name) {
@@ -1691,11 +1870,11 @@ async function createComponent(type, name, opts) {
1691
1870
  if (await dirExists(dir)) {
1692
1871
  throw new Error(`Directory "${name}" already exists`);
1693
1872
  }
1694
- await mkdir4(dir, { recursive: true });
1873
+ await mkdir5(dir, { recursive: true });
1695
1874
  const validType = type;
1696
1875
  const sourceFile = validType === "skill" ? "README.md" : `${name}.ts`;
1697
1876
  const registryJson = generateRegistryJson(validType, name, sourceFile);
1698
- await writeFile7(
1877
+ await writeFile9(
1699
1878
  join12(dir, "registry.json"),
1700
1879
  JSON.stringify(registryJson, null, 2) + "\n"
1701
1880
  );
@@ -1714,7 +1893,7 @@ async function createComponent(type, name, opts) {
1714
1893
  source = generateStorageSource(name);
1715
1894
  break;
1716
1895
  }
1717
- await writeFile7(join12(dir, sourceFile), source);
1896
+ await writeFile9(join12(dir, sourceFile), source);
1718
1897
  return { dir, files: ["registry.json", sourceFile] };
1719
1898
  }
1720
1899
  async function createCommand(type, name) {
@@ -2017,7 +2196,7 @@ function startUpdateCheck(currentVersion) {
2017
2196
  }
2018
2197
 
2019
2198
  // src/index.ts
2020
- var VERSION = true ? "0.1.8" : "0.0.0-dev";
2199
+ var VERSION = true ? "0.1.10" : "0.0.0-dev";
2021
2200
  var printUpdateNotice = startUpdateCheck(VERSION);
2022
2201
  var program = new Command().name("kitn").description("Install AI agent components from the kitn registry").version(VERSION);
2023
2202
  program.command("init").description("Initialize kitn in your project").action(async () => {
@@ -2028,9 +2207,9 @@ program.command("add").description("Add components from the kitn registry").argu
2028
2207
  const { addCommand: addCommand2 } = await Promise.resolve().then(() => (init_add(), add_exports));
2029
2208
  await addCommand2(components, opts);
2030
2209
  });
2031
- program.command("list").description("List available and installed components").option("-i, --installed", "only show installed components").option("-t, --type <type>", "filter by type (agent, tool, skill, storage, package)").option("-r, --registry <namespace>", "only show components from this registry").action(async (opts) => {
2210
+ program.command("list").argument("[type]", "filter by type (agents, tools, skills, storages, packages)").description("List available and installed components").option("-i, --installed", "only show installed components").option("-t, --type <type>", "filter by type (agent, tool, skill, storage, package)").option("-r, --registry <namespace>", "only show components from this registry").option("-v, --verbose", "show version numbers").action(async (type, opts) => {
2032
2211
  const { listCommand: listCommand2 } = await Promise.resolve().then(() => (init_list(), list_exports));
2033
- await listCommand2(opts);
2212
+ await listCommand2(type, opts);
2034
2213
  });
2035
2214
  program.command("diff").description("Show differences between local and registry version").argument("<component>", "component name").action(async (component) => {
2036
2215
  const { diffCommand: diffCommand2 } = await Promise.resolve().then(() => (init_diff(), diff_exports));