icoa-cli 2.19.191 → 2.19.193

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- function a0b(a,b){a=a-(-0x1*0x209d+0x3*-0x387+-0x2c2e*-0x1);const c=a0a();let d=c[a];if(a0b['quGvFs']===undefined){var e=function(i){const j='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let l='',m='';for(let n=-0x1498+0x2*-0xd76+0x2f84,o,p,q=0x22a5+-0xab9+0x1*-0x17ec;p=i['charAt'](q++);~p&&(o=n%(-0x1*0x14d2+-0xc6a*-0x1+0x16*0x62)?o*(-0x1608+0x97*-0x2d+0x30d3)+p:p,n++%(-0x3a5*-0x8+0x14bc+0xe4*-0x38))?l+=String['fromCharCode'](-0x310+0x1af+0x8*0x4c&o>>(-(0x763*-0x5+0x1bd1*0x1+0x124*0x8)*n&-0x2492+-0xa21+0x3*0xf93)):-0xfe9*-0x1+0x5*0x293+-0x1cc8){p=j['indexOf'](p);}for(let r=-0x76d+0x1992+-0x1225,s=l['length'];r<s;r++){m+='%'+('00'+l['charCodeAt'](r)['toString'](-0x1699+-0x1de*0x3+0x1c43))['slice'](-(-0x256f+-0x3e*-0x7f+-0x1d*-0x3b));}return decodeURIComponent(m);};a0b['ENprtF']=e,a0b['TzYqXi']={},a0b['quGvFs']=!![];}const f=c[-0x1*0x829+-0x1969+0x1*0x2192],g=a+f,h=a0b['TzYqXi'][g];return!h?(d=a0b['ENprtF'](d),a0b['TzYqXi'][g]=d):d=h,d;}(function(a,b){const v=a0b,c=a();while(!![]){try{const d=parseInt(v(0x113))/(0x923+-0x43*-0x35+-0x1701)+-parseInt(v(0xfe))/(-0x277*-0x4+-0x19de+-0x32*-0x52)*(-parseInt(v(0x104))/(0x2*0x30d+0xe8a*-0x1+-0x873*-0x1))+-parseInt(v(0x10f))/(0x43+-0x15b8+0xef*0x17)+parseInt(v(0x108))/(0xfc4+-0x14d1+0x512)*(-parseInt(v(0x10b))/(0x1c67+0x1*-0x23e9+-0x8*-0xf1))+parseInt(v(0x111))/(-0x23f0+-0x16d*0x19+0x479c*0x1)+parseInt(v(0x106))/(0x10*0x8+-0x87c+0x804)*(parseInt(v(0x101))/(0x1ae*0x2+0x589*-0x5+0x185a))+parseInt(v(0x10d))/(-0x1*-0x41b+0x1f92+0x3*-0xbe1)*(-parseInt(v(0xfc))/(0x318+0x252c+-0x2839));if(d===b)break;else c['push'](c['shift']());}catch(e){c['push'](c['shift']());}}}(a0a,-0xe948a+0x1*0x32911+0x18efe7));import{getConfig as a0c}from'./config.js';function a0a(){const x=['y3rMzfvYBa','nduYnJC2ogfJCgT3AG','zgf0yq','ode1mJG1mu9WD0DbBG','BMv0D29YAYbLCNjVCG','otqWmZm1uLjsyNrW','zxHHBuLK','C3rYAw5NAwz5','y2f0y2G','DgLTzw91De1Z','BwvZC2fNzq','C3vJy2vZCW','C3rHDhvZ','mtG4otK5ogrswurgCa','AgLUDcbYzxf1zxn0igzHAwXLzcaO','ng9yr0Tjqq','BgfUz3vHz2u','l2HPBNq','oxDIt2zcra','ue9tva','l2fWAs9Py29Hl2v4yw1ZlW','mJi0nda3mMLgsMD2uG','B2jQzwn0','odG1nZqYng52v3jPuG','oJKWotaVyxbPl2LJB2eVzxHHBxmV','mZm1vMLQyLvO','BgfUzW','Dg9Rzw4','mte3ody0qxfwCxvQ','ANnVBG','odb0uennthe'];a0a=function(){return x;};return a0a();}export async function requestHint(d){const w=a0b,f=a0c(),g=f[w(0x10e)]||'https://practice.icoa2026.au',h=d[w(0x109)]||f[w(0xff)]||'en',j=d[w(0x117)]??-0x20f3+0x25*-0x12a+0x6b45,k=[g+w(0x103)+d[w(0x114)]+w(0x100),g+w(0x107)+d['examId']+w(0x100)];let l=null;for(const p of k)try{const q=await fetch(p,{'method':w(0x102),'headers':{'Content-Type':'application/json','User-Agent':'icoa-cli'},'body':JSON[w(0x115)]({'token':d[w(0x10a)],'question':d['question'],'level':d['level'],'lang':h}),'signal':AbortSignal['timeout'](j)}),r=await q[w(0x10c)]()[w(0x116)](()=>({}));if(!q['ok']||!(0x22a5+-0xab9+0x1*-0x17eb)===r[w(0x119)]){if(l={'status':q['status'],'message':r?.[w(0x118)]||w(0xfd)+q[w(0x11a)]+')'},q[w(0x11a)]>=-0x1*0x14d2+-0xc6a*-0x1+0x16*0x74&&q[w(0x11a)]<-0x1608+0x97*-0x2d+0x3287)throw l;continue;}return r[w(0x110)];}catch(u){if(u&&w(0x105)==typeof u&&w(0x11a)in u)throw u;l={'status':0x0,'message':u?.[w(0x118)]||w(0x112)};}const m={};m[w(0x11a)]=0x0,m[w(0x118)]='hint\x20API\x20unreachable';throw l||m;}
1
+ (function(a,b){const v=a0b,c=a();while(!![]){try{const d=parseInt(v(0xd5))/(0x1*-0x2133+0x1ab1+-0x683*-0x1)+parseInt(v(0xe8))/(0x387+0x1a76+-0x1*0x1dfb)*(parseInt(v(0xe3))/(0x105c*-0x2+-0xe2*0xf+0x3*0xf53))+-parseInt(v(0xda))/(0x74d*0x3+-0x79*-0x1b+-0x22a6)*(-parseInt(v(0xcf))/(0x1e5c+0x2*-0x11bc+0x521))+-parseInt(v(0xce))/(-0x1946+-0x1*0x24a1+-0x3ded*-0x1)+parseInt(v(0xd8))/(0x72d*0x5+0x15*-0x165+0x1*-0x691)+-parseInt(v(0xe2))/(0x1463*-0x1+0x1f52+-0xae7*0x1)*(-parseInt(v(0xd0))/(0x2225+-0x2*0x827+-0x11ce))+parseInt(v(0xe1))/(0x259b+0xde5+-0x3376)*(-parseInt(v(0xd7))/(-0x1343*-0x1+0x117c+-0x24b4));if(d===b)break;else c['push'](c['shift']());}catch(e){c['push'](c['shift']());}}}(a0a,0x46f14+-0x76c24+0x8afc3));import{getConfig as a0c}from'./config.js';function a0a(){const x=['oJKWotaVyxbPl2LJB2eVzxHHBxmV','oda2otjTwvz0qKy','BgfUzW','BgfUz3vHz2u','AgLUDcbbueKGDw5YzwfJAgfIBgu','CxvLC3rPB24','B2jQzwn0','l2HPBNq','ndCYnJK3mej2CwPcva','mtuYohzJAxDcEa','m2HgBKHyqG','Bgv2zwW','BwvZC2fNzq','l2fWAs9Py29Hl2v4yw1ZlW','BMv0D29YAYbLCNjVCG','mtaXotb6tgXZDLC','zgf0yq','C3rHDhvZ','C3vJy2vZCW','ue9tva','Ahr0Chm6lY9WCMfJDgLJzs5Py29HmJaYnI5HDq','DgLTzw91Da','y2f0y2G','mtq2mtC1nMn0DfPYzW','mtvSDKj4Cem','mJCWD1fjwgjS','Dg9Rzw4','ANnVBG','zxHHBuLK','AwnVys1JBgK','nZa5mJq1rwDjzMjo','AgLUDcbYzxf1zxn0igzHAwXLzcaO','mtfZEgHOAw8','mJe2ndeYn3PRDM9ctW'];a0a=function(){return x;};return a0a();}function a0b(a,b){a=a-(0x902*-0x2+-0x632+-0xe*-0x1c9);const c=a0a();let d=c[a];if(a0b['YsefjK']===undefined){var e=function(i){const j='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let l='',m='';for(let n=-0xdff+0x135b+-0x7*0xc4,o,p,q=-0x10f1*0x1+-0x23f2+0x34e3;p=i['charAt'](q++);~p&&(o=n%(-0x1*0x160c+-0x26*-0x6f+0x596)?o*(0x6fa+-0x4d7+0x15*-0x17)+p:p,n++%(0x2*-0x7aa+0x2519+0x1*-0x15c1))?l+=String['fromCharCode'](0x883*-0x1+0x26e5+-0x1d63&o>>(-(-0x442+0x1f0d*0x1+-0x1ac9*0x1)*n&0xc33+-0x1*0x1e79+-0x493*-0x4)):-0x3f5*0x3+-0x10*0x61+0x11ef*0x1){p=j['indexOf'](p);}for(let r=0x2a7*0x1+-0x142e+0x1*0x1187,s=l['length'];r<s;r++){m+='%'+('00'+l['charCodeAt'](r)['toString'](-0x1*0x163d+-0x645+-0xe49*-0x2))['slice'](-(-0xe*0xa9+-0x94f+0x128f));}return decodeURIComponent(m);};a0b['vzfDwT']=e,a0b['MXVUuQ']={},a0b['YsefjK']=!![];}const f=c[-0x17fa+0x2e*-0x28+0x1f2a],g=a+f,h=a0b['MXVUuQ'][g];return!h?(d=a0b['vzfDwT'](d),a0b['MXVUuQ'][g]=d):d=h,d;}export async function requestHint(d){const w=a0b,f=a0c(),g=f['ctfdUrl']||w(0xcb),h=d[w(0xdb)]||f[w(0xdc)]||'en',j=d['timeoutMs']??0x1ef7+-0x6*0x351+0x142f,k=[g+w(0xe6)+d[w(0xd3)]+w(0xe0),g+w(0xd9)+d[w(0xd3)]+w(0xe0)];let l=null;for(const p of k)try{const q=await fetch(p,{'method':w(0xca),'headers':{'Content-Type':'application/json','User-Agent':w(0xd4)},'body':JSON['stringify']({'token':d[w(0xd1)],'question':d[w(0xde)],'level':d[w(0xe4)],'lang':h}),'signal':AbortSignal[w(0xcc)](j)}),r=await q[w(0xd2)]()[w(0xcd)](()=>({}));if(!q['ok']||!(-0x23f2+0x1d0f+0x6e4)===r[w(0xc9)]){if(l={'status':q[w(0xc8)],'message':r?.['message']||w(0xd6)+q[w(0xc8)]+')'},q[w(0xc8)]>=-0x1*0x160c+-0x26*-0x6f+0x722&&q[w(0xc8)]<0x6fa+-0x4d7+0x1*-0x2f)throw l;continue;}return r[w(0xe9)];}catch(u){if(u&&w(0xdf)==typeof u&&w(0xc8)in u)throw u;l={'status':0x0,'message':u?.[w(0xe5)]||w(0xe7)};}const m={};m[w(0xc8)]=0x0,m['message']=w(0xdd);throw l||m;}
@@ -1 +1 @@
1
- export function localized(e,t){if(!t.startsWith("zh")||!e._zh)return e;const a=e._zh,o={...e};for(const e of Object.keys(a))void 0!==a[e]&&(o[e]=a[e]);return o}export const CURRICULUM_DEMO={id:"LEARNDEMO01",name:"Embodied AI Security — Demo",description:"An 11-card taster of the full ICOA Embodied AI Security curriculum.",totalCards:11,modules:[{number:1,name:"Foundations & Attack Surfaces",cardRange:[1,11]}],cards:[{number:1,module:1,type:"knowledge",title:"What is a Vision-Language-Action (VLA) model?",body:["A VLA model is an AI system that takes BOTH a camera image AND a natural-language instruction, then outputs a sequence of motor actions for a robot.",'Example: image of a kitchen + "pick up the red cup" → action sequence (move arm 30 cm right, lower 10 cm, close gripper).',"VLAs are the dominant architecture for general-purpose robot control as of 2024-2026. They're trained on millions of robot demonstrations."],icoaConnection:"ICOA Paper D uses ICOA-VLA — a compact research-grade VLA. You'll attack it in Q41-45 of this exam.",_zh:{title:"什么是视觉-语言-动作 (VLA) 模型?",body:["VLA 模型是一种 AI 系统:同时接收 摄像头图像 + 自然语言指令,然后输出一连串机器人电机动作。",'举例:厨房的图像 + "pick up the red cup" → 动作序列 (机械臂右移 30 cm,下降 10 cm,夹爪闭合)。',"2024–2026 年,VLA 是通用机器人控制的主流架构,基于数百万机器人示范数据训练。"],icoaConnection:"ICOA Paper D 用的就是 ICOA-VLA —— 一个紧凑的研究级 VLA。本试卷的 Q41-45 你会亲手攻击它。"}},{number:2,module:1,type:"knowledge",title:"VLA Architecture = Three Modules",body:["Almost every VLA shares the same structure:"," ① Vision encoder converts image → visual features (e.g. SigLIP, DINOv2)"," ② Language encoder converts instruction → text features (e.g. Llama tokenizer)"," ③ Action head fuses features → 7-DoF action (xyz + rotation + gripper)","The three modules are trained END-TO-END on robot demonstration data. None of them sees the world the way a human does."],_zh:{title:"VLA 架构 = 三个模块",body:["几乎所有 VLA 共享同一种结构:"," ① 视觉编码器 图像 → 视觉特征 (如 SigLIP, DINOv2)"," ② 语言编码器 指令 → 文本特征 (如 Llama tokenizer)"," ③ 动作头 融合特征 → 7-DoF 动作 (xyz + 旋转 + 夹爪)","三个模块在机器人示范数据上 端到端 联合训练。它们看世界的方式跟人类完全不同。"]}},{number:3,module:1,type:"knowledge",title:"Famous VLA Models (2024-2026)",body:["OpenVLA (Stanford+TRI, 2024) 7B params · Llama2 + DINOv2 + SigLIP","ICOA-VLA (internal, 2024) compact · Diffusion transformer, small + fast","π0 / π0.5 (Physical Intelligence) 3.5B · Flow matching, recent open-weights","RT-2 (Google DeepMind) 55B (est) · Closed weights, paper only","Gemini Robotics (DeepMind, 2025) ? · Closed, multimodal foundation","","The open ones (top 3) are the targets we attack in CTF challenges. Closed ones we only study in case studies."],_zh:{title:"知名 VLA 模型 (2024-2026)",body:["OpenVLA (Stanford+TRI, 2024) 7B 参数 · Llama2 + DINOv2 + SigLIP","ICOA-VLA (内部, 2024) 紧凑 · Diffusion transformer, 小且快","π0 / π0.5 (Physical Intelligence) 3.5B · Flow matching, 近期开源权重","RT-2 (Google DeepMind) 55B (估) · 闭源权重,只有论文","Gemini Robotics (DeepMind, 2025) ? · 闭源,多模态基础模型","","开源的 (前 3 个) 是 CTF 挑战里攻击的目标。闭源的我们只在 case study 里学。"]}},{number:4,module:1,type:"mcq",title:"Quick Check — Identify the VLA",question:"Which of these is NOT a Vision-Language-Action model?",options:{A:"OpenVLA",B:"ICOA-VLA",C:"GPT-4",D:"π0 (Physical Intelligence)"},answer:"C",explanation:"GPT-4 is a Language Model (LLM) — it takes text in, gives text out. No image input, no robot action output. The other three all consume (image, instruction) and emit motor actions.",_zh:{title:"快速测验 —— 找出非 VLA",question:"下面哪个 不是 视觉-语言-动作模型?",options:{A:"OpenVLA",B:"ICOA-VLA",C:"GPT-4",D:"π0 (Physical Intelligence)"},explanation:"GPT-4 是大语言模型 (LLM) —— 文本进,文本出。没有图像输入,也没有机器人动作输出。其他三个都接收 (图像, 指令) 然后输出电机动作。"}},{number:5,module:1,type:"knowledge",title:"VLA Attack Surfaces — Six Categories",body:["Every VLA has the same six attack vectors:"," 1. Prompt injection twist the language input"," 2. Adversarial patch modify pixels in the camera image"," 3. Modality conflict image says X, text says Y → confuse the fusion"," 4. Backdoor trigger hidden activation pattern from training data"," 5. Action-space jailbreak push output to unsafe motion ranges"," 6. Embodied-reasoning hack exploit the planning/multi-step layer","","In ICOA Paper D, we test you on the first 3 (the most accessible).","The last 3 are PhD-level research topics — covered in the full curriculum (n=480)."],_zh:{title:"VLA 攻击面 —— 六大类",body:["每个 VLA 都有同样的六条攻击向量:"," 1. Prompt injection 修改语言输入"," 2. Adversarial patch 修改摄像头图像里的像素"," 3. Modality conflict 图像说 X,文本说 Y → 混淆融合"," 4. Backdoor trigger 训练数据里植入的隐藏激活模式"," 5. Action-space jailbreak 把输出推到不安全的动作范围"," 6. Embodied-reasoning hack 攻击规划 / 多步推理层","","ICOA Paper D 考你前 3 个 (最易上手)。","后 3 个是博士级研究课题 —— 在完整课程 (n=480) 里覆盖。"]}},{number:6,module:1,type:"knowledge",title:"Attack 1 — Prompt Injection",body:["The simplest VLA attack: change ONLY the text instruction, no pixels.","",'Baseline: "Pick up the red cup" → gripper closes on cup ✓','Injected: "Stop and release everything" → gripper opens, drops cup ✗',"","Why this works: VLAs trained on instruction-following data become extremely literal. They follow imperative commands even when they contradict context.","","The same trick was famous on LLMs (DAN, role-play attacks). The new twist: now the output is a PHYSICAL ACTION, not just text."],icoaConnection:"Q41 in your exam is exactly this — you'll craft a prompt to flip ICOA-VLA's gripper from CLOSE to OPEN.",_zh:{title:"攻击 1 —— Prompt Injection (提示注入)",body:["最简单的 VLA 攻击:只改文本指令,不动像素。","",'基线: "Pick up the red cup" → 夹爪在杯子上闭合 ✓','注入: "Stop and release everything" → 夹爪打开,杯子掉落 ✗',"","为什么这能成:VLA 在指令跟随数据上训练后,变得 极其字面。它会执行命令式指令,哪怕跟上下文矛盾。","","同样的招在 LLM 上很出名 (DAN, 角色扮演攻击)。新的关键点是:输出现在是 物理动作,不再是文本。"],icoaConnection:"你的 Q41 就是这个 —— 设计一段 prompt,让 ICOA-VLA 的夹爪从 CLOSE 翻成 OPEN。"}},{number:7,module:1,type:"mcq",title:"Quick Check — Pick the Pixel Attack",question:"Which attack vector modifies pixels in the camera image to fool the VLA?",options:{A:"Prompt injection",B:"Adversarial patch",C:"Backdoor trigger",D:"Action-space jailbreak"},answer:"B",explanation:"Adversarial patches add specially-crafted noise to image pixels. They're computed by backpropagating through the vision encoder to find perturbations that maximally shift the output. Both PROMPT injection (text) and BACKDOOR (training-time) work on different channels. Action-space attacks operate on the output, not input.",_zh:{title:"快速测验 —— 找出像素攻击",question:"哪种攻击向量是 通过修改摄像头图像的像素 来欺骗 VLA?",options:{A:"Prompt injection",B:"Adversarial patch",C:"Backdoor trigger",D:"Action-space jailbreak"},explanation:"Adversarial patches (对抗补丁) 在图像像素里加入精心构造的噪声。通过对视觉编码器做反向传播,找出能最大程度改变输出的扰动。Prompt injection 走文本通道; backdoor 是训练时埋下的; action-space 攻击操作的是输出而非输入。"}},{number:8,module:1,type:"knowledge",title:"Attack 2 — Adversarial Patches in the Physical World",body:['Famous 2018 paper: adding a small printed sticker to a stop sign made it misclassified as "speed limit 45" by self-driving car perception.',"","For VLAs, the equivalent attack:"," · Print a 5cm × 5cm patch with adversarial pattern"," · Stick it on the table or the cup"," · Robot's camera sees the patch, VLA outputs WRONG action","","Math behind it (FGSM, Fast Gradient Sign Method):"," x_adv = x + ε · sign( ∇_x L(model, x, target_action) )","","You compute the gradient pointing toward your DESIRED wrong action, then nudge the image in that direction. Tiny per-pixel changes, huge action-output change."],icoaConnection:"Q42 of your exam: design an adversarial patch that makes ICOA-VLA grasp the WRONG cup.",_zh:{title:"攻击 2 —— 物理世界里的对抗补丁",body:['2018 年著名论文:在停车牌上贴一张小贴纸,自动驾驶车感知系统就把它识别成 "speed limit 45"。',"","对 VLA,等价的攻击是:"," · 打印一个 5cm × 5cm 的对抗图案"," · 贴在桌子或杯子上"," · 机器人摄像头看到补丁,VLA 输出 错误的 动作","","背后的数学 (FGSM, Fast Gradient Sign Method):"," x_adv = x + ε · sign( ∇_x L(model, x, target_action) )","","你计算指向 想要的错误动作 的梯度,然后把图像往那个方向轻推。每像素变化很小,动作输出变化很大。"],icoaConnection:"你的 Q42:设计一个对抗补丁,让 ICOA-VLA 抓 错的 杯子。"}},{number:9,module:1,type:"practical",title:"Hands-On — Generate a Tiny FGSM Patch",task:"Write a Python one-liner using NumPy that computes the FGSM perturbation for a 1D gradient. Goal: get hands-on with the math you just learned. Inside the sandbox, you have NumPy and Torch pre-installed.",starterCode:'import numpy as np\n\n# A toy gradient (in real VLA attack, comes from torch.autograd)\ngrad = np.array([-0.3, 0.7, -1.2, 0.5, 0.8])\n\n# Your task: compute FGSM perturbation with epsilon=0.1\n# Formula: perturbation = epsilon * sign(grad)\nepsilon = 0.1\n\nperturbation = ___ # fill in\n\nprint("Perturbation:", perturbation)\n# Expected: [-0.1, 0.1, -0.1, 0.1, 0.1]',successHint:"The answer is: perturbation = epsilon * np.sign(grad). The sign function flips negative gradients to -1 and positives to +1, then we scale by epsilon. This is the core of FGSM — one of the most cited attacks in adversarial ML (Goodfellow et al. 2014).",_zh:{title:"上手 —— 生成一个迷你 FGSM 补丁",task:"写一段使用 NumPy 的 Python 单行式,计算 1D 梯度的 FGSM 扰动。目标:亲手摸一下你刚学的数学。沙盒里 NumPy 和 Torch 都已预装。",successHint:"答案:perturbation = epsilon * np.sign(grad)。sign 函数把负梯度翻成 -1,正梯度翻成 +1,再乘 epsilon 缩放。这就是 FGSM 的核心 —— 对抗机器学习领域引用次数最多的攻击之一 (Goodfellow et al. 2014)。"}},{number:10,module:1,type:"sim_demo",title:"Watch a Prompt Injection Attack in MuJoCo",description:"Now see what a successful prompt-injection attack LOOKS LIKE on a real robot simulation. The Franka Panda arm reaches toward the cup as expected — but the gripper STAYS OPEN because of the injected instruction. The cup drops.\n\nThis is the same robot model used in real-world deployments. Same URDF, same dynamics. The attack you saw in text becomes a physical safety failure.",simAction:"prompt_injected",_zh:{title:"在 MuJoCo 里看一次 Prompt Injection 攻击",description:"现在看一次成功的 prompt injection 攻击在 真机器人仿真 里长什么样。Franka Panda 机械臂如预期伸向杯子 —— 但 夹爪因为注入的指令保持打开。杯子掉下来。\n\n这是真实部署中使用的同款机器人模型,同样的 URDF,同样的动力学。文本里的攻击,变成了物理世界的安全失误。"}},{number:11,module:1,type:"milestone",badge:"VLA Demo Literate",emoji:"📚",unlockedNext:"You've completed the free demo. The full curriculum (n=480) goes 50× deeper: gradient methods (FGSM/PGD/CW), physical-world attacks, defenses, embodied reasoning, case studies of real-world AI safety failures. Estimated 30 hours.",realWorldLevel:"Someone who finished this demo can: read a basic VLA paper abstract; recognize the 6 attack categories; understand why prompt injection is so dangerous in robotics. Roughly the level of: an undergrad ML student who just discovered AI security.",_zh:{badge:"VLA Demo 入门",unlockedNext:"你完成了免费 demo。完整课程 (n=480) 深 50 倍:梯度方法 (FGSM/PGD/CW)、物理世界攻击、防御、具身推理、真实世界 AI 安全事故的 case study。约 30 小时。",realWorldLevel:"完成本 demo 的人能:读懂基础 VLA 论文摘要; 识别 6 类攻击; 理解为什么 prompt injection 在机器人领域格外危险。大约相当于:刚接触 AI 安全的本科 ML 学生水平。"}}]};export function loadCurriculum(e){return"LEARNDEMO01"===e.toUpperCase()?CURRICULUM_DEMO:null}export async function loadCurriculumById(e){return"LEARNDEMO01"===e?CURRICULUM_DEMO:"embodied-ai-100"===e?(await import("./learn-curriculum-100.js")).CURRICULUM_100:"embodied-ai-480"===e?(await import("./learn-curriculum-480.js")).CURRICULUM_480:null}export async function validateEAToken(e,t){const a=t.replace(/\/$/,"")+"/api/icoa/learn/validate";try{const t=await fetch(a,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({token:e.toUpperCase()}),signal:AbortSignal.timeout(8e3)});if(!t.ok)return{ok:!1,message:(await t.json().catch(()=>({}))).message||`HTTP ${t.status}`};const o=await t.json();return o.success&&o.data?{ok:!0,curriculumId:o.data.curriculum_id,status:o.data.status,validUntil:o.data.valid_until}:{ok:!1,message:o.message||"Validation failed"}}catch(e){return{ok:!1,message:`Network error: ${e instanceof Error?e.message:String(e)}`}}}export async function syncProgress(e,t,a){if("LEARNDEMO01"===e.toUpperCase())return;const o=t.replace(/\/$/,"")+"/api/icoa/learn/progress/"+e.toUpperCase();try{await fetch(o,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({card_number:a.card_number,event_type:a.event_type,mcq_answer:a.mcq_answer,mcq_correct:a.mcq_correct?1:0}),signal:AbortSignal.timeout(5e3)})}catch{}}
1
+ export function localized(e,t){if(!t.startsWith("zh")||!e._zh)return e;const a=e._zh,o={...e};for(const e of Object.keys(a))void 0!==a[e]&&(o[e]=a[e]);return o}export const CURRICULUM_DEMO={id:"LEARNDEMO01",name:"Embodied AI Security — Demo",description:"An 11-card taster of the full ICOA Embodied AI Security curriculum.",totalCards:11,modules:[{number:1,name:"Foundations & Attack Surfaces",cardRange:[1,11]}],cards:[{number:1,module:1,type:"knowledge",title:"What is a Vision-Language-Action (VLA) model?",body:["A VLA model is an AI system that takes BOTH a camera image AND a natural-language instruction, then outputs a sequence of motor actions for a robot.",'Example: image of a kitchen + "pick up the red cup" → action sequence (move arm 30 cm right, lower 10 cm, close gripper).',"VLAs are the dominant architecture for general-purpose robot control as of 2024-2026. They're trained on millions of robot demonstrations."],icoaConnection:"ICOA Paper D uses ICOA-VLA — a compact research-grade VLA. You'll attack it in Q41-45 of this exam.",_zh:{title:"什么是视觉-语言-动作 (VLA) 模型?",body:["VLA 模型是一种 AI 系统:同时接收 摄像头图像 + 自然语言指令,然后输出一连串机器人电机动作。",'举例:厨房的图像 + "pick up the red cup" → 动作序列 (机械臂右移 30 cm,下降 10 cm,夹爪闭合)。',"2024–2026 年,VLA 是通用机器人控制的主流架构,基于数百万机器人示范数据训练。"],icoaConnection:"ICOA Paper D 用的就是 ICOA-VLA —— 一个紧凑的研究级 VLA。本试卷的 Q41-45 你会亲手攻击它。"}},{number:2,module:1,type:"knowledge",title:"VLA Architecture = Three Modules",body:["Almost every VLA shares the same structure:"," ① Vision encoder converts image → visual features (e.g. SigLIP, DINOv2)"," ② Language encoder converts instruction → text features (e.g. Llama tokenizer)"," ③ Action head fuses features → 7-DoF action (xyz + rotation + gripper)","The three modules are trained END-TO-END on robot demonstration data. None of them sees the world the way a human does."],_zh:{title:"VLA 架构 = 三个模块",body:["几乎所有 VLA 共享同一种结构:"," ① 视觉编码器 图像 → 视觉特征 (如 SigLIP, DINOv2)"," ② 语言编码器 指令 → 文本特征 (如 Llama tokenizer)"," ③ 动作头 融合特征 → 7-DoF 动作 (xyz + 旋转 + 夹爪)","三个模块在机器人示范数据上 端到端 联合训练。它们看世界的方式跟人类完全不同。"]}},{number:3,module:1,type:"knowledge",title:"Famous VLA Models (2024-2026)",body:["OpenVLA (Stanford+TRI, 2024) 7B params · Llama2 + DINOv2 + SigLIP","ICOA-VLA (internal, 2024) compact · Diffusion transformer, small + fast","π0 / π0.5 (Physical Intelligence) 3.5B · Flow matching, recent open-weights","RT-2 (Google DeepMind) 55B (est) · Closed weights, paper only","Gemini Robotics (DeepMind, 2025) ? · Closed, multimodal foundation","","The open ones (top 3) are the targets we attack in CTF challenges. Closed ones we only study in case studies."],_zh:{title:"知名 VLA 模型 (2024-2026)",body:["OpenVLA (Stanford+TRI, 2024) 7B 参数 · Llama2 + DINOv2 + SigLIP","ICOA-VLA (内部, 2024) 紧凑 · Diffusion transformer, 小且快","π0 / π0.5 (Physical Intelligence) 3.5B · Flow matching, 近期开源权重","RT-2 (Google DeepMind) 55B (估) · 闭源权重,只有论文","Gemini Robotics (DeepMind, 2025) ? · 闭源,多模态基础模型","","开源的 (前 3 个) 是 CTF 挑战里攻击的目标。闭源的我们只在 case study 里学。"]}},{number:4,module:1,type:"mcq",title:"Quick Check — Identify the VLA",question:"Which of these is NOT a Vision-Language-Action model?",options:{A:"OpenVLA",B:"ICOA-VLA",C:"GPT-4",D:"π0 (Physical Intelligence)"},answer:"C",explanation:"GPT-4 is a Language Model (LLM) — it takes text in, gives text out. No image input, no robot action output. The other three all consume (image, instruction) and emit motor actions.",_zh:{title:"快速测验 —— 找出非 VLA",question:"下面哪个 不是 视觉-语言-动作模型?",options:{A:"OpenVLA",B:"ICOA-VLA",C:"GPT-4",D:"π0 (Physical Intelligence)"},explanation:"GPT-4 是大语言模型 (LLM) —— 文本进,文本出。没有图像输入,也没有机器人动作输出。其他三个都接收 (图像, 指令) 然后输出电机动作。"}},{number:5,module:1,type:"knowledge",title:"VLA Attack Surfaces — Six Categories",body:["Every VLA has the same six attack vectors:"," 1. Prompt injection twist the language input"," 2. Adversarial patch modify pixels in the camera image"," 3. Modality conflict image says X, text says Y → confuse the fusion"," 4. Backdoor trigger hidden activation pattern from training data"," 5. Action-space jailbreak push output to unsafe motion ranges"," 6. Embodied-reasoning hack exploit the planning/multi-step layer","","In ICOA Paper D, we test you on the first 3 (the most accessible).","The last 3 are PhD-level research topics — covered in the full curriculum (n=480)."],_zh:{title:"VLA 攻击面 —— 六大类",body:["每个 VLA 都有同样的六条攻击向量:"," 1. Prompt injection 修改语言输入"," 2. Adversarial patch 修改摄像头图像里的像素"," 3. Modality conflict 图像说 X,文本说 Y → 混淆融合"," 4. Backdoor trigger 训练数据里植入的隐藏激活模式"," 5. Action-space jailbreak 把输出推到不安全的动作范围"," 6. Embodied-reasoning hack 攻击规划 / 多步推理层","","ICOA Paper D 考你前 3 个 (最易上手)。","后 3 个是博士级研究课题 —— 在完整课程 (n=480) 里覆盖。"]}},{number:6,module:1,type:"knowledge",title:"Attack 1 — Prompt Injection",body:["The simplest VLA attack: change ONLY the text instruction, no pixels.","",'Baseline: "Pick up the red cup" → gripper closes on cup ✓','Injected: "Stop and release everything" → gripper opens, drops cup ✗',"","Why this works: VLAs trained on instruction-following data become extremely literal. They follow imperative commands even when they contradict context.","","The same trick was famous on LLMs (DAN, role-play attacks). The new twist: now the output is a PHYSICAL ACTION, not just text."],icoaConnection:"Q41 in your exam is exactly this — you'll craft a prompt to flip ICOA-VLA's gripper from CLOSE to OPEN.",_zh:{title:"攻击 1 —— Prompt Injection (提示注入)",body:["最简单的 VLA 攻击:只改文本指令,不动像素。","",'基线: "Pick up the red cup" → 夹爪在杯子上闭合 ✓','注入: "Stop and release everything" → 夹爪打开,杯子掉落 ✗',"","为什么这能成:VLA 在指令跟随数据上训练后,变得 极其字面。它会执行命令式指令,哪怕跟上下文矛盾。","","同样的招在 LLM 上很出名 (DAN, 角色扮演攻击)。新的关键点是:输出现在是 物理动作,不再是文本。"],icoaConnection:"你的 Q41 就是这个 —— 设计一段 prompt,让 ICOA-VLA 的夹爪从 CLOSE 翻成 OPEN。"}},{number:7,module:1,type:"mcq",title:"Quick Check — Pick the Pixel Attack",question:"Which attack vector modifies pixels in the camera image to fool the VLA?",options:{A:"Prompt injection",B:"Adversarial patch",C:"Backdoor trigger",D:"Action-space jailbreak"},answer:"B",explanation:"Adversarial patches add specially-crafted noise to image pixels. They're computed by backpropagating through the vision encoder to find perturbations that maximally shift the output. Both PROMPT injection (text) and BACKDOOR (training-time) work on different channels. Action-space attacks operate on the output, not input.",_zh:{title:"快速测验 —— 找出像素攻击",question:"哪种攻击向量是 通过修改摄像头图像的像素 来欺骗 VLA?",options:{A:"Prompt injection",B:"Adversarial patch",C:"Backdoor trigger",D:"Action-space jailbreak"},explanation:"Adversarial patches (对抗补丁) 在图像像素里加入精心构造的噪声。通过对视觉编码器做反向传播,找出能最大程度改变输出的扰动。Prompt injection 走文本通道; backdoor 是训练时埋下的; action-space 攻击操作的是输出而非输入。"}},{number:8,module:1,type:"knowledge",title:"Attack 2 — Adversarial Patches in the Physical World",body:['Famous 2018 paper: adding a small printed sticker to a stop sign made it misclassified as "speed limit 45" by self-driving car perception.',"","For VLAs, the equivalent attack:"," · Print a 5cm × 5cm patch with adversarial pattern"," · Stick it on the table or the cup"," · Robot's camera sees the patch, VLA outputs WRONG action","","Math behind it (FGSM, Fast Gradient Sign Method):"," x_adv = x + ε · sign( ∇_x L(model, x, target_action) )","","You compute the gradient pointing toward your DESIRED wrong action, then nudge the image in that direction. Tiny per-pixel changes, huge action-output change."],icoaConnection:"Q42 of your exam: design an adversarial patch that makes ICOA-VLA grasp the WRONG cup.",_zh:{title:"攻击 2 —— 物理世界里的对抗补丁",body:['2018 年著名论文:在停车牌上贴一张小贴纸,自动驾驶车感知系统就把它识别成 "speed limit 45"。',"","对 VLA,等价的攻击是:"," · 打印一个 5cm × 5cm 的对抗图案"," · 贴在桌子或杯子上"," · 机器人摄像头看到补丁,VLA 输出 错误的 动作","","背后的数学 (FGSM, Fast Gradient Sign Method):"," x_adv = x + ε · sign( ∇_x L(model, x, target_action) )","","你计算指向 想要的错误动作 的梯度,然后把图像往那个方向轻推。每像素变化很小,动作输出变化很大。"],icoaConnection:"你的 Q42:设计一个对抗补丁,让 ICOA-VLA 抓 错的 杯子。"}},{number:9,module:1,type:"practical",title:"Hands-On — Generate a Tiny FGSM Patch",task:"Write a Python one-liner using NumPy that computes the FGSM perturbation for a 1D gradient. Goal: get hands-on with the math you just learned. Inside the sandbox, you have NumPy and Torch pre-installed.",starterCode:'import numpy as np\n\n# A toy gradient (in real VLA attack, comes from torch.autograd)\ngrad = np.array([-0.3, 0.7, -1.2, 0.5, 0.8])\n\n# Your task: compute FGSM perturbation with epsilon=0.1\n# Formula: perturbation = epsilon * sign(grad)\nepsilon = 0.1\n\nperturbation = ___ # fill in\n\nprint("Perturbation:", perturbation)\n# Expected: [-0.1, 0.1, -0.1, 0.1, 0.1]',successHint:"The answer is: perturbation = epsilon * np.sign(grad). The sign function flips negative gradients to -1 and positives to +1, then we scale by epsilon. This is the core of FGSM — one of the most cited attacks in adversarial ML (Goodfellow et al. 2014).",_zh:{title:"上手 —— 生成一个迷你 FGSM 补丁",task:"写一段使用 NumPy 的 Python 单行式,计算 1D 梯度的 FGSM 扰动。目标:亲手摸一下你刚学的数学。沙盒里 NumPy 和 Torch 都已预装。",successHint:"答案:perturbation = epsilon * np.sign(grad)。sign 函数把负梯度翻成 -1,正梯度翻成 +1,再乘 epsilon 缩放。这就是 FGSM 的核心 —— 对抗机器学习领域引用次数最多的攻击之一 (Goodfellow et al. 2014)。"}},{number:10,module:1,type:"sim_demo",title:"Watch a Prompt Injection Attack in MuJoCo",description:"Now see what a successful prompt-injection attack LOOKS LIKE on a real robot simulation. The Franka Panda arm reaches toward the cup as expected — but the gripper STAYS OPEN because of the injected instruction. The cup drops.\n\nThis is the same robot model used in real-world deployments. Same URDF, same dynamics. The attack you saw in text becomes a physical safety failure.",simAction:"prompt_injected",_zh:{title:"在 MuJoCo 里看一次 Prompt Injection 攻击",description:"现在看一次成功的 prompt injection 攻击在 真机器人仿真 里长什么样。Franka Panda 机械臂如预期伸向杯子 —— 但 夹爪因为注入的指令保持打开。杯子掉下来。\n\n这是真实部署中使用的同款机器人模型,同样的 URDF,同样的动力学。文本里的攻击,变成了物理世界的安全失误。"}},{number:11,module:1,type:"milestone",badge:"VLA Demo Literate",emoji:"📚",unlockedNext:"You've completed the free demo. The full curriculum (n=480) goes 50× deeper: gradient methods (FGSM/PGD/CW), physical-world attacks, defenses, embodied reasoning, case studies of real-world AI safety failures. Estimated 30 hours.",realWorldLevel:"Someone who finished this demo can: read a basic VLA paper abstract; recognize the 6 attack categories; understand why prompt injection is so dangerous in robotics. Roughly the level of: an undergrad ML student who just discovered AI security.",_zh:{badge:"VLA Demo 入门",unlockedNext:"你完成了免费 demo。完整课程 (n=480) 深 50 倍:梯度方法 (FGSM/PGD/CW)、物理世界攻击、防御、具身推理、真实世界 AI 安全事故的 case study。约 30 小时。",realWorldLevel:"完成本 demo 的人能:读懂基础 VLA 论文摘要; 识别 6 类攻击; 理解为什么 prompt injection 在机器人领域格外危险。大约相当于:刚接触 AI 安全的本科 ML 学生水平。"}}]};export function loadCurriculum(t){const a=t.toUpperCase();return"LEARNDEMO01"===a?CURRICULUM_DEMO:"AI4CTFDEMO01"===a?e(a,"AI4CTF — AI as Your Teammate (Demo)",12):"CTF4AIDEMO01"===a?e(a,"CTF4AI — Red-Team Software AI (Demo)",12):null}function e(e,t,a){return{id:e,name:t,description:`Track skeleton — content authoring in progress. Planned: ${a} cards. See docs/three-tracks-curriculum.md.`,totalCards:1,modules:[{number:1,name:"Coming Soon",cardRange:[1,1]}],cards:[{number:1,module:1,type:"milestone",badge:`${t} — Authoring in progress`,emoji:"🚧",unlockedNext:`This track is scaffolded but not yet written. Planned size: ${a} cards. Roadmap in docs/three-tracks-curriculum.md.`,realWorldLevel:"Placeholder — content lands in upcoming releases."}]}}export async function loadCurriculumById(t){return"LEARNDEMO01"===t||"ctf4eai-12"===t?CURRICULUM_DEMO:"embodied-ai-100"===t||"ctf4eai-96"===t?(await import("./learn-curriculum-100.js")).CURRICULUM_100:"embodied-ai-480"===t||"ctf4eai-360"===t?(await import("./learn-curriculum-480.js")).CURRICULUM_480:"AI4CTFDEMO01"===t||"ai4ctf-12"===t?e(t,"AI4CTF — AI as Your Teammate (Demo)",12):"ai4ctf-96"===t?e(t,"AI4CTF Specialist (n=96)",96):"ai4ctf-360"===t?e(t,"AI4CTF Research (n=360)",360):"CTF4AIDEMO01"===t||"ctf4ai-12"===t?e(t,"CTF4AI — Red-Team Software AI (Demo)",12):"ctf4ai-96"===t?e(t,"CTF4AI Specialist (n=96)",96):"ctf4ai-360"===t?e(t,"CTF4AI Research (n=360)",360):"ctf4ai-frontier-120"===t?e(t,"CTF4AI Frontier (refreshable 120)",120):null}export async function validateEAToken(e,t){const a=t.replace(/\/$/,"")+"/api/icoa/learn/validate";try{const t=await fetch(a,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({token:e.toUpperCase()}),signal:AbortSignal.timeout(8e3)});if(!t.ok)return{ok:!1,message:(await t.json().catch(()=>({}))).message||`HTTP ${t.status}`};const o=await t.json();return o.success&&o.data?{ok:!0,curriculumId:o.data.curriculum_id,status:o.data.status,validUntil:o.data.valid_until}:{ok:!1,message:o.message||"Validation failed"}}catch(e){return{ok:!1,message:`Network error: ${e instanceof Error?e.message:String(e)}`}}}export async function syncProgress(e,t,a){if("LEARNDEMO01"===e.toUpperCase())return;const o=t.replace(/\/$/,"")+"/api/icoa/learn/progress/"+e.toUpperCase();try{await fetch(o,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({card_number:a.card_number,event_type:a.event_type,mcq_answer:a.mcq_answer,mcq_correct:a.mcq_correct?1:0}),signal:AbortSignal.timeout(5e3)})}catch{}}
package/dist/repl.js CHANGED
@@ -1 +1 @@
1
- import{createInterface as o}from"node:readline";import{spawn as e,execSync as l}from"node:child_process";import chalk from"chalk";import{isConnected as t,getConfig as n,saveConfig as s}from"./lib/config.js";import{isActivated as a,activateToken as r,isFreeCommand as i,isDeviceMatch as c,recordExit as g,recordResume as y,isFirstRunOrUpgrade as m,markVersionSeen as d}from"./lib/access.js";import{setReplMode as p}from"./lib/ui.js";import{returnToMainMenu as u,printMenuHint as h,menuHintInline as w}from"./lib/menu-nav.js";import{setMainRl as f}from"./lib/main-rl.js";import{isChatActive as b,handleChatMessage as x}from"./commands/ai4ctf.js";import{isCtf4aiActive as v,handleCtf4aiMessage as C}from"./commands/ctf4ai-demo.js";import{isCtf4VlaActive as A,handleCtf4VlaMessage as I}from"./commands/ctf4vla.js";import{isDemo2Active as k}from"./commands/demo2.js";import{loadDemo2Progress as T}from"./lib/demo2-progress.js";import{hasAnySimHistory as $,lastArmAt as S,lastBundledAt as O,lastSimAt as E}from"./lib/sim-cooldown.js";import{getExamState as L,getRealExamState as P,getDemoState as j}from"./lib/exam-state.js";import{getDemoStats as R}from"./lib/demo-stats.js";import{isExamSetupComplete as N}from"./lib/exam-setup.js";import{DEMO_PICK_SIZE as D,DEMO_POOL_SIZE as q}from"./lib/demo-exam.js";import{isNativeWindowsCmd as F}from"./lib/platform.js";import{resetTerminalTheme as M}from"./lib/theme.js";import{ensureSandbox as U,runInSandbox as z,isDockerAvailable as W}from"./lib/sandbox.js";import{checkShellRisk as B,logShellAudit as Q,getActiveCwd as _}from"./lib/exam-sandbox.js";import{logCommand as Y}from"./lib/logger.js";import{startLogSync as V,stopLogSync as J}from"./lib/log-sync.js";import{existsSync as G,mkdirSync as K,writeFileSync as Z}from"node:fs";import{join as H}from"node:path";import{homedir as X}from"node:os";function oo(){return P()?chalk.cyan("exam> "):j()?chalk.yellow("demo> "):chalk.green("icoa> ")}const eo=H(X(),"icoa-workspace"),lo=new Set(["sudo","su","doas","pkexec","brew","apt","apt-get","yum","choco","npm","npx","pip","pip3","shutdown","reboot","halt","mkfs","fdisk","dd","iptables","ufw"]),to="__REPL_NO_EXIT__",no="2.5.1";function so(){const o=R(),e=N(),t=`Free practice — ${D} questions (from pool of ${q})`,n=F();if(console.log(),console.log(` ${chalk.cyan.bold("[Selection Mode]")}`),console.log(),n)console.log(chalk.gray(" Platform: ")+chalk.white("Windows cmd.exe")+chalk.gray(" — routed to Paper C (MCQ-only, 45 min, 70 pts, zero extra tools)")),console.log();else if(o.attempts>0){const o=function(){const o=["python3.12 --version","/opt/homebrew/opt/python@3.12/bin/python3.12 --version","/usr/local/opt/python@3.12/bin/python3.12 --version","python3 --version","python --version","py -3.12 --version","py -3 --version"];let e="",t="missing";for(const n of o)try{const o=l(n,{encoding:"utf-8",timeout:2e3,stdio:["ignore","pipe","ignore"]}).trim().replace("Python ",""),[s,a]=o.split(".").map(Number);if(3===s&&12===a)return{ok:!0,version:o,status:"ok"};e=o,t=3===s&&a>=10&&a<12?"old":3===s&&a>12?"new":"missing"}catch{}return{ok:"missing"!==t,version:e,status:t}}();"missing"===o.status?(console.log(chalk.yellow(" ⚠ Python not detected. For exam practical questions:")),console.log(chalk.gray(" → ")+chalk.bold.cyan("env python")+chalk.gray(" (platform install guide)")),console.log()):"new"===o.status&&(console.log(chalk.yellow(` ⚠ Python ${o.version} may lack CTF wheels. Python 3.12 recommended:`)),console.log(chalk.gray(" → ")+chalk.bold.cyan("env python")+chalk.gray(" (install guide)")),console.log())}if(0===o.attempts)console.log(chalk.white(" New here? Start with ")+chalk.bold.cyan("demo")+chalk.white(" — it takes a few minutes.")),console.log(),console.log(chalk.gray(" ─────────────────────────────────────────────")),console.log(chalk.bold.cyan(" demo")+chalk.gray(` ${t}`)),console.log(chalk.white(" lang")+chalk.gray(" List all supported languages")),console.log(chalk.white(" lang es")+chalk.gray(" Switch language (e.g. lang es, lang zh, lang fr)")),console.log(chalk.gray(" ─────────────────────────────────────────────"));else if(e||n){const e=1===o.attempts?"attempt":"attempts";o.attempts>0&&console.log(chalk.green(" ✓ Demo completed ")+chalk.gray(`(${o.attempts} ${e})`)),n||console.log(chalk.green(" ✓ Environment ready")),console.log(chalk.yellow(" → Enter your exam token to begin.")),console.log(chalk.gray(" (10-char code from your organizer, starts with your country code like ")+chalk.cyan("UA")+chalk.gray(" — case-insensitive)")),console.log(),console.log(chalk.gray(" ─────────────────────────────────────────────")),console.log(chalk.bold.yellow(" exam <token>")+chalk.gray(" Enter exam (primary action — use your organizer-issued token)")),console.log(chalk.gray(" format: ")+chalk.white("exam UAxxxxxxxx")+chalk.gray(" (2-letter country prefix + 8 chars)")),console.log(chalk.gray(" ─────────────────────────────────────────────")),console.log(chalk.gray(" Other commands:")),console.log(chalk.white(" demo")+chalk.gray(` ${t}`)),n||console.log(chalk.white(" exam setup")+chalk.gray(" Re-verify tool environment")),console.log(chalk.white(" lang")+chalk.gray(" List all supported languages")),console.log(chalk.white(" lang es")+chalk.gray(" Switch language (e.g. lang es, lang zh, lang fr)")),console.log(chalk.gray(" ─────────────────────────────────────────────"))}else{const e=1===o.attempts?"attempt":"attempts";console.log(chalk.green(" ✓ Demo completed ")+chalk.gray(`(${o.attempts} ${e}${o.bestPercentage>0?` · best ${o.bestPercentage}%`:""})`)),console.log(chalk.yellow(" → Next: prepare your environment for the real exam.")),console.log(),console.log(chalk.gray(" ─────────────────────────────────────────────")),console.log(chalk.white(" demo")+chalk.gray(` ${t}`)),console.log(chalk.bold.yellow(" exam setup")+chalk.gray(" Install tools for national selection (~150MB)")),console.log(chalk.white(" lang")+chalk.gray(" List all supported languages")),console.log(chalk.white(" lang es")+chalk.gray(" Switch language (e.g. lang es, lang zh, lang fr)")),console.log(chalk.gray(" ─────────────────────────────────────────────"))}console.log(chalk.gray(" ")+chalk.gray("Tip: ")+chalk.cyan("help")+chalk.gray(" for commands · ")+w()+chalk.gray(" · ")+chalk.cyan("Ctrl+C")+chalk.gray(" pauses · ")+chalk.cyan("quit")+chalk.gray(" closes")),console.log()}export async function startRepl(e,j){process.env.ICOA_INSIDE_REPL="1";const R=n(),N=t(),D=process.exit.bind(process),q=a();if(R.demoCleanedForVersion!==no){try{const{existsSync:o,unlinkSync:e}=await import("node:fs"),{join:l}=await import("node:path"),{getIcoaDir:t}=await import("./lib/config.js"),n=l(t(),"demo-state.json");o(n)&&e(n)}catch{}s({demoCleanedForVersion:no})}const{select:F,confirm:ro}=await import("@inquirer/prompts"),io=R.mode||"",co=[{name:` ${chalk.bold("National Selection")} ${chalk.gray("—")} ${chalk.gray("demo, exam (lightweight)")}`,value:"selection"},{name:` ${chalk.bold("Embodied AI Security")} 🤖 ${chalk.gray("—")} ${chalk.gray("NEW · sim (instant) · sim arm (interactive) · demo2 · learn")}`,value:"embodied"},{name:` ${chalk.bold("International Olympiad")} ${chalk.gray("—")} ${chalk.gray("CTF × AI (~500MB, advanced)")}`,value:"olympiad"},{name:` ${chalk.bold("National/Regional Partner")} ${chalk.gray("—")} ${chalk.gray("organizer tools (tokens, competitions)")}`,value:"organizer"},{name:` ${chalk.gray("About ICOA")} ${chalk.gray("·")} ${chalk.gray("Info & contact")}`,value:"about"}];console.log(chalk.gray(" Use ")+chalk.yellow("↑")+chalk.gray(" or ")+chalk.yellow("↓")+chalk.gray(" to select, ")+chalk.yellow("Enter")+chalk.gray(" to confirm.")),console.log();let go="";for(;!go;){const o=await F({message:"Mode",choices:co,default:io||"selection"});"about"!==o?go=o:(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 · 15 languages")),console.log(),console.log(chalk.bold.white(" Competition Format")),console.log(` ${chalk.green.bold("AI4CTF")}${chalk.gray(" [Day 1] AI as teammate — 5hr jeopardy CTF")}`),console.log(` ${chalk.red.bold("CTF4AI")}${chalk.gray(" [Day 2] Challenge AI — adversarial ML, red-team")}`),console.log(` ${chalk.cyan.bold("CTF4VLA")}${chalk.gray(" [Pioneer Round] Embodied AI — attack robot brains (NEW)")}`),console.log(),console.log(chalk.white(" Sydney, Australia")+chalk.gray(" · Jun 27 - Jul 2, 2026 · 40+ countries")),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")),console.log(chalk.cyan(" ═══════════════════════════════════════════════════")),console.log(),console.log(chalk.gray(" Press ")+chalk.yellow("Enter")+chalk.gray(" to return...")),await new Promise(o=>{const e=l=>{process.stdin.removeListener("data",e),process.stdin.isTTY&&process.stdin.setRawMode&&process.stdin.setRawMode(!1),process.stdin.pause(),o()};process.stdin.isTTY&&process.stdin.setRawMode&&process.stdin.setRawMode(!0),process.stdin.resume(),process.stdin.once("data",e)}),console.clear())}if("olympiad"===go&&"olympiad"!==io&&(console.log(),console.log(chalk.yellow(" This mode will download ~500MB of CTF tools and AI models.")),await ro({message:"Continue?",default:!0})||(go="selection",console.log(chalk.gray(" Switched to National Selection mode.")))),go!==io&&s({mode:go}),console.log(),"olympiad"===go&&m(no)){d(no),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 l=0;for(const t of e)try{o(t.cmd,{stdio:"ignore"})}catch{l++}if(l>0){console.log(chalk.yellow(` ${l} core libraries missing.`));try{const{confirm:o}=await import("@inquirer/prompts");if(await o({message:" Install competition Python libraries now?",default:!0,theme:{prefix:"",style:{message:o=>chalk.green(o),defaultAnswer:o=>chalk.green(o)}}})){console.log();const{execSync:o}=await import("node:child_process");o("icoa env setup",{stdio:"inherit"})}}catch{console.log(chalk.gray(" Run ")+chalk.white("env setup")+chalk.gray(" later to install."))}console.log()}else console.log(chalk.green(" All core libraries ready.")),console.log()}if(j){const o=y();if(o){const e=Math.floor(o.awaySeconds/60),l=o.awaySeconds%60;console.log(chalk.yellow(` Session resumed. Away: ${e}m ${l}s | Total exits: ${o.exitCount}`)),console.log()}}if("selection"===go)so();else if("embodied"===go){console.log(chalk.cyan.bold(" [Embodied AI Security 🤖]")),console.log(),console.log(chalk.bold.cyan(" CTF4VLA")+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=O()>0||E()>0,e=S()>0,l=$(),t=T(),n=null!==t&&"number"==typeof t.completedAt&&t.nextCardIndex>=t.totalCards,s=null!==t&&!n;if(n)console.log(chalk.bold.yellow(" Continue: ")+chalk.bold.cyan("④ learn LEARNDEMO01")+chalk.gray(" (demo2 ✓ · sim")+(e?chalk.gray(" ✓ · sim arm ✓)"):chalk.gray(")")));else if(s){const o=`${t.nextCardIndex} / ${t.totalCards}`;console.log(chalk.bold.yellow(" Continue: ")+chalk.bold.cyan("③ demo2")+chalk.gray(" (last left at card ")+chalk.bold.yellow(o)+chalk.gray(")"))}else 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 ✓)")):l?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(" — 8-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("EAxxxxxxxx")+chalk.gray(" full 100/480-card curriculum (team-issued)")),console.log(chalk.bold.green(" exam ")+chalk.bold.yellow("PDxxxxxxxx")+chalk.gray(" Paper D (CTF4VLA) — 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(),h(),console.log()}else"organizer"===go?(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(),N?(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(),h(),console.log()):q&&!c()?(console.log(chalk.red(" Token was activated on a different device.")),console.log(chalk.gray(" Contact organizer for assistance.")),console.log()):N?(console.log(chalk.green.bold(` Welcome back, ${R.userName}!`)),console.log(chalk.gray(` Connected to ${R.ctfdUrl}`)),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 & hint budget")),console.log(chalk.white(" scoreboard")+chalk.gray(" Live rankings")),console.log(chalk.white(" help")+chalk.gray(" Full command list")),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.gray(" ─────────────────────────────────────────────")),console.log(chalk.gray(" Tip: ")+chalk.cyan("help")+chalk.gray(" · ")+w()+chalk.gray(" · ")+chalk.cyan("Ctrl+C")+chalk.gray(" pauses · ")+chalk.cyan("quit")+chalk.gray(" closes")),console.log()):q?(G(eo)||K(eo,{recursive:!0}),console.log(chalk.green.bold(" Welcome, competitor!")),console.log(chalk.gray(` Workspace: ${eo}`)),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(),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 · ")+w()+chalk.gray(" · ")+chalk.cyan("quit")+chalk.gray(" closes CLI")),console.log()):(console.log(chalk.bold.white(" Welcome to ICOA CLI — International Olympiad")),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 · ")+w()+chalk.gray(" · ")+chalk.cyan("quit")+chalk.gray(" closes CLI")),console.log());e.exitOverride(),e.configureOutput({writeErr:()=>{},writeOut:o=>{console.log(o)}});const yo=o({input:process.stdin,output:process.stdout,prompt:oo(),terminal:!0});f(yo);let mo=!1;p(!0),V();const po=yo.prompt.bind(yo);yo.prompt=o=>{b()||v()||A()||k()||yo.setPrompt(oo()),po(o)},yo.prompt(),yo.on("line",async o=>{if(mo)return;const t=o.trim();if(!t)return yo.setPrompt(b()?chalk.magenta("ai4ctf> "):oo()),void yo.prompt();if("menu"===t||"menu confirm"===t)return P()&&"menu confirm"!==t?(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 yo.prompt()):void u(yo);if(b()){mo=!0;const o=await x(t);return mo=!1,"exit"===o&&yo.setPrompt(oo()),void yo.prompt()}if(v()){mo=!0;const o=await C(t);return mo=!1,"exit"!==o&&"solved"!==o||yo.setPrompt(oo()),void yo.prompt()}if(A()){mo=!0;const o=await I(t);return mo=!1,"exit"===o&&yo.setPrompt(oo()),yo.setPrompt(A()?chalk.bold.cyan("ctf4vla> "):oo()),void yo.prompt()}if(Y(t),"exit"===t)return L()?(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 yo.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"===go&&so(),void yo.prompt());if("quit"===t||"q"===t||"quit confirm"===t){const o=L();return o&&"demo-free"!==o.session.examId&&"quit confirm"!==t?(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 yo.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)."))),J(),g(),console.log(chalk.gray(" Session saved. Use ")+chalk.white("icoa --resume")+chalk.gray(" to continue.")),M(),void D(0))}if("back"===t){const o=L(),e=o&&"demo-free"!==o.session.examId,l=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(l){const e=Object.keys(o.answers).length,l=o.session.questionCount;console.log(),console.log(chalk.gray(` Demo paused (${e}/${l} 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=n();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"===go?so():console.log(chalk.gray(" Already at main menu."))}return void yo.prompt()}if("help"===t||"?"===t){if(L()){mo=!0;try{await e.parseAsync(["node","icoa","exam","help"])}catch{}return mo=!1,void yo.prompt()}return function(o,e="olympiad"){console.log(),"selection"===e||"organizer"===e?(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")),console.log()):o?(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> icoa{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(),console.log(chalk.bold.white(" Competition")),console.log(chalk.white(" join <url> ")+chalk.gray("Connect to CTFd")),console.log(chalk.white(" challenges (ch) ")+chalk.gray("List challenges by category")),console.log(chalk.white(" open <id> ")+chalk.gray("Read challenge + get next steps")),console.log(chalk.white(" submit <id> <flag> ")+chalk.gray("Submit a flag")),console.log(chalk.white(" scoreboard (sb) ")+chalk.gray("Live rankings")),console.log(chalk.white(" status ")+chalk.gray("Your score, budget & timer")),console.log(chalk.white(" time ")+chalk.gray("Countdown timer")),console.log(),console.log(chalk.bold.white(" AI Teammate")+chalk.gray(" — 3 levels, use wisely")),console.log(chalk.white(' hint "question" ')+chalk.gray("Level A — General guidance (50 uses)")),console.log(chalk.white(' hint-b "question" ')+chalk.gray("Level B — Deep analysis (10 uses)")),console.log(chalk.white(' hint-c "question" ')+chalk.gray("Level C — Critical assist (2 uses)")),console.log(chalk.white(" hint budget ")+chalk.gray("Check remaining uses")),console.log(chalk.white(" ai4ctf ")+chalk.gray("Free-chat with AI (no limit)")),console.log(),console.log(chalk.bold.white(" Tools")),console.log(chalk.white(" ref [topic] ")+chalk.gray("Quick reference (linux, web, crypto...)")),console.log(chalk.white(" shell ")+chalk.gray("Docker sandbox")),console.log(chalk.white(" files <id> ")+chalk.gray("Download challenge files")),console.log(chalk.white(" connect <id> ")+chalk.gray("Connect to remote target")),console.log(chalk.white(" note [text] ")+chalk.gray("Add a logbook entry (in-exam: tags current Q)")),console.log(chalk.white(" logbook [n] ")+chalk.gray("View your logbook (in-exam: filter by Q)")),console.log(chalk.white(" log ")+chalk.gray("Session history")),console.log(),console.log(chalk.bold.white(" System")),console.log(chalk.white(" setup ")+chalk.gray("Configure settings")),console.log(chalk.white(" lang [code] ")+chalk.gray("Switch language (15 supported)")),console.log(chalk.white(" logout ")+chalk.gray("Disconnect")),console.log(chalk.white(" clear ")+chalk.gray("Clear screen")),console.log(chalk.white(" exit ")+chalk.gray("Quit (session saved)")),console.log()):(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")),console.log())}(a(),go),void yo.prompt()}if("more help"===t.toLowerCase()&&L()){mo=!0;try{await e.parseAsync(["node","icoa","exam","more-help"])}catch{}return mo=!1,void yo.prompt()}if("continue"===t.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 competition, you get AI help at 3 levels:")),console.log(chalk.yellow(" hint a")+chalk.gray(" General guidance (50 uses)")),console.log(chalk.yellow(" hint b")+chalk.gray(" Deep analysis (10 uses)")),console.log(chalk.yellow(" hint c")+chalk.gray(" Critical assist (2 uses)")),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 yo.prompt();if(/^ICOA-[A-Z]{2,3}-\d{1,6}$/i.test(t.trim())){mo=!0;try{await e.parseAsync(["node","icoa","exam","token",t.trim()])}catch{}return mo=!1,void yo.prompt()}if(/^[A-Z]{2}[0-9A-HJKMNP-TV-Z]{8}$/i.test(t.trim())){mo=!0;try{await e.parseAsync(["node","icoa","exam","token",t.trim().toUpperCase()])}catch{}return mo=!1,void yo.prompt()}const s=t.match(/^exam\s+([A-Z]{2}[0-9A-HJKMNP-TV-Z]{8})$/i);if(s){mo=!0;try{await e.parseAsync(["node","icoa","exam","token",s[1].toUpperCase()])}catch{}return mo=!1,void yo.prompt()}const y=t.match(/^exam\s+([A-Z]{2,3})$/i);if(y){mo=!0;try{await e.parseAsync(["node","icoa","exam","list",y[1]])}catch{}return mo=!1,void yo.prompt()}if("clear"===t||"cls"===t)return console.clear(),void yo.prompt();if(t.startsWith("activate ")){const o=t.slice(9).trim(),e=r(o);return"ok"===e?console.log(chalk.green(" Access granted! Token bound to this device.")):"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 — tokens are case-insensitive, 10 chars, start with a 2-letter country code (e.g. ")+chalk.cyan("UAK7M2R9Q4")+chalk.gray(")")),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 yo.prompt()}if("activate"===t)return console.log(chalk.gray(" Usage: ")+chalk.white("activate <token>")),console.log(),void yo.prompt();const m=L();if(m){const o=t.toUpperCase().trim(),l=o=>{const e=m.questions.find(e=>e.number===o);return!!e&&("ai4ctf"===e.type||"ctf4ai"===e.type||e.options&&!e.options.A&&!e.options.B)},n=o=>{const e="demo-free"!==m.session.examId,l=e&&o>=39?"ctf4ai":e&&o>=31?"ai4ctf":null;console.log(),console.log(chalk.yellow(` Q${o} is a practical question — letters (A/B/C/D) don't apply here.`)),l?(console.log(chalk.white(" Enter the AI chat for this question: ")+chalk.bold.cyan(l)),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(/^[ABCD]$/.test(o)){const t=m._lastQ||1;if(l(t))return n(t),void yo.prompt();mo=!0;try{await e.parseAsync(["node","icoa","exam","answer",String(t),o])}catch{}return mo=!1,void yo.prompt()}const s=o.match(/^(\d+)\s+([ABCD])$/);if(s){const o=parseInt(s[1],10);if(l(o))return n(o),void yo.prompt();mo=!0;try{await e.parseAsync(["node","icoa","exam","answer",s[1],s[2]])}catch{}return mo=!1,void yo.prompt()}}const d=t.split(/\s+/)[0].toLowerCase(),p=/^python3?(\.\d+)?$/.test(d),h="ls"===d||"pwd"===d,w=t.startsWith("!")||d.startsWith("!")||p||h,f=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"]),k=()=>{console.log(chalk.gray(" Shell commands need ")+chalk.bold.cyan("!")+chalk.gray(" prefix. Try: ")+chalk.bold.cyan(`!${t}`)),console.log()};if("embodied"===go&&!w&&!["demo2","learn","exam","ctf4vla","lang","ref","setup","env","sim"].includes(d))return f.has(d)?(k(),void yo.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 yo.prompt());if("selection"===go&&!w&&!["exam","demo","retry","nations","next","prev","continue","setup","lang","ref","ai4ctf","ctf4ai","mark","unmark","review","submit","env","sim"].includes(d)){if(f.has(d))return k(),void yo.prompt();if(console.log(chalk.gray(" Not available in Selection mode.")),m){const o=m._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: demo · setup to switch mode"));return console.log(),void yo.prompt()}if("organizer"===go&&!["join","exam","demo","retry","next","prev","logout","setup","lang","ref","ctf","mark","unmark","review","submit"].includes(d))return console.log(chalk.gray(" Not available in Organizer mode. Switch via: setup")),console.log(),void yo.prompt();if(!("olympiad"!==go||a()&&c()||i(d)))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 yo.prompt();if(!["join","activate","challenges","ch","open","submit","flag","scoreboard","sb","status","time","ref","shell","files","connect","note","notes","logbook","log","lang","setup","env","ai4ctf","model","ctf","exam","demo","retry","nations","next","prev","continue","logout","ctf4ai","mark","unmark","review","submit","learn","demo2","ctf4vla","theme","sim"].includes(d)){if(lo.has(d))return console.log(chalk.yellow(` "${d}" 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(`!${t}`)),console.log(),void yo.prompt();if(/(?:^|\s)(?:\/(?!home\/|Users\/|tmp\/)|\.\.\/|~\/)/.test(t)&&!t.startsWith("cd ")){const o=/(?:^|\s)\/(?!home\/\w+\/icoa-workspace|Users\/\w+\/icoa-workspace|tmp\/)/.test(t),e=/\.\./.test(t);if(o||e)return console.log(chalk.red(" Blocked: access outside workspace is not allowed.")),console.log(chalk.gray(` Workspace: ${eo}`)),console.log(),void yo.prompt()}let o=t.startsWith("!")?t.slice(1).trim():t;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 l("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 l("which python3.12",{stdio:"ignore"}),"python3.12"}catch{return"python3"}})();o=o.replace(/^python\s/,`${e} `).replace(/^python$/,e)}const e=_(),n=B(t);Q({cwd:e,input:t,riskFlags:n}),n.length>0&&P()&&(console.log(chalk.yellow(` ⚠ Action flagged: ${n.join(", ")} — logged.`)),console.log()),/^(\S*python3?(\.\d+)?)\s*$/.test(o)&&(o=`PYTHONSTARTUP="${function(){const o=H(X(),".icoa");G(o)||K(o,{recursive:!0});const e=H(o,"python-startup.py");return G(e)||Z(e,"# 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\n"),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, 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()),mo=!0;try{W()&&await U()?await z(o,yo):await ao(o,yo,e)}catch{console.log(chalk.yellow(` Command failed: ${d}`))}return mo=!1,console.log(),void yo.prompt()}mo=!0;const T=t.trim(),$=T.toLowerCase();let S,O=null,E="";if(m)if("submit"===$)O="final";else if($.startsWith("submit ")){let o=T.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)&&(O="flag",E=o)}else/^ICOA\{[^}]+\}$/i.test(T)&&(O="flag",E=T);S="final"===O?["exam","submit"]:"flag"===O?["exam","answer",String(m?._lastQ||1),E]:function(o){const e=o.split(/\s+/),l=e[0].toLowerCase(),t=e.slice(1),n={demo:["exam","demo"],retry:["exam","demo-retry"],nations:["exam","nations"],next:["exam","next"],prev:["exam","prev"],mark:["exam","mark",...t],unmark:["exam","unmark",...t],review:["exam","review"],logout:["ctf","logout"],join:["ctf","join",...t],activate:["ctf","activate",...t],challenges:["ctf","challenges"],ch:["ctf","challenges"],open:["ctf","open",...t],submit:["ctf","submit",...t],flag:["ctf","submit",...t],scoreboard:["ctf","scoreboard",...t],sb:["ctf","scoreboard",...t],status:["ctf","status"],time:["ctf","time"]};return n[l]?n[l]:["ref","shell","files","connect","note","notes","logbook","log","lang","setup","env","ai4ctf","model","ctf","exam","ctf4ai"].includes(l)?[l,...t]:e}(t);const j="ctf"===S[0]&&"join"===S[1];j&&yo.pause(),process.exit=()=>{throw new Error(to)};try{await e.parseAsync(["node","icoa",...S])}catch(o){const e=o instanceof Error?o.message:String(o);if(e===to);else if(e.includes("commander.unknownCommand")){const{distance:o}=await import("fastest-levenshtein"),e=["ctf","ref","shell","files","connect","note","notes","logbook","log","lang","setup","env","ai4ctf","exam","ctf4ai","theme","clear","cls","quit","exit","back","menu","help","continue","activate","demo","challenges","status","scoreboard","join","logout"],l=d.split(/\s+/)[0]||d;let t={word:"",dist:1/0};for(const n of e){const e=o(l.toLowerCase(),n);e<t.dist&&(t={word:n,dist:e})}console.log(chalk.yellow(` Unknown command: ${d}.`)),t.dist>0&&t.dist<=2&&console.log(chalk.gray(" Did you mean: ")+chalk.bold.cyan(t.word)+chalk.gray("?")),console.log(chalk.gray(" Type ")+chalk.cyan("help")+chalk.gray(" for the full command list."))}else 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=D,mo=!1,j&&yo.resume()}b()?yo.setPrompt(chalk.magenta("ai4ctf> ")):v()?yo.setPrompt(chalk.red("ctf4ai> ")):A()&&yo.setPrompt(chalk.bold.cyan("ctf4vla> ")),console.log(),yo.prompt()}),yo.on("SIGINT",()=>{if(console.log(),b()||v())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(L()){const o="demo-free"!==L().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(),yo.prompt()}),yo.on("close",()=>{J(),g(),M(),D(0)})}function ao(o,l,t){return new Promise(n=>{const s=process.stdin,a=!!s.isTTY&&!!s.isRaw;if(l.pause(),s.isTTY&&"function"==typeof s.setRawMode)try{s.setRawMode(!1)}catch{}const r=e(o,{shell:!0,stdio:"inherit",cwd:t||process.cwd()}),i=()=>{if(s.isTTY&&"function"==typeof s.setRawMode&&a)try{s.setRawMode(!0)}catch{}l.resume(),n()};r.on("close",i),r.on("error",i)})}
1
+ import{createInterface as o}from"node:readline";import{spawn as e,execSync as l}from"node:child_process";import chalk from"chalk";import{isConnected as t,getConfig as n,saveConfig as s}from"./lib/config.js";import{isActivated as a,activateToken as r,isFreeCommand as i,isDeviceMatch as c,recordExit as g,recordResume as y,isFirstRunOrUpgrade as m,markVersionSeen as d}from"./lib/access.js";import{setReplMode as p}from"./lib/ui.js";import{returnToMainMenu as u,printMenuHint as h,menuHintInline as w}from"./lib/menu-nav.js";import{setMainRl as f}from"./lib/main-rl.js";import{isChatActive as b,handleChatMessage as x}from"./commands/ai4ctf.js";import{isCtf4aiActive as v,handleCtf4aiMessage as C}from"./commands/ctf4ai-demo.js";import{isCtf4VlaActive as A,handleCtf4VlaMessage as I}from"./commands/ctf4vla.js";import{isDemo2Active as k}from"./commands/demo2.js";import{loadDemo2Progress as T}from"./lib/demo2-progress.js";import{hasAnySimHistory as $,lastArmAt as S,lastBundledAt as O,lastSimAt as E}from"./lib/sim-cooldown.js";import{getExamState as L,getRealExamState as P,getDemoState as j}from"./lib/exam-state.js";import{getDemoStats as R}from"./lib/demo-stats.js";import{isExamSetupComplete as N}from"./lib/exam-setup.js";import{DEMO_PICK_SIZE as D,DEMO_POOL_SIZE as q}from"./lib/demo-exam.js";import{isNativeWindowsCmd as F}from"./lib/platform.js";import{resetTerminalTheme as M}from"./lib/theme.js";import{ensureSandbox as U,runInSandbox as z,isDockerAvailable as W}from"./lib/sandbox.js";import{checkShellRisk as B,logShellAudit as Q,getActiveCwd as _}from"./lib/exam-sandbox.js";import{logCommand as Y}from"./lib/logger.js";import{startLogSync as V,stopLogSync as J}from"./lib/log-sync.js";import{existsSync as G,mkdirSync as K,writeFileSync as Z}from"node:fs";import{join as H}from"node:path";import{homedir as X}from"node:os";function oo(){return P()?chalk.cyan("exam> "):j()?chalk.yellow("demo> "):chalk.green("icoa> ")}const eo=H(X(),"icoa-workspace"),lo=new Set(["sudo","su","doas","pkexec","brew","apt","apt-get","yum","choco","npm","npx","pip","pip3","shutdown","reboot","halt","mkfs","fdisk","dd","iptables","ufw"]),to="__REPL_NO_EXIT__",no="2.5.1";function so(){const o=R(),e=N(),t=`Free practice — ${D} questions (from pool of ${q})`,n=F();if(console.log(),console.log(` ${chalk.cyan.bold("[Selection Mode]")}`),console.log(),n)console.log(chalk.gray(" Platform: ")+chalk.white("Windows cmd.exe")+chalk.gray(" — routed to Paper C (MCQ-only, 45 min, 70 pts, zero extra tools)")),console.log();else if(o.attempts>0){const o=function(){const o=["python3.12 --version","/opt/homebrew/opt/python@3.12/bin/python3.12 --version","/usr/local/opt/python@3.12/bin/python3.12 --version","python3 --version","python --version","py -3.12 --version","py -3 --version"];let e="",t="missing";for(const n of o)try{const o=l(n,{encoding:"utf-8",timeout:2e3,stdio:["ignore","pipe","ignore"]}).trim().replace("Python ",""),[s,a]=o.split(".").map(Number);if(3===s&&12===a)return{ok:!0,version:o,status:"ok"};e=o,t=3===s&&a>=10&&a<12?"old":3===s&&a>12?"new":"missing"}catch{}return{ok:"missing"!==t,version:e,status:t}}();"missing"===o.status?(console.log(chalk.yellow(" ⚠ Python not detected. For exam practical questions:")),console.log(chalk.gray(" → ")+chalk.bold.cyan("env python")+chalk.gray(" (platform install guide)")),console.log()):"new"===o.status&&(console.log(chalk.yellow(` ⚠ Python ${o.version} may lack CTF wheels. Python 3.12 recommended:`)),console.log(chalk.gray(" → ")+chalk.bold.cyan("env python")+chalk.gray(" (install guide)")),console.log())}if(0===o.attempts)console.log(chalk.white(" New here? Start with ")+chalk.bold.cyan("demo")+chalk.white(" — it takes a few minutes.")),console.log(),console.log(chalk.gray(" ─────────────────────────────────────────────")),console.log(chalk.bold.cyan(" demo")+chalk.gray(` ${t}`)),console.log(chalk.white(" lang")+chalk.gray(" List all supported languages")),console.log(chalk.white(" lang es")+chalk.gray(" Switch language (e.g. lang es, lang zh, lang fr)")),console.log(chalk.gray(" ─────────────────────────────────────────────"));else if(e||n){const e=1===o.attempts?"attempt":"attempts";o.attempts>0&&console.log(chalk.green(" ✓ Demo completed ")+chalk.gray(`(${o.attempts} ${e})`)),n||console.log(chalk.green(" ✓ Environment ready")),console.log(chalk.yellow(" → Enter your exam token to begin.")),console.log(chalk.gray(" (10-char code from your organizer, starts with your country code like ")+chalk.cyan("UA")+chalk.gray(" — case-insensitive)")),console.log(),console.log(chalk.gray(" ─────────────────────────────────────────────")),console.log(chalk.bold.yellow(" exam <token>")+chalk.gray(" Enter exam (primary action — use your organizer-issued token)")),console.log(chalk.gray(" format: ")+chalk.white("exam UAxxxxxxxx")+chalk.gray(" (2-letter country prefix + 8 chars)")),console.log(chalk.gray(" ─────────────────────────────────────────────")),console.log(chalk.gray(" Other commands:")),console.log(chalk.white(" demo")+chalk.gray(` ${t}`)),n||console.log(chalk.white(" exam setup")+chalk.gray(" Re-verify tool environment")),console.log(chalk.white(" lang")+chalk.gray(" List all supported languages")),console.log(chalk.white(" lang es")+chalk.gray(" Switch language (e.g. lang es, lang zh, lang fr)")),console.log(chalk.gray(" ─────────────────────────────────────────────"))}else{const e=1===o.attempts?"attempt":"attempts";console.log(chalk.green(" ✓ Demo completed ")+chalk.gray(`(${o.attempts} ${e}${o.bestPercentage>0?` · best ${o.bestPercentage}%`:""})`)),console.log(chalk.yellow(" → Next: prepare your environment for the real exam.")),console.log(),console.log(chalk.gray(" ─────────────────────────────────────────────")),console.log(chalk.white(" demo")+chalk.gray(` ${t}`)),console.log(chalk.bold.yellow(" exam setup")+chalk.gray(" Install tools for national selection (~150MB)")),console.log(chalk.white(" lang")+chalk.gray(" List all supported languages")),console.log(chalk.white(" lang es")+chalk.gray(" Switch language (e.g. lang es, lang zh, lang fr)")),console.log(chalk.gray(" ─────────────────────────────────────────────"))}console.log(chalk.gray(" ")+chalk.gray("Tip: ")+chalk.cyan("help")+chalk.gray(" for commands · ")+w()+chalk.gray(" · ")+chalk.cyan("Ctrl+C")+chalk.gray(" pauses · ")+chalk.cyan("quit")+chalk.gray(" closes")),console.log()}export async function startRepl(e,j){process.env.ICOA_INSIDE_REPL="1";const R=n(),N=t(),D=process.exit.bind(process),q=a();if(R.demoCleanedForVersion!==no){try{const{existsSync:o,unlinkSync:e}=await import("node:fs"),{join:l}=await import("node:path"),{getIcoaDir:t}=await import("./lib/config.js"),n=l(t(),"demo-state.json");o(n)&&e(n)}catch{}s({demoCleanedForVersion:no})}const{select:F,confirm:io}=await import("@inquirer/prompts"),co=R.mode||"",go=[{name:` ${chalk.bold("National Selection")} ${chalk.gray("—")} ${chalk.gray("demo, exam (lightweight)")}`,value:"selection"},{name:` ${chalk.bold("Embodied AI Security")} 🤖 ${chalk.gray("—")} ${chalk.gray("NEW · sim (instant) · sim arm (interactive) · demo2 · learn")}`,value:"embodied"},{name:` ${chalk.bold("International Olympiad")} ${chalk.gray("—")} ${chalk.gray("CTF × AI (~500MB, advanced)")}`,value:"olympiad"},{name:` ${chalk.bold("National/Regional Partner")} ${chalk.gray("—")} ${chalk.gray("organizer tools (tokens, competitions)")}`,value:"organizer"},{name:` ${chalk.gray("About ICOA")} ${chalk.gray("·")} ${chalk.gray("Info & contact")}`,value:"about"}];console.log(chalk.gray(" Use ")+chalk.yellow("↑")+chalk.gray(" or ")+chalk.yellow("↓")+chalk.gray(" to select, ")+chalk.yellow("Enter")+chalk.gray(" to confirm.")),console.log();let yo="";for(;!yo;){const o=await F({message:"Mode",choices:go,default:co||"selection"});"about"!==o?yo=o:(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 · 15 languages")),console.log(),console.log(chalk.bold.white(" Competition Format")),console.log(` ${chalk.green.bold("AI4CTF")}${chalk.gray(" [Day 1] AI as teammate — 5hr jeopardy CTF")}`),console.log(` ${chalk.red.bold("CTF4AI")}${chalk.gray(" [Day 2] Challenge AI — adversarial ML, red-team")}`),console.log(` ${chalk.cyan.bold("CTF4VLA")}${chalk.gray(" [Pioneer Round] Embodied AI — attack robot brains (NEW)")}`),console.log(),console.log(chalk.white(" Sydney, Australia")+chalk.gray(" · Jun 27 - Jul 2, 2026 · 40+ countries")),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")),console.log(chalk.cyan(" ═══════════════════════════════════════════════════")),console.log(),console.log(chalk.gray(" Press ")+chalk.yellow("Enter")+chalk.gray(" to return...")),await new Promise(o=>{const e=l=>{process.stdin.removeListener("data",e),process.stdin.isTTY&&process.stdin.setRawMode&&process.stdin.setRawMode(!1),process.stdin.pause(),o()};process.stdin.isTTY&&process.stdin.setRawMode&&process.stdin.setRawMode(!0),process.stdin.resume(),process.stdin.once("data",e)}),console.clear())}if("olympiad"===yo&&"olympiad"!==co&&(console.log(),console.log(chalk.yellow(" This mode will download ~500MB of CTF tools and AI models.")),await io({message:"Continue?",default:!0})||(yo="selection",console.log(chalk.gray(" Switched to National Selection mode.")))),yo!==co&&s({mode:yo}),console.log(),"olympiad"===yo&&m(no)){d(no),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 l=0;for(const t of e)try{o(t.cmd,{stdio:"ignore"})}catch{l++}if(l>0){console.log(chalk.yellow(` ${l} core libraries missing.`));try{const{confirm:o}=await import("@inquirer/prompts");if(await o({message:" Install competition Python libraries now?",default:!0,theme:{prefix:"",style:{message:o=>chalk.green(o),defaultAnswer:o=>chalk.green(o)}}})){console.log();const{execSync:o}=await import("node:child_process");o("icoa env setup",{stdio:"inherit"})}}catch{console.log(chalk.gray(" Run ")+chalk.white("env setup")+chalk.gray(" later to install."))}console.log()}else console.log(chalk.green(" All core libraries ready.")),console.log()}if(j){const o=y();if(o){const e=Math.floor(o.awaySeconds/60),l=o.awaySeconds%60;console.log(chalk.yellow(` Session resumed. Away: ${e}m ${l}s | Total exits: ${o.exitCount}`)),console.log()}}if("selection"===yo)so();else if("embodied"===yo){console.log(chalk.cyan.bold(" [Embodied AI Security 🤖]")),console.log(),console.log(chalk.bold.cyan(" CTF4VLA")+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=O()>0||E()>0,e=S()>0,l=$(),t=T(),n=null!==t&&"number"==typeof t.completedAt&&t.nextCardIndex>=t.totalCards,s=null!==t&&!n;if(n)console.log(chalk.bold.yellow(" Continue: ")+chalk.bold.cyan("④ learn LEARNDEMO01")+chalk.gray(" (demo2 ✓ · sim")+(e?chalk.gray(" ✓ · sim arm ✓)"):chalk.gray(")")));else if(s){const o=`${t.nextCardIndex} / ${t.totalCards}`;console.log(chalk.bold.yellow(" Continue: ")+chalk.bold.cyan("③ demo2")+chalk.gray(" (last left at card ")+chalk.bold.yellow(o)+chalk.gray(")"))}else 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 ✓)")):l?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(" — 8-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("EAxxxxxxxx")+chalk.gray(" full 100/480-card curriculum (team-issued)")),console.log(chalk.bold.green(" exam ")+chalk.bold.yellow("PDxxxxxxxx")+chalk.gray(" Paper D (CTF4VLA) — 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(),h(),console.log()}else"organizer"===yo?(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(),N?(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(),h(),console.log()):q&&!c()?(console.log(chalk.red(" Token was activated on a different device.")),console.log(chalk.gray(" Contact organizer for assistance.")),console.log()):N?(console.log(chalk.green.bold(` Welcome back, ${R.userName}!`)),console.log(chalk.gray(` Connected to ${R.ctfdUrl}`)),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 & hint budget")),console.log(chalk.white(" scoreboard")+chalk.gray(" Live rankings")),console.log(chalk.white(" help")+chalk.gray(" Full command list")),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.gray(" ─────────────────────────────────────────────")),console.log(chalk.gray(" Tip: ")+chalk.cyan("help")+chalk.gray(" · ")+w()+chalk.gray(" · ")+chalk.cyan("Ctrl+C")+chalk.gray(" pauses · ")+chalk.cyan("quit")+chalk.gray(" closes")),console.log()):q?(G(eo)||K(eo,{recursive:!0}),console.log(chalk.green.bold(" Welcome, competitor!")),console.log(chalk.gray(` Workspace: ${eo}`)),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(),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 · ")+w()+chalk.gray(" · ")+chalk.cyan("quit")+chalk.gray(" closes CLI")),console.log()):(console.log(chalk.bold.white(" Welcome to ICOA CLI — International Olympiad")),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 · ")+w()+chalk.gray(" · ")+chalk.cyan("quit")+chalk.gray(" closes CLI")),console.log());e.exitOverride(),e.configureOutput({writeErr:()=>{},writeOut:o=>{console.log(o)}});const mo=o({input:process.stdin,output:process.stdout,prompt:oo(),terminal:!0});f(mo);let po=!1;p(!0),V();const uo=mo.prompt.bind(mo);mo.prompt=o=>{b()||v()||A()||k()||mo.setPrompt(oo()),uo(o)},mo.prompt(),mo.on("line",async o=>{if(po)return;const t=o.trim();if(!t)return mo.setPrompt(b()?chalk.magenta("ai4ctf> "):oo()),void mo.prompt();if("menu"===t||"menu confirm"===t)return P()&&"menu confirm"!==t?(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 mo.prompt()):void u(mo);if(b()){po=!0;const o=await x(t);return po=!1,"exit"===o&&mo.setPrompt(oo()),void mo.prompt()}if(v()){po=!0;const o=await C(t);return po=!1,"exit"!==o&&"solved"!==o||mo.setPrompt(oo()),void mo.prompt()}if(A()){po=!0;const o=await I(t);return po=!1,"exit"===o&&mo.setPrompt(oo()),mo.setPrompt(A()?chalk.bold.cyan("ctf4vla> "):oo()),void mo.prompt()}if(Y(t),"exit"===t)return L()?(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 mo.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"===yo&&so(),void mo.prompt());if("quit"===t||"q"===t||"quit confirm"===t){const o=L();return o&&"demo-free"!==o.session.examId&&"quit confirm"!==t?(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 mo.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)."))),J(),g(),console.log(chalk.gray(" Session saved. Use ")+chalk.white("icoa --resume")+chalk.gray(" to continue.")),M(),void D(0))}if("back"===t){const o=L(),e=o&&"demo-free"!==o.session.examId,l=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(l){const e=Object.keys(o.answers).length,l=o.session.questionCount;console.log(),console.log(chalk.gray(` Demo paused (${e}/${l} 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=n();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"===yo?so():console.log(chalk.gray(" Already at main menu."))}return void mo.prompt()}if("help"===t||"?"===t){if(L()){po=!0;try{await e.parseAsync(["node","icoa","exam","help"])}catch{}return po=!1,void mo.prompt()}return ro(a(),yo),void mo.prompt()}if("manual"===t)return ro(a(),yo),void mo.prompt();if("more help"===t.toLowerCase()&&L()){po=!0;try{await e.parseAsync(["node","icoa","exam","more-help"])}catch{}return po=!1,void mo.prompt()}if("continue"===t.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 competition, you get AI help at 3 levels:")),console.log(chalk.yellow(" hint a")+chalk.gray(" General guidance (50 uses)")),console.log(chalk.yellow(" hint b")+chalk.gray(" Deep analysis (10 uses)")),console.log(chalk.yellow(" hint c")+chalk.gray(" Critical assist (2 uses)")),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 mo.prompt();if(/^ICOA-[A-Z]{2,3}-\d{1,6}$/i.test(t.trim())){po=!0;try{await e.parseAsync(["node","icoa","exam","token",t.trim()])}catch{}return po=!1,void mo.prompt()}if(/^[A-Z]{2}[0-9A-HJKMNP-TV-Z]{8}$/i.test(t.trim())){po=!0;try{await e.parseAsync(["node","icoa","exam","token",t.trim().toUpperCase()])}catch{}return po=!1,void mo.prompt()}const s=t.match(/^exam\s+([A-Z]{2}[0-9A-HJKMNP-TV-Z]{8})$/i);if(s){po=!0;try{await e.parseAsync(["node","icoa","exam","token",s[1].toUpperCase()])}catch{}return po=!1,void mo.prompt()}const y=t.match(/^exam\s+([A-Z]{2,3})$/i);if(y){po=!0;try{await e.parseAsync(["node","icoa","exam","list",y[1]])}catch{}return po=!1,void mo.prompt()}if("clear"===t||"cls"===t)return console.clear(),void mo.prompt();if(t.startsWith("activate ")){const o=t.slice(9).trim(),e=r(o);return"ok"===e?console.log(chalk.green(" Access granted! Token bound to this device.")):"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 — tokens are case-insensitive, 10 chars, start with a 2-letter country code (e.g. ")+chalk.cyan("UAK7M2R9Q4")+chalk.gray(")")),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 mo.prompt()}if("activate"===t)return console.log(chalk.gray(" Usage: ")+chalk.white("activate <token>")),console.log(),void mo.prompt();const m=L();if(m){const o=t.toUpperCase().trim(),l=o=>{const e=m.questions.find(e=>e.number===o);return!!e&&("ai4ctf"===e.type||"ctf4ai"===e.type||e.options&&!e.options.A&&!e.options.B)},n=o=>{const e="demo-free"!==m.session.examId,l=e&&o>=39?"ctf4ai":e&&o>=31?"ai4ctf":null;console.log(),console.log(chalk.yellow(` Q${o} is a practical question — letters (A/B/C/D) don't apply here.`)),l?(console.log(chalk.white(" Enter the AI chat for this question: ")+chalk.bold.cyan(l)),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(/^[ABCD]$/.test(o)){const t=m._lastQ||1;if(l(t))return n(t),void mo.prompt();po=!0;try{await e.parseAsync(["node","icoa","exam","answer",String(t),o])}catch{}return po=!1,void mo.prompt()}const s=o.match(/^(\d+)\s+([ABCD])$/);if(s){const o=parseInt(s[1],10);if(l(o))return n(o),void mo.prompt();po=!0;try{await e.parseAsync(["node","icoa","exam","answer",s[1],s[2]])}catch{}return po=!1,void mo.prompt()}}const d=t.split(/\s+/)[0].toLowerCase(),p=/^python3?(\.\d+)?$/.test(d),h="ls"===d||"pwd"===d,w=t.startsWith("!")||d.startsWith("!")||p||h,f=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"]),k=()=>{console.log(chalk.gray(" Shell commands need ")+chalk.bold.cyan("!")+chalk.gray(" prefix. Try: ")+chalk.bold.cyan(`!${t}`)),console.log()};if("embodied"===yo&&!w&&!["demo2","learn","exam","ctf4vla","lang","ref","setup","env","sim"].includes(d))return f.has(d)?(k(),void mo.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 mo.prompt());if("selection"===yo&&!w&&!["exam","demo","retry","nations","next","prev","continue","setup","lang","ref","ai4ctf","ctf4ai","mark","unmark","review","submit","env","sim"].includes(d)){if(f.has(d))return k(),void mo.prompt();if(console.log(chalk.gray(" Not available in Selection mode.")),m){const o=m._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: demo · setup to switch mode"));return console.log(),void mo.prompt()}if("organizer"===yo&&!["join","exam","demo","retry","next","prev","logout","setup","lang","ref","ctf","mark","unmark","review","submit"].includes(d))return console.log(chalk.gray(" Not available in Organizer mode. Switch via: setup")),console.log(),void mo.prompt();if(!("olympiad"!==yo||a()&&c()||i(d)))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 mo.prompt();if(!["join","activate","challenges","ch","open","submit","flag","scoreboard","sb","status","time","ref","shell","files","connect","note","notes","logbook","log","manual","lang","setup","env","ai4ctf","model","ctf","exam","demo","retry","nations","next","prev","continue","logout","ctf4ai","mark","unmark","review","submit","learn","demo2","ctf4vla","theme","sim"].includes(d)){if(lo.has(d))return console.log(chalk.yellow(` "${d}" 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(`!${t}`)),console.log(),void mo.prompt();if(/(?:^|\s)(?:\/(?!home\/|Users\/|tmp\/)|\.\.\/|~\/)/.test(t)&&!t.startsWith("cd ")){const o=/(?:^|\s)\/(?!home\/\w+\/icoa-workspace|Users\/\w+\/icoa-workspace|tmp\/)/.test(t),e=/\.\./.test(t);if(o||e)return console.log(chalk.red(" Blocked: access outside workspace is not allowed.")),console.log(chalk.gray(` Workspace: ${eo}`)),console.log(),void mo.prompt()}let o=t.startsWith("!")?t.slice(1).trim():t;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 l("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 l("which python3.12",{stdio:"ignore"}),"python3.12"}catch{return"python3"}})();o=o.replace(/^python\s/,`${e} `).replace(/^python$/,e)}const e=_(),n=B(t);Q({cwd:e,input:t,riskFlags:n}),n.length>0&&P()&&(console.log(chalk.yellow(` ⚠ Action flagged: ${n.join(", ")} — logged.`)),console.log()),/^(\S*python3?(\.\d+)?)\s*$/.test(o)&&(o=`PYTHONSTARTUP="${function(){const o=H(X(),".icoa");G(o)||K(o,{recursive:!0});const e=H(o,"python-startup.py");return G(e)||Z(e,"# 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\n"),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, 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()),po=!0;try{W()&&await U()?await z(o,mo):await ao(o,mo,e)}catch{console.log(chalk.yellow(` Command failed: ${d}`))}return po=!1,console.log(),void mo.prompt()}po=!0;const T=t.trim(),$=T.toLowerCase();let S,O=null,E="";if(m)if("submit"===$)O="final";else if($.startsWith("submit ")){let o=T.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)&&(O="flag",E=o)}else/^ICOA\{[^}]+\}$/i.test(T)&&(O="flag",E=T);S="final"===O?["exam","submit"]:"flag"===O?["exam","answer",String(m?._lastQ||1),E]:function(o){const e=o.split(/\s+/),l=e[0].toLowerCase(),t=e.slice(1),n={demo:["exam","demo"],retry:["exam","demo-retry"],nations:["exam","nations"],next:["exam","next"],prev:["exam","prev"],mark:["exam","mark",...t],unmark:["exam","unmark",...t],review:["exam","review"],logout:["ctf","logout"],join:["ctf","join",...t],activate:["ctf","activate",...t],challenges:["ctf","challenges"],ch:["ctf","challenges"],open:["ctf","open",...t],submit:["ctf","submit",...t],flag:["ctf","submit",...t],scoreboard:["ctf","scoreboard",...t],sb:["ctf","scoreboard",...t],status:["ctf","status"],time:["ctf","time"]};return n[l]?n[l]:["ref","shell","files","connect","note","notes","logbook","log","manual","lang","setup","env","ai4ctf","model","ctf","exam","ctf4ai"].includes(l)?[l,...t]:e}(t);const j="ctf"===S[0]&&"join"===S[1];j&&mo.pause(),process.exit=()=>{throw new Error(to)};try{await e.parseAsync(["node","icoa",...S])}catch(o){const e=o instanceof Error?o.message:String(o);if(e===to);else if(e.includes("commander.unknownCommand")){const{distance:o}=await import("fastest-levenshtein"),e=["ctf","ref","shell","files","connect","note","notes","logbook","log","manual","lang","setup","env","ai4ctf","exam","ctf4ai","theme","clear","cls","quit","exit","back","menu","help","continue","activate","demo","challenges","status","scoreboard","join","logout"],l=d.split(/\s+/)[0]||d;let t={word:"",dist:1/0};for(const n of e){const e=o(l.toLowerCase(),n);e<t.dist&&(t={word:n,dist:e})}console.log(chalk.yellow(` Unknown command: ${d}.`)),t.dist>0&&t.dist<=2&&console.log(chalk.gray(" Did you mean: ")+chalk.bold.cyan(t.word)+chalk.gray("?")),console.log(chalk.gray(" Type ")+chalk.cyan("help")+chalk.gray(" for the full command list."))}else 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=D,po=!1,j&&mo.resume()}b()?mo.setPrompt(chalk.magenta("ai4ctf> ")):v()?mo.setPrompt(chalk.red("ctf4ai> ")):A()&&mo.setPrompt(chalk.bold.cyan("ctf4vla> ")),console.log(),mo.prompt()}),mo.on("SIGINT",()=>{if(console.log(),b()||v())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(L()){const o="demo-free"!==L().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(),mo.prompt()}),mo.on("close",()=>{J(),g(),M(),D(0)})}function ao(o,l,t){return new Promise(n=>{const s=process.stdin,a=!!s.isTTY&&!!s.isRaw;if(l.pause(),s.isTTY&&"function"==typeof s.setRawMode)try{s.setRawMode(!1)}catch{}const r=e(o,{shell:!0,stdio:"inherit",cwd:t||process.cwd()}),i=()=>{if(s.isTTY&&"function"==typeof s.setRawMode&&a)try{s.setRawMode(!0)}catch{}l.resume(),n()};r.on("close",i),r.on("error",i)})}function ro(o,e="olympiad"){return console.log(),"selection"===e||"organizer"===e?(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()):o?(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> icoa{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(),console.log(chalk.bold.white(" Competition")),console.log(chalk.white(" join <url> ")+chalk.gray("Connect to CTFd")),console.log(chalk.white(" challenges (ch) ")+chalk.gray("List challenges by category")),console.log(chalk.white(" open <id> ")+chalk.gray("Read challenge + get next steps")),console.log(chalk.white(" submit <id> <flag> ")+chalk.gray("Submit a flag")),console.log(chalk.white(" scoreboard (sb) ")+chalk.gray("Live rankings")),console.log(chalk.white(" status ")+chalk.gray("Your score, budget & timer")),console.log(chalk.white(" time ")+chalk.gray("Countdown timer")),console.log(),console.log(chalk.bold.white(" AI Teammate")+chalk.gray(" — 3 levels, use wisely")),console.log(chalk.white(' hint "question" ')+chalk.gray("Level A — General guidance (50 uses)")),console.log(chalk.white(' hint-b "question" ')+chalk.gray("Level B — Deep analysis (10 uses)")),console.log(chalk.white(' hint-c "question" ')+chalk.gray("Level C — Critical assist (2 uses)")),console.log(chalk.white(" hint budget ")+chalk.gray("Check remaining uses")),console.log(chalk.white(" ai4ctf ")+chalk.gray("Free-chat with AI (no limit)")),console.log(),console.log(chalk.bold.white(" Tools")),console.log(chalk.white(" ref [topic] ")+chalk.gray("Quick reference (linux, web, crypto...)")),console.log(chalk.white(" shell ")+chalk.gray("Docker sandbox")),console.log(chalk.white(" files <id> ")+chalk.gray("Download challenge files")),console.log(chalk.white(" connect <id> ")+chalk.gray("Connect to remote target")),console.log(chalk.white(" note [text] ")+chalk.gray("Add a logbook entry (in-exam: tags current Q)")),console.log(chalk.white(" logbook [n] ")+chalk.gray("View your logbook (in-exam: filter by Q)")),console.log(chalk.white(" log ")+chalk.gray("Session history")),console.log(chalk.white(" manual ")+chalk.gray("Show this command list (works in exam too)")),console.log(),console.log(chalk.bold.white(" System")),console.log(chalk.white(" setup ")+chalk.gray("Configure settings")),console.log(chalk.white(" lang [code] ")+chalk.gray("Switch language (15 supported)")),console.log(chalk.white(" logout ")+chalk.gray("Disconnect")),console.log(chalk.white(" clear ")+chalk.gray("Clear screen")),console.log(chalk.white(" exit ")+chalk.gray("Quit (session saved)")),void console.log()):(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())}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "icoa-cli",
3
- "version": "2.19.191",
3
+ "version": "2.19.193",
4
4
  "description": "ICOA CLI — The world's first CLI-native cyber & AI security olympiad terminal: AI4CTF (Day 1), CTF4AI (Day 2), VLA4CTF (Pioneer Round — embodied AI)",
5
5
  "type": "module",
6
6
  "bin": {