icoa-cli 2.19.571 → 2.19.573
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/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/mujoco-setup.js +1 -0
- package/dist/lib/tls-trust.js +1 -1
- package/dist/repl.js +1 -1
- package/package.json +1 -1
|
@@ -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";B("ipv4first");const Q=z(q(import.meta.url)),Z=JSON.parse(X(K(Q,"..","package.json"),"utf-8")).version,oo=chalk.cyan(" ─────────────────────────────────────────────────────"),eo=`\n${oo}\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${Z}`)}\n\n${oo}\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 no=new o;if(no.name("icoa").version(Z).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(eo);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(no,s)}),e(no),n(no),s(no),r(no),t(no),i(no),l(no),a(no),c(no),m(no),g(no),d(no),p(no),y(no),h(no),f(no),u(no),w(no),b(no),j(no),$(no),v(no),T(no),A(no),I(no),E(no),C(no),_(no),x(no),S(no),L(no),k(no),R(no),N(no),O(no),F(no),no.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)))}no.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()}()}),no.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{startRepl as D}from"./repl.js";import{RELAUNCH_CODE as G}from"./lib/menu-nav.js";import{setTerminalTheme as W}from"./lib/theme.js";import{cleanupTerminal as H}from"./lib/terminal-cleanup.js";import{checkForUpdates as Y}from"./lib/update-check.js";import{detectIcoaInstalls as J,isWindowsBuildInWslShell as V}from"./lib/platform.js";import{ICOA_BIG as X}from"./lib/banner.js";import{readFileSync as q}from"node:fs";import{fileURLToPath as z}from"node:url";import{dirname as K,join as B}from"node:path";import{setDefaultResultOrder as Q}from"node:dns";import{setDefaultAutoSelectFamilyAttemptTimeout as Z}from"node:net";Q("ipv4first"),Z(4e3);const oo=K(z(import.meta.url)),eo=JSON.parse(q(B(oo,"..","package.json"),"utf-8")).version,no=chalk.cyan(" ─────────────────────────────────────────────────────"),so=`\n${no}\n\n${X.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${eo}`)}\n\n${no}\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!==G){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===G);H(),process.exit(e??0)}}const ro=new o;if(ro.name("icoa").version(eo).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();W("high-contrast"===e.themeVariant?"high-contrast":"dark"),Y(),function(){const o=J();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(so);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 D(ro,s)}),e(ro),n(ro),s(ro),r(ro),t(ro),i(ro),l(ro),a(ro),m(ro),c(ro),g(ro),d(ro),p(ro),y(ro),h(ro),f(ro),u(ro),w(ro),b(ro),j(ro),$(ro),v(ro),T(ro),A(ro),I(ro),E(ro),C(ro),_(ro),x(ro),S(ro),k(ro),R(ro),L(ro),O(ro),U(ro),F(ro),N(ro),ro.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)))}ro.hook("preAction",()=>{!function(){if(!V())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()}()}),ro.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:"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}));
|
|
@@ -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}
|
package/dist/lib/tls-trust.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import t from"node:tls";import chalk from"chalk";const e=new Set(["UNABLE_TO_GET_ISSUER_CERT","UNABLE_TO_GET_ISSUER_CERT_LOCALLY","UNABLE_TO_VERIFY_LEAF_SIGNATURE","SELF_SIGNED_CERT_IN_CHAIN","DEPTH_ZERO_SELF_SIGNED_CERT","CERT_UNTRUSTED","CERT_CHAIN_TOO_LONG","CERT_SIGNATURE_FAILURE"]);export function transportCauseCode(t){let e=t;for(let t=0;t<5&&e;t++){const t=e.code;if("string"==typeof t&&t)return t;e=e.cause}return""}export function isCertTrustError(t){return e.has(transportCauseCode(t))}let o=!1;export function systemTrustActive(){return o}export function enableSystemTrust(){if(o)return!1;const e=t.getCACertificates,r=t.setDefaultCACertificates;if("function"!=typeof e||"function"!=typeof r)return!1;let s,
|
|
1
|
+
import t from"node:tls";import chalk from"chalk";const e=new Set(["UNABLE_TO_GET_ISSUER_CERT","UNABLE_TO_GET_ISSUER_CERT_LOCALLY","UNABLE_TO_VERIFY_LEAF_SIGNATURE","SELF_SIGNED_CERT_IN_CHAIN","DEPTH_ZERO_SELF_SIGNED_CERT","CERT_UNTRUSTED","CERT_CHAIN_TOO_LONG","CERT_SIGNATURE_FAILURE"]);export function transportCauseCode(t){let e=t;for(let t=0;t<5&&e;t++){const t=e.code;if("string"==typeof t&&t)return t;e=e.cause}return""}export function isCertTrustError(t){return e.has(transportCauseCode(t))}let o=!1;export function systemTrustActive(){return o}export function enableSystemTrust(){if(o)return!1;const e=t.getCACertificates,r=t.setDefaultCACertificates;if("function"!=typeof e||"function"!=typeof r)return!1;let s,i;try{s=e("system"),i=e("default")}catch{return!1}if(!Array.isArray(s)||0===s.length)return!1;try{r([...new Set([...i,...s])])}catch{return!1}return o=!0,console.log(),console.log(chalk.yellow(" ⚠ This network inspects HTTPS traffic (school / library / office firewall).")),console.log(chalk.gray(" Continuing with the certificates your operating system already trusts.")),console.log(chalk.gray(" 这个网络对 HTTPS 做了拦截,已改用系统证书库继续 —— 属正常现象,可以照常上课。")),console.log(),!0}export function transportAdvice(t){const o=transportCauseCode(t);if(e.has(o))return["This network re-signs HTTPS traffic and Node does not trust its certificate.","Fix: run NODE_OPTIONS=--use-system-ca icoa (needs Node 22.15+ — check with: node -v)","Or ask the network admin to exempt practice.icoa2026.au from SSL inspection."];if("CERT_HAS_EXPIRED"===o||"CERT_NOT_YET_VALID"===o)return["This computer's clock is wrong, so every HTTPS certificate looks invalid.","Fix: correct the system date/time, then try again."];if("ERR_TLS_CERT_ALTNAME_INVALID"===o)return["Something on this network is answering for practice.icoa2026.au with the wrong certificate.","Fix: try a phone hotspot, or ask the network admin about the web filter."];if("ENOTFOUND"===o||"EAI_AGAIN"===o)return["This network cannot look up practice.icoa2026.au (DNS is blocked or broken).","Fix: set DNS to 1.1.1.1 or 8.8.8.8, or use a phone hotspot."];if("ECONNREFUSED"===o||"ECONNRESET"===o||"ENETUNREACH"===o||o.includes("CONNECT_TIMEOUT"))return["The connection to practice.icoa2026.au was blocked before it reached us.","If your browser CAN open https://practice.icoa2026.au this network only allows browser traffic (a proxy).","Fix: ask the admin to allow practice.icoa2026.au on TCP 443, or use a phone hotspot."];if("ETIMEDOUT"===o||/timeout/i.test(o)||function(t,e){let o=t;for(let t=0;t<5&&o;t++){const t=o.message;if("string"==typeof t&&e.test(t))return!0;o=o.cause}return!1}(t,/timed? ?out/i)){const t=["Nothing answered in time. On a crowded or weak mobile hotspot this is usually just slowness:","retry once or twice; if a classmate is on the same WiFi and it works for them, it is not blocked.","A VPN or proxy app on this computer is the other usual cause: quit it fully, then retry.","Then try a phone hotspot — if that works, this WiFi is too slow or blocks the route (tell your coach)."];return(process.env.HTTPS_PROXY||process.env.https_proxy||process.env.HTTP_PROXY||process.env.http_proxy)&&t.unshift("This shell is set to use a web proxy (HTTPS_PROXY) which icoa cannot use — browsers can, so they still work."),t}return[]}
|