blun-king-cli 2.3.1 → 2.4.0

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.
Files changed (2) hide show
  1. package/bin/blun.js +53 -18
  2. package/package.json +1 -1
package/bin/blun.js CHANGED
@@ -2267,6 +2267,31 @@ async function main() {
2267
2267
  printHeader();
2268
2268
  checkForUpdates();
2269
2269
 
2270
+ // API Key check — prompt if missing
2271
+ if (!config.api.key && !process.argv.includes("--api-key")) {
2272
+ console.log("");
2273
+ console.log(C.yellow + " " + BOX.bot + " No API key configured." + C.reset);
2274
+ console.log(C.gray + " Enter your BLUN King API key (or press Enter to skip):" + C.reset);
2275
+ var apiKeyAnswer = await new Promise(function(resolve) {
2276
+ var rlKey = readline.createInterface({ input: process.stdin, output: process.stdout });
2277
+ rlKey.question(C.brightBlue + " API Key: " + C.reset, function(answer) {
2278
+ rlKey.close();
2279
+ resolve(answer.trim());
2280
+ });
2281
+ });
2282
+ if (apiKeyAnswer) {
2283
+ config.api.key = apiKeyAnswer;
2284
+ // Save to config file
2285
+ var cfgFile = path.join(CONFIG_DIR, "config.json");
2286
+ var cfgData = {};
2287
+ if (fs.existsSync(cfgFile)) { try { cfgData = JSON.parse(fs.readFileSync(cfgFile, "utf8")); } catch(e) {} }
2288
+ if (!cfgData.api) cfgData.api = {};
2289
+ cfgData.api.key = apiKeyAnswer;
2290
+ fs.writeFileSync(cfgFile, JSON.stringify(cfgData, null, 2));
2291
+ printSuccess("API key saved.");
2292
+ }
2293
+ }
2294
+
2270
2295
  // Load session history for this workdir
2271
2296
  var session = loadSessionHistory();
2272
2297
  chatHistory = session.history.slice(-20);
@@ -2307,12 +2332,19 @@ async function main() {
2307
2332
  // Erase everything we drew and move cursor back to start
2308
2333
  function eraseUI() {
2309
2334
  if (drawnLines <= 0) return;
2310
- // Move to start of first drawn line
2311
- process.stdout.write("\x1b[" + drawnLines + "A");
2312
- for (var i = 0; i < drawnLines; i++) {
2313
- process.stdout.write("\x1b[2K\n"); // clear entire line
2335
+ // Move cursor up to where we started drawing
2336
+ process.stdout.write("\x1b[?25l");
2337
+ // Go up drawnLines from current cursor position
2338
+ // Cursor is on content line (line 2), so we need to go up 1 to reach top
2339
+ process.stdout.write("\x1b[" + (drawnLines) + "A\r");
2340
+ // Clear all lines we drew + extra buffer
2341
+ for (var i = 0; i < drawnLines + 3; i++) {
2342
+ process.stdout.write("\x1b[2K");
2343
+ if (i < drawnLines + 2) process.stdout.write("\n");
2314
2344
  }
2315
- process.stdout.write("\x1b[" + drawnLines + "A"); // back to start
2345
+ // Go back up
2346
+ process.stdout.write("\x1b[" + (drawnLines + 3) + "A\r");
2347
+ process.stdout.write("\x1b[?25h");
2316
2348
  drawnLines = 0;
2317
2349
  }
2318
2350
 
@@ -2322,26 +2354,30 @@ async function main() {
2322
2354
  var w = Math.min(getTermWidth() - 4, 76);
2323
2355
  var displayText = inputBuffer;
2324
2356
  if (displayText.length > w - 4) displayText = displayText.slice(-(w - 4));
2325
- var pad = Math.max(0, w - 2 - displayText.length);
2357
+ var pad = Math.max(0, w - 3 - displayText.length);
2326
2358
  var lines = 0;
2327
2359
 
2328
2360
  // Box top
2329
- process.stdout.write(C.brightBlue + " \u256D" + "\u2500".repeat(w - 2) + "\u256E" + C.reset + "\n"); lines++;
2361
+ process.stdout.write("\x1b[2K" + C.brightBlue + " \u256D" + "\u2500".repeat(w - 2) + "\u256E" + C.reset + "\n"); lines++;
2330
2362
  // Box content
2331
- process.stdout.write(C.brightBlue + " \u2502 " + C.reset + C.brightWhite + displayText + C.reset + " ".repeat(pad) + C.brightBlue + "\u2502" + C.reset + "\n"); lines++;
2363
+ process.stdout.write("\x1b[2K" + C.brightBlue + " \u2502 " + C.reset + C.brightWhite + displayText + C.reset + " ".repeat(pad) + C.brightBlue + "\u2502" + C.reset + "\n"); lines++;
2332
2364
  // Box bottom
2333
- process.stdout.write(C.brightBlue + " \u2570" + "\u2500".repeat(w - 2) + "\u256F" + C.reset + "\n"); lines++;
2365
+ process.stdout.write("\x1b[2K" + C.brightBlue + " \u2570" + "\u2500".repeat(w - 2) + "\u256F" + C.reset + "\n"); lines++;
2334
2366
 
2335
2367
  // Status bar (permission mode + model + workdir)
2336
- var permMode = getSetting("permissions.defaultMode") || "ask";
2337
- var permIcon = permMode === "allow" ? "\u2714" : permMode === "deny" ? "\u2718" : "\u2753";
2338
- var permColor = permMode === "allow" ? C.green : permMode === "deny" ? C.red : C.yellow;
2368
+ var rawPerm = getSetting("permissions.defaultMode");
2369
+ var permMode = typeof rawPerm === "string" ? rawPerm : "ask";
2370
+ // Check if --dangerously-skip-permissions or godmode
2371
+ var isDangerous = process.argv.includes("--dangerously-skip-permissions") || permMode === "allow";
2372
+ var permLabel = isDangerous ? "GOD MODE" : permMode === "deny" ? "LOCKED" : "ask permission";
2373
+ var permIcon = isDangerous ? "\u26A1" : permMode === "deny" ? "\u2718" : "\u2753";
2374
+ var permColor = isDangerous ? C.red + C.bold : permMode === "deny" ? C.red : C.yellow;
2339
2375
  var modelName = typeof config.model === "string" ? config.model : (config.model && config.model.name ? config.model.name : "default");
2340
2376
  var wdShort = config.workdir ? path.basename(config.workdir) : "~";
2341
- var statusLine = permColor + " " + permIcon + " " + permMode + C.reset + C.dim + " \u2502 " + C.reset +
2377
+ var statusLine = permColor + " " + permIcon + " " + permLabel + C.reset + C.dim + " \u2502 " + C.reset +
2342
2378
  C.cyan + modelName + C.reset + C.dim + " \u2502 " + C.reset +
2343
2379
  C.dim + wdShort + C.reset;
2344
- process.stdout.write(statusLine + "\x1b[K\n"); lines++;
2380
+ process.stdout.write("\x1b[2K" + statusLine + "\n"); lines++;
2345
2381
 
2346
2382
  // Menu
2347
2383
  if (menuVisible && menuItems.length > 0) {
@@ -2352,11 +2388,11 @@ async function main() {
2352
2388
  var descStr = item.desc.slice(0, getTermWidth() - 28);
2353
2389
  var cmdColor = i === menuSelected ? C.green + C.bold : C.green;
2354
2390
  var descColor = i === menuSelected ? C.brightWhite : C.white;
2355
- process.stdout.write(prefix + cmdColor + cmdStr + descColor + descStr + C.reset + "\x1b[K\n");
2391
+ process.stdout.write("\x1b[2K" + prefix + cmdColor + cmdStr + descColor + descStr + C.reset + "\n");
2356
2392
  lines++;
2357
2393
  });
2358
2394
  if (menuItems.length > 8) {
2359
- process.stdout.write(C.dim + " ... " + (menuItems.length - 8) + " more" + C.reset + "\x1b[K\n");
2395
+ process.stdout.write("\x1b[2K" + C.dim + " ... " + (menuItems.length - 8) + " more" + C.reset + "\n");
2360
2396
  lines++;
2361
2397
  }
2362
2398
  }
@@ -2364,8 +2400,7 @@ async function main() {
2364
2400
  drawnLines = lines;
2365
2401
 
2366
2402
  // Position cursor inside the box (line 2, after text)
2367
- process.stdout.write("\x1b[" + lines + "A"); // back to top
2368
- process.stdout.write("\x1b[1B"); // down to content line
2403
+ process.stdout.write("\x1b[" + (lines - 1) + "A"); // back to content line
2369
2404
  process.stdout.write("\r\x1b[" + (4 + displayText.length) + "C"); // right to cursor pos
2370
2405
  process.stdout.write("\x1b[?25h"); // show cursor
2371
2406
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blun-king-cli",
3
- "version": "2.3.1",
3
+ "version": "2.4.0",
4
4
  "description": "BLUN King CLI — Premium KI Console",
5
5
  "bin": {
6
6
  "blun": "./bin/blun.js"