@stevezhou/sisu 0.1.3 → 0.1.4

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/logo.js CHANGED
@@ -1,9 +1,15 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.sisuMarkLines = exports.sisuMarkArt = void 0;
3
4
  exports.sisuMobiusArt = sisuMobiusArt;
4
5
  exports.sisuWordmark = sisuWordmark;
6
+ exports.sisuSplash = sisuSplash;
5
7
  exports.sisuBanner = sisuBanner;
6
8
  exports.stripAnsi = stripAnsi;
9
+ var mark_1 = require("./mark");
10
+ Object.defineProperty(exports, "sisuMarkArt", { enumerable: true, get: function () { return mark_1.sisuMarkArt; } });
11
+ Object.defineProperty(exports, "sisuMarkLines", { enumerable: true, get: function () { return mark_1.sisuMarkLines; } });
12
+ const mark_2 = require("./mark");
7
13
  const mobius_1 = require("./mobius");
8
14
  function sisuMobiusArt(columns = 80, phase = 0, color = false) {
9
15
  return (0, mobius_1.renderMobiusFrame)({
@@ -16,14 +22,16 @@ function sisuMobiusArt(columns = 80, phase = 0, color = false) {
16
22
  function sisuWordmark() {
17
23
  return ['思溯', 'SISU'].join('\n');
18
24
  }
19
- function sisuBanner(columns = 80, phase = 0, color = false) {
20
- return [
21
- '',
22
- sisuMobiusArt(columns, phase, color),
23
- '',
24
- sisuWordmark(),
25
- '',
26
- ].join('\n');
25
+ /** Splash used on TUI enter: the web Möbius mark plus 思溯. */
26
+ function sisuSplash(columns = 80, color = true) {
27
+ const mark = (0, mark_2.sisuMarkArt)(columns, color);
28
+ const markWidth = (0, mark_2.sisuMarkLines)(columns)[0]?.length ?? 0;
29
+ const caption = '思溯 SISU';
30
+ const pad = Math.max(0, Math.floor((markWidth - caption.length) / 2));
31
+ return ['', mark, '', `${' '.repeat(pad)}${caption}`, ''].join('\n');
32
+ }
33
+ function sisuBanner(columns = 80, _phase = 0, color = false) {
34
+ return sisuSplash(columns, color);
27
35
  }
28
36
  function stripAnsi(text) {
29
37
  return text.replace(/\x1b\[[0-9;]*m/g, '');
package/dist/mark.js ADDED
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ /** Hand-drawn SiSu Möbius mark — the web ∞ ribbon, not a 3D rasterizer. */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.markRgb = markRgb;
5
+ exports.sisuMarkLines = sisuMarkLines;
6
+ exports.sisuMarkArt = sisuMarkArt;
7
+ exports.sisuMarkWidth = sisuMarkWidth;
8
+ exports.sisuMarkHeight = sisuMarkHeight;
9
+ const RESET = '\x1b[0m';
10
+ const MARK_WIDE = [
11
+ ' ▄▄████▄▄ ▄▄████▄▄ ',
12
+ ' ▄██▀ ▀██▄ ▄██▀ ▀██▄ ',
13
+ ' ██ ▀█▄ ▄█▀ ██ ',
14
+ ' ██ ▀████▀ ██ ',
15
+ ' ██ ▄████▄ ██ ',
16
+ ' ██ ▄█▀ ▀█▄ ██ ',
17
+ ' ▀██▄ ▄██▀ ▀██▄ ▄██▀ ',
18
+ ' ▀▀████▀▀ ▀▀████▀▀ ',
19
+ ];
20
+ const MARK_NARROW = [
21
+ ' ▄██▄ ▄██▄ ',
22
+ ' █▀ ▀█▄ ▄█▀ ▀█ ',
23
+ ' █ ▀██▀ █ ',
24
+ ' █ ▄██▄ █ ',
25
+ ' █▄ ▄█▀ ▀█▄ ▄█ ',
26
+ ' ▀██▀ ▀██▀ ',
27
+ ];
28
+ function lerp(a, b, t) {
29
+ return a + (b - a) * t;
30
+ }
31
+ /** Brand gradient along the ribbon: blue → purple → gold. */
32
+ function markRgb(x, width) {
33
+ const t = width <= 1 ? 0 : Math.max(0, Math.min(1, x / (width - 1)));
34
+ if (t < 0.5) {
35
+ const k = t / 0.5;
36
+ return [
37
+ Math.round(lerp(37, 124, k)),
38
+ Math.round(lerp(99, 58, k)),
39
+ Math.round(lerp(235, 237, k)),
40
+ ];
41
+ }
42
+ const k = (t - 0.5) / 0.5;
43
+ return [
44
+ Math.round(lerp(124, 217, k)),
45
+ Math.round(lerp(58, 119, k)),
46
+ Math.round(lerp(237, 6, k)),
47
+ ];
48
+ }
49
+ function paintLine(line) {
50
+ const width = line.length;
51
+ let out = '';
52
+ for (let i = 0; i < line.length; i += 1) {
53
+ const ch = line[i];
54
+ if (ch === ' ') {
55
+ out += ' ';
56
+ continue;
57
+ }
58
+ const [r, g, b] = markRgb(i, width);
59
+ out += `\x1b[38;2;${r};${g};${b}m${ch}`;
60
+ }
61
+ return `${out}${RESET}`;
62
+ }
63
+ function sisuMarkLines(columns = 80) {
64
+ return columns >= 48 ? MARK_WIDE : MARK_NARROW;
65
+ }
66
+ function sisuMarkArt(columns = 80, color = true) {
67
+ const lines = sisuMarkLines(columns);
68
+ const painted = color ? lines.map(paintLine) : lines;
69
+ return painted.join('\n');
70
+ }
71
+ function sisuMarkWidth(columns = 80) {
72
+ return sisuMarkLines(columns).reduce((max, line) => Math.max(max, line.length), 0);
73
+ }
74
+ function sisuMarkHeight(columns = 80) {
75
+ return sisuMarkLines(columns).length;
76
+ }
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.stripAnsi = void 0;
4
4
  exports.renderPager = renderPager;
5
+ const mark_1 = require("../mark");
5
6
  const model_1 = require("./model");
6
7
  const theme_1 = require("./theme");
7
8
  Object.defineProperty(exports, "stripAnsi", { enumerable: true, get: function () { return theme_1.stripAnsi; } });
@@ -100,24 +101,25 @@ function windowAroundSelected(lines, entryOf, selected, budget, lastEntry) {
100
101
  function isIdleWelcome(state) {
101
102
  return !state.conversationId && state.entries.length === 0;
102
103
  }
103
- function center(text, width) {
104
- const padLeft = Math.max(0, Math.floor((width - text.length) / 2));
104
+ function center(text, width, vis = (0, theme_1.stripAnsi)(text).length) {
105
+ const padLeft = Math.max(0, Math.floor((width - vis) / 2));
105
106
  return `${' '.repeat(padLeft)}${text}`;
106
107
  }
107
- function welcomeLines(guest, width, theme) {
108
- const title = theme.accent(center('SISU', width));
108
+ function welcomeLines(guest, width, height, theme) {
109
+ const markCols = height >= 20 && width >= 48 ? width : 40;
110
+ const raw = (0, mark_1.sisuMarkLines)(markCols);
111
+ const painted = (0, mark_1.sisuMarkArt)(markCols, true).split('\n');
112
+ const mark = painted.map((line, i) => center(line, width, raw[i]?.length ?? (0, theme_1.stripAnsi)(line).length));
109
113
  if (guest) {
110
114
  return [
111
- title,
115
+ ...mark,
112
116
  '',
113
117
  theme.text(center('Sign in to start a conversation.', width)),
114
- '',
115
- theme.dim(center('/login browser', width)),
116
- theme.dim(center('/help commands', width)),
118
+ theme.dim(center('/login browser /help commands', width)),
117
119
  ];
118
120
  }
119
121
  return [
120
- title,
122
+ ...mark,
121
123
  '',
122
124
  theme.dim(center('Ask anything, or type /help.', width)),
123
125
  ];
@@ -150,7 +152,7 @@ function renderPager(state, cols, rows, themeName = 'dark') {
150
152
  const slash = slashMenuLines(state, theme);
151
153
  const slashTake = Math.min(slash.length, bodyBudget);
152
154
  const guest = !(state.statusLine || '').trim() || (state.statusLine || '').includes('not signed in');
153
- const welcome = isIdleWelcome(state) ? welcomeLines(guest, width, theme) : [];
155
+ const welcome = isIdleWelcome(state) ? welcomeLines(guest, width, height, theme) : [];
154
156
  const welcomeTake = Math.min(welcome.length, Math.max(0, bodyBudget - slashTake));
155
157
  const scrollBudget = bodyBudget - slashTake - welcomeTake;
156
158
  const laid = layoutScrollback(state, width, theme);
package/dist/tui.js CHANGED
@@ -174,7 +174,7 @@ async function runTui(io, deps = {}) {
174
174
  const columns = deps.columns ?? process.stdout.columns ?? 80;
175
175
  const animate = deps.animate ?? shouldAnimateSplash();
176
176
  try {
177
- io.write(`\n${(0, logo_1.sisuWordmark)()}\n\n`);
177
+ io.write(`${(0, logo_1.sisuSplash)(columns, true)}\n`);
178
178
  if (animate) {
179
179
  await (deps.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms))))(80);
180
180
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stevezhou/sisu",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "SiSu CLI — one login, cloud quota, local workspace",
5
5
  "license": "UNLICENSED",
6
6
  "homepage": "https://www.sisu.chat",