@sudu-cli/fronted-preview-mcp 1.0.0-beta.0 → 1.0.0-beta.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.
@@ -0,0 +1,21 @@
1
+ import { Client } from 'chrome-remote-interface';
2
+ import { ToolContext } from '../types.js';
3
+ export interface AutoFixOptions {
4
+ maxIterations?: number;
5
+ timeoutPerIteration?: number;
6
+ stopOnSuccess?: boolean;
7
+ screenshotOnError?: boolean;
8
+ screenshotOnSuccess?: boolean;
9
+ targetErrors?: string[];
10
+ }
11
+ export interface AutoFixResult {
12
+ success: boolean;
13
+ iterations: number;
14
+ errorsFixed: number;
15
+ errorsRemaining: number;
16
+ screenshots: string[];
17
+ messages: string[];
18
+ errors: string[];
19
+ }
20
+ export declare function autoFixLoop(client: Client, context: ToolContext, options?: AutoFixOptions): Promise<AutoFixResult>;
21
+ export declare function handleAutoFixLoop(context: ToolContext, options?: AutoFixOptions): Promise<AutoFixResult>;
@@ -0,0 +1,135 @@
1
+ import { handleCheckPageErrors } from './checkPageErrors.js';
2
+ import { handleGetTypeScriptDiagnostics } from './typescriptDiagnostics.js';
3
+ import { handleTakeScreenshot } from './takeScreenshot.js';
4
+ export async function autoFixLoop(client, context, options = {}) {
5
+ const { maxIterations = 3, timeoutPerIteration = 30000, stopOnSuccess = true, screenshotOnError = true, screenshotOnSuccess = false, targetErrors = [] } = options;
6
+ const result = {
7
+ success: false,
8
+ iterations: 0,
9
+ errorsFixed: 0,
10
+ errorsRemaining: 0,
11
+ screenshots: [],
12
+ messages: [],
13
+ errors: []
14
+ };
15
+ // Check initial state
16
+ const initialConsoleErrors = await handleCheckPageErrors(context);
17
+ const initialTsDiagnostics = await handleGetTypeScriptDiagnostics(context);
18
+ let currentConsoleErrors = [...initialConsoleErrors.errors];
19
+ let currentTsDiagnostics = [...initialTsDiagnostics.diagnostics];
20
+ // Filter errors if targetErrors is specified
21
+ if (targetErrors.length > 0) {
22
+ currentConsoleErrors = currentConsoleErrors.filter(error => targetErrors.some(target => error.message.includes(target)));
23
+ currentTsDiagnostics = currentTsDiagnostics.filter(diagnostic => targetErrors.some(target => diagnostic.message.includes(target)));
24
+ }
25
+ const initialErrorCount = currentConsoleErrors.length + currentTsDiagnostics.length;
26
+ result.errorsRemaining = initialErrorCount;
27
+ // Take initial screenshot if requested
28
+ if (screenshotOnError && initialErrorCount > 0) {
29
+ const screenshot = await handleTakeScreenshot(context, { format: 'png' });
30
+ if (screenshot.success && screenshot.dataUrl) {
31
+ result.screenshots.push(`Initial state - ${initialErrorCount} errors: ${screenshot.dataUrl}`);
32
+ }
33
+ }
34
+ for (let iteration = 0; iteration < maxIterations; iteration++) {
35
+ result.iterations = iteration + 1;
36
+ result.messages.push(`=== Iteration ${iteration + 1} ===`);
37
+ try {
38
+ // Wait for any pending operations
39
+ await new Promise(resolve => setTimeout(resolve, 2000));
40
+ // Check current state
41
+ const currentErrors = await handleCheckPageErrors(context);
42
+ const currentDiagnostics = await handleGetTypeScriptDiagnostics(context);
43
+ // Update error counts
44
+ currentConsoleErrors = [...currentErrors.errors];
45
+ currentTsDiagnostics = [...currentDiagnostics.diagnostics];
46
+ if (targetErrors.length > 0) {
47
+ currentConsoleErrors = currentConsoleErrors.filter(error => targetErrors.some(target => error.message.includes(target)));
48
+ currentTsDiagnostics = currentTsDiagnostics.filter(diagnostic => targetErrors.some(target => diagnostic.message.includes(target)));
49
+ }
50
+ const currentErrorCount = currentConsoleErrors.length + currentTsDiagnostics.length;
51
+ const errorsFixed = initialErrorCount - currentErrorCount;
52
+ result.errorsFixed = errorsFixed;
53
+ result.errorsRemaining = currentErrorCount;
54
+ // Check if we've succeeded
55
+ if (currentErrorCount === 0 && stopOnSuccess) {
56
+ result.success = true;
57
+ result.messages.push(`✅ All errors fixed after ${iteration + 1} iterations`);
58
+ if (screenshotOnSuccess) {
59
+ const screenshot = await handleTakeScreenshot(context, { format: 'png' });
60
+ if (screenshot.success && screenshot.dataUrl) {
61
+ result.screenshots.push(`Success state - no errors: ${screenshot.dataUrl}`);
62
+ }
63
+ }
64
+ break;
65
+ }
66
+ // Log current state
67
+ result.messages.push(`Current errors: ${currentErrorCount} (fixed: ${errorsFixed})`);
68
+ if (currentConsoleErrors.length > 0) {
69
+ result.messages.push('Console errors:');
70
+ currentConsoleErrors.forEach((error) => {
71
+ result.messages.push(` - ${error.message} (${error.type})`);
72
+ });
73
+ }
74
+ if (currentTsDiagnostics.length > 0) {
75
+ result.messages.push('TypeScript diagnostics:');
76
+ currentTsDiagnostics.forEach((diagnostic) => {
77
+ result.messages.push(` - ${diagnostic.message} (${diagnostic.severity})`);
78
+ });
79
+ }
80
+ // Take screenshot if errors still exist
81
+ if (currentErrorCount > 0 && screenshotOnError) {
82
+ const screenshot = await handleTakeScreenshot(context, { format: 'png' });
83
+ if (screenshot.success && screenshot.dataUrl) {
84
+ result.screenshots.push(`Iteration ${iteration + 1} - ${currentErrorCount} errors: ${screenshot.dataUrl}`);
85
+ }
86
+ }
87
+ // If no errors but we're not stopping on success, continue
88
+ if (currentErrorCount === 0) {
89
+ result.messages.push('No errors found, but continuing to next iteration');
90
+ }
91
+ // Wait before next iteration
92
+ await new Promise(resolve => setTimeout(resolve, timeoutPerIteration));
93
+ }
94
+ catch (error) {
95
+ const errorMessage = `Error in iteration ${iteration + 1}: ${error instanceof Error ? error.message : 'Unknown error'}`;
96
+ result.errors.push(errorMessage);
97
+ result.messages.push(errorMessage);
98
+ // Take error screenshot if requested
99
+ if (screenshotOnError) {
100
+ const screenshot = await handleTakeScreenshot(context, { format: 'png' });
101
+ if (screenshot.success && screenshot.dataUrl) {
102
+ result.screenshots.push(`Error in iteration ${iteration + 1}: ${screenshot.dataUrl}`);
103
+ }
104
+ }
105
+ break;
106
+ }
107
+ }
108
+ // Final check
109
+ const finalConsoleErrors = await handleCheckPageErrors(context);
110
+ const finalTsDiagnostics = await handleGetTypeScriptDiagnostics(context);
111
+ let finalErrorCount = finalConsoleErrors.errors.length + finalTsDiagnostics.diagnostics.length;
112
+ if (targetErrors.length > 0) {
113
+ finalErrorCount = finalConsoleErrors.errors.filter((error) => targetErrors.some(target => error.message.includes(target))).length + finalTsDiagnostics.diagnostics.filter((diagnostic) => targetErrors.some(target => diagnostic.message.includes(target))).length;
114
+ }
115
+ result.errorsRemaining = finalErrorCount;
116
+ result.success = finalErrorCount === 0;
117
+ return result;
118
+ }
119
+ // MCP tool handler
120
+ export async function handleAutoFixLoop(context, options) {
121
+ const { chromeClient } = context;
122
+ if (!chromeClient) {
123
+ return {
124
+ success: false,
125
+ iterations: 0,
126
+ errorsFixed: 0,
127
+ errorsRemaining: 0,
128
+ screenshots: [],
129
+ messages: ['Chrome client not connected. Please connect to Chrome first.'],
130
+ errors: ['Chrome client not connected']
131
+ };
132
+ }
133
+ return await autoFixLoop(chromeClient, context, options);
134
+ }
135
+ //# sourceMappingURL=autoFixLoop.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"autoFixLoop.js","sourceRoot":"","sources":["../../src/handlers/autoFixLoop.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { MCPToolResponse } from '../types.js';
2
+ interface CheckPageErrorsArgs {
3
+ projectDir?: string;
4
+ customPort?: number;
5
+ cdpPort?: number;
6
+ waitForLoadMs?: number;
7
+ }
8
+ declare function handleCheckPageErrors(args: CheckPageErrorsArgs): Promise<MCPToolResponse>;
9
+ export { handleCheckPageErrors };
@@ -0,0 +1,168 @@
1
+ import { detectFramework } from '../detectors/frameworkDetector.js';
2
+ import { startServer } from '../serverManager.js';
3
+ import CDP from 'chrome-remote-interface';
4
+ async function handleCheckPageErrors(args) {
5
+ const projectDir = args.projectDir || process.cwd();
6
+ const cdpPort = args.cdpPort || 9222;
7
+ const waitForLoadMs = args.waitForLoadMs || 3000;
8
+ let client = null;
9
+ try {
10
+ // Step 1: Detect framework and start/get dev server
11
+ const info = await detectFramework(projectDir);
12
+ if (!info.devScript) {
13
+ return {
14
+ content: [
15
+ {
16
+ type: 'text',
17
+ text: JSON.stringify({
18
+ error: 'No dev script found',
19
+ availableScripts: Object.keys(info.npmScripts),
20
+ projectDir,
21
+ }, null, 2),
22
+ },
23
+ ],
24
+ isError: true,
25
+ };
26
+ }
27
+ // Step 2: Start dev server (or reuse existing)
28
+ const port = args.customPort || info.port;
29
+ const command = `npm run ${info.devScript}`;
30
+ const status = await startServer(projectDir, command, port);
31
+ const pageUrl = status.url;
32
+ // Step 3: Connect to Chrome via CDP
33
+ const cdpOptions = { port: cdpPort };
34
+ try {
35
+ client = await CDP(cdpOptions);
36
+ }
37
+ catch (cdpErr) {
38
+ return {
39
+ content: [
40
+ {
41
+ type: 'text',
42
+ text: JSON.stringify({
43
+ error: `Failed to connect to Chrome DevTools Protocol on port ${cdpPort}. Ensure Chrome is running with --remote-debugging-port=${cdpPort}`,
44
+ details: cdpErr instanceof Error ? cdpErr.message : String(cdpErr),
45
+ pageUrl,
46
+ suggestion: 'Start Chrome with: chrome --remote-debugging-port=9222 --user-data-dir=/tmp/chrome-debug',
47
+ }, null, 2),
48
+ },
49
+ ],
50
+ isError: true,
51
+ };
52
+ }
53
+ if (!client) {
54
+ return {
55
+ content: [
56
+ {
57
+ type: 'text',
58
+ text: JSON.stringify({
59
+ error: 'Failed to create CDP client',
60
+ pageUrl,
61
+ }, null, 2),
62
+ },
63
+ ],
64
+ isError: true,
65
+ };
66
+ }
67
+ // Enable domains
68
+ const { Page, Runtime, Network, Log } = client;
69
+ await Promise.all([
70
+ Page.enable(),
71
+ Runtime.enable(),
72
+ Network.enable(),
73
+ Log.enable(),
74
+ ]);
75
+ // Collect console messages
76
+ const consoleMessages = [];
77
+ const networkErrors = [];
78
+ // Listen for console messages (Log.entryAdded)
79
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
80
+ client.on('Log.entryAdded', (params) => {
81
+ const entry = params.entry;
82
+ consoleMessages.push({
83
+ type: entry.level,
84
+ text: entry.text,
85
+ url: entry.url,
86
+ lineNumber: entry.lineNumber,
87
+ stackTrace: entry.stackTrace,
88
+ });
89
+ });
90
+ // Listen for network errors (Network.responseReceived)
91
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
92
+ client.on('Network.responseReceived', (params) => {
93
+ const response = params.response;
94
+ if (response.status >= 400) {
95
+ networkErrors.push({
96
+ url: response.url,
97
+ method: response.requestMethod || 'GET',
98
+ statusCode: response.status,
99
+ errorText: `HTTP ${response.status}`,
100
+ });
101
+ }
102
+ });
103
+ // Listen for network loading failed
104
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
105
+ client.on('Network.loadingFailed', (params) => {
106
+ networkErrors.push({
107
+ url: `request:${params.requestId}`,
108
+ method: 'UNKNOWN',
109
+ errorText: params.errorText,
110
+ });
111
+ });
112
+ // Step 4: Navigate to the page
113
+ await Page.navigate({ url: pageUrl });
114
+ // Wait for page load
115
+ await new Promise((resolve) => {
116
+ const timeout = setTimeout(resolve, waitForLoadMs);
117
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
118
+ const handler = (params) => {
119
+ clearTimeout(timeout);
120
+ resolve();
121
+ };
122
+ client.on('Page.loadEventFired', handler);
123
+ });
124
+ // Give a bit more time for async console messages
125
+ await new Promise((resolve) => setTimeout(resolve, 1000));
126
+ // Step 5: Compile report
127
+ const errors = consoleMessages.filter((m) => m.type === 'error');
128
+ const warnings = consoleMessages.filter((m) => m.type === 'warning');
129
+ const report = {
130
+ pageUrl,
131
+ framework: info.framework,
132
+ port: status.port,
133
+ consoleMessages,
134
+ networkErrors,
135
+ hasErrors: errors.length > 0 || networkErrors.length > 0,
136
+ errorCount: errors.length + networkErrors.length,
137
+ warningCount: warnings.length,
138
+ timestamp: new Date().toISOString(),
139
+ };
140
+ return {
141
+ content: [
142
+ {
143
+ type: 'text',
144
+ text: JSON.stringify(report, null, 2),
145
+ },
146
+ ],
147
+ };
148
+ }
149
+ catch (err) {
150
+ const errorMessage = err instanceof Error ? err.message : String(err);
151
+ return {
152
+ content: [{ type: 'text', text: JSON.stringify({ error: errorMessage }, null, 2) }],
153
+ isError: true,
154
+ };
155
+ }
156
+ finally {
157
+ if (client) {
158
+ try {
159
+ await client.close();
160
+ }
161
+ catch {
162
+ // Ignore cleanup errors
163
+ }
164
+ }
165
+ }
166
+ }
167
+ export { handleCheckPageErrors };
168
+ //# sourceMappingURL=checkPageErrors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checkPageErrors.js","sourceRoot":"","sources":["../../src/handlers/checkPageErrors.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { MCPToolResponse } from '../types.js';
2
+ interface PickElementArgs {
3
+ projectDir?: string;
4
+ customPort?: number;
5
+ cdpPort?: number;
6
+ selector?: string;
7
+ waitForLoadMs?: number;
8
+ }
9
+ declare function handlePickElement(args: PickElementArgs): Promise<MCPToolResponse>;
10
+ export { handlePickElement };