Skip to content

Commit

Permalink
Merge branch 'main' into iAlsoWantGitLab
Browse files Browse the repository at this point in the history
  • Loading branch information
D-Byte authored Dec 16, 2024
2 parents 89c959b + 0b47365 commit d6da850
Show file tree
Hide file tree
Showing 32 changed files with 852 additions and 542 deletions.
12 changes: 9 additions & 3 deletions .github/workflows/commit.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,18 @@ jobs:
- name: Checkout the code
uses: actions/checkout@v3

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Get the latest commit hash
run: echo "COMMIT_HASH=$(git rev-parse HEAD)" >> $GITHUB_ENV

run: |
echo "COMMIT_HASH=$(git rev-parse HEAD)" >> $GITHUB_ENV
echo "CURRENT_VERSION=$(node -p "require('./package.json').version")" >> $GITHUB_ENV
- name: Update commit file
run: |
echo "{ \"commit\": \"$COMMIT_HASH\" }" > app/commit.json
echo "{ \"commit\": \"$COMMIT_HASH\" , \"version\": \"$CURRENT_VERSION\" }" > app/commit.json
- name: Commit and push the update
run: |
Expand Down
31 changes: 7 additions & 24 deletions .github/workflows/update-stable.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,30 +9,7 @@ permissions:
contents: write

jobs:
update-commit:
if: contains(github.event.head_commit.message, '#release')
runs-on: ubuntu-latest

steps:
- name: Checkout the code
uses: actions/checkout@v3

- name: Get the latest commit hash
run: echo "COMMIT_HASH=$(git rev-parse HEAD)" >> $GITHUB_ENV

- name: Update commit file
run: |
echo "{ \"commit\": \"$COMMIT_HASH\" }" > app/commit.json
- name: Commit and push the update
run: |
git config --global user.name "github-actions[bot]"
git config --global user.email "github-actions[bot]@users.noreply.github.com"
git add app/commit.json
git commit -m "chore: update commit hash to $COMMIT_HASH"
git push
prepare-release:
needs: update-commit
if: contains(github.event.head_commit.message, '#release')
runs-on: ubuntu-latest

Expand Down Expand Up @@ -181,10 +158,16 @@ jobs:
echo "$CHANGELOG_CONTENT" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
- name: Get the latest commit hash and version tag
run: |
echo "COMMIT_HASH=$(git rev-parse HEAD)" >> $GITHUB_ENV
echo "CURRENT_VERSION=$(node -p "require('./package.json').version")" >> $GITHUB_ENV
- name: Commit and Tag Release
run: |
git pull
git add package.json pnpm-lock.yaml changelog.md
echo "{ \"commit\": \"$COMMIT_HASH\" , \"version\": \"$CURRENT_VERSION\" }" > app/commit.json
git add package.json pnpm-lock.yaml changelog.md app/commit.json
git commit -m "chore: release version ${{ steps.bump_version.outputs.new_version }}"
git tag "v${{ steps.bump_version.outputs.new_version }}"
git push
Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ https://thinktank.ottomator.ai
- ✅ Mobile friendly (@qwikode)
- ✅ Better prompt enhancing (@SujalXplores)
- ✅ Attach images to prompts (@atrokhym)
- ✅ Added Git Clone button (@thecodacus)
- ✅ Git Import from url (@thecodacus)
- ✅ PromptLibrary to have different variations of prompts for different use cases (@thecodacus)
- ✅ Detect package.json and commands to auto install & run preview for folder and git import (@wonderwhy-er)
- ✅ Selection tool to target changes visually (@emcconnell)
-**HIGH PRIORITY** - Prevent bolt from rewriting files as often (file locking and diffs)
Expand Down
2 changes: 1 addition & 1 deletion app/commit.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{ "commit": "960f532f8234663d0b3630d18033c959fac6882c" }
{ "commit": "25b80ab267541b6ea290985dde09863f1a29c85c" , "version": "0.0.1" }
19 changes: 18 additions & 1 deletion app/components/chat/AssistantMessage.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,30 @@
import { memo } from 'react';
import { Markdown } from './Markdown';
import type { JSONValue } from 'ai';

interface AssistantMessageProps {
content: string;
annotations?: JSONValue[];
}

