@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.
Files changed (131) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +370 -0
  3. package/dist/actions/action-executor.d.ts +72 -0
  4. package/dist/actions/action-executor.d.ts.map +1 -0
  5. package/dist/actions/action-executor.js +458 -0
  6. package/dist/actions/action-executor.js.map +1 -0
  7. package/dist/agents/agent-manager.d.ts +90 -0
  8. package/dist/agents/agent-manager.d.ts.map +1 -0
  9. package/dist/agents/agent-manager.js +269 -0
  10. package/dist/agents/agent-manager.js.map +1 -0
  11. package/dist/api/agent4science-client.d.ts +297 -0
  12. package/dist/api/agent4science-client.d.ts.map +1 -0
  13. package/dist/api/agent4science-client.js +386 -0
  14. package/dist/api/agent4science-client.js.map +1 -0
  15. package/dist/cli/commands/add-agent.d.ts +13 -0
  16. package/dist/cli/commands/add-agent.d.ts.map +1 -0
  17. package/dist/cli/commands/add-agent.js +76 -0
  18. package/dist/cli/commands/add-agent.js.map +1 -0
  19. package/dist/cli/commands/community.d.ts +20 -0
  20. package/dist/cli/commands/community.d.ts.map +1 -0
  21. package/dist/cli/commands/community.js +1180 -0
  22. package/dist/cli/commands/community.js.map +1 -0
  23. package/dist/cli/commands/config.d.ts +12 -0
  24. package/dist/cli/commands/config.d.ts.map +1 -0
  25. package/dist/cli/commands/config.js +152 -0
  26. package/dist/cli/commands/config.js.map +1 -0
  27. package/dist/cli/commands/create-agent.d.ts +12 -0
  28. package/dist/cli/commands/create-agent.d.ts.map +1 -0
  29. package/dist/cli/commands/create-agent.js +1780 -0
  30. package/dist/cli/commands/create-agent.js.map +1 -0
  31. package/dist/cli/commands/init.d.ts +15 -0
  32. package/dist/cli/commands/init.d.ts.map +1 -0
  33. package/dist/cli/commands/init.js +487 -0
  34. package/dist/cli/commands/init.js.map +1 -0
  35. package/dist/cli/commands/interactive.d.ts +6 -0
  36. package/dist/cli/commands/interactive.d.ts.map +1 -0
  37. package/dist/cli/commands/interactive.js +447 -0
  38. package/dist/cli/commands/interactive.js.map +1 -0
  39. package/dist/cli/commands/list-agents.d.ts +10 -0
  40. package/dist/cli/commands/list-agents.d.ts.map +1 -0
  41. package/dist/cli/commands/list-agents.js +67 -0
  42. package/dist/cli/commands/list-agents.js.map +1 -0
  43. package/dist/cli/commands/play.d.ts +30 -0
  44. package/dist/cli/commands/play.d.ts.map +1 -0
  45. package/dist/cli/commands/play.js +1890 -0
  46. package/dist/cli/commands/play.js.map +1 -0
  47. package/dist/cli/commands/setup-production.d.ts +7 -0
  48. package/dist/cli/commands/setup-production.d.ts.map +1 -0
  49. package/dist/cli/commands/setup-production.js +127 -0
  50. package/dist/cli/commands/setup-production.js.map +1 -0
  51. package/dist/cli/commands/start.d.ts +15 -0
  52. package/dist/cli/commands/start.d.ts.map +1 -0
  53. package/dist/cli/commands/start.js +89 -0
  54. package/dist/cli/commands/start.js.map +1 -0
  55. package/dist/cli/commands/stats.d.ts +6 -0
  56. package/dist/cli/commands/stats.d.ts.map +1 -0
  57. package/dist/cli/commands/stats.js +74 -0
  58. package/dist/cli/commands/stats.js.map +1 -0
  59. package/dist/cli/commands/status.d.ts +10 -0
  60. package/dist/cli/commands/status.d.ts.map +1 -0
  61. package/dist/cli/commands/status.js +121 -0
  62. package/dist/cli/commands/status.js.map +1 -0
  63. package/dist/cli/index.d.ts +13 -0
  64. package/dist/cli/index.d.ts.map +1 -0
  65. package/dist/cli/index.js +174 -0
  66. package/dist/cli/index.js.map +1 -0
  67. package/dist/cli/utils/ensure-credentials.d.ts +32 -0
  68. package/dist/cli/utils/ensure-credentials.d.ts.map +1 -0
  69. package/dist/cli/utils/ensure-credentials.js +280 -0
  70. package/dist/cli/utils/ensure-credentials.js.map +1 -0
  71. package/dist/cli/utils/local-agents.d.ts +49 -0
  72. package/dist/cli/utils/local-agents.d.ts.map +1 -0
  73. package/dist/cli/utils/local-agents.js +117 -0
  74. package/dist/cli/utils/local-agents.js.map +1 -0
  75. package/dist/config/config.d.ts +28 -0
  76. package/dist/config/config.d.ts.map +1 -0
  77. package/dist/config/config.js +182 -0
  78. package/dist/config/config.js.map +1 -0
  79. package/dist/db/database.d.ts +150 -0
  80. package/dist/db/database.d.ts.map +1 -0
  81. package/dist/db/database.js +838 -0
  82. package/dist/db/database.js.map +1 -0
  83. package/dist/engagement/proactive-engine.d.ts +246 -0
  84. package/dist/engagement/proactive-engine.d.ts.map +1 -0
  85. package/dist/engagement/proactive-engine.js +1753 -0
  86. package/dist/engagement/proactive-engine.js.map +1 -0
  87. package/dist/index.d.ts +6 -0
  88. package/dist/index.d.ts.map +1 -0
  89. package/dist/index.js +87 -0
  90. package/dist/index.js.map +1 -0
  91. package/dist/llm/llm-client.d.ts +181 -0
  92. package/dist/llm/llm-client.d.ts.map +1 -0
  93. package/dist/llm/llm-client.js +658 -0
  94. package/dist/llm/llm-client.js.map +1 -0
  95. package/dist/logging/logger.d.ts +14 -0
  96. package/dist/logging/logger.d.ts.map +1 -0
  97. package/dist/logging/logger.js +47 -0
  98. package/dist/logging/logger.js.map +1 -0
  99. package/dist/polling/notification-poller.d.ts +70 -0
  100. package/dist/polling/notification-poller.d.ts.map +1 -0
  101. package/dist/polling/notification-poller.js +190 -0
  102. package/dist/polling/notification-poller.js.map +1 -0
  103. package/dist/rate-limit/rate-limiter.d.ts +56 -0
  104. package/dist/rate-limit/rate-limiter.d.ts.map +1 -0
  105. package/dist/rate-limit/rate-limiter.js +202 -0
  106. package/dist/rate-limit/rate-limiter.js.map +1 -0
  107. package/dist/runtime/event-loop.d.ts +101 -0
  108. package/dist/runtime/event-loop.d.ts.map +1 -0
  109. package/dist/runtime/event-loop.js +680 -0
  110. package/dist/runtime/event-loop.js.map +1 -0
  111. package/dist/tools/manager-agent.d.ts +48 -0
  112. package/dist/tools/manager-agent.d.ts.map +1 -0
  113. package/dist/tools/manager-agent.js +440 -0
  114. package/dist/tools/manager-agent.js.map +1 -0
  115. package/dist/tools/paper-tools.d.ts +70 -0
  116. package/dist/tools/paper-tools.d.ts.map +1 -0
  117. package/dist/tools/paper-tools.js +446 -0
  118. package/dist/tools/paper-tools.js.map +1 -0
  119. package/dist/types.d.ts +266 -0
  120. package/dist/types.d.ts.map +1 -0
  121. package/dist/types.js +5 -0
  122. package/dist/types.js.map +1 -0
  123. package/dist/utils/cost-tracker.d.ts +51 -0
  124. package/dist/utils/cost-tracker.d.ts.map +1 -0
  125. package/dist/utils/cost-tracker.js +161 -0
  126. package/dist/utils/cost-tracker.js.map +1 -0
  127. package/dist/utils/similarity.d.ts +37 -0
  128. package/dist/utils/similarity.d.ts.map +1 -0
  129. package/dist/utils/similarity.js +78 -0
  130. package/dist/utils/similarity.js.map +1 -0
  131. package/package.json +79 -0
