🎉 feat: Code Interpreter API and Agents Release (#4860)

* feat: Code Interpreter API & File Search Agent Uploads

chore: add back code files

wip: first pass, abstract key dialog

refactor: influence checkbox on key changes

refactor: update localization keys for 'execute code' to 'run code'

wip: run code button

refactor: add throwError parameter to loadAuthValues and getUserPluginAuthValue functions

feat: first pass, API tool calling

fix: handle missing toolId in callTool function and return 404 for non-existent tools

feat: show code outputs

fix: improve error handling in callTool function and log errors

fix: handle potential null value for filepath in attachment destructuring

fix: normalize language before rendering and prevent null return

fix: add loading indicator in RunCode component while executing code

feat: add support for conditional code execution in Markdown components

feat: attachments

refactor: remove bash

fix: pass abort signal to graph/run

refactor: debounce and rate limit tool call

refactor: increase debounce delay for execute function

feat: set code output attachments

feat: image attachments

refactor: apply message context

refactor: pass `partIndex`

feat: toolCall schema/model/methods

feat: block indexing

feat: get tool calls

chore: imports

chore: typing

chore: condense type imports

feat: get tool calls

fix: block indexing

chore: typing

refactor: update tool calls mapping to support multiple results

fix: add unique key to nav link for rendering

wip: first pass, tool call results

refactor: update query cache from successful tool call mutation

style: improve result switcher styling

chore: note on using \`.toObject()\`

feat: add agent_id field to conversation schema

chore: typing

refactor: rename agentMap to agentsMap for consistency

feat: Agent Name as chat input placeholder

chore: bump agents

📦 chore: update @langchain dependencies to latest versions to match agents package

📦 chore: update @librechat/agents dependency to version 1.8.0

fix: Aborting agent stream removes sender; fix(bedrock): completion removes preset name label

refactor: remove direct file parameter to use req.file, add `processAgentFileUpload` for image uploads

feat: upload menu

feat: prime message_file resources

feat: implement conversation access validation in chat route

refactor: remove file parameter from processFileUpload and use req.file instead

feat: add savedMessageIds set to track saved message IDs in BaseClient, to prevent unnecessary double-write to db

feat: prevent duplicate message saves by checking savedMessageIds in AgentController

refactor: skip legacy RAG API handling for agents

feat: add files field to convoSchema

refactor: update request type annotations from Express.Request to ServerRequest in file processing functions

feat: track conversation files

fix: resendFiles, addPreviousAttachments handling

feat: add ID validation for session_id and file_id in download route

feat: entity_id for code file uploads/downloads

fix: code file edge cases

feat: delete related tool calls

feat: add stream rate handling for LLM configuration

feat: enhance system content with attached file information

fix: improve error logging in resource priming function

* WIP: PoC, sequential agents

WIP: PoC Sequential Agents, first pass content data + bump agents package

fix: package-lock

WIP: PoC, o1 support, refactor bufferString

feat: convertJsonSchemaToZod

fix: form issues and schema defining erroneous model

fix: max length issue on agent form instructions, limit conversation messages to sequential agents

feat: add abort signal support to createRun function and AgentClient

feat: PoC, hide prior sequential agent steps

fix: update parameter naming from config to metadata in event handlers for clarity, add model to usage data

refactor: use only last contentData, track model for usage data

chore: bump agents package

fix: content parts issue

refactor: filter contentParts to include tool calls and relevant indices

feat: show function calls

refactor: filter context messages to exclude tool calls when no tools are available to the agent

fix: ensure tool call content is not undefined in formatMessages

feat: add agent_id field to conversationPreset schema

feat: hide sequential agents

feat: increase upload toast duration to 10 seconds

* refactor: tool context handling & update Code API Key Dialog

feat: toolContextMap

chore: skipSpecs -> useSpecs

ci: fix handleTools tests

feat: API Key Dialog

* feat: Agent Permissions Admin Controls

feat: replace label with button for prompt permission toggle

feat: update agent permissions

feat: enable experimental agents and streamline capability configuration

feat: implement access control for agents and enhance endpoint menu items

feat: add welcome message for agent selection in localization

feat: add agents permission to access control and update version to 0.7.57

* fix: update types in useAssistantListMap and useMentions hooks for better null handling

* feat: mention agents

* fix: agent tool resource race conditions when deleting agent tool resource files

* feat: add error handling for code execution with user feedback

* refactor: rename AdminControls to AdminSettings for clarity

* style: add gap to button in AdminSettings for improved layout

* refactor: separate agent query hooks and check access to enable fetching

* fix: remove unused provider from agent initialization options, creates issue with custom endpoints

* refactor: remove redundant/deprecated modelOptions from AgentClient processes

* chore: update @librechat/agents to version 1.8.5 in package.json and package-lock.json

* fix: minor styling issues + agent panel uniformity

* fix: agent edge cases when set endpoint is no longer defined

* refactor: remove unused cleanup function call from AppService

* fix: update link in ApiKeyDialog to point to pricing page

* fix: improve type handling and layout calculations in SidePanel component

* fix: add missing localization string for agent selection in SidePanel

* chore: form styling and localizations for upload filesearch/code interpreter

* fix: model selection placeholder logic in AgentConfig component

* style: agent capabilities

* fix: add localization for provider selection and improve dropdown styling in ModelPanel

* refactor: use gpt-4o-mini > gpt-3.5-turbo

* fix: agents configuration for loadDefaultInterface and update related tests

* feat: DALLE Agents support
This commit is contained in:
Danny Avila 2024-12-04 15:48:13 -05:00 committed by GitHub
parent affcebd48c
commit 1a815f5e19
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
189 changed files with 5056 additions and 1815 deletions

View file

@ -11,6 +11,8 @@ export type TAgentOption = OptionWithIcon &
export type TAgentCapabilities = {
[AgentCapabilities.execute_code]: boolean;
[AgentCapabilities.file_search]: boolean;
[AgentCapabilities.end_after_tools]?: boolean;
[AgentCapabilities.hide_sequential_outputs]?: boolean;
};
export type AgentForm = {
@ -23,4 +25,5 @@ export type AgentForm = {
model_parameters: AgentModelParameters;
tools?: string[];
provider?: AgentProvider | OptionWithIcon;
agent_ids?: string[];
} & TAgentCapabilities;

View file

@ -1,5 +1,6 @@
export * from './a11y';
export * from './artifacts';
export * from './types';
export * from './tools';
export * from './assistants-types';
export * from './agents-types';

View file

@ -0,0 +1,6 @@
import type { AuthType } from 'librechat-data-provider';
export type ApiKeyFormData = {
apiKey: string;
authType?: string | AuthType;
};

View file

@ -1,36 +1,21 @@
import React from 'react';
import { RefObject } from 'react';
import { FileSources } from 'librechat-data-provider';
import type * as InputNumberPrimitive from 'rc-input-number';
import type { ColumnDef } from '@tanstack/react-table';
import type { SetterOrUpdater } from 'recoil';
import type {
TRole,
TUser,
Agent,
Action,
TPreset,
TPlugin,
TMessage,
Assistant,
TResPlugin,
TLoginUser,
AuthTypeEnum,
TModelsConfig,
TConversation,
TStartupConfig,
EModelEndpoint,
TEndpointsConfig,
ActionMetadata,
AssistantDocument,
AssistantsEndpoint,
TMessageContentParts,
AuthorizationTypeEnum,
TSetOption as SetOption,
TokenExchangeMethodEnum,
} from 'librechat-data-provider';
import type * as t from 'librechat-data-provider';
import type { UseMutationResult } from '@tanstack/react-query';
import type { LucideIcon } from 'lucide-react';
export type CodeBarProps = {
lang: string;
error?: boolean;
plugin?: boolean;
blockIndex?: number;
allowExecution?: boolean;
codeRef: RefObject<HTMLElement>;
};
export enum PromptsEditorMode {
SIMPLE = 'simple',
ADVANCED = 'advanced',
@ -65,21 +50,21 @@ export type AudioChunk = {
export type AssistantListItem = {
id: string;
name: string;
metadata: Assistant['metadata'];
metadata: t.Assistant['metadata'];
model: string;
};
export type AgentListItem = {
id: string;
name: string;
avatar: Agent['avatar'];
avatar: t.Agent['avatar'];
};
export type TPluginMap = Record<string, TPlugin>;
export type TPluginMap = Record<string, t.TPlugin>;
export type GenericSetter<T> = (value: T | ((currentValue: T) => T)) => void;
export type LastSelectedModels = Record<EModelEndpoint, string>;
export type LastSelectedModels = Record<t.EModelEndpoint, string>;
export type LocalizeFunction = (phraseKey: string, ...values: string[]) => string;
@ -145,11 +130,11 @@ export type FileSetter =
export type ActionAuthForm = {
/* General */
type: AuthTypeEnum;
type: t.AuthTypeEnum;
saved_auth_fields: boolean;
/* API key */
api_key: string; // not nested
authorization_type: AuthorizationTypeEnum;
authorization_type: t.AuthorizationTypeEnum;
custom_auth_header: string;
/* OAuth */
oauth_client_id: string; // not nested
@ -157,23 +142,23 @@ export type ActionAuthForm = {
authorization_url: string;
client_url: string;
scope: string;
token_exchange_method: TokenExchangeMethodEnum;
token_exchange_method: t.TokenExchangeMethodEnum;
};
export type ActionWithNullableMetadata = Omit<Action, 'metadata'> & {
metadata: ActionMetadata | null;
export type ActionWithNullableMetadata = Omit<t.Action, 'metadata'> & {
metadata: t.ActionMetadata | null;
};
export type AssistantPanelProps = {
index?: number;
action?: ActionWithNullableMetadata;
actions?: Action[];
actions?: t.Action[];
assistant_id?: string;
activePanel?: string;
endpoint: AssistantsEndpoint;
endpoint: t.AssistantsEndpoint;
version: number | string;
documentsMap: Map<string, AssistantDocument> | null;
setAction: React.Dispatch<React.SetStateAction<Action | undefined>>;
documentsMap: Map<string, t.AssistantDocument> | null;
setAction: React.Dispatch<React.SetStateAction<t.Action | undefined>>;
setCurrentAssistantId: React.Dispatch<React.SetStateAction<string | undefined>>;
setActivePanel: React.Dispatch<React.SetStateAction<Panel>>;
};
@ -182,11 +167,11 @@ export type AgentPanelProps = {
index?: number;
agent_id?: string;
activePanel?: string;
action?: Action;
actions?: Action[];
action?: t.Action;
actions?: t.Action[];
setActivePanel: React.Dispatch<React.SetStateAction<Panel>>;
setAction: React.Dispatch<React.SetStateAction<Action | undefined>>;
endpointsConfig?: TEndpointsConfig;
setAction: React.Dispatch<React.SetStateAction<t.Action | undefined>>;
endpointsConfig?: t.TEndpointsConfig;
setCurrentAgentId: React.Dispatch<React.SetStateAction<string | undefined>>;
};
@ -199,7 +184,7 @@ export type AgentModelPanelProps = {
export type AugmentedColumnDef<TData, TValue> = ColumnDef<TData, TValue> & DataColumnMeta;
export type TSetOption = SetOption;
export type TSetOption = t.TSetOption;
export type TSetExample = (
i: number,
@ -234,7 +219,7 @@ export type TShowToast = {
};
export type TBaseSettingsProps = {
conversation: TConversation | TPreset | null;
conversation: t.TConversation | t.TPreset | null;
className?: string;
isPreset?: boolean;
readonly?: boolean;
@ -255,7 +240,7 @@ export type TModelSelectProps = TSettingsProps & TModels;
export type TEditPresetProps = {
open: boolean;
onOpenChange: React.Dispatch<React.SetStateAction<boolean>>;
preset: TPreset;
preset: t.TPreset;
title?: string;
};
@ -266,18 +251,18 @@ export type TSetOptionsPayload = {
addExample: () => void;
removeExample: () => void;
setAgentOption: TSetOption;
// getConversation: () => TConversation | TPreset | null;
// getConversation: () => t.TConversation | t.TPreset | null;
checkPluginSelection: (value: string) => boolean;
setTools: (newValue: string, remove?: boolean) => void;
setOptions?: TSetOptions;
};
export type TPresetItemProps = {
preset: TPreset;
value: TPreset;
onSelect: (preset: TPreset) => void;
onChangePreset: (preset: TPreset) => void;
onDeletePreset: (preset: TPreset) => void;
preset: t.TPreset;
value: t.TPreset;
onSelect: (preset: t.TPreset) => void;
onChangePreset: (preset: t.TPreset) => void;
onDeletePreset: (preset: t.TPreset) => void;
};
export type TOnClick = (e: React.MouseEvent<HTMLButtonElement>) => void;
@ -302,16 +287,16 @@ export type TOptions = {
isRegenerate?: boolean;
isContinued?: boolean;
isEdited?: boolean;
overrideMessages?: TMessage[];
overrideMessages?: t.TMessage[];
};
export type TAskFunction = (props: TAskProps, options?: TOptions) => void;
export type TMessageProps = {
conversation?: TConversation | null;
conversation?: t.TConversation | null;
messageId?: string | null;
message?: TMessage;
messagesTree?: TMessage[];
message?: t.TMessage;
messagesTree?: t.TMessage[];
currentEditId: string | number | null;
isSearchView?: boolean;
siblingIdx?: number;
@ -330,7 +315,7 @@ export type TInitialProps = {
};
export type TAdditionalProps = {
ask: TAskFunction;
message: TMessage;
message: t.TMessage;
isCreatedByUser: boolean;
siblingIdx: number;
enterEdit: (cancel: boolean) => void;
@ -354,7 +339,7 @@ export type TDisplayProps = TText &
export type TConfigProps = {
userKey: string;
setUserKey: React.Dispatch<React.SetStateAction<string>>;
endpoint: EModelEndpoint | string;
endpoint: t.EModelEndpoint | string;
};
export type TDangerButtonProps = {
@ -389,18 +374,18 @@ export type TResError = {
};
export type TAuthContext = {
user: TUser | undefined;
user: t.TUser | undefined;
token: string | undefined;
isAuthenticated: boolean;
error: string | undefined;
login: (data: TLoginUser) => void;
login: (data: t.TLoginUser) => void;
logout: () => void;
setError: React.Dispatch<React.SetStateAction<string | undefined>>;
roles?: Record<string, TRole | null | undefined>;
roles?: Record<string, t.TRole | null | undefined>;
};
export type TUserContext = {
user?: TUser | undefined;
user?: t.TUser | undefined;
token: string | undefined;
isAuthenticated: boolean;
redirect?: string;
@ -411,16 +396,16 @@ export type TAuthConfig = {
test?: boolean;
};
export type IconProps = Pick<TMessage, 'isCreatedByUser' | 'model'> &
Pick<TConversation, 'chatGptLabel' | 'modelLabel' | 'jailbreak'> & {
export type IconProps = Pick<t.TMessage, 'isCreatedByUser' | 'model'> &
Pick<t.TConversation, 'chatGptLabel' | 'modelLabel' | 'jailbreak'> & {
size?: number;
button?: boolean;
iconURL?: string;
message?: boolean;
className?: string;
iconClassName?: string;
endpoint?: EModelEndpoint | string | null;
endpointType?: EModelEndpoint | null;
endpoint?: t.EModelEndpoint | string | null;
endpointType?: t.EModelEndpoint | null;
assistantName?: string;
agentName?: string;
error?: boolean;
@ -440,7 +425,7 @@ export type VoiceOption = {
export type TMessageAudio = {
messageId?: string;
content?: TMessageContentParts[] | string;
content?: t.TMessageContentParts[] | string;
className?: string;
isLast: boolean;
index: number;
@ -482,12 +467,12 @@ export interface ExtendedFile {
export type ContextType = { navVisible: boolean; setNavVisible: (visible: boolean) => void };
export interface SwitcherProps {
endpoint?: EModelEndpoint | null;
endpoint?: t.EModelEndpoint | null;
endpointKeyProvided: boolean;
isCollapsed: boolean;
}
export type TLoginLayoutContext = {
startupConfig: TStartupConfig | null;
startupConfig: t.TStartupConfig | null;
startupConfigError: unknown;
isFetching: boolean;
error: string | null;
@ -497,34 +482,34 @@ export type TLoginLayoutContext = {
};
export type NewConversationParams = {
template?: Partial<TConversation>;
preset?: Partial<TPreset>;
modelsData?: TModelsConfig;
template?: Partial<t.TConversation>;
preset?: Partial<t.TPreset>;
modelsData?: t.TModelsConfig;
buildDefault?: boolean;
keepLatestMessage?: boolean;
keepAddedConvos?: boolean;
};
export type ConvoGenerator = (params: NewConversationParams) => void | TConversation;
export type ConvoGenerator = (params: NewConversationParams) => void | t.TConversation;
export type TBaseResData = {
plugin?: TResPlugin;
plugin?: t.TResPlugin;
final?: boolean;
initial?: boolean;
previousMessages?: TMessage[];
conversation: TConversation;
previousMessages?: t.TMessage[];
conversation: t.TConversation;
conversationId?: string;
runMessages?: TMessage[];
runMessages?: t.TMessage[];
};
export type TResData = TBaseResData & {
requestMessage: TMessage;
responseMessage: TMessage;
requestMessage: t.TMessage;
responseMessage: t.TMessage;
};
export type TFinalResData = TBaseResData & {
requestMessage?: TMessage;
responseMessage?: TMessage;
requestMessage?: t.TMessage;
responseMessage?: t.TMessage;
};
export type TVectorStore = {