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.
- package/cli.mjs +141 -10
- 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
|
-
*
|
|
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}
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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}
|
|
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
|
}
|