@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,152 @@
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/schemas/expectation.ts
21
+ import { z } from "zod";
22
+ var diffOptionsSchema = z.object({
23
+ enabled: z.boolean().default(false),
24
+ threshold: z.number().min(0).max(1).default(0.1),
25
+ format: z.enum(["unified", "split", "minimal"]).default("unified"),
26
+ maxDiffLines: z.number().positive().default(50),
27
+ ignoreWhitespace: z.boolean().default(true),
28
+ context: z.number().min(0).default(3)
29
+ }).optional();
30
+ var expectationSchema = z.object({
31
+ includeSnapshot: z.boolean().optional().default(false),
32
+ includeConsole: z.boolean().optional().default(false),
33
+ includeDownloads: z.boolean().optional().default(false),
34
+ includeTabs: z.boolean().optional().default(false),
35
+ includeCode: z.boolean().optional().default(false),
36
+ snapshotOptions: z.object({
37
+ selector: z.string().optional().describe("CSS selector to limit snapshot scope"),
38
+ maxLength: z.number().optional().describe("Maximum characters for snapshot"),
39
+ format: z.enum(["aria", "text", "html"]).optional().default("aria")
40
+ }).optional(),
41
+ consoleOptions: z.object({
42
+ levels: z.array(z.enum(["log", "warn", "error", "info"])).optional(),
43
+ maxMessages: z.number().optional().default(10),
44
+ patterns: z.array(z.string()).optional().describe("Regex patterns to filter messages"),
45
+ removeDuplicates: z.boolean().optional().default(false).describe("Remove duplicate messages")
46
+ }).optional(),
47
+ imageOptions: z.object({
48
+ quality: z.number().min(1).max(100).optional().describe("JPEG quality (1-100)"),
49
+ maxWidth: z.number().optional().describe("Maximum width in pixels"),
50
+ maxHeight: z.number().optional().describe("Maximum height in pixels"),
51
+ format: z.enum(["jpeg", "png", "webp"]).optional()
52
+ }).optional(),
53
+ diffOptions: diffOptionsSchema
54
+ }).optional();
55
+ var TOOL_DEFAULTS = {
56
+ browser_navigate: {
57
+ includeSnapshot: false,
58
+ includeConsole: false,
59
+ includeDownloads: false,
60
+ includeTabs: false,
61
+ includeCode: false
62
+ },
63
+ browser_click: {
64
+ includeSnapshot: false,
65
+ includeConsole: false,
66
+ includeDownloads: false,
67
+ includeTabs: false,
68
+ includeCode: false
69
+ },
70
+ browser_type: {
71
+ includeSnapshot: false,
72
+ includeConsole: false,
73
+ includeDownloads: false,
74
+ includeTabs: false,
75
+ includeCode: false
76
+ },
77
+ browser_take_screenshot: {
78
+ includeSnapshot: false,
79
+ includeConsole: false,
80
+ includeDownloads: false,
81
+ includeTabs: false,
82
+ includeCode: false
83
+ },
84
+ browser_snapshot: {
85
+ includeSnapshot: true,
86
+ includeConsole: false,
87
+ includeDownloads: false,
88
+ includeTabs: false,
89
+ includeCode: false
90
+ },
91
+ browser_evaluate: {
92
+ includeSnapshot: false,
93
+ includeConsole: false,
94
+ includeDownloads: false,
95
+ includeTabs: false,
96
+ includeCode: false
97
+ },
98
+ browser_pdf_save: {
99
+ includeSnapshot: false,
100
+ includeConsole: false,
101
+ includeDownloads: false,
102
+ includeTabs: false,
103
+ includeCode: true
104
+ },
105
+ browser_wait_for: {
106
+ includeSnapshot: false,
107
+ includeConsole: false,
108
+ includeDownloads: false,
109
+ includeTabs: false,
110
+ includeCode: false
111
+ },
112
+ browser_close: {
113
+ includeSnapshot: false,
114
+ includeConsole: false,
115
+ includeDownloads: false,
116
+ includeTabs: true,
117
+ includeCode: true
118
+ }
119
+ };
120
+ var GENERAL_DEFAULT = {
121
+ includeSnapshot: false,
122
+ includeConsole: false,
123
+ includeDownloads: false,
124
+ includeTabs: false,
125
+ includeCode: false
126
+ };
127
+ function getDefaultExpectation(toolName) {
128
+ return TOOL_DEFAULTS[toolName] ?? GENERAL_DEFAULT;
129
+ }
130
+ function mergeExpectations(toolName, userExpectation) {
131
+ const defaults = getDefaultExpectation(toolName);
132
+ if (!userExpectation) {
133
+ return defaults;
134
+ }
135
+ return {
136
+ includeSnapshot: userExpectation.includeSnapshot ?? defaults.includeSnapshot,
137
+ includeConsole: userExpectation.includeConsole ?? defaults.includeConsole,
138
+ includeDownloads: userExpectation.includeDownloads ?? defaults.includeDownloads,
139
+ includeTabs: userExpectation.includeTabs ?? defaults.includeTabs,
140
+ includeCode: userExpectation.includeCode ?? defaults.includeCode,
141
+ snapshotOptions: userExpectation.snapshotOptions,
142
+ consoleOptions: userExpectation.consoleOptions,
143
+ imageOptions: userExpectation.imageOptions,
144
+ diffOptions: userExpectation.diffOptions
145
+ };
146
+ }
147
+ export {
148
+ mergeExpectations,
149
+ getDefaultExpectation,
150
+ expectationSchema,
151
+ diffOptionsSchema
152
+ };
@@ -0,0 +1,210 @@
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/session-log.ts
21
+ import fs from "node:fs";
22
+ import path from "node:path";
23
+ import { outputFile } from "./config.js";
24
+ import { logUnhandledError } from "./log.js";
25
+
26
+ class SessionLog {
27
+ _folder;
28
+ _file;
29
+ _pendingEntries = [];
30
+ _sessionFileQueue = Promise.resolve();
31
+ _flushEntriesTimeout;
32
+ _ordinal = 0;
33
+ constructor(sessionFolder) {
34
+ this._folder = sessionFolder;
35
+ this._file = path.join(this._folder, "session.md");
36
+ }
37
+ static async create(config, rootPath) {
38
+ const sessionFolder = await outputFile(config, rootPath, `session-${Date.now()}`);
39
+ await fs.promises.mkdir(sessionFolder, { recursive: true });
40
+ return new SessionLog(sessionFolder);
41
+ }
42
+ logResponse(response) {
43
+ const entry = {
44
+ timestamp: performance.now(),
45
+ toolCall: {
46
+ toolName: response.toolName,
47
+ toolArgs: response.toolArgs,
48
+ result: response.result(),
49
+ isError: response.isError()
50
+ },
51
+ code: response.code(),
52
+ tabSnapshot: response.tabSnapshot()
53
+ };
54
+ this._appendEntry(entry);
55
+ }
56
+ logUserAction(action, tab, code, isUpdate) {
57
+ const trimmedCode = code.trim();
58
+ if (this._shouldUpdateExistingEntry(action, isUpdate, trimmedCode)) {
59
+ return;
60
+ }
61
+ if (this._shouldSkipDuplicateNavigation(action)) {
62
+ return;
63
+ }
64
+ const entry = this._createUserActionEntry(action, tab, trimmedCode);
65
+ this._appendEntry(entry);
66
+ }
67
+ _shouldUpdateExistingEntry(action, isUpdate, trimmedCode) {
68
+ if (!isUpdate) {
69
+ return false;
70
+ }
71
+ const lastEntry = this._pendingEntries.at(-1);
72
+ if (lastEntry?.userAction?.name === action.name) {
73
+ lastEntry.userAction = action;
74
+ lastEntry.code = trimmedCode;
75
+ return true;
76
+ }
77
+ return false;
78
+ }
79
+ _shouldSkipDuplicateNavigation(action) {
80
+ if (action.name !== "navigate") {
81
+ return false;
82
+ }
83
+ const lastEntry = this._pendingEntries.at(-1);
84
+ return lastEntry?.tabSnapshot?.url === action.url;
85
+ }
86
+ _createUserActionEntry(action, tab, trimmedCode) {
87
+ return {
88
+ timestamp: performance.now(),
89
+ userAction: action,
90
+ code: trimmedCode,
91
+ tabSnapshot: this._createTabSnapshot(action, tab)
92
+ };
93
+ }
94
+ _createTabSnapshot(action, tab) {
95
+ return this._buildTabSnapshotObject(action, tab);
96
+ }
97
+ _buildTabSnapshotObject(action, tab) {
98
+ return {
99
+ url: tab.page.url(),
100
+ title: "",
101
+ ariaSnapshot: action.ariaSnapshot ?? "",
102
+ modalStates: [],
103
+ consoleMessages: [],
104
+ downloads: []
105
+ };
106
+ }
107
+ _appendEntry(entry) {
108
+ this._pendingEntries.push(entry);
109
+ if (this._flushEntriesTimeout) {
110
+ clearTimeout(this._flushEntriesTimeout);
111
+ }
112
+ this._flushEntriesTimeout = setTimeout(() => this._flushEntries(), 1000);
113
+ }
114
+ _flushEntries() {
115
+ this._executeFlushProcess();
116
+ }
117
+ _executeFlushProcess() {
118
+ this._clearFlushTimeout();
119
+ const { entries, lines } = this._prepareFlushData();
120
+ this._processEntries(entries, lines);
121
+ this._writeToFile(lines);
122
+ }
123
+ _clearFlushTimeout() {
124
+ if (this._flushEntriesTimeout) {
125
+ clearTimeout(this._flushEntriesTimeout);
126
+ }
127
+ }
128
+ _prepareFlushData() {
129
+ const entries = this._pendingEntries;
130
+ this._pendingEntries = [];
131
+ const lines = [""];
132
+ return { entries, lines };
133
+ }
134
+ _processEntries(entries, lines) {
135
+ for (const entry of entries) {
136
+ this._ordinal++;
137
+ const ordinal = this._ordinal.toString().padStart(3, "0");
138
+ this._formatSingleLogEntry(entry, ordinal, lines);
139
+ }
140
+ }
141
+ _writeToFile(lines) {
142
+ this._sessionFileQueue = this._sessionFileQueue.then(() => fs.promises.appendFile(this._file, lines.join(`
143
+ `)));
144
+ }
145
+ _formatSingleLogEntry(entry, ordinal, lines) {
146
+ this._addAllEntryContent(entry, ordinal, lines);
147
+ this._addEntryDelimiters(lines);
148
+ }
149
+ _addAllEntryContent(entry, ordinal, lines) {
150
+ this._addToolCallContent(entry, lines);
151
+ this._addUserActionContent(entry, lines);
152
+ this._addCodeContent(entry, lines);
153
+ this._addTabSnapshotContent(entry, ordinal, lines);
154
+ }
155
+ _addEntryDelimiters(lines) {
156
+ lines.push("", "");
157
+ }
158
+ _addToolCallContent(entry, lines) {
159
+ if (!entry.toolCall) {
160
+ return;
161
+ }
162
+ this._addToolCallLines(entry.toolCall, lines);
163
+ }
164
+ _addUserActionContent(entry, lines) {
165
+ if (!entry.userAction) {
166
+ return;
167
+ }
168
+ this._addUserActionLines(entry.userAction, lines);
169
+ }
170
+ _addCodeContent(entry, lines) {
171
+ if (!entry.code) {
172
+ return;
173
+ }
174
+ lines.push("- Code", "```js", entry.code, "```");
175
+ }
176
+ _addTabSnapshotContent(entry, ordinal, lines) {
177
+ if (!entry.tabSnapshot) {
178
+ return;
179
+ }
180
+ this._addTabSnapshotLines(entry.tabSnapshot, ordinal, lines);
181
+ }
182
+ _addToolCallLines(toolCall, lines) {
183
+ this._addToolCallHeader(toolCall, lines);
184
+ this._addToolCallResult(toolCall, lines);
185
+ }
186
+ _addToolCallHeader(toolCall, lines) {
187
+ lines.push(`### Tool call: ${toolCall.toolName}`, "- Args", "```json", JSON.stringify(toolCall.toolArgs, null, 2), "```");
188
+ }
189
+ _addToolCallResult(toolCall, lines) {
190
+ if (!toolCall.result) {
191
+ return;
192
+ }
193
+ lines.push(toolCall.isError ? "- Error" : "- Result", "```", toolCall.result, "```");
194
+ }
195
+ _addUserActionLines(userAction, lines) {
196
+ const actionData = { ...userAction };
197
+ actionData.ariaSnapshot = undefined;
198
+ actionData.selector = undefined;
199
+ actionData.signals = undefined;
200
+ lines.push(`### User action: ${userAction.name}`, "- Args", "```json", JSON.stringify(actionData, null, 2), "```");
201
+ }
202
+ _addTabSnapshotLines(tabSnapshot, ordinal, lines) {
203
+ const fileName = `${ordinal}.snapshot.yml`;
204
+ fs.promises.writeFile(path.join(this._folder, fileName), tabSnapshot.ariaSnapshot).catch(logUnhandledError);
205
+ lines.push(`- Snapshot: ${fileName}`);
206
+ }
207
+ }
208
+ export {
209
+ SessionLog
210
+ };