@cuekit-ai/react 1.2.3 → 1.3.1

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.
@@ -22668,11 +22668,459 @@ var setWebRTCConnectionState = (state) => {
22668
22668
  };
22669
22669
 
22670
22670
  // src/constants/index.ts
22671
- var WEBRTC_BACKEND_SERVER_URL = "https://api-webrtc.cuekit.ai";
22671
+ var WEBRTC_BACKEND_SERVER_URL = "https://api-webrtc-dev.ansyr.ai";
22672
+
22673
+ // src/utils/jsx-encoder.ts
22674
+ function generateStableDOMId(element) {
22675
+ const tagName = element.tagName.toLowerCase();
22676
+ const text = (element.textContent || "").trim().substring(0, 50);
22677
+ let sibling = element.previousElementSibling;
22678
+ let position = 1;
22679
+ while (sibling) {
22680
+ if (sibling.tagName === element.tagName) {
22681
+ position++;
22682
+ }
22683
+ sibling = sibling.previousElementSibling;
22684
+ }
22685
+ const path = getElementPath(element);
22686
+ const idString = `${tagName}[${position}]_(${text})_${path}`;
22687
+ let hash = 0;
22688
+ for (let i = 0; i < idString.length; i++) {
22689
+ const char = idString.charCodeAt(i);
22690
+ hash = (hash << 5) - hash + char;
22691
+ hash |= 0;
22692
+ }
22693
+ return hash.toString(36);
22694
+ }
22695
+ function getElementPath(element) {
22696
+ if (element.id) {
22697
+ return `id(${element.id})`;
22698
+ }
22699
+ if (element.tagName.toLowerCase() === "body") {
22700
+ return "/body";
22701
+ }
22702
+ let ix = 0;
22703
+ const siblings = element.parentNode?.children || new HTMLCollection();
22704
+ for (let i = 0; i < siblings.length; i++) {
22705
+ const sibling = siblings[i];
22706
+ if (sibling === element) {
22707
+ return `${getElementPath(element.parentNode)}/${element.tagName}[${ix + 1}]`;
22708
+ }
22709
+ if (sibling.nodeType === 1 && sibling.tagName === element.tagName) {
22710
+ ix++;
22711
+ }
22712
+ }
22713
+ return "not_found";
22714
+ }
22715
+
22716
+ // src/core/intent-store.ts
22717
+ var store = {
22718
+ screenMetadata: {},
22719
+ allElementsData: []
22720
+ };
22721
+ var GlobalStore = {
22722
+ // 🔹 Screen Metadata Methods
22723
+ setMetadata(screen, metadata) {
22724
+ store.screenMetadata[screen] = metadata;
22725
+ },
22726
+ getMetadata(screen) {
22727
+ return store.screenMetadata[screen];
22728
+ },
22729
+ clearMetadata(screen) {
22730
+ delete store.screenMetadata[screen];
22731
+ },
22732
+ // 🔹 Generic Store Access Methods
22733
+ setData(key, value) {
22734
+ store[key] = value;
22735
+ },
22736
+ getData(key) {
22737
+ return store[key];
22738
+ },
22739
+ clearData(key) {
22740
+ delete store[key];
22741
+ },
22742
+ // 🔹 Element Data Management
22743
+ setElement(elementData) {
22744
+ const index = store.allElementsData.findIndex((e2) => e2.elementId === elementData.elementId);
22745
+ if (index >= 0) {
22746
+ console.log("Updating existing element");
22747
+ store.allElementsData[index] = elementData;
22748
+ } else {
22749
+ console.log("Adding new element");
22750
+ store.allElementsData.push(elementData);
22751
+ }
22752
+ },
22753
+ getElementById(elementId) {
22754
+ const match = store.allElementsData.find((e2) => e2.elementId === elementId);
22755
+ if (!match) {
22756
+ console.warn(`[GlobalStore] No element found for ID: ${elementId}`);
22757
+ console.log("All elements in store:", store.allElementsData);
22758
+ }
22759
+ return match;
22760
+ },
22761
+ deleteElementById(id) {
22762
+ store.allElementsData = store.allElementsData.filter((e2) => e2.elementId !== id);
22763
+ },
22764
+ clearAllElements() {
22765
+ store.allElementsData = [];
22766
+ }
22767
+ };
22768
+
22769
+ // src/core/navigation.ts
22770
+ var navigation;
22771
+ var navigationHandler = null;
22772
+ function setNavigationHandler(handler) {
22773
+ navigationHandler = handler;
22774
+ }
22775
+ function navigate(path, params) {
22776
+ const safeParams = params || {};
22777
+ const absolutePath = path.startsWith("/") ? path : `/${path}`;
22778
+ if (navigationHandler) {
22779
+ try {
22780
+ navigationHandler(absolutePath, safeParams);
22781
+ } catch (error) {
22782
+ console.error("[CueKit] navigation handler failed, falling back to default:", error);
22783
+ }
22784
+ return;
22785
+ }
22786
+ let fullPath = absolutePath;
22787
+ if (safeParams) {
22788
+ const searchParams = new URLSearchParams(safeParams).toString();
22789
+ if (searchParams) {
22790
+ fullPath += `?${searchParams}`;
22791
+ }
22792
+ }
22793
+ if (navigation) {
22794
+ navigation.push(fullPath);
22795
+ } else {
22796
+ if (typeof window !== "undefined") {
22797
+ window.location.href = fullPath;
22798
+ }
22799
+ }
22800
+ }
22801
+ var getCurrentPath = () => {
22802
+ if (typeof window === "undefined") return "";
22803
+ return window.location.pathname;
22804
+ };
22805
+ var getSearchParams = () => {
22806
+ if (typeof window === "undefined") return new URLSearchParams();
22807
+ return new URLSearchParams(window.location.search);
22808
+ };
22809
+ var safeNavigate = (name, params = {}) => {
22810
+ if (name) {
22811
+ navigate(name, params);
22812
+ } else {
22813
+ console.warn("[CueKit] route name not provided");
22814
+ }
22815
+ };
22816
+ function getCurrentScreenName() {
22817
+ try {
22818
+ const path = getCurrentPath();
22819
+ return path || "UnknownScreen";
22820
+ } catch (e2) {
22821
+ return "UnknownScreen";
22822
+ }
22823
+ }
22824
+ function getCurrentRouteParams() {
22825
+ try {
22826
+ const params = {};
22827
+ const searchParams = getSearchParams();
22828
+ if (searchParams instanceof URLSearchParams) {
22829
+ searchParams.forEach((value, key) => {
22830
+ params[key] = value;
22831
+ });
22832
+ } else {
22833
+ return searchParams;
22834
+ }
22835
+ return params;
22836
+ } catch (e2) {
22837
+ return {};
22838
+ }
22839
+ }
22840
+ function onStateChange() {
22841
+ const routeName = getCurrentScreenName();
22842
+ const params = getCurrentRouteParams();
22843
+ if (params && params.metadata) {
22844
+ try {
22845
+ const metadata = JSON.parse(params.metadata);
22846
+ GlobalStore.setMetadata(routeName, metadata);
22847
+ } catch (error) {
22848
+ console.error("Failed to parse metadata from URL:", error);
22849
+ }
22850
+ }
22851
+ }
22852
+ var handleNavigationAndClick = (routeName, elementHash) => {
22853
+ safeNavigate(routeName);
22854
+ if (typeof MutationObserver === "undefined" || typeof document === "undefined") return;
22855
+ const observer = new MutationObserver((mutationsList, observer2) => {
22856
+ setTimeout(() => {
22857
+ const allElements = document.querySelectorAll("*");
22858
+ let elementToClick = null;
22859
+ for (const element of allElements) {
22860
+ if (element instanceof HTMLElement) {
22861
+ const tagName = element.tagName.toLowerCase();
22862
+ const text = (element.textContent || "").trim().substring(0, 50);
22863
+ let sibling = element.previousElementSibling;
22864
+ let position = 1;
22865
+ while (sibling) {
22866
+ if (sibling.tagName === element.tagName) {
22867
+ position++;
22868
+ }
22869
+ sibling = sibling.previousElementSibling;
22870
+ }
22871
+ const path = getElementPath2(element);
22872
+ const idString = `${tagName}[${position}]_(${text})_${path}`;
22873
+ let hash = 0;
22874
+ for (let i = 0; i < idString.length; i++) {
22875
+ const char = idString.charCodeAt(i);
22876
+ hash = (hash << 5) - hash + char;
22877
+ hash |= 0;
22878
+ }
22879
+ const elementHashValue = hash.toString(36);
22880
+ if (elementHashValue === elementHash) {
22881
+ elementToClick = element;
22882
+ break;
22883
+ }
22884
+ }
22885
+ }
22886
+ if (elementToClick) {
22887
+ elementToClick.click();
22888
+ observer2.disconnect();
22889
+ }
22890
+ }, 100);
22891
+ });
22892
+ observer.observe(document.body, { childList: true, subtree: true });
22893
+ };
22894
+ function getElementPath2(element) {
22895
+ if (element.id) {
22896
+ return `id(${element.id})`;
22897
+ }
22898
+ const path = [];
22899
+ let current = element;
22900
+ while (current && current !== document.body) {
22901
+ let index = 1;
22902
+ let sibling = current.previousElementSibling;
22903
+ while (sibling) {
22904
+ if (sibling.tagName === current.tagName) {
22905
+ index++;
22906
+ }
22907
+ sibling = sibling.previousElementSibling;
22908
+ }
22909
+ path.unshift(`${current.tagName.toLowerCase()}[${index}]`);
22910
+ current = current.parentElement;
22911
+ }
22912
+ return path.join("/");
22913
+ }
22914
+
22915
+ // src/utils/element-service.ts
22916
+ var INTERACTIVE_ELEMENT_SELECTOR = 'a, button, input, textarea, select, [role="button"], [onclick]';
22917
+ function getInteractiveElements() {
22918
+ return document.querySelectorAll(INTERACTIVE_ELEMENT_SELECTOR);
22919
+ }
22920
+ function getImmediateText(element) {
22921
+ let text = "";
22922
+ if (element.childNodes) {
22923
+ for (const node of Array.from(element.childNodes)) {
22924
+ if (node.nodeType === 3) {
22925
+ text += node.textContent || "";
22926
+ }
22927
+ }
22928
+ }
22929
+ return text.trim();
22930
+ }
22931
+ function captureFullDOMStructure() {
22932
+ console.log("\u{1F333} Capturing full DOM structure...");
22933
+ const components = [];
22934
+ const interactiveElements = getInteractiveElements();
22935
+ interactiveElements.forEach((element) => {
22936
+ if (element instanceof HTMLElement && !element.closest("[data-cuekit-ignore]")) {
22937
+ const nodeData = buildFlatDOMNode(element);
22938
+ if (nodeData) {
22939
+ components.push(nodeData);
22940
+ }
22941
+ }
22942
+ });
22943
+ const result = { components };
22944
+ console.log("\u{1F333} Full DOM structure captured:", result);
22945
+ return result;
22946
+ }
22947
+ function buildFlatDOMNode(element) {
22948
+ if (element.tagName.toLowerCase() === "script" || element.hasAttribute("data-cuekit-ignore") || element.style.display === "none" || element.style.visibility === "hidden") {
22949
+ return null;
22950
+ }
22951
+ const hash = generateStableDOMId(element);
22952
+ const text = getImmediateText(element).substring(0, 100);
22953
+ const isClickable = isElementClickable(element);
22954
+ const componentType = element.tagName.toLowerCase();
22955
+ return {
22956
+ hash,
22957
+ text,
22958
+ isClickable,
22959
+ componentType,
22960
+ children: []
22961
+ // No children in a flat structure
22962
+ };
22963
+ }
22964
+ function isElementClickable(element) {
22965
+ const interactiveSelectors = [
22966
+ "button",
22967
+ "a",
22968
+ "input",
22969
+ "select",
22970
+ "textarea",
22971
+ '[role="button"]',
22972
+ '[role="link"]',
22973
+ '[role="tab"]',
22974
+ "[data-onclick-id]",
22975
+ "[data-on-press-id]",
22976
+ "[onclick]",
22977
+ "[onmousedown]",
22978
+ "[onmouseup]",
22979
+ "[ontouchstart]",
22980
+ "[ontouchend]",
22981
+ "[onkeydown]",
22982
+ "[onkeyup]",
22983
+ "[onkeypress]"
22984
+ ];
22985
+ for (const selector of interactiveSelectors) {
22986
+ if (element.matches(selector)) {
22987
+ return true;
22988
+ }
22989
+ }
22990
+ const hasClickEvents = element.onclick !== null || element.getAttribute("onclick") !== null;
22991
+ 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;
22992
+ const hasPointerCursor = element.style.cursor === "pointer" || getComputedStyle(element).cursor === "pointer";
22993
+ const hasTabIndex = element.hasAttribute("tabindex") && parseInt(element.getAttribute("tabindex") || "0") >= 0;
22994
+ const hasInteractiveDataAttrs = element.hasAttribute("data-clickable") || element.hasAttribute("data-interactive") || element.hasAttribute("data-action") || element.hasAttribute("data-handler");
22995
+ const hasInteractiveAria = element.hasAttribute("aria-pressed") || element.hasAttribute("aria-expanded") || element.hasAttribute("aria-selected") || element.hasAttribute("aria-checked");
22996
+ return hasClickEvents || hasInteractiveEvents || hasPointerCursor || hasTabIndex || hasInteractiveDataAttrs || hasInteractiveAria;
22997
+ }
22998
+ function executeAction(action) {
22999
+ console.log("\u{1F3AF} Executing element action:", action);
23000
+ const { action_type, target_element, target } = action;
23001
+ switch (action_type) {
23002
+ case "click":
23003
+ return clickElement(target_element);
23004
+ case "navigate":
23005
+ return navigateToElement(target_element || target);
23006
+ case "input":
23007
+ case "focus":
23008
+ return focusElement(target_element);
23009
+ case "toggle":
23010
+ return toggleElement(target_element);
23011
+ default:
23012
+ console.warn(`\u26A0\uFE0F Unknown action type: ${action_type}`);
23013
+ return false;
23014
+ }
23015
+ }
23016
+ function getFullDOMStructure() {
23017
+ console.log("\u{1F333} ElementService: Getting full DOM structure...");
23018
+ return captureFullDOMStructure();
23019
+ }
23020
+ function clickElement(elementId) {
23021
+ if (!elementId) {
23022
+ console.warn("\u26A0\uFE0F No element ID provided for click action");
23023
+ return false;
23024
+ }
23025
+ const domStructure = getFullDOMStructure();
23026
+ const elementToClick = findElementById(domStructure, elementId);
23027
+ if (elementToClick) {
23028
+ console.log(`\u{1F3AF} Clicking element: ${elementId}`);
23029
+ const domElement = findDOMElementById(elementId);
23030
+ if (domElement) {
23031
+ domElement.click();
23032
+ return true;
23033
+ }
23034
+ } else {
23035
+ console.warn(`\u26A0\uFE0F Element not found: ${elementId}`);
23036
+ }
23037
+ return false;
23038
+ }
23039
+ function navigateToElement(target) {
23040
+ if (!target) {
23041
+ console.warn("\u26A0\uFE0F No target provided for navigation action");
23042
+ return false;
23043
+ }
23044
+ console.log(`\u{1F9ED} Navigating to: ${target}`);
23045
+ if (target.includes("/") || target.startsWith("http")) {
23046
+ safeNavigate(target, {});
23047
+ } else {
23048
+ handleNavigationAndClick(target, target);
23049
+ }
23050
+ return true;
23051
+ }
23052
+ function focusElement(elementId) {
23053
+ if (!elementId) {
23054
+ console.warn("\u26A0\uFE0F No element ID provided for focus action");
23055
+ return false;
23056
+ }
23057
+ const domElement = findDOMElementById(elementId);
23058
+ if (domElement instanceof HTMLInputElement || domElement instanceof HTMLTextAreaElement || domElement instanceof HTMLSelectElement) {
23059
+ console.log(`\u{1F4DD} Focusing element: ${elementId}`);
23060
+ domElement.focus();
23061
+ return true;
23062
+ } else {
23063
+ console.warn(`\u26A0\uFE0F Focusable element not found: ${elementId}`);
23064
+ return false;
23065
+ }
23066
+ }
23067
+ function toggleElement(elementId) {
23068
+ if (!elementId) {
23069
+ console.warn("\u26A0\uFE0F No element ID provided for toggle action");
23070
+ return false;
23071
+ }
23072
+ const domElement = findDOMElementById(elementId);
23073
+ if (domElement instanceof HTMLElement) {
23074
+ console.log(`\u{1F504} Toggling element: ${elementId}`);
23075
+ if (domElement instanceof HTMLInputElement) {
23076
+ if (domElement.type === "checkbox") {
23077
+ domElement.checked = !domElement.checked;
23078
+ } else if (domElement.type === "radio") {
23079
+ domElement.checked = true;
23080
+ }
23081
+ domElement.dispatchEvent(new Event("change", { bubbles: true }));
23082
+ } else {
23083
+ domElement.click();
23084
+ }
23085
+ return true;
23086
+ } else {
23087
+ console.warn(`\u26A0\uFE0F Toggleable element not found: ${elementId}`);
23088
+ return false;
23089
+ }
23090
+ }
23091
+ function findElementById(domStructure, elementId) {
23092
+ const searchInComponents = (components) => {
23093
+ for (const component of components) {
23094
+ if (component.hash === elementId) {
23095
+ return component;
23096
+ }
23097
+ if (component.children.length > 0) {
23098
+ const found = searchInComponents(component.children);
23099
+ if (found) return found;
23100
+ }
23101
+ }
23102
+ return null;
23103
+ };
23104
+ return searchInComponents(domStructure.components);
23105
+ }
23106
+ function findDOMElementById(elementId) {
23107
+ const interactiveElements = getInteractiveElements();
23108
+ for (const element of interactiveElements) {
23109
+ if (element instanceof HTMLElement) {
23110
+ console.log("\u{1F50D} Checking element:", element);
23111
+ const hash = generateStableDOMId(element);
23112
+ console.log("\u{1F50D} Generated hash:", hash);
23113
+ if (hash === elementId) {
23114
+ console.log("\u{1F50D} Found element:", element);
23115
+ return element;
23116
+ }
23117
+ }
23118
+ }
23119
+ return null;
23120
+ }
22672
23121
 
