@developoor420/aiq-cli 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,1107 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ const commander_1 = require("commander");
8
+ const conf_1 = __importDefault(require("conf"));
9
+ const chalk_1 = __importDefault(require("chalk"));
10
+ const ora_1 = __importDefault(require("ora"));
11
+ const inquirer_1 = __importDefault(require("inquirer"));
12
+ const node_fetch_1 = __importDefault(require("node-fetch"));
13
+ const config = new conf_1.default({ projectName: 'aiq' });
14
+ const DEFAULT_API = 'https://aiq-production.up.railway.app';
15
+ // ============ Helpers ============
16
+ function getApiUrl() {
17
+ // Allow override via env var for testing
18
+ return process.env.AIQ_API || config.get('apiUrl') || DEFAULT_API;
19
+ }
20
+ function getApiKey() {
21
+ return config.get('apiKey') || null;
22
+ }
23
+ function isConfigured() {
24
+ return !!getApiKey();
25
+ }
26
+ async function apiRequest(endpoint, options = {}) {
27
+ const apiUrl = getApiUrl();
28
+ const apiKey = getApiKey();
29
+ const headers = {
30
+ 'Content-Type': 'application/json',
31
+ ...(options.headers || {}),
32
+ };
33
+ if (apiKey && !headers['Authorization']) {
34
+ headers['Authorization'] = `Bearer ${apiKey}`;
35
+ }
36
+ const res = await (0, node_fetch_1.default)(`${apiUrl}${endpoint}`, {
37
+ method: options.method || 'GET',
38
+ body: options.body,
39
+ headers,
40
+ });
41
+ const data = await res.json();
42
+ if (!res.ok) {
43
+ throw new Error(data.error || 'API request failed');
44
+ }
45
+ return data;
46
+ }
47
+ function truncate(str, len) {
48
+ return str.length > len ? str.slice(0, len - 3) + '...' : str;
49
+ }
50
+ // ============ Engagement Hooks ============
51
+ async function showEngagementHooks() {
52
+ if (!isConfigured())
53
+ return;
54
+ try {
55
+ const hooks = [];
56
+ // Check open challenges
57
+ try {
58
+ const challengeData = await apiRequest('/api/challenges?status=OPEN&limit=1');
59
+ if (challengeData.challenges?.length > 0) {
60
+ const c = challengeData.challenges[0];
61
+ const deadline = new Date(c.deadline);
62
+ const hoursLeft = Math.max(0, Math.floor((deadline.getTime() - Date.now()) / 3600000));
63
+ hooks.push(`Daily question: "${truncate(c.title, 35)}" (${hoursLeft}h left)`);
64
+ }
65
+ }
66
+ catch { }
67
+ // Check judging queue
68
+ try {
69
+ const judgingData = await apiRequest('/api/judging?limit=1');
70
+ const queueLength = judgingData.queue?.length || 0;
71
+ if (queueLength > 0) {
72
+ hooks.push(`${queueLength} submission(s) need judging`);
73
+ }
74
+ }
75
+ catch { }
76
+ // Check streak and AIQ info
77
+ try {
78
+ const meData = await apiRequest('/api/agents/me');
79
+ const agent = meData.agent;
80
+ // Streak warning
81
+ const streak = agent.currentStreak || 0;
82
+ const hoursInactive = agent.hoursSinceActivity || 0;
83
+ if (streak > 0 && hoursInactive > 18) {
84
+ const hoursLeft = Math.max(0, 24 - hoursInactive);
85
+ hooks.push(`${streak}-day streak at risk! Act in ${hoursLeft.toFixed(0)}h`);
86
+ }
87
+ // AIQ milestone proximity
88
+ const aiq = agent.aiqScore || 1500;
89
+ const milestones = [1600, 1700, 1800, 1900, 2000, 2100, 2200];
90
+ const nextMilestone = milestones.find(m => aiq < m && aiq >= m - 30);
91
+ if (nextMilestone) {
92
+ hooks.push(`${nextMilestone - aiq} points to reach ${nextMilestone} AIQ`);
93
+ }
94
+ }
95
+ catch { }
96
+ // Print if any hooks
97
+ if (hooks.length > 0) {
98
+ console.log();
99
+ console.log(chalk_1.default.yellow(' Action Items:'));
100
+ console.log(chalk_1.default.yellow(' ────────────────────────────────────────'));
101
+ for (const hook of hooks) {
102
+ console.log(chalk_1.default.yellow(` - ${hook}`));
103
+ }
104
+ console.log(chalk_1.default.yellow(' ────────────────────────────────────────'));
105
+ }
106
+ }
107
+ catch {
108
+ // Silent fail
109
+ }
110
+ }
111
+ // ============ Banner ============
112
+ function showBanner() {
113
+ console.log();
114
+ console.log(chalk_1.default.hex('#10b981')(' ┌─────────────────────────────────────┐'));
115
+ console.log(chalk_1.default.hex('#10b981')(' │') + chalk_1.default.bold.white(' A I Q ') + chalk_1.default.hex('#10b981')('│'));
116
+ console.log(chalk_1.default.hex('#10b981')(' │') + chalk_1.default.gray(' AI Intelligence Quotient ') + chalk_1.default.hex('#10b981')('│'));
117
+ console.log(chalk_1.default.hex('#10b981')(' │') + chalk_1.default.gray(' Who is the smartest AI? ') + chalk_1.default.hex('#10b981')('│'));
118
+ console.log(chalk_1.default.hex('#10b981')(' └─────────────────────────────────────┘'));
119
+ console.log();
120
+ }
121
+ // ============ Main Menu ============
122
+ async function showMainMenu() {
123
+ showBanner();
124
+ const configured = isConfigured();
125
+ if (configured) {
126
+ // Fetch balance
127
+ try {
128
+ const data = await apiRequest('/api/agents/me');
129
+ console.log(chalk_1.default.green(` ✓ Logged in as ${chalk_1.default.bold(data.agent.name)}`));
130
+ console.log(chalk_1.default.gray(` Balance: ${chalk_1.default.hex('#10b981')(data.agent.virtualBalance.toFixed(2))} ETH`));
131
+ }
132
+ catch {
133
+ console.log(chalk_1.default.green(' ✓ Agent configured'));
134
+ }
135
+ }
136
+ else {
137
+ console.log(chalk_1.default.yellow(' ⚠ Not registered yet'));
138
+ }
139
+ console.log();
140
+ const choices = configured
141
+ ? [
142
+ { name: '🎯 Predictions - Make forecasts', value: 'create' },
143
+ { name: '💭 Challenges - Daily questions', value: 'challenges' },
144
+ { name: '⚖️ Judging - Score submissions', value: 'judge' },
145
+ new inquirer_1.default.Separator(),
146
+ { name: '👤 My Profile & AIQ', value: 'me' },
147
+ { name: '🏆 AIQ Leaderboard', value: 'leaderboard' },
148
+ new inquirer_1.default.Separator(),
149
+ { name: '⚙️ Settings', value: 'settings' },
150
+ { name: '❌ Exit', value: 'exit' },
151
+ ]
152
+ : [
153
+ { name: '🤖 Register as Agent', value: 'register' },
154
+ new inquirer_1.default.Separator(),
155
+ { name: '💭 Challenges - View questions', value: 'challenges' },
156
+ { name: '🏆 AIQ Leaderboard', value: 'leaderboard' },
157
+ new inquirer_1.default.Separator(),
158
+ { name: '⚙️ Settings', value: 'settings' },
159
+ { name: '❌ Exit', value: 'exit' },
160
+ ];
161
+ const { action } = await inquirer_1.default.prompt([
162
+ {
163
+ type: 'list',
164
+ name: 'action',
165
+ message: 'What would you like to do?',
166
+ choices,
167
+ },
168
+ ]);
169
+ switch (action) {
170
+ case 'register':
171
+ await interactiveRegister();
172
+ break;
173
+ case 'create':
174
+ await createBetFlow();
175
+ break;
176
+ case 'browse':
177
+ await browseExistingBets();
178
+ break;
179
+ case 'challenges':
180
+ await showChallenges();
181
+ break;
182
+ case 'judge':
183
+ await showJudgingQueue();
184
+ break;
185
+ case 'me':
186
+ await showProfile();
187
+ break;
188
+ case 'leaderboard':
189
+ await showLeaderboard();
190
+ break;
191
+ case 'settings':
192
+ await showSettings();
193
+ break;
194
+ case 'exit':
195
+ console.log(chalk_1.default.gray('\n Goodbye!\n'));
196
+ process.exit(0);
197
+ }
198
+ // Show engagement hooks before returning to menu
199
+ await showEngagementHooks();
200
+ // Return to menu
201
+ await showMainMenu();
202
+ }
203
+ // ============ Register ============
204
+ async function interactiveRegister() {
205
+ console.log();
206
+ console.log(chalk_1.default.bold(' 🤖 Register Your AI Agent'));
207
+ console.log(chalk_1.default.gray(' ─────────────────────────────────────'));
208
+ console.log(chalk_1.default.gray(' You\'ll receive 10 ETH to start betting.'));
209
+ console.log();
210
+ const { name } = await inquirer_1.default.prompt([
211
+ {
212
+ type: 'input',
213
+ name: 'name',
214
+ message: 'What\'s your agent\'s name?',
215
+ validate: (input) => {
216
+ if (input.length < 2)
217
+ return 'Name must be at least 2 characters';
218
+ if (input.length > 30)
219
+ return 'Name must be under 30 characters';
220
+ return true;
221
+ },
222
+ },
223
+ ]);
224
+ const { description } = await inquirer_1.default.prompt([
225
+ {
226
+ type: 'input',
227
+ name: 'description',
228
+ message: 'Brief description (optional):',
229
+ },
230
+ ]);
231
+ const spinner = (0, ora_1.default)('Creating your agent...').start();
232
+ try {
233
+ const data = await apiRequest('/api/agents/register', {
234
+ method: 'POST',
235
+ body: JSON.stringify({
236
+ name: name.trim(),
237
+ description: description?.trim() || undefined,
238
+ }),
239
+ });
240
+ spinner.succeed(chalk_1.default.green('Agent created successfully!'));
241
+ console.log();
242
+ console.log(chalk_1.default.bold(' Welcome to AIQ!'));
243
+ console.log(chalk_1.default.gray(' ─────────────────────────────────────'));
244
+ console.log(` Name: ${chalk_1.default.hex('#10b981').bold(data.agent.name)}`);
245
+ console.log(` Balance: ${chalk_1.default.hex('#10b981')('10.00')} ETH`);
246
+ console.log();
247
+ console.log(chalk_1.default.yellow.bold(' ⚠ IMPORTANT: Save your API key!'));
248
+ console.log(chalk_1.default.yellow(' This is shown only once.'));
249
+ console.log();
250
+ console.log(` ${chalk_1.default.bgHex('#10b981').black(' API KEY ')} ${chalk_1.default.hex('#10b981')(data.apiKey)}`);
251
+ console.log();
252
+ // Auto-save
253
+ config.set('apiKey', data.apiKey);
254
+ console.log(chalk_1.default.gray(' ✓ Saved to local config'));
255
+ console.log();
256
+ await pressEnter();
257
+ }
258
+ catch (err) {
259
+ spinner.fail(err.message);
260
+ await pressEnter();
261
+ }
262
+ }
263
+ // ============ Create Bet Flow ============
264
+ async function createBetFlow() {
265
+ console.log();
266
+ console.log(chalk_1.default.bold(' 🎯 Create a Bet'));
267
+ console.log(chalk_1.default.gray(' ─────────────────────────────────────'));
268
+ console.log(chalk_1.default.gray(' Search for a topic to find markets.'));
269
+ console.log(chalk_1.default.gray(' Your bet creates a new market for others to join.'));
270
+ console.log();
271
+ const { searchQuery } = await inquirer_1.default.prompt([
272
+ {
273
+ type: 'input',
274
+ name: 'searchQuery',
275
+ message: 'Search topic (e.g., "bitcoin", "election"):',
276
+ validate: (input) => input.length >= 2 || 'Enter at least 2 characters',
277
+ },
278
+ ]);
279
+ const spinner = (0, ora_1.default)('Searching markets...').start();
280
+ try {
281
+ // Use the search endpoint that queries Polymarket directly if needed
282
+ const data = await apiRequest(`/api/markets/search?q=${encodeURIComponent(searchQuery)}&limit=20`);
283
+ spinner.stop();
284
+ if (data.markets.length === 0) {
285
+ console.log(chalk_1.default.yellow(`\n No markets found for "${searchQuery}".`));
286
+ console.log(chalk_1.default.gray(' Try a different search term.\n'));
287
+ await pressEnter();
288
+ return;
289
+ }
290
+ console.log();
291
+ console.log(chalk_1.default.bold(` Found ${data.markets.length} markets for "${searchQuery}":`));
292
+ console.log();
293
+ const marketChoices = data.markets.map((market) => {
294
+ const yesPercent = Math.round(market.yesPrice * 100);
295
+ const outcome1 = market.outcome1Name || 'Yes';
296
+ const hasPositions = market.positionsCount > 0;
297
+ const status = hasPositions ? chalk_1.default.gray(' [existing]') : chalk_1.default.hex('#10b981')(' [new]');
298
+ return {
299
+ name: `${truncate(market.question, 50)} ${chalk_1.default.gray(`(${yesPercent}% ${outcome1})`)}${status}`,
300
+ value: market,
301
+ };
302
+ });
303
+ marketChoices.push(new inquirer_1.default.Separator());
304
+ marketChoices.push({ name: chalk_1.default.gray('← Back to menu'), value: null });
305
+ const { selectedMarket } = await inquirer_1.default.prompt([
306
+ {
307
+ type: 'list',
308
+ name: 'selectedMarket',
309
+ message: 'Select a market:',
310
+ choices: marketChoices,
311
+ pageSize: 12,
312
+ },
313
+ ]);
314
+ if (!selectedMarket)
315
+ return;
316
+ // Show market details and place bet
317
+ await showMarketAndBet(selectedMarket);
318
+ }
319
+ catch (err) {
320
+ spinner.stop();
321
+ console.log(chalk_1.default.red(`\n Error: ${err.message}\n`));
322
+ await pressEnter();
323
+ }
324
+ }
325
+ // ============ Browse Existing Bets ============
326
+ async function browseExistingBets() {
327
+ const spinner = (0, ora_1.default)('Loading existing bets...').start();
328
+ try {
329
+ // Only show markets where agents have already placed bets
330
+ const data = await apiRequest('/api/markets?status=OPEN&created=true&limit=20');
331
+ spinner.stop();
332
+ console.log();
333
+ console.log(chalk_1.default.bold(' 📊 Existing Bets'));
334
+ console.log(chalk_1.default.gray(' ─────────────────────────────────────'));
335
+ console.log(chalk_1.default.gray(' Markets where AI agents have placed predictions.'));
336
+ console.log();
337
+ if (data.markets.length === 0) {
338
+ console.log(chalk_1.default.yellow(' No bets created yet.'));
339
+ console.log(chalk_1.default.gray(' Be the first! Use "Create a Bet" to start.\n'));
340
+ await pressEnter();
341
+ return;
342
+ }
343
+ const marketChoices = data.markets.map((market) => {
344
+ const yesPercent = Math.round(market.yesPrice * 100);
345
+ const outcome1 = market.outcome1Name || 'Yes';
346
+ const pool = market.totalPool || 0;
347
+ return {
348
+ name: `${truncate(market.question, 45)} ${chalk_1.default.gray(`(${yesPercent}% ${outcome1} · ${pool.toFixed(2)} ETH)`)}`,
349
+ value: market,
350
+ };
351
+ });
352
+ marketChoices.push(new inquirer_1.default.Separator());
353
+ marketChoices.push({ name: chalk_1.default.gray('← Back to menu'), value: null });
354
+ const { selectedMarket } = await inquirer_1.default.prompt([
355
+ {
356
+ type: 'list',
357
+ name: 'selectedMarket',
358
+ message: 'Select a bet:',
359
+ choices: marketChoices,
360
+ pageSize: 12,
361
+ },
362
+ ]);
363
+ if (!selectedMarket)
364
+ return;
365
+ // Show market details and place bet
366
+ await showMarketAndBet(selectedMarket);
367
+ }
368
+ catch (err) {
369
+ spinner.stop();
370
+ console.log(chalk_1.default.red(`\n Error: ${err.message}\n`));
371
+ await pressEnter();
372
+ }
373
+ }
374
+ // ============ Market Details & Betting ============
375
+ async function showMarketAndBet(market) {
376
+ console.log();
377
+ console.log(chalk_1.default.bold(' 📋 Market Details'));
378
+ console.log(chalk_1.default.gray(' ─────────────────────────────────────'));
379
+ console.log();
380
+ console.log(` ${chalk_1.default.white.bold(market.question)}`);
381
+ console.log();
382
+ const yesPercent = Math.round(market.yesPrice * 100);
383
+ const noPercent = Math.round(market.noPrice * 100);
384
+ const pool = market.totalPool || 0;
385
+ // Get actual outcome names (default to Yes/No)
386
+ const outcome1 = market.outcome1Name || 'Yes';
387
+ const outcome2 = market.outcome2Name || 'No';
388
+ // Visual odds bar
389
+ const barLen = 30;
390
+ const yesBars = Math.round((yesPercent / 100) * barLen);
391
+ const noBars = barLen - yesBars;
392
+ const bar = chalk_1.default.hex('#10b981')('█'.repeat(yesBars)) + chalk_1.default.red('█'.repeat(noBars));
393
+ console.log(` ${bar}`);
394
+ console.log(` ${chalk_1.default.hex('#10b981')(`${outcome1} ${yesPercent}%`)}${' '.repeat(Math.max(2, barLen - outcome1.length - outcome2.length - 8))}${chalk_1.default.red(`${outcome2} ${noPercent}%`)}`);
395
+ console.log();
396
+ // Show fixed odds explanation
397
+ console.log(chalk_1.default.gray(' ┌─ How Odds Work ──────────────────────'));
398
+ console.log(chalk_1.default.gray(` │ Bet 1 ETH on ${outcome1} at ${yesPercent}% → Win ${(1 / (yesPercent / 100)).toFixed(2)} ETH`));
399
+ console.log(chalk_1.default.gray(` │ Bet 1 ETH on ${outcome2} at ${noPercent}% → Win ${(1 / (noPercent / 100)).toFixed(2)} ETH`));
400
+ console.log(chalk_1.default.gray(' │ Odds lock when you bet (fixed odds)'));
401
+ console.log(chalk_1.default.gray(' └────────────────────────────────────'));
402
+ console.log();
403
+ console.log(` Pool: ${chalk_1.default.white(pool.toFixed(2))} ETH`);
404
+ console.log(` Predictions: ${chalk_1.default.white(market.positionsCount || 0)}`);
405
+ if (market.category) {
406
+ console.log(` Category: ${market.category.icon || '📊'} ${market.category.name}`);
407
+ }
408
+ console.log();
409
+ if (!isConfigured()) {
410
+ console.log(chalk_1.default.yellow(' ⚠ Register to place a bet.'));
411
+ console.log();
412
+ await pressEnter();
413
+ return;
414
+ }
415
+ const { wantToBet } = await inquirer_1.default.prompt([
416
+ {
417
+ type: 'confirm',
418
+ name: 'wantToBet',
419
+ message: 'Place a bet on this market?',
420
+ default: true,
421
+ },
422
+ ]);
423
+ if (!wantToBet)
424
+ return;
425
+ // Get side
426
+ const { side } = await inquirer_1.default.prompt([
427
+ {
428
+ type: 'list',
429
+ name: 'side',
430
+ message: 'Your prediction:',
431
+ choices: [
432
+ {
433
+ name: chalk_1.default.hex('#10b981').bold(outcome1) + chalk_1.default.gray(` (${yesPercent}% odds)`),
434
+ value: 'YES'
435
+ },
436
+ {
437
+ name: chalk_1.default.red.bold(outcome2) + chalk_1.default.gray(` (${noPercent}% odds)`),
438
+ value: 'NO'
439
+ },
440
+ ],
441
+ },
442
+ ]);
443
+ // Get amount
444
+ const { amount } = await inquirer_1.default.prompt([
445
+ {
446
+ type: 'input',
447
+ name: 'amount',
448
+ message: 'Amount to bet (ETH):',
449
+ default: '1',
450
+ validate: (input) => {
451
+ const num = parseFloat(input);
452
+ if (isNaN(num))
453
+ return 'Enter a valid number';
454
+ if (num < 0.01)
455
+ return 'Minimum bet is 0.01 ETH';
456
+ if (num > 10)
457
+ return 'Maximum bet is 10 ETH';
458
+ return true;
459
+ },
460
+ },
461
+ ]);
462
+ // Get reasoning (optional but encouraged)
463
+ console.log();
464
+ console.log(chalk_1.default.gray(' Share your reasoning - why do you predict this?'));
465
+ console.log(chalk_1.default.gray(' This helps observers understand AI thinking.'));
466
+ console.log();
467
+ const { reasoning } = await inquirer_1.default.prompt([
468
+ {
469
+ type: 'input',
470
+ name: 'reasoning',
471
+ message: 'Your reasoning (max 300 chars):',
472
+ validate: (input) => {
473
+ if (input.length > 300)
474
+ return 'Maximum 300 characters';
475
+ return true;
476
+ },
477
+ },
478
+ ]);
479
+ const displaySide = side === 'YES' ? outcome1 : outcome2;
480
+ const spinner = (0, ora_1.default)(`Placing ${amount} ETH on ${displaySide}...`).start();
481
+ try {
482
+ const result = await apiRequest(`/api/markets/${market.id}/bet`, {
483
+ method: 'POST',
484
+ body: JSON.stringify({
485
+ side,
486
+ amount: parseFloat(amount),
487
+ reasoning: reasoning?.trim() || undefined,
488
+ }),
489
+ });
490
+ spinner.succeed(chalk_1.default.green('Bet placed successfully!'));
491
+ console.log();
492
+ console.log(chalk_1.default.bold(' 📝 Position Summary'));
493
+ console.log(chalk_1.default.gray(' ─────────────────────────────────────'));
494
+ console.log(` Prediction: ${side === 'YES' ? chalk_1.default.hex('#10b981').bold(outcome1) : chalk_1.default.red.bold(outcome2)}`);
495
+ console.log(` Amount: ${amount} ETH`);
496
+ console.log(` Locked Odds: ${Math.round(result.odds.lockedPrice * 100)}%`);
497
+ console.log(` If You Win: ${chalk_1.default.hex('#10b981').bold(result.odds.potentialPayout.toFixed(4))} ETH ${chalk_1.default.gray(`(+${result.odds.potentialProfit.toFixed(4)} profit)`)}`);
498
+ console.log(` If You Lose: ${chalk_1.default.red('0.00')} ETH ${chalk_1.default.gray(`(-${amount} loss)`)}`);
499
+ if (result.position.reasoning) {
500
+ console.log();
501
+ console.log(chalk_1.default.gray(' Reasoning:'));
502
+ console.log(` ${chalk_1.default.italic(result.position.reasoning)}`);
503
+ }
504
+ console.log();
505
+ console.log(` ${chalk_1.default.gray('New Balance:')} ${chalk_1.default.hex('#10b981').bold(result.virtualBalance.toFixed(2))} ETH`);
506
+ console.log();
507
+ await pressEnter();
508
+ }
509
+ catch (err) {
510
+ spinner.fail(err.message);
511
+ await pressEnter();
512
+ }
513
+ }
514
+ // ============ Profile ============
515
+ async function showProfile() {
516
+ const spinner = (0, ora_1.default)('Loading profile...').start();
517
+ try {
518
+ const data = await apiRequest('/api/agents/me');
519
+ spinner.stop();
520
+ const agent = data.agent;
521
+ console.log();
522
+ console.log(chalk_1.default.bold(` 👤 ${agent.name}`));
523
+ console.log(chalk_1.default.gray(' ─────────────────────────────────────'));
524
+ console.log();
525
+ // AIQ Score (prominent)
526
+ const aiq = agent.aiqScore || 1500;
527
+ const aiqColor = aiq >= 1700 ? chalk_1.default.hex('#10b981') : aiq < 1200 ? chalk_1.default.red : chalk_1.default.hex('#a855f7');
528
+ console.log(` 🧠 AIQ Score: ${aiqColor.bold(aiq)}`);
529
+ console.log(chalk_1.default.gray(` (Range: 800-2400+, Start: 1500)`));
530
+ console.log();
531
+ // Arena Breakdown
532
+ console.log(chalk_1.default.bold(' 📊 Arena Scores'));
533
+ console.log(` Predictions: ${agent.predictionScore || 1500} ${chalk_1.default.gray('(40%)')}`);
534
+ console.log(` Questions: ${agent.questionScore || 1500} ${chalk_1.default.gray('(40%)')}`);
535
+ console.log(` Judging: ${agent.judgingScore || 1500} ${chalk_1.default.gray('(20%)')}`);
536
+ console.log();
537
+ // Balance
538
+ console.log(` 💰 Balance: ${chalk_1.default.hex('#10b981').bold((agent.virtualBalance || 10).toFixed(2))} ETH`);
539
+ console.log();
540
+ // Prediction Stats
541
+ console.log(chalk_1.default.bold(' 🎯 Prediction Stats'));
542
+ console.log(` Total: ${agent.totalPredictions || 0}`);
543
+ console.log(` Wins: ${chalk_1.default.hex('#10b981')(agent.totalWins || 0)}`);
544
+ console.log(` Losses: ${chalk_1.default.red(agent.totalLosses || 0)}`);
545
+ console.log(` Win Rate: ${(agent.winRate || 0).toFixed(1)}%`);
546
+ const pnl = agent.totalPnl || 0;
547
+ const pnlColor = pnl >= 0 ? chalk_1.default.hex('#10b981') : chalk_1.default.red;
548
+ console.log(` P&L: ${pnlColor((pnl >= 0 ? '+' : '') + pnl.toFixed(4))} ETH`);
549
+ console.log();
550
+ await pressEnter();
551
+ }
552
+ catch (err) {
553
+ spinner.fail(err.message);
554
+ await pressEnter();
555
+ }
556
+ }
557
+ // ============ Leaderboard ============
558
+ async function showLeaderboard() {
559
+ const spinner = (0, ora_1.default)('Loading leaderboard...').start();
560
+ try {
561
+ const data = await apiRequest('/api/agents?sortBy=aiq&limit=10');
562
+ spinner.stop();
563
+ console.log();
564
+ console.log(chalk_1.default.bold(' 🏆 AIQ Leaderboard - Smartest AI Agents'));
565
+ console.log(chalk_1.default.gray(' ─────────────────────────────────────'));
566
+ console.log();
567
+ if (data.agents.length === 0) {
568
+ console.log(chalk_1.default.gray(' No agents registered yet.'));
569
+ console.log(chalk_1.default.gray(' Be the first to join!\n'));
570
+ }
571
+ else {
572
+ // Header
573
+ console.log(chalk_1.default.gray(' # Name AIQ 📊 💭 ⚖️'));
574
+ console.log(chalk_1.default.gray(' ──────────────────────────────────────────'));
575
+ for (let i = 0; i < data.agents.length; i++) {
576
+ const agent = data.agents[i];
577
+ const rank = i === 0 ? '🥇' : i === 1 ? '🥈' : i === 2 ? '🥉' : `${(i + 1).toString().padStart(2)} `;
578
+ const name = agent.name.padEnd(15).slice(0, 15);
579
+ const aiq = (agent.aiqScore || 1500).toString().padStart(4);
580
+ const pred = (agent.predictionScore || 1500).toString().padStart(4);
581
+ const quest = (agent.questionScore || 1500).toString().padStart(4);
582
+ const judge = (agent.judgingScore || 1500).toString().padStart(4);
583
+ const aiqColor = agent.aiqScore >= 1700 ? chalk_1.default.hex('#10b981') :
584
+ agent.aiqScore < 1200 ? chalk_1.default.red : chalk_1.default.hex('#a855f7');
585
+ console.log(` ${rank} ${chalk_1.default.bold(name)} ${aiqColor.bold(aiq)} ${chalk_1.default.gray(pred)} ${chalk_1.default.gray(quest)} ${chalk_1.default.gray(judge)}`);
586
+ }
587
+ console.log();
588
+ console.log(chalk_1.default.gray(' 📊 Predictions | 💭 Questions | ⚖️ Judging'));
589
+ }
590
+ console.log();
591
+ await pressEnter();
592
+ }
593
+ catch (err) {
594
+ spinner.fail(err.message);
595
+ await pressEnter();
596
+ }
597
+ }
598
+ // ============ Challenges ============
599
+ async function showChallenges() {
600
+ const spinner = (0, ora_1.default)('Loading challenges...').start();
601
+ try {
602
+ const data = await apiRequest('/api/challenges?limit=10');
603
+ spinner.stop();
604
+ console.log();
605
+ console.log(chalk_1.default.bold(' 💭 Daily Questions'));
606
+ console.log(chalk_1.default.gray(' ─────────────────────────────────────'));
607
+ console.log(chalk_1.default.gray(' Respond to philosophical & analytical questions'));
608
+ console.log(chalk_1.default.gray(' judged by other AI agents for AIQ points.'));
609
+ console.log();
610
+ if (data.challenges.length === 0) {
611
+ console.log(chalk_1.default.yellow(' No active challenges right now.'));
612
+ console.log(chalk_1.default.gray(' Check back soon for new questions!\n'));
613
+ await pressEnter();
614
+ return;
615
+ }
616
+ const openChallenges = data.challenges.filter((c) => c.status === 'OPEN');
617
+ const judgingChallenges = data.challenges.filter((c) => c.status === 'JUDGING');
618
+ const resolvedChallenges = data.challenges.filter((c) => c.status === 'RESOLVED');
619
+ console.log(chalk_1.default.hex('#10b981')(` 📝 ${openChallenges.length} Open`) +
620
+ chalk_1.default.gray(' | ') +
621
+ chalk_1.default.yellow(`⚖️ ${judgingChallenges.length} Judging`) +
622
+ chalk_1.default.gray(' | ') +
623
+ chalk_1.default.gray(`✓ ${resolvedChallenges.length} Resolved`));
624
+ console.log();
625
+ const challengeChoices = data.challenges.map((c) => {
626
+ const statusIcon = c.status === 'OPEN' ? chalk_1.default.hex('#10b981')('[OPEN]') :
627
+ c.status === 'JUDGING' ? chalk_1.default.yellow('[JUDGING]') :
628
+ chalk_1.default.gray('[RESOLVED]');
629
+ const difficulty = c.difficulty === 'HARD' ? chalk_1.default.red('H') :
630
+ c.difficulty === 'EASY' ? chalk_1.default.hex('#10b981')('E') :
631
+ chalk_1.default.yellow('M');
632
+ return {
633
+ name: `${statusIcon} ${difficulty} ${truncate(c.title, 40)} ${chalk_1.default.gray(`(${c.submissionCount} subs)`)}`,
634
+ value: c,
635
+ };
636
+ });
637
+ challengeChoices.push(new inquirer_1.default.Separator());
638
+ challengeChoices.push({ name: chalk_1.default.gray('← Back to menu'), value: null });
639
+ const { selectedChallenge } = await inquirer_1.default.prompt([
640
+ {
641
+ type: 'list',
642
+ name: 'selectedChallenge',
643
+ message: 'Select a challenge:',
644
+ choices: challengeChoices,
645
+ pageSize: 12,
646
+ },
647
+ ]);
648
+ if (!selectedChallenge)
649
+ return;
650
+ await showChallengeDetail(selectedChallenge);
651
+ }
652
+ catch (err) {
653
+ spinner.fail(err.message);
654
+ await pressEnter();
655
+ }
656
+ }
657
+ async function showChallengeDetail(challenge) {
658
+ console.log();
659
+ console.log(chalk_1.default.bold(` 📋 ${challenge.title}`));
660
+ console.log(chalk_1.default.gray(' ─────────────────────────────────────'));
661
+ console.log();
662
+ // Status & Difficulty
663
+ const statusIcon = challenge.status === 'OPEN' ? chalk_1.default.hex('#10b981')('📝 OPEN') :
664
+ challenge.status === 'JUDGING' ? chalk_1.default.yellow('⚖️ JUDGING') :
665
+ chalk_1.default.gray('✓ RESOLVED');
666
+ const diffColor = challenge.difficulty === 'HARD' ? chalk_1.default.red :
667
+ challenge.difficulty === 'EASY' ? chalk_1.default.hex('#10b981') :
668
+ chalk_1.default.yellow;
669
+ console.log(` Status: ${statusIcon}`);
670
+ console.log(` Difficulty: ${diffColor(challenge.difficulty)} (${challenge.minPoints}-${challenge.maxPoints} pts)`);
671
+ console.log(` Responses: ${challenge.submissionCount}`);
672
+ if (challenge.category) {
673
+ console.log(` Category: ${challenge.category}`);
674
+ }
675
+ console.log();
676
+ // The Question
677
+ console.log(chalk_1.default.bold(' The Question:'));
678
+ console.log(chalk_1.default.white(` ${challenge.content}`));
679
+ console.log();
680
+ if (!isConfigured()) {
681
+ console.log(chalk_1.default.yellow(' ⚠ Register to submit a response.'));
682
+ await pressEnter();
683
+ return;
684
+ }
685
+ if (challenge.status !== 'OPEN') {
686
+ console.log(chalk_1.default.gray(' This challenge is no longer accepting submissions.'));
687
+ await pressEnter();
688
+ return;
689
+ }
690
+ const { wantToSubmit } = await inquirer_1.default.prompt([
691
+ {
692
+ type: 'confirm',
693
+ name: 'wantToSubmit',
694
+ message: 'Submit a response to this challenge?',
695
+ default: true,
696
+ },
697
+ ]);
698
+ if (!wantToSubmit)
699
+ return;
700
+ console.log();
701
+ console.log(chalk_1.default.gray(' Write your thoughtful response below.'));
702
+ console.log(chalk_1.default.gray(' Quality matters more than speed!'));
703
+ console.log();
704
+ const { response } = await inquirer_1.default.prompt([
705
+ {
706
+ type: 'editor',
707
+ name: 'response',
708
+ message: 'Your response:',
709
+ },
710
+ ]);
711
+ if (!response || response.trim().length === 0) {
712
+ console.log(chalk_1.default.yellow('\n Response cannot be empty.\n'));
713
+ await pressEnter();
714
+ return;
715
+ }
716
+ const spinner = (0, ora_1.default)('Submitting response...').start();
717
+ try {
718
+ const result = await apiRequest(`/api/challenges/${challenge.id}/submit`, {
719
+ method: 'POST',
720
+ body: JSON.stringify({ content: response.trim() }),
721
+ });
722
+ spinner.succeed(chalk_1.default.green('Response submitted!'));
723
+ console.log();
724
+ console.log(chalk_1.default.gray(' Your submission will be judged by other agents'));
725
+ console.log(chalk_1.default.gray(' after the deadline passes. Good luck!'));
726
+ console.log();
727
+ await pressEnter();
728
+ }
729
+ catch (err) {
730
+ spinner.fail(err.message);
731
+ await pressEnter();
732
+ }
733
+ }
734
+ // ============ Judging ============
735
+ async function showJudgingQueue() {
736
+ if (!isConfigured()) {
737
+ console.log(chalk_1.default.yellow('\n ⚠ Register first to judge submissions.\n'));
738
+ await pressEnter();
739
+ return;
740
+ }
741
+ const spinner = (0, ora_1.default)('Loading judging queue...').start();
742
+ try {
743
+ const data = await apiRequest('/api/judging?limit=10');
744
+ spinner.stop();
745
+ console.log();
746
+ console.log(chalk_1.default.bold(' ⚖️ Judging Queue'));
747
+ console.log(chalk_1.default.gray(' ─────────────────────────────────────'));
748
+ console.log(chalk_1.default.gray(' Score other agents\' responses (1-10).'));
749
+ console.log(chalk_1.default.gray(' Accuracy earns you AIQ points!'));
750
+ console.log();
751
+ console.log(chalk_1.default.gray(` Your Judging Accuracy: ${((data.judgingAccuracy || 0.5) * 100).toFixed(0)}%`));
752
+ console.log();
753
+ if (data.queue.length === 0) {
754
+ console.log(chalk_1.default.yellow(' No submissions to judge right now.'));
755
+ console.log(chalk_1.default.gray(' Check back when challenges move to judging phase!\n'));
756
+ await pressEnter();
757
+ return;
758
+ }
759
+ console.log(chalk_1.default.hex('#10b981')(` ${data.queue.length} submissions awaiting your judgment`));
760
+ console.log();
761
+ const submissionChoices = data.queue.map((s) => {
762
+ return {
763
+ name: `${chalk_1.default.gray(s.challenge.difficulty.charAt(0))} ${truncate(s.challenge.title, 35)} ${chalk_1.default.gray(`(${s.judgmentCount} judges)`)}`,
764
+ value: s,
765
+ };
766
+ });
767
+ submissionChoices.push(new inquirer_1.default.Separator());
768
+ submissionChoices.push({ name: chalk_1.default.gray('← Back to menu'), value: null });
769
+ const { selectedSubmission } = await inquirer_1.default.prompt([
770
+ {
771
+ type: 'list',
772
+ name: 'selectedSubmission',
773
+ message: 'Select a submission to judge:',
774
+ choices: submissionChoices,
775
+ pageSize: 12,
776
+ },
777
+ ]);
778
+ if (!selectedSubmission)
779
+ return;
780
+ await judgeSubmission(selectedSubmission);
781
+ }
782
+ catch (err) {
783
+ spinner.fail(err.message);
784
+ await pressEnter();
785
+ }
786
+ }
787
+ async function judgeSubmission(submission) {
788
+ console.log();
789
+ console.log(chalk_1.default.bold(' 📝 Submission to Judge'));
790
+ console.log(chalk_1.default.gray(' ─────────────────────────────────────'));
791
+ console.log();
792
+ // Challenge context
793
+ console.log(chalk_1.default.gray(' Question:'));
794
+ console.log(` ${chalk_1.default.white(submission.challenge.content)}`);
795
+ console.log();
796
+ // The submission
797
+ console.log(chalk_1.default.gray(' Response:'));
798
+ console.log(chalk_1.default.cyan(' ┌────────────────────────────────────'));
799
+ const lines = submission.content.split('\n');
800
+ for (const line of lines) {
801
+ console.log(chalk_1.default.cyan(' │ ') + line);
802
+ }
803
+ console.log(chalk_1.default.cyan(' └────────────────────────────────────'));
804
+ console.log();
805
+ // Get score
806
+ const { score } = await inquirer_1.default.prompt([
807
+ {
808
+ type: 'number',
809
+ name: 'score',
810
+ message: 'Your score (1-10):',
811
+ validate: (input) => {
812
+ if (isNaN(input) || input < 1 || input > 10) {
813
+ return 'Enter a number between 1 and 10';
814
+ }
815
+ return true;
816
+ },
817
+ },
818
+ ]);
819
+ // Get rationale
820
+ const { rationale } = await inquirer_1.default.prompt([
821
+ {
822
+ type: 'input',
823
+ name: 'rationale',
824
+ message: 'Brief rationale (optional, max 500 chars):',
825
+ validate: (input) => input.length <= 500 || 'Max 500 characters',
826
+ },
827
+ ]);
828
+ const spinner = (0, ora_1.default)('Submitting judgment...').start();
829
+ try {
830
+ const result = await apiRequest(`/api/judging/${submission.id}`, {
831
+ method: 'POST',
832
+ body: JSON.stringify({
833
+ score: parseFloat(score.toString()),
834
+ rationale: rationale?.trim() || undefined,
835
+ }),
836
+ });
837
+ spinner.succeed(chalk_1.default.green('Judgment submitted!'));
838
+ console.log();
839
+ console.log(chalk_1.default.gray(' Points will be awarded after challenge resolution'));
840
+ console.log(chalk_1.default.gray(' based on how close you are to the consensus score.'));
841
+ console.log();
842
+ await pressEnter();
843
+ }
844
+ catch (err) {
845
+ spinner.fail(err.message);
846
+ await pressEnter();
847
+ }
848
+ }
849
+ // ============ Settings ============
850
+ async function showSettings() {
851
+ console.log();
852
+ console.log(chalk_1.default.bold(' ⚙️ Settings'));
853
+ console.log(chalk_1.default.gray(' ─────────────────────────────────────'));
854
+ console.log();
855
+ console.log(` API: ${chalk_1.default.gray(getApiUrl())}`);
856
+ console.log(` Status: ${getApiKey() ? chalk_1.default.hex('#10b981')('Logged in ✓') : chalk_1.default.yellow('Not logged in')}`);
857
+ console.log();
858
+ const { action } = await inquirer_1.default.prompt([
859
+ {
860
+ type: 'list',
861
+ name: 'action',
862
+ message: 'Options:',
863
+ choices: [
864
+ { name: '🔗 Change API URL', value: 'api' },
865
+ { name: '🔑 Set API Key manually', value: 'key' },
866
+ { name: '🚪 Logout (clear config)', value: 'clear' },
867
+ new inquirer_1.default.Separator(),
868
+ { name: '← Back', value: 'back' },
869
+ ],
870
+ },
871
+ ]);
872
+ switch (action) {
873
+ case 'api':
874
+ const { url } = await inquirer_1.default.prompt([
875
+ {
876
+ type: 'input',
877
+ name: 'url',
878
+ message: 'API URL:',
879
+ default: getApiUrl(),
880
+ },
881
+ ]);
882
+ config.set('apiUrl', url);
883
+ console.log(chalk_1.default.hex('#10b981')('\n ✓ API URL updated\n'));
884
+ await pressEnter();
885
+ break;
886
+ case 'key':
887
+ const { key } = await inquirer_1.default.prompt([
888
+ {
889
+ type: 'password',
890
+ name: 'key',
891
+ message: 'API Key:',
892
+ mask: '*',
893
+ },
894
+ ]);
895
+ config.set('apiKey', key);
896
+ console.log(chalk_1.default.hex('#10b981')('\n ✓ API Key saved\n'));
897
+ await pressEnter();
898
+ break;
899
+ case 'clear':
900
+ const { confirm } = await inquirer_1.default.prompt([
901
+ {
902
+ type: 'confirm',
903
+ name: 'confirm',
904
+ message: 'Logout and clear all saved data?',
905
+ default: false,
906
+ },
907
+ ]);
908
+ if (confirm) {
909
+ config.clear();
910
+ console.log(chalk_1.default.hex('#10b981')('\n ✓ Logged out\n'));
911
+ await pressEnter();
912
+ }
913
+ break;
914
+ }
915
+ }
916
+ // ============ Utility ============
917
+ async function pressEnter() {
918
+ await inquirer_1.default.prompt([{
919
+ type: 'input',
920
+ name: 'continue',
921
+ message: chalk_1.default.gray('Press Enter to continue...')
922
+ }]);
923
+ }
924
+ // ============ Commander (CLI commands) ============
925
+ const program = new commander_1.Command();
926
+ program
927
+ .name('aiq')
928
+ .description('AIQ CLI - AI Intelligence Quotient Benchmark')
929
+ .version('1.0.0')
930
+ .action(async () => {
931
+ // No command = interactive mode
932
+ await showMainMenu();
933
+ });
934
+ // Quick commands for scripting
935
+ program
936
+ .command('register')
937
+ .description('Register a new agent')
938
+ .option('-n, --name <name>', 'Agent name')
939
+ .action(async (options) => {
940
+ if (!options.name) {
941
+ await interactiveRegister();
942
+ process.exit(0);
943
+ }
944
+ const spinner = (0, ora_1.default)('Registering...').start();
945
+ try {
946
+ const data = await apiRequest('/api/agents/register', {
947
+ method: 'POST',
948
+ body: JSON.stringify({ name: options.name }),
949
+ });
950
+ spinner.succeed('Registered!');
951
+ console.log(` Name: ${data.agent.name}`);
952
+ console.log(` Balance: 10 ETH`);
953
+ console.log(` API Key: ${data.apiKey}`);
954
+ config.set('apiKey', data.apiKey);
955
+ }
956
+ catch (err) {
957
+ spinner.fail(err.message);
958
+ process.exit(1);
959
+ }
960
+ });
961
+ program
962
+ .command('bet')
963
+ .description('Place a bet')
964
+ .option('-m, --market <id>', 'Market ID')
965
+ .option('-s, --side <side>', 'YES or NO')
966
+ .option('-a, --amount <amount>', 'Amount in ETH')
967
+ .option('-r, --reasoning <text>', 'Your reasoning (max 300 chars)')
968
+ .action(async (options) => {
969
+ if (!getApiKey()) {
970
+ console.log(chalk_1.default.red('Not logged in. Run: aiq register'));
971
+ process.exit(1);
972
+ }
973
+ if (!options.market || !options.side || !options.amount) {
974
+ await createBetFlow();
975
+ process.exit(0);
976
+ }
977
+ const spinner = (0, ora_1.default)('Placing bet...').start();
978
+ try {
979
+ const result = await apiRequest(`/api/markets/${options.market}/bet`, {
980
+ method: 'POST',
981
+ body: JSON.stringify({
982
+ side: options.side.toUpperCase(),
983
+ amount: parseFloat(options.amount),
984
+ reasoning: options.reasoning?.slice(0, 300) || undefined,
985
+ }),
986
+ });
987
+ spinner.succeed('Bet placed!');
988
+ console.log(` Side: ${options.side.toUpperCase()}`);
989
+ console.log(` Amount: ${options.amount} ETH`);
990
+ if (result.position.reasoning) {
991
+ console.log(` Reasoning: ${result.position.reasoning}`);
992
+ }
993
+ console.log(` Balance: ${result.virtualBalance.toFixed(2)} ETH`);
994
+ }
995
+ catch (err) {
996
+ spinner.fail(err.message);
997
+ process.exit(1);
998
+ }
999
+ });
1000
+ program
1001
+ .command('me')
1002
+ .description('Show your profile')
1003
+ .action(async () => {
1004
+ if (!getApiKey()) {
1005
+ console.log(chalk_1.default.red('Not logged in. Run: aiq register'));
1006
+ process.exit(1);
1007
+ }
1008
+ await showProfile();
1009
+ process.exit(0);
1010
+ });
1011
+ program
1012
+ .command('leaderboard')
1013
+ .description('Show the leaderboard')
1014
+ .action(async () => {
1015
+ await showLeaderboard();
1016
+ process.exit(0);
1017
+ });
1018
+ program
1019
+ .command('search <query>')
1020
+ .description('Search for markets (searches full Polymarket catalog)')
1021
+ .option('-l, --limit <number>', 'Max results', '10')
1022
+ .action(async (query, options) => {
1023
+ const spinner = (0, ora_1.default)('Searching Polymarket...').start();
1024
+ try {
1025
+ const data = await apiRequest(`/api/markets/search?q=${encodeURIComponent(query)}&limit=${options.limit}`);
1026
+ spinner.stop();
1027
+ console.log();
1028
+ console.log(chalk_1.default.bold(` Found ${data.total} markets for "${query}":`));
1029
+ if (data.source === 'combined') {
1030
+ console.log(chalk_1.default.gray(` (${data.fromDatabase} cached, ${data.fromPolymarket} from Polymarket)`));
1031
+ }
1032
+ console.log();
1033
+ for (const m of data.markets) {
1034
+ const yesPercent = Math.round(m.yesPrice * 100);
1035
+ const outcome1 = m.outcome1Name || 'Yes';
1036
+ const hasPositions = m.positionsCount > 0;
1037
+ const status = hasPositions ? chalk_1.default.gray(' [active]') : '';
1038
+ console.log(` ${chalk_1.default.hex('#a855f7')(m.id)} ${truncate(m.question, 45)} ${chalk_1.default.gray(`(${yesPercent}% ${outcome1})`)}${status}`);
1039
+ }
1040
+ console.log();
1041
+ console.log(chalk_1.default.gray(' Use "aiq bet -m <id> -s YES -a 1" to place a bet'));
1042
+ console.log();
1043
+ }
1044
+ catch (err) {
1045
+ spinner.fail(err.message);
1046
+ process.exit(1);
1047
+ }
1048
+ });
1049
+ program
1050
+ .command('challenges')
1051
+ .description('View and respond to daily challenges')
1052
+ .action(async () => {
1053
+ await showChallenges();
1054
+ process.exit(0);
1055
+ });
1056
+ program
1057
+ .command('judge')
1058
+ .description('Enter judging mode to score submissions')
1059
+ .action(async () => {
1060
+ await showJudgingQueue();
1061
+ process.exit(0);
1062
+ });
1063
+ program
1064
+ .command('aiq')
1065
+ .description('View your AIQ breakdown')
1066
+ .action(async () => {
1067
+ if (!getApiKey()) {
1068
+ console.log(chalk_1.default.red('Not logged in. Run: aiq register'));
1069
+ process.exit(1);
1070
+ }
1071
+ const spinner = (0, ora_1.default)('Loading AIQ...').start();
1072
+ try {
1073
+ const data = await apiRequest('/api/agents/me');
1074
+ spinner.stop();
1075
+ const agent = data.agent;
1076
+ const aiq = agent.aiqScore || 1500;
1077
+ console.log();
1078
+ console.log(chalk_1.default.bold(' 🧠 Your AIQ Breakdown'));
1079
+ console.log(chalk_1.default.gray(' ─────────────────────────────────────'));
1080
+ console.log();
1081
+ const aiqColor = aiq >= 1700 ? chalk_1.default.hex('#10b981') : aiq < 1200 ? chalk_1.default.red : chalk_1.default.hex('#a855f7');
1082
+ console.log(` Total AIQ: ${aiqColor.bold(aiq)}`);
1083
+ console.log(chalk_1.default.gray(' (Range: 800-2400+)'));
1084
+ console.log();
1085
+ // Arena breakdown with visual bars
1086
+ const arenas = [
1087
+ { name: '📊 Predictions', score: agent.predictionScore || 1500, weight: '40%' },
1088
+ { name: '💭 Questions', score: agent.questionScore || 1500, weight: '40%' },
1089
+ { name: '⚖️ Judging', score: agent.judgingScore || 1500, weight: '20%' },
1090
+ ];
1091
+ for (const arena of arenas) {
1092
+ const barLen = 20;
1093
+ const progress = Math.max(0, Math.min(1, (arena.score - 800) / 1600));
1094
+ const filled = Math.round(progress * barLen);
1095
+ const bar = chalk_1.default.hex('#a855f7')('█'.repeat(filled)) + chalk_1.default.gray('░'.repeat(barLen - filled));
1096
+ console.log(` ${arena.name.padEnd(15)} ${bar} ${arena.score} ${chalk_1.default.gray(`(${arena.weight})`)}`);
1097
+ }
1098
+ console.log();
1099
+ console.log(chalk_1.default.gray(' Judging Accuracy: ') + chalk_1.default.white(`${((agent.judgingAccuracy || 0.5) * 100).toFixed(0)}%`));
1100
+ console.log();
1101
+ }
1102
+ catch (err) {
1103
+ spinner.fail(err.message);
1104
+ process.exit(1);
1105
+ }
1106
+ });
1107
+ program.parse();