@ai-lighthouse/cli 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.
Files changed (103) hide show
  1. package/.ai-lighthouse/audit_example.com_2025-12-15T12-10-43.json +183 -0
  2. package/.ai-lighthouse/audit_fayeed.dev_2026-01-07T19-32-28.html +743 -0
  3. package/.ai-lighthouse/audit_fayeed.dev_2026-01-07T19-33-02.html +757 -0
  4. package/.ai-lighthouse/audit_github.com_2025-12-15T11-53-21.json +168 -0
  5. package/.ai-lighthouse/audit_github.com_2025-12-15T12-04-06.json +168 -0
  6. package/.ai-lighthouse/audit_github.com_2025-12-15T12-05-10.json +168 -0
  7. package/.ai-lighthouse/audit_github.com_2025-12-15T12-09-45.json +168 -0
  8. package/.ai-lighthouse/audit_github.com_2025-12-15T12-11-07.json +168 -0
  9. package/.ai-lighthouse/audit_github.com_2025-12-15T12-13-28.json +168 -0
  10. package/.ai-lighthouse/audit_github.com_2025-12-15T12-14-59.json +205 -0
  11. package/.ai-lighthouse/audit_github.com_2025-12-15T12-18-07.json +205 -0
  12. package/.ai-lighthouse/audit_github.com_2025-12-15T12-18-44.json +205 -0
  13. package/.ai-lighthouse/audit_github.com_2025-12-15T12-21-38.json +205 -0
  14. package/.ai-lighthouse/audit_github.com_2025-12-15T12-22-21.json +205 -0
  15. package/.ai-lighthouse/audit_github.com_2025-12-15T12-22-46.json +205 -0
  16. package/.ai-lighthouse/audit_github.com_2025-12-15T12-23-18.json +205 -0
  17. package/.ai-lighthouse/audit_github.com_2025-12-15T12-24-43.json +205 -0
  18. package/.ai-lighthouse/audit_github.com_2025-12-17T12-15-08.json +168 -0
  19. package/.ai-lighthouse/audit_github.com_2025-12-17T12-15-57.json +168 -0
  20. package/.ai-lighthouse/audit_github.com_2025-12-17T12-17-11.json +168 -0
  21. package/.ai-lighthouse/audit_github.com_2025-12-17T12-22-17.json +168 -0
  22. package/.ai-lighthouse/audit_github.com_2025-12-17T12-22-42.json +168 -0
  23. package/.ai-lighthouse/audit_github.com_2025-12-17T12-23-56.json +168 -0
  24. package/.ai-lighthouse/audit_github.com_2025-12-17T12-25-24.json +168 -0
  25. package/.ai-lighthouse/audit_github.com_2025-12-17T12-25-40.json +168 -0
  26. package/.ai-lighthouse/audit_github.com_2025-12-17T12-27-02.json +168 -0
  27. package/.ai-lighthouse/audit_github.com_2025-12-17T12-27-20.json +168 -0
  28. package/.ai-lighthouse/audit_github.com_2025-12-17T12-29-56.json +168 -0
  29. package/.ai-lighthouse/audit_github.com_2025-12-17T12-32-27.json +168 -0
  30. package/.ai-lighthouse/audit_github.com_2025-12-17T12-33-00.json +168 -0
  31. package/.ai-lighthouse/audit_github.com_2025-12-17T12-34-49.json +168 -0
  32. package/.ai-lighthouse/audit_stripe.com_2025-12-15T12-11-31.json +168 -0
  33. package/.ai-lighthouse/audit_stripe.com_2025-12-15T12-11-45.json +168 -0
  34. package/.ai-lighthouse/audit_tailwindcss.com_2025-12-15T12-12-01.json +169 -0
  35. package/.ai-lighthouse/crawl_example.com_2025-12-15T12-03-08.json +24 -0
  36. package/.ai-lighthouse/crawl_example.com_2025-12-15T12-03-23.json +24 -0
  37. package/.ai-lighthouse/crawl_github.com_2025-12-15T11-41-34.json +21 -0
  38. package/.ai-lighthouse/crawl_github.com_2025-12-15T11-42-09.json +21 -0
  39. package/.ai-lighthouse/crawl_github.com_2025-12-15T11-42-45.json +21 -0
  40. package/.ai-lighthouse/crawl_github.com_2025-12-15T11-43-02.json +21 -0
  41. package/.ai-lighthouse/crawl_github.com_2025-12-15T11-43-26.json +21 -0
  42. package/.ai-lighthouse/crawl_github.com_2025-12-15T11-47-46.json +906 -0
  43. package/.ai-lighthouse/crawl_github.com_2025-12-15T11-50-27.json +906 -0
  44. package/.ai-lighthouse/crawl_github.com_2025-12-15T11-52-59.json +906 -0
  45. package/.ai-lighthouse/crawl_github.com_2025-12-15T12-03-33.json +28 -0
  46. package/CLI_UI_README.md +211 -0
  47. package/EXAMPLES.md +87 -0
  48. package/IMPLEMENTATION.md +215 -0
  49. package/README.md +166 -0
  50. package/USAGE.md +264 -0
  51. package/WIZARD_GUIDE.md +340 -0
  52. package/bin/cli.js +2 -0
  53. package/dist/commands/audit-interactive.d.ts +2 -0
  54. package/dist/commands/audit-interactive.js +106 -0
  55. package/dist/commands/audit-wizard.d.ts +2 -0
  56. package/dist/commands/audit-wizard.js +110 -0
  57. package/dist/commands/audit.d.ts +2 -0
  58. package/dist/commands/audit.js +940 -0
  59. package/dist/commands/crawl.d.ts +2 -0
  60. package/dist/commands/crawl.js +267 -0
  61. package/dist/commands/report.d.ts +2 -0
  62. package/dist/commands/report.js +304 -0
  63. package/dist/index.d.ts +1 -0
  64. package/dist/index.js +16 -0
  65. package/dist/ui/AuditReportUI.d.ts +10 -0
  66. package/dist/ui/AuditReportUI.js +76 -0
  67. package/dist/ui/SetupWizard.d.ts +18 -0
  68. package/dist/ui/SetupWizard.js +179 -0
  69. package/dist/ui/components/AIUnderstandingSection.d.ts +6 -0
  70. package/dist/ui/components/AIUnderstandingSection.js +87 -0
  71. package/dist/ui/components/HallucinationSection.d.ts +6 -0
  72. package/dist/ui/components/HallucinationSection.js +84 -0
  73. package/dist/ui/components/IssuesSection.d.ts +6 -0
  74. package/dist/ui/components/IssuesSection.js +84 -0
  75. package/dist/ui/components/MessageAlignmentSection.d.ts +6 -0
  76. package/dist/ui/components/MessageAlignmentSection.js +108 -0
  77. package/dist/ui/components/OverviewSection.d.ts +6 -0
  78. package/dist/ui/components/OverviewSection.js +107 -0
  79. package/dist/ui/components/ScoreDisplay.d.ts +8 -0
  80. package/dist/ui/components/ScoreDisplay.js +41 -0
  81. package/dist/ui/components/TechnicalSection.d.ts +7 -0
  82. package/dist/ui/components/TechnicalSection.js +110 -0
  83. package/dist/utils/comprehensive-formatter.d.ts +5 -0
  84. package/dist/utils/comprehensive-formatter.js +370 -0
  85. package/package.json +49 -0
  86. package/src/commands/audit-interactive.ts +149 -0
  87. package/src/commands/audit-wizard.ts +137 -0
  88. package/src/commands/audit.ts +1012 -0
  89. package/src/commands/crawl.ts +307 -0
  90. package/src/commands/report.ts +321 -0
  91. package/src/index.ts +22 -0
  92. package/src/ui/AuditReportUI.tsx +151 -0
  93. package/src/ui/SetupWizard.tsx +294 -0
  94. package/src/ui/components/AIUnderstandingSection.tsx +183 -0
  95. package/src/ui/components/HallucinationSection.tsx +172 -0
  96. package/src/ui/components/IssuesSection.tsx +140 -0
  97. package/src/ui/components/MessageAlignmentSection.tsx +203 -0
  98. package/src/ui/components/OverviewSection.tsx +157 -0
  99. package/src/ui/components/ScoreDisplay.tsx +58 -0
  100. package/src/ui/components/TechnicalSection.tsx +200 -0
  101. package/src/utils/comprehensive-formatter.ts +455 -0
  102. package/test.sh +31 -0
  103. package/tsconfig.json +25 -0
