@jvittechs/j 1.0.41 → 1.0.43
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/{chunk-ZG3KLHJ4.js → chunk-WPXT7BL7.js} +37 -1
- package/dist/chunk-WPXT7BL7.js.map +1 -0
- package/dist/cli.js +407 -244
- package/dist/cli.js.map +1 -1
- package/dist/{summary-AEJ34P4Q.js → summary-WWNFDPZX.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-ZG3KLHJ4.js.map +0 -1
- /package/dist/{summary-AEJ34P4Q.js.map → summary-WWNFDPZX.js.map} +0 -0
package/dist/cli.js
CHANGED
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
STATUS_ICONS,
|
|
14
14
|
TaskService,
|
|
15
15
|
createTaskSummaryCommand
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-WPXT7BL7.js";
|
|
17
17
|
|
|
18
18
|
// src/utils/node-version-check.ts
|
|
19
19
|
import chalk from "chalk";
|
|
@@ -49,7 +49,7 @@ function checkNodeVersion() {
|
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
// src/cli.ts
|
|
52
|
-
import { Command as
|
|
52
|
+
import { Command as Command89 } from "commander";
|
|
53
53
|
|
|
54
54
|
// src/services/error-log.service.ts
|
|
55
55
|
import { promises as fs } from "fs";
|
|
@@ -149,7 +149,7 @@ import { basename as basename5 } from "path";
|
|
|
149
149
|
// package.json
|
|
150
150
|
var package_default = {
|
|
151
151
|
name: "@jvittechs/j",
|
|
152
|
-
version: "1.0.
|
|
152
|
+
version: "1.0.43",
|
|
153
153
|
description: "A unified CLI tool for JV-IT TECHS developers to manage Jai1 Framework. Supports both `j` and `jai1` commands. Please contact TeamAI for usage instructions.",
|
|
154
154
|
type: "module",
|
|
155
155
|
bin: {
|
|
@@ -10801,7 +10801,7 @@ function createHooksCommand() {
|
|
|
10801
10801
|
}
|
|
10802
10802
|
|
|
10803
10803
|
// src/commands/tasks/index.ts
|
|
10804
|
-
import { Command as
|
|
10804
|
+
import { Command as Command61 } from "commander";
|
|
10805
10805
|
|
|
10806
10806
|
// src/commands/tasks/add.ts
|
|
10807
10807
|
import { Command as Command48 } from "commander";
|
|
@@ -11338,9 +11338,165 @@ function createTaskParentsCommand() {
|
|
|
11338
11338
|
});
|
|
11339
11339
|
}
|
|
11340
11340
|
|
|
11341
|
+
// src/commands/tasks/cancel.ts
|
|
11342
|
+
import { Command as Command59 } from "commander";
|
|
11343
|
+
import chalk32 from "chalk";
|
|
11344
|
+
import { confirm as confirm10 } from "@inquirer/prompts";
|
|
11345
|
+
function createTaskCancelCommand() {
|
|
11346
|
+
return new Command59("cancel").description("Cancel a task (with dependency impact check)").argument("<id>", "Task ID (e.g. T-001)").option("-y, --yes", "Skip confirmation").option("-j, --json", "Output JSON").action(async (id, options) => {
|
|
11347
|
+
const service = new TaskService();
|
|
11348
|
+
try {
|
|
11349
|
+
const task = await service.findById(id);
|
|
11350
|
+
if (!task) {
|
|
11351
|
+
console.error(chalk32.red(`\u274C Task ${id} not found`));
|
|
11352
|
+
process.exit(1);
|
|
11353
|
+
}
|
|
11354
|
+
if (task.status === "cancelled") {
|
|
11355
|
+
console.error(chalk32.yellow(`\u26A0\uFE0F Task ${id} is already cancelled`));
|
|
11356
|
+
process.exit(0);
|
|
11357
|
+
}
|
|
11358
|
+
if (task.status === "done") {
|
|
11359
|
+
console.error(chalk32.red(`\u274C Task ${id} is already done \u2014 cannot cancel`));
|
|
11360
|
+
process.exit(1);
|
|
11361
|
+
}
|
|
11362
|
+
const dependents = await service.getDependents(id);
|
|
11363
|
+
const activeDependents = dependents.filter(
|
|
11364
|
+
(t) => t.status !== "done" && t.status !== "cancelled"
|
|
11365
|
+
);
|
|
11366
|
+
const icon = STATUS_ICONS[task.status] || "\u{1F4CB}";
|
|
11367
|
+
console.log(chalk32.bold(`
|
|
11368
|
+
\u26AB Cancel: ${icon} ${task.id} \u2014 ${task.title}
|
|
11369
|
+
`));
|
|
11370
|
+
if (activeDependents.length > 0) {
|
|
11371
|
+
console.log(chalk32.yellow(`\u26A0\uFE0F ${activeDependents.length} task(s) ph\u1EE5 thu\u1ED9c v\xE0o ${id}:`));
|
|
11372
|
+
for (const dep of activeDependents) {
|
|
11373
|
+
const depIcon = STATUS_ICONS[dep.status] || "\u{1F4CB}";
|
|
11374
|
+
console.log(` ${depIcon} ${chalk32.dim(dep.id)} ${dep.title}`);
|
|
11375
|
+
}
|
|
11376
|
+
console.log(
|
|
11377
|
+
chalk32.dim(
|
|
11378
|
+
`
|
|
11379
|
+
\u2192 Cancel s\u1EBD resolve dependency, c\xE1c task tr\xEAn c\xF3 th\u1EC3 \u0111\u01B0\u1EE3c unblock.`
|
|
11380
|
+
)
|
|
11381
|
+
);
|
|
11382
|
+
console.log();
|
|
11383
|
+
}
|
|
11384
|
+
if (!options.yes) {
|
|
11385
|
+
const proceed = await confirm10({
|
|
11386
|
+
message: `Cancel task ${id}?`,
|
|
11387
|
+
default: false
|
|
11388
|
+
});
|
|
11389
|
+
if (!proceed) {
|
|
11390
|
+
console.log(chalk32.dim("\u0110\xE3 hu\u1EF7."));
|
|
11391
|
+
return;
|
|
11392
|
+
}
|
|
11393
|
+
}
|
|
11394
|
+
const updated = await service.cancel(id);
|
|
11395
|
+
if (options.json) {
|
|
11396
|
+
console.log(JSON.stringify(updated, null, 2));
|
|
11397
|
+
return;
|
|
11398
|
+
}
|
|
11399
|
+
console.log(chalk32.green(`\u2705 ${updated.id}: ${updated.title} \u2192 cancelled`));
|
|
11400
|
+
} catch (error) {
|
|
11401
|
+
console.error(
|
|
11402
|
+
chalk32.red(`\u274C ${error instanceof Error ? error.message : String(error)}`)
|
|
11403
|
+
);
|
|
11404
|
+
process.exit(1);
|
|
11405
|
+
}
|
|
11406
|
+
});
|
|
11407
|
+
}
|
|
11408
|
+
|
|
11409
|
+
// src/commands/tasks/delete.ts
|
|
11410
|
+
import { Command as Command60 } from "commander";
|
|
11411
|
+
import chalk33 from "chalk";
|
|
11412
|
+
import { confirm as confirm11 } from "@inquirer/prompts";
|
|
11413
|
+
function createTaskDeleteCommand() {
|
|
11414
|
+
return new Command60("delete").description("Delete a task permanently (with dependency impact check)").argument("<id>", "Task ID (e.g. T-001)").option("-y, --yes", "Skip confirmation").option("-j, --json", "Output JSON before deletion").action(async (id, options) => {
|
|
11415
|
+
const service = new TaskService();
|
|
11416
|
+
try {
|
|
11417
|
+
const task = await service.findById(id);
|
|
11418
|
+
if (!task) {
|
|
11419
|
+
console.error(chalk33.red(`\u274C Task ${id} not found`));
|
|
11420
|
+
process.exit(1);
|
|
11421
|
+
}
|
|
11422
|
+
const dependents = await service.getDependents(id);
|
|
11423
|
+
const icon = STATUS_ICONS[task.status] || "\u{1F4CB}";
|
|
11424
|
+
console.log(chalk33.bold(`
|
|
11425
|
+
\u{1F5D1}\uFE0F Delete: ${icon} ${task.id} \u2014 ${task.title}
|
|
11426
|
+
`));
|
|
11427
|
+
console.log(` ${chalk33.dim("Status:")} ${task.status}`);
|
|
11428
|
+
console.log(` ${chalk33.dim("Parent:")} ${task.parent || "(none)"}`);
|
|
11429
|
+
if (task.depends_on.length > 0) {
|
|
11430
|
+
console.log(` ${chalk33.dim("Depends:")} ${task.depends_on.join(", ")}`);
|
|
11431
|
+
}
|
|
11432
|
+
console.log();
|
|
11433
|
+
if (dependents.length > 0) {
|
|
11434
|
+
const activeDependents = dependents.filter(
|
|
11435
|
+
(t) => t.status !== "done" && t.status !== "cancelled"
|
|
11436
|
+
);
|
|
11437
|
+
const resolvedDependents = dependents.filter(
|
|
11438
|
+
(t) => t.status === "done" || t.status === "cancelled"
|
|
11439
|
+
);
|
|
11440
|
+
console.log(
|
|
11441
|
+
chalk33.yellow(
|
|
11442
|
+
`\u26A0\uFE0F ${dependents.length} task(s) c\xF3 depends_on \u2192 ${id}:`
|
|
11443
|
+
)
|
|
11444
|
+
);
|
|
11445
|
+
for (const dep of dependents) {
|
|
11446
|
+
const depIcon = STATUS_ICONS[dep.status] || "\u{1F4CB}";
|
|
11447
|
+
console.log(` ${depIcon} ${chalk33.dim(dep.id)} ${dep.title}`);
|
|
11448
|
+
}
|
|
11449
|
+
console.log(
|
|
11450
|
+
chalk33.dim(
|
|
11451
|
+
`
|
|
11452
|
+
\u2192 Xo\xE1 s\u1EBD remove ${id} kh\u1ECFi depends_on c\u1EE7a c\xE1c task tr\xEAn.`
|
|
11453
|
+
)
|
|
11454
|
+
);
|
|
11455
|
+
if (activeDependents.length > 0) {
|
|
11456
|
+
console.log(
|
|
11457
|
+
chalk33.dim(
|
|
11458
|
+
` \u2192 ${activeDependents.length} task(s) ch\u01B0a done c\xF3 th\u1EC3 b\u1ECB \u1EA3nh h\u01B0\u1EDFng (unblock).`
|
|
11459
|
+
)
|
|
11460
|
+
);
|
|
11461
|
+
}
|
|
11462
|
+
console.log();
|
|
11463
|
+
}
|
|
11464
|
+
if (!options.yes) {
|
|
11465
|
+
const proceed = await confirm11({
|
|
11466
|
+
message: `Xo\xE1 v\u0129nh vi\u1EC5n task ${id}?`,
|
|
11467
|
+
default: false
|
|
11468
|
+
});
|
|
11469
|
+
if (!proceed) {
|
|
11470
|
+
console.log(chalk33.dim("\u0110\xE3 hu\u1EF7."));
|
|
11471
|
+
return;
|
|
11472
|
+
}
|
|
11473
|
+
}
|
|
11474
|
+
if (options.json) {
|
|
11475
|
+
console.log(JSON.stringify({ deleted: task, dependentsUpdated: dependents.map((d) => d.id) }, null, 2));
|
|
11476
|
+
}
|
|
11477
|
+
await service.deleteTask(id);
|
|
11478
|
+
if (!options.json) {
|
|
11479
|
+
console.log(chalk33.green(`\u2705 \u0110\xE3 xo\xE1 ${task.id}: ${task.title}`));
|
|
11480
|
+
if (dependents.length > 0) {
|
|
11481
|
+
console.log(
|
|
11482
|
+
chalk33.dim(
|
|
11483
|
+
` \u0110\xE3 c\u1EADp nh\u1EADt depends_on cho: ${dependents.map((d) => d.id).join(", ")}`
|
|
11484
|
+
)
|
|
11485
|
+
);
|
|
11486
|
+
}
|
|
11487
|
+
}
|
|
11488
|
+
} catch (error) {
|
|
11489
|
+
console.error(
|
|
11490
|
+
chalk33.red(`\u274C ${error instanceof Error ? error.message : String(error)}`)
|
|
11491
|
+
);
|
|
11492
|
+
process.exit(1);
|
|
11493
|
+
}
|
|
11494
|
+
});
|
|
11495
|
+
}
|
|
11496
|
+
|
|
11341
11497
|
// src/commands/tasks/index.ts
|
|
11342
11498
|
function createTasksCommand() {
|
|
11343
|
-
const cmd = new
|
|
11499
|
+
const cmd = new Command61("tasks").alias("t").description("Task management \u2014 track, assign, and manage development tasks").hook("preAction", (thisCommand, actionCommand) => {
|
|
11344
11500
|
if (actionCommand.name() !== "guide") {
|
|
11345
11501
|
TaskService.ensureJai1Dir();
|
|
11346
11502
|
}
|
|
@@ -11356,21 +11512,23 @@ function createTasksCommand() {
|
|
|
11356
11512
|
cmd.addCommand(createTaskSyncCommand());
|
|
11357
11513
|
cmd.addCommand(createTaskSummaryCommand());
|
|
11358
11514
|
cmd.addCommand(createTaskParentsCommand());
|
|
11515
|
+
cmd.addCommand(createTaskCancelCommand());
|
|
11516
|
+
cmd.addCommand(createTaskDeleteCommand());
|
|
11359
11517
|
cmd.addCommand(createTaskGuideCommand());
|
|
11360
11518
|
cmd.action(async () => {
|
|
11361
|
-
const { handleTaskSummary } = await import("./summary-
|
|
11519
|
+
const { handleTaskSummary } = await import("./summary-WWNFDPZX.js");
|
|
11362
11520
|
await handleTaskSummary({ json: false });
|
|
11363
11521
|
});
|
|
11364
11522
|
return cmd;
|
|
11365
11523
|
}
|
|
11366
11524
|
|
|
11367
11525
|
// src/commands/kit/index.ts
|
|
11368
|
-
import { Command as
|
|
11369
|
-
import
|
|
11526
|
+
import { Command as Command65 } from "commander";
|
|
11527
|
+
import chalk35 from "chalk";
|
|
11370
11528
|
|
|
11371
11529
|
// src/commands/kit/list.ts
|
|
11372
|
-
import { Command as
|
|
11373
|
-
import
|
|
11530
|
+
import { Command as Command62 } from "commander";
|
|
11531
|
+
import chalk34 from "chalk";
|
|
11374
11532
|
import Table6 from "cli-table3";
|
|
11375
11533
|
|
|
11376
11534
|
// src/services/starter-kit.service.ts
|
|
@@ -11438,13 +11596,13 @@ var StarterKitService = class {
|
|
|
11438
11596
|
|
|
11439
11597
|
// src/commands/kit/list.ts
|
|
11440
11598
|
function createKitListCommand() {
|
|
11441
|
-
return new
|
|
11599
|
+
return new Command62("list").description("List available starter kits").option("-c, --category <category>", "Filter by category (backend, frontend, fullstack)").option("-s, --search <term>", "Search kits by name or description").action(async (options) => {
|
|
11442
11600
|
const configService = new ConfigService();
|
|
11443
11601
|
const config = await configService.load();
|
|
11444
11602
|
if (!config) {
|
|
11445
11603
|
throw new ValidationError('Not initialized. Run "jai1 auth" first.');
|
|
11446
11604
|
}
|
|
11447
|
-
console.log(
|
|
11605
|
+
console.log(chalk34.cyan("\u{1F4E6} \u0110ang t\u1EA3i danh s\xE1ch starter kits..."));
|
|
11448
11606
|
console.log();
|
|
11449
11607
|
const kitService = new StarterKitService();
|
|
11450
11608
|
const kits = await kitService.list(config, {
|
|
@@ -11452,9 +11610,9 @@ function createKitListCommand() {
|
|
|
11452
11610
|
search: options.search
|
|
11453
11611
|
});
|
|
11454
11612
|
if (kits.length === 0) {
|
|
11455
|
-
console.log(
|
|
11613
|
+
console.log(chalk34.yellow("Kh\xF4ng t\xECm th\u1EA5y starter kits n\xE0o."));
|
|
11456
11614
|
if (options.category || options.search) {
|
|
11457
|
-
console.log(
|
|
11615
|
+
console.log(chalk34.dim("Th\u1EED b\u1ECF filter \u0111\u1EC3 xem t\u1EA5t c\u1EA3."));
|
|
11458
11616
|
}
|
|
11459
11617
|
return;
|
|
11460
11618
|
}
|
|
@@ -11478,35 +11636,35 @@ function createKitListCommand() {
|
|
|
11478
11636
|
const categoryKits = byCategory[category];
|
|
11479
11637
|
const categoryIcon = category === "frontend" ? "\u{1F3A8}" : category === "backend" ? "\u2699\uFE0F" : category === "fullstack" ? "\u{1F680}" : "\u{1F4E6}";
|
|
11480
11638
|
console.log(
|
|
11481
|
-
|
|
11639
|
+
chalk34.bold(`${categoryIcon} ${category.charAt(0).toUpperCase() + category.slice(1)}`)
|
|
11482
11640
|
);
|
|
11483
11641
|
const table = new Table6({
|
|
11484
11642
|
head: [
|
|
11485
|
-
|
|
11486
|
-
|
|
11487
|
-
|
|
11643
|
+
chalk34.cyan("Slug"),
|
|
11644
|
+
chalk34.cyan("M\xF4 t\u1EA3"),
|
|
11645
|
+
chalk34.cyan("Version")
|
|
11488
11646
|
],
|
|
11489
11647
|
style: { head: [], border: ["gray"] }
|
|
11490
11648
|
});
|
|
11491
11649
|
for (const kit of categoryKits) {
|
|
11492
11650
|
table.push([
|
|
11493
|
-
|
|
11494
|
-
|
|
11495
|
-
|
|
11651
|
+
chalk34.white(kit.slug),
|
|
11652
|
+
chalk34.dim(kit.description.slice(0, 50)),
|
|
11653
|
+
chalk34.green(`v${kit.version}`)
|
|
11496
11654
|
]);
|
|
11497
11655
|
}
|
|
11498
11656
|
console.log(table.toString());
|
|
11499
11657
|
console.log();
|
|
11500
11658
|
}
|
|
11501
|
-
console.log(
|
|
11502
|
-
console.log(
|
|
11659
|
+
console.log(chalk34.dim(`T\u1ED5ng c\u1ED9ng: ${kits.length} starter kit(s)`));
|
|
11660
|
+
console.log(chalk34.dim('\n\u{1F4A1} Ch\u1EA1y "jai1 kit create <slug>" \u0111\u1EC3 t\u1EA1o project m\u1EDBi'));
|
|
11503
11661
|
});
|
|
11504
11662
|
}
|
|
11505
11663
|
|
|
11506
11664
|
// src/commands/kit/info.ts
|
|
11507
|
-
import { Command as
|
|
11665
|
+
import { Command as Command63 } from "commander";
|
|
11508
11666
|
function createKitInfoCommand() {
|
|
11509
|
-
return new
|
|
11667
|
+
return new Command63("info").description("Show detailed information about a starter kit").argument("<slug>", "Starter kit slug").action(async (slug) => {
|
|
11510
11668
|
const configService = new ConfigService();
|
|
11511
11669
|
const config = await configService.load();
|
|
11512
11670
|
if (!config) {
|
|
@@ -11555,7 +11713,7 @@ Post-Init Commands:`);
|
|
|
11555
11713
|
}
|
|
11556
11714
|
|
|
11557
11715
|
// src/commands/kit/create.ts
|
|
11558
|
-
import { Command as
|
|
11716
|
+
import { Command as Command64 } from "commander";
|
|
11559
11717
|
import { promises as fs20 } from "fs";
|
|
11560
11718
|
import { join as join11 } from "path";
|
|
11561
11719
|
import { select as select3, input as input2, checkbox as checkbox4 } from "@inquirer/prompts";
|
|
@@ -11600,7 +11758,7 @@ var HookExecutor = class {
|
|
|
11600
11758
|
|
|
11601
11759
|
// src/commands/kit/create.ts
|
|
11602
11760
|
function createKitCreateCommand() {
|
|
11603
|
-
return new
|
|
11761
|
+
return new Command64("create").description("Create a new project from a starter kit").argument("<slug>", "Starter kit slug").argument("[directory]", "Project directory (default: ./<slug>)").option("-y, --yes", "Auto mode - use defaults, no prompts").option("--name <name>", "Project name").option("--skip-install", "Skip dependency installation").option("--skip-git", "Skip git initialization").option("--skip-framework", "Skip framework apply").option("--skip-ide", "Skip IDE sync").action(async (slug, directory, options) => {
|
|
11604
11762
|
const configService = new ConfigService();
|
|
11605
11763
|
const config = await configService.load();
|
|
11606
11764
|
if (!config) {
|
|
@@ -11779,23 +11937,23 @@ async function getAllFiles(dir) {
|
|
|
11779
11937
|
|
|
11780
11938
|
// src/commands/kit/index.ts
|
|
11781
11939
|
function showKitHelp() {
|
|
11782
|
-
console.log(
|
|
11940
|
+
console.log(chalk35.bold.cyan("\u{1F4E6} jai1 kit") + chalk35.dim(" - Qu\u1EA3n l\xFD starter kits"));
|
|
11783
11941
|
console.log();
|
|
11784
|
-
console.log(
|
|
11785
|
-
console.log(` ${
|
|
11786
|
-
console.log(` ${
|
|
11787
|
-
console.log(` ${
|
|
11942
|
+
console.log(chalk35.bold("C\xE1c l\u1EC7nh:"));
|
|
11943
|
+
console.log(` ${chalk35.cyan("list")} Li\u1EC7t k\xEA c\xE1c starter kits c\xF3 s\u1EB5n`);
|
|
11944
|
+
console.log(` ${chalk35.cyan("info")} Xem chi ti\u1EBFt m\u1ED9t starter kit`);
|
|
11945
|
+
console.log(` ${chalk35.cyan("create")} T\u1EA1o project m\u1EDBi t\u1EEB starter kit`);
|
|
11788
11946
|
console.log();
|
|
11789
|
-
console.log(
|
|
11790
|
-
console.log(
|
|
11791
|
-
console.log(
|
|
11792
|
-
console.log(
|
|
11793
|
-
console.log(
|
|
11947
|
+
console.log(chalk35.bold("V\xED d\u1EE5:"));
|
|
11948
|
+
console.log(chalk35.dim(" $ jai1 kit list"));
|
|
11949
|
+
console.log(chalk35.dim(" $ jai1 kit list --category frontend"));
|
|
11950
|
+
console.log(chalk35.dim(" $ jai1 kit info next-tw4-shadcn"));
|
|
11951
|
+
console.log(chalk35.dim(" $ jai1 kit create next-tw4-shadcn my-project"));
|
|
11794
11952
|
console.log();
|
|
11795
|
-
console.log(
|
|
11953
|
+
console.log(chalk35.dim('Ch\u1EA1y "jai1 kit <l\u1EC7nh> --help" \u0111\u1EC3 xem chi ti\u1EBFt'));
|
|
11796
11954
|
}
|
|
11797
11955
|
function createKitCommand() {
|
|
11798
|
-
const cmd = new
|
|
11956
|
+
const cmd = new Command65("kit").description("Manage starter kits for new projects").action(() => {
|
|
11799
11957
|
showKitHelp();
|
|
11800
11958
|
});
|
|
11801
11959
|
cmd.addCommand(createKitListCommand());
|
|
@@ -11805,21 +11963,21 @@ function createKitCommand() {
|
|
|
11805
11963
|
}
|
|
11806
11964
|
|
|
11807
11965
|
// src/commands/rules/index.ts
|
|
11808
|
-
import { Command as
|
|
11809
|
-
import
|
|
11966
|
+
import { Command as Command72 } from "commander";
|
|
11967
|
+
import chalk37 from "chalk";
|
|
11810
11968
|
|
|
11811
11969
|
// src/commands/rules/list.ts
|
|
11812
|
-
import { Command as
|
|
11813
|
-
import
|
|
11970
|
+
import { Command as Command66 } from "commander";
|
|
11971
|
+
import chalk36 from "chalk";
|
|
11814
11972
|
import Table7 from "cli-table3";
|
|
11815
11973
|
function createRulesListCommand() {
|
|
11816
|
-
return new
|
|
11974
|
+
return new Command66("list").description("List available rule presets").option("--json", "Output as JSON").action(async (options) => {
|
|
11817
11975
|
const configService = new ConfigService();
|
|
11818
11976
|
const config = await configService.load();
|
|
11819
11977
|
if (!config) {
|
|
11820
11978
|
throw new ValidationError('Not initialized. Run "jai1 auth" first.');
|
|
11821
11979
|
}
|
|
11822
|
-
console.log(
|
|
11980
|
+
console.log(chalk36.cyan("\u{1F4CB} \u0110ang t\u1EA3i danh s\xE1ch rule presets..."));
|
|
11823
11981
|
console.log();
|
|
11824
11982
|
try {
|
|
11825
11983
|
const response = await fetch(`${config.apiUrl}/api/rules/presets`, {
|
|
@@ -11836,23 +11994,23 @@ function createRulesListCommand() {
|
|
|
11836
11994
|
return;
|
|
11837
11995
|
}
|
|
11838
11996
|
if (data.total === 0) {
|
|
11839
|
-
console.log(
|
|
11997
|
+
console.log(chalk36.yellow("Kh\xF4ng c\xF3 presets n\xE0o."));
|
|
11840
11998
|
return;
|
|
11841
11999
|
}
|
|
11842
12000
|
console.log(
|
|
11843
|
-
|
|
12001
|
+
chalk36.green(`\u2713 T\xECm th\u1EA5y ${chalk36.bold(data.total)} preset${data.total > 1 ? "s" : ""}`)
|
|
11844
12002
|
);
|
|
11845
12003
|
console.log();
|
|
11846
12004
|
for (const preset of data.presets) {
|
|
11847
|
-
console.log(
|
|
12005
|
+
console.log(chalk36.bold.cyan(`\u{1F4E6} ${preset.slug}`));
|
|
11848
12006
|
const table = new Table7({
|
|
11849
12007
|
style: { head: [], border: ["gray"], compact: true },
|
|
11850
12008
|
colWidths: [15, 55]
|
|
11851
12009
|
});
|
|
11852
12010
|
table.push(
|
|
11853
|
-
[
|
|
11854
|
-
[
|
|
11855
|
-
[
|
|
12011
|
+
[chalk36.dim("T\xEAn"), chalk36.white(preset.name)],
|
|
12012
|
+
[chalk36.dim("M\xF4 t\u1EA3"), chalk36.white(preset.description)],
|
|
12013
|
+
[chalk36.dim("Version"), chalk36.green(`v${preset.version}`)]
|
|
11856
12014
|
);
|
|
11857
12015
|
const stackParts = [];
|
|
11858
12016
|
if (preset.stack.frontend) stackParts.push(preset.stack.frontend);
|
|
@@ -11860,16 +12018,16 @@ function createRulesListCommand() {
|
|
|
11860
12018
|
if (preset.stack.css) stackParts.push(preset.stack.css);
|
|
11861
12019
|
if (preset.stack.database) stackParts.push(preset.stack.database);
|
|
11862
12020
|
if (stackParts.length > 0) {
|
|
11863
|
-
table.push([
|
|
12021
|
+
table.push([chalk36.dim("Stack"), chalk36.yellow(stackParts.join(" + "))]);
|
|
11864
12022
|
}
|
|
11865
12023
|
table.push(
|
|
11866
|
-
[
|
|
11867
|
-
[
|
|
12024
|
+
[chalk36.dim("Tags"), chalk36.dim(preset.tags.join(", ") || "-")],
|
|
12025
|
+
[chalk36.dim("Downloads"), chalk36.white(preset.downloads.toString())]
|
|
11868
12026
|
);
|
|
11869
12027
|
console.log(table.toString());
|
|
11870
12028
|
console.log();
|
|
11871
12029
|
}
|
|
11872
|
-
console.log(
|
|
12030
|
+
console.log(chalk36.dim('\u{1F4A1} Ch\u1EA1y "jai1 rules apply <name>" \u0111\u1EC3 \xE1p d\u1EE5ng preset'));
|
|
11873
12031
|
} catch (error) {
|
|
11874
12032
|
throw new Error(
|
|
11875
12033
|
`L\u1ED7i khi t\u1EA3i presets: ${error instanceof Error ? error.message : String(error)}`
|
|
@@ -11879,10 +12037,10 @@ function createRulesListCommand() {
|
|
|
11879
12037
|
}
|
|
11880
12038
|
|
|
11881
12039
|
// src/commands/rules/init.ts
|
|
11882
|
-
import { Command as
|
|
12040
|
+
import { Command as Command67 } from "commander";
|
|
11883
12041
|
import { promises as fs22 } from "fs";
|
|
11884
12042
|
import { join as join13 } from "path";
|
|
11885
|
-
import { select as select4, confirm as
|
|
12043
|
+
import { select as select4, confirm as confirm12 } from "@inquirer/prompts";
|
|
11886
12044
|
|
|
11887
12045
|
// src/services/project-config.service.ts
|
|
11888
12046
|
import { promises as fs21 } from "fs";
|
|
@@ -12004,7 +12162,7 @@ var ProjectConfigService = class {
|
|
|
12004
12162
|
|
|
12005
12163
|
// src/commands/rules/init.ts
|
|
12006
12164
|
function createRulesInitCommand() {
|
|
12007
|
-
return new
|
|
12165
|
+
return new Command67("init").description("Apply rule preset to project").option("--preset <slug>", "Preset slug to apply").option("--output <format>", "Output format: cursor, agents-md, both (default: cursor)", "cursor").option("-y, --yes", "Skip confirmations").action(async (options) => {
|
|
12008
12166
|
const configService = new ConfigService();
|
|
12009
12167
|
const config = await configService.load();
|
|
12010
12168
|
if (!config) {
|
|
@@ -12066,7 +12224,7 @@ function createRulesInitCommand() {
|
|
|
12066
12224
|
});
|
|
12067
12225
|
}
|
|
12068
12226
|
if (!options.yes) {
|
|
12069
|
-
const proceed = await
|
|
12227
|
+
const proceed = await confirm12({
|
|
12070
12228
|
message: `Apply preset '${bundle.preset.name}' to current directory?`,
|
|
12071
12229
|
default: true
|
|
12072
12230
|
});
|
|
@@ -12136,10 +12294,10 @@ async function applyAgentsMdFormat(bundle) {
|
|
|
12136
12294
|
}
|
|
12137
12295
|
|
|
12138
12296
|
// src/commands/rules/apply.ts
|
|
12139
|
-
import { Command as
|
|
12297
|
+
import { Command as Command68 } from "commander";
|
|
12140
12298
|
import { promises as fs24 } from "fs";
|
|
12141
12299
|
import { join as join15 } from "path";
|
|
12142
|
-
import { search, confirm as
|
|
12300
|
+
import { search, confirm as confirm13, checkbox as checkbox5 } from "@inquirer/prompts";
|
|
12143
12301
|
|
|
12144
12302
|
// src/services/rules-generator.service.ts
|
|
12145
12303
|
var RulesGeneratorService = class {
|
|
@@ -12650,7 +12808,7 @@ Restoring backup from ${metadata.timestamp}...`);
|
|
|
12650
12808
|
|
|
12651
12809
|
// src/commands/rules/apply.ts
|
|
12652
12810
|
function createRulesApplyCommand() {
|
|
12653
|
-
return new
|
|
12811
|
+
return new Command68("apply").description("Apply rule preset to project with multi-IDE support").argument("[preset]", "Preset slug to apply (optional)").option("--ides <ides>", 'Comma-separated list of IDE formats (cursor,windsurf,antigravity,claude,agentsmd,gemini) or "all"').option("--skip-backup", "Skip backup creation").option("-y, --yes", "Skip all confirmations (auto mode)").action(async (presetSlug, options) => {
|
|
12654
12812
|
const configService = new ConfigService();
|
|
12655
12813
|
const config = await configService.load();
|
|
12656
12814
|
if (!config) {
|
|
@@ -12806,7 +12964,7 @@ function createRulesApplyCommand() {
|
|
|
12806
12964
|
if (backupPath) {
|
|
12807
12965
|
console.log(` Backup: ${backupPath}`);
|
|
12808
12966
|
}
|
|
12809
|
-
const proceed = await
|
|
12967
|
+
const proceed = await confirm13({
|
|
12810
12968
|
message: "Apply these rules to the current directory?",
|
|
12811
12969
|
default: true
|
|
12812
12970
|
});
|
|
@@ -12945,11 +13103,11 @@ function createRulesApplyCommand() {
|
|
|
12945
13103
|
}
|
|
12946
13104
|
|
|
12947
13105
|
// src/commands/rules/restore.ts
|
|
12948
|
-
import { Command as
|
|
13106
|
+
import { Command as Command69 } from "commander";
|
|
12949
13107
|
import { join as join16 } from "path";
|
|
12950
|
-
import { select as select5, confirm as
|
|
13108
|
+
import { select as select5, confirm as confirm14 } from "@inquirer/prompts";
|
|
12951
13109
|
function createRulesRestoreCommand() {
|
|
12952
|
-
return new
|
|
13110
|
+
return new Command69("restore").description("Restore rules from a backup").option("--latest", "Restore the most recent backup").option("-y, --yes", "Skip confirmation").action(async (options) => {
|
|
12953
13111
|
const backupService = new BackupService();
|
|
12954
13112
|
const backups = await backupService.listBackups();
|
|
12955
13113
|
if (backups.length === 0) {
|
|
@@ -12982,7 +13140,7 @@ function createRulesRestoreCommand() {
|
|
|
12982
13140
|
console.log(` IDEs: ${selectedBackup.ides.join(", ")}`);
|
|
12983
13141
|
console.log(` Files: ${selectedBackup.files.length}`);
|
|
12984
13142
|
if (!options.yes) {
|
|
12985
|
-
const proceed = await
|
|
13143
|
+
const proceed = await confirm14({
|
|
12986
13144
|
message: "This will overwrite current rules. Continue?",
|
|
12987
13145
|
default: false
|
|
12988
13146
|
});
|
|
@@ -13018,12 +13176,12 @@ function formatTimestamp(timestamp) {
|
|
|
13018
13176
|
}
|
|
13019
13177
|
|
|
13020
13178
|
// src/commands/rules/sync.ts
|
|
13021
|
-
import { Command as
|
|
13179
|
+
import { Command as Command70 } from "commander";
|
|
13022
13180
|
import { promises as fs25 } from "fs";
|
|
13023
13181
|
import { join as join17 } from "path";
|
|
13024
|
-
import { checkbox as checkbox6, confirm as
|
|
13182
|
+
import { checkbox as checkbox6, confirm as confirm15, Separator } from "@inquirer/prompts";
|
|
13025
13183
|
function createRulesSyncCommand() {
|
|
13026
|
-
return new
|
|
13184
|
+
return new Command70("sync").description("Regenerate rule outputs for all configured IDEs").option("--ides <ides>", "Comma-separated list of IDEs to sync (default: all configured)").option("--detect", "Auto-detect active IDEs instead of using config").option("-y, --yes", "Skip confirmations").action(async (options) => {
|
|
13027
13185
|
const rulePresetDir = join17(process.cwd(), ".jai1", "rule-preset");
|
|
13028
13186
|
const presetJsonPath = join17(rulePresetDir, "preset.json");
|
|
13029
13187
|
let presetExists = false;
|
|
@@ -13072,7 +13230,7 @@ Detected ${detected.length} active IDE(s):
|
|
|
13072
13230
|
console.log(` ${confidence} ${d.name} - ${d.ruleCount} rules`);
|
|
13073
13231
|
});
|
|
13074
13232
|
if (!options.yes) {
|
|
13075
|
-
const proceed = await
|
|
13233
|
+
const proceed = await confirm15({
|
|
13076
13234
|
message: "\nSync these detected IDEs?",
|
|
13077
13235
|
default: true
|
|
13078
13236
|
});
|
|
@@ -13241,11 +13399,11 @@ function buildIdeChoices(currentIdes, detected, suggestions) {
|
|
|
13241
13399
|
}
|
|
13242
13400
|
|
|
13243
13401
|
// src/commands/rules/info.ts
|
|
13244
|
-
import { Command as
|
|
13402
|
+
import { Command as Command71 } from "commander";
|
|
13245
13403
|
import { promises as fs26 } from "fs";
|
|
13246
13404
|
import { join as join18 } from "path";
|
|
13247
13405
|
function createRulesInfoCommand() {
|
|
13248
|
-
return new
|
|
13406
|
+
return new Command71("info").description("Show current preset information").option("--json", "Output as JSON").action(async (options) => {
|
|
13249
13407
|
const projectConfigService = new ProjectConfigService();
|
|
13250
13408
|
const rulesConfig = await projectConfigService.loadRules();
|
|
13251
13409
|
if (!rulesConfig) {
|
|
@@ -13348,26 +13506,26 @@ async function checkIdeFilesExist(ideId, format) {
|
|
|
13348
13506
|
|
|
13349
13507
|
// src/commands/rules/index.ts
|
|
13350
13508
|
function showRulesHelp() {
|
|
13351
|
-
console.log(
|
|
13509
|
+
console.log(chalk37.bold.cyan("\u{1F4CB} jai1 rules") + chalk37.dim(" - Qu\u1EA3n l\xFD rule presets cho AI agents"));
|
|
13352
13510
|
console.log();
|
|
13353
|
-
console.log(
|
|
13354
|
-
console.log(` ${
|
|
13355
|
-
console.log(` ${
|
|
13356
|
-
console.log(` ${
|
|
13357
|
-
console.log(` ${
|
|
13358
|
-
console.log(` ${
|
|
13359
|
-
console.log(` ${
|
|
13511
|
+
console.log(chalk37.bold("C\xE1c l\u1EC7nh:"));
|
|
13512
|
+
console.log(` ${chalk37.cyan("list")} Li\u1EC7t k\xEA c\xE1c presets c\xF3 s\u1EB5n`);
|
|
13513
|
+
console.log(` ${chalk37.cyan("info")} Xem chi ti\u1EBFt m\u1ED9t preset`);
|
|
13514
|
+
console.log(` ${chalk37.cyan("init")} Kh\u1EDFi t\u1EA1o rules t\u1EEB preset`);
|
|
13515
|
+
console.log(` ${chalk37.cyan("apply")} \xC1p d\u1EE5ng preset v\xE0o project`);
|
|
13516
|
+
console.log(` ${chalk37.cyan("sync")} \u0110\u1ED3ng b\u1ED9 rules sang c\xE1c \u0111\u1ECBnh d\u1EA1ng IDE`);
|
|
13517
|
+
console.log(` ${chalk37.cyan("restore")} Kh\xF4i ph\u1EE5c rules t\u1EEB backup`);
|
|
13360
13518
|
console.log();
|
|
13361
|
-
console.log(
|
|
13362
|
-
console.log(
|
|
13363
|
-
console.log(
|
|
13364
|
-
console.log(
|
|
13365
|
-
console.log(
|
|
13519
|
+
console.log(chalk37.bold("V\xED d\u1EE5:"));
|
|
13520
|
+
console.log(chalk37.dim(" $ jai1 rules list"));
|
|
13521
|
+
console.log(chalk37.dim(" $ jai1 rules info react-typescript"));
|
|
13522
|
+
console.log(chalk37.dim(" $ jai1 rules init --preset=react-typescript"));
|
|
13523
|
+
console.log(chalk37.dim(" $ jai1 rules apply react-typescript"));
|
|
13366
13524
|
console.log();
|
|
13367
|
-
console.log(
|
|
13525
|
+
console.log(chalk37.dim('Ch\u1EA1y "jai1 rules <l\u1EC7nh> --help" \u0111\u1EC3 xem chi ti\u1EBFt'));
|
|
13368
13526
|
}
|
|
13369
13527
|
function createRulesCommand() {
|
|
13370
|
-
const rulesCommand = new
|
|
13528
|
+
const rulesCommand = new Command72("rules").description("Manage rule presets for AI agents").action(() => {
|
|
13371
13529
|
showRulesHelp();
|
|
13372
13530
|
});
|
|
13373
13531
|
rulesCommand.addCommand(createRulesListCommand());
|
|
@@ -13380,12 +13538,12 @@ function createRulesCommand() {
|
|
|
13380
13538
|
}
|
|
13381
13539
|
|
|
13382
13540
|
// src/commands/skills/index.ts
|
|
13383
|
-
import { Command as
|
|
13384
|
-
import
|
|
13541
|
+
import { Command as Command78 } from "commander";
|
|
13542
|
+
import chalk43 from "chalk";
|
|
13385
13543
|
|
|
13386
13544
|
// src/commands/skills/find.ts
|
|
13387
|
-
import { Command as
|
|
13388
|
-
import
|
|
13545
|
+
import { Command as Command73 } from "commander";
|
|
13546
|
+
import chalk38 from "chalk";
|
|
13389
13547
|
import Table8 from "cli-table3";
|
|
13390
13548
|
|
|
13391
13549
|
// src/services/skills.service.ts
|
|
@@ -13679,7 +13837,7 @@ var SkillsService = class {
|
|
|
13679
13837
|
|
|
13680
13838
|
// src/commands/skills/find.ts
|
|
13681
13839
|
function createSkillsFindCommand() {
|
|
13682
|
-
return new
|
|
13840
|
+
return new Command73("find").description("Search for skills on server or npm").argument("<query>", "Search query").option("--skillsh", "Search on npm skills registry instead of Jai1 server").option("--all", "Search on both Jai1 server and npm").action(async (query, options) => {
|
|
13683
13841
|
const searchNpm = options.skillsh || options.all;
|
|
13684
13842
|
const searchServer = !options.skillsh || options.all;
|
|
13685
13843
|
if (searchServer) {
|
|
@@ -13688,19 +13846,19 @@ function createSkillsFindCommand() {
|
|
|
13688
13846
|
if (!config) {
|
|
13689
13847
|
throw new ValidationError('Ch\u01B0a x\xE1c th\u1EF1c. Ch\u1EA1y "jai1 auth" tr\u01B0\u1EDBc.');
|
|
13690
13848
|
}
|
|
13691
|
-
console.log(
|
|
13849
|
+
console.log(chalk38.cyan("\u{1F50D} \u0110ang t\xECm ki\u1EBFm tr\xEAn Jai1 server..."));
|
|
13692
13850
|
console.log();
|
|
13693
13851
|
const skillsService = new SkillsService();
|
|
13694
13852
|
const results = await skillsService.searchFromServer(config, query);
|
|
13695
13853
|
if (results.length === 0) {
|
|
13696
|
-
console.log(
|
|
13854
|
+
console.log(chalk38.yellow("Kh\xF4ng t\xECm th\u1EA5y skills n\xE0o tr\xEAn server."));
|
|
13697
13855
|
} else {
|
|
13698
13856
|
const table = new Table8({
|
|
13699
13857
|
head: [
|
|
13700
|
-
|
|
13701
|
-
|
|
13702
|
-
|
|
13703
|
-
|
|
13858
|
+
chalk38.cyan("T\xEAn"),
|
|
13859
|
+
chalk38.cyan("M\xF4 t\u1EA3"),
|
|
13860
|
+
chalk38.cyan("Version"),
|
|
13861
|
+
chalk38.cyan("Downloads")
|
|
13704
13862
|
],
|
|
13705
13863
|
style: { head: [], border: ["gray"] },
|
|
13706
13864
|
colWidths: [25, 40, 10, 12]
|
|
@@ -13708,70 +13866,70 @@ function createSkillsFindCommand() {
|
|
|
13708
13866
|
for (const skill of results) {
|
|
13709
13867
|
const name = skill.filepath.replace("skills/", "");
|
|
13710
13868
|
table.push([
|
|
13711
|
-
|
|
13712
|
-
|
|
13713
|
-
|
|
13714
|
-
|
|
13869
|
+
chalk38.white(name),
|
|
13870
|
+
chalk38.dim((skill.description || "").slice(0, 38)),
|
|
13871
|
+
chalk38.green(skill.version || "-"),
|
|
13872
|
+
chalk38.dim(String(skill.downloads || 0))
|
|
13715
13873
|
]);
|
|
13716
13874
|
}
|
|
13717
|
-
console.log(
|
|
13875
|
+
console.log(chalk38.bold(`\u{1F4E6} Jai1 Server (${results.length} k\u1EBFt qu\u1EA3)`));
|
|
13718
13876
|
console.log(table.toString());
|
|
13719
13877
|
console.log();
|
|
13720
13878
|
}
|
|
13721
13879
|
}
|
|
13722
13880
|
if (searchNpm) {
|
|
13723
|
-
console.log(
|
|
13881
|
+
console.log(chalk38.cyan("\u{1F50D} \u0110ang t\xECm ki\u1EBFm tr\xEAn npm skills..."));
|
|
13724
13882
|
console.log();
|
|
13725
13883
|
const skillsService = new SkillsService();
|
|
13726
13884
|
try {
|
|
13727
13885
|
const output = await skillsService.npmSkillsFind(query);
|
|
13728
|
-
console.log(
|
|
13886
|
+
console.log(chalk38.bold("\u{1F310} npm Skills Registry"));
|
|
13729
13887
|
console.log(output);
|
|
13730
13888
|
} catch (error) {
|
|
13731
|
-
console.log(
|
|
13889
|
+
console.log(chalk38.yellow(
|
|
13732
13890
|
`Kh\xF4ng th\u1EC3 t\xECm ki\u1EBFm tr\xEAn npm: ${error instanceof Error ? error.message : String(error)}`
|
|
13733
13891
|
));
|
|
13734
13892
|
}
|
|
13735
13893
|
}
|
|
13736
13894
|
if (searchServer && !searchNpm) {
|
|
13737
|
-
console.log(
|
|
13895
|
+
console.log(chalk38.dim('\u{1F4A1} D\xF9ng "j skills add <t\xEAn>" \u0111\u1EC3 c\xE0i \u0111\u1EB7t t\u1EEB server'));
|
|
13738
13896
|
} else if (searchNpm && !searchServer) {
|
|
13739
|
-
console.log(
|
|
13897
|
+
console.log(chalk38.dim('\u{1F4A1} D\xF9ng "j skills add <owner/repo@skill> --skillsh" \u0111\u1EC3 c\xE0i \u0111\u1EB7t'));
|
|
13740
13898
|
} else {
|
|
13741
|
-
console.log(
|
|
13742
|
-
console.log(
|
|
13743
|
-
console.log(
|
|
13899
|
+
console.log(chalk38.dim("\u{1F4A1} C\xE0i \u0111\u1EB7t:"));
|
|
13900
|
+
console.log(chalk38.dim(" Server: j skills add <t\xEAn>"));
|
|
13901
|
+
console.log(chalk38.dim(" Skills.sh: j skills add <owner/repo@skill> --skillsh"));
|
|
13744
13902
|
}
|
|
13745
13903
|
});
|
|
13746
13904
|
}
|
|
13747
13905
|
|
|
13748
13906
|
// src/commands/skills/add.ts
|
|
13749
|
-
import { Command as
|
|
13907
|
+
import { Command as Command74 } from "commander";
|
|
13750
13908
|
import { join as join20 } from "path";
|
|
13751
|
-
import
|
|
13909
|
+
import chalk39 from "chalk";
|
|
13752
13910
|
import { checkbox as checkbox7 } from "@inquirer/prompts";
|
|
13753
13911
|
function createSkillsAddCommand() {
|
|
13754
|
-
return new
|
|
13912
|
+
return new Command74("add").description("Install a skill to .jai1/skills/").argument("<name>", "Skill name or source (npm: GitHub shorthand, URL)").option("--skillsh", "Install from npm skills registry instead of Jai1 server").option("--sync", "Auto-sync to IDE(s) after install").option("--ides <ides...>", "Target IDEs for sync (cursor, windsurf, antigravity, claudecode, opencode)").option("--all", "Sync to all available IDEs").option("-y, --yes", "Headless mode (skip all prompts)").action(async (name, options) => {
|
|
13755
13913
|
const skillsService = new SkillsService();
|
|
13756
13914
|
const projectRoot = process.cwd();
|
|
13757
13915
|
const headless = options.yes === true;
|
|
13758
13916
|
if (options.skillsh) {
|
|
13759
|
-
console.log(
|
|
13917
|
+
console.log(chalk39.cyan(`\u{1F310} \u0110ang c\xE0i \u0111\u1EB7t skill t\u1EEB npm: ${name}...`));
|
|
13760
13918
|
console.log();
|
|
13761
13919
|
const output = await skillsService.npmSkillsAdd(name, projectRoot);
|
|
13762
13920
|
console.log(output);
|
|
13763
|
-
console.log(
|
|
13921
|
+
console.log(chalk39.green("\u2705 C\xE0i \u0111\u1EB7t t\u1EEB npm th\xE0nh c\xF4ng!"));
|
|
13764
13922
|
} else {
|
|
13765
13923
|
const configService = new ConfigService();
|
|
13766
13924
|
const config = await configService.load();
|
|
13767
13925
|
if (!config) {
|
|
13768
13926
|
throw new ValidationError('Ch\u01B0a x\xE1c th\u1EF1c. Ch\u1EA1y "jai1 auth" tr\u01B0\u1EDBc.');
|
|
13769
13927
|
}
|
|
13770
|
-
console.log(
|
|
13928
|
+
console.log(chalk39.cyan(`\u{1F4E6} \u0110ang c\xE0i \u0111\u1EB7t skill: ${name}...`));
|
|
13771
13929
|
console.log();
|
|
13772
13930
|
const targetDir = join20(projectRoot, ".jai1");
|
|
13773
13931
|
await skillsService.installFromServer(config, name, targetDir);
|
|
13774
|
-
console.log(
|
|
13932
|
+
console.log(chalk39.green(`\u2705 \u0110\xE3 c\xE0i \u0111\u1EB7t skill "${name}" v\xE0o .jai1/skills/${name}/`));
|
|
13775
13933
|
}
|
|
13776
13934
|
console.log();
|
|
13777
13935
|
if (options.sync) {
|
|
@@ -13796,7 +13954,7 @@ function createSkillsAddCommand() {
|
|
|
13796
13954
|
});
|
|
13797
13955
|
}
|
|
13798
13956
|
if (selectedIdes.length > 0) {
|
|
13799
|
-
console.log(
|
|
13957
|
+
console.log(chalk39.cyan("\u{1F504} \u0110ang sync sang IDE(s)..."));
|
|
13800
13958
|
console.log();
|
|
13801
13959
|
const slug = name.includes("/") ? name.split("/").pop() : name;
|
|
13802
13960
|
const result = await skillsService.syncToIdes(
|
|
@@ -13809,24 +13967,24 @@ function createSkillsAddCommand() {
|
|
|
13809
13967
|
}
|
|
13810
13968
|
);
|
|
13811
13969
|
console.log();
|
|
13812
|
-
console.log(
|
|
13970
|
+
console.log(chalk39.green(`\u2705 Sync ho\xE0n t\u1EA5t! Created: ${result.created}, Updated: ${result.updated}`));
|
|
13813
13971
|
if (result.errors > 0) {
|
|
13814
|
-
console.log(
|
|
13972
|
+
console.log(chalk39.yellow(`\u26A0\uFE0F Errors: ${result.errors}`));
|
|
13815
13973
|
}
|
|
13816
13974
|
}
|
|
13817
13975
|
} else {
|
|
13818
|
-
console.log(
|
|
13819
|
-
console.log(
|
|
13976
|
+
console.log(chalk39.dim('\u{1F4A1} Ch\u1EA1y "j skills sync" \u0111\u1EC3 \u0111\u1ED3ng b\u1ED9 sang IDE(s)'));
|
|
13977
|
+
console.log(chalk39.dim(' ho\u1EB7c "j ide sync" \u0111\u1EC3 sync to\xE0n b\u1ED9 .jai1/'));
|
|
13820
13978
|
}
|
|
13821
13979
|
});
|
|
13822
13980
|
}
|
|
13823
13981
|
|
|
13824
13982
|
// src/commands/skills/list.ts
|
|
13825
|
-
import { Command as
|
|
13826
|
-
import
|
|
13983
|
+
import { Command as Command75 } from "commander";
|
|
13984
|
+
import chalk40 from "chalk";
|
|
13827
13985
|
import Table9 from "cli-table3";
|
|
13828
13986
|
function createSkillsListCommand() {
|
|
13829
|
-
return new
|
|
13987
|
+
return new Command75("list").description("List installed skills or available skills on server").option("--available", "List all skills available on Jai1 server").option("-s, --search <term>", "Search skills by name or description").action(async (options) => {
|
|
13830
13988
|
const skillsService = new SkillsService();
|
|
13831
13989
|
if (options.available) {
|
|
13832
13990
|
const configService = new ConfigService();
|
|
@@ -13834,19 +13992,19 @@ function createSkillsListCommand() {
|
|
|
13834
13992
|
if (!config) {
|
|
13835
13993
|
throw new ValidationError('Ch\u01B0a x\xE1c th\u1EF1c. Ch\u1EA1y "jai1 auth" tr\u01B0\u1EDBc.');
|
|
13836
13994
|
}
|
|
13837
|
-
console.log(
|
|
13995
|
+
console.log(chalk40.cyan("\u{1F4E6} \u0110ang t\u1EA3i danh s\xE1ch skills t\u1EEB server..."));
|
|
13838
13996
|
console.log();
|
|
13839
13997
|
const results = await skillsService.searchFromServer(config, options.search);
|
|
13840
13998
|
if (results.length === 0) {
|
|
13841
|
-
console.log(
|
|
13999
|
+
console.log(chalk40.yellow("Kh\xF4ng t\xECm th\u1EA5y skills n\xE0o."));
|
|
13842
14000
|
return;
|
|
13843
14001
|
}
|
|
13844
14002
|
const table = new Table9({
|
|
13845
14003
|
head: [
|
|
13846
|
-
|
|
13847
|
-
|
|
13848
|
-
|
|
13849
|
-
|
|
14004
|
+
chalk40.cyan("T\xEAn"),
|
|
14005
|
+
chalk40.cyan("M\xF4 t\u1EA3"),
|
|
14006
|
+
chalk40.cyan("Version"),
|
|
14007
|
+
chalk40.cyan("Downloads")
|
|
13850
14008
|
],
|
|
13851
14009
|
style: { head: [], border: ["gray"] },
|
|
13852
14010
|
colWidths: [28, 40, 10, 12]
|
|
@@ -13854,63 +14012,63 @@ function createSkillsListCommand() {
|
|
|
13854
14012
|
for (const skill of results) {
|
|
13855
14013
|
const name = skill.filepath.replace("skills/", "");
|
|
13856
14014
|
table.push([
|
|
13857
|
-
|
|
13858
|
-
|
|
13859
|
-
|
|
13860
|
-
|
|
14015
|
+
chalk40.white(name),
|
|
14016
|
+
chalk40.dim((skill.description || "").slice(0, 38)),
|
|
14017
|
+
chalk40.green(skill.version || "-"),
|
|
14018
|
+
chalk40.dim(String(skill.downloads || 0))
|
|
13861
14019
|
]);
|
|
13862
14020
|
}
|
|
13863
14021
|
console.log(table.toString());
|
|
13864
14022
|
console.log();
|
|
13865
|
-
console.log(
|
|
13866
|
-
console.log(
|
|
14023
|
+
console.log(chalk40.dim(`T\u1ED5ng c\u1ED9ng: ${results.length} skill(s)`));
|
|
14024
|
+
console.log(chalk40.dim('\n\u{1F4A1} D\xF9ng "j skills add <t\xEAn>" \u0111\u1EC3 c\xE0i \u0111\u1EB7t'));
|
|
13867
14025
|
} else {
|
|
13868
14026
|
const projectRoot = process.cwd();
|
|
13869
14027
|
const skills = await skillsService.listLocal(projectRoot);
|
|
13870
14028
|
if (skills.length === 0) {
|
|
13871
|
-
console.log(
|
|
14029
|
+
console.log(chalk40.yellow("Ch\u01B0a c\xF3 skills n\xE0o \u0111\u01B0\u1EE3c c\xE0i \u0111\u1EB7t."));
|
|
13872
14030
|
console.log();
|
|
13873
|
-
console.log(
|
|
13874
|
-
console.log(
|
|
14031
|
+
console.log(chalk40.dim('\u{1F4A1} D\xF9ng "j skills add <t\xEAn>" \u0111\u1EC3 c\xE0i \u0111\u1EB7t'));
|
|
14032
|
+
console.log(chalk40.dim(' ho\u1EB7c "j skills list --available" \u0111\u1EC3 xem skills c\xF3 s\u1EB5n'));
|
|
13875
14033
|
return;
|
|
13876
14034
|
}
|
|
13877
|
-
console.log(
|
|
14035
|
+
console.log(chalk40.bold.cyan("\u{1F6E0} Skills \u0111\xE3 c\xE0i \u0111\u1EB7t"));
|
|
13878
14036
|
console.log();
|
|
13879
14037
|
const table = new Table9({
|
|
13880
14038
|
head: [
|
|
13881
|
-
|
|
13882
|
-
|
|
13883
|
-
|
|
14039
|
+
chalk40.cyan("T\xEAn"),
|
|
14040
|
+
chalk40.cyan("M\xF4 t\u1EA3"),
|
|
14041
|
+
chalk40.cyan("Files")
|
|
13884
14042
|
],
|
|
13885
14043
|
style: { head: [], border: ["gray"] },
|
|
13886
14044
|
colWidths: [28, 45, 8]
|
|
13887
14045
|
});
|
|
13888
14046
|
for (const skill of skills) {
|
|
13889
14047
|
table.push([
|
|
13890
|
-
|
|
13891
|
-
|
|
13892
|
-
|
|
14048
|
+
chalk40.white(skill.slug),
|
|
14049
|
+
chalk40.dim(skill.description.slice(0, 43)),
|
|
14050
|
+
chalk40.dim(String(skill.fileCount))
|
|
13893
14051
|
]);
|
|
13894
14052
|
}
|
|
13895
14053
|
console.log(table.toString());
|
|
13896
14054
|
console.log();
|
|
13897
|
-
console.log(
|
|
13898
|
-
console.log(
|
|
14055
|
+
console.log(chalk40.dim(`T\u1ED5ng c\u1ED9ng: ${skills.length} skill(s)`));
|
|
14056
|
+
console.log(chalk40.dim('\n\u{1F4A1} D\xF9ng "j skills sync" \u0111\u1EC3 \u0111\u1ED3ng b\u1ED9 sang IDE(s)'));
|
|
13899
14057
|
}
|
|
13900
14058
|
});
|
|
13901
14059
|
}
|
|
13902
14060
|
|
|
13903
14061
|
// src/commands/skills/info.ts
|
|
13904
|
-
import { Command as
|
|
13905
|
-
import
|
|
14062
|
+
import { Command as Command76 } from "commander";
|
|
14063
|
+
import chalk41 from "chalk";
|
|
13906
14064
|
function createSkillsInfoCommand() {
|
|
13907
|
-
return new
|
|
14065
|
+
return new Command76("info").description("Show detailed information about a skill").argument("<name>", "Skill name").option("--server", "Show info from Jai1 server instead of local").action(async (name, options) => {
|
|
13908
14066
|
const skillsService = new SkillsService();
|
|
13909
14067
|
if (options.server) {
|
|
13910
14068
|
const configService = new ConfigService();
|
|
13911
14069
|
const config = await configService.load();
|
|
13912
14070
|
if (!config) {
|
|
13913
|
-
console.log(
|
|
14071
|
+
console.log(chalk41.red('\u274C Ch\u01B0a x\xE1c th\u1EF1c. Ch\u1EA1y "jai1 auth" tr\u01B0\u1EDBc.'));
|
|
13914
14072
|
process.exit(1);
|
|
13915
14073
|
}
|
|
13916
14074
|
const filepath = name.startsWith("skills/") ? name : `skills/${name}`;
|
|
@@ -13919,7 +14077,7 @@ function createSkillsInfoCommand() {
|
|
|
13919
14077
|
try {
|
|
13920
14078
|
const component = await componentsService.get(config, filepath);
|
|
13921
14079
|
console.log(`
|
|
13922
|
-
\u{1F6E0} ${
|
|
14080
|
+
\u{1F6E0} ${chalk41.bold(component.name || name)}
|
|
13923
14081
|
`);
|
|
13924
14082
|
console.log(`Filepath: ${component.filepath}`);
|
|
13925
14083
|
console.log(`Version: ${component.version}`);
|
|
@@ -13932,47 +14090,47 @@ function createSkillsInfoCommand() {
|
|
|
13932
14090
|
}
|
|
13933
14091
|
console.log(`Type: ${component.contentType}`);
|
|
13934
14092
|
console.log();
|
|
13935
|
-
console.log(
|
|
14093
|
+
console.log(chalk41.dim('\u{1F4A1} D\xF9ng "j skills add ' + name + '" \u0111\u1EC3 c\xE0i \u0111\u1EB7t'));
|
|
13936
14094
|
} catch (error) {
|
|
13937
|
-
console.log(
|
|
14095
|
+
console.log(chalk41.red(`\u274C Kh\xF4ng t\xECm th\u1EA5y skill "${name}" tr\xEAn server.`));
|
|
13938
14096
|
process.exit(1);
|
|
13939
14097
|
}
|
|
13940
14098
|
} else {
|
|
13941
14099
|
const projectRoot = process.cwd();
|
|
13942
14100
|
const skill = await skillsService.getSkillInfo(projectRoot, name);
|
|
13943
14101
|
if (!skill) {
|
|
13944
|
-
console.log(
|
|
13945
|
-
console.log(
|
|
13946
|
-
console.log(
|
|
14102
|
+
console.log(chalk41.red(`\u274C Skill "${name}" ch\u01B0a \u0111\u01B0\u1EE3c c\xE0i \u0111\u1EB7t.`));
|
|
14103
|
+
console.log(chalk41.dim('\u{1F4A1} D\xF9ng "j skills info ' + name + ' --server" \u0111\u1EC3 xem tr\xEAn server'));
|
|
14104
|
+
console.log(chalk41.dim(' ho\u1EB7c "j skills add ' + name + '" \u0111\u1EC3 c\xE0i \u0111\u1EB7t'));
|
|
13947
14105
|
process.exit(1);
|
|
13948
14106
|
}
|
|
13949
14107
|
console.log(`
|
|
13950
|
-
\u{1F6E0} ${
|
|
14108
|
+
\u{1F6E0} ${chalk41.bold(skill.name)}
|
|
13951
14109
|
`);
|
|
13952
14110
|
console.log(`Slug: ${skill.slug}`);
|
|
13953
|
-
console.log(`Description: ${skill.description ||
|
|
14111
|
+
console.log(`Description: ${skill.description || chalk41.dim("(none)")}`);
|
|
13954
14112
|
console.log(`Path: ${skill.path}`);
|
|
13955
14113
|
console.log(`Files: ${skill.fileCount}`);
|
|
13956
14114
|
console.log();
|
|
13957
|
-
console.log(
|
|
14115
|
+
console.log(chalk41.dim('\u{1F4A1} D\xF9ng "j skills sync" \u0111\u1EC3 \u0111\u1ED3ng b\u1ED9 sang IDE(s)'));
|
|
13958
14116
|
}
|
|
13959
14117
|
});
|
|
13960
14118
|
}
|
|
13961
14119
|
|
|
13962
14120
|
// src/commands/skills/sync.ts
|
|
13963
|
-
import { Command as
|
|
13964
|
-
import
|
|
13965
|
-
import { confirm as
|
|
14121
|
+
import { Command as Command77 } from "commander";
|
|
14122
|
+
import chalk42 from "chalk";
|
|
14123
|
+
import { confirm as confirm17, checkbox as checkbox8 } from "@inquirer/prompts";
|
|
13966
14124
|
function createSkillsSyncCommand() {
|
|
13967
|
-
return new
|
|
14125
|
+
return new Command77("sync").description("Sync skills from .jai1/skills/ to IDE directories").option("--ides <ides...>", "Target IDEs (cursor, windsurf, antigravity, claudecode, opencode)").option("--skills <skills...>", "Specific skill slugs to sync (default: all)").option("--all", "Select all available IDEs").option("--dry-run", "Preview changes without writing files").option("-y, --yes", "Headless mode (skip all prompts)").action(async (options) => {
|
|
13968
14126
|
const skillsService = new SkillsService();
|
|
13969
14127
|
const projectRoot = process.cwd();
|
|
13970
14128
|
const headless = options.yes === true;
|
|
13971
|
-
console.log(
|
|
14129
|
+
console.log(chalk42.bold.cyan("\n\u{1F504} Sync skills sang IDE(s)\n"));
|
|
13972
14130
|
const localSkills = await skillsService.listLocal(projectRoot);
|
|
13973
14131
|
if (localSkills.length === 0) {
|
|
13974
|
-
console.log(
|
|
13975
|
-
console.log(
|
|
14132
|
+
console.log(chalk42.yellow("\u26A0\uFE0F Kh\xF4ng c\xF3 skills n\xE0o trong .jai1/skills/"));
|
|
14133
|
+
console.log(chalk42.dim('\u{1F4A1} Ch\u1EA1y "j skills add <t\xEAn>" \u0111\u1EC3 c\xE0i \u0111\u1EB7t skills tr\u01B0\u1EDBc'));
|
|
13976
14134
|
process.exit(1);
|
|
13977
14135
|
}
|
|
13978
14136
|
console.log(`\u{1F4C1} T\xECm th\u1EA5y ${localSkills.length} skill(s) trong .jai1/skills/`);
|
|
@@ -14004,7 +14162,7 @@ function createSkillsSyncCommand() {
|
|
|
14004
14162
|
theme: checkboxTheme
|
|
14005
14163
|
});
|
|
14006
14164
|
if (selectedIdes.length === 0) {
|
|
14007
|
-
console.log(
|
|
14165
|
+
console.log(chalk42.yellow("\n\u26A0\uFE0F Ch\u01B0a ch\u1ECDn IDE n\xE0o!"));
|
|
14008
14166
|
process.exit(0);
|
|
14009
14167
|
}
|
|
14010
14168
|
}
|
|
@@ -14019,34 +14177,34 @@ function createSkillsSyncCommand() {
|
|
|
14019
14177
|
console.log(` Total: ${totalFiles} skill folder(s) s\u1EBD \u0111\u01B0\u1EE3c sync
|
|
14020
14178
|
`);
|
|
14021
14179
|
if (options.dryRun) {
|
|
14022
|
-
console.log(
|
|
14180
|
+
console.log(chalk42.dim("\u{1F50D} DRY RUN - Kh\xF4ng c\xF3 file n\xE0o \u0111\u01B0\u1EE3c ghi\n"));
|
|
14023
14181
|
return;
|
|
14024
14182
|
}
|
|
14025
14183
|
if (!headless) {
|
|
14026
|
-
const confirmed = await
|
|
14184
|
+
const confirmed = await confirm17({
|
|
14027
14185
|
message: "Ti\u1EBFp t\u1EE5c sync?",
|
|
14028
14186
|
default: true
|
|
14029
14187
|
});
|
|
14030
14188
|
if (!confirmed) {
|
|
14031
|
-
console.log(
|
|
14189
|
+
console.log(chalk42.yellow("\n\u274C \u0110\xE3 h\u1EE7y sync.\n"));
|
|
14032
14190
|
process.exit(0);
|
|
14033
14191
|
}
|
|
14034
14192
|
}
|
|
14035
|
-
console.log(
|
|
14193
|
+
console.log(chalk42.cyan("\n\u{1F504} \u0110ang sync...\n"));
|
|
14036
14194
|
const result = await skillsService.syncToIdes(
|
|
14037
14195
|
projectRoot,
|
|
14038
14196
|
selectedIdes,
|
|
14039
14197
|
selectedSlugs,
|
|
14040
14198
|
(res) => {
|
|
14041
14199
|
const icon = res.status === "created" ? "\u2713" : res.status === "updated" ? "\u21BB" : "\u2717";
|
|
14042
|
-
const statusColor = res.status === "error" ?
|
|
14043
|
-
console.log(` ${statusColor(icon)} ${res.ide}: ${res.skill} \u2192 ${
|
|
14200
|
+
const statusColor = res.status === "error" ? chalk42.red : chalk42.green;
|
|
14201
|
+
console.log(` ${statusColor(icon)} ${res.ide}: ${res.skill} \u2192 ${chalk42.dim(res.path)}`);
|
|
14044
14202
|
if (res.status === "error" && res.error) {
|
|
14045
|
-
console.log(` ${
|
|
14203
|
+
console.log(` ${chalk42.red("Error:")} ${res.error}`);
|
|
14046
14204
|
}
|
|
14047
14205
|
}
|
|
14048
14206
|
);
|
|
14049
|
-
console.log(
|
|
14207
|
+
console.log(chalk42.green("\n\u2705 Sync ho\xE0n t\u1EA5t!\n"));
|
|
14050
14208
|
console.log(` Created: ${result.created}`);
|
|
14051
14209
|
console.log(` Updated: ${result.updated}`);
|
|
14052
14210
|
if (result.errors > 0) {
|
|
@@ -14059,27 +14217,27 @@ function createSkillsSyncCommand() {
|
|
|
14059
14217
|
// src/commands/skills/index.ts
|
|
14060
14218
|
function showSkillsHelp() {
|
|
14061
14219
|
const cli = getCliName();
|
|
14062
|
-
console.log(
|
|
14220
|
+
console.log(chalk43.bold.cyan("\u{1F6E0} " + cli + " skills") + chalk43.dim(" - Qu\u1EA3n l\xFD agent skills"));
|
|
14063
14221
|
console.log();
|
|
14064
|
-
console.log(
|
|
14065
|
-
console.log(` ${
|
|
14066
|
-
console.log(` ${
|
|
14067
|
-
console.log(` ${
|
|
14068
|
-
console.log(` ${
|
|
14069
|
-
console.log(` ${
|
|
14222
|
+
console.log(chalk43.bold("C\xE1c l\u1EC7nh:"));
|
|
14223
|
+
console.log(` ${chalk43.cyan("find")} T\xECm ki\u1EBFm skills tr\xEAn server ho\u1EB7c npm`);
|
|
14224
|
+
console.log(` ${chalk43.cyan("add")} C\xE0i \u0111\u1EB7t skill v\xE0o .jai1/skills/`);
|
|
14225
|
+
console.log(` ${chalk43.cyan("list")} Li\u1EC7t k\xEA skills \u0111\xE3 c\xE0i ho\u1EB7c c\xF3 s\u1EB5n`);
|
|
14226
|
+
console.log(` ${chalk43.cyan("info")} Xem chi ti\u1EBFt m\u1ED9t skill`);
|
|
14227
|
+
console.log(` ${chalk43.cyan("sync")} \u0110\u1ED3ng b\u1ED9 skills sang c\xE1c IDE`);
|
|
14070
14228
|
console.log();
|
|
14071
|
-
console.log(
|
|
14072
|
-
console.log(
|
|
14073
|
-
console.log(
|
|
14074
|
-
console.log(
|
|
14075
|
-
console.log(
|
|
14076
|
-
console.log(
|
|
14077
|
-
console.log(
|
|
14229
|
+
console.log(chalk43.bold("V\xED d\u1EE5:"));
|
|
14230
|
+
console.log(chalk43.dim(` $ ${cli} skills find audit`));
|
|
14231
|
+
console.log(chalk43.dim(` $ ${cli} skills find "react" --skillsh`));
|
|
14232
|
+
console.log(chalk43.dim(` $ ${cli} skills add brainstorming`));
|
|
14233
|
+
console.log(chalk43.dim(` $ ${cli} skills add vercel/next-skills --skillsh`));
|
|
14234
|
+
console.log(chalk43.dim(` $ ${cli} skills list`));
|
|
14235
|
+
console.log(chalk43.dim(` $ ${cli} skills sync --all -y`));
|
|
14078
14236
|
console.log();
|
|
14079
|
-
console.log(
|
|
14237
|
+
console.log(chalk43.dim(`Ch\u1EA1y "${cli} skills <l\u1EC7nh> --help" \u0111\u1EC3 xem chi ti\u1EBFt`));
|
|
14080
14238
|
}
|
|
14081
14239
|
function createSkillsCommand() {
|
|
14082
|
-
const cmd = new
|
|
14240
|
+
const cmd = new Command78("skills").alias("s").description("Manage agent skills (search, install, sync to IDEs)").action(() => {
|
|
14083
14241
|
showSkillsHelp();
|
|
14084
14242
|
});
|
|
14085
14243
|
cmd.addCommand(createSkillsFindCommand());
|
|
@@ -14091,8 +14249,8 @@ function createSkillsCommand() {
|
|
|
14091
14249
|
}
|
|
14092
14250
|
|
|
14093
14251
|
// src/commands/upgrade.ts
|
|
14094
|
-
import { Command as
|
|
14095
|
-
import { confirm as
|
|
14252
|
+
import { Command as Command79 } from "commander";
|
|
14253
|
+
import { confirm as confirm18 } from "@inquirer/prompts";
|
|
14096
14254
|
import { execSync as execSync5 } from "child_process";
|
|
14097
14255
|
var colors2 = {
|
|
14098
14256
|
yellow: "\x1B[33m",
|
|
@@ -14103,7 +14261,7 @@ var colors2 = {
|
|
|
14103
14261
|
bold: "\x1B[1m"
|
|
14104
14262
|
};
|
|
14105
14263
|
function createUpgradeCommand() {
|
|
14106
|
-
return new
|
|
14264
|
+
return new Command79("upgrade").description("Upgrade CLI client to the latest version").option("--check", "Only check for updates without installing").option("-y, --force", "Upgrade without confirmation prompt (skip if already latest)").action(async (options) => {
|
|
14107
14265
|
await handleUpgrade(options);
|
|
14108
14266
|
});
|
|
14109
14267
|
}
|
|
@@ -14133,8 +14291,13 @@ ${colors2.bold}Current version:${colors2.reset} ${currentVersion}`);
|
|
|
14133
14291
|
console.log(`${colors2.bold}Latest version:${colors2.reset} ${latestVersion}
|
|
14134
14292
|
`);
|
|
14135
14293
|
if (!isNewerVersion2(latestVersion, currentVersion)) {
|
|
14136
|
-
|
|
14294
|
+
if (options.force) {
|
|
14295
|
+
console.log(`${colors2.green}\u2705 Already on the latest version (${currentVersion}). No upgrade needed.${colors2.reset}
|
|
14296
|
+
`);
|
|
14297
|
+
} else {
|
|
14298
|
+
console.log(`${colors2.green}\u2705 You're already on the latest version!${colors2.reset}
|
|
14137
14299
|
`);
|
|
14300
|
+
}
|
|
14138
14301
|
return;
|
|
14139
14302
|
}
|
|
14140
14303
|
console.log(`${colors2.yellow}\u256D\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256E${colors2.reset}`);
|
|
@@ -14147,7 +14310,7 @@ ${colors2.bold}Current version:${colors2.reset} ${currentVersion}`);
|
|
|
14147
14310
|
return;
|
|
14148
14311
|
}
|
|
14149
14312
|
if (!options.force) {
|
|
14150
|
-
const shouldUpdate = await
|
|
14313
|
+
const shouldUpdate = await confirm18({
|
|
14151
14314
|
message: "Update to the latest version now?",
|
|
14152
14315
|
default: true
|
|
14153
14316
|
});
|
|
@@ -14251,11 +14414,11 @@ function getInstallCommand(packageManager2) {
|
|
|
14251
14414
|
}
|
|
14252
14415
|
|
|
14253
14416
|
// src/commands/clean.ts
|
|
14254
|
-
import { Command as
|
|
14255
|
-
import { confirm as
|
|
14417
|
+
import { Command as Command80 } from "commander";
|
|
14418
|
+
import { confirm as confirm19, select as select6 } from "@inquirer/prompts";
|
|
14256
14419
|
import { join as join21 } from "path";
|
|
14257
14420
|
function createCleanCommand() {
|
|
14258
|
-
return new
|
|
14421
|
+
return new Command80("clean").description("Clean up backups, cache, and temporary files").option("-y, --yes", "Skip confirmation").option("--backups", "Clean only backup files").option("--all", "Clean all (backups + cache)").action(async (options) => {
|
|
14259
14422
|
await handleClean(options);
|
|
14260
14423
|
});
|
|
14261
14424
|
}
|
|
@@ -14351,7 +14514,7 @@ async function cleanTarget(target, skipConfirm) {
|
|
|
14351
14514
|
}
|
|
14352
14515
|
const countStr = info.count ? ` (${info.count} items)` : "";
|
|
14353
14516
|
if (!skipConfirm) {
|
|
14354
|
-
const confirmed = await
|
|
14517
|
+
const confirmed = await confirm19({
|
|
14355
14518
|
message: `Delete ${target.name}${countStr}?`,
|
|
14356
14519
|
default: false
|
|
14357
14520
|
});
|
|
@@ -14369,7 +14532,7 @@ async function cleanTarget(target, skipConfirm) {
|
|
|
14369
14532
|
}
|
|
14370
14533
|
|
|
14371
14534
|
// src/commands/redmine/check.ts
|
|
14372
|
-
import { Command as
|
|
14535
|
+
import { Command as Command81 } from "commander";
|
|
14373
14536
|
|
|
14374
14537
|
// src/services/redmine-config.service.ts
|
|
14375
14538
|
import { readFile as readFile7 } from "fs/promises";
|
|
@@ -14676,7 +14839,7 @@ async function checkConnectivity(config) {
|
|
|
14676
14839
|
|
|
14677
14840
|
// src/commands/redmine/check.ts
|
|
14678
14841
|
function createRedmineCheckCommand() {
|
|
14679
|
-
const cmd = new
|
|
14842
|
+
const cmd = new Command81("check").description("Check Redmine connectivity").option("-c, --config <path>", "Config file path", "redmine.config.yaml").option("--json", "Output as JSON").action(async (options) => {
|
|
14680
14843
|
await handleRedmineCheck(options);
|
|
14681
14844
|
});
|
|
14682
14845
|
return cmd;
|
|
@@ -14704,7 +14867,7 @@ async function handleRedmineCheck(options) {
|
|
|
14704
14867
|
}
|
|
14705
14868
|
|
|
14706
14869
|
// src/commands/redmine/sync-issue.ts
|
|
14707
|
-
import { Command as
|
|
14870
|
+
import { Command as Command82 } from "commander";
|
|
14708
14871
|
|
|
14709
14872
|
// src/sync-issue.ts
|
|
14710
14873
|
import { resolve as resolve3, relative } from "path";
|
|
@@ -15088,7 +15251,7 @@ function extractIssueIdFromUrl(url) {
|
|
|
15088
15251
|
|
|
15089
15252
|
// src/commands/redmine/sync-issue.ts
|
|
15090
15253
|
function createSyncIssueCommand() {
|
|
15091
|
-
const cmd = new
|
|
15254
|
+
const cmd = new Command82("issue").description("Sync a single issue").option("-i, --id <number>", "Issue ID").option("-u, --url <url>", "Issue URL").option("--dry-run", "Preview without making changes").option("-c, --config <path>", "Config file path").option("-o, --output-dir <path>", "Output directory").option("--json", "Output as JSON").action(async (options) => {
|
|
15092
15255
|
await handleSyncIssue(options);
|
|
15093
15256
|
});
|
|
15094
15257
|
return cmd;
|
|
@@ -15132,7 +15295,7 @@ async function handleSyncIssue(options) {
|
|
|
15132
15295
|
}
|
|
15133
15296
|
|
|
15134
15297
|
// src/commands/redmine/sync-project.ts
|
|
15135
|
-
import { Command as
|
|
15298
|
+
import { Command as Command83 } from "commander";
|
|
15136
15299
|
|
|
15137
15300
|
// src/sync-project.ts
|
|
15138
15301
|
async function syncProject(config, options = {}) {
|
|
@@ -15202,7 +15365,7 @@ async function syncProject(config, options = {}) {
|
|
|
15202
15365
|
|
|
15203
15366
|
// src/commands/redmine/sync-project.ts
|
|
15204
15367
|
function createSyncProjectCommand() {
|
|
15205
|
-
const cmd = new
|
|
15368
|
+
const cmd = new Command83("project").description("Sync all issues in a project").option("-s, --status <status>", "Filter by status (default: *)", "*").option("--updated-since <date>", "Only sync issues updated since YYYY-MM-DD").option("--concurrency <number>", "Number of concurrent requests").option("--page-size <number>", "Page size for API requests").option("--dry-run", "Preview without making changes").option("-c, --config <path>", "Config file path").option("-o, --output-dir <path>", "Output directory").option("--json", "Output as JSON").action(async (options) => {
|
|
15206
15369
|
await handleSyncProject(options);
|
|
15207
15370
|
});
|
|
15208
15371
|
return cmd;
|
|
@@ -15257,12 +15420,12 @@ async function handleSyncProject(options) {
|
|
|
15257
15420
|
}
|
|
15258
15421
|
|
|
15259
15422
|
// src/commands/framework/info.ts
|
|
15260
|
-
import { Command as
|
|
15423
|
+
import { Command as Command84 } from "commander";
|
|
15261
15424
|
import { promises as fs28 } from "fs";
|
|
15262
15425
|
import { join as join22 } from "path";
|
|
15263
15426
|
import { homedir as homedir5 } from "os";
|
|
15264
15427
|
function createInfoCommand() {
|
|
15265
|
-
const cmd = new
|
|
15428
|
+
const cmd = new Command84("info").description("Show client configuration and status").option("--json", "Output as JSON").option("--verbose", "Show detailed information").action(async (options) => {
|
|
15266
15429
|
await handleInfo(options);
|
|
15267
15430
|
});
|
|
15268
15431
|
return cmd;
|
|
@@ -15318,8 +15481,8 @@ async function getProjectStatus2() {
|
|
|
15318
15481
|
}
|
|
15319
15482
|
|
|
15320
15483
|
// src/commands/self-update.ts
|
|
15321
|
-
import { Command as
|
|
15322
|
-
import { confirm as
|
|
15484
|
+
import { Command as Command85 } from "commander";
|
|
15485
|
+
import { confirm as confirm20 } from "@inquirer/prompts";
|
|
15323
15486
|
import { execSync as execSync6 } from "child_process";
|
|
15324
15487
|
var colors3 = {
|
|
15325
15488
|
yellow: "\x1B[33m",
|
|
@@ -15330,7 +15493,7 @@ var colors3 = {
|
|
|
15330
15493
|
bold: "\x1B[1m"
|
|
15331
15494
|
};
|
|
15332
15495
|
function createSelfUpdateCommand() {
|
|
15333
|
-
return new
|
|
15496
|
+
return new Command85("self-update").description("Update CLI client to the latest version").option("--check", "Only check for updates without installing").option("--force", "Force update without confirmation").action(async (options) => {
|
|
15334
15497
|
await handleSelfUpdate(options);
|
|
15335
15498
|
});
|
|
15336
15499
|
}
|
|
@@ -15374,7 +15537,7 @@ ${colors3.bold}Current version:${colors3.reset} ${currentVersion}`);
|
|
|
15374
15537
|
return;
|
|
15375
15538
|
}
|
|
15376
15539
|
if (!options.force) {
|
|
15377
|
-
const shouldUpdate = await
|
|
15540
|
+
const shouldUpdate = await confirm20({
|
|
15378
15541
|
message: "Update to the latest version now?",
|
|
15379
15542
|
default: true
|
|
15380
15543
|
});
|
|
@@ -15470,10 +15633,10 @@ function getInstallCommand2(packageManager2) {
|
|
|
15470
15633
|
}
|
|
15471
15634
|
|
|
15472
15635
|
// src/commands/clear-backups.ts
|
|
15473
|
-
import { Command as
|
|
15474
|
-
import { confirm as
|
|
15636
|
+
import { Command as Command86 } from "commander";
|
|
15637
|
+
import { confirm as confirm21 } from "@inquirer/prompts";
|
|
15475
15638
|
function createClearBackupsCommand() {
|
|
15476
|
-
return new
|
|
15639
|
+
return new Command86("clear-backups").description("Clear backup files").option("-y, --yes", "Skip confirmation").action(async (options) => {
|
|
15477
15640
|
const service = new ComponentsService();
|
|
15478
15641
|
const backups = await service.listBackups(process.cwd());
|
|
15479
15642
|
if (backups.length === 0) {
|
|
@@ -15489,7 +15652,7 @@ function createClearBackupsCommand() {
|
|
|
15489
15652
|
}
|
|
15490
15653
|
console.log();
|
|
15491
15654
|
if (!options.yes) {
|
|
15492
|
-
const ok = await
|
|
15655
|
+
const ok = await confirm21({ message: "Delete all backups?", default: false });
|
|
15493
15656
|
if (!ok) return;
|
|
15494
15657
|
}
|
|
15495
15658
|
await service.clearBackups(process.cwd());
|
|
@@ -15498,8 +15661,8 @@ function createClearBackupsCommand() {
|
|
|
15498
15661
|
}
|
|
15499
15662
|
|
|
15500
15663
|
// src/commands/vscode/index.ts
|
|
15501
|
-
import { Command as
|
|
15502
|
-
import { checkbox as checkbox9, confirm as
|
|
15664
|
+
import { Command as Command87 } from "commander";
|
|
15665
|
+
import { checkbox as checkbox9, confirm as confirm22, select as select7 } from "@inquirer/prompts";
|
|
15503
15666
|
import fs29 from "fs/promises";
|
|
15504
15667
|
import path12 from "path";
|
|
15505
15668
|
import { existsSync as existsSync4 } from "fs";
|
|
@@ -15638,7 +15801,7 @@ var PERFORMANCE_GROUPS2 = {
|
|
|
15638
15801
|
}
|
|
15639
15802
|
};
|
|
15640
15803
|
function createVSCodeCommand() {
|
|
15641
|
-
const vscodeCommand = new
|
|
15804
|
+
const vscodeCommand = new Command87("vscode").description("Qu\u1EA3n l\xFD c\xE0i \u0111\u1EB7t VSCode cho d\u1EF1 \xE1n hi\u1EC7n t\u1EA1i");
|
|
15642
15805
|
vscodeCommand.action(async () => {
|
|
15643
15806
|
await interactiveMode2();
|
|
15644
15807
|
});
|
|
@@ -15744,7 +15907,7 @@ async function applyGroups2(groupKeys, action) {
|
|
|
15744
15907
|
console.log("\u{1F4C4} \u0110\xE3 \u0111\u1ECDc c\xE0i \u0111\u1EB7t hi\u1EC7n t\u1EA1i t\u1EEB settings.json");
|
|
15745
15908
|
} catch {
|
|
15746
15909
|
console.warn("\u26A0\uFE0F Kh\xF4ng th\u1EC3 \u0111\u1ECDc settings.json (c\xF3 th\u1EC3 ch\u1EE9a comments).");
|
|
15747
|
-
const confirmOverwrite = await
|
|
15910
|
+
const confirmOverwrite = await confirm22({
|
|
15748
15911
|
message: "Ghi \u0111\xE8 file settings.json hi\u1EC7n t\u1EA1i?",
|
|
15749
15912
|
default: false
|
|
15750
15913
|
});
|
|
@@ -15791,7 +15954,7 @@ async function resetSettings2(groupKeys) {
|
|
|
15791
15954
|
console.log("\n\u26A0\uFE0F Kh\xF4ng t\xECm th\u1EA5y file settings.json");
|
|
15792
15955
|
return;
|
|
15793
15956
|
}
|
|
15794
|
-
const confirmReset = await
|
|
15957
|
+
const confirmReset = await confirm22({
|
|
15795
15958
|
message: groupKeys.length === 0 ? "Reset T\u1EA4T C\u1EA2 settings v\u1EC1 m\u1EB7c \u0111\u1ECBnh (x\xF3a to\xE0n b\u1ED9 file)?" : `Reset c\xE1c nh\xF3m: ${groupKeys.join(", ")}?`,
|
|
15796
15959
|
default: false
|
|
15797
15960
|
});
|
|
@@ -15809,10 +15972,10 @@ async function resetSettings2(groupKeys) {
|
|
|
15809
15972
|
}
|
|
15810
15973
|
|
|
15811
15974
|
// src/commands/migrate-ide.ts
|
|
15812
|
-
import { Command as
|
|
15813
|
-
import { checkbox as checkbox10, confirm as
|
|
15975
|
+
import { Command as Command88 } from "commander";
|
|
15976
|
+
import { checkbox as checkbox10, confirm as confirm23 } from "@inquirer/prompts";
|
|
15814
15977
|
function createMigrateIdeCommand() {
|
|
15815
|
-
const cmd = new
|
|
15978
|
+
const cmd = new Command88("migrate-ide").description("Migrate .jai1 rules v\xE0 workflows sang IDEs (Cursor, Windsurf, Claude Code, etc.)").option("--ide <ides...>", "Target IDEs (cursor, windsurf, antigravity, claudecode, opencode)").option("--type <types...>", "Content types (rules, workflows, commands)").option("--dry-run", "Preview changes without writing files").action(async (options) => {
|
|
15816
15979
|
await runMigrateIde(options);
|
|
15817
15980
|
});
|
|
15818
15981
|
return cmd;
|
|
@@ -15883,7 +16046,7 @@ async function runMigrateIde(options) {
|
|
|
15883
16046
|
if (options.dryRun) {
|
|
15884
16047
|
console.log("\u{1F50D} DRY RUN - No files will be written\n");
|
|
15885
16048
|
}
|
|
15886
|
-
const confirmed = await
|
|
16049
|
+
const confirmed = await confirm23({
|
|
15887
16050
|
message: "Proceed with migration?",
|
|
15888
16051
|
default: true
|
|
15889
16052
|
});
|
|
@@ -15921,20 +16084,20 @@ async function runMigrateIde(options) {
|
|
|
15921
16084
|
|
|
15922
16085
|
// src/utils/help-formatter.ts
|
|
15923
16086
|
import boxen4 from "boxen";
|
|
15924
|
-
import
|
|
16087
|
+
import chalk44 from "chalk";
|
|
15925
16088
|
import gradient from "gradient-string";
|
|
15926
16089
|
import figlet from "figlet";
|
|
15927
16090
|
function showCustomHelp(version) {
|
|
15928
16091
|
const title = figlet.textSync("JAI1", { font: "Small" });
|
|
15929
16092
|
console.log(gradient.pastel(title));
|
|
15930
16093
|
console.log(
|
|
15931
|
-
boxen4(
|
|
16094
|
+
boxen4(chalk44.cyan(`Agentic Coding CLI v${version}`), {
|
|
15932
16095
|
padding: { left: 1, right: 1, top: 0, bottom: 0 },
|
|
15933
16096
|
borderStyle: "round",
|
|
15934
16097
|
borderColor: "cyan"
|
|
15935
16098
|
})
|
|
15936
16099
|
);
|
|
15937
|
-
console.log(
|
|
16100
|
+
console.log(chalk44.bold("\n\u{1F527} Thi\u1EBFt l\u1EADp & Th\xF4ng tin"));
|
|
15938
16101
|
console.log(" auth X\xE1c th\u1EF1c v\xE0 c\u1EA5u h\xECnh client");
|
|
15939
16102
|
console.log(" status Hi\u1EC3n th\u1ECB tr\u1EA1ng th\xE1i c\u1EA5u h\xECnh");
|
|
15940
16103
|
console.log(" client-info T\u1EA1o th\xF4ng tin client \u0111\u1EC3 g\u1EEDi \u0111\u1ED9i ph\xE1t tri\u1EC3n");
|
|
@@ -15942,43 +16105,43 @@ function showCustomHelp(version) {
|
|
|
15942
16105
|
console.log(" guide H\u01B0\u1EDBng d\u1EABn s\u1EED d\u1EE5ng nhanh");
|
|
15943
16106
|
console.log(" quickstart B\u1EAFt \u0111\u1EA7u t\u1EEB \u0111\xE2u? (theo t\xECnh hu\u1ED1ng)");
|
|
15944
16107
|
console.log(" doctor Chu\u1EA9n \u0111o\xE1n project hi\u1EC7n t\u1EA1i");
|
|
15945
|
-
console.log(
|
|
16108
|
+
console.log(chalk44.bold("\n\u{1F4E6} Qu\u1EA3n l\xFD Components"));
|
|
15946
16109
|
console.log(" apply C\xE0i \u0111\u1EB7t components (interactive)");
|
|
15947
16110
|
console.log(" update C\u1EADp nh\u1EADt components \u0111\xE3 c\xE0i");
|
|
15948
16111
|
console.log(" check Ki\u1EC3m tra c\u1EADp nh\u1EADt t\u1EEB server");
|
|
15949
|
-
console.log(
|
|
16112
|
+
console.log(chalk44.bold("\n\u{1F5A5}\uFE0F IDE & T\xEDch h\u1EE3p"));
|
|
15950
16113
|
console.log(" ide L\u1EC7nh c\u1EA5u h\xECnh IDE");
|
|
15951
16114
|
console.log(" chat Chat AI v\u1EDBi Jai1 LLM Proxy");
|
|
15952
16115
|
console.log(" openai-keys Th\xF4ng tin API credentials");
|
|
15953
|
-
console.log(
|
|
16116
|
+
console.log(chalk44.bold("\n\u{1F916} AI Tools"));
|
|
15954
16117
|
console.log(" translate D\u1ECBch v\u0103n b\u1EA3n/file b\u1EB1ng AI");
|
|
15955
16118
|
console.log(" image T\u1EA1o \u1EA3nh (Coming Soon)");
|
|
15956
16119
|
console.log(" stats Th\u1ED1ng k\xEA s\u1EED d\u1EE5ng LLM");
|
|
15957
16120
|
console.log(" feedback G\u1EEDi b\xE1o c\xE1o/\u0111\u1EC1 xu\u1EA5t");
|
|
15958
|
-
console.log(
|
|
16121
|
+
console.log(chalk44.bold("\n\u{1F4C1} Project"));
|
|
15959
16122
|
console.log(" kit Qu\u1EA3n l\xFD starter kits");
|
|
15960
16123
|
console.log(" tasks (t) Qu\u1EA3n l\xFD tasks ph\xE1t tri\u1EC3n");
|
|
15961
16124
|
console.log(" rules Qu\u1EA3n l\xFD rule presets");
|
|
15962
16125
|
console.log(" deps Qu\u1EA3n l\xFD dependencies");
|
|
15963
16126
|
console.log(" redmine Redmine context sync");
|
|
15964
|
-
console.log(
|
|
16127
|
+
console.log(chalk44.bold("\n\u2699\uFE0F B\u1EA3o tr\xEC"));
|
|
15965
16128
|
console.log(" upgrade C\u1EADp nh\u1EADt CLI client");
|
|
15966
16129
|
console.log(" clean D\u1ECDn d\u1EB9p cache/backup");
|
|
15967
16130
|
console.log(" utils Developer utilities");
|
|
15968
16131
|
const name = getCliName();
|
|
15969
|
-
console.log(
|
|
16132
|
+
console.log(chalk44.dim(`
|
|
15970
16133
|
S\u1EED d\u1EE5ng: ${name} [l\u1EC7nh] --help \u0111\u1EC3 xem chi ti\u1EBFt`));
|
|
15971
16134
|
}
|
|
15972
16135
|
function showUnknownCommand(commandName) {
|
|
15973
|
-
console.error(
|
|
16136
|
+
console.error(chalk44.red(`\u274C L\u1EC7nh kh\xF4ng t\u1ED3n t\u1EA1i: ${commandName}`));
|
|
15974
16137
|
const name = getCliName();
|
|
15975
|
-
console.error(
|
|
16138
|
+
console.error(chalk44.dim(`
|
|
15976
16139
|
G\u1EE3i \xFD: Ch\u1EA1y ${name} --help \u0111\u1EC3 xem danh s\xE1ch l\u1EC7nh`));
|
|
15977
16140
|
}
|
|
15978
16141
|
|
|
15979
16142
|
// src/cli.ts
|
|
15980
16143
|
checkNodeVersion();
|
|
15981
|
-
var program = new
|
|
16144
|
+
var program = new Command89();
|
|
15982
16145
|
if (process.argv.includes("-v") || process.argv.includes("--version")) {
|
|
15983
16146
|
console.log(package_default.version);
|
|
15984
16147
|
if (!process.argv.includes("--skip-update-check")) {
|
|
@@ -16020,9 +16183,9 @@ program.addCommand(createSkillsCommand());
|
|
|
16020
16183
|
program.addCommand(createHooksCommand());
|
|
16021
16184
|
program.addCommand(createUpgradeCommand());
|
|
16022
16185
|
program.addCommand(createCleanCommand());
|
|
16023
|
-
var redmineCommand = new
|
|
16186
|
+
var redmineCommand = new Command89("redmine").description("Redmine context sync commands");
|
|
16024
16187
|
redmineCommand.addCommand(createRedmineCheckCommand());
|
|
16025
|
-
var syncCommand = new
|
|
16188
|
+
var syncCommand = new Command89("sync").description("Sync Redmine issues to markdown files");
|
|
16026
16189
|
syncCommand.addCommand(createSyncIssueCommand());
|
|
16027
16190
|
syncCommand.addCommand(createSyncProjectCommand());
|
|
16028
16191
|
redmineCommand.addCommand(syncCommand);
|