@ai-lighthouse/cli 1.0.1 โ†’ 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/README.md +126 -53
  2. package/dist/index.js +2788 -12
  3. package/package.json +10 -4
  4. package/.ai-lighthouse/audit_example.com_2025-12-15T12-10-43.json +0 -183
  5. package/.ai-lighthouse/audit_fayeed.dev_2026-01-07T19-32-28.html +0 -743
  6. package/.ai-lighthouse/audit_fayeed.dev_2026-01-07T19-33-02.html +0 -757
  7. package/.ai-lighthouse/audit_github.com_2025-12-15T11-53-21.json +0 -168
  8. package/.ai-lighthouse/audit_github.com_2025-12-15T12-04-06.json +0 -168
  9. package/.ai-lighthouse/audit_github.com_2025-12-15T12-05-10.json +0 -168
  10. package/.ai-lighthouse/audit_github.com_2025-12-15T12-09-45.json +0 -168
  11. package/.ai-lighthouse/audit_github.com_2025-12-15T12-11-07.json +0 -168
  12. package/.ai-lighthouse/audit_github.com_2025-12-15T12-13-28.json +0 -168
  13. package/.ai-lighthouse/audit_github.com_2025-12-15T12-14-59.json +0 -205
  14. package/.ai-lighthouse/audit_github.com_2025-12-15T12-18-07.json +0 -205
  15. package/.ai-lighthouse/audit_github.com_2025-12-15T12-18-44.json +0 -205
  16. package/.ai-lighthouse/audit_github.com_2025-12-15T12-21-38.json +0 -205
  17. package/.ai-lighthouse/audit_github.com_2025-12-15T12-22-21.json +0 -205
  18. package/.ai-lighthouse/audit_github.com_2025-12-15T12-22-46.json +0 -205
  19. package/.ai-lighthouse/audit_github.com_2025-12-15T12-23-18.json +0 -205
  20. package/.ai-lighthouse/audit_github.com_2025-12-15T12-24-43.json +0 -205
  21. package/.ai-lighthouse/audit_github.com_2025-12-17T12-15-08.json +0 -168
  22. package/.ai-lighthouse/audit_github.com_2025-12-17T12-15-57.json +0 -168
  23. package/.ai-lighthouse/audit_github.com_2025-12-17T12-17-11.json +0 -168
  24. package/.ai-lighthouse/audit_github.com_2025-12-17T12-22-17.json +0 -168
  25. package/.ai-lighthouse/audit_github.com_2025-12-17T12-22-42.json +0 -168
  26. package/.ai-lighthouse/audit_github.com_2025-12-17T12-23-56.json +0 -168
  27. package/.ai-lighthouse/audit_github.com_2025-12-17T12-25-24.json +0 -168
  28. package/.ai-lighthouse/audit_github.com_2025-12-17T12-25-40.json +0 -168
  29. package/.ai-lighthouse/audit_github.com_2025-12-17T12-27-02.json +0 -168
  30. package/.ai-lighthouse/audit_github.com_2025-12-17T12-27-20.json +0 -168
  31. package/.ai-lighthouse/audit_github.com_2025-12-17T12-29-56.json +0 -168
  32. package/.ai-lighthouse/audit_github.com_2025-12-17T12-32-27.json +0 -168
  33. package/.ai-lighthouse/audit_github.com_2025-12-17T12-33-00.json +0 -168
  34. package/.ai-lighthouse/audit_github.com_2025-12-17T12-34-49.json +0 -168
  35. package/.ai-lighthouse/audit_stripe.com_2025-12-15T12-11-31.json +0 -168
  36. package/.ai-lighthouse/audit_stripe.com_2025-12-15T12-11-45.json +0 -168
  37. package/.ai-lighthouse/audit_tailwindcss.com_2025-12-15T12-12-01.json +0 -169
  38. package/.ai-lighthouse/crawl_example.com_2025-12-15T12-03-08.json +0 -24
  39. package/.ai-lighthouse/crawl_example.com_2025-12-15T12-03-23.json +0 -24
  40. package/.ai-lighthouse/crawl_github.com_2025-12-15T11-41-34.json +0 -21
  41. package/.ai-lighthouse/crawl_github.com_2025-12-15T11-42-09.json +0 -21
  42. package/.ai-lighthouse/crawl_github.com_2025-12-15T11-42-45.json +0 -21
  43. package/.ai-lighthouse/crawl_github.com_2025-12-15T11-43-02.json +0 -21
  44. package/.ai-lighthouse/crawl_github.com_2025-12-15T11-43-26.json +0 -21
  45. package/.ai-lighthouse/crawl_github.com_2025-12-15T11-47-46.json +0 -906
  46. package/.ai-lighthouse/crawl_github.com_2025-12-15T11-50-27.json +0 -906
  47. package/.ai-lighthouse/crawl_github.com_2025-12-15T11-52-59.json +0 -906
  48. package/.ai-lighthouse/crawl_github.com_2025-12-15T12-03-33.json +0 -28
  49. package/CLI_UI_README.md +0 -211
  50. package/EXAMPLES.md +0 -87
  51. package/IMPLEMENTATION.md +0 -215
  52. package/USAGE.md +0 -264
  53. package/WIZARD_GUIDE.md +0 -340
  54. package/bin/cli.js +0 -2
  55. package/dist/commands/audit-interactive.d.ts +0 -2
  56. package/dist/commands/audit-interactive.js +0 -106
  57. package/dist/commands/audit-wizard.d.ts +0 -2
  58. package/dist/commands/audit-wizard.js +0 -110
  59. package/dist/commands/audit.d.ts +0 -2
  60. package/dist/commands/audit.js +0 -940
  61. package/dist/commands/crawl.d.ts +0 -2
  62. package/dist/commands/crawl.js +0 -267
  63. package/dist/commands/report.d.ts +0 -2
  64. package/dist/commands/report.js +0 -304
  65. package/dist/index.d.ts +0 -1
  66. package/dist/ui/AuditReportUI.d.ts +0 -10
  67. package/dist/ui/AuditReportUI.js +0 -76
  68. package/dist/ui/SetupWizard.d.ts +0 -18
  69. package/dist/ui/SetupWizard.js +0 -179
  70. package/dist/ui/components/AIUnderstandingSection.d.ts +0 -6
  71. package/dist/ui/components/AIUnderstandingSection.js +0 -87
  72. package/dist/ui/components/HallucinationSection.d.ts +0 -6
  73. package/dist/ui/components/HallucinationSection.js +0 -84
  74. package/dist/ui/components/IssuesSection.d.ts +0 -6
  75. package/dist/ui/components/IssuesSection.js +0 -84
  76. package/dist/ui/components/MessageAlignmentSection.d.ts +0 -6
  77. package/dist/ui/components/MessageAlignmentSection.js +0 -108
  78. package/dist/ui/components/OverviewSection.d.ts +0 -6
  79. package/dist/ui/components/OverviewSection.js +0 -107
  80. package/dist/ui/components/ScoreDisplay.d.ts +0 -8
  81. package/dist/ui/components/ScoreDisplay.js +0 -41
  82. package/dist/ui/components/TechnicalSection.d.ts +0 -7
  83. package/dist/ui/components/TechnicalSection.js +0 -110
  84. package/dist/utils/comprehensive-formatter.d.ts +0 -5
  85. package/dist/utils/comprehensive-formatter.js +0 -370
  86. package/src/commands/audit-interactive.ts +0 -149
  87. package/src/commands/audit-wizard.ts +0 -137
  88. package/src/commands/audit.ts +0 -1012
  89. package/src/commands/crawl.ts +0 -307
  90. package/src/commands/report.ts +0 -321
  91. package/src/index.ts +0 -22
  92. package/src/ui/AuditReportUI.tsx +0 -151
  93. package/src/ui/SetupWizard.tsx +0 -294
  94. package/src/ui/components/AIUnderstandingSection.tsx +0 -183
  95. package/src/ui/components/HallucinationSection.tsx +0 -172
  96. package/src/ui/components/IssuesSection.tsx +0 -140
  97. package/src/ui/components/MessageAlignmentSection.tsx +0 -203
  98. package/src/ui/components/OverviewSection.tsx +0 -157
  99. package/src/ui/components/ScoreDisplay.tsx +0 -58
  100. package/src/ui/components/TechnicalSection.tsx +0 -200
  101. package/src/utils/comprehensive-formatter.ts +0 -455
  102. package/test.sh +0 -31
  103. package/tsconfig.json +0 -25
