agentaudit 3.12.6 → 3.12.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.
Files changed (2) hide show
  1. package/cli.mjs +141 -10
  2. package/package.json +1 -1
package/cli.mjs CHANGED
@@ -15,7 +15,8 @@
15
15
  * activity Your recent audits & findings
16
16
  * search <query> Search packages in registry
17
17
  * model [name|reset] Configure LLM provider + model
18
- * setup Log in to agentaudit.dev (for report uploads)
18
+ * login Sign in with GitHub (opens browser, auto-creates API key)
19
+ * setup Manual login — paste an API key from agentaudit.dev
19
20
  * status Show current config + auth status
20
21
  * profile Your profile — rank, points, audit stats
21
22
  * help [command] Show help
@@ -515,12 +516,12 @@ async function validateApiKey(apiKey) {
515
516
 
516
517
  async function setupCommand() {
517
518
  console.log(` ${c.bold}AgentAudit Setup${c.reset}`);
518
- console.log(` ${c.dim}Link your API key to upload audit reports to agentaudit.dev${c.reset}`);
519
+ console.log(` ${c.dim}Sign in to upload audit reports to agentaudit.dev${c.reset}`);
519
520
  console.log();
520
521
 
521
522
  const existing = loadCredentials();
522
523
  if (existing) {
523
- console.log(` ${icons.safe} Already configured as ${c.bold}${existing.agent_name}${c.reset}`);
524
+ console.log(` ${icons.safe} Already logged in as ${c.bold}${existing.agent_name}${c.reset}`);
524
525
  console.log(` ${c.dim}Key: ${existing.api_key.slice(0, 12)}...${c.reset}`);
525
526
  console.log();
526
527
  const answer = await askQuestion(` Reconfigure? ${c.dim}(y/N)${c.reset} `);
@@ -531,6 +532,25 @@ async function setupCommand() {
531
532
  console.log();
532
533
  }
533
534
 
535
+ // Offer choice: GitHub OAuth (recommended) or manual API key
536
+ console.log(` ${c.bold}How do you want to sign in?${c.reset}`);
537
+ console.log();
538
+ console.log(` ${c.cyan}1${c.reset} Sign in with GitHub ${c.dim}(recommended — opens browser)${c.reset}`);
539
+ console.log(` ${c.cyan}2${c.reset} Paste an API key manually ${c.dim}(from ${REGISTRY_URL}/profile)${c.reset}`);
540
+ console.log();
541
+ const choice = await askQuestion(` Choice ${c.dim}(1/2, default: 1):${c.reset} `);
542
+ console.log();
543
+
544
+ if (choice.trim() === '2') {
545
+ // ── Manual API key flow ──
546
+ await setupManualKey();
547
+ } else {
548
+ // ── GitHub OAuth Device Flow (default) ──
549
+ await loginCommand();
550
+ }
551
+ }
552
+
553
+ async function setupManualKey() {
534
554
  console.log(` ${c.bold}Step 1:${c.reset} Create an API key at ${c.cyan}${REGISTRY_URL}/profile${c.reset}`);
535
555
  console.log(` ${c.dim}Sign in with GitHub, then click "Create API Key".${c.reset}`);
536
556
  console.log();
@@ -555,6 +575,10 @@ async function setupCommand() {
555
575
  return;
556
576
  }
557
577
 
578
+ setupReadyMessage();
579
+ }
580
+
581
+ function setupReadyMessage() {
558
582
  console.log();
559
583
 
560
584
  // ── LLM configuration hint ──
@@ -579,6 +603,112 @@ async function setupCommand() {
579
603
  console.log();
580
604
  }
581
605
 
606
+ // ── Login via GitHub Device Flow ─────────────────────────
607
+
608
+ async function loginCommand() {
609
+ console.log(` ${c.bold}AgentAudit Login${c.reset}`);
610
+ console.log(` ${c.dim}Sign in with GitHub to upload audit reports${c.reset}`);
611
+ console.log();
612
+
613
+ const existing = loadCredentials();
614
+ if (existing) {
615
+ console.log(` ${icons.safe} Already logged in as ${c.bold}${existing.agent_name}${c.reset}`);
616
+ console.log(` ${c.dim}Key: ${existing.api_key.slice(0, 12)}...${c.reset}`);
617
+ console.log();
618
+ const answer = await askQuestion(` Re-authenticate? ${c.dim}(y/N)${c.reset} `);
619
+ if (answer.toLowerCase() !== 'y') {
620
+ console.log(` ${c.dim}Keeping existing login.${c.reset}`);
621
+ return;
622
+ }
623
+ console.log();
624
+ }
625
+
626
+ // Step 1: Start device flow
627
+ process.stdout.write(` Starting login flow...`);
628
+ let deviceData;
629
+ try {
630
+ const res = await fetch(`${REGISTRY_URL}/api/auth/device`, {
631
+ method: 'POST',
632
+ headers: { 'Content-Type': 'application/json' },
633
+ signal: AbortSignal.timeout(10_000),
634
+ });
635
+ deviceData = await res.json();
636
+ if (!res.ok || !deviceData.device_code) {
637
+ console.log(` ${c.red}failed${c.reset}`);
638
+ console.log(` ${c.red}${deviceData.error || 'Could not start login flow'}${c.reset}`);
639
+ console.log(` ${c.dim}Fallback: run ${c.cyan}agentaudit setup${c.dim} to paste an API key manually${c.reset}`);
640
+ return;
641
+ }
642
+ console.log(` ${c.green}ok${c.reset}`);
643
+ } catch (err) {
644
+ console.log(` ${c.red}failed${c.reset}`);
645
+ console.log(` ${c.red}Could not reach ${REGISTRY_URL}${c.reset}`);
646
+ console.log(` ${c.dim}Fallback: run ${c.cyan}agentaudit setup${c.dim} to paste an API key manually${c.reset}`);
647
+ return;
648
+ }
649
+
650
+ // Step 2: Open browser
651
+ const verifyUrl = deviceData.verification_url;
652
+ console.log();
653
+ console.log(` ${c.bold}Open this URL in your browser:${c.reset}`);
654
+ console.log(` ${c.cyan}${verifyUrl}${c.reset}`);
655
+ console.log();
656
+
657
+ // Try to auto-open browser
658
+ try {
659
+ const openCmd = process.platform === 'darwin' ? 'open' : process.platform === 'win32' ? 'start' : 'xdg-open';
660
+ const { exec } = await import('child_process');
661
+ exec(`${openCmd} "${verifyUrl}"`);
662
+ console.log(` ${c.dim}(Browser should open automatically)${c.reset}`);
663
+ } catch {}
664
+
665
+ // Step 3: Poll for authorization
666
+ console.log(` ${c.dim}Waiting for GitHub authorization...${c.reset}`);
667
+ console.log();
668
+
669
+ const interval = (deviceData.interval || 5) * 1000;
670
+ const maxAttempts = Math.ceil((deviceData.expires_in || 900) / (interval / 1000));
671
+
672
+ for (let attempt = 0; attempt < maxAttempts; attempt++) {
673
+ await new Promise(r => setTimeout(r, interval));
674
+
675
+ try {
676
+ const res = await fetch(`${REGISTRY_URL}/api/auth/device?device_code=${deviceData.device_code}`, {
677
+ signal: AbortSignal.timeout(10_000),
678
+ });
679
+ const data = await res.json();
680
+
681
+ if (res.ok && data.api_key) {
682
+ // Success!
683
+ saveCredentials({ api_key: data.api_key, agent_name: data.agent_name });
684
+ console.log(`\r ${c.green}${icons.safe} Logged in as ${c.bold}${data.agent_name}${c.reset} `);
685
+ console.log(` ${c.dim}Key saved to: ${USER_CRED_FILE}${c.reset}`);
686
+ setupReadyMessage();
687
+ return;
688
+ }
689
+
690
+ if (data.error === 'authorization_pending') {
691
+ process.stdout.write(`\r ${c.dim}Waiting... (${attempt + 1}/${maxAttempts})${c.reset} `);
692
+ continue;
693
+ }
694
+
695
+ if (data.error === 'expired_token') {
696
+ console.log(`\n ${c.red}Login expired. Run ${c.cyan}agentaudit login${c.red} again.${c.reset}`);
697
+ return;
698
+ }
699
+
700
+ // Unknown error
701
+ console.log(`\n ${c.red}${data.error || 'Unknown error'}${c.reset}`);
702
+ return;
703
+ } catch {
704
+ // Network error during poll — continue trying
705
+ continue;
706
+ }
707
+ }
708
+
709
+ console.log(`\n ${c.red}Login timed out. Run ${c.cyan}agentaudit login${c.red} again.${c.reset}`);
710
+ }
711
+
582
712
  // ── Helpers ──────────────────────────────────────────────
583
713
 
584
714
  function validateGitUrl(url) {
@@ -3126,7 +3256,7 @@ async function auditRepo(url) {
3126
3256
  for (const { report } of reports) await uploadReport(report, creds);
3127
3257
  console.log(` ${c.dim}Reports: ${REGISTRY_URL}/packages/${slug}${c.reset}`);
3128
3258
  } else if (!noUpload && !creds) {
3129
- console.log(` ${c.dim}Run ${c.cyan}agentaudit setup${c.dim} to upload reports to agentaudit.dev${c.reset}`);
3259
+ console.log(` ${c.dim}Run ${c.cyan}agentaudit login${c.dim} to upload reports to agentaudit.dev${c.reset}`);
3130
3260
  }
3131
3261
 
3132
3262
  console.log();
@@ -3265,11 +3395,11 @@ async function auditRepo(url) {
3265
3395
  console.log(` ${c.dim}Report: ${REGISTRY_URL}/packages/${slug}${c.reset}`);
3266
3396
  } else {
3267
3397
  console.log(` ${c.red}invalid key${c.reset}`);
3268
- console.log(` ${c.dim}Run ${c.cyan}agentaudit setup${c.dim} to configure.${c.reset}`);
3398
+ console.log(` ${c.dim}Run ${c.cyan}agentaudit login${c.dim} to sign in.${c.reset}`);
3269
3399
  }
3270
3400
  }
3271
3401
  } else {
3272
- console.log(` ${c.dim}Run ${c.cyan}agentaudit setup${c.dim} to configure your API key and upload reports${c.reset}`);
3402
+ console.log(` ${c.dim}Run ${c.cyan}agentaudit login${c.dim} to sign in and upload reports${c.reset}`);
3273
3403
  }
3274
3404
 
3275
3405
  console.log();
@@ -3370,7 +3500,7 @@ function renderOverviewTab(data, width) {
3370
3500
  profileLines.push(sevParts.join(' ') || `${c.dim}no findings yet${c.reset}`);
3371
3501
  } else {
3372
3502
  profileLines.push(`${c.dim}Not logged in${c.reset}`);
3373
- profileLines.push(`${c.dim}Run ${c.cyan}agentaudit setup${c.dim} to create account${c.reset}`);
3503
+ profileLines.push(`${c.dim}Run ${c.cyan}agentaudit login${c.dim} to sign in${c.reset}`);
3374
3504
  }
3375
3505
 
3376
3506
  // Registry box
@@ -3591,7 +3721,7 @@ async function activityCommand(args) {
3591
3721
  } else {
3592
3722
  banner();
3593
3723
  console.log(` ${c.yellow}Not logged in${c.reset}`);
3594
- console.log(` ${c.dim}Run ${c.cyan}agentaudit setup${c.dim} to create an account${c.reset}`);
3724
+ console.log(` ${c.dim}Run ${c.cyan}agentaudit login${c.dim} to sign in${c.reset}`);
3595
3725
  }
3596
3726
  return;
3597
3727
  }
@@ -4467,7 +4597,8 @@ async function main() {
4467
4597
  console.log();
4468
4598
  console.log(` ${c.bold}CONFIGURATION${c.reset}`);
4469
4599
  console.log(` ${c.cyan}model${c.reset} Configure LLM provider + model`);
4470
- console.log(` ${c.cyan}setup${c.reset} Log in to agentaudit.dev (for report uploads)`);
4600
+ console.log(` ${c.cyan}login${c.reset} Sign in with GitHub (opens browser)`);
4601
+ console.log(` ${c.cyan}setup${c.reset} Manual login — paste API key`);
4471
4602
  console.log(` ${c.cyan}status${c.reset} Show current config + auth status`);
4472
4603
  console.log(` ${c.cyan}profile${c.reset} Your profile — rank, points, audit stats`);
4473
4604
  console.log();
@@ -4621,7 +4752,7 @@ async function main() {
4621
4752
 
4622
4753
  banner();
4623
4754
 
4624
- if (command === 'setup') {
4755
+ if (command === 'setup' || command === 'login') {
4625
4756
  await setupCommand();
4626
4757
  return;
4627
4758
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentaudit",
3
- "version": "3.12.6",
3
+ "version": "3.12.8",
4
4
  "description": "Security scanner for AI packages — MCP server + CLI",
5
5
  "type": "module",
6
6
  "bin": {