@forkpoint/agent-lighthouse 0.2.0 → 0.2.2

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 ADDED
@@ -0,0 +1,39 @@
1
+ # @forkpoint/agent-lighthouse
2
+
3
+ Lighthouse-style CLI for auditing whether AI agents, LLM crawlers, MCP clients, and agentic browsers can discover, parse, cite, and act on a website.
4
+
5
+ ## Quickstart
6
+
7
+ ```bash
8
+ npx @forkpoint/agent-lighthouse https://yourstore.com
9
+ npx @forkpoint/agent-lighthouse https://yourstore.com --view
10
+ npx @forkpoint/agent-lighthouse https://staging.yourstore.com --min-score 85
11
+ ```
12
+
13
+ The CLI generates terminal, HTML, JSON, and Markdown reports for 199 audits across:
14
+
15
+ - `llms.txt`, `llms-full.txt`, sitemaps, and RSS discovery
16
+ - robots.txt access for GPTBot, ClaudeBot, PerplexityBot, and other AI crawlers
17
+ - Schema.org, JSON-LD, product, offer, review, and organization markup
18
+ - WebMCP, OpenAPI, agents.json, and action-surface discovery
19
+ - AEO/GEO content structure, semantic HTML, accessibility, and technical readiness
20
+
21
+ ## CI
22
+
23
+ ```bash
24
+ npx @forkpoint/agent-lighthouse https://staging.yourstore.com \
25
+ --preset ecommerce \
26
+ --min-score 85 \
27
+ --output terminal,html,json,md \
28
+ --output-dir ./reports
29
+ ```
30
+
31
+ ## Links
32
+
33
+ - Documentation: https://forkpoint.github.io/agent-lighthouse/
34
+ - Repository: https://github.com/ForkPoint/agent-lighthouse
35
+ - Issues: https://github.com/ForkPoint/agent-lighthouse/issues
36
+
37
+ ## License
38
+
39
+ GPL-3.0-only
package/dist/main.js CHANGED
@@ -9,9 +9,19 @@ var import_node_path = require("path");
9
9
  var import_node_child_process = require("child_process");
10
10
  var args = process.argv.slice(2);
11
11
  var command = args[0];
12
+ function getPackageVersion() {
13
+ try {
14
+ const pkg = JSON.parse(
15
+ (0, import_node_fs.readFileSync)((0, import_node_path.resolve)(__dirname, "../package.json"), "utf8")
16
+ );
17
+ return pkg.version || "unknown";
18
+ } catch {
19
+ return "unknown";
20
+ }
21
+ }
12
22
  function printBanner() {
13
23
  console.log(`
14
- \x1B[1m\x1B[36m\u{1F5FC} Agent Lighthouse\x1B[0m \x1B[90mv0.1.0\x1B[0m
24
+ \x1B[1m\x1B[36m\u{1F5FC} Agent Lighthouse\x1B[0m \x1B[90mv${getPackageVersion()}\x1B[0m
15
25
  \x1B[90mThe Open-Source Lighthouse for the Agentic Web\x1B[0m
16
26
  `);
17
27
  }
