@kitnai/cli 0.1.19 → 0.1.20

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
@@ -330,7 +330,7 @@ async function resolveDependencies(names, fetchItem) {
330
330
  const visited = /* @__PURE__ */ new Set();
331
331
  const items = /* @__PURE__ */ new Map();
332
332
  const edges = [];
333
- async function resolve3(name) {
333
+ async function resolve(name) {
334
334
  if (visited.has(name)) return;
335
335
  visited.add(name);
336
336
  const item = await fetchItem(name);
@@ -338,11 +338,11 @@ async function resolveDependencies(names, fetchItem) {
338
338
  const deps = item.registryDependencies ?? [];
339
339
  for (const dep of deps) {
340
340
  edges.push([dep, name]);
341
- await resolve3(dep);
341
+ await resolve(dep);
342
342
  }
343
343
  }
344
344
  for (const name of names) {
345
- await resolve3(name);
345
+ await resolve(name);
346
346
  }
347
347
  return topologicalSort(items, edges);
348
348
  }
@@ -1654,433 +1654,23 @@ var init_update = __esm({
1654
1654
  }
1655
1655
  });
1656
1656
 
1657
- // src/registry/build-output.ts
1658
- import { readdir, writeFile as writeFile9, mkdir as mkdir5, access as access4 } from "fs/promises";
1659
- import { join as join11, resolve } from "path";
1660
- async function fileExists(path) {
1661
- try {
1662
- await access4(path);
1663
- return true;
1664
- } catch {
1665
- return false;
1666
- }
1667
- }
1668
- async function walkForRegistryJson(dir) {
1669
- const results = [];
1670
- let entries;
1671
- try {
1672
- entries = await readdir(dir, { withFileTypes: true });
1673
- } catch {
1674
- return results;
1675
- }
1676
- if (await fileExists(join11(dir, "registry.json"))) {
1677
- results.push(dir);
1678
- return results;
1679
- }
1680
- for (const entry of entries) {
1681
- if (entry.isDirectory() && !SKIP_DIRS.has(entry.name)) {
1682
- const subResults = await walkForRegistryJson(join11(dir, entry.name));
1683
- results.push(...subResults);
1684
- }
1685
- }
1686
- return results;
1687
- }
1688
- async function scanForComponents(cwd, paths) {
1689
- const resolvedCwd = resolve(cwd);
1690
- if (paths && paths.length > 0) {
1691
- const results = [];
1692
- for (const p13 of paths) {
1693
- const absPath = resolve(resolvedCwd, p13);
1694
- if (await fileExists(join11(absPath, "registry.json"))) {
1695
- results.push(absPath);
1696
- continue;
1697
- }
1698
- let entries;
1699
- try {
1700
- entries = await readdir(absPath, { withFileTypes: true });
1701
- } catch {
1702
- continue;
1703
- }
1704
- for (const entry of entries) {
1705
- if (entry.isDirectory()) {
1706
- const subDir = join11(absPath, entry.name);
1707
- if (await fileExists(join11(subDir, "registry.json"))) {
1708
- results.push(subDir);
1709
- }
1710
- }
1711
- }
1712
- }
1713
- return results;
1714
- }
1715
- return walkForRegistryJson(resolvedCwd);
1716
- }
1717
- function parseVersionFromFilename(name, componentName) {
1718
- const prefix = `${componentName}@`;
1719
- const suffix = ".json";
1720
- if (name.startsWith(prefix) && name.endsWith(suffix)) {
1721
- return name.slice(prefix.length, -suffix.length);
1722
- }
1723
- return null;
1724
- }
1725
- async function writeRegistryOutput(outputDir, items) {
1726
- const written = [];
1727
- const skipped = [];
1728
- const resolvedOutput = resolve(outputDir);
1729
- const indexItems = [];
1730
- for (const item of items) {
1731
- const dir = typeToDir[item.type];
1732
- const typeDir = join11(resolvedOutput, dir);
1733
- await mkdir5(typeDir, { recursive: true });
1734
- const itemJson = JSON.stringify(item, null, 2);
1735
- const latestPath = join11(typeDir, `${item.name}.json`);
1736
- const latestRelative = `${dir}/${item.name}.json`;
1737
- await writeFile9(latestPath, itemJson, "utf-8");
1738
- written.push(latestRelative);
1739
- if (item.version) {
1740
- const versionedFilename = `${item.name}@${item.version}.json`;
1741
- const versionedPath = join11(typeDir, versionedFilename);
1742
- const versionedRelative = `${dir}/${versionedFilename}`;
1743
- if (await fileExists(versionedPath)) {
1744
- skipped.push(versionedRelative);
1745
- } else {
1746
- await writeFile9(versionedPath, itemJson, "utf-8");
1747
- written.push(versionedRelative);
1748
- }
1749
- }
1750
- const versions = [];
1751
- let entries;
1752
- try {
1753
- entries = await readdir(typeDir);
1754
- } catch {
1755
- entries = [];
1756
- }
1757
- for (const filename of entries) {
1758
- const ver = parseVersionFromFilename(filename, item.name);
1759
- if (ver) {
1760
- versions.push(ver);
1761
- }
1762
- }
1763
- versions.sort();
1764
- indexItems.push({
1765
- name: item.name,
1766
- type: item.type,
1767
- description: item.description,
1768
- ...item.registryDependencies && item.registryDependencies.length > 0 && {
1769
- registryDependencies: item.registryDependencies
1770
- },
1771
- ...item.categories && item.categories.length > 0 && { categories: item.categories },
1772
- ...item.version && { version: item.version },
1773
- ...versions.length > 0 && { versions },
1774
- ...item.updatedAt && { updatedAt: item.updatedAt }
1775
- });
1776
- }
1777
- const index = {
1778
- version: "1",
1779
- items: indexItems
1780
- };
1781
- const indexPath = join11(resolvedOutput, "registry.json");
1782
- await writeFile9(indexPath, JSON.stringify(index, null, 2), "utf-8");
1783
- written.push("registry.json");
1784
- return { written, skipped };
1785
- }
1786
- var SKIP_DIRS;
1787
- var init_build_output = __esm({
1788
- "src/registry/build-output.ts"() {
1789
- "use strict";
1790
- init_schema();
1791
- SKIP_DIRS = /* @__PURE__ */ new Set([
1792
- "node_modules",
1793
- "dist",
1794
- ".git",
1795
- "r",
1796
- "test",
1797
- "tests",
1798
- ".claude"
1799
- ]);
1800
- }
1801
- });
1802
-
1803
- // src/registry/builder.ts
1804
- import { readFile as readFile9, readdir as readdir2 } from "fs/promises";
1805
- import { join as join12, relative as relative5 } from "path";
1806
- function isExcludedDevDep(name) {
1807
- return EXCLUDED_DEV_DEPS.has(name) || name.startsWith("@types/");
1808
- }
1809
- function stripScope(name) {
1810
- const match = name.match(/^@[^/]+\/(.+)$/);
1811
- return match ? match[1] : name;
1812
- }
1813
- async function readTsFiles(dir, baseDir, exclude) {
1814
- const results = [];
1815
- const entries = await readdir2(dir, { withFileTypes: true });
1816
- for (const entry of entries) {
1817
- const fullPath = join12(dir, entry.name);
1818
- const relPath = relative5(baseDir, fullPath);
1819
- if (entry.isDirectory()) {
1820
- const nested = await readTsFiles(fullPath, baseDir, exclude);
1821
- results.push(...nested);
1822
- } else if (entry.isFile() && entry.name.endsWith(".ts")) {
1823
- if (exclude.includes(relPath)) {
1824
- continue;
1825
- }
1826
- const content = await readFile9(fullPath, "utf-8");
1827
- results.push({ relativePath: relPath, content });
1828
- }
1829
- }
1830
- return results;
1831
- }
1832
- async function buildComponent(componentDir) {
1833
- let rawConfig;
1834
- try {
1835
- rawConfig = await readFile9(join12(componentDir, "registry.json"), "utf-8");
1836
- } catch {
1837
- throw new Error(
1838
- `No registry.json found in ${componentDir}. Every component must have a registry.json file.`
1839
- );
1840
- }
1841
- let config;
1842
- try {
1843
- config = componentConfigSchema.parse(JSON.parse(rawConfig));
1844
- } catch (err) {
1845
- throw new Error(
1846
- `Invalid registry.json in ${componentDir}: ${err instanceof Error ? err.message : String(err)}`
1847
- );
1848
- }
1849
- let pkg = null;
1850
- try {
1851
- const rawPkg = await readFile9(join12(componentDir, "package.json"), "utf-8");
1852
- pkg = JSON.parse(rawPkg);
1853
- } catch {
1854
- }
1855
- const name = config.name ?? (pkg?.name ? stripScope(pkg.name) : void 0);
1856
- const version = config.version ?? pkg?.version;
1857
- const description = config.description ?? pkg?.description;
1858
- if (!name) {
1859
- throw new Error(
1860
- `Component in ${componentDir} is missing a name. Provide "name" in registry.json or have a package.json with a "name" field.`
1861
- );
1862
- }
1863
- if (!description) {
1864
- throw new Error(
1865
- `Component in ${componentDir} is missing a description. Provide "description" in registry.json or have a package.json with a "description" field.`
1866
- );
1867
- }
1868
- let dependencies = config.dependencies;
1869
- let devDependencies = config.devDependencies;
1870
- if (pkg && !config.dependencies) {
1871
- const deps = [];
1872
- if (pkg.dependencies) {
1873
- for (const [depName, depVersion] of Object.entries(pkg.dependencies)) {
1874
- if (depVersion !== "workspace:*") {
1875
- deps.push(depName);
1876
- }
1877
- }
1878
- }
1879
- if (pkg.peerDependencies) {
1880
- for (const [depName, depVersion] of Object.entries(pkg.peerDependencies)) {
1881
- if (depVersion !== "workspace:*") {
1882
- deps.push(depName);
1883
- }
1884
- }
1885
- }
1886
- if (deps.length > 0) {
1887
- dependencies = deps;
1888
- }
1889
- }
1890
- if (pkg && !config.devDependencies) {
1891
- const devDeps = [];
1892
- if (pkg.devDependencies) {
1893
- for (const depName of Object.keys(pkg.devDependencies)) {
1894
- if (!isExcludedDevDep(depName)) {
1895
- devDeps.push(depName);
1896
- }
1897
- }
1898
- }
1899
- if (devDeps.length > 0) {
1900
- devDependencies = devDeps;
1901
- }
1902
- }
1903
- const isPackage = config.type === "kitn:package";
1904
- const dirPrefix = config.installDir ?? typeToDir[config.type];
1905
- let files;
1906
- if (isPackage) {
1907
- const sourceDir = config.sourceDir ?? "src";
1908
- const sourcePath = join12(componentDir, sourceDir);
1909
- const exclude = config.exclude ?? [];
1910
- let tsFiles;
1911
- try {
1912
- tsFiles = await readTsFiles(sourcePath, sourcePath, exclude);
1913
- } catch {
1914
- throw new Error(
1915
- `Cannot read source directory "${sourceDir}" in ${componentDir}. Make sure it exists.`
1916
- );
1917
- }
1918
- files = tsFiles.map((f) => ({
1919
- path: `${dirPrefix}/${f.relativePath}`,
1920
- content: f.content,
1921
- type: config.type
1922
- }));
1923
- } else {
1924
- if (!config.files || config.files.length === 0) {
1925
- throw new Error(
1926
- `Component "${name}" (type: ${config.type}) has no "files" array in registry.json. Standalone components must list their source files.`
1927
- );
1928
- }
1929
- files = await Promise.all(
1930
- config.files.map(async (filePath) => {
1931
- const fullPath = join12(componentDir, filePath);
1932
- let content;
1933
- try {
1934
- content = await readFile9(fullPath, "utf-8");
1935
- } catch {
1936
- throw new Error(
1937
- `Cannot read file "${filePath}" referenced in registry.json for component "${name}". Make sure the file exists at ${fullPath}.`
1938
- );
1939
- }
1940
- return {
1941
- path: `${dirPrefix}/${filePath}`,
1942
- content,
1943
- type: config.type
1944
- };
1945
- })
1946
- );
1947
- }
1948
- const item = {
1949
- name,
1950
- type: config.type,
1951
- description,
1952
- files
1953
- };
1954
- if (version) item.version = version;
1955
- if (dependencies && dependencies.length > 0) item.dependencies = dependencies;
1956
- if (devDependencies && devDependencies.length > 0) item.devDependencies = devDependencies;
1957
- if (config.registryDependencies && config.registryDependencies.length > 0) {
1958
- item.registryDependencies = config.registryDependencies;
1959
- }
1960
- if (config.envVars) item.envVars = config.envVars;
1961
- if (config.tsconfig) item.tsconfig = config.tsconfig;
1962
- if (config.docs) item.docs = config.docs;
1963
- if (config.categories && config.categories.length > 0) item.categories = config.categories;
1964
- if (config.changelog && config.changelog.length > 0) item.changelog = config.changelog;
1965
- if (isPackage && config.installDir) item.installDir = config.installDir;
1966
- try {
1967
- return registryItemSchema.parse(item);
1968
- } catch (err) {
1969
- throw new Error(
1970
- `Built component "${name}" failed validation: ${err instanceof Error ? err.message : String(err)}`
1971
- );
1972
- }
1973
- }
1974
- var EXCLUDED_DEV_DEPS;
1975
- var init_builder = __esm({
1976
- "src/registry/builder.ts"() {
1977
- "use strict";
1978
- init_schema();
1979
- EXCLUDED_DEV_DEPS = /* @__PURE__ */ new Set([
1980
- "typescript",
1981
- "@types/bun",
1982
- "@types/node",
1983
- "tsup",
1984
- "vitest",
1985
- "jest",
1986
- "@types/jest"
1987
- ]);
1988
- }
1989
- });
1990
-
1991
- // src/commands/build.ts
1992
- var build_exports = {};
1993
- __export(build_exports, {
1994
- buildCommand: () => buildCommand
1995
- });
1996
- import * as p8 from "@clack/prompts";
1997
- import pc7 from "picocolors";
1998
- import { resolve as resolve2, relative as relative6 } from "path";
1999
- async function buildCommand(paths, opts) {
2000
- p8.intro(pc7.bgCyan(pc7.black(" kitn build ")));
2001
- const cwd = process.cwd();
2002
- const outputDir = resolve2(cwd, opts.output ?? "dist/r");
2003
- const s = p8.spinner();
2004
- s.start("Scanning for components...");
2005
- const componentDirs = await scanForComponents(cwd, paths.length > 0 ? paths : void 0);
2006
- if (componentDirs.length === 0) {
2007
- s.stop("No components found");
2008
- p8.log.info(
2009
- `No directories with ${pc7.bold("registry.json")} found. Run ${pc7.bold("kitn create")} to scaffold a component.`
2010
- );
2011
- return;
2012
- }
2013
- s.stop(`Found ${componentDirs.length} component(s)`);
2014
- p8.log.message(componentDirs.map((dir) => ` ${pc7.dim(relative6(cwd, dir))}`).join("\n"));
2015
- s.start("Building components...");
2016
- const items = [];
2017
- const errors = [];
2018
- for (const dir of componentDirs) {
2019
- try {
2020
- const item = await buildComponent(dir);
2021
- items.push(item);
2022
- } catch (err) {
2023
- errors.push({ dir: relative6(cwd, dir), error: err.message });
2024
- }
2025
- }
2026
- if (errors.length > 0) {
2027
- s.stop(pc7.red(`Build failed with ${errors.length} error(s)`));
2028
- p8.log.error(errors.map(({ dir, error }) => `${pc7.bold(dir)}: ${error}`).join("\n"));
2029
- process.exit(1);
2030
- }
2031
- const { written, skipped } = await writeRegistryOutput(outputDir, items);
2032
- s.stop(pc7.green(`Built ${items.length} component(s)`));
2033
- if (written.length > 0) {
2034
- p8.log.success(`Wrote ${written.length} file(s):
2035
- ` + written.map((f) => ` ${pc7.green("+")} ${f}`).join("\n"));
2036
- }
2037
- if (skipped.length > 0) {
2038
- p8.log.info(`Skipped ${skipped.length} file(s) (already exist):
2039
- ` + skipped.map((f) => ` ${pc7.dim("-")} ${f}`).join("\n"));
2040
- }
2041
- p8.outro(`Output: ${pc7.cyan(relative6(cwd, outputDir) || ".")}`);
2042
- }
2043
- var init_build = __esm({
2044
- "src/commands/build.ts"() {
2045
- "use strict";
2046
- init_build_output();
2047
- init_builder();
2048
- }
2049
- });
2050
-
2051
1657
  // src/commands/create.ts
2052
1658
  var create_exports = {};
2053
1659
  __export(create_exports, {
2054
1660
  createCommand: () => createCommand,
2055
- createComponent: () => createComponent
1661
+ createComponentInProject: () => createComponentInProject
2056
1662
  });
2057
- import * as p9 from "@clack/prompts";
2058
- import pc8 from "picocolors";
2059
- import { join as join13 } from "path";
2060
- import { mkdir as mkdir6, writeFile as writeFile10 } from "fs/promises";
1663
+ import * as p8 from "@clack/prompts";
1664
+ import pc7 from "picocolors";
1665
+ import { join as join11, relative as relative4 } from "path";
1666
+ import { existsSync as existsSync3 } from "fs";
1667
+ import { readFile as readFile8, writeFile as writeFile9, mkdir as mkdir5 } from "fs/promises";
2061
1668
  function toCamelCase(str) {
2062
1669
  return str.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
2063
1670
  }
2064
1671
  function toTitleCase(str) {
2065
1672
  return str.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
2066
1673
  }
2067
- function generateRegistryJson(type, name, sourceFile) {
2068
- const base = {
2069
- $schema: "https://kitn.dev/schema/registry.json",
2070
- name,
2071
- type: `kitn:${type}`,
2072
- version: "0.1.0",
2073
- description: "",
2074
- files: [sourceFile],
2075
- categories: []
2076
- };
2077
- if (type === "tool") {
2078
- base.dependencies = ["ai", "zod"];
2079
- } else if (type === "agent" || type === "storage") {
2080
- base.dependencies = [];
2081
- }
2082
- return base;
2083
- }
2084
1674
  function generateAgentSource(name) {
2085
1675
  const camel = toCamelCase(name);
2086
1676
  return `import { registerAgent } from "@kitn/core";
@@ -2103,7 +1693,7 @@ import { z } from "zod";
2103
1693
 
2104
1694
  export const ${camel} = tool({
2105
1695
  description: "",
2106
- parameters: z.object({
1696
+ inputSchema: z.object({
2107
1697
  input: z.string().describe("Input parameter"),
2108
1698
  }),
2109
1699
  execute: async ({ input }) => {
@@ -2142,34 +1732,28 @@ export function ${camel}(config?: Record<string, unknown>): StorageProvider {
2142
1732
  }
2143
1733
  `;
2144
1734
  }
2145
- async function dirExists(path) {
2146
- try {
2147
- const { stat: stat2 } = await import("fs/promises");
2148
- const s = await stat2(path);
2149
- return s.isDirectory();
2150
- } catch {
2151
- return false;
2152
- }
2153
- }
2154
- async function createComponent(type, name, opts) {
1735
+ async function createComponentInProject(type, name, opts) {
2155
1736
  if (!VALID_TYPES.includes(type)) {
2156
1737
  throw new Error(
2157
1738
  `Invalid component type: "${type}". Valid types: ${VALID_TYPES.join(", ")}`
2158
1739
  );
2159
1740
  }
2160
1741
  const cwd = opts?.cwd ?? process.cwd();
2161
- const dir = join13(cwd, name);
2162
- if (await dirExists(dir)) {
2163
- throw new Error(`Directory "${name}" already exists`);
1742
+ const config = await readConfig(cwd);
1743
+ if (!config) {
1744
+ throw new Error(
1745
+ `No kitn.json found in ${cwd}. Run ${pc7.bold("kitn init")} first.`
1746
+ );
2164
1747
  }
2165
- await mkdir6(dir, { recursive: true });
2166
1748
  const validType = type;
2167
- const sourceFile = validType === "skill" ? "README.md" : `${name}.ts`;
2168
- const registryJson = generateRegistryJson(validType, name, sourceFile);
2169
- await writeFile10(
2170
- join13(dir, "registry.json"),
2171
- JSON.stringify(registryJson, null, 2) + "\n"
2172
- );
1749
+ const kitnType = typeToKitnType[validType];
1750
+ const fileName = validType === "skill" ? `${name}.md` : `${name}.ts`;
1751
+ const filePath = join11(cwd, getInstallPath(config, kitnType, fileName));
1752
+ const dummyContent = "";
1753
+ const status = await checkFileStatus(filePath, dummyContent);
1754
+ if (status !== "new" /* New */) {
1755
+ throw new Error(`File already exists: ${filePath}`);
1756
+ }
2173
1757
  let source;
2174
1758
  switch (validType) {
2175
1759
  case "agent":
@@ -2185,31 +1769,59 @@ async function createComponent(type, name, opts) {
2185
1769
  source = generateStorageSource(name);
2186
1770
  break;
2187
1771
  }
2188
- await writeFile10(join13(dir, sourceFile), source);
2189
- return { dir, files: ["registry.json", sourceFile] };
1772
+ await writeComponentFile(filePath, source);
1773
+ let barrelUpdated = false;
1774
+ if (BARREL_TYPES.includes(validType)) {
1775
+ const baseDir = config.aliases.base ?? "src/ai";
1776
+ const barrelPath = join11(cwd, baseDir, "index.ts");
1777
+ let barrelContent;
1778
+ if (existsSync3(barrelPath)) {
1779
+ barrelContent = await readFile8(barrelPath, "utf-8");
1780
+ } else {
1781
+ barrelContent = createBarrelFile();
1782
+ await mkdir5(join11(cwd, baseDir), { recursive: true });
1783
+ }
1784
+ const importPath = "./" + relative4(join11(cwd, baseDir), filePath).replace(/\.ts$/, ".js");
1785
+ const updatedBarrel = addImportToBarrel(barrelContent, importPath);
1786
+ if (updatedBarrel !== barrelContent) {
1787
+ await writeFile9(barrelPath, updatedBarrel);
1788
+ barrelUpdated = true;
1789
+ }
1790
+ }
1791
+ return { filePath, barrelUpdated };
2190
1792
  }
2191
1793
  async function createCommand(type, name) {
2192
- p9.intro(pc8.bgCyan(pc8.black(" kitn create ")));
1794
+ p8.intro(pc7.bgCyan(pc7.black(" kitn create ")));
2193
1795
  try {
2194
- const { dir, files } = await createComponent(type, name);
2195
- p9.log.success(`Created ${pc8.bold(type)} component ${pc8.cyan(name)}`);
2196
- for (const file of files) {
2197
- p9.log.message(` ${pc8.green("+")} ${file}`);
1796
+ const { filePath, barrelUpdated } = await createComponentInProject(type, name);
1797
+ p8.log.success(`Created ${pc7.bold(type)} component ${pc7.cyan(name)}`);
1798
+ p8.log.message(` ${pc7.green("+")} ${filePath}`);
1799
+ if (barrelUpdated) {
1800
+ p8.log.message(` ${pc7.green("+")} barrel file updated`);
2198
1801
  }
2199
- const editFile = files.find((f) => f !== "registry.json") ?? files[0];
2200
- p9.outro(
2201
- `Edit ${pc8.cyan(`${name}/${editFile}`)}, then run ${pc8.bold("kitn build")}`
1802
+ p8.outro(
1803
+ `Edit ${pc7.cyan(filePath)} to customize your ${type}.`
2202
1804
  );
2203
1805
  } catch (err) {
2204
- p9.log.error(err.message);
1806
+ p8.log.error(err.message);
2205
1807
  process.exit(1);
2206
1808
  }
2207
1809
  }
2208
- var VALID_TYPES;
1810
+ var VALID_TYPES, typeToKitnType, BARREL_TYPES;
2209
1811
  var init_create = __esm({
2210
1812
  "src/commands/create.ts"() {
2211
1813
  "use strict";
1814
+ init_config();
1815
+ init_file_writer();
1816
+ init_barrel_manager();
2212
1817
  VALID_TYPES = ["agent", "tool", "skill", "storage"];
1818
+ typeToKitnType = {
1819
+ agent: "kitn:agent",
1820
+ tool: "kitn:tool",
1821
+ skill: "kitn:skill",
1822
+ storage: "kitn:storage"
1823
+ };
1824
+ BARREL_TYPES = ["agent", "tool", "skill"];
2213
1825
  }
2214
1826
  });
2215
1827
 
@@ -2218,31 +1830,31 @@ var info_exports = {};
2218
1830
  __export(info_exports, {
2219
1831
  infoCommand: () => infoCommand
2220
1832
  });
2221
- import * as p10 from "@clack/prompts";
2222
- import pc9 from "picocolors";
1833
+ import * as p9 from "@clack/prompts";
1834
+ import pc8 from "picocolors";
2223
1835
  async function infoCommand(component) {
2224
1836
  const cwd = process.cwd();
2225
1837
  const config = await readConfig(cwd);
2226
1838
  if (!config) {
2227
- p10.log.error("No kitn.json found. Run `kitn init` first.");
1839
+ p9.log.error("No kitn.json found. Run `kitn init` first.");
2228
1840
  process.exit(1);
2229
1841
  }
2230
1842
  const ref = parseComponentRef(component);
2231
1843
  const fetcher = new RegistryFetcher(config.registries);
2232
- const s = p10.spinner();
1844
+ const s = p9.spinner();
2233
1845
  s.start("Fetching component info...");
2234
1846
  let index;
2235
1847
  try {
2236
1848
  index = await fetcher.fetchIndex(ref.namespace);
2237
1849
  } catch (err) {
2238
- s.stop(pc9.red("Failed to fetch registry"));
2239
- p10.log.error(err.message);
1850
+ s.stop(pc8.red("Failed to fetch registry"));
1851
+ p9.log.error(err.message);
2240
1852
  process.exit(1);
2241
1853
  }
2242
1854
  const indexItem = index.items.find((i) => i.name === ref.name);
2243
1855
  if (!indexItem) {
2244
- s.stop(pc9.red("Component not found"));
2245
- p10.log.error(`Component '${ref.name}' not found in registry.`);
1856
+ s.stop(pc8.red("Component not found"));
1857
+ p9.log.error(`Component '${ref.name}' not found in registry.`);
2246
1858
  process.exit(1);
2247
1859
  }
2248
1860
  const dir = typeToDir[indexItem.type];
@@ -2250,8 +1862,8 @@ async function infoCommand(component) {
2250
1862
  try {
2251
1863
  item = await fetcher.fetchItem(ref.name, dir, ref.namespace, ref.version);
2252
1864
  } catch (err) {
2253
- s.stop(pc9.red("Failed to fetch component"));
2254
- p10.log.error(err.message);
1865
+ s.stop(pc8.red("Failed to fetch component"));
1866
+ p9.log.error(err.message);
2255
1867
  process.exit(1);
2256
1868
  }
2257
1869
  s.stop("Component found");
@@ -2259,62 +1871,62 @@ async function infoCommand(component) {
2259
1871
  const typeName = indexItem.type.replace("kitn:", "");
2260
1872
  console.log();
2261
1873
  console.log(
2262
- ` ${pc9.bold(item.name)} ${pc9.cyan(`v${version}`)}${" ".repeat(Math.max(1, 40 - item.name.length - version.length - 2))}${pc9.dim(ref.namespace)}`
1874
+ ` ${pc8.bold(item.name)} ${pc8.cyan(`v${version}`)}${" ".repeat(Math.max(1, 40 - item.name.length - version.length - 2))}${pc8.dim(ref.namespace)}`
2263
1875
  );
2264
- console.log(` ${pc9.dim(item.description)}`);
1876
+ console.log(` ${pc8.dim(item.description)}`);
2265
1877
  console.log();
2266
- console.log(` ${pc9.dim("Type:")} ${typeName}`);
1878
+ console.log(` ${pc8.dim("Type:")} ${typeName}`);
2267
1879
  if (item.dependencies?.length) {
2268
1880
  console.log(
2269
- ` ${pc9.dim("Dependencies:")} ${item.dependencies.join(", ")}`
1881
+ ` ${pc8.dim("Dependencies:")} ${item.dependencies.join(", ")}`
2270
1882
  );
2271
1883
  }
2272
1884
  if (item.registryDependencies?.length) {
2273
1885
  console.log(
2274
- ` ${pc9.dim("Registry deps:")} ${item.registryDependencies.join(", ")}`
1886
+ ` ${pc8.dim("Registry deps:")} ${item.registryDependencies.join(", ")}`
2275
1887
  );
2276
1888
  }
2277
1889
  if (item.categories?.length) {
2278
1890
  console.log(
2279
- ` ${pc9.dim("Categories:")} ${item.categories.join(", ")}`
1891
+ ` ${pc8.dim("Categories:")} ${item.categories.join(", ")}`
2280
1892
  );
2281
1893
  }
2282
1894
  if (item.updatedAt) {
2283
- console.log(` ${pc9.dim("Updated:")} ${item.updatedAt}`);
1895
+ console.log(` ${pc8.dim("Updated:")} ${item.updatedAt}`);
2284
1896
  }
2285
1897
  const versions = indexItem.versions;
2286
1898
  if (versions?.length) {
2287
- console.log(` ${pc9.dim("Versions:")} ${versions.join(", ")}`);
1899
+ console.log(` ${pc8.dim("Versions:")} ${versions.join(", ")}`);
2288
1900
  }
2289
1901
  if (item.changelog?.length) {
2290
1902
  console.log();
2291
- console.log(` ${pc9.bold("Changelog:")}`);
1903
+ console.log(` ${pc8.bold("Changelog:")}`);
2292
1904
  for (const entry of item.changelog) {
2293
- const tag = entry.type === "feature" ? pc9.green(entry.type) : entry.type === "fix" ? pc9.yellow(entry.type) : entry.type === "breaking" ? pc9.red(entry.type) : pc9.dim(entry.type);
1905
+ const tag = entry.type === "feature" ? pc8.green(entry.type) : entry.type === "fix" ? pc8.yellow(entry.type) : entry.type === "breaking" ? pc8.red(entry.type) : pc8.dim(entry.type);
2294
1906
  console.log(
2295
- ` ${pc9.cyan(entry.version)} ${pc9.dim(entry.date)} ${tag} ${entry.note}`
1907
+ ` ${pc8.cyan(entry.version)} ${pc8.dim(entry.date)} ${tag} ${entry.note}`
2296
1908
  );
2297
1909
  }
2298
1910
  }
2299
1911
  console.log();
2300
1912
  const fileCount = item.files.length;
2301
- console.log(` ${pc9.bold(`Files:`)} ${pc9.dim(`(${fileCount})`)}`);
1913
+ console.log(` ${pc8.bold(`Files:`)} ${pc8.dim(`(${fileCount})`)}`);
2302
1914
  const maxShown = 10;
2303
1915
  for (const file of item.files.slice(0, maxShown)) {
2304
- console.log(` ${pc9.dim(file.path)}`);
1916
+ console.log(` ${pc8.dim(file.path)}`);
2305
1917
  }
2306
1918
  if (fileCount > maxShown) {
2307
- console.log(` ${pc9.dim(`... and ${fileCount - maxShown} more`)}`);
1919
+ console.log(` ${pc8.dim(`... and ${fileCount - maxShown} more`)}`);
2308
1920
  }
2309
1921
  const installed = config.installed?.[item.name];
2310
1922
  if (installed) {
2311
1923
  console.log();
2312
1924
  console.log(
2313
- ` ${pc9.green("Installed")} ${pc9.dim(`v${installed.version}`)}`
1925
+ ` ${pc8.green("Installed")} ${pc8.dim(`v${installed.version}`)}`
2314
1926
  );
2315
1927
  if (version !== installed.version) {
2316
1928
  console.log(
2317
- ` ${pc9.yellow("Update available:")} ${pc9.dim(`v${installed.version}`)} \u2192 ${pc9.cyan(`v${version}`)}`
1929
+ ` ${pc8.yellow("Update available:")} ${pc8.dim(`v${installed.version}`)} \u2192 ${pc8.cyan(`v${version}`)}`
2318
1930
  );
2319
1931
  }
2320
1932
  }
@@ -2335,26 +1947,26 @@ var check_exports = {};
2335
1947
  __export(check_exports, {
2336
1948
  checkCommand: () => checkCommand
2337
1949
  });
2338
- import * as p11 from "@clack/prompts";
2339
- import pc10 from "picocolors";
1950
+ import * as p10 from "@clack/prompts";
1951
+ import pc9 from "picocolors";
2340
1952
  async function checkCommand(currentVersion) {
2341
- p11.intro(pc10.bgCyan(pc10.black(" kitn check ")));
2342
- p11.log.info(`kitn v${currentVersion}`);
2343
- const s = p11.spinner();
1953
+ p10.intro(pc9.bgCyan(pc9.black(" kitn check ")));
1954
+ p10.log.info(`kitn v${currentVersion}`);
1955
+ const s = p10.spinner();
2344
1956
  s.start("Checking for updates...");
2345
1957
  const latest = await fetchLatestVersion();
2346
1958
  if (!latest) {
2347
- s.stop(pc10.yellow("Could not reach the npm registry"));
2348
- p11.outro("Try again later.");
1959
+ s.stop(pc9.yellow("Could not reach the npm registry"));
1960
+ p10.outro("Try again later.");
2349
1961
  return;
2350
1962
  }
2351
1963
  if (isNewer(latest, currentVersion)) {
2352
- s.stop(pc10.yellow(`Update available: ${currentVersion} \u2192 ${latest}`));
2353
- p11.log.message(` Run: ${pc10.cyan("npm i -g @kitnai/cli")}`);
1964
+ s.stop(pc9.yellow(`Update available: ${currentVersion} \u2192 ${latest}`));
1965
+ p10.log.message(` Run: ${pc9.cyan("npm i -g @kitnai/cli")}`);
2354
1966
  } else {
2355
- s.stop(pc10.green("You're on the latest version"));
1967
+ s.stop(pc9.green("You're on the latest version"));
2356
1968
  }
2357
- p11.outro("");
1969
+ p10.outro("");
2358
1970
  }
2359
1971
  var init_check = __esm({
2360
1972
  "src/commands/check.ts"() {
@@ -2370,8 +1982,8 @@ __export(registry_exports, {
2370
1982
  registryListCommand: () => registryListCommand,
2371
1983
  registryRemoveCommand: () => registryRemoveCommand
2372
1984
  });
2373
- import * as p12 from "@clack/prompts";
2374
- import pc11 from "picocolors";
1985
+ import * as p11 from "@clack/prompts";
1986
+ import pc10 from "picocolors";
2375
1987
  async function registryAddCommand(namespace, url, opts = {}) {
2376
1988
  const cwd = opts.cwd ?? process.cwd();
2377
1989
  const config = await readConfig(cwd);
@@ -2397,10 +2009,10 @@ async function registryAddCommand(namespace, url, opts = {}) {
2397
2009
  config.registries[namespace] = url;
2398
2010
  }
2399
2011
  await writeConfig(cwd, config);
2400
- p12.log.success(`Added registry ${pc11.bold(namespace)}`);
2401
- p12.log.message(pc11.dim(` ${url}`));
2402
- if (opts.homepage) p12.log.message(pc11.dim(` Homepage: ${opts.homepage}`));
2403
- if (opts.description) p12.log.message(pc11.dim(` ${opts.description}`));
2012
+ p11.log.success(`Added registry ${pc10.bold(namespace)}`);
2013
+ p11.log.message(pc10.dim(` ${url}`));
2014
+ if (opts.homepage) p11.log.message(pc10.dim(` Homepage: ${opts.homepage}`));
2015
+ if (opts.description) p11.log.message(pc10.dim(` ${opts.description}`));
2404
2016
  }
2405
2017
  async function registryRemoveCommand(namespace, opts = {}) {
2406
2018
  const cwd = opts.cwd ?? process.cwd();
@@ -2422,10 +2034,10 @@ async function registryRemoveCommand(namespace, opts = {}) {
2422
2034
  }
2423
2035
  delete config.registries[namespace];
2424
2036
  await writeConfig(cwd, config);
2425
- p12.log.success(`Removed registry ${pc11.bold(namespace)}`);
2037
+ p11.log.success(`Removed registry ${pc10.bold(namespace)}`);
2426
2038
  if (affectedComponents.length > 0) {
2427
- p12.log.warn(`${affectedComponents.length} installed component(s) referenced this registry:
2428
- ` + affectedComponents.map((name) => ` ${pc11.yellow("!")} ${name}`).join("\n"));
2039
+ p11.log.warn(`${affectedComponents.length} installed component(s) referenced this registry:
2040
+ ` + affectedComponents.map((name) => ` ${pc10.yellow("!")} ${name}`).join("\n"));
2429
2041
  }
2430
2042
  return { affectedComponents };
2431
2043
  }
@@ -2440,15 +2052,15 @@ async function registryListCommand(opts = {}) {
2440
2052
  return { namespace, url, homepage, description };
2441
2053
  });
2442
2054
  if (entries.length === 0) {
2443
- p12.log.message(pc11.dim(" No registries configured."));
2055
+ p11.log.message(pc10.dim(" No registries configured."));
2444
2056
  } else {
2445
2057
  const lines = [];
2446
2058
  for (const { namespace, url, homepage, description } of entries) {
2447
- lines.push(` ${pc11.bold(namespace.padEnd(16))} ${pc11.dim(url)}`);
2059
+ lines.push(` ${pc10.bold(namespace.padEnd(16))} ${pc10.dim(url)}`);
2448
2060
  if (description) lines.push(` ${" ".repeat(16)} ${description}`);
2449
- if (homepage) lines.push(` ${" ".repeat(16)} ${pc11.dim(homepage)}`);
2061
+ if (homepage) lines.push(` ${" ".repeat(16)} ${pc10.dim(homepage)}`);
2450
2062
  }
2451
- p12.log.message(lines.join("\n"));
2063
+ p11.log.message(lines.join("\n"));
2452
2064
  }
2453
2065
  return entries;
2454
2066
  }
@@ -2462,7 +2074,7 @@ var init_registry = __esm({
2462
2074
  // src/index.ts
2463
2075
  init_update_check();
2464
2076
  import { Command } from "commander";
2465
- var VERSION = true ? "0.1.19" : "0.0.0-dev";
2077
+ var VERSION = true ? "0.1.20" : "0.0.0-dev";
2466
2078
  var printUpdateNotice = startUpdateCheck(VERSION);
2467
2079
  var program = new Command().name("kitn").description("Install AI agent components from the kitn registry").version(VERSION);
2468
2080
  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) => {
@@ -2489,10 +2101,6 @@ program.command("update").description("Update installed components to latest reg
2489
2101
  const { updateCommand: updateCommand2 } = await Promise.resolve().then(() => (init_update(), update_exports));
2490
2102
  await updateCommand2(components);
2491
2103
  });
2492
- program.command("build").description("Build registry JSON from components with registry.json files").argument("[paths...]", "directories to build (default: scan from cwd)").option("-o, --output <dir>", "output directory", "dist/r").action(async (paths, opts) => {
2493
- const { buildCommand: buildCommand2 } = await Promise.resolve().then(() => (init_build(), build_exports));
2494
- await buildCommand2(paths, opts);
2495
- });
2496
2104
  program.command("create").description("Scaffold a new kitn component").argument("<type>", "component type (agent, tool, skill, storage)").argument("<name>", "component name").action(async (type, name) => {
2497
2105
  const { createCommand: createCommand2 } = await Promise.resolve().then(() => (init_create(), create_exports));
2498
2106
  await createCommand2(type, name);