@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.
Files changed (102) hide show
  1. package/README.md +2 -2
  2. package/dist/brain/index.d.ts +2 -0
  3. package/dist/brain/index.d.ts.map +1 -1
  4. package/dist/brain/index.js +96 -10
  5. package/dist/brain/index.js.map +1 -1
  6. package/dist/browser-launch.d.ts +3 -0
  7. package/dist/browser-launch.d.ts.map +1 -1
  8. package/dist/browser-launch.js +12 -2
  9. package/dist/browser-launch.js.map +1 -1
  10. package/dist/cli-design-audit.d.ts.map +1 -1
  11. package/dist/cli-design-audit.js +250 -2
  12. package/dist/cli-design-audit.js.map +1 -1
  13. package/dist/cli-showcase.d.ts +28 -0
  14. package/dist/cli-showcase.d.ts.map +1 -0
  15. package/dist/cli-showcase.js +131 -0
  16. package/dist/cli-showcase.js.map +1 -0
  17. package/dist/cli-ui.d.ts.map +1 -1
  18. package/dist/cli-ui.js +35 -2
  19. package/dist/cli-ui.js.map +1 -1
  20. package/dist/cli.js +462 -217
  21. package/dist/cli.js.map +1 -1
  22. package/dist/config.d.ts +5 -1
  23. package/dist/config.d.ts.map +1 -1
  24. package/dist/config.js +3 -2
  25. package/dist/config.js.map +1 -1
  26. package/dist/design/compare.d.ts +9 -0
  27. package/dist/design/compare.d.ts.map +1 -0
  28. package/dist/design/compare.js +339 -0
  29. package/dist/design/compare.js.map +1 -0
  30. package/dist/design/index.d.ts +6 -0
  31. package/dist/design/index.d.ts.map +1 -0
  32. package/dist/design/index.js +5 -0
  33. package/dist/design/index.js.map +1 -0
  34. package/dist/design/page-interaction.d.ts +24 -0
  35. package/dist/design/page-interaction.d.ts.map +1 -0
  36. package/dist/design/page-interaction.js +244 -0
  37. package/dist/design/page-interaction.js.map +1 -0
  38. package/dist/design/rip.d.ts +9 -0
  39. package/dist/design/rip.d.ts.map +1 -0
  40. package/dist/design/rip.js +362 -0
  41. package/dist/design/rip.js.map +1 -0
  42. package/dist/design/types.d.ts +126 -0
  43. package/dist/design/types.d.ts.map +1 -0
  44. package/dist/design/types.js +3 -0
  45. package/dist/design/types.js.map +1 -0
  46. package/dist/design-audit.js +2 -2
  47. package/dist/design-audit.js.map +1 -1
  48. package/dist/index.d.ts +10 -4
  49. package/dist/index.d.ts.map +1 -1
  50. package/dist/index.js +6 -1
  51. package/dist/index.js.map +1 -1
  52. package/dist/memory/knowledge.d.ts +25 -9
  53. package/dist/memory/knowledge.d.ts.map +1 -1
  54. package/dist/memory/knowledge.js +94 -28
  55. package/dist/memory/knowledge.js.map +1 -1
  56. package/dist/memory/run-registry.d.ts +85 -0
  57. package/dist/memory/run-registry.d.ts.map +1 -0
  58. package/dist/memory/run-registry.js +144 -0
  59. package/dist/memory/run-registry.js.map +1 -0
  60. package/dist/multi-actor.d.ts +3 -3
  61. package/dist/multi-actor.d.ts.map +1 -1
  62. package/dist/multi-actor.js +3 -3
  63. package/dist/multi-actor.js.map +1 -1
  64. package/dist/runner/index.d.ts +2 -2
  65. package/dist/runner/index.d.ts.map +1 -1
  66. package/dist/runner/index.js +1 -1
  67. package/dist/runner/index.js.map +1 -1
  68. package/dist/runner/runner.d.ts +9 -5
  69. package/dist/runner/runner.d.ts.map +1 -1
  70. package/dist/runner/runner.js +95 -22
  71. package/dist/runner/runner.js.map +1 -1
  72. package/dist/runner.d.ts +2 -2
  73. package/dist/runner.d.ts.map +1 -1
  74. package/dist/runner.js +1 -1
  75. package/dist/runner.js.map +1 -1
  76. package/dist/showcase/annotate.d.ts +28 -0
  77. package/dist/showcase/annotate.d.ts.map +1 -0
  78. package/dist/showcase/annotate.js +95 -0
  79. package/dist/showcase/annotate.js.map +1 -0
  80. package/dist/showcase/assemble.d.ts +31 -0
  81. package/dist/showcase/assemble.d.ts.map +1 -0
  82. package/dist/showcase/assemble.js +107 -0
  83. package/dist/showcase/assemble.js.map +1 -0
  84. package/dist/showcase/demo-player.d.ts +53 -0
  85. package/dist/showcase/demo-player.d.ts.map +1 -0
  86. package/dist/showcase/demo-player.js +325 -0
  87. package/dist/showcase/demo-player.js.map +1 -0
  88. package/dist/showcase/index.d.ts +21 -0
  89. package/dist/showcase/index.d.ts.map +1 -0
  90. package/dist/showcase/index.js +289 -0
  91. package/dist/showcase/index.js.map +1 -0
  92. package/dist/showcase/types.d.ts +111 -0
  93. package/dist/showcase/types.d.ts.map +1 -0
  94. package/dist/showcase/types.js +3 -0
  95. package/dist/showcase/types.js.map +1 -0
  96. package/dist/test-runner.d.ts +1 -0
  97. package/dist/test-runner.d.ts.map +1 -1
  98. package/dist/test-runner.js +26 -2
  99. package/dist/test-runner.js.map +1 -1
  100. package/dist/types.d.ts +32 -0
  101. package/dist/types.d.ts.map +1 -1
  102. 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":"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"}
@@ -0,0 +1,3 @@
1
+ /** Types for the `bad showcase` walkthrough capture system. */
2
+ export {};
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/showcase/types.ts"],"names":[],"mappings":"AAAA,+DAA+D"}
@@ -56,6 +56,7 @@ export declare class TestRunner {
56
56
  private stopOnFailure;
57
57
  private store;
58
58
  private projectStore?;
59
+ private runRegistry?;
59
60
  private feedbackHints;
60
61
  private screenshotInterval;
61
62
  private analyzer;
@@ -1 +1 @@
1
- {"version":3,"file":"test-runner.d.ts","sourceRoot":"","sources":["../src/test-runner.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"test-runner.d.ts","sourceRoot":"","sources":["../src/test-runner.ts"],"names":[],"mappings":"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"}
@@ -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 { AgentRunner } from './runner.js';
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 AgentRunner({
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',