@sailfish-ai/recorder 1.8.10 → 1.8.12-alpha-2

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/recording.js CHANGED
@@ -155,8 +155,8 @@ export function initializeConsolePlugin(consoleRecordSettings, sessionId) {
155
155
  }
156
156
  export async function initializeRecording(captureSettings, // TODO - Sibyl post-launch - replace type
157
157
  // networkRecordSettings: NetworkRecordOptions,
158
- backendApi, apiKey, sessionId) {
159
- const webSocket = initializeWebSocket(backendApi, apiKey, sessionId);
158
+ backendApi, apiKey, sessionId, envValue) {
159
+ const webSocket = initializeWebSocket(backendApi, apiKey, sessionId, envValue);
160
160
  try {
161
161
  record({
162
162
  emit(event) {
package/dist/session.js CHANGED
@@ -1,12 +1,49 @@
1
1
  import { v4 as uuidv4 } from "uuid";
2
2
  import { HAS_WINDOW } from "./runtimeEnv";
3
- // Storing the sailfishSessionId in window.name, as window.name retains its value after a page refresh
4
- // but resets when a new tab (including a duplicated tab) is opened.
3
+ // Hybrid approach: use window.name as a temporary "refresh flag" and sessionStorage for persistence
4
+ // - window.name flag is removed immediately after reading, preserving customer's data
5
+ // - sessionStorage stores the actual session ID
6
+ // - beforeunload sets a flag in window.name to detect page refresh vs duplicate tab
7
+ const SESSION_ID_KEY = "sailfishSessionId";
8
+ const REFRESH_FLAG = "__sailfish_refresh__";
9
+ // Cache the resolved session ID to avoid regenerating on multiple calls
10
+ let resolvedSessionId = null;
5
11
  export function getOrSetSessionId() {
6
12
  if (!HAS_WINDOW)
7
13
  return uuidv4();
8
- if (!window.name) {
9
- window.name = uuidv4();
14
+ // Return cached session ID if already resolved
15
+ if (resolvedSessionId) {
16
+ return resolvedSessionId;
10
17
  }
11
- return window.name;
18
+ // Check if window.name contains our refresh flag
19
+ const isRefresh = window.name.startsWith(REFRESH_FLAG);
20
+ // Remove our flag and restore customer's original window.name
21
+ if (isRefresh) {
22
+ window.name = window.name.substring(REFRESH_FLAG.length);
23
+ }
24
+ if (isRefresh) {
25
+ // Page refresh - reuse existing session ID from sessionStorage
26
+ const existingSessionId = window.sessionStorage.getItem(SESSION_ID_KEY);
27
+ if (existingSessionId) {
28
+ resolvedSessionId = existingSessionId;
29
+ return existingSessionId;
30
+ }
31
+ }
32
+ // New tab or duplicate tab - generate new session ID
33
+ const sessionId = uuidv4();
34
+ resolvedSessionId = sessionId;
35
+ try {
36
+ window.sessionStorage.setItem(SESSION_ID_KEY, sessionId);
37
+ }
38
+ catch (error) {
39
+ // Ignore storage errors, use in-memory session ID
40
+ }
41
+ return sessionId;
42
+ }
43
+ // Set up beforeunload listener to mark page refresh
44
+ if (HAS_WINDOW) {
45
+ window.addEventListener("beforeunload", () => {
46
+ // Prepend our flag to preserve customer's window.name
47
+ window.name = REFRESH_FLAG + window.name;
48
+ });
12
49
  }
@@ -1,8 +1,9 @@
1
- import { CaptureSettingsResponse, CreateTriageResponse, GraphQLResponse, StartSessionResponse } from "./types";
1
+ import { CaptureSettingsResponse, CreateTriageResponse, FunctionSpanTrackingEnabledResponse, GraphQLResponse, StartSessionResponse } from "./types";
2
2
  export declare function sendGraphQLRequest<T>(operationName: string, query: string, variables: object, retries?: number, // Number of retries before giving up
3
3
  initialBackoff?: number, // Initial backoff in milliseconds
4
4
  backoffFactor?: number): Promise<GraphQLResponse<T>>;
5
5
  export declare function fetchCaptureSettings(apiKey: string, backendApi: string): Promise<GraphQLResponse<CaptureSettingsResponse>>;
6
+ export declare function fetchFunctionSpanTrackingEnabled(apiKey: string, backendApi: string): Promise<GraphQLResponse<FunctionSpanTrackingEnabledResponse>>;
6
7
  export declare function startRecordingSession(apiKey: string, recordingId: string, backendApi: string, serviceIdentifier: string, serviceVersion?: string, mapUuid?: string, gitSha?: string, library?: string, serviceAdditionalMetadata?: Record<string, any>): Promise<GraphQLResponse<StartSessionResponse>>;
7
8
  export declare function sendDomainsToNotPropagateHeaderTo(apiKey: string, domains: string[], backendApi: string): Promise<GraphQLResponse<void>>;
8
9
  export declare function createTriageFromRecorder(apiKey: string, backendApi: string, recordingSessionId: string, timestampStart: string, timestampEnd: string, description?: string): Promise<GraphQLResponse<CreateTriageResponse>>;
@@ -31,6 +31,7 @@ export * from "./graphql";
31
31
  export { openReportIssueModal } from "./inAppReportIssueModal";
32
32
  export * from "./recording";
33
33
  export * from "./sendSailfishMessages";
34
+ export { getOrSetSessionId } from "./session";
34
35
  export * from "./types";
35
36
  export * from "./utils";
36
37
  export * from "./websocket";
@@ -10,4 +10,4 @@ export declare const getUrlAndStoredUuids: () => {
10
10
  export declare function initializeDomContentEvents(sessionId: string): void;
11
11
  export declare function initializeConsolePlugin(consoleRecordSettings: LogRecordOptions, sessionId: string): void;
12
12
  export declare function initializeRecording(captureSettings: any, // TODO - Sibyl post-launch - replace type
13
- backendApi: string, apiKey: string, sessionId: string): Promise<ReconnectingWebSocket>;
13
+ backendApi: string, apiKey: string, sessionId: string, envValue?: string): Promise<ReconnectingWebSocket>;
@@ -46,6 +46,9 @@ export interface GraphQLResponse<T> {
46
46
  export interface CaptureSettingsResponse {
47
47
  captureSettingsFromApiKey: CaptureSettings;
48
48
  }
49
+ export interface FunctionSpanTrackingEnabledResponse {
50
+ isFunctionSpanTrackingEnabledFromApiKey: boolean;
51
+ }
49
52
  export interface StartSessionResponse {
50
53
  startRecordingSession: {
51
54
  id: string;
@@ -1,7 +1,12 @@
1
1
  import ReconnectingWebSocket from "reconnecting-websocket";
2
+ /**
3
+ * Clear stale function span tracking state (called from index.tsx to validate localStorage)
4
+ * This disables tracking and clears localStorage if backend says tracking is not active
5
+ */
6
+ export declare function clearStaleFuncSpanState(): void;
2
7
  export declare function flushBufferedEvents(): Promise<void>;
3
8
  export declare function sendEvent(event: any): void;
4
- export declare function initializeWebSocket(backendApi: string, apiKey: string, sessionId: string): ReconnectingWebSocket;
9
+ export declare function initializeWebSocket(backendApi: string, apiKey: string, sessionId: string, envValue?: string): ReconnectingWebSocket;
5
10
  export declare function sendMessage(message: Record<string, any>): void;
6
11
  /**
7
12
  * Enable function span tracking for this session (e.g., when report issue recording starts)
@@ -17,6 +22,11 @@ export declare function disableFunctionSpanTracking(): void;
17
22
  * Check if function span tracking is currently enabled
18
23
  */
19
24
  export declare function isFunctionSpanTrackingEnabled(): boolean;
25
+ /**
26
+ * Initialize function span tracking state from API response (during page load)
27
+ * This is called before the WebSocket connects to ensure headers are added from the start
28
+ */
29
+ export declare function initializeFunctionSpanTrackingFromApi(isEnabled: boolean): void;
20
30
  /**
21
31
  * Get the current funcspan header name and value
22
32
  * Header constants are defined here but used by HTTP interceptors in index.tsx
package/dist/websocket.js CHANGED
@@ -14,12 +14,24 @@ const FUNCSPAN_HEADER_VALUE = "1-0-5-5-0-1.0";
14
14
  // Tracking configuration type constants (must match backend TrackingConfigurationType enum)
15
15
  const TRACKING_CONFIG_GLOBAL = "global";
16
16
  const TRACKING_CONFIG_PER_SESSION = "per_session";
17
- // localStorage key for persisting global function span tracking state
18
- const FUNCSPAN_GLOBAL_STATE_KEY = "sailfish_funcspan_global_state";
19
17
  let webSocket = null;
20
18
  let isDraining = false;
21
19
  let inFlightFlush = null;
22
20
  let flushIntervalId = null;
21
+ // Function span tracking state (only manages enabled/disabled)
22
+ let funcSpanTrackingEnabled = false;
23
+ let funcSpanTimeoutId = null;
24
+ let funcSpanExpirationTime = null; // Timestamp when tracking should expire (milliseconds)
25
+ let isLocalTrackingMode = false; // True when tracking is enabled locally (Report Issue), not globally
26
+ // Saved global state when switching to local mode
27
+ let savedGlobalTimeoutId = null;
28
+ let savedGlobalExpirationTime = null;
29
+ // LocalStorage key for persisting global function span tracking state
30
+ const FUNCSPAN_STORAGE_KEY = "sailfish_funcspan_global_state";
31
+ /**
32
+ * Save global function span tracking state to localStorage
33
+ * This persists the state across page refreshes
34
+ */
23
35
  function saveGlobalFuncSpanState(enabled, expirationTimestampMs) {
24
36
  try {
25
37
  if (typeof localStorage === "undefined")
@@ -27,73 +39,73 @@ function saveGlobalFuncSpanState(enabled, expirationTimestampMs) {
27
39
  const state = {
28
40
  enabled,
29
41
  expirationTimestampMs,
42
+ savedAt: Date.now()
30
43
  };
31
- localStorage.setItem(FUNCSPAN_GLOBAL_STATE_KEY, JSON.stringify(state));
44
+ localStorage.setItem(FUNCSPAN_STORAGE_KEY, JSON.stringify(state));
32
45
  if (DEBUG) {
33
- console.log(`[Sailfish] Saved global function span state to localStorage:`, state);
46
+ console.log("[Sailfish] Saved funcSpan state to localStorage:", state);
34
47
  }
35
48
  }
36
49
  catch (e) {
37
50
  if (DEBUG) {
38
- console.warn(`[Sailfish] Failed to save global function span state to localStorage:`, e);
51
+ console.warn("[Sailfish] Failed to save funcSpan state to localStorage:", e);
39
52
  }
40
53
  }
41
54
  }
55
+ /**
56
+ * Load global function span tracking state from localStorage
57
+ */
42
58
  function loadGlobalFuncSpanState() {
43
59
  try {
44
60
  if (typeof localStorage === "undefined")
45
61
  return null;
46
- const stored = localStorage.getItem(FUNCSPAN_GLOBAL_STATE_KEY);
62
+ const stored = localStorage.getItem(FUNCSPAN_STORAGE_KEY);
47
63
  if (!stored)
48
64
  return null;
49
65
  const state = JSON.parse(stored);
50
- // Check if the stored state has expired
51
- if (state.enabled && state.expirationTimestampMs) {
52
- const now = Date.now();
53
- if (now >= state.expirationTimestampMs) {
54
- // Expired - clear localStorage and return null
55
- if (DEBUG) {
56
- console.log(`[Sailfish] Stored global function span state has expired, clearing`);
57
- }
58
- localStorage.removeItem(FUNCSPAN_GLOBAL_STATE_KEY);
59
- return null;
60
- }
61
- }
62
66
  if (DEBUG) {
63
- console.log(`[Sailfish] Loaded global function span state from localStorage:`, state);
67
+ console.log("[Sailfish] Loaded funcSpan state from localStorage:", state);
64
68
  }
65
69
  return state;
66
70
  }
67
71
  catch (e) {
68
72
  if (DEBUG) {
69
- console.warn(`[Sailfish] Failed to load global function span state from localStorage:`, e);
73
+ console.warn("[Sailfish] Failed to load funcSpan state from localStorage:", e);
70
74
  }
71
75
  return null;
72
76
  }
73
77
  }
78
+ /**
79
+ * Clear global function span tracking state from localStorage
80
+ */
74
81
  function clearGlobalFuncSpanState() {
75
82
  try {
76
83
  if (typeof localStorage === "undefined")
77
84
  return;
78
- localStorage.removeItem(FUNCSPAN_GLOBAL_STATE_KEY);
85
+ localStorage.removeItem(FUNCSPAN_STORAGE_KEY);
79
86
  if (DEBUG) {
80
- console.log(`[Sailfish] Cleared global function span state from localStorage`);
87
+ console.log("[Sailfish] Cleared funcSpan state from localStorage");
81
88
  }
82
89
  }
83
90
  catch (e) {
84
91
  if (DEBUG) {
85
- console.warn(`[Sailfish] Failed to clear global function span state from localStorage:`, e);
92
+ console.warn("[Sailfish] Failed to clear funcSpan state from localStorage:", e);
86
93
  }
87
94
  }
88
95
  }
89
- // Function span tracking state (only manages enabled/disabled)
90
- let funcSpanTrackingEnabled = false;
91
- let funcSpanTimeoutId = null;
92
- let funcSpanExpirationTime = null; // Timestamp when tracking should expire (milliseconds)
93
- let isLocalTrackingMode = false; // True when tracking is enabled locally (Report Issue), not globally
94
- // Saved global state when switching to local mode
95
- let savedGlobalTimeoutId = null;
96
- let savedGlobalExpirationTime = null;
96
+ /**
97
+ * Clear stale function span tracking state (called from index.tsx to validate localStorage)
98
+ * This disables tracking and clears localStorage if backend says tracking is not active
99
+ */
100
+ export function clearStaleFuncSpanState() {
101
+ funcSpanTrackingEnabled = false;
102
+ funcSpanExpirationTime = null;
103
+ isLocalTrackingMode = false;
104
+ clearGlobalFuncSpanState();
105
+ if (DEBUG) {
106
+ console.log("[Sailfish] Cleared stale function span tracking state (backend validation failed)");
107
+ }
108
+ }
97
109
  // Load persisted global state immediately on module initialization
98
110
  // This ensures headers are added from the very first HTTP request, even before WebSocket connects
99
111
  (() => {
@@ -105,9 +117,34 @@ let savedGlobalExpirationTime = null;
105
117
  if (DEBUG) {
106
118
  console.log(`[Sailfish] Module init: Restored global function span tracking from localStorage:`, {
107
119
  enabled: true,
108
- expirationTimestampMs: funcSpanExpirationTime,
120
+ expirationTime: funcSpanExpirationTime
109
121
  });
110
122
  }
123
+ // Check if tracking has already expired
124
+ if (funcSpanExpirationTime !== null) {
125
+ const now = Date.now();
126
+ if (now >= funcSpanExpirationTime) {
127
+ // Already expired, clear it
128
+ funcSpanTrackingEnabled = false;
129
+ funcSpanExpirationTime = null;
130
+ clearGlobalFuncSpanState();
131
+ if (DEBUG) {
132
+ console.log("[Sailfish] Module init: Persisted tracking already expired, cleared state");
133
+ }
134
+ }
135
+ else {
136
+ // State is still valid, keep it temporarily until WebSocket provides the true state
137
+ if (DEBUG) {
138
+ console.log("[Sailfish] Module init: Function span tracking is active and valid (temporary until WebSocket confirms)");
139
+ }
140
+ }
141
+ }
142
+ else {
143
+ // No expiration time - keep enabled temporarily until WebSocket provides the true state
144
+ if (DEBUG) {
145
+ console.log("[Sailfish] Module init: Function span tracking is active (no expiration, temporary until WebSocket confirms)");
146
+ }
147
+ }
111
148
  }
112
149
  })();
113
150
  function isWebSocketOpen(ws) {
@@ -203,14 +240,15 @@ export function sendEvent(event) {
203
240
  saveEventToIDB(enrichedEvent);
204
241
  }
205
242
  }
206
- export function initializeWebSocket(backendApi, apiKey, sessionId) {
207
- // Note: Global function span tracking state is now loaded at module initialization time
208
- // (see IIFE above) so headers work immediately, even before WebSocket connects.
209
- // The WebSocket "funcSpanTrackingControl" message will update the state if needed.
243
+ export function initializeWebSocket(backendApi, apiKey, sessionId, envValue) {
210
244
  const wsHost = getWebSocketHost(backendApi);
211
245
  const apiProtocol = new URL(backendApi).protocol;
212
246
  const wsScheme = apiProtocol === "https:" ? "wss" : "ws";
213
- const wsUrl = `${wsScheme}://${wsHost}/ws/notify/?apiKey=${apiKey}&sessionId=${sessionId}&sender=JS%2FTS&version=${version}`;
247
+ let wsUrl = `${wsScheme}://${wsHost}/ws/notify/?apiKey=${apiKey}&sessionId=${sessionId}&sender=JS%2FTS&version=${version}`;
248
+ // Append envValue if provided
249
+ if (envValue) {
250
+ wsUrl += `&envValue=${encodeURIComponent(envValue)}`;
251
+ }
214
252
  const options = {
215
253
  connectionTimeout: 30000,
216
254
  };
@@ -289,6 +327,25 @@ export function initializeWebSocket(backendApi, apiKey, sessionId) {
289
327
  if (DEBUG) {
290
328
  console.log(`[Sailfish] GLOBAL function span tracking auto-disabled at server expiration time`);
291
329
  }
330
+ // Notify backend that this client's tracking has expired
331
+ // Backend will update database and broadcast to all other clients
332
+ try {
333
+ if (isWebSocketOpen(webSocket)) {
334
+ webSocket.send(JSON.stringify({
335
+ type: "funcSpanTrackingExpired",
336
+ sessionId: getOrSetSessionId(),
337
+ expiredAt: Date.now(),
338
+ }));
339
+ if (DEBUG) {
340
+ console.log(`[Sailfish] Notified backend that function span tracking expired`);
341
+ }
342
+ }
343
+ }
344
+ catch (e) {
345
+ if (DEBUG) {
346
+ console.warn(`[Sailfish] Failed to notify backend of tracking expiry:`, e);
347
+ }
348
+ }
292
349
  }
293
350
  }, msUntilExpiration);
294
351
  }
@@ -319,6 +376,24 @@ export function initializeWebSocket(backendApi, apiKey, sessionId) {
319
376
  if (DEBUG) {
320
377
  console.log(`[Sailfish] GLOBAL function span tracking auto-disabled after ${timeoutSeconds}s (legacy)`);
321
378
  }
379
+ // Notify backend that this client's tracking has expired
380
+ try {
381
+ if (isWebSocketOpen(webSocket)) {
382
+ webSocket.send(JSON.stringify({
383
+ type: "funcSpanTrackingExpired",
384
+ sessionId: getOrSetSessionId(),
385
+ expiredAt: Date.now(),
386
+ }));
387
+ if (DEBUG) {
388
+ console.log(`[Sailfish] Notified backend that function span tracking expired (legacy timeout)`);
389
+ }
390
+ }
391
+ }
392
+ catch (e) {
393
+ if (DEBUG) {
394
+ console.warn(`[Sailfish] Failed to notify backend of tracking expiry:`, e);
395
+ }
396
+ }
322
397
  }
323
398
  }, timeoutSeconds * 1000);
324
399
  }
@@ -364,7 +439,12 @@ export function sendMessage(message) {
364
439
  ...message,
365
440
  app_url: message?.app_url ?? window?.location?.href,
366
441
  });
367
- if (isWebSocketOpen(webSocket)) {
442
+ // Check isDraining to prevent out-of-order delivery during reconnection
443
+ // When draining buffered events, queue new messages to maintain order
444
+ if (isDraining || !isWebSocketOpen(webSocket)) {
445
+ saveNotifyMessageToIDB(msg);
446
+ }
447
+ else {
368
448
  try {
369
449
  webSocket.send(msg);
370
450
  }
@@ -372,9 +452,6 @@ export function sendMessage(message) {
372
452
  saveNotifyMessageToIDB(msg);
373
453
  }
374
454
  }
375
- else {
376
- saveNotifyMessageToIDB(msg);
377
- }
378
455
  }
379
456
  function getWebSocketHost(url) {
380
457
  const parser = document.createElement("a");
@@ -389,18 +466,14 @@ export function enableFunctionSpanTracking() {
389
466
  if (DEBUG) {
390
467
  console.log("[Sailfish] enableFunctionSpanTracking() called - Report Issue recording started (LOCAL MODE)");
391
468
  }
392
- // If global tracking was already active, save its state so we can restore it later
393
- if (funcSpanTrackingEnabled && !isLocalTrackingMode) {
394
- savedGlobalTimeoutId = funcSpanTimeoutId;
395
- savedGlobalExpirationTime = funcSpanExpirationTime;
396
- if (DEBUG) {
397
- console.log("[Sailfish] Saved global tracking state while switching to local mode");
398
- }
399
- }
400
469
  funcSpanTrackingEnabled = true;
401
470
  isLocalTrackingMode = true; // Mark as local tracking
402
471
  funcSpanExpirationTime = null; // Local mode has no expiration
403
- funcSpanTimeoutId = null; // Clear timeout (saved above if it was global)
472
+ // Clear any existing timeout
473
+ if (funcSpanTimeoutId !== null) {
474
+ window.clearTimeout(funcSpanTimeoutId);
475
+ funcSpanTimeoutId = null;
476
+ }
404
477
  // Report this session to backend for tracking with per_session configuration type
405
478
  if (isWebSocketOpen(webSocket)) {
406
479
  try {
@@ -453,29 +526,17 @@ export function disableFunctionSpanTracking() {
453
526
  console.warn(`[FUNCSPAN STOP] ✗ WebSocket not open, cannot notify tracking end`);
454
527
  }
455
528
  if (isLocalTrackingMode) {
529
+ funcSpanTrackingEnabled = false;
456
530
  isLocalTrackingMode = false;
457
- // Restore global tracking state if it was active before local mode
458
- if (savedGlobalTimeoutId !== null || savedGlobalExpirationTime !== null) {
459
- funcSpanTrackingEnabled = true; // Keep tracking enabled (global was active)
460
- funcSpanExpirationTime = savedGlobalExpirationTime;
461
- funcSpanTimeoutId = savedGlobalTimeoutId;
462
- if (DEBUG) {
463
- console.log("[Sailfish] LOCAL tracking mode disabled, restored GLOBAL tracking state");
464
- }
465
- // Clear saved state
466
- savedGlobalTimeoutId = null;
467
- savedGlobalExpirationTime = null;
468
- }
469
- else {
470
- // No global tracking was active, fully disable
471
- funcSpanTrackingEnabled = false;
472
- funcSpanExpirationTime = null;
473
- funcSpanTimeoutId = null;
474
- if (DEBUG) {
475
- console.log("[Sailfish] LOCAL tracking mode disabled, no global tracking to restore");
476
- }
531
+ funcSpanExpirationTime = null;
532
+ if (DEBUG) {
533
+ console.log("[Sailfish] LOCAL tracking mode disabled");
477
534
  }
478
535
  }
536
+ if (funcSpanTimeoutId !== null) {
537
+ window.clearTimeout(funcSpanTimeoutId);
538
+ funcSpanTimeoutId = null;
539
+ }
479
540
  }
480
541
  /**
481
542
  * Check if function span tracking is currently enabled
@@ -483,6 +544,28 @@ export function disableFunctionSpanTracking() {
483
544
  export function isFunctionSpanTrackingEnabled() {
484
545
  return funcSpanTrackingEnabled;
485
546
  }
547
+ /**
548
+ * Initialize function span tracking state from API response (during page load)
549
+ * This is called before the WebSocket connects to ensure headers are added from the start
550
+ */
551
+ export function initializeFunctionSpanTrackingFromApi(isEnabled) {
552
+ if (isEnabled && !funcSpanTrackingEnabled) {
553
+ funcSpanTrackingEnabled = true;
554
+ isLocalTrackingMode = false; // This is global tracking from API
555
+ funcSpanExpirationTime = null; // Will be set by WebSocket message later
556
+ if (DEBUG) {
557
+ console.log("[Sailfish] Function span tracking initialized as ENABLED from API check");
558
+ }
559
+ }
560
+ else if (!isEnabled && funcSpanTrackingEnabled) {
561
+ funcSpanTrackingEnabled = false;
562
+ isLocalTrackingMode = false;
563
+ funcSpanExpirationTime = null;
564
+ if (DEBUG) {
565
+ console.log("[Sailfish] Function span tracking initialized as DISABLED from API check");
566
+ }
567
+ }
568
+ }
486
569
  /**
487
570
  * Get the current funcspan header name and value
488
571
  * Header constants are defined here but used by HTTP interceptors in index.tsx
@@ -499,6 +582,7 @@ export function getFuncSpanHeader() {
499
582
  // Tracking has expired, disable it immediately
500
583
  funcSpanTrackingEnabled = false;
501
584
  funcSpanExpirationTime = null;
585
+ clearGlobalFuncSpanState();
502
586
  if (DEBUG) {
503
587
  console.log("[Sailfish] Function span tracking expired on header check - disabling now");
504
588
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sailfish-ai/recorder",
3
- "version": "1.8.10",
3
+ "version": "1.8.12-alpha-2",
4
4
  "publishPublicly": true,
5
5
  "type": "module",
6
6
  "main": "dist/recorder.cjs",
@@ -37,7 +37,7 @@
37
37
  "dist"
38
38
  ],
39
39
  "dependencies": {
40
- "@sailfish-ai/sf-map-utils": "0.4.3",
40
+ "@sailfish-ai/sf-map-utils": "0.4.4",
41
41
  "@sailfish-rrweb/rrweb-plugin-console-record": "0.5.2",
42
42
  "@sailfish-rrweb/rrweb-record-only": "0.5.2",
43
43
  "@sailfish-rrweb/types": "0.5.2",