@skalfa/skalfa-cli 1.0.7 → 1.0.8

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.
@@ -13,10 +13,11 @@ const create_api_1 = require("../commands/create-api");
13
13
  const create_app_1 = require("../commands/create-app");
14
14
  const pick_1 = require("../commands/pick");
15
15
  const update_1 = require("../commands/update");
16
+ const agent_1 = require("../commands/agent");
16
17
  const fs_1 = require("../utils/fs");
17
18
  // Dynamic routing / forwarding logic
18
19
  const args = process.argv.slice(2);
19
- const knownCommands = ["create-api", "create-app", "add", "pick", "update"];
20
+ const knownCommands = ["create:api", "create:app", "add", "pick", "update", "agent:install", "agent:update"];
20
21
  if (args.length > 0 && !knownCommands.includes(args[0]) && !["-h", "--help", "-v", "--version", "help"].includes(args[0])) {
21
22
  const projectRoot = (0, fs_1.findProjectRoot)(process.cwd());
22
23
  if (projectRoot) {
@@ -58,14 +59,14 @@ program
58
59
  .version(version)
59
60
  .addHelpText("before", banner);
60
61
  program
61
- .command("create-api")
62
+ .command("create:api")
62
63
  .description("Create a new Skalfa API project.")
63
64
  .argument("<name>", "project folder and package name")
64
65
  .action(async (name) => {
65
66
  await runCommand(() => (0, create_api_1.createApi)(name));
66
67
  });
67
68
  program
68
- .command("create-app")
69
+ .command("create:app")
69
70
  .description("Create a new Skalfa App Next.js project.")
70
71
  .argument("<name>", "project folder and package name")
71
72
  .action(async (name) => {
@@ -91,6 +92,19 @@ program
91
92
  .action(async () => {
92
93
  await runCommand(() => (0, update_1.updateCli)());
93
94
  });
95
+ program
96
+ .command("agent:install")
97
+ .description("Install the corresponding AI coding agent (agent-api or agent-app) into the current project.")
98
+ .option("-t, --type <type>", "Override project type detection: api or app")
99
+ .action(async (options) => {
100
+ await runCommand(() => (0, agent_1.installAgent)(options.type));
101
+ });
102
+ program
103
+ .command("agent:update")
104
+ .description("Update the installed AI coding agent to the latest version.")
105
+ .action(async () => {
106
+ await runCommand(() => (0, agent_1.updateAgent)());
107
+ });
94
108
  program.parse(process.argv);
95
109
  async function runCommand(command) {
96
110
  try {
@@ -0,0 +1,101 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.installAgent = installAgent;
7
+ exports.updateAgent = updateAgent;
8
+ const node_child_process_1 = require("node:child_process");
9
+ const node_path_1 = __importDefault(require("node:path"));
10
+ const node_fs_1 = __importDefault(require("node:fs"));
11
+ async function installAgent(overrideType) {
12
+ let type = overrideType;
13
+ // 1. Auto-detect project type if not overridden
14
+ if (!type) {
15
+ const pkgPath = node_path_1.default.join(process.cwd(), "package.json");
16
+ if (!node_fs_1.default.existsSync(pkgPath)) {
17
+ throw new Error("package.json not found. Please run this command in your project root.");
18
+ }
19
+ try {
20
+ const pkg = JSON.parse(node_fs_1.default.readFileSync(pkgPath, "utf8"));
21
+ const deps = { ...(pkg.dependencies || {}), ...(pkg.devDependencies || {}) };
22
+ const isApi = !!(deps["elysia"] || deps["knex"] || deps["@skalfa/skalfa-api-core"]);
23
+ const isApp = !!(deps["react"] || deps["next"] || deps["vite"] || deps["skalfa-app-core"]);
24
+ if (isApi) {
25
+ type = "api";
26
+ }
27
+ else if (isApp) {
28
+ type = "app";
29
+ }
30
+ else {
31
+ throw new Error("Could not auto-detect project type. Please specify using --type api or --type app.");
32
+ }
33
+ }
34
+ catch (e) {
35
+ throw new Error(`Failed to auto-detect project type: ${e.message}`);
36
+ }
37
+ }
38
+ if (type !== "api" && type !== "app") {
39
+ throw new Error("Invalid agent type. Must be 'api' or 'app'.");
40
+ }
41
+ const targetDir = node_path_1.default.join(process.cwd(), ".agents");
42
+ if (node_fs_1.default.existsSync(targetDir)) {
43
+ throw new Error(".agents folder already exists. Run 'skalfa agent:update' to pull the latest changes.");
44
+ }
45
+ const repoUrl = `https://github.com/skalfa-framework/agent-${type}.git`;
46
+ console.log(`Cloning agent-${type} from ${repoUrl}...`);
47
+ try {
48
+ // Clone repo directly into .agents/
49
+ (0, node_child_process_1.execSync)(`git clone ${repoUrl} "${targetDir}"`, { stdio: "inherit" });
50
+ }
51
+ catch (e) {
52
+ throw new Error(`Failed to clone agent repository: ${e.message}`);
53
+ }
54
+ // 2. Copy template files to records/
55
+ const templatesDir = node_path_1.default.join(targetDir, "templates");
56
+ const recordsDir = node_path_1.default.join(targetDir, "records");
57
+ if (node_fs_1.default.existsSync(templatesDir)) {
58
+ if (!node_fs_1.default.existsSync(recordsDir)) {
59
+ node_fs_1.default.mkdirSync(recordsDir, { recursive: true });
60
+ }
61
+ const files = node_fs_1.default.readdirSync(templatesDir);
62
+ for (const file of files) {
63
+ const srcFile = node_path_1.default.join(templatesDir, file);
64
+ const destFile = node_path_1.default.join(recordsDir, file);
65
+ if (!node_fs_1.default.existsSync(destFile)) {
66
+ node_fs_1.default.copyFileSync(srcFile, destFile);
67
+ console.log(`Created initial record: ${file}`);
68
+ }
69
+ }
70
+ }
71
+ // 3. Add /.agents/ to project's .gitignore
72
+ const gitignorePath = node_path_1.default.join(process.cwd(), ".gitignore");
73
+ let gitignoreContent = "";
74
+ if (node_fs_1.default.existsSync(gitignorePath)) {
75
+ gitignoreContent = node_fs_1.default.readFileSync(gitignorePath, "utf8");
76
+ }
77
+ if (!gitignoreContent.includes("/.agents/")) {
78
+ const separator = gitignoreContent.endsWith("\n") || gitignoreContent === "" ? "" : "\n";
79
+ node_fs_1.default.appendFileSync(gitignorePath, `${separator}/.agents/\n`);
80
+ console.log("Added /.agents/ to .gitignore");
81
+ }
82
+ console.log(`\nSuccessfully installed agent-${type}!`);
83
+ }
84
+ async function updateAgent() {
85
+ const targetDir = node_path_1.default.join(process.cwd(), ".agents");
86
+ if (!node_fs_1.default.existsSync(targetDir)) {
87
+ throw new Error("No agent installed in this project. Run 'skalfa agent:install' first.");
88
+ }
89
+ const gitDir = node_path_1.default.join(targetDir, ".git");
90
+ if (!node_fs_1.default.existsSync(gitDir)) {
91
+ throw new Error(".agents folder is not a Git repository.");
92
+ }
93
+ console.log("Updating agent to the latest version...");
94
+ try {
95
+ (0, node_child_process_1.execSync)("git pull", { cwd: targetDir, stdio: "inherit" });
96
+ console.log("Agent updated successfully!");
97
+ }
98
+ catch (e) {
99
+ throw new Error(`Failed to update agent: ${e.message}`);
100
+ }
101
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skalfa/skalfa-cli",
3
- "version": "1.0.7",
3
+ "version": "1.0.8",
4
4
  "description": "Command Line Interface tool for scaffolding Skalfa projects, managing extensions, and ejecting core utilities.",
5
5
  "main": "dist/bin/skalfa.js",
6
6
  "bin": {