Add canvas interface (#461)
This commit is contained in:
parent
1a74a5ca9a
commit
b3cb0ea755
44 changed files with 7454 additions and 4691 deletions
123
lib/utils.ts
123
lib/utils.ts
|
|
@ -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)
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue