slapify 0.0.0
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/README.md +452 -0
- package/bin/slapify.js +2 -0
- package/dist/ai/interpreter.d.ts +54 -0
- package/dist/ai/interpreter.d.ts.map +1 -0
- package/dist/ai/interpreter.js +293 -0
- package/dist/ai/interpreter.js.map +1 -0
- package/dist/browser/agent.d.ts +137 -0
- package/dist/browser/agent.d.ts.map +1 -0
- package/dist/browser/agent.js +362 -0
- package/dist/browser/agent.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +1181 -0
- package/dist/cli.js.map +1 -0
- package/dist/config/loader.d.ts +35 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +278 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/index.d.ts +155 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +260 -0
- package/dist/index.js.map +1 -0
- package/dist/parser/flow.d.ts +27 -0
- package/dist/parser/flow.d.ts.map +1 -0
- package/dist/parser/flow.js +117 -0
- package/dist/parser/flow.js.map +1 -0
- package/dist/report/generator.d.ts +61 -0
- package/dist/report/generator.d.ts.map +1 -0
- package/dist/report/generator.js +549 -0
- package/dist/report/generator.js.map +1 -0
- package/dist/runner/index.d.ts +44 -0
- package/dist/runner/index.d.ts.map +1 -0
- package/dist/runner/index.js +403 -0
- package/dist/runner/index.js.map +1 -0
- package/dist/types.d.ts +105 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +61 -0
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
import { generateText } from "ai";
|
|
2
|
+
import { createAnthropic } from "@ai-sdk/anthropic";
|
|
3
|
+
import { createOpenAI } from "@ai-sdk/openai";
|
|
4
|
+
import { createGoogleGenerativeAI } from "@ai-sdk/google";
|
|
5
|
+
import { createMistral } from "@ai-sdk/mistral";
|
|
6
|
+
import { createGroq } from "@ai-sdk/groq";
|
|
7
|
+
/**
|
|
8
|
+
* Get the AI model based on config
|
|
9
|
+
*/
|
|
10
|
+
function getModel(config) {
|
|
11
|
+
switch (config.provider) {
|
|
12
|
+
case "anthropic": {
|
|
13
|
+
const anthropic = createAnthropic({ apiKey: config.api_key });
|
|
14
|
+
return anthropic(config.model);
|
|
15
|
+
}
|
|
16
|
+
case "openai": {
|
|
17
|
+
const openai = createOpenAI({ apiKey: config.api_key });
|
|
18
|
+
return openai(config.model);
|
|
19
|
+
}
|
|
20
|
+
case "google": {
|
|
21
|
+
const google = createGoogleGenerativeAI({ apiKey: config.api_key });
|
|
22
|
+
return google(config.model);
|
|
23
|
+
}
|
|
24
|
+
case "mistral": {
|
|
25
|
+
const mistral = createMistral({ apiKey: config.api_key });
|
|
26
|
+
return mistral(config.model);
|
|
27
|
+
}
|
|
28
|
+
case "groq": {
|
|
29
|
+
const groq = createGroq({ apiKey: config.api_key });
|
|
30
|
+
return groq(config.model);
|
|
31
|
+
}
|
|
32
|
+
case "ollama": {
|
|
33
|
+
// Ollama uses OpenAI-compatible API
|
|
34
|
+
const ollama = createOpenAI({
|
|
35
|
+
apiKey: "ollama", // Ollama doesn't need a real key
|
|
36
|
+
baseURL: config.base_url || "http://localhost:11434/v1",
|
|
37
|
+
});
|
|
38
|
+
return ollama(config.model);
|
|
39
|
+
}
|
|
40
|
+
default:
|
|
41
|
+
throw new Error(`Unsupported LLM provider: ${config.provider}`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* AI interpreter for converting natural language steps to browser actions
|
|
46
|
+
*/
|
|
47
|
+
export class AIInterpreter {
|
|
48
|
+
config;
|
|
49
|
+
constructor(config) {
|
|
50
|
+
this.config = config;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Interpret a step and generate browser commands
|
|
54
|
+
*/
|
|
55
|
+
async interpretStep(step, browserState, credentials) {
|
|
56
|
+
const model = getModel(this.config);
|
|
57
|
+
const systemPrompt = `You are a browser automation assistant. Your job is to interpret natural language test steps and convert them to specific browser actions.
|
|
58
|
+
|
|
59
|
+
You have access to a browser with the following current state:
|
|
60
|
+
- URL: ${browserState.url}
|
|
61
|
+
- Title: ${browserState.title}
|
|
62
|
+
- Page snapshot (accessibility tree with refs):
|
|
63
|
+
${browserState.snapshot}
|
|
64
|
+
|
|
65
|
+
Available browser commands:
|
|
66
|
+
- navigate(url) - Go to a URL
|
|
67
|
+
- click(ref) - Click element by ref (e.g., @e1)
|
|
68
|
+
- fill(ref, value) - Fill input field
|
|
69
|
+
- type(ref, value) - Type text (append)
|
|
70
|
+
- press(key) - Press keyboard key
|
|
71
|
+
- hover(ref) - Hover over element
|
|
72
|
+
- select(ref, value) - Select dropdown option
|
|
73
|
+
- scroll(direction, amount?) - Scroll page
|
|
74
|
+
- wait(ms) - Wait milliseconds
|
|
75
|
+
- waitForText(text) - Wait for text to appear
|
|
76
|
+
- getText(ref) - Get element text
|
|
77
|
+
- screenshot(path?) - Take screenshot
|
|
78
|
+
- goBack() - Navigate back
|
|
79
|
+
- reload() - Reload page
|
|
80
|
+
|
|
81
|
+
${credentials
|
|
82
|
+
? `Available credentials profiles: ${Object.keys(credentials).join(", ")}`
|
|
83
|
+
: ""}
|
|
84
|
+
|
|
85
|
+
Respond with a JSON object containing:
|
|
86
|
+
{
|
|
87
|
+
"actions": [
|
|
88
|
+
{ "command": "click", "args": ["@e5"], "description": "Click the login button" }
|
|
89
|
+
],
|
|
90
|
+
"assumptions": ["Assumed 'login button' refers to the element labeled 'Sign In'"],
|
|
91
|
+
"needsCredentials": false,
|
|
92
|
+
"credentialProfile": null,
|
|
93
|
+
"skipReason": null,
|
|
94
|
+
"verified": false
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
IMPORTANT RULES:
|
|
98
|
+
- For "Verify" steps: If the verification PASSES, set "verified": true and include a description in actions. Do NOT use skipReason for successful verifications.
|
|
99
|
+
- skipReason should ONLY be used when a step cannot be completed or should be skipped (element not found, condition not met, etc.)
|
|
100
|
+
- If the step is a verification and it passes based on current page state, that's a SUCCESS - set verified: true.
|
|
101
|
+
- If the step is a verification and it fails, set skipReason to explain why it failed.`;
|
|
102
|
+
const userPrompt = `Interpret this test step and provide browser commands:
|
|
103
|
+
|
|
104
|
+
Step: "${step.text}"
|
|
105
|
+
${step.optional
|
|
106
|
+
? "(This step is optional - can be skipped if not applicable)"
|
|
107
|
+
: ""}
|
|
108
|
+
${step.conditional
|
|
109
|
+
? `Condition: "${step.condition}" → Action: "${step.action}"`
|
|
110
|
+
: ""}`;
|
|
111
|
+
const response = await generateText({
|
|
112
|
+
model,
|
|
113
|
+
system: systemPrompt,
|
|
114
|
+
prompt: userPrompt,
|
|
115
|
+
maxTokens: 1000,
|
|
116
|
+
});
|
|
117
|
+
try {
|
|
118
|
+
// Extract JSON from response
|
|
119
|
+
const jsonMatch = response.text.match(/\{[\s\S]*\}/);
|
|
120
|
+
if (!jsonMatch) {
|
|
121
|
+
throw new Error("No JSON found in response");
|
|
122
|
+
}
|
|
123
|
+
const result = JSON.parse(jsonMatch[0]);
|
|
124
|
+
return {
|
|
125
|
+
actions: result.actions || [],
|
|
126
|
+
assumptions: result.assumptions || [],
|
|
127
|
+
needsCredentials: result.needsCredentials || false,
|
|
128
|
+
credentialProfile: result.credentialProfile || null,
|
|
129
|
+
skipReason: result.skipReason || null,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
catch (error) {
|
|
133
|
+
// Fallback: try to parse as simple command
|
|
134
|
+
return {
|
|
135
|
+
actions: [],
|
|
136
|
+
assumptions: [],
|
|
137
|
+
needsCredentials: false,
|
|
138
|
+
credentialProfile: null,
|
|
139
|
+
skipReason: `Failed to interpret step: ${error}`,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Check for auto-handle opportunities (popups, banners, etc.)
|
|
145
|
+
*/
|
|
146
|
+
async checkAutoHandle(browserState) {
|
|
147
|
+
const model = getModel(this.config);
|
|
148
|
+
const systemPrompt = `You are analyzing a webpage for common interruptions that should be automatically handled during test automation.
|
|
149
|
+
|
|
150
|
+
Page snapshot:
|
|
151
|
+
${browserState.snapshot}
|
|
152
|
+
|
|
153
|
+
Look for these common interruptions:
|
|
154
|
+
1. Cookie consent banners (GDPR, etc.)
|
|
155
|
+
2. Newsletter signup popups
|
|
156
|
+
3. "Allow notifications" prompts
|
|
157
|
+
4. Chat widgets that might block content
|
|
158
|
+
5. Age verification dialogs
|
|
159
|
+
6. Promotional popups/modals
|
|
160
|
+
7. "Sign up for deals" overlays
|
|
161
|
+
|
|
162
|
+
IMPORTANT: When dismissing interruptions, ALWAYS prefer these buttons in order:
|
|
163
|
+
- For cookie banners: "Accept", "Accept All", "Allow", "Agree", "OK", "Got it", "Save changes", close button (X)
|
|
164
|
+
- NEVER click "Manage", "Customize", "Settings", "Preferences", "Learn more" as these open MORE dialogs
|
|
165
|
+
- For popups/modals: Close button (X), "No thanks", "Maybe later", "Skip", "Dismiss"
|
|
166
|
+
- For notifications: "Block", "Not now", "Later"
|
|
167
|
+
|
|
168
|
+
The goal is to DISMISS/CLOSE the interruption with ONE click, not configure it.
|
|
169
|
+
|
|
170
|
+
Respond with JSON:
|
|
171
|
+
{
|
|
172
|
+
"interruptions": [
|
|
173
|
+
{ "type": "cookie-banner", "ref": "@e15", "action": "click", "description": "Click Accept to dismiss cookie banner" }
|
|
174
|
+
]
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
If no interruptions found, return: { "interruptions": [] }`;
|
|
178
|
+
const response = await generateText({
|
|
179
|
+
model,
|
|
180
|
+
system: systemPrompt,
|
|
181
|
+
prompt: "Analyze this page for interruptions to auto-handle.",
|
|
182
|
+
maxTokens: 500,
|
|
183
|
+
});
|
|
184
|
+
try {
|
|
185
|
+
const jsonMatch = response.text.match(/\{[\s\S]*\}/);
|
|
186
|
+
if (!jsonMatch)
|
|
187
|
+
return [];
|
|
188
|
+
const result = JSON.parse(jsonMatch[0]);
|
|
189
|
+
return result.interruptions || [];
|
|
190
|
+
}
|
|
191
|
+
catch {
|
|
192
|
+
return [];
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Analyze page to find login form for credentials injection
|
|
197
|
+
*/
|
|
198
|
+
async findLoginForm(browserState) {
|
|
199
|
+
const model = getModel(this.config);
|
|
200
|
+
const systemPrompt = `You are analyzing a webpage to find login form elements.
|
|
201
|
+
|
|
202
|
+
Page snapshot:
|
|
203
|
+
${browserState.snapshot}
|
|
204
|
+
|
|
205
|
+
Find:
|
|
206
|
+
1. Username/email input field (ref)
|
|
207
|
+
2. Password input field (ref)
|
|
208
|
+
3. Submit/login button (ref)
|
|
209
|
+
|
|
210
|
+
Respond with JSON:
|
|
211
|
+
{
|
|
212
|
+
"found": true,
|
|
213
|
+
"usernameRef": "@e1",
|
|
214
|
+
"passwordRef": "@e2",
|
|
215
|
+
"submitRef": "@e3"
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
If no login form found: { "found": false }`;
|
|
219
|
+
const response = await generateText({
|
|
220
|
+
model,
|
|
221
|
+
system: systemPrompt,
|
|
222
|
+
prompt: "Find the login form elements on this page.",
|
|
223
|
+
maxTokens: 300,
|
|
224
|
+
});
|
|
225
|
+
try {
|
|
226
|
+
const jsonMatch = response.text.match(/\{[\s\S]*\}/);
|
|
227
|
+
if (!jsonMatch)
|
|
228
|
+
return null;
|
|
229
|
+
const result = JSON.parse(jsonMatch[0]);
|
|
230
|
+
if (!result.found)
|
|
231
|
+
return null;
|
|
232
|
+
return {
|
|
233
|
+
usernameRef: result.usernameRef,
|
|
234
|
+
passwordRef: result.passwordRef,
|
|
235
|
+
submitRef: result.submitRef,
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
catch {
|
|
239
|
+
return null;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Verify an assertion/condition on the page
|
|
244
|
+
*/
|
|
245
|
+
async verifyCondition(condition, browserState) {
|
|
246
|
+
const model = getModel(this.config);
|
|
247
|
+
const systemPrompt = `You are verifying a condition on a webpage.
|
|
248
|
+
|
|
249
|
+
Page URL: ${browserState.url}
|
|
250
|
+
Page Title: ${browserState.title}
|
|
251
|
+
Page snapshot:
|
|
252
|
+
${browserState.snapshot}
|
|
253
|
+
|
|
254
|
+
Respond with JSON:
|
|
255
|
+
{
|
|
256
|
+
"satisfied": true,
|
|
257
|
+
"evidence": "Found the text 'Welcome' in heading @e5",
|
|
258
|
+
"suggestion": null
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
Or if not satisfied:
|
|
262
|
+
{
|
|
263
|
+
"satisfied": false,
|
|
264
|
+
"evidence": "Could not find any element containing 'Welcome'",
|
|
265
|
+
"suggestion": "The page might still be loading, or the user might not be logged in"
|
|
266
|
+
}`;
|
|
267
|
+
const response = await generateText({
|
|
268
|
+
model,
|
|
269
|
+
system: systemPrompt,
|
|
270
|
+
prompt: `Verify this condition: "${condition}"`,
|
|
271
|
+
maxTokens: 300,
|
|
272
|
+
});
|
|
273
|
+
try {
|
|
274
|
+
const jsonMatch = response.text.match(/\{[\s\S]*\}/);
|
|
275
|
+
if (!jsonMatch) {
|
|
276
|
+
return {
|
|
277
|
+
satisfied: false,
|
|
278
|
+
evidence: "Could not parse verification result",
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
const result = JSON.parse(jsonMatch[0]);
|
|
282
|
+
return {
|
|
283
|
+
satisfied: result.satisfied,
|
|
284
|
+
evidence: result.evidence,
|
|
285
|
+
suggestion: result.suggestion,
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
catch {
|
|
289
|
+
return { satisfied: false, evidence: "Verification failed" };
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
//# sourceMappingURL=interpreter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interpreter.js","sourceRoot":"","sources":["../../src/ai/interpreter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { BrowserConfig, BrowserState, RefInfo } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Wrapper around agent-browser CLI
|
|
4
|
+
*/
|
|
5
|
+
export declare class BrowserAgent {
|
|
6
|
+
private config;
|
|
7
|
+
private isOpen;
|
|
8
|
+
constructor(config?: BrowserConfig);
|
|
9
|
+
/**
|
|
10
|
+
* Check if an error is transient and should be retried
|
|
11
|
+
*/
|
|
12
|
+
private isTransientError;
|
|
13
|
+
/**
|
|
14
|
+
* Sleep for a given number of milliseconds
|
|
15
|
+
*/
|
|
16
|
+
private sleep;
|
|
17
|
+
/**
|
|
18
|
+
* Execute an agent-browser command with auto-retry for transient errors
|
|
19
|
+
*/
|
|
20
|
+
private exec;
|
|
21
|
+
/**
|
|
22
|
+
* Check if agent-browser is installed
|
|
23
|
+
*/
|
|
24
|
+
static isInstalled(): boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Install agent-browser and its browser
|
|
27
|
+
*/
|
|
28
|
+
static install(): void;
|
|
29
|
+
/**
|
|
30
|
+
* Navigate to a URL
|
|
31
|
+
*/
|
|
32
|
+
navigate(url: string): Promise<void>;
|
|
33
|
+
/**
|
|
34
|
+
* Get page snapshot (accessibility tree)
|
|
35
|
+
*/
|
|
36
|
+
snapshot(interactive?: boolean): Promise<string>;
|
|
37
|
+
/**
|
|
38
|
+
* Get page snapshot as JSON with refs
|
|
39
|
+
*/
|
|
40
|
+
snapshotJson(): Promise<{
|
|
41
|
+
snapshot: string;
|
|
42
|
+
refs: Record<string, RefInfo>;
|
|
43
|
+
}>;
|
|
44
|
+
/**
|
|
45
|
+
* Click an element by ref or selector
|
|
46
|
+
*/
|
|
47
|
+
click(selector: string): Promise<void>;
|
|
48
|
+
/**
|
|
49
|
+
* Fill an input field
|
|
50
|
+
*/
|
|
51
|
+
fill(selector: string, value: string): Promise<void>;
|
|
52
|
+
/**
|
|
53
|
+
* Type text (appends to existing value)
|
|
54
|
+
*/
|
|
55
|
+
type(selector: string, value: string): Promise<void>;
|
|
56
|
+
/**
|
|
57
|
+
* Press a key
|
|
58
|
+
*/
|
|
59
|
+
press(key: string): Promise<void>;
|
|
60
|
+
/**
|
|
61
|
+
* Hover over an element
|
|
62
|
+
*/
|
|
63
|
+
hover(selector: string): Promise<void>;
|
|
64
|
+
/**
|
|
65
|
+
* Select dropdown option
|
|
66
|
+
*/
|
|
67
|
+
select(selector: string, value: string): Promise<void>;
|
|
68
|
+
/**
|
|
69
|
+
* Scroll the page
|
|
70
|
+
*/
|
|
71
|
+
scroll(direction: "up" | "down" | "left" | "right", amount?: number): Promise<void>;
|
|
72
|
+
/**
|
|
73
|
+
* Wait for various conditions
|
|
74
|
+
*/
|
|
75
|
+
wait(condition: string | number): Promise<void>;
|
|
76
|
+
/**
|
|
77
|
+
* Take a screenshot
|
|
78
|
+
*/
|
|
79
|
+
screenshot(path?: string, fullPage?: boolean): Promise<string>;
|
|
80
|
+
/**
|
|
81
|
+
* Get text content of an element
|
|
82
|
+
*/
|
|
83
|
+
getText(selector: string): Promise<string>;
|
|
84
|
+
/**
|
|
85
|
+
* Get current URL
|
|
86
|
+
*/
|
|
87
|
+
getUrl(): Promise<string>;
|
|
88
|
+
/**
|
|
89
|
+
* Get page title
|
|
90
|
+
*/
|
|
91
|
+
getTitle(): Promise<string>;
|
|
92
|
+
/**
|
|
93
|
+
* Check if element is visible
|
|
94
|
+
*/
|
|
95
|
+
isVisible(selector: string): Promise<boolean>;
|
|
96
|
+
/**
|
|
97
|
+
* Execute JavaScript
|
|
98
|
+
*/
|
|
99
|
+
evaluate(script: string): Promise<string>;
|
|
100
|
+
/**
|
|
101
|
+
* Set cookies
|
|
102
|
+
*/
|
|
103
|
+
setCookie(name: string, value: string): Promise<void>;
|
|
104
|
+
/**
|
|
105
|
+
* Set localStorage value
|
|
106
|
+
*/
|
|
107
|
+
setLocalStorage(key: string, value: string): Promise<void>;
|
|
108
|
+
/**
|
|
109
|
+
* Set sessionStorage value
|
|
110
|
+
*/
|
|
111
|
+
setSessionStorage(key: string, value: string): Promise<void>;
|
|
112
|
+
/**
|
|
113
|
+
* Go back
|
|
114
|
+
*/
|
|
115
|
+
goBack(): Promise<void>;
|
|
116
|
+
/**
|
|
117
|
+
* Go forward
|
|
118
|
+
*/
|
|
119
|
+
goForward(): Promise<void>;
|
|
120
|
+
/**
|
|
121
|
+
* Reload page
|
|
122
|
+
*/
|
|
123
|
+
reload(): Promise<void>;
|
|
124
|
+
/**
|
|
125
|
+
* Close the browser
|
|
126
|
+
*/
|
|
127
|
+
close(): Promise<void>;
|
|
128
|
+
/**
|
|
129
|
+
* Get current browser state (with graceful error handling)
|
|
130
|
+
*/
|
|
131
|
+
getState(): Promise<BrowserState>;
|
|
132
|
+
/**
|
|
133
|
+
* Wait for page to be stable (no navigation in progress)
|
|
134
|
+
*/
|
|
135
|
+
waitForStable(timeout?: number): Promise<void>;
|
|
136
|
+
}
|
|
137
|
+
//# sourceMappingURL=agent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/browser/agent.ts"],"names":[],"mappings":"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"}
|