diff --git a/apps/web/src/context/AppVersion/useAppVersion.tsx b/apps/web/src/context/AppVersion/useAppVersion.tsx index dfd8eb887..053662da6 100644 --- a/apps/web/src/context/AppVersion/useAppVersion.tsx +++ b/apps/web/src/context/AppVersion/useAppVersion.tsx @@ -1,5 +1,5 @@ import { useQuery } from '@tanstack/react-query'; -import { useCallback, useEffect } from 'react'; +import { useCallback, useEffect, useMemo } from 'react'; import { versionGetAppVersion } from '@/api/query_keys/version'; import { Text } from '@/components/ui/typography'; import { useWindowFocus } from '@/hooks/useWindowFocus'; @@ -53,17 +53,6 @@ export const useAppVersion = () => { }; const AppVersionMessage = () => { - // const [countdown, setCountdown] = useState(180); - // useEffect(() => { - // const interval = setInterval(() => { - // setCountdown((prev) => Math.max(prev - 1, 0)); - // if (countdown === 0) { - // window.location.reload(); - // } - // }, 1000); - // return () => clearInterval(interval); - // }, []); - return ( A new version of the app is available. Please refresh the page to get the latest features. @@ -78,3 +67,12 @@ export const useIsVersionChanged = () => { }); return data; }; + +export const useAppVersionMeta = () => { + const { data } = useQuery({ + ...versionGetAppVersion, + select: (data) => data, + notifyOnChangeProps: ['data'], + }); + return useMemo(() => ({ ...data, browserBuild }), [data]); +}; diff --git a/apps/web/src/context/Posthog/BusterPosthogProvider.tsx b/apps/web/src/context/Posthog/BusterPosthogProvider.tsx index 55bba1fe5..31afcc249 100644 --- a/apps/web/src/context/Posthog/BusterPosthogProvider.tsx +++ b/apps/web/src/context/Posthog/BusterPosthogProvider.tsx @@ -2,7 +2,6 @@ import { isServer } from '@tanstack/react-query'; import { ClientOnly } from '@tanstack/react-router'; import type { PostHogConfig } from 'posthog-js'; import React, { type PropsWithChildren, useEffect, useState } from 'react'; -import { useGetUserTeams } from '@/api/buster_rest/users'; import { useGetUserBasicInfo, useGetUserOrganization, @@ -10,10 +9,8 @@ import { import { ComponentErrorCard } from '@/components/features/global/ComponentErrorCard'; import { isDev } from '@/config/dev'; import { env } from '@/env'; -import { useMount } from '@/hooks/useMount'; -import packageJson from '../../../package.json'; +import { useAppVersionMeta } from '../AppVersion/useAppVersion'; -const version = packageJson.version; const POSTHOG_KEY = env.VITE_PUBLIC_POSTHOG_KEY; const DEBUG_POSTHOG = false; @@ -38,9 +35,13 @@ const options: Partial = { session_recording: { recordBody: true, }, + api_host: '/phrp/', + ui_host: 'https://us.posthog.com', + defaults: '2025-05-24', }; const PosthogWrapper: React.FC = ({ children }) => { + const appVersionMeta = useAppVersionMeta(); const user = useGetUserBasicInfo(); const userOrganizations = useGetUserOrganization(); const userOrganizationId = userOrganizations?.id || ''; @@ -60,6 +61,7 @@ const PosthogWrapper: React.FC = ({ children }) => { import('posthog-js'), import('posthog-js/react'), ]); + console.log('posthog', posthog); setPosthogModules({ posthog, PostHogProvider }); } catch (error) { @@ -89,8 +91,34 @@ const PosthogWrapper: React.FC = ({ children }) => { organization: userOrganizations, }); posthog.group(userOrganizationId, userOrganizationName); + + // Register app version metadata to be included with all events + if (appVersionMeta) { + posthog.register({ + app_version: appVersionMeta.buildId, + browser_build: appVersionMeta.browserBuild, + server_build: appVersionMeta.buildId, + version_changed: appVersionMeta.buildId !== appVersionMeta.browserBuild, + }); + } } - }, [user?.id, userOrganizationId, userOrganizationName, posthogModules]); + }, [user?.id, userOrganizationId, userOrganizationName, posthogModules, appVersionMeta]); + + // Update app version metadata when it changes after PostHog is initialized + useEffect(() => { + if (posthogModules?.posthog && appVersionMeta) { + const { posthog } = posthogModules; + + if (posthog.__loaded) { + posthog.register({ + app_version: appVersionMeta.buildId, + browser_build: appVersionMeta.browserBuild, + server_build: appVersionMeta.buildId, + version_changed: appVersionMeta.buildId !== appVersionMeta.browserBuild, + }); + } + } + }, [appVersionMeta, posthogModules]); // Show children while loading or if modules failed to load if (isLoading || !posthogModules) { diff --git a/apps/web/src/routeTree.gen.ts b/apps/web/src/routeTree.gen.ts index f0448c41e..5b2113d49 100644 --- a/apps/web/src/routeTree.gen.ts +++ b/apps/web/src/routeTree.gen.ts @@ -22,6 +22,7 @@ import { Route as InfoGettingStartedRouteImport } from './routes/info/getting-st import { Route as AuthResetPasswordRouteImport } from './routes/auth.reset-password' import { Route as AuthLogoutRouteImport } from './routes/auth.logout' import { Route as AuthLoginRouteImport } from './routes/auth.login' +import { Route as AppThrowRouteImport } from './routes/app.throw' import { Route as AppSettingsRouteImport } from './routes/app/_settings' import { Route as AppAppRouteImport } from './routes/app/_app' import { Route as EmbedReportReportIdRouteImport } from './routes/embed/report.$reportId' @@ -212,6 +213,11 @@ const AuthLoginRoute = AuthLoginRouteImport.update({ path: '/login', getParentRoute: () => AuthRoute, } as any) +const AppThrowRoute = AppThrowRouteImport.update({ + id: '/throw', + path: '/throw', + getParentRoute: () => AppRoute, +} as any) const AppSettingsRoute = AppSettingsRouteImport.update({ id: '/_settings', getParentRoute: () => AppRoute, @@ -939,6 +945,7 @@ export interface FileRoutesByFullPath { '/auth': typeof AuthRouteWithChildren '/embed': typeof EmbedRouteWithChildren '/healthcheck': typeof HealthcheckRoute + '/app/throw': typeof AppThrowRoute '/auth/login': typeof AuthLoginRoute '/auth/logout': typeof AuthLogoutRoute '/auth/reset-password': typeof AuthResetPasswordRoute @@ -1048,6 +1055,7 @@ export interface FileRoutesByTo { '/embed': typeof EmbedRouteWithChildren '/healthcheck': typeof HealthcheckRoute '/app': typeof AppSettingsRestricted_layoutAdmin_onlyRouteWithChildren + '/app/throw': typeof AppThrowRoute '/auth/login': typeof AuthLoginRoute '/auth/logout': typeof AuthLogoutRoute '/auth/reset-password': typeof AuthResetPasswordRoute @@ -1142,6 +1150,7 @@ export interface FileRoutesById { '/healthcheck': typeof HealthcheckRoute '/app/_app': typeof AppAppRouteWithChildren '/app/_settings': typeof AppSettingsRouteWithChildren + '/app/throw': typeof AppThrowRoute '/auth/login': typeof AuthLoginRoute '/auth/logout': typeof AuthLogoutRoute '/auth/reset-password': typeof AuthResetPasswordRoute @@ -1267,6 +1276,7 @@ export interface FileRouteTypes { | '/auth' | '/embed' | '/healthcheck' + | '/app/throw' | '/auth/login' | '/auth/logout' | '/auth/reset-password' @@ -1376,6 +1386,7 @@ export interface FileRouteTypes { | '/embed' | '/healthcheck' | '/app' + | '/app/throw' | '/auth/login' | '/auth/logout' | '/auth/reset-password' @@ -1469,6 +1480,7 @@ export interface FileRouteTypes { | '/healthcheck' | '/app/_app' | '/app/_settings' + | '/app/throw' | '/auth/login' | '/auth/logout' | '/auth/reset-password' @@ -1689,6 +1701,13 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof AuthLoginRouteImport parentRoute: typeof AuthRoute } + '/app/throw': { + id: '/app/throw' + path: '/throw' + fullPath: '/app/throw' + preLoaderRoute: typeof AppThrowRouteImport + parentRoute: typeof AppRoute + } '/app/_settings': { id: '/app/_settings' path: '' @@ -3215,12 +3234,14 @@ const AppSettingsRouteWithChildren = AppSettingsRoute._addFileChildren( interface AppRouteChildren { AppAppRoute: typeof AppAppRouteWithChildren AppSettingsRoute: typeof AppSettingsRouteWithChildren + AppThrowRoute: typeof AppThrowRoute AppIndexRoute: typeof AppIndexRoute } const AppRouteChildren: AppRouteChildren = { AppAppRoute: AppAppRouteWithChildren, AppSettingsRoute: AppSettingsRouteWithChildren, + AppThrowRoute: AppThrowRoute, AppIndexRoute: AppIndexRoute, } diff --git a/apps/web/src/routes/app.throw.tsx b/apps/web/src/routes/app.throw.tsx new file mode 100644 index 000000000..42dd2b42d --- /dev/null +++ b/apps/web/src/routes/app.throw.tsx @@ -0,0 +1,23 @@ +import { createFileRoute } from '@tanstack/react-router'; +import { useState } from 'react'; +import { useMount } from '../hooks/useMount'; + +export const Route = createFileRoute('/app/throw')({ + component: RouteComponent, +}); + +function RouteComponent() { + const [throwError, setThrowError] = useState(false); + + useMount(() => { + setTimeout(() => { + setThrowError(true); + }, 1000); + }); + + if (throwError) { + throw new Error('Nate is testing this error'); + } + + return
Hello "/app/throw"! {throwError ? 'Throwing error' : 'Not throwing error'}
; +} diff --git a/apps/web/vercel.json b/apps/web/vercel.json new file mode 100644 index 000000000..24bd1eaaa --- /dev/null +++ b/apps/web/vercel.json @@ -0,0 +1,12 @@ +{ + "rewrites": [ + { + "source": "/phrp/static/(.*)", + "destination": "https://us-assets.i.posthog.com/static/$1" + }, + { + "source": "/phrp/(.*)", + "destination": "https://us.i.posthog.com/$1" + } + ] +} diff --git a/packages/ai/src/llm/providers/gateway.ts b/packages/ai/src/llm/providers/gateway.ts index 4be511723..e5b32828a 100644 --- a/packages/ai/src/llm/providers/gateway.ts +++ b/packages/ai/src/llm/providers/gateway.ts @@ -13,11 +13,11 @@ export const DEFAULT_ANTHROPIC_OPTIONS = { export const DEFAULT_OPENAI_OPTIONS = { gateway: { order: ['openai'], - openai: { - parallelToolCalls: false, - reasoningEffort: 'minimal', - verbosity: 'low', - }, + }, + openai: { + parallelToolCalls: false, + reasoningEffort: 'minimal', + verbosity: 'low', }, };