@modelnex/sdk 0.5.13 → 0.5.15

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,71 @@
1
+ import "./chunk-6DZX6EAA.mjs";
2
+
3
+ // src/utils/aom.ts
4
+ var uidMap = /* @__PURE__ */ new Map();
5
+ var nextUid = 1;
6
+ function generateMinifiedAOM() {
7
+ uidMap.clear();
8
+ nextUid = 1;
9
+ const interactives = document.querySelectorAll(
10
+ 'button, a, input, select, textarea, [role="button"], [role="link"], [role="tab"], [role="menuitem"], [role="option"]'
11
+ );
12
+ const nodes = [];
13
+ interactives.forEach((el) => {
14
+ if (!el.offsetParent && (el.offsetWidth === 0 || el.offsetHeight === 0)) {
15
+ return;
16
+ }
17
+ if (el.closest("#modelnex-studio-root") || el.closest("#modelnex-active-agent-root")) {
18
+ return;
19
+ }
20
+ const uid = `node:${nextUid++}`;
21
+ uidMap.set(uid, el);
22
+ let text = (el.textContent || "").replace(/\s+/g, " ").trim();
23
+ const ariaLabel = el.getAttribute("aria-label");
24
+ const placeholder = el.getAttribute("placeholder");
25
+ let value = void 0;
26
+ if (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement || el instanceof HTMLSelectElement) {
27
+ value = el.value;
28
+ }
29
+ let role = el.tagName.toLowerCase();
30
+ if (el.hasAttribute("role")) {
31
+ role = el.getAttribute("role");
32
+ } else if (role === "a") {
33
+ role = "link";
34
+ } else if (el instanceof HTMLInputElement) {
35
+ role = el.type ? `input[${el.type}]` : "input";
36
+ }
37
+ const node = { uid, role };
38
+ const displayLabel = ariaLabel || text || placeholder;
39
+ if (displayLabel) {
40
+ node.text = displayLabel.substring(0, 100);
41
+ }
42
+ if (el.getAttribute("name")) {
43
+ node.name = el.getAttribute("name");
44
+ }
45
+ if (value) {
46
+ node.value = value.substring(0, 100);
47
+ }
48
+ if (el instanceof HTMLAnchorElement && el.href) {
49
+ try {
50
+ const url = new URL(el.href);
51
+ node.href = url.pathname + url.search + url.hash;
52
+ } catch {
53
+ node.href = el.getAttribute("href");
54
+ }
55
+ }
56
+ nodes.push(node);
57
+ });
58
+ return { nodes };
59
+ }
60
+ function getElementByUid(uid) {
61
+ return uidMap.get(uid) || null;
62
+ }
63
+ function clearAOMMap() {
64
+ uidMap.clear();
65
+ nextUid = 1;
66
+ }
67
+ export {
68
+ clearAOMMap,
69
+ generateMinifiedAOM,
70
+ getElementByUid
71
+ };
@@ -0,0 +1,69 @@
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
+ export {
66
+ clearAOMMap,
67
+ generateMinifiedAOM,
68
+ getElementByUid
69
+ };
@@ -0,0 +1,37 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
8
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
9
+ }) : x)(function(x) {
10
+ if (typeof require !== "undefined") return require.apply(this, arguments);
11
+ throw Error('Dynamic require of "' + x + '" is not supported');
12
+ });
13
+ var __commonJS = (cb, mod) => function __require2() {
14
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
15
+ };
16
+ var __copyProps = (to, from, except, desc) => {
17
+ if (from && typeof from === "object" || typeof from === "function") {
18
+ for (let key of __getOwnPropNames(from))
19
+ if (!__hasOwnProp.call(to, key) && key !== except)
20
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
21
+ }
22
+ return to;
23
+ };
24
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
25
+ // If the importer is in node compatibility mode or this is not an ESM
26
+ // file that has been converted to a CommonJS file using a Babel-
27
+ // compatible transform (i.e. "__esModule" has not been set), then set
28
+ // "default" to the CommonJS "module.exports" for node compatibility.
29
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
30
+ mod
31
+ ));
32
+
33
+ export {
34
+ __require,
35
+ __commonJS,
36
+ __toESM
37
+ };
@@ -0,0 +1,57 @@
1
+ import "./chunk-6DZX6EAA.mjs";
2
+
3
+ // src/utils/dom-sync.ts
4
+ function waitForDomSettle(options = {}) {
5
+ const { timeoutMs = 5e3, debounceMs = 400, minWaitMs = 100 } = options;
6
+ return new Promise((resolve) => {
7
+ let debounceTimer = null;
8
+ let resolved = false;
9
+ const maxTimer = setTimeout(() => {
10
+ if (!resolved) {
11
+ resolved = true;
12
+ cleanup();
13
+ console.log("[DOM Sync] Forced resolution by max timeout");
14
+ resolve();
15
+ }
16
+ }, Math.max(timeoutMs, minWaitMs));
17
+ const finish = () => {
18
+ if (!resolved) {
19
+ resolved = true;
20
+ cleanup();
21
+ resolve();
22
+ }
23
+ };
24
+ const observer = new MutationObserver((mutations) => {
25
+ const hasSignificantMutations = mutations.some((m) => {
26
+ if (m.target instanceof HTMLElement) {
27
+ if (m.target.hasAttribute("data-modelnex-tour-highlight")) return false;
28
+ if (m.target.hasAttribute("data-modelnex-caption")) return false;
29
+ if (m.target.closest("#modelnex-studio-root")) return false;
30
+ if (m.target.closest("#modelnex-active-agent-root")) return false;
31
+ }
32
+ return true;
33
+ });
34
+ if (!hasSignificantMutations) return;
35
+ if (debounceTimer) clearTimeout(debounceTimer);
36
+ debounceTimer = setTimeout(finish, debounceMs);
37
+ });
38
+ const cleanup = () => {
39
+ observer.disconnect();
40
+ if (debounceTimer) clearTimeout(debounceTimer);
41
+ clearTimeout(maxTimer);
42
+ };
43
+ setTimeout(() => {
44
+ if (resolved) return;
45
+ observer.observe(document.body, {
46
+ childList: true,
47
+ subtree: true,
48
+ attributes: true,
49
+ characterData: true
50
+ });
51
+ debounceTimer = setTimeout(finish, debounceMs);
52
+ }, minWaitMs);
53
+ });
54
+ }
55
+ export {
56
+ waitForDomSettle
57
+ };
package/dist/index.d.mts CHANGED
@@ -227,6 +227,9 @@ interface RecordingStep {
227
227
  onboarding?: OnboardingStepMetadata;
228
228
  }
