@modelnex/sdk 0.5.51 → 0.5.53

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.
@@ -0,0 +1,10 @@
1
+ import {
2
+ clearAOMMap,
3
+ generateMinifiedAOM,
4
+ getElementByUid
5
+ } from "./chunk-N65UEB6X.mjs";
6
+ export {
7
+ clearAOMMap,
8
+ generateMinifiedAOM,
9
+ getElementByUid
10
+ };
@@ -0,0 +1,10 @@
1
+ import {
2
+ clearAOMMap,
3
+ generateMinifiedAOM,
4
+ getElementByUid
5
+ } from "./chunk-H4LUY7LI.mjs";
6
+ export {
7
+ clearAOMMap,
8
+ generateMinifiedAOM,
9
+ getElementByUid
10
+ };
@@ -0,0 +1,243 @@
1
+ // src/utils/editable-controls.ts
2
+ var EDITABLE_ROLES = /* @__PURE__ */ new Set(["textbox", "combobox"]);
3
+ var EDITABLE_CONTROL_SELECTOR = [
4
+ 'input:not([type="hidden"])',
5
+ "textarea",
6
+ "select",
7
+ '[contenteditable="true"]',
8
+ '[role="textbox"]',
9
+ '[role="combobox"]'
10
+ ].join(", ");
11
+ function getTagName(element) {
12
+ return String(element?.tagName || "").toLowerCase();
13
+ }
14
+ function getRole(element) {
15
+ const role = element && typeof element.getAttribute === "function" ? element.getAttribute("role") : null;
16
+ return String(role || "").toLowerCase();
17
+ }
18
+ function getLabelControl(element) {
19
+ const labelCtor = typeof HTMLLabelElement !== "undefined" ? HTMLLabelElement : null;
20
+ if (labelCtor && element instanceof labelCtor && element.control instanceof HTMLElement) {
21
+ return element.control;
22
+ }
23
+ return null;
24
+ }
25
+ function isValueBearingElement(element) {
26
+ if (!element) return false;
27
+ const inputCtor = typeof HTMLInputElement !== "undefined" ? HTMLInputElement : null;
28
+ if (inputCtor && element instanceof inputCtor) return true;
29
+ const textareaCtor = typeof HTMLTextAreaElement !== "undefined" ? HTMLTextAreaElement : null;
30
+ if (textareaCtor && element instanceof textareaCtor) return true;
31
+ const selectCtor = typeof HTMLSelectElement !== "undefined" ? HTMLSelectElement : null;
32
+ if (selectCtor && element instanceof selectCtor) return true;
33
+ return ["input", "textarea", "select"].includes(getTagName(element));
34
+ }
35
+ function findEditableControlInShadowRoot(root) {
36
+ if (!root) return null;
37
+ if (root.shadowRoot) {
38
+ const found = root.shadowRoot.querySelector(EDITABLE_CONTROL_SELECTOR);
39
+ if (found) {
40
+ return resolveEditableControlElement(found);
41
+ }
42
+ }
43
+ for (const child of Array.from(root.children)) {
44
+ if (child instanceof HTMLElement) {
45
+ const found = findEditableControlInShadowRoot(child);
46
+ if (found) return found;
47
+ }
48
+ }
49
+ return null;
50
+ }
51
+ function resolveEditableControlElement(element) {
52
+ const labelControl = getLabelControl(element);
53
+ if (labelControl) {
54
+ return resolveEditableControlElement(labelControl);
55
+ }
56
+ if (isValueBearingElement(element) || element.isContentEditable) {
57
+ return element;
58
+ }
59
+ const role = getRole(element);
60
+ if (EDITABLE_ROLES.has(role)) {
61
+ const nested2 = element.querySelector(EDITABLE_CONTROL_SELECTOR);
62
+ if (nested2 && nested2 !== element) {
63
+ return resolveEditableControlElement(nested2);
64
+ }
65
+ const shadowNested2 = findEditableControlInShadowRoot(element);
66
+ return shadowNested2 ?? element;
67
+ }
68
+ const nested = element.querySelector(EDITABLE_CONTROL_SELECTOR);
69
+ if (nested) {
70
+ return resolveEditableControlElement(nested);
71
+ }
72
+ const shadowNested = findEditableControlInShadowRoot(element);
73
+ return shadowNested ?? element;
74
+ }
75
+ function readEditableControlValue(element, options = {}) {
76
+ const target = resolveEditableControlElement(element);
77
+ const maskPasswords = options.maskPasswords !== false;
78
+ if (isValueBearingElement(target)) {
79
+ const type = String(target.type || "").toLowerCase();
80
+ if (maskPasswords && type === "password") {
81
+ return "***";
82
+ }
83
+ return String(target.value || "").trim().slice(0, 100);
84
+ }
85
+ const genericValue = target.value;
86
+ if (typeof genericValue === "string") {
87
+ return genericValue.trim().slice(0, 100);
88
+ }
89
+ if (typeof genericValue === "number" && Number.isFinite(genericValue)) {
90
+ return String(genericValue).trim().slice(0, 100);
91
+ }
92
+ if (target.isContentEditable) {
93
+ return String(target.textContent || "").trim().slice(0, 100);
94
+ }
95
+ const ariaValueText = target.getAttribute("aria-valuetext");
96
+ if (ariaValueText?.trim()) {
97
+ return ariaValueText.trim().slice(0, 100);
98
+ }
99
+ const ariaValueNow = target.getAttribute("aria-valuenow");
100
+ if (ariaValueNow?.trim()) {
101
+ return ariaValueNow.trim().slice(0, 100);
102
+ }
103
+ return String(target.textContent || "").trim().slice(0, 100);
104
+ }
105
+ function readEditableControlPlaceholder(element) {
106
+ const target = resolveEditableControlElement(element);
107
+ if (typeof target.placeholder === "string") {
108
+ return String(target.placeholder || "").trim().slice(0, 100);
109
+ }
110
+ return String(target.getAttribute("placeholder") || "").trim().slice(0, 100);
111
+ }
112
+ function readEditableControlName(element) {
113
+ const target = resolveEditableControlElement(element);
114
+ const explicitName = target.name;
115
+ if (typeof explicitName === "string" && explicitName.trim()) {
116
+ return explicitName.trim().slice(0, 100);
117
+ }
118
+ return String(
119
+ target.getAttribute("name") || target.getAttribute("id") || target.getAttribute("aria-label") || ""
120
+ ).trim().slice(0, 100);
121
+ }
122
+ function readEditableControlType(element) {
123
+ const target = resolveEditableControlElement(element);
124
+ const role = getRole(target);
125
+ if (role) return role;
126
+ const explicitType = target.type;
127
+ if (typeof explicitType === "string" && explicitType.trim()) {
128
+ return explicitType.trim().toLowerCase().slice(0, 50);
129
+ }
130
+ const attributeType = target.getAttribute("type");
131
+ if (attributeType?.trim()) {
132
+ return attributeType.trim().toLowerCase().slice(0, 50);
133
+ }
134
+ return getTagName(target);
135
+ }
136
+ function isEditableControlDisabled(element) {
137
+ const target = resolveEditableControlElement(element);
138
+ const ariaDisabled = String(target.getAttribute("aria-disabled") || "").toLowerCase();
139
+ if (ariaDisabled === "true") return true;
140
+ return Boolean(target.disabled);
141
+ }
142
+ function collectEditableControls(scope) {
143
+ const seen = /* @__PURE__ */ new Set();
144
+ const controls = [];
145
+ for (const rawElement of Array.from(scope.querySelectorAll(EDITABLE_CONTROL_SELECTOR))) {
146
+ const resolved = resolveEditableControlElement(rawElement);
147
+ if (seen.has(resolved)) continue;
148
+ if (isValueBearingElement(resolved) && String(resolved.type || "").toLowerCase() === "hidden") {
149
+ continue;
150
+ }
151
+ seen.add(resolved);
152
+ controls.push(resolved);
153
+ }
154
+ return controls;
155
+ }
156
+
157
+ // src/utils/aom.ts
158
+ var uidMap = /* @__PURE__ */ new Map();
159
+ var nextUid = 1;
160
+ function generateMinifiedAOM() {
161
+ uidMap.clear();
162
+ nextUid = 1;
163
+ const interactiveSet = /* @__PURE__ */ new Set();
164
+ const interactiveCandidates = [
165
+ ...Array.from(document.querySelectorAll(
166
+ 'button, a, input, select, textarea, [role="button"], [role="link"], [role="tab"], [role="menuitem"], [role="option"], [role="textbox"], [role="combobox"], [contenteditable="true"]'
167
+ )),
168
+ ...collectEditableControls(document)
169
+ ];
170
+ const nodes = [];
171
+ interactiveCandidates.forEach((candidate) => {
172
+ const el = resolveEditableControlElement(candidate);
173
+ if (interactiveSet.has(el)) {
174
+ return;
175
+ }
176
+ interactiveSet.add(el);
177
+ if (!el.offsetParent && (el.offsetWidth === 0 || el.offsetHeight === 0)) {
178
+ return;
179
+ }
180
+ if (el.closest("#modelnex-studio-root") || el.closest("#modelnex-active-agent-root")) {
181
+ return;
182
+ }
183
+ const uid = `node:${nextUid++}`;
184
+ uidMap.set(uid, el);
185
+ let text = (el.textContent || "").replace(/\s+/g, " ").trim();
186
+ const ariaLabel = el.getAttribute("aria-label");
187
+ const placeholder = el.getAttribute("placeholder");
188
+ const value = readEditableControlValue(el, { maskPasswords: false }) || void 0;
189
+ let role = el.tagName.toLowerCase();
190
+ if (el.hasAttribute("role")) {
191
+ role = el.getAttribute("role");
192
+ } else if (role === "a") {
193
+ role = "link";
194
+ } else if (el.tagName.toLowerCase() === "input") {
195
+ const inputType = el.type;
196
+ role = inputType ? `input[${inputType}]` : "input";
197
+ }
198
+ const node = { uid, role };
199
+ const displayLabel = ariaLabel || text || placeholder;
200
+ if (displayLabel) {
201
+ node.text = displayLabel.substring(0, 100);
202
+ }
203
+ const controlName = readEditableControlName(el);
204
+ if (controlName) {
205
+ node.name = controlName;
206
+ }
207
+ if (value) {
208
+ node.value = value.substring(0, 100);
209
+ }
210
+ if (el instanceof HTMLAnchorElement && el.href) {
211
+ try {
212
+ const url = new URL(el.href);
213
+ node.href = url.pathname + url.search + url.hash;
214
+ } catch {
215
+ node.href = el.getAttribute("href");
216
+ }
217
+ }
218
+ nodes.push(node);
219
+ });
220
+ return { nodes };
221
+ }
222
+ function getElementByUid(uid) {
223
+ return uidMap.get(uid) || null;
224
+ }
225
+ function clearAOMMap() {
226
+ uidMap.clear();
227
+ nextUid = 1;
228
+ }
229
+
230
+ export {
231
+ isValueBearingElement,
232
+ findEditableControlInShadowRoot,
233
+ resolveEditableControlElement,
234
+ readEditableControlValue,
235
+ readEditableControlPlaceholder,
236
+ readEditableControlName,
237
+ readEditableControlType,
238
+ isEditableControlDisabled,
239
+ collectEditableControls,
240
+ generateMinifiedAOM,
241
+ getElementByUid,
242
+ clearAOMMap
243
+ };
@@ -0,0 +1,70 @@
1
+ // src/utils/aom.ts
2
+ var uidMap = /* @__PURE__ */ new Map();
3
+ var nextUid = 1;
4
+ function generateMinifiedAOM() {
5
+ uidMap.clear();
6
+ nextUid = 1;
7
+ const interactives = document.querySelectorAll(
8
+ 'button, a, input, select, textarea, [role="button"], [role="link"], [role="tab"], [role="menuitem"], [role="option"]'
9
+ );
10
+ const nodes = [];
11
+ interactives.forEach((el) => {
12
+ if (!el.offsetParent && (el.offsetWidth === 0 || el.offsetHeight === 0)) {
13
+ return;
14
+ }
15
+ if (el.closest("#modelnex-studio-root") || el.closest("#modelnex-active-agent-root")) {
16
+ return;
17
+ }
18
+ const uid = `node:${nextUid++}`;
19
+ uidMap.set(uid, el);
20
+ let text = (el.textContent || "").replace(/\s+/g, " ").trim();
21
+ const ariaLabel = el.getAttribute("aria-label");
22
+ const placeholder = el.getAttribute("placeholder");
23
+ let value = void 0;
24
+ if (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement || el instanceof HTMLSelectElement) {
25
+ value = el.value;
26
+ }
27
+ let role = el.tagName.toLowerCase();
28
+ if (el.hasAttribute("role")) {
29
+ role = el.getAttribute("role");
30
+ } else if (role === "a") {
31
+ role = "link";
32
+ } else if (el instanceof HTMLInputElement) {
33
+ role = el.type ? `input[${el.type}]` : "input";
34
+ }
35
+ const node = { uid, role };
36
+ const displayLabel = ariaLabel || text || placeholder;
37
+ if (displayLabel) {
38
+ node.text = displayLabel.substring(0, 100);
39
+ }
40
+ if (el.getAttribute("name")) {
41
+ node.name = el.getAttribute("name");
42
+ }
43
+ if (value) {
44
+ node.value = value.substring(0, 100);
45
+ }
46
+ if (el instanceof HTMLAnchorElement && el.href) {
47
+ try {
48
+ const url = new URL(el.href);
49
+ node.href = url.pathname + url.search + url.hash;
50
+ } catch {
51
+ node.href = el.getAttribute("href");
52
+ }
53
+ }
54
+ nodes.push(node);
55
+ });
56
+ return { nodes };
57
+ }
58
+ function getElementByUid(uid) {
59
+ return uidMap.get(uid) || null;
60
+ }
61
+ function clearAOMMap() {
62
+ uidMap.clear();
63
+ nextUid = 1;
64
+ }
65
+
66
+ export {
67
+ generateMinifiedAOM,
68
+ getElementByUid,
69
+ clearAOMMap
70
+ };
@@ -0,0 +1,55 @@
1
+ // src/utils/dom-sync.ts
2
+ function waitForDomSettle(options = {}) {
3
+ const { timeoutMs = 5e3, debounceMs = 400, minWaitMs = 100 } = options;
4
+ return new Promise((resolve) => {
5
+ let debounceTimer = null;
6
+ let resolved = false;
7
+ const maxTimer = setTimeout(() => {
8
+ if (!resolved) {
9
+ resolved = true;
10
+ cleanup();
11
+ console.log("[DOM Sync] Forced resolution by max timeout");
12
+ resolve();
13
+ }
14
+ }, Math.max(timeoutMs, minWaitMs));
15
+ const finish = () => {
16
+ if (!resolved) {
17
+ resolved = true;
18
+ cleanup();
19
+ resolve();
20
+ }
21
+ };
22
+ const observer = new MutationObserver((mutations) => {
23
+ const hasSignificantMutations = mutations.some((m) => {
24
+ if (m.target instanceof HTMLElement) {
25
+ if (m.target.hasAttribute("data-modelnex-tour-highlight")) return false;
26
+ if (m.target.hasAttribute("data-modelnex-caption")) return false;
27
+ if (m.target.closest("#modelnex-studio-root")) return false;
28
+ if (m.target.closest("#modelnex-active-agent-root")) return false;
29
+ }
30
+ return true;
31
+ });
32
+ if (!hasSignificantMutations) return;
33
+ if (debounceTimer) clearTimeout(debounceTimer);
34
+ debounceTimer = setTimeout(finish, debounceMs);
35
+ });
36
+ const cleanup = () => {
37
+ observer.disconnect();
38
+ if (debounceTimer) clearTimeout(debounceTimer);
39
+ clearTimeout(maxTimer);
40
+ };
41
+ setTimeout(() => {
42
+ if (resolved) return;
43
+ observer.observe(document.body, {
44
+ childList: true,
45
+ subtree: true,
46
+ attributes: true,
47
+ characterData: true
48
+ });
49
+ debounceTimer = setTimeout(finish, debounceMs);
50
+ }, minWaitMs);
51
+ });
52
+ }
53
+ export {
54
+ waitForDomSettle
55
+ };
package/dist/index.d.mts CHANGED
@@ -477,13 +477,15 @@ interface ModelNexChatBubbleProps {
477
477
  borderRadius?: string;
478
478
  zIndex?: number;
479
479
  };