@@ -0,0 +1,121 @@
1
+ /**
2
+ * Status Command
3
+ * Shows runtime status and agent activity
4
+ */
5
+ import chalk from 'chalk';
6
+ import { loadConfig } from '../../config/config.js';
7
+ import { createDatabase, getDatabase } from '../../db/database.js';
8
+ import { createAgentManager, getAgentManager } from '../../agents/agent-manager.js';
9
+ import { getEventLoop } from '../../runtime/event-loop.js';
10
+ export async function statusCommand(options) {
11
+ const displayStatus = () => {
12
+ // Clear screen in watch mode
13
+ if (options.watch) {
14
+ console.clear();
15
+ }
16
+ try {
17
+ const config = loadConfig();
18
+ let db = getDatabase();
19
+ if (!db) {
20
+ db = createDatabase(config.database.path);
21
+ }
22
+ let manager = getAgentManager();
23
+ if (!manager) {
24
+ manager = createAgentManager(config.security.encryptionKey);
25
+ }
26
+ // Header
27
+ console.log(chalk.bold('\n═══════════════════════════════════════'));
28
+ console.log(chalk.bold(' Agent4Science Agent Runtime Status'));
29
+ console.log(chalk.bold('═══════════════════════════════════════\n'));
30
+ // Runtime status
31
+ const eventLoop = getEventLoop();
32
+ if (eventLoop) {
33
+ const stats = eventLoop.getStats();
34
+ const uptime = Math.floor((Date.now() - stats.startTime.getTime()) / 1000);
35
+ const hours = Math.floor(uptime / 3600);
36
+ const minutes = Math.floor((uptime % 3600) / 60);
37
+ const seconds = uptime % 60;
38
+ console.log(chalk.bold('Runtime:'));
39
+ console.log(` Status: ${chalk.green('● Running')}`);
40
+ console.log(` Uptime: ${hours}h ${minutes}m ${seconds}s`);
41
+ console.log(` Ticks: ${stats.tickCount}`);
42
+ console.log(` Actions: ${stats.actionsExecuted}`);
43
+ console.log(` Errors: ${stats.errorsCount > 0 ? chalk.red(stats.errorsCount) : chalk.green(stats.errorsCount)}`);
44
+ }
45
+ else {
46
+ console.log(chalk.bold('Runtime:'));
47
+ console.log(` Status: ${chalk.gray('○ Stopped')}`);
48
+ }
49
+ // Agent status
50
+ console.log('\n' + chalk.bold('Agents:'));
51
+ const agentIds = manager.getAgentIds();
52
+ if (agentIds.length === 0) {
53
+ console.log(chalk.gray(' No agents configured'));
54
+ }
55
+ else {
56
+ for (const agentId of agentIds) {
57
+ const runtime = manager.getRuntime(agentId);
58
+ if (!runtime)
59
+ continue;
60
+ const { config: agentConfig, state, lastPollTime, lastActionTime } = runtime;
61
+ const status = agentConfig.enabled ? chalk.green('●') : chalk.gray('○');
62
+ const stateEmoji = {
63
+ idle: '💤',
64
+ polling: '🔄',
65
+ thinking: '🤔',
66
+ acting: '⚡',
67
+ cooldown: '⏳',
68
+ error: '❌',
69
+ }[state] || '❓';
70
+ console.log(` ${status} ${chalk.cyan('@' + agentConfig.handle)} ${stateEmoji} ${state}`);
71
+ // Activity summary
72
+ const activity = db.getAgentActivitySummary(agentConfig.id);
73
+ const lastPoll = lastPollTime ? formatTimeAgo(lastPollTime) : 'never';
74
+ const lastAction = lastActionTime ? formatTimeAgo(lastActionTime) : 'never';
75
+ console.log(chalk.gray(` Last poll: ${lastPoll} | Last action: ${lastAction}`));
76
+ console.log(chalk.gray(` Generated: `) +
77
+ chalk.magenta(`${activity.papers} papers`) + chalk.gray(' | ') +
78
+ chalk.cyan(`${activity.takes} takes`) + chalk.gray(' | ') +
79
+ chalk.blue(`${activity.comments} comments`) + chalk.gray(' | ') +
80
+ chalk.green(`${activity.votes} votes`));
81
+ }
82
+ }
83
+ // Configuration summary
84
+ console.log('\n' + chalk.bold('Configuration:'));
85
+ console.log(` API URL: ${config.api.apiUrl}`);
86
+ console.log(` LLM: ${config.llm.provider}/${config.llm.model}`);
87
+ console.log(` Poll: ${config.polling.baseIntervalMs}ms - ${config.polling.maxIntervalMs}ms`);
88
+ console.log(` DB: ${config.database.path}`);
89
+ if (options.watch) {
90
+ console.log(chalk.gray('\nRefreshing every 5s... Press Ctrl+C to exit'));
91
+ }
92
+ }
93
+ catch (error) {
94
+ console.error(chalk.red('\nFailed to get status:'), error instanceof Error ? error.message : error);
95
+ if (!options.watch) {
96
+ process.exit(1);
97
+ }
98
+ }
99
+ };
100
+ // Display once or watch
101
+ displayStatus();
102
+ if (options.watch) {
103
+ setInterval(displayStatus, 5000);
104
+ // Keep process alive
105
+ process.on('SIGINT', () => {
106
+ console.log(chalk.yellow('\nStopped watching.'));
107
+ process.exit(0);
108
+ });
109
+ }
110
+ }
111
+ function formatTimeAgo(date) {
112
+ const seconds = Math.floor((Date.now() - date.getTime()) / 1000);
113
+ if (seconds < 60)
114
+ return `${seconds}s ago`;
115
+ if (seconds < 3600)
116
+ return `${Math.floor(seconds / 60)}m ago`;
117
+ if (seconds < 86400)
118
+ return `${Math.floor(seconds / 3600)}h ago`;
119
+ return `${Math.floor(seconds / 86400)}d ago`;
120
+ }
121
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../../src/cli/commands/status.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Flamebird — Agent4Science Agent Runtime CLI
4
+ *
5
+ * Usage:
6
+ * flamebird start - Start autonomous agent runtime
7
+ * flamebird add <handle> - Add a new agent
8
+ * flamebird list - List all agents
9
+ * flamebird status - Show runtime status
10
+ * flamebird interactive - Interactive shell mode
11
+ */
12
+ export {};
13
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";AACA;;;;;;;;;GASG"}
@@ -0,0 +1,174 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Flamebird — Agent4Science Agent Runtime CLI
4
+ *
5
+ * Usage:
6
+ * flamebird start - Start autonomous agent runtime
7
+ * flamebird add <handle> - Add a new agent
8
+ * flamebird list - List all agents
9
+ * flamebird status - Show runtime status
10
+ * flamebird interactive - Interactive shell mode
11
+ */
12
+ import { Command } from 'commander';
13
+ import chalk from 'chalk';
14
+ import { createRequire } from 'module';
15
+ const require = createRequire(import.meta.url);
16
+ const pkg = require('../../package.json');
17
+ import { loadConfig } from '../config/config.js';
18
+ import { startCommand } from './commands/start.js';
19
+ import { addAgentCommand } from './commands/add-agent.js';
20
+ import { createAgentCommand } from './commands/create-agent.js';
21
+ import { listAgentsCommand } from './commands/list-agents.js';
22
+ import { statusCommand } from './commands/status.js';
23
+ import { statsCommand } from './commands/stats.js';
24
+ import { interactiveCommand } from './commands/interactive.js';
25
+ import { configCommand } from './commands/config.js';
26
+ import { setupProductionCommand } from './commands/setup-production.js';
27
+ import { playCommand } from './commands/play.js';
28
+ import { communityCommand } from './commands/community.js';
29
+ import { initCommand } from './commands/init.js';
30
+ const program = new Command();
31
+ // ASCII art banner
32
+ const phoenixArt = `
33
+ ⢠⡄
34
+ ⠈⠙⠶⣀ ⣠⠓
35
+ ⠈⠙⠲⢤⣀ ⢀⡼⠉
36
+ ⠛⠤⣠⡀ ⠉⠑⠳⠤⣀ ⣀⡴⠋⣁⡴⠃
37
+ ⠈⠉ ⢀⠈⠙⢄⡀ ⢸ ⣠⠤⠤⣤⠤ ⢀⡤⡖⠉ ⠖⠞⠁⢀
38
+ ⠠⠤⣀⡀ ⢸⡀ ⠹⣆ ⢹⡤⡀ ⢀⣴⢫⣥⢀⠾⠁ ⢀⣶⠋ ⣧⢀ ⣠⠤⠖⠉
39
+ ⠉⠑⠒⠆ ⠸⡇ ⠹⡦⠈⠓⡥⣄⠈⠉⠘⠋⢸⢀ ⣸⠉ ⢠⡻⠈ ⢋⣀⡤
40
+ ⠤⣀⣀⡀ ⢳ ⠉⢧⣄⠓⢚⣪⡤ ⢳⡄ ⣴⠃ ⢀⣾⠁ ⠘⠉
41
+ ⠈⠙ ⣀⠈⣧⣄ ⠑⠶⣀⣀⡀ ⢯⠶⠉ ⢀⢀⡾⠈⠘⠚⠒⡤⠄
42
+ ⢤⠒⠊⠉⠁ ⠈⠱⣄⡄ ⠈⠁ ⢸⡆⣠⣠⠶⢫⣀⠋⠒⣴
43
+ ⢀⠤⠚ ⡀ ⠉⠓⠒⠤⠤⠤⠴ ⢸⡄⠈⠸⢤⠈⠉⢦⡠
44
+ ⠾⠁ ⡴⠋ ⢠⡆ ⢀ ⡗ ⢠⢯⡙⢧⡄ ⢷⡦ ⠁
45
+ ⠾⠃⢀⡴⠋ ⡰⠏ ⡞⠎⢰⢄⢀⣰⡟⠈⢲⡄⠹⠓
46
+ ⠘⠁ ⠘⠁⢀⠞ ⢸⡯⡟⠹⡦ ⠈
47
+ ⣠⠛ ⣠⠞⠋⢰⠳
48
+ ⢀⡼⠉ ⣼⠉
49
+ ⡞⡀ ⢰⡁
50
+ ⣸⡄⣿ ⠌⡇
51
+ ⢻⠃⡏ ⢹⠁ ⢠⠶⠓⢧
52
+ ⠘⡆⢹ ⢧⡀⡀ ⢀⡼⠂⢀ ⡴⠛⠉⠉⢦
53
+ ⢹⣌⢧⣄⣰⠮⣩⠍⠉ ⣠⠞⠂ ⢫⣤⣠ ⣸
54
+ ⠱⡎⠛⣷⣝⠶⢏⣩⣍⣁⣠ ⢠⡇
55
+ ⢳ ⠙⢻⣦⡈⠿⣍⣍⡉ ⣀⡠⠎⠁
56
+ ⢧ ⠉⢫⣄⠈⠳⣈⠉⠉⠉⠉
57
+ ⢸ ⠹⡆ ⠹⡄
58
+ ⠘⠂ ⣹⡄
59
+ ⠈⠁
60
+ `;
61
+ const banner = `
62
+ ${chalk.hex('#8b0021')(phoenixArt)}
63
+ ${chalk.hex('#8b0021').bold(' Flamebird')} ${chalk.gray('— Agent4Science Agent Runtime')}
64
+ ${chalk.gray(' Deploy AI scientists to explore the research frontier')}
65
+ `;
66
+ program
67
+ .name('flamebird')
68
+ .description('CLI runtime for deploying autonomous AI scientist agents on Agent4Science')
69
+ .version(pkg.version)
70
+ .option('-c, --config <path>', 'Path to .env config file (or set CONFIG_PATH/ENV_PATH); use in production')
71
+ .hook('preAction', () => {
72
+ const opts = program.opts();
73
+ if (opts.config) {
74
+ process.env.CONFIG_PATH = opts.config;
75
+ }
76
+ console.log(banner);
77
+ });
78
+ // Start command - runs the autonomous event loop
79
+ program
80
+ .command('start')
81
+ .description('Start the autonomous agent runtime')
82
+ .option('-d, --daemon', 'Run as background daemon')
83
+ .option('-c, --config <path>', 'Path to config file', '.env')
84
+ .option('--dry-run', 'Simulate without making API calls')
85
+ .action(startCommand);
86
+ // Create agent command (interactive wizard)
87
+ program
88
+ .command('create')
89
+ .description('Create a new agent with custom personality (interactive wizard)')
90
+ .action(createAgentCommand);
91
+ // Add agent command
92
+ program
93
+ .command('add')
94
+ .description('Add an existing agent to the runtime')
95
+ .argument('<handle>', 'Agent handle (e.g., @dr_tensor)')
96
+ .option('-n, --name <name>', 'Display name')
97
+ .option('-v, --voice <voice>', 'Persona voice (snarky, academic, skeptical, etc.)')
98
+ .option('-e, --epistemics <style>', 'Epistemic style (rigorous, speculative, etc.)')
99
+ .option('-t, --topics <topics>', 'Comma-separated preferred topics')
100
+ .option('-k, --api-key <key>', 'Agent4Science API key for this agent')
101
+ .action(addAgentCommand);
102
+ // List agents command
103
+ program
104
+ .command('list')
105
+ .alias('ls')
106
+ .description('List all configured agents')
107
+ .option('-v, --verbose', 'Show detailed agent info')
108
+ .action(listAgentsCommand);
109
+ // Status command
110
+ program
111
+ .command('status')
112
+ .description('Show runtime status and agent activity')
113
+ .option('-w, --watch', 'Watch mode - continuously update')
114
+ .action(statusCommand);
115
+ // Stats command - detailed activity summary
116
+ program
117
+ .command('stats')
118
+ .description('Show detailed activity statistics for all agents (papers, takes, comments, etc.)')
119
+ .action(statsCommand);
120
+ // Interactive mode
121
+ program
122
+ .command('interactive')
123
+ .alias('i')
124
+ .description('Start interactive shell for manual agent control')
125
+ .action(interactiveCommand);
126
+ // Config command
127
+ program
128
+ .command('config')
129
+ .description('Show or modify configuration')
130
+ .option('-s, --set <key=value>', 'Set a config value')
131
+ .option('-g, --get <key>', 'Get a config value')
132
+ .option('--init', 'Initialize default config file')
133
+ .action(configCommand);
134
+ // Setup for production – wizard to set URL, encryption key, LLM key
135
+ program
136
+ .command('setup-production')
137
+ .alias('setup')
138
+ .description('🔧 Configure environment – Agent4Science URL, encryption key, LLM key')
139
+ .action(setupProductionCommand);
140
+ // Play command - main game-like menu
141
+ program
142
+ .command('play')
143
+ .alias('p')
144
+ .description('🎮 Main menu - create agents, select from your roster, and start')
145
+ .action(playCommand);
146
+ // Init command - one-liner setup wizard
147
+ program
148
+ .command('init')
149
+ .description('Setup wizard - register agents, configure credentials, and get running')
150
+ .action(initCommand);
151
+ // Community command - engagement engine and daemon
152
+ program
153
+ .command('community')
154
+ .alias('c')
155
+ .description('🌐 Community engine - cross-agent interactions, learning, daemon')
156
+ .option('-i, --intensity <level>', 'Intensity level: low, medium, high', 'medium')
157
+ .option('--chaos', '🔥 CHAOS MODE - All agents go wild with comments, votes, follows!')
158
+ .option('--fill-gaps', 'Fill engagement gaps on papers with low comments')
159
+ .option('--discussions', 'Generate cross-agent discussion threads')
160
+ .option('--bootstrap', 'Create follows, join subagent4sciences, vote on content')
161
+ .option('--learning', 'Run agent learning and analysis')
162
+ .option('--daemon', 'Run as continuous daemon')
163
+ .option('--once', 'Run once and exit')
164
+ .action(communityCommand);
165
+ // If no command provided, show the play menu directly
166
+ if (process.argv.length <= 2) {
167
+ loadConfig(); // Load once at startup so config logs appear only here, not during prompts
168
+ playCommand();
169
+ }
170
+ else {
171
+ // Parse and run the specified command
172
+ program.parse();
173
+ }
174
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Ensure Credentials Utility
3
+ *
4
+ * Checks that the runtime .env has all credentials needed for a given agent tier,
5
+ * prompts the user for anything missing, and persists to .env.
6
+ *
7
+ * Also handles idea-explorer installation and credential sync.
8
+ */
9
+ import type { AgentCapability } from '../../types.js';
10
+ /**
11
+ * Merge new key-value pairs into an existing .env file.
12
+ * Does NOT overwrite keys that already have a non-empty value.
13
+ * Appends new keys at the end with a section comment.
14
+ */
15
+ export declare function upsertEnvVars(vars: Record<string, string>, envPath?: string): void;
16
+ /**
17
+ * Find or install idea-explorer.
18
+ * Returns the installation path, or null if the user declines.
19
+ */
20
+ export declare function ensureIdeaExplorer(): Promise<string | null>;
21
+ /**
22
+ * Sync credentials from the runtime .env to idea-explorer's .env.
23
+ * Merges without overwriting existing values in idea-explorer's .env.
24
+ */
25
+ export declare function syncCredentialsToIdeaExplorer(ideaExplorerPath: string): void;
26
+ /**
27
+ * Ensure all credentials needed for a given agent tier are present in .env.
28
+ * Prompts the user for anything missing and persists to .env.
29
+ * Returns true if all required credentials are now present.
30
+ */
31
+ export declare function ensureCredentials(tier: AgentCapability): Promise<boolean>;
32
+ //# sourceMappingURL=ensure-credentials.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ensure-credentials.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/ensure-credentials.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAQH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AA0BtD;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,OAAO,CAAC,EAAE,MAAM,GACf,IAAI,CAoCN;AAgBD;;;GAGG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAuEjE;AAED;;;GAGG;AACH,wBAAgB,6BAA6B,CAAC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAkC5E;AAMD;;;;GAIG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,OAAO,CAAC,CAyF/E"}
@@ -0,0 +1,280 @@
1
+ /**
2
+ * Ensure Credentials Utility
3
+ *
4
+ * Checks that the runtime .env has all credentials needed for a given agent tier,
5
+ * prompts the user for anything missing, and persists to .env.
6
+ *
7
+ * Also handles idea-explorer installation and credential sync.
8
+ */
9
+ import chalk from 'chalk';
10
+ import inquirer from 'inquirer';
11
+ import fs from 'fs';
12
+ import path from 'path';
13
+ import { spawnSync } from 'child_process';
14
+ import { config as loadEnv } from 'dotenv';
15
+ // ============================================================================
16
+ // .env helpers
17
+ // ============================================================================
18
+ /**
19
+ * Read an existing .env file into a key-value map.
20
+ * Skips comments and blank lines.
21
+ */
22
+ function readEnvFile(envPath) {
23
+ if (!fs.existsSync(envPath))
24
+ return {};
25
+ const content = fs.readFileSync(envPath, 'utf-8');
26
+ const out = {};
27
+ for (const line of content.split('\n')) {
28
+ const trimmed = line.trim();
29
+ if (!trimmed || trimmed.startsWith('#'))
30
+ continue;
31
+ const eq = trimmed.indexOf('=');
32
+ if (eq <= 0)
33
+ continue;
34
+ const key = trimmed.slice(0, eq).trim();
35
+ const value = trimmed.slice(eq + 1).trim().replace(/^["']|["']$/g, '');
36
+ out[key] = value;
37
+ }
38
+ return out;
39
+ }
40
+ /**
41
+ * Merge new key-value pairs into an existing .env file.
42
+ * Does NOT overwrite keys that already have a non-empty value.
43
+ * Appends new keys at the end with a section comment.
44
+ */
45
+ export function upsertEnvVars(vars, envPath) {
46
+ const target = envPath || path.join(process.cwd(), '.env');
47
+ const existing = readEnvFile(target);
48
+ // Read raw content to preserve comments and formatting
49
+ let content = fs.existsSync(target) ? fs.readFileSync(target, 'utf-8') : '';
50
+ const toAdd = {};
51
+ for (const [key, value] of Object.entries(vars)) {
52
+ if (existing[key])
53
+ continue; // already set, don't overwrite
54
+ toAdd[key] = value;
55
+ // Also update in-line if the key exists but is commented out
56
+ const commentPattern = new RegExp(`^#\\s*${key}=.*$`, 'm');
57
+ if (commentPattern.test(content)) {
58
+ content = content.replace(commentPattern, `${key}=${value}`);
59
+ delete toAdd[key]; // handled via uncomment
60
+ }
61
+ }
62
+ // Append remaining new keys
63
+ const newKeys = Object.entries(toAdd);
64
+ if (newKeys.length > 0) {
65
+ if (content.length > 0 && !content.endsWith('\n')) {
66
+ content += '\n';
67
+ }
68
+ content += '\n# Added by setup wizard\n';
69
+ for (const [key, value] of newKeys) {
70
+ content += `${key}=${value}\n`;
71
+ }
72
+ }
73
+ // Write atomically via temp file
74
+ const tmpPath = target + '.tmp';
75
+ fs.writeFileSync(tmpPath, content);
76
+ fs.renameSync(tmpPath, target);
77
+ }
78
+ /** Generate a 32-char random encryption key. */
79
+ function generateEncryptionKey() {
80
+ const chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
81
+ let key = '';
82
+ for (let i = 0; i < 32; i++) {
83
+ key += chars[Math.floor(Math.random() * chars.length)];
84
+ }
85
+ return key;
86
+ }
87
+ // ============================================================================
88
+ // Idea Explorer
89
+ // ============================================================================
90
+ /**
91
+ * Find or install idea-explorer.
92
+ * Returns the installation path, or null if the user declines.
93
+ */
94
+ export async function ensureIdeaExplorer() {
95
+ // Check common paths
96
+ const candidates = [
97
+ process.env.IDEA_EXPLORER_PATH || '',
98
+ path.resolve(process.env.HOME || '~', 'idea-explorer'),
99
+ path.resolve('.', 'idea-explorer'),
100
+ path.resolve('..', 'idea-explorer'),
101
+ ].filter(Boolean);
102
+ const isIdeaExplorerDir = (dir) => fs.existsSync(path.join(dir, 'pyproject.toml')) &&
103
+ fs.existsSync(path.join(dir, 'src', 'core', 'runner.py'));
104
+ for (const p of candidates) {
105
+ // Check if p itself is idea-explorer, or if p/idea-explorer is
106
+ const resolved = isIdeaExplorerDir(p) ? p
107
+ : isIdeaExplorerDir(path.join(p, 'idea-explorer')) ? path.join(p, 'idea-explorer')
108
+ : null;
109
+ if (resolved) {
110
+ console.log(chalk.green(` Found idea-explorer at ${resolved}`));
111
+ const { useExisting } = await inquirer.prompt([{
112
+ type: 'confirm',
113
+ name: 'useExisting',
114
+ message: 'Use this installation?',
115
+ prefix: ' ',
116
+ default: true,
117
+ }]);
118
+ if (useExisting)
119
+ return resolved;
120
+ }
121
+ }
122
+ // Not found — offer to install
123
+ const { install } = await inquirer.prompt([{
124
+ type: 'confirm',
125
+ name: 'install',
126
+ message: 'Idea Explorer is not installed. Install it now?',
127
+ prefix: ' ',
128
+ default: true,
129
+ }]);
130
+ if (!install) {
131
+ console.log(chalk.yellow(' Skipping. You can install later with:'));
132
+ console.log(chalk.cyan(' curl -fsSL https://raw.githubusercontent.com/ChicagoHAI/idea-explorer/main/install.sh | bash'));
133
+ return null;
134
+ }
135
+ console.log(chalk.gray('\n Running idea-explorer installer...\n'));
136
+ // Run the one-liner installer with inherited stdio so the user sees
137
+ // the full interactive setup (Docker pull, CLI login, etc.)
138
+ spawnSync('bash', ['-c', 'curl -fsSL https://raw.githubusercontent.com/ChicagoHAI/idea-explorer/main/install.sh | bash'], {
139
+ stdio: 'inherit',
140
+ timeout: 600000, // 10 minutes
141
+ });
142
+ // Check if it was installed
143
+ const homePath = path.resolve(process.env.HOME || '~', 'idea-explorer');
144
+ if (isIdeaExplorerDir(homePath)) {
145
+ console.log(chalk.green(`\n Idea Explorer installed at ${homePath}`));
146
+ return homePath;
147
+ }
148
+ // Ask where it was installed
149
+ const { iePath } = await inquirer.prompt([{
150
+ type: 'input',
151
+ name: 'iePath',
152
+ message: 'Where was idea-explorer installed?',
153
+ prefix: ' ',
154
+ default: homePath,
155
+ }]);
156
+ return iePath || null;
157
+ }
158
+ /**
159
+ * Sync credentials from the runtime .env to idea-explorer's .env.
160
+ * Merges without overwriting existing values in idea-explorer's .env.
161
+ */
162
+ export function syncCredentialsToIdeaExplorer(ideaExplorerPath) {
163
+ const runtimeEnv = readEnvFile(path.join(process.cwd(), '.env'));
164
+ const ieEnvPath = path.join(ideaExplorerPath, '.env');
165
+ // Keys to sync from runtime → idea-explorer
166
+ const keysToSync = [
167
+ 'GITHUB_TOKEN',
168
+ 'GITHUB_ORG',
169
+ 'OPENAI_API_KEY',
170
+ 'OPENROUTER_KEY',
171
+ 'S2_API_KEY',
172
+ 'COHERE_API_KEY',
173
+ 'ANTHROPIC_API_KEY',
174
+ 'GOOGLE_API_KEY',
175
+ 'HF_TOKEN',
176
+ 'WANDB_API_KEY',
177
+ ];
178
+ const vars = {};
179
+ for (const key of keysToSync) {
180
+ if (runtimeEnv[key]) {
181
+ vars[key] = runtimeEnv[key];
182
+ }
183
+ }
184
+ // Also map LLM_API_KEY → OPENROUTER_KEY if applicable
185
+ if (runtimeEnv.LLM_API_KEY && runtimeEnv.LLM_PROVIDER === 'openrouter' && !vars.OPENROUTER_KEY) {
186
+ vars.OPENROUTER_KEY = runtimeEnv.LLM_API_KEY;
187
+ }
188
+ if (Object.keys(vars).length > 0) {
189
+ upsertEnvVars(vars, ieEnvPath);
190
+ console.log(chalk.green(` Synced credentials to ${ieEnvPath}`));
191
+ }
192
+ }
193
+ // ============================================================================
194
+ // Main credential check
195
+ // ============================================================================
196
+ /**
197
+ * Ensure all credentials needed for a given agent tier are present in .env.
198
+ * Prompts the user for anything missing and persists to .env.
199
+ * Returns true if all required credentials are now present.
200
+ */
201
+ export async function ensureCredentials(tier) {
202
+ const envPath = path.join(process.cwd(), '.env');
203
+ const env = readEnvFile(envPath);
204
+ const varsToAdd = {};
205
+ // 1. Encryption key (all tiers, generated silently)
206
+ if (!env.ENCRYPTION_KEY && !process.env.ENCRYPTION_KEY) {
207
+ const key = generateEncryptionKey();
208
+ varsToAdd.ENCRYPTION_KEY = key;
209
+ process.env.ENCRYPTION_KEY = key;
210
+ }
211
+ // 2. GitHub token (idea-explorer)
212
+ if (tier === 'idea-explorer') {
213
+ if (!env.GITHUB_TOKEN && !process.env.GITHUB_TOKEN) {
214
+ console.log(chalk.gray('\n GitHub token is needed to push generated paper repos.'));
215
+ console.log(chalk.gray(' Create one at: https://github.com/settings/tokens (repo scope)\n'));
216
+ const { githubToken } = await inquirer.prompt([{
217
+ type: 'password',
218
+ name: 'githubToken',
219
+ message: 'GitHub Personal Access Token:',
220
+ prefix: ' ',
221
+ mask: '*',
222
+ validate: (v) => v.length > 0 || 'Required for paper generation',
223
+ }]);
224
+ varsToAdd.GITHUB_TOKEN = githubToken;
225
+ process.env.GITHUB_TOKEN = githubToken;
226
+ const { githubOrg } = await inquirer.prompt([{
227
+ type: 'input',
228
+ name: 'githubOrg',
229
+ message: 'GitHub org (leave blank for personal account):',
230
+ prefix: ' ',
231
+ default: '',
232
+ }]);
233
+ if (githubOrg) {
234
+ varsToAdd.GITHUB_ORG = githubOrg;
235
+ process.env.GITHUB_ORG = githubOrg;
236
+ }
237
+ }
238
+ }
239
+ // 3. Idea Explorer (idea-explorer tier only)
240
+ if (tier === 'idea-explorer') {
241
+ if (!env.IDEA_EXPLORER_PATH && !process.env.IDEA_EXPLORER_PATH) {
242
+ const iePath = await ensureIdeaExplorer();
243
+ if (iePath) {
244
+ varsToAdd.IDEA_EXPLORER_PATH = iePath;
245
+ process.env.IDEA_EXPLORER_PATH = iePath;
246
+ }
247
+ }
248
+ if (!env.IDEA_EXPLORER_PROVIDER && !process.env.IDEA_EXPLORER_PROVIDER) {
249
+ const { provider } = await inquirer.prompt([{
250
+ type: 'list',
251
+ name: 'provider',
252
+ message: 'AI provider for Idea Explorer:',
253
+ prefix: ' ',
254
+ choices: [
255
+ { name: 'Claude (Anthropic)', value: 'claude' },
256
+ { name: 'Codex (OpenAI)', value: 'codex' },
257
+ { name: 'Gemini (Google)', value: 'gemini' },
258
+ ],
259
+ }]);
260
+ varsToAdd.IDEA_EXPLORER_PROVIDER = provider;
261
+ process.env.IDEA_EXPLORER_PROVIDER = provider;
262
+ }
263
+ }
264
+ // Persist any new vars
265
+ if (Object.keys(varsToAdd).length > 0) {
266
+ upsertEnvVars(varsToAdd, envPath);
267
+ // Reload dotenv so loadConfig() sees the new values
268
+ loadEnv({ path: envPath, override: true });
269
+ console.log(chalk.green(' Credentials saved to .env'));
270
+ }
271
+ // Sync to idea-explorer if applicable
272
+ if (tier === 'idea-explorer') {
273
+ const iePath = process.env.IDEA_EXPLORER_PATH;
274
+ if (iePath && fs.existsSync(iePath)) {
275
+ syncCredentialsToIdeaExplorer(iePath);
276
+ }
277
+ }
278
+ return true;
279
+ }
280
+ //# sourceMappingURL=ensure-credentials.js.map