ispbills-icli 8.5.7 → 8.5.8

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/bin/icli.js CHANGED
@@ -320,6 +320,9 @@ async function main() {
320
320
  if (has('--experimental')) {
321
321
  cfg.tui = { ...(cfg.tui || {}), experimental: true };
322
322
  }
323
+ if (has('--cloud')) {
324
+ cfg.tui = { ...(cfg.tui || {}), cloud: true };
325
+ }
323
326
  if (flag('--allow-tool')) {
324
327
  const tool = flag('--allow-tool');
325
328
  cfg.tui = { ...(cfg.tui || {}), allowedTools: [...(cfg.tui?.allowedTools || []), tool] };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ispbills-icli",
3
- "version": "8.5.7",
3
+ "version": "8.5.8",
4
4
  "description": "iCli — IspBills AI network engineer in your terminal",
5
5
  "keywords": [
6
6
  "ispbills",
package/src/tui/app.js CHANGED
@@ -442,6 +442,17 @@ export function App({ cfg, display = {}, onExternal, onExit, initialQuestion, sh
442
442
  if (!trusted && !choice) openTrustDialog(process.cwd());
443
443
  }, [trusted, choice, openTrustDialog]);
444
444
 
445
+ // §2 (stage 3): auth check — once the folder is trusted, warn if no token.
446
+ const authNoticeRef = useRef(false);
447
+ useEffect(() => {
448
+ if (!trusted || authNoticeRef.current) return;
449
+ const isAuth = Boolean(cfg?.user?.name || cfg?.user?.email || cfg?.apiKey || cfg?._token);
450
+ if (!isAuth) {
451
+ authNoticeRef.current = true;
452
+ pushNotice(`${glyphs.warn} Not authenticated — run /login to connect.`, C.warning, false);
453
+ }
454
+ }, [trusted, cfg, pushNotice]);
455
+
445
456
  const doExit = useCallback(() => { onExit?.(plain.current); exit(); }, [exit, onExit]);
446
457
 
447
458
  const maybeProcessQueue = useCallback(() => {
@@ -1779,7 +1790,7 @@ export function App({ cfg, display = {}, onExternal, onExit, initialQuestion, sh
1779
1790
  case 'activity': return html`<${StatusLines} key=${it.id} lines=${it.status} busy=${false} />`;
1780
1791
  case 'notice': return html`<${Notice} key=${it.id} text=${it.text} color=${it.color} />`;
1781
1792
  case 'info': return html`<${LabeledNotice} key=${it.id} label="ℹ Info" text=${it.text} color=${C.muted} bodyColor=${it.color || C.white} cols=${c} ts=${it.ts} />`;
1782
- case 'error': return html`<${LabeledNotice} key=${it.id} label=" Error" text=${it.text} color=${C.error} bodyColor=${it.color || C.white} cols=${c} ts=${it.ts} />`;
1793
+ case 'error': return html`<${LabeledNotice} key=${it.id} label=" Error" text=${it.text} color=${C.error} bodyColor=${it.color || C.white} cols=${c} ts=${it.ts} />`;
1783
1794
  case 'system': return html`<${LabeledNotice} key=${it.id} label="⚙ System" text=${it.text} color=${C.muted} bodyColor=${it.color || C.white} cols=${c} ts=${it.ts} />`;
1784
1795
  case 'shell': return html`<${ShellOutput} key=${it.id} command=${it.command} output=${it.output} code=${it.code} cols=${c} ts=${it.ts} />`;
1785
1796
  case 'help': return html`<${HelpOverlay} key=${it.id} cols=${c} ts=${it.ts} />`;
@@ -121,7 +121,7 @@ export function TabBar({ active = 'session', cols = 80, mode = 'ask' }) {
121
121
  ${i > 0 ? html`<${Text} color="cyan" backgroundColor="blue"> <//>` : null}
122
122
  ${on
123
123
  ? html`<${Text} color="white" bold backgroundColor="blue">[${t.label}]<//>`
124
- : html`<${Text} color="cyan" backgroundColor="blue">${t.label}<//>`}
124
+ : html`<${Text} color="white" dimColor backgroundColor="blue">${t.label}<//>`}
125
125
  <//>`;
126
126
  })}
127
127
  <//>
@@ -251,11 +251,13 @@ function StreamingText({ text = '' }) {
251
251
  }
252
252
 
253
253
  export function AssistantMessage({ text, cols = 80, ts, label = `${glyphs.copilotDot} iCopilot`, streaming = false }) {
254
+ // §11: response content box capped at 100 columns; separators stay full-width (§6).
255
+ const bodyWidth = Math.min(cols, 100);
254
256
  return html`
255
257
  <${Box} flexDirection="column" marginTop=${1}>
256
258
  <${Sep} cols=${cols} />
257
259
  <${SpeakerLine} label=${label} color=${C.accent} cols=${cols} ts=${ts} />
258
- <${Box} paddingX=${2} flexDirection="column">
260
+ <${Box} paddingX=${2} flexDirection="column" width=${bodyWidth}>
259
261
  ${streaming ? html`<${StreamingText} text=${text} />` : html`<${Markdown} content=${text} />`}
260
262
  <//>
261
263
  <//>`;
@@ -3,7 +3,7 @@
3
3
  // the input and is navigable with the arrow keys.
4
4
  import { html, useState, useEffect, useCallback, useRef } from './dom.js';
5
5
  import { Box, Text, useInput } from 'ink';
6
- import { C, glyphs } from './theme.js';
6
+ import { C, glyphs, asciiSafe } from './theme.js';
7
7
  import { SLASH_COMMANDS } from '../commands.js';
8
8
  import { readFileSync, writeFileSync, rmSync, readdirSync, statSync } from 'fs';
9
9
  import { join, basename, dirname, resolve } from 'path';
@@ -530,6 +530,6 @@ export function Composer({
530
530
  <//>`
531
531
  : null}
532
532
 
533
- <${Text} color=${C.separator}>${'─'.repeat(Math.max(1, width))}<//>
533
+ <${Text} color=${C.separator}>${(asciiSafe() ? '-' : '─').repeat(Math.max(1, width))}<//>
534
534
  <//>`;
535
535
  }
package/src/tui/run.js CHANGED
@@ -14,7 +14,7 @@ const LOGO = [
14
14
  ];
15
15
  const COLORS = ['35', '95', '94', '96', '97'];
16
16
 
17
- async function animateSplash() {
17
+ async function animateSplash(cfg = {}) {
18
18
  if (!process.stdout.isTTY) return;
19
19
  for (let frame = 0; frame < COLORS.length; frame++) {
20
20
  const color = COLORS[frame];
@@ -23,6 +23,21 @@ async function animateSplash() {
23
23
  await new Promise((resolve) => setTimeout(resolve, 110));
24
24
  if (frame !== COLORS.length - 1) process.stdout.write(`\x1b[${LOGO.length}A`);
25
25
  }
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`);
37
+ const isAuth = Boolean(cfg?.user?.name || cfg?.user?.email || cfg?.apiKey || cfg?._token);
38
+ if (!isAuth) {
39
+ process.stdout.write(`\n ${WARN}⚠ Not authenticated — run ${R}${ACCENT}/login${R}${WARN} to connect.${R}\n`);
40
+ }
26
41
  process.stdout.write('\n');
27
42
  }
28
43
 
@@ -33,7 +48,7 @@ export async function runTui(cfg, opts = {}) {
33
48
  const showAnimation = banner || !seen;
34
49
 
35
50
  if (showAnimation) {
36
- await animateSplash();
51
+ await animateSplash(cfg);
37
52
  cfg.tui = { ...(cfg.tui || {}), bannerSeen: true };
38
53
  try { saveConfig(cfg); } catch {}
39
54
  }