@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.
- package/dist/bin/skalfa.js +17 -3
- package/dist/commands/agent.js +101 -0
- package/package.json +1 -1
package/dist/bin/skalfa.js
CHANGED
|
@@ -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
|
|
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
|
|
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
|
|
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