export const AssistantMessage = memo(({ content }: AssistantMessageProps) => {
export const AssistantMessage = memo(({ content, annotations }: AssistantMessageProps) => {
const filteredAnnotations = (annotations?.filter(
(annotation: JSONValue) => annotation && typeof annotation === 'object' && Object.keys(annotation).includes('type'),
) || []) as { type: string; value: any }[];

const usage: {
completionTokens: number;
promptTokens: number;
totalTokens: number;
} = filteredAnnotations.find((annotation) => annotation.type === 'usage')?.value;

return (
<div className="overflow-hidden w-full">
{usage && (
<div className="text-sm text-bolt-elements-textSecondary mb-2">
Tokens: {usage.totalTokens} (prompt: {usage.promptTokens}, completion: {usage.completionTokens})
</div>
)}
<Markdown html>{content}</Markdown>
</div>
);
Expand Down
8 changes: 3 additions & 5 deletions app/components/chat/BaseChat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ export const BaseChat = React.forwardRef<HTMLDivElement, BaseChatProps>(
input = '',
enhancingPrompt,
handleInputChange,
promptEnhanced,

// promptEnhanced,
enhancePrompt,
sendMessage,
handleStop,
Expand Down Expand Up @@ -490,10 +491,7 @@ export const BaseChat = React.forwardRef<HTMLDivElement, BaseChatProps>(
<IconButton
title="Enhance prompt"
disabled={input.length === 0 || enhancingPrompt}
className={classNames(
'transition-all',
enhancingPrompt ? 'opacity-100' : '',
)}
className={classNames('transition-all', enhancingPrompt ? 'opacity-100' : '')}
onClick={() => {
enhancePrompt?.();
toast.success('Prompt enhanced!');
Expand Down
34 changes: 32 additions & 2 deletions app/components/chat/Chat.client.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import Cookies from 'js-cookie';
import { debounce } from '~/utils/debounce';
import { useSettings } from '~/lib/hooks/useSettings';
import type { ProviderInfo } from '~/types/model';
import { useSearchParams } from '@remix-run/react';

const toastAnimation = cssTransition({
enter: 'animated fadeInRight',
Expand Down Expand Up @@ -92,8 +93,9 @@ export const ChatImpl = memo(
const [chatStarted, setChatStarted] = useState(initialMessages.length > 0);
const [uploadedFiles, setUploadedFiles] = useState<File[]>([]); // Move here
const [imageDataList, setImageDataList] = useState<string[]>([]); // Move here
const [searchParams, setSearchParams] = useSearchParams();
const files = useStore(workbenchStore.files);
const { activeProviders } = useSettings();
const { activeProviders, promptId } = useSettings();

const [model, setModel] = useState(() => {
const savedModel = Cookies.get('selectedModel');
Expand All @@ -115,19 +117,47 @@ export const ChatImpl = memo(
body: {
apiKeys,
files,
promptId,
},
sendExtraMessageFields: true,
onError: (error) => {
logger.error('Request failed\n\n', error);
toast.error(
'There was an error processing your request: ' + (error.message ? error.message : 'No details were returned'),
);
},
onFinish: () => {
onFinish: (message, response) => {
const usage = response.usage;

if (usage) {
console.log('Token usage:', usage);

// You can now use the usage data as needed
}

logger.debug('Finished streaming');
},
initialMessages,
initialInput: Cookies.get(PROMPT_COOKIE_KEY) || '',
});
useEffect(() => {
const prompt = searchParams.get('prompt');
console.log(prompt, searchParams, model, provider);

if (prompt) {
setSearchParams({});
runAnimation();
append({
role: 'user',
content: [
{
type: 'text',
text: `[Model: ${model}]\n\n[Provider: ${provider.name}]\n\n${prompt}`,
},
] as any, // Type assertion to bypass compiler check
});
}
}, [model, provider, searchParams]);

const { enhancingPrompt, promptEnhanced, enhancePrompt, resetEnhancer } = usePromptEnhancer();
const { parsedMessages, parseMessages } = useMessageParser();
Expand Down
4 changes: 2 additions & 2 deletions app/components/chat/CodeBlock.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export const CodeBlock = memo(
<div
className={classNames(
styles.CopyButtonContainer,
'bg-white absolute top-[10px] right-[10px] rounded-md z-10 text-lg flex items-center justify-center opacity-0 group-hover:opacity-100',
'bg-transparant absolute top-[10px] right-[10px] rounded-md z-10 text-lg flex items-center justify-center opacity-0 group-hover:opacity-100',
{
'rounded-l-0 opacity-100': copied,
},
Expand All @@ -62,7 +62,7 @@ export const CodeBlock = memo(
{!disableCopy && (
<button
className={classNames(
'flex items-center bg-transparent p-[6px] justify-center before:bg-white before:rounded-l-md before:text-gray-500 before:border-r before:border-gray-300',
'flex items-center bg-accent-500 p-[6px] justify-center before:bg-white before:rounded-l-md before:text-gray-500 before:border-r before:border-gray-300 rounded-md transition-theme',
{
'before:opacity-0': !copied,
'before:opacity-100': copied,
Expand Down
14 changes: 9 additions & 5 deletions app/components/chat/Messages.client.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,16 @@ export const Messages = React.forwardRef<HTMLDivElement, MessagesProps>((props:
</div>
)}
<div className="grid grid-col-1 w-full">
{isUserMessage ? <UserMessage content={content} /> : <AssistantMessage content={content} />}
{isUserMessage ? (
<UserMessage content={content} />
) : (
<AssistantMessage content={content} annotations={message.annotations} />
)}
</div>
{!isUserMessage && (
<div className="flex gap-2 flex-col lg:flex-row">
<WithTooltip tooltip="Revert to this message">
{messageId && (
{messageId && (
<WithTooltip tooltip="Revert to this message">
<button
onClick={() => handleRewind(messageId)}
key="i-ph:arrow-u-up-left"
Expand All @@ -79,8 +83,8 @@ export const Messages = React.forwardRef<HTMLDivElement, MessagesProps>((props:
'text-xl text-bolt-elements-textSecondary hover:text-bolt-elements-textPrimary transition-colors',
)}
/>
)}
</WithTooltip>
</WithTooltip>
)}

<WithTooltip tooltip="Fork chat from this message">
<button
Expand Down
36 changes: 15 additions & 21 deletions app/components/chat/UserMessage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,42 +12,36 @@ interface UserMessageProps {
export function UserMessage({ content }: UserMessageProps) {
if (Array.isArray(content)) {
const textItem = content.find((item) => item.type === 'text');
const textContent = sanitizeUserMessage(textItem?.text || '');
const textContent = stripMetadata(textItem?.text || '');
const images = content.filter((item) => item.type === 'image' && item.image);

return (
<div className="overflow-hidden pt-[4px]">
<div className="flex items-start gap-4">
<div className="flex-1">
<Markdown limitedMarkdown>{textContent}</Markdown>
</div>
{images.length > 0 && (
<div className="flex-shrink-0 w-[160px]">
{images.map((item, index) => (
<div key={index} className="relative">
<img
src={item.image}
alt={`Uploaded image ${index + 1}`}
className="w-full h-[160px] rounded-lg object-cover border border-bolt-elements-borderColor"
/>
</div>
))}
</div>
)}
<div className="flex flex-col gap-4">
{textContent && <Markdown html>{textContent}</Markdown>}
{images.map((item, index) => (
<img
key={index}
src={item.image}
alt={`Image ${index + 1}`}
className="max-w-full h-auto rounded-lg"
style={{ maxHeight: '512px', objectFit: 'contain' }}
/>
))}
</div>
</div>
);
}

const textContent = sanitizeUserMessage(content);
const textContent = stripMetadata(content);

return (
<div className="overflow-hidden pt-[4px]">
<Markdown limitedMarkdown>{textContent}</Markdown>
<Markdown html>{textContent}</Markdown>
</div>
);
}

function sanitizeUserMessage(content: string) {
function stripMetadata(content: string) {
return content.replace(MODEL_REGEX, '').replace(PROVIDER_REGEX, '');
}
21 changes: 19 additions & 2 deletions app/components/git/GitUrlImport.client.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import { Chat } from '~/components/chat/Chat.client';
import { useGit } from '~/lib/hooks/useGit';
import { useChatHistory } from '~/lib/persistence';
import { createCommandsMessage, detectProjectCommands } from '~/utils/projectCommands';
import { LoadingOverlay } from '~/components/ui/LoadingOverlay';
import { toast } from 'react-toastify';

const IGNORE_PATTERNS = [
'node_modules/**',
Expand Down Expand Up @@ -38,6 +40,7 @@ export function GitUrlImport() {
const { ready: historyReady, importChat } = useChatHistory();
const { ready: gitReady, gitClone } = useGit();
const [imported, setImported] = useState(false);
const [loading, setLoading] = useState(true);

const importRepo = async (repoUrl?: string) => {
if (!gitReady && !historyReady) {
Expand Down Expand Up @@ -109,9 +112,23 @@ ${file.content}
return;
}

importRepo(url);
importRepo(url).catch((error) => {
console.error('Error importing repo:', error);
toast.error('Failed to import repository');
setLoading(false);
window.location.href = '/';
});
setImported(true);
}, [searchParams, historyReady, gitReady, imported]);

return <ClientOnly fallback={<BaseChat />}>{() => <Chat />}</ClientOnly>;
return (
<ClientOnly fallback={<BaseChat />}>
{() => (
<>
<Chat />
{loading && <LoadingOverlay message="Please wait while we clone the repository..." />}
</>
)}
</ClientOnly>
);
}
6 changes: 5 additions & 1 deletion app/components/settings/chat-history/ChatHistoryTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ export default function ChatHistoryTab() {
};

const handleDeleteAllChats = async () => {
const confirmDelete = window.confirm("Are you sure you want to delete all chats? This action cannot be undone.");
const confirmDelete = window.confirm('Are you sure you want to delete all chats? This action cannot be undone.');

if (!confirmDelete) {
return; // Exit if the user cancels
}
Expand All @@ -31,11 +32,13 @@ export default function ChatHistoryTab() {
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 });
Expand All @@ -55,6 +58,7 @@ export default function ChatHistoryTab() {
const error = new Error('Database is not available');
logStore.logError('Failed to export chats - DB unavailable', error);
toast.error('Database is not available');

return;
}

Expand Down
Loading

0 comments on commit d6da850

Please sign in to comment.