icoa-cli 1.8.5 → 1.9.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 +124 -35
- package/dist/index.js +1 -1
- package/dist/repl.js +1 -1
- package/package.json +1 -1
package/dist/commands/env.js
CHANGED
|
@@ -61,9 +61,9 @@ const SYSTEM_TOOLS = [
|
|
|
61
61
|
{ name: 'as', check: CMD('as'), category: 'Compilers & Build' },
|
|
62
62
|
{ name: 'ld', check: CMD('ld'), category: 'Compilers & Build' },
|
|
63
63
|
{ name: 'pkg-config', check: CMD('pkg-config'), brew: 'pkg-config', apt: 'pkg-config', category: 'Compilers & Build' },
|
|
64
|
-
// Python (3)
|
|
65
|
-
{ name: 'python3', check: W ? 'python --version' : 'python3 --version', brew: 'python@3.12', apt: 'python3', choco: 'python312', category: 'Python Runtime' },
|
|
66
|
-
{ name: 'pip3', check: W ? 'pip --version' : 'pip3 --version', category: 'Python Runtime' },
|
|
64
|
+
// Python (3) — prefer brew 3.12 on macOS
|
|
65
|
+
{ name: 'python3', check: process.platform === 'darwin' ? '/opt/homebrew/opt/python@3.12/bin/python3.12 --version' : (W ? 'python --version' : 'python3 --version'), brew: 'python@3.12', apt: 'python3', choco: 'python312', category: 'Python Runtime' },
|
|
66
|
+
{ name: 'pip3', check: process.platform === 'darwin' ? '/opt/homebrew/opt/python@3.12/bin/pip3.12 --version' : (W ? 'pip --version' : 'pip3 --version'), category: 'Python Runtime' },
|
|
67
67
|
{ name: 'python3-venv', check: W ? 'python -c "import venv"' : 'python3 -c "import venv"', apt: 'python3-venv', category: 'Python Runtime' },
|
|
68
68
|
// Networking (12)
|
|
69
69
|
{ name: 'curl', check: CMD('curl'), brew: 'curl', apt: 'curl', choco: 'curl', category: 'Networking' },
|
|
@@ -158,30 +158,92 @@ function isInstalled(check) {
|
|
|
158
158
|
}
|
|
159
159
|
}
|
|
160
160
|
function getVersion(name) {
|
|
161
|
+
// Version commands for each tool
|
|
162
|
+
const versionCmds = {
|
|
163
|
+
'python3': process.platform === 'darwin' ? '/opt/homebrew/opt/python@3.12/bin/python3.12 --version' : 'python3 --version',
|
|
164
|
+
'pip3': process.platform === 'darwin' ? '/opt/homebrew/opt/python@3.12/bin/pip3.12 --version' : 'pip3 --version',
|
|
165
|
+
'gcc': 'gcc --version',
|
|
166
|
+
'g++': 'g++ --version',
|
|
167
|
+
'make': 'make --version',
|
|
168
|
+
'nasm': 'nasm --version',
|
|
169
|
+
'cmake': 'cmake --version',
|
|
170
|
+
'vim': 'vim --version',
|
|
171
|
+
'nano': 'nano --version',
|
|
172
|
+
'tmux': 'tmux -V',
|
|
173
|
+
'screen': 'screen --version',
|
|
174
|
+
'curl': 'curl --version',
|
|
175
|
+
'wget': 'wget --version',
|
|
176
|
+
'nmap': 'nmap --version',
|
|
177
|
+
'ssh': 'ssh -V',
|
|
178
|
+
'socat': 'socat -V',
|
|
179
|
+
'gdb': 'gdb --version',
|
|
180
|
+
'radare2': 'r2 -v',
|
|
181
|
+
'upx': 'upx --version',
|
|
182
|
+
'binwalk': 'binwalk --help',
|
|
183
|
+
'exiftool': 'exiftool -ver',
|
|
184
|
+
'john': 'john --help',
|
|
185
|
+
'hashcat': 'hashcat --version',
|
|
186
|
+
'openssl': 'openssl version',
|
|
187
|
+
'gpg': 'gpg --version',
|
|
188
|
+
'jq': 'jq --version',
|
|
189
|
+
'sqlite3': 'sqlite3 --version',
|
|
190
|
+
'git': 'git --version',
|
|
191
|
+
'docker': 'docker --version',
|
|
192
|
+
'tshark': 'tshark --version',
|
|
193
|
+
'tcpdump': 'tcpdump --version',
|
|
194
|
+
'pdftotext': 'pdftotext -v',
|
|
195
|
+
'pngcheck': 'pngcheck 2>&1',
|
|
196
|
+
};
|
|
197
|
+
const cmd = versionCmds[name];
|
|
198
|
+
if (!cmd)
|
|
199
|
+
return '';
|
|
161
200
|
try {
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
201
|
+
const out = execSync(cmd + ' 2>&1', { encoding: 'utf-8', timeout: 3000 }).trim();
|
|
202
|
+
// Extract version number pattern
|
|
203
|
+
const m = out.match(/(\d+\.\d+[\.\d]*)/);
|
|
204
|
+
return m?.[1] || '';
|
|
205
|
+
}
|
|
206
|
+
catch { /* ignore */ }
|
|
207
|
+
return '';
|
|
208
|
+
}
|
|
209
|
+
function getOsInfo() {
|
|
210
|
+
const os = platform();
|
|
211
|
+
try {
|
|
212
|
+
if (os === 'darwin') {
|
|
213
|
+
const ver = execSync('sw_vers -productVersion', { encoding: 'utf-8' }).trim();
|
|
214
|
+
const arch = execSync('uname -m', { encoding: 'utf-8' }).trim();
|
|
215
|
+
return `macOS ${ver} (${arch})`;
|
|
171
216
|
}
|
|
172
|
-
if (
|
|
173
|
-
|
|
174
|
-
|
|
217
|
+
else if (os === 'linux') {
|
|
218
|
+
try {
|
|
219
|
+
const pretty = execSync('cat /etc/os-release | grep PRETTY_NAME', { encoding: 'utf-8' });
|
|
220
|
+
const m = pretty.match(/PRETTY_NAME="(.+)"/);
|
|
221
|
+
const arch = execSync('uname -m', { encoding: 'utf-8' }).trim();
|
|
222
|
+
return m ? `${m[1]} (${arch})` : `Linux (${arch})`;
|
|
223
|
+
}
|
|
224
|
+
catch {
|
|
225
|
+
return 'Linux';
|
|
226
|
+
}
|
|
175
227
|
}
|
|
176
|
-
if (
|
|
177
|
-
const
|
|
178
|
-
return
|
|
228
|
+
else if (os === 'win32') {
|
|
229
|
+
const ver = execSync('ver', { encoding: 'utf-8' }).trim();
|
|
230
|
+
return ver || 'Windows';
|
|
179
231
|
}
|
|
180
232
|
}
|
|
181
233
|
catch { /* ignore */ }
|
|
182
|
-
return
|
|
234
|
+
return os;
|
|
235
|
+
}
|
|
236
|
+
function getNodeInfo() {
|
|
237
|
+
return `Node.js ${process.version}`;
|
|
183
238
|
}
|
|
184
239
|
function getPythonMajorMinor() {
|
|
240
|
+
// On macOS, prefer brew Python 3.12
|
|
241
|
+
if (process.platform === 'darwin') {
|
|
242
|
+
try {
|
|
243
|
+
return execSync('/opt/homebrew/opt/python@3.12/bin/python3.12 -c "import sys; print(f\'{sys.version_info.major}.{sys.version_info.minor}\')"', { encoding: 'utf-8' }).trim();
|
|
244
|
+
}
|
|
245
|
+
catch { /* fall through */ }
|
|
246
|
+
}
|
|
185
247
|
try {
|
|
186
248
|
return execSync('python3 -c "import sys; print(f\'{sys.version_info.major}.{sys.version_info.minor}\')"', { encoding: 'utf-8' }).trim();
|
|
187
249
|
}
|
|
@@ -189,6 +251,20 @@ function getPythonMajorMinor() {
|
|
|
189
251
|
return '';
|
|
190
252
|
}
|
|
191
253
|
}
|
|
254
|
+
function getPythonFullVersion() {
|
|
255
|
+
if (process.platform === 'darwin') {
|
|
256
|
+
try {
|
|
257
|
+
return execSync('/opt/homebrew/opt/python@3.12/bin/python3.12 --version', { encoding: 'utf-8' }).trim().replace('Python ', '');
|
|
258
|
+
}
|
|
259
|
+
catch { /* fall through */ }
|
|
260
|
+
}
|
|
261
|
+
try {
|
|
262
|
+
return execSync('python3 --version', { encoding: 'utf-8' }).trim().replace('Python ', '');
|
|
263
|
+
}
|
|
264
|
+
catch {
|
|
265
|
+
return '';
|
|
266
|
+
}
|
|
267
|
+
}
|
|
192
268
|
export function registerEnvCommand(program) {
|
|
193
269
|
const envCmd = program.command('env').description('Manage competition environment');
|
|
194
270
|
envCmd.command('status').alias('check').description('Check all 109 tools').action(() => showStatus());
|
|
@@ -198,24 +274,22 @@ export function registerEnvCommand(program) {
|
|
|
198
274
|
function showStatus() {
|
|
199
275
|
console.log();
|
|
200
276
|
const os = platform();
|
|
201
|
-
const osName = os === 'darwin' ? 'macOS' : os === 'linux' ? 'Linux' : 'Windows';
|
|
202
277
|
const pm = os === 'darwin' ? 'brew' : os === 'linux' ? 'apt' : 'choco';
|
|
203
|
-
console.log(chalk.bold.white(' ICOA Competition Environment
|
|
204
|
-
console.log(chalk.gray(
|
|
278
|
+
console.log(chalk.bold.white(' ICOA Competition Environment'));
|
|
279
|
+
console.log(chalk.gray(' ─────────────────────────────────────────────'));
|
|
280
|
+
console.log(chalk.gray(' OS: ') + chalk.white(getOsInfo()));
|
|
281
|
+
console.log(chalk.gray(' Node: ') + chalk.white(getNodeInfo()));
|
|
282
|
+
console.log(chalk.gray(' Package: ') + chalk.white(pm));
|
|
283
|
+
console.log(chalk.gray(' Target: ') + chalk.white(`Python ${PYTHON_TARGET}.x`));
|
|
205
284
|
console.log(chalk.gray(' ─────────────────────────────────────────────'));
|
|
206
|
-
// Python version check
|
|
285
|
+
// Python version check — use brew 3.12 on macOS
|
|
207
286
|
const pyVer = getPythonMajorMinor();
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
console.log(chalk.yellow(` ~ Python ${fullVer}`) + chalk.gray(' (3.12.x recommended for full compatibility)'));
|
|
215
|
-
}
|
|
216
|
-
else {
|
|
217
|
-
console.log(chalk.red(` ✗ Python ${fullVer}`) + chalk.gray(' (3.12.x required — some tools may not work)'));
|
|
218
|
-
}
|
|
287
|
+
const fullVer = getPythonFullVersion();
|
|
288
|
+
if (pyVer === '3.12') {
|
|
289
|
+
console.log(chalk.green(` ✓ Python ${fullVer}`) + chalk.gray(' (recommended)'));
|
|
290
|
+
}
|
|
291
|
+
else if (pyVer) {
|
|
292
|
+
console.log(chalk.yellow(` ~ Python ${fullVer}`) + chalk.gray(' (3.12.x recommended)'));
|
|
219
293
|
}
|
|
220
294
|
else {
|
|
221
295
|
console.log(chalk.red(' ✗ Python 3 not found'));
|
|
@@ -242,6 +316,7 @@ function showStatus() {
|
|
|
242
316
|
}
|
|
243
317
|
}
|
|
244
318
|
currentCategory = '';
|
|
319
|
+
const pipExe = os === 'darwin' ? '/opt/homebrew/opt/python@3.12/bin/pip3.12' : 'pip3';
|
|
245
320
|
for (const lib of PYTHON_LIBS) {
|
|
246
321
|
if (lib.category !== currentCategory) {
|
|
247
322
|
currentCategory = lib.category;
|
|
@@ -249,7 +324,21 @@ function showStatus() {
|
|
|
249
324
|
}
|
|
250
325
|
const ok = isInstalled(lib.check);
|
|
251
326
|
if (ok) {
|
|
252
|
-
|
|
327
|
+
// Get actual installed version — try pip3.12, then pip3
|
|
328
|
+
let ver = '';
|
|
329
|
+
for (const pip of [pipExe, 'pip3']) {
|
|
330
|
+
try {
|
|
331
|
+
const pkgName = lib.name.replace('python-magic', 'python_magic').replace('beautifulsoup4', 'beautifulsoup4');
|
|
332
|
+
const out = execSync(`${pip} show ${pkgName} 2>/dev/null | grep Version`, { encoding: 'utf-8', timeout: 3000 });
|
|
333
|
+
const m = out.match(/Version:\s*(\S+)/);
|
|
334
|
+
if (m) {
|
|
335
|
+
ver = m[1];
|
|
336
|
+
break;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
catch { /* try next */ }
|
|
340
|
+
}
|
|
341
|
+
console.log(chalk.green(` ✓ ${lib.name}`) + chalk.gray(ver ? ` (${ver})` : ''));
|
|
253
342
|
installed++;
|
|
254
343
|
}
|
|
255
344
|
else {
|
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.9.1')}
|
|
40
40
|
|
|
41
41
|
${LINE}
|
|
42
42
|
`;
|
package/dist/repl.js
CHANGED
|
@@ -8,7 +8,7 @@ import { ensureSandbox, runInSandbox, isDockerAvailable } from './lib/sandbox.js
|
|
|
8
8
|
import { logCommand } from './lib/logger.js';
|
|
9
9
|
import { startLogSync, stopLogSync } from './lib/log-sync.js';
|
|
10
10
|
const INTERCEPT = '__REPL_NO_EXIT__';
|
|
11
|
-
const VERSION = '1.
|
|
11
|
+
const VERSION = '1.9.1';
|
|
12
12
|
export async function startRepl(program, resumeMode) {
|
|
13
13
|
const config = getConfig();
|
|
14
14
|
const connected = isConnected();
|