icoa-cli 2.19.195 → 2.19.197

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.
Files changed (806) hide show
  1. package/dist/commands/ai4ctf.js +1 -1
  2. package/dist/commands/ctf4ai-demo.js +1 -1
  3. package/dist/commands/ctf4vla.js +1 -1
  4. package/dist/commands/exam.js +1 -1
  5. package/dist/commands/lang.js +1 -1
  6. package/dist/commands/sim.js +1 -1
  7. package/dist/lib/demo-exam.js +1 -1
  8. package/dist/lib/hint-client.js +1 -1
  9. package/dist/lib/translation.js +1 -1
  10. package/dist/lib/translations-fetcher.d.ts +6 -0
  11. package/dist/lib/translations-fetcher.js +1 -0
  12. package/dist/repl.js +1 -1
  13. package/package.json +1 -2
  14. package/assets/sim/ensemble.mp4 +0 -0
  15. package/translations/ar/1.json +0 -9
  16. package/translations/ar/10.json +0 -9
  17. package/translations/ar/11.json +0 -9
  18. package/translations/ar/12.json +0 -9
  19. package/translations/ar/13.json +0 -9
  20. package/translations/ar/14.json +0 -9
  21. package/translations/ar/15.json +0 -9
  22. package/translations/ar/16.json +0 -9
  23. package/translations/ar/17.json +0 -9
  24. package/translations/ar/18.json +0 -9
  25. package/translations/ar/19.json +0 -9
  26. package/translations/ar/20.json +0 -9
  27. package/translations/ar/21.json +0 -9
  28. package/translations/ar/22.json +0 -9
  29. package/translations/ar/23.json +0 -9
  30. package/translations/ar/24.json +0 -9
  31. package/translations/ar/25.json +0 -9
  32. package/translations/ar/26.json +0 -9
  33. package/translations/ar/27.json +0 -9
  34. package/translations/ar/28.json +0 -9
  35. package/translations/ar/29.json +0 -9
  36. package/translations/ar/30.json +0 -9
  37. package/translations/ar/31.json +0 -9
  38. package/translations/ar/32.json +0 -9
  39. package/translations/ar/33.json +0 -9
  40. package/translations/ar/34.json +0 -9
  41. package/translations/ar/35.json +0 -9
  42. package/translations/ar/36.json +0 -9
  43. package/translations/ar/37.json +0 -9
  44. package/translations/ar/38.json +0 -9
  45. package/translations/ar/39.json +0 -9
  46. package/translations/ar/4.json +0 -9
  47. package/translations/ar/40.json +0 -9
  48. package/translations/ar/41.json +0 -9
  49. package/translations/ar/42.json +0 -9
  50. package/translations/ar/43.json +0 -9
  51. package/translations/ar/44.json +0 -9
  52. package/translations/ar/45.json +0 -9
  53. package/translations/ar/46.json +0 -9
  54. package/translations/ar/47.json +0 -9
  55. package/translations/ar/48.json +0 -9
  56. package/translations/ar/49.json +0 -9
  57. package/translations/ar/5.json +0 -9
  58. package/translations/ar/6.json +0 -9
  59. package/translations/ar/7.json +0 -9
  60. package/translations/ar/8.json +0 -9
  61. package/translations/ar/9.json +0 -9
  62. package/translations/ar/demo-explanations.json +0 -32
  63. package/translations/ar/demo.json +0 -332
  64. package/translations/bn/demo-explanations.json +0 -32
  65. package/translations/bn/i18n-snippet.ts +0 -1
  66. package/translations/de/1.json +0 -9
  67. package/translations/de/10.json +0 -9
  68. package/translations/de/11.json +0 -9
  69. package/translations/de/12.json +0 -9
  70. package/translations/de/13.json +0 -9
  71. package/translations/de/14.json +0 -9
  72. package/translations/de/15.json +0 -9
  73. package/translations/de/16.json +0 -9
  74. package/translations/de/17.json +0 -9
  75. package/translations/de/18.json +0 -9
  76. package/translations/de/19.json +0 -9
  77. package/translations/de/20.json +0 -9
  78. package/translations/de/21.json +0 -9
  79. package/translations/de/22.json +0 -9
  80. package/translations/de/23.json +0 -9
  81. package/translations/de/24.json +0 -9
  82. package/translations/de/25.json +0 -9
  83. package/translations/de/26.json +0 -9
  84. package/translations/de/27.json +0 -9
  85. package/translations/de/28.json +0 -9
  86. package/translations/de/29.json +0 -9
  87. package/translations/de/30.json +0 -9
  88. package/translations/de/31.json +0 -9
  89. package/translations/de/32.json +0 -9
  90. package/translations/de/33.json +0 -9
  91. package/translations/de/34.json +0 -9
  92. package/translations/de/35.json +0 -9
  93. package/translations/de/36.json +0 -9
  94. package/translations/de/37.json +0 -9
  95. package/translations/de/38.json +0 -9
  96. package/translations/de/39.json +0 -9
  97. package/translations/de/4.json +0 -9
  98. package/translations/de/40.json +0 -9
  99. package/translations/de/41.json +0 -9
  100. package/translations/de/42.json +0 -9
  101. package/translations/de/43.json +0 -9
  102. package/translations/de/44.json +0 -9
  103. package/translations/de/45.json +0 -9
  104. package/translations/de/46.json +0 -9
  105. package/translations/de/47.json +0 -9
  106. package/translations/de/48.json +0 -9
  107. package/translations/de/49.json +0 -9
  108. package/translations/de/5.json +0 -9
  109. package/translations/de/6.json +0 -9
  110. package/translations/de/7.json +0 -9
  111. package/translations/de/8.json +0 -9
  112. package/translations/de/9.json +0 -9
  113. package/translations/de/demo-explanations.json +0 -32
  114. package/translations/de/demo.json +0 -332
  115. package/translations/es/1.json +0 -9
  116. package/translations/es/10.json +0 -9
  117. package/translations/es/11.json +0 -9
  118. package/translations/es/12.json +0 -9
  119. package/translations/es/13.json +0 -9
  120. package/translations/es/14.json +0 -9
  121. package/translations/es/15.json +0 -9
  122. package/translations/es/16.json +0 -9
  123. package/translations/es/17.json +0 -9
  124. package/translations/es/18.json +0 -9
  125. package/translations/es/19.json +0 -9
  126. package/translations/es/20.json +0 -9
  127. package/translations/es/21.json +0 -9
  128. package/translations/es/22.json +0 -9
  129. package/translations/es/23.json +0 -9
  130. package/translations/es/24.json +0 -9
  131. package/translations/es/25.json +0 -9
  132. package/translations/es/26.json +0 -9
  133. package/translations/es/27.json +0 -9
  134. package/translations/es/28.json +0 -9
  135. package/translations/es/29.json +0 -9
  136. package/translations/es/30.json +0 -9
  137. package/translations/es/31.json +0 -9
  138. package/translations/es/32.json +0 -9
  139. package/translations/es/33.json +0 -9
  140. package/translations/es/34.json +0 -9
  141. package/translations/es/35.json +0 -9
  142. package/translations/es/36.json +0 -9
  143. package/translations/es/37.json +0 -9
  144. package/translations/es/38.json +0 -9
  145. package/translations/es/39.json +0 -9
  146. package/translations/es/4.json +0 -9
  147. package/translations/es/40.json +0 -9
  148. package/translations/es/41.json +0 -9
  149. package/translations/es/42.json +0 -9
  150. package/translations/es/43.json +0 -9
  151. package/translations/es/44.json +0 -9
  152. package/translations/es/45.json +0 -9
  153. package/translations/es/46.json +0 -9
  154. package/translations/es/47.json +0 -9
  155. package/translations/es/48.json +0 -9
  156. package/translations/es/49.json +0 -9
  157. package/translations/es/5.json +0 -9
  158. package/translations/es/6.json +0 -9
  159. package/translations/es/7.json +0 -9
  160. package/translations/es/8.json +0 -9
  161. package/translations/es/9.json +0 -9
  162. package/translations/es/demo-explanations.json +0 -32
  163. package/translations/es/demo.json +0 -332
  164. package/translations/fr/1.json +0 -9
  165. package/translations/fr/10.json +0 -9
  166. package/translations/fr/11.json +0 -9
  167. package/translations/fr/12.json +0 -9
  168. package/translations/fr/13.json +0 -9
  169. package/translations/fr/14.json +0 -9
  170. package/translations/fr/15.json +0 -9
  171. package/translations/fr/16.json +0 -9
  172. package/translations/fr/17.json +0 -9
  173. package/translations/fr/18.json +0 -9
  174. package/translations/fr/19.json +0 -9
  175. package/translations/fr/20.json +0 -9
  176. package/translations/fr/21.json +0 -9
  177. package/translations/fr/22.json +0 -9
  178. package/translations/fr/23.json +0 -9
  179. package/translations/fr/24.json +0 -9
  180. package/translations/fr/25.json +0 -9
  181. package/translations/fr/26.json +0 -9
  182. package/translations/fr/27.json +0 -9
  183. package/translations/fr/28.json +0 -9
  184. package/translations/fr/29.json +0 -9
  185. package/translations/fr/30.json +0 -9
  186. package/translations/fr/31.json +0 -9
  187. package/translations/fr/32.json +0 -9
  188. package/translations/fr/33.json +0 -9
  189. package/translations/fr/34.json +0 -9
  190. package/translations/fr/35.json +0 -9
  191. package/translations/fr/36.json +0 -9
  192. package/translations/fr/37.json +0 -9
  193. package/translations/fr/38.json +0 -9
  194. package/translations/fr/39.json +0 -9
  195. package/translations/fr/4.json +0 -9
  196. package/translations/fr/40.json +0 -9
  197. package/translations/fr/41.json +0 -9
  198. package/translations/fr/42.json +0 -9
  199. package/translations/fr/43.json +0 -9
  200. package/translations/fr/44.json +0 -9
  201. package/translations/fr/45.json +0 -9
  202. package/translations/fr/46.json +0 -9
  203. package/translations/fr/47.json +0 -9
  204. package/translations/fr/48.json +0 -9
  205. package/translations/fr/49.json +0 -9
  206. package/translations/fr/5.json +0 -9
  207. package/translations/fr/6.json +0 -9
  208. package/translations/fr/7.json +0 -9
  209. package/translations/fr/8.json +0 -9
  210. package/translations/fr/9.json +0 -9
  211. package/translations/fr/demo-explanations.json +0 -32
  212. package/translations/fr/demo.json +0 -332
  213. package/translations/hi/1.json +0 -9
  214. package/translations/hi/10.json +0 -9
  215. package/translations/hi/11.json +0 -9
  216. package/translations/hi/12.json +0 -9
  217. package/translations/hi/13.json +0 -9
  218. package/translations/hi/14.json +0 -9
  219. package/translations/hi/15.json +0 -9
  220. package/translations/hi/16.json +0 -9
  221. package/translations/hi/17.json +0 -9
  222. package/translations/hi/18.json +0 -9
  223. package/translations/hi/19.json +0 -9
  224. package/translations/hi/20.json +0 -9
  225. package/translations/hi/21.json +0 -9
  226. package/translations/hi/22.json +0 -9
  227. package/translations/hi/23.json +0 -9
  228. package/translations/hi/24.json +0 -9
  229. package/translations/hi/25.json +0 -9
  230. package/translations/hi/26.json +0 -9
  231. package/translations/hi/27.json +0 -9
  232. package/translations/hi/28.json +0 -9
  233. package/translations/hi/29.json +0 -9
  234. package/translations/hi/30.json +0 -9
  235. package/translations/hi/31.json +0 -9
  236. package/translations/hi/32.json +0 -9
  237. package/translations/hi/33.json +0 -9
  238. package/translations/hi/34.json +0 -9
  239. package/translations/hi/35.json +0 -9
  240. package/translations/hi/36.json +0 -9
  241. package/translations/hi/37.json +0 -9
  242. package/translations/hi/38.json +0 -9
  243. package/translations/hi/39.json +0 -9
  244. package/translations/hi/4.json +0 -9
  245. package/translations/hi/40.json +0 -9
  246. package/translations/hi/41.json +0 -9
  247. package/translations/hi/42.json +0 -9
  248. package/translations/hi/43.json +0 -9
  249. package/translations/hi/44.json +0 -9
  250. package/translations/hi/45.json +0 -9
  251. package/translations/hi/46.json +0 -9
  252. package/translations/hi/47.json +0 -9
  253. package/translations/hi/48.json +0 -9
  254. package/translations/hi/49.json +0 -9
  255. package/translations/hi/5.json +0 -9
  256. package/translations/hi/6.json +0 -9
  257. package/translations/hi/7.json +0 -9
  258. package/translations/hi/8.json +0 -9
  259. package/translations/hi/9.json +0 -9
  260. package/translations/hi/demo-explanations.json +0 -32
  261. package/translations/hi/demo.json +0 -332
  262. package/translations/ht/1.json +0 -9
  263. package/translations/ht/10.json +0 -9
  264. package/translations/ht/11.json +0 -9
  265. package/translations/ht/12.json +0 -9
  266. package/translations/ht/13.json +0 -9
  267. package/translations/ht/14.json +0 -9
  268. package/translations/ht/15.json +0 -9
  269. package/translations/ht/16.json +0 -9
  270. package/translations/ht/17.json +0 -9
  271. package/translations/ht/18.json +0 -9
  272. package/translations/ht/19.json +0 -9
  273. package/translations/ht/20.json +0 -9
  274. package/translations/ht/21.json +0 -9
  275. package/translations/ht/22.json +0 -9
  276. package/translations/ht/23.json +0 -9
  277. package/translations/ht/24.json +0 -9
  278. package/translations/ht/25.json +0 -9
  279. package/translations/ht/26.json +0 -9
  280. package/translations/ht/27.json +0 -9
  281. package/translations/ht/28.json +0 -9
  282. package/translations/ht/29.json +0 -9
  283. package/translations/ht/30.json +0 -9
  284. package/translations/ht/31.json +0 -9
  285. package/translations/ht/32.json +0 -9
  286. package/translations/ht/33.json +0 -9
  287. package/translations/ht/34.json +0 -9
  288. package/translations/ht/35.json +0 -9
  289. package/translations/ht/36.json +0 -9
  290. package/translations/ht/37.json +0 -9
  291. package/translations/ht/38.json +0 -9
  292. package/translations/ht/39.json +0 -9
  293. package/translations/ht/4.json +0 -9
  294. package/translations/ht/40.json +0 -9
  295. package/translations/ht/41.json +0 -9
  296. package/translations/ht/42.json +0 -9
  297. package/translations/ht/43.json +0 -9
  298. package/translations/ht/44.json +0 -9
  299. package/translations/ht/45.json +0 -9
  300. package/translations/ht/46.json +0 -9
  301. package/translations/ht/47.json +0 -9
  302. package/translations/ht/48.json +0 -9
  303. package/translations/ht/49.json +0 -9
  304. package/translations/ht/5.json +0 -9
  305. package/translations/ht/6.json +0 -9
  306. package/translations/ht/7.json +0 -9
  307. package/translations/ht/8.json +0 -9
  308. package/translations/ht/9.json +0 -9
  309. package/translations/ht/demo-explanations.json +0 -32
  310. package/translations/ht/demo.json +0 -332
  311. package/translations/ht/i18n-snippet.ts +0 -1
  312. package/translations/id/1.json +0 -9
  313. package/translations/id/10.json +0 -9
  314. package/translations/id/11.json +0 -9
  315. package/translations/id/12.json +0 -9
  316. package/translations/id/13.json +0 -9
  317. package/translations/id/14.json +0 -9
  318. package/translations/id/15.json +0 -9
  319. package/translations/id/16.json +0 -9
  320. package/translations/id/17.json +0 -9
  321. package/translations/id/18.json +0 -9
  322. package/translations/id/19.json +0 -9
  323. package/translations/id/20.json +0 -9
  324. package/translations/id/21.json +0 -9
  325. package/translations/id/22.json +0 -9
  326. package/translations/id/23.json +0 -9
  327. package/translations/id/24.json +0 -9
  328. package/translations/id/25.json +0 -9
  329. package/translations/id/26.json +0 -9
  330. package/translations/id/27.json +0 -9
  331. package/translations/id/28.json +0 -9
  332. package/translations/id/29.json +0 -9
  333. package/translations/id/30.json +0 -9
  334. package/translations/id/31.json +0 -9
  335. package/translations/id/32.json +0 -9
  336. package/translations/id/33.json +0 -9
  337. package/translations/id/34.json +0 -9
  338. package/translations/id/35.json +0 -9
  339. package/translations/id/36.json +0 -9
  340. package/translations/id/37.json +0 -9
  341. package/translations/id/38.json +0 -9
  342. package/translations/id/39.json +0 -9
  343. package/translations/id/4.json +0 -9
  344. package/translations/id/40.json +0 -9
  345. package/translations/id/41.json +0 -9
  346. package/translations/id/42.json +0 -9
  347. package/translations/id/43.json +0 -9
  348. package/translations/id/44.json +0 -9
  349. package/translations/id/45.json +0 -9
  350. package/translations/id/46.json +0 -9
  351. package/translations/id/47.json +0 -9
  352. package/translations/id/48.json +0 -9
  353. package/translations/id/49.json +0 -9
  354. package/translations/id/5.json +0 -9
  355. package/translations/id/6.json +0 -9
  356. package/translations/id/7.json +0 -9
  357. package/translations/id/8.json +0 -9
  358. package/translations/id/9.json +0 -9
  359. package/translations/id/demo-explanations.json +0 -32
  360. package/translations/id/demo.json +0 -332
  361. package/translations/ja/1.json +0 -9
  362. package/translations/ja/10.json +0 -9
  363. package/translations/ja/11.json +0 -9
  364. package/translations/ja/12.json +0 -9
  365. package/translations/ja/13.json +0 -9
  366. package/translations/ja/14.json +0 -9
  367. package/translations/ja/15.json +0 -9
  368. package/translations/ja/16.json +0 -9
  369. package/translations/ja/17.json +0 -9
  370. package/translations/ja/18.json +0 -9
  371. package/translations/ja/19.json +0 -9
  372. package/translations/ja/20.json +0 -9
  373. package/translations/ja/21.json +0 -9
  374. package/translations/ja/22.json +0 -9
  375. package/translations/ja/23.json +0 -9
  376. package/translations/ja/24.json +0 -9
  377. package/translations/ja/25.json +0 -9
  378. package/translations/ja/26.json +0 -9
  379. package/translations/ja/27.json +0 -9
  380. package/translations/ja/28.json +0 -9
  381. package/translations/ja/29.json +0 -9
  382. package/translations/ja/30.json +0 -9
  383. package/translations/ja/31.json +0 -9
  384. package/translations/ja/32.json +0 -9
  385. package/translations/ja/33.json +0 -9
  386. package/translations/ja/34.json +0 -9
  387. package/translations/ja/35.json +0 -9
  388. package/translations/ja/36.json +0 -9
  389. package/translations/ja/37.json +0 -9
  390. package/translations/ja/38.json +0 -9
  391. package/translations/ja/39.json +0 -9
  392. package/translations/ja/4.json +0 -9
  393. package/translations/ja/40.json +0 -9
  394. package/translations/ja/41.json +0 -9
  395. package/translations/ja/42.json +0 -9
  396. package/translations/ja/43.json +0 -9
  397. package/translations/ja/44.json +0 -9
  398. package/translations/ja/45.json +0 -9
  399. package/translations/ja/46.json +0 -9
  400. package/translations/ja/47.json +0 -9
  401. package/translations/ja/48.json +0 -9
  402. package/translations/ja/49.json +0 -9
  403. package/translations/ja/5.json +0 -9
  404. package/translations/ja/6.json +0 -9
  405. package/translations/ja/7.json +0 -9
  406. package/translations/ja/8.json +0 -9
  407. package/translations/ja/9.json +0 -9
  408. package/translations/ja/demo-explanations.json +0 -32
  409. package/translations/ja/demo.json +0 -332
  410. package/translations/ko/1.json +0 -9
  411. package/translations/ko/10.json +0 -9
  412. package/translations/ko/11.json +0 -9
  413. package/translations/ko/12.json +0 -9
  414. package/translations/ko/13.json +0 -9
  415. package/translations/ko/14.json +0 -9
  416. package/translations/ko/15.json +0 -9
  417. package/translations/ko/16.json +0 -9
  418. package/translations/ko/17.json +0 -9
  419. package/translations/ko/18.json +0 -9
  420. package/translations/ko/19.json +0 -9
  421. package/translations/ko/20.json +0 -9
  422. package/translations/ko/21.json +0 -9
  423. package/translations/ko/22.json +0 -9
  424. package/translations/ko/23.json +0 -9
  425. package/translations/ko/24.json +0 -9
  426. package/translations/ko/25.json +0 -9
  427. package/translations/ko/26.json +0 -9
  428. package/translations/ko/27.json +0 -9
  429. package/translations/ko/28.json +0 -9
  430. package/translations/ko/29.json +0 -9
  431. package/translations/ko/30.json +0 -9
  432. package/translations/ko/31.json +0 -9
  433. package/translations/ko/32.json +0 -9
  434. package/translations/ko/33.json +0 -9
  435. package/translations/ko/34.json +0 -9
  436. package/translations/ko/35.json +0 -9
  437. package/translations/ko/36.json +0 -9
  438. package/translations/ko/37.json +0 -9
  439. package/translations/ko/38.json +0 -9
  440. package/translations/ko/39.json +0 -9
  441. package/translations/ko/4.json +0 -9
  442. package/translations/ko/40.json +0 -9
  443. package/translations/ko/41.json +0 -9
  444. package/translations/ko/42.json +0 -9
  445. package/translations/ko/43.json +0 -9
  446. package/translations/ko/44.json +0 -9
  447. package/translations/ko/45.json +0 -9
  448. package/translations/ko/46.json +0 -9
  449. package/translations/ko/47.json +0 -9
  450. package/translations/ko/48.json +0 -9
  451. package/translations/ko/49.json +0 -9
  452. package/translations/ko/5.json +0 -9
  453. package/translations/ko/6.json +0 -9
  454. package/translations/ko/7.json +0 -9
  455. package/translations/ko/8.json +0 -9
  456. package/translations/ko/9.json +0 -9
  457. package/translations/ko/demo-explanations.json +0 -32
  458. package/translations/ko/demo.json +0 -332
  459. package/translations/lo/demo-explanations.json +0 -32
  460. package/translations/lo/i18n-snippet.ts +0 -1
  461. package/translations/pt/1.json +0 -9
  462. package/translations/pt/10.json +0 -9
  463. package/translations/pt/11.json +0 -9
  464. package/translations/pt/12.json +0 -9
  465. package/translations/pt/13.json +0 -9
  466. package/translations/pt/14.json +0 -9
  467. package/translations/pt/15.json +0 -9
  468. package/translations/pt/16.json +0 -9
  469. package/translations/pt/17.json +0 -9
  470. package/translations/pt/18.json +0 -9
  471. package/translations/pt/19.json +0 -9
  472. package/translations/pt/20.json +0 -9
  473. package/translations/pt/21.json +0 -9
  474. package/translations/pt/22.json +0 -9
  475. package/translations/pt/23.json +0 -9
  476. package/translations/pt/24.json +0 -9
  477. package/translations/pt/25.json +0 -9
  478. package/translations/pt/26.json +0 -9
  479. package/translations/pt/27.json +0 -9
  480. package/translations/pt/28.json +0 -9
  481. package/translations/pt/29.json +0 -9
  482. package/translations/pt/30.json +0 -9
  483. package/translations/pt/31.json +0 -9
  484. package/translations/pt/32.json +0 -9
  485. package/translations/pt/33.json +0 -9
  486. package/translations/pt/34.json +0 -9
  487. package/translations/pt/35.json +0 -9
  488. package/translations/pt/36.json +0 -9
  489. package/translations/pt/37.json +0 -9
  490. package/translations/pt/38.json +0 -9
  491. package/translations/pt/39.json +0 -9
  492. package/translations/pt/4.json +0 -9
  493. package/translations/pt/40.json +0 -9
  494. package/translations/pt/41.json +0 -9
  495. package/translations/pt/42.json +0 -9
  496. package/translations/pt/43.json +0 -9
  497. package/translations/pt/44.json +0 -9
  498. package/translations/pt/45.json +0 -9
  499. package/translations/pt/46.json +0 -9
  500. package/translations/pt/47.json +0 -9
  501. package/translations/pt/48.json +0 -9
  502. package/translations/pt/49.json +0 -9
  503. package/translations/pt/5.json +0 -9
  504. package/translations/pt/6.json +0 -9
  505. package/translations/pt/7.json +0 -9
  506. package/translations/pt/8.json +0 -9
  507. package/translations/pt/9.json +0 -9
  508. package/translations/pt/demo-explanations.json +0 -32
  509. package/translations/pt/demo.json +0 -332
  510. package/translations/ru/1.json +0 -9
  511. package/translations/ru/10.json +0 -9
  512. package/translations/ru/11.json +0 -9
  513. package/translations/ru/12.json +0 -9
  514. package/translations/ru/13.json +0 -9
  515. package/translations/ru/14.json +0 -9
  516. package/translations/ru/15.json +0 -9
  517. package/translations/ru/16.json +0 -9
  518. package/translations/ru/17.json +0 -9
  519. package/translations/ru/18.json +0 -9
  520. package/translations/ru/19.json +0 -9
  521. package/translations/ru/20.json +0 -9
  522. package/translations/ru/21.json +0 -9
  523. package/translations/ru/22.json +0 -9
  524. package/translations/ru/23.json +0 -9
  525. package/translations/ru/24.json +0 -9
  526. package/translations/ru/25.json +0 -9
  527. package/translations/ru/26.json +0 -9
  528. package/translations/ru/27.json +0 -9
  529. package/translations/ru/28.json +0 -9
  530. package/translations/ru/29.json +0 -9
  531. package/translations/ru/30.json +0 -9
  532. package/translations/ru/31.json +0 -9
  533. package/translations/ru/32.json +0 -9
  534. package/translations/ru/33.json +0 -9
  535. package/translations/ru/34.json +0 -9
  536. package/translations/ru/35.json +0 -9
  537. package/translations/ru/36.json +0 -9
  538. package/translations/ru/37.json +0 -9
  539. package/translations/ru/38.json +0 -9
  540. package/translations/ru/39.json +0 -9
  541. package/translations/ru/4.json +0 -9
  542. package/translations/ru/40.json +0 -9
  543. package/translations/ru/41.json +0 -9
  544. package/translations/ru/42.json +0 -9
  545. package/translations/ru/43.json +0 -9
  546. package/translations/ru/44.json +0 -9
  547. package/translations/ru/45.json +0 -9
  548. package/translations/ru/46.json +0 -9
  549. package/translations/ru/47.json +0 -9
  550. package/translations/ru/48.json +0 -9
  551. package/translations/ru/49.json +0 -9
  552. package/translations/ru/5.json +0 -9
  553. package/translations/ru/6.json +0 -9
  554. package/translations/ru/7.json +0 -9
  555. package/translations/ru/8.json +0 -9
  556. package/translations/ru/9.json +0 -9
  557. package/translations/ru/demo-explanations.json +0 -32
  558. package/translations/ru/demo.json +0 -332
  559. package/translations/si/demo-explanations.json +0 -32
  560. package/translations/sw/demo-explanations.json +0 -32
  561. package/translations/sw/i18n-snippet.ts +0 -1
  562. package/translations/th/1.json +0 -9
  563. package/translations/th/10.json +0 -9
  564. package/translations/th/11.json +0 -9
  565. package/translations/th/12.json +0 -9
  566. package/translations/th/13.json +0 -9
  567. package/translations/th/14.json +0 -9
  568. package/translations/th/15.json +0 -9
  569. package/translations/th/16.json +0 -9
  570. package/translations/th/17.json +0 -9
  571. package/translations/th/18.json +0 -9
  572. package/translations/th/19.json +0 -9
  573. package/translations/th/20.json +0 -9
  574. package/translations/th/21.json +0 -9
  575. package/translations/th/22.json +0 -9
  576. package/translations/th/23.json +0 -9
  577. package/translations/th/24.json +0 -9
  578. package/translations/th/25.json +0 -9
  579. package/translations/th/26.json +0 -9
  580. package/translations/th/27.json +0 -9
  581. package/translations/th/28.json +0 -9
  582. package/translations/th/29.json +0 -9
  583. package/translations/th/30.json +0 -9
  584. package/translations/th/31.json +0 -9
  585. package/translations/th/32.json +0 -9
  586. package/translations/th/33.json +0 -9
  587. package/translations/th/34.json +0 -9
  588. package/translations/th/35.json +0 -9
  589. package/translations/th/36.json +0 -9
  590. package/translations/th/37.json +0 -9
  591. package/translations/th/38.json +0 -9
  592. package/translations/th/39.json +0 -9
  593. package/translations/th/4.json +0 -9
  594. package/translations/th/40.json +0 -9
  595. package/translations/th/41.json +0 -9
  596. package/translations/th/42.json +0 -9
  597. package/translations/th/43.json +0 -9
  598. package/translations/th/44.json +0 -9
  599. package/translations/th/45.json +0 -9
  600. package/translations/th/46.json +0 -9
  601. package/translations/th/47.json +0 -9
  602. package/translations/th/48.json +0 -9
  603. package/translations/th/49.json +0 -9
  604. package/translations/th/5.json +0 -9
  605. package/translations/th/6.json +0 -9
  606. package/translations/th/7.json +0 -9
  607. package/translations/th/8.json +0 -9
  608. package/translations/th/9.json +0 -9
  609. package/translations/th/demo-explanations.json +0 -32
  610. package/translations/th/demo.json +0 -332
  611. package/translations/tr/1.json +0 -9
  612. package/translations/tr/10.json +0 -9
  613. package/translations/tr/11.json +0 -9
  614. package/translations/tr/12.json +0 -9
  615. package/translations/tr/13.json +0 -9
  616. package/translations/tr/14.json +0 -9
  617. package/translations/tr/15.json +0 -9
  618. package/translations/tr/16.json +0 -9
  619. package/translations/tr/17.json +0 -9
  620. package/translations/tr/18.json +0 -9
  621. package/translations/tr/19.json +0 -9
  622. package/translations/tr/20.json +0 -9
  623. package/translations/tr/21.json +0 -9
  624. package/translations/tr/22.json +0 -9
  625. package/translations/tr/23.json +0 -9
  626. package/translations/tr/24.json +0 -9
  627. package/translations/tr/25.json +0 -9
  628. package/translations/tr/26.json +0 -9
  629. package/translations/tr/27.json +0 -9
  630. package/translations/tr/28.json +0 -9
  631. package/translations/tr/30.json +0 -9
  632. package/translations/tr/31.json +0 -9
  633. package/translations/tr/32.json +0 -9
  634. package/translations/tr/33.json +0 -9
  635. package/translations/tr/34.json +0 -9
  636. package/translations/tr/35.json +0 -9
  637. package/translations/tr/36.json +0 -9
  638. package/translations/tr/37.json +0 -9
  639. package/translations/tr/38.json +0 -9
  640. package/translations/tr/39.json +0 -9
  641. package/translations/tr/4.json +0 -9
  642. package/translations/tr/40.json +0 -9
  643. package/translations/tr/41.json +0 -9
  644. package/translations/tr/42.json +0 -9
  645. package/translations/tr/43.json +0 -9
  646. package/translations/tr/44.json +0 -9
  647. package/translations/tr/45.json +0 -9
  648. package/translations/tr/46.json +0 -9
  649. package/translations/tr/47.json +0 -9
  650. package/translations/tr/48.json +0 -9
  651. package/translations/tr/49.json +0 -9
  652. package/translations/tr/5.json +0 -9
  653. package/translations/tr/6.json +0 -9
  654. package/translations/tr/7.json +0 -9
  655. package/translations/tr/8.json +0 -9
  656. package/translations/tr/9.json +0 -9
  657. package/translations/tr/demo-explanations.json +0 -32
  658. package/translations/tr/demo.json +0 -332
  659. package/translations/uk/1.json +0 -9
  660. package/translations/uk/10.json +0 -9
  661. package/translations/uk/11.json +0 -9
  662. package/translations/uk/12.json +0 -9
  663. package/translations/uk/13.json +0 -9
  664. package/translations/uk/14.json +0 -9
  665. package/translations/uk/15.json +0 -9
  666. package/translations/uk/16.json +0 -9
  667. package/translations/uk/17.json +0 -9
  668. package/translations/uk/18.json +0 -9
  669. package/translations/uk/19.json +0 -9
  670. package/translations/uk/20.json +0 -9
  671. package/translations/uk/21.json +0 -9
  672. package/translations/uk/22.json +0 -9
  673. package/translations/uk/23.json +0 -9
  674. package/translations/uk/24.json +0 -9
  675. package/translations/uk/25.json +0 -9
  676. package/translations/uk/26.json +0 -9
  677. package/translations/uk/27.json +0 -9
  678. package/translations/uk/28.json +0 -9
  679. package/translations/uk/29.json +0 -9
  680. package/translations/uk/30.json +0 -9
  681. package/translations/uk/31.json +0 -9
  682. package/translations/uk/32.json +0 -9
  683. package/translations/uk/33.json +0 -9
  684. package/translations/uk/34.json +0 -9
  685. package/translations/uk/35.json +0 -9
  686. package/translations/uk/36.json +0 -9
  687. package/translations/uk/37.json +0 -9
  688. package/translations/uk/38.json +0 -9
  689. package/translations/uk/39.json +0 -9
  690. package/translations/uk/4.json +0 -9
  691. package/translations/uk/40.json +0 -9
  692. package/translations/uk/41.json +0 -9
  693. package/translations/uk/42.json +0 -9
  694. package/translations/uk/43.json +0 -9
  695. package/translations/uk/44.json +0 -9
  696. package/translations/uk/45.json +0 -9
  697. package/translations/uk/46.json +0 -9
  698. package/translations/uk/47.json +0 -9
  699. package/translations/uk/48.json +0 -9
  700. package/translations/uk/49.json +0 -9
  701. package/translations/uk/5.json +0 -9
  702. package/translations/uk/6.json +0 -9
  703. package/translations/uk/7.json +0 -9
  704. package/translations/uk/8.json +0 -9
  705. package/translations/uk/9.json +0 -9
  706. package/translations/uk/demo-explanations.json +0 -32
  707. package/translations/uk/demo.json +0 -332
  708. package/translations/uz/demo-explanations.json +0 -32
  709. package/translations/uz/i18n-snippet.ts +0 -1
  710. package/translations/vi/1.json +0 -9
  711. package/translations/vi/10.json +0 -9
  712. package/translations/vi/11.json +0 -9
  713. package/translations/vi/12.json +0 -9
  714. package/translations/vi/14.json +0 -9
  715. package/translations/vi/15.json +0 -9
  716. package/translations/vi/16.json +0 -9
  717. package/translations/vi/17.json +0 -9
  718. package/translations/vi/18.json +0 -9
  719. package/translations/vi/19.json +0 -9
  720. package/translations/vi/20.json +0 -9
  721. package/translations/vi/21.json +0 -9
  722. package/translations/vi/22.json +0 -9
  723. package/translations/vi/23.json +0 -9
  724. package/translations/vi/24.json +0 -9
  725. package/translations/vi/25.json +0 -9
  726. package/translations/vi/26.json +0 -9
  727. package/translations/vi/27.json +0 -9
  728. package/translations/vi/28.json +0 -9
  729. package/translations/vi/29.json +0 -9
  730. package/translations/vi/30.json +0 -9
  731. package/translations/vi/31.json +0 -9
  732. package/translations/vi/32.json +0 -9
  733. package/translations/vi/33.json +0 -9
  734. package/translations/vi/34.json +0 -9
  735. package/translations/vi/35.json +0 -9
  736. package/translations/vi/36.json +0 -9
  737. package/translations/vi/37.json +0 -9
  738. package/translations/vi/38.json +0 -9
  739. package/translations/vi/39.json +0 -9
  740. package/translations/vi/4.json +0 -9
  741. package/translations/vi/40.json +0 -9
  742. package/translations/vi/41.json +0 -9
  743. package/translations/vi/42.json +0 -9
  744. package/translations/vi/43.json +0 -9
  745. package/translations/vi/44.json +0 -9
  746. package/translations/vi/45.json +0 -9
  747. package/translations/vi/46.json +0 -9
  748. package/translations/vi/47.json +0 -9
  749. package/translations/vi/48.json +0 -9
  750. package/translations/vi/49.json +0 -9
  751. package/translations/vi/5.json +0 -9
  752. package/translations/vi/6.json +0 -9
  753. package/translations/vi/7.json +0 -9
  754. package/translations/vi/8.json +0 -9
  755. package/translations/vi/9.json +0 -9
  756. package/translations/vi/demo-explanations.json +0 -32
  757. package/translations/vi/demo.json +0 -332
  758. package/translations/zh/1.json +0 -9
  759. package/translations/zh/10.json +0 -9
  760. package/translations/zh/11.json +0 -9
  761. package/translations/zh/12.json +0 -9
  762. package/translations/zh/13.json +0 -9
  763. package/translations/zh/14.json +0 -9
  764. package/translations/zh/15.json +0 -9
  765. package/translations/zh/16.json +0 -9
  766. package/translations/zh/17.json +0 -9
  767. package/translations/zh/18.json +0 -9
  768. package/translations/zh/19.json +0 -9
  769. package/translations/zh/20.json +0 -9
  770. package/translations/zh/21.json +0 -9
  771. package/translations/zh/22.json +0 -9
  772. package/translations/zh/23.json +0 -9
  773. package/translations/zh/24.json +0 -9
  774. package/translations/zh/25.json +0 -9
  775. package/translations/zh/26.json +0 -9
  776. package/translations/zh/27.json +0 -9
  777. package/translations/zh/28.json +0 -9
  778. package/translations/zh/29.json +0 -9
  779. package/translations/zh/30.json +0 -9
  780. package/translations/zh/31.json +0 -9
  781. package/translations/zh/32.json +0 -9
  782. package/translations/zh/33.json +0 -9
  783. package/translations/zh/34.json +0 -9
  784. package/translations/zh/35.json +0 -9
  785. package/translations/zh/36.json +0 -9
  786. package/translations/zh/37.json +0 -9
  787. package/translations/zh/38.json +0 -9
  788. package/translations/zh/39.json +0 -9
  789. package/translations/zh/4.json +0 -9
  790. package/translations/zh/40.json +0 -9
  791. package/translations/zh/41.json +0 -9
  792. package/translations/zh/42.json +0 -9
  793. package/translations/zh/43.json +0 -9
  794. package/translations/zh/44.json +0 -9
  795. package/translations/zh/45.json +0 -9
  796. package/translations/zh/46.json +0 -9
  797. package/translations/zh/47.json +0 -9
  798. package/translations/zh/48.json +0 -9
  799. package/translations/zh/49.json +0 -9
  800. package/translations/zh/5.json +0 -9
  801. package/translations/zh/6.json +0 -9
  802. package/translations/zh/7.json +0 -9
  803. package/translations/zh/8.json +0 -9
  804. package/translations/zh/9.json +0 -9
  805. package/translations/zh/demo-explanations.json +0 -32
  806. package/translations/zh/demo.json +0 -332
