teamshare-bridge 0.26.11 → 0.26.13

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 (49) hide show
  1. package/dist/bridge/local-server.js +6 -10
  2. package/dist/bridge/local-server.js.map +1 -1
  3. package/dist/cli/commands/research.js +15 -0
  4. package/dist/cli/commands/research.js.map +1 -1
  5. package/dist/lib/browser/batch.d.ts +47 -2
  6. package/dist/lib/browser/batch.js +48 -5
  7. package/dist/lib/browser/batch.js.map +1 -1
  8. package/dist/lib/browser/browse-cdp.js +5 -1
  9. package/dist/lib/browser/browse-cdp.js.map +1 -1
  10. package/dist/lib/browser/browse-editor.js +8 -0
  11. package/dist/lib/browser/browse-editor.js.map +1 -1
  12. package/dist/lib/browser/cdp.d.ts +2 -0
  13. package/dist/lib/browser/cdp.js +8 -0
  14. package/dist/lib/browser/cdp.js.map +1 -1
  15. package/dist/lib/browser/index.d.ts +3 -1
  16. package/dist/lib/browser/index.js +12 -1
  17. package/dist/lib/browser/index.js.map +1 -1
  18. package/dist/lib/browser/login.d.ts +67 -25
  19. package/dist/lib/browser/login.js +681 -174
  20. package/dist/lib/browser/login.js.map +1 -1
  21. package/dist/lib/browser/manager.d.ts +26 -0
  22. package/dist/lib/browser/manager.js +48 -0
  23. package/dist/lib/browser/manager.js.map +1 -1
  24. package/dist/lib/browser/network-log.d.ts +9 -0
  25. package/dist/lib/browser/network-log.js +21 -0
  26. package/dist/lib/browser/network-log.js.map +1 -1
  27. package/dist/lib/browser/page-context.d.ts +176 -0
  28. package/dist/lib/browser/page-context.js +637 -0
  29. package/dist/lib/browser/page-context.js.map +1 -0
  30. package/dist/lib/browser/page-events.d.ts +39 -0
  31. package/dist/lib/browser/page-events.js +128 -0
  32. package/dist/lib/browser/page-events.js.map +1 -0
  33. package/dist/lib/browser/screen-change.js +3 -0
  34. package/dist/lib/browser/screen-change.js.map +1 -1
  35. package/dist/lib/browser/session-pool.d.ts +44 -0
  36. package/dist/lib/browser/session-pool.js +128 -0
  37. package/dist/lib/browser/session-pool.js.map +1 -0
  38. package/dist/lib/browser/session.d.ts +115 -1
  39. package/dist/lib/browser/session.js +355 -2
  40. package/dist/lib/browser/session.js.map +1 -1
  41. package/dist/lib/config.js +25 -4
  42. package/dist/lib/config.js.map +1 -1
  43. package/dist/lib/orchestrator/handlers/browser.js +283 -40
  44. package/dist/lib/orchestrator/handlers/browser.js.map +1 -1
  45. package/dist/lib/tools/browser-tool.d.ts +2 -2
  46. package/dist/lib/tools/browser-tool.js +58 -19
  47. package/dist/lib/tools/browser-tool.js.map +1 -1
  48. package/package.json +1 -1
  49. package/templates/common/AGENTS.md.tpl +19 -19
