From 1d656bbb4930f9eb089199b927befb0abc670ea6 Mon Sep 17 00:00:00 2001 From: Anirban Kar Date: Tue, 24 Dec 2024 23:49:22 +0530 Subject: [PATCH 1/3] inital changes --- app/components/settings/data/DataTab.tsx | 74 +++++----- bin/bolt.js | 176 +++++++++++++++++++++++ package.json | 18 ++- 3 files changed, 231 insertions(+), 37 deletions(-) create mode 100755 bin/bolt.js diff --git a/app/components/settings/data/DataTab.tsx b/app/components/settings/data/DataTab.tsx index 756abaadb..faf76a623 100644 --- a/app/components/settings/data/DataTab.tsx +++ b/app/components/settings/data/DataTab.tsx @@ -25,7 +25,7 @@ const API_KEY_PROVIDERS = [ 'AzureOpenAI', ] as const; -type Provider = typeof API_KEY_PROVIDERS[number]; +type Provider = (typeof API_KEY_PROVIDERS)[number]; interface ApiKeys { [key: string]: string; @@ -52,6 +52,7 @@ export default function DataTab() { const error = new Error('Database is not available'); logStore.logError('Failed to export chats - DB unavailable', error); toast.error('Database is not available'); + return; } @@ -83,11 +84,13 @@ export default function DataTab() { const error = new Error('Database is not available'); logStore.logError('Failed to delete chats - DB unavailable', error); toast.error('Database is not available'); + return; } try { setIsDeleting(true); + const allChats = await getAll(db); await Promise.all(allChats.map((chat) => deleteById(db!, chat.id))); logStore.logSystem('All chats deleted successfully', { count: allChats.length }); @@ -125,16 +128,22 @@ export default function DataTab() { const handleImportSettings = (event: React.ChangeEvent) => { const file = event.target.files?.[0]; - if (!file) return; + + if (!file) { + return; + } const reader = new FileReader(); + reader.onload = (e) => { try { const settings = JSON.parse(e.target?.result as string); - + Object.entries(settings).forEach(([key, value]) => { if (key === 'bolt_theme') { - if (value) localStorage.setItem(key, value as string); + if (value) { + localStorage.setItem(key, value as string); + } } else if (value) { Cookies.set(key, value as string); } @@ -152,14 +161,14 @@ export default function DataTab() { const handleExportApiKeyTemplate = () => { const template: ApiKeys = {}; - API_KEY_PROVIDERS.forEach(provider => { + API_KEY_PROVIDERS.forEach((provider) => { template[`${provider}_API_KEY`] = ''; }); - template['OPENAI_LIKE_API_BASE_URL'] = ''; - template['LMSTUDIO_API_BASE_URL'] = ''; - template['OLLAMA_API_BASE_URL'] = ''; - template['TOGETHER_API_BASE_URL'] = ''; + template.OPENAI_LIKE_API_BASE_URL = ''; + template.LMSTUDIO_API_BASE_URL = ''; + template.OLLAMA_API_BASE_URL = ''; + template.TOGETHER_API_BASE_URL = ''; downloadAsJson(template, 'api-keys-template.json'); toast.success('API keys template exported successfully'); @@ -167,17 +176,22 @@ export default function DataTab() { const handleImportApiKeys = (event: React.ChangeEvent) => { const file = event.target.files?.[0]; - if (!file) return; + + if (!file) { + return; + } const reader = new FileReader(); + reader.onload = (e) => { try { const apiKeys = JSON.parse(e.target?.result as string); let importedCount = 0; const consolidatedKeys: Record = {}; - API_KEY_PROVIDERS.forEach(provider => { + API_KEY_PROVIDERS.forEach((provider) => { const keyName = `${provider}_API_KEY`; + if (apiKeys[keyName]) { consolidatedKeys[provider] = apiKeys[keyName]; importedCount++; @@ -187,13 +201,14 @@ export default function DataTab() { if (importedCount > 0) { // Store all API keys in a single cookie as JSON Cookies.set('apiKeys', JSON.stringify(consolidatedKeys)); - + // Also set individual cookies for backward compatibility Object.entries(consolidatedKeys).forEach(([provider, key]) => { Cookies.set(`${provider}_API_KEY`, key); }); toast.success(`Successfully imported ${importedCount} API keys/URLs. Refreshing page to apply changes...`); + // Reload the page after a short delay to allow the toast to be seen setTimeout(() => { window.location.reload(); @@ -203,12 +218,13 @@ export default function DataTab() { } // Set base URLs if they exist - ['OPENAI_LIKE_API_BASE_URL', 'LMSTUDIO_API_BASE_URL', 'OLLAMA_API_BASE_URL', 'TOGETHER_API_BASE_URL'].forEach(baseUrl => { - if (apiKeys[baseUrl]) { - Cookies.set(baseUrl, apiKeys[baseUrl]); - } - }); - + ['OPENAI_LIKE_API_BASE_URL', 'LMSTUDIO_API_BASE_URL', 'OLLAMA_API_BASE_URL', 'TOGETHER_API_BASE_URL'].forEach( + (baseUrl) => { + if (apiKeys[baseUrl]) { + Cookies.set(baseUrl, apiKeys[baseUrl]); + } + }, + ); } catch (error) { toast.error('Failed to import API keys. Make sure the file is a valid JSON file.'); console.error('Failed to import API keys:', error); @@ -226,9 +242,7 @@ export default function DataTab() {

Chat History

-

- Export or delete all your chat history. -

+

Export or delete all your chat history.

@@ -287,12 +296,7 @@ export default function DataTab() {
@@ -301,4 +305,4 @@ export default function DataTab() { ); -} \ No newline at end of file +} diff --git a/bin/bolt.js b/bin/bolt.js new file mode 100755 index 000000000..ff07fb709 --- /dev/null +++ b/bin/bolt.js @@ -0,0 +1,176 @@ +#!/usr/bin/env node + +// bin/bolt.js +import { spawn } from 'child_process'; +import { fileURLToPath } from 'url'; +import { dirname, join } from 'path'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +// Find the root directory where the package is installed +const rootDir = join(__dirname, '..'); + +// Parse command line arguments +const args = process.argv.slice(2); +const options = { + port: 5173, // default port + help: false, + version: false, +}; + +// Parse arguments +for (let i = 0; i < args.length; i++) { + const arg = args[i]; + switch (arg) { + case '--help': + case '-h': + options.help = true; + break; + case '--version': + case '-v': + options.version = true; + break; + case '--port': + case '-p': + const port = parseInt(args[i + 1]); + if (isNaN(port)) { + console.error('Error: Port must be a number'); + process.exit(1); + } + options.port = port; + i++; // Skip the next argument since it's the port number + break; + } +} + +async function getVersion() { + try { + const fs = await import('fs/promises'); + const packageJson = JSON.parse(await fs.readFile(join(rootDir, 'package.json'), 'utf8')); + return packageJson.version; + } catch (e) { + console.error('Error reading package.json:', e); + return 'undefined'; + } +} + +function showHelp() { + console.log(` +★═══════════════════════════════════════★ + B O L T . D I Y + Usage Instructions +★═══════════════════════════════════════★ + +Options: + -h, --help Show this help message + -v, --version Show the current version + -p, --port Specify a custom port (default: 5173) + +Examples: + bolt Start with default settings + bolt --port 3000 Start on port 3000 + bolt --help Show this help message + bolt --version Show version information + +For more information, visit: https://github.com/stackblitz-labs/bolt.diy +`); +} + +async function showVersion() { + const version = await getVersion(); + let commitHash; + try { + commitHash = execSync('git rev-parse --short HEAD', { stdio: ['pipe', 'pipe', 'ignore'] }) + .toString() + .trim(); + } catch (e) { + commitHash = undefined; + } + + console.log(` +★═══════════════════════════════════════★ + B O L T . D I Y +★═══════════════════════════════════════★ +Version: ${version} +${commitHash?`Commit: ${commitHash}\n`:''}`); +} + +async function displayBanner() { + const version = await getVersion(); + let commitHash; + try { + commitHash = execSync('git rev-parse --short HEAD', { stdio: ['pipe', 'pipe', 'ignore'] }) + .toString() + .trim(); + } catch (e) { + commitHash = 'unknown'; + } + + console.log('★═══════════════════════════════════════★'); + console.log(' B O L T . D I Y'); + console.log(' ⚡️ Welcome ⚡️'); + console.log('★═══════════════════════════════════════★'); + console.log(`📍 Current Version Tag: v${version}`); + console.log(`📍 Current Commit Version: "${commitHash}"`); + console.log(`📍 Starting on port: ${options.port}`); + console.log(' Please wait until the URL appears here'); + console.log('★═══════════════════════════════════════★'); +} + + +async function startApp() { + if (options.help) { + showHelp(); + process.exit(0); + } + + if (options.version) { + await showVersion(); + process.exit(0); + } + + await displayBanner(); + + try { + // Use the local remix CLI from node_modules + const remixBinPath = join(rootDir, 'node_modules', '.bin', 'remix'); + + // Then start the development server using the local remix binary + const devProcess = spawn(remixBinPath, ['vite:dev', '--port', options.port.toString()], { + cwd: rootDir, + stdio: 'inherit', + shell: true, + env: { + ...process.env, + PORT: options.port.toString(), + PATH: `${join(rootDir, 'node_modules', '.bin')}:${process.env.PATH}`, + }, + }); + + devProcess.on('error', (err) => { + console.error('Failed to start development server:', err); + if (err.code === 'ENOENT') { + console.error('\nError: Required dependencies not found. Please ensure you have run:'); + console.error('npm install\n'); + } + process.exit(1); + }); + + // Handle interruption signals + process.on('SIGINT', () => { + devProcess.kill('SIGINT'); + process.exit(0); + }); + + process.on('SIGTERM', () => { + devProcess.kill('SIGTERM'); + process.exit(0); + }); + } catch (error) { + console.error('Error starting the application:', error); + process.exit(1); + } +} + +startApp(); \ No newline at end of file diff --git a/package.json b/package.json index 05d483b91..55058c7a6 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,25 @@ { - "name": "bolt", + "name": "bolt-diy", "description": "An AI Agent", "private": true, "license": "MIT", "sideEffects": false, "type": "module", "version": "0.0.3", + "bin": { + "bolt": "bin/bolt.js" + }, + "files": [ + "bin/", + "app/", + "public/", + "build/", + "functions/", + "pre-start.cjs", + "vite.config.ts", + "remix.config.js", + "uno.config.ts" + ], "scripts": { "deploy": "npm run build && wrangler pages deploy", "build": "remix vite:build", @@ -133,4 +147,4 @@ "@typescript-eslint/utils": "^8.0.0-alpha.30" }, "packageManager": "pnpm@9.4.0" -} +} \ No newline at end of file From 20e9d55c1197e4ffc9b79ee596ae6e83898255a1 Mon Sep 17 00:00:00 2001 From: Anirban Kar Date: Tue, 24 Dec 2024 23:49:38 +0530 Subject: [PATCH 2/3] updated lint --- app/components/settings/data/DataTab.tsx | 3 --- 1 file changed, 3 deletions(-) diff --git a/app/components/settings/data/DataTab.tsx b/app/components/settings/data/DataTab.tsx index faf76a623..aac2fe0fb 100644 --- a/app/components/settings/data/DataTab.tsx +++ b/app/components/settings/data/DataTab.tsx @@ -5,7 +5,6 @@ import { toast } from 'react-toastify'; import { db, deleteById, getAll } from '~/lib/persistence'; import { logStore } from '~/lib/stores/logs'; import { classNames } from '~/utils/classNames'; -import styles from '~/components/settings/Settings.module.scss'; // List of supported providers that can have API keys const API_KEY_PROVIDERS = [ @@ -25,8 +24,6 @@ const API_KEY_PROVIDERS = [ 'AzureOpenAI', ] as const; -type Provider = (typeof API_KEY_PROVIDERS)[number]; - interface ApiKeys { [key: string]: string; } From ba908c7f324a089bb28716ca74b20e829b9abc6b Mon Sep 17 00:00:00 2001 From: Anirban Kar Date: Wed, 25 Dec 2024 00:42:06 +0530 Subject: [PATCH 3/3] renamed the bin command --- bin/bolt.js | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/bolt.js b/bin/bolt.js index ff07fb709..c88bdfa60 100755 --- a/bin/bolt.js +++ b/bin/bolt.js @@ -112,7 +112,7 @@ async function displayBanner() { console.log(' ⚡️ Welcome ⚡️'); console.log('★═══════════════════════════════════════★'); console.log(`📍 Current Version Tag: v${version}`); - console.log(`📍 Current Commit Version: "${commitHash}"`); + // console.log(`📍 Current Commit Version: "${commitHash}"`); console.log(`📍 Starting on port: ${options.port}`); console.log(' Please wait until the URL appears here'); console.log('★═══════════════════════════════════════★'); diff --git a/package.json b/package.json index 55058c7a6..3657a52c1 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "type": "module", "version": "0.0.3", "bin": { - "bolt": "bin/bolt.js" + "bolt.diy": "bin/bolt.js" }, "files": [ "bin/",