ttp-agent-sdk 2.45.6 → 2.45.7

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.
@@ -11947,7 +11947,7 @@ var TextChatSDK = /*#__PURE__*/function (_EventEmitter) {
11947
11947
 
11948
11948
  // SDK build time for debugging
11949
11949
  if (true) {
11950
- helloMessage.lastBuildTime = "2026-06-13T08:36:31.824Z";
11950
+ helloMessage.lastBuildTime = "2026-06-14T07:18:03.004Z";
11951
11951
  }
11952
11952
  try {
11953
11953
  this.ws.send(JSON.stringify(helloMessage));
@@ -20113,8 +20113,8 @@ var VoiceSDK = _v2_VoiceSDK_js__WEBPACK_IMPORTED_MODULE_0__["default"];
20113
20113
 
20114
20114
 
20115
20115
  // Version - injected at build time from package.json via webpack DefinePlugin
20116
- var VERSION = "2.45.6";
20117
- var BUILD_TIME = "2026-06-13T08:36:31.824Z";
20116
+ var VERSION = "2.45.7";
20117
+ var BUILD_TIME = "2026-06-14T07:18:03.004Z";
20118
20118
  console.log("%c TTP Agent SDK v".concat(VERSION, " (").concat(BUILD_TIME, ") "), 'background: #4f46e5; color: white; font-size: 12px; font-weight: bold; padding: 2px 6px; border-radius: 4px;');
20119
20119
 
20120
20120
  // Named exports
@@ -23039,208 +23039,300 @@ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r)
23039
23039
  function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
23040
23040
  /**
23041
23041
  * DOM Context Extraction
23042
- *
23043
- * Extracts structured information about interactive elements on the page
23044
- * to provide context to the LLM for visual assistance.
23042
+ *
23043
+ * Extracts the actual readable content of the page — text, headings, code
23044
+ * blocks, lists plus interactive elements (buttons, forms, links) for
23045
+ * navigation and action context.
23045
23046
  */
23046
23047
 
23047
23048
 
23048
-
23049
- // Default limits to prevent token explosion
23050
23049
  var DEFAULT_LIMITS = {
23050
+ maxContentLength: 8000,
23051
+ // chars of main text content
23052
+ maxCodeBlockLength: 600,
23053
+ // chars per code block
23051
23054
  buttons: 20,
23052
23055
  links: 30,
23053
23056
  forms: 5,
23054
23057
  fieldsPerForm: 15,
23055
- sections: 10,
23056
- headings: 15,
23057
- maxTextLength: 100,
23058
- maxSummaryLength: 150
23058
+ maxTextLength: 100 // per interactive element label
23059
23059
  };
23060
23060
 
23061
- /**
23062
- * Generate a unique, stable CSS selector for an element
23063
- * Prioritizes stable attributes over auto-generated IDs
23064
- *
23065
- * @param {HTMLElement} element - The element to generate selector for
23066
- * @returns {string} - CSS selector string
23067
- */
23068
- function generateSelector(element) {
23069
- var _element$dataset, _element$dataset2;
23070
- if (!element || !element.tagName) return null;
23071
-
23072
- // Priority 1: data-testid (designed to be stable)
23073
- if ((_element$dataset = element.dataset) !== null && _element$dataset !== void 0 && _element$dataset.testid) {
23074
- return "[data-testid=\"".concat(element.dataset.testid, "\"]");
23075
- }
23076
-
23077
- // Priority 2: data-cy (Cypress test attribute)
23078
- if ((_element$dataset2 = element.dataset) !== null && _element$dataset2 !== void 0 && _element$dataset2.cy) {
23079
- return "[data-cy=\"".concat(element.dataset.cy, "\"]");
23080
- }
23081
-
23082
- // Priority 3: aria-label (accessibility, usually stable)
23083
- var ariaLabel = element.getAttribute('aria-label');
23084
- if (ariaLabel && ariaLabel.length < 50) {
23085
- return "[aria-label=\"".concat(ariaLabel.replace(/"/g, '\\"'), "\"]");
23086
- }
23087
-
23088
- // Priority 4: Stable ID (not auto-generated)
23089
- if (element.id && !isAutoGeneratedId(element.id)) {
23090
- return "#".concat(CSS.escape(element.id));
23091
- }
23061
+ // ─── Noise exclusion ────────────────────────────────────────────────────────
23062
+
23063
+ var NOISE_TAGS = new Set(['nav', 'header', 'footer', 'aside', 'script', 'style', 'noscript', 'svg', 'canvas', 'iframe']);
23064
+ var NOISE_ROLES = new Set(['navigation', 'banner', 'complementary', 'search']);
23065
+ function isNoise(el) {
23066
+ if (NOISE_TAGS.has(el.tagName.toLowerCase())) return true;
23067
+ var role = el.getAttribute('role');
23068
+ if (role && NOISE_ROLES.has(role)) return true;
23069
+ var cls = el.className || '';
23070
+ // Common sidebar/nav class patterns
23071
+ if (/\b(sidebar|navbar|topbar|breadcrumb|cookie|toast|modal-backdrop)\b/i.test(cls)) return true;
23072
+ return false;
23073
+ }
23092
23074
 
23093
- // Priority 5: name attribute (for form fields)
23094
- if (element.name) {
23095
- var tag = element.tagName.toLowerCase();
23096
- return "".concat(tag, "[name=\"").concat(element.name, "\"]");
23097
- }
23075
+ // ─── Visibility ──────────────────────────────────────────────────────────────
23098
23076
 
23099
- // Priority 6: Unique text content for buttons/links
23100
- if (['BUTTON', 'A'].includes(element.tagName)) {
23101
- var _element$innerText;
23102
- var text = (_element$innerText = element.innerText) === null || _element$innerText === void 0 ? void 0 : _element$innerText.trim();
23103
- if (text && text.length < 30 && text.length > 0) {
23104
- var _tag = element.tagName.toLowerCase();
23105
- // Check if this text is unique on the page
23106
- var matches = document.querySelectorAll("".concat(_tag));
23107
- var sameTextCount = Array.from(matches).filter(function (el) {
23108
- var _el$innerText;
23109
- return ((_el$innerText = el.innerText) === null || _el$innerText === void 0 ? void 0 : _el$innerText.trim()) === text;
23110
- }).length;
23111
- if (sameTextCount === 1) {
23112
- return "".concat(_tag, ":contains(\"").concat(text.replace(/"/g, '\\"'), "\")");
23113
- }
23114
- }
23115
- }
23116
-
23117
- // Priority 7: Build path from stable ancestors
23118
- return buildPathSelector(element);
23077
+ function isVisible(el) {
23078
+ if (!el) return false;
23079
+ var style = window.getComputedStyle(el);
23080
+ return style.display !== 'none' && style.visibility !== 'hidden' && style.opacity !== '0' && el.offsetWidth > 0 && el.offsetHeight > 0;
23081
+ }
23082
+ function isInViewport(el) {
23083
+ var buffer = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 500;
23084
+ var rect = el.getBoundingClientRect();
23085
+ return rect.bottom >= -buffer && rect.top <= window.innerHeight + buffer && rect.right >= 0 && rect.left <= window.innerWidth;
23119
23086
  }
23120
23087
 
23121
- /**
23122
- * Check if an ID looks auto-generated (React, Angular, Vue, etc.)
23123
- */
23088
+ // ─── Selector generation (kept for interactive elements) ─────────────────────
23089
+
23124
23090
  function isAutoGeneratedId(id) {
23125
- var autoGenPatterns = [/^:r[0-9a-z]+:$/,
23126
- // React 18+ useId
23127
- /^react-/i,
23128
- // React
23129
- /^ng-/i,
23130
- // Angular
23131
- /^vue-/i,
23132
- // Vue
23133
- /^ember[0-9]+/i,
23134
- // Ember
23135
- /^_[a-z0-9]{8,}$/i,
23136
- // Generic hash IDs
23137
- /^[a-f0-9]{8}-[a-f0-9]{4}/i,
23138
- // UUID-like
23139
- /^uid-/i,
23140
- // Generic UID
23141
- /^id[0-9]+$/i // Generic numbered IDs
23142
- ];
23143
- return autoGenPatterns.some(function (pattern) {
23144
- return pattern.test(id);
23091
+ return /^(:r[0-9a-z]+:|react-|ng-|vue-|ember[0-9]+|_[a-z0-9]{8,}|[a-f0-9]{8}-[a-f0-9]{4}|uid-|id[0-9]+$)/i.test(id);
23092
+ }
23093
+ function getMeaningfulClass(el) {
23094
+ var utilityPatterns = [/^(flex|grid|block|inline|hidden)$/, /^(m|p|w|h|min|max)-/, /^(text|font|bg|border)-/, /^(col|row)-/, /^(sm|md|lg|xl|2xl):/, /^hover:|focus:|active:/, /^[a-z]{1,3}-[0-9]+$/];
23095
+ var classes = Array.from(el.classList || []);
23096
+ var meaningful = classes.filter(function (cls) {
23097
+ return !utilityPatterns.some(function (p) {
23098
+ return p.test(cls);
23099
+ }) && cls.length > 2 && cls.length < 30;
23145
23100
  });
23101
+ return meaningful[0] || null;
23146
23102
  }
23147
-
23148
- /**
23149
- * Build a selector path from ancestors
23150
- */
23151
- function buildPathSelector(element) {
23103
+ function buildPathSelector(el) {
23152
23104
  var maxDepth = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 3;
23153
23105
  var path = [];
23154
- var current = element;
23106
+ var cur = el;
23155
23107
  var depth = 0;
23156
- while (current && current !== document.body && depth < maxDepth) {
23157
- var tag = current.tagName.toLowerCase();
23158
-
23159
- // Try to add distinguishing info
23160
- if (current.id && !isAutoGeneratedId(current.id)) {
23161
- path.unshift("#".concat(CSS.escape(current.id)));
23162
- break; // ID is unique, stop here
23163
- }
23164
-
23165
- // Add class if it seems meaningful
23166
- var meaningfulClass = getMeaningfulClass(current);
23167
- if (meaningfulClass) {
23168
- path.unshift("".concat(tag, ".").concat(meaningfulClass));
23108
+ while (cur && cur !== document.body && depth < maxDepth) {
23109
+ var tag = cur.tagName.toLowerCase();
23110
+ if (cur.id && !isAutoGeneratedId(cur.id)) {
23111
+ path.unshift("#".concat(CSS.escape(cur.id)));
23112
+ break;
23113
+ }
23114
+ var cls = getMeaningfulClass(cur);
23115
+ if (cls) {
23116
+ path.unshift("".concat(tag, ".").concat(cls));
23169
23117
  } else {
23170
- var _current$parentElemen;
23171
- // Add nth-child if needed
23172
- var siblings = (_current$parentElemen = current.parentElement) === null || _current$parentElemen === void 0 ? void 0 : _current$parentElemen.children;
23118
+ var _cur$parentElement;
23119
+ var siblings = (_cur$parentElement = cur.parentElement) === null || _cur$parentElement === void 0 ? void 0 : _cur$parentElement.children;
23173
23120
  if (siblings && siblings.length > 1) {
23174
- var index = Array.from(siblings).indexOf(current) + 1;
23175
- path.unshift("".concat(tag, ":nth-child(").concat(index, ")"));
23121
+ var idx = Array.from(siblings).indexOf(cur) + 1;
23122
+ path.unshift("".concat(tag, ":nth-child(").concat(idx, ")"));
23176
23123
  } else {
23177
23124
  path.unshift(tag);
23178
23125
  }
23179
23126
  }
23180
- current = current.parentElement;
23127
+ cur = cur.parentElement;
23181
23128
  depth++;
23182
23129
  }
23183
23130
  return path.join(' > ');
23184
23131
  }
23132
+ function generateSelector(el) {
23133
+ var _el$dataset, _el$dataset2;
23134
+ if (!el || !el.tagName) return null;
23135
+ if ((_el$dataset = el.dataset) !== null && _el$dataset !== void 0 && _el$dataset.testid) return "[data-testid=\"".concat(el.dataset.testid, "\"]");
23136
+ if ((_el$dataset2 = el.dataset) !== null && _el$dataset2 !== void 0 && _el$dataset2.cy) return "[data-cy=\"".concat(el.dataset.cy, "\"]");
23137
+ var aria = el.getAttribute('aria-label');
23138
+ if (aria && aria.length < 50) return "[aria-label=\"".concat(aria.replace(/"/g, '\\"'), "\"]");
23139
+ if (el.id && !isAutoGeneratedId(el.id)) return "#".concat(CSS.escape(el.id));
23140
+ if (el.name) return "".concat(el.tagName.toLowerCase(), "[name=\"").concat(el.name, "\"]");
23141
+ if (['BUTTON', 'A'].includes(el.tagName)) {
23142
+ var _el$innerText;
23143
+ var text = (_el$innerText = el.innerText) === null || _el$innerText === void 0 ? void 0 : _el$innerText.trim();
23144
+ if (text && text.length < 30) {
23145
+ var tag = el.tagName.toLowerCase();
23146
+ var matches = document.querySelectorAll(tag);
23147
+ if (Array.from(matches).filter(function (e) {
23148
+ var _e$innerText;
23149
+ return ((_e$innerText = e.innerText) === null || _e$innerText === void 0 ? void 0 : _e$innerText.trim()) === text;
23150
+ }).length === 1) {
23151
+ return "".concat(tag, ":contains(\"").concat(text.replace(/"/g, '\\"'), "\")");
23152
+ }
23153
+ }
23154
+ }
23155
+ return buildPathSelector(el);
23156
+ }
23157
+
23158
+ // ─── Main content extraction ─────────────────────────────────────────────────
23185
23159
 
23186
23160
  /**
23187
- * Get a meaningful class name (not utility classes)
23161
+ * Find the best container element that holds the page's primary content.
23162
+ * Tries progressively wider selectors; falls back to document.body.
23188
23163
  */
23189
- function getMeaningfulClass(element) {
23190
- var classes = Array.from(element.classList || []);
23191
-
23192
- // Skip utility class patterns (Tailwind, Bootstrap, etc.)
23193
- var utilityPatterns = [/^(flex|grid|block|inline|hidden)$/, /^(m|p|w|h|min|max)-/,
23194
- // Spacing/sizing
23195
- /^(text|font|bg|border)-/,
23196
- // Typography/colors
23197
- /^(col|row)-/,
23198
- // Grid
23199
- /^(sm|md|lg|xl|2xl):/,
23200
- // Responsive
23201
- /^hover:|focus:|active:/,
23202
- // States
23203
- /^[a-z]{1,3}-[0-9]+$/ // Generic utilities
23204
- ];
23205
- var meaningfulClasses = classes.filter(function (cls) {
23206
- return !utilityPatterns.some(function (pattern) {
23207
- return pattern.test(cls);
23208
- }) && cls.length > 2 && cls.length < 30;
23209
- });
23210
- return meaningfulClasses[0] || null;
23164
+ function findContentRoot() {
23165
+ var candidates = ['article', '[role="article"]', 'main', '[role="main"]', '.prose', '.markdown-body', '.content', '#content', '#main-content', '#main'];
23166
+ for (var _i = 0, _candidates = candidates; _i < _candidates.length; _i++) {
23167
+ var sel = _candidates[_i];
23168
+ try {
23169
+ var el = document.querySelector(sel);
23170
+ if (el && isVisible(el)) return el;
23171
+ } catch (_unused) {}
23172
+ }
23173
+ return document.body;
23211
23174
  }
23212
23175
 
23213
23176
  /**
23214
- * Check if element is in or near viewport
23177
+ * Walk the content root and emit structured content items.
23178
+ * Skips noise elements (nav, header, aside…).
23179
+ *
23180
+ * Returns an array of items:
23181
+ * { type: 'heading', level: 'h2', text: '...' }
23182
+ * { type: 'text', text: '...' }
23183
+ * { type: 'code', lang: 'bash', text: '...' }
23184
+ * { type: 'listItem', text: '...' }
23215
23185
  */
23216
- function isInViewport(element) {
23217
- var buffer = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 500;
23218
- var rect = element.getBoundingClientRect();
23219
- return rect.bottom >= -buffer && rect.top <= window.innerHeight + buffer && rect.right >= 0 && rect.left <= window.innerWidth;
23186
+ function walkContent(root, limits) {
23187
+ var items = [];
23188
+ var charCount = 0;
23189
+ var BLOCK_TAGS = new Set(['p', 'li', 'dt', 'dd', 'td', 'th', 'blockquote', 'figcaption']);
23190
+ var HEADING_TAGS = new Set(['h1', 'h2', 'h3', 'h4', 'h5', 'h6']);
23191
+ function walk(node) {
23192
+ if (charCount >= limits.maxContentLength) return;
23193
+ if (node.nodeType !== Node.ELEMENT_NODE) return;
23194
+ var tag = node.tagName.toLowerCase();
23195
+
23196
+ // Skip noise subtrees entirely
23197
+ if (isNoise(node)) return;
23198
+ if (!isVisible(node)) return;
23199
+
23200
+ // Heading → new section marker
23201
+ if (HEADING_TAGS.has(tag)) {
23202
+ var text = (node.innerText || '').trim();
23203
+ if (text) {
23204
+ items.push({
23205
+ type: 'heading',
23206
+ level: tag,
23207
+ text: text
23208
+ });
23209
+ charCount += text.length;
23210
+ }
23211
+ return; // don't recurse — heading text already captured
23212
+ }
23213
+
23214
+ // Code block
23215
+ if (tag === 'pre') {
23216
+ var codeEl = node.querySelector('code');
23217
+ var raw = (codeEl || node).innerText || '';
23218
+ var _text = raw.trim().substring(0, limits.maxCodeBlockLength);
23219
+ if (_text) {
23220
+ var _match;
23221
+ var lang = ((_match = ((codeEl === null || codeEl === void 0 ? void 0 : codeEl.className) || '').match(/language-(\w+)/)) === null || _match === void 0 ? void 0 : _match[1]) || '';
23222
+ items.push({
23223
+ type: 'code',
23224
+ lang: lang,
23225
+ text: _text
23226
+ });
23227
+ charCount += _text.length;
23228
+ }
23229
+ return;
23230
+ }
23231
+
23232
+ // Inline code (not inside pre)
23233
+ if (tag === 'code' && node.closest('pre') === null) {
23234
+ // Let the parent block pick it up via innerText
23235
+ return;
23236
+ }
23237
+
23238
+ // Block-level text elements
23239
+ if (BLOCK_TAGS.has(tag)) {
23240
+ var _node$parentElement;
23241
+ // Skip if nested inside another block (e.g. <p> inside <blockquote> handled by blockquote)
23242
+ var parentTag = (_node$parentElement = node.parentElement) === null || _node$parentElement === void 0 ? void 0 : _node$parentElement.tagName.toLowerCase();
23243
+ if (tag !== 'blockquote' && BLOCK_TAGS.has(parentTag) && parentTag !== 'li') return;
23244
+ var _text2 = (node.innerText || '').trim();
23245
+ if (_text2) {
23246
+ var type = tag === 'li' ? 'listItem' : 'text';
23247
+ var truncated = _text2.substring(0, 400);
23248
+ items.push({
23249
+ type: type,
23250
+ text: truncated
23251
+ });
23252
+ charCount += truncated.length;
23253
+ }
23254
+ return; // innerText already captures children
23255
+ }
23256
+
23257
+ // Container — recurse into children
23258
+ var _iterator = _createForOfIteratorHelper(node.children),
23259
+ _step;
23260
+ try {
23261
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
23262
+ var child = _step.value;
23263
+ if (charCount >= limits.maxContentLength) break;
23264
+ walk(child);
23265
+ }
23266
+ } catch (err) {
23267
+ _iterator.e(err);
23268
+ } finally {
23269
+ _iterator.f();
23270
+ }
23271
+ }
23272
+ walk(root);
23273
+ return items;
23220
23274
  }
23221
23275
 
23222
23276
  /**
23223
- * Check if element is visible (not hidden)
23277
+ * Convert structured content items into a readable flat string,
23278
+ * organised by heading sections.
23224
23279
  */
23225
- function isVisible(element) {
23226
- if (!element) return false;
23227
- var style = window.getComputedStyle(element);
23228
- return style.display !== 'none' && style.visibility !== 'hidden' && style.opacity !== '0' && element.offsetWidth > 0 && element.offsetHeight > 0;
23280
+ function itemsToText(items) {
23281
+ var text = '';
23282
+ var _iterator2 = _createForOfIteratorHelper(items),
23283
+ _step2;
23284
+ try {
23285
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
23286
+ var item = _step2.value;
23287
+ switch (item.type) {
23288
+ case 'heading':
23289
+ text += "\n".concat('#'.repeat(parseInt(item.level[1])), " ").concat(item.text, "\n");
23290
+ break;
23291
+ case 'text':
23292
+ text += "".concat(item.text, "\n");
23293
+ break;
23294
+ case 'listItem':
23295
+ text += "\u2022 ".concat(item.text, "\n");
23296
+ break;
23297
+ case 'code':
23298
+ text += "```".concat(item.lang, "\n").concat(item.text, "\n```\n");
23299
+ break;
23300
+ }
23301
+ }
23302
+ } catch (err) {
23303
+ _iterator2.e(err);
23304
+ } finally {
23305
+ _iterator2.f();
23306
+ }
23307
+ return text.trim();
23229
23308
  }
23230
23309
 
23231
23310
  /**
23232
- * Extract buttons from the page
23311
+ * Extract the main readable content of the page.
23233
23312
  */
23234
- function extractButtons() {
23235
- var limits = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : DEFAULT_LIMITS;
23313
+ function extractMainContent(limits) {
23314
+ var root = findContentRoot();
23315
+ var items = walkContent(root, limits);
23316
+ var text = itemsToText(items);
23317
+ var truncated = text.length >= limits.maxContentLength;
23318
+ return {
23319
+ text: text,
23320
+ items: items,
23321
+ truncated: truncated,
23322
+ sourceElement: root.tagName.toLowerCase() + (root.id ? "#".concat(root.id) : '') + (getMeaningfulClass(root) ? ".".concat(getMeaningfulClass(root)) : '')
23323
+ };
23324
+ }
23325
+
23326
+ // ─── Interactive elements ─────────────────────────────────────────────────────
23327
+
23328
+ function extractButtons(limits) {
23236
23329
  var buttons = [];
23237
- var selector = 'button, [type="submit"], [type="button"], [role="button"], .btn, .button';
23238
- var elements = document.querySelectorAll(selector);
23239
- var _iterator = _createForOfIteratorHelper(elements),
23240
- _step;
23330
+ var els = document.querySelectorAll('button, [type="submit"], [type="button"], [role="button"], .btn, .button');
23331
+ var _iterator3 = _createForOfIteratorHelper(els),
23332
+ _step3;
23241
23333
  try {
23242
- for (_iterator.s(); !(_step = _iterator.n()).done;) {
23243
- var el = _step.value;
23334
+ for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
23335
+ var el = _step3.value;
23244
23336
  if (buttons.length >= limits.buttons) break;
23245
23337
  if (!isVisible(el)) continue;
23246
23338
  var text = (el.innerText || el.value || el.getAttribute('aria-label') || '').trim();
@@ -23254,101 +23346,76 @@ function extractButtons() {
23254
23346
  });
23255
23347
  }
23256
23348
  } catch (err) {
23257
- _iterator.e(err);
23349
+ _iterator3.e(err);
23258
23350
  } finally {
23259
- _iterator.f();
23351
+ _iterator3.f();
23260
23352
  }
23261
23353
  return buttons;
23262
23354
  }
23263
-
23264
- /**
23265
- * Extract links from the page
23266
- */
23267
- function extractLinks() {
23268
- var limits = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : DEFAULT_LIMITS;
23355
+ function extractLinks(limits) {
23269
23356
  var links = [];
23270
- var elements = document.querySelectorAll('a[href]');
23271
- var currentOrigin = window.location.origin;
23272
- var _iterator2 = _createForOfIteratorHelper(elements),
23273
- _step2;
23357
+ var els = document.querySelectorAll('a[href]');
23358
+ var origin = window.location.origin;
23359
+ var _iterator4 = _createForOfIteratorHelper(els),
23360
+ _step4;
23274
23361
  try {
23275
- for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
23276
- var el = _step2.value;
23362
+ for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
23363
+ var el = _step4.value;
23277
23364
  if (links.length >= limits.links) break;
23278
23365
  if (!isVisible(el)) continue;
23279
23366
  var text = (el.innerText || el.getAttribute('aria-label') || '').trim();
23280
23367
  if (!text || text.length < 2) continue;
23281
-
23282
- // Skip anchor links and javascript:void
23283
23368
  var href = el.href;
23284
23369
  if (!href || href.startsWith('javascript:') || href === '#') continue;
23285
- var isInternal = false;
23370
+ var internal = false;
23286
23371
  try {
23287
- isInternal = new URL(href).origin === currentOrigin;
23288
- } catch (_unused) {}
23372
+ internal = new URL(href).origin === origin;
23373
+ } catch (_unused2) {}
23289
23374
  links.push({
23290
23375
  selector: generateSelector(el),
23291
23376
  text: text.substring(0, limits.maxTextLength),
23292
23377
  href: href,
23293
- internal: isInternal,
23378
+ internal: internal,
23294
23379
  inViewport: isInViewport(el, 0)
23295
23380
  });
23296
23381
  }
23297
23382
  } catch (err) {
23298
- _iterator2.e(err);
23383
+ _iterator4.e(err);
23299
23384
  } finally {
23300
- _iterator2.f();
23385
+ _iterator4.f();
23301
23386
  }
23302
23387
  return links;
23303
23388
  }
23304
-
23305
- /**
23306
- * Extract forms from the page (with sensitive field filtering)
23307
- */
23308
- function extractForms() {
23309
- var limits = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : DEFAULT_LIMITS;
23389
+ function extractForms(limits) {
23310
23390
  var forms = [];
23311
- var elements = document.querySelectorAll('form');
23312
23391
  var sensitiveCount = 0;
23313
- var _iterator3 = _createForOfIteratorHelper(elements),
23314
- _step3;
23392
+ var _iterator5 = _createForOfIteratorHelper(document.querySelectorAll('form')),
23393
+ _step5;
23315
23394
  try {
23316
- for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
23317
- var form = _step3.value;
23395
+ for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
23396
+ var form = _step5.value;
23318
23397
  if (forms.length >= limits.forms) break;
23319
23398
  if (!isVisible(form)) continue;
23320
23399
  var fields = [];
23321
- var fieldElements = form.querySelectorAll('input, textarea, select');
23322
- var _iterator4 = _createForOfIteratorHelper(fieldElements),
23323
- _step4;
23400
+ var _iterator6 = _createForOfIteratorHelper(form.querySelectorAll('input, textarea, select')),
23401
+ _step6;
23324
23402
  try {
23325
- for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
23403
+ for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
23326
23404
  var _label, _field$placeholder;
23327
- var field = _step4.value;
23405
+ var field = _step6.value;
23328
23406
  if (fields.length >= limits.fieldsPerForm) break;
23329
-
23330
- // Skip hidden fields
23331
23407
  if (field.type === 'hidden') continue;
23332
-
23333
- // IMPORTANT: Filter sensitive fields
23334
23408
  if ((0,_sensitive_filter_js__WEBPACK_IMPORTED_MODULE_0__.isSensitiveField)(field)) {
23335
23409
  sensitiveCount++;
23336
23410
  continue;
23337
23411
  }
23338
-
23339
- // Get label
23340
23412
  var label = null;
23341
23413
  if (field.id) {
23342
- var _labelEl$innerText;
23343
- var labelEl = document.querySelector("label[for=\"".concat(field.id, "\"]"));
23344
- label = labelEl === null || labelEl === void 0 || (_labelEl$innerText = labelEl.innerText) === null || _labelEl$innerText === void 0 ? void 0 : _labelEl$innerText.trim();
23345
- }
23346
- if (!label && field.getAttribute('aria-label')) {
23347
- label = field.getAttribute('aria-label');
23348
- }
23349
- if (!label && field.placeholder) {
23350
- label = field.placeholder;
23414
+ var _lEl$innerText;
23415
+ var lEl = document.querySelector("label[for=\"".concat(field.id, "\"]"));
23416
+ label = lEl === null || lEl === void 0 || (_lEl$innerText = lEl.innerText) === null || _lEl$innerText === void 0 ? void 0 : _lEl$innerText.trim();
23351
23417
  }
23418
+ label = label || field.getAttribute('aria-label') || field.placeholder || null;
23352
23419
  fields.push({
23353
23420
  selector: generateSelector(field),
23354
23421
  name: field.name || null,
@@ -23356,15 +23423,14 @@ function extractForms() {
23356
23423
  label: ((_label = label) === null || _label === void 0 ? void 0 : _label.substring(0, 50)) || null,
23357
23424
  placeholder: ((_field$placeholder = field.placeholder) === null || _field$placeholder === void 0 ? void 0 : _field$placeholder.substring(0, 50)) || null,
23358
23425
  required: field.required || false
23359
- // NEVER include value for security
23360
23426
  });
23361
23427
  }
23362
23428
  } catch (err) {
23363
- _iterator4.e(err);
23429
+ _iterator6.e(err);
23364
23430
  } finally {
23365
- _iterator4.f();
23431
+ _iterator6.f();
23366
23432
  }
23367
- if (fields.length === 0) continue;
23433
+ if (!fields.length) continue;
23368
23434
  forms.push({
23369
23435
  selector: generateSelector(form),
23370
23436
  id: form.id || null,
@@ -23374,9 +23440,9 @@ function extractForms() {
23374
23440
  });
23375
23441
  }
23376
23442
  } catch (err) {
23377
- _iterator3.e(err);
23443
+ _iterator5.e(err);
23378
23444
  } finally {
23379
- _iterator3.f();
23445
+ _iterator5.f();
23380
23446
  }
23381
23447
  return {
23382
23448
  forms: forms,
@@ -23384,143 +23450,56 @@ function extractForms() {
23384
23450
  };
23385
23451
  }
23386
23452
 
23387
- /**
23388
- * Extract sections/landmarks from the page
23389
- */
23390
- function extractSections() {
23391
- var limits = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : DEFAULT_LIMITS;
23392
- var sections = [];
23393
- var selector = 'section, article, main, [role="main"], [role="region"], .section';
23394
- var elements = document.querySelectorAll(selector);
23395
- var _iterator5 = _createForOfIteratorHelper(elements),
23396
- _step5;
23397
- try {
23398
- for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
23399
- var _heading$innerText, _firstP$innerText, _el$innerText2;
23400
- var el = _step5.value;
23401
- if (sections.length >= limits.sections) break;
23402
- if (!isVisible(el)) continue;
23403
-
23404
- // Get a summary of the section content
23405
- var heading = el.querySelector('h1, h2, h3');
23406
- var headingText = (heading === null || heading === void 0 || (_heading$innerText = heading.innerText) === null || _heading$innerText === void 0 ? void 0 : _heading$innerText.trim()) || '';
23407
-
23408
- // Get first paragraph or first N characters
23409
- var firstP = el.querySelector('p');
23410
- var summary = headingText || (firstP === null || firstP === void 0 || (_firstP$innerText = firstP.innerText) === null || _firstP$innerText === void 0 ? void 0 : _firstP$innerText.trim().substring(0, limits.maxSummaryLength)) || ((_el$innerText2 = el.innerText) === null || _el$innerText2 === void 0 ? void 0 : _el$innerText2.trim().substring(0, limits.maxSummaryLength)) || '';
23411
- sections.push({
23412
- selector: generateSelector(el),
23413
- id: el.id || null,
23414
- tagName: el.tagName.toLowerCase(),
23415
- summary: summary.substring(0, limits.maxSummaryLength),
23416
- inViewport: isInViewport(el, 0)
23417
- });
23418
- }
23419
- } catch (err) {
23420
- _iterator5.e(err);
23421
- } finally {
23422
- _iterator5.f();
23423
- }
23424
- return sections;
23425
- }
23426
-
23427
- /**
23428
- * Extract headings from the page
23429
- */
23430
- function extractHeadings() {
23431
- var limits = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : DEFAULT_LIMITS;
23432
- var headings = [];
23433
- var elements = document.querySelectorAll('h1, h2, h3');
23434
- var _iterator6 = _createForOfIteratorHelper(elements),
23435
- _step6;
23436
- try {
23437
- for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
23438
- var _el$innerText3;
23439
- var el = _step6.value;
23440
- if (headings.length >= limits.headings) break;
23441
- if (!isVisible(el)) continue;
23442
- var text = (_el$innerText3 = el.innerText) === null || _el$innerText3 === void 0 ? void 0 : _el$innerText3.trim();
23443
- if (!text) continue;
23444
- headings.push({
23445
- selector: generateSelector(el),
23446
- level: el.tagName.toLowerCase(),
23447
- text: text.substring(0, limits.maxTextLength),
23448
- inViewport: isInViewport(el, 0)
23449
- });
23450
- }
23451
- } catch (err) {
23452
- _iterator6.e(err);
23453
- } finally {
23454
- _iterator6.f();
23455
- }
23456
- return headings;
23457
- }
23453
+ // ─── Public API ───────────────────────────────────────────────────────────────
23458
23454
 
23459
23455
  /**
23460
- * Main function: Extract full DOM context
23461
- *
23462
- * @param {Object} options - Extraction options
23463
- * @param {Object} options.limits - Override default limits
23464
- * @returns {Object} - Structured DOM context
23456
+ * Main extraction function called by the read_page tool handler.
23457
+ *
23458
+ * Returns:
23459
+ * content — flat readable text of the page (most important)
23460
+ * contentItems — structured array of { type, text, level?, lang? }
23461
+ * contentTruncated — true if content was cut at maxContentLength
23462
+ * url, title, language, viewport
23463
+ * buttons, links, forms — interactive elements for navigation / actions
23464
+ * metadata
23465
23465
  */
23466
23466
  function extractDOMContext() {
23467
23467
  return _extractDOMContext.apply(this, arguments);
23468
23468
  }
23469
23469
 
23470
23470
  /**
23471
- * Extract minimal context (for re-extraction after navigation)
23471
+ * Minimal context snapshot used on reconnect / navigation events.
23472
23472
  */
23473
23473
  function _extractDOMContext() {
23474
23474
  _extractDOMContext = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee() {
23475
23475
  var _document$querySelect;
23476
23476
  var options,
23477
23477
  limits,
23478
+ mainContent,
23478
23479
  buttons,
23479
23480
  links,
23480
23481
  _extractForms,
23481
23482
  forms,
23482
23483
  sensitiveCount,
23483
- sections,
23484
- headings,
23485
- totalElements,
23486
- visibleInViewport,
23487
23484
  htmlLang,
23488
- browserLang,
23489
23485
  language,
23490
23486
  _args = arguments;
23491
23487
  return _regenerator().w(function (_context) {
23492
23488
  while (1) switch (_context.n) {
23493
23489
  case 0:
23494
23490
  options = _args.length > 0 && _args[0] !== undefined ? _args[0] : {};
23495
- limits = _objectSpread(_objectSpread({}, DEFAULT_LIMITS), options.limits); // Extract all elements
23491
+ limits = _objectSpread(_objectSpread({}, DEFAULT_LIMITS), options.limits);
23492
+ mainContent = extractMainContent(limits);
23496
23493
  buttons = extractButtons(limits);
23497
23494
  links = extractLinks(limits);
23498
23495
  _extractForms = extractForms(limits), forms = _extractForms.forms, sensitiveCount = _extractForms.sensitiveCount;
23499
- sections = extractSections(limits);
23500
- headings = extractHeadings(limits); // Count totals
23501
- totalElements = buttons.length + links.length + forms.reduce(function (sum, f) {
23502
- return sum + f.fields.length;
23503
- }, 0) + sections.length + headings.length;
23504
- visibleInViewport = buttons.filter(function (b) {
23505
- return b.inViewport;
23506
- }).length + links.filter(function (l) {
23507
- return l.inViewport;
23508
- }).length + sections.filter(function (s) {
23509
- return s.inViewport;
23510
- }).length + headings.filter(function (h) {
23511
- return h.inViewport;
23512
- }).length; // Detect site language
23513
- // Priority: HTML lang attribute > browser language
23514
23496
  htmlLang = document.documentElement.lang || ((_document$querySelect = document.querySelector('html')) === null || _document$querySelect === void 0 ? void 0 : _document$querySelect.getAttribute('lang')) || null;
23515
- browserLang = navigator.language || navigator.languages && navigator.languages[0] || null;
23516
- language = htmlLang || browserLang || null;
23497
+ language = htmlLang || navigator.language || navigator.languages && navigator.languages[0] || null;
23517
23498
  return _context.a(2, {
23518
23499
  url: window.location.href,
23519
23500
  title: document.title,
23520
23501
  timestamp: Date.now(),
23521
23502
  language: language,
23522
- // Site language (from HTML lang attribute or browser)
23523
-
23524
23503
  viewport: {
23525
23504
  width: window.innerWidth,
23526
23505
  height: window.innerHeight,
@@ -23528,14 +23507,20 @@ function _extractDOMContext() {
23528
23507
  scrollY: window.scrollY,
23529
23508
  pageHeight: document.documentElement.scrollHeight
23530
23509
  },
23510
+ // ── Primary: actual page content ──────────────────────────────────────
23511
+ content: mainContent.text,
23512
+ contentItems: mainContent.items,
23513
+ contentTruncated: mainContent.truncated,
23514
+ contentSource: mainContent.sourceElement,
23515
+ // ── Secondary: interactive elements ───────────────────────────────────
23531
23516
  buttons: buttons,
23532
23517
  links: links,
23533
23518
  forms: forms,
23534
- sections: sections,
23535
- headings: headings,
23536
23519
  metadata: {
23537
- totalElements: totalElements,
23538
- visibleInViewport: visibleInViewport,
23520
+ totalContentChars: mainContent.text.length,
23521
+ contentItemCount: mainContent.items.length,
23522
+ buttonsCount: buttons.length,
23523
+ linksCount: links.length,
23539
23524
  formsCount: forms.length,
23540
23525
  sensitiveFieldsFiltered: sensitiveCount
23541
23526
  }
@@ -23551,14 +23536,12 @@ function extractMinimalContext() {
23551
23536
  function _extractMinimalContext() {
23552
23537
  _extractMinimalContext = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2() {
23553
23538
  var _document$querySelect2;
23554
- var htmlLang, browserLang, language;
23539
+ var htmlLang, language;
23555
23540
  return _regenerator().w(function (_context2) {
23556
23541
  while (1) switch (_context2.n) {
23557
23542
  case 0:
23558
- // Detect site language
23559
23543
  htmlLang = document.documentElement.lang || ((_document$querySelect2 = document.querySelector('html')) === null || _document$querySelect2 === void 0 ? void 0 : _document$querySelect2.getAttribute('lang')) || null;
23560
- browserLang = navigator.language || navigator.languages && navigator.languages[0] || null;
23561
- language = htmlLang || browserLang || null;
23544
+ language = htmlLang || navigator.language || navigator.languages && navigator.languages[0] || null;
23562
23545
  return _context2.a(2, {
23563
23546
  url: window.location.href,
23564
23547
  title: document.title,
@@ -24039,16 +24022,19 @@ function registerVisualTools(registry) {
24039
24022
  while (1) switch (_context.n) {
24040
24023
  case 0:
24041
24024
  params = _args.length > 0 && _args[0] !== undefined ? _args[0] : {};
24042
- console.log('[TTP] 📋 Reading page structure...');
24025
+ console.log('[TTP] 📋 Reading page content...');
24043
24026
  _context.n = 1;
24044
24027
  return (0,_dom_context_js__WEBPACK_IMPORTED_MODULE_0__.extractDOMContext)(params);
24045
24028
  case 1:
24046
24029
  context = _context.v;
24047
- console.log('[TTP] ✅ Page structure extracted:', {
24048
- buttons: context.buttons.length,
24049
- links: context.links.length,
24050
- forms: context.forms.length,
24051
- headings: context.headings.length
24030
+ console.log('[TTP] ✅ Page content extracted:', {
24031
+ contentChars: context.metadata.totalContentChars,
24032
+ contentItems: context.metadata.contentItemCount,
24033
+ truncated: context.contentTruncated,
24034
+ source: context.contentSource,
24035
+ buttons: context.metadata.buttonsCount,
24036
+ links: context.metadata.linksCount,
24037
+ forms: context.metadata.formsCount
24052
24038
  });
24053
24039
  return _context.a(2, context);
24054
24040
  }
@@ -24267,12 +24253,12 @@ function _extractPageContext() {
24267
24253
  timestamp: domContext.timestamp,
24268
24254
  language: domContext.language,
24269
24255
  viewport: domContext.viewport,
24256
+ content: domContext.content,
24257
+ contentTruncated: domContext.contentTruncated,
24270
24258
  dom: {
24271
24259
  buttons: domContext.buttons,
24272
24260
  links: domContext.links,
24273
24261
  forms: domContext.forms,
24274
- sections: domContext.sections,
24275
- headings: domContext.headings,
24276
24262
  metadata: domContext.metadata
24277
24263
  }
24278
24264
  });
@@ -27616,7 +27602,7 @@ var VoiceSDK_v2 = /*#__PURE__*/function (_EventEmitter) {
27616
27602
 
27617
27603
  // Include SDK build time for debugging
27618
27604
  if (true) {
27619
- helloMessage.lastBuildTime = "2026-06-13T08:36:31.824Z";
27605
+ helloMessage.lastBuildTime = "2026-06-14T07:18:03.004Z";
27620
27606
  }
27621
27607
 
27622
27608
  // Page context is intentionally NOT attached to the hello message.