agentaudit 3.12.6 → 3.12.7
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 +125 -7
- 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
|
|
@@ -579,6 +580,117 @@ async function setupCommand() {
|
|
|
579
580
|
console.log();
|
|
580
581
|
}
|
|
581
582
|
|
|
583
|
+
// ── Login via GitHub Device Flow ─────────────────────────
|
|
584
|
+
|
|
585
|
+
async function loginCommand() {
|
|
586
|
+
console.log(` ${c.bold}AgentAudit Login${c.reset}`);
|
|
587
|
+
console.log(` ${c.dim}Sign in with GitHub to upload audit reports${c.reset}`);
|
|
588
|
+
console.log();
|
|
589
|
+
|
|
590
|
+
const existing = loadCredentials();
|
|
591
|
+
if (existing) {
|
|
592
|
+
console.log(` ${icons.safe} Already logged in as ${c.bold}${existing.agent_name}${c.reset}`);
|
|
593
|
+
console.log(` ${c.dim}Key: ${existing.api_key.slice(0, 12)}...${c.reset}`);
|
|
594
|
+
console.log();
|
|
595
|
+
const answer = await askQuestion(` Re-authenticate? ${c.dim}(y/N)${c.reset} `);
|
|
596
|
+
if (answer.toLowerCase() !== 'y') {
|
|
597
|
+
console.log(` ${c.dim}Keeping existing login.${c.reset}`);
|
|
598
|
+
return;
|
|
599
|
+
}
|
|
600
|
+
console.log();
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
// Step 1: Start device flow
|
|
604
|
+
process.stdout.write(` Starting login flow...`);
|
|
605
|
+
let deviceData;
|
|
606
|
+
try {
|
|
607
|
+
const res = await fetch(`${REGISTRY_URL}/api/auth/device`, {
|
|
608
|
+
method: 'POST',
|
|
609
|
+
headers: { 'Content-Type': 'application/json' },
|
|
610
|
+
signal: AbortSignal.timeout(10_000),
|
|
611
|
+
});
|
|
612
|
+
deviceData = await res.json();
|
|
613
|
+
if (!res.ok || !deviceData.device_code) {
|
|
614
|
+
console.log(` ${c.red}failed${c.reset}`);
|
|
615
|
+
console.log(` ${c.red}${deviceData.error || 'Could not start login flow'}${c.reset}`);
|
|
616
|
+
console.log(` ${c.dim}Fallback: run ${c.cyan}agentaudit setup${c.dim} to paste an API key manually${c.reset}`);
|
|
617
|
+
return;
|
|
618
|
+
}
|
|
619
|
+
console.log(` ${c.green}ok${c.reset}`);
|
|
620
|
+
} catch (err) {
|
|
621
|
+
console.log(` ${c.red}failed${c.reset}`);
|
|
622
|
+
console.log(` ${c.red}Could not reach ${REGISTRY_URL}${c.reset}`);
|
|
623
|
+
console.log(` ${c.dim}Fallback: run ${c.cyan}agentaudit setup${c.dim} to paste an API key manually${c.reset}`);
|
|
624
|
+
return;
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
// Step 2: Open browser
|
|
628
|
+
const verifyUrl = deviceData.verification_url;
|
|
629
|
+
console.log();
|
|
630
|
+
console.log(` ${c.bold}Open this URL in your browser:${c.reset}`);
|
|
631
|
+
console.log(` ${c.cyan}${verifyUrl}${c.reset}`);
|
|
632
|
+
console.log();
|
|
633
|
+
|
|
634
|
+
// Try to auto-open browser
|
|
635
|
+
try {
|
|
636
|
+
const openCmd = process.platform === 'darwin' ? 'open' : process.platform === 'win32' ? 'start' : 'xdg-open';
|
|
637
|
+
const { exec } = await import('child_process');
|
|
638
|
+
exec(`${openCmd} "${verifyUrl}"`);
|
|
639
|
+
console.log(` ${c.dim}(Browser should open automatically)${c.reset}`);
|
|
640
|
+
} catch {}
|
|
641
|
+
|
|
642
|
+
// Step 3: Poll for authorization
|
|
643
|
+
console.log(` ${c.dim}Waiting for GitHub authorization...${c.reset}`);
|
|
644
|
+
console.log();
|
|
645
|
+
|
|
646
|
+
const interval = (deviceData.interval || 5) * 1000;
|
|
647
|
+
const maxAttempts = Math.ceil((deviceData.expires_in || 900) / (interval / 1000));
|
|
648
|
+
|
|
649
|
+
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
650
|
+
await new Promise(r => setTimeout(r, interval));
|
|
651
|
+
|
|
652
|
+
try {
|
|
653
|
+
const res = await fetch(`${REGISTRY_URL}/api/auth/device?device_code=${deviceData.device_code}`, {
|
|
654
|
+
signal: AbortSignal.timeout(10_000),
|
|
655
|
+
});
|
|
656
|
+
const data = await res.json();
|
|
657
|
+
|
|
658
|
+
if (res.ok && data.api_key) {
|
|
659
|
+
// Success!
|
|
660
|
+
saveCredentials({ api_key: data.api_key, agent_name: data.agent_name });
|
|
661
|
+
console.log(` ${c.green}${icons.safe} Logged in as ${c.bold}${data.agent_name}${c.reset}`);
|
|
662
|
+
console.log(` ${c.dim}Key saved to: ${USER_CRED_FILE}${c.reset}`);
|
|
663
|
+
console.log();
|
|
664
|
+
console.log(` ${c.bold}Ready!${c.reset} You can now:`);
|
|
665
|
+
console.log(` ${c.dim}•${c.reset} Audit packages: ${c.cyan}agentaudit audit <repo-url>${c.reset}`);
|
|
666
|
+
console.log(` ${c.dim}•${c.reset} Quick scan: ${c.cyan}agentaudit scan <repo-url>${c.reset}`);
|
|
667
|
+
console.log(` ${c.dim}•${c.reset} Check registry: ${c.cyan}agentaudit check <name>${c.reset}`);
|
|
668
|
+
console.log();
|
|
669
|
+
return;
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
if (data.error === 'authorization_pending') {
|
|
673
|
+
process.stdout.write(`\r ${c.dim}Waiting... (${attempt + 1}/${maxAttempts})${c.reset} `);
|
|
674
|
+
continue;
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
if (data.error === 'expired_token') {
|
|
678
|
+
console.log(`\n ${c.red}Login expired. Run ${c.cyan}agentaudit login${c.red} again.${c.reset}`);
|
|
679
|
+
return;
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
// Unknown error
|
|
683
|
+
console.log(`\n ${c.red}${data.error || 'Unknown error'}${c.reset}`);
|
|
684
|
+
return;
|
|
685
|
+
} catch {
|
|
686
|
+
// Network error during poll — continue trying
|
|
687
|
+
continue;
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
console.log(`\n ${c.red}Login timed out. Run ${c.cyan}agentaudit login${c.red} again.${c.reset}`);
|
|
692
|
+
}
|
|
693
|
+
|
|
582
694
|
// ── Helpers ──────────────────────────────────────────────
|
|
583
695
|
|
|
584
696
|
function validateGitUrl(url) {
|
|
@@ -3126,7 +3238,7 @@ async function auditRepo(url) {
|
|
|
3126
3238
|
for (const { report } of reports) await uploadReport(report, creds);
|
|
3127
3239
|
console.log(` ${c.dim}Reports: ${REGISTRY_URL}/packages/${slug}${c.reset}`);
|
|
3128
3240
|
} else if (!noUpload && !creds) {
|
|
3129
|
-
console.log(` ${c.dim}Run ${c.cyan}agentaudit
|
|
3241
|
+
console.log(` ${c.dim}Run ${c.cyan}agentaudit login${c.dim} to upload reports to agentaudit.dev${c.reset}`);
|
|
3130
3242
|
}
|
|
3131
3243
|
|
|
3132
3244
|
console.log();
|
|
@@ -3265,11 +3377,11 @@ async function auditRepo(url) {
|
|
|
3265
3377
|
console.log(` ${c.dim}Report: ${REGISTRY_URL}/packages/${slug}${c.reset}`);
|
|
3266
3378
|
} else {
|
|
3267
3379
|
console.log(` ${c.red}invalid key${c.reset}`);
|
|
3268
|
-
console.log(` ${c.dim}Run ${c.cyan}agentaudit
|
|
3380
|
+
console.log(` ${c.dim}Run ${c.cyan}agentaudit login${c.dim} to sign in.${c.reset}`);
|
|
3269
3381
|
}
|
|
3270
3382
|
}
|
|
3271
3383
|
} else {
|
|
3272
|
-
console.log(` ${c.dim}Run ${c.cyan}agentaudit
|
|
3384
|
+
console.log(` ${c.dim}Run ${c.cyan}agentaudit login${c.dim} to sign in and upload reports${c.reset}`);
|
|
3273
3385
|
}
|
|
3274
3386
|
|
|
3275
3387
|
console.log();
|
|
@@ -3370,7 +3482,7 @@ function renderOverviewTab(data, width) {
|
|
|
3370
3482
|
profileLines.push(sevParts.join(' ') || `${c.dim}no findings yet${c.reset}`);
|
|
3371
3483
|
} else {
|
|
3372
3484
|
profileLines.push(`${c.dim}Not logged in${c.reset}`);
|
|
3373
|
-
profileLines.push(`${c.dim}Run ${c.cyan}agentaudit
|
|
3485
|
+
profileLines.push(`${c.dim}Run ${c.cyan}agentaudit login${c.dim} to sign in${c.reset}`);
|
|
3374
3486
|
}
|
|
3375
3487
|
|
|
3376
3488
|
// Registry box
|
|
@@ -3591,7 +3703,7 @@ async function activityCommand(args) {
|
|
|
3591
3703
|
} else {
|
|
3592
3704
|
banner();
|
|
3593
3705
|
console.log(` ${c.yellow}Not logged in${c.reset}`);
|
|
3594
|
-
console.log(` ${c.dim}Run ${c.cyan}agentaudit
|
|
3706
|
+
console.log(` ${c.dim}Run ${c.cyan}agentaudit login${c.dim} to sign in${c.reset}`);
|
|
3595
3707
|
}
|
|
3596
3708
|
return;
|
|
3597
3709
|
}
|
|
@@ -4467,7 +4579,8 @@ async function main() {
|
|
|
4467
4579
|
console.log();
|
|
4468
4580
|
console.log(` ${c.bold}CONFIGURATION${c.reset}`);
|
|
4469
4581
|
console.log(` ${c.cyan}model${c.reset} Configure LLM provider + model`);
|
|
4470
|
-
console.log(` ${c.cyan}
|
|
4582
|
+
console.log(` ${c.cyan}login${c.reset} Sign in with GitHub (opens browser)`);
|
|
4583
|
+
console.log(` ${c.cyan}setup${c.reset} Manual login — paste API key`);
|
|
4471
4584
|
console.log(` ${c.cyan}status${c.reset} Show current config + auth status`);
|
|
4472
4585
|
console.log(` ${c.cyan}profile${c.reset} Your profile — rank, points, audit stats`);
|
|
4473
4586
|
console.log();
|
|
@@ -4626,6 +4739,11 @@ async function main() {
|
|
|
4626
4739
|
return;
|
|
4627
4740
|
}
|
|
4628
4741
|
|
|
4742
|
+
if (command === 'login') {
|
|
4743
|
+
await loginCommand();
|
|
4744
|
+
return;
|
|
4745
|
+
}
|
|
4746
|
+
|
|
4629
4747
|
if (command === 'status' || command === 'whoami') {
|
|
4630
4748
|
// ── Status / diagnostic overview ──
|
|
4631
4749
|
const config = loadLlmConfig();
|