From cb79c9b3adc3160e6df33fd83cd94bb5d88dbcc5 Mon Sep 17 00:00:00 2001 From: saravanakumardb1 Date: Thu, 5 Mar 2026 10:57:58 -0800 Subject: [PATCH] feat(diagnostics): wire @bytelyst/diagnostics-client init in ChronoMind web --- web/package.json | 1 + web/src/app/providers.tsx | 2 ++ web/src/lib/diagnostics.ts | 48 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+) create mode 100644 web/src/lib/diagnostics.ts diff --git a/web/package.json b/web/package.json index 2908bc8..5705f13 100644 --- a/web/package.json +++ b/web/package.json @@ -17,6 +17,7 @@ "@bytelyst/api-client": "file:../../learning_ai_common_plat/packages/api-client", "@bytelyst/auth-client": "file:../../learning_ai_common_plat/packages/auth-client", "@bytelyst/react-auth": "file:../../learning_ai_common_plat/packages/react-auth", + "@bytelyst/diagnostics-client": "file:../../learning_ai_common_plat/packages/diagnostics-client", "@bytelyst/telemetry-client": "file:../../learning_ai_common_plat/packages/telemetry-client", "@serwist/next": "^9.5.6", "date-fns": "^4.1.0", diff --git a/web/src/app/providers.tsx b/web/src/app/providers.tsx index b3819f3..4fc46cb 100644 --- a/web/src/app/providers.tsx +++ b/web/src/app/providers.tsx @@ -5,6 +5,7 @@ import { usePathname } from 'next/navigation'; import { AuthProvider } from '@/lib/auth-context'; import { initTelemetry, trackPageView } from '@/lib/telemetry'; import { initFeatureFlags } from '@/lib/feature-flags'; +import { initDiagnostics } from '@/lib/diagnostics'; import type { ReactNode } from 'react'; export function Providers({ children }: { children: ReactNode }) { @@ -13,6 +14,7 @@ export function Providers({ children }: { children: ReactNode }) { useEffect(() => { initTelemetry(); initFeatureFlags({ platform: 'web' }); + initDiagnostics(); }, []); useEffect(() => { diff --git a/web/src/lib/diagnostics.ts b/web/src/lib/diagnostics.ts new file mode 100644 index 0000000..5e58865 --- /dev/null +++ b/web/src/lib/diagnostics.ts @@ -0,0 +1,48 @@ +// ── Remote Diagnostics Client ───────────────────────────────── +// Delegates to @bytelyst/diagnostics-client shared package. +// Polls platform-service for active debug sessions targeting this install. +// Privacy: only captures console logs + JS errors when a session is active. + +import { DiagnosticsClient } from '@bytelyst/diagnostics-client'; +import { getAuthClient, PRODUCT_ID, getBaseUrl } from './auth-api'; + +function getOrCreateInstallId(): string { + const key = `${PRODUCT_ID}_diag_install_id`; + let id = localStorage.getItem(key); + if (!id) { + id = + typeof crypto?.randomUUID === 'function' + ? crypto.randomUUID() + : Math.random().toString(36).slice(2) + Date.now().toString(36); + localStorage.setItem(key, id); + } + return id; +} + +export function initDiagnostics(): void { + if (typeof window === 'undefined') return; + DiagnosticsClient.getInstance({ + productId: PRODUCT_ID, + anonymousInstallId: getOrCreateInstallId(), + platform: 'web', + channel: 'pwa', + osFamily: 'unknown', + appVersion: process.env.NEXT_PUBLIC_APP_VERSION ?? '0.1.0', + buildNumber: process.env.NEXT_PUBLIC_BUILD_NUMBER ?? '1', + releaseChannel: process.env.NEXT_PUBLIC_RELEASE_CHANNEL ?? 'beta', + serverUrl: getBaseUrl(), + getAuthToken: () => getAuthClient().getAccessToken() ?? undefined, + captureConsole: true, + captureErrors: true, + captureNetwork: false, + pollIntervalMs: 30_000, + }).start(); +} + +export function stopDiagnostics(): void { + try { + DiagnosticsClient.getInstance().stop(); + } catch { + // not initialized + } +}