gitarsenal-cli 1.9.40 → 1.9.41

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-11T12:44:14.984Z","packages":["modal","gitingest","requests","anthropic"],"uv_version":"uv 0.8.4 (Homebrew 2025-07-30)"}
1
+ {"created":"2025-08-11T14:42:03.859Z","packages":["modal","gitingest","requests","anthropic"],"uv_version":"uv 0.8.4 (Homebrew 2025-07-30)"}
package/bin/gitarsenal.js CHANGED
@@ -41,7 +41,6 @@ function activateVirtualEnvironment() {
41
41
  if (fs.existsSync(statusFile)) {
42
42
  try {
43
43
  const status = JSON.parse(fs.readFileSync(statusFile, 'utf8'));
44
- // console.log(chalk.gray(`✅ Virtual environment created: ${status.created}`));
45
44
  console.log(chalk.gray(`📦 Packages: ${status.packages.join(', ')}`));
46
45
  } catch (error) {
47
46
  console.log(chalk.gray('✅ Virtual environment found'));
@@ -311,7 +310,7 @@ function printGpuTorchCudaSummary(result) {
311
310
  // Full fetch to get both setup commands and recommendations in one request
312
311
  async function fetchFullSetupAndRecs(repoUrl) {
313
312
  const envUrl = process.env.GITARSENAL_API_URL;
314
- const endpoints = envUrl ? [envUrl] : ['https://www.gitarsenal.dev/api/gitingest-setup-commands'];
313
+ const endpoints = envUrl ? [envUrl] : ['https://www.gitarsenal.dev/api/best_gpu'];
315
314
  const payload = {
316
315
  repoUrl,
317
316
  gitingestData: {
@@ -399,7 +398,7 @@ async function sendUserData(userId, userName, userEmail) {
399
398
  webhookUrl = process.env.GITARSENAL_WEBHOOK_URL;
400
399
  }
401
400
 
402
- console.log(chalk.gray(`📡 Sending to: ${webhookUrl}`));
401
+ // console.log(chalk.gray(`📡 Sending to: ${webhookUrl}`));
403
402
  console.log(chalk.gray(`📦 Data: ${data}`));
404
403
 
405
404
  const urlObj = new URL(webhookUrl);
@@ -426,8 +425,6 @@ async function sendUserData(userId, userName, userEmail) {
426
425
  responseData += chunk;
427
426
  });
428
427
  res.on('end', () => {
429
- console.log(chalk.gray(`📊 Response status: ${res.statusCode}`));
430
- console.log(chalk.gray(`📄 Response: ${responseData}`));
431
428
 
432
429
  if (res.statusCode >= 200 && res.statusCode < 300) {
433
430
  console.log(chalk.green('✅ User registered on GitArsenal dashboard'));
@@ -477,6 +474,35 @@ async function collectUserCredentials(options) {
477
474
  try {
478
475
  const config = JSON.parse(fs.readFileSync(userConfigPath, 'utf8'));
479
476
  if (config.userId && config.userName && config.userEmail) {
477
+ // Check if the email is a fake one (contains @example.com)
478
+ if (config.userEmail.includes('@example.com')) {
479
+ console.log(chalk.yellow('⚠️ Detected placeholder email address. Please update your credentials.'));
480
+ console.log(chalk.gray('We need your real email address for proper registration.'));
481
+
482
+ // Prompt for real email address
483
+ const emailUpdate = await inquirer.prompt([
484
+ {
485
+ type: 'input',
486
+ name: 'userEmail',
487
+ message: 'Enter your real email address:',
488
+ validate: (input) => {
489
+ const email = input.trim();
490
+ if (email === '') return 'Email address is required';
491
+ if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
492
+ return 'Please enter a valid email address (e.g., user@example.com)';
493
+ }
494
+ return true;
495
+ }
496
+ }
497
+ ]);
498
+
499
+ // Update the config with real email
500
+ config.userEmail = emailUpdate.userEmail;
501
+ config.updatedAt = new Date().toISOString();
502
+ fs.writeFileSync(userConfigPath, JSON.stringify(config, null, 2));
503
+ console.log(chalk.green('✅ Email address updated successfully!'));
504
+ }
505
+
480
506
  userId = config.userId;
481
507
  userName = config.userName;
482
508
  userEmail = config.userEmail;
@@ -570,9 +596,34 @@ async function collectUserCredentials(options) {
570
596
  const credentials = await inquirer.prompt([
571
597
  {
572
598
  type: 'input',
573
- name: 'userIdentifier',
574
- message: 'Enter your username or email:',
575
- validate: (input) => input.trim() !== '' ? true : 'Username/email is required'
599
+ name: 'userId',
600
+ message: 'Enter your username:',
601
+ validate: (input) => {
602
+ const username = input.trim();
603
+ if (username === '') return 'Username is required';
604
+ if (username.length < 3) return 'Username must be at least 3 characters';
605
+ if (!/^[a-zA-Z0-9_-]+$/.test(username)) return 'Username can only contain letters, numbers, _ and -';
606
+ return true;
607
+ }
608
+ },
609
+ {
610
+ type: 'input',
611
+ name: 'userEmail',
612
+ message: 'Enter your email address:',
613
+ validate: (input) => {
614
+ const email = input.trim();
615
+ if (email === '') return 'Email address is required';
616
+ if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
617
+ return 'Please enter a valid email address (e.g., user@example.com)';
618
+ }
619
+ return true;
620
+ }
621
+ },
622
+ {
623
+ type: 'input',
624
+ name: 'userName',
625
+ message: 'Enter your full name:',
626
+ validate: (input) => input.trim() !== '' ? true : 'Name is required'
576
627
  },
577
628
  {
578
629
  type: 'password',
@@ -582,12 +633,9 @@ async function collectUserCredentials(options) {
582
633
  }
583
634
  ]);
584
635
 
585
- // For now, we'll simulate successful login
586
- // In a real implementation, you'd validate against a user database
587
- const identifier = credentials.userIdentifier;
588
- userId = identifier.includes('@') ? identifier.split('@')[0] : identifier;
589
- userName = `User ${userId}`; // Would be fetched from database
590
- userEmail = identifier.includes('@') ? identifier : `${identifier}@example.com`;
636
+ userId = credentials.userId;
637
+ userName = credentials.userName;
638
+ userEmail = credentials.userEmail;
591
639
 
592
640
  console.log(chalk.green('✅ Login successful!'));
593
641
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gitarsenal-cli",
3
- "version": "1.9.40",
3
+ "version": "1.9.41",
4
4
  "description": "CLI tool for creating Modal sandboxes with GitHub repositories",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -253,6 +253,24 @@ class CommandListManager:
253
253
 
254
254
  print("="*60)
255
255
 
256
+ def print_all_commands(self):
257
+ """Print all commands in the list for debugging/transparency."""
258
+ if not self.commands:
259
+ print("📋 No commands in the list")
260
+ return
261
+
262
+ print("\n" + "="*80)
263
+ print("📋 ALL SETUP COMMANDS")
264
+ print("="*80)
265
+ for i, cmd in enumerate(self.commands):
266
+ status_icon = {
267
+ 'pending': '⏳',
268
+ 'success': '✅',
269
+ 'failed': '❌'
270
+ }.get(cmd['status'], '❓')
271
+ print(f" {i+1:2d}. {status_icon} {cmd['command']}")
272
+ print("="*80 + "\n")
273
+
256
274
  def get_failed_commands_for_llm(self):
257
275
  """Get failed commands for LLM analysis."""
258
276
  failed_commands = []
@@ -398,6 +398,14 @@ def create_modal_ssh_container(gpu_type, repo_url=None, repo_name=None, setup_co
398
398
  processed_commands = preprocess_commands_with_llm(setup_commands, stored_credentials, api_key)
399
399
  print(f"⚙️ Running {len(processed_commands)} preprocessed setup commands with dynamic command list...")
400
400
 
401
+ # Display all setup commands that will be executed
402
+ print("\n" + "="*80)
403
+ print("📋 SETUP COMMANDS TO BE EXECUTED")
404
+ print("="*80)
405
+ for i, cmd in enumerate(processed_commands, 1):
406
+ print(f" {i:2d}. {cmd}")
407
+ print("="*80 + "\n")
408
+
401
409
  # Create command list manager with processed commands
402
410
  cmd_manager = CommandListManager(processed_commands)
403
411