From 76cc7a813931e87b78096be06a4b91e30f8cb550 Mon Sep 17 00:00:00 2001 From: Martin Ouimet Date: Sat, 23 Nov 2024 00:20:35 -0500 Subject: [PATCH 01/21] feat: add Together AI integration and provider implementation guide - Create detailed provider implementation guide with: - Architecture overview and implementation steps - Configuration patterns and best practices - Testing checklist and Docker integration guide - Example using Together AI implementation - Add Together AI as new provider with: - Environment variables and Docker configuration - Support for Qwen, Llama, and Mixtral models - API key and base URL management - OpenAI-compatible API integration --- .env.example | 6 ++++++ Dockerfile | 8 ++++++++ app/lib/.server/llm/api-key.ts | 4 ++++ app/lib/.server/llm/model.ts | 2 ++ app/utils/constants.ts | 17 +++++++++++++++++ docker-compose.yaml | 4 ++++ worker-configuration.d.ts | 2 ++ 7 files changed, 43 insertions(+) diff --git a/.env.example b/.env.example index 08774d2e..613b95d2 100644 --- a/.env.example +++ b/.env.example @@ -38,12 +38,18 @@ OLLAMA_API_BASE_URL= # You only need this environment variable set if you want to use OpenAI Like models OPENAI_LIKE_API_BASE_URL= +# You only need this environment variable set if you want to use Together AI models +TOGETHER_API_BASE_URL= + # You only need this environment variable set if you want to use DeepSeek models through their API DEEPSEEK_API_KEY= # Get your OpenAI Like API Key OPENAI_LIKE_API_KEY= +# Get your Together API Key +TOGATHER_API_KEY= + # Get your Mistral API Key by following these instructions - # https://console.mistral.ai/api-keys/ # You only need this environment variable set if you want to use Mistral models diff --git a/Dockerfile b/Dockerfile index c581f7f1..06541d30 100644 --- a/Dockerfile +++ b/Dockerfile @@ -25,6 +25,8 @@ ARG ANTHROPIC_API_KEY ARG OPEN_ROUTER_API_KEY ARG GOOGLE_GENERATIVE_AI_API_KEY ARG OLLAMA_API_BASE_URL +ARG TOGETHER_API_KEY +ARG TOGETHER_API_BASE_URL ARG VITE_LOG_LEVEL=debug ARG DEFAULT_NUM_CTX @@ -36,6 +38,8 @@ ENV WRANGLER_SEND_METRICS=false \ OPEN_ROUTER_API_KEY=${OPEN_ROUTER_API_KEY} \ GOOGLE_GENERATIVE_AI_API_KEY=${GOOGLE_GENERATIVE_AI_API_KEY} \ OLLAMA_API_BASE_URL=${OLLAMA_API_BASE_URL} \ + TOGETHER_API_KEY=${TOGETHER_API_KEY} \ + TOGETHER_API_BASE_URL=${TOGETHER_API_BASE_URL} \ VITE_LOG_LEVEL=${VITE_LOG_LEVEL} \ DEFAULT_NUM_CTX=${DEFAULT_NUM_CTX} @@ -58,6 +62,8 @@ ARG ANTHROPIC_API_KEY ARG OPEN_ROUTER_API_KEY ARG GOOGLE_GENERATIVE_AI_API_KEY ARG OLLAMA_API_BASE_URL +ARG TOGETHER_API_KEY +ARG TOGETHER_API_BASE_URL ARG VITE_LOG_LEVEL=debug ARG DEFAULT_NUM_CTX @@ -68,6 +74,8 @@ ENV GROQ_API_KEY=${GROQ_API_KEY} \ OPEN_ROUTER_API_KEY=${OPEN_ROUTER_API_KEY} \ GOOGLE_GENERATIVE_AI_API_KEY=${GOOGLE_GENERATIVE_AI_API_KEY} \ OLLAMA_API_BASE_URL=${OLLAMA_API_BASE_URL} \ + TOGETHER_API_KEY=${TOGETHER_API_KEY} \ + TOGETHER_API_BASE_URL=${TOGETHER_API_BASE_URL} \ VITE_LOG_LEVEL=${VITE_LOG_LEVEL} \ DEFAULT_NUM_CTX=${DEFAULT_NUM_CTX} diff --git a/app/lib/.server/llm/api-key.ts b/app/lib/.server/llm/api-key.ts index 29561819..b06acb87 100644 --- a/app/lib/.server/llm/api-key.ts +++ b/app/lib/.server/llm/api-key.ts @@ -35,6 +35,8 @@ export function getAPIKey(cloudflareEnv: Env, provider: string, userApiKeys?: Re return env.MISTRAL_API_KEY || cloudflareEnv.MISTRAL_API_KEY; case 'OpenAILike': return env.OPENAI_LIKE_API_KEY || cloudflareEnv.OPENAI_LIKE_API_KEY; + case 'Together': + return env.TOGETHER_API_KEY || cloudflareEnv.TOGETHER_API_KEY; case 'xAI': return env.XAI_API_KEY || cloudflareEnv.XAI_API_KEY; case 'Cohere': @@ -48,6 +50,8 @@ export function getAPIKey(cloudflareEnv: Env, provider: string, userApiKeys?: Re export function getBaseURL(cloudflareEnv: Env, provider: string) { switch (provider) { + case 'Together': + return env.TOGETHER_API_BASE_URL || cloudflareEnv.TOGETHER_API_BASE_URL; case 'OpenAILike': return env.OPENAI_LIKE_API_BASE_URL || cloudflareEnv.OPENAI_LIKE_API_BASE_URL; case 'LMStudio': diff --git a/app/lib/.server/llm/model.ts b/app/lib/.server/llm/model.ts index 76a37116..8850a12f 100644 --- a/app/lib/.server/llm/model.ts +++ b/app/lib/.server/llm/model.ts @@ -146,6 +146,8 @@ export function getModel(provider: string, model: string, env: Env, apiKeys?: Re return getGoogleModel(apiKey, model); case 'OpenAILike': return getOpenAILikeModel(baseURL, apiKey, model); + case 'Together': + return getOpenAILikeModel(baseURL, apiKey, model); case 'Deepseek': return getDeepseekModel(apiKey, model); case 'Mistral': diff --git a/app/utils/constants.ts b/app/utils/constants.ts index de68a82e..3383f27e 100644 --- a/app/utils/constants.ts +++ b/app/utils/constants.ts @@ -259,6 +259,23 @@ const PROVIDER_LIST: ProviderInfo[] = [ labelForGetApiKey: 'Get LMStudio', icon: 'i-ph:cloud-arrow-down', }, + { + name: 'Together', + staticModels: [ + + { name: 'Qwen/Qwen2.5-Coder-32B-Instruct', label: 'Qwen/Qwen2.5-Coder-32B-Instruct', provider: 'Together', maxTokenAllowed: 8000, }, + { + name: 'meta-llama/Llama-3.2-90B-Vision-Instruct-Turbo', + label: 'meta-llama/Llama-3.2-90B-Vision-Instruct-Turbo', + provider: 'Together', + maxTokenAllowed: 8000, + }, + + { name: 'mistralai/Mixtral-8x7B-Instruct-v0.1', label: 'Mixtral 8x7B Instruct', provider: 'Together', maxTokenAllowed: 8192 }, + + ], + getApiKeyLink: 'https://api.together.xyz/settings/api-keys', + }, ]; export const DEFAULT_PROVIDER = PROVIDER_LIST[0]; diff --git a/docker-compose.yaml b/docker-compose.yaml index 4a3cc0ab..f504d806 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -20,6 +20,8 @@ services: - OPEN_ROUTER_API_KEY=${OPEN_ROUTER_API_KEY} - GOOGLE_GENERATIVE_AI_API_KEY=${GOOGLE_GENERATIVE_AI_API_KEY} - OLLAMA_API_BASE_URL=${OLLAMA_API_BASE_URL} + - TOGETHER_API_KEY=${TOGETHER_API_KEY} + - TOGETHER_API_BASE_URL=${TOGETHER_API_BASE_URL} - VITE_LOG_LEVEL=${VITE_LOG_LEVEL:-debug} - DEFAULT_NUM_CTX=${DEFAULT_NUM_CTX:-32768} - RUNNING_IN_DOCKER=true @@ -48,6 +50,8 @@ services: - OPEN_ROUTER_API_KEY=${OPEN_ROUTER_API_KEY} - GOOGLE_GENERATIVE_AI_API_KEY=${GOOGLE_GENERATIVE_AI_API_KEY} - OLLAMA_API_BASE_URL=${OLLAMA_API_BASE_URL} + - TOGETHER_API_KEY=${TOGETHER_API_KEY} + - TOGETHER_API_BASE_URL=${TOGETHER_API_BASE_URL} - VITE_LOG_LEVEL=${VITE_LOG_LEVEL:-debug} - DEFAULT_NUM_CTX=${DEFAULT_NUM_CTX:-32768} - RUNNING_IN_DOCKER=true diff --git a/worker-configuration.d.ts b/worker-configuration.d.ts index 9c074b81..4eaf2107 100644 --- a/worker-configuration.d.ts +++ b/worker-configuration.d.ts @@ -7,6 +7,8 @@ interface Env { OLLAMA_API_BASE_URL: string; OPENAI_LIKE_API_KEY: string; OPENAI_LIKE_API_BASE_URL: string; + TOGETHER_API_KEY: string; + TOGETHER_API_BASE_URL: string; DEEPSEEK_API_KEY: string; LMSTUDIO_API_BASE_URL: string; GOOGLE_GENERATIVE_AI_API_KEY: string; From 913656eff9f14159508ad84abaa6ab71a764b62e Mon Sep 17 00:00:00 2001 From: Hgosansn Date: Sat, 23 Nov 2024 03:25:43 +0100 Subject: [PATCH 02/21] BugFix: Terminal render too many times causing performance freeze --- app/components/workbench/EditorPanel.tsx | 178 +---------------- .../workbench/terminal/Terminal.tsx | 97 ++++----- .../workbench/terminal/TerminalTabs.tsx | 186 ++++++++++++++++++ 3 files changed, 242 insertions(+), 219 deletions(-) create mode 100644 app/components/workbench/terminal/TerminalTabs.tsx diff --git a/app/components/workbench/EditorPanel.tsx b/app/components/workbench/EditorPanel.tsx index 0a18658c..f68e030e 100644 --- a/app/components/workbench/EditorPanel.tsx +++ b/app/components/workbench/EditorPanel.tsx @@ -1,6 +1,6 @@ import { useStore } from '@nanostores/react'; -import { memo, useEffect, useMemo, useRef, useState } from 'react'; -import { Panel, PanelGroup, PanelResizeHandle, type ImperativePanelHandle } from 'react-resizable-panels'; +import { memo, useMemo } from 'react'; +import { Panel, PanelGroup, PanelResizeHandle } from 'react-resizable-panels'; import { CodeMirrorEditor, type EditorDocument, @@ -9,21 +9,17 @@ import { type OnSaveCallback as OnEditorSave, type OnScrollCallback as OnEditorScroll, } from '~/components/editor/codemirror/CodeMirrorEditor'; -import { IconButton } from '~/components/ui/IconButton'; import { PanelHeader } from '~/components/ui/PanelHeader'; import { PanelHeaderButton } from '~/components/ui/PanelHeaderButton'; -import { shortcutEventEmitter } from '~/lib/hooks'; import type { FileMap } from '~/lib/stores/files'; import { themeStore } from '~/lib/stores/theme'; -import { workbenchStore } from '~/lib/stores/workbench'; -import { classNames } from '~/utils/classNames'; import { WORK_DIR } from '~/utils/constants'; -import { logger, renderLogger } from '~/utils/logger'; +import { renderLogger } from '~/utils/logger'; import { isMobile } from '~/utils/mobile'; import { FileBreadcrumb } from './FileBreadcrumb'; import { FileTree } from './FileTree'; -import { Terminal, type TerminalRef } from './terminal/Terminal'; -import React from 'react'; +import { DEFAULT_TERMINAL_SIZE, TerminalTabs } from './terminal/TerminalTabs'; +import { workbenchStore } from '~/lib/stores/workbench'; interface EditorPanelProps { files?: FileMap; @@ -38,8 +34,6 @@ interface EditorPanelProps { onFileReset?: () => void; } -const MAX_TERMINALS = 3; -const DEFAULT_TERMINAL_SIZE = 25; const DEFAULT_EDITOR_SIZE = 100 - DEFAULT_TERMINAL_SIZE; const editorSettings: EditorSettings = { tabSize: 2 }; @@ -62,13 +56,6 @@ export const EditorPanel = memo( const theme = useStore(themeStore); const showTerminal = useStore(workbenchStore.showTerminal); - const terminalRefs = useRef>([]); - const terminalPanelRef = useRef(null); - const terminalToggledByShortcut = useRef(false); - - const [activeTerminal, setActiveTerminal] = useState(0); - const [terminalCount, setTerminalCount] = useState(1); - const activeFileSegments = useMemo(() => { if (!editorDocument) { return undefined; @@ -81,48 +68,6 @@ export const EditorPanel = memo( return editorDocument !== undefined && unsavedFiles?.has(editorDocument.filePath); }, [editorDocument, unsavedFiles]); - useEffect(() => { - const unsubscribeFromEventEmitter = shortcutEventEmitter.on('toggleTerminal', () => { - terminalToggledByShortcut.current = true; - }); - - const unsubscribeFromThemeStore = themeStore.subscribe(() => { - for (const ref of Object.values(terminalRefs.current)) { - ref?.reloadStyles(); - } - }); - - return () => { - unsubscribeFromEventEmitter(); - unsubscribeFromThemeStore(); - }; - }, []); - - useEffect(() => { - const { current: terminal } = terminalPanelRef; - - if (!terminal) { - return; - } - - const isCollapsed = terminal.isCollapsed(); - - if (!showTerminal && !isCollapsed) { - terminal.collapse(); - } else if (showTerminal && isCollapsed) { - terminal.resize(DEFAULT_TERMINAL_SIZE); - } - - terminalToggledByShortcut.current = false; - }, [showTerminal]); - - const addTerminal = () => { - if (terminalCount < MAX_TERMINALS) { - setTerminalCount(terminalCount + 1); - setActiveTerminal(terminalCount); - } - }; - return ( @@ -181,118 +126,7 @@ export const EditorPanel = memo( - { - if (!terminalToggledByShortcut.current) { - workbenchStore.toggleTerminal(true); - } - }} - onCollapse={() => { - if (!terminalToggledByShortcut.current) { - workbenchStore.toggleTerminal(false); - } - }} - > -
-
-
- {Array.from({ length: terminalCount + 1 }, (_, index) => { - const isActive = activeTerminal === index; - - return ( - - {index == 0 ? ( - - ) : ( - - - - )} - - ); - })} - {terminalCount < MAX_TERMINALS && } - workbenchStore.toggleTerminal(false)} - /> -
- {Array.from({ length: terminalCount + 1 }, (_, index) => { - const isActive = activeTerminal === index; - - if (index == 0) { - logger.info('Starting bolt terminal'); - - return ( - { - terminalRefs.current.push(ref); - }} - onTerminalReady={(terminal) => workbenchStore.attachBoltTerminal(terminal)} - onTerminalResize={(cols, rows) => workbenchStore.onTerminalResize(cols, rows)} - theme={theme} - /> - ); - } - - return ( - { - terminalRefs.current.push(ref); - }} - onTerminalReady={(terminal) => workbenchStore.attachTerminal(terminal)} - onTerminalResize={(cols, rows) => workbenchStore.onTerminalResize(cols, rows)} - theme={theme} - /> - ); - })} -
-
-
+ ); }, diff --git a/app/components/workbench/terminal/Terminal.tsx b/app/components/workbench/terminal/Terminal.tsx index b9b84dc8..337a72a6 100644 --- a/app/components/workbench/terminal/Terminal.tsx +++ b/app/components/workbench/terminal/Terminal.tsx @@ -16,71 +16,74 @@ export interface TerminalProps { className?: string; theme: Theme; readonly?: boolean; + id: string; onTerminalReady?: (terminal: XTerm) => void; onTerminalResize?: (cols: number, rows: number) => void; } export const Terminal = memo( - forwardRef(({ className, theme, readonly, onTerminalReady, onTerminalResize }, ref) => { - const terminalElementRef = useRef(null); - const terminalRef = useRef(); + forwardRef( + ({ className, theme, readonly, id, onTerminalReady, onTerminalResize }, ref) => { + const terminalElementRef = useRef(null); + const terminalRef = useRef(); - useEffect(() => { - const element = terminalElementRef.current!; + useEffect(() => { + const element = terminalElementRef.current!; - const fitAddon = new FitAddon(); - const webLinksAddon = new WebLinksAddon(); + const fitAddon = new FitAddon(); + const webLinksAddon = new WebLinksAddon(); - const terminal = new XTerm({ - cursorBlink: true, - convertEol: true, - disableStdin: readonly, - theme: getTerminalTheme(readonly ? { cursor: '#00000000' } : {}), - fontSize: 12, - fontFamily: 'Menlo, courier-new, courier, monospace', - }); + const terminal = new XTerm({ + cursorBlink: true, + convertEol: true, + disableStdin: readonly, + theme: getTerminalTheme(readonly ? { cursor: '#00000000' } : {}), + fontSize: 12, + fontFamily: 'Menlo, courier-new, courier, monospace', + }); - terminalRef.current = terminal; + terminalRef.current = terminal; - terminal.loadAddon(fitAddon); - terminal.loadAddon(webLinksAddon); - terminal.open(element); + terminal.loadAddon(fitAddon); + terminal.loadAddon(webLinksAddon); + terminal.open(element); - const resizeObserver = new ResizeObserver(() => { - fitAddon.fit(); - onTerminalResize?.(terminal.cols, terminal.rows); - }); + const resizeObserver = new ResizeObserver(() => { + fitAddon.fit(); + onTerminalResize?.(terminal.cols, terminal.rows); + }); - resizeObserver.observe(element); + resizeObserver.observe(element); - logger.info('Attach terminal'); + logger.debug(`Attach [${id}]`); - onTerminalReady?.(terminal); + onTerminalReady?.(terminal); - return () => { - resizeObserver.disconnect(); - terminal.dispose(); - }; - }, []); + return () => { + resizeObserver.disconnect(); + terminal.dispose(); + }; + }, []); - useEffect(() => { - const terminal = terminalRef.current!; + useEffect(() => { + const terminal = terminalRef.current!; - // we render a transparent cursor in case the terminal is readonly - terminal.options.theme = getTerminalTheme(readonly ? { cursor: '#00000000' } : {}); + // we render a transparent cursor in case the terminal is readonly + terminal.options.theme = getTerminalTheme(readonly ? { cursor: '#00000000' } : {}); - terminal.options.disableStdin = readonly; - }, [theme, readonly]); + terminal.options.disableStdin = readonly; + }, [theme, readonly]); - useImperativeHandle(ref, () => { - return { - reloadStyles: () => { - const terminal = terminalRef.current!; - terminal.options.theme = getTerminalTheme(readonly ? { cursor: '#00000000' } : {}); - }, - }; - }, []); + useImperativeHandle(ref, () => { + return { + reloadStyles: () => { + const terminal = terminalRef.current!; + terminal.options.theme = getTerminalTheme(readonly ? { cursor: '#00000000' } : {}); + }, + }; + }, []); - return
; - }), + return
; + }, + ), ); diff --git a/app/components/workbench/terminal/TerminalTabs.tsx b/app/components/workbench/terminal/TerminalTabs.tsx new file mode 100644 index 00000000..cecc5dc9 --- /dev/null +++ b/app/components/workbench/terminal/TerminalTabs.tsx @@ -0,0 +1,186 @@ +import { useStore } from '@nanostores/react'; +import React, { memo, useEffect, useRef, useState } from 'react'; +import { Panel, type ImperativePanelHandle } from 'react-resizable-panels'; +import { IconButton } from '~/components/ui/IconButton'; +import { shortcutEventEmitter } from '~/lib/hooks'; +import { themeStore } from '~/lib/stores/theme'; +import { workbenchStore } from '~/lib/stores/workbench'; +import { classNames } from '~/utils/classNames'; +import { Terminal, type TerminalRef } from './Terminal'; +import { createScopedLogger } from '~/utils/logger'; + +const logger = createScopedLogger('Terminal'); + +const MAX_TERMINALS = 3; +export const DEFAULT_TERMINAL_SIZE = 25; + +export const TerminalTabs = memo(() => { + const showTerminal = useStore(workbenchStore.showTerminal); + const theme = useStore(themeStore); + + const terminalRefs = useRef>([]); + const terminalPanelRef = useRef(null); + const terminalToggledByShortcut = useRef(false); + + const [activeTerminal, setActiveTerminal] = useState(0); + const [terminalCount, setTerminalCount] = useState(1); + + const addTerminal = () => { + if (terminalCount < MAX_TERMINALS) { + setTerminalCount(terminalCount + 1); + setActiveTerminal(terminalCount); + } + }; + + useEffect(() => { + const { current: terminal } = terminalPanelRef; + + if (!terminal) { + return; + } + + const isCollapsed = terminal.isCollapsed(); + + if (!showTerminal && !isCollapsed) { + terminal.collapse(); + } else if (showTerminal && isCollapsed) { + terminal.resize(DEFAULT_TERMINAL_SIZE); + } + + terminalToggledByShortcut.current = false; + }, [showTerminal]); + + useEffect(() => { + const unsubscribeFromEventEmitter = shortcutEventEmitter.on('toggleTerminal', () => { + terminalToggledByShortcut.current = true; + }); + + const unsubscribeFromThemeStore = themeStore.subscribe(() => { + for (const ref of Object.values(terminalRefs.current)) { + ref?.reloadStyles(); + } + }); + + return () => { + unsubscribeFromEventEmitter(); + unsubscribeFromThemeStore(); + }; + }, []); + + return ( + { + if (!terminalToggledByShortcut.current) { + workbenchStore.toggleTerminal(true); + } + }} + onCollapse={() => { + if (!terminalToggledByShortcut.current) { + workbenchStore.toggleTerminal(false); + } + }} + > +
+
+
+ {Array.from({ length: terminalCount + 1 }, (_, index) => { + const isActive = activeTerminal === index; + + return ( + + {index == 0 ? ( + + ) : ( + + + + )} + + ); + })} + {terminalCount < MAX_TERMINALS && } + workbenchStore.toggleTerminal(false)} + /> +
+ {Array.from({ length: terminalCount + 1 }, (_, index) => { + const isActive = activeTerminal === index; + + logger.debug(`Starting bolt terminal [${index}]`); + + if (index == 0) { + return ( + { + terminalRefs.current.push(ref); + }} + onTerminalReady={(terminal) => workbenchStore.attachBoltTerminal(terminal)} + onTerminalResize={(cols, rows) => workbenchStore.onTerminalResize(cols, rows)} + theme={theme} + /> + ); + } else { + return ( + { + terminalRefs.current.push(ref); + }} + onTerminalReady={(terminal) => workbenchStore.attachTerminal(terminal)} + onTerminalResize={(cols, rows) => workbenchStore.onTerminalResize(cols, rows)} + theme={theme} + /> + ); + } + })} +
+
+
+ ); +}); From a71b45d5949a9fc46c25c6020810b431792e4fe9 Mon Sep 17 00:00:00 2001 From: Dustin Loring Date: Sun, 1 Dec 2024 11:19:11 -0500 Subject: [PATCH 03/21] added example buttons --- app/components/chat/ExamplePrompts.tsx | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/app/components/chat/ExamplePrompts.tsx b/app/components/chat/ExamplePrompts.tsx index 2274b0e1..8378c7b6 100644 --- a/app/components/chat/ExamplePrompts.tsx +++ b/app/components/chat/ExamplePrompts.tsx @@ -10,8 +10,16 @@ const EXAMPLE_PROMPTS = [ export function ExamplePrompts(sendMessage?: { (event: React.UIEvent, messageInput?: string): void | undefined }) { return ( -
-
+
+
{EXAMPLE_PROMPTS.map((examplePrompt, index: number) => { return ( ); })} From cf7c7f328a8c80674acbfa2a06b1fd61f1ca516c Mon Sep 17 00:00:00 2001 From: Dustin Loring Date: Sun, 1 Dec 2024 11:43:54 -0500 Subject: [PATCH 04/21] improved start --- package.json | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 5e859227..75a7d98d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "bolt", - "description": "StackBlitz AI Agent", + "description": "An AI Agent", "private": true, "license": "MIT", "sideEffects": false, @@ -13,7 +13,9 @@ "test:watch": "vitest", "lint": "eslint --cache --cache-location ./node_modules/.cache/eslint app", "lint:fix": "npm run lint -- --fix && prettier app --write", - "start": "bindings=$(./bindings.sh) && wrangler pages dev ./build/client $bindings", + "start:windows": "wrangler pages dev ./build/client", + "start:unix": "bindings=$(./bindings.sh) && wrangler pages dev ./build/client $bindings", + "start": "node -e \"const { spawn } = require('child_process'); const isWindows = process.platform === 'win32'; const cmd = isWindows ? 'npm run start:windows' : 'npm run start:unix'; const child = spawn(cmd, { shell: true, stdio: 'inherit' }); child.on('exit', code => process.exit(code));\"", "dockerstart": "bindings=$(./bindings.sh) && wrangler pages dev ./build/client $bindings --ip 0.0.0.0 --port 5173 --no-show-interactive-dev-session", "dockerrun": "docker run -it -d --name bolt-ai-live -p 5173:5173 --env-file .env.local bolt-ai", "dockerbuild:prod": "docker build -t bolt-ai:production -t bolt-ai:latest --target bolt-ai-production .", From 6a4fd7ea3db12b7c2ce53461ee366c877b8da99a Mon Sep 17 00:00:00 2001 From: Dustin Loring Date: Sun, 1 Dec 2024 12:29:15 -0500 Subject: [PATCH 05/21] fixed typo --- docker-compose.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yaml b/docker-compose.yaml index 2a5e0179..0c9acd09 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -11,7 +11,7 @@ services: environment: - NODE_ENV=production - COMPOSE_PROFILES=production - # No strictly neded but serving as hints for Coolify + # No strictly needed but serving as hints for Coolify - PORT=5173 - GROQ_API_KEY=${GROQ_API_KEY} - HuggingFace_API_KEY=${HuggingFace_API_KEY} From 67f0bba948d37da869c66ac14f6fc908d17317bf Mon Sep 17 00:00:00 2001 From: Dustin Loring Date: Sun, 1 Dec 2024 12:31:12 -0500 Subject: [PATCH 06/21] fixed typo --- docker-compose.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yaml b/docker-compose.yaml index 2a5e0179..0c9acd09 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -11,7 +11,7 @@ services: environment: - NODE_ENV=production - COMPOSE_PROFILES=production - # No strictly neded but serving as hints for Coolify + # No strictly needed but serving as hints for Coolify - PORT=5173 - GROQ_API_KEY=${GROQ_API_KEY} - HuggingFace_API_KEY=${HuggingFace_API_KEY} From 7aad82aa1cee5d0ae522f5cc9033e996a07a054a Mon Sep 17 00:00:00 2001 From: Dustin Loring Date: Sun, 1 Dec 2024 13:06:45 -0500 Subject: [PATCH 07/21] Update package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 75a7d98d..87043344 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "test:watch": "vitest", "lint": "eslint --cache --cache-location ./node_modules/.cache/eslint app", "lint:fix": "npm run lint -- --fix && prettier app --write", - "start:windows": "wrangler pages dev ./build/client", + "start:windows": "wrangler pages dev ./build/client", "start:unix": "bindings=$(./bindings.sh) && wrangler pages dev ./build/client $bindings", "start": "node -e \"const { spawn } = require('child_process'); const isWindows = process.platform === 'win32'; const cmd = isWindows ? 'npm run start:windows' : 'npm run start:unix'; const child = spawn(cmd, { shell: true, stdio: 'inherit' }); child.on('exit', code => process.exit(code));\"", "dockerstart": "bindings=$(./bindings.sh) && wrangler pages dev ./build/client $bindings --ip 0.0.0.0 --port 5173 --no-show-interactive-dev-session", From 931272bf69355f18aed794ee80e65fc594ee6591 Mon Sep 17 00:00:00 2001 From: Dustin Loring Date: Sun, 1 Dec 2024 13:32:29 -0500 Subject: [PATCH 08/21] moved faq to its own page --- FAQ.md | 46 ++++++++++++++++++++++++++++++++++++++++++++++ README.md | 47 ++++------------------------------------------- 2 files changed, 50 insertions(+), 43 deletions(-) create mode 100644 FAQ.md diff --git a/FAQ.md b/FAQ.md new file mode 100644 index 00000000..4278a68a --- /dev/null +++ b/FAQ.md @@ -0,0 +1,46 @@ +[![Bolt.new: AI-Powered Full-Stack Web Development in the Browser](./public/social_preview_index.jpg)](https://bolt.new) + +# Bolt.new Fork by Cole Medin - oTToDev + +## FAQ + +### How do I get the best results with oTToDev? + +- **Be specific about your stack**: If you want to use specific frameworks or libraries (like Astro, Tailwind, ShadCN, or any other popular JavaScript framework), mention them in your initial prompt to ensure Bolt scaffolds the project accordingly. + +- **Use the enhance prompt icon**: Before sending your prompt, try clicking the 'enhance' icon to have the AI model help you refine your prompt, then edit the results before submitting. + +- **Scaffold the basics first, then add features**: Make sure the basic structure of your application is in place before diving into more advanced functionality. This helps oTToDev understand the foundation of your project and ensure everything is wired up right before building out more advanced functionality. + +- **Batch simple instructions**: Save time by combining simple instructions into one message. For example, you can ask oTToDev to change the color scheme, add mobile responsiveness, and restart the dev server, all in one go saving you time and reducing API credit consumption significantly. + +### Do you plan on merging oTToDev back into the official Bolt.new repo? + +More news coming on this coming early next month - stay tuned! + +### Why are there so many open issues/pull requests? + +oTToDev was started simply to showcase how to edit an open source project and to do something cool with local LLMs on my (@ColeMedin) YouTube channel! However, it quickly +grew into a massive community project that I am working hard to keep up with the demand of by forming a team of maintainers and getting as many people involved as I can. +That effort is going well and all of our maintainers are ABSOLUTE rockstars, but it still takes time to organize everything so we can efficiently get through all +the issues and PRs. But rest assured, we are working hard and even working on some partnerships behind the scenes to really help this project take off! + +### How do local LLMs fair compared to larger models like Claude 3.5 Sonnet for oTToDev/Bolt.new? + +As much as the gap is quickly closing between open source and massive close source models, you’re still going to get the best results with the very large models like GPT-4o, Claude 3.5 Sonnet, and DeepSeek Coder V2 236b. This is one of the big tasks we have at hand - figuring out how to prompt better, use agents, and improve the platform as a whole to make it work better for even the smaller local LLMs! + +### I'm getting the error: "There was an error processing this request" + +If you see this error within oTToDev, that is just the application telling you there is a problem at a high level, and this could mean a number of different things. To find the actual error, please check BOTH the terminal where you started the application (with Docker or pnpm) and the developer console in the browser. For most browsers, you can access the developer console by pressing F12 or right clicking anywhere in the browser and selecting “Inspect”. Then go to the “console” tab in the top right. + +### I'm getting the error: "x-api-key header missing" + +We have seen this error a couple times and for some reason just restarting the Docker container has fixed it. This seems to be Ollama specific. Another thing to try is try to run oTToDev with Docker or pnpm, whichever you didn’t run first. We are still on the hunt for why this happens once and a while! + +### I'm getting a blank preview when oTToDev runs my app! + +We promise you that we are constantly testing new PRs coming into oTToDev and the preview is core functionality, so the application is not broken! When you get a blank preview or don’t get a preview, this is generally because the LLM hallucinated bad code or incorrect commands. We are working on making this more transparent so it is obvious. Sometimes the error will appear in developer console too so check that as well. + +### Everything works but the results are bad + +This goes to the point above about how local LLMs are getting very powerful but you still are going to see better (sometimes much better) results with the largest LLMs like GPT-4o, Claude 3.5 Sonnet, and DeepSeek Coder V2 236b. If you are using smaller LLMs like Qwen-2.5-Coder, consider it more experimental and educational at this point. It can build smaller applications really well, which is super impressive for a local LLM, but for larger scale applications you want to use the larger LLMs still! \ No newline at end of file diff --git a/README.md b/README.md index 0b3fb24a..32efb255 100644 --- a/README.md +++ b/README.md @@ -228,55 +228,16 @@ pnpm run dev This will start the Remix Vite development server. You will need Google Chrome Canary to run this locally if you use Chrome! It's an easy install and a good browser for web development anyway. -## FAQ - -### How do I get the best results with oTToDev? - -- **Be specific about your stack**: If you want to use specific frameworks or libraries (like Astro, Tailwind, ShadCN, or any other popular JavaScript framework), mention them in your initial prompt to ensure Bolt scaffolds the project accordingly. - -- **Use the enhance prompt icon**: Before sending your prompt, try clicking the 'enhance' icon to have the AI model help you refine your prompt, then edit the results before submitting. - -- **Scaffold the basics first, then add features**: Make sure the basic structure of your application is in place before diving into more advanced functionality. This helps oTToDev understand the foundation of your project and ensure everything is wired up right before building out more advanced functionality. - -- **Batch simple instructions**: Save time by combining simple instructions into one message. For example, you can ask oTToDev to change the color scheme, add mobile responsiveness, and restart the dev server, all in one go saving you time and reducing API credit consumption significantly. - -### How do I contribute to oTToDev? +## How do I contribute to oTToDev? [Please check out our dedicated page for contributing to oTToDev here!](CONTRIBUTING.md) -### Do you plan on merging oTToDev back into the official Bolt.new repo? - -More news coming on this coming early next month - stay tuned! - -### What are the future plans for oTToDev? +## What are the future plans for oTToDev? [Check out our Roadmap here!](https://roadmap.sh/r/ottodev-roadmap-2ovzo) Lot more updates to this roadmap coming soon! -### Why are there so many open issues/pull requests? +## FAQ -oTToDev was started simply to showcase how to edit an open source project and to do something cool with local LLMs on my (@ColeMedin) YouTube channel! However, it quickly -grew into a massive community project that I am working hard to keep up with the demand of by forming a team of maintainers and getting as many people involved as I can. -That effort is going well and all of our maintainers are ABSOLUTE rockstars, but it still takes time to organize everything so we can efficiently get through all -the issues and PRs. But rest assured, we are working hard and even working on some partnerships behind the scenes to really help this project take off! - -### How do local LLMs fair compared to larger models like Claude 3.5 Sonnet for oTToDev/Bolt.new? - -As much as the gap is quickly closing between open source and massive close source models, you’re still going to get the best results with the very large models like GPT-4o, Claude 3.5 Sonnet, and DeepSeek Coder V2 236b. This is one of the big tasks we have at hand - figuring out how to prompt better, use agents, and improve the platform as a whole to make it work better for even the smaller local LLMs! - -### I'm getting the error: "There was an error processing this request" - -If you see this error within oTToDev, that is just the application telling you there is a problem at a high level, and this could mean a number of different things. To find the actual error, please check BOTH the terminal where you started the application (with Docker or pnpm) and the developer console in the browser. For most browsers, you can access the developer console by pressing F12 or right clicking anywhere in the browser and selecting “Inspect”. Then go to the “console” tab in the top right. - -### I'm getting the error: "x-api-key header missing" - -We have seen this error a couple times and for some reason just restarting the Docker container has fixed it. This seems to be Ollama specific. Another thing to try is try to run oTToDev with Docker or pnpm, whichever you didn’t run first. We are still on the hunt for why this happens once and a while! - -### I'm getting a blank preview when oTToDev runs my app! - -We promise you that we are constantly testing new PRs coming into oTToDev and the preview is core functionality, so the application is not broken! When you get a blank preview or don’t get a preview, this is generally because the LLM hallucinated bad code or incorrect commands. We are working on making this more transparent so it is obvious. Sometimes the error will appear in developer console too so check that as well. - -### Everything works but the results are bad - -This goes to the point above about how local LLMs are getting very powerful but you still are going to see better (sometimes much better) results with the largest LLMs like GPT-4o, Claude 3.5 Sonnet, and DeepSeek Coder V2 236b. If you are using smaller LLMs like Qwen-2.5-Coder, consider it more experimental and educational at this point. It can build smaller applications really well, which is super impressive for a local LLM, but for larger scale applications you want to use the larger LLMs still! +[Please check out our dedicated page for FAQ's related to oTToDev here!](FAQ.md) \ No newline at end of file From ff8e7c80274ada8d131bf917964ff77dba34e365 Mon Sep 17 00:00:00 2001 From: Dustin Loring Date: Sun, 1 Dec 2024 13:41:38 -0500 Subject: [PATCH 09/21] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 0b3fb24a..d22625a1 100644 --- a/README.md +++ b/README.md @@ -32,13 +32,13 @@ https://thinktank.ottomator.ai - ✅ Cohere Integration (@hasanraiyan) - ✅ Dynamic model max token length (@hasanraiyan) - ✅ Prompt caching (@SujalXplores) -- ✅ **HIGH PRIORITY** - Load local projects into the app (@wonderwhy-er) +- ✅ Load local projects into the app (@wonderwhy-er) +- ✅ Together Integration (@mouimet-infinisoft) +- ✅ Mobile friendly (@qwikode) - ⬜ **HIGH PRIORITY** - ALMOST DONE - Attach images to prompts (@atrokhym) - ⬜ **HIGH PRIORITY** - Prevent Bolt from rewriting files as often (file locking and diffs) - ⬜ **HIGH PRIORITY** - Better prompting for smaller LLMs (code window sometimes doesn't start) - ⬜ **HIGH PRIORITY** - Run agents in the backend as opposed to a single model call -- ⬜ Mobile friendly -- ⬜ Together Integration - ⬜ Azure Open AI API Integration - ⬜ Perplexity Integration - ⬜ Vertex AI Integration From d49a7e3cc0450224a9fa54cf6ed46c477e92604c Mon Sep 17 00:00:00 2001 From: Dustin Loring Date: Sun, 1 Dec 2024 14:13:25 -0500 Subject: [PATCH 10/21] Update README.md small touch up --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 32efb255..4cdb11a3 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ This fork of Bolt.new (oTToDev) allows you to choose the LLM that you use for ea https://thinktank.ottomator.ai -## Requested Additions to this Fork - Feel Free to Contribute!! +## Requested Additions - Feel Free to Contribute! - ✅ OpenRouter Integration (@coleam00) - ✅ Gemini Integration (@jonathands) @@ -240,4 +240,4 @@ Lot more updates to this roadmap coming soon! ## FAQ -[Please check out our dedicated page for FAQ's related to oTToDev here!](FAQ.md) \ No newline at end of file +[Please check out our dedicated page for FAQ's related to oTToDev here!](FAQ.md) From f692b6f9f23c4ea9f872fb0445e490c91a191fac Mon Sep 17 00:00:00 2001 From: Dustin Loring Date: Sun, 1 Dec 2024 14:47:44 -0500 Subject: [PATCH 11/21] Update README.md --- README.md | 9 --------- 1 file changed, 9 deletions(-) diff --git a/README.md b/README.md index 9bbb5c35..6590ab28 100644 --- a/README.md +++ b/README.md @@ -198,15 +198,6 @@ sudo npm install -g pnpm ```bash pnpm run dev ``` - -## Adding New LLMs: - -To make new LLMs available to use in this version of Bolt.new, head on over to `app/utils/constants.ts` and find the constant MODEL_LIST. Each element in this array is an object that has the model ID for the name (get this from the provider's API documentation), a label for the frontend model dropdown, and the provider. - -By default, Anthropic, OpenAI, Groq, and Ollama are implemented as providers, but the YouTube video for this repo covers how to extend this to work with more providers if you wish! - -When you add a new model to the MODEL_LIST array, it will immediately be available to use when you run the app locally or reload it. For Ollama models, make sure you have the model installed already before trying to use it here! - ## Available Scripts - `pnpm run dev`: Starts the development server. From 3cdadad4bda8921f3869421d4613390a72dfaf1c Mon Sep 17 00:00:00 2001 From: Dustin Loring Date: Sun, 1 Dec 2024 14:48:30 -0500 Subject: [PATCH 12/21] Update FAQ.md --- FAQ.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/FAQ.md b/FAQ.md index 4278a68a..52c84dca 100644 --- a/FAQ.md +++ b/FAQ.md @@ -41,6 +41,14 @@ We have seen this error a couple times and for some reason just restarting the D We promise you that we are constantly testing new PRs coming into oTToDev and the preview is core functionality, so the application is not broken! When you get a blank preview or don’t get a preview, this is generally because the LLM hallucinated bad code or incorrect commands. We are working on making this more transparent so it is obvious. Sometimes the error will appear in developer console too so check that as well. +## How to add a LLM: + +To make new LLMs available to use in this version of Bolt.new, head on over to `app/utils/constants.ts` and find the constant MODEL_LIST. Each element in this array is an object that has the model ID for the name (get this from the provider's API documentation), a label for the frontend model dropdown, and the provider. + +By default, Anthropic, OpenAI, Groq, and Ollama are implemented as providers, but the YouTube video for this repo covers how to extend this to work with more providers if you wish! + +When you add a new model to the MODEL_LIST array, it will immediately be available to use when you run the app locally or reload it. For Ollama models, make sure you have the model installed already before trying to use it here! + ### Everything works but the results are bad -This goes to the point above about how local LLMs are getting very powerful but you still are going to see better (sometimes much better) results with the largest LLMs like GPT-4o, Claude 3.5 Sonnet, and DeepSeek Coder V2 236b. If you are using smaller LLMs like Qwen-2.5-Coder, consider it more experimental and educational at this point. It can build smaller applications really well, which is super impressive for a local LLM, but for larger scale applications you want to use the larger LLMs still! \ No newline at end of file +This goes to the point above about how local LLMs are getting very powerful but you still are going to see better (sometimes much better) results with the largest LLMs like GPT-4o, Claude 3.5 Sonnet, and DeepSeek Coder V2 236b. If you are using smaller LLMs like Qwen-2.5-Coder, consider it more experimental and educational at this point. It can build smaller applications really well, which is super impressive for a local LLM, but for larger scale applications you want to use the larger LLMs still! From f3cdb7a2400595bf6aafe3a4ead8012f4d46735c Mon Sep 17 00:00:00 2001 From: Dustin Loring Date: Sun, 1 Dec 2024 14:48:46 -0500 Subject: [PATCH 13/21] Update FAQ.md --- FAQ.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FAQ.md b/FAQ.md index 52c84dca..3e267058 100644 --- a/FAQ.md +++ b/FAQ.md @@ -41,7 +41,7 @@ We have seen this error a couple times and for some reason just restarting the D We promise you that we are constantly testing new PRs coming into oTToDev and the preview is core functionality, so the application is not broken! When you get a blank preview or don’t get a preview, this is generally because the LLM hallucinated bad code or incorrect commands. We are working on making this more transparent so it is obvious. Sometimes the error will appear in developer console too so check that as well. -## How to add a LLM: +### How to add a LLM: To make new LLMs available to use in this version of Bolt.new, head on over to `app/utils/constants.ts` and find the constant MODEL_LIST. Each element in this array is an object that has the model ID for the name (get this from the provider's API documentation), a label for the frontend model dropdown, and the provider. From e06108683372cfb4cef25dc52dbaa3694ec227fc Mon Sep 17 00:00:00 2001 From: Calvin Vette Date: Sun, 1 Dec 2024 15:05:08 -0500 Subject: [PATCH 14/21] Updated SCSS to use @use instead of @import via sass-migrator --- .gitignore | 1 + app/styles/components/resize-handle.scss | 6 ++++-- app/styles/index.scss | 16 ++++++++-------- package.json | 2 -- 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/.gitignore b/.gitignore index 314faa9d..7bbcc2ea 100644 --- a/.gitignore +++ b/.gitignore @@ -27,6 +27,7 @@ dist-ssr /build .env.local .env +.dev.vars *.vars .wrangler _worker.bundle diff --git a/app/styles/components/resize-handle.scss b/app/styles/components/resize-handle.scss index 0b750097..bed98690 100644 --- a/app/styles/components/resize-handle.scss +++ b/app/styles/components/resize-handle.scss @@ -1,3 +1,5 @@ +@use "../z-index"; + [data-resize-handle] { position: relative; @@ -8,7 +10,7 @@ bottom: 0; left: -6px; right: -5px; - z-index: $zIndexMax; + z-index: z-index.$zIndexMax; } &[data-panel-group-direction='vertical']:after { @@ -18,7 +20,7 @@ right: 0; top: -5px; bottom: -6px; - z-index: $zIndexMax; + z-index: z-index.$zIndexMax; } &[data-resize-handle-state='hover']:after, diff --git a/app/styles/index.scss b/app/styles/index.scss index a45d65a1..36ebac2c 100644 --- a/app/styles/index.scss +++ b/app/styles/index.scss @@ -1,11 +1,11 @@ -@import './variables.scss'; -@import './z-index.scss'; -@import './animations.scss'; -@import './components/terminal.scss'; -@import './components/resize-handle.scss'; -@import './components/code.scss'; -@import './components/editor.scss'; -@import './components/toast.scss'; +@use 'variables.scss'; +@use 'z-index.scss'; +@use 'animations.scss'; +@use 'components/terminal.scss'; +@use 'components/resize-handle.scss'; +@use 'components/code.scss'; +@use 'components/editor.scss'; +@use 'components/toast.scss'; html, body { diff --git a/package.json b/package.json index 5e859227..04234eb9 100644 --- a/package.json +++ b/package.json @@ -97,9 +97,7 @@ "devDependencies": { "@blitz/eslint-plugin": "0.1.0", "@cloudflare/workers-types": "^4.20241127.0", - "@jridgewell/sourcemap-codec": "^1.5.0", "@remix-run/dev": "^2.15.0", - "@rollup/plugin-inject": "^5.0.5", "@types/diff": "^5.2.3", "@types/file-saver": "^2.0.7", "@types/js-cookie": "^3.0.6", From 4250fa9834f7a694332620c5c3021a0a8a8ad334 Mon Sep 17 00:00:00 2001 From: Dustin Loring Date: Sun, 1 Dec 2024 15:17:02 -0500 Subject: [PATCH 15/21] pre commit lint --- app/components/chat/ExamplePrompts.tsx | 19 ++++++++----------- app/utils/constants.ts | 16 ++++++++++++---- package-lock.json | 15 +++++++++------ pnpm-lock.yaml | 18 ++++++++++-------- 4 files changed, 39 insertions(+), 29 deletions(-) diff --git a/app/components/chat/ExamplePrompts.tsx b/app/components/chat/ExamplePrompts.tsx index 8378c7b6..4ef117fc 100644 --- a/app/components/chat/ExamplePrompts.tsx +++ b/app/components/chat/ExamplePrompts.tsx @@ -10,16 +10,13 @@ const EXAMPLE_PROMPTS = [ export function ExamplePrompts(sendMessage?: { (event: React.UIEvent, messageInput?: string): void | undefined }) { return ( -
-
+
+
{EXAMPLE_PROMPTS.map((examplePrompt, index: number) => { return ( diff --git a/app/utils/constants.ts b/app/utils/constants.ts index 6ab76610..1120bc1f 100644 --- a/app/utils/constants.ts +++ b/app/utils/constants.ts @@ -263,8 +263,12 @@ const PROVIDER_LIST: ProviderInfo[] = [ { name: 'Together', staticModels: [ - - { name: 'Qwen/Qwen2.5-Coder-32B-Instruct', label: 'Qwen/Qwen2.5-Coder-32B-Instruct', provider: 'Together', maxTokenAllowed: 8000, }, + { + name: 'Qwen/Qwen2.5-Coder-32B-Instruct', + label: 'Qwen/Qwen2.5-Coder-32B-Instruct', + provider: 'Together', + maxTokenAllowed: 8000, + }, { name: 'meta-llama/Llama-3.2-90B-Vision-Instruct-Turbo', label: 'meta-llama/Llama-3.2-90B-Vision-Instruct-Turbo', @@ -272,8 +276,12 @@ const PROVIDER_LIST: ProviderInfo[] = [ maxTokenAllowed: 8000, }, - { name: 'mistralai/Mixtral-8x7B-Instruct-v0.1', label: 'Mixtral 8x7B Instruct', provider: 'Together', maxTokenAllowed: 8192 }, - + { + name: 'mistralai/Mixtral-8x7B-Instruct-v0.1', + label: 'Mixtral 8x7B Instruct', + provider: 'Together', + maxTokenAllowed: 8192, + }, ], getApiKeyLink: 'https://api.together.xyz/settings/api-keys', }, diff --git a/package-lock.json b/package-lock.json index fe27b5d7..f909e42b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8728,9 +8728,9 @@ "license": "BSD-2-Clause" }, "node_modules/globals": { - "version": "15.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-15.12.0.tgz", - "integrity": "sha512-1+gLErljJFhbOVyaetcwJiJ4+eLe45S2E7P5UiZ9xGfeq3ATQf5DOv9G7MH3gGbKQLkzmNh2DxfZwLdw+j6oTQ==", + "version": "15.13.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.13.0.tgz", + "integrity": "sha512-49TewVEz0UxZjr1WYYsWpPrhyC/B/pA8Bq0fUmet2n+eR7yn0IvNzNaoBwnK6mdkzcN+se7Ez9zUgULTz2QH4g==", "dev": true, "license": "MIT", "engines": { @@ -8835,11 +8835,14 @@ } }, "node_modules/has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.1.0.tgz", + "integrity": "sha512-QLdzI9IIO1Jg7f9GT1gXpPpXArAn6cS31R1eEZqz08Gc+uQ8/XiqHWt17Fiw+2p6oTTIq5GXEpQkAlA88YRl/Q==", "devOptional": true, "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7" + }, "engines": { "node": ">= 0.4" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 96f06003..243c05ac 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -3331,8 +3331,8 @@ packages: resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} engines: {node: '>=18'} - globals@15.12.0: - resolution: {integrity: sha512-1+gLErljJFhbOVyaetcwJiJ4+eLe45S2E7P5UiZ9xGfeq3ATQf5DOv9G7MH3gGbKQLkzmNh2DxfZwLdw+j6oTQ==} + globals@15.13.0: + resolution: {integrity: sha512-49TewVEz0UxZjr1WYYsWpPrhyC/B/pA8Bq0fUmet2n+eR7yn0IvNzNaoBwnK6mdkzcN+se7Ez9zUgULTz2QH4g==} engines: {node: '>=18'} globrex@0.1.2: @@ -3363,8 +3363,8 @@ packages: has-property-descriptors@1.0.2: resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} - has-proto@1.0.3: - resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==} + has-proto@1.1.0: + resolution: {integrity: sha512-QLdzI9IIO1Jg7f9GT1gXpPpXArAn6cS31R1eEZqz08Gc+uQ8/XiqHWt17Fiw+2p6oTTIq5GXEpQkAlA88YRl/Q==} engines: {node: '>= 0.4'} has-symbols@1.0.3: @@ -6117,7 +6117,7 @@ snapshots: eslint-config-prettier: 9.1.0(eslint@9.16.0(jiti@1.21.6)) eslint-plugin-jsonc: 2.18.2(eslint@9.16.0(jiti@1.21.6)) eslint-plugin-prettier: 5.2.1(@types/eslint@8.56.10)(eslint-config-prettier@9.1.0(eslint@9.16.0(jiti@1.21.6)))(eslint@9.16.0(jiti@1.21.6))(prettier@3.4.1) - globals: 15.12.0 + globals: 15.13.0 typescript-eslint: 8.16.0(eslint@9.16.0(jiti@1.21.6))(typescript@5.7.2) transitivePeerDependencies: - '@eslint/json' @@ -9016,7 +9016,7 @@ snapshots: dependencies: es-errors: 1.3.0 function-bind: 1.1.2 - has-proto: 1.0.3 + has-proto: 1.1.0 has-symbols: 1.0.3 hasown: 2.0.2 @@ -9058,7 +9058,7 @@ snapshots: globals@14.0.0: {} - globals@15.12.0: {} + globals@15.13.0: {} globrex@0.1.2: {} @@ -9089,7 +9089,9 @@ snapshots: dependencies: es-define-property: 1.0.0 - has-proto@1.0.3: {} + has-proto@1.1.0: + dependencies: + call-bind: 1.0.7 has-symbols@1.0.3: {} From 8514a3baaf90a530aca02cb037860fbcae061b45 Mon Sep 17 00:00:00 2001 From: Dustin Loring Date: Sun, 1 Dec 2024 15:39:33 -0500 Subject: [PATCH 16/21] precommit lint --- app/styles/components/resize-handle.scss | 2 +- package-lock.json | 2 -- pnpm-lock.yaml | 6 ------ 3 files changed, 1 insertion(+), 9 deletions(-) diff --git a/app/styles/components/resize-handle.scss b/app/styles/components/resize-handle.scss index bed98690..7ee37b97 100644 --- a/app/styles/components/resize-handle.scss +++ b/app/styles/components/resize-handle.scss @@ -1,4 +1,4 @@ -@use "../z-index"; +@use '../z-index'; [data-resize-handle] { position: relative; diff --git a/package-lock.json b/package-lock.json index f909e42b..e1f72756 100644 --- a/package-lock.json +++ b/package-lock.json @@ -77,9 +77,7 @@ "devDependencies": { "@blitz/eslint-plugin": "0.1.0", "@cloudflare/workers-types": "^4.20241127.0", - "@jridgewell/sourcemap-codec": "^1.5.0", "@remix-run/dev": "^2.15.0", - "@rollup/plugin-inject": "^5.0.5", "@types/diff": "^5.2.3", "@types/file-saver": "^2.0.7", "@types/js-cookie": "^3.0.6", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 243c05ac..2f002fb2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -216,15 +216,9 @@ importers: '@cloudflare/workers-types': specifier: ^4.20241127.0 version: 4.20241127.0 - '@jridgewell/sourcemap-codec': - specifier: ^1.5.0 - version: 1.5.0 '@remix-run/dev': specifier: ^2.15.0 version: 2.15.0(@remix-run/react@2.15.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.7.2))(@types/node@22.10.1)(sass-embedded@1.81.0)(sass@1.77.6)(typescript@5.7.2)(vite@5.4.11(@types/node@22.10.1)(sass-embedded@1.81.0)(sass@1.77.6))(wrangler@3.91.0(@cloudflare/workers-types@4.20241127.0)) - '@rollup/plugin-inject': - specifier: ^5.0.5 - version: 5.0.5(rollup@4.28.0) '@types/diff': specifier: ^5.2.3 version: 5.2.3 From 83191d394b24812d3d925e9c356c1ca57ba8635c Mon Sep 17 00:00:00 2001 From: Dustin Loring Date: Sun, 1 Dec 2024 18:42:44 -0500 Subject: [PATCH 17/21] new lint rules --- eslint.config.mjs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/eslint.config.mjs b/eslint.config.mjs index 160e5f3e..bb7a5c60 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -4,7 +4,13 @@ import { getNamingConventionRule, tsFileExtensions } from '@blitz/eslint-plugin/ export default [ { - ignores: ['**/dist', '**/node_modules', '**/.wrangler', '**/bolt/build', '**/.history'], + ignores: [ + '**/dist', + '**/node_modules', + '**/.wrangler', + '**/bolt/build', + '**/.history', + ], }, ...blitzPlugin.configs.recommended(), { @@ -38,7 +44,7 @@ export default [ patterns: [ { group: ['../'], - message: `Relative imports are not allowed. Please use '~/' instead.`, + message: 'Relative imports are not allowed. Please use \'~/\' instead.', }, ], }, From aef26f1c683858fa828cce945732653143113470 Mon Sep 17 00:00:00 2001 From: Dustin Loring Date: Sun, 1 Dec 2024 19:02:52 -0500 Subject: [PATCH 18/21] prompt enhanchment --- README.md | 2 +- app/routes/api.enhancer.ts | 20 ++++++++++++++++++-- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 6590ab28..91eae02a 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,7 @@ https://thinktank.ottomator.ai - ✅ Load local projects into the app (@wonderwhy-er) - ✅ Together Integration (@mouimet-infinisoft) - ✅ Mobile friendly (@qwikode) +- ✅ Better prompt enhancing (@SujalXplores) - ⬜ **HIGH PRIORITY** - ALMOST DONE - Attach images to prompts (@atrokhym) - ⬜ **HIGH PRIORITY** - Prevent Bolt from rewriting files as often (file locking and diffs) - ⬜ **HIGH PRIORITY** - Better prompting for smaller LLMs (code window sometimes doesn't start) @@ -43,7 +44,6 @@ https://thinktank.ottomator.ai - ⬜ Perplexity Integration - ⬜ Vertex AI Integration - ⬜ Deploy directly to Vercel/Netlify/other similar platforms -- ⬜ Better prompt enhancing - ⬜ Have LLM plan the project in a MD file for better results/transparency - ⬜ VSCode Integration with git-like confirmations - ⬜ Upload documents for knowledge - UI design templates, a code base to reference coding style, etc. diff --git a/app/routes/api.enhancer.ts b/app/routes/api.enhancer.ts index 77e6f2fd..caebae0c 100644 --- a/app/routes/api.enhancer.ts +++ b/app/routes/api.enhancer.ts @@ -44,9 +44,25 @@ async function enhancerAction({ context, request }: ActionFunctionArgs) { content: `[Model: ${model}]\n\n[Provider: ${providerName}]\n\n` + stripIndents` + You are a professional prompt engineer specializing in crafting precise, effective prompts. + Your task is to enhance prompts by making them more specific, actionable, and effective. I want you to improve the user prompt that is wrapped in \`\` tags. - IMPORTANT: Only respond with the improved prompt and nothing else! + For valid prompts: + - Make instructions explicit and unambiguous + - Add relevant context and constraints + - Remove redundant information + - Maintain the core intent + - Ensure the prompt is self-contained + - Use professional language + For invalid or unclear prompts: + - Respond with a clear, professional guidance message + - Keep responses concise and actionable + - Maintain a helpful, constructive tone + - Focus on what the user should provide + - Use a standard template for consistency + IMPORTANT: Your response must ONLY contain the enhanced prompt text. + Do not include any explanations, metadata, or wrapper tags. ${message} @@ -79,7 +95,7 @@ async function enhancerAction({ context, request }: ActionFunctionArgs) { }, }); - const transformedStream = result.toAIStream().pipeThrough(transformStream); + const transformedStream = result.toDataStream().pipeThrough(transformStream); return new StreamingTextResponse(transformedStream); } catch (error: unknown) { From 7b3b97eabb08e0a064eb55b9ca35492ccc95aaaa Mon Sep 17 00:00:00 2001 From: Dustin Loring Date: Mon, 2 Dec 2024 05:16:43 -0500 Subject: [PATCH 19/21] Update .env.example Fixed typo in example env --- .env.example | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.env.example b/.env.example index 613b95d2..7306f361 100644 --- a/.env.example +++ b/.env.example @@ -48,7 +48,7 @@ DEEPSEEK_API_KEY= OPENAI_LIKE_API_KEY= # Get your Together API Key -TOGATHER_API_KEY= +TOGETHER_API_KEY= # Get your Mistral API Key by following these instructions - # https://console.mistral.ai/api-keys/ From 87620f38be14a44cf0fc62643061f6b3c51447f1 Mon Sep 17 00:00:00 2001 From: Dustin Loring Date: Mon, 2 Dec 2024 06:06:17 -0500 Subject: [PATCH 20/21] lint rules added and fixed --- app/components/chat/BaseChat.tsx | 8 +- app/entry.server.tsx | 2 +- app/lib/persistence/useChatHistory.ts | 4 +- app/lib/stores/workbench.ts | 4 +- eslint.config.mjs | 6 ++ package-lock.json | 110 +++++++++++++------------- package.json | 2 +- pnpm-lock.yaml | 108 ++++++++++++------------- 8 files changed, 127 insertions(+), 117 deletions(-) diff --git a/app/components/chat/BaseChat.tsx b/app/components/chat/BaseChat.tsx index efa87fa2..5e213a67 100644 --- a/app/components/chat/BaseChat.tsx +++ b/app/components/chat/BaseChat.tsx @@ -283,7 +283,9 @@ export const BaseChat = React.forwardRef( >