480
+ /** Whether to auto-start tours configured with auto_start policies based on user state */
481
+ enableAutoDiscovery?: boolean;
480
482
  }
481
483
  /**
482
484
  * Chat interface for natural language commands.
483
485
  * Shows conversation history; on exit, the agent summarizes what it did and suggests next steps.
484
486
  * Use within ModelNexProvider. Omit to use your own UI with useRunCommand.
485
487
  */
486
- declare function ModelNexChatBubble({ placeholder, defaultCommand, className, welcomeMessage, agentName, appName, theme, }: ModelNexChatBubbleProps): React$1.ReactPortal | null;
488
+ declare function ModelNexChatBubble({ placeholder, defaultCommand, className, welcomeMessage, agentName, appName, theme, enableAutoDiscovery, }: ModelNexChatBubbleProps): React$1.ReactPortal | null;
487
489
 
488
490
  interface ModelNexOnboardingPanelProps {
489
491
  appName?: string;
package/dist/index.d.ts CHANGED
@@ -477,13 +477,15 @@ interface ModelNexChatBubbleProps {
477
477
  borderRadius?: string;
478
478
  zIndex?: number;
479
479
  };
480
+ /** Whether to auto-start tours configured with auto_start policies based on user state */
481
+ enableAutoDiscovery?: boolean;
480
482
  }
