@modelnex/sdk 0.5.35 → 0.5.37

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/dist/index.d.mts CHANGED
@@ -817,9 +817,14 @@ interface SavedDraftPreview {
817
817
  experienceType: ExperienceType;
818
818
  }
819
819
  type PreviewLaunchSource = 'standard' | 'query_param';
820
+ type DraftPreviewModeListener = (enabled: boolean) => void;
820
821
  declare function getPreviewQueryParamName(experienceType: ExperienceType): 'modelnex_test_tour' | 'modelnex_test_workflow';
821
822
  declare function buildDraftPreviewUrl(currentUrl: string, draft: SavedDraftPreview): string;
822
823
  declare function shouldPromptForPreviewStart(notificationType: TourNotificationType | undefined, _source: PreviewLaunchSource): boolean;
824
+ declare function hasDraftPreviewModeSignal(): boolean;
825
+ declare function observeDraftPreviewModeSignal(listener: DraftPreviewModeListener, options?: {
826
+ pollIntervalMs?: number;
827
+ }): () => void;
823
828
  declare function persistActiveDraftPreview(draft: SavedDraftPreview): void;
824
829
  declare function readActiveDraftPreview(): SavedDraftPreview | null;
825
830
  declare function clearActiveDraftPreview(experienceType?: ExperienceType): void;
@@ -847,4 +852,4 @@ interface ModelNexProviderProps {
847
852
  }
848
853
  declare const ModelNexProvider: React$1.FC<ModelNexProviderProps>;
849
854
 
850
- 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 };
855
+ 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, hasDraftPreviewModeSignal, inferOnboardingMetadataForStep, isAskDrivenInputStepType, isInteractiveInputStepType, isManualOnboardingStep, isRecordingDraftGenerating, observeDraftPreviewModeSignal, persistActiveDraftPreview, readActiveDraftPreview, shouldPromptForPreviewStart, shouldShowRecordingOverlay, useActionHighlight, useAgentViewport, useAutoExtract, useExperiencePlayback, useOnboardingPlayback, useRecordingMode, useRunCommand, useTagStore, useTourPlayback, useUIState, useViewportTrack, useVisibleIds, useVoice };
package/dist/index.d.ts CHANGED
@@ -817,9 +817,14 @@ interface SavedDraftPreview {
817
817
  experienceType: ExperienceType;
818
818
  }
819
819
  type PreviewLaunchSource = 'standard' | 'query_param';
820
+ type DraftPreviewModeListener = (enabled: boolean) => void;
820
821
  declare function getPreviewQueryParamName(experienceType: ExperienceType): 'modelnex_test_tour' | 'modelnex_test_workflow';
821
822
  declare function buildDraftPreviewUrl(currentUrl: string, draft: SavedDraftPreview): string;
822
823
  declare function shouldPromptForPreviewStart(notificationType: TourNotificationType | undefined, _source: PreviewLaunchSource): boolean;
824
+ declare function hasDraftPreviewModeSignal(): boolean;
825
+ declare function observeDraftPreviewModeSignal(listener: DraftPreviewModeListener, options?: {
826
+ pollIntervalMs?: number;
827
+ }): () => void;
823
828
  declare function persistActiveDraftPreview(draft: SavedDraftPreview): void;
824
829
  declare function readActiveDraftPreview(): SavedDraftPreview | null;
825
830
  declare function clearActiveDraftPreview(experienceType?: ExperienceType): void;
@@ -847,4 +852,4 @@ interface ModelNexProviderProps {
847
852
  }
848
853
  declare const ModelNexProvider: React$1.FC<ModelNexProviderProps>;
849
854
 
