testchimp-runner-core 0.0.21 → 0.0.23
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/VISION_DIAGNOSTICS_IMPROVEMENTS.md +336 -0
- package/dist/credit-usage-service.d.ts +9 -0
- package/dist/credit-usage-service.d.ts.map +1 -1
- package/dist/credit-usage-service.js +20 -5
- package/dist/credit-usage-service.js.map +1 -1
- package/dist/execution-service.d.ts +7 -2
- package/dist/execution-service.d.ts.map +1 -1
- package/dist/execution-service.js +91 -36
- package/dist/execution-service.js.map +1 -1
- package/dist/index.d.ts +30 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +91 -26
- package/dist/index.js.map +1 -1
- package/dist/llm-facade.d.ts +64 -8
- package/dist/llm-facade.d.ts.map +1 -1
- package/dist/llm-facade.js +361 -109
- package/dist/llm-facade.js.map +1 -1
- package/dist/llm-provider.d.ts +39 -0
- package/dist/llm-provider.d.ts.map +1 -0
- package/dist/llm-provider.js +7 -0
- package/dist/llm-provider.js.map +1 -0
- package/dist/model-constants.d.ts +21 -0
- package/dist/model-constants.d.ts.map +1 -0
- package/dist/model-constants.js +24 -0
- package/dist/model-constants.js.map +1 -0
- package/dist/orchestrator/index.d.ts +8 -0
- package/dist/orchestrator/index.d.ts.map +1 -0
- package/dist/orchestrator/index.js +23 -0
- package/dist/orchestrator/index.js.map +1 -0
- package/dist/orchestrator/orchestrator-agent.d.ts +66 -0
- package/dist/orchestrator/orchestrator-agent.d.ts.map +1 -0
- package/dist/orchestrator/orchestrator-agent.js +855 -0
- package/dist/orchestrator/orchestrator-agent.js.map +1 -0
- package/dist/orchestrator/tool-registry.d.ts +74 -0
- package/dist/orchestrator/tool-registry.d.ts.map +1 -0
- package/dist/orchestrator/tool-registry.js +131 -0
- package/dist/orchestrator/tool-registry.js.map +1 -0
- package/dist/orchestrator/tools/check-page-ready.d.ts +13 -0
- package/dist/orchestrator/tools/check-page-ready.d.ts.map +1 -0
- package/dist/orchestrator/tools/check-page-ready.js +72 -0
- package/dist/orchestrator/tools/check-page-ready.js.map +1 -0
- package/dist/orchestrator/tools/extract-data.d.ts +13 -0
- package/dist/orchestrator/tools/extract-data.d.ts.map +1 -0
- package/dist/orchestrator/tools/extract-data.js +84 -0
- package/dist/orchestrator/tools/extract-data.js.map +1 -0
- package/dist/orchestrator/tools/index.d.ts +10 -0
- package/dist/orchestrator/tools/index.d.ts.map +1 -0
- package/dist/orchestrator/tools/index.js +18 -0
- package/dist/orchestrator/tools/index.js.map +1 -0
- package/dist/orchestrator/tools/inspect-page.d.ts +13 -0
- package/dist/orchestrator/tools/inspect-page.d.ts.map +1 -0
- package/dist/orchestrator/tools/inspect-page.js +39 -0
- package/dist/orchestrator/tools/inspect-page.js.map +1 -0
- package/dist/orchestrator/tools/recall-history.d.ts +13 -0
- package/dist/orchestrator/tools/recall-history.d.ts.map +1 -0
- package/dist/orchestrator/tools/recall-history.js +64 -0
- package/dist/orchestrator/tools/recall-history.js.map +1 -0
- package/dist/orchestrator/tools/take-screenshot.d.ts +15 -0
- package/dist/orchestrator/tools/take-screenshot.d.ts.map +1 -0
- package/dist/orchestrator/tools/take-screenshot.js +112 -0
- package/dist/orchestrator/tools/take-screenshot.js.map +1 -0
- package/dist/orchestrator/types.d.ts +133 -0
- package/dist/orchestrator/types.d.ts.map +1 -0
- package/dist/orchestrator/types.js +28 -0
- package/dist/orchestrator/types.js.map +1 -0
- package/dist/playwright-mcp-service.d.ts +9 -0
- package/dist/playwright-mcp-service.d.ts.map +1 -1
- package/dist/playwright-mcp-service.js +20 -5
- package/dist/playwright-mcp-service.js.map +1 -1
- package/dist/progress-reporter.d.ts +97 -0
- package/dist/progress-reporter.d.ts.map +1 -0
- package/dist/progress-reporter.js +18 -0
- package/dist/progress-reporter.js.map +1 -0
- package/dist/prompts.d.ts +24 -0
- package/dist/prompts.d.ts.map +1 -1
- package/dist/prompts.js +593 -68
- package/dist/prompts.js.map +1 -1
- package/dist/providers/backend-proxy-llm-provider.d.ts +25 -0
- package/dist/providers/backend-proxy-llm-provider.d.ts.map +1 -0
- package/dist/providers/backend-proxy-llm-provider.js +76 -0
- package/dist/providers/backend-proxy-llm-provider.js.map +1 -0
- package/dist/providers/local-llm-provider.d.ts +21 -0
- package/dist/providers/local-llm-provider.d.ts.map +1 -0
- package/dist/providers/local-llm-provider.js +35 -0
- package/dist/providers/local-llm-provider.js.map +1 -0
- package/dist/scenario-service.d.ts +27 -1
- package/dist/scenario-service.d.ts.map +1 -1
- package/dist/scenario-service.js +48 -12
- package/dist/scenario-service.js.map +1 -1
- package/dist/scenario-worker-class.d.ts +39 -2
- package/dist/scenario-worker-class.d.ts.map +1 -1
- package/dist/scenario-worker-class.js +614 -86
- package/dist/scenario-worker-class.js.map +1 -1
- package/dist/script-utils.d.ts +2 -0
- package/dist/script-utils.d.ts.map +1 -1
- package/dist/script-utils.js +44 -4
- package/dist/script-utils.js.map +1 -1
- package/dist/types.d.ts +11 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/utils/browser-utils.d.ts +20 -1
- package/dist/utils/browser-utils.d.ts.map +1 -1
- package/dist/utils/browser-utils.js +102 -51
- package/dist/utils/browser-utils.js.map +1 -1
- package/dist/utils/page-info-utils.d.ts +23 -4
- package/dist/utils/page-info-utils.d.ts.map +1 -1
- package/dist/utils/page-info-utils.js +174 -43
- package/dist/utils/page-info-utils.js.map +1 -1
- package/package.json +1 -2
- package/plandocs/HUMAN_LIKE_IMPROVEMENTS.md +642 -0
- package/plandocs/MULTI_AGENT_ARCHITECTURE_REVIEW.md +844 -0
- package/plandocs/ORCHESTRATOR_MVP_SUMMARY.md +539 -0
- package/plandocs/PHASE1_ABSTRACTION_COMPLETE.md +241 -0
- package/plandocs/PHASE1_FINAL_STATUS.md +210 -0
- package/plandocs/PLANNING_SESSION_SUMMARY.md +372 -0
- package/plandocs/SCRIPT_CLEANUP_FEATURE.md +201 -0
- package/plandocs/SCRIPT_GENERATION_ARCHITECTURE.md +364 -0
- package/plandocs/SELECTOR_IMPROVEMENTS.md +139 -0
- package/src/credit-usage-service.ts +23 -5
- package/src/execution-service.ts +152 -42
- package/src/index.ts +169 -26
- package/src/llm-facade.ts +500 -126
- package/src/llm-provider.ts +43 -0
- package/src/model-constants.ts +23 -0
- package/src/orchestrator/index.ts +33 -0
- package/src/orchestrator/orchestrator-agent.ts +1037 -0
- package/src/orchestrator/tool-registry.ts +182 -0
- package/src/orchestrator/tools/check-page-ready.ts +75 -0
- package/src/orchestrator/tools/extract-data.ts +92 -0
- package/src/orchestrator/tools/index.ts +11 -0
- package/src/orchestrator/tools/inspect-page.ts +42 -0
- package/src/orchestrator/tools/recall-history.ts +72 -0
- package/src/orchestrator/tools/take-screenshot.ts +128 -0
- package/src/orchestrator/types.ts +200 -0
- package/src/playwright-mcp-service.ts +23 -5
- package/src/progress-reporter.ts +109 -0
- package/src/prompts.ts +606 -69
- package/src/providers/backend-proxy-llm-provider.ts +91 -0
- package/src/providers/local-llm-provider.ts +38 -0
- package/src/scenario-service.ts +83 -13
- package/src/scenario-worker-class.ts +740 -72
- package/src/script-utils.ts +50 -5
- package/src/types.ts +13 -1
- package/src/utils/browser-utils.ts +123 -51
- package/src/utils/page-info-utils.ts +210 -53
- package/testchimp-runner-core-0.0.22.tgz +0 -0
package/src/script-utils.ts
CHANGED
|
@@ -115,7 +115,14 @@ export function addTestChimpComment(script: string, repairAdvice?: string, hasht
|
|
|
115
115
|
*/
|
|
116
116
|
export function generateTestScript(
|
|
117
117
|
testName: string,
|
|
118
|
-
steps: Array<{
|
|
118
|
+
steps: Array<{
|
|
119
|
+
stepNumber: number;
|
|
120
|
+
description: string;
|
|
121
|
+
playwrightCommand?: string;
|
|
122
|
+
playwrightCommands?: string[];
|
|
123
|
+
success?: boolean;
|
|
124
|
+
error?: string;
|
|
125
|
+
}>,
|
|
119
126
|
repairAdvice?: string,
|
|
120
127
|
hashtags?: string[]
|
|
121
128
|
): string {
|
|
@@ -134,10 +141,48 @@ export function generateTestScript(
|
|
|
134
141
|
|
|
135
142
|
// Add steps
|
|
136
143
|
for (const step of steps) {
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
144
|
+
// Check if step was skipped
|
|
145
|
+
const isSkipped = step.error?.includes('Skipped due to') ||
|
|
146
|
+
(step.success === false && (!step.playwrightCommand && (!step.playwrightCommands || step.playwrightCommands.length === 0)));
|
|
147
|
+
|
|
148
|
+
if (isSkipped) {
|
|
149
|
+
// Step was skipped due to previous failures
|
|
150
|
+
scriptLines.push(` // ${step.description} [SKIPPED]`);
|
|
151
|
+
} else if (step.success === false) {
|
|
152
|
+
// Step failed - only show command if this step actually attempted any commands
|
|
153
|
+
if (step.playwrightCommands && step.playwrightCommands.length > 0) {
|
|
154
|
+
// Failed after attempting commands - show them
|
|
155
|
+
scriptLines.push(` // ${step.description} [FAILED]`);
|
|
156
|
+
step.playwrightCommands.forEach((cmd: string) => {
|
|
157
|
+
scriptLines.push(` // Attempted: ${cmd}`);
|
|
158
|
+
});
|
|
159
|
+
} else if (step.playwrightCommand) {
|
|
160
|
+
// Single command attempted (backward compatibility)
|
|
161
|
+
scriptLines.push(` // ${step.description} [FAILED] - ${step.playwrightCommand}`);
|
|
162
|
+
} else {
|
|
163
|
+
// Failed without attempting any commands
|
|
164
|
+
scriptLines.push(` // ${step.description} [FAILED]`);
|
|
165
|
+
}
|
|
166
|
+
} else {
|
|
167
|
+
// Step succeeded or in progress
|
|
168
|
+
// Only add comment if step has commands to show
|
|
169
|
+
const hasCommands = (step.playwrightCommands && step.playwrightCommands.length > 0) || step.playwrightCommand;
|
|
170
|
+
|
|
171
|
+
if (hasCommands) {
|
|
172
|
+
scriptLines.push(` // ${step.description}`);
|
|
173
|
+
|
|
174
|
+
// Handle multiple commands per step
|
|
175
|
+
if (step.playwrightCommands && step.playwrightCommands.length > 0) {
|
|
176
|
+
// Multiple commands - output all of them
|
|
177
|
+
step.playwrightCommands.forEach((cmd: string) => {
|
|
178
|
+
scriptLines.push(` ${cmd}`);
|
|
179
|
+
});
|
|
180
|
+
} else if (step.playwrightCommand) {
|
|
181
|
+
// Single command (backward compatibility)
|
|
182
|
+
scriptLines.push(` ${step.playwrightCommand}`);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
// If step has no commands, skip it entirely (work was done in previous step)
|
|
141
186
|
}
|
|
142
187
|
}
|
|
143
188
|
|
package/src/types.ts
CHANGED
|
@@ -99,13 +99,25 @@ export interface ScenarioResponse {
|
|
|
99
99
|
error?: string;
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
+
/**
|
|
103
|
+
* Individual sub-action within a step
|
|
104
|
+
*/
|
|
105
|
+
export interface SubAction {
|
|
106
|
+
command: string;
|
|
107
|
+
success: boolean;
|
|
108
|
+
error?: string;
|
|
109
|
+
retryCount: number;
|
|
110
|
+
}
|
|
111
|
+
|
|
102
112
|
/**
|
|
103
113
|
* Individual scenario step
|
|
104
114
|
*/
|
|
105
115
|
export interface ScenarioStep {
|
|
106
116
|
stepNumber: number;
|
|
107
117
|
description: string;
|
|
108
|
-
playwrightCommand?: string;
|
|
118
|
+
playwrightCommand?: string; // For backward compatibility - last successful command or aggregated command
|
|
119
|
+
playwrightCommands?: string[]; // Multiple commands for complex steps
|
|
120
|
+
subActions?: SubAction[]; // Detailed tracking of all sub-actions
|
|
109
121
|
success?: boolean;
|
|
110
122
|
error?: string;
|
|
111
123
|
retryCount?: number;
|
|
@@ -8,14 +8,24 @@ const { build } = esbuild;
|
|
|
8
8
|
* Initialize browser with Playwright configuration
|
|
9
9
|
* @param playwrightConfig - JavaScript config file content (playwright.config.js)
|
|
10
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
|
|
11
13
|
* @returns Browser, context, and page instances
|
|
12
14
|
*/
|
|
13
15
|
export async function initializeBrowser(
|
|
14
16
|
playwrightConfigContent?: string,
|
|
15
17
|
headless?: boolean,
|
|
16
|
-
playwrightConfigFilePath?: string
|
|
18
|
+
playwrightConfigFilePath?: string,
|
|
19
|
+
logger?: (message: string, level?: 'log' | 'error' | 'warn') => void
|
|
17
20
|
): Promise<{ browser: any; context: any; page: any }> {
|
|
18
|
-
|
|
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');
|
|
19
29
|
|
|
20
30
|
// Import Playwright modules dynamically
|
|
21
31
|
const playwright = await import('playwright');
|
|
@@ -25,11 +35,11 @@ export async function initializeBrowser(
|
|
|
25
35
|
|
|
26
36
|
// Use Playwright config content if provided
|
|
27
37
|
if (playwrightConfigContent) {
|
|
28
|
-
|
|
38
|
+
log('Using provided Playwright config content');
|
|
29
39
|
|
|
30
40
|
try {
|
|
31
41
|
// Transpile the config content in-memory and evaluate it
|
|
32
|
-
|
|
42
|
+
log(`Transpiling config content (${playwrightConfigContent.length} characters)`);
|
|
33
43
|
|
|
34
44
|
const result = await build({
|
|
35
45
|
stdin: {
|
|
@@ -55,25 +65,25 @@ export async function initializeBrowser(
|
|
|
55
65
|
}
|
|
56
66
|
|
|
57
67
|
const transpiledCode = result.outputFiles[0].text;
|
|
58
|
-
|
|
68
|
+
log(`Transpilation complete. Generated ${transpiledCode.length} characters of code`);
|
|
59
69
|
|
|
60
70
|
// Evaluate the transpiled code in a safe context
|
|
61
71
|
const loadedConfig = eval(transpiledCode);
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
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'}`);
|
|
65
75
|
|
|
66
76
|
// Get the actual config from the default export (ES module transpiled to CommonJS)
|
|
67
77
|
const actualConfig = loadedConfig.default || loadedConfig;
|
|
68
78
|
|
|
69
79
|
if (actualConfig && typeof actualConfig === 'object') {
|
|
70
|
-
|
|
71
|
-
|
|
80
|
+
log('Successfully loaded Playwright config from content');
|
|
81
|
+
log(`Config keys: ${Object.keys(actualConfig).join(', ')}`);
|
|
72
82
|
|
|
73
83
|
// Extract context options from the config
|
|
74
84
|
if (actualConfig.use && actualConfig.use.contextOptions) {
|
|
75
85
|
contextOptions = { ...contextOptions, ...actualConfig.use.contextOptions };
|
|
76
|
-
|
|
86
|
+
log('Applied context options from config');
|
|
77
87
|
}
|
|
78
88
|
|
|
79
89
|
// Apply other config settings
|
|
@@ -81,113 +91,113 @@ export async function initializeBrowser(
|
|
|
81
91
|
// Override headless mode if specified in config and not explicitly overridden
|
|
82
92
|
if (headless === undefined) {
|
|
83
93
|
headless = actualConfig.use.headless;
|
|
84
|
-
|
|
94
|
+
log(`Using headless mode from config: ${headless}`);
|
|
85
95
|
}
|
|
86
96
|
}
|
|
87
97
|
|
|
88
98
|
// Apply timeout settings
|
|
89
99
|
if (actualConfig.use && actualConfig.use.actionTimeout) {
|
|
90
|
-
|
|
100
|
+
log(`Using action timeout from config: ${actualConfig.use.actionTimeout}ms`);
|
|
91
101
|
}
|
|
92
102
|
|
|
93
103
|
// Apply viewport settings
|
|
94
104
|
if (actualConfig.use && actualConfig.use.viewport) {
|
|
95
105
|
contextOptions.viewport = actualConfig.use.viewport;
|
|
96
|
-
|
|
106
|
+
log(`Using viewport from config: ${JSON.stringify(actualConfig.use.viewport)}`);
|
|
97
107
|
}
|
|
98
108
|
|
|
99
109
|
// Apply user agent
|
|
100
110
|
if (actualConfig.use && actualConfig.use.userAgent) {
|
|
101
111
|
contextOptions.userAgent = actualConfig.use.userAgent;
|
|
102
|
-
|
|
112
|
+
log(`Using user agent from config: ${actualConfig.use.userAgent}`);
|
|
103
113
|
}
|
|
104
114
|
|
|
105
115
|
// Apply other context options
|
|
106
116
|
if (actualConfig.use && actualConfig.use.extraHTTPHeaders) {
|
|
107
117
|
contextOptions.extraHTTPHeaders = actualConfig.use.extraHTTPHeaders;
|
|
108
|
-
|
|
118
|
+
log(`Using extra HTTP headers from config`);
|
|
109
119
|
}
|
|
110
120
|
|
|
111
121
|
if (actualConfig.use && actualConfig.use.locale) {
|
|
112
122
|
contextOptions.locale = actualConfig.use.locale;
|
|
113
|
-
|
|
123
|
+
log(`Using locale from config: ${actualConfig.use.locale}`);
|
|
114
124
|
}
|
|
115
125
|
|
|
116
126
|
if (actualConfig.use && actualConfig.use.timezoneId) {
|
|
117
127
|
contextOptions.timezoneId = actualConfig.use.timezoneId;
|
|
118
|
-
|
|
128
|
+
log(`Using timezone from config: ${actualConfig.use.timezoneId}`);
|
|
119
129
|
}
|
|
120
130
|
|
|
121
131
|
if (actualConfig.use && actualConfig.use.geolocation) {
|
|
122
132
|
contextOptions.geolocation = actualConfig.use.geolocation;
|
|
123
|
-
|
|
133
|
+
log(`Using geolocation from config: ${JSON.stringify(actualConfig.use.geolocation)}`);
|
|
124
134
|
}
|
|
125
135
|
|
|
126
136
|
if (actualConfig.use && actualConfig.use.permissions) {
|
|
127
137
|
contextOptions.permissions = actualConfig.use.permissions;
|
|
128
|
-
|
|
138
|
+
log(`Using permissions from config: ${JSON.stringify(actualConfig.use.permissions)}`);
|
|
129
139
|
}
|
|
130
140
|
|
|
131
141
|
if (actualConfig.use && actualConfig.use.colorScheme) {
|
|
132
142
|
contextOptions.colorScheme = actualConfig.use.colorScheme;
|
|
133
|
-
|
|
143
|
+
log(`Using color scheme from config: ${actualConfig.use.colorScheme}`);
|
|
134
144
|
}
|
|
135
145
|
|
|
136
146
|
if (actualConfig.use && actualConfig.use.reducedMotion) {
|
|
137
147
|
contextOptions.reducedMotion = actualConfig.use.reducedMotion;
|
|
138
|
-
|
|
148
|
+
log(`Using reduced motion from config: ${actualConfig.use.reducedMotion}`);
|
|
139
149
|
}
|
|
140
150
|
|
|
141
151
|
if (actualConfig.use && actualConfig.use.forcedColors) {
|
|
142
152
|
contextOptions.forcedColors = actualConfig.use.forcedColors;
|
|
143
|
-
|
|
153
|
+
log(`Using forced colors from config: ${actualConfig.use.forcedColors}`);
|
|
144
154
|
}
|
|
145
155
|
|
|
146
156
|
if (actualConfig.use && actualConfig.use.acceptDownloads) {
|
|
147
157
|
contextOptions.acceptDownloads = actualConfig.use.acceptDownloads;
|
|
148
|
-
|
|
158
|
+
log(`Using accept downloads from config: ${actualConfig.use.acceptDownloads}`);
|
|
149
159
|
}
|
|
150
160
|
|
|
151
161
|
if (actualConfig.use && actualConfig.use.bypassCSP) {
|
|
152
162
|
contextOptions.bypassCSP = actualConfig.use.bypassCSP;
|
|
153
|
-
|
|
163
|
+
log(`Using bypass CSP from config: ${actualConfig.use.bypassCSP}`);
|
|
154
164
|
}
|
|
155
165
|
|
|
156
166
|
if (actualConfig.use && actualConfig.use.javaScriptEnabled) {
|
|
157
167
|
contextOptions.javaScriptEnabled = actualConfig.use.javaScriptEnabled;
|
|
158
|
-
|
|
168
|
+
log(`Using JavaScript enabled from config: ${actualConfig.use.javaScriptEnabled}`);
|
|
159
169
|
}
|
|
160
170
|
|
|
161
171
|
if (actualConfig.use && actualConfig.use.ignoreHTTPSErrors) {
|
|
162
172
|
contextOptions.ignoreHTTPSErrors = actualConfig.use.ignoreHTTPSErrors;
|
|
163
|
-
|
|
173
|
+
log(`Using ignore HTTPS errors from config: ${actualConfig.use.ignoreHTTPSErrors}`);
|
|
164
174
|
}
|
|
165
175
|
|
|
166
|
-
|
|
176
|
+
log(`Final context options: ${JSON.stringify(contextOptions, null, 2)}`);
|
|
167
177
|
} else {
|
|
168
|
-
|
|
178
|
+
log('Config loaded but no valid configuration found');
|
|
169
179
|
}
|
|
170
180
|
} catch (error) {
|
|
171
|
-
|
|
172
|
-
|
|
181
|
+
log(`Error transpiling config content: ${error}`, 'error');
|
|
182
|
+
log('Falling back to default configuration');
|
|
173
183
|
}
|
|
174
184
|
} else if (playwrightConfigFilePath) {
|
|
175
185
|
// Fallback to file path if no content provided (for backward compatibility)
|
|
176
|
-
|
|
186
|
+
log('No config content provided, falling back to file path');
|
|
177
187
|
// Resolve the path - it might be relative or absolute
|
|
178
188
|
const resolvedPath = path.isAbsolute(String(playwrightConfigFilePath))
|
|
179
189
|
? String(playwrightConfigFilePath)
|
|
180
190
|
: path.resolve(String(process.cwd()), String(playwrightConfigFilePath));
|
|
181
191
|
|
|
182
|
-
|
|
183
|
-
|
|
192
|
+
log(`Looking for Playwright config at: ${resolvedPath}`);
|
|
193
|
+
log(`File exists: ${fs.existsSync(String(resolvedPath))}`);
|
|
184
194
|
|
|
185
195
|
if (fs.existsSync(String(resolvedPath))) {
|
|
186
|
-
|
|
196
|
+
log(`Loading Playwright config from: ${resolvedPath}`);
|
|
187
197
|
|
|
188
198
|
try {
|
|
189
199
|
// Transpile the config in-memory and evaluate it
|
|
190
|
-
|
|
200
|
+
log(`Transpiling config in-memory from: ${resolvedPath}`);
|
|
191
201
|
|
|
192
202
|
const result = await build({
|
|
193
203
|
entryPoints: [String(resolvedPath)],
|
|
@@ -210,50 +220,50 @@ export async function initializeBrowser(
|
|
|
210
220
|
}
|
|
211
221
|
|
|
212
222
|
const transpiledCode = result.outputFiles[0].text;
|
|
213
|
-
|
|
223
|
+
log(`Transpilation complete. Generated ${transpiledCode.length} characters of code`);
|
|
214
224
|
|
|
215
225
|
// Evaluate the transpiled code in a safe context
|
|
216
226
|
const loadedConfig = eval(transpiledCode);
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
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'}`);
|
|
220
230
|
|
|
221
231
|
// Get the actual config from the default export (ES module transpiled to CommonJS)
|
|
222
232
|
const actualConfig = loadedConfig.default || loadedConfig;
|
|
223
|
-
|
|
224
|
-
|
|
233
|
+
log(`Actual config: ${JSON.stringify(actualConfig)}`);
|
|
234
|
+
log(`Actual config keys: ${actualConfig ? Object.keys(actualConfig).join(', ') : 'null/undefined'}`);
|
|
225
235
|
|
|
226
236
|
if (!actualConfig) {
|
|
227
|
-
|
|
237
|
+
log('Config import did not return a valid config; using defaults');
|
|
228
238
|
} else {
|
|
229
239
|
// Apply global use options
|
|
230
240
|
if (actualConfig.use) {
|
|
231
241
|
contextOptions = { ...actualConfig.use };
|
|
232
|
-
|
|
242
|
+
log('Applied context options from Playwright config:', contextOptions);
|
|
233
243
|
} else {
|
|
234
|
-
|
|
244
|
+
log('No use property found in config');
|
|
235
245
|
}
|
|
236
246
|
// Apply first project overrides if present
|
|
237
247
|
if (Array.isArray(actualConfig.projects) && actualConfig.projects.length > 0) {
|
|
238
248
|
const firstProject = actualConfig.projects[0];
|
|
239
249
|
if (firstProject && firstProject.use) {
|
|
240
250
|
contextOptions = { ...contextOptions, ...firstProject.use };
|
|
241
|
-
|
|
251
|
+
log('Applied project-specific options:', firstProject.use);
|
|
242
252
|
}
|
|
243
253
|
} else {
|
|
244
|
-
|
|
254
|
+
log('No projects found in config');
|
|
245
255
|
}
|
|
246
256
|
}
|
|
247
257
|
|
|
248
258
|
// No cleanup needed - we used in-memory transpilation
|
|
249
259
|
|
|
250
260
|
} catch (error) {
|
|
251
|
-
|
|
252
|
-
|
|
261
|
+
log(`Failed to load Playwright config via esbuild/import: ${error}`);
|
|
262
|
+
log('Using default browser settings');
|
|
253
263
|
}
|
|
254
264
|
} else {
|
|
255
|
-
|
|
256
|
-
|
|
265
|
+
log(`Playwright config file not found at: ${resolvedPath}`);
|
|
266
|
+
log('Using default browser settings');
|
|
257
267
|
}
|
|
258
268
|
}
|
|
259
269
|
|
|
@@ -274,3 +284,65 @@ export async function initializeBrowser(
|
|
|
274
284
|
|
|
275
285
|
return { browser, context, page };
|
|
276
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
|
+
}
|