22673
23122
  // src/utils/webrtc-service.ts
22674
23123
  var room = null;
22675
- var eventSource = null;
22676
23124
  var reconnectTimeout = null;
22677
23125
  var serverUrl = WEBRTC_BACKEND_SERVER_URL || "https://bdd4c945f073.ngrok-free.app";
22678
23126
  var callbacks = {};
@@ -22792,19 +23240,19 @@ function setupEventListeners() {
22792
23240
  }).on(RoomEvent.TrackUnsubscribed, (track) => {
22793
23241
  track.detach().forEach((element) => element.remove());
22794
23242
  }).on(RoomEvent.DataReceived, (payload, participant) => {
22795
- handleDataReceived(payload, participant);
23243
+ console.log("\u{1F4E1} LiveKit data received:", new TextDecoder().decode(payload));
23244
+ try {
23245
+ const message = JSON.parse(new TextDecoder().decode(payload));
23246
+ console.log("\u{1F4E1} LiveKit data received:", message);
23247
+ callbacks.onNavigationCommand?.(message);
23248
+ } catch (error) {
23249
+ const message = new TextDecoder().decode(payload);
23250
+ callbacks.onNavigationCommand?.({ type: "raw_text", data: message });
23251
+ }
22796
23252
  }).on(RoomEvent.Disconnected, () => {
22797
23253
  setWebRTCConnectionState({ isConnected: false, isConnecting: false });
22798
23254
  });
