testchimp-runner-core 0.0.21 → 0.0.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/VISION_DIAGNOSTICS_IMPROVEMENTS.md +336 -0
- package/dist/credit-usage-service.d.ts +9 -0
- package/dist/credit-usage-service.d.ts.map +1 -1
- package/dist/credit-usage-service.js +20 -5
- package/dist/credit-usage-service.js.map +1 -1
- package/dist/execution-service.d.ts +7 -2
- package/dist/execution-service.d.ts.map +1 -1
- package/dist/execution-service.js +91 -36
- package/dist/execution-service.js.map +1 -1
- package/dist/index.d.ts +30 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +91 -26
- package/dist/index.js.map +1 -1
- package/dist/llm-facade.d.ts +64 -8
- package/dist/llm-facade.d.ts.map +1 -1
- package/dist/llm-facade.js +361 -109
- package/dist/llm-facade.js.map +1 -1
- package/dist/llm-provider.d.ts +39 -0
- package/dist/llm-provider.d.ts.map +1 -0
- package/dist/llm-provider.js +7 -0
- package/dist/llm-provider.js.map +1 -0
- package/dist/model-constants.d.ts +21 -0
- package/dist/model-constants.d.ts.map +1 -0
- package/dist/model-constants.js +24 -0
- package/dist/model-constants.js.map +1 -0
- package/dist/orchestrator/index.d.ts +8 -0
- package/dist/orchestrator/index.d.ts.map +1 -0
- package/dist/orchestrator/index.js +23 -0
- package/dist/orchestrator/index.js.map +1 -0
- package/dist/orchestrator/orchestrator-agent.d.ts +66 -0
- package/dist/orchestrator/orchestrator-agent.d.ts.map +1 -0
- package/dist/orchestrator/orchestrator-agent.js +855 -0
- package/dist/orchestrator/orchestrator-agent.js.map +1 -0
- package/dist/orchestrator/tool-registry.d.ts +74 -0
- package/dist/orchestrator/tool-registry.d.ts.map +1 -0
- package/dist/orchestrator/tool-registry.js +131 -0
- package/dist/orchestrator/tool-registry.js.map +1 -0
- package/dist/orchestrator/tools/check-page-ready.d.ts +13 -0
- package/dist/orchestrator/tools/check-page-ready.d.ts.map +1 -0
- package/dist/orchestrator/tools/check-page-ready.js +72 -0
- package/dist/orchestrator/tools/check-page-ready.js.map +1 -0
- package/dist/orchestrator/tools/extract-data.d.ts +13 -0
- package/dist/orchestrator/tools/extract-data.d.ts.map +1 -0
- package/dist/orchestrator/tools/extract-data.js +84 -0
- package/dist/orchestrator/tools/extract-data.js.map +1 -0
- package/dist/orchestrator/tools/index.d.ts +10 -0
- package/dist/orchestrator/tools/index.d.ts.map +1 -0
- package/dist/orchestrator/tools/index.js +18 -0
- package/dist/orchestrator/tools/index.js.map +1 -0
- package/dist/orchestrator/tools/inspect-page.d.ts +13 -0
- package/dist/orchestrator/tools/inspect-page.d.ts.map +1 -0
- package/dist/orchestrator/tools/inspect-page.js +39 -0
- package/dist/orchestrator/tools/inspect-page.js.map +1 -0
- package/dist/orchestrator/tools/recall-history.d.ts +13 -0
- package/dist/orchestrator/tools/recall-history.d.ts.map +1 -0
- package/dist/orchestrator/tools/recall-history.js +64 -0
- package/dist/orchestrator/tools/recall-history.js.map +1 -0
- package/dist/orchestrator/tools/take-screenshot.d.ts +15 -0
- package/dist/orchestrator/tools/take-screenshot.d.ts.map +1 -0
- package/dist/orchestrator/tools/take-screenshot.js +112 -0
- package/dist/orchestrator/tools/take-screenshot.js.map +1 -0
- package/dist/orchestrator/types.d.ts +133 -0
- package/dist/orchestrator/types.d.ts.map +1 -0
- package/dist/orchestrator/types.js +28 -0
- package/dist/orchestrator/types.js.map +1 -0
- package/dist/playwright-mcp-service.d.ts +9 -0
- package/dist/playwright-mcp-service.d.ts.map +1 -1
- package/dist/playwright-mcp-service.js +20 -5
- package/dist/playwright-mcp-service.js.map +1 -1
- package/dist/progress-reporter.d.ts +97 -0
- package/dist/progress-reporter.d.ts.map +1 -0
- package/dist/progress-reporter.js +18 -0
- package/dist/progress-reporter.js.map +1 -0
- package/dist/prompts.d.ts +24 -0
- package/dist/prompts.d.ts.map +1 -1
- package/dist/prompts.js +593 -68
- package/dist/prompts.js.map +1 -1
- package/dist/providers/backend-proxy-llm-provider.d.ts +25 -0
- package/dist/providers/backend-proxy-llm-provider.d.ts.map +1 -0
- package/dist/providers/backend-proxy-llm-provider.js +76 -0
- package/dist/providers/backend-proxy-llm-provider.js.map +1 -0
- package/dist/providers/local-llm-provider.d.ts +21 -0
- package/dist/providers/local-llm-provider.d.ts.map +1 -0
- package/dist/providers/local-llm-provider.js +35 -0
- package/dist/providers/local-llm-provider.js.map +1 -0
- package/dist/scenario-service.d.ts +27 -1
- package/dist/scenario-service.d.ts.map +1 -1
- package/dist/scenario-service.js +48 -12
- package/dist/scenario-service.js.map +1 -1
- package/dist/scenario-worker-class.d.ts +39 -2
- package/dist/scenario-worker-class.d.ts.map +1 -1
- package/dist/scenario-worker-class.js +614 -86
- package/dist/scenario-worker-class.js.map +1 -1
- package/dist/script-utils.d.ts +2 -0
- package/dist/script-utils.d.ts.map +1 -1
- package/dist/script-utils.js +44 -4
- package/dist/script-utils.js.map +1 -1
- package/dist/types.d.ts +11 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/utils/browser-utils.d.ts +20 -1
- package/dist/utils/browser-utils.d.ts.map +1 -1
- package/dist/utils/browser-utils.js +102 -51
- package/dist/utils/browser-utils.js.map +1 -1
- package/dist/utils/page-info-utils.d.ts +23 -4
- package/dist/utils/page-info-utils.d.ts.map +1 -1
- package/dist/utils/page-info-utils.js +174 -43
- package/dist/utils/page-info-utils.js.map +1 -1
- package/package.json +1 -2
- package/plandocs/HUMAN_LIKE_IMPROVEMENTS.md +642 -0
- package/plandocs/MULTI_AGENT_ARCHITECTURE_REVIEW.md +844 -0
- package/plandocs/ORCHESTRATOR_MVP_SUMMARY.md +539 -0
- package/plandocs/PHASE1_ABSTRACTION_COMPLETE.md +241 -0
- package/plandocs/PHASE1_FINAL_STATUS.md +210 -0
- package/plandocs/PLANNING_SESSION_SUMMARY.md +372 -0
- package/plandocs/SCRIPT_CLEANUP_FEATURE.md +201 -0
- package/plandocs/SCRIPT_GENERATION_ARCHITECTURE.md +364 -0
- package/plandocs/SELECTOR_IMPROVEMENTS.md +139 -0
- package/src/credit-usage-service.ts +23 -5
- package/src/execution-service.ts +152 -42
- package/src/index.ts +169 -26
- package/src/llm-facade.ts +500 -126
- package/src/llm-provider.ts +43 -0
- package/src/model-constants.ts +23 -0
- package/src/orchestrator/index.ts +33 -0
- package/src/orchestrator/orchestrator-agent.ts +1037 -0
- package/src/orchestrator/tool-registry.ts +182 -0
- package/src/orchestrator/tools/check-page-ready.ts +75 -0
- package/src/orchestrator/tools/extract-data.ts +92 -0
- package/src/orchestrator/tools/index.ts +11 -0
- package/src/orchestrator/tools/inspect-page.ts +42 -0
- package/src/orchestrator/tools/recall-history.ts +72 -0
- package/src/orchestrator/tools/take-screenshot.ts +128 -0
- package/src/orchestrator/types.ts +200 -0
- package/src/playwright-mcp-service.ts +23 -5
- package/src/progress-reporter.ts +109 -0
- package/src/prompts.ts +606 -69
- package/src/providers/backend-proxy-llm-provider.ts +91 -0
- package/src/providers/local-llm-provider.ts +38 -0
- package/src/scenario-service.ts +83 -13
- package/src/scenario-worker-class.ts +740 -72
- package/src/script-utils.ts +50 -5
- package/src/types.ts +13 -1
- package/src/utils/browser-utils.ts +123 -51
- package/src/utils/page-info-utils.ts +210 -53
- package/testchimp-runner-core-0.0.22.tgz +0 -0
|
@@ -1,93 +1,250 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Enhanced Page Info Utilities
|
|
3
|
+
* Extracts ARIA tree, interactive elements with bounding boxes, and suggested selectors
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export interface InteractiveElement {
|
|
7
|
+
tag: string;
|
|
8
|
+
id: string | null;
|
|
9
|
+
text: string;
|
|
10
|
+
type: string;
|
|
11
|
+
role: string;
|
|
12
|
+
ariaLabel: string;
|
|
13
|
+
placeholder: string;
|
|
14
|
+
bbox: {x: number; y: number; width: number; height: number};
|
|
15
|
+
selectors: string[];
|
|
16
|
+
}
|
|
2
17
|
|
|
3
18
|
export interface PageInfo {
|
|
4
19
|
url: string;
|
|
5
20
|
title: string;
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
pageStructure: string;
|
|
21
|
+
ariaSnapshot: any; // Raw ARIA tree for hierarchical structure
|
|
22
|
+
interactiveElements: InteractiveElement[]; // All interactive elements with position and selectors
|
|
23
|
+
formattedElements: string; // Human-readable summary for logging
|
|
10
24
|
}
|
|
11
25
|
|
|
12
26
|
export async function getEnhancedPageInfo(page: any): Promise<PageInfo>;
|
|
13
27
|
export async function getEnhancedPageInfo(domSnapshot: { url: string; title: string; accessibilityTree: any }): Promise<PageInfo>;
|
|
14
28
|
export async function getEnhancedPageInfo(input: any | { url: string; title: string; accessibilityTree: any }): Promise<PageInfo> {
|
|
15
29
|
let domSnapshot: { url: string; title: string; accessibilityTree: any } = { url: 'Unknown', title: 'Unknown', accessibilityTree: null };
|
|
30
|
+
let interactiveElements: InteractiveElement[] = [];
|
|
31
|
+
let hasPageObject = false;
|
|
16
32
|
|
|
17
33
|
try {
|
|
18
34
|
if ('accessibility' in input) {
|
|
19
35
|
// Input is a Page object
|
|
36
|
+
hasPageObject = true;
|
|
20
37
|
const snapshot = await input.accessibility.snapshot();
|
|
21
38
|
const url = input.url();
|
|
22
39
|
const title = await input.title();
|
|
23
40
|
domSnapshot = { url, title, accessibilityTree: snapshot };
|
|
41
|
+
|
|
42
|
+
// Extract ALL interactive elements with bounding boxes and selectors
|
|
43
|
+
try {
|
|
44
|
+
interactiveElements = await input.evaluate(() => {
|
|
45
|
+
const doc = (globalThis as any).document;
|
|
46
|
+
const elements: any[] = [];
|
|
47
|
+
|
|
48
|
+
// Get all interactive elements
|
|
49
|
+
const interactiveSelectors = [
|
|
50
|
+
'button',
|
|
51
|
+
'input',
|
|
52
|
+
'textarea',
|
|
53
|
+
'select',
|
|
54
|
+
'a[href]',
|
|
55
|
+
'[role="button"]',
|
|
56
|
+
'[role="link"]',
|
|
57
|
+
'[role="textbox"]',
|
|
58
|
+
'[role="checkbox"]',
|
|
59
|
+
'[role="radio"]',
|
|
60
|
+
'[onclick]'
|
|
61
|
+
];
|
|
62
|
+
|
|
63
|
+
const allInteractive = new Set<any>();
|
|
64
|
+
interactiveSelectors.forEach((selector: string) => {
|
|
65
|
+
doc.querySelectorAll(selector).forEach((el: any) => allInteractive.add(el));
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
allInteractive.forEach((el: any) => {
|
|
69
|
+
const rect = el.getBoundingClientRect();
|
|
70
|
+
|
|
71
|
+
// Skip invisible elements
|
|
72
|
+
if (rect.width === 0 || rect.height === 0) return;
|
|
73
|
+
|
|
74
|
+
const id = el.id || null;
|
|
75
|
+
const tag = el.tagName.toLowerCase();
|
|
76
|
+
const text = el.textContent?.trim().substring(0, 40) || '';
|
|
77
|
+
const type = el.type || '';
|
|
78
|
+
const role = el.getAttribute('role') || el.tagName.toLowerCase();
|
|
79
|
+
const ariaLabel = el.getAttribute('aria-label') || '';
|
|
80
|
+
const placeholder = el.placeholder || '';
|
|
81
|
+
|
|
82
|
+
// Build possible selectors - PRIORITIZE SEMANTIC SELECTORS (Playwright best practices)
|
|
83
|
+
const selectors: string[] = [];
|
|
84
|
+
|
|
85
|
+
// 1. BEST: getByLabel for form inputs with associated labels
|
|
86
|
+
if ((tag === 'input' || tag === 'textarea' || tag === 'select') && el.labels && el.labels.length > 0) {
|
|
87
|
+
const labelText = el.labels[0].textContent?.trim();
|
|
88
|
+
if (labelText && labelText.length > 0 && labelText.length < 50) {
|
|
89
|
+
selectors.push(`getByLabel('${labelText}')`);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// 2. BEST: getByRole with name (semantic and accessible)
|
|
94
|
+
if (text && text.length > 0 && text.length < 30) {
|
|
95
|
+
selectors.push(`getByRole('${role}', {name: '${text}'})`);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// 3. BEST: getByPlaceholder for inputs with placeholders
|
|
99
|
+
if (placeholder && placeholder.length > 0 && placeholder.length < 50) {
|
|
100
|
+
selectors.push(`getByPlaceholder('${placeholder}')`);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// 4. GOOD: getByText for elements with visible text (fallback for non-role elements)
|
|
104
|
+
if (text && text.length > 0 && text.length < 30 && !selectors.some(s => s.includes('getByRole'))) {
|
|
105
|
+
selectors.push(`getByText('${text}')`);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// 5. GOOD: data-testid attributes (stable, explicit)
|
|
109
|
+
const dataTestId = el.getAttribute('data-testid') || el.getAttribute('data-test-id') ||
|
|
110
|
+
el.getAttribute('data-id') || el.getAttribute('data-test');
|
|
111
|
+
if (dataTestId) selectors.push(`getByTestId('${dataTestId}')`);
|
|
112
|
+
|
|
113
|
+
// 6. LAST RESORT: ID selector (only if stable - avoid auto-generated IDs with unicode)
|
|
114
|
+
// Skip auto-generated Ant Design IDs like «r3»-form-item or rc_select_xxx
|
|
115
|
+
if (id && !id.includes('«') && !id.match(/^(rc_|:r[0-9]+:|__)/)) {
|
|
116
|
+
selectors.push(`#${id}`);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
elements.push({
|
|
120
|
+
tag,
|
|
121
|
+
id,
|
|
122
|
+
text,
|
|
123
|
+
type,
|
|
124
|
+
role,
|
|
125
|
+
ariaLabel,
|
|
126
|
+
placeholder,
|
|
127
|
+
bbox: {
|
|
128
|
+
x: Math.round(rect.x),
|
|
129
|
+
y: Math.round(rect.y),
|
|
130
|
+
width: Math.round(rect.width),
|
|
131
|
+
height: Math.round(rect.height)
|
|
132
|
+
},
|
|
133
|
+
selectors
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
return elements;
|
|
138
|
+
});
|
|
139
|
+
} catch (evalError: any) {
|
|
140
|
+
// Error extracting interactive elements - continue with empty array
|
|
141
|
+
console.error('[getEnhancedPageInfo] Failed to extract interactive elements:', evalError.message);
|
|
142
|
+
interactiveElements = [];
|
|
143
|
+
}
|
|
24
144
|
} else {
|
|
25
145
|
// Input is already a domSnapshot
|
|
26
146
|
domSnapshot = input;
|
|
27
147
|
}
|
|
28
148
|
|
|
29
|
-
//
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
149
|
+
// Log extraction results for debugging
|
|
150
|
+
if (hasPageObject) {
|
|
151
|
+
console.log(`[getEnhancedPageInfo] Extracted ${interactiveElements.length} interactive elements from ${domSnapshot.url}`);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Create smart summary prioritizing important elements over repetitive lists
|
|
155
|
+
let formattedElements = '';
|
|
156
|
+
|
|
157
|
+
if (interactiveElements.length > 0) {
|
|
158
|
+
// Prioritize: forms/buttons > unique elements > list items
|
|
159
|
+
const prioritized: InteractiveElement[] = [];
|
|
160
|
+
const listItems: InteractiveElement[] = [];
|
|
37
161
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
162
|
+
// Group elements
|
|
163
|
+
for (const el of interactiveElements) {
|
|
164
|
+
// High priority: forms, buttons, unique interactive elements
|
|
165
|
+
if (['input', 'textarea', 'select', 'button'].includes(el.tag) ||
|
|
166
|
+
(el.tag === 'a' && el.text.length > 0 && el.text.length < 50)) {
|
|
167
|
+
prioritized.push(el);
|
|
168
|
+
} else {
|
|
169
|
+
listItems.push(el);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Take top 25 prioritized
|
|
174
|
+
const selectedElements = prioritized.slice(0, 25);
|
|
175
|
+
|
|
176
|
+
// Add sample of list items if space remains (show diversity, not just first N)
|
|
177
|
+
if (selectedElements.length < 30 && listItems.length > 0) {
|
|
178
|
+
const step = Math.max(1, Math.floor(listItems.length / 5)); // Sample 5 from list
|
|
179
|
+
for (let i = 0; i < Math.min(5, listItems.length); i++) {
|
|
180
|
+
selectedElements.push(listItems[i * step]);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
formattedElements = selectedElements.map((e, i) => {
|
|
185
|
+
const idInfo = e.id ? `#${e.id}` : 'NO-ID';
|
|
186
|
+
const typeInfo = e.type ? ` type="${e.type}"` : '';
|
|
187
|
+
const placeholderInfo = e.placeholder ? ` placeholder="${e.placeholder}"` : '';
|
|
188
|
+
|
|
189
|
+
// Show BEST selector first, with alternatives
|
|
190
|
+
let selectorsInfo: string;
|
|
191
|
+
if (e.selectors && e.selectors.length > 0) {
|
|
192
|
+
selectorsInfo = e.selectors[0]; // Best option
|
|
193
|
+
if (e.selectors.length > 1) {
|
|
194
|
+
selectorsInfo += ` (or: ${e.selectors.slice(1, 3).join(', ')})`; // Show up to 2 alternatives
|
|
50
195
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
196
|
+
} else {
|
|
197
|
+
selectorsInfo = 'No reliable selector available';
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
return `${i + 1}. [${e.bbox.x},${e.bbox.y} ${e.bbox.width}x${e.bbox.height}] <${e.tag}> ${idInfo}${typeInfo}${placeholderInfo} "${e.text}"
|
|
201
|
+
→ ${selectorsInfo}`;
|
|
202
|
+
}).join('\n');
|
|
203
|
+
|
|
204
|
+
// Show stats for omitted elements
|
|
205
|
+
const omitted = interactiveElements.length - selectedElements.length;
|
|
206
|
+
if (omitted > 0) {
|
|
207
|
+
formattedElements += `\n\n... (+${omitted} more elements)`;
|
|
208
|
+
|
|
209
|
+
// Show pattern summary for lists/tables
|
|
210
|
+
const linkCount = interactiveElements.filter(e => e.tag === 'a').length;
|
|
211
|
+
const listItemPatterns: Record<string, number> = {};
|
|
212
|
+
|
|
213
|
+
for (const el of interactiveElements) {
|
|
214
|
+
if (el.tag === 'a' || el.tag === 'li' || el.tag === 'div') {
|
|
215
|
+
const pattern = `${el.tag}${el.role ? `[${el.role}]` : ''}`;
|
|
216
|
+
listItemPatterns[pattern] = (listItemPatterns[pattern] || 0) + 1;
|
|
54
217
|
}
|
|
55
218
|
}
|
|
56
|
-
|
|
57
|
-
if (
|
|
58
|
-
|
|
219
|
+
|
|
220
|
+
if (Object.keys(listItemPatterns).length > 0) {
|
|
221
|
+
formattedElements += `\nPattern summary: `;
|
|
222
|
+
formattedElements += Object.entries(listItemPatterns)
|
|
223
|
+
.filter(([_, count]) => count > 5)
|
|
224
|
+
.map(([pattern, count]) => `${count}x ${pattern}`)
|
|
225
|
+
.join(', ');
|
|
59
226
|
}
|
|
60
227
|
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
// Create a more focused summary
|
|
66
|
-
const getElementSummary = (elementList: string[], maxItems: number, category: string) => {
|
|
67
|
-
if (elementList.length === 0) return `No ${category} found`;
|
|
68
|
-
const limited = elementList.slice(0, maxItems);
|
|
69
|
-
const remaining = elementList.length - maxItems;
|
|
70
|
-
const summary = limited.join(', ');
|
|
71
|
-
return remaining > 0 ? `${summary} (+${remaining} more)` : summary;
|
|
72
|
-
};
|
|
228
|
+
} else {
|
|
229
|
+
formattedElements = 'No interactive elements found (page may not be loaded or extraction failed)';
|
|
230
|
+
}
|
|
73
231
|
|
|
74
232
|
return {
|
|
75
233
|
url: domSnapshot.url,
|
|
76
234
|
title: domSnapshot.title,
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
pageStructure: getElementSummary(pageStructure, 6, 'page sections')
|
|
235
|
+
ariaSnapshot: domSnapshot.accessibilityTree,
|
|
236
|
+
interactiveElements,
|
|
237
|
+
formattedElements
|
|
81
238
|
};
|
|
82
|
-
} catch (error) {
|
|
83
|
-
|
|
239
|
+
} catch (error: any) {
|
|
240
|
+
// Error extracting page info - return defaults
|
|
241
|
+
console.error('[getEnhancedPageInfo] Top-level error:', error.message);
|
|
84
242
|
return {
|
|
85
243
|
url: domSnapshot?.url || 'Unknown',
|
|
86
244
|
title: 'Unknown',
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
pageStructure: 'Unable to extract'
|
|
245
|
+
ariaSnapshot: null,
|
|
246
|
+
interactiveElements: [],
|
|
247
|
+
formattedElements: `Unable to extract: ${error.message}`
|
|
91
248
|
};
|
|
92
249
|
}
|
|
93
250
|
}
|
|
Binary file
|