blun-king-cli 7.0.0 → 7.0.2

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 (3) hide show
  1. package/lib/chat.js +29 -78
  2. package/lib/ui.js +17 -39
  3. package/package.json +1 -1
package/lib/chat.js CHANGED
@@ -14,7 +14,7 @@ var localMode = false;
14
14
  var permissionMode = "normal"; // safe, normal, god
15
15
 
16
16
  function showPrompt(rl, username, model) {
17
- ui.renderInputBox(username, model, permissionMode);
17
+ ui.setCurrentPerm(permissionMode);
18
18
  rl.prompt();
19
19
  }
20
20
 
@@ -22,6 +22,7 @@ function cyclePermission() {
22
22
  var modes = ui.PERMISSION_MODES;
23
23
  var idx = modes.indexOf(permissionMode);
24
24
  permissionMode = modes[(idx + 1) % modes.length];
25
+ ui.setCurrentPerm(permissionMode);
25
26
  return permissionMode;
26
27
  }
27
28
 
@@ -271,91 +272,41 @@ function startChat() {
271
272
  return;
272
273
  }
273
274
 
274
- // Use streaming
275
+ // Send message
275
276
  var spinner = ui.renderSpinner("Thinking...");
276
277
  client
277
- .sendMessageStream(input, {
278
- model: settings.model || "auto",
279
- onChunk: function (chunk) {
280
- if (spinner) {
281
- ui.stopSpinner(true, "Streaming...");
282
- spinner = null;
283
- ui.renderStreamStart();
278
+ .sendMessage(input, { model: settings.model || "auto" })
279
+ .then(function (res) {
280
+ ui.stopSpinner(true, "Response received");
281
+ if (res.status === 200 && res.data) {
282
+ var text =
283
+ res.data.answer ||
284
+ res.data.response ||
285
+ res.data.text ||
286
+ res.data.message ||
287
+ JSON.stringify(res.data);
288
+ ui.renderResponse(text, "agent");
289
+ var tok = res.data.tokens || res.data.usage || {};
290
+ var tokTotal = tok.total || tok.total_tokens || 0;
291
+ if (!tokTotal && text) {
292
+ tokTotal = Math.ceil(text.length / 4) + Math.ceil(input.length / 4);
284
293
  }
285
- ui.renderStreamChunk(chunk);
286
- },
287
- })
288
- .then(function (result) {
289
- if (spinner) {
290
- // No streaming happened, fallback to non-stream
291
- ui.stopSpinner(true, "Response received");
292
- ui.renderResponse(result.text || "(empty response)", "agent");
294
+ if (tokTotal) ui.addTokens(tokTotal);
295
+ ui.renderMiniStatus(settings.model || "chat", tokTotal);
296
+ } else if (res.status === 401 || res.status === 403) {
297
+ ui.renderResponse("Auth error. Use /login to re-authenticate.", "error");
293
298
  } else {
294
- ui.renderStreamEnd();
295
- }
296
-
297
- // Token tracking
298
- var tokTotal = 0;
299
- if (result.usage) {
300
- tokTotal =
301
- result.usage.total ||
302
- result.usage.total_tokens ||
303
- (result.usage.input || 0) + (result.usage.output || 0) ||
304
- 0;
305
- }
306
- // Estimate tokens from text length if no usage data
307
- if (!tokTotal && result.text) {
308
- tokTotal = Math.ceil(result.text.length / 4) + Math.ceil(input.length / 4);
299
+ ui.renderResponse("Error: " + JSON.stringify(res.data), "error");
309
300
  }
310
- if (tokTotal) ui.addTokens(tokTotal);
311
-
312
- var usedModel = settings.model || "chat";
313
- ui.renderMiniStatus(usedModel, tokTotal);
314
301
  showPrompt(rl, username, model);
315
302
  })
316
303
  .catch(function (e) {
317
- if (spinner) {
318
- ui.stopSpinner(false, e.message);
319
- } else {
320
- ui.renderStreamEnd();
321
- }
322
- // Fallback to non-streaming
323
- ui.renderResponse("Stream failed, trying non-stream...", "system");
324
- return client
325
- .sendMessage(input, { model: settings.model || "auto" })
326
- .then(function (res) {
327
- if (res.status === 200 && res.data) {
328
- var text =
329
- res.data.answer ||
330
- res.data.response ||
331
- res.data.text ||
332
- res.data.message ||
333
- JSON.stringify(res.data);
334
- ui.renderResponse(text, "agent");
335
- var tok = res.data.tokens || res.data.usage || {};
336
- var tokTotal = tok.total || tok.total_tokens || 0;
337
- if (tokTotal) ui.addTokens(tokTotal);
338
- ui.renderMiniStatus(settings.model || "chat", tokTotal);
339
- } else if (res.status === 401 || res.status === 403) {
340
- ui.renderResponse(
341
- "Auth error. Use /login to re-authenticate.",
342
- "error"
343
- );
344
- } else {
345
- ui.renderResponse(
346
- "Error: " + JSON.stringify(res.data),
347
- "error"
348
- );
349
- }
350
- showPrompt(rl, username, model);
351
- })
352
- .catch(function (e2) {
353
- ui.renderResponse(
354
- "Request failed: " + e2.message + "\n Try /login if auth expired.",
355
- "error"
356
- );
357
- showPrompt(rl, username, model);
358
- });
304
+ ui.stopSpinner(false, e.message);
305
+ ui.renderResponse(
306
+ "Request failed: " + e.message + "\n Try /login if auth expired.",
307
+ "error"
308
+ );
309
+ showPrompt(rl, username, model);
359
310
  });
360
311
  });
361
312
 
package/lib/ui.js CHANGED
@@ -60,31 +60,20 @@ function getInputBoxWidth() {
60
60
  }
61
61
 
62
62
  function renderInputBox(username, model, permMode) {
63
- var w = getInputBoxWidth();
64
- var u = username || "user";
65
- var m = model || "auto";
66
- var pm = permMode || "normal";
67
- var hints = "/help \u2502 /settings \u2502 /model \u2502 /exit";
68
- var labelText = " " + u + " [" + m + "] ";
69
- var hintsText = " " + hints + " ";
70
- var topFill = w - labelText.length - hintsText.length;
71
- if (topFill < 2) topFill = 2;
72
- var topLine =
73
- chalk.dim("\u256d") +
74
- chalk.cyan(labelText) +
75
- chalk.dim("\u2500".repeat(topFill)) +
76
- chalk.dim(hintsText) +
77
- chalk.dim("\u256e");
78
- console.log(topLine);
63
+ // Claude Code style - no box, just clean space
79
64
  }
80
65
 
66
+ var currentPermMode = "normal";
67
+ function setCurrentPerm(pm) { currentPermMode = pm; }
68
+
81
69
  function renderInputBoxClose() {
82
- var w = getInputBoxWidth();
83
- console.log(chalk.dim("\u2570" + "\u2500".repeat(w) + "\u256f"));
70
+ // Show permission line after input (like Claude Code)
71
+ var label = permissionLabels[currentPermMode] || permissionLabels.normal;
72
+ console.log(chalk.dim(" \u276f\u276f ") + chalk.dim("bypass permissions ") + label + chalk.dim(" (shift+tab to cycle)"));
84
73
  }
85
74
 
86
75
  function renderPrompt() {
87
- return chalk.dim("\u2502") + " " + chalk.green.bold("\u276f") + " ";
76
+ return chalk.bold.green("> ");
88
77
  }
89
78
 
90
79
  function renderPermissionLine(permMode) {
@@ -114,27 +103,15 @@ function renderResponse(text, type) {
114
103
  var rendered = renderMarkdown(text);
115
104
 
116
105
  if (type === "agent") {
117
- console.log(
118
- boxen(rendered, {
119
- title: chalk.green.bold(" \u2728 BLUN "),
120
- titleAlignment: "left",
121
- padding: { top: 0, bottom: 0, left: 1, right: 1 },
122
- margin: { top: 0, bottom: 0, left: 1, right: 1 },
123
- borderStyle: "round",
124
- borderColor: "green",
125
- })
126
- );
106
+ // Claude Code style - plain text with green prefix, no box
107
+ var lines = rendered.split("\n");
108
+ lines.forEach(function (line) {
109
+ console.log(" " + chalk.green(line));
110
+ });
111
+ console.log();
127
112
  } else if (type === "error") {
128
- console.log(
129
- boxen(chalk.red(rendered), {
130
- title: chalk.red.bold(" \u2718 Error "),
131
- titleAlignment: "left",
132
- padding: { top: 0, bottom: 0, left: 1, right: 1 },
133
- margin: { top: 0, bottom: 0, left: 1, right: 1 },
134
- borderStyle: "round",
135
- borderColor: "red",
136
- })
137
- );
113
+ console.log(chalk.red(" \u2718 " + rendered));
114
+ console.log();
138
115
  } else if (type === "system") {
139
116
  console.log(chalk.yellow.bold(" [SYS] ") + chalk.yellow(rendered));
140
117
  console.log();
@@ -381,6 +358,7 @@ module.exports = {
381
358
  renderPrompt: renderPrompt,
382
359
  renderInputBox: renderInputBox,
383
360
  renderInputBoxClose: renderInputBoxClose,
361
+ setCurrentPerm: setCurrentPerm,
384
362
  renderWelcomeInfo: renderWelcomeInfo,
385
363
  renderPermissionLine: renderPermissionLine,
386
364
  renderMiniStatus: renderMiniStatus,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blun-king-cli",
3
- "version": "7.0.0",
3
+ "version": "7.0.2",
4
4
  "description": "BLUN AI Assistant - Command Line Interface",
5
5
  "bin": {
6
6
  "blun": "./bin/blun.js"