22799
23255
  }
22800
- function handleDataReceived(payload, participant) {
22801
- try {
22802
- const message = JSON.parse(new TextDecoder().decode(payload));
22803
- callbacks.onNavigationCommand?.(message);
22804
- } catch (error) {
22805
- console.error("\u{1F3A4} WebRTCService: Error parsing data:", error);
22806
- }
22807
- }
22808
23256
  function updateParticipantsList() {
22809
23257
  if (!room) return;
22810
23258
  const participants = [
@@ -22817,7 +23265,10 @@ function updateParticipantsList() {
22817
23265
  async function sendData(data, reliable = true) {
22818
23266
  if (!room) throw new Error("Not connected to room");
22819
23267
  try {
22820
- await room.localParticipant.publishData(new TextEncoder().encode(JSON.stringify(data)), {
23268
+ console.log("\u{1F4E1} LiveKit data sending:", data);
23269
+ const encoder = new TextEncoder();
23270
+ const encodedData = encoder.encode(data);
23271
+ await room.localParticipant.publishData(encodedData, {
22821
23272
  reliable
22822
23273
  });
22823
23274
  } catch (error) {
@@ -22848,14 +23299,30 @@ function getParticipants() {
22848
23299
  }
22849
23300
  async function sendUserCommand(command) {
22850
23301
  if (!room) return;
22851
- const userCommand = {
22852
- type: "user_command",
22853
- data: {
22854
- command,
22855
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
22856
- }
22857
- };
22858
- await sendData(userCommand);
23302
+ console.log(`\u{1F4AC} Sending user command: "${command}"`);
23303
+ await sendData(command);
23304
+ }
23305
+ async function sendRuntimeData() {
23306
+ if (!room) {
23307
+ console.error("\u274C Cannot send runtime data without a room connection");
23308
+ return;
23309
+ }
23310
+ try {
23311
+ const domStructure = captureFullDOMStructure();
23312
+ const screenName = getCurrentScreenName();
23313
+ const response = {
23314
+ type: "runtime_data_response",
23315
+ data: {
23316
+ components: domStructure.components,
23317
+ current_screen: screenName
23318
+ }
23319
+ };
23320
+ console.log("\u{1F4E6} Sending runtime data response");
23321
+ await sendData(JSON.stringify(response));
23322
+ console.log("\u{1F4E6} Runtime data sent successfully");
23323
+ } catch (error) {
23324
+ console.error("\u274C Failed to send runtime data:", error);
23325
+ }
22859
23326
  }
22860
23327
  async function sendStaticData(componentData, appId = "default") {
22861
23328
  try {
@@ -22886,10 +23353,6 @@ async function disconnectFromRoom() {
22886
23353
  await room.disconnect();
22887
23354
  room = null;
22888
23355
  }
22889
- if (eventSource) {
22890
- eventSource.close();
22891
- eventSource = null;
22892
- }
22893
23356
  if (reconnectTimeout) {
22894
23357
  clearTimeout(reconnectTimeout);
22895
23358
  reconnectTimeout = null;
@@ -22913,6 +23376,9 @@ export {
22913
23376
  setApiKey,
22914
23377
  setAppId,
22915
23378
  setWebRTCConfig,
23379
+ GlobalStore,
23380
+ setNavigationHandler,
23381
+ onStateChange,
22916
23382
  WEBRTC_BACKEND_SERVER_URL,
22917
23383
  RoomEvent,
22918
23384
  ParticipantEvent,
@@ -22920,6 +23386,9 @@ export {
22920
23386
  createAudioAnalyser,
22921
23387
  Participant,
22922
23388
  ConnectionState,
23389
+ captureFullDOMStructure,
23390
+ executeAction,
23391
+ getFullDOMStructure,
22923
23392
  setServerUrl,
22924
23393
  setAudioContainer,
22925
23394
  setWebRTCCallbacks,
@@ -22931,6 +23400,7 @@ export {
22931
23400
  getRoomName,
22932
23401
  getParticipants,
22933
23402
  sendUserCommand,
23403
+ sendRuntimeData,
22934
23404
  sendStaticData,
22935
23405
  disconnectFromRoom,
22936
23406
  getRoom