@su-record/vibe 0.1.2 → 0.1.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/README.md +13 -6
- package/bin/vibe +20 -2
- package/package.json +5 -6
- package/scripts/install-mcp.js +31 -5
- package/mcp/dist/__tests__/complexity.test.js +0 -126
- package/mcp/dist/__tests__/memory.test.js +0 -120
- package/mcp/dist/__tests__/python-dart-complexity.test.js +0 -146
- package/mcp/dist/index.js +0 -230
- package/mcp/dist/lib/ContextCompressor.js +0 -305
- package/mcp/dist/lib/MemoryManager.js +0 -334
- package/mcp/dist/lib/ProjectCache.js +0 -126
- package/mcp/dist/lib/PythonParser.js +0 -241
- package/mcp/dist/tools/browser/browserPool.js +0 -76
- package/mcp/dist/tools/browser/browserUtils.js +0 -135
- package/mcp/dist/tools/browser/inspectNetworkRequests.js +0 -140
- package/mcp/dist/tools/browser/monitorConsoleLogs.js +0 -97
- package/mcp/dist/tools/convention/analyzeComplexity.js +0 -248
- package/mcp/dist/tools/convention/applyQualityRules.js +0 -102
- package/mcp/dist/tools/convention/checkCouplingCohesion.js +0 -233
- package/mcp/dist/tools/convention/complexityMetrics.js +0 -133
- package/mcp/dist/tools/convention/dartComplexity.js +0 -117
- package/mcp/dist/tools/convention/getCodingGuide.js +0 -64
- package/mcp/dist/tools/convention/languageDetector.js +0 -50
- package/mcp/dist/tools/convention/pythonComplexity.js +0 -109
- package/mcp/dist/tools/convention/suggestImprovements.js +0 -257
- package/mcp/dist/tools/convention/validateCodeQuality.js +0 -177
- package/mcp/dist/tools/memory/autoSaveContext.js +0 -79
- package/mcp/dist/tools/memory/database.js +0 -123
- package/mcp/dist/tools/memory/deleteMemory.js +0 -39
- package/mcp/dist/tools/memory/listMemories.js +0 -38
- package/mcp/dist/tools/memory/memoryConfig.js +0 -27
- package/mcp/dist/tools/memory/memorySQLite.js +0 -138
- package/mcp/dist/tools/memory/memoryUtils.js +0 -34
- package/mcp/dist/tools/memory/migrate.js +0 -113
- package/mcp/dist/tools/memory/prioritizeMemory.js +0 -109
- package/mcp/dist/tools/memory/recallMemory.js +0 -40
- package/mcp/dist/tools/memory/restoreSessionContext.js +0 -69
- package/mcp/dist/tools/memory/saveMemory.js +0 -34
- package/mcp/dist/tools/memory/searchMemories.js +0 -37
- package/mcp/dist/tools/memory/startSession.js +0 -100
- package/mcp/dist/tools/memory/updateMemory.js +0 -46
- package/mcp/dist/tools/planning/analyzeRequirements.js +0 -166
- package/mcp/dist/tools/planning/createUserStories.js +0 -119
- package/mcp/dist/tools/planning/featureRoadmap.js +0 -202
- package/mcp/dist/tools/planning/generatePrd.js +0 -156
- package/mcp/dist/tools/prompt/analyzePrompt.js +0 -145
- package/mcp/dist/tools/prompt/enhancePrompt.js +0 -105
- package/mcp/dist/tools/semantic/findReferences.js +0 -195
- package/mcp/dist/tools/semantic/findSymbol.js +0 -200
- package/mcp/dist/tools/thinking/analyzeProblem.js +0 -50
- package/mcp/dist/tools/thinking/breakDownProblem.js +0 -140
- package/mcp/dist/tools/thinking/createThinkingChain.js +0 -39
- package/mcp/dist/tools/thinking/formatAsPlan.js +0 -73
- package/mcp/dist/tools/thinking/stepByStepAnalysis.js +0 -58
- package/mcp/dist/tools/thinking/thinkAloudProcess.js +0 -75
- package/mcp/dist/tools/time/getCurrentTime.js +0 -61
- package/mcp/dist/tools/ui/previewUiAscii.js +0 -232
- package/mcp/dist/types/tool.js +0 -2
- package/mcp/package.json +0 -53
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
// Browser instance pool for efficient resource management
|
|
2
|
-
import puppeteer from 'puppeteer-core';
|
|
3
|
-
import { getBrowserLaunchOptions } from './browserUtils.js';
|
|
4
|
-
class BrowserPool {
|
|
5
|
-
browser = null;
|
|
6
|
-
lastUsed = 0;
|
|
7
|
-
IDLE_TIMEOUT = 5 * 60 * 1000; // 5 minutes
|
|
8
|
-
cleanupTimer = null;
|
|
9
|
-
/**
|
|
10
|
-
* Get or create browser instance
|
|
11
|
-
*/
|
|
12
|
-
async getBrowser() {
|
|
13
|
-
// If browser exists and is connected, return it
|
|
14
|
-
if (this.browser && this.browser.isConnected()) {
|
|
15
|
-
this.lastUsed = Date.now();
|
|
16
|
-
this.scheduleCleanup();
|
|
17
|
-
return this.browser;
|
|
18
|
-
}
|
|
19
|
-
// Create new browser instance
|
|
20
|
-
const options = getBrowserLaunchOptions();
|
|
21
|
-
this.browser = await puppeteer.launch(options);
|
|
22
|
-
this.lastUsed = Date.now();
|
|
23
|
-
this.scheduleCleanup();
|
|
24
|
-
return this.browser;
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* Schedule automatic cleanup of idle browser
|
|
28
|
-
*/
|
|
29
|
-
scheduleCleanup() {
|
|
30
|
-
// Clear existing timer
|
|
31
|
-
if (this.cleanupTimer) {
|
|
32
|
-
clearTimeout(this.cleanupTimer);
|
|
33
|
-
}
|
|
34
|
-
// Set new timer
|
|
35
|
-
this.cleanupTimer = setTimeout(async () => {
|
|
36
|
-
const idleTime = Date.now() - this.lastUsed;
|
|
37
|
-
if (idleTime >= this.IDLE_TIMEOUT) {
|
|
38
|
-
await this.closeBrowser();
|
|
39
|
-
}
|
|
40
|
-
}, this.IDLE_TIMEOUT);
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* Manually close browser instance
|
|
44
|
-
*/
|
|
45
|
-
async closeBrowser() {
|
|
46
|
-
if (this.cleanupTimer) {
|
|
47
|
-
clearTimeout(this.cleanupTimer);
|
|
48
|
-
this.cleanupTimer = null;
|
|
49
|
-
}
|
|
50
|
-
if (this.browser && this.browser.isConnected()) {
|
|
51
|
-
await this.browser.close();
|
|
52
|
-
this.browser = null;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
/**
|
|
56
|
-
* Get a new page from the browser pool
|
|
57
|
-
*/
|
|
58
|
-
async getPage() {
|
|
59
|
-
const browser = await this.getBrowser();
|
|
60
|
-
return await browser.newPage();
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
// Singleton instance
|
|
64
|
-
export const browserPool = new BrowserPool();
|
|
65
|
-
// Cleanup on process exit
|
|
66
|
-
process.on('exit', () => {
|
|
67
|
-
browserPool.closeBrowser();
|
|
68
|
-
});
|
|
69
|
-
process.on('SIGINT', async () => {
|
|
70
|
-
await browserPool.closeBrowser();
|
|
71
|
-
process.exit(0);
|
|
72
|
-
});
|
|
73
|
-
process.on('SIGTERM', async () => {
|
|
74
|
-
await browserPool.closeBrowser();
|
|
75
|
-
process.exit(0);
|
|
76
|
-
});
|
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
// Browser utility functions for finding Chrome/Chromium executables
|
|
2
|
-
import { existsSync } from 'fs';
|
|
3
|
-
import { execSync } from 'child_process';
|
|
4
|
-
import { platform } from 'os';
|
|
5
|
-
/**
|
|
6
|
-
* Finds Chrome or Chromium executable path on the system
|
|
7
|
-
*/
|
|
8
|
-
export function findChromePath() {
|
|
9
|
-
const platformName = platform();
|
|
10
|
-
// Platform-specific paths for Chrome
|
|
11
|
-
const chromePaths = {
|
|
12
|
-
win32: [
|
|
13
|
-
process.env.LOCALAPPDATA + '\\Google\\Chrome\\Application\\chrome.exe',
|
|
14
|
-
process.env.PROGRAMFILES + '\\Google\\Chrome\\Application\\chrome.exe',
|
|
15
|
-
process.env['PROGRAMFILES(X86)'] + '\\Google\\Chrome\\Application\\chrome.exe',
|
|
16
|
-
'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe',
|
|
17
|
-
'C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe',
|
|
18
|
-
],
|
|
19
|
-
darwin: [
|
|
20
|
-
'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
|
|
21
|
-
'/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary',
|
|
22
|
-
'/Applications/Chromium.app/Contents/MacOS/Chromium',
|
|
23
|
-
],
|
|
24
|
-
linux: [
|
|
25
|
-
'/usr/bin/google-chrome-stable',
|
|
26
|
-
'/usr/bin/google-chrome',
|
|
27
|
-
'/usr/bin/chromium-browser',
|
|
28
|
-
'/usr/bin/chromium',
|
|
29
|
-
'/snap/bin/chromium',
|
|
30
|
-
]
|
|
31
|
-
};
|
|
32
|
-
// Platform-specific paths for Edge (as fallback)
|
|
33
|
-
const edgePaths = {
|
|
34
|
-
win32: [
|
|
35
|
-
process.env['PROGRAMFILES(X86)'] + '\\Microsoft\\Edge\\Application\\msedge.exe',
|
|
36
|
-
process.env.PROGRAMFILES + '\\Microsoft\\Edge\\Application\\msedge.exe',
|
|
37
|
-
'C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe',
|
|
38
|
-
'C:\\Program Files\\Microsoft\\Edge\\Application\\msedge.exe',
|
|
39
|
-
],
|
|
40
|
-
darwin: [
|
|
41
|
-
'/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge',
|
|
42
|
-
],
|
|
43
|
-
linux: [
|
|
44
|
-
'/usr/bin/microsoft-edge',
|
|
45
|
-
'/usr/bin/microsoft-edge-stable',
|
|
46
|
-
]
|
|
47
|
-
};
|
|
48
|
-
// Platform-specific paths for Brave (as fallback)
|
|
49
|
-
const bravePaths = {
|
|
50
|
-
win32: [
|
|
51
|
-
process.env.LOCALAPPDATA + '\\BraveSoftware\\Brave-Browser\\Application\\brave.exe',
|
|
52
|
-
process.env.PROGRAMFILES + '\\BraveSoftware\\Brave-Browser\\Application\\brave.exe',
|
|
53
|
-
process.env['PROGRAMFILES(X86)'] + '\\BraveSoftware\\Brave-Browser\\Application\\brave.exe',
|
|
54
|
-
],
|
|
55
|
-
darwin: [
|
|
56
|
-
'/Applications/Brave Browser.app/Contents/MacOS/Brave Browser',
|
|
57
|
-
],
|
|
58
|
-
linux: [
|
|
59
|
-
'/usr/bin/brave-browser',
|
|
60
|
-
'/usr/bin/brave',
|
|
61
|
-
'/snap/bin/brave',
|
|
62
|
-
]
|
|
63
|
-
};
|
|
64
|
-
// Check user-specified path first
|
|
65
|
-
if (process.env.CHROME_PATH && existsSync(process.env.CHROME_PATH)) {
|
|
66
|
-
return process.env.CHROME_PATH;
|
|
67
|
-
}
|
|
68
|
-
// Get paths for current platform
|
|
69
|
-
const currentPlatform = platformName === 'win32' ? 'win32' :
|
|
70
|
-
platformName === 'darwin' ? 'darwin' : 'linux';
|
|
71
|
-
const allPaths = [
|
|
72
|
-
...(chromePaths[currentPlatform] || []),
|
|
73
|
-
...(edgePaths[currentPlatform] || []),
|
|
74
|
-
...(bravePaths[currentPlatform] || [])
|
|
75
|
-
];
|
|
76
|
-
// Find first existing path
|
|
77
|
-
for (const path of allPaths) {
|
|
78
|
-
if (path && existsSync(path)) {
|
|
79
|
-
return path;
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
// Try to find Chrome using 'which' command on Unix systems
|
|
83
|
-
if (platformName !== 'win32') {
|
|
84
|
-
try {
|
|
85
|
-
const chromePath = execSync('which google-chrome || which chromium || which chromium-browser', {
|
|
86
|
-
encoding: 'utf8'
|
|
87
|
-
}).trim();
|
|
88
|
-
if (chromePath && existsSync(chromePath)) {
|
|
89
|
-
return chromePath;
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
catch {
|
|
93
|
-
// Command failed, continue to next method
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
// Try to find Chrome using 'where' command on Windows
|
|
97
|
-
if (platformName === 'win32') {
|
|
98
|
-
try {
|
|
99
|
-
const chromePath = execSync('where chrome', { encoding: 'utf8' }).trim().split('\n')[0];
|
|
100
|
-
if (chromePath && existsSync(chromePath)) {
|
|
101
|
-
return chromePath;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
catch {
|
|
105
|
-
// Command failed, continue
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
return undefined;
|
|
109
|
-
}
|
|
110
|
-
/**
|
|
111
|
-
* Get launch options for puppeteer with proper browser configuration
|
|
112
|
-
*/
|
|
113
|
-
export function getBrowserLaunchOptions(additionalOptions = {}) {
|
|
114
|
-
const executablePath = findChromePath();
|
|
115
|
-
if (!executablePath) {
|
|
116
|
-
throw new Error('Chrome/Chromium browser not found. Please install Chrome or set CHROME_PATH environment variable.\n' +
|
|
117
|
-
'Download Chrome from: https://www.google.com/chrome/\n' +
|
|
118
|
-
'Or set environment variable: export CHROME_PATH="/path/to/chrome"');
|
|
119
|
-
}
|
|
120
|
-
return {
|
|
121
|
-
headless: true,
|
|
122
|
-
executablePath,
|
|
123
|
-
args: [
|
|
124
|
-
'--no-sandbox',
|
|
125
|
-
'--disable-setuid-sandbox',
|
|
126
|
-
'--disable-dev-shm-usage',
|
|
127
|
-
'--disable-accelerated-2d-canvas',
|
|
128
|
-
'--no-first-run',
|
|
129
|
-
'--no-zygote',
|
|
130
|
-
'--single-process', // For Windows compatibility
|
|
131
|
-
'--disable-gpu'
|
|
132
|
-
],
|
|
133
|
-
...additionalOptions
|
|
134
|
-
};
|
|
135
|
-
}
|
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
// Browser development tool - completely independent
|
|
2
|
-
import puppeteer from 'puppeteer-core';
|
|
3
|
-
import { getBrowserLaunchOptions } from './browserUtils.js';
|
|
4
|
-
export const inspectNetworkRequestsDefinition = {
|
|
5
|
-
name: 'inspect_network_requests',
|
|
6
|
-
description: '네트워크|API 호출|요청 확인|network|API calls|check requests|network traffic - Inspect network requests',
|
|
7
|
-
inputSchema: {
|
|
8
|
-
type: 'object',
|
|
9
|
-
properties: {
|
|
10
|
-
url: { type: 'string', description: 'URL to inspect' },
|
|
11
|
-
filterType: { type: 'string', description: 'Request type filter', enum: ['all', 'xhr', 'fetch', 'websocket', 'failed'] },
|
|
12
|
-
includeHeaders: { type: 'boolean', description: 'Include request/response headers' }
|
|
13
|
-
},
|
|
14
|
-
required: ['url']
|
|
15
|
-
},
|
|
16
|
-
annotations: {
|
|
17
|
-
title: 'Inspect Network Requests',
|
|
18
|
-
audience: ['user', 'assistant']
|
|
19
|
-
}
|
|
20
|
-
};
|
|
21
|
-
export async function inspectNetworkRequests(args) {
|
|
22
|
-
const { url: inspectUrl, filterType = 'all', includeHeaders = false } = args;
|
|
23
|
-
try {
|
|
24
|
-
// Get browser launch options with proper executable path
|
|
25
|
-
const launchOptions = getBrowserLaunchOptions();
|
|
26
|
-
const browser = await puppeteer.launch(launchOptions);
|
|
27
|
-
const page = await browser.newPage();
|
|
28
|
-
const networkRequests = [];
|
|
29
|
-
let requestId = 0;
|
|
30
|
-
const requestTimings = new Map();
|
|
31
|
-
// Capture network requests
|
|
32
|
-
page.on('request', request => {
|
|
33
|
-
const startTime = Date.now();
|
|
34
|
-
const id = `req_${String(requestId++).padStart(3, '0')}`;
|
|
35
|
-
const requestUrl = request.url();
|
|
36
|
-
requestTimings.set(requestUrl, startTime);
|
|
37
|
-
networkRequests.push({
|
|
38
|
-
id,
|
|
39
|
-
url: requestUrl,
|
|
40
|
-
method: request.method(),
|
|
41
|
-
type: request.resourceType(),
|
|
42
|
-
responseTime: 0,
|
|
43
|
-
size: 0,
|
|
44
|
-
timestamp: new Date().toISOString(),
|
|
45
|
-
headers: includeHeaders ? {
|
|
46
|
-
request: request.headers()
|
|
47
|
-
} : undefined
|
|
48
|
-
});
|
|
49
|
-
});
|
|
50
|
-
page.on('response', async (response) => {
|
|
51
|
-
const requestUrl = response.url();
|
|
52
|
-
const request = networkRequests.find(req => req.url === requestUrl);
|
|
53
|
-
const startTime = requestTimings.get(requestUrl);
|
|
54
|
-
if (request) {
|
|
55
|
-
request.status = response.status();
|
|
56
|
-
request.statusText = response.statusText();
|
|
57
|
-
request.responseTime = startTime ? Date.now() - startTime : 0;
|
|
58
|
-
request.failed = !response.ok();
|
|
59
|
-
if (includeHeaders && request.headers) {
|
|
60
|
-
request.headers.response = response.headers();
|
|
61
|
-
}
|
|
62
|
-
// Estimate response size
|
|
63
|
-
try {
|
|
64
|
-
const buffer = await response.buffer();
|
|
65
|
-
request.size = buffer.length;
|
|
66
|
-
}
|
|
67
|
-
catch {
|
|
68
|
-
request.size = 0;
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
});
|
|
72
|
-
page.on('requestfailed', request => {
|
|
73
|
-
const requestUrl = request.url();
|
|
74
|
-
const failedRequest = networkRequests.find(req => req.url === requestUrl);
|
|
75
|
-
if (failedRequest) {
|
|
76
|
-
failedRequest.failed = true;
|
|
77
|
-
failedRequest.status = 0;
|
|
78
|
-
failedRequest.statusText = request.failure()?.errorText || 'Failed';
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
// Navigate to URL and wait for network to be idle
|
|
82
|
-
await page.goto(inspectUrl, { waitUntil: 'networkidle0', timeout: 30000 });
|
|
83
|
-
// Wait a bit for any remaining requests
|
|
84
|
-
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
85
|
-
await browser.close();
|
|
86
|
-
const filteredRequests = networkRequests.filter(req => {
|
|
87
|
-
switch (filterType) {
|
|
88
|
-
case 'xhr':
|
|
89
|
-
return req.type === 'xhr';
|
|
90
|
-
case 'fetch':
|
|
91
|
-
return req.type === 'fetch';
|
|
92
|
-
case 'websocket':
|
|
93
|
-
return req.type === 'websocket';
|
|
94
|
-
case 'failed':
|
|
95
|
-
return req.failed || (req.status !== undefined && req.status >= 400);
|
|
96
|
-
default:
|
|
97
|
-
return true;
|
|
98
|
-
}
|
|
99
|
-
});
|
|
100
|
-
const networkInspectionResult = {
|
|
101
|
-
action: 'inspect_network_requests',
|
|
102
|
-
url: inspectUrl,
|
|
103
|
-
filterType,
|
|
104
|
-
includeHeaders,
|
|
105
|
-
requests: filteredRequests,
|
|
106
|
-
summary: {
|
|
107
|
-
totalRequests: filteredRequests.length,
|
|
108
|
-
successful: filteredRequests.filter(r => r.status !== undefined && r.status >= 200 && r.status < 300).length,
|
|
109
|
-
failed: filteredRequests.filter(r => r.failed || (r.status !== undefined && r.status >= 400)).length,
|
|
110
|
-
averageResponseTime: filteredRequests.reduce((sum, r) => sum + r.responseTime, 0) / filteredRequests.length,
|
|
111
|
-
totalDataTransferred: filteredRequests.reduce((sum, r) => sum + r.size, 0),
|
|
112
|
-
requestTypes: {
|
|
113
|
-
xhr: filteredRequests.filter(r => r.type === 'xhr').length,
|
|
114
|
-
fetch: filteredRequests.filter(r => r.type === 'fetch').length,
|
|
115
|
-
websocket: filteredRequests.filter(r => r.type === 'websocket').length
|
|
116
|
-
}
|
|
117
|
-
},
|
|
118
|
-
status: 'success'
|
|
119
|
-
};
|
|
120
|
-
// Compact summary format
|
|
121
|
-
const failed = filteredRequests.filter(r => r.failed || (r.status !== undefined && r.status >= 400));
|
|
122
|
-
const errorSummary = failed.length > 0
|
|
123
|
-
? `\nErrors: ${failed.slice(0, 3).map(r => `${r.method} ${new URL(r.url).pathname} (${r.status})`).join(', ')}${failed.length > 3 ? ` +${failed.length - 3}` : ''}`
|
|
124
|
-
: '';
|
|
125
|
-
return {
|
|
126
|
-
content: [{
|
|
127
|
-
type: 'text',
|
|
128
|
-
text: `${networkInspectionResult.summary.totalRequests} reqs | ${networkInspectionResult.summary.successful} OK, ${networkInspectionResult.summary.failed} fail | Avg: ${networkInspectionResult.summary.averageResponseTime.toFixed(0)}ms | ${(networkInspectionResult.summary.totalDataTransferred / 1024).toFixed(1)}KB${errorSummary}`
|
|
129
|
-
}]
|
|
130
|
-
};
|
|
131
|
-
}
|
|
132
|
-
catch (error) {
|
|
133
|
-
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
134
|
-
const helpMessage = errorMessage.includes('Chrome') ?
|
|
135
|
-
'\n\nTroubleshooting:\n1. Install Chrome: https://www.google.com/chrome/\n2. Or set CHROME_PATH environment variable\n3. Or install puppeteer instead of puppeteer-core' : '';
|
|
136
|
-
return {
|
|
137
|
-
content: [{ type: 'text', text: `Error inspecting network requests: ${errorMessage}${helpMessage}` }]
|
|
138
|
-
};
|
|
139
|
-
}
|
|
140
|
-
}
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
// Browser development tool - completely independent
|
|
2
|
-
import puppeteer from 'puppeteer-core';
|
|
3
|
-
import { getBrowserLaunchOptions } from './browserUtils.js';
|
|
4
|
-
export const monitorConsoleLogsDefinition = {
|
|
5
|
-
name: 'monitor_console_logs',
|
|
6
|
-
description: '콘솔 로그|에러 확인|로그 봐줘|console|check logs|debug output|console errors - Monitor browser console',
|
|
7
|
-
inputSchema: {
|
|
8
|
-
type: 'object',
|
|
9
|
-
properties: {
|
|
10
|
-
url: { type: 'string', description: 'URL to monitor' },
|
|
11
|
-
logLevel: { type: 'string', description: 'Log level to capture', enum: ['all', 'error', 'warn', 'info', 'debug'] },
|
|
12
|
-
duration: { type: 'number', description: 'Monitoring duration in seconds' }
|
|
13
|
-
},
|
|
14
|
-
required: ['url']
|
|
15
|
-
},
|
|
16
|
-
annotations: {
|
|
17
|
-
title: 'Monitor Console Logs',
|
|
18
|
-
audience: ['user', 'assistant']
|
|
19
|
-
}
|
|
20
|
-
};
|
|
21
|
-
export async function monitorConsoleLogs(args) {
|
|
22
|
-
const { url: monitorUrl, logLevel = 'all', duration = 30 } = args;
|
|
23
|
-
try {
|
|
24
|
-
// Get browser launch options with proper executable path
|
|
25
|
-
const launchOptions = getBrowserLaunchOptions();
|
|
26
|
-
const browser = await puppeteer.launch(launchOptions);
|
|
27
|
-
const page = await browser.newPage();
|
|
28
|
-
const logs = [];
|
|
29
|
-
// Capture console events
|
|
30
|
-
page.on('console', msg => {
|
|
31
|
-
const msgLevel = msg.type();
|
|
32
|
-
if (logLevel === 'all' || msgLevel === logLevel) {
|
|
33
|
-
logs.push({
|
|
34
|
-
timestamp: new Date().toISOString(),
|
|
35
|
-
level: msgLevel,
|
|
36
|
-
message: msg.text(),
|
|
37
|
-
source: msg.location()?.url || 'unknown'
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
});
|
|
41
|
-
// Capture page errors
|
|
42
|
-
page.on('pageerror', error => {
|
|
43
|
-
if (logLevel === 'all' || logLevel === 'error') {
|
|
44
|
-
logs.push({
|
|
45
|
-
timestamp: new Date().toISOString(),
|
|
46
|
-
level: 'error',
|
|
47
|
-
message: error.message,
|
|
48
|
-
source: error.stack?.split('\n')[0] || 'unknown'
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
});
|
|
52
|
-
// Navigate to URL and wait for specified duration
|
|
53
|
-
await page.goto(monitorUrl, { waitUntil: 'networkidle0', timeout: 30000 });
|
|
54
|
-
await new Promise(resolve => setTimeout(resolve, duration * 1000));
|
|
55
|
-
await browser.close();
|
|
56
|
-
const consoleMonitorResult = {
|
|
57
|
-
action: 'monitor_console_logs',
|
|
58
|
-
url: monitorUrl,
|
|
59
|
-
logLevel,
|
|
60
|
-
duration,
|
|
61
|
-
capturedLogs: logs,
|
|
62
|
-
summary: {
|
|
63
|
-
totalLogs: logs.length,
|
|
64
|
-
errors: logs.filter(l => l.level === 'error').length,
|
|
65
|
-
warnings: logs.filter(l => l.level === 'warn').length,
|
|
66
|
-
infos: logs.filter(l => l.level === 'info').length,
|
|
67
|
-
debugs: logs.filter(l => l.level === 'debug').length,
|
|
68
|
-
logs: logs.filter(l => l.level === 'log').length
|
|
69
|
-
},
|
|
70
|
-
monitoringStatus: 'completed',
|
|
71
|
-
status: 'success'
|
|
72
|
-
};
|
|
73
|
-
// Compact summary with errors only
|
|
74
|
-
const errors = logs.filter(l => l.level === 'error');
|
|
75
|
-
const warnings = logs.filter(l => l.level === 'warn');
|
|
76
|
-
const errorSummary = errors.length > 0
|
|
77
|
-
? `\nErrors: ${errors.slice(0, 3).map(l => l.message.substring(0, 50)).join(', ')}${errors.length > 3 ? ` +${errors.length - 3}` : ''}`
|
|
78
|
-
: '';
|
|
79
|
-
const warnSummary = warnings.length > 0 && errors.length === 0
|
|
80
|
-
? `\nWarnings: ${warnings.slice(0, 3).map(l => l.message.substring(0, 50)).join(', ')}${warnings.length > 3 ? ` +${warnings.length - 3}` : ''}`
|
|
81
|
-
: '';
|
|
82
|
-
return {
|
|
83
|
-
content: [{
|
|
84
|
-
type: 'text',
|
|
85
|
-
text: `${logs.length} logs | ${consoleMonitorResult.summary.errors}E ${consoleMonitorResult.summary.warnings}W ${consoleMonitorResult.summary.infos}I | ${duration}s${errorSummary}${warnSummary}`
|
|
86
|
-
}]
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
catch (error) {
|
|
90
|
-
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
91
|
-
const helpMessage = errorMessage.includes('Chrome') ?
|
|
92
|
-
'\n\nTroubleshooting:\n1. Install Chrome: https://www.google.com/chrome/\n2. Or set CHROME_PATH environment variable\n3. Or install puppeteer instead of puppeteer-core' : '';
|
|
93
|
-
return {
|
|
94
|
-
content: [{ type: 'text', text: `Error monitoring console logs: ${errorMessage}${helpMessage}` }]
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
|
-
}
|