next-chat / components /document.tsx
NeoPy's picture
Upload folder using huggingface_hub
867b17d verified
raw
history blame
4.38 kB
import { memo } from 'react';
import type { ArtifactKind } from './artifact';
import { FileIcon, LoaderIcon, MessageIcon, PencilEditIcon } from './icons';
import { toast } from 'sonner';
import { useArtifact } from '@/hooks/use-artifact';
const getActionText = (
type: 'create' | 'update' | 'request-suggestions',
tense: 'present' | 'past',
) => {
switch (type) {
case 'create':
return tense === 'present' ? 'Creating' : 'Created';
case 'update':
return tense === 'present' ? 'Updating' : 'Updated';
case 'request-suggestions':
return tense === 'present'
? 'Adding suggestions'
: 'Added suggestions to';
default:
return null;
}
};
interface DocumentToolResultProps {
type: 'create' | 'update' | 'request-suggestions';
result: { id: string; title: string; kind: ArtifactKind };
isReadonly: boolean;
}
function PureDocumentToolResult({
type,
result,
isReadonly,
}: DocumentToolResultProps) {
const { setArtifact } = useArtifact();
return (
<button
type="button"
className="bg-background cursor-pointer border py-2 px-3 rounded-xl w-fit flex flex-row gap-3 items-start"
onClick={(event) => {
if (isReadonly) {
toast.error(
'Viewing files in shared chats is currently not supported.',
);
return;
}
const rect = event.currentTarget.getBoundingClientRect();
const boundingBox = {
top: rect.top,
left: rect.left,
width: rect.width,
height: rect.height,
};
setArtifact({
documentId: result.id,
kind: result.kind,
content: '',
title: result.title,
isVisible: true,
status: 'idle',
boundingBox,
});
}}
>
<div className="text-muted-foreground mt-1">
{type === 'create' ? (
<FileIcon />
) : type === 'update' ? (
<PencilEditIcon />
) : type === 'request-suggestions' ? (
<MessageIcon />
) : null}
</div>
<div className="text-left">
{`${getActionText(type, 'past')} "${result.title}"`}
</div>
</button>
);
}
export const DocumentToolResult = memo(PureDocumentToolResult, () => true);
interface DocumentToolCallProps {
type: 'create' | 'update' | 'request-suggestions';
args:
| { title: string; kind: ArtifactKind } // for create
| { id: string; description: string } // for update
| { documentId: string }; // for request-suggestions
isReadonly: boolean;
}
function PureDocumentToolCall({
type,
args,
isReadonly,
}: DocumentToolCallProps) {
const { setArtifact } = useArtifact();
return (
<button
type="button"
className="cursor pointer w-fit border py-2 px-3 rounded-xl flex flex-row items-start justify-between gap-3"
onClick={(event) => {
if (isReadonly) {
toast.error(
'Viewing files in shared chats is currently not supported.',
);
return;
}
const rect = event.currentTarget.getBoundingClientRect();
const boundingBox = {
top: rect.top,
left: rect.left,
width: rect.width,
height: rect.height,
};
setArtifact((currentArtifact) => ({
...currentArtifact,
isVisible: true,
boundingBox,
}));
}}
>
<div className="flex flex-row gap-3 items-start">
<div className="text-zinc-500 mt-1">
{type === 'create' ? (
<FileIcon />
) : type === 'update' ? (
<PencilEditIcon />
) : type === 'request-suggestions' ? (
<MessageIcon />
) : null}
</div>
<div className="text-left">
{`${getActionText(type, 'present')} ${
type === 'create' && 'title' in args && args.title
? `"${args.title}"`
: type === 'update' && 'description' in args
? `"${args.description}"`
: type === 'request-suggestions'
? 'for document'
: ''
}`}
</div>
</div>
<div className="animate-spin mt-1">{<LoaderIcon />}</div>
</button>
);
}
export const DocumentToolCall = memo(PureDocumentToolCall, () => true);