@@ -91,12 +101,16 @@ async function audit(targetUrl) {
91
101
  const outputFormats = outputFormatArg ? outputFormatArg.split(",").map((s) => s.trim()) : fileConfig.output ?? ["terminal", "html", "json"];
92
102
  if (!isSilent) {
93
103
  printBanner();
94
- console.log(`Auditing \x1B[1m${url}\x1B[0m using \x1B[36m${preset.name}\x1B[0m preset ...
95
- `);
104
+ console.log(
105
+ `Auditing \x1B[1m${url}\x1B[0m using \x1B[36m${preset.name}\x1B[0m preset ...
106
+ `
107
+ );
96
108
  }
97
109
  const report = await (0, import_agent_lighthouse_core.runScan)(url, (pct, phase) => {
98
110
  if (!isSilent) {
99
- process.stdout.write(`\r \x1B[36m[${pct.toString().padStart(3)}%]\x1B[0m ${phase}`);
111
+ process.stdout.write(
112
+ `\r \x1B[36m[${pct.toString().padStart(3)}%]\x1B[0m ${phase}`
113
+ );
100
114
  }
101
115
  });
102
116
  if (!isSilent) {
@@ -104,31 +118,47 @@ async function audit(targetUrl) {
104
118
  }
105
119
  const view = (0, import_agent_lighthouse_report.buildReportView)(report);
106
120
  if (outputFormats.includes("terminal") && !isSilent) {
107
- console.log(`\x1B[1m\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\x1B[0m`);
121
+ console.log(
122
+ `\x1B[1m\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\x1B[0m`
123
+ );
108
124
  console.log(
109
125
  `\x1B[1mOVERALL AGENT READINESS:\x1B[0m \x1B[1m${view.overallScore}/100\x1B[0m (${view.scoreTier.toUpperCase()})`
110
126
  );
111
127
  console.log(
112
128
  `Target: ${report.url} | Preset: ${preset.name} | Pages: ${view.pagesScanned.length} | Duration: ${(view.durationMs / 1e3).toFixed(1)}s`
113
129
  );
114
- console.log(`\x1B[1m\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\x1B[0m
115
- `);
130
+ console.log(
131
+ `\x1B[1m\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\x1B[0m
132
+ `
133
+ );
116
134
  if (report.wafProtection?.isBlocked) {
117
- console.log(` \x1B[41m\x1B[37m\x1B[1m \u{1F6E1}\uFE0F BOT PROTECTION WALL DETECTED: ${report.wafProtection.name.toUpperCase()} \x1B[0m`);
118
- console.log(` \x1B[31m\u26A0\uFE0F Diagnosis: ${report.wafProtection.reason}\x1B[0m`);
119
- console.log(` \x1B[90mThis storefront is actively dropping or challenging automated crawler connections.\x1B[0m`);
120
- console.log(` \x1B[90mAI agents (GPTBot, Claude, Perplexity) cannot index or interact with this catalog.\x1B[0m
121
- `);
135
+ console.log(
136
+ ` \x1B[41m\x1B[37m\x1B[1m \u{1F6E1}\uFE0F BOT PROTECTION WALL DETECTED: ${report.wafProtection.name.toUpperCase()} \x1B[0m`
137
+ );
138
+ console.log(
139
+ ` \x1B[31m\u26A0\uFE0F Diagnosis: ${report.wafProtection.reason}\x1B[0m`
140
+ );
141
+ console.log(
142
+ ` \x1B[90mThis storefront is actively dropping or challenging automated crawler connections.\x1B[0m`
143
+ );
144
+ console.log(
145
+ ` \x1B[90mAI agents (GPTBot, Claude, Perplexity) cannot index or interact with this catalog.\x1B[0m
146
+ `
147
+ );
122
148
  }
123
149
  console.log(`\x1B[1m\u{1F4CA} CATEGORIES:\x1B[0m`);
124
150
  for (const group of view.groups) {
125
- console.log(`
126
- \x1B[1m${group.label}\x1B[0m \x1B[90m\u2014\x1B[0m ${group.score}/100`);
151
+ console.log(
152
+ `
153
+ \x1B[1m${group.label}\x1B[0m \x1B[90m\u2014\x1B[0m ${group.score}/100`
154
+ );
127
155
  for (const cat of group.categories) {
128
156
  const c = cat.counts;
129
157
  const scoreColor = cat.score >= 90 ? "\x1B[32m" : cat.score >= 70 ? "\x1B[34m" : cat.score >= 50 ? "\x1B[33m" : "\x1B[31m";
130
158
  console.log(
131
- ` ${scoreColor}\u2022\x1B[0m ${cat.name.padEnd(36)} : ${scoreColor}${cat.score.toString().padStart(3)}/100\x1B[0m \x1B[90m(${c.pass}\u2713 ${c.warn}! ${c.fail}\u2717)\x1B[0m`
159
+ ` ${scoreColor}\u2022\x1B[0m ${cat.name.padEnd(36)} : ${scoreColor}${cat.score.toString().padStart(
160
+ 3
161
+ )}/100\x1B[0m \x1B[90m(${c.pass}\u2713 ${c.warn}! ${c.fail}\u2717)\x1B[0m`
132
162
  );
133
163
  }
134
164
  }
@@ -142,21 +172,37 @@ async function audit(targetUrl) {
142
172
  (c) => c.id === debugAudit || c.title.toLowerCase().includes(debugAudit.toLowerCase())
143
173
  );
144
174
  if (targetChecks.length === 0) {
145
- console.log(`\x1B[33m[debugger] No audits found matching: ${debugAudit}\x1B[0m
146
- `);
175
+ console.log(
176
+ `\x1B[33m[debugger] No audits found matching: ${debugAudit}\x1B[0m
177
+ `
178
+ );
147
179
  } else {
148
- console.log(`\x1B[1m\u{1F50D} AUDIT DEBUGGER DIAGNOSTICS (${targetChecks.length} checks):\x1B[0m`);
149
- console.log(`\x1B[1m\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\x1B[0m`);
180
+ console.log(
181
+ `\x1B[1m\u{1F50D} AUDIT DEBUGGER DIAGNOSTICS (${targetChecks.length} checks):\x1B[0m`
182
+ );
183
+ console.log(
184
+ `\x1B[1m\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\x1B[0m`
185
+ );
150
186
  for (const check of targetChecks) {
151
187
  const statusBadge = check.status === "pass" ? "\x1B[32m[PASS]\x1B[0m" : check.status === "warn" ? "\x1B[33m[WARN]\x1B[0m" : check.status === "fail" ? "\x1B[31m[FAIL]\x1B[0m" : "\x1B[90m[N/A]\x1B[0m";
152
- console.log(`
153
- ${statusBadge} \x1B[1m[${check.id}] ${check.title}\x1B[0m (Score: ${check.score})`);
154
- if (check.pageUrl) console.log(` \x1B[90mPage:\x1B[0m ${check.pageUrl}`);
155
- if (check.displayValue) console.log(` \x1B[90mFound:\x1B[0m ${check.displayValue}`);
156
- if (check.details?.expected) console.log(` \x1B[90mExpected:\x1B[0m ${check.details.expected}`);
157
- if (check.explanation) console.log(` \x1B[90mExplanation:\x1B[0m ${check.explanation}`);
158
- if (check.impact) console.log(` \x1B[90mImpact:\x1B[0m ${check.impact}`);
159
- if (check.fix) console.log(` \x1B[90mFix:\x1B[0m ${check.fix}`);
188
+ console.log(
189
+ `
190
+ ${statusBadge} \x1B[1m[${check.id}] ${check.title}\x1B[0m (Score: ${check.score})`
191
+ );
192
+ if (check.pageUrl)
193
+ console.log(` \x1B[90mPage:\x1B[0m ${check.pageUrl}`);
194
+ if (check.displayValue)
195
+ console.log(` \x1B[90mFound:\x1B[0m ${check.displayValue}`);
196
+ if (check.details?.expected)
197
+ console.log(
198
+ ` \x1B[90mExpected:\x1B[0m ${check.details.expected}`
199
+ );
200
+ if (check.explanation)
201
+ console.log(` \x1B[90mExplanation:\x1B[0m ${check.explanation}`);
202
+ if (check.impact)
203
+ console.log(` \x1B[90mImpact:\x1B[0m ${check.impact}`);
204
+ if (check.fix)
205
+ console.log(` \x1B[90mFix:\x1B[0m ${check.fix}`);
160
206
  if (check.details?.code) {
161
207
  console.log(` \x1B[90mCode Example:\x1B[0m`);
162
208
  console.log(
@@ -164,22 +210,26 @@ ${statusBadge} \x1B[1m[${check.id}] ${check.title}\x1B[0m (Score: ${check.score}
164
210
  );
165
211
  }
166
212
  }
167
- console.log(`\x1B[1m\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\x1B[0m
168
- `);
213
+ console.log(
214
+ `\x1B[1m\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\x1B[0m
215
+ `
216
+ );
169
217
  }
170
218
  }
171
219
  (0, import_node_fs.mkdirSync)((0, import_node_path.resolve)(outputDir), { recursive: true });
172
220
  if (outputFormats.includes("json")) {
173
221
  const jsonPath = (0, import_node_path.resolve)(outputDir, "agent-lighthouse-report.json");
174
222
  (0, import_node_fs.writeFileSync)(jsonPath, JSON.stringify(report, null, 2));
175
- if (!isSilent) console.log(` \x1B[90m\u2022 JSON Report:\x1B[0m ${jsonPath}`);
223
+ if (!isSilent)
224
+ console.log(` \x1B[90m\u2022 JSON Report:\x1B[0m ${jsonPath}`);
176
225
  }
177
226
  let htmlPath = "";
178
227
  if (outputFormats.includes("html")) {
179
228
  htmlPath = (0, import_node_path.resolve)(outputDir, "agent-lighthouse-report.html");
180
229
  const htmlContent = (0, import_agent_lighthouse_report.generateHtmlReport)(report);
181
230
  (0, import_node_fs.writeFileSync)(htmlPath, htmlContent);
182
- if (!isSilent) console.log(` \x1B[90m\u2022 HTML Report:\x1B[0m ${htmlPath}`);
231
+ if (!isSilent)
232
+ console.log(` \x1B[90m\u2022 HTML Report:\x1B[0m ${htmlPath}`);
183
233
  }
184
234
  if (outputFormats.includes("md") || outputFormats.includes("markdown")) {
185
235
  const mdPath = (0, import_node_path.resolve)(outputDir, "agent-lighthouse-report.md");
@@ -205,7 +255,9 @@ ${statusBadge} \x1B[1m[${check.id}] ${check.title}\x1B[0m (Score: ${check.score}
205
255
  }
206
256
  }
207
257
  for (const [catId, threshold] of Object.entries(categoryAssertions)) {
208
- const matchedCategory = view.groups.flatMap((g) => g.categories).find((c) => c.id === catId || c.name.toLowerCase().includes(catId.toLowerCase()));
258
+ const matchedCategory = view.groups.flatMap((g) => g.categories).find(
259
+ (c) => c.id === catId || c.name.toLowerCase().includes(catId.toLowerCase())
260
+ );
209
261
  if (matchedCategory && matchedCategory.score < threshold) {
210
262
  console.error(
211
263
  `
package/dist/main.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/main.ts"],"sourcesContent":["import { runScan, loadConfigFile, getPreset, type PresetName } from '@forkpoint/agent-lighthouse-core';\nimport { buildReportView, generateHtmlReport, generateMarkdownSummary } from '@forkpoint/agent-lighthouse-report';\nimport { writeFileSync, mkdirSync } 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 printBanner() {\n console.log(`\n\\x1b[1m\\x1b[36m🗼 Agent Lighthouse\\x1b[0m \\x1b[90mv0.1.0\\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 (shortIdx !== -1 && args[shortIdx + 1] && !args[shortIdx + 1].startsWith('-')) {\n return args[shortIdx + 1];\n }\n const longIdx = longFlag ? args.indexOf(longFlag) : -1;\n if (longIdx !== -1 && args[longIdx + 1] && !args[longIdx + 1].startsWith('-')) {\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') || fileConfig.preset || 'full') as PresetName;\n const preset = getPreset(presetName);\n\n const minScoreArg = getArgValue('', '--min-score');\n const minScore = minScoreArg ? Number(minScoreArg) : fileConfig.minScore ?? 0;\n\n const outputDir = 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(`Auditing \\x1b[1m${url}\\x1b[0m using \\x1b[36m${preset.name}\\x1b[0m preset ...\\n`);\n }\n\n const report = await runScan(url, (pct, phase) => {\n if (!isSilent) {\n process.stdout.write(`\\r \\x1b[36m[${pct.toString().padStart(3)}%]\\x1b[0m ${phase}`);\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(`\\x1b[1m────────────────────────────────────────────────────────────────────────\\x1b[0m`);\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(`\\x1b[1m────────────────────────────────────────────────────────────────────────\\x1b[0m\\n`);\n\n if (report.wafProtection?.isBlocked) {\n console.log(` \\x1b[41m\\x1b[37m\\x1b[1m 🛡️ BOT PROTECTION WALL DETECTED: ${report.wafProtection.name.toUpperCase()} \\x1b[0m`);\n console.log(` \\x1b[31m⚠️ Diagnosis: ${report.wafProtection.reason}\\x1b[0m`);\n console.log(` \\x1b[90mThis storefront is actively dropping or challenging automated crawler connections.\\x1b[0m`);\n console.log(` \\x1b[90mAI agents (GPTBot, Claude, Perplexity) cannot index or interact with this catalog.\\x1b[0m\\n`);\n }\n\n console.log(`\\x1b[1m📊 CATEGORIES:\\x1b[0m`);\n for (const group of view.groups) {\n console.log(`\\n \\x1b[1m${group.label}\\x1b[0m \\x1b[90m—\\x1b[0m ${group.score}/100`);\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(3)}/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) => c.id === debugAudit || c.title.toLowerCase().includes(debugAudit.toLowerCase())\n );\n\n if (targetChecks.length === 0) {\n console.log(`\\x1b[33m[debugger] No audits found matching: ${debugAudit}\\x1b[0m\\n`);\n } else {\n console.log(`\\x1b[1m🔍 AUDIT DEBUGGER DIAGNOSTICS (${targetChecks.length} checks):\\x1b[0m`);\n console.log(`\\x1b[1m────────────────────────────────────────────────────────────────────────\\x1b[0m`);\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${statusBadge} \\x1b[1m[${check.id}] ${check.title}\\x1b[0m (Score: ${check.score})`);\n if (check.pageUrl) console.log(` \\x1b[90mPage:\\x1b[0m ${check.pageUrl}`);\n if (check.displayValue) console.log(` \\x1b[90mFound:\\x1b[0m ${check.displayValue}`);\n if (check.details?.expected) console.log(` \\x1b[90mExpected:\\x1b[0m ${check.details.expected}`);\n if (check.explanation) console.log(` \\x1b[90mExplanation:\\x1b[0m ${check.explanation}`);\n if (check.impact) console.log(` \\x1b[90mImpact:\\x1b[0m ${check.impact}`);\n if (check.fix) 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(`\\x1b[1m────────────────────────────────────────────────────────────────────────\\x1b[0m\\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) 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) 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((c) => c.id === catId || c.name.toLowerCase().includes(catId.toLowerCase()));\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"],"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":[]}
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@forkpoint/agent-lighthouse",
3
- "version": "0.2.0",
4
- "description": "The Open-Source Lighthouse for the Agentic Web",
3
+ "version": "0.2.2",
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": "GPL-3.0-only",
7
- "homepage": "https://github.com/ForkPoint/agent-lighthouse#readme",
7
+ "homepage": "https://forkpoint.github.io/agent-lighthouse/",
8
8
  "repository": {
9
9
  "type": "git",
10
10
  "url": "git+https://github.com/ForkPoint/agent-lighthouse.git",
@@ -25,6 +25,12 @@
25
25
  "mcp",
26
26
  "openapi",
27
27
  "schema-org",
28
+ "llms-txt",
29
+ "robots-txt",
30
+ "ai-seo",
31
+ "crawler",
32
+ "github-actions",
33
+ "agent-readiness",
28
34
  "aeo",
29
35
  "geo",
30
36
  "seo"
@@ -41,8 +47,8 @@
41
47
  "access": "public"
42
48
  },
43
49
  "dependencies": {
44
- "@forkpoint/agent-lighthouse-core": "0.2.0",
45
- "@forkpoint/agent-lighthouse-report": "0.2.0"
50
+ "@forkpoint/agent-lighthouse-core": "0.2.2",
51
+ "@forkpoint/agent-lighthouse-report": "0.2.2"
46
52
  },
47
53
  "devDependencies": {
48
54
  "@types/node": "^22.10.5",