@@ -1 +1 @@
1
- import chalk from"chalk";import{getConfig as e,saveConfig as o}from"../lib/config.js";import{getExamState as s}from"../lib/exam-state.js";import{logCommand as a}from"../lib/logger.js";import{printSuccess as t,printError as n,printInfo as i}from"../lib/ui.js";import{SUPPORTED_LANGUAGES as r}from"../types/index.js";const l={en:"English",zh:"中文 (Chinese)",ja:"日本語 (Japanese)",ko:"한국어 (Korean)",es:"Español (Spanish)",ar:"العربية (Arabic)",fr:"Français (French)",pt:"Português (Portuguese)",ru:"Русский (Russian)",hi:"हिन्दी (Hindi)",de:"Deutsch (German)",id:"Bahasa (Indonesian)",th:"ไทย (Thai)",vi:"Tiếng Việt (Vietnamese)",tr:"Türkçe (Turkish)",uk:"Українська (Ukrainian)",ht:"Kreyòl (Haitian Creole)",sw:"Kiswahili (Swahili)",uz:"Oʻzbek (Uzbek)",lo:"ລາວ (Lao)"};export function registerLangCommand(c){c.command("lang [code]").description("Switch display language").action(async c=>{if(a(`lang ${c||""}`),!c){const o=e();i(`Current language: ${chalk.white(l[o.language]||o.language)}`),console.log(),console.log(chalk.gray(" Supported languages:"));for(const e of r){const s=o.language===e?chalk.yellow(" ← current"):"";console.log(` ${chalk.white(e)} ${l[e]}${s}`)}return console.log(),console.log(chalk.gray(" Switch now: ")+chalk.cyan("lang <code>")+chalk.gray(" (e.g. ")+chalk.cyan("lang es")+chalk.gray(")")),console.log(chalk.gray(' No "back" needed — you are still at the ')+chalk.cyan("icoa>")+chalk.gray(" prompt.")),void console.log()}if(!r.includes(c)){n(`Unsupported language: ${c}`);const e=r.map(e=>`${e} (${l[e]?.split(" ")[0]||e})`).join(", ");return void i(`Supported: ${e}`)}o({language:c}),t(`Language set to: ${l[c]||c}`);const g=s();if(g&&"demo-free"===g.session.examId)try{const{pickDemoQuestions:e,getLocalizedDemoSession:o,getLocalizedDemoQuestions:s,getLocalizedExplanations:a,DEMO_PICK_SIZE:t}=await import("../lib/demo-exam.js"),{saveExamState:n}=await import("../lib/exam-state.js");if(g.questions.every(e=>null!=e.sourceNumber&&Array.isArray(e.sourceOrder)&&4===e.sourceOrder.length)){const e=s(),t=a();g.questions=g.questions.map(o=>{const s=e.find(e=>e.number===o.sourceNumber);return s&&o.sourceOrder?{...o,text:s.text,category:s.category,options:{A:s.options[o.sourceOrder[0]],B:s.options[o.sourceOrder[1]],C:s.options[o.sourceOrder[2]],D:s.options[o.sourceOrder[3]]},explanation:t[o.sourceNumber]}:o}),g.session.examName=o().examName,n(g);const i=g._lastQ||1;console.log(),console.log(chalk.green(` Demo continues in ${l[c]||c}. Your progress is kept.`)),console.log(chalk.white(` Resume: exam q ${i}`))}else g.questions=e(t),g.answers={},g.session.examName=o().examName,g.session.startedAt=(new Date).toISOString(),g._lastQ=1,n(g),console.log(),console.log(chalk.green(` Demo restarted in ${l[c]||c}.`)),console.log(chalk.white(" Type: exam q 1"))}catch{console.log(chalk.gray(" Language changed. Type: demo"))}else if(g&&g.session.token)try{const{getConfig:e}=await import("../lib/config.js"),{saveExamState:o}=await import("../lib/exam-state.js"),{getDeviceFingerprint:s}=await import("../lib/access.js"),a=e().ctfdUrl||"https://practice.icoa2026.au",n=g.session.token,i=await fetch(`${a}/api/icoa/exam-token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({token:n,deviceHash:s(),lang:c}),signal:AbortSignal.timeout(1e4)});if(i.ok){const e=(await i.json()).data.questions;g.questions=e,o(g);const s=g._lastQ||1;console.log(),t(`Exam questions updated to ${l[c]||c}. Your answers are kept.`),console.log(chalk.white(` Resume: exam q ${s}`))}else{const{clearExamState:e}=await import("../lib/exam-state.js");e(),console.log(),console.log(chalk.yellow(" Your saved exam session is no longer active on the server")),console.log(chalk.gray(" (most often: already submitted, or the exam window has closed).")),console.log(chalk.gray(" We cleared the stale state for you. To start a fresh attempt:")),console.log(chalk.gray(" → ")+chalk.bold.cyan("exam <your-token>"))}}catch{console.log(chalk.yellow(" Could not reach server. Language changed for UI only."))}else if(g){const e=g._lastQ||1;console.log(),console.log(chalk.gray(` Exam in progress — resuming Q${e}:`)),console.log(chalk.white(` Type: exam q ${e}`))}})}
1
+ import chalk from"chalk";import{getConfig as e,saveConfig as o}from"../lib/config.js";import{getExamState as s}from"../lib/exam-state.js";import{logCommand as a}from"../lib/logger.js";import{ensureLangCache as t}from"../lib/translations-fetcher.js";import{printSuccess as n,printError as i,printInfo as r}from"../lib/ui.js";import{SUPPORTED_LANGUAGES as l}from"../types/index.js";const c={en:"English",zh:"中文 (Chinese)",ja:"日本語 (Japanese)",ko:"한국어 (Korean)",es:"Español (Spanish)",ar:"العربية (Arabic)",fr:"Français (French)",pt:"Português (Portuguese)",ru:"Русский (Russian)",hi:"हिन्दी (Hindi)",de:"Deutsch (German)",id:"Bahasa (Indonesian)",th:"ไทย (Thai)",vi:"Tiếng Việt (Vietnamese)",tr:"Türkçe (Turkish)",uk:"Українська (Ukrainian)",ht:"Kreyòl (Haitian Creole)",sw:"Kiswahili (Swahili)",uz:"Oʻzbek (Uzbek)",lo:"ລາວ (Lao)"};export function registerLangCommand(g){g.command("lang [code]").description("Switch display language").action(async g=>{if(a(`lang ${g||""}`),!g){const o=e();r(`Current language: ${chalk.white(c[o.language]||o.language)}`),console.log(),console.log(chalk.gray(" Supported languages:"));for(const e of l){const s=o.language===e?chalk.yellow(" ← current"):"";console.log(` ${chalk.white(e)} ${c[e]}${s}`)}return console.log(),console.log(chalk.gray(" Switch now: ")+chalk.cyan("lang <code>")+chalk.gray(" (e.g. ")+chalk.cyan("lang es")+chalk.gray(")")),console.log(chalk.gray(' No "back" needed — you are still at the ')+chalk.cyan("icoa>")+chalk.gray(" prompt.")),void console.log()}if(!l.includes(g)){i(`Unsupported language: ${g}`);const e=l.map(e=>`${e} (${c[e]?.split(" ")[0]||e})`).join(", ");return void r(`Supported: ${e}`)}o({language:g}),n(`Language set to: ${c[g]||g}`),await t(g);const m=s();if(m&&"demo-free"===m.session.examId)try{const{pickDemoQuestions:e,getLocalizedDemoSession:o,getLocalizedDemoQuestions:s,getLocalizedExplanations:a,DEMO_PICK_SIZE:t}=await import("../lib/demo-exam.js"),{saveExamState:n}=await import("../lib/exam-state.js");if(m.questions.every(e=>null!=e.sourceNumber&&Array.isArray(e.sourceOrder)&&4===e.sourceOrder.length)){const e=s(),t=a();m.questions=m.questions.map(o=>{const s=e.find(e=>e.number===o.sourceNumber);return s&&o.sourceOrder?{...o,text:s.text,category:s.category,options:{A:s.options[o.sourceOrder[0]],B:s.options[o.sourceOrder[1]],C:s.options[o.sourceOrder[2]],D:s.options[o.sourceOrder[3]]},explanation:t[o.sourceNumber]}:o}),m.session.examName=o().examName,n(m);const i=m._lastQ||1;console.log(),console.log(chalk.green(` Demo continues in ${c[g]||g}. Your progress is kept.`)),console.log(chalk.white(` Resume: exam q ${i}`))}else m.questions=e(t),m.answers={},m.session.examName=o().examName,m.session.startedAt=(new Date).toISOString(),m._lastQ=1,n(m),console.log(),console.log(chalk.green(` Demo restarted in ${c[g]||g}.`)),console.log(chalk.white(" Type: exam q 1"))}catch{console.log(chalk.gray(" Language changed. Type: demo"))}else if(m&&m.session.token)try{const{getConfig:e}=await import("../lib/config.js"),{saveExamState:o}=await import("../lib/exam-state.js"),{getDeviceFingerprint:s}=await import("../lib/access.js"),a=e().ctfdUrl||"https://practice.icoa2026.au",t=m.session.token,i=await fetch(`${a}/api/icoa/exam-token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({token:t,deviceHash:s(),lang:g}),signal:AbortSignal.timeout(1e4)});if(i.ok){const e=(await i.json()).data.questions;m.questions=e,o(m);const s=m._lastQ||1;console.log(),n(`Exam questions updated to ${c[g]||g}. Your answers are kept.`),console.log(chalk.white(` Resume: exam q ${s}`))}else{const{clearExamState:e}=await import("../lib/exam-state.js");e(),console.log(),console.log(chalk.yellow(" Your saved exam session is no longer active on the server")),console.log(chalk.gray(" (most often: already submitted, or the exam window has closed).")),console.log(chalk.gray(" We cleared the stale state for you. To start a fresh attempt:")),console.log(chalk.gray(" → ")+chalk.bold.cyan("exam <your-token>"))}}catch{console.log(chalk.yellow(" Could not reach server. Language changed for UI only."))}else if(m){const e=m._lastQ||1;console.log(),console.log(chalk.gray(` Exam in progress — resuming Q${e}:`)),console.log(chalk.white(` Type: exam q ${e}`))}})}
@@ -1 +1 @@
1
- import chalk from"chalk";import{spawn as e}from"node:child_process";import{copyFileSync as o,existsSync as n,writeFileSync as r}from"node:fs";import{dirname as a,join as l,resolve as s}from"node:path";import{createInterface as t}from"node:readline";import{fileURLToPath as i}from"node:url";import{fetchWithCountdown as c}from"../lib/countdown.js";import{getMainRl as d}from"../lib/main-rl.js";import{COOLDOWN_SECONDS as p,lastSimAt as m,markArmAt as g,markBundledAt as u,markSimAt as y}from"../lib/sim-cooldown.js";const b={baseline:{action:null,label:"Baseline — robot doing its job",hint:"Approach → grasp → lift → place → return. This is what normal looks like.",frames:90,narrative:!0},release:{action:{xyz:[.1,0,.3],rotation:[0,0,0],gripper_close:.05},label:'Prompt Injection — "release the gripper"',hint:"Gripper opens (0.05 < 0.10 win threshold). This is Paper D Q41 success."},patch:{action:{xyz:[-.3,.2,.5],rotation:[.5,0,.3],gripper_close:.95},label:"Adversarial Patch — sticker redirects the arm",hint:"Same instruction, but arm reaches LEFT instead of RIGHT. Paper D Q42 success."},confused:{action:{xyz:[.001,0,.001],rotation:[0,0,0],gripper_close:.5},label:'Modality Confusion — "pick up the purple object"',hint:"No purple object exists. VLA freezes near origin. Paper D Q43 success."},color:{action:{xyz:[.4,-.3,.6],rotation:[-.4,.2,-.1],gripper_close:.2},label:"Cross-Modal Attack — image + text manipulated together",hint:"Action drifts hard on multiple axes. Paper D Q49-class attack (future).",hidden:!0},ensemble:{action:null,label:"Ensemble — 8 robots dancing on one beat",hint:"Pre-rendered group dance. Instant. No cooldown.",bundled:"ensemble.mp4"},arm:{action:null,label:"Arm mode — interactive 6-DOF companion-arm sandbox",hint:"Type 6 joint amplitudes (or a preset). Each render takes ~15s, 60s cooldown.",bundled:void 0}},f=Object.fromEntries(Object.entries(b).filter(([,e])=>!e.hidden)),h={1:{vec:[1,1,1,1,1.4,1],label:"full demo — every joint at full amplitude"},2:{vec:[1,0,0,0,0,0],label:"base spin only (joint 1 swings)"},3:{vec:[0,.8,.8,0,0,0],label:"shoulder + elbow (lift cycle)"},4:{vec:[0,0,0,.8,1.4,1],label:"wrist drill — j4 roll + j5 bend + j6 twist"},5:{vec:[-.7,-.8,.6,.7,-1,.5],label:"mixed asymmetric (chaotic)"}};function w(){return"darwin"===process.platform?"open":"win32"===process.platform?"start":"xdg-open"}async function v(o){const n=(Date.now()-m())/1e3;if(n<p){const e=Math.ceil(p-n);return console.log(chalk.yellow(` Please wait ${e}s before the next render.`)),console.log(chalk.gray(" (One render per minute keeps things fast for everyone.)")),!1}const a=`${process.env.ICOA_SERVER_URL?.replace(/\/+$/,"")||"https://practice.icoa2026.au"}/api/ai/vla/41/sim`;o.quietHeader||(console.log(),console.log(chalk.bold.cyan(" ICOA · MuJoCo Sim")),console.log(chalk.gray(" ")+chalk.white(o.label)),console.log());try{const n=fetch(a,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({action:o.action,frames:o.frames,narrative:o.narrative,...o.panda2_pose?{panda2_pose:o.panda2_pose}:{}}),signal:AbortSignal.timeout(6e4)}),s=await c(n);if(!s.ok)return console.log(chalk.yellow(` Server returned HTTP ${s.status}.`)),!1;const t=await s.json();if(!t.success||!t.data?.mp4_b64)return console.log(chalk.yellow(" Renderer unavailable.")),!1;const i=process.env.TMPDIR||"/tmp",d=l(i,`icoa-sim-${o.scenarioName}-${Date.now()}.mp4`);r(d,Buffer.from(t.data.mp4_b64,"base64")),y(Date.now()),console.log(),console.log(chalk.bold.green(" ✓ ")+chalk.gray("Rendered.")),t.data.description&&console.log(chalk.gray(" Action: ")+chalk.white(t.data.description)),console.log(),console.log(chalk.gray(" ")+o.hint),console.log();const p=w();return p?(e(p,[d],{stdio:"ignore",detached:!0}).unref(),console.log(chalk.gray(" Opening in your default video player..."))):console.log(chalk.gray(" Video at: ")+chalk.white(d)),console.log(),!0}catch(e){const o=e instanceof Error?e.message:String(e);return console.log(chalk.yellow(` Sim error: ${o}`)),!1}}export function registerSimCommand(r){r.command("sim [scenario]").description("MuJoCo VLA — sim (group dance) · sim arm (interactive companion arm) · sim baseline/release/patch/confused").action(async r=>{await async function(r){const c=r.toLowerCase();if("arm"===c)return void await async function(){console.log(),console.log(chalk.bold.cyan(" ICOA · Companion Arm Sandbox")),console.log(chalk.gray(" Drive the printable 6-DOF arm directly. Server renders, video opens.")),console.log(),console.log(chalk.gray(" Joint amplitudes (radians, suggested range −1.0 to +1.0):")),console.log(chalk.gray(" j1=base spin j2=shoulder j3=elbow")),console.log(chalk.gray(" j4=forearm roll j5=wrist pitch j6=wrist roll")),console.log(),console.log(chalk.gray(" Type 6 numbers separated by spaces, or pick a preset:"));for(const[e,o]of Object.entries(h)){const n=o.vec.map(e=>e.toFixed(1).padStart(4)).join(" ");console.log(chalk.gray(" ")+chalk.bold.cyan(e)+chalk.gray(" → ["+n+"] "+o.label))}console.log(),console.log(chalk.gray(" Each render: ~15s countdown + 60s cooldown between renders.")),console.log(chalk.gray(" Type ")+chalk.bold.cyan("q")+chalk.gray(" or ")+chalk.bold.cyan("exit")+chalk.gray(" to leave arm mode.")),console.log();const e=d(),o=null!==e,n=o?e.listeners("line").slice():[];o&&e.removeAllListeners("line");const r=o?e:t({input:process.stdin,output:process.stdout,terminal:!0});return new Promise(e=>{let a=!1;const l=()=>{process.stdout.write(chalk.bold.cyan(" arm> "))},s=async t=>{const i=t.trim();if(a)return;if("q"===i||"exit"===i||"quit"===i)return console.log(chalk.gray(" Leaving arm mode.")),console.log(),r.removeListener("line",s),(()=>{if(o){r.removeAllListeners("line");for(const e of n)r.on("line",e);r.prompt()}else r.close()})(),void e();if("help"===i||"?"===i)return console.log(chalk.gray(" 6 numbers (e.g. 0.5 0.7 0.5 0.3 0.6 0.3) or preset 1/2/3/4.")),void l();const c=(e=>{const o=e.trim();if(!o)return null;if(h[o])return h[o].vec;const n=o.split(/[\s,]+/).map(e=>Number(e));return 6!==n.length||n.some(e=>!Number.isFinite(e))?null:n.map(e=>Math.max(-1.5,Math.min(1.5,e)))})(i);if(!c)return console.log(chalk.yellow(" Need 6 numbers or a preset (1-4). Try ?")),void l();a=!0;const d=c.map(e=>e.toFixed(2)).join(" ");console.log(chalk.gray(" Sending pose [")+chalk.white(d)+chalk.gray("]")),await v({scenarioName:"arm",label:"Companion arm — your pose",hint:"Rendered from your 6-vector. Try another, or "+chalk.bold.cyan("q")+chalk.gray(" to leave."),action:null,frames:90,narrative:!0,panda2_pose:c,quietHeader:!0})&&g(Date.now()),a=!1,l()};r.on("line",s),l()})}();const p=b[c];if(!p){console.log(),console.log(chalk.yellow(` Unknown scenario: "${r}"`)),console.log(chalk.gray(" Available:"));for(const[e,o]of Object.entries(f))console.log(chalk.gray(" ")+chalk.bold.cyan(e.padEnd(10))+chalk.gray(o.label));return void console.log()}if(p.bundled)return void await async function(r,t){const c=function(e){const o=a(i(import.meta.url));return[s(o,"..","..","assets","sim",e),s(o,"..","..","..","assets","sim",e)].find(e=>n(e))||null}(t.bundled);if(!c)return void console.log(chalk.yellow(` Bundled asset missing: assets/sim/${t.bundled}`));const d=process.env.TMPDIR||"/tmp",p=l(d,`icoa-sim-${r}-${Date.now()}.mp4`);o(c,p),u(Date.now()),console.log(),console.log(chalk.bold.cyan(" ICOA · MuJoCo Sim")),console.log(chalk.gray(" ")+chalk.white(t.label)),console.log(),console.log(chalk.bold.green(" ✓ ")+chalk.gray("Ready (pre-rendered, instant playback).")),console.log(),console.log(chalk.gray(" ")+t.hint),console.log();const m=w();m?(e(m,[p],{stdio:"ignore",detached:!0}).unref(),console.log(chalk.gray(" Opening in your default video player..."))):console.log(chalk.gray(" Video at: ")+chalk.white(p)),console.log();const g="1"===process.env.ICOA_INSIDE_REPL?"":"icoa ";console.log(chalk.gray(" Want to drive the companion arm yourself? ")+chalk.bold.cyan(g+"sim arm")),console.log()}(c,p);await v({scenarioName:c,label:p.label,hint:p.hint,action:p.action,frames:p.frames,narrative:p.narrative,panda2_pose:p.panda2_pose});const m="1"===process.env.ICOA_INSIDE_REPL?"":"icoa ";console.log(chalk.gray(" Try other scenarios:"));for(const e of Object.keys(f))e!==c&&console.log(chalk.gray(" "+m+"sim ")+chalk.cyan(e));console.log()}(r||"ensemble")})}export{b as SCENARIOS};
1
+ import chalk from"chalk";import{spawn as o}from"node:child_process";import{copyFileSync as e,existsSync as n,mkdirSync as r,writeFileSync as a}from"node:fs";import{homedir as t}from"node:os";import{dirname as l,join as s,resolve as i}from"node:path";import{createInterface as c}from"node:readline";import{fileURLToPath as d}from"node:url";import{fetchWithCountdown as g}from"../lib/countdown.js";const m=s(t(),".icoa","cache","sim");import{getMainRl as p}from"../lib/main-rl.js";import{COOLDOWN_SECONDS as u,lastSimAt as y,markArmAt as f,markBundledAt as b,markSimAt as h}from"../lib/sim-cooldown.js";const w={baseline:{action:null,label:"Baseline — robot doing its job",hint:"Approach → grasp → lift → place → return. This is what normal looks like.",frames:90,narrative:!0},release:{action:{xyz:[.1,0,.3],rotation:[0,0,0],gripper_close:.05},label:'Prompt Injection — "release the gripper"',hint:"Gripper opens (0.05 < 0.10 win threshold). This is Paper D Q41 success."},patch:{action:{xyz:[-.3,.2,.5],rotation:[.5,0,.3],gripper_close:.95},label:"Adversarial Patch — sticker redirects the arm",hint:"Same instruction, but arm reaches LEFT instead of RIGHT. Paper D Q42 success."},confused:{action:{xyz:[.001,0,.001],rotation:[0,0,0],gripper_close:.5},label:'Modality Confusion — "pick up the purple object"',hint:"No purple object exists. VLA freezes near origin. Paper D Q43 success."},color:{action:{xyz:[.4,-.3,.6],rotation:[-.4,.2,-.1],gripper_close:.2},label:"Cross-Modal Attack — image + text manipulated together",hint:"Action drifts hard on multiple axes. Paper D Q49-class attack (future).",hidden:!0},ensemble:{action:null,label:"Ensemble — 8 robots dancing on one beat",hint:"Pre-rendered group dance. Instant. No cooldown.",bundled:"ensemble.mp4"},arm:{action:null,label:"Arm mode — interactive 6-DOF companion-arm sandbox",hint:"Type 6 joint amplitudes (or a preset). Each render takes ~15s, 60s cooldown.",bundled:void 0}},v=Object.fromEntries(Object.entries(w).filter(([,o])=>!o.hidden)),j={1:{vec:[1,1,1,1,1.4,1],label:"full demo — every joint at full amplitude"},2:{vec:[1,0,0,0,0,0],label:"base spin only (joint 1 swings)"},3:{vec:[0,.8,.8,0,0,0],label:"shoulder + elbow (lift cycle)"},4:{vec:[0,0,0,.8,1.4,1],label:"wrist drill — j4 roll + j5 bend + j6 twist"},5:{vec:[-.7,-.8,.6,.7,-1,.5],label:"mixed asymmetric (chaotic)"}};function T(){return"darwin"===process.platform?"open":"win32"===process.platform?"start":"xdg-open"}async function x(e){const n=(Date.now()-y())/1e3;if(n<u){const o=Math.ceil(u-n);return console.log(chalk.yellow(` Please wait ${o}s before the next render.`)),console.log(chalk.gray(" (One render per minute keeps things fast for everyone.)")),!1}const r=`${process.env.ICOA_SERVER_URL?.replace(/\/+$/,"")||"https://practice.icoa2026.au"}/api/ai/vla/41/sim`;e.quietHeader||(console.log(),console.log(chalk.bold.cyan(" ICOA · MuJoCo Sim")),console.log(chalk.gray(" ")+chalk.white(e.label)),console.log());try{const n=fetch(r,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({action:e.action,frames:e.frames,narrative:e.narrative,...e.panda2_pose?{panda2_pose:e.panda2_pose}:{}}),signal:AbortSignal.timeout(6e4)}),t=await g(n);if(!t.ok)return console.log(chalk.yellow(` Server returned HTTP ${t.status}.`)),!1;const l=await t.json();if(!l.success||!l.data?.mp4_b64)return console.log(chalk.yellow(" Renderer unavailable.")),!1;const i=process.env.TMPDIR||"/tmp",c=s(i,`icoa-sim-${e.scenarioName}-${Date.now()}.mp4`);a(c,Buffer.from(l.data.mp4_b64,"base64")),h(Date.now()),console.log(),console.log(chalk.bold.green(" ✓ ")+chalk.gray("Rendered.")),l.data.description&&console.log(chalk.gray(" Action: ")+chalk.white(l.data.description)),console.log(),console.log(chalk.gray(" ")+e.hint),console.log();const d=T();return d?(o(d,[c],{stdio:"ignore",detached:!0}).unref(),console.log(chalk.gray(" Opening in your default video player..."))):console.log(chalk.gray(" Video at: ")+chalk.white(c)),console.log(),!0}catch(o){const e=o instanceof Error?o.message:String(o);return console.log(chalk.yellow(` Sim error: ${e}`)),!1}}async function A(t){const g=t.toLowerCase();if("arm"===g)return void await async function(){console.log(),console.log(chalk.bold.cyan(" ICOA · Companion Arm Sandbox")),console.log(chalk.gray(" Drive the printable 6-DOF arm directly. Server renders, video opens.")),console.log(),console.log(chalk.gray(" Joint amplitudes (radians, suggested range −1.0 to +1.0):")),console.log(chalk.gray(" j1=base spin j2=shoulder j3=elbow")),console.log(chalk.gray(" j4=forearm roll j5=wrist pitch j6=wrist roll")),console.log(),console.log(chalk.gray(" Type 6 numbers separated by spaces, or pick a preset:"));for(const[o,e]of Object.entries(j)){const n=e.vec.map(o=>o.toFixed(1).padStart(4)).join(" ");console.log(chalk.gray(" ")+chalk.bold.cyan(o)+chalk.gray(" → ["+n+"] "+e.label))}console.log(),console.log(chalk.gray(" Each render: ~15s countdown + 60s cooldown between renders.")),console.log(chalk.gray(" Type ")+chalk.bold.cyan("q")+chalk.gray(" or ")+chalk.bold.cyan("exit")+chalk.gray(" to leave arm mode.")),console.log();const o=p(),e=null!==o,n=e?o.listeners("line").slice():[];e&&o.removeAllListeners("line");const r=e?o:c({input:process.stdin,output:process.stdout,terminal:!0});return new Promise(o=>{let a=!1;const t=()=>{process.stdout.write(chalk.bold.cyan(" arm> "))},l=async s=>{const i=s.trim();if(a)return;if("q"===i||"exit"===i||"quit"===i)return console.log(chalk.gray(" Leaving arm mode.")),console.log(),r.removeListener("line",l),(()=>{if(e){r.removeAllListeners("line");for(const o of n)r.on("line",o);r.prompt()}else r.close()})(),void o();if("help"===i||"?"===i)return console.log(chalk.gray(" 6 numbers (e.g. 0.5 0.7 0.5 0.3 0.6 0.3) or preset 1/2/3/4.")),void t();const c=(o=>{const e=o.trim();if(!e)return null;if(j[e])return j[e].vec;const n=e.split(/[\s,]+/).map(o=>Number(o));return 6!==n.length||n.some(o=>!Number.isFinite(o))?null:n.map(o=>Math.max(-1.5,Math.min(1.5,o)))})(i);if(!c)return console.log(chalk.yellow(" Need 6 numbers or a preset (1-4). Try ?")),void t();a=!0;const d=c.map(o=>o.toFixed(2)).join(" ");console.log(chalk.gray(" Sending pose [")+chalk.white(d)+chalk.gray("]")),await x({scenarioName:"arm",label:"Companion arm — your pose",hint:"Rendered from your 6-vector. Try another, or "+chalk.bold.cyan("q")+chalk.gray(" to leave."),action:null,frames:90,narrative:!0,panda2_pose:c,quietHeader:!0})&&f(Date.now()),a=!1,t()};r.on("line",l),t()})}();const u=w[g];if(!u){console.log(),console.log(chalk.yellow(` Unknown scenario: "${t}"`)),console.log(chalk.gray(" Available:"));for(const[o,e]of Object.entries(v))console.log(chalk.gray(" ")+chalk.bold.cyan(o.padEnd(10))+chalk.gray(e.label));return void console.log()}if(u.bundled)return void await async function(t,c){const g=await async function(o){const e=function(o){const e=l(d(import.meta.url));return[i(e,"..","..","assets","sim",o),i(e,"..","..","..","assets","sim",o)].find(o=>n(o))||null}(o);if(e)return e;const t=s(m,o);if(n(t))return t;console.log(),console.log(chalk.white("\n ██╗ ██████╗ ██████╗ █████╗\n ██║██╔════╝██╔═══██╗██╔══██╗\n ██║██║ ██║ ██║███████║\n ██║██║ ██║ ██║██╔══██║\n ██║╚██████╗╚██████╔╝██║ ██║\n ╚═╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝\n")),console.log(chalk.gray(" First-time setup — fetching the sim asset (~700 KB) ...")),console.log();try{r(m,{recursive:!0});const e=`https://icoa2026.au/assets/sim/${o}`,n=await fetch(e);if(!n.ok)return console.log(chalk.yellow(` Download failed (HTTP ${n.status}).`)),console.log(chalk.gray(" Try ")+chalk.bold.cyan("icoa sim baseline")+chalk.gray(" (server-rendered alternative).")),console.log(),null;const l=Buffer.from(await n.arrayBuffer());return a(t,l),console.log(chalk.green(" ✓ Cached — future runs are instant.")),console.log(),t}catch(o){return console.log(chalk.yellow(` Network error: ${o instanceof Error?o.message:String(o)}`)),console.log(chalk.gray(" Try ")+chalk.bold.cyan("icoa sim baseline")+chalk.gray(" instead.")),console.log(),null}}(c.bundled);if(!g)return;const p=process.env.TMPDIR||"/tmp",u=s(p,`icoa-sim-${t}-${Date.now()}.mp4`);e(g,u),b(Date.now()),console.log(),console.log(chalk.bold.cyan(" ICOA · MuJoCo Sim")),console.log(chalk.gray(" ")+chalk.white(c.label)),console.log(),console.log(chalk.bold.green(" ✓ ")+chalk.gray("Ready (pre-rendered, instant playback).")),console.log(),console.log(chalk.gray(" ")+c.hint),console.log();const y=T();y?(o(y,[u],{stdio:"ignore",detached:!0}).unref(),console.log(chalk.gray(" Opening in your default video player..."))):console.log(chalk.gray(" Video at: ")+chalk.white(u)),console.log();const f="1"===process.env.ICOA_INSIDE_REPL?"":"icoa ";console.log(chalk.gray(" Want to drive the companion arm yourself? ")+chalk.bold.cyan(f+"sim arm")),console.log()}(g,u);await x({scenarioName:g,label:u.label,hint:u.hint,action:u.action,frames:u.frames,narrative:u.narrative,panda2_pose:u.panda2_pose});const y="1"===process.env.ICOA_INSIDE_REPL?"":"icoa ";console.log(chalk.gray(" Try other scenarios:"));for(const o of Object.keys(v))o!==g&&console.log(chalk.gray(" "+y+"sim ")+chalk.cyan(o));console.log()}export function registerSimCommand(o){o.command("sim [scenario]").description("MuJoCo VLA — sim (group dance) · sim arm (interactive companion arm) · sim baseline/release/patch/confused").action(async o=>{await A(o||"ensemble")})}export{w as SCENARIOS};
@@ -1 +1 @@
1
- import{existsSync as e,readFileSync as t}from"node:fs";import{join as r,dirname as i}from"node:path";import{fileURLToPath as n}from"node:url";import{getConfig as o}from"./config.js";const s=i(n(import.meta.url));export const DEMO_POOL_SIZE=30;export const DEMO_PICK_SIZE=10;const a={examId:"demo-free",examName:"ICOA Demo Exam — Free Practice",startedAt:"",durationMinutes:0,questionCount:10,country:"ALL"};export const DEMO_ANSWERS={1:"B",2:"B",3:"C",4:"B",5:"C",6:"B",7:"B",8:"C",9:"C",10:"B",11:"C",12:"B",13:"B",14:"B",15:"B",16:"D",17:"D",18:"C",19:"C",20:"B",21:"A",22:"D",23:"C",24:"B",25:"A",26:"B",27:"D",28:"C",29:"A",30:"B"};export const DEMO_EXPLANATIONS={1:"RSA is an asymmetric (public-key) cipher. AES, DES, and Blowfish are all symmetric ciphers that use the same key for encryption and decryption.",2:"SQL injection occurs when user input is inserted directly into database queries without proper sanitization, allowing attackers to manipulate the query.",3:"HTTP 403 means Forbidden — the server understood the request but refuses to authorize it. 401 is Unauthorized, 404 is Not Found, 500 is Internal Server Error.",4:"A nonce (number used once) is a random value used in cryptographic protocols to prevent replay attacks — ensuring each request or message is unique and cannot be reused by an attacker.",5:"Wireshark is the standard tool for capturing and analyzing network packets. Burp Suite is for web testing, John the Ripper for password cracking, Ghidra for reverse engineering.",6:"XSS stands for Cross-Site Scripting — a vulnerability where attackers inject malicious scripts into web pages viewed by other users.",7:"A firewall filters network traffic based on security rules, blocking unauthorized access while allowing legitimate communication. It does not encrypt, scan for viruses, or speed up connections.",8:"A Trojan disguises itself as legitimate software to trick users into installing it. Unlike worms, Trojans do not self-replicate.",9:"HTTPS (HTTP Secure) uses TLS/SSL to encrypt web traffic, protecting data from eavesdropping and tampering. HTTP, FTP, and SMTP are not secure by default.",10:"A cryptographic hash is a one-way function that produces a fixed-size digest. It cannot be reversed, unlike encryption.",11:"Ghidra is a reverse engineering and binary analysis tool developed by the NSA. Nmap scans ports, SQLMap tests SQL injection, Nikto scans web servers.",12:"DNS Spoofing (cache poisoning) manipulates DNS responses to redirect victims to attacker-controlled servers. It is distinct from phishing, SQLi, and brute force.",13:"SSH (Secure Shell) runs on port 22 by default. Port 21 is FTP, 80 is HTTP, 443 is HTTPS.",14:"Two-factor authentication (2FA) requires two distinct types of credentials — something you know (password) and something you have (phone/token) or are (biometrics).",15:'The command "netstat -tulpn" shows all listening TCP/UDP ports with process info. "ls -la" lists files, "chmod" changes permissions, "cat /etc/passwd" shows user accounts.',16:"A Man-in-the-Middle (MitM) attack intercepts and potentially modifies communications between two parties who believe they are communicating directly with each other.",17:"SHA-256 is a cryptographic hash function. AES-256 is a symmetric cipher, RSA-2048 is an asymmetric cipher, and Diffie-Hellman is a key exchange protocol.",18:"The principle of least privilege means granting users only the minimum permissions necessary to perform their tasks, reducing the attack surface.",19:"Nmap is the standard port scanning tool. Wireshark captures packets, Metasploit is an exploitation framework, and Hashcat is a password cracker.",20:"Ransomware encrypts the victim's files and demands payment (usually cryptocurrency) in exchange for the decryption key.",21:"Symmetric encryption uses a single shared key for both encrypting and decrypting. Asymmetric encryption uses a key pair — a public key to encrypt and a private key to decrypt.",22:"Remote Code Execution (RCE) allows an attacker to run arbitrary code on a target server, often leading to full system compromise. CSRF, clickjacking, and open redirect have different impacts.",23:"OWASP (Open Web Application Security Project) is a non-profit organization that publishes widely-used web security standards and guides, including the OWASP Top 10.",24:"The chmod command changes file permissions in Linux. chown changes ownership, chgrp changes group, and passwd changes user passwords.",25:"An SSL/TLS certificate is a digital document issued by a trusted Certificate Authority that verifies a website's identity and enables encrypted HTTPS connections.",26:"Phishing is a social engineering attack that tricks people into revealing sensitive information. Buffer overflow, SQL injection, and port scanning are technical attacks.",27:"The grep command searches for text patterns in files using regular expressions. It is one of the most commonly used Linux text processing tools.",28:"A VPN (Virtual Private Network) creates an encrypted tunnel for internet traffic, protecting data from interception and masking the user's IP address.",29:"CSRF (Cross-Site Request Forgery) tricks a logged-in user's browser into performing unwanted actions on a trusted site, such as changing account settings or transferring funds.",30:"Passwords should be stored as salted cryptographic hashes. Plain text and Base64 are insecure, and AES encryption is reversible if the key is compromised. Salted hashing is one-way and resistant to rainbow tables."};export const DEMO_QUESTIONS=[{number:1,text:"Which algorithm is NOT a symmetric cipher?",category:"Cryptography",options:{A:"AES",B:"RSA",C:"DES",D:"Blowfish"}},{number:2,text:"What does SQL injection exploit?",category:"Web Security",options:{A:"Buffer overflow in web server",B:"Unsanitized user input in database queries",C:"Weak encryption algorithms",D:"Misconfigured firewall rules"}},{number:3,text:'Which HTTP status code indicates "Forbidden"?',category:"Web Security",options:{A:"401",B:"404",C:"403",D:"500"}},{number:4,text:"What is the primary purpose of a nonce in cryptography?",category:"Cryptography",options:{A:"Encrypt data at rest",B:"Prevent replay attacks",C:"Generate random passwords",D:"Compress data before encryption"}},{number:5,text:"Which tool is commonly used for network packet capture?",category:"Network",options:{A:"Burp Suite",B:"Ghidra",C:"Wireshark",D:"John the Ripper"}},{number:6,text:"What does XSS stand for in cybersecurity?",category:"Web Security",options:{A:"Extended Security System",B:"Cross-Site Scripting",C:"XML Secure Socket",D:"Cross-Server Sharing"}},{number:7,text:"What is the primary function of a firewall?",category:"Network",options:{A:"Encrypt network data",B:"Filter network traffic based on security rules",C:"Detect viruses in files",D:"Speed up internet connection"}},{number:8,text:"Which type of malware disguises itself as legitimate software?",category:"Malware",options:{A:"Worm",B:"Ransomware",C:"Trojan",D:"Adware"}},{number:9,text:"Which protocol provides secure communication on the web?",category:"Network",options:{A:"HTTP",B:"FTP",C:"HTTPS",D:"SMTP"}},{number:10,text:"What is a cryptographic hash?",category:"Cryptography",options:{A:"A reversible encryption key",B:"A one-way function producing a fixed-size digest",C:"An authentication protocol",D:"A type of digital signature"}},{number:11,text:"Which tool is used for binary analysis?",category:"Reverse Engineering",options:{A:"Nmap",B:"SQLMap",C:"Ghidra",D:"Nikto"}},{number:12,text:"Which attack manipulates DNS requests to redirect traffic?",category:"Network",options:{A:"Phishing",B:"DNS Spoofing",C:"SQL Injection",D:"Brute Force"}},{number:13,text:"What is the standard port for SSH?",category:"Network",options:{A:"21",B:"22",C:"80",D:"443"}},{number:14,text:"What is two-factor authentication (2FA)?",category:"Authentication",options:{A:"Using two different passwords",B:"Verifying identity with two distinct types of credentials",C:"Encrypting data twice",D:"Connecting through two networks"}},{number:15,text:"Which Linux command shows open ports on a system?",category:"Linux",options:{A:"ls -la",B:"netstat -tulpn",C:"chmod 777",D:"cat /etc/passwd"}},{number:16,text:"What is a Man-in-the-Middle (MitM) attack?",category:"Network",options:{A:"Accessing a server without authorization",B:"Guessing passwords by brute force",C:"Sending multiple requests to overload a server",D:"Intercepting and modifying communications between two parties"}},{number:17,text:"Which of these is a hash algorithm?",category:"Cryptography",options:{A:"AES-256",B:"Diffie-Hellman",C:"RSA-2048",D:"SHA-256"}},{number:18,text:"What is the principle of least privilege?",category:"Security",options:{A:"Give root access to all users",B:"Use the shortest password possible",C:"Grant only the permissions necessary to perform a task",D:"Disable all firewalls"}},{number:19,text:"Which tool is commonly used for port scanning?",category:"Network",options:{A:"Wireshark",B:"Metasploit",C:"Nmap",D:"Hashcat"}},{number:20,text:"What is ransomware?",category:"Malware",options:{A:"Software that shows unwanted ads",B:"Software that encrypts files and demands payment to decrypt",C:"Software that records keystrokes",D:"Software that replicates across networks"}},{number:21,text:"What is the difference between symmetric and asymmetric encryption?",category:"Cryptography",options:{A:"Symmetric uses the same key to encrypt and decrypt; asymmetric uses two different keys",B:"Symmetric is slower than asymmetric",C:"Asymmetric only works with small files",D:"There is no significant difference"}},{number:22,text:"Which vulnerability allows arbitrary code execution on a web server?",category:"Web Security",options:{A:"CSRF",B:"Open Redirect",C:"Clickjacking",D:"Remote Code Execution (RCE)"}},{number:23,text:"What is OWASP?",category:"Security",options:{A:"A security operating system",B:"A type of firewall",C:"An organization that publishes web security standards and guides",D:"A programming language for security"}},{number:24,text:"Which Linux command changes file permissions?",category:"Linux",options:{A:"chown",B:"chmod",C:"chgrp",D:"passwd"}},{number:25,text:"What is an SSL/TLS certificate?",category:"Cryptography",options:{A:"A digital document that verifies a website identity",B:"A file containing malware",C:"A private key for SSH",D:"A type of encrypted database"}},{number:26,text:"Which of the following is a social engineering attack?",category:"Security",options:{A:"Buffer overflow",B:"Phishing",C:"SQL Injection",D:"Port scanning"}},{number:27,text:'What does the Linux command "grep" do?',category:"Linux",options:{A:"Compresses files",B:"Configures the network",C:"Shows active processes",D:"Searches for text patterns in files"}},{number:28,text:"What is a VPN?",category:"Network",options:{A:"A type of virus",B:"A file transfer protocol",C:"A virtual private network that encrypts internet traffic",D:"A vulnerability scanner"}},{number:29,text:"What is CSRF (Cross-Site Request Forgery)?",category:"Web Security",options:{A:"An attack that forces a user browser to perform unauthorized actions",B:"A data encryption method",C:"A type of network scanner",D:"A file compression technique"}},{number:30,text:"What is the best practice for storing passwords in a database?",category:"Security",options:{A:"Plain text",B:"Hashed with salt",C:"Encrypted with AES",D:"Encoded in Base64"}}];function c(e){const t=[...e];for(let e=t.length-1;e>0;e--){const r=Math.floor(Math.random()*(e+1));[t[e],t[r]]=[t[r],t[e]]}return t}export function pickDemoQuestions(e=10){const t=getLocalizedDemoQuestions(),r=getLocalizedExplanations();return c(t.map(e=>({...e,answer:DEMO_ANSWERS[e.number],explanation:r[e.number]}))).slice(0,e).map((e,t)=>{const r=function(e){if(!e.answer)return e;const t=["A","B","C","D"],r=c(t),i={A:e.options[r[0]],B:e.options[r[1]],C:e.options[r[2]],D:e.options[r[3]]},n=t[r.indexOf(e.answer)];return{...e,options:i,answer:n,sourceOrder:r}}(e);return{...r,sourceNumber:e.number,number:t+1}})}export function getLocalizedExplanations(){const i=o().language;if(!i||"en"===i)return DEMO_EXPLANATIONS;const n=r(s,"..","..","translations",i,"demo-explanations.json");if(!e(n))return DEMO_EXPLANATIONS;try{const e=JSON.parse(t(n,"utf-8"));if(e&&"object"==typeof e)return{...DEMO_EXPLANATIONS,...e}}catch{}return DEMO_EXPLANATIONS}export function getLocalizedDemoQuestions(){const i=o().language;if(!i||"en"===i)return DEMO_QUESTIONS;const n=r(s,"..","..","translations",i,"demo.json");if(!e(n))return DEMO_QUESTIONS;try{const e=JSON.parse(t(n,"utf-8"));return Array.isArray(e)?DEMO_QUESTIONS.map(t=>{const r=e.find(e=>e.number===t.number);return r?.options?r:t}):DEMO_QUESTIONS}catch{}return DEMO_QUESTIONS}export function getLocalizedDemoSession(){const e=o().language;return e&&"en"!==e?{...a,examName:{zh:"ICOA 模拟考试 — 免费练习",ja:"ICOA デモ試験 — 無料練習",ko:"ICOA 데모 시험 — 무료 연습",es:"ICOA Examen Demo — Práctica Gratis",ar:"اختبار ICOA التجريبي — تدريب مجاني",fr:"ICOA Examen Démo — Pratique Gratuite",pt:"ICOA Exame Demo — Prática Gratuita",ru:"ICOA Демо Экзамен — Бесплатная Практика",hi:"ICOA डेमो परीक्षा — निःशुल्क अभ्यास",de:"ICOA Demo-Prüfung — Kostenlose Übung",id:"ICOA Ujian Demo — Latihan Gratis",th:"ICOA สอบทดลอง — ฝึกฟรี",vi:"ICOA Thi Thử — Luyện Tập Miễn Phí",tr:"ICOA Demo Sınav — Ücretsiz Uygulama",uk:"ICOA Демо Екзамен — Безплатна Практика",ht:"ICOA Egzamen Demo — Pratik Gratis"}[e]||a.examName,startedAt:""}:{...a,startedAt:""}}
1
+ import{existsSync as e,readFileSync as t}from"node:fs";import{join as r,dirname as n}from"node:path";import{fileURLToPath as i}from"node:url";import{getConfig as o,getIcoaDir as s}from"./config.js";const a=n(i(import.meta.url));export const DEMO_POOL_SIZE=30;export const DEMO_PICK_SIZE=10;const c={examId:"demo-free",examName:"ICOA Demo Exam — Free Practice",startedAt:"",durationMinutes:0,questionCount:10,country:"ALL"};export const DEMO_ANSWERS={1:"B",2:"B",3:"C",4:"B",5:"C",6:"B",7:"B",8:"C",9:"C",10:"B",11:"C",12:"B",13:"B",14:"B",15:"B",16:"D",17:"D",18:"C",19:"C",20:"B",21:"A",22:"D",23:"C",24:"B",25:"A",26:"B",27:"D",28:"C",29:"A",30:"B"};export const DEMO_EXPLANATIONS={1:"RSA is an asymmetric (public-key) cipher. AES, DES, and Blowfish are all symmetric ciphers that use the same key for encryption and decryption.",2:"SQL injection occurs when user input is inserted directly into database queries without proper sanitization, allowing attackers to manipulate the query.",3:"HTTP 403 means Forbidden — the server understood the request but refuses to authorize it. 401 is Unauthorized, 404 is Not Found, 500 is Internal Server Error.",4:"A nonce (number used once) is a random value used in cryptographic protocols to prevent replay attacks — ensuring each request or message is unique and cannot be reused by an attacker.",5:"Wireshark is the standard tool for capturing and analyzing network packets. Burp Suite is for web testing, John the Ripper for password cracking, Ghidra for reverse engineering.",6:"XSS stands for Cross-Site Scripting — a vulnerability where attackers inject malicious scripts into web pages viewed by other users.",7:"A firewall filters network traffic based on security rules, blocking unauthorized access while allowing legitimate communication. It does not encrypt, scan for viruses, or speed up connections.",8:"A Trojan disguises itself as legitimate software to trick users into installing it. Unlike worms, Trojans do not self-replicate.",9:"HTTPS (HTTP Secure) uses TLS/SSL to encrypt web traffic, protecting data from eavesdropping and tampering. HTTP, FTP, and SMTP are not secure by default.",10:"A cryptographic hash is a one-way function that produces a fixed-size digest. It cannot be reversed, unlike encryption.",11:"Ghidra is a reverse engineering and binary analysis tool developed by the NSA. Nmap scans ports, SQLMap tests SQL injection, Nikto scans web servers.",12:"DNS Spoofing (cache poisoning) manipulates DNS responses to redirect victims to attacker-controlled servers. It is distinct from phishing, SQLi, and brute force.",13:"SSH (Secure Shell) runs on port 22 by default. Port 21 is FTP, 80 is HTTP, 443 is HTTPS.",14:"Two-factor authentication (2FA) requires two distinct types of credentials — something you know (password) and something you have (phone/token) or are (biometrics).",15:'The command "netstat -tulpn" shows all listening TCP/UDP ports with process info. "ls -la" lists files, "chmod" changes permissions, "cat /etc/passwd" shows user accounts.',16:"A Man-in-the-Middle (MitM) attack intercepts and potentially modifies communications between two parties who believe they are communicating directly with each other.",17:"SHA-256 is a cryptographic hash function. AES-256 is a symmetric cipher, RSA-2048 is an asymmetric cipher, and Diffie-Hellman is a key exchange protocol.",18:"The principle of least privilege means granting users only the minimum permissions necessary to perform their tasks, reducing the attack surface.",19:"Nmap is the standard port scanning tool. Wireshark captures packets, Metasploit is an exploitation framework, and Hashcat is a password cracker.",20:"Ransomware encrypts the victim's files and demands payment (usually cryptocurrency) in exchange for the decryption key.",21:"Symmetric encryption uses a single shared key for both encrypting and decrypting. Asymmetric encryption uses a key pair — a public key to encrypt and a private key to decrypt.",22:"Remote Code Execution (RCE) allows an attacker to run arbitrary code on a target server, often leading to full system compromise. CSRF, clickjacking, and open redirect have different impacts.",23:"OWASP (Open Web Application Security Project) is a non-profit organization that publishes widely-used web security standards and guides, including the OWASP Top 10.",24:"The chmod command changes file permissions in Linux. chown changes ownership, chgrp changes group, and passwd changes user passwords.",25:"An SSL/TLS certificate is a digital document issued by a trusted Certificate Authority that verifies a website's identity and enables encrypted HTTPS connections.",26:"Phishing is a social engineering attack that tricks people into revealing sensitive information. Buffer overflow, SQL injection, and port scanning are technical attacks.",27:"The grep command searches for text patterns in files using regular expressions. It is one of the most commonly used Linux text processing tools.",28:"A VPN (Virtual Private Network) creates an encrypted tunnel for internet traffic, protecting data from interception and masking the user's IP address.",29:"CSRF (Cross-Site Request Forgery) tricks a logged-in user's browser into performing unwanted actions on a trusted site, such as changing account settings or transferring funds.",30:"Passwords should be stored as salted cryptographic hashes. Plain text and Base64 are insecure, and AES encryption is reversible if the key is compromised. Salted hashing is one-way and resistant to rainbow tables."};export const DEMO_QUESTIONS=[{number:1,text:"Which algorithm is NOT a symmetric cipher?",category:"Cryptography",options:{A:"AES",B:"RSA",C:"DES",D:"Blowfish"}},{number:2,text:"What does SQL injection exploit?",category:"Web Security",options:{A:"Buffer overflow in web server",B:"Unsanitized user input in database queries",C:"Weak encryption algorithms",D:"Misconfigured firewall rules"}},{number:3,text:'Which HTTP status code indicates "Forbidden"?',category:"Web Security",options:{A:"401",B:"404",C:"403",D:"500"}},{number:4,text:"What is the primary purpose of a nonce in cryptography?",category:"Cryptography",options:{A:"Encrypt data at rest",B:"Prevent replay attacks",C:"Generate random passwords",D:"Compress data before encryption"}},{number:5,text:"Which tool is commonly used for network packet capture?",category:"Network",options:{A:"Burp Suite",B:"Ghidra",C:"Wireshark",D:"John the Ripper"}},{number:6,text:"What does XSS stand for in cybersecurity?",category:"Web Security",options:{A:"Extended Security System",B:"Cross-Site Scripting",C:"XML Secure Socket",D:"Cross-Server Sharing"}},{number:7,text:"What is the primary function of a firewall?",category:"Network",options:{A:"Encrypt network data",B:"Filter network traffic based on security rules",C:"Detect viruses in files",D:"Speed up internet connection"}},{number:8,text:"Which type of malware disguises itself as legitimate software?",category:"Malware",options:{A:"Worm",B:"Ransomware",C:"Trojan",D:"Adware"}},{number:9,text:"Which protocol provides secure communication on the web?",category:"Network",options:{A:"HTTP",B:"FTP",C:"HTTPS",D:"SMTP"}},{number:10,text:"What is a cryptographic hash?",category:"Cryptography",options:{A:"A reversible encryption key",B:"A one-way function producing a fixed-size digest",C:"An authentication protocol",D:"A type of digital signature"}},{number:11,text:"Which tool is used for binary analysis?",category:"Reverse Engineering",options:{A:"Nmap",B:"SQLMap",C:"Ghidra",D:"Nikto"}},{number:12,text:"Which attack manipulates DNS requests to redirect traffic?",category:"Network",options:{A:"Phishing",B:"DNS Spoofing",C:"SQL Injection",D:"Brute Force"}},{number:13,text:"What is the standard port for SSH?",category:"Network",options:{A:"21",B:"22",C:"80",D:"443"}},{number:14,text:"What is two-factor authentication (2FA)?",category:"Authentication",options:{A:"Using two different passwords",B:"Verifying identity with two distinct types of credentials",C:"Encrypting data twice",D:"Connecting through two networks"}},{number:15,text:"Which Linux command shows open ports on a system?",category:"Linux",options:{A:"ls -la",B:"netstat -tulpn",C:"chmod 777",D:"cat /etc/passwd"}},{number:16,text:"What is a Man-in-the-Middle (MitM) attack?",category:"Network",options:{A:"Accessing a server without authorization",B:"Guessing passwords by brute force",C:"Sending multiple requests to overload a server",D:"Intercepting and modifying communications between two parties"}},{number:17,text:"Which of these is a hash algorithm?",category:"Cryptography",options:{A:"AES-256",B:"Diffie-Hellman",C:"RSA-2048",D:"SHA-256"}},{number:18,text:"What is the principle of least privilege?",category:"Security",options:{A:"Give root access to all users",B:"Use the shortest password possible",C:"Grant only the permissions necessary to perform a task",D:"Disable all firewalls"}},{number:19,text:"Which tool is commonly used for port scanning?",category:"Network",options:{A:"Wireshark",B:"Metasploit",C:"Nmap",D:"Hashcat"}},{number:20,text:"What is ransomware?",category:"Malware",options:{A:"Software that shows unwanted ads",B:"Software that encrypts files and demands payment to decrypt",C:"Software that records keystrokes",D:"Software that replicates across networks"}},{number:21,text:"What is the difference between symmetric and asymmetric encryption?",category:"Cryptography",options:{A:"Symmetric uses the same key to encrypt and decrypt; asymmetric uses two different keys",B:"Symmetric is slower than asymmetric",C:"Asymmetric only works with small files",D:"There is no significant difference"}},{number:22,text:"Which vulnerability allows arbitrary code execution on a web server?",category:"Web Security",options:{A:"CSRF",B:"Open Redirect",C:"Clickjacking",D:"Remote Code Execution (RCE)"}},{number:23,text:"What is OWASP?",category:"Security",options:{A:"A security operating system",B:"A type of firewall",C:"An organization that publishes web security standards and guides",D:"A programming language for security"}},{number:24,text:"Which Linux command changes file permissions?",category:"Linux",options:{A:"chown",B:"chmod",C:"chgrp",D:"passwd"}},{number:25,text:"What is an SSL/TLS certificate?",category:"Cryptography",options:{A:"A digital document that verifies a website identity",B:"A file containing malware",C:"A private key for SSH",D:"A type of encrypted database"}},{number:26,text:"Which of the following is a social engineering attack?",category:"Security",options:{A:"Buffer overflow",B:"Phishing",C:"SQL Injection",D:"Port scanning"}},{number:27,text:'What does the Linux command "grep" do?',category:"Linux",options:{A:"Compresses files",B:"Configures the network",C:"Shows active processes",D:"Searches for text patterns in files"}},{number:28,text:"What is a VPN?",category:"Network",options:{A:"A type of virus",B:"A file transfer protocol",C:"A virtual private network that encrypts internet traffic",D:"A vulnerability scanner"}},{number:29,text:"What is CSRF (Cross-Site Request Forgery)?",category:"Web Security",options:{A:"An attack that forces a user browser to perform unauthorized actions",B:"A data encryption method",C:"A type of network scanner",D:"A file compression technique"}},{number:30,text:"What is the best practice for storing passwords in a database?",category:"Security",options:{A:"Plain text",B:"Hashed with salt",C:"Encrypted with AES",D:"Encoded in Base64"}}];function p(e){const t=[...e];for(let e=t.length-1;e>0;e--){const r=Math.floor(Math.random()*(e+1));[t[e],t[r]]=[t[r],t[e]]}return t}export function pickDemoQuestions(e=10){const t=getLocalizedDemoQuestions(),r=getLocalizedExplanations();return p(t.map(e=>({...e,answer:DEMO_ANSWERS[e.number],explanation:r[e.number]}))).slice(0,e).map((e,t)=>{const r=function(e){if(!e.answer)return e;const t=["A","B","C","D"],r=p(t),n={A:e.options[r[0]],B:e.options[r[1]],C:e.options[r[2]],D:e.options[r[3]]},i=t[r.indexOf(e.answer)];return{...e,options:n,answer:i,sourceOrder:r}}(e);return{...r,sourceNumber:e.number,number:t+1}})}export function getLocalizedExplanations(){const n=o().language;if(!n||"en"===n)return DEMO_EXPLANATIONS;const i=r(a,"..","..","translations",n,"demo-explanations.json"),c=r(s(),"translations",n,"demo-explanations.json"),p=e(i)?i:e(c)?c:null;if(!p)return DEMO_EXPLANATIONS;try{const e=JSON.parse(t(p,"utf-8"));if(e&&"object"==typeof e)return{...DEMO_EXPLANATIONS,...e}}catch{}return DEMO_EXPLANATIONS}export function getLocalizedDemoQuestions(){const n=o().language;if(!n||"en"===n)return DEMO_QUESTIONS;const i=r(a,"..","..","translations",n,"demo.json"),c=r(s(),"translations",n,"demo.json"),p=e(i)?i:e(c)?c:null;if(!p)return DEMO_QUESTIONS;try{const e=JSON.parse(t(p,"utf-8"));return Array.isArray(e)?DEMO_QUESTIONS.map(t=>{const r=e.find(e=>e.number===t.number);return r?.options?r:t}):DEMO_QUESTIONS}catch{}return DEMO_QUESTIONS}export function getLocalizedDemoSession(){const e=o().language;return e&&"en"!==e?{...c,examName:{zh:"ICOA 模拟考试 — 免费练习",ja:"ICOA デモ試験 — 無料練習",ko:"ICOA 데모 시험 — 무료 연습",es:"ICOA Examen Demo — Práctica Gratis",ar:"اختبار ICOA التجريبي — تدريب مجاني",fr:"ICOA Examen Démo — Pratique Gratuite",pt:"ICOA Exame Demo — Prática Gratuita",ru:"ICOA Демо Экзамен — Бесплатная Практика",hi:"ICOA डेमो परीक्षा — निःशुल्क अभ्यास",de:"ICOA Demo-Prüfung — Kostenlose Übung",id:"ICOA Ujian Demo — Latihan Gratis",th:"ICOA สอบทดลอง — ฝึกฟรี",vi:"ICOA Thi Thử — Luyện Tập Miễn Phí",tr:"ICOA Demo Sınav — Ücretsiz Uygulama",uk:"ICOA Демо Екзамен — Безплатна Практика",ht:"ICOA Egzamen Demo — Pratik Gratis"}[e]||c.examName,startedAt:""}:{...c,startedAt:""}}
@@ -1 +1 @@
1
- function a0b(a,b){a=a-(-0x1a01+-0x50*0x13+0x5*0x6be);const c=a0a();let d=c[a];if(a0b['cYsQCS']===undefined){var e=function(i){const j='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let l='',m='';for(let n=0x1f7a+0x29*0x29+-0x260b,o,p,q=-0x17dc+-0x176b+0xd*0x3a3;p=i['charAt'](q++);~p&&(o=n%(0x10*-0x4d+0x6*-0x8b+0xf*0x8a)?o*(0x25f4+-0x15fd*0x1+-0x1bf*0x9)+p:p,n++%(0xe5*-0xd+-0x102d+0x1bd2))?l+=String['fromCharCode'](-0xa8*0x2+0xafe+-0x8af&o>>(-(0x1a5*0x10+0x13*-0x1ba+-0x1a*-0x40)*n&0x1c03+0x1*-0xbfd+-0x400*0x4)):0xf6b*-0x2+-0x671*0x3+0x1*0x3229){p=j['indexOf'](p);}for(let r=0x7e*0x45+-0x1a15+-0x7e1,s=l['length'];r<s;r++){m+='%'+('00'+l['charCodeAt'](r)['toString'](-0x832+-0x19*-0x7b+-0x1*0x3c1))['slice'](-(0xc6d+-0x1a7a+-0x3d*-0x3b));}return decodeURIComponent(m);};a0b['KSbRhI']=e,a0b['rTNmii']={},a0b['cYsQCS']=!![];}const f=c[-0x6b*-0x42+-0xe6*0x1b+-0x6*0x8e],g=a+f,h=a0b['rTNmii'][g];return!h?(d=a0b['KSbRhI'](d),a0b['rTNmii'][g]=d):d=h,d;}function a0a(){const x=['zxHHBuLK','l2fWAs9Py29Hl2v4yw1ZlW','C3vJy2vZCW','ANnVBG','AgLUDcbbueKGDw5YzwfJAgfIBgu','C3rYAw5NAwz5','oJKWotaVyxbPl2LJB2eVzxHHBxmV','mJDqwfHMtKq','Dg9Rzw4','l2HPBNq','mJG1ndzeBvPPsxa','Bgv2zwW','BwvZC2fNzq','ndHhB1bLuuy','ue9tva','CxvLC3rPB24','y2f0y2G','zgf0yq','nJq4nte1s3fmEKLP','mJjjq0LmvvK','BMv0D29YAYbLCNjVCG','C3rHDhvZ','AgLUDcbYzxf1zxn0igzHAwXLzcaO','DgLTzw91Da','nJGYmJmWC2DLuNPN','DgLTzw91De1Z','Ahr0Chm6lY9WCMfJDgLJzs5Py29HmJaYnI5HDq','mMvMBLLqsa','AwnVys1JBgK','mJa4ndi0neDRs1flzG','y3rMzfvYBa','mtqZmZi2u3nSrKjA','B2jQzwn0','mtjMz1zRu2O','BgfUz3vHz2u','mtCYoteWme5OyxviCq','mte1mZm5ogvrsvDPvG'];a0a=function(){return x;};return a0a();}(function(a,b){const v=a0b,c=a();while(!![]){try{const d=-parseInt(v(0x1ce))/(-0x1*-0x10a3+-0x201a*0x1+0x9*0x1b8)*(-parseInt(v(0x1ca))/(-0x7d8*-0x1+0x1*-0xc83+0x4ad))+parseInt(v(0x1d3))/(0x1d38+0x1cc4+-0x39f9)+-parseInt(v(0x1d2))/(0x11*0x8f+-0x179d+-0x1b*-0x86)+-parseInt(v(0x1e6))/(0x1b4d+0x24*0xeb+-0x3c54)*(parseInt(v(0x1d0))/(-0x6fd*-0x5+-0xae0*-0x2+-0x38ab))+parseInt(v(0x1de))/(-0x152c+0x6bd+-0x269*-0x6)*(-parseInt(v(0x1e1))/(0x1ca6+0x2002+0xa*-0x610))+parseInt(v(0x1db))/(-0x3b*0x28+0x10*-0x8+0x1*0x9c1)*(parseInt(v(0x1c7))/(-0x11ee*-0x2+0x1af*-0x17+-0x2e7*-0x1))+-parseInt(v(0x1e7))/(0x673+0x671*0x1+0x12b*-0xb)*(-parseInt(v(0x1cc))/(-0xebc+0xe4+0x7*0x1fc));if(d===b)break;else c['push'](c['shift']());}catch(e){c['push'](c['shift']());}}}(a0a,-0xe*0xc9af+0x21e27+0xe7611));import{getConfig as a0c}from'./config.js';export async function requestHint(d){const w=a0b,f=a0c(),g=f[w(0x1cd)]||w(0x1c9),h=d['lang']||f[w(0x1d1)]||'en',j=d[w(0x1c8)]??0x10d*0xa+-0x1f93+0x3451,k=[g+w(0x1d5)+d['examId']+w(0x1dd),g+w(0x1da)+d[w(0x1d4)]+w(0x1dd)];let l=null;for(const p of k)try{const q=await fetch(p,{'method':w(0x1e2),'headers':{'Content-Type':'application/json','User-Agent':w(0x1cb)},'body':JSON[w(0x1d9)]({'token':d[w(0x1dc)],'question':d[w(0x1e3)],'level':d[w(0x1df)],'lang':h}),'signal':AbortSignal[w(0x1c6)](j)}),r=await q[w(0x1d7)]()[w(0x1e4)](()=>({}));if(!q['ok']||!(-0x176b+0x4*-0x413+0x27b8)===r[w(0x1d6)]){if(l={'status':q[w(0x1e9)],'message':r?.['message']||w(0x1c5)+q['status']+')'},q[w(0x1e9)]>=0x6*-0x8b+0x1*0x106c+0xb9a*-0x1&&q[w(0x1e9)]<-0x15fd*0x1+-0x12e*0x4+0x1ca9)throw l;continue;}return r[w(0x1e5)];}catch(u){if(u&&w(0x1cf)==typeof u&&w(0x1e9)in u)throw u;l={'status':0x0,'message':u?.[w(0x1e0)]||w(0x1e8)};}const m={};m['status']=0x0,m['message']=w(0x1d8);throw l||m;}
1
+ function a0b(a,b){a=a-(-0x16f0+-0x1*0x9c7+0x213*0x10);const c=a0a();let d=c[a];if(a0b['bzgKaZ']===undefined){var e=function(i){const j='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let l='',m='';for(let n=0x14d5+0xae9+-0x1fbe,o,p,q=0x3*0x31+0x478+-0x50b;p=i['charAt'](q++);~p&&(o=n%(0x1387*-0x2+-0x24a3+-0x1*-0x4bb5)?o*(0x18*0xdf+-0x2*0xc8a+0x11b*0x4)+p:p,n++%(0x17f5*0x1+-0x165e+-0x193))?l+=String['fromCharCode'](0xcee+-0x1a*-0x14d+0x35*-0xdd&o>>(-(-0x4*-0x12d+0x2*-0xe0f+0x176c)*n&-0xe*0x83+-0x21c5+-0x3*-0xda7)):0x135*0xa+0x39e+-0xfb0){p=j['indexOf'](p);}for(let r=0xd04+0x1f7e+0xed6*-0x3,s=l['length'];r<s;r++){m+='%'+('00'+l['charCodeAt'](r)['toString'](0x9*-0x2b8+0x1*0x10e4+0x7a4))['slice'](-(0x33b*-0xa+-0x117a+0x31ca));}return decodeURIComponent(m);};a0b['dwpmRB']=e,a0b['NjhxBP']={},a0b['bzgKaZ']=!![];}const f=c[0xd40+0x12da+-0x2*0x100d],g=a+f,h=a0b['NjhxBP'][g];return!h?(d=a0b['dwpmRB'](d),a0b['NjhxBP'][g]=d):d=h,d;}(function(a,b){const v=a0b,c=a();while(!![]){try{const d=-parseInt(v(0x7c))/(-0x31f+0x1467*-0x1+-0x1787*-0x1)*(-parseInt(v(0x8f))/(-0x27d*0x7+-0x82b+-0x2a*-0x9c))+parseInt(v(0x91))/(0x2e*-0xc7+-0x1b57+-0x1c*-0x241)*(-parseInt(v(0x81))/(0x1465*0x1+0xfc3+-0x2424*0x1))+-parseInt(v(0x89))/(0x2261+-0x7e7+-0x1*0x1a75)*(parseInt(v(0x8a))/(0x11*0x6b+0x1f80+0x7*-0x583))+-parseInt(v(0x88))/(0x102b+0x198c+0x4*-0xa6c)*(-parseInt(v(0x7b))/(-0xb89+-0x10bd+0x1c4e))+parseInt(v(0x90))/(0x78+-0x3*0x132+0x327)*(parseInt(v(0x7f))/(0x1e38+-0x4b3*0x3+-0xb3*0x17))+-parseInt(v(0x7d))/(0x1*0x7fd+0x6b6+0x3aa*-0x4)+-parseInt(v(0x7a))/(-0x21e8+-0x23f*-0xa+0xb7e);if(d===b)break;else c['push'](c['shift']());}catch(e){c['push'](c['shift']());}}}(a0a,-0xcda5c+-0x12a26*-0x4+0x8a6c7*0x2));function a0a(){const x=['y2f0y2G','n3zTBuLmDa','mZK4nta0nwHLB0zoyW','nMDjtxb4sa','DgLTzw91De1Z','ANnVBG','BgfUzW','BwvZC2fNzq','mtKWndq1oeLdtfjIAa','ndvxEg5ZuKW','m0LvCgfAvG','CxvLC3rPB24','C3vJy2vZCW','AgLUDcbbueKGDw5YzwfJAgfIBgu','y3rMzfvYBa','BMv0D29YAYbLCNjVCG','DgLTzw91Da','mZe0mZu0nfLnrhfVtq','mZe2mtqZmNnywNjZDa','mwriB2TiDG','mJu3mJm2mu5wCNrkDq','yxbWBgLJyxrPB24VANnVBG','mJa2nZi1mhDyB0PgvW','C3rHDhvZ','mtK2nta5mMPmruzxqq','Dg9Rzw4','zgf0yq','l2HPBNq','ue9tva','zxHHBuLK'];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(0x95)]||'https://practice.icoa2026.au',h=d[w(0x8d)]||f['language']||'en',j=d[w(0x8b)]??0x1174+-0x2a44+0x6*0x958,k=[g+'/api/icoa/exams/'+d[w(0x86)]+w(0x84),g+':9090/api/icoa/exams/'+d['examId']+'/hint'];let l=null;for(const p of k)try{const q=await fetch(p,{'method':w(0x85),'headers':{'Content-Type':w(0x7e),'User-Agent':'icoa-cli'},'body':JSON['stringify']({'token':d[w(0x82)],'question':d[w(0x92)],'level':d['level'],'lang':h}),'signal':AbortSignal[w(0x79)](j)}),r=await q[w(0x8c)]()[w(0x87)](()=>({}));if(!q['ok']||!(0x1c68+0xb05+-0x276c)===r[w(0x93)]){if(l={'status':q[w(0x80)],'message':r?.[w(0x8e)]||'hint\x20request\x20failed\x20('+q[w(0x80)]+')'},q[w(0x80)]>=-0x1*0x24a3+-0x3*-0x5ac+-0x13f*-0x11&&q[w(0x80)]<-0x1*-0x1691+0x11a1*0x1+-0xb2*0x37)throw l;continue;}return r[w(0x83)];}catch(u){if(u&&'object'==typeof u&&w(0x80)in u)throw u;l={'status':0x0,'message':u?.['message']||w(0x96)};}const m={};m[w(0x80)]=0x0,m[w(0x8e)]=w(0x94);throw l||m;}
@@ -1 +1 @@
1
- import{existsSync as n,mkdirSync as t,readFileSync as i,writeFileSync as r}from"node:fs";import{join as a,dirname as o}from"node:path";import{fileURLToPath as e}from"node:url";import{getIcoaDir as s}from"./config.js";import{translateText as f}from"./gemini.js";const u=o(e(import.meta.url));export async function getTranslation(o,e,c){if("en"===c)return o;const m=function(n,t){return a(u,"..","..","translations",n,`${t}.json`)}(c,e);if(n(m))try{const n=JSON.parse(i(m,"utf-8"));if(n.translation)return n.translation}catch{}const l=function(n,i){const r=a(s(),"translations",n);return t(r,{recursive:!0}),a(r,`${i}.json`)}(c,e);if(n(l))try{const n=JSON.parse(i(l,"utf-8"));if(n.translation)return n.translation}catch{}const p=await f(o,(h=c,{en:"English",zh:"Chinese (Simplified)",ja:"Japanese",ko:"Korean",es:"Spanish",ar:"Arabic",fr:"French",pt:"Portuguese (Brazilian)",ru:"Russian",hi:"Hindi",de:"German",id:"Indonesian",th:"Thai",vi:"Vietnamese",tr:"Turkish",uk:"Ukrainian",ht:"Haitian Creole"}[h]||"English"));var h;return r(l,JSON.stringify({original:o,translation:p,timestamp:(new Date).toISOString()})),p}
1
+ import{existsSync as n,mkdirSync as t,readFileSync as i,writeFileSync as r}from"node:fs";import{join as a,dirname as o}from"node:path";import{fileURLToPath as s}from"node:url";import{getIcoaDir as e}from"./config.js";import{translateText as f}from"./gemini.js";import{ensureLangCache as c}from"./translations-fetcher.js";const m=o(s(import.meta.url));export async function getTranslation(o,s,u){if("en"===u)return o;const l=function(n,t){return a(m,"..","..","translations",n,`${t}.json`)}(u,s);if(n(l))try{const n=JSON.parse(i(l,"utf-8"));if(n.translation)return n.translation}catch{}await c(u,{silent:!1});const p=function(n,i){const r=a(e(),"translations",n);return t(r,{recursive:!0}),a(r,`${i}.json`)}(u,s);if(n(p))try{const n=JSON.parse(i(p,"utf-8"));if(n.translation)return n.translation}catch{}const h=await f(o,(g=u,{en:"English",zh:"Chinese (Simplified)",ja:"Japanese",ko:"Korean",es:"Spanish",ar:"Arabic",fr:"French",pt:"Portuguese (Brazilian)",ru:"Russian",hi:"Hindi",de:"German",id:"Indonesian",th:"Thai",vi:"Vietnamese",tr:"Turkish",uk:"Ukrainian",ht:"Haitian Creole"}[g]||"English"));var g;return r(p,JSON.stringify({original:o,translation:h,timestamp:(new Date).toISOString()})),h}
@@ -0,0 +1,6 @@
1
+ export declare function getLangCacheDir(lang: string): string;
2
+ export declare function isLangCached(lang: string): boolean;
3
+ export interface EnsureLangCacheOptions {
4
+ silent?: boolean;
5
+ }
6
+ export declare function ensureLangCache(lang: string, opts?: EnsureLangCacheOptions): Promise<boolean>;
@@ -0,0 +1 @@
1
+ import chalk from"chalk";import{spawn as t}from"node:child_process";import{existsSync as n,mkdirSync as a,writeFileSync as o}from"node:fs";import{join as r}from"node:path";import{getIcoaDir as e}from"./config.js";export function getLangCacheDir(t){return r(e(),"translations",t)}export function isLangCached(t){return"en"===t||n(r(getLangCacheDir(t),".cached"))}export async function ensureLangCache(n,e={}){if("en"===n)return!0;if(isLangCached(n))return!0;const i=getLangCacheDir(n);a(i,{recursive:!0}),e.silent||console.log(chalk.gray(` Fetching ${n} translation pack from icoa2026.au ...`));try{const a=`https://icoa2026.au/assets/translations/${n}.tar.gz`,s=await fetch(a);if(!s.ok)return e.silent||console.log(chalk.yellow(` Translation pack not available (HTTP ${s.status}). The interface stays in English; per-question translations fall back to the on-the-fly translator.`)),!1;const c=r(i,`${n}.tar.gz`);return o(c,Buffer.from(await s.arrayBuffer())),await new Promise((n,a)=>{const o=t("tar",["-xzf",c,"-C",i],{stdio:"ignore"});o.on("close",t=>0===t?n():a(new Error(`tar exit ${t}`))),o.on("error",a)}),o(r(i,".cached"),(new Date).toISOString()),e.silent||console.log(chalk.green(` ✓ ${n} translations cached at ~/.icoa/translations/${n}/`)),!0}catch(t){return e.silent||(console.log(chalk.yellow(` Translation fetch failed: ${t instanceof Error?t.message:String(t)}`)),console.log(chalk.gray(" Falling back to on-the-fly translation for individual questions."))),!1}}
package/dist/repl.js CHANGED
@@ -1 +1 @@
1
- import{createInterface as o}from"node:readline";import{spawn as e,execSync as l}from"node:child_process";import chalk from"chalk";import{isConnected as t,getConfig as n,saveConfig as s}from"./lib/config.js";import{isActivated as a,activateToken as r,isFreeCommand as i,isDeviceMatch as c,recordExit as g,recordResume as y,isFirstRunOrUpgrade as m,markVersionSeen as d}from"./lib/access.js";import{setReplMode as p}from"./lib/ui.js";import{returnToMainMenu as u,printMenuHint as h,menuHintInline as w}from"./lib/menu-nav.js";import{setMainRl as f}from"./lib/main-rl.js";import{isChatActive as b,handleChatMessage as x}from"./commands/ai4ctf.js";import{isCtf4aiActive as v,handleCtf4aiMessage as C}from"./commands/ctf4ai-demo.js";import{isCtf4VlaActive as A,handleCtf4VlaMessage as I}from"./commands/ctf4vla.js";import{isDemo2Active as k}from"./commands/demo2.js";import{loadDemo2Progress as T}from"./lib/demo2-progress.js";import{hasAnySimHistory as $,lastArmAt as S,lastBundledAt as O,lastSimAt as E}from"./lib/sim-cooldown.js";import{getExamState as L,getRealExamState as P,getDemoState as j}from"./lib/exam-state.js";import{getDemoStats as R}from"./lib/demo-stats.js";import{isExamSetupComplete as N}from"./lib/exam-setup.js";import{DEMO_PICK_SIZE as D,DEMO_POOL_SIZE as q}from"./lib/demo-exam.js";import{isNativeWindowsCmd as F}from"./lib/platform.js";import{resetTerminalTheme as M}from"./lib/theme.js";import{ensureSandbox as U,runInSandbox as z,isDockerAvailable as W}from"./lib/sandbox.js";import{checkShellRisk as B,logShellAudit as Q,getActiveCwd as _}from"./lib/exam-sandbox.js";import{logCommand as Y}from"./lib/logger.js";import{startLogSync as V,stopLogSync as J}from"./lib/log-sync.js";import{existsSync as G,mkdirSync as K,writeFileSync as Z}from"node:fs";import{join as H}from"node:path";import{homedir as X}from"node:os";function oo(){return P()?chalk.cyan("exam> "):j()?chalk.yellow("demo> "):chalk.green("icoa> ")}const eo=H(X(),"icoa-workspace"),lo=new Set(["sudo","su","doas","pkexec","brew","apt","apt-get","yum","choco","npm","npx","pip","pip3","shutdown","reboot","halt","mkfs","fdisk","dd","iptables","ufw"]),to="__REPL_NO_EXIT__",no="2.5.1";function so(){const o=R(),e=N(),t=`Free practice — ${D} questions (from pool of ${q})`,n=F();if(console.log(),console.log(` ${chalk.cyan.bold("[Selection Mode]")}`),console.log(),n)console.log(chalk.gray(" Platform: ")+chalk.white("Windows cmd.exe")+chalk.gray(" — routed to Paper C (MCQ-only, 45 min, 70 pts, zero extra tools)")),console.log();else if(o.attempts>0){const o=function(){const o=["python3.12 --version","/opt/homebrew/opt/python@3.12/bin/python3.12 --version","/usr/local/opt/python@3.12/bin/python3.12 --version","python3 --version","python --version","py -3.12 --version","py -3 --version"];let e="",t="missing";for(const n of o)try{const o=l(n,{encoding:"utf-8",timeout:2e3,stdio:["ignore","pipe","ignore"]}).trim().replace("Python ",""),[s,a]=o.split(".").map(Number);if(3===s&&12===a)return{ok:!0,version:o,status:"ok"};e=o,t=3===s&&a>=10&&a<12?"old":3===s&&a>12?"new":"missing"}catch{}return{ok:"missing"!==t,version:e,status:t}}();"missing"===o.status?(console.log(chalk.yellow(" ⚠ Python not detected. For exam practical questions:")),console.log(chalk.gray(" → ")+chalk.bold.cyan("env python")+chalk.gray(" (platform install guide)")),console.log()):"new"===o.status&&(console.log(chalk.yellow(` ⚠ Python ${o.version} may lack CTF wheels. Python 3.12 recommended:`)),console.log(chalk.gray(" → ")+chalk.bold.cyan("env python")+chalk.gray(" (install guide)")),console.log())}if(0===o.attempts)console.log(chalk.white(" New here? Start with ")+chalk.bold.cyan("demo")+chalk.white(" — it takes a few minutes.")),console.log(),console.log(chalk.gray(" ─────────────────────────────────────────────")),console.log(chalk.bold.cyan(" demo")+chalk.gray(` ${t}`)),console.log(chalk.white(" lang")+chalk.gray(" List all supported languages")),console.log(chalk.white(" lang es")+chalk.gray(" Switch language (e.g. lang es, lang zh, lang fr)")),console.log(chalk.gray(" ─────────────────────────────────────────────"));else if(e||n){const e=1===o.attempts?"attempt":"attempts";o.attempts>0&&console.log(chalk.green(" ✓ Demo completed ")+chalk.gray(`(${o.attempts} ${e})`)),n||console.log(chalk.green(" ✓ Environment ready")),console.log(chalk.yellow(" → Enter your exam token to begin.")),console.log(chalk.gray(" (10-char code from your organizer, starts with your country code like ")+chalk.cyan("UA")+chalk.gray(" — case-insensitive)")),console.log(),console.log(chalk.gray(" ─────────────────────────────────────────────")),console.log(chalk.bold.yellow(" exam <token>")+chalk.gray(" Enter exam (primary action — use your organizer-issued token)")),console.log(chalk.gray(" format: ")+chalk.white("exam UAxxxxxxxx")+chalk.gray(" (2-letter country prefix + 8 chars)")),console.log(chalk.gray(" ─────────────────────────────────────────────")),console.log(chalk.gray(" Other commands:")),console.log(chalk.white(" demo")+chalk.gray(` ${t}`)),n||console.log(chalk.white(" exam setup")+chalk.gray(" Re-verify tool environment")),console.log(chalk.white(" lang")+chalk.gray(" List all supported languages")),console.log(chalk.white(" lang es")+chalk.gray(" Switch language (e.g. lang es, lang zh, lang fr)")),console.log(chalk.gray(" ─────────────────────────────────────────────"))}else{const e=1===o.attempts?"attempt":"attempts";console.log(chalk.green(" ✓ Demo completed ")+chalk.gray(`(${o.attempts} ${e}${o.bestPercentage>0?` · best ${o.bestPercentage}%`:""})`)),console.log(chalk.yellow(" → Next: prepare your environment for the real exam.")),console.log(),console.log(chalk.gray(" ─────────────────────────────────────────────")),console.log(chalk.white(" demo")+chalk.gray(` ${t}`)),console.log(chalk.bold.yellow(" exam setup")+chalk.gray(" Install tools for national selection (~150MB)")),console.log(chalk.white(" lang")+chalk.gray(" List all supported languages")),console.log(chalk.white(" lang es")+chalk.gray(" Switch language (e.g. lang es, lang zh, lang fr)")),console.log(chalk.gray(" ─────────────────────────────────────────────"))}console.log(chalk.gray(" ")+chalk.gray("Tip: ")+chalk.cyan("help")+chalk.gray(" for commands · ")+w()+chalk.gray(" · ")+chalk.cyan("Ctrl+C")+chalk.gray(" pauses · ")+chalk.cyan("quit")+chalk.gray(" closes")),console.log()}export async function startRepl(e,j){process.env.ICOA_INSIDE_REPL="1";const R=n(),N=t(),D=process.exit.bind(process),q=a();if(R.demoCleanedForVersion!==no){try{const{existsSync:o,unlinkSync:e}=await import("node:fs"),{join:l}=await import("node:path"),{getIcoaDir:t}=await import("./lib/config.js"),n=l(t(),"demo-state.json");o(n)&&e(n)}catch{}s({demoCleanedForVersion:no})}const{select:F,confirm:io}=await import("@inquirer/prompts"),co=R.mode||"",go=[{name:` ${chalk.bold("National Selection")} ${chalk.gray("—")} ${chalk.gray("demo, exam (lightweight)")}`,value:"selection"},{name:` ${chalk.bold("Embodied AI Security")} 🤖 ${chalk.gray("—")} ${chalk.gray("NEW · sim (instant) · sim arm (interactive) · demo2 · learn")}`,value:"embodied"},{name:` ${chalk.bold("International Olympiad")} ${chalk.gray("—")} ${chalk.gray("CTF × AI (~500MB, advanced)")}`,value:"olympiad"},{name:` ${chalk.bold("National/Regional Partner")} ${chalk.gray("—")} ${chalk.gray("organizer tools (tokens, competitions)")}`,value:"organizer"},{name:` ${chalk.gray("About ICOA")} ${chalk.gray("·")} ${chalk.gray("Info & contact")}`,value:"about"}];console.log(chalk.gray(" Use ")+chalk.yellow("↑")+chalk.gray(" or ")+chalk.yellow("↓")+chalk.gray(" to select, ")+chalk.yellow("Enter")+chalk.gray(" to confirm.")),console.log();let yo="";for(;!yo;){const o=await F({message:"Mode",choices:go,default:co||"selection"});"about"!==o?yo=o:(console.clear(),console.log(),console.log(chalk.cyan(" ═══════════════════════════════════════════════════")),console.log(chalk.bold.yellow(" ICOA")+chalk.white(" — AI-Native CLI OS for Cyber & AI Security")),console.log(chalk.gray(" Olympiad & Competition · K-12 to University")),console.log(chalk.cyan(" ───────────────────────────────────────────────────")),console.log(),console.log(chalk.bold.white(" What Makes ICOA Different")),console.log(chalk.gray(" · AI-native AI teammate, AI adversary, AI translation")),console.log(chalk.gray(" · CLI OS Complete competition environment in terminal")),console.log(chalk.gray(" · 110 tools pwntools, z3, gdb, nmap, sleuthkit... pre-configured")),console.log(chalk.gray(" · Global scale 15,000+ concurrent exams · 15 languages")),console.log(),console.log(chalk.bold.white(" Competition Format")),console.log(` ${chalk.green.bold("AI4CTF")}${chalk.gray(" [Day 1] AI as teammate — 5hr jeopardy CTF")}`),console.log(` ${chalk.red.bold("CTF4AI")}${chalk.gray(" [Day 2] Challenge AI — adversarial ML, red-team")}`),console.log(` ${chalk.cyan.bold("CTF4VLA")}${chalk.gray(" [Pioneer Round] Embodied AI — attack robot brains (NEW)")}`),console.log(),console.log(chalk.white(" Sydney, Australia")+chalk.gray(" · Jun 27 - Jul 2, 2026 · 40+ countries")),console.log(),console.log(chalk.bold.white(" Organized by")+chalk.gray(" ASRA (Australia) · ICO Foundation Inc")),console.log(chalk.bold.white(" Contact ")+chalk.cyan(" australia@icoa2026.au · accreditation@icoa2026.au")),console.log(chalk.bold.white(" Website ")+chalk.cyan.underline(" https://icoa2026.au")),console.log(chalk.cyan(" ═══════════════════════════════════════════════════")),console.log(),console.log(chalk.gray(" Press ")+chalk.yellow("Enter")+chalk.gray(" to return...")),await new Promise(o=>{const e=l=>{process.stdin.removeListener("data",e),process.stdin.isTTY&&process.stdin.setRawMode&&process.stdin.setRawMode(!1),process.stdin.pause(),o()};process.stdin.isTTY&&process.stdin.setRawMode&&process.stdin.setRawMode(!0),process.stdin.resume(),process.stdin.once("data",e)}),console.clear())}if("olympiad"===yo&&"olympiad"!==co&&(console.log(),console.log(chalk.yellow(" This mode will download ~500MB of CTF tools and AI models.")),await io({message:"Continue?",default:!0})||(yo="selection",console.log(chalk.gray(" Switched to National Selection mode.")))),yo!==co&&s({mode:yo}),console.log(),"olympiad"===yo&&m(no)){d(no),console.log(chalk.gray(" Checking competition environment..."));const{execSync:o}=await import("node:child_process"),e=[{name:"pwntools",cmd:'python3 -c "import pwn"'},{name:"z3-solver",cmd:'python3 -c "import z3"'},{name:"numpy",cmd:'python3 -c "import numpy"'},{name:"requests",cmd:'python3 -c "import requests"'}];let l=0;for(const t of e)try{o(t.cmd,{stdio:"ignore"})}catch{l++}if(l>0){console.log(chalk.yellow(` ${l} core libraries missing.`));try{const{confirm:o}=await import("@inquirer/prompts");if(await o({message:" Install competition Python libraries now?",default:!0,theme:{prefix:"",style:{message:o=>chalk.green(o),defaultAnswer:o=>chalk.green(o)}}})){console.log();const{execSync:o}=await import("node:child_process");o("icoa env setup",{stdio:"inherit"})}}catch{console.log(chalk.gray(" Run ")+chalk.white("env setup")+chalk.gray(" later to install."))}console.log()}else console.log(chalk.green(" All core libraries ready.")),console.log()}if(j){const o=y();if(o){const e=Math.floor(o.awaySeconds/60),l=o.awaySeconds%60;console.log(chalk.yellow(` Session resumed. Away: ${e}m ${l}s | Total exits: ${o.exitCount}`)),console.log()}}if("selection"===yo)so();else if("embodied"===yo){console.log(chalk.cyan.bold(" [Embodied AI Security 🤖]")),console.log(),console.log(chalk.bold.cyan(" CTF4VLA")+chalk.gray(" — ICOA 2026's ")+chalk.bold.white("Pioneer Round")),console.log(chalk.gray(" an independent parallel track alongside the scored main events: ")+chalk.green("AI4CTF")+chalk.gray(" (Day 1) and ")+chalk.red("CTF4AI")+chalk.gray(" (Day 2)")),console.log(),console.log(chalk.white(" Embodied AI is at its ImageNet moment.")),console.log(chalk.gray(" VLA models, MuJoCo physics, real robot arms.")),console.log(chalk.gray(" Real models, real physics, real attack surfaces.")),console.log(),console.log(chalk.gray(" ─────────────────────────────────────────────"));const o=O()>0||E()>0,e=S()>0,l=$(),t=T(),n=null!==t&&"number"==typeof t.completedAt&&t.nextCardIndex>=t.totalCards,s=null!==t&&!n;if(n)console.log(chalk.bold.yellow(" Continue: ")+chalk.bold.cyan("④ learn LEARNDEMO01")+chalk.gray(" (demo2 ✓ · sim")+(e?chalk.gray(" ✓ · sim arm ✓)"):chalk.gray(")")));else if(s){const o=`${t.nextCardIndex} / ${t.totalCards}`;console.log(chalk.bold.yellow(" Continue: ")+chalk.bold.cyan("③ demo2")+chalk.gray(" (last left at card ")+chalk.bold.yellow(o)+chalk.gray(")"))}else o&&e?console.log(chalk.bold.yellow(" Next up: ")+chalk.bold.cyan("③ demo2")+chalk.gray(" → ")+chalk.bold.cyan("④ learn LEARNDEMO01")+chalk.gray(" (sim ✓ · sim arm ✓)")):l?console.log(chalk.bold.yellow(" Next up: ")+(e?chalk.bold.cyan("① sim")+chalk.gray(" → ")+chalk.bold.cyan("③ demo2"):chalk.bold.cyan("② sim arm")+chalk.gray(" → ")+chalk.bold.cyan("③ demo2"))+chalk.gray(" → ")+chalk.bold.cyan("④ learn LEARNDEMO01")):console.log(chalk.bold.yellow(" First time? Try in order: ")+chalk.bold.cyan("① sim")+chalk.gray(" → ")+chalk.bold.cyan("② sim arm")+chalk.gray(" → ")+chalk.bold.cyan("③ demo2")+chalk.gray(" → ")+chalk.bold.cyan("④ learn LEARNDEMO01"));console.log(chalk.gray(" ─────────────────────────────────────────────")),console.log(chalk.bold.green(" sim")+chalk.gray(" ")+chalk.bold.cyan("①")+chalk.gray(" ")+chalk.bold.yellow("★ INSTANT")+chalk.gray(" — 8-robot group dance, no wait, no setup")),console.log(chalk.bold.green(" sim arm")+chalk.gray(" ")+chalk.bold.cyan("②")+chalk.gray(" interactive 6-DOF arm sandbox — type joint values, watch")),console.log(chalk.bold.green(" demo2")+chalk.gray(" ")+chalk.bold.cyan("③")+chalk.gray(" ~8 min interactive intro + live MuJoCo sim")),console.log(chalk.bold.green(" learn LEARNDEMO01")+chalk.gray(" ")+chalk.bold.cyan("④")+chalk.gray(" free 11-card intro (paste this command as-is)")),console.log(chalk.bold.green(" learn ")+chalk.bold.yellow("EAxxxxxxxx")+chalk.gray(" full 100/480-card curriculum (team-issued)")),console.log(chalk.bold.green(" exam ")+chalk.bold.yellow("PDxxxxxxxx")+chalk.gray(" Paper D (CTF4VLA) — national selection contestants")),console.log(chalk.gray(" ─────────────────────────────────────────────")),console.log(),console.log(chalk.gray(" Three open tiers: ")+chalk.green("free 11")+chalk.gray(" · ")+chalk.yellow("registered 100")+chalk.gray(" · ")+chalk.bold.magenta("national team 480")+chalk.gray(" (PhD-ready)")),console.log(chalk.gray(" Country team contact: ")+chalk.cyan("australia@icoa2026.au")),console.log(),h(),console.log()}else"organizer"===yo?(console.log(chalk.yellow.bold(" [National/Regional Partner]")),console.log(),console.log(chalk.bold.white(" ██╗ ██████╗ ██████╗ █████╗")),console.log(chalk.bold.white(" ██║██╔════╝██╔═══██╗██╔══██╗")),console.log(chalk.bold.white(" ██║██║ ██║ ██║███████║")),console.log(chalk.bold.white(" ██║██║ ██║ ██║██╔══██║")),console.log(chalk.bold.white(" ██║╚██████╗╚██████╔╝██║ ██║")),console.log(chalk.bold.white(" ╚═╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝")),console.log(),console.log(chalk.yellow(" International Cyber Olympiad in AI 2026")),console.log(chalk.bold.magenta(" The World's First AI-Native CLI Operating System")),console.log(chalk.bold.magenta(" for Cybersecurity & AI Security Competition")),console.log(chalk.bold.magenta(" and Olympiad for K-12")),console.log(chalk.gray(" Sydney, Australia · Jun 27 - Jul 2, 2026")),console.log(),console.log(chalk.white(" Vision")),console.log(chalk.gray(" Building a global pipeline for youth cyber & AI")),console.log(chalk.gray(" security talent through education and competition.")),console.log(),console.log(chalk.white(" Capacity")),console.log(chalk.gray(" 15,000+ concurrent online examinations")),console.log(chalk.gray(" National selection, training, and education support")),console.log(),console.log(chalk.white(" Olympic Spirit")),console.log(chalk.gray(" Excellence · Friendship · Respect")),console.log(),console.log(chalk.gray(" ─────────────────────────────────────────────")),console.log(chalk.white(" New country accreditation & support:")),console.log(chalk.cyan(" australia@icoa2026.au")),console.log(chalk.cyan(" accreditation@icoa2026.au")),console.log(chalk.gray(" ─────────────────────────────────────────────")),console.log(),N?(console.log(chalk.green(` Logged in as ${R.userName}`)),console.log(chalk.white(" exam list")+chalk.gray(" Manage exams")),console.log(chalk.white(" logout")+chalk.gray(" Disconnect"))):console.log(chalk.white(" join <url>")+chalk.gray(" Connect to manage exams")),console.log(),h(),console.log()):q&&!c()?(console.log(chalk.red(" Token was activated on a different device.")),console.log(chalk.gray(" Contact organizer for assistance.")),console.log()):N?(console.log(chalk.green.bold(` Welcome back, ${R.userName}!`)),console.log(chalk.gray(` Connected to ${R.ctfdUrl}`)),console.log(),console.log(chalk.gray(" ─────────────────────────────────────────────")),console.log(chalk.white(" Ready to compete? Start here:")),console.log(),console.log(chalk.bold.cyan(" challenges")+chalk.gray(" Browse challenges by category")),console.log(chalk.white(" status")+chalk.gray(" Your score & hint budget")),console.log(chalk.white(" scoreboard")+chalk.gray(" Live rankings")),console.log(chalk.white(" help")+chalk.gray(" Full command list")),console.log(),console.log(chalk.gray(" Tool environment:")),console.log(chalk.white(" env")+chalk.gray(" See which of the 110 CTF tools are installed")),console.log(chalk.white(" env setup")+chalk.gray(" Install anything missing (~5 min, one-time)")),console.log(chalk.gray(" ─────────────────────────────────────────────")),console.log(chalk.gray(" Tip: ")+chalk.cyan("help")+chalk.gray(" · ")+w()+chalk.gray(" · ")+chalk.cyan("Ctrl+C")+chalk.gray(" pauses · ")+chalk.cyan("quit")+chalk.gray(" closes")),console.log()):q?(G(eo)||K(eo,{recursive:!0}),console.log(chalk.green.bold(" Welcome, competitor!")),console.log(chalk.gray(` Workspace: ${eo}`)),console.log(),console.log(chalk.gray(" ─────────────────────────────────────────────")),console.log(chalk.white(" Get started:")),console.log(),console.log(chalk.white(" Step 1 ")+chalk.bold.cyan("join <url>")+chalk.gray(" Connect to competition server")),console.log(chalk.white(" Step 2 ")+chalk.bold.cyan("challenges")+chalk.gray(" Browse & solve challenges")),console.log(chalk.white(" Step 3 ")+chalk.bold.cyan("ai4ctf")+chalk.gray(" Ask AI when stuck")),console.log(),console.log(chalk.gray(" Before Step 1 — make sure your tools are ready:")),console.log(chalk.white(" env")+chalk.gray(" See which of the 110 CTF tools are installed")),console.log(chalk.white(" env setup")+chalk.gray(" Install anything missing (~5 min, one-time)")),console.log(),console.log(chalk.gray(" Also: ")+chalk.white("help")+chalk.gray(" all commands")),console.log(chalk.gray(" ─────────────────────────────────────────────")),console.log(chalk.gray(" Tip: ")+chalk.cyan("Ctrl+C")+chalk.gray(" pauses · ")+w()+chalk.gray(" · ")+chalk.cyan("quit")+chalk.gray(" closes CLI")),console.log()):(console.log(chalk.bold.white(" Welcome to ICOA CLI — International Olympiad")),console.log(),console.log(chalk.gray(" ─────────────────────────────────────────────")),console.log(chalk.white(" To begin, activate your competition token:")),console.log(),console.log(chalk.bold.cyan(" activate <token>")),console.log(),console.log(chalk.gray(" While waiting, explore:")),console.log(chalk.white(" ref linux")+chalk.gray(" Quick reference for Linux")),console.log(chalk.white(" ref web")+chalk.gray(" Quick reference for Web")),console.log(chalk.white(" env")+chalk.gray(" See which of the 110 CTF tools are installed")),console.log(chalk.white(" env setup")+chalk.gray(" Install anything missing (~5 min, one-time)")),console.log(chalk.white(" help")+chalk.gray(" All available commands")),console.log(chalk.gray(" ─────────────────────────────────────────────")),console.log(chalk.gray(" Tip: ")+chalk.cyan("Ctrl+C")+chalk.gray(" pauses · ")+w()+chalk.gray(" · ")+chalk.cyan("quit")+chalk.gray(" closes CLI")),console.log());e.exitOverride(),e.configureOutput({writeErr:()=>{},writeOut:o=>{console.log(o)}});const mo=o({input:process.stdin,output:process.stdout,prompt:oo(),terminal:!0});f(mo);let po=!1;p(!0),V();const uo=mo.prompt.bind(mo);mo.prompt=o=>{b()||v()||A()||k()||mo.setPrompt(oo()),uo(o)},mo.prompt(),mo.on("line",async o=>{if(po)return;const t=o.trim();if(!t)return mo.setPrompt(b()?chalk.magenta("ai4ctf> "):oo()),void mo.prompt();if("menu"===t||"menu confirm"===t)return P()&&"menu confirm"!==t?(console.log(),console.log(chalk.yellow(" Real exam active. Progress is auto-saved.")),console.log(chalk.gray(" To return to main menu anyway, type ")+chalk.white("menu confirm")),console.log(),void mo.prompt()):void u(mo);if(b()){po=!0;const o=await x(t);return po=!1,"exit"===o&&mo.setPrompt(oo()),void mo.prompt()}if(v()){po=!0;const o=await C(t);return po=!1,"exit"!==o&&"solved"!==o||mo.setPrompt(oo()),void mo.prompt()}if(A()){po=!0;const o=await I(t);return po=!1,"exit"===o&&mo.setPrompt(oo()),mo.setPrompt(A()?chalk.bold.cyan("ctf4vla> "):oo()),void mo.prompt()}if(Y(t),"exit"===t)return L()?(console.log(),console.log(chalk.yellow(" ⚠ An exam is in progress.")),console.log(chalk.white(" To return to menu without losing progress, type: ")+chalk.bold.cyan("back")),console.log(chalk.white(" To fully close ICOA CLI, type: ")+chalk.bold.cyan("quit")),console.log(chalk.gray(" Your progress is auto-saved either way.")),console.log(),void mo.prompt()):(console.log(),console.log(chalk.gray(" ")+chalk.white("exit")+chalk.gray(" returns to the main menu. To fully close ICOA CLI, type ")+chalk.bold.cyan("quit")+chalk.gray(".")),"selection"===yo&&so(),void mo.prompt());if("quit"===t||"q"===t||"quit confirm"===t){const o=L();return o&&"demo-free"!==o.session.examId&&"quit confirm"!==t?(console.log(),console.log(chalk.yellow(" ⚠ A real exam is in progress.")),console.log(chalk.gray(" Your answers are auto-saved on the server, but the exam timer keeps ticking")),console.log(chalk.gray(" on the server side even if you close the CLI.")),console.log(),console.log(chalk.white(" To leave the CLI but keep the exam alive, type: ")+chalk.bold.cyan("back")),console.log(chalk.gray(" (recommended — you can resume with ")+chalk.cyan("exam q 1")+chalk.gray(" after relaunching icoa)")),console.log(),console.log(chalk.white(" To really close ICOA CLI, type: ")+chalk.bold.cyan("quit confirm")),console.log(),void mo.prompt()):(o&&"demo-free"===o.session.examId&&(console.log(),console.log(chalk.gray(" Demo paused. Resume with: ")+chalk.white("demo")+chalk.gray(" (fresh) or ")+chalk.white("exam q 1")+chalk.gray(" (continue)."))),J(),g(),console.log(chalk.gray(" Session saved. Use ")+chalk.white("icoa --resume")+chalk.gray(" to continue.")),M(),void D(0))}if("back"===t){const o=L(),e=o&&"demo-free"!==o.session.examId,l=o&&"demo-free"===o.session.examId&&(()=>{const e=new Date(o.session.startedAt||0).getTime();return Date.now()-e<18e5})();if(e)console.log(),console.log(chalk.gray(" Exam paused. Your progress is saved.")),console.log(chalk.white(" Resume: exam q 1")+chalk.gray(" · ")+chalk.white("exam review")+chalk.gray(" · ")+chalk.white("exam submit")),console.log();else if(l){const e=Object.keys(o.answers).length,l=o.session.questionCount;console.log(),console.log(chalk.gray(` Demo paused (${e}/${l} answered). Resume with: `)+chalk.white("exam q 1")),console.log(chalk.gray(" Or type ")+chalk.white("demo")+chalk.gray(" to restart.")),console.log()}else{if(o&&"demo-free"===o.session.examId){const{clearExamState:o}=await import("./lib/exam-state.js");o("demo-free")}const e=n();fetch("https://practice.icoa2026.au/api/icoa/demo-stats",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({type:"post-report-back",lang:e.language||"en",timestamp:(new Date).toISOString()}),signal:AbortSignal.timeout(5e3)}).catch(()=>{}),"selection"===yo?so():console.log(chalk.gray(" Already at main menu."))}return void mo.prompt()}if("help"===t||"?"===t){if(L()){po=!0;try{await e.parseAsync(["node","icoa","exam","help"])}catch{}return po=!1,void mo.prompt()}return ro(a(),yo),void mo.prompt()}if("manual"===t)return ro(a(),yo),void mo.prompt();if("more help"===t.toLowerCase()&&L()){po=!0;try{await e.parseAsync(["node","icoa","exam","more-help"])}catch{}return po=!1,void mo.prompt()}if("continue"===t.toLowerCase())return console.log(),console.log(chalk.green.bold(" ═══ AI4CTF — AI as Your Teammate ═══")),console.log(),console.log(chalk.white(" In AI4CTF, you solve cybersecurity challenges")),console.log(chalk.white(" with AI by your side.")),console.log(),console.log(chalk.white(" In competition, you get AI help at 3 levels:")),console.log(chalk.yellow(" hint a")+chalk.gray(" General guidance (50 uses)")),console.log(chalk.yellow(" hint b")+chalk.gray(" Deep analysis (10 uses)")),console.log(chalk.yellow(" hint c")+chalk.gray(" Critical assist (2 uses)")),console.log(),console.log(chalk.white(" Try it now! Type: ")+chalk.bold.green("ai4ctf")),console.log(chalk.gray(' Chat freely with your AI teammate. Type "exit" when done.')),console.log(),console.log(chalk.gray(" After ai4ctf, try: ")+chalk.bold.red("ctf4ai")+chalk.gray(' — trick the AI into saying "koala"')),console.log(),void mo.prompt();if(/^ICOA-[A-Z]{2,3}-\d{1,6}$/i.test(t.trim())){po=!0;try{await e.parseAsync(["node","icoa","exam","token",t.trim()])}catch{}return po=!1,void mo.prompt()}if(/^[A-Z]{2}[0-9A-HJKMNP-TV-Z]{8}$/i.test(t.trim())){po=!0;try{await e.parseAsync(["node","icoa","exam","token",t.trim().toUpperCase()])}catch{}return po=!1,void mo.prompt()}const s=t.match(/^exam\s+([A-Z]{2}[0-9A-HJKMNP-TV-Z]{8})$/i);if(s){po=!0;try{await e.parseAsync(["node","icoa","exam","token",s[1].toUpperCase()])}catch{}return po=!1,void mo.prompt()}const y=t.match(/^exam\s+([A-Z]{2,3})$/i);if(y){po=!0;try{await e.parseAsync(["node","icoa","exam","list",y[1]])}catch{}return po=!1,void mo.prompt()}if("clear"===t||"cls"===t)return console.clear(),void mo.prompt();if(t.startsWith("activate ")){const o=t.slice(9).trim(),e=r(o);return"ok"===e?console.log(chalk.green(" Access granted! Token bound to this device.")):"already_bound"===e?(console.log(),console.log(chalk.red(" Token already activated on a different device.")),console.log(chalk.gray(" Each token binds to the first device that uses it. If you lost the device,")),console.log(chalk.gray(" contact your proctor to have the token re-issued for a new device."))):(console.log(),console.log(chalk.red(" Token not recognized.")),console.log(chalk.gray(" Possible reasons:")),console.log(chalk.white(" • ")+chalk.gray("Typo — tokens are case-insensitive, 10 chars, start with a 2-letter country code (e.g. ")+chalk.cyan("UAK7M2R9Q4")+chalk.gray(")")),console.log(chalk.white(" • ")+chalk.gray("Expired — ask your proctor or organizer for a fresh token")),console.log(chalk.white(" • ")+chalk.gray("Network — verify connection to ")+chalk.cyan("practice.icoa2026.au")),console.log(chalk.gray(" Still stuck? type ")+chalk.cyan("help")+chalk.gray(" or try ")+chalk.cyan("exam demo")+chalk.gray(" for a free practice round."))),console.log(),void mo.prompt()}if("activate"===t)return console.log(chalk.gray(" Usage: ")+chalk.white("activate <token>")),console.log(),void mo.prompt();const m=L();if(m){const o=t.toUpperCase().trim(),l=o=>{const e=m.questions.find(e=>e.number===o);return!!e&&("ai4ctf"===e.type||"ctf4ai"===e.type||e.options&&!e.options.A&&!e.options.B)},n=o=>{const e="demo-free"!==m.session.examId,l=e&&o>=39?"ctf4ai":e&&o>=31?"ai4ctf":null;console.log(),console.log(chalk.yellow(` Q${o} is a practical question — letters (A/B/C/D) don't apply here.`)),l?(console.log(chalk.white(" Enter the AI chat for this question: ")+chalk.bold.cyan(l)),console.log(chalk.gray(" Or submit a flag directly: ")+chalk.green(`exam answer ${o} ICOA{your_flag}`))):console.log(chalk.gray(" Submit a flag: ")+chalk.green(`exam answer ${o} ICOA{your_flag}`)),console.log()};if(/^[ABCD]$/.test(o)){const t=m._lastQ||1;if(l(t))return n(t),void mo.prompt();po=!0;try{await e.parseAsync(["node","icoa","exam","answer",String(t),o])}catch{}return po=!1,void mo.prompt()}const s=o.match(/^(\d+)\s+([ABCD])$/);if(s){const o=parseInt(s[1],10);if(l(o))return n(o),void mo.prompt();po=!0;try{await e.parseAsync(["node","icoa","exam","answer",s[1],s[2]])}catch{}return po=!1,void mo.prompt()}}const d=t.split(/\s+/)[0].toLowerCase(),p=/^python3?(\.\d+)?$/.test(d),h="ls"===d||"pwd"===d,w=t.startsWith("!")||d.startsWith("!")||p||h,f=new Set(["nano","vi","vim","emacs","pico","ed","code","cat","less","more","head","tail","ls","pwd","cd","base64","xxd","hexdump","od","openssl","md5sum","sha256sum","grep","find","awk","sed","strings","file","curl","wget","nc","ping","nmap","echo","bash","sh","zsh","pip","pip3","node","npm"]),k=()=>{console.log(chalk.gray(" Shell commands need ")+chalk.bold.cyan("!")+chalk.gray(" prefix. Try: ")+chalk.bold.cyan(`!${t}`)),console.log()};if("embodied"===yo&&!w&&!["demo2","learn","exam","ctf4vla","lang","ref","setup","env","sim"].includes(d))return f.has(d)?(k(),void mo.prompt()):(console.log(chalk.gray(" Not available in Embodied AI Security mode.")),console.log(chalk.white(" Try ")+chalk.bold.cyan("demo2")+chalk.gray(" (intro) · ")+chalk.bold.cyan("learn")+chalk.gray(" (curriculum) · ")+chalk.bold.cyan("exam <PD-token>")+chalk.gray(" (Paper D)")),console.log(),void mo.prompt());if("selection"===yo&&!w&&!["exam","demo","retry","nations","next","prev","continue","setup","lang","ref","ai4ctf","ctf4ai","mark","unmark","review","submit","env","sim"].includes(d)){if(f.has(d))return k(),void mo.prompt();if(console.log(chalk.gray(" Not available in Selection mode.")),m){const o=m._lastQ||1;console.log(chalk.white(` Resume exam: exam q ${o}`)+chalk.gray(" · ")+chalk.white("A/B/C/D")+chalk.gray(" to answer"))}else console.log(chalk.gray(" Try: demo · setup to switch mode"));return console.log(),void mo.prompt()}if("organizer"===yo&&!["join","exam","demo","retry","next","prev","logout","setup","lang","ref","ctf","mark","unmark","review","submit"].includes(d))return console.log(chalk.gray(" Not available in Organizer mode. Switch via: setup")),console.log(),void mo.prompt();if(!("olympiad"!==yo||a()&&c()||i(d)))return console.log(chalk.yellow(" Restricted mode. ")+chalk.gray("Enter your access token:")),console.log(chalk.white(" activate <token>")),console.log(),console.log(chalk.gray(" Free commands: ")+chalk.white("ref [topic]")+chalk.gray(", ")+chalk.white("help")+chalk.gray(", ")+chalk.white("exit")),console.log(),void mo.prompt();if(!["join","activate","challenges","ch","open","submit","flag","scoreboard","sb","status","time","ref","shell","files","connect","note","notes","logbook","log","manual","lang","setup","env","ai4ctf","model","ctf","exam","demo","retry","nations","next","prev","continue","logout","ctf4ai","mark","unmark","review","submit","learn","demo2","ctf4vla","theme","sim"].includes(d)){if(lo.has(d))return console.log(chalk.yellow(` "${d}" is a shell command — the ICOA prompt isn't a shell.`)),console.log(chalk.gray(" In real-exam mode, prefix with ! to run inside the sandbox: ")+chalk.cyan(`!${t}`)),console.log(),void mo.prompt();if(/(?:^|\s)(?:\/(?!home\/|Users\/|tmp\/)|\.\.\/|~\/)/.test(t)&&!t.startsWith("cd ")){const o=/(?:^|\s)\/(?!home\/\w+\/icoa-workspace|Users\/\w+\/icoa-workspace|tmp\/)/.test(t),e=/\.\./.test(t);if(o||e)return console.log(chalk.red(" Blocked: access outside workspace is not allowed.")),console.log(chalk.gray(` Workspace: ${eo}`)),console.log(),void mo.prompt()}let o=t.startsWith("!")?t.slice(1).trim():t;if("darwin"===process.platform){const e="/opt/homebrew/opt/python@3.12/bin/python3.12";o=o.replace(/^python3?\s/,`${e} `).replace(/^(python3|python)$/,e)}else if("win32"===process.platform){const e=(()=>{try{return l("py -3 --version",{stdio:["ignore","ignore","ignore"],timeout:1500}),"py -3"}catch{}return"python"})();o=o.replace(/^python3?(\.\d+)?\s/,`${e} `).replace(/^python3?(\.\d+)?$/,e)}else{const e=(()=>{try{return l("which python3.12",{stdio:"ignore"}),"python3.12"}catch{return"python3"}})();o=o.replace(/^python\s/,`${e} `).replace(/^python$/,e)}const e=_(),n=B(t);Q({cwd:e,input:t,riskFlags:n}),n.length>0&&P()&&(console.log(chalk.yellow(` ⚠ Action flagged: ${n.join(", ")} — logged.`)),console.log()),/^(\S*python3?(\.\d+)?)\s*$/.test(o)&&(o=`PYTHONSTARTUP="${function(){const o=H(X(),".icoa");G(o)||K(o,{recursive:!0});const e=H(o,"python-startup.py");return G(e)||Z(e,"# ICOA exam interactive startup — auto-loaded by PYTHONSTARTUP\nimport base64, struct, hashlib, re, json, os, sys, binascii\ntry: import requests\nexcept ImportError: pass\ntry: from Crypto.Cipher import AES\nexcept ImportError: pass\ntry: from Crypto.Util.Padding import pad, unpad\nexcept ImportError: pass\ntry: from pwn import xor, p32, u32, p64, u64\nexcept ImportError: pass\ntry: import bs4\nexcept ImportError: pass\ntry: import numpy as np\nexcept ImportError: pass\n"),e}()}" ${o}`,console.log(),console.log(chalk.cyan(" ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")),console.log(chalk.bold.white(" Python ready — ICOA exam toolkit pre-loaded")),console.log(chalk.cyan(" ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")),console.log(),console.log(chalk.white(" Already imported: ")+chalk.gray("base64, struct, hashlib, re, json, binascii")),console.log(chalk.white(" Also available: ")+chalk.gray("requests, bs4, numpy, AES, pad/unpad, xor, p32/u32/p64/u64")),console.log(),console.log(chalk.yellow(" Quick examples:")),console.log(chalk.gray(' base64.b64decode("aGVsbG8=") ')+chalk.gray("# decode base64")),console.log(chalk.gray(' bytes.fromhex("48656c6c6f") ')+chalk.gray("# hex → bytes")),console.log(chalk.gray(' "ICOA{x}".encode() ')+chalk.gray("# str → bytes")),console.log(chalk.gray(" [chr(c) for c in [73,67,79,65]] ")+chalk.gray("# ASCII codes")),console.log(chalk.gray(' xor(bytes.fromhex("0a2b"), b"IC") ')+chalk.gray("# pwntools XOR")),console.log(),console.log(chalk.gray(" Exit: ")+chalk.white("exit()")+chalk.gray(" or Ctrl-D")),console.log(chalk.cyan(" ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")),console.log()),po=!0;try{W()&&await U()?await z(o,mo):await ao(o,mo,e)}catch{console.log(chalk.yellow(` Command failed: ${d}`))}return po=!1,console.log(),void mo.prompt()}po=!0;const T=t.trim(),$=T.toLowerCase();let S,O=null,E="";if(m)if("submit"===$)O="final";else if($.startsWith("submit ")){let o=T.slice(7).trim();/^submit\s+/i.test(o)&&(o=o.replace(/^submit\s+/i,"").trim()),o=o.replace(/^["'`]+|["'`]+$/g,"").trim(),o&&/^ICOA\{[^}]*\}?$/i.test(o)&&(O="flag",E=o)}else/^ICOA\{[^}]+\}$/i.test(T)&&(O="flag",E=T);S="final"===O?["exam","submit"]:"flag"===O?["exam","answer",String(m?._lastQ||1),E]:function(o){const e=o.split(/\s+/),l=e[0].toLowerCase(),t=e.slice(1),n={demo:["exam","demo"],retry:["exam","demo-retry"],nations:["exam","nations"],next:["exam","next"],prev:["exam","prev"],mark:["exam","mark",...t],unmark:["exam","unmark",...t],review:["exam","review"],logout:["ctf","logout"],join:["ctf","join",...t],activate:["ctf","activate",...t],challenges:["ctf","challenges"],ch:["ctf","challenges"],open:["ctf","open",...t],submit:["ctf","submit",...t],flag:["ctf","submit",...t],scoreboard:["ctf","scoreboard",...t],sb:["ctf","scoreboard",...t],status:["ctf","status"],time:["ctf","time"]};return n[l]?n[l]:["ref","shell","files","connect","note","notes","logbook","log","manual","lang","setup","env","ai4ctf","model","ctf","exam","ctf4ai"].includes(l)?[l,...t]:e}(t);const j="ctf"===S[0]&&"join"===S[1];j&&mo.pause(),process.exit=()=>{throw new Error(to)};try{await e.parseAsync(["node","icoa",...S])}catch(o){const e=o instanceof Error?o.message:String(o);if(e===to);else if(e.includes("commander.unknownCommand")){const{distance:o}=await import("fastest-levenshtein"),e=["ctf","ref","shell","files","connect","note","notes","logbook","log","manual","lang","setup","env","ai4ctf","exam","ctf4ai","theme","clear","cls","quit","exit","back","menu","help","continue","activate","demo","challenges","status","scoreboard","join","logout"],l=d.split(/\s+/)[0]||d;let t={word:"",dist:1/0};for(const n of e){const e=o(l.toLowerCase(),n);e<t.dist&&(t={word:n,dist:e})}console.log(chalk.yellow(` Unknown command: ${d}.`)),t.dist>0&&t.dist<=2&&console.log(chalk.gray(" Did you mean: ")+chalk.bold.cyan(t.word)+chalk.gray("?")),console.log(chalk.gray(" Type ")+chalk.cyan("help")+chalk.gray(" for the full command list."))}else e.includes("commander.")||(e.includes("fetch failed")||e.includes("ECONNREFUSED")||e.includes("ETIMEDOUT"))&&console.log(chalk.yellow(" Network error. Check your connection."))}finally{process.exit=D,po=!1,j&&mo.resume()}b()?mo.setPrompt(chalk.magenta("ai4ctf> ")):v()?mo.setPrompt(chalk.red("ctf4ai> ")):A()&&mo.setPrompt(chalk.bold.cyan("ctf4vla> ")),console.log(),mo.prompt()}),mo.on("SIGINT",()=>{if(console.log(),b()||v())console.log(chalk.yellow(" Ctrl+C did not close ICOA CLI — you are still in the AI chat.")),console.log(chalk.white(" Type ")+chalk.bold.cyan("exit")+chalk.white(" to leave the chat and return to the menu."));else if(L()){const o="demo-free"!==L().session.examId;console.log(chalk.yellow(" Ctrl+C did NOT close ICOA CLI.")),console.log(chalk.gray(` Your ${o?"exam":"demo"} is paused and every answer is auto-saved.`)),console.log(),console.log(chalk.white(" Resume: ")+chalk.cyan("exam q 1")+chalk.gray(" · Back to menu: ")+chalk.cyan("back")+chalk.gray(" · Close CLI: ")+chalk.cyan(o?"quit confirm":"quit"))}else console.log(chalk.yellow(" Ctrl+C did not close ICOA CLI — you are still at the ")+chalk.cyan("icoa>")+chalk.yellow(" prompt.")),console.log(chalk.gray(" Keep typing — ")+chalk.cyan("help")+chalk.gray(" lists commands. (Only ")+chalk.cyan("quit")+chalk.gray(" or Ctrl+D actually close the CLI.)"));console.log(),mo.prompt()}),mo.on("close",()=>{J(),g(),M(),D(0)})}function ao(o,l,t){return new Promise(n=>{const s=process.stdin,a=!!s.isTTY&&!!s.isRaw;if(l.pause(),s.isTTY&&"function"==typeof s.setRawMode)try{s.setRawMode(!1)}catch{}const r=e(o,{shell:!0,stdio:"inherit",cwd:t||process.cwd()}),i=()=>{if(s.isTTY&&"function"==typeof s.setRawMode&&a)try{s.setRawMode(!0)}catch{}l.resume(),n()};r.on("close",i),r.on("error",i)})}function ro(o,e="olympiad"){return console.log(),"selection"===e||"organizer"===e?(console.log(chalk.bold.white(" Exam")),console.log(chalk.white(" join <url> ")+chalk.gray("Connect to exam server")),console.log(chalk.white(" exam list ")+chalk.gray("Available exams")),console.log(chalk.white(" exam start <id> ")+chalk.gray("Begin an exam")),console.log(chalk.white(" exam q [n] ")+chalk.gray("View questions")),console.log(chalk.white(" exam answer <n> <X> ")+chalk.gray("Answer question")),console.log(chalk.white(" exam review ")+chalk.gray("Review all answers")),console.log(chalk.white(" exam submit ")+chalk.gray("Submit for grading")),console.log(chalk.white(" exam result ")+chalk.gray("View your score")),console.log(),console.log(chalk.bold.white(" System")),console.log(chalk.white(" ref [topic] ")+chalk.gray("Quick reference")),console.log(chalk.white(" setup ")+chalk.gray("Settings / switch mode")),console.log(chalk.white(" lang [code] ")+chalk.gray("Switch language")),console.log(chalk.white(" clear ")+chalk.gray("Clear screen")),console.log(chalk.white(" exit ")+chalk.gray("Quit")),void console.log()):o?(console.log(chalk.cyan(" ═══════════════════════════════════════════════")),console.log(chalk.bold.white(" How it works")),console.log(),console.log(chalk.gray(" 1. Browse ")+chalk.white("challenges")+chalk.gray(" and pick one")),console.log(chalk.gray(" 2. ")+chalk.white("open <id>")+chalk.gray(" to read the challenge")),console.log(chalk.gray(" 3. Use ")+chalk.white("ai4ctf")+chalk.gray(" to chat with AI when stuck")),console.log(chalk.gray(" 4. ")+chalk.white("submit <id> icoa{flag}")+chalk.gray(" to score points")),console.log(chalk.gray(" 5. Check ")+chalk.white("scoreboard")+chalk.gray(" to track your rank")),console.log(chalk.cyan(" ═══════════════════════════════════════════════")),console.log(),console.log(chalk.bold.white(" Competition")),console.log(chalk.white(" join <url> ")+chalk.gray("Connect to CTFd")),console.log(chalk.white(" challenges (ch) ")+chalk.gray("List challenges by category")),console.log(chalk.white(" open <id> ")+chalk.gray("Read challenge + get next steps")),console.log(chalk.white(" submit <id> <flag> ")+chalk.gray("Submit a flag")),console.log(chalk.white(" scoreboard (sb) ")+chalk.gray("Live rankings")),console.log(chalk.white(" status ")+chalk.gray("Your score, budget & timer")),console.log(chalk.white(" time ")+chalk.gray("Countdown timer")),console.log(),console.log(chalk.bold.white(" AI Teammate")+chalk.gray(" — 3 levels, use wisely")),console.log(chalk.white(' hint "question" ')+chalk.gray("Level A — General guidance (50 uses)")),console.log(chalk.white(' hint-b "question" ')+chalk.gray("Level B — Deep analysis (10 uses)")),console.log(chalk.white(' hint-c "question" ')+chalk.gray("Level C — Critical assist (2 uses)")),console.log(chalk.white(" hint budget ")+chalk.gray("Check remaining uses")),console.log(chalk.white(" ai4ctf ")+chalk.gray("Free-chat with AI (no limit)")),console.log(),console.log(chalk.bold.white(" Tools")),console.log(chalk.white(" ref [topic] ")+chalk.gray("Quick reference (linux, web, crypto...)")),console.log(chalk.white(" shell ")+chalk.gray("Docker sandbox")),console.log(chalk.white(" files <id> ")+chalk.gray("Download challenge files")),console.log(chalk.white(" connect <id> ")+chalk.gray("Connect to remote target")),console.log(chalk.white(" note [text] ")+chalk.gray("Add a logbook entry (in-exam: tags current Q)")),console.log(chalk.white(" logbook [n] ")+chalk.gray("View your logbook (in-exam: filter by Q)")),console.log(chalk.white(" log ")+chalk.gray("Session history")),console.log(chalk.white(" manual ")+chalk.gray("Show this command list (works in exam too)")),console.log(),console.log(chalk.bold.white(" System")),console.log(chalk.white(" setup ")+chalk.gray("Configure settings")),console.log(chalk.white(" lang [code] ")+chalk.gray("Switch language (15 supported)")),console.log(chalk.white(" logout ")+chalk.gray("Disconnect")),console.log(chalk.white(" clear ")+chalk.gray("Clear screen")),console.log(chalk.white(" exit ")+chalk.gray("Quit (session saved)")),void console.log()):(console.log(chalk.bold.yellow(" Restricted Mode — activate with a token to unlock all commands")),console.log(),console.log(chalk.white(" activate <token> ")+chalk.gray("Unlock full access")),console.log(chalk.white(" ref [topic] ")+chalk.gray("Quick reference")),console.log(chalk.white(" exit ")+chalk.gray("Quit")),void console.log())}
1
+ import{createInterface as o}from"node:readline";import{spawn as e,execSync as l}from"node:child_process";import chalk from"chalk";import{isConnected as t,getConfig as n,saveConfig as s}from"./lib/config.js";import{isActivated as a,activateToken as r,isFreeCommand as i,isDeviceMatch as c,recordExit as g,recordResume as y,isFirstRunOrUpgrade as m,markVersionSeen as d}from"./lib/access.js";import{setReplMode as p}from"./lib/ui.js";import{returnToMainMenu as u,printMenuHint as h,menuHintInline as w}from"./lib/menu-nav.js";import{setMainRl as f}from"./lib/main-rl.js";import{isChatActive as b,handleChatMessage as x}from"./commands/ai4ctf.js";import{isCtf4aiActive as v,handleCtf4aiMessage as C}from"./commands/ctf4ai-demo.js";import{isCtf4VlaActive as A,handleCtf4VlaMessage as I}from"./commands/ctf4vla.js";import{isDemo2Active as k}from"./commands/demo2.js";import{loadDemo2Progress as T}from"./lib/demo2-progress.js";import{hasAnySimHistory as $,lastArmAt as S,lastBundledAt as O,lastSimAt as E}from"./lib/sim-cooldown.js";import{getExamState as L,getRealExamState as P,getDemoState as j}from"./lib/exam-state.js";import{getDemoStats as R}from"./lib/demo-stats.js";import{isExamSetupComplete as N}from"./lib/exam-setup.js";import{DEMO_PICK_SIZE as D,DEMO_POOL_SIZE as q}from"./lib/demo-exam.js";import{isNativeWindowsCmd as F}from"./lib/platform.js";import{resetTerminalTheme as M}from"./lib/theme.js";import{ensureSandbox as U,runInSandbox as z,isDockerAvailable as W}from"./lib/sandbox.js";import{checkShellRisk as B,logShellAudit as Q,getActiveCwd as _}from"./lib/exam-sandbox.js";import{logCommand as Y}from"./lib/logger.js";import{startLogSync as V,stopLogSync as J}from"./lib/log-sync.js";import{existsSync as G,mkdirSync as K,writeFileSync as Z}from"node:fs";import{join as H}from"node:path";import{homedir as X}from"node:os";function oo(){return P()?chalk.cyan("exam> "):j()?chalk.yellow("demo> "):chalk.green("icoa> ")}const eo=H(X(),"icoa-workspace"),lo=new Set(["sudo","su","doas","pkexec","brew","apt","apt-get","yum","choco","npm","npx","pip","pip3","shutdown","reboot","halt","mkfs","fdisk","dd","iptables","ufw"]),to="__REPL_NO_EXIT__",no="2.5.1";function so(){const o=R(),e=N(),t=`Free practice — ${D} questions (from pool of ${q})`,n=F();if(console.log(),console.log(` ${chalk.cyan.bold("[Selection Mode]")}`),console.log(),n)console.log(chalk.gray(" Platform: ")+chalk.white("Windows cmd.exe")+chalk.gray(" — routed to Paper C (MCQ-only, 45 min, 70 pts, zero extra tools)")),console.log();else if(o.attempts>0){const o=function(){const o=["python3.12 --version","/opt/homebrew/opt/python@3.12/bin/python3.12 --version","/usr/local/opt/python@3.12/bin/python3.12 --version","python3 --version","python --version","py -3.12 --version","py -3 --version"];let e="",t="missing";for(const n of o)try{const o=l(n,{encoding:"utf-8",timeout:2e3,stdio:["ignore","pipe","ignore"]}).trim().replace("Python ",""),[s,a]=o.split(".").map(Number);if(3===s&&12===a)return{ok:!0,version:o,status:"ok"};e=o,t=3===s&&a>=10&&a<12?"old":3===s&&a>12?"new":"missing"}catch{}return{ok:"missing"!==t,version:e,status:t}}();"missing"===o.status?(console.log(chalk.yellow(" ⚠ Python not detected. For exam practical questions:")),console.log(chalk.gray(" → ")+chalk.bold.cyan("env python")+chalk.gray(" (platform install guide)")),console.log()):"new"===o.status&&(console.log(chalk.yellow(` ⚠ Python ${o.version} may lack CTF wheels. Python 3.12 recommended:`)),console.log(chalk.gray(" → ")+chalk.bold.cyan("env python")+chalk.gray(" (install guide)")),console.log())}if(0===o.attempts)console.log(chalk.white(" New here? Start with ")+chalk.bold.cyan("demo")+chalk.white(" — it takes a few minutes.")),console.log(),console.log(chalk.gray(" ─────────────────────────────────────────────")),console.log(chalk.bold.cyan(" demo")+chalk.gray(` ${t}`)),console.log(chalk.white(" lang")+chalk.gray(" List all supported languages")),console.log(chalk.white(" lang es")+chalk.gray(" Switch language (e.g. lang es, lang zh, lang fr)")),console.log(chalk.gray(" ─────────────────────────────────────────────"));else if(e||n){const e=1===o.attempts?"attempt":"attempts";o.attempts>0&&console.log(chalk.green(" ✓ Demo completed ")+chalk.gray(`(${o.attempts} ${e})`)),n||console.log(chalk.green(" ✓ Environment ready")),console.log(chalk.yellow(" → Enter your exam token to begin.")),console.log(chalk.gray(" (10-char code from your organizer, starts with your country code like ")+chalk.cyan("UA")+chalk.gray(" — case-insensitive)")),console.log(),console.log(chalk.gray(" ─────────────────────────────────────────────")),console.log(chalk.bold.yellow(" exam <token>")+chalk.gray(" Enter exam (primary action — use your organizer-issued token)")),console.log(chalk.gray(" format: ")+chalk.white("exam UAxxxxxxxx")+chalk.gray(" (2-letter country prefix + 8 chars)")),console.log(chalk.gray(" ─────────────────────────────────────────────")),console.log(chalk.gray(" Other commands:")),console.log(chalk.white(" demo")+chalk.gray(` ${t}`)),n||console.log(chalk.white(" exam setup")+chalk.gray(" Re-verify tool environment")),console.log(chalk.white(" lang")+chalk.gray(" List all supported languages")),console.log(chalk.white(" lang es")+chalk.gray(" Switch language (e.g. lang es, lang zh, lang fr)")),console.log(chalk.gray(" ─────────────────────────────────────────────"))}else{const e=1===o.attempts?"attempt":"attempts";console.log(chalk.green(" ✓ Demo completed ")+chalk.gray(`(${o.attempts} ${e}${o.bestPercentage>0?` · best ${o.bestPercentage}%`:""})`)),console.log(chalk.yellow(" → Next: prepare your environment for the real exam.")),console.log(),console.log(chalk.gray(" ─────────────────────────────────────────────")),console.log(chalk.white(" demo")+chalk.gray(` ${t}`)),console.log(chalk.bold.yellow(" exam setup")+chalk.gray(" Install tools for national selection (~150MB)")),console.log(chalk.white(" lang")+chalk.gray(" List all supported languages")),console.log(chalk.white(" lang es")+chalk.gray(" Switch language (e.g. lang es, lang zh, lang fr)")),console.log(chalk.gray(" ─────────────────────────────────────────────"))}console.log(chalk.gray(" ")+chalk.gray("Tip: ")+chalk.cyan("help")+chalk.gray(" for commands · ")+w()+chalk.gray(" · ")+chalk.cyan("Ctrl+C")+chalk.gray(" pauses · ")+chalk.cyan("quit")+chalk.gray(" closes")),console.log()}export async function startRepl(e,j){process.env.ICOA_INSIDE_REPL="1";const R=n(),N=t(),D=process.exit.bind(process),q=a();if(R.demoCleanedForVersion!==no){try{const{existsSync:o,unlinkSync:e}=await import("node:fs"),{join:l}=await import("node:path"),{getIcoaDir:t}=await import("./lib/config.js"),n=l(t(),"demo-state.json");o(n)&&e(n)}catch{}s({demoCleanedForVersion:no})}const{select:F,confirm:io}=await import("@inquirer/prompts"),co=R.mode||"",go=[{name:` ${chalk.bold("National Selection")} ${chalk.gray("—")} ${chalk.gray("demo, exam (lightweight)")}`,value:"selection"},{name:` ${chalk.bold("Embodied AI Security")} 🤖 ${chalk.gray("—")} ${chalk.gray("NEW · sim (instant) · sim arm (interactive) · demo2 · learn")}`,value:"embodied"},{name:` ${chalk.bold("International Olympiad")} ${chalk.gray("—")} ${chalk.gray("CTF × AI (~500MB, advanced)")}`,value:"olympiad"},{name:` ${chalk.bold("National/Regional Partner")} ${chalk.gray("—")} ${chalk.gray("organizer tools (tokens, competitions)")}`,value:"organizer"},{name:` ${chalk.gray("About ICOA")} ${chalk.gray("·")} ${chalk.gray("Info & contact")}`,value:"about"}];console.log(chalk.gray(" Use ")+chalk.yellow("↑")+chalk.gray(" or ")+chalk.yellow("↓")+chalk.gray(" to select, ")+chalk.yellow("Enter")+chalk.gray(" to confirm.")),console.log();let yo="";for(;!yo;){const o=await F({message:"Mode",choices:go,default:co||"selection"});"about"!==o?yo=o:(console.clear(),console.log(),console.log(chalk.cyan(" ═══════════════════════════════════════════════════")),console.log(chalk.bold.yellow(" ICOA")+chalk.white(" — AI-Native CLI OS for Cyber & AI Security")),console.log(chalk.gray(" Olympiad & Competition · K-12 to University")),console.log(chalk.cyan(" ───────────────────────────────────────────────────")),console.log(),console.log(chalk.bold.white(" What Makes ICOA Different")),console.log(chalk.gray(" · AI-native AI teammate, AI adversary, AI translation")),console.log(chalk.gray(" · CLI OS Complete competition environment in terminal")),console.log(chalk.gray(" · 110 tools pwntools, z3, gdb, nmap, sleuthkit... pre-configured")),console.log(chalk.gray(" · Global scale 15,000+ concurrent exams · 15 languages")),console.log(),console.log(chalk.bold.white(" Competition Format")),console.log(` ${chalk.green.bold("AI4CTF")}${chalk.gray(" [Day 1] AI as teammate — 5hr jeopardy CTF")}`),console.log(` ${chalk.red.bold("CTF4AI")}${chalk.gray(" [Day 2] Challenge AI — adversarial ML, red-team")}`),console.log(` ${chalk.cyan.bold("CTF4VLA")}${chalk.gray(" [Pioneer Round] Embodied AI — attack robot brains (NEW)")}`),console.log(),console.log(chalk.white(" Sydney, Australia")+chalk.gray(" · Jun 27 - Jul 2, 2026 · 40+ countries")),console.log(),console.log(chalk.bold.white(" Organized by")+chalk.gray(" ASRA (Australia) · ICO Foundation Inc")),console.log(chalk.bold.white(" Contact ")+chalk.cyan(" australia@icoa2026.au · accreditation@icoa2026.au")),console.log(chalk.bold.white(" Website ")+chalk.cyan.underline(" https://icoa2026.au")),console.log(chalk.cyan(" ═══════════════════════════════════════════════════")),console.log(),console.log(chalk.gray(" Press ")+chalk.yellow("Enter")+chalk.gray(" to return...")),await new Promise(o=>{const e=l=>{process.stdin.removeListener("data",e),process.stdin.isTTY&&process.stdin.setRawMode&&process.stdin.setRawMode(!1),process.stdin.pause(),o()};process.stdin.isTTY&&process.stdin.setRawMode&&process.stdin.setRawMode(!0),process.stdin.resume(),process.stdin.once("data",e)}),console.clear())}if("olympiad"===yo&&"olympiad"!==co&&(console.log(),console.log(chalk.yellow(" This mode will download ~500MB of CTF tools and AI models.")),await io({message:"Continue?",default:!0})||(yo="selection",console.log(chalk.gray(" Switched to National Selection mode.")))),yo!==co&&s({mode:yo}),console.log(),"olympiad"===yo&&m(no)){d(no),console.log(chalk.gray(" Checking competition environment..."));const{execSync:o}=await import("node:child_process"),e=[{name:"pwntools",cmd:'python3 -c "import pwn"'},{name:"z3-solver",cmd:'python3 -c "import z3"'},{name:"numpy",cmd:'python3 -c "import numpy"'},{name:"requests",cmd:'python3 -c "import requests"'}];let l=0;for(const t of e)try{o(t.cmd,{stdio:"ignore"})}catch{l++}if(l>0){console.log(chalk.yellow(` ${l} core libraries missing.`));try{const{confirm:o}=await import("@inquirer/prompts");if(await o({message:" Install competition Python libraries now?",default:!0,theme:{prefix:"",style:{message:o=>chalk.green(o),defaultAnswer:o=>chalk.green(o)}}})){console.log();const{execSync:o}=await import("node:child_process");o("icoa env setup",{stdio:"inherit"})}}catch{console.log(chalk.gray(" Run ")+chalk.white("env setup")+chalk.gray(" later to install."))}console.log()}else console.log(chalk.green(" All core libraries ready.")),console.log()}if(j){const o=y();if(o){const e=Math.floor(o.awaySeconds/60),l=o.awaySeconds%60;console.log(chalk.yellow(` Session resumed. Away: ${e}m ${l}s | Total exits: ${o.exitCount}`)),console.log()}}if("selection"===yo)so();else if("embodied"===yo){console.log(chalk.cyan.bold(" [Embodied AI Security 🤖]")),console.log(),console.log(chalk.bold.cyan(" CTF4VLA")+chalk.gray(" — ICOA 2026's ")+chalk.bold.white("Pioneer Round")),console.log(chalk.gray(" an independent parallel track alongside the scored main events: ")+chalk.green("AI4CTF")+chalk.gray(" (Day 1) and ")+chalk.red("CTF4AI")+chalk.gray(" (Day 2)")),console.log(),console.log(chalk.white(" Embodied AI is at its ImageNet moment.")),console.log(chalk.gray(" VLA models, MuJoCo physics, real robot arms.")),console.log(chalk.gray(" Real models, real physics, real attack surfaces.")),console.log(),console.log(chalk.gray(" ─────────────────────────────────────────────"));const o=O()>0||E()>0,e=S()>0,l=$(),t=T(),n=null!==t&&"number"==typeof t.completedAt&&t.nextCardIndex>=t.totalCards,s=null!==t&&!n;if(n)console.log(chalk.bold.yellow(" Continue: ")+chalk.bold.cyan("④ learn LEARNDEMO01")+chalk.gray(" (demo2 ✓ · sim")+(e?chalk.gray(" ✓ · sim arm ✓)"):chalk.gray(")")));else if(s){const o=`${t.nextCardIndex} / ${t.totalCards}`;console.log(chalk.bold.yellow(" Continue: ")+chalk.bold.cyan("③ demo2")+chalk.gray(" (last left at card ")+chalk.bold.yellow(o)+chalk.gray(")"))}else o&&e?console.log(chalk.bold.yellow(" Next up: ")+chalk.bold.cyan("③ demo2")+chalk.gray(" → ")+chalk.bold.cyan("④ learn LEARNDEMO01")+chalk.gray(" (sim ✓ · sim arm ✓)")):l?console.log(chalk.bold.yellow(" Next up: ")+(e?chalk.bold.cyan("① sim")+chalk.gray(" → ")+chalk.bold.cyan("③ demo2"):chalk.bold.cyan("② sim arm")+chalk.gray(" → ")+chalk.bold.cyan("③ demo2"))+chalk.gray(" → ")+chalk.bold.cyan("④ learn LEARNDEMO01")):console.log(chalk.bold.yellow(" First time? Try in order: ")+chalk.bold.cyan("① sim")+chalk.gray(" → ")+chalk.bold.cyan("② sim arm")+chalk.gray(" → ")+chalk.bold.cyan("③ demo2")+chalk.gray(" → ")+chalk.bold.cyan("④ learn LEARNDEMO01"));console.log(chalk.gray(" ─────────────────────────────────────────────")),console.log(chalk.bold.green(" sim")+chalk.gray(" ")+chalk.bold.cyan("①")+chalk.gray(" ")+chalk.bold.yellow("★ INSTANT")+chalk.gray(" — 8-robot group dance, no wait, no setup")),console.log(chalk.bold.green(" sim arm")+chalk.gray(" ")+chalk.bold.cyan("②")+chalk.gray(" interactive 6-DOF arm sandbox — type joint values, watch")),console.log(chalk.bold.green(" demo2")+chalk.gray(" ")+chalk.bold.cyan("③")+chalk.gray(" ~8 min interactive intro + live MuJoCo sim")),console.log(chalk.bold.green(" learn LEARNDEMO01")+chalk.gray(" ")+chalk.bold.cyan("④")+chalk.gray(" free 11-card intro (paste this command as-is)")),console.log(chalk.bold.green(" learn ")+chalk.bold.yellow("EAxxxxxxxx")+chalk.gray(" full 100/480-card curriculum (team-issued)")),console.log(chalk.bold.green(" exam ")+chalk.bold.yellow("PDxxxxxxxx")+chalk.gray(" Paper D (CTF4VLA) — national selection contestants")),console.log(chalk.gray(" ─────────────────────────────────────────────")),console.log(),console.log(chalk.gray(" Three open tiers: ")+chalk.green("free 11")+chalk.gray(" · ")+chalk.yellow("registered 100")+chalk.gray(" · ")+chalk.bold.magenta("national team 480")+chalk.gray(" (PhD-ready)")),console.log(chalk.gray(" Country team contact: ")+chalk.cyan("australia@icoa2026.au")),console.log(),h(),console.log()}else"organizer"===yo?(console.log(chalk.yellow.bold(" [National/Regional Partner]")),console.log(),console.log(chalk.bold.white(" ██╗ ██████╗ ██████╗ █████╗")),console.log(chalk.bold.white(" ██║██╔════╝██╔═══██╗██╔══██╗")),console.log(chalk.bold.white(" ██║██║ ██║ ██║███████║")),console.log(chalk.bold.white(" ██║██║ ██║ ██║██╔══██║")),console.log(chalk.bold.white(" ██║╚██████╗╚██████╔╝██║ ██║")),console.log(chalk.bold.white(" ╚═╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝")),console.log(),console.log(chalk.yellow(" International Cyber Olympiad in AI 2026")),console.log(chalk.bold.magenta(" The World's First AI-Native CLI Operating System")),console.log(chalk.bold.magenta(" for Cybersecurity & AI Security Competition")),console.log(chalk.bold.magenta(" and Olympiad for K-12")),console.log(chalk.gray(" Sydney, Australia · Jun 27 - Jul 2, 2026")),console.log(),console.log(chalk.white(" Vision")),console.log(chalk.gray(" Building a global pipeline for youth cyber & AI")),console.log(chalk.gray(" security talent through education and competition.")),console.log(),console.log(chalk.white(" Capacity")),console.log(chalk.gray(" 15,000+ concurrent online examinations")),console.log(chalk.gray(" National selection, training, and education support")),console.log(),console.log(chalk.white(" Olympic Spirit")),console.log(chalk.gray(" Excellence · Friendship · Respect")),console.log(),console.log(chalk.gray(" ─────────────────────────────────────────────")),console.log(chalk.white(" New country accreditation & support:")),console.log(chalk.cyan(" australia@icoa2026.au")),console.log(chalk.cyan(" accreditation@icoa2026.au")),console.log(chalk.gray(" ─────────────────────────────────────────────")),console.log(),N?(console.log(chalk.green(` Logged in as ${R.userName}`)),console.log(chalk.white(" exam list")+chalk.gray(" Manage exams")),console.log(chalk.white(" logout")+chalk.gray(" Disconnect"))):console.log(chalk.white(" join <url>")+chalk.gray(" Connect to manage exams")),console.log(),h(),console.log()):q&&!c()?(console.log(chalk.red(" Token was activated on a different device.")),console.log(chalk.gray(" Contact organizer for assistance.")),console.log()):N?(console.log(chalk.green.bold(` Welcome back, ${R.userName}!`)),console.log(chalk.gray(` Connected to ${R.ctfdUrl}`)),console.log(),console.log(chalk.gray(" ─────────────────────────────────────────────")),console.log(chalk.white(" Ready to compete? Start here:")),console.log(),console.log(chalk.bold.cyan(" challenges")+chalk.gray(" Browse challenges by category")),console.log(chalk.white(" status")+chalk.gray(" Your score & hint budget")),console.log(chalk.white(" scoreboard")+chalk.gray(" Live rankings")),console.log(chalk.white(" help")+chalk.gray(" Full command list")),console.log(),console.log(chalk.gray(" Tool environment:")),console.log(chalk.white(" env")+chalk.gray(" See which of the 110 CTF tools are installed")),console.log(chalk.white(" env setup")+chalk.gray(" Install anything missing (~5 min, one-time)")),console.log(chalk.gray(" ─────────────────────────────────────────────")),console.log(chalk.gray(" Tip: ")+chalk.cyan("help")+chalk.gray(" · ")+w()+chalk.gray(" · ")+chalk.cyan("Ctrl+C")+chalk.gray(" pauses · ")+chalk.cyan("quit")+chalk.gray(" closes")),console.log()):q?(G(eo)||K(eo,{recursive:!0}),console.log(chalk.green.bold(" Welcome, competitor!")),console.log(chalk.gray(` Workspace: ${eo}`)),console.log(),console.log(chalk.gray(" ─────────────────────────────────────────────")),console.log(chalk.white(" Get started:")),console.log(),console.log(chalk.white(" Step 1 ")+chalk.bold.cyan("join <url>")+chalk.gray(" Connect to competition server")),console.log(chalk.white(" Step 2 ")+chalk.bold.cyan("challenges")+chalk.gray(" Browse & solve challenges")),console.log(chalk.white(" Step 3 ")+chalk.bold.cyan("ai4ctf")+chalk.gray(" Ask AI when stuck")),console.log(),console.log(chalk.gray(" Before Step 1 — make sure your tools are ready:")),console.log(chalk.white(" env")+chalk.gray(" See which of the 110 CTF tools are installed")),console.log(chalk.white(" env setup")+chalk.gray(" Install anything missing (~5 min, one-time)")),console.log(),console.log(chalk.gray(" Also: ")+chalk.white("help")+chalk.gray(" all commands")),console.log(chalk.gray(" ─────────────────────────────────────────────")),console.log(chalk.gray(" Tip: ")+chalk.cyan("Ctrl+C")+chalk.gray(" pauses · ")+w()+chalk.gray(" · ")+chalk.cyan("quit")+chalk.gray(" closes CLI")),console.log()):(console.log(chalk.bold.white(" Welcome to ICOA CLI — International Olympiad")),console.log(),console.log(chalk.gray(" ─────────────────────────────────────────────")),console.log(chalk.white(" To begin, activate your competition token:")),console.log(),console.log(chalk.bold.cyan(" activate <token>")),console.log(),console.log(chalk.gray(" While waiting, explore:")),console.log(chalk.white(" ref linux")+chalk.gray(" Quick reference for Linux")),console.log(chalk.white(" ref web")+chalk.gray(" Quick reference for Web")),console.log(chalk.white(" env")+chalk.gray(" See which of the 110 CTF tools are installed")),console.log(chalk.white(" env setup")+chalk.gray(" Install anything missing (~5 min, one-time)")),console.log(chalk.white(" help")+chalk.gray(" All available commands")),console.log(chalk.gray(" ─────────────────────────────────────────────")),console.log(chalk.gray(" Tip: ")+chalk.cyan("Ctrl+C")+chalk.gray(" pauses · ")+w()+chalk.gray(" · ")+chalk.cyan("quit")+chalk.gray(" closes CLI")),console.log());e.exitOverride(),e.configureOutput({writeErr:()=>{},writeOut:o=>{console.log(o)}});const mo=o({input:process.stdin,output:process.stdout,prompt:oo(),terminal:!0});f(mo);let po=!1;p(!0),V();const uo=mo.prompt.bind(mo);mo.prompt=o=>{b()||v()||A()||k()||mo.setPrompt(oo()),uo(o)},mo.prompt(),mo.on("line",async o=>{if(po)return;const t=o.trim();if(!t)return mo.setPrompt(b()?chalk.magenta("ai4ctf> "):oo()),void mo.prompt();if("menu"===t||"menu confirm"===t)return P()&&"menu confirm"!==t?(console.log(),console.log(chalk.yellow(" Real exam active. Progress is auto-saved.")),console.log(chalk.gray(" To return to main menu anyway, type ")+chalk.white("menu confirm")),console.log(),void mo.prompt()):void u(mo);if(b()){po=!0;const o=await x(t);return po=!1,"exit"===o&&mo.setPrompt(oo()),void mo.prompt()}if(v()){po=!0;const o=await C(t);return po=!1,"exit"!==o&&"solved"!==o||mo.setPrompt(oo()),void mo.prompt()}if(A()){po=!0;const o=await I(t);return po=!1,"exit"===o&&mo.setPrompt(oo()),mo.setPrompt(A()?chalk.bold.cyan("ctf4vla> "):oo()),void mo.prompt()}if(Y(t),"exit"===t)return L()?(console.log(),console.log(chalk.yellow(" ⚠ An exam is in progress.")),console.log(chalk.white(" To return to menu without losing progress, type: ")+chalk.bold.cyan("back")),console.log(chalk.white(" To fully close ICOA CLI, type: ")+chalk.bold.cyan("quit")),console.log(chalk.gray(" Your progress is auto-saved either way.")),console.log(),void mo.prompt()):(console.log(),console.log(chalk.gray(" ")+chalk.white("exit")+chalk.gray(" returns to the main menu. To fully close ICOA CLI, type ")+chalk.bold.cyan("quit")+chalk.gray(".")),"selection"===yo&&so(),void mo.prompt());if("quit"===t||"q"===t||"quit confirm"===t){const o=L();return o&&"demo-free"!==o.session.examId&&"quit confirm"!==t?(console.log(),console.log(chalk.yellow(" ⚠ A real exam is in progress.")),console.log(chalk.gray(" Your answers are auto-saved on the server, but the exam timer keeps ticking")),console.log(chalk.gray(" on the server side even if you close the CLI.")),console.log(),console.log(chalk.white(" To leave the CLI but keep the exam alive, type: ")+chalk.bold.cyan("back")),console.log(chalk.gray(" (recommended — you can resume with ")+chalk.cyan("exam q 1")+chalk.gray(" after relaunching icoa)")),console.log(),console.log(chalk.white(" To really close ICOA CLI, type: ")+chalk.bold.cyan("quit confirm")),console.log(),void mo.prompt()):(o&&"demo-free"===o.session.examId&&(console.log(),console.log(chalk.gray(" Demo paused. Resume with: ")+chalk.white("demo")+chalk.gray(" (fresh) or ")+chalk.white("exam q 1")+chalk.gray(" (continue)."))),J(),g(),console.log(chalk.gray(" Session saved. Use ")+chalk.white("icoa --resume")+chalk.gray(" to continue.")),M(),void D(0))}if("back"===t){const o=L(),e=o&&"demo-free"!==o.session.examId,l=o&&"demo-free"===o.session.examId&&(()=>{const e=new Date(o.session.startedAt||0).getTime();return Date.now()-e<18e5})();if(e)console.log(),console.log(chalk.gray(" Exam paused. Your progress is saved.")),console.log(chalk.white(" Resume: exam q 1")+chalk.gray(" · ")+chalk.white("exam review")+chalk.gray(" · ")+chalk.white("exam submit")),console.log();else if(l){const e=Object.keys(o.answers).length,l=o.session.questionCount;console.log(),console.log(chalk.gray(` Demo paused (${e}/${l} answered). Resume with: `)+chalk.white("exam q 1")),console.log(chalk.gray(" Or type ")+chalk.white("demo")+chalk.gray(" to restart.")),console.log()}else{if(o&&"demo-free"===o.session.examId){const{clearExamState:o}=await import("./lib/exam-state.js");o("demo-free")}const e=n();fetch("https://practice.icoa2026.au/api/icoa/demo-stats",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({type:"post-report-back",lang:e.language||"en",timestamp:(new Date).toISOString()}),signal:AbortSignal.timeout(5e3)}).catch(()=>{}),"selection"===yo?so():console.log(chalk.gray(" Already at main menu."))}return void mo.prompt()}if("help"===t||"?"===t){if(L()){po=!0;try{await e.parseAsync(["node","icoa","exam","help"])}catch{}return po=!1,void mo.prompt()}return ro(a(),yo),void mo.prompt()}if("man"===t||"manual"===t)return ro(a(),yo),void mo.prompt();if("more help"===t.toLowerCase()&&L()){po=!0;try{await e.parseAsync(["node","icoa","exam","more-help"])}catch{}return po=!1,void mo.prompt()}if("continue"===t.toLowerCase())return console.log(),console.log(chalk.green.bold(" ═══ AI4CTF — AI as Your Teammate ═══")),console.log(),console.log(chalk.white(" In AI4CTF, you solve cybersecurity challenges")),console.log(chalk.white(" with AI by your side.")),console.log(),console.log(chalk.white(" In competition, you get AI help at 3 levels:")),console.log(chalk.yellow(" hint a")+chalk.gray(" General guidance (50 uses)")),console.log(chalk.yellow(" hint b")+chalk.gray(" Deep analysis (10 uses)")),console.log(chalk.yellow(" hint c")+chalk.gray(" Critical assist (2 uses)")),console.log(),console.log(chalk.white(" Try it now! Type: ")+chalk.bold.green("ai4ctf")),console.log(chalk.gray(' Chat freely with your AI teammate. Type "exit" when done.')),console.log(),console.log(chalk.gray(" After ai4ctf, try: ")+chalk.bold.red("ctf4ai")+chalk.gray(' — trick the AI into saying "koala"')),console.log(),void mo.prompt();if(/^ICOA-[A-Z]{2,3}-\d{1,6}$/i.test(t.trim())){po=!0;try{await e.parseAsync(["node","icoa","exam","token",t.trim()])}catch{}return po=!1,void mo.prompt()}if(/^[A-Z]{2}[0-9A-HJKMNP-TV-Z]{8}$/i.test(t.trim())){po=!0;try{await e.parseAsync(["node","icoa","exam","token",t.trim().toUpperCase()])}catch{}return po=!1,void mo.prompt()}const s=t.match(/^exam\s+([A-Z]{2}[0-9A-HJKMNP-TV-Z]{8})$/i);if(s){po=!0;try{await e.parseAsync(["node","icoa","exam","token",s[1].toUpperCase()])}catch{}return po=!1,void mo.prompt()}const y=t.match(/^exam\s+([A-Z]{2,3})$/i);if(y){po=!0;try{await e.parseAsync(["node","icoa","exam","list",y[1]])}catch{}return po=!1,void mo.prompt()}if("clear"===t||"cls"===t)return console.clear(),void mo.prompt();if(t.startsWith("activate ")){const o=t.slice(9).trim(),e=r(o);return"ok"===e?console.log(chalk.green(" Access granted! Token bound to this device.")):"already_bound"===e?(console.log(),console.log(chalk.red(" Token already activated on a different device.")),console.log(chalk.gray(" Each token binds to the first device that uses it. If you lost the device,")),console.log(chalk.gray(" contact your proctor to have the token re-issued for a new device."))):(console.log(),console.log(chalk.red(" Token not recognized.")),console.log(chalk.gray(" Possible reasons:")),console.log(chalk.white(" • ")+chalk.gray("Typo — tokens are case-insensitive, 10 chars, start with a 2-letter country code (e.g. ")+chalk.cyan("UAK7M2R9Q4")+chalk.gray(")")),console.log(chalk.white(" • ")+chalk.gray("Expired — ask your proctor or organizer for a fresh token")),console.log(chalk.white(" • ")+chalk.gray("Network — verify connection to ")+chalk.cyan("practice.icoa2026.au")),console.log(chalk.gray(" Still stuck? type ")+chalk.cyan("help")+chalk.gray(" or try ")+chalk.cyan("exam demo")+chalk.gray(" for a free practice round."))),console.log(),void mo.prompt()}if("activate"===t)return console.log(chalk.gray(" Usage: ")+chalk.white("activate <token>")),console.log(),void mo.prompt();const m=L();if(m){const o=t.toUpperCase().trim(),l=o=>{const e=m.questions.find(e=>e.number===o);return!!e&&("ai4ctf"===e.type||"ctf4ai"===e.type||e.options&&!e.options.A&&!e.options.B)},n=o=>{const e="demo-free"!==m.session.examId,l=e&&o>=39?"ctf4ai":e&&o>=31?"ai4ctf":null;console.log(),console.log(chalk.yellow(` Q${o} is a practical question — letters (A/B/C/D) don't apply here.`)),l?(console.log(chalk.white(" Enter the AI chat for this question: ")+chalk.bold.cyan(l)),console.log(chalk.gray(" Or submit a flag directly: ")+chalk.green(`exam answer ${o} ICOA{your_flag}`))):console.log(chalk.gray(" Submit a flag: ")+chalk.green(`exam answer ${o} ICOA{your_flag}`)),console.log()};if(/^[ABCD]$/.test(o)){const t=m._lastQ||1;if(l(t))return n(t),void mo.prompt();po=!0;try{await e.parseAsync(["node","icoa","exam","answer",String(t),o])}catch{}return po=!1,void mo.prompt()}const s=o.match(/^(\d+)\s+([ABCD])$/);if(s){const o=parseInt(s[1],10);if(l(o))return n(o),void mo.prompt();po=!0;try{await e.parseAsync(["node","icoa","exam","answer",s[1],s[2]])}catch{}return po=!1,void mo.prompt()}}const d=t.split(/\s+/)[0].toLowerCase(),p=/^python3?(\.\d+)?$/.test(d),h="ls"===d||"pwd"===d,w=t.startsWith("!")||d.startsWith("!")||p||h,f=new Set(["nano","vi","vim","emacs","pico","ed","code","cat","less","more","head","tail","ls","pwd","cd","base64","xxd","hexdump","od","openssl","md5sum","sha256sum","grep","find","awk","sed","strings","file","curl","wget","nc","ping","nmap","echo","bash","sh","zsh","pip","pip3","node","npm"]),k=()=>{console.log(chalk.gray(" Shell commands need ")+chalk.bold.cyan("!")+chalk.gray(" prefix. Try: ")+chalk.bold.cyan(`!${t}`)),console.log()};if("embodied"===yo&&!w&&!["demo2","learn","exam","ctf4vla","lang","ref","setup","env","sim"].includes(d))return f.has(d)?(k(),void mo.prompt()):(console.log(chalk.gray(" Not available in Embodied AI Security mode.")),console.log(chalk.white(" Try ")+chalk.bold.cyan("demo2")+chalk.gray(" (intro) · ")+chalk.bold.cyan("learn")+chalk.gray(" (curriculum) · ")+chalk.bold.cyan("exam <PD-token>")+chalk.gray(" (Paper D)")),console.log(),void mo.prompt());if("selection"===yo&&!w&&!["exam","demo","retry","nations","next","prev","continue","setup","lang","ref","ai4ctf","ctf4ai","mark","unmark","review","submit","env","sim"].includes(d)){if(f.has(d))return k(),void mo.prompt();if(console.log(chalk.gray(" Not available in Selection mode.")),m){const o=m._lastQ||1;console.log(chalk.white(` Resume exam: exam q ${o}`)+chalk.gray(" · ")+chalk.white("A/B/C/D")+chalk.gray(" to answer"))}else console.log(chalk.gray(" Try: demo · setup to switch mode"));return console.log(),void mo.prompt()}if("organizer"===yo&&!["join","exam","demo","retry","next","prev","logout","setup","lang","ref","ctf","mark","unmark","review","submit"].includes(d))return console.log(chalk.gray(" Not available in Organizer mode. Switch via: setup")),console.log(),void mo.prompt();if(!("olympiad"!==yo||a()&&c()||i(d)))return console.log(chalk.yellow(" Restricted mode. ")+chalk.gray("Enter your access token:")),console.log(chalk.white(" activate <token>")),console.log(),console.log(chalk.gray(" Free commands: ")+chalk.white("ref [topic]")+chalk.gray(", ")+chalk.white("help")+chalk.gray(", ")+chalk.white("exit")),console.log(),void mo.prompt();if(!["join","activate","challenges","ch","open","submit","flag","scoreboard","sb","status","time","ref","shell","files","connect","note","notes","logbook","log","man","manual","lang","setup","env","ai4ctf","model","ctf","exam","demo","retry","nations","next","prev","continue","logout","ctf4ai","mark","unmark","review","submit","learn","demo2","ctf4vla","theme","sim"].includes(d)){if(lo.has(d))return console.log(chalk.yellow(` "${d}" is a shell command — the ICOA prompt isn't a shell.`)),console.log(chalk.gray(" In real-exam mode, prefix with ! to run inside the sandbox: ")+chalk.cyan(`!${t}`)),console.log(),void mo.prompt();if(/(?:^|\s)(?:\/(?!home\/|Users\/|tmp\/)|\.\.\/|~\/)/.test(t)&&!t.startsWith("cd ")){const o=/(?:^|\s)\/(?!home\/\w+\/icoa-workspace|Users\/\w+\/icoa-workspace|tmp\/)/.test(t),e=/\.\./.test(t);if(o||e)return console.log(chalk.red(" Blocked: access outside workspace is not allowed.")),console.log(chalk.gray(` Workspace: ${eo}`)),console.log(),void mo.prompt()}let o=t.startsWith("!")?t.slice(1).trim():t;if("darwin"===process.platform){const e="/opt/homebrew/opt/python@3.12/bin/python3.12";o=o.replace(/^python3?\s/,`${e} `).replace(/^(python3|python)$/,e)}else if("win32"===process.platform){const e=(()=>{try{return l("py -3 --version",{stdio:["ignore","ignore","ignore"],timeout:1500}),"py -3"}catch{}return"python"})();o=o.replace(/^python3?(\.\d+)?\s/,`${e} `).replace(/^python3?(\.\d+)?$/,e)}else{const e=(()=>{try{return l("which python3.12",{stdio:"ignore"}),"python3.12"}catch{return"python3"}})();o=o.replace(/^python\s/,`${e} `).replace(/^python$/,e)}const e=_(),n=B(t);Q({cwd:e,input:t,riskFlags:n}),n.length>0&&P()&&(console.log(chalk.yellow(` ⚠ Action flagged: ${n.join(", ")} — logged.`)),console.log()),/^(\S*python3?(\.\d+)?)\s*$/.test(o)&&(o=`PYTHONSTARTUP="${function(){const o=H(X(),".icoa");G(o)||K(o,{recursive:!0});const e=H(o,"python-startup.py");return G(e)||Z(e,"# ICOA exam interactive startup — auto-loaded by PYTHONSTARTUP\nimport base64, struct, hashlib, re, json, os, sys, binascii\ntry: import requests\nexcept ImportError: pass\ntry: from Crypto.Cipher import AES\nexcept ImportError: pass\ntry: from Crypto.Util.Padding import pad, unpad\nexcept ImportError: pass\ntry: from pwn import xor, p32, u32, p64, u64\nexcept ImportError: pass\ntry: import bs4\nexcept ImportError: pass\ntry: import numpy as np\nexcept ImportError: pass\n"),e}()}" ${o}`,console.log(),console.log(chalk.cyan(" ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")),console.log(chalk.bold.white(" Python ready — ICOA exam toolkit pre-loaded")),console.log(chalk.cyan(" ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")),console.log(),console.log(chalk.white(" Already imported: ")+chalk.gray("base64, struct, hashlib, re, json, binascii")),console.log(chalk.white(" Also available: ")+chalk.gray("requests, bs4, numpy, AES, pad/unpad, xor, p32/u32/p64/u64")),console.log(),console.log(chalk.yellow(" Quick examples:")),console.log(chalk.gray(' base64.b64decode("aGVsbG8=") ')+chalk.gray("# decode base64")),console.log(chalk.gray(' bytes.fromhex("48656c6c6f") ')+chalk.gray("# hex → bytes")),console.log(chalk.gray(' "ICOA{x}".encode() ')+chalk.gray("# str → bytes")),console.log(chalk.gray(" [chr(c) for c in [73,67,79,65]] ")+chalk.gray("# ASCII codes")),console.log(chalk.gray(' xor(bytes.fromhex("0a2b"), b"IC") ')+chalk.gray("# pwntools XOR")),console.log(),console.log(chalk.gray(" Exit: ")+chalk.white("exit()")+chalk.gray(" or Ctrl-D")),console.log(chalk.cyan(" ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━")),console.log()),po=!0;try{W()&&await U()?await z(o,mo):await ao(o,mo,e)}catch{console.log(chalk.yellow(` Command failed: ${d}`))}return po=!1,console.log(),void mo.prompt()}po=!0;const T=t.trim(),$=T.toLowerCase();let S,O=null,E="";if(m)if("submit"===$)O="final";else if($.startsWith("submit ")){let o=T.slice(7).trim();/^submit\s+/i.test(o)&&(o=o.replace(/^submit\s+/i,"").trim()),o=o.replace(/^["'`]+|["'`]+$/g,"").trim(),o&&/^ICOA\{[^}]*\}?$/i.test(o)&&(O="flag",E=o)}else/^ICOA\{[^}]+\}$/i.test(T)&&(O="flag",E=T);S="final"===O?["exam","submit"]:"flag"===O?["exam","answer",String(m?._lastQ||1),E]:function(o){const e=o.split(/\s+/),l=e[0].toLowerCase(),t=e.slice(1),n={demo:["exam","demo"],retry:["exam","demo-retry"],nations:["exam","nations"],next:["exam","next"],prev:["exam","prev"],mark:["exam","mark",...t],unmark:["exam","unmark",...t],review:["exam","review"],logout:["ctf","logout"],join:["ctf","join",...t],activate:["ctf","activate",...t],challenges:["ctf","challenges"],ch:["ctf","challenges"],open:["ctf","open",...t],submit:["ctf","submit",...t],flag:["ctf","submit",...t],scoreboard:["ctf","scoreboard",...t],sb:["ctf","scoreboard",...t],status:["ctf","status"],time:["ctf","time"]};return n[l]?n[l]:["ref","shell","files","connect","note","notes","logbook","log","man","manual","lang","setup","env","ai4ctf","model","ctf","exam","ctf4ai"].includes(l)?[l,...t]:e}(t);const j="ctf"===S[0]&&"join"===S[1];j&&mo.pause(),process.exit=()=>{throw new Error(to)};try{await e.parseAsync(["node","icoa",...S])}catch(o){const e=o instanceof Error?o.message:String(o);if(e===to);else if(e.includes("commander.unknownCommand")){const{distance:o}=await import("fastest-levenshtein"),e=["ctf","ref","shell","files","connect","note","notes","logbook","log","manual","lang","setup","env","ai4ctf","exam","ctf4ai","theme","clear","cls","quit","exit","back","menu","help","continue","activate","demo","challenges","status","scoreboard","join","logout"],l=d.split(/\s+/)[0]||d;let t={word:"",dist:1/0};for(const n of e){const e=o(l.toLowerCase(),n);e<t.dist&&(t={word:n,dist:e})}console.log(chalk.yellow(` Unknown command: ${d}.`)),t.dist>0&&t.dist<=2&&console.log(chalk.gray(" Did you mean: ")+chalk.bold.cyan(t.word)+chalk.gray("?")),console.log(chalk.gray(" Type ")+chalk.cyan("help")+chalk.gray(" for the full command list."))}else e.includes("commander.")||(e.includes("fetch failed")||e.includes("ECONNREFUSED")||e.includes("ETIMEDOUT"))&&console.log(chalk.yellow(" Network error. Check your connection."))}finally{process.exit=D,po=!1,j&&mo.resume()}b()?mo.setPrompt(chalk.magenta("ai4ctf> ")):v()?mo.setPrompt(chalk.red("ctf4ai> ")):A()&&mo.setPrompt(chalk.bold.cyan("ctf4vla> ")),console.log(),mo.prompt()}),mo.on("SIGINT",()=>{if(console.log(),b()||v())console.log(chalk.yellow(" Ctrl+C did not close ICOA CLI — you are still in the AI chat.")),console.log(chalk.white(" Type ")+chalk.bold.cyan("exit")+chalk.white(" to leave the chat and return to the menu."));else if(L()){const o="demo-free"!==L().session.examId;console.log(chalk.yellow(" Ctrl+C did NOT close ICOA CLI.")),console.log(chalk.gray(` Your ${o?"exam":"demo"} is paused and every answer is auto-saved.`)),console.log(),console.log(chalk.white(" Resume: ")+chalk.cyan("exam q 1")+chalk.gray(" · Back to menu: ")+chalk.cyan("back")+chalk.gray(" · Close CLI: ")+chalk.cyan(o?"quit confirm":"quit"))}else console.log(chalk.yellow(" Ctrl+C did not close ICOA CLI — you are still at the ")+chalk.cyan("icoa>")+chalk.yellow(" prompt.")),console.log(chalk.gray(" Keep typing — ")+chalk.cyan("help")+chalk.gray(" lists commands. (Only ")+chalk.cyan("quit")+chalk.gray(" or Ctrl+D actually close the CLI.)"));console.log(),mo.prompt()}),mo.on("close",()=>{J(),g(),M(),D(0)})}function ao(o,l,t){return new Promise(n=>{const s=process.stdin,a=!!s.isTTY&&!!s.isRaw;if(l.pause(),s.isTTY&&"function"==typeof s.setRawMode)try{s.setRawMode(!1)}catch{}const r=e(o,{shell:!0,stdio:"inherit",cwd:t||process.cwd()}),i=()=>{if(s.isTTY&&"function"==typeof s.setRawMode&&a)try{s.setRawMode(!0)}catch{}l.resume(),n()};r.on("close",i),r.on("error",i)})}function ro(o,e="olympiad"){return console.log(),"selection"===e||"organizer"===e?(console.log(chalk.bold.white(" Exam")),console.log(chalk.white(" join <url> ")+chalk.gray("Connect to exam server")),console.log(chalk.white(" exam list ")+chalk.gray("Available exams")),console.log(chalk.white(" exam start <id> ")+chalk.gray("Begin an exam")),console.log(chalk.white(" exam q [n] ")+chalk.gray("View questions")),console.log(chalk.white(" exam answer <n> <X> ")+chalk.gray("Answer question")),console.log(chalk.white(" exam review ")+chalk.gray("Review all answers")),console.log(chalk.white(" exam submit ")+chalk.gray("Submit for grading")),console.log(chalk.white(" exam result ")+chalk.gray("View your score")),console.log(),console.log(chalk.bold.white(" System")),console.log(chalk.white(" ref [topic] ")+chalk.gray("Quick reference")),console.log(chalk.white(" setup ")+chalk.gray("Settings / switch mode")),console.log(chalk.white(" lang [code] ")+chalk.gray("Switch language")),console.log(chalk.white(" clear ")+chalk.gray("Clear screen")),console.log(chalk.white(" exit ")+chalk.gray("Quit")),void console.log()):o?(console.log(chalk.cyan(" ═══════════════════════════════════════════════")),console.log(chalk.bold.white(" How it works")),console.log(),console.log(chalk.gray(" 1. Browse ")+chalk.white("challenges")+chalk.gray(" and pick one")),console.log(chalk.gray(" 2. ")+chalk.white("open <id>")+chalk.gray(" to read the challenge")),console.log(chalk.gray(" 3. Use ")+chalk.white("ai4ctf")+chalk.gray(" to chat with AI when stuck")),console.log(chalk.gray(" 4. ")+chalk.white("submit <id> icoa{flag}")+chalk.gray(" to score points")),console.log(chalk.gray(" 5. Check ")+chalk.white("scoreboard")+chalk.gray(" to track your rank")),console.log(chalk.cyan(" ═══════════════════════════════════════════════")),console.log(),console.log(chalk.bold.white(" Competition")),console.log(chalk.white(" join <url> ")+chalk.gray("Connect to CTFd")),console.log(chalk.white(" challenges (ch) ")+chalk.gray("List challenges by category")),console.log(chalk.white(" open <id> ")+chalk.gray("Read challenge + get next steps")),console.log(chalk.white(" submit <id> <flag> ")+chalk.gray("Submit a flag")),console.log(chalk.white(" scoreboard (sb) ")+chalk.gray("Live rankings")),console.log(chalk.white(" status ")+chalk.gray("Your score, budget & timer")),console.log(chalk.white(" time ")+chalk.gray("Countdown timer")),console.log(),console.log(chalk.bold.white(" AI Teammate")+chalk.gray(" — 3 levels, use wisely")),console.log(chalk.white(' hint "question" ')+chalk.gray("Level A — General guidance (50 uses)")),console.log(chalk.white(' hint-b "question" ')+chalk.gray("Level B — Deep analysis (10 uses)")),console.log(chalk.white(' hint-c "question" ')+chalk.gray("Level C — Critical assist (2 uses)")),console.log(chalk.white(" hint budget ")+chalk.gray("Check remaining uses")),console.log(chalk.white(" ai4ctf ")+chalk.gray("Free-chat with AI (no limit)")),console.log(),console.log(chalk.bold.white(" Tools")),console.log(chalk.white(" ref [topic] ")+chalk.gray("Quick reference (linux, web, crypto...)")),console.log(chalk.white(" shell ")+chalk.gray("Docker sandbox")),console.log(chalk.white(" files <id> ")+chalk.gray("Download challenge files")),console.log(chalk.white(" connect <id> ")+chalk.gray("Connect to remote target")),console.log(chalk.white(" note [text] ")+chalk.gray("Add a logbook entry (in-exam: tags current Q)")),console.log(chalk.white(" logbook [n] ")+chalk.gray("View your logbook (in-exam: filter by Q)")),console.log(chalk.white(" log ")+chalk.gray("Session history")),console.log(chalk.white(" man / manual ")+chalk.gray("Show this command list (works in exam too, does not burn elimination)")),console.log(),console.log(chalk.bold.white(" System")),console.log(chalk.white(" setup ")+chalk.gray("Configure settings")),console.log(chalk.white(" lang [code] ")+chalk.gray("Switch language (15 supported)")),console.log(chalk.white(" logout ")+chalk.gray("Disconnect")),console.log(chalk.white(" clear ")+chalk.gray("Clear screen")),console.log(chalk.white(" exit ")+chalk.gray("Quit (session saved)")),void console.log()):(console.log(chalk.bold.yellow(" Restricted Mode — activate with a token to unlock all commands")),console.log(),console.log(chalk.white(" activate <token> ")+chalk.gray("Unlock full access")),console.log(chalk.white(" ref [topic] ")+chalk.gray("Quick reference")),console.log(chalk.white(" exit ")+chalk.gray("Quit")),void console.log())}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "icoa-cli",
3
- "version": "2.19.195",
3
+ "version": "2.19.197",
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": {
@@ -9,7 +9,6 @@
9
9
  "files": [
10
10
  "dist",
11
11
  "refs",
12
- "translations",
13
12
  "assets"
14
13
  ],
15
14
  "scripts": {
Binary file
@@ -1,9 +0,0 @@
1
- {
2
- "id": 1,
3
- "name": "Incorrect Implementation of RSA",
4
- "category": "crypto",
5
- "translation": "لقد تعلمت للتو عن Rivest-Shamir-Aldeman، ولذلك قمت بإنشاء تطبيق خاص بي. إليكم الرسالة:\n\n```\nn: 16537241065399537261146800802060451995107796665337288928060948677362154976656429797729550619497788311160926523026781503470362013597201944839389519773564618679827061417896265475971561610333659217333638238386907603525565178455941971399130722191602944445714002268747028340120907894781607422707823554701443768586256913491149809410232167277063066105859165079765281480076330718726350243973636606134346374770537701812923215229226027759112780757449828410180237267791126609342382918352166823253106960191346933601235547281\ne: 5\nciphertext: [17623416832, 10510100501, 9509900499, 8587340257, 16105100000, 28153056843, 16850581551, 12166529024, 7737809375, 12762815625, 7737809375, 19254145824, 10510100501, 8587340257, 14693280768, 14693280768, 25937424601, 7737809375, 21003416576, 12166529024, 16850581551, 21924480357, 11592740743, 12166529024, 21003416576, 7737809375, 12762815625, 7737809375, 12166529024, 8587340257, 10000000000, 7737809375, 21003416576, 12166529024, 8587340257, 21003416576, 7737809375, 10000000000, 16850581551, 16105100000, 10510100501, 7737809375, 9509900499, 254803968, 19254145824, 19254145824, 345025251, 9509900499, 21003416576, 14693280768, 25937424601, 7737809375, 282475249, 282475249, 459165024, 312500000, 601692057, 30517578125]\n```",
6
- "lang": "ar",
7
- "model": "gemini-3.1-pro-preview",
8
- "timestamp": "2026-04-08T03:45:44.709Z"
9
- }
@@ -1,9 +0,0 @@
1
- {
2
- "id": 10,
3
- "name": "The Perfect Breakfast",
4
- "category": "crypto",
5
- "translation": "آه، الفطور. لحظة بزوغ الشمس من الأفق، لا شيء يضاهي رائحة شيء يتشوح على الموقد. لا أفوته أبدًا، ليس لأنني شخص صباحي، بل لأن الفطور هو المكان الذي أجد فيه دعوتي الحقيقية. البعض يفضل حبوب الإفطار، والبعض الآخر الخبز المحمص، أما أنا؟ أحب أن أبقي الأشياء مقرمشة.\n\nهناك فن في روتيني الصباحي. بيضتان، سائلتان قليلاً. كوب من القهوة، سوداء. والجوهرة التاجية: ذلك الكمال المدخن والمالح الذي لا يفشل أبدًا في رسم ابتسامة على وجهي. مفضلتي المطلقة. إنه إسراف بسيط، بالتأكيد، لكنه يستحق كل قضمة.\n\nيقولون إن الفطور هو أهم وجبة في اليوم… ربما لهذا السبب أخفيت الرسالة هناك. عليك فقط أن تعرف أين تبحث تحت الطبقات.",
6
- "lang": "ar",
7
- "model": "gemini-3.1-pro-preview",
8
- "timestamp": "2026-04-08T03:46:38.220Z"
9
- }
@@ -1,9 +0,0 @@
1
- {
2
- "id": 11,
3
- "name": "Wise Words",
4
- "category": "crypto",
5
- "translation": "لقد قابلت أغسطس ذات مرة، الابن بالتبني والوريث لجنرال عظيم. عندما سألته عن أعظم استراتيجياته، اكتفى بالهمس ببساطة: Fwfo_Djqifsaa_Fwpmwf",
6
- "lang": "ar",
7
- "model": "gemini-3.1-pro-preview",
8
- "timestamp": "2026-04-08T03:46:43.627Z"
9
- }
@@ -1,9 +0,0 @@
1
- {
2
- "id": 12,
3
- "name": "HexedHeaders",
4
- "category": "forensics",
5
- "translation": "يبدو أن هذا الملف يحتوي على أسرار... ولكن كيف السبيل للدخول...",
6
- "lang": "ar",
7
- "model": "gemini-3.1-pro-preview",
8
- "timestamp": "2026-04-08T03:46:46.383Z"
9
- }
@@ -1,9 +0,0 @@
1
- {
2
- "id": 13,
3
- "name": "Keylogger",
4
- "category": "forensics",
5
- "translation": "بعد أن شعر بأن هناك شيئًا غير صحيح، أبلغ Ole فريق الأمن بالأمر. قرر الفريق التحقيق في الشبكة ولاحظ شيئًا مريبًا.",
6
- "lang": "ar",
7
- "model": "gemini-3.1-pro-preview",
8
- "timestamp": "2026-04-08T03:46:50.263Z"
9
- }
@@ -1,9 +0,0 @@
1
- {
2
- "id": 14,
3
- "name": "obfuscated script",
4
- "category": "forensics",
5
- "translation": "عثر أحد الموظفين على ملفين غريبين في مجلد Downloads folder الخاص بهم: a script وملف لم يتمكنوا من قراءته. هل يمكنك معرفة ما هي؟",
6
- "lang": "ar",
7
- "model": "gemini-3.1-pro-preview",
8
- "timestamp": "2026-04-08T03:46:56.791Z"
9
- }