icoa-cli 2.19.240 → 2.19.242
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/ai4ctf.js +1 -1
- package/dist/commands/ctf4ai-demo.js +1 -1
- package/dist/commands/ctf4vla.js +1 -1
- package/dist/commands/exam.js +1 -1
- package/dist/index.js +1 -1
- package/dist/lib/banner.d.ts +9 -0
- package/dist/lib/banner.js +1 -0
- package/dist/lib/hint-client.js +1 -1
- package/dist/lib/learn-render.js +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{Command as o}from"commander";import chalk from"chalk";import{registerCtfCommands as e}from"./commands/ctf.js";import{registerRefCommand as n}from"./commands/ref.js";import{registerShellCommand as r}from"./commands/shell.js";import{registerFilesCommand as s}from"./commands/files.js";import{registerConnectCommand as t}from"./commands/connect.js";import{registerNoteCommand as
|
|
2
|
+
import{Command as o}from"commander";import chalk from"chalk";import{registerCtfCommands as e}from"./commands/ctf.js";import{registerRefCommand as n}from"./commands/ref.js";import{registerShellCommand as r}from"./commands/shell.js";import{registerFilesCommand as s}from"./commands/files.js";import{registerConnectCommand as t}from"./commands/connect.js";import{registerNoteCommand as i}from"./commands/note.js";import{registerLogCommand as l}from"./commands/log.js";import{registerLangCommand as a}from"./commands/lang.js";import{registerSetupCommand as m}from"./commands/setup.js";import{registerEnvCommand as c}from"./commands/env.js";import{registerAi4ctfCommand as g}from"./commands/ai4ctf.js";import{registerExamCommand as d}from"./commands/exam.js";import{registerCtf4aiDemoCommand as p}from"./commands/ctf4ai-demo.js";import{registerThemeCommand as y}from"./commands/theme.js";import{registerLearnCommand as h}from"./commands/learn.js";import{registerCtf4VlaCommand as f}from"./commands/ctf4vla.js";import{registerDemo2Command as u}from"./commands/demo2.js";import{registerSimCommand as w}from"./commands/sim.js";import{getConfig as b,saveConfig as T}from"./lib/config.js";import{startRepl as $}from"./repl.js";import{setTerminalTheme as v}from"./lib/theme.js";import{checkForUpdates as j}from"./lib/update-check.js";import{detectIcoaInstalls as A}from"./lib/platform.js";import{ICOA_BIG as C}from"./lib/banner.js";import{readFileSync as I}from"node:fs";import{fileURLToPath as _}from"node:url";import{dirname as E,join as S}from"node:path";const L=E(_(import.meta.url)),x=JSON.parse(I(S(L,"..","package.json"),"utf-8")).version,F=chalk.cyan(" ─────────────────────────────────────────────────────"),k=`\n${F}\n\n${C.map(o=>` ${chalk.bold.white(o)}`).join("\n")}\n\n ${chalk.yellow("International Cyber Olympiad in AI 2026")}\n ${chalk.bold.magenta("The World's First AI-Native CLI Operating System")}\n ${chalk.bold.magenta("for Cybersecurity & AI Security Competition")}\n ${chalk.bold.magenta("and Olympiad for K-12")}\n\n ${chalk.green.bold("AI4CTF")} ${chalk.gray("[Day 1]")} ${chalk.white("AI as your teammate")}\n ${chalk.red.bold("CTF4AI")} ${chalk.gray("[Day 2]")} ${chalk.white("Challenge & evaluate AI systems")}\n ${chalk.cyan.bold("CTF4VLA")} ${chalk.gray("[Pioneer]")} ${chalk.white("Embodied AI security")}\n ${chalk.bold.yellow("AI is your teammate. AI is your target. AI is embodied.")}\n\n ${chalk.white("Sydney, Australia")} ${chalk.gray("Jun 27 - Jul 2, 2026")}\n ${chalk.cyan.underline("https://icoa2026.au")}\n\n ${chalk.gray(`CLI-Native Competition Terminal v${x}`)}\n\n${F}\n`;process.on("uncaughtException",o=>{"__REPL_NO_EXIT__"!==o.message&&(console.error(chalk.red("Error:"),o.message),process.exit(1))}),process.on("unhandledRejection",o=>{const e=o instanceof Error?o.message:String(o);"__REPL_NO_EXIT__"!==e&&(console.error(chalk.red("Error:"),e),process.exit(1))});const N=new o;if(N.name("icoa").version(x).description("ICOA CLI — CLI-Native CTF Competition Terminal").option("--resume","Resume previous session").action(async o=>{const e=b();v("high-contrast"===e.themeVariant?"high-contrast":"dark"),j(),function(){const o=A();if(o.length<=1)return;const e=o[0];if([...o.map(o=>o.version||"0.0.0")].sort((o,e)=>function(o,e){const n=o.split(".").map(o=>parseInt(o,10)||0),r=e.split(".").map(o=>parseInt(o,10)||0);for(let o=0;o<3;o++)if((n[o]||0)!==(r[o]||0))return(n[o]||0)-(r[o]||0);return 0}(e,o))[0]!==e.version){console.log(),console.log(chalk.yellow.bold(" ⚠ Multiple icoa installations detected on PATH:"));for(let e=0;e<o.length;e++){const n=o[e],r=n.version?`v${n.version}`:"(version unreadable)",s=0===e?chalk.yellow("→"):" ",t=0===e?chalk.gray(" ← currently running (older — shadowing newer install)"):chalk.gray(" ← shadowed");console.log(` ${s} ${chalk.cyan(n.path.padEnd(28))} ${chalk.white(r)}${t}`)}console.log(),console.log(chalk.yellow(" The first install on PATH wins. To use the newer one, remove the older:")),console.log(),e.pkgDir?console.log(` ${chalk.bold.cyan(`sudo rm -rf ${e.pkgDir} ${e.path}`)}`):console.log(` ${chalk.bold.cyan(`sudo rm -rf ${e.path} # also delete its node_modules dir`)}`),console.log(),console.log(chalk.gray(" Then re-run icoa to confirm version banner shows the newer release.")),console.log()}}();const n=process.env.LANG||process.env.LC_ALL||process.env.LC_CTYPE||"";if(!/UTF-?8/i.test(n))if("win32"===process.platform){let o="";try{const{execFileSync:e}=await import("node:child_process");o=e("chcp.com",[],{encoding:"utf-8",timeout:1500,stdio:["ignore","pipe","ignore"]}).trim()}catch{}o.includes("65001")||(console.log(chalk.yellow(`⚠ Windows terminal is not using UTF-8 (current: ${o||"unknown"}).`)),console.log(chalk.gray(' Non-English text (Ukrainian, Chinese, Japanese, etc.) may show as "?" or garbled glyphs.')),console.log(chalk.gray(" Fix (run before ")+chalk.cyan("icoa")+chalk.gray("): ")+chalk.cyan("chcp 65001")),console.log(chalk.gray(" Or stay in English inside the CLI: ")+chalk.cyan("lang en")),console.log())}else console.log(chalk.yellow(`⚠ Your terminal locale is not UTF-8 (LANG=${n||"(unset)"}).`)),console.log(chalk.gray(' Non-English text and box characters may display as "?" or garbled glyphs.')),console.log(chalk.gray(" Fix: ")+chalk.cyan("export LANG=en_US.UTF-8")+chalk.gray(" (or your locale, e.g. ")+chalk.cyan("zh_CN.UTF-8")+chalk.gray(", ")+chalk.cyan("uk_UA.UTF-8")+chalk.gray(")")),console.log();if(console.log(k),process.argv.length<=2||o.resume)return o.resume||await async function(){const o=process.stdin;if(o.isTTY&&"function"==typeof o.setRawMode)return new Promise(e=>{let n=!1;const r=()=>{if(!n){n=!0,o.removeListener("data",s);try{o.setRawMode(!1)}catch{}o.pause(),e()}},s=()=>r();o.setRawMode(!0),o.resume(),o.once("data",s),console.log(chalk.gray(" (press any key to continue...)")),setTimeout(r,3e3)});await new Promise(o=>setTimeout(o,3e3))}(),void $(N,!!o.resume)}),e(N),n(N),r(N),s(N),t(N),i(N),l(N),a(N),m(N),c(N),g(N),d(N),p(N),y(N),h(N),f(N),u(N),w(N),N.command("model",{hidden:!0}).argument("[name]","model name to switch to").action(o=>{const e=b().geminiModel||"gemini-2.5-flash-lite";o?(T({geminiModel:o}),console.log(),console.log(chalk.green(" Model switched: ")+chalk.gray(e)+chalk.white(" -> ")+chalk.bold.white(o)),console.log()):(console.log(),console.log(chalk.gray(" Current model: ")+chalk.white(e)),console.log(),console.log(chalk.gray(" Available models:")),console.log(chalk.bold.white(" Gemini 3.x (Latest)")),console.log(chalk.white(" model gemini-3.5-flash ")+chalk.gray("Newest stable, paid Tier 1+")),console.log(chalk.white(" model gemini-3-flash-preview ")+chalk.gray("Preview")),console.log(chalk.bold.white(" Gemini 2.5 (Stable)")),console.log(chalk.white(" model gemini-2.5-flash-lite ")+chalk.gray("Fastest, default, free tier")),console.log(chalk.white(" model gemini-2.5-flash ")+chalk.gray("Heavier, thinking enabled")),console.log(chalk.white(" model gemini-2.5-pro ")+chalk.gray("Strong reasoning, paid")),console.log(chalk.bold.white(" Open Source")),console.log(chalk.white(" model gemma-4-31b-it ")+chalk.gray("Free, open-source")),console.log(chalk.white(" model <any-model-id> ")+chalk.gray("Custom model")),console.log(),console.log(chalk.gray(" Translation uses gemini-3.5-flash for best quality.")),console.log())}),"1"===process.env.ICOA_RESET_STATE)try{const{clearExamState:o}=await import("./lib/exam-state.js");o(),console.log(chalk.yellow("⚠ ICOA_RESET_STATE=1 — local exam state wiped.")),console.log(chalk.gray(" (Token NOT revoked server-side. Re-enter a fresh token with `exam <token>`.)")),console.log()}catch(o){console.log(chalk.red("⚠ ICOA_RESET_STATE: could not clear state — ")+chalk.gray(String(o)))}N.parse();
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare const ICOA_BIG: readonly string[];
|
|
2
|
+
/**
|
|
3
|
+
* Ready-to-print logo lines, bold white, indented by `indent`.
|
|
4
|
+
*
|
|
5
|
+
* Degrades to a one-line wordmark when the terminal is too narrow for the block
|
|
6
|
+
* art (Chromebook split-screen / narrow WSL pane), so it never overflow-wraps.
|
|
7
|
+
* 60 cols is the rich-display floor from the cross-platform baseline.
|
|
8
|
+
*/
|
|
9
|
+
export declare function icoaBannerLines(indent?: string): string[];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import chalk from"chalk";export const ICOA_BIG=["██╗ ██████╗ ██████╗ █████╗","██║██╔════╝██╔═══██╗██╔══██╗","██║██║ ██║ ██║███████║","██║██║ ██║ ██║██╔══██║","██║╚██████╗╚██████╔╝██║ ██║","╚═╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝"];export function icoaBannerLines(o=" "){return(process.stdout.columns||80)<60?[o+chalk.bold.white("I C O A")+chalk.gray(" 2026")]:ICOA_BIG.map(t=>o+chalk.bold.white(t))}
|
package/dist/lib/hint-client.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
function
|
|
1
|
+
function a0b(a,b){a=a-(-0x5*0x3ad+-0x837+0x1c57);const c=a0a();let d=c[a];if(a0b['TtueTV']===undefined){var e=function(i){const j='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let l='',m='';for(let n=0x1d43+-0x2*-0x650+-0x29e3,o,p,q=-0x47b*-0x7+-0x7*-0x2df+-0x3376;p=i['charAt'](q++);~p&&(o=n%(0x19c7+0x4fc+-0x1ebf)?o*(-0x3e*0x3+-0x1*0x832+0x92c)+p:p,n++%(0xf95*0x1+0x10d6*-0x1+0x145))?l+=String['fromCharCode'](-0x1*-0x24fb+-0xc*0x2bd+-0x320&o>>(-(0x1902+-0x17*0xbf+-0x9*0xdf)*n&-0xb*-0x315+-0x2f*-0xb9+0x14e*-0x34)):-0x1a5f*-0x1+0x1*0x16b8+-0x105d*0x3){p=j['indexOf'](p);}for(let r=-0x1e99+0x5*-0x34c+0x2f15*0x1,s=l['length'];r<s;r++){m+='%'+('00'+l['charCodeAt'](r)['toString'](-0xd50+-0x376*-0x1+0x9ea))['slice'](-(0x1f*-0xe5+-0x1e1*-0x5+0x1258));}return decodeURIComponent(m);};a0b['UicRXm']=e,a0b['iYmMwF']={},a0b['TtueTV']=!![];}const f=c[0x1d*-0xc4+-0xfed*0x1+0x2621],g=a+f,h=a0b['iYmMwF'][g];return!h?(d=a0b['UicRXm'](d),a0b['iYmMwF'][g]=d):d=h,d;}(function(a,b){const v=a0b,c=a();while(!![]){try{const d=-parseInt(v(0x1db))/(-0x21d3+0xbbd+0x1617)*(-parseInt(v(0x1ce))/(-0x5d3*-0x1+0x1b73*0x1+0x851*-0x4))+-parseInt(v(0x1d0))/(0x199e+-0x1b00+0x165)*(-parseInt(v(0x1d7))/(0x8b8+0x47*-0x59+0x1*0xffb))+parseInt(v(0x1c5))/(-0x11*0x1b+-0x26c1+0x2891)+-parseInt(v(0x1dc))/(0x58f*-0x3+-0xe3*-0x25+-0x80e*0x2)*(parseInt(v(0x1cd))/(-0x9fc+-0xf*0x191+-0x2182*-0x1))+parseInt(v(0x1d6))/(0xfa7*0x2+0x241d*0x1+-0x4363)+-parseInt(v(0x1d3))/(-0x15f9+0x1fb9+-0x1*0x9b7)*(parseInt(v(0x1de))/(0x1*0x264b+0x9f2+0x1*-0x3033))+-parseInt(v(0x1c6))/(0x3d*-0x25+0x9a7+0xcb*-0x1)*(parseInt(v(0x1dd))/(0x219e+-0x2*-0xc22+-0x39d6));if(d===b)break;else c['push'](c['shift']());}catch(e){c['push'](c['shift']());}}}(a0a,-0x116d4+0xafefd*0x1+-0xe0a0));function a0a(){const x=['Bgv2zwW','C3rHDhvZ','yxbWBgLJyxrPB24VANnVBG','Ahr0Chm6lY9WCMfJDgLJzs5Py29HmJaYnI5HDq','ntuYmtyWmenQvgvPAa','mJjwsvPXC20','Dg9Rzw4','CxvLC3rPB24','ANnVBG','oJKWotaVyxbPl2LJB2eVzxHHBxmV','l2HPBNq','AwnVys1JBgK','ntC4ndfSCfPkvge','mtCWodCYnenquLbAzq','ue9tva','mJe2mfrbqMvMCa','zxHHBuLK','BwvZC2fNzq','ovf3vLvqra','BgfUz3vHz2u','y2f0y2G','odK2mZi1nNz1BKPKEq','ntC1mNfjsufxCG','BMv0D29YAYbLCNjVCG','AgLUDcbYzxf1zxn0igzHAwXLzcaO','C3vJy2vZCW','mvDxt3jdCa','mJiYr1PnvwrK','mtmZmJG1ntztwhnZALC','otK1ntm5mg5tyxjQtG','BgfUzW','y3rMzfvYBa'];a0a=function(){return x;};return a0a();}import{getConfig as a0c}from'./config.js';export async function requestHint(d){const w=a0b,f=a0c(),g=f[w(0x1c0)]||w(0x1c4),h=d[w(0x1bf)]||f[w(0x1d4)]||'en',j=d['timeoutMs']??-0x1a57+0x181+0x959*0x6,k=[g+'/api/icoa/exams/'+d[w(0x1d1)]+w(0x1cb),g+w(0x1ca)+d[w(0x1d1)]+w(0x1cb)];let l=null;for(const p of k)try{const q=await fetch(p,{'method':w(0x1cf),'headers':{'Content-Type':w(0x1c3),'User-Agent':w(0x1cc)},'body':JSON['stringify']({'token':d[w(0x1c7)],'question':d[w(0x1c8)],'level':d[w(0x1c1)],'lang':h}),'signal':AbortSignal['timeout'](j)}),r=await q[w(0x1c9)]()[w(0x1d5)](()=>({}));if(!q['ok']||!(-0x3*-0x2fc+-0x1e71+0x3*0x72a)===r[w(0x1da)]){if(l={'status':q['status'],'message':r?.[w(0x1d2)]||w(0x1d9)+q[w(0x1c2)]+')'},q[w(0x1c2)]>=-0x277+-0x1c72+0x2079&&q[w(0x1c2)]<-0x1*-0x1ed3+-0x19a3+-0x12*0x2e)throw l;continue;}return r['data'];}catch(u){if(u&&'object'==typeof u&&w(0x1c2)in u)throw u;l={'status':0x0,'message':u?.['message']||w(0x1d8)};}const m={};m[w(0x1c2)]=0x0,m[w(0x1d2)]='hint\x20API\x20unreachable';throw l||m;}
|
package/dist/lib/learn-render.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import chalk from"chalk";import o from"string-width";import{localized as e}from"./learn-curricula.js";import{t as n}from"./learn-i18n.js";import{getConfig as l}from"./config.js";import{renderCharts as t,detectCaps as r}from"./render-card.js";function c(){return(l().language||"en").toLowerCase()}const s=64;function a(o="─"){return o.repeat(66)}function g(o,e,n=20){const l=e>0?o/e:0,t=Math.floor(l*n),r=n-t;return`${chalk.green("█".repeat(t))+chalk.gray("░".repeat(r))} ${(100*l).toFixed(1)}%`}function i(o){return o>=30?chalk.red("🔥🔥🔥 "+o+" days"):o>=7?chalk.yellow("🔥 "+o+" days"):o>=1?chalk.gray("· "+o+" day"+(o>1?"s":"")):chalk.gray("—")}export function renderWelcome(o,e,l){const t=c(),r=e.cardsCompleted.length,s=o.totalCards,y=s-r,d=o.modules.find(o=>e.currentCard>=o.cardRange[0]&&e.currentCard<=o.cardRange[1]);if(console.log(),console.log(chalk.cyan(" ╭"+a("═"))),console.log(chalk.cyan(" ║")),console.log(chalk.cyan(" ║ ")+chalk.bold.white(" "+n("academy_title",t))),console.log(chalk.cyan(" ║")),l)console.log(chalk.cyan(" ║ ")+chalk.white(" "+n("welcome_new_demo",t)));else{const o=new Date(e.lastSeenAt),l=Math.floor((Date.now()-o.getTime())/36e5),r=l<1?n("just_now",t):l<24?`${l}${n("ago_hours",t)}`:`${Math.floor(l/24)}${n("ago_days",t)}`;console.log(chalk.cyan(" ║ ")+chalk.white(` ${n("welcome_back",t)} ${r}`))}console.log(chalk.cyan(" ║"));const u=d?`${d.number}. ${d.name}`:"—";console.log(chalk.cyan(" ║ ")+" "+chalk.gray(n("module",t).padEnd(11))+chalk.white(u)),console.log(chalk.cyan(" ║ ")+" "+chalk.gray(n("progress",t).padEnd(11))+g(r,s)+chalk.gray(` (${r}/${s})`)),console.log(chalk.cyan(" ║ ")+" "+chalk.gray(n("streak",t).padEnd(11))+i(e.streakDays)),y>0&&e.currentCard<=s&&console.log(chalk.cyan(" ║ ")+" "+chalk.gray(n("next_card",t).padEnd(11))+chalk.white(`#${e.currentCard} ${n("of",t)} ${s}`)),console.log(chalk.cyan(" ║")),console.log(chalk.cyan(" ╰"+a("═"))),console.log(),console.log(chalk.gray(" ─────────────────────────────────────────────"));const h=0===r?n("continue_start",t):`${n("continue_resume",t)} ${e.currentCard}`;console.log(chalk.bold.green(" continue")+chalk.gray(" "+h)),console.log(chalk.yellow(" status")+chalk.gray(" "+n("status_full",t))),e.bookmarks.length>0&&console.log(chalk.yellow(" bookmarks")+chalk.gray(` ${e.bookmarks.length} ${n("bookmarks_desc",t)}`)),console.log(chalk.gray(" quit")+chalk.gray(" "+n("quit_desc",t))),console.log(chalk.gray(" ─────────────────────────────────────────────")),console.log()}function y(o,e){const l=c(),t=o.module,r=e.modules.find(o=>o.number===t),a=r?r.name:n("unknown_module",l),g=n("module",l).replace(":","").trim(),i=`${n("card",l)} ${o.number} / ${e.totalCards} · ${g} ${t} · ${a}`;console.log(),console.log(chalk.cyan(" ╭─ ")+chalk.bold.white(i)+" "+chalk.cyan("─".repeat(Math.max(0,s-i.length-4))))}function d(){console.log(chalk.cyan(" ╰"+a())),console.log()}function u(o){console.log(chalk.cyan(" │ ")+chalk.white(o))}function h(){console.log(chalk.cyan(" │"))}const m=/[┌┐└┘├┤┬┴┼─│╔╗╚╝═║╠╣╦╩╬▓▒░█]/;function f(o){return/^(?: {4}|\t)/.test(o)||m.test(o)||/ {3,}/.test(o)}function b(e,n){const l=[];let t="",r=0,c=!1;for(const s of function(e){const n=[],l=e=>{let l="";const t=()=>{l&&(n.push({t:"atom",s:l}),l="")};for(const r of e)" "===r?(t(),n.push({t:"space"})):2===o(r)?(t(),n.push({t:"wide",s:r})):l+=r;t()},t=/`[^`]*`/g;let r,c=0;for(;null!==(r=t.exec(e));)l(e.slice(c,r.index)),n.push({t:"code",s:r[0]}),c=r.index+r[0].length;return l(e.slice(c)),n}(e)){if("space"===s.t){""!==t&&(c=!0);continue}const e=s.s,a=o("code"===s.t?e.replace(/`/g,""):e),g=c?1:0,i="atom"===s.t&&e.length<=2&&/^[.,;:!?)\]}…'"]+$/.test(e);""!==t&&!i&&r+g+a>n?(l.push(t),t=e,r=a,c=!1):(c&&(t+=" ",r+=1,c=!1),t+=e,r+=a)}return t&&l.push(t),l}const p=/\b(?:Common bug|Common mistake|Common error|Pitfall|Gotcha|Footgun)\b[::]?|\b(?:Warning|Caution)\b[::]|(?:常见错误|常见陷阱|常见误区|陷阱|注意|警告|误区)[::]/gi;function w(o,e){const n=e?chalk.bold.white:chalk.white;let l,t="",r=0;for(p.lastIndex=0;null!==(l=p.exec(o));)l.index>r&&(t+=n(o.slice(r,l.index))),t+=chalk.bold.yellow(l[0]),r=l.index+l[0].length;return r<o.length&&(t+=n(o.slice(r))),t}function _(o,e=!1){let n="",l=0;const t=/`([^`]*)`/g;let r;for(;null!==(r=t.exec(o));)r.index>l&&(n+=w(o.slice(l,r.index),e)),n+=chalk.cyan(r[1]),l=r.index+r[0].length;return l<o.length&&(n+=w(o.slice(l),e)),n}function $(o,e=!1){let n=!1;for(const l of o.split("\n"))if(/^\s*```/.test(l))n=!n;else if(n)console.log(chalk.cyan(" │ ")+chalk.cyan(` ${l}`));else if(""!==l)if(f(l))console.log(chalk.cyan(" │ ")+chalk.white(l));else for(const o of b(l,60))console.log(chalk.cyan(" │ ")+` ${_(o,e)}`);else h()}function k(o,e){const n=[];for(const l of o.split("\n")){if(""===l){n.push("");continue}if(f(l)){n.push(l);continue}let o="";for(const t of l.split(" "))(o+" "+t).trim().length>e?(n.push(o.trim()),o=t):o=(o+" "+t).trim();o&&n.push(o)}return n}export function renderKnowledgeCard(l,a){const g=c(),i=e(l,g);y(i,a),h();const m=b(i.title,60);for(const o of m)u(chalk.bold.yellow(o));u(chalk.gray("─".repeat(Math.min(Math.max(...m.map(e=>o(e))),s))));const f=!!(l.chart_ids&&l.chart_ids.length>0);if(f&&t(l.chart_ids.slice(0,1),a.charts,r()),i.key_point&&""!==i.key_point.trim()?(f||h(),function(o,e,n){const l=c().startsWith("zh"),t=r().cols,a="-".repeat(Math.min(s,Math.max(24,t-6))),g=l?"要点":"KEY POINT",i=l?`第 ${e} / ${n} 张`:`Card ${e} / ${n}`;console.log(chalk.cyan(" │ ")+chalk.green(a)),console.log(chalk.cyan(" │ ")+chalk.green(`${g} · ${i}`));for(const e of b(o,60))console.log(chalk.cyan(" │ ")+chalk.bold.green(" "+e));console.log(chalk.cyan(" │ ")+chalk.green(a)),h()}(i.key_point,i.number,a.totalCards)):f||h(),i.body.filter(o=>null!=o&&""!==o.trim()).forEach((o,e)=>{const n=0===e?o.match(/^([\s\S]*?(?:[.!?](?=\s|$)|[。!?]))(\s[\s\S]*)?$/):null;if(n&&n[1].trim().length<=180){$(n[1],!0);const o=n[2]?.trimStart();o&&$(o,!1)}else $(o,!1);h()}),i.icoaConnection){u(chalk.magenta(" "+n("icoa_connection",g))),u(chalk.gray(" "+"─".repeat(20)));for(const o of b(i.icoaConnection,60))u(" "+chalk.magenta(o));h()}if(l.check){const o=g.startsWith("zh"),e=l._zh?.checkStatement??l._zh?.check?.statement,n=o?e??l.check.statement:l.check.statement;u(chalk.cyan(" 🤔 "+(o?"请回答 (输 y 或 n):":"Quick comprehension check (type y or n):"))),u(chalk.gray(" "+"─".repeat(20)));for(const o of b(n,60))u(" "+chalk.white(o));h()}d(),function(o,e){const n=c().startsWith("zh"),l=r().cols,t="-".repeat(Math.min(s,Math.max(24,l-6))),a=chalk.gray(" "),g=[];o.check?(g.push(chalk.bold.green("[y]")+chalk.gray(n?" 是":" yes")),g.push(chalk.bold.green("[n]")+chalk.gray(n?" 否":" no"))):g.push(chalk.bold.green("[ok]")+chalk.gray(n?" 继续":" next")),g.push(chalk.bold.yellow("[e]")+chalk.gray(n?" 报告问题":" report")),g.push(chalk.bold.cyan("[b]")+chalk.gray(n?" 上一张":" back")),g.push(chalk.bold.cyan("[card N]")+chalk.gray(n?" 跳转":" jump")),g.push(chalk.gray("[quit]")+chalk.gray(n?" 退出":" quit")),console.log(chalk.gray(" "+t)),console.log(chalk.gray(" "+(n?`第 ${o.number} / ${e.totalCards} 张`:`Card ${o.number} / ${e.totalCards}`))),console.log(" "+g.join(a)),console.log(chalk.gray(" "+t)),console.log(chalk.gray(" "+(n?"e = 报告本卡错误,不算作答;提交后回到本题继续":"e = report a problem with this card (not an answer); you return here after"))),console.log(chalk.gray(" "+(n?"更多: bookmark · status · lang zh/en":"more: bookmark · status · lang zh/en"))),console.log()}(l,a)}export function renderCheckFeedback(o,e,n,l=!1){const t=c().startsWith("zh");if(console.log(),n)console.log(chalk.green(" ✓ ")+chalk.white(t?"答对了。":"Correct."));else if(console.log(chalk.yellow(" ✗ ")+chalk.white(t?"记下了,继续。":"Noted — moving on.")),l){const e="y"===o.check?.answer?t?"是":"Yes":t?"否":"No";console.log(chalk.gray(" "+(t?"正确答案: ":"Answer: ")+e+". "+(t?"回看上面那段。":"Re-read the paragraph above.")))}console.log()}export function renderPhaseComplete(o,e,n,l){const t=c().startsWith("zh"),[r,s]=n.cardRange,a=e.checkResults||{};let g=0,i=0;for(let o=r;o<=s;o++){const e=a[String(o)];e&&(g++,e.correct&&i++)}const y="-".repeat(48);console.log(),console.log(chalk.bold.yellow(" "+y)),console.log(chalk.bold.yellow(" "+(t?`阶段 ${n.number} 完成`:`Phase ${n.number} complete`))+chalk.gray(" · ")+chalk.white(n.name));const d=g>0&&i===g?chalk.bold.green:chalk.bold.white;console.log(chalk.gray(" "+(t?"理解检查得分: ":"comprehension score: "))+d(`${i}/${g}`)+chalk.gray(0===g?t?" (本阶段未作答 y/n)":" (no y/n answered)":"")),l&&console.log(chalk.gray(" "+(t?"下一阶段: ":"next: "))+chalk.bold.cyan(t?`阶段 ${l.number}`:`Phase ${l.number}`)+chalk.gray(" · ")+chalk.white(l.name)),console.log(chalk.bold.yellow(" "+y))}export function renderCurriculumComplete(o,e){const n=c().startsWith("zh"),l=e.checkResults||{},t="-".repeat(48);let r=0,s=0;console.log(),console.log(chalk.bold.green(" "+t)),console.log(chalk.bold.green(" 🏆 "+(n?`${o.name} — 全部完成!`:`${o.name} — complete!`))),console.log(chalk.bold.green(" "+t));for(const e of o.modules){const[o,t]=e.cardRange;let c=0,a=0;for(let e=o;e<=t;e++){const o=l[String(e)];o&&(c++,o.correct&&a++)}r+=c,s+=a;const g=c>0&&a===c?chalk.green:chalk.white;console.log(chalk.gray(" "+(n?`阶段 ${e.number}`:`Phase ${e.number}`).padEnd(8))+g(`${a}/${c}`.padEnd(7))+chalk.gray(e.name))}console.log(chalk.bold.green(" "+t)),console.log(chalk.bold.green(" "+(n?"总分 / overall: ":"Overall: "))+chalk.bold.white(`${s}/${r}`)),console.log(chalk.bold.green(" "+t)),console.log()}export function renderMCQCard(o,l){const t=c(),r=e(o,t);y(r,l),h(),u(chalk.bold.yellow("🎯 "+r.title)),u(chalk.gray("─".repeat(Math.min(r.title.length+4,s)))),h();for(const o of k(r.question,60))u(" "+o);h();for(const o of["A","B","C","D"])u(chalk.cyan(` ${o}.`)+" "+chalk.white(r.options[o]));h(),d(),console.log(chalk.gray(" "+(t.startsWith("zh")?"输入 ":"Type "))+chalk.bold.green("A")+chalk.gray(" / ")+chalk.bold.green("B")+chalk.gray(" / ")+chalk.bold.green("C")+chalk.gray(" / ")+chalk.bold.green("D")+chalk.gray(" "+n("type_to_answer",t))),console.log()}export function renderMCQFeedback(o,l,t,r){const s=c(),a=e(o,s);console.log(),t?console.log(" "+chalk.bold.green(n("correct",s)+" ")+chalk.gray(`${n("one_point",s)} · ${l} = ${a.options[l]}`)):console.log(" "+chalk.bold.red(n("not_quite",s)+" ")+chalk.gray(`${n("you_chose",s)} ${l}; ${n("answer_is",s)} ${a.answer}.`)),console.log(),console.log(chalk.gray(" "+n("explanation",s)));for(const o of k(a.explanation,60))console.log(chalk.gray(" "+o));const g=Object.values(r.mcqResults),i=g.filter(o=>o.correct).length;console.log(),console.log(chalk.gray(" "+n("mcq_accuracy_so_far",s)+" ")+chalk.white(`${i}/${g.length}`)),console.log(),t||(console.log(chalk.gray(" "+n("press_ok_continue",s)+" ")+chalk.bold.green("ok")+chalk.gray(" "+n("to_continue",s))),console.log())}export function renderPracticalCard(o,l){const t=c(),r=e(o,t);y(r,l),h(),u(chalk.bold.yellow("🛠 "+r.title)),u(chalk.gray("─".repeat(Math.min(r.title.length+4,s)))),h();for(const o of k(r.task,60))u(" "+o);if(r.starterCode){h(),u(chalk.gray(" "+n("starter_code",t))),h();for(const o of r.starterCode.split("\n"))u(" "+chalk.cyan(o))}h(),d(),console.log(chalk.gray(" "+n("try_in_sandbox",t)+" ")+chalk.bold.cyan("!python3")+chalk.gray(" "+n("drops_into_python",t))),console.log(chalk.gray(" "+n("when_done",t))),console.log(chalk.gray(" ")+chalk.bold.green("done")+chalk.gray(" "+n("done_desc",t))),console.log(chalk.gray(" ")+chalk.bold.yellow("skip")+chalk.gray(" "+n("skip_desc",t))),console.log(chalk.gray(" card N jump to a card by number")),console.log()}export function renderPracticalSuccess(o){const l=c(),t=e(o,l);console.log(),console.log(" "+chalk.bold.green(n("practical_recorded",l))),console.log(),console.log(chalk.gray(" "+n("reference_answer",l)));for(const o of k(t.successHint,60))console.log(chalk.gray(" "+o));console.log(),console.log(chalk.gray(" "+n("press_ok_continue",l)+" ")+chalk.bold.green("ok")+chalk.gray(" "+n("to_continue",l))),console.log()}export function renderSimDemoCard(o,l){const t=c(),r=e(o,t);y(r,l),h(),u(chalk.bold.yellow("🎬 "+r.title)),h();for(const o of k(r.description,60))u(" "+o);h(),u(chalk.gray(" "+n("sim_requires",t))),h(),d(),console.log(chalk.gray(" ")+chalk.bold.cyan("sim")+chalk.gray(" "+n("sim_launch_desc",t))),console.log(chalk.gray(" ")+chalk.bold.green("ok")+chalk.gray(" / ")+chalk.bold.green("next")+chalk.gray(" "+n("continue_to_next",t))),console.log(chalk.gray(" bookmark "+n("bookmark_desc",t))),console.log(chalk.gray(" back "+n("back_desc",t))),console.log(chalk.gray(" card N jump to a card by number")),console.log(chalk.gray(" quit "+n("quit_desc",t))),console.log()}export function renderMilestone(o,l){const t=c(),r=e(o,t),s=o.number===l.totalCards;console.log(),console.log(chalk.bold.yellow(" ╭"+a("═"))),console.log(chalk.bold.yellow(" ║")),console.log(chalk.bold.yellow(" ║ ")+chalk.white(" "+n("milestone_header",t))),console.log(chalk.bold.yellow(" ║"));const g=` ${r.badge} ${r.emoji}`;console.log(chalk.bold.yellow(" ║ ")+chalk.bold.green(g)),console.log(chalk.bold.yellow(" ║ ")+chalk.gray(" ─".repeat(Math.max(1,Math.floor(r.badge.length/2+2))))),console.log(chalk.bold.yellow(" ║")),console.log(chalk.bold.yellow(" ║ ")+" "+chalk.gray(n("in_wild_corresponds",t)));for(const o of k(r.realWorldLevel,60))console.log(chalk.bold.yellow(" ║ ")+" "+chalk.white(o));console.log(chalk.bold.yellow(" ║")),console.log(chalk.bold.yellow(" ║ ")+" "+chalk.gray(n("whats_next",t)));for(const o of k(r.unlockedNext,60))console.log(chalk.bold.yellow(" ║ ")+" "+chalk.white(o));console.log(chalk.bold.yellow(" ║")),console.log(chalk.bold.yellow(" ╰"+a("═"))),console.log(),s?(console.log(chalk.gray(" "+n("demo_complete",t))),console.log(),console.log(chalk.gray(" "+n("unlock_full",t)+" ")+chalk.white(n("curriculum_name",t))+chalk.gray(",")),console.log(chalk.gray(" "+n("contact_team_leader",t)+" ")+chalk.bold.yellow("EA")+chalk.gray(" "+n("learn_token",t))),console.log(chalk.gray(" "+n("or_email",t)+" ")+chalk.cyan("asra@icoa2026.au")+chalk.gray(" "+n("for_partnership",t))),console.log(),console.log(chalk.gray(" "+n("type_quit",t)+" ")+chalk.bold.green("quit")+chalk.gray(" "+n("to_exit",t)+" ")+chalk.bold.green("status")+chalk.gray(" "+n("for_dashboard",t)))):(console.log(chalk.gray(" ")+chalk.bold.green("ok")+chalk.gray(" / ")+chalk.bold.green("next")+chalk.gray(" "+n("continue_to_next",t))),console.log(chalk.gray(" status "+n("status_full",t))),console.log(chalk.gray(" card N jump to a card by number")),console.log(chalk.gray(" quit "+n("quit_desc",t)))),console.log()}export function renderStatus(o,e){const l=c(),t=e.cardsCompleted.length,r=o.totalCards,s=Object.values(e.mcqResults),a=s.filter(o=>o.correct).length;console.log(),console.log(chalk.cyan(" ╭─ ")+chalk.bold.white(n("status_title",l))+" "+chalk.cyan("─".repeat(25))),h(),u(" "+chalk.gray(n("total_progress",l)+" ")+g(t,r)+chalk.gray(` (${t}/${r})`)),u(" "+chalk.gray(n("streak",l)+" ")+i(e.streakDays)+chalk.gray(` (${n("longest",l)} ${e.longestStreak})`)),u(" "+chalk.gray(n("mcq_accuracy",l)+" ")+chalk.white(`${a}/${s.length}`)),u(" "+chalk.gray(n("practicals_done",l)+" ")+chalk.white(`${e.practicalsCompleted.length}`)),u(" "+chalk.gray(n("bookmarked",l)+" ")+chalk.white(`${e.bookmarks.length}`)),h();const y=n("module",l).replace(":","").trim();for(const n of o.modules){const[o,l]=n.cardRange,t=e.cardsCompleted.filter(e=>e>=o&&e<=l).length,r=l-o+1;u(" "+(t===r?chalk.green("✓"):t>0?chalk.yellow("▶"):chalk.gray("□"))+" "+chalk.gray(`${y} ${n.number}: `)+chalk.white(`${t}/${r}`)+chalk.gray(" "+n.name))}if(h(),e.achievements.length>0){u(" "+chalk.gray(n("achievements",l)));for(const o of e.achievements)u(" "+chalk.bold.yellow("★ ")+chalk.white(o))}else u(" "+chalk.gray(n("achievements_none",l)));h(),d()}
|
|
1
|
+
import chalk from"chalk";import o from"string-width";import{localized as e}from"./learn-curricula.js";import{t as n}from"./learn-i18n.js";import{getConfig as l}from"./config.js";import{icoaBannerLines as t}from"./banner.js";import{renderCharts as r,detectCaps as c}from"./render-card.js";function s(){return(l().language||"en").toLowerCase()}const a=64;function g(o="─"){return o.repeat(66)}function i(o,e,n=20){const l=e>0?o/e:0,t=Math.floor(l*n),r=n-t;return`${chalk.green("█".repeat(t))+chalk.gray("░".repeat(r))} ${(100*l).toFixed(1)}%`}function d(o){return o>=30?chalk.red("🔥🔥🔥 "+o+" days"):o>=7?chalk.yellow("🔥 "+o+" days"):o>=1?chalk.gray("· "+o+" day"+(o>1?"s":"")):chalk.gray("—")}export function renderWelcome(o,e,l){const t=s(),r=e.cardsCompleted.length,c=o.totalCards,a=c-r,y=o.modules.find(o=>e.currentCard>=o.cardRange[0]&&e.currentCard<=o.cardRange[1]);if(console.log(),console.log(chalk.cyan(" ╭"+g("═"))),console.log(chalk.cyan(" ║")),console.log(chalk.cyan(" ║ ")+chalk.bold.white(" "+n("academy_title",t))),console.log(chalk.cyan(" ║")),l)console.log(chalk.cyan(" ║ ")+chalk.white(" "+n("welcome_new_demo",t)));else{const o=new Date(e.lastSeenAt),l=Math.floor((Date.now()-o.getTime())/36e5),r=l<1?n("just_now",t):l<24?`${l}${n("ago_hours",t)}`:`${Math.floor(l/24)}${n("ago_days",t)}`;console.log(chalk.cyan(" ║ ")+chalk.white(` ${n("welcome_back",t)} ${r}`))}console.log(chalk.cyan(" ║"));const u=y?`${y.number}. ${y.name}`:"—";console.log(chalk.cyan(" ║ ")+" "+chalk.gray(n("module",t).padEnd(11))+chalk.white(u)),console.log(chalk.cyan(" ║ ")+" "+chalk.gray(n("progress",t).padEnd(11))+i(r,c)+chalk.gray(` (${r}/${c})`)),console.log(chalk.cyan(" ║ ")+" "+chalk.gray(n("streak",t).padEnd(11))+d(e.streakDays)),a>0&&e.currentCard<=c&&console.log(chalk.cyan(" ║ ")+" "+chalk.gray(n("next_card",t).padEnd(11))+chalk.white(`#${e.currentCard} ${n("of",t)} ${c}`)),console.log(chalk.cyan(" ║")),console.log(chalk.cyan(" ╰"+g("═"))),console.log(),console.log(chalk.gray(" ─────────────────────────────────────────────"));const h=0===r?n("continue_start",t):`${n("continue_resume",t)} ${e.currentCard}`;console.log(chalk.bold.green(" continue")+chalk.gray(" "+h)),console.log(chalk.yellow(" status")+chalk.gray(" "+n("status_full",t))),e.bookmarks.length>0&&console.log(chalk.yellow(" bookmarks")+chalk.gray(` ${e.bookmarks.length} ${n("bookmarks_desc",t)}`)),console.log(chalk.gray(" quit")+chalk.gray(" "+n("quit_desc",t))),console.log(chalk.gray(" ─────────────────────────────────────────────")),console.log()}function y(o,e){const l=s(),t=o.module,r=e.modules.find(o=>o.number===t),c=r?r.name:n("unknown_module",l),g=n("module",l).replace(":","").trim(),i=`${n("card",l)} ${o.number} / ${e.totalCards} · ${g} ${t} · ${c}`;console.log(),console.log(chalk.cyan(" ╭─ ")+chalk.bold.white(i)+" "+chalk.cyan("─".repeat(Math.max(0,a-i.length-4))))}function u(){console.log(chalk.cyan(" ╰"+g())),console.log()}function h(o){console.log(chalk.cyan(" │ ")+chalk.white(o))}function m(){console.log(chalk.cyan(" │"))}const f=/[┌┐└┘├┤┬┴┼─│╔╗╚╝═║╠╣╦╩╬▓▒░█]/;function b(o){return/^(?: {4}|\t)/.test(o)||f.test(o)||/ {3,}/.test(o)}function p(e,n){const l=[];let t="",r=0,c=!1;for(const s of function(e){const n=[],l=e=>{let l="";const t=()=>{l&&(n.push({t:"atom",s:l}),l="")};for(const r of e)" "===r?(t(),n.push({t:"space"})):2===o(r)?(t(),n.push({t:"wide",s:r})):l+=r;t()},t=/`[^`]*`/g;let r,c=0;for(;null!==(r=t.exec(e));)l(e.slice(c,r.index)),n.push({t:"code",s:r[0]}),c=r.index+r[0].length;return l(e.slice(c)),n}(e)){if("space"===s.t){""!==t&&(c=!0);continue}const e=s.s,a=o("code"===s.t?e.replace(/`/g,""):e),g=c?1:0,i="atom"===s.t&&e.length<=2&&/^[.,;:!?)\]}…'"]+$/.test(e);""!==t&&!i&&r+g+a>n?(l.push(t),t=e,r=a,c=!1):(c&&(t+=" ",r+=1,c=!1),t+=e,r+=a)}return t&&l.push(t),l}const w=/\b(?:Common bug|Common mistake|Common error|Pitfall|Gotcha|Footgun)\b[::]?|\b(?:Warning|Caution)\b[::]|(?:常见错误|常见陷阱|常见误区|陷阱|注意|警告|误区)[::]/gi;function _(o,e){const n=e?chalk.bold.white:chalk.white;let l,t="",r=0;for(w.lastIndex=0;null!==(l=w.exec(o));)l.index>r&&(t+=n(o.slice(r,l.index))),t+=chalk.bold.yellow(l[0]),r=l.index+l[0].length;return r<o.length&&(t+=n(o.slice(r))),t}function $(o,e=!1){let n="",l=0;const t=/`([^`]*)`/g;let r;for(;null!==(r=t.exec(o));)r.index>l&&(n+=_(o.slice(l,r.index),e)),n+=chalk.cyan(r[1]),l=r.index+r[0].length;return l<o.length&&(n+=_(o.slice(l),e)),n}function k(o,e=!1){let n=!1;for(const l of o.split("\n"))if(/^\s*```/.test(l))n=!n;else if(n)console.log(chalk.cyan(" │ ")+chalk.cyan(` ${l}`));else if(""!==l)if(b(l))console.log(chalk.cyan(" │ ")+chalk.white(l));else for(const o of p(l,60))console.log(chalk.cyan(" │ ")+` ${$(o,e)}`);else m()}function C(o,e){const n=[];for(const l of o.split("\n")){if(""===l){n.push("");continue}if(b(l)){n.push(l);continue}let o="";for(const t of l.split(" "))(o+" "+t).trim().length>e?(n.push(o.trim()),o=t):o=(o+" "+t).trim();o&&n.push(o)}return n}export function renderKnowledgeCard(l,t){const g=s(),i=e(l,g);y(i,t),m();const d=p(i.title,60);for(const o of d)h(chalk.bold.yellow(o));h(chalk.gray("─".repeat(Math.min(Math.max(...d.map(e=>o(e))),a))));const f=!!(l.chart_ids&&l.chart_ids.length>0);if(f&&r(l.chart_ids.slice(0,1),t.charts,c()),i.key_point&&""!==i.key_point.trim()?(f||m(),function(o,e,n){const l=s().startsWith("zh"),t=c().cols,r="-".repeat(Math.min(a,Math.max(24,t-6))),g=l?"要点":"KEY POINT",i=l?`第 ${e} / ${n} 张`:`Card ${e} / ${n}`;console.log(chalk.cyan(" │ ")+chalk.green(r)),console.log(chalk.cyan(" │ ")+chalk.green(`${g} · ${i}`));for(const e of p(o,60))console.log(chalk.cyan(" │ ")+chalk.bold.green(" "+e));console.log(chalk.cyan(" │ ")+chalk.green(r)),m()}(i.key_point,i.number,t.totalCards)):f||m(),i.body.filter(o=>null!=o&&""!==o.trim()).forEach((o,e)=>{const n=0===e?o.match(/^([\s\S]*?(?:[.!?](?=\s|$)|[。!?]))(\s[\s\S]*)?$/):null;if(n&&n[1].trim().length<=180){k(n[1],!0);const o=n[2]?.trimStart();o&&k(o,!1)}else k(o,!1);m()}),i.icoaConnection){h(chalk.magenta(" "+n("icoa_connection",g))),h(chalk.gray(" "+"─".repeat(20)));for(const o of p(i.icoaConnection,60))h(" "+chalk.magenta(o));m()}if(l.check){const o=g.startsWith("zh"),e=l._zh?.checkStatement??l._zh?.check?.statement,n=o?e??l.check.statement:l.check.statement;h(chalk.cyan(" 🤔 "+(o?"请回答 (输 y 或 n):":"Quick comprehension check (type y or n):"))),h(chalk.gray(" "+"─".repeat(20)));for(const o of p(n,60))h(" "+chalk.white(o));m()}u(),function(o,e){const n=s().startsWith("zh"),l=c().cols,t="-".repeat(Math.min(a,Math.max(24,l-6))),r=chalk.gray(" "),g=[];o.check?(g.push(chalk.bold.green("[y]")+chalk.gray(n?" 是":" yes")),g.push(chalk.bold.green("[n]")+chalk.gray(n?" 否":" no"))):g.push(chalk.bold.green("[ok]")+chalk.gray(n?" 继续":" next")),g.push(chalk.bold.yellow("[e]")+chalk.gray(n?" 报告问题":" report")),g.push(chalk.bold.cyan("[b]")+chalk.gray(n?" 上一张":" back")),g.push(chalk.bold.cyan("[card N]")+chalk.gray(n?" 跳转":" jump")),g.push(chalk.gray("[quit]")+chalk.gray(n?" 退出":" quit")),console.log(chalk.gray(" "+t)),console.log(chalk.gray(" "+(n?`第 ${o.number} / ${e.totalCards} 张`:`Card ${o.number} / ${e.totalCards}`))),console.log(" "+g.join(r)),console.log(chalk.gray(" "+t)),console.log(chalk.gray(" "+(n?"e = 报告本卡错误,不算作答;提交后回到本题继续":"e = report a problem with this card (not an answer); you return here after"))),console.log(chalk.gray(" "+(n?"更多: bookmark · status · lang zh/en":"more: bookmark · status · lang zh/en"))),console.log()}(l,t)}export function renderCheckFeedback(o,e,n,l=!1){const t=s().startsWith("zh");if(console.log(),n)console.log(chalk.green(" ✓ ")+chalk.white(t?"答对了。":"Correct."));else if(console.log(chalk.yellow(" ✗ ")+chalk.white(t?"记下了,继续。":"Noted — moving on.")),l){const e="y"===o.check?.answer?t?"是":"Yes":t?"否":"No";console.log(chalk.gray(" "+(t?"正确答案: ":"Answer: ")+e+". "+(t?"回看上面那段。":"Re-read the paragraph above.")))}console.log()}function x(o){return[chalk.white(" "+(o?"编著:Charlie Zhu":"Created & edited by Charlie Zhu")),chalk.gray(" "+(o?"ICOA 2026 创始人 · 课程总架构师":"Founder & Chief Curriculum Architect · ICOA 2026"))]}export function renderPhaseComplete(o,e,n,l){const r=s().startsWith("zh"),[c,a]=n.cardRange,g=e.checkResults||{};let i=0,d=0;for(let o=c;o<=a;o++){const e=g[String(o)];e&&(i++,e.correct&&d++)}const y="-".repeat(48);console.log();for(const o of t(" "))console.log(o);console.log(),console.log(chalk.bold.yellow(" "+y)),console.log(chalk.bold.yellow(" "+(r?`阶段 ${n.number} 完成`:`Phase ${n.number} complete`))+chalk.gray(" · ")+chalk.white(n.name));const u=i>0&&d===i?chalk.bold.green:chalk.bold.white;console.log(chalk.gray(" "+(r?"理解检查得分: ":"comprehension score: "))+u(`${d}/${i}`)+chalk.gray(0===i?r?" (本阶段未作答 y/n)":" (no y/n answered)":"")),l&&console.log(chalk.gray(" "+(r?"下一阶段: ":"next: "))+chalk.bold.cyan(r?`阶段 ${l.number}`:`Phase ${l.number}`)+chalk.gray(" · ")+chalk.white(l.name)),console.log(chalk.bold.yellow(" "+y));for(const o of x(r))console.log(o)}export function renderCurriculumComplete(o,e){const n=s().startsWith("zh"),l=e.checkResults||{},r="-".repeat(48);let c=0,a=0;console.log();for(const o of t(" "))console.log(o);console.log(),console.log(chalk.bold.green(" "+r)),console.log(chalk.bold.green(" 🏆 "+(n?`${o.name} — 全部完成!`:`${o.name} — complete!`))),console.log(chalk.bold.green(" "+r));for(const e of o.modules){const[o,t]=e.cardRange;let r=0,s=0;for(let e=o;e<=t;e++){const o=l[String(e)];o&&(r++,o.correct&&s++)}c+=r,a+=s;const g=r>0&&s===r?chalk.green:chalk.white;console.log(chalk.gray(" "+(n?`阶段 ${e.number}`:`Phase ${e.number}`).padEnd(8))+g(`${s}/${r}`.padEnd(7))+chalk.gray(e.name))}console.log(chalk.bold.green(" "+r)),console.log(chalk.bold.green(" "+(n?"总分 / overall: ":"Overall: "))+chalk.bold.white(`${a}/${c}`)),console.log(chalk.bold.green(" "+r));for(const o of x(n))console.log(o);console.log()}export function renderMCQCard(o,l){const t=s(),r=e(o,t);y(r,l),m(),h(chalk.bold.yellow("🎯 "+r.title)),h(chalk.gray("─".repeat(Math.min(r.title.length+4,a)))),m();for(const o of C(r.question,60))h(" "+o);m();for(const o of["A","B","C","D"])h(chalk.cyan(` ${o}.`)+" "+chalk.white(r.options[o]));m(),u(),console.log(chalk.gray(" "+(t.startsWith("zh")?"输入 ":"Type "))+chalk.bold.green("A")+chalk.gray(" / ")+chalk.bold.green("B")+chalk.gray(" / ")+chalk.bold.green("C")+chalk.gray(" / ")+chalk.bold.green("D")+chalk.gray(" "+n("type_to_answer",t))),console.log()}export function renderMCQFeedback(o,l,t,r){const c=s(),a=e(o,c);console.log(),t?console.log(" "+chalk.bold.green(n("correct",c)+" ")+chalk.gray(`${n("one_point",c)} · ${l} = ${a.options[l]}`)):console.log(" "+chalk.bold.red(n("not_quite",c)+" ")+chalk.gray(`${n("you_chose",c)} ${l}; ${n("answer_is",c)} ${a.answer}.`)),console.log(),console.log(chalk.gray(" "+n("explanation",c)));for(const o of C(a.explanation,60))console.log(chalk.gray(" "+o));const g=Object.values(r.mcqResults),i=g.filter(o=>o.correct).length;console.log(),console.log(chalk.gray(" "+n("mcq_accuracy_so_far",c)+" ")+chalk.white(`${i}/${g.length}`)),console.log(),t||(console.log(chalk.gray(" "+n("press_ok_continue",c)+" ")+chalk.bold.green("ok")+chalk.gray(" "+n("to_continue",c))),console.log())}export function renderPracticalCard(o,l){const t=s(),r=e(o,t);y(r,l),m(),h(chalk.bold.yellow("🛠 "+r.title)),h(chalk.gray("─".repeat(Math.min(r.title.length+4,a)))),m();for(const o of C(r.task,60))h(" "+o);if(r.starterCode){m(),h(chalk.gray(" "+n("starter_code",t))),m();for(const o of r.starterCode.split("\n"))h(" "+chalk.cyan(o))}m(),u(),console.log(chalk.gray(" "+n("try_in_sandbox",t)+" ")+chalk.bold.cyan("!python3")+chalk.gray(" "+n("drops_into_python",t))),console.log(chalk.gray(" "+n("when_done",t))),console.log(chalk.gray(" ")+chalk.bold.green("done")+chalk.gray(" "+n("done_desc",t))),console.log(chalk.gray(" ")+chalk.bold.yellow("skip")+chalk.gray(" "+n("skip_desc",t))),console.log(chalk.gray(" card N jump to a card by number")),console.log()}export function renderPracticalSuccess(o){const l=s(),t=e(o,l);console.log(),console.log(" "+chalk.bold.green(n("practical_recorded",l))),console.log(),console.log(chalk.gray(" "+n("reference_answer",l)));for(const o of C(t.successHint,60))console.log(chalk.gray(" "+o));console.log(),console.log(chalk.gray(" "+n("press_ok_continue",l)+" ")+chalk.bold.green("ok")+chalk.gray(" "+n("to_continue",l))),console.log()}export function renderSimDemoCard(o,l){const t=s(),r=e(o,t);y(r,l),m(),h(chalk.bold.yellow("🎬 "+r.title)),m();for(const o of C(r.description,60))h(" "+o);m(),h(chalk.gray(" "+n("sim_requires",t))),m(),u(),console.log(chalk.gray(" ")+chalk.bold.cyan("sim")+chalk.gray(" "+n("sim_launch_desc",t))),console.log(chalk.gray(" ")+chalk.bold.green("ok")+chalk.gray(" / ")+chalk.bold.green("next")+chalk.gray(" "+n("continue_to_next",t))),console.log(chalk.gray(" bookmark "+n("bookmark_desc",t))),console.log(chalk.gray(" back "+n("back_desc",t))),console.log(chalk.gray(" card N jump to a card by number")),console.log(chalk.gray(" quit "+n("quit_desc",t))),console.log()}export function renderMilestone(o,l){const t=s(),r=e(o,t),c=o.number===l.totalCards;console.log(),console.log(chalk.bold.yellow(" ╭"+g("═"))),console.log(chalk.bold.yellow(" ║")),console.log(chalk.bold.yellow(" ║ ")+chalk.white(" "+n("milestone_header",t))),console.log(chalk.bold.yellow(" ║"));const a=` ${r.badge} ${r.emoji}`;console.log(chalk.bold.yellow(" ║ ")+chalk.bold.green(a)),console.log(chalk.bold.yellow(" ║ ")+chalk.gray(" ─".repeat(Math.max(1,Math.floor(r.badge.length/2+2))))),console.log(chalk.bold.yellow(" ║")),console.log(chalk.bold.yellow(" ║ ")+" "+chalk.gray(n("in_wild_corresponds",t)));for(const o of C(r.realWorldLevel,60))console.log(chalk.bold.yellow(" ║ ")+" "+chalk.white(o));console.log(chalk.bold.yellow(" ║")),console.log(chalk.bold.yellow(" ║ ")+" "+chalk.gray(n("whats_next",t)));for(const o of C(r.unlockedNext,60))console.log(chalk.bold.yellow(" ║ ")+" "+chalk.white(o));console.log(chalk.bold.yellow(" ║")),console.log(chalk.bold.yellow(" ╰"+g("═"))),console.log(),c?(console.log(chalk.gray(" "+n("demo_complete",t))),console.log(),console.log(chalk.gray(" "+n("unlock_full",t)+" ")+chalk.white(n("curriculum_name",t))+chalk.gray(",")),console.log(chalk.gray(" "+n("contact_team_leader",t)+" ")+chalk.bold.yellow("EA")+chalk.gray(" "+n("learn_token",t))),console.log(chalk.gray(" "+n("or_email",t)+" ")+chalk.cyan("asra@icoa2026.au")+chalk.gray(" "+n("for_partnership",t))),console.log(),console.log(chalk.gray(" "+n("type_quit",t)+" ")+chalk.bold.green("quit")+chalk.gray(" "+n("to_exit",t)+" ")+chalk.bold.green("status")+chalk.gray(" "+n("for_dashboard",t)))):(console.log(chalk.gray(" ")+chalk.bold.green("ok")+chalk.gray(" / ")+chalk.bold.green("next")+chalk.gray(" "+n("continue_to_next",t))),console.log(chalk.gray(" status "+n("status_full",t))),console.log(chalk.gray(" card N jump to a card by number")),console.log(chalk.gray(" quit "+n("quit_desc",t)))),console.log()}export function renderStatus(o,e){const l=s(),t=e.cardsCompleted.length,r=o.totalCards,c=Object.values(e.mcqResults),a=c.filter(o=>o.correct).length;console.log(),console.log(chalk.cyan(" ╭─ ")+chalk.bold.white(n("status_title",l))+" "+chalk.cyan("─".repeat(25))),m(),h(" "+chalk.gray(n("total_progress",l)+" ")+i(t,r)+chalk.gray(` (${t}/${r})`)),h(" "+chalk.gray(n("streak",l)+" ")+d(e.streakDays)+chalk.gray(` (${n("longest",l)} ${e.longestStreak})`)),h(" "+chalk.gray(n("mcq_accuracy",l)+" ")+chalk.white(`${a}/${c.length}`)),h(" "+chalk.gray(n("practicals_done",l)+" ")+chalk.white(`${e.practicalsCompleted.length}`)),h(" "+chalk.gray(n("bookmarked",l)+" ")+chalk.white(`${e.bookmarks.length}`)),m();const g=n("module",l).replace(":","").trim();for(const n of o.modules){const[o,l]=n.cardRange,t=e.cardsCompleted.filter(e=>e>=o&&e<=l).length,r=l-o+1;h(" "+(t===r?chalk.green("✓"):t>0?chalk.yellow("▶"):chalk.gray("□"))+" "+chalk.gray(`${g} ${n.number}: `)+chalk.white(`${t}/${r}`)+chalk.gray(" "+n.name))}if(m(),e.achievements.length>0){h(" "+chalk.gray(n("achievements",l)));for(const o of e.achievements)h(" "+chalk.bold.yellow("★ ")+chalk.white(o))}else h(" "+chalk.gray(n("achievements_none",l)));m(),u()}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "icoa-cli",
|
|
3
|
-
"version": "2.19.
|
|
3
|
+
"version": "2.19.242",
|
|
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": {
|