blun-king-cli 2.5.2 → 2.6.1
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/bin/blun.js +75 -19
- package/package.json +1 -1
package/bin/blun.js
CHANGED
|
@@ -495,9 +495,17 @@ async function sendChat(message) {
|
|
|
495
495
|
chatHistory.push({ role: "user", content: message });
|
|
496
496
|
chatHistory.push({ role: "assistant", content: resp.data.answer });
|
|
497
497
|
|
|
498
|
+
// Token tracking
|
|
499
|
+
var inTok = Math.ceil(message.length / 3.5);
|
|
500
|
+
var outTok = Math.ceil((resp.data.answer || "").length / 3.5);
|
|
501
|
+
sessionCost.requests++;
|
|
502
|
+
sessionCost.inputTokensEst += inTok;
|
|
503
|
+
sessionCost.outputTokensEst += outTok;
|
|
504
|
+
|
|
498
505
|
var q = resp.data.quality || {};
|
|
506
|
+
var tokInfo = C.dim + (inTok + outTok) + " tok" + C.reset;
|
|
499
507
|
var meta = resp.data.task_type + "/" + resp.data.role + " " + BOX.dot + " score: " + (q.score || "?") +
|
|
500
|
-
(q.retried ? " " + BOX.dot + " retried" : "");
|
|
508
|
+
(q.retried ? " " + BOX.dot + " retried" : "") + " " + BOX.dot + " " + tokInfo;
|
|
501
509
|
printAnswer(resp.data.answer, meta);
|
|
502
510
|
|
|
503
511
|
// Auto Memory Dream Mode
|
|
@@ -2258,36 +2266,82 @@ async function main() {
|
|
|
2258
2266
|
console.log("");
|
|
2259
2267
|
console.log(C.yellow + " " + BOX.bot + " Working in: " + C.brightWhite + process.cwd() + C.reset);
|
|
2260
2268
|
console.log(C.gray + " Do you trust this folder? BLUN King will read/write files here." + C.reset);
|
|
2261
|
-
console.log(
|
|
2269
|
+
console.log("");
|
|
2270
|
+
|
|
2271
|
+
var trustOptions = [
|
|
2272
|
+
{ label: "Yes, trust this folder", action: "trust" },
|
|
2273
|
+
{ label: "Always trust this folder", action: "always" },
|
|
2274
|
+
{ label: "Choose another folder", action: "choose" }
|
|
2275
|
+
];
|
|
2276
|
+
var trustSel = 0;
|
|
2277
|
+
|
|
2278
|
+
// Arrow key menu for trust selection
|
|
2279
|
+
var trustChoice = await new Promise(function(resolve) {
|
|
2280
|
+
function renderTrustMenu() {
|
|
2281
|
+
// Move up and clear previous menu
|
|
2282
|
+
if (trustSel >= 0) process.stdout.write("\x1b[3A\r");
|
|
2283
|
+
trustOptions.forEach(function(opt, i) {
|
|
2284
|
+
var prefix = i === trustSel ? C.green + C.bold + " \u276F " : " ";
|
|
2285
|
+
var color = i === trustSel ? C.brightWhite + C.bold : C.gray;
|
|
2286
|
+
process.stdout.write("\x1b[2K" + prefix + color + (i + 1) + ". " + opt.label + C.reset + "\n");
|
|
2287
|
+
});
|
|
2288
|
+
}
|
|
2289
|
+
// Initial render
|
|
2290
|
+
console.log(""); console.log(""); console.log("");
|
|
2291
|
+
renderTrustMenu();
|
|
2262
2292
|
|
|
2263
|
-
var trustAnswer = await new Promise(function(resolve) {
|
|
2264
2293
|
process.stdin.setRawMode(true);
|
|
2265
2294
|
process.stdin.resume();
|
|
2266
2295
|
process.stdin.setEncoding("utf8");
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2296
|
+
function onKey(key) {
|
|
2297
|
+
if (key === "\x1b[A") { trustSel = Math.max(0, trustSel - 1); renderTrustMenu(); return; }
|
|
2298
|
+
if (key === "\x1b[B") { trustSel = Math.min(2, trustSel + 1); renderTrustMenu(); return; }
|
|
2299
|
+
if (key === "1") { trustSel = 0; process.stdin.removeListener("data", onKey); process.stdin.setRawMode(false); resolve(trustOptions[0].action); return; }
|
|
2300
|
+
if (key === "2") { trustSel = 1; process.stdin.removeListener("data", onKey); process.stdin.setRawMode(false); resolve(trustOptions[1].action); return; }
|
|
2301
|
+
if (key === "3") { trustSel = 2; process.stdin.removeListener("data", onKey); process.stdin.setRawMode(false); resolve(trustOptions[2].action); return; }
|
|
2302
|
+
if (key === "\r" || key === "\n") {
|
|
2303
|
+
process.stdin.removeListener("data", onKey);
|
|
2304
|
+
process.stdin.setRawMode(false);
|
|
2305
|
+
resolve(trustOptions[trustSel].action);
|
|
2306
|
+
return;
|
|
2307
|
+
}
|
|
2308
|
+
}
|
|
2309
|
+
process.stdin.on("data", onKey);
|
|
2271
2310
|
});
|
|
2272
2311
|
|
|
2273
|
-
if (
|
|
2312
|
+
if (trustChoice === "always") {
|
|
2274
2313
|
trustedDirs.push(process.cwd());
|
|
2275
2314
|
fs.writeFileSync(trustFile, JSON.stringify(trustedDirs, null, 2));
|
|
2276
2315
|
printSuccess("Folder trusted permanently.");
|
|
2277
|
-
} else if (
|
|
2278
|
-
|
|
2279
|
-
var newDir =
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2316
|
+
} else if (trustChoice === "choose") {
|
|
2317
|
+
// Open Windows folder picker if available
|
|
2318
|
+
var newDir = null;
|
|
2319
|
+
if (process.platform === "win32") {
|
|
2320
|
+
try {
|
|
2321
|
+
printInfo("Opening folder picker...");
|
|
2322
|
+
var psCmd = 'powershell -NoProfile -Command "Add-Type -AssemblyName System.Windows.Forms; $f = New-Object System.Windows.Forms.FolderBrowserDialog; $f.Description = \'Choose BLUN King workspace\'; $f.ShowNewFolderButton = $true; if($f.ShowDialog() -eq \'OK\'){ Write-Output $f.SelectedPath } else { Write-Output \'CANCELLED\' }"';
|
|
2323
|
+
newDir = require("child_process").execSync(psCmd, { encoding: "utf8", timeout: 60000 }).trim();
|
|
2324
|
+
if (newDir === "CANCELLED") newDir = null;
|
|
2325
|
+
} catch(e) { newDir = null; }
|
|
2326
|
+
}
|
|
2327
|
+
// Fallback to text input
|
|
2328
|
+
if (!newDir) {
|
|
2329
|
+
var rlDir = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
2330
|
+
newDir = await new Promise(function(resolve) {
|
|
2331
|
+
rlDir.question(C.brightBlue + " Enter path: " + C.reset, resolve);
|
|
2332
|
+
});
|
|
2333
|
+
rlDir.close();
|
|
2334
|
+
newDir = newDir ? newDir.trim() : null;
|
|
2335
|
+
}
|
|
2336
|
+
if (newDir && fs.existsSync(newDir)) {
|
|
2337
|
+
config.workdir = newDir;
|
|
2285
2338
|
try { fs.writeFileSync(path.join(CONFIG_DIR, "last-workdir.json"), JSON.stringify({ dir: config.workdir, ts: new Date().toISOString() })); } catch(e) {}
|
|
2286
|
-
|
|
2339
|
+
printSuccess("Workspace: " + config.workdir);
|
|
2340
|
+
} else if (newDir) {
|
|
2287
2341
|
printError("Invalid path, using current directory.");
|
|
2288
2342
|
}
|
|
2289
2343
|
}
|
|
2290
|
-
//
|
|
2344
|
+
// trust = trust for this session only
|
|
2291
2345
|
console.log("");
|
|
2292
2346
|
}
|
|
2293
2347
|
}
|
|
@@ -2396,7 +2450,9 @@ async function main() {
|
|
|
2396
2450
|
var permColor = isDangerous ? C.red + C.bold : permMode === "deny" ? C.red : C.yellow;
|
|
2397
2451
|
var modelName = typeof config.model === "string" ? config.model : (config.model && config.model.name ? config.model.name : "default");
|
|
2398
2452
|
var wdShort = config.workdir ? path.basename(config.workdir) : "~";
|
|
2399
|
-
|
|
2453
|
+
var totalTok = sessionCost.inputTokensEst + sessionCost.outputTokensEst;
|
|
2454
|
+
var tokStr = totalTok > 1000 ? (totalTok / 1000).toFixed(1) + "k" : String(totalTok);
|
|
2455
|
+
lines.push(permColor + " " + permIcon + " " + permLabel + C.reset + C.dim + " \u2502 " + C.reset + C.cyan + modelName + C.reset + C.dim + " \u2502 " + C.reset + C.dim + wdShort + C.reset + C.dim + " \u2502 " + C.reset + C.yellow + tokStr + " tok" + C.reset);
|
|
2400
2456
|
|
|
2401
2457
|
// Menu
|
|
2402
2458
|
if (menuVisible && menuItems.length > 0) {
|