@forkpoint/agent-lighthouse 0.3.0 โ†’ 1.0.0

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/README.md CHANGED
@@ -10,7 +10,7 @@ npx @forkpoint/agent-lighthouse https://yourstore.com --view
10
10
  npx @forkpoint/agent-lighthouse https://staging.yourstore.com --min-score 85
11
11
  ```
12
12
 
13
- The CLI generates terminal, HTML, JSON, and Markdown reports for 207 audits across:
13
+ The CLI generates terminal, HTML, JSON, and Markdown reports for 189 audits across:
14
14
 
15
15
  - `llms.txt`, `llms-full.txt`, sitemaps, and RSS discovery
16
16
  - robots.txt access for GPTBot, ClaudeBot, PerplexityBot, and other AI crawlers
package/dist/main.js CHANGED
@@ -3,6 +3,115 @@
3
3
 
4
4
  // src/main.ts
5
5
  var import_agent_lighthouse_core = require("@forkpoint/agent-lighthouse-core");
6
+
7
+ // src/progress-renderer.ts
8
+ var PHASE_LABELS = {
9
+ "fetch-root": "Root files",
10
+ "fetch-pages": "Pages",
11
+ analyze: "Page analysis",
12
+ audits: "Audits",
13
+ report: "Report"
14
+ };
15
+ var SPINNER = ["|", "/", "-", "\\"];
16
+ var BAR_WIDTH = 20;
17
+ var ETA_MIN_FRACTION = 0.05;
18
+ var ETA_MAX_MS = 5 * 60 * 1e3;
19
+ function formatPhaseDone(info) {
20
+ const color = info.color ?? true;
21
+ const seconds = (info.durationMs / 1e3).toFixed(1);
22
+ const check = color ? "\x1B[32m\u2713\x1B[0m" : "\u2713";
23
+ let line = `${check} ${PHASE_LABELS[info.phase]} ${info.completed}/${info.total} \xB7 ${seconds}s`;
24
+ if ((info.failures ?? 0) > 0) {
25
+ const suffix = `\xB7 ${info.failures} errored`;
26
+ line += color ? ` \x1B[33m${suffix}\x1B[0m` : ` ${suffix}`;
27
+ }
28
+ return line;
29
+ }
30
+ function formatEta(fraction, elapsedMs) {
31
+ if (fraction <= ETA_MIN_FRACTION || fraction >= 1) return null;
32
+ const etaMs = elapsedMs * (1 - fraction) / fraction;
33
+ if (!Number.isFinite(etaMs) || etaMs < 0 || etaMs > ETA_MAX_MS) return null;
34
+ return `~${Math.ceil(etaMs / 1e3)}s left`;
35
+ }
36
+ function formatStatusLine(info) {
37
+ const spinner = SPINNER[info.spinnerIndex % SPINNER.length];
38
+ const fraction = Math.min(1, Math.max(0, info.fraction));
39
+ const filled = Math.round(fraction * BAR_WIDTH);
40
+ const bar = "\u2588".repeat(filled) + "\u2591".repeat(BAR_WIDTH - filled);
41
+ const pct = Math.round(fraction * 100);
42
+ const eta = formatEta(info.fraction, info.elapsedMs);
43
+ const counts = info.total > 0 ? ` ${info.completed}/${info.total}` : "";
44
+ return ` \x1B[36m${spinner}\x1B[0m ${info.label}${counts} [${bar}] ${pct}%${eta ? ` ${eta}` : ""}`;
45
+ }
46
+ function createProgressRenderer(options) {
47
+ const write = options.write ?? ((text) => process.stdout.write(text));
48
+ const now = options.now ?? (() => Date.now());
49
+ const minInterval = options.minRenderIntervalMs ?? 30;
50
+ let spinnerIndex = 0;
51
+ let lastRender = Number.NEGATIVE_INFINITY;
52
+ let stickyShown = false;
53
+ let label = "";
54
+ let completed = 0;
55
+ let total = 0;
56
+ let failures = 0;
57
+ const clearSticky = () => {
58
+ if (stickyShown) {
59
+ write("\r\x1B[K");
60
+ stickyShown = false;
61
+ }
62
+ };
63
+ const renderSticky = (fraction, elapsedMs) => {
64
+ const t = now();
65
+ if (t - lastRender < minInterval) return;
66
+ lastRender = t;
67
+ spinnerIndex += 1;
68
+ write(
69
+ "\r" + formatStatusLine({ spinnerIndex, label, completed, total, fraction, elapsedMs }) + "\x1B[K"
70
+ );
71
+ stickyShown = true;
72
+ };
73
+ return (event) => {
74
+ switch (event.type) {
75
+ case "scan:start":
76
+ break;
77
+ case "phase:start":
78
+ label = PHASE_LABELS[event.phase];
79
+ completed = 0;
80
+ total = event.totalUnits;
81
+ failures = 0;
82
+ break;
83
+ case "unit:done":
84
+ completed = event.completed;
85
+ total = event.total;
86
+ if (options.tty) renderSticky(event.fraction, event.elapsedMs);
87
+ break;
88
+ case "unit:fail":
89
+ completed += 1;
90
+ failures += 1;
91
+ if (options.tty) renderSticky(event.fraction, event.elapsedMs);
92
+ break;
93
+ case "phase:done":
94
+ clearSticky();
95
+ write(
96
+ formatPhaseDone({
97
+ phase: event.phase,
98
+ completed,
99
+ total,
100
+ durationMs: event.durationMs,
101
+ failures,
102
+ color: options.tty
103
+ }) + "\n"
104
+ );
105
+ failures = 0;
106
+ break;
107
+ case "scan:done":
108
+ clearSticky();
109
+ break;
110
+ }
111
+ };
112
+ }
113
+
114
+ // src/main.ts
6
115
  var import_agent_lighthouse_report = require("@forkpoint/agent-lighthouse-report");
7
116
  var import_node_fs = require("fs");
8
117
  var import_node_path = require("path");
@@ -42,6 +151,11 @@ Options:
42
151
  --min-score <number> Minimum score (0-100) required to pass CI assertions
43
152
  --assert-category <id:min> Per-category assertions (e.g. --assert-category structured-data:90)
44
153
  --silent Suppress progress output
154
+ --progress-json Stream scan progress as NDJSON (one ScanEvent per line) to stderr
155
+ and suppress the interactive progress display. Stderr is used so
156
+ NDJSON never interleaves with the terminal report on stdout;
157
+ all scanner logs (including error logs) are silenced to keep the
158
+ stream clean \u2014 audit errors still appear in the report itself.
45
159
 
46
160
  Examples:
47
161
  npx @forkpoint/agent-lighthouse https://yourstore.com
@@ -90,6 +204,8 @@ async function audit(targetUrl) {
90
204
  process.exit(1);
91
205
  }
92
206
  const isSilent = args.includes("--silent");
207
+ const progressJson = args.includes("--progress-json");
208
+ if (progressJson) import_agent_lighthouse_core.logger.level = "silent";
93
209
  const shouldView = args.includes("-v") || args.includes("--view");
94
210
  const debugAudit = getArgValue("", "--debug-audit");
95
211
  const presetName = getArgValue("-p", "--preset") || fileConfig.preset || "full";
@@ -106,16 +222,10 @@ async function audit(targetUrl) {
106
222
  `
107
223
  );
108
224
  }
109
- const report = await (0, import_agent_lighthouse_core.runScan)(url, (pct, phase) => {
110
- if (!isSilent) {
111
- process.stdout.write(
112
- `\r \x1B[36m[${pct.toString().padStart(3)}%]\x1B[0m ${phase}`
113
- );
114
- }
115
- });
116
- if (!isSilent) {
117
- process.stdout.write("\r" + " ".repeat(80) + "\r");
118
- }
225
+ const onEvent = progressJson ? (event) => {
226
+ process.stderr.write(JSON.stringify(event) + "\n");
227
+ } : isSilent ? void 0 : createProgressRenderer({ tty: Boolean(process.stdout.isTTY) });
228
+ const report = await (0, import_agent_lighthouse_core.runScan)(url, { onEvent });
119
229
  const view = (0, import_agent_lighthouse_report.buildReportView)(report);
120
230
  if (outputFormats.includes("terminal") && !isSilent) {
121
231
  console.log(
package/dist/main.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/main.ts"],"sourcesContent":["import {\n runScan,\n loadConfigFile,\n getPreset,\n type PresetName,\n} from \"@forkpoint/agent-lighthouse-core\";\nimport {\n buildReportView,\n generateHtmlReport,\n generateMarkdownSummary,\n} from \"@forkpoint/agent-lighthouse-report\";\nimport { writeFileSync, mkdirSync, readFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { exec } from \"node:child_process\";\n\nconst args = process.argv.slice(2);\nconst command = args[0];\n\nfunction getPackageVersion() {\n try {\n const pkg = JSON.parse(\n readFileSync(resolve(__dirname, \"../package.json\"), \"utf8\"),\n ) as { version?: string };\n return pkg.version || \"unknown\";\n } catch {\n return \"unknown\";\n }\n}\n\nfunction printBanner() {\n console.log(`\n\\x1b[1m\\x1b[36m๐Ÿ—ผ Agent Lighthouse\\x1b[0m \\x1b[90mv${getPackageVersion()}\\x1b[0m\n\\x1b[90mThe Open-Source Lighthouse for the Agentic Web\\x1b[0m\n`);\n}\n\nfunction usage(): never {\n printBanner();\n console.log(`Usage:\n agent-lighthouse <url> [options]\n agent-lighthouse audit <url> [options]\n\nOptions:\n -p, --preset <name> Audit preset (ecommerce, saas, content, quick, full) [default: full]\n -c, --config <path> Path to configuration file (e.g. agent-lighthouse.config.json)\n --debug-audit <id|fails> Print deep diagnostic breakdown for specific audit ID (e.g. 3.2) or all fails\n --categories <list> Comma-separated list of categories to audit\n -o, --output <formats> Output formats (comma-separated: terminal, html, json, md) [default: terminal,html,json]\n -d, --output-dir <path> Output directory for generated reports [default: ./reports]\n -v, --view Automatically open the generated HTML report in your browser\n --min-score <number> Minimum score (0-100) required to pass CI assertions\n --assert-category <id:min> Per-category assertions (e.g. --assert-category structured-data:90)\n --silent Suppress progress output\n\nExamples:\n npx @forkpoint/agent-lighthouse https://yourstore.com\n npx @forkpoint/agent-lighthouse https://yourstore.com --preset ecommerce\n npx @forkpoint/agent-lighthouse https://yourstore.com --debug-audit 3.2\n npx @forkpoint/agent-lighthouse https://staging.yourstore.com --min-score 85\n`);\n process.exit(1);\n}\n\nfunction openInBrowser(filePath: string) {\n const cmd =\n process.platform === \"darwin\"\n ? `open \"${filePath}\"`\n : process.platform === \"win32\"\n ? `start \"\" \"${filePath}\"`\n : `xdg-open \"${filePath}\"`;\n exec(cmd, () => {});\n}\n\nfunction getArgValue(shortFlag: string, longFlag: string): string | undefined {\n for (const arg of args) {\n if (shortFlag && arg.startsWith(`${shortFlag}=`)) {\n return arg.slice(shortFlag.length + 1);\n }\n if (longFlag && arg.startsWith(`${longFlag}=`)) {\n return arg.slice(longFlag.length + 1);\n }\n }\n const shortIdx = shortFlag ? args.indexOf(shortFlag) : -1;\n if (\n shortIdx !== -1 &&\n args[shortIdx + 1] &&\n !args[shortIdx + 1].startsWith(\"-\")\n ) {\n return args[shortIdx + 1];\n }\n const longIdx = longFlag ? args.indexOf(longFlag) : -1;\n if (\n longIdx !== -1 &&\n args[longIdx + 1] &&\n !args[longIdx + 1].startsWith(\"-\")\n ) {\n return args[longIdx + 1];\n }\n return undefined;\n}\n\nasync function audit(targetUrl?: string) {\n const customConfigPath = getArgValue(\"-c\", \"--config\");\n const fileConfig = loadConfigFile(customConfigPath);\n\n const url = targetUrl || fileConfig.url;\n if (!url) {\n console.error(\"\\x1b[31mError:\\x1b[0m No target URL specified.\");\n usage();\n }\n\n try {\n new URL(url);\n } catch {\n console.error(`\\x1b[31mInvalid URL:\\x1b[0m ${url}`);\n process.exit(1);\n }\n\n const isSilent = args.includes(\"--silent\");\n const shouldView = args.includes(\"-v\") || args.includes(\"--view\");\n const debugAudit = getArgValue(\"\", \"--debug-audit\");\n\n const presetName = (getArgValue(\"-p\", \"--preset\") ||\n fileConfig.preset ||\n \"full\") as PresetName;\n const preset = getPreset(presetName);\n\n const minScoreArg = getArgValue(\"\", \"--min-score\");\n const minScore = minScoreArg\n ? Number(minScoreArg)\n : (fileConfig.minScore ?? 0);\n\n const outputDir =\n getArgValue(\"-d\", \"--output-dir\") || fileConfig.outputDir || \"./reports\";\n\n const outputFormatArg = getArgValue(\"-o\", \"--output\");\n const outputFormats = outputFormatArg\n ? outputFormatArg.split(\",\").map((s) => s.trim())\n : (fileConfig.output ?? [\"terminal\", \"html\", \"json\"]);\n\n if (!isSilent) {\n printBanner();\n console.log(\n `Auditing \\x1b[1m${url}\\x1b[0m using \\x1b[36m${preset.name}\\x1b[0m preset ...\\n`,\n );\n }\n\n const report = await runScan(url, (pct, phase) => {\n if (!isSilent) {\n process.stdout.write(\n `\\r \\x1b[36m[${pct.toString().padStart(3)}%]\\x1b[0m ${phase}`,\n );\n }\n });\n\n if (!isSilent) {\n process.stdout.write(\"\\r\" + \" \".repeat(80) + \"\\r\");\n }\n\n const view = buildReportView(report);\n\n // Terminal Output\n if (outputFormats.includes(\"terminal\") && !isSilent) {\n console.log(\n `\\x1b[1mโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\\x1b[0m`,\n );\n console.log(\n `\\x1b[1mOVERALL AGENT READINESS:\\x1b[0m \\x1b[1m${view.overallScore}/100\\x1b[0m (${view.scoreTier.toUpperCase()})`,\n );\n console.log(\n `Target: ${report.url} | Preset: ${preset.name} | Pages: ${view.pagesScanned.length} | Duration: ${(view.durationMs / 1000).toFixed(1)}s`,\n );\n console.log(\n `\\x1b[1mโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\\x1b[0m\\n`,\n );\n\n if (report.wafProtection?.isBlocked) {\n console.log(\n ` \\x1b[41m\\x1b[37m\\x1b[1m ๐Ÿ›ก๏ธ BOT PROTECTION WALL DETECTED: ${report.wafProtection.name.toUpperCase()} \\x1b[0m`,\n );\n console.log(\n ` \\x1b[31mโš ๏ธ Diagnosis: ${report.wafProtection.reason}\\x1b[0m`,\n );\n console.log(\n ` \\x1b[90mThis storefront is actively dropping or challenging automated crawler connections.\\x1b[0m`,\n );\n console.log(\n ` \\x1b[90mAI agents (GPTBot, Claude, Perplexity) cannot index or interact with this catalog.\\x1b[0m\\n`,\n );\n }\n\n console.log(`\\x1b[1m๐Ÿ“Š CATEGORIES:\\x1b[0m`);\n for (const group of view.groups) {\n console.log(\n `\\n \\x1b[1m${group.label}\\x1b[0m \\x1b[90mโ€”\\x1b[0m ${group.score}/100`,\n );\n for (const cat of group.categories) {\n const c = cat.counts;\n const scoreColor =\n cat.score >= 90\n ? \"\\x1b[32m\"\n : cat.score >= 70\n ? \"\\x1b[34m\"\n : cat.score >= 50\n ? \"\\x1b[33m\"\n : \"\\x1b[31m\";\n console.log(\n ` ${scoreColor}โ€ข\\x1b[0m ${cat.name.padEnd(36)} : ${scoreColor}${cat.score\n .toString()\n .padStart(\n 3,\n )}/100\\x1b[0m \\x1b[90m(${c.pass}โœ“ ${c.warn}! ${c.fail}โœ—)\\x1b[0m`,\n );\n }\n }\n console.log();\n }\n\n // Audit Debugger Output\n if (debugAudit) {\n const allChecks = view.groups.flatMap((g) =>\n g.categories.flatMap((c) => [...c.checks, ...c.notApplicable]),\n );\n const targetChecks =\n debugAudit === \"fails\"\n ? allChecks.filter((c) => c.status === \"fail\" || c.status === \"warn\")\n : allChecks.filter(\n (c) =>\n c.id === debugAudit ||\n c.title.toLowerCase().includes(debugAudit.toLowerCase()),\n );\n\n if (targetChecks.length === 0) {\n console.log(\n `\\x1b[33m[debugger] No audits found matching: ${debugAudit}\\x1b[0m\\n`,\n );\n } else {\n console.log(\n `\\x1b[1m๐Ÿ” AUDIT DEBUGGER DIAGNOSTICS (${targetChecks.length} checks):\\x1b[0m`,\n );\n console.log(\n `\\x1b[1mโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\\x1b[0m`,\n );\n\n for (const check of targetChecks) {\n const statusBadge =\n check.status === \"pass\"\n ? \"\\x1b[32m[PASS]\\x1b[0m\"\n : check.status === \"warn\"\n ? \"\\x1b[33m[WARN]\\x1b[0m\"\n : check.status === \"fail\"\n ? \"\\x1b[31m[FAIL]\\x1b[0m\"\n : \"\\x1b[90m[N/A]\\x1b[0m\";\n\n console.log(\n `\\n${statusBadge} \\x1b[1m[${check.id}] ${check.title}\\x1b[0m (Score: ${check.score})`,\n );\n if (check.pageUrl)\n console.log(` \\x1b[90mPage:\\x1b[0m ${check.pageUrl}`);\n if (check.displayValue)\n console.log(` \\x1b[90mFound:\\x1b[0m ${check.displayValue}`);\n if (check.details?.expected)\n console.log(\n ` \\x1b[90mExpected:\\x1b[0m ${check.details.expected}`,\n );\n if (check.explanation)\n console.log(` \\x1b[90mExplanation:\\x1b[0m ${check.explanation}`);\n if (check.impact)\n console.log(` \\x1b[90mImpact:\\x1b[0m ${check.impact}`);\n if (check.fix)\n console.log(` \\x1b[90mFix:\\x1b[0m ${check.fix}`);\n if (check.details?.code) {\n console.log(` \\x1b[90mCode Example:\\x1b[0m`);\n console.log(\n check.details.code\n .split(\"\\n\")\n .map((line: string) => ` \\x1b[36m${line}\\x1b[0m`)\n .join(\"\\n\"),\n );\n }\n }\n console.log(\n `\\x1b[1mโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\\x1b[0m\\n`,\n );\n }\n }\n\n // Ensure output directory exists\n mkdirSync(resolve(outputDir), { recursive: true });\n\n // JSON Report\n if (outputFormats.includes(\"json\")) {\n const jsonPath = resolve(outputDir, \"agent-lighthouse-report.json\");\n writeFileSync(jsonPath, JSON.stringify(report, null, 2));\n if (!isSilent)\n console.log(` \\x1b[90mโ€ข JSON Report:\\x1b[0m ${jsonPath}`);\n }\n\n // HTML Report\n let htmlPath = \"\";\n if (outputFormats.includes(\"html\")) {\n htmlPath = resolve(outputDir, \"agent-lighthouse-report.html\");\n const htmlContent = generateHtmlReport(report);\n writeFileSync(htmlPath, htmlContent);\n if (!isSilent)\n console.log(` \\x1b[90mโ€ข HTML Report:\\x1b[0m ${htmlPath}`);\n }\n\n // Markdown Summary\n if (outputFormats.includes(\"md\") || outputFormats.includes(\"markdown\")) {\n const mdPath = resolve(outputDir, \"agent-lighthouse-report.md\");\n const mdContent = generateMarkdownSummary(report);\n writeFileSync(mdPath, mdContent);\n if (!isSilent) console.log(` \\x1b[90mโ€ข Markdown Report:\\x1b[0m ${mdPath}`);\n }\n\n if (shouldView && htmlPath) {\n openInBrowser(htmlPath);\n }\n\n // Overall Score Assertion\n if (minScore > 0 && view.overallScore < minScore) {\n console.error(\n `\\n\\x1b[31mโœ– CI Assertion Failed:\\x1b[0m Overall score ${view.overallScore} is below minimum threshold ${minScore}`,\n );\n process.exit(1);\n }\n\n // Per-category Assertions\n const categoryAssertions = fileConfig.assertCategories ?? {};\n for (let i = 0; i < args.length; i++) {\n if (args[i] === \"--assert-category\" && args[i + 1]) {\n const [catId, min] = args[i + 1].split(\":\");\n if (catId && min) categoryAssertions[catId] = Number(min);\n }\n }\n\n for (const [catId, threshold] of Object.entries(categoryAssertions)) {\n const matchedCategory = view.groups\n .flatMap((g) => g.categories)\n .find(\n (c) =>\n c.id === catId || c.name.toLowerCase().includes(catId.toLowerCase()),\n );\n\n if (matchedCategory && matchedCategory.score < threshold) {\n console.error(\n `\\n\\x1b[31mโœ– Category Assertion Failed:\\x1b[0m Category '${matchedCategory.name}' scored ${matchedCategory.score} (threshold: ${threshold})`,\n );\n process.exit(1);\n }\n }\n}\n\nasync function main() {\n if (!command || command === \"-h\" || command === \"--help\") {\n usage();\n }\n\n if (command === \"audit\") {\n const url = args[1];\n await audit(url);\n } else if (!command.startsWith(\"-\")) {\n await audit(command);\n } else {\n await audit();\n }\n}\n\nmain().catch((err) => {\n console.error(\"\\x1b[31mFatal error:\\x1b[0m\", err.message ?? err);\n process.exit(1);\n});\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/main.ts","../src/progress-renderer.ts"],"sourcesContent":["import {\n runScan,\n loadConfigFile,\n getPreset,\n logger,\n type PresetName,\n type ScanEvent,\n} from \"@forkpoint/agent-lighthouse-core\";\nimport { createProgressRenderer } from \"./progress-renderer\";\nimport {\n buildReportView,\n generateHtmlReport,\n generateMarkdownSummary,\n} from \"@forkpoint/agent-lighthouse-report\";\nimport { writeFileSync, mkdirSync, readFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\nimport { exec } from \"node:child_process\";\n\nconst args = process.argv.slice(2);\nconst command = args[0];\n\nfunction getPackageVersion() {\n try {\n const pkg = JSON.parse(\n readFileSync(resolve(__dirname, \"../package.json\"), \"utf8\"),\n ) as { version?: string };\n return pkg.version || \"unknown\";\n } catch {\n return \"unknown\";\n }\n}\n\nfunction printBanner() {\n console.log(`\n\\x1b[1m\\x1b[36m๐Ÿ—ผ Agent Lighthouse\\x1b[0m \\x1b[90mv${getPackageVersion()}\\x1b[0m\n\\x1b[90mThe Open-Source Lighthouse for the Agentic Web\\x1b[0m\n`);\n}\n\nfunction usage(): never {\n printBanner();\n console.log(`Usage:\n agent-lighthouse <url> [options]\n agent-lighthouse audit <url> [options]\n\nOptions:\n -p, --preset <name> Audit preset (ecommerce, saas, content, quick, full) [default: full]\n -c, --config <path> Path to configuration file (e.g. agent-lighthouse.config.json)\n --debug-audit <id|fails> Print deep diagnostic breakdown for specific audit ID (e.g. 3.2) or all fails\n --categories <list> Comma-separated list of categories to audit\n -o, --output <formats> Output formats (comma-separated: terminal, html, json, md) [default: terminal,html,json]\n -d, --output-dir <path> Output directory for generated reports [default: ./reports]\n -v, --view Automatically open the generated HTML report in your browser\n --min-score <number> Minimum score (0-100) required to pass CI assertions\n --assert-category <id:min> Per-category assertions (e.g. --assert-category structured-data:90)\n --silent Suppress progress output\n --progress-json Stream scan progress as NDJSON (one ScanEvent per line) to stderr\n and suppress the interactive progress display. Stderr is used so\n NDJSON never interleaves with the terminal report on stdout;\n all scanner logs (including error logs) are silenced to keep the\n stream clean โ€” audit errors still appear in the report itself.\n\nExamples:\n npx @forkpoint/agent-lighthouse https://yourstore.com\n npx @forkpoint/agent-lighthouse https://yourstore.com --preset ecommerce\n npx @forkpoint/agent-lighthouse https://yourstore.com --debug-audit 3.2\n npx @forkpoint/agent-lighthouse https://staging.yourstore.com --min-score 85\n`);\n process.exit(1);\n}\n\nfunction openInBrowser(filePath: string) {\n const cmd =\n process.platform === \"darwin\"\n ? `open \"${filePath}\"`\n : process.platform === \"win32\"\n ? `start \"\" \"${filePath}\"`\n : `xdg-open \"${filePath}\"`;\n exec(cmd, () => {});\n}\n\nfunction getArgValue(shortFlag: string, longFlag: string): string | undefined {\n for (const arg of args) {\n if (shortFlag && arg.startsWith(`${shortFlag}=`)) {\n return arg.slice(shortFlag.length + 1);\n }\n if (longFlag && arg.startsWith(`${longFlag}=`)) {\n return arg.slice(longFlag.length + 1);\n }\n }\n const shortIdx = shortFlag ? args.indexOf(shortFlag) : -1;\n if (\n shortIdx !== -1 &&\n args[shortIdx + 1] &&\n !args[shortIdx + 1].startsWith(\"-\")\n ) {\n return args[shortIdx + 1];\n }\n const longIdx = longFlag ? args.indexOf(longFlag) : -1;\n if (\n longIdx !== -1 &&\n args[longIdx + 1] &&\n !args[longIdx + 1].startsWith(\"-\")\n ) {\n return args[longIdx + 1];\n }\n return undefined;\n}\n\nasync function audit(targetUrl?: string) {\n const customConfigPath = getArgValue(\"-c\", \"--config\");\n const fileConfig = loadConfigFile(customConfigPath);\n\n const url = targetUrl || fileConfig.url;\n if (!url) {\n console.error(\"\\x1b[31mError:\\x1b[0m No target URL specified.\");\n usage();\n }\n\n try {\n new URL(url);\n } catch {\n console.error(`\\x1b[31mInvalid URL:\\x1b[0m ${url}`);\n process.exit(1);\n }\n\n const isSilent = args.includes(\"--silent\");\n const progressJson = args.includes(\"--progress-json\");\n // Keep the NDJSON stream clean: scanner logs also go to stderr.\n if (progressJson) logger.level = \"silent\";\n const shouldView = args.includes(\"-v\") || args.includes(\"--view\");\n const debugAudit = getArgValue(\"\", \"--debug-audit\");\n\n const presetName = (getArgValue(\"-p\", \"--preset\") ||\n fileConfig.preset ||\n \"full\") as PresetName;\n const preset = getPreset(presetName);\n\n const minScoreArg = getArgValue(\"\", \"--min-score\");\n const minScore = minScoreArg\n ? Number(minScoreArg)\n : (fileConfig.minScore ?? 0);\n\n const outputDir =\n getArgValue(\"-d\", \"--output-dir\") || fileConfig.outputDir || \"./reports\";\n\n const outputFormatArg = getArgValue(\"-o\", \"--output\");\n const outputFormats = outputFormatArg\n ? outputFormatArg.split(\",\").map((s) => s.trim())\n : (fileConfig.output ?? [\"terminal\", \"html\", \"json\"]);\n\n if (!isSilent) {\n printBanner();\n console.log(\n `Auditing \\x1b[1m${url}\\x1b[0m using \\x1b[36m${preset.name}\\x1b[0m preset ...\\n`,\n );\n }\n\n // Progress: --progress-json streams raw ScanEvents as NDJSON to stderr (kept\n // off stdout so it can't interleave with the terminal report). Otherwise the\n // interactive renderer animates on a TTY and prints plain phase summaries in\n // CI (non-TTY). --silent suppresses all progress output as before.\n const onEvent = progressJson\n ? (event: ScanEvent) => {\n process.stderr.write(JSON.stringify(event) + \"\\n\");\n }\n : isSilent\n ? undefined\n : createProgressRenderer({ tty: Boolean(process.stdout.isTTY) });\n\n const report = await runScan(url, { onEvent });\n\n const view = buildReportView(report);\n\n // Terminal Output\n if (outputFormats.includes(\"terminal\") && !isSilent) {\n console.log(\n `\\x1b[1mโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\\x1b[0m`,\n );\n console.log(\n `\\x1b[1mOVERALL AGENT READINESS:\\x1b[0m \\x1b[1m${view.overallScore}/100\\x1b[0m (${view.scoreTier.toUpperCase()})`,\n );\n console.log(\n `Target: ${report.url} | Preset: ${preset.name} | Pages: ${view.pagesScanned.length} | Duration: ${(view.durationMs / 1000).toFixed(1)}s`,\n );\n console.log(\n `\\x1b[1mโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\\x1b[0m\\n`,\n );\n\n if (report.wafProtection?.isBlocked) {\n console.log(\n ` \\x1b[41m\\x1b[37m\\x1b[1m ๐Ÿ›ก๏ธ BOT PROTECTION WALL DETECTED: ${report.wafProtection.name.toUpperCase()} \\x1b[0m`,\n );\n console.log(\n ` \\x1b[31mโš ๏ธ Diagnosis: ${report.wafProtection.reason}\\x1b[0m`,\n );\n console.log(\n ` \\x1b[90mThis storefront is actively dropping or challenging automated crawler connections.\\x1b[0m`,\n );\n console.log(\n ` \\x1b[90mAI agents (GPTBot, Claude, Perplexity) cannot index or interact with this catalog.\\x1b[0m\\n`,\n );\n }\n\n console.log(`\\x1b[1m๐Ÿ“Š CATEGORIES:\\x1b[0m`);\n for (const group of view.groups) {\n console.log(\n `\\n \\x1b[1m${group.label}\\x1b[0m \\x1b[90mโ€”\\x1b[0m ${group.score}/100`,\n );\n for (const cat of group.categories) {\n const c = cat.counts;\n const scoreColor =\n cat.score >= 90\n ? \"\\x1b[32m\"\n : cat.score >= 70\n ? \"\\x1b[34m\"\n : cat.score >= 50\n ? \"\\x1b[33m\"\n : \"\\x1b[31m\";\n console.log(\n ` ${scoreColor}โ€ข\\x1b[0m ${cat.name.padEnd(36)} : ${scoreColor}${cat.score\n .toString()\n .padStart(\n 3,\n )}/100\\x1b[0m \\x1b[90m(${c.pass}โœ“ ${c.warn}! ${c.fail}โœ—)\\x1b[0m`,\n );\n }\n }\n console.log();\n }\n\n // Audit Debugger Output\n if (debugAudit) {\n const allChecks = view.groups.flatMap((g) =>\n g.categories.flatMap((c) => [...c.checks, ...c.notApplicable]),\n );\n const targetChecks =\n debugAudit === \"fails\"\n ? allChecks.filter((c) => c.status === \"fail\" || c.status === \"warn\")\n : allChecks.filter(\n (c) =>\n c.id === debugAudit ||\n c.title.toLowerCase().includes(debugAudit.toLowerCase()),\n );\n\n if (targetChecks.length === 0) {\n console.log(\n `\\x1b[33m[debugger] No audits found matching: ${debugAudit}\\x1b[0m\\n`,\n );\n } else {\n console.log(\n `\\x1b[1m๐Ÿ” AUDIT DEBUGGER DIAGNOSTICS (${targetChecks.length} checks):\\x1b[0m`,\n );\n console.log(\n `\\x1b[1mโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\\x1b[0m`,\n );\n\n for (const check of targetChecks) {\n const statusBadge =\n check.status === \"pass\"\n ? \"\\x1b[32m[PASS]\\x1b[0m\"\n : check.status === \"warn\"\n ? \"\\x1b[33m[WARN]\\x1b[0m\"\n : check.status === \"fail\"\n ? \"\\x1b[31m[FAIL]\\x1b[0m\"\n : \"\\x1b[90m[N/A]\\x1b[0m\";\n\n console.log(\n `\\n${statusBadge} \\x1b[1m[${check.id}] ${check.title}\\x1b[0m (Score: ${check.score})`,\n );\n if (check.pageUrl)\n console.log(` \\x1b[90mPage:\\x1b[0m ${check.pageUrl}`);\n if (check.displayValue)\n console.log(` \\x1b[90mFound:\\x1b[0m ${check.displayValue}`);\n if (check.details?.expected)\n console.log(\n ` \\x1b[90mExpected:\\x1b[0m ${check.details.expected}`,\n );\n if (check.explanation)\n console.log(` \\x1b[90mExplanation:\\x1b[0m ${check.explanation}`);\n if (check.impact)\n console.log(` \\x1b[90mImpact:\\x1b[0m ${check.impact}`);\n if (check.fix)\n console.log(` \\x1b[90mFix:\\x1b[0m ${check.fix}`);\n if (check.details?.code) {\n console.log(` \\x1b[90mCode Example:\\x1b[0m`);\n console.log(\n check.details.code\n .split(\"\\n\")\n .map((line: string) => ` \\x1b[36m${line}\\x1b[0m`)\n .join(\"\\n\"),\n );\n }\n }\n console.log(\n `\\x1b[1mโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€\\x1b[0m\\n`,\n );\n }\n }\n\n // Ensure output directory exists\n mkdirSync(resolve(outputDir), { recursive: true });\n\n // JSON Report\n if (outputFormats.includes(\"json\")) {\n const jsonPath = resolve(outputDir, \"agent-lighthouse-report.json\");\n writeFileSync(jsonPath, JSON.stringify(report, null, 2));\n if (!isSilent)\n console.log(` \\x1b[90mโ€ข JSON Report:\\x1b[0m ${jsonPath}`);\n }\n\n // HTML Report\n let htmlPath = \"\";\n if (outputFormats.includes(\"html\")) {\n htmlPath = resolve(outputDir, \"agent-lighthouse-report.html\");\n const htmlContent = generateHtmlReport(report);\n writeFileSync(htmlPath, htmlContent);\n if (!isSilent)\n console.log(` \\x1b[90mโ€ข HTML Report:\\x1b[0m ${htmlPath}`);\n }\n\n // Markdown Summary\n if (outputFormats.includes(\"md\") || outputFormats.includes(\"markdown\")) {\n const mdPath = resolve(outputDir, \"agent-lighthouse-report.md\");\n const mdContent = generateMarkdownSummary(report);\n writeFileSync(mdPath, mdContent);\n if (!isSilent) console.log(` \\x1b[90mโ€ข Markdown Report:\\x1b[0m ${mdPath}`);\n }\n\n if (shouldView && htmlPath) {\n openInBrowser(htmlPath);\n }\n\n // Overall Score Assertion\n if (minScore > 0 && view.overallScore < minScore) {\n console.error(\n `\\n\\x1b[31mโœ– CI Assertion Failed:\\x1b[0m Overall score ${view.overallScore} is below minimum threshold ${minScore}`,\n );\n process.exit(1);\n }\n\n // Per-category Assertions\n const categoryAssertions = fileConfig.assertCategories ?? {};\n for (let i = 0; i < args.length; i++) {\n if (args[i] === \"--assert-category\" && args[i + 1]) {\n const [catId, min] = args[i + 1].split(\":\");\n if (catId && min) categoryAssertions[catId] = Number(min);\n }\n }\n\n for (const [catId, threshold] of Object.entries(categoryAssertions)) {\n const matchedCategory = view.groups\n .flatMap((g) => g.categories)\n .find(\n (c) =>\n c.id === catId || c.name.toLowerCase().includes(catId.toLowerCase()),\n );\n\n if (matchedCategory && matchedCategory.score < threshold) {\n console.error(\n `\\n\\x1b[31mโœ– Category Assertion Failed:\\x1b[0m Category '${matchedCategory.name}' scored ${matchedCategory.score} (threshold: ${threshold})`,\n );\n process.exit(1);\n }\n }\n}\n\nasync function main() {\n if (!command || command === \"-h\" || command === \"--help\") {\n usage();\n }\n\n if (command === \"audit\") {\n const url = args[1];\n await audit(url);\n } else if (!command.startsWith(\"-\")) {\n await audit(command);\n } else {\n await audit();\n }\n}\n\nmain().catch((err) => {\n console.error(\"\\x1b[31mFatal error:\\x1b[0m\", err.message ?? err);\n process.exit(1);\n});\n","import type { PhaseId, ScanEvent } from \"@forkpoint/agent-lighthouse-core\";\n\nexport const PHASE_LABELS: Record<PhaseId, string> = {\n \"fetch-root\": \"Root files\",\n \"fetch-pages\": \"Pages\",\n analyze: \"Page analysis\",\n audits: \"Audits\",\n report: \"Report\",\n};\n\nconst SPINNER = [\"|\", \"/\", \"-\", \"\\\\\"];\nconst BAR_WIDTH = 20;\nconst ETA_MIN_FRACTION = 0.05;\nconst ETA_MAX_MS = 5 * 60 * 1000;\n\nexport interface PhaseDoneInfo {\n phase: PhaseId;\n completed: number;\n total: number;\n durationMs: number;\n failures?: number;\n color?: boolean;\n}\n\n/** Permanent one-line summary printed when a phase finishes. */\nexport function formatPhaseDone(info: PhaseDoneInfo): string {\n const color = info.color ?? true;\n const seconds = (info.durationMs / 1000).toFixed(1);\n const check = color ? \"\\x1b[32mโœ“\\x1b[0m\" : \"โœ“\";\n let line = `${check} ${PHASE_LABELS[info.phase]} ${info.completed}/${info.total} ยท ${seconds}s`;\n if ((info.failures ?? 0) > 0) {\n const suffix = `ยท ${info.failures} errored`;\n line += color ? ` \\x1b[33m${suffix}\\x1b[0m` : ` ${suffix}`;\n }\n return line;\n}\n\n/** Human ETA from overall scan fraction, or null when unreliable/absurd. */\nexport function formatEta(fraction: number, elapsedMs: number): string | null {\n if (fraction <= ETA_MIN_FRACTION || fraction >= 1) return null;\n const etaMs = (elapsedMs * (1 - fraction)) / fraction;\n if (!Number.isFinite(etaMs) || etaMs < 0 || etaMs > ETA_MAX_MS) return null;\n return `~${Math.ceil(etaMs / 1000)}s left`;\n}\n\nexport interface StatusLineInfo {\n spinnerIndex: number;\n label: string;\n completed: number;\n total: number;\n fraction: number;\n elapsedMs: number;\n}\n\n/** The sticky overwriting status line shown while a phase is active. */\nexport function formatStatusLine(info: StatusLineInfo): string {\n const spinner = SPINNER[info.spinnerIndex % SPINNER.length];\n const fraction = Math.min(1, Math.max(0, info.fraction));\n const filled = Math.round(fraction * BAR_WIDTH);\n const bar = \"โ–ˆ\".repeat(filled) + \"โ–‘\".repeat(BAR_WIDTH - filled);\n const pct = Math.round(fraction * 100);\n const eta = formatEta(info.fraction, info.elapsedMs);\n const counts = info.total > 0 ? ` ${info.completed}/${info.total}` : \"\";\n return ` \\x1b[36m${spinner}\\x1b[0m ${info.label}${counts} [${bar}] ${pct}%${eta ? ` ${eta}` : \"\"}`;\n}\n\nexport interface ProgressRendererOptions {\n /** TTY: animate a sticky status line. Non-TTY: phase summaries only, no ANSI. */\n tty: boolean;\n write?: (text: string) => void;\n now?: () => number;\n minRenderIntervalMs?: number;\n}\n\n/**\n * Stateful ScanEvent consumer. Returns the `onEvent` handler for runScan.\n * Sticky-line renders are throttled; phase:done lines are always written;\n * scan:done only erases the sticky line (the report output follows).\n */\nexport function createProgressRenderer(\n options: ProgressRendererOptions,\n): (event: ScanEvent) => void {\n const write = options.write ?? ((text: string) => process.stdout.write(text));\n const now = options.now ?? (() => Date.now());\n const minInterval = options.minRenderIntervalMs ?? 30;\n\n let spinnerIndex = 0;\n let lastRender = Number.NEGATIVE_INFINITY;\n let stickyShown = false;\n let label = \"\";\n let completed = 0;\n let total = 0;\n let failures = 0;\n\n const clearSticky = () => {\n if (stickyShown) {\n write(\"\\r\\x1b[K\");\n stickyShown = false;\n }\n };\n\n const renderSticky = (fraction: number, elapsedMs: number) => {\n const t = now();\n if (t - lastRender < minInterval) return;\n lastRender = t;\n spinnerIndex += 1;\n write(\n \"\\r\" +\n formatStatusLine({ spinnerIndex, label, completed, total, fraction, elapsedMs }) +\n \"\\x1b[K\",\n );\n stickyShown = true;\n };\n\n return (event) => {\n switch (event.type) {\n case \"scan:start\":\n break;\n case \"phase:start\":\n label = PHASE_LABELS[event.phase];\n completed = 0;\n total = event.totalUnits;\n failures = 0;\n break;\n case \"unit:done\":\n completed = event.completed;\n total = event.total;\n if (options.tty) renderSticky(event.fraction, event.elapsedMs);\n break;\n case \"unit:fail\":\n // A failed unit still counts as settled work (see ProgressTracker).\n completed += 1;\n failures += 1;\n if (options.tty) renderSticky(event.fraction, event.elapsedMs);\n break;\n case \"phase:done\":\n clearSticky();\n write(\n formatPhaseDone({\n phase: event.phase,\n completed,\n total,\n durationMs: event.durationMs,\n failures,\n color: options.tty,\n }) + \"\\n\",\n );\n failures = 0;\n break;\n case \"scan:done\":\n clearSticky();\n break;\n }\n };\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forkpoint/agent-lighthouse",
3
- "version": "0.3.0",
3
+ "version": "1.0.0",
4
4
  "description": "Lighthouse-style CLI for auditing websites for AI agents, LLM crawlers, MCP clients, llms.txt, WebMCP, OpenAPI, and Schema.org readiness",
5
5
  "author": "ForkPoint",
6
6
  "license": "Apache-2.0",
@@ -47,8 +47,8 @@
47
47
  "access": "public"
48
48
  },
49
49
  "dependencies": {
50
- "@forkpoint/agent-lighthouse-core": "0.3.0",
51
- "@forkpoint/agent-lighthouse-report": "0.3.0"
50
+ "@forkpoint/agent-lighthouse-core": "1.0.0",
51
+ "@forkpoint/agent-lighthouse-report": "1.0.0"
52
52
  },
53
53
  "devDependencies": {
54
54
  "@types/node": "^22.10.5",