Add canvas interface (#461)

This commit is contained in:
Jeremy 2024-10-30 16:01:24 +05:30 committed by GitHub
parent 1a74a5ca9a
commit b3cb0ea755
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
44 changed files with 7454 additions and 4691 deletions

View file

@ -1,14 +1,15 @@
import {
CoreAssistantMessage,
CoreMessage,
CoreToolMessage,
generateId,
Message,
ToolInvocation,
} from "ai";
import { clsx, type ClassValue } from "clsx";
import { twMerge } from "tailwind-merge";
} from 'ai';
import { clsx, type ClassValue } from 'clsx';
import { twMerge } from 'tailwind-merge';
import { Chat } from "@/db/schema";
import { Chat } from '@/db/schema';
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
@ -24,7 +25,7 @@ export const fetcher = async (url: string) => {
if (!res.ok) {
const error = new Error(
"An error occurred while fetching the data.",
'An error occurred while fetching the data.'
) as ApplicationError;
error.info = await res.json();
@ -37,16 +38,16 @@ export const fetcher = async (url: string) => {
};
export function getLocalStorage(key: string) {
if (typeof window !== "undefined") {
return JSON.parse(localStorage.getItem(key) || "[]");
if (typeof window !== 'undefined') {
return JSON.parse(localStorage.getItem(key) || '[]');
}
return [];
}
export function generateUUID(): string {
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
const r = (Math.random() * 16) | 0;
const v = c === "x" ? r : (r & 0x3) | 0x8;
const v = c === 'x' ? r : (r & 0x3) | 0x8;
return v.toString(16);
});
}
@ -64,13 +65,13 @@ function addToolMessageToChat({
...message,
toolInvocations: message.toolInvocations.map((toolInvocation) => {
const toolResult = toolMessage.content.find(
(tool) => tool.toolCallId === toolInvocation.toolCallId,
(tool) => tool.toolCallId === toolInvocation.toolCallId
);
if (toolResult) {
return {
...toolInvocation,
state: "result",
state: 'result',
result: toolResult.result,
};
}
@ -85,28 +86,28 @@ function addToolMessageToChat({
}
export function convertToUIMessages(
messages: Array<CoreMessage>,
messages: Array<CoreMessage>
): Array<Message> {
return messages.reduce((chatMessages: Array<Message>, message) => {
if (message.role === "tool") {
if (message.role === 'tool') {
return addToolMessageToChat({
toolMessage: message as CoreToolMessage,
messages: chatMessages,
});
}
let textContent = "";
let textContent = '';
let toolInvocations: Array<ToolInvocation> = [];
if (typeof message.content === "string") {
if (typeof message.content === 'string') {
textContent = message.content;
} else if (Array.isArray(message.content)) {
for (const content of message.content) {
if (content.type === "text") {
if (content.type === 'text') {
textContent += content.text;
} else if (content.type === "tool-call") {
} else if (content.type === 'tool-call') {
toolInvocations.push({
state: "call",
state: 'call',
toolCallId: content.toolCallId,
toolName: content.toolName,
args: content.args,
@ -131,8 +132,92 @@ export function getTitleFromChat(chat: Chat) {
const firstMessage = messages[0];
if (!firstMessage) {
return "Untitled";
return 'Untitled';
}
return firstMessage.content;
}
const emptyAssistantMessage = [
{
role: 'assistant',
content: [
{
type: 'text',
text: '',
},
],
},
];
export function sanitizeResponseMessages(
messages: Array<CoreToolMessage | CoreAssistantMessage>
): Array<CoreToolMessage | CoreAssistantMessage> {
let toolResultIds: Array<string> = [];
for (const message of messages) {
if (message.role === 'tool') {
for (const content of message.content) {
if (content.type === 'tool-result') {
toolResultIds.push(content.toolCallId);
}
}
}
}
const messagesBySanitizedContent = messages.map((message) => {
if (message.role !== 'assistant') return message;
if (typeof message.content === 'string') return message;
const sanitizedContent = message.content.filter((content) =>
content.type === 'tool-call'
? toolResultIds.includes(content.toolCallId)
: content.type === 'text'
? content.text.length > 0
: true
);
return {
...message,
content: sanitizedContent,
};
});
return messagesBySanitizedContent.filter(
(message) => message.content.length > 0
);
}
export function sanitizeUIMessages(messages: Array<Message>): Array<Message> {
const messagesBySanitizedToolInvocations = messages.map((message) => {
if (message.role !== 'assistant') return message;
if (!message.toolInvocations) return message;
let toolResultIds: Array<string> = [];
for (const toolInvocation of message.toolInvocations) {
if (toolInvocation.state === 'result') {
toolResultIds.push(toolInvocation.toolCallId);
}
}
const sanitizedToolInvocations = message.toolInvocations.filter(
(toolInvocation) =>
toolInvocation.state === 'result' ||
toolResultIds.includes(toolInvocation.toolCallId)
);
return {
...message,
toolInvocations: sanitizedToolInvocations,
};
});
return messagesBySanitizedToolInvocations.filter(
(message) =>
message.content.length > 0 ||
(message.toolInvocations && message.toolInvocations.length > 0)
);
}