icoa-cli 1.6.2 → 1.7.1
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/dist/commands/env.js +244 -115
- package/dist/index.js +1 -1
- package/dist/repl.js +1 -1
- package/package.json +1 -1
package/dist/commands/env.js
CHANGED
|
@@ -1,72 +1,145 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import { execSync } from 'node:child_process';
|
|
3
3
|
import { platform } from 'node:os';
|
|
4
|
+
// Target Python version for full compatibility
|
|
5
|
+
const PYTHON_TARGET = '3.12';
|
|
6
|
+
// ══════════════════════════════════════════════════════════
|
|
7
|
+
// 27 Python Libraries — ALL LOCKED VERSIONS
|
|
8
|
+
// Tested on Python 3.12.x (recommended)
|
|
9
|
+
// ══════════════════════════════════════════════════════════
|
|
4
10
|
const PYTHON_LIBS = [
|
|
5
|
-
|
|
6
|
-
{ name: '
|
|
7
|
-
{ name: '
|
|
8
|
-
{ name: '
|
|
9
|
-
{ name: '
|
|
10
|
-
|
|
11
|
-
{ name: '
|
|
12
|
-
{ name: '
|
|
13
|
-
{ name: '
|
|
14
|
-
{ name: '
|
|
15
|
-
{ name: '
|
|
16
|
-
|
|
17
|
-
{ name: '
|
|
18
|
-
{ name: '
|
|
19
|
-
{ name: 'cryptography', check: 'python3 -c "import cryptography"', install: 'cryptography==42.0.0', category: '
|
|
20
|
-
|
|
21
|
-
{ name: '
|
|
22
|
-
{ name: '
|
|
23
|
-
{ name: '
|
|
24
|
-
{ name: '
|
|
11
|
+
// Core CTF
|
|
12
|
+
{ name: 'pwntools', check: 'python3 -c "import pwn"', install: 'pwntools==4.12.0', category: 'CTF Core' },
|
|
13
|
+
{ name: 'pycryptodome', check: 'python3 -c "import Crypto"', install: 'pycryptodome==3.20.0', category: 'CTF Core' },
|
|
14
|
+
{ name: 'z3-solver', check: 'python3 -c "import z3"', install: 'z3-solver==4.12.6', category: 'CTF Core' },
|
|
15
|
+
{ name: 'angr', check: 'python3 -c "import angr"', install: 'angr', category: 'CTF Core' },
|
|
16
|
+
// Networking & Web
|
|
17
|
+
{ name: 'requests', check: 'python3 -c "import requests"', install: 'requests==2.31.0', category: 'Web & Network' },
|
|
18
|
+
{ name: 'beautifulsoup4', check: 'python3 -c "import bs4"', install: 'beautifulsoup4==4.12.3', category: 'Web & Network' },
|
|
19
|
+
{ name: 'flask', check: 'python3 -c "import flask"', install: 'flask==3.0.0', category: 'Web & Network' },
|
|
20
|
+
{ name: 'scapy', check: 'python3 -c "import scapy"', install: 'scapy==2.5.0', category: 'Web & Network' },
|
|
21
|
+
{ name: 'paramiko', check: 'python3 -c "import paramiko"', install: 'paramiko==3.4.0', category: 'Web & Network' },
|
|
22
|
+
// Crypto & Math
|
|
23
|
+
{ name: 'sympy', check: 'python3 -c "import sympy"', install: 'sympy==1.12', category: 'Crypto & Math' },
|
|
24
|
+
{ name: 'gmpy2', check: 'python3 -c "import gmpy2"', install: 'gmpy2==2.1.5', category: 'Crypto & Math' },
|
|
25
|
+
{ name: 'cryptography', check: 'python3 -c "import cryptography"', install: 'cryptography==42.0.0', category: 'Crypto & Math' },
|
|
26
|
+
// Binary & RE
|
|
27
|
+
{ name: 'capstone', check: 'python3 -c "import capstone"', install: 'capstone==5.0.1', category: 'Binary & RE' },
|
|
28
|
+
{ name: 'ropper', check: 'python3 -c "import ropper"', install: 'ropper==1.13.8', category: 'Binary & RE' },
|
|
29
|
+
{ name: 'ROPgadget', check: 'which ROPgadget', install: 'ROPgadget==7.4', category: 'Binary & RE' },
|
|
30
|
+
{ name: 'pefile', check: 'python3 -c "import pefile"', install: 'pefile==2023.2.7', category: 'Binary & RE' },
|
|
31
|
+
// Data & Forensics
|
|
32
|
+
{ name: 'pillow', check: 'python3 -c "import PIL"', install: 'pillow==10.2.0', category: 'Data & Forensics' },
|
|
33
|
+
{ name: 'numpy', check: 'python3 -c "import numpy"', install: 'numpy==1.26.4', category: 'Data & Forensics' },
|
|
34
|
+
{ name: 'python-magic', check: 'python3 -c "import magic"', install: 'python-magic==0.4.27', category: 'Data & Forensics' },
|
|
35
|
+
{ name: 'yara-python', check: 'python3 -c "import yara"', install: 'yara-python==4.5.0', category: 'Data & Forensics' },
|
|
36
|
+
// Tools
|
|
37
|
+
{ name: 'sqlmap', check: 'which sqlmap', install: 'sqlmap', category: 'Security Tools' },
|
|
38
|
+
{ name: 'ipython', check: 'which ipython3 || which ipython', install: 'ipython', category: 'Security Tools' },
|
|
39
|
+
{ name: 'uncompyle6', check: 'python3 -c "import uncompyle6"', install: 'uncompyle6==3.9.1', category: 'Security Tools' },
|
|
40
|
+
{ name: 'rsactftool', check: 'which rsactftool || python3 -c "import rsactftool"', install: 'rsactftool', category: 'Security Tools' },
|
|
41
|
+
{ name: 'pngcheck', check: 'python3 -c "import pngcheck"', install: 'pngcheck', category: 'Security Tools' },
|
|
42
|
+
{ name: 'volatility3', check: 'python3 -c "import volatility3"', install: 'volatility3', category: 'Security Tools' },
|
|
43
|
+
{ name: 'pyserial', check: 'python3 -c "import serial"', install: 'pyserial==3.5', category: 'Security Tools' },
|
|
25
44
|
];
|
|
45
|
+
// ══════════════════════════════════════════════════════════
|
|
46
|
+
// 82 System Tools — brew (Mac) / apt (Ubuntu) / choco (Win)
|
|
47
|
+
// ══════════════════════════════════════════════════════════
|
|
48
|
+
const W = process.platform === 'win32';
|
|
49
|
+
const CMD = (unix, win) => W ? (win || `where ${unix}`) : `which ${unix}`;
|
|
26
50
|
const SYSTEM_TOOLS = [
|
|
27
|
-
// Editors
|
|
28
|
-
{ name: 'vim', check: '
|
|
29
|
-
{ name: 'nano', check: '
|
|
30
|
-
{ name: 'tmux', check: '
|
|
31
|
-
|
|
32
|
-
{ name: '
|
|
33
|
-
|
|
34
|
-
{ name: '
|
|
35
|
-
{ name: '
|
|
36
|
-
|
|
37
|
-
{ name: '
|
|
38
|
-
{ name: '
|
|
39
|
-
|
|
40
|
-
{ name: '
|
|
41
|
-
{ name: '
|
|
42
|
-
|
|
43
|
-
{ name: '
|
|
44
|
-
{ name: '
|
|
45
|
-
{ name: '
|
|
46
|
-
//
|
|
47
|
-
{ name: '
|
|
48
|
-
{ name: '
|
|
49
|
-
{ name: '
|
|
50
|
-
|
|
51
|
-
{ name: '
|
|
52
|
-
{ name: '
|
|
53
|
-
|
|
54
|
-
{ name: '
|
|
55
|
-
{ name: '
|
|
56
|
-
{ name: '
|
|
57
|
-
{ name: '
|
|
58
|
-
{ name: '
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
{ name: '
|
|
62
|
-
{ name: '
|
|
63
|
-
{ name: '
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
{ name: '
|
|
67
|
-
|
|
68
|
-
{ name: '
|
|
69
|
-
{ name: '
|
|
51
|
+
// Editors & Terminal (5)
|
|
52
|
+
{ name: 'vim', check: CMD('vim'), brew: 'vim', apt: 'vim', choco: 'vim', category: 'Editors & Terminal' },
|
|
53
|
+
{ name: 'nano', check: CMD('nano'), brew: 'nano', apt: 'nano', choco: 'nano', category: 'Editors & Terminal' },
|
|
54
|
+
{ name: 'tmux', check: CMD('tmux'), brew: 'tmux', apt: 'tmux', category: 'Editors & Terminal' },
|
|
55
|
+
{ name: 'screen', check: CMD('screen'), brew: 'screen', apt: 'screen', category: 'Editors & Terminal' },
|
|
56
|
+
{ name: 'less', check: CMD('less'), category: 'Editors & Terminal' },
|
|
57
|
+
// Compilers & Build (8)
|
|
58
|
+
{ name: 'gcc', check: CMD('gcc'), brew: 'gcc', apt: 'gcc', choco: 'mingw', category: 'Compilers & Build' },
|
|
59
|
+
{ name: 'g++', check: CMD('g++'), brew: 'gcc', apt: 'g++', choco: 'mingw', category: 'Compilers & Build' },
|
|
60
|
+
{ name: 'make', check: CMD('make'), brew: 'make', apt: 'make', choco: 'make', category: 'Compilers & Build' },
|
|
61
|
+
{ name: 'nasm', check: CMD('nasm'), brew: 'nasm', apt: 'nasm', choco: 'nasm', category: 'Compilers & Build' },
|
|
62
|
+
{ name: 'cmake', check: CMD('cmake'), brew: 'cmake', apt: 'cmake', choco: 'cmake', category: 'Compilers & Build' },
|
|
63
|
+
{ name: 'as', check: CMD('as'), category: 'Compilers & Build' },
|
|
64
|
+
{ name: 'ld', check: CMD('ld'), category: 'Compilers & Build' },
|
|
65
|
+
{ name: 'pkg-config', check: CMD('pkg-config'), brew: 'pkg-config', apt: 'pkg-config', category: 'Compilers & Build' },
|
|
66
|
+
// Python (3)
|
|
67
|
+
{ name: 'python3', check: W ? 'python --version' : 'python3 --version', brew: 'python@3.12', apt: 'python3', choco: 'python312', category: 'Python Runtime' },
|
|
68
|
+
{ name: 'pip3', check: W ? 'pip --version' : 'pip3 --version', category: 'Python Runtime' },
|
|
69
|
+
{ name: 'python3-venv', check: W ? 'python -c "import venv"' : 'python3 -c "import venv"', apt: 'python3-venv', category: 'Python Runtime' },
|
|
70
|
+
// Networking (12)
|
|
71
|
+
{ name: 'curl', check: CMD('curl'), brew: 'curl', apt: 'curl', choco: 'curl', category: 'Networking' },
|
|
72
|
+
{ name: 'wget', check: CMD('wget'), brew: 'wget', apt: 'wget', choco: 'wget', category: 'Networking' },
|
|
73
|
+
{ name: 'nc', check: CMD('nc', 'where ncat'), brew: 'netcat', apt: 'netcat-openbsd', choco: 'nmap', category: 'Networking' },
|
|
74
|
+
{ name: 'socat', check: CMD('socat'), brew: 'socat', apt: 'socat', category: 'Networking' },
|
|
75
|
+
{ name: 'nmap', check: CMD('nmap'), brew: 'nmap', apt: 'nmap', choco: 'nmap', category: 'Networking' },
|
|
76
|
+
{ name: 'ssh', check: CMD('ssh'), apt: 'openssh-client', category: 'Networking' },
|
|
77
|
+
{ name: 'dig', check: CMD('dig'), brew: 'bind', apt: 'dnsutils', category: 'Networking' },
|
|
78
|
+
{ name: 'whois', check: CMD('whois'), brew: 'whois', apt: 'whois', choco: 'whois', category: 'Networking' },
|
|
79
|
+
{ name: 'ping', check: CMD('ping'), apt: 'iputils-ping', category: 'Networking' },
|
|
80
|
+
{ name: 'traceroute', check: CMD('traceroute', 'where tracert'), brew: 'traceroute', apt: 'traceroute', category: 'Networking' },
|
|
81
|
+
{ name: 'tcpdump', check: CMD('tcpdump'), brew: 'tcpdump', apt: 'tcpdump', category: 'Networking' },
|
|
82
|
+
{ name: 'tshark', check: CMD('tshark'), brew: 'wireshark', apt: 'tshark', choco: 'wireshark', category: 'Networking' },
|
|
83
|
+
// Debuggers & Tracing (5)
|
|
84
|
+
{ name: 'gdb', check: CMD('gdb'), brew: 'gdb', apt: 'gdb', choco: 'mingw', category: 'Debuggers' },
|
|
85
|
+
{ name: 'ltrace', check: CMD('ltrace'), apt: 'ltrace', category: 'Debuggers' },
|
|
86
|
+
{ name: 'strace', check: CMD('strace'), apt: 'strace', category: 'Debuggers' },
|
|
87
|
+
{ name: 'objdump', check: CMD('objdump'), category: 'Debuggers' },
|
|
88
|
+
{ name: 'readelf', check: CMD('readelf'), category: 'Debuggers' },
|
|
89
|
+
// Reverse Engineering (4)
|
|
90
|
+
{ name: 'radare2', check: CMD('r2'), brew: 'radare2', apt: 'radare2', choco: 'radare2', category: 'Reverse Engineering' },
|
|
91
|
+
{ name: 'rabin2', check: CMD('rabin2'), category: 'Reverse Engineering' },
|
|
92
|
+
{ name: 'upx', check: CMD('upx'), brew: 'upx', apt: 'upx', choco: 'upx', category: 'Reverse Engineering' },
|
|
93
|
+
{ name: 'strings', check: CMD('strings'), category: 'Reverse Engineering' },
|
|
94
|
+
// Forensics (7)
|
|
95
|
+
{ name: 'binwalk', check: CMD('binwalk'), brew: 'binwalk', apt: 'binwalk', category: 'Forensics' },
|
|
96
|
+
{ name: 'foremost', check: CMD('foremost'), apt: 'foremost', category: 'Forensics' },
|
|
97
|
+
{ name: 'exiftool', check: CMD('exiftool'), brew: 'exiftool', apt: 'exiftool', choco: 'exiftool', category: 'Forensics' },
|
|
98
|
+
{ name: 'steghide', check: CMD('steghide'), apt: 'steghide', category: 'Forensics' },
|
|
99
|
+
{ name: 'file', check: CMD('file'), category: 'Forensics' },
|
|
100
|
+
{ name: 'xxd', check: CMD('xxd'), brew: 'vim', apt: 'xxd', category: 'Forensics' },
|
|
101
|
+
{ name: 'pdftotext', check: CMD('pdftotext'), brew: 'poppler', apt: 'poppler-utils', category: 'Forensics' },
|
|
102
|
+
// Crypto & Password (4)
|
|
103
|
+
{ name: 'john', check: CMD('john'), brew: 'john', apt: 'john', choco: 'john', category: 'Crypto & Password' },
|
|
104
|
+
{ name: 'hashcat', check: CMD('hashcat'), brew: 'hashcat', apt: 'hashcat', choco: 'hashcat', category: 'Crypto & Password' },
|
|
105
|
+
{ name: 'openssl', check: CMD('openssl'), category: 'Crypto & Password' },
|
|
106
|
+
{ name: 'gpg', check: CMD('gpg'), brew: 'gnupg', apt: 'gpg', choco: 'gnupg', category: 'Crypto & Password' },
|
|
107
|
+
// Data Processing (8)
|
|
108
|
+
{ name: 'jq', check: CMD('jq'), brew: 'jq', apt: 'jq', choco: 'jq', category: 'Data Processing' },
|
|
109
|
+
{ name: 'sqlite3', check: CMD('sqlite3'), brew: 'sqlite', apt: 'sqlite3', choco: 'sqlite', category: 'Data Processing' },
|
|
110
|
+
{ name: 'base64', check: CMD('base64'), category: 'Data Processing' },
|
|
111
|
+
{ name: 'hexdump', check: CMD('hexdump'), category: 'Data Processing' },
|
|
112
|
+
{ name: 'od', check: CMD('od'), category: 'Data Processing' },
|
|
113
|
+
{ name: 'sort', check: CMD('sort'), category: 'Data Processing' },
|
|
114
|
+
{ name: 'uniq', check: CMD('uniq'), category: 'Data Processing' },
|
|
115
|
+
{ name: 'wc', check: CMD('wc'), category: 'Data Processing' },
|
|
116
|
+
// Archive (6)
|
|
117
|
+
{ name: 'unzip', check: CMD('unzip'), brew: 'unzip', apt: 'unzip', category: 'Archive' },
|
|
118
|
+
{ name: 'zip', check: CMD('zip'), brew: 'zip', apt: 'zip', category: 'Archive' },
|
|
119
|
+
{ name: 'tar', check: CMD('tar'), category: 'Archive' },
|
|
120
|
+
{ name: 'gzip', check: CMD('gzip'), category: 'Archive' },
|
|
121
|
+
{ name: 'bzip2', check: CMD('bzip2'), category: 'Archive' },
|
|
122
|
+
{ name: 'xz', check: CMD('xz'), brew: 'xz', apt: 'xz-utils', category: 'Archive' },
|
|
123
|
+
// Core Unix (16)
|
|
124
|
+
{ name: 'cat', check: CMD('cat'), category: 'Core Unix' },
|
|
125
|
+
{ name: 'grep', check: CMD('grep'), category: 'Core Unix' },
|
|
126
|
+
{ name: 'sed', check: CMD('sed'), category: 'Core Unix' },
|
|
127
|
+
{ name: 'awk', check: CMD('awk'), category: 'Core Unix' },
|
|
128
|
+
{ name: 'find', check: CMD('find'), category: 'Core Unix' },
|
|
129
|
+
{ name: 'head', check: CMD('head'), category: 'Core Unix' },
|
|
130
|
+
{ name: 'tail', check: CMD('tail'), category: 'Core Unix' },
|
|
131
|
+
{ name: 'diff', check: CMD('diff'), category: 'Core Unix' },
|
|
132
|
+
{ name: 'patch', check: CMD('patch'), category: 'Core Unix' },
|
|
133
|
+
{ name: 'chmod', check: CMD('chmod'), category: 'Core Unix' },
|
|
134
|
+
{ name: 'chown', check: CMD('chown'), category: 'Core Unix' },
|
|
135
|
+
{ name: 'ln', check: CMD('ln'), category: 'Core Unix' },
|
|
136
|
+
{ name: 'cp', check: CMD('cp'), category: 'Core Unix' },
|
|
137
|
+
{ name: 'mv', check: CMD('mv'), category: 'Core Unix' },
|
|
138
|
+
{ name: 'mkdir', check: CMD('mkdir'), category: 'Core Unix' },
|
|
139
|
+
{ name: 'rm', check: CMD('rm'), category: 'Core Unix' },
|
|
140
|
+
// Version Control & Container (2)
|
|
141
|
+
{ name: 'git', check: CMD('git'), brew: 'git', apt: 'git', choco: 'git', category: 'Git & Docker' },
|
|
142
|
+
{ name: 'docker', check: CMD('docker'), brew: '--cask docker', choco: 'docker-desktop', category: 'Git & Docker' },
|
|
70
143
|
];
|
|
71
144
|
function isInstalled(check) {
|
|
72
145
|
try {
|
|
@@ -79,54 +152,71 @@ function isInstalled(check) {
|
|
|
79
152
|
}
|
|
80
153
|
function getVersion(name) {
|
|
81
154
|
try {
|
|
82
|
-
if (name === 'python3')
|
|
155
|
+
if (name === 'python3')
|
|
83
156
|
return execSync('python3 --version', { encoding: 'utf-8' }).trim().replace('Python ', '');
|
|
84
|
-
}
|
|
85
157
|
if (name === 'gcc') {
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
return match ? match[1] : '';
|
|
158
|
+
const m = execSync('gcc --version', { encoding: 'utf-8' }).match(/(\d+\.\d+[\.\d]*)/);
|
|
159
|
+
return m?.[1] || '';
|
|
89
160
|
}
|
|
90
161
|
if (name === 'docker') {
|
|
91
|
-
const
|
|
92
|
-
|
|
93
|
-
|
|
162
|
+
const m = execSync('docker --version', { encoding: 'utf-8' }).match(/(\d+\.\d+\.\d+)/);
|
|
163
|
+
return m?.[1] || '';
|
|
164
|
+
}
|
|
165
|
+
if (name === 'pip3') {
|
|
166
|
+
const m = execSync('pip3 --version', { encoding: 'utf-8' }).match(/(\d+\.\d+[\.\d]*)/);
|
|
167
|
+
return m?.[1] || '';
|
|
168
|
+
}
|
|
169
|
+
if (name === 'nmap') {
|
|
170
|
+
const m = execSync('nmap --version', { encoding: 'utf-8' }).match(/(\d+\.\d+)/);
|
|
171
|
+
return m?.[1] || '';
|
|
94
172
|
}
|
|
95
173
|
}
|
|
96
174
|
catch { /* ignore */ }
|
|
97
175
|
return '';
|
|
98
176
|
}
|
|
177
|
+
function getPythonMajorMinor() {
|
|
178
|
+
try {
|
|
179
|
+
return execSync('python3 -c "import sys; print(f\'{sys.version_info.major}.{sys.version_info.minor}\')"', { encoding: 'utf-8' }).trim();
|
|
180
|
+
}
|
|
181
|
+
catch {
|
|
182
|
+
return '';
|
|
183
|
+
}
|
|
184
|
+
}
|
|
99
185
|
export function registerEnvCommand(program) {
|
|
100
186
|
const envCmd = program.command('env').description('Manage competition environment');
|
|
101
|
-
|
|
102
|
-
envCmd
|
|
103
|
-
|
|
104
|
-
.alias('check')
|
|
105
|
-
.description('Check installed tools and libraries')
|
|
106
|
-
.action(() => {
|
|
107
|
-
showStatus();
|
|
108
|
-
});
|
|
109
|
-
// icoa env setup — install everything
|
|
110
|
-
envCmd
|
|
111
|
-
.command('setup')
|
|
112
|
-
.description('Install all Python libraries (locked versions)')
|
|
113
|
-
.action(async () => {
|
|
114
|
-
await installAll();
|
|
115
|
-
});
|
|
116
|
-
// Default action: show status
|
|
117
|
-
envCmd.action(() => {
|
|
118
|
-
showStatus();
|
|
119
|
-
});
|
|
187
|
+
envCmd.command('status').alias('check').description('Check all 109 tools').action(() => showStatus());
|
|
188
|
+
envCmd.command('setup').description('Install all Python libraries + system tools').action(async () => { await installAll(); });
|
|
189
|
+
envCmd.action(() => showStatus());
|
|
120
190
|
}
|
|
121
191
|
function showStatus() {
|
|
122
192
|
console.log();
|
|
123
|
-
|
|
124
|
-
|
|
193
|
+
const os = platform();
|
|
194
|
+
const osName = os === 'darwin' ? 'macOS' : os === 'linux' ? 'Linux' : 'Windows';
|
|
195
|
+
const pm = os === 'darwin' ? 'brew' : os === 'linux' ? 'apt' : 'choco';
|
|
196
|
+
console.log(chalk.bold.white(' ICOA Competition Environment (109 commands)'));
|
|
197
|
+
console.log(chalk.gray(` Platform: ${osName} | Package Manager: ${pm} | Python: ${PYTHON_TARGET}.x`));
|
|
198
|
+
console.log(chalk.gray(' ─────────────────────────────────────────────'));
|
|
199
|
+
// Python version check
|
|
200
|
+
const pyVer = getPythonMajorMinor();
|
|
201
|
+
if (pyVer) {
|
|
202
|
+
const fullVer = getVersion('python3');
|
|
203
|
+
if (pyVer === '3.12') {
|
|
204
|
+
console.log(chalk.green(` ✓ Python ${fullVer}`) + chalk.gray(' (recommended)'));
|
|
205
|
+
}
|
|
206
|
+
else if (pyVer === '3.11' || pyVer === '3.13') {
|
|
207
|
+
console.log(chalk.yellow(` ~ Python ${fullVer}`) + chalk.gray(' (3.12.x recommended for full compatibility)'));
|
|
208
|
+
}
|
|
209
|
+
else {
|
|
210
|
+
console.log(chalk.red(` ✗ Python ${fullVer}`) + chalk.gray(' (3.12.x required — some tools may not work)'));
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
console.log(chalk.red(' ✗ Python 3 not found'));
|
|
215
|
+
}
|
|
125
216
|
console.log();
|
|
126
217
|
let installed = 0;
|
|
127
218
|
let missing = 0;
|
|
128
219
|
let currentCategory = '';
|
|
129
|
-
// System tools
|
|
130
220
|
for (const tool of SYSTEM_TOOLS) {
|
|
131
221
|
if (tool.category !== currentCategory) {
|
|
132
222
|
currentCategory = tool.category;
|
|
@@ -144,7 +234,6 @@ function showStatus() {
|
|
|
144
234
|
missing++;
|
|
145
235
|
}
|
|
146
236
|
}
|
|
147
|
-
// Python libraries
|
|
148
237
|
currentCategory = '';
|
|
149
238
|
for (const lib of PYTHON_LIBS) {
|
|
150
239
|
if (lib.category !== currentCategory) {
|
|
@@ -152,57 +241,97 @@ function showStatus() {
|
|
|
152
241
|
console.log(chalk.bold.gray(` ${currentCategory}`));
|
|
153
242
|
}
|
|
154
243
|
const ok = isInstalled(lib.check);
|
|
155
|
-
const verStr = lib.install ? chalk.gray(` (${lib.install})`) : '';
|
|
156
244
|
if (ok) {
|
|
157
|
-
console.log(chalk.green(` ✓ ${lib.name}`) +
|
|
245
|
+
console.log(chalk.green(` ✓ ${lib.name}`) + chalk.gray(` (${lib.install || 'latest'})`));
|
|
158
246
|
installed++;
|
|
159
247
|
}
|
|
160
248
|
else {
|
|
161
|
-
console.log(chalk.red(` ✗ ${lib.name}`) +
|
|
249
|
+
console.log(chalk.red(` ✗ ${lib.name}`) + chalk.gray(` → ${lib.install || 'latest'}`));
|
|
162
250
|
missing++;
|
|
163
251
|
}
|
|
164
252
|
}
|
|
253
|
+
const total = installed + missing;
|
|
165
254
|
console.log();
|
|
166
|
-
console.log(chalk.gray('
|
|
167
|
-
console.log(` ${chalk.green(`✓ ${installed}
|
|
255
|
+
console.log(chalk.gray(' ─────────────────────────────────────────────'));
|
|
256
|
+
console.log(` ${chalk.green(`✓ ${installed}/${total}`)} ${missing > 0 ? chalk.red(`✗ ${missing} missing`) : chalk.green('All 109 ready!')}`);
|
|
168
257
|
if (missing > 0) {
|
|
169
|
-
console.log();
|
|
170
|
-
console.log(chalk.gray(' Install missing Python libs: ') + chalk.white('env setup'));
|
|
258
|
+
console.log(chalk.gray(' Install everything: ') + chalk.white('env setup'));
|
|
171
259
|
}
|
|
172
260
|
console.log();
|
|
173
261
|
}
|
|
174
262
|
async function installAll() {
|
|
175
|
-
console.log();
|
|
176
|
-
console.log(chalk.bold.white(' Installing Python libraries (locked versions)...'));
|
|
177
263
|
console.log();
|
|
178
264
|
const os = platform();
|
|
179
265
|
const pipFlag = os === 'darwin' || os === 'linux' ? '--break-system-packages' : '';
|
|
180
|
-
|
|
181
|
-
|
|
266
|
+
// Python version warning
|
|
267
|
+
const pyVer = getPythonMajorMinor();
|
|
268
|
+
if (pyVer && pyVer !== '3.12') {
|
|
269
|
+
console.log(chalk.yellow(` Note: Python ${pyVer} detected. Python 3.12.x recommended.`));
|
|
270
|
+
console.log();
|
|
271
|
+
}
|
|
272
|
+
// Install system tools via brew (macOS) / apt (Linux) / choco (Windows)
|
|
273
|
+
const missingSystem = [];
|
|
274
|
+
for (const tool of SYSTEM_TOOLS) {
|
|
275
|
+
if (!isInstalled(tool.check)) {
|
|
276
|
+
const pkg = os === 'darwin' ? tool.brew : os === 'linux' ? tool.apt : tool.choco;
|
|
277
|
+
if (pkg)
|
|
278
|
+
missingSystem.push(tool);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
if (missingSystem.length > 0) {
|
|
282
|
+
const pmName = os === 'darwin' ? 'brew' : os === 'linux' ? 'apt' : 'choco';
|
|
283
|
+
console.log(chalk.bold.white(` System Tools via ${pmName} (${missingSystem.length} missing)`));
|
|
284
|
+
console.log(chalk.gray(' ─────────────────────────────────────────────'));
|
|
285
|
+
for (const tool of missingSystem) {
|
|
286
|
+
const pkg = os === 'darwin' ? tool.brew : os === 'linux' ? tool.apt : tool.choco;
|
|
287
|
+
process.stdout.write(chalk.gray(` ⏳ ${tool.name}...`));
|
|
288
|
+
try {
|
|
289
|
+
let cmd;
|
|
290
|
+
if (os === 'darwin')
|
|
291
|
+
cmd = `brew install ${pkg}`;
|
|
292
|
+
else if (os === 'linux')
|
|
293
|
+
cmd = `sudo apt-get install -y ${pkg}`;
|
|
294
|
+
else
|
|
295
|
+
cmd = `choco install -y ${pkg}`;
|
|
296
|
+
execSync(cmd, { stdio: 'ignore' });
|
|
297
|
+
process.stdout.write('\r');
|
|
298
|
+
console.log(chalk.green(` ✓ ${tool.name}`));
|
|
299
|
+
}
|
|
300
|
+
catch {
|
|
301
|
+
process.stdout.write('\r');
|
|
302
|
+
console.log(chalk.red(` ✗ ${tool.name}`) + chalk.gray(` (${pmName} install ${pkg})`));
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
console.log();
|
|
306
|
+
}
|
|
307
|
+
// Install Python libraries
|
|
308
|
+
let pipInstalled = 0;
|
|
309
|
+
let pipFailed = 0;
|
|
310
|
+
console.log(chalk.bold.white(` Python Libraries (${PYTHON_LIBS.length} packages)`));
|
|
311
|
+
console.log(chalk.gray(' ─────────────────────────────────────────────'));
|
|
182
312
|
for (const lib of PYTHON_LIBS) {
|
|
183
313
|
if (!lib.install)
|
|
184
314
|
continue;
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
installed++;
|
|
315
|
+
if (isInstalled(lib.check)) {
|
|
316
|
+
console.log(chalk.green(` ✓ ${lib.name}`) + chalk.gray(' (installed)'));
|
|
317
|
+
pipInstalled++;
|
|
189
318
|
continue;
|
|
190
319
|
}
|
|
191
|
-
process.stdout.write(chalk.gray(` ⏳
|
|
320
|
+
process.stdout.write(chalk.gray(` ⏳ ${lib.name}...`));
|
|
192
321
|
try {
|
|
193
322
|
execSync(`pip3 install ${pipFlag} ${lib.install}`, { stdio: 'ignore' });
|
|
194
323
|
process.stdout.write('\r');
|
|
195
324
|
console.log(chalk.green(` ✓ ${lib.name}`) + chalk.gray(` (${lib.install})`));
|
|
196
|
-
|
|
325
|
+
pipInstalled++;
|
|
197
326
|
}
|
|
198
327
|
catch {
|
|
199
328
|
process.stdout.write('\r');
|
|
200
|
-
console.log(chalk.red(` ✗ ${lib.name}`) + chalk.gray(
|
|
201
|
-
|
|
329
|
+
console.log(chalk.red(` ✗ ${lib.name}`) + chalk.gray(' (failed)'));
|
|
330
|
+
pipFailed++;
|
|
202
331
|
}
|
|
203
332
|
}
|
|
204
333
|
console.log();
|
|
205
|
-
console.log(chalk.gray('
|
|
206
|
-
console.log(` ${chalk.green(`✓ ${
|
|
334
|
+
console.log(chalk.gray(' ─────────────────────────────────────────────'));
|
|
335
|
+
console.log(` ${chalk.green(`✓ ${pipInstalled} installed`)} ${pipFailed > 0 ? chalk.red(`✗ ${pipFailed} failed`) : chalk.green('All ready!')}`);
|
|
207
336
|
console.log();
|
|
208
337
|
}
|
package/dist/index.js
CHANGED
|
@@ -36,7 +36,7 @@ ${LINE}
|
|
|
36
36
|
${chalk.white('Sydney, Australia')} ${chalk.gray('Jun 27 - Jul 2, 2026')}
|
|
37
37
|
${chalk.cyan.underline('https://icoa2026.au')}
|
|
38
38
|
|
|
39
|
-
${chalk.gray('CLI-Native Competition Terminal v1.
|
|
39
|
+
${chalk.gray('CLI-Native Competition Terminal v1.7.1')}
|
|
40
40
|
|
|
41
41
|
${LINE}
|
|
42
42
|
`;
|
package/dist/repl.js
CHANGED
|
@@ -6,7 +6,7 @@ import { isActivated, activateToken, isFreeCommand, isDeviceMatch, recordExit, r
|
|
|
6
6
|
import { resetTerminalTheme } from './lib/theme.js';
|
|
7
7
|
import { ensureSandbox, runInSandbox, isDockerAvailable } from './lib/sandbox.js';
|
|
8
8
|
const INTERCEPT = '__REPL_NO_EXIT__';
|
|
9
|
-
const VERSION = '1.
|
|
9
|
+
const VERSION = '1.7.1';
|
|
10
10
|
export async function startRepl(program, resumeMode) {
|
|
11
11
|
const config = getConfig();
|
|
12
12
|
const connected = isConnected();
|