@modelnex/sdk 0.5.29 → 0.5.30

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.
package/README.md CHANGED
@@ -86,7 +86,6 @@ Current behavior:
86
86
  | `serverUrl` | Backend base URL for chat, tags, tours, voice, and recording APIs |
87
87
  | `websiteId` | Tenant/integration identifier |
88
88
  | `userProfile` | End-user targeting data for tours/workflows |
89
- | `devMode` | Enables recording/studio tooling for your internal users |
90
89
 
91
90
  ## Chat Bubble Props
92
91
 
@@ -115,10 +114,7 @@ export function AppShell({ children, currentUser }) {
115
114
  return (
116
115
  <ModelNexProvider
117
116
  websiteId="prod_site_123"
118
-
119
- // Development setup
120
- devMode={process.env.NODE_ENV === 'development'}
121
-
117
+
122
118
  // User Targeting for Tours & Workflows
123
119
  userProfile={{
124
120
  userId: currentUser.id,
@@ -132,6 +128,16 @@ export function AppShell({ children, currentUser }) {
132
128
  }
133
129
  ```
134
130
 
131
+ ### Browser-Injected Dev Mode
132
+
133
+ ```html
134
+ <script>
135
+ window.__MODELNEX_DEV_MODE_KEY__ = 'dmk_live_xxxxxxxxx';
136
+ </script>
137
+ ```
138
+
139
+ The SDK now enables dev tooling only after it finds a browser-injected dev mode key and validates it with the backend for the current `websiteId`.
140
+
135
141
  ### Themed Chat Bubble
136
142
 
137
143
  ```tsx
@@ -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
@@ -845,15 +845,6 @@ interface ModelNexProviderProps {
845
845
  * Same-origin base for tour API (avoids CORS for ?modelnex_test_tour=)
846
846
  */
847
847
  toursApiBase?: string;
848
- /**
849
- * Enable SDK dev tools unconditionally (tour recording, studio mode)
850
- */
851
- devMode?: boolean;
852
- /**
853
- * Optional dev mode key. When present, the SDK validates it with the backend
854
- * and enables dev tooling when the key matches the project configuration.
855
- */
856
- devModeKey?: string;
857
848
  }
858
849
  declare const ModelNexProvider: React$1.FC<ModelNexProviderProps>;
859
850
 
package/dist/index.d.ts CHANGED
@@ -845,15 +845,6 @@ interface ModelNexProviderProps {
845
845
  * Same-origin base for tour API (avoids CORS for ?modelnex_test_tour=)
846
846
  */
847
847
  toursApiBase?: string;
848
- /**
849
- * Enable SDK dev tools unconditionally (tour recording, studio mode)
850
- */
851
- devMode?: boolean;
852
- /**
853
- * Optional dev mode key. When present, the SDK validates it with the backend
854
- * and enables dev tooling when the key matches the project configuration.
855
- */
856
- devModeKey?: string;
857
848
  }
858
849
  declare const ModelNexProvider: React$1.FC<ModelNexProviderProps>;
859
850
 
package/dist/index.js CHANGED
@@ -2766,9 +2766,7 @@ function normalizeDevModeKey(value) {
2766
2766
  const normalized = value.trim();
2767
2767
  return normalized || void 0;
2768
2768
  }
2769
- function resolveInjectedDevModeKey(explicitDevModeKey) {
2770
- const normalizedExplicitKey = normalizeDevModeKey(explicitDevModeKey);
2771
- if (normalizedExplicitKey) return normalizedExplicitKey;
2769
+ function resolveInjectedDevModeKey() {
2772
2770
  if (typeof window === "undefined") return void 0;
2773
2771
  const browserWindow = window;
2774
2772
  for (const globalName of DEV_MODE_KEY_GLOBAL_NAMES) {
@@ -11741,8 +11739,6 @@ var ModelNexProvider = ({
11741
11739
  websiteId,
11742
11740
  userProfile,
11743
11741
  toursApiBase,
11744
- devMode,
11745
- devModeKey,
11746
11742
  serverUrl: serverUrlProp
11747
11743
  }) => {
11748
11744
  const serverUrl = serverUrlProp ?? DEFAULT_MODELNEX_SERVER_URL;
@@ -11766,7 +11762,7 @@ var ModelNexProvider = ({
11766
11762
  const [socketId, setSocketId] = (0, import_react21.useState)(null);
11767
11763
  const [actions, setActions] = (0, import_react21.useState)(/* @__PURE__ */ new Map());
11768
11764
  const [validatedBrowserDevMode, setValidatedBrowserDevMode] = (0, import_react21.useState)(false);
11769
- const resolvedDevModeKey = (0, import_react21.useMemo)(() => resolveInjectedDevModeKey(devModeKey), [devModeKey]);
11765
+ const resolvedDevModeKey = (0, import_react21.useMemo)(() => resolveInjectedDevModeKey(), []);
11770
11766
  (0, import_react21.useEffect)(() => {
11771
11767
  let cancelled = false;
11772
11768
  if (!websiteId || !resolvedDevModeKey) {
@@ -11783,7 +11779,7 @@ var ModelNexProvider = ({
11783
11779
  cancelled = true;
11784
11780
  };
11785
11781
  }, [resolvedDevModeKey, serverUrl, websiteId]);
11786
- const effectiveDevMode = Boolean(devMode) || validatedBrowserDevMode;
11782
+ const effectiveDevMode = validatedBrowserDevMode;
11787
11783
  const registerAction = (0, import_react21.useCallback)((action) => {
11788
11784
  setActions((prev) => {
11789
11785
  const next = new Map(prev);
package/dist/index.mjs CHANGED
@@ -2557,9 +2557,7 @@ function normalizeDevModeKey(value) {
2557
2557
  const normalized = value.trim();
2558
2558
  return normalized || void 0;
2559
2559
  }
2560
- function resolveInjectedDevModeKey(explicitDevModeKey) {
2561
- const normalizedExplicitKey = normalizeDevModeKey(explicitDevModeKey);
2562
- if (normalizedExplicitKey) return normalizedExplicitKey;
2560
+ function resolveInjectedDevModeKey() {
2563
2561
  if (typeof window === "undefined") return void 0;
2564
2562
  const browserWindow = window;
2565
2563
  for (const globalName of DEV_MODE_KEY_GLOBAL_NAMES) {
@@ -11531,8 +11529,6 @@ var ModelNexProvider = ({
11531
11529
  websiteId,
11532
11530
  userProfile,
11533
11531
  toursApiBase,
11534
- devMode,
11535
- devModeKey,
11536
11532
  serverUrl: serverUrlProp
11537
11533
  }) => {
11538
11534
  const serverUrl = serverUrlProp ?? DEFAULT_MODELNEX_SERVER_URL;
@@ -11556,7 +11552,7 @@ var ModelNexProvider = ({
11556
11552
  const [socketId, setSocketId] = useState15(null);
11557
11553
  const [actions, setActions] = useState15(/* @__PURE__ */ new Map());
11558
11554
  const [validatedBrowserDevMode, setValidatedBrowserDevMode] = useState15(false);
11559
- const resolvedDevModeKey = useMemo5(() => resolveInjectedDevModeKey(devModeKey), [devModeKey]);
11555
+ const resolvedDevModeKey = useMemo5(() => resolveInjectedDevModeKey(), []);
11560
11556
  useEffect19(() => {
11561
11557
  let cancelled = false;
11562
11558
  if (!websiteId || !resolvedDevModeKey) {
@@ -11573,7 +11569,7 @@ var ModelNexProvider = ({
11573
11569
  cancelled = true;
11574
11570
  };
11575
11571
  }, [resolvedDevModeKey, serverUrl, websiteId]);
11576
- const effectiveDevMode = Boolean(devMode) || validatedBrowserDevMode;
11572
+ const effectiveDevMode = validatedBrowserDevMode;
11577
11573
  const registerAction = useCallback14((action) => {
11578
11574
  setActions((prev) => {
11579
11575
  const next = new Map(prev);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@modelnex/sdk",
3
- "version": "0.5.29",
3
+ "version": "0.5.30",
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
+ }