ispbills-icli 8.5.2 → 8.5.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/bin/icli.js +2 -1
- package/package.json +1 -1
- package/src/commands.js +38 -35
- package/src/tui/app.js +508 -202
- package/src/tui/components.js +115 -56
- package/src/tui/composer.js +239 -73
- package/src/tui/run.js +34 -7
package/bin/icli.js
CHANGED
|
@@ -109,6 +109,7 @@ function printHelp() {
|
|
|
109
109
|
|
|
110
110
|
console.log(`\n ${BOLD}Flags${RESET}`);
|
|
111
111
|
[
|
|
112
|
+
['--banner', 'Force-show the animated splash banner'],
|
|
112
113
|
['--reasoning', 'Stream reasoning inline (on by default)'],
|
|
113
114
|
['--no-reasoning', 'Hide the reasoning trace'],
|
|
114
115
|
['--loader-style STYLE', 'spinner | gradient | minimal'],
|
|
@@ -314,7 +315,7 @@ async function main() {
|
|
|
314
315
|
// Always use the Ink TUI — Ink handles non-TTY environments gracefully.
|
|
315
316
|
// The old readline REPL fallback is kept only for explicit pipe/script usage.
|
|
316
317
|
const { runTui } = await import('../src/tui/run.js');
|
|
317
|
-
const action = await runTui(cfg, { display });
|
|
318
|
+
const action = await runTui(cfg, { display, banner: has('--banner') });
|
|
318
319
|
if (action === 'logout') {
|
|
319
320
|
const cleared = clearConfig();
|
|
320
321
|
console.log(`\n ${cleared ? GREEN + glyphs.check + RESET + ' Logged out — credentials cleared.' : YELLOW + 'Already logged out.' + RESET}`);
|
package/package.json
CHANGED
package/src/commands.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { RESET, BOLD, DIM, GRAY, WHITE, ACCENT
|
|
1
|
+
import { RESET, BOLD, DIM, GRAY, WHITE, ACCENT } from './ui.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* All slash commands, used for the menu, help and Tab completion.
|
|
@@ -43,6 +43,8 @@ export const SLASH_COMMANDS = [
|
|
|
43
43
|
|
|
44
44
|
// ── Backups & version control ──
|
|
45
45
|
{ cmd: '/git', hint: '[args]', desc: 'Run git in your backup repo (status/commit/push/log)', group: 'Backups', local: true },
|
|
46
|
+
{ cmd: '/diff', hint: '', desc: 'Show the recent backup-repo diff', group: 'Backups', local: true },
|
|
47
|
+
{ cmd: '/review', hint: '[focus]', desc: 'Review the last AI answer', group: 'Backups', local: true },
|
|
46
48
|
{ cmd: '/gist', hint: '', desc: 'Save the last answer or transcript to a GitHub gist', group: 'Backups', local: true },
|
|
47
49
|
|
|
48
50
|
// ── Memory ──
|
|
@@ -52,26 +54,34 @@ export const SLASH_COMMANDS = [
|
|
|
52
54
|
{ cmd: '/copy', hint: '', desc: 'Copy the last AI answer to the clipboard', group: 'Memory', local: true },
|
|
53
55
|
|
|
54
56
|
// ── Session & app ──
|
|
55
|
-
{ cmd: '/plan',
|
|
56
|
-
{ cmd: '/autopilot',
|
|
57
|
-
{ cmd: '/
|
|
58
|
-
{ cmd: '/
|
|
59
|
-
{ cmd: '/
|
|
60
|
-
{ cmd: '/
|
|
61
|
-
{ cmd: '/
|
|
62
|
-
{ cmd: '/
|
|
63
|
-
{ cmd: '/
|
|
64
|
-
{ cmd: '/
|
|
65
|
-
{ cmd: '/
|
|
66
|
-
{ cmd: '/
|
|
67
|
-
{ cmd: '/
|
|
68
|
-
{ cmd: '/
|
|
69
|
-
{ cmd: '/
|
|
70
|
-
{ cmd: '/
|
|
71
|
-
{ cmd: '/
|
|
57
|
+
{ cmd: '/plan', hint: '[prompt]', desc: 'Switch to plan mode (Shift+Tab to cycle)', group: 'Session', local: true },
|
|
58
|
+
{ cmd: '/autopilot', hint: '', desc: 'Toggle autopilot mode (auto-apply fixes)', group: 'Session', local: true },
|
|
59
|
+
{ cmd: '/allow-all', hint: '[on|off|show]', desc: 'Toggle auto-approval mode', group: 'Session', local: true },
|
|
60
|
+
{ cmd: '/model', hint: '[name]', desc: 'Show or set the AI model', group: 'Session', local: true },
|
|
61
|
+
{ cmd: '/reasoning', hint: '', desc: 'Toggle reasoning display (Ctrl+T)', group: 'Session', local: true },
|
|
62
|
+
{ cmd: '/context', hint: '', desc: 'Show context window token usage', group: 'Session', local: true },
|
|
63
|
+
{ cmd: '/usage', hint: '', desc: 'Show session usage metrics', group: 'Session', local: true },
|
|
64
|
+
{ cmd: '/compact', hint: '[focus]', desc: 'Compress conversation history', group: 'Session', local: true },
|
|
65
|
+
{ cmd: '/session', hint: '', desc: 'Show session info (cwd, branch, tokens)', group: 'Session', local: true },
|
|
66
|
+
{ cmd: '/resume', hint: '[id]', desc: 'Show session stats / resume info', group: 'Session', local: true },
|
|
67
|
+
{ cmd: '/rename', hint: '[name]', desc: 'Rename this session', group: 'Session', local: true },
|
|
68
|
+
{ cmd: '/share', hint: '', desc: 'Share session to a GitHub gist', group: 'Session', local: true },
|
|
69
|
+
{ cmd: '/theme', hint: '', desc: 'View current colour theme info', group: 'Session', local: true },
|
|
70
|
+
{ cmd: '/cwd', hint: '', desc: 'Show the current working directory', group: 'Session', local: true },
|
|
71
|
+
{ cmd: '/cd', hint: '[path]', desc: 'Change the working directory', group: 'Session', local: true },
|
|
72
|
+
{ cmd: '/env', hint: '', desc: 'Show loaded environment info', group: 'Session', local: true },
|
|
73
|
+
{ cmd: '/streamer-mode', hint: '', desc: 'Hide model names and token counts', group: 'Session', local: true },
|
|
74
|
+
{ cmd: '/new', hint: '', desc: 'Start a fresh conversation', group: 'Session', local: true },
|
|
75
|
+
{ cmd: '/history', hint: '', desc: 'Show conversation history', group: 'Session', local: true },
|
|
76
|
+
{ cmd: '/clear', hint: '', desc: 'Clear the screen', group: 'Session', local: true },
|
|
77
|
+
{ cmd: '/changelog', hint: '', desc: 'Show recent npm package releases', group: 'Session', local: true },
|
|
78
|
+
{ cmd: '/feedback', hint: '', desc: 'Show the feedback / bug-report URL', group: 'Session', local: true },
|
|
79
|
+
{ cmd: '/update', hint: '', desc: 'Update iCli to the latest version', group: 'Session', local: true },
|
|
80
|
+
{ cmd: '/logout', hint: '', desc: 'Log out and clear credentials', group: 'Session', local: true },
|
|
81
|
+
{ cmd: '/help', hint: '', desc: 'Show help', group: 'Session', local: true },
|
|
82
|
+
{ cmd: '/exit', hint: '', desc: 'Exit iCli', group: 'Session', local: true },
|
|
72
83
|
];
|
|
73
84
|
|
|
74
|
-
/** readline completer for slash commands (used by the non-Ink fallback REPL). */
|
|
75
85
|
export function slashCompleter(line) {
|
|
76
86
|
if (line.startsWith('/')) {
|
|
77
87
|
const hits = SLASH_COMMANDS.map((s) => s.cmd + ' ').filter((s) => s.startsWith(line));
|
|
@@ -80,16 +90,11 @@ export function slashCompleter(line) {
|
|
|
80
90
|
return [[], line];
|
|
81
91
|
}
|
|
82
92
|
|
|
83
|
-
/**
|
|
84
|
-
* Map a NOC shortcut command to a natural-language question for the AI.
|
|
85
|
-
* Returns null for commands that are handled locally by the REPL.
|
|
86
|
-
*/
|
|
87
93
|
export function slashToQuestion(line) {
|
|
88
94
|
const [sc, ...rest] = line.trim().split(/\s+/);
|
|
89
95
|
const arg = rest.join(' ');
|
|
90
96
|
const on = (withArg, without) => (arg ? withArg : without);
|
|
91
97
|
switch (sc) {
|
|
92
|
-
// Devices & diagnostics
|
|
93
98
|
case '/check': return on(`run full diagnostics on ${arg} and summarise any problems`, 'run diagnostics across all devices and flag anything unhealthy');
|
|
94
99
|
case '/status': return on(`give a health summary for ${arg}`, 'give a health summary of every device in the fleet');
|
|
95
100
|
case '/reachable': return 'which devices are reachable right now and which are down?';
|
|
@@ -102,7 +107,6 @@ export function slashToQuestion(line) {
|
|
|
102
107
|
case '/reboot': return on(`reboot ${arg} safely`, 'which device should I reboot? list the devices first');
|
|
103
108
|
case '/alarms': return 'show active alarms and recent faults across the network';
|
|
104
109
|
|
|
105
|
-
// Optical / access
|
|
106
110
|
case '/onu': return on(`show ONU ${arg} status and optical signal level`, 'list all ONUs with their status and signal levels');
|
|
107
111
|
case '/optical': return on(`show optical RX/TX power in dBm for ${arg} and flag weak signals`, 'show optical RX/TX power across ONUs and flag any weak or out-of-range signals');
|
|
108
112
|
case '/vlan': return on(`is VLAN ${arg} in use or free across the network?`, 'list all VLANs and show which are in use or free');
|
|
@@ -110,10 +114,10 @@ export function slashToQuestion(line) {
|
|
|
110
114
|
case '/online': return 'list currently online PPPoE sessions';
|
|
111
115
|
case '/offline': {
|
|
112
116
|
const t = arg.toLowerCase();
|
|
113
|
-
if (/olt/.test(t))
|
|
117
|
+
if (/olt/.test(t)) return 'list all OLTs that are currently offline or unreachable';
|
|
114
118
|
if (/rout|nas|mikrotik|router/.test(t)) return 'list all routers / NAS devices that are currently offline or unreachable';
|
|
115
|
-
if (/onu|ont/.test(t))
|
|
116
|
-
if (/cust|client|user/.test(t))
|
|
119
|
+
if (/onu|ont/.test(t)) return 'list all ONUs that are currently offline';
|
|
120
|
+
if (/cust|client|user/.test(t)) return 'list all customers that are currently offline';
|
|
117
121
|
return arg
|
|
118
122
|
? `list all ${arg} that are currently offline`
|
|
119
123
|
: 'list everything that is currently offline — OLTs, routers and ONUs';
|
|
@@ -121,17 +125,16 @@ export function slashToQuestion(line) {
|
|
|
121
125
|
case '/down': return on(`is the ${arg} circuit / uplink down? show its status`, 'list all down circuits, uplinks or backbone links across the network');
|
|
122
126
|
case '/bandwidth': return on(`show traffic and bandwidth usage on ${arg}`, 'show current bandwidth usage across the network and flag the top talkers');
|
|
123
127
|
|
|
124
|
-
// Layer 2/3 lookups
|
|
125
128
|
case '/mac': return on(`locate MAC address ${arg} — which device and port is it on?`, 'how do I locate a MAC address? ask me for the address');
|
|
126
129
|
case '/arp': return on(`show the ARP table for ${arg}`, 'show ARP tables and flag any duplicate or suspicious entries');
|
|
127
130
|
case '/route': return on(`show the routing table for ${arg}`, 'show routing tables across the network');
|
|
128
131
|
case '/overlaps': {
|
|
129
132
|
const t = arg.toLowerCase();
|
|
130
|
-
if (/vlan/.test(t))
|
|
131
|
-
if (/bgp|prefix|as\b|peer/.test(t))
|
|
132
|
-
if (/route|routing/.test(t))
|
|
133
|
-
if (/int|port/.test(t))
|
|
134
|
-
if (/ip|subnet|network|cidr/.test(t))
|
|
133
|
+
if (/vlan/.test(t)) return 'scan all devices for duplicate or overlapping VLAN ids and list each conflict with the devices/interfaces involved';
|
|
134
|
+
if (/bgp|prefix|as\b|peer/.test(t)) return 'check BGP for overlapping or conflicting prefixes and duplicate AS announcements across routers and list each conflict';
|
|
135
|
+
if (/route|routing/.test(t)) return 'find overlapping or conflicting routes across the routing tables and list each pair with the devices involved';
|
|
136
|
+
if (/int|port/.test(t)) return 'find interfaces/ports with overlapping or duplicate address or VLAN assignments and list each conflict';
|
|
137
|
+
if (/ip|subnet|network|cidr/.test(t)) return 'find overlapping or conflicting IP subnets and duplicate IP addresses across the network and list each conflict with the devices involved';
|
|
135
138
|
return 'scan the whole network for any overlapping or conflicting IP subnets, duplicate IPs, duplicate/overlapping VLAN ids, interface assignment conflicts, and overlapping BGP prefixes or routes — list each conflict grouped by type with the devices involved';
|
|
136
139
|
}
|
|
137
140
|
case '/flapping': return on(`check ${arg} for flapping interfaces — list ports with frequent up/down transitions, their flap counts and last change time`, 'scan all devices for flapping interfaces (frequent up/down transitions) and list them with flap counts and the last state-change time');
|
|
@@ -140,7 +143,7 @@ export function slashToQuestion(line) {
|
|
|
140
143
|
case '/trace': return on(`traceroute the path to ${arg} and show each hop`, 'what host should I traceroute?');
|
|
141
144
|
case '/customer': return on(`look up customer ${arg} with their device, plan and session status`, 'show recently active customers');
|
|
142
145
|
|
|
143
|
-
default: return null;
|
|
146
|
+
default: return null;
|
|
144
147
|
}
|
|
145
148
|
}
|
|
146
149
|
|