From 2b040664cb7dd643a6b2546d36c97df5854b64e7 Mon Sep 17 00:00:00 2001 From: Enrico Ros Date: Wed, 21 Feb 2024 02:10:39 -0800 Subject: [PATCH] Use /info/debug to export App and Browser info for debugging --- pages/info/debug.tsx | 164 +++++++++++++++++++++++++++++++++ src/modules/llms/store-llms.ts | 5 + 2 files changed, 169 insertions(+) create mode 100644 pages/info/debug.tsx diff --git a/pages/info/debug.tsx b/pages/info/debug.tsx new file mode 100644 index 000000000..3c8c06bfb --- /dev/null +++ b/pages/info/debug.tsx @@ -0,0 +1,164 @@ +import * as React from 'react'; +import { fileSave } from 'browser-fs-access'; + +import { Box, Button, Card, CardContent, Typography } from '@mui/joy'; +import DownloadIcon from '@mui/icons-material/Download'; + +import { AppPlaceholder } from '../../src/apps/AppPlaceholder'; + +import { backendCaps } from '~/modules/backend/state-backend'; + +import { withLayout } from '~/common/layout/withLayout'; + + +// app config +import { Brand } from '~/common/app.config'; +import { ROUTE_APP_CHAT, ROUTE_INDEX } from '~/common/app.routes'; + +// apps access +import { incrementalNewsVersion } from '../../src/apps/news/news.version'; + +// capabilities access +import { useCapabilityBrowserSpeechRecognition, useCapabilityElevenLabs, useCapabilityTextToImage } from '~/common/components/useCapabilities'; + +// stores access +import { getLLMsDebugInfo } from '~/modules/llms/store-llms'; +import { useAppStateStore } from '~/common/state/store-appstate'; +import { useChatStore } from '~/common/state/store-chats'; +import { useFolderStore } from '~/common/state/store-folders'; +import { useUXLabsStore } from '~/common/state/store-ux-labs'; + +// utils access +import { clientHostName, isChromeDesktop, isFirefox, isIPhoneUser, isMacUser, isPwa, isVercelFromBackend, isVercelFromFrontend } from '~/common/util/pwaUtils'; +import { supportsClipboardRead } from '~/common/util/clipboardUtils'; +import { supportsScreenCapture } from '~/common/util/screenCaptureUtils'; + + +function DebugCard(props: { title: string, children: React.ReactNode }) { + return ( + + + {props.title} + + {props.children} + + ); +} + +function prettifyJsonString(jsonString: string, deleteChars: number, removeDoubleQuotes: boolean, removeTrailComma: boolean): string { + return jsonString.split('\n').map(l => { + if (deleteChars > 0) + l = l.substring(deleteChars); + if (removeDoubleQuotes) + l = l.replaceAll('\"', ''); + if (removeTrailComma && l.endsWith(',')) + l = l.substring(0, l.length - 1); + return l; + }).join('\n').trim(); +} + +function DebugJsonCard(props: { title: string, data: any }) { + return ( + + + {prettifyJsonString(JSON.stringify(props.data, null, 2), 2, true, true)} + + + ); +} + + +function AppDebug() { + + // state + const [saved, setSaved] = React.useState(false); + + // external state + const backendCapabilities = backendCaps(); + const chatsCount = useChatStore.getState().conversations?.length; + const uxLabsExperiments = Object.entries(useUXLabsStore.getState()).filter(([_k, v]) => v === true).map(([k, _]) => k).join(', '); + const { folders, enableFolders } = useFolderStore.getState(); + const { lastSeenNewsVersion, usageCount } = useAppStateStore.getState(); + + + // derived state + const cClient = { + // isBrowser, + isChromeDesktop, + isFirefox, + isIPhone: isIPhoneUser, + isMac: isMacUser, + isPWA: isPwa(), + supportsClipboardPaste: supportsClipboardRead, + supportsScreenCapture, + }; + const cProduct = { + capabilities: { + mic: useCapabilityBrowserSpeechRecognition(), + elevenLabs: useCapabilityElevenLabs(), + textToImage: useCapabilityTextToImage(), + }, + models: getLLMsDebugInfo(), + state: { + chatsCount, + foldersCount: folders?.length, + foldersEnabled: enableFolders, + newsCurrent: incrementalNewsVersion, + newsSeen: lastSeenNewsVersion, + labsActive: uxLabsExperiments, + reloads: usageCount, + }, + }; + const cBackend = { + configuration: backendCapabilities, + deployment: { + home: Brand.URIs.Home, + hostName: clientHostName(), + isVercelFromBackend, + isVercelFromFrontend, + routeIndex: ROUTE_INDEX, + routeChat: ROUTE_APP_CHAT, + }, + }; + + const handleDownload = async () => { + fileSave( + new Blob([JSON.stringify({ client: cClient, agi: cProduct, backend: cBackend }, null, 2)], { type: 'application/json' }), + { fileName: `big-agi-debug-${new Date().toISOString().replace(/:/g, '-')}.json`, extensions: ['.json'] }, + ) + .then(() => setSaved(true)) + .catch(e => console.error('Error saving debug.json', e)); + }; + + return ( + + + + + + + + + + + + + ); +} + + +export default function DebugPage() { + return withLayout({ type: 'plain' }, ); +}; \ No newline at end of file diff --git a/src/modules/llms/store-llms.ts b/src/modules/llms/store-llms.ts index 2e6e7356e..f4b7c7535 100644 --- a/src/modules/llms/store-llms.ts +++ b/src/modules/llms/store-llms.ts @@ -342,4 +342,9 @@ export function useChatLLM() { const chatLLM = chatLLMId ? state.llms.find(llm => llm.id === chatLLMId) ?? null : null; return { chatLLM }; }, shallow); +} + +export function getLLMsDebugInfo() { + const { llms, sources, chatLLMId, fastLLMId, funcLLMId } = useModelsStore.getState(); + return { sources: sources.length, llmsCount: llms.length, chatId: chatLLMId, fastId: fastLLMId, funcId: funcLLMId }; } \ No newline at end of file