@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,131 @@
|
|
|
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/tools/utils.ts
|
|
21
|
+
import debug from "debug";
|
|
22
|
+
import { asLocator } from "playwright-core/lib/utils";
|
|
23
|
+
import { TIMEOUTS } from "../config/constants.js";
|
|
24
|
+
var toolsDebug = debug("pw:mcp:tools");
|
|
25
|
+
async function waitForCompletion(tab, callback) {
|
|
26
|
+
const requests = new Set;
|
|
27
|
+
let frameNavigated = false;
|
|
28
|
+
let navigationCompleted = false;
|
|
29
|
+
let waitCallback = () => {};
|
|
30
|
+
const waitBarrier = new Promise((f) => {
|
|
31
|
+
waitCallback = f;
|
|
32
|
+
});
|
|
33
|
+
const requestListener = (request) => requests.add(request);
|
|
34
|
+
const requestFinishedListener = (request) => {
|
|
35
|
+
requests.delete(request);
|
|
36
|
+
if (!requests.size && navigationCompleted) {
|
|
37
|
+
waitCallback();
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
const frameNavigateListener = (frame) => {
|
|
41
|
+
if (frame.parentFrame()) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
frameNavigated = true;
|
|
45
|
+
(async () => {
|
|
46
|
+
try {
|
|
47
|
+
await tab.waitForLoadState("load");
|
|
48
|
+
await tab.waitForLoadState("networkidle", {
|
|
49
|
+
timeout: getNavigationConfig().networkIdleTimeout
|
|
50
|
+
}).catch((error) => {
|
|
51
|
+
toolsDebug("Network idle timeout reached:", error);
|
|
52
|
+
});
|
|
53
|
+
navigationCompleted = true;
|
|
54
|
+
if (!requests.size) {
|
|
55
|
+
waitCallback();
|
|
56
|
+
}
|
|
57
|
+
} catch (error) {
|
|
58
|
+
toolsDebug("Load state waiting failed, continuing:", error);
|
|
59
|
+
navigationCompleted = true;
|
|
60
|
+
waitCallback();
|
|
61
|
+
}
|
|
62
|
+
})().catch((error) => {
|
|
63
|
+
toolsDebug("Navigation handling failed:", error);
|
|
64
|
+
navigationCompleted = true;
|
|
65
|
+
waitCallback();
|
|
66
|
+
});
|
|
67
|
+
};
|
|
68
|
+
const onTimeout = () => {
|
|
69
|
+
dispose();
|
|
70
|
+
navigationCompleted = true;
|
|
71
|
+
waitCallback();
|
|
72
|
+
};
|
|
73
|
+
tab.page.on("request", requestListener);
|
|
74
|
+
tab.page.on("requestfinished", requestFinishedListener);
|
|
75
|
+
tab.page.on("framenavigated", frameNavigateListener);
|
|
76
|
+
const timeout = setTimeout(onTimeout, getNavigationConfig().completionTimeout);
|
|
77
|
+
const dispose = () => {
|
|
78
|
+
tab.page.off("request", requestListener);
|
|
79
|
+
tab.page.off("requestfinished", requestFinishedListener);
|
|
80
|
+
tab.page.off("framenavigated", frameNavigateListener);
|
|
81
|
+
clearTimeout(timeout);
|
|
82
|
+
};
|
|
83
|
+
try {
|
|
84
|
+
const result = await callback();
|
|
85
|
+
if (!(requests.size || frameNavigated)) {
|
|
86
|
+
navigationCompleted = true;
|
|
87
|
+
waitCallback();
|
|
88
|
+
}
|
|
89
|
+
await waitBarrier;
|
|
90
|
+
if (frameNavigated) {
|
|
91
|
+
await tab.waitForTimeout(getNavigationConfig().stabilityWait);
|
|
92
|
+
try {
|
|
93
|
+
await tab.page.evaluate(() => document.readyState);
|
|
94
|
+
} catch (error) {
|
|
95
|
+
toolsDebug("Page readyState check failed (context may be destroyed):", error);
|
|
96
|
+
}
|
|
97
|
+
} else {
|
|
98
|
+
await tab.waitForTimeout(getNavigationConfig().defaultWait);
|
|
99
|
+
}
|
|
100
|
+
return result;
|
|
101
|
+
} finally {
|
|
102
|
+
dispose();
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
async function generateLocator(locator) {
|
|
106
|
+
try {
|
|
107
|
+
const { resolvedSelector } = await locator._resolveSelector();
|
|
108
|
+
return asLocator("javascript", resolvedSelector);
|
|
109
|
+
} catch (error) {
|
|
110
|
+
toolsDebug("Locator generation failed:", error);
|
|
111
|
+
throw new Error("Ref not found, likely because element was removed. Use browser_snapshot to see what elements are currently on the page.");
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
async function callOnPageNoTrace(page, callback) {
|
|
115
|
+
return await page._wrapApiCall(() => callback(page), {
|
|
116
|
+
internal: true
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
function getNavigationConfig() {
|
|
120
|
+
return {
|
|
121
|
+
networkIdleTimeout: TIMEOUTS.NETWORK_IDLE_TIMEOUT,
|
|
122
|
+
completionTimeout: 15000,
|
|
123
|
+
stabilityWait: TIMEOUTS.STABILITY_WAIT,
|
|
124
|
+
defaultWait: TIMEOUTS.WAIT_FOR_COMPLETION
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
export {
|
|
128
|
+
waitForCompletion,
|
|
129
|
+
generateLocator,
|
|
130
|
+
callOnPageNoTrace
|
|
131
|
+
};
|
|
@@ -0,0 +1,64 @@
|
|
|
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/tools/wait.ts
|
|
21
|
+
import { z } from "zod";
|
|
22
|
+
import { expectationSchema } from "../schemas/expectation.js";
|
|
23
|
+
import { defineTool } from "./tool.js";
|
|
24
|
+
var wait = defineTool({
|
|
25
|
+
capability: "core",
|
|
26
|
+
schema: {
|
|
27
|
+
name: "browser_wait_for",
|
|
28
|
+
title: "Wait for",
|
|
29
|
+
description: `Wait for text to appear/disappear or time to pass.PREFER text-based wait over time for reliability.For loading states:wait for text:"Loading..." textGone:true.For dynamic content:wait for specific text to appear.expectation:{includeSnapshot:true,snapshotOptions:{selector:"#status"},diffOptions:{enabled:true}} shows only what changed.AVOID:fixed time waits unless necessary.`,
|
|
30
|
+
inputSchema: z.object({
|
|
31
|
+
time: z.number().optional().describe("The time to wait in seconds"),
|
|
32
|
+
text: z.string().optional().describe("The text to wait for"),
|
|
33
|
+
textGone: z.string().optional().describe("The text to wait for to disappear"),
|
|
34
|
+
expectation: expectationSchema
|
|
35
|
+
}),
|
|
36
|
+
type: "readOnly"
|
|
37
|
+
},
|
|
38
|
+
handle: async (context, params, response) => {
|
|
39
|
+
if (!(params.text || params.textGone || params.time)) {
|
|
40
|
+
throw new Error("Either time, text or textGone must be provided");
|
|
41
|
+
}
|
|
42
|
+
if (params.time) {
|
|
43
|
+
response.addCode(`await new Promise(f => setTimeout(f, ${params.time} * 1000));`);
|
|
44
|
+
await new Promise((f) => setTimeout(f, Math.min(30000, (params.time ?? 0) * 1000)));
|
|
45
|
+
}
|
|
46
|
+
const tab = context.currentTabOrDie();
|
|
47
|
+
const locator = params.text ? tab.page.getByText(params.text).first() : undefined;
|
|
48
|
+
const goneLocator = params.textGone ? tab.page.getByText(params.textGone).first() : undefined;
|
|
49
|
+
if (goneLocator) {
|
|
50
|
+
response.addCode(`await page.getByText(${JSON.stringify(params.textGone)}).first().waitFor({ state: 'hidden' });`);
|
|
51
|
+
await goneLocator.waitFor({ state: "hidden" });
|
|
52
|
+
}
|
|
53
|
+
if (locator) {
|
|
54
|
+
response.addCode(`await page.getByText(${JSON.stringify(params.text)}).first().waitFor({ state: 'visible' });`);
|
|
55
|
+
await locator.waitFor({ state: "visible" });
|
|
56
|
+
}
|
|
57
|
+
response.addResult(`Waited for ${params.text ?? params.textGone ?? params.time}`);
|
|
58
|
+
response.setIncludeSnapshot();
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
var wait_default = [wait];
|
|
62
|
+
export {
|
|
63
|
+
wait_default as default
|
|
64
|
+
};
|
package/lib/tools.js
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
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/tools.ts
|
|
21
|
+
import { batchExecuteTool } from "./tools/batch-execute.js";
|
|
22
|
+
import common from "./tools/common.js";
|
|
23
|
+
import console from "./tools/console.js";
|
|
24
|
+
import { browserDiagnose } from "./tools/diagnose.js";
|
|
25
|
+
import dialogs from "./tools/dialogs.js";
|
|
26
|
+
import evaluate from "./tools/evaluate.js";
|
|
27
|
+
import files from "./tools/files.js";
|
|
28
|
+
import { browserFindElements } from "./tools/find-elements.js";
|
|
29
|
+
import install from "./tools/install.js";
|
|
30
|
+
import keyboard from "./tools/keyboard.js";
|
|
31
|
+
import mouse from "./tools/mouse.js";
|
|
32
|
+
import navigate from "./tools/navigate.js";
|
|
33
|
+
import network from "./tools/network.js";
|
|
34
|
+
import pdf from "./tools/pdf.js";
|
|
35
|
+
import screenshot from "./tools/screenshot.js";
|
|
36
|
+
import snapshot from "./tools/snapshot.js";
|
|
37
|
+
import tabs from "./tools/tabs.js";
|
|
38
|
+
import wait from "./tools/wait.js";
|
|
39
|
+
var allTools = [
|
|
40
|
+
...common,
|
|
41
|
+
...console,
|
|
42
|
+
...dialogs,
|
|
43
|
+
...evaluate,
|
|
44
|
+
...files,
|
|
45
|
+
...install,
|
|
46
|
+
...keyboard,
|
|
47
|
+
...navigate,
|
|
48
|
+
...network,
|
|
49
|
+
...mouse,
|
|
50
|
+
...pdf,
|
|
51
|
+
...screenshot,
|
|
52
|
+
...snapshot,
|
|
53
|
+
...tabs,
|
|
54
|
+
...wait,
|
|
55
|
+
batchExecuteTool,
|
|
56
|
+
browserFindElements,
|
|
57
|
+
browserDiagnose
|
|
58
|
+
];
|
|
59
|
+
function filteredTools(config) {
|
|
60
|
+
return allTools.filter((tool) => tool.capability.startsWith("core") || config.capabilities?.includes(tool.capability));
|
|
61
|
+
}
|
|
62
|
+
export {
|
|
63
|
+
filteredTools,
|
|
64
|
+
allTools
|
|
65
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
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/types/batch.ts
|
|
21
|
+
import { z } from "zod";
|
|
22
|
+
import { expectationSchema } from "../schemas/expectation.js";
|
|
23
|
+
var parseJsonString = (val) => {
|
|
24
|
+
if (typeof val === "string") {
|
|
25
|
+
try {
|
|
26
|
+
return JSON.parse(val);
|
|
27
|
+
} catch {
|
|
28
|
+
return val;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return val;
|
|
32
|
+
};
|
|
33
|
+
var batchStepSchema = z.object({
|
|
34
|
+
tool: z.string().describe("Tool name to execute"),
|
|
35
|
+
arguments: z.record(z.unknown()).describe("Arguments for the tool"),
|
|
36
|
+
continueOnError: z.boolean().optional().default(false).describe("Continue batch execution if this step fails"),
|
|
37
|
+
expectation: expectationSchema.describe("Expected output configuration for this step")
|
|
38
|
+
});
|
|
39
|
+
var batchExecuteSchema = z.object({
|
|
40
|
+
steps: z.array(batchStepSchema).min(1).describe("Array of steps to execute in sequence"),
|
|
41
|
+
stopOnFirstError: z.boolean().optional().default(false).describe("Stop entire batch on first error"),
|
|
42
|
+
globalExpectation: z.preprocess(parseJsonString, expectationSchema).optional().describe("Default expectation for all steps")
|
|
43
|
+
});
|
|
44
|
+
export {
|
|
45
|
+
batchStepSchema,
|
|
46
|
+
batchExecuteSchema
|
|
47
|
+
};
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,44 @@
|
|
|
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/utils/array-utils.ts
|
|
21
|
+
function deduplicateAndLimit(items, limit) {
|
|
22
|
+
const unique = [...new Set(items)];
|
|
23
|
+
return limit ? unique.slice(0, limit) : unique;
|
|
24
|
+
}
|
|
25
|
+
function deduplicate(items) {
|
|
26
|
+
return [...new Set(items)];
|
|
27
|
+
}
|
|
28
|
+
function limitItems(items, limit) {
|
|
29
|
+
return limit > 0 ? items.slice(0, limit) : items;
|
|
30
|
+
}
|
|
31
|
+
function filterTruthy(items) {
|
|
32
|
+
return items.filter((item) => Boolean(item));
|
|
33
|
+
}
|
|
34
|
+
function joinFiltered(items, separator = `
|
|
35
|
+
`) {
|
|
36
|
+
return filterTruthy(items).join(separator);
|
|
37
|
+
}
|
|
38
|
+
export {
|
|
39
|
+
limitItems,
|
|
40
|
+
joinFiltered,
|
|
41
|
+
filterTruthy,
|
|
42
|
+
deduplicateAndLimit,
|
|
43
|
+
deduplicate
|
|
44
|
+
};
|
|
@@ -0,0 +1,141 @@
|
|
|
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/utils/code-deduplication-utils.ts
|
|
21
|
+
import { formatDiagnosticPair } from "./common-formatters.js";
|
|
22
|
+
var formatDiagnosticKeyValue = formatDiagnosticPair;
|
|
23
|
+
function formatElementCounts(counts) {
|
|
24
|
+
const results = [];
|
|
25
|
+
if (counts.total !== undefined) {
|
|
26
|
+
results.push(formatDiagnosticPair("Total elements", counts.total));
|
|
27
|
+
}
|
|
28
|
+
if (counts.visible !== undefined) {
|
|
29
|
+
results.push(formatDiagnosticPair("Visible elements", counts.visible));
|
|
30
|
+
}
|
|
31
|
+
if (counts.interactable !== undefined) {
|
|
32
|
+
results.push(formatDiagnosticPair("Interactable elements", counts.interactable));
|
|
33
|
+
}
|
|
34
|
+
if (counts.disabled !== undefined) {
|
|
35
|
+
results.push(formatDiagnosticPair("Disabled elements", counts.disabled));
|
|
36
|
+
}
|
|
37
|
+
return results;
|
|
38
|
+
}
|
|
39
|
+
function formatListItems(items, level = 0) {
|
|
40
|
+
const indent = " ".repeat(level);
|
|
41
|
+
return items.map((item) => `${indent}- ${item}`);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
class ArrayBuilder {
|
|
45
|
+
items = [];
|
|
46
|
+
constructor(initial) {
|
|
47
|
+
if (initial) {
|
|
48
|
+
this.items = [...initial];
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
add(item) {
|
|
52
|
+
this.items.push(item);
|
|
53
|
+
return this;
|
|
54
|
+
}
|
|
55
|
+
addAll(items) {
|
|
56
|
+
this.items.push(...items);
|
|
57
|
+
return this;
|
|
58
|
+
}
|
|
59
|
+
addIf(condition, item) {
|
|
60
|
+
const shouldAdd = typeof condition === "function" ? condition() : condition;
|
|
61
|
+
if (shouldAdd) {
|
|
62
|
+
const itemToAdd = typeof item === "function" ? item() : item;
|
|
63
|
+
this.items.push(itemToAdd);
|
|
64
|
+
}
|
|
65
|
+
return this;
|
|
66
|
+
}
|
|
67
|
+
addAllIf(condition, items) {
|
|
68
|
+
const shouldAdd = typeof condition === "function" ? condition() : condition;
|
|
69
|
+
if (shouldAdd) {
|
|
70
|
+
const itemsToAdd = typeof items === "function" ? items() : items;
|
|
71
|
+
this.items.push(...itemsToAdd);
|
|
72
|
+
}
|
|
73
|
+
return this;
|
|
74
|
+
}
|
|
75
|
+
build() {
|
|
76
|
+
return [...this.items];
|
|
77
|
+
}
|
|
78
|
+
getItems() {
|
|
79
|
+
return [...this.items];
|
|
80
|
+
}
|
|
81
|
+
clear() {
|
|
82
|
+
this.items = [];
|
|
83
|
+
return this;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
function joinLines(lines) {
|
|
87
|
+
return lines.join(`
|
|
88
|
+
`);
|
|
89
|
+
}
|
|
90
|
+
function truncateAtWordBoundary(text, maxLength) {
|
|
91
|
+
if (text.length <= maxLength) {
|
|
92
|
+
return text;
|
|
93
|
+
}
|
|
94
|
+
let truncateIndex = maxLength;
|
|
95
|
+
if (text[maxLength] && text[maxLength] !== " " && text[maxLength] !== `
|
|
96
|
+
`) {
|
|
97
|
+
for (let i = maxLength - 1;i >= 0; i--) {
|
|
98
|
+
if (text[i] === " " || text[i] === `
|
|
99
|
+
`) {
|
|
100
|
+
truncateIndex = i;
|
|
101
|
+
break;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
if (maxLength - truncateIndex > 20) {
|
|
105
|
+
truncateIndex = maxLength;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return text.substring(0, truncateIndex).trim();
|
|
109
|
+
}
|
|
110
|
+
function formatError(error) {
|
|
111
|
+
const result = [`Error: ${error.message}`];
|
|
112
|
+
if (error.suggestions && error.suggestions.length > 0) {
|
|
113
|
+
result.push("", "Suggestions:");
|
|
114
|
+
result.push(...error.suggestions.map((s) => `- ${s}`));
|
|
115
|
+
}
|
|
116
|
+
return result;
|
|
117
|
+
}
|
|
118
|
+
function getStatusIcon(status) {
|
|
119
|
+
switch (status) {
|
|
120
|
+
case "success":
|
|
121
|
+
return "✅";
|
|
122
|
+
case "warning":
|
|
123
|
+
return "⚠️";
|
|
124
|
+
case "error":
|
|
125
|
+
return "\uD83D\uDEA8";
|
|
126
|
+
case "info":
|
|
127
|
+
return "ℹ️";
|
|
128
|
+
default:
|
|
129
|
+
return "⚪";
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
export {
|
|
133
|
+
truncateAtWordBoundary,
|
|
134
|
+
joinLines,
|
|
135
|
+
getStatusIcon,
|
|
136
|
+
formatListItems,
|
|
137
|
+
formatError,
|
|
138
|
+
formatElementCounts,
|
|
139
|
+
formatDiagnosticKeyValue,
|
|
140
|
+
ArrayBuilder
|
|
141
|
+
};
|