icoa-cli 2.0.2 → 2.1.0

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.
@@ -3,6 +3,7 @@ import { execSync } from 'node:child_process';
3
3
  import { platform } from 'node:os';
4
4
  // Target Python version for full compatibility
5
5
  const PYTHON_TARGET = '3.12';
6
+ const PYTHON_EXACT = '3.12.13';
6
7
  // ══════════════════════════════════════════════════════════
7
8
  // 27 Python Libraries — ALL LOCKED VERSIONS
8
9
  // Tested on Python 3.12.x (recommended)
@@ -288,14 +289,17 @@ function showStatus() {
288
289
  console.log(chalk.gray(' Then run icoa inside WSL for 100% tool compatibility'));
289
290
  }
290
291
  console.log(chalk.gray(' ─────────────────────────────────────────────'));
291
- // Python version check — use brew 3.12 on macOS
292
+ // Python version check
292
293
  const pyVer = getPythonMajorMinor();
293
294
  const fullVer = getPythonFullVersion();
294
- if (pyVer === '3.12') {
295
- console.log(chalk.green(` ✓ Python ${fullVer}`) + chalk.gray(' (recommended)'));
295
+ if (fullVer === PYTHON_EXACT) {
296
+ console.log(chalk.green(` ✓ Python ${fullVer}`) + chalk.gray(' (official)'));
297
+ }
298
+ else if (pyVer === '3.12') {
299
+ console.log(chalk.yellow(` ~ Python ${fullVer}`) + chalk.gray(` (${PYTHON_EXACT} recommended, run env setup)`));
296
300
  }
297
301
  else if (pyVer) {
298
- console.log(chalk.yellow(` ~ Python ${fullVer}`) + chalk.gray(' (3.12.x recommended)'));
302
+ console.log(chalk.yellow(` ~ Python ${fullVer}`) + chalk.gray(` (${PYTHON_EXACT} required, run env setup)`));
299
303
  }
300
304
  else {
301
305
  console.log(chalk.red(' ✗ Python 3 not found'));
@@ -365,10 +369,15 @@ async function installAll() {
365
369
  console.log();
366
370
  const os = platform();
367
371
  const pipFlag = os === 'darwin' || os === 'linux' ? '--break-system-packages' : '';
368
- // Python version check — install 3.12 if needed
372
+ // Python version check — install 3.12.13 if needed
369
373
  const pyVer = getPythonMajorMinor();
370
- if (pyVer !== '3.12') {
371
- console.log(chalk.yellow(` Python ${pyVer || 'not found'} — installing Python 3.12...`));
374
+ const currentFullVer = getPythonFullVersion();
375
+ if (currentFullVer === PYTHON_EXACT) {
376
+ console.log(chalk.green(` ✓ Python ${PYTHON_EXACT}`));
377
+ console.log();
378
+ }
379
+ else {
380
+ console.log(chalk.yellow(` Python ${currentFullVer || 'not found'} — installing Python ${PYTHON_EXACT}...`));
372
381
  try {
373
382
  if (os === 'darwin') {
374
383
  execSync('brew install python@3.12', { stdio: 'inherit' });
@@ -382,21 +391,24 @@ async function installAll() {
382
391
  console.log(chalk.gray(' Or: brew link --overwrite python@3.12'));
383
392
  }
384
393
  else if (os === 'linux') {
385
- // Add deadsnakes PPA for older Ubuntu (22.04 etc.)
394
+ console.log(chalk.gray(` Building Python ${PYTHON_EXACT} from source...`));
395
+ // Install build dependencies
396
+ execSync('sudo apt-get update && sudo apt-get install -y build-essential libssl-dev zlib1g-dev libncurses5-dev libncursesw5-dev libreadline-dev libsqlite3-dev libgdbm-dev libdb5.3-dev libbz2-dev libexpat1-dev liblzma-dev libffi-dev tk-dev curl', { stdio: 'inherit' });
397
+ // Download and build
398
+ execSync(`curl -sS https://www.python.org/ftp/python/${PYTHON_EXACT}/Python-${PYTHON_EXACT}.tgz -o /tmp/Python-${PYTHON_EXACT}.tgz`, { stdio: 'inherit' });
399
+ execSync(`cd /tmp && tar xzf Python-${PYTHON_EXACT}.tgz && cd Python-${PYTHON_EXACT} && ./configure --prefix=/usr/local --enable-optimizations 2>&1 | tail -1 && make -j$(nproc) 2>&1 | tail -1 && sudo make altinstall`, { stdio: 'inherit', timeout: 600000 });
400
+ // Install pip
386
401
  try {
387
- execSync('sudo apt-get install -y software-properties-common', { stdio: 'inherit' });
388
- execSync('sudo add-apt-repository -y ppa:deadsnakes/ppa', { stdio: 'inherit' });
389
- execSync('sudo apt-get update', { stdio: 'inherit' });
402
+ execSync('curl -sS https://bootstrap.pypa.io/get-pip.py | sudo /usr/local/bin/python3.12', { stdio: 'inherit' });
390
403
  }
391
- catch { /* PPA may already exist or not needed on newer Ubuntu */ }
392
- execSync('sudo apt-get install -y python3.12 python3.12-venv python3.12-dev', { stdio: 'inherit' });
393
- // Install pip for 3.12
404
+ catch { /* ok */ }
405
+ // Set as default
394
406
  try {
395
- execSync('curl -sS https://bootstrap.pypa.io/get-pip.py | sudo python3.12', { stdio: 'inherit' });
407
+ execSync('sudo update-alternatives --install /usr/bin/python3 python3 /usr/local/bin/python3.12 2', { stdio: 'ignore' });
408
+ execSync('sudo update-alternatives --set python3 /usr/local/bin/python3.12', { stdio: 'ignore' });
396
409
  }
397
410
  catch { /* ok */ }
398
- console.log(chalk.green(' ✓ Python 3.12 installed'));
399
- console.log(chalk.gray(' Set default: sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.12 1'));
411
+ console.log(chalk.green(` ✓ Python ${PYTHON_EXACT} installed`));
400
412
  }
401
413
  else {
402
414
  // Windows: try winget first, then choco
@@ -416,10 +428,6 @@ async function installAll() {
416
428
  }
417
429
  console.log();
418
430
  }
419
- else {
420
- console.log(chalk.green(` ✓ Python 3.12 (${getVersion('python3')})`));
421
- console.log();
422
- }
423
431
  // Windows: recommend WSL instead of installing tools natively
424
432
  if (os === 'win32') {
425
433
  console.log(chalk.yellow(' Windows: Most CTF tools require Linux. Recommended:'));
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 v2.0.2')}
39
+ ${chalk.gray('CLI-Native Competition Terminal v2.1.0')}
40
40
 
41
41
  ${LINE}
42
42
  `;
package/dist/repl.js CHANGED
@@ -27,7 +27,7 @@ const BLOCKED_COMMANDS = new Set([
27
27
  'iptables', 'ufw', // firewall
28
28
  ]);
29
29
  const INTERCEPT = '__REPL_NO_EXIT__';
30
- const VERSION = '2.0.2';
30
+ const VERSION = '2.1.0';
31
31
  export async function startRepl(program, resumeMode) {
32
32
  const config = getConfig();
33
33
  const connected = isConnected();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "icoa-cli",
3
- "version": "2.0.2",
3
+ "version": "2.1.0",
4
4
  "description": "ICOA CLI — The world's first CLI-native CTF competition terminal",
5
5
  "type": "module",
6
6
  "bin": {