icoa-cli 2.19.29 → 2.19.31

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.
@@ -31,9 +31,70 @@ function drawTokenBar() {
31
31
  console.log(chalk.gray(' Tokens: ') + color('█'.repeat(filled)) + chalk.gray('░'.repeat(empty)) + chalk.gray(` ${used}/${cap} (${pct}%)`));
32
32
  }
33
33
  const DEMO_FLAG = 'icoa{w3lc0me_2_ai4ctf}';
34
+ // Scripted hints for the built-in Base64 demo challenge. The hint philosophy:
35
+ // - a: nudge you toward the fingerprint (padding, charset).
36
+ // - b: tell you the encoding name, nothing more. No shell command.
37
+ // - c: for simple challenges, c deliberately adds no new info — hint b was
38
+ // already enough. Instead c explains the hint principle and reminds the
39
+ // user how to run a shell command inside ai4ctf (the `!` prefix).
40
+ // This mirrors real competition behavior where trivial challenges cap at hint b.
41
+ const DEMO_HINTS = {
42
+ a: [
43
+ 'The string ends with "==" and uses only letters, digits, "+", "/", and "=".',
44
+ 'That pattern is a fingerprint — you have seen it before.',
45
+ 'Where is "=" typically used as padding?',
46
+ ],
47
+ b: [
48
+ 'This is Base64 encoded. Decode the string to find the flag.',
49
+ ],
50
+ c: [
51
+ 'Hints never give you the answer directly — they only point you in the right direction.',
52
+ 'For simple challenges like this one, hint c adds nothing extra:',
53
+ 'hint b already tells you everything you need.',
54
+ '',
55
+ 'If you do not remember how to decode Base64, ask your AI teammate —',
56
+ 'just type a question like: how do I decode Base64 on the command line?',
57
+ '',
58
+ 'To run a shell command inside ai4ctf, prefix it with "!". For example:',
59
+ '',
60
+ ' !echo aWNvYXt3M2xjMG1lXzJfYWk0Y3RmfQ== | base64 -d',
61
+ ],
62
+ };
63
+ function showDemoHint(tier) {
64
+ const title = tier === 'a' ? t('ai4ctfHintA') : tier === 'b' ? t('ai4ctfHintB') : t('ai4ctfHintC');
65
+ const tierLabel = `Hint ${tier.toUpperCase()}`;
66
+ const color = tier === 'a' ? chalk.green : tier === 'b' ? chalk.yellow : chalk.red;
67
+ console.log();
68
+ console.log(color.bold(` ▸ ${tierLabel} `) + chalk.gray(title));
69
+ console.log();
70
+ for (const line of DEMO_HINTS[tier]) {
71
+ if (line === '')
72
+ console.log();
73
+ else
74
+ console.log(chalk.white(' ' + line));
75
+ }
76
+ console.log();
77
+ if (tier === 'a') {
78
+ console.log(chalk.gray(' Stuck? Try: ') + chalk.cyan('hint b'));
79
+ console.log();
80
+ }
81
+ else if (tier === 'b') {
82
+ console.log(chalk.gray(' Really stuck? Try: ') + chalk.cyan('hint c'));
83
+ console.log();
84
+ }
85
+ // No trailing CTA after hint c — the content itself explains everything.
86
+ }
34
87
  export async function handleChatMessage(input) {
35
88
  if (!chatSession)
36
89
  return 'exit';
90
+ // Scripted demo hints — intercept before the AI chat so that typing
91
+ // `hint a` / `hint b` / `hint c` behaves like a real competition command
92
+ // instead of becoming a generic AI chat turn.
93
+ const hintMatch = input.trim().toLowerCase().match(/^hint\s+([abc])$/);
94
+ if (hintMatch) {
95
+ showDemoHint(hintMatch[1]);
96
+ return 'continue';
97
+ }
37
98
  // Flag submission
38
99
  const submitMatch = input.match(/^submit\s+(.+)/i);
39
100
  if (submitMatch) {
@@ -197,13 +258,20 @@ export function registerAi4ctfCommand(program) {
197
258
  console.log(chalk.gray(` ${t('ai4ctfHintCUses')}`));
198
259
  console.log();
199
260
  console.log(chalk.gray(' ─────────────────────────────────────────'));
200
- console.log(chalk.white(` ${t('ai4ctfTryNow')}`));
201
- console.log(chalk.gray(` ${t('ai4ctfExample')}`));
202
- console.log(chalk.gray(` ${t('ai4ctfFreeChat')}`));
261
+ console.log(chalk.bold.white(' 👉 New here? Start with the hints in order:'));
262
+ console.log(' ' + chalk.cyan('hint a') + chalk.gray(' → nudge'));
263
+ console.log(' ' + chalk.cyan('hint b') + chalk.gray(' → technique'));
264
+ console.log(' ' + chalk.cyan('hint c') + chalk.gray(' → principle + shell reminder'));
265
+ console.log(chalk.gray(' (hints guide you — they never give the answer directly)'));
266
+ console.log();
267
+ console.log(chalk.white(' Or chat freely with your AI teammate — ask anything'));
268
+ console.log(chalk.gray(' about the challenge. Example: ') + chalk.white('"what encoding is this?"'));
203
269
  console.log();
204
270
  console.log(chalk.yellow(` ${t('ai4ctfCommands')}`));
205
- console.log(chalk.white(' submit <flag>') + chalk.gray(` ${t('ai4ctfSubmitCmd')}`));
206
- console.log(chalk.white(' !<command>') + chalk.gray(` ${t('ai4ctfShellCmd')}`));
271
+ console.log(chalk.white(' hint a / b / c ') + chalk.gray('pre-written hints (safe to use)'));
272
+ console.log(chalk.white(' submit <flag> ') + chalk.gray(t('ai4ctfSubmitCmd')));
273
+ console.log(chalk.white(' !<shell cmd> ') + chalk.gray('run a shell command'));
274
+ console.log(chalk.gray(' e.g. ') + chalk.white('!echo aWNv... | base64 -d'));
207
275
  console.log(chalk.gray(` exit ${t('ai4ctfEndSession')}`));
208
276
  console.log();
209
277
  drawTokenBar();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "icoa-cli",
3
- "version": "2.19.29",
3
+ "version": "2.19.31",
4
4
  "description": "ICOA CLI — The world's first CLI-native CTF competition terminal",
5
5
  "type": "module",
6
6
  "bin": {