) : (
@@ -126,13 +164,17 @@ export default function EventLogsTab() {
key={index}
className="text-sm mb-3 font-mono border-b border-bolt-elements-borderColor pb-2 last:border-0"
>
-
-
[{log.level.toUpperCase()}]
-
{new Date(log.timestamp).toLocaleString()}
-
{log.message}
+
+
+ [{log.level.toUpperCase()}]
+
+
+ {new Date(log.timestamp).toLocaleString()}
+
+ {log.message}
{log.details && (
-
+
{JSON.stringify(log.details, null, 2)}
)}
diff --git a/app/components/settings/providers/ProvidersTab.tsx b/app/components/settings/providers/ProvidersTab.tsx
index edcf6f9..0efbc66 100644
--- a/app/components/settings/providers/ProvidersTab.tsx
+++ b/app/components/settings/providers/ProvidersTab.tsx
@@ -51,11 +51,7 @@ export default function ProvidersTab() {
>
-
+
{provider.name}
>({});
- showLogs = atom(false);
+ showLogs = atom(true);
constructor() {
// Load saved logs from cookies on initialization
From b16aab1f167d91903592e33357ae38e304ca7f65 Mon Sep 17 00:00:00 2001
From: Stijnus <72551117+Stijnus@users.noreply.github.com>
Date: Fri, 13 Dec 2024 09:17:35 +0100
Subject: [PATCH 04/14] Update debug tab to check against fork
---
app/components/settings/debug/DebugTab.tsx | 511 ++++++++++++++++--
.../settings/event-logs/EventLogsTab.tsx | 28 +-
app/types/global.d.ts | 8 +
3 files changed, 500 insertions(+), 47 deletions(-)
diff --git a/app/components/settings/debug/DebugTab.tsx b/app/components/settings/debug/DebugTab.tsx
index 7a84ec1..f37d1d4 100644
--- a/app/components/settings/debug/DebugTab.tsx
+++ b/app/components/settings/debug/DebugTab.tsx
@@ -2,68 +2,493 @@ import React, { useCallback, useEffect, useState } from 'react';
import { useSettings } from '~/lib/hooks/useSettings';
import commit from '~/commit.json';
-const versionHash = commit.commit; // Get the version hash from commit.json
+interface ProviderStatus {
+ name: string;
+ enabled: boolean;
+ isLocal: boolean;
+ isRunning: boolean | null;
+ error?: string;
+ lastChecked: Date;
+ responseTime?: number;
+ url: string | null;
+}
+
+interface SystemInfo {
+ os: string;
+ browser: string;
+ screen: string;
+ language: string;
+ timezone: string;
+ memory: string;
+ cores: number;
+}
+
+interface IProviderConfig {
+ name: string;
+ settings: {
+ enabled: boolean;
+ };
+}
+
+const LOCAL_PROVIDERS = ['Ollama', 'LMStudio', 'OpenAILike'];
+const versionHash = commit.commit;
+const GITHUB_URLS = {
+ original: 'https://api.github.com/repos/Stijnus/bolt.new-any-llm/commits/main',
+ fork: 'https://api.github.com/repos/Stijnus/bolt.new-any-llm/commits/main',
+};
+
+function getSystemInfo(): SystemInfo {
+ const formatBytes = (bytes: number): string => {
+ if (bytes === 0) {
+ return '0 Bytes';
+ }
+
+ const k = 1024;
+ const sizes = ['Bytes', 'KB', 'MB', 'GB'];
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
+
+ return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
+ };
+
+ return {
+ os: navigator.platform,
+ browser: navigator.userAgent.split(' ').slice(-1)[0],
+ screen: `${window.screen.width}x${window.screen.height}`,
+ language: navigator.language,
+ timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
+ memory: formatBytes(performance?.memory?.jsHeapSizeLimit || 0),
+ cores: navigator.hardwareConcurrency || 0,
+ };
+}
+
+const checkProviderStatus = async (url: string | null, providerName: string): Promise => {
+ if (!url) {
+ console.log(`[Debug] No URL provided for ${providerName}`);
+ return {
+ name: providerName,
+ enabled: false,
+ isLocal: true,
+ isRunning: false,
+ error: 'No URL configured',
+ lastChecked: new Date(),
+ url: null,
+ };
+ }
+
+ console.log(`[Debug] Checking status for ${providerName} at ${url}`);
+
+ const startTime = performance.now();
+
+ try {
+ if (providerName.toLowerCase() === 'ollama') {
+ // Special check for Ollama root endpoint
+ try {
+ console.log(`[Debug] Checking Ollama root endpoint: ${url}`);
+
+ const controller = new AbortController();
+ const timeoutId = setTimeout(() => controller.abort(), 5000); // 5 second timeout
+
+ const response = await fetch(url, {
+ signal: controller.signal,
+ headers: {
+ Accept: 'text/plain,application/json',
+ },
+ });
+ clearTimeout(timeoutId);
+
+ const text = await response.text();
+ console.log(`[Debug] Ollama root response:`, text);
+
+ if (text.includes('Ollama is running')) {
+ console.log(`[Debug] Ollama running confirmed via root endpoint`);
+ return {
+ name: providerName,
+ enabled: false,
+ isLocal: true,
+ isRunning: true,
+ lastChecked: new Date(),
+ responseTime: performance.now() - startTime,
+ url,
+ };
+ }
+ } catch (error) {
+ console.log(`[Debug] Ollama root check failed:`, error);
+
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
+
+ if (errorMessage.includes('aborted')) {
+ return {
+ name: providerName,
+ enabled: false,
+ isLocal: true,
+ isRunning: false,
+ error: 'Connection timeout',
+ lastChecked: new Date(),
+ responseTime: performance.now() - startTime,
+ url,
+ };
+ }
+ }
+ }
+
+ // Try different endpoints based on provider
+ const checkUrls = [`${url}/api/health`, `${url}/v1/models`];
+ console.log(`[Debug] Checking additional endpoints:`, checkUrls);
+
+ const results = await Promise.all(
+ checkUrls.map(async (checkUrl) => {
+ try {
+ console.log(`[Debug] Trying endpoint: ${checkUrl}`);
+
+ const controller = new AbortController();
+ const timeoutId = setTimeout(() => controller.abort(), 5000);
+
+ const response = await fetch(checkUrl, {
+ signal: controller.signal,
+ headers: {
+ Accept: 'application/json',
+ },
+ });
+ clearTimeout(timeoutId);
+
+ const ok = response.ok;
+ console.log(`[Debug] Endpoint ${checkUrl} response:`, ok);
+
+ if (ok) {
+ try {
+ const data = await response.json();
+ console.log(`[Debug] Endpoint ${checkUrl} data:`, data);
+ } catch {
+ console.log(`[Debug] Could not parse JSON from ${checkUrl}`);
+ }
+ }
+
+ return ok;
+ } catch (error) {
+ console.log(`[Debug] Endpoint ${checkUrl} failed:`, error);
+ return false;
+ }
+ }),
+ );
+
+ const isRunning = results.some((result) => result);
+ console.log(`[Debug] Final status for ${providerName}:`, isRunning);
+
+ return {
+ name: providerName,
+ enabled: false,
+ isLocal: true,
+ isRunning,
+ lastChecked: new Date(),
+ responseTime: performance.now() - startTime,
+ url,
+ };
+ } catch (error) {
+ console.log(`[Debug] Provider check failed for ${providerName}:`, error);
+ return {
+ name: providerName,
+ enabled: false,
+ isLocal: true,
+ isRunning: false,
+ error: error instanceof Error ? error.message : 'Unknown error',
+ lastChecked: new Date(),
+ responseTime: performance.now() - startTime,
+ url,
+ };
+ }
+};
export default function DebugTab() {
const { providers } = useSettings();
- const [activeProviders, setActiveProviders] = useState([]);
+ const [activeProviders, setActiveProviders] = useState([]);
+ const [updateMessage, setUpdateMessage] = useState('');
+ const [systemInfo] = useState(getSystemInfo());
+ const [isCheckingUpdate, setIsCheckingUpdate] = useState(false);
+
+ const updateProviderStatuses = async () => {
+ if (!providers) {
+ return;
+ }
+
+ try {
+ const entries = Object.entries(providers) as [string, IProviderConfig][];
+ const statuses = entries
+ .filter(([, provider]) => LOCAL_PROVIDERS.includes(provider.name))
+ .map(async ([, provider]) => {
+ const envVarName =
+ provider.name.toLowerCase() === 'ollama'
+ ? 'OLLAMA_API_BASE_URL'
+ : provider.name.toLowerCase() === 'lmstudio'
+ ? 'LMSTUDIO_API_BASE_URL'
+ : `REACT_APP_${provider.name.toUpperCase()}_URL`;
+
+ // Access environment variables through import.meta.env
+ const url = import.meta.env[envVarName] || null;
+ console.log(`[Debug] Using URL for ${provider.name}:`, url, `(from ${envVarName})`);
+
+ const status = await checkProviderStatus(url, provider.name);
+
+ return {
+ ...status,
+ enabled: provider.settings.enabled ?? false,
+ };
+ });
+
+ Promise.all(statuses).then(setActiveProviders);
+ } catch (error) {
+ console.error('[Debug] Failed to update provider statuses:', error);
+ }
+ };
+
useEffect(() => {
- setActiveProviders(
- Object.entries(providers)
- .filter(([_key, provider]) => provider.settings.enabled)
- .map(([_key, provider]) => provider.name),
- );
+ updateProviderStatuses();
+
+ const interval = setInterval(updateProviderStatuses, 30000);
+
+ return () => clearInterval(interval);
}, [providers]);
+ const handleCheckForUpdate = useCallback(async () => {
+ if (isCheckingUpdate) {
+ return;
+ }
+
+ try {
+ setIsCheckingUpdate(true);
+ setUpdateMessage('Checking for updates...');
+
+ const [originalResponse, forkResponse] = await Promise.all([
+ fetch(GITHUB_URLS.original),
+ fetch(GITHUB_URLS.fork),
+ ]);
+
+ if (!originalResponse.ok || !forkResponse.ok) {
+ throw new Error('Failed to fetch repository information');
+ }
+
+ const [originalData, forkData] = await Promise.all([
+ originalResponse.json() as Promise<{ sha: string }>,
+ forkResponse.json() as Promise<{ sha: string }>,
+ ]);
+
+ const originalCommitHash = originalData.sha;
+ const forkCommitHash = forkData.sha;
+ const isForked = versionHash === forkCommitHash && forkCommitHash !== originalCommitHash;
+
+ if (originalCommitHash !== versionHash) {
+ setUpdateMessage(
+ `Update available from original repository!\n` +
+ `Current: ${versionHash.slice(0, 7)}${isForked ? ' (forked)' : ''}\n` +
+ `Latest: ${originalCommitHash.slice(0, 7)}`,
+ );
+ } else {
+ setUpdateMessage('You are on the latest version from the original repository');
+ }
+ } catch (error) {
+ setUpdateMessage('Failed to check for updates');
+ console.error('[Debug] Failed to check for updates:', error);
+ } finally {
+ setIsCheckingUpdate(false);
+ }
+ }, [isCheckingUpdate]);
+
const handleCopyToClipboard = useCallback(() => {
const debugInfo = {
- OS: navigator.platform,
- Browser: navigator.userAgent,
- ActiveFeatures: activeProviders,
- BaseURLs: {
- Ollama: process.env.REACT_APP_OLLAMA_URL,
- OpenAI: process.env.REACT_APP_OPENAI_URL,
- LMStudio: process.env.REACT_APP_LM_STUDIO_URL,
- },
+ System: systemInfo,
+ Providers: activeProviders.map((provider) => ({
+ name: provider.name,
+ enabled: provider.enabled,
+ isLocal: provider.isLocal,
+ running: provider.isRunning,
+ error: provider.error,
+ lastChecked: provider.lastChecked,
+ responseTime: provider.responseTime,
+ url: provider.url,
+ })),
Version: versionHash,
+ Timestamp: new Date().toISOString(),
};
navigator.clipboard.writeText(JSON.stringify(debugInfo, null, 2)).then(() => {
alert('Debug information copied to clipboard!');
});
- }, [providers]);
+ }, [activeProviders, systemInfo]);
return (
-
-
Debug Tab
-
+
+
+
Debug Information
+
+
+
+
+
-
System Information
-
OS: {navigator.platform}
-
Browser: {navigator.userAgent}
+ {updateMessage && (
+
+
{updateMessage}
+ {updateMessage.includes('Update available') && (
+
+
To update:
+
+ -
+ Pull the latest changes:{' '}
+
git pull upstream main
+
+ -
+ Install any new dependencies:{' '}
+
npm install
+
+ - Restart the application
+
+
+ )}
+
+ )}
-
Active Features
-
- {activeProviders.map((name) => (
- -
- {name}
-
- ))}
-
+
+
+
System Information
+
+
+
+
Operating System
+
{systemInfo.os}
+
+
+
Browser
+
{systemInfo.browser}
+
+
+
Screen Resolution
+
{systemInfo.screen}
+
+
+
Language
+
{systemInfo.language}
+
+
+
Timezone
+
{systemInfo.timezone}
+
+
+
CPU Cores
+
{systemInfo.cores}
+
+
+
+
Version
+
+ {versionHash.slice(0, 7)}
+
+ ({new Date().toLocaleDateString()})
+
+
+
+
+
- Base URLs
-
- - Ollama: {process.env.REACT_APP_OLLAMA_URL}
- - OpenAI: {process.env.REACT_APP_OPENAI_URL}
- - LM Studio: {process.env.REACT_APP_LM_STUDIO_URL}
-
+
+
Local LLM Status
+
+
+ {activeProviders.map((provider) => (
+
+
+
+
+
+
{provider.name}
+ {provider.url && (
+
+ {provider.url}
+
+ )}
+
+
+
+
+ {provider.enabled ? 'Enabled' : 'Disabled'}
+
+ {provider.enabled && (
+
+ {provider.isRunning ? 'Running' : 'Not Running'}
+
+ )}
+
+
-
Version Information
-
Version Hash: {versionHash}
+
+ {/* Status Details */}
+
+
+ Last checked: {new Date(provider.lastChecked).toLocaleTimeString()}
+
+ {provider.responseTime && (
+
+ Response time: {Math.round(provider.responseTime)}ms
+
+ )}
+
+
+ {/* Error Message */}
+ {provider.error && (
+
+ Error: {provider.error}
+
+ )}
+
+ {/* Connection Info */}
+ {provider.url && (
+
+
Endpoints checked:
+
+ - {provider.url} (root)
+ - {provider.url}/api/health
+ - {provider.url}/v1/models
+
+
+ )}
+
+
+ ))}
+ {activeProviders.length === 0 && (
+
No local LLMs configured
+ )}
+
+
+
+
);
}
diff --git a/app/components/settings/event-logs/EventLogsTab.tsx b/app/components/settings/event-logs/EventLogsTab.tsx
index be2a2d2..55c3d66 100644
--- a/app/components/settings/event-logs/EventLogsTab.tsx
+++ b/app/components/settings/event-logs/EventLogsTab.tsx
@@ -32,10 +32,30 @@ export default function EventLogsTab() {
}, []);
useEffect(() => {
- // Add some initial logs for testing
- logStore.logSystem('System started', { version: '1.0.0' });
- logStore.logWarning('High memory usage detected', { memoryUsage: '85%' });
- logStore.logError('Failed to connect to provider', new Error('Connection timeout'), { provider: 'OpenAI' });
+ // System info logs
+ logStore.logSystem('Application initialized', {
+ version: process.env.NEXT_PUBLIC_APP_VERSION,
+ environment: process.env.NODE_ENV,
+ });
+
+ // Debug logs for system state
+ logStore.logDebug('System configuration loaded', {
+ runtime: 'Next.js',
+ features: ['AI Chat', 'Event Logging'],
+ });
+
+ // Warning logs for potential issues
+ logStore.logWarning('Resource usage threshold approaching', {
+ memoryUsage: '75%',
+ cpuLoad: '60%',
+ });
+
+ // Error logs with detailed context
+ logStore.logError('API connection failed', new Error('Connection timeout'), {
+ endpoint: '/api/chat',
+ retryCount: 3,
+ lastAttempt: new Date().toISOString(),
+ });
}, []);
useEffect(() => {
diff --git a/app/types/global.d.ts b/app/types/global.d.ts
index 6a03036..e0ad664 100644
--- a/app/types/global.d.ts
+++ b/app/types/global.d.ts
@@ -3,3 +3,11 @@ interface Window {
webkitSpeechRecognition: typeof SpeechRecognition;
SpeechRecognition: typeof SpeechRecognition;
}
+
+interface Performance {
+ memory?: {
+ jsHeapSizeLimit: number;
+ totalJSHeapSize: number;
+ usedJSHeapSize: number;
+ };
+}
From b1a3e3993ee013b58cee6f02f2e05429d3b3a592 Mon Sep 17 00:00:00 2001
From: Stijnus <72551117+Stijnus@users.noreply.github.com>
Date: Fri, 13 Dec 2024 09:22:21 +0100
Subject: [PATCH 05/14] debug fixes
---
.husky/pre-commit | 5 +++++
app/commit.json | 2 +-
2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/.husky/pre-commit b/.husky/pre-commit
index 1aab67d..45ed10d 100644
--- a/.husky/pre-commit
+++ b/.husky/pre-commit
@@ -23,4 +23,9 @@ if ! pnpm lint; then
exit 1
fi
+# Update commit.json with the latest commit hash
+COMMIT_HASH=$(git rev-parse HEAD)
+echo "{ \"commit\": \"$COMMIT_HASH\" }" > app/commit.json
+git add app/commit.json
+
echo "👍 All good! Committing changes..."
diff --git a/app/commit.json b/app/commit.json
index 64e78b6..45cf76f 100644
--- a/app/commit.json
+++ b/app/commit.json
@@ -1 +1 @@
-{ "commit": "4b36601061652ec2ec3cb1f1d5c7cc5649690bbb" }
+{ "commit": "b16aab1f167d91903592e33357ae38e304ca7f65" }
From c0c12752267586ba61fdb423a9644a2dbb8ba04c Mon Sep 17 00:00:00 2001
From: Stijnus
Date: Fri, 13 Dec 2024 11:33:29 +0100
Subject: [PATCH 06/14] minor bug fixes
---
.husky/pre-commit | 36 +-
app/commit.json | 2 +-
app/components/settings/debug/DebugTab.tsx | 6 +-
package-lock.json | 26039 +++++++++++++++++++
package.json | 13 +-
pnpm-lock.yaml | 681 +-
6 files changed, 26419 insertions(+), 358 deletions(-)
create mode 100644 package-lock.json
diff --git a/.husky/pre-commit b/.husky/pre-commit
index 45ed10d..b95e00d 100644
--- a/.husky/pre-commit
+++ b/.husky/pre-commit
@@ -2,30 +2,42 @@
echo "🔍 Running pre-commit hook to check the code looks good... 🔍"
+# Load NVM if available (useful for managing Node.js versions)
export NVM_DIR="$HOME/.nvm"
-[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # Load nvm if you're using i
+[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
-echo "Running typecheck..."
-which pnpm
-
-if ! pnpm typecheck; then
- echo "❌ Type checking failed! Please review TypeScript types."
- echo "Once you're done, don't forget to add your changes to the commit! 🚀"
- echo "Typecheck exit code: $?"
- exit 1
+# Ensure `pnpm` is available
+echo "Checking if pnpm is available..."
+if ! command -v pnpm >/dev/null 2>&1; then
+ echo "❌ pnpm not found! Please ensure pnpm is installed and available in PATH."
+ exit 1
fi
+# Run typecheck
+echo "Running typecheck..."
+if ! pnpm typecheck; then
+ echo "❌ Type checking failed! Please review TypeScript types."
+ echo "Once you're done, don't forget to add your changes to the commit! 🚀"
+ exit 1
+fi
+
+# Run lint
echo "Running lint..."
if ! pnpm lint; then
- echo "❌ Linting failed! 'pnpm lint:fix' will help you fix the easy ones."
+ echo "❌ Linting failed! Run 'pnpm lint:fix' to fix the easy issues."
echo "Once you're done, don't forget to add your beautification to the commit! 🤩"
- echo "lint exit code: $?"
exit 1
fi
# Update commit.json with the latest commit hash
+echo "Updating commit.json with the latest commit hash..."
COMMIT_HASH=$(git rev-parse HEAD)
+if [ $? -ne 0 ]; then
+ echo "❌ Failed to get commit hash. Ensure you are in a git repository."
+ exit 1
+fi
+
echo "{ \"commit\": \"$COMMIT_HASH\" }" > app/commit.json
git add app/commit.json
-echo "👍 All good! Committing changes..."
+echo "👍 All checks passed! Committing changes..."
diff --git a/app/commit.json b/app/commit.json
index 45cf76f..696f6c0 100644
--- a/app/commit.json
+++ b/app/commit.json
@@ -1 +1 @@
-{ "commit": "b16aab1f167d91903592e33357ae38e304ca7f65" }
+{ "commit": "b1a3e3993ee013b58cee6f02f2e05429d3b3a592" }
diff --git a/app/components/settings/debug/DebugTab.tsx b/app/components/settings/debug/DebugTab.tsx
index f37d1d4..e18607d 100644
--- a/app/components/settings/debug/DebugTab.tsx
+++ b/app/components/settings/debug/DebugTab.tsx
@@ -33,7 +33,7 @@ interface IProviderConfig {
const LOCAL_PROVIDERS = ['Ollama', 'LMStudio', 'OpenAILike'];
const versionHash = commit.commit;
const GITHUB_URLS = {
- original: 'https://api.github.com/repos/Stijnus/bolt.new-any-llm/commits/main',
+ original: 'https://api.github.com/repos/stackblitz-labs/bolt.diy/commits/main',
fork: 'https://api.github.com/repos/Stijnus/bolt.new-any-llm/commits/main',
};
@@ -327,7 +327,7 @@ export default function DebugTab() {