icoa-cli 2.19.629 → 2.19.630
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/lib/algo-replay.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import chalk from"chalk";import{lazyJson as t}from"./lazy-assets.js";export
|
|
1
|
+
import chalk from"chalk";import{lazyJson as t}from"./lazy-assets.js";export function replayKey(t){if("number"==typeof t)return Number.isInteger(t)&&t>0?`aio${t}`:null;const e=t.trim();if(/^PY\d{4}$/i.test(e))return e.toUpperCase();const s=/^aio(\d+)$/i.exec(e);return s&&Number(s[1])>0?`aio${Number(s[1])}`:null}export function replayAssetName(t){const e=replayKey(t);return e?`replays/${e}.json`:null}export async function loadReplay(e){const s=replayAssetName(e);if(!s)return null;const n=await t(s,8e3);return n&&1===n.v&&Array.isArray(n.frames)&&n.frames.length>0?n:null}let e=null,s=null;export function warmReplayIndex(){return s||(s=t("replays/index.json",5e3,{force:!0}).then(t=>{t&&Array.isArray(t.ids)&&(e=new Set(t.ids.filter(t=>"string"==typeof t)))}).catch(()=>{})),s}export function hasReplay(t){const s=replayKey(t);return Boolean(s&&e?.has(s))}export function setReplayIndexForTest(t){e=t?new Set(t):null,s=Promise.resolve()}export const REPLAY_MIN_COLS=120;const n=new RegExp(`${String.fromCharCode(27)}\\[[0-9;]*m`,"g"),r=(t,e)=>t+" ".repeat(Math.max(0,e-(t=>[...t.replace(n,"")].length)(t))),i=(t,e)=>{const s=[];let n="";for(const r of t.split(/\s+/).filter(Boolean))n&&n.length+1+r.length>e?(s.push(n),n=r):n=n?`${n} ${r}`:r;return n&&s.push(n),s};export class ReplayPlayer{doc;opts;i=0;lang="python";steps;extra=null;constructor(t,e){this.doc=t,this.opts=e,this.steps=[...t.frames],t.summary?.idea?.length&&this.steps.push({left:[],line:null,vars:{},verdict:"ok",summary:!0,key:"Last step — the whole idea on one screen, key lines marked ◆. Ask about anything: /ai what does line 5 do"})}static tooNarrow(){return(process.stdout.columns??120)<120}start(t){"cpp"===t&&this.doc.code.cpp&&(this.lang="cpp"),this.render()}code(){return"cpp"===this.lang&&this.doc.code.cpp?this.doc.code.cpp:this.doc.code.python}highlight(t){return null==t.line?new Set:"cpp"===this.lang?new Set((this.doc.map[String(t.line+1)]??[]).map(t=>t-1)):new Set([t.line])}keyLines(){return("cpp"===this.lang?this.doc.summary?.cpp:this.doc.summary?.python)??[]}drawSummary(){const t=[chalk.bold.green("SUMMARY")+chalk.gray(" the idea")];for(const e of this.doc.summary.idea){const s=i(e,59);t.push(chalk.green("• ")+chalk.white(s[0]??""),...s.slice(1).map(t=>` ${chalk.white(t)}`),"")}t.push(chalk.bold.green("THE CODE")+chalk.gray(" what makes it work in "+("cpp"===this.lang?"C++":"Python")));for(const[e,s]of this.keyLines()){const n=i(s,52);t.push(`${chalk.green("◆ ")}${chalk.bold.cyan(`line ${String(e).padEnd(2)}`)} ${chalk.white(n[0]??"")}`,...n.slice(1).map(t=>` ${chalk.white(t)}`))}return t}rightPanel(t,e,s){const n=this.code(),r=this.highlight(t),i=t.summary?new Set(this.keyLines().map(([t])=>t-1)):new Set,o=[...r.size?r:i].sort((t,e)=>t-e);let a=0,h=n.length;if(s&&n.length>s){const t=o.length?Math.floor(((o[0]??0)+(o[o.length-1]??0))/2):0;a=Math.max(0,Math.min(t-Math.floor(s/2),n.length-s)),h=a+s}const l="cpp"===this.lang?"C++":"Python",c=[chalk.gray("─ ")+chalk.bold.white(l)+chalk.gray(` ${"─".repeat(54-l.length-3)}`)];a>0&&c.push(chalk.gray(` ⋮ ${a} line${a>1?"s":""} above`));for(let t=a;t<h;t++){const e=`${String(t+1).padStart(2)} `,s=n[t]??"";r.has(t)?c.push(chalk.bold.yellow(`▸${e}${s}`)):i.has(t)?c.push(chalk.green("◆")+chalk.bold.cyan(e)+chalk.white(s)):c.push(chalk.gray(` ${e}${s}`))}h<n.length&&c.push(chalk.gray(` ⋮ ${n.length-h} more line${n.length-h>1?"s":""}`));const p=t.vars??{},d=Object.keys(p);if(d.length){c.push(chalk.gray(`─ variables ${"─".repeat(42)}`));for(const t of d){let s=String(p[t]);s.length>54-t.length-6&&(s=`${s.slice(0,54-t.length-9)}...`);const n=null!==e&&(!(t in(e.vars??{}))||e.vars[t]!==p[t]);c.push(` ${chalk.cyan(t)} = ${n?chalk.yellow(s):chalk.white(s)}`)}}return c}footer(){const t=this.i===this.steps.length-1,e=[chalk.bold.green("[Enter]")+chalk.gray(t?" finish":" next"),chalk.bold.cyan("[b]")+chalk.gray(" back")];return this.doc.code.cpp&&e.push("cpp"===this.lang?chalk.bold.cyan("[p]")+chalk.gray(" Python code"):chalk.bold.cyan("[c]")+chalk.gray(" C++ code")),e.push(chalk.bold.magenta("[/ai]")+chalk.gray(" 🐼 ask about this step or a line")),e.push(chalk.bold.cyan("[q]")+chalk.gray(" back to the card")),e.join(" ")}render(){const t=this.steps[this.i],e=this.i>0?this.steps[this.i-1]:null,s=t.summary?this.drawSummary():[...t.left],n=i(t.key,116),o=Object.keys(t.vars??{}).length,a=this.extra?this.extra.length+2:0,h=process.stdout.rows??0,l=h?Math.max(8,h-2-1-n.length-1-2-1-a-(o?o+1:0)-3):null,c=this.rightPanel(t,e,l),p=Math.max(s.length,c.length);for(;s.length<p;)s.push("");for(;c.length<p;)c.push("");const d=this.steps.length,u=Math.round(12*(this.i+1)/d),g=chalk.white(`step ${this.i+1}/${d} `)+chalk.green("▰".repeat(u))+chalk.gray("▱".repeat(12-u))+(t.summary?chalk.bold.green(" summary"):""),y=/(.*?card \d+)/.exec(this.doc.source)?.[1]??this.doc.source,m=[`${chalk.bold.white(this.doc.title)}${chalk.gray(` ${y}`)} ${g}`,""];for(let t=0;t<p;t++)m.push(`${r(s[t]??"",62)} ${c[t]??""}`);m.push("");const f="ok"===t.verdict?chalk.green:"no"===t.verdict?chalk.red:chalk.white;for(const[t,e]of n.entries())m.push(chalk.bold.yellow(0===t?"▸ ":" ")+f(e));if(this.extra){m.push("");for(const t of this.extra)m.push(` ${chalk.white(t)}`)}m.push("",this.footer()),process.stdout.isTTY&&process.stdout.write("[2J[H"),console.log(m.join("\n")),this.extra=null}async handle(t){const e=t.trim(),s=e.toLowerCase();if(["q","quit","exit","back to card","card"].includes(s))return"done";if(s.startsWith("/ai")||s.startsWith("ai ")){const t=e.replace(/^\/?ai\s*/i,"");return t?(await this.opts.ask(t,this.context(t)),console.log(chalk.gray(" ▸ ")+chalk.bold.green("Enter")+chalk.gray(" next step · b back · q back to the card")),"input"):(this.extra=["Ask about this step or any line of the code on screen, for example:"," /ai what does line 5 do /ai why is this step red"],this.render(),"input")}if("c"===s||"c++"===s||"cpp"===s)this.doc.code.cpp?"cpp"===this.lang?this.extra=["Already showing C++. Press p for Python."]:this.lang="cpp":this.extra=["No C++ view for this replay yet."];else if("p"===s||"py"===s||"python"===s)"python"===this.lang?this.extra=["Already showing Python."+(this.doc.code.cpp?" Press c for C++.":"")]:this.lang="python";else if("b"===s||"back"===s)0===this.i&&(this.extra=["This is the first step. q goes back to the card."]),this.i=Math.max(0,this.i-1);else if(""===s||"n"===s||"next"===s||"ok"===s){if(this.i>=this.steps.length-1)return"done";this.i++}else this.extra=[`"${e}" is not a replay key. Enter next · b back · ${"cpp"===this.lang?"p Python":"c C++"} · /ai <question> · q back to the card`];return this.render(),"input"}context(t){const e=this.steps[this.i],s=this.code(),n=new Set,r=t=>{Number.isInteger(t)&&t>=1&&t<=s.length&&n.add(t)};for(const e of t.matchAll(/(?:line|l|第)\s*(\d+)/gi))r(Number(e[1]));for(const t of[...this.highlight(e)].sort((t,e)=>t-e))r(t+1);if(e.summary)for(const[t]of this.keyLines())r(t);const i=("cpp"===this.lang?this.doc.notes?.cpp:this.doc.notes?.python)??{};return{id:replayKey(this.doc.id)??String(this.doc.id),title:this.doc.title,source:this.doc.source,lang:this.lang,step:this.i+1,total:this.steps.length,key:e.key,lines:[...n].slice(0,8).sort((t,e)=>t-e).map(t=>({n:t,code:(s[t-1]??"").trim(),note:i[String(t)]??""})),idea:(this.doc.summary?.idea??[]).slice(0,3)}}}
|
package/dist/lib/learn-ai.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{getDeviceFingerprint as e}from"./access.js";import{LEARN_SERVER as t}from"./learn-curricula.js";import{httpFetch as a}from"./http.js";import{getConfig as r}from"./config.js";function n(e,t){const a=(r().language||"en").toLowerCase().startsWith("zh");return 502===e||503===e||504===e?a?"服务这次没能在窗口内答复 — 你的内容已安全存在服务器上。稍等一会再试即可。":"The server did not answer in time — your work is safe on the server. Wait a moment and try again.":t||`HTTP ${e}`}export async function submitPqs(a){const r=t.replace(/\/$/,"")+"/api/icoa/learn/submit";try{const t=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({token:a.token.toUpperCase(),card_number:a.cardNumber,device_fingerprint:e()}),signal:AbortSignal.timeout(18e4)}),o=await t.json().catch(()=>({}));if(!t.ok||!o.success||!o.data)return{ok:!1,message:n(t.status,o.message),code:o.code};const s=o.data;return{ok:!0,score:s.score,tier:s.tier,manipulation:s.manipulation,feedback:s.feedback,improve:s.improve,submissionIndex:s.submission_index,submissionsLeft:s.submissions_left,rank:s.rank,entrants:s.entrants,inTop3:s.in_top3,turns:s.turns,spent:s.spent,cap:s.cap}}catch(e){return{ok:!1,message:e instanceof Error&&"TimeoutError"===e.name?"PQS grading timed out — your conversation is safe on the server; try /submit again in a minute.":`Network error: ${e instanceof Error?e.message:String(e)}`}}}export async function viewPqsTop(a){const r=t.replace(/\/$/,"")+"/api/icoa/learn/view";try{const t=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({token:a.token.toUpperCase(),card_number:a.cardNumber,device_fingerprint:e()}),signal:AbortSignal.timeout(3e4)}),o=await t.json().catch(()=>({}));return t.ok&&o.success&&o.data?{ok:!0,top3:o.data.top3,myRank:o.data.my_rank,entrants:o.data.entrants}:{ok:!1,message:n(t.status,o.message),code:o.code,myRank:o.rank,entrants:o.entrants}}catch(e){return{ok:!1,message:`Network error: ${e instanceof Error?e.message:String(e)}`}}}export async function fetchMyScores(a){const r=t.replace(/\/$/,"")+"/api/icoa/learn/myscores";try{const t=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({token:a.token.toUpperCase(),card_lo:a.cardLo,card_hi:a.cardHi,device_fingerprint:e()}),signal:AbortSignal.timeout(8e3)}),o=await t.json().catch(()=>({}));return t.ok&&o.success&&o.data?{ok:!0,scores:o.data.scores??[]}:{ok:!1,message:n(t.status,o.message),code:o.code}}catch(e){return{ok:!1,message:`Network error: ${e instanceof Error?e.message:String(e)}`}}}export async function viewHonors(a){const r=t.replace(/\/$/,"")+"/api/icoa/learn/honors";try{const t=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({token:a.token.toUpperCase(),curriculum_id:a.curriculumId,card_number:a.cardNumber,device_fingerprint:e()}),signal:AbortSignal.timeout(3e4)}),o=await t.json().catch(()=>({}));return t.ok&&o.success&&o.data?{ok:!0,board:o.data.board,mine:o.data.mine??null,nickname:o.data.nickname??null,totals:o.data.totals,chapters:o.data.chapters,floor:o.data.floor,phaseBoard:o.data.phaseBoard??null,practiceBoard:o.data.practiceBoard??null}:{ok:!1,message:n(t.status,o.message),code:o.code}}catch(e){return{ok:!1,message:`Network error: ${e instanceof Error?e.message:String(e)}`}}}export async function setNickname(a){const r=t.replace(/\/$/,"")+"/api/icoa/learn/nickname";try{const t=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({token:a.token.toUpperCase(),nickname:a.nickname,device_fingerprint:e()}),signal:AbortSignal.timeout(3e4)}),o=await t.json().catch(()=>({}));return t.ok&&o.success&&o.data?{ok:!0,nickname:o.data.nickname}:{ok:!1,message:n(t.status,o.message),code:o.code}}catch(e){return{ok:!1,message:`Network error: ${e instanceof Error?e.message:String(e)}`}}}export async function recallCoach(r){const o=t.replace(/\/$/,"")+"/api/icoa/learn/recall";try{const t=await a(o,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({token:r.token.toUpperCase(),device_fingerprint:e(),phase:r.phase,slot:r.slot,problem_title:r.problemTitle,statement:r.statement,code:r.code,level:r.level,lang:r.lang}),signal:AbortSignal.timeout(55e3)}),s=await t.json().catch(()=>({}));return t.ok&&s.success&&s.data?.hint?{ok:!0,hint:s.data.hint,level:s.data.level,spent:s.data.spent,cap:s.data.cap}:{ok:!1,message:n(t.status,s.message),code:s.code}}catch(e){return{ok:!1,message:e instanceof Error&&"TimeoutError"===e.name?"Coach timed out — try again in a minute.":`Network error: ${e instanceof Error?e.message:String(e)}`}}}export async function streamLearnTutor(r,o){const s=t.replace(/\/$/,"")+"/api/icoa/learn/ai",i=new AbortController;let c=setTimeout(()=>i.abort(),6e4);const d=()=>{clearTimeout(c),c=setTimeout(()=>i.abort(),6e4)};try{const t=await a(s,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({token:r.token.toUpperCase(),card_number:r.cardNumber,question:r.question,mode:r.mode,lang:r.lang??"en",history:r.history?.slice(-6),device_fingerprint:e()}),signal:i.signal});if(!t.ok||!t.body){const e=await t.json().catch(()=>({}));return{ok:!1,answer:"",message:e.message||n(t.status),code:e.code,spent:e.spent,cap:e.cap,tier:e.tier,cardLeft:e.card_left,cardCap:e.card_cap}}const c=t.body.getReader(),
|
|
1
|
+
import{getDeviceFingerprint as e}from"./access.js";import{LEARN_SERVER as t}from"./learn-curricula.js";import{httpFetch as a}from"./http.js";import{getConfig as r}from"./config.js";function n(e,t){const a=(r().language||"en").toLowerCase().startsWith("zh");return 502===e||503===e||504===e?a?"服务这次没能在窗口内答复 — 你的内容已安全存在服务器上。稍等一会再试即可。":"The server did not answer in time — your work is safe on the server. Wait a moment and try again.":t||`HTTP ${e}`}export async function submitPqs(a){const r=t.replace(/\/$/,"")+"/api/icoa/learn/submit";try{const t=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({token:a.token.toUpperCase(),card_number:a.cardNumber,device_fingerprint:e()}),signal:AbortSignal.timeout(18e4)}),o=await t.json().catch(()=>({}));if(!t.ok||!o.success||!o.data)return{ok:!1,message:n(t.status,o.message),code:o.code};const s=o.data;return{ok:!0,score:s.score,tier:s.tier,manipulation:s.manipulation,feedback:s.feedback,improve:s.improve,submissionIndex:s.submission_index,submissionsLeft:s.submissions_left,rank:s.rank,entrants:s.entrants,inTop3:s.in_top3,turns:s.turns,spent:s.spent,cap:s.cap}}catch(e){return{ok:!1,message:e instanceof Error&&"TimeoutError"===e.name?"PQS grading timed out — your conversation is safe on the server; try /submit again in a minute.":`Network error: ${e instanceof Error?e.message:String(e)}`}}}export async function viewPqsTop(a){const r=t.replace(/\/$/,"")+"/api/icoa/learn/view";try{const t=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({token:a.token.toUpperCase(),card_number:a.cardNumber,device_fingerprint:e()}),signal:AbortSignal.timeout(3e4)}),o=await t.json().catch(()=>({}));return t.ok&&o.success&&o.data?{ok:!0,top3:o.data.top3,myRank:o.data.my_rank,entrants:o.data.entrants}:{ok:!1,message:n(t.status,o.message),code:o.code,myRank:o.rank,entrants:o.entrants}}catch(e){return{ok:!1,message:`Network error: ${e instanceof Error?e.message:String(e)}`}}}export async function fetchMyScores(a){const r=t.replace(/\/$/,"")+"/api/icoa/learn/myscores";try{const t=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({token:a.token.toUpperCase(),card_lo:a.cardLo,card_hi:a.cardHi,device_fingerprint:e()}),signal:AbortSignal.timeout(8e3)}),o=await t.json().catch(()=>({}));return t.ok&&o.success&&o.data?{ok:!0,scores:o.data.scores??[]}:{ok:!1,message:n(t.status,o.message),code:o.code}}catch(e){return{ok:!1,message:`Network error: ${e instanceof Error?e.message:String(e)}`}}}export async function viewHonors(a){const r=t.replace(/\/$/,"")+"/api/icoa/learn/honors";try{const t=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({token:a.token.toUpperCase(),curriculum_id:a.curriculumId,card_number:a.cardNumber,device_fingerprint:e()}),signal:AbortSignal.timeout(3e4)}),o=await t.json().catch(()=>({}));return t.ok&&o.success&&o.data?{ok:!0,board:o.data.board,mine:o.data.mine??null,nickname:o.data.nickname??null,totals:o.data.totals,chapters:o.data.chapters,floor:o.data.floor,phaseBoard:o.data.phaseBoard??null,practiceBoard:o.data.practiceBoard??null}:{ok:!1,message:n(t.status,o.message),code:o.code}}catch(e){return{ok:!1,message:`Network error: ${e instanceof Error?e.message:String(e)}`}}}export async function setNickname(a){const r=t.replace(/\/$/,"")+"/api/icoa/learn/nickname";try{const t=await fetch(r,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({token:a.token.toUpperCase(),nickname:a.nickname,device_fingerprint:e()}),signal:AbortSignal.timeout(3e4)}),o=await t.json().catch(()=>({}));return t.ok&&o.success&&o.data?{ok:!0,nickname:o.data.nickname}:{ok:!1,message:n(t.status,o.message),code:o.code}}catch(e){return{ok:!1,message:`Network error: ${e instanceof Error?e.message:String(e)}`}}}export async function recallCoach(r){const o=t.replace(/\/$/,"")+"/api/icoa/learn/recall";try{const t=await a(o,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({token:r.token.toUpperCase(),device_fingerprint:e(),phase:r.phase,slot:r.slot,problem_title:r.problemTitle,statement:r.statement,code:r.code,level:r.level,lang:r.lang}),signal:AbortSignal.timeout(55e3)}),s=await t.json().catch(()=>({}));return t.ok&&s.success&&s.data?.hint?{ok:!0,hint:s.data.hint,level:s.data.level,spent:s.data.spent,cap:s.data.cap}:{ok:!1,message:n(t.status,s.message),code:s.code}}catch(e){return{ok:!1,message:e instanceof Error&&"TimeoutError"===e.name?"Coach timed out — try again in a minute.":`Network error: ${e instanceof Error?e.message:String(e)}`}}}export async function streamLearnTutor(r,o){const s=t.replace(/\/$/,"")+"/api/icoa/learn/ai",i=new AbortController;let c=setTimeout(()=>i.abort(),6e4);const d=()=>{clearTimeout(c),c=setTimeout(()=>i.abort(),6e4)};try{const t=await a(s,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({token:r.token.toUpperCase(),card_number:r.cardNumber,question:r.question,mode:r.mode,lang:r.lang??"en",history:r.history?.slice(-6),...r.replay?{replay:r.replay}:{},device_fingerprint:e()}),signal:i.signal});if(!t.ok||!t.body){const e=await t.json().catch(()=>({}));return{ok:!1,answer:"",message:e.message||n(t.status),code:e.code,spent:e.spent,cap:e.cap,tier:e.tier,cardLeft:e.card_left,cardCap:e.card_cap}}const c=t.body.getReader(),p=new TextDecoder;let m="",l="",u=null,g=null;for(;;){const e=await c.read();if(e.done)break;d(),m+=p.decode(e.value,{stream:!0});const t=m.split("\n");m=t.pop()??"";for(const e of t){const t=e.trim();if(!t.startsWith("data:"))continue;let a;try{a=JSON.parse(t.slice(5).trim())}catch{continue}a.r&&o({kind:"reasoning",text:a.r}),a.c&&(l+=a.c,o({kind:"content",text:a.c})),a.error&&(g=a.error),a.done&&(u=a)}}return g&&!l?{ok:!1,answer:"",message:g}:l?{ok:!0,answer:l,offtopic:!0===u?.offtopic,spent:u?.spent,cap:u?.cap,tier:u?.tier,cardLeft:u?.card_left,cardCap:u?.card_cap}:{ok:!1,answer:"",message:"No answer received — try again."}}catch(e){return{ok:!1,answer:"",message:e instanceof Error&&"AbortError"===e.name?"AI Panda Tutor timed out (no data for 60s) — try again.":`Network error: ${e instanceof Error?e.message:String(e)}`}}finally{clearTimeout(c)}}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "icoa-cli",
|
|
3
|
-
"version": "2.19.
|
|
3
|
+
"version": "2.19.630",
|
|
4
4
|
"description": "ICOA CLI — AI-native competition runtime of the International Cyber Olympiad in AI: learn, practise, and compete in AI & cybersecurity from the terminal (AI4CTF · CTF4AI · CTF4EAI)",
|
|
5
5
|
"author": "Charlie Zhu",
|
|
6
6
|
"type": "module",
|