850
- 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 };
855
+ 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, hasDraftPreviewModeSignal, inferOnboardingMetadataForStep, isAskDrivenInputStepType, isInteractiveInputStepType, isManualOnboardingStep, isRecordingDraftGenerating, observeDraftPreviewModeSignal, persistActiveDraftPreview, readActiveDraftPreview, shouldPromptForPreviewStart, shouldShowRecordingOverlay, useActionHighlight, useAgentViewport, useAutoExtract, useExperiencePlayback, useOnboardingPlayback, useRecordingMode, useRunCommand, useTagStore, useTourPlayback, useUIState, useViewportTrack, useVisibleIds, useVoice };
package/dist/index.js CHANGED
@@ -188,11 +188,13 @@ __export(index_exports, {
188
188
  getPreviewQueryParamName: () => getPreviewQueryParamName,
189
189
  getRecordingDraftActionLabel: () => getRecordingDraftActionLabel,
190
190
  getRecordingDraftStatusMessage: () => getRecordingDraftStatusMessage,
191
+ hasDraftPreviewModeSignal: () => hasDraftPreviewModeSignal,
191
192
  inferOnboardingMetadataForStep: () => inferOnboardingMetadataForStep,
192
193
  isAskDrivenInputStepType: () => isAskDrivenInputStepType,
193
194
  isInteractiveInputStepType: () => isInteractiveInputStepType,
194
195
  isManualOnboardingStep: () => isManualOnboardingStep,
195
196
  isRecordingDraftGenerating: () => isRecordingDraftGenerating,
197
+ observeDraftPreviewModeSignal: () => observeDraftPreviewModeSignal,
196
198
  persistActiveDraftPreview: () => persistActiveDraftPreview,
197
199
  readActiveDraftPreview: () => readActiveDraftPreview,
198
200
  shouldPromptForPreviewStart: () => shouldPromptForPreviewStart,
@@ -2918,6 +2920,159 @@ function clearPersistedRecordingSession() {
2918
2920
  }
2919
2921
  }
2920
2922
 
2923
+ // src/utils/draftPreview.ts
2924
+ var ACTIVE_DRAFT_PREVIEW_STORAGE_KEY = "modelnex:active-draft-preview";
2925
+ var PREVIEW_SESSION_SUPPRESSION_STORAGE_KEY = "modelnex:preview-session-suppressed";
2926
+ var SUPPRESSED_DRAFT_PREVIEW_STORAGE_KEY = "modelnex:suppressed-draft-preview";
2927
+ function getPreviewQueryParamName(experienceType) {
2928
+ return experienceType === "onboarding" ? "modelnex_test_workflow" : "modelnex_test_tour";
2929
+ }
2930
+ function buildDraftPreviewUrl(currentUrl, draft) {
2931
+ const url = new URL(currentUrl);
2932
+ url.searchParams.delete("modelnex_test_tour");
2933
+ url.searchParams.delete("modelnex_test_onboarding");
2934
+ url.searchParams.delete("modelnex_test_workflow");
2935
+ url.searchParams.set(getPreviewQueryParamName(draft.experienceType), draft.id);
2936
+ return url.toString();
2937
+ }
2938
+ function shouldPromptForPreviewStart(notificationType, _source) {
2939
+ const normalizedNotificationType = notificationType ?? "bubble_card";
2940
+ return normalizedNotificationType === "modal";
2941
+ }
2942
+ function hasDraftPreviewModeSignal() {
2943
+ if (typeof window === "undefined") return false;
2944
+ try {
2945
+ const params = new URLSearchParams(window.location.search);
2946
+ if (params.has("modelnex_test_tour") || params.has("modelnex_test_workflow") || params.has("modelnex_test_onboarding")) {
2947
+ return true;
2948
+ }
2949
+ } catch {
2950
+ }
2951
+ return readActiveDraftPreview() !== null;
2952
+ }
2953
+ function observeDraftPreviewModeSignal(listener, options) {
2954
+ if (typeof window === "undefined") return () => {
2955
+ };
2956
+ let currentValue = hasDraftPreviewModeSignal();
2957
+ const pollIntervalMs = options?.pollIntervalMs ?? 500;
2958
+ const syncPreviewModeSignal = () => {
2959
+ const nextValue = hasDraftPreviewModeSignal();
2960
+ if (nextValue === currentValue) return;
2961
+ currentValue = nextValue;
2962
+ listener(nextValue);
2963
+ };
2964
+ const intervalId = window.setInterval(syncPreviewModeSignal, pollIntervalMs);
2965
+ window.addEventListener("focus", syncPreviewModeSignal);
2966
+ window.addEventListener("pageshow", syncPreviewModeSignal);
2967
+ window.addEventListener("popstate", syncPreviewModeSignal);
2968
+ if (typeof document !== "undefined") {
2969
+ document.addEventListener("visibilitychange", syncPreviewModeSignal);
2970
+ }
2971
+ return () => {
2972
+ window.clearInterval(intervalId);
2973
+ window.removeEventListener("focus", syncPreviewModeSignal);
2974
+ window.removeEventListener("pageshow", syncPreviewModeSignal);
2975
+ window.removeEventListener("popstate", syncPreviewModeSignal);
2976
+ if (typeof document !== "undefined") {
2977
+ document.removeEventListener("visibilitychange", syncPreviewModeSignal);
2978
+ }
2979
+ };
2980
+ }
2981
+ function persistActiveDraftPreview(draft) {
2982
+ if (typeof window === "undefined") return;
2983
+ try {
2984
+ window.sessionStorage.setItem(ACTIVE_DRAFT_PREVIEW_STORAGE_KEY, JSON.stringify(draft));
2985
+ } catch {
2986
+ }
2987
+ }
2988
+ function readActiveDraftPreview() {
2989
+ if (typeof window === "undefined") return null;
2990
+ try {
2991
+ const raw = window.sessionStorage.getItem(ACTIVE_DRAFT_PREVIEW_STORAGE_KEY);
2992
+ if (!raw) return null;
2993
+ const parsed = JSON.parse(raw);
2994
+ if (!parsed || typeof parsed.id !== "string") return null;
2995
+ if (parsed.experienceType !== "tour" && parsed.experienceType !== "onboarding") return null;
2996
+ return {
2997
+ id: parsed.id,
2998
+ experienceType: parsed.experienceType
2999
+ };
3000
+ } catch {
3001
+ return null;
3002
+ }
3003
+ }
3004
+ function clearActiveDraftPreview(experienceType) {
3005
+ if (typeof window === "undefined") return;
3006
+ try {
3007
+ const activePreview = readActiveDraftPreview();
3008
+ if (experienceType && activePreview && activePreview.experienceType !== experienceType) {
3009
+ return;
3010
+ }
3011
+ window.sessionStorage.removeItem(ACTIVE_DRAFT_PREVIEW_STORAGE_KEY);
3012
+ } catch {
3013
+ }
3014
+ }
3015
+ function readSavedDraftPreview(storageKey) {
3016
+ if (typeof window === "undefined") return null;
3017
+ try {
3018
+ const raw = window.sessionStorage.getItem(storageKey);
3019
+ if (!raw) return null;
3020
+ const parsed = JSON.parse(raw);
3021
+ if (!parsed || typeof parsed.id !== "string") return null;
3022
+ if (parsed.experienceType !== "tour" && parsed.experienceType !== "onboarding") return null;
3023
+ return {
3024
+ id: parsed.id,
3025
+ experienceType: parsed.experienceType
3026
+ };
3027
+ } catch {
3028
+ return null;
3029
+ }
3030
+ }
3031
+ function readSuppressedDraftPreview() {
3032
+ return readSavedDraftPreview(SUPPRESSED_DRAFT_PREVIEW_STORAGE_KEY);
3033
+ }
3034
+ function persistSuppressedDraftPreview(draft) {
3035
+ if (typeof window === "undefined") return;
3036
+ try {
3037
+ window.sessionStorage.setItem(SUPPRESSED_DRAFT_PREVIEW_STORAGE_KEY, JSON.stringify(draft));
3038
+ } catch {
3039
+ }
3040
+ }
3041
+ function clearSuppressedDraftPreview(draft) {
3042
+ if (typeof window === "undefined") return;
3043
+ try {
3044
+ const suppressedDraft = readSuppressedDraftPreview();
3045
+ if (draft && suppressedDraft) {
3046
+ if (suppressedDraft.id !== draft.id || suppressedDraft.experienceType !== draft.experienceType) {
3047
+ return;
3048
+ }
3049
+ }
3050
+ window.sessionStorage.removeItem(SUPPRESSED_DRAFT_PREVIEW_STORAGE_KEY);
3051
+ } catch {
3052
+ }
3053
+ }
3054
+ function isSuppressedDraftPreview(draft) {
3055
+ const suppressedDraft = readSuppressedDraftPreview();
3056
+ return Boolean(
3057
+ suppressedDraft && suppressedDraft.id === draft.id && suppressedDraft.experienceType === draft.experienceType
3058
+ );
3059
+ }
3060
+ function persistPreviewSessionSuppression() {
3061
+ if (typeof window === "undefined") return;
3062
+ try {
3063
+ window.sessionStorage.setItem(PREVIEW_SESSION_SUPPRESSION_STORAGE_KEY, "true");
3064
+ } catch {
3065
+ }
3066
+ }
3067
+ function readPreviewSessionSuppression() {
3068
+ if (typeof window === "undefined") return false;
3069
+ try {
3070
+ return window.sessionStorage.getItem(PREVIEW_SESSION_SUPPRESSION_STORAGE_KEY) === "true";
3071
+ } catch {
3072
+ return false;
3073
+ }
3074
+ }
3075
+
2921
3076
  // src/hooks/useRunCommand.ts
2922
3077
  var import_react9 = require("react");
2923
3078
  function searchTaggedElementsForQuery(store, query, limit = 8) {
@@ -3053,118 +3208,10 @@ var import_react_dom = require("react-dom");
3053
3208
  // src/hooks/useExperiencePlaybackController.ts
3054
3209
  var import_react13 = require("react");
3055
3210
 
3056
- // src/utils/draftPreview.ts
3057
- var ACTIVE_DRAFT_PREVIEW_STORAGE_KEY = "modelnex:active-draft-preview";
3058
- var PREVIEW_SESSION_SUPPRESSION_STORAGE_KEY = "modelnex:preview-session-suppressed";
3059
- var SUPPRESSED_DRAFT_PREVIEW_STORAGE_KEY = "modelnex:suppressed-draft-preview";
3060
- function getPreviewQueryParamName(experienceType) {
3061
- return experienceType === "onboarding" ? "modelnex_test_workflow" : "modelnex_test_tour";
3062
- }
3063
- function buildDraftPreviewUrl(currentUrl, draft) {
3064
- const url = new URL(currentUrl);
3065
- url.searchParams.delete("modelnex_test_tour");
3066
- url.searchParams.delete("modelnex_test_onboarding");
3067
- url.searchParams.delete("modelnex_test_workflow");
3068
- url.searchParams.set(getPreviewQueryParamName(draft.experienceType), draft.id);
3069
- return url.toString();
3070
- }
3071
- function shouldPromptForPreviewStart(notificationType, _source) {
3072
- const normalizedNotificationType = notificationType ?? "bubble_card";
3073
- return normalizedNotificationType === "modal";
3074
- }
3075
- function persistActiveDraftPreview(draft) {
3076
- if (typeof window === "undefined") return;
3077
- try {
3078
- window.sessionStorage.setItem(ACTIVE_DRAFT_PREVIEW_STORAGE_KEY, JSON.stringify(draft));
3079
- } catch {
3080
- }
3081
- }
3082
- function readActiveDraftPreview() {
3083
- if (typeof window === "undefined") return null;
3084
- try {
3085
- const raw = window.sessionStorage.getItem(ACTIVE_DRAFT_PREVIEW_STORAGE_KEY);
3086
- if (!raw) return null;
3087
- const parsed = JSON.parse(raw);
3088
- if (!parsed || typeof parsed.id !== "string") return null;
3089
- if (parsed.experienceType !== "tour" && parsed.experienceType !== "onboarding") return null;
3090
- return {
3091
- id: parsed.id,
3092
- experienceType: parsed.experienceType
3093
- };
3094
- } catch {
3095
- return null;
3096
- }
3097
- }
3098
- function clearActiveDraftPreview(experienceType) {
3099
- if (typeof window === "undefined") return;
3100
- try {
3101
- const activePreview = readActiveDraftPreview();
3102
- if (experienceType && activePreview && activePreview.experienceType !== experienceType) {
3103
- return;
3104
- }
3105
- window.sessionStorage.removeItem(ACTIVE_DRAFT_PREVIEW_STORAGE_KEY);
3106
- } catch {
3107
- }
3108
- }
3109
- function readSavedDraftPreview(storageKey) {
3110
- if (typeof window === "undefined") return null;
3111
- try {
3112
- const raw = window.sessionStorage.getItem(storageKey);
3113
- if (!raw) return null;
3114
- const parsed = JSON.parse(raw);
3115
- if (!parsed || typeof parsed.id !== "string") return null;
3116
- if (parsed.experienceType !== "tour" && parsed.experienceType !== "onboarding") return null;
3117
- return {
3118
- id: parsed.id,
3119
- experienceType: parsed.experienceType
3120
- };
3121
- } catch {
3122
- return null;
3123
- }
3124
- }
3125
- function readSuppressedDraftPreview() {
3126
- return readSavedDraftPreview(SUPPRESSED_DRAFT_PREVIEW_STORAGE_KEY);
3127
- }
3128
- function persistSuppressedDraftPreview(draft) {
3129
- if (typeof window === "undefined") return;
3130
- try {
3131
- window.sessionStorage.setItem(SUPPRESSED_DRAFT_PREVIEW_STORAGE_KEY, JSON.stringify(draft));
3132
- } catch {
3133
- }
3134
- }
3135
- function clearSuppressedDraftPreview(draft) {
3136
- if (typeof window === "undefined") return;
3137
- try {
3138
- const suppressedDraft = readSuppressedDraftPreview();
3139
- if (draft && suppressedDraft) {
3140
- if (suppressedDraft.id !== draft.id || suppressedDraft.experienceType !== draft.experienceType) {
3141
- return;
3142
- }
3143
- }
3144
- window.sessionStorage.removeItem(SUPPRESSED_DRAFT_PREVIEW_STORAGE_KEY);
3145
- } catch {
3146
- }
3147
- }
3148
- function isSuppressedDraftPreview(draft) {
3149
- const suppressedDraft = readSuppressedDraftPreview();
3150
- return Boolean(
3151
- suppressedDraft && suppressedDraft.id === draft.id && suppressedDraft.experienceType === draft.experienceType
3152
- );
3153
- }
3154
- function persistPreviewSessionSuppression() {
3155
- if (typeof window === "undefined") return;
3156
- try {
3157
- window.sessionStorage.setItem(PREVIEW_SESSION_SUPPRESSION_STORAGE_KEY, "true");
3158
- } catch {
3159
- }
3160
- }
3161
- function readPreviewSessionSuppression() {
3162
- if (typeof window === "undefined") return false;
3163
- try {
3164
- return window.sessionStorage.getItem(PREVIEW_SESSION_SUPPRESSION_STORAGE_KEY) === "true";
3165
- } catch {
3166
- return false;
3167
- }
3211
+ // src/utils/locationSignature.ts
3212
+ function getLocationSignature(locationLike) {
3213
+ if (!locationLike) return "";
3214
+ return `${locationLike.pathname ?? ""}${locationLike.search ?? ""}${locationLike.hash ?? ""}`;
3168
3215
  }
3169
3216
 
3170
3217
  // src/hooks/useTourPlayback.ts
@@ -3799,6 +3846,7 @@ function useTourPlayback({
3799
3846
  showCaptions = true,
3800
3847
  enableAutoDiscovery = true
3801
3848
  }) {
3849
+ const locationSignature = typeof window === "undefined" ? "" : getLocationSignature(window.location);
3802
3850
  const [isActive, setIsActive] = (0, import_react12.useState)(false);
3803
3851
  const [currentStepIndex, setCurrentStepIndex] = (0, import_react12.useState)(0);
3804
3852
  const [totalSteps, setTotalSteps] = (0, import_react12.useState)(0);
@@ -4842,7 +4890,7 @@ function useTourPlayback({
4842
4890
  return () => {
4843
4891
  cancelled = true;
4844
4892
  };
4845
- }, [serverUrl, toursApiBase, disabled, websiteId, experienceType, enableAutoDiscovery]);
4893
+ }, [serverUrl, toursApiBase, disabled, websiteId, experienceType, enableAutoDiscovery, locationSignature]);
4846
4894
  (0, import_react12.useEffect)(() => {
4847
4895
  if (!shouldRunTourAutoDiscovery({
4848
4896
  enableAutoDiscovery,
@@ -4889,7 +4937,7 @@ function useTourPlayback({
4889
4937
  cancelled = true;
4890
4938
  clearTimeout(timer);
4891
4939
  };
4892
- }, [websiteId, serverUrl, toursApiBase, disabled, experienceType, userProfile?.userId, userProfile?.type, userProfile?.isNewUser, enableAutoDiscovery]);
4940
+ }, [websiteId, serverUrl, toursApiBase, disabled, experienceType, userProfile?.userId, userProfile?.type, userProfile?.isNewUser, enableAutoDiscovery, locationSignature]);
4893
4941
  (0, import_react12.useEffect)(() => {
4894
4942
  if (!disabled || !isActiveRef.current) return;
4895
4943
  stopTour();
@@ -5107,6 +5155,7 @@ function useExperiencePlaybackController({
5107
5155
  showCaptions = true,
5108
5156
  initialExperienceType = "tour"
5109
5157
  }) {
5158
+ const locationSignature = typeof window === "undefined" ? "" : getLocationSignature(window.location);
5110
5159
  const [activeExperienceType, setActiveExperienceType] = (0, import_react13.useState)(initialExperienceType);
5111
5160
  const [startingExperienceType, setStartingExperienceType] = (0, import_react13.useState)(null);
5112
5161
  const [pendingPrompt, setPendingPrompt] = (0, import_react13.useState)(null);
@@ -5302,7 +5351,7 @@ function useExperiencePlaybackController({
5302
5351
  cancelled = true;
5303
5352
  previewDiscoveryInFlightRef.current = false;
5304
5353
  };
5305
- }, [disabled, playback.isActive, queueExperienceStart, serverUrl, startingExperienceType, toursApiBase, websiteId]);
5354
+ }, [disabled, playback.isActive, queueExperienceStart, serverUrl, startingExperienceType, toursApiBase, websiteId, locationSignature]);
5306
5355
  (0, import_react13.useEffect)(() => {
5307
5356
  if (!shouldDiscoverEligibleTours({
5308
5357
  disabled,
@@ -5353,7 +5402,7 @@ function useExperiencePlaybackController({
5353
5402
  cancelled = true;
5354
5403
  clearTimeout(timer);
5355
5404
  };
5356
- }, [disabled, playback.isActive, queueExperienceStart, serverUrl, startingExperienceType, toursApiBase, userProfile, websiteId]);
5405
+ }, [disabled, playback.isActive, queueExperienceStart, serverUrl, startingExperienceType, toursApiBase, userProfile, websiteId, locationSignature]);
5357
5406
  return {
5358
5407
  activeExperienceType,
5359
5408
  startingExperienceType,
@@ -9442,6 +9491,7 @@ function ModelNexChatBubble({
9442
9491
  const setRecordingMode = ctx?.setRecordingMode ?? (() => {
9443
9492
  });
9444
9493
  const devMode = ctx?.devMode ?? false;
9494
+ const authoringMode = ctx?.authoringMode ?? devMode;
9445
9495
  const [recordingTourName, setRecordingTourName] = (0, import_react18.useState)("");
9446
9496
  const [recordingTargetTypes, setRecordingTargetTypes] = (0, import_react18.useState)("admin");
9447
9497
  const [showStopModal, setShowStopModal] = (0, import_react18.useState)(false);
@@ -9570,11 +9620,11 @@ function ModelNexChatBubble({
9570
9620
  }
9571
9621
  }, [ctx]);
9572
9622
  (0, import_react18.useEffect)(() => {
9573
- if (devMode && ctx?.extractedElements.length) {
9623
+ if (authoringMode && ctx?.extractedElements.length) {
9574
9624
  const timer = setTimeout(handleAutoTag, 1e3);
9575
9625
  return () => clearTimeout(timer);
9576
9626
  }
9577
- }, [devMode, handleAutoTag, ctx?.extractedElements.length, window.location.pathname]);
9627
+ }, [authoringMode, handleAutoTag, ctx?.extractedElements.length, window.location.pathname]);
9578
9628
  const onboardingReviewToggle = getReviewModeToggleConfig(onboardingPlayback.playbackState);
9579
9629
  const pendingPrompt = playbackController.pendingPrompt;
9580
9630
  const pendingNotificationType = (onboardingPlayback.pendingTour || tourPlayback.pendingTour)?.notificationType ?? "bubble_card";
@@ -9935,7 +9985,7 @@ function ModelNexChatBubble({
9935
9985
  content: summary || fallbackContent,
9936
9986
  summary: summary ?? void 0,
9937
9987
  nextSteps: nextSteps ?? void 0,
9938
- debug: devMode ? data?.debug ?? void 0 : void 0
9988
+ debug: authoringMode ? data?.debug ?? void 0 : void 0
9939
9989
  }
9940
9990
  ]);
9941
9991
  } catch (err) {
@@ -10223,7 +10273,7 @@ function ModelNexChatBubble({
10223
10273
  children: voice.isMuted ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(VolumeMuteIcon, {}) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(VolumeIcon, {})
10224
10274
  }
10225
10275
  ) }),
10226
- devMode && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { display: "flex", background: "var(--modelnex-bg-secondary, #f4f4f5)", borderRadius: "12px", padding: "2px", gap: "2px", marginRight: "4px" }, children: (!recordingMode || activeRecordingExperienceType === "onboarding") && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Tooltip, { title: recordingMode ? "Stop & Save Workflow" : "Record Workflow", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
10276
+ authoringMode && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { display: "flex", background: "var(--modelnex-bg-secondary, #f4f4f5)", borderRadius: "12px", padding: "2px", gap: "2px", marginRight: "4px" }, children: (!recordingMode || activeRecordingExperienceType === "onboarding") && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Tooltip, { title: recordingMode ? "Stop & Save Workflow" : "Record Workflow", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
10227
10277
  "button",
10228
10278
  {
10229
10279
  onClick: () => {
@@ -10979,7 +11029,7 @@ function ModelNexChatBubble({
10979
11029
  )
10980
11030
  }
10981
11031
  ),
10982
- msg.role === "assistant" && devMode && msg.debug && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(AgentTraces, { debug: msg.debug, command: messages[i - 1]?.content ?? "" })
11032
+ msg.role === "assistant" && authoringMode && msg.debug && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(AgentTraces, { debug: msg.debug, command: messages[i - 1]?.content ?? "" })
10983
11033
  ] }, i)),
10984
11034
  loading && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { display: "flex", justifyContent: "flex-start" }, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
10985
11035
  "div",
@@ -11980,7 +12030,9 @@ var ModelNexProvider = ({
11980
12030
  const [actions, setActions] = (0, import_react21.useState)(/* @__PURE__ */ new Map());
11981
12031
  const [validatedBrowserDevMode, setValidatedBrowserDevMode] = (0, import_react21.useState)(false);
11982
12032
  const [resolvedDevModeKey, setResolvedDevModeKey] = (0, import_react21.useState)(() => resolveInjectedDevModeKey());
12033
+ const [previewRuntimeMode, setPreviewRuntimeMode] = (0, import_react21.useState)(() => hasDraftPreviewModeSignal());
11983
12034
  (0, import_react21.useEffect)(() => observeInjectedDevModeKey(setResolvedDevModeKey), []);
12035
+ (0, import_react21.useEffect)(() => observeDraftPreviewModeSignal(setPreviewRuntimeMode), []);
11984
12036
  (0, import_react21.useEffect)(() => {
11985
12037
  let cancelled = false;
11986
12038
  if (!websiteId || !resolvedDevModeKey) {
@@ -11997,7 +12049,7 @@ var ModelNexProvider = ({
11997
12049
  cancelled = true;
11998
12050
  };
11999
12051
  }, [resolvedDevModeKey, serverUrl, websiteId]);
12000
- const effectiveDevMode = validatedBrowserDevMode;
12052
+ const effectiveDevMode = validatedBrowserDevMode || previewRuntimeMode;
12001
12053
  const registerAction = (0, import_react21.useCallback)((action) => {
12002
12054
  setActions((prev) => {
12003
12055
  const next = new Map(prev);
@@ -12094,9 +12146,10 @@ var ModelNexProvider = ({
12094
12146
  voiceMuted,
12095
12147
  setVoiceMuted,
12096
12148
  socketId,
12097
- devMode: effectiveDevMode
12149
+ devMode: effectiveDevMode,
12150
+ authoringMode: validatedBrowserDevMode
12098
12151
  }),
12099
- [serverUrl, commandUrl, registerAction, unregisterAction, activeAgentActions, stagingFields, highlightActions, studioMode, recordingMode, extractedElements, tagStore, chatMessages, websiteId, userProfile?.userId, userProfile?.type, userProfile?.isNewUser, toursApiBase, voiceMuted, socketId, effectiveDevMode]
12152
+ [serverUrl, commandUrl, registerAction, unregisterAction, activeAgentActions, stagingFields, highlightActions, studioMode, recordingMode, extractedElements, tagStore, chatMessages, websiteId, userProfile?.userId, userProfile?.type, userProfile?.isNewUser, toursApiBase, voiceMuted, socketId, effectiveDevMode, validatedBrowserDevMode]
12100
12153
  );
12101
12154
  return import_react21.default.createElement(
12102
12155
  ModelNexContext.Provider,
@@ -12127,11 +12180,13 @@ var ModelNexProvider = ({
12127
12180
  getPreviewQueryParamName,
12128
12181
  getRecordingDraftActionLabel,
12129
12182
  getRecordingDraftStatusMessage,
12183
+ hasDraftPreviewModeSignal,
12130
12184
  inferOnboardingMetadataForStep,
12131
12185
  isAskDrivenInputStepType,
12132
12186
  isInteractiveInputStepType,
12133
12187
  isManualOnboardingStep,
12134
12188
  isRecordingDraftGenerating,
12189
+ observeDraftPreviewModeSignal,
12135
12190
  persistActiveDraftPreview,
12136
12191
  readActiveDraftPreview,
12137
12192
  shouldPromptForPreviewStart,
package/dist/index.mjs CHANGED
@@ -2709,6 +2709,159 @@ function clearPersistedRecordingSession() {
2709
2709
  }
2710
2710
  }
2711
2711
 
2712
+ // src/utils/draftPreview.ts
2713
+ var ACTIVE_DRAFT_PREVIEW_STORAGE_KEY = "modelnex:active-draft-preview";
2714
+ var PREVIEW_SESSION_SUPPRESSION_STORAGE_KEY = "modelnex:preview-session-suppressed";
2715
+ var SUPPRESSED_DRAFT_PREVIEW_STORAGE_KEY = "modelnex:suppressed-draft-preview";
2716
+ function getPreviewQueryParamName(experienceType) {
2717
+ return experienceType === "onboarding" ? "modelnex_test_workflow" : "modelnex_test_tour";
2718
+ }
2719
+ function buildDraftPreviewUrl(currentUrl, draft) {
2720
+ const url = new URL(currentUrl);
2721
+ url.searchParams.delete("modelnex_test_tour");
2722
+ url.searchParams.delete("modelnex_test_onboarding");
2723
+ url.searchParams.delete("modelnex_test_workflow");
2724
+ url.searchParams.set(getPreviewQueryParamName(draft.experienceType), draft.id);
2725
+ return url.toString();
2726
+ }
2727
+ function shouldPromptForPreviewStart(notificationType, _source) {
2728
+ const normalizedNotificationType = notificationType ?? "bubble_card";
2729
+ return normalizedNotificationType === "modal";
2730
+ }
2731
+ function hasDraftPreviewModeSignal() {
2732
+ if (typeof window === "undefined") return false;
2733
+ try {
2734
+ const params = new URLSearchParams(window.location.search);
2735
+ if (params.has("modelnex_test_tour") || params.has("modelnex_test_workflow") || params.has("modelnex_test_onboarding")) {
2736
+ return true;
2737
+ }
2738
+ } catch {
2739
+ }
2740
+ return readActiveDraftPreview() !== null;
2741
+ }
2742
+ function observeDraftPreviewModeSignal(listener, options) {
2743
+ if (typeof window === "undefined") return () => {
2744
+ };
2745
+ let currentValue = hasDraftPreviewModeSignal();
2746
+ const pollIntervalMs = options?.pollIntervalMs ?? 500;
2747
+ const syncPreviewModeSignal = () => {
2748
+ const nextValue = hasDraftPreviewModeSignal();
2749
+ if (nextValue === currentValue) return;
2750
+ currentValue = nextValue;
2751
+ listener(nextValue);
2752
+ };
2753
+ const intervalId = window.setInterval(syncPreviewModeSignal, pollIntervalMs);
2754
+ window.addEventListener("focus", syncPreviewModeSignal);
2755
+ window.addEventListener("pageshow", syncPreviewModeSignal);
2756
+ window.addEventListener("popstate", syncPreviewModeSignal);
2757
+ if (typeof document !== "undefined") {
2758
+ document.addEventListener("visibilitychange", syncPreviewModeSignal);
2759
+ }
2760
+ return () => {
2761
+ window.clearInterval(intervalId);
2762
+ window.removeEventListener("focus", syncPreviewModeSignal);
2763
+ window.removeEventListener("pageshow", syncPreviewModeSignal);
2764
+ window.removeEventListener("popstate", syncPreviewModeSignal);
2765
+ if (typeof document !== "undefined") {
2766
+ document.removeEventListener("visibilitychange", syncPreviewModeSignal);
2767
+ }
2768
+ };
2769
+ }
2770
+ function persistActiveDraftPreview(draft) {
2771
+ if (typeof window === "undefined") return;
2772
+ try {
2773
+ window.sessionStorage.setItem(ACTIVE_DRAFT_PREVIEW_STORAGE_KEY, JSON.stringify(draft));
2774
+ } catch {
2775
+ }
2776
+ }
2777
+ function readActiveDraftPreview() {
2778
+ if (typeof window === "undefined") return null;
2779
+ try {
2780
+ const raw = window.sessionStorage.getItem(ACTIVE_DRAFT_PREVIEW_STORAGE_KEY);
2781
+ if (!raw) return null;
2782
+ const parsed = JSON.parse(raw);
2783
+ if (!parsed || typeof parsed.id !== "string") return null;
2784
+ if (parsed.experienceType !== "tour" && parsed.experienceType !== "onboarding") return null;
2785
+ return {
2786
+ id: parsed.id,
2787
+ experienceType: parsed.experienceType
2788
+ };
2789
+ } catch {
2790
+ return null;
2791
+ }
2792
+ }
2793
+ function clearActiveDraftPreview(experienceType) {
2794
+ if (typeof window === "undefined") return;
2795
+ try {
2796
+ const activePreview = readActiveDraftPreview();
2797
+ if (experienceType && activePreview && activePreview.experienceType !== experienceType) {
2798
+ return;
2799
+ }
2800
+ window.sessionStorage.removeItem(ACTIVE_DRAFT_PREVIEW_STORAGE_KEY);
2801
+ } catch {
2802
+ }
2803
+ }
2804
+ function readSavedDraftPreview(storageKey) {
2805
+ if (typeof window === "undefined") return null;
2806
+ try {
2807
+ const raw = window.sessionStorage.getItem(storageKey);
2808
+ if (!raw) return null;
2809
+ const parsed = JSON.parse(raw);
2810
+ if (!parsed || typeof parsed.id !== "string") return null;
2811
+ if (parsed.experienceType !== "tour" && parsed.experienceType !== "onboarding") return null;
2812
+ return {
2813
+ id: parsed.id,
2814
+ experienceType: parsed.experienceType
2815
+ };
2816
+ } catch {
2817
+ return null;
2818
+ }
2819
+ }
2820
+ function readSuppressedDraftPreview() {
2821
+ return readSavedDraftPreview(SUPPRESSED_DRAFT_PREVIEW_STORAGE_KEY);
2822
+ }
2823
+ function persistSuppressedDraftPreview(draft) {
2824
+ if (typeof window === "undefined") return;
2825
+ try {
2826
+ window.sessionStorage.setItem(SUPPRESSED_DRAFT_PREVIEW_STORAGE_KEY, JSON.stringify(draft));
2827
+ } catch {
2828
+ }
2829
+ }
2830
+ function clearSuppressedDraftPreview(draft) {
2831
+ if (typeof window === "undefined") return;
2832
+ try {
2833
+ const suppressedDraft = readSuppressedDraftPreview();
2834
+ if (draft && suppressedDraft) {
2835
+ if (suppressedDraft.id !== draft.id || suppressedDraft.experienceType !== draft.experienceType) {
2836
+ return;
2837
+ }
2838
+ }
2839
+ window.sessionStorage.removeItem(SUPPRESSED_DRAFT_PREVIEW_STORAGE_KEY);
2840
+ } catch {
2841
+ }
2842
+ }
2843
+ function isSuppressedDraftPreview(draft) {
2844
+ const suppressedDraft = readSuppressedDraftPreview();
2845
+ return Boolean(
2846
+ suppressedDraft && suppressedDraft.id === draft.id && suppressedDraft.experienceType === draft.experienceType
2847
+ );
2848
+ }
2849
+ function persistPreviewSessionSuppression() {
2850
+ if (typeof window === "undefined") return;
2851
+ try {
2852
+ window.sessionStorage.setItem(PREVIEW_SESSION_SUPPRESSION_STORAGE_KEY, "true");
2853
+ } catch {
2854
+ }
2855
+ }
2856
+ function readPreviewSessionSuppression() {
2857
+ if (typeof window === "undefined") return false;
2858
+ try {
2859
+ return window.sessionStorage.getItem(PREVIEW_SESSION_SUPPRESSION_STORAGE_KEY) === "true";
2860
+ } catch {
2861
+ return false;
2862
+ }
2863
+ }
2864
+
2712
2865
  // src/hooks/useRunCommand.ts
2713
2866
  import { useCallback as useCallback5, useContext as useContext2 } from "react";
2714
2867
  function searchTaggedElementsForQuery(store, query, limit = 8) {
@@ -2844,118 +2997,10 @@ import { createPortal, flushSync } from "react-dom";
2844
2997
  // src/hooks/useExperiencePlaybackController.ts
2845
2998
  import { useCallback as useCallback8, useEffect as useEffect12, useRef as useRef9, useState as useState8 } from "react";
2846
2999
 
2847
- // src/utils/draftPreview.ts
2848
- var ACTIVE_DRAFT_PREVIEW_STORAGE_KEY = "modelnex:active-draft-preview";
2849
- var PREVIEW_SESSION_SUPPRESSION_STORAGE_KEY = "modelnex:preview-session-suppressed";
2850
- var SUPPRESSED_DRAFT_PREVIEW_STORAGE_KEY = "modelnex:suppressed-draft-preview";
2851
- function getPreviewQueryParamName(experienceType) {
2852
- return experienceType === "onboarding" ? "modelnex_test_workflow" : "modelnex_test_tour";
2853
- }
2854
- function buildDraftPreviewUrl(currentUrl, draft) {
2855
- const url = new URL(currentUrl);
2856
- url.searchParams.delete("modelnex_test_tour");
2857
- url.searchParams.delete("modelnex_test_onboarding");
2858
- url.searchParams.delete("modelnex_test_workflow");
2859
- url.searchParams.set(getPreviewQueryParamName(draft.experienceType), draft.id);
2860
- return url.toString();
2861
- }
2862
- function shouldPromptForPreviewStart(notificationType, _source) {
2863
- const normalizedNotificationType = notificationType ?? "bubble_card";
2864
- return normalizedNotificationType === "modal";
2865
- }
2866
- function persistActiveDraftPreview(draft) {
2867
- if (typeof window === "undefined") return;
2868
- try {
2869
- window.sessionStorage.setItem(ACTIVE_DRAFT_PREVIEW_STORAGE_KEY, JSON.stringify(draft));
2870
- } catch {
2871
- }
2872
- }
2873
- function readActiveDraftPreview() {
2874
- if (typeof window === "undefined") return null;
2875
- try {
2876
- const raw = window.sessionStorage.getItem(ACTIVE_DRAFT_PREVIEW_STORAGE_KEY);
2877
- if (!raw) return null;
2878
- const parsed = JSON.parse(raw);
2879
- if (!parsed || typeof parsed.id !== "string") return null;
2880
- if (parsed.experienceType !== "tour" && parsed.experienceType !== "onboarding") return null;
2881
- return {
2882
- id: parsed.id,
2883
- experienceType: parsed.experienceType
2884
- };
2885
- } catch {
2886
- return null;
2887
- }
2888
- }
2889
- function clearActiveDraftPreview(experienceType) {
2890
- if (typeof window === "undefined") return;
2891
- try {
2892
- const activePreview = readActiveDraftPreview();
2893
- if (experienceType && activePreview && activePreview.experienceType !== experienceType) {
2894
- return;
2895
- }
2896
- window.sessionStorage.removeItem(ACTIVE_DRAFT_PREVIEW_STORAGE_KEY);
2897
- } catch {
2898
- }
2899
- }
2900
- function readSavedDraftPreview(storageKey) {
2901
- if (typeof window === "undefined") return null;
2902
- try {
2903
- const raw = window.sessionStorage.getItem(storageKey);
2904
- if (!raw) return null;
2905
- const parsed = JSON.parse(raw);
2906
- if (!parsed || typeof parsed.id !== "string") return null;
2907
- if (parsed.experienceType !== "tour" && parsed.experienceType !== "onboarding") return null;
2908
- return {
2909
- id: parsed.id,
2910
- experienceType: parsed.experienceType
2911
- };
2912
- } catch {
2913
- return null;
2914
- }
2915
- }
2916
- function readSuppressedDraftPreview() {
2917
- return readSavedDraftPreview(SUPPRESSED_DRAFT_PREVIEW_STORAGE_KEY);
2918
- }
2919
- function persistSuppressedDraftPreview(draft) {
2920
- if (typeof window === "undefined") return;
2921
- try {
2922
- window.sessionStorage.setItem(SUPPRESSED_DRAFT_PREVIEW_STORAGE_KEY, JSON.stringify(draft));
2923
- } catch {
2924
- }
2925
- }
2926
- function clearSuppressedDraftPreview(draft) {
2927
- if (typeof window === "undefined") return;
2928
- try {
2929
- const suppressedDraft = readSuppressedDraftPreview();
2930
- if (draft && suppressedDraft) {
2931
- if (suppressedDraft.id !== draft.id || suppressedDraft.experienceType !== draft.experienceType) {
2932
- return;
2933
- }
2934
- }
2935
- window.sessionStorage.removeItem(SUPPRESSED_DRAFT_PREVIEW_STORAGE_KEY);
2936
- } catch {
2937
- }
2938
- }
2939
- function isSuppressedDraftPreview(draft) {
2940
- const suppressedDraft = readSuppressedDraftPreview();
2941
- return Boolean(
2942
- suppressedDraft && suppressedDraft.id === draft.id && suppressedDraft.experienceType === draft.experienceType
2943
- );
2944
- }
2945
- function persistPreviewSessionSuppression() {
2946
- if (typeof window === "undefined") return;
2947
- try {
2948
- window.sessionStorage.setItem(PREVIEW_SESSION_SUPPRESSION_STORAGE_KEY, "true");
2949
- } catch {
2950
- }
2951
- }
2952
- function readPreviewSessionSuppression() {
2953
- if (typeof window === "undefined") return false;
2954
- try {
2955
- return window.sessionStorage.getItem(PREVIEW_SESSION_SUPPRESSION_STORAGE_KEY) === "true";
2956
- } catch {
2957
- return false;
2958
- }
3000
+ // src/utils/locationSignature.ts
3001
+ function getLocationSignature(locationLike) {
3002
+ if (!locationLike) return "";
3003
+ return `${locationLike.pathname ?? ""}${locationLike.search ?? ""}${locationLike.hash ?? ""}`;
2959
3004
  }
2960
3005
 
2961
3006
  // src/hooks/useTourPlayback.ts
@@ -3590,6 +3635,7 @@ function useTourPlayback({
3590
3635
  showCaptions = true,
3591
3636
  enableAutoDiscovery = true
3592
3637
  }) {
3638
+ const locationSignature = typeof window === "undefined" ? "" : getLocationSignature(window.location);
3593
3639
  const [isActive, setIsActive] = useState7(false);
3594
3640
  const [currentStepIndex, setCurrentStepIndex] = useState7(0);
3595
3641
  const [totalSteps, setTotalSteps] = useState7(0);
@@ -4633,7 +4679,7 @@ function useTourPlayback({
4633
4679
  return () => {
4634
4680
  cancelled = true;
4635
4681
  };
4636
- }, [serverUrl, toursApiBase, disabled, websiteId, experienceType, enableAutoDiscovery]);
4682
+ }, [serverUrl, toursApiBase, disabled, websiteId, experienceType, enableAutoDiscovery, locationSignature]);
4637
4683
  useEffect11(() => {
4638
4684
  if (!shouldRunTourAutoDiscovery({
4639
4685
  enableAutoDiscovery,
@@ -4680,7 +4726,7 @@ function useTourPlayback({
4680
4726
  cancelled = true;
4681
4727
  clearTimeout(timer);
4682
4728
  };
4683
- }, [websiteId, serverUrl, toursApiBase, disabled, experienceType, userProfile?.userId, userProfile?.type, userProfile?.isNewUser, enableAutoDiscovery]);
4729
+ }, [websiteId, serverUrl, toursApiBase, disabled, experienceType, userProfile?.userId, userProfile?.type, userProfile?.isNewUser, enableAutoDiscovery, locationSignature]);
4684
4730
  useEffect11(() => {
4685
4731
  if (!disabled || !isActiveRef.current) return;
4686
4732
  stopTour();
@@ -4898,6 +4944,7 @@ function useExperiencePlaybackController({
4898
4944
  showCaptions = true,
4899
4945
  initialExperienceType = "tour"
4900
4946
  }) {
4947
+ const locationSignature = typeof window === "undefined" ? "" : getLocationSignature(window.location);
4901
4948
  const [activeExperienceType, setActiveExperienceType] = useState8(initialExperienceType);
4902
4949
  const [startingExperienceType, setStartingExperienceType] = useState8(null);
4903
4950
  const [pendingPrompt, setPendingPrompt] = useState8(null);
@@ -5093,7 +5140,7 @@ function useExperiencePlaybackController({
5093
5140
  cancelled = true;
5094
5141
  previewDiscoveryInFlightRef.current = false;
5095
5142
  };
5096
- }, [disabled, playback.isActive, queueExperienceStart, serverUrl, startingExperienceType, toursApiBase, websiteId]);
5143
+ }, [disabled, playback.isActive, queueExperienceStart, serverUrl, startingExperienceType, toursApiBase, websiteId, locationSignature]);
5097
5144
  useEffect12(() => {
5098
5145
  if (!shouldDiscoverEligibleTours({
5099
5146
  disabled,
@@ -5144,7 +5191,7 @@ function useExperiencePlaybackController({
5144
5191
  cancelled = true;
5145
5192
  clearTimeout(timer);
5146
5193
  };
5147
- }, [disabled, playback.isActive, queueExperienceStart, serverUrl, startingExperienceType, toursApiBase, userProfile, websiteId]);
5194
+ }, [disabled, playback.isActive, queueExperienceStart, serverUrl, startingExperienceType, toursApiBase, userProfile, websiteId, locationSignature]);
5148
5195
  return {
5149
5196
  activeExperienceType,
5150
5197
  startingExperienceType,
@@ -9232,6 +9279,7 @@ function ModelNexChatBubble({
9232
9279
  const setRecordingMode = ctx?.setRecordingMode ?? (() => {
9233
9280
  });
9234
9281
  const devMode = ctx?.devMode ?? false;
9282
+ const authoringMode = ctx?.authoringMode ?? devMode;
9235
9283
  const [recordingTourName, setRecordingTourName] = useState13("");
9236
9284
  const [recordingTargetTypes, setRecordingTargetTypes] = useState13("admin");
9237
9285
  const [showStopModal, setShowStopModal] = useState13(false);
@@ -9360,11 +9408,11 @@ function ModelNexChatBubble({
9360
9408
  }
9361
9409
  }, [ctx]);
9362
9410
  useEffect17(() => {
9363
- if (devMode && ctx?.extractedElements.length) {
9411
+ if (authoringMode && ctx?.extractedElements.length) {
9364
9412
  const timer = setTimeout(handleAutoTag, 1e3);
9365
9413
  return () => clearTimeout(timer);
9366
9414
  }
9367
- }, [devMode, handleAutoTag, ctx?.extractedElements.length, window.location.pathname]);
9415
+ }, [authoringMode, handleAutoTag, ctx?.extractedElements.length, window.location.pathname]);
9368
9416
  const onboardingReviewToggle = getReviewModeToggleConfig(onboardingPlayback.playbackState);
9369
9417
  const pendingPrompt = playbackController.pendingPrompt;
9370
9418
  const pendingNotificationType = (onboardingPlayback.pendingTour || tourPlayback.pendingTour)?.notificationType ?? "bubble_card";
@@ -9725,7 +9773,7 @@ function ModelNexChatBubble({
9725
9773
  content: summary || fallbackContent,
9726
9774
  summary: summary ?? void 0,
9727
9775
  nextSteps: nextSteps ?? void 0,
9728
- debug: devMode ? data?.debug ?? void 0 : void 0
9776
+ debug: authoringMode ? data?.debug ?? void 0 : void 0
9729
9777
  }
9730
9778
  ]);
9731
9779
  } catch (err) {
@@ -10013,7 +10061,7 @@ function ModelNexChatBubble({
10013
10061
  children: voice.isMuted ? /* @__PURE__ */ jsx4(VolumeMuteIcon, {}) : /* @__PURE__ */ jsx4(VolumeIcon, {})
10014
10062
  }
10015
10063
  ) }),
10016
- devMode && /* @__PURE__ */ jsx4("div", { style: { display: "flex", background: "var(--modelnex-bg-secondary, #f4f4f5)", borderRadius: "12px", padding: "2px", gap: "2px", marginRight: "4px" }, children: (!recordingMode || activeRecordingExperienceType === "onboarding") && /* @__PURE__ */ jsx4(Tooltip, { title: recordingMode ? "Stop & Save Workflow" : "Record Workflow", children: /* @__PURE__ */ jsx4(
10064
+ authoringMode && /* @__PURE__ */ jsx4("div", { style: { display: "flex", background: "var(--modelnex-bg-secondary, #f4f4f5)", borderRadius: "12px", padding: "2px", gap: "2px", marginRight: "4px" }, children: (!recordingMode || activeRecordingExperienceType === "onboarding") && /* @__PURE__ */ jsx4(Tooltip, { title: recordingMode ? "Stop & Save Workflow" : "Record Workflow", children: /* @__PURE__ */ jsx4(
10017
10065
  "button",
10018
10066
  {
10019
10067
  onClick: () => {
@@ -10769,7 +10817,7 @@ function ModelNexChatBubble({
10769
10817
  )
10770
10818
  }
10771
10819
  ),
10772
- msg.role === "assistant" && devMode && msg.debug && /* @__PURE__ */ jsx4(AgentTraces, { debug: msg.debug, command: messages[i - 1]?.content ?? "" })
10820
+ msg.role === "assistant" && authoringMode && msg.debug && /* @__PURE__ */ jsx4(AgentTraces, { debug: msg.debug, command: messages[i - 1]?.content ?? "" })
10773
10821
  ] }, i)),
10774
10822
  loading && /* @__PURE__ */ jsx4("div", { style: { display: "flex", justifyContent: "flex-start" }, children: /* @__PURE__ */ jsxs3(
10775
10823
  "div",
@@ -11770,7 +11818,9 @@ var ModelNexProvider = ({
11770
11818
  const [actions, setActions] = useState15(/* @__PURE__ */ new Map());
11771
11819
  const [validatedBrowserDevMode, setValidatedBrowserDevMode] = useState15(false);
11772
11820
  const [resolvedDevModeKey, setResolvedDevModeKey] = useState15(() => resolveInjectedDevModeKey());
11821
+ const [previewRuntimeMode, setPreviewRuntimeMode] = useState15(() => hasDraftPreviewModeSignal());
11773
11822
  useEffect19(() => observeInjectedDevModeKey(setResolvedDevModeKey), []);
11823
+ useEffect19(() => observeDraftPreviewModeSignal(setPreviewRuntimeMode), []);
11774
11824
  useEffect19(() => {
11775
11825
  let cancelled = false;
11776
11826
  if (!websiteId || !resolvedDevModeKey) {
@@ -11787,7 +11837,7 @@ var ModelNexProvider = ({
11787
11837
  cancelled = true;
11788
11838
  };
11789
11839
  }, [resolvedDevModeKey, serverUrl, websiteId]);
11790
- const effectiveDevMode = validatedBrowserDevMode;
11840
+ const effectiveDevMode = validatedBrowserDevMode || previewRuntimeMode;
11791
11841
  const registerAction = useCallback14((action) => {
11792
11842
  setActions((prev) => {
11793
11843
  const next = new Map(prev);
@@ -11884,9 +11934,10 @@ var ModelNexProvider = ({
11884
11934
  voiceMuted,
11885
11935
  setVoiceMuted,
11886
11936
  socketId,
11887
- devMode: effectiveDevMode
11937
+ devMode: effectiveDevMode,
11938
+ authoringMode: validatedBrowserDevMode
11888
11939
  }),
11889
- [serverUrl, commandUrl, registerAction, unregisterAction, activeAgentActions, stagingFields, highlightActions, studioMode, recordingMode, extractedElements, tagStore, chatMessages, websiteId, userProfile?.userId, userProfile?.type, userProfile?.isNewUser, toursApiBase, voiceMuted, socketId, effectiveDevMode]
11940
+ [serverUrl, commandUrl, registerAction, unregisterAction, activeAgentActions, stagingFields, highlightActions, studioMode, recordingMode, extractedElements, tagStore, chatMessages, websiteId, userProfile?.userId, userProfile?.type, userProfile?.isNewUser, toursApiBase, voiceMuted, socketId, effectiveDevMode, validatedBrowserDevMode]
11890
11941
  );
11891
11942
  return React8.createElement(
11892
11943
  ModelNexContext.Provider,
@@ -11916,11 +11967,13 @@ export {
11916
11967
  getPreviewQueryParamName,
11917
11968
  getRecordingDraftActionLabel,
11918
11969
  getRecordingDraftStatusMessage,
11970
+ hasDraftPreviewModeSignal,
11919
11971
  inferOnboardingMetadataForStep,
11920
11972
  isAskDrivenInputStepType,
11921
11973
  isInteractiveInputStepType,
11922
11974
  isManualOnboardingStep,
11923
11975
  isRecordingDraftGenerating,
11976
+ observeDraftPreviewModeSignal,
11924
11977
  persistActiveDraftPreview,
11925
11978
  readActiveDraftPreview,
11926
11979
  shouldPromptForPreviewStart,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@modelnex/sdk",
3
- "version": "0.5.35",
3
+ "version": "0.5.37",
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",