@sudu-cli/fronted-preview-mcp 1.0.0-beta.2 → 1.0.0-beta.4
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/cdp/connectionManager.d.ts +57 -0
- package/dist/cdp/connectionManager.js +153 -0
- package/dist/cdp/connectionManager.js.map +1 -0
- package/dist/cli.js +2 -1
- package/dist/cli.js.map +1 -1
- package/dist/constants.d.ts +19 -0
- package/dist/constants.js +26 -0
- package/dist/constants.js.map +1 -0
- package/dist/detectors/frameworkDetector.js +17 -13
- package/dist/detectors/frameworkDetector.js.map +1 -1
- package/dist/handlers/autoFixLoop.d.ts +32 -5
- package/dist/handlers/autoFixLoop.js +122 -47
- package/dist/handlers/autoFixLoop.js.map +1 -1
- package/dist/handlers/checkPageErrors.js +11 -50
- package/dist/handlers/checkPageErrors.js.map +1 -1
- package/dist/handlers/typescriptDiagnostics.js +4 -25
- package/dist/handlers/typescriptDiagnostics.js.map +1 -1
- package/dist/index.js +27 -133
- package/dist/index.js.map +1 -1
- package/dist/serverManager.d.ts +22 -4
- package/dist/serverManager.js +215 -140
- package/dist/serverManager.js.map +1 -1
- package/dist/types.d.ts +9 -0
- package/dist/types.js +21 -1
- package/dist/types.js.map +1 -1
- package/dist/version.d.ts +7 -0
- package/dist/version.js +10 -0
- package/dist/version.js.map +1 -0
- package/package.json +1 -1
- package/templates/init/instructions.md +1 -11
- package/templates/init/opencode.json +1 -1
- package/dist/handlers/pickElement.d.ts +0 -10
- package/dist/handlers/pickElement.js +0 -413
- package/dist/handlers/pickElement.js.map +0 -1
- package/dist/handlers/takeScreenshot.d.ts +0 -17
- package/dist/handlers/takeScreenshot.js +0 -83
- package/dist/handlers/takeScreenshot.js.map +0 -1
package/dist/serverManager.js
CHANGED
|
@@ -1,166 +1,241 @@
|
|
|
1
1
|
import { spawn } from 'node:child_process';
|
|
2
2
|
import * as net from 'node:net';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
3
|
+
import { TIMEOUTS } from './constants.js';
|
|
4
|
+
export class ServerManager {
|
|
5
|
+
static instance = null;
|
|
6
|
+
activeServer = null;
|
|
7
|
+
startLocks = new Map();
|
|
8
|
+
shutdownLock = null;
|
|
9
|
+
constructor() { }
|
|
10
|
+
static getInstance() {
|
|
11
|
+
if (!ServerManager.instance) {
|
|
12
|
+
ServerManager.instance = new ServerManager();
|
|
13
|
+
}
|
|
14
|
+
return ServerManager.instance;
|
|
15
|
+
}
|
|
16
|
+
static resetInstance() {
|
|
17
|
+
ServerManager.instance = null;
|
|
18
|
+
}
|
|
19
|
+
isPortAvailable(port) {
|
|
20
|
+
return new Promise((resolve) => {
|
|
21
|
+
const server = net.createServer();
|
|
22
|
+
server.once('error', () => resolve(false));
|
|
23
|
+
server.once('listening', () => {
|
|
24
|
+
server.close();
|
|
25
|
+
resolve(true);
|
|
26
|
+
});
|
|
27
|
+
server.listen(port, '127.0.0.1');
|
|
11
28
|
});
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
29
|
+
}
|
|
30
|
+
waitForServerReady(port, timeoutMs = TIMEOUTS.SERVER_START_TIMEOUT) {
|
|
31
|
+
const start = Date.now();
|
|
32
|
+
return new Promise((resolve) => {
|
|
33
|
+
const check = async () => {
|
|
34
|
+
const available = await this.isPortAvailable(port);
|
|
35
|
+
if (!available) {
|
|
36
|
+
resolve(true); // port is in use = server is ready
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
if (Date.now() - start > timeoutMs) {
|
|
40
|
+
resolve(false); // timeout
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
setTimeout(check, TIMEOUTS.PORT_CHECK_INTERVAL);
|
|
44
|
+
};
|
|
45
|
+
check();
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
async startServer(projectDir, devCommand, port, timeoutMs = TIMEOUTS.SERVER_START_TIMEOUT) {
|
|
49
|
+
// Check if there's already a start in progress for this port
|
|
50
|
+
const existingLock = this.startLocks.get(port);
|
|
51
|
+
if (existingLock) {
|
|
52
|
+
return existingLock;
|
|
53
|
+
}
|
|
54
|
+
// Create the start operation with lock
|
|
55
|
+
const startPromise = this.doStartServer(projectDir, devCommand, port, timeoutMs);
|
|
56
|
+
this.startLocks.set(port, startPromise);
|
|
57
|
+
try {
|
|
58
|
+
const result = await startPromise;
|
|
59
|
+
return result;
|
|
60
|
+
}
|
|
61
|
+
finally {
|
|
62
|
+
this.startLocks.delete(port);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
async doStartServer(projectDir, devCommand, port, timeoutMs) {
|
|
66
|
+
// Atomic check: if we have a running server on this port, return it
|
|
67
|
+
if (this.activeServer && this.activeServer.port === port) {
|
|
68
|
+
const isRunning = this.activeServer.process.exitCode === null;
|
|
69
|
+
if (isRunning) {
|
|
70
|
+
return {
|
|
71
|
+
url: this.activeServer.url,
|
|
72
|
+
port: this.activeServer.port,
|
|
73
|
+
pid: this.activeServer.process.pid || 0,
|
|
74
|
+
ready: true,
|
|
75
|
+
startedAt: new Date(this.activeServer.startTime).toISOString(),
|
|
76
|
+
};
|
|
27
77
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
// If already running, return current status
|
|
35
|
-
if (activeServer) {
|
|
36
|
-
const isRunning = activeServer.process.exitCode === null;
|
|
37
|
-
if (isRunning) {
|
|
78
|
+
// Process died, clean up atomically
|
|
79
|
+
this.activeServer = null;
|
|
80
|
+
}
|
|
81
|
+
// Check if port is already in use (server running externally)
|
|
82
|
+
const portAvailable = await this.isPortAvailable(port);
|
|
83
|
+
if (!portAvailable) {
|
|
38
84
|
return {
|
|
39
|
-
url:
|
|
40
|
-
port
|
|
41
|
-
pid:
|
|
85
|
+
url: `http://localhost:${port}`,
|
|
86
|
+
port,
|
|
87
|
+
pid: 0,
|
|
42
88
|
ready: true,
|
|
43
|
-
startedAt: new Date(
|
|
89
|
+
startedAt: new Date().toISOString(),
|
|
44
90
|
};
|
|
45
91
|
}
|
|
46
|
-
//
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
92
|
+
// Determine shell command
|
|
93
|
+
const isWin = process.platform === 'win32';
|
|
94
|
+
const shellCmd = isWin ? `cmd /c "${devCommand}"` : devCommand;
|
|
95
|
+
const child = spawn(shellCmd, [], {
|
|
96
|
+
cwd: projectDir,
|
|
97
|
+
shell: true,
|
|
98
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
99
|
+
windowsHide: true,
|
|
100
|
+
});
|
|
101
|
+
let urlConfirmed = false;
|
|
102
|
+
child.stdout?.on('data', (data) => {
|
|
103
|
+
const text = data.toString();
|
|
104
|
+
// Vite prints local URL on stdout
|
|
105
|
+
if (text.includes('Local:')) {
|
|
106
|
+
const urlMatch = text.match(/http:\/\/localhost:\d+/);
|
|
107
|
+
if (urlMatch) {
|
|
108
|
+
urlConfirmed = true;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
child.stderr?.on('data', (data) => {
|
|
113
|
+
// Some frameworks output to stderr
|
|
114
|
+
});
|
|
115
|
+
// Handle process errors
|
|
116
|
+
const errorPromise = new Promise((_, reject) => {
|
|
117
|
+
child.on('error', (err) => {
|
|
118
|
+
this.activeServer = null;
|
|
119
|
+
reject(new Error(`Failed to start dev server: ${err.message}`));
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
// Handle process exit
|
|
123
|
+
child.on('exit', (code) => {
|
|
124
|
+
if (this.activeServer?.process === child) {
|
|
125
|
+
this.activeServer = null;
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
// Wait for server to be ready with timeout
|
|
129
|
+
const ready = await Promise.race([
|
|
130
|
+
this.waitForServerReady(port, timeoutMs),
|
|
131
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error(`Timeout waiting for server on port ${port}`)), timeoutMs + TIMEOUTS.PORT_CHECK_INTERVAL)),
|
|
132
|
+
errorPromise.then(() => false)
|
|
133
|
+
]);
|
|
134
|
+
if (!ready) {
|
|
135
|
+
// Kill the process if it didn't start in time
|
|
136
|
+
try {
|
|
137
|
+
child.kill();
|
|
138
|
+
}
|
|
139
|
+
catch {
|
|
140
|
+
// Ignore kill errors
|
|
141
|
+
}
|
|
142
|
+
throw new Error(`Dev server did not start within ${timeoutMs}ms on port ${port}`);
|
|
143
|
+
}
|
|
144
|
+
const url = `http://localhost:${port}`;
|
|
145
|
+
this.activeServer = {
|
|
146
|
+
process: child,
|
|
147
|
+
port,
|
|
148
|
+
url,
|
|
149
|
+
startTime: Date.now(),
|
|
150
|
+
};
|
|
52
151
|
return {
|
|
53
|
-
url
|
|
152
|
+
url,
|
|
54
153
|
port,
|
|
55
|
-
pid: 0,
|
|
154
|
+
pid: child.pid || 0,
|
|
56
155
|
ready: true,
|
|
57
156
|
startedAt: new Date().toISOString(),
|
|
58
157
|
};
|
|
59
158
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
cwd: projectDir,
|
|
65
|
-
shell: true,
|
|
66
|
-
stdio: ['ignore', 'pipe', 'pipe'],
|
|
67
|
-
windowsHide: true,
|
|
68
|
-
});
|
|
69
|
-
child.stdout?.on('data', (data) => {
|
|
70
|
-
// Optionally log or filter output
|
|
71
|
-
const text = data.toString();
|
|
72
|
-
// Vite prints local URL on stdout
|
|
73
|
-
if (text.includes('Local:')) {
|
|
74
|
-
const urlMatch = text.match(/http:\/\/localhost:\d+/);
|
|
75
|
-
if (urlMatch) {
|
|
76
|
-
// URL is confirmed
|
|
77
|
-
}
|
|
159
|
+
async stopServer() {
|
|
160
|
+
// If shutdown already in progress, return that promise
|
|
161
|
+
if (this.shutdownLock) {
|
|
162
|
+
return this.shutdownLock;
|
|
78
163
|
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
});
|
|
87
|
-
child.on('exit', (code) => {
|
|
88
|
-
if (activeServer?.process === child) {
|
|
89
|
-
activeServer = null;
|
|
164
|
+
const shutdownPromise = this.doStopServer();
|
|
165
|
+
this.shutdownLock = shutdownPromise;
|
|
166
|
+
try {
|
|
167
|
+
return await shutdownPromise;
|
|
168
|
+
}
|
|
169
|
+
finally {
|
|
170
|
+
this.shutdownLock = null;
|
|
90
171
|
}
|
|
91
|
-
});
|
|
92
|
-
// Wait for port to be ready
|
|
93
|
-
const ready = await waitForPort(port, 30000);
|
|
94
|
-
if (!ready) {
|
|
95
|
-
// Kill the process if it didn't start in time
|
|
96
|
-
child.kill();
|
|
97
|
-
throw new Error(`Dev server did not start within 30 seconds on port ${port}`);
|
|
98
|
-
}
|
|
99
|
-
const url = `http://localhost:${port}`;
|
|
100
|
-
activeServer = {
|
|
101
|
-
process: child,
|
|
102
|
-
port,
|
|
103
|
-
url,
|
|
104
|
-
startTime: Date.now(),
|
|
105
|
-
};
|
|
106
|
-
return {
|
|
107
|
-
url,
|
|
108
|
-
port,
|
|
109
|
-
pid: child.pid || 0,
|
|
110
|
-
ready: true,
|
|
111
|
-
startedAt: new Date().toISOString(),
|
|
112
|
-
};
|
|
113
|
-
}
|
|
114
|
-
async function stopServer() {
|
|
115
|
-
if (!activeServer) {
|
|
116
|
-
return { success: true, message: 'No active dev server to stop.' };
|
|
117
172
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
// Try graceful shutdown first
|
|
122
|
-
const isWin = process.platform === 'win32';
|
|
123
|
-
if (isWin) {
|
|
124
|
-
spawn('taskkill', ['/pid', String(child.pid), '/f', '/t']);
|
|
173
|
+
async doStopServer() {
|
|
174
|
+
if (!this.activeServer) {
|
|
175
|
+
return { success: true, message: 'No active dev server to stop.' };
|
|
125
176
|
}
|
|
126
|
-
|
|
127
|
-
|
|
177
|
+
const child = this.activeServer.process;
|
|
178
|
+
const port = this.activeServer.port;
|
|
179
|
+
try {
|
|
180
|
+
// Try graceful shutdown first
|
|
181
|
+
const isWin = process.platform === 'win32';
|
|
182
|
+
if (isWin) {
|
|
183
|
+
spawn('taskkill', ['/pid', String(child.pid), '/f', '/t']);
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
child.kill('SIGTERM');
|
|
187
|
+
}
|
|
188
|
+
// Wait for process to exit with timeout
|
|
189
|
+
await Promise.race([
|
|
190
|
+
new Promise((resolve) => {
|
|
191
|
+
child.on('exit', () => resolve());
|
|
192
|
+
}),
|
|
193
|
+
new Promise((resolve) => {
|
|
194
|
+
setTimeout(() => {
|
|
195
|
+
try {
|
|
196
|
+
child.kill('SIGKILL');
|
|
197
|
+
}
|
|
198
|
+
catch { }
|
|
199
|
+
resolve();
|
|
200
|
+
}, TIMEOUTS.SERVER_STOP_TIMEOUT);
|
|
201
|
+
})
|
|
202
|
+
]);
|
|
203
|
+
this.activeServer = null;
|
|
204
|
+
return {
|
|
205
|
+
success: true,
|
|
206
|
+
message: `Dev server on port ${port} stopped.`,
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
catch (err) {
|
|
210
|
+
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
211
|
+
this.activeServer = null;
|
|
212
|
+
return {
|
|
213
|
+
success: false,
|
|
214
|
+
message: `Failed to stop dev server: ${errorMessage}`,
|
|
215
|
+
};
|
|
128
216
|
}
|
|
129
|
-
// Wait for process to exit
|
|
130
|
-
await new Promise((resolve) => {
|
|
131
|
-
const timeout = setTimeout(() => {
|
|
132
|
-
child.kill('SIGKILL');
|
|
133
|
-
resolve();
|
|
134
|
-
}, 5000);
|
|
135
|
-
child.on('exit', () => {
|
|
136
|
-
clearTimeout(timeout);
|
|
137
|
-
resolve();
|
|
138
|
-
});
|
|
139
|
-
});
|
|
140
|
-
activeServer = null;
|
|
141
|
-
return {
|
|
142
|
-
success: true,
|
|
143
|
-
message: `Dev server on port ${port} stopped.`,
|
|
144
|
-
};
|
|
145
217
|
}
|
|
146
|
-
|
|
147
|
-
|
|
218
|
+
getServerStatus() {
|
|
219
|
+
if (!this.activeServer)
|
|
220
|
+
return null;
|
|
148
221
|
return {
|
|
149
|
-
|
|
150
|
-
|
|
222
|
+
url: this.activeServer.url,
|
|
223
|
+
port: this.activeServer.port,
|
|
224
|
+
pid: this.activeServer.process.pid || 0,
|
|
225
|
+
ready: this.activeServer.process.exitCode === null,
|
|
226
|
+
startedAt: new Date(this.activeServer.startTime).toISOString(),
|
|
151
227
|
};
|
|
152
228
|
}
|
|
153
229
|
}
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
return
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
230
|
+
// Backward compatibility exports
|
|
231
|
+
const manager = ServerManager.getInstance();
|
|
232
|
+
export async function startServer(projectDir, devCommand, port) {
|
|
233
|
+
return manager.startServer(projectDir, devCommand, port);
|
|
234
|
+
}
|
|
235
|
+
export async function stopServer() {
|
|
236
|
+
return manager.stopServer();
|
|
237
|
+
}
|
|
238
|
+
export function getServerStatus() {
|
|
239
|
+
return manager.getServerStatus();
|
|
164
240
|
}
|
|
165
|
-
export { startServer, stopServer, getServerStatus };
|
|
166
241
|
//# sourceMappingURL=serverManager.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serverManager.js","sourceRoot":"","sources":["../src/serverManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAqB,MAAM,oBAAoB,CAAC;AAC9D,OAAO,KAAK,GAAG,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"serverManager.js","sourceRoot":"","sources":["../src/serverManager.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -28,3 +28,12 @@ export interface ToolContext {
|
|
|
28
28
|
port?: number;
|
|
29
29
|
cdpPort?: number;
|
|
30
30
|
}
|
|
31
|
+
export type MCPErrorCode = 'FRAMEWORK_NOT_DETECTED' | 'DEV_SERVER_START_FAILED' | 'CDP_CONNECTION_FAILED' | 'PAGE_NAVIGATION_FAILED' | 'TYPE_CHECK_FAILED' | 'CONFIG_NOT_FOUND' | 'INVALID_PROJECT_DIR' | 'PORT_IN_USE' | 'TIMEOUT' | 'UNKNOWN_ERROR';
|
|
32
|
+
export interface MCPError {
|
|
33
|
+
code: MCPErrorCode;
|
|
34
|
+
message: string;
|
|
35
|
+
details?: unknown;
|
|
36
|
+
suggestion?: string;
|
|
37
|
+
}
|
|
38
|
+
export declare function createMCPError(code: MCPErrorCode, message: string, details?: unknown, suggestion?: string): MCPToolResponse;
|
|
39
|
+
export declare function createMCPSuccess(data: unknown): MCPToolResponse;
|
package/dist/types.js
CHANGED
|
@@ -1,2 +1,22 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export function createMCPError(code, message, details, suggestion) {
|
|
2
|
+
return {
|
|
3
|
+
content: [
|
|
4
|
+
{
|
|
5
|
+
type: 'text',
|
|
6
|
+
text: JSON.stringify({ error: { code, message, details, suggestion } }, null, 2),
|
|
7
|
+
},
|
|
8
|
+
],
|
|
9
|
+
isError: true,
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
export function createMCPSuccess(data) {
|
|
13
|
+
return {
|
|
14
|
+
content: [
|
|
15
|
+
{
|
|
16
|
+
type: 'text',
|
|
17
|
+
text: JSON.stringify(data, null, 2),
|
|
18
|
+
},
|
|
19
|
+
],
|
|
20
|
+
};
|
|
21
|
+
}
|
|
2
22
|
//# sourceMappingURL=types.js.map
|
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAsDA,MAAM,UAAU,cAAc,CAC5B,IAAkB,EAClB,OAAe,EACf,OAAiB,EACjB,UAAmB;IAEnB,OAAO;QACL,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;aACjF;SACF;QACD,OAAO,EAAE,IAAI;KACd,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,IAAa;IAC5C,OAAO;QACL,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;aACpC;SACF;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare const VERSION = "1.0.0-beta.4";
|
|
2
|
+
export declare const VERSION_MAJOR = 1;
|
|
3
|
+
export declare const VERSION_MINOR = 0;
|
|
4
|
+
export declare const VERSION_PATCH = 0;
|
|
5
|
+
export declare const VERSION_PRERELEASE = "beta.4";
|
|
6
|
+
export declare const VERSION_STRING = "1.0.0-beta.4";
|
|
7
|
+
export declare const VERSION_SHORT = "1.0.0";
|
package/dist/version.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// Version management - single source of truth
|
|
2
|
+
export const VERSION = '1.0.0-beta.4';
|
|
3
|
+
export const VERSION_MAJOR = 1;
|
|
4
|
+
export const VERSION_MINOR = 0;
|
|
5
|
+
export const VERSION_PATCH = 0;
|
|
6
|
+
export const VERSION_PRERELEASE = 'beta.4';
|
|
7
|
+
// Formatted version strings
|
|
8
|
+
export const VERSION_STRING = VERSION;
|
|
9
|
+
export const VERSION_SHORT = `${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}`;
|
|
10
|
+
//# sourceMappingURL=version.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,8CAA8C;AAC9C,MAAM,CAAC,MAAM,OAAO,GAAG,cAAc,CAAC;AACtC,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAC;AAC/B,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAC;AAC/B,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAC;AAC/B,MAAM,CAAC,MAAM,kBAAkB,GAAG,QAAQ,CAAC;AAE3C,4BAA4B;AAC5B,MAAM,CAAC,MAAM,cAAc,GAAG,OAAO,CAAC;AACtC,MAAM,CAAC,MAAM,aAAa,GAAG,GAAG,aAAa,IAAI,aAAa,IAAI,aAAa,EAAE,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sudu-cli/fronted-preview-mcp",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.4",
|
|
4
4
|
"description": "MCP server for frontend project detection, dev server management, and preview workflow. Pairs with chrome-devtools-mcp for automated frontend checking.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -22,14 +22,6 @@
|
|
|
22
22
|
3. **`auto_fix_loop`** — 自动检测和修复错误(可选)
|
|
23
23
|
4. **汇总结果** — 告诉用户:错误类型、数量、修复建议
|
|
24
24
|
|
|
25
|
-
## 元素分析与截图工作流
|
|
26
|
-
|
|
27
|
-
当用户想"分析元素"、"截图"、"查看样式"时,按照以下步骤:
|
|
28
|
-
|
|
29
|
-
1. **`pick_element`** — 拾取页面元素获取详细信息
|
|
30
|
-
2. **`take_screenshot`** — 截图页面或特定元素
|
|
31
|
-
3. **汇总结果** — 告诉用户:元素信息、样式、截图结果
|
|
32
|
-
|
|
33
25
|
## 工具快速参考
|
|
34
26
|
|
|
35
27
|
| 工具 | 用途 | 优先使用场景 |
|
|
@@ -43,8 +35,6 @@
|
|
|
43
35
|
| `check_page_errors` | 检测页面 console 错误和网络失败 | 检查页面是否有 JavaScript 错误 |
|
|
44
36
|
| `get_typescript_diagnostics` | 检测 TypeScript 类型错误 | 检查代码类型错误和警告 |
|
|
45
37
|
| `auto_fix_loop` | 自动检测和修复错误 | 自动修复所有检测到的错误 |
|
|
46
|
-
| **元素分析工具** | | |
|
|
47
|
-
| `pick_element` | 拾取页面元素获取详细信息 | 分析特定元素的信息和样式 |
|
|
48
38
|
| **chrome-devtools** | | |
|
|
49
39
|
| `chrome-devtools `navigate_page` | 打开 URL | 拿到 URL 后立即使用 |
|
|
50
40
|
| `chrome-devtools `list_console_messages` | 检查 console 错误 | 页面加载完成后 |
|
|
@@ -57,4 +47,4 @@
|
|
|
57
47
|
- `quick_preview` 已包含 framework 检测,不要再重复调 `get_project_info`
|
|
58
48
|
- dev server 可以保持运行,不需要每次用完就关闭
|
|
59
49
|
- 使用 `auto_fix_loop` 时需要 Chrome 运行在调试模式(--remote-debugging-port=9222)
|
|
60
|
-
- `
|
|
50
|
+
- 元素拾取和截图功能已委托给 `chrome-devtools-mcp`
|
|
@@ -1,10 +0,0 @@
|
|
|
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 };
|