slapify 0.0.14 → 0.0.17

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 (48) hide show
  1. package/README.md +342 -258
  2. package/dist/ai/interpreter.d.ts +13 -0
  3. package/dist/ai/interpreter.js +1 -293
  4. package/dist/browser/agent.js +1 -485
  5. package/dist/cli.js +1 -1315
  6. package/dist/config/loader.js +1 -305
  7. package/dist/index.d.ts +2 -0
  8. package/dist/index.js +1 -260
  9. package/dist/parser/flow.js +1 -117
  10. package/dist/perf/audit.d.ts +215 -0
  11. package/dist/perf/audit.js +1 -0
  12. package/dist/report/generator.d.ts +1 -0
  13. package/dist/report/generator.js +1 -549
  14. package/dist/runner/index.d.ts +14 -1
  15. package/dist/runner/index.js +1 -584
  16. package/dist/task/index.d.ts +5 -0
  17. package/dist/task/index.js +1 -0
  18. package/dist/task/report.d.ts +9 -0
  19. package/dist/task/report.js +1 -0
  20. package/dist/task/runner.d.ts +3 -0
  21. package/dist/task/runner.js +1 -0
  22. package/dist/task/session.d.ts +18 -0
  23. package/dist/task/session.js +1 -0
  24. package/dist/task/tools.d.ts +253 -0
  25. package/dist/task/tools.js +1 -0
  26. package/dist/task/types.d.ts +153 -0
  27. package/dist/task/types.js +1 -0
  28. package/dist/types.d.ts +2 -0
  29. package/dist/types.js +1 -2
  30. package/package.json +25 -15
  31. package/dist/ai/interpreter.d.ts.map +0 -1
  32. package/dist/ai/interpreter.js.map +0 -1
  33. package/dist/browser/agent.d.ts.map +0 -1
  34. package/dist/browser/agent.js.map +0 -1
  35. package/dist/cli.d.ts.map +0 -1
  36. package/dist/cli.js.map +0 -1
  37. package/dist/config/loader.d.ts.map +0 -1
  38. package/dist/config/loader.js.map +0 -1
  39. package/dist/index.d.ts.map +0 -1
  40. package/dist/index.js.map +0 -1
  41. package/dist/parser/flow.d.ts.map +0 -1
  42. package/dist/parser/flow.js.map +0 -1
  43. package/dist/report/generator.d.ts.map +0 -1
  44. package/dist/report/generator.js.map +0 -1
  45. package/dist/runner/index.d.ts.map +0 -1
  46. package/dist/runner/index.js.map +0 -1
  47. package/dist/types.d.ts.map +0 -1
  48. package/dist/types.js.map +0 -1
package/README.md CHANGED
@@ -1,453 +1,537 @@
1
1
  # slapify 🖐️
2
2
 
3
- **AI-powered E2E testing that slaps** — write tests in plain English.
3
+ **AI-powered browser automation that slaps** — run autonomous agents, audit performance, and write E2E tests in plain English.
4
4
 
