icoa-cli 2.19.322 → 2.19.324

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.
@@ -1 +1 @@
1
- import chalk from"chalk";import{spawn as t}from"node:child_process";import{existsSync as n,mkdirSync as o,writeFileSync as a}from"node:fs";import{join as r}from"node:path";import{getIcoaDir as e}from"./config.js";export function getLangCacheDir(t){return r(e(),"translations",t)}export function isLangCached(t){if("en"===t)return!0;const o=getLangCacheDir(t);return n(r(o,".cached"))}export async function ensureLangCache(n,e={}){if("en"===n)return!0;if(isLangCached(n))return!0;const i=getLangCacheDir(n);o(i,{recursive:!0}),e.silent||console.log(chalk.gray(` Fetching ${n} translation pack from icoa2026.au ...`));try{const o=`https://icoa2026.au/assets/translations/${n}.tar.gz`,s=await fetch(o);if(!s.ok)return e.silent||console.log(chalk.yellow(` Translation pack not available (HTTP ${s.status}). The interface stays in English; per-question translations fall back to the on-the-fly translator.`)),!1;const c=r(i,`${n}.tar.gz`);return a(c,Buffer.from(await s.arrayBuffer())),await new Promise((n,o)=>{const a=t("tar",["-xzf",c,"-C",i],{stdio:"ignore"});a.on("close",t=>0===t?n():o(new Error(`tar exit ${t}`))),a.on("error",o)}),a(r(i,".cached"),(new Date).toISOString()),e.silent||console.log(chalk.green(` ✓ ${n} translations cached at ~/.icoa/translations/${n}/`)),!0}catch(t){return e.silent||(console.log(chalk.yellow(` Translation fetch failed: ${t instanceof Error?t.message:String(t)}`)),console.log(chalk.gray(" Falling back to on-the-fly translation for individual questions."))),!1}}
1
+ import chalk from"chalk";import{spawn as t}from"node:child_process";import{existsSync as n,mkdirSync as r,writeFileSync as a}from"node:fs";import{join as e}from"node:path";import{getIcoaDir as o}from"./config.js";const s=["https://icoa2026.au/assets/translations","https://practice.icoa2026.au/assets/translations"];export function getLangCacheDir(t){return e(o(),"translations",t)}export function isLangCached(t){if("en"===t)return!0;const r=getLangCacheDir(t);return n(e(r,".cached"))}export async function ensureLangCache(n,o={}){if("en"===n)return!0;if(isLangCached(n))return!0;const i=getLangCacheDir(n);r(i,{recursive:!0}),o.silent||console.log(chalk.gray(` Fetching ${n} translation pack ...`));let c=null;for(const r of s)try{const s=`${r}/${n}.tar.gz`,l=await fetch(s);if(!l.ok){c=`HTTP ${l.status}`;continue}const f=e(i,`${n}.tar.gz`);return a(f,Buffer.from(await l.arrayBuffer())),await new Promise((n,r)=>{const a=t("tar",["-xzf",f,"-C",i],{stdio:"ignore"});a.on("close",t=>0===t?n():r(new Error(`tar exit ${t}`))),a.on("error",r)}),a(e(i,".cached"),(new Date).toISOString()),o.silent||console.log(chalk.green(` ✓ ${n} translations cached at ~/.icoa/translations/${n}/`)),!0}catch(t){c=t instanceof Error?t.message:String(t)}return o.silent||console.log(chalk.yellow(` Translation pack not available (${c??"all mirrors unreachable"}). The interface stays in English; per-question translations fall back to the on-the-fly translator.`)),!1}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "icoa-cli",
3
- "version": "2.19.322",
3
+ "version": "2.19.324",
4
4
  "description": "ICOA CLI — The world's first CLI-native cyber & AI security olympiad terminal: AI4CTF (Day 1), CTF4AI (Day 2), VLA4CTF (Pioneer Round — embodied AI)",
5
5
  "type": "module",
6
6
  "bin": {