@jvittechs/j 1.0.15 → 1.0.16
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 +62 -34
- 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.16",
|
|
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: {
|
|
@@ -2966,57 +2966,86 @@ var ContextScannerService = class {
|
|
|
2966
2966
|
var MAX_TOKENS = 256e3;
|
|
2967
2967
|
var SYSTEM_PROMPT_TOKENS = 1e4;
|
|
2968
2968
|
var COMPACT_BUFFER_TOKENS = 56e3;
|
|
2969
|
-
var BAR_WIDTH =
|
|
2969
|
+
var BAR_WIDTH = 50;
|
|
2970
2970
|
var CHARS_PER_TOKEN = 4;
|
|
2971
2971
|
function estimateTokens(bytes) {
|
|
2972
2972
|
return Math.ceil(bytes / CHARS_PER_TOKEN);
|
|
2973
2973
|
}
|
|
2974
|
+
function formatTokens(n) {
|
|
2975
|
+
if (n >= 1e3) {
|
|
2976
|
+
const k = n / 1e3;
|
|
2977
|
+
return k % 1 === 0 ? `${k}k` : `${k.toFixed(1)}k`;
|
|
2978
|
+
}
|
|
2979
|
+
return String(n);
|
|
2980
|
+
}
|
|
2974
2981
|
function formatNumber(n) {
|
|
2975
2982
|
return n.toLocaleString("en-US");
|
|
2976
2983
|
}
|
|
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) {
|
|
2984
|
+
function pct(value, total) {
|
|
2983
2985
|
return (value / total * 100).toFixed(1) + "%";
|
|
2984
2986
|
}
|
|
2987
|
+
function renderStackedBar(segments, total, width) {
|
|
2988
|
+
let bar = "";
|
|
2989
|
+
let usedCols = 0;
|
|
2990
|
+
for (let i = 0; i < segments.length; i++) {
|
|
2991
|
+
const seg = segments[i];
|
|
2992
|
+
const isLast = i === segments.length - 1;
|
|
2993
|
+
const cols = isLast ? width - usedCols : Math.round(seg.tokens / total * width);
|
|
2994
|
+
if (cols > 0) {
|
|
2995
|
+
bar += seg.color(seg.char.repeat(cols));
|
|
2996
|
+
usedCols += cols;
|
|
2997
|
+
}
|
|
2998
|
+
}
|
|
2999
|
+
return bar;
|
|
3000
|
+
}
|
|
2985
3001
|
function renderIDEContext(ideContext) {
|
|
2986
3002
|
const { config, items } = ideContext;
|
|
2987
3003
|
const ruleItems = items.filter((item) => item.type === "rules");
|
|
2988
3004
|
const rulesTotalBytes = ruleItems.reduce((sum, item) => sum + item.fileSize, 0);
|
|
2989
3005
|
const rulesTokens = estimateTokens(rulesTotalBytes);
|
|
3006
|
+
const usedTokens = SYSTEM_PROMPT_TOKENS + rulesTokens;
|
|
2990
3007
|
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)));
|
|
3008
|
+
console.log(`${chalk6.dim("\u2514")} ${chalk6.bold("Context Usage")}`);
|
|
2994
3009
|
const segments = [
|
|
2995
|
-
{
|
|
2996
|
-
{
|
|
2997
|
-
{
|
|
2998
|
-
{
|
|
3010
|
+
{ tokens: SYSTEM_PROMPT_TOKENS, char: "\u2593", color: chalk6.yellow },
|
|
3011
|
+
{ tokens: rulesTokens, char: "\u2593", color: chalk6.red },
|
|
3012
|
+
{ tokens: userPromptTokens, char: "\u2591", color: chalk6.dim },
|
|
3013
|
+
{ tokens: COMPACT_BUFFER_TOKENS, char: "\u2592", color: chalk6.magenta }
|
|
3014
|
+
];
|
|
3015
|
+
const barLine = renderStackedBar(segments, MAX_TOKENS, BAR_WIDTH);
|
|
3016
|
+
const summary = `${config.icon} ${config.name} \xB7 ${formatTokens(usedTokens)}/${formatTokens(MAX_TOKENS)} tokens (${pct(usedTokens, MAX_TOKENS)})`;
|
|
3017
|
+
console.log(` ${barLine} ${chalk6.bold(summary)}`);
|
|
3018
|
+
const legendItems = [
|
|
3019
|
+
{ icon: "\u{1F7E1}", label: "System prompt", tokens: SYSTEM_PROMPT_TOKENS },
|
|
3020
|
+
{ icon: "\u{1F534}", label: "IDE Rules", tokens: rulesTokens },
|
|
3021
|
+
{ icon: "\u2B1C", label: "Free space", tokens: userPromptTokens },
|
|
3022
|
+
{ icon: "\u{1F7E3}", label: "Autocompact buffer", tokens: COMPACT_BUFFER_TOKENS }
|
|
2999
3023
|
];
|
|
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})`)}`);
|
|
3024
|
+
const pad = " ".repeat(BAR_WIDTH + 5);
|
|
3025
|
+
for (const item of legendItems) {
|
|
3026
|
+
console.log(`${pad} ${item.icon} ${item.label}: ${formatTokens(item.tokens)} tokens (${pct(item.tokens, MAX_TOKENS)})`);
|
|
3006
3027
|
}
|
|
3007
3028
|
if (ruleItems.length > 0) {
|
|
3008
3029
|
console.log("");
|
|
3009
|
-
console.log(chalk6.
|
|
3030
|
+
console.log(` ${chalk6.bold("Rules")} ${chalk6.dim(`\xB7 ${config.basePath}/rules`)}`);
|
|
3010
3031
|
const sorted = [...ruleItems].sort((a, b) => b.fileSize - a.fileSize);
|
|
3011
3032
|
for (const rule of sorted) {
|
|
3012
3033
|
const tokens = estimateTokens(rule.fileSize);
|
|
3013
3034
|
const name = typeof rule.name === "string" ? rule.name : rule.relativePath;
|
|
3014
|
-
const badge = rule.alwaysApply ? chalk6.
|
|
3015
|
-
console.log(`
|
|
3035
|
+
const badge = rule.alwaysApply ? chalk6.dim(" [always]") : "";
|
|
3036
|
+
console.log(` ${chalk6.dim("\u2514")} ${name}${badge}: ${formatNumber(tokens)} tokens`);
|
|
3016
3037
|
}
|
|
3017
|
-
}
|
|
3038
|
+
}
|
|
3039
|
+
const workflowItems = items.filter((item) => item.type === "workflows");
|
|
3040
|
+
if (workflowItems.length > 0) {
|
|
3018
3041
|
console.log("");
|
|
3019
|
-
console.log(chalk6.
|
|
3042
|
+
console.log(` ${chalk6.bold("Workflows")} ${chalk6.dim(`\xB7 ${config.basePath}/workflows`)}`);
|
|
3043
|
+
const sorted = [...workflowItems].sort((a, b) => b.fileSize - a.fileSize);
|
|
3044
|
+
for (const wf of sorted) {
|
|
3045
|
+
const tokens = estimateTokens(wf.fileSize);
|
|
3046
|
+
const name = typeof wf.name === "string" ? wf.name : wf.relativePath;
|
|
3047
|
+
console.log(` ${chalk6.dim("\u2514")} ${name}: ${formatNumber(tokens)} tokens`);
|
|
3048
|
+
}
|
|
3020
3049
|
}
|
|
3021
3050
|
console.log("");
|
|
3022
3051
|
}
|
|
@@ -3034,9 +3063,8 @@ function createContextCommand() {
|
|
|
3034
3063
|
}
|
|
3035
3064
|
const scanner = new ContextScannerService();
|
|
3036
3065
|
const targetIDEs = ideArg ? [ideArg] : validIDEs;
|
|
3037
|
-
console.log(
|
|
3038
|
-
console.log(chalk6.
|
|
3039
|
-
`));
|
|
3066
|
+
console.log("");
|
|
3067
|
+
console.log(` ${chalk6.bgGray.white.bold(" /context ")}`);
|
|
3040
3068
|
let found = false;
|
|
3041
3069
|
for (const ide of targetIDEs) {
|
|
3042
3070
|
try {
|
|
@@ -3050,8 +3078,8 @@ function createContextCommand() {
|
|
|
3050
3078
|
}
|
|
3051
3079
|
}
|
|
3052
3080
|
if (!found) {
|
|
3053
|
-
console.log(chalk6.yellow("\u26A0\uFE0F No IDEs detected in this project."));
|
|
3054
|
-
console.log(chalk6.dim(`
|
|
3081
|
+
console.log(chalk6.yellow(" \u26A0\uFE0F No IDEs detected in this project."));
|
|
3082
|
+
console.log(chalk6.dim(` Run "${name} apply" to install context for your IDE.
|
|
3055
3083
|
`));
|
|
3056
3084
|
}
|
|
3057
3085
|
});
|
|
@@ -4899,9 +4927,9 @@ var ChatApp = ({ service, initialModel }) => {
|
|
|
4899
4927
|
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
4928
|
const limit = m.dailyLimit ?? 0;
|
|
4901
4929
|
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:
|
|
4930
|
+
const pct2 = limit > 0 ? Math.round(used / limit * 100) : 0;
|
|
4931
|
+
const bar = "\u2588".repeat(Math.round(pct2 / 5)) + "\u2591".repeat(20 - Math.round(pct2 / 5));
|
|
4932
|
+
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
4933
|
}), /* @__PURE__ */ React11.createElement(Text9, { dimColor: true }, "[Esc] Back"));
|
|
4906
4934
|
}, [models, selectedModel]);
|
|
4907
4935
|
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";
|