icoa-cli 2.19.622 → 2.19.623
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/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{Command as o}from"commander";import chalk from"chalk";import{registerCtfCommands as e}from"./commands/ctf.js";import{registerRefCommand as n}from"./commands/ref.js";import{registerShellCommand as s}from"./commands/shell.js";import{registerFilesCommand as r}from"./commands/files.js";import{registerViewCommand as t}from"./commands/view.js";import{registerConnectCommand as i}from"./commands/connect.js";import{registerChallengeCommand as l}from"./commands/challenge.js";import{registerDoctorCommand as a}from"./commands/doctor.js";import{registerUpgradeCommand as m}from"./commands/upgrade.js";import{registerNoteCommand as c}from"./commands/note.js";import{registerLogCommand as g}from"./commands/log.js";import{registerLangCommand as d}from"./commands/lang.js";import{registerSetupCommand as p}from"./commands/setup.js";import{registerEnvCommand as y}from"./commands/env.js";import{registerAienvCommand as h}from"./commands/aienv.js";import{registerPythonCommands as f}from"./commands/python.js";import{registerMujocoCommands as u}from"./commands/mujoco.js";import{registerDuckCommand as w}from"./commands/duck.js";import{registerIpynbCommand as b}from"./commands/ipynb.js";import{registerAi4ctfCommand as j}from"./commands/ai4ctf.js";import{registerExamCommand as v}from"./commands/exam.js";import{registerCtf4aiDemoCommand as $}from"./commands/ctf4ai-demo.js";import{registerThemeCommand as T}from"./commands/theme.js";import{registerLearnCommand as A}from"./commands/learn.js";import{registerCtf4VlaCommand as I}from"./commands/ctf4vla.js";import{registerDemo2Command as E}from"./commands/demo2.js";import{registerDemo4Command as C}from"./commands/demo4.js";import{registerDemo5Command as x}from"./commands/demo5.js";import{registerGfssmCommand as _}from"./commands/gfssm.js";import{registerGpuForTaskCommand as k}from"./commands/gpufortask.js";import{registerSimCommand as S}from"./commands/sim.js";import{registerArenaCommand as L}from"./commands/arena.js";import{registerKaggleCommand as R}from"./commands/kaggle.js";import{registerSprintCommand as O}from"./commands/sprint.js";import{registerTeleloadCommand as F}from"./commands/teleload.js";import{registerBoardCommand as N}from"./commands/board.js";import{registerTypeCommand as U}from"./commands/type.js";import{registerBattleCommand as P}from"./commands/battle.js";import{registerWmCommand as M}from"./commands/wm.js";import{getConfig as D,saveConfig as G}from"./lib/config.js";import{registerMicroduckCommand as W}from"./commands/microduck.js";import{startRepl as H}from"./repl.js";import{RELAUNCH_CODE as Y}from"./lib/menu-nav.js";import{setTerminalTheme as J}from"./lib/theme.js";import{cleanupTerminal as V}from"./lib/terminal-cleanup.js";import{checkForUpdates as X,runUpgrade as q,bootUpgradeEligible as z}from"./lib/update-check.js";import{detectIcoaInstalls as K,isWindowsBuildInWslShell as B}from"./lib/platform.js";import{ICOA_BIG as Q}from"./lib/banner.js";import{readFileSync as Z}from"node:fs";import{fileURLToPath as oo}from"node:url";import{dirname as eo,join as no}from"node:path";import{setDefaultResultOrder as so}from"node:dns";import{setDefaultAutoSelectFamilyAttemptTimeout as ro}from"node:net";so("ipv4first"),ro(4e3);const to=eo(oo(import.meta.url)),io=JSON.parse(Z(no(to,"..","package.json"),"utf-8")).version,lo=chalk.cyan(" ─────────────────────────────────────────────────────"),ao=`\n${lo}\n\n${Q.map(o=>` ${chalk.bold.white(o)}`).join("\n")}\n\n ${chalk.yellow("International Cyber Olympiad in AI 2026")}\n ${chalk.bold.magenta("The World's First AI-Native CLI Operating System")}\n ${chalk.bold.magenta("for Cybersecurity & AI Security Competition")}\n ${chalk.bold.magenta("and Olympiad for K-12")}\n\n ${chalk.green.bold("AI4CTF")} ${chalk.gray("[Day 1]")} ${chalk.white("AI as your teammate")}\n ${chalk.red.bold("CTF4AI")} ${chalk.gray("[Day 2]")} ${chalk.white("Challenge & evaluate AI systems")}\n ${chalk.cyan.bold("CTF4EAI")} ${chalk.gray("[Pioneer]")} ${chalk.white("Embodied AI security")}\n ${chalk.bold.yellow("AI is your teammate. AI is your target. AI is embodied.")}\n\n ${chalk.white("Sydney, Australia")} ${chalk.gray("Jun 27 - Jul 2, 2026")}\n ${chalk.cyan.underline("https://icoa2026.au")}\n\n ${chalk.gray(`CLI-Native Competition Terminal v${io}`)}\n\n${lo}\n`;process.on("uncaughtException",o=>{"__REPL_NO_EXIT__"!==o.message&&(console.error(chalk.red("Error:"),o.message),process.exit(1))}),process.on("unhandledRejection",o=>{const e=o instanceof Error?o.message:String(o);"__REPL_NO_EXIT__"!==e&&(console.error(chalk.red("Error:"),e),process.exit(1))});{const o=process.argv.slice(2).some(o=>["-V","--version","-h","--help"].includes(o));if(!0===process.stdin.isTTY&&"1"!==process.env.ICOA_SUPERVISED&&!o){const{spawnSync:o}=await import("node:child_process");process.on("SIGINT",()=>{}),process.on("SIGTERM",()=>{});let e=0,n=!1;do{const s=n?process.argv.slice(1,2):process.argv.slice(1),r=o(process.execPath,s,{stdio:"inherit",env:{...process.env,ICOA_SUPERVISED:"1",...n?{ICOA_RELAUNCH:"1"}:{}}});if(r.signal){const{appendExitLog:o}=await import("./lib/exit-log.js");o("worker-signal",`signal=${r.signal}`),console.log(),console.log(chalk.yellow(` ⚠ icoa was stopped by signal ${r.signal}`)+chalk.gray(" — another process killed it (not a crash). Run icoa --resume to continue.")),e=0;break}if(e=r.status,0!==e&&e!==Y){const{appendExitLog:o}=await import("./lib/exit-log.js");o("worker-exit",`code=${e}`);const n=null!==e&&e>128?e-128:0;console.log(),console.log(n?chalk.yellow(` ⚠ icoa was stopped by signal ${n}`)+chalk.gray(" — another process killed it (not a crash). Run icoa --resume to continue."):chalk.yellow(` ⚠ icoa exited unexpectedly (code ${e})`)+chalk.gray(" — see ~/.icoa/exit.log · run icoa --resume to continue."))}n=!0}while(e===Y);V(),process.exit(e??0)}}const mo=new o;if(mo.name("icoa").version(io).description("ICOA CLI — CLI-Native CTF Competition Terminal").option("--resume","Resume previous session").option("--continue","Continue where you left off — jump straight to your last learn card / exam").action(async o=>{const e=D();J("high-contrast"===e.themeVariant?"high-contrast":"dark");const n=!!o.resume||!!o.continue,s=z(n)&&process.argv.length<=2;s||X(),function(){const o=K();if(o.length<=1)return;const e=o[0];if([...o.map(o=>o.version||"0.0.0")].sort((o,e)=>function(o,e){const n=o.split(".").map(o=>parseInt(o,10)||0),s=e.split(".").map(o=>parseInt(o,10)||0);for(let o=0;o<3;o++)if((n[o]||0)!==(s[o]||0))return(n[o]||0)-(s[o]||0);return 0}(e,o))[0]!==e.version){console.log(),console.log(chalk.yellow.bold(" ⚠ Multiple icoa installations detected on PATH:"));for(let e=0;e<o.length;e++){const n=o[e],s=n.version?`v${n.version}`:"(version unreadable)",r=0===e?chalk.yellow("→"):" ",t=0===e?chalk.gray(" ← currently running (older — shadowing newer install)"):chalk.gray(" ← shadowed");console.log(` ${r} ${chalk.cyan(n.path.padEnd(28))} ${chalk.white(s)}${t}`)}console.log(),console.log(chalk.yellow(" The first install on PATH wins. To use the newer one, remove the older:")),console.log(),e.pkgDir?console.log(` ${chalk.bold.cyan(`sudo rm -rf ${e.pkgDir} ${e.path}`)}`):console.log(` ${chalk.bold.cyan(`sudo rm -rf ${e.path} # also delete its node_modules dir`)}`),console.log(),console.log(chalk.gray(" Then re-run icoa to confirm version banner shows the newer release.")),console.log()}}();const r=process.env.LANG||process.env.LC_ALL||process.env.LC_CTYPE||"";if(!/UTF-?8/i.test(r))if("win32"===process.platform){let o="";try{const{execFileSync:e}=await import("node:child_process");o=e("chcp.com",[],{encoding:"utf-8",timeout:1500,stdio:["ignore","pipe","ignore"]}).trim()}catch{}o.includes("65001")||(console.log(chalk.yellow(`⚠ Windows terminal is not using UTF-8 (current: ${o||"unknown"}).`)),console.log(chalk.gray(' Non-English text (Ukrainian, Chinese, Japanese, etc.) may show as "?" or garbled glyphs.')),console.log(chalk.gray(" Fix (run before ")+chalk.cyan("icoa")+chalk.gray("): ")+chalk.cyan("chcp 65001")),console.log(chalk.gray(" Or stay in English inside the CLI: ")+chalk.cyan("lang en")),console.log())}else console.log(chalk.yellow(`⚠ Your terminal locale is not UTF-8 (LANG=${r||"(unset)"}).`)),console.log(chalk.gray(' Non-English text and box characters may display as "?" or garbled glyphs.')),console.log(chalk.gray(" Fix: ")+chalk.cyan("export LANG=en_US.UTF-8")+chalk.gray(" (or your locale, e.g. ")+chalk.cyan("zh_CN.UTF-8")+chalk.gray(", ")+chalk.cyan("uk_UA.UTF-8")+chalk.gray(")")),console.log();if(console.log(ao),s&&"upgraded"===await q({ask:!0})&&process.exit(Y),process.argv.length<=2||n)return o.continue&&(process.env.ICOA_AUTO_RESUME="1"),n||"1"===process.env.ICOA_RELAUNCH||await async function(){const o=process.stdin;if(o.isTTY&&"function"==typeof o.setRawMode)return new Promise(e=>{let n=!1;const s=()=>{if(!n){n=!0,o.removeListener("data",r);try{o.setRawMode(!1)}catch{}o.pause(),e()}},r=()=>s();o.setRawMode(!0),o.resume(),o.once("data",r),console.log(chalk.gray(" (press any key to continue...)")),setTimeout(s,3e3)});await new Promise(o=>setTimeout(o,3e3))}(),void H(mo,n)}),e(mo),n(mo),s(mo),r(mo),t(mo),i(mo),l(mo),a(mo),m(mo),c(mo),g(mo),d(mo),p(mo),y(mo),h(mo),f(mo),u(mo),w(mo),b(mo),j(mo),v(mo),$(mo),T(mo),A(mo),I(mo),E(mo),C(mo),x(mo),_(mo),k(mo),S(mo),L(mo),R(mo),F(mo),O(mo),N(mo),M(mo),U(mo),P(mo),W(mo),mo.command("model",{hidden:!0}).argument("[name]","model name to switch to").action(o=>{const e=D().geminiModel||"gemini-2.5-flash-lite";o?(G({geminiModel:o}),console.log(),console.log(chalk.green(" Model switched: ")+chalk.gray(e)+chalk.white(" -> ")+chalk.bold.white(o)),console.log()):(console.log(),console.log(chalk.gray(" Current model: ")+chalk.white(e)),console.log(),console.log(chalk.gray(" Available models:")),console.log(chalk.bold.white(" Gemini 3.x (Latest)")),console.log(chalk.white(" model gemini-3.5-flash ")+chalk.gray("Newest stable, paid Tier 1+")),console.log(chalk.white(" model gemini-3-flash-preview ")+chalk.gray("Preview")),console.log(chalk.bold.white(" Gemini 2.5 (Stable)")),console.log(chalk.white(" model gemini-2.5-flash-lite ")+chalk.gray("Fastest, default, free tier")),console.log(chalk.white(" model gemini-2.5-flash ")+chalk.gray("Heavier, thinking enabled")),console.log(chalk.white(" model gemini-2.5-pro ")+chalk.gray("Strong reasoning, paid")),console.log(chalk.bold.white(" Open Source")),console.log(chalk.white(" model gemma-4-31b-it ")+chalk.gray("Free, open-source")),console.log(chalk.white(" model <any-model-id> ")+chalk.gray("Custom model")),console.log(),console.log(chalk.gray(" Translation uses gemini-3.5-flash for best quality.")),console.log())}),"1"===process.env.ICOA_RESET_STATE)try{const{clearExamState:o}=await import("./lib/exam-state.js");o(),console.log(chalk.yellow("⚠ ICOA_RESET_STATE=1 — local exam state wiped.")),console.log(chalk.gray(" (Token NOT revoked server-side. Re-enter a fresh token with `exam <token>`.)")),console.log()}catch(o){console.log(chalk.red("⚠ ICOA_RESET_STATE: could not clear state — ")+chalk.gray(String(o)))}mo.hook("preAction",()=>{!function(){if(!B())return;const o="─".repeat(Math.max(24,Math.min(52,(process.stdout.columns||80)-4)));console.log(),console.log(chalk.yellow(` ${o}`)),console.log(chalk.yellow.bold(" ⚠ You ARE inside Ubuntu — but this icoa")),console.log(chalk.yellow.bold(" is the WINDOWS build.")),console.log(),console.log(chalk.gray(" WSL appends the Windows PATH, so ")+chalk.cyan("icoa")),console.log(chalk.gray(" found the Windows copy first. Almost")),console.log(chalk.gray(" nothing will work: no vi, no python3,")),console.log(chalk.gray(" env setup cannot install.")),console.log(),console.log(chalk.gray(" Running: ")+chalk.white(process.execPath)),console.log(),console.log(chalk.white(" Fix — inside Ubuntu, check npm is Linux FIRST:")),console.log(` ${chalk.bold.cyan("which npm")}${chalk.gray(" → must not be /mnt/c/...")}`),console.log(` ${chalk.bold.cyan("sudo npm install -g icoa-cli")}`),console.log(` ${chalk.bold.cyan("hash -r")}${chalk.gray(" → bash caches the old path")}`),console.log(chalk.gray(" Then restart icoa and check ")+chalk.bold.cyan("which icoa")),console.log(chalk.yellow(` ${o}`)),console.log()}()}),mo.parse();
|
|
2
|
+
import{Command as o}from"commander";import chalk from"chalk";import{registerCtfCommands as e}from"./commands/ctf.js";import{registerRefCommand as n}from"./commands/ref.js";import{registerShellCommand as s}from"./commands/shell.js";import{registerFilesCommand as r}from"./commands/files.js";import{registerViewCommand as t}from"./commands/view.js";import{registerConnectCommand as i}from"./commands/connect.js";import{registerChallengeCommand as l}from"./commands/challenge.js";import{registerDoctorCommand as a}from"./commands/doctor.js";import{registerUpgradeCommand as m}from"./commands/upgrade.js";import{registerNoteCommand as c}from"./commands/note.js";import{registerLogCommand as g}from"./commands/log.js";import{registerLangCommand as d}from"./commands/lang.js";import{registerSetupCommand as p}from"./commands/setup.js";import{registerEnvCommand as y}from"./commands/env.js";import{registerAienvCommand as h}from"./commands/aienv.js";import{registerPythonCommands as f}from"./commands/python.js";import{registerMujocoCommands as u}from"./commands/mujoco.js";import{registerDuckCommand as w}from"./commands/duck.js";import{registerIpynbCommand as b}from"./commands/ipynb.js";import{registerAi4ctfCommand as j}from"./commands/ai4ctf.js";import{registerExamCommand as v}from"./commands/exam.js";import{registerCtf4aiDemoCommand as $}from"./commands/ctf4ai-demo.js";import{registerThemeCommand as T}from"./commands/theme.js";import{registerLearnCommand as A}from"./commands/learn.js";import{registerCtf4VlaCommand as I}from"./commands/ctf4vla.js";import{registerDemo2Command as E}from"./commands/demo2.js";import{registerDemo4Command as C}from"./commands/demo4.js";import{registerDemo5Command as x}from"./commands/demo5.js";import{registerGfssmCommand as _}from"./commands/gfssm.js";import{registerGpuForTaskCommand as k}from"./commands/gpufortask.js";import{registerSimCommand as S}from"./commands/sim.js";import{registerArenaCommand as L}from"./commands/arena.js";import{registerKaggleCommand as R}from"./commands/kaggle.js";import{registerSprintCommand as O}from"./commands/sprint.js";import{registerTeleloadCommand as F}from"./commands/teleload.js";import{registerBoardCommand as N}from"./commands/board.js";import{registerTypeCommand as U}from"./commands/type.js";import{registerBattleCommand as P}from"./commands/battle.js";import{registerWmCommand as M}from"./commands/wm.js";import{getConfig as D,saveConfig as G}from"./lib/config.js";import{registerMicroduckCommand as W}from"./commands/microduck.js";import{startRepl as H}from"./repl.js";import{RELAUNCH_CODE as Y}from"./lib/menu-nav.js";import{setTerminalTheme as J}from"./lib/theme.js";import{cleanupTerminal as V}from"./lib/terminal-cleanup.js";import{checkForUpdates as X,runUpgrade as q,bootUpgradeEligible as z,startBootCheck as K}from"./lib/update-check.js";import{detectIcoaInstalls as B,isWindowsBuildInWslShell as Q}from"./lib/platform.js";import{ICOA_BIG as Z}from"./lib/banner.js";import{readFileSync as oo}from"node:fs";import{fileURLToPath as eo}from"node:url";import{dirname as no,join as so}from"node:path";import{setDefaultResultOrder as ro}from"node:dns";import{setDefaultAutoSelectFamilyAttemptTimeout as to}from"node:net";ro("ipv4first"),to(4e3);const io=no(eo(import.meta.url)),lo=JSON.parse(oo(so(io,"..","package.json"),"utf-8")).version,ao=chalk.cyan(" ─────────────────────────────────────────────────────"),mo=`\n${ao}\n\n${Z.map(o=>` ${chalk.bold.white(o)}`).join("\n")}\n\n ${chalk.yellow("International Cyber Olympiad in AI 2026")}\n ${chalk.bold.magenta("The World's First AI-Native CLI Operating System")}\n ${chalk.bold.magenta("for Cybersecurity & AI Security Competition")}\n ${chalk.bold.magenta("and Olympiad for K-12")}\n\n ${chalk.green.bold("AI4CTF")} ${chalk.gray("[Day 1]")} ${chalk.white("AI as your teammate")}\n ${chalk.red.bold("CTF4AI")} ${chalk.gray("[Day 2]")} ${chalk.white("Challenge & evaluate AI systems")}\n ${chalk.cyan.bold("CTF4EAI")} ${chalk.gray("[Pioneer]")} ${chalk.white("Embodied AI security")}\n ${chalk.bold.yellow("AI is your teammate. AI is your target. AI is embodied.")}\n\n ${chalk.white("Sydney, Australia")} ${chalk.gray("Jun 27 - Jul 2, 2026")}\n ${chalk.cyan.underline("https://icoa2026.au")}\n\n ${chalk.gray(`CLI-Native Competition Terminal v${lo}`)}\n\n${ao}\n`;process.on("uncaughtException",o=>{"__REPL_NO_EXIT__"!==o.message&&(console.error(chalk.red("Error:"),o.message),process.exit(1))}),process.on("unhandledRejection",o=>{const e=o instanceof Error?o.message:String(o);"__REPL_NO_EXIT__"!==e&&(console.error(chalk.red("Error:"),e),process.exit(1))});{const o=process.argv.slice(2).some(o=>["-V","--version","-h","--help"].includes(o));if(!0===process.stdin.isTTY&&"1"!==process.env.ICOA_SUPERVISED&&!o){const{spawnSync:o}=await import("node:child_process");process.on("SIGINT",()=>{}),process.on("SIGTERM",()=>{});let e=0,n=!1;do{const s=n?process.argv.slice(1,2):process.argv.slice(1),r=o(process.execPath,s,{stdio:"inherit",env:{...process.env,ICOA_SUPERVISED:"1",...n?{ICOA_RELAUNCH:"1"}:{}}});if(r.signal){const{appendExitLog:o}=await import("./lib/exit-log.js");o("worker-signal",`signal=${r.signal}`),console.log(),console.log(chalk.yellow(` ⚠ icoa was stopped by signal ${r.signal}`)+chalk.gray(" — another process killed it (not a crash). Run icoa --resume to continue.")),e=0;break}if(e=r.status,0!==e&&e!==Y){const{appendExitLog:o}=await import("./lib/exit-log.js");o("worker-exit",`code=${e}`);const n=null!==e&&e>128?e-128:0;console.log(),console.log(n?chalk.yellow(` ⚠ icoa was stopped by signal ${n}`)+chalk.gray(" — another process killed it (not a crash). Run icoa --resume to continue."):chalk.yellow(` ⚠ icoa exited unexpectedly (code ${e})`)+chalk.gray(" — see ~/.icoa/exit.log · run icoa --resume to continue."))}n=!0}while(e===Y);V(),process.exit(e??0)}}const co=new o;if(co.name("icoa").version(lo).description("ICOA CLI — CLI-Native CTF Competition Terminal").option("--resume","Resume previous session").option("--continue","Continue where you left off — jump straight to your last learn card / exam").action(async o=>{const e=D();J("high-contrast"===e.themeVariant?"high-contrast":"dark");const n=!!o.resume||!!o.continue,s=z(n)&&process.argv.length<=2;s?K():X(),function(){const o=B();if(o.length<=1)return;const e=o[0];if([...o.map(o=>o.version||"0.0.0")].sort((o,e)=>function(o,e){const n=o.split(".").map(o=>parseInt(o,10)||0),s=e.split(".").map(o=>parseInt(o,10)||0);for(let o=0;o<3;o++)if((n[o]||0)!==(s[o]||0))return(n[o]||0)-(s[o]||0);return 0}(e,o))[0]!==e.version){console.log(),console.log(chalk.yellow.bold(" ⚠ Multiple icoa installations detected on PATH:"));for(let e=0;e<o.length;e++){const n=o[e],s=n.version?`v${n.version}`:"(version unreadable)",r=0===e?chalk.yellow("→"):" ",t=0===e?chalk.gray(" ← currently running (older — shadowing newer install)"):chalk.gray(" ← shadowed");console.log(` ${r} ${chalk.cyan(n.path.padEnd(28))} ${chalk.white(s)}${t}`)}console.log(),console.log(chalk.yellow(" The first install on PATH wins. To use the newer one, remove the older:")),console.log(),e.pkgDir?console.log(` ${chalk.bold.cyan(`sudo rm -rf ${e.pkgDir} ${e.path}`)}`):console.log(` ${chalk.bold.cyan(`sudo rm -rf ${e.path} # also delete its node_modules dir`)}`),console.log(),console.log(chalk.gray(" Then re-run icoa to confirm version banner shows the newer release.")),console.log()}}();const r=process.env.LANG||process.env.LC_ALL||process.env.LC_CTYPE||"";if(!/UTF-?8/i.test(r))if("win32"===process.platform){let o="";try{const{execFileSync:e}=await import("node:child_process");o=e("chcp.com",[],{encoding:"utf-8",timeout:1500,stdio:["ignore","pipe","ignore"]}).trim()}catch{}o.includes("65001")||(console.log(chalk.yellow(`⚠ Windows terminal is not using UTF-8 (current: ${o||"unknown"}).`)),console.log(chalk.gray(' Non-English text (Ukrainian, Chinese, Japanese, etc.) may show as "?" or garbled glyphs.')),console.log(chalk.gray(" Fix (run before ")+chalk.cyan("icoa")+chalk.gray("): ")+chalk.cyan("chcp 65001")),console.log(chalk.gray(" Or stay in English inside the CLI: ")+chalk.cyan("lang en")),console.log())}else console.log(chalk.yellow(`⚠ Your terminal locale is not UTF-8 (LANG=${r||"(unset)"}).`)),console.log(chalk.gray(' Non-English text and box characters may display as "?" or garbled glyphs.')),console.log(chalk.gray(" Fix: ")+chalk.cyan("export LANG=en_US.UTF-8")+chalk.gray(" (or your locale, e.g. ")+chalk.cyan("zh_CN.UTF-8")+chalk.gray(", ")+chalk.cyan("uk_UA.UTF-8")+chalk.gray(")")),console.log();if(console.log(mo),s&&"upgraded"===await q({ask:!0})&&process.exit(Y),process.argv.length<=2||n)return o.continue&&(process.env.ICOA_AUTO_RESUME="1"),n||"1"===process.env.ICOA_RELAUNCH||await async function(){const o=process.stdin;if(o.isTTY&&"function"==typeof o.setRawMode)return new Promise(e=>{let n=!1;const s=()=>{if(!n){n=!0,o.removeListener("data",r);try{o.setRawMode(!1)}catch{}o.pause(),e()}},r=()=>s();o.setRawMode(!0),o.resume(),o.once("data",r),console.log(chalk.gray(" (press any key to continue...)")),setTimeout(s,3e3)});await new Promise(o=>setTimeout(o,3e3))}(),void H(co,n)}),e(co),n(co),s(co),r(co),t(co),i(co),l(co),a(co),m(co),c(co),g(co),d(co),p(co),y(co),h(co),f(co),u(co),w(co),b(co),j(co),v(co),$(co),T(co),A(co),I(co),E(co),C(co),x(co),_(co),k(co),S(co),L(co),R(co),F(co),O(co),N(co),M(co),U(co),P(co),W(co),co.command("model",{hidden:!0}).argument("[name]","model name to switch to").action(o=>{const e=D().geminiModel||"gemini-2.5-flash-lite";o?(G({geminiModel:o}),console.log(),console.log(chalk.green(" Model switched: ")+chalk.gray(e)+chalk.white(" -> ")+chalk.bold.white(o)),console.log()):(console.log(),console.log(chalk.gray(" Current model: ")+chalk.white(e)),console.log(),console.log(chalk.gray(" Available models:")),console.log(chalk.bold.white(" Gemini 3.x (Latest)")),console.log(chalk.white(" model gemini-3.5-flash ")+chalk.gray("Newest stable, paid Tier 1+")),console.log(chalk.white(" model gemini-3-flash-preview ")+chalk.gray("Preview")),console.log(chalk.bold.white(" Gemini 2.5 (Stable)")),console.log(chalk.white(" model gemini-2.5-flash-lite ")+chalk.gray("Fastest, default, free tier")),console.log(chalk.white(" model gemini-2.5-flash ")+chalk.gray("Heavier, thinking enabled")),console.log(chalk.white(" model gemini-2.5-pro ")+chalk.gray("Strong reasoning, paid")),console.log(chalk.bold.white(" Open Source")),console.log(chalk.white(" model gemma-4-31b-it ")+chalk.gray("Free, open-source")),console.log(chalk.white(" model <any-model-id> ")+chalk.gray("Custom model")),console.log(),console.log(chalk.gray(" Translation uses gemini-3.5-flash for best quality.")),console.log())}),"1"===process.env.ICOA_RESET_STATE)try{const{clearExamState:o}=await import("./lib/exam-state.js");o(),console.log(chalk.yellow("⚠ ICOA_RESET_STATE=1 — local exam state wiped.")),console.log(chalk.gray(" (Token NOT revoked server-side. Re-enter a fresh token with `exam <token>`.)")),console.log()}catch(o){console.log(chalk.red("⚠ ICOA_RESET_STATE: could not clear state — ")+chalk.gray(String(o)))}co.hook("preAction",()=>{!function(){if(!Q())return;const o="─".repeat(Math.max(24,Math.min(52,(process.stdout.columns||80)-4)));console.log(),console.log(chalk.yellow(` ${o}`)),console.log(chalk.yellow.bold(" ⚠ You ARE inside Ubuntu — but this icoa")),console.log(chalk.yellow.bold(" is the WINDOWS build.")),console.log(),console.log(chalk.gray(" WSL appends the Windows PATH, so ")+chalk.cyan("icoa")),console.log(chalk.gray(" found the Windows copy first. Almost")),console.log(chalk.gray(" nothing will work: no vi, no python3,")),console.log(chalk.gray(" env setup cannot install.")),console.log(),console.log(chalk.gray(" Running: ")+chalk.white(process.execPath)),console.log(),console.log(chalk.white(" Fix — inside Ubuntu, check npm is Linux FIRST:")),console.log(` ${chalk.bold.cyan("which npm")}${chalk.gray(" → must not be /mnt/c/...")}`),console.log(` ${chalk.bold.cyan("sudo npm install -g icoa-cli")}`),console.log(` ${chalk.bold.cyan("hash -r")}${chalk.gray(" → bash caches the old path")}`),console.log(chalk.gray(" Then restart icoa and check ")+chalk.bold.cyan("which icoa")),console.log(chalk.yellow(` ${o}`)),console.log()}()}),co.parse();
|
package/dist/lib/update-check.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{readFileSync as e,writeFileSync as o,existsSync as n,accessSync as t,realpathSync as r,constants as s}from"node:fs";import{join as i,dirname as a,basename as l,sep as c}from"node:path";import{fileURLToPath as u}from"node:url";import{homedir as g,platform as d}from"node:os";import{spawnSync as p}from"node:child_process";import chalk from"chalk";import{getIcoaDir as f}from"./config.js";const y=a(u(import.meta.url)),m=i(y,"..",".."),h=y,v=h.startsWith(g()+c)||h.includes(`${c}.nvm${c}`)||h.includes(`${c}.fnm${c}`)||h.includes(`${c}.volta${c}`),w="win32"===d()||"darwin"===d()||v?"":"sudo "
|
|
1
|
+
import{readFileSync as e,writeFileSync as o,existsSync as n,accessSync as t,realpathSync as r,constants as s}from"node:fs";import{join as i,dirname as a,basename as l,sep as c}from"node:path";import{fileURLToPath as u}from"node:url";import{homedir as g,platform as d}from"node:os";import{spawnSync as p}from"node:child_process";import chalk from"chalk";import{getIcoaDir as f}from"./config.js";const y=a(u(import.meta.url)),m=i(y,"..",".."),h=y,v=h.startsWith(g()+c)||h.includes(`${c}.nvm${c}`)||h.includes(`${c}.fnm${c}`)||h.includes(`${c}.volta${c}`),w="win32"===d()||"darwin"===d()||v?"":"sudo ",k=e=>`${w}npm install -g icoa-cli@${e}`,$=["https://registry.npmjs.org","https://registry.npmmirror.com"];function b(){return JSON.parse(e(i(m,"package.json"),"utf-8")).version}function C(e,o){const n=e.split(".").map(Number),t=o.split(".").map(Number);for(let e=0;e<Math.max(n.length,t.length);e++){const o=n[e]??0,r=t[e]??0;if(o>r)return!0;if(o<r)return!1}return!1}function x(){return i(f(),"update-check.json")}function O(){try{return n(x())?JSON.parse(e(x(),"utf-8")):null}catch{return null}}function S(e){try{const n={lastCheck:Date.now(),latestVersion:e.version,registries:e.registries};o(x(),JSON.stringify(n,null,2))}catch{}}async function A(e){const o=await Promise.all($.map(async o=>{const n=Date.now(),t=new AbortController,r=setTimeout(()=>t.abort(),e);try{const e=await fetch(`${o}/icoa-cli/latest`,{signal:t.signal,headers:{Accept:"application/json"}});return e.ok?{reg:o,version:(await e.json()).version??null,ms:Date.now()-n}:{reg:o,version:null,ms:1/0}}catch{return{reg:o,version:null,ms:1/0}}finally{clearTimeout(r)}}));let n=null;for(const e of o)!e.version||n&&!C(e.version,n)||(n=e.version);if(!n)return null;const t=[...o].sort((e,o)=>(e.version===n?0:1)-(o.version===n?0:1)||e.ms-o.ms);return{version:n,registries:t.map(e=>e.reg)}}let N=null;export function startBootCheck(){N??=A(2e3).then(e=>(e&&S(e),e??function(){const e=O();return e?.latestVersion?{version:e.latestVersion,registries:e.registries?.length?e.registries:$}:null}()))}function T(e,o){const n=function(e,o){const n=e.split(".").map(Number),t=o.split(".").map(Number);return n[0]!==t[0]||n[1]!==t[1]?-1:(n[2]??0)-(t[2]??0)}(o,e),t=n>0?chalk.gray(` (${n} version${1===n?"":"s"} behind)`):"",r=chalk.yellow(" ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");if(console.log(),console.log(r),console.log(chalk.bold.yellow(" ⬆ New version available!")),console.log(),console.log(chalk.white(" Current: ")+chalk.gray(`v${e}`)),console.log(chalk.white(" Latest: ")+chalk.bold.green(`v${o}`)+t),console.log(),E().ok)console.log(chalk.white(" Update: ")+chalk.gray("type ")+chalk.bold.cyan("upgrade")+chalk.gray(" at icoa>")),console.log(chalk.gray(" or in your shell: ")+chalk.cyan(k(o)));else{console.log(chalk.white(" Update: ")+chalk.bold.cyan(k(o)));const e="darwin"===d()?"Cmd+C":"win32"===d()?"Ctrl+C":"Ctrl+Shift+C";console.log(chalk.gray(` ↑ select & ${e} to copy — typos break it`))}console.log(r),console.log()}export function checkForUpdates(){setTimeout(async()=>{try{const e=b(),o=await async function(e){const o=O();if(o?.latestVersion&&Date.now()-o.lastCheck<e.maxAgeMs)return{version:o.latestVersion,registries:o.registries?.length?o.registries:$};const n=await A(e.timeoutMs);return n&&S(n),n}({maxAgeMs:6e5,timeoutMs:5e3});o&&C(o.version,e)&&T(e,o.version)}catch{}},0)}let _=null;function E(){return _||(_=(()=>{if("win32"===d())return{ok:!1,reason:"native Windows install"};let e;try{e=r(m)}catch{return{ok:!1,reason:"cannot resolve install directory"}}const o=a(e);if("node_modules"!==l(o)||"lib"!==l(a(o)))return{ok:!1,reason:"not an npm global install (dev tree?)"};const n=a(a(o));let c;try{c=r(i(a(process.execPath),"npm"))}catch{return{ok:!1,reason:"npm not found next to node"}}let u=!1;for(const e of[o,i(n,"bin")])try{t(e,s.W_OK)}catch{u=!0}return u&&0!==p("sudo",["-V"],{stdio:"ignore"}).status?{ok:!1,reason:"needs sudo, and sudo is not available"}:{ok:!0,npm:[process.execPath,c],prefix:n,needsSudo:u}})(),_)}function U(e,o,n){console.log(chalk.yellow(" ⚠ icoa cannot upgrade itself here")+chalk.gray(` — ${n}.`)),console.log(chalk.white(" Run this in your shell instead: ")+chalk.bold.cyan(k(o))),console.log(chalk.gray(" then ")+chalk.cyan("hash -r")+chalk.gray(" and ")+chalk.cyan("icoa --version")+chalk.gray(` (now v${e})`))}export async function runUpgrade(e){const o=b();e.ask&&startBootCheck();const n=e.ask?await N:await A(8e3);if(!n)return e.ask||(console.log(chalk.yellow(" ⚠ could not reach the npm registry")+chalk.gray(` — you are on v${o}.`)),console.log(chalk.gray(" Check the network (")+chalk.cyan("doctor")+chalk.gray(") and try again."))),"offline";if(e.ask||S(n),!C(n.version,o))return e.ask||console.log(chalk.green(` ✅ icoa v${o} is the latest version.`)),"current";const t=E();if(!t.ok)return e.ask?T(o,n.version):U(o,n.version,t.reason),"skipped";if(e.ask){console.log(),console.log(chalk.bold.yellow(" ⬆ New version: ")+chalk.gray(`v${o}`)+chalk.white(" → ")+chalk.bold.green(`v${n.version}`));const{default:e}=await import("@inquirer/confirm");let t=!0;try{t=await e({message:"Upgrade now? (Enter = yes, n = later)",default:!0})}catch{t=!1}if(!t)return console.log(chalk.gray(" Later — type ")+chalk.cyan("upgrade")+chalk.gray(" at icoa> any time.")),"skipped"}return function(e,o,n){const t=process.stdin;try{t.isTTY&&t.setRawMode&&t.setRawMode(!1)}catch{}e.needsSudo&&console.log(chalk.gray(" icoa is installed system-wide — sudo will ask for your computer password."));for(const t of n)for(const n of[!1,!0]){console.log(chalk.gray(` ⬇ icoa-cli@${o} from ${t.replace(/^https:\/\//,"")}${n?" (refreshing)":""} …`));const r=[e.npm[1],"install","-g",`icoa-cli@${o}`,`--prefix=${e.prefix}`,`--registry=${t}/`,...n?["--prefer-online"]:[],"--no-fund","--no-progress","--no-audit","--loglevel=error","--fetch-timeout=30000","--fetch-retries=1"],s=e.needsSudo?p("sudo",[e.npm[0],...r],{stdio:"inherit"}):p(e.npm[0],r,{stdio:"inherit"});let i="";try{i=b()}catch{}if(i===o)return!0;console.log(chalk.yellow(" ⚠ that did not work")+chalk.gray(0===s.status?` (npm finished but icoa is still v${i||"?"})`:` (npm exit ${s.status})`))}return!1}(t,n.version,n.registries)?(console.log(chalk.green(` ✅ upgraded to v${n.version}`)+("1"===process.env.ICOA_SUPERVISED?chalk.gray(" — restarting icoa …"):chalk.gray(" — run ")+chalk.cyan("icoa")+chalk.gray(" to start it."))),console.log(),"upgraded"):(console.log(chalk.red(` ✗ upgrade failed — still v${o}.`)),U(o,n.version,"every source failed"),"failed")}export function bootUpgradeEligible(e){return!0===process.stdin.isTTY&&"1"===process.env.ICOA_SUPERVISED&&"1"!==process.env.ICOA_RELAUNCH&&"1"!==process.env.ICOA_NO_UPDATE&&!process.env.ICOA_TEST_BOOT_MODE&&!e}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "icoa-cli",
|
|
3
|
-
"version": "2.19.
|
|
3
|
+
"version": "2.19.623",
|
|
4
4
|
"description": "ICOA CLI — AI-native competition runtime of the International Cyber Olympiad in AI: learn, practise, and compete in AI & cybersecurity from the terminal (AI4CTF · CTF4AI · CTF4EAI)",
|
|
5
5
|
"author": "Charlie Zhu",
|
|
6
6
|
"type": "module",
|