icoa-cli 2.19.574 β 2.19.576
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/battle.js +1 -1
- package/dist/commands/ctf4ai-demo.js +1 -1
- package/dist/commands/ctf4vla.js +1 -1
- package/dist/commands/duck.js +1 -0
- package/dist/commands/exam.js +1 -1
- package/dist/commands/learn.js +1 -1
- package/dist/index.js +1 -1
- package/dist/lib/commands.js +1 -1
- package/dist/lib/learn-render.js +1 -1
- package/dist/repl.js +1 -1
- package/package.json +1 -1
package/dist/repl.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createInterface as o}from"node:readline";import{spawn as e,execSync as t}from"node:child_process";import chalk from"chalk";import{appendExitLog as n}from"./lib/exit-log.js";import{dispatchable as l,helpRows as a,shortcutFor as s,subcommandsOf as r,surface as i}from"./lib/commands.js";import{distance as c}from"fastest-levenshtein";import{isConnected as g,getConfig as m,saveConfig as y}from"./lib/config.js";import{selectionSetupLine as d}from"./lib/python-setup.js";import{isExamSetupComplete as u}from"./lib/exam-setup.js";import{detectCaps as p}from"./lib/render-card.js";import{ensureLangCache as h}from"./lib/translations-fetcher.js";import{loadUiPack as f}from"./lib/i18n.js";import{isActivated as w,activateToken as b,isFreeCommand as k,isDeviceMatch as x,recordExit as v,recordResume as C,isFirstRunOrUpgrade as $,markVersionSeen as A}from"./lib/access.js";import{setReplMode as I}from"./lib/ui.js";import{returnToMainMenu as T,printMenuHint as S,menuHintInline as E,registerRealExit as j}from"./lib/menu-nav.js";import{setMainRl as O}from"./lib/main-rl.js";import{shellSplit as L}from"./lib/shell-split.js";import{isChatActive as N,handleChatMessage as D}from"./commands/ai4ctf.js";import{isMicroduckWord as P}from"./commands/microduck.js";import{renderToolMan as M}from"./lib/tool-man.js";import{isCtf4aiActive as _,handleCtf4aiMessage as F}from"./commands/ctf4ai-demo.js";import{isCtf4VlaActive as U,handleCtf4VlaMessage as R}from"./commands/ctf4vla.js";import{isDemo2Active as q}from"./commands/demo2.js";import{isSprintActive as W}from"./commands/sprint.js";import{isCardDeckActive as B}from"./lib/card-engine.js";import{hasAnySimHistory as Z,lastArmAt as Y,lastBundledAt as z,lastSimAt as X}from"./lib/sim-cooldown.js";import{getExamState as Q,getRealExamState as H,getDemoState as J,practicalChatCommand as V}from"./lib/exam-state.js";import{resolveResumePoint as G}from"./lib/resume.js";import{buildStatusLine as K}from"./lib/statusline.js";import{startBgTask as oo,startAsyncTask as eo,listBgTasks as to,getBgTask as no,drainCompleted as lo,killAllBgTasks as ao,runningCount as so}from"./lib/bgtasks.js";import{computeStart as ro,renderStart as io}from"./commands/challenge.js";import{addDraft as co,listDrafts as go,removeDraft as mo,clearDrafts as yo}from"./lib/drafts.js";import{resetTerminalTheme as uo}from"./lib/theme.js";import{ensureSandbox as po,runInSandbox as ho,isDockerAvailable as fo}from"./lib/sandbox.js";import{checkShellRisk as wo,logShellAudit as bo,getActiveCwd as ko}from"./lib/exam-sandbox.js";import{logCommand as xo}from"./lib/logger.js";import{startLogSync as vo,stopLogSync as Co}from"./lib/log-sync.js";import{installInputDynamics as $o,uninstallInputDynamics as Ao,stripTerminalMarkers as Io,rearmFocusMode as To}from"./lib/input-dynamics.js";import{startBroadcastPoll as So,stopBroadcastPoll as Eo,showBroadcast as jo,isCompetitionJoined as Oo,isMelCompetition as Lo,isLeaderAccount as No,isLeaderSession as Do,fetchPublicScoreboard as Po,isCommsActive as Mo}from"./lib/comms.js";import{enterMemoScreen as _o,enterJuryScreen as Fo}from"./commands/comms.js";import{existsSync as Uo,mkdirSync as Ro,readFileSync as qo,writeFileSync as Wo}from"node:fs";import{join as Bo}from"node:path";import{homedir as Zo}from"node:os";const Yo="# ICOA exam interactive startup β auto-loaded by PYTHONSTARTUP\nimport base64, struct, hashlib, re, json, os, sys, binascii\ntry: import requests\nexcept ImportError: pass\ntry: from Crypto.Cipher import AES\nexcept ImportError: pass\ntry: from Crypto.Util.Padding import pad, unpad\nexcept ImportError: pass\ntry: from pwn import xor, p32, u32, p64, u64\nexcept ImportError: pass\ntry: import bs4\nexcept ImportError: pass\ntry: import numpy as np\nexcept ImportError: pass\ntry: from PIL import Image\nexcept ImportError: pass\n",zo=Date.now();function Xo(){return Lo()?chalk.yellow("icoa 2026> "):H()?chalk.cyan("icoa exam> "):function(){const o=J();return!(!o||"demo-free"!==o.session?.examId)&&new Date(o.session.startedAt||0).getTime()>=zo}()?chalk.yellow("icoa demo> "):chalk.green("icoa> ")}const Qo=Bo(Zo(),"icoa-workspace"),Ho=new Set(["sudo","su","doas","pkexec","brew","apt","apt-get","yum","choco","npm","npx","pip","pip3","shutdown","reboot","halt","mkfs","fdisk","dd","iptables","ufw"]),Jo="__REPL_NO_EXIT__",Vo="2.5.1",Go=i();export function nearestCommand(o,e=2){const t=o.trim().toLowerCase();if(!t)return null;let n={word:"",dist:Number.POSITIVE_INFINITY};for(const o of Go){const e=c(t,o);e<n.dist&&(n={word:o,dist:e})}return n.dist>0&&n.dist<=e?n.word:null}const Ko=new Set(["answer","demo","demo-retry","help","list","mark","more-help","nations","next","prev","q","reset","result","review","setup","start","submit","token","unmark","status","time"]);function oe(o){const e=o.replace(/^\s+/,"");if(/^\/\S*$/.test(e)){const o=e.slice(1).toLowerCase();return[Go.filter(e=>e.startsWith(o)).map(o=>`/${o}`),e]}const t=e.split(/\s+/);if(t.length<=1){const o=(t[0]??"").toLowerCase();return[Go.filter(e=>e.startsWith(o)).slice(),o]}if(2===t.length){const o=r(t[0].toLowerCase());if(o){const e=t[1].toLowerCase();return[o.filter(o=>o.startsWith(e)).slice(),e]}}return[[],o]}async function ee(o){const e=G();if(!e)return null;const t=process.exit;process.exit=()=>{throw new Error(Jo)};try{await o.parseAsync(["node","icoa",...e.command])}catch(o){if(!(o instanceof Error&&o.message===Jo))throw o}finally{process.exit=t}return e}function te(){console.log(),console.log(` ${chalk.cyan.bold("π― ICOA 2026 Β· National Selection")}`),console.log(),console.log(" "+chalk.bold.cyan("learn ")+chalk.white("ACxxxxxxxx")+chalk.gray(" β ai4ctf-12 (AI as your CTF teammate)")),console.log(" "+chalk.bold.cyan("learn ")+chalk.white("CAxxxxxxxx")+chalk.gray(" β ctf4ai-12 (red-team software AI)")),console.log(" "+chalk.bold.cyan("learn ")+chalk.white("EAxxxxxxxx")+chalk.gray(" β ctf4eai-12 (red-team embodied AI)")),console.log(" "+chalk.bold.cyan("exam ")+chalk.white("<CC>xxxxxxxx")+chalk.gray(" β Paper A/B/C/D/E (country exam token)")),console.log(" "+chalk.bold.cyan("demo")+chalk.gray(" β free practice")),console.log(" "+chalk.bold.cyan("lang")+chalk.white(" es")+chalk.gray(" β switch language")),console.log(" "+chalk.gray("help Β· menu Β· quit"));try{console.log(),console.log(d(u(),"T0"===p().tier))}catch{}console.log()}export async function startRepl(e,a){process.env.ICOA_INSIDE_REPL="1";let s=!1;if(Lo()){const o=m().joinedAt,e=o=>new Intl.DateTimeFormat("en-CA",{timeZone:"Australia/Sydney",year:"numeric",month:"2-digit",day:"2-digit"}).format(o);o&&e(new Date(o))===e(new Date)||(y({ctfdUrl:"",token:"",sessionCookie:"",userId:null,userName:"",teamId:null,country:"",joinedAt:""}),s=!0)}const r=m(),i=g(),c=process.exit.bind(process);j(c);const d=w();if(r.language&&"en"!==r.language&&(await h(r.language,{silent:!0}),f(r.language)),r.demoCleanedForVersion!==Vo){try{const{existsSync:o,unlinkSync:e}=await import("node:fs"),{join:t}=await import("node:path"),{getIcoaDir:n}=await import("./lib/config.js"),l=t(n(),"demo-state.json");o(l)&&e(l)}catch{}y({demoCleanedForVersion:Vo})}const{select:u,confirm:p}=await import("@inquirer/prompts"),L=r.mode||"",J=""===L?"instant":"selection"===L?"learn":["instant","learn","olympiad"].includes(L)?L:"learn",To=[{name:` ${chalk.bold("β‘ Try ICOA in 30 seconds")} ${chalk.gray("β")} ${chalk.gray("watch Β· no token needed")}`,value:"instant"},{name:` ${chalk.bold("π§ Learn")} ${chalk.gray("β")} ${chalk.gray("team token Β· skill up")}`,value:"learn"},{name:` ${chalk.bold("π― National Selection")} ${chalk.gray("β")} ${chalk.gray("country exam token Β· aim for finals")}`,value:"selection"},{name:` ${chalk.bold("π International Olympiad")} ${chalk.gray("β")} ${chalk.gray("finals stage Β· Sydney 2026 Β· full sandbox")}`,value:"olympiad"},{name:` ${chalk.gray("βΉοΈ About ICOA")} ${chalk.gray("Β·")} ${chalk.gray("what this is Β· how to join")}`,value:"about"}];""===L&&(console.log(chalk.green(" π First time here? ")+chalk.white("Just press ")+chalk.bold.cyan("Enter")+chalk.white(" β youβll see ICOA in 30 seconds, no signup needed.")),console.log()),console.log(chalk.gray(" Type ")+chalk.bold.cyan("menu")+chalk.gray(" from anywhere to return here.")),console.log();let zo="";for(;!zo;){let o;const e=process.env.ICOA_TEST_BOOT_MODE;if(e&&["instant","learn","selection","olympiad"].includes(e))o=e;else try{o=await u({message:"Mode",choices:To,default:J||"instant"})}catch(o){throw o instanceof Error&&"ExitPromptError"===o.name&&(console.log(),console.log(chalk.gray(" Goodbye.")),process.exit(0)),o}if("about"!==o)zo=o;else{console.clear(),console.log(),console.log(chalk.cyan(" βββββββββββββββββββββββββββββββββββββββββββββββββββ")),console.log(chalk.bold.yellow(" ICOA")+chalk.white(" β AI-Native CLI OS for Cyber & AI Security")),console.log(chalk.gray(" Olympiad & Competition Β· K-12 to University")),console.log(chalk.cyan(" βββββββββββββββββββββββββββββββββββββββββββββββββββ")),console.log(),console.log(chalk.bold.white(" What Makes ICOA Different")),console.log(chalk.gray(" Β· AI-native AI teammate, AI adversary, AI translation")),console.log(chalk.gray(" Β· CLI OS Complete competition environment in terminal")),console.log(chalk.gray(" Β· 110 tools pwntools, z3, gdb, nmap, sleuthkit... pre-configured")),console.log(chalk.gray(" Β· Global scale 15,000+ concurrent exams Β· 20+ languages")),console.log(),console.log(chalk.bold.white(" Three Frontiers of AI Security")),console.log(` ${chalk.green.bold("AI4CTF")}${chalk.gray(" AI as teammate β 5 CTF disciplines, 5-hour endurance round")}`),console.log(` ${chalk.red.bold("CTF4AI")}${chalk.gray(" AI as target β the AI system itself is the objective")}`),console.log(` ${chalk.cyan.bold("CTF4EAI")}${chalk.gray(" Embodied-AI Arena β probe robot policies in live simulation")}`),console.log(),console.log(chalk.bold.white(" First Edition β Sydney 2026 ")+chalk.green.bold("β held")),console.log(chalk.gray(" Β· Jun 27 - Jul 2, 2026 Β· University of Technology Sydney")),console.log(chalk.gray(" Β· 65 competitors Β· 20 countries & regions (10 on-site, 10 remote)")),console.log(chalk.gray(" Β· 36 awards β 6 Gold Β· 11 Silver Β· 17 Bronze Β· 2 Honorable Mentions")),console.log(chalk.gray(" Β· Champion: Oleg Uteshev Β· Embodied-AI Arena Gold: Kingsley Lim (AU)")),console.log(chalk.gray(" Β· Founding Charter signed β ICOA is now a permanent institution")),console.log(),console.log(chalk.bold.white(" Next: ICOA 2027")+chalk.gray(" β 20 more countries already accredited")),console.log(),console.log(chalk.bold.white(" Organized by")+chalk.gray(" ASRA (Australia) Β· ICO Foundation Inc")),console.log(chalk.bold.white(" Contact ")+chalk.cyan(" australia@icoa2026.au Β· accreditation@icoa2026.au")),console.log(chalk.bold.white(" Website ")+chalk.cyan.underline(" https://icoa2026.au")+chalk.gray(" Β· press: ")+chalk.cyan.underline("https://icoa2026.au/press/")),console.log(chalk.cyan(" βββββββββββββββββββββββββββββββββββββββββββββββββββ")),console.log();try{const{input:o}=await import("@inquirer/prompts"),e=()=>o({message:chalk.gray("Press Enter to return..."),theme:{prefix:"",style:{message:o=>o}}}),t=Date.now();let n=await e();Date.now()-t<200&&(n=await e());const l=n.trim().toLowerCase();if("setup"===l||"config"===l||"/setup"===l){const{runSetupWizard:o}=await import("./commands/setup.js");await o(),await e()}}catch{}console.clear()}}if("olympiad"===zo&&"olympiad"!==J){console.log(),console.log(chalk.yellow(" This mode will download ~500MB of CTF tools and AI models."));let o=!0;try{o=await p({message:"Continue?",default:!0})}catch(e){if(!(e instanceof Error&&"ExitPromptError"===e.name))throw e;o=!1}o||(zo="selection",console.log(chalk.gray(" Switched to National Selection mode.")))}if(zo!==J&&y({mode:zo}),console.log(),"olympiad"===zo&&$(Vo)){A(Vo),console.log(chalk.gray(" Checking competition environment..."));const{execSync:o}=await import("node:child_process"),e=[{name:"pwntools",cmd:'python3 -c "import pwn"'},{name:"z3-solver",cmd:'python3 -c "import z3"'},{name:"numpy",cmd:'python3 -c "import numpy"'},{name:"requests",cmd:'python3 -c "import requests"'}];let t=0;for(const n of e)try{o(n.cmd,{stdio:"ignore"})}catch{t++}t>0?(console.log(chalk.yellow(` ${t} core competition libraries missing.`)),console.log(chalk.gray(" Run ")+chalk.white("env setup")+chalk.gray(" when you are ready to install them.")),console.log()):(console.log(chalk.green(" All core libraries ready.")),console.log())}if(a){const o=C();if(o){const e=Math.floor(o.awaySeconds/60),t=o.awaySeconds%60;console.log(chalk.yellow(` Session resumed. Away: ${e}m ${t}s | Total exits: ${o.exitCount}`)),console.log()}}if("selection"===zo)console.log(chalk.gray(" βββ exam hall Β· 90 min per paper once started Β· no pause βββ")),console.log(),te();else if("embodied"===zo)!function(){console.log(chalk.cyan.bold(" [π€ ctf4eai β Embodied AI Security]")),console.log(),console.log(chalk.bold.cyan(" CTF4EAI")+chalk.gray(" β ICOA 2026's ")+chalk.bold.white("Pioneer Round")),console.log(chalk.gray(" an independent parallel track alongside the scored main events: ")+chalk.green("AI4CTF")+chalk.gray(" (Day 1) and ")+chalk.red("CTF4AI")+chalk.gray(" (Day 2)")),console.log(),console.log(chalk.white(" Embodied AI is at its ImageNet moment.")),console.log(chalk.gray(" VLA models, MuJoCo physics, real robot arms.")),console.log(chalk.gray(" Real models, real physics, real attack surfaces.")),console.log(),console.log(chalk.gray(" βββββββββββββββββββββββββββββββββββββββββββββ"));const o=z()>0||X()>0,e=Y()>0,t=Z();o&&e?console.log(chalk.bold.yellow(" Next up: ")+chalk.bold.cyan("β’ demo2")+chalk.gray(" β ")+chalk.bold.cyan("β£ learn LEARNDEMO01")+chalk.gray(" (sim β Β· sim arm β)")):t?console.log(chalk.bold.yellow(" Next up: ")+(e?chalk.bold.cyan("β sim")+chalk.gray(" β ")+chalk.bold.cyan("β’ demo2"):chalk.bold.cyan("β‘ sim arm")+chalk.gray(" β ")+chalk.bold.cyan("β’ demo2"))+chalk.gray(" β ")+chalk.bold.cyan("β£ learn LEARNDEMO01")):console.log(chalk.bold.yellow(" First time? Try in order: ")+chalk.bold.cyan("β sim")+chalk.gray(" β ")+chalk.bold.cyan("β‘ sim arm")+chalk.gray(" β ")+chalk.bold.cyan("β’ demo2")+chalk.gray(" β ")+chalk.bold.cyan("β£ learn LEARNDEMO01")),console.log(chalk.gray(" βββββββββββββββββββββββββββββββββββββββββββββ")),console.log(chalk.bold.green(" sim")+chalk.gray(" ")+chalk.bold.cyan("β ")+chalk.gray(" ")+chalk.bold.yellow("β
INSTANT")+chalk.gray(" β 9-robot group dance, no wait, no setup")),console.log(chalk.bold.green(" sim arm")+chalk.gray(" ")+chalk.bold.cyan("β‘")+chalk.gray(" interactive 6-DOF arm sandbox β type joint values, watch")),console.log(chalk.bold.green(" demo2")+chalk.gray(" ")+chalk.bold.cyan("β’")+chalk.gray(" ~8 min interactive intro + live MuJoCo sim")),console.log(chalk.bold.green(" learn LEARNDEMO01")+chalk.gray(" ")+chalk.bold.cyan("β£")+chalk.gray(" free 11-card intro (paste this command as-is)")),console.log(chalk.bold.green(" learn ")+chalk.bold.yellow("EA")+chalk.gray(" + 8 chars full 96 / 360 curriculum (team-issued)")),console.log(chalk.bold.green(" exam ")+chalk.bold.yellow("PDxxxxxxxx")+chalk.gray(" Paper D (CTF4EAI) β national selection contestants")),console.log(chalk.gray(" βββββββββββββββββββββββββββββββββββββββββββββ")),console.log(),console.log(chalk.gray(" Three open tiers: ")+chalk.green("free 11")+chalk.gray(" Β· ")+chalk.yellow("registered 100")+chalk.gray(" Β· ")+chalk.bold.magenta("national team 480")+chalk.gray(" (PhD-ready)")),console.log(chalk.gray(" Country team contact: ")+chalk.cyan("australia@icoa2026.au")),console.log(),S(),console.log()}();else if("instant"===zo)console.log(chalk.cyan.bold(" [β‘ Try ICOA in 30 seconds β no token needed]")),console.log(),console.log(chalk.gray(" Three free tastes β just type the word and press Enter:")),console.log(),console.log(chalk.bold.green(" demo ")+chalk.gray(" Paper A/B/C taste β 10 MCQs, no timer ")+chalk.bold.cyan("π― selection-style")),console.log(chalk.bold.green(" demo2 ")+chalk.gray(" Embodied-AI mini-demo β robots & MuJoCo ")+chalk.bold.yellow("π€ hands-on")),console.log(chalk.bold.green(" kaggle")+chalk.gray(" ML practice β train a model, real board ")+chalk.bold.magenta("π data-science")),console.log(),console.log(chalk.gray(" Type ")+chalk.bold.cyan("demo")+chalk.gray(", ")+chalk.bold.cyan("demo2")+chalk.gray(" or ")+chalk.bold.cyan("kaggle")+chalk.gray(" to start Β· ")+chalk.bold.cyan("menu")+chalk.gray(" to go back Β· ")+chalk.bold.cyan("quit")+chalk.gray(" to exit")),console.log(),y({mode:"selection"}),zo="selection";else{if("learn"===zo){console.log(chalk.cyan.bold(" [π§ Learn]")),console.log();const o=await(async()=>{try{const o=await import("./lib/learn-state.js");return{sessions:o.listLearnSessions(),listMax:o.CONTINUE_LIST_MAX}}catch{return{sessions:[],listMax:5}}})(),t=o.sessions,l=o=>/^[A-Z]{2}[A-Z0-9]{8}$/i.test(o)?`${o.slice(0,2)}β’β’β’β’β’β’${o.slice(-2)}`:o,a=o=>{const e=new Date(o);if(Number.isNaN(e.getTime()))return"";const t=o=>new Date(o.getFullYear(),o.getMonth(),o.getDate()).getTime(),n=Math.round((t(new Date)-t(e))/864e5);return n<0?"":0===n?"today":1===n?"yesterday":n<30?`${n} days ago`:"a while back"},s=e=>{const n=e?t:t.slice(0,o.listMax),s=o=>Math.max(...n.map(e=>o(e).length)),r=s(o=>o.curriculumId),i=s(o=>`card ${o.currentCard}/${o.totalCards}`),c=s(o=>a(o.lastSeenAt));return n.forEach((o,e)=>{const t=o.token===o.curriculumId?"":` ${l(o.token)}`;console.log(chalk.green(` ${e+1} `)+chalk.bold.white(o.curriculumId.padEnd(r))+chalk.gray(` ${`card ${o.currentCard}/${o.totalCards}`.padEnd(i)} ${a(o.lastSeenAt).padEnd(c)}${t}`))}),n.length};if(1===t.length){const o=t[0],e=a(o.lastSeenAt);console.log(chalk.green(" βΈ Continue ")+chalk.bold.white(o.curriculumId)+chalk.gray(` Β· card ${o.currentCard}/${o.totalCards}${e?` Β· ${e}`:""} Β· ${l(o.token)}`)),console.log(chalk.gray(" type ")+chalk.bold.green("c")+chalk.gray(" or ")+chalk.bold.green("continue")+chalk.gray(" to resume Β· Enter to go back")),console.log()}else if(t.length>1){console.log(chalk.green(" βΈ Continue"));const o=s(!1);t.length>o&&console.log(chalk.gray(` +${t.length-o} more β type `)+chalk.bold.green("c all")+chalk.gray(" to list them")),console.log(chalk.gray(" type ")+chalk.bold.green("c")+chalk.gray(" to resume 1 Β· ")+chalk.bold.green("c 2")+chalk.gray(" to switch Β· Enter to go back")),console.log()}{const{doorStoryLines:o,doorWelcomeLines:e,fetchProfilesForLocalTokens:n}=await import("./lib/learn-door.js"),{learnW:l}=await import("./lib/learn-render.js");let a=null;if(t.find(o=>/^[A-Z]{2}[A-Z0-9]{8}$/i.test(o.token)&&!/DEMO01$/i.test(o.token))){const s=await n(t.map(o=>o.token)),r=s[0]??null,i=new Set(s.flatMap(o=>o.tokens.filter(o=>o.credits?.completed).map(o=>o.curriculum_id))).size;a=r?o(r,l(),i):e(l(),!0)}else a=e(l(),!1);for(const o of a)console.log(o);try{const{pythonDoorLine:o}=await import("./lib/python-setup.js"),{detectCaps:e}=await import("./lib/render-card.js"),t=(m().language||"en").toLowerCase().startsWith("zh");console.log(o(t,"T0"===e().tier))}catch{}console.log()}try{const{input:o}=await import("@inquirer/prompts"),{resolveLearnInput:n}=await import("./lib/learn-input.js");console.log(chalk.gray(" Enter a token (or just press Enter to go back).")),console.log();const l=async()=>{try{await o({message:chalk.bold.yellow("Press Enter to return to the menu"),theme:{prefix:"",style:{message:o=>o}}})}catch{}},a=3;for(let r=1;r<=a;r++){const i=await o({message:chalk.bold.cyan("icoa learn>"),theme:{prefix:"",style:{message:o=>o}}}),c=i.trim().toLowerCase();if("ai4ioai"===c||"/ai4ioai"===c){const{runAi4ioaiStandalone:o}=await import("./commands/ai4ioai.js");return await o(),await l(),y({mode:"selection"}),void T()}if(P(i)){const{runMicroduck:o}=await import("./commands/microduck.js");return await o(),await l(),y({mode:"selection"}),void T()}if(["pandahelpme31","/pandahelpme31","panda help me 31","pandahelpme"].includes(c)){const{runSprint:o}=await import("./commands/sprint.js");return await o(),y({mode:"selection"}),void T()}if("wm"===c||"/wm"===c||c.startsWith("wm ")){const{runWm:o}=await import("./commands/wm.js");return await o(i.trim().split(/\s+/).slice(1).join(" ")||void 0),y({mode:"selection"}),void T()}if("ioailab"===c||"/ioailab"===c){const{runIoailabStandalone:o}=await import("./commands/ioailab.js");return await o(),await l(),y({mode:"selection"}),void T()}if("me"===c||"/me"===c||"profile"===c||"/profile"===c){const o=t.find(o=>/^[A-Z]{2}[A-Z0-9]{8}$/i.test(o.token)&&!/DEMO01$/i.test(o.token));if(o){const{fetchLearnProfile:e,renderLearnProfile:t}=await import("./lib/learn-profile.js"),{learnW:n}=await import("./lib/learn-render.js");console.log(chalk.gray(` Loading your profile (${o.token.slice(0,2)}β’β’β’β’β’β’${o.token.slice(-2)})β¦`));const l=await e(o.token);"ok"===l.kind?t(l.profile,!1,n(),"prompt"):"offline"===l.kind?console.log(chalk.yellow(" Cannot reach the learn server β try me again online.")):console.log(chalk.yellow(` ${"demo"===l.kind?"No profile for a demo token":l.message}`)),console.log()}else console.log(),console.log(chalk.yellow(" No profile yet β open a course with your token first, then type me.")),console.log();r--;continue}const g=c.match(/^\/?python(?:3)?(?:\s+(setup|install|status))?$/);if(g){const{runSetup:o,printStatus:e}=await import("./commands/python.js");"setup"===g[1]||"install"===g[1]?await o():e(),r--;continue}const m=c.match(/^\/?m[ou]joco(?:\s+(setup|install|status))?$/);if(m){const{runMujocoSetup:o,printMujocoStatus:e}=await import("./commands/mujoco.js");"setup"===m[1]||"install"===m[1]?await o():e(),r--;continue}const d=c.match(/^\/?(certificate|certificates|cert)(?:\s+(\S+))?$/);if(d){const{certificateLines:e,dropProfileCache:n}=await import("./lib/learn-door.js"),{certifiable:l,certificateIntroLines:a,sameName:s,issueCertificate:i,announceCertificate:c}=await import("./lib/learn-certificate.js"),{fetchProfilesForLocalTokens:g}=await import("./lib/learn-door.js"),m=await g(t.map(o=>o.token)),y=m[0]??null,u=new Set,p=m.flatMap(o=>l(o)).filter(o=>!u.has(o.curriculum_id)&&u.add(o.curriculum_id)),h=(d[2]??"").toLowerCase();console.log();const f=h?p.find(o=>o.curriculum_id.toLowerCase()===h||o.curriculum_id.toLowerCase().startsWith(h)):1===p.length?p[0]:void 0;if(0===p.length||!f&&!h){for(const o of e(y,!1))console.log(o);p.length>1&&console.log(chalk.gray(" type ")+chalk.bold.green("certificate <track>")+chalk.gray(" to issue one.")),console.log(),r--;continue}if(!f){console.log(chalk.yellow(` No finished track matches "${h}". `)+chalk.gray("Finished: "+p.map(o=>o.curriculum_id).join(", "))),console.log(),r--;continue}for(const o of a(f,!1))console.log(o);console.log();const w=async e=>(await o({message:chalk.bold.cyan(e),theme:{prefix:"",style:{message:o=>o}}})).trim(),b=await w("Name on the certificate:");if(!b){console.log(chalk.gray(" Cancelled β nothing issued.")),console.log(),r--;continue}if(!s(b,await w("Type it once more:"))){console.log(chalk.yellow(" The two names differ β nothing issued. Type certificate to try again.")),console.log(),r--;continue}console.log(chalk.gray(" Issuingβ¦ (the name is sent once, never stored)")),c(await i(f.token,f.curriculum_id,b),!1),n(),r--;continue}const u=c.match(/^\/?(story|credits)(?:\s+(\S+))?$/);if(u){const{fetchLearnProfile:o}=await import("./lib/learn-profile.js"),{buildCreditLines:e,rollCredits:n,storyListLines:l}=await import("./lib/learn-credits.js"),{learnW:a}=await import("./lib/learn-render.js"),s=t.find(o=>/^[A-Z]{2}[A-Z0-9]{8}$/i.test(o.token)&&!/DEMO01$/i.test(o.token));if(console.log(),s){const r=await o(s.token,"credits"===u[1]?"credits":"story");if("ok"!==r.kind)console.log(chalk.yellow(" Cannot reach the learn server β try story again online."));else{const o=(u[2]??"").toLowerCase(),s=r.profile;let i;if(o){const e=Number(o);i=Number.isInteger(e)&&e>=1&&e<=s.tokens.length?s.tokens[e-1]:s.tokens.find(e=>e.curriculum_id.toLowerCase()===o||e.curriculum_id.toLowerCase().startsWith(o))}else"credits"===u[1]&&(i=s.tokens.find(o=>o.credits?.completed));if(i){if(await n(e(i,s,i.curriculum_id,{},!1,a(),!1),()=>!1,180),i.credits?.completed&&!i.credits.credits_rolled_at){const{postCreditsRolled:o}=await import("./lib/learn-profile.js");o(i.token,i.curriculum_id)}}else{o&&console.log(chalk.yellow(` No story for "${o}".`));for(const o of l(s,!1))console.log(o);const e=new Set(s.tokens.map(o=>o.token.toUpperCase())),n=t.filter(o=>/^[A-Z]{2}[A-Z0-9]{8}$/i.test(o.token)&&!/DEMO01$/i.test(o.token)&&!e.has(o.token.toUpperCase()));n.length>0&&console.log(chalk.gray(` +${n.length} more course${1===n.length?"":"s"} on this computer not linked yet β open one and type `)+chalk.bold.green("link")+chalk.gray(" to join them."))}}}else console.log(chalk.yellow(" No story yet β open a course with your token first."));console.log(),r--;continue}const{FOCUS_LOG_RE:p,fetchFocusLog:h,renderFocusLog:f}=await import("./lib/learn-focus-log.js");if(p.test(c)){const o=t.find(o=>/^[A-Z]{2}[A-Z0-9]{8}$/i.test(o.token)&&!/DEMO01$/i.test(o.token));if(console.log(),o){const{detectCaps:e}=await import("./lib/render-card.js"),t=await h(o.token);if("ok"===t.kind)for(const o of f(t.log,!1,"T0"===e().tier,"Enter to go back"))console.log(o);else console.log(chalk.yellow("offline"===t.kind?" Offline β the focus log lives on the server; try again when connected.":"demo"===t.kind?" Demo tokens are shared β no focus log. Use your own token.":` Could not load the focus log: ${t.message}`));console.log()}else console.log(chalk.yellow(" No focus log yet β open a course with your token first, then type focus log.")),console.log();r--;continue}const w=c.match(/^\/?(focus|timer)(?:\s+(.*))?$/);if(w){const{FOCUS_MAX:o,FOCUS_MIN:e,FOCUS_STEP:t,getStudyTimer:n,parseFocusMinutes:l}=await import("./lib/learn-study-timer.js"),a=n(),s=(w[2]??"").trim();if(console.log(),a.showPending());else if("off"===s||"stop"===s||"end"===s||"cancel"===s)a.stop()?(await new Promise(o=>setTimeout(o,300)),a.showPending()):console.log(chalk.gray(" No focus session running. Start one: ")+chalk.bold.green("focus 30"));else if(a.active)console.log(chalk.yellow(" β± ")+chalk.white(`focus running Β· ${a.remainingMin()} min left`)+chalk.gray(" Β· paste a token and keep going, or ")+chalk.bold.green("focus off"));else if(""===s||"?"===s||"help"===s)console.log(chalk.bold.white(" β± Focus session")),console.log(chalk.gray(` How long? (${e}β${o}, steps of ${t}) e.g. `)+chalk.bold.green("focus 30")),console.log(chalk.gray(" Start it here, then open any course β every course you visit counts."));else{const n=l(s);if(n){if("ok"!==n.note){const l="min"===n.note?`min is ${e}`:"max"===n.note?`max is ${o}`:`rounded to the nearest ${t}`;console.log(chalk.gray(` you typed ${s} β ${l}, using ${n.min}`))}a.start(n.min),console.log(chalk.yellow(" β± ")+chalk.bold.white(`Focus ${n.min} min β go`)+chalk.gray(" Β· now paste your token (any course counts) Β· soft reminder every 10 min Β· end early: ")+chalk.bold.green("focus off"))}else console.log(chalk.yellow(` Didn't understand "${s}". `)+chalk.gray("Type minutes, e.g. ")+chalk.bold.green("focus 30"))}console.log(),r--;continue}if(/^(doctor|\/doctor)$/i.test(i.trim())){const{runDoctor:o}=await import("./commands/doctor.js");await o(),console.log(),console.log(chalk.gray(" Paste your token to try again, or press Enter to go back.")),console.log(),r--;continue}let b=n(i);if("back"===b.kind)break;if("continue"===b.kind){if(0===t.length){if(console.log(),console.log(chalk.yellow(" Nothing to continue β no previous session on this computer.")),console.log(chalk.gray(" Paste your cohort token to start.")),console.log(),r===a){await l();break}continue}const{which:o}=b;let e=t[0];if("all"===o){console.log(),s(!0),console.log(),r-=1;continue}if("number"==typeof o){if(o<1||o>t.length){if(console.log(),console.log(chalk.yellow(` You have ${t.length} course${t.length>1?"s":""} in progress β pick 1${t.length>1?`-${t.length}`:""}, or type part of its name.`)),console.log(),r===a){await l();break}continue}e=t[o-1]}else if("string"==typeof o){const n=t.filter(e=>e.curriculumId.toLowerCase().includes(o)||e.token.toLowerCase().includes(o));if(1!==n.length){if(console.log(),console.log(chalk.yellow(0===n.length?` No course in progress matches "${o}".`:` "${o}" matches ${n.length} of your courses β be more specific, or use its number.`)),console.log(),s(!0),console.log(),r===a){await l();break}continue}e=n[0]}b={kind:"token",token:e.token}}if("ambiguous"===b.kind||"unknown"===b.kind){if(console.log(),console.log(chalk.yellow(` ${b.hint}`)),console.log(),r===a){console.log(chalk.gray(` That was attempt ${a} of ${a} β going back to the menu.`)),console.log(chalk.gray(" Your token comes from your country team leader.")),console.log(),await l();break}continue}if(b.from){const{loadCurriculumById:o}=await import("./lib/learn-curricula.js");if(!await o(b.token,b.token)){if(console.log(),console.log(chalk.yellow(` "${b.from}" is not a token.`)),console.log(chalk.gray(" Paste the token your team leader gave you (2 letters + 8 characters).")),console.log(),r===a){await l();break}continue}}if(!/^[A-Z0-9]+DEMO01$/i.test(b.token)&&/^[A-Z]{2}[A-Z0-9]{8}$/i.test(b.token)){console.log(),console.log(chalk.gray(" Checking tokenβ¦"));const{validateEAToken:o}=await import("./lib/learn-curricula.js");let e=await o(b.token);if(!e.ok){const{normalizeTokenBody:t}=await import("./lib/token-format.js"),n=t(b.token);if(n!==b.token.trim().toUpperCase()){const t=await o(n);t.ok&&(console.log(chalk.yellow(` Corrected look-alike characters: ${b.token} β ${n}`)),e=t,b={...b,token:n})}}if(!e.ok){if(console.log(),console.log(chalk.red(` β Token check failed: ${e.message||"validation failed"}`)+(e.code?chalk.gray(` [${e.code}]`):"")),"device_bound"===e.code)console.log(chalk.gray(" This learn token is bound to the first computer it was used on,")),console.log(chalk.gray(" and this is a different computer. Ask the coordinator who issued")),console.log(chalk.gray(" it to move it to this device, then try again."));else if("expired"===e.code)console.log(chalk.gray(" This learn token has expired β ask your coordinator for a new one."));else if("network"===e.code){console.log(chalk.yellow(" Your token was not checked β this computer could not reach the ICOA server.")),console.log(chalk.gray(" (Your browser opening Google or practice.icoa2026.au does not count: icoa")),console.log(chalk.gray(" connects on its own, without the browser, and can be blocked separately.)")),console.log();for(const o of e.advice??[])console.log(chalk.gray(` ${o}`));(e.advice?.length??0)>0&&console.log(),console.log(chalk.gray(" βΈ Type ")+chalk.cyan("doctor")+chalk.gray(" right here β it names the exact fault and the fix.")),console.log(chalk.gray(" If it does not, send its output to your coordinator."))}else console.log(chalk.gray(" Possible causes:")),console.log(chalk.gray(" Β· Typo in token (check 0/O, 1/I/L, V/U)")),console.log(chalk.gray(" Β· Token expired or revoked"));if(console.log(),r<a){console.log(chalk.gray(" Try again β or press Enter to go back.")),console.log();continue}await l();break}}console.log(),console.log(chalk.gray(" Opening ")+chalk.bold.cyan("learn")+chalk.gray(`: ${b.token}`)),console.log(),y({mode:"selection"}),process.env.ICOA_LEARN_EMBEDDED="1";const{setLearnSessionStarted:k}=await import("./lib/learn-outcome.js");k(!1);try{await e.parseAsync(["node","icoa","learn",b.token])}catch(o){console.log(),console.log(chalk.red(` β learn failed to start: ${o instanceof Error?o.message:String(o)}`)),console.log()}finally{delete process.env.ICOA_LEARN_EMBEDDED}await l();break}}catch(o){n("learn-token-prompt-cancel",o instanceof Error?`${o.name}: ${o.message}`:String(o))}return y({mode:"selection"}),void T()}"organizer"===zo?(console.log(chalk.yellow.bold(" [National/Regional Partner]")),console.log(),console.log(chalk.bold.white(" βββ βββββββ βββββββ ββββββ")),console.log(chalk.bold.white(" ββββββββββββββββββββββββββββ")),console.log(chalk.bold.white(" ββββββ βββ βββββββββββ")),console.log(chalk.bold.white(" ββββββ βββ βββββββββββ")),console.log(chalk.bold.white(" βββββββββββββββββββββββ βββ")),console.log(chalk.bold.white(" βββ βββββββ βββββββ βββ βββ")),console.log(),console.log(chalk.yellow(" International Cyber Olympiad in AI 2026")),console.log(chalk.bold.magenta(" The World's First AI-Native CLI Operating System")),console.log(chalk.bold.magenta(" for Cybersecurity & AI Security Competition")),console.log(chalk.bold.magenta(" and Olympiad for K-12")),console.log(chalk.gray(" Sydney, Australia Β· Jun 27 - Jul 2, 2026")),console.log(),console.log(chalk.white(" Vision")),console.log(chalk.gray(" Building a global pipeline for youth cyber & AI")),console.log(chalk.gray(" security talent through education and competition.")),console.log(),console.log(chalk.white(" Capacity")),console.log(chalk.gray(" 15,000+ concurrent online examinations")),console.log(chalk.gray(" National selection, training, and education support")),console.log(),console.log(chalk.white(" Olympic Spirit")),console.log(chalk.gray(" Excellence Β· Friendship Β· Respect")),console.log(),console.log(chalk.gray(" βββββββββββββββββββββββββββββββββββββββββββββ")),console.log(chalk.white(" New country accreditation & support:")),console.log(chalk.cyan(" australia@icoa2026.au")),console.log(chalk.cyan(" accreditation@icoa2026.au")),console.log(chalk.gray(" βββββββββββββββββββββββββββββββββββββββββββββ")),console.log(),i?(console.log(chalk.green(` Logged in as ${r.userName}`)),console.log(chalk.white(" exam list")+chalk.gray(" Manage exams")),console.log(chalk.white(" logout")+chalk.gray(" Disconnect"))):console.log(chalk.white(" join <url>")+chalk.gray(" Connect to manage exams")),console.log(),S(),console.log()):(console.log(` ${chalk.cyan.bold("π ICOA 2026 Β· International Olympiad")}`),console.log(),d&&!x()?(console.log(chalk.red(" Token was activated on a different device.")),console.log(chalk.gray(" Contact organizer for assistance.")),console.log()):i?(console.log(chalk.green.bold(` Welcome back, ${r.userName}!`)),console.log(chalk.gray(` Connected to ${r.ctfdUrl}`)),console.log(chalk.gray(" Not you? Type ")+chalk.cyan("logout")+chalk.gray(" to switch accounts")),console.log(),console.log(chalk.gray(" βββββββββββββββββββββββββββββββββββββββββββββ")),console.log(chalk.white(" Ready to compete? Start here:")),console.log(),console.log(chalk.bold.cyan(" challenges")+chalk.gray(" Browse challenges by category")),console.log(chalk.white(" status")+chalk.gray(" Your score & timer")),console.log(chalk.white(" scoreboard")+chalk.gray(" Live rankings")),console.log(chalk.white(" memo")+chalk.gray(" Report an issue to organizers (one-way)")),console.log(),console.log(chalk.gray(" Tool environment:")),console.log(chalk.white(" env")+chalk.gray(" See which of the 110 CTF tools are installed")),console.log(chalk.white(" env setup")+chalk.gray(" Install anything missing (~5 min, one-time)")),console.log(chalk.bold.yellow(" β
")+chalk.bold.cyan("man <tool>")+chalk.gray(" How to USE a tool (steghide, nmapβ¦) Β· ")+chalk.cyan("man tools")+chalk.gray(" = list")),console.log(chalk.gray(" βββββββββββββββββββββββββββββββββββββββββββββ")),console.log(chalk.gray(" Tip: ")+chalk.cyan("help")+chalk.gray(" Β· ")+E()+chalk.gray(" Β· ")+chalk.cyan("Ctrl+C")+chalk.gray(" pauses Β· ")+chalk.cyan("quit")+chalk.gray(" closes")),console.log()):d?(Uo(Qo)||Ro(Qo,{recursive:!0}),console.log(chalk.green.bold(" Welcome, competitor!")),console.log(chalk.gray(` Workspace: ${Qo}`)),console.log(),console.log(chalk.gray(" βββββββββββββββββββββββββββββββββββββββββββββ")),console.log(chalk.white(" Get started:")),console.log(),console.log(chalk.white(" Step 1 ")+chalk.bold.cyan("join <url>")+chalk.gray(" Connect to competition server")),console.log(chalk.white(" Step 2 ")+chalk.bold.cyan("challenges")+chalk.gray(" Browse & solve challenges")),console.log(chalk.white(" Step 3 ")+chalk.bold.cyan("ai4ctf")+chalk.gray(" Ask AI when stuck")),console.log(),console.log(chalk.gray(" Before Step 1 β make sure your tools are ready:")),console.log(chalk.white(" env")+chalk.gray(" See which of the 110 CTF tools are installed")),console.log(chalk.white(" env setup")+chalk.gray(" Install anything missing (~5 min, one-time)")),console.log(chalk.bold.yellow(" β
")+chalk.bold.cyan("man <tool>")+chalk.gray(" How to USE a tool (steghide, nmapβ¦) Β· ")+chalk.cyan("man tools")+chalk.gray(" = list")),console.log(),console.log(chalk.gray(" Also: ")+chalk.white("help")+chalk.gray(" all commands")),console.log(chalk.gray(" βββββββββββββββββββββββββββββββββββββββββββββ")),console.log(chalk.gray(" Tip: ")+chalk.cyan("Ctrl+C")+chalk.gray(" pauses Β· ")+E()+chalk.gray(" Β· ")+chalk.cyan("quit")+chalk.gray(" closes CLI")),console.log()):(console.log(chalk.bold.yellow(" π You reached the finals tier.")),console.log(chalk.gray(" Full sandbox Β· 110 CTF tools Β· Sydney 2026 Β· this is where finalists compete.")),console.log(),console.log(chalk.gray(" βββββββββββββββββββββββββββββββββββββββββββββ")),console.log(chalk.white(" To begin, activate your competition token:")),console.log(),console.log(chalk.bold.cyan(" activate <token>")),console.log(),console.log(chalk.gray(" While waiting, explore:")),console.log(chalk.white(" ref linux")+chalk.gray(" Quick reference for Linux")),console.log(chalk.white(" ref web")+chalk.gray(" Quick reference for Web")),console.log(chalk.white(" env")+chalk.gray(" See which of the 110 CTF tools are installed")),console.log(chalk.white(" env setup")+chalk.gray(" Install anything missing (~5 min, one-time)")),console.log(chalk.white(" help")+chalk.gray(" All available commands")),console.log(chalk.gray(" βββββββββββββββββββββββββββββββββββββββββββββ")),console.log(chalk.gray(" Tip: ")+chalk.cyan("Ctrl+C")+chalk.gray(" pauses Β· ")+E()+chalk.gray(" Β· ")+chalk.cyan("quit")+chalk.gray(" closes CLI")),console.log()))}const ae=o=>{o.exitOverride(),o.configureOutput({writeErr:o=>{const e=o.replace(/^error:\s*/i,"").trim();e&&console.log(chalk.yellow(` ${e}`))},writeOut:o=>{console.log(o)}});for(const e of o.commands)ae(e)};ae(e);const se=o({input:process.stdin,output:process.stdout,prompt:Xo(),terminal:!0,completer:oe});O(se),$o(!1!==m().bracketedPaste);let re=!1;if(I(!0),vo(),s&&(console.log(),console.log(chalk.yellow(" β± A new competition day has started (Sydney time).")),console.log(chalk.gray(" For fairness, yesterdayβs sign-in has been cleared. Type ")+chalk.cyan("join <url>")+chalk.gray(" to sign in with your account.")),console.log()),Lo()){const o=m().userName||"this account";console.log(),console.log(chalk.yellow(" β This machine is signed in as ")+chalk.bold.white(o)+chalk.yellow(".")),console.log(chalk.gray(" Press ")+chalk.cyan("Enter")+chalk.gray(` to continue as ${o}, or type `)+chalk.cyan("logout")+chalk.gray(" to switch accounts.")),"logout"===(await new Promise(o=>{se.question(chalk.white(" > "),e=>o(e.trim()))})).toLowerCase()&&(y({ctfdUrl:"",token:"",sessionCookie:"",userId:null,userName:"",teamId:null,country:""}),console.log(),console.log(chalk.green(" β Logged out. ")+chalk.gray("Run ")+chalk.cyan("join <url>")+chalk.gray(" to sign in with your own account."))),console.log()}Oo()&&So(()=>se.prompt());let ie=null;const ce=se.prompt.bind(se);se.prompt=o=>{if(!(N()||_()||U()||q()||B()||Mo()||W()||(se.setPrompt(Xo()),o)))try{for(const o of lo()){const e="done"===o.status,t=o.cmd.length>40?`${o.cmd.slice(0,37)}β¦`:o.cmd,n=o.render?"":chalk.gray(" (")+chalk.white(t)+chalk.gray(") β ")+chalk.cyan(`tasks ${o.id}`);if(console.log((e?chalk.green(" β"):chalk.red(" β"))+chalk.white(` background task #${o.id} ${o.status}`)+n),o.render)try{o.render()}catch{}}const o=K();o&&o!==ie?(console.log(o),ie=o):o||(ie=null)}catch{}ce(o)};const ge=G();ge&&(console.log(chalk.cyan(" β» Continue where you left off: ")+chalk.white(ge.label)+(ge.urgent?chalk.yellow(" (exam timer running)"):"")),console.log(chalk.gray(" type ")+chalk.cyan("resume")+chalk.gray(" to jump back in.")),console.log()),se.prompt(),se.on("line",async o=>{if(re)return;let n=Io(o.trim());if(!n)return se.setPrompt(N()?chalk.magenta("icoa ai4ctf> "):Xo()),void se.prompt();if(/^icoa\s+\S/i.test(n)&&(n=n.replace(/^icoa\s+/i,"")),n.startsWith("/")&&!n.startsWith("//")){const o=n.slice(1).split(/\s+/)[0].toLowerCase(),t=n.slice(1+o.length).trim();if("ai"===o)return re=!0,await async function(o,e){if(N())return void(o?await D(o):console.log(chalk.gray(" You are already in the AI chat β just type your message.")));if(_())return void(o?await F(o):console.log(chalk.gray(" You are already in the CTF4AI target chat β just type your message.")));if(U())return void(o?await R(o):console.log(chalk.gray(" You are already in the Embodied-AI chat β just type your message.")));xo(o?`/ai ${o}`:"/ai");const t=process.exit;process.exit=()=>{throw new Error(Jo)};try{await e.parseAsync(["node","icoa","ai4ctf"])}catch(o){if(!(o instanceof Error&&o.message===Jo))throw o}finally{process.exit=t}o&&N()&&await D(o)}(t,e),re=!1,se.setPrompt(N()?chalk.magenta("icoa ai4ctf> "):Xo()),void se.prompt();!(N()||_()||U()||q()||B()||Mo())&&Go.includes(o)&&(n=n.slice(1))}if("resume"===n.toLowerCase()){const o=G();return o?(xo(`resume β ${o.command.join(" ")}`),re=!0,await ee(e),re=!1,se.setPrompt(N()?chalk.magenta("icoa ai4ctf> "):Xo()),void se.prompt()):(console.log(),console.log(chalk.gray(" Nothing to resume yet β start with ")+chalk.cyan("learn")+chalk.gray(" (curriculum) or ")+chalk.cyan("demo")+chalk.gray(" (taste).")),console.log(),void se.prompt())}const a=N()||_()||U()||q()||B();if(!a&&("bg"===n.toLowerCase()||/^bg\s/i.test(n))){const o=n.replace(/^bg\s*/i,"").trim();if(!o)return console.log(),console.log(chalk.gray(" Usage: ")+chalk.cyan("bg <command>")+chalk.gray(" β run a non-interactive shell command in the background.")),console.log(chalk.gray(" e.g. ")+chalk.cyan("bg nmap -p- 10.0.0.5")+chalk.gray(" Β· view: ")+chalk.cyan("tasks")),console.log(),void se.prompt();const e=ko(),t=wo(o);bo({cwd:e,input:`bg ${o}`,riskFlags:t}),t.length>0&&H()&&console.log(chalk.yellow(` β Action flagged: ${t.join(", ")} β logged.`));const l=oo(o,e);return console.log(),console.log(chalk.cyan(` βΈ background task #${l.id} started`)+chalk.gray(` (${so()} running)`)),console.log(chalk.gray(" ")+chalk.white(o)),console.log(chalk.gray(" view: ")+chalk.cyan("tasks")+chalk.gray(" Β· output: ")+chalk.cyan(`tasks ${l.id}`)),console.log(),void se.prompt()}if(!a&&("tasks"===n.toLowerCase()||/^tasks\s/i.test(n))){const o=n.replace(/^tasks\s*/i,"").trim(),e=to();if(console.log(),o){const e=no(Number(o));if(!e||Number.isNaN(Number(o)))console.log(chalk.yellow(` No background task #${o}.`)+chalk.gray(" Type ")+chalk.cyan("tasks")+chalk.gray(" to list them."));else{const o="running"===e.status?chalk.yellow:"done"===e.status?chalk.green:chalk.red;console.log(o(` #${e.id} [${e.status}]`)+chalk.white(` ${e.cmd}`)+(null!==e.exitCode?chalk.gray(` (exit ${e.exitCode})`):"")),console.log(chalk.gray(" βββββββββββββββββββββββββββββββββββββββββββββ"));const t=e.output.trim();if(t)for(const o of t.split("\n"))console.log(chalk.gray(" ")+chalk.white(o));else console.log(chalk.gray(" (no output yet)"))}}else if(0===e.length)console.log(chalk.gray(" No background tasks. Start one with ")+chalk.cyan("bg <command>")+chalk.gray("."));else{console.log(chalk.bold.white(" Background tasks"));for(const o of e){const e="running"===o.status?chalk.yellow("β"):"done"===o.status?chalk.green("β"):chalk.red("β"),t=Math.round(((o.endedAt??Date.now())-o.startedAt)/1e3),n=(o.endedAt?`${t}s`:`${t}sβ¦`).padStart(5),l=o.cmd.length>48?`${o.cmd.slice(0,45)}β¦`:o.cmd;console.log(` ${e} `+chalk.white(`#${o.id}`)+chalk.gray(` ${n} `)+chalk.white(l))}console.log(chalk.gray(" output: ")+chalk.cyan("tasks <id>"))}return console.log(),void se.prompt()}if(!a&&/&\s*$/.test(n)&&/^challenge\s+start\s+/i.test(n)){const o=n.replace(/\s*&\s*$/,"").trim().replace(/^challenge\s+start\s+/i,"").trim().split(/\s+/),e=o.some(o=>"-n"===o||"--new"===o),t=o.find(o=>"-n"!==o&&"--new"!==o);if(!t)return console.log(),console.log(chalk.gray(" Usage: ")+chalk.cyan("challenge start <id> &")),console.log(),void se.prompt();if(!g())return console.log(),console.log(chalk.red(" Not connected. ")+chalk.gray("Run ")+chalk.cyan("join <url>")+chalk.gray(" first.")),console.log(),void se.prompt();xo(`challenge start ${t}${e?" --new":""} & (background)`);const l=eo(`challenge start ${t}`,()=>ro(t,e),o=>io(t,o));return console.log(),console.log(chalk.cyan(` βΈ background task #${l.id}: `)+chalk.white(`starting ${t}`)+chalk.gray(" β you can keep working; the connection info appears here when it is ready.")),console.log(),void se.prompt()}if(!a&&n.startsWith("#")){const o=n.slice(1).trim();if(!o)return console.log(),console.log(chalk.gray(" Usage: ")+chalk.cyan("#<candidate answer>")+chalk.gray(" β stage a flag/answer WITHOUT submitting it. Review with ")+chalk.cyan("drafts")+chalk.gray(".")),console.log(),void se.prompt();const e=Q(),t=e?.session?.examId??null,l=e?e._lastQ||1:null,a=co(o,t,l);return xo(`draft #${a.id} (not submitted)`),console.log(),console.log(chalk.green(` β draft #${a.id} saved`)+(l?chalk.gray(` (Q${l})`):"")+chalk.yellow(" β NOT submitted.")),console.log(chalk.gray(" review with ")+chalk.cyan("drafts")+chalk.gray("; when sure, submit it the normal way.")),console.log(),void se.prompt()}if(!a&&("drafts"===n.toLowerCase()||/^drafts\s/i.test(n))){const o=n.replace(/^drafts\s*/i,"").trim().toLowerCase();if("clear"===o){const o=yo();return console.log(),console.log(chalk.gray(` Cleared ${o} draft${1===o?"":"s"}.`)),console.log(),void se.prompt()}const e=o.match(/^(?:rm|remove|del|delete)\s+(\d+)$/);if(e){const o=mo(Number(e[1]));return console.log(),console.log(o?chalk.gray(` Removed draft #${e[1]}.`):chalk.yellow(` No draft #${e[1]}.`)),console.log(),void se.prompt()}const t=Q(),l=go(t?.session?.examId??null);if(console.log(),0===l.length)console.log(chalk.gray(" No drafts yet. Stage a candidate with ")+chalk.cyan("#ICOA{maybe_this}")+chalk.gray(" β it wonβt submit."));else{console.log(chalk.bold.white(" Draft answers")+chalk.gray(" (staged β not submitted)"));for(const o of l){const e=o.q?chalk.cyan(`Q${o.q}`.padStart(4)):chalk.gray(" Β· ");console.log(chalk.gray(` #${o.id}`)+` ${e} `+chalk.white(o.text.length>56?`${o.text.slice(0,53)}β¦`:o.text))}console.log(chalk.gray(" remove: ")+chalk.cyan("drafts rm <id>")+chalk.gray(" Β· clear all: ")+chalk.cyan("drafts clear"))}return console.log(),void se.prompt()}if("menu"===n||"menu confirm"===n)return H()&&"menu confirm"!==n?(console.log(),console.log(chalk.yellow(" Real exam active. Progress is auto-saved.")),console.log(chalk.gray(" To return to main menu anyway, type ")+chalk.white("menu confirm")),console.log(),void se.prompt()):void T(se);if(N()){re=!0;const o=await D(n);return re=!1,"exit"===o&&se.setPrompt(Xo()),void se.prompt()}if(_()){re=!0;const o=await F(n);return re=!1,"exit"!==o&&"solved"!==o||se.setPrompt(Xo()),void se.prompt()}if(U()){re=!0;const o=await R(n);return re=!1,"exit"===o&&se.setPrompt(Xo()),se.setPrompt(U()?chalk.bold.cyan("icoa ctf4eai> "):Xo()),void se.prompt()}if(xo(n),"exit"===n)return Q()?(console.log(),console.log(chalk.yellow(" β An exam is in progress.")),console.log(chalk.white(" To return to menu without losing progress, type: ")+chalk.bold.cyan("back")),console.log(chalk.white(" To fully close ICOA CLI, type: ")+chalk.bold.cyan("quit")),console.log(chalk.gray(" Your progress is auto-saved either way.")),console.log(),void se.prompt()):(console.log(),console.log(chalk.gray(" ")+chalk.white("exit")+chalk.gray(" returns to the main menu. To fully close ICOA CLI, type ")+chalk.bold.cyan("quit")+chalk.gray(".")),"selection"===zo&&te(),void se.prompt());if("quit"===n||"q"===n||"quit confirm"===n){const o=Q();return o&&"demo-free"!==o.session.examId&&"quit confirm"!==n?(console.log(),console.log(chalk.yellow(" β A real exam is in progress.")),console.log(chalk.gray(" Your answers are auto-saved on the server, but the exam timer keeps ticking")),console.log(chalk.gray(" on the server side even if you close the CLI.")),console.log(),console.log(chalk.white(" To leave the CLI but keep the exam alive, type: ")+chalk.bold.cyan("back")),console.log(chalk.gray(" (recommended β you can resume with ")+chalk.cyan("exam q 1")+chalk.gray(" after relaunching icoa)")),console.log(),console.log(chalk.white(" To really close ICOA CLI, type: ")+chalk.bold.cyan("quit confirm")),console.log(),void se.prompt()):(o&&"demo-free"===o.session.examId&&(console.log(),console.log(chalk.gray(" Demo paused. Resume with: ")+chalk.white("demo")+chalk.gray(" (fresh) or ")+chalk.white("exam q 1")+chalk.gray(" (continue)."))),Co(),Ao(),Eo(),ao(),v(),console.log(chalk.gray(" Session saved. Use ")+chalk.white("icoa --resume")+chalk.gray(" to continue.")),uo(),void c(0))}if("back"===n){const o=Q(),e=o&&"demo-free"!==o.session.examId,t=o&&"demo-free"===o.session.examId&&(()=>{const e=new Date(o.session.startedAt||0).getTime();return Date.now()-e<18e5})();if(e)console.log(),console.log(chalk.gray(" Exam paused. Your progress is saved.")),console.log(chalk.white(" Resume: exam q 1")+chalk.gray(" Β· ")+chalk.white("exam review")+chalk.gray(" Β· ")+chalk.white("exam submit")),console.log();else if(t){const e=Object.keys(o.answers).length,t=o.session.questionCount;console.log(),console.log(chalk.gray(` Demo paused (${e}/${t} answered). Resume with: `)+chalk.white("exam q 1")),console.log(chalk.gray(" Or type ")+chalk.white("demo")+chalk.gray(" to restart.")),console.log()}else{if(o&&"demo-free"===o.session.examId){const{clearExamState:o}=await import("./lib/exam-state.js");o("demo-free")}const e=m();fetch("https://practice.icoa2026.au/api/icoa/demo-stats",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({type:"post-report-back",lang:e.language||"en",timestamp:(new Date).toISOString()}),signal:AbortSignal.timeout(5e3)}).catch(()=>{}),"selection"===zo?te():console.log(chalk.gray(" Already at main menu."))}return void se.prompt()}if("help"===n||"?"===n){if(Q()){re=!0;try{await e.parseAsync(["node","icoa","exam","help"])}catch{}return re=!1,void se.prompt()}return le(w(),zo),void se.prompt()}if("man"===n||"manual"===n)return le(w(),zo),console.log(),console.log(chalk.bold.yellow(" β
Stuck on a tool? ")+chalk.bold.cyan("man <tool>")+chalk.gray(" e.g. ")+chalk.cyan("man steghide")+chalk.gray(" Β· ")+chalk.cyan("man tools")+chalk.gray(" = full list")),void se.prompt();if(/^(?:man|manual)\s+\S/i.test(n))return M(n.replace(/^(?:man|manual)\s+/i,"")),void se.prompt();if("more help"===n.toLowerCase()&&Q()){re=!0;try{await e.parseAsync(["node","icoa","exam","more-help"])}catch{}return re=!1,void se.prompt()}if("continue"===n.toLowerCase())return console.log(),console.log(chalk.green.bold(" βββ AI4CTF β AI as Your Teammate βββ")),console.log(),console.log(chalk.white(" In AI4CTF, you solve cybersecurity challenges")),console.log(chalk.white(" with AI by your side.")),console.log(),console.log(chalk.white(" In this demo, your AI teammate gives help at 3 levels:")),console.log(chalk.yellow(" hint a")+chalk.gray(" General guidance")),console.log(chalk.yellow(" hint b")+chalk.gray(" Deep analysis")),console.log(chalk.yellow(" hint c")+chalk.gray(" Critical assist")),console.log(),console.log(chalk.white(" Try it now! Type: ")+chalk.bold.green("ai4ctf")),console.log(chalk.gray(' Chat freely with your AI teammate. Type "exit" when done.')),console.log(),console.log(chalk.gray(" After ai4ctf, try: ")+chalk.bold.red("ctf4ai")+chalk.gray(' β trick the AI into saying "koala"')),console.log(),void se.prompt();if(/^ICOA-[A-Z]{2,3}-\d{1,6}$/i.test(n.trim())){re=!0;try{await e.parseAsync(["node","icoa","exam","token",n.trim()])}catch{}return re=!1,void se.prompt()}if(/^[A-Z]{2}[0-9A-HJKMNP-TV-Z]{8}$/i.test(n.trim())){re=!0;try{await e.parseAsync(["node","icoa","exam","token",n.trim().toUpperCase()])}catch{}return re=!1,void se.prompt()}const s=n.match(/^exam\s+([A-Z]{2}[0-9A-HJKMNP-TV-Z]{8})$/i);if(s){re=!0;try{await e.parseAsync(["node","icoa","exam","token",s[1].toUpperCase()])}catch{}return re=!1,void se.prompt()}const r=n.match(/^exam\s+([A-Z]{2,3})$/i);if(r){re=!0;try{await e.parseAsync(["node","icoa","exam","list",r[1]])}catch{}return re=!1,void se.prompt()}const i=n.match(/^exam\s+(\S+)$/i);if(i&&!Ko.has(i[1].toLowerCase())){const o=i[1].toUpperCase(),{normalizeTokenBody:t}=await import("./lib/token-format.js"),n=t(o),l=/^[A-Z]{2}[0-9A-HJKMNP-TV-Z]{8}$/;if(console.log(),l.test(n)){console.log(chalk.yellow(` Corrected look-alike characters: ${o} β ${n}`)),re=!0;try{await e.parseAsync(["node","icoa","exam","token",n])}catch{}return re=!1,void se.prompt()}return console.log(chalk.red(` β Not a valid exam token: ${o}`)),console.log(),console.log(chalk.gray(" An exam token is ")+chalk.bold.white("2 letters + 8 characters")+chalk.gray(" (e.g. ")+chalk.bold.yellow("AUHXP7SWMM")+chalk.gray(`) β yours is ${o.length}.`)),console.log(chalk.gray(" Check for 0/O, 1/I/L, V/U mix-ups, or ask your country team leader.")),console.log(),console.log(chalk.gray(" No token yet? Try ")+chalk.bold.green("demo")+chalk.gray(" (free practice paper) or ")+chalk.bold.green("exam nations")+chalk.gray(" to see participating countries.")),console.log(),void se.prompt()}if("clear"===n||"cls"===n)return console.clear(),void se.prompt();if("news"===n)return Oo()?jo():console.log(chalk.gray(" No competition joined. Use ")+chalk.white("join <url>")+chalk.gray(".")),void se.prompt();if("memo"===n){if(!Oo())return console.log(chalk.gray(" Join a competition first: ")+chalk.white("join <url>")),void se.prompt();re=!0;try{await _o()}catch{}return void(re=!1)}const y=Do()||No(m().userName||"");if("jury"===n&&y){re=!0;try{await Fo()}catch{}return void(re=!1)}if(y&&Do()&&"scoreboard"===n.split(/\s+/)[0]){re=!0;try{const o=await Po();if(console.log(),0===o.length)console.log(chalk.gray(" Scoreboard is empty."));else{console.log(chalk.bold.white(" Scoreboard"));for(const e of o.slice(0,50))console.log(chalk.gray(` ${String(e.pos).padStart(3)}. `)+chalk.white(e.name.padEnd(28).slice(0,28))+chalk.cyan(String(e.score)))}console.log()}catch{}return re=!1,void se.prompt()}if(y&&Lo()){const o=n.split(/\s+/)[0];if(["challenges","open","submit","hint"].includes(o))return console.log(),console.log(chalk.yellow(" Team-leader account β the challenge bracket is not available here.")),console.log(chalk.gray(" Available: ")+chalk.white("scoreboard")+chalk.gray(" Β· ")+chalk.white("news")+chalk.gray(" Β· ")+chalk.white("jury")+chalk.gray(" Β· ")+chalk.white("time")+chalk.gray(" Β· ")+chalk.white("status")+chalk.gray(" Β· ")+chalk.white("logout")),console.log(),void se.prompt()}if(n.startsWith("activate ")){const o=n.slice(9).trim(),e=await b(o);return"ok"===e?console.log(chalk.green(" Access granted! Token bound to this device.")):"network"===e?(console.log(),console.log(chalk.red(" Could not reach the activation server.")),console.log(chalk.gray(" Activation needs internet once β check your connection to ")+chalk.cyan("practice.icoa2026.au")+chalk.gray(" and run the same command again."))):"already_bound"===e?(console.log(),console.log(chalk.red(" Token already activated on a different device.")),console.log(chalk.gray(" Each token binds to the first device that uses it. If you lost the device,")),console.log(chalk.gray(" contact your proctor to have the token re-issued for a new device."))):(console.log(),console.log(chalk.red(" Token not recognized.")),console.log(chalk.gray(" Possible reasons:")),console.log(chalk.white(" β’ ")+chalk.gray("Typo β access tokens are case-insensitive and look like ")+chalk.cyan("ICOA-XXXX-XXXX-XXXX")+chalk.gray(" (4-char hex groups, e.g. ICOA-385E-27F2-B21B)")),console.log(chalk.white(" β’ ")+chalk.gray("Expired β ask your proctor or organizer for a fresh token")),console.log(chalk.white(" β’ ")+chalk.gray("Network β verify connection to ")+chalk.cyan("practice.icoa2026.au")),console.log(chalk.gray(" Still stuck? type ")+chalk.cyan("help")+chalk.gray(" or try ")+chalk.cyan("exam demo")+chalk.gray(" for a free practice round."))),console.log(),void se.prompt()}if("activate"===n)return console.log(chalk.gray(" Usage: ")+chalk.white("activate <token>")),console.log(),void se.prompt();const d=Q();if(d){const o=n.toUpperCase().trim(),t=o=>{const e=d.questions.find(e=>e.number===o);return!!e&&("ai4ctf"===e.type||"ctf4ai"===e.type||e.options&&!e.options.A&&!e.options.B)},l=o=>{const e=d.questions.find(e=>e.number===o);return"short_answer"===e?.type},a=o=>{const e="demo-free"!==d.session.examId,t=d.questions.find(e=>e.number===o),n=V(t?.type,e);console.log(),console.log(chalk.yellow(` Q${o} is a practical question β letters (A/B/C/D) don't apply here.`)),n?(console.log(chalk.white(" Enter the AI chat for this question: ")+chalk.bold.cyan(n)),console.log(chalk.gray(" Or submit a flag directly: ")+chalk.green(`exam answer ${o} ICOA{your_flag}`))):console.log(chalk.gray(" Submit a flag: ")+chalk.green(`exam answer ${o} ICOA{your_flag}`)),console.log()};if(/^[ABCDE]$/.test(o)){const n=d._lastQ||1;if(t(n))return a(n),void se.prompt();if(l(n))return console.log(),console.log(chalk.yellow(` Q${n} is a short-answer question β type a number, not a letter.`)),console.log(chalk.gray(" Example: ")+chalk.green("42")+chalk.gray(" (or ")+chalk.green(`exam answer ${n} 42`)+chalk.gray(")")),console.log(),void se.prompt();re=!0;try{await e.parseAsync(["node","icoa","exam","answer",String(n),o])}catch{}return re=!1,void se.prompt()}if(/^-?\d+$/.test(o)){const t=d._lastQ||1;if(l(t)){re=!0;try{await e.parseAsync(["node","icoa","exam","answer",String(t),o])}catch{}return re=!1,void se.prompt()}}const s=o.match(/^(\d+)\s+([ABCDE]|-?\d+)$/);if(s){const o=parseInt(s[1],10);if(t(o))return a(o),void se.prompt();re=!0;try{await e.parseAsync(["node","icoa","exam","answer",s[1],s[2]])}catch{}return re=!1,void se.prompt()}}const u=n.split(/\s+/)[0].toLowerCase(),p=/^python3?(\.\d+)?$/.test(u),h="ls"===u||"pwd"===u||"tmux"===u,f=n.startsWith("!")||u.startsWith("!")||p||h,C=new Set(["nano","vi","vim","emacs","pico","ed","code","cat","less","more","head","tail","ls","pwd","cd","base64","xxd","hexdump","od","openssl","md5sum","sha256sum","grep","find","awk","sed","strings","file","curl","wget","nc","ping","nmap","echo","bash","sh","zsh","pip","pip3","node","npm"]),$=()=>{console.log(chalk.gray(" Shell commands need ")+chalk.bold.cyan("!")+chalk.gray(" prefix. Try: ")+chalk.bold.cyan(`!${n}`)),console.log()};if("py"===u||"pylist"===u)return console.log(chalk.yellow(` ${u} is the learn-card Python scratchpad β it lives inside learn.`)),console.log(chalk.gray(" Open your course first: ")+chalk.bold.cyan("learn <TOKEN>")+chalk.gray(" (or bare ")+chalk.bold.cyan("learn")+chalk.gray(" for the demo), then type ")+chalk.bold.cyan("py"===u?"/py":"/pylist")+chalk.gray(" on any card.")),console.log(),void se.prompt();if("embodied"===zo&&!f&&!["doctor","type","demo2","learn","exam","ctf4eai","ctf4vla","eai","arena","lang","ref","env","aienv","ipynb","kaggle","teleload","pandahelpme31","microduck","guide","board","sim"].includes(u))return C.has(u)?($(),void se.prompt()):(console.log(chalk.gray(" Not available in Embodied AI Security mode.")),console.log(chalk.white(" Try ")+chalk.bold.cyan("demo2")+chalk.gray(" (intro) Β· ")+chalk.bold.cyan("learn")+chalk.gray(" (curriculum) Β· ")+chalk.bold.cyan("exam <PD-token>")+chalk.gray(" (Paper D)")),console.log(),void se.prompt());if("selection"===zo&&!f&&!["doctor","type","battle","python","mujoco","mojoco","exam","demo","demo2","demo4","demo5","gfssm","retry","nations","next","prev","continue","lang","ref","ai4ctf","ctf4ai","mark","unmark","review","submit","env","aienv","ipynb","kaggle","teleload","pandahelpme31","microduck","gpufortask","guide","board","sim"].includes(u)){if(C.has(u))return $(),void se.prompt();if(l().includes(u))console.log(chalk.gray(` ${u} isn't available on this screen.`));else{console.log(chalk.yellow(` Unknown command: ${u}`));const o=nearestCommand(u);o&&console.log(chalk.gray(" Did you mean: ")+chalk.bold.cyan(o)+chalk.gray("?"))}if(d){const o=d._lastQ||1;console.log(chalk.white(` Resume exam: exam q ${o}`)+chalk.gray(" Β· ")+chalk.white("A/B/C/D")+chalk.gray(" to answer"))}else console.log(chalk.gray(" Try: ")+chalk.bold.cyan("learn <TOKEN>")+chalk.gray(" Β· ")+chalk.bold.cyan("exam <CC>xxxxxxxx")+chalk.gray(" Β· ")+chalk.bold.cyan("demo")+chalk.gray(" Β· ")+chalk.bold.cyan("help")+chalk.gray(" Β· ")+chalk.bold.cyan("menu"));return console.log(),void se.prompt()}if("organizer"===zo&&!["doctor","join","exam","demo","retry","next","prev","logout","lang","ref","ctf","mark","unmark","review","submit","tmux"].includes(u))return console.log(chalk.gray(" Not available in Organizer mode. Switch via: setup")),console.log(),void se.prompt();if(!("olympiad"!==zo||w()&&x()||k(u)))return console.log(chalk.yellow(" Restricted mode. ")+chalk.gray("Enter your access token:")),console.log(chalk.white(" activate <token>")),console.log(),console.log(chalk.gray(" Free commands: ")+chalk.white("ref [topic]")+chalk.gray(", ")+chalk.white("help")+chalk.gray(", ")+chalk.white("exit")),console.log(),void se.prompt();if(!l().includes(u)){if("tmux"===u)try{t("command -v tmux",{stdio:"ignore"})}catch{return console.log(chalk.yellow(" tmux is not installed yet.")),console.log(chalk.gray(" Install it with ")+chalk.bold.cyan("env setup")+chalk.gray(" (full toolkit) or ")+chalk.bold.cyan("darwin"===process.platform?"brew install tmux":"sudo apt install tmux")+chalk.gray(".")),console.log(),void se.prompt()}if(Ho.has(u))return console.log(chalk.yellow(` "${u}" is a shell command β the ICOA prompt isn't a shell.`)),console.log(chalk.gray(" In real-exam mode, prefix with ! to run inside the sandbox: ")+chalk.cyan(`!${n}`)),console.log(),void se.prompt();if(/(?:^|\s)(?:\/(?!home\/|Users\/|tmp\/)|\.\.\/|~\/)/.test(n)&&!n.startsWith("cd ")){const o=/(?:^|\s)\/(?!home\/\w+\/icoa-workspace|Users\/\w+\/icoa-workspace|tmp\/)/.test(n),e=/\.\./.test(n);if(o||e)return console.log(chalk.red(" Blocked: access outside workspace is not allowed.")),console.log(chalk.gray(` Workspace: ${Qo}`)),console.log(),void se.prompt()}let o=n.startsWith("!")?n.slice(1).trim():n;if("darwin"===process.platform){const e="/opt/homebrew/opt/python@3.12/bin/python3.12";o=o.replace(/^python3?\s/,`${e} `).replace(/^(python3|python)$/,e)}else if("win32"===process.platform){const e=(()=>{try{return t("py -3 --version",{stdio:["ignore","ignore","ignore"],timeout:1500}),"py -3"}catch{}return"python"})();o=o.replace(/^python3?(\.\d+)?\s/,`${e} `).replace(/^python3?(\.\d+)?$/,e)}else{const e=(()=>{try{return t("which python3.12",{stdio:"ignore"}),"python3.12"}catch{return"python3"}})();o=o.replace(/^python\s/,`${e} `).replace(/^python$/,e)}const e=ko(),l=wo(n);bo({cwd:e,input:n,riskFlags:l}),l.length>0&&H()&&(console.log(chalk.yellow(` β Action flagged: ${l.join(", ")} β logged.`)),console.log()),/^(\S*python3?(\.\d+)?)\s*$/.test(o)&&(o=`PYTHONSTARTUP="${function(){const o=Bo(Zo(),".icoa");Uo(o)||Ro(o,{recursive:!0});const e=Bo(o,"python-startup.py");let t="";if(Uo(e))try{t=qo(e,"utf-8")}catch{}return t!==Yo&&Wo(e,Yo),e}()}" ${o}`,console.log(),console.log(chalk.cyan(" βββββββββββββββββββββββββββββββββββββββββ")),console.log(chalk.bold.white(" Python ready β ICOA exam toolkit pre-loaded")),console.log(chalk.cyan(" βββββββββββββββββββββββββββββββββββββββββ")),console.log(),console.log(chalk.white(" Already imported: ")+chalk.gray("base64, struct, hashlib, re, json, binascii")),console.log(chalk.white(" Also available: ")+chalk.gray("requests, bs4, numpy, PIL.Image, AES, pad/unpad, xor, p32/u32/p64/u64")),console.log(),console.log(chalk.yellow(" Quick examples:")),console.log(chalk.gray(' base64.b64decode("aGVsbG8=") ')+chalk.gray("# decode base64")),console.log(chalk.gray(' bytes.fromhex("48656c6c6f") ')+chalk.gray("# hex β bytes")),console.log(chalk.gray(' "ICOA{x}".encode() ')+chalk.gray("# str β bytes")),console.log(chalk.gray(" [chr(c) for c in [73,67,79,65]] ")+chalk.gray("# ASCII codes")),console.log(chalk.gray(' xor(bytes.fromhex("0a2b"), b"IC") ')+chalk.gray("# pwntools XOR")),console.log(),console.log(chalk.gray(" Exit: ")+chalk.white("exit()")+chalk.gray(" or Ctrl-D")),console.log(chalk.cyan(" βββββββββββββββββββββββββββββββββββββββββ")),console.log()),re=!0;try{await fo()&&await po()?await ho(o,se):await ne(o,se,e)}catch{console.log(chalk.yellow(` Command failed: ${u}`))}return re=!1,console.log(),void se.prompt()}re=!0;const A=n.trim(),I=A.toLowerCase();let S,E=null,j="";if(d)if("submit"===I)E="final";else if(I.startsWith("submit ")){let o=A.slice(7).trim();/^submit\s+/i.test(o)&&(o=o.replace(/^submit\s+/i,"").trim()),o=o.replace(/^["'`]+|["'`]+$/g,"").trim(),o&&/^ICOA\{[^}]*\}?$/i.test(o)?(E="flag",j=o):o&&/^[ABCDE]$/i.test(o)&&(E="flag",j=o.toUpperCase())}else/^ICOA\{[^}]+\}$/i.test(A)&&(E="flag",j=A);S="final"===E?["exam","submit"]:"flag"===E?["exam","answer",String(d?._lastQ||1),j]:mapCommand(n);const O="ctf"===S[0]&&"join"===S[1];O&&se.pause(),process.exit=()=>{throw new Error(Jo)};try{await e.parseAsync(["node","icoa",...S])}catch(o){const e=o instanceof Error?o.message:String(o);if(e===Jo);else if(e.includes("commander.unknownCommand")){const o=nearestCommand(u.split(/\s+/)[0]||u);console.log(chalk.yellow(` Unknown command: ${u}.`)),o&&console.log(chalk.gray(" Did you mean: ")+chalk.bold.cyan(o)+chalk.gray("?")),console.log(chalk.gray(" Type ")+chalk.cyan("help")+chalk.gray(" for the full command list."))}else e.includes("commander.missingArgument")||"commander.missingArgument"===o?.code?"submit"===u||"flag"===u?(console.log(chalk.yellow(" Incomplete β usage: ")+chalk.cyan("submit <challenge#> <flag>")),console.log(chalk.gray(" Put the number AND the flag on one line, e.g. ")+chalk.cyan("submit 44 pecan{...}"))):(console.log(chalk.yellow(` Incomplete command: ${u}`)),console.log(chalk.gray(" Type ")+chalk.cyan("help")+chalk.gray(" for usage."))):e.includes("commander.")||(e.includes("fetch failed")||e.includes("ECONNREFUSED")||e.includes("ETIMEDOUT"))&&console.log(chalk.yellow(" Network error. Check your connection."))}finally{process.exit=c,re=!1,O&&se.resume()}N()?se.setPrompt(chalk.magenta("icoa ai4ctf> ")):_()?se.setPrompt(chalk.red("icoa ctf4ai> ")):U()&&se.setPrompt(chalk.bold.cyan("icoa ctf4eai> ")),console.log(),se.prompt()}),se.on("SIGINT",()=>{if(console.log(),N()||_())console.log(chalk.yellow(" Ctrl+C did not close ICOA CLI β you are still in the AI chat.")),console.log(chalk.white(" Type ")+chalk.bold.cyan("exit")+chalk.white(" to leave the chat and return to the menu."));else if(Q()){const o="demo-free"!==Q().session.examId;console.log(chalk.yellow(" Ctrl+C did NOT close ICOA CLI.")),console.log(chalk.gray(` Your ${o?"exam":"demo"} is paused and every answer is auto-saved.`)),console.log(),console.log(chalk.white(" Resume: ")+chalk.cyan("exam q 1")+chalk.gray(" Β· Back to menu: ")+chalk.cyan("back")+chalk.gray(" Β· Close CLI: ")+chalk.cyan(o?"quit confirm":"quit"))}else console.log(chalk.yellow(" Ctrl+C did not close ICOA CLI β you are still at the ")+chalk.cyan("icoa>")+chalk.yellow(" prompt.")),console.log(chalk.gray(" Keep typing β ")+chalk.cyan("help")+chalk.gray(" lists commands. (Only ")+chalk.cyan("quit")+chalk.gray(" or Ctrl+D actually close the CLI.)"));console.log(),se.prompt()}),se.on("close",()=>{n("main-rl-close",`stdin.isTTY=${!0===process.stdin.isTTY}`),console.log(),console.log(chalk.gray(" input closed β leaving icoa. Run icoa --resume to continue.")),Co(),Ao(),Eo(),ao(),v(),uo(),c(0)}),"1"===process.env.ICOA_AUTO_RESUME&&(delete process.env.ICOA_AUTO_RESUME,G()&&(re=!0,await ee(e),re=!1,se.setPrompt(N()?chalk.magenta("icoa ai4ctf> "):Xo()),se.prompt()))}function ne(o,t,n){return new Promise(l=>{const a=process.stdin,s=!!a.isTTY&&!!a.isRaw;if(t.pause(),a.isTTY&&"function"==typeof a.setRawMode)try{a.setRawMode(!1)}catch{}const r=e(o,{shell:!0,stdio:"inherit",cwd:n||process.cwd()}),i=()=>{if(a.isTTY&&"function"==typeof a.setRawMode&&s)try{a.setRawMode(!0)}catch{}To(),t.resume(),l()};r.on("close",e=>{if(127===e){const e=nearestCommand(o.trim().split(/\s+/)[0]??"");e&&console.log(chalk.gray(" Did you mean: ")+chalk.bold.cyan(e)+chalk.gray("?"))}i()}),r.on("error",i)})}export function mapCommand(o){const e=o.split(/\s+/),t=e[0].toLowerCase(),n=e.slice(1);if("aienv"===t&&["run","python","py"].includes((n[0]??"").toLowerCase()))return L(o);if(("submit"===t||"flag"===t)&&n.length>=2)return["ctf","submit",n[0],n.slice(1).join(" ").trim().replace(/^["'`]+|["'`]+$/g,"")];if("connect"===t&&n.length>=2){const e=L(o);return["connect",e[1]??n[0],e.slice(2).join(" ")]}return s(t,n)||[t,...n]}function le(o,e="olympiad"){if(console.log(),"selection"===e||"organizer"===e)return console.log(chalk.bold.white(" Exam")),console.log(chalk.white(" join <url> ")+chalk.gray("Connect to exam server")),console.log(chalk.white(" exam list ")+chalk.gray("Available exams")),console.log(chalk.white(" exam start <id> ")+chalk.gray("Begin an exam")),console.log(chalk.white(" exam q [n] ")+chalk.gray("View questions")),console.log(chalk.white(" exam answer <n> <X> ")+chalk.gray("Answer question")),console.log(chalk.white(" exam review ")+chalk.gray("Review all answers")),console.log(chalk.white(" exam submit ")+chalk.gray("Submit for grading")),console.log(chalk.white(" exam result ")+chalk.gray("View your score")),console.log(),console.log(chalk.bold.white(" System")),console.log(chalk.white(" ref [topic] ")+chalk.gray("Quick reference")),console.log(chalk.white(" setup ")+chalk.gray("Settings / switch mode")),console.log(chalk.white(" lang [code] ")+chalk.gray("Switch language")),console.log(chalk.white(" clear ")+chalk.gray("Clear screen")),console.log(chalk.white(" exit ")+chalk.gray("Quit")),void console.log();if(!o)return console.log(chalk.bold.yellow(" Restricted Mode β activate with a token to unlock all commands")),console.log(),console.log(chalk.white(" activate <token> ")+chalk.gray("Unlock full access")),console.log(chalk.white(" ref [topic] ")+chalk.gray("Quick reference")),console.log(chalk.white(" exit ")+chalk.gray("Quit")),void console.log();console.log(chalk.cyan(" βββββββββββββββββββββββββββββββββββββββββββββββ")),console.log(chalk.bold.white(" How it works")),console.log(),console.log(chalk.gray(" 1. Browse ")+chalk.white("challenges")+chalk.gray(" and pick one")),console.log(chalk.gray(" 2. ")+chalk.white("open <id>")+chalk.gray(" to read the challenge")),console.log(chalk.gray(" 3. Use ")+chalk.white("ai4ctf")+chalk.gray(" to chat with AI when stuck")),console.log(chalk.gray(" 4. ")+chalk.white("submit <id> <flag>")+chalk.gray(" to score points")),console.log(chalk.gray(" 5. Check ")+chalk.white("scoreboard")+chalk.gray(" to track your rank")),console.log(chalk.cyan(" βββββββββββββββββββββββββββββββββββββββββββββββ")),console.log();for(const o of["Competition","AI Teammate","Tools","System"]){console.log(chalk.bold.white(` ${o}`));for(const e of a(o))console.log(chalk.white(` ${e.label.padEnd(20)}`)+chalk.gray(e.text)),"System"===o&&"resume"===e.label&&console.log(chalk.white(" #<candidate> ")+chalk.gray("Stage a draft answer (never auto-submits)"));"Tools"===o&&console.log(chalk.white(" man <tool> ")+chalk.bold.yellow("β
")+chalk.gray("How to use a tool (steghide, nmapβ¦); ")+chalk.cyan("man tools")+chalk.gray(" = list. Bare ")+chalk.cyan("man")+chalk.gray(" = this list.")),console.log()}}
|
|
1
|
+
import{createInterface as o}from"node:readline";import{spawn as e,execSync as t}from"node:child_process";import chalk from"chalk";import{appendExitLog as n}from"./lib/exit-log.js";import{dispatchable as l,helpRows as a,shortcutFor as s,subcommandsOf as r,surface as i}from"./lib/commands.js";import{distance as c}from"fastest-levenshtein";import{isConnected as g,getConfig as m,saveConfig as y}from"./lib/config.js";import{selectionSetupLine as d}from"./lib/python-setup.js";import{isExamSetupComplete as u}from"./lib/exam-setup.js";import{detectCaps as p}from"./lib/render-card.js";import{ensureLangCache as h}from"./lib/translations-fetcher.js";import{loadUiPack as f}from"./lib/i18n.js";import{isActivated as w,activateToken as b,isFreeCommand as k,isDeviceMatch as x,recordExit as v,recordResume as C,isFirstRunOrUpgrade as $,markVersionSeen as A}from"./lib/access.js";import{setReplMode as I}from"./lib/ui.js";import{returnToMainMenu as T,printMenuHint as S,menuHintInline as E,registerRealExit as j}from"./lib/menu-nav.js";import{setMainRl as O}from"./lib/main-rl.js";import{shellSplit as L}from"./lib/shell-split.js";import{isChatActive as N,handleChatMessage as D}from"./commands/ai4ctf.js";import{isMicroduckWord as P}from"./commands/microduck.js";import{renderToolMan as M}from"./lib/tool-man.js";import{isCtf4aiActive as _,handleCtf4aiMessage as F}from"./commands/ctf4ai-demo.js";import{isCtf4VlaActive as U,handleCtf4VlaMessage as R}from"./commands/ctf4vla.js";import{isDemo2Active as q}from"./commands/demo2.js";import{isSprintActive as W}from"./commands/sprint.js";import{isCardDeckActive as B}from"./lib/card-engine.js";import{hasAnySimHistory as Z,lastArmAt as Y,lastBundledAt as z,lastSimAt as X}from"./lib/sim-cooldown.js";import{getExamState as Q,getRealExamState as H,getDemoState as J,practicalChatCommand as V}from"./lib/exam-state.js";import{resolveResumePoint as G}from"./lib/resume.js";import{buildStatusLine as K}from"./lib/statusline.js";import{startBgTask as oo,startAsyncTask as eo,listBgTasks as to,getBgTask as no,drainCompleted as lo,killAllBgTasks as ao,runningCount as so}from"./lib/bgtasks.js";import{computeStart as ro,renderStart as io}from"./commands/challenge.js";import{addDraft as co,listDrafts as go,removeDraft as mo,clearDrafts as yo}from"./lib/drafts.js";import{resetTerminalTheme as uo}from"./lib/theme.js";import{ensureSandbox as po,runInSandbox as ho,isDockerAvailable as fo}from"./lib/sandbox.js";import{checkShellRisk as wo,logShellAudit as bo,getActiveCwd as ko}from"./lib/exam-sandbox.js";import{logCommand as xo}from"./lib/logger.js";import{startLogSync as vo,stopLogSync as Co}from"./lib/log-sync.js";import{installInputDynamics as $o,uninstallInputDynamics as Ao,stripTerminalMarkers as Io,rearmFocusMode as To}from"./lib/input-dynamics.js";import{startBroadcastPoll as So,stopBroadcastPoll as Eo,showBroadcast as jo,isCompetitionJoined as Oo,isMelCompetition as Lo,isLeaderAccount as No,isLeaderSession as Do,fetchPublicScoreboard as Po,isCommsActive as Mo}from"./lib/comms.js";import{enterMemoScreen as _o,enterJuryScreen as Fo}from"./commands/comms.js";import{existsSync as Uo,mkdirSync as Ro,readFileSync as qo,writeFileSync as Wo}from"node:fs";import{join as Bo}from"node:path";import{homedir as Zo}from"node:os";const Yo="# ICOA exam interactive startup β auto-loaded by PYTHONSTARTUP\nimport base64, struct, hashlib, re, json, os, sys, binascii\ntry: import requests\nexcept ImportError: pass\ntry: from Crypto.Cipher import AES\nexcept ImportError: pass\ntry: from Crypto.Util.Padding import pad, unpad\nexcept ImportError: pass\ntry: from pwn import xor, p32, u32, p64, u64\nexcept ImportError: pass\ntry: import bs4\nexcept ImportError: pass\ntry: import numpy as np\nexcept ImportError: pass\ntry: from PIL import Image\nexcept ImportError: pass\n",zo=Date.now();function Xo(){return Lo()?chalk.yellow("icoa 2026> "):H()?chalk.cyan("icoa exam> "):function(){const o=J();return!(!o||"demo-free"!==o.session?.examId)&&new Date(o.session.startedAt||0).getTime()>=zo}()?chalk.yellow("icoa demo> "):chalk.green("icoa> ")}const Qo=Bo(Zo(),"icoa-workspace"),Ho=new Set(["sudo","su","doas","pkexec","brew","apt","apt-get","yum","choco","npm","npx","pip","pip3","shutdown","reboot","halt","mkfs","fdisk","dd","iptables","ufw"]),Jo="__REPL_NO_EXIT__",Vo="2.5.1",Go=i();export function nearestCommand(o,e=2){const t=o.trim().toLowerCase();if(!t)return null;let n={word:"",dist:Number.POSITIVE_INFINITY};for(const o of Go){const e=c(t,o);e<n.dist&&(n={word:o,dist:e})}return n.dist>0&&n.dist<=e?n.word:null}const Ko=new Set(["answer","demo","demo-retry","help","list","mark","more-help","nations","next","prev","q","reset","result","review","setup","start","submit","token","unmark","status","time"]);function oe(o){const e=o.replace(/^\s+/,"");if(/^\/\S*$/.test(e)){const o=e.slice(1).toLowerCase();return[Go.filter(e=>e.startsWith(o)).map(o=>`/${o}`),e]}const t=e.split(/\s+/);if(t.length<=1){const o=(t[0]??"").toLowerCase();return[Go.filter(e=>e.startsWith(o)).slice(),o]}if(2===t.length){const o=r(t[0].toLowerCase());if(o){const e=t[1].toLowerCase();return[o.filter(o=>o.startsWith(e)).slice(),e]}}return[[],o]}async function ee(o){const e=G();if(!e)return null;const t=process.exit;process.exit=()=>{throw new Error(Jo)};try{await o.parseAsync(["node","icoa",...e.command])}catch(o){if(!(o instanceof Error&&o.message===Jo))throw o}finally{process.exit=t}return e}function te(){console.log(),console.log(` ${chalk.cyan.bold("π― ICOA 2026 Β· National Selection")}`),console.log(),console.log(" "+chalk.bold.cyan("learn ")+chalk.white("ACxxxxxxxx")+chalk.gray(" β ai4ctf-12 (AI as your CTF teammate)")),console.log(" "+chalk.bold.cyan("learn ")+chalk.white("CAxxxxxxxx")+chalk.gray(" β ctf4ai-12 (red-team software AI)")),console.log(" "+chalk.bold.cyan("learn ")+chalk.white("EAxxxxxxxx")+chalk.gray(" β ctf4eai-12 (red-team embodied AI)")),console.log(" "+chalk.bold.cyan("exam ")+chalk.white("<CC>xxxxxxxx")+chalk.gray(" β Paper A/B/C/D/E (country exam token)")),console.log(" "+chalk.bold.cyan("demo")+chalk.gray(" β free practice")),console.log(" "+chalk.bold.cyan("lang")+chalk.white(" es")+chalk.gray(" β switch language")),console.log(" "+chalk.gray("help Β· menu Β· quit"));try{console.log(),console.log(d(u(),"T0"===p().tier))}catch{}console.log()}export async function startRepl(e,a){process.env.ICOA_INSIDE_REPL="1";let s=!1;if(Lo()){const o=m().joinedAt,e=o=>new Intl.DateTimeFormat("en-CA",{timeZone:"Australia/Sydney",year:"numeric",month:"2-digit",day:"2-digit"}).format(o);o&&e(new Date(o))===e(new Date)||(y({ctfdUrl:"",token:"",sessionCookie:"",userId:null,userName:"",teamId:null,country:"",joinedAt:""}),s=!0)}const r=m(),i=g(),c=process.exit.bind(process);j(c);const d=w();if(r.language&&"en"!==r.language&&(await h(r.language,{silent:!0}),f(r.language)),r.demoCleanedForVersion!==Vo){try{const{existsSync:o,unlinkSync:e}=await import("node:fs"),{join:t}=await import("node:path"),{getIcoaDir:n}=await import("./lib/config.js"),l=t(n(),"demo-state.json");o(l)&&e(l)}catch{}y({demoCleanedForVersion:Vo})}const{select:u,confirm:p}=await import("@inquirer/prompts"),L=r.mode||"",J=""===L?"instant":"selection"===L?"learn":["instant","learn","olympiad"].includes(L)?L:"learn",To=[{name:` ${chalk.bold("β‘ Try ICOA in 30 seconds")} ${chalk.gray("β")} ${chalk.gray("watch Β· no token needed")}`,value:"instant"},{name:` ${chalk.bold("π§ Learn")} ${chalk.gray("β")} ${chalk.gray("team token Β· skill up")}`,value:"learn"},{name:` ${chalk.bold("π― National Selection")} ${chalk.gray("β")} ${chalk.gray("country exam token Β· aim for finals")}`,value:"selection"},{name:` ${chalk.bold("π International Olympiad")} ${chalk.gray("β")} ${chalk.gray("finals stage Β· Sydney 2026 Β· full sandbox")}`,value:"olympiad"},{name:` ${chalk.gray("βΉοΈ About ICOA")} ${chalk.gray("Β·")} ${chalk.gray("what this is Β· how to join")}`,value:"about"}];""===L&&(console.log(chalk.green(" π First time here? ")+chalk.white("Just press ")+chalk.bold.cyan("Enter")+chalk.white(" β youβll see ICOA in 30 seconds, no signup needed.")),console.log()),console.log(chalk.gray(" Type ")+chalk.bold.cyan("menu")+chalk.gray(" from anywhere to return here.")),console.log();let zo="";for(;!zo;){let o;const e=process.env.ICOA_TEST_BOOT_MODE;if(e&&["instant","learn","selection","olympiad"].includes(e))o=e;else try{o=await u({message:"Mode",choices:To,default:J||"instant"})}catch(o){throw o instanceof Error&&"ExitPromptError"===o.name&&(console.log(),console.log(chalk.gray(" Goodbye.")),process.exit(0)),o}if("about"!==o)zo=o;else{console.clear(),console.log(),console.log(chalk.cyan(" βββββββββββββββββββββββββββββββββββββββββββββββββββ")),console.log(chalk.bold.yellow(" ICOA")+chalk.white(" β AI-Native CLI OS for Cyber & AI Security")),console.log(chalk.gray(" Olympiad & Competition Β· K-12 to University")),console.log(chalk.cyan(" βββββββββββββββββββββββββββββββββββββββββββββββββββ")),console.log(),console.log(chalk.bold.white(" What Makes ICOA Different")),console.log(chalk.gray(" Β· AI-native AI teammate, AI adversary, AI translation")),console.log(chalk.gray(" Β· CLI OS Complete competition environment in terminal")),console.log(chalk.gray(" Β· 110 tools pwntools, z3, gdb, nmap, sleuthkit... pre-configured")),console.log(chalk.gray(" Β· Global scale 15,000+ concurrent exams Β· 20+ languages")),console.log(),console.log(chalk.bold.white(" Three Frontiers of AI Security")),console.log(` ${chalk.green.bold("AI4CTF")}${chalk.gray(" AI as teammate β 5 CTF disciplines, 5-hour endurance round")}`),console.log(` ${chalk.red.bold("CTF4AI")}${chalk.gray(" AI as target β the AI system itself is the objective")}`),console.log(` ${chalk.cyan.bold("CTF4EAI")}${chalk.gray(" Embodied-AI Arena β probe robot policies in live simulation")}`),console.log(),console.log(chalk.bold.white(" First Edition β Sydney 2026 ")+chalk.green.bold("β held")),console.log(chalk.gray(" Β· Jun 27 - Jul 2, 2026 Β· University of Technology Sydney")),console.log(chalk.gray(" Β· 65 competitors Β· 20 countries & regions (10 on-site, 10 remote)")),console.log(chalk.gray(" Β· 36 awards β 6 Gold Β· 11 Silver Β· 17 Bronze Β· 2 Honorable Mentions")),console.log(chalk.gray(" Β· Champion: Oleg Uteshev Β· Embodied-AI Arena Gold: Kingsley Lim (AU)")),console.log(chalk.gray(" Β· Founding Charter signed β ICOA is now a permanent institution")),console.log(),console.log(chalk.bold.white(" Next: ICOA 2027")+chalk.gray(" β 20 more countries already accredited")),console.log(),console.log(chalk.bold.white(" Organized by")+chalk.gray(" ASRA (Australia) Β· ICO Foundation Inc")),console.log(chalk.bold.white(" Contact ")+chalk.cyan(" australia@icoa2026.au Β· accreditation@icoa2026.au")),console.log(chalk.bold.white(" Website ")+chalk.cyan.underline(" https://icoa2026.au")+chalk.gray(" Β· press: ")+chalk.cyan.underline("https://icoa2026.au/press/")),console.log(chalk.cyan(" βββββββββββββββββββββββββββββββββββββββββββββββββββ")),console.log();try{const{input:o}=await import("@inquirer/prompts"),e=()=>o({message:chalk.gray("Press Enter to return..."),theme:{prefix:"",style:{message:o=>o}}}),t=Date.now();let n=await e();Date.now()-t<200&&(n=await e());const l=n.trim().toLowerCase();if("setup"===l||"config"===l||"/setup"===l){const{runSetupWizard:o}=await import("./commands/setup.js");await o(),await e()}}catch{}console.clear()}}if("olympiad"===zo&&"olympiad"!==J){console.log(),console.log(chalk.yellow(" This mode will download ~500MB of CTF tools and AI models."));let o=!0;try{o=await p({message:"Continue?",default:!0})}catch(e){if(!(e instanceof Error&&"ExitPromptError"===e.name))throw e;o=!1}o||(zo="selection",console.log(chalk.gray(" Switched to National Selection mode.")))}if(zo!==J&&y({mode:zo}),console.log(),"olympiad"===zo&&$(Vo)){A(Vo),console.log(chalk.gray(" Checking competition environment..."));const{execSync:o}=await import("node:child_process"),e=[{name:"pwntools",cmd:'python3 -c "import pwn"'},{name:"z3-solver",cmd:'python3 -c "import z3"'},{name:"numpy",cmd:'python3 -c "import numpy"'},{name:"requests",cmd:'python3 -c "import requests"'}];let t=0;for(const n of e)try{o(n.cmd,{stdio:"ignore"})}catch{t++}t>0?(console.log(chalk.yellow(` ${t} core competition libraries missing.`)),console.log(chalk.gray(" Run ")+chalk.white("env setup")+chalk.gray(" when you are ready to install them.")),console.log()):(console.log(chalk.green(" All core libraries ready.")),console.log())}if(a){const o=C();if(o){const e=Math.floor(o.awaySeconds/60),t=o.awaySeconds%60;console.log(chalk.yellow(` Session resumed. Away: ${e}m ${t}s | Total exits: ${o.exitCount}`)),console.log()}}if("selection"===zo)console.log(chalk.gray(" βββ exam hall Β· 90 min per paper once started Β· no pause βββ")),console.log(),te();else if("embodied"===zo)!function(){console.log(chalk.cyan.bold(" [π€ ctf4eai β Embodied AI Security]")),console.log(),console.log(chalk.bold.cyan(" CTF4EAI")+chalk.gray(" β ICOA 2026's ")+chalk.bold.white("Pioneer Round")),console.log(chalk.gray(" an independent parallel track alongside the scored main events: ")+chalk.green("AI4CTF")+chalk.gray(" (Day 1) and ")+chalk.red("CTF4AI")+chalk.gray(" (Day 2)")),console.log(),console.log(chalk.white(" Embodied AI is at its ImageNet moment.")),console.log(chalk.gray(" VLA models, MuJoCo physics, real robot arms.")),console.log(chalk.gray(" Real models, real physics, real attack surfaces.")),console.log(),console.log(chalk.gray(" βββββββββββββββββββββββββββββββββββββββββββββ"));const o=z()>0||X()>0,e=Y()>0,t=Z();o&&e?console.log(chalk.bold.yellow(" Next up: ")+chalk.bold.cyan("β’ demo2")+chalk.gray(" β ")+chalk.bold.cyan("β£ learn LEARNDEMO01")+chalk.gray(" (sim β Β· sim arm β)")):t?console.log(chalk.bold.yellow(" Next up: ")+(e?chalk.bold.cyan("β sim")+chalk.gray(" β ")+chalk.bold.cyan("β’ demo2"):chalk.bold.cyan("β‘ sim arm")+chalk.gray(" β ")+chalk.bold.cyan("β’ demo2"))+chalk.gray(" β ")+chalk.bold.cyan("β£ learn LEARNDEMO01")):console.log(chalk.bold.yellow(" First time? Try in order: ")+chalk.bold.cyan("β sim")+chalk.gray(" β ")+chalk.bold.cyan("β‘ sim arm")+chalk.gray(" β ")+chalk.bold.cyan("β’ demo2")+chalk.gray(" β ")+chalk.bold.cyan("β£ learn LEARNDEMO01")),console.log(chalk.gray(" βββββββββββββββββββββββββββββββββββββββββββββ")),console.log(chalk.bold.green(" sim")+chalk.gray(" ")+chalk.bold.cyan("β ")+chalk.gray(" ")+chalk.bold.yellow("β
INSTANT")+chalk.gray(" β 9-robot group dance, no wait, no setup")),console.log(chalk.bold.green(" sim arm")+chalk.gray(" ")+chalk.bold.cyan("β‘")+chalk.gray(" interactive 6-DOF arm sandbox β type joint values, watch")),console.log(chalk.bold.green(" demo2")+chalk.gray(" ")+chalk.bold.cyan("β’")+chalk.gray(" ~8 min interactive intro + live MuJoCo sim")),console.log(chalk.bold.green(" learn LEARNDEMO01")+chalk.gray(" ")+chalk.bold.cyan("β£")+chalk.gray(" free 11-card intro (paste this command as-is)")),console.log(chalk.bold.green(" learn ")+chalk.bold.yellow("EA")+chalk.gray(" + 8 chars full 96 / 360 curriculum (team-issued)")),console.log(chalk.bold.green(" exam ")+chalk.bold.yellow("PDxxxxxxxx")+chalk.gray(" Paper D (CTF4EAI) β national selection contestants")),console.log(chalk.gray(" βββββββββββββββββββββββββββββββββββββββββββββ")),console.log(),console.log(chalk.gray(" Three open tiers: ")+chalk.green("free 11")+chalk.gray(" Β· ")+chalk.yellow("registered 100")+chalk.gray(" Β· ")+chalk.bold.magenta("national team 480")+chalk.gray(" (PhD-ready)")),console.log(chalk.gray(" Country team contact: ")+chalk.cyan("australia@icoa2026.au")),console.log(),S(),console.log()}();else if("instant"===zo)console.log(chalk.cyan.bold(" [β‘ Try ICOA in 30 seconds β no token needed]")),console.log(),console.log(chalk.gray(" Three free tastes β just type the word and press Enter:")),console.log(),console.log(chalk.bold.green(" demo ")+chalk.gray(" Paper A/B/C taste β 10 MCQs, no timer ")+chalk.bold.cyan("π― selection-style")),console.log(chalk.bold.green(" demo2 ")+chalk.gray(" Embodied-AI mini-demo β robots & MuJoCo ")+chalk.bold.yellow("π€ hands-on")),console.log(chalk.bold.green(" kaggle")+chalk.gray(" ML practice β train a model, real board ")+chalk.bold.magenta("π data-science")),console.log(),console.log(chalk.gray(" Type ")+chalk.bold.cyan("demo")+chalk.gray(", ")+chalk.bold.cyan("demo2")+chalk.gray(" or ")+chalk.bold.cyan("kaggle")+chalk.gray(" to start Β· ")+chalk.bold.cyan("menu")+chalk.gray(" to go back Β· ")+chalk.bold.cyan("quit")+chalk.gray(" to exit")),console.log(),y({mode:"selection"}),zo="selection";else{if("learn"===zo){console.log(chalk.cyan.bold(" [π§ Learn]")),console.log();const o=await(async()=>{try{const o=await import("./lib/learn-state.js");return{sessions:o.listLearnSessions(),listMax:o.CONTINUE_LIST_MAX}}catch{return{sessions:[],listMax:5}}})(),t=o.sessions,l=o=>/^[A-Z]{2}[A-Z0-9]{8}$/i.test(o)?`${o.slice(0,2)}β’β’β’β’β’β’${o.slice(-2)}`:o,a=o=>{const e=new Date(o);if(Number.isNaN(e.getTime()))return"";const t=o=>new Date(o.getFullYear(),o.getMonth(),o.getDate()).getTime(),n=Math.round((t(new Date)-t(e))/864e5);return n<0?"":0===n?"today":1===n?"yesterday":n<30?`${n} days ago`:"a while back"},s=e=>{const n=e?t:t.slice(0,o.listMax),s=o=>Math.max(...n.map(e=>o(e).length)),r=s(o=>o.curriculumId),i=s(o=>`card ${o.currentCard}/${o.totalCards}`),c=s(o=>a(o.lastSeenAt));return n.forEach((o,e)=>{const t=o.token===o.curriculumId?"":` ${l(o.token)}`;console.log(chalk.green(` ${e+1} `)+chalk.bold.white(o.curriculumId.padEnd(r))+chalk.gray(` ${`card ${o.currentCard}/${o.totalCards}`.padEnd(i)} ${a(o.lastSeenAt).padEnd(c)}${t}`))}),n.length};if(1===t.length){const o=t[0],e=a(o.lastSeenAt);console.log(chalk.green(" βΈ Continue ")+chalk.bold.white(o.curriculumId)+chalk.gray(` Β· card ${o.currentCard}/${o.totalCards}${e?` Β· ${e}`:""} Β· ${l(o.token)}`)),console.log(chalk.gray(" type ")+chalk.bold.green("c")+chalk.gray(" or ")+chalk.bold.green("continue")+chalk.gray(" to resume Β· Enter to go back")),console.log()}else if(t.length>1){console.log(chalk.green(" βΈ Continue"));const o=s(!1);t.length>o&&console.log(chalk.gray(` +${t.length-o} more β type `)+chalk.bold.green("c all")+chalk.gray(" to list them")),console.log(chalk.gray(" type ")+chalk.bold.green("c")+chalk.gray(" to resume 1 Β· ")+chalk.bold.green("c 2")+chalk.gray(" to switch Β· Enter to go back")),console.log()}{const{doorStoryLines:o,doorWelcomeLines:e,fetchProfilesForLocalTokens:n}=await import("./lib/learn-door.js"),{learnW:l}=await import("./lib/learn-render.js");let a=null;if(t.find(o=>/^[A-Z]{2}[A-Z0-9]{8}$/i.test(o.token)&&!/DEMO01$/i.test(o.token))){const s=await n(t.map(o=>o.token)),r=s[0]??null,i=new Set(s.flatMap(o=>o.tokens.filter(o=>o.credits?.completed).map(o=>o.curriculum_id))).size;a=r?o(r,l(),i):e(l(),!0)}else a=e(l(),!1);for(const o of a)console.log(o);try{const{pythonDoorLine:o}=await import("./lib/python-setup.js"),{detectCaps:e}=await import("./lib/render-card.js"),t=(m().language||"en").toLowerCase().startsWith("zh");console.log(o(t,"T0"===e().tier))}catch{}console.log()}try{const{input:o}=await import("@inquirer/prompts"),{resolveLearnInput:n}=await import("./lib/learn-input.js");console.log(chalk.gray(" Enter a token (or just press Enter to go back).")),console.log();const l=async()=>{try{await o({message:chalk.bold.yellow("Press Enter to return to the menu"),theme:{prefix:"",style:{message:o=>o}}})}catch{}},a=3;for(let r=1;r<=a;r++){const i=await o({message:chalk.bold.cyan("icoa learn>"),theme:{prefix:"",style:{message:o=>o}}}),c=i.trim().toLowerCase();if("ai4ioai"===c||"/ai4ioai"===c){const{runAi4ioaiStandalone:o}=await import("./commands/ai4ioai.js");return await o(),await l(),y({mode:"selection"}),void T()}if(P(i)){const{runMicroduck:o}=await import("./commands/microduck.js");return await o(),await l(),y({mode:"selection"}),void T()}if(["pandahelpme31","/pandahelpme31","panda help me 31","pandahelpme"].includes(c)){const{runSprint:o}=await import("./commands/sprint.js");return await o(),y({mode:"selection"}),void T()}if("wm"===c||"/wm"===c||c.startsWith("wm ")){const{runWm:o}=await import("./commands/wm.js");return await o(i.trim().split(/\s+/).slice(1).join(" ")||void 0),y({mode:"selection"}),void T()}if("ioailab"===c||"/ioailab"===c){const{runIoailabStandalone:o}=await import("./commands/ioailab.js");return await o(),await l(),y({mode:"selection"}),void T()}if("me"===c||"/me"===c||"profile"===c||"/profile"===c){const o=t.find(o=>/^[A-Z]{2}[A-Z0-9]{8}$/i.test(o.token)&&!/DEMO01$/i.test(o.token));if(o){const{fetchLearnProfile:e,renderLearnProfile:t}=await import("./lib/learn-profile.js"),{learnW:n}=await import("./lib/learn-render.js");console.log(chalk.gray(` Loading your profile (${o.token.slice(0,2)}β’β’β’β’β’β’${o.token.slice(-2)})β¦`));const l=await e(o.token);"ok"===l.kind?t(l.profile,!1,n(),"prompt"):"offline"===l.kind?console.log(chalk.yellow(" Cannot reach the learn server β try me again online.")):console.log(chalk.yellow(` ${"demo"===l.kind?"No profile for a demo token":l.message}`)),console.log()}else console.log(),console.log(chalk.yellow(" No profile yet β open a course with your token first, then type me.")),console.log();r--;continue}const g=c.match(/^\/?python(?:3)?(?:\s+(setup|install|status))?$/);if(g){const{runSetup:o,printStatus:e}=await import("./commands/python.js");"setup"===g[1]||"install"===g[1]?await o():e(),r--;continue}const m=c.match(/^\/?m[ou]joco(?:\s+(setup|install|status))?$/);if(m){const{runMujocoSetup:o,printMujocoStatus:e}=await import("./commands/mujoco.js");"setup"===m[1]||"install"===m[1]?await o():e(),r--;continue}const d=c.match(/^\/?(certificate|certificates|cert)(?:\s+(\S+))?$/);if(d){const{certificateLines:e,dropProfileCache:n}=await import("./lib/learn-door.js"),{certifiable:l,certificateIntroLines:a,sameName:s,issueCertificate:i,announceCertificate:c}=await import("./lib/learn-certificate.js"),{fetchProfilesForLocalTokens:g}=await import("./lib/learn-door.js"),m=await g(t.map(o=>o.token)),y=m[0]??null,u=new Set,p=m.flatMap(o=>l(o)).filter(o=>!u.has(o.curriculum_id)&&u.add(o.curriculum_id)),h=(d[2]??"").toLowerCase();console.log();const f=h?p.find(o=>o.curriculum_id.toLowerCase()===h||o.curriculum_id.toLowerCase().startsWith(h)):1===p.length?p[0]:void 0;if(0===p.length||!f&&!h){for(const o of e(y,!1))console.log(o);p.length>1&&console.log(chalk.gray(" type ")+chalk.bold.green("certificate <track>")+chalk.gray(" to issue one.")),console.log(),r--;continue}if(!f){console.log(chalk.yellow(` No finished track matches "${h}". `)+chalk.gray("Finished: "+p.map(o=>o.curriculum_id).join(", "))),console.log(),r--;continue}for(const o of a(f,!1))console.log(o);console.log();const w=async e=>(await o({message:chalk.bold.cyan(e),theme:{prefix:"",style:{message:o=>o}}})).trim(),b=await w("Name on the certificate:");if(!b){console.log(chalk.gray(" Cancelled β nothing issued.")),console.log(),r--;continue}if(!s(b,await w("Type it once more:"))){console.log(chalk.yellow(" The two names differ β nothing issued. Type certificate to try again.")),console.log(),r--;continue}console.log(chalk.gray(" Issuingβ¦ (the name is sent once, never stored)")),c(await i(f.token,f.curriculum_id,b),!1),n(),r--;continue}const u=c.match(/^\/?(story|credits)(?:\s+(\S+))?$/);if(u){const{fetchLearnProfile:o}=await import("./lib/learn-profile.js"),{buildCreditLines:e,rollCredits:n,storyListLines:l}=await import("./lib/learn-credits.js"),{learnW:a}=await import("./lib/learn-render.js"),s=t.find(o=>/^[A-Z]{2}[A-Z0-9]{8}$/i.test(o.token)&&!/DEMO01$/i.test(o.token));if(console.log(),s){const r=await o(s.token,"credits"===u[1]?"credits":"story");if("ok"!==r.kind)console.log(chalk.yellow(" Cannot reach the learn server β try story again online."));else{const o=(u[2]??"").toLowerCase(),s=r.profile;let i;if(o){const e=Number(o);i=Number.isInteger(e)&&e>=1&&e<=s.tokens.length?s.tokens[e-1]:s.tokens.find(e=>e.curriculum_id.toLowerCase()===o||e.curriculum_id.toLowerCase().startsWith(o))}else"credits"===u[1]&&(i=s.tokens.find(o=>o.credits?.completed));if(i){if(await n(e(i,s,i.curriculum_id,{},!1,a(),!1),()=>!1,180),i.credits?.completed&&!i.credits.credits_rolled_at){const{postCreditsRolled:o}=await import("./lib/learn-profile.js");o(i.token,i.curriculum_id)}}else{o&&console.log(chalk.yellow(` No story for "${o}".`));for(const o of l(s,!1))console.log(o);const e=new Set(s.tokens.map(o=>o.token.toUpperCase())),n=t.filter(o=>/^[A-Z]{2}[A-Z0-9]{8}$/i.test(o.token)&&!/DEMO01$/i.test(o.token)&&!e.has(o.token.toUpperCase()));n.length>0&&console.log(chalk.gray(` +${n.length} more course${1===n.length?"":"s"} on this computer not linked yet β open one and type `)+chalk.bold.green("link")+chalk.gray(" to join them."))}}}else console.log(chalk.yellow(" No story yet β open a course with your token first."));console.log(),r--;continue}const{FOCUS_LOG_RE:p,fetchFocusLog:h,renderFocusLog:f}=await import("./lib/learn-focus-log.js");if(p.test(c)){const o=t.find(o=>/^[A-Z]{2}[A-Z0-9]{8}$/i.test(o.token)&&!/DEMO01$/i.test(o.token));if(console.log(),o){const{detectCaps:e}=await import("./lib/render-card.js"),t=await h(o.token);if("ok"===t.kind)for(const o of f(t.log,!1,"T0"===e().tier,"Enter to go back"))console.log(o);else console.log(chalk.yellow("offline"===t.kind?" Offline β the focus log lives on the server; try again when connected.":"demo"===t.kind?" Demo tokens are shared β no focus log. Use your own token.":` Could not load the focus log: ${t.message}`));console.log()}else console.log(chalk.yellow(" No focus log yet β open a course with your token first, then type focus log.")),console.log();r--;continue}const w=c.match(/^\/?(focus|timer)(?:\s+(.*))?$/);if(w){const{FOCUS_MAX:o,FOCUS_MIN:e,FOCUS_STEP:t,getStudyTimer:n,parseFocusMinutes:l}=await import("./lib/learn-study-timer.js"),a=n(),s=(w[2]??"").trim();if(console.log(),a.showPending());else if("off"===s||"stop"===s||"end"===s||"cancel"===s)a.stop()?(await new Promise(o=>setTimeout(o,300)),a.showPending()):console.log(chalk.gray(" No focus session running. Start one: ")+chalk.bold.green("focus 30"));else if(a.active)console.log(chalk.yellow(" β± ")+chalk.white(`focus running Β· ${a.remainingMin()} min left`)+chalk.gray(" Β· paste a token and keep going, or ")+chalk.bold.green("focus off"));else if(""===s||"?"===s||"help"===s)console.log(chalk.bold.white(" β± Focus session")),console.log(chalk.gray(` How long? (${e}β${o}, steps of ${t}) e.g. `)+chalk.bold.green("focus 30")),console.log(chalk.gray(" Start it here, then open any course β every course you visit counts."));else{const n=l(s);if(n){if("ok"!==n.note){const l="min"===n.note?`min is ${e}`:"max"===n.note?`max is ${o}`:`rounded to the nearest ${t}`;console.log(chalk.gray(` you typed ${s} β ${l}, using ${n.min}`))}a.start(n.min),console.log(chalk.yellow(" β± ")+chalk.bold.white(`Focus ${n.min} min β go`)+chalk.gray(" Β· now paste your token (any course counts) Β· soft reminder every 10 min Β· end early: ")+chalk.bold.green("focus off"))}else console.log(chalk.yellow(` Didn't understand "${s}". `)+chalk.gray("Type minutes, e.g. ")+chalk.bold.green("focus 30"))}console.log(),r--;continue}if(/^(doctor|\/doctor)$/i.test(i.trim())){const{runDoctor:o}=await import("./commands/doctor.js");await o(),console.log(),console.log(chalk.gray(" Paste your token to try again, or press Enter to go back.")),console.log(),r--;continue}let b=n(i);if("back"===b.kind)break;if("continue"===b.kind){if(0===t.length){if(console.log(),console.log(chalk.yellow(" Nothing to continue β no previous session on this computer.")),console.log(chalk.gray(" Paste your cohort token to start.")),console.log(),r===a){await l();break}continue}const{which:o}=b;let e=t[0];if("all"===o){console.log(),s(!0),console.log(),r-=1;continue}if("number"==typeof o){if(o<1||o>t.length){if(console.log(),console.log(chalk.yellow(` You have ${t.length} course${t.length>1?"s":""} in progress β pick 1${t.length>1?`-${t.length}`:""}, or type part of its name.`)),console.log(),r===a){await l();break}continue}e=t[o-1]}else if("string"==typeof o){const n=t.filter(e=>e.curriculumId.toLowerCase().includes(o)||e.token.toLowerCase().includes(o));if(1!==n.length){if(console.log(),console.log(chalk.yellow(0===n.length?` No course in progress matches "${o}".`:` "${o}" matches ${n.length} of your courses β be more specific, or use its number.`)),console.log(),s(!0),console.log(),r===a){await l();break}continue}e=n[0]}b={kind:"token",token:e.token}}if("ambiguous"===b.kind||"unknown"===b.kind){if(console.log(),console.log(chalk.yellow(` ${b.hint}`)),console.log(),r===a){console.log(chalk.gray(` That was attempt ${a} of ${a} β going back to the menu.`)),console.log(chalk.gray(" Your token comes from your country team leader.")),console.log(),await l();break}continue}if(b.from){const{loadCurriculumById:o}=await import("./lib/learn-curricula.js");if(!await o(b.token,b.token)){if(console.log(),console.log(chalk.yellow(` "${b.from}" is not a token.`)),console.log(chalk.gray(" Paste the token your team leader gave you (2 letters + 8 characters).")),console.log(),r===a){await l();break}continue}}if(!/^[A-Z0-9]+DEMO01$/i.test(b.token)&&/^[A-Z]{2}[A-Z0-9]{8}$/i.test(b.token)){console.log(),console.log(chalk.gray(" Checking tokenβ¦"));const{validateEAToken:o}=await import("./lib/learn-curricula.js");let e=await o(b.token);if(!e.ok){const{normalizeTokenBody:t}=await import("./lib/token-format.js"),n=t(b.token);if(n!==b.token.trim().toUpperCase()){const t=await o(n);t.ok&&(console.log(chalk.yellow(` Corrected look-alike characters: ${b.token} β ${n}`)),e=t,b={...b,token:n})}}if(!e.ok){if(console.log(),console.log(chalk.red(` β Token check failed: ${e.message||"validation failed"}`)+(e.code?chalk.gray(` [${e.code}]`):"")),"device_bound"===e.code)console.log(chalk.gray(" This learn token is bound to the first computer it was used on,")),console.log(chalk.gray(" and this is a different computer. Ask the coordinator who issued")),console.log(chalk.gray(" it to move it to this device, then try again."));else if("expired"===e.code)console.log(chalk.gray(" This learn token has expired β ask your coordinator for a new one."));else if("network"===e.code){console.log(chalk.yellow(" Your token was not checked β this computer could not reach the ICOA server.")),console.log(chalk.gray(" (Your browser opening Google or practice.icoa2026.au does not count: icoa")),console.log(chalk.gray(" connects on its own, without the browser, and can be blocked separately.)")),console.log();for(const o of e.advice??[])console.log(chalk.gray(` ${o}`));(e.advice?.length??0)>0&&console.log(),console.log(chalk.gray(" βΈ Type ")+chalk.cyan("doctor")+chalk.gray(" right here β it names the exact fault and the fix.")),console.log(chalk.gray(" If it does not, send its output to your coordinator."))}else console.log(chalk.gray(" Possible causes:")),console.log(chalk.gray(" Β· Typo in token (check 0/O, 1/I/L, V/U)")),console.log(chalk.gray(" Β· Token expired or revoked"));if(console.log(),r<a){console.log(chalk.gray(" Try again β or press Enter to go back.")),console.log();continue}await l();break}}console.log(),console.log(chalk.gray(" Opening ")+chalk.bold.cyan("learn")+chalk.gray(`: ${b.token}`)),console.log(),y({mode:"selection"}),process.env.ICOA_LEARN_EMBEDDED="1";const{setLearnSessionStarted:k}=await import("./lib/learn-outcome.js");k(!1);try{await e.parseAsync(["node","icoa","learn",b.token])}catch(o){console.log(),console.log(chalk.red(` β learn failed to start: ${o instanceof Error?o.message:String(o)}`)),console.log()}finally{delete process.env.ICOA_LEARN_EMBEDDED}await l();break}}catch(o){n("learn-token-prompt-cancel",o instanceof Error?`${o.name}: ${o.message}`:String(o))}return y({mode:"selection"}),void T()}"organizer"===zo?(console.log(chalk.yellow.bold(" [National/Regional Partner]")),console.log(),console.log(chalk.bold.white(" βββ βββββββ βββββββ ββββββ")),console.log(chalk.bold.white(" ββββββββββββββββββββββββββββ")),console.log(chalk.bold.white(" ββββββ βββ βββββββββββ")),console.log(chalk.bold.white(" ββββββ βββ βββββββββββ")),console.log(chalk.bold.white(" βββββββββββββββββββββββ βββ")),console.log(chalk.bold.white(" βββ βββββββ βββββββ βββ βββ")),console.log(),console.log(chalk.yellow(" International Cyber Olympiad in AI 2026")),console.log(chalk.bold.magenta(" The World's First AI-Native CLI Operating System")),console.log(chalk.bold.magenta(" for Cybersecurity & AI Security Competition")),console.log(chalk.bold.magenta(" and Olympiad for K-12")),console.log(chalk.gray(" Sydney, Australia Β· Jun 27 - Jul 2, 2026")),console.log(),console.log(chalk.white(" Vision")),console.log(chalk.gray(" Building a global pipeline for youth cyber & AI")),console.log(chalk.gray(" security talent through education and competition.")),console.log(),console.log(chalk.white(" Capacity")),console.log(chalk.gray(" 15,000+ concurrent online examinations")),console.log(chalk.gray(" National selection, training, and education support")),console.log(),console.log(chalk.white(" Olympic Spirit")),console.log(chalk.gray(" Excellence Β· Friendship Β· Respect")),console.log(),console.log(chalk.gray(" βββββββββββββββββββββββββββββββββββββββββββββ")),console.log(chalk.white(" New country accreditation & support:")),console.log(chalk.cyan(" australia@icoa2026.au")),console.log(chalk.cyan(" accreditation@icoa2026.au")),console.log(chalk.gray(" βββββββββββββββββββββββββββββββββββββββββββββ")),console.log(),i?(console.log(chalk.green(` Logged in as ${r.userName}`)),console.log(chalk.white(" exam list")+chalk.gray(" Manage exams")),console.log(chalk.white(" logout")+chalk.gray(" Disconnect"))):console.log(chalk.white(" join <url>")+chalk.gray(" Connect to manage exams")),console.log(),S(),console.log()):(console.log(` ${chalk.cyan.bold("π ICOA 2026 Β· International Olympiad")}`),console.log(),d&&!x()?(console.log(chalk.red(" Token was activated on a different device.")),console.log(chalk.gray(" Contact organizer for assistance.")),console.log()):i?(console.log(chalk.green.bold(` Welcome back, ${r.userName}!`)),console.log(chalk.gray(` Connected to ${r.ctfdUrl}`)),console.log(chalk.gray(" Not you? Type ")+chalk.cyan("logout")+chalk.gray(" to switch accounts")),console.log(),console.log(chalk.gray(" βββββββββββββββββββββββββββββββββββββββββββββ")),console.log(chalk.white(" Ready to compete? Start here:")),console.log(),console.log(chalk.bold.cyan(" challenges")+chalk.gray(" Browse challenges by category")),console.log(chalk.white(" status")+chalk.gray(" Your score & timer")),console.log(chalk.white(" scoreboard")+chalk.gray(" Live rankings")),console.log(chalk.white(" memo")+chalk.gray(" Report an issue to organizers (one-way)")),console.log(),console.log(chalk.gray(" Tool environment:")),console.log(chalk.white(" env")+chalk.gray(" See which of the 110 CTF tools are installed")),console.log(chalk.white(" env setup")+chalk.gray(" Install anything missing (~5 min, one-time)")),console.log(chalk.bold.yellow(" β
")+chalk.bold.cyan("man <tool>")+chalk.gray(" How to USE a tool (steghide, nmapβ¦) Β· ")+chalk.cyan("man tools")+chalk.gray(" = list")),console.log(chalk.gray(" βββββββββββββββββββββββββββββββββββββββββββββ")),console.log(chalk.gray(" Tip: ")+chalk.cyan("help")+chalk.gray(" Β· ")+E()+chalk.gray(" Β· ")+chalk.cyan("Ctrl+C")+chalk.gray(" pauses Β· ")+chalk.cyan("quit")+chalk.gray(" closes")),console.log()):d?(Uo(Qo)||Ro(Qo,{recursive:!0}),console.log(chalk.green.bold(" Welcome, competitor!")),console.log(chalk.gray(` Workspace: ${Qo}`)),console.log(),console.log(chalk.gray(" βββββββββββββββββββββββββββββββββββββββββββββ")),console.log(chalk.white(" Get started:")),console.log(),console.log(chalk.white(" Step 1 ")+chalk.bold.cyan("join <url>")+chalk.gray(" Connect to competition server")),console.log(chalk.white(" Step 2 ")+chalk.bold.cyan("challenges")+chalk.gray(" Browse & solve challenges")),console.log(chalk.white(" Step 3 ")+chalk.bold.cyan("ai4ctf")+chalk.gray(" Ask AI when stuck")),console.log(),console.log(chalk.gray(" Before Step 1 β make sure your tools are ready:")),console.log(chalk.white(" env")+chalk.gray(" See which of the 110 CTF tools are installed")),console.log(chalk.white(" env setup")+chalk.gray(" Install anything missing (~5 min, one-time)")),console.log(chalk.bold.yellow(" β
")+chalk.bold.cyan("man <tool>")+chalk.gray(" How to USE a tool (steghide, nmapβ¦) Β· ")+chalk.cyan("man tools")+chalk.gray(" = list")),console.log(),console.log(chalk.gray(" Also: ")+chalk.white("help")+chalk.gray(" all commands")),console.log(chalk.gray(" βββββββββββββββββββββββββββββββββββββββββββββ")),console.log(chalk.gray(" Tip: ")+chalk.cyan("Ctrl+C")+chalk.gray(" pauses Β· ")+E()+chalk.gray(" Β· ")+chalk.cyan("quit")+chalk.gray(" closes CLI")),console.log()):(console.log(chalk.bold.yellow(" π You reached the finals tier.")),console.log(chalk.gray(" Full sandbox Β· 110 CTF tools Β· Sydney 2026 Β· this is where finalists compete.")),console.log(),console.log(chalk.gray(" βββββββββββββββββββββββββββββββββββββββββββββ")),console.log(chalk.white(" To begin, activate your competition token:")),console.log(),console.log(chalk.bold.cyan(" activate <token>")),console.log(),console.log(chalk.gray(" While waiting, explore:")),console.log(chalk.white(" ref linux")+chalk.gray(" Quick reference for Linux")),console.log(chalk.white(" ref web")+chalk.gray(" Quick reference for Web")),console.log(chalk.white(" env")+chalk.gray(" See which of the 110 CTF tools are installed")),console.log(chalk.white(" env setup")+chalk.gray(" Install anything missing (~5 min, one-time)")),console.log(chalk.white(" help")+chalk.gray(" All available commands")),console.log(chalk.gray(" βββββββββββββββββββββββββββββββββββββββββββββ")),console.log(chalk.gray(" Tip: ")+chalk.cyan("Ctrl+C")+chalk.gray(" pauses Β· ")+E()+chalk.gray(" Β· ")+chalk.cyan("quit")+chalk.gray(" closes CLI")),console.log()))}const ae=o=>{o.exitOverride(),o.configureOutput({writeErr:o=>{const e=o.replace(/^error:\s*/i,"").trim();e&&console.log(chalk.yellow(` ${e}`))},writeOut:o=>{console.log(o)}});for(const e of o.commands)ae(e)};ae(e);const se=o({input:process.stdin,output:process.stdout,prompt:Xo(),terminal:!0,completer:oe});O(se),$o(!1!==m().bracketedPaste);let re=!1;if(I(!0),vo(),s&&(console.log(),console.log(chalk.yellow(" β± A new competition day has started (Sydney time).")),console.log(chalk.gray(" For fairness, yesterdayβs sign-in has been cleared. Type ")+chalk.cyan("join <url>")+chalk.gray(" to sign in with your account.")),console.log()),Lo()){const o=m().userName||"this account";console.log(),console.log(chalk.yellow(" β This machine is signed in as ")+chalk.bold.white(o)+chalk.yellow(".")),console.log(chalk.gray(" Press ")+chalk.cyan("Enter")+chalk.gray(` to continue as ${o}, or type `)+chalk.cyan("logout")+chalk.gray(" to switch accounts.")),"logout"===(await new Promise(o=>{se.question(chalk.white(" > "),e=>o(e.trim()))})).toLowerCase()&&(y({ctfdUrl:"",token:"",sessionCookie:"",userId:null,userName:"",teamId:null,country:""}),console.log(),console.log(chalk.green(" β Logged out. ")+chalk.gray("Run ")+chalk.cyan("join <url>")+chalk.gray(" to sign in with your own account."))),console.log()}Oo()&&So(()=>se.prompt());let ie=null;const ce=se.prompt.bind(se);se.prompt=o=>{if(!(N()||_()||U()||q()||B()||Mo()||W()||(se.setPrompt(Xo()),o)))try{for(const o of lo()){const e="done"===o.status,t=o.cmd.length>40?`${o.cmd.slice(0,37)}β¦`:o.cmd,n=o.render?"":chalk.gray(" (")+chalk.white(t)+chalk.gray(") β ")+chalk.cyan(`tasks ${o.id}`);if(console.log((e?chalk.green(" β"):chalk.red(" β"))+chalk.white(` background task #${o.id} ${o.status}`)+n),o.render)try{o.render()}catch{}}const o=K();o&&o!==ie?(console.log(o),ie=o):o||(ie=null)}catch{}ce(o)};const ge=G();ge&&(console.log(chalk.cyan(" β» Continue where you left off: ")+chalk.white(ge.label)+(ge.urgent?chalk.yellow(" (exam timer running)"):"")),console.log(chalk.gray(" type ")+chalk.cyan("resume")+chalk.gray(" to jump back in.")),console.log()),se.prompt(),se.on("line",async o=>{if(re)return;let n=Io(o.trim());if(!n)return se.setPrompt(N()?chalk.magenta("icoa ai4ctf> "):Xo()),void se.prompt();if(/^icoa\s+\S/i.test(n)&&(n=n.replace(/^icoa\s+/i,"")),n.startsWith("/")&&!n.startsWith("//")){const o=n.slice(1).split(/\s+/)[0].toLowerCase(),t=n.slice(1+o.length).trim();if("ai"===o)return re=!0,await async function(o,e){if(N())return void(o?await D(o):console.log(chalk.gray(" You are already in the AI chat β just type your message.")));if(_())return void(o?await F(o):console.log(chalk.gray(" You are already in the CTF4AI target chat β just type your message.")));if(U())return void(o?await R(o):console.log(chalk.gray(" You are already in the Embodied-AI chat β just type your message.")));xo(o?`/ai ${o}`:"/ai");const t=process.exit;process.exit=()=>{throw new Error(Jo)};try{await e.parseAsync(["node","icoa","ai4ctf"])}catch(o){if(!(o instanceof Error&&o.message===Jo))throw o}finally{process.exit=t}o&&N()&&await D(o)}(t,e),re=!1,se.setPrompt(N()?chalk.magenta("icoa ai4ctf> "):Xo()),void se.prompt();!(N()||_()||U()||q()||B()||Mo())&&Go.includes(o)&&(n=n.slice(1))}if("resume"===n.toLowerCase()){const o=G();return o?(xo(`resume β ${o.command.join(" ")}`),re=!0,await ee(e),re=!1,se.setPrompt(N()?chalk.magenta("icoa ai4ctf> "):Xo()),void se.prompt()):(console.log(),console.log(chalk.gray(" Nothing to resume yet β start with ")+chalk.cyan("learn")+chalk.gray(" (curriculum) or ")+chalk.cyan("demo")+chalk.gray(" (taste).")),console.log(),void se.prompt())}const a=N()||_()||U()||q()||B();if(!a&&("bg"===n.toLowerCase()||/^bg\s/i.test(n))){const o=n.replace(/^bg\s*/i,"").trim();if(!o)return console.log(),console.log(chalk.gray(" Usage: ")+chalk.cyan("bg <command>")+chalk.gray(" β run a non-interactive shell command in the background.")),console.log(chalk.gray(" e.g. ")+chalk.cyan("bg nmap -p- 10.0.0.5")+chalk.gray(" Β· view: ")+chalk.cyan("tasks")),console.log(),void se.prompt();const e=ko(),t=wo(o);bo({cwd:e,input:`bg ${o}`,riskFlags:t}),t.length>0&&H()&&console.log(chalk.yellow(` β Action flagged: ${t.join(", ")} β logged.`));const l=oo(o,e);return console.log(),console.log(chalk.cyan(` βΈ background task #${l.id} started`)+chalk.gray(` (${so()} running)`)),console.log(chalk.gray(" ")+chalk.white(o)),console.log(chalk.gray(" view: ")+chalk.cyan("tasks")+chalk.gray(" Β· output: ")+chalk.cyan(`tasks ${l.id}`)),console.log(),void se.prompt()}if(!a&&("tasks"===n.toLowerCase()||/^tasks\s/i.test(n))){const o=n.replace(/^tasks\s*/i,"").trim(),e=to();if(console.log(),o){const e=no(Number(o));if(!e||Number.isNaN(Number(o)))console.log(chalk.yellow(` No background task #${o}.`)+chalk.gray(" Type ")+chalk.cyan("tasks")+chalk.gray(" to list them."));else{const o="running"===e.status?chalk.yellow:"done"===e.status?chalk.green:chalk.red;console.log(o(` #${e.id} [${e.status}]`)+chalk.white(` ${e.cmd}`)+(null!==e.exitCode?chalk.gray(` (exit ${e.exitCode})`):"")),console.log(chalk.gray(" βββββββββββββββββββββββββββββββββββββββββββββ"));const t=e.output.trim();if(t)for(const o of t.split("\n"))console.log(chalk.gray(" ")+chalk.white(o));else console.log(chalk.gray(" (no output yet)"))}}else if(0===e.length)console.log(chalk.gray(" No background tasks. Start one with ")+chalk.cyan("bg <command>")+chalk.gray("."));else{console.log(chalk.bold.white(" Background tasks"));for(const o of e){const e="running"===o.status?chalk.yellow("β"):"done"===o.status?chalk.green("β"):chalk.red("β"),t=Math.round(((o.endedAt??Date.now())-o.startedAt)/1e3),n=(o.endedAt?`${t}s`:`${t}sβ¦`).padStart(5),l=o.cmd.length>48?`${o.cmd.slice(0,45)}β¦`:o.cmd;console.log(` ${e} `+chalk.white(`#${o.id}`)+chalk.gray(` ${n} `)+chalk.white(l))}console.log(chalk.gray(" output: ")+chalk.cyan("tasks <id>"))}return console.log(),void se.prompt()}if(!a&&/&\s*$/.test(n)&&/^challenge\s+start\s+/i.test(n)){const o=n.replace(/\s*&\s*$/,"").trim().replace(/^challenge\s+start\s+/i,"").trim().split(/\s+/),e=o.some(o=>"-n"===o||"--new"===o),t=o.find(o=>"-n"!==o&&"--new"!==o);if(!t)return console.log(),console.log(chalk.gray(" Usage: ")+chalk.cyan("challenge start <id> &")),console.log(),void se.prompt();if(!g())return console.log(),console.log(chalk.red(" Not connected. ")+chalk.gray("Run ")+chalk.cyan("join <url>")+chalk.gray(" first.")),console.log(),void se.prompt();xo(`challenge start ${t}${e?" --new":""} & (background)`);const l=eo(`challenge start ${t}`,()=>ro(t,e),o=>io(t,o));return console.log(),console.log(chalk.cyan(` βΈ background task #${l.id}: `)+chalk.white(`starting ${t}`)+chalk.gray(" β you can keep working; the connection info appears here when it is ready.")),console.log(),void se.prompt()}if(!a&&n.startsWith("#")){const o=n.slice(1).trim();if(!o)return console.log(),console.log(chalk.gray(" Usage: ")+chalk.cyan("#<candidate answer>")+chalk.gray(" β stage a flag/answer WITHOUT submitting it. Review with ")+chalk.cyan("drafts")+chalk.gray(".")),console.log(),void se.prompt();const e=Q(),t=e?.session?.examId??null,l=e?e._lastQ||1:null,a=co(o,t,l);return xo(`draft #${a.id} (not submitted)`),console.log(),console.log(chalk.green(` β draft #${a.id} saved`)+(l?chalk.gray(` (Q${l})`):"")+chalk.yellow(" β NOT submitted.")),console.log(chalk.gray(" review with ")+chalk.cyan("drafts")+chalk.gray("; when sure, submit it the normal way.")),console.log(),void se.prompt()}if(!a&&("drafts"===n.toLowerCase()||/^drafts\s/i.test(n))){const o=n.replace(/^drafts\s*/i,"").trim().toLowerCase();if("clear"===o){const o=yo();return console.log(),console.log(chalk.gray(` Cleared ${o} draft${1===o?"":"s"}.`)),console.log(),void se.prompt()}const e=o.match(/^(?:rm|remove|del|delete)\s+(\d+)$/);if(e){const o=mo(Number(e[1]));return console.log(),console.log(o?chalk.gray(` Removed draft #${e[1]}.`):chalk.yellow(` No draft #${e[1]}.`)),console.log(),void se.prompt()}const t=Q(),l=go(t?.session?.examId??null);if(console.log(),0===l.length)console.log(chalk.gray(" No drafts yet. Stage a candidate with ")+chalk.cyan("#ICOA{maybe_this}")+chalk.gray(" β it wonβt submit."));else{console.log(chalk.bold.white(" Draft answers")+chalk.gray(" (staged β not submitted)"));for(const o of l){const e=o.q?chalk.cyan(`Q${o.q}`.padStart(4)):chalk.gray(" Β· ");console.log(chalk.gray(` #${o.id}`)+` ${e} `+chalk.white(o.text.length>56?`${o.text.slice(0,53)}β¦`:o.text))}console.log(chalk.gray(" remove: ")+chalk.cyan("drafts rm <id>")+chalk.gray(" Β· clear all: ")+chalk.cyan("drafts clear"))}return console.log(),void se.prompt()}if("menu"===n||"menu confirm"===n)return H()&&"menu confirm"!==n?(console.log(),console.log(chalk.yellow(" Real exam active. Progress is auto-saved.")),console.log(chalk.gray(" To return to main menu anyway, type ")+chalk.white("menu confirm")),console.log(),void se.prompt()):void T(se);if(N()){re=!0;const o=await D(n);return re=!1,"exit"===o&&se.setPrompt(Xo()),void se.prompt()}if(_()){re=!0;const o=await F(n);return re=!1,"exit"!==o&&"solved"!==o||se.setPrompt(Xo()),void se.prompt()}if(U()){re=!0;const o=await R(n);return re=!1,"exit"===o&&se.setPrompt(Xo()),se.setPrompt(U()?chalk.bold.cyan("icoa ctf4eai> "):Xo()),void se.prompt()}if(xo(n),"exit"===n)return Q()?(console.log(),console.log(chalk.yellow(" β An exam is in progress.")),console.log(chalk.white(" To return to menu without losing progress, type: ")+chalk.bold.cyan("back")),console.log(chalk.white(" To fully close ICOA CLI, type: ")+chalk.bold.cyan("quit")),console.log(chalk.gray(" Your progress is auto-saved either way.")),console.log(),void se.prompt()):(console.log(),console.log(chalk.gray(" ")+chalk.white("exit")+chalk.gray(" returns to the main menu. To fully close ICOA CLI, type ")+chalk.bold.cyan("quit")+chalk.gray(".")),"selection"===zo&&te(),void se.prompt());if("quit"===n||"q"===n||"quit confirm"===n){const o=Q();return o&&"demo-free"!==o.session.examId&&"quit confirm"!==n?(console.log(),console.log(chalk.yellow(" β A real exam is in progress.")),console.log(chalk.gray(" Your answers are auto-saved on the server, but the exam timer keeps ticking")),console.log(chalk.gray(" on the server side even if you close the CLI.")),console.log(),console.log(chalk.white(" To leave the CLI but keep the exam alive, type: ")+chalk.bold.cyan("back")),console.log(chalk.gray(" (recommended β you can resume with ")+chalk.cyan("exam q 1")+chalk.gray(" after relaunching icoa)")),console.log(),console.log(chalk.white(" To really close ICOA CLI, type: ")+chalk.bold.cyan("quit confirm")),console.log(),void se.prompt()):(o&&"demo-free"===o.session.examId&&(console.log(),console.log(chalk.gray(" Demo paused. Resume with: ")+chalk.white("demo")+chalk.gray(" (fresh) or ")+chalk.white("exam q 1")+chalk.gray(" (continue)."))),Co(),Ao(),Eo(),ao(),v(),console.log(chalk.gray(" Session saved. Use ")+chalk.white("icoa --resume")+chalk.gray(" to continue.")),uo(),void c(0))}if("back"===n){const o=Q(),e=o&&"demo-free"!==o.session.examId,t=o&&"demo-free"===o.session.examId&&(()=>{const e=new Date(o.session.startedAt||0).getTime();return Date.now()-e<18e5})();if(e)console.log(),console.log(chalk.gray(" Exam paused. Your progress is saved.")),console.log(chalk.white(" Resume: exam q 1")+chalk.gray(" Β· ")+chalk.white("exam review")+chalk.gray(" Β· ")+chalk.white("exam submit")),console.log();else if(t){const e=Object.keys(o.answers).length,t=o.session.questionCount;console.log(),console.log(chalk.gray(` Demo paused (${e}/${t} answered). Resume with: `)+chalk.white("exam q 1")),console.log(chalk.gray(" Or type ")+chalk.white("demo")+chalk.gray(" to restart.")),console.log()}else{if(o&&"demo-free"===o.session.examId){const{clearExamState:o}=await import("./lib/exam-state.js");o("demo-free")}const e=m();fetch("https://practice.icoa2026.au/api/icoa/demo-stats",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({type:"post-report-back",lang:e.language||"en",timestamp:(new Date).toISOString()}),signal:AbortSignal.timeout(5e3)}).catch(()=>{}),"selection"===zo?te():console.log(chalk.gray(" Already at main menu."))}return void se.prompt()}if("help"===n||"?"===n){if(Q()){re=!0;try{await e.parseAsync(["node","icoa","exam","help"])}catch{}return re=!1,void se.prompt()}return le(w(),zo),void se.prompt()}if("man"===n||"manual"===n)return le(w(),zo),console.log(),console.log(chalk.bold.yellow(" β
Stuck on a tool? ")+chalk.bold.cyan("man <tool>")+chalk.gray(" e.g. ")+chalk.cyan("man steghide")+chalk.gray(" Β· ")+chalk.cyan("man tools")+chalk.gray(" = full list")),void se.prompt();if(/^(?:man|manual)\s+\S/i.test(n))return M(n.replace(/^(?:man|manual)\s+/i,"")),void se.prompt();if("more help"===n.toLowerCase()&&Q()){re=!0;try{await e.parseAsync(["node","icoa","exam","more-help"])}catch{}return re=!1,void se.prompt()}if("continue"===n.toLowerCase())return console.log(),console.log(chalk.green.bold(" βββ AI4CTF β AI as Your Teammate βββ")),console.log(),console.log(chalk.white(" In AI4CTF, you solve cybersecurity challenges")),console.log(chalk.white(" with AI by your side.")),console.log(),console.log(chalk.white(" In this demo, your AI teammate gives help at 3 levels:")),console.log(chalk.yellow(" hint a")+chalk.gray(" General guidance")),console.log(chalk.yellow(" hint b")+chalk.gray(" Deep analysis")),console.log(chalk.yellow(" hint c")+chalk.gray(" Critical assist")),console.log(),console.log(chalk.white(" Try it now! Type: ")+chalk.bold.green("ai4ctf")),console.log(chalk.gray(' Chat freely with your AI teammate. Type "exit" when done.')),console.log(),console.log(chalk.gray(" After ai4ctf, try: ")+chalk.bold.red("ctf4ai")+chalk.gray(' β trick the AI into saying "koala"')),console.log(),void se.prompt();if(/^ICOA-[A-Z]{2,3}-\d{1,6}$/i.test(n.trim())){re=!0;try{await e.parseAsync(["node","icoa","exam","token",n.trim()])}catch{}return re=!1,void se.prompt()}if(/^[A-Z]{2}[0-9A-HJKMNP-TV-Z]{8}$/i.test(n.trim())){re=!0;try{await e.parseAsync(["node","icoa","exam","token",n.trim().toUpperCase()])}catch{}return re=!1,void se.prompt()}const s=n.match(/^exam\s+([A-Z]{2}[0-9A-HJKMNP-TV-Z]{8})$/i);if(s){re=!0;try{await e.parseAsync(["node","icoa","exam","token",s[1].toUpperCase()])}catch{}return re=!1,void se.prompt()}const r=n.match(/^exam\s+([A-Z]{2,3})$/i);if(r){re=!0;try{await e.parseAsync(["node","icoa","exam","list",r[1]])}catch{}return re=!1,void se.prompt()}const i=n.match(/^exam\s+(\S+)$/i);if(i&&!Ko.has(i[1].toLowerCase())){const o=i[1].toUpperCase(),{normalizeTokenBody:t}=await import("./lib/token-format.js"),n=t(o),l=/^[A-Z]{2}[0-9A-HJKMNP-TV-Z]{8}$/;if(console.log(),l.test(n)){console.log(chalk.yellow(` Corrected look-alike characters: ${o} β ${n}`)),re=!0;try{await e.parseAsync(["node","icoa","exam","token",n])}catch{}return re=!1,void se.prompt()}return console.log(chalk.red(` β Not a valid exam token: ${o}`)),console.log(),console.log(chalk.gray(" An exam token is ")+chalk.bold.white("2 letters + 8 characters")+chalk.gray(" (e.g. ")+chalk.bold.yellow("AUHXP7SWMM")+chalk.gray(`) β yours is ${o.length}.`)),console.log(chalk.gray(" Check for 0/O, 1/I/L, V/U mix-ups, or ask your country team leader.")),console.log(),console.log(chalk.gray(" No token yet? Try ")+chalk.bold.green("demo")+chalk.gray(" (free practice paper) or ")+chalk.bold.green("exam nations")+chalk.gray(" to see participating countries.")),console.log(),void se.prompt()}if("clear"===n||"cls"===n)return console.clear(),void se.prompt();if("news"===n)return Oo()?jo():console.log(chalk.gray(" No competition joined. Use ")+chalk.white("join <url>")+chalk.gray(".")),void se.prompt();if("memo"===n){if(!Oo())return console.log(chalk.gray(" Join a competition first: ")+chalk.white("join <url>")),void se.prompt();re=!0;try{await _o()}catch{}return void(re=!1)}const y=Do()||No(m().userName||"");if("jury"===n&&y){re=!0;try{await Fo()}catch{}return void(re=!1)}if(y&&Do()&&"scoreboard"===n.split(/\s+/)[0]){re=!0;try{const o=await Po();if(console.log(),0===o.length)console.log(chalk.gray(" Scoreboard is empty."));else{console.log(chalk.bold.white(" Scoreboard"));for(const e of o.slice(0,50))console.log(chalk.gray(` ${String(e.pos).padStart(3)}. `)+chalk.white(e.name.padEnd(28).slice(0,28))+chalk.cyan(String(e.score)))}console.log()}catch{}return re=!1,void se.prompt()}if(y&&Lo()){const o=n.split(/\s+/)[0];if(["challenges","open","submit","hint"].includes(o))return console.log(),console.log(chalk.yellow(" Team-leader account β the challenge bracket is not available here.")),console.log(chalk.gray(" Available: ")+chalk.white("scoreboard")+chalk.gray(" Β· ")+chalk.white("news")+chalk.gray(" Β· ")+chalk.white("jury")+chalk.gray(" Β· ")+chalk.white("time")+chalk.gray(" Β· ")+chalk.white("status")+chalk.gray(" Β· ")+chalk.white("logout")),console.log(),void se.prompt()}if(n.startsWith("activate ")){const o=n.slice(9).trim(),e=await b(o);return"ok"===e?console.log(chalk.green(" Access granted! Token bound to this device.")):"network"===e?(console.log(),console.log(chalk.red(" Could not reach the activation server.")),console.log(chalk.gray(" Activation needs internet once β check your connection to ")+chalk.cyan("practice.icoa2026.au")+chalk.gray(" and run the same command again."))):"already_bound"===e?(console.log(),console.log(chalk.red(" Token already activated on a different device.")),console.log(chalk.gray(" Each token binds to the first device that uses it. If you lost the device,")),console.log(chalk.gray(" contact your proctor to have the token re-issued for a new device."))):(console.log(),console.log(chalk.red(" Token not recognized.")),console.log(chalk.gray(" Possible reasons:")),console.log(chalk.white(" β’ ")+chalk.gray("Typo β access tokens are case-insensitive and look like ")+chalk.cyan("ICOA-XXXX-XXXX-XXXX")+chalk.gray(" (4-char hex groups, e.g. ICOA-385E-27F2-B21B)")),console.log(chalk.white(" β’ ")+chalk.gray("Expired β ask your proctor or organizer for a fresh token")),console.log(chalk.white(" β’ ")+chalk.gray("Network β verify connection to ")+chalk.cyan("practice.icoa2026.au")),console.log(chalk.gray(" Still stuck? type ")+chalk.cyan("help")+chalk.gray(" or try ")+chalk.cyan("exam demo")+chalk.gray(" for a free practice round."))),console.log(),void se.prompt()}if("activate"===n)return console.log(chalk.gray(" Usage: ")+chalk.white("activate <token>")),console.log(),void se.prompt();const d=Q();if(d){const o=n.toUpperCase().trim(),t=o=>{const e=d.questions.find(e=>e.number===o);return!!e&&("ai4ctf"===e.type||"ctf4ai"===e.type||e.options&&!e.options.A&&!e.options.B)},l=o=>{const e=d.questions.find(e=>e.number===o);return"short_answer"===e?.type},a=o=>{const e="demo-free"!==d.session.examId,t=d.questions.find(e=>e.number===o),n=V(t?.type,e);console.log(),console.log(chalk.yellow(` Q${o} is a practical question β letters (A/B/C/D) don't apply here.`)),n?(console.log(chalk.white(" Enter the AI chat for this question: ")+chalk.bold.cyan(n)),console.log(chalk.gray(" Or submit a flag directly: ")+chalk.green(`exam answer ${o} ICOA{your_flag}`))):console.log(chalk.gray(" Submit a flag: ")+chalk.green(`exam answer ${o} ICOA{your_flag}`)),console.log()};if(/^[ABCDE]$/.test(o)){const n=d._lastQ||1;if(t(n))return a(n),void se.prompt();if(l(n))return console.log(),console.log(chalk.yellow(` Q${n} is a short-answer question β type a number, not a letter.`)),console.log(chalk.gray(" Example: ")+chalk.green("42")+chalk.gray(" (or ")+chalk.green(`exam answer ${n} 42`)+chalk.gray(")")),console.log(),void se.prompt();re=!0;try{await e.parseAsync(["node","icoa","exam","answer",String(n),o])}catch{}return re=!1,void se.prompt()}if(/^-?\d+$/.test(o)){const t=d._lastQ||1;if(l(t)){re=!0;try{await e.parseAsync(["node","icoa","exam","answer",String(t),o])}catch{}return re=!1,void se.prompt()}}const s=o.match(/^(\d+)\s+([ABCDE]|-?\d+)$/);if(s){const o=parseInt(s[1],10);if(t(o))return a(o),void se.prompt();re=!0;try{await e.parseAsync(["node","icoa","exam","answer",s[1],s[2]])}catch{}return re=!1,void se.prompt()}}const u=n.split(/\s+/)[0].toLowerCase(),p=/^python3?(\.\d+)?$/.test(u),h="ls"===u||"pwd"===u||"tmux"===u,f=n.startsWith("!")||u.startsWith("!")||p||h,C=new Set(["nano","vi","vim","emacs","pico","ed","code","cat","less","more","head","tail","ls","pwd","cd","base64","xxd","hexdump","od","openssl","md5sum","sha256sum","grep","find","awk","sed","strings","file","curl","wget","nc","ping","nmap","echo","bash","sh","zsh","pip","pip3","node","npm"]),$=()=>{console.log(chalk.gray(" Shell commands need ")+chalk.bold.cyan("!")+chalk.gray(" prefix. Try: ")+chalk.bold.cyan(`!${n}`)),console.log()};if("py"===u||"pylist"===u)return console.log(chalk.yellow(` ${u} is the learn-card Python scratchpad β it lives inside learn.`)),console.log(chalk.gray(" Open your course first: ")+chalk.bold.cyan("learn <TOKEN>")+chalk.gray(" (or bare ")+chalk.bold.cyan("learn")+chalk.gray(" for the demo), then type ")+chalk.bold.cyan("py"===u?"/py":"/pylist")+chalk.gray(" on any card.")),console.log(),void se.prompt();if("embodied"===zo&&!f&&!["doctor","type","demo2","learn","exam","ctf4eai","ctf4vla","eai","arena","lang","ref","env","aienv","ipynb","kaggle","teleload","pandahelpme31","microduck","guide","board","sim"].includes(u))return C.has(u)?($(),void se.prompt()):(console.log(chalk.gray(" Not available in Embodied AI Security mode.")),console.log(chalk.white(" Try ")+chalk.bold.cyan("demo2")+chalk.gray(" (intro) Β· ")+chalk.bold.cyan("learn")+chalk.gray(" (curriculum) Β· ")+chalk.bold.cyan("exam <PD-token>")+chalk.gray(" (Paper D)")),console.log(),void se.prompt());if("selection"===zo&&!f&&!["doctor","type","battle","duck","python","mujoco","mojoco","exam","demo","demo2","demo4","demo5","gfssm","retry","nations","next","prev","continue","lang","ref","ai4ctf","ctf4ai","mark","unmark","review","submit","env","aienv","ipynb","kaggle","teleload","pandahelpme31","microduck","gpufortask","guide","board","sim"].includes(u)){if(C.has(u))return $(),void se.prompt();if(l().includes(u))console.log(chalk.gray(` ${u} isn't available on this screen.`));else{console.log(chalk.yellow(` Unknown command: ${u}`));const o=nearestCommand(u);o&&console.log(chalk.gray(" Did you mean: ")+chalk.bold.cyan(o)+chalk.gray("?"))}if(d){const o=d._lastQ||1;console.log(chalk.white(` Resume exam: exam q ${o}`)+chalk.gray(" Β· ")+chalk.white("A/B/C/D")+chalk.gray(" to answer"))}else console.log(chalk.gray(" Try: ")+chalk.bold.cyan("learn <TOKEN>")+chalk.gray(" Β· ")+chalk.bold.cyan("exam <CC>xxxxxxxx")+chalk.gray(" Β· ")+chalk.bold.cyan("demo")+chalk.gray(" Β· ")+chalk.bold.cyan("help")+chalk.gray(" Β· ")+chalk.bold.cyan("menu"));return console.log(),void se.prompt()}if("organizer"===zo&&!["doctor","join","exam","demo","retry","next","prev","logout","lang","ref","ctf","mark","unmark","review","submit","tmux"].includes(u))return console.log(chalk.gray(" Not available in Organizer mode. Switch via: setup")),console.log(),void se.prompt();if(!("olympiad"!==zo||w()&&x()||k(u)))return console.log(chalk.yellow(" Restricted mode. ")+chalk.gray("Enter your access token:")),console.log(chalk.white(" activate <token>")),console.log(),console.log(chalk.gray(" Free commands: ")+chalk.white("ref [topic]")+chalk.gray(", ")+chalk.white("help")+chalk.gray(", ")+chalk.white("exit")),console.log(),void se.prompt();if(!l().includes(u)){if("tmux"===u)try{t("command -v tmux",{stdio:"ignore"})}catch{return console.log(chalk.yellow(" tmux is not installed yet.")),console.log(chalk.gray(" Install it with ")+chalk.bold.cyan("env setup")+chalk.gray(" (full toolkit) or ")+chalk.bold.cyan("darwin"===process.platform?"brew install tmux":"sudo apt install tmux")+chalk.gray(".")),console.log(),void se.prompt()}if(Ho.has(u))return console.log(chalk.yellow(` "${u}" is a shell command β the ICOA prompt isn't a shell.`)),console.log(chalk.gray(" In real-exam mode, prefix with ! to run inside the sandbox: ")+chalk.cyan(`!${n}`)),console.log(),void se.prompt();if(/(?:^|\s)(?:\/(?!home\/|Users\/|tmp\/)|\.\.\/|~\/)/.test(n)&&!n.startsWith("cd ")){const o=/(?:^|\s)\/(?!home\/\w+\/icoa-workspace|Users\/\w+\/icoa-workspace|tmp\/)/.test(n),e=/\.\./.test(n);if(o||e)return console.log(chalk.red(" Blocked: access outside workspace is not allowed.")),console.log(chalk.gray(` Workspace: ${Qo}`)),console.log(),void se.prompt()}let o=n.startsWith("!")?n.slice(1).trim():n;if("darwin"===process.platform){const e="/opt/homebrew/opt/python@3.12/bin/python3.12";o=o.replace(/^python3?\s/,`${e} `).replace(/^(python3|python)$/,e)}else if("win32"===process.platform){const e=(()=>{try{return t("py -3 --version",{stdio:["ignore","ignore","ignore"],timeout:1500}),"py -3"}catch{}return"python"})();o=o.replace(/^python3?(\.\d+)?\s/,`${e} `).replace(/^python3?(\.\d+)?$/,e)}else{const e=(()=>{try{return t("which python3.12",{stdio:"ignore"}),"python3.12"}catch{return"python3"}})();o=o.replace(/^python\s/,`${e} `).replace(/^python$/,e)}const e=ko(),l=wo(n);bo({cwd:e,input:n,riskFlags:l}),l.length>0&&H()&&(console.log(chalk.yellow(` β Action flagged: ${l.join(", ")} β logged.`)),console.log()),/^(\S*python3?(\.\d+)?)\s*$/.test(o)&&(o=`PYTHONSTARTUP="${function(){const o=Bo(Zo(),".icoa");Uo(o)||Ro(o,{recursive:!0});const e=Bo(o,"python-startup.py");let t="";if(Uo(e))try{t=qo(e,"utf-8")}catch{}return t!==Yo&&Wo(e,Yo),e}()}" ${o}`,console.log(),console.log(chalk.cyan(" βββββββββββββββββββββββββββββββββββββββββ")),console.log(chalk.bold.white(" Python ready β ICOA exam toolkit pre-loaded")),console.log(chalk.cyan(" βββββββββββββββββββββββββββββββββββββββββ")),console.log(),console.log(chalk.white(" Already imported: ")+chalk.gray("base64, struct, hashlib, re, json, binascii")),console.log(chalk.white(" Also available: ")+chalk.gray("requests, bs4, numpy, PIL.Image, AES, pad/unpad, xor, p32/u32/p64/u64")),console.log(),console.log(chalk.yellow(" Quick examples:")),console.log(chalk.gray(' base64.b64decode("aGVsbG8=") ')+chalk.gray("# decode base64")),console.log(chalk.gray(' bytes.fromhex("48656c6c6f") ')+chalk.gray("# hex β bytes")),console.log(chalk.gray(' "ICOA{x}".encode() ')+chalk.gray("# str β bytes")),console.log(chalk.gray(" [chr(c) for c in [73,67,79,65]] ")+chalk.gray("# ASCII codes")),console.log(chalk.gray(' xor(bytes.fromhex("0a2b"), b"IC") ')+chalk.gray("# pwntools XOR")),console.log(),console.log(chalk.gray(" Exit: ")+chalk.white("exit()")+chalk.gray(" or Ctrl-D")),console.log(chalk.cyan(" βββββββββββββββββββββββββββββββββββββββββ")),console.log()),re=!0;try{await fo()&&await po()?await ho(o,se):await ne(o,se,e)}catch{console.log(chalk.yellow(` Command failed: ${u}`))}return re=!1,console.log(),void se.prompt()}re=!0;const A=n.trim(),I=A.toLowerCase();let S,E=null,j="";if(d)if("submit"===I)E="final";else if(I.startsWith("submit ")){let o=A.slice(7).trim();/^submit\s+/i.test(o)&&(o=o.replace(/^submit\s+/i,"").trim()),o=o.replace(/^["'`]+|["'`]+$/g,"").trim(),o&&/^ICOA\{[^}]*\}?$/i.test(o)?(E="flag",j=o):o&&/^[ABCDE]$/i.test(o)&&(E="flag",j=o.toUpperCase())}else/^ICOA\{[^}]+\}$/i.test(A)&&(E="flag",j=A);S="final"===E?["exam","submit"]:"flag"===E?["exam","answer",String(d?._lastQ||1),j]:mapCommand(n);const O="ctf"===S[0]&&"join"===S[1];O&&se.pause(),process.exit=()=>{throw new Error(Jo)};try{await e.parseAsync(["node","icoa",...S])}catch(o){const e=o instanceof Error?o.message:String(o);if(e===Jo);else if(e.includes("commander.unknownCommand")){const o=nearestCommand(u.split(/\s+/)[0]||u);console.log(chalk.yellow(` Unknown command: ${u}.`)),o&&console.log(chalk.gray(" Did you mean: ")+chalk.bold.cyan(o)+chalk.gray("?")),console.log(chalk.gray(" Type ")+chalk.cyan("help")+chalk.gray(" for the full command list."))}else e.includes("commander.missingArgument")||"commander.missingArgument"===o?.code?"submit"===u||"flag"===u?(console.log(chalk.yellow(" Incomplete β usage: ")+chalk.cyan("submit <challenge#> <flag>")),console.log(chalk.gray(" Put the number AND the flag on one line, e.g. ")+chalk.cyan("submit 44 pecan{...}"))):(console.log(chalk.yellow(` Incomplete command: ${u}`)),console.log(chalk.gray(" Type ")+chalk.cyan("help")+chalk.gray(" for usage."))):e.includes("commander.")||(e.includes("fetch failed")||e.includes("ECONNREFUSED")||e.includes("ETIMEDOUT"))&&console.log(chalk.yellow(" Network error. Check your connection."))}finally{process.exit=c,re=!1,O&&se.resume()}N()?se.setPrompt(chalk.magenta("icoa ai4ctf> ")):_()?se.setPrompt(chalk.red("icoa ctf4ai> ")):U()&&se.setPrompt(chalk.bold.cyan("icoa ctf4eai> ")),console.log(),se.prompt()}),se.on("SIGINT",()=>{if(console.log(),N()||_())console.log(chalk.yellow(" Ctrl+C did not close ICOA CLI β you are still in the AI chat.")),console.log(chalk.white(" Type ")+chalk.bold.cyan("exit")+chalk.white(" to leave the chat and return to the menu."));else if(Q()){const o="demo-free"!==Q().session.examId;console.log(chalk.yellow(" Ctrl+C did NOT close ICOA CLI.")),console.log(chalk.gray(` Your ${o?"exam":"demo"} is paused and every answer is auto-saved.`)),console.log(),console.log(chalk.white(" Resume: ")+chalk.cyan("exam q 1")+chalk.gray(" Β· Back to menu: ")+chalk.cyan("back")+chalk.gray(" Β· Close CLI: ")+chalk.cyan(o?"quit confirm":"quit"))}else console.log(chalk.yellow(" Ctrl+C did not close ICOA CLI β you are still at the ")+chalk.cyan("icoa>")+chalk.yellow(" prompt.")),console.log(chalk.gray(" Keep typing β ")+chalk.cyan("help")+chalk.gray(" lists commands. (Only ")+chalk.cyan("quit")+chalk.gray(" or Ctrl+D actually close the CLI.)"));console.log(),se.prompt()}),se.on("close",()=>{n("main-rl-close",`stdin.isTTY=${!0===process.stdin.isTTY}`),console.log(),console.log(chalk.gray(" input closed β leaving icoa. Run icoa --resume to continue.")),Co(),Ao(),Eo(),ao(),v(),uo(),c(0)}),"1"===process.env.ICOA_AUTO_RESUME&&(delete process.env.ICOA_AUTO_RESUME,G()&&(re=!0,await ee(e),re=!1,se.setPrompt(N()?chalk.magenta("icoa ai4ctf> "):Xo()),se.prompt()))}function ne(o,t,n){return new Promise(l=>{const a=process.stdin,s=!!a.isTTY&&!!a.isRaw;if(t.pause(),a.isTTY&&"function"==typeof a.setRawMode)try{a.setRawMode(!1)}catch{}const r=e(o,{shell:!0,stdio:"inherit",cwd:n||process.cwd()}),i=()=>{if(a.isTTY&&"function"==typeof a.setRawMode&&s)try{a.setRawMode(!0)}catch{}To(),t.resume(),l()};r.on("close",e=>{if(127===e){const e=nearestCommand(o.trim().split(/\s+/)[0]??"");e&&console.log(chalk.gray(" Did you mean: ")+chalk.bold.cyan(e)+chalk.gray("?"))}i()}),r.on("error",i)})}export function mapCommand(o){const e=o.split(/\s+/),t=e[0].toLowerCase(),n=e.slice(1);if("aienv"===t&&["run","python","py"].includes((n[0]??"").toLowerCase()))return L(o);if(("submit"===t||"flag"===t)&&n.length>=2)return["ctf","submit",n[0],n.slice(1).join(" ").trim().replace(/^["'`]+|["'`]+$/g,"")];if("connect"===t&&n.length>=2){const e=L(o);return["connect",e[1]??n[0],e.slice(2).join(" ")]}return s(t,n)||[t,...n]}function le(o,e="olympiad"){if(console.log(),"selection"===e||"organizer"===e)return console.log(chalk.bold.white(" Exam")),console.log(chalk.white(" join <url> ")+chalk.gray("Connect to exam server")),console.log(chalk.white(" exam list ")+chalk.gray("Available exams")),console.log(chalk.white(" exam start <id> ")+chalk.gray("Begin an exam")),console.log(chalk.white(" exam q [n] ")+chalk.gray("View questions")),console.log(chalk.white(" exam answer <n> <X> ")+chalk.gray("Answer question")),console.log(chalk.white(" exam review ")+chalk.gray("Review all answers")),console.log(chalk.white(" exam submit ")+chalk.gray("Submit for grading")),console.log(chalk.white(" exam result ")+chalk.gray("View your score")),console.log(),console.log(chalk.bold.white(" System")),console.log(chalk.white(" ref [topic] ")+chalk.gray("Quick reference")),console.log(chalk.white(" setup ")+chalk.gray("Settings / switch mode")),console.log(chalk.white(" lang [code] ")+chalk.gray("Switch language")),console.log(chalk.white(" clear ")+chalk.gray("Clear screen")),console.log(chalk.white(" exit ")+chalk.gray("Quit")),void console.log();if(!o)return console.log(chalk.bold.yellow(" Restricted Mode β activate with a token to unlock all commands")),console.log(),console.log(chalk.white(" activate <token> ")+chalk.gray("Unlock full access")),console.log(chalk.white(" ref [topic] ")+chalk.gray("Quick reference")),console.log(chalk.white(" exit ")+chalk.gray("Quit")),void console.log();console.log(chalk.cyan(" βββββββββββββββββββββββββββββββββββββββββββββββ")),console.log(chalk.bold.white(" How it works")),console.log(),console.log(chalk.gray(" 1. Browse ")+chalk.white("challenges")+chalk.gray(" and pick one")),console.log(chalk.gray(" 2. ")+chalk.white("open <id>")+chalk.gray(" to read the challenge")),console.log(chalk.gray(" 3. Use ")+chalk.white("ai4ctf")+chalk.gray(" to chat with AI when stuck")),console.log(chalk.gray(" 4. ")+chalk.white("submit <id> <flag>")+chalk.gray(" to score points")),console.log(chalk.gray(" 5. Check ")+chalk.white("scoreboard")+chalk.gray(" to track your rank")),console.log(chalk.cyan(" βββββββββββββββββββββββββββββββββββββββββββββββ")),console.log();for(const o of["Competition","AI Teammate","Tools","System"]){console.log(chalk.bold.white(` ${o}`));for(const e of a(o))console.log(chalk.white(` ${e.label.padEnd(20)}`)+chalk.gray(e.text)),"System"===o&&"resume"===e.label&&console.log(chalk.white(" #<candidate> ")+chalk.gray("Stage a draft answer (never auto-submits)"));"Tools"===o&&console.log(chalk.white(" man <tool> ")+chalk.bold.yellow("β
")+chalk.gray("How to use a tool (steghide, nmapβ¦); ")+chalk.cyan("man tools")+chalk.gray(" = list. Bare ")+chalk.cyan("man")+chalk.gray(" = this list.")),console.log()}}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "icoa-cli",
|
|
3
|
-
"version": "2.19.
|
|
3
|
+
"version": "2.19.576",
|
|
4
4
|
"description": "ICOA CLI β AI-native competition runtime of the International Cyber Olympiad in AI: learn, practise, and compete in AI & cybersecurity from the terminal (AI4CTF Β· CTF4AI Β· CTF4EAI)",
|
|
5
5
|
"author": "Charlie Zhu",
|
|
6
6
|
"type": "module",
|