agen-vektor 0.3.32 → 0.3.33

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/README.md CHANGED
@@ -471,6 +471,11 @@ secrets stay private):
471
471
 
472
472
  ## Changelog
473
473
 
474
+ ### 0.3.33
475
+ - **Boot splash "Loading System . . ." before the TUI dashboard.** Launching `vector` now shows a brief boot screen — brand banner, three loading steps (Config → Environment → Provider), a braille spinner and progress bar, then "System ready" — before the whole block is cleanly erased and the chat TUI enters alt-screen. Zero scrollback residue.
476
+ - **Zero dependencies, Termux-safe.** The splash follows `VECTOR_ASCII` (spinner becomes `|/-\` in ASCII safe mode), never blocks process exit (timer is unref'd), and failure to build the agent still clears the splash before the error propagates.
477
+ - **Controls:** `VECTOR_SPLASH=0` disables it entirely; `VECTOR_SPLASH_STEP_MS` (default 450) and `VECTOR_SPLASH_HOLD_MS` (default 900) tune the timing.
478
+
474
479
  ### 0.3.30
475
480
  - **Thinking card matches Freebuff `thinking.tsx` exactly — no mid-run color flip-flop.** The reasoning body renders muted (`#acb3bf`) italic in BOTH streaming and completed states; only the header (dot + bold "Thinking") is foreground-white. Previously the body flipped from white (streaming) to muted (done), which read as the card changing color during a run.
476
481
  - **Expanded thinking view is raw muted italic with word wrap.** The in-card markdown re-render was removed — headings/inline code no longer paint their own colors inside the card (the mixed-color expanded view read as noise). Markdown markers in reasoning now show as-is, uniformly styled.
package/dist/cli/index.js CHANGED
@@ -22,6 +22,7 @@ const factory_1 = require("../providers/factory");
22
22
  const paths_1 = require("../utils/paths");
23
23
  const logger_1 = require("../utils/logger");
24
24
  const keyboard_1 = require("./keyboard");
25
+ const splash_1 = require("./splash");
25
26
  const terminal_1 = require("../utils/terminal");
26
27
  /** Disable auto-wrap margins (DECAWM off): a full-width row then CANNOT
27
28
  * push the cursor into the pending-wrap state, so the next write can never
@@ -248,7 +249,21 @@ async function runTui(opts) {
248
249
  await runNonInteractive(opts);
249
250
  return;
250
251
  }
251
- const agent = await buildAgent(opts);
252
+ // Boot splash "Loading System . . ." (additive, 2026-09-16): tampil
253
+ // sebelum buildAgent/loading dashboard; VECTOR_SPLASH=0 mematikan.
254
+ const splash = await (0, splash_1.runSplash)();
255
+ let agent;
256
+ try {
257
+ await splash.step('config dimuat');
258
+ agent = await buildAgent(opts);
259
+ await splash.step('environment siap');
260
+ await splash.step(`provider ${opts.provider || agent.config.provider}`);
261
+ await splash.finish();
262
+ }
263
+ catch (err) {
264
+ await splash.finish();
265
+ throw err;
266
+ }
252
267
  const config = agent.config;
253
268
  // OpenCode-style theming: --theme wins, then VECTOR_THEME (already folded
254
269
  // into config via effectiveConfig inside the Agent), then config.json.
@@ -0,0 +1,167 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.splashEnabled = splashEnabled;
4
+ exports.runSplash = runSplash;
5
+ /**
6
+ * Boot splash — "Loading System . . ." (2026-09-16).
7
+ *
8
+ * Additive fitur: ditampilkan HANYA di runTui (interactive TTY) sebelum
9
+ * dashboard chat TUI masuk alt-screen. Tidak menyentuh agent, provider,
10
+ * maupun TUI — murni penggambar ANSI di buffer utama lalu DIHAPUS BERSIH
11
+ * sebelum TUI mulai (tidak meninggalkan sampah scrollback).
12
+ *
13
+ * Zero dependency: hanya ANSI escape dari utils/terminal. ASCII safe mode
14
+ * (VECTOR_ASCII=1) otomatis: spinner & simbol di-ganti varian 1 kolom via
15
+ * toAsciiSafe agar tidak merobek layout di Termux/font CJK.
16
+ *
17
+ * Skip: VECTOR_SPLASH=0 mematikan splash sepenuhnya (zero delay) — cocok
18
+ * untuk skrip/otomasi. Step delay bisa diatur VECTOR_SPLASH_STEP_MS.
19
+ */
20
+ const terminal_1 = require("../utils/terminal");
21
+ /** Spinner frames — braille di mode normal, 1-kolom ASCII di ASCII mode. */
22
+ const SPINNER_BRAILLE = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
23
+ const SPINNER_ASCII = ['|', '/', '-', '\\'];
24
+ /** Warna brand (independen dari THEME — theme di-apply SETELAH buildAgent). */
25
+ const ORANGE = '\x1b[38;2;255;133;52m'; // #FF8534 — aksen VectorHead
26
+ const GREEN = '\x1b[38;2;159;252;98m'; // #9EFC62 — sukses VectorHead
27
+ const WHITE = '\x1b[97m';
28
+ const DIM = terminal_1.ANSI.dim;
29
+ const RESET = terminal_1.ANSI.reset;
30
+ /** Jeda per step agar urutan loading terasa (bisa di-override untuk test). */
31
+ const STEP_DELAY_MS = Math.max(0, Number(process.env.VECTOR_SPLASH_STEP_MS ?? 450));
32
+ /** Jeda "System ready" sebelum blok dihapus. */
33
+ const FINISH_HOLD_MS = Math.max(0, Number(process.env.VECTOR_SPLASH_HOLD_MS ?? 900));
34
+ /** Lebar progress bar (kolom). */
35
+ const BAR_WIDTH = 22;
36
+ /** Splash aktif? VECTOR_SPLASH=0 mematikan (env menang, default ON). */
37
+ function splashEnabled() {
38
+ const v = process.env['VECTOR_SPLASH'];
39
+ if (v === undefined)
40
+ return true;
41
+ return v !== '0' && v.toLowerCase() !== 'false';
42
+ }
43
+ /** Panjang terlihat (kolom) dari string ber-ANSI milik splash sendiri. */
44
+ function visibleLen(painted) {
45
+ return painted.replace(/\x1b\[[0-9;]*[A-Za-z]/g, '').length;
46
+ }
47
+ /** Bar progress "███░░░░░ 45%" — satu kolom per glyph di kedua mode. */
48
+ function bar(fraction) {
49
+ const pct = Math.max(0, Math.min(1, fraction));
50
+ const filled = Math.round(BAR_WIDTH * pct);
51
+ return (GREEN + '█'.repeat(filled) + DIM + '░'.repeat(BAR_WIDTH - filled) + RESET +
52
+ ` ${Math.round(pct * 100)}%`);
53
+ }
54
+ /**
55
+ * Jalankan splash: banner sekali + spinner live row. Panggil `step()` per
56
+ * progress, akhiri dengan `finish()` (WAJIB — mengembalikan kursor).
57
+ * Menangani sendiri kasus lebar terminal ekstrim (kolom < 24 → bar disembunyikan).
58
+ */
59
+ async function runSplash() {
60
+ if (!splashEnabled()) {
61
+ // No-op handle: kode pemanggil tetap bisa memanggil step()/finish().
62
+ return { step: async () => { }, finish: async () => { } };
63
+ }
64
+ const out = process.stdout;
65
+ const cols = Math.max(1, (0, terminal_1.getTerminalSize)().cols);
66
+ const ascii = terminal_1.toAsciiSafe; // ASCII safe mode mengikuti VECTOR_ASCII/Termux
67
+ const frames = asciiModeFrames();
68
+ const showBar = cols >= BAR_WIDTH + 30;
69
+ // Pusatkan satu baris (diukur dari versi TERPAINT agar ASCII map ikut dihitung).
70
+ const center = (text) => {
71
+ const painted = ascii(text);
72
+ const pad = Math.max(0, Math.floor((cols - visibleLen(painted)) / 2));
73
+ return ' '.repeat(pad) + text;
74
+ };
75
+ const lines = []; // jumlah baris yang sudah digambar (untuk clear di finish)
76
+ const write = (s) => {
77
+ out.write(ascii(s));
78
+ };
79
+ const paintLine = (s) => {
80
+ lines.push(s);
81
+ write(center(s) + '\r\n');
82
+ };
83
+ out.write(terminal_1.ANSI.hideCursor);
84
+ // ── Banner (sekali) ──────────────────────────────────────────────
85
+ paintLine(`${ORANGE}▮${RESET} ${WHITE}VectorHead${RESET} ${DIM}v${version()}${RESET}`);
86
+ paintLine(`${DIM}Initializing system components . . .${RESET}`);
87
+ paintLine('');
88
+ // ── Live row (spinner + label + bar) — di-rewrite di tempat ──────
89
+ let frame = 0;
90
+ let stepIndex = 0;
91
+ let label = 'Loading System';
92
+ const renderLive = () => {
93
+ const glyph = frames[frame % frames.length];
94
+ frame++;
95
+ const pct = Math.min(0.92, 0.15 + stepIndex * 0.22);
96
+ const text = `${GREEN}${glyph}${RESET} ${WHITE}${label}${RESET} ${DIM}.${RESET}${DIM}.${RESET}${DIM}.${RESET}` +
97
+ (showBar ? ` ${bar(pct)}` : '');
98
+ // Rewrite in place: kembali ke awal baris live lalu gambar ulang.
99
+ write('\r' + terminal_1.ANSI.clearLineEnd + center(text));
100
+ };
101
+ const liveTimer = setInterval(renderLive, 90);
102
+ // Timer TIDAK boleh menahan proses kalau splash ternyata tidak di-finish
103
+ // (crash path) — biarkan Node berhemi natural.
104
+ if (typeof liveTimer.unref === 'function')
105
+ liveTimer.unref();
106
+ renderLive();
107
+ await sleep(420); // momen awal "Loading System . . ." terlihat jelas
108
+ const names = ['Config', 'Environment', 'Provider'];
109
+ return {
110
+ async step(detail) {
111
+ const name = names[Math.min(stepIndex, names.length - 1)];
112
+ stepIndex++;
113
+ // Ganti live row dengan baris step selesai (append permanen).
114
+ const mark = ascii('✓') === '✓' ? '✓' : 'ok';
115
+ const check = `${GREEN}${mark}${RESET}`;
116
+ const info = detail ? ` ${DIM}${detail}${RESET}` : '';
117
+ write('\r' + terminal_1.ANSI.clearLineEnd); // hapus live row
118
+ paintLine(`${check} ${WHITE}${name}${RESET}${info}`);
119
+ label = `Loading ${names[Math.min(stepIndex, names.length - 1)] ?? 'System'}`;
120
+ renderLive();
121
+ await sleep(STEP_DELAY_MS);
122
+ },
123
+ async finish() {
124
+ clearInterval(liveTimer);
125
+ const mark = ascii('✓') === '✓' ? '✓' : 'ok';
126
+ write('\r' + terminal_1.ANSI.clearLineEnd);
127
+ paintLine(`${GREEN}${mark}${RESET} ${WHITE}System ready${RESET}`);
128
+ write(`\r\n${DIM}Starting VectorHead TUI . . .${RESET}`);
129
+ lines.push('', '');
130
+ await sleep(FINISH_HOLD_MS);
131
+ // Hapus seluruh blok splash → terminal bersih sebelum alt-screen TUI.
132
+ // Kursor berada DI baris terakhir (Starting…) → clearLine dulu, lalu
133
+ // naik + clear per baris tergambar (banner s.d. baris kosong terakhir).
134
+ let clear = terminal_1.ANSI.clearLine;
135
+ for (let i = 0; i < lines.length; i++)
136
+ clear += terminal_1.ANSI.cursorUp(1) + terminal_1.ANSI.clearLine;
137
+ out.write('\r' + clear);
138
+ out.write(terminal_1.ANSI.showCursor);
139
+ },
140
+ };
141
+ }
142
+ function asciiModeFrames() {
143
+ // toAsciiSafe memetakan braille → '*' (3 kolom? tidak — catchall 1 kolom),
144
+ // tapi spinner jadi tidak enak dilihat; varian ASCII asli lebih rapi.
145
+ try {
146
+ // Impur dinamis dihindari; cukup cek env yang sama dengan asciiModeEnabled.
147
+ const v = process.env['VECTOR_ASCII'];
148
+ const on = v !== undefined ? v !== '0' && v.toLowerCase() !== 'false' : false;
149
+ return on ? SPINNER_ASCII : SPINNER_BRAILLE;
150
+ }
151
+ catch {
152
+ return SPINNER_BRAILLE;
153
+ }
154
+ }
155
+ function sleep(ms) {
156
+ return new Promise((r) => setTimeout(r, ms));
157
+ }
158
+ function version() {
159
+ try {
160
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
161
+ const pkg = require('../../package.json');
162
+ return pkg.version || '0.0.0';
163
+ }
164
+ catch {
165
+ return '0.0.0';
166
+ }
167
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agen-vektor",
3
- "version": "0.3.32",
3
+ "version": "0.3.33",
4
4
  "description": "VectorHead (agen-vektor) — AI Coding Agent CLI/TUI for Linux & Termux. Multi-provider, tool calling, session, permission system.",
5
5
  "type": "commonjs",
6
6
  "bin": {