solrouter 0.3.0 → 0.3.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "solrouter",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "Local privacy router for coding tools: pseudonymises every request before it leaves your machine, and sends work a frontier model would refuse to an uncensored open-weight model you control.",
5
5
  "type": "module",
6
6
  "bin": {
package/src/banner.js CHANGED
@@ -7,7 +7,7 @@ import { MARK_LG, MARK_SM } from "./mark.js";
7
7
  export const PAL = {
8
8
  bg: "#0a0908", raised: "#161412", accent: "#F5E6D3", ink: "#e8e0d4",
9
9
  muted: "#b5ac9f", faint: "#78746b", rule: "#2a2723",
10
- cream: "#F5E6D3", out: "#050403", eye: "#0a0908", nose: "#c98f7f", hood: "#15130f",
10
+ cream: "#F5E6D3", out: "#050403", eye: "#0a0908", nose: "#c98f7f", hood: "#050403",
11
11
  };
12
12
 
13
13
  const rgb = (h) => [parseInt(h.slice(1, 3), 16), parseInt(h.slice(3, 5), 16), parseInt(h.slice(5, 7), 16)];
@@ -48,8 +48,8 @@ const CAT = [
48
48
  function catWithMark() {
49
49
  const g = CAT.map(r => r.split(""));
50
50
  const mw = MARK_SM[0].length, mh = MARK_SM.length;
51
- const c0 = Math.round((26 - mw) / 2); // centre horizontally
52
- const r0 = 15; // top of hoodie chest
51
+ const c0 = Math.round((CAT[0].length - mw) / 2); // centre horizontally
52
+ const r0 = 16; // centred on the black hoodie
53
53
  for (let y = 0; y < mh; y++) for (let x = 0; x < mw; x++) {
54
54
  if (MARK_SM[y][x] === "v" && g[r0 + y] && g[r0 + y][c0 + x] === "H") g[r0 + y][c0 + x] = "v";
55
55
  }
package/src/mark.js CHANGED
@@ -31,6 +31,7 @@ function downsample(grid, tw, th) {
31
31
  return out;
32
32
  }
33
33
 
34
- export const MARK_SM = downsample(MARK_LG, 16, 7);
34
+ // Small mark for the hoodie — kept compact so it sits centred with black around it.
35
+ export const MARK_SM = downsample(MARK_LG, 12, 5);
35
36
 
36
37
  export default { MARK_LG, MARK_SM };
package/src/setup.js CHANGED
@@ -21,33 +21,31 @@ const clear = () => process.stdout.write("\x1b[2J\x1b[H");
21
21
  const hideCur = () => process.stdout.write("\x1b[?25l");
22
22
  const showCur = () => process.stdout.write("\x1b[?25h");
23
23
 
24
- // A rounded speech bubble in accent, tail pointing right (toward the cat).
24
+ // A rounded speech bubble in accent with a consistent width, tail pointing to the cat.
25
25
  function bubble(lines) {
26
- const w = Math.max(...lines.map(l => l.length)) + 4;
26
+ const iw = Math.max(...lines.map(l => l.length)); // inner text width
27
27
  const A = PAL.accent;
28
28
  const out = [];
29
- out.push(fg(A) + "╭" + "─".repeat(w) + "╮" + RESET);
30
- for (const l of lines) out.push(fg(A) + "│ " + RESET + paint(PAL.ink, l.padEnd(w - 2)) + fg(A) + " │" + RESET);
31
- out.push(fg(A) + "╰" + "─".repeat(w) + "╯" + RESET);
32
- out.push(" ".repeat(Math.min(w - 2, 6)) + fg(A) + "╲" + RESET);
29
+ out.push(fg(A) + "╭" + "─".repeat(iw + 2) + "╮" + RESET);
30
+ for (const l of lines) out.push(fg(A) + "│ " + RESET + paint(PAL.ink, l.padEnd(iw)) + fg(A) + " │" + RESET);
31
+ out.push(fg(A) + "╰" + "─".repeat(iw + 2) + "╯" + RESET);
32
+ out.push(" " + fg(A) + "╲" + RESET); // tail toward the cat below
33
33
  return out;
34
34
  }
35
35
 
36
- // Right block = bubble (with the step's question) stacked above the cat.
36
+ // Right block = bubble (with the step's question) stacked above the cat, cat indented.
37
37
  function rightBlock(question) {
38
- const cat = catLines();
38
+ const cat = catLines().map(l => " " + l);
39
39
  const b = bubble(question);
40
- return [...b, "", ...cat, "", paint(PAL.faint, " the router, in the hoodie")];
40
+ return [...b, "", ...cat, "", " " + paint(PAL.faint, "the router")];
41
41
  }
42
42
 
43
- // Left block = header + step + rendered body lines (already ANSI).
43
+ // Left block = header (stacked, no long inline rows) + step + body lines.
44
44
  function leftBlock(step, bodyLines) {
45
45
  const L = [];
46
- const mk = markLines(); // real wave mark
47
- L.push(mk[0] || "");
48
- L.push((mk[1] || "") + " " + paint(PAL.accent, "SOLROUTER", true));
49
- L.push((mk[2] || "") + " " + paint(PAL.muted, "private routing for your coding agent"));
50
- for (let i = 3; i < mk.length; i++) L.push(mk[i]);
46
+ markLines().forEach(m => L.push(m)); // real wave mark
47
+ L.push(paint(PAL.accent, "SOLROUTER", true));
48
+ L.push(paint(PAL.muted, "private routing for your coding agent"));
51
49
  L.push("");
52
50
  L.push(paint(PAL.faint, `STEP ${step} / 3`));
53
51
  L.push("");
@@ -66,14 +64,19 @@ function card(name, desc, selected) {
66
64
  function compose(step, question, bodyLines) {
67
65
  const left = leftBlock(step, bodyLines);
68
66
  const right = rightBlock(question);
69
- const leftW = Math.min(58, Math.max(...left.map(visLen)) + 2);
70
- const gap = 6;
67
+ const termW = W();
68
+ const leftMax = Math.max(...left.map(visLen));
69
+ const rightW = Math.max(...right.map(visLen));
70
+ // Pin the right block to a FIXED column near the right edge, so nothing shoves it
71
+ // around and the bubble stays aligned. Push the cat as far right as fits.
72
+ const rightCol = Math.max(leftMax + 8, termW - rightW - 3);
71
73
  const rows = Math.max(left.length, right.length);
72
74
  const out = [""];
73
75
  for (let i = 0; i < rows; i++) {
74
- const l = left[i] || "";
76
+ let l = left[i] || "";
75
77
  const r = right[i] || "";
76
- const pad = Math.max(gap, leftW + gap - visLen(l));
78
+ if (visLen(l) > rightCol - 2) l = l.slice(0, rightCol - 2); // safety clamp
79
+ const pad = Math.max(2, rightCol - visLen(l));
77
80
  out.push(" " + l + " ".repeat(pad) + r);
78
81
  }
79
82
  out.push("");