-
Notifications
You must be signed in to change notification settings - Fork 104
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
24176b8
commit 44c5c9a
Showing
36 changed files
with
3,803 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
'use client'; | ||
|
||
import { UIBlock } from '@/components/block'; | ||
import { useCallback, useMemo } from 'react'; | ||
import useSWR from 'swr'; | ||
|
||
export const initialBlockData: UIBlock = { | ||
documentId: 'init', | ||
content: '', | ||
kind: 'text', | ||
title: '', | ||
status: 'idle', | ||
isVisible: false, | ||
boundingBox: { | ||
top: 0, | ||
left: 0, | ||
width: 0, | ||
height: 0, | ||
}, | ||
}; | ||
|
||
// Add type for selector function | ||
type Selector<T> = (state: UIBlock) => T; | ||
|
||
export function useBlockSelector<Selected>(selector: Selector<Selected>) { | ||
const { data: localBlock } = useSWR<UIBlock>('block', null, { | ||
fallbackData: initialBlockData, | ||
}); | ||
|
||
const selectedValue = useMemo(() => { | ||
if (!localBlock) return selector(initialBlockData); | ||
return selector(localBlock); | ||
}, [localBlock, selector]); | ||
|
||
return selectedValue; | ||
} | ||
|
||
export function useBlock() { | ||
const { data: localBlock, mutate: setLocalBlock } = useSWR<UIBlock>( | ||
'block', | ||
null, | ||
{ | ||
fallbackData: initialBlockData, | ||
}, | ||
); | ||
|
||
const block = useMemo(() => { | ||
if (!localBlock) return initialBlockData; | ||
return localBlock; | ||
}, [localBlock]); | ||
|
||
const setBlock = useCallback( | ||
(updaterFn: UIBlock | ((currentBlock: UIBlock) => UIBlock)) => { | ||
setLocalBlock((currentBlock) => { | ||
const blockToUpdate = currentBlock || initialBlockData; | ||
|
||
if (typeof updaterFn === 'function') { | ||
return updaterFn(blockToUpdate); | ||
} | ||
|
||
return updaterFn; | ||
}); | ||
}, | ||
[setLocalBlock], | ||
); | ||
|
||
return useMemo(() => ({ block, setBlock }), [block, setBlock]); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
'use client'; | ||
|
||
import { updateChatVisibility } from '@/app/(chat)/actions'; | ||
import { VisibilityType } from '@/components/visibility-selector'; | ||
import { Chat } from '@/lib/db/schema'; | ||
import { useMemo } from 'react'; | ||
import useSWR, { useSWRConfig } from 'swr'; | ||
|
||
export function useChatVisibility({ | ||
chatId, | ||
initialVisibility, | ||
}: { | ||
chatId: string; | ||
initialVisibility: VisibilityType; | ||
}) { | ||
const { mutate, cache } = useSWRConfig(); | ||
const history: Array<Chat> = cache.get('/api/history')?.data; | ||
|
||
const { data: localVisibility, mutate: setLocalVisibility } = useSWR( | ||
`${chatId}-visibility`, | ||
null, | ||
{ | ||
fallbackData: initialVisibility, | ||
}, | ||
); | ||
|
||
const visibilityType = useMemo(() => { | ||
if (!history) return localVisibility; | ||
const chat = history.find((chat) => chat.id === chatId); | ||
if (!chat) return 'private'; | ||
return chat.visibility; | ||
}, [history, chatId, localVisibility]); | ||
|
||
const setVisibilityType = (updatedVisibilityType: VisibilityType) => { | ||
setLocalVisibility(updatedVisibilityType); | ||
|
||
mutate<Array<Chat>>( | ||
'/api/history', | ||
(history) => { | ||
return history | ||
? history.map((chat) => { | ||
if (chat.id === chatId) { | ||
return { | ||
...chat, | ||
visibility: updatedVisibilityType, | ||
}; | ||
} | ||
return chat; | ||
}) | ||
: []; | ||
}, | ||
{ revalidate: false }, | ||
); | ||
|
||
updateChatVisibility({ | ||
chatId: chatId, | ||
visibility: updatedVisibilityType, | ||
}); | ||
}; | ||
|
||
return { visibilityType, setVisibilityType }; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import * as React from 'react'; | ||
|
||
const MOBILE_BREAKPOINT = 768; | ||
|
||
export function useIsMobile() { | ||
const [isMobile, setIsMobile] = React.useState<boolean | undefined>( | ||
undefined, | ||
); | ||
|
||
React.useEffect(() => { | ||
const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`); | ||
const onChange = () => { | ||
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT); | ||
}; | ||
mql.addEventListener('change', onChange); | ||
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT); | ||
return () => mql.removeEventListener('change', onChange); | ||
}, []); | ||
|
||
return !!isMobile; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import { useCopyToClipboard } from 'usehooks-ts'; | ||
|
||
async function copyImageToClipboard(base64String: string) { | ||
try { | ||
const blob = await fetch(`data:image/png;base64,${base64String}`).then( | ||
(res) => res.blob(), | ||
); | ||
|
||
const item = new ClipboardItem({ | ||
'image/png': blob, | ||
}); | ||
|
||
await navigator.clipboard.write([item]); | ||
} catch (error) { | ||
console.error('Failed to copy image to clipboard:', error); | ||
} | ||
} | ||
|
||
export function useMultimodalCopyToClipboard() { | ||
const [_, copyTextToClipboard] = useCopyToClipboard(); | ||
return { copyTextToClipboard, copyImageToClipboard }; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
'use client'; | ||
|
||
import useSWR from 'swr'; | ||
|
||
export function useUserMessageId() { | ||
const { data: userMessageIdFromServer, mutate: setUserMessageIdFromServer } = | ||
useSWR('userMessageIdFromServer', null); | ||
|
||
return { userMessageIdFromServer, setUserMessageIdFromServer }; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
import type { Experimental_LanguageModelV1Middleware } from 'ai'; | ||
|
||
export const customMiddleware: Experimental_LanguageModelV1Middleware = {}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { openai } from '@ai-sdk/openai'; | ||
import { experimental_wrapLanguageModel as wrapLanguageModel } from 'ai'; | ||
|
||
import { customMiddleware } from './custom-middleware'; | ||
|
||
export const customModel = (apiIdentifier: string) => { | ||
return wrapLanguageModel({ | ||
model: openai(apiIdentifier), | ||
middleware: customMiddleware, | ||
}); | ||
}; | ||
|
||
export const imageGenerationModel = openai.image('dall-e-3'); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
// Define your models here. | ||
|
||
export interface Model { | ||
id: string; | ||
label: string; | ||
apiIdentifier: string; | ||
description: string; | ||
} | ||
|
||
export const models: Array<Model> = [ | ||
{ | ||
id: 'gpt-4o-mini', | ||
label: 'GPT 4o mini', | ||
apiIdentifier: 'gpt-4o-mini', | ||
description: 'Small model for fast, lightweight tasks', | ||
}, | ||
{ | ||
id: 'gpt-4o', | ||
label: 'GPT 4o', | ||
apiIdentifier: 'gpt-4o', | ||
description: 'For complex, multi-step tasks', | ||
}, | ||
] as const; | ||
|
||
export const DEFAULT_MODEL_NAME: string = 'gpt-4o-mini'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
import { BlockKind } from '@/components/block'; | ||
|
||
export const blocksPrompt = ` | ||
Blocks is a special user interface mode that helps users with writing, editing, and other content creation tasks. When block is open, it is on the right side of the screen, while the conversation is on the left side. When creating or updating documents, changes are reflected in real-time on the blocks and visible to the user. | ||
When asked to write code, always use blocks. When writing code, specify the language in the backticks, e.g. \`\`\`python\`code here\`\`\`. The default language is Python. Other languages are not yet supported, so let the user know if they request a different language. | ||
DO NOT UPDATE DOCUMENTS IMMEDIATELY AFTER CREATING THEM. WAIT FOR USER FEEDBACK OR REQUEST TO UPDATE IT. | ||
This is a guide for using blocks tools: \`createDocument\` and \`updateDocument\`, which render content on a blocks beside the conversation. | ||
**When to use \`createDocument\`:** | ||
- For substantial content (>10 lines) or code | ||
- For content users will likely save/reuse (emails, code, essays, etc.) | ||
- When explicitly requested to create a document | ||
- For when content contains a single code snippet | ||
**When NOT to use \`createDocument\`:** | ||
- For informational/explanatory content | ||
- For conversational responses | ||
- When asked to keep it in chat | ||
**Using \`updateDocument\`:** | ||
- Default to full document rewrites for major changes | ||
- Use targeted updates only for specific, isolated changes | ||
- Follow user instructions for which parts to modify | ||
**When NOT to use \`updateDocument\`:** | ||
- Immediately after creating a document | ||
Do not update document right after creating it. Wait for user feedback or request to update it. | ||
`; | ||
|
||
export const regularPrompt = | ||
'You are a friendly assistant! Keep your responses concise and helpful.'; | ||
|
||
export const systemPrompt = `${regularPrompt}\n\n${blocksPrompt}`; | ||
|
||
export const codePrompt = ` | ||
You are a Python code generator that creates self-contained, executable code snippets. When writing code: | ||
1. Each snippet should be complete and runnable on its own | ||
2. Prefer using print() statements to display outputs | ||
3. Include helpful comments explaining the code | ||
4. Keep snippets concise (generally under 15 lines) | ||
5. Avoid external dependencies - use Python standard library | ||
6. Handle potential errors gracefully | ||
7. Return meaningful output that demonstrates the code's functionality | ||
8. Don't use input() or other interactive functions | ||
9. Don't access files or network resources | ||
10. Don't use infinite loops | ||
Examples of good snippets: | ||
\`\`\`python | ||
# Calculate factorial iteratively | ||
def factorial(n): | ||
result = 1 | ||
for i in range(1, n + 1): | ||
result *= i | ||
return result | ||
print(f"Factorial of 5 is: {factorial(5)}") | ||
\`\`\` | ||
`; | ||
|
||
export const updateDocumentPrompt = ( | ||
currentContent: string | null, | ||
type: BlockKind, | ||
) => | ||
type === 'text' | ||
? `\ | ||
Improve the following contents of the document based on the given prompt. | ||
${currentContent} | ||
` | ||
: type === 'code' | ||
? `\ | ||
Improve the following code snippet based on the given prompt. | ||
${currentContent} | ||
` | ||
: ''; |
Oops, something went wrong.