@mushi-mushi/core 1.32.2 → 1.33.0

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.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { M as MushiApiClient, a as MushiConfig, b as MushiPreFilterConfig, c as MushiReport, d as MushiOfflineConfig, e as MushiEnvironment, f as MushiAnalyticsConfig, g as MushiPropertyValue, h as MushiBreadcrumb } from './types-CWa7T4bx.cjs';
2
- export { i as MushiActivityEvent, j as MushiApiCascadeConfig, k as MushiApiResponse, l as MushiAssistantConfig, m as MushiAssistantReply, n as MushiAssistantStep, o as MushiBannerConfig, p as MushiBannerLink, q as MushiBetaChangelogEntry, r as MushiBetaModeConfig, s as MushiCaptureConfig, t as MushiCaptureEventInput, u as MushiCaptureExceptionOptions, v as MushiConsoleEntry, w as MushiCooldownConfig, x as MushiCrossAppReport, y as MushiCustomCategory, z as MushiDiagnosticsResult, A as MushiDiscoverInventoryConfig, B as MushiDiscoveryEventPayload, C as MushiEventHandler, D as MushiEventType, E as MushiHallOfFameEntry, F as MushiIntegrationsConfig, G as MushiLeaderboardEntry, H as MushiNetworkEntry, I as MushiNotificationsConfig, J as MushiOnDeviceClassifier, K as MushiOnDeviceClassifierInput, L as MushiOnDeviceClassifierResult, N as MushiPageContext, O as MushiPerformanceMetrics, P as MushiPreset, Q as MushiPrivacyConfig, R as MushiProactiveConfig, S as MushiProductEventPayload, T as MushiPushSubscriptionJSON, U as MushiReportBuilder, V as MushiReportCategory, W as MushiReportStatus, X as MushiReporterChannelUnavailable, Y as MushiReporterComment, Z as MushiReporterNotificationPrefs, _ as MushiReporterPrefsUpdate, $ as MushiReporterReport, a0 as MushiReporterReportDetail, a1 as MushiReporterTimelineItem, a2 as MushiReporterUpdates, a3 as MushiReputationResult, a4 as MushiRewardsConfig, a5 as MushiRuntimeSdkConfig, a6 as MushiSDKInstance, a7 as MushiSdkVersionInfo, a8 as MushiSelectedElement, a9 as MushiSentryConfig, aa as MushiSentryContext, ab as MushiSessionEventPayload, ac as MushiTesterReputation, ad as MushiTierResult, ae as MushiTimelineEntry, af as MushiTimelineKind, ag as MushiTracePropagationConfig, ah as MushiUrlMatcher, ai as MushiWidgetAnchor, aj as MushiWidgetConfig } from './types-CWa7T4bx.cjs';
1
+ import { M as MushiApiClient, a as MushiConfig, b as MushiPreFilterConfig, c as MushiReport, d as MushiOfflineConfig, e as MushiEnvironment, f as MushiAnalyticsConfig, g as MushiPropertyValue, h as MushiBreadcrumb } from './types-DkC08B8U.cjs';
2
+ export { i as MushiActivityEvent, j as MushiApiCascadeConfig, k as MushiApiResponse, l as MushiAssistantConfig, m as MushiAssistantReply, n as MushiAssistantStep, o as MushiBannerConfig, p as MushiBannerLink, q as MushiBetaChangelogEntry, r as MushiBetaModeConfig, s as MushiCaptureConfig, t as MushiCaptureEventInput, u as MushiCaptureExceptionOptions, v as MushiConsoleEntry, w as MushiCooldownConfig, x as MushiCrossAppReport, y as MushiCustomCategory, z as MushiDiagnosticsResult, A as MushiDiscoverInventoryConfig, B as MushiDiscoveryEventPayload, C as MushiEventHandler, D as MushiEventType, E as MushiHallOfFameEntry, F as MushiInitConfig, G as MushiIntegrationsConfig, H as MushiLeaderboardEntry, I as MushiNetworkEntry, J as MushiNotificationsConfig, K as MushiOnDeviceClassifier, L as MushiOnDeviceClassifierInput, N as MushiOnDeviceClassifierResult, O as MushiPageContext, P as MushiPerformanceMetrics, Q as MushiPreset, R as MushiPrivacyConfig, S as MushiProactiveConfig, T as MushiProductEventPayload, U as MushiPushSubscriptionJSON, V as MushiReportBuilder, W as MushiReportCategory, X as MushiReportStatus, Y as MushiReporterChannelUnavailable, Z as MushiReporterComment, _ as MushiReporterNotificationPrefs, $ as MushiReporterPrefsUpdate, a0 as MushiReporterReport, a1 as MushiReporterReportDetail, a2 as MushiReporterTimelineItem, a3 as MushiReporterUpdates, a4 as MushiReputationResult, a5 as MushiRewardsConfig, a6 as MushiRuntimeSdkConfig, a7 as MushiRuntimeWidgetConfig, a8 as MushiSDKInstance, a9 as MushiSdkVersionInfo, aa as MushiSelectedElement, ab as MushiSentryConfig, ac as MushiSentryContext, ad as MushiSessionEventPayload, ae as MushiTesterReputation, af as MushiTierResult, ag as MushiTimelineEntry, ah as MushiTimelineKind, ai as MushiTracePropagationConfig, aj as MushiUrlMatcher, ak as MushiWidgetAnchor, al as MushiWidgetConfig } from './types-DkC08B8U.cjs';
3
3
 
