gitarsenal-cli 1.9.7 → 1.9.8

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-03T18:14:08.672Z","packages":["modal","gitingest","requests"],"uv_version":"uv 0.8.4 (e176e1714 2025-07-30)"}
1
+ {"created":"2025-08-04T06:53:34.568Z","packages":["modal","gitingest","requests"],"uv_version":"uv 0.8.4 (e176e1714 2025-07-30)"}
package/bin/gitarsenal.js CHANGED
@@ -105,22 +105,19 @@ function activateVirtualEnvironment() {
105
105
  }
106
106
 
107
107
  // Function to send user data to web application
108
- async function sendUserData(userId, userName, command, repoUrl = null, success = true, error = null) {
108
+ async function sendUserData(userId, userName) {
109
109
  try {
110
+ console.log(chalk.blue(`šŸ”— Attempting to register user: ${userName} (${userId})`));
111
+
110
112
  const userData = {
111
- userId,
112
- userName,
113
- command,
114
- repoUrl,
115
- success,
116
- error,
117
- timestamp: new Date().toISOString()
113
+ id: userId,
114
+ name: userName
118
115
  };
119
116
 
120
117
  const data = JSON.stringify(userData);
121
118
 
122
119
  // Get webhook URL from config or use default
123
- let webhookUrl = 'https://gitarsenal.dev/api/users/cli-log';
120
+ let webhookUrl = 'https://www.gitarsenal.dev/api/users';
124
121
  const configPath = path.join(__dirname, '..', 'config.json');
125
122
  if (fs.existsSync(configPath)) {
126
123
  try {
@@ -129,10 +126,13 @@ async function sendUserData(userId, userName, command, repoUrl = null, success =
129
126
  webhookUrl = config.webhookUrl;
130
127
  }
131
128
  } catch (error) {
132
- // Use default URL if config can't be read
129
+ console.log(chalk.yellow('āš ļø Could not read config file, using default URL'));
133
130
  }
134
131
  }
135
132
 
133
+ console.log(chalk.gray(`šŸ“” Sending to: ${webhookUrl}`));
134
+ console.log(chalk.gray(`šŸ“¦ Data: ${data}`));
135
+
136
136
  const urlObj = new URL(webhookUrl);
137
137
  const options = {
138
138
  hostname: urlObj.hostname,
@@ -141,7 +141,8 @@ async function sendUserData(userId, userName, command, repoUrl = null, success =
141
141
  method: 'POST',
142
142
  headers: {
143
143
  'Content-Type': 'application/json',
144
- 'Content-Length': Buffer.byteLength(data)
144
+ 'Content-Length': Buffer.byteLength(data),
145
+ 'User-Agent': 'GitArsenal-CLI/1.0'
145
146
  }
146
147
  };
147
148
 
@@ -153,18 +154,31 @@ async function sendUserData(userId, userName, command, repoUrl = null, success =
153
154
  responseData += chunk;
154
155
  });
155
156
  res.on('end', () => {
157
+ console.log(chalk.gray(`šŸ“Š Response status: ${res.statusCode}`));
158
+ console.log(chalk.gray(`šŸ“„ Response: ${responseData}`));
159
+
156
160
  if (res.statusCode >= 200 && res.statusCode < 300) {
157
- console.log(chalk.green('āœ… User activity logged to GitArsenal dashboard'));
161
+ console.log(chalk.green('āœ… User registered on GitArsenal dashboard'));
162
+ resolve(responseData);
163
+ } else if (res.statusCode === 409) {
164
+ console.log(chalk.green('āœ… User already exists on GitArsenal dashboard'));
158
165
  resolve(responseData);
159
166
  } else {
160
- console.log(chalk.yellow('āš ļø Failed to log user activity (non-critical)'));
167
+ console.log(chalk.yellow(`āš ļø Failed to register user (status: ${res.statusCode})`));
168
+ console.log(chalk.gray(`Response: ${responseData}`));
161
169
  resolve(responseData);
162
170
  }
163
171
  });
164
172
  });
165
173
 
166
174
  req.on('error', (err) => {
167
- console.log(chalk.yellow('āš ļø Could not connect to GitArsenal dashboard (non-critical)'));
175
+ console.log(chalk.red(`āŒ Could not connect to GitArsenal dashboard: ${err.message}`));
176
+ resolve();
177
+ });
178
+
179
+ req.setTimeout(10000, () => {
180
+ console.log(chalk.red('āŒ Request timeout - could not connect to dashboard'));
181
+ req.destroy();
168
182
  resolve();
169
183
  });
170
184
 
@@ -172,7 +186,7 @@ async function sendUserData(userId, userName, command, repoUrl = null, success =
172
186
  req.end();
173
187
  });
174
188
  } catch (error) {
175
- console.log(chalk.yellow('āš ļø Error logging user activity (non-critical)'));
189
+ console.log(chalk.red(`āŒ Error registering user: ${error.message}`));
176
190
  }
177
191
  }
178
192
 
