@jvittechs/j 1.0.66 → 1.0.67
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 +191 -169
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -160,7 +160,7 @@ import { basename as basename5 } from "path";
|
|
|
160
160
|
// package.json
|
|
161
161
|
var package_default = {
|
|
162
162
|
name: "@jvittechs/j",
|
|
163
|
-
version: "1.0.
|
|
163
|
+
version: "1.0.67",
|
|
164
164
|
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.",
|
|
165
165
|
type: "module",
|
|
166
166
|
bin: {
|
|
@@ -618,7 +618,7 @@ async function getProjectStatus() {
|
|
|
618
618
|
// src/commands/apply.ts
|
|
619
619
|
import React4 from "react";
|
|
620
620
|
import { render } from "ink";
|
|
621
|
-
import { Command as
|
|
621
|
+
import { Command as Command4 } from "commander";
|
|
622
622
|
|
|
623
623
|
// src/ui/apply/UnifiedApplyApp.tsx
|
|
624
624
|
import React3, { useState, useEffect, useMemo } from "react";
|
|
@@ -1581,9 +1581,162 @@ var UnifiedApplyApp = ({
|
|
|
1581
1581
|
}), filteredComponents.length === 0 && /* @__PURE__ */ React3.createElement(Text3, { dimColor: true }, "No components match your filter")), 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, 3).map((fp) => /* @__PURE__ */ React3.createElement(Text3, { key: fp, dimColor: true }, "\u{1F4CC} ", fp)), selectedPaths.size > 3 && /* @__PURE__ */ React3.createElement(Text3, { dimColor: true }, " ... +", selectedPaths.size - 3, " more"))), /* @__PURE__ */ React3.createElement(Box2, { marginTop: 1, borderStyle: "single", borderColor: "gray", paddingX: 1 }, /* @__PURE__ */ React3.createElement(Text3, { dimColor: true }, focusArea === "packages" && "[\u2190\u2192] Package \xB7 [\u2193] List \xB7 [\u2423] Select all", focusArea === "search" && "Type to filter \xB7 [\u2193] List", focusArea === "components" && "[\u2191\u2193] Navigate \xB7 [\u2423] Toggle", " \xB7 [Tab] Switch \xB7 [A] All \xB7 [C] Clear \xB7 [Enter] Apply")));
|
|
1582
1582
|
};
|
|
1583
1583
|
|
|
1584
|
+
// src/commands/ide/sync.ts
|
|
1585
|
+
import { Command as Command3 } from "commander";
|
|
1586
|
+
import { checkbox, confirm } from "@inquirer/prompts";
|
|
1587
|
+
|
|
1588
|
+
// src/utils/prompt-theme.ts
|
|
1589
|
+
var keysHelpTipWithQuit = (keys) => {
|
|
1590
|
+
const keyStrings = keys.map(([key, action]) => `${key} ${action}`);
|
|
1591
|
+
keyStrings.push("Ctrl+C quit");
|
|
1592
|
+
return keyStrings.join(" \u2022 ");
|
|
1593
|
+
};
|
|
1594
|
+
var checkboxTheme = {
|
|
1595
|
+
style: {
|
|
1596
|
+
keysHelpTip: keysHelpTipWithQuit
|
|
1597
|
+
}
|
|
1598
|
+
};
|
|
1599
|
+
var selectTheme = {
|
|
1600
|
+
style: {
|
|
1601
|
+
keysHelpTip: keysHelpTipWithQuit
|
|
1602
|
+
}
|
|
1603
|
+
};
|
|
1604
|
+
|
|
1605
|
+
// src/commands/ide/sync.ts
|
|
1606
|
+
function createSyncSubcommand() {
|
|
1607
|
+
const cmd = new Command3("sync").description("Sync .jai1 content to IDE directories (Cursor, Windsurf, Claude Code, etc.)").option("--ides <ides...>", "Target IDEs (cursor, windsurf, antigravity, claudecode, opencode)").option("--type <types...>", "Content types (rules, workflows, commands)").option("--dry-run", "Preview changes without writing files").option("-y, --yes", "Headless mode (skip all prompts)").option("--all", "Select all available IDEs").action(async (options) => {
|
|
1608
|
+
await runSync(options);
|
|
1609
|
+
});
|
|
1610
|
+
return cmd;
|
|
1611
|
+
}
|
|
1612
|
+
async function runSync(options) {
|
|
1613
|
+
const service = new MigrateIdeService();
|
|
1614
|
+
const headless = options.yes === true;
|
|
1615
|
+
console.log("\n\u{1F504} Sync rules and workflows to IDE(s)\n");
|
|
1616
|
+
console.log("\u{1F4C1} Scanning .jai1/ directory...");
|
|
1617
|
+
console.log(" \u2022 .jai1/rule-preset/ (active rule preset)");
|
|
1618
|
+
console.log(" \u2022 .jai1/rules/ (manual rules)");
|
|
1619
|
+
console.log(" \u2022 .jai1/workflows/\n");
|
|
1620
|
+
const content = await service.scanJai1Content();
|
|
1621
|
+
if (content.totalCount === 0) {
|
|
1622
|
+
console.log("\u26A0\uFE0F No content found in .jai1/");
|
|
1623
|
+
console.log(' \u{1F4A1} Run "jai1 rules apply" to apply a rule preset, or');
|
|
1624
|
+
console.log(" \u{1F4A1} Create files in .jai1/rules/ or .jai1/workflows/\n");
|
|
1625
|
+
process.exit(1);
|
|
1626
|
+
}
|
|
1627
|
+
console.log(`\u2713 Found: ${content.rules.length} rules, ${content.workflows.length} workflows
|
|
1628
|
+
`);
|
|
1629
|
+
let selectedIdes;
|
|
1630
|
+
if (options.all) {
|
|
1631
|
+
selectedIdes = getMigrationIDEs();
|
|
1632
|
+
} else if (options.ides && options.ides.length > 0) {
|
|
1633
|
+
selectedIdes = options.ides;
|
|
1634
|
+
} else if (headless) {
|
|
1635
|
+
throw new Error(
|
|
1636
|
+
"Headless mode (-y) requires --ides or --all flag.\nExamples:\n j ide sync --ides cursor windsurf -y\n j ide sync --all -y"
|
|
1637
|
+
);
|
|
1638
|
+
} else {
|
|
1639
|
+
const ideChoices = getMigrationIDEs().map((ide) => {
|
|
1640
|
+
const config = IDE_MIGRATION_CONFIGS[ide];
|
|
1641
|
+
return {
|
|
1642
|
+
name: `${config.icon} ${config.name}`,
|
|
1643
|
+
value: ide
|
|
1644
|
+
};
|
|
1645
|
+
});
|
|
1646
|
+
selectedIdes = await checkbox({
|
|
1647
|
+
message: "Select target IDE(s) (SPACE to select, ENTER to confirm):",
|
|
1648
|
+
choices: ideChoices,
|
|
1649
|
+
theme: checkboxTheme
|
|
1650
|
+
});
|
|
1651
|
+
if (selectedIdes.length === 0) {
|
|
1652
|
+
console.log("\n\u26A0\uFE0F No IDE selected!");
|
|
1653
|
+
console.log(" \u{1F4A1} Select at least 1 IDE.\n");
|
|
1654
|
+
process.exit(0);
|
|
1655
|
+
}
|
|
1656
|
+
}
|
|
1657
|
+
let selectedTypes;
|
|
1658
|
+
if (options.type && options.type.length > 0) {
|
|
1659
|
+
selectedTypes = options.type;
|
|
1660
|
+
} else if (headless) {
|
|
1661
|
+
selectedTypes = ["rules", "workflows", "commands"];
|
|
1662
|
+
} else {
|
|
1663
|
+
const typeChoices = [
|
|
1664
|
+
{ name: `Rules (${content.rules.length} files)`, value: "rules" },
|
|
1665
|
+
{ name: `Workflows (${content.workflows.length} files)`, value: "workflows" },
|
|
1666
|
+
{ name: `Commands (${content.commands.length} files)`, value: "commands" }
|
|
1667
|
+
];
|
|
1668
|
+
selectedTypes = await checkbox({
|
|
1669
|
+
message: "Select content types to sync:",
|
|
1670
|
+
choices: typeChoices,
|
|
1671
|
+
theme: checkboxTheme
|
|
1672
|
+
});
|
|
1673
|
+
if (selectedTypes.length === 0) {
|
|
1674
|
+
console.log("\n\u26A0\uFE0F No content type selected!");
|
|
1675
|
+
console.log(" \u{1F4A1} Select at least 1 content type.\n");
|
|
1676
|
+
process.exit(0);
|
|
1677
|
+
}
|
|
1678
|
+
}
|
|
1679
|
+
const totalItems = selectedTypes.reduce((sum, type) => {
|
|
1680
|
+
return sum + (type === "rules" ? content.rules.length : type === "workflows" ? content.workflows.length : content.commands.length);
|
|
1681
|
+
}, 0);
|
|
1682
|
+
const totalFiles = totalItems * selectedIdes.length;
|
|
1683
|
+
console.log("\n\u{1F4CA} Preview:\n");
|
|
1684
|
+
console.log(` IDEs: ${selectedIdes.map((ide) => IDE_MIGRATION_CONFIGS[ide].name).join(", ")}`);
|
|
1685
|
+
console.log(` Content types: ${selectedTypes.join(", ")}`);
|
|
1686
|
+
console.log(` Will create/update: ${totalFiles} stub files
|
|
1687
|
+
`);
|
|
1688
|
+
if (options.dryRun) {
|
|
1689
|
+
console.log("\u{1F50D} DRY RUN - No files will be written\n");
|
|
1690
|
+
}
|
|
1691
|
+
if (!headless) {
|
|
1692
|
+
const confirmed = await confirm({
|
|
1693
|
+
message: "Proceed with sync?",
|
|
1694
|
+
default: true
|
|
1695
|
+
});
|
|
1696
|
+
if (!confirmed) {
|
|
1697
|
+
console.log("\n\u274C Sync cancelled.\n");
|
|
1698
|
+
process.exit(0);
|
|
1699
|
+
}
|
|
1700
|
+
}
|
|
1701
|
+
console.log("\n\u{1F504} Syncing...\n");
|
|
1702
|
+
let completed = 0;
|
|
1703
|
+
const results = await service.migrate(
|
|
1704
|
+
selectedIdes,
|
|
1705
|
+
selectedTypes,
|
|
1706
|
+
content,
|
|
1707
|
+
(result) => {
|
|
1708
|
+
completed++;
|
|
1709
|
+
const icon = result.status === "created" ? "\u2713" : result.status === "updated" ? "\u21BB" : result.status === "error" ? "\u2717" : "\u25CB";
|
|
1710
|
+
const percentage = Math.round(completed / totalFiles * 100);
|
|
1711
|
+
console.log(` ${icon} [${percentage}%] ${result.targetPath}`);
|
|
1712
|
+
if (result.status === "error" && result.error) {
|
|
1713
|
+
console.log(` Error: ${result.error}`);
|
|
1714
|
+
}
|
|
1715
|
+
}
|
|
1716
|
+
);
|
|
1717
|
+
const created = results.filter((r) => r.status === "created").length;
|
|
1718
|
+
const updated = results.filter((r) => r.status === "updated").length;
|
|
1719
|
+
const skipped = results.filter((r) => r.status === "skipped").length;
|
|
1720
|
+
const errors = results.filter((r) => r.status === "error").length;
|
|
1721
|
+
console.log("\n\u2705 Sync complete!\n");
|
|
1722
|
+
console.log(` Created: ${created}`);
|
|
1723
|
+
console.log(` Updated: ${updated}`);
|
|
1724
|
+
if (skipped > 0) console.log(` Skipped: ${skipped}`);
|
|
1725
|
+
if (errors > 0) console.log(` Errors: ${errors}`);
|
|
1726
|
+
console.log("");
|
|
1727
|
+
}
|
|
1728
|
+
|
|
1584
1729
|
// src/commands/apply.ts
|
|
1730
|
+
var TARGET_IDE_MAP = {
|
|
1731
|
+
"cursor": "cursor",
|
|
1732
|
+
"windsurf": "windsurf",
|
|
1733
|
+
"antigravity": "antigravity",
|
|
1734
|
+
"claude": "claudecode",
|
|
1735
|
+
"claudecode": "claudecode",
|
|
1736
|
+
"opencode": "opencode"
|
|
1737
|
+
};
|
|
1585
1738
|
function createApplyCommand() {
|
|
1586
|
-
const cmd = new
|
|
1739
|
+
const cmd = new Command4("apply").description("Apply components to your project (interactive UI)").argument("[items...]", "Package name or component filepaths (non-interactive mode)").option("--force", "Force overwrite even if modified locally").option("--no-interactive", "Disable interactive UI (for CI/CD)").option("--target <ides...>", "Auto-sync to target IDE(s) after apply (claude, cursor, windsurf, etc.)").action(async (items, options) => {
|
|
1587
1740
|
const configService = new ConfigService();
|
|
1588
1741
|
const config = await configService.load();
|
|
1589
1742
|
if (!config) {
|
|
@@ -1667,16 +1820,29 @@ async function nonInteractiveApply(config, items, options) {
|
|
|
1667
1820
|
console.log(`
|
|
1668
1821
|
\u2705 Complete: ${added} added, ${updated} updated, ${skipped} skipped`);
|
|
1669
1822
|
console.log(`\u{1F4C1} Location: ${targetDir}`);
|
|
1670
|
-
|
|
1823
|
+
if (options.target && options.target.length > 0) {
|
|
1824
|
+
const resolvedIdes = options.target.map((ide) => TARGET_IDE_MAP[ide.toLowerCase()]).filter((ide) => !!ide);
|
|
1825
|
+
if (resolvedIdes.length > 0) {
|
|
1826
|
+
console.log(`
|
|
1827
|
+
\u{1F504} Auto-syncing to IDE(s): ${resolvedIdes.join(", ")}...`);
|
|
1828
|
+
await runSync({ ides: resolvedIdes, yes: true });
|
|
1829
|
+
} else {
|
|
1830
|
+
const valid = Object.keys(TARGET_IDE_MAP).join(", ");
|
|
1831
|
+
console.log(`
|
|
1832
|
+
\u26A0\uFE0F Unknown --target IDE(s): ${options.target.join(", ")}. Valid: ${valid}`);
|
|
1833
|
+
}
|
|
1834
|
+
} else {
|
|
1835
|
+
console.log(`
|
|
1671
1836
|
\u{1F4A1} B\u01B0\u1EDBc ti\u1EBFp theo:`);
|
|
1672
|
-
|
|
1673
|
-
|
|
1837
|
+
console.log(` \u2022 Ch\u1EA1y "${name} ide sync" \u0111\u1EC3 \u0111\u1ED3ng b\u1ED9 n\u1ED9i dung sang c\xE1c IDE b\u1EA1n \u0111ang d\xF9ng.`);
|
|
1838
|
+
console.log(` \u2022 Ch\u1EA1y "${name} doctor" \u0111\u1EC3 ki\u1EC3m tra d\u1EF1 \xE1n \u0111\xE3 setup Jai1 \u0111\u1EA7y \u0111\u1EE7 ch\u01B0a.`);
|
|
1839
|
+
}
|
|
1674
1840
|
}
|
|
1675
1841
|
|
|
1676
1842
|
// src/commands/apply-new.ts
|
|
1677
1843
|
import React6 from "react";
|
|
1678
1844
|
import { render as render2 } from "ink";
|
|
1679
|
-
import { Command as
|
|
1845
|
+
import { Command as Command5 } from "commander";
|
|
1680
1846
|
|
|
1681
1847
|
// src/ui/apply/TwoPaneApplyApp.tsx
|
|
1682
1848
|
import React5, { useState as useState2, useEffect as useEffect2, useMemo as useMemo2 } from "react";
|
|
@@ -2035,7 +2201,7 @@ var TwoPaneApplyApp = ({
|
|
|
2035
2201
|
|
|
2036
2202
|
// src/commands/apply-new.ts
|
|
2037
2203
|
function createApplyNewCommand() {
|
|
2038
|
-
const cmd = new
|
|
2204
|
+
const cmd = new Command5("apply-new").description("Apply components (Two-Pane UI - experimental)").option("--force", "Force overwrite even if modified locally").action(async (options) => {
|
|
2039
2205
|
const configService = new ConfigService();
|
|
2040
2206
|
const config = await configService.load();
|
|
2041
2207
|
if (!config) {
|
|
@@ -2056,11 +2222,11 @@ function createApplyNewCommand() {
|
|
|
2056
2222
|
}
|
|
2057
2223
|
|
|
2058
2224
|
// src/commands/update.ts
|
|
2059
|
-
import { Command as
|
|
2060
|
-
import { confirm } from "@inquirer/prompts";
|
|
2225
|
+
import { Command as Command6 } from "commander";
|
|
2226
|
+
import { confirm as confirm2 } from "@inquirer/prompts";
|
|
2061
2227
|
import chalk4 from "chalk";
|
|
2062
2228
|
function createUpdateCommand() {
|
|
2063
|
-
return new
|
|
2229
|
+
return new Command6("update").description("Update installed components to latest versions").option("--force", "Force update even if files are modified locally").action(async (options) => {
|
|
2064
2230
|
await handleUpdate(options);
|
|
2065
2231
|
});
|
|
2066
2232
|
}
|
|
@@ -2121,7 +2287,7 @@ async function handleUpdate(options) {
|
|
|
2121
2287
|
}
|
|
2122
2288
|
console.log();
|
|
2123
2289
|
if (!options.force) {
|
|
2124
|
-
const shouldUpdate = await
|
|
2290
|
+
const shouldUpdate = await confirm2({ message: "C\u1EADp nh\u1EADt ngay?", default: true });
|
|
2125
2291
|
if (!shouldUpdate) {
|
|
2126
2292
|
console.log(chalk4.dim("\u0110\xE3 h\u1EE7y c\u1EADp nh\u1EADt."));
|
|
2127
2293
|
return;
|
|
@@ -2155,7 +2321,7 @@ async function handleUpdate(options) {
|
|
|
2155
2321
|
if (backupPaths.length > 0) {
|
|
2156
2322
|
console.log(chalk4.dim(`
|
|
2157
2323
|
\u{1F4C1} \u0110\xE3 t\u1EA1o backup t\u1EA1i .jai1_backup/`));
|
|
2158
|
-
const cleanBackups = await
|
|
2324
|
+
const cleanBackups = await confirm2({ message: "X\xF3a c\xE1c backup n\xE0y?", default: false });
|
|
2159
2325
|
if (cleanBackups) {
|
|
2160
2326
|
await componentsService.clearBackups(process.cwd());
|
|
2161
2327
|
console.log(chalk4.green("\u{1F5D1}\uFE0F \u0110\xE3 x\xF3a backups."));
|
|
@@ -2170,11 +2336,11 @@ async function handleUpdate(options) {
|
|
|
2170
2336
|
}
|
|
2171
2337
|
|
|
2172
2338
|
// src/commands/framework/check.ts
|
|
2173
|
-
import { Command as
|
|
2339
|
+
import { Command as Command7 } from "commander";
|
|
2174
2340
|
import chalk5 from "chalk";
|
|
2175
2341
|
import Table from "cli-table3";
|
|
2176
2342
|
function createCheckCommand() {
|
|
2177
|
-
const cmd = new
|
|
2343
|
+
const cmd = new Command7("check").description("Ki\u1EC3m tra c\u1EADp nh\u1EADt framework").option("--json", "Output as JSON").action(async (options) => {
|
|
2178
2344
|
await handleCheck(options);
|
|
2179
2345
|
});
|
|
2180
2346
|
return cmd;
|
|
@@ -2289,7 +2455,7 @@ import { Command as Command11 } from "commander";
|
|
|
2289
2455
|
import chalk7 from "chalk";
|
|
2290
2456
|
|
|
2291
2457
|
// src/commands/context.ts
|
|
2292
|
-
import { Command as
|
|
2458
|
+
import { Command as Command8 } from "commander";
|
|
2293
2459
|
import chalk6 from "chalk";
|
|
2294
2460
|
|
|
2295
2461
|
// src/services/context-scanner.service.ts
|
|
@@ -2797,7 +2963,7 @@ function renderIDEContext(ideContext) {
|
|
|
2797
2963
|
console.log("");
|
|
2798
2964
|
}
|
|
2799
2965
|
function createContextCommand() {
|
|
2800
|
-
const cmd = new
|
|
2966
|
+
const cmd = new Command8("context").description("Visualize IDE context window token budget").argument("[ide]", "Show specific IDE only (cursor, windsurf, antigravity, claudecode, opencode)").action(async (ideArg) => {
|
|
2801
2967
|
const name = getCliName();
|
|
2802
2968
|
const allIDEs = ["cursor", "windsurf", "antigravity", "claudecode", "opencode"];
|
|
2803
2969
|
if (ideArg) {
|
|
@@ -2841,30 +3007,11 @@ function createContextSubcommand() {
|
|
|
2841
3007
|
}
|
|
2842
3008
|
|
|
2843
3009
|
// src/commands/ide/setup.ts
|
|
2844
|
-
import { Command as
|
|
2845
|
-
import { checkbox, confirm as
|
|
3010
|
+
import { Command as Command9 } from "commander";
|
|
3011
|
+
import { checkbox as checkbox2, confirm as confirm3, select } from "@inquirer/prompts";
|
|
2846
3012
|
import fs5 from "fs/promises";
|
|
2847
3013
|
import path3 from "path";
|
|
2848
3014
|
import { existsSync } from "fs";
|
|
2849
|
-
|
|
2850
|
-
// src/utils/prompt-theme.ts
|
|
2851
|
-
var keysHelpTipWithQuit = (keys) => {
|
|
2852
|
-
const keyStrings = keys.map(([key, action]) => `${key} ${action}`);
|
|
2853
|
-
keyStrings.push("Ctrl+C quit");
|
|
2854
|
-
return keyStrings.join(" \u2022 ");
|
|
2855
|
-
};
|
|
2856
|
-
var checkboxTheme = {
|
|
2857
|
-
style: {
|
|
2858
|
-
keysHelpTip: keysHelpTipWithQuit
|
|
2859
|
-
}
|
|
2860
|
-
};
|
|
2861
|
-
var selectTheme = {
|
|
2862
|
-
style: {
|
|
2863
|
-
keysHelpTip: keysHelpTipWithQuit
|
|
2864
|
-
}
|
|
2865
|
-
};
|
|
2866
|
-
|
|
2867
|
-
// src/commands/ide/setup.ts
|
|
2868
3015
|
var PERFORMANCE_GROUPS = {
|
|
2869
3016
|
telemetry: {
|
|
2870
3017
|
name: "Telemetry",
|
|
@@ -3000,7 +3147,7 @@ var PERFORMANCE_GROUPS = {
|
|
|
3000
3147
|
}
|
|
3001
3148
|
};
|
|
3002
3149
|
function createSetupSubcommand() {
|
|
3003
|
-
const setupCommand = new
|
|
3150
|
+
const setupCommand = new Command9("setup").description("Configure IDE settings and optimizations");
|
|
3004
3151
|
setupCommand.action(async () => {
|
|
3005
3152
|
await interactiveMode();
|
|
3006
3153
|
});
|
|
@@ -3069,7 +3216,7 @@ async function selectGroupsToApply(action) {
|
|
|
3069
3216
|
value: key
|
|
3070
3217
|
}));
|
|
3071
3218
|
try {
|
|
3072
|
-
const selectedGroups = await
|
|
3219
|
+
const selectedGroups = await checkbox2({
|
|
3073
3220
|
message: `Select groups to ${action} (SPACE to select, ENTER to confirm):`,
|
|
3074
3221
|
choices,
|
|
3075
3222
|
theme: checkboxTheme
|
|
@@ -3106,7 +3253,7 @@ async function applyGroups(groupKeys, action) {
|
|
|
3106
3253
|
console.log("\u{1F4C4} Read current settings from settings.json");
|
|
3107
3254
|
} catch {
|
|
3108
3255
|
console.warn("\u26A0\uFE0F Cannot read settings.json (may contain comments).");
|
|
3109
|
-
const confirmOverwrite = await
|
|
3256
|
+
const confirmOverwrite = await confirm3({
|
|
3110
3257
|
message: "Overwrite current settings.json file?",
|
|
3111
3258
|
default: false
|
|
3112
3259
|
});
|
|
@@ -3153,7 +3300,7 @@ async function resetSettings(groupKeys) {
|
|
|
3153
3300
|
console.log("\n\u26A0\uFE0F No settings.json file found");
|
|
3154
3301
|
return;
|
|
3155
3302
|
}
|
|
3156
|
-
const confirmReset = await
|
|
3303
|
+
const confirmReset = await confirm3({
|
|
3157
3304
|
message: groupKeys.length === 0 ? "Reset ALL settings to default (delete entire file)?" : `Reset groups: ${groupKeys.join(", ")}?`,
|
|
3158
3305
|
default: false
|
|
3159
3306
|
});
|
|
@@ -3170,132 +3317,6 @@ async function resetSettings(groupKeys) {
|
|
|
3170
3317
|
console.log("\u{1F4A1} Tip: Restart your IDE to apply changes.");
|
|
3171
3318
|
}
|
|
3172
3319
|
|
|
3173
|
-
// src/commands/ide/sync.ts
|
|
3174
|
-
import { Command as Command9 } from "commander";
|
|
3175
|
-
import { checkbox as checkbox2, confirm as confirm3 } from "@inquirer/prompts";
|
|
3176
|
-
function createSyncSubcommand() {
|
|
3177
|
-
const cmd = new Command9("sync").description("Sync .jai1 content to IDE directories (Cursor, Windsurf, Claude Code, etc.)").option("--ides <ides...>", "Target IDEs (cursor, windsurf, antigravity, claudecode, opencode)").option("--type <types...>", "Content types (rules, workflows, commands)").option("--dry-run", "Preview changes without writing files").option("-y, --yes", "Headless mode (skip all prompts)").option("--all", "Select all available IDEs").action(async (options) => {
|
|
3178
|
-
await runSync(options);
|
|
3179
|
-
});
|
|
3180
|
-
return cmd;
|
|
3181
|
-
}
|
|
3182
|
-
async function runSync(options) {
|
|
3183
|
-
const service = new MigrateIdeService();
|
|
3184
|
-
const headless = options.yes === true;
|
|
3185
|
-
console.log("\n\u{1F504} Sync rules and workflows to IDE(s)\n");
|
|
3186
|
-
console.log("\u{1F4C1} Scanning .jai1/ directory...");
|
|
3187
|
-
console.log(" \u2022 .jai1/rule-preset/ (active rule preset)");
|
|
3188
|
-
console.log(" \u2022 .jai1/rules/ (manual rules)");
|
|
3189
|
-
console.log(" \u2022 .jai1/workflows/\n");
|
|
3190
|
-
const content = await service.scanJai1Content();
|
|
3191
|
-
if (content.totalCount === 0) {
|
|
3192
|
-
console.log("\u26A0\uFE0F No content found in .jai1/");
|
|
3193
|
-
console.log(' \u{1F4A1} Run "jai1 rules apply" to apply a rule preset, or');
|
|
3194
|
-
console.log(" \u{1F4A1} Create files in .jai1/rules/ or .jai1/workflows/\n");
|
|
3195
|
-
process.exit(1);
|
|
3196
|
-
}
|
|
3197
|
-
console.log(`\u2713 Found: ${content.rules.length} rules, ${content.workflows.length} workflows
|
|
3198
|
-
`);
|
|
3199
|
-
let selectedIdes;
|
|
3200
|
-
if (options.all) {
|
|
3201
|
-
selectedIdes = getMigrationIDEs();
|
|
3202
|
-
} else if (options.ides && options.ides.length > 0) {
|
|
3203
|
-
selectedIdes = options.ides;
|
|
3204
|
-
} else if (headless) {
|
|
3205
|
-
throw new Error(
|
|
3206
|
-
"Headless mode (-y) requires --ides or --all flag.\nExamples:\n j ide sync --ides cursor windsurf -y\n j ide sync --all -y"
|
|
3207
|
-
);
|
|
3208
|
-
} else {
|
|
3209
|
-
const ideChoices = getMigrationIDEs().map((ide) => {
|
|
3210
|
-
const config = IDE_MIGRATION_CONFIGS[ide];
|
|
3211
|
-
return {
|
|
3212
|
-
name: `${config.icon} ${config.name}`,
|
|
3213
|
-
value: ide
|
|
3214
|
-
};
|
|
3215
|
-
});
|
|
3216
|
-
selectedIdes = await checkbox2({
|
|
3217
|
-
message: "Select target IDE(s) (SPACE to select, ENTER to confirm):",
|
|
3218
|
-
choices: ideChoices,
|
|
3219
|
-
theme: checkboxTheme
|
|
3220
|
-
});
|
|
3221
|
-
if (selectedIdes.length === 0) {
|
|
3222
|
-
console.log("\n\u26A0\uFE0F No IDE selected!");
|
|
3223
|
-
console.log(" \u{1F4A1} Select at least 1 IDE.\n");
|
|
3224
|
-
process.exit(0);
|
|
3225
|
-
}
|
|
3226
|
-
}
|
|
3227
|
-
let selectedTypes;
|
|
3228
|
-
if (options.type && options.type.length > 0) {
|
|
3229
|
-
selectedTypes = options.type;
|
|
3230
|
-
} else if (headless) {
|
|
3231
|
-
selectedTypes = ["rules", "workflows", "commands"];
|
|
3232
|
-
} else {
|
|
3233
|
-
const typeChoices = [
|
|
3234
|
-
{ name: `Rules (${content.rules.length} files)`, value: "rules" },
|
|
3235
|
-
{ name: `Workflows (${content.workflows.length} files)`, value: "workflows" },
|
|
3236
|
-
{ name: `Commands (${content.commands.length} files)`, value: "commands" }
|
|
3237
|
-
];
|
|
3238
|
-
selectedTypes = await checkbox2({
|
|
3239
|
-
message: "Select content types to sync:",
|
|
3240
|
-
choices: typeChoices,
|
|
3241
|
-
theme: checkboxTheme
|
|
3242
|
-
});
|
|
3243
|
-
if (selectedTypes.length === 0) {
|
|
3244
|
-
console.log("\n\u26A0\uFE0F No content type selected!");
|
|
3245
|
-
console.log(" \u{1F4A1} Select at least 1 content type.\n");
|
|
3246
|
-
process.exit(0);
|
|
3247
|
-
}
|
|
3248
|
-
}
|
|
3249
|
-
const totalItems = selectedTypes.reduce((sum, type) => {
|
|
3250
|
-
return sum + (type === "rules" ? content.rules.length : type === "workflows" ? content.workflows.length : content.commands.length);
|
|
3251
|
-
}, 0);
|
|
3252
|
-
const totalFiles = totalItems * selectedIdes.length;
|
|
3253
|
-
console.log("\n\u{1F4CA} Preview:\n");
|
|
3254
|
-
console.log(` IDEs: ${selectedIdes.map((ide) => IDE_MIGRATION_CONFIGS[ide].name).join(", ")}`);
|
|
3255
|
-
console.log(` Content types: ${selectedTypes.join(", ")}`);
|
|
3256
|
-
console.log(` Will create/update: ${totalFiles} stub files
|
|
3257
|
-
`);
|
|
3258
|
-
if (options.dryRun) {
|
|
3259
|
-
console.log("\u{1F50D} DRY RUN - No files will be written\n");
|
|
3260
|
-
}
|
|
3261
|
-
if (!headless) {
|
|
3262
|
-
const confirmed = await confirm3({
|
|
3263
|
-
message: "Proceed with sync?",
|
|
3264
|
-
default: true
|
|
3265
|
-
});
|
|
3266
|
-
if (!confirmed) {
|
|
3267
|
-
console.log("\n\u274C Sync cancelled.\n");
|
|
3268
|
-
process.exit(0);
|
|
3269
|
-
}
|
|
3270
|
-
}
|
|
3271
|
-
console.log("\n\u{1F504} Syncing...\n");
|
|
3272
|
-
let completed = 0;
|
|
3273
|
-
const results = await service.migrate(
|
|
3274
|
-
selectedIdes,
|
|
3275
|
-
selectedTypes,
|
|
3276
|
-
content,
|
|
3277
|
-
(result) => {
|
|
3278
|
-
completed++;
|
|
3279
|
-
const icon = result.status === "created" ? "\u2713" : result.status === "updated" ? "\u21BB" : result.status === "error" ? "\u2717" : "\u25CB";
|
|
3280
|
-
const percentage = Math.round(completed / totalFiles * 100);
|
|
3281
|
-
console.log(` ${icon} [${percentage}%] ${result.targetPath}`);
|
|
3282
|
-
if (result.status === "error" && result.error) {
|
|
3283
|
-
console.log(` Error: ${result.error}`);
|
|
3284
|
-
}
|
|
3285
|
-
}
|
|
3286
|
-
);
|
|
3287
|
-
const created = results.filter((r) => r.status === "created").length;
|
|
3288
|
-
const updated = results.filter((r) => r.status === "updated").length;
|
|
3289
|
-
const skipped = results.filter((r) => r.status === "skipped").length;
|
|
3290
|
-
const errors = results.filter((r) => r.status === "error").length;
|
|
3291
|
-
console.log("\n\u2705 Sync complete!\n");
|
|
3292
|
-
console.log(` Created: ${created}`);
|
|
3293
|
-
console.log(` Updated: ${updated}`);
|
|
3294
|
-
if (skipped > 0) console.log(` Skipped: ${skipped}`);
|
|
3295
|
-
if (errors > 0) console.log(` Errors: ${errors}`);
|
|
3296
|
-
console.log("");
|
|
3297
|
-
}
|
|
3298
|
-
|
|
3299
3320
|
// src/commands/ide/status.ts
|
|
3300
3321
|
import { Command as Command10 } from "commander";
|
|
3301
3322
|
|
|
@@ -17100,10 +17121,11 @@ function showCustomHelp(version) {
|
|
|
17100
17121
|
console.log(" rules Qu\u1EA3n l\xFD rule presets");
|
|
17101
17122
|
console.log(" deps Qu\u1EA3n l\xFD dependencies");
|
|
17102
17123
|
console.log(" redmine Redmine context sync");
|
|
17124
|
+
console.log(chalk57.bold("\n\u{1F6E0}\uFE0F Utilities"));
|
|
17125
|
+
console.log(" utils Developer utilities");
|
|
17103
17126
|
console.log(chalk57.bold("\n\u2699\uFE0F B\u1EA3o tr\xEC"));
|
|
17104
17127
|
console.log(" upgrade C\u1EADp nh\u1EADt CLI client");
|
|
17105
17128
|
console.log(" clean D\u1ECDn d\u1EB9p cache/backup");
|
|
17106
|
-
console.log(" utils Developer utilities");
|
|
17107
17129
|
const name = getCliName();
|
|
17108
17130
|
console.log(chalk57.dim(`
|
|
17109
17131
|
S\u1EED d\u1EE5ng: ${name} [l\u1EC7nh] --help \u0111\u1EC3 xem chi ti\u1EBFt`));
|