icoa-cli 1.8.5 → 1.9.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.
@@ -158,28 +158,83 @@ function isInstalled(check) {
158
158
  }
159
159
  }
160
160
  function getVersion(name) {
161
+ // Version commands for each tool
162
+ const versionCmds = {
163
+ 'python3': 'python3 --version',
164
+ 'pip3': '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
- if (name === 'python3')
163
- return execSync('python3 --version', { encoding: 'utf-8' }).trim().replace('Python ', '');
164
- if (name === 'gcc') {
165
- const m = execSync('gcc --version', { encoding: 'utf-8' }).match(/(\d+\.\d+[\.\d]*)/);
166
- return m?.[1] || '';
167
- }
168
- if (name === 'docker') {
169
- const m = execSync('docker --version', { encoding: 'utf-8' }).match(/(\d+\.\d+\.\d+)/);
170
- return m?.[1] || '';
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 (name === 'pip3') {
173
- const m = execSync('pip3 --version', { encoding: 'utf-8' }).match(/(\d+\.\d+[\.\d]*)/);
174
- return m?.[1] || '';
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 (name === 'nmap') {
177
- const m = execSync('nmap --version', { encoding: 'utf-8' }).match(/(\d+\.\d+)/);
178
- return m?.[1] || '';
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() {
185
240
  try {
@@ -198,10 +253,13 @@ export function registerEnvCommand(program) {
198
253
  function showStatus() {
199
254
  console.log();
200
255
  const os = platform();
201
- const osName = os === 'darwin' ? 'macOS' : os === 'linux' ? 'Linux' : 'Windows';
202
256
  const pm = os === 'darwin' ? 'brew' : os === 'linux' ? 'apt' : 'choco';
203
- console.log(chalk.bold.white(' ICOA Competition Environment (109 commands)'));
204
- console.log(chalk.gray(` Platform: ${osName} | Package Manager: ${pm} | Python: ${PYTHON_TARGET}.x`));
257
+ console.log(chalk.bold.white(' ICOA Competition Environment'));
258
+ console.log(chalk.gray(' ─────────────────────────────────────────────'));
259
+ console.log(chalk.gray(' OS: ') + chalk.white(getOsInfo()));
260
+ console.log(chalk.gray(' Node: ') + chalk.white(getNodeInfo()));
261
+ console.log(chalk.gray(' Package: ') + chalk.white(pm));
262
+ console.log(chalk.gray(' Target: ') + chalk.white(`Python ${PYTHON_TARGET}.x`));
205
263
  console.log(chalk.gray(' ─────────────────────────────────────────────'));
206
264
  // Python version check
207
265
  const pyVer = getPythonMajorMinor();
@@ -242,6 +300,7 @@ function showStatus() {
242
300
  }
243
301
  }
244
302
  currentCategory = '';
303
+ const pipExe = os === 'darwin' ? '/opt/homebrew/opt/python@3.12/bin/pip3.12' : 'pip3';
245
304
  for (const lib of PYTHON_LIBS) {
246
305
  if (lib.category !== currentCategory) {
247
306
  currentCategory = lib.category;
@@ -249,7 +308,21 @@ function showStatus() {
249
308
  }
250
309
  const ok = isInstalled(lib.check);
251
310
  if (ok) {
252
- console.log(chalk.green(` ✓ ${lib.name}`) + chalk.gray(` (${lib.install || 'latest'})`));
311
+ // Get actual installed version — try pip3.12, then pip3
312
+ let ver = '';
313
+ for (const pip of [pipExe, 'pip3']) {
314
+ try {
315
+ const pkgName = lib.name.replace('python-magic', 'python_magic').replace('beautifulsoup4', 'beautifulsoup4');
316
+ const out = execSync(`${pip} show ${pkgName} 2>/dev/null | grep Version`, { encoding: 'utf-8', timeout: 3000 });
317
+ const m = out.match(/Version:\s*(\S+)/);
318
+ if (m) {
319
+ ver = m[1];
320
+ break;
321
+ }
322
+ }
323
+ catch { /* try next */ }
324
+ }
325
+ console.log(chalk.green(` ✓ ${lib.name}`) + chalk.gray(ver ? ` (${ver})` : ''));
253
326
  installed++;
254
327
  }
255
328
  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.8.5')}
39
+ ${chalk.gray('CLI-Native Competition Terminal v1.9.0')}
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.8.5';
11
+ const VERSION = '1.9.0';
12
12
  export async function startRepl(program, resumeMode) {
13
13
  const config = getConfig();
14
14
  const connected = isConnected();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "icoa-cli",
3
- "version": "1.8.5",
3
+ "version": "1.9.0",
4
4
  "description": "ICOA CLI — The world's first CLI-native CTF competition terminal",
5
5
  "type": "module",
6
6
  "bin": {