@@ -0,0 +1,637 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DEFAULT_TEXT_CAP = exports.MAX_TOASTS = exports.MAX_ERRORS = exports.MAX_DIALOGS = exports.MAX_FIELDS = exports.WAIT_FOR_VALUES = exports.PAGE_ERROR_SELECTORS = void 0;
4
+ exports.buildPageStateScript = buildPageStateScript;
5
+ exports.readPageState = readPageState;
6
+ exports.compactPageState = compactPageState;
7
+ exports.buildCompactStateScript = buildCompactStateScript;
8
+ exports.readCompactState = readCompactState;
9
+ exports.renderPageStateText = renderPageStateText;
10
+ exports.buildWaitProbeScript = buildWaitProbeScript;
11
+ exports.emptyPageSnapshot = emptyPageSnapshot;
12
+ /**
13
+ * Rich page state for the debug/MCP browser (2026-10).
14
+ *
15
+ * The auto-answer loop already extracts title/URL/headings/errors/toasts/full
16
+ * text (`extractPageContext` in browse-editor.ts). The debug browser had only a
17
+ * flat text read, so a QA agent could not SEE a login dialog, its buttons, its
18
+ * field state, a toast that had already disappeared, or the validation error
19
+ * that explained a failed submit. In the live Soludesks run that cost five
20
+ * minutes of raw `evaluate` calls and still ended on the wrong page.
21
+ *
22
+ * This module is the shared, structured equivalent: one in-page script returns
23
+ * a JSON-safe `PageState` with the topmost dialog, its buttons and fields,
24
+ * visible errors, the persistent toast buffer (page-events.ts), headings,
25
+ * focus, busy state and optional page text. `compactPageState` is the bounded
26
+ * version attached to ordinary action results.
27
+ *
28
+ * Rules:
29
+ * - NEVER return a field VALUE - only `valueLength` (a password must not
30
+ * travel through a tool result).
31
+ * - The topmost open dialog is the interaction scope. Page fields behind a
32
+ * modal are not offered as primary targets.
33
+ * - Everything is capped so one snapshot cannot balloon a tool response.
34
+ */
35
+ const cdp_1 = require("./cdp");
36
+ const DEFAULT_TEXT_CAP = 12_000;
37
+ exports.DEFAULT_TEXT_CAP = DEFAULT_TEXT_CAP;
38
+ const MAX_FIELDS = 40;
39
+ exports.MAX_FIELDS = MAX_FIELDS;
40
+ const MAX_DIALOGS = 8;
41
+ exports.MAX_DIALOGS = MAX_DIALOGS;
42
+ const MAX_ERRORS = 8;
43
+ exports.MAX_ERRORS = MAX_ERRORS;
44
+ const MAX_TOASTS = 10;
45
+ exports.MAX_TOASTS = MAX_TOASTS;
46
+ /**
47
+ * Selectors that surface user-visible errors/alerts/validation messages.
48
+ * Deliberately broad (sites use every naming scheme) but every match is
49
+ * length-capped and deduped by the page script.
50
+ */
51
+ exports.PAGE_ERROR_SELECTORS = [
52
+ '[role="alert"]',
53
+ '[role="status"]',
54
+ '[aria-invalid="true"]',
55
+ '[class*="error"]',
56
+ '[class*="Error"]',
57
+ '[class*="danger"]',
58
+ '[class*="warning"]',
59
+ '[class*="invalid"]',
60
+ '[class*="field-error"]',
61
+ '[class*="form-error"]',
62
+ '[class*="validation-error"]',
63
+ '[class*="error-message"]',
64
+ '.text-red',
65
+ '.text-danger',
66
+ '.text-error',
67
+ '[data-sonner-toast]',
68
+ ].join(',');
69
+ /**
70
+ * Build the in-page state script. `includeText` and `maxTextChars` are the only
71
+ * variable parts; the rest is fixed and capped inside the page.
72
+ */
73
+ function buildPageStateScript(opts = {}) {
74
+ const includeText = opts.includeText !== false;
75
+ const maxText = Math.min(Math.max(Number(opts.maxTextChars) || DEFAULT_TEXT_CAP, 500), 40_000);
76
+ const maxFields = Math.min(Math.max(Number(opts.maxFields) || MAX_FIELDS, 1), 100);
77
+ const errorSelectors = JSON.stringify(exports.PAGE_ERROR_SELECTORS);
78
+ return `
79
+ (() => {
80
+ const MAX_TEXT = ${maxText};
81
+ const MAX_FIELDS = ${maxFields};
82
+ const MAX_DIALOGS = ${MAX_DIALOGS};
83
+ const MAX_ERRORS = ${MAX_ERRORS};
84
+ const MAX_TOASTS = ${MAX_TOASTS};
85
+ const INCLUDE_TEXT = ${includeText ? 'true' : 'false'};
86
+ const ERROR_SEL = ${errorSelectors};
87
+
88
+ const clean = (v, cap) => String(v == null ? '' : v)
89
+ .replace(/\\s+/g, ' ')
90
+ .trim()
91
+ .slice(0, cap || 300);
92
+ const vis = (el) => {
93
+ if (!el || el.nodeType !== 1) return false;
94
+ const r = el.getBoundingClientRect();
95
+ if (r.width === 0 || r.height === 0) return false;
96
+ const cs = getComputedStyle(el);
97
+ return cs.visibility !== 'hidden' && cs.display !== 'none' && cs.opacity !== '0';
98
+ };
99
+ const rect = (el) => {
100
+ const r = el.getBoundingClientRect();
101
+ return {
102
+ x: Math.round(r.x + r.width / 2),
103
+ y: Math.round(r.y + r.height / 2),
104
+ width: Math.round(r.width),
105
+ height: Math.round(r.height),
106
+ };
107
+ };
108
+ const labelOf = (el) => {
109
+ const aria = el.getAttribute('aria-label');
110
+ if (aria) return clean(aria, 120);
111
+ const by = el.getAttribute('aria-labelledby');
112
+ if (by) {
113
+ const t = by.split(/\\s+/).map((id) => {
114
+ const n = document.getElementById(id);
115
+ return n ? (n.innerText || n.textContent || '') : '';
116
+ }).join(' ');
117
+ if (t.trim()) return clean(t, 120);
118
+ }
119
+ const id = el.id;
120
+ if (id) {
121
+ try {
122
+ const l = document.querySelector('label[for="' + CSS.escape(id) + '"]');
123
+ if (l) return clean(l.innerText || l.textContent, 120);
124
+ } catch (e) {}
125
+ }
126
+ const wrap = el.closest && el.closest('label');
127
+ if (wrap) return clean(wrap.innerText || wrap.textContent, 120);
128
+ return clean(el.getAttribute('placeholder') || el.getAttribute('name') || el.id || '', 120);
129
+ };
130
+ const fieldOf = (el, inDialog) => {
131
+ const r = rect(el);
132
+ const type = String(el.type || el.tagName || '').toLowerCase();
133
+ const valueLength = typeof el.value === 'string' ? el.value.length : 0;
134
+ const invalid = el.getAttribute('aria-invalid') === 'true' ||
135
+ (typeof el.checkValidity === 'function' && !el.checkValidity() && valueLength > 0);
136
+ return {
137
+ tag: String(el.tagName || '').toLowerCase(),
138
+ type: type,
139
+ label: labelOf(el),
140
+ name: clean(el.getAttribute('name') || el.id || '', 80),
141
+ autocomplete: clean(el.getAttribute('autocomplete') || '', 60),
142
+ valueLength: valueLength,
143
+ required: el.required === true,
144
+ invalid: invalid,
145
+ disabled: el.disabled === true,
146
+ readonly: el.readOnly === true,
147
+ focused: document.activeElement === el,
148
+ inDialog: !!inDialog,
149
+ x: r.x,
150
+ y: r.y,
151
+ };
152
+ };
153
+ const buttonOf = (el) => {
154
+ const r = rect(el);
155
+ return {
156
+ text: clean(el.innerText || el.textContent || el.value || el.getAttribute('aria-label') || '', 100),
157
+ type: clean(el.getAttribute('type') || el.tagName || '', 30).toLowerCase(),
158
+ disabled: el.disabled === true || el.getAttribute('aria-disabled') === 'true',
159
+ x: r.x,
160
+ y: r.y,
161
+ };
162
+ };
163
+ const zOf = (el) => {
164
+ let z = 0;
165
+ let n = el;
166
+ let guard = 0;
167
+ while (n && n !== document.body && guard++ < 8) {
168
+ const cs = getComputedStyle(n);
169
+ const v = parseInt(cs.zIndex, 10);
170
+ if (!isNaN(v)) z = Math.max(z, v);
171
+ n = n.parentElement;
172
+ }
173
+ return z;
174
+ };
175
+ const dialogSel = 'dialog[open],[role="dialog"],[aria-modal="true"],' +
176
+ '[class*="modal"],[class*="Modal"],[class*="dialog"],[class*="Dialog"]';
177
+ const dialogEls = [...document.querySelectorAll(dialogSel)]
178
+ .filter(vis)
179
+ .slice(0, MAX_DIALOGS);
180
+ const dialogs = dialogEls.map((el, index) => {
181
+ const title =
182
+ clean(el.getAttribute('aria-label') || '', 120) ||
183
+ (() => {
184
+ const by = el.getAttribute('aria-labelledby');
185
+ if (by) {
186
+ const t = by.split(/\\s+/).map((id) => {
187
+ const n = document.getElementById(id);
188
+ return n ? (n.innerText || n.textContent || '') : '';
189
+ }).join(' ');
190
+ if (t.trim()) return clean(t, 120);
191
+ }
192
+ const h = el.querySelector('h1,h2,h3,[class*="title"],[class*="Title"]');
193
+ return h ? clean(h.innerText || h.textContent, 120) : '';
194
+ })();
195
+ const r = rect(el);
196
+ return {
197
+ index: index,
198
+ role: clean(el.getAttribute('role') || (el.tagName || '').toLowerCase(), 30),
199
+ title: title,
200
+ text: clean(el.innerText || el.textContent || '', 1600),
201
+ z: zOf(el),
202
+ x: r.x,
203
+ y: r.y,
204
+ width: r.width,
205
+ height: r.height,
206
+ fields: [...el.querySelectorAll('input,textarea,select')]
207
+ .filter(vis)
208
+ .filter((f) => String(f.type || '').toLowerCase() !== 'hidden')
209
+ .slice(0, MAX_FIELDS)
210
+ .map((f) => fieldOf(f, true)),
211
+ buttons: [...el.querySelectorAll('button,input[type="submit"],input[type="button"],[role="button"],a')]
212
+ .filter(vis)
213
+ .slice(0, 20)
214
+ .map(buttonOf),
215
+ };
216
+ }).sort((a, b) => (a.z - b.z) || (a.index - b.index));
217
+ // Prefer the dialog that actually holds a login field: a cookie banner
218
+ // or a newsletter modal can have a higher z-index, but it is not what
219
+ // the agent is interacting with.
220
+ const loginTop = [...dialogs].reverse().find((d) =>
221
+ d.fields.some(
222
+ (f) =>
223
+ f.type === 'password' ||
224
+ f.type === 'email' ||
225
+ /username|one-time-code|current-password|new-password/.test(
226
+ f.autocomplete || '',
227
+ ),
228
+ ),
229
+ );
230
+ const top = loginTop ?? (dialogs.length ? dialogs[dialogs.length - 1] : null);
231
+ const topEl = dialogEls[top ? top.index : -1] || null;
232
+ const scope = topEl || document;
233
+
234
+ const fields = (top ? top.fields : [...document.querySelectorAll('input,textarea,select')]
235
+ .slice(0, 200)
236
+ .filter(vis)
237
+ .filter((f) => String(f.type || '').toLowerCase() !== 'hidden')
238
+ .slice(0, MAX_FIELDS)
239
+ .map((f) => fieldOf(f, false)));
240
+
241
+ const errors = [];
242
+ const pushError = (text, role) => {
243
+ const t = clean(text, 240);
244
+ if (t.length < 3) return;
245
+ if (/^(error|errors|warning|warnings)$/i.test(t)) return;
246
+ if (errors.some((e) => e.text === t)) return;
247
+ if (errors.length < MAX_ERRORS) errors.push({ text: t, role: clean(role || '', 30) });
248
+ };
249
+ // Alerts and invalid fields first, then the broad class-based sweep.
250
+ for (const el of [...scope.querySelectorAll('[role="alert"],[aria-invalid="true"]')].filter(vis).slice(0, 4)) {
251
+ pushError(el.innerText || el.textContent || el.getAttribute('aria-label') || '', el.getAttribute('role') || 'invalid');
252
+ }
253
+ for (const el of [...scope.querySelectorAll(ERROR_SEL)].filter(vis).slice(0, 20)) {
254
+ pushError(el.innerText || el.textContent || '', el.getAttribute('role') || 'error');
255
+ }
256
+
257
+ const toasts = (window.__tsPageEvents || [])
258
+ .filter((e) => e && e.type !== 'dialog' && e.type !== 'dialog-closed')
259
+ .slice(-MAX_TOASTS);
260
+
261
+ const headings = [...document.querySelectorAll('h1,h2,h3')]
262
+ .filter(vis)
263
+ .map((h) => clean(h.innerText || h.textContent || '', 160))
264
+ .filter(Boolean)
265
+ .slice(0, 8);
266
+
267
+ const active = document.activeElement;
268
+ const focused = active && ['input', 'textarea', 'select'].includes(String(active.tagName || '').toLowerCase())
269
+ ? {
270
+ tag: String(active.tagName || '').toLowerCase(),
271
+ type: String(active.type || '').toLowerCase(),
272
+ label: labelOf(active),
273
+ valueLength: typeof active.value === 'string' ? active.value.length : 0,
274
+ inDialog: !!(topEl && topEl.contains(active)),
275
+ }
276
+ : null;
277
+
278
+ const busy = [...document.querySelectorAll('[aria-busy="true"],[data-loading="true"],[class*="loading"],[class*="spinner"]')]
279
+ .some(vis);
280
+
281
+ let text = '';
282
+ let textTruncated = false;
283
+ if (INCLUDE_TEXT) {
284
+ const root = document.querySelector('main,article,[role="main"]') || document.body;
285
+ const raw = root ? (root.innerText || root.textContent || '') : '';
286
+ const normalized = raw
287
+ .replace(/\\r/g, '')
288
+ .replace(/[ \\t]+\\n/g, '\\n')
289
+ .replace(/\\n{3,}/g, '\\n\\n')
290
+ .trim();
291
+ textTruncated = normalized.length > MAX_TEXT;
292
+ text = textTruncated ? normalized.slice(0, MAX_TEXT) : normalized;
293
+ }
294
+
295
+ return {
296
+ url: location.href,
297
+ title: document.title || '',
298
+ readyState: document.readyState || 'unknown',
299
+ headings: headings,
300
+ dialogs: dialogs,
301
+ modal: !!top,
302
+ fields: fields,
303
+ focused: focused,
304
+ errors: errors,
305
+ toasts: toasts,
306
+ busy: busy,
307
+ scroll: { x: Math.round(window.scrollX || 0), y: Math.round(window.scrollY || 0) },
308
+ text: text,
309
+ textTruncated: textTruncated,
310
+ maxTextChars: MAX_TEXT,
311
+ };
312
+ })()
313
+ `;
314
+ }
315
+ function emptyState() {
316
+ return {
317
+ url: '',
318
+ title: '',
319
+ readyState: 'unknown',
320
+ headings: [],
321
+ dialogs: [],
322
+ modal: false,
323
+ fields: [],
324
+ focused: null,
325
+ errors: [],
326
+ toasts: [],
327
+ busy: false,
328
+ scroll: { x: 0, y: 0 },
329
+ text: '',
330
+ textTruncated: false,
331
+ maxTextChars: DEFAULT_TEXT_CAP,
332
+ };
333
+ }
334
+ /** Read the rich page state. Never throws for a malformed page result. */
335
+ async function readPageState(page, opts = {}) {
336
+ const raw = await (0, cdp_1.evaluateJs)(page, buildPageStateScript(opts));
337
+ if (!raw || typeof raw !== 'object')
338
+ return emptyState();
339
+ const r = raw;
340
+ return {
341
+ ...emptyState(),
342
+ ...r,
343
+ dialogs: Array.isArray(r.dialogs) ? r.dialogs : [],
344
+ fields: Array.isArray(r.fields) ? r.fields : [],
345
+ errors: Array.isArray(r.errors) ? r.errors : [],
346
+ toasts: Array.isArray(r.toasts) ? r.toasts : [],
347
+ headings: Array.isArray(r.headings) ? r.headings : [],
348
+ };
349
+ }
350
+ /**
351
+ * Bounded state attached to every mutating action result. Keeps the top
352
+ * dialog and its controls, a few errors/toasts and focus - enough for the
353
+ * agent to know what just happened without a second call.
354
+ */
355
+ function compactPageState(state) {
356
+ const dialogs = state.dialogs.slice(-2).map((d) => ({
357
+ title: d.title,
358
+ role: d.role,
359
+ text: d.text.slice(0, 400),
360
+ fields: d.fields.slice(0, 10),
361
+ buttons: d.buttons.slice(0, 8),
362
+ }));
363
+ return {
364
+ url: state.url,
365
+ title: state.title,
366
+ readyState: state.readyState,
367
+ modal: state.modal,
368
+ dialogs: dialogs,
369
+ fields: state.fields.slice(0, 12),
370
+ focused: state.focused,
371
+ errors: state.errors.slice(0, 4),
372
+ toasts: state.toasts.slice(-4),
373
+ busy: state.busy,
374
+ scroll: state.scroll,
375
+ };
376
+ }
377
+ /**
378
+ * Fast, bounded state for action results and `waitFor` timeouts (2026-10).
379
+ *
380
+ * Deliberately smaller than `buildPageStateScript`: it skips the full page
381
+ * text, all-dialog enumeration, headings and the z-index sort, so attaching it
382
+ * to every click/type/navigate does not slow a QA run down. Still enough to
383
+ * see the top modal, its controls, errors, toasts and focus.
384
+ */
385
+ function buildCompactStateScript() {
386
+ const errorSelectors = JSON.stringify('[role="alert"],[aria-invalid="true"],[class*="field-error"],[class*="form-error"],[class*="error-message"],[class*="invalid-feedback"],[data-sonner-toast]');
387
+ return `
388
+ (() => {
389
+ const clean = (v, cap) => String(v == null ? '' : v).replace(/\\s+/g, ' ').trim().slice(0, cap || 200);
390
+ const vis = (el) => {
391
+ if (!el || el.nodeType !== 1) return false;
392
+ const r = el.getBoundingClientRect();
393
+ if (r.width === 0 || r.height === 0) return false;
394
+ const cs = getComputedStyle(el);
395
+ return cs.visibility !== 'hidden' && cs.display !== 'none' && cs.opacity !== '0';
396
+ };
397
+ const rect = (el) => {
398
+ const r = el.getBoundingClientRect();
399
+ return { x: Math.round(r.x + r.width / 2), y: Math.round(r.y + r.height / 2) };
400
+ };
401
+ const labelOf = (el) => clean(
402
+ el.getAttribute('aria-label') ||
403
+ el.getAttribute('placeholder') ||
404
+ el.getAttribute('name') ||
405
+ el.id ||
406
+ '',
407
+ 100,
408
+ );
409
+ const fieldOf = (el, inDialog) => {
410
+ const r = rect(el);
411
+ return {
412
+ tag: String(el.tagName || '').toLowerCase(),
413
+ type: String(el.type || el.tagName || '').toLowerCase(),
414
+ label: labelOf(el),
415
+ name: clean(el.getAttribute('name') || el.id || '', 80),
416
+ autocomplete: clean(el.getAttribute('autocomplete') || '', 60),
417
+ valueLength: typeof el.value === 'string' ? el.value.length : 0,
418
+ required: el.required === true,
419
+ invalid: el.getAttribute('aria-invalid') === 'true',
420
+ disabled: el.disabled === true,
421
+ readonly: el.readOnly === true,
422
+ focused: document.activeElement === el,
423
+ inDialog: !!inDialog,
424
+ x: r.x,
425
+ y: r.y,
426
+ };
427
+ };
428
+ const buttonOf = (el) => {
429
+ const r = rect(el);
430
+ return {
431
+ text: clean(el.innerText || el.textContent || el.value || el.getAttribute('aria-label') || '', 80),
432
+ type: clean(el.getAttribute('type') || el.tagName || '', 30).toLowerCase(),
433
+ disabled: el.disabled === true || el.getAttribute('aria-disabled') === 'true',
434
+ x: r.x,
435
+ y: r.y,
436
+ };
437
+ };
438
+ const dialogEls = [...document.querySelectorAll('dialog[open],[role="dialog"],[aria-modal="true"],[class*="modal"],[class*="Modal"],[class*="dialog"],[class*="Dialog"]')]
439
+ .filter(vis)
440
+ .slice(0, 3);
441
+ const loginTop = [...dialogEls].reverse().find((d) =>
442
+ d.querySelector('input[type="password"],input[type="email"],input[autocomplete="username"],input[autocomplete="one-time-code"]'),
443
+ );
444
+ const topEl = loginTop ||
445
+ [...dialogEls].reverse().find((d) => d.querySelector('input,textarea')) ||
446
+ dialogEls[dialogEls.length - 1] ||
447
+ null;
448
+ const top = topEl ? {
449
+ role: clean(topEl.getAttribute('role') || (topEl.tagName || '').toLowerCase(), 30),
450
+ title: clean(
451
+ topEl.getAttribute('aria-label') ||
452
+ (topEl.querySelector('h1,h2,h3') ? topEl.querySelector('h1,h2,h3').innerText : '') ||
453
+ '',
454
+ 120,
455
+ ),
456
+ text: clean(topEl.innerText || topEl.textContent || '', 300),
457
+ fields: [...topEl.querySelectorAll('input,textarea,select')]
458
+ .filter(vis)
459
+ .filter((f) => String(f.type || '').toLowerCase() !== 'hidden')
460
+ .slice(0, 10)
461
+ .map((f) => fieldOf(f, true)),
462
+ buttons: [...topEl.querySelectorAll('button,input[type="submit"],input[type="button"],[role="button"],a')]
463
+ .filter(vis)
464
+ .slice(0, 8)
465
+ .map(buttonOf),
466
+ } : null;
467
+ const scope = topEl || document;
468
+ const errors = [];
469
+ const pushError = (t, role) => {
470
+ const text = clean(t, 200);
471
+ if (text.length < 3 || errors.length >= 3) return;
472
+ if (/^(error|errors|warning|warnings)$/i.test(text)) return;
473
+ if (!errors.some((e) => e.text === text)) errors.push({ text: text, role: clean(role || '', 24) });
474
+ };
475
+ for (const el of [...scope.querySelectorAll('[role="alert"],[aria-invalid="true"]')].filter(vis).slice(0, 3)) {
476
+ pushError(el.innerText || el.textContent || el.getAttribute('aria-label') || '', el.getAttribute('role') || 'invalid');
477
+ }
478
+ for (const el of [...scope.querySelectorAll(${errorSelectors})].filter(vis).slice(0, 8)) {
479
+ pushError(el.innerText || el.textContent || '', el.getAttribute('role') || 'error');
480
+ }
481
+ const active = document.activeElement;
482
+ const focused = active && ['input', 'textarea', 'select'].includes(String(active.tagName || '').toLowerCase())
483
+ ? { tag: String(active.tagName || '').toLowerCase(), type: String(active.type || '').toLowerCase(), label: labelOf(active), valueLength: typeof active.value === 'string' ? active.value.length : 0, inDialog: !!(topEl && topEl.contains(active)) }
484
+ : null;
485
+ return {
486
+ url: location.href,
487
+ title: document.title || '',
488
+ readyState: document.readyState || 'unknown',
489
+ modal: !!topEl,
490
+ dialogs: top ? [top] : [],
491
+ fields: top ? top.fields : [...document.querySelectorAll('input,textarea,select')]
492
+ .slice(0, 120)
493
+ .filter(vis)
494
+ .filter((f) => String(f.type || '').toLowerCase() !== 'hidden')
495
+ .slice(0, 12)
496
+ .map((f) => fieldOf(f, false)),
497
+ focused: focused,
498
+ errors: errors,
499
+ toasts: (window.__tsPageEvents || []).slice(-4),
500
+ busy: [...document.querySelectorAll('[aria-busy="true"],[data-loading="true"],[class*="loading"],[class*="spinner"]')].some(vis),
501
+ scroll: { x: Math.round(window.scrollX || 0), y: Math.round(window.scrollY || 0) },
502
+ };
503
+ })()
504
+ `;
505
+ }
506
+ /** Read the fast compact state; null on a malformed result. */
507
+ async function readCompactState(page) {
508
+ try {
509
+ const raw = await (0, cdp_1.evaluateJs)(page, buildCompactStateScript());
510
+ return raw && typeof raw === 'object'
511
+ ? raw
512
+ : null;
513
+ }
514
+ catch {
515
+ return null;
516
+ }
517
+ }
518
+ /** Human/LLM-readable rendering of a state (used in `snapshot.summary`). */
519
+ function renderPageStateText(state) {
520
+ const lines = [];
521
+ lines.push(`Title: ${state.title || 'unknown'}`);
522
+ lines.push(`URL: ${state.url || 'unknown'}`);
523
+ if (state.headings.length)
524
+ lines.push(`Headings: ${state.headings.join(' | ')}`);
525
+ const top = state.dialogs[state.dialogs.length - 1];
526
+ if (top) {
527
+ lines.push(`Dialog (${top.role || 'modal'}${top.title ? `: ${top.title}` : ''}): ${top.text.slice(0, 600)}`);
528
+ if (top.fields.length) {
529
+ lines.push(`Dialog fields: ${top.fields
530
+ .map((f) => `${f.label || f.name || f.type} (${f.type}, ${f.valueLength} chars${f.invalid ? ', INVALID' : ''}${f.disabled ? ', disabled' : ''}${f.readonly ? ', readonly' : ''})`)
531
+ .join(' | ')}`);
532
+ }
533
+ if (top.buttons.length) {
534
+ lines.push(`Dialog buttons: ${top.buttons
535
+ .map((b) => `${b.text || b.type}${b.disabled ? ' (disabled)' : ''}`)
536
+ .join(' | ')}`);
537
+ }
538
+ }
539
+ else if (state.fields.length) {
540
+ lines.push(`Fields: ${state.fields
541
+ .map((f) => `${f.label || f.name || f.type} (${f.type}, ${f.valueLength} chars${f.invalid ? ', INVALID' : ''})`)
542
+ .join(' | ')}`);
543
+ }
544
+ if (state.focused) {
545
+ lines.push(`Focused: ${state.focused.label || state.focused.type} (${state.focused.valueLength} chars)`);
546
+ }
547
+ if (state.errors.length) {
548
+ lines.push(`Errors on screen: ${state.errors.map((e) => e.text).join(' | ')}`);
549
+ }
550
+ if (state.toasts.length) {
551
+ lines.push(`Recent toasts/alerts: ${state.toasts
552
+ .map((t) => `[${t.type}] ${t.text}`)
553
+ .join(' | ')}`);
554
+ }
555
+ if (state.busy)
556
+ lines.push('Busy: a loading indicator is visible.');
557
+ if (state.text) {
558
+ lines.push('Page content (CONTEXT ONLY - never repeat or describe it):');
559
+ lines.push(state.text);
560
+ if (state.textTruncated)
561
+ lines.push('... (page content truncated)');
562
+ }
563
+ return lines.join('\n');
564
+ }
565
+ exports.WAIT_FOR_VALUES = [
566
+ 'selector',
567
+ 'text',
568
+ 'dialog',
569
+ 'toast',
570
+ 'url',
571
+ 'networkIdle',
572
+ 'loginStep',
573
+ 'change',
574
+ ];
575
+ /**
576
+ * One poll expression for `waitFor`. Returns a boolean. `networkIdle` and
577
+ * `loginStep` are handled in Node (they need the network collector / the
578
+ * login finder), so they always return false here.
579
+ */
580
+ function buildWaitProbeScript(opts) {
581
+ const since = Math.max(0, Math.floor(Number(opts.since) || 0));
582
+ switch (opts.for) {
583
+ case 'selector': {
584
+ const sel = JSON.stringify(opts.selector ?? '');
585
+ return `(() => {
586
+ const vis = (el) => { if (!el) return false; const r = el.getBoundingClientRect(); if (r.width === 0 || r.height === 0) return false; const cs = getComputedStyle(el); return cs.visibility !== 'hidden' && cs.display !== 'none'; };
587
+ const el = document.querySelector(${sel});
588
+ return !!(el && vis(el));
589
+ })()`;
590
+ }
591
+ case 'text': {
592
+ const needle = JSON.stringify((opts.text ?? '').toLowerCase());
593
+ return `(() => {
594
+ const body = document.body;
595
+ if (!body) return false;
596
+ const t = (body.innerText || body.textContent || '').toLowerCase();
597
+ return t.includes(${needle});
598
+ })()`;
599
+ }
600
+ case 'dialog': {
601
+ const wantClosed = opts.state === 'closed';
602
+ return `(() => {
603
+ const vis = (el) => { if (!el) return false; const r = el.getBoundingClientRect(); if (r.width === 0 || r.height === 0) return false; const cs = getComputedStyle(el); return cs.visibility !== 'hidden' && cs.display !== 'none'; };
604
+ const n = [...document.querySelectorAll('dialog[open],[role="dialog"],[aria-modal="true"]')].filter(vis).length;
605
+ return ${wantClosed ? 'n === 0' : 'n > 0'};
606
+ })()`;
607
+ }
608
+ case 'toast': {
609
+ const needle = JSON.stringify((opts.text ?? '').toLowerCase());
610
+ return `(() => {
611
+ const ev = (window.__tsPageEvents || []).filter((e) => e && e.at >= ${since} &&
612
+ (e.type === 'toast' || e.type === 'alert' || e.type === 'status' || e.type === 'error'));
613
+ const needle = ${needle};
614
+ if (needle) return ev.some((e) => String(e.text || '').toLowerCase().includes(needle));
615
+ return ev.length > 0;
616
+ })()`;
617
+ }
618
+ case 'url': {
619
+ const needle = JSON.stringify(opts.urlIncludes ?? '');
620
+ return `(() => location.href.includes(${needle}))()`;
621
+ }
622
+ case 'change':
623
+ return `(() => !!(window.__tsScreenObs && window.__tsScreenObs.mutated >= ${since}))()`;
624
+ default:
625
+ return 'false';
626
+ }
627
+ }
628
+ /** Empty snapshot used when the page is blocked by a native dialog. */
629
+ function emptyPageSnapshot(nativeDialog, pendingRequests, consoleErrors = []) {
630
+ return {
631
+ ...emptyState(),
632
+ nativeDialog,
633
+ pendingRequests,
634
+ consoleErrors,
635
+ };
636
+ }
637
+ //# sourceMappingURL=page-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page-context.js","sourceRoot":"","sources":["../../../src/lib/browser/page-context.ts"],"names":[],"mappings":"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"}