solrouter 0.3.2 → 0.3.3

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/package.json +1 -1
  2. package/src/banner.js +11 -48
  3. package/src/setup.js +20 -57
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "solrouter",
3
- "version": "0.3.2",
3
+ "version": "0.3.3",
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
@@ -1,8 +1,7 @@
1
- // banner.js — pixel art for the terminal, rendered with truecolor half-blocks (▀).
2
- // Exports the cat (wearing the real wave mark on its hoodie) and the mark alone,
3
- // plus helpers the interactive setup uses to compose the full-width screen.
1
+ // banner.js — the wave mark + wordmark for the terminal, rendered with truecolor
2
+ // half-blocks. The mark is decoded from the real logo (see mark.js).
4
3
 
5
- import { MARK_LG, MARK_SM } from "./mark.js";
4
+ import { MARK_LG } from "./mark.js";
6
5
 
7
6
  export const PAL = {
8
7
  bg: "#0a0908", raised: "#161412", accent: "#F5E6D3", ink: "#e8e0d4",
@@ -16,42 +15,6 @@ export const bgc = (h) => { const [r, g, b] = rgb(h); return `\x1b[48;2;${r};${g
16
15
  export const RESET = "\x1b[0m";
17
16
  export const paint = (h, t, bold = false) => fg(h) + (bold ? "\x1b[1m" : "") + t + RESET;
18
17
 
19
- // The cat, generated to hold the REAL wave mark on its black hoodie at full
20
- // resolution (verified rendered, not downsampled). .=transparent b=body e=eye
21
- // n=nose p=ear-inner H=hoodie(black) v=mark(cream).
22
- const CAT = [
23
- "................................",
24
- "..........b..........b..........",
25
- ".........bbb........bbb.........",
26
- "........bbpbb......bbpbb........",
27
- ".......bbbbbbbbbbbbbbbbbb.......",
28
- ".......bbbbbbbbbbbbbbbbbb.......",
29
- ".......bbbbbbbbbbbbbbbbbb.......",
30
- "......bbbbbbbbbbbbbbbbbbbb......",
31
- "......bbbbbbbbbbbbbbbbbbbb......",
32
- "......bbbbeebbbbbbbeebbbbb......",
33
- "......bbbbeebbbbbbbeebbbbb......",
34
- "......bbbbbbbbbnnbbbbbbbbb......",
35
- "......bbbbbbbbbnnbbbbbbbbb......",
36
- ".......bbbbbbbbbbbbbbbbbb.......",
37
- "........bbbbbbbbbbbbbbbb........",
38
- "..........bbbbbbbbbbbb..........",
39
- ".............bbbbbb.............",
40
- "....HHHHHHHHHHHHHHHHHHHHHHHH....",
41
- "..HHHHHHvvvvHHHHHHHHvvvvHHHHHH..",
42
- "..HHHHHvvvvvvHHHHHHvvvvvvvHHHH..",
43
- "..HHHvvvHHHHvvvHHvvvvHHHvvvHHH..",
44
- "..HvvvvHHHHHHvvvvvvHHHHHHvvvvH..",
45
- "..HvvHHHHHHHHHvvvvHHHHHHHHHvvH..",
46
- "..HHHHHHHHHHHHHHHHHHHHHHHHHHHH..",
47
- "..HHHHHHvvvvHHHHHHHHvvvvHHHHHH..",
48
- "..HHHHHvvvvvvHHHHHHvvvvvvvHHHH..",
49
- "..HHHvvvvHHHvvvHHHvvvHHHvvvHHH..",
50
- "..HvvvvHHHHHHvvvvvvHHHHHHvvvvH..",
51
- "..bbbbHHHHHHHHvvvvHHHHHHHHbbbb..",
52
- "..bbbbHHHHHHHHHHHHHHHHHHHHbbbb..",
53
- ];
54
-
55
18
  const CMAP = { o: PAL.out, b: PAL.cream, e: PAL.eye, n: PAL.nose, p: PAL.nose, H: PAL.hood, v: PAL.cream };
56
19
 
57
20
  /** Render a pixel grid to ANSI half-block lines. Display width = grid width in chars. */
@@ -72,16 +35,16 @@ export function renderGrid(grid, cmap = CMAP) {
72
35
  return lines;
73
36
  }
74
37
 
75
- export const catLines = () => renderGrid(CAT);
76
- export const catWidth = () => CAT[0].length;
77
38
  export const markLines = () => renderGrid(MARK_LG, { v: PAL.cream });
78
39
 
79
- /** Legacy one-shot splash (used by the `banner` command). */
40
+ /** One-shot splash: the wave mark + wordmark. */
80
41
  export function banner() {
81
- const L = ["", " " + paint(PAL.accent, "≈≈", true) + " " + paint(PAL.accent, "SOLROUTER", true),
82
- " " + paint(PAL.muted, "private routing for your coding agent"), ""];
83
- catLines().forEach(l => L.push(" " + l));
84
- L.push(""); return L.join("\n");
42
+ const L = [""];
43
+ markLines().forEach(m => L.push(" " + m));
44
+ L.push(" " + paint(PAL.accent, "SOLROUTER", true));
45
+ L.push(" " + paint(PAL.muted, "private routing for your coding agent"));
46
+ L.push("");
47
+ return L.join("\n");
85
48
  }
86
49
 
87
- export default { banner, catLines, markLines, catWidth, renderGrid, PAL, paint, fg, bgc, RESET };
50
+ export default { banner, markLines, renderGrid, PAL, paint, fg, bgc, RESET };
package/src/setup.js CHANGED
@@ -1,5 +1,5 @@
1
- // setup.js — the interactive first-run wizard. Full-width TUI: selectable option
2
- // cards on the left, the cat + a speech bubble on the right that changes per step.
1
+ // setup.js — the interactive first-run wizard. A clean single-column TUI: the wave
2
+ // mark, the step question as a heading, and selectable option cards.
3
3
  // Arrow keys move, enter selects, esc/ctrl-c quits.
4
4
  //
5
5
  // Steps (v1 — API-key only for the frontier leg; no subscription relay):
@@ -9,7 +9,7 @@
9
9
  // 4. done — save config, offer to launch
10
10
 
11
11
  import readline from "node:readline";
12
- import { catLines, markLines, catWidth, PAL, paint, fg, RESET } from "./banner.js";
12
+ import { markLines, PAL, paint, fg, RESET } from "./banner.js";
13
13
  import { loadConfig, saveAuth, loadAuth, isLoggedIn, HOME_DIR } from "./config.js";
14
14
  import { browserLogin } from "./auth.js";
15
15
  import { writeFileSync, readFileSync, mkdirSync, existsSync } from "node:fs";
@@ -21,67 +21,30 @@ 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 with a consistent width, tail pointing to the cat.
25
- function bubble(lines) {
26
- const iw = Math.max(...lines.map(l => l.length)); // inner text width
27
- const A = PAL.accent;
28
- const out = [];
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
- return out;
34
- }
35
-
36
- // Right block = bubble (with the step's question) stacked above the cat, cat indented.
37
- function rightBlock(question) {
38
- const cat = catLines().map(l => " " + l);
39
- const b = bubble(question);
40
- return [...b, "", ...cat, "", " " + paint(PAL.faint, "the router")];
41
- }
42
-
43
- // Left block = header (stacked, no long inline rows) + step + body lines.
44
- function leftBlock(step, bodyLines) {
45
- const L = [];
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"));
49
- L.push("");
50
- L.push(paint(PAL.faint, `STEP ${step} / 3`));
51
- L.push("");
52
- bodyLines.forEach(l => L.push(l));
53
- return L;
54
- }
55
-
56
24
  // One option card (two lines): selected gets an accent bar + bright text.
57
25
  function card(name, desc, selected) {
58
26
  const bar = selected ? fg(PAL.accent) + "▐ " + RESET : " ";
59
27
  const nm = selected ? paint(PAL.accent, "▸ " + name, true) : paint(PAL.ink, " " + name);
60
- const ds = paint(selected ? PAL.muted : PAL.faint, " " + desc);
61
- return [bar + nm, bar + ds, ""];
28
+ const ds = desc ? paint(selected ? PAL.muted : PAL.faint, " " + desc) : "";
29
+ return desc ? [bar + nm, bar + ds, ""] : [bar + nm, ""];
62
30
  }
63
31
 
32
+ // Clean single-column frame: header (wave mark + wordmark), step, the question as a
33
+ // heading, then the option cards. No cat.
64
34
  function compose(step, question, bodyLines) {
65
- const left = leftBlock(step, bodyLines);
66
- const right = rightBlock(question);
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);
73
- const rows = Math.max(left.length, right.length);
74
- const out = [""];
75
- for (let i = 0; i < rows; i++) {
76
- let l = left[i] || "";
77
- const r = right[i] || "";
78
- if (visLen(l) > rightCol - 2) l = l.slice(0, rightCol - 2); // safety clamp
79
- const pad = Math.max(2, rightCol - visLen(l));
80
- out.push(" " + l + " ".repeat(pad) + r);
81
- }
82
- out.push("");
83
- out.push(" " + paint(PAL.faint, "↑↓ move ↵ select esc quit"));
84
- return out.join("\n");
35
+ const L = [""];
36
+ markLines().forEach(m => L.push(" " + m)); // the real wave mark
37
+ L.push(" " + paint(PAL.accent, "SOLROUTER", true));
38
+ L.push(" " + paint(PAL.muted, "private routing for your coding agent"));
39
+ L.push("");
40
+ L.push(" " + paint(PAL.faint, `STEP ${step} / 3`));
41
+ L.push("");
42
+ L.push(" " + paint(PAL.ink, question.join(" "), true));
43
+ L.push("");
44
+ bodyLines.forEach(l => L.push(" " + l));
45
+ L.push("");
46
+ L.push(" " + paint(PAL.faint, "↑↓ move ↵ select esc quit"));
47
+ return L.join("\n");
85
48
  }
86
49
 
87
50
  function render(step, question, bodyLines) { clear(); process.stdout.write(compose(step, question, bodyLines)); }