mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-24 20:30:13 +01:00
* refactor: Agent CodeFiles, abortUpload WIP * feat: code environment file upload * refactor: useLazyEffect * refactor: - Add `watch` from `useFormContext` to check if code execution is enabled - Disable file upload button if `agent_id` is not selected or code execution is disabled * WIP: primeCodeFiles; refactor: rename sessionId to session_id for uniformity * Refactor: Rename session_id to sessionId for uniformity in AuthService.js * chore: bump @librechat/agents to version 1.7.1 * WIP: prime code files * refactor: Update code env file upload method to use read stream * feat: reupload code env file if no longer active * refactor: isAssistantTool -> isEntityTool + address type issues * feat: execute code tool hook * refactor: Rename isPluginAuthenticated to checkPluginAuth in PluginController.js * refactor: Update PluginController.js to use AuthType constant for comparison * feat: verify tool authentication (execute_code) * feat: enter librechat_code_api_key * refactor: Remove unused imports in BookmarkForm.tsx * feat: authenticate code tool * refactor: Update Action.tsx to conditionally render the key and revoke key buttons * refactor(Code/Action): prevent uncheck-able 'Run Code' capability when key is revoked * refactor(Code/Action): Update Action.tsx to conditionally render the key and revoke key buttons * fix: agent file upload edge cases * chore: bump @librechat/agents * fix: custom endpoint providerValue icon * feat: ollama meta modal token values + context * feat: ollama agents * refactor: Update token models for Ollama models * chore: Comment out CodeForm * refactor: Update token models for Ollama and Meta models
106 lines
3.6 KiB
TypeScript
106 lines
3.6 KiB
TypeScript
import React, { useState } from 'react';
|
|
import { useFormContext } from 'react-hook-form';
|
|
import type { TPlugin } from 'librechat-data-provider';
|
|
import { useUpdateUserPluginsMutation } from 'librechat-data-provider/react-query';
|
|
import { OGDialog, OGDialogTrigger, Label } from '~/components/ui';
|
|
import OGDialogTemplate from '~/components/ui/OGDialogTemplate';
|
|
import { useToastContext } from '~/Providers';
|
|
import { TrashIcon } from '~/components/svg';
|
|
import { useLocalize } from '~/hooks';
|
|
import { cn } from '~/utils';
|
|
|
|
export default function AssistantTool({
|
|
tool,
|
|
allTools,
|
|
assistant_id = '',
|
|
}: {
|
|
tool: string;
|
|
allTools: TPlugin[];
|
|
assistant_id?: string;
|
|
}) {
|
|
const [isHovering, setIsHovering] = useState(false);
|
|
const localize = useLocalize();
|
|
const { showToast } = useToastContext();
|
|
const updateUserPlugins = useUpdateUserPluginsMutation();
|
|
const { getValues, setValue } = useFormContext();
|
|
const currentTool = allTools.find((t) => t.pluginKey === tool);
|
|
|
|
const removeTool = (tool: string) => {
|
|
if (tool) {
|
|
updateUserPlugins.mutate(
|
|
{ pluginKey: tool, action: 'uninstall', auth: null, isEntityTool: true },
|
|
{
|
|
onError: (error: unknown) => {
|
|
showToast({ message: `Error while deleting the tool: ${error}`, status: 'error' });
|
|
},
|
|
onSuccess: () => {
|
|
const fns = getValues('functions').filter((fn) => fn !== tool);
|
|
setValue('functions', fns);
|
|
showToast({ message: 'Tool deleted successfully', status: 'success' });
|
|
},
|
|
},
|
|
);
|
|
}
|
|
};
|
|
|
|
if (!currentTool) {
|
|
return null;
|
|
}
|
|
|
|
return (
|
|
<OGDialog>
|
|
<div
|
|
className={cn(
|
|
'flex w-full items-center rounded-lg text-sm',
|
|
!assistant_id ? 'opacity-40' : '',
|
|
)}
|
|
onMouseEnter={() => setIsHovering(true)}
|
|
onMouseLeave={() => setIsHovering(false)}
|
|
>
|
|
<div className="flex grow items-center">
|
|
{currentTool.icon && (
|
|
<div className="flex h-9 w-9 items-center justify-center overflow-hidden rounded-full">
|
|
<div
|
|
className="flex h-6 w-6 items-center justify-center overflow-hidden rounded-full bg-center bg-no-repeat dark:bg-white/20"
|
|
style={{ backgroundImage: `url(${currentTool.icon})`, backgroundSize: 'cover' }}
|
|
/>
|
|
</div>
|
|
)}
|
|
<div
|
|
className="h-9 grow px-3 py-2"
|
|
style={{ textOverflow: 'ellipsis', wordBreak: 'break-all', overflow: 'hidden' }}
|
|
>
|
|
{currentTool.name}
|
|
</div>
|
|
</div>
|
|
|
|
{isHovering && (
|
|
<OGDialogTrigger asChild>
|
|
<button
|
|
type="button"
|
|
className="flex h-9 w-9 min-w-9 items-center justify-center rounded-lg transition-colors duration-200 hover:bg-gray-200 dark:hover:bg-gray-700"
|
|
>
|
|
<TrashIcon />
|
|
</button>
|
|
</OGDialogTrigger>
|
|
)}
|
|
</div>
|
|
<OGDialogTemplate
|
|
showCloseButton={false}
|
|
title={localize('com_ui_delete_tool')}
|
|
className="max-w-[450px]"
|
|
main={
|
|
<Label className="text-left text-sm font-medium">
|
|
{localize('com_ui_delete_tool_confirm')}
|
|
</Label>
|
|
}
|
|
selection={{
|
|
selectHandler: () => removeTool(currentTool.pluginKey),
|
|
selectClasses:
|
|
'bg-red-700 dark:bg-red-600 hover:bg-red-800 dark:hover:bg-red-800 transition-colors duration-200 text-white',
|
|
selectText: localize('com_ui_delete'),
|
|
}}
|
|
/>
|
|
</OGDialog>
|
|
);
|
|
}
|