229
229
 
230
+ /** Default ModelNex server when `serverUrl` is omitted or React context is unavailable. */
231
+ declare const DEFAULT_MODELNEX_SERVER_URL = "https://api.modelnex.com";
232
+
230
233
  /**
231
234
  * Automatic DOM element extraction with stable fingerprinting.
232
235
  *
@@ -818,6 +821,11 @@ declare function clearActiveDraftPreview(experienceType?: ExperienceType): void;
818
821
 
819
822
  interface ModelNexProviderProps {
820
823
  children?: unknown;
824
+ /**
825
+ * ModelNex Server URL (e.g. https://api.modelnex.com).
826
+ * When omitted, {@link DEFAULT_MODELNEX_SERVER_URL} is used.
827
+ */
828
+ serverUrl?: string;
821
829
  /** Identifier for the integrated website, for multi-tenancy */
822
830
  websiteId?: string;
823
831
  /**
@@ -838,4 +846,4 @@ interface ModelNexProviderProps {
838
846
  }
839
847
  declare const ModelNexProvider: React$1.FC<ModelNexProviderProps>;
840
848
 
841
- export { type AgentDebug, type AgentTraceLlmInput, type AgentTraceStep, type ChatMessage, type ExperienceGoal, type ExperiencePlaybackHook, type ExperiencePresentation, type ExperienceType, type ExtractedElement, ModelNexChatBubble, type ModelNexChatBubbleProps, ModelNexOnboardingPanel, type ModelNexOnboardingPanelProps, ModelNexProvider, type ModelNexProviderProps, type OnboardingPlaybackHook, type OnboardingStepMetadata, type PreviewLaunchSource, type RecordingModeHook, RecordingOverlay, type RunCommandResult, type SavedDraftPreview, StudioOverlay, type TagData, type TagStore, type Tour, type TourNotificationType, type TourPlaybackHook, type TourPlaybackState, TourProgressPanel, type TourStartPolicy, type TourStep, type TourStepType, type TourTrigger, UIStateProvider, type UserProfile, type VoiceHook, buildDraftPreviewUrl, buildRecordingCapturePayload, buildRecordingStepGoal, clearActiveDraftPreview, extractInteractiveElements, generateFingerprint, getPreviewQueryParamName, getRecordingDraftActionLabel, getRecordingDraftStatusMessage, inferOnboardingMetadataForStep, isAskDrivenInputStepType, isInteractiveInputStepType, isManualOnboardingStep, isRecordingDraftGenerating, persistActiveDraftPreview, readActiveDraftPreview, shouldPromptForPreviewStart, shouldShowRecordingOverlay, useActionHighlight, useAgentViewport, useAutoExtract, useExperiencePlayback, useOnboardingPlayback, useRecordingMode, useRunCommand, useTagStore, useTourPlayback, useUIState, useViewportTrack, useVisibleIds, useVoice };
849
+ export { type AgentDebug, type AgentTraceLlmInput, type AgentTraceStep, type ChatMessage, DEFAULT_MODELNEX_SERVER_URL, type ExperienceGoal, type ExperiencePlaybackHook, type ExperiencePresentation, type ExperienceType, type ExtractedElement, ModelNexChatBubble, type ModelNexChatBubbleProps, ModelNexOnboardingPanel, type ModelNexOnboardingPanelProps, ModelNexProvider, type ModelNexProviderProps, type OnboardingPlaybackHook, type OnboardingStepMetadata, type PreviewLaunchSource, type RecordingModeHook, RecordingOverlay, type RunCommandResult, type SavedDraftPreview, StudioOverlay, type TagData, type TagStore, type Tour, type TourNotificationType, type TourPlaybackHook, type TourPlaybackState, TourProgressPanel, type TourStartPolicy, type TourStep, type TourStepType, type TourTrigger, UIStateProvider, type UserProfile, type VoiceHook, buildDraftPreviewUrl, buildRecordingCapturePayload, buildRecordingStepGoal, clearActiveDraftPreview, extractInteractiveElements, generateFingerprint, getPreviewQueryParamName, getRecordingDraftActionLabel, getRecordingDraftStatusMessage, inferOnboardingMetadataForStep, isAskDrivenInputStepType, isInteractiveInputStepType, isManualOnboardingStep, isRecordingDraftGenerating, persistActiveDraftPreview, readActiveDraftPreview, shouldPromptForPreviewStart, shouldShowRecordingOverlay, useActionHighlight, useAgentViewport, useAutoExtract, useExperiencePlayback, useOnboardingPlayback, useRecordingMode, useRunCommand, useTagStore, useTourPlayback, useUIState, useViewportTrack, useVisibleIds, useVoice };
package/dist/index.d.ts CHANGED
@@ -227,6 +227,9 @@ interface RecordingStep {
227
227
  onboarding?: OnboardingStepMetadata;
228
228
  }
229
229
 
230
+ /** Default ModelNex server when `serverUrl` is omitted or React context is unavailable. */
231
+ declare const DEFAULT_MODELNEX_SERVER_URL = "https://api.modelnex.com";
232
+
230
233
  /**
231
234
  * Automatic DOM element extraction with stable fingerprinting.
232
235
  *
@@ -818,6 +821,11 @@ declare function clearActiveDraftPreview(experienceType?: ExperienceType): void;
818
821
 
819
822
  interface ModelNexProviderProps {
820
823
  children?: unknown;
824
+ /**
825
+ * ModelNex Server URL (e.g. https://api.modelnex.com).
826
+ * When omitted, {@link DEFAULT_MODELNEX_SERVER_URL} is used.
827
+ */
828
+ serverUrl?: string;
821
829
  /** Identifier for the integrated website, for multi-tenancy */
822
830
  websiteId?: string;
