icoa-cli 2.19.572 โ 2.19.574
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/commands/ai4ctf.js +1 -1
- package/dist/commands/ctf4ai-demo.js +1 -1
- package/dist/commands/ctf4vla.js +1 -1
- package/dist/commands/exam.js +1 -1
- package/dist/commands/learn.js +1 -1
- package/dist/commands/microduck.js +1 -0
- package/dist/commands/mujoco.js +1 -0
- package/dist/commands/python.js +1 -1
- package/dist/index.js +1 -1
- package/dist/lib/commands.js +1 -1
- package/dist/lib/lazy-assets.js +1 -1
- package/dist/lib/mujoco-setup.js +1 -0
- package/dist/repl.js +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import chalk from"chalk";import{getConfig as o}from"../lib/config.js";import{lazyFile as c}from"../lib/lazy-assets.js";import{openMedia as i}from"../lib/open-file.js";export function isMicroduckWord(o){const c=o.trim().toLowerCase().replace(/\s+/g," ");return["microduck","/microduck","micro duck","microduck.mp4","micro-duck"].includes(c)}export async function runMicroduck(){const r=(o().language||"en").toLowerCase().startsWith("zh");console.log(),console.log(chalk.bold.white(r?" ๐ฆ MicroDuck โ ๅ่ถณ้ธญ 3 ็ง่ก่ตฐ็ๆฎต":" ๐ฆ MicroDuck โ a 3-second walk of the bipedal duck")+chalk.gray(r?"(MuJoCo ไปฟ็ ยท ๅบๅ ONNX ็ญ็ฅ ยท ็บฏ CPU)":" (MuJoCo sim ยท factory ONNX policy ยท CPU only)")),console.log(chalk.gray(r?" ้ฆๆฌก้่ฆไธ่ฝฝ 140 KBโฆ":" First time fetches 140 KBโฆ"));const e=await c("microduck/duck_walk_3s.mp4");if(!e)return console.log(chalk.yellow(r?" ๆฟไธๅฐ็ๆฎต(็ฆป็บฟ?)โ ่็ฝๅๅๆฒไธๆฌก microduckใ":" Could not fetch the clip (offline?) โ try microduck again once online.")),void console.log();i(e,o=>console.log(chalk.gray(o))),console.log(chalk.gray(` ${r?"ๆไปถ":"file"}: ${e}`)),console.log()}export function registerMicroduckCommand(o){o.command("microduck",{hidden:!0}).description("MicroDuck โ play the bipedal-duck teaser clip").action(async()=>{await runMicroduck()})}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import chalk from"chalk";import{logCommand as o}from"../lib/logger.js";import{MUJOCO_PACKAGES as e,mujocoVersionsLine as n,probeMujoco as s,provisionMujoco as t}from"../lib/mujoco-setup.js";import{probePython as a}from"../lib/python-setup.js";export function registerMujocoCommands(e){const n=e.command("mujoco").alias("mojoco").description("MuJoCo physics + onnxruntime + numpy for the robot cards โ status and one-command install");n.command("status").description("Show whether the robot sim can run on this machine").action(()=>{o("mujoco status"),printMujocoStatus()}),n.command("setup").description("Install MuJoCo + onnxruntime + numpy into ~/.icoa/mujoco (no sudo; installs Python 3.12 first if needed)").option("--force","recreate the venv and reinstall").action(async e=>{o("mujoco setup"),await runMujocoSetup(!!e.force)}),n.action(()=>{o("mujoco"),printMujocoStatus()})}export function printMujocoStatus(){const o=s(!0),t=a(!0,{hostOnly:!0});if(console.log(),console.log(chalk.bold.white(" MuJoCo โ robot sim on this machine")),console.log(chalk.gray(" โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ")),console.log(),t.ok?console.log(chalk.green(` โ Python ${t.version}`)+chalk.gray(` ยท ${t.cmd}`)):console.log(chalk.yellow(" โ No Python 3.12 yet")+chalk.gray(" โ mujoco setup installs one first (no sudo)")),o.ok)console.log(chalk.green(` โ ${n(o)}`)+chalk.gray(` ยท ${o.python}`)),console.log(),console.log(chalk.gray(" The robot cards can run the sim here and save pictures / a short video."));else{for(const n of e)o.versions[n.module]?console.log(chalk.green(` โ ${n.name} ${o.versions[n.module]}`)):console.log(chalk.yellow(` โ ${n.name}`)+chalk.gray(` โ ${n.role}`));console.log(),console.log(chalk.gray(" Reading cards and answering questions needs none of it, and a replay can come")),console.log(chalk.gray(" back from the judge. To run the sim on this machine:")),console.log(chalk.gray(" โ ")+chalk.bold.cyan("mujoco setup")+chalk.gray(" (3 packages, ~45 MB download, ~200 MB on disk, no sudo)"))}console.log()}export async function runMujocoSetup(o=!1){const a=s(!0);if(console.log(),console.log(chalk.bold.white(" MuJoCo setup")),console.log(chalk.gray(" โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ")),a.ok&&!o)return console.log(chalk.green(` โ ${n(a)} already here`)+chalk.gray(` ยท ${a.python}`)),console.log(chalk.gray(" Nothing to install. ")+chalk.gray("Re-run with ")+chalk.bold.cyan("--force")+chalk.gray(" to reinstall.")),console.log(),!0;console.log(chalk.gray(" Three packages into their own venv (~/.icoa/mujoco). No sudo; your system python3")),console.log(chalk.gray(" and the aienv notebook stack are left alone. ~45 MB down, ~200 MB on disk.")),console.log(chalk.gray(" ")+e.map(o=>chalk.white(o.name)+chalk.gray(` (${o.role})`)).join(chalk.gray(" ยท "))),console.log();const r=await t({force:o});return console.log(),r?(console.log(chalk.green(" โ Ready.")+chalk.gray(" Check any time with ")+chalk.bold.cyan("mujoco status")+chalk.gray(".")),console.log(chalk.gray(" Training (reward tweaks, 4096 ducks at once) stays on the GPU boxes โ nothing more to install here."))):(console.log(chalk.gray(" Offline or blocked? The cards still work โ reading, answering and the judge replay")),console.log(chalk.gray(" are all server-side. Try again when the network is better."))),console.log(),r}
|
package/dist/commands/python.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import chalk from"chalk";import{REQUIRED_PY as o}from"../lib/aienv.js";import{logCommand as n}from"../lib/logger.js";import{
|
|
1
|
+
import chalk from"chalk";import{REQUIRED_PY as o}from"../lib/aienv.js";import{logCommand as n}from"../lib/logger.js";import{mujocoVersionsLine as e,probeMujoco as s}from"../lib/mujoco-setup.js";import{probePython as l,provisionPython312 as a}from"../lib/python-setup.js";const r=`${o.major}.${o.minor}`;export function registerPythonCommands(o){const e=o.command("python").description(`Python ${r} โ status and one-command install`);e.command("status").description("Show which Python this machine will run your code with").action(()=>{n("python status"),printStatus()}),e.command("setup").description(`Install Python ${r} side-by-side (no sudo)`).option("--force","reinstall even if a 3.12 is already present").action(async o=>{n("python setup"),await runSetup(!!o.force)}),e.action(()=>{n("python"),printStatus()})}export function printStatus(){const o=l(!0);if(console.log(),console.log(chalk.bold.white(` Python ${r} โ this machine`)),console.log(chalk.gray(" โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ")),console.log(),o.ok){const n="aienv"===o.source?"aienv venv":"icoa"===o.source?"installed by icoa":"already on this machine";console.log(chalk.green(` โ Python ${o.version}`)+chalk.gray(` ยท ${n}`)),console.log(chalk.gray(` ${o.cmd}`)),console.log(),console.log(chalk.gray(" Your code runs locally: ")+chalk.bold.cyan("/py")+chalk.gray(" scratchpad ยท arena ")+chalk.bold.cyan("/run")+chalk.gray(" and ")+chalk.bold.cyan("/debug")+chalk.gray("."));const l=s();console.log(),l.ok?console.log(chalk.green(` โ ${e(l)}`)+chalk.gray(" ยท robot sim runs locally")):console.log(chalk.gray(" Robot cards (sim): ")+chalk.bold.cyan("mujoco setup")+chalk.gray(" โ MuJoCo + onnxruntime + numpy, ~45 MB, no sudo. Not needed to read or answer."))}else o.otherVersion?(console.log(chalk.yellow(` โ Python ${o.otherVersion} found โ but courses run on the ${r} line.`)),console.log(chalk.gray(" 3.13 is not a newer 3.12: stdlib removals and missing wheels make it a different machine to grade on."))):console.log(chalk.yellow(" โ No Python on this machine.")),console.log(),console.log(chalk.gray(" Reading cards and answering questions needs none of it. ")+chalk.gray("To run code:")),console.log(chalk.gray(" โ ")+chalk.bold.cyan("python setup")+chalk.gray(" (~25-35 MB, ~20 s, no sudo)"));console.log()}export async function runSetup(o=!1){const n=l(!0);if(console.log(),console.log(chalk.bold.white(` Python ${r}`)),console.log(chalk.gray(" โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ")),n.ok&&!o)return console.log(chalk.green(` โ Python ${n.version} is already here`)+chalk.gray(` ยท ${n.cmd}`)),console.log(chalk.gray(" Nothing to install. ")+chalk.gray("Re-run with ")+chalk.bold.cyan("--force")+chalk.gray(" to reinstall.")),console.log(),!0;console.log(chalk.gray(" One interpreter, side-by-side. No sudo, no pip, and your system python3 is left alone.")),console.log(chalk.gray(" ~25-35 MB ยท about twenty seconds on a normal link.")),console.log();const e=await a({force:o});return console.log(),e?(console.log(chalk.gray(" Ready: ")+chalk.bold.cyan("learn")+chalk.gray(" โ open a card โ ")+chalk.bold.cyan("/py")+chalk.gray(" โ ")+chalk.bold.cyan("run 1")),console.log(chalk.gray(" Later, if a course needs numpy / pandas / matplotlib: ")+chalk.bold.cyan("aienv setup")+chalk.gray("."))):(console.log(chalk.gray(" Offline or blocked? Your course still works โ reading, answering and")),console.log(chalk.gray(" ")+chalk.bold.cyan("/submit")+chalk.gray(" are all server-side. Try again when the network is better."))),console.log(),e}
|
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{registerNoteCommand as c}from"./commands/note.js";import{registerLogCommand as m}from"./commands/log.js";import{registerLangCommand as g}from"./commands/lang.js";import{registerSetupCommand as d}from"./commands/setup.js";import{registerEnvCommand as p}from"./commands/env.js";import{registerAienvCommand as y}from"./commands/aienv.js";import{registerPythonCommands as h}from"./commands/python.js";import{registerIpynbCommand as f}from"./commands/ipynb.js";import{registerAi4ctfCommand as u}from"./commands/ai4ctf.js";import{registerExamCommand as w}from"./commands/exam.js";import{registerCtf4aiDemoCommand as b}from"./commands/ctf4ai-demo.js";import{registerThemeCommand as j}from"./commands/theme.js";import{registerLearnCommand as $}from"./commands/learn.js";import{registerCtf4VlaCommand as v}from"./commands/ctf4vla.js";import{registerDemo2Command as T}from"./commands/demo2.js";import{registerDemo4Command as A}from"./commands/demo4.js";import{registerDemo5Command as I}from"./commands/demo5.js";import{registerGfssmCommand as E}from"./commands/gfssm.js";import{registerGpuForTaskCommand as C}from"./commands/gpufortask.js";import{registerSimCommand as _}from"./commands/sim.js";import{registerArenaCommand as x}from"./commands/arena.js";import{registerKaggleCommand as S}from"./commands/kaggle.js";import{registerSprintCommand as k}from"./commands/sprint.js";import{registerTeleloadCommand as L}from"./commands/teleload.js";import{registerBoardCommand as R}from"./commands/board.js";import{registerTypeCommand as O}from"./commands/type.js";import{registerBattleCommand as F}from"./commands/battle.js";import{registerWmCommand as N}from"./commands/wm.js";import{getConfig as U,saveConfig as P}from"./lib/config.js";import{startRepl as M}from"./repl.js";import{RELAUNCH_CODE as D}from"./lib/menu-nav.js";import{setTerminalTheme as G}from"./lib/theme.js";import{cleanupTerminal as W}from"./lib/terminal-cleanup.js";import{checkForUpdates as H}from"./lib/update-check.js";import{detectIcoaInstalls as Y,isWindowsBuildInWslShell as J}from"./lib/platform.js";import{ICOA_BIG as V}from"./lib/banner.js";import{readFileSync as X}from"node:fs";import{fileURLToPath as q}from"node:url";import{dirname as z,join as K}from"node:path";import{setDefaultResultOrder as B}from"node:dns";import{setDefaultAutoSelectFamilyAttemptTimeout as Q}from"node:net";B("ipv4first"),Q(4e3);const Z=z(q(import.meta.url)),oo=JSON.parse(X(K(Z,"..","package.json"),"utf-8")).version,eo=chalk.cyan(" โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ"),no=`\n${eo}\n\n${V.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${oo}`)}\n\n${eo}\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!==D){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===D);W(),process.exit(e??0)}}const so=new o;if(so.name("icoa").version(oo).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=U();G("high-contrast"===e.themeVariant?"high-contrast":"dark"),H(),function(){const o=Y();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 n=process.env.LANG||process.env.LC_ALL||process.env.LC_CTYPE||"";if(!/UTF-?8/i.test(n))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=${n||"(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();console.log(no);const s=!!o.resume||!!o.continue;if(process.argv.length<=2||s)return o.continue&&(process.env.ICOA_AUTO_RESUME="1"),s||"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 M(so,s)}),e(so),n(so),s(so),r(so),t(so),i(so),l(so),a(so),c(so),m(so),g(so),d(so),p(so),y(so),h(so),f(so),u(so),w(so),b(so),j(so),$(so),v(so),T(so),A(so),I(so),E(so),C(so),_(so),x(so),S(so),L(so),k(so),R(so),N(so),O(so),F(so),so.command("model",{hidden:!0}).argument("[name]","model name to switch to").action(o=>{const e=U().geminiModel||"gemini-2.5-flash-lite";o?(P({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)))}so.hook("preAction",()=>{!function(){if(!J())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()}()}),so.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{registerNoteCommand as m}from"./commands/note.js";import{registerLogCommand as c}from"./commands/log.js";import{registerLangCommand as g}from"./commands/lang.js";import{registerSetupCommand as d}from"./commands/setup.js";import{registerEnvCommand as p}from"./commands/env.js";import{registerAienvCommand as y}from"./commands/aienv.js";import{registerPythonCommands as h}from"./commands/python.js";import{registerMujocoCommands as f}from"./commands/mujoco.js";import{registerIpynbCommand as u}from"./commands/ipynb.js";import{registerAi4ctfCommand as w}from"./commands/ai4ctf.js";import{registerExamCommand as b}from"./commands/exam.js";import{registerCtf4aiDemoCommand as j}from"./commands/ctf4ai-demo.js";import{registerThemeCommand as $}from"./commands/theme.js";import{registerLearnCommand as v}from"./commands/learn.js";import{registerCtf4VlaCommand as T}from"./commands/ctf4vla.js";import{registerDemo2Command as A}from"./commands/demo2.js";import{registerDemo4Command as I}from"./commands/demo4.js";import{registerDemo5Command as E}from"./commands/demo5.js";import{registerGfssmCommand as C}from"./commands/gfssm.js";import{registerGpuForTaskCommand as _}from"./commands/gpufortask.js";import{registerSimCommand as x}from"./commands/sim.js";import{registerArenaCommand as S}from"./commands/arena.js";import{registerKaggleCommand as k}from"./commands/kaggle.js";import{registerSprintCommand as L}from"./commands/sprint.js";import{registerTeleloadCommand as R}from"./commands/teleload.js";import{registerBoardCommand as O}from"./commands/board.js";import{registerTypeCommand as F}from"./commands/type.js";import{registerBattleCommand as N}from"./commands/battle.js";import{registerWmCommand as U}from"./commands/wm.js";import{getConfig as P,saveConfig as M}from"./lib/config.js";import{registerMicroduckCommand as D}from"./commands/microduck.js";import{startRepl as G}from"./repl.js";import{RELAUNCH_CODE as W}from"./lib/menu-nav.js";import{setTerminalTheme as H}from"./lib/theme.js";import{cleanupTerminal as Y}from"./lib/terminal-cleanup.js";import{checkForUpdates as J}from"./lib/update-check.js";import{detectIcoaInstalls as V,isWindowsBuildInWslShell as X}from"./lib/platform.js";import{ICOA_BIG as q}from"./lib/banner.js";import{readFileSync as z}from"node:fs";import{fileURLToPath as K}from"node:url";import{dirname as B,join as Q}from"node:path";import{setDefaultResultOrder as Z}from"node:dns";import{setDefaultAutoSelectFamilyAttemptTimeout as oo}from"node:net";Z("ipv4first"),oo(4e3);const eo=B(K(import.meta.url)),no=JSON.parse(z(Q(eo,"..","package.json"),"utf-8")).version,so=chalk.cyan(" โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ"),ro=`\n${so}\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${no}`)}\n\n${so}\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!==W){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===W);Y(),process.exit(e??0)}}const to=new o;if(to.name("icoa").version(no).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=P();H("high-contrast"===e.themeVariant?"high-contrast":"dark"),J(),function(){const o=V();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 n=process.env.LANG||process.env.LC_ALL||process.env.LC_CTYPE||"";if(!/UTF-?8/i.test(n))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=${n||"(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();console.log(ro);const s=!!o.resume||!!o.continue;if(process.argv.length<=2||s)return o.continue&&(process.env.ICOA_AUTO_RESUME="1"),s||"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 G(to,s)}),e(to),n(to),s(to),r(to),t(to),i(to),l(to),a(to),m(to),c(to),g(to),d(to),p(to),y(to),h(to),f(to),u(to),w(to),b(to),j(to),$(to),v(to),T(to),A(to),I(to),E(to),C(to),_(to),x(to),S(to),k(to),R(to),L(to),O(to),U(to),F(to),N(to),D(to),to.command("model",{hidden:!0}).argument("[name]","model name to switch to").action(o=>{const e=P().geminiModel||"gemini-2.5-flash-lite";o?(M({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)))}to.hook("preAction",()=>{!function(){if(!X())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()}()}),to.parse();
|
package/dist/lib/commands.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const REGISTRY=[{name:"join",mapsTo:["ctf","join"],rest:!0,help:{order:0,section:"Competition",label:"join <url>",text:"Connect to CTFd"}},{name:"activate",mapsTo:["ctf","activate"],rest:!0},{name:"challenges",mapsTo:["ctf","challenges"],help:{order:1,section:"Competition",label:"challenges (ch)",text:"List challenges by category"}},{name:"ch",mapsTo:["ctf","challenges"]},{name:"open",mapsTo:["ctf","open"],rest:!0,help:{order:2,section:"Competition",label:"open <id>",text:"Read challenge + get next steps"}},{name:"submit",mapsTo:["ctf","submit"],rest:!0,help:{order:3,section:"Competition",label:"submit <id> <flag>",text:"Submit a flag"}},{name:"flag",mapsTo:["ctf","submit"],rest:!0},{name:"scoreboard",mapsTo:["ctf","scoreboard"],rest:!0,help:{order:4,section:"Competition",label:"scoreboard (sb)",text:"Live rankings"}},{name:"sb",mapsTo:["ctf","scoreboard"],rest:!0},{name:"status",mapsTo:["ctf","status"],help:{order:5,section:"Competition",label:"status",text:"Your score & timer"}},{name:"time",mapsTo:["ctf","time"],help:{order:6,section:"Competition",label:"time",text:"Countdown timer"}},{name:"ref",help:{order:8,section:"Tools",label:"ref [topic]",text:"Quick reference (linux, web, crypto...)"}},{name:"shell",help:{order:9,section:"Tools",label:"shell",text:"Interactive CTF shell (sandbox if present, else host)"}},{name:"files",help:{order:10,section:"Tools",label:"files <id>",text:"Download challenge files"}},{name:"view"},{name:"connect",help:{order:11,section:"Tools",label:"connect <id>",text:"Connect to remote target"}},{name:"challenge",subs:["start","stop","status"]},{name:"note",help:{order:12,section:"Tools",label:"note [text]",text:"Add a logbook entry (in-exam: tags current Q)"}},{name:"notes"},{name:"logbook",help:{order:13,section:"Tools",label:"logbook [n]",text:"View your logbook (in-exam: filter by Q)"}},{name:"log",help:{order:14,section:"Tools",label:"log",text:"Session history"}},{name:"man"},{name:"manual"},{name:"lang",help:{order:21,section:"System",label:"lang [code]",text:"Switch language (15 supported)"}},{name:"setup"},{name:"env"},{name:"aienv"},{name:"python",subs:["setup","status"]},{name:"ipynb"},{name:"kaggle"},{name:"teleload"},{name:"pandahelpme31"},{name:"gpufortask"},{name:"guide"},{name:"ai4ctf",help:{order:7,section:"AI Teammate",label:"ai4ctf",text:"Free-chat with your AI teammate"}},{name:"model"},{name:"ctf",subs:["challenges","open","submit","scoreboard","status","join","logout","time"]},{name:"exam",subs:["list","start","q","answer","submit","review","result","next","prev","mark","unmark","help"]},{name:"demo",mapsTo:["exam","demo"]},{name:"retry",mapsTo:["exam","demo-retry"]},{name:"nations",mapsTo:["exam","nations"]},{name:"next",mapsTo:["exam","next"]},{name:"prev",mapsTo:["exam","prev"]},{name:"continue"},{name:"logout",mapsTo:["ctf","logout"],help:{order:22,section:"System",label:"logout",text:"Disconnect"}},{name:"ctf4ai"},{name:"mark",mapsTo:["exam","mark"],rest:!0},{name:"unmark",mapsTo:["exam","unmark"],rest:!0},{name:"review",mapsTo:["exam","review"]},{name:"learn",subs:["start","continue"]},{name:"demo2"},{name:"demo4"},{name:"demo5"},{name:"gfssm"},{name:"ctf4eai"},{name:"ctf4vla"},{name:"theme"},{name:"sim"},{name:"arena",subs:["eai"]},{name:"eai"},{name:"wm"},{name:"battle",subs:["edit","syntax","play","replay","submit","status","bots"]},{name:"type",subs:["15","30","60","words","python","shell","history"],help:{order:15,section:"Tools",label:"type [30]",text:"Typing speed trainer โ WPM, live colours, no token"}},{name:"board"},{name:"learn-pull"},{name:"doctor",help:{order:19,section:"System",label:"doctor",text:"Self-check: version, Python, network/firewall, server"}},{name:"bg",nav:!0,help:{order:17,section:"System",label:"bg <command>",text:"Run a shell command in the background"}},{name:"tasks",nav:!0,help:{order:18,section:"System",label:"tasks [id]",text:"Background task panel / view output"}},{name:"drafts",nav:!0,help:{order:16,section:"System",label:"drafts",text:"Review staged draft answers"}},{name:"help",nav:!0},{name:"menu",nav:!0},{name:"quit",nav:!0},{name:"q",nav:!0},{name:"exit",nav:!0,help:{order:24,section:"System",label:"exit",text:"Quit (session saved)"}},{name:"back",nav:!0},{name:"resume",nav:!0,help:{order:15,section:"System",label:"resume",text:"Continue your last learn card / exam"}},{name:"clear",nav:!0,help:{order:23,section:"System",label:"clear",text:"Clear screen"}},{name:"cls",nav:!0}];export const surface=()=>REGISTRY.map(e=>e.name);export const dispatchable=()=>REGISTRY.filter(e=>!e.nav).map(e=>e.name);export function shortcutFor(e,t){const a=REGISTRY.find(t=>t.name===e&&t.mapsTo);return a?.mapsTo?a.rest?[...a.mapsTo,...t]:[...a.mapsTo]:null}export const subcommandsOf=e=>REGISTRY.find(t=>t.name===e)?.subs;export const helpRows=e=>REGISTRY.filter(t=>t.help?.section===e).sort((e,t)=>e.help.order-t.help.order).map(e=>({label:e.help.label,text:e.help.text}));
|
|
1
|
+
export const REGISTRY=[{name:"join",mapsTo:["ctf","join"],rest:!0,help:{order:0,section:"Competition",label:"join <url>",text:"Connect to CTFd"}},{name:"activate",mapsTo:["ctf","activate"],rest:!0},{name:"challenges",mapsTo:["ctf","challenges"],help:{order:1,section:"Competition",label:"challenges (ch)",text:"List challenges by category"}},{name:"ch",mapsTo:["ctf","challenges"]},{name:"open",mapsTo:["ctf","open"],rest:!0,help:{order:2,section:"Competition",label:"open <id>",text:"Read challenge + get next steps"}},{name:"submit",mapsTo:["ctf","submit"],rest:!0,help:{order:3,section:"Competition",label:"submit <id> <flag>",text:"Submit a flag"}},{name:"flag",mapsTo:["ctf","submit"],rest:!0},{name:"scoreboard",mapsTo:["ctf","scoreboard"],rest:!0,help:{order:4,section:"Competition",label:"scoreboard (sb)",text:"Live rankings"}},{name:"sb",mapsTo:["ctf","scoreboard"],rest:!0},{name:"status",mapsTo:["ctf","status"],help:{order:5,section:"Competition",label:"status",text:"Your score & timer"}},{name:"time",mapsTo:["ctf","time"],help:{order:6,section:"Competition",label:"time",text:"Countdown timer"}},{name:"ref",help:{order:8,section:"Tools",label:"ref [topic]",text:"Quick reference (linux, web, crypto...)"}},{name:"shell",help:{order:9,section:"Tools",label:"shell",text:"Interactive CTF shell (sandbox if present, else host)"}},{name:"files",help:{order:10,section:"Tools",label:"files <id>",text:"Download challenge files"}},{name:"view"},{name:"connect",help:{order:11,section:"Tools",label:"connect <id>",text:"Connect to remote target"}},{name:"challenge",subs:["start","stop","status"]},{name:"note",help:{order:12,section:"Tools",label:"note [text]",text:"Add a logbook entry (in-exam: tags current Q)"}},{name:"notes"},{name:"logbook",help:{order:13,section:"Tools",label:"logbook [n]",text:"View your logbook (in-exam: filter by Q)"}},{name:"log",help:{order:14,section:"Tools",label:"log",text:"Session history"}},{name:"man"},{name:"manual"},{name:"lang",help:{order:21,section:"System",label:"lang [code]",text:"Switch language (15 supported)"}},{name:"setup"},{name:"env"},{name:"aienv"},{name:"python",subs:["setup","status"]},{name:"mujoco",subs:["setup","status"]},{name:"mojoco",mapsTo:["mujoco"],rest:!0},{name:"ipynb"},{name:"kaggle"},{name:"teleload"},{name:"pandahelpme31"},{name:"gpufortask"},{name:"guide"},{name:"ai4ctf",help:{order:7,section:"AI Teammate",label:"ai4ctf",text:"Free-chat with your AI teammate"}},{name:"model"},{name:"ctf",subs:["challenges","open","submit","scoreboard","status","join","logout","time"]},{name:"exam",subs:["list","start","q","answer","submit","review","result","next","prev","mark","unmark","help"]},{name:"demo",mapsTo:["exam","demo"]},{name:"retry",mapsTo:["exam","demo-retry"]},{name:"nations",mapsTo:["exam","nations"]},{name:"next",mapsTo:["exam","next"]},{name:"prev",mapsTo:["exam","prev"]},{name:"continue"},{name:"logout",mapsTo:["ctf","logout"],help:{order:22,section:"System",label:"logout",text:"Disconnect"}},{name:"ctf4ai"},{name:"mark",mapsTo:["exam","mark"],rest:!0},{name:"unmark",mapsTo:["exam","unmark"],rest:!0},{name:"review",mapsTo:["exam","review"]},{name:"learn",subs:["start","continue"]},{name:"demo2"},{name:"demo4"},{name:"demo5"},{name:"gfssm"},{name:"ctf4eai"},{name:"ctf4vla"},{name:"theme"},{name:"sim"},{name:"arena",subs:["eai"]},{name:"eai"},{name:"wm"},{name:"microduck"},{name:"battle",subs:["edit","syntax","play","replay","submit","status","bots"]},{name:"type",subs:["15","30","60","words","python","shell","history"],help:{order:15,section:"Tools",label:"type [30]",text:"Typing speed trainer โ WPM, live colours, no token"}},{name:"board"},{name:"learn-pull"},{name:"doctor",help:{order:19,section:"System",label:"doctor",text:"Self-check: version, Python, network/firewall, server"}},{name:"bg",nav:!0,help:{order:17,section:"System",label:"bg <command>",text:"Run a shell command in the background"}},{name:"tasks",nav:!0,help:{order:18,section:"System",label:"tasks [id]",text:"Background task panel / view output"}},{name:"drafts",nav:!0,help:{order:16,section:"System",label:"drafts",text:"Review staged draft answers"}},{name:"help",nav:!0},{name:"menu",nav:!0},{name:"quit",nav:!0},{name:"q",nav:!0},{name:"exit",nav:!0,help:{order:24,section:"System",label:"exit",text:"Quit (session saved)"}},{name:"back",nav:!0},{name:"resume",nav:!0,help:{order:15,section:"System",label:"resume",text:"Continue your last learn card / exam"}},{name:"clear",nav:!0,help:{order:23,section:"System",label:"clear",text:"Clear screen"}},{name:"cls",nav:!0}];export const surface=()=>REGISTRY.map(e=>e.name);export const dispatchable=()=>REGISTRY.filter(e=>!e.nav).map(e=>e.name);export function shortcutFor(e,t){const a=REGISTRY.find(t=>t.name===e&&t.mapsTo);return a?.mapsTo?a.rest?[...a.mapsTo,...t]:[...a.mapsTo]:null}export const subcommandsOf=e=>REGISTRY.find(t=>t.name===e)?.subs;export const helpRows=e=>REGISTRY.filter(t=>t.help?.section===e).sort((e,t)=>e.help.order-t.help.order).map(e=>({label:e.help.label,text:e.help.text}));
|
package/dist/lib/lazy-assets.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{spawnSync as t}from"node:child_process";import{existsSync as r,mkdirSync as n,readFileSync as e,renameSync as o,statSync as a,writeFileSync as s}from"node:fs";import{homedir as c}from"node:os";import{dirname as i,join as u}from"node:path";const l="https://practice.icoa2026.au/assets/translations";export function assetDir(){const t=u(c(),".icoa","assets");return r(t)||n(t,{recursive:!0}),t}export async function lazyJson(t,n=6e3,e){const o=u(assetDir(),t),s=r(o);return s&&function(t){try{return Date.now()-a(t).mtimeMs<6048e5}catch{return!1}}(o)&&!e?.force||await
|
|
1
|
+
import{spawnSync as t}from"node:child_process";import{existsSync as r,mkdirSync as n,readFileSync as e,renameSync as o,statSync as a,writeFileSync as s}from"node:fs";import{homedir as c}from"node:os";import{dirname as i,join as u}from"node:path";const l="https://practice.icoa2026.au/assets/translations";export function assetDir(){const t=u(c(),".icoa","assets");return r(t)||n(t,{recursive:!0}),t}export async function lazyJson(t,n=6e3,e){const o=u(assetDir(),t),s=r(o);return s&&function(t){try{return Date.now()-a(t).mtimeMs<6048e5}catch{return!1}}(o)&&!e?.force||await p(`${l}/${t}`,o,n)||s?f(o):null}function f(t){try{return JSON.parse(e(t,"utf8"))}catch{return null}}async function p(t,r,e){const a=`${r}.part`;try{n(i(r),{recursive:!0});const c=new AbortController,u=setTimeout(()=>c.abort(),e),l=await fetch(t,{signal:c.signal});if(clearTimeout(u),!l.ok)return!1;const f=Buffer.from(await l.arrayBuffer());return!!f.length&&(s(a,f),o(a,r),!0)}catch{return!1}}export async function lazyFile(t,n=2e4){const e=u(assetDir(),t);return r(e)||await p(`${l}/${t}`,e,n)?e:null}export async function lazyTarball(e,a,c=15e3){const i=u(assetDir(),a),f=u(i,".complete");if(r(f))return i;const m=u(assetDir(),e);if(!await p(`${l}/${e}`,m,c))return null;const y=`${i}.staging`;try{return n(y,{recursive:!0}),0!==t("tar",["-xzf",m,"-C",y],{stdio:"ignore"}).status?null:(r(i)&&o(i,`${i}.old-${Date.now()}`),o(y,i),s(f,(new Date).toISOString()),i)}catch{return null}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import chalk from"chalk";import{execSync as o}from"node:child_process";import{existsSync as n,mkdirSync as e,writeFileSync as t}from"node:fs";import{homedir as r}from"node:os";import{posix as i,win32 as s}from"node:path";import{REQUIRED_PY as p}from"./aienv.js";import{probePython as c,provisionPython312 as u,resetPythonProbe as a}from"./python-setup.js";const m=`${p.major}.${p.minor}`;export const MUJOCO_PACKAGES=[{name:"numpy",module:"numpy",spec:"numpy>=1.26",role:"vectors"},{name:"mujoco",module:"mujoco",spec:"mujoco>=3.2",role:"physics + rendering"},{name:"onnxruntime",module:"onnxruntime",spec:"onnxruntime>=1.18",role:"runs the walking policy"}];export function mujocoPaths(o,n=process.platform){const e="win32"===n?s:i,t=e.join(o,".icoa","mujoco");if("win32"===n){const o=e.join(t,"Scripts");return{root:t,binDir:o,python:e.join(o,"python.exe"),marker:e.join(t,"icoa-mujoco.json")}}const r=e.join(t,"bin");return{root:t,binDir:r,python:e.join(r,"python"),marker:e.join(t,"icoa-mujoco.json")}}let l;export function probeMujoco(e=!1){if(l&&!e)return l;const t=mujocoPaths(r()),i={ok:!1,venv:n(t.python),python:t.python,versions:{},missing:[]};if(!i.venv)return i.missing=MUJOCO_PACKAGES.map(o=>o.module),l=i,i;const s=MUJOCO_PACKAGES.map(o=>o.module),p=["import json, importlib","out = {}",`for m in ${JSON.stringify(s)}:`," try:",' mod = importlib.import_module(m); out[m] = str(getattr(mod, "__version__", "?"))'," except Exception:"," out[m] = None","print(json.dumps(out))",""].join("\n");try{const n=o(`"${t.python}" -`,{input:p,encoding:"utf-8",stdio:["pipe","pipe","ignore"],timeout:2e4}).trim(),e=JSON.parse(n.split("\n").pop()??"{}");for(const o of s)e[o]?i.versions[o]=e[o]:i.missing.push(o)}catch{i.missing=s}return i.ok=0===i.missing.length,l=i,i}export function mujocoVersionsLine(o){return MUJOCO_PACKAGES.filter(n=>o.versions[n.module]).map(n=>`${n.name} ${o.versions[n.module]}`).join(" ยท ")}export function mujocoDoorLine(o,n=!1,e){const t=e??probeMujoco(),r=n?"":"๐ฆ ";return t.ok?chalk.gray(` ${r}${mujocoVersionsLine(t)} ยท `)+chalk.gray(o?"ๆฌๆบๅฏ่ทไปฟ็":"sim runs locally"):t.venv?chalk.gray(` ${r}`+(o?`็ผบ ${t.missing.join(", ")} ยท `:`missing ${t.missing.join(", ")} ยท `))+chalk.bold.green("mujoco setup")+chalk.gray(o?" ่กฅ้ฝ":" finishes the install"):chalk.gray(` ${r}${o?"ๆฒกๆ MuJoCo โ ่ฏปๅก็ญ้ขไธ้่ฆๅฎ,ๅๆพๅฏ็ฑๅคๅๆบ้ๅ ยท ":"No MuJoCo โ reading and answering cards works without it, replays can come from the judge ยท "}`)+chalk.bold.green("mujoco setup")+chalk.gray(o?" ่ฎฉ run ๅจๆฌๆบๅบๅพ(~45 MB,ๅ
sudo)":" to run the sim here (~45 MB, no sudo)")}function g(n){try{return o(`"${n}" -m pip --version`,{stdio:"ignore",timeout:15e3}),!0}catch{return!1}}function y(o){const n=(o?.stderr?.toString()??"").split("\n").map(o=>o.trim()).filter(Boolean);return n.length?n[n.length-1].slice(0,120):""}export async function provisionMujoco(s={}){const p=o=>{s.quiet||console.log(o)},l=r(),d=mujocoPaths(l);let h=c(!0,{hostOnly:!0});if(!h.ok){if(p(chalk.gray(` No Python ${m} here โ installing one first (stage 0, no sudo) โฆ`)),!await u({quiet:s.quiet}))return p(chalk.red(` โ Could not get a Python ${m}`)+chalk.gray(" โ try ")+chalk.bold.cyan("python setup")),!1;if(a(),h=c(!0,{hostOnly:!0}),!h.ok||!h.cmd)return!1}const f=h.cmd;if(p(chalk.green(` โ Python ${h.version}`)+chalk.gray(` ยท ${f}`)),s.force&&n(d.root)){p(chalk.gray(" --force: recreating the venv โฆ"));try{o(`${f.includes(" ")?f:`"${f}"`} -m venv --clear "${d.root}"`,{stdio:["ignore","ignore","pipe"]})}catch{}}if(n(d.python))p(chalk.green(" โ venv exists")+chalk.gray(" โ reusing"));else{p(chalk.gray(` Creating venv โ ${d.root}`));try{e(i.join(l,".icoa"),{recursive:!0}),o(`${f.includes(" ")?f:`"${f}"`} -m venv "${d.root}"`,{stdio:["ignore","ignore","pipe"]})}catch(o){return p(chalk.red(" โ Could not create the venv")+chalk.gray(y(o)?` (${y(o)})`:"")),"linux"===process.platform&&p(chalk.gray(" A distro 3.12 without venv? ")+chalk.bold.cyan("python setup")+chalk.gray(" installs one that has venv and pip built in.")),!1}p(chalk.green(" โ venv created"))}if(!g(d.python)){p(chalk.gray(" Bootstrapping pip โฆ"));try{o(`"${d.python}" -m ensurepip --upgrade`,{stdio:["ignore","ignore","pipe"]})}catch{}if(!g(d.python))return p(chalk.red(" โ The venv has no pip and it could not be bootstrapped.")),p(chalk.gray(" Fix: ")+chalk.bold.cyan("python setup")+chalk.gray(" then ")+chalk.bold.cyan("mujoco setup --force")),!1}const v=probeMujoco(!0);let $=0;for(const n of MUJOCO_PACKAGES)if(v.versions[n.module])p(chalk.green(` โ ${n.name} ${v.versions[n.module]}`)+chalk.gray(" (already installed)"));else{p(chalk.cyan(` โฌ ${n.name}`)+chalk.gray(` ${n.spec} โ ${n.role}`));try{o(`"${d.python}" -m pip install --disable-pip-version-check -q "${n.spec}"`,{stdio:["ignore","ignore","pipe"],timeout:9e5})}catch(o){p(chalk.red(` โ ${n.name} failed to install`)+chalk.gray(y(o)?` (${y(o)})`:"")),$++}}const j=probeMujoco(!0);for(const o of MUJOCO_PACKAGES)v.versions[o.module]||(j.versions[o.module]?p(chalk.green(` โ ${o.name} ${j.versions[o.module]} installed`)):$||p(chalk.red(` โ ${o.name} installed but does not import`)));if(!j.ok)return!1;const b={version:1,hostPython:(function(n){try{return o(`${n} --version`,{encoding:"utf-8",stdio:["ignore","pipe","ignore"],timeout:5e3}).trim()}catch{return null}}(f.includes(" ")?f:`"${f}"`)??h.version??m).replace(/^Python\s+/i,""),venvPython:d.python,packages:MUJOCO_PACKAGES.map(o=>o.name),created:(new Date).toISOString()};try{t(d.marker,`${JSON.stringify(b,null,2)}\n`)}catch{}return!0}
|