gitarsenal-cli 1.6.13 → 1.6.15

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/lib/sandbox.js CHANGED
@@ -110,8 +110,8 @@ async function runContainer(options) {
110
110
  // Log the command being executed
111
111
  console.log(chalk.dim(`\nExecuting: python ${args.join(' ')}`));
112
112
 
113
- // Start the spinner
114
- const spinner = ora('Launching container...').start();
113
+ // Run the Python script without spinner to avoid terminal interference
114
+ console.log(chalk.dim('Launching container...'));
115
115
 
116
116
  try {
117
117
  // Run the Python script
@@ -123,22 +123,22 @@ async function runContainer(options) {
123
123
  return new Promise((resolve, reject) => {
124
124
  pythonProcess.on('close', (code) => {
125
125
  if (code === 0) {
126
- spinner.succeed('Container launched successfully');
126
+ console.log(chalk.green('Container launched successfully'));
127
127
  resolve();
128
128
  } else {
129
- spinner.fail(`Container launch failed with exit code ${code}`);
129
+ console.log(chalk.red(`❌ Container launch failed with exit code ${code}`));
130
130
  reject(new Error(`Process exited with code ${code}`));
131
131
  }
132
132
  });
133
133
 
134
134
  // Handle process errors
135
135
  pythonProcess.on('error', (error) => {
136
- spinner.fail(`Failed to start Python process: ${error.message}`);
136
+ console.log(chalk.red(`❌ Failed to start Python process: ${error.message}`));
137
137
  reject(error);
138
138
  });
139
139
  });
140
140
  } catch (error) {
141
- spinner.fail(`Error launching container: ${error.message}`);
141
+ console.log(chalk.red(`❌ Error launching container: ${error.message}`));
142
142
  throw error;
143
143
  }
144
144
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gitarsenal-cli",
3
- "version": "1.6.13",
3
+ "version": "1.6.15",
4
4
  "description": "CLI tool for creating Modal sandboxes with GitHub repositories",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -64,15 +64,15 @@ except (ImportError, ValueError) as e:
64
64
  modal_dir = Path.home() / ".modal"
65
65
  modal_dir.mkdir(exist_ok=True)
66
66
  token_file = modal_dir / "token.json"
67
- with open(token_file, 'w') as f:
68
- f.write(f'{{"token_id": "{TOKEN_ID}", "token_secret": "{TOKEN_SECRET}"}}')
69
- print(f"✅ Created token file at {token_file}")
67
+ # with open(token_file, 'w') as f:
68
+ # f.write(f'{{"token_id": "{TOKEN_ID}", "token_secret": "{TOKEN_SECRET}"}}')
69
+ # print(f"✅ Created token file at {token_file}")
70
70
 
71
71
  # Create .modalconfig file
72
72
  modalconfig_file = Path.home() / ".modalconfig"
73
- with open(modalconfig_file, 'w') as f:
74
- f.write(f"token_id = {TOKEN_ID}\n")
75
- f.write(f"token_secret = {TOKEN_SECRET}\n")
73
+ # with open(modalconfig_file, 'w') as f:
74
+ # f.write(f"token_id = {TOKEN_ID}\n")
75
+ # f.write(f"token_secret = {TOKEN_SECRET}\n")
76
76
  print(f"✅ Created .modalconfig file at {modalconfig_file}")
77
77
 
78
78
  print("\n✅ Done fixing Modal token. Please try your command again.")
@@ -19,23 +19,13 @@ import inspect
19
19
  from pathlib import Path
20
20
  import time
21
21
 
22
- # Try to get tokens from the proxy server
23
- try:
24
- # First, try to import the fetch_modal_tokens module
25
- from fetch_modal_tokens import get_tokens
26
- TOKEN_ID, TOKEN_SECRET = get_tokens()
27
- # print(f"✅ Using tokens from proxy server or defaults")
28
- except ImportError:
29
- # If the module is not available, use hardcoded tokens
30
- # print(f"⚠️ Using default tokens")
31
- print("")
32
22
 
33
23
  # print("🔧 Advanced Modal Token Fixer")
34
24
 
35
25
  # Approach 1: Set environment variables
36
26
  # print("\n📋 Approach 1: Setting environment variables")
37
- os.environ["MODAL_TOKEN_ID"] = TOKEN_ID
38
- os.environ["MODAL_TOKEN_SECRET"] = TOKEN_SECRET
27
+ # os.environ["MODAL_TOKEN_ID"] = TOKEN_ID
28
+ # os.environ["MODAL_TOKEN_SECRET"] = TOKEN_SECRET
39
29
  # print(f"✅ Set MODAL_TOKEN_ID = [HIDDEN]")
40
30
  # print(f"✅ Set MODAL_TOKEN_SECRET = [HIDDEN]")
41
31
 
@@ -2364,9 +2364,39 @@ def get_setup_commands_from_gitingest(repo_url):
2364
2364
  api_keys = result.get("requiredApiKeys", [])
2365
2365
  if api_keys:
2366
2366
  print(f"\n🔑 Required API Keys ({len(api_keys)}):")
2367
+ # Load stored GitArsenal credentials
2368
+ stored_credentials = {}
2369
+ try:
2370
+ credentials_file = Path.home() / ".gitarsenal" / "credentials.json"
2371
+ if credentials_file.exists():
2372
+ with open(credentials_file, 'r') as f:
2373
+ stored_credentials = json.load(f)
2374
+ print(f"📋 Found {len(stored_credentials)} stored GitArsenal credentials")
2375
+ else:
2376
+ print("📋 No stored GitArsenal credentials found")
2377
+ except Exception as e:
2378
+ print(f"⚠️ Error loading stored credentials: {e}")
2379
+
2380
+ # Identify missing required API keys
2381
+ missing_required_keys = []
2382
+ available_keys = []
2383
+
2367
2384
  for i, api_key in enumerate(api_keys, 1):
2368
- status = "🔴 Required" if api_key.get("required", False) else "🟡 Optional"
2369
- print(f" {i}. {api_key.get('name', 'Unknown')} - {status}")
2385
+ key_name = api_key.get('name', 'Unknown')
2386
+ is_required = api_key.get("required", False)
2387
+ has_stored_key = key_name in stored_credentials
2388
+
2389
+ if is_required:
2390
+ if has_stored_key:
2391
+ status = "✅ Required (Available)"
2392
+ available_keys.append(key_name)
2393
+ else:
2394
+ status = "🔴 Required (Missing)"
2395
+ missing_required_keys.append(api_key)
2396
+ else:
2397
+ status = "🟡 Optional"
2398
+
2399
+ print(f" {i}. {key_name} - {status}")
2370
2400
  print(f" Service: {api_key.get('service', 'Unknown')}")
2371
2401
  print(f" Description: {api_key.get('description', 'No description')}")
2372
2402
  if api_key.get('example'):
@@ -2374,6 +2404,67 @@ def get_setup_commands_from_gitingest(repo_url):
2374
2404
  if api_key.get('documentation_url'):
2375
2405
  print(f" Docs: {api_key.get('documentation_url')}")
2376
2406
  print()
2407
+
2408
+ # Prompt for missing required API keys
2409
+ if missing_required_keys:
2410
+ print("🔧 Setting up missing required API keys...")
2411
+ print("Press Enter to continue or Ctrl+C to skip...")
2412
+
2413
+ for api_key in missing_required_keys:
2414
+ key_name = api_key.get('name', 'Unknown')
2415
+ service = api_key.get('service', 'Unknown')
2416
+ description = api_key.get('description', 'No description')
2417
+ example = api_key.get('example', '')
2418
+ docs_url = api_key.get('documentation_url', '')
2419
+
2420
+ print(f"\n📝 Setting up {key_name} for {service}:")
2421
+ print(f" Description: {description}")
2422
+ if example:
2423
+ print(f" Example: {example}")
2424
+ if docs_url:
2425
+ print(f" Documentation: {docs_url}")
2426
+
2427
+ # Prompt user for the API key
2428
+ try:
2429
+ import getpass
2430
+ print(f"\nPlease enter your {key_name}:")
2431
+ new_key = getpass.getpass("API Key (hidden): ").strip()
2432
+
2433
+ if new_key:
2434
+ # Save to credentials file
2435
+ credentials_file = Path.home() / ".gitarsenal" / "credentials.json"
2436
+ credentials_file.parent.mkdir(parents=True, exist_ok=True)
2437
+
2438
+ # Load existing credentials
2439
+ if credentials_file.exists():
2440
+ with open(credentials_file, 'r') as f:
2441
+ all_credentials = json.load(f)
2442
+ else:
2443
+ all_credentials = {}
2444
+
2445
+ # Add new key
2446
+ all_credentials[key_name] = new_key
2447
+
2448
+ # Save back to file
2449
+ with open(credentials_file, 'w') as f:
2450
+ json.dump(all_credentials, f, indent=2)
2451
+
2452
+ print(f"✅ {key_name} saved successfully!")
2453
+ available_keys.append(key_name)
2454
+ else:
2455
+ print(f"⚠️ Skipping {key_name} (no input provided)")
2456
+ except KeyboardInterrupt:
2457
+ print(f"\n⚠️ Skipping {key_name} (cancelled by user)")
2458
+ except Exception as e:
2459
+ print(f"❌ Error saving {key_name}: {e}")
2460
+
2461
+ # Show summary
2462
+ if available_keys:
2463
+ print(f"✅ Available API keys: {', '.join(available_keys)}")
2464
+ if missing_required_keys:
2465
+ print(f"⚠️ Missing required keys: {', '.join([k.get('name') for k in missing_required_keys])}")
2466
+ else:
2467
+ print("ℹ️ All required API keys are already available.")
2377
2468
 
2378
2469
  # Display setup complexity if available
2379
2470
  if "setupComplexity" in result:
@@ -2364,9 +2364,39 @@ def get_setup_commands_from_gitingest(repo_url):
2364
2364
  api_keys = result.get("requiredApiKeys", [])
2365
2365
  if api_keys:
2366
2366
  print(f"\n🔑 Required API Keys ({len(api_keys)}):")
2367
+ # Load stored GitArsenal credentials
2368
+ stored_credentials = {}
2369
+ try:
2370
+ credentials_file = Path.home() / ".gitarsenal" / "credentials.json"
2371
+ if credentials_file.exists():
2372
+ with open(credentials_file, 'r') as f:
2373
+ stored_credentials = json.load(f)
2374
+ print(f"📋 Found {len(stored_credentials)} stored GitArsenal credentials")
2375
+ else:
2376
+ print("📋 No stored GitArsenal credentials found")
2377
+ except Exception as e:
2378
+ print(f"⚠️ Error loading stored credentials: {e}")
2379
+
2380
+ # Identify missing required API keys
2381
+ missing_required_keys = []
2382
+ available_keys = []
2383
+
2367
2384
  for i, api_key in enumerate(api_keys, 1):
2368
- status = "🔴 Required" if api_key.get("required", False) else "🟡 Optional"
2369
- print(f" {i}. {api_key.get('name', 'Unknown')} - {status}")
2385
+ key_name = api_key.get('name', 'Unknown')
2386
+ is_required = api_key.get("required", False)
2387
+ has_stored_key = key_name in stored_credentials
2388
+
2389
+ if is_required:
2390
+ if has_stored_key:
2391
+ status = "✅ Required (Available)"
2392
+ available_keys.append(key_name)
2393
+ else:
2394
+ status = "🔴 Required (Missing)"
2395
+ missing_required_keys.append(api_key)
2396
+ else:
2397
+ status = "🟡 Optional"
2398
+
2399
+ print(f" {i}. {key_name} - {status}")
2370
2400
  print(f" Service: {api_key.get('service', 'Unknown')}")
2371
2401
  print(f" Description: {api_key.get('description', 'No description')}")
2372
2402
  if api_key.get('example'):
@@ -2374,6 +2404,67 @@ def get_setup_commands_from_gitingest(repo_url):
2374
2404
  if api_key.get('documentation_url'):
2375
2405
  print(f" Docs: {api_key.get('documentation_url')}")
2376
2406
  print()
2407
+
2408
+ # Prompt for missing required API keys
2409
+ if missing_required_keys:
2410
+ print("🔧 Setting up missing required API keys...")
2411
+ print("Press Enter to continue or Ctrl+C to skip...")
2412
+
2413
+ for api_key in missing_required_keys:
2414
+ key_name = api_key.get('name', 'Unknown')
2415
+ service = api_key.get('service', 'Unknown')
2416
+ description = api_key.get('description', 'No description')
2417
+ example = api_key.get('example', '')
2418
+ docs_url = api_key.get('documentation_url', '')
2419
+
2420
+ print(f"\n📝 Setting up {key_name} for {service}:")
2421
+ print(f" Description: {description}")
2422
+ if example:
2423
+ print(f" Example: {example}")
2424
+ if docs_url:
2425
+ print(f" Documentation: {docs_url}")
2426
+
2427
+ # Prompt user for the API key
2428
+ try:
2429
+ import getpass
2430
+ print(f"\nPlease enter your {key_name}:")
2431
+ new_key = getpass.getpass("API Key (hidden): ").strip()
2432
+
2433
+ if new_key:
2434
+ # Save to credentials file
2435
+ credentials_file = Path.home() / ".gitarsenal" / "credentials.json"
2436
+ credentials_file.parent.mkdir(parents=True, exist_ok=True)
2437
+
2438
+ # Load existing credentials
2439
+ if credentials_file.exists():
2440
+ with open(credentials_file, 'r') as f:
2441
+ all_credentials = json.load(f)
2442
+ else:
2443
+ all_credentials = {}
2444
+
2445
+ # Add new key
2446
+ all_credentials[key_name] = new_key
2447
+
2448
+ # Save back to file
2449
+ with open(credentials_file, 'w') as f:
2450
+ json.dump(all_credentials, f, indent=2)
2451
+
2452
+ print(f"✅ {key_name} saved successfully!")
2453
+ available_keys.append(key_name)
2454
+ else:
2455
+ print(f"⚠️ Skipping {key_name} (no input provided)")
2456
+ except KeyboardInterrupt:
2457
+ print(f"\n⚠️ Skipping {key_name} (cancelled by user)")
2458
+ except Exception as e:
2459
+ print(f"❌ Error saving {key_name}: {e}")
2460
+
2461
+ # Show summary
2462
+ if available_keys:
2463
+ print(f"✅ Available API keys: {', '.join(available_keys)}")
2464
+ if missing_required_keys:
2465
+ print(f"⚠️ Missing required keys: {', '.join([k.get('name') for k in missing_required_keys])}")
2466
+ else:
2467
+ print("ℹ️ All required API keys are already available.")
2377
2468
 
2378
2469
  # Display setup complexity if available
2379
2470
  if "setupComplexity" in result: