mirror of
https://github.com/run-llama/ai-chatbot.git
synced 2026-07-01 21:14:02 -04:00
152 lines
3.8 KiB
TypeScript
152 lines
3.8 KiB
TypeScript
import { memo } from 'react';
|
|
|
|
import type { BlockKind } from './block';
|
|
import { FileIcon, LoaderIcon, MessageIcon, PencilEditIcon } from './icons';
|
|
import { toast } from 'sonner';
|
|
import { useBlock } from '@/hooks/use-block';
|
|
|
|
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: BlockKind };
|
|
isReadonly: boolean;
|
|
}
|
|
|
|
function PureDocumentToolResult({
|
|
type,
|
|
result,
|
|
isReadonly,
|
|
}: DocumentToolResultProps) {
|
|
const { setBlock } = useBlock();
|
|
|
|
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,
|
|
};
|
|
|
|
setBlock({
|
|
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 };
|
|
isReadonly: boolean;
|
|
}
|
|
|
|
function PureDocumentToolCall({
|
|
type,
|
|
args,
|
|
isReadonly,
|
|
}: DocumentToolCallProps) {
|
|
const { setBlock } = useBlock();
|
|
|
|
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,
|
|
};
|
|
|
|
setBlock((currentBlock) => ({
|
|
...currentBlock,
|
|
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')} ${args.title ? `"${args.title}"` : ''}`}
|
|
</div>
|
|
</div>
|
|
|
|
<div className="animate-spin mt-1">{<LoaderIcon />}</div>
|
|
</button>
|
|
);
|
|
}
|
|
|
|
export const DocumentToolCall = memo(PureDocumentToolCall, () => true);
|