@vincemakes/kiso-code 0.1.15 → 0.1.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/render.js CHANGED
@@ -3,8 +3,8 @@
3
3
  * the lines a human sees. Colors are raw ANSI — no dependencies.
4
4
  */
5
5
  import { canonicalTargetPath } from "@vincemakes/kiso-tools-node";
6
- export const COLOR_ON = { blue: "\x1b[38;5;75m", dim: "\x1b[2m", red: "\x1b[31m", reset: "\x1b[0m" };
7
- export const COLOR_OFF = { blue: "", dim: "", red: "", reset: "" };
6
+ export const COLOR_ON = { blue: "\x1b[38;5;75m", dim: "\x1b[2m", red: "\x1b[31m", green: "\x1b[32m", bg: "\x1b[48;5;237m", reset: "\x1b[0m" };
7
+ export const COLOR_OFF = { blue: "", dim: "", red: "", green: "", bg: "", reset: "" };
8
8
  export function palette() {
9
9
  return process.env.NO_COLOR === undefined && process.stdout.isTTY ? COLOR_ON : COLOR_OFF;
10
10
  }
@@ -50,7 +50,7 @@ export function foldThinking(block) {
50
50
  const p = palette();
51
51
  const trimmed = escapeTerminal(block.trim());
52
52
  const truncated = trimmed.length > 100;
53
- return `${p.dim}…${trimmed.slice(0, 100)}${truncated ? " ( /think shows full)" : ""}${p.reset}\n`;
53
+ return `${p.dim}…${trimmed.slice(0, 100)}${truncated ? ` (${block.length} chars · /think)` : ""}${p.reset}\n`;
54
54
  }
55
55
  /** v2b — the [result] echo truncates at 160 chars + a /last hint. */
56
56
  export function foldResult(content) {
@@ -215,7 +215,7 @@ function exitCodeOf(result) {
215
215
  return m !== null ? Number(m[1]) : 1;
216
216
  }
217
217
  /** k-units for the status line: 12345 → 12.3k, 800 → 800, null → ?. */
218
- function kUnit(value) {
218
+ export function kUnit(value) {
219
219
  if (value === null)
220
220
  return "?";
221
221
  if (value >= 1000)
@@ -257,6 +257,66 @@ export function renderStatusLine(turn, usage, ctxRatio, faux = false) {
257
257
  export function renderTerminalGap(statusLine) {
258
258
  return `${statusLine === null ? "" : `${statusLine}\n`}\n`;
259
259
  }
260
+ /**
261
+ * v3 §01 — the banner, block-split. The logo is three INDEPENDENT rows
262
+ * (TOP / the tagline / BOTTOM), then TWO info rows (version,
263
+ * extensions). Every row truncates at the terminal width with a " (+N)"
264
+ * marker (N = the hidden display width); a window narrower than 40
265
+ * columns skips the logo entirely — only the info rows. Pure.
266
+ */
267
+ export const TAGLINE = "the coding agent that survives kill -9";
268
+ const LOGO_ROWS = ["█ █ ▀█▀ █▀▀ █▀█", TAGLINE, "▀ ▀ ▀▀▀ ▀▀▀ ▀▀▀"];
269
+ /** Display width of a row (1-cell ASCII; 2-cell CJK/wide). */
270
+ function displayW(row) {
271
+ let w = 0;
272
+ for (let i = 0; i < row.length; i += 1) {
273
+ const cp = row.codePointAt(i);
274
+ w += cp > 0xff ? 2 : 1;
275
+ }
276
+ return w;
277
+ }
278
+ /** v3 §01: truncate a row at `width`, marking the hidden span " (+N)". */
279
+ export function truncateRow(row, width) {
280
+ if (displayW(row) <= width)
281
+ return row;
282
+ const cut = Math.max(0, width - 4);
283
+ let w = 0;
284
+ let i = 0;
285
+ for (; i < row.length; i += 1) {
286
+ const cw = row.codePointAt(i) > 0xff ? 2 : 1;
287
+ if (w + cw > cut)
288
+ break;
289
+ w += cw;
290
+ }
291
+ return `${row.slice(0, i)} (+${displayW(row) - w})`;
292
+ }
293
+ /** v3 §01: the banner lines for a width W — logo (skipped under 40
294
+ * columns) + version + extensions. */
295
+ export function bannerLines(W, version, extensionsText) {
296
+ const rows = [];
297
+ if (W >= 40)
298
+ for (const r of LOGO_ROWS)
299
+ rows.push(truncateRow(r, W));
300
+ rows.push(truncateRow(`v${version}`, W));
301
+ if (extensionsText !== "")
302
+ rows.push(truncateRow(extensionsText, W));
303
+ return rows;
304
+ }
305
+ export function renderRecap(s) {
306
+ const p = palette();
307
+ const parts = [`${s.seconds}s`, `${s.tools} tool${s.tools === 1 ? "" : "s"}${s.edits > 0 ? ` (${s.edits} edit${s.edits === 1 ? "" : "s"})` : ""}`];
308
+ if (s.usage.known) {
309
+ const seg = `${s.usage.in !== null ? `in ${kUnit(s.usage.in)}` : ""}${s.usage.in !== null && s.usage.out !== null ? " " : ""}${s.usage.out !== null ? `out ${kUnit(s.usage.out)}` : ""}`;
310
+ if (seg !== "")
311
+ parts.push(seg);
312
+ if (s.usage.cache !== null && s.usage.in !== null && s.usage.in > 0) {
313
+ parts.push(`cache ${Math.round((s.usage.cache / s.usage.in) * 100)}%`);
314
+ }
315
+ }
316
+ if (s.ctxLeftPct !== null)
317
+ parts.push(`ctx left ~${Math.round(s.ctxLeftPct)}%`);
318
+ return `${p.blue}▞${p.reset} ${parts.join(" · ")}\n`;
319
+ }
260
320
  /** One-line summary of a session, for `kiso sessions`. */
261
321
  export function renderSessionLine(meta) {
262
322
  const when = meta.updatedAt ? new Date(meta.updatedAt).toISOString().slice(0, 16) : "—";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vincemakes/kiso-code",
3
- "version": "0.1.15",
3
+ "version": "0.1.17",
4
4
  "description": "kiso CLI — the coding-agent reference product: kiso chat / kiso resume / kiso sessions.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -18,12 +18,12 @@
18
18
  "test": "vitest run"
19
19
  },
20
20
  "dependencies": {
21
- "@vincemakes/kiso-core": "0.1.15",
22
- "@vincemakes/kiso-evals": "0.1.15",
23
- "@vincemakes/kiso-provider-anthropic": "0.1.15",
24
- "@vincemakes/kiso-provider-openai": "0.1.15",
25
- "@vincemakes/kiso-runtime": "0.1.15",
26
- "@vincemakes/kiso-tools-node": "0.1.15"
21
+ "@vincemakes/kiso-core": "0.1.17",
22
+ "@vincemakes/kiso-evals": "0.1.17",
23
+ "@vincemakes/kiso-provider-anthropic": "0.1.17",
24
+ "@vincemakes/kiso-provider-openai": "0.1.17",
25
+ "@vincemakes/kiso-runtime": "0.1.17",
26
+ "@vincemakes/kiso-tools-node": "0.1.17"
27
27
  },
28
28
  "devDependencies": {
29
29
  "@types/node": "^26.1.2",