feat: support image outputs during code execution (#674)
Co-authored-by: Bailey Simrell <baileysimrell@gmail.com>
This commit is contained in:
parent
50fbc0dab2
commit
50bd4604b6
7 changed files with 313 additions and 117 deletions
|
|
@ -1,18 +1,12 @@
|
|||
import { cn, generateUUID } from '@/lib/utils';
|
||||
import { ClockRewind, CopyIcon, PlayIcon, RedoIcon, UndoIcon } from './icons';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { ClockRewind, CopyIcon, RedoIcon, UndoIcon } from './icons';
|
||||
import { Button } from './ui/button';
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from './ui/tooltip';
|
||||
import { useCopyToClipboard } from 'usehooks-ts';
|
||||
import { toast } from 'sonner';
|
||||
import { ConsoleOutput, UIBlock } from './block';
|
||||
import {
|
||||
Dispatch,
|
||||
memo,
|
||||
SetStateAction,
|
||||
startTransition,
|
||||
useCallback,
|
||||
useState,
|
||||
} from 'react';
|
||||
import { Dispatch, memo, SetStateAction } from 'react';
|
||||
import { RunCodeButton } from './run-code-button';
|
||||
|
||||
interface BlockActionsProps {
|
||||
block: UIBlock;
|
||||
|
|
@ -23,98 +17,6 @@ interface BlockActionsProps {
|
|||
setConsoleOutputs: Dispatch<SetStateAction<Array<ConsoleOutput>>>;
|
||||
}
|
||||
|
||||
export function RunCodeButton({
|
||||
block,
|
||||
setConsoleOutputs,
|
||||
}: {
|
||||
block: UIBlock;
|
||||
setConsoleOutputs: Dispatch<SetStateAction<Array<ConsoleOutput>>>;
|
||||
}) {
|
||||
const [pyodide, setPyodide] = useState<any>(null);
|
||||
const isPython = true;
|
||||
const codeContent = block.content;
|
||||
|
||||
const updateConsoleOutput = useCallback(
|
||||
(runId: string, content: string | null, status: 'completed' | 'failed') => {
|
||||
setConsoleOutputs((consoleOutputs) => {
|
||||
const index = consoleOutputs.findIndex((output) => output.id === runId);
|
||||
|
||||
if (index === -1) return consoleOutputs;
|
||||
|
||||
const updatedOutputs = [...consoleOutputs];
|
||||
updatedOutputs[index] = {
|
||||
id: runId,
|
||||
content,
|
||||
status,
|
||||
};
|
||||
|
||||
return updatedOutputs;
|
||||
});
|
||||
},
|
||||
[setConsoleOutputs],
|
||||
);
|
||||
|
||||
const loadAndRunPython = useCallback(async () => {
|
||||
const runId = generateUUID();
|
||||
|
||||
setConsoleOutputs((consoleOutputs) => [
|
||||
...consoleOutputs,
|
||||
{
|
||||
id: runId,
|
||||
content: null,
|
||||
status: 'in_progress',
|
||||
},
|
||||
]);
|
||||
|
||||
let currentPyodideInstance = pyodide;
|
||||
|
||||
if (isPython) {
|
||||
if (!currentPyodideInstance) {
|
||||
// @ts-expect-error - pyodide is not defined
|
||||
const newPyodideInstance = await loadPyodide({
|
||||
indexURL: 'https://cdn.jsdelivr.net/pyodide/v0.23.4/full/',
|
||||
});
|
||||
|
||||
setPyodide(newPyodideInstance);
|
||||
currentPyodideInstance = newPyodideInstance;
|
||||
}
|
||||
|
||||
try {
|
||||
await currentPyodideInstance.runPythonAsync(`
|
||||
import sys
|
||||
import io
|
||||
sys.stdout = io.StringIO()
|
||||
`);
|
||||
|
||||
await currentPyodideInstance.runPythonAsync(codeContent);
|
||||
|
||||
const output: string = await currentPyodideInstance.runPythonAsync(
|
||||
`sys.stdout.getvalue()`,
|
||||
);
|
||||
|
||||
updateConsoleOutput(runId, output, 'completed');
|
||||
} catch (error: any) {
|
||||
updateConsoleOutput(runId, error.message, 'failed');
|
||||
}
|
||||
}
|
||||
}, [pyodide, codeContent, isPython, setConsoleOutputs, updateConsoleOutput]);
|
||||
|
||||
return (
|
||||
<Button
|
||||
variant="outline"
|
||||
className="py-1.5 px-2 h-fit dark:hover:bg-zinc-700"
|
||||
onClick={() => {
|
||||
startTransition(() => {
|
||||
loadAndRunPython();
|
||||
});
|
||||
}}
|
||||
disabled={block.status === 'streaming'}
|
||||
>
|
||||
<PlayIcon size={18} /> Run
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
||||
function PureBlockActions({
|
||||
block,
|
||||
handleVersionChange,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue