@kitnai/cli 0.1.31 → 0.1.32

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
@@ -1568,8 +1568,20 @@ __export(init_exports, {
1568
1568
  });
1569
1569
  import * as p3 from "@clack/prompts";
1570
1570
  import pc4 from "picocolors";
1571
- import { mkdir as mkdir5, writeFile as writeFile8 } from "fs/promises";
1571
+ import { mkdir as mkdir5, readFile as readFile7, writeFile as writeFile8 } from "fs/promises";
1572
1572
  import { join as join9 } from "path";
1573
+ async function detectFramework(cwd) {
1574
+ try {
1575
+ const pkg = JSON.parse(await readFile7(join9(cwd, "package.json"), "utf-8"));
1576
+ const deps = { ...pkg.dependencies, ...pkg.devDependencies };
1577
+ if (deps["elysia"]) return "elysia";
1578
+ if (deps["@hono/zod-openapi"]) return "hono-openapi";
1579
+ if (deps["hono"]) return "hono";
1580
+ return null;
1581
+ } catch {
1582
+ return null;
1583
+ }
1584
+ }
1573
1585
  function getPluginTemplate(framework) {
1574
1586
  const adapterName = framework === "hono-openapi" ? "hono-openapi" : framework;
1575
1587
  return `import { createAIPlugin } from "@kitn/adapters/${adapterName}";
@@ -1637,12 +1649,41 @@ async function initCommand(opts = {}) {
1637
1649
  }
1638
1650
  const validFrameworks = ["hono", "hono-openapi", "elysia"];
1639
1651
  let framework;
1652
+ const detected = await detectFramework(cwd);
1640
1653
  if (opts.framework) {
1641
1654
  if (!validFrameworks.includes(opts.framework)) {
1642
1655
  p3.log.error(`Invalid framework: ${opts.framework}. Must be one of: ${validFrameworks.join(", ")}`);
1643
1656
  process.exit(1);
1644
1657
  }
1645
1658
  framework = opts.framework;
1659
+ } else if (detected) {
1660
+ framework = detected;
1661
+ p3.log.info(`Detected ${pc4.bold(detected)} from package.json`);
1662
+ if (!opts.yes) {
1663
+ const confirm6 = await p3.confirm({
1664
+ message: `Use ${detected}?`,
1665
+ initialValue: true
1666
+ });
1667
+ if (p3.isCancel(confirm6)) {
1668
+ p3.cancel("Init cancelled.");
1669
+ process.exit(0);
1670
+ }
1671
+ if (!confirm6) {
1672
+ const selected = await p3.select({
1673
+ message: "Which HTTP framework do you use?",
1674
+ options: [
1675
+ { value: "hono", label: "Hono" },
1676
+ { value: "hono-openapi", label: "Hono + OpenAPI", hint: "zod-openapi routes with /doc endpoint" },
1677
+ { value: "elysia", label: "Elysia", hint: "Bun-native framework" }
1678
+ ]
1679
+ });
1680
+ if (p3.isCancel(selected)) {
1681
+ p3.cancel("Init cancelled.");
1682
+ process.exit(0);
1683
+ }
1684
+ framework = selected;
1685
+ }
1686
+ }
1646
1687
  } else if (opts.yes) {
1647
1688
  framework = "hono";
1648
1689
  } else {
@@ -2000,7 +2041,7 @@ __export(remove_exports, {
2000
2041
  import * as p6 from "@clack/prompts";
2001
2042
  import pc6 from "picocolors";
2002
2043
  import { join as join11, relative as relative3, dirname as dirname5 } from "path";
2003
- import { unlink as unlink3, readFile as readFile7, writeFile as writeFile9 } from "fs/promises";
2044
+ import { unlink as unlink3, readFile as readFile8, writeFile as writeFile9 } from "fs/promises";
2004
2045
  import { existsSync as existsSync2 } from "fs";
2005
2046
  async function removeSingleComponent(installedKey, lock, config, cwd) {
2006
2047
  const entry = lock[installedKey];
@@ -2023,7 +2064,7 @@ async function removeSingleComponent(installedKey, lock, config, cwd) {
2023
2064
  config.aliases.skills
2024
2065
  ]);
2025
2066
  if (existsSync2(barrelPath) && deleted.length > 0) {
2026
- let barrelContent = await readFile7(barrelPath, "utf-8");
2067
+ let barrelContent = await readFile8(barrelPath, "utf-8");
2027
2068
  let barrelChanged = false;
2028
2069
  for (const filePath of deleted) {
2029
2070
  const fileDir = dirname5(filePath);
@@ -2208,7 +2249,7 @@ import * as p8 from "@clack/prompts";
2208
2249
  import pc7 from "picocolors";
2209
2250
  import { join as join12, relative as relative4 } from "path";
2210
2251
  import { existsSync as existsSync3 } from "fs";
2211
- import { readFile as readFile8, writeFile as writeFile10, mkdir as mkdir6 } from "fs/promises";
2252
+ import { readFile as readFile9, writeFile as writeFile10, mkdir as mkdir6 } from "fs/promises";
2212
2253
  function generateAgentSource(name) {
2213
2254
  const camel = toCamelCase(name);
2214
2255
  return `import { registerAgent } from "@kitn/core";
@@ -2346,7 +2387,7 @@ async function createComponentInProject(type, name, opts) {
2346
2387
  const barrelPath = join12(cwd, baseDir, "index.ts");
2347
2388
  let barrelContent;
2348
2389
  if (existsSync3(barrelPath)) {
2349
- barrelContent = await readFile8(barrelPath, "utf-8");
2390
+ barrelContent = await readFile9(barrelPath, "utf-8");
2350
2391
  } else {
2351
2392
  barrelContent = createBarrelFile();
2352
2393
  await mkdir6(join12(cwd, baseDir), { recursive: true });
@@ -2398,7 +2439,7 @@ var init_create = __esm({
2398
2439
  });
2399
2440
 
2400
2441
  // src/utils/component-resolver.ts
2401
- import { readdir, readFile as readFile9 } from "fs/promises";
2442
+ import { readdir, readFile as readFile10 } from "fs/promises";
2402
2443
  import { join as join13, relative as relative5 } from "path";
2403
2444
  function stripSuffix(name, suffix) {
2404
2445
  if (name.endsWith(`-${suffix}`)) {
@@ -2420,7 +2461,7 @@ async function findFile(dir, candidates) {
2420
2461
  for (const name of candidates) {
2421
2462
  const filePath = join13(dir, `${name}.ts`);
2422
2463
  try {
2423
- await readFile9(filePath);
2464
+ await readFile10(filePath);
2424
2465
  return filePath;
2425
2466
  } catch {
2426
2467
  }
@@ -2455,7 +2496,7 @@ async function resolveToolByName(name, config, cwd) {
2455
2496
  if (toolFile) {
2456
2497
  const filePath2 = join13(cwd, toolFile);
2457
2498
  try {
2458
- const source2 = await readFile9(filePath2, "utf-8");
2499
+ const source2 = await readFile10(filePath2, "utf-8");
2459
2500
  const exportName2 = parseExportName(source2);
2460
2501
  if (exportName2) {
2461
2502
  return {
@@ -2473,7 +2514,7 @@ async function resolveToolByName(name, config, cwd) {
2473
2514
  const uniqueCandidates = [...new Set(candidates)];
2474
2515
  const filePath = await findFile(tDir, uniqueCandidates);
2475
2516
  if (!filePath) return null;
2476
- const source = await readFile9(filePath, "utf-8");
2517
+ const source = await readFile10(filePath, "utf-8");
2477
2518
  const exportName = parseExportName(source);
2478
2519
  if (!exportName) return null;
2479
2520
  return {
@@ -2494,7 +2535,7 @@ async function resolveAgentByName(name, config, cwd) {
2494
2535
  if (agentFile) {
2495
2536
  const filePath2 = join13(cwd, agentFile);
2496
2537
  try {
2497
- const source2 = await readFile9(filePath2, "utf-8");
2538
+ const source2 = await readFile10(filePath2, "utf-8");
2498
2539
  const agentName2 = parseAgentName(source2);
2499
2540
  return {
2500
2541
  filePath: filePath2,
@@ -2509,7 +2550,7 @@ async function resolveAgentByName(name, config, cwd) {
2509
2550
  const uniqueCandidates = [...new Set(candidates)];
2510
2551
  const filePath = await findFile(aDir, uniqueCandidates);
2511
2552
  if (!filePath) return null;
2512
- const source = await readFile9(filePath, "utf-8");
2553
+ const source = await readFile10(filePath, "utf-8");
2513
2554
  const agentName = parseAgentName(source);
2514
2555
  const fallbackName = filePath.split("/").pop().replace(/\.ts$/, "");
2515
2556
  return {
@@ -2797,7 +2838,7 @@ __export(link_exports, {
2797
2838
  });
2798
2839
  import * as p9 from "@clack/prompts";
2799
2840
  import pc8 from "picocolors";
2800
- import { readFile as readFile10, writeFile as writeFile11 } from "fs/promises";
2841
+ import { readFile as readFile11, writeFile as writeFile11 } from "fs/promises";
2801
2842
  import { basename } from "path";
2802
2843
  async function linkCommand(type, name, opts) {
2803
2844
  p9.intro(pc8.bgCyan(pc8.black(" kitn link ")));
@@ -2867,7 +2908,7 @@ async function linkCommand(type, name, opts) {
2867
2908
  );
2868
2909
  process.exit(1);
2869
2910
  }
2870
- const agentContent = await readFile10(agent.filePath, "utf-8");
2911
+ const agentContent = await readFile11(agent.filePath, "utf-8");
2871
2912
  const toolRef = {
2872
2913
  exportName: tool.exportName,
2873
2914
  importPath: tool.importPath
@@ -2913,7 +2954,7 @@ __export(unlink_exports, {
2913
2954
  });
2914
2955
  import * as p10 from "@clack/prompts";
2915
2956
  import pc9 from "picocolors";
2916
- import { readFile as readFile11, writeFile as writeFile12 } from "fs/promises";
2957
+ import { readFile as readFile12, writeFile as writeFile12 } from "fs/promises";
2917
2958
  import { basename as basename2 } from "path";
2918
2959
  async function unlinkCommand(type, name, opts) {
2919
2960
  p10.intro(pc9.bgCyan(pc9.black(" kitn unlink ")));
@@ -2983,7 +3024,7 @@ async function unlinkCommand(type, name, opts) {
2983
3024
  );
2984
3025
  process.exit(1);
2985
3026
  }
2986
- const agentContent = await readFile11(agent.filePath, "utf-8");
3027
+ const agentContent = await readFile12(agent.filePath, "utf-8");
2987
3028
  const toolRef = {
2988
3029
  exportName: tool.exportName,
2989
3030
  importPath: tool.importPath
@@ -3346,7 +3387,7 @@ var init_registry = __esm({
3346
3387
  // src/index.ts
3347
3388
  init_update_check();
3348
3389
  import { Command } from "commander";
3349
- var VERSION = true ? "0.1.31" : "0.0.0-dev";
3390
+ var VERSION = true ? "0.1.32" : "0.0.0-dev";
3350
3391
  var printUpdateNotice = startUpdateCheck(VERSION);
3351
3392
  var program = new Command().name("kitn").description("Install AI agent components from the kitn registry").version(VERSION);
3352
3393
  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) => {