testchimp-runner-core 0.0.34 → 0.0.36

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 (150) hide show
  1. package/dist/execution-service.d.ts +1 -4
  2. package/dist/execution-service.d.ts.map +1 -1
  3. package/dist/execution-service.js +155 -468
  4. package/dist/execution-service.js.map +1 -1
  5. package/dist/index.d.ts +3 -1
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +11 -1
  8. package/dist/index.js.map +1 -1
  9. package/dist/orchestrator/decision-parser.d.ts +18 -0
  10. package/dist/orchestrator/decision-parser.d.ts.map +1 -0
  11. package/dist/orchestrator/decision-parser.js +127 -0
  12. package/dist/orchestrator/decision-parser.js.map +1 -0
  13. package/dist/orchestrator/index.d.ts +4 -2
  14. package/dist/orchestrator/index.d.ts.map +1 -1
  15. package/dist/orchestrator/index.js +14 -2
  16. package/dist/orchestrator/index.js.map +1 -1
  17. package/dist/orchestrator/orchestrator-agent.d.ts +17 -14
  18. package/dist/orchestrator/orchestrator-agent.d.ts.map +1 -1
  19. package/dist/orchestrator/orchestrator-agent.js +534 -204
  20. package/dist/orchestrator/orchestrator-agent.js.map +1 -1
  21. package/dist/orchestrator/orchestrator-prompts.d.ts +14 -2
  22. package/dist/orchestrator/orchestrator-prompts.d.ts.map +1 -1
  23. package/dist/orchestrator/orchestrator-prompts.js +529 -247
  24. package/dist/orchestrator/orchestrator-prompts.js.map +1 -1
  25. package/dist/orchestrator/page-som-handler.d.ts +106 -0
  26. package/dist/orchestrator/page-som-handler.d.ts.map +1 -0
  27. package/dist/orchestrator/page-som-handler.js +1353 -0
  28. package/dist/orchestrator/page-som-handler.js.map +1 -0
  29. package/dist/orchestrator/som-types.d.ts +149 -0
  30. package/dist/orchestrator/som-types.d.ts.map +1 -0
  31. package/dist/orchestrator/som-types.js +87 -0
  32. package/dist/orchestrator/som-types.js.map +1 -0
  33. package/dist/orchestrator/tool-registry.d.ts +2 -0
  34. package/dist/orchestrator/tool-registry.d.ts.map +1 -1
  35. package/dist/orchestrator/tool-registry.js.map +1 -1
  36. package/dist/orchestrator/tools/index.d.ts +4 -1
  37. package/dist/orchestrator/tools/index.d.ts.map +1 -1
  38. package/dist/orchestrator/tools/index.js +7 -2
  39. package/dist/orchestrator/tools/index.js.map +1 -1
  40. package/dist/orchestrator/tools/refresh-som-markers.d.ts +12 -0
  41. package/dist/orchestrator/tools/refresh-som-markers.d.ts.map +1 -0
  42. package/dist/orchestrator/tools/refresh-som-markers.js +64 -0
  43. package/dist/orchestrator/tools/refresh-som-markers.js.map +1 -0
  44. package/dist/orchestrator/tools/view-previous-screenshot.d.ts +15 -0
  45. package/dist/orchestrator/tools/view-previous-screenshot.d.ts.map +1 -0
  46. package/dist/orchestrator/tools/view-previous-screenshot.js +92 -0
  47. package/dist/orchestrator/tools/view-previous-screenshot.js.map +1 -0
  48. package/dist/orchestrator/types.d.ts +23 -1
  49. package/dist/orchestrator/types.d.ts.map +1 -1
  50. package/dist/orchestrator/types.js +11 -1
  51. package/dist/orchestrator/types.js.map +1 -1
  52. package/dist/scenario-service.d.ts +5 -0
  53. package/dist/scenario-service.d.ts.map +1 -1
  54. package/dist/scenario-service.js +17 -0
  55. package/dist/scenario-service.js.map +1 -1
  56. package/dist/scenario-worker-class.d.ts +4 -0
  57. package/dist/scenario-worker-class.d.ts.map +1 -1
  58. package/dist/scenario-worker-class.js +18 -3
  59. package/dist/scenario-worker-class.js.map +1 -1
  60. package/dist/testing/agent-tester.d.ts +35 -0
  61. package/dist/testing/agent-tester.d.ts.map +1 -0
  62. package/dist/testing/agent-tester.js +84 -0
  63. package/dist/testing/agent-tester.js.map +1 -0
  64. package/dist/testing/ref-translator-tester.d.ts +44 -0
  65. package/dist/testing/ref-translator-tester.d.ts.map +1 -0
  66. package/dist/testing/ref-translator-tester.js +104 -0
  67. package/dist/testing/ref-translator-tester.js.map +1 -0
  68. package/dist/utils/hierarchical-selector.d.ts +47 -0
  69. package/dist/utils/hierarchical-selector.d.ts.map +1 -0
  70. package/dist/utils/hierarchical-selector.js +212 -0
  71. package/dist/utils/hierarchical-selector.js.map +1 -0
  72. package/dist/utils/page-info-retry.d.ts +14 -0
  73. package/dist/utils/page-info-retry.d.ts.map +1 -0
  74. package/dist/utils/page-info-retry.js +60 -0
  75. package/dist/utils/page-info-retry.js.map +1 -0
  76. package/dist/utils/page-info-utils.d.ts +1 -0
  77. package/dist/utils/page-info-utils.d.ts.map +1 -1
  78. package/dist/utils/page-info-utils.js +46 -18
  79. package/dist/utils/page-info-utils.js.map +1 -1
  80. package/dist/utils/ref-attacher.d.ts +21 -0
  81. package/dist/utils/ref-attacher.d.ts.map +1 -0
  82. package/dist/utils/ref-attacher.js +149 -0
  83. package/dist/utils/ref-attacher.js.map +1 -0
  84. package/dist/utils/ref-translator.d.ts +49 -0
  85. package/dist/utils/ref-translator.d.ts.map +1 -0
  86. package/dist/utils/ref-translator.js +276 -0
  87. package/dist/utils/ref-translator.js.map +1 -0
  88. package/package.json +6 -1
  89. package/RELEASE_0.0.26.md +0 -165
  90. package/RELEASE_0.0.27.md +0 -236
  91. package/RELEASE_0.0.28.md +0 -286
  92. package/plandocs/BEFORE_AFTER_VERIFICATION.md +0 -148
  93. package/plandocs/COORDINATE_MODE_DIAGNOSIS.md +0 -144
  94. package/plandocs/CREDIT_CALLBACK_ARCHITECTURE.md +0 -253
  95. package/plandocs/HUMAN_LIKE_IMPROVEMENTS.md +0 -642
  96. package/plandocs/IMPLEMENTATION_STATUS.md +0 -108
  97. package/plandocs/INTEGRATION_COMPLETE.md +0 -322
  98. package/plandocs/MULTI_AGENT_ARCHITECTURE_REVIEW.md +0 -844
  99. package/plandocs/ORCHESTRATOR_MVP_SUMMARY.md +0 -539
  100. package/plandocs/PHASE1_ABSTRACTION_COMPLETE.md +0 -241
  101. package/plandocs/PHASE1_FINAL_STATUS.md +0 -210
  102. package/plandocs/PHASE_1_COMPLETE.md +0 -165
  103. package/plandocs/PHASE_1_SUMMARY.md +0 -184
  104. package/plandocs/PLANNING_SESSION_SUMMARY.md +0 -372
  105. package/plandocs/PROMPT_OPTIMIZATION_ANALYSIS.md +0 -120
  106. package/plandocs/PROMPT_SANITY_CHECK.md +0 -120
  107. package/plandocs/SCRIPT_CLEANUP_FEATURE.md +0 -201
  108. package/plandocs/SCRIPT_GENERATION_ARCHITECTURE.md +0 -364
  109. package/plandocs/SELECTOR_IMPROVEMENTS.md +0 -139
  110. package/plandocs/SESSION_SUMMARY_v0.0.33.md +0 -151
  111. package/plandocs/TROUBLESHOOTING_SESSION.md +0 -72
  112. package/plandocs/VISION_DIAGNOSTICS_IMPROVEMENTS.md +0 -336
  113. package/plandocs/VISUAL_AGENT_EVOLUTION_PLAN.md +0 -396
  114. package/plandocs/WHATS_NEW_v0.0.33.md +0 -183
  115. package/src/auth-config.ts +0 -84
  116. package/src/credit-usage-service.ts +0 -188
  117. package/src/env-loader.ts +0 -103
  118. package/src/execution-service.ts +0 -1413
  119. package/src/file-handler.ts +0 -104
  120. package/src/index.ts +0 -422
  121. package/src/llm-facade.ts +0 -821
  122. package/src/llm-provider.ts +0 -53
  123. package/src/model-constants.ts +0 -35
  124. package/src/orchestrator/index.ts +0 -34
  125. package/src/orchestrator/orchestrator-agent.ts +0 -862
  126. package/src/orchestrator/orchestrator-agent.ts.backup +0 -1386
  127. package/src/orchestrator/orchestrator-prompts.ts +0 -474
  128. package/src/orchestrator/tool-registry.ts +0 -182
  129. package/src/orchestrator/tools/check-page-ready.ts +0 -75
  130. package/src/orchestrator/tools/extract-data.ts +0 -92
  131. package/src/orchestrator/tools/index.ts +0 -12
  132. package/src/orchestrator/tools/inspect-page.ts +0 -42
  133. package/src/orchestrator/tools/recall-history.ts +0 -72
  134. package/src/orchestrator/tools/take-screenshot.ts +0 -128
  135. package/src/orchestrator/tools/verify-action-result.ts +0 -159
  136. package/src/orchestrator/types.ts +0 -248
  137. package/src/playwright-mcp-service.ts +0 -224
  138. package/src/progress-reporter.ts +0 -144
  139. package/src/prompts.ts +0 -842
  140. package/src/providers/backend-proxy-llm-provider.ts +0 -91
  141. package/src/providers/local-llm-provider.ts +0 -38
  142. package/src/scenario-service.ts +0 -232
  143. package/src/scenario-worker-class.ts +0 -1089
  144. package/src/script-utils.ts +0 -203
  145. package/src/types.ts +0 -239
  146. package/src/utils/browser-utils.ts +0 -348
  147. package/src/utils/coordinate-converter.ts +0 -162
  148. package/src/utils/page-info-utils.ts +0 -250
  149. package/testchimp-runner-core-0.0.33.tgz +0 -0
  150. package/tsconfig.json +0 -19
