@tangle-network/browser-agent-driver 0.8.7 → 0.11.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 +2 -2
- package/dist/brain/index.d.ts +2 -0
- package/dist/brain/index.d.ts.map +1 -1
- package/dist/brain/index.js +96 -10
- package/dist/brain/index.js.map +1 -1
- package/dist/browser-launch.d.ts +3 -0
- package/dist/browser-launch.d.ts.map +1 -1
- package/dist/browser-launch.js +12 -2
- package/dist/browser-launch.js.map +1 -1
- package/dist/cli-design-audit.d.ts.map +1 -1
- package/dist/cli-design-audit.js +250 -2
- package/dist/cli-design-audit.js.map +1 -1
- package/dist/cli-showcase.d.ts +28 -0
- package/dist/cli-showcase.d.ts.map +1 -0
- package/dist/cli-showcase.js +131 -0
- package/dist/cli-showcase.js.map +1 -0
- package/dist/cli-ui.d.ts.map +1 -1
- package/dist/cli-ui.js +35 -2
- package/dist/cli-ui.js.map +1 -1
- package/dist/cli.js +462 -217
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +5 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +3 -2
- package/dist/config.js.map +1 -1
- package/dist/design/compare.d.ts +9 -0
- package/dist/design/compare.d.ts.map +1 -0
- package/dist/design/compare.js +339 -0
- package/dist/design/compare.js.map +1 -0
- package/dist/design/index.d.ts +6 -0
- package/dist/design/index.d.ts.map +1 -0
- package/dist/design/index.js +5 -0
- package/dist/design/index.js.map +1 -0
- package/dist/design/page-interaction.d.ts +24 -0
- package/dist/design/page-interaction.d.ts.map +1 -0
- package/dist/design/page-interaction.js +244 -0
- package/dist/design/page-interaction.js.map +1 -0
- package/dist/design/rip.d.ts +9 -0
- package/dist/design/rip.d.ts.map +1 -0
- package/dist/design/rip.js +362 -0
- package/dist/design/rip.js.map +1 -0
- package/dist/design/types.d.ts +126 -0
- package/dist/design/types.d.ts.map +1 -0
- package/dist/design/types.js +3 -0
- package/dist/design/types.js.map +1 -0
- package/dist/design-audit.js +2 -2
- package/dist/design-audit.js.map +1 -1
- package/dist/index.d.ts +10 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -1
- package/dist/index.js.map +1 -1
- package/dist/memory/knowledge.d.ts +25 -9
- package/dist/memory/knowledge.d.ts.map +1 -1
- package/dist/memory/knowledge.js +94 -28
- package/dist/memory/knowledge.js.map +1 -1
- package/dist/memory/run-registry.d.ts +85 -0
- package/dist/memory/run-registry.d.ts.map +1 -0
- package/dist/memory/run-registry.js +144 -0
- package/dist/memory/run-registry.js.map +1 -0
- package/dist/multi-actor.d.ts +3 -3
- package/dist/multi-actor.d.ts.map +1 -1
- package/dist/multi-actor.js +3 -3
- package/dist/multi-actor.js.map +1 -1
- package/dist/runner/index.d.ts +2 -2
- package/dist/runner/index.d.ts.map +1 -1
- package/dist/runner/index.js +1 -1
- package/dist/runner/index.js.map +1 -1
- package/dist/runner/runner.d.ts +9 -5
- package/dist/runner/runner.d.ts.map +1 -1
- package/dist/runner/runner.js +95 -22
- package/dist/runner/runner.js.map +1 -1
- package/dist/runner.d.ts +2 -2
- package/dist/runner.d.ts.map +1 -1
- package/dist/runner.js +1 -1
- package/dist/runner.js.map +1 -1
- package/dist/showcase/annotate.d.ts +28 -0
- package/dist/showcase/annotate.d.ts.map +1 -0
- package/dist/showcase/annotate.js +95 -0
- package/dist/showcase/annotate.js.map +1 -0
- package/dist/showcase/assemble.d.ts +31 -0
- package/dist/showcase/assemble.d.ts.map +1 -0
- package/dist/showcase/assemble.js +107 -0
- package/dist/showcase/assemble.js.map +1 -0
- package/dist/showcase/demo-player.d.ts +53 -0
- package/dist/showcase/demo-player.d.ts.map +1 -0
- package/dist/showcase/demo-player.js +325 -0
- package/dist/showcase/demo-player.js.map +1 -0
- package/dist/showcase/index.d.ts +21 -0
- package/dist/showcase/index.d.ts.map +1 -0
- package/dist/showcase/index.js +289 -0
- package/dist/showcase/index.js.map +1 -0
- package/dist/showcase/types.d.ts +111 -0
- package/dist/showcase/types.d.ts.map +1 -0
- package/dist/showcase/types.js +3 -0
- package/dist/showcase/types.js.map +1 -0
- package/dist/test-runner.d.ts +1 -0
- package/dist/test-runner.d.ts.map +1 -1
- package/dist/test-runner.js +26 -2
- package/dist/test-runner.js.map +1 -1
- package/dist/types.d.ts +32 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +11 -1
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Showcase — deterministic walkthrough capture for marketing assets.
|
|
3
|
+
*
|
|
4
|
+
* Unlike `bad run` (LLM-driven exploration) or `bad design-audit` (quality assessment),
|
|
5
|
+
* showcase executes a pre-scripted walkthrough and captures polished screenshots,
|
|
6
|
+
* GIFs, and videos. No LLM calls. No quality judgement. Just beautiful captures.
|
|
7
|
+
*
|
|
8
|
+
* Reuses:
|
|
9
|
+
* - page-interaction.ts: dismissModals() for cookie/popup cleanup
|
|
10
|
+
* - browser-launch.ts: buildBrowserLaunchPlan() for consistent browser config
|
|
11
|
+
* - cli-ui.ts: CliRenderer for progress output
|
|
12
|
+
*/
|
|
13
|
+
import * as fs from 'node:fs';
|
|
14
|
+
import * as path from 'node:path';
|
|
15
|
+
import { chromium } from 'playwright';
|
|
16
|
+
import { captureWithHighlight, captureWithCrop } from './annotate.js';
|
|
17
|
+
import { assembleGif } from './assemble.js';
|
|
18
|
+
import { revealHiddenContent } from '../design/page-interaction.js';
|
|
19
|
+
// ── Main Entry ──
|
|
20
|
+
export async function runShowcase(config) {
|
|
21
|
+
const startTime = Date.now();
|
|
22
|
+
const outputDir = config.output?.dir ?? './showcase';
|
|
23
|
+
const scale = config.output?.scale ?? 2;
|
|
24
|
+
const formats = config.output?.formats ?? ['png'];
|
|
25
|
+
const quality = config.output?.quality ?? 90;
|
|
26
|
+
fs.mkdirSync(outputDir, { recursive: true });
|
|
27
|
+
const viewport = config.viewport ?? { width: 1440, height: 900 };
|
|
28
|
+
const browser = await chromium.launch({ headless: config.headless ?? true });
|
|
29
|
+
const context = await browser.newContext({
|
|
30
|
+
viewport,
|
|
31
|
+
deviceScaleFactor: scale,
|
|
32
|
+
colorScheme: config.colorScheme,
|
|
33
|
+
storageState: config.storageState ? JSON.parse(fs.readFileSync(config.storageState, 'utf-8')) : undefined,
|
|
34
|
+
// Record video if webm format requested
|
|
35
|
+
...(formats.includes('webm') ? { recordVideo: { dir: path.join(outputDir, '_video'), size: viewport } } : {}),
|
|
36
|
+
});
|
|
37
|
+
const page = await context.newPage();
|
|
38
|
+
const frames = [];
|
|
39
|
+
// Dismiss modals/cookie banners before starting
|
|
40
|
+
if (config.dismissModals !== false) {
|
|
41
|
+
await page.goto(config.url, { waitUntil: 'networkidle', timeout: 30_000 }).catch(() => page.goto(config.url, { waitUntil: 'domcontentloaded', timeout: 30_000 }));
|
|
42
|
+
await page.waitForTimeout(1500);
|
|
43
|
+
// Dismiss modals/cookie banners — reuses design/page-interaction.ts
|
|
44
|
+
await revealHiddenContent(page).catch(() => null);
|
|
45
|
+
}
|
|
46
|
+
// Execute steps
|
|
47
|
+
for (let i = 0; i < config.steps.length; i++) {
|
|
48
|
+
const step = config.steps[i];
|
|
49
|
+
await executeStep(page, step);
|
|
50
|
+
if (step.capture) {
|
|
51
|
+
const frame = await captureFrame(page, step.capture, i, { quality });
|
|
52
|
+
if (frame) {
|
|
53
|
+
const framePath = path.join(outputDir, `${frame.name}.png`);
|
|
54
|
+
fs.writeFileSync(framePath, frame.buffer);
|
|
55
|
+
frames.push(frame);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// Generate interactive demo HTML if requested
|
|
60
|
+
let demoPath;
|
|
61
|
+
if (formats.includes('demo')) {
|
|
62
|
+
const { buildDemoSteps, generateDemoHtml } = await import('./demo-player.js');
|
|
63
|
+
// Build demo steps — hotspot calculation is best-effort
|
|
64
|
+
// Try to navigate back for element positions, but don't fail if it errors
|
|
65
|
+
let demoPage;
|
|
66
|
+
try {
|
|
67
|
+
await page.goto(config.url, { waitUntil: 'domcontentloaded', timeout: 10_000 });
|
|
68
|
+
await page.waitForTimeout(1000);
|
|
69
|
+
demoPage = page;
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
// Can't navigate back — build demo without hotspots
|
|
73
|
+
}
|
|
74
|
+
const demoSteps = await buildDemoSteps(outputDir, config.steps, demoPage);
|
|
75
|
+
const demoHtml = generateDemoHtml({
|
|
76
|
+
title: config.name.replace(/-/g, ' ').replace(/\b\w/g, c => c.toUpperCase()),
|
|
77
|
+
steps: demoSteps,
|
|
78
|
+
});
|
|
79
|
+
demoPath = path.join(outputDir, `${config.name}-demo.html`);
|
|
80
|
+
fs.writeFileSync(demoPath, demoHtml);
|
|
81
|
+
}
|
|
82
|
+
// Assemble GIF if requested
|
|
83
|
+
let gifPath;
|
|
84
|
+
if (formats.includes('gif') && frames.length > 1) {
|
|
85
|
+
gifPath = path.join(outputDir, `${config.name}.gif`);
|
|
86
|
+
const ok = assembleGif(frames, gifPath, { fps: 1, maxWidth: viewport.width });
|
|
87
|
+
if (!ok)
|
|
88
|
+
gifPath = undefined;
|
|
89
|
+
}
|
|
90
|
+
// Get video recording path if available
|
|
91
|
+
let videoPath;
|
|
92
|
+
if (formats.includes('webm')) {
|
|
93
|
+
await page.close(); // Must close page to flush video
|
|
94
|
+
const videoFile = await context.pages()[0]?.video()?.path().catch(() => undefined);
|
|
95
|
+
// Page already closed, try getting video from context
|
|
96
|
+
// Video is written on context.close()
|
|
97
|
+
await context.close();
|
|
98
|
+
const videoDir = path.join(outputDir, '_video');
|
|
99
|
+
if (fs.existsSync(videoDir)) {
|
|
100
|
+
const vids = fs.readdirSync(videoDir).filter(f => f.endsWith('.webm'));
|
|
101
|
+
if (vids.length) {
|
|
102
|
+
videoPath = path.join(outputDir, `${config.name}.webm`);
|
|
103
|
+
fs.renameSync(path.join(videoDir, vids[0]), videoPath);
|
|
104
|
+
fs.rmSync(videoDir, { recursive: true, force: true });
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
await context.close();
|
|
110
|
+
}
|
|
111
|
+
await browser.close();
|
|
112
|
+
// Convert to WebP if requested
|
|
113
|
+
if (formats.includes('webp')) {
|
|
114
|
+
for (const frame of frames) {
|
|
115
|
+
const pngPath = path.join(outputDir, `${frame.name}.png`);
|
|
116
|
+
// Playwright can't export webp directly from buffer,
|
|
117
|
+
// but we keep the PNG — webp conversion would need sharp or ffmpeg
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return {
|
|
121
|
+
name: config.name,
|
|
122
|
+
outputDir,
|
|
123
|
+
frames: frames.map((f) => ({
|
|
124
|
+
name: f.name,
|
|
125
|
+
path: path.join(outputDir, `${f.name}.png`),
|
|
126
|
+
width: f.width,
|
|
127
|
+
height: f.height,
|
|
128
|
+
step: f.step,
|
|
129
|
+
})),
|
|
130
|
+
gif: gifPath,
|
|
131
|
+
video: videoPath,
|
|
132
|
+
demo: demoPath,
|
|
133
|
+
durationMs: Date.now() - startTime,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
// ── Quick Capture ──
|
|
137
|
+
/**
|
|
138
|
+
* Quick capture mode — no script file needed.
|
|
139
|
+
* Captures named positions: 'hero' (viewport), 'full' (full page), 'scroll:N' (scroll N px first).
|
|
140
|
+
*/
|
|
141
|
+
export async function quickCapture(config) {
|
|
142
|
+
const steps = [
|
|
143
|
+
{ action: 'navigate', url: config.url },
|
|
144
|
+
];
|
|
145
|
+
for (const capture of config.captures) {
|
|
146
|
+
if (capture === 'hero') {
|
|
147
|
+
steps.push({
|
|
148
|
+
action: 'screenshot',
|
|
149
|
+
capture: {
|
|
150
|
+
name: 'hero',
|
|
151
|
+
fullPage: false,
|
|
152
|
+
crop: config.cropSelector ? { selector: config.cropSelector, padding: 16 } : undefined,
|
|
153
|
+
highlight: config.highlightSelector ? { selector: config.highlightSelector } : undefined,
|
|
154
|
+
},
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
else if (capture === 'full') {
|
|
158
|
+
steps.push({
|
|
159
|
+
action: 'screenshot',
|
|
160
|
+
capture: { name: 'full-page', fullPage: true },
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
else if (capture.startsWith('scroll:')) {
|
|
164
|
+
const amount = parseInt(capture.split(':')[1], 10);
|
|
165
|
+
steps.push({ action: 'scroll', amount }, {
|
|
166
|
+
action: 'screenshot',
|
|
167
|
+
capture: {
|
|
168
|
+
name: `scroll-${amount}`,
|
|
169
|
+
fullPage: false,
|
|
170
|
+
crop: config.cropSelector ? { selector: config.cropSelector, padding: 16 } : undefined,
|
|
171
|
+
},
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
else if (capture === 'footer') {
|
|
175
|
+
steps.push({ action: 'scroll', amount: 99999 }, { action: 'screenshot', capture: { name: 'footer', fullPage: false } });
|
|
176
|
+
}
|
|
177
|
+
else {
|
|
178
|
+
// Treat as a section name — try scrolling to an element with that id or class
|
|
179
|
+
steps.push({ action: 'screenshot', capture: { name: capture, fullPage: false } });
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return runShowcase({
|
|
183
|
+
name: 'quick-capture',
|
|
184
|
+
url: config.url,
|
|
185
|
+
steps,
|
|
186
|
+
viewport: config.viewport,
|
|
187
|
+
output: config.output,
|
|
188
|
+
headless: config.headless,
|
|
189
|
+
storageState: config.storageState,
|
|
190
|
+
colorScheme: config.colorScheme,
|
|
191
|
+
dismissModals: config.dismissModals,
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
// ── Internals ──
|
|
195
|
+
async function executeStep(page, step) {
|
|
196
|
+
switch (step.action) {
|
|
197
|
+
case 'navigate':
|
|
198
|
+
if (step.url) {
|
|
199
|
+
await page.goto(step.url, { waitUntil: 'networkidle', timeout: 30_000 }).catch(() => page.goto(step.url, { waitUntil: 'domcontentloaded', timeout: 30_000 }));
|
|
200
|
+
await page.waitForTimeout(1500);
|
|
201
|
+
}
|
|
202
|
+
break;
|
|
203
|
+
case 'click':
|
|
204
|
+
if (step.selector) {
|
|
205
|
+
const el = page.locator(step.selector).first();
|
|
206
|
+
await el.click({ timeout: 5_000 }).catch(() => {
|
|
207
|
+
// Fallback: try force click
|
|
208
|
+
return el.click({ force: true, timeout: 3_000 }).catch(() => null);
|
|
209
|
+
});
|
|
210
|
+
await page.waitForTimeout(500);
|
|
211
|
+
}
|
|
212
|
+
break;
|
|
213
|
+
case 'type':
|
|
214
|
+
if (step.selector && step.text) {
|
|
215
|
+
const el = page.locator(step.selector).first();
|
|
216
|
+
await el.click({ timeout: 3_000 }).catch(() => null);
|
|
217
|
+
await el.fill(step.text);
|
|
218
|
+
await page.waitForTimeout(300);
|
|
219
|
+
}
|
|
220
|
+
break;
|
|
221
|
+
case 'scroll':
|
|
222
|
+
const amount = step.amount ?? 500;
|
|
223
|
+
const dir = step.direction === 'up' ? -1 : 1;
|
|
224
|
+
await page.evaluate((px) => window.scrollBy(0, px), amount * dir);
|
|
225
|
+
await page.waitForTimeout(500);
|
|
226
|
+
break;
|
|
227
|
+
case 'wait':
|
|
228
|
+
await page.waitForTimeout(step.amount ?? 1000);
|
|
229
|
+
break;
|
|
230
|
+
case 'hover':
|
|
231
|
+
if (step.selector) {
|
|
232
|
+
await page.locator(step.selector).first().hover({ timeout: 3_000 }).catch(() => null);
|
|
233
|
+
await page.waitForTimeout(300);
|
|
234
|
+
}
|
|
235
|
+
break;
|
|
236
|
+
case 'screenshot':
|
|
237
|
+
// Screenshot-only step — capture handled by caller
|
|
238
|
+
break;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
async function captureFrame(page, capture, stepIndex, opts) {
|
|
242
|
+
// Wait for animations to settle
|
|
243
|
+
if (capture.delay) {
|
|
244
|
+
await page.waitForTimeout(capture.delay);
|
|
245
|
+
}
|
|
246
|
+
let buffer;
|
|
247
|
+
if (capture.highlight) {
|
|
248
|
+
// Capture with highlight overlay
|
|
249
|
+
buffer = await captureWithHighlight(page, {
|
|
250
|
+
selector: capture.highlight.selector,
|
|
251
|
+
color: capture.highlight.color,
|
|
252
|
+
label: capture.highlight.label,
|
|
253
|
+
fullPage: capture.fullPage,
|
|
254
|
+
quality: opts.quality,
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
else if (capture.crop) {
|
|
258
|
+
// Capture cropped to element
|
|
259
|
+
const cropped = await captureWithCrop(page, {
|
|
260
|
+
selector: capture.crop.selector,
|
|
261
|
+
padding: capture.crop.padding,
|
|
262
|
+
quality: opts.quality,
|
|
263
|
+
});
|
|
264
|
+
if (!cropped) {
|
|
265
|
+
// Fallback: full viewport
|
|
266
|
+
buffer = await page.screenshot({ type: 'png', fullPage: false });
|
|
267
|
+
}
|
|
268
|
+
else {
|
|
269
|
+
buffer = cropped;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
else {
|
|
273
|
+
// Standard capture
|
|
274
|
+
buffer = await page.screenshot({
|
|
275
|
+
type: 'png',
|
|
276
|
+
fullPage: capture.fullPage ?? false,
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
// Get dimensions from viewport (actual pixel dimensions depend on scale factor)
|
|
280
|
+
const viewport = page.viewportSize();
|
|
281
|
+
return {
|
|
282
|
+
name: capture.name,
|
|
283
|
+
buffer,
|
|
284
|
+
width: viewport?.width ?? 1440,
|
|
285
|
+
height: viewport?.height ?? 900,
|
|
286
|
+
step: stepIndex,
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/showcase/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/** Types for the `bad showcase` walkthrough capture system. */
|
|
2
|
+
export type ShowcaseAction = 'navigate' | 'click' | 'type' | 'scroll' | 'wait' | 'hover' | 'screenshot';
|
|
3
|
+
export interface CaptureConfig {
|
|
4
|
+
/** Output filename stem (no extension). */
|
|
5
|
+
name: string;
|
|
6
|
+
/** Capture full page or viewport only. Default: false (viewport). */
|
|
7
|
+
fullPage?: boolean;
|
|
8
|
+
/** Crop to a specific element. */
|
|
9
|
+
crop?: {
|
|
10
|
+
selector: string;
|
|
11
|
+
/** Padding in px around the element bounding box. Default: 0. */
|
|
12
|
+
padding?: number;
|
|
13
|
+
};
|
|
14
|
+
/** Draw a highlight rectangle on an element. */
|
|
15
|
+
highlight?: {
|
|
16
|
+
selector: string;
|
|
17
|
+
/** CSS color. Default: rgba(142, 89, 255, 0.5). */
|
|
18
|
+
color?: string;
|
|
19
|
+
/** Optional text label above the highlight. */
|
|
20
|
+
label?: string;
|
|
21
|
+
};
|
|
22
|
+
/** Delay in ms before capture (let animations settle). Default: 0. */
|
|
23
|
+
delay?: number;
|
|
24
|
+
}
|
|
25
|
+
export interface ShowcaseStep {
|
|
26
|
+
action: ShowcaseAction;
|
|
27
|
+
/** CSS selector (for click, type, hover). */
|
|
28
|
+
selector?: string;
|
|
29
|
+
/** Text to type (for type action). */
|
|
30
|
+
text?: string;
|
|
31
|
+
/** URL (for navigate action). */
|
|
32
|
+
url?: string;
|
|
33
|
+
/** Pixels to scroll (scroll action) or ms to wait (wait action). */
|
|
34
|
+
amount?: number;
|
|
35
|
+
/** Scroll direction. Default: 'down'. */
|
|
36
|
+
direction?: 'up' | 'down';
|
|
37
|
+
/** Capture a screenshot after this step completes. */
|
|
38
|
+
capture?: CaptureConfig;
|
|
39
|
+
}
|
|
40
|
+
export interface ShowcaseConfig {
|
|
41
|
+
/** Human name for this showcase (used in output directory). */
|
|
42
|
+
name: string;
|
|
43
|
+
/** Starting URL. */
|
|
44
|
+
url: string;
|
|
45
|
+
/** Browser viewport. Default: { width: 1440, height: 900 }. */
|
|
46
|
+
viewport?: {
|
|
47
|
+
width: number;
|
|
48
|
+
height: number;
|
|
49
|
+
};
|
|
50
|
+
/** Ordered steps to execute. */
|
|
51
|
+
steps: ShowcaseStep[];
|
|
52
|
+
/** Output options. */
|
|
53
|
+
output?: {
|
|
54
|
+
dir?: string;
|
|
55
|
+
/** Which formats to generate. Default: ['png']. */
|
|
56
|
+
formats?: Array<'png' | 'webp' | 'gif' | 'webm' | 'demo'>;
|
|
57
|
+
/** Image quality 1-100. Default: 90. */
|
|
58
|
+
quality?: number;
|
|
59
|
+
/** Device scale factor. Default: 2 (retina). */
|
|
60
|
+
scale?: number;
|
|
61
|
+
};
|
|
62
|
+
/** Run headless. Default: true. */
|
|
63
|
+
headless?: boolean;
|
|
64
|
+
/** Playwright storage state for auth. */
|
|
65
|
+
storageState?: string;
|
|
66
|
+
/** Force color scheme. */
|
|
67
|
+
colorScheme?: 'dark' | 'light';
|
|
68
|
+
/** Dismiss cookie banners and modals before starting. Default: true. */
|
|
69
|
+
dismissModals?: boolean;
|
|
70
|
+
}
|
|
71
|
+
export interface QuickCaptureConfig {
|
|
72
|
+
url: string;
|
|
73
|
+
/** Named capture positions. 'hero' = viewport, 'full' = full page, 'scroll:N' = scroll N px. */
|
|
74
|
+
captures: string[];
|
|
75
|
+
/** Crop all captures to this element. */
|
|
76
|
+
cropSelector?: string;
|
|
77
|
+
/** Highlight this element in all captures. */
|
|
78
|
+
highlightSelector?: string;
|
|
79
|
+
viewport?: {
|
|
80
|
+
width: number;
|
|
81
|
+
height: number;
|
|
82
|
+
};
|
|
83
|
+
output?: ShowcaseConfig['output'];
|
|
84
|
+
headless?: boolean;
|
|
85
|
+
storageState?: string;
|
|
86
|
+
colorScheme?: 'dark' | 'light';
|
|
87
|
+
dismissModals?: boolean;
|
|
88
|
+
}
|
|
89
|
+
export interface ShowcaseFrame {
|
|
90
|
+
name: string;
|
|
91
|
+
buffer: Buffer;
|
|
92
|
+
width: number;
|
|
93
|
+
height: number;
|
|
94
|
+
step: number;
|
|
95
|
+
}
|
|
96
|
+
export interface ShowcaseResult {
|
|
97
|
+
name: string;
|
|
98
|
+
outputDir: string;
|
|
99
|
+
frames: Array<{
|
|
100
|
+
name: string;
|
|
101
|
+
path: string;
|
|
102
|
+
width: number;
|
|
103
|
+
height: number;
|
|
104
|
+
step: number;
|
|
105
|
+
}>;
|
|
106
|
+
gif?: string;
|
|
107
|
+
video?: string;
|
|
108
|
+
demo?: string;
|
|
109
|
+
durationMs: number;
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/showcase/types.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAI/D,MAAM,MAAM,cAAc,GAAG,UAAU,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,YAAY,CAAA;AAEvG,MAAM,WAAW,aAAa;IAC5B,2CAA2C;IAC3C,IAAI,EAAE,MAAM,CAAA;IACZ,qEAAqE;IACrE,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,kCAAkC;IAClC,IAAI,CAAC,EAAE;QACL,QAAQ,EAAE,MAAM,CAAA;QAChB,iEAAiE;QACjE,OAAO,CAAC,EAAE,MAAM,CAAA;KACjB,CAAA;IACD,gDAAgD;IAChD,SAAS,CAAC,EAAE;QACV,QAAQ,EAAE,MAAM,CAAA;QAChB,mDAAmD;QACnD,KAAK,CAAC,EAAE,MAAM,CAAA;QACd,+CAA+C;QAC/C,KAAK,CAAC,EAAE,MAAM,CAAA;KACf,CAAA;IACD,sEAAsE;IACtE,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,cAAc,CAAA;IACtB,6CAA6C;IAC7C,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,sCAAsC;IACtC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,iCAAiC;IACjC,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,oEAAoE;IACpE,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,yCAAyC;IACzC,SAAS,CAAC,EAAE,IAAI,GAAG,MAAM,CAAA;IACzB,sDAAsD;IACtD,OAAO,CAAC,EAAE,aAAa,CAAA;CACxB;AAID,MAAM,WAAW,cAAc;IAC7B,+DAA+D;IAC/D,IAAI,EAAE,MAAM,CAAA;IACZ,oBAAoB;IACpB,GAAG,EAAE,MAAM,CAAA;IACX,+DAA+D;IAC/D,QAAQ,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;IAC5C,gCAAgC;IAChC,KAAK,EAAE,YAAY,EAAE,CAAA;IACrB,sBAAsB;IACtB,MAAM,CAAC,EAAE;QACP,GAAG,CAAC,EAAE,MAAM,CAAA;QACZ,mDAAmD;QACnD,OAAO,CAAC,EAAE,KAAK,CAAC,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,CAAC,CAAA;QACzD,wCAAwC;QACxC,OAAO,CAAC,EAAE,MAAM,CAAA;QAChB,gDAAgD;QAChD,KAAK,CAAC,EAAE,MAAM,CAAA;KACf,CAAA;IACD,mCAAmC;IACnC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,yCAAyC;IACzC,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,0BAA0B;IAC1B,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;IAC9B,wEAAwE;IACxE,aAAa,CAAC,EAAE,OAAO,CAAA;CACxB;AAID,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,MAAM,CAAA;IACX,gGAAgG;IAChG,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB,yCAAyC;IACzC,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,8CAA8C;IAC9C,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;IAC5C,MAAM,CAAC,EAAE,cAAc,CAAC,QAAQ,CAAC,CAAA;IACjC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;IAC9B,aAAa,CAAC,EAAE,OAAO,CAAA;CACxB;AAID,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;CACb;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,KAAK,CAAC;QACZ,IAAI,EAAE,MAAM,CAAA;QACZ,IAAI,EAAE,MAAM,CAAA;QACZ,KAAK,EAAE,MAAM,CAAA;QACb,MAAM,EAAE,MAAM,CAAA;QACd,IAAI,EAAE,MAAM,CAAA;KACb,CAAC,CAAA;IACF,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,UAAU,EAAE,MAAM,CAAA;CACnB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/showcase/types.ts"],"names":[],"mappings":"AAAA,+DAA+D"}
|
package/dist/test-runner.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test-runner.d.ts","sourceRoot":"","sources":["../src/test-runner.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,KAAK,EACV,QAAQ,EACR,UAAU,EACV,eAAe,EAGf,WAAW,EAEX,IAAI,EACL,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAIxE,OAAO,EAAsB,KAAK,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAC5E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"test-runner.d.ts","sourceRoot":"","sources":["../src/test-runner.ts"],"names":[],"mappings":"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"}
|
package/dist/test-runner.js
CHANGED
|
@@ -7,11 +7,12 @@
|
|
|
7
7
|
import { existsSync, readFileSync, unlinkSync } from 'node:fs';
|
|
8
8
|
import { tmpdir } from 'node:os';
|
|
9
9
|
import { join } from 'node:path';
|
|
10
|
-
import {
|
|
10
|
+
import { BrowserAgent } from './runner.js';
|
|
11
11
|
import { Brain } from './brain/index.js';
|
|
12
12
|
import { TrajectoryStore } from './memory/store.js';
|
|
13
13
|
import { TrajectoryAnalyzer } from './memory/analyzer.js';
|
|
14
14
|
import { AppKnowledge } from './memory/knowledge.js';
|
|
15
|
+
import { RunRegistry } from './memory/run-registry.js';
|
|
15
16
|
import { generateReport } from './test-report.js';
|
|
16
17
|
const DEFAULT_MAX_TURNS = 30;
|
|
17
18
|
import { loadPricing, calculateCost } from './model-pricing.js';
|
|
@@ -53,6 +54,7 @@ export class TestRunner {
|
|
|
53
54
|
stopOnFailure;
|
|
54
55
|
store;
|
|
55
56
|
projectStore;
|
|
57
|
+
runRegistry;
|
|
56
58
|
feedbackHints;
|
|
57
59
|
screenshotInterval;
|
|
58
60
|
analyzer;
|
|
@@ -74,6 +76,7 @@ export class TestRunner {
|
|
|
74
76
|
this.concurrency = options.concurrency ?? 1;
|
|
75
77
|
this.stopOnFailure = options.stopOnFailure ?? false;
|
|
76
78
|
this.projectStore = options.projectStore;
|
|
79
|
+
this.runRegistry = options.projectStore ? new RunRegistry(options.projectStore.getRoot()) : undefined;
|
|
77
80
|
this.store = options.enableMemory
|
|
78
81
|
? new TrajectoryStore(options.trajectoryStorePath, {
|
|
79
82
|
enableScoring: this.config.traceScoring === true,
|
|
@@ -133,11 +136,12 @@ export class TestRunner {
|
|
|
133
136
|
? `${combinedReference}\n\n${this.feedbackHints}`
|
|
134
137
|
: this.feedbackHints;
|
|
135
138
|
}
|
|
136
|
-
const runner = new
|
|
139
|
+
const runner = new BrowserAgent({
|
|
137
140
|
driver: activeDriver,
|
|
138
141
|
config: this.config,
|
|
139
142
|
referenceTrajectory: combinedReference,
|
|
140
143
|
projectStore: this.projectStore,
|
|
144
|
+
runRegistry: this.runRegistry,
|
|
141
145
|
onTurn: (turn) => {
|
|
142
146
|
if (timeToFirstTurnMs === undefined) {
|
|
143
147
|
timeToFirstTurnMs = Math.max(0, Date.now() - runStartedAtMs);
|
|
@@ -200,6 +204,8 @@ export class TestRunner {
|
|
|
200
204
|
allowedDomains: testCase.allowedDomains,
|
|
201
205
|
maxTurns: testCase.maxTurns ?? DEFAULT_MAX_TURNS,
|
|
202
206
|
signal: combinedSignal,
|
|
207
|
+
sessionId: testCase.sessionId,
|
|
208
|
+
parentRunId: testCase.parentRunId,
|
|
203
209
|
});
|
|
204
210
|
let agentResult;
|
|
205
211
|
if (timeoutMs && timeoutMs > 0 && timeoutAbortController) {
|
|
@@ -312,6 +318,24 @@ export class TestRunner {
|
|
|
312
318
|
// Video capture is best-effort
|
|
313
319
|
}
|
|
314
320
|
}
|
|
321
|
+
// Update run manifest with artifact paths from the sink
|
|
322
|
+
if (this.runRegistry && this.artifactSink) {
|
|
323
|
+
const manifest = this.artifactSink.getManifest();
|
|
324
|
+
const testArtifacts = manifest
|
|
325
|
+
.filter(e => e.testId === testCase.id)
|
|
326
|
+
.map(e => e.uri);
|
|
327
|
+
if (testArtifacts.length > 0) {
|
|
328
|
+
// Find the matching run manifest by sessionId or recent domain runs
|
|
329
|
+
const runs = this.runRegistry.listRuns({
|
|
330
|
+
sessionId: testCase.sessionId,
|
|
331
|
+
status: 'completed',
|
|
332
|
+
limit: 1,
|
|
333
|
+
});
|
|
334
|
+
if (runs.length > 0) {
|
|
335
|
+
this.runRegistry.updateRun(runs[0].runId, { artifactPaths: testArtifacts });
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
}
|
|
315
339
|
this.onTestComplete?.(result);
|
|
316
340
|
this.onProgress?.({
|
|
317
341
|
type: 'test:complete',
|