🤖 feat: Add Agents librechat.yaml Configuration (#4953)

* feat: CONFIG_VERSION v1.1.9, agents config

* refactor: Assistants Code Interpreter Toggle Improved Accessibility

* feat: Agents Config
This commit is contained in:
Danny Avila 2024-12-12 08:58:00 -05:00 committed by GitHub
parent 51e016ef2c
commit e82af236bc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 65 additions and 48 deletions

View file

@ -27,6 +27,15 @@ async function endpointController(req, res) {
capabilities,
};
}
if (mergedConfig[EModelEndpoint.agents] && req.app.locals?.[EModelEndpoint.agents]) {
const { disableBuilder, capabilities, ..._rest } = req.app.locals[EModelEndpoint.agents];
mergedConfig[EModelEndpoint.agents] = {
...mergedConfig[EModelEndpoint.agents],
disableBuilder,
capabilities,
};
}
if (
mergedConfig[EModelEndpoint.azureAssistants] &&

View file

@ -7,6 +7,7 @@ const handleRateLimits = require('./Config/handleRateLimits');
const { loadDefaultInterface } = require('./start/interface');
const { azureConfigSetup } = require('./start/azureOpenAI');
const { loadAndFormatTools } = require('./ToolService');
const { agentsConfigSetup } = require('./start/agents');
const { initializeRoles } = require('~/models/Role');
const paths = require('~/config/paths');
@ -94,6 +95,10 @@ const AppService = async (app) => {
);
}
if (endpoints?.[EModelEndpoint.agents]) {
endpointLocals[EModelEndpoint.agents] = agentsConfigSetup(config);
}
const endpointKeys = [
EModelEndpoint.openAI,
EModelEndpoint.google,

View file

@ -0,0 +1,14 @@
const { EModelEndpoint, agentsEndpointSChema } = require('librechat-data-provider');
/**
* Sets up the Agents configuration from the config (`librechat.yaml`) file.
* @param {TCustomConfig} config - The loaded custom configuration.
* @returns {Partial<TAgentsEndpoint>} The Agents endpoint configuration.
*/
function agentsConfigSetup(config) {
const agentsConfig = config.endpoints[EModelEndpoint.agents];
const parsedConfig = agentsEndpointSChema.parse(agentsConfig);
return parsedConfig;
}
module.exports = { agentsConfigSetup };

View file

@ -819,11 +819,17 @@
*/
/**
* @exports TAssistantEndpoint
* @exports TAgentsEndpoint
* @typedef {import('librechat-data-provider').TAssistantEndpoint} TAssistantEndpoint
* @memberof typedefs
*/
/**
* @exports TAgentsEndpoint
* @typedef {import('librechat-data-provider').TAgentsEndpoint} TAgentsEndpoint
* @memberof typedefs
*/
/**
* @exports Agent
* @typedef {import('librechat-data-provider').Agent} Agent

View file

@ -173,6 +173,7 @@ export type AgentPanelProps = {
setAction: React.Dispatch<React.SetStateAction<t.Action | undefined>>;
endpointsConfig?: t.TEndpointsConfig;
setCurrentAgentId: React.Dispatch<React.SetStateAction<string | undefined>>;
agentsConfig?: t.TAgentsEndpoint | null;
};
export type AgentModelPanelProps = {

View file

@ -9,7 +9,7 @@ import {
PermissionTypes,
AgentCapabilities,
} from 'librechat-data-provider';
import type { TConfig, TPlugin } from 'librechat-data-provider';
import type { TPlugin } from 'librechat-data-provider';
import type { AgentForm, AgentPanelProps } from '~/common';
import { cn, defaultTextProps, removeFocusOutlines, getEndpointField, getIconKey } from '~/utils';
import { useCreateAgentMutation, useUpdateAgentMutation } from '~/data-provider';
@ -43,7 +43,7 @@ export default function AgentConfig({
endpointsConfig,
setActivePanel,
setCurrentAgentId,
}: AgentPanelProps & { agentsConfig?: TConfig | null }) {
}: AgentPanelProps) {
const { user } = useAuthContext();
const fileMap = useFileMapContext();
const queryClient = useQueryClient();
@ -69,19 +69,19 @@ export default function AgentConfig({
});
const toolsEnabled = useMemo(
() => agentsConfig?.capabilities?.includes(AgentCapabilities.tools),
() => agentsConfig?.capabilities.includes(AgentCapabilities.tools),
[agentsConfig],
);
const actionsEnabled = useMemo(
() => agentsConfig?.capabilities?.includes(AgentCapabilities.actions),
() => agentsConfig?.capabilities.includes(AgentCapabilities.actions),
[agentsConfig],
);
const fileSearchEnabled = useMemo(
() => agentsConfig?.capabilities?.includes(AgentCapabilities.file_search) ?? false,
() => agentsConfig?.capabilities.includes(AgentCapabilities.file_search) ?? false,
[agentsConfig],
);
const codeEnabled = useMemo(
() => agentsConfig?.capabilities?.includes(AgentCapabilities.execute_code) ?? false,
() => agentsConfig?.capabilities.includes(AgentCapabilities.execute_code) ?? false,
[agentsConfig],
);

View file

@ -8,7 +8,6 @@ import {
isAssistantsEndpoint,
defaultAgentFormValues,
} from 'librechat-data-provider';
import type { TConfig } from 'librechat-data-provider';
import type { AgentForm, AgentPanelProps, StringOption } from '~/common';
import {
useCreateAgentMutation,
@ -33,7 +32,7 @@ export default function AgentPanel({
setCurrentAgentId,
agentsConfig,
endpointsConfig,
}: AgentPanelProps & { agentsConfig?: TConfig | null }) {
}: AgentPanelProps) {
const localize = useLocalize();
const { user } = useAuthContext();
const { showToast } = useToastContext();

View file

@ -30,26 +30,29 @@ export default function Code({ version }: { version: number | string }) {
checked={field.value}
onCheckedChange={field.onChange}
className="relative float-left mr-2 inline-flex h-4 w-4 cursor-pointer"
value={field?.value?.toString()}
value={field.value.toString()}
/>
)}
/>
<div className="flex items-center space-x-2">
<button
type="button"
className="flex items-center space-x-2"
onClick={() =>
setValue(Capabilities.code_interpreter, !getValues(Capabilities.code_interpreter), {
shouldDirty: true,
})
}
>
<label
className="form-check-label text-token-text-primary w-full cursor-pointer"
htmlFor={Capabilities.code_interpreter}
onClick={() =>
setValue(Capabilities.code_interpreter, !getValues(Capabilities.code_interpreter), {
shouldDirty: true,
})
}
>
{localize('com_assistants_code_interpreter')}
</label>
<HoverCardTrigger>
<CircleHelpIcon className="h-5 w-5 text-gray-500" />
</HoverCardTrigger>
</div>
</button>
<HoverCardPortal>
<HoverCardContent side={ESide.Top} className="w-80">
<div className="space-y-2">

View file

@ -76,7 +76,7 @@ export default function useSideNavLinks({
hasAccessToCreateAgents &&
isAgentsEndpoint(endpoint) &&
agents &&
// agents.disableBuilder !== true &&
agents.disableBuilder !== true &&
keyProvided &&
interfaceConfig.parameters === true
) {

View file

@ -119,7 +119,7 @@ export default {
com_agents_enable_file_search: 'Enable File Search',
com_agents_file_search_info:
'When enabled, the agent will be informed of the exact filenames listed below, allowing it to retrieve relevant context from these files.',
com_agents_code_interpreter_title: 'Code Interpreter',
com_agents_code_interpreter_title: 'Code Interpreter API',
com_agents_by_librechat: 'by LibreChat',
com_agents_code_interpreter:
'When enabled, allows your agent to leverage the LibreChat Code Interpreter API to run generated code, including file processing, securely. Requires a valid API key.',

2
package-lock.json generated
View file

@ -36153,7 +36153,7 @@
},
"packages/data-provider": {
"name": "librechat-data-provider",
"version": "0.7.60",
"version": "0.7.61",
"license": "ISC",
"dependencies": {
"@types/js-yaml": "^4.0.9",

View file

@ -1,6 +1,6 @@
{
"name": "librechat-data-provider",
"version": "0.7.60",
"version": "0.7.61",
"description": "data services for librechat apps",
"main": "dist/index.js",
"module": "dist/index.es.js",

View file

@ -208,37 +208,17 @@ export type TAssistantEndpoint = z.infer<typeof assistantEndpointSchema>;
export const agentsEndpointSChema = baseEndpointSchema.merge(
z.object({
/* assistants specific */
/* agents specific */
disableBuilder: z.boolean().optional(),
pollIntervalMs: z.number().optional(),
timeoutMs: z.number().optional(),
version: z.union([z.string(), z.number()]).default(2),
supportedIds: z.array(z.string()).min(1).optional(),
excludedIds: z.array(z.string()).min(1).optional(),
privateAssistants: z.boolean().optional(),
retrievalModels: z.array(z.string()).min(1).optional().default(defaultRetrievalModels),
capabilities: z
.array(z.nativeEnum(Capabilities))
.array(z.nativeEnum(AgentCapabilities))
.optional()
.default([
Capabilities.code_interpreter,
Capabilities.image_vision,
Capabilities.retrieval,
Capabilities.actions,
Capabilities.tools,
AgentCapabilities.execute_code,
AgentCapabilities.file_search,
AgentCapabilities.actions,
AgentCapabilities.tools,
]),
/* general */
apiKey: z.string().optional(),
models: z
.object({
default: z.array(z.string()).min(1),
fetch: z.boolean().optional(),
userIdQuery: z.boolean().optional(),
})
.optional(),
titleConvo: z.boolean().optional(),
titleMethod: z.union([z.literal('completion'), z.literal('functions')]).optional(),
headers: z.record(z.any()).optional(),
}),
);
@ -1097,7 +1077,7 @@ export enum Constants {
/** Key for the app's version. */
VERSION = 'v0.7.5',
/** Key for the Custom Config's version (librechat.yaml). */
CONFIG_VERSION = '1.1.8',
CONFIG_VERSION = '1.1.9',
/** Standard value for the first message's `parentMessageId` value, to indicate no parent exists. */
NO_PARENT = '00000000-0000-0000-0000-000000000000',
/** Standard value for the initial conversationId before a request is sent */