@@ -1,348 +0,0 @@
1
- import * as path from 'path';
2
- import * as fs from 'fs';
3
- import * as os from 'os';
4
- const esbuild = require('esbuild');
5
- const { build } = esbuild;
6
-
7
- /**
8
- * Initialize browser with Playwright configuration
9
- * @param playwrightConfig - JavaScript config file content (playwright.config.js)
10
- * @param headless - Override headless mode (optional)
11
- * @param playwrightConfigFilePath - Path to playwright config file (optional)
12
- * @param logger - Optional logger callback for capturing logs
13
- * @returns Browser, context, and page instances
14
- */
15
- export async function initializeBrowser(
16
- playwrightConfigContent?: string,
17
- headless?: boolean,
18
- playwrightConfigFilePath?: string,
19
- logger?: (message: string, level?: 'log' | 'error' | 'warn') => void
20
- ): Promise<{ browser: any; context: any; page: any }> {
21
- const log = (message: string, level: 'log' | 'error' | 'warn' = 'log') => {
22
- if (logger) {
23
- logger(message, level);
24
- }
25
- // No console fallback - logs are routed to consumer
26
- };
27
-
28
- log('Initializing browser with Playwright');
29
-
30
- // Import Playwright modules dynamically
31
- const playwright = await import('playwright');
32
- const { chromium, firefox, webkit } = playwright;
33
-
34
- let contextOptions: any = {};
35
-
36
- // Use Playwright config content if provided
37
- if (playwrightConfigContent) {
38
- log('Using provided Playwright config content');
39
-
40
- try {
41
- // Transpile the config content in-memory and evaluate it
42
- log(`Transpiling config content (${playwrightConfigContent.length} characters)`);
43
-
44
- const result = await build({
45
- stdin: {
46
- contents: playwrightConfigContent,
47
- resolveDir: String(process.cwd()),
48
- },
49
- bundle: true,
50
- platform: 'node',
51
- format: 'cjs',
52
- sourcemap: false,
53
- target: 'node18',
54
- logLevel: 'silent',
55
- write: false, // Don't write to file, get the result in memory
56
- external: [
57
- '@playwright/test',
58
- 'playwright',
59
- 'playwright-core'
60
- ]
61
- });
62
-
63
- if (!result.outputFiles || result.outputFiles.length === 0) {
64
- throw new Error('esbuild failed to generate output');
65
- }
66
-
67
- const transpiledCode = result.outputFiles[0].text;
68
- log(`Transpilation complete. Generated ${transpiledCode.length} characters of code`);
69
-
70
- // Evaluate the transpiled code in a safe context
71
- const loadedConfig = eval(transpiledCode);
72
- log(`Loaded config object: ${JSON.stringify(loadedConfig)}`);
73
- log(`Config type: ${typeof loadedConfig}`);
74
- log(`Config keys: ${loadedConfig ? Object.keys(loadedConfig).join(', ') : 'null/undefined'}`);
75
-
76
- // Get the actual config from the default export (ES module transpiled to CommonJS)
77
- const actualConfig = loadedConfig.default || loadedConfig;
78
-
79
- if (actualConfig && typeof actualConfig === 'object') {
80
- log('Successfully loaded Playwright config from content');
81
- log(`Config keys: ${Object.keys(actualConfig).join(', ')}`);
82
-
83
- // Extract context options from the config
84
- if (actualConfig.use && actualConfig.use.contextOptions) {
85
- contextOptions = { ...contextOptions, ...actualConfig.use.contextOptions };
86
- log('Applied context options from config');
87
- }
88
-
89
- // Apply other config settings
90
- if (actualConfig.use && actualConfig.use.headless !== undefined) {
91
- // Override headless mode if specified in config and not explicitly overridden
92
- if (headless === undefined) {
93
- headless = actualConfig.use.headless;
94
- log(`Using headless mode from config: ${headless}`);
95
- }
96
- }
97
-
98
- // Apply timeout settings
99
- if (actualConfig.use && actualConfig.use.actionTimeout) {
100
- log(`Using action timeout from config: ${actualConfig.use.actionTimeout}ms`);
101
- }
102
-
103
- // Apply viewport settings
104
- if (actualConfig.use && actualConfig.use.viewport) {
105
- contextOptions.viewport = actualConfig.use.viewport;
106
- log(`Using viewport from config: ${JSON.stringify(actualConfig.use.viewport)}`);
107
- }
108
-
109
- // Apply user agent
110
- if (actualConfig.use && actualConfig.use.userAgent) {
111
- contextOptions.userAgent = actualConfig.use.userAgent;
112
- log(`Using user agent from config: ${actualConfig.use.userAgent}`);
113
- }
114
-
115
- // Apply other context options
116
- if (actualConfig.use && actualConfig.use.extraHTTPHeaders) {
117
- contextOptions.extraHTTPHeaders = actualConfig.use.extraHTTPHeaders;
118
- log(`Using extra HTTP headers from config`);
119
- }
120
-
121
- if (actualConfig.use && actualConfig.use.locale) {
122
- contextOptions.locale = actualConfig.use.locale;
123
- log(`Using locale from config: ${actualConfig.use.locale}`);
124
- }
125
-
126
- if (actualConfig.use && actualConfig.use.timezoneId) {
127
- contextOptions.timezoneId = actualConfig.use.timezoneId;
128
- log(`Using timezone from config: ${actualConfig.use.timezoneId}`);
129
- }
130
-
131
- if (actualConfig.use && actualConfig.use.geolocation) {
132
- contextOptions.geolocation = actualConfig.use.geolocation;
133
- log(`Using geolocation from config: ${JSON.stringify(actualConfig.use.geolocation)}`);
134
- }
135
-
136
- if (actualConfig.use && actualConfig.use.permissions) {
137
- contextOptions.permissions = actualConfig.use.permissions;
138
- log(`Using permissions from config: ${JSON.stringify(actualConfig.use.permissions)}`);
139
- }
140
-
141
- if (actualConfig.use && actualConfig.use.colorScheme) {
142
- contextOptions.colorScheme = actualConfig.use.colorScheme;
143
- log(`Using color scheme from config: ${actualConfig.use.colorScheme}`);
144
- }
145
-
146
- if (actualConfig.use && actualConfig.use.reducedMotion) {
147
- contextOptions.reducedMotion = actualConfig.use.reducedMotion;
148
- log(`Using reduced motion from config: ${actualConfig.use.reducedMotion}`);
149
- }
150
-
151
- if (actualConfig.use && actualConfig.use.forcedColors) {
152
- contextOptions.forcedColors = actualConfig.use.forcedColors;
153
- log(`Using forced colors from config: ${actualConfig.use.forcedColors}`);
154
- }
155
-
156
- if (actualConfig.use && actualConfig.use.acceptDownloads) {
157
- contextOptions.acceptDownloads = actualConfig.use.acceptDownloads;
158
- log(`Using accept downloads from config: ${actualConfig.use.acceptDownloads}`);
159
- }
160
-
161
- if (actualConfig.use && actualConfig.use.bypassCSP) {
162
- contextOptions.bypassCSP = actualConfig.use.bypassCSP;
163
- log(`Using bypass CSP from config: ${actualConfig.use.bypassCSP}`);
164
- }
165
-
166
- if (actualConfig.use && actualConfig.use.javaScriptEnabled) {
167
- contextOptions.javaScriptEnabled = actualConfig.use.javaScriptEnabled;
168
- log(`Using JavaScript enabled from config: ${actualConfig.use.javaScriptEnabled}`);
169
- }
170
-
171
- if (actualConfig.use && actualConfig.use.ignoreHTTPSErrors) {
172
- contextOptions.ignoreHTTPSErrors = actualConfig.use.ignoreHTTPSErrors;
173
- log(`Using ignore HTTPS errors from config: ${actualConfig.use.ignoreHTTPSErrors}`);
174
- }
175
-
176
- log(`Final context options: ${JSON.stringify(contextOptions, null, 2)}`);
177
- } else {
178
- log('Config loaded but no valid configuration found');
179
- }
180
- } catch (error) {
181
- log(`Error transpiling config content: ${error}`, 'error');
182
- log('Falling back to default configuration');
183
- }
184
- } else if (playwrightConfigFilePath) {
185
- // Fallback to file path if no content provided (for backward compatibility)
186
- log('No config content provided, falling back to file path');
187
- // Resolve the path - it might be relative or absolute
188
- const resolvedPath = path.isAbsolute(String(playwrightConfigFilePath))
189
- ? String(playwrightConfigFilePath)
190
- : path.resolve(String(process.cwd()), String(playwrightConfigFilePath));
191
-
192
- log(`Looking for Playwright config at: ${resolvedPath}`);
193
- log(`File exists: ${fs.existsSync(String(resolvedPath))}`);
194
-
195
- if (fs.existsSync(String(resolvedPath))) {
196
- log(`Loading Playwright config from: ${resolvedPath}`);
197
-
198
- try {
199
- // Transpile the config in-memory and evaluate it
200
- log(`Transpiling config in-memory from: ${resolvedPath}`);
201
-
202
- const result = await build({
203
- entryPoints: [String(resolvedPath)],
204
- bundle: true,
205
- platform: 'node',
206
- format: 'cjs',
207
- sourcemap: false,
208
- target: 'node18',
209
- logLevel: 'silent',
210
- write: false, // Don't write to file, get the result in memory
211
- external: [
212
- '@playwright/test',
213
- 'playwright',
214
- 'playwright-core'
215
- ]
216
- });
217
-
218
- if (!result.outputFiles || result.outputFiles.length === 0) {
219
- throw new Error('esbuild failed to generate output');
220
- }
221
-
222
- const transpiledCode = result.outputFiles[0].text;
223
- log(`Transpilation complete. Generated ${transpiledCode.length} characters of code`);
224
-
225
- // Evaluate the transpiled code in a safe context
226
- const loadedConfig = eval(transpiledCode);
227
- log(`Loaded config object: ${JSON.stringify(loadedConfig)}`);
228
- log(`Config type: ${typeof loadedConfig}`);
229
- log(`Config keys: ${loadedConfig ? Object.keys(loadedConfig).join(', ') : 'null/undefined'}`);
230
-
231
- // Get the actual config from the default export (ES module transpiled to CommonJS)
232
- const actualConfig = loadedConfig.default || loadedConfig;
233
- log(`Actual config: ${JSON.stringify(actualConfig)}`);
234
- log(`Actual config keys: ${actualConfig ? Object.keys(actualConfig).join(', ') : 'null/undefined'}`);
235
-
236
- if (!actualConfig) {
237
- log('Config import did not return a valid config; using defaults');
238
- } else {
239
- // Apply global use options
240
- if (actualConfig.use) {
241
- contextOptions = { ...actualConfig.use };
242
- log('Applied context options from Playwright config:', contextOptions);
243
- } else {
244
- log('No use property found in config');
245
- }
246
- // Apply first project overrides if present
247
- if (Array.isArray(actualConfig.projects) && actualConfig.projects.length > 0) {
248
- const firstProject = actualConfig.projects[0];
249
- if (firstProject && firstProject.use) {
250
- contextOptions = { ...contextOptions, ...firstProject.use };
251
- log('Applied project-specific options:', firstProject.use);
252
- }
253
- } else {
254
- log('No projects found in config');
255
- }
256
- }
257
-
258
- // No cleanup needed - we used in-memory transpilation
259
-
260
- } catch (error) {
261
- log(`Failed to load Playwright config via esbuild/import: ${error}`);
262
- log('Using default browser settings');
263
- }
264
- } else {
265
- log(`Playwright config file not found at: ${resolvedPath}`);
266
- log('Using default browser settings');
267
- }
268
- }
269
-
270
- // Use chromium as default browser
271
- const browser = await chromium.launch({
272
- headless: headless !== undefined ? headless : false
273
- });
274
-
275
- // Create context with config options or defaults
276
- const context = await browser.newContext(contextOptions);
277
- const page = await context.newPage();
278
-
279
- // Set default timeout to 5 seconds (unless overridden by playwright config)
280
- if (!contextOptions.timeout) {
281
- context.setDefaultTimeout(5000);
282
- page.setDefaultTimeout(5000);
283
- }
284
-
285
- return { browser, context, page };
286
- }
287
-
288
- /**
289
- * Capture an optimized screenshot for vision API calls
290
- * - Sets temporary viewport to reduce image size
291
- * - Uses JPEG compression
292
- * - Returns base64 data URL
293
- *
294
- * @param page - Playwright page instance
295
- * @param options - Screenshot options
296
- * @param log - Optional logger callback
297
- * @returns Data URL string (data:image/jpeg;base64,...)
298
- */
299
- export async function captureOptimizedScreenshot(
300
- page: any,
301
- options: {
302
- quality?: number; // JPEG quality (0-100), default 60 (optimal for vision API)
303
- width?: number; // Viewport width, default 800
304
- height?: number; // Viewport height, default 800
305
- timeout?: number; // Screenshot timeout in ms, default 10000
306
- } = {},
307
- log?: (message: string) => void
308
- ): Promise<string> {
309
- const {
310
- quality = 60, // Sweet spot: 50% smaller than quality 85, minimal visual loss
311
- width = 800,
312
- height = 800,
313
- timeout = 10000
314
- } = options;
315
-
316
- // Save current viewport
317
- const currentViewport = page.viewportSize();
318
-
319
- // Set smaller viewport to reduce screenshot size
320
- await page.setViewportSize({ width, height });
321
-
322
- try {
323
- const screenshotBuffer = await page.screenshot({
324
- type: 'jpeg', // JPEG for smaller file size
325
- quality, // Compression quality
326
- fullPage: false, // Viewport only
327
- timeout // Timeout for slow pages
328
- });
329
-
330
- // Convert Buffer to base64 string explicitly
331
- const screenshotBase64 = screenshotBuffer.toString('base64');
332
-
333
- if (log) {
334
- const sizeKB = Math.round(screenshotBase64.length * 0.75 / 1024);
335
- log(` 📏 Screenshot size: ~${sizeKB}KB (base64)`);
336
- }
337
-
338
- // Construct data URL for vision API
339
- const imageDataUrl = `data:image/jpeg;base64,${screenshotBase64}`;
340
-
341
- return imageDataUrl;
342
- } finally {
343
- // Always restore original viewport, even if screenshot fails
344
- if (currentViewport) {
345
- await page.setViewportSize(currentViewport);
346
- }
347
- }
348
- }
@@ -1,162 +0,0 @@
1
- /**
2
- * Coordinate Converter Utility
3
- * Converts percentage-based coordinates to pixel coordinates and generates Playwright commands
4
- */
5
-
6
- import { CoordinateAction } from '../orchestrator/types';
7
-
8
- export class CoordinateConverter {
9
-
10
- /**
11
- * Convert percentage coordinates to actual pixel coordinates
12
- */
13
- static percentToPixels(
14
- xPercent: number,
15
- yPercent: number,
16
- viewportWidth: number,
17
- viewportHeight: number
18
- ): { x: number; y: number } {
19
- return {
20
- x: Math.round((xPercent / 100) * viewportWidth),
21
- y: Math.round((yPercent / 100) * viewportHeight)
22
- };
23
- }
24
-
25
- /**
26
- * Get viewport dimensions from page
27
- */
28
- static async getViewportSize(page: any): Promise<{ width: number; height: number }> {
29
- return await page.evaluate((): { width: number; height: number } => {
30
- const win = (globalThis as any).window;
31
- return {
32
- width: win.innerWidth as number,
33
- height: win.innerHeight as number
34
- };
35
- });
36
- }
37
-
38
- /**
39
- * Convert coordinate action with percentages to Playwright commands
40
- * Returns array of command strings
41
- */
42
- static async generateCommands(
43
- action: CoordinateAction,
44
- page: any
45
- ): Promise<string[]> {
46
- const viewport = await this.getViewportSize(page);
47
- const { x, y } = this.percentToPixels(action.xPercent, action.yPercent, viewport.width, viewport.height);
48
-
49
- const commands: string[] = [];
50
-
51
- switch (action.action) {
52
- case 'click':
53
- commands.push(`await page.mouse.click(${x}, ${y});`);
54
- break;
55
-
56
- case 'doubleClick':
57
- commands.push(`await page.mouse.dblclick(${x}, ${y});`);
58
- break;
59
-
60
- case 'rightClick':
61
- commands.push(`await page.mouse.click(${x}, ${y}, { button: 'right' });`);
62
- break;
63
-
64
- case 'hover':
65
- commands.push(`await page.mouse.move(${x}, ${y});`);
66
- break;
67
-
68
- case 'drag':
69
- if (action.toXPercent === undefined || action.toYPercent === undefined) {
70
- throw new Error('Drag action requires toXPercent and toYPercent');
71
- }
72
- const to = this.percentToPixels(action.toXPercent, action.toYPercent, viewport.width, viewport.height);
73
- commands.push(`await page.mouse.move(${x}, ${y});`);
74
- commands.push(`await page.mouse.down();`);
75
- commands.push(`await page.mouse.move(${to.x}, ${to.y});`);
76
- commands.push(`await page.mouse.up();`);
77
- break;
78
-
79
- case 'fill':
80
- if (!action.value) {
81
- throw new Error('Fill action requires value');
82
- }
83
- // Click to focus, wait briefly, then type
84
- commands.push(`await page.mouse.click(${x}, ${y});`);
85
- commands.push(`await page.waitForTimeout(100);`);
86
- commands.push(`await page.keyboard.type(${JSON.stringify(action.value)});`);
87
- break;
88
-
89
- case 'scroll':
90
- const scrollAmount = action.scrollAmount || 100;
91
- // Move to position, then scroll
92
- commands.push(`await page.mouse.move(${x}, ${y});`);
93
- commands.push(`await page.mouse.wheel(0, ${scrollAmount});`);
94
- break;
95
-
96
- default:
97
- throw new Error(`Unknown coordinate action: ${action.action}`);
98
- }
99
-
100
- return commands;
101
- }
102
-
103
- /**
104
- * Execute coordinate action directly on page
105
- * Used during agent execution (converts and runs immediately)
106
- */
107
- static async executeAction(
108
- action: CoordinateAction,
109
- page: any
110
- ): Promise<void> {
111
- const viewport = await this.getViewportSize(page);
112
- const { x, y } = this.percentToPixels(action.xPercent, action.yPercent, viewport.width, viewport.height);
113
-
114
- switch (action.action) {
115
- case 'click':
116
- await page.mouse.click(x, y);
117
- break;
118
-
119
- case 'doubleClick':
120
- await page.mouse.dblclick(x, y);
121
- break;
122
-
123
- case 'rightClick':
124
- await page.mouse.click(x, y, { button: 'right' });
125
- break;
126
-
127
- case 'hover':
128
- await page.mouse.move(x, y);
129
- break;
130
-
131
- case 'drag':
132
- if (action.toXPercent === undefined || action.toYPercent === undefined) {
133
- throw new Error('Drag requires toXPercent and toYPercent');
134
- }
135
- const to = this.percentToPixels(action.toXPercent, action.toYPercent, viewport.width, viewport.height);
136
- await page.mouse.move(x, y);
137
- await page.mouse.down();
138
- await page.mouse.move(to.x, to.y);
139
- await page.mouse.up();
140
- break;
141
-
142
- case 'fill':
143
- if (!action.value) {
144
- throw new Error('Fill requires value');
145
- }
146
- await page.mouse.click(x, y);
147
- await page.waitForTimeout(100);
148
- await page.keyboard.type(action.value);
149
- break;
150
-
151
- case 'scroll':
152
- const scrollAmount = action.scrollAmount || 100;
153
- await page.mouse.move(x, y);
154
- await page.mouse.wheel(0, scrollAmount);
155
- break;
156
-
157
- default:
158
- throw new Error(`Unknown coordinate action: ${action.action}`);
159
- }
160
- }
161
- }
162
-