4
4
  /** Replay the in-flight POST via keepalive/beacon during pagehide. */
5
5
  declare function flushLastOutboundOnUnload(): boolean;
@@ -463,19 +463,21 @@ interface SessionTrackerOptions {
463
463
  * Initialise the session tracker. Call once at SDK init for web environments.
464
464
  * Subsequent calls on the same page are no-ops (idempotent).
465
465
  *
466
- * Emits, once the analytics gate allows it: session_start, heartbeats every
467
- * minute, session_end on visibilitychange/pagehide, and page_view on history
468
- * API navigation. Under `consent: 'required'` nothing is sent until
469
- * setConsent('granted').
466
+ * Emits, once the analytics gate allows it: session_start, a heartbeat after
467
+ * each minute without another request while the tab is visible, one
468
+ * session_end per hide (visibilitychange/pagehide), and page_view when a
469
+ * history API navigation changes the pathname. Under `consent: 'required'`
470
+ * nothing is sent until setConsent('granted').
470
471
  */
471
472
  declare function initSessionTracker(opts: SessionTrackerOptions): void;
472
473
  /**
473
474
  * Record a page view manually — call from framework router hooks where the
474
475
  * history patch may fire too early (e.g. React Router v7 loader transitions),
475
- * or from a host that initialised with `patchHistory: false`.
476
+ * or from a host that initialised with `patchHistory: false`. A call whose
477
+ * pathname matches the last page view is ignored: it is the same page.
476
478
  */
477
479
  declare function trackPageView(route?: string): void;
478
- /** Update the user identity after a Mushi.identify() call. */
480
+ /** Set the identity heartbeats carry: a SHA-256 hex of the host user id, never the raw id. */
479
481
  declare function updateSessionIdentity(userIdHash: string | null): void;
480
482
  /** Tear down timers (e.g. in tests or SSR environments). */
481
483
  declare function destroySessionTracker(): void;
@@ -1190,8 +1192,8 @@ declare const MUSHI_LETTER_SPACING: {
1190
1192
  declare const MUSHI_GEOMETRY: {
1191
1193
  readonly bannerHeight: 36;
1192
1194
  readonly fabSize: 52;
1193
- /** edge-tab launcher width (px) */
1194
- readonly edgeTabWidth: 32;
1195
+ /** edge-tab launcher drawn width (px) */
1196
+ readonly edgeTabWidth: 22;
1195
1197
  /** default gutter from the screen edge (added on top of safe-area insets) */
1196
1198
  readonly gutter: 24;
1197
1199
  /** Web panel width (px) — matches shipped Shadow DOM widget */
@@ -1217,7 +1219,7 @@ declare function resolveWidgetAccent(mode: MushiThemeMode, accent?: string, acce
1217
1219
  * label / CTA wording (seen as inconsistent across the four host apps).
1218
1220
  */
1219
1221
  declare const MUSHI_COPY: {
1220
- readonly bannerLabel: "Beta";
1222
+ readonly bannerLabel: "Feedback";
1221
1223
  readonly bannerMessage: "Found a bug? Tap to report it.";
1222
1224
  readonly bugCta: "Report a bug";
1223
1225
  readonly featureCta: "Feature request";
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { M as MushiApiClient, a as MushiConfig, b as MushiPreFilterConfig, c as MushiReport, d as MushiOfflineConfig, e as MushiEnvironment, f as MushiAnalyticsConfig, g as MushiPropertyValue, h as MushiBreadcrumb } from './types-CWa7T4bx.js';
2
- export { i as MushiActivityEvent, j as MushiApiCascadeConfig, k as MushiApiResponse, l as MushiAssistantConfig, m as MushiAssistantReply, n as MushiAssistantStep, o as MushiBannerConfig, p as MushiBannerLink, q as MushiBetaChangelogEntry, r as MushiBetaModeConfig, s as MushiCaptureConfig, t as MushiCaptureEventInput, u as MushiCaptureExceptionOptions, v as MushiConsoleEntry, w as MushiCooldownConfig, x as MushiCrossAppReport, y as MushiCustomCategory, z as MushiDiagnosticsResult, A as MushiDiscoverInventoryConfig, B as MushiDiscoveryEventPayload, C as MushiEventHandler, D as MushiEventType, E as MushiHallOfFameEntry, F as MushiIntegrationsConfig, G as MushiLeaderboardEntry, H as MushiNetworkEntry, I as MushiNotificationsConfig, J as MushiOnDeviceClassifier, K as MushiOnDeviceClassifierInput, L as MushiOnDeviceClassifierResult, N as MushiPageContext, O as MushiPerformanceMetrics, P as MushiPreset, Q as MushiPrivacyConfig, R as MushiProactiveConfig, S as MushiProductEventPayload, T as MushiPushSubscriptionJSON, U as MushiReportBuilder, V as MushiReportCategory, W as MushiReportStatus, X as MushiReporterChannelUnavailable, Y as MushiReporterComment, Z as MushiReporterNotificationPrefs, _ as MushiReporterPrefsUpdate, $ as MushiReporterReport, a0 as MushiReporterReportDetail, a1 as MushiReporterTimelineItem, a2 as MushiReporterUpdates, a3 as MushiReputationResult, a4 as MushiRewardsConfig, a5 as MushiRuntimeSdkConfig, a6 as MushiSDKInstance, a7 as MushiSdkVersionInfo, a8 as MushiSelectedElement, a9 as MushiSentryConfig, aa as MushiSentryContext, ab as MushiSessionEventPayload, ac as MushiTesterReputation, ad as MushiTierResult, ae as MushiTimelineEntry, af as MushiTimelineKind, ag as MushiTracePropagationConfig, ah as MushiUrlMatcher, ai as MushiWidgetAnchor, aj as MushiWidgetConfig } from './types-CWa7T4bx.js';
1
+ import { M as MushiApiClient, a as MushiConfig, b as MushiPreFilterConfig, c as MushiReport, d as MushiOfflineConfig, e as MushiEnvironment, f as MushiAnalyticsConfig, g as MushiPropertyValue, h as MushiBreadcrumb } from './types-DkC08B8U.js';
2
+ export { i as MushiActivityEvent, j as MushiApiCascadeConfig, k as MushiApiResponse, l as MushiAssistantConfig, m as MushiAssistantReply, n as MushiAssistantStep, o as MushiBannerConfig, p as MushiBannerLink, q as MushiBetaChangelogEntry, r as MushiBetaModeConfig, s as MushiCaptureConfig, t as MushiCaptureEventInput, u as MushiCaptureExceptionOptions, v as MushiConsoleEntry, w as MushiCooldownConfig, x as MushiCrossAppReport, y as MushiCustomCategory, z as MushiDiagnosticsResult, A as MushiDiscoverInventoryConfig, B as MushiDiscoveryEventPayload, C as MushiEventHandler, D as MushiEventType, E as MushiHallOfFameEntry, F as MushiInitConfig, G as MushiIntegrationsConfig, H as MushiLeaderboardEntry, I as MushiNetworkEntry, J as MushiNotificationsConfig, K as MushiOnDeviceClassifier, L as MushiOnDeviceClassifierInput, N as MushiOnDeviceClassifierResult, O as MushiPageContext, P as MushiPerformanceMetrics, Q as MushiPreset, R as MushiPrivacyConfig, S as MushiProactiveConfig, T as MushiProductEventPayload, U as MushiPushSubscriptionJSON, V as MushiReportBuilder, W as MushiReportCategory, X as MushiReportStatus, Y as MushiReporterChannelUnavailable, Z as MushiReporterComment, _ as MushiReporterNotificationPrefs, $ as MushiReporterPrefsUpdate, a0 as MushiReporterReport, a1 as MushiReporterReportDetail, a2 as MushiReporterTimelineItem, a3 as MushiReporterUpdates, a4 as MushiReputationResult, a5 as MushiRewardsConfig, a6 as MushiRuntimeSdkConfig, a7 as MushiRuntimeWidgetConfig, a8 as MushiSDKInstance, a9 as MushiSdkVersionInfo, aa as MushiSelectedElement, ab as MushiSentryConfig, ac as MushiSentryContext, ad as MushiSessionEventPayload, ae as MushiTesterReputation, af as MushiTierResult, ag as MushiTimelineEntry, ah as MushiTimelineKind, ai as MushiTracePropagationConfig, aj as MushiUrlMatcher, ak as MushiWidgetAnchor, al as MushiWidgetConfig } from './types-DkC08B8U.js';
3
3
 
4
4
  /** Replay the in-flight POST via keepalive/beacon during pagehide. */
5
5
  declare function flushLastOutboundOnUnload(): boolean;
@@ -463,19 +463,21 @@ interface SessionTrackerOptions {
463
463
  * Initialise the session tracker. Call once at SDK init for web environments.
464
464
  * Subsequent calls on the same page are no-ops (idempotent).
465
465
  *
466
- * Emits, once the analytics gate allows it: session_start, heartbeats every
467
- * minute, session_end on visibilitychange/pagehide, and page_view on history
468
- * API navigation. Under `consent: 'required'` nothing is sent until
469
- * setConsent('granted').
466
+ * Emits, once the analytics gate allows it: session_start, a heartbeat after
467
+ * each minute without another request while the tab is visible, one
468
+ * session_end per hide (visibilitychange/pagehide), and page_view when a
469
+ * history API navigation changes the pathname. Under `consent: 'required'`
470
+ * nothing is sent until setConsent('granted').
470
471
  */
471
472
  declare function initSessionTracker(opts: SessionTrackerOptions): void;
472
473
  /**
473
474
  * Record a page view manually — call from framework router hooks where the
474
475
  * history patch may fire too early (e.g. React Router v7 loader transitions),
475
- * or from a host that initialised with `patchHistory: false`.
476
+ * or from a host that initialised with `patchHistory: false`. A call whose
477
+ * pathname matches the last page view is ignored: it is the same page.
476
478
  */
477
479
  declare function trackPageView(route?: string): void;
478
- /** Update the user identity after a Mushi.identify() call. */
480
+ /** Set the identity heartbeats carry: a SHA-256 hex of the host user id, never the raw id. */
479
481
  declare function updateSessionIdentity(userIdHash: string | null): void;
480
482
  /** Tear down timers (e.g. in tests or SSR environments). */
481
483
  declare function destroySessionTracker(): void;
@@ -1190,8 +1192,8 @@ declare const MUSHI_LETTER_SPACING: {
1190
1192
  declare const MUSHI_GEOMETRY: {
1191
1193
  readonly bannerHeight: 36;
1192
1194
  readonly fabSize: 52;
1193
- /** edge-tab launcher width (px) */
1194
- readonly edgeTabWidth: 32;
1195
+ /** edge-tab launcher drawn width (px) */
1196
+ readonly edgeTabWidth: 22;
1195
1197
  /** default gutter from the screen edge (added on top of safe-area insets) */
1196
1198
  readonly gutter: 24;
1197
1199
  /** Web panel width (px) — matches shipped Shadow DOM widget */
@@ -1217,7 +1219,7 @@ declare function resolveWidgetAccent(mode: MushiThemeMode, accent?: string, acce
1217
1219
  * label / CTA wording (seen as inconsistent across the four host apps).
1218
1220
  */
1219
1221
  declare const MUSHI_COPY: {
1220
- readonly bannerLabel: "Beta";
1222
+ readonly bannerLabel: "Feedback";
1221
1223
  readonly bannerMessage: "Found a bug? Tap to report it.";
1222
1224
  readonly bugCta: "Report a bug";
1223
1225
  readonly featureCta: "Feature request";
package/dist/index.js CHANGED
@@ -1594,14 +1594,10 @@ function createOfflineQueue(config = {}) {
1594
1594
  });
1595
1595
  break;
1596
1596
  }
1597
- const permanent = result.error?.code === "HTTP_400" || result.error?.code === "HTTP_413" || result.error?.code === "HTTP_422" || result.error?.code === "INGEST_ERROR" || result.error?.code === "VALIDATION_ERROR" || // A payload that exceeds the size guard will never shrink on its own;
1598
- // retrying re-serialises the multi-MB body every sync tick and wedges
1599
- // the queue (it matches neither permanent nor transient otherwise).
1600
- // SERIALIZE_FAILED (circular ref) is likewise unrecoverable on retry.
1601
- result.error?.code === "PAYLOAD_TOO_LARGE" || result.error?.code === "SERIALIZE_FAILED" || typeof result.error?.message === "string" && /invalid payload|description must be at least|validation/i.test(
1597
+ const permanent = result.error?.code === "HTTP_400" || result.error?.status === 401 || result.error?.status === 403 || result.error?.code === "HTTP_401" || result.error?.code === "HTTP_403" || result.error?.code === "HTTP_413" || result.error?.code === "HTTP_422" || result.error?.code === "INGEST_ERROR" || result.error?.code === "VALIDATION_ERROR" || result.error?.code === "PAYLOAD_TOO_LARGE" || result.error?.code === "SERIALIZE_FAILED" || typeof result.error?.message === "string" && /invalid payload|description must be at least|validation/i.test(
1602
1598
  result.error.message
1603
1599
  );
1604
- const transient = !permanent && (result.error?.code === "NETWORK_ERROR" || result.error?.code === "HTTP_403" || result.error?.code === "HTTP_429" || result.error?.code === "HTTP_502" || result.error?.code === "HTTP_503" || result.error?.code === "HTTP_504" || typeof result.error?.code === "string" && result.error.code.startsWith("HTTP_5"));
1600
+ const transient = !permanent && (result.error?.code === "NETWORK_ERROR" || result.error?.code === "HTTP_429" || result.error?.code === "HTTP_502" || result.error?.code === "HTTP_503" || result.error?.code === "HTTP_504" || typeof result.error?.code === "string" && result.error.code.startsWith("HTTP_5"));
1605
1601
  if (permanent) {
1606
1602
  await removeRow(backend, rowId);
1607
1603
  } else {
@@ -2046,7 +2042,7 @@ function randomSuffix() {
2046
2042
  }
2047
2043
  let n = 0;
2048
2044
  for (const b of bytes) n = n * 256 + b >>> 0;
2049
- return n.toString(36).padStart(6, "0").slice(0, 6);
2045
+ return (n % 36 ** 6).toString(36).padStart(6, "0");
2050
2046
  }
2051
2047
 
2052
2048
  // src/analytics-gate.ts
@@ -2118,7 +2114,9 @@ var _sdkVersion;
2118
2114
  var _userIdHash = null;
2119
2115
  var _reporterToken = null;
2120
2116
  var _pageViewCount = 0;
2121
- var _heartbeatTimer = null;
2117
+ var _heartbeatTimer;
2118
+ var _lastRoute = null;
2119
+ var _endSent = false;
2122
2120
  var _initialized = false;
2123
2121
  var _active = false;
2124
2122
  var _started = false;
@@ -2160,30 +2158,62 @@ function send(payload) {
2160
2158
  if (!_client || !_active) return;
2161
2159
  _client.postSessionEvent(payload).catch(() => {
2162
2160
  });
2161
+ scheduleHeartbeat();
2162
+ }
2163
+ function clearHeartbeat() {
2164
+ clearTimeout(_heartbeatTimer);
2165
+ }
2166
+ function scheduleHeartbeat() {
2167
+ clearHeartbeat();
2168
+ if (!_active || globalThis.document?.visibilityState === "hidden") return;
2169
+ _heartbeatTimer = setTimeout(() => {
2170
+ send(buildPayload("session_heartbeat", { route: currentRoute() }));
2171
+ }, HEARTBEAT_INTERVAL_MS);
2163
2172
  }
2164
2173
  function recordPageView(route) {
2165
2174
  if (!_active) return;
2175
+ if (route === _lastRoute) return;
2176
+ _lastRoute = route;
2166
2177
  _pageViewCount += 1;
2167
2178
  send(buildPayload("page_view", { route }));
2168
2179
  }
2180
+ function sendSessionEnd() {
2181
+ if (_endSent || !_active) return;
2182
+ _endSent = true;
2183
+ send(buildPayload("session_end", { route: currentRoute() }));
2184
+ clearHeartbeat();
2185
+ }
2169
2186
  function activate() {
2170
2187
  if (_active || !_initialized) return;
2171
2188
  _active = true;
2172
2189
  if (!_started) {
2173
2190
  _started = true;
2174
2191
  _pageViewCount = 1;
2175
- send(buildPayload("session_start", { route: currentRoute(), referrer: referrerOrigin() }));
2192
+ _lastRoute = currentRoute();
2193
+ send(buildPayload("session_start", { route: _lastRoute, referrer: referrerOrigin() }));
2194
+ } else {
2195
+ scheduleHeartbeat();
2176
2196
  }
2177
- _heartbeatTimer = setInterval(() => {
2178
- send(buildPayload("session_heartbeat", { route: currentRoute() }));
2179
- }, HEARTBEAT_INTERVAL_MS);
2197
+ }
2198
+ function onHide() {
2199
+ if (document.visibilityState === "hidden") {
2200
+ sendSessionEnd();
2201
+ } else {
2202
+ _endSent = false;
2203
+ scheduleHeartbeat();
2204
+ }
2205
+ }
2206
+ function onPagehide() {
2207
+ sendSessionEnd();
2208
+ }
2209
+ function onPageshow(event) {
2210
+ if (!event.persisted) return;
2211
+ _endSent = false;
2212
+ scheduleHeartbeat();
2180
2213
  }
2181
2214
  function deactivate() {
2182
2215
  _active = false;
2183
- if (_heartbeatTimer != null) {
2184
- clearInterval(_heartbeatTimer);
2185
- _heartbeatTimer = null;
2186
- }
2216
+ clearHeartbeat();
2187
2217
  }
2188
2218
  function initSessionTracker(opts) {
2189
2219
  if (_initialized || typeof window === "undefined") return;
@@ -2193,17 +2223,11 @@ function initSessionTracker(opts) {
2193
2223
  _sdkVersion = opts.sdkVersion;
2194
2224
  _reporterToken = opts.reporterToken ?? opts.reporterTokenHash ?? null;
2195
2225
  _userIdHash = opts.userIdHash ?? null;
2196
- const onHide = () => {
2197
- if (typeof document !== "undefined" && document.visibilityState === "hidden") {
2198
- send(buildPayload("session_end", { route: currentRoute() }));
2199
- }
2200
- };
2201
2226
  if (typeof document !== "undefined") {
2202
2227
  document.addEventListener("visibilitychange", onHide, { passive: true });
2203
2228
  }
2204
- window.addEventListener("pagehide", () => {
2205
- send(buildPayload("session_end", { route: currentRoute() }));
2206
- }, { passive: true });
2229
+ window.addEventListener("pagehide", onPagehide, { passive: true });
2230
+ window.addEventListener("pageshow", onPageshow, { passive: true });
2207
2231
  if (opts.patchHistory !== false) {
2208
2232
  patchHistoryForPageViews();
2209
2233
  }
@@ -2218,6 +2242,7 @@ function trackPageView(route) {
2218
2242
  recordPageView(route ?? currentRoute());
2219
2243
  }
2220
2244
  function updateSessionIdentity(userIdHash) {
2245
+ if (userIdHash && userIdHash !== _userIdHash) _lastRoute = null;
2221
2246
  _userIdHash = userIdHash;
2222
2247
  }
2223
2248
  function destroySessionTracker() {
@@ -2226,6 +2251,8 @@ function destroySessionTracker() {
2226
2251
  _unsubscribeConsent = null;
2227
2252
  _initialized = false;
2228
2253
  _started = false;
2254
+ _lastRoute = null;
2255
+ _endSent = false;
2229
2256
  _client = null;
2230
2257
  }
2231
2258
  var _historyPatched = false;
@@ -2547,10 +2574,10 @@ function initEventTracker(opts) {
2547
2574
  _flushTimer = setInterval(() => {
2548
2575
  void flushNow();
2549
2576
  }, interval);
2550
- const onHide = () => {
2577
+ const onHide2 = () => {
2551
2578
  if (typeof document !== "undefined" && document.visibilityState === "hidden") void flushNow();
2552
2579
  };
2553
- if (typeof document !== "undefined") document.addEventListener("visibilitychange", onHide, { passive: true });
2580
+ if (typeof document !== "undefined") document.addEventListener("visibilitychange", onHide2, { passive: true });
2554
2581
  window.addEventListener("pagehide", () => {
2555
2582
  void flushNow();
2556
2583
  }, { passive: true });
@@ -2990,8 +3017,8 @@ var MUSHI_LETTER_SPACING = {
2990
3017
  var MUSHI_GEOMETRY = {
2991
3018
  bannerHeight: 36,
2992
3019
  fabSize: 52,
2993
- /** edge-tab launcher width (px) */
2994
- edgeTabWidth: 32,
3020
+ /** edge-tab launcher drawn width (px) */
3021
+ edgeTabWidth: 22,
2995
3022
  /** default gutter from the screen edge (added on top of safe-area insets) */
2996
3023
  gutter: 24,
2997
3024
  /** Web panel width (px) — matches shipped Shadow DOM widget */
@@ -3014,7 +3041,7 @@ function resolveWidgetAccent(mode, accent = "", accentText = "") {
3014
3041
  return { accent: resolvedAccent, accentWash, accentInk };
3015
3042
  }
3016
3043
  var MUSHI_COPY = {
3017
- bannerLabel: "Beta",
3044
+ bannerLabel: "Feedback",
3018
3045
  bannerMessage: "Found a bug? Tap to report it.",
3019
3046
  bugCta: "Report a bug",
3020
3047
  featureCta: "Feature request",