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 +1 -1
- package/src/banner.js +3 -3
- package/src/mark.js +2 -1
- package/src/setup.js +22 -19
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "solrouter",
|
|
3
|
-
"version": "0.3.
|
|
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: "#
|
|
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((
|
|
52
|
-
const r0 =
|
|
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
|
-
|
|
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
|
|
24
|
+
// A rounded speech bubble in accent with a consistent width, tail pointing to the cat.
|
|
25
25
|
function bubble(lines) {
|
|
26
|
-
const
|
|
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(
|
|
30
|
-
for (const l of lines) out.push(fg(A) + "│ " + RESET + paint(PAL.ink, l.padEnd(
|
|
31
|
-
out.push(fg(A) + "╰" + "─".repeat(
|
|
32
|
-
out.push("
|
|
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, "
|
|
40
|
+
return [...b, "", ...cat, "", " " + paint(PAL.faint, "the router")];
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
// Left block = header + step +
|
|
43
|
+
// Left block = header (stacked, no long inline rows) + step + body lines.
|
|
44
44
|
function leftBlock(step, bodyLines) {
|
|
45
45
|
const L = [];
|
|
46
|
-
|
|
47
|
-
L.push(
|
|
48
|
-
L.push((
|
|
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
|
|
70
|
-
const
|
|
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
|
-
|
|
76
|
+
let l = left[i] || "";
|
|
75
77
|
const r = right[i] || "";
|
|
76
|
-
|
|
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("");
|