gitarsenal-cli 1.9.78 → 1.9.81

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/.venv_status.json CHANGED
@@ -1 +1 @@
1
- {"created":"2025-08-17T17:20:43.416Z","packages":["modal","gitingest","requests","anthropic"],"uv_version":"uv 0.8.4 (Homebrew 2025-07-30)"}
1
+ {"created":"2025-08-18T04:41:52.342Z","packages":["modal","gitingest","requests","anthropic"],"uv_version":"uv 0.8.4 (Homebrew 2025-07-30)"}
package/bin/gitarsenal.js CHANGED
@@ -89,7 +89,7 @@ function activateVirtualEnvironment() {
89
89
  process.env.PYTHON_EXECUTABLE = pythonPath;
90
90
  process.env.PIP_EXECUTABLE = pipPath;
91
91
 
92
- console.log(chalk.green('✅ Virtual environment activated successfully'));
92
+ // console.log(chalk.green('✅ Virtual environment activated successfully'));
93
93
 
94
94
  return true;
95
95
  }
@@ -259,16 +259,33 @@ function printGpuTorchCudaSummary(result) {
259
259
 
260
260
  // Print API key requirements if available
261
261
  if (result.requiredApiKeys && Array.isArray(result.requiredApiKeys) && result.requiredApiKeys.length > 0) {
262
- console.log(chalk.bold('🔑 REQUIRED API KEYS'));
263
- result.requiredApiKeys.forEach(apiKey => {
264
- const status = apiKey.required ? chalk.red('REQUIRED') : chalk.yellow('OPTIONAL');
265
- console.log(` - ${apiKey.name} (${status})`);
266
- console.log(` Service: ${apiKey.service}`);
267
- console.log(` Purpose: ${apiKey.description}`);
268
- if (apiKey.example) console.log(` Format: ${apiKey.example}`);
269
- if (apiKey.documentation_url) console.log(` Docs: ${apiKey.documentation_url}`);
270
- console.log();
271
- });
262
+ // Separate critical and optional API keys
263
+ const criticalKeys = result.requiredApiKeys.filter(key => key.priority === 'critical' || key.required);
264
+ const optionalKeys = result.requiredApiKeys.filter(key => key.priority === 'optional' || !key.required);
265
+
266
+ if (criticalKeys.length > 0) {
267
+ console.log(chalk.bold('🔑 CRITICAL API KEYS'));
268
+ criticalKeys.forEach(apiKey => {
269
+ console.log(` - ${apiKey.name} ${chalk.red('(REQUIRED)')}`);
270
+ console.log(` Service: ${apiKey.service}`);
271
+ console.log(` Purpose: ${apiKey.description}`);
272
+ if (apiKey.example) console.log(` Format: ${apiKey.example}`);
273
+ if (apiKey.documentation_url) console.log(` Docs: ${apiKey.documentation_url}`);
274
+ console.log();
275
+ });
276
+ }
277
+
278
+ if (optionalKeys.length > 0) {
279
+ console.log(chalk.bold('🔧 OPTIONAL API KEYS'));
280
+ optionalKeys.forEach(apiKey => {
281
+ console.log(` - ${apiKey.name} ${chalk.yellow('(OPTIONAL)')}`);
282
+ console.log(` Service: ${apiKey.service}`);
283
+ console.log(` Purpose: ${apiKey.description}`);
284
+ if (apiKey.example) console.log(` Format: ${apiKey.example}`);
285
+ if (apiKey.documentation_url) console.log(` Docs: ${apiKey.documentation_url}`);
286
+ console.log();
287
+ });
288
+ }
272
289
  }
273
290
  } catch {}
274
291
  }
@@ -316,19 +333,22 @@ async function promptForMissingApiKeys(requiredApiKeys, storedKeys) {
316
333
  }
317
334
 
318
335
  const missingKeys = {};
