@tontoko/fast-playwright-mcp 0.0.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/LICENSE +202 -0
- package/README.md +1047 -0
- package/cli.js +18 -0
- package/config.d.ts +124 -0
- package/index.d.ts +25 -0
- package/index.js +18 -0
- package/lib/actions.d.js +0 -0
- package/lib/batch/batch-executor.js +137 -0
- package/lib/browser-context-factory.js +252 -0
- package/lib/browser-server-backend.js +139 -0
- package/lib/config/constants.js +80 -0
- package/lib/config.js +405 -0
- package/lib/context.js +274 -0
- package/lib/diagnostics/common/diagnostic-base.js +63 -0
- package/lib/diagnostics/common/error-enrichment-utils.js +212 -0
- package/lib/diagnostics/common/index.js +56 -0
- package/lib/diagnostics/common/initialization-manager.js +210 -0
- package/lib/diagnostics/common/performance-tracker.js +132 -0
- package/lib/diagnostics/diagnostic-error.js +140 -0
- package/lib/diagnostics/diagnostic-level.js +123 -0
- package/lib/diagnostics/diagnostic-thresholds.js +347 -0
- package/lib/diagnostics/element-discovery.js +441 -0
- package/lib/diagnostics/enhanced-error-handler.js +376 -0
- package/lib/diagnostics/error-enrichment.js +157 -0
- package/lib/diagnostics/frame-reference-manager.js +179 -0
- package/lib/diagnostics/page-analyzer.js +639 -0
- package/lib/diagnostics/parallel-page-analyzer.js +129 -0
- package/lib/diagnostics/resource-manager.js +134 -0
- package/lib/diagnostics/smart-config.js +482 -0
- package/lib/diagnostics/smart-handle.js +118 -0
- package/lib/diagnostics/unified-system.js +717 -0
- package/lib/extension/cdp-relay.js +486 -0
- package/lib/extension/extension-context-factory.js +74 -0
- package/lib/extension/main.js +41 -0
- package/lib/file-utils.js +42 -0
- package/lib/generate-keys.js +75 -0
- package/lib/http-server.js +50 -0
- package/lib/in-process-client.js +64 -0
- package/lib/index.js +48 -0
- package/lib/javascript.js +90 -0
- package/lib/log.js +33 -0
- package/lib/loop/loop-claude.js +247 -0
- package/lib/loop/loop-open-ai.js +222 -0
- package/lib/loop/loop.js +174 -0
- package/lib/loop/main.js +46 -0
- package/lib/loopTools/context.js +76 -0
- package/lib/loopTools/main.js +65 -0
- package/lib/loopTools/perform.js +40 -0
- package/lib/loopTools/snapshot.js +37 -0
- package/lib/loopTools/tool.js +26 -0
- package/lib/manual-promise.js +125 -0
- package/lib/mcp/in-process-transport.js +91 -0
- package/lib/mcp/proxy-backend.js +127 -0
- package/lib/mcp/server.js +123 -0
- package/lib/mcp/transport.js +159 -0
- package/lib/package.js +28 -0
- package/lib/program.js +82 -0
- package/lib/response.js +493 -0
- package/lib/schemas/expectation.js +152 -0
- package/lib/session-log.js +210 -0
- package/lib/tab.js +417 -0
- package/lib/tools/base-tool-handler.js +141 -0
- package/lib/tools/batch-execute.js +150 -0
- package/lib/tools/common.js +65 -0
- package/lib/tools/console.js +60 -0
- package/lib/tools/diagnose/diagnose-analysis-runner.js +101 -0
- package/lib/tools/diagnose/diagnose-config-handler.js +130 -0
- package/lib/tools/diagnose/diagnose-report-builder.js +394 -0
- package/lib/tools/diagnose.js +147 -0
- package/lib/tools/dialogs.js +57 -0
- package/lib/tools/evaluate.js +67 -0
- package/lib/tools/files.js +53 -0
- package/lib/tools/find-elements.js +307 -0
- package/lib/tools/install.js +60 -0
- package/lib/tools/keyboard.js +93 -0
- package/lib/tools/mouse.js +110 -0
- package/lib/tools/navigate.js +82 -0
- package/lib/tools/network.js +50 -0
- package/lib/tools/pdf.js +46 -0
- package/lib/tools/screenshot.js +113 -0
- package/lib/tools/snapshot.js +158 -0
- package/lib/tools/tabs.js +97 -0
- package/lib/tools/tool.js +47 -0
- package/lib/tools/utils.js +131 -0
- package/lib/tools/wait.js +64 -0
- package/lib/tools.js +65 -0
- package/lib/types/batch.js +47 -0
- package/lib/types/diff.js +0 -0
- package/lib/types/performance.js +0 -0
- package/lib/types/threshold-base.js +0 -0
- package/lib/utils/array-utils.js +44 -0
- package/lib/utils/code-deduplication-utils.js +141 -0
- package/lib/utils/common-formatters.js +252 -0
- package/lib/utils/console-filter.js +64 -0
- package/lib/utils/diagnostic-report-utils.js +178 -0
- package/lib/utils/diff-formatter.js +126 -0
- package/lib/utils/disposable-manager.js +135 -0
- package/lib/utils/error-handler-middleware.js +77 -0
- package/lib/utils/image-processor.js +137 -0
- package/lib/utils/index.js +92 -0
- package/lib/utils/report-builder.js +189 -0
- package/lib/utils/request-logger.js +82 -0
- package/lib/utils/response-diff-detector.js +150 -0
- package/lib/utils/section-builder.js +62 -0
- package/lib/utils/tool-patterns.js +153 -0
- package/lib/utils.js +46 -0
- package/package.json +77 -0
|
@@ -0,0 +1,482 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __toESM = (mod, isNodeMode, target) => {
|
|
8
|
+
target = mod != null ? __create(__getProtoOf(mod)) : {};
|
|
9
|
+
const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
|
|
10
|
+
for (let key of __getOwnPropNames(mod))
|
|
11
|
+
if (!__hasOwnProp.call(to, key))
|
|
12
|
+
__defProp(to, key, {
|
|
13
|
+
get: () => mod[key],
|
|
14
|
+
enumerable: true
|
|
15
|
+
});
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
19
|
+
|
|
20
|
+
// src/diagnostics/smart-config.ts
|
|
21
|
+
import debug from "debug";
|
|
22
|
+
import { DiagnosticLevel } from "./diagnostic-level.js";
|
|
23
|
+
import { DiagnosticThresholds } from "./diagnostic-thresholds.js";
|
|
24
|
+
var configDebug = debug("pw:mcp:config");
|
|
25
|
+
|
|
26
|
+
class SmartConfigManager {
|
|
27
|
+
static instance;
|
|
28
|
+
config;
|
|
29
|
+
listeners = [];
|
|
30
|
+
thresholdsManager;
|
|
31
|
+
constructor(initialConfig) {
|
|
32
|
+
this.config = this.createDefaultConfig();
|
|
33
|
+
this.thresholdsManager = DiagnosticThresholds.getInstance();
|
|
34
|
+
if (initialConfig) {
|
|
35
|
+
this.updateConfig(initialConfig);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
static getInstance(initialConfig) {
|
|
39
|
+
SmartConfigManager.instance ??= new SmartConfigManager(initialConfig);
|
|
40
|
+
if (!SmartConfigManager.instance) {
|
|
41
|
+
configDebug("Critical: SmartConfigManager instance is null after creation");
|
|
42
|
+
SmartConfigManager.instance = new SmartConfigManager(initialConfig);
|
|
43
|
+
}
|
|
44
|
+
return SmartConfigManager.instance;
|
|
45
|
+
}
|
|
46
|
+
static resetInstance() {
|
|
47
|
+
const wasNull = SmartConfigManager.instance === null;
|
|
48
|
+
SmartConfigManager.instance = null;
|
|
49
|
+
configDebug("SmartConfigManager instance reset", {
|
|
50
|
+
wasAlreadyNull: wasNull
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
createDefaultConfig() {
|
|
54
|
+
const defaultThresholds = DiagnosticThresholds.getInstance().getMetricsThresholds();
|
|
55
|
+
return {
|
|
56
|
+
autoDisposeTimeout: 30000,
|
|
57
|
+
maxConcurrentHandles: 100,
|
|
58
|
+
enableLeakDetection: true,
|
|
59
|
+
batchSizeLimit: 50,
|
|
60
|
+
parallelAnalysisEnabled: true,
|
|
61
|
+
diagnostic: {
|
|
62
|
+
level: DiagnosticLevel.STANDARD,
|
|
63
|
+
enableAlternativeSuggestions: true,
|
|
64
|
+
enablePageAnalysis: true,
|
|
65
|
+
enablePerformanceMetrics: true,
|
|
66
|
+
maxAlternatives: 5,
|
|
67
|
+
enableDetailedErrors: true
|
|
68
|
+
},
|
|
69
|
+
performance: {
|
|
70
|
+
enableMetricsCollection: true,
|
|
71
|
+
enableResourceMonitoring: true,
|
|
72
|
+
enablePerformanceWarnings: true,
|
|
73
|
+
autoOptimization: true,
|
|
74
|
+
thresholds: defaultThresholds
|
|
75
|
+
},
|
|
76
|
+
errorHandling: {
|
|
77
|
+
enableErrorEnrichment: true,
|
|
78
|
+
enableContextualSuggestions: true,
|
|
79
|
+
logLevel: "warn",
|
|
80
|
+
maxErrorHistory: 100,
|
|
81
|
+
enablePerformanceErrorDetection: true
|
|
82
|
+
},
|
|
83
|
+
features: {
|
|
84
|
+
enableParallelAnalysis: true,
|
|
85
|
+
enableSmartHandleManagement: true,
|
|
86
|
+
enableAdvancedElementDiscovery: true,
|
|
87
|
+
enableResourceLeakDetection: true,
|
|
88
|
+
enableRealTimeMonitoring: false
|
|
89
|
+
},
|
|
90
|
+
runtime: {
|
|
91
|
+
enableAdaptiveThresholds: true,
|
|
92
|
+
enableAutoTuning: false,
|
|
93
|
+
statsCollectionEnabled: true
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
getConfig() {
|
|
98
|
+
return { ...this.config };
|
|
99
|
+
}
|
|
100
|
+
updateConfig(updates) {
|
|
101
|
+
this.config = this.mergeDeep(this.config, updates);
|
|
102
|
+
if (updates.performance?.thresholds) {
|
|
103
|
+
this.syncThresholdsWithManager(updates.performance.thresholds);
|
|
104
|
+
}
|
|
105
|
+
this.notifyListeners();
|
|
106
|
+
}
|
|
107
|
+
mergeDeep(target, source) {
|
|
108
|
+
const result = { ...target };
|
|
109
|
+
for (const key in source) {
|
|
110
|
+
if (Object.hasOwn(source, key)) {
|
|
111
|
+
const sourceValue = source[key];
|
|
112
|
+
const targetValue = target[key];
|
|
113
|
+
if (typeof sourceValue === "object" && sourceValue !== null && !Array.isArray(sourceValue) && typeof targetValue === "object" && targetValue !== null && !Array.isArray(targetValue)) {
|
|
114
|
+
result[key] = {
|
|
115
|
+
...targetValue,
|
|
116
|
+
...sourceValue
|
|
117
|
+
};
|
|
118
|
+
} else {
|
|
119
|
+
result[key] = sourceValue;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return result;
|
|
124
|
+
}
|
|
125
|
+
onConfigChange(listener) {
|
|
126
|
+
this.listeners.push(listener);
|
|
127
|
+
return () => {
|
|
128
|
+
const index = this.listeners.indexOf(listener);
|
|
129
|
+
if (index > -1) {
|
|
130
|
+
this.listeners.splice(index, 1);
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
notifyListeners() {
|
|
135
|
+
for (const listener of this.listeners) {
|
|
136
|
+
try {
|
|
137
|
+
listener(this.config);
|
|
138
|
+
} catch (error) {
|
|
139
|
+
configDebug("Config change listener failed:", error);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
adjustThresholds(component, avgExecutionTime, successRate) {
|
|
144
|
+
if (!this.isAdaptiveThresholdsEnabled()) {
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
const currentThreshold = this.config.performance.thresholds.executionTime[component];
|
|
148
|
+
if (avgExecutionTime > currentThreshold * 0.8 && successRate > 0.9) {
|
|
149
|
+
const newThreshold = Math.min(currentThreshold * 1.2, currentThreshold + 1000);
|
|
150
|
+
this.updateConfig({
|
|
151
|
+
performance: {
|
|
152
|
+
...this.config.performance,
|
|
153
|
+
thresholds: {
|
|
154
|
+
...this.config.performance.thresholds,
|
|
155
|
+
executionTime: {
|
|
156
|
+
...this.config.performance.thresholds.executionTime,
|
|
157
|
+
[component]: newThreshold
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
if (avgExecutionTime < currentThreshold * 0.5 && successRate > 0.95) {
|
|
164
|
+
const newThreshold = Math.max(currentThreshold * 0.9, 100);
|
|
165
|
+
this.updateConfig({
|
|
166
|
+
performance: {
|
|
167
|
+
...this.config.performance,
|
|
168
|
+
thresholds: {
|
|
169
|
+
...this.config.performance.thresholds,
|
|
170
|
+
executionTime: {
|
|
171
|
+
...this.config.performance.thresholds.executionTime,
|
|
172
|
+
[component]: newThreshold
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
getComponentConfig(component) {
|
|
180
|
+
const base = {
|
|
181
|
+
diagnostic: this.config.diagnostic,
|
|
182
|
+
performance: this.config.performance,
|
|
183
|
+
errorHandling: this.config.errorHandling
|
|
184
|
+
};
|
|
185
|
+
switch (component) {
|
|
186
|
+
case "pageAnalyzer":
|
|
187
|
+
return {
|
|
188
|
+
...base,
|
|
189
|
+
executionTimeout: this.config.performance.thresholds.executionTime.pageAnalysis,
|
|
190
|
+
enableParallel: this.config.features.enableParallelAnalysis,
|
|
191
|
+
enableResourceMonitoring: this.config.features.enableResourceLeakDetection
|
|
192
|
+
};
|
|
193
|
+
case "elementDiscovery":
|
|
194
|
+
return {
|
|
195
|
+
...base,
|
|
196
|
+
executionTimeout: this.config.performance.thresholds.executionTime.elementDiscovery,
|
|
197
|
+
maxAlternatives: this.config.diagnostic.maxAlternatives,
|
|
198
|
+
enableAdvanced: this.config.features.enableAdvancedElementDiscovery
|
|
199
|
+
};
|
|
200
|
+
case "resourceManager":
|
|
201
|
+
return {
|
|
202
|
+
...base,
|
|
203
|
+
executionTimeout: this.config.performance.thresholds.executionTime.resourceMonitoring,
|
|
204
|
+
autoDisposeTimeout: this.config.autoDisposeTimeout,
|
|
205
|
+
maxHandles: this.config.maxConcurrentHandles,
|
|
206
|
+
enableLeakDetection: this.config.features.enableResourceLeakDetection
|
|
207
|
+
};
|
|
208
|
+
default:
|
|
209
|
+
return base;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
exportConfig() {
|
|
213
|
+
return JSON.stringify(this.config, null, 2);
|
|
214
|
+
}
|
|
215
|
+
reset() {
|
|
216
|
+
this.config = this.createDefaultConfig();
|
|
217
|
+
this.thresholdsManager.resetToDefaults();
|
|
218
|
+
this.notifyListeners();
|
|
219
|
+
}
|
|
220
|
+
syncThresholdsWithManager(thresholds) {
|
|
221
|
+
try {
|
|
222
|
+
const thresholdsConfig = {
|
|
223
|
+
executionTime: thresholds.executionTime,
|
|
224
|
+
memory: thresholds.memory,
|
|
225
|
+
performance: thresholds.performance,
|
|
226
|
+
dom: thresholds.dom,
|
|
227
|
+
interaction: thresholds.interaction,
|
|
228
|
+
layout: thresholds.layout
|
|
229
|
+
};
|
|
230
|
+
this.thresholdsManager.updateThresholds(thresholdsConfig);
|
|
231
|
+
} catch (error) {
|
|
232
|
+
configDebug("Failed to sync thresholds:", error);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
getThresholdsFromManager() {
|
|
236
|
+
return this.thresholdsManager.getMetricsThresholds();
|
|
237
|
+
}
|
|
238
|
+
getThresholdsStatus() {
|
|
239
|
+
const managerThresholds = this.thresholdsManager.getMetricsThresholds();
|
|
240
|
+
const configThresholds = this.config.performance.thresholds;
|
|
241
|
+
const isInSync = JSON.stringify(managerThresholds) === JSON.stringify(configThresholds);
|
|
242
|
+
return {
|
|
243
|
+
isInSync,
|
|
244
|
+
diagnostics: this.thresholdsManager.getConfigDiagnostics(),
|
|
245
|
+
smartConfigStatus: isInSync ? "Synchronized with DiagnosticThresholds" : "Out of sync - manual update required"
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
isAdaptiveThresholdsEnabled() {
|
|
249
|
+
return this.config.runtime.enableAdaptiveThresholds;
|
|
250
|
+
}
|
|
251
|
+
isAutoTuningEnabled() {
|
|
252
|
+
return this.config.runtime.enableAutoTuning;
|
|
253
|
+
}
|
|
254
|
+
isStatsCollectionEnabled() {
|
|
255
|
+
return this.config.runtime.statsCollectionEnabled;
|
|
256
|
+
}
|
|
257
|
+
configureForEnvironment(env) {
|
|
258
|
+
const envConfigs = {
|
|
259
|
+
development: {
|
|
260
|
+
diagnostic: { level: DiagnosticLevel.FULL },
|
|
261
|
+
performance: {
|
|
262
|
+
enableMetricsCollection: true,
|
|
263
|
+
enableResourceMonitoring: true,
|
|
264
|
+
enablePerformanceWarnings: true,
|
|
265
|
+
autoOptimization: true,
|
|
266
|
+
thresholds: this.thresholdsManager.getMetricsThresholds()
|
|
267
|
+
},
|
|
268
|
+
errorHandling: {
|
|
269
|
+
enableErrorEnrichment: true,
|
|
270
|
+
enableContextualSuggestions: true,
|
|
271
|
+
logLevel: "debug",
|
|
272
|
+
maxErrorHistory: 100,
|
|
273
|
+
enablePerformanceErrorDetection: true
|
|
274
|
+
},
|
|
275
|
+
features: {
|
|
276
|
+
enableParallelAnalysis: true,
|
|
277
|
+
enableSmartHandleManagement: true,
|
|
278
|
+
enableAdvancedElementDiscovery: true,
|
|
279
|
+
enableResourceLeakDetection: true,
|
|
280
|
+
enableRealTimeMonitoring: true
|
|
281
|
+
}
|
|
282
|
+
},
|
|
283
|
+
production: {
|
|
284
|
+
diagnostic: { level: DiagnosticLevel.STANDARD },
|
|
285
|
+
performance: {
|
|
286
|
+
enableMetricsCollection: true,
|
|
287
|
+
enableResourceMonitoring: true,
|
|
288
|
+
enablePerformanceWarnings: false,
|
|
289
|
+
autoOptimization: true,
|
|
290
|
+
thresholds: this.thresholdsManager.getMetricsThresholds()
|
|
291
|
+
},
|
|
292
|
+
errorHandling: {
|
|
293
|
+
enableErrorEnrichment: true,
|
|
294
|
+
enableContextualSuggestions: true,
|
|
295
|
+
logLevel: "warn",
|
|
296
|
+
maxErrorHistory: 50,
|
|
297
|
+
enablePerformanceErrorDetection: true
|
|
298
|
+
},
|
|
299
|
+
features: {
|
|
300
|
+
enableParallelAnalysis: true,
|
|
301
|
+
enableSmartHandleManagement: true,
|
|
302
|
+
enableAdvancedElementDiscovery: true,
|
|
303
|
+
enableResourceLeakDetection: true,
|
|
304
|
+
enableRealTimeMonitoring: false
|
|
305
|
+
}
|
|
306
|
+
},
|
|
307
|
+
testing: {
|
|
308
|
+
diagnostic: { level: DiagnosticLevel.BASIC },
|
|
309
|
+
performance: {
|
|
310
|
+
enableMetricsCollection: false,
|
|
311
|
+
enableResourceMonitoring: false,
|
|
312
|
+
enablePerformanceWarnings: false,
|
|
313
|
+
autoOptimization: false,
|
|
314
|
+
thresholds: this.thresholdsManager.getMetricsThresholds()
|
|
315
|
+
},
|
|
316
|
+
errorHandling: {
|
|
317
|
+
enableErrorEnrichment: false,
|
|
318
|
+
enableContextualSuggestions: false,
|
|
319
|
+
logLevel: "error",
|
|
320
|
+
maxErrorHistory: 20,
|
|
321
|
+
enablePerformanceErrorDetection: false
|
|
322
|
+
},
|
|
323
|
+
features: {
|
|
324
|
+
enableParallelAnalysis: false,
|
|
325
|
+
enableSmartHandleManagement: false,
|
|
326
|
+
enableAdvancedElementDiscovery: false,
|
|
327
|
+
enableResourceLeakDetection: false,
|
|
328
|
+
enableRealTimeMonitoring: false
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
};
|
|
332
|
+
this.updateConfig(envConfigs[env]);
|
|
333
|
+
}
|
|
334
|
+
updateThresholds(thresholdsConfig) {
|
|
335
|
+
this.thresholdsManager.updateThresholds(thresholdsConfig);
|
|
336
|
+
const updatedThresholds = this.thresholdsManager.getMetricsThresholds();
|
|
337
|
+
this.updateConfig({
|
|
338
|
+
performance: {
|
|
339
|
+
...this.config.performance,
|
|
340
|
+
thresholds: updatedThresholds
|
|
341
|
+
}
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
getConfigurationImpactReport() {
|
|
345
|
+
const defaultConfig = this.createDefaultConfig();
|
|
346
|
+
const currentConfig = this.getConfig();
|
|
347
|
+
const activeOverrides = [];
|
|
348
|
+
const executionTimeChanges = this.analyzeThresholdChanges(defaultConfig, currentConfig, activeOverrides);
|
|
349
|
+
const featureChanges = this.analyzeFeatureChanges(defaultConfig, currentConfig, activeOverrides);
|
|
350
|
+
this.analyzeConfigurationChanges(defaultConfig, currentConfig, featureChanges.modified, activeOverrides);
|
|
351
|
+
const performanceImpact = this.evaluatePerformanceImpact(currentConfig, defaultConfig, executionTimeChanges);
|
|
352
|
+
const validationStatus = this.generateValidationWarnings(executionTimeChanges, featureChanges.enabled);
|
|
353
|
+
return {
|
|
354
|
+
activeOverrides,
|
|
355
|
+
performanceImpact,
|
|
356
|
+
featureChanges,
|
|
357
|
+
validationStatus
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
analyzeThresholdChanges(defaultConfig, currentConfig, activeOverrides) {
|
|
361
|
+
const executionTimeChanges = {};
|
|
362
|
+
const defaultThresholds = defaultConfig.performance.thresholds.executionTime;
|
|
363
|
+
const currentThresholds = currentConfig.performance.thresholds.executionTime;
|
|
364
|
+
for (const key of Object.keys(defaultThresholds)) {
|
|
365
|
+
const componentKey = key;
|
|
366
|
+
const defaultValue = defaultThresholds[componentKey];
|
|
367
|
+
const currentValue = currentThresholds[componentKey];
|
|
368
|
+
if (defaultValue !== currentValue) {
|
|
369
|
+
const percentChange = (currentValue - defaultValue) / defaultValue * 100;
|
|
370
|
+
executionTimeChanges[key] = {
|
|
371
|
+
from: defaultValue,
|
|
372
|
+
to: currentValue,
|
|
373
|
+
percentChange: Math.round(percentChange)
|
|
374
|
+
};
|
|
375
|
+
activeOverrides.push(`${key} threshold: ${defaultValue}ms → ${currentValue}ms (${percentChange > 0 ? "+" : ""}${percentChange.toFixed(1)}%)`);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
return executionTimeChanges;
|
|
379
|
+
}
|
|
380
|
+
analyzeFeatureChanges(defaultConfig, currentConfig, activeOverrides) {
|
|
381
|
+
const enabled = [];
|
|
382
|
+
const disabled = [];
|
|
383
|
+
const modified = [];
|
|
384
|
+
const featureChecks = [
|
|
385
|
+
{ key: "enableParallelAnalysis", name: "Parallel Analysis" },
|
|
386
|
+
{ key: "enableSmartHandleManagement", name: "Smart Handle Management" },
|
|
387
|
+
{
|
|
388
|
+
key: "enableAdvancedElementDiscovery",
|
|
389
|
+
name: "Advanced Element Discovery"
|
|
390
|
+
},
|
|
391
|
+
{ key: "enableResourceLeakDetection", name: "Resource Leak Detection" },
|
|
392
|
+
{ key: "enableRealTimeMonitoring", name: "Real-Time Monitoring" }
|
|
393
|
+
];
|
|
394
|
+
for (const { key, name } of featureChecks) {
|
|
395
|
+
const featureKey = key;
|
|
396
|
+
const defaultValue = defaultConfig.features[featureKey];
|
|
397
|
+
const currentValue = currentConfig.features[featureKey];
|
|
398
|
+
if (defaultValue !== currentValue) {
|
|
399
|
+
if (currentValue && !defaultValue) {
|
|
400
|
+
enabled.push(name);
|
|
401
|
+
activeOverrides.push(`${name}: Enabled (was disabled by default)`);
|
|
402
|
+
} else if (!currentValue && defaultValue) {
|
|
403
|
+
disabled.push(name);
|
|
404
|
+
activeOverrides.push(`${name}: Disabled (was enabled by default)`);
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
return { enabled, disabled, modified };
|
|
409
|
+
}
|
|
410
|
+
analyzeConfigurationChanges(defaultConfig, currentConfig, modified, activeOverrides) {
|
|
411
|
+
if (defaultConfig.errorHandling.enableErrorEnrichment !== currentConfig.errorHandling.enableErrorEnrichment) {
|
|
412
|
+
const status = currentConfig.errorHandling.enableErrorEnrichment ? "Enabled" : "Disabled";
|
|
413
|
+
modified.push(`Error Enrichment: ${status}`);
|
|
414
|
+
activeOverrides.push(`Error Enrichment: ${status}`);
|
|
415
|
+
}
|
|
416
|
+
if (defaultConfig.diagnostic.level !== currentConfig.diagnostic.level) {
|
|
417
|
+
modified.push(`Diagnostic Level: ${defaultConfig.diagnostic.level} → ${currentConfig.diagnostic.level}`);
|
|
418
|
+
activeOverrides.push(`Diagnostic Level: ${defaultConfig.diagnostic.level} → ${currentConfig.diagnostic.level}`);
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
evaluatePerformanceImpact(currentConfig, defaultConfig, executionTimeChanges) {
|
|
422
|
+
let memoryImpact = "Minimal";
|
|
423
|
+
const recommendedOptimizations = [];
|
|
424
|
+
if (currentConfig.features.enableResourceLeakDetection && !defaultConfig.features.enableResourceLeakDetection) {
|
|
425
|
+
memoryImpact = "Low - Resource monitoring adds overhead";
|
|
426
|
+
recommendedOptimizations.push("Consider disabling in production if not needed");
|
|
427
|
+
}
|
|
428
|
+
if (currentConfig.features.enableRealTimeMonitoring) {
|
|
429
|
+
memoryImpact = "Medium - Real-time monitoring requires continuous data collection";
|
|
430
|
+
recommendedOptimizations.push("Only enable for debugging sessions");
|
|
431
|
+
}
|
|
432
|
+
return {
|
|
433
|
+
executionTimeChanges,
|
|
434
|
+
memoryImpact,
|
|
435
|
+
recommendedOptimizations
|
|
436
|
+
};
|
|
437
|
+
}
|
|
438
|
+
generateValidationWarnings(executionTimeChanges, enabledFeatures) {
|
|
439
|
+
const warnings = [];
|
|
440
|
+
const errors = [];
|
|
441
|
+
for (const [component, change] of Object.entries(executionTimeChanges)) {
|
|
442
|
+
if (change.percentChange > 50) {
|
|
443
|
+
warnings.push(`${component} timeout increased significantly (+${change.percentChange}%) - may mask performance issues`);
|
|
444
|
+
} else if (change.percentChange < -30) {
|
|
445
|
+
warnings.push(`${component} timeout decreased significantly (${change.percentChange}%) - may cause false failures`);
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
if (enabledFeatures.length > 3) {
|
|
449
|
+
warnings.push(`Many features enabled (${enabledFeatures.length}) - consider selective enablement for better performance`);
|
|
450
|
+
}
|
|
451
|
+
const isValid = errors.length === 0;
|
|
452
|
+
return { isValid, warnings, errors };
|
|
453
|
+
}
|
|
454
|
+
getConfigurationSummary() {
|
|
455
|
+
const impactReport = this.getConfigurationImpactReport();
|
|
456
|
+
const totalOverrides = impactReport.activeOverrides.length;
|
|
457
|
+
const significantChanges = impactReport.featureChanges.enabled.length + impactReport.featureChanges.disabled.length + Object.keys(impactReport.performanceImpact.executionTimeChanges).length;
|
|
458
|
+
let performanceRisk = "low";
|
|
459
|
+
if (impactReport.validationStatus.errors.length > 0) {
|
|
460
|
+
performanceRisk = "high";
|
|
461
|
+
} else if (impactReport.validationStatus.warnings.length > 2 || significantChanges > 5) {
|
|
462
|
+
performanceRisk = "medium";
|
|
463
|
+
}
|
|
464
|
+
let recommendation = "Configuration is optimal";
|
|
465
|
+
if (performanceRisk === "high") {
|
|
466
|
+
recommendation = "Review and fix configuration errors before proceeding";
|
|
467
|
+
} else if (performanceRisk === "medium") {
|
|
468
|
+
recommendation = "Consider reviewing warnings and optimizing configuration";
|
|
469
|
+
} else if (totalOverrides === 0) {
|
|
470
|
+
recommendation = "Using default configuration - consider customization for your use case";
|
|
471
|
+
}
|
|
472
|
+
return {
|
|
473
|
+
totalOverrides,
|
|
474
|
+
significantChanges,
|
|
475
|
+
performanceRisk,
|
|
476
|
+
recommendation
|
|
477
|
+
};
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
export {
|
|
481
|
+
SmartConfigManager
|
|
482
|
+
};
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __toESM = (mod, isNodeMode, target) => {
|
|
8
|
+
target = mod != null ? __create(__getProtoOf(mod)) : {};
|
|
9
|
+
const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
|
|
10
|
+
for (let key of __getOwnPropNames(mod))
|
|
11
|
+
if (!__hasOwnProp.call(to, key))
|
|
12
|
+
__defProp(to, key, {
|
|
13
|
+
get: () => mod[key],
|
|
14
|
+
enumerable: true
|
|
15
|
+
});
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
19
|
+
|
|
20
|
+
// src/diagnostics/smart-handle.ts
|
|
21
|
+
import debug from "debug";
|
|
22
|
+
import {
|
|
23
|
+
globalResourceManager
|
|
24
|
+
} from "./resource-manager.js";
|
|
25
|
+
var smartHandleDebug = debug("pw:mcp:smart-handle");
|
|
26
|
+
|
|
27
|
+
class SmartHandle {
|
|
28
|
+
disposed = false;
|
|
29
|
+
resource;
|
|
30
|
+
resourceId;
|
|
31
|
+
tracker;
|
|
32
|
+
constructor(resource, tracker) {
|
|
33
|
+
this.resource = resource;
|
|
34
|
+
this.tracker = tracker || globalResourceManager;
|
|
35
|
+
this.resourceId = this.tracker.trackResource(resource, "dispose");
|
|
36
|
+
}
|
|
37
|
+
get(target, prop, _receiver) {
|
|
38
|
+
if (this.disposed) {
|
|
39
|
+
throw new Error("SmartHandle has been disposed");
|
|
40
|
+
}
|
|
41
|
+
const value = target[prop];
|
|
42
|
+
if (typeof value === "function") {
|
|
43
|
+
return value.bind(target);
|
|
44
|
+
}
|
|
45
|
+
return value;
|
|
46
|
+
}
|
|
47
|
+
set(target, prop, value, _receiver) {
|
|
48
|
+
if (this.disposed) {
|
|
49
|
+
throw new Error("SmartHandle has been disposed");
|
|
50
|
+
}
|
|
51
|
+
target[prop] = value;
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
async dispose() {
|
|
55
|
+
if (this.disposed) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
try {
|
|
59
|
+
if (this.resource && typeof this.resource.dispose === "function") {
|
|
60
|
+
await this.resource.dispose();
|
|
61
|
+
}
|
|
62
|
+
} catch (error) {
|
|
63
|
+
smartHandleDebug("Resource disposal failed:", error instanceof Error ? error.message : String(error));
|
|
64
|
+
} finally {
|
|
65
|
+
this.disposed = true;
|
|
66
|
+
this.tracker.untrackResource(this.resourceId);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
isDisposed() {
|
|
70
|
+
return this.disposed;
|
|
71
|
+
}
|
|
72
|
+
getResource() {
|
|
73
|
+
if (this.disposed) {
|
|
74
|
+
throw new Error("SmartHandle has been disposed");
|
|
75
|
+
}
|
|
76
|
+
return this.resource;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
function createSmartHandle(elementHandle, tracker) {
|
|
80
|
+
const smartHandle = new SmartHandle(elementHandle, tracker);
|
|
81
|
+
return new Proxy(elementHandle, smartHandle);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
class SmartHandleBatch {
|
|
85
|
+
handles = [];
|
|
86
|
+
disposed = false;
|
|
87
|
+
add(handle, tracker) {
|
|
88
|
+
if (this.disposed) {
|
|
89
|
+
throw new Error("SmartHandleBatch has been disposed");
|
|
90
|
+
}
|
|
91
|
+
const smartHandle = new SmartHandle(handle, tracker);
|
|
92
|
+
this.handles.push(smartHandle);
|
|
93
|
+
return new Proxy(handle, smartHandle);
|
|
94
|
+
}
|
|
95
|
+
async dispose() {
|
|
96
|
+
await this.disposeAll();
|
|
97
|
+
}
|
|
98
|
+
async disposeAll() {
|
|
99
|
+
if (this.disposed) {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
const disposePromises = this.handles.map((handle) => handle.dispose());
|
|
103
|
+
await Promise.allSettled(disposePromises);
|
|
104
|
+
this.handles.length = 0;
|
|
105
|
+
this.disposed = true;
|
|
106
|
+
}
|
|
107
|
+
getActiveCount() {
|
|
108
|
+
return this.handles.filter((handle) => !handle.isDisposed()).length;
|
|
109
|
+
}
|
|
110
|
+
isDisposed() {
|
|
111
|
+
return this.disposed;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
export {
|
|
115
|
+
createSmartHandle,
|
|
116
|
+
SmartHandleBatch,
|
|
117
|
+
SmartHandle
|
|
118
|
+
};
|