@reepoe/plugin 1.1.9 → 1.2.5

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/bin/start.js CHANGED
@@ -18,7 +18,7 @@ function isCloudEnvironment() {
18
18
  );
19
19
  }
20
20
 
21
- // Get binary path
21
+ // Get binary path (FIXED - use require.resolve for correct npm path)
22
22
  function getBinaryPath() {
23
23
  const platform = os.platform();
24
24
  const arch = os.arch();
@@ -32,8 +32,16 @@ function getBinaryPath() {
32
32
  binaryName = 'reepoe-windows.exe';
33
33
  }
34
34
 
35
- const binaryPath = path.join(__dirname, '../binaries', binaryName);
36
- return fs.existsSync(binaryPath) ? binaryPath : null;
35
+ // Use require.resolve to find the actual npm install location
36
+ try {
37
+ const packageRoot = path.dirname(require.resolve('reepoe/package.json'));
38
+ const binaryPath = path.join(packageRoot, 'binaries', binaryName);
39
+ return fs.existsSync(binaryPath) ? binaryPath : null;
40
+ } catch (e) {
41
+ // Fallback to relative path
42
+ const binaryPath = path.join(__dirname, '../binaries', binaryName);
43
+ return fs.existsSync(binaryPath) ? binaryPath : null;
44
+ }
37
45
  }
38
46
 
39
47
  // Check if server is already running
@@ -168,11 +176,158 @@ async function checkActivationStatus() {
168
176
  }
169
177
  }
170
178
 
179
+ // ========== BYOK WIZARD (FIX #1) ==========
180
+ async function checkAndSetupBYOK() {
181
+ const byokConfigPath = path.join(os.homedir(), '.reepoe', 'config.json');
182
+
183
+ if (fs.existsSync(byokConfigPath)) {
184
+ return; // Already configured
185
+ }
186
+
187
+ const readline = require('readline');
188
+ const crypto = require('crypto');
189
+
190
+ console.log('\n╔══════════════════════════════════════════════════════════════╗');
191
+ console.log('║ ReePoe BYOK Setup - Bring Your Own Key ║');
192
+ console.log('╚══════════════════════════════════════════════════════════════╝\n');
193
+ console.log('💡 ReePoe can use YOUR OpenRouter API key for intelligent routing.');
194
+ console.log(' Benefits:');
195
+ console.log(' ✅ Use OpenRouter free tier (50 queries/day)');
196
+ console.log(' ✅ Full cost transparency and tracking');
197
+ console.log(' ✅ Uses google/gemma-3-4b-it:free for routing\n');
198
+ console.log(' ℹ️ Your key is stored locally and NEVER transmitted.');
199
+ console.log(' ℹ️ Get a free key at: https://openrouter.ai/keys\n');
200
+
201
+ const rl = readline.createInterface({
202
+ input: process.stdin,
203
+ output: process.stdout
204
+ });
205
+
206
+ const apiKey = await new Promise((resolve) => {
207
+ rl.question('Enter OpenRouter API key (or press Enter to skip): ', (answer) => {
208
+ rl.close();
209
+ resolve(answer.trim());
210
+ });
211
+ });
212
+
213
+ if (apiKey && apiKey.startsWith('sk-or-v1-')) {
214
+ try {
215
+ const globalConfigDir = path.join(os.homedir(), '.reepoe');
216
+ if (!fs.existsSync(globalConfigDir)) {
217
+ fs.mkdirSync(globalConfigDir, { recursive: true, mode: 0o700 });
218
+ }
219
+
220
+ const userId = 'anon_' + crypto.createHash('sha256')
221
+ .update(crypto.randomBytes(32))
222
+ .digest('hex')
223
+ .substring(0, 16);
224
+
225
+ const encryptedKey = Buffer.from(apiKey).toString('base64');
226
+
227
+ const globalConfig = {
228
+ api_keys: { openrouter: encryptedKey, encrypted: true },
229
+ user_id: userId,
230
+ analytics: { enabled: true, anonymous: true },
231
+ created_at: new Date().toISOString()
232
+ };
233
+
234
+ fs.writeFileSync(byokConfigPath, JSON.stringify(globalConfig, null, 2), { mode: 0o600 });
235
+ console.log('\n✅ API key stored securely in ~/.reepoe/config.json');
236
+ } catch (error) {
237
+ console.error(`\n❌ Failed to store API key: ${error.message}`);
238
+ }
239
+ } else if (apiKey) {
240
+ console.log('\n⚠️ Invalid key format (should start with sk-or-v1-)');
241
+ } else {
242
+ console.log('\n ℹ️ Skipping BYOK setup - using default routing');
243
+ }
244
+ }
245
+
246
+ // ========== PROJECT SETUP (FIX #2) ==========
247
+ function detectProjectType(projectPath) {
248
+ const markers = {
249
+ 'package.json': { language: 'javascript', name: 'Node.js' },
250
+ 'requirements.txt': { language: 'python', name: 'Python' },
251
+ 'go.mod': { language: 'go', name: 'Go' },
252
+ 'Cargo.toml': { language: 'rust', name: 'Rust' },
253
+ 'pom.xml': { language: 'java', name: 'Java' }
254
+ };
255
+
256
+ for (const [file, config] of Object.entries(markers)) {
257
+ if (fs.existsSync(path.join(projectPath, file))) {
258
+ let projectName = path.basename(projectPath);
259
+
260
+ if (file === 'package.json') {
261
+ try {
262
+ const pkg = JSON.parse(fs.readFileSync(path.join(projectPath, file), 'utf8'));
263
+ projectName = pkg.name || projectName;
264
+ const deps = { ...pkg.dependencies, ...pkg.devDependencies };
265
+ if (deps.express) config.framework = 'Express';
266
+ else if (deps.react) config.framework = 'React';
267
+ else if (deps.vue) config.framework = 'Vue';
268
+ } catch (e) {
269
+ // Use defaults
270
+ }
271
+ }
272
+
273
+ return { ...config, projectName };
274
+ }
275
+ }
276
+
277
+ return { language: 'unknown', name: 'Generic', projectName: path.basename(projectPath) };
278
+ }
279
+
280
+ async function setupProjectIfNeeded(port) {
281
+ const configPath = path.join(process.cwd(), 'reepoe.config.json');
282
+
283
+ if (fs.existsSync(configPath)) {
284
+ return; // Already set up
285
+ }
286
+
287
+ console.log('🔍 First run in this directory - initializing project...\n');
288
+
289
+ const projectInfo = detectProjectType(process.cwd());
290
+ console.log(` ✅ ${projectInfo.name} project detected`);
291
+ if (projectInfo.framework) {
292
+ console.log(` Framework: ${projectInfo.framework}`);
293
+ }
294
+
295
+ const config = {
296
+ project: {
297
+ name: projectInfo.projectName,
298
+ type: projectInfo.language,
299
+ framework: projectInfo.framework || null,
300
+ root: process.cwd()
301
+ },
302
+ api: { port, host: '127.0.0.1' },
303
+ mini_rag: {
304
+ enabled: true,
305
+ confidence_threshold: 0.6,
306
+ cta_whitelist: ['run_tests', 'open_file', 'search_symbols', 'get_repo_stats']
307
+ },
308
+ scanner: { language: projectInfo.language, auto_scan: true }
309
+ };
310
+
311
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
312
+ console.log(` ✅ Configuration created`);
313
+
314
+ ['data', 'logs'].forEach(dir => {
315
+ const dirPath = path.join(process.cwd(), dir);
316
+ if (!fs.existsSync(dirPath)) {
317
+ fs.mkdirSync(dirPath, { recursive: true });
318
+ }
319
+ });
320
+ console.log(` ✅ Directories created\n`);
321
+ }
322
+
171
323
  // Main function