@@ -1,107 +0,0 @@
1
- import React from 'react';
2
- import { Box, Text } from 'ink';
3
- export const OverviewSection = ({ aiReadiness }) => {
4
- const getStatusColor = (status) => {
5
- if (status === 'excellent')
6
- return 'green';
7
- if (status === 'good')
8
- return 'blue';
9
- if (status === 'needs-work')
10
- return 'yellow';
11
- return 'red';
12
- };
13
- const renderProgressBar = (score, width = 20) => {
14
- const filled = Math.round((score / 100) * width);
15
- const empty = width - filled;
16
- const color = score >= 80 ? 'green' : score >= 60 ? 'yellow' : 'red';
17
- return (React.createElement(Text, { color: color },
18
- 'โ–ˆ'.repeat(filled),
19
- React.createElement(Text, { dimColor: true }, 'โ–‘'.repeat(empty)),
20
- ` ${Math.round(score)}%`));
21
- };
22
- return (React.createElement(Box, { flexDirection: "column", paddingY: 1 },
23
- React.createElement(Box, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 2, paddingY: 1, marginBottom: 1 },
24
- React.createElement(Text, { bold: true, color: "cyan" }, "\uD83E\uDD16 AI Agent Perspective"),
25
- React.createElement(Box, { marginTop: 1, flexDirection: "column" },
26
- React.createElement(Box, null,
27
- React.createElement(Text, null,
28
- aiReadiness.aiPerspective?.canUnderstand ? 'โœ…' : 'โŒ',
29
- " Can Understand",
30
- aiReadiness.aiPerspective?.canExtract ? 'โœ…' : 'โŒ',
31
- " Can Extract")),
32
- React.createElement(Box, null,
33
- React.createElement(Text, null,
34
- aiReadiness.aiPerspective?.canIndex ? 'โœ…' : 'โŒ',
35
- " Can Index",
36
- aiReadiness.aiPerspective?.canAnswer ? 'โœ…' : 'โŒ',
37
- " Can Answer")),
38
- React.createElement(Box, { marginTop: 1 },
39
- React.createElement(Text, { dimColor: true },
40
- "Confidence: ",
41
- Math.round((aiReadiness.aiPerspective?.confidence || 0) * 100),
42
- "%"))),
43
- aiReadiness.aiPerspective?.mainBlockers && aiReadiness.aiPerspective.mainBlockers.length > 0 && (React.createElement(Box, { marginTop: 1, flexDirection: "column" },
44
- React.createElement(Text, { bold: true, color: "red" }, "Main Blockers:"),
45
- aiReadiness.aiPerspective.mainBlockers.map((blocker, idx) => (React.createElement(Text, { key: idx, color: "red" },
46
- "\u2022 ",
47
- blocker)))))),
48
- React.createElement(Box, { flexDirection: "column", marginTop: 1 },
49
- React.createElement(Text, { bold: true, underline: true }, "\uD83C\uDFAF Dimension Scores"),
50
- Object.entries(aiReadiness.dimensions || {}).map(([key, dim]) => (React.createElement(Box, { key: key, flexDirection: "column", marginTop: 1 },
51
- React.createElement(Box, { justifyContent: "space-between" },
52
- React.createElement(Text, { bold: true, color: getStatusColor(dim.status) },
53
- getDimensionIcon(key),
54
- " ",
55
- formatDimensionName(key)),
56
- React.createElement(Text, { color: getStatusColor(dim.status) },
57
- Math.round(dim.score),
58
- "/100")),
59
- React.createElement(Box, { marginTop: 0.5 }, renderProgressBar(dim.score)),
60
- dim.recommendation && (React.createElement(Box, { marginTop: 0.5 },
61
- React.createElement(Text, { dimColor: true },
62
- "\u2192 ",
63
- dim.recommendation))))))),
64
- aiReadiness.quickWins && aiReadiness.quickWins.length > 0 && (React.createElement(Box, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 2, paddingY: 1, marginTop: 1 },
65
- React.createElement(Text, { bold: true, color: "yellow" }, "\u26A1 Quick Wins (High Impact, Low Effort)"),
66
- aiReadiness.quickWins.slice(0, 5).map((win, idx) => (React.createElement(Box, { key: idx, flexDirection: "column", marginTop: 1 },
67
- React.createElement(Text, { bold: true },
68
- idx + 1,
69
- ". ",
70
- win.issue),
71
- React.createElement(Text, { dimColor: true },
72
- "Impact: ",
73
- win.impact,
74
- " \u2022 Effort: ",
75
- win.effort),
76
- React.createElement(Text, { color: "cyan" },
77
- "\u2192 ",
78
- win.fix))))))));
79
- };
80
- function getDimensionIcon(key) {
81
- const icons = {
82
- technical: 'โš™๏ธ',
83
- contentQuality: '๐Ÿ“',
84
- crawlability: '๐Ÿ•ท๏ธ',
85
- discoverability: '๐Ÿ”',
86
- knowledge: '๐Ÿง ',
87
- extractability: '๐Ÿ”„',
88
- comprehensibility: '๐Ÿ’ก',
89
- trustworthiness: 'โœ…',
90
- accessibility: 'โ™ฟ',
91
- };
92
- return icons[key] || '๐Ÿ“Œ';
93
- }
94
- function formatDimensionName(key) {
95
- const names = {
96
- technical: 'Technical',
97
- contentQuality: 'Content Quality',
98
- crawlability: 'Crawlability',
99
- discoverability: 'Discoverability',
100
- knowledge: 'Knowledge',
101
- extractability: 'Extractability',
102
- comprehensibility: 'Comprehensibility',
103
- trustworthiness: 'Trustworthiness',
104
- accessibility: 'Accessibility',
105
- };
106
- return names[key] || key;
107
- }
@@ -1,8 +0,0 @@
1
- import React from 'react';
2
- interface ScoreDisplayProps {
3
- score: number;
4
- grade: string;
5
- url: string;
6
- }
7
- export declare const ScoreDisplay: React.FC<ScoreDisplayProps>;
8
- export {};
@@ -1,41 +0,0 @@
1
- import React from 'react';
2
- import { Box, Text } from 'ink';
3
- import Gradient from 'ink-gradient';
4
- import BigText from 'ink-big-text';
5
- export const ScoreDisplay = ({ score, grade, url }) => {
6
- const getGradeColor = (grade) => {
7
- if (grade.startsWith('A'))
8
- return 'green';
9
- if (grade.startsWith('B'))
10
- return 'blue';
11
- if (grade.startsWith('C'))
12
- return 'yellow';
13
- return 'red';
14
- };
15
- const getScoreMessage = (score) => {
16
- if (score >= 90)
17
- return { status: 'Excellent', message: 'Your site is AI-ready!', color: 'green' };
18
- if (score >= 80)
19
- return { status: 'Good', message: 'Your site works well with AI', color: 'blue' };
20
- if (score >= 70)
21
- return { status: 'Fair', message: 'Room for improvement', color: 'yellow' };
22
- if (score >= 60)
23
- return { status: 'Poor', message: 'Needs significant work', color: 'yellow' };
24
- return { status: 'Critical', message: 'Major issues detected', color: 'red' };
25
- };
26
- const { status, message, color } = getScoreMessage(score);
27
- return (React.createElement(Box, { flexDirection: "column", paddingY: 1 },
28
- React.createElement(Box, { marginBottom: 1 },
29
- React.createElement(Gradient, { name: "rainbow" },
30
- React.createElement(BigText, { text: `${score}`, font: "block" }))),
31
- React.createElement(Box, { marginBottom: 1 },
32
- React.createElement(Text, { bold: true, color: getGradeColor(grade) },
33
- "Grade: ",
34
- grade,
35
- " \u2022 ",
36
- status)),
37
- React.createElement(Box, { marginBottom: 1 },
38
- React.createElement(Text, { dimColor: true }, url)),
39
- React.createElement(Box, { borderStyle: "round", borderColor: color, paddingX: 2, paddingY: 1 },
40
- React.createElement(Text, { color: color }, message))));
41
- };
@@ -1,7 +0,0 @@
1
- import React from 'react';
2
- interface TechnicalSectionProps {
3
- result: any;
4
- scoring: any;
5
- }
6
- export declare const TechnicalSection: React.FC<TechnicalSectionProps>;
7
- export {};
@@ -1,110 +0,0 @@
1
- import React from 'react';
2
- import { Box, Text } from 'ink';
3
- export const TechnicalSection = ({ result, scoring }) => {
4
- const renderProgressBar = (score, width = 20) => {
5
- const filled = Math.round((score / 100) * width);
6
- const empty = width - filled;
7
- const color = score >= 80 ? 'green' : score >= 60 ? 'yellow' : 'red';
8
- return (React.createElement(Text, { color: color },
9
- 'โ–ˆ'.repeat(filled),
10
- React.createElement(Text, { dimColor: true }, 'โ–‘'.repeat(empty)),
11
- ` ${Math.round(score)}%`));
12
- };
13
- return (React.createElement(Box, { flexDirection: "column", paddingY: 1 },
14
- React.createElement(Box, { flexDirection: "column", borderStyle: "round", borderColor: "blue", paddingX: 2, paddingY: 1, marginBottom: 1 },
15
- React.createElement(Text, { bold: true, color: "blue" }, "\uD83D\uDCCA Category Scores"),
16
- React.createElement(Box, { marginTop: 1, flexDirection: "column" },
17
- scoring?.crawlability !== undefined && (React.createElement(Box, { flexDirection: "column", marginTop: 0.5 },
18
- React.createElement(Box, { justifyContent: "space-between" },
19
- React.createElement(Text, { bold: true }, "\uD83D\uDD77\uFE0F Crawlability"),
20
- React.createElement(Text, null,
21
- Math.round(scoring.crawlability),
22
- "/100")),
23
- React.createElement(Box, { marginTop: 0.5 }, renderProgressBar(scoring.crawlability)))),
24
- scoring?.structure !== undefined && (React.createElement(Box, { flexDirection: "column", marginTop: 1 },
25
- React.createElement(Box, { justifyContent: "space-between" },
26
- React.createElement(Text, { bold: true }, "\uD83D\uDCD0 Structure"),
27
- React.createElement(Text, null,
28
- Math.round(scoring.structure),
29
- "/100")),
30
- React.createElement(Box, { marginTop: 0.5 }, renderProgressBar(scoring.structure)))),
31
- scoring?.schema_coverage !== undefined && (React.createElement(Box, { flexDirection: "column", marginTop: 1 },
32
- React.createElement(Box, { justifyContent: "space-between" },
33
- React.createElement(Text, { bold: true }, "\uD83C\uDFF7\uFE0F Schema Coverage"),
34
- React.createElement(Text, null,
35
- Math.round(scoring.schema_coverage),
36
- "/100")),
37
- React.createElement(Box, { marginTop: 0.5 }, renderProgressBar(scoring.schema_coverage)))),
38
- scoring?.content_clarity !== undefined && (React.createElement(Box, { flexDirection: "column", marginTop: 1 },
39
- React.createElement(Box, { justifyContent: "space-between" },
40
- React.createElement(Text, { bold: true }, "\uD83D\uDCDD Content Clarity"),
41
- React.createElement(Text, null,
42
- Math.round(scoring.content_clarity),
43
- "/100")),
44
- React.createElement(Box, { marginTop: 0.5 }, renderProgressBar(scoring.content_clarity)))))),
45
- result.chunking && Object.keys(result.chunking).length > 0 ? (React.createElement(Box, { flexDirection: "column", borderStyle: "round", borderColor: "green", paddingX: 2, paddingY: 1, marginBottom: 1 },
46
- React.createElement(Text, { bold: true, color: "green" }, "\uD83D\uDCC4 Content Chunking Analysis"),
47
- React.createElement(Box, { marginTop: 1, flexDirection: "column" },
48
- React.createElement(Text, null,
49
- React.createElement(Text, { bold: true }, "Strategy:"),
50
- " ",
51
- result.chunking.chunkingStrategy),
52
- React.createElement(Text, null,
53
- React.createElement(Text, { bold: true }, "Total Chunks:"),
54
- " ",
55
- result.chunking.totalChunks),
56
- React.createElement(Text, null,
57
- React.createElement(Text, { bold: true }, "Avg Tokens/Chunk:"),
58
- " ",
59
- result.chunking.averageTokensPerChunk),
60
- React.createElement(Text, null,
61
- React.createElement(Text, { bold: true }, "Avg Noise Ratio:"),
62
- " ",
63
- (result.chunking.averageNoiseRatio * 100).toFixed(1),
64
- "%")),
65
- result.chunking.chunkingStrategy === 'heading-based' && (React.createElement(Box, { marginTop: 1 },
66
- React.createElement(Text, { color: "green" }, "\u2713 Heading-based chunking is ideal for AI comprehension"))),
67
- result.chunking.chunkingStrategy === 'paragraph-based' && (React.createElement(Box, { marginTop: 1 },
68
- React.createElement(Text, { color: "yellow" }, "\u26A0 Consider adding headings for better semantic structure"))))) : (React.createElement(Box, { flexDirection: "column", borderStyle: "round", borderColor: "gray", paddingX: 2, paddingY: 1, marginBottom: 1 },
69
- React.createElement(Text, { dimColor: true }, "\uD83D\uDCA1 Enable chunking analysis with --enable-chunking to see how your content is divided for AI processing"))),
70
- result.extractability && Object.keys(result.extractability).length > 0 ? (React.createElement(Box, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 2, paddingY: 1, marginBottom: 1 },
71
- React.createElement(Text, { bold: true, color: "yellow" }, "\uD83D\uDD04 Extractability Analysis"),
72
- React.createElement(Box, { marginTop: 1, flexDirection: "column" },
73
- React.createElement(Text, null,
74
- React.createElement(Text, { bold: true }, "Overall Score:"),
75
- " ",
76
- result.extractability.score.extractabilityScore,
77
- "/100"),
78
- React.createElement(Text, null,
79
- React.createElement(Text, { bold: true }, "Server-Rendered:"),
80
- " ",
81
- result.extractability.score.serverRenderedPercent,
82
- "%")),
83
- React.createElement(Box, { marginTop: 1, flexDirection: "column" },
84
- React.createElement(Text, { bold: true, underline: true }, "Content Type Extractability:"),
85
- Object.entries(result.extractability.contentTypes).map(([type, data]) => {
86
- const percentage = data.percentage;
87
- const color = percentage >= 80 ? 'green' : percentage >= 50 ? 'yellow' : 'red';
88
- return (React.createElement(Box, { key: type, marginTop: 0.5 },
89
- React.createElement(Text, null,
90
- React.createElement(Text, { bold: true },
91
- type.charAt(0).toUpperCase() + type.slice(1),
92
- ":"),
93
- ' ',
94
- React.createElement(Text, { color: color },
95
- percentage,
96
- "%"),
97
- ' ',
98
- React.createElement(Text, { dimColor: true },
99
- "(",
100
- data.extractable,
101
- "/",
102
- data.total,
103
- ")"))));
104
- })),
105
- result.extractability.score.extractabilityScore >= 80 && (React.createElement(Box, { marginTop: 1 },
106
- React.createElement(Text, { color: "green" }, "\u2713 Good extractability - AI can easily read your content"))),
107
- result.extractability.score.extractabilityScore < 50 && (React.createElement(Box, { marginTop: 1 },
108
- React.createElement(Text, { color: "red" }, "\u26A0 Low extractability - Consider server-side rendering"))))) : (React.createElement(Box, { flexDirection: "column", borderStyle: "round", borderColor: "gray", paddingX: 2, paddingY: 1, marginBottom: 1 },
109
- React.createElement(Text, { dimColor: true }, "\uD83D\uDCA1 Enable extractability analysis with --enable-extractability to see how well AI can extract your content")))));
110
- };
@@ -1,5 +0,0 @@
1
- /**
2
- * Comprehensive CLI formatter that displays all data shown on the website
3
- */
4
- export declare function formatComprehensiveReport(result: any, aiReadiness: any): string;
5
- export declare function formatDetailedIssues(issues: any[]): string;
@@ -1,370 +0,0 @@
1
- import chalk from 'chalk';
2
- /**
3
- * Comprehensive CLI formatter that displays all data shown on the website
4
- */
5
- export function formatComprehensiveReport(result, aiReadiness) {
6
- const sections = [];
7
- // LLM/AI Understanding Section
8
- if (result.llm) {
9
- sections.push(formatLLMSection(result.llm));
10
- }
11
- // Chunking Section
12
- if (result.chunking) {
13
- sections.push(formatChunkingSection(result.chunking));
14
- }
15
- // Extractability Section
16
- if (result.extractability) {
17
- sections.push(formatExtractabilitySection(result.extractability));
18
- }
19
- // Hallucination Risk Section
20
- if (result.hallucinationReport) {
21
- sections.push(formatHallucinationSection(result.hallucinationReport));
22
- }
23
- // Mirror Report Section
24
- if (result.mirrorReport) {
25
- sections.push(formatMirrorReportSection(result.mirrorReport));
26
- }
27
- // Dimension Scores
28
- if (aiReadiness?.dimensions) {
29
- sections.push(formatDimensionsSection(aiReadiness.dimensions));
30
- }
31
- // Quick Wins
32
- if (aiReadiness?.quickWins && aiReadiness.quickWins.length > 0) {
33
- sections.push(formatQuickWinsSection(aiReadiness.quickWins));
34
- }
35
- return sections.join('\n\n');
36
- }
37
- function formatLLMSection(llm) {
38
- const lines = [];
39
- lines.push(chalk.bold.blue('๐Ÿ“ AI Understanding Analysis'));
40
- lines.push('โ”€'.repeat(70));
41
- if (llm.summary) {
42
- lines.push(chalk.bold('Summary:'));
43
- lines.push(` ${llm.summary}`);
44
- lines.push('');
45
- }
46
- if (llm.pageType) {
47
- lines.push(chalk.bold('Inferred Page Type:'));
48
- lines.push(` ${chalk.magenta.bold(llm.pageType)}`);
49
- if (llm.pageTypeInsights && llm.pageTypeInsights.length > 0) {
50
- lines.push('');
51
- lines.push(chalk.bold('๐Ÿ’ก AI-Generated Insights:'));
52
- llm.pageTypeInsights.forEach((insight) => {
53
- lines.push(` ${chalk.cyan('โ€ข')} ${insight}`);
54
- });
55
- }
56
- lines.push('');
57
- }
58
- if (llm.keyTopics && llm.keyTopics.length > 0) {
59
- lines.push(chalk.bold('Key Topics:'));
60
- lines.push(` ${llm.keyTopics.map((t) => chalk.blue(t)).join(', ')}`);
61
- lines.push('');
62
- }
63
- const metadata = [];
64
- if (llm.readingLevel) {
65
- metadata.push(`Reading Level: ${llm.readingLevel.description}`);
66
- }
67
- if (llm.sentiment) {
68
- metadata.push(`Sentiment: ${llm.sentiment}`);
69
- }
70
- if (llm.technicalDepth) {
71
- metadata.push(`Technical Depth: ${llm.technicalDepth}`);
72
- }
73
- if (metadata.length > 0) {
74
- lines.push(chalk.bold('Metadata:'));
75
- metadata.forEach(m => lines.push(` ${m}`));
76
- lines.push('');
77
- }
78
- if (llm.topEntities && llm.topEntities.length > 0) {
79
- lines.push(chalk.bold('๐Ÿ” Key Entities:'));
80
- llm.topEntities.slice(0, 5).forEach((entity) => {
81
- const relevance = entity.relevance ? ` - ${Math.round(entity.relevance * 100)}% relevance` : '';
82
- lines.push(` ${chalk.cyan('โ€ข')} ${chalk.bold(entity.name)} ${chalk.dim(`(${entity.type})${relevance}`)}`);
83
- });
84
- lines.push('');
85
- }
86
- if (llm.questions && llm.questions.length > 0) {
87
- lines.push(chalk.bold('โ“ Questions AI Can Answer:'));
88
- llm.questions.slice(0, 5).forEach((q, idx) => {
89
- const difficulty = chalk.dim(`[${q.difficulty.toUpperCase()}]`);
90
- lines.push(` ${idx + 1}. ${difficulty} ${q.question}`);
91
- });
92
- lines.push('');
93
- }
94
- if (llm.suggestedFAQ && llm.suggestedFAQ.length > 0) {
95
- lines.push(chalk.bold('๐Ÿ’ก Suggested FAQs:'));
96
- llm.suggestedFAQ
97
- .filter((f) => f.importance === 'high')
98
- .slice(0, 3)
99
- .forEach((faq, idx) => {
100
- lines.push(` ${idx + 1}. Q: ${chalk.yellow(faq.question)}`);
101
- lines.push(` A: ${chalk.dim(faq.suggestedAnswer)}`);
102
- });
103
- }
104
- return lines.join('\n');
105
- }
106
- function formatChunkingSection(chunking) {
107
- const lines = [];
108
- lines.push(chalk.bold.green('๐Ÿ“„ Content Chunking Analysis'));
109
- lines.push('โ”€'.repeat(70));
110
- const grid = [
111
- ['Strategy', chunking.chunkingStrategy],
112
- ['Total Chunks', chunking.totalChunks.toString()],
113
- ['Avg Tokens/Chunk', chunking.averageTokensPerChunk.toString()],
114
- ['Avg Noise Ratio', `${(chunking.averageNoiseRatio * 100).toFixed(1)}%`],
115
- ];
116
- grid.forEach(([label, value]) => {
117
- lines.push(` ${chalk.bold(label + ':').padEnd(25)} ${chalk.cyan(value)}`);
118
- });
119
- if (chunking.chunkingStrategy === 'heading-based') {
120
- lines.push('');
121
- lines.push(chalk.green(' โœ“ Heading-based chunking is ideal for AI comprehension'));
122
- }
123
- else if (chunking.chunkingStrategy === 'paragraph-based') {
124
- lines.push('');
125
- lines.push(chalk.yellow(' โš  Consider adding headings for better semantic structure'));
126
- }
127
- if (chunking.chunks && chunking.chunks.length > 0) {
128
- lines.push('');
129
- lines.push(chalk.bold('Chunk Distribution:'));
130
- // Show token distribution
131
- const tokenCounts = chunking.chunks.map((c) => c.tokenCount);
132
- const min = Math.min(...tokenCounts);
133
- const max = Math.max(...tokenCounts);
134
- const avg = tokenCounts.reduce((a, b) => a + b, 0) / tokenCounts.length;
135
- lines.push(` Min Tokens: ${min}, Max Tokens: ${max}, Avg: ${avg.toFixed(0)}`);
136
- // Show noise distribution
137
- const noiseRatios = chunking.chunks.map((c) => c.noiseRatio);
138
- const avgNoise = noiseRatios.reduce((a, b) => a + b, 0) / noiseRatios.length;
139
- lines.push(` Avg Noise per Chunk: ${(avgNoise * 100).toFixed(1)}%`);
140
- }
141
- return lines.join('\n');
142
- }
143
- function formatExtractabilitySection(extractability) {
144
- const lines = [];
145
- lines.push(chalk.bold.yellow('๐Ÿ”„ Extractability Analysis'));
146
- lines.push('โ”€'.repeat(70));
147
- const grid = [
148
- ['Overall Score', `${extractability.score.extractabilityScore}/100`],
149
- ['Server-Rendered', `${extractability.score.serverRenderedPercent}%`],
150
- ];
151
- grid.forEach(([label, value]) => {
152
- lines.push(` ${chalk.bold(label + ':').padEnd(25)} ${chalk.cyan(value)}`);
153
- });
154
- lines.push('');
155
- lines.push(chalk.bold('Content Type Extractability:'));
156
- Object.entries(extractability.contentTypes).forEach(([type, data]) => {
157
- const percentage = data.percentage;
158
- const color = percentage >= 80 ? chalk.green : percentage >= 50 ? chalk.yellow : chalk.red;
159
- lines.push(` ${chalk.bold(type.charAt(0).toUpperCase() + type.slice(1) + ':').padEnd(15)} ${color(`${percentage}%`)} (${data.extractable}/${data.total})`);
160
- });
161
- const overallScore = extractability.score.extractabilityScore;
162
- if (overallScore >= 80) {
163
- lines.push('');
164
- lines.push(chalk.green(' โœ“ Good extractability - AI can easily read your content'));
165
- }
166
- else if (overallScore < 50) {
167
- lines.push('');
168
- lines.push(chalk.red(' โš  Low extractability - Consider server-side rendering'));
169
- }
170
- return lines.join('\n');
171
- }
172
- function formatHallucinationSection(report) {
173
- const lines = [];
174
- lines.push(chalk.bold.red('โš ๏ธ Hallucination Risk Assessment'));
175
- lines.push('โ”€'.repeat(70));
176
- const riskScore = report.hallucinationRiskScore;
177
- const riskColor = riskScore >= 70 ? chalk.red : riskScore >= 40 ? chalk.yellow : chalk.green;
178
- lines.push(` ${chalk.bold('Risk Score:')} ${riskColor.bold(`${riskScore}/100`)}`);
179
- if (report.factCheckSummary) {
180
- lines.push('');
181
- lines.push(chalk.bold('Fact Check Summary:'));
182
- const summary = report.factCheckSummary;
183
- lines.push(` Total Facts: ${chalk.cyan(summary.totalFacts)}`);
184
- lines.push(` Verified: ${chalk.green(summary.verifiedFacts)}`);
185
- lines.push(` Unverified: ${chalk.yellow(summary.unverifiedFacts)}`);
186
- lines.push(` Contradictions: ${chalk.red(summary.contradictions)}`);
187
- if (summary.ambiguities !== undefined) {
188
- lines.push(` Ambiguities: ${chalk.yellow(summary.ambiguities)}`);
189
- }
190
- }
191
- if (report.factCheckSummary && report.factCheckSummary.unverifiedFacts > 0) {
192
- lines.push('');
193
- lines.push(chalk.yellow('๐Ÿ’ก Tip: Add citations and links to verify claims and reduce AI hallucination risk'));
194
- }
195
- if (report.triggers && report.triggers.length > 0) {
196
- const highSeverityTriggers = report.triggers.filter((t) => t.severity === 'high' || t.severity === 'critical');
197
- if (highSeverityTriggers.length > 0) {
198
- lines.push('');
199
- lines.push(chalk.bold('๐Ÿšจ High-Risk Triggers:'));
200
- highSeverityTriggers.slice(0, 5).forEach((trigger, idx) => {
201
- lines.push(` ${idx + 1}. ${chalk.red(`[${trigger.severity.toUpperCase()}]`)} ${trigger.type}`);
202
- lines.push(` ${chalk.dim(trigger.description)}`);
203
- if (trigger.confidence) {
204
- lines.push(` ${chalk.dim(`Confidence: ${Math.round(trigger.confidence * 100)}%`)}`);
205
- }
206
- });
207
- }
208
- }
209
- if (report.recommendations && report.recommendations.length > 0) {
210
- lines.push('');
211
- lines.push(chalk.bold('๐Ÿ’ก Recommendations:'));
212
- report.recommendations.slice(0, 3).forEach((rec, idx) => {
213
- lines.push(` ${idx + 1}. ${rec}`);
214
- });
215
- }
216
- return lines.join('\n');
217
- }
218
- function formatMirrorReportSection(report) {
219
- const lines = [];
220
- lines.push(chalk.bold.magenta('๐Ÿ” AI Misunderstanding Check'));
221
- lines.push('โ”€'.repeat(70));
222
- const alignmentColor = report.summary.alignmentScore >= 80 ? chalk.green :
223
- report.summary.alignmentScore >= 60 ? chalk.yellow : chalk.red;
224
- const clarityColor = report.summary.clarityScore >= 80 ? chalk.green :
225
- report.summary.clarityScore >= 60 ? chalk.yellow : chalk.red;
226
- lines.push(` ${chalk.bold('Alignment Score:').padEnd(25)} ${alignmentColor.bold(`${report.summary.alignmentScore}/100`)}`);
227
- lines.push(` ${chalk.bold('Clarity Score:').padEnd(25)} ${clarityColor.bold(`${report.summary.clarityScore}/100`)}`);
228
- lines.push(` ${chalk.bold('Critical Issues:').padEnd(25)} ${chalk.red(report.summary.critical)}`);
229
- lines.push(` ${chalk.bold('Major Issues:').padEnd(25)} ${chalk.yellow(report.summary.major)}`);
230
- // AI Interpretation - What AI Actually Understood
231
- if (report.llmInterpretation) {
232
- lines.push('');
233
- lines.push(chalk.bold.blue('๐Ÿค– What AI Actually Understood'));
234
- lines.push(chalk.dim(` (${Math.round(report.llmInterpretation.confidence * 100)}% confident)`));
235
- if (report.llmInterpretation.productName) {
236
- lines.push(` ${chalk.bold('Product:')} ${report.llmInterpretation.productName}`);
237
- }
238
- if (report.llmInterpretation.purpose) {
239
- lines.push(` ${chalk.bold('Purpose:')} ${report.llmInterpretation.purpose}`);
240
- }
241
- if (report.llmInterpretation.valueProposition) {
242
- lines.push(` ${chalk.bold.magenta('๐Ÿ’Ž Value:')} ${report.llmInterpretation.valueProposition}`);
243
- }
244
- if (report.llmInterpretation.keyBenefits && report.llmInterpretation.keyBenefits.length > 0) {
245
- lines.push(` ${chalk.bold('Benefits:')}`);
246
- report.llmInterpretation.keyBenefits.forEach((benefit) => {
247
- lines.push(` โ€ข ${benefit}`);
248
- });
249
- }
250
- if (report.llmInterpretation.keyFeatures && report.llmInterpretation.keyFeatures.length > 0) {
251
- lines.push(` ${chalk.bold('Features:')}`);
252
- report.llmInterpretation.keyFeatures.slice(0, 3).forEach((feature) => {
253
- lines.push(` โ€ข ${feature}`);
254
- });
255
- }
256
- if (report.llmInterpretation.targetAudience) {
257
- lines.push(` ${chalk.bold('Audience:')} ${report.llmInterpretation.targetAudience}`);
258
- }
259
- }
260
- if (report.mismatches && report.mismatches.length > 0) {
261
- const priorityMismatches = report.mismatches.filter((m) => m.severity === 'critical' || m.severity === 'major');
262
- if (priorityMismatches.length > 0) {
263
- lines.push('');
264
- lines.push(chalk.bold('Priority Mismatches:'));
265
- priorityMismatches.slice(0, 5).forEach((mismatch, idx) => {
266
- const icon = mismatch.severity === 'critical' ? '๐Ÿ”ด' : '๐ŸŸก';
267
- lines.push(` ${icon} ${idx + 1}. ${chalk.bold(mismatch.field)}`);
268
- lines.push(` ${chalk.dim(mismatch.description)}`);
269
- lines.push(` ${chalk.cyan('โ†’')} ${mismatch.recommendation}`);
270
- });
271
- }
272
- }
273
- if (report.recommendations && report.recommendations.length > 0) {
274
- lines.push('');
275
- lines.push(chalk.bold('๐Ÿ’ก Top Recommendations:'));
276
- report.recommendations.slice(0, 3).forEach((rec, idx) => {
277
- lines.push(` ${idx + 1}. ${rec}`);
278
- });
279
- }
280
- return lines.join('\n');
281
- }
282
- function formatDimensionsSection(dimensions) {
283
- const lines = [];
284
- lines.push(chalk.bold.cyan('๐ŸŽฏ Dimension Analysis'));
285
- lines.push('โ”€'.repeat(70));
286
- const dimensionDescriptions = {
287
- technical: 'โš™๏ธ Technical',
288
- contentQuality: '๐Ÿ“ Content Quality',
289
- crawlability: '๐Ÿ•ท๏ธ Crawlability',
290
- discoverability: '๐Ÿ” Discoverability',
291
- knowledge: '๐Ÿง  Knowledge',
292
- extractability: '๐Ÿ”„ Extractability',
293
- comprehensibility: '๐Ÿ’ก Comprehensibility',
294
- trustworthiness: 'โœ… Trustworthiness',
295
- accessibility: 'โ™ฟ Accessibility',
296
- };
297
- Object.entries(dimensions).forEach(([key, dim]) => {
298
- const name = dimensionDescriptions[key] || key;
299
- const scoreColor = dim.score >= 90 ? chalk.green :
300
- dim.score >= 75 ? chalk.yellow :
301
- dim.score >= 60 ? chalk.hex('#FFA500') : chalk.red;
302
- lines.push('');
303
- lines.push(`${name}: ${scoreColor.bold(`${Math.round(dim.score)}/100`)} ${chalk.dim(`(${dim.status})`)}`);
304
- if (dim.strengths && dim.strengths.length > 0) {
305
- lines.push(` ${chalk.green('Strengths:')} ${dim.strengths.join(', ')}`);
306
- }
307
- if (dim.weaknesses && dim.weaknesses.length > 0) {
308
- lines.push(` ${chalk.yellow('Weaknesses:')} ${dim.weaknesses.join(', ')}`);
309
- }
310
- if (dim.recommendation) {
311
- lines.push(` ${chalk.cyan('โ†’')} ${dim.recommendation}`);
312
- }
313
- });
314
- return lines.join('\n');
315
- }
316
- function formatQuickWinsSection(quickWins) {
317
- const lines = [];
318
- lines.push(chalk.bold.yellow('โšก Quick Wins (High Impact, Low Effort)'));
319
- lines.push('โ”€'.repeat(70));
320
- quickWins.slice(0, 5).forEach((win, idx) => {
321
- lines.push('');
322
- lines.push(`${chalk.bold(`${idx + 1}.`)} ${chalk.yellow(win.issue)}`);
323
- lines.push(` ${chalk.dim(`Impact: ${win.impact} ยท Effort: ${win.effort}`)}`);
324
- lines.push(` ${chalk.cyan('โ†’')} ${win.fix}`);
325
- });
326
- return lines.join('\n');
327
- }
328
- export function formatDetailedIssues(issues) {
329
- const lines = [];
330
- lines.push(chalk.bold('โš ๏ธ All Issues'));
331
- lines.push('โ”€'.repeat(70));
332
- // Group by severity
333
- const grouped = {
334
- critical: issues.filter(i => i.severity === 'critical'),
335
- high: issues.filter(i => i.severity === 'high'),
336
- medium: issues.filter(i => i.severity === 'medium'),
337
- low: issues.filter(i => i.severity === 'low'),
338
- };
339
- // Stats
340
- lines.push('');
341
- lines.push(chalk.bold('Issue Count by Severity:'));
342
- lines.push(` Critical: ${chalk.red.bold(grouped.critical.length)}`);
343
- lines.push(` High: ${chalk.yellow.bold(grouped.high.length)}`);
344
- lines.push(` Medium: ${chalk.blue.bold(grouped.medium.length)}`);
345
- lines.push(` Low: ${chalk.dim(grouped.low.length)}`);
346
- // Show all issues by severity
347
- for (const [severity, severityIssues] of Object.entries(grouped)) {
348
- if (severityIssues.length === 0)
349
- continue;
350
- lines.push('');
351
- lines.push(chalk.bold(`${severity.toUpperCase()} Issues:`));
352
- severityIssues.forEach((issue, idx) => {
353
- const icon = severity === 'critical' ? '๐Ÿ”ด' :
354
- severity === 'high' ? '๐ŸŸ ' :
355
- severity === 'medium' ? '๐ŸŸก' : '๐Ÿ”ต';
356
- lines.push('');
357
- lines.push(`${icon} ${idx + 1}. ${chalk.bold(issue.message || issue.title)}`);
358
- lines.push(` ${chalk.dim(`Category: ${issue.category} ยท Impact: ${issue.impact}`)}`);
359
- if (issue.evidence) {
360
- const evidenceText = typeof issue.evidence === 'string' ? issue.evidence : issue.evidence.join(', ');
361
- lines.push(` ${chalk.dim(evidenceText.substring(0, 100))}${evidenceText.length > 100 ? '...' : ''}`);
362
- }
363
- if (issue.element) {
364
- lines.push(` ${chalk.dim(issue.element.substring(0, 100))}${issue.element.length > 100 ? '...' : ''}`);
365
- }
366
- lines.push(` ${chalk.cyan('๐Ÿ’ก Fix:')} ${issue.suggested_fix || issue.remediation}`);
367
- });
368
- }
369
- return lines.join('\n');
370
- }