Skip to content

Commit

Permalink
Merge branch 'main' of github.com:athrael-soju/ai-chatbot
Browse files Browse the repository at this point in the history
  • Loading branch information
athrael-soju committed Jan 27, 2025
2 parents 883d2e5 + 38527ff commit 906fded
Show file tree
Hide file tree
Showing 18 changed files with 684 additions and 604 deletions.
8 changes: 8 additions & 0 deletions blocks/actions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
'use server';

import { getSuggestionsByDocumentId } from '@/lib/db/queries';

export async function getSuggestions({ documentId }: { documentId: string }) {
const suggestions = await getSuggestionsByDocumentId({ documentId });
return suggestions;
}
154 changes: 154 additions & 0 deletions blocks/code.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
import { Block } from '@/components/create-block';
import { CodeEditor } from '@/components/code-editor';
import {
CopyIcon,
LogsIcon,
MessageIcon,
PlayIcon,
RedoIcon,
UndoIcon,
} from '@/components/icons';
import { toast } from 'sonner';
import { generateUUID } from '@/lib/utils';
import { Console, ConsoleOutput } from '@/components/console';

interface Metadata {
outputs: Array<ConsoleOutput>;
}

export const codeBlock = new Block<'code', Metadata>({
kind: 'code',
description:
'Useful for code generation; Code execution is only available for python code.',
initialize: () => ({
outputs: [],
}),
onStreamPart: ({ streamPart, setBlock }) => {
if (streamPart.type === 'code-delta') {
setBlock((draftBlock) => ({
...draftBlock,
content: streamPart.content as string,
isVisible:
draftBlock.status === 'streaming' &&
draftBlock.content.length > 300 &&
draftBlock.content.length < 310
? true
: draftBlock.isVisible,
status: 'streaming',
}));
}
},
content: ({ metadata, setMetadata, ...props }) => {
return (
<>
<CodeEditor {...props} />

{metadata?.outputs && (
<Console
consoleOutputs={metadata.outputs}
setConsoleOutputs={() => {
setMetadata({
...metadata,
outputs: [],
});
}}
/>
)}
</>
);
},
actions: [
{
icon: <PlayIcon size={18} />,
label: 'Run',
description: 'Execute code',
onClick: async ({ content, setMetadata }) => {
const runId = generateUUID();
const outputs: any[] = [];

// @ts-expect-error - loadPyodide is not defined
const currentPyodideInstance = await globalThis.loadPyodide({
indexURL: 'https://cdn.jsdelivr.net/pyodide/v0.23.4/full/',
});

currentPyodideInstance.setStdout({
batched: (output: string) => {
outputs.push({
id: runId,
contents: [
{
type: output.startsWith('data:image/png;base64')
? 'image'
: 'text',
value: output,
},
],
status: 'completed',
});
},
});

await currentPyodideInstance.loadPackagesFromImports(content, {
messageCallback: (message: string) => {
outputs.push({
id: runId,
contents: [{ type: 'text', value: message }],
status: 'loading_packages',
});
},
});

await currentPyodideInstance.runPythonAsync(content);

setMetadata((metadata: any) => ({
...metadata,
outputs,
}));
},
},
{
icon: <UndoIcon size={18} />,
description: 'View Previous version',
onClick: ({ handleVersionChange }) => {
handleVersionChange('prev');
},
},
{
icon: <RedoIcon size={18} />,
description: 'View Next version',
onClick: ({ handleVersionChange }) => {
handleVersionChange('next');
},
},
{
icon: <CopyIcon size={18} />,
description: 'Copy code to clipboard',
onClick: ({ content }) => {
navigator.clipboard.writeText(content);
toast.success('Copied to clipboard!');
},
},
],
toolbar: [
{
icon: <MessageIcon />,
description: 'Add comments',
onClick: ({ appendMessage }) => {
appendMessage({
role: 'user',
content: 'Add comments to the code snippet for understanding',
});
},
},
{
icon: <LogsIcon />,
description: 'Add logs',
onClick: ({ appendMessage }) => {
appendMessage({
role: 'user',
content: 'Add logs to the code snippet for debugging',
});
},
},
],
});
59 changes: 59 additions & 0 deletions blocks/image.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { Block } from '@/components/create-block';
import { CopyIcon, RedoIcon, UndoIcon } from '@/components/icons';
import { ImageEditor } from '@/components/image-editor';