5
5
  By [slaps.dev](https://slaps.dev)
6
6
 
7
+ ---
8
+
9
+ ## What can it do?
10
+
11
+ | Mode | What it does |
12
+ | ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
13
+ | **`task`** | Autonomous AI agent — give it any goal, it figures out how to achieve it. Browses, logs in, schedules itself, audits performance, remembers state across runs. |
14
+ | **`run`** | Execute `.flow` test files — plain-English E2E tests with screenshots and HTML reports |
15
+
16
+ ---
17
+
7
18
  ## Installation
8
19
 
9
20
  ```bash
10
- # Install globally
11
21
  npm install -g slapify
12
22
 
13
- # Or use directly with npx (no install needed)
23
+ # or run without installing
14
24
  npx slapify init
15
25
  ```
16
26
 
27
+ ---
28
+
17
29
  ## Quick Start
18
30
 
19
31
  ```bash
20
- # Initialize in your project (interactive setup)
32
+ # 1. Set up your project (interactive — picks LLM, browser, creates sample files)
21
33
  slapify init
22
34
 
23
- # Or with npx
24
- npx slapify init
35
+ # 2. Set your API key
36
+ export ANTHROPIC_API_KEY=your-key
25
37
 
26
- # Quick init with defaults (skip prompts)
27
- slapify init -y
38
+ # 3a. Run an autonomous task
39
+ slapify task "Summarise the top posts on reddit.com/r/programming today" --report
28
40
 
29
- # Set your API key
30
- export ANTHROPIC_API_KEY=your-key
41
+ # 3b. Run a test flow
42
+ slapify run tests/example.flow --report
43
+ ```
44
+
45
+ ---
31
46
 
32
- # Run the example test (command is "slapify run", not "flow")
33
- slapify run tests/example.flow
34
- # Or with npx:
35
- npx slapify run tests/example.flow
47
+ ## Autonomous Agent (`slapify task`)
48
+
49
+ Give it a goal in plain English. The agent decides what to do, browses pages, handles login, retries on errors, and keeps running until the goal is complete — even if that takes hours or days.
50
+
51
+ ### CLI
52
+
53
+ ```bash
54
+ # One-off research
55
+ slapify task "What is the current gold price?"
56
+ slapify task "Go to reddit.com/r/programming and summarise the top 5 posts"
57
+ slapify task "Check https://myapp.com and tell me if anything looks broken"
58
+
59
+ # Performance audits
60
+ slapify task "Audit the performance of slaps.dev" --report
61
+ slapify task "Audit the home, pricing, and about pages on vercel.com" --report
62
+
63
+ # Long-running / scheduled
64
+ slapify task "Check my LinkedIn messages every 30 minutes and summarise new ones"
65
+ slapify task "Monitor https://example.com/status every 5 minutes and alert if down"
66
+ slapify task "Check BTC price every hour for 24 hours and give me an end-of-day summary"
67
+
68
+ # Auth-required tasks (agent handles login automatically)
69
+ slapify task "Log into myapp.com and export my account data"
70
+ slapify task "Reply to any unread Slack DMs with a friendly holding message"
71
+
72
+ # Flags
73
+ slapify task "..." --report # generate HTML report on exit
74
+ slapify task "..." --headed # show the browser window
75
+ slapify task "..." --debug # verbose logs
76
+ slapify task "..." --save-flow # save steps as a reusable .flow file
36
77
  ```
37
78
 
38
- The interactive `init` command will:
79
+ ### What the agent can do
80
+
81
+ | Capability | Details |
82
+ | ------------------------- | ------------------------------------------------------------------------------ |
83
+ | **Browse & interact** | Navigate, click, type, scroll, fill forms, handle popups |
84
+ | **Bypass bot protection** | Falls back to HTTP-level requests when the browser is blocked |
85
+ | **Login automatically** | Detects login forms, uses saved credential profiles, asks you to save new ones |
86
+ | **Persistent memory** | Stores key facts between runs (thread URLs, last-seen items, etc.) |
87
+ | **Schedule itself** | Creates its own cron jobs for recurring subtasks |
88
+ | **Ask for input** | Pauses and prompts you when it needs information (e.g. OTP, confirmation) |
89
+ | **Performance audit** | Scores, web vitals, network analysis, framework detection, re-render testing |
90
+ | **HTML report** | Full session report with tool timeline, summaries, and perf data |
39
91
 
40
- - Ask which LLM provider to use (Anthropic/OpenAI)
41
- - Detect installed browsers on your system
42
- - Let you choose between system Chrome or downloading Chromium
43
- - Create a sample test file to get started
92
+ ### Programmatic (JS/TS)
44
93
 
45
- ## Writing Tests
94
+ ```typescript
95
+ import { runTask } from "slapify";
46
96
 
47
- Create `.flow` files with natural language steps:
97
+ // Simple one-shot task
98
+ const result = await runTask({
99
+ goal: "Go to news.ycombinator.com and return the top 10 headlines",
100
+ });
48
101
 
102
+ console.log(result.finalSummary);
49
103
  ```
50
- # tests/login.flow
51
-
52
- Go to https://myapp.com
53
- Login with default credentials
54
- Verify "Welcome" message appears
55
- [Optional] Close promotional popup
56
- Navigate to settings
57
- Verify "Account Settings" page loads
104
+
105
+ ```typescript
106
+ import { runTask, TaskEvent } from "slapify";
107
+
108
+ // With real-time events
109
+ const result = await runTask({
110
+ goal: "Audit the performance of https://myapp.com/pricing and /about",
111
+
112
+ onEvent: (event: TaskEvent) => {
113
+ if (event.type === "message") console.log("Agent:", event.text);
114
+ if (event.type === "status_update") console.log("→", event.message);
115
+ if (event.type === "tool_start") console.log(` [${event.toolName}]`);
116
+ if (event.type === "done") console.log("✅", event.summary);
117
+ },
118
+
119
+ // Called when the agent needs a human answer (e.g. 2FA code, confirmation)
120
+ onHumanInput: async (question, hint) => {
121
+ return await promptUser(question); // plug in your own UI
122
+ },
123
+ });
58
124
  ```
59
125
 
60
- ### Syntax
126
+ ```typescript
127
+ import { runTask } from "slapify";
61
128
 
62
- | Feature | Example |
63
- | ------------- | ------------------------------------------- |
64
- | Comments | `# This is a comment` |
65
- | Required step | `Click the login button` |
66
- | Optional step | `[Optional] Close popup` |
67
- | Conditional | `If "Accept cookies" appears, click Accept` |
68
- | Credentials | `Login with admin credentials` |
69
- | Verification | `Verify "Success" message appears` |
129
+ // Resume a previous session (credentials, memory, and context are preserved)
130
+ const result = await runTask({
131
+ goal: "Continue monitoring LinkedIn messages",
132
+ sessionId: "task-2026-02-19T20-19-44-dtbfu",
133
+ });
134
+ ```
70
135
 
71
- ## Configuration
136
+ ```typescript
137
+ import { runTask } from "slapify";
138
+
139
+ // Long-running scheduled task — agent sets its own cron internally
140
+ await runTask({
141
+ goal:
142
+ "Every hour, check the BTC price and store it. " +
143
+ "After 24 hours, summarise the day's movements.",
144
+ maxIterations: 500,
145
+ onEvent: (e) => {
146
+ if (e.type === "scheduled") console.log(`Scheduled: ${e.cron}`);
147
+ if (e.type === "sleeping") console.log(`Sleeping until: ${e.until}`);
148
+ if (e.type === "done") console.log(e.summary);
149
+ },
150
+ });
151
+ ```
72
152
 
73
- ### `.slapify/config.yaml`
153
+ ---
74
154
 
75
- ```yaml
76
- # LLM Settings (required)
77
- llm:
78
- provider: anthropic
79
- model: claude-sonnet-4-20250514
80
- api_key: ${ANTHROPIC_API_KEY}
155
+ ## Performance Auditing
81
156
 
82
- # Browser Settings (optional)
83
- browser:
84
- headless: true
85
- timeout: 30000
86
- viewport:
87
- width: 1280
88
- height: 720
157
+ The agent has a built-in `perf_audit` tool. Just ask it to check performance — it navigates, injects observers, collects everything, and includes it all in the HTML report.
89
158
 
90
- # Report Settings (optional)
91
- report:
92
- format: html
93
- screenshots: true
94
- output_dir: ./test-reports
159
+ ### What's measured
160
+
161
+ | Category | Metrics |
162
+ | --------------------- | ---------------------------------------------------------------- |
163
+ | **Real-user metrics** | FCP, LCP, CLS, TTFB |
164
+ | **Lab scores** | Performance, Accessibility, SEO, Best Practices (0–100) |
165
+ | **Framework** | React / Next.js detection, re-render issues, interaction tests |
166
+ | **Network** | Total size, JS bundle size, CSS, images |
167
+ | **API calls** | Method, URL, status, duration — slow (>500ms) and failed flagged |
168
+ | **Long tasks** | JavaScript blocking the main thread (>50ms) |
169
+ | **Memory** | JS heap usage |
170
+
171
+ ### Multi-page comparison
172
+
173
+ Audit multiple pages in one command. The HTML report shows a **tab bar** — one tab per URL, click to switch. Each tab has the full breakdown for that page.
174
+
175
+ ```bash
176
+ # Three-tab report: /, /pricing, /about
177
+ slapify task "Audit the home, pricing, and about pages on vercel.com" --report
95
178
  ```
96
179
 
97
- ### `.slapify/credentials.yaml`
180
+ ### Programmatic
98
181
 
99
- ```yaml
100
- profiles:
101
- default:
102
- type: login-form
103
- username: ${TEST_USERNAME}
104
- password: ${TEST_PASSWORD}
182
+ ```typescript
183
+ import { runPerfAudit } from "slapify/perf";
184
+ import { BrowserAgent } from "slapify";
105
185
 
106
- admin:
107
- type: login-form
108
- username: admin@example.com
109
- password: ${ADMIN_PASSWORD}
110
- totp_secret: JBSWY3DPEHPK3PXP # For 2FA
186
+ const browser = new BrowserAgent();
187
+ await browser.launch();
111
188
 
112
- session:
113
- type: inject
114
- cookies:
115
- - name: auth_token
116
- value: ${AUTH_TOKEN}
117
- domain: .example.com
189
+ const result = await runPerfAudit("https://myapp.com/pricing", browser, {
190
+ lighthouse: true, // lab scores — Performance/A11y/SEO/Best Practices (default: true)
191
+ reactScan: true, // framework detection + re-render analysis (default: true)
192
+ navigate: true, // navigate to the URL before auditing (default: true)
193
+ });
194
+
195
+ console.log(result.vitals); // { fcp, lcp, cls, ttfb }
196
+ console.log(result.scores); // { performance, accessibility, seo, bestPractices }
197
+ console.log(result.react); // { detected, version, issues, interactionTests }
198
+ console.log(result.network); // { totalRequests, totalBytes, apiCalls, longTasks, ... }
199
+
200
+ await browser.close();
118
201
  ```
119
202
 
120
- ## CLI Commands
203
+ ---
121
204
 
122
- ```bash
123
- # Initialize project
124
- slapify init
205
+ ## Test Flows (`slapify run`)
206
+
207
+ Write tests as `.flow` files in plain English. The AI interprets each line and executes browser actions, with screenshots and auto-retry on failure.
208
+
209
+ ### Smart by default
210
+
211
+ You don't need to spell out every edge case. The runner handles these automatically on every step:
125
212
 
126
- # Run all tests in tests/ directory
127
- slapify run
213
+ | What happens automatically | How |
214
+ | ---------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
215
+ | **Cookie banners, popups, chat widgets** | Detected and dismissed before they block the next step |
216
+ | **CAPTCHAs** | Detected by page content signals (reCAPTCHA, hCaptcha, Cloudflare Turnstile) and solved automatically |
217
+ | **Credential lookup** | Steps like `Log in` or `Sign in` (no profile named) auto-pick the best matching profile for the current domain, falling back to `default` |
218
+ | **Auto-retry** | Failed steps are retried once before being marked failed |
128
219
 
129
- # Run specific files
130
- slapify run tests/login.flow tests/checkout.flow
220
+ ### Writing `.flow` files
131
221
 
132
- # Run all tests in a directory
222
+ ```
223
+ # tests/checkout.flow
224
+
225
+ Go to https://myshop.com
226
+ [Optional] Close cookie banner
227
+ Click "Add to Cart" on the first product
228
+ Go to checkout
229
+ Log in # picks the right credential profile automatically
230
+ Fill shipping address
231
+ Click "Place Order"
232
+ Verify "Order confirmed" appears
233
+ ```
234
+
235
+ **Syntax reference:**
236
+
237
+ | Syntax | Example |
238
+ | ---------------- | ------------------------------------------------ |
239
+ | Comment | `# This is a comment` |
240
+ | Required step | `Click the login button` |
241
+ | Optional step | `[Optional] Close popup` |
242
+ | Conditional | `If "Accept cookies" appears, click Accept` |
243
+ | Named credential | `Login with admin credentials` |
244
+ | Auto credential | `Log in` — picks best profile for current domain |
245
+ | Assertion | `Verify "Welcome" message appears` |
246
+
247
+ ### CLI
248
+
249
+ ```bash
250
+ # Run a single flow
251
+ slapify run tests/login.flow
252
+
253
+ # Run all flows in a directory
133
254
  slapify run tests/
134
255
 
135
- # Run with visible browser
136
- slapify run --headed
256
+ # With visible browser
257
+ slapify run tests/ --headed
137
258
 
138
- # Run with HTML report
139
- slapify run --report
259
+ # Generate HTML report with screenshots
260
+ slapify run tests/ --report
261
+
262
+ # Include performance audit in the report
263
+ slapify run tests/ --report --performance
140
264
 
141
265
  # Run in parallel (4 workers by default)
142
266
  slapify run tests/ --parallel
143
267
 
144
268
  # Run in parallel with 8 workers
145
- slapify run tests/ -p -w 8
269
+ slapify run tests/ --parallel --workers 8
146
270
 
147
- # Fix failing tests automatically
271
+ # Auto-fix a failing flow
148
272
  slapify fix tests/broken.flow
149
273
 
150
- # Validate flow files
151
- slapify validate
274
+ # Other utilities
275
+ slapify list # list all flow files
276
+ slapify validate # validate flow syntax
277
+ slapify create my-test # create a blank flow
278
+ ```
279
+
280
+ ### Generating flows
152
281
 
153
- # List all tests
154
- slapify list
282
+ Instead of writing flows by hand, use `generate` to have the agent discover the real path by actually running it in the browser — handles login, captcha, and dynamic content automatically, and only records steps that worked.
155
283
 
156
- # Create a new flow file
157
- slapify create my-test
284
+ ```bash
285
+ # Agent runs the goal, saves verified steps to tests/
286
+ slapify generate "test the login flow on github.com"
158
287
 
159
- # Generate flow from prompt
160
- slapify generate "test login flow for github.com"
288
+ # Save to a specific directory
289
+ slapify generate "test checkout on myshop.com" --dir tests/checkout
161
290
 
162
- # Interactive mode
163
- slapify interactive https://myapp.com
291
+ # With visible browser
292
+ slapify generate "sign up flow on myapp.com" --headed
164
293
  ```
165
294
 
166
- ## Programmatic Usage
295
+ This is equivalent to `slapify task "..." --save-flow --dir tests/` — the saved `.flow` file is proven to work, not just AI-guessed from a page snapshot.
167
296
 
168
- ### Basic Usage
297
+ ### Programmatic (JS/TS)
169
298
 
170
299
  ```typescript
171
300
  import { Slapify } from "slapify";
172
301
 
173
- // Using config directory
174
302
  const slapify = new Slapify({ configDir: ".slapify" });
175
303
 
176
- // Or with inline config
177
- const slapify = new Slapify({
178
- config: {
179
- llm: {
180
- provider: "anthropic",
181
- model: "claude-sonnet-4-20250514",
182
- api_key: process.env.ANTHROPIC_API_KEY,
183
- },
184
- browser: { headless: true },
185
- },
186
- });
187
-
188
304
  // Run inline steps
189
305
  const result = await slapify.run(
190
306
  [
191
307
  "Go to https://example.com",
192
- 'Click on "More information"',
308
+ 'Click "More information"',
193
309
  'Verify URL contains "iana.org"',
194
310
  ],
195
311
  "example-test"
196
312
  );
197
313
 
198
- console.log(result.status); // 'passed' or 'failed'
199
- console.log(result.passedSteps); // Number of passed steps
200
- console.log(result.duration); // Total time in ms
314
+ console.log(result.status); // 'passed' | 'failed'
315
+ console.log(result.passedSteps); // number
316
+ console.log(result.duration); // ms
201
317
  ```
202
318
 
203
- ### Run from File
204
-
205
319
  ```typescript
320
+ // Run from file
206
321
  const result = await slapify.runFile("./tests/checkout.flow");
207
- ```
208
-
209
- ### Run Multiple Tests
210
322
 
211
- ```typescript
212
- // Sequential
323
+ // Run multiple — sequential
213
324
  const results = await slapify.runMultiple([
214
325
  "tests/login.flow",
215
326
  "tests/checkout.flow",
216
327
  ]);
217
328
 
218
- // Parallel with 4 workers
329
+ // Run multiple parallel
219
330
  const results = await slapify.runMultiple(["tests/"], {
220
331
  parallel: true,
221
332
  workers: 4,
222
333
  });
223
-
224
- // Run all tests in a directory
225
- const results = await slapify.runAll("tests/", { parallel: true });
226
334
  ```
227
335
 
228
- ### With Progress Callbacks
229
-
230
336
  ```typescript
337
+ // Step-level callbacks
231
338
  const result = await slapify.run(steps, "my-test", {
232
- onTestStart: (name, totalSteps) => {
233
- console.log(`Starting ${name} with ${totalSteps} steps`);
234
- },
235
- onStep: (stepResult, testName) => {
339
+ onTestStart: (name, totalSteps) =>
340
+ console.log(`Starting ${name} (${totalSteps} steps)`),
341
+ onStep: (stepResult) => {
236
342
  const icon = stepResult.status === "passed" ? "✓" : "✗";
237
343
  console.log(` ${icon} ${stepResult.step.text}`);
238
344
  },
239
- onTestComplete: (result) => {
240
- console.log(`Finished: ${result.status}`);
241
- },
345
+ onTestComplete: (result) => console.log(`Done: ${result.status}`),
242
346
  });
243
347
  ```
244
348
 
245
- ### Generate Reports
246
-
247
349
  ```typescript
248
- // Single test report
249
- const reportPath = slapify.saveReport(result);
250
-
251
- // Suite report for multiple tests
252
- const suiteReportPath = slapify.saveSuiteReport(results);
253
-
254
- // Get report HTML as string
255
- const html = slapify.generateReport(result);
350
+ // Save reports
351
+ const reportPath = slapify.saveReport(result); // single test
352
+ const suiteReport = slapify.saveSuiteReport(results); // full suite
353
+ const html = slapify.generateReport(result); // HTML as string
256
354
  ```
257
355
 
258
- ### Jest Integration
356
+ ### Jest / Vitest integration
259
357
 
260
358
  ```typescript
261
359
  import { Slapify } from "slapify";
262
360
 
263
- describe("E2E Tests", () => {
264
- const slapify = new Slapify({ configDir: ".slapify" });
265
-
266
- test("user can login", async () => {
267
- const result = await slapify.run(
268
- [
269
- "Go to https://myapp.com/login",
270
- "Fill email with test@example.com",
271
- "Fill password with secret123",
272
- "Click Login button",
273
- 'Verify "Dashboard" appears',
274
- ],
275
- "login-test"
276
- );
277
-
278
- expect(result.status).toBe("passed");
279
- }, 60000);
280
-
281
- test("checkout flow works", async () => {
282
- const result = await slapify.runFile("tests/checkout.flow");
283
- expect(result.failedSteps).toBe(0);
284
- }, 120000);
285
- });
286
- ```
287
-
288
- ### Vitest Integration
289
-
290
- ```typescript
291
- import { describe, test, expect } from "vitest";
292
- import { Slapify } from "slapify";
361
+ const slapify = new Slapify({ configDir: ".slapify" });
293
362
 
294
- describe("E2E Tests", () => {
295
- const slapify = new Slapify({ configDir: ".slapify" });
296
-
297
- test(
298
- "user can search",
299
- async () => {
300
- const result = await slapify.run([
301
- "Go to https://google.com",
302
- "Fill search box with slapify",
303
- "Press Enter",
304
- "Verify results appear",
305
- ]);
306
-
307
- expect(result.status).toBe("passed");
308
- },
309
- { timeout: 60000 }
363
+ test("user can log in", async () => {
364
+ const result = await slapify.run(
365
+ [
366
+ "Go to https://myapp.com/login",
367
+ "Fill email with test@example.com",
368
+ "Fill password with secret123",
369
+ "Click Login",
370
+ 'Verify "Dashboard" appears',
371
+ ],
372
+ "login-test"
310
373
  );
311
- });
374
+ expect(result.status).toBe("passed");
375
+ }, 60_000);
376
+
377
+ test("checkout flow", async () => {
378
+ const result = await slapify.runFile("tests/checkout.flow");
379
+ expect(result.failedSteps).toBe(0);
380
+ }, 120_000);
312
381
  ```
313
382
 
314
- ## How It Works
383
+ ---
315
384
 
316
- 1. **Parse**: Flow files are parsed into structured steps
317
- 2. **Interpret**: AI interprets each step and determines browser actions
318
- 3. **Execute**: Browser automation executes the actions
319
- 4. **Report**: Results are collected and formatted
385
+ ## Credential Management
320
386
 
321
- ### Auto-Handling
387
+ Slapify handles credentials for any site — login forms, OAuth, or injecting an existing session.
322
388
 
323
- Slapify automatically handles common interruptions:
389
+ ### `.slapify/credentials.yaml`
324
390
 
325
- - Cookie consent banners
326
- - Newsletter popups
327
- - Notification prompts
328
- - Chat widgets
329
- - CAPTCHAs (basic)
391
+ ```yaml
392
+ profiles:
393
+ default:
394
+ type: login-form
395
+ username: ${TEST_USERNAME}
396
+ password: ${TEST_PASSWORD}
330
397
 
331
- All auto-handled items are noted in the report.
398
+ admin:
399
+ type: login-form
400
+ username: admin@example.com
401
+ password: ${ADMIN_PASSWORD}
402
+ totp_secret: JBSWY3DPEHPK3PXP # TOTP 2FA
332
403
 
333
- ### Auto-Retry
404
+ # Skip login entirely — inject an existing session
405
+ my-session:
406
+ type: inject
407
+ cookies:
408
+ - name: auth_token
409
+ value: ${AUTH_TOKEN}
410
+ domain: .example.com
411
+ localStorage:
412
+ user_id: "12345"
413
+ theme: dark
414
+ ```
334
415
 
335
- Failed steps are automatically retried once before marking as failed. This helps with:
416
+ In **task mode**, credentials are fully automatic:
336
417
 
337
- - Flaky network requests
338
- - Animation timing issues
339
- - Element loading delays
418
+ - The agent detects login forms and picks the right profile
419
+ - If no profile matches, it asks you to enter credentials and offers to save them
420
+ - Saved sessions are reused on future runs — no re-login needed
340
421
 
341
- ### Auto-Fix
422
+ ---
342
423
 
343
- Use `slapify fix` to automatically analyze and fix failing tests:
424
+ ## Configuration
344
425
 
345
- ```bash
346
- slapify fix tests/broken.flow
347
- ```
426
+ ### `.slapify/config.yaml`
348
427
 
349
- ## Reports
428
+ ```yaml
429
+ llm:
430
+ provider: anthropic
431
+ model: claude-haiku-4-5-20251001 # fast & cheap — recommended
432
+ api_key: ${ANTHROPIC_API_KEY}
350
433
 
351
- Beautiful HTML reports with:
434
+ browser:
435
+ headless: true
436
+ timeout: 30000
437
+ viewport:
438
+ width: 1280
439
+ height: 720
352
440
 
353
- - Expandable step details
354
- - Embedded screenshots
355
- - Duration metrics
356
- - Pass/fail summary
357
- - Assumptions highlighted
358
- - Auto-handled items noted
441
+ report:
442
+ format: html
443
+ screenshots: true
444
+ output_dir: ./test-reports
445
+ ```
446
+
447
+ ---
359
448
 
360
449
  ## LLM Providers
361
450
 
362
- Supports 6 AI providers via Vercel AI SDK. **Cheap models are recommended by default.**
451
+ Supports 6 providers via Vercel AI SDK.
363
452
 
364
- ### Recommended (Budget-Friendly)
453
+ ### Budget-friendly (recommended)
365
454
 
366
455
  ```yaml
367
- # Anthropic - Claude Haiku 4.5 (fast & cheap, $1/5M tokens)
456
+ # Anthropic Claude Haiku 4.5 (fast, ~$1/5M tokens)
368
457
  llm:
369
458
  provider: anthropic
370
459
  model: claude-haiku-4-5-20251001
371
460
  api_key: ${ANTHROPIC_API_KEY}
372
461
 
373
- # OpenAI - GPT-4o Mini (fast & cheap, $0.15/0.6M tokens)
462
+ # OpenAI GPT-4o Mini
374
463
  llm:
375
464
  provider: openai
376
465
  model: gpt-4o-mini
377
466
  api_key: ${OPENAI_API_KEY}
378
467
 
379
- # Google - Gemini 2.0 Flash (fastest & cheapest)
468
+ # Google Gemini 2.0 Flash (generous free tier)
380
469
  llm:
381
470
  provider: google
382
471
  model: gemini-2.0-flash
383
472
  api_key: ${GOOGLE_API_KEY}
384
473
 
385
- # Groq - Free tier available!
474
+ # Groq free tier available
386
475
  llm:
387
476
  provider: groq
388
477
  model: llama-3.3-70b-versatile
389
478
  api_key: ${GROQ_API_KEY}
390
479
  ```
391
480
 
392
- ### More Capable (Higher Cost)
481
+ ### More capable
393
482
 
394
483
  ```yaml
395
- # Anthropic - Claude Sonnet 4 ($3/15M tokens)
484
+ # Anthropic Claude Sonnet
396
485
  llm:
397
486
  provider: anthropic
398
487
  model: claude-sonnet-4-20250514
399
488
 
400
- # OpenAI - GPT-4o ($2.5/10M tokens)
489
+ # OpenAI GPT-4o
401
490
  llm:
402
491
  provider: openai
403
492
  model: gpt-4o
404
493
  ```
405
494
 
406
- ### Local (No API Key)
495
+ ### Local (no API key)
407
496
 
408
497
  ```yaml
409
- # Ollama - runs locally, free
498
+ # Ollama runs on your machine, completely free
410
499
  llm:
411
500
  provider: ollama
412
501
  model: llama3 # or mistral, codellama, phi3
413
502
  base_url: http://localhost:11434/v1
414
503
  ```
415
504
 
416
- ### Other Providers
417
-
418
- ```yaml
419
- # Mistral
420
- llm:
421
- provider: mistral
422
- model: mistral-small-latest # or mistral-large-latest
423
- api_key: ${MISTRAL_API_KEY}
424
- ```
505
+ ---
425
506
 
426
507
  ## Project Structure
427
508
 
428
509
  ```
429
510
  your-project/
430
511
  ├── .slapify/
431
- │ ├── config.yaml
432
- │ ├── credentials.yaml
433
- │ └── .gitignore
512
+ │ ├── config.yaml # LLM + browser + report settings
513
+ │ ├── credentials.yaml # Saved login profiles
514
+ │ └── tasks/ # Persisted agent sessions (auto-created)
515
+ │ └── task-2026-....jsonl
434
516
  ├── tests/
435
517
  │ ├── auth/
436
518
  │ │ ├── login.flow
437
519
  │ │ └── signup.flow
438
- ├── checkout/
439
- │ │ └── purchase.flow
440
- │ └── smoke.flow
441
- └── test-reports/
520
+ └── checkout.flow
521
+ └── test-reports/ # HTML reports
442
522
  └── login-1234567890/
443
523
  ├── report.html
444
- └── screenshots...
524
+ └── screenshots/
445
525
  ```
446
526
 
527
+ ---
528
+
447
529
  ## Requirements
448
530
 
449
531
  - Node.js 18+
450
- - `agent-browser` (installed automatically)
532
+ - `agent-browser` (installed as a peer dependency)
533
+
534
+ ---
451
535
 
452
536
  ## License
453
537