@@ -0,0 +1,76 @@
1
+ import React, { useState } from 'react';
2
+ import { Box, Text, useInput } from 'ink';
3
+ import Spinner from 'ink-spinner';
4
+ import { ScoreDisplay } from './components/ScoreDisplay.js';
5
+ import { OverviewSection } from './components/OverviewSection.js';
6
+ import { IssuesSection } from './components/IssuesSection.js';
7
+ import { AIUnderstandingSection } from './components/AIUnderstandingSection.js';
8
+ import { HallucinationSection } from './components/HallucinationSection.js';
9
+ import { MessageAlignmentSection } from './components/MessageAlignmentSection.js';
10
+ import { TechnicalSection } from './components/TechnicalSection.js';
11
+ export const AuditReportUI = ({ url, result, aiReadiness, loading = false, currentStep = '', }) => {
12
+ const [currentTab, setCurrentTab] = useState('overview');
13
+ const tabs = [
14
+ { key: 'overview', label: 'Overview', icon: '📊' },
15
+ { key: 'issues', label: 'Issues', icon: '⚠️' },
16
+ { key: 'ai-understanding', label: 'AI Understanding', icon: '🧠' },
17
+ { key: 'hallucination', label: 'Hallucination Risk', icon: '⚠️' },
18
+ { key: 'message-alignment', label: 'Message Alignment', icon: '🔍' },
19
+ { key: 'technical', label: 'Technical', icon: '⚙️' },
20
+ ];
21
+ useInput((input, key) => {
22
+ if (loading)
23
+ return;
24
+ if (key.leftArrow) {
25
+ const currentIndex = tabs.findIndex(t => t.key === currentTab);
26
+ const prevIndex = currentIndex > 0 ? currentIndex - 1 : tabs.length - 1;
27
+ setCurrentTab(tabs[prevIndex].key);
28
+ }
29
+ if (key.rightArrow) {
30
+ const currentIndex = tabs.findIndex(t => t.key === currentTab);
31
+ const nextIndex = currentIndex < tabs.length - 1 ? currentIndex + 1 : 0;
32
+ setCurrentTab(tabs[nextIndex].key);
33
+ }
34
+ // Number keys for quick tab switching
35
+ const num = parseInt(input);
36
+ if (num >= 1 && num <= tabs.length) {
37
+ setCurrentTab(tabs[num - 1].key);
38
+ }
39
+ });
40
+ if (loading) {
41
+ return (React.createElement(Box, { flexDirection: "column", paddingY: 1 },
42
+ React.createElement(Box, null,
43
+ React.createElement(Text, { color: "green" },
44
+ React.createElement(Spinner, { type: "dots" })),
45
+ React.createElement(Text, null,
46
+ " ",
47
+ currentStep || 'Loading...'))));
48
+ }
49
+ const overallScore = aiReadiness?.overall || 0;
50
+ const grade = aiReadiness?.grade || 'N/A';
51
+ return (React.createElement(Box, { flexDirection: "column" },
52
+ React.createElement(Box, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 2, paddingY: 1 },
53
+ React.createElement(Text, { bold: true, color: "cyan" }, "\uD83D\uDEA8 AI Lighthouse Report")),
54
+ React.createElement(ScoreDisplay, { score: overallScore, grade: grade, url: url }),
55
+ React.createElement(Box, { flexDirection: "row", borderStyle: "single", borderColor: "blue", paddingX: 1, marginTop: 1 }, tabs.map((tab, index) => {
56
+ const isActive = tab.key === currentTab;
57
+ return (React.createElement(Box, { key: tab.key, marginRight: 1 },
58
+ React.createElement(Text, { bold: isActive, color: isActive ? 'cyan' : 'gray', backgroundColor: isActive ? 'blue' : undefined }, ` ${index + 1}. ${tab.icon} ${tab.label} `)));
59
+ })),
60
+ React.createElement(Box, { marginTop: 1, marginBottom: 1 },
61
+ React.createElement(Text, { dimColor: true },
62
+ "Use \u2190 \u2192 arrow keys or numbers (1-",
63
+ tabs.length,
64
+ ") to navigate tabs")),
65
+ React.createElement(Box, { flexDirection: "column" },
66
+ currentTab === 'overview' && React.createElement(OverviewSection, { aiReadiness: aiReadiness }),
67
+ currentTab === 'issues' && React.createElement(IssuesSection, { issues: result.issues || [] }),
68
+ currentTab === 'ai-understanding' && React.createElement(AIUnderstandingSection, { llm: result.llm }),
69
+ currentTab === 'hallucination' && React.createElement(HallucinationSection, { hallucinationReport: result.hallucinationReport }),
70
+ currentTab === 'message-alignment' && React.createElement(MessageAlignmentSection, { mirrorReport: result.mirrorReport }),
71
+ currentTab === 'technical' && React.createElement(TechnicalSection, { result: result, scoring: result.scoring })),
72
+ React.createElement(Box, { marginTop: 2, borderStyle: "round", borderColor: "gray", paddingX: 2, paddingY: 1 },
73
+ React.createElement(Text, { dimColor: true },
74
+ "Press Ctrl+C to exit \u2022 Report generated at ",
75
+ new Date().toLocaleString()))));
76
+ };
@@ -0,0 +1,18 @@
1
+ import React from 'react';
2
+ interface SetupWizardProps {
3
+ onComplete: (config: AuditConfig) => void;
4
+ initialUrl?: string;
5
+ }
6
+ export interface AuditConfig {
7
+ url: string;
8
+ enableLlm: boolean;
9
+ enableChunking: boolean;
10
+ enableExtractability: boolean;
11
+ enableHallucination: boolean;
12
+ llmProvider?: string;
13
+ llmModel?: string;
14
+ llmApiKey?: string;
15
+ llmBaseUrl?: string;
16
+ }
17
+ export declare const SetupWizard: React.FC<SetupWizardProps>;
18
+ export {};
@@ -0,0 +1,179 @@
1
+ import React, { useState } from 'react';
2
+ import { Box, Text, useApp } from 'ink';
3
+ import TextInput from 'ink-text-input';
4
+ import SelectInput from 'ink-select-input';
5
+ export const SetupWizard = ({ onComplete, initialUrl }) => {
6
+ const { exit } = useApp();
7
+ const [step, setStep] = useState(initialUrl ? 'features' : 'url');
8
+ const [url, setUrl] = useState(initialUrl || '');
9
+ const [selectedFeatures, setSelectedFeatures] = useState([]);
10
+ const [llmProvider, setLlmProvider] = useState('');
11
+ const [llmModel, setLlmModel] = useState('');
12
+ const [llmApiKey, setLlmApiKey] = useState('');
13
+ const [llmBaseUrl, setLlmBaseUrl] = useState('');
14
+ const featureOptions = [
15
+ { label: '🧠 AI Understanding (LLM Analysis)', value: 'llm' },
16
+ { label: '📄 Content Chunking Analysis', value: 'chunking' },
17
+ { label: '🔄 Extractability Analysis', value: 'extractability' },
18
+ { label: '⚠️ Hallucination Detection', value: 'hallucination' },
19
+ { label: '✅ Continue with selected features', value: 'done' },
20
+ ];
21
+ const llmProviderOptions = [
22
+ { label: 'OpenAI (GPT-4, GPT-3.5)', value: 'openai' },
23
+ { label: 'Anthropic (Claude)', value: 'anthropic' },
24
+ { label: 'Ollama (Local)', value: 'ollama' },
25
+ { label: 'Custom/Local Provider', value: 'local' },
26
+ ];
27
+ const handleUrlSubmit = (value) => {
28
+ setUrl(value);
29
+ setStep('features');
30
+ };
31
+ const handleFeatureSelect = (item) => {
32
+ if (item.value === 'done') {
33
+ // Check if LLM is needed
34
+ if (selectedFeatures.includes('llm') || selectedFeatures.includes('hallucination')) {
35
+ setStep('llm-provider');
36
+ }
37
+ else {
38
+ completeSetup();
39
+ }
40
+ }
41
+ else {
42
+ // Toggle feature selection
43
+ if (selectedFeatures.includes(item.value)) {
44
+ setSelectedFeatures(selectedFeatures.filter(f => f !== item.value));
45
+ }
46
+ else {
47
+ setSelectedFeatures([...selectedFeatures, item.value]);
48
+ }
49
+ }
50
+ };
51
+ const handleLlmProviderSelect = (item) => {
52
+ setLlmProvider(item.value);
53
+ // Set default base URL for ollama
54
+ if (item.value === 'ollama') {
55
+ setLlmBaseUrl('http://localhost:11434');
56
+ }
57
+ setStep('llm-model');
58
+ };
59
+ const handleLlmModelSubmit = (value) => {
60
+ setLlmModel(value);
61
+ // If ollama, skip API key and go to base URL
62
+ if (llmProvider === 'ollama') {
63
+ setStep('llm-base-url');
64
+ }
65
+ else {
66
+ setStep('llm-api-key');
67
+ }
68
+ };
69
+ const handleLlmApiKeySubmit = (value) => {
70
+ setLlmApiKey(value);
71
+ // If provider needs base URL, go there, otherwise complete
72
+ if (llmProvider === 'local' || llmProvider === 'anthropic') {
73
+ setStep('llm-base-url');
74
+ }
75
+ else {
76
+ completeSetup();
77
+ }
78
+ };
79
+ const handleLlmBaseUrlSubmit = (value) => {
80
+ setLlmBaseUrl(value);
81
+ completeSetup();
82
+ };
83
+ const completeSetup = () => {
84
+ const config = {
85
+ url,
86
+ enableLlm: selectedFeatures.includes('llm') || selectedFeatures.includes('hallucination'),
87
+ enableChunking: selectedFeatures.includes('chunking'),
88
+ enableExtractability: selectedFeatures.includes('extractability'),
89
+ enableHallucination: selectedFeatures.includes('hallucination'),
90
+ };
91
+ if (config.enableLlm) {
92
+ config.llmProvider = llmProvider;
93
+ config.llmModel = llmModel;
94
+ config.llmApiKey = llmApiKey || undefined;
95
+ config.llmBaseUrl = llmBaseUrl || undefined;
96
+ }
97
+ onComplete(config);
98
+ // Exit the wizard app
99
+ exit();
100
+ };
101
+ const getModelPlaceholder = () => {
102
+ switch (llmProvider) {
103
+ case 'openai':
104
+ return 'gpt-4o-mini (default)';
105
+ case 'anthropic':
106
+ return 'claude-3-5-sonnet-20241022 (default)';
107
+ case 'ollama':
108
+ return 'qwen2.5:0.5b';
109
+ default:
110
+ return 'model-name';
111
+ }
112
+ };
113
+ const getApiKeyPlaceholder = () => {
114
+ switch (llmProvider) {
115
+ case 'openai':
116
+ return 'sk-...';
117
+ case 'anthropic':
118
+ return 'sk-ant-...';
119
+ default:
120
+ return 'your-api-key';
121
+ }
122
+ };
123
+ return (React.createElement(Box, { flexDirection: "column", paddingY: 1 },
124
+ React.createElement(Box, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 2, paddingY: 1, marginBottom: 1 },
125
+ React.createElement(Text, { bold: true, color: "cyan" }, "\uD83D\uDEA8 AI Lighthouse Setup Wizard"),
126
+ React.createElement(Text, { dimColor: true }, "Configure your audit settings")),
127
+ step === 'url' && (React.createElement(Box, { flexDirection: "column" },
128
+ React.createElement(Text, { bold: true }, "Enter the URL to audit:"),
129
+ React.createElement(Box, { marginTop: 1 },
130
+ React.createElement(Text, { color: "cyan" }, "URL: "),
131
+ React.createElement(TextInput, { value: url, onChange: setUrl, onSubmit: handleUrlSubmit, placeholder: "https://example.com" })),
132
+ React.createElement(Box, { marginTop: 1 },
133
+ React.createElement(Text, { dimColor: true }, "Press Enter to continue")))),
134
+ step === 'features' && (React.createElement(Box, { flexDirection: "column" },
135
+ React.createElement(Text, { bold: true }, "Select features to enable:"),
136
+ React.createElement(Box, { marginTop: 1 },
137
+ React.createElement(Text, { dimColor: true },
138
+ "Selected: ",
139
+ selectedFeatures.length === 0 ? 'None (basic audit only)' : selectedFeatures.map(f => {
140
+ const feature = featureOptions.find(opt => opt.value === f);
141
+ return feature?.label.split(' ')[0];
142
+ }).join(', '))),
143
+ React.createElement(Box, { marginTop: 1 },
144
+ React.createElement(SelectInput, { items: featureOptions.map(opt => ({
145
+ ...opt,
146
+ label: selectedFeatures.includes(opt.value) && opt.value !== 'done'
147
+ ? `✓ ${opt.label}`
148
+ : opt.label,
149
+ })), onSelect: handleFeatureSelect })),
150
+ React.createElement(Box, { marginTop: 1 },
151
+ React.createElement(Text, { dimColor: true }, "Use \u2191\u2193 to navigate, Enter to toggle/continue")))),
152
+ step === 'llm-provider' && (React.createElement(Box, { flexDirection: "column" },
153
+ React.createElement(Text, { bold: true }, "Select LLM provider:"),
154
+ React.createElement(Box, { marginTop: 1 },
155
+ React.createElement(SelectInput, { items: llmProviderOptions, onSelect: handleLlmProviderSelect })),
156
+ React.createElement(Box, { marginTop: 1 },
157
+ React.createElement(Text, { dimColor: true }, "Use \u2191\u2193 to navigate, Enter to select")))),
158
+ step === 'llm-model' && (React.createElement(Box, { flexDirection: "column" },
159
+ React.createElement(Text, { bold: true }, "Enter LLM model name:"),
160
+ React.createElement(Box, { marginTop: 1 },
161
+ React.createElement(Text, { color: "cyan" }, "Model: "),
162
+ React.createElement(TextInput, { value: llmModel, onChange: setLlmModel, onSubmit: handleLlmModelSubmit, placeholder: getModelPlaceholder() })),
163
+ React.createElement(Box, { marginTop: 1 },
164
+ React.createElement(Text, { dimColor: true }, "Leave empty for default, or press Enter to continue")))),
165
+ step === 'llm-api-key' && (React.createElement(Box, { flexDirection: "column" },
166
+ React.createElement(Text, { bold: true }, "Enter API key:"),
167
+ React.createElement(Box, { marginTop: 1 },
168
+ React.createElement(Text, { color: "cyan" }, "API Key: "),
169
+ React.createElement(TextInput, { value: llmApiKey, onChange: setLlmApiKey, onSubmit: handleLlmApiKeySubmit, placeholder: getApiKeyPlaceholder(), mask: "*" })),
170
+ React.createElement(Box, { marginTop: 1 },
171
+ React.createElement(Text, { dimColor: true }, "Your API key will not be stored")))),
172
+ step === 'llm-base-url' && (React.createElement(Box, { flexDirection: "column" },
173
+ React.createElement(Text, { bold: true }, "Enter API base URL (optional):"),
174
+ React.createElement(Box, { marginTop: 1 },
175
+ React.createElement(Text, { color: "cyan" }, "Base URL: "),
176
+ React.createElement(TextInput, { value: llmBaseUrl, onChange: setLlmBaseUrl, onSubmit: handleLlmBaseUrlSubmit, placeholder: llmProvider === 'ollama' ? 'http://localhost:11434' : 'https://api.example.com' })),
177
+ React.createElement(Box, { marginTop: 1 },
178
+ React.createElement(Text, { dimColor: true }, "Press Enter to continue (leave empty for default)"))))));
179
+ };
@@ -0,0 +1,6 @@
1
+ import React from 'react';
2
+ interface AIUnderstandingSectionProps {
3
+ llm: any;
4
+ }
5
+ export declare const AIUnderstandingSection: React.FC<AIUnderstandingSectionProps>;
6
+ export {};
@@ -0,0 +1,87 @@
1
+ import React from 'react';
2
+ import { Box, Text } from 'ink';
3
+ export const AIUnderstandingSection = ({ llm }) => {
4
+ if (!llm || Object.keys(llm).length === 0) {
5
+ return (React.createElement(Box, { flexDirection: "column", paddingY: 1 },
6
+ React.createElement(Box, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 2, paddingY: 1 },
7
+ React.createElement(Text, { bold: true, color: "yellow" }, "\uD83D\uDCA1 Enable AI Understanding Analysis"),
8
+ React.createElement(Box, { marginTop: 1, flexDirection: "column" },
9
+ React.createElement(Text, null, "LLM analysis is not enabled. To see AI understanding insights, run:"),
10
+ React.createElement(Box, { marginTop: 1, borderStyle: "single", paddingX: 1 },
11
+ React.createElement(Text, { color: "cyan" }, "ai-lighthouse audit [URL] --enable-llm --llm-provider openai --llm-api-key YOUR_KEY")),
12
+ React.createElement(Box, { marginTop: 1 },
13
+ React.createElement(Text, { dimColor: true }, "Supported providers: openai, anthropic, ollama, local"))))));
14
+ }
15
+ return (React.createElement(Box, { flexDirection: "column", paddingY: 1 },
16
+ llm.pageType && (React.createElement(Box, { flexDirection: "column", borderStyle: "round", borderColor: "magenta", paddingX: 2, paddingY: 1, marginBottom: 1 },
17
+ React.createElement(Text, { bold: true, color: "magenta" }, "\uD83D\uDCC4 Inferred Page Type"),
18
+ React.createElement(Text, { color: "cyan" }, llm.pageType))),
19
+ llm.pageTypeInsights && llm.pageTypeInsights.length > 0 && (React.createElement(Box, { flexDirection: "column", marginBottom: 1 },
20
+ React.createElement(Text, { bold: true, underline: true, color: "blue" }, "\uD83D\uDCA1 AI-Generated Insights"),
21
+ llm.pageTypeInsights.map((insight, idx) => (React.createElement(Box, { key: idx, marginTop: 0.5 },
22
+ React.createElement(Text, { color: "cyan" },
23
+ "\u2022 ",
24
+ insight)))))),
25
+ llm.summary && (React.createElement(Box, { flexDirection: "column", marginBottom: 1 },
26
+ React.createElement(Text, { bold: true, underline: true }, "Summary"),
27
+ React.createElement(Box, { marginTop: 0.5 },
28
+ React.createElement(Text, null, llm.summary)))),
29
+ llm.keyTopics && llm.keyTopics.length > 0 && (React.createElement(Box, { flexDirection: "column", marginBottom: 1 },
30
+ React.createElement(Text, { bold: true, underline: true }, "\uD83C\uDFF7\uFE0F Key Topics"),
31
+ React.createElement(Box, { marginTop: 0.5 },
32
+ React.createElement(Text, null, llm.keyTopics.map((t) => `[${t}]`).join(' '))))),
33
+ React.createElement(Box, { flexDirection: "column", marginBottom: 1 },
34
+ React.createElement(Text, { bold: true, underline: true }, "Metadata"),
35
+ React.createElement(Box, { marginTop: 0.5, flexDirection: "column" },
36
+ llm.readingLevel && (React.createElement(Text, null,
37
+ React.createElement(Text, { bold: true }, "Reading Level:"),
38
+ " ",
39
+ llm.readingLevel.description)),
40
+ llm.sentiment && (React.createElement(Text, null,
41
+ React.createElement(Text, { bold: true }, "Sentiment:"),
42
+ " ",
43
+ llm.sentiment)),
44
+ llm.technicalDepth && (React.createElement(Text, null,
45
+ React.createElement(Text, { bold: true }, "Technical Depth:"),
46
+ " ",
47
+ llm.technicalDepth)))),
48
+ llm.topEntities && llm.topEntities.length > 0 && (React.createElement(Box, { flexDirection: "column", marginBottom: 1 },
49
+ React.createElement(Text, { bold: true, underline: true }, "\uD83D\uDD0D Key Entities"),
50
+ llm.topEntities.slice(0, 5).map((entity, idx) => (React.createElement(Box, { key: idx, marginTop: 0.5 },
51
+ React.createElement(Text, null,
52
+ "\u2022 ",
53
+ React.createElement(Text, { bold: true }, entity.name),
54
+ ' ',
55
+ React.createElement(Text, { dimColor: true },
56
+ "(",
57
+ entity.type,
58
+ ") - ",
59
+ Math.round((entity.relevance || 0) * 100),
60
+ "% relevance"))))))),
61
+ llm.questions && llm.questions.length > 0 && (React.createElement(Box, { flexDirection: "column", marginBottom: 1 },
62
+ React.createElement(Text, { bold: true, underline: true }, "\u2753 Questions AI Can Answer"),
63
+ llm.questions.slice(0, 5).map((q, idx) => (React.createElement(Box, { key: idx, marginTop: 0.5 },
64
+ React.createElement(Text, null,
65
+ idx + 1,
66
+ ". ",
67
+ React.createElement(Text, { dimColor: true },
68
+ "[",
69
+ q.difficulty.toUpperCase(),
70
+ "]"),
71
+ " ",
72
+ q.question)))))),
73
+ llm.suggestedFAQ && llm.suggestedFAQ.length > 0 && (React.createElement(Box, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 2, paddingY: 1 },
74
+ React.createElement(Text, { bold: true, color: "yellow" }, "\uD83D\uDCA1 Suggested FAQs"),
75
+ llm.suggestedFAQ
76
+ .filter((f) => f.importance === 'high')
77
+ .slice(0, 3)
78
+ .map((faq, idx) => (React.createElement(Box, { key: idx, flexDirection: "column", marginTop: 1 },
79
+ React.createElement(Text, null,
80
+ React.createElement(Text, { bold: true }, "Q:"),
81
+ " ",
82
+ faq.question),
83
+ React.createElement(Text, { dimColor: true },
84
+ React.createElement(Text, { bold: true }, "A:"),
85
+ " ",
86
+ faq.suggestedAnswer))))))));
87
+ };
@@ -0,0 +1,6 @@
1
+ import React from 'react';
2
+ interface HallucinationSectionProps {
3
+ hallucinationReport: any;
4
+ }
5
+ export declare const HallucinationSection: React.FC<HallucinationSectionProps>;
6
+ export {};
@@ -0,0 +1,84 @@
1
+ import React from 'react';
2
+ import { Box, Text } from 'ink';
3
+ export const HallucinationSection = ({ hallucinationReport }) => {
4
+ if (!hallucinationReport || Object.keys(hallucinationReport).length === 0) {
5
+ return (React.createElement(Box, { flexDirection: "column", paddingY: 1 },
6
+ React.createElement(Box, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 2, paddingY: 1 },
7
+ React.createElement(Text, { bold: true, color: "yellow" }, "\uD83D\uDCA1 Enable Hallucination Detection"),
8
+ React.createElement(Box, { marginTop: 1, flexDirection: "column" },
9
+ React.createElement(Text, null, "Hallucination detection is not enabled. To see risk assessment, run:"),
10
+ React.createElement(Box, { marginTop: 1, borderStyle: "single", paddingX: 1 },
11
+ React.createElement(Text, { color: "cyan" }, "ai-lighthouse audit [URL] --enable-hallucination --enable-llm --llm-provider openai --llm-api-key YOUR_KEY")),
12
+ React.createElement(Box, { marginTop: 1 },
13
+ React.createElement(Text, { dimColor: true }, "Note: Hallucination detection requires LLM analysis to be enabled"))))));
14
+ }
15
+ const riskScore = hallucinationReport.hallucinationRiskScore;
16
+ const getRiskColor = (score) => {
17
+ if (score >= 70)
18
+ return 'red';
19
+ if (score >= 40)
20
+ return 'yellow';
21
+ return 'green';
22
+ };
23
+ return (React.createElement(Box, { flexDirection: "column", paddingY: 1 },
24
+ React.createElement(Box, { flexDirection: "column", borderStyle: "round", borderColor: getRiskColor(riskScore), paddingX: 2, paddingY: 1, marginBottom: 1 },
25
+ React.createElement(Text, { bold: true, color: getRiskColor(riskScore) }, "\u26A0\uFE0F Hallucination Risk Assessment"),
26
+ React.createElement(Box, { marginTop: 1 },
27
+ React.createElement(Text, null,
28
+ React.createElement(Text, { bold: true }, "Risk Score: "),
29
+ React.createElement(Text, { bold: true, color: getRiskColor(riskScore) },
30
+ riskScore,
31
+ "/100")))),
32
+ hallucinationReport.factCheckSummary && (React.createElement(Box, { flexDirection: "column", borderStyle: "round", borderColor: "blue", paddingX: 2, paddingY: 1, marginBottom: 1 },
33
+ React.createElement(Text, { bold: true, color: "blue" }, "\uD83D\uDCCA Fact Check Summary"),
34
+ React.createElement(Box, { marginTop: 1, flexDirection: "column" },
35
+ React.createElement(Text, null,
36
+ React.createElement(Text, { bold: true }, "Total Facts:"),
37
+ " ",
38
+ hallucinationReport.factCheckSummary.totalFacts),
39
+ React.createElement(Text, null,
40
+ React.createElement(Text, { bold: true, color: "green" }, "Verified:"),
41
+ " ",
42
+ hallucinationReport.factCheckSummary.verifiedFacts),
43
+ React.createElement(Text, null,
44
+ React.createElement(Text, { bold: true, color: "yellow" }, "Unverified:"),
45
+ " ",
46
+ hallucinationReport.factCheckSummary.unverifiedFacts),
47
+ React.createElement(Text, null,
48
+ React.createElement(Text, { bold: true, color: "red" }, "Contradictions:"),
49
+ " ",
50
+ hallucinationReport.factCheckSummary.contradictions),
51
+ hallucinationReport.factCheckSummary.ambiguities !== undefined && (React.createElement(Text, null,
52
+ React.createElement(Text, { bold: true, color: "yellow" }, "Ambiguities:"),
53
+ " ",
54
+ hallucinationReport.factCheckSummary.ambiguities))))),
55
+ hallucinationReport.factCheckSummary?.unverifiedFacts > 0 && (React.createElement(Box, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 2, paddingY: 1, marginBottom: 1 },
56
+ React.createElement(Text, { color: "yellow" }, "\uD83D\uDCA1 Tip: Add citations and links to verify claims and reduce AI hallucination risk"))),
57
+ hallucinationReport.triggers && hallucinationReport.triggers.length > 0 && (React.createElement(React.Fragment, null, hallucinationReport.triggers.filter((t) => t.severity === 'high' || t.severity === 'critical').length > 0 && (React.createElement(Box, { flexDirection: "column", marginBottom: 1 },
58
+ React.createElement(Text, { bold: true, underline: true, color: "red" }, "\uD83D\uDEA8 High-Risk Triggers"),
59
+ hallucinationReport.triggers
60
+ .filter((t) => t.severity === 'high' || t.severity === 'critical')
61
+ .slice(0, 5)
62
+ .map((trigger, idx) => (React.createElement(Box, { key: idx, flexDirection: "column", borderStyle: "single", borderColor: "red", paddingX: 1, paddingY: 0.5, marginTop: 1 },
63
+ React.createElement(Text, null,
64
+ idx + 1,
65
+ ". ",
66
+ React.createElement(Text, { bold: true, color: "red" },
67
+ "[",
68
+ trigger.severity.toUpperCase(),
69
+ "]"),
70
+ " ",
71
+ trigger.type),
72
+ React.createElement(Text, { dimColor: true }, trigger.description),
73
+ trigger.confidence && (React.createElement(Text, { dimColor: true },
74
+ "Confidence: ",
75
+ Math.round(trigger.confidence * 100),
76
+ "%"))))))))),
77
+ hallucinationReport.recommendations && hallucinationReport.recommendations.length > 0 && (React.createElement(Box, { flexDirection: "column" },
78
+ React.createElement(Text, { bold: true, underline: true, color: "cyan" }, "\uD83D\uDCA1 Recommendations"),
79
+ hallucinationReport.recommendations.slice(0, 3).map((rec, idx) => (React.createElement(Box, { key: idx, marginTop: 0.5 },
80
+ React.createElement(Text, { color: "cyan" },
81
+ idx + 1,
82
+ ". ",
83
+ rec))))))));
84
+ };
@@ -0,0 +1,6 @@
1
+ import React from 'react';
2
+ interface IssuesSectionProps {
3
+ issues: any[];
4
+ }
5
+ export declare const IssuesSection: React.FC<IssuesSectionProps>;
6
+ export {};
@@ -0,0 +1,84 @@
1
+ import React, { useState } from 'react';
2
+ import { Box, Text } from 'ink';
3
+ export const IssuesSection = ({ issues }) => {
4
+ const [selectedSeverity, setSelectedSeverity] = useState('all');
5
+ const [expandedIssue, setExpandedIssue] = useState(null);
6
+ const getSeverityColor = (severity) => {
7
+ if (severity === 'critical')
8
+ return 'red';
9
+ if (severity === 'high')
10
+ return 'magenta';
11
+ if (severity === 'medium')
12
+ return 'yellow';
13
+ return 'blue';
14
+ };
15
+ const getSeverityIcon = (severity) => {
16
+ if (severity === 'critical')
17
+ return '🔴';
18
+ if (severity === 'high')
19
+ return '🟠';
20
+ if (severity === 'medium')
21
+ return '🟡';
22
+ return '🔵';
23
+ };
24
+ // Group issues by severity
25
+ const grouped = {
26
+ critical: issues.filter(i => i.severity === 'critical'),
27
+ high: issues.filter(i => i.severity === 'high'),
28
+ medium: issues.filter(i => i.severity === 'medium'),
29
+ low: issues.filter(i => i.severity === 'low'),
30
+ };
31
+ const filteredIssues = selectedSeverity === 'all' ? issues : grouped[selectedSeverity] || [];
32
+ return (React.createElement(Box, { flexDirection: "column", paddingY: 1 },
33
+ React.createElement(Box, { flexDirection: "column", borderStyle: "round", borderColor: "blue", paddingX: 2, paddingY: 1, marginBottom: 1 },
34
+ React.createElement(Text, { bold: true, color: "blue" }, "\u26A0\uFE0F Issues Summary"),
35
+ React.createElement(Box, { marginTop: 1 },
36
+ React.createElement(Box, { flexDirection: "column", width: "50%" },
37
+ React.createElement(Text, null,
38
+ React.createElement(Text, { color: "red", bold: true }, "Critical:"),
39
+ ' ',
40
+ grouped.critical.length),
41
+ React.createElement(Text, null,
42
+ React.createElement(Text, { color: "magenta", bold: true }, "High:"),
43
+ ' ',
44
+ grouped.high.length)),
45
+ React.createElement(Box, { flexDirection: "column", width: "50%" },
46
+ React.createElement(Text, null,
47
+ React.createElement(Text, { color: "yellow", bold: true }, "Medium:"),
48
+ ' ',
49
+ grouped.medium.length),
50
+ React.createElement(Text, null,
51
+ React.createElement(Text, { color: "blue", bold: true }, "Low:"),
52
+ ' ',
53
+ grouped.low.length)))),
54
+ React.createElement(Box, { flexDirection: "column" },
55
+ React.createElement(Text, { bold: true, underline: true },
56
+ selectedSeverity === 'all' ? 'All Issues' : `${selectedSeverity.toUpperCase()} Issues`,
57
+ " (",
58
+ filteredIssues.length,
59
+ ")"),
60
+ filteredIssues.map((issue, idx) => (React.createElement(Box, { key: idx, flexDirection: "column", borderStyle: "round", borderColor: getSeverityColor(issue.severity), paddingX: 2, paddingY: 1, marginTop: 1 },
61
+ React.createElement(Box, null,
62
+ React.createElement(Text, null,
63
+ getSeverityIcon(issue.severity),
64
+ ' ',
65
+ React.createElement(Text, { bold: true, color: getSeverityColor(issue.severity) }, issue.message || issue.title))),
66
+ React.createElement(Box, { marginTop: 0.5 },
67
+ React.createElement(Text, { dimColor: true },
68
+ "Category: ",
69
+ issue.category,
70
+ " \u2022 Impact: ",
71
+ issue.impact)),
72
+ issue.evidence && (React.createElement(Box, { marginTop: 0.5 },
73
+ React.createElement(Text, { dimColor: true },
74
+ typeof issue.evidence === 'string'
75
+ ? issue.evidence.substring(0, 100)
76
+ : Array.isArray(issue.evidence)
77
+ ? issue.evidence.join(', ').substring(0, 100)
78
+ : '',
79
+ (typeof issue.evidence === 'string' ? issue.evidence : issue.evidence?.join(', ') || '').length > 100 ? '...' : ''))),
80
+ React.createElement(Box, { marginTop: 1, borderStyle: "single", borderColor: "cyan", paddingX: 1, paddingY: 0.5 },
81
+ React.createElement(Text, { color: "cyan" },
82
+ "\uD83D\uDCA1 Fix: ",
83
+ issue.suggested_fix || issue.remediation))))))));
84
+ };
@@ -0,0 +1,6 @@
1
+ import React from 'react';
2
+ interface MessageAlignmentSectionProps {
3
+ mirrorReport: any;
4
+ }
5
+ export declare const MessageAlignmentSection: React.FC<MessageAlignmentSectionProps>;
6
+ export {};