reepoe 1.1.1

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.
@@ -0,0 +1,269 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * ReePoe Post-Install Setup
4
+ * Automatically configures ReePoe for the current project
5
+ */
6
+
7
+ const fs = require('fs');
8
+ const path = require('path');
9
+ const { spawn } = require('child_process');
10
+ const os = require('os');
11
+
12
+ // Detect project type
13
+ function detectProjectType(projectPath) {
14
+ const markers = {
15
+ 'package.json': { language: 'javascript', name: 'Node.js' },
16
+ 'requirements.txt': { language: 'python', name: 'Python' },
17
+ 'go.mod': { language: 'go', name: 'Go' },
18
+ 'Cargo.toml': { language: 'rust', name: 'Rust' },
19
+ 'pom.xml': { language: 'java', name: 'Java' }
20
+ };
21
+
22
+ for (const [file, config] of Object.entries(markers)) {
23
+ if (fs.existsSync(path.join(projectPath, file))) {
24
+ // Read project name if possible
25
+ let projectName = path.basename(projectPath);
26
+
27
+ if (file === 'package.json') {
28
+ try {
29
+ const pkg = JSON.parse(fs.readFileSync(path.join(projectPath, file), 'utf8'));
30
+ projectName = pkg.name || projectName;
31
+
32
+ // Detect framework
33
+ const deps = { ...pkg.dependencies, ...pkg.devDependencies };
34
+ if (deps.express) config.framework = 'Express';
35
+ else if (deps.react) config.framework = 'React';
36
+ else if (deps.vue) config.framework = 'Vue';
37
+
38
+ } catch (e) {
39
+ // Use defaults
40
+ }
41
+ }
42
+
43
+ return { ...config, projectName };
44
+ }
45
+ }
46
+
47
+ return { language: 'unknown', name: 'Generic', projectName: path.basename(projectPath) };
48
+ }
49
+
50
+ // Find available port
51
+ async function findAvailablePort(start = 8000, end = 9000) {
52
+ const net = require('net');
53
+
54
+ for (let port = start; port <= end; port++) {
55
+ const available = await new Promise((resolve) => {
56
+ const server = net.createServer();
57
+ server.once('error', () => resolve(false));
58
+ server.once('listening', () => {
59
+ server.close();
60
+ resolve(true);
61
+ });
62
+ server.listen(port, '127.0.0.1');
63
+ });
64
+
65
+ if (available) {
66
+ return port;
67
+ }
68
+ }
69
+
70
+ return start; // Fallback to first port
71
+ }
72
+
73
+ // Create configuration file
74
+ async function createConfiguration(projectInfo, port) {
75
+ const config = {
76
+ project: {
77
+ name: projectInfo.projectName,
78
+ type: projectInfo.language,
79
+ framework: projectInfo.framework || null,
80
+ root: process.cwd()
81
+ },
82
+ api: {
83
+ port: port,
84
+ host: '127.0.0.1'
85
+ },
86
+ mini_rag: {
87
+ enabled: true,
88
+ confidence_threshold: 0.6,
89
+ cta_whitelist: ['run_tests', 'open_file', 'search_symbols', 'get_repo_stats']
90
+ },
91
+ scanner: {
92
+ language: projectInfo.language,
93
+ auto_scan: true
94
+ }
95
+ };
96
+
97
+ const configPath = path.join(process.cwd(), 'reepoe.config.json');
98
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
99
+
100
+ return configPath;
101
+ }
102
+
103
+ // Create data directories
104
+ function createDataDirectories() {
105
+ const dirs = ['data', 'logs'];
106
+
107
+ for (const dir of dirs) {
108
+ const dirPath = path.join(process.cwd(), dir);
109
+ if (!fs.existsSync(dirPath)) {
110
+ fs.mkdirSync(dirPath, { recursive: true });
111
+ }
112
+ }
113
+ }
114
+
115
+ // ========== BYOK (Bring Your Own Key) Setup Wizard ==========
116
+
117
+ async function setupBYOK() {
118
+ // BYOK Setup Wizard for global installations
119
+ const readline = require('readline');
120
+ const crypto = require('crypto');
121
+
122
+ console.log('\n╔══════════════════════════════════════════════════════════════╗');
123
+ console.log('║ ReePoe BYOK Setup - Bring Your Own Key ║');
124
+ console.log('╚══════════════════════════════════════════════════════════════╝\n');
125
+
126
+ console.log('💡 ReePoe can use YOUR OpenRouter API key for intelligent routing.');
127
+ console.log(' Benefits:');
128
+ console.log(' ✅ Use OpenRouter free tier (50 queries/day)');
129
+ console.log(' ✅ Full cost transparency and tracking');
130
+ console.log(' ✅ Uses google/gemma-3-4b-it:free for routing\n');
131
+
132
+ console.log(' ℹ️ Your key is stored locally and NEVER transmitted.');
133
+ console.log(' ℹ️ Get a free key at: https://openrouter.ai/keys\n');
134
+
135
+ // Prompt for API key
136
+ const rl = readline.createInterface({
137
+ input: process.stdin,
138
+ output: process.stdout
139
+ });
140
+
141
+ const apiKey = await new Promise((resolve) => {
142
+ rl.question('Enter OpenRouter API key (or press Enter to skip): ', (answer) => {
143
+ rl.close();
144
+ resolve(answer.trim());
145
+ });
146
+ });
147
+
148
+ if (apiKey && apiKey.length > 0) {
149
+ // Validate format
150
+ if (apiKey.startsWith('sk-or-v1-')) {
151
+ try {
152
+ // Store API key in ~/.reepoe/config.json
153
+ const globalConfigDir = path.join(os.homedir(), '.reepoe');
154
+ const globalConfigPath = path.join(globalConfigDir, 'config.json');
155
+
156
+ // Create directory if doesn't exist
157
+ if (!fs.existsSync(globalConfigDir)) {
158
+ fs.mkdirSync(globalConfigDir, { recursive: true, mode: 0o700 });
159
+ }
160
+
161
+ // Generate anonymous user ID
162
+ const userId = 'anon_' + crypto.createHash('sha256')
163
+ .update(crypto.randomBytes(32))
164
+ .digest('hex')
165
+ .substring(0, 16);
166
+
167
+ // Simple encryption (base64)
168
+ const encryptedKey = Buffer.from(apiKey).toString('base64');
169
+
170
+ const globalConfig = {
171
+ api_keys: {
172
+ openrouter: encryptedKey,
173
+ encrypted: true
174
+ },
175
+ user_id: userId,
176
+ analytics: {
177
+ enabled: true,
178
+ anonymous: true
179
+ },
180
+ created_at: new Date().toISOString()
181
+ };
182
+
183
+ fs.writeFileSync(globalConfigPath, JSON.stringify(globalConfig, null, 2), { mode: 0o600 });
184
+
185
+ console.log('\n✅ API key stored securely in ~/.reepoe/config.json');
186
+ console.log(' Your key is encrypted and only accessible by you.');
187
+ console.log(' Anonymous user ID generated for analytics.');
188
+ console.log('\n💰 Cost tracking enabled - monitor your usage in real-time!');
189
+
190
+ } catch (error) {
191
+ console.error(`\n❌ Failed to store API key: ${error.message}`);
192
+ console.log(' Continuing with limited features...');
193
+ }
194
+ } else {
195
+ console.log('\n⚠️ Invalid API key format (should start with sk-or-v1-)');
196
+ console.log(' Skipping BYOK setup - ReePoe will use default routing.');
197
+ console.log(' You can add your key later in ~/.reepoe/config.json');
198
+ }
199
+ } else {
200
+ console.log('\n ℹ️ Skipping BYOK setup - using default routing');
201
+ console.log(' ReePoe will work with limited features.');
202
+ console.log(' To enable BYOK later, run: reepoe-setup-key');
203
+ }
204
+ }
205
+
206
+ // Main setup function
207
+ async function setup() {
208
+ // For global install, run BYOK wizard
209
+ if (process.env.npm_config_global === 'true') {
210
+ await setupBYOK();
211
+
212
+ console.log('\n✅ ReePoe installed globally');
213
+ console.log('\n📝 To use in a project:');
214
+ console.log(' cd /path/to/your/project');
215
+ console.log(' reepoe-start\n');
216
+ return;
217
+ }
218
+
219
+ console.log('\n╔══════════════════════════════════════════════════════════════╗');
220
+ console.log('║ ReePoe Plugin - Auto Setup ║');
221
+ console.log('╚══════════════════════════════════════════════════════════════╝\n');
222
+
223
+ // Detect project
224
+ console.log('🔍 Detecting project type...');
225
+ const projectInfo = detectProjectType(process.cwd());
226
+ console.log(` ✅ ${projectInfo.name} project detected`);
227
+ if (projectInfo.framework) {
228
+ console.log(` Framework: ${projectInfo.framework}`);
229
+ }
230
+
231
+ // Find available port
232
+ console.log('\n⚙️ Finding available port...');
233
+ const port = await findAvailablePort();
234
+ console.log(` ✅ Port ${port} available`);
235
+
236
+ // Create configuration
237
+ console.log('\n📝 Creating configuration...');
238
+ const configPath = await createConfiguration(projectInfo, port);
239
+ console.log(` ✅ Configuration created: ${configPath}`);
240
+
241
+ // Create directories
242
+ console.log('\n📁 Setting up directories...');
243
+ createDataDirectories();
244
+ console.log(` ✅ Data directories created`);
245
+
246
+ // Success message
247
+ console.log('\n╔══════════════════════════════════════════════════════════════╗');
248
+ console.log('║ ✅ ReePoe Setup Complete! ║');
249
+ console.log('╚══════════════════════════════════════════════════════════════╝\n');
250
+
251
+ console.log('🚀 Start ReePoe:');
252
+ console.log(' reepoe-start\n');
253
+
254
+ console.log('💡 Try these commands:');
255
+ console.log(' reepoe query "what does this codebase do?"');
256
+ console.log(' reepoe query "show me all API endpoints"');
257
+ console.log(' reepoe query "find test files"\n');
258
+
259
+ console.log('📊 Management:');
260
+ console.log(' reepoe-status - Check server status');
261
+ console.log(' reepoe-stop - Stop server\n');
262
+ }
263
+
264
+ setup().catch(error => {
265
+ console.error(`\n❌ Setup failed: ${error.message}`);
266
+ console.error(' You can run setup manually with: node scripts/setup.js');
267
+ process.exit(1);
268
+ });
269
+