/** * Main Entry Point — deploy trigger: smoke test with pre-installed Chromium * * Clean provider setup using our own auth and workspace management. * NO Bird dependencies (apikit, shared/auth). */ // ============================================================================= // STYLES - Must be imported before components for Tailwind to work // ============================================================================= import "@bird-ai/ui-agent/style-core.css" // ============================================================================= // BUILD INFO — accessible via window.__BUILD_INFO__ in browser devtools // ============================================================================= if (typeof window !== "undefined") { ;(window as unknown as Record).__BUILD_INFO__ = Object.freeze({ commit: __BUILD_COMMIT__, buildTime: __BUILD_TIME__, env: import.meta.env.MODE, }) } // ============================================================================= // ERROR REPORTING - Initialize early to capture all errors // ============================================================================= import { errorReporter } from "./lib/error-reporter" // Defer Sentry to after first paint — removes ~300KB from critical path if (typeof window !== "undefined") { const initSentryDeferred = () => import("./lib/sentry").then((m) => m.initSentry()) if ("requestIdleCallback" in window) { requestIdleCallback(() => initSentryDeferred(), { timeout: 3000 }) } else { setTimeout(() => initSentryDeferred(), 1) } } // Defer heavy feature CSS (editor prose, syntax highlighting, slide deck, xyflow) // to after first paint — loaded via dynamic import which Vite resolves to the hashed filename. if (typeof window !== "undefined") { const loadFeatureCSS = () => import("@bird-ai/ui-agent/style-artifacts.css") if ("requestIdleCallback" in window) { requestIdleCallback(() => loadFeatureCSS(), { timeout: 3000 }) } else { setTimeout(() => loadFeatureCSS(), 1) } } // Initialize internal error reporting errorReporter.init() // ============================================================================= // REACT & PROVIDERS // ============================================================================= import { createRoot } from "react-dom/client" import { BrowserRouter } from "react-router" import { QueryClient, QueryClientProvider } from "@tanstack/react-query" import { IntlProvider } from "react-intl" import { useDocumentLocale } from "./hooks/useDocumentLocale" import { StrictMode, useState, useEffect, type FC, type ReactNode } from "react" import enMessages from "./locales/en.json" import { LocalAuthProvider } from "./auth" import { AnonymousProvider } from "./context/AnonymousContext" import { WorkspaceProvider } from "./context/WorkspaceContext" import { PermissionsProvider } from "./context/PermissionsContext" import { GlobalErrorBoundary } from "./components/GlobalErrorBoundary" import { ActionIntentProvider } from "./context/ActionIntentContext" import { App } from "./App" import { SUPPORTED_LOCALES } from "./lib/locale" import { initWebVitals } from "./lib/web-vitals" if ("requestIdleCallback" in window) { requestIdleCallback(() => initWebVitals(), { timeout: 5000 }) } else { setTimeout(() => initWebVitals(), 100) } if ("serviceWorker" in navigator && import.meta.env.PROD) { const registerSW = () => { navigator.serviceWorker.register("/sw.js", { scope: "/" }).catch(() => {}) } if ("requestIdleCallback" in window) { requestIdleCallback(registerSW, { timeout: 5000 }) } else { setTimeout(registerSW, 1) } } // Strip the cache-busting _reload parameter injected by ArtifactErrorFallback when // a chunk-load error forces a hard navigation to bypass stale HTTP caches. // This runs before React mounts so the URL is clean before any route-matching occurs. ;(() => { try { const url = new URL(window.location.href) if (url.searchParams.has("_reload")) { url.searchParams.delete("_reload") window.history.replaceState(null, "", url.toString()) } } catch { // ignore URL parsing errors (e.g. in unusual browser environments) } })() // Detect locale prefix from URL so React Router strips it via basename. // CloudFront redirects / → /{locale}/ for SEO; the SPA must be aware. const LOCALE_SLUGS_LOWER = new Set(SUPPORTED_LOCALES.map((l) => l.toLowerCase())) function detectLocaleBasename(): string | undefined { const match = window.location.pathname.match(/^\/([a-z]{2}(?:-[a-z]+?)?)(?:\/|$)/) if (match && LOCALE_SLUGS_LOWER.has(match[1])) { return `/${match[1]}` } return undefined } const localeBasename = detectLocaleBasename() // ============================================================================= // QUERY CLIENT // ============================================================================= const queryClient = new QueryClient({ defaultOptions: { queries: { staleTime: 5 * 60 * 1000, // 5 minutes retry: 1, refetchOnWindowFocus: false, }, }, }) // Note: QueryClient is exposed via React context (QueryClientProvider) instead of window // to prevent untrusted scripts from accessing/mutating cached data // ============================================================================= // LOCALE PROVIDER — dynamic locale detection + message loading // ============================================================================= const LocaleProvider: FC<{ children: ReactNode }> = ({ children }) => { const locale = useDocumentLocale() const [messages, setMessages] = useState>( enMessages as Record ) useEffect(() => { if (locale === "en") { setMessages(enMessages as Record) return } // Validate locale against allowlist before dynamic import to prevent path traversal if (!SUPPORTED_LOCALES.includes(locale)) { setMessages(enMessages as Record) return } import(`./locales/${locale}.json`) .then((mod) => setMessages((mod.default ?? mod) as Record)) .catch(() => setMessages(enMessages as Record)) }, [locale]) return ( {children} ) } // ============================================================================= // RENDER // ============================================================================= createRoot(document.getElementById("root")!).render( ) // Force rebuild Sat Jan 17 13:25:38 CET 2026 // Trigger build 1768653986 // Rebuild with correct role 1768654061 // Force rebuild 1768654984 // Rebuild with cleared Turbo cache 1768655026 // Fix all auth paths 1768655570 // Complete auth fix 1768655607 // Build trigger: Sat Jan 17 23:51:46 CET 2026