icoa-cli 2.19.431 → 2.19.433
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/ai4ctf.js +1 -1
- package/dist/commands/ctf4ai-demo.js +1 -1
- package/dist/commands/ctf4vla.js +1 -1
- package/dist/commands/exam.js +1 -1
- package/dist/commands/kaggle.js +1 -1
- package/dist/commands/learn.js +1 -1
- package/dist/data/sprint-cards.json +229 -247
- package/dist/data/sprint-tasks.json +380 -406
- package/dist/index.js +1 -1
- package/dist/lib/kaggle.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 s}from"./commands/shell.js";import{registerFilesCommand as r}from"./commands/files.js";import{registerViewCommand as t}from"./commands/view.js";import{registerConnectCommand as l}from"./commands/connect.js";import{registerChallengeCommand as i}from"./commands/challenge.js";import{registerDoctorCommand as a}from"./commands/doctor.js";import{registerNoteCommand as m}from"./commands/note.js";import{registerLogCommand as c}from"./commands/log.js";import{registerLangCommand as g}from"./commands/lang.js";import{registerSetupCommand as d}from"./commands/setup.js";import{registerEnvCommand as p}from"./commands/env.js";import{registerAienvCommand as y}from"./commands/aienv.js";import{registerIpynbCommand as f}from"./commands/ipynb.js";import{registerAi4ctfCommand as h}from"./commands/ai4ctf.js";import{registerExamCommand as u}from"./commands/exam.js";import{registerCtf4aiDemoCommand as w}from"./commands/ctf4ai-demo.js";import{registerThemeCommand as b}from"./commands/theme.js";import{registerLearnCommand as v}from"./commands/learn.js";import{registerCtf4VlaCommand as T}from"./commands/ctf4vla.js";import{registerDemo2Command as j}from"./commands/demo2.js";import{registerDemo4Command as A}from"./commands/demo4.js";import{registerDemo5Command as $}from"./commands/demo5.js";import{registerSimCommand as I}from"./commands/sim.js";import{registerArenaCommand as C}from"./commands/arena.js";import{registerKaggleCommand as E}from"./commands/kaggle.js";import{registerSprintCommand as _}from"./commands/sprint.js";import{registerTeleloadCommand as S}from"./commands/teleload.js";import{registerBoardCommand as x}from"./commands/board.js";import{getConfig as O,saveConfig as k}from"./lib/config.js";import{startRepl as L}from"./repl.js";import{RELAUNCH_CODE as N}from"./lib/menu-nav.js";import{setTerminalTheme as R}from"./lib/theme.js";import{cleanupTerminal as F}from"./lib/terminal-cleanup.js";import{checkForUpdates as U}from"./lib/update-check.js";import{detectIcoaInstalls as P,isWindowsBuildInWslShell as M}from"./lib/platform.js";import{ICOA_BIG as D}from"./lib/banner.js";import{readFileSync as G}from"node:fs";import{fileURLToPath as W}from"node:url";import{dirname as H,join as Y}from"node:path";const J=H(W(import.meta.url)),V=JSON.parse(G(Y(J,"..","package.json"),"utf-8")).version,X=chalk.cyan(" ─────────────────────────────────────────────────────"),q=`\n${X}\n\n${D.map(o=>` ${chalk.bold.white(o)}`).join("\n")}\n\n ${chalk.yellow("International Cyber Olympiad in AI 2026")}\n ${chalk.bold.magenta("The World's First AI-Native CLI Operating System")}\n ${chalk.bold.magenta("for Cybersecurity & AI Security Competition")}\n ${chalk.bold.magenta("and Olympiad for K-12")}\n\n ${chalk.green.bold("AI4CTF")} ${chalk.gray("[Day 1]")} ${chalk.white("AI as your teammate")}\n ${chalk.red.bold("CTF4AI")} ${chalk.gray("[Day 2]")} ${chalk.white("Challenge & evaluate AI systems")}\n ${chalk.cyan.bold("CTF4EAI")} ${chalk.gray("[Pioneer]")} ${chalk.white("Embodied AI security")}\n ${chalk.bold.yellow("AI is your teammate. AI is your target. AI is embodied.")}\n\n ${chalk.white("Sydney, Australia")} ${chalk.gray("Jun 27 - Jul 2, 2026")}\n ${chalk.cyan.underline("https://icoa2026.au")}\n\n ${chalk.gray(`CLI-Native Competition Terminal v${V}`)}\n\n${X}\n`;process.on("uncaughtException",o=>{"__REPL_NO_EXIT__"!==o.message&&(console.error(chalk.red("Error:"),o.message),process.exit(1))}),process.on("unhandledRejection",o=>{const e=o instanceof Error?o.message:String(o);"__REPL_NO_EXIT__"!==e&&(console.error(chalk.red("Error:"),e),process.exit(1))});{const o=process.argv.slice(2).some(o=>["-V","--version","-h","--help"].includes(o));if(!0===process.stdin.isTTY&&"1"!==process.env.ICOA_SUPERVISED&&!o){const{spawnSync:o}=await import("node:child_process");process.on("SIGINT",()=>{}),process.on("SIGTERM",()=>{});let e=0,n=!1;do{const s=n?process.argv.slice(1,2):process.argv.slice(1),r=o(process.execPath,s,{stdio:"inherit",env:{...process.env,ICOA_SUPERVISED:"1",...n?{ICOA_RELAUNCH:"1"}:{}}});if(r.signal){e=0;break}e=r.status,n=!0}while(e===N);F(),process.exit(e??0)}}const z=new o;if(z.name("icoa").version(V).description("ICOA CLI — CLI-Native CTF Competition Terminal").option("--resume","Resume previous session").option("--continue","Continue where you left off — jump straight to your last learn card / exam").action(async o=>{const e=O();R("high-contrast"===e.themeVariant?"high-contrast":"dark"),U(),function(){const o=P();if(o.length<=1)return;const e=o[0];if([...o.map(o=>o.version||"0.0.0")].sort((o,e)=>function(o,e){const n=o.split(".").map(o=>parseInt(o,10)||0),s=e.split(".").map(o=>parseInt(o,10)||0);for(let o=0;o<3;o++)if((n[o]||0)!==(s[o]||0))return(n[o]||0)-(s[o]||0);return 0}(e,o))[0]!==e.version){console.log(),console.log(chalk.yellow.bold(" ⚠ Multiple icoa installations detected on PATH:"));for(let e=0;e<o.length;e++){const n=o[e],s=n.version?`v${n.version}`:"(version unreadable)",r=0===e?chalk.yellow("→"):" ",t=0===e?chalk.gray(" ← currently running (older — shadowing newer install)"):chalk.gray(" ← shadowed");console.log(` ${r} ${chalk.cyan(n.path.padEnd(28))} ${chalk.white(s)}${t}`)}console.log(),console.log(chalk.yellow(" The first install on PATH wins. To use the newer one, remove the older:")),console.log(),e.pkgDir?console.log(` ${chalk.bold.cyan(`sudo rm -rf ${e.pkgDir} ${e.path}`)}`):console.log(` ${chalk.bold.cyan(`sudo rm -rf ${e.path} # also delete its node_modules dir`)}`),console.log(),console.log(chalk.gray(" Then re-run icoa to confirm version banner shows the newer release.")),console.log()}}(),function(){if(!M())return;const o="─".repeat(52);console.log(),console.log(chalk.yellow(` ${o}`)),console.log(chalk.yellow.bold(" ⚠ You ARE inside Ubuntu — but this icoa")),console.log(chalk.yellow.bold(" is the WINDOWS build.")),console.log(),console.log(chalk.gray(" WSL appends the Windows PATH, so ")+chalk.cyan("icoa")),console.log(chalk.gray(" found the Windows copy first. Almost")),console.log(chalk.gray(" nothing will work: no vi, no python3,")),console.log(chalk.gray(" env setup cannot install.")),console.log(),console.log(chalk.white(" Fix — inside Ubuntu:")),console.log(` ${chalk.bold.cyan("npm install -g icoa-cli")}`),console.log(chalk.gray(" Check: ")+chalk.bold.cyan("which icoa")+chalk.gray(" (not /mnt/c/...)")),console.log(chalk.yellow(` ${o}`)),console.log()}();const n=process.env.LANG||process.env.LC_ALL||process.env.LC_CTYPE||"";if(!/UTF-?8/i.test(n))if("win32"===process.platform){let o="";try{const{execFileSync:e}=await import("node:child_process");o=e("chcp.com",[],{encoding:"utf-8",timeout:1500,stdio:["ignore","pipe","ignore"]}).trim()}catch{}o.includes("65001")||(console.log(chalk.yellow(`⚠ Windows terminal is not using UTF-8 (current: ${o||"unknown"}).`)),console.log(chalk.gray(' Non-English text (Ukrainian, Chinese, Japanese, etc.) may show as "?" or garbled glyphs.')),console.log(chalk.gray(" Fix (run before ")+chalk.cyan("icoa")+chalk.gray("): ")+chalk.cyan("chcp 65001")),console.log(chalk.gray(" Or stay in English inside the CLI: ")+chalk.cyan("lang en")),console.log())}else console.log(chalk.yellow(`⚠ Your terminal locale is not UTF-8 (LANG=${n||"(unset)"}).`)),console.log(chalk.gray(' Non-English text and box characters may display as "?" or garbled glyphs.')),console.log(chalk.gray(" Fix: ")+chalk.cyan("export LANG=en_US.UTF-8")+chalk.gray(" (or your locale, e.g. ")+chalk.cyan("zh_CN.UTF-8")+chalk.gray(", ")+chalk.cyan("uk_UA.UTF-8")+chalk.gray(")")),console.log();console.log(q);const s=!!o.resume||!!o.continue;if(process.argv.length<=2||s)return o.continue&&(process.env.ICOA_AUTO_RESUME="1"),s||"1"===process.env.ICOA_RELAUNCH||await async function(){const o=process.stdin;if(o.isTTY&&"function"==typeof o.setRawMode)return new Promise(e=>{let n=!1;const s=()=>{if(!n){n=!0,o.removeListener("data",r);try{o.setRawMode(!1)}catch{}o.pause(),e()}},r=()=>s();o.setRawMode(!0),o.resume(),o.once("data",r),console.log(chalk.gray(" (press any key to continue...)")),setTimeout(s,3e3)});await new Promise(o=>setTimeout(o,3e3))}(),void L(z,s)}),e(z),n(z),s(z),r(z),t(z),l(z),i(z),a(z),m(z),c(z),g(z),d(z),p(z),y(z),f(z),h(z),u(z),w(z),b(z),v(z),T(z),j(z),A(z),$(z),I(z),C(z),E(z),S(z),_(z),x(z),z.command("model",{hidden:!0}).argument("[name]","model name to switch to").action(o=>{const e=O().geminiModel||"gemini-2.5-flash-lite";o?(k({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)))}z.parse();
|
|
2
|
+
import{Command as o}from"commander";import chalk from"chalk";import{registerCtfCommands as e}from"./commands/ctf.js";import{registerRefCommand as n}from"./commands/ref.js";import{registerShellCommand as s}from"./commands/shell.js";import{registerFilesCommand as r}from"./commands/files.js";import{registerViewCommand as t}from"./commands/view.js";import{registerConnectCommand as l}from"./commands/connect.js";import{registerChallengeCommand as i}from"./commands/challenge.js";import{registerDoctorCommand as a}from"./commands/doctor.js";import{registerNoteCommand as c}from"./commands/note.js";import{registerLogCommand as m}from"./commands/log.js";import{registerLangCommand as g}from"./commands/lang.js";import{registerSetupCommand as d}from"./commands/setup.js";import{registerEnvCommand as p}from"./commands/env.js";import{registerAienvCommand as h}from"./commands/aienv.js";import{registerIpynbCommand as y}from"./commands/ipynb.js";import{registerAi4ctfCommand as f}from"./commands/ai4ctf.js";import{registerExamCommand as u}from"./commands/exam.js";import{registerCtf4aiDemoCommand as w}from"./commands/ctf4ai-demo.js";import{registerThemeCommand as b}from"./commands/theme.js";import{registerLearnCommand as T}from"./commands/learn.js";import{registerCtf4VlaCommand as v}from"./commands/ctf4vla.js";import{registerDemo2Command as j}from"./commands/demo2.js";import{registerDemo4Command as $}from"./commands/demo4.js";import{registerDemo5Command as A}from"./commands/demo5.js";import{registerSimCommand as I}from"./commands/sim.js";import{registerArenaCommand as E}from"./commands/arena.js";import{registerKaggleCommand as C}from"./commands/kaggle.js";import{registerSprintCommand as _}from"./commands/sprint.js";import{registerTeleloadCommand as S}from"./commands/teleload.js";import{registerBoardCommand as x}from"./commands/board.js";import{getConfig as k,saveConfig as L}from"./lib/config.js";import{startRepl as O}from"./repl.js";import{RELAUNCH_CODE as R}from"./lib/menu-nav.js";import{setTerminalTheme as F}from"./lib/theme.js";import{cleanupTerminal as N}from"./lib/terminal-cleanup.js";import{checkForUpdates as U}from"./lib/update-check.js";import{detectIcoaInstalls as P,isWindowsBuildInWslShell as M}from"./lib/platform.js";import{ICOA_BIG as D}from"./lib/banner.js";import{readFileSync as G}from"node:fs";import{fileURLToPath as W}from"node:url";import{dirname as H,join as Y}from"node:path";const J=H(W(import.meta.url)),V=JSON.parse(G(Y(J,"..","package.json"),"utf-8")).version,X=chalk.cyan(" ─────────────────────────────────────────────────────"),q=`\n${X}\n\n${D.map(o=>` ${chalk.bold.white(o)}`).join("\n")}\n\n ${chalk.yellow("International Cyber Olympiad in AI 2026")}\n ${chalk.bold.magenta("The World's First AI-Native CLI Operating System")}\n ${chalk.bold.magenta("for Cybersecurity & AI Security Competition")}\n ${chalk.bold.magenta("and Olympiad for K-12")}\n\n ${chalk.green.bold("AI4CTF")} ${chalk.gray("[Day 1]")} ${chalk.white("AI as your teammate")}\n ${chalk.red.bold("CTF4AI")} ${chalk.gray("[Day 2]")} ${chalk.white("Challenge & evaluate AI systems")}\n ${chalk.cyan.bold("CTF4EAI")} ${chalk.gray("[Pioneer]")} ${chalk.white("Embodied AI security")}\n ${chalk.bold.yellow("AI is your teammate. AI is your target. AI is embodied.")}\n\n ${chalk.white("Sydney, Australia")} ${chalk.gray("Jun 27 - Jul 2, 2026")}\n ${chalk.cyan.underline("https://icoa2026.au")}\n\n ${chalk.gray(`CLI-Native Competition Terminal v${V}`)}\n\n${X}\n`;process.on("uncaughtException",o=>{"__REPL_NO_EXIT__"!==o.message&&(console.error(chalk.red("Error:"),o.message),process.exit(1))}),process.on("unhandledRejection",o=>{const e=o instanceof Error?o.message:String(o);"__REPL_NO_EXIT__"!==e&&(console.error(chalk.red("Error:"),e),process.exit(1))});{const o=process.argv.slice(2).some(o=>["-V","--version","-h","--help"].includes(o));if(!0===process.stdin.isTTY&&"1"!==process.env.ICOA_SUPERVISED&&!o){const{spawnSync:o}=await import("node:child_process");process.on("SIGINT",()=>{}),process.on("SIGTERM",()=>{});let e=0,n=!1;do{const s=n?process.argv.slice(1,2):process.argv.slice(1),r=o(process.execPath,s,{stdio:"inherit",env:{...process.env,ICOA_SUPERVISED:"1",...n?{ICOA_RELAUNCH:"1"}:{}}});if(r.signal){e=0;break}e=r.status,n=!0}while(e===R);N(),process.exit(e??0)}}const z=new o;if(z.name("icoa").version(V).description("ICOA CLI — CLI-Native CTF Competition Terminal").option("--resume","Resume previous session").option("--continue","Continue where you left off — jump straight to your last learn card / exam").action(async o=>{const e=k();F("high-contrast"===e.themeVariant?"high-contrast":"dark"),U(),function(){const o=P();if(o.length<=1)return;const e=o[0];if([...o.map(o=>o.version||"0.0.0")].sort((o,e)=>function(o,e){const n=o.split(".").map(o=>parseInt(o,10)||0),s=e.split(".").map(o=>parseInt(o,10)||0);for(let o=0;o<3;o++)if((n[o]||0)!==(s[o]||0))return(n[o]||0)-(s[o]||0);return 0}(e,o))[0]!==e.version){console.log(),console.log(chalk.yellow.bold(" ⚠ Multiple icoa installations detected on PATH:"));for(let e=0;e<o.length;e++){const n=o[e],s=n.version?`v${n.version}`:"(version unreadable)",r=0===e?chalk.yellow("→"):" ",t=0===e?chalk.gray(" ← currently running (older — shadowing newer install)"):chalk.gray(" ← shadowed");console.log(` ${r} ${chalk.cyan(n.path.padEnd(28))} ${chalk.white(s)}${t}`)}console.log(),console.log(chalk.yellow(" The first install on PATH wins. To use the newer one, remove the older:")),console.log(),e.pkgDir?console.log(` ${chalk.bold.cyan(`sudo rm -rf ${e.pkgDir} ${e.path}`)}`):console.log(` ${chalk.bold.cyan(`sudo rm -rf ${e.path} # also delete its node_modules dir`)}`),console.log(),console.log(chalk.gray(" Then re-run icoa to confirm version banner shows the newer release.")),console.log()}}();const n=process.env.LANG||process.env.LC_ALL||process.env.LC_CTYPE||"";if(!/UTF-?8/i.test(n))if("win32"===process.platform){let o="";try{const{execFileSync:e}=await import("node:child_process");o=e("chcp.com",[],{encoding:"utf-8",timeout:1500,stdio:["ignore","pipe","ignore"]}).trim()}catch{}o.includes("65001")||(console.log(chalk.yellow(`⚠ Windows terminal is not using UTF-8 (current: ${o||"unknown"}).`)),console.log(chalk.gray(' Non-English text (Ukrainian, Chinese, Japanese, etc.) may show as "?" or garbled glyphs.')),console.log(chalk.gray(" Fix (run before ")+chalk.cyan("icoa")+chalk.gray("): ")+chalk.cyan("chcp 65001")),console.log(chalk.gray(" Or stay in English inside the CLI: ")+chalk.cyan("lang en")),console.log())}else console.log(chalk.yellow(`⚠ Your terminal locale is not UTF-8 (LANG=${n||"(unset)"}).`)),console.log(chalk.gray(' Non-English text and box characters may display as "?" or garbled glyphs.')),console.log(chalk.gray(" Fix: ")+chalk.cyan("export LANG=en_US.UTF-8")+chalk.gray(" (or your locale, e.g. ")+chalk.cyan("zh_CN.UTF-8")+chalk.gray(", ")+chalk.cyan("uk_UA.UTF-8")+chalk.gray(")")),console.log();console.log(q);const s=!!o.resume||!!o.continue;if(process.argv.length<=2||s)return o.continue&&(process.env.ICOA_AUTO_RESUME="1"),s||"1"===process.env.ICOA_RELAUNCH||await async function(){const o=process.stdin;if(o.isTTY&&"function"==typeof o.setRawMode)return new Promise(e=>{let n=!1;const s=()=>{if(!n){n=!0,o.removeListener("data",r);try{o.setRawMode(!1)}catch{}o.pause(),e()}},r=()=>s();o.setRawMode(!0),o.resume(),o.once("data",r),console.log(chalk.gray(" (press any key to continue...)")),setTimeout(s,3e3)});await new Promise(o=>setTimeout(o,3e3))}(),void O(z,s)}),e(z),n(z),s(z),r(z),t(z),l(z),i(z),a(z),c(z),m(z),g(z),d(z),p(z),h(z),y(z),f(z),u(z),w(z),b(z),T(z),v(z),j(z),$(z),A(z),I(z),E(z),C(z),S(z),_(z),x(z),z.command("model",{hidden:!0}).argument("[name]","model name to switch to").action(o=>{const e=k().geminiModel||"gemini-2.5-flash-lite";o?(L({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)))}z.hook("preAction",()=>{!function(){if(!M())return;const o="─".repeat(52);console.log(),console.log(chalk.yellow(` ${o}`)),console.log(chalk.yellow.bold(" ⚠ You ARE inside Ubuntu — but this icoa")),console.log(chalk.yellow.bold(" is the WINDOWS build.")),console.log(),console.log(chalk.gray(" WSL appends the Windows PATH, so ")+chalk.cyan("icoa")),console.log(chalk.gray(" found the Windows copy first. Almost")),console.log(chalk.gray(" nothing will work: no vi, no python3,")),console.log(chalk.gray(" env setup cannot install.")),console.log(),console.log(chalk.gray(" Running: ")+chalk.white(process.execPath)),console.log(),console.log(chalk.white(" Fix — inside Ubuntu, check npm is Linux FIRST:")),console.log(` ${chalk.bold.cyan("which npm")}${chalk.gray(" → must not be /mnt/c/...")}`),console.log(` ${chalk.bold.cyan("sudo npm install -g icoa-cli")}`),console.log(` ${chalk.bold.cyan("hash -r")}${chalk.gray(" → bash caches the old path")}`),console.log(chalk.gray(" Then restart icoa and check ")+chalk.bold.cyan("which icoa")),console.log(chalk.yellow(` ${o}`)),console.log()}()}),z.parse();
|
package/dist/lib/kaggle.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export function parseKaggleTaskList(e){const t=e??{},s=(t.data??t).tasks;if(!Array.isArray(s))return[];const n=[];for(const e of s){if(!e||"object"!=typeof e)continue;const t=e;"string"==typeof t.comp_id&&""!==t.comp_id&&n.push({comp_id:t.comp_id,title:"string"==typeof t.title?t.title:t.comp_id,metric:"string"==typeof t.metric?t.metric:"accuracy",description:"string"==typeof t.description&&""!==t.description?t.description:void 0,kaggle_url:"string"==typeof t.kaggle_url?t.kaggle_url:null,licence:"string"==typeof t.licence?t.licence:void 0,attribution:"string"==typeof t.attribution?t.attribution:void 0,data_base:"string"==typeof t.data_base&&""!==t.data_base?t.data_base:null,id_col:"string"==typeof t.id_col?t.id_col:void 0,target_col:"string"==typeof t.target_col?t.target_col:void 0,n_train:"number"==typeof t.n_train?t.n_train:void 0,n_test:"number"==typeof t.n_test?t.n_test:void 0,judge:"string"==typeof t.judge&&""!==t.judge?t.judge:void 0,board_event:"string"==typeof t.board_event&&""!==t.board_event?t.board_event:null,needs_gpu:!0===t.needs_gpu})}return n}export function dataFileUrls(e){const t=e.data_base;if("string"!=typeof t||""===t)return null;const s=t.replace(/\/$/,"");return{train:`${s}/train.csv`,test:`${s}/test.csv`,sample_submission:`${s}/sample_submission.csv`}}export function buildStarterCells(e,t){const s=t.id_col??"id",n=t.target_col??"target";var a;a=t.metric,/rmse|mse|mae|error/i.test(a);const i="icoa-holdout"===t.judge,r=e=>({kind:"markdown",source:e,result:null}),o=e=>({kind:"code",source:e.join("\n"),result:null}),l=[`# ${t.title}`,"",...t.description?[t.description,""]:[],`Kaggle-style practice — metric: **${t.metric}**.`,"","- `train.csv` — labelled training data",`- \`test.csv\` — rows to predict (no \`${n}\` column)`,"- `sample_submission.csv` — the exact format Kaggle expects","","Run all cells top to bottom: a baseline model trains on your CPU and","`submission.csv` appears next to the data. Then improve the model cell",...i?["and re-run — `icoa kaggle submit` scores it and ranks you on the board."]:["and re-run — your score is whatever Kaggle says it is."],"","**AI help:** split your terminal (`Ctrl-b %`), run `icoa` in the right pane","and type `ai4ioai` for a live Gemma 3n E4B. Ask it for feature ideas or bug fixes —","then verify every suggestion with the val score. A tip that lowers it, drop it.",...t.licence?["",`**Data licence:** ${t.licence}`]:[],...t.attribution?[`**Attribution:** ${t.attribution}`]:[]].join("\n"),c=o(["# setup — load the data (leave as is)","import os","import numpy as np","import pandas as pd","from pandas.api.types import is_numeric_dtype","from sklearn.feature_extraction.text import TfidfVectorizer","from sklearn.model_selection import train_test_split","from sklearn.metrics import accuracy_score, mean_squared_error","","# same code everywhere: in a GPU session these env vars point at the","# box's own dataset copy + workspace — locally they are unset.",`DIR = os.environ.get("ICOA_KAGGLE_DATA") or r"${e}"`,'OUT = os.environ.get("ICOA_KAGGLE_OUT") or DIR',...t.data_base?[`DATA_BASE = "${t.data_base.replace(/\/$/,"")}"`,'if not os.path.exists(DIR + "/train.csv"):'," import urllib.request"," os.makedirs(DIR, exist_ok=True)",' for f in ("train.csv", "test.csv", "sample_submission.csv"):',' urllib.request.urlretrieve(DATA_BASE + "/" + f, DIR + "/" + f)']:[],'train = pd.read_csv(DIR + "/train.csv")','test = pd.read_csv(DIR + "/test.csv")','sub_fmt = pd.read_csv(DIR + "/sample_submission.csv")',"","# 🔴 The submission column names are NOT always the training column names.","# On tasks imported from other platforms the two genuinely differ: train.csv",'# labels the answer "class" or "result" while sample_submission.csv calls it','# "answer". Hard-coding the submission name here used to raise KeyError on the',"# very first cell. So trust the DATA: whatever column train has and test lacks","# is the thing to predict.",`SUB_ID, SUB_TARGET = "${s}", "${n}" # names the submission file wants`,"only_train = [c for c in train.columns if c not in test.columns]","TARGET = only_train[-1] if only_train else SUB_TARGET","shared = [c for c in train.columns if c in test.columns]","# Only treat a column as the row id when the submission actually names it AND",'# both files carry it. Falling back to "first shared column" silently spent a',"# real feature as an id on tasks whose id lives only in test.csv.","ID = SUB_ID if SUB_ID in shared else None",'assert TARGET in train.columns, f"cannot find the label column in {list(train.columns)}"',"","# Regression or classification? Decided from the labels, not from metadata —","# several tasks ship continuous labels, and handing those to a classifier",'# raises "Unknown label type: continuous".',"REG = is_numeric_dtype(train[TARGET]) and train[TARGET].nunique() > 20",'print(f"train {train.shape} · test {test.shape} · predicting {TARGET!r} "'," f\"({'regression' if REG else 'classification'})\")"]),d=o(["# FEATURES — turn raw columns into numbers a model can use (improve THIS cell).","# Numbers: fill gaps with the median. Category (<= 20 distinct): one-hot.","# Free text: TF-IDF — on a text task the sentences ARE the signal, and dropping",'# them as "high-cardinality" leaves nothing to train on (that used to crash the','# whole notebook with "No objects to concatenate").',"# only columns present in BOTH files — a train-only column cannot be a feature","# at prediction time, and indexing test with it raises KeyError.","feat = [c for c in shared if c not in (ID, TARGET)]","Xtr_raw, Xte_raw = train[feat].copy(), test[feat].copy()","num = [c for c in feat if is_numeric_dtype(Xtr_raw[c])]","cat = [c for c in feat if c not in num and Xtr_raw[c].nunique() <= 20]","# Everything else is vectorised as text. Requiring a long average length here","# used to throw away high-cardinality SHORT strings — ingredient names, single","# words, category codes — which on several tasks are the entire signal, leaving","# the notebook with zero features.","txt = [c for c in feat if c not in num and c not in cat]","for c in num:"," med = Xtr_raw[c].median()"," Xtr_raw[c] = Xtr_raw[c].fillna(med)"," Xte_raw[c] = Xte_raw[c].fillna(med)","blocks_tr, blocks_te = [], []","if num or cat:"," d_tr = pd.get_dummies(Xtr_raw[num + cat], columns=cat, dummy_na=True)"," d_te = pd.get_dummies(Xte_raw[num + cat], columns=cat, dummy_na=True)",' d_tr, d_te = d_tr.align(d_te, join="left", axis=1, fill_value=0)'," blocks_tr.append(d_tr.to_numpy(dtype=float))"," blocks_te.append(d_te.to_numpy(dtype=float))","for c in txt:"," # fillna BEFORE astype(str): a real NaN reaching the vectoriser raises",' # "np.nan is an invalid document", and astype alone does not catch it.',' tr_txt = Xtr_raw[c].fillna("").astype(str)',' te_txt = Xte_raw[c].fillna("").astype(str)'," # min_df=1: on a short-token column (one ingredient per row) min_df=2 can"," # filter the vocabulary down to nothing."," long_col = tr_txt.str.len().mean() >= 12"," # Try the good settings, then a permissive fallback, then give up on THIS"," # column only. A column whose vocabulary prunes to nothing used to abort the",' # whole run with "After pruning, no terms remain".',' for kw in ({"min_df": 2 if long_col else 1,',' "analyzer": "word" if long_col else "char_wb"},',' {"min_df": 1, "analyzer": "char_wb"}):'," try:"," vec = TfidfVectorizer(max_features=3000, ngram_range=(1, 2), **kw)"," b_tr = vec.fit_transform(tr_txt).toarray()"," blocks_tr.append(b_tr)"," blocks_te.append(vec.transform(te_txt).toarray())"," break"," except ValueError as e:"," last = e"," else:",' print(f" skipped text column {c!r}: {last}")',"if not blocks_tr:"," raise SystemExit(",' f"No usable feature columns. The shared columns are {feat} — none of them "',' f"is numeric, categorical or text.\\n"',' f"Two kinds of task land here, and both are real work rather than a bug:\\n"',' f" 1. audio/image — train.csv only lists sample ids and labels, and the "',' f"signal is in the media files shipped with the task. Load them "',' f"(librosa / PIL), turn each file into a feature row.\\n"',' f" 2. train.csv and test.csv describe different things (a retrieval or "',' f"matching task). Read both files, work out what links a test row to a "',' f"train row, and build that mapping yourself.\\n"',' f"Either way: replace this cell. train={list(train.columns)} "',' f"test={list(test.columns)}"'," )","X = np.hstack(blocks_tr)","X_test = np.hstack(blocks_te)","y = train[TARGET]","X_tr, X_val, y_tr, y_val = train_test_split(X, y, test_size=0.2, random_state=0)",'print(f"{X.shape[1]} model-ready features "',' f"({len(num)} numeric, {len(cat)} one-hot, {len(txt)} TF-IDF text)")']),u=o(["# MODEL — a working baseline. Improve THIS cell to climb the board.","from sklearn.linear_model import LogisticRegression, Ridge","# REG was decided from the labels back in setup.","model = Ridge() if REG else LogisticRegression(max_iter=2000)"]),m=o(["# validate — quick local score on a held-out fifth of train","model.fit(X_tr, y_tr)","p_val = model.predict(X_val)","if REG:",' print("val RMSE:", round(mean_squared_error(y_val, p_val) ** 0.5, 4))',"else:"," acc = accuracy_score(y_val, p_val)",' print("val accuracy:", round(acc, 4))'," if acc < 0.3:"," # A near-zero baseline is the expected result on several of these tasks,"," # not a broken notebook — say so, or the student reads it as a bug.",' print(" A score this low usually means the linear baseline cannot "',' "represent the pattern at all (combination rules, sequences, "',' "spelling). That IS the task: build features that expose it, "',' "or switch to a model that can. The chain itself works — "',' "submission.csv is written either way.")']),p=o(["# submission — retrain on ALL data, write submission.csv (Kaggle format)","model.fit(X, y)","pred = model.predict(X_test)",'out = OUT + "/submission.csv"',"# Copy the layout of sample_submission.csv and swap in the predictions, rather","# than rebuilding the file from column names. Some tasks want more than two","# columns (e.g. subtaskID,datapointID,answer) and a hand-built 2-column frame","# is rejected by the grader even when every prediction is right.","if len(sub_fmt) == len(pred):"," sub = sub_fmt.copy()"," sub[sub.columns[-1]] = pred","else:"," keys = {}"," if ID is not None and ID in test.columns:"," keys[SUB_ID] = test[ID]"," keys[SUB_TARGET] = pred"," sub = pd.DataFrame(keys)",' print(f"NOTE: sample_submission has {len(sub_fmt)} rows but test has "',' f"{len(pred)} — built the file from column names instead; "',' f"check it against the task page before submitting.")',"sub.to_csv(out, index=False)",'print("wrote", out, "·", list(sub.columns))',i?`print("score it: icoa kaggle submit ${t.comp_id}")`:'print("format check: icoa kaggle check")']),h=i?["## Submit to ICOA (scored on the server)","",`1. In the ICOA CLI run \`icoa kaggle submit ${t.comp_id}\``,"2. The server scores `submission.csv` against the secret test labels"," and your rank lands on the live board (`icoa board`).","3. Improve the MODEL cell, re-run, submit again — best score counts."]:t.kaggle_url?["## Submit on Kaggle (manual, your own account)","",`1. Open ${t.kaggle_url}`,"2. **Submit Predictions** → upload `submission.csv`","3. Read your leaderboard score, come back, improve the MODEL cell, repeat."]:["## Submit on Kaggle (manual, your own account)","","_This is a placeholder practice dataset — it has no live Kaggle page yet._","When the real competition dataset lands, this cell will link straight to","its Kaggle submission page. The loop is identical: upload `submission.csv`,","read the score, improve the MODEL cell, repeat."];return[r(l),c,d,u,m,p,r(h.join("\n"))]}export function parseSubmitResponse(e){const t=e&&"object"==typeof e?e:{},s=t.data??t,n=s&&"object"==typeof s?s:{};return"number"==typeof n.score&&"string"==typeof n.metric?{ok:!0,score:n.score,metric:n.metric,rank:"number"==typeof n.rank_at_time?n.rank_at_time:null,fieldSize:"number"==typeof n.field_size?n.field_size:null,deduped:!0===n.deduped,boardEvent:"string"==typeof n.board_event?n.board_event:null}:"string"==typeof n.reason&&""!==n.reason?{ok:!1,reason:n.reason,error:"string"==typeof n.error?n.error:void 0,problems:Array.isArray(n.problems)?n.problems.filter(e=>"string"==typeof e):void 0}:{ok:!1,reason:"network"}}export function validateSubmissionText(e,t){const s=[],n=e.trim().split(/\r?\n/),a=t.trim().split(/\r?\n/),i=n[0]??"",r=a[0]??"";i.trim()!==r.trim()&&s.push(`header mismatch: expected "${r}", got "${i}"`);const o=n.slice(1).filter(e=>""!==e.trim()),l=a.slice(1).filter(e=>""!==e.trim());o.length!==l.length&&s.push(`row count mismatch: expected ${l.length}, got ${o.length}`);const c=e=>new Set(e.map(e=>(e.split(",")[0]??"").trim())),d=c(o),u=c(l),m=[...u].filter(e=>!d.has(e)),p=[...d].filter(e=>!u.has(e));if(m.length>0||p.length>0){const e=[];m.length>0&&e.push(`${m.length} missing (e.g. ${m[0]})`),p.length>0&&e.push(`${p.length} unknown (e.g. ${p[0]})`),s.push(`id mismatch vs sample_submission: ${e.join(", ")}`)}for(let e=0;e<o.length;e++)if(o[e].split(",").some(e=>""===e.trim())){s.push(`empty cell in data row ${e+1}`);break}return{ok:0===s.length,problems:s}}
|
|
1
|
+
export function parseKaggleTaskList(e){const t=e??{},a=(t.data??t).tasks;if(!Array.isArray(a))return[];const s=[];for(const e of a){if(!e||"object"!=typeof e)continue;const t=e;"string"==typeof t.comp_id&&""!==t.comp_id&&s.push({comp_id:t.comp_id,title:"string"==typeof t.title?t.title:t.comp_id,metric:"string"==typeof t.metric?t.metric:"accuracy",description:"string"==typeof t.description&&""!==t.description?t.description:void 0,kaggle_url:"string"==typeof t.kaggle_url?t.kaggle_url:null,licence:"string"==typeof t.licence?t.licence:void 0,attribution:"string"==typeof t.attribution?t.attribution:void 0,data_base:"string"==typeof t.data_base&&""!==t.data_base?t.data_base:null,id_col:"string"==typeof t.id_col?t.id_col:void 0,target_col:"string"==typeof t.target_col?t.target_col:void 0,n_train:"number"==typeof t.n_train?t.n_train:void 0,n_test:"number"==typeof t.n_test?t.n_test:void 0,judge:"string"==typeof t.judge&&""!==t.judge?t.judge:void 0,board_event:"string"==typeof t.board_event&&""!==t.board_event?t.board_event:null,needs_gpu:!0===t.needs_gpu})}return s}export function dataFileUrls(e){const t=e.data_base;if("string"!=typeof t||""===t)return null;const a=t.replace(/\/$/,"");return{train:`${a}/train.csv`,test:`${a}/test.csv`,sample_submission:`${a}/sample_submission.csv`}}export function buildStarterCells(e,t){const a=t.id_col??"id",s=t.target_col??"target";var r;r=t.metric,/rmse|mse|mae|error/i.test(r);const n="icoa-holdout"===t.judge,i=e=>({kind:"markdown",source:e,result:null}),o=e=>({kind:"code",source:e.join("\n"),result:null}),l=[`# ${t.title}`,"",...t.description?[t.description,""]:[],`Kaggle-style practice — metric: **${t.metric}**.`,"","- `train.csv` — labelled training data",`- \`test.csv\` — rows to predict (no \`${s}\` column)`,"- `sample_submission.csv` — the exact format Kaggle expects","","Run all cells top to bottom: a baseline model trains on your CPU and","`submission.csv` appears next to the data. Then improve the model cell",...n?["and re-run — `icoa kaggle submit` scores it and ranks you on the board."]:["and re-run — your score is whatever Kaggle says it is."],"","**AI help:** split your terminal (`Ctrl-b %`), run `icoa` in the right pane","and type `ai4ioai` for a live Gemma 3n E4B. Ask it for feature ideas or bug fixes —","then verify every suggestion with the val score. A tip that lowers it, drop it.",...t.licence?["",`**Data licence:** ${t.licence}`]:[],...t.attribution?[`**Attribution:** ${t.attribution}`]:[]].join("\n"),c=o(["# setup — load the data (leave as is)","import os","import numpy as np","import pandas as pd","from pandas.api.types import is_numeric_dtype","from sklearn.feature_extraction.text import TfidfVectorizer","from sklearn.model_selection import train_test_split","from sklearn.metrics import accuracy_score, mean_squared_error","","# same code everywhere: in a GPU session these env vars point at the","# box's own dataset copy + workspace — locally they are unset.",`DIR = os.environ.get("ICOA_KAGGLE_DATA") or r"${e}"`,'OUT = os.environ.get("ICOA_KAGGLE_OUT") or DIR',...t.data_base?[`DATA_BASE = "${t.data_base.replace(/\/$/,"")}"`,'if not os.path.exists(DIR + "/train.csv"):'," import urllib.request"," os.makedirs(DIR, exist_ok=True)",' for f in ("train.csv", "test.csv", "sample_submission.csv"):',' urllib.request.urlretrieve(DATA_BASE + "/" + f, DIR + "/" + f)']:[],'train = pd.read_csv(DIR + "/train.csv")','test = pd.read_csv(DIR + "/test.csv")','sub_fmt = pd.read_csv(DIR + "/sample_submission.csv")',"","# 🔴 The submission column names are NOT always the training column names.","# On tasks imported from other platforms the two genuinely differ: train.csv",'# labels the answer "class" or "result" while sample_submission.csv calls it','# "answer". Hard-coding the submission name here used to raise KeyError on the',"# very first cell. So trust the DATA: whatever column train has and test lacks","# is the thing to predict.",`SUB_ID, SUB_TARGET = "${a}", "${s}" # names the submission file wants`,"only_train = [c for c in train.columns if c not in test.columns]","TARGET = only_train[-1] if only_train else SUB_TARGET","shared = [c for c in train.columns if c in test.columns]","# Only treat a column as the row id when the submission actually names it AND",'# both files carry it. Falling back to "first shared column" silently spent a',"# real feature as an id on tasks whose id lives only in test.csv.","ID = SUB_ID if SUB_ID in shared else None",'assert TARGET in train.columns, f"cannot find the label column in {list(train.columns)}"',"","# Regression or classification? Decided from the labels, not from metadata —","# several tasks ship continuous labels, and handing those to a classifier",'# raises "Unknown label type: continuous".',"REG = is_numeric_dtype(train[TARGET]) and train[TARGET].nunique() > 20",'print(f"train {train.shape} · test {test.shape} · predicting {TARGET!r} "'," f\"({'regression' if REG else 'classification'})\")"]),u=o(["# FEATURES — turn raw columns into numbers a model can use (improve THIS cell).","# Numbers: fill gaps with the median. Category (<= 20 distinct): one-hot.","# Free text: TF-IDF — on a text task the sentences ARE the signal, and dropping",'# them as "high-cardinality" leaves nothing to train on (that used to crash the','# whole notebook with "No objects to concatenate").',"# only columns present in BOTH files — a train-only column cannot be a feature","# at prediction time, and indexing test with it raises KeyError.","feat = [c for c in shared if c not in (ID, TARGET)]","Xtr_raw, Xte_raw = train[feat].copy(), test[feat].copy()","num = [c for c in feat if is_numeric_dtype(Xtr_raw[c])]","cat = [c for c in feat if c not in num and Xtr_raw[c].nunique() <= 20]","# Everything else is vectorised as text. Requiring a long average length here","# used to throw away high-cardinality SHORT strings — ingredient names, single","# words, category codes — which on several tasks are the entire signal, leaving","# the notebook with zero features.","txt = [c for c in feat if c not in num and c not in cat]","for c in num:"," med = Xtr_raw[c].median()"," Xtr_raw[c] = Xtr_raw[c].fillna(med)"," Xte_raw[c] = Xte_raw[c].fillna(med)","blocks_tr, blocks_te = [], []","if num or cat:"," d_tr = pd.get_dummies(Xtr_raw[num + cat], columns=cat, dummy_na=True)"," d_te = pd.get_dummies(Xte_raw[num + cat], columns=cat, dummy_na=True)",' d_tr, d_te = d_tr.align(d_te, join="left", axis=1, fill_value=0)'," blocks_tr.append(d_tr.to_numpy(dtype=float))"," blocks_te.append(d_te.to_numpy(dtype=float))","for c in txt:"," # fillna BEFORE astype(str): a real NaN reaching the vectoriser raises",' # "np.nan is an invalid document", and astype alone does not catch it.',' tr_txt = Xtr_raw[c].fillna("").astype(str)',' te_txt = Xte_raw[c].fillna("").astype(str)'," # min_df=1: on a short-token column (one ingredient per row) min_df=2 can"," # filter the vocabulary down to nothing."," long_col = tr_txt.str.len().mean() >= 12"," # Try the good settings, then a permissive fallback, then give up on THIS"," # column only. A column whose vocabulary prunes to nothing used to abort the",' # whole run with "After pruning, no terms remain".',' for kw in ({"min_df": 2 if long_col else 1,',' "analyzer": "word" if long_col else "char_wb"},',' {"min_df": 1, "analyzer": "char_wb"}):'," try:"," vec = TfidfVectorizer(max_features=3000, ngram_range=(1, 2), **kw)"," b_tr = vec.fit_transform(tr_txt).toarray()"," blocks_tr.append(b_tr)"," blocks_te.append(vec.transform(te_txt).toarray())"," break"," except ValueError as e:"," last = e"," else:",' print(f" skipped text column {c!r}: {last}")',"if not blocks_tr:"," raise SystemExit(",' f"No usable feature columns. The shared columns are {feat} — none of them "',' f"is numeric, categorical or text.\\n"',' f"Two kinds of task land here, and both are real work rather than a bug:\\n"',' f" 1. audio/image — train.csv only lists sample ids and labels, and the "',' f"signal is in the media files shipped with the task. Load them "',' f"(librosa / PIL), turn each file into a feature row.\\n"',' f" 2. train.csv and test.csv describe different things (a retrieval or "',' f"matching task). Read both files, work out what links a test row to a "',' f"train row, and build that mapping yourself.\\n"',' f"Either way: replace this cell. train={list(train.columns)} "',' f"test={list(test.columns)}"'," )","X = np.hstack(blocks_tr)","X_test = np.hstack(blocks_te)","y = train[TARGET]","X_tr, X_val, y_tr, y_val = train_test_split(X, y, test_size=0.2, random_state=0)",'print(f"{X.shape[1]} model-ready features "',' f"({len(num)} numeric, {len(cat)} one-hot, {len(txt)} TF-IDF text)")']),d=o(["# MODEL — a working baseline. Improve THIS cell to climb the board.","from sklearn.linear_model import LogisticRegression, Ridge","# REG was decided from the labels back in setup.","model = Ridge() if REG else LogisticRegression(max_iter=2000)"]),m=o(["# validate — quick local score on a held-out fifth of train","model.fit(X_tr, y_tr)","p_val = model.predict(X_val)","if REG:",' print("val RMSE:", round(mean_squared_error(y_val, p_val) ** 0.5, 4))',"else:"," acc = accuracy_score(y_val, p_val)",' print("val accuracy:", round(acc, 4))'," if acc < 0.3:"," # A near-zero baseline is the expected result on several of these tasks,"," # not a broken notebook — say so, or the student reads it as a bug.",' print(" A score this low usually means the linear baseline cannot "',' "represent the pattern at all (combination rules, sequences, "',' "spelling). That IS the task: build features that expose it, "',' "or switch to a model that can. The chain itself works — "',' "submission.csv is written either way.")']),p=o(["# submission — retrain on ALL data, write submission.csv (Kaggle format)","model.fit(X, y)","pred = model.predict(X_test)",'out = OUT + "/submission.csv"',"# Copy the layout of sample_submission.csv and swap in the predictions, rather","# than rebuilding the file from column names. Some tasks want more than two","# columns (e.g. subtaskID,datapointID,answer) and a hand-built 2-column frame","# is rejected by the grader even when every prediction is right.","if len(sub_fmt) == len(pred):"," sub = sub_fmt.copy()"," sub[sub.columns[-1]] = pred","else:"," keys = {}"," if ID is not None and ID in test.columns:"," keys[SUB_ID] = test[ID]"," keys[SUB_TARGET] = pred"," sub = pd.DataFrame(keys)",' print(f"NOTE: sample_submission has {len(sub_fmt)} rows but test has "',' f"{len(pred)} — built the file from column names instead; "',' f"check it against the task page before submitting.")',"sub.to_csv(out, index=False)",'print("wrote", out, "·", list(sub.columns))',n?`print("score it: icoa kaggle submit ${t.comp_id}")`:'print("format check: icoa kaggle check")']),h=n?["## Submit to ICOA (scored on the server)","",`1. In the ICOA CLI run \`icoa kaggle submit ${t.comp_id}\``,"2. The server scores `submission.csv` against the secret test labels"," and your rank lands on the live board (`icoa board`).","3. Improve the MODEL cell, re-run, submit again — best score counts."]:"nitro"===t.judge?["## Where this one gets scored","","This task comes from **judge.nitro-ai.org** and the answer key stays on","their server, so ICOA cannot score it for you. That does not make it a","practice stub — it is a real task, just judged elsewhere.","",`1. \`icoa kaggle check ${t.comp_id}\` — checks the FORMAT of`," `submission.csv` (headers, row count, ids). Format errors are the most"," common way a correct answer still scores zero.","2. Watch the **val score** printed above — that is your real feedback loop"," during the sprint, and it needs no account anywhere.","3. Want the official number? Register at judge.nitro-ai.org and submit"," there. Otherwise compare against the official solution, or ask"," `ai4ioai` to review your approach."]:t.kaggle_url?["## Submit on Kaggle (manual, your own account)","",`1. Open ${t.kaggle_url}`,"2. **Submit Predictions** → upload `submission.csv`","3. Read your leaderboard score, come back, improve the MODEL cell, repeat."]:["## Submit on Kaggle (manual, your own account)","","_This dataset has no live Kaggle page linked yet._","The loop is identical: upload `submission.csv`, read the score, improve","the MODEL cell, repeat. Meanwhile the **val score** printed above is a","real signal you can work against with no account at all."];return[i(l),c,u,d,m,p,i(h.join("\n"))]}export function parseSubmitResponse(e){const t=e&&"object"==typeof e?e:{},a=t.data??t,s=a&&"object"==typeof a?a:{};return"number"==typeof s.score&&"string"==typeof s.metric?{ok:!0,score:s.score,metric:s.metric,rank:"number"==typeof s.rank_at_time?s.rank_at_time:null,fieldSize:"number"==typeof s.field_size?s.field_size:null,deduped:!0===s.deduped,boardEvent:"string"==typeof s.board_event?s.board_event:null}:"string"==typeof s.reason&&""!==s.reason?{ok:!1,reason:s.reason,error:"string"==typeof s.error?s.error:void 0,problems:Array.isArray(s.problems)?s.problems.filter(e=>"string"==typeof e):void 0}:{ok:!1,reason:"network"}}export function validateSubmissionText(e,t){const a=[],s=e.trim().split(/\r?\n/),r=t.trim().split(/\r?\n/),n=s[0]??"",i=r[0]??"";n.trim()!==i.trim()&&a.push(`header mismatch: expected "${i}", got "${n}"`);const o=s.slice(1).filter(e=>""!==e.trim()),l=r.slice(1).filter(e=>""!==e.trim());o.length!==l.length&&a.push(`row count mismatch: expected ${l.length}, got ${o.length}`);const c=e=>new Set(e.map(e=>(e.split(",")[0]??"").trim())),u=c(o),d=c(l),m=[...d].filter(e=>!u.has(e)),p=[...u].filter(e=>!d.has(e));if(m.length>0||p.length>0){const e=[];m.length>0&&e.push(`${m.length} missing (e.g. ${m[0]})`),p.length>0&&e.push(`${p.length} unknown (e.g. ${p[0]})`),a.push(`id mismatch vs sample_submission: ${e.join(", ")}`)}for(let e=0;e<o.length;e++)if(o[e].split(",").some(e=>""===e.trim())){a.push(`empty cell in data row ${e+1}`);break}return{ok:0===a.length,problems:a}}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "icoa-cli",
|
|
3
|
-
"version": "2.19.
|
|
3
|
+
"version": "2.19.433",
|
|
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": {
|