@jvittechs/jai1-cli 0.1.90 → 0.1.92
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/cli.js +503 -151
- package/dist/cli.js.map +1 -1
- package/package.json +2 -1
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/cli.ts
|
|
4
|
-
import { Command as
|
|
4
|
+
import { Command as Command60 } from "commander";
|
|
5
5
|
|
|
6
6
|
// src/errors/index.ts
|
|
7
7
|
var Jai1Error = class extends Error {
|
|
@@ -33,7 +33,7 @@ var NetworkError = class extends Jai1Error {
|
|
|
33
33
|
// package.json
|
|
34
34
|
var package_default = {
|
|
35
35
|
name: "@jvittechs/jai1-cli",
|
|
36
|
-
version: "0.1.
|
|
36
|
+
version: "0.1.92",
|
|
37
37
|
description: "A unified CLI tool for JV-IT TECHS developers to manage Jai1 Framework. Please contact TeamAI for usage instructions.",
|
|
38
38
|
type: "module",
|
|
39
39
|
bin: {
|
|
@@ -97,6 +97,7 @@ var package_default = {
|
|
|
97
97
|
"p-retry": "^6.2.0",
|
|
98
98
|
react: "^18.3.1",
|
|
99
99
|
slugify: "^1.6.6",
|
|
100
|
+
"terminal-image": "^4.1.0",
|
|
100
101
|
undici: "^6.19.5",
|
|
101
102
|
yaml: "^2.5.0",
|
|
102
103
|
zod: "^3.23.8"
|
|
@@ -539,7 +540,11 @@ var ComponentsService = class {
|
|
|
539
540
|
const bundleJson = gunzipSync(compressed).toString("utf-8");
|
|
540
541
|
checksumContent = bundleJson;
|
|
541
542
|
const bundle = JSON.parse(bundleJson);
|
|
542
|
-
const presetDir = join2(targetDir,
|
|
543
|
+
const presetDir = join2(targetDir, "rule-preset");
|
|
544
|
+
try {
|
|
545
|
+
await fs2.rm(presetDir, { recursive: true, force: true });
|
|
546
|
+
} catch {
|
|
547
|
+
}
|
|
543
548
|
await fs2.mkdir(presetDir, { recursive: true });
|
|
544
549
|
await fs2.writeFile(
|
|
545
550
|
join2(presetDir, "preset.json"),
|
|
@@ -879,7 +884,7 @@ var UnifiedApplyApp = ({
|
|
|
879
884
|
const [searchQuery, setSearchQuery] = useState("");
|
|
880
885
|
const [selectedPaths, setSelectedPaths] = useState(/* @__PURE__ */ new Set());
|
|
881
886
|
const [cursorIndex, setCursorIndex] = useState(0);
|
|
882
|
-
const [focusArea, setFocusArea] = useState("
|
|
887
|
+
const [focusArea, setFocusArea] = useState("packages");
|
|
883
888
|
const [selectedPackageIndex, setSelectedPackageIndex] = useState(0);
|
|
884
889
|
const [installProgress, setInstallProgress] = useState([]);
|
|
885
890
|
const [installStats, setInstallStats] = useState({ total: 0, completed: 0, added: 0, updated: 0, failed: 0 });
|
|
@@ -922,9 +927,9 @@ var UnifiedApplyApp = ({
|
|
|
922
927
|
return;
|
|
923
928
|
}
|
|
924
929
|
if (key.tab) {
|
|
925
|
-
if (focusArea === "
|
|
926
|
-
else if (focusArea === "
|
|
927
|
-
else setFocusArea("
|
|
930
|
+
if (focusArea === "packages") setFocusArea("components");
|
|
931
|
+
else if (focusArea === "components") setFocusArea("search");
|
|
932
|
+
else setFocusArea("packages");
|
|
928
933
|
return;
|
|
929
934
|
}
|
|
930
935
|
if (key.escape || input4 === "q") {
|
|
@@ -937,6 +942,19 @@ var UnifiedApplyApp = ({
|
|
|
937
942
|
}
|
|
938
943
|
return;
|
|
939
944
|
}
|
|
945
|
+
if (focusArea !== "search") {
|
|
946
|
+
if (input4 === "a") {
|
|
947
|
+
setSelectedPaths((prev) => {
|
|
948
|
+
const next = new Set(prev);
|
|
949
|
+
filteredComponents.forEach((c) => next.add(c.filepath));
|
|
950
|
+
return next;
|
|
951
|
+
});
|
|
952
|
+
return;
|
|
953
|
+
} else if (input4 === "c") {
|
|
954
|
+
setSelectedPaths(/* @__PURE__ */ new Set());
|
|
955
|
+
return;
|
|
956
|
+
}
|
|
957
|
+
}
|
|
940
958
|
if (focusArea === "components") {
|
|
941
959
|
if (key.upArrow) {
|
|
942
960
|
setCursorIndex((prev) => Math.max(0, prev - 1));
|
|
@@ -955,14 +973,6 @@ var UnifiedApplyApp = ({
|
|
|
955
973
|
return next;
|
|
956
974
|
});
|
|
957
975
|
}
|
|
958
|
-
} else if (input4 === "a") {
|
|
959
|
-
setSelectedPaths((prev) => {
|
|
960
|
-
const next = new Set(prev);
|
|
961
|
-
filteredComponents.forEach((c) => next.add(c.filepath));
|
|
962
|
-
return next;
|
|
963
|
-
});
|
|
964
|
-
} else if (input4 === "c") {
|
|
965
|
-
setSelectedPaths(/* @__PURE__ */ new Set());
|
|
966
976
|
}
|
|
967
977
|
}
|
|
968
978
|
if (focusArea === "packages") {
|
|
@@ -1067,7 +1077,7 @@ var UnifiedApplyApp = ({
|
|
|
1067
1077
|
const isChecked = selectedPaths.has(comp.filepath);
|
|
1068
1078
|
const isInstalled = installedPaths.has(comp.filepath);
|
|
1069
1079
|
return /* @__PURE__ */ React3.createElement(Box2, { key: comp.filepath }, /* @__PURE__ */ React3.createElement(Text3, { color: isCursor ? "cyan" : "white" }, isCursor ? "\u276F " : " ", isChecked ? "[\u2713]" : "[ ]", " ", comp.filepath), /* @__PURE__ */ React3.createElement(Text3, { dimColor: true }, " ", isInstalled ? "\u2713 installed" : "\u25CB new"));
|
|
1070
|
-
}), filteredComponents.length === 0 && /* @__PURE__ */ React3.createElement(Text3, { dimColor: true }, "No components match your search")), selectedPaths.size > 0 && /* @__PURE__ */ React3.createElement(Box2, { marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React3.createElement(Text3, { bold: true }, "Selected: ", selectedPaths.size, " components"), /* @__PURE__ */ React3.createElement(Box2, { flexDirection: "column", marginLeft: 2 }, Array.from(selectedPaths).slice(0, 4).map((fp) => /* @__PURE__ */ React3.createElement(Text3, { key: fp, dimColor: true }, "\u{1F4CC} ", fp)), selectedPaths.size > 4 && /* @__PURE__ */ React3.createElement(Text3, { dimColor: true }, " ... and ", selectedPaths.size - 4, " more"))), /* @__PURE__ */ React3.createElement(Box2, { marginTop: 1, borderStyle: "single", borderColor: "gray", paddingX: 1 }, /* @__PURE__ */ React3.createElement(Text3, { dimColor: true }, "[Tab] Switch area \xB7 [\u2191\u2193] Navigate \xB7 [\u2423] Toggle \xB7 [
|
|
1080
|
+
}), filteredComponents.length === 0 && /* @__PURE__ */ React3.createElement(Text3, { dimColor: true }, "No components match your search")), selectedPaths.size > 0 && /* @__PURE__ */ React3.createElement(Box2, { marginTop: 1, flexDirection: "column" }, /* @__PURE__ */ React3.createElement(Text3, { bold: true }, "Selected: ", selectedPaths.size, " components"), /* @__PURE__ */ React3.createElement(Box2, { flexDirection: "column", marginLeft: 2 }, Array.from(selectedPaths).slice(0, 4).map((fp) => /* @__PURE__ */ React3.createElement(Text3, { key: fp, dimColor: true }, "\u{1F4CC} ", fp)), selectedPaths.size > 4 && /* @__PURE__ */ React3.createElement(Text3, { dimColor: true }, " ... and ", selectedPaths.size - 4, " more"))), /* @__PURE__ */ React3.createElement(Box2, { marginTop: 1, borderStyle: "single", borderColor: "gray", paddingX: 1 }, /* @__PURE__ */ React3.createElement(Text3, { dimColor: true }, "[Tab] Switch area \xB7 [\u2191\u2193/\u2190\u2192] Navigate \xB7 [\u2423] Toggle \xB7 [A] Select all \xB7 [C] Clear \xB7 [Enter] Apply \xB7 [Q] Quit")));
|
|
1071
1081
|
};
|
|
1072
1082
|
|
|
1073
1083
|
// src/commands/apply.ts
|
|
@@ -2529,17 +2539,20 @@ trigger: ${trigger}
|
|
|
2529
2539
|
name: "Claude Code",
|
|
2530
2540
|
icon: "\u{1F916}",
|
|
2531
2541
|
basePath: ".claude",
|
|
2532
|
-
rulesPath:
|
|
2542
|
+
rulesPath: "rules",
|
|
2533
2543
|
workflowsPath: null,
|
|
2534
2544
|
commandsPath: "commands",
|
|
2535
2545
|
fileExtension: ".md",
|
|
2536
2546
|
generateFrontmatter: (opts) => {
|
|
2547
|
+
const lines = ["---"];
|
|
2537
2548
|
if (opts.description) {
|
|
2538
|
-
|
|
2539
|
-
description: ${opts.description}
|
|
2540
|
-
---`;
|
|
2549
|
+
lines.push(`description: ${opts.description}`);
|
|
2541
2550
|
}
|
|
2542
|
-
|
|
2551
|
+
if (opts.globs && opts.globs.length > 0) {
|
|
2552
|
+
lines.push(`paths: ${opts.globs.join(", ")}`);
|
|
2553
|
+
}
|
|
2554
|
+
lines.push("---");
|
|
2555
|
+
return lines.join("\n");
|
|
2543
2556
|
}
|
|
2544
2557
|
},
|
|
2545
2558
|
opencode: {
|
|
@@ -2575,7 +2588,9 @@ var MigrateIdeService = class {
|
|
|
2575
2588
|
* Scan .jai1/ directory for content
|
|
2576
2589
|
*/
|
|
2577
2590
|
async scanJai1Content() {
|
|
2578
|
-
const
|
|
2591
|
+
const manualRules = await this.scanContentType("rules");
|
|
2592
|
+
const presetRules = await this.scanRulePreset();
|
|
2593
|
+
const rules = [...presetRules, ...manualRules];
|
|
2579
2594
|
const workflows = await this.scanContentType("workflows");
|
|
2580
2595
|
const commands = [];
|
|
2581
2596
|
return {
|
|
@@ -2585,6 +2600,42 @@ var MigrateIdeService = class {
|
|
|
2585
2600
|
totalCount: rules.length + workflows.length + commands.length
|
|
2586
2601
|
};
|
|
2587
2602
|
}
|
|
2603
|
+
/**
|
|
2604
|
+
* Scan .jai1/rule-preset/ directory for rule preset files
|
|
2605
|
+
*/
|
|
2606
|
+
async scanRulePreset() {
|
|
2607
|
+
const items = [];
|
|
2608
|
+
const presetDir = path3.join(this.jai1Path, "rule-preset");
|
|
2609
|
+
try {
|
|
2610
|
+
await fs6.access(presetDir);
|
|
2611
|
+
} catch {
|
|
2612
|
+
return items;
|
|
2613
|
+
}
|
|
2614
|
+
const files = await fs6.readdir(presetDir);
|
|
2615
|
+
for (const file of files) {
|
|
2616
|
+
if (!file.endsWith(".mdc")) continue;
|
|
2617
|
+
const filepath = path3.join(presetDir, file);
|
|
2618
|
+
const stat = await fs6.stat(filepath);
|
|
2619
|
+
if (!stat.isFile()) continue;
|
|
2620
|
+
const content = await fs6.readFile(filepath, "utf-8");
|
|
2621
|
+
let frontmatter = {};
|
|
2622
|
+
try {
|
|
2623
|
+
const { data } = matter2(content);
|
|
2624
|
+
frontmatter = data;
|
|
2625
|
+
} catch {
|
|
2626
|
+
}
|
|
2627
|
+
items.push({
|
|
2628
|
+
type: "rules",
|
|
2629
|
+
name: path3.basename(file, ".mdc"),
|
|
2630
|
+
filepath,
|
|
2631
|
+
relativePath: path3.relative(this.projectPath, filepath),
|
|
2632
|
+
description: frontmatter.description,
|
|
2633
|
+
globs: this.extractGlobs(frontmatter),
|
|
2634
|
+
alwaysApply: this.extractAlwaysApply(frontmatter)
|
|
2635
|
+
});
|
|
2636
|
+
}
|
|
2637
|
+
return items;
|
|
2638
|
+
}
|
|
2588
2639
|
/**
|
|
2589
2640
|
* Scan a specific content type
|
|
2590
2641
|
*/
|
|
@@ -2708,7 +2759,7 @@ ${reference}
|
|
|
2708
2759
|
contentPath = config.rulesPath;
|
|
2709
2760
|
break;
|
|
2710
2761
|
case "workflows":
|
|
2711
|
-
contentPath = config.workflowsPath;
|
|
2762
|
+
contentPath = config.workflowsPath ?? config.commandsPath;
|
|
2712
2763
|
break;
|
|
2713
2764
|
case "commands":
|
|
2714
2765
|
contentPath = config.commandsPath;
|
|
@@ -2743,13 +2794,17 @@ async function runSync(options) {
|
|
|
2743
2794
|
const service = new MigrateIdeService();
|
|
2744
2795
|
console.log("\n\u{1F504} Sync rules and workflows to IDE(s)\n");
|
|
2745
2796
|
console.log("\u{1F4C1} Scanning .jai1/ directory...");
|
|
2797
|
+
console.log(" \u2022 .jai1/rule-preset/ (active rule preset)");
|
|
2798
|
+
console.log(" \u2022 .jai1/rules/ (manual rules)");
|
|
2799
|
+
console.log(" \u2022 .jai1/workflows/\n");
|
|
2746
2800
|
const content = await service.scanJai1Content();
|
|
2747
2801
|
if (content.totalCount === 0) {
|
|
2748
|
-
console.log("\
|
|
2749
|
-
console.log(
|
|
2802
|
+
console.log("\u26A0\uFE0F No content found in .jai1/");
|
|
2803
|
+
console.log(' \u{1F4A1} Run "jai1 rules apply" to apply a rule preset, or');
|
|
2804
|
+
console.log(" \u{1F4A1} Create files in .jai1/rules/ or .jai1/workflows/\n");
|
|
2750
2805
|
process.exit(1);
|
|
2751
2806
|
}
|
|
2752
|
-
console.log(
|
|
2807
|
+
console.log(`\u2713 Found: ${content.rules.length} rules, ${content.workflows.length} workflows
|
|
2753
2808
|
`);
|
|
2754
2809
|
let selectedIdes;
|
|
2755
2810
|
if (options.ide && options.ide.length > 0) {
|
|
@@ -5360,11 +5415,266 @@ function createTranslateCommand() {
|
|
|
5360
5415
|
return cmd;
|
|
5361
5416
|
}
|
|
5362
5417
|
|
|
5418
|
+
// src/commands/image/index.ts
|
|
5419
|
+
import { Command as Command20 } from "commander";
|
|
5420
|
+
|
|
5421
|
+
// src/commands/image/gen.ts
|
|
5422
|
+
import { Command as Command16 } from "commander";
|
|
5423
|
+
|
|
5424
|
+
// src/services/image.service.ts
|
|
5425
|
+
var ImageService = class {
|
|
5426
|
+
/**
|
|
5427
|
+
* Generate image from prompt
|
|
5428
|
+
*/
|
|
5429
|
+
async generate(config, options) {
|
|
5430
|
+
const response = await fetch(`${config.apiUrl}/api/image/generate`, {
|
|
5431
|
+
method: "POST",
|
|
5432
|
+
headers: {
|
|
5433
|
+
"Content-Type": "application/json",
|
|
5434
|
+
"JAI1-Access-Key": config.accessKey
|
|
5435
|
+
},
|
|
5436
|
+
body: JSON.stringify(options)
|
|
5437
|
+
});
|
|
5438
|
+
if (!response.ok) {
|
|
5439
|
+
let errorMessage = `HTTP ${response.status}`;
|
|
5440
|
+
try {
|
|
5441
|
+
const error = await response.json();
|
|
5442
|
+
errorMessage = error.message || errorMessage;
|
|
5443
|
+
} catch (e) {
|
|
5444
|
+
}
|
|
5445
|
+
throw new NetworkError(errorMessage);
|
|
5446
|
+
}
|
|
5447
|
+
const data = await response.json();
|
|
5448
|
+
return data.data;
|
|
5449
|
+
}
|
|
5450
|
+
/**
|
|
5451
|
+
* List generated images
|
|
5452
|
+
*/
|
|
5453
|
+
async list(config, options) {
|
|
5454
|
+
const params = new URLSearchParams();
|
|
5455
|
+
if (options.model) params.set("model", options.model);
|
|
5456
|
+
if (options.limit) params.set("limit", options.limit.toString());
|
|
5457
|
+
if (options.offset) params.set("offset", options.offset.toString());
|
|
5458
|
+
const url = `${config.apiUrl}/api/image/list?${params}`;
|
|
5459
|
+
const response = await fetch(url, {
|
|
5460
|
+
headers: {
|
|
5461
|
+
"JAI1-Access-Key": config.accessKey
|
|
5462
|
+
}
|
|
5463
|
+
});
|
|
5464
|
+
if (!response.ok) {
|
|
5465
|
+
throw new NetworkError(`Failed to list images: HTTP ${response.status}`);
|
|
5466
|
+
}
|
|
5467
|
+
const data = await response.json();
|
|
5468
|
+
return data.data;
|
|
5469
|
+
}
|
|
5470
|
+
/**
|
|
5471
|
+
* Get image info
|
|
5472
|
+
*/
|
|
5473
|
+
async getInfo(config, id) {
|
|
5474
|
+
const response = await fetch(`${config.apiUrl}/api/image/${id}`, {
|
|
5475
|
+
headers: {
|
|
5476
|
+
"JAI1-Access-Key": config.accessKey
|
|
5477
|
+
}
|
|
5478
|
+
});
|
|
5479
|
+
if (!response.ok) {
|
|
5480
|
+
if (response.status === 404) {
|
|
5481
|
+
throw new Error("Image not found");
|
|
5482
|
+
}
|
|
5483
|
+
throw new NetworkError(`Failed to get image: HTTP ${response.status}`);
|
|
5484
|
+
}
|
|
5485
|
+
const data = await response.json();
|
|
5486
|
+
return data.data;
|
|
5487
|
+
}
|
|
5488
|
+
/**
|
|
5489
|
+
* Delete image
|
|
5490
|
+
*/
|
|
5491
|
+
async delete(config, id) {
|
|
5492
|
+
const response = await fetch(`${config.apiUrl}/api/image/${id}`, {
|
|
5493
|
+
method: "DELETE",
|
|
5494
|
+
headers: {
|
|
5495
|
+
"JAI1-Access-Key": config.accessKey
|
|
5496
|
+
}
|
|
5497
|
+
});
|
|
5498
|
+
if (!response.ok) {
|
|
5499
|
+
if (response.status === 404) {
|
|
5500
|
+
throw new Error("Image not found");
|
|
5501
|
+
}
|
|
5502
|
+
throw new NetworkError(`Failed to delete image: HTTP ${response.status}`);
|
|
5503
|
+
}
|
|
5504
|
+
}
|
|
5505
|
+
};
|
|
5506
|
+
|
|
5507
|
+
// src/commands/image/gen.ts
|
|
5508
|
+
import terminalImage from "terminal-image";
|
|
5509
|
+
function createImageGenCommand() {
|
|
5510
|
+
return new Command16("gen").description("Generate an image from text prompt").argument("<prompt>", "Image description prompt").option("-m, --model <model>", "Model to use", "gemini-3-flash-preview").option("-w, --width <number>", "Image width").option("-h, --height <number>", "Image height").option("-r, --ratio <ratio>", "Aspect ratio (1:1, 16:9, 9:16, 4:3, 3:4)").option("--negative <prompt>", "Negative prompt").option("--seed <number>", "Random seed").option("--no-display", "Don't display image in terminal").action(async (prompt, options) => {
|
|
5511
|
+
const configService = new ConfigService();
|
|
5512
|
+
const config = await configService.load();
|
|
5513
|
+
if (!config) {
|
|
5514
|
+
throw new ValidationError('Not initialized. Run "jai1 auth" first.');
|
|
5515
|
+
}
|
|
5516
|
+
const imageService = new ImageService();
|
|
5517
|
+
console.log("\u{1F3A8} Generating image...");
|
|
5518
|
+
console.log(` Prompt: ${prompt}`);
|
|
5519
|
+
console.log(` Model: ${options.model}`);
|
|
5520
|
+
try {
|
|
5521
|
+
const result = await imageService.generate(config, {
|
|
5522
|
+
prompt,
|
|
5523
|
+
model: options.model,
|
|
5524
|
+
...options.width && { width: parseInt(options.width) },
|
|
5525
|
+
...options.height && { height: parseInt(options.height) },
|
|
5526
|
+
...options.ratio && { aspectRatio: options.ratio },
|
|
5527
|
+
...options.negative && { negativePrompt: options.negative },
|
|
5528
|
+
...options.seed && { seed: parseInt(options.seed) }
|
|
5529
|
+
});
|
|
5530
|
+
console.log("\n\u2705 Image generated successfully!");
|
|
5531
|
+
console.log(` URL: ${result.url}`);
|
|
5532
|
+
console.log(` Size: ${(result.contentSize / 1024).toFixed(2)} KB`);
|
|
5533
|
+
console.log(` ID: ${result.id}`);
|
|
5534
|
+
if (options.display !== false) {
|
|
5535
|
+
try {
|
|
5536
|
+
const imageResponse = await fetch(result.url);
|
|
5537
|
+
const arrayBuffer = await imageResponse.arrayBuffer();
|
|
5538
|
+
const imageBuffer = Buffer.from(arrayBuffer);
|
|
5539
|
+
const rendered = await terminalImage.buffer(imageBuffer, {
|
|
5540
|
+
width: "50%",
|
|
5541
|
+
height: "50%"
|
|
5542
|
+
});
|
|
5543
|
+
console.log("\n" + rendered);
|
|
5544
|
+
} catch (displayError) {
|
|
5545
|
+
}
|
|
5546
|
+
}
|
|
5547
|
+
console.log('\n\u{1F4A1} Tip: Use "jai1 image list" to view all your images');
|
|
5548
|
+
console.log(' Use "jai1 image info <id>" for details');
|
|
5549
|
+
} catch (error) {
|
|
5550
|
+
if (error instanceof Error) {
|
|
5551
|
+
if (error.message.includes("Rate limit")) {
|
|
5552
|
+
console.error("\n\u26A0\uFE0F Rate limit exceeded");
|
|
5553
|
+
console.error(' Use "jai1 image limits" to check your quota');
|
|
5554
|
+
} else {
|
|
5555
|
+
throw error;
|
|
5556
|
+
}
|
|
5557
|
+
}
|
|
5558
|
+
throw error;
|
|
5559
|
+
}
|
|
5560
|
+
});
|
|
5561
|
+
}
|
|
5562
|
+
|
|
5563
|
+
// src/commands/image/list.ts
|
|
5564
|
+
import { Command as Command17 } from "commander";
|
|
5565
|
+
function createImageListCommand() {
|
|
5566
|
+
return new Command17("list").description("List generated images").option("-m, --model <model>", "Filter by model").option("-l, --limit <number>", "Number of results", "20").option("-o, --offset <number>", "Offset for pagination", "0").action(async (options) => {
|
|
5567
|
+
const configService = new ConfigService();
|
|
5568
|
+
const config = await configService.load();
|
|
5569
|
+
if (!config) {
|
|
5570
|
+
throw new ValidationError('Not initialized. Run "jai1 auth" first.');
|
|
5571
|
+
}
|
|
5572
|
+
const imageService = new ImageService();
|
|
5573
|
+
const result = await imageService.list(config, {
|
|
5574
|
+
model: options.model,
|
|
5575
|
+
limit: parseInt(options.limit),
|
|
5576
|
+
offset: parseInt(options.offset)
|
|
5577
|
+
});
|
|
5578
|
+
if (result.images.length === 0) {
|
|
5579
|
+
console.log("No images found.");
|
|
5580
|
+
return;
|
|
5581
|
+
}
|
|
5582
|
+
console.log(`
|
|
5583
|
+
\u{1F4F8} Your Generated Images (${result.total} total):
|
|
5584
|
+
`);
|
|
5585
|
+
for (const img of result.images) {
|
|
5586
|
+
const date = new Date(img.createdAt).toLocaleString();
|
|
5587
|
+
const promptPreview = img.prompt.length > 50 ? img.prompt.slice(0, 50) + "..." : img.prompt;
|
|
5588
|
+
console.log(`ID: ${img.id.toString().padEnd(6)} | ${date}`);
|
|
5589
|
+
console.log(` Model: ${img.model}`);
|
|
5590
|
+
console.log(` Prompt: ${promptPreview}`);
|
|
5591
|
+
console.log(` URL: ${img.url}`);
|
|
5592
|
+
console.log();
|
|
5593
|
+
}
|
|
5594
|
+
if (result.total > result.offset + result.limit) {
|
|
5595
|
+
const nextOffset = result.offset + result.limit;
|
|
5596
|
+
console.log(`\u{1F4A1} Show more: jai1 image list -o ${nextOffset}`);
|
|
5597
|
+
}
|
|
5598
|
+
});
|
|
5599
|
+
}
|
|
5600
|
+
|
|
5601
|
+
// src/commands/image/info.ts
|
|
5602
|
+
import { Command as Command18 } from "commander";
|
|
5603
|
+
function createImageInfoCommand() {
|
|
5604
|
+
return new Command18("info").description("Get detailed info about an image").argument("<id>", "Image ID").action(async (id) => {
|
|
5605
|
+
const configService = new ConfigService();
|
|
5606
|
+
const config = await configService.load();
|
|
5607
|
+
if (!config) {
|
|
5608
|
+
throw new ValidationError('Not initialized. Run "jai1 auth" first.');
|
|
5609
|
+
}
|
|
5610
|
+
const imageService = new ImageService();
|
|
5611
|
+
const image = await imageService.getInfo(config, parseInt(id));
|
|
5612
|
+
console.log("\n\u{1F4F8} Image Details:\n");
|
|
5613
|
+
console.log(`ID: ${image.id}`);
|
|
5614
|
+
console.log(`Model: ${image.model}`);
|
|
5615
|
+
console.log(`Prompt: ${image.prompt}`);
|
|
5616
|
+
console.log(`URL: ${image.url}`);
|
|
5617
|
+
console.log(`Size: ${(image.contentSize / 1024).toFixed(2)} KB`);
|
|
5618
|
+
if (image.width && image.height) {
|
|
5619
|
+
console.log(`Dimensions: ${image.width}x${image.height}`);
|
|
5620
|
+
}
|
|
5621
|
+
console.log(`Created: ${new Date(image.createdAt).toLocaleString()}`);
|
|
5622
|
+
if (image.metadata) {
|
|
5623
|
+
const meta = typeof image.metadata === "string" ? JSON.parse(image.metadata) : image.metadata;
|
|
5624
|
+
if (meta.aspectRatio) {
|
|
5625
|
+
console.log(`Ratio: ${meta.aspectRatio}`);
|
|
5626
|
+
}
|
|
5627
|
+
if (meta.negativePrompt) {
|
|
5628
|
+
console.log(`Negative: ${meta.negativePrompt}`);
|
|
5629
|
+
}
|
|
5630
|
+
if (meta.seed) {
|
|
5631
|
+
console.log(`Seed: ${meta.seed}`);
|
|
5632
|
+
}
|
|
5633
|
+
}
|
|
5634
|
+
});
|
|
5635
|
+
}
|
|
5636
|
+
|
|
5637
|
+
// src/commands/image/delete.ts
|
|
5638
|
+
import { Command as Command19 } from "commander";
|
|
5639
|
+
import { confirm as confirm4 } from "@inquirer/prompts";
|
|
5640
|
+
function createImageDeleteCommand() {
|
|
5641
|
+
return new Command19("delete").description("Delete a generated image").argument("<id>", "Image ID").option("-y, --yes", "Skip confirmation").action(async (id, options) => {
|
|
5642
|
+
const configService = new ConfigService();
|
|
5643
|
+
const config = await configService.load();
|
|
5644
|
+
if (!config) {
|
|
5645
|
+
throw new ValidationError('Not initialized. Run "jai1 auth" first.');
|
|
5646
|
+
}
|
|
5647
|
+
if (!options.yes) {
|
|
5648
|
+
const confirmed = await confirm4({
|
|
5649
|
+
message: `Are you sure you want to delete image #${id}?`,
|
|
5650
|
+
default: false
|
|
5651
|
+
});
|
|
5652
|
+
if (!confirmed) {
|
|
5653
|
+
console.log("Cancelled.");
|
|
5654
|
+
return;
|
|
5655
|
+
}
|
|
5656
|
+
}
|
|
5657
|
+
const imageService = new ImageService();
|
|
5658
|
+
await imageService.delete(config, parseInt(id));
|
|
5659
|
+
console.log(`\u2705 Image #${id} deleted successfully.`);
|
|
5660
|
+
});
|
|
5661
|
+
}
|
|
5662
|
+
|
|
5663
|
+
// src/commands/image/index.ts
|
|
5664
|
+
function createImageCommand() {
|
|
5665
|
+
const cmd = new Command20("image").description("Image generation commands");
|
|
5666
|
+
cmd.addCommand(createImageGenCommand());
|
|
5667
|
+
cmd.addCommand(createImageListCommand());
|
|
5668
|
+
cmd.addCommand(createImageInfoCommand());
|
|
5669
|
+
cmd.addCommand(createImageDeleteCommand());
|
|
5670
|
+
return cmd;
|
|
5671
|
+
}
|
|
5672
|
+
|
|
5363
5673
|
// src/commands/utils/index.ts
|
|
5364
|
-
import { Command as
|
|
5674
|
+
import { Command as Command34 } from "commander";
|
|
5365
5675
|
|
|
5366
5676
|
// src/commands/utils/password.ts
|
|
5367
|
-
import { Command as
|
|
5677
|
+
import { Command as Command21 } from "commander";
|
|
5368
5678
|
|
|
5369
5679
|
// src/services/utils.service.ts
|
|
5370
5680
|
import crypto from "crypto";
|
|
@@ -5633,7 +5943,7 @@ async function handlePasswordGeneration(options) {
|
|
|
5633
5943
|
}
|
|
5634
5944
|
}
|
|
5635
5945
|
function createPasswordCommand() {
|
|
5636
|
-
const cmd = new
|
|
5946
|
+
const cmd = new Command21("password").description("Generate secure random password").option("-l, --length <number>", "Password length", "16").option("--no-lowercase", "Exclude lowercase letters").option("--no-uppercase", "Exclude uppercase letters").option("--no-digits", "Exclude digits").option("--no-symbols", "Exclude symbols").option("--symbol-chars <chars>", "Custom symbol characters").option("-c, --count <number>", "Number of passwords to generate", "1").addHelpText("after", `
|
|
5637
5947
|
Examples:
|
|
5638
5948
|
$ jai1 utils password
|
|
5639
5949
|
$ jai1 utils password --length 24
|
|
@@ -5651,7 +5961,7 @@ Examples:
|
|
|
5651
5961
|
}
|
|
5652
5962
|
|
|
5653
5963
|
// src/commands/utils/uuid.ts
|
|
5654
|
-
import { Command as
|
|
5964
|
+
import { Command as Command22 } from "commander";
|
|
5655
5965
|
async function handleUuidGeneration(options) {
|
|
5656
5966
|
const service = new UtilsService();
|
|
5657
5967
|
try {
|
|
@@ -5679,7 +5989,7 @@ async function handleUuidGeneration(options) {
|
|
|
5679
5989
|
}
|
|
5680
5990
|
}
|
|
5681
5991
|
function createUuidCommand() {
|
|
5682
|
-
const cmd = new
|
|
5992
|
+
const cmd = new Command22("uuid").description("Generate UUID v4 identifier").option("-c, --count <number>", "Number of UUIDs to generate", "1").option("--uppercase", "Output in uppercase").option("--no-hyphens", "Remove hyphens from output").addHelpText("after", `
|
|
5683
5993
|
Examples:
|
|
5684
5994
|
$ jai1 utils uuid
|
|
5685
5995
|
$ jai1 utils uuid --count 10
|
|
@@ -5696,7 +6006,7 @@ Examples:
|
|
|
5696
6006
|
}
|
|
5697
6007
|
|
|
5698
6008
|
// src/commands/utils/hash.ts
|
|
5699
|
-
import { Command as
|
|
6009
|
+
import { Command as Command23 } from "commander";
|
|
5700
6010
|
async function handleHashGeneration(input4, options) {
|
|
5701
6011
|
const service = new UtilsService();
|
|
5702
6012
|
try {
|
|
@@ -5736,7 +6046,7 @@ async function handleHashGeneration(input4, options) {
|
|
|
5736
6046
|
}
|
|
5737
6047
|
}
|
|
5738
6048
|
function createHashCommand() {
|
|
5739
|
-
const cmd = new
|
|
6049
|
+
const cmd = new Command23("hash").description("Generate hash (MD5, SHA, bcrypt)").argument("[input]", "Text to hash").option(
|
|
5740
6050
|
"-a, --algorithm <algorithm>",
|
|
5741
6051
|
"Hash algorithm (md5, sha1, sha256, sha512, bcrypt)",
|
|
5742
6052
|
"sha256"
|
|
@@ -5758,7 +6068,7 @@ Examples:
|
|
|
5758
6068
|
}
|
|
5759
6069
|
|
|
5760
6070
|
// src/commands/utils/base64-encode.ts
|
|
5761
|
-
import { Command as
|
|
6071
|
+
import { Command as Command24 } from "commander";
|
|
5762
6072
|
import { readFile as readFile2 } from "fs/promises";
|
|
5763
6073
|
async function handleBase64Encode(input4, options) {
|
|
5764
6074
|
const service = new UtilsService();
|
|
@@ -5791,7 +6101,7 @@ async function handleBase64Encode(input4, options) {
|
|
|
5791
6101
|
}
|
|
5792
6102
|
}
|
|
5793
6103
|
function createBase64EncodeCommand() {
|
|
5794
|
-
const cmd = new
|
|
6104
|
+
const cmd = new Command24("base64-encode").description("Encode text or file to Base64").argument("[input]", "Text to encode").option("-f, --file <path>", "Encode file contents").option("--url-safe", "Use URL-safe Base64 encoding").addHelpText("after", `
|
|
5795
6105
|
Examples:
|
|
5796
6106
|
$ jai1 utils base64-encode "hello world"
|
|
5797
6107
|
$ jai1 utils base64-encode "hello world" --url-safe
|
|
@@ -5804,7 +6114,7 @@ Examples:
|
|
|
5804
6114
|
}
|
|
5805
6115
|
|
|
5806
6116
|
// src/commands/utils/base64-decode.ts
|
|
5807
|
-
import { Command as
|
|
6117
|
+
import { Command as Command25 } from "commander";
|
|
5808
6118
|
import { readFile as readFile3, writeFile } from "fs/promises";
|
|
5809
6119
|
async function handleBase64Decode(input4, options) {
|
|
5810
6120
|
const service = new UtilsService();
|
|
@@ -5836,7 +6146,7 @@ async function handleBase64Decode(input4, options) {
|
|
|
5836
6146
|
}
|
|
5837
6147
|
}
|
|
5838
6148
|
function createBase64DecodeCommand() {
|
|
5839
|
-
const cmd = new
|
|
6149
|
+
const cmd = new Command25("base64-decode").description("Decode Base64 string").argument("[input]", "Base64 string to decode").option("-f, --file <path>", "Decode from file").option("-o, --output <path>", "Write decoded output to file").addHelpText("after", `
|
|
5840
6150
|
Examples:
|
|
5841
6151
|
$ jai1 utils base64-decode "aGVsbG8gd29ybGQ="
|
|
5842
6152
|
$ jai1 utils base64-decode --file ./encoded.txt
|
|
@@ -5849,7 +6159,7 @@ Examples:
|
|
|
5849
6159
|
}
|
|
5850
6160
|
|
|
5851
6161
|
// src/commands/utils/http.ts
|
|
5852
|
-
import { Command as
|
|
6162
|
+
import { Command as Command26 } from "commander";
|
|
5853
6163
|
import { readFile as readFile4 } from "fs/promises";
|
|
5854
6164
|
async function handleHttpRequest(url, options) {
|
|
5855
6165
|
const service = new UtilsService();
|
|
@@ -5915,7 +6225,7 @@ async function handleHttpRequest(url, options) {
|
|
|
5915
6225
|
}
|
|
5916
6226
|
}
|
|
5917
6227
|
function createHttpCommand() {
|
|
5918
|
-
const cmd = new
|
|
6228
|
+
const cmd = new Command26("http").description("Make HTTP request with formatted output").argument("<url>", "Target URL").option("-X, --method <method>", "HTTP method", "GET").option("-H, --header <header...>", "Request headers (repeatable)").option("-d, --data <data>", "Request body (JSON string)").option("--file <path>", "Read body from file").option("--timeout <ms>", "Request timeout in milliseconds", "30000").option("--no-follow", "Do not follow redirects").option("--only-headers", "Show only response headers").option("--only-body", "Show only response body").addHelpText("after", `
|
|
5919
6229
|
Examples:
|
|
5920
6230
|
$ jai1 utils http https://api.example.com/users
|
|
5921
6231
|
$ jai1 utils http https://api.example.com/users -X POST -d '{"name":"John"}'
|
|
@@ -5933,7 +6243,7 @@ Examples:
|
|
|
5933
6243
|
}
|
|
5934
6244
|
|
|
5935
6245
|
// src/commands/utils/jwt.ts
|
|
5936
|
-
import { Command as
|
|
6246
|
+
import { Command as Command27 } from "commander";
|
|
5937
6247
|
async function handleJwtDecode(token) {
|
|
5938
6248
|
const service = new UtilsService();
|
|
5939
6249
|
try {
|
|
@@ -5972,7 +6282,7 @@ async function handleJwtEncode(options) {
|
|
|
5972
6282
|
}
|
|
5973
6283
|
}
|
|
5974
6284
|
function createJwtCommand() {
|
|
5975
|
-
const jwtCommand = new
|
|
6285
|
+
const jwtCommand = new Command27("jwt").description("Decode and encode JWT tokens");
|
|
5976
6286
|
jwtCommand.command("decode").description("Decode JWT token").argument("<token>", "JWT token to decode").addHelpText("after", `
|
|
5977
6287
|
Examples:
|
|
5978
6288
|
$ jai1 utils jwt decode "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"
|
|
@@ -5993,7 +6303,7 @@ Examples:
|
|
|
5993
6303
|
}
|
|
5994
6304
|
|
|
5995
6305
|
// src/commands/utils/unix-time.ts
|
|
5996
|
-
import { Command as
|
|
6306
|
+
import { Command as Command28 } from "commander";
|
|
5997
6307
|
async function handleUnixTime(input4, options) {
|
|
5998
6308
|
const service = new UtilsService();
|
|
5999
6309
|
try {
|
|
@@ -6041,7 +6351,7 @@ async function handleUnixTime(input4, options) {
|
|
|
6041
6351
|
}
|
|
6042
6352
|
}
|
|
6043
6353
|
function createUnixTimeCommand() {
|
|
6044
|
-
const cmd = new
|
|
6354
|
+
const cmd = new Command28("unix-time").description("Convert unix timestamps to/from dates").argument("[input]", "Unix timestamp or date string").option("-f, --format <format>", "Output format (iso, local, utc)", "iso").option("--ms", "Use milliseconds instead of seconds").addHelpText("after", `
|
|
6045
6355
|
Examples:
|
|
6046
6356
|
$ jai1 utils unix-time
|
|
6047
6357
|
$ jai1 utils unix-time 1702550400
|
|
@@ -6056,7 +6366,7 @@ Examples:
|
|
|
6056
6366
|
}
|
|
6057
6367
|
|
|
6058
6368
|
// src/commands/utils/timezone.ts
|
|
6059
|
-
import { Command as
|
|
6369
|
+
import { Command as Command29 } from "commander";
|
|
6060
6370
|
async function handleTimezoneConversion(time, options) {
|
|
6061
6371
|
const service = new UtilsService();
|
|
6062
6372
|
try {
|
|
@@ -6093,7 +6403,7 @@ async function handleTimezoneConversion(time, options) {
|
|
|
6093
6403
|
}
|
|
6094
6404
|
}
|
|
6095
6405
|
function createTimezoneCommand() {
|
|
6096
|
-
const cmd = new
|
|
6406
|
+
const cmd = new Command29("timezone").description("Convert time between timezones").argument("[time]", 'Time to convert (e.g., "2024-01-15 10:00")').option("--from <timezone>", "Source timezone").option("--to <timezone>", "Target timezone").option("--list", "Show available timezones").addHelpText("after", `
|
|
6097
6407
|
Examples:
|
|
6098
6408
|
$ jai1 utils timezone --list
|
|
6099
6409
|
$ jai1 utils timezone "2024-01-15 10:00" --from "America/New_York" --to "Asia/Tokyo"
|
|
@@ -6106,7 +6416,7 @@ Examples:
|
|
|
6106
6416
|
}
|
|
6107
6417
|
|
|
6108
6418
|
// src/commands/utils/url-encode.ts
|
|
6109
|
-
import { Command as
|
|
6419
|
+
import { Command as Command30 } from "commander";
|
|
6110
6420
|
async function handleUrlEncode(input4, options) {
|
|
6111
6421
|
const service = new UtilsService();
|
|
6112
6422
|
try {
|
|
@@ -6127,7 +6437,7 @@ async function handleUrlEncode(input4, options) {
|
|
|
6127
6437
|
}
|
|
6128
6438
|
}
|
|
6129
6439
|
function createUrlEncodeCommand() {
|
|
6130
|
-
const cmd = new
|
|
6440
|
+
const cmd = new Command30("url-encode").description("Encode URL component or full URL").argument("<input>", "Text to encode").option("--full", "Encode full URL (use encodeURI instead of encodeURIComponent)").addHelpText("after", `
|
|
6131
6441
|
Examples:
|
|
6132
6442
|
$ jai1 utils url-encode "hello world"
|
|
6133
6443
|
$ jai1 utils url-encode "hello world & test"
|
|
@@ -6140,7 +6450,7 @@ Examples:
|
|
|
6140
6450
|
}
|
|
6141
6451
|
|
|
6142
6452
|
// src/commands/utils/url-decode.ts
|
|
6143
|
-
import { Command as
|
|
6453
|
+
import { Command as Command31 } from "commander";
|
|
6144
6454
|
async function handleUrlDecode(input4, options) {
|
|
6145
6455
|
const service = new UtilsService();
|
|
6146
6456
|
try {
|
|
@@ -6161,7 +6471,7 @@ async function handleUrlDecode(input4, options) {
|
|
|
6161
6471
|
}
|
|
6162
6472
|
}
|
|
6163
6473
|
function createUrlDecodeCommand() {
|
|
6164
|
-
const cmd = new
|
|
6474
|
+
const cmd = new Command31("url-decode").description("Decode URL-encoded string").argument("<input>", "Text to decode").option("--full", "Decode full URL (use decodeURI instead of decodeURIComponent)").addHelpText("after", `
|
|
6165
6475
|
Examples:
|
|
6166
6476
|
$ jai1 utils url-decode "hello%20world"
|
|
6167
6477
|
$ jai1 utils url-decode "hello%20world%20%26%20test"
|
|
@@ -6174,7 +6484,7 @@ Examples:
|
|
|
6174
6484
|
}
|
|
6175
6485
|
|
|
6176
6486
|
// src/commands/utils/cron.ts
|
|
6177
|
-
import { Command as
|
|
6487
|
+
import { Command as Command32 } from "commander";
|
|
6178
6488
|
import cronstrue from "cronstrue";
|
|
6179
6489
|
async function handleCronParse(expression) {
|
|
6180
6490
|
try {
|
|
@@ -6217,7 +6527,7 @@ async function handleCronParse(expression) {
|
|
|
6217
6527
|
}
|
|
6218
6528
|
}
|
|
6219
6529
|
function createCronCommand() {
|
|
6220
|
-
const cmd = new
|
|
6530
|
+
const cmd = new Command32("cron").description("Parse and explain cron expression").argument("<expression>", 'Cron expression (e.g., "0 5 * * *")').addHelpText("after", `
|
|
6221
6531
|
Examples:
|
|
6222
6532
|
$ jai1 utils cron "0 5 * * *"
|
|
6223
6533
|
$ jai1 utils cron "*/15 * * * *"
|
|
@@ -6231,7 +6541,7 @@ Examples:
|
|
|
6231
6541
|
}
|
|
6232
6542
|
|
|
6233
6543
|
// src/commands/utils/markdown-preview.ts
|
|
6234
|
-
import { Command as
|
|
6544
|
+
import { Command as Command33 } from "commander";
|
|
6235
6545
|
import { readFile as readFile5 } from "fs/promises";
|
|
6236
6546
|
import { marked } from "marked";
|
|
6237
6547
|
import TerminalRenderer from "marked-terminal";
|
|
@@ -6270,7 +6580,7 @@ ${code.trim()}
|
|
|
6270
6580
|
}
|
|
6271
6581
|
}
|
|
6272
6582
|
function createMarkdownPreviewCommand() {
|
|
6273
|
-
const cmd = new
|
|
6583
|
+
const cmd = new Command33("markdown-preview").description("Preview markdown file in terminal").argument("<file>", "Markdown file path").option("--raw", "Show raw markdown instead of rendered").addHelpText("after", `
|
|
6274
6584
|
Examples:
|
|
6275
6585
|
$ jai1 utils markdown-preview README.md
|
|
6276
6586
|
$ jai1 utils markdown-preview ./docs/guide.md
|
|
@@ -7679,7 +7989,7 @@ async function runInteractiveMode() {
|
|
|
7679
7989
|
|
|
7680
7990
|
// src/commands/utils/index.ts
|
|
7681
7991
|
function createUtilsCommand() {
|
|
7682
|
-
const utilsCommand = new
|
|
7992
|
+
const utilsCommand = new Command34("utils").description("Developer utilities for common tasks").option("-i, --interactive", "Run in interactive mode").addHelpText("after", `
|
|
7683
7993
|
Interactive Mode:
|
|
7684
7994
|
$ jai1 utils --interactive
|
|
7685
7995
|
$ jai1 utils -i
|
|
@@ -7714,11 +8024,11 @@ Quick Usage:
|
|
|
7714
8024
|
}
|
|
7715
8025
|
|
|
7716
8026
|
// src/commands/deps/index.ts
|
|
7717
|
-
import { Command as
|
|
8027
|
+
import { Command as Command36 } from "commander";
|
|
7718
8028
|
|
|
7719
8029
|
// src/commands/deps/upgrade.ts
|
|
7720
|
-
import { Command as
|
|
7721
|
-
import { checkbox as checkbox3, confirm as
|
|
8030
|
+
import { Command as Command35 } from "commander";
|
|
8031
|
+
import { checkbox as checkbox3, confirm as confirm5 } from "@inquirer/prompts";
|
|
7722
8032
|
|
|
7723
8033
|
// src/services/deps.service.ts
|
|
7724
8034
|
import { promises as fs10 } from "fs";
|
|
@@ -7931,7 +8241,7 @@ var colors2 = {
|
|
|
7931
8241
|
dim: "\x1B[2m"
|
|
7932
8242
|
};
|
|
7933
8243
|
function createDepsUpgradeCommand() {
|
|
7934
|
-
return new
|
|
8244
|
+
return new Command35("upgrade").description("Upgrade npm packages l\xEAn version m\u1EDBi nh\u1EA5t").option("--check", "Ch\u1EC9 ki\u1EC3m tra, kh\xF4ng upgrade").option("--all", "Upgrade t\u1EA5t c\u1EA3 kh\xF4ng c\u1EA7n ch\u1ECDn").option("--deps-only", "Ch\u1EC9 upgrade dependencies").option("--dev-only", "Ch\u1EC9 upgrade devDependencies").action(async (options) => {
|
|
7935
8245
|
await handleDepsUpgrade(options);
|
|
7936
8246
|
});
|
|
7937
8247
|
}
|
|
@@ -8023,7 +8333,7 @@ ${colors2.yellow}\u23F8\uFE0F \u0110\xE3 h\u1EE7y${colors2.reset}
|
|
|
8023
8333
|
}
|
|
8024
8334
|
let shouldProceed;
|
|
8025
8335
|
try {
|
|
8026
|
-
shouldProceed = await
|
|
8336
|
+
shouldProceed = await confirm5({
|
|
8027
8337
|
message: `Ti\u1EBFn h\xE0nh upgrade ${selectedPackages.length} packages?`,
|
|
8028
8338
|
default: true
|
|
8029
8339
|
});
|
|
@@ -8111,16 +8421,16 @@ function displayUpgradeTable(packages) {
|
|
|
8111
8421
|
|
|
8112
8422
|
// src/commands/deps/index.ts
|
|
8113
8423
|
function createDepsCommand() {
|
|
8114
|
-
const depsCommand = new
|
|
8424
|
+
const depsCommand = new Command36("deps").description("Qu\u1EA3n l\xFD dependencies trong project");
|
|
8115
8425
|
depsCommand.addCommand(createDepsUpgradeCommand());
|
|
8116
8426
|
return depsCommand;
|
|
8117
8427
|
}
|
|
8118
8428
|
|
|
8119
8429
|
// src/commands/kit/index.ts
|
|
8120
|
-
import { Command as
|
|
8430
|
+
import { Command as Command40 } from "commander";
|
|
8121
8431
|
|
|
8122
8432
|
// src/commands/kit/list.ts
|
|
8123
|
-
import { Command as
|
|
8433
|
+
import { Command as Command37 } from "commander";
|
|
8124
8434
|
|
|
8125
8435
|
// src/services/starter-kit.service.ts
|
|
8126
8436
|
import { promises as fs11 } from "fs";
|
|
@@ -8187,7 +8497,7 @@ var StarterKitService = class {
|
|
|
8187
8497
|
|
|
8188
8498
|
// src/commands/kit/list.ts
|
|
8189
8499
|
function createKitListCommand() {
|
|
8190
|
-
return new
|
|
8500
|
+
return new Command37("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) => {
|
|
8191
8501
|
const configService = new ConfigService();
|
|
8192
8502
|
const config = await configService.load();
|
|
8193
8503
|
if (!config) {
|
|
@@ -8224,9 +8534,9 @@ function createKitListCommand() {
|
|
|
8224
8534
|
}
|
|
8225
8535
|
|
|
8226
8536
|
// src/commands/kit/info.ts
|
|
8227
|
-
import { Command as
|
|
8537
|
+
import { Command as Command38 } from "commander";
|
|
8228
8538
|
function createKitInfoCommand() {
|
|
8229
|
-
return new
|
|
8539
|
+
return new Command38("info").description("Show detailed information about a starter kit").argument("<slug>", "Starter kit slug").action(async (slug) => {
|
|
8230
8540
|
const configService = new ConfigService();
|
|
8231
8541
|
const config = await configService.load();
|
|
8232
8542
|
if (!config) {
|
|
@@ -8275,7 +8585,7 @@ Post-Init Commands:`);
|
|
|
8275
8585
|
}
|
|
8276
8586
|
|
|
8277
8587
|
// src/commands/kit/create.ts
|
|
8278
|
-
import { Command as
|
|
8588
|
+
import { Command as Command39 } from "commander";
|
|
8279
8589
|
import { promises as fs12 } from "fs";
|
|
8280
8590
|
import { join as join6 } from "path";
|
|
8281
8591
|
import { select as select2, input, checkbox as checkbox4 } from "@inquirer/prompts";
|
|
@@ -8320,7 +8630,7 @@ var HookExecutor = class {
|
|
|
8320
8630
|
|
|
8321
8631
|
// src/commands/kit/create.ts
|
|
8322
8632
|
function createKitCreateCommand() {
|
|
8323
|
-
return new
|
|
8633
|
+
return new Command39("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) => {
|
|
8324
8634
|
const configService = new ConfigService();
|
|
8325
8635
|
const config = await configService.load();
|
|
8326
8636
|
if (!config) {
|
|
@@ -8492,7 +8802,7 @@ async function getAllFiles(dir) {
|
|
|
8492
8802
|
|
|
8493
8803
|
// src/commands/kit/index.ts
|
|
8494
8804
|
function createKitCommand() {
|
|
8495
|
-
const cmd = new
|
|
8805
|
+
const cmd = new Command40("kit").description("Manage starter kits for new projects").action(() => {
|
|
8496
8806
|
cmd.help();
|
|
8497
8807
|
});
|
|
8498
8808
|
cmd.addCommand(createKitListCommand());
|
|
@@ -8502,12 +8812,12 @@ function createKitCommand() {
|
|
|
8502
8812
|
}
|
|
8503
8813
|
|
|
8504
8814
|
// src/commands/rules/index.ts
|
|
8505
|
-
import { Command as
|
|
8815
|
+
import { Command as Command47 } from "commander";
|
|
8506
8816
|
|
|
8507
8817
|
// src/commands/rules/list.ts
|
|
8508
|
-
import { Command as
|
|
8818
|
+
import { Command as Command41 } from "commander";
|
|
8509
8819
|
function createRulesListCommand() {
|
|
8510
|
-
return new
|
|
8820
|
+
return new Command41("list").description("List available rule presets").option("--json", "Output as JSON").action(async (options) => {
|
|
8511
8821
|
const configService = new ConfigService();
|
|
8512
8822
|
const config = await configService.load();
|
|
8513
8823
|
if (!config) {
|
|
@@ -8562,12 +8872,12 @@ function createRulesListCommand() {
|
|
|
8562
8872
|
}
|
|
8563
8873
|
|
|
8564
8874
|
// src/commands/rules/init.ts
|
|
8565
|
-
import { Command as
|
|
8875
|
+
import { Command as Command42 } from "commander";
|
|
8566
8876
|
import { promises as fs13 } from "fs";
|
|
8567
8877
|
import { join as join7 } from "path";
|
|
8568
|
-
import { select as select3, confirm as
|
|
8878
|
+
import { select as select3, confirm as confirm6 } from "@inquirer/prompts";
|
|
8569
8879
|
function createRulesInitCommand() {
|
|
8570
|
-
return new
|
|
8880
|
+
return new Command42("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) => {
|
|
8571
8881
|
const configService = new ConfigService();
|
|
8572
8882
|
const config = await configService.load();
|
|
8573
8883
|
if (!config) {
|
|
@@ -8627,7 +8937,7 @@ function createRulesInitCommand() {
|
|
|
8627
8937
|
});
|
|
8628
8938
|
}
|
|
8629
8939
|
if (!options.yes) {
|
|
8630
|
-
const proceed = await
|
|
8940
|
+
const proceed = await confirm6({
|
|
8631
8941
|
message: `Apply preset '${bundle.preset.name}' to current directory?`,
|
|
8632
8942
|
default: true
|
|
8633
8943
|
});
|
|
@@ -8695,10 +9005,10 @@ async function applyAgentsMdFormat(bundle) {
|
|
|
8695
9005
|
}
|
|
8696
9006
|
|
|
8697
9007
|
// src/commands/rules/apply.ts
|
|
8698
|
-
import { Command as
|
|
9008
|
+
import { Command as Command43 } from "commander";
|
|
8699
9009
|
import { promises as fs15 } from "fs";
|
|
8700
9010
|
import { join as join9 } from "path";
|
|
8701
|
-
import { select as select4, confirm as
|
|
9011
|
+
import { select as select4, confirm as confirm7, checkbox as checkbox5 } from "@inquirer/prompts";
|
|
8702
9012
|
|
|
8703
9013
|
// src/services/rules-generator.service.ts
|
|
8704
9014
|
var RulesGeneratorService = class {
|
|
@@ -9278,7 +9588,7 @@ Restoring backup from ${metadata.timestamp}...`);
|
|
|
9278
9588
|
|
|
9279
9589
|
// src/commands/rules/apply.ts
|
|
9280
9590
|
function createRulesApplyCommand() {
|
|
9281
|
-
return new
|
|
9591
|
+
return new Command43("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)").option("--skip-backup", "Skip backup creation").option("-y, --yes", "Skip all confirmations (auto mode)").action(async (presetSlug, options) => {
|
|
9282
9592
|
const configService = new ConfigService();
|
|
9283
9593
|
const config = await configService.load();
|
|
9284
9594
|
if (!config) {
|
|
@@ -9418,7 +9728,7 @@ function createRulesApplyCommand() {
|
|
|
9418
9728
|
if (backupPath) {
|
|
9419
9729
|
console.log(` Backup: ${backupPath}`);
|
|
9420
9730
|
}
|
|
9421
|
-
const proceed = await
|
|
9731
|
+
const proceed = await confirm7({
|
|
9422
9732
|
message: "Apply these rules to the current directory?",
|
|
9423
9733
|
default: true
|
|
9424
9734
|
});
|
|
@@ -9428,19 +9738,23 @@ function createRulesApplyCommand() {
|
|
|
9428
9738
|
}
|
|
9429
9739
|
}
|
|
9430
9740
|
console.log("\n\u{1F4DD} Applying preset...\n");
|
|
9431
|
-
const
|
|
9432
|
-
|
|
9741
|
+
const rulePresetDir = join9(process.cwd(), ".jai1", "rule-preset");
|
|
9742
|
+
try {
|
|
9743
|
+
await fs15.rm(rulePresetDir, { recursive: true, force: true });
|
|
9744
|
+
} catch {
|
|
9745
|
+
}
|
|
9746
|
+
await fs15.mkdir(rulePresetDir, { recursive: true });
|
|
9433
9747
|
await fs15.writeFile(
|
|
9434
|
-
join9(
|
|
9748
|
+
join9(rulePresetDir, "preset.json"),
|
|
9435
9749
|
JSON.stringify(bundle.preset, null, 2),
|
|
9436
9750
|
"utf-8"
|
|
9437
9751
|
);
|
|
9438
9752
|
for (const [filename, content] of Object.entries(bundle.files)) {
|
|
9439
|
-
const filePath = join9(
|
|
9753
|
+
const filePath = join9(rulePresetDir, filename);
|
|
9440
9754
|
await fs15.mkdir(join9(filePath, ".."), { recursive: true });
|
|
9441
9755
|
await fs15.writeFile(filePath, content, "utf-8");
|
|
9442
9756
|
}
|
|
9443
|
-
console.log(`\u2713 Saved preset to .jai1/rule-
|
|
9757
|
+
console.log(`\u2713 Saved preset to .jai1/rule-preset/`);
|
|
9444
9758
|
const allGeneratedFiles = [];
|
|
9445
9759
|
for (const ideId of resolvedIdes) {
|
|
9446
9760
|
try {
|
|
@@ -9511,19 +9825,19 @@ function createRulesApplyCommand() {
|
|
|
9511
9825
|
}
|
|
9512
9826
|
console.log("\n\u{1F4DD} Next steps:");
|
|
9513
9827
|
console.log(" 1. Review generated files in your IDE");
|
|
9514
|
-
console.log(" 2. Edit
|
|
9515
|
-
console.log(
|
|
9516
|
-
console.log(
|
|
9828
|
+
console.log(" 2. Edit rules in .jai1/rule-preset/ (source of truth)");
|
|
9829
|
+
console.log(' 3. Run "jai1 rules sync" to regenerate IDE outputs');
|
|
9830
|
+
console.log(" 4. Commit the rules to git");
|
|
9517
9831
|
console.log(' 5. Use "jai1 ide status" to check IDE configuration\n');
|
|
9518
9832
|
});
|
|
9519
9833
|
}
|
|
9520
9834
|
|
|
9521
9835
|
// src/commands/rules/restore.ts
|
|
9522
|
-
import { Command as
|
|
9836
|
+
import { Command as Command44 } from "commander";
|
|
9523
9837
|
import { join as join10 } from "path";
|
|
9524
|
-
import { select as select5, confirm as
|
|
9838
|
+
import { select as select5, confirm as confirm8 } from "@inquirer/prompts";
|
|
9525
9839
|
function createRulesRestoreCommand() {
|
|
9526
|
-
return new
|
|
9840
|
+
return new Command44("restore").description("Restore rules from a backup").option("--latest", "Restore the most recent backup").option("-y, --yes", "Skip confirmation").action(async (options) => {
|
|
9527
9841
|
const backupService = new BackupService();
|
|
9528
9842
|
const backups = await backupService.listBackups();
|
|
9529
9843
|
if (backups.length === 0) {
|
|
@@ -9555,7 +9869,7 @@ function createRulesRestoreCommand() {
|
|
|
9555
9869
|
console.log(` IDEs: ${selectedBackup.ides.join(", ")}`);
|
|
9556
9870
|
console.log(` Files: ${selectedBackup.files.length}`);
|
|
9557
9871
|
if (!options.yes) {
|
|
9558
|
-
const proceed = await
|
|
9872
|
+
const proceed = await confirm8({
|
|
9559
9873
|
message: "This will overwrite current rules. Continue?",
|
|
9560
9874
|
default: false
|
|
9561
9875
|
});
|
|
@@ -9591,12 +9905,12 @@ function formatTimestamp(timestamp) {
|
|
|
9591
9905
|
}
|
|
9592
9906
|
|
|
9593
9907
|
// src/commands/rules/sync.ts
|
|
9594
|
-
import { Command as
|
|
9908
|
+
import { Command as Command45 } from "commander";
|
|
9595
9909
|
import { promises as fs16 } from "fs";
|
|
9596
9910
|
import { join as join11 } from "path";
|
|
9597
|
-
import { confirm as
|
|
9911
|
+
import { confirm as confirm9 } from "@inquirer/prompts";
|
|
9598
9912
|
function createRulesSyncCommand() {
|
|
9599
|
-
return new
|
|
9913
|
+
return new Command45("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) => {
|
|
9600
9914
|
const configPath = join11(process.cwd(), "jai1-rules.json");
|
|
9601
9915
|
let projectConfig;
|
|
9602
9916
|
try {
|
|
@@ -9627,7 +9941,7 @@ Detected ${detected.length} active IDE(s):
|
|
|
9627
9941
|
console.log(` ${confidence} ${d.name} - ${d.ruleCount} rules`);
|
|
9628
9942
|
});
|
|
9629
9943
|
if (!options.yes) {
|
|
9630
|
-
const proceed = await
|
|
9944
|
+
const proceed = await confirm9({
|
|
9631
9945
|
message: "\nSync these detected IDEs?",
|
|
9632
9946
|
default: true
|
|
9633
9947
|
});
|
|
@@ -9680,17 +9994,21 @@ Detected ${detected.length} active IDE(s):
|
|
|
9680
9994
|
throw new Error(`Failed to fetch preset: ${presetResponse.statusText}`);
|
|
9681
9995
|
}
|
|
9682
9996
|
const bundle = await presetResponse.json();
|
|
9683
|
-
const
|
|
9684
|
-
const
|
|
9685
|
-
if (
|
|
9686
|
-
const files = await fs16.readdir(
|
|
9997
|
+
const rulePresetDir = join11(process.cwd(), ".jai1", "rule-preset");
|
|
9998
|
+
const presetExists = await checkPathExists(rulePresetDir);
|
|
9999
|
+
if (presetExists) {
|
|
10000
|
+
const files = await fs16.readdir(rulePresetDir);
|
|
9687
10001
|
for (const file of files) {
|
|
9688
10002
|
if (file.endsWith(".mdc")) {
|
|
9689
|
-
const filePath = join11(
|
|
10003
|
+
const filePath = join11(rulePresetDir, file);
|
|
9690
10004
|
const content = await fs16.readFile(filePath, "utf-8");
|
|
9691
10005
|
bundle.files[file] = content;
|
|
9692
10006
|
}
|
|
9693
10007
|
}
|
|
10008
|
+
} else {
|
|
10009
|
+
console.log("\n\u26A0\uFE0F No rule preset found in .jai1/rule-preset/");
|
|
10010
|
+
console.log(' Run "jai1 rules apply" first to apply a preset.\n');
|
|
10011
|
+
return;
|
|
9694
10012
|
}
|
|
9695
10013
|
const generatorService = new RulesGeneratorService();
|
|
9696
10014
|
for (const ideId of idesToSync) {
|
|
@@ -9724,12 +10042,12 @@ Detected ${detected.length} active IDE(s):
|
|
|
9724
10042
|
console.log("\u{1F4A1} Next steps:");
|
|
9725
10043
|
console.log(" \u2022 Your IDE may need to be restarted to pick up changes");
|
|
9726
10044
|
console.log(' \u2022 Use "jai1 ide status" to verify IDE configuration');
|
|
9727
|
-
console.log(" \u2022 Edit source files in .
|
|
10045
|
+
console.log(" \u2022 Edit source files in .jai1/rule-preset/ and sync again\n");
|
|
9728
10046
|
});
|
|
9729
10047
|
}
|
|
9730
|
-
async function checkPathExists(
|
|
10048
|
+
async function checkPathExists(absolutePath) {
|
|
9731
10049
|
try {
|
|
9732
|
-
await fs16.access(
|
|
10050
|
+
await fs16.access(absolutePath);
|
|
9733
10051
|
return true;
|
|
9734
10052
|
} catch {
|
|
9735
10053
|
return false;
|
|
@@ -9737,11 +10055,11 @@ async function checkPathExists(path8) {
|
|
|
9737
10055
|
}
|
|
9738
10056
|
|
|
9739
10057
|
// src/commands/rules/info.ts
|
|
9740
|
-
import { Command as
|
|
10058
|
+
import { Command as Command46 } from "commander";
|
|
9741
10059
|
import { promises as fs17 } from "fs";
|
|
9742
10060
|
import { join as join12 } from "path";
|
|
9743
10061
|
function createRulesInfoCommand() {
|
|
9744
|
-
return new
|
|
10062
|
+
return new Command46("info").description("Show current preset information").option("--json", "Output as JSON").action(async (options) => {
|
|
9745
10063
|
const configPath = join12(process.cwd(), "jai1-rules.json");
|
|
9746
10064
|
let projectConfig;
|
|
9747
10065
|
try {
|
|
@@ -9757,10 +10075,43 @@ function createRulesInfoCommand() {
|
|
|
9757
10075
|
return;
|
|
9758
10076
|
}
|
|
9759
10077
|
console.log("\u{1F4CB} Current Preset Information\n");
|
|
9760
|
-
|
|
9761
|
-
|
|
10078
|
+
const rulePresetDir = join12(process.cwd(), ".jai1", "rule-preset");
|
|
10079
|
+
const presetJsonPath = join12(rulePresetDir, "preset.json");
|
|
10080
|
+
let presetMetadata = null;
|
|
10081
|
+
let presetFiles = [];
|
|
10082
|
+
try {
|
|
10083
|
+
const presetContent = await fs17.readFile(presetJsonPath, "utf-8");
|
|
10084
|
+
presetMetadata = JSON.parse(presetContent);
|
|
10085
|
+
const files = await fs17.readdir(rulePresetDir);
|
|
10086
|
+
presetFiles = files.filter((f) => f.endsWith(".mdc"));
|
|
10087
|
+
} catch {
|
|
10088
|
+
}
|
|
10089
|
+
if (presetMetadata) {
|
|
10090
|
+
console.log(`Preset: ${presetMetadata.name} (${presetMetadata.slug})`);
|
|
10091
|
+
console.log(`Version: ${presetMetadata.version}`);
|
|
10092
|
+
console.log(`Description: ${presetMetadata.description}`);
|
|
10093
|
+
if (presetMetadata.tags && presetMetadata.tags.length > 0) {
|
|
10094
|
+
console.log(`Tags: ${presetMetadata.tags.join(", ")}`);
|
|
10095
|
+
}
|
|
10096
|
+
} else {
|
|
10097
|
+
console.log(`Preset: ${projectConfig.preset}`);
|
|
10098
|
+
console.log(`Version: ${projectConfig.version}`);
|
|
10099
|
+
}
|
|
9762
10100
|
console.log(`Applied at: ${new Date(projectConfig.appliedAt).toLocaleString()}`);
|
|
9763
|
-
console.log(`
|
|
10101
|
+
console.log(`
|
|
10102
|
+
Source of Truth:`);
|
|
10103
|
+
if (presetFiles.length > 0) {
|
|
10104
|
+
console.log(` \u{1F4C1} .jai1/rule-preset/ (${presetFiles.length} files)`);
|
|
10105
|
+
for (const file of presetFiles.slice(0, 5)) {
|
|
10106
|
+
console.log(` \u2022 ${file}`);
|
|
10107
|
+
}
|
|
10108
|
+
if (presetFiles.length > 5) {
|
|
10109
|
+
console.log(` ... and ${presetFiles.length - 5} more`);
|
|
10110
|
+
}
|
|
10111
|
+
} else {
|
|
10112
|
+
console.log(` \u26A0\uFE0F .jai1/rule-preset/ not found`);
|
|
10113
|
+
console.log(` Run "jai1 rules apply" to create it`);
|
|
10114
|
+
}
|
|
9764
10115
|
if (projectConfig.ides && projectConfig.ides.length > 0) {
|
|
9765
10116
|
console.log(`
|
|
9766
10117
|
Configured IDEs (${projectConfig.ides.length}):`);
|
|
@@ -9785,9 +10136,9 @@ Available Backups (${projectConfig.backups.length}):`);
|
|
|
9785
10136
|
}
|
|
9786
10137
|
}
|
|
9787
10138
|
console.log("\n\u2139\uFE0F Commands:");
|
|
9788
|
-
console.log(' \u2022 "jai1 rules sync" - Regenerate outputs after editing');
|
|
10139
|
+
console.log(' \u2022 "jai1 rules sync" - Regenerate IDE outputs after editing .jai1/rule-preset/');
|
|
9789
10140
|
console.log(' \u2022 "jai1 rules restore" - Restore from backup');
|
|
9790
|
-
console.log(' \u2022 "jai1 rules apply" - Apply a different preset');
|
|
10141
|
+
console.log(' \u2022 "jai1 rules apply" - Apply a different preset (replaces current)');
|
|
9791
10142
|
});
|
|
9792
10143
|
}
|
|
9793
10144
|
async function checkPathExists2(path8) {
|
|
@@ -9814,7 +10165,7 @@ async function checkIdeFilesExist(ideId, format) {
|
|
|
9814
10165
|
|
|
9815
10166
|
// src/commands/rules/index.ts
|
|
9816
10167
|
function createRulesCommand() {
|
|
9817
|
-
const rulesCommand = new
|
|
10168
|
+
const rulesCommand = new Command47("rules").description("Manage rule presets for AI agents");
|
|
9818
10169
|
rulesCommand.addCommand(createRulesListCommand());
|
|
9819
10170
|
rulesCommand.addCommand(createRulesInitCommand());
|
|
9820
10171
|
rulesCommand.addCommand(createRulesApplyCommand());
|
|
@@ -9825,8 +10176,8 @@ function createRulesCommand() {
|
|
|
9825
10176
|
}
|
|
9826
10177
|
|
|
9827
10178
|
// src/commands/upgrade.ts
|
|
9828
|
-
import { Command as
|
|
9829
|
-
import { confirm as
|
|
10179
|
+
import { Command as Command48 } from "commander";
|
|
10180
|
+
import { confirm as confirm10 } from "@inquirer/prompts";
|
|
9830
10181
|
import { execSync as execSync2 } from "child_process";
|
|
9831
10182
|
var colors3 = {
|
|
9832
10183
|
yellow: "\x1B[33m",
|
|
@@ -9837,7 +10188,7 @@ var colors3 = {
|
|
|
9837
10188
|
bold: "\x1B[1m"
|
|
9838
10189
|
};
|
|
9839
10190
|
function createUpgradeCommand() {
|
|
9840
|
-
return new
|
|
10191
|
+
return new Command48("upgrade").description("Upgrade jai1-client to the latest version").option("--check", "Only check for updates without installing").option("--force", "Force upgrade without confirmation").action(async (options) => {
|
|
9841
10192
|
await handleUpgrade(options);
|
|
9842
10193
|
});
|
|
9843
10194
|
}
|
|
@@ -9881,7 +10232,7 @@ ${colors3.bold}Current version:${colors3.reset} ${currentVersion}`);
|
|
|
9881
10232
|
return;
|
|
9882
10233
|
}
|
|
9883
10234
|
if (!options.force) {
|
|
9884
|
-
const shouldUpdate = await
|
|
10235
|
+
const shouldUpdate = await confirm10({
|
|
9885
10236
|
message: "Update to the latest version now?",
|
|
9886
10237
|
default: true
|
|
9887
10238
|
});
|
|
@@ -9985,11 +10336,11 @@ function getInstallCommand(packageManager2) {
|
|
|
9985
10336
|
}
|
|
9986
10337
|
|
|
9987
10338
|
// src/commands/clean.ts
|
|
9988
|
-
import { Command as
|
|
9989
|
-
import { confirm as
|
|
10339
|
+
import { Command as Command49 } from "commander";
|
|
10340
|
+
import { confirm as confirm11, select as select6 } from "@inquirer/prompts";
|
|
9990
10341
|
import { join as join13 } from "path";
|
|
9991
10342
|
function createCleanCommand() {
|
|
9992
|
-
return new
|
|
10343
|
+
return new Command49("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) => {
|
|
9993
10344
|
await handleClean(options);
|
|
9994
10345
|
});
|
|
9995
10346
|
}
|
|
@@ -10084,7 +10435,7 @@ async function cleanTarget(target, skipConfirm) {
|
|
|
10084
10435
|
}
|
|
10085
10436
|
const countStr = info.count ? ` (${info.count} items)` : "";
|
|
10086
10437
|
if (!skipConfirm) {
|
|
10087
|
-
const confirmed = await
|
|
10438
|
+
const confirmed = await confirm11({
|
|
10088
10439
|
message: `Delete ${target.name}${countStr}?`,
|
|
10089
10440
|
default: false
|
|
10090
10441
|
});
|
|
@@ -10102,7 +10453,7 @@ async function cleanTarget(target, skipConfirm) {
|
|
|
10102
10453
|
}
|
|
10103
10454
|
|
|
10104
10455
|
// src/commands/redmine/check.ts
|
|
10105
|
-
import { Command as
|
|
10456
|
+
import { Command as Command50 } from "commander";
|
|
10106
10457
|
|
|
10107
10458
|
// src/services/redmine-config.service.ts
|
|
10108
10459
|
import { readFile as readFile6 } from "fs/promises";
|
|
@@ -10409,7 +10760,7 @@ async function checkConnectivity(config) {
|
|
|
10409
10760
|
|
|
10410
10761
|
// src/commands/redmine/check.ts
|
|
10411
10762
|
function createRedmineCheckCommand() {
|
|
10412
|
-
const cmd = new
|
|
10763
|
+
const cmd = new Command50("check").description("Check Redmine connectivity").option("-c, --config <path>", "Config file path", "redmine.config.yaml").option("--json", "Output as JSON").action(async (options) => {
|
|
10413
10764
|
await handleRedmineCheck(options);
|
|
10414
10765
|
});
|
|
10415
10766
|
return cmd;
|
|
@@ -10437,7 +10788,7 @@ async function handleRedmineCheck(options) {
|
|
|
10437
10788
|
}
|
|
10438
10789
|
|
|
10439
10790
|
// src/commands/redmine/sync-issue.ts
|
|
10440
|
-
import { Command as
|
|
10791
|
+
import { Command as Command51 } from "commander";
|
|
10441
10792
|
|
|
10442
10793
|
// src/sync-issue.ts
|
|
10443
10794
|
import { resolve as resolve3, relative } from "path";
|
|
@@ -10813,7 +11164,7 @@ function extractIssueIdFromUrl(url) {
|
|
|
10813
11164
|
|
|
10814
11165
|
// src/commands/redmine/sync-issue.ts
|
|
10815
11166
|
function createSyncIssueCommand() {
|
|
10816
|
-
const cmd = new
|
|
11167
|
+
const cmd = new Command51("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) => {
|
|
10817
11168
|
await handleSyncIssue(options);
|
|
10818
11169
|
});
|
|
10819
11170
|
return cmd;
|
|
@@ -10857,7 +11208,7 @@ async function handleSyncIssue(options) {
|
|
|
10857
11208
|
}
|
|
10858
11209
|
|
|
10859
11210
|
// src/commands/redmine/sync-project.ts
|
|
10860
|
-
import { Command as
|
|
11211
|
+
import { Command as Command52 } from "commander";
|
|
10861
11212
|
|
|
10862
11213
|
// src/sync-project.ts
|
|
10863
11214
|
async function syncProject(config, options = {}) {
|
|
@@ -10927,7 +11278,7 @@ async function syncProject(config, options = {}) {
|
|
|
10927
11278
|
|
|
10928
11279
|
// src/commands/redmine/sync-project.ts
|
|
10929
11280
|
function createSyncProjectCommand() {
|
|
10930
|
-
const cmd = new
|
|
11281
|
+
const cmd = new Command52("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) => {
|
|
10931
11282
|
await handleSyncProject(options);
|
|
10932
11283
|
});
|
|
10933
11284
|
return cmd;
|
|
@@ -10982,12 +11333,12 @@ async function handleSyncProject(options) {
|
|
|
10982
11333
|
}
|
|
10983
11334
|
|
|
10984
11335
|
// src/commands/framework/info.ts
|
|
10985
|
-
import { Command as
|
|
11336
|
+
import { Command as Command53 } from "commander";
|
|
10986
11337
|
import { promises as fs18 } from "fs";
|
|
10987
11338
|
import { join as join14 } from "path";
|
|
10988
11339
|
import { homedir as homedir5 } from "os";
|
|
10989
11340
|
function createInfoCommand() {
|
|
10990
|
-
const cmd = new
|
|
11341
|
+
const cmd = new Command53("info").description("Show jai1-client configuration and status").option("--json", "Output as JSON").option("--verbose", "Show detailed information").action(async (options) => {
|
|
10991
11342
|
await handleInfo(options);
|
|
10992
11343
|
});
|
|
10993
11344
|
return cmd;
|
|
@@ -11043,8 +11394,8 @@ async function getProjectStatus2() {
|
|
|
11043
11394
|
}
|
|
11044
11395
|
|
|
11045
11396
|
// src/commands/self-update.ts
|
|
11046
|
-
import { Command as
|
|
11047
|
-
import { confirm as
|
|
11397
|
+
import { Command as Command54 } from "commander";
|
|
11398
|
+
import { confirm as confirm12 } from "@inquirer/prompts";
|
|
11048
11399
|
import { execSync as execSync3 } from "child_process";
|
|
11049
11400
|
var colors4 = {
|
|
11050
11401
|
yellow: "\x1B[33m",
|
|
@@ -11055,7 +11406,7 @@ var colors4 = {
|
|
|
11055
11406
|
bold: "\x1B[1m"
|
|
11056
11407
|
};
|
|
11057
11408
|
function createSelfUpdateCommand() {
|
|
11058
|
-
return new
|
|
11409
|
+
return new Command54("self-update").description("Update jai1-client to the latest version").option("--check", "Only check for updates without installing").option("--force", "Force update without confirmation").action(async (options) => {
|
|
11059
11410
|
await handleSelfUpdate(options);
|
|
11060
11411
|
});
|
|
11061
11412
|
}
|
|
@@ -11099,7 +11450,7 @@ ${colors4.bold}Current version:${colors4.reset} ${currentVersion}`);
|
|
|
11099
11450
|
return;
|
|
11100
11451
|
}
|
|
11101
11452
|
if (!options.force) {
|
|
11102
|
-
const shouldUpdate = await
|
|
11453
|
+
const shouldUpdate = await confirm12({
|
|
11103
11454
|
message: "Update to the latest version now?",
|
|
11104
11455
|
default: true
|
|
11105
11456
|
});
|
|
@@ -11195,10 +11546,10 @@ function getInstallCommand2(packageManager2) {
|
|
|
11195
11546
|
}
|
|
11196
11547
|
|
|
11197
11548
|
// src/commands/clear-backups.ts
|
|
11198
|
-
import { Command as
|
|
11199
|
-
import { confirm as
|
|
11549
|
+
import { Command as Command55 } from "commander";
|
|
11550
|
+
import { confirm as confirm13 } from "@inquirer/prompts";
|
|
11200
11551
|
function createClearBackupsCommand() {
|
|
11201
|
-
return new
|
|
11552
|
+
return new Command55("clear-backups").description("Clear backup files").option("-y, --yes", "Skip confirmation").action(async (options) => {
|
|
11202
11553
|
const service = new ComponentsService();
|
|
11203
11554
|
const backups = await service.listBackups(process.cwd());
|
|
11204
11555
|
if (backups.length === 0) {
|
|
@@ -11214,7 +11565,7 @@ function createClearBackupsCommand() {
|
|
|
11214
11565
|
}
|
|
11215
11566
|
console.log();
|
|
11216
11567
|
if (!options.yes) {
|
|
11217
|
-
const ok = await
|
|
11568
|
+
const ok = await confirm13({ message: "Delete all backups?", default: false });
|
|
11218
11569
|
if (!ok) return;
|
|
11219
11570
|
}
|
|
11220
11571
|
await service.clearBackups(process.cwd());
|
|
@@ -11223,8 +11574,8 @@ function createClearBackupsCommand() {
|
|
|
11223
11574
|
}
|
|
11224
11575
|
|
|
11225
11576
|
// src/commands/vscode/index.ts
|
|
11226
|
-
import { Command as
|
|
11227
|
-
import { checkbox as checkbox7, confirm as
|
|
11577
|
+
import { Command as Command56 } from "commander";
|
|
11578
|
+
import { checkbox as checkbox7, confirm as confirm14, select as select7 } from "@inquirer/prompts";
|
|
11228
11579
|
import fs19 from "fs/promises";
|
|
11229
11580
|
import path7 from "path";
|
|
11230
11581
|
import { existsSync as existsSync3 } from "fs";
|
|
@@ -11363,7 +11714,7 @@ var PERFORMANCE_GROUPS2 = {
|
|
|
11363
11714
|
}
|
|
11364
11715
|
};
|
|
11365
11716
|
function createVSCodeCommand() {
|
|
11366
|
-
const vscodeCommand = new
|
|
11717
|
+
const vscodeCommand = new Command56("vscode").description("Qu\u1EA3n l\xFD c\xE0i \u0111\u1EB7t VSCode cho d\u1EF1 \xE1n hi\u1EC7n t\u1EA1i");
|
|
11367
11718
|
vscodeCommand.action(async () => {
|
|
11368
11719
|
await interactiveMode2();
|
|
11369
11720
|
});
|
|
@@ -11467,7 +11818,7 @@ async function applyGroups2(groupKeys, action) {
|
|
|
11467
11818
|
console.log("\u{1F4C4} \u0110\xE3 \u0111\u1ECDc c\xE0i \u0111\u1EB7t hi\u1EC7n t\u1EA1i t\u1EEB settings.json");
|
|
11468
11819
|
} catch {
|
|
11469
11820
|
console.warn("\u26A0\uFE0F Kh\xF4ng th\u1EC3 \u0111\u1ECDc settings.json (c\xF3 th\u1EC3 ch\u1EE9a comments).");
|
|
11470
|
-
const confirmOverwrite = await
|
|
11821
|
+
const confirmOverwrite = await confirm14({
|
|
11471
11822
|
message: "Ghi \u0111\xE8 file settings.json hi\u1EC7n t\u1EA1i?",
|
|
11472
11823
|
default: false
|
|
11473
11824
|
});
|
|
@@ -11514,7 +11865,7 @@ async function resetSettings2(groupKeys) {
|
|
|
11514
11865
|
console.log("\n\u26A0\uFE0F Kh\xF4ng t\xECm th\u1EA5y file settings.json");
|
|
11515
11866
|
return;
|
|
11516
11867
|
}
|
|
11517
|
-
const confirmReset = await
|
|
11868
|
+
const confirmReset = await confirm14({
|
|
11518
11869
|
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(", ")}?`,
|
|
11519
11870
|
default: false
|
|
11520
11871
|
});
|
|
@@ -11534,9 +11885,9 @@ async function resetSettings2(groupKeys) {
|
|
|
11534
11885
|
// src/commands/guide.ts
|
|
11535
11886
|
import React40 from "react";
|
|
11536
11887
|
import { render as render6 } from "ink";
|
|
11537
|
-
import { Command as
|
|
11888
|
+
import { Command as Command57 } from "commander";
|
|
11538
11889
|
function createGuideCommand() {
|
|
11539
|
-
const cmd = new
|
|
11890
|
+
const cmd = new Command57("guide").description("Interactive guide center for Agentic Coding").option("--topic <topic>", "Open specific topic (intro, rules, workflows, prompts, skills)").action(async (options) => {
|
|
11540
11891
|
const { waitUntilExit } = render6(
|
|
11541
11892
|
React40.createElement(GuideApp, {
|
|
11542
11893
|
initialTopic: options.topic,
|
|
@@ -11553,9 +11904,9 @@ function createGuideCommand() {
|
|
|
11553
11904
|
// src/commands/context.ts
|
|
11554
11905
|
import React41 from "react";
|
|
11555
11906
|
import { render as render7 } from "ink";
|
|
11556
|
-
import { Command as
|
|
11907
|
+
import { Command as Command58 } from "commander";
|
|
11557
11908
|
function createContextCommand() {
|
|
11558
|
-
const cmd = new
|
|
11909
|
+
const cmd = new Command58("context").description("Kh\xE1m ph\xE1 v\xE0 qu\u1EA3n l\xFD context d\u1EF1 \xE1n cho c\xE1c IDE").option("--ide <ide>", "M\u1EDF tr\u1EF1c ti\u1EBFp IDE c\u1EE5 th\u1EC3 (cursor, windsurf, antigravity, jai1)").option("--type <type>", "Hi\u1EC3n th\u1ECB lo\u1EA1i context c\u1EE5 th\u1EC3 (rules, workflows, skills, agents, prompts)").option("--stats", "Hi\u1EC3n th\u1ECB th\u1ED1ng k\xEA context (non-interactive)").action(async (options) => {
|
|
11559
11910
|
let initialIDE;
|
|
11560
11911
|
if (options.ide) {
|
|
11561
11912
|
const validIDEs = ["cursor", "windsurf", "antigravity", "jai1"];
|
|
@@ -11632,10 +11983,10 @@ async function printStats2() {
|
|
|
11632
11983
|
}
|
|
11633
11984
|
|
|
11634
11985
|
// src/commands/migrate-ide.ts
|
|
11635
|
-
import { Command as
|
|
11636
|
-
import { checkbox as checkbox8, confirm as
|
|
11986
|
+
import { Command as Command59 } from "commander";
|
|
11987
|
+
import { checkbox as checkbox8, confirm as confirm15 } from "@inquirer/prompts";
|
|
11637
11988
|
function createMigrateIdeCommand() {
|
|
11638
|
-
const cmd = new
|
|
11989
|
+
const cmd = new Command59("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) => {
|
|
11639
11990
|
await runMigrateIde(options);
|
|
11640
11991
|
});
|
|
11641
11992
|
return cmd;
|
|
@@ -11704,7 +12055,7 @@ async function runMigrateIde(options) {
|
|
|
11704
12055
|
if (options.dryRun) {
|
|
11705
12056
|
console.log("\u{1F50D} DRY RUN - No files will be written\n");
|
|
11706
12057
|
}
|
|
11707
|
-
const confirmed = await
|
|
12058
|
+
const confirmed = await confirm15({
|
|
11708
12059
|
message: "Proceed with migration?",
|
|
11709
12060
|
default: true
|
|
11710
12061
|
});
|
|
@@ -11741,7 +12092,7 @@ async function runMigrateIde(options) {
|
|
|
11741
12092
|
}
|
|
11742
12093
|
|
|
11743
12094
|
// src/cli.ts
|
|
11744
|
-
var program = new
|
|
12095
|
+
var program = new Command60();
|
|
11745
12096
|
if (process.argv.includes("-v") || process.argv.includes("--version")) {
|
|
11746
12097
|
console.log(package_default.version);
|
|
11747
12098
|
if (!process.argv.includes("--skip-update-check")) {
|
|
@@ -11762,15 +12113,16 @@ program.addCommand(createChatCommand());
|
|
|
11762
12113
|
program.addCommand(createOpenAiKeysCommand());
|
|
11763
12114
|
program.addCommand(createStatsCommand());
|
|
11764
12115
|
program.addCommand(createTranslateCommand());
|
|
12116
|
+
program.addCommand(createImageCommand());
|
|
11765
12117
|
program.addCommand(createUtilsCommand());
|
|
11766
12118
|
program.addCommand(createDepsCommand());
|
|
11767
12119
|
program.addCommand(createKitCommand());
|
|
11768
12120
|
program.addCommand(createRulesCommand());
|
|
11769
12121
|
program.addCommand(createUpgradeCommand());
|
|
11770
12122
|
program.addCommand(createCleanCommand());
|
|
11771
|
-
var redmineCommand = new
|
|
12123
|
+
var redmineCommand = new Command60("redmine").description("Redmine context sync commands");
|
|
11772
12124
|
redmineCommand.addCommand(createRedmineCheckCommand());
|
|
11773
|
-
var syncCommand = new
|
|
12125
|
+
var syncCommand = new Command60("sync").description("Sync Redmine issues to markdown files");
|
|
11774
12126
|
syncCommand.addCommand(createSyncIssueCommand());
|
|
11775
12127
|
syncCommand.addCommand(createSyncProjectCommand());
|
|
11776
12128
|
redmineCommand.addCommand(syncCommand);
|