@jvittechs/j 1.0.15 → 1.0.17
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 +89 -47
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -169,7 +169,7 @@ import { basename as basename4 } from "path";
|
|
|
169
169
|
// package.json
|
|
170
170
|
var package_default = {
|
|
171
171
|
name: "@jvittechs/j",
|
|
172
|
-
version: "1.0.
|
|
172
|
+
version: "1.0.17",
|
|
173
173
|
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.",
|
|
174
174
|
type: "module",
|
|
175
175
|
bin: {
|
|
@@ -1140,6 +1140,15 @@ function getMigrationIDEs() {
|
|
|
1140
1140
|
return Object.keys(IDE_MIGRATION_CONFIGS);
|
|
1141
1141
|
}
|
|
1142
1142
|
|
|
1143
|
+
// src/utils/heading-utils.ts
|
|
1144
|
+
function downshiftHeadings(content) {
|
|
1145
|
+
return content.replace(/^(#{1,5})\s/gm, (_match, hashes) => "#" + hashes + " ");
|
|
1146
|
+
}
|
|
1147
|
+
function extractBody(content) {
|
|
1148
|
+
const match = content.match(/^---\n[\s\S]*?\n---\n?([\s\S]*)$/);
|
|
1149
|
+
return match ? match[1].trim() : content.trim();
|
|
1150
|
+
}
|
|
1151
|
+
|
|
1143
1152
|
// src/services/migrate-ide.service.ts
|
|
1144
1153
|
var MigrateIdeService = class {
|
|
1145
1154
|
projectPath;
|
|
@@ -1248,9 +1257,10 @@ var MigrateIdeService = class {
|
|
|
1248
1257
|
return items;
|
|
1249
1258
|
}
|
|
1250
1259
|
/**
|
|
1251
|
-
* Generate
|
|
1260
|
+
* Generate copied content for IDE rule file.
|
|
1261
|
+
* Reads the actual source file and combines IDE-specific frontmatter with the body content.
|
|
1252
1262
|
*/
|
|
1253
|
-
|
|
1263
|
+
async generateCopiedContent(ide, sourceItem) {
|
|
1254
1264
|
const config = IDE_MIGRATION_CONFIGS[ide];
|
|
1255
1265
|
if (!config) throw new Error(`Unknown IDE: ${ide}`);
|
|
1256
1266
|
const frontmatter = config.generateFrontmatter({
|
|
@@ -1260,14 +1270,15 @@ var MigrateIdeService = class {
|
|
|
1260
1270
|
alwaysApply: sourceItem.alwaysApply,
|
|
1261
1271
|
sourceFile: sourceItem.relativePath
|
|
1262
1272
|
});
|
|
1263
|
-
const
|
|
1273
|
+
const sourceContent = await fs5.readFile(sourceItem.filepath, "utf-8");
|
|
1274
|
+
const bodyContent = extractBody(sourceContent);
|
|
1264
1275
|
if (frontmatter) {
|
|
1265
1276
|
return `${frontmatter}
|
|
1266
1277
|
|
|
1267
|
-
${
|
|
1278
|
+
${bodyContent}
|
|
1268
1279
|
`;
|
|
1269
1280
|
}
|
|
1270
|
-
return `${
|
|
1281
|
+
return `${bodyContent}
|
|
1271
1282
|
`;
|
|
1272
1283
|
}
|
|
1273
1284
|
/**
|
|
@@ -1316,7 +1327,12 @@ ${reference}
|
|
|
1316
1327
|
""
|
|
1317
1328
|
];
|
|
1318
1329
|
for (const rule of rules) {
|
|
1319
|
-
|
|
1330
|
+
const content = await fs5.readFile(rule.filepath, "utf-8");
|
|
1331
|
+
const body = extractBody(content);
|
|
1332
|
+
if (body.trim()) {
|
|
1333
|
+
lines.push(downshiftHeadings(body));
|
|
1334
|
+
lines.push("");
|
|
1335
|
+
}
|
|
1320
1336
|
}
|
|
1321
1337
|
lines.push("");
|
|
1322
1338
|
await fs5.writeFile(agentsPath, lines.join("\n"), "utf-8");
|
|
@@ -1372,8 +1388,8 @@ ${reference}
|
|
|
1372
1388
|
status = "updated";
|
|
1373
1389
|
} catch {
|
|
1374
1390
|
}
|
|
1375
|
-
const
|
|
1376
|
-
await fs5.writeFile(targetPath,
|
|
1391
|
+
const copiedContent = await this.generateCopiedContent(ide, item);
|
|
1392
|
+
await fs5.writeFile(targetPath, copiedContent, "utf-8");
|
|
1377
1393
|
return {
|
|
1378
1394
|
source: item,
|
|
1379
1395
|
targetIDE: ide,
|
|
@@ -2966,57 +2982,86 @@ var ContextScannerService = class {
|
|
|
2966
2982
|
var MAX_TOKENS = 256e3;
|
|
2967
2983
|
var SYSTEM_PROMPT_TOKENS = 1e4;
|
|
2968
2984
|
var COMPACT_BUFFER_TOKENS = 56e3;
|
|
2969
|
-
var BAR_WIDTH =
|
|
2985
|
+
var BAR_WIDTH = 50;
|
|
2970
2986
|
var CHARS_PER_TOKEN = 4;
|
|
2971
2987
|
function estimateTokens(bytes) {
|
|
2972
2988
|
return Math.ceil(bytes / CHARS_PER_TOKEN);
|
|
2973
2989
|
}
|
|
2990
|
+
function formatTokens(n) {
|
|
2991
|
+
if (n >= 1e3) {
|
|
2992
|
+
const k = n / 1e3;
|
|
2993
|
+
return k % 1 === 0 ? `${k}k` : `${k.toFixed(1)}k`;
|
|
2994
|
+
}
|
|
2995
|
+
return String(n);
|
|
2996
|
+
}
|
|
2974
2997
|
function formatNumber(n) {
|
|
2975
2998
|
return n.toLocaleString("en-US");
|
|
2976
2999
|
}
|
|
2977
|
-
function
|
|
2978
|
-
const filled = Math.round(value / total * width);
|
|
2979
|
-
const empty = width - filled;
|
|
2980
|
-
return color("\u2588".repeat(filled)) + chalk6.gray("\u2591".repeat(empty));
|
|
2981
|
-
}
|
|
2982
|
-
function renderPercentage(value, total) {
|
|
3000
|
+
function pct(value, total) {
|
|
2983
3001
|
return (value / total * 100).toFixed(1) + "%";
|
|
2984
3002
|
}
|
|
3003
|
+
function renderStackedBar(segments, total, width) {
|
|
3004
|
+
let bar = "";
|
|
3005
|
+
let usedCols = 0;
|
|
3006
|
+
for (let i = 0; i < segments.length; i++) {
|
|
3007
|
+
const seg = segments[i];
|
|
3008
|
+
const isLast = i === segments.length - 1;
|
|
3009
|
+
const cols = isLast ? width - usedCols : Math.round(seg.tokens / total * width);
|
|
3010
|
+
if (cols > 0) {
|
|
3011
|
+
bar += seg.color(seg.char.repeat(cols));
|
|
3012
|
+
usedCols += cols;
|
|
3013
|
+
}
|
|
3014
|
+
}
|
|
3015
|
+
return bar;
|
|
3016
|
+
}
|
|
2985
3017
|
function renderIDEContext(ideContext) {
|
|
2986
3018
|
const { config, items } = ideContext;
|
|
2987
3019
|
const ruleItems = items.filter((item) => item.type === "rules");
|
|
2988
3020
|
const rulesTotalBytes = ruleItems.reduce((sum, item) => sum + item.fileSize, 0);
|
|
2989
3021
|
const rulesTokens = estimateTokens(rulesTotalBytes);
|
|
3022
|
+
const usedTokens = SYSTEM_PROMPT_TOKENS + rulesTokens;
|
|
2990
3023
|
const userPromptTokens = Math.max(0, MAX_TOKENS - SYSTEM_PROMPT_TOKENS - rulesTokens - COMPACT_BUFFER_TOKENS);
|
|
2991
|
-
console.log("");
|
|
2992
|
-
console.log(chalk6.bold(`${config.icon} ${config.name} Context Window (${formatNumber(MAX_TOKENS)} tokens)`));
|
|
2993
|
-
console.log(chalk6.dim("\u2501".repeat(55)));
|
|
3024
|
+
console.log(`${chalk6.dim("\u2514")} ${chalk6.bold("Context Usage")}`);
|
|
2994
3025
|
const segments = [
|
|
2995
|
-
{
|
|
2996
|
-
{
|
|
2997
|
-
{
|
|
2998
|
-
{
|
|
3026
|
+
{ tokens: SYSTEM_PROMPT_TOKENS, char: "\u2593", color: chalk6.yellow },
|
|
3027
|
+
{ tokens: rulesTokens, char: "\u2593", color: chalk6.red },
|
|
3028
|
+
{ tokens: userPromptTokens, char: "\u2591", color: chalk6.dim },
|
|
3029
|
+
{ tokens: COMPACT_BUFFER_TOKENS, char: "\u2592", color: chalk6.magenta }
|
|
3030
|
+
];
|
|
3031
|
+
const barLine = renderStackedBar(segments, MAX_TOKENS, BAR_WIDTH);
|
|
3032
|
+
const summary = `${config.icon} ${config.name} \xB7 ${formatTokens(usedTokens)}/${formatTokens(MAX_TOKENS)} tokens (${pct(usedTokens, MAX_TOKENS)})`;
|
|
3033
|
+
console.log(` ${barLine} ${chalk6.bold(summary)}`);
|
|
3034
|
+
const legendItems = [
|
|
3035
|
+
{ icon: "\u{1F7E1}", label: "System prompt", tokens: SYSTEM_PROMPT_TOKENS },
|
|
3036
|
+
{ icon: "\u{1F534}", label: "IDE Rules", tokens: rulesTokens },
|
|
3037
|
+
{ icon: "\u2B1C", label: "Free space", tokens: userPromptTokens },
|
|
3038
|
+
{ icon: "\u{1F7E3}", label: "Autocompact buffer", tokens: COMPACT_BUFFER_TOKENS }
|
|
2999
3039
|
];
|
|
3000
|
-
const
|
|
3001
|
-
for (const
|
|
3002
|
-
|
|
3003
|
-
const bar = renderBar(seg.tokens, MAX_TOKENS, BAR_WIDTH, seg.color);
|
|
3004
|
-
const pct = renderPercentage(seg.tokens, MAX_TOKENS);
|
|
3005
|
-
console.log(` ${seg.icon} ${label} ${bar} ${chalk6.white(formatNumber(seg.tokens).padStart(7))} tokens ${chalk6.dim(`(${pct})`)}`);
|
|
3040
|
+
const pad = " ".repeat(BAR_WIDTH + 5);
|
|
3041
|
+
for (const item of legendItems) {
|
|
3042
|
+
console.log(`${pad} ${item.icon} ${item.label}: ${formatTokens(item.tokens)} tokens (${pct(item.tokens, MAX_TOKENS)})`);
|
|
3006
3043
|
}
|
|
3007
3044
|
if (ruleItems.length > 0) {
|
|
3008
3045
|
console.log("");
|
|
3009
|
-
console.log(chalk6.
|
|
3046
|
+
console.log(` ${chalk6.bold("Rules")} ${chalk6.dim(`\xB7 ${config.basePath}/rules`)}`);
|
|
3010
3047
|
const sorted = [...ruleItems].sort((a, b) => b.fileSize - a.fileSize);
|
|
3011
3048
|
for (const rule of sorted) {
|
|
3012
3049
|
const tokens = estimateTokens(rule.fileSize);
|
|
3013
3050
|
const name = typeof rule.name === "string" ? rule.name : rule.relativePath;
|
|
3014
|
-
const badge = rule.alwaysApply ? chalk6.
|
|
3015
|
-
console.log(`
|
|
3051
|
+
const badge = rule.alwaysApply ? chalk6.dim(" [always]") : "";
|
|
3052
|
+
console.log(` ${chalk6.dim("\u2514")} ${name}${badge}: ${formatNumber(tokens)} tokens`);
|
|
3016
3053
|
}
|
|
3017
|
-
}
|
|
3054
|
+
}
|
|
3055
|
+
const workflowItems = items.filter((item) => item.type === "workflows");
|
|
3056
|
+
if (workflowItems.length > 0) {
|
|
3018
3057
|
console.log("");
|
|
3019
|
-
console.log(chalk6.
|
|
3058
|
+
console.log(` ${chalk6.bold("Workflows")} ${chalk6.dim(`\xB7 ${config.basePath}/workflows`)}`);
|
|
3059
|
+
const sorted = [...workflowItems].sort((a, b) => b.fileSize - a.fileSize);
|
|
3060
|
+
for (const wf of sorted) {
|
|
3061
|
+
const tokens = estimateTokens(wf.fileSize);
|
|
3062
|
+
const name = typeof wf.name === "string" ? wf.name : wf.relativePath;
|
|
3063
|
+
console.log(` ${chalk6.dim("\u2514")} ${name}: ${formatNumber(tokens)} tokens`);
|
|
3064
|
+
}
|
|
3020
3065
|
}
|
|
3021
3066
|
console.log("");
|
|
3022
3067
|
}
|
|
@@ -3034,9 +3079,8 @@ function createContextCommand() {
|
|
|
3034
3079
|
}
|
|
3035
3080
|
const scanner = new ContextScannerService();
|
|
3036
3081
|
const targetIDEs = ideArg ? [ideArg] : validIDEs;
|
|
3037
|
-
console.log(
|
|
3038
|
-
console.log(chalk6.
|
|
3039
|
-
`));
|
|
3082
|
+
console.log("");
|
|
3083
|
+
console.log(` ${chalk6.bgGray.white.bold(" /context ")}`);
|
|
3040
3084
|
let found = false;
|
|
3041
3085
|
for (const ide of targetIDEs) {
|
|
3042
3086
|
try {
|
|
@@ -3050,8 +3094,8 @@ function createContextCommand() {
|
|
|
3050
3094
|
}
|
|
3051
3095
|
}
|
|
3052
3096
|
if (!found) {
|
|
3053
|
-
console.log(chalk6.yellow("\u26A0\uFE0F No IDEs detected in this project."));
|
|
3054
|
-
console.log(chalk6.dim(`
|
|
3097
|
+
console.log(chalk6.yellow(" \u26A0\uFE0F No IDEs detected in this project."));
|
|
3098
|
+
console.log(chalk6.dim(` Run "${name} apply" to install context for your IDE.
|
|
3055
3099
|
`));
|
|
3056
3100
|
}
|
|
3057
3101
|
});
|
|
@@ -4899,9 +4943,9 @@ var ChatApp = ({ service, initialModel }) => {
|
|
|
4899
4943
|
return /* @__PURE__ */ React11.createElement(Box8, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", padding: 1 }, /* @__PURE__ */ React11.createElement(Text9, { bold: true, color: "cyan" }, "\u{1F4CA} Model Usage Statistics"), allowed.map((m) => {
|
|
4900
4944
|
const limit = m.dailyLimit ?? 0;
|
|
4901
4945
|
const used = m.usedToday ?? 0;
|
|
4902
|
-
const
|
|
4903
|
-
const bar = "\u2588".repeat(Math.round(
|
|
4904
|
-
return /* @__PURE__ */ React11.createElement(Box8, { key: m.id, flexDirection: "column" }, /* @__PURE__ */ React11.createElement(Text9, { color: m.id === selectedModel ? "yellow" : "white" }, m.id === selectedModel ? "\u25BA " : " ", m.id), /* @__PURE__ */ React11.createElement(Text9, { color:
|
|
4946
|
+
const pct2 = limit > 0 ? Math.round(used / limit * 100) : 0;
|
|
4947
|
+
const bar = "\u2588".repeat(Math.round(pct2 / 5)) + "\u2591".repeat(20 - Math.round(pct2 / 5));
|
|
4948
|
+
return /* @__PURE__ */ React11.createElement(Box8, { key: m.id, flexDirection: "column" }, /* @__PURE__ */ React11.createElement(Text9, { color: m.id === selectedModel ? "yellow" : "white" }, m.id === selectedModel ? "\u25BA " : " ", m.id), /* @__PURE__ */ React11.createElement(Text9, { color: pct2 > 80 ? "red" : pct2 > 50 ? "yellow" : "green" }, " ", bar, " ", /* @__PURE__ */ React11.createElement(Text9, { dimColor: true }, used, "/", limit)));
|
|
4905
4949
|
}), /* @__PURE__ */ React11.createElement(Text9, { dimColor: true }, "[Esc] Back"));
|
|
4906
4950
|
}, [models, selectedModel]);
|
|
4907
4951
|
const footer = currentView === "error" ? "[Enter/r] Retry \u2022 [Esc] Quit" : currentView === "model" || currentView === "stats" ? "[\u2191\u2193] Navigate \u2022 [Enter] Select \u2022 [Esc] Back" : showSlashMenu ? "[\u2191\u2193] Navigate \u2022 [Enter] Select \u2022 [Esc] Cancel" : "[Tab] Next Model \u2022 [/] Commands \u2022 [Esc] Quit";
|
|
@@ -12025,7 +12069,7 @@ ${body.trim()}
|
|
|
12025
12069
|
`;
|
|
12026
12070
|
}
|
|
12027
12071
|
/**
|
|
12028
|
-
* Generate Antigravity format (.md files with trigger metadata +
|
|
12072
|
+
* Generate Antigravity format (.md files with trigger metadata + actual content)
|
|
12029
12073
|
*/
|
|
12030
12074
|
generateAntigravityFiles(bundle, format) {
|
|
12031
12075
|
const files = [];
|
|
@@ -12056,9 +12100,7 @@ ${body.trim()}
|
|
|
12056
12100
|
}
|
|
12057
12101
|
const antigravityFrontmatter = `---
|
|
12058
12102
|
trigger: ${trigger}
|
|
12059
|
-
|
|
12060
|
-
|
|
12061
|
-
@AGENTS.md`;
|
|
12103
|
+
---`;
|
|
12062
12104
|
return `${antigravityFrontmatter}
|
|
12063
12105
|
|
|
12064
12106
|
${body.trim()}
|
|
@@ -12128,7 +12170,7 @@ ${body.trim()}
|
|
|
12128
12170
|
const content = bundle.files[filename];
|
|
12129
12171
|
const withoutFrontmatter = this.removeFrontmatter(content);
|
|
12130
12172
|
if (withoutFrontmatter.trim()) {
|
|
12131
|
-
sections.push(withoutFrontmatter.trim());
|
|
12173
|
+
sections.push(downshiftHeadings(withoutFrontmatter.trim()));
|
|
12132
12174
|
sections.push("\n");
|
|
12133
12175
|
}
|
|
12134
12176
|
}
|