@cuekit-ai/react 1.3.4 → 1.4.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.
@@ -22729,15 +22729,24 @@ var GlobalStore = {
22729
22729
  var navigation;
22730
22730
  var navigationHandler = null;
22731
22731
  function setNavigationHandler(handler) {
22732
+ console.log("\u{1F9ED} setNavigationHandler called with:", !!handler);
22732
22733
  navigationHandler = handler;
22733
22734
  }
22734
22735
  function navigate(path, params) {
22735
22736
  const safeParams = params || {};
22736
22737
  const absolutePath = path.startsWith("/") ? path : `/${path}`;
22738
+ console.log("\u{1F9ED} navigate() called with:", {
22739
+ path,
22740
+ absolutePath,
22741
+ safeParams,
22742
+ hasNavigationHandler: !!navigationHandler
22743
+ });
22737
22744
  if (navigationHandler) {
22738
22745
  try {
22746
+ console.log("\u{1F9ED} Using navigationHandler:", absolutePath, safeParams);
22739
22747
  navigationHandler(absolutePath, safeParams);
22740
22748
  } catch (error) {
22749
+ console.error("\u{1F9ED} NavigationHandler error:", error);
22741
22750
  }
22742
22751
  return;
22743
22752
  }
@@ -22752,27 +22761,46 @@ function navigate(path, params) {
22752
22761
  navigation.push(fullPath);
22753
22762
  } else {
22754
22763
  if (typeof window !== "undefined") {
22755
- window.location.href = fullPath;
22764
+ if (window.location.hash && window.location.hash.startsWith("#")) {
22765
+ window.location.hash = fullPath;
22766
+ } else {
22767
+ window.location.href = fullPath;
22768
+ }
22756
22769
  }
22757
22770
  }
22758
22771
  }
22759
22772
  var getCurrentPath = () => {
22760
22773
  if (typeof window === "undefined") return "";
22774
+ if (window.location.hash && window.location.hash.startsWith("#")) {
22775
+ const hashPath = window.location.hash.substring(1);
22776
+ return hashPath.split("?")[0];
22777
+ }
22761
22778
  return window.location.pathname;
22762
22779
  };
22763
22780
  var getSearchParams = () => {
22764
22781
  if (typeof window === "undefined") return new URLSearchParams();
22782
+ if (window.location.hash && window.location.hash.includes("?")) {
22783
+ const queryString = window.location.hash.split("?")[1];
22784
+ return new URLSearchParams(queryString);
22785
+ }
22765
22786
  return new URLSearchParams(window.location.search);
22766
22787
  };
22767
22788
  var safeNavigate = (name, params = {}) => {
22789
+ console.log("\u{1F9ED} safeNavigate called with:", { name, params });
22768
22790
  if (name) {
22769
22791
  navigate(name, params);
22770
22792
  } else {
22793
+ console.log("\u{1F9ED} safeNavigate: no name provided, skipping navigation");
22771
22794
  }
22772
22795
  };
22773
22796
  function getCurrentScreenName() {
22774
22797
  try {
22775
22798
  const path = getCurrentPath();
22799
+ const pathParams = getCurrentPathParams();
22800
+ if (path && Object.keys(pathParams).length > 0) {
22801
+ const paramString = Object.entries(pathParams).map(([key, value]) => `${key}=${value}`).join(",");
22802
+ return `${path}?${paramString}`;
22803
+ }
22776
22804
  return path || "UnknownScreen";
22777
22805
  } catch (e2) {
22778
22806
  return "UnknownScreen";
@@ -22794,6 +22822,45 @@ function getCurrentRouteParams() {
22794
22822
  return {};
22795
22823
  }
22796
22824
  }
22825
+ function getCurrentPathParams() {
22826
+ try {
22827
+ const currentPath = getCurrentPath();
22828
+ const params = {};
22829
+ const numericIdMatch = currentPath.match(/\/(\d+)(?:\/|$)/);
22830
+ if (numericIdMatch) {
22831
+ params.id = numericIdMatch[1];
22832
+ }
22833
+ const uuidMatch = currentPath.match(
22834
+ /\/([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})(?:\/|$)/i
22835
+ );
22836
+ if (uuidMatch) {
22837
+ params.uuid = uuidMatch[1];
22838
+ }
22839
+ const slugMatch = currentPath.match(/\/([a-z0-9-]+)(?:\/|$)/i);
22840
+ if (slugMatch && !numericIdMatch && !uuidMatch) {
22841
+ params.slug = slugMatch[1];
22842
+ }
22843
+ return params;
22844
+ } catch (e2) {
22845
+ return {};
22846
+ }
22847
+ }
22848
+ function resolveRoutePath(routePath, params) {
22849
+ try {
22850
+ let resolvedPath = routePath;
22851
+ Object.entries(params).forEach(([key, value]) => {
22852
+ const placeholder = `:${key}`;
22853
+ if (resolvedPath.includes(placeholder)) {
22854
+ resolvedPath = resolvedPath.replace(placeholder, value);
22855
+ }
22856
+ });
22857
+ resolvedPath = resolvedPath.replace(/:\w+/g, "");
22858
+ resolvedPath = resolvedPath.replace(/\/+/g, "/");
22859
+ return resolvedPath;
22860
+ } catch (e2) {
22861
+ return routePath;
22862
+ }
22863
+ }
22797
22864
  function onStateChange() {
22798
22865
  const routeName = getCurrentScreenName();
22799
22866
  const params = getCurrentRouteParams();
@@ -22912,13 +22979,23 @@ function getElementPath2(element) {
22912
22979
  }
22913
22980
 
22914
22981
  // src/utils/element-service.ts
22915
- var INTERACTIVE_ELEMENT_SELECTOR = 'a, button, input, textarea, select, [role="button"], [onclick], [data-ansyr-static], [data-ansyr-dynamic]';
22982
+ var INTERACTIVE_ELEMENT_SELECTOR = 'a, button, select, [role="button"], [role="link"], [role="tab"], [onclick], [onmousedown], [onmouseup], [ontouchstart], [ontouchend], [onkeydown], [onkeyup], [onkeypress], [onchange], [onsubmit], [onfocus], [onblur], [data-ansyr-static], [data-ansyr-dynamic]';
22983
+ var elementCache = /* @__PURE__ */ new Map();
22984
+ var cacheTimestamp = 0;
22985
+ var CACHE_TTL = 5e3;
22916
22986
  function getInteractiveElements() {
22917
22987
  const elements = document.querySelectorAll(INTERACTIVE_ELEMENT_SELECTOR);
22918
22988
  return Array.from(new Set(Array.from(elements)));
22919
22989
  }
22920
22990
  function getImmediateText(element) {
22921
22991
  let text = "";
22992
+ const textAttributes = ["label", "text", "placeholder", "title", "alt", "aria-label"];
22993
+ for (const attr of textAttributes) {
22994
+ const value = element.getAttribute(attr);
22995
+ if (value) {
22996
+ text += value + " ";
22997
+ }
22998
+ }
22922
22999
  if (element.childNodes) {
22923
23000
  for (const node of Array.from(element.childNodes)) {
22924
23001
  if (node.nodeType === 3) {
@@ -22928,12 +23005,30 @@ function getImmediateText(element) {
22928
23005
  }
22929
23006
  return text.trim();
22930
23007
  }
22931
- function captureFullDOMStructure() {
22932
- console.log("\u{1F333} Capturing full DOM structure for Cuekit...");
22933
- const interactiveElements = [];
23008
+ function executeAction(action) {
23009
+ console.log("\u{1F3AF} Executing element action:", action);
23010
+ const { action_type, target_element, target } = action;
23011
+ switch (action_type) {
23012
+ case "click":
23013
+ return clickElement(target_element);
23014
+ case "navigate":
23015
+ return navigateToElement(target_element || target);
23016
+ case "input":
23017
+ case "focus":
23018
+ return focusElement(target_element);
23019
+ case "toggle":
23020
+ return toggleElement(target_element);
23021
+ default:
23022
+ console.warn(`\u26A0\uFE0F Unknown action type: ${action_type}`);
23023
+ return false;
23024
+ }
23025
+ }
23026
+ function captureAllInteractiveElements() {
23027
+ console.log("\u{1F333} Capturing ALL interactive elements for Cuekit...");
23028
+ const interactiveElements = {};
22934
23029
  const descriptionsMap = /* @__PURE__ */ new Map();
22935
- document.querySelectorAll("[data-for]").forEach((el) => {
22936
- const targetId = el.getAttribute("data-for");
23030
+ document.querySelectorAll("[data-ansyr-for]").forEach((el) => {
23031
+ const targetId = el.getAttribute("data-ansyr-for");
22937
23032
  if (!targetId) return;
22938
23033
  const tags = [];
22939
23034
  const description = el.getAttribute("data-ansyr-description");
@@ -22948,110 +23043,115 @@ function captureFullDOMStructure() {
22948
23043
  descriptionsMap.set(targetId, [...existingTags, ...tags]);
22949
23044
  }
22950
23045
  });
22951
- const allElements = getInteractiveElements();
22952
- allElements.forEach((element) => {
23046
+ const allInteractiveElements = getInteractiveElements();
23047
+ console.log("\u{1F333} Found", allInteractiveElements.length, "interactive elements");
23048
+ allInteractiveElements.forEach((element) => {
23049
+ if (!(element instanceof HTMLElement)) return;
22953
23050
  const style = getComputedStyle(element);
22954
- if (element.closest("[data-cuekit-ignore]") || !isElementClickable(element) || element.tagName.toLowerCase() === "script" || style.display === "none" || style.visibility === "hidden") {
23051
+ if (element.closest("[data-cuekit-ignore]") || element.tagName.toLowerCase() === "script" || style.display === "none" || style.visibility === "hidden") {
22955
23052
  return;
22956
23053
  }
23054
+ let elementId = null;
22957
23055
  const staticId = element.getAttribute("data-ansyr-static");
22958
23056
  const dynamicId = element.getAttribute("data-ansyr-dynamic");
22959
- const id = staticId || dynamicId;
23057
+ if (staticId) {
23058
+ elementId = staticId;
23059
+ console.log("\u{1F333} Using pre-assigned static ID:", elementId);
23060
+ } else if (dynamicId) {
23061
+ elementId = dynamicId;
23062
+ console.log("\u{1F333} Using pre-assigned dynamic ID:", elementId);
23063
+ } else {
23064
+ elementId = generateStableDOMId(element);
23065
+ console.log("\u{1F333} Calculated stable DOM ID:", elementId);
23066
+ }
23067
+ if (!elementId) {
23068
+ console.log("\u{1F333} No ID could be determined for element:", element);
23069
+ return;
23070
+ }
22960
23071
  const tags = [];
22961
23072
  const directDescription = element.getAttribute("data-ansyr-description");
22962
23073
  if (directDescription) {
22963
23074
  tags.push(directDescription);
22964
23075
  }
22965
- if (id && descriptionsMap.has(id)) {
22966
- tags.push(...descriptionsMap.get(id) || []);
23076
+ if (descriptionsMap.has(elementId)) {
23077
+ tags.push(...descriptionsMap.get(elementId) || []);
22967
23078
  }
22968
- const dto = {
22969
- testID: id || generateStableDOMId(element),
22970
- type: element.tagName.toLowerCase(),
22971
- textContent: getImmediateText(element) || element.textContent?.trim() || "",
22972
- tags
22973
- };
22974
- interactiveElements.push(dto);
23079
+ const textContent = getImmediateText(element) || element.textContent?.trim() || "";
23080
+ interactiveElements[elementId] = [textContent, ...tags];
23081
+ console.log("\u{1F333} Captured element:", {
23082
+ id: elementId,
23083
+ tagName: element.tagName,
23084
+ textContent: textContent.substring(0, 50),
23085
+ hasStaticId: !!staticId,
23086
+ hasDynamicId: !!dynamicId,
23087
+ isCalculated: !staticId && !dynamicId
23088
+ });
22975
23089
  });
22976
23090
  const result = {
22977
23091
  components: interactiveElements
22978
23092
  };
22979
- console.log("\u{1F333} Full DOM structure captured:", result);
23093
+ console.log("\u{1F333} All interactive elements captured:", result);
22980
23094
  return result;
22981
23095
  }
22982
- function isElementClickable(element) {
22983
- const interactiveSelectors = [
22984
- "button",
22985
- "a",
22986
- "input",
22987
- "select",
22988
- "textarea",
22989
- '[role="button"]',
22990
- '[role="link"]',
22991
- '[role="tab"]',
22992
- "[data-onclick-id]",
22993
- "[data-on-press-id]",
22994
- "[onclick]",
22995
- "[onmousedown]",
22996
- "[onmouseup]",
22997
- "[ontouchstart]",
22998
- "[ontouchend]",
22999
- "[onkeydown]",
23000
- "[onkeyup]",
23001
- "[onkeypress]"
23002
- ];
23003
- for (const selector of interactiveSelectors) {
23004
- if (element.matches(selector)) {
23005
- return true;
23006
- }
23007
- }
23008
- const hasClickEvents = element.onclick !== null || element.getAttribute("onclick") !== null;
23009
- const hasInteractiveEvents = element.ontouchstart !== null || element.getAttribute("ontouchstart") !== null || element.ontouchend !== null || element.getAttribute("ontouchend") !== null || element.onkeydown !== null || element.getAttribute("onkeydown") !== null || element.onkeyup !== null || element.getAttribute("onkeyup") !== null || element.onkeypress !== null || element.getAttribute("onkeypress") !== null;
23010
- const hasPointerCursor = element.style.cursor === "pointer" || getComputedStyle(element).cursor === "pointer";
23011
- const hasTabIndex = element.hasAttribute("tabindex") && parseInt(element.getAttribute("tabindex") || "0") >= 0;
23012
- const hasInteractiveDataAttrs = element.hasAttribute("data-clickable") || element.hasAttribute("data-interactive") || element.hasAttribute("data-action") || element.hasAttribute("data-handler");
23013
- const hasInteractiveAria = element.hasAttribute("aria-pressed") || element.hasAttribute("aria-expanded") || element.hasAttribute("aria-selected") || element.hasAttribute("aria-checked");
23014
- return hasClickEvents || hasInteractiveEvents || hasPointerCursor || hasTabIndex || hasInteractiveDataAttrs || hasInteractiveAria;
23096
+ function clearElementCache() {
23097
+ elementCache.clear();
23098
+ cacheTimestamp = 0;
23015
23099
  }
23016
- function executeAction(action) {
23017
- console.log("\u{1F3AF} Executing element action:", action);
23018
- const { action_type, target_element, target } = action;
23019
- switch (action_type) {
23020
- case "click":
23021
- return clickElement(target_element);
23022
- case "navigate":
23023
- return navigateToElement(target_element || target);
23024
- case "input":
23025
- case "focus":
23026
- return focusElement(target_element);
23027
- case "toggle":
23028
- return toggleElement(target_element);
23029
- default:
23030
- console.warn(`\u26A0\uFE0F Unknown action type: ${action_type}`);
23031
- return false;
23100
+ function validateDynamicElements() {
23101
+ if (false) {
23102
+ const elements = document.querySelectorAll("[data-ansyr-dynamic]");
23103
+ const ids = /* @__PURE__ */ new Set();
23104
+ const duplicates = [];
23105
+ elements.forEach((element) => {
23106
+ const id = element.getAttribute("data-ansyr-dynamic");
23107
+ if (id) {
23108
+ if (ids.has(id)) {
23109
+ duplicates.push(id);
23110
+ }
23111
+ ids.add(id);
23112
+ }
23113
+ });
23114
+ if (duplicates.length > 0) {
23115
+ console.warn("\u{1F6A8} CueKit: Duplicate dynamic IDs found:", duplicates);
23116
+ console.warn(
23117
+ "This can cause incorrect element targeting. Ensure each dynamic element has a unique identifier."
23118
+ );
23119
+ }
23032
23120
  }
23033
23121
  }
23034
- function getFullDOMStructure() {
23035
- return captureFullDOMStructure();
23036
- }
23037
23122
  function clickElement(elementId) {
23123
+ console.log("\u{1F5B1}\uFE0F clickElement called with:", elementId);
23038
23124
  if (!elementId) {
23125
+ console.log("\u{1F5B1}\uFE0F clickElement: no elementId provided");
23039
23126
  return false;
23040
23127
  }
23041
23128
  const domElement = findDOMElementById(elementId);
23129
+ console.log("\u{1F5B1}\uFE0F clickElement: found DOM element:", domElement);
23042
23130
  if (domElement) {
23131
+ console.log("\u{1F5B1}\uFE0F clickElement: attempting to click element:", {
23132
+ tagName: domElement.tagName,
23133
+ id: domElement.id,
23134
+ className: domElement.className,
23135
+ textContent: domElement.textContent?.substring(0, 50)
23136
+ });
23043
23137
  domElement.click();
23138
+ console.log("\u{1F5B1}\uFE0F clickElement: click() called successfully");
23044
23139
  return true;
23045
23140
  }
23141
+ console.log("\u{1F5B1}\uFE0F clickElement: element not found");
23046
23142
  return false;
23047
23143
  }
23048
23144
  function navigateToElement(target) {
23145
+ console.log("\u{1F9ED} navigateToElement called with:", target);
23049
23146
  if (!target) {
23147
+ console.log("\u{1F9ED} navigateToElement: no target provided");
23050
23148
  return false;
23051
23149
  }
23052
23150
  if (target.includes("/") || target.startsWith("http")) {
23151
+ console.log("\u{1F9ED} navigateToElement: using safeNavigate for path:", target);
23053
23152
  safeNavigate(target, {});
23054
23153
  } else {
23154
+ console.log("\u{1F9ED} navigateToElement: using handleNavigationAndClick for element:", target);
23055
23155
  handleNavigationAndClick(target, target);
23056
23156
  }
23057
23157
  return true;
@@ -23090,21 +23190,82 @@ function toggleElement(elementId) {
23090
23190
  }
23091
23191
  }
23092
23192
  function findDOMElementById(elementId) {
23193
+ console.log("\u{1F50D} findDOMElementById called with:", elementId);
23093
23194
  if (!elementId) {
23195
+ console.log("\u{1F50D} findDOMElementById: no elementId provided");
23094
23196
  return null;
23095
23197
  }
23096
- const interactiveElements = getInteractiveElements();
23097
- for (const element of interactiveElements) {
23098
- if (element instanceof HTMLElement) {
23198
+ const now = Date.now();
23199
+ if (now - cacheTimestamp < CACHE_TTL && elementCache.has(elementId)) {
23200
+ const cachedElement = elementCache.get(elementId);
23201
+ console.log("\u{1F50D} findDOMElementById: found in cache:", cachedElement);
23202
+ if (document.contains(cachedElement)) {
23203
+ console.log("\u{1F50D} findDOMElementById: returning cached element");
23204
+ return cachedElement;
23205
+ } else {
23206
+ console.log("\u{1F50D} findDOMElementById: cached element no longer in DOM, removing from cache");
23207
+ elementCache.delete(elementId);
23208
+ }
23209
+ }
23210
+ let foundElement = null;
23211
+ console.log(
23212
+ "\u{1F50D} findDOMElementById: checking for static element with selector:",
23213
+ `[data-ansyr-static="${elementId}"]`
23214
+ );
23215
+ const staticElement = document.querySelector(`[data-ansyr-static="${elementId}"]`);
23216
+ if (staticElement instanceof HTMLElement) {
23217
+ console.log("\u{1F50D} findDOMElementById: found static element:", staticElement);
23218
+ foundElement = staticElement;
23219
+ } else {
23220
+ console.log(
23221
+ "\u{1F50D} findDOMElementById: checking for dynamic element with selector:",
23222
+ `[data-ansyr-dynamic="${elementId}"]`
23223
+ );
23224
+ const dynamicElement = document.querySelector(`[data-ansyr-dynamic="${elementId}"]`);
23225
+ if (dynamicElement instanceof HTMLElement) {
23226
+ console.log("\u{1F50D} findDOMElementById: found dynamic element:", dynamicElement);
23227
+ foundElement = dynamicElement;
23228
+ }
23229
+ }
23230
+ if (!foundElement) {
23231
+ console.log(
23232
+ "\u{1F50D} findDOMElementById: no pre-assigned element found, scanning all interactive elements"
23233
+ );
23234
+ const interactiveElements = getInteractiveElements();
23235
+ console.log("\u{1F50D} findDOMElementById: found", interactiveElements.length, "interactive elements");
23236
+ for (const element of interactiveElements) {
23237
+ if (!(element instanceof HTMLElement)) continue;
23099
23238
  const staticId = element.getAttribute("data-ansyr-static");
23100
23239
  const dynamicId = element.getAttribute("data-ansyr-dynamic");
23101
- const currentElementId = staticId || dynamicId || generateStableDOMId(element);
23240
+ let currentElementId = null;
23241
+ if (staticId) {
23242
+ currentElementId = staticId;
23243
+ } else if (dynamicId) {
23244
+ currentElementId = dynamicId;
23245
+ } else {
23246
+ currentElementId = generateStableDOMId(element);
23247
+ }
23102
23248
  if (currentElementId === elementId) {
23103
- return element;
23249
+ console.log("\u{1F50D} findDOMElementById: found element by ID match:", {
23250
+ element,
23251
+ id: currentElementId,
23252
+ hasStaticId: !!staticId,
23253
+ hasDynamicId: !!dynamicId,
23254
+ isCalculated: !staticId && !dynamicId
23255
+ });
23256
+ foundElement = element;
23257
+ break;
23104
23258
  }
23105
23259
  }
23260
+ if (!foundElement) {
23261
+ console.log("\u{1F50D} findDOMElementById: element not found in interactive elements scan");
23262
+ }
23263
+ }
23264
+ if (foundElement) {
23265
+ elementCache.set(elementId, foundElement);
23266
+ cacheTimestamp = now;
23106
23267
  }
23107
- return null;
23268
+ return foundElement;
23108
23269
  }
23109
23270
 
23110
23271
  // src/utils/webrtc-service.ts
@@ -23123,8 +23284,16 @@ function setAudioContainer(newAudioContainerRef) {
23123
23284
  audioContainerRef = newAudioContainerRef;
23124
23285
  }
23125
23286
  function setWebRTCCallbacks(newCallbacks) {
23287
+ console.log("\u{1F4E1} setWebRTCCallbacks called with:", {
23288
+ hasOnNavigationCommand: !!newCallbacks.onNavigationCommand,
23289
+ hasOnConnectionStateChange: !!newCallbacks.onConnectionStateChange,
23290
+ hasOnParticipantUpdate: !!newCallbacks.onParticipantUpdate
23291
+ });
23126
23292
  callbacks = newCallbacks;
23127
23293
  }
23294
+ function getCurrentCallbacks() {
23295
+ return callbacks;
23296
+ }
23128
23297
  async function authenticate(userIdentity, apiKey, appId) {
23129
23298
  try {
23130
23299
  const authPayload = {
@@ -23215,12 +23384,34 @@ function setupEventListeners() {
23215
23384
  track.detach().forEach((element) => element.remove());
23216
23385
  }).on(RoomEvent.DataReceived, (payload, participant) => {
23217
23386
  const decodedPayload = new TextDecoder().decode(payload);
23218
- try {
23219
- const message = JSON.parse(decodedPayload);
23220
- callbacks.onNavigationCommand?.(message);
23221
- } catch (error) {
23222
- const message = decodedPayload;
23223
- callbacks.onNavigationCommand?.({ type: "raw_text", data: message });
23387
+ console.log("\u{1F4E1} WebRTC DataReceived:", { decodedPayload, participant: participant?.identity });
23388
+ if (decodedPayload.includes("|")) {
23389
+ const parts = decodedPayload.split("|");
23390
+ const textPart = parts[0];
23391
+ const jsonPart = parts[1];
23392
+ console.log("\u{1F4E1} WebRTC Pipe-separated message:", { textPart, jsonPart });
23393
+ if (textPart) {
23394
+ callbacks.onNavigationCommand?.({ type: "speech_text", data: textPart });
23395
+ }
23396
+ if (jsonPart) {
23397
+ try {
23398
+ const message = JSON.parse(jsonPart);
23399
+ console.log("\u{1F4E1} WebRTC Parsed JSON message:", message);
23400
+ callbacks.onNavigationCommand?.(message);
23401
+ } catch (error) {
23402
+ console.log("\u{1F4E1} WebRTC JSON parse error for JSON part:", error, "JSON part:", jsonPart);
23403
+ }
23404
+ }
23405
+ } else {
23406
+ try {
23407
+ const message = JSON.parse(decodedPayload);
23408
+ console.log("\u{1F4E1} WebRTC Parsed message:", message);
23409
+ callbacks.onNavigationCommand?.(message);
23410
+ } catch (error) {
23411
+ console.log("\u{1F4E1} WebRTC JSON parse error:", error, "Raw payload:", decodedPayload);
23412
+ const message = decodedPayload;
23413
+ callbacks.onNavigationCommand?.({ type: "raw_text", data: message });
23414
+ }
23224
23415
  }
23225
23416
  }).on(RoomEvent.Disconnected, () => {
23226
23417
  setWebRTCConnectionState({ isConnected: false, isConnecting: false });
@@ -23274,17 +23465,19 @@ async function sendUserCommand(command) {
23274
23465
  await sendData(command);
23275
23466
  }
23276
23467
  async function sendRuntimeData() {
23468
+ console.log("\u{1F9E0} checking room:", room);
23277
23469
  if (!room) {
23278
23470
  return;
23279
23471
  }
23472
+ console.log("\u{1F9E0} Sending runtime data", room);
23280
23473
  try {
23281
- const domStructure = captureFullDOMStructure();
23474
+ const allInteractiveElements = captureAllInteractiveElements();
23282
23475
  const screenName = getCurrentScreenName();
23283
23476
  const response = {
23284
23477
  type: "runtime_data_response",
23285
23478
  data: {
23286
- components: domStructure.components,
23287
- current_screen: screenName
23479
+ components: allInteractiveElements.components,
23480
+ currentRoute: screenName
23288
23481
  }
23289
23482
  };
23290
23483
  await sendData(JSON.stringify(response));
@@ -23349,6 +23542,8 @@ export {
23349
23542
  setWebRTCConfig,
23350
23543
  GlobalStore,
23351
23544
  setNavigationHandler,
23545
+ getCurrentPathParams,
23546
+ resolveRoutePath,
23352
23547
  onStateChange,
23353
23548
  WEBRTC_BACKEND_SERVER_URL,
23354
23549
  RoomEvent,
@@ -23356,12 +23551,14 @@ export {
23356
23551
  Track,
23357
23552
  createAudioAnalyser,
23358
23553
  ConnectionState,
23359
- captureFullDOMStructure,
23360
23554
  executeAction,
23361
- getFullDOMStructure,
23555
+ captureAllInteractiveElements,
23556
+ clearElementCache,
23557
+ validateDynamicElements,
23362
23558
  setServerUrl,
23363
23559
  setAudioContainer,
23364
23560
  setWebRTCCallbacks,
23561
+ getCurrentCallbacks,
23365
23562
  authenticate,
23366
23563
  connectToRoom,
23367
23564
  sendData,
package/dist/index.d.mts CHANGED
@@ -129,25 +129,15 @@ interface ServerConfig {
129
129
  token_ttl_seconds: number;
130
130
  server_version: string;
131
131
  }
132
+ interface AIIntentData {
133
+ actionType: 'navigate' | 'click' | 'input' | 'scroll';
134
+ routeName?: string;
135
+ elementId?: string;
136
+ }
132
137
  interface NavigationCommand {
133
- type: 'static_data_ready' | 'ai_intent' | 'user_speech_text' | 'ai_speech_text';
134
- data?: {
135
- app_id?: string;
136
- components?: any[];
137
- intents?: any[];
138
- pages_count?: number;
139
- elements_count?: number;
140
- };
141
- intent?: string;
142
- actionType?: string;
143
- text?: string;
144
- confidence?: number;
145
- target_element?: string;
146
- current_page?: string;
147
- user_input?: string;
148
- speaker?: 'user' | 'ai';
149
- duration?: number;
138
+ type: 'ai_intent';
150
139
  timestamp?: number;
140
+ data: AIIntentData;
151
141
  }
152
142
  declare function sendData(data: string, reliable?: boolean): Promise<void>;
153
143
  declare function sendScreenStatus(screenData: any): Promise<void>;
@@ -254,20 +244,13 @@ declare const initWebRTCWithDeployedBackend: (apiKey: string, customConfig?: Par
254
244
  */
255
245
  declare const initWebRTC: (apiKey: string) => WebRTCServerConfig;
256
246
 
257
- interface InteractiveElementDto {
258
- testID: string;
259
- type: string;
260
- textContent: string;
261
- tags: string[];
262
- }
247
+ type InteractiveElement = {
248
+ [btnId: string]: string[];
249
+ };
263
250
  interface DOMStructurePayload {
264
- components: InteractiveElementDto[];
251
+ components: InteractiveElement;
265
252
  }
266
253
 
267
- /**
268
- * Capture the full DOM structure as a flat list of interactive elements
269
- */
270
- declare function captureFullDOMStructure(): DOMStructurePayload;
271
254
  interface ElementAction {
272
255
  action_type: 'click' | 'navigate' | 'input' | 'focus' | 'toggle';
273
256
  target_element?: string;
@@ -275,7 +258,23 @@ interface ElementAction {
275
258
  instruction?: string;
276
259
  }
277
260
  declare function executeAction(action: ElementAction): boolean;
278
- declare function getFullDOMStructure(): DOMStructurePayload;
261
+ /**
262
+ * Captures ALL interactive elements on the page.
263
+ * Uses pre-assigned IDs (data-ansyr-static, data-ansyr-dynamic) when available,
264
+ * otherwise calculates stable DOM IDs for elements without pre-assigned IDs.
265
+ *
266
+ * This ensures comprehensive coverage of all interactive elements for AI interaction.
267
+ */
268
+ declare function captureAllInteractiveElements(): DOMStructurePayload;
269
+ /**
270
+ * Clears the element cache. Call this when the DOM structure changes significantly.
271
+ */
272
+ declare function clearElementCache(): void;
273
+ /**
274
+ * Validates dynamic elements in development mode.
275
+ * Checks for duplicate IDs and provides warnings.
276
+ */
277
+ declare function validateDynamicElements(): void;
279
278
 
280
279
  /**
281
280
  * Generates a stable, unique 8-character ID for an interactive element.
@@ -287,4 +286,15 @@ declare function getFullDOMStructure(): DOMStructurePayload;
287
286
  */
288
287
  declare function generateDynamicId(routePath: string, elementIdentifier: string): string;
289
288
 
290
- export { BorderGlow, ChatPopup, type ChatPopupProps, CuekitProvider, type DOMStructurePayload, type ElementAction, InitCuekit, type InteractiveElementDto, MicButton, type MicButtonProps, type MicState$1 as MicState, type NavigationCommand, type ServerConfig, type TokenRequest, type TokenResponse, VoiceIntensityVisualizer, type WebRTCServerConfig, captureFullDOMStructure, configureWebRTCServer, executeAction, generateDynamicId, getFullDOMStructure, getWebRTCServerConfig, initWebRTC, initWebRTCWithDeployedBackend, useCuekit, useQubeContext, useWebRTC };
289
+ /**
290
+ * Extracts route parameters from the current URL path.
291
+ * For routes like /form/:id, extracts { id: "123" } from /form/123
292
+ */
293
+ declare function getCurrentPathParams(): Record<string, string>;
294
+ /**
295
+ * Resolves a route path with parameters.
296
+ * Example: resolveRoutePath('/form/:id', { id: '123' }) -> '/form/123'
297
+ */
298
+ declare function resolveRoutePath(routePath: string, params: Record<string, string>): string;
299
+
300
+ export { BorderGlow, ChatPopup, type ChatPopupProps, CuekitProvider, type DOMStructurePayload, type ElementAction, InitCuekit, type InteractiveElement, MicButton, type MicButtonProps, type MicState$1 as MicState, type NavigationCommand, type ServerConfig, type TokenRequest, type TokenResponse, VoiceIntensityVisualizer, type WebRTCServerConfig, captureAllInteractiveElements, clearElementCache, configureWebRTCServer, executeAction, generateDynamicId, getCurrentPathParams, getWebRTCServerConfig, initWebRTC, initWebRTCWithDeployedBackend, resolveRoutePath, useCuekit, useQubeContext, useWebRTC, validateDynamicElements };