319
- const requiredMissingKeys = requiredApiKeys.filter(apiKey =>
320
- apiKey.required && !storedKeys[apiKey.service.toLowerCase()]
336
+
337
+ // Separate critical and optional missing keys
338
+ const criticalMissingKeys = requiredApiKeys.filter(apiKey =>
339
+ (apiKey.priority === 'critical' || apiKey.required) && !storedKeys[apiKey.service.toLowerCase()]
340
+ );
341
+
342
+ const optionalMissingKeys = requiredApiKeys.filter(apiKey =>
343
+ (apiKey.priority === 'optional' || !apiKey.required) && !storedKeys[apiKey.service.toLowerCase()]
321
344
  );
322
345
 
323
- if (requiredMissingKeys.length === 0) {
324
- console.log(chalk.green('✅ All required API keys are already stored'));
325
- return {};
326
- }
327
-
328
- console.log(chalk.yellow('\n🔑 Missing Required API Keys'));
329
- console.log(chalk.gray('The following API keys are required for this repository:'));
346
+ // Handle critical keys first
347
+ if (criticalMissingKeys.length > 0) {
348
+ console.log(chalk.red('\n🔑 Critical API Keys Required'));
349
+ console.log(chalk.gray('These API keys are required for core functionality:'));
330
350
 
331
- for (const apiKey of requiredMissingKeys) {
351
+ for (const apiKey of criticalMissingKeys) {
332
352
  console.log(chalk.bold(`\n📝 ${apiKey.name} (${apiKey.service})`));
333
353
  console.log(chalk.gray(`Purpose: ${apiKey.description}`));
334
354
  if (apiKey.documentation_url) {
@@ -402,6 +422,101 @@ async function promptForMissingApiKeys(requiredApiKeys, storedKeys) {
402
422
  console.log(chalk.yellow(`⚠️ Skipping ${apiKey.service} API key. Repository setup may fail without it.`));
403
423
  }
404
424
  }
425
+ }
426
+
427
+ // Handle optional keys
428
+ if (optionalMissingKeys.length > 0) {
429
+ const setupOptional = await inquirer.prompt([
430
+ {
431
+ type: 'confirm',
432
+ name: 'wantOptional',
433
+ message: `${optionalMissingKeys.length} optional API key(s) available. Set them up for enhanced features?`,
434
+ default: false
435
+ }
436
+ ]);
437
+
438
+ if (setupOptional.wantOptional) {
439
+ console.log(chalk.blue('\n🔧 Optional API Keys Setup'));
440
+ console.log(chalk.gray('These enhance functionality but are not required:'));
441
+
442
+ for (const apiKey of optionalMissingKeys) {
443
+ console.log(chalk.bold(`\n📝 ${apiKey.name} (${apiKey.service}) - Optional`));
444
+ console.log(chalk.gray(`Purpose: ${apiKey.description}`));
445
+ if (apiKey.documentation_url) {
446
+ console.log(chalk.blue(`Documentation: ${apiKey.documentation_url}`));
447
+ }
448
+
449
+ const answers = await inquirer.prompt([
450
+ {
451
+ type: 'confirm',
452
+ name: 'provideKey',
453
+ message: `Provide ${apiKey.service} API key for enhanced features?`,
454
+ default: false
455
+ }
456
+ ]);
457
+
458
+ if (answers.provideKey) {
459
+ const keyAnswer = await inquirer.prompt([
460
+ {
461
+ type: 'password',
462
+ name: 'key',
463
+ message: `Enter your ${apiKey.service} API key:`,
464
+ mask: '*',
465
+ validate: (input) => {
466
+ const key = input.trim();
467
+ if (key === '') return `${apiKey.service} API key cannot be empty`;
468
+ return true;
469
+ }
470
+ }
471
+ ]);
472
+
473
+ const storeAnswer = await inquirer.prompt([
474
+ {
475
+ type: 'confirm',
476
+ name: 'store',
477
+ message: `Store this API key locally for future use?`,
478
+ default: true
479
+ }
480
+ ]);
481
+
482
+ missingKeys[apiKey.service.toLowerCase()] = keyAnswer.key;
483
+
484
+ if (storeAnswer.store) {
485
+ try {
486
+ const scriptPath = path.join(__dirname, '..', 'python', 'gitarsenal_keys.py');
487
+ const pythonExecutable = process.env.PYTHON_EXECUTABLE || 'python';
488
+
489
+ await new Promise((resolve, reject) => {
490
+ const pythonProcess = spawn(pythonExecutable, [
491
+ scriptPath,
492
+ 'add',
493
+ '--service', apiKey.service.toLowerCase(),
494
+ '--key', keyAnswer.key
495
+ ], { stdio: 'pipe' });
496
+
497
+ pythonProcess.on('close', (code) => {
498
+ if (code === 0) {
499
+ console.log(chalk.green(`✅ ${apiKey.service} API key stored successfully`));
500
+ resolve();
501
+ } else {
502
+ console.log(chalk.yellow(`⚠️ Could not store ${apiKey.service} API key locally`));
503
+ resolve();
504
+ }
505
+ });
506
+ });
507
+ } catch (error) {
508
+ console.log(chalk.yellow(`⚠️ Could not store ${apiKey.service} API key: ${error.message}`));
509
+ }
510
+ }
511
+ }
512
+ }
513
+ }
514
+ }
515
+
516
+ // Check if all critical keys are handled
517
+ if (criticalMissingKeys.length === 0) {
518
+ console.log(chalk.green('✅ All critical API keys are available'));
519
+ }
405
520
 
406
521
  return missingKeys;
407
522
  }
@@ -509,22 +624,12 @@ async function fetchFullSetupAndRecs(repoUrl, storedCredentials = null) {
509
624
  preview: false // This is a full analysis, not preview
510
625
  };
511
626
 
512
- // console.log(chalk.gray('🐛 DEBUG: Payload being sent to API:'));
513
- // console.log(chalk.gray(' - Repo URL:', repoUrl));
514
- // console.log(chalk.gray(' - GitIngest Data Summary Length:', payload.gitingestData.repository_analysis.summary.length));
515
- // console.log(chalk.gray(' - GitIngest Data Tree Length:', payload.gitingestData.repository_analysis.tree.length));
516
- // console.log(chalk.gray(' - GitIngest Data Content Length:', payload.gitingestData.repository_analysis.content_preview.length));
517
- // console.log(chalk.gray(' - Detected Language:', payload.gitingestData.system_info.detected_language));
518
- // console.log(chalk.gray(' - Detected Technologies:', payload.gitingestData.system_info.detected_technologies.join(', ')));
519
- // console.log(chalk.gray(' - Stored Credentials:', storedCredentials ? Object.keys(storedCredentials).length + ' keys' : 'none'));
520
- // console.log(chalk.gray(' - Preview Mode:', payload.preview));
521
-
522
627
  let data = null;
523
628
  let lastErrorText = '';
524
629
 
525
630
  for (const url of endpoints) {
526
631
  try {
527
- spinner.text = `Analyzing repository: ${url}`;
632
+ spinner.text = `Analyzing repository...`;
528
633
  const res = await fetch(url, {
529
634
  method: 'POST',
530
635
  headers: { 'Content-Type': 'application/json', 'User-Agent': 'GitArsenal-CLI/1.0' },