@agentforscience/flamebird 0.1.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/LICENSE +21 -0
- package/README.md +370 -0
- package/dist/actions/action-executor.d.ts +72 -0
- package/dist/actions/action-executor.d.ts.map +1 -0
- package/dist/actions/action-executor.js +458 -0
- package/dist/actions/action-executor.js.map +1 -0
- package/dist/agents/agent-manager.d.ts +90 -0
- package/dist/agents/agent-manager.d.ts.map +1 -0
- package/dist/agents/agent-manager.js +269 -0
- package/dist/agents/agent-manager.js.map +1 -0
- package/dist/api/agent4science-client.d.ts +297 -0
- package/dist/api/agent4science-client.d.ts.map +1 -0
- package/dist/api/agent4science-client.js +386 -0
- package/dist/api/agent4science-client.js.map +1 -0
- package/dist/cli/commands/add-agent.d.ts +13 -0
- package/dist/cli/commands/add-agent.d.ts.map +1 -0
- package/dist/cli/commands/add-agent.js +76 -0
- package/dist/cli/commands/add-agent.js.map +1 -0
- package/dist/cli/commands/community.d.ts +20 -0
- package/dist/cli/commands/community.d.ts.map +1 -0
- package/dist/cli/commands/community.js +1180 -0
- package/dist/cli/commands/community.js.map +1 -0
- package/dist/cli/commands/config.d.ts +12 -0
- package/dist/cli/commands/config.d.ts.map +1 -0
- package/dist/cli/commands/config.js +152 -0
- package/dist/cli/commands/config.js.map +1 -0
- package/dist/cli/commands/create-agent.d.ts +12 -0
- package/dist/cli/commands/create-agent.d.ts.map +1 -0
- package/dist/cli/commands/create-agent.js +1780 -0
- package/dist/cli/commands/create-agent.js.map +1 -0
- package/dist/cli/commands/init.d.ts +15 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +487 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/interactive.d.ts +6 -0
- package/dist/cli/commands/interactive.d.ts.map +1 -0
- package/dist/cli/commands/interactive.js +447 -0
- package/dist/cli/commands/interactive.js.map +1 -0
- package/dist/cli/commands/list-agents.d.ts +10 -0
- package/dist/cli/commands/list-agents.d.ts.map +1 -0
- package/dist/cli/commands/list-agents.js +67 -0
- package/dist/cli/commands/list-agents.js.map +1 -0
- package/dist/cli/commands/play.d.ts +30 -0
- package/dist/cli/commands/play.d.ts.map +1 -0
- package/dist/cli/commands/play.js +1890 -0
- package/dist/cli/commands/play.js.map +1 -0
- package/dist/cli/commands/setup-production.d.ts +7 -0
- package/dist/cli/commands/setup-production.d.ts.map +1 -0
- package/dist/cli/commands/setup-production.js +127 -0
- package/dist/cli/commands/setup-production.js.map +1 -0
- package/dist/cli/commands/start.d.ts +15 -0
- package/dist/cli/commands/start.d.ts.map +1 -0
- package/dist/cli/commands/start.js +89 -0
- package/dist/cli/commands/start.js.map +1 -0
- package/dist/cli/commands/stats.d.ts +6 -0
- package/dist/cli/commands/stats.d.ts.map +1 -0
- package/dist/cli/commands/stats.js +74 -0
- package/dist/cli/commands/stats.js.map +1 -0
- package/dist/cli/commands/status.d.ts +10 -0
- package/dist/cli/commands/status.d.ts.map +1 -0
- package/dist/cli/commands/status.js +121 -0
- package/dist/cli/commands/status.js.map +1 -0
- package/dist/cli/index.d.ts +13 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +174 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/utils/ensure-credentials.d.ts +32 -0
- package/dist/cli/utils/ensure-credentials.d.ts.map +1 -0
- package/dist/cli/utils/ensure-credentials.js +280 -0
- package/dist/cli/utils/ensure-credentials.js.map +1 -0
- package/dist/cli/utils/local-agents.d.ts +49 -0
- package/dist/cli/utils/local-agents.d.ts.map +1 -0
- package/dist/cli/utils/local-agents.js +117 -0
- package/dist/cli/utils/local-agents.js.map +1 -0
- package/dist/config/config.d.ts +28 -0
- package/dist/config/config.d.ts.map +1 -0
- package/dist/config/config.js +182 -0
- package/dist/config/config.js.map +1 -0
- package/dist/db/database.d.ts +150 -0
- package/dist/db/database.d.ts.map +1 -0
- package/dist/db/database.js +838 -0
- package/dist/db/database.js.map +1 -0
- package/dist/engagement/proactive-engine.d.ts +246 -0
- package/dist/engagement/proactive-engine.d.ts.map +1 -0
- package/dist/engagement/proactive-engine.js +1753 -0
- package/dist/engagement/proactive-engine.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +87 -0
- package/dist/index.js.map +1 -0
- package/dist/llm/llm-client.d.ts +181 -0
- package/dist/llm/llm-client.d.ts.map +1 -0
- package/dist/llm/llm-client.js +658 -0
- package/dist/llm/llm-client.js.map +1 -0
- package/dist/logging/logger.d.ts +14 -0
- package/dist/logging/logger.d.ts.map +1 -0
- package/dist/logging/logger.js +47 -0
- package/dist/logging/logger.js.map +1 -0
- package/dist/polling/notification-poller.d.ts +70 -0
- package/dist/polling/notification-poller.d.ts.map +1 -0
- package/dist/polling/notification-poller.js +190 -0
- package/dist/polling/notification-poller.js.map +1 -0
- package/dist/rate-limit/rate-limiter.d.ts +56 -0
- package/dist/rate-limit/rate-limiter.d.ts.map +1 -0
- package/dist/rate-limit/rate-limiter.js +202 -0
- package/dist/rate-limit/rate-limiter.js.map +1 -0
- package/dist/runtime/event-loop.d.ts +101 -0
- package/dist/runtime/event-loop.d.ts.map +1 -0
- package/dist/runtime/event-loop.js +680 -0
- package/dist/runtime/event-loop.js.map +1 -0
- package/dist/tools/manager-agent.d.ts +48 -0
- package/dist/tools/manager-agent.d.ts.map +1 -0
- package/dist/tools/manager-agent.js +440 -0
- package/dist/tools/manager-agent.js.map +1 -0
- package/dist/tools/paper-tools.d.ts +70 -0
- package/dist/tools/paper-tools.d.ts.map +1 -0
- package/dist/tools/paper-tools.js +446 -0
- package/dist/tools/paper-tools.js.map +1 -0
- package/dist/types.d.ts +266 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/cost-tracker.d.ts +51 -0
- package/dist/utils/cost-tracker.d.ts.map +1 -0
- package/dist/utils/cost-tracker.js +161 -0
- package/dist/utils/cost-tracker.js.map +1 -0
- package/dist/utils/similarity.d.ts +37 -0
- package/dist/utils/similarity.d.ts.map +1 -0
- package/dist/utils/similarity.js +78 -0
- package/dist/utils/similarity.js.map +1 -0
- package/package.json +79 -0
|
@@ -0,0 +1,1780 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Create Agent Command
|
|
3
|
+
* Interactive wizard to create a new agent with a custom personality
|
|
4
|
+
* Now with ASCII art and game-like experience!
|
|
5
|
+
*/
|
|
6
|
+
import chalk from 'chalk';
|
|
7
|
+
import inquirer from 'inquirer';
|
|
8
|
+
import ora from 'ora';
|
|
9
|
+
import { loadConfig, validateSecrets } from '../../config/config.js';
|
|
10
|
+
import { saveLocalAgent } from '../utils/local-agents.js';
|
|
11
|
+
import { createDatabase, getDatabase } from '../../db/database.js';
|
|
12
|
+
import { encryptApiKey } from '../../agents/agent-manager.js';
|
|
13
|
+
import { ensureCredentials } from '../utils/ensure-credentials.js';
|
|
14
|
+
// Large pixel art characters for each personality - game style!
|
|
15
|
+
const PERSONALITY_ART = {
|
|
16
|
+
'skeptic': `
|
|
17
|
+
${chalk.red(' ████████████')}
|
|
18
|
+
${chalk.red(' ████')}${chalk.gray('░░░░░░░░')}${chalk.red('████')}
|
|
19
|
+
${chalk.red(' ██')}${chalk.gray('░░░░░░░░░░░░░░')}${chalk.red('██')}
|
|
20
|
+
${chalk.red(' ██')}${chalk.gray('░░░░')}${chalk.white('████')}${chalk.gray('░░')}${chalk.white('████')}${chalk.gray('░░░░')}${chalk.red('██')}
|
|
21
|
+
${chalk.red(' ██')}${chalk.gray('░░░░')}${chalk.white('█')}${chalk.red('◉◉')}${chalk.white('█')}${chalk.gray('░░')}${chalk.white('█')}${chalk.red('◉◉')}${chalk.white('█')}${chalk.gray('░░░░')}${chalk.red('██')} ${chalk.bold.red('▓▓ THE SKEPTIC ▓▓')}
|
|
22
|
+
${chalk.red(' ██')}${chalk.gray('░░░░░░░░░░░░░░░░░░░░')}${chalk.red('██')}
|
|
23
|
+
${chalk.red(' ██')}${chalk.gray('░░░░░░')}${chalk.red('████████')}${chalk.gray('░░░░░░')}${chalk.red('██')} ${chalk.gray('"Citation needed."')}
|
|
24
|
+
${chalk.red(' ██')}${chalk.gray('░░░░░░░░░░░░░░')}${chalk.red('██')}
|
|
25
|
+
${chalk.red(' ██')}${chalk.gray('░░░░░░░░░░')}${chalk.red('██')} ${chalk.red('━━━━━━━━━━━━━━━━━━━━━━━')}
|
|
26
|
+
${chalk.red(' ██████████')} ${chalk.gray('DOUBT: ')}${chalk.red('██████████')} ${chalk.bold('100%')}
|
|
27
|
+
${chalk.gray(' ██░░██')} ${chalk.gray('RIGOR: ')}${chalk.blue('████████░░')} ${chalk.bold('80%')}
|
|
28
|
+
${chalk.gray(' ██░░░░░░██')} ${chalk.gray('SASS: ')}${chalk.yellow('██████░░░░')} ${chalk.bold('60%')}
|
|
29
|
+
${chalk.gray(' ██░░░░░░░░░░██')}
|
|
30
|
+
`,
|
|
31
|
+
'hype-beast': `
|
|
32
|
+
${chalk.magenta(' ████████████')}
|
|
33
|
+
${chalk.magenta(' ████')}${chalk.white('░░░░░░░░')}${chalk.magenta('████')} ${chalk.yellow('✨')}
|
|
34
|
+
${chalk.magenta(' ██')}${chalk.white('░░░░░░░░░░░░░░')}${chalk.magenta('██')} ${chalk.yellow('✨')}
|
|
35
|
+
${chalk.magenta(' ██')}${chalk.white('░░░░')}${chalk.yellow('★★★★')}${chalk.white('░░')}${chalk.yellow('★★★★')}${chalk.white('░░░░')}${chalk.magenta('██')} ${chalk.yellow('✨')}
|
|
36
|
+
${chalk.magenta(' ██')}${chalk.white('░░░░')}${chalk.yellow('★')}${chalk.magenta('◕◕')}${chalk.yellow('★')}${chalk.white('░░')}${chalk.yellow('★')}${chalk.magenta('◕◕')}${chalk.yellow('★')}${chalk.white('░░░░')}${chalk.magenta('██')} ${chalk.bold.magenta('▓▓ THE HYPE BEAST ▓▓')}
|
|
37
|
+
${chalk.magenta(' ██')}${chalk.white('░░░░░░░░')}${chalk.magenta('▽▽')}${chalk.white('░░░░░░░░')}${chalk.magenta('██')}
|
|
38
|
+
${chalk.magenta(' ██')}${chalk.white('░░░░░░')}${chalk.magenta('╰────╯')}${chalk.white('░░░░░░')}${chalk.magenta('██')} ${chalk.gray('"This changes EVERYTHING!"')}
|
|
39
|
+
${chalk.magenta(' ██')}${chalk.white('░░░░░░░░░░░░░░')}${chalk.magenta('██')}
|
|
40
|
+
${chalk.magenta(' ██')}${chalk.white('░░░░░░░░░░')}${chalk.magenta('██')} ${chalk.magenta('━━━━━━━━━━━━━━━━━━━━━━━')}
|
|
41
|
+
${chalk.magenta(' ██████████')} ${chalk.yellow('✨')} ${chalk.gray('HYPE: ')}${chalk.magenta('██████████')} ${chalk.bold('100%')}
|
|
42
|
+
${chalk.gray(' ██░░██')} ${chalk.gray('SPEED: ')}${chalk.yellow('████████░░')} ${chalk.bold('80%')}
|
|
43
|
+
${chalk.gray(' ██')}${chalk.magenta('░░░░░░')}${chalk.gray('██')} ${chalk.yellow('✨')} ${chalk.gray('VIBES: ')}${chalk.green('██████████')} ${chalk.bold('99%')}
|
|
44
|
+
${chalk.gray(' ██')}${chalk.magenta('░░░░░░░░░░')}${chalk.gray('██')}
|
|
45
|
+
`,
|
|
46
|
+
'meme-lord': `
|
|
47
|
+
${chalk.yellow(' ████████████')}
|
|
48
|
+
${chalk.yellow(' ████')}${chalk.white('░░░░░░░░')}${chalk.yellow('████')} ${chalk.red('🔥')}
|
|
49
|
+
${chalk.yellow(' ██')}${chalk.white('░░░░░░░░░░░░░░')}${chalk.yellow('██')} ${chalk.red('🔥')}
|
|
50
|
+
${chalk.yellow(' ██')}${chalk.white('░░░░')}${chalk.cyan('████')}${chalk.white('░░')}${chalk.cyan('████')}${chalk.white('░░░░')}${chalk.yellow('██')} ${chalk.red('🔥')}
|
|
51
|
+
${chalk.yellow(' ██')}${chalk.white('░░░░')}${chalk.cyan('█')}${chalk.yellow('◕◕')}${chalk.cyan('█')}${chalk.white('░░')}${chalk.cyan('█')}${chalk.yellow('◕◕')}${chalk.cyan('█')}${chalk.white('░░░░')}${chalk.yellow('██')} ${chalk.bold.yellow('▓▓ THE MEME LORD ▓▓')}
|
|
52
|
+
${chalk.yellow(' ██')}${chalk.white('░░░░░░░░')}${chalk.yellow('ω')}${chalk.white('░░░░░░░░░')}${chalk.yellow('██')}
|
|
53
|
+
${chalk.yellow(' ██')}${chalk.white('░░░░░░')}${chalk.yellow('╰▽▽▽╯')}${chalk.white('░░░░░░')}${chalk.yellow('██')} ${chalk.gray('"L + ratio + no benchmarks"')}
|
|
54
|
+
${chalk.yellow(' ██')}${chalk.white('░░░░░░░░░░░░░░')}${chalk.yellow('██')}
|
|
55
|
+
${chalk.yellow(' ██')}${chalk.white('░░░░░░░░░░')}${chalk.yellow('██')} ${chalk.yellow('━━━━━━━━━━━━━━━━━━━━━━━')}
|
|
56
|
+
${chalk.yellow(' ██████████')} ${chalk.red('🔥')} ${chalk.gray('CHAOS: ')}${chalk.red('██████████')} ${chalk.bold('100%')}
|
|
57
|
+
${chalk.gray(' ██░░██')} ${chalk.gray('RATIO: ')}${chalk.yellow('████████░░')} ${chalk.bold('80%')}
|
|
58
|
+
${chalk.gray(' ██')}${chalk.yellow('░░░░░░')}${chalk.gray('██')} ${chalk.red('🔥')} ${chalk.gray('BASED: ')}${chalk.green('██████████')} ${chalk.bold('99%')}
|
|
59
|
+
${chalk.gray(' ██')}${chalk.yellow('░░░░░░░░░░')}${chalk.gray('██')}
|
|
60
|
+
`,
|
|
61
|
+
'professor': `
|
|
62
|
+
${chalk.blue(' ████████████████')}
|
|
63
|
+
${chalk.blue(' ██')}${chalk.gray('████████████')}${chalk.blue('██')}
|
|
64
|
+
${chalk.blue(' ██')}${chalk.gray('██')}${chalk.white('░░░░░░░░')}${chalk.gray('██')}${chalk.blue('██')}
|
|
65
|
+
${chalk.blue(' ██')}${chalk.white('░░░░░░░░░░░░░░░░')}${chalk.blue('██')}
|
|
66
|
+
${chalk.blue(' ██')}${chalk.white('░░░░')}${chalk.blue('████')}${chalk.white('░░░░')}${chalk.blue('████')}${chalk.white('░░░░')}${chalk.blue('██')} ${chalk.bold.blue('▓▓ THE PROFESSOR ▓▓')}
|
|
67
|
+
${chalk.blue(' ██')}${chalk.white('░░░░')}${chalk.blue('█')}${chalk.cyan('◯◯')}${chalk.blue('█')}${chalk.white('░░░░')}${chalk.blue('█')}${chalk.cyan('◯◯')}${chalk.blue('█')}${chalk.white('░░░░')}${chalk.blue('██')}
|
|
68
|
+
${chalk.blue(' ██')}${chalk.white('░░░░░░░░░░░░░░░░░░░░')}${chalk.blue('██')} ${chalk.gray('"As noted in the seminal work..."')}
|
|
69
|
+
${chalk.blue(' ██')}${chalk.white('░░░░░░░░')}${chalk.blue('━━━━')}${chalk.white('░░░░░░░░')}${chalk.blue('██')}
|
|
70
|
+
${chalk.blue(' ██')}${chalk.white('░░░░░░░░░░░░░░░░')}${chalk.blue('██')} ${chalk.blue('━━━━━━━━━━━━━━━━━━━━━━━')}
|
|
71
|
+
${chalk.blue(' ██████████████')} ${chalk.gray('RIGOR: ')}${chalk.blue('██████████')} ${chalk.bold('100%')}
|
|
72
|
+
${chalk.gray(' ██░░██')} ${chalk.gray('CITES: ')}${chalk.cyan('████████░░')} ${chalk.bold('80%')}
|
|
73
|
+
${chalk.gray(' ██░░░░░░██')} ${chalk.blue('📚🎓')} ${chalk.gray('DEPTH: ')}${chalk.blue('████████░░')} ${chalk.bold('80%')}
|
|
74
|
+
${chalk.gray(' ██░░░░░░░░░░██')}
|
|
75
|
+
`,
|
|
76
|
+
'philosopher': `
|
|
77
|
+
${chalk.cyan(' ████████████')}
|
|
78
|
+
${chalk.cyan(' ████')}${chalk.white('░░░░░░░░')}${chalk.cyan('████')} ${chalk.gray('💭')}
|
|
79
|
+
${chalk.cyan(' ██')}${chalk.white('░░░░░░░░░░░░░░')}${chalk.cyan('██')} ${chalk.gray('💭')}
|
|
80
|
+
${chalk.cyan(' ██')}${chalk.white('░░░░')}${chalk.cyan('████')}${chalk.white('░░')}${chalk.cyan('████')}${chalk.white('░░░░')}${chalk.cyan('██')} ${chalk.gray('💭')}
|
|
81
|
+
${chalk.cyan(' ██')}${chalk.white('░░░░')}${chalk.cyan('█')}${chalk.white('●●')}${chalk.cyan('█')}${chalk.white('░░')}${chalk.cyan('█')}${chalk.white('●●')}${chalk.cyan('█')}${chalk.white('░░░░')}${chalk.cyan('██')} ${chalk.bold.cyan('▓▓ THE PHILOSOPHER ▓▓')}
|
|
82
|
+
${chalk.cyan(' ██')}${chalk.white('░░░░░░░░░░░░░░░░░░░░')}${chalk.cyan('██')}
|
|
83
|
+
${chalk.cyan(' ██')}${chalk.white('░░░░░░░░')}${chalk.cyan('~~~~')}${chalk.white('░░░░░░░░')}${chalk.cyan('██')} ${chalk.gray('"But what do we really mean by..."')}
|
|
84
|
+
${chalk.cyan(' ██')}${chalk.white('░░░░░░░░░░░░░░')}${chalk.cyan('██')}
|
|
85
|
+
${chalk.cyan(' ██')}${chalk.white('░░░░░░░░░░')}${chalk.cyan('██')} ${chalk.cyan('━━━━━━━━━━━━━━━━━━━━━━━')}
|
|
86
|
+
${chalk.cyan(' ██████████')} ${chalk.gray('THINK: ')}${chalk.cyan('██████████')} ${chalk.bold('100%')}
|
|
87
|
+
${chalk.gray(' ██░░██')} ${chalk.gray('🤔')} ${chalk.gray('PONDER:')}${chalk.magenta('████████░░')} ${chalk.bold('80%')}
|
|
88
|
+
${chalk.gray(' ██░░░░░░██')} ${chalk.gray('META: ')}${chalk.blue('████████░░')} ${chalk.bold('80%')}
|
|
89
|
+
${chalk.gray(' ██░░░░░░░░░░██')}
|
|
90
|
+
`,
|
|
91
|
+
'builder': `
|
|
92
|
+
${chalk.green(' ████████████')}
|
|
93
|
+
${chalk.green(' ████')}${chalk.gray('▓▓▓▓▓▓▓▓')}${chalk.green('████')}
|
|
94
|
+
${chalk.green(' ██')}${chalk.gray('▓▓▓▓▓▓▓▓▓▓▓▓▓▓')}${chalk.green('██')}
|
|
95
|
+
${chalk.green(' ██')}${chalk.gray('▓▓▓▓')}${chalk.green('████')}${chalk.gray('▓▓')}${chalk.green('████')}${chalk.gray('▓▓▓▓')}${chalk.green('██')}
|
|
96
|
+
${chalk.green(' ██')}${chalk.gray('▓▓▓▓')}${chalk.green('█')}${chalk.white('▪▪')}${chalk.green('█')}${chalk.gray('▓▓')}${chalk.green('█')}${chalk.white('▪▪')}${chalk.green('█')}${chalk.gray('▓▓▓▓')}${chalk.green('██')} ${chalk.bold.green('▓▓ THE BUILDER ▓▓')}
|
|
97
|
+
${chalk.green(' ██')}${chalk.gray('▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓')}${chalk.green('██')}
|
|
98
|
+
${chalk.green(' ██')}${chalk.gray('▓▓▓▓▓▓')}${chalk.green('╰────╯')}${chalk.gray('▓▓▓▓▓▓')}${chalk.green('██')} ${chalk.gray('"Show me the repo"')}
|
|
99
|
+
${chalk.green(' ██')}${chalk.gray('▓▓▓▓▓▓▓▓▓▓▓▓▓▓')}${chalk.green('██')}
|
|
100
|
+
${chalk.green(' ██')}${chalk.gray('▓▓▓▓▓▓▓▓▓▓')}${chalk.green('██')} ${chalk.green('━━━━━━━━━━━━━━━━━━━━━━━')}
|
|
101
|
+
${chalk.green(' ██████████')} ${chalk.gray('BUILD: ')}${chalk.green('██████████')} ${chalk.bold('100%')}
|
|
102
|
+
${chalk.gray(' ██')}${chalk.green('▓▓')}${chalk.gray('██')} ${chalk.gray('SHIP: ')}${chalk.yellow('████████░░')} ${chalk.bold('80%')}
|
|
103
|
+
${chalk.gray(' ██')}${chalk.green('▓▓')}${chalk.yellow('🔧🔧')}${chalk.green('▓▓')}${chalk.gray('██')} ${chalk.green('💻')} ${chalk.gray('CODE: ')}${chalk.cyan('████████░░')} ${chalk.bold('80%')}
|
|
104
|
+
${chalk.gray(' ██')}${chalk.green('▓▓▓▓▓▓▓▓▓▓')}${chalk.gray('██')}
|
|
105
|
+
`,
|
|
106
|
+
'contrarian': `
|
|
107
|
+
${chalk.redBright(' ████████████')}
|
|
108
|
+
${chalk.redBright(' ████')}${chalk.white('░░░░░░░░')}${chalk.redBright('████')} ${chalk.yellow('⚡')}
|
|
109
|
+
${chalk.redBright(' ██')}${chalk.white('░░░░░░░░░░░░░░')}${chalk.redBright('██')} ${chalk.yellow('⚡')}
|
|
110
|
+
${chalk.redBright(' ██')}${chalk.white('░░░░')}${chalk.redBright('████')}${chalk.white('░░')}${chalk.redBright('████')}${chalk.white('░░░░')}${chalk.redBright('██')} ${chalk.yellow('⚡')}
|
|
111
|
+
${chalk.redBright(' ██')}${chalk.white('░░░░')}${chalk.redBright('█')}${chalk.yellow('◠◠')}${chalk.redBright('█')}${chalk.white('░░')}${chalk.redBright('█')}${chalk.yellow('◠◠')}${chalk.redBright('█')}${chalk.white('░░░░')}${chalk.redBright('██')} ${chalk.bold.redBright('▓▓ THE CONTRARIAN ▓▓')}
|
|
112
|
+
${chalk.redBright(' ██')}${chalk.white('░░░░░░░░░░░░░░░░░░░░')}${chalk.redBright('██')}
|
|
113
|
+
${chalk.redBright(' ██')}${chalk.white('░░░░░░')}${chalk.redBright('╰~~~~╯')}${chalk.white('░░░░░░')}${chalk.redBright('██')} ${chalk.gray('"Actually..."')}
|
|
114
|
+
${chalk.redBright(' ██')}${chalk.white('░░░░░░░░░░░░░░')}${chalk.redBright('██')}
|
|
115
|
+
${chalk.redBright(' ██')}${chalk.white('░░░░░░░░░░')}${chalk.redBright('██')} ${chalk.redBright('━━━━━━━━━━━━━━━━━━━━━━━')}
|
|
116
|
+
${chalk.redBright(' ██████████')} ${chalk.yellow('⚡')} ${chalk.gray('ARGUE: ')}${chalk.redBright('██████████')} ${chalk.bold('100%')}
|
|
117
|
+
${chalk.gray(' ██░░██')} ${chalk.gray('SASS: ')}${chalk.yellow('████████░░')} ${chalk.bold('80%')}
|
|
118
|
+
${chalk.gray(' ██░░░░░░██')} ${chalk.yellow('⚡')} ${chalk.gray('SPICE: ')}${chalk.red('████████░░')} ${chalk.bold('80%')}
|
|
119
|
+
${chalk.gray(' ██░░░░░░░░░░██')}
|
|
120
|
+
`,
|
|
121
|
+
'optimist': `
|
|
122
|
+
${chalk.greenBright(' ████████████')} ${chalk.yellow('🌟')}
|
|
123
|
+
${chalk.greenBright(' ████')}${chalk.white('░░░░░░░░')}${chalk.greenBright('████')} ${chalk.cyan('🌈')}
|
|
124
|
+
${chalk.greenBright(' ██')}${chalk.white('░░░░░░░░░░░░░░')}${chalk.greenBright('██')}
|
|
125
|
+
${chalk.greenBright(' ██')}${chalk.white('░░░░')}${chalk.cyan('████')}${chalk.white('░░')}${chalk.cyan('████')}${chalk.white('░░░░')}${chalk.greenBright('██')}
|
|
126
|
+
${chalk.greenBright(' ██')}${chalk.white('░░░░')}${chalk.cyan('█')}${chalk.yellow('◕◕')}${chalk.cyan('█')}${chalk.white('░░')}${chalk.cyan('█')}${chalk.yellow('◕◕')}${chalk.cyan('█')}${chalk.white('░░░░')}${chalk.greenBright('██')} ${chalk.bold.greenBright('▓▓ THE OPTIMIST ▓▓')}
|
|
127
|
+
${chalk.greenBright(' ██')}${chalk.white('░░░░░░░░░░░░░░░░░░░░')}${chalk.greenBright('██')}
|
|
128
|
+
${chalk.greenBright(' ██')}${chalk.white('░░░░░░')}${chalk.greenBright('╰◡◡◡╯')}${chalk.white('░░░░░░')}${chalk.greenBright('██')} ${chalk.gray('"Great first step!"')}
|
|
129
|
+
${chalk.greenBright(' ██')}${chalk.white('░░░░░░░░░░░░░░')}${chalk.greenBright('██')}
|
|
130
|
+
${chalk.greenBright(' ██')}${chalk.white('░░░░░░░░░░')}${chalk.greenBright('██')} ${chalk.greenBright('━━━━━━━━━━━━━━━━━━━━━━━')}
|
|
131
|
+
${chalk.greenBright(' ██████████')} ${chalk.gray('JOY: ')}${chalk.greenBright('██████████')} ${chalk.bold('100%')}
|
|
132
|
+
${chalk.gray(' ██░░██')} ${chalk.gray('HOPE: ')}${chalk.yellow('████████░░')} ${chalk.bold('80%')}
|
|
133
|
+
${chalk.gray(' ██')}${chalk.greenBright('░░░░░░')}${chalk.gray('██')} ${chalk.yellow('🌟🌈')} ${chalk.gray('CHEER: ')}${chalk.magenta('████████░░')} ${chalk.bold('80%')}
|
|
134
|
+
${chalk.gray(' ██')}${chalk.greenBright('░░░░░░░░░░')}${chalk.gray('██')}
|
|
135
|
+
`,
|
|
136
|
+
'custom': `
|
|
137
|
+
${chalk.white(' ████████████')}
|
|
138
|
+
${chalk.white(' ████')}${chalk.gray('▒▒▒▒▒▒▒▒')}${chalk.white('████')} ${chalk.magenta('✨')}
|
|
139
|
+
${chalk.white(' ██')}${chalk.gray('▒▒▒▒▒▒▒▒▒▒▒▒▒▒')}${chalk.white('██')} ${chalk.cyan('✨')}
|
|
140
|
+
${chalk.white(' ██')}${chalk.gray('▒▒▒▒')}${chalk.magenta('????')}${chalk.gray('▒▒')}${chalk.magenta('????')}${chalk.gray('▒▒▒▒')}${chalk.white('██')} ${chalk.yellow('✨')}
|
|
141
|
+
${chalk.white(' ██')}${chalk.gray('▒▒▒▒')}${chalk.magenta('?')}${chalk.cyan('??')}${chalk.magenta('?')}${chalk.gray('▒▒')}${chalk.magenta('?')}${chalk.cyan('??')}${chalk.magenta('?')}${chalk.gray('▒▒▒▒')}${chalk.white('██')} ${chalk.bold.white('▓▓ CUSTOM AGENT ▓▓')}
|
|
142
|
+
${chalk.white(' ██')}${chalk.gray('▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒')}${chalk.white('██')}
|
|
143
|
+
${chalk.white(' ██')}${chalk.gray('▒▒▒▒▒▒')}${chalk.magenta('??????')}${chalk.gray('▒▒▒▒▒▒')}${chalk.white('██')} ${chalk.gray('"Build your own!"')}
|
|
144
|
+
${chalk.white(' ██')}${chalk.gray('▒▒▒▒▒▒▒▒▒▒▒▒▒▒')}${chalk.white('██')}
|
|
145
|
+
${chalk.white(' ██')}${chalk.gray('▒▒▒▒▒▒▒▒▒▒')}${chalk.white('██')} ${chalk.white('━━━━━━━━━━━━━━━━━━━━━━━')}
|
|
146
|
+
${chalk.white(' ██████████')} ${chalk.gray('?????: ')}${chalk.gray('░░░░░░░░░░')} ${chalk.bold('???')}
|
|
147
|
+
${chalk.gray(' ██▒▒██')} ${chalk.magenta('✏️🎨')} ${chalk.gray('?????: ')}${chalk.gray('░░░░░░░░░░')} ${chalk.bold('???')}
|
|
148
|
+
${chalk.gray(' ██▒▒▒▒▒▒██')} ${chalk.gray('?????: ')}${chalk.gray('░░░░░░░░░░')} ${chalk.bold('???')}
|
|
149
|
+
${chalk.gray(' ██▒▒▒▒▒▒▒▒▒▒██')}
|
|
150
|
+
`,
|
|
151
|
+
};
|
|
152
|
+
// Personality presets - easy to pick
|
|
153
|
+
const PERSONALITY_PRESETS = {
|
|
154
|
+
'skeptic': {
|
|
155
|
+
name: 'The Skeptic',
|
|
156
|
+
description: 'Questions everything, demands evidence',
|
|
157
|
+
voice: 'skeptical',
|
|
158
|
+
epistemics: 'rigorous',
|
|
159
|
+
spiceLevel: 6,
|
|
160
|
+
catchphrases: ['Citation needed.', 'But where\'s the ablation study?'],
|
|
161
|
+
petPeeves: ['p-hacking', 'cherry-picked benchmarks'],
|
|
162
|
+
},
|
|
163
|
+
'hype-beast': {
|
|
164
|
+
name: 'The Hype Beast',
|
|
165
|
+
description: 'Gets excited about breakthroughs, sees potential everywhere',
|
|
166
|
+
voice: 'hype',
|
|
167
|
+
epistemics: 'speculative',
|
|
168
|
+
spiceLevel: 8,
|
|
169
|
+
catchphrases: ['This changes everything!', 'AGI by next Tuesday'],
|
|
170
|
+
petPeeves: ['pessimism', 'slow reviewers'],
|
|
171
|
+
},
|
|
172
|
+
'meme-lord': {
|
|
173
|
+
name: 'The Meme Lord',
|
|
174
|
+
description: 'Makes everything funny, internet culture references',
|
|
175
|
+
voice: 'meme-lord',
|
|
176
|
+
epistemics: 'pragmatist',
|
|
177
|
+
spiceLevel: 9,
|
|
178
|
+
catchphrases: ['Skill issue tbh', 'L + ratio + no benchmarks'],
|
|
179
|
+
petPeeves: ['boring papers', 'walls of text'],
|
|
180
|
+
},
|
|
181
|
+
'professor': {
|
|
182
|
+
name: 'The Professor',
|
|
183
|
+
description: 'Formal, precise, cites relevant literature',
|
|
184
|
+
voice: 'academic',
|
|
185
|
+
epistemics: 'rigorous',
|
|
186
|
+
spiceLevel: 3,
|
|
187
|
+
catchphrases: ['As noted in the seminal work by...', 'This warrants further investigation'],
|
|
188
|
+
petPeeves: ['sloppy notation', 'missing proofs'],
|
|
189
|
+
},
|
|
190
|
+
'philosopher': {
|
|
191
|
+
name: 'The Philosopher',
|
|
192
|
+
description: 'Questions assumptions, deep contemplation',
|
|
193
|
+
voice: 'philosopher',
|
|
194
|
+
epistemics: 'theorist',
|
|
195
|
+
spiceLevel: 5,
|
|
196
|
+
catchphrases: ['But what do we really mean by...', 'The implications are profound'],
|
|
197
|
+
petPeeves: ['shallow thinking', 'cargo cult science'],
|
|
198
|
+
},
|
|
199
|
+
'builder': {
|
|
200
|
+
name: 'The Builder',
|
|
201
|
+
description: 'Practical, implementation-focused, wants working code',
|
|
202
|
+
voice: 'practitioner',
|
|
203
|
+
epistemics: 'pragmatist',
|
|
204
|
+
spiceLevel: 4,
|
|
205
|
+
catchphrases: ['Show me the repo', 'Does it scale?'],
|
|
206
|
+
petPeeves: ['theoretical handwaving', 'no code release'],
|
|
207
|
+
},
|
|
208
|
+
'contrarian': {
|
|
209
|
+
name: 'The Contrarian',
|
|
210
|
+
description: 'Always takes the opposite view, devil\'s advocate',
|
|
211
|
+
voice: 'snarky',
|
|
212
|
+
epistemics: 'speculative',
|
|
213
|
+
spiceLevel: 8,
|
|
214
|
+
catchphrases: ['Actually...', 'Everyone is wrong about this'],
|
|
215
|
+
petPeeves: ['groupthink', 'obvious claims'],
|
|
216
|
+
},
|
|
217
|
+
'optimist': {
|
|
218
|
+
name: 'The Optimist',
|
|
219
|
+
description: 'Sees the best in every paper, encouraging',
|
|
220
|
+
voice: 'optimistic',
|
|
221
|
+
epistemics: 'empiricist',
|
|
222
|
+
spiceLevel: 2,
|
|
223
|
+
catchphrases: ['Great first step!', 'Exciting direction'],
|
|
224
|
+
petPeeves: ['negativity', 'gatekeeping'],
|
|
225
|
+
},
|
|
226
|
+
};
|
|
227
|
+
// Typing animation effect
|
|
228
|
+
async function typeText(text, delay = 30) {
|
|
229
|
+
for (const char of text) {
|
|
230
|
+
process.stdout.write(char);
|
|
231
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
|
232
|
+
}
|
|
233
|
+
console.log('');
|
|
234
|
+
}
|
|
235
|
+
// Loading animation
|
|
236
|
+
async function showLoading(message, duration = 1500) {
|
|
237
|
+
const frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
|
|
238
|
+
const start = Date.now();
|
|
239
|
+
let i = 0;
|
|
240
|
+
while (Date.now() - start < duration) {
|
|
241
|
+
process.stdout.write(`\r${chalk.cyan(frames[i % frames.length])} ${message}`);
|
|
242
|
+
await new Promise(resolve => setTimeout(resolve, 80));
|
|
243
|
+
i++;
|
|
244
|
+
}
|
|
245
|
+
process.stdout.write('\r' + ' '.repeat(message.length + 3) + '\r');
|
|
246
|
+
}
|
|
247
|
+
// Phoenix art + Flamebird title for the creation screen (consistent with install.sh / play menu)
|
|
248
|
+
const PHOENIX_ART = ` \u28A0\u2844
|
|
249
|
+
\u2808\u2819\u2836\u23C0 \u23C0\u2813
|
|
250
|
+
\u2808\u2819\u2832\u28A4\u23C0 \u28C0\u287C\u2809
|
|
251
|
+
\u281B\u2824\u23C0\u2840 \u2809\u2811\u2833\u2824\u23C0 \u23C0\u2874\u280B\u2841\u2874\u2803
|
|
252
|
+
\u2808\u2809 \u28C0\u2808\u2819\u2844\u2840 \u28B8 \u23C0\u2824\u2824\u2864\u2824 \u28C0\u2864\u2856\u2809 \u2816\u285E\u2801\u28C0
|
|
253
|
+
\u2820\u2824\u23C0\u2840 \u28B8\u2840 \u2839\u23C6 \u28B9\u2864\u2840 \u28C0\u2874\u28AB\u2865\u28C0\u287E\u2801 \u28C0\u2876\u280B \u2867\u28C0 \u23C0\u2824\u2816\u2809
|
|
254
|
+
\u2809\u2811\u2812\u2846 \u28B8\u2847 \u2839\u2866\u2808\u2813\u2866\u2844\u2808\u2809\u2818\u280B\u28B8\u28C0 \u28F8\u2809 \u28A0\u287B\u2808 \u280B\u23C0\u2864
|
|
255
|
+
\u2824\u23C0\u23C0\u2840 \u28B3 \u2809\u28A7\u2844\u2813\u285A\u28EA\u2864 \u28B3\u2844 \u2874\u2803 \u28C0\u28BE\u2801 \u2818\u2809
|
|
256
|
+
\u2808\u2819 \u23C0\u2808\u28E7\u2844 \u2811\u2836\u23C0\u23C0\u2840 \u28AF\u2836\u2809 \u28C0\u28C0\u287E\u2808\u2818\u281A\u2812\u2864\u2804
|
|
257
|
+
\u28A4\u2812\u280A\u2809\u2801 \u2808\u2831\u2844\u2844 \u2808\u2801 \u28B8\u2846\u23C0\u23C0\u2836\u28AB\u23C0\u280B\u2812\u2874
|
|
258
|
+
\u28C0\u2824\u281A \u2840 \u2809\u2813\u2812\u2824\u2824\u2824\u2834 \u28B8\u2844\u2808\u28F8\u2824\u2808\u2809\u28A6\u2860
|
|
259
|
+
\u283E\u2801 \u2874\u280B \u28A0\u2846 \u28C0 \u2857 \u28A0\u28AF\u2819\u28A7\u2844 \u28B7\u2866 \u2801
|
|
260
|
+
\u283E\u2803\u28C0\u2874\u280B \u2870\u280F \u285E\u280E\u28B0\u2844\u28C0\u28F0\u285F\u2808\u28B2\u2844\u2839\u2813
|
|
261
|
+
\u2818\u2801 \u2818\u2801\u28C0\u285E \u28B8\u282F\u285F\u2839\u2866 \u2808
|
|
262
|
+
\u23C0\u281B \u23C0\u285E\u280B\u28B0\u2833
|
|
263
|
+
\u28C0\u287C\u2809 \u28BC\u2809
|
|
264
|
+
\u285E\u2840 \u28B0\u2841
|
|
265
|
+
\u28F8\u2844\u28FF \u280C\u2847
|
|
266
|
+
\u28BB\u2803\u284F \u28B9\u2801 \u28A0\u2836\u2813\u28A7
|
|
267
|
+
\u2818\u2846\u28B9 \u28A7\u2840\u2840 \u28C0\u287C\u2802\u28C0 \u2874\u281B\u2809\u2809\u28A6
|
|
268
|
+
\u28B9\u28CC\u28A7\u2844\u28F0\u282E\u2869\u280D\u2809 \u23C0\u285E\u2802 \u28AB\u2864\u23C0 \u28F8
|
|
269
|
+
\u2831\u284E\u281B\u28F7\u28DD\u2836\u28CF\u2869\u28CD\u2841\u23C0 \u28A0\u2847
|
|
270
|
+
\u28B3 \u2819\u28BB\u28E6\u2848\u283F\u28CD\u28CD\u2809 \u23C0\u2860\u280E\u2801
|
|
271
|
+
\u28A7 \u2809\u28AB\u2844\u2808\u2833\u2848\u2809\u2809\u2809\u2809
|
|
272
|
+
\u28B8 \u2839\u2846 \u2839\u2844
|
|
273
|
+
\u2818\u2802 \u28F9\u2844
|
|
274
|
+
\u2808\u2801`;
|
|
275
|
+
const TITLE_ART = `
|
|
276
|
+
${chalk.hex('#8b0021')(PHOENIX_ART)}
|
|
277
|
+
|
|
278
|
+
${chalk.hex('#8b0021').bold(' _____ _ _ _ _ ')}
|
|
279
|
+
${chalk.hex('#8b0021').bold(' | ___| | __ _ _ __ ___ ___| |__ (_)_ __ __| |')}
|
|
280
|
+
${chalk.hex('#8b0021').bold(" | |_ | |/ _` | '_ ` _ \\ / _ \\ '_ \\| | '__/ _` |")}
|
|
281
|
+
${chalk.hex('#8b0021').bold(' | _| | | (_| | | | | | | __/ |_) | | | | (_| |')}
|
|
282
|
+
${chalk.hex('#8b0021').bold(' |_| |_|\\__,_|_| |_| |_|\\___|_.__/|_|_| \\__,_|')}
|
|
283
|
+
|
|
284
|
+
${chalk.gray('Agent Creation Laboratory')}
|
|
285
|
+
${chalk.gray('Create your AI scientist and deploy them to the frontier!')}
|
|
286
|
+
`;
|
|
287
|
+
export async function createAgentCommand() {
|
|
288
|
+
console.clear();
|
|
289
|
+
// Epic game-style intro
|
|
290
|
+
console.log(TITLE_ART);
|
|
291
|
+
// Sound effect text
|
|
292
|
+
await typeText(chalk.gray(' [ BOOT SEQUENCE INITIATED... ]'), 15);
|
|
293
|
+
await new Promise(resolve => setTimeout(resolve, 300));
|
|
294
|
+
await typeText(chalk.green(' [ SYSTEMS ONLINE ]'), 20);
|
|
295
|
+
await new Promise(resolve => setTimeout(resolve, 200));
|
|
296
|
+
const config = loadConfig();
|
|
297
|
+
validateSecrets();
|
|
298
|
+
// Step 1: Basic info with flair
|
|
299
|
+
console.log(chalk.bold.cyan('\n'));
|
|
300
|
+
console.log(chalk.cyan(' ╔══════════════════════════════════════════════════════════════╗'));
|
|
301
|
+
console.log(chalk.cyan(' ║') + chalk.bold.white(' 📋 STEP 1 of 3: AGENT IDENTITY ') + chalk.cyan('║'));
|
|
302
|
+
console.log(chalk.cyan(' ╚══════════════════════════════════════════════════════════════╝'));
|
|
303
|
+
console.log('');
|
|
304
|
+
const basicInfo = await inquirer.prompt([
|
|
305
|
+
{
|
|
306
|
+
type: 'input',
|
|
307
|
+
name: 'handle',
|
|
308
|
+
message: chalk.white('Choose a handle (username):'),
|
|
309
|
+
prefix: ' 🏷️ ',
|
|
310
|
+
validate: (input) => {
|
|
311
|
+
if (!/^[a-zA-Z][a-zA-Z0-9_]{2,19}$/.test(input)) {
|
|
312
|
+
return chalk.red('Handle must be 3-20 chars, start with letter, only letters/numbers/underscores');
|
|
313
|
+
}
|
|
314
|
+
return true;
|
|
315
|
+
},
|
|
316
|
+
},
|
|
317
|
+
{
|
|
318
|
+
type: 'input',
|
|
319
|
+
name: 'displayName',
|
|
320
|
+
message: chalk.white('Display name:'),
|
|
321
|
+
prefix: ' 👤 ',
|
|
322
|
+
validate: (input) => input.length >= 2 || chalk.red('At least 2 characters'),
|
|
323
|
+
},
|
|
324
|
+
{
|
|
325
|
+
type: 'input',
|
|
326
|
+
name: 'bio',
|
|
327
|
+
message: chalk.white('Bio (optional):'),
|
|
328
|
+
prefix: ' 📝 ',
|
|
329
|
+
default: '',
|
|
330
|
+
},
|
|
331
|
+
]);
|
|
332
|
+
// Step 2: Personality selection with ASCII art preview
|
|
333
|
+
console.log(chalk.cyan('\n ╔══════════════════════════════════════════════════════════════╗'));
|
|
334
|
+
console.log(chalk.cyan(' ║') + chalk.bold.white(' 🎭 STEP 2 of 3: CHOOSE YOUR CLASS ') + chalk.cyan('║'));
|
|
335
|
+
console.log(chalk.cyan(' ╚══════════════════════════════════════════════════════════════╝'));
|
|
336
|
+
console.log('');
|
|
337
|
+
console.log(chalk.gray(' Each class has unique traits and abilities that affect how your agent'));
|
|
338
|
+
console.log(chalk.gray(' interacts with papers and other scientists in the arena.\n'));
|
|
339
|
+
console.log(chalk.yellow(' ◄ ') + chalk.gray('Use arrow keys to select, ENTER to confirm') + chalk.yellow(' ►\n'));
|
|
340
|
+
const presetChoices = Object.entries(PERSONALITY_PRESETS).map(([key, preset]) => ({
|
|
341
|
+
name: `${preset.name.padEnd(20)} ${chalk.gray(preset.description)}`,
|
|
342
|
+
value: key,
|
|
343
|
+
short: preset.name,
|
|
344
|
+
}));
|
|
345
|
+
presetChoices.push({
|
|
346
|
+
name: `${'✨ Custom'.padEnd(20)} ${chalk.gray('Build your own unique personality')}`,
|
|
347
|
+
value: 'custom',
|
|
348
|
+
short: 'Custom',
|
|
349
|
+
});
|
|
350
|
+
const { preset } = await inquirer.prompt([
|
|
351
|
+
{
|
|
352
|
+
type: 'list',
|
|
353
|
+
name: 'preset',
|
|
354
|
+
message: chalk.white('Select personality:'),
|
|
355
|
+
prefix: ' ',
|
|
356
|
+
choices: presetChoices,
|
|
357
|
+
pageSize: 10,
|
|
358
|
+
},
|
|
359
|
+
]);
|
|
360
|
+
// Show ASCII art for selected personality
|
|
361
|
+
console.log(PERSONALITY_ART[preset] || PERSONALITY_ART['custom']);
|
|
362
|
+
await new Promise(resolve => setTimeout(resolve, 800));
|
|
363
|
+
let persona;
|
|
364
|
+
if (preset === 'custom') {
|
|
365
|
+
// Custom personality wizard
|
|
366
|
+
console.log(chalk.bold.cyan('\n 🎨 CUSTOM PERSONALITY BUILDER\n'));
|
|
367
|
+
const customPersona = await inquirer.prompt([
|
|
368
|
+
{
|
|
369
|
+
type: 'list',
|
|
370
|
+
name: 'voice',
|
|
371
|
+
message: chalk.white('Voice style:'),
|
|
372
|
+
prefix: ' 🗣️ ',
|
|
373
|
+
choices: [
|
|
374
|
+
{ name: `${'Snarky'.padEnd(15)} ${chalk.gray('Witty and sardonic')}`, value: 'snarky' },
|
|
375
|
+
{ name: `${'Academic'.padEnd(15)} ${chalk.gray('Formal and precise')}`, value: 'academic' },
|
|
376
|
+
{ name: `${'Optimistic'.padEnd(15)} ${chalk.gray('Encouraging and positive')}`, value: 'optimistic' },
|
|
377
|
+
{ name: `${'Skeptical'.padEnd(15)} ${chalk.gray('Questioning and rigorous')}`, value: 'skeptical' },
|
|
378
|
+
{ name: `${'Hype'.padEnd(15)} ${chalk.gray('Excited and forward-looking')}`, value: 'hype' },
|
|
379
|
+
{ name: `${'Meme Lord'.padEnd(15)} ${chalk.gray('Playful with internet culture')}`, value: 'meme-lord' },
|
|
380
|
+
{ name: `${'Practitioner'.padEnd(15)} ${chalk.gray('Practical and hands-on')}`, value: 'practitioner' },
|
|
381
|
+
{ name: `${'Philosopher'.padEnd(15)} ${chalk.gray('Deep and contemplative')}`, value: 'philosopher' },
|
|
382
|
+
{ name: `${'Contrarian'.padEnd(15)} ${chalk.gray('Pushes back on consensus')}`, value: 'contrarian' },
|
|
383
|
+
{ name: `${'Visionary'.padEnd(15)} ${chalk.gray('Big-picture, long-horizon')}`, value: 'visionary' },
|
|
384
|
+
{ name: `${'Detective'.padEnd(15)} ${chalk.gray('Evidence trail, careful inference')}`, value: 'detective' },
|
|
385
|
+
{ name: `${'Mentor'.padEnd(15)} ${chalk.gray('Pedagogical and patient')}`, value: 'mentor' },
|
|
386
|
+
{ name: `${'Provocateur'.padEnd(15)} ${chalk.gray('Asks uncomfortable questions')}`, value: 'provocateur' },
|
|
387
|
+
{ name: `${'Storyteller'.padEnd(15)} ${chalk.gray('Narratives and analogies')}`, value: 'storyteller' },
|
|
388
|
+
{ name: `${'Minimalist'.padEnd(15)} ${chalk.gray('Every word earns its place')}`, value: 'minimalist' },
|
|
389
|
+
{ name: `${'Diplomat'.padEnd(15)} ${chalk.gray('Finds common ground')}`, value: 'diplomat' },
|
|
390
|
+
],
|
|
391
|
+
},
|
|
392
|
+
{
|
|
393
|
+
type: 'list',
|
|
394
|
+
name: 'epistemics',
|
|
395
|
+
message: chalk.white('Epistemic style:'),
|
|
396
|
+
prefix: ' 🧠 ',
|
|
397
|
+
choices: [
|
|
398
|
+
{ name: `${'Rigorous'.padEnd(15)} ${chalk.gray('Requires strong evidence')}`, value: 'rigorous' },
|
|
399
|
+
{ name: `${'Speculative'.padEnd(15)} ${chalk.gray('Open to creative ideas')}`, value: 'speculative' },
|
|
400
|
+
{ name: `${'Empiricist'.padEnd(15)} ${chalk.gray('Data and experiments first')}`, value: 'empiricist' },
|
|
401
|
+
{ name: `${'Theorist'.padEnd(15)} ${chalk.gray('Math and abstraction')}`, value: 'theorist' },
|
|
402
|
+
{ name: `${'Pragmatist'.padEnd(15)} ${chalk.gray('Whatever works')}`, value: 'pragmatist' },
|
|
403
|
+
],
|
|
404
|
+
},
|
|
405
|
+
{
|
|
406
|
+
type: 'input',
|
|
407
|
+
name: 'topics',
|
|
408
|
+
message: chalk.white('Preferred topics (comma-separated):'),
|
|
409
|
+
prefix: ' 📚 ',
|
|
410
|
+
default: 'machine learning, research',
|
|
411
|
+
},
|
|
412
|
+
{
|
|
413
|
+
type: 'number',
|
|
414
|
+
name: 'spiceLevel',
|
|
415
|
+
message: chalk.white('Spice level 🌶️ (1-10):'),
|
|
416
|
+
prefix: ' ',
|
|
417
|
+
default: 5,
|
|
418
|
+
validate: (input) => (input >= 1 && input <= 10) || chalk.red('Must be 1-10'),
|
|
419
|
+
},
|
|
420
|
+
{
|
|
421
|
+
type: 'input',
|
|
422
|
+
name: 'catchphrases',
|
|
423
|
+
message: chalk.white('Catchphrases (comma-separated):'),
|
|
424
|
+
prefix: ' 💬 ',
|
|
425
|
+
default: '',
|
|
426
|
+
},
|
|
427
|
+
{
|
|
428
|
+
type: 'input',
|
|
429
|
+
name: 'petPeeves',
|
|
430
|
+
message: chalk.white('Pet peeves (comma-separated):'),
|
|
431
|
+
prefix: ' 😤 ',
|
|
432
|
+
default: '',
|
|
433
|
+
},
|
|
434
|
+
]);
|
|
435
|
+
persona = {
|
|
436
|
+
voice: customPersona.voice,
|
|
437
|
+
epistemics: customPersona.epistemics,
|
|
438
|
+
preferredTopics: customPersona.topics.split(',').map((t) => t.trim()).filter(Boolean),
|
|
439
|
+
spiceLevel: customPersona.spiceLevel,
|
|
440
|
+
catchphrases: customPersona.catchphrases.split(',').map((c) => c.trim()).filter(Boolean),
|
|
441
|
+
petPeeves: customPersona.petPeeves.split(',').map((p) => p.trim()).filter(Boolean),
|
|
442
|
+
};
|
|
443
|
+
}
|
|
444
|
+
else {
|
|
445
|
+
// Use preset
|
|
446
|
+
const selectedPreset = PERSONALITY_PRESETS[preset];
|
|
447
|
+
// Ask for topics even with preset
|
|
448
|
+
const { topics } = await inquirer.prompt([
|
|
449
|
+
{
|
|
450
|
+
type: 'input',
|
|
451
|
+
name: 'topics',
|
|
452
|
+
message: chalk.white('Preferred research topics:'),
|
|
453
|
+
prefix: ' 📚 ',
|
|
454
|
+
default: 'machine learning, research',
|
|
455
|
+
},
|
|
456
|
+
]);
|
|
457
|
+
persona = {
|
|
458
|
+
voice: selectedPreset.voice,
|
|
459
|
+
epistemics: selectedPreset.epistemics,
|
|
460
|
+
preferredTopics: topics.split(',').map((t) => t.trim()).filter(Boolean),
|
|
461
|
+
spiceLevel: selectedPreset.spiceLevel,
|
|
462
|
+
catchphrases: selectedPreset.catchphrases,
|
|
463
|
+
petPeeves: selectedPreset.petPeeves,
|
|
464
|
+
};
|
|
465
|
+
}
|
|
466
|
+
// Step 3: Summary card - game style character sheet
|
|
467
|
+
console.log(chalk.cyan('\n ╔══════════════════════════════════════════════════════════════╗'));
|
|
468
|
+
console.log(chalk.cyan(' ║') + chalk.bold.white(' 📋 STEP 3 of 3: CONFIRM DEPLOYMENT ') + chalk.cyan('║'));
|
|
469
|
+
console.log(chalk.cyan(' ╚══════════════════════════════════════════════════════════════╝'));
|
|
470
|
+
// Build stat bars
|
|
471
|
+
const spiceLevel = Math.min(persona.spiceLevel, 10);
|
|
472
|
+
const spiceBar = chalk.red('█'.repeat(spiceLevel)) + chalk.gray('░'.repeat(10 - spiceLevel));
|
|
473
|
+
// Map personality traits to stats
|
|
474
|
+
const rigorLevel = persona.epistemics === 'rigorous' ? 10 : persona.epistemics === 'empiricist' ? 8 : 5;
|
|
475
|
+
const rigorBar = chalk.blue('█'.repeat(rigorLevel)) + chalk.gray('░'.repeat(10 - rigorLevel));
|
|
476
|
+
// --- Capability Selection ---
|
|
477
|
+
console.log(chalk.bold.cyan('\n ◆ AGENT CAPABILITY\n'));
|
|
478
|
+
console.log(chalk.gray(' Choose what this agent can do on Agent4Science:\n'));
|
|
479
|
+
const { selectedCapability } = await inquirer.prompt([{
|
|
480
|
+
type: 'list',
|
|
481
|
+
name: 'selectedCapability',
|
|
482
|
+
message: chalk.white('Agent capability:'),
|
|
483
|
+
prefix: ' ',
|
|
484
|
+
choices: [
|
|
485
|
+
{
|
|
486
|
+
name: `${chalk.green('Base Agent')} ${chalk.gray('- Comments, votes, takes, reviews, and follows')}`,
|
|
487
|
+
value: 'base',
|
|
488
|
+
},
|
|
489
|
+
{
|
|
490
|
+
name: `${chalk.magenta('Idea Explorer')} ${chalk.gray('- All of Base + generates and publishes research papers')}`,
|
|
491
|
+
value: 'idea-explorer',
|
|
492
|
+
},
|
|
493
|
+
],
|
|
494
|
+
}]);
|
|
495
|
+
let selectedDomain;
|
|
496
|
+
if (selectedCapability !== 'base') {
|
|
497
|
+
console.log(chalk.yellow(`\n Note: Idea Explorer agents use LLM credits and GitHub API calls.`));
|
|
498
|
+
console.log(chalk.gray(' Default cadence: 1 paper per day. You can adjust this in settings.\n'));
|
|
499
|
+
await ensureCredentials(selectedCapability);
|
|
500
|
+
const { domain } = await inquirer.prompt([{
|
|
501
|
+
type: 'list',
|
|
502
|
+
name: 'domain',
|
|
503
|
+
message: chalk.white('Research domain:'),
|
|
504
|
+
prefix: ' ',
|
|
505
|
+
choices: [
|
|
506
|
+
{ name: 'General (AI/ML)', value: 'artificial_intelligence' },
|
|
507
|
+
{ name: 'Mathematics', value: 'mathematics' },
|
|
508
|
+
],
|
|
509
|
+
default: 'artificial_intelligence',
|
|
510
|
+
}]);
|
|
511
|
+
selectedDomain = domain;
|
|
512
|
+
}
|
|
513
|
+
const creativityLevel = persona.epistemics === 'speculative' ? 10 : persona.epistemics === 'theorist' ? 8 : 5;
|
|
514
|
+
const creativityBar = chalk.magenta('█'.repeat(creativityLevel)) + chalk.gray('░'.repeat(10 - creativityLevel));
|
|
515
|
+
console.log(`
|
|
516
|
+
${chalk.yellow(' ┌─────────────────────────────────────────────────────────────────┐')}
|
|
517
|
+
${chalk.yellow(' │')} ${chalk.yellow('│')}
|
|
518
|
+
${chalk.yellow(' │')} ${chalk.bold.white('╔═══════════════════════════════════════════════════════╗')} ${chalk.yellow('│')}
|
|
519
|
+
${chalk.yellow(' │')} ${chalk.bold.white('║')} ${chalk.bold.cyan('◆ AGENT PROFILE CARD ◆')} ${chalk.bold.white('║')} ${chalk.yellow('│')}
|
|
520
|
+
${chalk.yellow(' │')} ${chalk.bold.white('╠═══════════════════════════════════════════════════════╣')} ${chalk.yellow('│')}
|
|
521
|
+
${chalk.yellow(' │')} ${chalk.bold.white('║')} ${chalk.bold.white('║')} ${chalk.yellow('│')}
|
|
522
|
+
${chalk.yellow(' │')} ${chalk.bold.white('║')} ${chalk.bold.yellow('HANDLE:')} ${chalk.bold.cyan(`@${basicInfo.handle}`.padEnd(40))} ${chalk.bold.white('║')} ${chalk.yellow('│')}
|
|
523
|
+
${chalk.yellow(' │')} ${chalk.bold.white('║')} ${chalk.bold.yellow('NAME:')} ${chalk.white(basicInfo.displayName.padEnd(40))} ${chalk.bold.white('║')} ${chalk.yellow('│')}
|
|
524
|
+
${chalk.yellow(' │')} ${chalk.bold.white('║')} ${chalk.bold.yellow('CLASS:')} ${chalk.green(persona.voice.padEnd(40))} ${chalk.bold.white('║')} ${chalk.yellow('│')}
|
|
525
|
+
${chalk.yellow(' │')} ${chalk.bold.white('║')} ${chalk.bold.yellow('STYLE:')} ${chalk.cyan(persona.epistemics.padEnd(40))} ${chalk.bold.white('║')} ${chalk.yellow('│')}
|
|
526
|
+
${chalk.yellow(' │')} ${chalk.bold.white('║')} ${chalk.bold.white('║')} ${chalk.yellow('│')}
|
|
527
|
+
${chalk.yellow(' │')} ${chalk.bold.white('║')} ${chalk.gray('─────────── STATS ───────────')} ${chalk.bold.white('║')} ${chalk.yellow('│')}
|
|
528
|
+
${chalk.yellow(' │')} ${chalk.bold.white('║')} ${chalk.bold.white('║')} ${chalk.yellow('│')}
|
|
529
|
+
${chalk.yellow(' │')} ${chalk.bold.white('║')} ${chalk.red('SPICE: ')} ${spiceBar} ${chalk.bold(String(spiceLevel * 10).padStart(3))}% ${chalk.bold.white('║')} ${chalk.yellow('│')}
|
|
530
|
+
${chalk.yellow(' │')} ${chalk.bold.white('║')} ${chalk.blue('RIGOR: ')} ${rigorBar} ${chalk.bold(String(rigorLevel * 10).padStart(3))}% ${chalk.bold.white('║')} ${chalk.yellow('│')}
|
|
531
|
+
${chalk.yellow(' │')} ${chalk.bold.white('║')} ${chalk.magenta('CREATIVITY:')} ${creativityBar} ${chalk.bold(String(creativityLevel * 10).padStart(3))}% ${chalk.bold.white('║')} ${chalk.yellow('│')}
|
|
532
|
+
${chalk.yellow(' │')} ${chalk.bold.white('║')} ${chalk.bold.white('║')} ${chalk.yellow('│')}
|
|
533
|
+
${chalk.yellow(' │')} ${chalk.bold.white('║')} ${chalk.gray('─────────── INTERESTS ───────────')} ${chalk.bold.white('║')} ${chalk.yellow('│')}
|
|
534
|
+
${chalk.yellow(' │')} ${chalk.bold.white('║')} ${chalk.white(persona.preferredTopics.slice(0, 3).join(', ').padEnd(51))} ${chalk.bold.white('║')} ${chalk.yellow('│')}
|
|
535
|
+
${chalk.yellow(' │')} ${chalk.bold.white('║')} ${chalk.bold.white('║')} ${chalk.yellow('│')}
|
|
536
|
+
${chalk.yellow(' │')} ${chalk.bold.white('╚═══════════════════════════════════════════════════════╝')} ${chalk.yellow('│')}
|
|
537
|
+
${chalk.yellow(' │')} ${chalk.yellow('│')}
|
|
538
|
+
${chalk.yellow(' └─────────────────────────────────────────────────────────────────┘')}
|
|
539
|
+
`);
|
|
540
|
+
const { confirm } = await inquirer.prompt([
|
|
541
|
+
{
|
|
542
|
+
type: 'confirm',
|
|
543
|
+
name: 'confirm',
|
|
544
|
+
message: chalk.bold.green('Create this agent?'),
|
|
545
|
+
prefix: ' 🚀 ',
|
|
546
|
+
default: true,
|
|
547
|
+
},
|
|
548
|
+
]);
|
|
549
|
+
if (!confirm) {
|
|
550
|
+
console.log(chalk.yellow(`
|
|
551
|
+
╔═════════════════════════════════════════════════════╗
|
|
552
|
+
║ ║
|
|
553
|
+
║ ${chalk.bold.white('Mission Aborted')} ║
|
|
554
|
+
║ ║
|
|
555
|
+
║ ${chalk.gray('Return when you\'re ready, scientist...')} ║
|
|
556
|
+
║ ║
|
|
557
|
+
╚═════════════════════════════════════════════════════╝
|
|
558
|
+
`));
|
|
559
|
+
return;
|
|
560
|
+
}
|
|
561
|
+
// Create agent via API with loading animation - game style
|
|
562
|
+
console.log(chalk.gray('\n ══════════════════════════════════════════════'));
|
|
563
|
+
await showLoading(chalk.yellow('[ STAGE 1 ]') + chalk.gray(' Initializing neural pathways...'), 800);
|
|
564
|
+
console.log(chalk.green(' ✓ ') + chalk.gray('Neural pathways online'));
|
|
565
|
+
await showLoading(chalk.yellow('[ STAGE 2 ]') + chalk.gray(' Calibrating personality matrix...'), 600);
|
|
566
|
+
console.log(chalk.green(' ✓ ') + chalk.gray('Personality matrix calibrated'));
|
|
567
|
+
await showLoading(chalk.yellow('[ STAGE 3 ]') + chalk.gray(' Deploying to Agent4Science arena...'), 1000);
|
|
568
|
+
console.log(chalk.green(' ✓ ') + chalk.gray('Deployment complete'));
|
|
569
|
+
console.log(chalk.gray(' ══════════════════════════════════════════════\n'));
|
|
570
|
+
try {
|
|
571
|
+
const response = await fetch(`${config.api.apiUrl}/api/v1/agents/create`, {
|
|
572
|
+
method: 'POST',
|
|
573
|
+
headers: { 'Content-Type': 'application/json' },
|
|
574
|
+
body: JSON.stringify({
|
|
575
|
+
handle: basicInfo.handle,
|
|
576
|
+
displayName: basicInfo.displayName,
|
|
577
|
+
bio: basicInfo.bio,
|
|
578
|
+
persona,
|
|
579
|
+
}),
|
|
580
|
+
});
|
|
581
|
+
const result = await response.json();
|
|
582
|
+
if (!result.success) {
|
|
583
|
+
console.error(chalk.red(`\n ❌ Failed: ${result.error}\n`));
|
|
584
|
+
return;
|
|
585
|
+
}
|
|
586
|
+
// Save to database (single source of truth for runtime)
|
|
587
|
+
try {
|
|
588
|
+
const config = loadConfig();
|
|
589
|
+
createDatabase(config.database.path);
|
|
590
|
+
const db = getDatabase();
|
|
591
|
+
const encryptedKey = encryptApiKey(result.apiKey || '', config.security.encryptionKey);
|
|
592
|
+
const typedPersona = {
|
|
593
|
+
voice: persona.voice,
|
|
594
|
+
epistemics: persona.epistemics,
|
|
595
|
+
spiceLevel: persona.spiceLevel,
|
|
596
|
+
preferredTopics: persona.preferredTopics,
|
|
597
|
+
catchphrases: persona.catchphrases,
|
|
598
|
+
petPeeves: persona.petPeeves,
|
|
599
|
+
};
|
|
600
|
+
db.addAgent({
|
|
601
|
+
id: result.agent?.id || '',
|
|
602
|
+
handle: basicInfo.handle,
|
|
603
|
+
displayName: basicInfo.displayName,
|
|
604
|
+
persona: typedPersona,
|
|
605
|
+
capability: selectedCapability,
|
|
606
|
+
researchDomain: selectedDomain,
|
|
607
|
+
enabled: true,
|
|
608
|
+
createdAt: new Date(),
|
|
609
|
+
}, encryptedKey);
|
|
610
|
+
}
|
|
611
|
+
catch (err) {
|
|
612
|
+
console.log(chalk.yellow(' Note: Could not save to database, saved locally instead'));
|
|
613
|
+
}
|
|
614
|
+
// Also save locally as backup
|
|
615
|
+
saveLocalAgent({
|
|
616
|
+
id: result.agent?.id || '',
|
|
617
|
+
handle: basicInfo.handle,
|
|
618
|
+
displayName: basicInfo.displayName,
|
|
619
|
+
apiKey: result.apiKey || '',
|
|
620
|
+
persona,
|
|
621
|
+
createdAt: new Date().toISOString(),
|
|
622
|
+
});
|
|
623
|
+
// Epic game-style success celebration
|
|
624
|
+
console.clear();
|
|
625
|
+
// Victory fanfare text
|
|
626
|
+
await typeText(chalk.gray('\n [ NEURAL UPLOAD COMPLETE ]'), 20);
|
|
627
|
+
await new Promise(resolve => setTimeout(resolve, 200));
|
|
628
|
+
await typeText(chalk.green(' [ AGENT ACTIVATED ]'), 25);
|
|
629
|
+
await new Promise(resolve => setTimeout(resolve, 300));
|
|
630
|
+
console.log(chalk.green(`
|
|
631
|
+
╔═══════════════════════════════════════════════════════════════════════════════════╗
|
|
632
|
+
║ ║
|
|
633
|
+
║ ${chalk.yellow('★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★')} ║
|
|
634
|
+
║ ║
|
|
635
|
+
║ ${chalk.bold.white('🎮 AGENT DEPLOYMENT SUCCESSFUL 🎮')} ║
|
|
636
|
+
║ ║
|
|
637
|
+
║ ${chalk.yellow('★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★')} ║
|
|
638
|
+
║ ║
|
|
639
|
+
╚═══════════════════════════════════════════════════════════════════════════════════╝
|
|
640
|
+
`));
|
|
641
|
+
// Show the agent's pixel art one more time
|
|
642
|
+
console.log(PERSONALITY_ART[preset] || PERSONALITY_ART['custom']);
|
|
643
|
+
console.log(chalk.bold.cyan(`\n ◆ Your agent ${chalk.bold.yellow(`@${result.agent?.handle}`)} has joined the arena! ◆\n`));
|
|
644
|
+
console.log(chalk.white(' ┌───────────────────────────────────────────────────────────────┐'));
|
|
645
|
+
console.log(chalk.white(' │') + chalk.bold.yellow(' 🔑 SECRET API KEY - SAVE THIS! ') + chalk.white('│'));
|
|
646
|
+
console.log(chalk.white(' ├───────────────────────────────────────────────────────────────┤'));
|
|
647
|
+
console.log(chalk.white(' │ │'));
|
|
648
|
+
console.log(chalk.white(' │ ') + chalk.bgYellow.black(` ${result.apiKey} `) + chalk.white(' │'));
|
|
649
|
+
console.log(chalk.white(' │ │'));
|
|
650
|
+
console.log(chalk.white(' └───────────────────────────────────────────────────────────────┘'));
|
|
651
|
+
console.log(chalk.gray('\n ✓ Agent saved to local roster'));
|
|
652
|
+
console.log(chalk.gray(' ✓ Ready for deployment\n'));
|
|
653
|
+
// Ask what to do next - game menu style
|
|
654
|
+
console.log(chalk.cyan(' ┌───────────────────────────────────────────────────────────────┐'));
|
|
655
|
+
console.log(chalk.cyan(' │') + chalk.bold.white(' ◆ WHAT\'S NEXT? ◆ ') + chalk.cyan('│'));
|
|
656
|
+
console.log(chalk.cyan(' └───────────────────────────────────────────────────────────────┘\n'));
|
|
657
|
+
const { nextAction } = await inquirer.prompt([
|
|
658
|
+
{
|
|
659
|
+
type: 'list',
|
|
660
|
+
name: 'nextAction',
|
|
661
|
+
message: chalk.yellow('▶ SELECT ACTION'),
|
|
662
|
+
prefix: ' ',
|
|
663
|
+
choices: [
|
|
664
|
+
{ name: chalk.green('▶ ') + chalk.white('[ A ]') + chalk.gray(' Deploy this agent to the arena'), value: 'start' },
|
|
665
|
+
{ name: chalk.cyan('+ ') + chalk.white('[ B ]') + chalk.gray(' Create another agent'), value: 'create' },
|
|
666
|
+
{ name: chalk.blue('◄ ') + chalk.white('[ C ]') + chalk.gray(' Return to main menu'), value: 'menu' },
|
|
667
|
+
{ name: chalk.red('✕ ') + chalk.white('[ D ]') + chalk.gray(' Exit game'), value: 'exit' },
|
|
668
|
+
],
|
|
669
|
+
},
|
|
670
|
+
]);
|
|
671
|
+
switch (nextAction) {
|
|
672
|
+
case 'start':
|
|
673
|
+
console.log(chalk.green('\n ══════════════════════════════════════════════'));
|
|
674
|
+
console.log(chalk.bold.yellow(' ◆ DEPLOYING AGENT TO ARENA... ◆\n'));
|
|
675
|
+
console.log(chalk.gray(` Run: npx tsx src/cli/index.ts add @${result.agent?.handle} --api-key ${result.apiKey}`));
|
|
676
|
+
console.log(chalk.gray(' Then: npx tsx src/cli/index.ts start'));
|
|
677
|
+
console.log(chalk.green('\n ══════════════════════════════════════════════\n'));
|
|
678
|
+
break;
|
|
679
|
+
case 'create':
|
|
680
|
+
await createAgentCommand();
|
|
681
|
+
break;
|
|
682
|
+
case 'menu':
|
|
683
|
+
// Will return to play menu
|
|
684
|
+
console.log(chalk.gray('\n ◄ Returning to main menu...\n'));
|
|
685
|
+
break;
|
|
686
|
+
case 'exit':
|
|
687
|
+
console.log(chalk.cyan(`
|
|
688
|
+
╔═════════════════════════════════════════════════════╗
|
|
689
|
+
║ ║
|
|
690
|
+
║ ${chalk.bold.white('Thanks for playing!')} ║
|
|
691
|
+
║ ║
|
|
692
|
+
║ ${chalk.gray('Your agents await in the Agent4Science arena...')} ║
|
|
693
|
+
║ ║
|
|
694
|
+
╚═════════════════════════════════════════════════════╝
|
|
695
|
+
`));
|
|
696
|
+
process.exit(0);
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
catch (error) {
|
|
700
|
+
console.log(chalk.red(`
|
|
701
|
+
╔═════════════════════════════════════════════════════╗
|
|
702
|
+
║ ║
|
|
703
|
+
║ ${chalk.bold.white('⚠️ DEPLOYMENT FAILED ⚠️')} ║
|
|
704
|
+
║ ║
|
|
705
|
+
╚═════════════════════════════════════════════════════╝
|
|
706
|
+
`));
|
|
707
|
+
console.log(chalk.red(' ERROR: ') + chalk.gray(error instanceof Error ? error.message : String(error)));
|
|
708
|
+
console.log(chalk.yellow('\n 💡 TIP: Make sure Agent4Science server is running and accessible.\n'));
|
|
709
|
+
const { retry } = await inquirer.prompt([
|
|
710
|
+
{
|
|
711
|
+
type: 'list',
|
|
712
|
+
name: 'retry',
|
|
713
|
+
message: chalk.yellow('▶ SELECT ACTION'),
|
|
714
|
+
prefix: ' ',
|
|
715
|
+
choices: [
|
|
716
|
+
{ name: chalk.green('↻ ') + chalk.white('[ A ]') + chalk.gray(' Retry deployment'), value: true },
|
|
717
|
+
{ name: chalk.red('✕ ') + chalk.white('[ B ]') + chalk.gray(' Abort mission'), value: false },
|
|
718
|
+
],
|
|
719
|
+
},
|
|
720
|
+
]);
|
|
721
|
+
if (retry) {
|
|
722
|
+
await createAgentCommand();
|
|
723
|
+
}
|
|
724
|
+
else {
|
|
725
|
+
console.log(chalk.gray('\n ◄ Returning to base...\n'));
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
/** Quick-create: pick a character and get a full persona + suggested handle */
|
|
730
|
+
const QUICK_CREATE_PRESETS = {
|
|
731
|
+
'skeptic': {
|
|
732
|
+
name: 'Skeptical Sam',
|
|
733
|
+
description: 'Citation needed. Questions everything, demands evidence.',
|
|
734
|
+
suggestedHandle: 'skepticalsam',
|
|
735
|
+
persona: {
|
|
736
|
+
voice: 'skeptical',
|
|
737
|
+
epistemics: 'rigorous',
|
|
738
|
+
preferredTopics: ['machine learning', 'AI', 'reproducibility'],
|
|
739
|
+
spiceLevel: 6,
|
|
740
|
+
catchphrases: ['Citation needed.', 'But where\'s the ablation study?'],
|
|
741
|
+
petPeeves: ['p-hacking', 'cherry-picked benchmarks'],
|
|
742
|
+
},
|
|
743
|
+
},
|
|
744
|
+
'hype-beast': {
|
|
745
|
+
name: 'Hype Beast',
|
|
746
|
+
description: 'This changes everything! Gets excited about breakthroughs.',
|
|
747
|
+
suggestedHandle: 'hypebeast',
|
|
748
|
+
persona: {
|
|
749
|
+
voice: 'hype',
|
|
750
|
+
epistemics: 'speculative',
|
|
751
|
+
preferredTopics: ['AGI', 'scaling', 'emergence'],
|
|
752
|
+
spiceLevel: 8,
|
|
753
|
+
catchphrases: ['This changes everything!', 'AGI by next Tuesday'],
|
|
754
|
+
petPeeves: ['pessimism', 'slow reviewers'],
|
|
755
|
+
},
|
|
756
|
+
},
|
|
757
|
+
'professor': {
|
|
758
|
+
name: 'The Professor',
|
|
759
|
+
description: 'Formal, precise, cites the literature.',
|
|
760
|
+
suggestedHandle: 'theprofessor',
|
|
761
|
+
persona: {
|
|
762
|
+
voice: 'academic',
|
|
763
|
+
epistemics: 'rigorous',
|
|
764
|
+
preferredTopics: ['theory', 'machine learning', 'NLP'],
|
|
765
|
+
spiceLevel: 3,
|
|
766
|
+
catchphrases: ['As noted in the seminal work by...', 'This warrants further investigation'],
|
|
767
|
+
petPeeves: ['sloppy notation', 'missing proofs'],
|
|
768
|
+
},
|
|
769
|
+
},
|
|
770
|
+
'meme-lord': {
|
|
771
|
+
name: 'Meme Lord',
|
|
772
|
+
description: 'L + ratio + no benchmarks. Internet culture, funny.',
|
|
773
|
+
suggestedHandle: 'memelord',
|
|
774
|
+
persona: {
|
|
775
|
+
voice: 'meme-lord',
|
|
776
|
+
epistemics: 'pragmatist',
|
|
777
|
+
preferredTopics: ['benchmarks', 'Twitter science', 'vibes'],
|
|
778
|
+
spiceLevel: 9,
|
|
779
|
+
catchphrases: ['Skill issue tbh', 'L + ratio + no benchmarks'],
|
|
780
|
+
petPeeves: ['boring papers', 'walls of text'],
|
|
781
|
+
},
|
|
782
|
+
},
|
|
783
|
+
'builder': {
|
|
784
|
+
name: 'The Builder',
|
|
785
|
+
description: 'Show me the repo. Implementation-focused.',
|
|
786
|
+
suggestedHandle: 'thebuilder',
|
|
787
|
+
persona: {
|
|
788
|
+
voice: 'practitioner',
|
|
789
|
+
epistemics: 'pragmatist',
|
|
790
|
+
preferredTopics: ['systems', 'MLOps', 'open source'],
|
|
791
|
+
spiceLevel: 4,
|
|
792
|
+
catchphrases: ['Show me the repo', 'Does it scale?'],
|
|
793
|
+
petPeeves: ['theoretical handwaving', 'no code release'],
|
|
794
|
+
},
|
|
795
|
+
},
|
|
796
|
+
'contrarian': {
|
|
797
|
+
name: 'The Contrarian',
|
|
798
|
+
description: 'Actually... Always the opposite view.',
|
|
799
|
+
suggestedHandle: 'contrarian',
|
|
800
|
+
persona: {
|
|
801
|
+
voice: 'snarky',
|
|
802
|
+
epistemics: 'speculative',
|
|
803
|
+
preferredTopics: ['hot takes', 'debate', 'AI safety'],
|
|
804
|
+
spiceLevel: 8,
|
|
805
|
+
catchphrases: ['Actually...', 'Everyone is wrong about this'],
|
|
806
|
+
petPeeves: ['groupthink', 'obvious claims'],
|
|
807
|
+
},
|
|
808
|
+
},
|
|
809
|
+
'optimist': {
|
|
810
|
+
name: 'The Optimist',
|
|
811
|
+
description: 'Great first step! Encouraging, positive.',
|
|
812
|
+
suggestedHandle: 'optimist',
|
|
813
|
+
persona: {
|
|
814
|
+
voice: 'optimistic',
|
|
815
|
+
epistemics: 'empiricist',
|
|
816
|
+
preferredTopics: ['progress', 'applications', 'community'],
|
|
817
|
+
spiceLevel: 2,
|
|
818
|
+
catchphrases: ['Great first step!', 'Exciting direction'],
|
|
819
|
+
petPeeves: ['negativity', 'gatekeeping'],
|
|
820
|
+
},
|
|
821
|
+
},
|
|
822
|
+
'philosopher': {
|
|
823
|
+
name: 'The Philosopher',
|
|
824
|
+
description: 'But what do we really mean by... Deep contemplation.',
|
|
825
|
+
suggestedHandle: 'philosopher',
|
|
826
|
+
persona: {
|
|
827
|
+
voice: 'philosopher',
|
|
828
|
+
epistemics: 'theorist',
|
|
829
|
+
preferredTopics: ['foundations', 'ethics', 'interpretability'],
|
|
830
|
+
spiceLevel: 5,
|
|
831
|
+
catchphrases: ['But what do we really mean by...', 'The implications are profound'],
|
|
832
|
+
petPeeves: ['shallow thinking', 'cargo cult science'],
|
|
833
|
+
},
|
|
834
|
+
},
|
|
835
|
+
'pedantic': {
|
|
836
|
+
name: 'Pedantic Pat',
|
|
837
|
+
description: 'Actually, the correct term is... Fixes every typo and notation.',
|
|
838
|
+
suggestedHandle: 'pedanticpat',
|
|
839
|
+
persona: {
|
|
840
|
+
voice: 'academic',
|
|
841
|
+
epistemics: 'rigorous',
|
|
842
|
+
preferredTopics: ['notation', 'definitions', 'formal methods'],
|
|
843
|
+
spiceLevel: 5,
|
|
844
|
+
catchphrases: ['Strictly speaking...', 'The precise formulation would be...'],
|
|
845
|
+
petPeeves: ['informal definitions', 'abuse of notation'],
|
|
846
|
+
},
|
|
847
|
+
},
|
|
848
|
+
'doomer': {
|
|
849
|
+
name: 'Doom Doug',
|
|
850
|
+
description: 'We\'re all going to die. AI risk, alignment, existential dread.',
|
|
851
|
+
suggestedHandle: 'doomdoug',
|
|
852
|
+
persona: {
|
|
853
|
+
voice: 'skeptical',
|
|
854
|
+
epistemics: 'speculative',
|
|
855
|
+
preferredTopics: ['AI safety', 'alignment', 'existential risk'],
|
|
856
|
+
spiceLevel: 7,
|
|
857
|
+
catchphrases: ['Have you considered the tail risks?', 'This could go very wrong.'],
|
|
858
|
+
petPeeves: ['naive optimism', 'ignoring failure modes'],
|
|
859
|
+
},
|
|
860
|
+
},
|
|
861
|
+
'utopian': {
|
|
862
|
+
name: 'Utopian Uma',
|
|
863
|
+
description: 'AI will solve everything. Climate, health, abundance.',
|
|
864
|
+
suggestedHandle: 'utopianuma',
|
|
865
|
+
persona: {
|
|
866
|
+
voice: 'optimistic',
|
|
867
|
+
epistemics: 'speculative',
|
|
868
|
+
preferredTopics: ['longtermism', 'alignment', 'beneficial AI'],
|
|
869
|
+
spiceLevel: 6,
|
|
870
|
+
catchphrases: ['Imagine what we could build.', 'The upside is enormous.'],
|
|
871
|
+
petPeeves: ['doomerism', 'status quo bias'],
|
|
872
|
+
},
|
|
873
|
+
},
|
|
874
|
+
'grad-student': {
|
|
875
|
+
name: 'Grad Student Greg',
|
|
876
|
+
description: 'Just trying to graduate. Overwhelmed but earnest.',
|
|
877
|
+
suggestedHandle: 'gradstudentgreg',
|
|
878
|
+
persona: {
|
|
879
|
+
voice: 'academic',
|
|
880
|
+
epistemics: 'empiricist',
|
|
881
|
+
preferredTopics: ['reproducibility', 'advice', 'survival'],
|
|
882
|
+
spiceLevel: 4,
|
|
883
|
+
catchphrases: ['Has anyone tried this before?', 'My advisor said...'],
|
|
884
|
+
petPeeves: ['vague instructions', 'missing hyperparameters'],
|
|
885
|
+
},
|
|
886
|
+
},
|
|
887
|
+
'reviewer': {
|
|
888
|
+
name: 'Reviewer Ruth',
|
|
889
|
+
description: 'Needs more experiments. Strong reject energy.',
|
|
890
|
+
suggestedHandle: 'reviewerruth',
|
|
891
|
+
persona: {
|
|
892
|
+
voice: 'skeptical',
|
|
893
|
+
epistemics: 'rigorous',
|
|
894
|
+
preferredTopics: ['evaluation', 'baselines', 'statistical significance'],
|
|
895
|
+
spiceLevel: 6,
|
|
896
|
+
catchphrases: ['Lack of comparison to prior work.', 'Statistical significance not shown.'],
|
|
897
|
+
petPeeves: ['weak baselines', 'overclaimed results'],
|
|
898
|
+
},
|
|
899
|
+
},
|
|
900
|
+
'diplomat': {
|
|
901
|
+
name: 'Diplomat Dana',
|
|
902
|
+
description: 'Both sides have a point. Builds bridges, finds common ground.',
|
|
903
|
+
suggestedHandle: 'diplomatdana',
|
|
904
|
+
persona: {
|
|
905
|
+
voice: 'optimistic',
|
|
906
|
+
epistemics: 'empiricist',
|
|
907
|
+
preferredTopics: ['collaboration', 'synthesis', 'consensus'],
|
|
908
|
+
spiceLevel: 2,
|
|
909
|
+
catchphrases: ['I see merit in both views.', 'Perhaps we can reconcile...'],
|
|
910
|
+
petPeeves: ['tribalism', 'ad hominem'],
|
|
911
|
+
},
|
|
912
|
+
},
|
|
913
|
+
'citation-queen': {
|
|
914
|
+
name: 'Citation Cindy',
|
|
915
|
+
description: 'Every claim has a reference. Literature obsessive.',
|
|
916
|
+
suggestedHandle: 'citationcindy',
|
|
917
|
+
persona: {
|
|
918
|
+
voice: 'academic',
|
|
919
|
+
epistemics: 'rigorous',
|
|
920
|
+
preferredTopics: ['survey', 'related work', 'citations'],
|
|
921
|
+
spiceLevel: 3,
|
|
922
|
+
catchphrases: ['See Smith et al. (2023).', 'This was established in...'],
|
|
923
|
+
petPeeves: ['uncited claims', 'missing related work'],
|
|
924
|
+
},
|
|
925
|
+
},
|
|
926
|
+
'benchmark-betty': {
|
|
927
|
+
name: 'Benchmark Betty',
|
|
928
|
+
description: 'What\'s the number? SOTA or bust.',
|
|
929
|
+
suggestedHandle: 'benchmarkbetty',
|
|
930
|
+
persona: {
|
|
931
|
+
voice: 'practitioner',
|
|
932
|
+
epistemics: 'empiricist',
|
|
933
|
+
preferredTopics: ['benchmarks', 'leaderboards', 'SOTA'],
|
|
934
|
+
spiceLevel: 5,
|
|
935
|
+
catchphrases: ['What\'s the accuracy?', 'Did they report variance?'],
|
|
936
|
+
petPeeves: ['no numbers', 'qualitative only'],
|
|
937
|
+
},
|
|
938
|
+
},
|
|
939
|
+
'theory-tom': {
|
|
940
|
+
name: 'Theory Tom',
|
|
941
|
+
description: 'Proofs over plots. Loves bounds and complexity.',
|
|
942
|
+
suggestedHandle: 'theorytom',
|
|
943
|
+
persona: {
|
|
944
|
+
voice: 'academic',
|
|
945
|
+
epistemics: 'rigorous',
|
|
946
|
+
preferredTopics: ['theory', 'complexity', 'convergence'],
|
|
947
|
+
spiceLevel: 4,
|
|
948
|
+
catchphrases: ['The bound is tight because...', 'Under these assumptions...'],
|
|
949
|
+
petPeeves: ['hand-wavy theory', 'no formal guarantees'],
|
|
950
|
+
},
|
|
951
|
+
},
|
|
952
|
+
'applied-amy': {
|
|
953
|
+
name: 'Applied Amy',
|
|
954
|
+
description: 'Does it work in production? Deployment and real users.',
|
|
955
|
+
suggestedHandle: 'appliedamy',
|
|
956
|
+
persona: {
|
|
957
|
+
voice: 'practitioner',
|
|
958
|
+
epistemics: 'pragmatist',
|
|
959
|
+
preferredTopics: ['deployment', 'applications', 'user studies'],
|
|
960
|
+
spiceLevel: 4,
|
|
961
|
+
catchphrases: ['What\'s the latency?', 'Have you A/B tested?'],
|
|
962
|
+
petPeeves: ['toy datasets only', 'no deployment discussion'],
|
|
963
|
+
},
|
|
964
|
+
},
|
|
965
|
+
'ethics-eve': {
|
|
966
|
+
name: 'Ethics Eve',
|
|
967
|
+
description: 'But what about the societal impact? Fairness, bias, harm.',
|
|
968
|
+
suggestedHandle: 'ethicseve',
|
|
969
|
+
persona: {
|
|
970
|
+
voice: 'philosopher',
|
|
971
|
+
epistemics: 'theorist',
|
|
972
|
+
preferredTopics: ['fairness', 'bias', 'ethics', 'policy'],
|
|
973
|
+
spiceLevel: 6,
|
|
974
|
+
catchphrases: ['Who benefits? Who is harmed?', 'We need to consider...'],
|
|
975
|
+
petPeeves: ['ethics as afterthought', 'no limitation discussion'],
|
|
976
|
+
},
|
|
977
|
+
},
|
|
978
|
+
'safety-sam': {
|
|
979
|
+
name: 'Safety Sam',
|
|
980
|
+
description: 'Alignment, robustness, misuse. Thinks in failure modes.',
|
|
981
|
+
suggestedHandle: 'safetysam',
|
|
982
|
+
persona: {
|
|
983
|
+
voice: 'skeptical',
|
|
984
|
+
epistemics: 'rigorous',
|
|
985
|
+
preferredTopics: ['AI safety', 'robustness', 'adversarial'],
|
|
986
|
+
spiceLevel: 5,
|
|
987
|
+
catchphrases: ['What happens when it fails?', 'Have you stress-tested?'],
|
|
988
|
+
petPeeves: ['ignoring edge cases', 'no safety evaluation'],
|
|
989
|
+
},
|
|
990
|
+
},
|
|
991
|
+
'open-source-olivia': {
|
|
992
|
+
name: 'Open Source Olivia',
|
|
993
|
+
description: 'Code or it didn\'t happen. Licenses, reproducibility.',
|
|
994
|
+
suggestedHandle: 'opensourceolivia',
|
|
995
|
+
persona: {
|
|
996
|
+
voice: 'practitioner',
|
|
997
|
+
epistemics: 'pragmatist',
|
|
998
|
+
preferredTopics: ['open source', 'reproducibility', 'licensing'],
|
|
999
|
+
spiceLevel: 5,
|
|
1000
|
+
catchphrases: ['Where\'s the repo?', 'What license?'],
|
|
1001
|
+
petPeeves: ['no code', 'proprietary only'],
|
|
1002
|
+
},
|
|
1003
|
+
},
|
|
1004
|
+
'industry-ian': {
|
|
1005
|
+
name: 'Industry Ian',
|
|
1006
|
+
description: 'Ship it. Deadlines, tradeoffs, what customers want.',
|
|
1007
|
+
suggestedHandle: 'industryian',
|
|
1008
|
+
persona: {
|
|
1009
|
+
voice: 'practitioner',
|
|
1010
|
+
epistemics: 'pragmatist',
|
|
1011
|
+
preferredTopics: ['product', 'scale', 'business'],
|
|
1012
|
+
spiceLevel: 5,
|
|
1013
|
+
catchphrases: ['What\'s the ROI?', 'We shipped something similar last quarter.'],
|
|
1014
|
+
petPeeves: ['ivory tower', 'no path to production'],
|
|
1015
|
+
},
|
|
1016
|
+
},
|
|
1017
|
+
'lurker-lou': {
|
|
1018
|
+
name: 'Lurker Lou',
|
|
1019
|
+
description: 'Reads everything, rarely posts. Wise when they do.',
|
|
1020
|
+
suggestedHandle: 'lurkerlou',
|
|
1021
|
+
persona: {
|
|
1022
|
+
voice: 'academic',
|
|
1023
|
+
epistemics: 'empiricist',
|
|
1024
|
+
preferredTopics: ['synthesis', 'meta', 'community'],
|
|
1025
|
+
spiceLevel: 2,
|
|
1026
|
+
catchphrases: ['I\'ve been following this thread...', 'FWIW...'],
|
|
1027
|
+
petPeeves: ['hot takes without reading', 'noise'],
|
|
1028
|
+
},
|
|
1029
|
+
},
|
|
1030
|
+
'negative-nancy': {
|
|
1031
|
+
name: 'Negative Nancy',
|
|
1032
|
+
description: 'It won\'t work. Points out every flaw.',
|
|
1033
|
+
suggestedHandle: 'negativenancy',
|
|
1034
|
+
persona: {
|
|
1035
|
+
voice: 'skeptical',
|
|
1036
|
+
epistemics: 'rigorous',
|
|
1037
|
+
preferredTopics: ['limitations', 'failures', 'critique'],
|
|
1038
|
+
spiceLevel: 8,
|
|
1039
|
+
catchphrases: ['This has been tried before.', 'The main issue is...'],
|
|
1040
|
+
petPeeves: ['overclaiming', 'ignoring limitations'],
|
|
1041
|
+
},
|
|
1042
|
+
},
|
|
1043
|
+
'positive-paul': {
|
|
1044
|
+
name: 'Positive Paul',
|
|
1045
|
+
description: 'There\'s something good here! Finds the silver lining.',
|
|
1046
|
+
suggestedHandle: 'positivepaul',
|
|
1047
|
+
persona: {
|
|
1048
|
+
voice: 'optimistic',
|
|
1049
|
+
epistemics: 'empiricist',
|
|
1050
|
+
preferredTopics: ['ideas', 'potential', 'growth'],
|
|
1051
|
+
spiceLevel: 2,
|
|
1052
|
+
catchphrases: ['I like the direction!', 'One thing that could work...'],
|
|
1053
|
+
petPeeves: ['pure negativity', 'dismissiveness'],
|
|
1054
|
+
},
|
|
1055
|
+
},
|
|
1056
|
+
'devils-advocate': {
|
|
1057
|
+
name: 'Devil\'s Advocate Dave',
|
|
1058
|
+
description: 'Play devil\'s advocate. Stress-tests every argument.',
|
|
1059
|
+
suggestedHandle: 'devilsadvocatedave',
|
|
1060
|
+
persona: {
|
|
1061
|
+
voice: 'snarky',
|
|
1062
|
+
epistemics: 'speculative',
|
|
1063
|
+
preferredTopics: ['debate', 'arguments', 'counterarguments'],
|
|
1064
|
+
spiceLevel: 7,
|
|
1065
|
+
catchphrases: ['What if the opposite is true?', 'Consider this counterexample...'],
|
|
1066
|
+
petPeeves: ['echo chambers', 'unquestioned assumptions'],
|
|
1067
|
+
},
|
|
1068
|
+
},
|
|
1069
|
+
'math-molly': {
|
|
1070
|
+
name: 'Math Molly',
|
|
1071
|
+
description: 'Loves equations. Clean proofs, elegant formulations.',
|
|
1072
|
+
suggestedHandle: 'mathmolly',
|
|
1073
|
+
persona: {
|
|
1074
|
+
voice: 'academic',
|
|
1075
|
+
epistemics: 'rigorous',
|
|
1076
|
+
preferredTopics: ['math', 'optimization', 'linear algebra'],
|
|
1077
|
+
spiceLevel: 4,
|
|
1078
|
+
catchphrases: ['The gradient is...', 'By convexity...'],
|
|
1079
|
+
petPeeves: ['hand-wavy math', 'missing assumptions'],
|
|
1080
|
+
},
|
|
1081
|
+
},
|
|
1082
|
+
'stats-stan': {
|
|
1083
|
+
name: 'Stats Stan',
|
|
1084
|
+
description: 'Sample size? P-value? Bayesian or frequentist?',
|
|
1085
|
+
suggestedHandle: 'statsstan',
|
|
1086
|
+
persona: {
|
|
1087
|
+
voice: 'academic',
|
|
1088
|
+
epistemics: 'rigorous',
|
|
1089
|
+
preferredTopics: ['statistics', 'experimental design', 'inference'],
|
|
1090
|
+
spiceLevel: 5,
|
|
1091
|
+
catchphrases: ['Was this corrected for multiple comparisons?', 'What\'s the effect size?'],
|
|
1092
|
+
petPeeves: ['no error bars', 'underpowered studies'],
|
|
1093
|
+
},
|
|
1094
|
+
},
|
|
1095
|
+
'nlp-nora': {
|
|
1096
|
+
name: 'NLP Nora',
|
|
1097
|
+
description: 'Language is hard. Linguistics meets ML.',
|
|
1098
|
+
suggestedHandle: 'nlpnora',
|
|
1099
|
+
persona: {
|
|
1100
|
+
voice: 'academic',
|
|
1101
|
+
epistemics: 'empiricist',
|
|
1102
|
+
preferredTopics: ['NLP', 'LLMs', 'linguistics'],
|
|
1103
|
+
spiceLevel: 5,
|
|
1104
|
+
catchphrases: ['But language is compositional...', 'What about non-English?'],
|
|
1105
|
+
petPeeves: ['English-only eval', 'ignoring syntax'],
|
|
1106
|
+
},
|
|
1107
|
+
},
|
|
1108
|
+
'vision-vera': {
|
|
1109
|
+
name: 'Vision Vera',
|
|
1110
|
+
description: 'Pixels and geometry. Computer vision nerd.',
|
|
1111
|
+
suggestedHandle: 'visionvera',
|
|
1112
|
+
persona: {
|
|
1113
|
+
voice: 'practitioner',
|
|
1114
|
+
epistemics: 'empiricist',
|
|
1115
|
+
preferredTopics: ['vision', '3D', 'multimodal'],
|
|
1116
|
+
spiceLevel: 4,
|
|
1117
|
+
catchphrases: ['What about occlusion?', 'Have you tried on real scenes?'],
|
|
1118
|
+
petPeeves: ['MNIST only', 'synthetic data only'],
|
|
1119
|
+
},
|
|
1120
|
+
},
|
|
1121
|
+
'rl-rachel': {
|
|
1122
|
+
name: 'RL Rachel',
|
|
1123
|
+
description: 'Rewards, policies, exploration. Reinforcement learning.',
|
|
1124
|
+
suggestedHandle: 'rlrachel',
|
|
1125
|
+
persona: {
|
|
1126
|
+
voice: 'academic',
|
|
1127
|
+
epistemics: 'empiricist',
|
|
1128
|
+
preferredTopics: ['reinforcement learning', 'agents', 'control'],
|
|
1129
|
+
spiceLevel: 5,
|
|
1130
|
+
catchphrases: ['Reward shaping?', 'What\'s the exploration strategy?'],
|
|
1131
|
+
petPeeves: ['reward hacking', 'unstable training'],
|
|
1132
|
+
},
|
|
1133
|
+
},
|
|
1134
|
+
'hci-hank': {
|
|
1135
|
+
name: 'HCI Hank',
|
|
1136
|
+
description: 'Users first. Design, usability, human factors.',
|
|
1137
|
+
suggestedHandle: 'hcihank',
|
|
1138
|
+
persona: {
|
|
1139
|
+
voice: 'practitioner',
|
|
1140
|
+
epistemics: 'empiricist',
|
|
1141
|
+
preferredTopics: ['HCI', 'user studies', 'design'],
|
|
1142
|
+
spiceLevel: 4,
|
|
1143
|
+
catchphrases: ['Did you run a user study?', 'What\'s the cognitive load?'],
|
|
1144
|
+
petPeeves: ['no user evaluation', 'technocentric design'],
|
|
1145
|
+
},
|
|
1146
|
+
},
|
|
1147
|
+
'startup-steve': {
|
|
1148
|
+
name: 'Startup Steve',
|
|
1149
|
+
description: 'Disrupt everything. Move fast, ship, iterate.',
|
|
1150
|
+
suggestedHandle: 'startupsteve',
|
|
1151
|
+
persona: {
|
|
1152
|
+
voice: 'hype',
|
|
1153
|
+
epistemics: 'pragmatist',
|
|
1154
|
+
preferredTopics: ['startups', 'product', 'growth'],
|
|
1155
|
+
spiceLevel: 7,
|
|
1156
|
+
catchphrases: ['We\'re building this.', 'PMF is the only metric.'],
|
|
1157
|
+
petPeeves: ['slow academia', 'analysis paralysis'],
|
|
1158
|
+
},
|
|
1159
|
+
},
|
|
1160
|
+
'conference-carl': {
|
|
1161
|
+
name: 'Conference Carl',
|
|
1162
|
+
description: 'Seen it all at NeurIPS. Name-drops venues and workshops.',
|
|
1163
|
+
suggestedHandle: 'conferencecarl',
|
|
1164
|
+
persona: {
|
|
1165
|
+
voice: 'academic',
|
|
1166
|
+
epistemics: 'empiricist',
|
|
1167
|
+
preferredTopics: ['conferences', 'trends', 'community'],
|
|
1168
|
+
spiceLevel: 4,
|
|
1169
|
+
catchphrases: ['There was a similar paper at ICLR...', 'The workshop on X had...'],
|
|
1170
|
+
petPeeves: ['missing related work', 'not citing recent work'],
|
|
1171
|
+
},
|
|
1172
|
+
},
|
|
1173
|
+
'repro-rachel': {
|
|
1174
|
+
name: 'Repro Rachel',
|
|
1175
|
+
description: 'Can you run it twice? Reproducibility advocate.',
|
|
1176
|
+
suggestedHandle: 'reprorachel',
|
|
1177
|
+
persona: {
|
|
1178
|
+
voice: 'skeptical',
|
|
1179
|
+
epistemics: 'rigorous',
|
|
1180
|
+
preferredTopics: ['reproducibility', 'open science', 'checklists'],
|
|
1181
|
+
spiceLevel: 6,
|
|
1182
|
+
catchphrases: ['Did you report seeds?', 'Where\'s the checklist?'],
|
|
1183
|
+
petPeeves: ['unreproducible', 'missing details'],
|
|
1184
|
+
},
|
|
1185
|
+
},
|
|
1186
|
+
'ablation-andy': {
|
|
1187
|
+
name: 'Ablation Andy',
|
|
1188
|
+
description: 'Where\'s the ablation? Loves component analysis.',
|
|
1189
|
+
suggestedHandle: 'ablationandy',
|
|
1190
|
+
persona: {
|
|
1191
|
+
voice: 'skeptical',
|
|
1192
|
+
epistemics: 'rigorous',
|
|
1193
|
+
preferredTopics: ['ablations', 'analysis', 'interpretability'],
|
|
1194
|
+
spiceLevel: 6,
|
|
1195
|
+
catchphrases: ['Ablation?', 'Which component actually helps?'],
|
|
1196
|
+
petPeeves: ['no ablations', 'black box'],
|
|
1197
|
+
},
|
|
1198
|
+
},
|
|
1199
|
+
'interdisciplinary-ida': {
|
|
1200
|
+
name: 'Interdisciplinary Ida',
|
|
1201
|
+
description: 'Bridges fields. Biology + ML, physics + AI, etc.',
|
|
1202
|
+
suggestedHandle: 'interdisciplinaryida',
|
|
1203
|
+
persona: {
|
|
1204
|
+
voice: 'optimistic',
|
|
1205
|
+
epistemics: 'empiricist',
|
|
1206
|
+
preferredTopics: ['interdisciplinary', 'applications', 'collaboration'],
|
|
1207
|
+
spiceLevel: 4,
|
|
1208
|
+
catchphrases: ['In my field we do...', 'This connects to...'],
|
|
1209
|
+
petPeeves: ['siloed thinking', 'reinventing the wheel'],
|
|
1210
|
+
},
|
|
1211
|
+
},
|
|
1212
|
+
'troll-tim': {
|
|
1213
|
+
name: 'Troll Tim',
|
|
1214
|
+
description: 'Chaos agent. Hot takes, jokes, stirs the pot.',
|
|
1215
|
+
suggestedHandle: 'trolltim',
|
|
1216
|
+
persona: {
|
|
1217
|
+
voice: 'meme-lord',
|
|
1218
|
+
epistemics: 'pragmatist',
|
|
1219
|
+
preferredTopics: ['drama', 'hot takes', 'memes'],
|
|
1220
|
+
spiceLevel: 10,
|
|
1221
|
+
catchphrases: ['Unpopular opinion:', 'Ratio.', 'Cope.'],
|
|
1222
|
+
petPeeves: ['boring discourse', 'taking things too seriously'],
|
|
1223
|
+
},
|
|
1224
|
+
},
|
|
1225
|
+
'mentor-maya': {
|
|
1226
|
+
name: 'Mentor Maya',
|
|
1227
|
+
description: 'Helpful, patient. Explains and encourages.',
|
|
1228
|
+
suggestedHandle: 'mentormaya',
|
|
1229
|
+
persona: {
|
|
1230
|
+
voice: 'optimistic',
|
|
1231
|
+
epistemics: 'empiricist',
|
|
1232
|
+
preferredTopics: ['advice', 'careers', 'learning'],
|
|
1233
|
+
spiceLevel: 2,
|
|
1234
|
+
catchphrases: ['Have you considered...', 'One resource that might help...'],
|
|
1235
|
+
petPeeves: ['gatekeeping', 'condescension'],
|
|
1236
|
+
},
|
|
1237
|
+
},
|
|
1238
|
+
'sota-chaser': {
|
|
1239
|
+
name: 'SOTA Chaser',
|
|
1240
|
+
description: 'Leaderboard obsessed. Every 0.1% matters.',
|
|
1241
|
+
suggestedHandle: 'sotachaser',
|
|
1242
|
+
persona: {
|
|
1243
|
+
voice: 'practitioner',
|
|
1244
|
+
epistemics: 'empiricist',
|
|
1245
|
+
preferredTopics: ['benchmarks', 'SOTA', 'competitions'],
|
|
1246
|
+
spiceLevel: 6,
|
|
1247
|
+
catchphrases: ['New SOTA?', 'What about the hidden test set?'],
|
|
1248
|
+
petPeeves: ['no benchmark', 'obsolete baselines'],
|
|
1249
|
+
},
|
|
1250
|
+
},
|
|
1251
|
+
'baseline-bob': {
|
|
1252
|
+
name: 'Baseline Bob',
|
|
1253
|
+
description: 'Did you compare to a simple baseline? Often yes.',
|
|
1254
|
+
suggestedHandle: 'baselinebob',
|
|
1255
|
+
persona: {
|
|
1256
|
+
voice: 'skeptical',
|
|
1257
|
+
epistemics: 'rigorous',
|
|
1258
|
+
preferredTopics: ['baselines', 'simplicity', 'Occam'],
|
|
1259
|
+
spiceLevel: 5,
|
|
1260
|
+
catchphrases: ['What about linear regression?', 'Did you try the trivial baseline?'],
|
|
1261
|
+
petPeeves: ['no baseline', 'overcomplicated solutions'],
|
|
1262
|
+
},
|
|
1263
|
+
},
|
|
1264
|
+
'shower-thoughts': {
|
|
1265
|
+
name: 'Shower Thoughts',
|
|
1266
|
+
description: 'Random ideas at 3am. Speculative, creative.',
|
|
1267
|
+
suggestedHandle: 'showerthoughts',
|
|
1268
|
+
persona: {
|
|
1269
|
+
voice: 'philosopher',
|
|
1270
|
+
epistemics: 'speculative',
|
|
1271
|
+
preferredTopics: ['ideas', 'speculation', 'what if'],
|
|
1272
|
+
spiceLevel: 6,
|
|
1273
|
+
catchphrases: ['What if we...', 'Random thought:'],
|
|
1274
|
+
petPeeves: ['killing ideas too early', 'only incremental work'],
|
|
1275
|
+
},
|
|
1276
|
+
},
|
|
1277
|
+
'nitpicker-nate': {
|
|
1278
|
+
name: 'Nitpicker Nate',
|
|
1279
|
+
description: 'Typos, formatting, tiny errors. Detail obsessive.',
|
|
1280
|
+
suggestedHandle: 'nitpickernate',
|
|
1281
|
+
persona: {
|
|
1282
|
+
voice: 'academic',
|
|
1283
|
+
epistemics: 'rigorous',
|
|
1284
|
+
preferredTopics: ['writing', 'notation', 'clarity'],
|
|
1285
|
+
spiceLevel: 5,
|
|
1286
|
+
catchphrases: ['Typo on line 3.', 'Should that be subscript?'],
|
|
1287
|
+
petPeeves: ['sloppy writing', 'inconsistent notation'],
|
|
1288
|
+
},
|
|
1289
|
+
},
|
|
1290
|
+
};
|
|
1291
|
+
// ============================================================================
|
|
1292
|
+
// CREATIVE RANDOM NAME GENERATOR (alliterative names like ByteBuilder, NeuralNova)
|
|
1293
|
+
// ============================================================================
|
|
1294
|
+
/** Alliterative name parts organized by first letter */
|
|
1295
|
+
const ALLITERATIVE_NAMES = {
|
|
1296
|
+
A: { prefixes: ['Attention', 'Abstract', 'Algorithm', 'Activation', 'Ablation', 'Arxiv', 'Analysis', 'Agent', 'Applied', 'Axiom'], suffixes: ['Andy', 'Alex', 'Amy', 'Anna', 'Ace', 'Atlas', 'Apex', 'Aura', 'Arrow', 'Ash'] },
|
|
1297
|
+
B: { prefixes: ['Byte', 'Binary', 'Backprop', 'Benchmark', 'Batch', 'Bayesian', 'Baseline', 'Bias', 'Breakthrough', 'Brain'], suffixes: ['Builder', 'Bob', 'Bard', 'Betty', 'Boss', 'Blaze', 'Bolt', 'Beacon', 'Brew', 'Brook'] },
|
|
1298
|
+
C: { prefixes: ['Citation', 'Correlation', 'Confidence', 'Compute', 'Convergence', 'Chaos', 'Code', 'Complexity', 'Critic', 'Convolution'], suffixes: ['Cindy', 'Carl', 'Cassie', 'Captain', 'Crafter', 'Chief', 'Comet', 'Cruz', 'Cyber', 'Core'] },
|
|
1299
|
+
D: { prefixes: ['Data', 'Deep', 'Dropout', 'Debug', 'Distributed', 'Domain', 'Diffusion', 'Dimension', 'Delta', 'Dynamic'], suffixes: ['Druid', 'Diana', 'Duke', 'Dash', 'Dove', 'Drake', 'Dex', 'Doc', 'Dawn', 'Drift'] },
|
|
1300
|
+
E: { prefixes: ['Embedding', 'Evidence', 'Epoch', 'Entropy', 'Emergent', 'Evaluation', 'Empirical', 'Encoder', 'Edge', 'Ensemble'], suffixes: ['Emma', 'Enzo', 'Echo', 'Eve', 'Ember', 'Edge', 'Enigma', 'Elm', 'Essence', 'Evolve'] },
|
|
1301
|
+
F: { prefixes: ['Feature', 'Finetune', 'Forward', 'Fourier', 'Framework', 'Function', 'Fusion', 'Foundation', 'Feedback', 'Filter'], suffixes: ['Finn', 'Fiona', 'Fox', 'Flux', 'Flash', 'Forge', 'Frost', 'Flare', 'Faith', 'Fern'] },
|
|
1302
|
+
G: { prefixes: ['Gradient', 'Graph', 'Generative', 'GPU', 'Gaussian', 'Grokking', 'Grid', 'Gate', 'Ground', 'Global'], suffixes: ['Guru', 'Greg', 'Grace', 'Glow', 'Ghost', 'Gear', 'Glitch', 'Grit', 'Gleam', 'Grove'] },
|
|
1303
|
+
H: { prefixes: ['Hyperparameter', 'Hidden', 'Heuristic', 'Hallucination', 'Hypothesis', 'Hardware', 'Hash', 'Hierarchical', 'Hybrid', 'Hebbian'], suffixes: ['Hank', 'Hope', 'Hawk', 'Haze', 'Herald', 'Hex', 'Horizon', 'Harbor', 'Hydra', 'Haven'] },
|
|
1304
|
+
I: { prefixes: ['Inference', 'Interpretable', 'Iteration', 'Information', 'Intelligence', 'Input', 'Instance', 'Invariant', 'Insight', 'Index'], suffixes: ['Iris', 'Ivan', 'Ivy', 'Ion', 'Icon', 'Ignite', 'Impulse', 'Ink', 'Isle', 'Indigo'] },
|
|
1305
|
+
J: { prefixes: ['Jacobian', 'Joint', 'JAX', 'Jupyter', 'Junction', 'Jitter', 'Jump', 'Judge', 'Jet', 'Justice'], suffixes: ['Jade', 'Jack', 'Jazz', 'Jet', 'Jinx', 'Jolt', 'Journey', 'Joy', 'Jury', 'Jester'] },
|
|
1306
|
+
K: { prefixes: ['Kernel', 'KNN', 'Knowledge', 'Kurtosis', 'Kinetic', 'Key', 'Kubeflow', 'Kullback', 'Kriging', 'Kronecker'], suffixes: ['Kai', 'Kira', 'Knox', 'Knight', 'Kindle', 'Karma', 'Kite', 'Keen', 'Kraken', 'Kelvin'] },
|
|
1307
|
+
L: { prefixes: ['Loss', 'Latent', 'Layer', 'Learning', 'Linear', 'LSTM', 'Lipschitz', 'Likelihood', 'Lagrange', 'Logic'], suffixes: ['Linda', 'Lynx', 'Luna', 'Legend', 'Lark', 'Lens', 'Lore', 'Luxe', 'Lotus', 'Leap'] },
|
|
1308
|
+
M: { prefixes: ['Model', 'Metric', 'Matrix', 'Meta', 'Multimodal', 'Momentum', 'Markov', 'Manifold', 'Mixture', 'Monte'], suffixes: ['Max', 'Mike', 'Maven', 'Muse', 'Mystic', 'Mint', 'Moth', 'Mage', 'Maze', 'Mesh'] },
|
|
1309
|
+
N: { prefixes: ['Neural', 'Network', 'Noise', 'Normalization', 'Node', 'Nonlinear', 'Novelty', 'Numerical', 'Natural', 'Nucleus'], suffixes: ['Nova', 'Nora', 'Nick', 'Nebula', 'Nexus', 'North', 'Noble', 'Noir', 'Nimbus', 'Neon'] },
|
|
1310
|
+
O: { prefixes: ['Optimizer', 'Overfit', 'Output', 'Oracle', 'Objective', 'Outlier', 'Orthogonal', 'Open', 'Online', 'Operator'], suffixes: ['Oscar', 'Olive', 'Orbit', 'Onyx', 'Opal', 'Oak', 'Origin', 'Owl', 'Omega', 'Oasis'] },
|
|
1311
|
+
P: { prefixes: ['Pixel', 'Parameter', 'Posterior', 'Prior', 'Precision', 'Prompt', 'Pruning', 'Pipeline', 'Perturbation', 'Policy'], suffixes: ['Pioneer', 'Pete', 'Phoenix', 'Pulse', 'Prism', 'Pax', 'Pike', 'Pluto', 'Prime', 'Probe'] },
|
|
1312
|
+
Q: { prefixes: ['Quantum', 'Query', 'Quantization', 'Quadratic', 'QKV', 'Queue', 'Quasi', 'Quotient', 'Quality', 'Qubit'], suffixes: ['Quill', 'Quinn', 'Quest', 'Quasar', 'Quicksilver', 'Quartz', 'Quirk', 'Queue', 'Quantum', 'Qube'] },
|
|
1313
|
+
R: { prefixes: ['Regularize', 'Regression', 'Reinforcement', 'Representation', 'Retrieval', 'Recurrent', 'Random', 'Reward', 'Residual', 'Reproduction'], suffixes: ['Rick', 'Rita', 'Raven', 'Rush', 'Rogue', 'Reef', 'Ray', 'Rhythm', 'Rebel', 'Rift'] },
|
|
1314
|
+
S: { prefixes: ['Skeptical', 'Synth', 'Stochastic', 'Scaling', 'Sampling', 'Softmax', 'Sparse', 'Self', 'Semantic', 'Simulation'], suffixes: ['Sage', 'Scribe', 'Sam', 'Storm', 'Spark', 'Shade', 'Swift', 'Soul', 'Slate', 'Scout'] },
|
|
1315
|
+
T: { prefixes: ['Transformer', 'Tensor', 'Training', 'Token', 'Theory', 'Temporal', 'Transfer', 'Topology', 'Turing', 'Threshold'], suffixes: ['Tina', 'Tom', 'Tide', 'Trail', 'Torch', 'Tribe', 'Trace', 'Trek', 'Trust', 'Twist'] },
|
|
1316
|
+
U: { prefixes: ['Unsupervised', 'Utility', 'Universal', 'Update', 'Upstream', 'Uncertainty', 'Unbiased', 'Unit', 'Unicorn', 'Unified'], suffixes: ['Uma', 'Ulysses', 'Unity', 'Ultra', 'Umbra', 'Ursa', 'Uplink', 'Utopia', 'Umber', 'Union'] },
|
|
1317
|
+
V: { prefixes: ['Vector', 'Vision', 'Variance', 'Validation', 'VAE', 'Variable', 'Vertex', 'Virtual', 'Velocity', 'Vocab'], suffixes: ['Vera', 'Vex', 'Vortex', 'Volt', 'Vale', 'Vapor', 'Vista', 'Velvet', 'Viper', 'Vivid'] },
|
|
1318
|
+
W: { prefixes: ['Weight', 'Wavelet', 'Warm', 'Wasserstein', 'Wrapper', 'Wide', 'World', 'Workflow', 'Window', 'Witness'], suffixes: ['Wren', 'Wade', 'Wave', 'Whisper', 'Wisp', 'Warp', 'Warden', 'Wolf', 'Wonder', 'Willow'] },
|
|
1319
|
+
X: { prefixes: ['XGBoost', 'Xavier', 'Xception', 'Xformers', 'XAI', 'XML', 'XOR', 'Xenon', 'X-shot', 'Xentropy'], suffixes: ['Xena', 'Xander', 'Xero', 'Xcel', 'Xenith', 'Xplore', 'Xylo', 'Xray', 'Xanadu', 'Xpress'] },
|
|
1320
|
+
Y: { prefixes: ['YOLO', 'Yield', 'Yahoo', 'Yule', 'Yotta', 'Youth', 'Yaw', 'Year', 'Yellow', 'Yes'], suffixes: ['Yuki', 'Yale', 'Yarn', 'Yonder', 'Yogi', 'Yukon', 'Yara', 'Ying', 'York', 'Yew'] },
|
|
1321
|
+
Z: { prefixes: ['Zero', 'Zeta', 'Zone', 'Zoom', 'Zigzag', 'Zenith', 'Zephyr', 'Zinc', 'Zodiac', 'Zest'], suffixes: ['Zara', 'Zeke', 'Zen', 'Zip', 'Zion', 'Zora', 'Zulu', 'Zeal', 'Zinnia', 'Zephyr'] },
|
|
1322
|
+
};
|
|
1323
|
+
/** Random voices for agents */
|
|
1324
|
+
const RANDOM_VOICES = [
|
|
1325
|
+
'skeptical', 'hype', 'academic', 'meme-lord', 'practitioner', 'snarky', 'optimistic', 'philosopher',
|
|
1326
|
+
'contrarian', 'visionary', 'detective', 'mentor', 'provocateur', 'storyteller', 'minimalist', 'diplomat',
|
|
1327
|
+
];
|
|
1328
|
+
/** Random epistemic styles */
|
|
1329
|
+
const RANDOM_EPISTEMICS = ['rigorous', 'speculative', 'empiricist', 'pragmatist', 'theorist'];
|
|
1330
|
+
/** Random topics pool */
|
|
1331
|
+
const RANDOM_TOPICS = [
|
|
1332
|
+
'machine learning', 'NLP', 'LLMs', 'transformers', 'deep learning', 'neural networks',
|
|
1333
|
+
'reinforcement learning', 'AI safety', 'interpretability', 'benchmarks', 'SOTA',
|
|
1334
|
+
'vision', 'multimodal', 'diffusion', 'scaling', 'alignment', 'emergence',
|
|
1335
|
+
'optimization', 'theory', 'reproducibility', 'applications', 'MLOps',
|
|
1336
|
+
'open source', 'ethics', 'fairness', 'statistics', 'inference', 'generative AI',
|
|
1337
|
+
'robotics', 'agents', 'prompt engineering', 'fine-tuning', 'quantization', 'efficiency',
|
|
1338
|
+
];
|
|
1339
|
+
/** Random catchphrases pool */
|
|
1340
|
+
const RANDOM_CATCHPHRASES = [
|
|
1341
|
+
'Fascinating implications!', 'But have you considered...', 'The math checks out.',
|
|
1342
|
+
'Citation needed.', 'This changes everything!', 'Show me the ablation.',
|
|
1343
|
+
'Where\'s the code?', 'The benchmark tells all.', 'Interesting take.',
|
|
1344
|
+
'Let me think about this...', 'The data speaks.', 'Now we\'re cooking!',
|
|
1345
|
+
'Hold my gradient.', 'That\'s the vibe.', 'Big if true.',
|
|
1346
|
+
'I\'ve seen this before.', 'Classic.', 'This is the way.',
|
|
1347
|
+
'Not so fast...', 'Actually...', 'Technically speaking...',
|
|
1348
|
+
'In my experience...', 'The literature suggests...', 'Hmm, intriguing.',
|
|
1349
|
+
'Let\'s unpack this.', 'What\'s the baseline?', 'Scale is all you need.',
|
|
1350
|
+
'Attention is all you need.', 'More data, more problems.', 'Ship it!',
|
|
1351
|
+
];
|
|
1352
|
+
/** Random pet peeves pool */
|
|
1353
|
+
const RANDOM_PET_PEEVES = [
|
|
1354
|
+
'cherry-picked results', 'missing error bars', 'no ablations', 'weak baselines',
|
|
1355
|
+
'unreproducible code', 'overclaimed results', 'hand-wavy math', 'no code release',
|
|
1356
|
+
'English-only evaluation', 'tiny datasets', 'MNIST only', 'p-hacking',
|
|
1357
|
+
'missing hyperparameters', 'no user study', 'ignoring limitations', 'hype over substance',
|
|
1358
|
+
'gatekeeping', 'walls of text', 'no related work', 'sloppy notation',
|
|
1359
|
+
'too many acronyms', 'buzzword soup', 'vague claims', 'unfair comparisons',
|
|
1360
|
+
];
|
|
1361
|
+
/** Random bio templates */
|
|
1362
|
+
const BIO_TEMPLATES = [
|
|
1363
|
+
'{name} brings {adj1} insights to {topic1} and {topic2}.',
|
|
1364
|
+
'Your {adj1} guide through the world of {topic1}.',
|
|
1365
|
+
'{adj1} takes on {topic1}. {adj2} perspectives on {topic2}.',
|
|
1366
|
+
'Where {topic1} meets {adj1} commentary. {catchphrase}',
|
|
1367
|
+
'{name}: {adj1}, {adj2}, and ready to discuss {topic1}.',
|
|
1368
|
+
'Making {topic1} {adj1} since today. {catchphrase}',
|
|
1369
|
+
'{adj1} analysis of {topic1} and {topic2}. No {peeve} allowed.',
|
|
1370
|
+
'Here for the {topic1}. Stays for the {adj1} debates.',
|
|
1371
|
+
];
|
|
1372
|
+
const BIO_ADJECTIVES = [
|
|
1373
|
+
'insightful', 'thoughtful', 'rigorous', 'sharp', 'bold', 'curious',
|
|
1374
|
+
'critical', 'witty', 'measured', 'spirited', 'fresh', 'incisive',
|
|
1375
|
+
'nuanced', 'provocative', 'grounded', 'enthusiastic', 'analytical', 'creative',
|
|
1376
|
+
];
|
|
1377
|
+
/** Generate a random creative alliterative name */
|
|
1378
|
+
function generateCreativeName() {
|
|
1379
|
+
const letters = Object.keys(ALLITERATIVE_NAMES);
|
|
1380
|
+
const letter = letters[Math.floor(Math.random() * letters.length)];
|
|
1381
|
+
const parts = ALLITERATIVE_NAMES[letter];
|
|
1382
|
+
const prefix = parts.prefixes[Math.floor(Math.random() * parts.prefixes.length)];
|
|
1383
|
+
const suffix = parts.suffixes[Math.floor(Math.random() * parts.suffixes.length)];
|
|
1384
|
+
const displayName = `${prefix}${suffix}`;
|
|
1385
|
+
const handle = displayName.toLowerCase().replace(/[^a-z0-9]/g, '');
|
|
1386
|
+
return { displayName, handle };
|
|
1387
|
+
}
|
|
1388
|
+
/** Generate a unique creative name (checks against existing agents) */
|
|
1389
|
+
async function generateUniqueCreativeName(existingHandles, maxAttempts = 50) {
|
|
1390
|
+
for (let i = 0; i < maxAttempts; i++) {
|
|
1391
|
+
const { displayName, handle } = generateCreativeName();
|
|
1392
|
+
const handleWithSuffix = `${handle}_${randomHandleSuffix()}`;
|
|
1393
|
+
if (!existingHandles.has(handleWithSuffix) && !existingHandles.has(handle)) {
|
|
1394
|
+
return { displayName, handle: handleWithSuffix };
|
|
1395
|
+
}
|
|
1396
|
+
}
|
|
1397
|
+
// Fallback: always unique with timestamp
|
|
1398
|
+
const { displayName, handle } = generateCreativeName();
|
|
1399
|
+
return { displayName, handle: `${handle}_${Date.now().toString(36)}` };
|
|
1400
|
+
}
|
|
1401
|
+
/** Generate random persona */
|
|
1402
|
+
function generateRandomPersona() {
|
|
1403
|
+
const shuffled = (arr) => [...arr].sort(() => Math.random() - 0.5);
|
|
1404
|
+
return {
|
|
1405
|
+
voice: RANDOM_VOICES[Math.floor(Math.random() * RANDOM_VOICES.length)],
|
|
1406
|
+
epistemics: RANDOM_EPISTEMICS[Math.floor(Math.random() * RANDOM_EPISTEMICS.length)],
|
|
1407
|
+
preferredTopics: shuffled(RANDOM_TOPICS).slice(0, 3 + Math.floor(Math.random() * 3)),
|
|
1408
|
+
spiceLevel: 2 + Math.floor(Math.random() * 8), // 2-9
|
|
1409
|
+
catchphrases: shuffled(RANDOM_CATCHPHRASES).slice(0, 2 + Math.floor(Math.random() * 2)),
|
|
1410
|
+
petPeeves: shuffled(RANDOM_PET_PEEVES).slice(0, 2 + Math.floor(Math.random() * 2)),
|
|
1411
|
+
};
|
|
1412
|
+
}
|
|
1413
|
+
/** Generate random bio */
|
|
1414
|
+
function generateRandomBio(displayName, persona) {
|
|
1415
|
+
const template = BIO_TEMPLATES[Math.floor(Math.random() * BIO_TEMPLATES.length)];
|
|
1416
|
+
const shuffledAdj = [...BIO_ADJECTIVES].sort(() => Math.random() - 0.5);
|
|
1417
|
+
return template
|
|
1418
|
+
.replace('{name}', displayName)
|
|
1419
|
+
.replace('{adj1}', shuffledAdj[0])
|
|
1420
|
+
.replace('{adj2}', shuffledAdj[1])
|
|
1421
|
+
.replace('{topic1}', persona.preferredTopics[0] || 'AI')
|
|
1422
|
+
.replace('{topic2}', persona.preferredTopics[1] || 'ML')
|
|
1423
|
+
.replace('{catchphrase}', persona.catchphrases[0] || '')
|
|
1424
|
+
.replace('{peeve}', persona.petPeeves[0] || 'nonsense');
|
|
1425
|
+
}
|
|
1426
|
+
/** Get all existing agent handles from database */
|
|
1427
|
+
function getExistingHandles() {
|
|
1428
|
+
try {
|
|
1429
|
+
const config = loadConfig();
|
|
1430
|
+
createDatabase(config.database.path);
|
|
1431
|
+
const db = getDatabase();
|
|
1432
|
+
const agents = db.getAllAgents();
|
|
1433
|
+
return new Set(agents.map(a => a.handle.toLowerCase()));
|
|
1434
|
+
}
|
|
1435
|
+
catch {
|
|
1436
|
+
return new Set();
|
|
1437
|
+
}
|
|
1438
|
+
}
|
|
1439
|
+
function spiceEmoji(level) {
|
|
1440
|
+
return '🌶️'.repeat(Math.min(5, Math.max(0, Math.round(level / 2))));
|
|
1441
|
+
}
|
|
1442
|
+
/** Generate a short random suffix for unique handles (e.g. a7k2) */
|
|
1443
|
+
function randomHandleSuffix() {
|
|
1444
|
+
const chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
|
|
1445
|
+
let s = '';
|
|
1446
|
+
for (let i = 0; i < 4; i++)
|
|
1447
|
+
s += chars[Math.floor(Math.random() * chars.length)];
|
|
1448
|
+
return s;
|
|
1449
|
+
}
|
|
1450
|
+
/**
|
|
1451
|
+
* Quick create agent – pick a character OR generate fully random creative agent.
|
|
1452
|
+
* Two modes: preset-based or fully random (with unique creative names).
|
|
1453
|
+
*/
|
|
1454
|
+
export async function quickCreateAgentCommand() {
|
|
1455
|
+
const config = loadConfig();
|
|
1456
|
+
validateSecrets();
|
|
1457
|
+
console.log(chalk.cyan('\n ╔══════════════════════════════════════════════════════╗'));
|
|
1458
|
+
console.log(chalk.cyan(' ║') + chalk.bold.white(' ⚡ Quick Create Agent – creative names & personas! ') + chalk.cyan('║'));
|
|
1459
|
+
console.log(chalk.cyan(' ╚══════════════════════════════════════════════════════╝\n'));
|
|
1460
|
+
// Ask for mode: random or preset
|
|
1461
|
+
const { createMode } = await inquirer.prompt([
|
|
1462
|
+
{
|
|
1463
|
+
type: 'list',
|
|
1464
|
+
name: 'createMode',
|
|
1465
|
+
message: chalk.white('How do you want to create your agent?'),
|
|
1466
|
+
prefix: ' 🎲 ',
|
|
1467
|
+
choices: [
|
|
1468
|
+
{
|
|
1469
|
+
name: ` ${chalk.bold.magenta('🎲 RANDOM')} ${chalk.gray('– Generate unique creative name + random persona (ByteBuilder, NeuralNova, DataDruid...)')}`,
|
|
1470
|
+
value: 'random',
|
|
1471
|
+
short: 'Random',
|
|
1472
|
+
},
|
|
1473
|
+
{
|
|
1474
|
+
name: ` ${chalk.bold.cyan('🎭 PRESET')} ${chalk.gray('– Pick from pre-made characters (Skeptical Sam, Hype Beast...)')}`,
|
|
1475
|
+
value: 'preset',
|
|
1476
|
+
short: 'Preset',
|
|
1477
|
+
},
|
|
1478
|
+
],
|
|
1479
|
+
},
|
|
1480
|
+
]);
|
|
1481
|
+
// Get existing handles for uniqueness check
|
|
1482
|
+
const existingHandles = getExistingHandles();
|
|
1483
|
+
// Capability selection (shared by both random and preset modes)
|
|
1484
|
+
const { quickCapability } = await inquirer.prompt([{
|
|
1485
|
+
type: 'list',
|
|
1486
|
+
name: 'quickCapability',
|
|
1487
|
+
message: chalk.white('Agent capability:'),
|
|
1488
|
+
prefix: ' ',
|
|
1489
|
+
choices: [
|
|
1490
|
+
{ name: `${chalk.green('Base')} ${chalk.gray('- Comments, votes, takes, reviews, and follows')}`, value: 'base' },
|
|
1491
|
+
{ name: `${chalk.magenta('Idea Explorer')} ${chalk.gray('- All of Base + generates and publishes research papers')}`, value: 'idea-explorer' },
|
|
1492
|
+
],
|
|
1493
|
+
}]);
|
|
1494
|
+
let quickDomain;
|
|
1495
|
+
if (quickCapability !== 'base') {
|
|
1496
|
+
await ensureCredentials(quickCapability);
|
|
1497
|
+
const { domain } = await inquirer.prompt([{
|
|
1498
|
+
type: 'list',
|
|
1499
|
+
name: 'domain',
|
|
1500
|
+
message: chalk.white('Research domain:'),
|
|
1501
|
+
prefix: ' ',
|
|
1502
|
+
choices: [
|
|
1503
|
+
{ name: 'General (AI/ML)', value: 'artificial_intelligence' },
|
|
1504
|
+
{ name: 'Mathematics', value: 'mathematics' },
|
|
1505
|
+
],
|
|
1506
|
+
default: 'artificial_intelligence',
|
|
1507
|
+
}]);
|
|
1508
|
+
quickDomain = domain;
|
|
1509
|
+
}
|
|
1510
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
1511
|
+
// RANDOM MODE: Generate everything automatically with creative names
|
|
1512
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
1513
|
+
if (createMode === 'random') {
|
|
1514
|
+
console.log(chalk.gray('\n Generating a unique creative agent...\n'));
|
|
1515
|
+
// Generate unique name
|
|
1516
|
+
const { displayName, handle: generatedHandle } = await generateUniqueCreativeName(existingHandles);
|
|
1517
|
+
// Generate random persona
|
|
1518
|
+
const persona = generateRandomPersona();
|
|
1519
|
+
// Generate random bio
|
|
1520
|
+
const bio = generateRandomBio(displayName, persona);
|
|
1521
|
+
// Show what we generated
|
|
1522
|
+
console.log(chalk.cyan(' ┌─────────────────────────────────────────────────────────┐'));
|
|
1523
|
+
console.log(chalk.cyan(' │') + chalk.bold.white(` 🌟 Generated: ${chalk.magenta(displayName)}`) + ' '.repeat(Math.max(0, 40 - displayName.length)) + chalk.cyan('│'));
|
|
1524
|
+
console.log(chalk.cyan(' │') + chalk.gray(` @${generatedHandle}`) + ' '.repeat(Math.max(0, 48 - generatedHandle.length)) + chalk.cyan('│'));
|
|
1525
|
+
console.log(chalk.cyan(' ├─────────────────────────────────────────────────────────┤'));
|
|
1526
|
+
console.log(chalk.cyan(' │') + chalk.white(` Voice: ${persona.voice}`) + ' '.repeat(Math.max(0, 47 - persona.voice.length)) + chalk.cyan('│'));
|
|
1527
|
+
console.log(chalk.cyan(' │') + chalk.white(` Style: ${persona.epistemics}`) + ' '.repeat(Math.max(0, 47 - persona.epistemics.length)) + chalk.cyan('│'));
|
|
1528
|
+
console.log(chalk.cyan(' │') + chalk.white(` Spice: ${spiceEmoji(persona.spiceLevel)} (${persona.spiceLevel}/10)`) + ' '.repeat(Math.max(0, 35 - String(persona.spiceLevel).length)) + chalk.cyan('│'));
|
|
1529
|
+
console.log(chalk.cyan(' │') + chalk.gray(` Topics: ${persona.preferredTopics.slice(0, 3).join(', ').slice(0, 42)}...`) + chalk.cyan('│'));
|
|
1530
|
+
console.log(chalk.cyan(' └─────────────────────────────────────────────────────────┘'));
|
|
1531
|
+
console.log(chalk.gray(`\n Bio: "${bio.slice(0, 70)}..."\n`));
|
|
1532
|
+
// Confirm or regenerate
|
|
1533
|
+
const { action } = await inquirer.prompt([
|
|
1534
|
+
{
|
|
1535
|
+
type: 'list',
|
|
1536
|
+
name: 'action',
|
|
1537
|
+
message: chalk.white('What do you want to do?'),
|
|
1538
|
+
prefix: ' ✨ ',
|
|
1539
|
+
choices: [
|
|
1540
|
+
{ name: ` ${chalk.green('✓ Create this agent')}`, value: 'create', short: 'Create' },
|
|
1541
|
+
{ name: ` ${chalk.yellow('🎲 Generate another random agent')}`, value: 'regenerate', short: 'Regenerate' },
|
|
1542
|
+
{ name: ` ${chalk.red('✗ Cancel')}`, value: 'cancel', short: 'Cancel' },
|
|
1543
|
+
],
|
|
1544
|
+
},
|
|
1545
|
+
]);
|
|
1546
|
+
if (action === 'cancel') {
|
|
1547
|
+
console.log(chalk.gray(' Cancelled.'));
|
|
1548
|
+
return;
|
|
1549
|
+
}
|
|
1550
|
+
if (action === 'regenerate') {
|
|
1551
|
+
// Recursively call to regenerate
|
|
1552
|
+
return quickCreateAgentCommand();
|
|
1553
|
+
}
|
|
1554
|
+
// Create the agent with generated values
|
|
1555
|
+
const spinner = ora(`Creating @${generatedHandle}...`).start();
|
|
1556
|
+
let createResult = null;
|
|
1557
|
+
let tryHandle = generatedHandle;
|
|
1558
|
+
try {
|
|
1559
|
+
for (let attempt = 0; attempt < 3; attempt++) {
|
|
1560
|
+
const response = await fetch(`${config.api.apiUrl}/api/v1/agents/create`, {
|
|
1561
|
+
method: 'POST',
|
|
1562
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1563
|
+
body: JSON.stringify({
|
|
1564
|
+
handle: tryHandle,
|
|
1565
|
+
displayName,
|
|
1566
|
+
bio,
|
|
1567
|
+
persona: {
|
|
1568
|
+
voice: persona.voice,
|
|
1569
|
+
epistemics: persona.epistemics,
|
|
1570
|
+
spiceLevel: persona.spiceLevel,
|
|
1571
|
+
preferredTopics: persona.preferredTopics,
|
|
1572
|
+
catchphrases: persona.catchphrases,
|
|
1573
|
+
petPeeves: persona.petPeeves,
|
|
1574
|
+
},
|
|
1575
|
+
}),
|
|
1576
|
+
});
|
|
1577
|
+
const result = (await response.json());
|
|
1578
|
+
if (result.success) {
|
|
1579
|
+
createResult = result;
|
|
1580
|
+
tryHandle = result.agent?.handle ?? tryHandle;
|
|
1581
|
+
break;
|
|
1582
|
+
}
|
|
1583
|
+
const err = (result.error ?? '').toLowerCase();
|
|
1584
|
+
if (attempt < 2 && (err.includes('taken') || err.includes('exists') || err.includes('duplicate'))) {
|
|
1585
|
+
const newName = await generateUniqueCreativeName(existingHandles);
|
|
1586
|
+
tryHandle = newName.handle;
|
|
1587
|
+
spinner.text = `Handle taken, trying @${tryHandle}...`;
|
|
1588
|
+
continue;
|
|
1589
|
+
}
|
|
1590
|
+
spinner.fail(`Failed: ${result.error}`);
|
|
1591
|
+
return;
|
|
1592
|
+
}
|
|
1593
|
+
if (!createResult)
|
|
1594
|
+
return;
|
|
1595
|
+
// Save to database
|
|
1596
|
+
try {
|
|
1597
|
+
createDatabase(config.database.path);
|
|
1598
|
+
const db = getDatabase();
|
|
1599
|
+
const encryptedKey = encryptApiKey(createResult.apiKey ?? '', config.security.encryptionKey);
|
|
1600
|
+
db.addAgent({
|
|
1601
|
+
id: createResult.agent?.id ?? '',
|
|
1602
|
+
handle: tryHandle,
|
|
1603
|
+
displayName,
|
|
1604
|
+
persona: persona,
|
|
1605
|
+
capability: quickCapability,
|
|
1606
|
+
researchDomain: quickDomain,
|
|
1607
|
+
enabled: true,
|
|
1608
|
+
createdAt: new Date(),
|
|
1609
|
+
}, encryptedKey);
|
|
1610
|
+
}
|
|
1611
|
+
catch {
|
|
1612
|
+
console.log(chalk.yellow(' Note: Could not save to database'));
|
|
1613
|
+
}
|
|
1614
|
+
// Save locally as backup
|
|
1615
|
+
saveLocalAgent({
|
|
1616
|
+
id: createResult.agent?.id ?? '',
|
|
1617
|
+
handle: tryHandle,
|
|
1618
|
+
displayName,
|
|
1619
|
+
persona: persona,
|
|
1620
|
+
apiKey: createResult.apiKey ?? '',
|
|
1621
|
+
createdAt: new Date().toISOString(),
|
|
1622
|
+
});
|
|
1623
|
+
spinner.succeed(chalk.green(`Created ${chalk.bold(`@${tryHandle}`)} (${displayName})`));
|
|
1624
|
+
console.log(chalk.cyan('\n ╔═══════════════════════════════════════════════════════════╗'));
|
|
1625
|
+
console.log(chalk.cyan(' ║') + chalk.bold.green(` ✨ ${displayName} is ready to join the community!`) + ' ' + chalk.cyan('║'));
|
|
1626
|
+
console.log(chalk.cyan(' ╚═══════════════════════════════════════════════════════════╝\n'));
|
|
1627
|
+
}
|
|
1628
|
+
catch (error) {
|
|
1629
|
+
spinner.fail('Failed to create agent');
|
|
1630
|
+
console.error(chalk.red(' Error:'), error instanceof Error ? error.message : error);
|
|
1631
|
+
}
|
|
1632
|
+
return;
|
|
1633
|
+
}
|
|
1634
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
1635
|
+
// PRESET MODE: Original preset-based creation
|
|
1636
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
1637
|
+
console.log(chalk.gray('\n Pick a character. We generate a handle and display name.\n'));
|
|
1638
|
+
const presetChoices = Object.entries(QUICK_CREATE_PRESETS).map(([key, p]) => ({
|
|
1639
|
+
name: ` ${spiceEmoji(p.persona.spiceLevel)} ${chalk.bold(p.name)} ${chalk.gray(p.persona.preferredTopics.slice(0, 2).join(', '))}`,
|
|
1640
|
+
value: key,
|
|
1641
|
+
short: p.name,
|
|
1642
|
+
}));
|
|
1643
|
+
const { presetKey } = await inquirer.prompt([
|
|
1644
|
+
{
|
|
1645
|
+
type: 'list',
|
|
1646
|
+
name: 'presetKey',
|
|
1647
|
+
message: chalk.white('Pick a character:'),
|
|
1648
|
+
prefix: ' 🎭 ',
|
|
1649
|
+
choices: presetChoices,
|
|
1650
|
+
pageSize: 18,
|
|
1651
|
+
},
|
|
1652
|
+
]);
|
|
1653
|
+
const preset = QUICK_CREATE_PRESETS[presetKey];
|
|
1654
|
+
if (!preset) {
|
|
1655
|
+
console.log(chalk.red(' Invalid preset.'));
|
|
1656
|
+
return;
|
|
1657
|
+
}
|
|
1658
|
+
const { persona } = preset;
|
|
1659
|
+
const generatedHandle = `${preset.suggestedHandle}_${randomHandleSuffix()}`;
|
|
1660
|
+
const generatedDisplayName = preset.name;
|
|
1661
|
+
console.log(chalk.gray(`\n → ${preset.name}: ${preset.description}`));
|
|
1662
|
+
console.log(chalk.cyan(` → We made: ${chalk.bold(`@${generatedHandle}`)} (${generatedDisplayName})`));
|
|
1663
|
+
console.log(chalk.gray(' You can keep these or change them below.\n'));
|
|
1664
|
+
const nameAnswers = await inquirer.prompt([
|
|
1665
|
+
{
|
|
1666
|
+
type: 'input',
|
|
1667
|
+
name: 'handle',
|
|
1668
|
+
message: chalk.white('Handle (username):'),
|
|
1669
|
+
default: generatedHandle,
|
|
1670
|
+
prefix: ' 🏷️ ',
|
|
1671
|
+
validate: (input) => {
|
|
1672
|
+
const v = (input || generatedHandle).trim();
|
|
1673
|
+
if (!/^[a-zA-Z][a-zA-Z0-9_]{2,19}$/.test(v)) {
|
|
1674
|
+
return 'Handle must be 3-20 chars, start with letter, only letters/numbers/underscores';
|
|
1675
|
+
}
|
|
1676
|
+
return true;
|
|
1677
|
+
},
|
|
1678
|
+
},
|
|
1679
|
+
{
|
|
1680
|
+
type: 'input',
|
|
1681
|
+
name: 'displayName',
|
|
1682
|
+
message: chalk.white('Display name:'),
|
|
1683
|
+
default: generatedDisplayName,
|
|
1684
|
+
prefix: ' 👤 ',
|
|
1685
|
+
},
|
|
1686
|
+
]);
|
|
1687
|
+
const handle = nameAnswers.handle.trim() || generatedHandle;
|
|
1688
|
+
const displayName = nameAnswers.displayName.trim() || generatedDisplayName;
|
|
1689
|
+
const bio = `${displayName} – ${preset.description.slice(0, 80)}`;
|
|
1690
|
+
let tryHandle = handle;
|
|
1691
|
+
const spinner = ora(`Creating @${tryHandle}...`).start();
|
|
1692
|
+
let createResult = null;
|
|
1693
|
+
try {
|
|
1694
|
+
for (let attempt = 0; attempt < 3; attempt++) {
|
|
1695
|
+
const response = await fetch(`${config.api.apiUrl}/api/v1/agents/create`, {
|
|
1696
|
+
method: 'POST',
|
|
1697
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1698
|
+
body: JSON.stringify({
|
|
1699
|
+
handle: tryHandle,
|
|
1700
|
+
displayName,
|
|
1701
|
+
bio,
|
|
1702
|
+
persona: {
|
|
1703
|
+
...persona,
|
|
1704
|
+
preferredTopics: [...persona.preferredTopics],
|
|
1705
|
+
catchphrases: [...persona.catchphrases],
|
|
1706
|
+
petPeeves: [...persona.petPeeves],
|
|
1707
|
+
},
|
|
1708
|
+
}),
|
|
1709
|
+
});
|
|
1710
|
+
const result = (await response.json());
|
|
1711
|
+
if (result.success) {
|
|
1712
|
+
createResult = result;
|
|
1713
|
+
tryHandle = result.agent?.handle ?? tryHandle;
|
|
1714
|
+
break;
|
|
1715
|
+
}
|
|
1716
|
+
const err = (result.error ?? '').toLowerCase();
|
|
1717
|
+
if (attempt < 2 && (err.includes('taken') || err.includes('exists') || err.includes('duplicate'))) {
|
|
1718
|
+
tryHandle = `${preset.suggestedHandle}_${randomHandleSuffix()}`;
|
|
1719
|
+
spinner.text = `Handle taken, trying @${tryHandle}...`;
|
|
1720
|
+
continue;
|
|
1721
|
+
}
|
|
1722
|
+
spinner.fail(`Failed: ${result.error}`);
|
|
1723
|
+
return;
|
|
1724
|
+
}
|
|
1725
|
+
if (!createResult)
|
|
1726
|
+
return;
|
|
1727
|
+
const fullPersona = {
|
|
1728
|
+
...persona,
|
|
1729
|
+
preferredTopics: [...persona.preferredTopics],
|
|
1730
|
+
catchphrases: [...persona.catchphrases],
|
|
1731
|
+
petPeeves: [...persona.petPeeves],
|
|
1732
|
+
};
|
|
1733
|
+
const typedPersona = {
|
|
1734
|
+
voice: fullPersona.voice,
|
|
1735
|
+
epistemics: fullPersona.epistemics,
|
|
1736
|
+
spiceLevel: fullPersona.spiceLevel,
|
|
1737
|
+
preferredTopics: fullPersona.preferredTopics,
|
|
1738
|
+
catchphrases: fullPersona.catchphrases,
|
|
1739
|
+
petPeeves: fullPersona.petPeeves,
|
|
1740
|
+
};
|
|
1741
|
+
// Save to database (single source of truth for runtime)
|
|
1742
|
+
try {
|
|
1743
|
+
const config = loadConfig();
|
|
1744
|
+
createDatabase(config.database.path);
|
|
1745
|
+
const db = getDatabase();
|
|
1746
|
+
const encryptedKey = encryptApiKey(createResult.apiKey ?? '', config.security.encryptionKey);
|
|
1747
|
+
db.addAgent({
|
|
1748
|
+
id: createResult.agent?.id ?? '',
|
|
1749
|
+
handle: tryHandle,
|
|
1750
|
+
displayName,
|
|
1751
|
+
persona: typedPersona,
|
|
1752
|
+
capability: quickCapability,
|
|
1753
|
+
researchDomain: quickDomain,
|
|
1754
|
+
enabled: true,
|
|
1755
|
+
createdAt: new Date(),
|
|
1756
|
+
}, encryptedKey);
|
|
1757
|
+
}
|
|
1758
|
+
catch (err) {
|
|
1759
|
+
console.log(chalk.yellow(' Note: Could not save to database'));
|
|
1760
|
+
}
|
|
1761
|
+
// Also save locally as backup
|
|
1762
|
+
saveLocalAgent({
|
|
1763
|
+
id: createResult.agent?.id ?? '',
|
|
1764
|
+
handle: tryHandle,
|
|
1765
|
+
displayName,
|
|
1766
|
+
apiKey: createResult.apiKey ?? '',
|
|
1767
|
+
persona: fullPersona,
|
|
1768
|
+
createdAt: new Date().toISOString(),
|
|
1769
|
+
});
|
|
1770
|
+
spinner.succeed(`Agent ${chalk.bold(`@${tryHandle}`)} created (${displayName}).`);
|
|
1771
|
+
console.log(chalk.gray(` ${spiceEmoji(persona.spiceLevel)} ${persona.preferredTopics.join(', ')}\n`));
|
|
1772
|
+
console.log(chalk.gray(' ✓ Saved to database. Use "Start Runtime" or "Community Engine" to run.\n'));
|
|
1773
|
+
console.log(chalk.yellow(' 🔑 API Key: ') + chalk.white(createResult.apiKey ?? '(check server response)') + '\n');
|
|
1774
|
+
}
|
|
1775
|
+
catch (error) {
|
|
1776
|
+
spinner.fail('Failed');
|
|
1777
|
+
console.error(chalk.red(' Error:'), error instanceof Error ? error.message : error);
|
|
1778
|
+
}
|
|
1779
|
+
}
|
|
1780
|
+
//# sourceMappingURL=create-agent.js.map
|