481
483
  /**
482
484
  * Chat interface for natural language commands.
483
485
  * Shows conversation history; on exit, the agent summarizes what it did and suggests next steps.
484
486
  * Use within ModelNexProvider. Omit to use your own UI with useRunCommand.
485
487
  */
486
- declare function ModelNexChatBubble({ placeholder, defaultCommand, className, welcomeMessage, agentName, appName, theme, }: ModelNexChatBubbleProps): React$1.ReactPortal | null;
488
+ declare function ModelNexChatBubble({ placeholder, defaultCommand, className, welcomeMessage, agentName, appName, theme, enableAutoDiscovery, }: ModelNexChatBubbleProps): React$1.ReactPortal | null;
487
489
 
488
490
  interface ModelNexOnboardingPanelProps {
489
491
  appName?: string;
package/dist/index.js CHANGED
@@ -4592,7 +4592,7 @@ function useTourPlayback({
4592
4592
  if (typeof persistedRunId === "number") {
4593
4593
  payload.resumeRunId = persistedRunId;
4594
4594
  }
4595
- if (!payload.resumeRunId && (!payload.websiteId || !payload.userType)) {
4595
+ if (!payload.resumeRunId && (!payload.websiteId || !payload.userType && !payload.userId)) {
4596
4596
  return;
4597
4597
  }
4598
4598
  emitSocketEvent(socket, "tour:init", payload);
@@ -5955,9 +5955,10 @@ function shouldDiscoverEligibleTours({
5955
5955
  isPreviewDiscoveryInFlight,
5956
5956
  isStartingExperience,
5957
5957
  hasUserProfile,
5958
- hasWebsiteId
5958
+ hasWebsiteId,
5959
+ enableAutoDiscovery
5959
5960
  }) {
5960
- return !disabled && !hasPendingPrompt && !hasPreviewSession && !isPlaybackActive && !isPreviewDiscoveryInFlight && !isStartingExperience && hasUserProfile && hasWebsiteId;
5961
+ return enableAutoDiscovery && !disabled && !hasPendingPrompt && !hasPreviewSession && !isPlaybackActive && !isPreviewDiscoveryInFlight && !isStartingExperience && hasUserProfile && hasWebsiteId;
5961
5962
  }
5962
5963
  function useExperiencePlaybackController({
5963
5964
  serverUrl,
@@ -5973,7 +5974,8 @@ function useExperiencePlaybackController({
5973
5974
  onTourEnd,
5974
5975
  disabled = false,
5975
5976
  showCaptions = true,
5976
- initialExperienceType = "tour"
5977
+ initialExperienceType = "tour",
5978
+ enableAutoDiscovery = true
5977
5979
  }) {
5978
5980
  const locationSignature = typeof window === "undefined" ? "" : getLocationSignature(window.location);
5979
5981
  const [activeExperienceType, setActiveExperienceType] = (0, import_react13.useState)(initialExperienceType);
@@ -6181,8 +6183,10 @@ function useExperiencePlaybackController({
6181
6183
  isPreviewDiscoveryInFlight: previewDiscoveryInFlightRef.current,
6182
6184
  isStartingExperience: startingExperienceType !== null,
6183
6185
  hasUserProfile: Boolean(userProfile),
6184
- hasWebsiteId: Boolean(websiteId)
6186
+ hasWebsiteId: Boolean(websiteId),
6187
+ enableAutoDiscovery
6185
6188
  })) return;
6189
+ if (!userProfile || !websiteId) return;
6186
6190
  let cancelled = false;
6187
6191
  const checkTours = async () => {
6188
6192
  const toursByExperience = await Promise.all(
@@ -10273,7 +10277,8 @@ function ModelNexChatBubble({
10273
10277
  welcomeMessage = "Hi! I can help you navigate and manage your documents. Try asking me to open a document, go to templates, or filter by status.",
10274
10278
  agentName = "ModelNex AI",
10275
10279
  appName = "this app",
10276
- theme
10280
+ theme,
10281
+ enableAutoDiscovery = true
10277
10282
  }) {
10278
10283
  const onCommand = void 0;
10279
10284
  const recordingExperienceType = "tour";
@@ -10346,7 +10351,8 @@ function ModelNexChatBubble({
10346
10351
  },
10347
10352
  showCaptions: !expanded,
10348
10353
  disabled: recordingMode || !hydrated,
10349
- initialExperienceType: recordingExperienceType
10354
+ initialExperienceType: recordingExperienceType,
10355
+ enableAutoDiscovery
10350
10356
  });
10351
10357
  const activePlayback = playbackController.playback;
10352
10358
  const activeExperienceType = playbackController.activeExperienceType;
package/dist/index.mjs CHANGED
@@ -3763,7 +3763,7 @@ function useTourPlayback({
3763
3763
  if (typeof persistedRunId === "number") {
3764
3764
  payload.resumeRunId = persistedRunId;
3765
3765
  }
3766
- if (!payload.resumeRunId && (!payload.websiteId || !payload.userType)) {
3766
+ if (!payload.resumeRunId && (!payload.websiteId || !payload.userType && !payload.userId)) {
3767
3767
  return;
3768
3768
  }
3769
3769
  emitSocketEvent(socket, "tour:init", payload);
@@ -5126,9 +5126,10 @@ function shouldDiscoverEligibleTours({
5126
5126
  isPreviewDiscoveryInFlight,
5127
5127
  isStartingExperience,
5128
5128
  hasUserProfile,
5129
- hasWebsiteId
5129
+ hasWebsiteId,
5130
+ enableAutoDiscovery
5130
5131
  }) {
5131
- return !disabled && !hasPendingPrompt && !hasPreviewSession && !isPlaybackActive && !isPreviewDiscoveryInFlight && !isStartingExperience && hasUserProfile && hasWebsiteId;
5132
+ return enableAutoDiscovery && !disabled && !hasPendingPrompt && !hasPreviewSession && !isPlaybackActive && !isPreviewDiscoveryInFlight && !isStartingExperience && hasUserProfile && hasWebsiteId;
5132
5133
  }
5133
5134
  function useExperiencePlaybackController({
5134
5135
  serverUrl,
@@ -5144,7 +5145,8 @@ function useExperiencePlaybackController({
5144
5145
  onTourEnd,
5145
5146
  disabled = false,
5146
5147
  showCaptions = true,
5147
- initialExperienceType = "tour"
5148
+ initialExperienceType = "tour",
5149
+ enableAutoDiscovery = true
5148
5150
  }) {
5149
5151
  const locationSignature = typeof window === "undefined" ? "" : getLocationSignature(window.location);
5150
5152
  const [activeExperienceType, setActiveExperienceType] = useState7(initialExperienceType);
@@ -5352,8 +5354,10 @@ function useExperiencePlaybackController({
5352
5354
  isPreviewDiscoveryInFlight: previewDiscoveryInFlightRef.current,
5353
5355
  isStartingExperience: startingExperienceType !== null,
5354
5356
  hasUserProfile: Boolean(userProfile),
5355
- hasWebsiteId: Boolean(websiteId)
5357
+ hasWebsiteId: Boolean(websiteId),
5358
+ enableAutoDiscovery
5356
5359
  })) return;
5360
+ if (!userProfile || !websiteId) return;
5357
5361
  let cancelled = false;
5358
5362
  const checkTours = async () => {
5359
5363
  const toursByExperience = await Promise.all(
@@ -9442,7 +9446,8 @@ function ModelNexChatBubble({
9442
9446
  welcomeMessage = "Hi! I can help you navigate and manage your documents. Try asking me to open a document, go to templates, or filter by status.",
9443
9447
  agentName = "ModelNex AI",
9444
9448
  appName = "this app",
9445
- theme
9449
+ theme,
9450
+ enableAutoDiscovery = true
9446
9451
  }) {
9447
9452
  const onCommand = void 0;
9448
9453
  const recordingExperienceType = "tour";
@@ -9515,7 +9520,8 @@ function ModelNexChatBubble({
9515
9520
  },
9516
9521
  showCaptions: !expanded,
9517
9522
  disabled: recordingMode || !hydrated,
9518
- initialExperienceType: recordingExperienceType
9523
+ initialExperienceType: recordingExperienceType,
9524
+ enableAutoDiscovery
9519
9525
  });
9520
9526
  const activePlayback = playbackController.playback;
9521
9527
  const activeExperienceType = playbackController.activeExperienceType;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@modelnex/sdk",
3
- "version": "0.5.51",
3
+ "version": "0.5.53",
4
4
  "description": "React SDK for natural language control of web apps via AI agents",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -20,6 +20,15 @@
20
20
  "dist",
21
21
  "README.md"
22
22
  ],
23
+ "scripts": {
24
+ "prepublishOnly": "npm run build",
25
+ "build": "npm exec -- tsup src/index.ts --format cjs,esm --dts",
26
+ "dev": "npm exec -- tsup src/index.ts --format cjs,esm --watch --dts",
27
+ "lint": "eslint src/",
28
+ "test": "npm run build && node --test tests/*.test.js",
29
+ "test:ci": "npm run test && npm run test:unit",
30
+ "test:unit": "node --import tsx --test tests/*.test.ts"
31
+ },
23
32
  "peerDependencies": {
24
33
  "react": ">=17.0.0",
25
34
  "react-dom": ">=17.0.0",
@@ -58,13 +67,5 @@
58
67
  "bugs": {
59
68
  "url": "https://github.com/sharunaraksha/modelnex-sdk/issues"
60
69
  },
61
- "homepage": "https://github.com/sharunaraksha/modelnex-sdk#readme",
62
- "scripts": {
63
- "build": "npm exec -- tsup src/index.ts --format cjs,esm --dts",
64
- "dev": "npm exec -- tsup src/index.ts --format cjs,esm --watch --dts",
65
- "lint": "eslint src/",
66
- "test": "npm run build && node --test tests/*.test.js",
67
- "test:ci": "npm run test && npm run test:unit",
68
- "test:unit": "node --import tsx --test tests/*.test.ts"
69
- }
70
- }
70
+ "homepage": "https://github.com/sharunaraksha/modelnex-sdk#readme"
71
+ }