ispbills-icli 8.5.7 → 8.5.9
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 +3 -0
- package/package.json +1 -1
- package/src/tui/app.js +13 -2
- package/src/tui/components.js +8 -5
- package/src/tui/composer.js +2 -2
- package/src/tui/run.js +17 -2
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
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(() => {
|
|
@@ -695,7 +706,7 @@ export function App({ cfg, display = {}, onExternal, onExit, initialQuestion, sh
|
|
|
695
706
|
setChoice({
|
|
696
707
|
title: '⚙ Tool request',
|
|
697
708
|
note: toolDesc,
|
|
698
|
-
sel: 0, text: '', focusText: false, allowText:
|
|
709
|
+
sel: 0, text: '', focusText: false, allowText: true,
|
|
699
710
|
isToolApproval: true,
|
|
700
711
|
options: [
|
|
701
712
|
{ label: '1. Yes', value: 'yes, proceed with this tool call' },
|
|
@@ -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="
|
|
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} />`;
|
package/src/tui/components.js
CHANGED
|
@@ -90,7 +90,7 @@ function formatTs(ts) {
|
|
|
90
90
|
function SpeakerLine({ label, color, cols = 80, ts, rightLabel = '' }) {
|
|
91
91
|
const stamp = ts ? `[${formatTs(ts)}]` : '';
|
|
92
92
|
return html`
|
|
93
|
-
<${Box} paddingX=${
|
|
93
|
+
<${Box} paddingX=${1} marginTop=${1} width=${cols}>
|
|
94
94
|
<${Text} color=${color} bold>${label}<//>
|
|
95
95
|
<${Box} flexGrow=${1} />
|
|
96
96
|
${rightLabel ? html`<${Text} color=${C.muted}>${rightLabel}<//>` : null}
|
|
@@ -118,10 +118,10 @@ export function TabBar({ active = 'session', cols = 80, mode = 'ask' }) {
|
|
|
118
118
|
const on = t.id === active;
|
|
119
119
|
return html`
|
|
120
120
|
<${Box} key=${t.id}>
|
|
121
|
-
${i > 0 ? html`<${Text}
|
|
121
|
+
${i > 0 ? html`<${Text} backgroundColor="blue"> <//>` : null}
|
|
122
122
|
${on
|
|
123
123
|
? html`<${Text} color="white" bold backgroundColor="blue">[${t.label}]<//>`
|
|
124
|
-
: html`<${Text} color="
|
|
124
|
+
: html`<${Text} color="white" dimColor backgroundColor="blue">${t.label}<//>`}
|
|
125
125
|
<//>`;
|
|
126
126
|
})}
|
|
127
127
|
<//>
|
|
@@ -221,7 +221,7 @@ export function UserMessage({ text, cols = 80, ts }) {
|
|
|
221
221
|
<${Box} flexDirection="column" marginTop=${1}>
|
|
222
222
|
<${Sep} cols=${cols} />
|
|
223
223
|
<${SpeakerLine} label="You" color=${C.brand} cols=${cols} ts=${ts} />
|
|
224
|
-
<${Box} paddingX=${
|
|
224
|
+
<${Box} paddingX=${1}>
|
|
225
225
|
<${Text}>${withMentions(text)}<//>
|
|
226
226
|
<//>
|
|
227
227
|
<//>`;
|
|
@@ -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=${
|
|
260
|
+
<${Box} paddingX=${1} flexDirection="column" width=${bodyWidth}>
|
|
259
261
|
${streaming ? html`<${StreamingText} text=${text} />` : html`<${Markdown} content=${text} />`}
|
|
260
262
|
<//>
|
|
261
263
|
<//>`;
|
|
@@ -516,6 +518,7 @@ export function Choice({ title, note, options = [], sel = 0, allowText = false,
|
|
|
516
518
|
<${Box} paddingX=${2} marginTop=${1}>
|
|
517
519
|
<${Text} color=${C.accent} bold>⚙ Tool request<//>
|
|
518
520
|
<//>
|
|
521
|
+
<${Sep} cols=${80} />
|
|
519
522
|
${note ? html`<${Box} paddingX=${2} marginTop=${1}><${Text} color=${C.muted}>${note}<//><//>` : null}
|
|
520
523
|
<${Box} flexDirection="column" marginTop=${1} paddingX=${2}>
|
|
521
524
|
${options.map((o, i) => {
|
package/src/tui/composer.js
CHANGED
|
@@ -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
|
}
|