172
324
  async function main() {
173
325
  // Check activation first (Phase 3B)
174
326
  const email = await checkActivationStatus();
175
327
 
328
+ // FIX #1: Check and setup BYOK if needed
329
+ await checkAndSetupBYOK();
330
+
176
331
  console.log('\n🚀 Starting ReePoe server...\n');
177
332
 
178
333
  // Read configuration
@@ -194,6 +349,11 @@ async function main() {
194
349
  // Detect cloud environment
195
350
  const isCloud = isCloudEnvironment();
196
351
 
352
+ // FIX #2: Setup project if needed (before starting binary)
353
+ if (!isCloud) {
354
+ await setupProjectIfNeeded(port);
355
+ }
356
+
197
357
  if (isCloud) {
198
358
  // Cloud environment - skip local server
199
359
  console.log('\n☁️ Cloud environment detected');
@@ -245,8 +405,8 @@ async function main() {
245
405
  const pidFile = path.join(os.tmpdir(), `reepoe-${port}.pid`);
246
406
  fs.writeFileSync(pidFile, child.pid.toString());
247
407
 
248
- // Wait a bit and check if server started
249
- await new Promise(resolve => setTimeout(resolve, 2000));
408
+ // Wait for server to start (FIX #3: Increased timeout)
409
+ await new Promise(resolve => setTimeout(resolve, 5000));
250
410
 
251
411
  const started = await isServerRunning(port);
252
412
 
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reepoe/plugin",
3
- "version": "1.1.9",
3
+ "version": "1.2.5",
4
4
  "description": "ReePoe AI Code Manager - Install in any codebase for instant AI agent integration",
5
5
  "keywords": [
6
6
  "ai",