@sailfish-ai/recorder 1.10.2 → 1.10.4
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/chunks/fiberHook-CEzmPkx_.js +125 -0
- package/dist/chunks/fiberHook-CEzmPkx_.js.br +0 -0
- package/dist/chunks/fiberHook-CEzmPkx_.js.gz +0 -0
- package/dist/chunks/fiberHook-DGANQ2ma.js +130 -0
- package/dist/chunks/fiberHook-DGANQ2ma.js.br +0 -0
- package/dist/chunks/fiberHook-DGANQ2ma.js.gz +0 -0
- package/dist/chunks/rrweb-plugin-console-record-BmAm-Ih_.js +181 -0
- package/dist/chunks/rrweb-plugin-console-record-BmAm-Ih_.js.br +0 -0
- package/dist/chunks/rrweb-plugin-console-record-BmAm-Ih_.js.gz +0 -0
- package/dist/chunks/rrweb-plugin-console-record-Cr-osXuj.js +180 -0
- package/dist/chunks/rrweb-plugin-console-record-Cr-osXuj.js.br +0 -0
- package/dist/chunks/rrweb-plugin-console-record-Cr-osXuj.js.gz +0 -0
- package/dist/chunks/rrweb-record-only-Ba4xyfd6.js +5253 -0
- package/dist/chunks/rrweb-record-only-Ba4xyfd6.js.br +0 -0
- package/dist/chunks/rrweb-record-only-Ba4xyfd6.js.gz +0 -0
- package/dist/chunks/rrweb-record-only-C5Qb-uaQ.js +5253 -0
- package/dist/chunks/rrweb-record-only-C5Qb-uaQ.js.br +0 -0
- package/dist/chunks/rrweb-record-only-C5Qb-uaQ.js.gz +0 -0
- package/dist/inAppReportIssueModal/index.js +171 -129
- package/dist/inAppReportIssueModal/integrations.js +84 -19
- package/dist/inAppReportIssueModal/state.js +1 -0
- package/dist/inAppReportIssueModal/types.js +1 -0
- package/dist/inAppReportIssueModal/ui.js +9 -0
- package/dist/index.js +259 -60
- package/dist/recorder.cjs +1954 -7344
- package/dist/recorder.js +1953 -7344
- package/dist/recorder.js.br +0 -0
- package/dist/recorder.js.gz +0 -0
- package/dist/recording.js +41 -32
- package/dist/session.js +12 -6
- package/dist/types/inAppReportIssueModal/integrations.d.ts +8 -0
- package/dist/types/inAppReportIssueModal/types.d.ts +3 -4
- package/dist/types/index.d.ts +11 -3
- package/dist/types/recording.d.ts +2 -2
- package/dist/types/session.d.ts +1 -0
- package/dist/types/websocket.d.ts +1 -0
- package/dist/websocket.js +11 -10
- package/package.json +1 -1
package/dist/recorder.js.br
CHANGED
|
Binary file
|
package/dist/recorder.js.gz
CHANGED
|
Binary file
|
package/dist/recording.js
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
|
-
import { record } from "@sailfish-rrweb/rrweb-record-only";
|
|
2
|
-
import { getRecordConsolePlugin, } from "@sailfish-rrweb/rrweb-plugin-console-record";
|
|
3
1
|
// import { NetworkRecordOptions } from "@sailfish-rrweb/rrweb-plugin-network-record";
|
|
4
2
|
import { EventType } from "@sailfish-rrweb/types";
|
|
5
3
|
import { Complete, DomContentEventId, DomContentSource, Loading, } from "./constants";
|
|
6
|
-
// Fiber tracking for source → DOM correlation
|
|
7
|
-
import { installFiberHook, processExistingTree } from "./fiberHook";
|
|
8
4
|
import { getCallerLocation, getCallerLocationFromTrace, } from "./sourceLocation";
|
|
9
5
|
import suppressConsoleLogsDuringCall from "./suppressConsoleLogsDuringCall";
|
|
10
6
|
import { initializeWebSocket, sendEvent } from "./websocket";
|
|
7
|
+
// Module-level reference to rrweb record, populated after dynamic import
|
|
8
|
+
let _record = null;
|
|
11
9
|
const MASK_CLASS = "sailfishSanitize";
|
|
12
10
|
const ZENDESK_ELEMENT_ID = "zendesk_chat";
|
|
13
11
|
const ZENDESK_PROVIDER = "Zendesk";
|
|
@@ -140,7 +138,8 @@ export function initializeDomContentEvents(sessionId) {
|
|
|
140
138
|
});
|
|
141
139
|
});
|
|
142
140
|
}
|
|
143
|
-
export function initializeConsolePlugin(consoleRecordSettings, sessionId) {
|
|
141
|
+
export async function initializeConsolePlugin(consoleRecordSettings, sessionId) {
|
|
142
|
+
const { getRecordConsolePlugin } = await import("@sailfish-rrweb/rrweb-plugin-console-record");
|
|
144
143
|
const { name, observer } = getRecordConsolePlugin(consoleRecordSettings);
|
|
145
144
|
observer((payload) => {
|
|
146
145
|
const anyPayload = payload;
|
|
@@ -249,21 +248,6 @@ export async function initializeRecording(captureSettings, // TODO - Sibyl post-
|
|
|
249
248
|
backendApi, apiKey, sessionId, envValue) {
|
|
250
249
|
const webSocket = initializeWebSocket(backendApi, apiKey, sessionId, envValue);
|
|
251
250
|
try {
|
|
252
|
-
// Initialize fiber tracking for source → DOM correlation
|
|
253
|
-
// This captures React component names via _debugOwner chain and adds data-sf-* attributes
|
|
254
|
-
// IMPORTANT: Must process existing tree BEFORE rrweb starts, so full snapshot includes attributes
|
|
255
|
-
if (captureSettings.enableFiberTracking !== false) {
|
|
256
|
-
try {
|
|
257
|
-
installFiberHook();
|
|
258
|
-
// Process any components that already rendered before hook was installed
|
|
259
|
-
// This must happen synchronously BEFORE record() to ensure attributes are in the snapshot
|
|
260
|
-
processExistingTree();
|
|
261
|
-
console.log("[Sailfish] React Fiber tracking enabled");
|
|
262
|
-
}
|
|
263
|
-
catch (fiberError) {
|
|
264
|
-
console.warn("[Sailfish] Failed to enable Fiber tracking:", fiberError);
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
251
|
// Create throttled emit wrapper (only for text edit events)
|
|
268
252
|
const throttledEmit = createThrottledEmit(captureSettings.textEditThrottleEnabled);
|
|
269
253
|
const emitWithContext = (event) => {
|
|
@@ -271,15 +255,40 @@ backendApi, apiKey, sessionId, envValue) {
|
|
|
271
255
|
event.sessionId = sessionId;
|
|
272
256
|
throttledEmit.emit(event);
|
|
273
257
|
};
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
258
|
+
// Defer heavy synchronous work (Fiber hook install, DOM tree walk, rrweb full snapshot)
|
|
259
|
+
// via requestIdleCallback so the main thread can finish loading first.
|
|
260
|
+
const startHeavyWork = async () => {
|
|
261
|
+
// Initialize fiber tracking for source → DOM correlation
|
|
262
|
+
if (captureSettings.enableFiberTracking !== false) {
|
|
263
|
+
try {
|
|
264
|
+
const { installFiberHook, processExistingTree } = await import("./fiberHook");
|
|
265
|
+
installFiberHook();
|
|
266
|
+
processExistingTree();
|
|
267
|
+
console.log("[Sailfish] React Fiber tracking enabled");
|
|
268
|
+
}
|
|
269
|
+
catch (fiberError) {
|
|
270
|
+
console.warn("[Sailfish] Failed to enable Fiber tracking:", fiberError);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
const { record } = await import("@sailfish-rrweb/rrweb-record-only");
|
|
274
|
+
_record = record;
|
|
275
|
+
record({
|
|
276
|
+
emit(event) {
|
|
277
|
+
emitWithContext(event);
|
|
278
|
+
},
|
|
279
|
+
maskInputOptions: { text: true },
|
|
280
|
+
maskInputFn,
|
|
281
|
+
maskTextClass: MASK_CLASS,
|
|
282
|
+
...captureSettings,
|
|
283
|
+
});
|
|
284
|
+
};
|
|
285
|
+
if (typeof requestIdleCallback === "function") {
|
|
286
|
+
requestIdleCallback(startHeavyWork, { timeout: 2000 });
|
|
287
|
+
}
|
|
288
|
+
else {
|
|
289
|
+
// Fallback for browsers without requestIdleCallback (Safari < 16.4)
|
|
290
|
+
setTimeout(startHeavyWork, 0);
|
|
291
|
+
}
|
|
283
292
|
// Flush buffered text edits before page unload
|
|
284
293
|
window.addEventListener('beforeunload', () => {
|
|
285
294
|
throttledEmit.flush();
|
|
@@ -302,21 +311,21 @@ backendApi, apiKey, sessionId, envValue) {
|
|
|
302
311
|
]);
|
|
303
312
|
});
|
|
304
313
|
const handleWidgetOpen = () => {
|
|
305
|
-
|
|
314
|
+
_record?.addSailfishEvent(EventType.SailfishCustom, {
|
|
306
315
|
action: "customer support chat opened",
|
|
307
316
|
element_id: ZENDESK_ELEMENT_ID,
|
|
308
317
|
provider: ZENDESK_PROVIDER,
|
|
309
318
|
});
|
|
310
319
|
};
|
|
311
320
|
const handleWidgetClose = () => {
|
|
312
|
-
|
|
321
|
+
_record?.addSailfishEvent(EventType.SailfishCustom, {
|
|
313
322
|
action: "customer support chat closed",
|
|
314
323
|
element_id: ZENDESK_ELEMENT_ID,
|
|
315
324
|
provider: ZENDESK_PROVIDER,
|
|
316
325
|
});
|
|
317
326
|
};
|
|
318
327
|
const handleUnreadMessages = (count) => {
|
|
319
|
-
|
|
328
|
+
_record?.addSailfishEvent(EventType.SailfishCustom, {
|
|
320
329
|
action: "zendesk unreadmessages",
|
|
321
330
|
element_id: ZENDESK_ELEMENT_ID,
|
|
322
331
|
provider: ZENDESK_PROVIDER,
|
package/dist/session.js
CHANGED
|
@@ -40,10 +40,16 @@ export function getOrSetSessionId() {
|
|
|
40
40
|
}
|
|
41
41
|
return sessionId;
|
|
42
42
|
}
|
|
43
|
-
//
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
43
|
+
// Deferred: call ensureSessionListeners() from startRecording() to avoid module-level side effects
|
|
44
|
+
let _sessionListenersInstalled = false;
|
|
45
|
+
export function ensureSessionListeners() {
|
|
46
|
+
if (_sessionListenersInstalled)
|
|
47
|
+
return;
|
|
48
|
+
_sessionListenersInstalled = true;
|
|
49
|
+
if (HAS_WINDOW) {
|
|
50
|
+
window.addEventListener("beforeunload", () => {
|
|
51
|
+
// Prepend our flag to preserve customer's window.name
|
|
52
|
+
window.name = REFRESH_FLAG + window.name;
|
|
53
|
+
});
|
|
54
|
+
}
|
|
49
55
|
}
|
|
@@ -3,8 +3,16 @@ import { IssueReportState } from "./types";
|
|
|
3
3
|
export declare function getIntegrationData(): EngineeringTicketIntegration | null;
|
|
4
4
|
export declare function hasValidIntegration(): boolean;
|
|
5
5
|
export declare function fetchIntegrationData(apiKey: string, backendApi: string): Promise<void>;
|
|
6
|
+
/**
|
|
7
|
+
* Re-fetch integration data in the background. Returns the fresh data
|
|
8
|
+
* and updates the module-level cache. Callers can compare with previous
|
|
9
|
+
* data to decide whether to refresh the UI.
|
|
10
|
+
*/
|
|
11
|
+
export declare function refreshIntegrationData(apiKey: string, backendApi: string): Promise<EngineeringTicketIntegration | null>;
|
|
6
12
|
export declare function populateSelectOptions(selectElement: HTMLSelectElement, options: any[], defaultValue?: string): void;
|
|
7
13
|
export declare function populatePriorityOptions(selectElement: HTMLSelectElement, provider: string, defaultPriority?: number): void;
|
|
14
|
+
export declare function populateSprintOptions(selectElement: HTMLSelectElement, sprints: any[], currentValue?: string): void;
|
|
15
|
+
export declare function getSprintFieldId(): string;
|
|
8
16
|
export declare function updateIssueTypeOptions(selectElement: HTMLSelectElement, projectId: string): void;
|
|
9
17
|
export declare function getFieldsForProject(projectId: string, issueTypeId?: string): any[];
|
|
10
18
|
export declare function getUsers(): any[];
|
|
@@ -11,6 +11,7 @@ export interface IssueReportState {
|
|
|
11
11
|
engTicketProject: string;
|
|
12
12
|
engTicketPriority: number;
|
|
13
13
|
engTicketLabels: string[];
|
|
14
|
+
engTicketSprint: string;
|
|
14
15
|
engTicketIssueType: string;
|
|
15
16
|
engTicketCustomFields: Record<string, any>;
|
|
16
17
|
}
|
|
@@ -28,13 +29,11 @@ export declare const STORAGE_KEYS: {
|
|
|
28
29
|
};
|
|
29
30
|
export declare const DEFAULT_SHORTCUTS: ShortcutsConfig;
|
|
30
31
|
export declare const ReportIssueContext: {
|
|
31
|
-
shortcuts:
|
|
32
|
-
openReportIssue?: ShortcutConfig;
|
|
33
|
-
openStartNowMode?: ShortcutConfig;
|
|
34
|
-
};
|
|
32
|
+
shortcuts: ShortcutsConfig;
|
|
35
33
|
resolveSessionId: (() => string) | null;
|
|
36
34
|
apiKey: string | null;
|
|
37
35
|
backendApi: string | null;
|
|
38
36
|
triageBaseUrl: string;
|
|
39
37
|
deactivateIsolation: () => void;
|
|
38
|
+
integrationData: any;
|
|
40
39
|
};
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { LogRecordOptions } from "@sailfish-rrweb/rrweb-plugin-console-record";
|
|
2
|
-
import { ShortcutsConfig } from "./inAppReportIssueModal";
|
|
1
|
+
import type { LogRecordOptions } from "@sailfish-rrweb/rrweb-plugin-console-record";
|
|
2
|
+
import type { ShortcutsConfig } from "./inAppReportIssueModal";
|
|
3
3
|
import { CaptureSettings } from "./types";
|
|
4
4
|
export declare const STORAGE_VERSION = 1;
|
|
5
5
|
export declare const DEFAULT_CAPTURE_SETTINGS: CaptureSettings;
|
|
6
6
|
export declare const DEFAULT_CONSOLE_RECORDING_SETTINGS: LogRecordOptions;
|
|
7
7
|
export declare function matchUrlWithWildcard(input: unknown, patterns: string[]): boolean;
|
|
8
|
-
export declare function startRecording({ apiKey, backendApi, domainsToPropagateHeaderTo, domainsToNotPropagateHeaderTo, serviceVersion, serviceIdentifier, gitSha, serviceAdditionalMetadata, enableIpTracking, }: {
|
|
8
|
+
export declare function startRecording({ apiKey, backendApi, domainsToPropagateHeaderTo, domainsToNotPropagateHeaderTo, serviceVersion, serviceIdentifier, gitSha, serviceAdditionalMetadata, enableIpTracking, captureStreamingResponseBody, captureResponseBodyMaxMb, captureStreamPrefixKb, captureStreamTimeoutMs, }: {
|
|
9
9
|
apiKey: string;
|
|
10
10
|
backendApi?: string;
|
|
11
11
|
domainsToPropagateHeaderTo?: string[];
|
|
@@ -15,6 +15,10 @@ export declare function startRecording({ apiKey, backendApi, domainsToPropagateH
|
|
|
15
15
|
gitSha?: string;
|
|
16
16
|
serviceAdditionalMetadata?: Record<string, any>;
|
|
17
17
|
enableIpTracking?: boolean;
|
|
18
|
+
captureStreamingResponseBody?: boolean;
|
|
19
|
+
captureResponseBodyMaxMb?: number;
|
|
20
|
+
captureStreamPrefixKb?: number;
|
|
21
|
+
captureStreamTimeoutMs?: number;
|
|
18
22
|
}): Promise<void>;
|
|
19
23
|
export declare const initRecorder: (options: {
|
|
20
24
|
apiKey: string;
|
|
@@ -29,6 +33,10 @@ export declare const initRecorder: (options: {
|
|
|
29
33
|
customBaseUrl?: string;
|
|
30
34
|
enableFiberTracking?: boolean;
|
|
31
35
|
enableIpTracking?: boolean;
|
|
36
|
+
captureStreamingResponseBody?: boolean;
|
|
37
|
+
captureResponseBodyMaxMb?: number;
|
|
38
|
+
captureStreamPrefixKb?: number;
|
|
39
|
+
captureStreamTimeoutMs?: number;
|
|
32
40
|
}) => Promise<void>;
|
|
33
41
|
export * from "./graphql";
|
|
34
42
|
export { openReportIssueModal } from "./inAppReportIssueModal";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { LogRecordOptions } from "@sailfish-rrweb/rrweb-plugin-console-record";
|
|
1
|
+
import type { LogRecordOptions } from "@sailfish-rrweb/rrweb-plugin-console-record";
|
|
2
2
|
import ReconnectingWebSocket from "reconnecting-websocket";
|
|
3
3
|
export declare const getUrlAndStoredUuids: () => {
|
|
4
4
|
page_visit_uuid: string;
|
|
@@ -8,6 +8,6 @@ export declare const getUrlAndStoredUuids: () => {
|
|
|
8
8
|
tabVisibilityState: string;
|
|
9
9
|
};
|
|
10
10
|
export declare function initializeDomContentEvents(sessionId: string): void;
|
|
11
|
-
export declare function initializeConsolePlugin(consoleRecordSettings: LogRecordOptions, sessionId: string): void
|
|
11
|
+
export declare function initializeConsolePlugin(consoleRecordSettings: LogRecordOptions, sessionId: string): Promise<void>;
|
|
12
12
|
export declare function initializeRecording(captureSettings: any, // TODO - Sibyl post-launch - replace type
|
|
13
13
|
backendApi: string, apiKey: string, sessionId: string, envValue?: string): Promise<ReconnectingWebSocket>;
|
package/dist/types/session.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ import ReconnectingWebSocket from "reconnecting-websocket";
|
|
|
4
4
|
* This disables tracking and clears localStorage if backend says tracking is not active
|
|
5
5
|
*/
|
|
6
6
|
export declare function clearStaleFuncSpanState(): void;
|
|
7
|
+
export declare function restoreFuncSpanState(): void;
|
|
7
8
|
export declare function flushBufferedEvents(): Promise<void>;
|
|
8
9
|
export declare function sendEvent(event: any): void;
|
|
9
10
|
export declare function initializeWebSocket(backendApi: string, apiKey: string, sessionId: string, envValue?: string): ReconnectingWebSocket;
|
package/dist/websocket.js
CHANGED
|
@@ -106,16 +106,19 @@ export function clearStaleFuncSpanState() {
|
|
|
106
106
|
console.log("[Sailfish] Cleared stale function span tracking state (backend validation failed)");
|
|
107
107
|
}
|
|
108
108
|
}
|
|
109
|
-
//
|
|
110
|
-
|
|
111
|
-
(
|
|
109
|
+
// Deferred: call restoreFuncSpanState() from startRecording() to avoid module-level side effects
|
|
110
|
+
let _funcSpanStateRestored = false;
|
|
111
|
+
export function restoreFuncSpanState() {
|
|
112
|
+
if (_funcSpanStateRestored)
|
|
113
|
+
return;
|
|
114
|
+
_funcSpanStateRestored = true;
|
|
112
115
|
const persistedState = loadGlobalFuncSpanState();
|
|
113
116
|
if (persistedState && persistedState.enabled) {
|
|
114
117
|
funcSpanTrackingEnabled = true;
|
|
115
118
|
funcSpanExpirationTime = persistedState.expirationTimestampMs;
|
|
116
119
|
isLocalTrackingMode = false;
|
|
117
120
|
if (DEBUG) {
|
|
118
|
-
console.log(`[Sailfish]
|
|
121
|
+
console.log(`[Sailfish] Restored global function span tracking from localStorage:`, {
|
|
119
122
|
enabled: true,
|
|
120
123
|
expirationTime: funcSpanExpirationTime,
|
|
121
124
|
});
|
|
@@ -129,24 +132,22 @@ export function clearStaleFuncSpanState() {
|
|
|
129
132
|
funcSpanExpirationTime = null;
|
|
130
133
|
clearGlobalFuncSpanState();
|
|
131
134
|
if (DEBUG) {
|
|
132
|
-
console.log("[Sailfish]
|
|
135
|
+
console.log("[Sailfish] Persisted tracking already expired, cleared state");
|
|
133
136
|
}
|
|
134
137
|
}
|
|
135
138
|
else {
|
|
136
|
-
// State is still valid, keep it temporarily until WebSocket provides the true state
|
|
137
139
|
if (DEBUG) {
|
|
138
|
-
console.log("[Sailfish]
|
|
140
|
+
console.log("[Sailfish] Function span tracking is active and valid (temporary until WebSocket confirms)");
|
|
139
141
|
}
|
|
140
142
|
}
|
|
141
143
|
}
|
|
142
144
|
else {
|
|
143
|
-
// No expiration time - keep enabled temporarily until WebSocket provides the true state
|
|
144
145
|
if (DEBUG) {
|
|
145
|
-
console.log("[Sailfish]
|
|
146
|
+
console.log("[Sailfish] Function span tracking is active (no expiration, temporary until WebSocket confirms)");
|
|
146
147
|
}
|
|
147
148
|
}
|
|
148
149
|
}
|
|
149
|
-
}
|
|
150
|
+
}
|
|
150
151
|
function isWebSocketOpen(ws) {
|
|
151
152
|
return ws?.readyState === WebSocket.OPEN;
|
|
152
153
|
}
|