🧠 feat: User Memories for Conversational Context (#7760)

* 🧠 feat: User Memories for Conversational Context

chore: mcp typing, use `t`

WIP: first pass, Memories UI

- Added MemoryViewer component for displaying, editing, and deleting user memories.
- Integrated data provider hooks for fetching, updating, and deleting memories.
- Implemented pagination and loading states for better user experience.
- Created unit tests for MemoryViewer to ensure functionality and interaction with data provider.
- Updated translation files to include new UI strings related to memories.

chore: move mcp-related files to own directory

chore: rename librechat-mcp to librechat-api

WIP: first pass, memory processing and data schemas

chore: linting in fileSearch.js query description

chore: rename librechat-api to @librechat/api across the project

WIP: first pass, functional memory agent

feat: add MemoryEditDialog and MemoryViewer components for managing user memories

- Introduced MemoryEditDialog for editing memory entries with validation and toast notifications.
- Updated MemoryViewer to support editing and deleting memories, including pagination and loading states.
- Enhanced data provider to handle memory updates with optional original key for better management.
- Added new localization strings for memory-related UI elements.

feat: add memory permissions management

- Implemented memory permissions in the backend, allowing roles to have specific permissions for using, creating, updating, and reading memories.
- Added new API endpoints for updating memory permissions associated with roles.
- Created a new AdminSettings component for managing memory permissions in the frontend.
- Integrated memory permissions into the existing roles and permissions schemas.
- Updated the interface to include memory settings and permissions.
- Enhanced the MemoryViewer component to conditionally render admin settings based on user roles.
- Added localization support for memory permissions in the translation files.

feat: move AdminSettings component to a new position in MemoryViewer for better visibility

refactor: clean up commented code in MemoryViewer component

feat: enhance MemoryViewer with search functionality and improve MemoryEditDialog integration

- Added a search input to filter memories in the MemoryViewer component.
- Refactored MemoryEditDialog to accept children for better customization.
- Updated MemoryViewer to utilize the new EditMemoryButton and DeleteMemoryButton components for editing and deleting memories.
- Improved localization support by adding new strings for memory filtering and deletion confirmation.

refactor: optimize memory filtering in MemoryViewer using match-sorter

- Replaced manual filtering logic with match-sorter for improved search functionality.
- Enhanced performance and readability of the filteredMemories computation.

feat: enhance MemoryEditDialog with triggerRef and improve updateMemory mutation handling

feat: implement access control for MemoryEditDialog and MemoryViewer components

refactor: remove commented out code and create runMemory method

refactor: rename role based files

feat: implement access control for memory usage in AgentClient

refactor: simplify checkVisionRequest method in AgentClient by removing commented-out code

refactor: make `agents` dir in api package

refactor: migrate Azure utilities to TypeScript and consolidate imports

refactor: move sanitizeFilename function to a new file and update imports, add related tests

refactor: update LLM configuration types and consolidate Azure options in the API package

chore: linting

chore: import order

refactor: replace getLLMConfig with getOpenAIConfig and remove unused LLM configuration file

chore: update winston-daily-rotate-file to version 5.0.0 and add object-hash dependency in package-lock.json

refactor: move primeResources and optionalChainWithEmptyCheck functions to resources.ts and update imports

refactor: move createRun function to a new run.ts file and update related imports

fix: ensure safeAttachments is correctly typed as an array of TFile

chore: add node-fetch dependency and refactor fetch-related functions into packages/api/utils, removing the old generators file

refactor: enhance TEndpointOption type by using Pick to streamline endpoint fields and add new properties for model parameters and client options

feat: implement initializeOpenAIOptions function and update OpenAI types for enhanced configuration handling

fix: update types due to new TEndpointOption typing

fix: ensure safe access to group parameters in initializeOpenAIOptions function

fix: remove redundant API key validation comment in initializeOpenAIOptions function

refactor: rename initializeOpenAIOptions to initializeOpenAI for consistency and update related documentation

refactor: decouple req.body fields and tool loading from initializeAgentOptions

chore: linting

refactor: adjust column widths in MemoryViewer for improved layout

refactor: simplify agent initialization by creating loadAgent function and removing unused code

feat: add memory configuration loading and validation functions

WIP: first pass, memory processing with config

feat: implement memory callback and artifact handling

feat: implement memory artifacts display and processing updates

feat: add memory configuration options and schema validation for validKeys

fix: update MemoryEditDialog and MemoryViewer to handle memory state and display improvements

refactor: remove padding from BookmarkTable and MemoryViewer headers for consistent styling

WIP: initial tokenLimit config and move Tokenizer to @librechat/api

refactor: update mongoMeili plugin methods to use callback for better error handling

feat: enhance memory management with token tracking and usage metrics

- Added token counting for memory entries to enforce limits and provide usage statistics.
- Updated memory retrieval and update routes to include total token usage and limit.
- Enhanced MemoryEditDialog and MemoryViewer components to display memory usage and token information.
- Refactored memory processing functions to handle token limits and provide feedback on memory capacity.

feat: implement memory artifact handling in attachment handler

- Enhanced useAttachmentHandler to process memory artifacts when receiving updates.
- Introduced handleMemoryArtifact utility to manage memory updates and deletions.
- Updated query client to reflect changes in memory state based on incoming data.

refactor: restructure web search key extraction logic

- Moved the logic for extracting API keys from the webSearchAuth configuration into a dedicated function, getWebSearchKeys.
- Updated webSearchKeys to utilize the new function for improved clarity and maintainability.
- Prevents build time errors

feat: add personalization settings and memory preferences management

- Introduced a new Personalization tab in settings to manage user memory preferences.
- Implemented API endpoints and client-side logic for updating memory preferences.
- Enhanced user interface components to reflect personalization options and memory usage.
- Updated permissions to allow users to opt out of memory features.
- Added localization support for new settings and messages related to personalization.

style: personalization switch class

feat: add PersonalizationIcon and align Side Panel UI

feat: implement memory creation functionality

- Added a new API endpoint for creating memory entries, including validation for key and value.
- Introduced MemoryCreateDialog component for user interface to facilitate memory creation.
- Integrated token limit checks to prevent exceeding user memory capacity.
- Updated MemoryViewer to include a button for opening the memory creation dialog.
- Enhanced localization support for new messages related to memory creation.

feat: enhance message processing with configurable window size

- Updated AgentClient to use a configurable message window size for processing messages.
- Introduced messageWindowSize option in memory configuration schema with a default value of 5.
- Improved logic for selecting messages to process based on the configured window size.

chore: update librechat-data-provider version to 0.7.87 in package.json and package-lock.json

chore: remove OpenAPIPlugin and its associated tests

chore: remove MIGRATION_README.md as migration tasks are completed

ci: fix backend tests

chore: remove unused translation keys from localization file

chore: remove problematic test file and unused var in AgentClient

chore: remove unused import and import directly for JSDoc

* feat: add api package build stage in Dockerfile for improved modularity

* docs: reorder build steps in contributing guide for clarity
This commit is contained in:
Danny Avila 2025-06-07 18:52:22 -04:00 committed by GitHub
parent cd7dd576c1
commit 29ef91b4dd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
170 changed files with 5700 additions and 3632 deletions

View file

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

View file

@ -254,6 +254,7 @@ export const getAllPromptGroups = () => `${prompts()}/all`;
export const roles = () => '/api/roles';
export const getRole = (roleName: string) => `${roles()}/${roleName.toLowerCase()}`;
export const updatePromptPermissions = (roleName: string) => `${getRole(roleName)}/prompts`;
export const updateMemoryPermissions = (roleName: string) => `${getRole(roleName)}/memories`;
export const updateAgentPermissions = (roleName: string) => `${getRole(roleName)}/agents`;
/* Conversation Tags */
@ -283,3 +284,8 @@ export const confirmTwoFactor = () => '/api/auth/2fa/confirm';
export const disableTwoFactor = () => '/api/auth/2fa/disable';
export const regenerateBackupCodes = () => '/api/auth/2fa/backup/regenerate';
export const verifyTwoFactorTemp = () => '/api/auth/2fa/verify-temp';
/* Memories */
export const memories = () => '/api/memories';
export const memory = (key: string) => `${memories()}/${encodeURIComponent(key)}`;
export const memoryPreferences = () => `${memories()}/preferences`;

View file

@ -493,6 +493,7 @@ export const intefaceSchema = z
sidePanel: z.boolean().optional(),
multiConvo: z.boolean().optional(),
bookmarks: z.boolean().optional(),
memories: z.boolean().optional(),
presets: z.boolean().optional(),
prompts: z.boolean().optional(),
agents: z.boolean().optional(),
@ -508,6 +509,7 @@ export const intefaceSchema = z
presets: true,
multiConvo: true,
bookmarks: true,
memories: true,
prompts: true,
agents: true,
temporaryChat: true,
@ -649,11 +651,35 @@ export const balanceSchema = z.object({
refillAmount: z.number().optional().default(10000),
});
export const memorySchema = z.object({
disabled: z.boolean().optional(),
validKeys: z.array(z.string()).optional(),
tokenLimit: z.number().optional(),
personalize: z.boolean().default(true),
messageWindowSize: z.number().optional().default(5),
agent: z
.union([
z.object({
id: z.string(),
}),
z.object({
provider: z.string(),
model: z.string(),
instructions: z.string().optional(),
model_parameters: z.record(z.any()).optional(),
}),
])
.optional(),
});
export type TMemoryConfig = z.infer<typeof memorySchema>;
export const configSchema = z.object({
version: z.string(),
cache: z.boolean().default(true),
ocr: ocrSchema.optional(),
webSearch: webSearchSchema.optional(),
memory: memorySchema.optional(),
secureImageLinks: z.boolean().optional(),
imageOutputType: z.nativeEnum(EImageOutputType).default(EImageOutputType.PNG),
includedTools: z.array(z.string()).optional(),
@ -1291,6 +1317,10 @@ export enum SettingsTabValues {
* Chat input commands
*/
COMMANDS = 'commands',
/**
* Tab for Personalization Settings
*/
PERSONALIZATION = 'personalization',
}
export enum STTProviders {

View file

@ -13,11 +13,11 @@ export default function createPayload(submission: t.TSubmission) {
ephemeralAgent,
} = submission;
const { conversationId } = s.tConvoUpdateSchema.parse(conversation);
const { endpoint, endpointType } = endpointOption as {
const { endpoint: _e, endpointType } = endpointOption as {
endpoint: s.EModelEndpoint;
endpointType?: s.EModelEndpoint;
};
const endpoint = _e as s.EModelEndpoint;
let server = EndpointURLs[endpointType ?? endpoint];
const isEphemeral = s.isEphemeralAgent(endpoint, ephemeralAgent);
@ -32,6 +32,7 @@ export default function createPayload(submission: t.TSubmission) {
const payload: t.TPayload = {
...userMessage,
...endpointOption,
endpoint,
ephemeralAgent: isEphemeral ? ephemeralAgent : undefined,
isContinued: !!(isEdited && isContinued),
conversationId,

View file

@ -718,6 +718,12 @@ export function updateAgentPermissions(
return request.put(endpoints.updateAgentPermissions(variables.roleName), variables.updates);
}
export function updateMemoryPermissions(
variables: m.UpdateMemoryPermVars,
): Promise<m.UpdatePermResponse> {
return request.put(endpoints.updateMemoryPermissions(variables.roleName), variables.updates);
}
/* Tags */
export function getConversationTags(): Promise<t.TConversationTagsResponse> {
return request.get(endpoints.conversationTags());
@ -799,3 +805,33 @@ export function verifyTwoFactorTemp(
): Promise<t.TVerify2FATempResponse> {
return request.post(endpoints.verifyTwoFactorTemp(), payload);
}
/* Memories */
export const getMemories = (): Promise<q.MemoriesResponse> => {
return request.get(endpoints.memories());
};
export const deleteMemory = (key: string): Promise<void> => {
return request.delete(endpoints.memory(key));
};
export const updateMemory = (
key: string,
value: string,
originalKey?: string,
): Promise<q.TUserMemory> => {
return request.patch(endpoints.memory(originalKey || key), { key, value });
};
export const updateMemoryPreferences = (preferences: {
memories: boolean;
}): Promise<{ updated: boolean; preferences: { memories: boolean } }> => {
return request.patch(endpoints.memoryPreferences(), preferences);
};
export const createMemory = (data: {
key: string;
value: string;
}): Promise<{ created: boolean; memory: q.TUserMemory }> => {
return request.post(endpoints.memories(), data);
};

View file

@ -16,6 +16,8 @@ export * from './models';
export * from './mcp';
/* web search */
export * from './web';
/* memory */
export * from './memory';
/* RBAC */
export * from './permissions';
export * from './roles';

View file

@ -46,6 +46,8 @@ export enum QueryKeys {
health = 'health',
userTerms = 'userTerms',
banner = 'banner',
/* Memories */
memories = 'memories',
}
export enum MutationKeys {
@ -70,4 +72,5 @@ export enum MutationKeys {
updateRole = 'updateRole',
enableTwoFactor = 'enableTwoFactor',
verifyTwoFactor = 'verifyTwoFactor',
updateMemoryPreferences = 'updateMemoryPreferences',
}

View file

@ -0,0 +1,62 @@
import type { TCustomConfig, TMemoryConfig } from './config';
/**
* Loads the memory configuration and validates it
* @param config - The memory configuration from librechat.yaml
* @returns The validated memory configuration
*/
export function loadMemoryConfig(config: TCustomConfig['memory']): TMemoryConfig | undefined {
if (!config) {
return undefined;
}
// If disabled is explicitly true, return the config as-is
if (config.disabled === true) {
return config;
}
// Check if the agent configuration is valid
const hasValidAgent =
config.agent &&
(('id' in config.agent && !!config.agent.id) ||
('provider' in config.agent &&
'model' in config.agent &&
!!config.agent.provider &&
!!config.agent.model));
// If agent config is invalid, treat as disabled
if (!hasValidAgent) {
return {
...config,
disabled: true,
};
}
return config;
}
/**
* Checks if memory feature is enabled based on the configuration
* @param config - The memory configuration
* @returns True if memory is enabled, false otherwise
*/
export function isMemoryEnabled(config: TMemoryConfig | undefined): boolean {
if (!config) {
return false;
}
if (config.disabled === true) {
return false;
}
// Check if agent configuration is valid
const hasValidAgent =
config.agent &&
(('id' in config.agent && !!config.agent.id) ||
('provider' in config.agent &&
'model' in config.agent &&
!!config.agent.provider &&
!!config.agent.model));
return !!hasValidAgent;
}

View file

@ -225,13 +225,15 @@ const extractOmniVersion = (modelStr: string): string => {
export const getResponseSender = (endpointOption: t.TEndpointOption): string => {
const {
model: _m,
endpoint,
endpoint: _e,
endpointType,
modelDisplayLabel: _mdl,
chatGptLabel: _cgl,
modelLabel: _ml,
} = endpointOption;
const endpoint = _e as EModelEndpoint;
const model = _m ?? '';
const modelDisplayLabel = _mdl ?? '';
const chatGptLabel = _cgl ?? '';

View file

@ -16,6 +16,10 @@ export enum PermissionTypes {
* Type for Agent Permissions
*/
AGENTS = 'AGENTS',
/**
* Type for Memory Permissions
*/
MEMORIES = 'MEMORIES',
/**
* Type for Multi-Conversation Permissions
*/
@ -45,6 +49,8 @@ export enum Permissions {
READ = 'READ',
READ_AUTHOR = 'READ_AUTHOR',
SHARE = 'SHARE',
/** Can disable if desired */
OPT_OUT = 'OPT_OUT',
}
export const promptPermissionsSchema = z.object({
@ -60,6 +66,15 @@ export const bookmarkPermissionsSchema = z.object({
});
export type TBookmarkPermissions = z.infer<typeof bookmarkPermissionsSchema>;
export const memoryPermissionsSchema = z.object({
[Permissions.USE]: z.boolean().default(true),
[Permissions.CREATE]: z.boolean().default(true),
[Permissions.UPDATE]: z.boolean().default(true),
[Permissions.READ]: z.boolean().default(true),
[Permissions.OPT_OUT]: z.boolean().default(true),
});
export type TMemoryPermissions = z.infer<typeof memoryPermissionsSchema>;
export const agentPermissionsSchema = z.object({
[Permissions.SHARED_GLOBAL]: z.boolean().default(false),
[Permissions.USE]: z.boolean().default(true),
@ -92,6 +107,7 @@ export type TWebSearchPermissions = z.infer<typeof webSearchPermissionsSchema>;
export const permissionsSchema = z.object({
[PermissionTypes.PROMPTS]: promptPermissionsSchema,
[PermissionTypes.BOOKMARKS]: bookmarkPermissionsSchema,
[PermissionTypes.MEMORIES]: memoryPermissionsSchema,
[PermissionTypes.AGENTS]: agentPermissionsSchema,
[PermissionTypes.MULTI_CONVO]: multiConvoPermissionsSchema,
[PermissionTypes.TEMPORARY_CHAT]: temporaryChatPermissionsSchema,

View file

@ -5,6 +5,7 @@ import {
permissionsSchema,
agentPermissionsSchema,
promptPermissionsSchema,
memoryPermissionsSchema,
runCodePermissionsSchema,
webSearchPermissionsSchema,
bookmarkPermissionsSchema,
@ -48,6 +49,13 @@ const defaultRolesSchema = z.object({
[PermissionTypes.BOOKMARKS]: bookmarkPermissionsSchema.extend({
[Permissions.USE]: z.boolean().default(true),
}),
[PermissionTypes.MEMORIES]: memoryPermissionsSchema.extend({
[Permissions.USE]: z.boolean().default(true),
[Permissions.CREATE]: z.boolean().default(true),
[Permissions.UPDATE]: z.boolean().default(true),
[Permissions.READ]: z.boolean().default(true),
[Permissions.OPT_OUT]: z.boolean().default(true),
}),
[PermissionTypes.AGENTS]: agentPermissionsSchema.extend({
[Permissions.SHARED_GLOBAL]: z.boolean().default(true),
[Permissions.USE]: z.boolean().default(true),
@ -86,6 +94,13 @@ export const roleDefaults = defaultRolesSchema.parse({
[PermissionTypes.BOOKMARKS]: {
[Permissions.USE]: true,
},
[PermissionTypes.MEMORIES]: {
[Permissions.USE]: true,
[Permissions.CREATE]: true,
[Permissions.UPDATE]: true,
[Permissions.READ]: true,
[Permissions.OPT_OUT]: true,
},
[PermissionTypes.AGENTS]: {
[Permissions.SHARED_GLOBAL]: true,
[Permissions.USE]: true,
@ -110,6 +125,7 @@ export const roleDefaults = defaultRolesSchema.parse({
permissions: {
[PermissionTypes.PROMPTS]: {},
[PermissionTypes.BOOKMARKS]: {},
[PermissionTypes.MEMORIES]: {},
[PermissionTypes.AGENTS]: {},
[PermissionTypes.MULTI_CONVO]: {},
[PermissionTypes.TEMPORARY_CHAT]: {},

View file

@ -522,11 +522,19 @@ export const tMessageSchema = z.object({
feedback: feedbackSchema.optional(),
});
export type MemoryArtifact = {
key: string;
value?: string;
tokenCount?: number;
type: 'update' | 'delete';
};
export type TAttachmentMetadata = {
type?: Tools;
messageId: string;
toolCallId: string;
[Tools.web_search]?: SearchResultData;
[Tools.memory]?: MemoryArtifact;
};
export type TAttachment =

View file

@ -1,17 +1,18 @@
import type OpenAI from 'openai';
import type { InfiniteData } from '@tanstack/react-query';
import type {
TBanner,
TMessage,
TResPlugin,
ImageDetail,
TSharedLink,
TConversation,
EModelEndpoint,
TConversationTag,
TBanner,
TAttachment,
} from './schemas';
import { TMinimalFeedback } from './feedback';
import { SettingDefinition } from './generate';
import type { SettingDefinition } from './generate';
import type { TMinimalFeedback } from './feedback';
import type { Agent } from './types/assistants';
export type TOpenAIMessage = OpenAI.Chat.ChatCompletionMessageParam;
@ -20,28 +21,78 @@ export * from './schemas';
export type TMessages = TMessage[];
/* TODO: Cleanup EndpointOption types */
export type TEndpointOption = {
spec?: string | null;
iconURL?: string | null;
endpoint: EModelEndpoint;
endpointType?: EModelEndpoint;
export type TEndpointOption = Pick<
TConversation,
// Core conversation fields
| 'endpoint'
| 'endpointType'
| 'model'
| 'modelLabel'
| 'chatGptLabel'
| 'promptPrefix'
| 'temperature'
| 'topP'
| 'topK'
| 'top_p'
| 'frequency_penalty'
| 'presence_penalty'
| 'maxOutputTokens'
| 'maxContextTokens'
| 'max_tokens'
| 'maxTokens'
| 'resendFiles'
| 'imageDetail'
| 'reasoning_effort'
| 'instructions'
| 'additional_instructions'
| 'append_current_datetime'
| 'tools'
| 'stop'
| 'region'
| 'additionalModelRequestFields'
// Anthropic-specific
| 'promptCache'
| 'thinking'
| 'thinkingBudget'
// Assistant/Agent fields
| 'assistant_id'
| 'agent_id'
// UI/Display fields
| 'iconURL'
| 'greeting'
| 'spec'
// Artifacts
| 'artifacts'
// Files
| 'file_ids'
// System field
| 'system'
// Google examples
| 'examples'
// Context
| 'context'
> & {
// Fields specific to endpoint options that don't exist on TConversation
modelDisplayLabel?: string;
resendFiles?: boolean;
promptCache?: boolean;
maxContextTokens?: number;
imageDetail?: ImageDetail;
model?: string | null;
promptPrefix?: string;
temperature?: number;
chatGptLabel?: string | null;
modelLabel?: string | null;
jailbreak?: boolean;
key?: string | null;
/* assistant */
/** @deprecated Assistants API */
thread_id?: string;
/* multi-response stream */
// Conversation identifiers for multi-response streams
overrideConvoId?: string;
overrideUserMessageId?: string;
// Model parameters (used by different endpoints)
modelOptions?: Record<string, unknown>;
model_parameters?: Record<string, unknown>;
// Configuration data (added by middleware)
modelsConfig?: TModelsConfig;
// File attachments (processed by middleware)
attachments?: TAttachment[];
// Generated prompts
artifactsPrompt?: string;
// Agent-specific fields
agent?: Promise<Agent>;
// Client-specific options
clientOptions?: Record<string, unknown>;
};
export type TEphemeralAgent = {
@ -130,6 +181,9 @@ export type TUser = {
plugins?: string[];
twoFactorEnabled?: boolean;
backupCodes?: TBackupCode[];
personalization?: {
memories?: boolean;
};
createdAt: string;
updatedAt: string;
};
@ -557,7 +611,7 @@ export type TUpdateFeedbackResponse = {
messageId: string;
conversationId: string;
feedback?: TMinimalFeedback;
}
};
export type TBalanceResponse = {
tokenCredits: number;

View file

@ -22,6 +22,7 @@ export enum Tools {
web_search = 'web_search',
retrieval = 'retrieval',
function = 'function',
memory = 'memory',
}
export enum EToolResources {

View file

@ -278,7 +278,7 @@ export type UpdatePermVars<T> = {
};
export type UpdatePromptPermVars = UpdatePermVars<p.TPromptPermissions>;
export type UpdateMemoryPermVars = UpdatePermVars<p.TMemoryPermissions>;
export type UpdateAgentPermVars = UpdatePermVars<p.TAgentPermissions>;
export type UpdatePermResponse = r.TRole;
@ -290,6 +290,13 @@ export type UpdatePromptPermOptions = MutationOptions<
types.TError | null | undefined
>;
export type UpdateMemoryPermOptions = MutationOptions<
UpdatePermResponse,
UpdateMemoryPermVars,
unknown,
types.TError | null | undefined
>;
export type UpdateAgentPermOptions = MutationOptions<
UpdatePermResponse,
UpdateAgentPermVars,

View file

@ -109,3 +109,18 @@ export type VerifyToolAuthResponse = {
export type GetToolCallParams = { conversationId: string };
export type ToolCallResults = a.ToolCallResult[];
/* Memories */
export type TUserMemory = {
key: string;
value: string;
updated_at: string;
tokenCount?: number;
};
export type MemoriesResponse = {
memories: TUserMemory[];
totalTokens: number;
tokenLimit: number | null;
usagePercentage: number | null;
};

View file

@ -5,8 +5,8 @@ import type {
SearchProviders,
TWebSearchConfig,
} from './config';
import { extractVariableName } from './utils';
import { SearchCategories, SafeSearchTypes } from './config';
import { extractVariableName } from './utils';
import { AuthType } from './schemas';
export function loadWebSearchConfig(
@ -64,23 +64,29 @@ export const webSearchAuth = {
/**
* Extracts all API keys from the webSearchAuth configuration object
*/
export const webSearchKeys: TWebSearchKeys[] = [];
export function getWebSearchKeys(): TWebSearchKeys[] {
const keys: TWebSearchKeys[] = [];
// Iterate through each category (providers, scrapers, rerankers)
for (const category of Object.keys(webSearchAuth)) {
const categoryObj = webSearchAuth[category as TWebSearchCategories];
// Iterate through each category (providers, scrapers, rerankers)
for (const category of Object.keys(webSearchAuth)) {
const categoryObj = webSearchAuth[category as TWebSearchCategories];
// Iterate through each service within the category
for (const service of Object.keys(categoryObj)) {
const serviceObj = categoryObj[service as keyof typeof categoryObj];
// Iterate through each service within the category
for (const service of Object.keys(categoryObj)) {
const serviceObj = categoryObj[service as keyof typeof categoryObj];
// Extract the API keys from the service
for (const key of Object.keys(serviceObj)) {
webSearchKeys.push(key as TWebSearchKeys);
// Extract the API keys from the service
for (const key of Object.keys(serviceObj)) {
keys.push(key as TWebSearchKeys);
}
}
}
return keys;
}
export const webSearchKeys: TWebSearchKeys[] = getWebSearchKeys();
export function extractWebSearchEnvVars({
keys,
config,