@ai-lighthouse/cli 1.0.0 → 1.0.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/dist/index.js +2573 -12
- package/package.json +10 -4
- package/.ai-lighthouse/audit_example.com_2025-12-15T12-10-43.json +0 -183
- package/.ai-lighthouse/audit_fayeed.dev_2026-01-07T19-32-28.html +0 -743
- package/.ai-lighthouse/audit_fayeed.dev_2026-01-07T19-33-02.html +0 -757
- package/.ai-lighthouse/audit_github.com_2025-12-15T11-53-21.json +0 -168
- package/.ai-lighthouse/audit_github.com_2025-12-15T12-04-06.json +0 -168
- package/.ai-lighthouse/audit_github.com_2025-12-15T12-05-10.json +0 -168
- package/.ai-lighthouse/audit_github.com_2025-12-15T12-09-45.json +0 -168
- package/.ai-lighthouse/audit_github.com_2025-12-15T12-11-07.json +0 -168
- package/.ai-lighthouse/audit_github.com_2025-12-15T12-13-28.json +0 -168
- package/.ai-lighthouse/audit_github.com_2025-12-15T12-14-59.json +0 -205
- package/.ai-lighthouse/audit_github.com_2025-12-15T12-18-07.json +0 -205
- package/.ai-lighthouse/audit_github.com_2025-12-15T12-18-44.json +0 -205
- package/.ai-lighthouse/audit_github.com_2025-12-15T12-21-38.json +0 -205
- package/.ai-lighthouse/audit_github.com_2025-12-15T12-22-21.json +0 -205
- package/.ai-lighthouse/audit_github.com_2025-12-15T12-22-46.json +0 -205
- package/.ai-lighthouse/audit_github.com_2025-12-15T12-23-18.json +0 -205
- package/.ai-lighthouse/audit_github.com_2025-12-15T12-24-43.json +0 -205
- package/.ai-lighthouse/audit_github.com_2025-12-17T12-15-08.json +0 -168
- package/.ai-lighthouse/audit_github.com_2025-12-17T12-15-57.json +0 -168
- package/.ai-lighthouse/audit_github.com_2025-12-17T12-17-11.json +0 -168
- package/.ai-lighthouse/audit_github.com_2025-12-17T12-22-17.json +0 -168
- package/.ai-lighthouse/audit_github.com_2025-12-17T12-22-42.json +0 -168
- package/.ai-lighthouse/audit_github.com_2025-12-17T12-23-56.json +0 -168
- package/.ai-lighthouse/audit_github.com_2025-12-17T12-25-24.json +0 -168
- package/.ai-lighthouse/audit_github.com_2025-12-17T12-25-40.json +0 -168
- package/.ai-lighthouse/audit_github.com_2025-12-17T12-27-02.json +0 -168
- package/.ai-lighthouse/audit_github.com_2025-12-17T12-27-20.json +0 -168
- package/.ai-lighthouse/audit_github.com_2025-12-17T12-29-56.json +0 -168
- package/.ai-lighthouse/audit_github.com_2025-12-17T12-32-27.json +0 -168
- package/.ai-lighthouse/audit_github.com_2025-12-17T12-33-00.json +0 -168
- package/.ai-lighthouse/audit_github.com_2025-12-17T12-34-49.json +0 -168
- package/.ai-lighthouse/audit_stripe.com_2025-12-15T12-11-31.json +0 -168
- package/.ai-lighthouse/audit_stripe.com_2025-12-15T12-11-45.json +0 -168
- package/.ai-lighthouse/audit_tailwindcss.com_2025-12-15T12-12-01.json +0 -169
- package/.ai-lighthouse/crawl_example.com_2025-12-15T12-03-08.json +0 -24
- package/.ai-lighthouse/crawl_example.com_2025-12-15T12-03-23.json +0 -24
- package/.ai-lighthouse/crawl_github.com_2025-12-15T11-41-34.json +0 -21
- package/.ai-lighthouse/crawl_github.com_2025-12-15T11-42-09.json +0 -21
- package/.ai-lighthouse/crawl_github.com_2025-12-15T11-42-45.json +0 -21
- package/.ai-lighthouse/crawl_github.com_2025-12-15T11-43-02.json +0 -21
- package/.ai-lighthouse/crawl_github.com_2025-12-15T11-43-26.json +0 -21
- package/.ai-lighthouse/crawl_github.com_2025-12-15T11-47-46.json +0 -906
- package/.ai-lighthouse/crawl_github.com_2025-12-15T11-50-27.json +0 -906
- package/.ai-lighthouse/crawl_github.com_2025-12-15T11-52-59.json +0 -906
- package/.ai-lighthouse/crawl_github.com_2025-12-15T12-03-33.json +0 -28
- package/CLI_UI_README.md +0 -211
- package/EXAMPLES.md +0 -87
- package/IMPLEMENTATION.md +0 -215
- package/USAGE.md +0 -264
- package/WIZARD_GUIDE.md +0 -340
- package/bin/cli.js +0 -2
- package/dist/commands/audit-interactive.d.ts +0 -2
- package/dist/commands/audit-interactive.js +0 -106
- package/dist/commands/audit-wizard.d.ts +0 -2
- package/dist/commands/audit-wizard.js +0 -110
- package/dist/commands/audit.d.ts +0 -2
- package/dist/commands/audit.js +0 -940
- package/dist/commands/crawl.d.ts +0 -2
- package/dist/commands/crawl.js +0 -267
- package/dist/commands/report.d.ts +0 -2
- package/dist/commands/report.js +0 -304
- package/dist/index.d.ts +0 -1
- package/dist/ui/AuditReportUI.d.ts +0 -10
- package/dist/ui/AuditReportUI.js +0 -76
- package/dist/ui/SetupWizard.d.ts +0 -18
- package/dist/ui/SetupWizard.js +0 -179
- package/dist/ui/components/AIUnderstandingSection.d.ts +0 -6
- package/dist/ui/components/AIUnderstandingSection.js +0 -87
- package/dist/ui/components/HallucinationSection.d.ts +0 -6
- package/dist/ui/components/HallucinationSection.js +0 -84
- package/dist/ui/components/IssuesSection.d.ts +0 -6
- package/dist/ui/components/IssuesSection.js +0 -84
- package/dist/ui/components/MessageAlignmentSection.d.ts +0 -6
- package/dist/ui/components/MessageAlignmentSection.js +0 -108
- package/dist/ui/components/OverviewSection.d.ts +0 -6
- package/dist/ui/components/OverviewSection.js +0 -107
- package/dist/ui/components/ScoreDisplay.d.ts +0 -8
- package/dist/ui/components/ScoreDisplay.js +0 -41
- package/dist/ui/components/TechnicalSection.d.ts +0 -7
- package/dist/ui/components/TechnicalSection.js +0 -110
- package/dist/utils/comprehensive-formatter.d.ts +0 -5
- package/dist/utils/comprehensive-formatter.js +0 -370
- package/src/commands/audit-interactive.ts +0 -149
- package/src/commands/audit-wizard.ts +0 -137
- package/src/commands/audit.ts +0 -1012
- package/src/commands/crawl.ts +0 -307
- package/src/commands/report.ts +0 -321
- package/src/index.ts +0 -22
- package/src/ui/AuditReportUI.tsx +0 -151
- package/src/ui/SetupWizard.tsx +0 -294
- package/src/ui/components/AIUnderstandingSection.tsx +0 -183
- package/src/ui/components/HallucinationSection.tsx +0 -172
- package/src/ui/components/IssuesSection.tsx +0 -140
- package/src/ui/components/MessageAlignmentSection.tsx +0 -203
- package/src/ui/components/OverviewSection.tsx +0 -157
- package/src/ui/components/ScoreDisplay.tsx +0 -58
- package/src/ui/components/TechnicalSection.tsx +0 -200
- package/src/utils/comprehensive-formatter.ts +0 -455
- package/test.sh +0 -31
- package/tsconfig.json +0 -25
package/src/ui/AuditReportUI.tsx
DELETED
|
@@ -1,151 +0,0 @@
|
|
|
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
|
-
|
|
12
|
-
interface AuditReportUIProps {
|
|
13
|
-
url: string;
|
|
14
|
-
result: any;
|
|
15
|
-
aiReadiness: any;
|
|
16
|
-
loading?: boolean;
|
|
17
|
-
currentStep?: string;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
type TabType = 'overview' | 'issues' | 'ai-understanding' | 'hallucination' | 'message-alignment' | 'technical';
|
|
21
|
-
|
|
22
|
-
export const AuditReportUI: React.FC<AuditReportUIProps> = ({
|
|
23
|
-
url,
|
|
24
|
-
result,
|
|
25
|
-
aiReadiness,
|
|
26
|
-
loading = false,
|
|
27
|
-
currentStep = '',
|
|
28
|
-
}) => {
|
|
29
|
-
const [currentTab, setCurrentTab] = useState<TabType>('overview');
|
|
30
|
-
|
|
31
|
-
const tabs: { key: TabType; label: string; icon: string }[] = [
|
|
32
|
-
{ key: 'overview', label: 'Overview', icon: '📊' },
|
|
33
|
-
{ key: 'issues', label: 'Issues', icon: '⚠️' },
|
|
34
|
-
{ key: 'ai-understanding', label: 'AI Understanding', icon: '🧠' },
|
|
35
|
-
{ key: 'hallucination', label: 'Hallucination Risk', icon: '⚠️' },
|
|
36
|
-
{ key: 'message-alignment', label: 'Message Alignment', icon: '🔍' },
|
|
37
|
-
{ key: 'technical', label: 'Technical', icon: '⚙️' },
|
|
38
|
-
];
|
|
39
|
-
|
|
40
|
-
useInput((input, key) => {
|
|
41
|
-
if (loading) return;
|
|
42
|
-
|
|
43
|
-
if (key.leftArrow) {
|
|
44
|
-
const currentIndex = tabs.findIndex(t => t.key === currentTab);
|
|
45
|
-
const prevIndex = currentIndex > 0 ? currentIndex - 1 : tabs.length - 1;
|
|
46
|
-
setCurrentTab(tabs[prevIndex].key);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
if (key.rightArrow) {
|
|
50
|
-
const currentIndex = tabs.findIndex(t => t.key === currentTab);
|
|
51
|
-
const nextIndex = currentIndex < tabs.length - 1 ? currentIndex + 1 : 0;
|
|
52
|
-
setCurrentTab(tabs[nextIndex].key);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// Number keys for quick tab switching
|
|
56
|
-
const num = parseInt(input);
|
|
57
|
-
if (num >= 1 && num <= tabs.length) {
|
|
58
|
-
setCurrentTab(tabs[num - 1].key);
|
|
59
|
-
}
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
if (loading) {
|
|
63
|
-
return (
|
|
64
|
-
<Box flexDirection="column" paddingY={1}>
|
|
65
|
-
<Box>
|
|
66
|
-
<Text color="green">
|
|
67
|
-
<Spinner type="dots" />
|
|
68
|
-
</Text>
|
|
69
|
-
<Text> {currentStep || 'Loading...'}</Text>
|
|
70
|
-
</Box>
|
|
71
|
-
</Box>
|
|
72
|
-
);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
const overallScore = aiReadiness?.overall || 0;
|
|
76
|
-
const grade = aiReadiness?.grade || 'N/A';
|
|
77
|
-
|
|
78
|
-
return (
|
|
79
|
-
<Box flexDirection="column">
|
|
80
|
-
{/* Header */}
|
|
81
|
-
<Box
|
|
82
|
-
flexDirection="column"
|
|
83
|
-
borderStyle="round"
|
|
84
|
-
borderColor="cyan"
|
|
85
|
-
paddingX={2}
|
|
86
|
-
paddingY={1}
|
|
87
|
-
>
|
|
88
|
-
<Text bold color="cyan">
|
|
89
|
-
🚨 AI Lighthouse Report
|
|
90
|
-
</Text>
|
|
91
|
-
</Box>
|
|
92
|
-
|
|
93
|
-
{/* Score Display */}
|
|
94
|
-
<ScoreDisplay score={overallScore} grade={grade} url={url} />
|
|
95
|
-
|
|
96
|
-
{/* Tab Navigation */}
|
|
97
|
-
<Box
|
|
98
|
-
flexDirection="row"
|
|
99
|
-
borderStyle="single"
|
|
100
|
-
borderColor="blue"
|
|
101
|
-
paddingX={1}
|
|
102
|
-
marginTop={1}
|
|
103
|
-
>
|
|
104
|
-
{tabs.map((tab, index) => {
|
|
105
|
-
const isActive = tab.key === currentTab;
|
|
106
|
-
return (
|
|
107
|
-
<Box key={tab.key} marginRight={1}>
|
|
108
|
-
<Text
|
|
109
|
-
bold={isActive}
|
|
110
|
-
color={isActive ? 'cyan' : 'gray'}
|
|
111
|
-
backgroundColor={isActive ? 'blue' : undefined}
|
|
112
|
-
>
|
|
113
|
-
{` ${index + 1}. ${tab.icon} ${tab.label} `}
|
|
114
|
-
</Text>
|
|
115
|
-
</Box>
|
|
116
|
-
);
|
|
117
|
-
})}
|
|
118
|
-
</Box>
|
|
119
|
-
|
|
120
|
-
{/* Help Text */}
|
|
121
|
-
<Box marginTop={1} marginBottom={1}>
|
|
122
|
-
<Text dimColor>
|
|
123
|
-
Use ← → arrow keys or numbers (1-{tabs.length}) to navigate tabs
|
|
124
|
-
</Text>
|
|
125
|
-
</Box>
|
|
126
|
-
|
|
127
|
-
{/* Tab Content */}
|
|
128
|
-
<Box flexDirection="column">
|
|
129
|
-
{currentTab === 'overview' && <OverviewSection aiReadiness={aiReadiness} />}
|
|
130
|
-
{currentTab === 'issues' && <IssuesSection issues={result.issues || []} />}
|
|
131
|
-
{currentTab === 'ai-understanding' && <AIUnderstandingSection llm={result.llm} />}
|
|
132
|
-
{currentTab === 'hallucination' && <HallucinationSection hallucinationReport={result.hallucinationReport} />}
|
|
133
|
-
{currentTab === 'message-alignment' && <MessageAlignmentSection mirrorReport={result.mirrorReport} />}
|
|
134
|
-
{currentTab === 'technical' && <TechnicalSection result={result} scoring={result.scoring} />}
|
|
135
|
-
</Box>
|
|
136
|
-
|
|
137
|
-
{/* Footer */}
|
|
138
|
-
<Box
|
|
139
|
-
marginTop={2}
|
|
140
|
-
borderStyle="round"
|
|
141
|
-
borderColor="gray"
|
|
142
|
-
paddingX={2}
|
|
143
|
-
paddingY={1}
|
|
144
|
-
>
|
|
145
|
-
<Text dimColor>
|
|
146
|
-
Press Ctrl+C to exit • Report generated at {new Date().toLocaleString()}
|
|
147
|
-
</Text>
|
|
148
|
-
</Box>
|
|
149
|
-
</Box>
|
|
150
|
-
);
|
|
151
|
-
};
|
package/src/ui/SetupWizard.tsx
DELETED
|
@@ -1,294 +0,0 @@
|
|
|
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
|
-
|
|
6
|
-
interface SetupWizardProps {
|
|
7
|
-
onComplete: (config: AuditConfig) => void;
|
|
8
|
-
initialUrl?: string;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export interface AuditConfig {
|
|
12
|
-
url: string;
|
|
13
|
-
enableLlm: boolean;
|
|
14
|
-
enableChunking: boolean;
|
|
15
|
-
enableExtractability: boolean;
|
|
16
|
-
enableHallucination: boolean;
|
|
17
|
-
llmProvider?: string;
|
|
18
|
-
llmModel?: string;
|
|
19
|
-
llmApiKey?: string;
|
|
20
|
-
llmBaseUrl?: string;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
type Step = 'url' | 'features' | 'llm-provider' | 'llm-model' | 'llm-api-key' | 'llm-base-url';
|
|
24
|
-
|
|
25
|
-
export const SetupWizard: React.FC<SetupWizardProps> = ({ onComplete, initialUrl }) => {
|
|
26
|
-
const { exit } = useApp();
|
|
27
|
-
const [step, setStep] = useState<Step>(initialUrl ? 'features' : 'url');
|
|
28
|
-
const [url, setUrl] = useState(initialUrl || '');
|
|
29
|
-
const [selectedFeatures, setSelectedFeatures] = useState<string[]>([]);
|
|
30
|
-
const [llmProvider, setLlmProvider] = useState<string>('');
|
|
31
|
-
const [llmModel, setLlmModel] = useState<string>('');
|
|
32
|
-
const [llmApiKey, setLlmApiKey] = useState<string>('');
|
|
33
|
-
const [llmBaseUrl, setLlmBaseUrl] = useState<string>('');
|
|
34
|
-
|
|
35
|
-
const featureOptions = [
|
|
36
|
-
{ label: '🧠 AI Understanding (LLM Analysis)', value: 'llm' },
|
|
37
|
-
{ label: '📄 Content Chunking Analysis', value: 'chunking' },
|
|
38
|
-
{ label: '🔄 Extractability Analysis', value: 'extractability' },
|
|
39
|
-
{ label: '⚠️ Hallucination Detection', value: 'hallucination' },
|
|
40
|
-
{ label: '✅ Continue with selected features', value: 'done' },
|
|
41
|
-
];
|
|
42
|
-
|
|
43
|
-
const llmProviderOptions = [
|
|
44
|
-
{ label: 'OpenAI (GPT-4, GPT-3.5)', value: 'openai' },
|
|
45
|
-
{ label: 'Anthropic (Claude)', value: 'anthropic' },
|
|
46
|
-
{ label: 'Ollama (Local)', value: 'ollama' },
|
|
47
|
-
{ label: 'Custom/Local Provider', value: 'local' },
|
|
48
|
-
];
|
|
49
|
-
|
|
50
|
-
const handleUrlSubmit = (value: string) => {
|
|
51
|
-
setUrl(value);
|
|
52
|
-
setStep('features');
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
const handleFeatureSelect = (item: any) => {
|
|
56
|
-
if (item.value === 'done') {
|
|
57
|
-
// Check if LLM is needed
|
|
58
|
-
if (selectedFeatures.includes('llm') || selectedFeatures.includes('hallucination')) {
|
|
59
|
-
setStep('llm-provider');
|
|
60
|
-
} else {
|
|
61
|
-
completeSetup();
|
|
62
|
-
}
|
|
63
|
-
} else {
|
|
64
|
-
// Toggle feature selection
|
|
65
|
-
if (selectedFeatures.includes(item.value)) {
|
|
66
|
-
setSelectedFeatures(selectedFeatures.filter(f => f !== item.value));
|
|
67
|
-
} else {
|
|
68
|
-
setSelectedFeatures([...selectedFeatures, item.value]);
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
const handleLlmProviderSelect = (item: any) => {
|
|
74
|
-
setLlmProvider(item.value);
|
|
75
|
-
|
|
76
|
-
// Set default base URL for ollama
|
|
77
|
-
if (item.value === 'ollama') {
|
|
78
|
-
setLlmBaseUrl('http://localhost:11434');
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
setStep('llm-model');
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
const handleLlmModelSubmit = (value: string) => {
|
|
85
|
-
setLlmModel(value);
|
|
86
|
-
|
|
87
|
-
// If ollama, skip API key and go to base URL
|
|
88
|
-
if (llmProvider === 'ollama') {
|
|
89
|
-
setStep('llm-base-url');
|
|
90
|
-
} else {
|
|
91
|
-
setStep('llm-api-key');
|
|
92
|
-
}
|
|
93
|
-
};
|
|
94
|
-
|
|
95
|
-
const handleLlmApiKeySubmit = (value: string) => {
|
|
96
|
-
setLlmApiKey(value);
|
|
97
|
-
|
|
98
|
-
// If provider needs base URL, go there, otherwise complete
|
|
99
|
-
if (llmProvider === 'local' || llmProvider === 'anthropic') {
|
|
100
|
-
setStep('llm-base-url');
|
|
101
|
-
} else {
|
|
102
|
-
completeSetup();
|
|
103
|
-
}
|
|
104
|
-
};
|
|
105
|
-
|
|
106
|
-
const handleLlmBaseUrlSubmit = (value: string) => {
|
|
107
|
-
setLlmBaseUrl(value);
|
|
108
|
-
completeSetup();
|
|
109
|
-
};
|
|
110
|
-
|
|
111
|
-
const completeSetup = () => {
|
|
112
|
-
const config: AuditConfig = {
|
|
113
|
-
url,
|
|
114
|
-
enableLlm: selectedFeatures.includes('llm') || selectedFeatures.includes('hallucination'),
|
|
115
|
-
enableChunking: selectedFeatures.includes('chunking'),
|
|
116
|
-
enableExtractability: selectedFeatures.includes('extractability'),
|
|
117
|
-
enableHallucination: selectedFeatures.includes('hallucination'),
|
|
118
|
-
};
|
|
119
|
-
|
|
120
|
-
if (config.enableLlm) {
|
|
121
|
-
config.llmProvider = llmProvider;
|
|
122
|
-
config.llmModel = llmModel;
|
|
123
|
-
config.llmApiKey = llmApiKey || undefined;
|
|
124
|
-
config.llmBaseUrl = llmBaseUrl || undefined;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
onComplete(config);
|
|
128
|
-
// Exit the wizard app
|
|
129
|
-
exit();
|
|
130
|
-
};
|
|
131
|
-
|
|
132
|
-
const getModelPlaceholder = () => {
|
|
133
|
-
switch (llmProvider) {
|
|
134
|
-
case 'openai':
|
|
135
|
-
return 'gpt-4o-mini (default)';
|
|
136
|
-
case 'anthropic':
|
|
137
|
-
return 'claude-3-5-sonnet-20241022 (default)';
|
|
138
|
-
case 'ollama':
|
|
139
|
-
return 'qwen2.5:0.5b';
|
|
140
|
-
default:
|
|
141
|
-
return 'model-name';
|
|
142
|
-
}
|
|
143
|
-
};
|
|
144
|
-
|
|
145
|
-
const getApiKeyPlaceholder = () => {
|
|
146
|
-
switch (llmProvider) {
|
|
147
|
-
case 'openai':
|
|
148
|
-
return 'sk-...';
|
|
149
|
-
case 'anthropic':
|
|
150
|
-
return 'sk-ant-...';
|
|
151
|
-
default:
|
|
152
|
-
return 'your-api-key';
|
|
153
|
-
}
|
|
154
|
-
};
|
|
155
|
-
|
|
156
|
-
return (
|
|
157
|
-
<Box flexDirection="column" paddingY={1}>
|
|
158
|
-
{/* Header */}
|
|
159
|
-
<Box
|
|
160
|
-
flexDirection="column"
|
|
161
|
-
borderStyle="round"
|
|
162
|
-
borderColor="cyan"
|
|
163
|
-
paddingX={2}
|
|
164
|
-
paddingY={1}
|
|
165
|
-
marginBottom={1}
|
|
166
|
-
>
|
|
167
|
-
<Text bold color="cyan">
|
|
168
|
-
🚨 AI Lighthouse Setup Wizard
|
|
169
|
-
</Text>
|
|
170
|
-
<Text dimColor>Configure your audit settings</Text>
|
|
171
|
-
</Box>
|
|
172
|
-
|
|
173
|
-
{/* URL Input */}
|
|
174
|
-
{step === 'url' && (
|
|
175
|
-
<Box flexDirection="column">
|
|
176
|
-
<Text bold>Enter the URL to audit:</Text>
|
|
177
|
-
<Box marginTop={1}>
|
|
178
|
-
<Text color="cyan">URL: </Text>
|
|
179
|
-
<TextInput
|
|
180
|
-
value={url}
|
|
181
|
-
onChange={setUrl}
|
|
182
|
-
onSubmit={handleUrlSubmit}
|
|
183
|
-
placeholder="https://example.com"
|
|
184
|
-
/>
|
|
185
|
-
</Box>
|
|
186
|
-
<Box marginTop={1}>
|
|
187
|
-
<Text dimColor>Press Enter to continue</Text>
|
|
188
|
-
</Box>
|
|
189
|
-
</Box>
|
|
190
|
-
)}
|
|
191
|
-
|
|
192
|
-
{/* Feature Selection */}
|
|
193
|
-
{step === 'features' && (
|
|
194
|
-
<Box flexDirection="column">
|
|
195
|
-
<Text bold>Select features to enable:</Text>
|
|
196
|
-
<Box marginTop={1}>
|
|
197
|
-
<Text dimColor>
|
|
198
|
-
Selected: {selectedFeatures.length === 0 ? 'None (basic audit only)' : selectedFeatures.map(f => {
|
|
199
|
-
const feature = featureOptions.find(opt => opt.value === f);
|
|
200
|
-
return feature?.label.split(' ')[0];
|
|
201
|
-
}).join(', ')}
|
|
202
|
-
</Text>
|
|
203
|
-
</Box>
|
|
204
|
-
<Box marginTop={1}>
|
|
205
|
-
<SelectInput
|
|
206
|
-
items={featureOptions.map(opt => ({
|
|
207
|
-
...opt,
|
|
208
|
-
label: selectedFeatures.includes(opt.value) && opt.value !== 'done'
|
|
209
|
-
? `✓ ${opt.label}`
|
|
210
|
-
: opt.label,
|
|
211
|
-
}))}
|
|
212
|
-
onSelect={handleFeatureSelect}
|
|
213
|
-
/>
|
|
214
|
-
</Box>
|
|
215
|
-
<Box marginTop={1}>
|
|
216
|
-
<Text dimColor>Use ↑↓ to navigate, Enter to toggle/continue</Text>
|
|
217
|
-
</Box>
|
|
218
|
-
</Box>
|
|
219
|
-
)}
|
|
220
|
-
|
|
221
|
-
{/* LLM Provider Selection */}
|
|
222
|
-
{step === 'llm-provider' && (
|
|
223
|
-
<Box flexDirection="column">
|
|
224
|
-
<Text bold>Select LLM provider:</Text>
|
|
225
|
-
<Box marginTop={1}>
|
|
226
|
-
<SelectInput items={llmProviderOptions} onSelect={handleLlmProviderSelect} />
|
|
227
|
-
</Box>
|
|
228
|
-
<Box marginTop={1}>
|
|
229
|
-
<Text dimColor>Use ↑↓ to navigate, Enter to select</Text>
|
|
230
|
-
</Box>
|
|
231
|
-
</Box>
|
|
232
|
-
)}
|
|
233
|
-
|
|
234
|
-
{/* LLM Model Input */}
|
|
235
|
-
{step === 'llm-model' && (
|
|
236
|
-
<Box flexDirection="column">
|
|
237
|
-
<Text bold>Enter LLM model name:</Text>
|
|
238
|
-
<Box marginTop={1}>
|
|
239
|
-
<Text color="cyan">Model: </Text>
|
|
240
|
-
<TextInput
|
|
241
|
-
value={llmModel}
|
|
242
|
-
onChange={setLlmModel}
|
|
243
|
-
onSubmit={handleLlmModelSubmit}
|
|
244
|
-
placeholder={getModelPlaceholder()}
|
|
245
|
-
/>
|
|
246
|
-
</Box>
|
|
247
|
-
<Box marginTop={1}>
|
|
248
|
-
<Text dimColor>Leave empty for default, or press Enter to continue</Text>
|
|
249
|
-
</Box>
|
|
250
|
-
</Box>
|
|
251
|
-
)}
|
|
252
|
-
|
|
253
|
-
{/* LLM API Key Input */}
|
|
254
|
-
{step === 'llm-api-key' && (
|
|
255
|
-
<Box flexDirection="column">
|
|
256
|
-
<Text bold>Enter API key:</Text>
|
|
257
|
-
<Box marginTop={1}>
|
|
258
|
-
<Text color="cyan">API Key: </Text>
|
|
259
|
-
<TextInput
|
|
260
|
-
value={llmApiKey}
|
|
261
|
-
onChange={setLlmApiKey}
|
|
262
|
-
onSubmit={handleLlmApiKeySubmit}
|
|
263
|
-
placeholder={getApiKeyPlaceholder()}
|
|
264
|
-
mask="*"
|
|
265
|
-
/>
|
|
266
|
-
</Box>
|
|
267
|
-
<Box marginTop={1}>
|
|
268
|
-
<Text dimColor>Your API key will not be stored</Text>
|
|
269
|
-
</Box>
|
|
270
|
-
</Box>
|
|
271
|
-
)}
|
|
272
|
-
|
|
273
|
-
{/* LLM Base URL Input */}
|
|
274
|
-
{step === 'llm-base-url' && (
|
|
275
|
-
<Box flexDirection="column">
|
|
276
|
-
<Text bold>Enter API base URL (optional):</Text>
|
|
277
|
-
<Box marginTop={1}>
|
|
278
|
-
<Text color="cyan">Base URL: </Text>
|
|
279
|
-
<TextInput
|
|
280
|
-
value={llmBaseUrl}
|
|
281
|
-
onChange={setLlmBaseUrl}
|
|
282
|
-
onSubmit={handleLlmBaseUrlSubmit}
|
|
283
|
-
placeholder={llmProvider === 'ollama' ? 'http://localhost:11434' : 'https://api.example.com'}
|
|
284
|
-
/>
|
|
285
|
-
</Box>
|
|
286
|
-
<Box marginTop={1}>
|
|
287
|
-
<Text dimColor>Press Enter to continue (leave empty for default)</Text>
|
|
288
|
-
</Box>
|
|
289
|
-
</Box>
|
|
290
|
-
)}
|
|
291
|
-
|
|
292
|
-
</Box>
|
|
293
|
-
);
|
|
294
|
-
};
|
|
@@ -1,183 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { Box, Text } from 'ink';
|
|
3
|
-
|
|
4
|
-
interface AIUnderstandingSectionProps {
|
|
5
|
-
llm: any;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
export const AIUnderstandingSection: React.FC<AIUnderstandingSectionProps> = ({ llm }) => {
|
|
9
|
-
if (!llm || Object.keys(llm).length === 0) {
|
|
10
|
-
return (
|
|
11
|
-
<Box flexDirection="column" paddingY={1}>
|
|
12
|
-
<Box
|
|
13
|
-
flexDirection="column"
|
|
14
|
-
borderStyle="round"
|
|
15
|
-
borderColor="yellow"
|
|
16
|
-
paddingX={2}
|
|
17
|
-
paddingY={1}
|
|
18
|
-
>
|
|
19
|
-
<Text bold color="yellow">
|
|
20
|
-
💡 Enable AI Understanding Analysis
|
|
21
|
-
</Text>
|
|
22
|
-
<Box marginTop={1} flexDirection="column">
|
|
23
|
-
<Text>LLM analysis is not enabled. To see AI understanding insights, run:</Text>
|
|
24
|
-
<Box marginTop={1} borderStyle="single" paddingX={1}>
|
|
25
|
-
<Text color="cyan">
|
|
26
|
-
ai-lighthouse audit [URL] --enable-llm --llm-provider openai --llm-api-key YOUR_KEY
|
|
27
|
-
</Text>
|
|
28
|
-
</Box>
|
|
29
|
-
<Box marginTop={1}>
|
|
30
|
-
<Text dimColor>Supported providers: openai, anthropic, ollama, local</Text>
|
|
31
|
-
</Box>
|
|
32
|
-
</Box>
|
|
33
|
-
</Box>
|
|
34
|
-
</Box>
|
|
35
|
-
);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
return (
|
|
39
|
-
<Box flexDirection="column" paddingY={1}>
|
|
40
|
-
{/* Page Type */}
|
|
41
|
-
{llm.pageType && (
|
|
42
|
-
<Box
|
|
43
|
-
flexDirection="column"
|
|
44
|
-
borderStyle="round"
|
|
45
|
-
borderColor="magenta"
|
|
46
|
-
paddingX={2}
|
|
47
|
-
paddingY={1}
|
|
48
|
-
marginBottom={1}
|
|
49
|
-
>
|
|
50
|
-
<Text bold color="magenta">
|
|
51
|
-
📄 Inferred Page Type
|
|
52
|
-
</Text>
|
|
53
|
-
<Text color="cyan">{llm.pageType}</Text>
|
|
54
|
-
</Box>
|
|
55
|
-
)}
|
|
56
|
-
|
|
57
|
-
{/* AI-Generated Insights */}
|
|
58
|
-
{llm.pageTypeInsights && llm.pageTypeInsights.length > 0 && (
|
|
59
|
-
<Box flexDirection="column" marginBottom={1}>
|
|
60
|
-
<Text bold underline color="blue">
|
|
61
|
-
💡 AI-Generated Insights
|
|
62
|
-
</Text>
|
|
63
|
-
{llm.pageTypeInsights.map((insight: string, idx: number) => (
|
|
64
|
-
<Box key={idx} marginTop={0.5}>
|
|
65
|
-
<Text color="cyan">• {insight}</Text>
|
|
66
|
-
</Box>
|
|
67
|
-
))}
|
|
68
|
-
</Box>
|
|
69
|
-
)}
|
|
70
|
-
|
|
71
|
-
{/* Summary */}
|
|
72
|
-
{llm.summary && (
|
|
73
|
-
<Box flexDirection="column" marginBottom={1}>
|
|
74
|
-
<Text bold underline>
|
|
75
|
-
Summary
|
|
76
|
-
</Text>
|
|
77
|
-
<Box marginTop={0.5}>
|
|
78
|
-
<Text>{llm.summary}</Text>
|
|
79
|
-
</Box>
|
|
80
|
-
</Box>
|
|
81
|
-
)}
|
|
82
|
-
|
|
83
|
-
{/* Key Topics */}
|
|
84
|
-
{llm.keyTopics && llm.keyTopics.length > 0 && (
|
|
85
|
-
<Box flexDirection="column" marginBottom={1}>
|
|
86
|
-
<Text bold underline>
|
|
87
|
-
🏷️ Key Topics
|
|
88
|
-
</Text>
|
|
89
|
-
<Box marginTop={0.5}>
|
|
90
|
-
<Text>{llm.keyTopics.map((t: string) => `[${t}]`).join(' ')}</Text>
|
|
91
|
-
</Box>
|
|
92
|
-
</Box>
|
|
93
|
-
)}
|
|
94
|
-
|
|
95
|
-
{/* Metadata Grid */}
|
|
96
|
-
<Box flexDirection="column" marginBottom={1}>
|
|
97
|
-
<Text bold underline>
|
|
98
|
-
Metadata
|
|
99
|
-
</Text>
|
|
100
|
-
<Box marginTop={0.5} flexDirection="column">
|
|
101
|
-
{llm.readingLevel && (
|
|
102
|
-
<Text>
|
|
103
|
-
<Text bold>Reading Level:</Text> {llm.readingLevel.description}
|
|
104
|
-
</Text>
|
|
105
|
-
)}
|
|
106
|
-
{llm.sentiment && (
|
|
107
|
-
<Text>
|
|
108
|
-
<Text bold>Sentiment:</Text> {llm.sentiment}
|
|
109
|
-
</Text>
|
|
110
|
-
)}
|
|
111
|
-
{llm.technicalDepth && (
|
|
112
|
-
<Text>
|
|
113
|
-
<Text bold>Technical Depth:</Text> {llm.technicalDepth}
|
|
114
|
-
</Text>
|
|
115
|
-
)}
|
|
116
|
-
</Box>
|
|
117
|
-
</Box>
|
|
118
|
-
|
|
119
|
-
{/* Top Entities */}
|
|
120
|
-
{llm.topEntities && llm.topEntities.length > 0 && (
|
|
121
|
-
<Box flexDirection="column" marginBottom={1}>
|
|
122
|
-
<Text bold underline>
|
|
123
|
-
🔍 Key Entities
|
|
124
|
-
</Text>
|
|
125
|
-
{llm.topEntities.slice(0, 5).map((entity: any, idx: number) => (
|
|
126
|
-
<Box key={idx} marginTop={0.5}>
|
|
127
|
-
<Text>
|
|
128
|
-
• <Text bold>{entity.name}</Text>{' '}
|
|
129
|
-
<Text dimColor>
|
|
130
|
-
({entity.type}) - {Math.round((entity.relevance || 0) * 100)}% relevance
|
|
131
|
-
</Text>
|
|
132
|
-
</Text>
|
|
133
|
-
</Box>
|
|
134
|
-
))}
|
|
135
|
-
</Box>
|
|
136
|
-
)}
|
|
137
|
-
|
|
138
|
-
{/* Questions AI Can Answer */}
|
|
139
|
-
{llm.questions && llm.questions.length > 0 && (
|
|
140
|
-
<Box flexDirection="column" marginBottom={1}>
|
|
141
|
-
<Text bold underline>
|
|
142
|
-
❓ Questions AI Can Answer
|
|
143
|
-
</Text>
|
|
144
|
-
{llm.questions.slice(0, 5).map((q: any, idx: number) => (
|
|
145
|
-
<Box key={idx} marginTop={0.5}>
|
|
146
|
-
<Text>
|
|
147
|
-
{idx + 1}. <Text dimColor>[{q.difficulty.toUpperCase()}]</Text> {q.question}
|
|
148
|
-
</Text>
|
|
149
|
-
</Box>
|
|
150
|
-
))}
|
|
151
|
-
</Box>
|
|
152
|
-
)}
|
|
153
|
-
|
|
154
|
-
{/* Suggested FAQs */}
|
|
155
|
-
{llm.suggestedFAQ && llm.suggestedFAQ.length > 0 && (
|
|
156
|
-
<Box
|
|
157
|
-
flexDirection="column"
|
|
158
|
-
borderStyle="round"
|
|
159
|
-
borderColor="yellow"
|
|
160
|
-
paddingX={2}
|
|
161
|
-
paddingY={1}
|
|
162
|
-
>
|
|
163
|
-
<Text bold color="yellow">
|
|
164
|
-
💡 Suggested FAQs
|
|
165
|
-
</Text>
|
|
166
|
-
{llm.suggestedFAQ
|
|
167
|
-
.filter((f: any) => f.importance === 'high')
|
|
168
|
-
.slice(0, 3)
|
|
169
|
-
.map((faq: any, idx: number) => (
|
|
170
|
-
<Box key={idx} flexDirection="column" marginTop={1}>
|
|
171
|
-
<Text>
|
|
172
|
-
<Text bold>Q:</Text> {faq.question}
|
|
173
|
-
</Text>
|
|
174
|
-
<Text dimColor>
|
|
175
|
-
<Text bold>A:</Text> {faq.suggestedAnswer}
|
|
176
|
-
</Text>
|
|
177
|
-
</Box>
|
|
178
|
-
))}
|
|
179
|
-
</Box>
|
|
180
|
-
)}
|
|
181
|
-
</Box>
|
|
182
|
-
);
|
|
183
|
-
};
|