icoa-cli 2.19.324 → 2.19.326

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{existsSync as n,mkdirSync as t,readFileSync as i,writeFileSync as r}from"node:fs";import{join as a,dirname as o}from"node:path";import{fileURLToPath as s}from"node:url";import{getIcoaDir as e}from"./config.js";import{translateText as f}from"./gemini.js";import{ensureLangCache as c}from"./translations-fetcher.js";const m=o(s(import.meta.url));export async function getTranslation(o,s,u){if("en"===u)return o;const l=function(n,t){return a(m,"..","..","translations",n,`${t}.json`)}(u,s);if(n(l))try{const n=JSON.parse(i(l,"utf-8"));if(n.translation)return n.translation}catch{}await c(u,{silent:!1});const p=function(n,i){const r=a(e(),"translations",n);return t(r,{recursive:!0}),a(r,`${i}.json`)}(u,s);if(n(p))try{const n=JSON.parse(i(p,"utf-8"));if(n.translation)return n.translation}catch{}const h=await f(o,(g=u,{en:"English",zh:"Chinese (Simplified)",ja:"Japanese",ko:"Korean",es:"Spanish",ar:"Arabic",fr:"French",pt:"Portuguese (Brazilian)",ru:"Russian",hi:"Hindi",de:"German",id:"Indonesian",th:"Thai",vi:"Vietnamese",tr:"Turkish",uk:"Ukrainian",ht:"Haitian Creole"}[g]||"English"));var g;return r(p,JSON.stringify({original:o,translation:h,timestamp:(new Date).toISOString()})),h}
1
+ import{existsSync as n,mkdirSync as t,readFileSync as i,writeFileSync as r}from"node:fs";import{join as a,dirname as o}from"node:path";import{fileURLToPath as e}from"node:url";import{getIcoaDir as s}from"./config.js";import{translateText as f}from"./gemini.js";import{ensureLangCache as u}from"./translations-fetcher.js";const c=o(e(import.meta.url));export async function getTranslation(o,e,l){if("en"===l)return o;const m=function(n,t){return a(c,"..","..","translations",n,`${t}.json`)}(l,e);if(n(m))try{const n=JSON.parse(i(m,"utf-8"));if(n.translation)return n.translation}catch{}await u(l,{silent:!1});const h=function(n,i){const r=a(s(),"translations",n);return t(r,{recursive:!0}),a(r,`${i}.json`)}(l,e);if(n(h))try{const n=JSON.parse(i(h,"utf-8"));if(n.translation)return n.translation}catch{}const p=await f(o,(g=l,{en:"English",zh:"Chinese (Simplified)",ja:"Japanese",ko:"Korean",es:"Spanish",ar:"Arabic",fr:"French",pt:"Portuguese (Brazilian)",ru:"Russian",hi:"Hindi",de:"German",id:"Indonesian",th:"Thai",vi:"Vietnamese",tr:"Turkish",uk:"Ukrainian",ht:"Haitian Creole",bn:"Bengali",kk:"Kazakh",uz:"Uzbek",lo:"Lao"}[g]||"English"));var g;return r(h,JSON.stringify({original:o,translation:p,timestamp:(new Date).toISOString()})),p}
@@ -1 +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}
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://practice.icoa2026.au/assets/translations","https://au.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.324",
3
+ "version": "2.19.326",
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": {