@@ -233,7 +247,7 @@ async function collectUserCredentials(options) {
233
247
  const config = {
234
248
  userId,
235
249
  userName,
236
- webhookUrl: 'https://gitarsenal.dev/api/users/cli-log'
250
+ webhookUrl: 'https://www.gitarsenal.dev/api/users'
237
251
  };
238
252
  fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
239
253
  console.log(chalk.green('āœ… Credentials saved to config file'));
@@ -360,14 +374,17 @@ async function runContainerCommand(options) {
360
374
  const userCredentials = await collectUserCredentials(options);
361
375
  const { userId, userName } = userCredentials;
362
376
 
377
+ // Register user on dashboard immediately after collecting credentials
378
+ console.log(chalk.blue('\nšŸ“ Registering user on GitArsenal dashboard...'));
379
+ // Note: User data will be sent by the Python script after authentication
380
+ // await sendUserData(userId, userName);
381
+
363
382
  // Check for required dependencies
364
383
  const spinner = ora('Checking dependencies...').start();
365
384
  const dependenciesOk = await checkDependencies();
366
385
 
367
386
  if (!dependenciesOk) {
368
387
  spinner.fail('Missing dependencies. Please install them and try again.');
369
- // Log failed dependency check
370
- await sendUserData(userId, userName, 'dependency-check', null, false, 'Missing dependencies');
371
388
  process.exit(1);
372
389
  }
373
390
  spinner.succeed('Dependencies checked');
@@ -501,7 +518,6 @@ async function runContainerCommand(options) {
501
518
 
502
519
  // Log command start
503
520
  const commandString = `gitarsenal container ${repoUrl ? `--repo ${repoUrl}` : ''} ${gpuType ? `--gpu ${gpuType}` : ''}`;
504
- await sendUserData(userId, userName, commandString, repoUrl, true);
505
521
 
506
522
  // Run the container
507
523
  try {
@@ -513,12 +529,7 @@ async function runContainerCommand(options) {
513
529
  useApi
514
530
  });
515
531
 
516
- // Log successful completion
517
- await sendUserData(userId, userName, commandString, repoUrl, true);
518
-
519
532
  } catch (containerError) {
520
- // Log error
521
- await sendUserData(userId, userName, commandString, repoUrl, false, containerError.message);
522
533
  throw containerError;
523
534
  }
524
535
 
@@ -534,6 +545,11 @@ async function handleKeysAdd(options) {
534
545
  const userCredentials = await collectUserCredentials(options);
535
546
  const { userId, userName } = userCredentials;
536
547
 
548
+ // Register user on dashboard
549
+ console.log(chalk.blue('\nšŸ“ Registering user on GitArsenal dashboard...'));
550
+ // Note: User data will be sent by the Python script after authentication
551
+ // await sendUserData(userId, userName);
552
+
537
553
  const spinner = ora('Adding API key...').start();
538
554
 
539
555
  let service = options.service;
@@ -588,12 +604,8 @@ async function handleKeysAdd(options) {
588
604
  pythonProcess.on('close', async (code) => {
589
605
  if (code === 0) {
590
606
  spinner.succeed(`API key for ${service} added successfully`);
591
- // Log successful key addition
592
- await sendUserData(userId, userName, `gitarsenal keys add --service ${service}`, null, true);
593
607
  } else {
594
608
  spinner.fail(`Failed to add API key: ${output}`);
595
- // Log failed key addition
596
- await sendUserData(userId, userName, `gitarsenal keys add --service ${service}`, null, false, output);
597
609
  }
598
610
  });
599
611
 
@@ -609,6 +621,11 @@ async function handleKeysList() {
609
621
  const userCredentials = await collectUserCredentials({});
610
622
  const { userId, userName } = userCredentials;
611
623
 
624
+ // Register user on dashboard
625
+ console.log(chalk.blue('\nšŸ“ Registering user on GitArsenal dashboard...'));
626
+ // Note: User data will be sent by the Python script after authentication
627
+ // await sendUserData(userId, userName);
628
+
612
629
  const spinner = ora('Fetching API keys...').start();
613
630
 
614
631
  // Call Python script to list keys
@@ -623,10 +640,8 @@ async function handleKeysList() {
623
640
  pythonProcess.on('close', async (code) => {
624
641
  if (code !== 0) {
625
642
  spinner.fail('Failed to list API keys');
626
- await sendUserData(userId, userName, 'gitarsenal keys list', null, false, 'Failed to list API keys');
627
643
  } else {
628
644
  spinner.stop();
629
- await sendUserData(userId, userName, 'gitarsenal keys list', null, true);
630
645
  }
631
646
  });
632
647
 
@@ -642,6 +657,11 @@ async function handleKeysView(options) {
642
657
  const userCredentials = await collectUserCredentials(options);
643
658
  const { userId, userName } = userCredentials;
644
659
 
660
+ // Register user on dashboard
661
+ console.log(chalk.blue('\nšŸ“ Registering user on GitArsenal dashboard...'));
662
+ // Note: User data will be sent by the Python script after authentication
663
+ // await sendUserData(userId, userName);
664
+
645
665
  const spinner = ora('Viewing API key...').start();
646
666
 
647
667
  let service = options.service;
@@ -672,10 +692,8 @@ async function handleKeysView(options) {
672
692
  pythonProcess.on('close', async (code) => {
673
693
  if (code !== 0) {
674
694
  spinner.fail(`Failed to view API key for ${service}`);
675
- await sendUserData(userId, userName, `gitarsenal keys view --service ${service}`, null, false, `Failed to view API key for ${service}`);
676
695
  } else {
677
696
  spinner.stop();
678
- await sendUserData(userId, userName, `gitarsenal keys view --service ${service}`, null, true);
679
697
  }
680
698
  });
681
699
 
@@ -691,6 +709,11 @@ async function handleKeysDelete(options) {
691
709
  const userCredentials = await collectUserCredentials(options);
692
710
  const { userId, userName } = userCredentials;
693
711
 
712
+ // Register user on dashboard
713
+ console.log(chalk.blue('\nšŸ“ Registering user on GitArsenal dashboard...'));
714
+ // Note: User data will be sent by the Python script after authentication
715
+ // await sendUserData(userId, userName);
716
+
694
717
  const spinner = ora('Deleting API key...').start();
695
718
 
696
719
  let service = options.service;
@@ -721,7 +744,6 @@ async function handleKeysDelete(options) {
721
744
 
722
745
  if (!confirmAnswer.confirm) {
723
746
  console.log(chalk.yellow('Operation cancelled by user.'));
724
- await sendUserData(userId, userName, `gitarsenal keys delete --service ${service}`, null, false, 'Operation cancelled by user');
725
747
  return;
726
748
  }
727
749
 
@@ -749,10 +771,8 @@ async function handleKeysDelete(options) {
749
771
  pythonProcess.on('close', async (code) => {
750
772
  if (code === 0) {
751
773
  spinner.succeed(`API key for ${service} deleted successfully`);
752
- await sendUserData(userId, userName, `gitarsenal keys delete --service ${service}`, null, true);
753
774
  } else {
754
775
  spinner.fail(`Failed to delete API key: ${output}`);
755
- await sendUserData(userId, userName, `gitarsenal keys delete --service ${service}`, null, false, output);
756
776
  }
757
777
  });
758
778
 
package/config.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "userId": "rs545837",
3
3
  "userName": "Rohan Sharma",
4
- "webhookUrl": "https://gitarsenal.dev/api/users/cli-log"
4
+ "webhookUrl": "https://www.gitarsenal.dev/api/users"
5
5
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gitarsenal-cli",
3
- "version": "1.9.7",
3
+ "version": "1.9.8",
4
4
  "description": "CLI tool for creating Modal sandboxes with GitHub repositories",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -203,11 +203,51 @@ class AuthManager:
203
203
  print(f"Username: {username}")
204
204
  print(f"Email: {email}")
205
205
  print("\nYou can now login with your credentials.")
206
+
207
+ # Send user data to web application
208
+ self.send_user_data_to_webapp(username, email)
209
+
206
210
  return True
207
211
  else:
208
212
  print("āŒ Failed to save registration data.")
209
213
  return False
210
214
 
215
+ def send_user_data_to_webapp(self, username: str, email: str):
216
+ """Send user data to the web application for tracking"""
217
+ try:
218
+ # Get webhook URL from environment or use default
219
+ webhook_url = os.getenv("GITARSENAL_WEBHOOK_URL", "https://www.gitarsenal.dev/api/users")
220
+
221
+ user_data = {
222
+ "id": username, # Use username as ID for consistency
223
+ "name": username # Use username as name for now
224
+ }
225
+
226
+ print(f"šŸ”— Sending user data to web application: {username}")
227
+
228
+ response = requests.post(
229
+ webhook_url,
230
+ json=user_data,
231
+ headers={
232
+ 'Content-Type': 'application/json',
233
+ 'User-Agent': 'GitArsenal-CLI/1.0'
234
+ },
235
+ timeout=10
236
+ )
237
+
238
+ if response.status_code >= 200 and response.status_code < 300:
239
+ print("āœ… User data sent to web application successfully")
240
+ elif response.status_code == 409:
241
+ print("āœ… User already exists in web application")
242
+ else:
243
+ print(f"āš ļø Failed to send user data (status: {response.status_code})")
244
+ print(f"Response: {response.text}")
245
+
246
+ except requests.exceptions.RequestException as e:
247
+ print(f"āš ļø Failed to send user data to web application: {e}")
248
+ except Exception as e:
249
+ print(f"āš ļø Error sending user data: {e}")
250
+
211
251
  def login_user(self, username: str, password: str) -> bool:
212
252
  """Login a user"""
213
253
  print("\n" + "="*60)
@@ -249,6 +289,10 @@ class AuthManager:
249
289
  if self.save_session(session_data):
250
290
  print("āœ… Login successful!")
251
291
  print(f"Welcome back, {username}!")
292
+
293
+ # Send user data to web application
294
+ self.send_user_data_to_webapp(username, user_data.get('email', ''))
295
+
252
296
  return True
253
297
  else:
254
298
  print("āŒ Failed to create session.")