823
831
  /**
@@ -838,4 +846,4 @@ interface ModelNexProviderProps {
838
846
  }
839
847
  declare const ModelNexProvider: React$1.FC<ModelNexProviderProps>;
840
848
 
841
- export { type AgentDebug, type AgentTraceLlmInput, type AgentTraceStep, type ChatMessage, type ExperienceGoal, type ExperiencePlaybackHook, type ExperiencePresentation, type ExperienceType, type ExtractedElement, ModelNexChatBubble, type ModelNexChatBubbleProps, ModelNexOnboardingPanel, type ModelNexOnboardingPanelProps, ModelNexProvider, type ModelNexProviderProps, type OnboardingPlaybackHook, type OnboardingStepMetadata, type PreviewLaunchSource, type RecordingModeHook, RecordingOverlay, type RunCommandResult, type SavedDraftPreview, StudioOverlay, type TagData, type TagStore, type Tour, type TourNotificationType, type TourPlaybackHook, type TourPlaybackState, TourProgressPanel, type TourStartPolicy, type TourStep, type TourStepType, type TourTrigger, UIStateProvider, type UserProfile, type VoiceHook, buildDraftPreviewUrl, buildRecordingCapturePayload, buildRecordingStepGoal, clearActiveDraftPreview, extractInteractiveElements, generateFingerprint, getPreviewQueryParamName, getRecordingDraftActionLabel, getRecordingDraftStatusMessage, inferOnboardingMetadataForStep, isAskDrivenInputStepType, isInteractiveInputStepType, isManualOnboardingStep, isRecordingDraftGenerating, persistActiveDraftPreview, readActiveDraftPreview, shouldPromptForPreviewStart, shouldShowRecordingOverlay, useActionHighlight, useAgentViewport, useAutoExtract, useExperiencePlayback, useOnboardingPlayback, useRecordingMode, useRunCommand, useTagStore, useTourPlayback, useUIState, useViewportTrack, useVisibleIds, useVoice };
849
+ export { type AgentDebug, type AgentTraceLlmInput, type AgentTraceStep, type ChatMessage, DEFAULT_MODELNEX_SERVER_URL, type ExperienceGoal, type ExperiencePlaybackHook, type ExperiencePresentation, type ExperienceType, type ExtractedElement, ModelNexChatBubble, type ModelNexChatBubbleProps, ModelNexOnboardingPanel, type ModelNexOnboardingPanelProps, ModelNexProvider, type ModelNexProviderProps, type OnboardingPlaybackHook, type OnboardingStepMetadata, type PreviewLaunchSource, type RecordingModeHook, RecordingOverlay, type RunCommandResult, type SavedDraftPreview, StudioOverlay, type TagData, type TagStore, type Tour, type TourNotificationType, type TourPlaybackHook, type TourPlaybackState, TourProgressPanel, type TourStartPolicy, type TourStep, type TourStepType, type TourTrigger, UIStateProvider, type UserProfile, type VoiceHook, buildDraftPreviewUrl, buildRecordingCapturePayload, buildRecordingStepGoal, clearActiveDraftPreview, extractInteractiveElements, generateFingerprint, getPreviewQueryParamName, getRecordingDraftActionLabel, getRecordingDraftStatusMessage, inferOnboardingMetadataForStep, isAskDrivenInputStepType, isInteractiveInputStepType, isManualOnboardingStep, isRecordingDraftGenerating, persistActiveDraftPreview, readActiveDraftPreview, shouldPromptForPreviewStart, shouldShowRecordingOverlay, useActionHighlight, useAgentViewport, useAutoExtract, useExperiencePlayback, useOnboardingPlayback, useRecordingMode, useRunCommand, useTagStore, useTourPlayback, useUIState, useViewportTrack, useVisibleIds, useVoice };
package/dist/index.js CHANGED
@@ -172,6 +172,7 @@ var init_dom_sync = __esm({
172
172
  // src/index.ts
173
173
  var index_exports = {};
174
174
  __export(index_exports, {
175
+ DEFAULT_MODELNEX_SERVER_URL: () => DEFAULT_MODELNEX_SERVER_URL,
175
176
  ModelNexChatBubble: () => ModelNexChatBubble,
176
177
  ModelNexOnboardingPanel: () => ModelNexOnboardingPanel,
177
178
  ModelNexProvider: () => ModelNexProvider,
@@ -227,11 +228,11 @@ function resolveSocketIoTransports(serverUrl, order) {
227
228
  try {
228
229
  const host = new URL(serverUrl).hostname.toLowerCase();
229
230
  if (host.endsWith("awsapprunner.com")) {
230
- return ["polling"];
231
+ return ["websocket"];
231
232
  }
232
233
  } catch {
233
234
  }
234
- return order === "websocket-first" ? ["websocket", "polling"] : ["polling", "websocket"];
235
+ return ["websocket", "polling"];
235
236
  }
236
237
 
237
238
  // src/auto-extract.ts
@@ -2322,9 +2323,11 @@ function useBuiltinActions(registerAction, unregisterAction, tagStore, serverUrl
2322
2323
  }, [registerAction, unregisterAction]);
2323
2324
  }
2324
2325
 
2326
+ // src/constants.ts
2327
+ var DEFAULT_MODELNEX_SERVER_URL = "https://api.modelnex.com";
2328
+
2325
2329
  // src/hooks/useRunCommand.ts
2326
2330
  var import_react9 = require("react");
2327
- var DEFAULT_SERVER_URL = "https://69tgf4aic6.us-east-1.awsapprunner.com";
2328
2331
  function searchTaggedElementsForQuery(store, query, limit = 8) {
2329
2332
  const allTags = store.getAllTags();
2330
2333
  if (allTags.length === 0) return [];
@@ -2345,7 +2348,7 @@ function searchTaggedElementsForQuery(store, query, limit = 8) {
2345
2348
  }
2346
2349
  function useRunCommand(serverUrlOverride) {
2347
2350
  const context = (0, import_react9.useContext)(ModelNexContext);
2348
- const baseUrl = serverUrlOverride ?? context?.commandUrl ?? context?.serverUrl ?? DEFAULT_SERVER_URL;
2351
+ const baseUrl = serverUrlOverride ?? context?.commandUrl ?? context?.serverUrl ?? DEFAULT_MODELNEX_SERVER_URL;
2349
2352
  const tagStore = context?.tagStore;
2350
2353
  return (0, import_react9.useCallback)(
2351
2354
  async (command, signal) => {
@@ -3151,6 +3154,12 @@ function useTourPlayback({
3151
3154
  const [serverState, setServerState] = (0, import_react12.useState)(null);
3152
3155
  const ctx = (0, import_react12.useContext)(ModelNexContext);
3153
3156
  const devMode = ctx?.devMode;
3157
+ const devModeRef = (0, import_react12.useRef)(devMode);
3158
+ devModeRef.current = devMode;
3159
+ const userProfileRef = (0, import_react12.useRef)(userProfile);
3160
+ userProfileRef.current = userProfile;
3161
+ const experienceTypeRef = (0, import_react12.useRef)(experienceType);
3162
+ experienceTypeRef.current = experienceType;
3154
3163
  const tourRef = (0, import_react12.useRef)(null);
3155
3164
  const stepIndexRef = (0, import_react12.useRef)(0);
3156
3165
  const skipRequestedRef = (0, import_react12.useRef)(false);
@@ -3190,18 +3199,27 @@ function useTourPlayback({
3190
3199
  (0, import_react12.useEffect)(() => {
3191
3200
  if (disabled) return;
3192
3201
  if (typeof window === "undefined") return;
3202
+ let cancelled = false;
3203
+ let createdSocket = null;
3193
3204
  import("socket.io-client").then((ioModule) => {
3205
+ if (cancelled) return;
3194
3206
  const io2 = ioModule.default || ioModule;
3195
3207
  const socket = io2(serverUrl, {
3196
3208
  path: "/socket.io",
3197
3209
  // standard
3198
- transports: resolveSocketIoTransports(serverUrl, "websocket-first")
3210
+ transports: resolveSocketIoTransports(serverUrl, "polling-first")
3199
3211
  });
3212
+ if (cancelled) {
3213
+ socket.disconnect();
3214
+ return;
3215
+ }
3216
+ createdSocket = socket;
3200
3217
  socketRef.current = socket;
3201
3218
  socket.on("connect", () => {
3202
3219
  console.log("[TourClient] Connected to tour agent server:", socket.id);
3203
- if (websiteId && userProfile) {
3204
- socket.emit("tour:init", { websiteId, userId: userProfile.userId, userType: userProfile.type });
3220
+ const profile = userProfileRef.current;
3221
+ if (websiteId && profile?.userId) {
3222
+ socket.emit("tour:init", { websiteId, userId: profile.userId, userType: profile.type });
3205
3223
  }
3206
3224
  });
3207
3225
  socket.on("tour:server_state", (payload) => {
@@ -3226,6 +3244,11 @@ function useTourPlayback({
3226
3244
  }
3227
3245
  });
3228
3246
  socket.on("tour:command", async (payload) => {
3247
+ const emitIfOpen = (ev, data) => {
3248
+ if (socketRef.current !== socket) return;
3249
+ if (!socket.connected) return;
3250
+ socket.emit(ev, data);
3251
+ };
3229
3252
  console.log("[TourClient] Received command batch:", payload.stepIndex, payload.commands);
3230
3253
  runCleanup(pendingManualWaitCleanupRef.current);
3231
3254
  pendingManualWaitCleanupRef.current = null;
@@ -3284,7 +3307,7 @@ function useTourPlayback({
3284
3307
  if (!payload.commands || !Array.isArray(payload.commands)) {
3285
3308
  console.warn("[TourClient] Payload commands is not an array:", payload);
3286
3309
  commandInFlightRef.current = false;
3287
- socket.emit("tour:action_result", {
3310
+ emitIfOpen("tour:action_result", {
3288
3311
  success: false,
3289
3312
  reason: "invalid_commands",
3290
3313
  commandBatchId,
@@ -3563,7 +3586,7 @@ function useTourPlayback({
3563
3586
  currentStepOrder: stepIndexRef.current
3564
3587
  });
3565
3588
  }
3566
- socket.emit("tour:action_result", {
3589
+ emitIfOpen("tour:action_result", {
3567
3590
  success: true,
3568
3591
  interrupted: true,
3569
3592
  results,
@@ -3588,7 +3611,7 @@ function useTourPlayback({
3588
3611
  currentStepOrder: stepIndexRef.current
3589
3612
  });
3590
3613
  }
3591
- socket.emit("tour:action_result", {
3614
+ emitIfOpen("tour:action_result", {
3592
3615
  success: false,
3593
3616
  reason: "execution_error",
3594
3617
  error: String(err),
@@ -3657,7 +3680,7 @@ function useTourPlayback({
3657
3680
  currentStepOrder: stepIndexRef.current
3658
3681
  });
3659
3682
  }
3660
- socket.emit("tour:action_result", {
3683
+ emitIfOpen("tour:action_result", {
3661
3684
  success: true,
3662
3685
  waitingForInput: true,
3663
3686
  results,
@@ -3690,7 +3713,7 @@ function useTourPlayback({
3690
3713
  const { waitForDomSettle: waitForDomSettle2 } = await Promise.resolve().then(() => (init_dom_sync(), dom_sync_exports));
3691
3714
  await waitForDomSettle2({ timeoutMs: 1500, debounceMs: 200 });
3692
3715
  await syncAOM();
3693
- socket.emit("tour:user_input", {
3716
+ emitIfOpen("tour:user_input", {
3694
3717
  transcript,
3695
3718
  runId: runIdRef.current,
3696
3719
  turnId: turnIdRef.current
@@ -3709,7 +3732,7 @@ function useTourPlayback({
3709
3732
  currentStepOrder: stepIndexRef.current
3710
3733
  });
3711
3734
  }
3712
- socket.emit("tour:action_result", {
3735
+ emitIfOpen("tour:action_result", {
3713
3736
  success: true,
3714
3737
  results,
3715
3738
  commandBatchId,
@@ -3722,8 +3745,9 @@ function useTourPlayback({
3722
3745
  if (isActiveRef.current) return;
3723
3746
  runIdRef.current = typeof tourData.runId === "number" ? tourData.runId : runIdRef.current;
3724
3747
  const tour = tourData.tourContext ?? tourRef.current;
3725
- if (tour?.type && tour.type !== experienceType) {
3726
- console.log(`[TourClient] Ignoring ${tour.type} start (this hook is for ${experienceType})`);
3748
+ const expType = experienceTypeRef.current;
3749
+ if (tour?.type && tour.type !== expType) {
3750
+ console.log(`[TourClient] Ignoring ${tour.type} start (this hook is for ${expType})`);
3727
3751
  return;
3728
3752
  }
3729
3753
  skipRequestedRef.current = false;
@@ -3750,11 +3774,13 @@ function useTourPlayback({
3750
3774
  try {
3751
3775
  const { generateMinifiedAOM: generateMinifiedAOM2 } = await Promise.resolve().then(() => (init_aom(), aom_exports));
3752
3776
  const aom = generateMinifiedAOM2();
3753
- socket.emit("tour:sync_dom", {
3754
- url: window.location.pathname + window.location.search + window.location.hash,
3755
- aom: aom.nodes,
3756
- domSummary: captureDomSummary()
3757
- });
3777
+ if (socketRef.current === socket && socket.connected) {
3778
+ socket.emit("tour:sync_dom", {
3779
+ url: window.location.pathname + window.location.search + window.location.hash,
3780
+ aom: aom.nodes,
3781
+ domSummary: captureDomSummary()
3782
+ });
3783
+ }
3758
3784
  } catch (e) {
3759
3785
  console.warn("[TourClient] Initial DOM sync failed:", e);
3760
3786
  }
@@ -3782,7 +3808,7 @@ function useTourPlayback({
3782
3808
  handleTourEnd();
3783
3809
  });
3784
3810
  socket.on("tour:debug_log", (entry) => {
3785
- const isDev = devMode || process.env.NODE_ENV === "development" || typeof window !== "undefined" && window.MODELNEX_DEBUG;
3811
+ const isDev = devModeRef.current || process.env.NODE_ENV === "development" || typeof window !== "undefined" && window.MODELNEX_DEBUG;
3786
3812
  if (isDev) {
3787
3813
  console.log(`%c[ModelNex Tour] ${entry.type}`, "color: #3b82f6; font-weight: bold", entry);
3788
3814
  if (typeof window !== "undefined") {
@@ -3792,18 +3818,28 @@ function useTourPlayback({
3792
3818
  }
3793
3819
  }
3794
3820
  });
3795
- console.log("[ModelNex SDK] Tour playback initialized. Debug logs enabled:", devMode || process.env.NODE_ENV === "development");
3821
+ console.log("[ModelNex SDK] Tour playback initialized. Debug logs enabled:", devModeRef.current || process.env.NODE_ENV === "development");
3796
3822
  });
3797
3823
  return () => {
3798
- if (socketRef.current) {
3799
- socketRef.current.disconnect();
3800
- socketRef.current = null;
3824
+ cancelled = true;
3825
+ const toClose = createdSocket ?? socketRef.current;
3826
+ if (toClose) {
3827
+ toClose.disconnect();
3801
3828
  }
3829
+ createdSocket = null;
3830
+ socketRef.current = null;
3802
3831
  setServerState(null);
3803
3832
  runIdRef.current = null;
3804
3833
  turnIdRef.current = null;
3805
3834
  };
3806
- }, [serverUrl, websiteId, userProfile, disabled, devMode, experienceType]);
3835
+ }, [serverUrl, websiteId, disabled]);
3836
+ (0, import_react12.useEffect)(() => {
3837
+ if (disabled) return;
3838
+ const s = socketRef.current;
3839
+ const profile = userProfile;
3840
+ if (!s?.connected || !websiteId || !profile?.userId) return;
3841
+ s.emit("tour:init", { websiteId, userId: profile.userId, userType: profile.type });
3842
+ }, [disabled, websiteId, userProfile?.userId, userProfile?.type]);
3807
3843
  (0, import_react12.useEffect)(() => {
3808
3844
  if (!showCaptions || !isReviewMode) {
3809
3845
  removeCaption();
@@ -3942,7 +3978,7 @@ function useTourPlayback({
3942
3978
  setPendingTour(null);
3943
3979
  pendingTourRef.current = null;
3944
3980
  let retries = 0;
3945
- while (!socketRef.current?.connected && retries < 15) {
3981
+ while (!socketRef.current?.connected && retries < 30) {
3946
3982
  await new Promise((r) => setTimeout(r, 200));
3947
3983
  retries++;
3948
3984
  }
@@ -8419,7 +8455,7 @@ function ModelNexChatBubble({
8419
8455
  const messagesEndRef = (0, import_react18.useRef)(null);
8420
8456
  const abortControllerRef = (0, import_react18.useRef)(null);
8421
8457
  const panelRef = (0, import_react18.useRef)(null);
8422
- const serverUrl = ctx?.serverUrl ?? "https://69tgf4aic6.us-east-1.awsapprunner.com";
8458
+ const serverUrl = ctx?.serverUrl ?? DEFAULT_MODELNEX_SERVER_URL;
8423
8459
  const voice = useVoice(serverUrl);
8424
8460
  const audioLevels = useAudioLevel(voice.isListening);
8425
8461
  const recordingMode = ctx?.recordingMode ?? false;
@@ -8506,7 +8542,7 @@ function ModelNexChatBubble({
8506
8542
  if (lastAutoTaggedUrlRef.current === currentUrl || localStorage.getItem(storageKey)) {
8507
8543
  return;
8508
8544
  }
8509
- const baseUrl = commandUrl ?? serverUrl2 ?? "https://69tgf4aic6.us-east-1.awsapprunner.com";
8545
+ const baseUrl = commandUrl ?? serverUrl2 ?? DEFAULT_MODELNEX_SERVER_URL;
8510
8546
  const url = baseUrl.startsWith("/") ? `${window.location.origin}${baseUrl}/agent/auto-tag` : `${baseUrl}/agent/auto-tag`;
8511
8547
  const elements = extractedElements.map((el) => ({
8512
8548
  fingerprint: el.fingerprint,
@@ -8896,7 +8932,7 @@ function ModelNexChatBubble({
8896
8932
  }
8897
8933
  };
8898
8934
  const stopAgent = async () => {
8899
- const baseUrl = ctx?.commandUrl ?? ctx?.serverUrl ?? "https://69tgf4aic6.us-east-1.awsapprunner.com";
8935
+ const baseUrl = ctx?.commandUrl ?? ctx?.serverUrl ?? DEFAULT_MODELNEX_SERVER_URL;
8900
8936
  const abortUrl = baseUrl.startsWith("/") ? `${window.location.origin}${baseUrl}/agent/abort` : `${baseUrl}/agent/abort`;
8901
8937
  try {
8902
8938
  await fetch(abortUrl, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ socketId: ctx?.socketId }) });
@@ -10163,7 +10199,7 @@ function ModelNexOnboardingPanel({
10163
10199
  title = "Getting Started"
10164
10200
  }) {
10165
10201
  const ctx = (0, import_react19.useContext)(ModelNexContext);
10166
- const serverUrl = ctx?.serverUrl ?? "https://69tgf4aic6.us-east-1.awsapprunner.com";
10202
+ const serverUrl = ctx?.serverUrl ?? DEFAULT_MODELNEX_SERVER_URL;
10167
10203
  const voice = useVoice(serverUrl);
10168
10204
  const audioLevels = useAudioLevel(voice.isListening);
10169
10205
  const [input, setInput] = (0, import_react19.useState)("");
@@ -10862,15 +10898,15 @@ function TourProgressPanel({ tour, currentStepIndex, onSkip, voiceOnly }) {
10862
10898
  }
10863
10899
 
10864
10900
  // src/index.ts
10865
- var DEFAULT_SERVER_URL2 = "https://69tgf4aic6.us-east-1.awsapprunner.com";
10866
10901
  var ModelNexProvider = ({
10867
10902
  children,
10868
10903
  websiteId,
10869
10904
  userProfile,
10870
10905
  toursApiBase,
10871
- devMode
10906
+ devMode,
10907
+ serverUrl: serverUrlProp
10872
10908
  }) => {
10873
- const serverUrl = DEFAULT_SERVER_URL2;
10909
+ const serverUrl = serverUrlProp ?? DEFAULT_MODELNEX_SERVER_URL;
10874
10910
  const commandUrl = void 0;
10875
10911
  const disableSocket = false;
10876
10912
  const renderedChildren = children;
@@ -10983,6 +11019,7 @@ var ModelNexProvider = ({
10983
11019
  };
10984
11020
  // Annotate the CommonJS export names for ESM import in node:
10985
11021
  0 && (module.exports = {
11022
+ DEFAULT_MODELNEX_SERVER_URL,
10986
11023
  ModelNexChatBubble,
10987
11024
  ModelNexOnboardingPanel,
10988
11025
  ModelNexProvider,
package/dist/index.mjs CHANGED
@@ -18,11 +18,11 @@ function resolveSocketIoTransports(serverUrl, order) {
18
18
  try {
19
19
  const host = new URL(serverUrl).hostname.toLowerCase();
20
20
  if (host.endsWith("awsapprunner.com")) {
21
- return ["polling"];
21
+ return ["websocket"];
22
22
  }
23
23
  } catch {
24
24
  }
25
- return order === "websocket-first" ? ["websocket", "polling"] : ["polling", "websocket"];
25
+ return ["websocket", "polling"];
26
26
  }
27
27
 
28
28
  // src/auto-extract.ts
@@ -2113,9 +2113,11 @@ function useBuiltinActions(registerAction, unregisterAction, tagStore, serverUrl
2113
2113
  }, [registerAction, unregisterAction]);
2114
2114
  }
2115
2115
 
2116
+ // src/constants.ts
2117
+ var DEFAULT_MODELNEX_SERVER_URL = "https://api.modelnex.com";
2118
+
2116
2119
  // src/hooks/useRunCommand.ts
2117
2120
  import { useCallback as useCallback5, useContext as useContext2 } from "react";
2118
- var DEFAULT_SERVER_URL = "https://69tgf4aic6.us-east-1.awsapprunner.com";
2119
2121
  function searchTaggedElementsForQuery(store, query, limit = 8) {
2120
2122
  const allTags = store.getAllTags();
2121
2123
  if (allTags.length === 0) return [];
@@ -2136,7 +2138,7 @@ function searchTaggedElementsForQuery(store, query, limit = 8) {
2136
2138
  }
2137
2139
  function useRunCommand(serverUrlOverride) {
2138
2140
  const context = useContext2(ModelNexContext);
2139
- const baseUrl = serverUrlOverride ?? context?.commandUrl ?? context?.serverUrl ?? DEFAULT_SERVER_URL;
2141
+ const baseUrl = serverUrlOverride ?? context?.commandUrl ?? context?.serverUrl ?? DEFAULT_MODELNEX_SERVER_URL;
2140
2142
  const tagStore = context?.tagStore;
2141
2143
  return useCallback5(
2142
2144
  async (command, signal) => {
@@ -2942,6 +2944,12 @@ function useTourPlayback({
2942
2944
  const [serverState, setServerState] = useState7(null);
2943
2945
  const ctx = useContext4(ModelNexContext);
2944
2946
  const devMode = ctx?.devMode;
2947
+ const devModeRef = useRef8(devMode);
2948
+ devModeRef.current = devMode;
2949
+ const userProfileRef = useRef8(userProfile);
2950
+ userProfileRef.current = userProfile;
2951
+ const experienceTypeRef = useRef8(experienceType);
2952
+ experienceTypeRef.current = experienceType;
2945
2953
  const tourRef = useRef8(null);
2946
2954
  const stepIndexRef = useRef8(0);
2947
2955
  const skipRequestedRef = useRef8(false);
@@ -2981,18 +2989,27 @@ function useTourPlayback({
2981
2989
  useEffect11(() => {
2982
2990
  if (disabled) return;
2983
2991
  if (typeof window === "undefined") return;
2992
+ let cancelled = false;
2993
+ let createdSocket = null;
2984
2994
  import("socket.io-client").then((ioModule) => {
2995
+ if (cancelled) return;
2985
2996
  const io2 = ioModule.default || ioModule;
2986
2997
  const socket = io2(serverUrl, {
2987
2998
  path: "/socket.io",
2988
2999
  // standard
2989
- transports: resolveSocketIoTransports(serverUrl, "websocket-first")
3000
+ transports: resolveSocketIoTransports(serverUrl, "polling-first")
2990
3001
  });
3002
+ if (cancelled) {
3003
+ socket.disconnect();
3004
+ return;
3005
+ }
3006
+ createdSocket = socket;
2991
3007
  socketRef.current = socket;
2992
3008
  socket.on("connect", () => {
2993
3009
  console.log("[TourClient] Connected to tour agent server:", socket.id);
2994
- if (websiteId && userProfile) {
2995
- socket.emit("tour:init", { websiteId, userId: userProfile.userId, userType: userProfile.type });
3010
+ const profile = userProfileRef.current;
3011
+ if (websiteId && profile?.userId) {
3012
+ socket.emit("tour:init", { websiteId, userId: profile.userId, userType: profile.type });
2996
3013
  }
2997
3014
  });
2998
3015
  socket.on("tour:server_state", (payload) => {
@@ -3017,6 +3034,11 @@ function useTourPlayback({
3017
3034
  }
3018
3035
  });
3019
3036
  socket.on("tour:command", async (payload) => {
3037
+ const emitIfOpen = (ev, data) => {
3038
+ if (socketRef.current !== socket) return;
3039
+ if (!socket.connected) return;
3040
+ socket.emit(ev, data);
3041
+ };
3020
3042
  console.log("[TourClient] Received command batch:", payload.stepIndex, payload.commands);
3021
3043
  runCleanup(pendingManualWaitCleanupRef.current);
3022
3044
  pendingManualWaitCleanupRef.current = null;
@@ -3075,7 +3097,7 @@ function useTourPlayback({
3075
3097
  if (!payload.commands || !Array.isArray(payload.commands)) {
3076
3098
  console.warn("[TourClient] Payload commands is not an array:", payload);
3077
3099
  commandInFlightRef.current = false;
3078
- socket.emit("tour:action_result", {
3100
+ emitIfOpen("tour:action_result", {
3079
3101
  success: false,
3080
3102
  reason: "invalid_commands",
3081
3103
  commandBatchId,
@@ -3354,7 +3376,7 @@ function useTourPlayback({
3354
3376
  currentStepOrder: stepIndexRef.current
3355
3377
  });
3356
3378
  }
3357
- socket.emit("tour:action_result", {
3379
+ emitIfOpen("tour:action_result", {
3358
3380
  success: true,
3359
3381
  interrupted: true,
3360
3382
  results,
@@ -3379,7 +3401,7 @@ function useTourPlayback({
3379
3401
  currentStepOrder: stepIndexRef.current
3380
3402
  });
3381
3403
  }
3382
- socket.emit("tour:action_result", {
3404
+ emitIfOpen("tour:action_result", {
3383
3405
  success: false,
3384
3406
  reason: "execution_error",
3385
3407
  error: String(err),
@@ -3448,7 +3470,7 @@ function useTourPlayback({
3448
3470
  currentStepOrder: stepIndexRef.current
3449
3471
  });
3450
3472
  }
3451
- socket.emit("tour:action_result", {
3473
+ emitIfOpen("tour:action_result", {
3452
3474
  success: true,
3453
3475
  waitingForInput: true,
3454
3476
  results,
@@ -3481,7 +3503,7 @@ function useTourPlayback({
3481
3503
  const { waitForDomSettle } = await import("./dom-sync-L5KIP45X.mjs");
3482
3504
  await waitForDomSettle({ timeoutMs: 1500, debounceMs: 200 });
3483
3505
  await syncAOM();
3484
- socket.emit("tour:user_input", {
3506
+ emitIfOpen("tour:user_input", {
3485
3507
  transcript,
3486
3508
  runId: runIdRef.current,
3487
3509
  turnId: turnIdRef.current
@@ -3500,7 +3522,7 @@ function useTourPlayback({
3500
3522
  currentStepOrder: stepIndexRef.current
3501
3523
  });
3502
3524
  }
3503
- socket.emit("tour:action_result", {
3525
+ emitIfOpen("tour:action_result", {
3504
3526
  success: true,
3505
3527
  results,
3506
3528
  commandBatchId,
@@ -3513,8 +3535,9 @@ function useTourPlayback({
3513
3535
  if (isActiveRef.current) return;
3514
3536
  runIdRef.current = typeof tourData.runId === "number" ? tourData.runId : runIdRef.current;
3515
3537
  const tour = tourData.tourContext ?? tourRef.current;
3516
- if (tour?.type && tour.type !== experienceType) {
3517
- console.log(`[TourClient] Ignoring ${tour.type} start (this hook is for ${experienceType})`);
3538
+ const expType = experienceTypeRef.current;
3539
+ if (tour?.type && tour.type !== expType) {
3540
+ console.log(`[TourClient] Ignoring ${tour.type} start (this hook is for ${expType})`);
3518
3541
  return;
3519
3542
  }
3520
3543
  skipRequestedRef.current = false;
@@ -3541,11 +3564,13 @@ function useTourPlayback({
3541
3564
  try {
3542
3565
  const { generateMinifiedAOM: generateMinifiedAOM2 } = await import("./aom-HDYNCIOY.mjs");
3543
3566
  const aom = generateMinifiedAOM2();
3544
- socket.emit("tour:sync_dom", {
3545
- url: window.location.pathname + window.location.search + window.location.hash,
3546
- aom: aom.nodes,
3547
- domSummary: captureDomSummary()
3548
- });
3567
+ if (socketRef.current === socket && socket.connected) {
3568
+ socket.emit("tour:sync_dom", {
3569
+ url: window.location.pathname + window.location.search + window.location.hash,
3570
+ aom: aom.nodes,
3571
+ domSummary: captureDomSummary()
3572
+ });
3573
+ }
3549
3574
  } catch (e) {
3550
3575
  console.warn("[TourClient] Initial DOM sync failed:", e);
3551
3576
  }
@@ -3573,7 +3598,7 @@ function useTourPlayback({
3573
3598
  handleTourEnd();
3574
3599
  });
3575
3600
  socket.on("tour:debug_log", (entry) => {
3576
- const isDev = devMode || process.env.NODE_ENV === "development" || typeof window !== "undefined" && window.MODELNEX_DEBUG;
3601
+ const isDev = devModeRef.current || process.env.NODE_ENV === "development" || typeof window !== "undefined" && window.MODELNEX_DEBUG;
3577
3602
  if (isDev) {
3578
3603
  console.log(`%c[ModelNex Tour] ${entry.type}`, "color: #3b82f6; font-weight: bold", entry);
3579
3604
  if (typeof window !== "undefined") {
@@ -3583,18 +3608,28 @@ function useTourPlayback({
3583
3608
  }
3584
3609
  }
3585
3610
  });
3586
- console.log("[ModelNex SDK] Tour playback initialized. Debug logs enabled:", devMode || process.env.NODE_ENV === "development");
3611
+ console.log("[ModelNex SDK] Tour playback initialized. Debug logs enabled:", devModeRef.current || process.env.NODE_ENV === "development");
3587
3612
  });
3588
3613
  return () => {
3589
- if (socketRef.current) {
3590
- socketRef.current.disconnect();
3591
- socketRef.current = null;
3614
+ cancelled = true;
3615
+ const toClose = createdSocket ?? socketRef.current;
3616
+ if (toClose) {
3617
+ toClose.disconnect();
3592
3618
  }
3619
+ createdSocket = null;
3620
+ socketRef.current = null;
3593
3621
  setServerState(null);
3594
3622
  runIdRef.current = null;
3595
3623
  turnIdRef.current = null;
3596
3624
  };
3597
- }, [serverUrl, websiteId, userProfile, disabled, devMode, experienceType]);
3625
+ }, [serverUrl, websiteId, disabled]);
3626
+ useEffect11(() => {
3627
+ if (disabled) return;
3628
+ const s = socketRef.current;
3629
+ const profile = userProfile;
3630
+ if (!s?.connected || !websiteId || !profile?.userId) return;
3631
+ s.emit("tour:init", { websiteId, userId: profile.userId, userType: profile.type });
3632
+ }, [disabled, websiteId, userProfile?.userId, userProfile?.type]);
3598
3633
  useEffect11(() => {
3599
3634
  if (!showCaptions || !isReviewMode) {
3600
3635
  removeCaption();
@@ -3733,7 +3768,7 @@ function useTourPlayback({
3733
3768
  setPendingTour(null);
3734
3769
  pendingTourRef.current = null;
3735
3770
  let retries = 0;
3736
- while (!socketRef.current?.connected && retries < 15) {
3771
+ while (!socketRef.current?.connected && retries < 30) {
3737
3772
  await new Promise((r) => setTimeout(r, 200));
3738
3773
  retries++;
3739
3774
  }
@@ -8209,7 +8244,7 @@ function ModelNexChatBubble({
8209
8244
  const messagesEndRef = useRef13(null);
8210
8245
  const abortControllerRef = useRef13(null);
8211
8246
  const panelRef = useRef13(null);
8212
- const serverUrl = ctx?.serverUrl ?? "https://69tgf4aic6.us-east-1.awsapprunner.com";
8247
+ const serverUrl = ctx?.serverUrl ?? DEFAULT_MODELNEX_SERVER_URL;
8213
8248
  const voice = useVoice(serverUrl);
8214
8249
  const audioLevels = useAudioLevel(voice.isListening);
8215
8250
  const recordingMode = ctx?.recordingMode ?? false;
@@ -8296,7 +8331,7 @@ function ModelNexChatBubble({
8296
8331
  if (lastAutoTaggedUrlRef.current === currentUrl || localStorage.getItem(storageKey)) {
8297
8332
  return;
8298
8333
  }
8299
- const baseUrl = commandUrl ?? serverUrl2 ?? "https://69tgf4aic6.us-east-1.awsapprunner.com";
8334
+ const baseUrl = commandUrl ?? serverUrl2 ?? DEFAULT_MODELNEX_SERVER_URL;
8300
8335
  const url = baseUrl.startsWith("/") ? `${window.location.origin}${baseUrl}/agent/auto-tag` : `${baseUrl}/agent/auto-tag`;
8301
8336
  const elements = extractedElements.map((el) => ({
8302
8337
  fingerprint: el.fingerprint,
@@ -8686,7 +8721,7 @@ function ModelNexChatBubble({
8686
8721
  }
8687
8722
  };
8688
8723
  const stopAgent = async () => {
8689
- const baseUrl = ctx?.commandUrl ?? ctx?.serverUrl ?? "https://69tgf4aic6.us-east-1.awsapprunner.com";
8724
+ const baseUrl = ctx?.commandUrl ?? ctx?.serverUrl ?? DEFAULT_MODELNEX_SERVER_URL;
8690
8725
  const abortUrl = baseUrl.startsWith("/") ? `${window.location.origin}${baseUrl}/agent/abort` : `${baseUrl}/agent/abort`;
8691
8726
  try {
8692
8727
  await fetch(abortUrl, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ socketId: ctx?.socketId }) });
@@ -9953,7 +9988,7 @@ function ModelNexOnboardingPanel({
9953
9988
  title = "Getting Started"
9954
9989
  }) {
9955
9990
  const ctx = useContext6(ModelNexContext);
9956
- const serverUrl = ctx?.serverUrl ?? "https://69tgf4aic6.us-east-1.awsapprunner.com";
9991
+ const serverUrl = ctx?.serverUrl ?? DEFAULT_MODELNEX_SERVER_URL;
9957
9992
  const voice = useVoice(serverUrl);
9958
9993
  const audioLevels = useAudioLevel(voice.isListening);
9959
9994
  const [input, setInput] = useState14("");
@@ -10652,15 +10687,15 @@ function TourProgressPanel({ tour, currentStepIndex, onSkip, voiceOnly }) {
10652
10687
  }
10653
10688
 
10654
10689
  // src/index.ts
10655
- var DEFAULT_SERVER_URL2 = "https://69tgf4aic6.us-east-1.awsapprunner.com";
10656
10690
  var ModelNexProvider = ({
10657
10691
  children,
10658
10692
  websiteId,
10659
10693
  userProfile,
10660
10694
  toursApiBase,
10661
- devMode
10695
+ devMode,
10696
+ serverUrl: serverUrlProp
10662
10697
  }) => {
10663
- const serverUrl = DEFAULT_SERVER_URL2;
10698
+ const serverUrl = serverUrlProp ?? DEFAULT_MODELNEX_SERVER_URL;
10664
10699
  const commandUrl = void 0;
10665
10700
  const disableSocket = false;
10666
10701
  const renderedChildren = children;
@@ -10772,6 +10807,7 @@ var ModelNexProvider = ({
10772
10807
  );
10773
10808
  };
10774
10809
  export {
10810
+ DEFAULT_MODELNEX_SERVER_URL,
10775
10811
  ModelNexChatBubble,
10776
10812
  ModelNexOnboardingPanel,
10777
10813
  ModelNexProvider,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@modelnex/sdk",
3
- "version": "0.5.13",
3
+ "version": "0.5.15",
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
+ }