ispbills-icli 8.6.5 → 8.6.7

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": "ispbills-icli",
3
- "version": "8.6.5",
3
+ "version": "8.6.7",
4
4
  "description": "iCli — IspBills AI network engineer in your terminal",
5
5
  "keywords": [
6
6
  "ispbills",
package/src/tui/app.js CHANGED
@@ -1822,7 +1822,7 @@ export function App({ cfg, display = {}, onExternal, onExit, initialQuestion, sh
1822
1822
  <${Box} flexDirection="column" width=${cols}>
1823
1823
  <${Static} key=${clearEpoch} items=${staticItems}>
1824
1824
  ${(it) => it.type === 'banner'
1825
- ? html`<${Box} key=${it.id} flexDirection="column" alignItems="center">
1825
+ ? html`<${Box} key=${it.id} flexDirection="column" alignItems="center" width=${cols}>
1826
1826
  <${Banner} cfg=${cfg} model=${model} width=${cols} compact=${compact} streamerMode=${streamerMode} />
1827
1827
  <//>`
1828
1828
  : renderItem(it)}
@@ -187,32 +187,41 @@ export function Banner({ cfg = {}, model, width = 80, compact = false, streamerM
187
187
  }
188
188
 
189
189
  return html`
190
- <${Box} flexDirection="column" marginBottom=${1} alignItems="center">
190
+ <${Box} flexDirection="column" marginBottom=${1} alignItems="center" width=${width}>
191
191
  ${wide
192
- ? html`<${Box} flexDirection="column" alignItems="center">
192
+ ? html`<${Box} flexDirection="column" alignItems="center" width=${width}>
193
193
  ${LOGO.map((l, i) => html`<${Text} key=${'l' + i} color=${C.accent} bold>${l}<//>`)}
194
- <${Text} color=${C.muted}>iCopilot ${dash()} IspBills network engineer in your terminal<//>
195
194
  <//>`
196
- : html`<${Text} color=${C.accent} bold>iCopilot ${html`<${Text} color=${C.muted}>${dash()} IspBills AI terminal<//>`}<//>`}
197
- <${Box} marginTop=${1}>
195
+ : html`<${Text} color=${C.accent} bold>◈ iCopilot ${html`<${Text} color=${C.muted}>${dash()} IspBills AI terminal<//>`}<//>` }
196
+
197
+ ${wide ? html`<${Text} color=${C.separator}>${'─'.repeat(Math.max(1, width))}<//>\n` : null}
198
+
199
+ <${Box} marginTop=${wide ? 0 : 1} justifyContent="center">
200
+ <${Text} color=${C.accent} bold>◈ iCopilot<//>
201
+ <${Text} color=${C.muted}> ${dash()} IspBills network engineer in your terminal<//>
202
+ <//>
203
+
204
+ ${wide ? html`<${Text} color=${C.separator}>${'─'.repeat(Math.max(1, width))}<//>\n` : null}
205
+
206
+ ${meta.length ? html`<${Box} marginTop=${1} justifyContent="center">
198
207
  ${meta.map(([label, val], i) => html`
199
208
  <${Box} key=${'m' + i}>
200
209
  ${i > 0 ? html`<${Text} color=${C.muted}>${midDot()}<//>` : null}
201
210
  <${Text} color=${C.muted}>${label} <//>
202
211
  <${Text} color=${label === 'model' ? C.accent : C.brand}>${val}<//>
203
212
  <//>`)}
213
+ <//>` : null}
214
+
215
+ ${cfg.url ? html`<${Box} justifyContent="center"><${Text} color=${C.muted}>${cfg.url}<//><//>` : null}
216
+
217
+ <${Box} flexDirection="column" marginTop=${1} alignItems="center" width=${width}>
218
+ <${Box} paddingX=${2} flexDirection="column">
219
+ <${Text} color=${C.muted} dimColor> ${' @ '}${html`<${Text} color=${C.accent}>@<//>`} mention files · ${html`<${Text} color=${C.accent}>/<//>`} commands · ${html`<${Text} color=${C.accent}>?<//>`} help · ${html`<${Text} color=${C.accent}>!<//>` } shell<//>
220
+ <//>
204
221
  <//>
205
- ${cfg.url ? html`<${Text} color=${C.muted}>${cfg.url}<//>` : null}
206
-
207
- <${Box} flexDirection="column" marginTop=${1} paddingX=${2} alignSelf="flex-start">
208
- <${Text} color=${C.muted} bold>Quick start:<//>\n
209
- <${Text} color=${C.muted}> <${Text} color=${C.accent}>@<//> mention files or devices<//>
210
- <${Text} color=${C.muted}> <${Text} color=${C.accent}>/<//> slash commands<//>
211
- <${Text} color=${C.muted}> <${Text} color=${C.accent}>?<//> quick help overlay<//>
212
- <${Text} color=${C.muted}> <${Text} color=${C.accent}>!<//> run shell command<//>
213
- <//>
222
+
214
223
  ${!isAuth
215
- ? html`<${Box} marginTop=${1}>
224
+ ? html`<${Box} marginTop=${1} justifyContent="center">
216
225
  <${Text} color=${C.warning}>⚠ Not authenticated — run <//>
217
226
  <${Text} color=${C.slash} bold>/login<//>
218
227
  <${Text} color=${C.warning}> to connect.<//><//>`
package/src/tui/run.js CHANGED
@@ -4,39 +4,85 @@ import { render } from 'ink';
4
4
  import { App } from './app.js';
5
5
  import { saveConfig } from '../config.js';
6
6
 
7
+ // iCopilot wordmark in block letters
7
8
  const LOGO = [
8
- '██╗ ██████╗ ██████╗ ██████╗ ██╗██╗ ██████╗ ████████╗',
9
- '██║██╔════╝██╔═══██╗██╔══██╗██║██║ ██╔═══██╗╚══██╔══╝',
10
- '██║██║ ██║ ██║██████╔╝██║██║ ██║ ██║ ██║ ',
11
- '██║██║ ██║ ██║██╔═══╝ ██║██║ ██║ ██║ ██║ ',
12
- '██║╚██████╗╚██████╔╝██║ ██║███████╗╚██████╔╝ ██║ ',
13
- '╚═╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚═╝ ',
9
+ ' ██╗ ██████╗ ██████╗ ██████╗ ██╗██╗ ██████╗ ████████╗',
10
+ ' ██║██╔════╝██╔═══██╗██╔══██╗██║██║ ██╔═══██╗╚══██╔══╝',
11
+ ' ██║██║ ██║ ██║██████╔╝██║██║ ██║ ██║ ██║ ',
12
+ ' ██║██║ ██║ ██║██╔═══╝ ██║██║ ██║ ██║ ██║ ',
13
+ ' ██║╚██████╗╚██████╔╝██║ ██║███████╗╚██████╔╝ ██║ ',
14
+ ' ╚═╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚═╝ ',
15
+ ];
16
+
17
+ // ANSI gradient: dim purple → bright purple → bright blue → bright cyan
18
+ const FRAMES = [
19
+ LOGO.map((l) => `\x1b[2;35m${l}\x1b[0m`), // dim magenta
20
+ LOGO.map((l) => `\x1b[1;35m${l}\x1b[0m`), // bold magenta
21
+ LOGO.map((l, i) => i < 3 ? `\x1b[1;35m${l}\x1b[0m` : `\x1b[1;34m${l}\x1b[0m`), // split
22
+ LOGO.map((l) => `\x1b[1;34m${l}\x1b[0m`), // bold blue
23
+ LOGO.map((l, i) => i < 3 ? `\x1b[1;34m${l}\x1b[0m` : `\x1b[1;36m${l}\x1b[0m`), // split
24
+ LOGO.map((l) => `\x1b[1;36m${l}\x1b[0m`), // bold cyan
25
+ LOGO.map((l) => `\x1b[1;35m${l}\x1b[0m`), // back to bold magenta
14
26
  ];
15
- const COLORS = ['35', '95', '94', '96', '97'];
16
27
 
17
28
  async function animateSplash(cfg = {}) {
18
29
  if (!process.stdout.isTTY) return;
19
- for (let frame = 0; frame < COLORS.length; frame++) {
20
- const color = COLORS[frame];
21
- const lines = LOGO.map((line, idx) => `\x1b[${Math.min(frame + idx + 1, 5) > 3 ? '1' : '2'};${color}m${line}\x1b[0m`).join('\n');
22
- process.stdout.write(lines + '\n');
23
- await new Promise((resolve) => setTimeout(resolve, 110));
24
- if (frame !== COLORS.length - 1) process.stdout.write(`\x1b[${LOGO.length}A`);
30
+ const cols = process.stdout.columns || 80;
31
+ const logoW = LOGO[0].length;
32
+ const pad = ' '.repeat(Math.max(0, Math.floor((cols - logoW) / 2)));
33
+
34
+ // Phase 1: reveal lines one-by-one dim
35
+ for (let i = 0; i < LOGO.length; i++) {
36
+ process.stdout.write(`${pad}\x1b[2;35m${LOGO[i]}\x1b[0m\n`);
37
+ await new Promise((r) => setTimeout(r, 55));
25
38
  }
26
- // §3: welcome text, quick-start tips and a visible /login instruction.
27
- const DIM = '\x1b[2m';
28
- const ACCENT = '\x1b[38;5;141m';
29
- const WARN = '\x1b[38;5;179m';
30
- const R = '\x1b[0m';
31
- process.stdout.write(`\n ${ACCENT}iCopilot${R} ${DIM}— IspBills network engineer in your terminal${R}\n\n`);
32
- process.stdout.write(` ${DIM}Quick start:${R}\n`);
33
- process.stdout.write(` ${ACCENT}@${R}${DIM} mention files or devices${R}\n`);
34
- process.stdout.write(` ${ACCENT}/${R}${DIM} slash commands${R}\n`);
35
- process.stdout.write(` ${ACCENT}?${R}${DIM} quick help overlay${R}\n`);
36
- process.stdout.write(` ${ACCENT}!${R}${DIM} run a shell command${R}\n`);
39
+
40
+ // Phase 2: colour-cycle animation
41
+ for (let fi = 1; fi < FRAMES.length; fi++) {
42
+ process.stdout.write(`\x1b[${LOGO.length}A`);
43
+ for (const line of FRAMES[fi]) {
44
+ process.stdout.write(`${pad}${line}\n`);
45
+ }
46
+ await new Promise((r) => setTimeout(r, 90));
47
+ }
48
+
49
+ // Welcome section — centered
50
+ const DIM = '\x1b[2m';
51
+ const BOLD = '\x1b[1m';
52
+ const ACC = '\x1b[38;5;141m'; // #A371F7 purple
53
+ const BLU = '\x1b[38;5;75m'; // #58A6FF blue
54
+ const WARN = '\x1b[38;5;179m'; // #D29922 amber
55
+ const SEP = '\x1b[38;5;237m'; // #30363D separator
56
+ const R = '\x1b[0m';
57
+
58
+ const hr = `${SEP}${'─'.repeat(cols)}${R}`;
59
+ const subtitle = `${ACC}◈ iCopilot${R} ${DIM}IspBills network engineer in your terminal${R}`;
60
+ const subtitleLen = 10 + 2 + 46; // approx visual length
61
+ const subPad = ' '.repeat(Math.max(0, Math.floor((cols - subtitleLen) / 2)));
62
+
63
+ process.stdout.write(`\n${hr}\n`);
64
+ process.stdout.write(`${subPad}${subtitle}\n`);
65
+ process.stdout.write(`${hr}\n\n`);
66
+
67
+ // Quick-start tips in a two-column grid, centered
68
+ const tips = [
69
+ [`${ACC}@${R}`, 'mention files, devices, ONUs'],
70
+ [`${ACC}/${R}`, 'slash commands & autocomplete'],
71
+ [`${ACC}?${R}`, 'quick help overlay'],
72
+ [`${ACC}!${R}`, 'run shell command directly'],
73
+ [`${BLU}Shift+Tab${R}`, 'cycle Ask → Plan → Autopilot'],
74
+ [`${BLU}Ctrl+T${R}`, 'toggle reasoning display'],
75
+ ];
76
+ const tipW = 42;
77
+ const tipPad = ' '.repeat(Math.max(0, Math.floor((cols - tipW) / 2)));
78
+ process.stdout.write(`${tipPad}${DIM}Quick start:${R}\n`);
79
+ for (const [key, desc] of tips) {
80
+ process.stdout.write(`${tipPad} ${BOLD}${key}${R} ${DIM}${desc}${R}\n`);
81
+ }
82
+
37
83
  const isAuth = Boolean(cfg?.user?.name || cfg?.user?.email || cfg?.apiKey || cfg?._token);
38
84
  if (!isAuth) {
39
- process.stdout.write(`\n ${WARN}⚠ Not authenticatedrun ${R}${ACCENT}/login${R}${WARN} to connect.${R}\n`);
85
+ process.stdout.write(`\n${tipPad}${WARN}⚠ Not authenticated${R} ${DIM}run${R} ${ACC}/login${R} ${DIM}to connect${R}\n`);
40
86
  }
41
87
  process.stdout.write('\n');
42
88
  }