export const imageBlock = new Block({
kind: 'image',
description: 'Useful for image generation',
onStreamPart: ({ streamPart, setBlock }) => {
if (streamPart.type === 'image-delta') {
setBlock((draftBlock) => ({
...draftBlock,
content: streamPart.content as string,
isVisible: true,
status: 'streaming',
}));
}
},
content: ImageEditor,
actions: [
{
icon: <UndoIcon size={18} />,
description: 'View Previous version',
onClick: ({ handleVersionChange }) => {
handleVersionChange('prev');
},
},
{
icon: <RedoIcon size={18} />,
description: 'View Next version',
onClick: ({ handleVersionChange }) => {
handleVersionChange('next');
},
},
{
icon: <CopyIcon size={18} />,
description: 'Copy image to clipboard',
onClick: ({ content }) => {
const img = new Image();
img.src = `data:image/png;base64,${content}`;

img.onload = () => {
const canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
const ctx = canvas.getContext('2d');
ctx?.drawImage(img, 0, 0);
canvas.toBlob((blob) => {
if (blob) {
navigator.clipboard.write([
new ClipboardItem({ 'image/png': blob }),
]);
}
}, 'image/png');
};
},
},
],
toolbar: [],
});
174 changes: 174 additions & 0 deletions blocks/text.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
import { Block } from '@/components/create-block';
import { DiffView } from '@/components/diffview';
import { DocumentSkeleton } from '@/components/document-skeleton';
import { Editor } from '@/components/editor';
import {
ClockRewind,
CopyIcon,
MessageIcon,
PenIcon,
RedoIcon,
UndoIcon,
} from '@/components/icons';
import { Suggestion } from '@/lib/db/schema';
import { toast } from 'sonner';
import { getSuggestions } from './actions';

interface TextBlockMetadata {
suggestions: Array<Suggestion>;
}

export const textBlock = new Block<'text', TextBlockMetadata>({
kind: 'text',
description: 'Useful for text content, like drafting essays and emails.',
initialize: async ({ documentId, setMetadata }) => {
const suggestions = await getSuggestions({ documentId });

setMetadata({
suggestions,
});
},
onStreamPart: ({ streamPart, setMetadata, setBlock }) => {
if (streamPart.type === 'suggestion') {
setMetadata((metadata) => {
return {
suggestions: [
...metadata.suggestions,
streamPart.content as Suggestion,
],
};
});
}

if (streamPart.type === 'text-delta') {
setBlock((draftBlock) => {
return {
...draftBlock,
content: draftBlock.content + (streamPart.content as string),
isVisible:
draftBlock.status === 'streaming' &&
draftBlock.content.length > 400 &&
draftBlock.content.length < 450
? true
: draftBlock.isVisible,
status: 'streaming',
};
});
}
},
content: ({
mode,
status,
content,
isCurrentVersion,
currentVersionIndex,
onSaveContent,
getDocumentContentById,
isLoading,
metadata,
}) => {
if (isLoading) {
return <DocumentSkeleton blockKind="text" />;
}

if (mode === 'diff') {
const oldContent = getDocumentContentById(currentVersionIndex - 1);
const newContent = getDocumentContentById(currentVersionIndex);

return <DiffView oldContent={oldContent} newContent={newContent} />;
}

return (
<>
<Editor
content={content}
suggestions={metadata ? metadata.suggestions : []}
isCurrentVersion={isCurrentVersion}
currentVersionIndex={currentVersionIndex}
status={status}
onSaveContent={onSaveContent}
/>

{metadata && metadata.suggestions && metadata.suggestions.length > 0 ? (
<div className="md:hidden h-dvh w-12 shrink-0" />
) : null}
</>
);
},
actions: [
{
icon: <ClockRewind size={18} />,
description: 'View changes',
onClick: ({ handleVersionChange }) => {
handleVersionChange('toggle');
},
isDisabled: ({ currentVersionIndex, setMetadata }) => {
if (currentVersionIndex === 0) {
return true;
}

return false;
},
},
{
icon: <UndoIcon size={18} />,
description: 'View Previous version',
onClick: ({ handleVersionChange }) => {
handleVersionChange('prev');
},
isDisabled: ({ currentVersionIndex }) => {
if (currentVersionIndex === 0) {
return true;
}

return false;
},
},
{
icon: <RedoIcon size={18} />,
description: 'View Next version',
onClick: ({ handleVersionChange }) => {
handleVersionChange('next');
},
isDisabled: ({ isCurrentVersion }) => {
if (isCurrentVersion) {
return true;
}

return false;
},
},
{
icon: <CopyIcon size={18} />,
description: 'Copy to clipboard',
onClick: ({ content }) => {
navigator.clipboard.writeText(content);
toast.success('Copied to clipboard!');
},
},
],
toolbar: [
{
icon: <PenIcon />,
description: 'Add final polish',
onClick: ({ appendMessage }) => {
appendMessage({
role: 'user',
content:
'Please add final polish and check for grammar, add section titles for better structure, and ensure everything reads smoothly.',
});
},
},
{
icon: <MessageIcon />,
description: 'Request suggestions',
onClick: ({ appendMessage }) => {
appendMessage({
role: 'user',
content:
'Please add suggestions you have that could improve the writing.',
});
},
},
],
});
Loading

0 comments on commit 906fded

Please sign in to comment.