import debounce from 'lodash/debounce'; import { Tools, AuthType } from 'librechat-data-provider'; import { TerminalSquareIcon } from 'lucide-react'; import React, { useMemo, useCallback, useEffect } from 'react'; import type { CodeBarProps } from '~/common'; import { useVerifyAgentToolAuth, useToolCallMutation } from '~/data-provider'; import ApiKeyDialog from '~/components/SidePanel/Agents/Code/ApiKeyDialog'; import { useLocalize, useCodeApiKeyForm } from '~/hooks'; import { useMessageContext } from '~/Providers'; import { cn, normalizeLanguage } from '~/utils'; import { useToastContext } from '~/Providers'; import { Spinner } from '~/components'; const RunCode: React.FC = React.memo(({ lang, codeRef, blockIndex }) => { const localize = useLocalize(); const { showToast } = useToastContext(); const execute = useToolCallMutation(Tools.execute_code, { onError: () => { showToast({ message: localize('com_ui_run_code_error'), status: 'error' }); }, }); const { messageId, conversationId, partIndex } = useMessageContext(); const normalizedLang = useMemo(() => normalizeLanguage(lang), [lang]); const { data } = useVerifyAgentToolAuth( { toolId: Tools.execute_code }, { retry: 1, }, ); const authType = useMemo(() => data?.message ?? false, [data?.message]); const isAuthenticated = useMemo(() => data?.authenticated ?? false, [data?.authenticated]); const { methods, onSubmit, isDialogOpen, setIsDialogOpen, handleRevokeApiKey } = useCodeApiKeyForm({}); const handleExecute = useCallback(async () => { if (!isAuthenticated) { setIsDialogOpen(true); return; } const codeString: string = codeRef.current?.textContent ?? ''; if ( typeof codeString !== 'string' || codeString.length === 0 || typeof normalizedLang !== 'string' || normalizedLang.length === 0 ) { return; } execute.mutate({ partIndex, messageId, blockIndex, conversationId: conversationId ?? '', lang: normalizedLang, code: codeString, }); }, [ codeRef, execute, partIndex, messageId, blockIndex, conversationId, normalizedLang, setIsDialogOpen, isAuthenticated, ]); const debouncedExecute = useMemo( () => debounce(handleExecute, 1000, { leading: true }), [handleExecute], ); useEffect(() => { return () => { debouncedExecute.cancel(); }; }, [debouncedExecute]); if (typeof normalizedLang !== 'string' || normalizedLang.length === 0) { return null; } return ( <> ); }); export default RunCode;