mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-01-02 08:38:51 +01:00
* agents - phase 1 (#30) * chore: copy assistant files * feat: frontend and data-provider * feat: backend get endpoint test * fix(MessageEndpointIcon): switched to AgentName and AgentAvatar * fix: small fixes * fix: agent endpoint config * fix: show Agent Builder * chore: install agentus * chore: initial scaffolding for agents * fix: updated Assistant logic to Agent Logic for some Agent components * WIP first pass, demo of agent package * WIP: initial backend infra for agents * fix: agent list error * wip: agents routing * chore: Refactor useSSE hook to handle different data events * wip: correctly emit events * chore: Update @librechat/agentus npm dependency to version 1.0.9 * remove comment * first pass: streaming agent text * chore: Remove @librechat/agentus root-level workspace npm dependency * feat: Agent Schema and Model * fix: content handling fixes * fix: content message save * WIP: new content data * fix: run step issue with tool calls * chore: Update @librechat/agentus npm dependency to version 1.1.5 * feat: update controller and agent routes * wip: initial backend tool and tool error handling support * wip: tool chunks * chore: Update @librechat/agentus npm dependency to version 1.1.7 * chore: update tool_call typing, add test conditions and logs * fix: create agent * fix: create agent * first pass: render completed content parts * fix: remove logging, fix step handler typing * chore: Update @librechat/agentus npm dependency to version 1.1.9 * refactor: cleanup maps on unmount * chore: Update BaseClient.js to safely count tokens for string, number, and boolean values * fix: support subsequent messages with tool_calls * chore: export order * fix: select agent * fix: tool call types and handling * chore: switch to anthropic for testing * fix: AgentSelect * refactor: experimental: OpenAIClient to use array for intermediateReply * fix(useSSE): revert old condition for streaming legacy client tokens * fix: lint * revert `agent_id` to `id` * chore: update localization keys for agent-related components * feat: zod schema handling for actions * refactor(actions): if no params, no zodSchema * chore: Update @librechat/agentus npm dependency to version 1.2.1 * feat: first pass, actions * refactor: empty schema for actions without params * feat: Update createRun function to accept additional options * fix: message payload formatting; feat: add more client options * fix: ToolCall component rendering when action has no args but has output * refactor(ToolCall): allow non-stringy args * WIP: first pass, correctly formatted tool_calls between providers * refactor: Remove duplicate import of 'roles' module * refactor: Exclude 'vite.config.ts' from TypeScript compilation * refactor: fix agent related types > - no need to use endpoint/model fields for identifying agent metadata > - add `provider` distinction for agent-configured 'endpoint' - no need for agent-endpoint map - reduce complexity of tools as functions into tools as string[] - fix types related to above changes - reduce unnecessary variables for queries/mutations and corresponding react-query keys * refactor: Add tools and tool_kwargs fields to agent schema * refactor: Remove unused code and update dependencies * refactor: Update updateAgentHandler to use req.body directly * refactor: Update AgentSelect component to use localized hooks * refactor: Update agent schema to include tools and provider fields * refactor(AgentPanel): add scrollbar gutter, add provider field to form, fix agent schema required values * refactor: Update AgentSwitcher component to use selectedAgentId instead of selectedAgent * refactor: Update AgentPanel component to include alternateName import and defaultAgentFormValues * refactor(SelectDropDown): allow setting value as option while still supporting legacy usage (string values only) * refactor: SelectDropdown changes - Only necessary when the available values are objects with label/value fields and the selected value is expected to be a string. * refactor: TypeError issues and handle provider as option * feat: Add placeholder for provider selection in AgentPanel component * refactor: Update agent schema to include author and provider fields * fix: show expected 'create agent' placeholder when creating agent * chore: fix localization strings, hide capabilities form for now * chore: typing * refactor: import order and use compact agents schema for now * chore: typing * refactor: Update AgentForm type to use AgentCapabilities * fix agent form agent selection issues * feat: responsive agent selection * fix: Handle cancelled fetch in useSelectAgent hook * fix: reset agent form on accordion close/open * feat: Add agent_id to default conversation for agents endpoint * feat: agents endpoint request handling * refactor: reset conversation model on agent select * refactor: add `additional_instructions` to conversation schema, organize other fields * chore: casing * chore: types * refactor(loadAgentTools): explicitly pass agent_id, do not pass `model` to loadAgentTools for now, load action sets by agent_id * WIP: initial draft of real agent client initialization * WIP: first pass, anthropic agent requests * feat: remember last selected agent * feat: openai and azure connected * fix: prioritize agent model for runs unless an explicit override model is passed from client * feat: Agent Actions * fix: save agent id to convo * feat: model panel (#29) * feat: model panel * bring back comments * fix: method still null * fix: AgentPanel FormContext * feat: add more parameters * fix: style issues; refactor: Agent Controller * fix: cherry-pick * fix: Update AgentAvatar component to use AssistantIcon instead of BrainCircuit * feat: OGDialog for delete agent; feat(assistant): update Agent types, introduced `model_parameters` * feat: icon and general `model_parameters` update * feat: use react-hook-form better * fix: agent builder form reset issue when switching panels * refactor: modularize agent builder form --------- Co-authored-by: Danny Avila <danny@librechat.ai> * fix: AgentPanel and ModelPanel type issues and use `useFormContext` and `watch` instead of `methods` directly and `useWatch`. * fix: tool call issues due to invalid input (anthropic) of empty string * fix: handle empty text in Part component --------- Co-authored-by: Marco Beretta <81851188+berry-13@users.noreply.github.com> * refactor: remove form ModelPanel and fixed nested ternary expressions in AgentConfig * fix: Model Parameters not saved correctly * refactor: remove console log * feat: avatar upload and get for Agents (#36) Co-authored-by: Marco Beretta <81851188+berry-13@users.noreply.github.com> * chore: update to public package * fix: typing, optional chaining * fix: cursor not showing for content parts * chore: conditionally enable agents * ci: fix azure test * ci: fix frontend tests, fix eslint api * refactor: Remove unused errorContentPart variable * continue of the agent message PR (#40) * last fixes * fix: agentMap * pr merge test (#41) * fix: model icon not fetching correctly * remove console logs * feat: agent name * refactor: pass documentsMap as a prop to allow re-render of assistant form * refactor: pass documentsMap as a prop to allow re-render of assistant form * chore: Bump version to 0.7.419 * fix: TypeError: Cannot read properties of undefined (reading 'id') * refactor: update AgentSwitcher component to use ControlCombobox instead of Combobox --------- Co-authored-by: Marco Beretta <81851188+berry-13@users.noreply.github.com>
198 lines
8.5 KiB
TypeScript
198 lines
8.5 KiB
TypeScript
import { useEffect, useState } from 'react';
|
|
import { useForm, FormProvider } from 'react-hook-form';
|
|
import {
|
|
AuthTypeEnum,
|
|
AuthorizationTypeEnum,
|
|
TokenExchangeMethodEnum,
|
|
} from 'librechat-data-provider';
|
|
import { ChevronLeft } from 'lucide-react';
|
|
import type { AgentPanelProps, ActionAuthForm } from '~/common';
|
|
import { Dialog, DialogTrigger, OGDialog, OGDialogTrigger, Label } from '~/components/ui';
|
|
import OGDialogTemplate from '~/components/ui/OGDialogTemplate';
|
|
import { useDeleteAgentAction } from '~/data-provider';
|
|
import useLocalize from '~/hooks/useLocalize';
|
|
import { useToastContext } from '~/Providers';
|
|
import { TrashIcon } from '~/components/svg';
|
|
import ActionsInput from './ActionsInput';
|
|
import ActionsAuth from './ActionsAuth';
|
|
import { Panel } from '~/common';
|
|
|
|
export default function ActionsPanel({
|
|
// activePanel,
|
|
action,
|
|
setAction,
|
|
agent_id,
|
|
setActivePanel,
|
|
}: AgentPanelProps) {
|
|
const localize = useLocalize();
|
|
const { showToast } = useToastContext();
|
|
|
|
const [openAuthDialog, setOpenAuthDialog] = useState(false);
|
|
const deleteAgentAction = useDeleteAgentAction({
|
|
onSuccess: () => {
|
|
showToast({
|
|
message: localize('com_assistants_delete_actions_success'),
|
|
status: 'success',
|
|
});
|
|
setActivePanel(Panel.builder);
|
|
setAction(undefined);
|
|
},
|
|
onError(error) {
|
|
showToast({
|
|
message: (error as Error)?.message ?? localize('com_assistants_delete_actions_error'),
|
|
status: 'error',
|
|
});
|
|
},
|
|
});
|
|
|
|
const methods = useForm<ActionAuthForm>({
|
|
defaultValues: {
|
|
/* General */
|
|
type: AuthTypeEnum.None,
|
|
saved_auth_fields: false,
|
|
/* API key */
|
|
api_key: '',
|
|
authorization_type: AuthorizationTypeEnum.Basic,
|
|
custom_auth_header: '',
|
|
/* OAuth */
|
|
oauth_client_id: '',
|
|
oauth_client_secret: '',
|
|
authorization_url: '',
|
|
client_url: '',
|
|
scope: '',
|
|
token_exchange_method: TokenExchangeMethodEnum.DefaultPost,
|
|
},
|
|
});
|
|
|
|
const { reset, watch } = methods;
|
|
const type = watch('type');
|
|
|
|
useEffect(() => {
|
|
if (action?.metadata?.auth) {
|
|
reset({
|
|
type: action.metadata.auth.type || AuthTypeEnum.None,
|
|
saved_auth_fields: false,
|
|
api_key: action.metadata.api_key ?? '',
|
|
authorization_type: action.metadata.auth.authorization_type || AuthorizationTypeEnum.Basic,
|
|
oauth_client_id: action.metadata.oauth_client_id ?? '',
|
|
oauth_client_secret: action.metadata.oauth_client_secret ?? '',
|
|
authorization_url: action.metadata.auth.authorization_url ?? '',
|
|
client_url: action.metadata.auth.client_url ?? '',
|
|
scope: action.metadata.auth.scope ?? '',
|
|
token_exchange_method:
|
|
action.metadata.auth.token_exchange_method ?? TokenExchangeMethodEnum.DefaultPost,
|
|
});
|
|
}
|
|
}, [action, reset]);
|
|
|
|
return (
|
|
<FormProvider {...methods}>
|
|
<form className="h-full grow overflow-hidden">
|
|
<div className="h-full overflow-auto px-2 pb-12 text-sm">
|
|
<div className="relative flex flex-col items-center px-16 py-6 text-center">
|
|
<div className="absolute left-0 top-6">
|
|
<button
|
|
type="button"
|
|
className="btn btn-neutral relative"
|
|
onClick={() => {
|
|
setActivePanel(Panel.builder);
|
|
setAction(undefined);
|
|
}}
|
|
>
|
|
<div className="flex w-full items-center justify-center gap-2">
|
|
<ChevronLeft />
|
|
</div>
|
|
</button>
|
|
</div>
|
|
|
|
{!!action && (
|
|
<OGDialog>
|
|
<OGDialogTrigger asChild>
|
|
<div className="absolute right-0 top-6">
|
|
<button
|
|
type="button"
|
|
disabled={!agent_id || !action.action_id}
|
|
className="btn btn-neutral border-token-border-light relative h-9 rounded-lg font-medium"
|
|
>
|
|
<TrashIcon className="text-red-500" />
|
|
</button>
|
|
</div>
|
|
</OGDialogTrigger>
|
|
<OGDialogTemplate
|
|
showCloseButton={false}
|
|
title={localize('com_ui_delete_action')}
|
|
className="max-w-[450px]"
|
|
main={
|
|
<Label className="text-left text-sm font-medium">
|
|
{localize('com_ui_delete_action_confirm')}
|
|
</Label>
|
|
}
|
|
selection={{
|
|
selectHandler: () => {
|
|
if (!agent_id) {
|
|
return showToast({
|
|
message: 'No agent_id found, is the agent created?',
|
|
status: 'error',
|
|
});
|
|
}
|
|
deleteAgentAction.mutate({
|
|
action_id: action.action_id,
|
|
agent_id,
|
|
});
|
|
},
|
|
selectClasses:
|
|
'bg-red-700 dark:bg-red-600 hover:bg-red-800 dark:hover:bg-red-800 transition-color duration-200 text-white',
|
|
selectText: localize('com_ui_delete'),
|
|
}}
|
|
/>
|
|
</OGDialog>
|
|
)}
|
|
|
|
<div className="text-xl font-medium">{(action ? 'Edit' : 'Add') + ' ' + 'actions'}</div>
|
|
<div className="text-token-text-tertiary text-sm">
|
|
{localize('com_assistants_actions_info')}
|
|
</div>
|
|
{/* <div className="text-sm text-token-text-tertiary">
|
|
<a href="https://help.openai.com/en/articles/8554397-creating-a-gpt" target="_blank" rel="noreferrer" className="font-medium">Learn more.</a>
|
|
</div> */}
|
|
</div>
|
|
<Dialog open={openAuthDialog} onOpenChange={setOpenAuthDialog}>
|
|
<DialogTrigger asChild>
|
|
<div className="relative mb-6">
|
|
<div className="mb-1.5 flex items-center">
|
|
<label className="text-token-text-primary block font-medium">
|
|
{localize('com_ui_authentication')}
|
|
</label>
|
|
</div>
|
|
<div className="border-token-border-medium flex rounded-lg border text-sm hover:cursor-pointer">
|
|
<div className="h-9 grow px-3 py-2">{type}</div>
|
|
<div className="bg-token-border-medium w-px"></div>
|
|
<button type="button" color="neutral" className="flex items-center gap-2 px-3">
|
|
<svg
|
|
width="24"
|
|
height="24"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
className="icon-sm"
|
|
>
|
|
<path
|
|
d="M11.6439 3C10.9352 3 10.2794 3.37508 9.92002 3.98596L9.49644 4.70605C8.96184 5.61487 7.98938 6.17632 6.93501 6.18489L6.09967 6.19168C5.39096 6.19744 4.73823 6.57783 4.38386 7.19161L4.02776 7.80841C3.67339 8.42219 3.67032 9.17767 4.01969 9.7943L4.43151 10.5212C4.95127 11.4386 4.95127 12.5615 4.43151 13.4788L4.01969 14.2057C3.67032 14.8224 3.67339 15.5778 4.02776 16.1916L4.38386 16.8084C4.73823 17.4222 5.39096 17.8026 6.09966 17.8083L6.93502 17.8151C7.98939 17.8237 8.96185 18.3851 9.49645 19.294L9.92002 20.014C10.2794 20.6249 10.9352 21 11.6439 21H12.3561C13.0648 21 13.7206 20.6249 14.08 20.014L14.5035 19.294C15.0381 18.3851 16.0106 17.8237 17.065 17.8151L17.9004 17.8083C18.6091 17.8026 19.2618 17.4222 19.6162 16.8084L19.9723 16.1916C20.3267 15.5778 20.3298 14.8224 19.9804 14.2057L19.5686 13.4788C19.0488 12.5615 19.0488 11.4386 19.5686 10.5212L19.9804 9.7943C20.3298 9.17767 20.3267 8.42219 19.9723 7.80841L19.6162 7.19161C19.2618 6.57783 18.6091 6.19744 17.9004 6.19168L17.065 6.18489C16.0106 6.17632 15.0382 5.61487 14.5036 4.70605L14.08 3.98596C13.7206 3.37508 13.0648 3 12.3561 3H11.6439Z"
|
|
stroke="currentColor"
|
|
strokeWidth="2"
|
|
strokeLinejoin="round"
|
|
/>
|
|
<circle cx="12" cy="12" r="2.5" stroke="currentColor" strokeWidth="2" />
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</DialogTrigger>
|
|
<ActionsAuth setOpenAuthDialog={setOpenAuthDialog} />
|
|
</Dialog>
|
|
<ActionsInput action={action} agent_id={agent_id} setAction={setAction} />
|
|
</div>
|
|
</form>
|
|
</FormProvider>
|
|
);
|
|
}
|