@dynamicu/chromedebug-mcp 2.6.7 → 2.7.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.
- package/CLAUDE.md +1 -1
- package/README.md +1 -1
- package/chrome-extension/background.js +611 -505
- package/chrome-extension/browser-recording-manager.js +1 -1
- package/chrome-extension/chrome-debug-logger.js +168 -0
- package/chrome-extension/console-interception-library.js +430 -0
- package/chrome-extension/content.css +16 -16
- package/chrome-extension/content.js +458 -126
- package/chrome-extension/extension-config.js +1 -1
- package/chrome-extension/license-helper.js +26 -0
- package/chrome-extension/manifest.free.json +0 -3
- package/chrome-extension/options.js +1 -1
- package/chrome-extension/popup.html +221 -191
- package/chrome-extension/popup.js +88 -379
- package/chrome-extension/pro/enhanced-capture.js +406 -0
- package/chrome-extension/pro/frame-editor.html +410 -0
- package/chrome-extension/pro/frame-editor.js +1496 -0
- package/chrome-extension/pro/function-tracker.js +843 -0
- package/chrome-extension/pro/jszip.min.js +13 -0
- package/dist/chromedebug-extension-free.zip +0 -0
- package/package.json +3 -1
- package/scripts/webpack.config.free.cjs +8 -8
- package/scripts/webpack.config.pro.cjs +2 -0
- package/src/cli.js +2 -2
- package/src/database.js +55 -7
- package/src/index.js +9 -6
- package/src/mcp/server.js +2 -2
- package/src/services/process-manager.js +10 -6
- package/src/services/process-tracker.js +10 -5
- package/src/services/profile-manager.js +17 -2
- package/src/validation/schemas.js +2 -2
- package/src/index-direct.js +0 -157
- package/src/index-modular.js +0 -219
- package/src/index-monolithic-backup.js +0 -2230
- package/src/legacy/chrome-controller-old.js +0 -1406
- package/src/legacy/index-express.js +0 -625
- package/src/legacy/index-old.js +0 -977
- package/src/legacy/routes.js +0 -260
- package/src/legacy/shared-storage.js +0 -101
package/src/legacy/routes.js
DELETED
|
@@ -1,260 +0,0 @@
|
|
|
1
|
-
import express from 'express';
|
|
2
|
-
|
|
3
|
-
export function createRoutes(chromeController) {
|
|
4
|
-
const router = express.Router();
|
|
5
|
-
|
|
6
|
-
const asyncHandler = (fn) => (req, res, next) => {
|
|
7
|
-
Promise.resolve(fn(req, res, next)).catch(next);
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
router.post('/chrome-pilot/launch', asyncHandler(async (req, res) => {
|
|
11
|
-
const result = await chromeController.launch();
|
|
12
|
-
res.json(result);
|
|
13
|
-
}));
|
|
14
|
-
|
|
15
|
-
router.post('/chrome-pilot/navigate', asyncHandler(async (req, res) => {
|
|
16
|
-
const { url } = req.body;
|
|
17
|
-
if (!url) {
|
|
18
|
-
return res.status(400).json({ error: 'URL is required' });
|
|
19
|
-
}
|
|
20
|
-
const result = await chromeController.navigateTo(url);
|
|
21
|
-
res.json(result);
|
|
22
|
-
}));
|
|
23
|
-
|
|
24
|
-
router.post('/chrome-pilot/pause', asyncHandler(async (req, res) => {
|
|
25
|
-
const result = await chromeController.pause();
|
|
26
|
-
res.json(result);
|
|
27
|
-
}));
|
|
28
|
-
|
|
29
|
-
router.post('/chrome-pilot/resume', asyncHandler(async (req, res) => {
|
|
30
|
-
const result = await chromeController.resume();
|
|
31
|
-
res.json(result);
|
|
32
|
-
}));
|
|
33
|
-
|
|
34
|
-
router.post('/chrome-pilot/step-over', asyncHandler(async (req, res) => {
|
|
35
|
-
const result = await chromeController.stepOver();
|
|
36
|
-
res.json(result);
|
|
37
|
-
}));
|
|
38
|
-
|
|
39
|
-
router.post('/chrome-pilot/evaluate', asyncHandler(async (req, res) => {
|
|
40
|
-
const { expression } = req.body;
|
|
41
|
-
if (!expression) {
|
|
42
|
-
return res.status(400).json({ error: 'Expression is required' });
|
|
43
|
-
}
|
|
44
|
-
const result = await chromeController.evaluate(expression);
|
|
45
|
-
res.json(result);
|
|
46
|
-
}));
|
|
47
|
-
|
|
48
|
-
router.get('/chrome-pilot/scopes', asyncHandler(async (req, res) => {
|
|
49
|
-
const result = await chromeController.getScopes();
|
|
50
|
-
res.json(result);
|
|
51
|
-
}));
|
|
52
|
-
|
|
53
|
-
router.post('/chrome-pilot/set-breakpoint', asyncHandler(async (req, res) => {
|
|
54
|
-
const { url, lineNumber } = req.body;
|
|
55
|
-
if (!url || lineNumber === undefined) {
|
|
56
|
-
return res.status(400).json({ error: 'URL and lineNumber are required' });
|
|
57
|
-
}
|
|
58
|
-
const result = await chromeController.setBreakpoint(url, lineNumber);
|
|
59
|
-
res.json(result);
|
|
60
|
-
}));
|
|
61
|
-
|
|
62
|
-
router.get('/chrome-pilot/logs', asyncHandler(async (req, res) => {
|
|
63
|
-
const result = chromeController.getLogs();
|
|
64
|
-
res.json(result);
|
|
65
|
-
}));
|
|
66
|
-
|
|
67
|
-
router.post('/chrome-pilot/screenshot', asyncHandler(async (req, res) => {
|
|
68
|
-
const { type, fullPage, path } = req.body || {};
|
|
69
|
-
const options = {};
|
|
70
|
-
if (type) options.type = type;
|
|
71
|
-
if (fullPage !== undefined) options.fullPage = fullPage;
|
|
72
|
-
if (path) options.path = path;
|
|
73
|
-
|
|
74
|
-
const result = await chromeController.takeScreenshot(options);
|
|
75
|
-
res.json(result);
|
|
76
|
-
}));
|
|
77
|
-
|
|
78
|
-
router.post('/chrome-pilot/dom-intent', asyncHandler(async (req, res) => {
|
|
79
|
-
const { selector, instruction, elementInfo } = req.body;
|
|
80
|
-
if (!selector) {
|
|
81
|
-
return res.status(400).json({ error: 'Selector is required' });
|
|
82
|
-
}
|
|
83
|
-
const result = await chromeController.selectElement(selector, instruction, elementInfo);
|
|
84
|
-
res.json(result);
|
|
85
|
-
}));
|
|
86
|
-
|
|
87
|
-
router.get('/chrome-pilot/status', asyncHandler(async (req, res) => {
|
|
88
|
-
const isConnected = await chromeController.isConnected();
|
|
89
|
-
res.json({ connected: isConnected, status: 'ok' });
|
|
90
|
-
}));
|
|
91
|
-
|
|
92
|
-
// Port discovery endpoint for Claude to find the server
|
|
93
|
-
router.get('/chrome-pilot/port', (req, res) => {
|
|
94
|
-
const serverPort = process.env.SERVER_PORT || process.env.PORT || 3000;
|
|
95
|
-
res.json({
|
|
96
|
-
port: serverPort,
|
|
97
|
-
message: 'Chrome Debug server port',
|
|
98
|
-
timestamp: new Date().toISOString()
|
|
99
|
-
});
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
router.get('/chrome-pilot/recording/:id', asyncHandler(async (req, res) => {
|
|
103
|
-
// Get recording for Claude to analyze
|
|
104
|
-
const result = await chromeController.getRecording(req.params.id);
|
|
105
|
-
if (result.error) {
|
|
106
|
-
return res.status(404).json(result);
|
|
107
|
-
}
|
|
108
|
-
res.json(result);
|
|
109
|
-
}));
|
|
110
|
-
|
|
111
|
-
router.delete('/chrome-pilot/recording/:id', asyncHandler(async (req, res) => {
|
|
112
|
-
// Delete recording
|
|
113
|
-
const result = await chromeController.deleteRecording(req.params.id);
|
|
114
|
-
if (result.error) {
|
|
115
|
-
return res.status(404).json(result);
|
|
116
|
-
}
|
|
117
|
-
res.json(result);
|
|
118
|
-
}));
|
|
119
|
-
|
|
120
|
-
// New frame capture endpoints
|
|
121
|
-
router.post('/chrome-pilot/frame-batch', (req, res, next) => {
|
|
122
|
-
// Use multer middleware for this specific route
|
|
123
|
-
chromeController.upload(req, res, async (err) => {
|
|
124
|
-
if (err) {
|
|
125
|
-
console.error('Multer error:', err);
|
|
126
|
-
return res.status(400).json({ error: true, message: err.message });
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
try {
|
|
130
|
-
// Extract data from req.body (populated by multer)
|
|
131
|
-
const { sessionId, frames } = req.body;
|
|
132
|
-
|
|
133
|
-
console.log('Route received sessionId:', sessionId);
|
|
134
|
-
console.log('Route received frames (type):', typeof frames);
|
|
135
|
-
|
|
136
|
-
if (!sessionId || !frames) {
|
|
137
|
-
return res.status(400).json({ error: 'Missing sessionId or frames in request body' });
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
// Parse the stringified frames and call the controller method correctly
|
|
141
|
-
const parsedFrames = JSON.parse(frames);
|
|
142
|
-
console.log('Parsed frames count:', parsedFrames.length);
|
|
143
|
-
|
|
144
|
-
const result = await chromeController.storeFrameBatch(sessionId, parsedFrames);
|
|
145
|
-
res.json(result);
|
|
146
|
-
|
|
147
|
-
} catch (error) {
|
|
148
|
-
console.error('Error processing frame batch:', error);
|
|
149
|
-
res.status(500).json({ error: 'Failed to store frame batch', details: error.message });
|
|
150
|
-
}
|
|
151
|
-
});
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
router.get('/chrome-pilot/check-session/:sessionId', asyncHandler(async (req, res) => {
|
|
155
|
-
const { sessionId } = req.params;
|
|
156
|
-
const result = await chromeController.checkFrameSession(sessionId);
|
|
157
|
-
if (result.found) {
|
|
158
|
-
return res.status(200).json({ status: 'found', sessionId, ...result });
|
|
159
|
-
} else {
|
|
160
|
-
return res.status(404).json({ status: 'not_found', sessionId });
|
|
161
|
-
}
|
|
162
|
-
}));
|
|
163
|
-
|
|
164
|
-
router.post('/chrome-pilot/associate-logs', asyncHandler(async (req, res) => {
|
|
165
|
-
const { sessionId, logs } = req.body;
|
|
166
|
-
if (!sessionId || !logs) {
|
|
167
|
-
return res.status(400).json({ error: 'sessionId and logs are required' });
|
|
168
|
-
}
|
|
169
|
-
const result = await chromeController.associateLogsWithFrames(sessionId, logs);
|
|
170
|
-
res.json(result);
|
|
171
|
-
}));
|
|
172
|
-
|
|
173
|
-
router.post('/chrome-pilot/save-edited-session', asyncHandler(async (req, res) => {
|
|
174
|
-
const { sessionId, sessionData } = req.body;
|
|
175
|
-
if (!sessionId || !sessionData) {
|
|
176
|
-
return res.status(400).json({ error: 'sessionId and sessionData are required' });
|
|
177
|
-
}
|
|
178
|
-
const result = await chromeController.saveEditedSession(sessionId, sessionData);
|
|
179
|
-
res.json(result);
|
|
180
|
-
}));
|
|
181
|
-
|
|
182
|
-
router.get('/chrome-pilot/session/:sessionId', asyncHandler(async (req, res) => {
|
|
183
|
-
const { sessionId } = req.params;
|
|
184
|
-
const result = await chromeController.getFrameSession(sessionId);
|
|
185
|
-
if (result) {
|
|
186
|
-
res.json(result);
|
|
187
|
-
} else {
|
|
188
|
-
res.status(404).json({ error: 'Session not found' });
|
|
189
|
-
}
|
|
190
|
-
}));
|
|
191
|
-
|
|
192
|
-
// Import session from Chrome extension storage format
|
|
193
|
-
router.post('/chrome-pilot/import-session', asyncHandler(async (req, res) => {
|
|
194
|
-
const { sessionId, sessionData } = req.body;
|
|
195
|
-
if (!sessionId || !sessionData) {
|
|
196
|
-
return res.status(400).json({ error: 'sessionId and sessionData are required' });
|
|
197
|
-
}
|
|
198
|
-
const result = await chromeController.importSessionFromChrome(sessionId, sessionData);
|
|
199
|
-
res.json(result);
|
|
200
|
-
}));
|
|
201
|
-
|
|
202
|
-
// Workflow recording endpoints
|
|
203
|
-
router.post('/chrome-pilot/workflow-recording', asyncHandler(async (req, res) => {
|
|
204
|
-
const { sessionId, url, title, includeLogs, actions, logs } = req.body;
|
|
205
|
-
if (!sessionId || !actions) {
|
|
206
|
-
return res.status(400).json({ error: 'sessionId and actions are required' });
|
|
207
|
-
}
|
|
208
|
-
const result = await chromeController.storeWorkflowRecording(sessionId, url, title, includeLogs, actions, logs);
|
|
209
|
-
res.json(result);
|
|
210
|
-
}));
|
|
211
|
-
|
|
212
|
-
router.get('/chrome-pilot/workflow-recording/:sessionId', asyncHandler(async (req, res) => {
|
|
213
|
-
const { sessionId } = req.params;
|
|
214
|
-
const result = await chromeController.getWorkflowRecording(sessionId);
|
|
215
|
-
if (result.error) {
|
|
216
|
-
return res.status(404).json(result);
|
|
217
|
-
}
|
|
218
|
-
res.json(result);
|
|
219
|
-
}));
|
|
220
|
-
|
|
221
|
-
router.get('/chrome-pilot/workflow-recordings', asyncHandler(async (req, res) => {
|
|
222
|
-
const result = await chromeController.listWorkflowRecordings();
|
|
223
|
-
res.json(result);
|
|
224
|
-
}));
|
|
225
|
-
|
|
226
|
-
// Restore point endpoints
|
|
227
|
-
router.post('/chrome-pilot/restore-point', asyncHandler(async (req, res) => {
|
|
228
|
-
const result = await chromeController.saveRestorePoint(req.body);
|
|
229
|
-
res.json(result);
|
|
230
|
-
}));
|
|
231
|
-
|
|
232
|
-
router.get('/chrome-pilot/restore-point/:id', asyncHandler(async (req, res) => {
|
|
233
|
-
const result = await chromeController.getRestorePoint(req.params.id);
|
|
234
|
-
if (result.error) {
|
|
235
|
-
res.status(404).json(result);
|
|
236
|
-
} else {
|
|
237
|
-
res.json(result);
|
|
238
|
-
}
|
|
239
|
-
}));
|
|
240
|
-
|
|
241
|
-
router.get('/chrome-pilot/restore-points/:workflowId', asyncHandler(async (req, res) => {
|
|
242
|
-
const result = await chromeController.listRestorePoints(req.params.workflowId);
|
|
243
|
-
res.json(result);
|
|
244
|
-
}));
|
|
245
|
-
|
|
246
|
-
router.delete('/chrome-pilot/restore-point/:id', asyncHandler(async (req, res) => {
|
|
247
|
-
const result = await chromeController.deleteRestorePoint(req.params.id);
|
|
248
|
-
res.json(result);
|
|
249
|
-
}));
|
|
250
|
-
|
|
251
|
-
router.use((error, req, res, next) => {
|
|
252
|
-
console.error('Error:', error);
|
|
253
|
-
res.status(500).json({
|
|
254
|
-
error: true,
|
|
255
|
-
message: error.message || 'Internal server error'
|
|
256
|
-
});
|
|
257
|
-
});
|
|
258
|
-
|
|
259
|
-
return router;
|
|
260
|
-
}
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
// New shared storage implementation using SQLite database
|
|
2
|
-
import { database } from './database.js';
|
|
3
|
-
|
|
4
|
-
class SharedRecordingStorage {
|
|
5
|
-
constructor() {
|
|
6
|
-
this.initialized = false;
|
|
7
|
-
this.initPromise = this.init();
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
async init() {
|
|
11
|
-
database.init();
|
|
12
|
-
this.initialized = true;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
async ensureInitialized() {
|
|
16
|
-
if (!this.initialized) {
|
|
17
|
-
await this.initPromise;
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
// Legacy method - no longer needed with SQLite
|
|
22
|
-
async loadFromDisk() {
|
|
23
|
-
// SQLite handles persistence automatically
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
// Legacy method - no longer needed with SQLite
|
|
27
|
-
async saveToDisk() {
|
|
28
|
-
// SQLite handles persistence automatically
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
async get(id) {
|
|
32
|
-
await this.ensureInitialized();
|
|
33
|
-
return database.getRecording(id);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
async delete(id) {
|
|
37
|
-
await this.ensureInitialized();
|
|
38
|
-
return database.deleteRecording(id);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
async list() {
|
|
42
|
-
await this.ensureInitialized();
|
|
43
|
-
return database.listRecordings();
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// Store frame batch for frame capture sessions
|
|
47
|
-
async storeFrameBatch(sessionId, frames) {
|
|
48
|
-
await this.ensureInitialized();
|
|
49
|
-
return database.storeFrameBatch(sessionId, frames);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// Get frame session info
|
|
53
|
-
async getFrameSessionInfo(sessionId) {
|
|
54
|
-
await this.ensureInitialized();
|
|
55
|
-
return database.getFrameSessionInfo(sessionId);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// Get specific frame from session
|
|
59
|
-
async getFrame(sessionId, frameIndex) {
|
|
60
|
-
await this.ensureInitialized();
|
|
61
|
-
return database.getFrame(sessionId, frameIndex);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// Get entire frame session
|
|
65
|
-
async getFrameSession(sessionId) {
|
|
66
|
-
await this.ensureInitialized();
|
|
67
|
-
return database.getFrameSession(sessionId);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// Update frame session - for SQLite this is handled by associateLogsWithFrames
|
|
71
|
-
async updateFrameSession(sessionId, updatedSession) {
|
|
72
|
-
await this.ensureInitialized();
|
|
73
|
-
|
|
74
|
-
// With SQLite, we don't update the entire session at once
|
|
75
|
-
// Instead, we use the database's structured approach
|
|
76
|
-
// This method is kept for backward compatibility
|
|
77
|
-
|
|
78
|
-
if (updatedSession.frames) {
|
|
79
|
-
// Store the frames
|
|
80
|
-
const result = database.storeFrameBatch(sessionId, updatedSession.frames);
|
|
81
|
-
return result;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
throw new Error('Frame session update not supported in SQLite mode');
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// Associate logs with frames
|
|
88
|
-
async associateLogsWithFrames(sessionId, logs) {
|
|
89
|
-
await this.ensureInitialized();
|
|
90
|
-
return database.associateLogsWithFrames(sessionId, logs);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// Get database statistics
|
|
94
|
-
async getStats() {
|
|
95
|
-
await this.ensureInitialized();
|
|
96
|
-
return database.getStats();
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// Export singleton instance
|
|
101
|
-
export const sharedStorage = new SharedRecordingStorage();
|