@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.
Files changed (107) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +1047 -0
  3. package/cli.js +18 -0
  4. package/config.d.ts +124 -0
  5. package/index.d.ts +25 -0
  6. package/index.js +18 -0
  7. package/lib/actions.d.js +0 -0
  8. package/lib/batch/batch-executor.js +137 -0
  9. package/lib/browser-context-factory.js +252 -0
  10. package/lib/browser-server-backend.js +139 -0
  11. package/lib/config/constants.js +80 -0
  12. package/lib/config.js +405 -0
  13. package/lib/context.js +274 -0
  14. package/lib/diagnostics/common/diagnostic-base.js +63 -0
  15. package/lib/diagnostics/common/error-enrichment-utils.js +212 -0
  16. package/lib/diagnostics/common/index.js +56 -0
  17. package/lib/diagnostics/common/initialization-manager.js +210 -0
  18. package/lib/diagnostics/common/performance-tracker.js +132 -0
  19. package/lib/diagnostics/diagnostic-error.js +140 -0
  20. package/lib/diagnostics/diagnostic-level.js +123 -0
  21. package/lib/diagnostics/diagnostic-thresholds.js +347 -0
  22. package/lib/diagnostics/element-discovery.js +441 -0
  23. package/lib/diagnostics/enhanced-error-handler.js +376 -0
  24. package/lib/diagnostics/error-enrichment.js +157 -0
  25. package/lib/diagnostics/frame-reference-manager.js +179 -0
  26. package/lib/diagnostics/page-analyzer.js +639 -0
  27. package/lib/diagnostics/parallel-page-analyzer.js +129 -0
  28. package/lib/diagnostics/resource-manager.js +134 -0
  29. package/lib/diagnostics/smart-config.js +482 -0
  30. package/lib/diagnostics/smart-handle.js +118 -0
  31. package/lib/diagnostics/unified-system.js +717 -0
  32. package/lib/extension/cdp-relay.js +486 -0
  33. package/lib/extension/extension-context-factory.js +74 -0
  34. package/lib/extension/main.js +41 -0
  35. package/lib/file-utils.js +42 -0
  36. package/lib/generate-keys.js +75 -0
  37. package/lib/http-server.js +50 -0
  38. package/lib/in-process-client.js +64 -0
  39. package/lib/index.js +48 -0
  40. package/lib/javascript.js +90 -0
  41. package/lib/log.js +33 -0
  42. package/lib/loop/loop-claude.js +247 -0
  43. package/lib/loop/loop-open-ai.js +222 -0
  44. package/lib/loop/loop.js +174 -0
  45. package/lib/loop/main.js +46 -0
  46. package/lib/loopTools/context.js +76 -0
  47. package/lib/loopTools/main.js +65 -0
  48. package/lib/loopTools/perform.js +40 -0
  49. package/lib/loopTools/snapshot.js +37 -0
  50. package/lib/loopTools/tool.js +26 -0
  51. package/lib/manual-promise.js +125 -0
  52. package/lib/mcp/in-process-transport.js +91 -0
  53. package/lib/mcp/proxy-backend.js +127 -0
  54. package/lib/mcp/server.js +123 -0
  55. package/lib/mcp/transport.js +159 -0
  56. package/lib/package.js +28 -0
  57. package/lib/program.js +82 -0
  58. package/lib/response.js +493 -0
  59. package/lib/schemas/expectation.js +152 -0
  60. package/lib/session-log.js +210 -0
  61. package/lib/tab.js +417 -0
  62. package/lib/tools/base-tool-handler.js +141 -0
  63. package/lib/tools/batch-execute.js +150 -0
  64. package/lib/tools/common.js +65 -0
  65. package/lib/tools/console.js +60 -0
  66. package/lib/tools/diagnose/diagnose-analysis-runner.js +101 -0
  67. package/lib/tools/diagnose/diagnose-config-handler.js +130 -0
  68. package/lib/tools/diagnose/diagnose-report-builder.js +394 -0
  69. package/lib/tools/diagnose.js +147 -0
  70. package/lib/tools/dialogs.js +57 -0
  71. package/lib/tools/evaluate.js +67 -0
  72. package/lib/tools/files.js +53 -0
  73. package/lib/tools/find-elements.js +307 -0
  74. package/lib/tools/install.js +60 -0
  75. package/lib/tools/keyboard.js +93 -0
  76. package/lib/tools/mouse.js +110 -0
  77. package/lib/tools/navigate.js +82 -0
  78. package/lib/tools/network.js +50 -0
  79. package/lib/tools/pdf.js +46 -0
  80. package/lib/tools/screenshot.js +113 -0
  81. package/lib/tools/snapshot.js +158 -0
  82. package/lib/tools/tabs.js +97 -0
  83. package/lib/tools/tool.js +47 -0
  84. package/lib/tools/utils.js +131 -0
  85. package/lib/tools/wait.js +64 -0
  86. package/lib/tools.js +65 -0
  87. package/lib/types/batch.js +47 -0
  88. package/lib/types/diff.js +0 -0
  89. package/lib/types/performance.js +0 -0
  90. package/lib/types/threshold-base.js +0 -0
  91. package/lib/utils/array-utils.js +44 -0
  92. package/lib/utils/code-deduplication-utils.js +141 -0
  93. package/lib/utils/common-formatters.js +252 -0
  94. package/lib/utils/console-filter.js +64 -0
  95. package/lib/utils/diagnostic-report-utils.js +178 -0
  96. package/lib/utils/diff-formatter.js +126 -0
  97. package/lib/utils/disposable-manager.js +135 -0
  98. package/lib/utils/error-handler-middleware.js +77 -0
  99. package/lib/utils/image-processor.js +137 -0
  100. package/lib/utils/index.js +92 -0
  101. package/lib/utils/report-builder.js +189 -0
  102. package/lib/utils/request-logger.js +82 -0
  103. package/lib/utils/response-diff-detector.js +150 -0
  104. package/lib/utils/section-builder.js +62 -0
  105. package/lib/utils/tool-patterns.js +153 -0
  106. package/lib/utils.js +46 -0
  107. 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
+ };