2023-12-14 07:49:27 -05:00
|
|
|
const _ = require('lodash');
|
2023-03-22 19:52:38 -04:00
|
|
|
const mongoose = require('mongoose');
|
2023-03-22 01:31:01 -04:00
|
|
|
const { MeiliSearch } = require('meilisearch');
|
2025-03-27 17:09:46 -04:00
|
|
|
const { parseTextParts, ContentTypes } = require('librechat-data-provider');
|
2023-12-14 07:49:27 -05:00
|
|
|
const { cleanUpPrimaryKeyValue } = require('~/lib/utils/misc');
|
|
|
|
|
const logger = require('~/config/meiliLogger');
|
|
|
|
|
|
2025-03-08 20:37:33 +01:00
|
|
|
// Environment flags
|
|
|
|
|
/**
|
|
|
|
|
* Flag to indicate if search is enabled based on environment variables.
|
|
|
|
|
* @type {boolean}
|
|
|
|
|
*/
|
2023-07-08 11:41:51 -04:00
|
|
|
const searchEnabled = process.env.SEARCH && process.env.SEARCH.toLowerCase() === 'true';
|
2025-03-08 20:37:33 +01:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Flag to indicate if MeiliSearch is enabled based on required environment variables.
|
|
|
|
|
* @type {boolean}
|
|
|
|
|
*/
|
2023-07-08 11:41:51 -04:00
|
|
|
const meiliEnabled = process.env.MEILI_HOST && process.env.MEILI_MASTER_KEY && searchEnabled;
|
2023-03-22 01:31:01 -04:00
|
|
|
|
2025-03-08 20:37:33 +01:00
|
|
|
/**
|
|
|
|
|
* Validates the required options for configuring the mongoMeili plugin.
|
|
|
|
|
*
|
|
|
|
|
* @param {Object} options - The configuration options.
|
|
|
|
|
* @param {string} options.host - The MeiliSearch host.
|
|
|
|
|
* @param {string} options.apiKey - The MeiliSearch API key.
|
|
|
|
|
* @param {string} options.indexName - The name of the index.
|
|
|
|
|
* @throws {Error} Throws an error if any required option is missing.
|
|
|
|
|
*/
|
2023-03-22 01:31:01 -04:00
|
|
|
const validateOptions = function (options) {
|
|
|
|
|
const requiredKeys = ['host', 'apiKey', 'indexName'];
|
|
|
|
|
requiredKeys.forEach((key) => {
|
feat: ChatGPT Plugins/OpenAPI specs for Plugins Endpoint (#620)
* wip: proof of concept for openapi chain
* chore(api): update langchain dependency to version 0.0.105
* feat(Plugins): use ChatGPT Plugins/OpenAPI specs (first pass)
* chore(manifest.json): update pluginKey for "Browser" tool to "web-browser"
chore(handleTools.js): update customConstructor key for "web-browser" tool
* fix(handleSubmit.js): set unfinished property to false for all endpoints
* fix(handlers.js): remove unnecessary capitalizeWords function and use action.tool directly
refactor(endpoints.js): rename availableTools to tools and transform it into a map
* feat(endpoints): add plugins selector to endpoints file
refactor(CodeBlock.tsx): refactor to typescript
refactor(Plugin.tsx): use recoil Map for plugin name and refactor to typescript
chore(Message.jsx): linting
chore(PluginsOptions/index.jsx): remove comment/linting
chore(svg): export Clipboard and CheckMark components from SVG index and refactor to typescript
* fix(OpenAPIPlugin.js): rename readYamlFile function to readSpecFile
fix(OpenAPIPlugin.js): handle JSON files in readSpecFile function
fix(OpenAPIPlugin.js): handle JSON URLs in getSpec function
fix(OpenAPIPlugin.js): handle JSON variables in createOpenAPIPlugin function
fix(OpenAPIPlugin.js): add description for variables in createOpenAPIPlugin function
fix(OpenAPIPlugin.js): add optional flag for is_user_authenticated and has_user_authentication in ManifestDefinition
fix(loadSpecs.js): add optional flag for is_user_authenticated and has_user_authentication in ManifestDefinition
fix(Plugin.tsx): remove unnecessary callback parameter in getPluginName function
fix(getDefaultConversation.js): fix browser console error: handle null value for lastConversationSetup in getDefaultConversation function
* feat(api): add new tools
Add Ai PDF tool for super-fast, interactive chats with PDFs of any size, complete with page references for fact checking.
Add VoxScript tool for searching through YouTube transcripts, financial data sources, Google Search results, and more.
Add WebPilot tool for browsing and QA of webpages, PDFs, and data. Generate articles from one or more URLs.
feat(api): update OpenAPIPlugin.js
- Add support for bearer token authorization in the OpenAPIPlugin.
- Add support for custom headers in the OpenAPIPlugin.
fix(api): fix loadTools.js
- Pass the user parameter to the loadSpecs function.
* feat(PluginsClient.js): import findMessageContent function from utils
feat(PluginsClient.js): add message parameter to options object in initializeCustomAgent function
feat(PluginsClient.js): add content to errorMessage if message content is found
feat(PluginsClient.js): break out of loop if message content is found
feat(PluginsClient.js): add delay option with value of 8 to generateTextStream function
feat(PluginsClient.js): add support for process.env.PORT environment variable in app.listen function
feat(askyourpdf.json): add askyourpdf plugin configuration
feat(metar.json): add metar plugin configuration
feat(askyourpdf.yaml): add askyourpdf plugin OpenAPI specification
feat(OpenAPIPlugin.js): add message parameter to createOpenAPIPlugin function
feat(OpenAPIPlugin.js): add description_for_model to chain run message
feat(addOpenAPISpecs.js): remove verbose option from loadSpecs function call
fix(loadSpecs.js): add 'message' parameter to the loadSpecs function
feat(findMessageContent.js): add utility function to find message content in JSON objects
* fix(PluginStoreDialog.tsx): update z-index value for the dialog container
The z-index value for the dialog container was updated to "102" to ensure it appears above other elements on the page.
* chore(web_pilot.json): add "params" field with "user_has_request" parameter set to true
* chore(eslintrc.js): update eslint rules
fix(Login.tsx): add missing semicolon after import statement
* fix(package-lock.json): update langchain dependency to version ^0.0.105
* fix(OpenAPIPlugin.js): change header key from 'id' to 'librechat_user_id' for consistency and clarity
feat(plugins): add documentation for using official ChatGPT Plugins with OpenAPI specs
This commit adds a new file `chatgpt_plugins_openapi.md` to the `docs/features/plugins` directory. The file provides detailed information on how to use official ChatGPT Plugins with OpenAPI specifications. It explains the components of a plugin, including the Plugin Manifest file and the OpenAPI spec. It also covers the process of adding a plugin, editing manifest files, and customizing OpenAPI spec files. Additionally, the commit includes disclaimers about the limitations and compatibility of plugins with LibreChat. The documentation also clarifies that the use of ChatGPT Plugins with LibreChat does not violate OpenAI's Terms of Service.
The purpose of this commit is to provide comprehensive documentation for developers who want to integrate ChatGPT Plugins into their projects using OpenAPI specs. It aims to guide them through the process of adding and configuring plugins, as well as addressing potential issues and
chore(introduction.md): update link to ChatGPT Plugins documentation
docs(introduction.md): clarify the purpose of the plugins endpoint and its capabilities
* fix(OpenAPIPlugin.js): update SUFFIX variable to provide a clearer description
docs(chatgpt_plugins_openapi.md): update information about adding plugins via url on the frontend
* feat(PluginsClient.js): sendIntermediateMessage on successful Agent load
fix(PluginsClient.js, server/index.js, gptPlugins.js): linting fixes
docs(chatgpt_plugins_openapi.md): update links and add additional information
* Update chatgpt_plugins_openapi.md
* chore: rebuild package-lock file
* chore: format/lint all files with new rules
* chore: format all files
* chore(README.md): update AI model selection list
The AI model selection list in the README.md file has been updated to reflect the current options available. The "Anthropic" model has been added as an alternative name for the "Claude" model.
* fix(Plugin.tsx): type issue
* feat(tools): add new tool WebPilot
feat(tools): remove tool Weather Report
feat(tools): add new tool Prompt Perfect
feat(tools): add new tool Scholarly Graph Link
* feat(OpenAPIPlugin.js): add getSpec and readSpecFile functions
feat(OpenAPIPlugin.spec.js): add tests for readSpecFile, getSpec, and createOpenAPIPlugin functions
* chore(agent-demo-1.js): remove unused code and dependencies
chore(agent-demo-2.js): remove unused code and dependencies
chore(demo.js): remove unused code and dependencies
* feat(addOpenAPISpecs): add function to transform OpenAPI specs into desired format
feat(addOpenAPISpecs.spec): add tests for transformSpec function
fix(loadSpecs): remove debugging code
* feat(loadSpecs.spec.js): add unit tests for ManifestDefinition, validateJson, and loadSpecs functions
* fix: package file resolution bug
* chore: move scholarly_graph_link manifest to 'has-issues'
* refactor(client/hooks): convert to TS and export from index
* Update introduction.md
* Update chatgpt_plugins_openapi.md
2023-07-16 12:19:47 -04:00
|
|
|
if (!options[key]) {
|
|
|
|
|
throw new Error(`Missing mongoMeili Option: ${key}`);
|
|
|
|
|
}
|
2023-03-22 01:31:01 -04:00
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
2025-03-08 20:37:33 +01:00
|
|
|
/**
|
|
|
|
|
* Factory function to create a MeiliMongooseModel class which extends a Mongoose model.
|
|
|
|
|
* This class contains static and instance methods to synchronize and manage the MeiliSearch index
|
|
|
|
|
* corresponding to the MongoDB collection.
|
|
|
|
|
*
|
|
|
|
|
* @param {Object} config - Configuration object.
|
|
|
|
|
* @param {Object} config.index - The MeiliSearch index object.
|
|
|
|
|
* @param {Array<string>} config.attributesToIndex - List of attributes to index.
|
|
|
|
|
* @returns {Function} A class definition that will be loaded into the Mongoose schema.
|
|
|
|
|
*/
|
2023-07-28 11:46:15 -04:00
|
|
|
const createMeiliMongooseModel = function ({ index, attributesToIndex }) {
|
2025-03-08 20:37:33 +01:00
|
|
|
// The primary key is assumed to be the first attribute in the attributesToIndex array.
|
2023-03-22 01:31:01 -04:00
|
|
|
const primaryKey = attributesToIndex[0];
|
2025-03-08 20:37:33 +01:00
|
|
|
|
2023-03-22 01:31:01 -04:00
|
|
|
class MeiliMongooseModel {
|
2023-07-28 11:46:15 -04:00
|
|
|
/**
|
2025-03-08 20:37:33 +01:00
|
|
|
* Synchronizes the data between the MongoDB collection and the MeiliSearch index.
|
2023-07-28 11:46:15 -04:00
|
|
|
*
|
2025-03-08 20:37:33 +01:00
|
|
|
* The synchronization process involves:
|
|
|
|
|
* 1. Fetching all documents from the MongoDB collection and MeiliSearch index.
|
|
|
|
|
* 2. Comparing documents from both sources.
|
|
|
|
|
* 3. Deleting documents from MeiliSearch that no longer exist in MongoDB.
|
|
|
|
|
* 4. Adding documents to MeiliSearch that exist in MongoDB but not in the index.
|
|
|
|
|
* 5. Updating documents in MeiliSearch if key fields (such as `text` or `title`) differ.
|
|
|
|
|
* 6. Updating the `_meiliIndex` field in MongoDB to indicate the indexing status.
|
2023-07-28 11:46:15 -04:00
|
|
|
*
|
2025-03-08 20:37:33 +01:00
|
|
|
* Note: The function processes documents in batches because MeiliSearch's
|
|
|
|
|
* `index.getDocuments` requires an exact limit and `index.addDocuments` does not handle
|
|
|
|
|
* partial failures in a batch.
|
2023-07-28 11:46:15 -04:00
|
|
|
*
|
2025-03-08 20:37:33 +01:00
|
|
|
* @returns {Promise<void>} Resolves when the synchronization is complete.
|
2023-07-28 11:46:15 -04:00
|
|
|
*/
|
2023-03-22 01:31:01 -04:00
|
|
|
static async syncWithMeili() {
|
2023-07-08 11:20:57 +09:00
|
|
|
try {
|
2023-07-28 11:46:15 -04:00
|
|
|
let moreDocuments = true;
|
2025-03-08 20:37:33 +01:00
|
|
|
// Retrieve all MongoDB documents from the collection as plain JavaScript objects.
|
2023-07-28 11:46:15 -04:00
|
|
|
const mongoDocuments = await this.find().lean();
|
|
|
|
|
|
2025-03-08 20:37:33 +01:00
|
|
|
// Helper function to format a document by selecting only the attributes to index
|
|
|
|
|
// and omitting keys starting with '$'.
|
|
|
|
|
const format = (doc) =>
|
|
|
|
|
_.omitBy(_.pick(doc, attributesToIndex), (v, k) => k.startsWith('$'));
|
|
|
|
|
|
|
|
|
|
// Build a map of MongoDB documents for quick lookup based on the primary key.
|
2023-07-28 11:46:15 -04:00
|
|
|
const mongoMap = new Map(mongoDocuments.map((doc) => [doc[primaryKey], format(doc)]));
|
|
|
|
|
const indexMap = new Map();
|
|
|
|
|
let offset = 0;
|
|
|
|
|
const batchSize = 1000;
|
|
|
|
|
|
2025-03-08 20:37:33 +01:00
|
|
|
// Fetch documents from the MeiliSearch index in batches.
|
2023-07-28 11:46:15 -04:00
|
|
|
while (moreDocuments) {
|
|
|
|
|
const batch = await index.getDocuments({ limit: batchSize, offset });
|
|
|
|
|
if (batch.results.length === 0) {
|
|
|
|
|
moreDocuments = false;
|
|
|
|
|
}
|
|
|
|
|
for (const doc of batch.results) {
|
|
|
|
|
indexMap.set(doc[primaryKey], format(doc));
|
|
|
|
|
}
|
|
|
|
|
offset += batchSize;
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-14 07:49:27 -05:00
|
|
|
logger.debug('[syncWithMeili]', { indexMap: indexMap.size, mongoMap: mongoMap.size });
|
2023-07-28 11:46:15 -04:00
|
|
|
|
|
|
|
|
const updateOps = [];
|
|
|
|
|
|
2025-03-08 20:37:33 +01:00
|
|
|
// Process documents present in the MeiliSearch index.
|
2023-07-28 11:46:15 -04:00
|
|
|
for (const [id, doc] of indexMap) {
|
|
|
|
|
const update = {};
|
|
|
|
|
update[primaryKey] = id;
|
|
|
|
|
if (mongoMap.has(id)) {
|
2025-03-08 20:37:33 +01:00
|
|
|
// If document exists in MongoDB, check for discrepancies in key fields.
|
2023-07-28 11:46:15 -04:00
|
|
|
if (
|
|
|
|
|
(doc.text && doc.text !== mongoMap.get(id).text) ||
|
|
|
|
|
(doc.title && doc.title !== mongoMap.get(id).title)
|
|
|
|
|
) {
|
2023-12-14 07:49:27 -05:00
|
|
|
logger.debug(
|
|
|
|
|
`[syncWithMeili] ${id} had document discrepancy in ${
|
|
|
|
|
doc.text ? 'text' : 'title'
|
|
|
|
|
} field`,
|
|
|
|
|
);
|
2023-07-28 11:46:15 -04:00
|
|
|
updateOps.push({
|
|
|
|
|
updateOne: { filter: update, update: { $set: { _meiliIndex: true } } },
|
|
|
|
|
});
|
|
|
|
|
await index.addDocuments([doc]);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2025-03-08 20:37:33 +01:00
|
|
|
// If the document does not exist in MongoDB, delete it from MeiliSearch.
|
2023-07-28 11:46:15 -04:00
|
|
|
await index.deleteDocument(id);
|
|
|
|
|
updateOps.push({
|
|
|
|
|
updateOne: { filter: update, update: { $set: { _meiliIndex: false } } },
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-08 20:37:33 +01:00
|
|
|
// Process documents present in MongoDB.
|
2023-07-28 11:46:15 -04:00
|
|
|
for (const [id, doc] of mongoMap) {
|
|
|
|
|
const update = {};
|
|
|
|
|
update[primaryKey] = id;
|
2025-03-08 20:37:33 +01:00
|
|
|
// If the document is missing in the Meili index, add it.
|
2023-07-28 11:46:15 -04:00
|
|
|
if (!indexMap.has(id)) {
|
|
|
|
|
await index.addDocuments([doc]);
|
|
|
|
|
updateOps.push({
|
|
|
|
|
updateOne: { filter: update, update: { $set: { _meiliIndex: true } } },
|
|
|
|
|
});
|
|
|
|
|
} else if (doc._meiliIndex === false) {
|
2025-03-08 20:37:33 +01:00
|
|
|
// If the document exists but is marked as not indexed, update the flag.
|
2023-07-28 11:46:15 -04:00
|
|
|
updateOps.push({
|
|
|
|
|
updateOne: { filter: update, update: { $set: { _meiliIndex: true } } },
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-08 20:37:33 +01:00
|
|
|
// Execute bulk update operations in MongoDB to update the _meiliIndex flags.
|
2023-07-28 11:46:15 -04:00
|
|
|
if (updateOps.length > 0) {
|
|
|
|
|
await this.collection.bulkWrite(updateOps);
|
2023-12-14 07:49:27 -05:00
|
|
|
logger.debug(
|
|
|
|
|
`[syncWithMeili] Finished indexing ${
|
2023-07-28 12:13:16 -04:00
|
|
|
primaryKey === 'messageId' ? 'messages' : 'conversations'
|
|
|
|
|
}`,
|
2023-07-28 11:46:15 -04:00
|
|
|
);
|
|
|
|
|
}
|
2023-07-08 11:20:57 +09:00
|
|
|
} catch (error) {
|
2023-12-14 07:49:27 -05:00
|
|
|
logger.error('[syncWithMeili] Error adding document to Meili', error);
|
2023-07-08 11:20:57 +09:00
|
|
|
}
|
2023-03-22 01:31:01 -04:00
|
|
|
}
|
|
|
|
|
|
2025-03-08 20:37:33 +01:00
|
|
|
/**
|
|
|
|
|
* Updates settings for the MeiliSearch index.
|
|
|
|
|
*
|
|
|
|
|
* @param {Object} settings - The settings to update on the MeiliSearch index.
|
|
|
|
|
* @returns {Promise<Object>} Promise resolving to the update result.
|
|
|
|
|
*/
|
2023-03-22 01:31:01 -04:00
|
|
|
static async setMeiliIndexSettings(settings) {
|
|
|
|
|
return await index.updateSettings(settings);
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-08 20:37:33 +01:00
|
|
|
/**
|
|
|
|
|
* Searches the MeiliSearch index and optionally populates the results with data from MongoDB.
|
|
|
|
|
*
|
|
|
|
|
* @param {string} q - The search query.
|
|
|
|
|
* @param {Object} params - Additional search parameters for MeiliSearch.
|
|
|
|
|
* @param {boolean} populate - Whether to populate search hits with full MongoDB documents.
|
|
|
|
|
* @returns {Promise<Object>} The search results with populated hits if requested.
|
|
|
|
|
*/
|
2023-03-22 01:31:01 -04:00
|
|
|
static async meiliSearch(q, params, populate) {
|
|
|
|
|
const data = await index.search(q, params);
|
|
|
|
|
|
|
|
|
|
if (populate) {
|
2025-03-08 20:37:33 +01:00
|
|
|
// Build a query using the primary key values from the search hits.
|
2023-03-22 01:31:01 -04:00
|
|
|
const query = {};
|
2023-05-18 11:44:07 -07:00
|
|
|
query[primaryKey] = _.map(data.hits, (hit) => cleanUpPrimaryKeyValue(hit[primaryKey]));
|
2025-03-08 20:37:33 +01:00
|
|
|
|
|
|
|
|
// Build a projection object, including only keys that do not start with '$'.
|
|
|
|
|
const projection = Object.keys(this.schema.obj).reduce(
|
|
|
|
|
(results, key) => {
|
|
|
|
|
if (!key.startsWith('$')) {
|
|
|
|
|
results[key] = 1;
|
|
|
|
|
}
|
|
|
|
|
return results;
|
|
|
|
|
},
|
|
|
|
|
{ _id: 1, __v: 1 },
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// Retrieve the full documents from MongoDB.
|
|
|
|
|
const hitsFromMongoose = await this.find(query, projection).lean();
|
|
|
|
|
|
|
|
|
|
// Merge the MongoDB documents with the search hits.
|
2023-03-22 01:31:01 -04:00
|
|
|
const populatedHits = data.hits.map(function (hit) {
|
|
|
|
|
const query = {};
|
|
|
|
|
query[primaryKey] = hit[primaryKey];
|
|
|
|
|
const originalHit = _.find(hitsFromMongoose, query);
|
|
|
|
|
|
|
|
|
|
return {
|
2023-07-28 13:16:41 -04:00
|
|
|
...(originalHit ?? {}),
|
2023-07-14 09:36:49 -04:00
|
|
|
...hit,
|
2023-03-22 01:31:01 -04:00
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
data.hits = populatedHits;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return data;
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-08 20:37:33 +01:00
|
|
|
/**
|
|
|
|
|
* Preprocesses the current document for indexing.
|
|
|
|
|
*
|
|
|
|
|
* This method:
|
|
|
|
|
* - Picks only the defined attributes to index.
|
|
|
|
|
* - Omits any keys starting with '$'.
|
|
|
|
|
* - Replaces pipe characters ('|') in `conversationId` with '--'.
|
|
|
|
|
* - Extracts and concatenates text from an array of content items.
|
|
|
|
|
*
|
|
|
|
|
* @returns {Object} The preprocessed object ready for indexing.
|
|
|
|
|
*/
|
2023-07-08 11:20:57 +09:00
|
|
|
preprocessObjectForIndex() {
|
2025-03-08 20:37:33 +01:00
|
|
|
const object = _.omitBy(_.pick(this.toJSON(), attributesToIndex), (v, k) =>
|
|
|
|
|
k.startsWith('$'),
|
|
|
|
|
);
|
2023-03-22 01:31:01 -04:00
|
|
|
if (object.conversationId && object.conversationId.includes('|')) {
|
|
|
|
|
object.conversationId = object.conversationId.replace(/\|/g, '--');
|
|
|
|
|
}
|
✨ feat: Assistants API, General File Support, Side Panel, File Explorer (#1696)
* feat: assistant name/icon in Landing & Header
* feat: assistname in textarea placeholder, and use `Assistant` as default name
* feat: display non-image files in user messages
* fix: only render files if files.length is > 0
* refactor(config -> file-config): move file related configuration values to separate module, add excel types
* chore: spreadsheet file rendering
* fix(Landing): dark mode style for Assistant Name
* refactor: move progress incrementing to own hook, start smaller, cap near limit \(1\)
* refactor(useContentHandler): add empty Text part if last part was completed tool or image
* chore: add accordion trigger border styling for dark mode
* feat: Assistant Builder model selection
* chore: use Spinner when Assistant is mutating
* fix(get/assistants): return correct response object `AssistantListResponse`
* refactor(Spinner): pass size as prop
* refactor: make assistant crud mutations optimistic, add types for options
* chore: remove assistants route and view
* chore: move assistant builder components to separate directory
* feat(ContextButton): delete Assistant via context button/dialog, add localization
* refactor: conditionally show use and context menu buttons, add localization for create assistant
* feat: save side panel states to localStorage
* style(SidePanel): improve avatar menu and assistant select styling for dark mode
* refactor: make NavToggle reusable for either side (left or right), add SidePanel Toggle with ability to close it completely
* fix: resize handle and navToggle behavior
* fix(/avatar/:assistant_id): await `deleteFile` and assign unique name to uploaded image
* WIP: file UI components from PR #576
* refactor(OpenAIMinimalIcon): pass className
* feat: formatDate helper fn
* feat: DataTableColumnHeader
* feat: add row selection, formatted row values, number of rows selected
* WIP: add files to Side panel temporarily
* feat: `LB_QueueAsyncCall`: Leaky Bucket queue for external APIs, use in `processDeleteRequest`
* fix(TFile): correct `source` type with `FileSources`
* fix(useFileHandling): use `continue` instead of return when iterating multiple files, add file type to extendedFile
* chore: add generic setter type
* refactor(processDeleteRequest): settle promises to prevent rejections from processing deletions, log errors
* feat: `useFileDeletion` to reuse file deletion logic
* refactor(useFileDeletion): make `setFiles` an optional param and use object as param
* feat: useDeleteFilesFromTable
* feat: use real `files` data and add deletion action to data table
* fix(Table): make headers sticky
* feat: add dynamic filtering for columns; only show to user Host or OpenAI storage type
* style(DropdownMenu): replace `slate` with `gray`
* style(DataTable): apply dark mode themes and other misc styling
* style(Columns): add color to OpenAI Storage option
* refactor(FileContainer): make file preview reusable
* refactor(Images): make image preview reusable
* refactor(FilePreview): make file prop optional for FileIcon and FilePreview, fix relative style
* feat(Columns): add file/image previews, set a minimum size to show for file size in bytes
* WIP: File Panel with real files and formatted
* feat: open files dialog from panel
* style: file data table mobile and general column styling fixes
* refactor(api/files): return files sorted by the most recently updated
* refactor: provide fileMap through context to prevent re-selecting files to map in different areas; remove unused imports commented out in PanelColumns
* refactor(ExtendFile): make File type optional, add `attached` to prevent attached files from being deleted on remove, make Message.files a partial TFile type
* feat: attach files through file panel
* refactor(useFileHandling): move files to the start of cache list when uploaded
* refactor(useDeleteFilesMutation): delete files from cache when successfully deleted from server
* fix(FileRow): handle possible edge case of duplication due to attaching recently uploaded file
* style(SidePanel): make resize grip border transparent, remove unnecessary styling on close sidepanel button
* feat: action utilities and tests
* refactor(actions): add `ValidationResult` type and change wording for no server URL found
* refactor(actions): check for empty server URL
* fix(data-provider): revert tsconfig to fix type issue resolution
* feat(client): first pass of actions input for assistants
* refactor(FunctionSignature): change method to output object instead of string
* refactor(models/Assistant): add actions field to schema, use searchParams object for methods, and add `getAssistant`
* feat: post actions input first pass
- create new Action document
- add actions to Assistant DB document
- create /action/:assistant_id POST route
- pass more props down from PanelSwitcher, derive assistant_id from switcher
- move privacy policy to ActionInput
- reset data on input change/validation
- add `useUpdateAction`
- conform FunctionSignature type to FunctionTool
- add action, assistant doc, update hook related types
* refactor: optimize assistant/actions relationship
- past domain in metadata as hostname and not a URL
- include domain in tool name
- add `getActions` for actions retrieval by user
- add `getAssistants` for assistant docs retrieval by user
- add `assistant_id` to Action schema
- move actions to own module as a subroute to `api/assistants`
- add `useGetActionsQuery` and `useGetAssistantDocsQuery` hooks
- fix Action type def
* feat: show assistant actions in assistant builder
* feat: switch to actions on action click, editing action styling
* fix: add Assistant state for builder panel to allow immediate selection of newly created assistants as well as retaining the current assistant when switching to a different panel within the builder
* refactor(SidePanel/NavToggle): offset less from right when SidePanel is completely collapsed
* chore: rename `processActions` -> `processRequiredActions`
* chore: rename Assistant API Action to RequiredAction
* refactor(actions): avoid nesting actual API params under generic `requestBody` to optimize LLM token usage
* fix(handleTools): avoid calling `validTool` if not defined, add optional param to skip the loading of specs, which throws an error in the context of assistants
* WIP: working first pass of toolCalls generated from openapi specs
* WIP: first pass ToolCall styling
* feat: programmatic iv encryption/decryption helpers
* fix: correct ActionAuth types/enums, and define type for AuthForm
* feat: encryption/decryption helpers for Action AuthMetadata
* refactor(getActions): remove sensitive fields from query response
* refactor(POST/actions): encrypt and remove sensitive fields from mutation response
* fix(ActionService): change ESM import to CJS
* feat: frontend auth handling for actions + optimistic update on action update/creation
* refactor(actions): use the correct variables and types for setAuth method
* refactor: POST /:assistant_id action can now handle updating an existing action, add `saved_auth_fields` to determine when user explicitly saves new auth creds. only send auth metadata if user explicitly saved fields
* refactor(createActionTool): catch errors and send back meaningful error message, add flag to `getActions` to determine whether to retrieve sensitive values or not
* refactor(ToolService): add `action` property to ToolCall PartMetadata to determine if the tool call was an action, fix parsing function name issue with actionDelimiter
* fix(ActionRequest): use URL class to correctly join endpoint parts for `execute` call
* feat: delete assistant actions
* refactor: conditionally show Available actions
* refactor: show `retrieval` and `code_interpreter` as Capabilities, swap `Switch` for `Checkbox`
* chore: remove shadow-stroke from messages
* WIP: first pass of Assistants Knowledge attachments
* refactor: remove AssistantsProvider in favor of FormProvider, fix selectedAssistant re-render bug, map Assistant file_ids to files via fileMap, initialize Knowledge component with mapped files if any exist
* fix: prevent deleting files on assistant file upload
* chore: remove console.log
* refactor(useUploadFileMutation): update files and assistants cache on upload
* chore: disable oauth option as not supported yet
* feat: cancel assistant runs
* refactor: initialize OpenAI client with helper function, resolve all related circular dependencies
* fix(DALL-E): initialization
* fix(process): openai client initialization
* fix: select an existing Assistant when the active one is deleted
* chore: allow attaching files for assistant endpoint, send back relevant OpenAI error message when uploading, deconstruct openAI initialization correctly, add `message_file` to formData when a file is attached to the message but not the assistant
* fix: add assistant_id on newConvo
* fix(initializeClient): import fix
* chore: swap setAssistant for setOption in useEffect
* fix(DALL-E): add processFileURL to loadTools call
* chore: add customConfig to debug logs
* feat: delete threads on convo delete
* chore: replace Assistants icon
* chore: remove console.dir() in `abortRun`
* feat(AssistantService): accumulate text values from run in openai.responseText
* feat: titling for assistants endpoint
* chore: move panel file components to appropriate directory, add file checks for attaching files, change icon for Attach Files
* refactor: add localizations to tools, plugins, add condition for adding/remove user plugins so tool selections don't affect this value
* chore: disable `import from url` action for now
* chore: remove textMimeTypes from default fileConfig for now
* fix: catch tool errors and send as outputs with error messages
* fix: React warning about button as descendant of button
* style: retrieval and cancelled icon
* WIP: pass isSubmitting to Parts, use InProgressCall to display cancelled tool calls correctly, show domain/function name
* fix(meilisearch): fix `postSaveHook` issue where indexing expects a mongo document, and join all text content parts for meili indexing
* ci: fix dall-e tests
* ci: fix client tests
* fix: button types in actions panel
* fix: plugin auth form persisting across tool selections
* fix(ci): update AppService spec with `loadAndFormatTools`
* fix(clearConvos): add id check earlier on
* refactor(AssistantAvatar): set previewURL dynamically when emtadata.avatar changes
* feat(assistants): addTitle cache setting
* fix(useSSE): resolve rebase conflicts
* fix: delete mutation
* style(SidePanel): make grip visible on active and hover, invisible otherwise
* ci: add data-provider tests to workflow, also update eslint/tsconfig to recognize specs, and add `text/csv` to fileConfig
* fix: handle edge case where auth object is undefined, and log errors
* refactor(actions): resolve schemas, add tests for resolving refs, import specs from separate file for tests
* chore: remove comment
* fix(ActionsInput): re-render bug when initializing states with action fields
* fix(patch/assistant): filter undefined tools
* chore: add logging for errors in assistants routes
* fix(updateAssistant): map actions to functions to avoid overwriting
* fix(actions): properly handle GET paths
* fix(convos): unhandled delete thread exception
* refactor(AssistantService): pass both thread_id and conversationId when sending intermediate assistant messages, remove `mapMessagesToSteps` from AssistantService
* refactor(useSSE): replace all messages with runMessages and pass latestMessageId to abortRun; fix(checkMessageGaps): include tool calls when syncing messages
* refactor(assistants/chat): invoke `createOnTextProgress` after thread creation
* chore: add typing
* style: sidepanel styling
* style: action tool call domain styling
* feat(assistants): default models, limit retrieval to certain models, add env variables to to env.example
* feat: assistants api key in EndpointService
* refactor: set assistant model to conversation on assistant switch
* refactor: set assistant model to conversation on assistant select from panel
* fix(retrieveAndProcessFile): catch attempt to download file with `assistant` purpose which is not allowed; add logging
* feat: retrieval styling, handling, and logging
* chore: rename ASSISTANTS_REVERSE_PROXY to ASSISTANTS_BASE_URL
* feat: FileContext for file metadata
* feat: context file mgmt and filtering
* style(Select): hover/rounded changes
* refactor: explicit conversation switch, endpoint dependent, through `useSelectAssistant`, which does not create new chat if current endpoint is assistant endpoint
* fix(AssistantAvatar): make empty previewURL if no avatar present
* refactor: side panel mobile styling
* style: merge tool and action section, optimize mobile styling for action/tool buttons
* fix: localStorage issues
* fix(useSelectAssistant): invoke react query hook directly in select hook as Map was not being updated in time
* style: light mode fixes
* fix: prevent sidepanel nav styling from shifting layout up
* refactor: change default layout (collapsed by default)
* style: mobile optimization of DataTable
* style: datatable
* feat: client-side hide right-side panel
* chore(useNewConvo): add partial typing for preset
* fix(useSelectAssistant): pass correct model name by using template as preset
* WIP: assistant presets
* refactor(ToolService): add native solution for `TavilySearchResults` and log tool output errors
* refactor: organize imports and use native TavilySearchResults
* fix(TavilySearchResults): stringify result
* fix(ToolCall): show tool call outputs when not an action
* chore: rename Prompt Prefix to custom instructions (in user facing text only)
* refactor(EditPresetDialog): Optimize setting title by debouncing, reset preset on dialog close to avoid state mixture
* feat: add `presetOverride` to overwrite active conversation settings when saving a Preset (relevant for client side updates only)
* feat: Assistant preset settings (client-side)
* fix(Switcher): only set assistant_id and model if current endpoint is Assistants
* feat: use `useDebouncedInput` for updating conversation settings, starting with EditPresetDialog title setting and Assistant instructions setting
* feat(Assistants): add instructions field to settings
* feat(chat/assistants): pass conversation settings to run body
* wip: begin localization and only allow actions if the assistant is created
* refactor(AssistantsPanel): knowledge localization, allow tools on creation
* feat: experimental: allow 'priming' values before assistant is created, that would normally require an assistant_id to be defined
* chore: trim console logs and make more meaningful
* chore: toast messages
* fix(ci): date test
* feat: create file when uploading Assistant Avatar
* feat: file upload rate limiting from custom config with dynamic file route initialization
* refactor: use file upload limiters on post routes only
* refactor(fileConfig): add endpoints field for endpoint specific fileconfigs, add mergeConfig function, add tests
* refactor: fileConfig route, dynamic multer instances used on all '/' and '/images' POST routes, data service and query hook
* feat: supportedMimeTypesSchema, test for array of regex
* feat: configurable file config limits
* chore: clarify assistants file knowledge prereq.
* chore(useTextarea): default to localized 'Assistant' if assistant name is empty
* feat: configurable file limits and toggle file upload per endpoint
* fix(useUploadFileMutation): prevent updating assistant.files cache if file upload is a message_file attachment
* fix(AssistantSelect): set last selected assistant only when timeout successfully runs
* refactor(queries): disable assistant queries if assistants endpoint is not enabled
* chore(Switcher): add localization
* chore: pluralize `assistant` for `EModelEndpoint key and value
* feat: show/hide assistant UI components based on endpoint availability; librechat.yaml config for disabling builder section and setting polling/timeout intervals
* fix(compactEndpointSchemas): use EModelEndpoint for schema access
* feat(runAssistant): use configured values from `librechat.yaml` for `pollIntervalMs` and `timeout`
* fix: naming issue
* wip: revert landing
* 🎉 happy birthday LibreChat (#1768)
* happy birthday LibreChat
* Refactor endpoint condition in Landing component
* Update birthday message in Eng.tsx
* fix(/config): avoid nesting ternaries
* refactor(/config): check birthday
---------
Co-authored-by: Danny Avila <messagedaniel@protonmail.com>
* fix: landing
* fix: landing
* fix(useMessageHelpers): hardcoded check to use EModelEndpoint instead
* fix(ci): convo test revert to main
* fix(assistants/chat): fix issue where assistant_id was being saved as model for convo
* chore: added logging, promises racing to prevent longer timeouts, explicit setting of maxRetries and timeouts, robust catching of invalid abortRun params
* refactor: use recoil state for `showStopButton` and only show for assistants endpoint after syncing conversation data
* refactor: optimize abortRun strategy using localStorage, refactor `abortConversation` to use async/await and await the result, refactor how the abortKey cache is set for runs
* fix(checkMessageGaps): assign `assistant_id` to synced messages if defined; prevents UI from showing blank assistant for cancelled messages
* refactor: re-order sequence of chat route, only allow aborting messages after run is created, cancel abortRun if there was a cancelling error (likely due already cancelled in chat route), and add extra logging
* chore(typedefs): add httpAgent type to OpenAIClient
* refactor: use custom implementation of retrieving run with axios to allow for timing out run query
* fix(waitForRun): handle timed out run retrieval query
* refactor: update preset conditions:
- presets will retain settings when a different endpoint is selected; for existing convos, either when modular or is assistant switch
- no longer use `navigateToConvo` on preset select
* fix: temporary calculator hack as expects string input when invoked
* fix: cancel abortRun only when cancelling error is a result of the run already being cancelled
* chore: remove use of `fileMaxSizeMB` and total counterpart (redundant)
* docs: custom config documentation update
* docs: assistants api setup and dotenv, new custom config fields
* refactor(Switcher): make Assistant switcher sticky in SidePanel
* chore(useSSE): remove console log of data and message index
* refactor(AssistantPanel): button styling and add secondary select button to bottom of panel
* refactor(OpenAIClient): allow passing conversationId to RunManager through titleConvo and initializeLLM to properly record title context tokens used in cases where conversationId was not defined by the client
* feat(assistants): token tracking for assistant runs
* chore(spendTokens): improve logging
* feat: support/exclude specific assistant Ids
* chore: add update `librechat.example.yaml`, optimize `AppService` handling, new tests for `AppService`, optimize missing/outdate config logging
* chore: mount docker logs to root of project
* chore: condense axios errors
* chore: bump vite
* chore: vite hot reload fix using latest version
* chore(getOpenAIModels): sort instruct models to the end of models list
* fix(assistants): user provided key
* fix(assistants): user provided key, invalidate more queries on revoke
---------
Co-authored-by: Marco Beretta <81851188+Berry-13@users.noreply.github.com>
2024-02-13 20:42:27 -05:00
|
|
|
|
|
|
|
|
if (object.content && Array.isArray(object.content)) {
|
2025-03-27 17:09:46 -04:00
|
|
|
object.text = parseTextParts(object.content);
|
✨ feat: Assistants API, General File Support, Side Panel, File Explorer (#1696)
* feat: assistant name/icon in Landing & Header
* feat: assistname in textarea placeholder, and use `Assistant` as default name
* feat: display non-image files in user messages
* fix: only render files if files.length is > 0
* refactor(config -> file-config): move file related configuration values to separate module, add excel types
* chore: spreadsheet file rendering
* fix(Landing): dark mode style for Assistant Name
* refactor: move progress incrementing to own hook, start smaller, cap near limit \(1\)
* refactor(useContentHandler): add empty Text part if last part was completed tool or image
* chore: add accordion trigger border styling for dark mode
* feat: Assistant Builder model selection
* chore: use Spinner when Assistant is mutating
* fix(get/assistants): return correct response object `AssistantListResponse`
* refactor(Spinner): pass size as prop
* refactor: make assistant crud mutations optimistic, add types for options
* chore: remove assistants route and view
* chore: move assistant builder components to separate directory
* feat(ContextButton): delete Assistant via context button/dialog, add localization
* refactor: conditionally show use and context menu buttons, add localization for create assistant
* feat: save side panel states to localStorage
* style(SidePanel): improve avatar menu and assistant select styling for dark mode
* refactor: make NavToggle reusable for either side (left or right), add SidePanel Toggle with ability to close it completely
* fix: resize handle and navToggle behavior
* fix(/avatar/:assistant_id): await `deleteFile` and assign unique name to uploaded image
* WIP: file UI components from PR #576
* refactor(OpenAIMinimalIcon): pass className
* feat: formatDate helper fn
* feat: DataTableColumnHeader
* feat: add row selection, formatted row values, number of rows selected
* WIP: add files to Side panel temporarily
* feat: `LB_QueueAsyncCall`: Leaky Bucket queue for external APIs, use in `processDeleteRequest`
* fix(TFile): correct `source` type with `FileSources`
* fix(useFileHandling): use `continue` instead of return when iterating multiple files, add file type to extendedFile
* chore: add generic setter type
* refactor(processDeleteRequest): settle promises to prevent rejections from processing deletions, log errors
* feat: `useFileDeletion` to reuse file deletion logic
* refactor(useFileDeletion): make `setFiles` an optional param and use object as param
* feat: useDeleteFilesFromTable
* feat: use real `files` data and add deletion action to data table
* fix(Table): make headers sticky
* feat: add dynamic filtering for columns; only show to user Host or OpenAI storage type
* style(DropdownMenu): replace `slate` with `gray`
* style(DataTable): apply dark mode themes and other misc styling
* style(Columns): add color to OpenAI Storage option
* refactor(FileContainer): make file preview reusable
* refactor(Images): make image preview reusable
* refactor(FilePreview): make file prop optional for FileIcon and FilePreview, fix relative style
* feat(Columns): add file/image previews, set a minimum size to show for file size in bytes
* WIP: File Panel with real files and formatted
* feat: open files dialog from panel
* style: file data table mobile and general column styling fixes
* refactor(api/files): return files sorted by the most recently updated
* refactor: provide fileMap through context to prevent re-selecting files to map in different areas; remove unused imports commented out in PanelColumns
* refactor(ExtendFile): make File type optional, add `attached` to prevent attached files from being deleted on remove, make Message.files a partial TFile type
* feat: attach files through file panel
* refactor(useFileHandling): move files to the start of cache list when uploaded
* refactor(useDeleteFilesMutation): delete files from cache when successfully deleted from server
* fix(FileRow): handle possible edge case of duplication due to attaching recently uploaded file
* style(SidePanel): make resize grip border transparent, remove unnecessary styling on close sidepanel button
* feat: action utilities and tests
* refactor(actions): add `ValidationResult` type and change wording for no server URL found
* refactor(actions): check for empty server URL
* fix(data-provider): revert tsconfig to fix type issue resolution
* feat(client): first pass of actions input for assistants
* refactor(FunctionSignature): change method to output object instead of string
* refactor(models/Assistant): add actions field to schema, use searchParams object for methods, and add `getAssistant`
* feat: post actions input first pass
- create new Action document
- add actions to Assistant DB document
- create /action/:assistant_id POST route
- pass more props down from PanelSwitcher, derive assistant_id from switcher
- move privacy policy to ActionInput
- reset data on input change/validation
- add `useUpdateAction`
- conform FunctionSignature type to FunctionTool
- add action, assistant doc, update hook related types
* refactor: optimize assistant/actions relationship
- past domain in metadata as hostname and not a URL
- include domain in tool name
- add `getActions` for actions retrieval by user
- add `getAssistants` for assistant docs retrieval by user
- add `assistant_id` to Action schema
- move actions to own module as a subroute to `api/assistants`
- add `useGetActionsQuery` and `useGetAssistantDocsQuery` hooks
- fix Action type def
* feat: show assistant actions in assistant builder
* feat: switch to actions on action click, editing action styling
* fix: add Assistant state for builder panel to allow immediate selection of newly created assistants as well as retaining the current assistant when switching to a different panel within the builder
* refactor(SidePanel/NavToggle): offset less from right when SidePanel is completely collapsed
* chore: rename `processActions` -> `processRequiredActions`
* chore: rename Assistant API Action to RequiredAction
* refactor(actions): avoid nesting actual API params under generic `requestBody` to optimize LLM token usage
* fix(handleTools): avoid calling `validTool` if not defined, add optional param to skip the loading of specs, which throws an error in the context of assistants
* WIP: working first pass of toolCalls generated from openapi specs
* WIP: first pass ToolCall styling
* feat: programmatic iv encryption/decryption helpers
* fix: correct ActionAuth types/enums, and define type for AuthForm
* feat: encryption/decryption helpers for Action AuthMetadata
* refactor(getActions): remove sensitive fields from query response
* refactor(POST/actions): encrypt and remove sensitive fields from mutation response
* fix(ActionService): change ESM import to CJS
* feat: frontend auth handling for actions + optimistic update on action update/creation
* refactor(actions): use the correct variables and types for setAuth method
* refactor: POST /:assistant_id action can now handle updating an existing action, add `saved_auth_fields` to determine when user explicitly saves new auth creds. only send auth metadata if user explicitly saved fields
* refactor(createActionTool): catch errors and send back meaningful error message, add flag to `getActions` to determine whether to retrieve sensitive values or not
* refactor(ToolService): add `action` property to ToolCall PartMetadata to determine if the tool call was an action, fix parsing function name issue with actionDelimiter
* fix(ActionRequest): use URL class to correctly join endpoint parts for `execute` call
* feat: delete assistant actions
* refactor: conditionally show Available actions
* refactor: show `retrieval` and `code_interpreter` as Capabilities, swap `Switch` for `Checkbox`
* chore: remove shadow-stroke from messages
* WIP: first pass of Assistants Knowledge attachments
* refactor: remove AssistantsProvider in favor of FormProvider, fix selectedAssistant re-render bug, map Assistant file_ids to files via fileMap, initialize Knowledge component with mapped files if any exist
* fix: prevent deleting files on assistant file upload
* chore: remove console.log
* refactor(useUploadFileMutation): update files and assistants cache on upload
* chore: disable oauth option as not supported yet
* feat: cancel assistant runs
* refactor: initialize OpenAI client with helper function, resolve all related circular dependencies
* fix(DALL-E): initialization
* fix(process): openai client initialization
* fix: select an existing Assistant when the active one is deleted
* chore: allow attaching files for assistant endpoint, send back relevant OpenAI error message when uploading, deconstruct openAI initialization correctly, add `message_file` to formData when a file is attached to the message but not the assistant
* fix: add assistant_id on newConvo
* fix(initializeClient): import fix
* chore: swap setAssistant for setOption in useEffect
* fix(DALL-E): add processFileURL to loadTools call
* chore: add customConfig to debug logs
* feat: delete threads on convo delete
* chore: replace Assistants icon
* chore: remove console.dir() in `abortRun`
* feat(AssistantService): accumulate text values from run in openai.responseText
* feat: titling for assistants endpoint
* chore: move panel file components to appropriate directory, add file checks for attaching files, change icon for Attach Files
* refactor: add localizations to tools, plugins, add condition for adding/remove user plugins so tool selections don't affect this value
* chore: disable `import from url` action for now
* chore: remove textMimeTypes from default fileConfig for now
* fix: catch tool errors and send as outputs with error messages
* fix: React warning about button as descendant of button
* style: retrieval and cancelled icon
* WIP: pass isSubmitting to Parts, use InProgressCall to display cancelled tool calls correctly, show domain/function name
* fix(meilisearch): fix `postSaveHook` issue where indexing expects a mongo document, and join all text content parts for meili indexing
* ci: fix dall-e tests
* ci: fix client tests
* fix: button types in actions panel
* fix: plugin auth form persisting across tool selections
* fix(ci): update AppService spec with `loadAndFormatTools`
* fix(clearConvos): add id check earlier on
* refactor(AssistantAvatar): set previewURL dynamically when emtadata.avatar changes
* feat(assistants): addTitle cache setting
* fix(useSSE): resolve rebase conflicts
* fix: delete mutation
* style(SidePanel): make grip visible on active and hover, invisible otherwise
* ci: add data-provider tests to workflow, also update eslint/tsconfig to recognize specs, and add `text/csv` to fileConfig
* fix: handle edge case where auth object is undefined, and log errors
* refactor(actions): resolve schemas, add tests for resolving refs, import specs from separate file for tests
* chore: remove comment
* fix(ActionsInput): re-render bug when initializing states with action fields
* fix(patch/assistant): filter undefined tools
* chore: add logging for errors in assistants routes
* fix(updateAssistant): map actions to functions to avoid overwriting
* fix(actions): properly handle GET paths
* fix(convos): unhandled delete thread exception
* refactor(AssistantService): pass both thread_id and conversationId when sending intermediate assistant messages, remove `mapMessagesToSteps` from AssistantService
* refactor(useSSE): replace all messages with runMessages and pass latestMessageId to abortRun; fix(checkMessageGaps): include tool calls when syncing messages
* refactor(assistants/chat): invoke `createOnTextProgress` after thread creation
* chore: add typing
* style: sidepanel styling
* style: action tool call domain styling
* feat(assistants): default models, limit retrieval to certain models, add env variables to to env.example
* feat: assistants api key in EndpointService
* refactor: set assistant model to conversation on assistant switch
* refactor: set assistant model to conversation on assistant select from panel
* fix(retrieveAndProcessFile): catch attempt to download file with `assistant` purpose which is not allowed; add logging
* feat: retrieval styling, handling, and logging
* chore: rename ASSISTANTS_REVERSE_PROXY to ASSISTANTS_BASE_URL
* feat: FileContext for file metadata
* feat: context file mgmt and filtering
* style(Select): hover/rounded changes
* refactor: explicit conversation switch, endpoint dependent, through `useSelectAssistant`, which does not create new chat if current endpoint is assistant endpoint
* fix(AssistantAvatar): make empty previewURL if no avatar present
* refactor: side panel mobile styling
* style: merge tool and action section, optimize mobile styling for action/tool buttons
* fix: localStorage issues
* fix(useSelectAssistant): invoke react query hook directly in select hook as Map was not being updated in time
* style: light mode fixes
* fix: prevent sidepanel nav styling from shifting layout up
* refactor: change default layout (collapsed by default)
* style: mobile optimization of DataTable
* style: datatable
* feat: client-side hide right-side panel
* chore(useNewConvo): add partial typing for preset
* fix(useSelectAssistant): pass correct model name by using template as preset
* WIP: assistant presets
* refactor(ToolService): add native solution for `TavilySearchResults` and log tool output errors
* refactor: organize imports and use native TavilySearchResults
* fix(TavilySearchResults): stringify result
* fix(ToolCall): show tool call outputs when not an action
* chore: rename Prompt Prefix to custom instructions (in user facing text only)
* refactor(EditPresetDialog): Optimize setting title by debouncing, reset preset on dialog close to avoid state mixture
* feat: add `presetOverride` to overwrite active conversation settings when saving a Preset (relevant for client side updates only)
* feat: Assistant preset settings (client-side)
* fix(Switcher): only set assistant_id and model if current endpoint is Assistants
* feat: use `useDebouncedInput` for updating conversation settings, starting with EditPresetDialog title setting and Assistant instructions setting
* feat(Assistants): add instructions field to settings
* feat(chat/assistants): pass conversation settings to run body
* wip: begin localization and only allow actions if the assistant is created
* refactor(AssistantsPanel): knowledge localization, allow tools on creation
* feat: experimental: allow 'priming' values before assistant is created, that would normally require an assistant_id to be defined
* chore: trim console logs and make more meaningful
* chore: toast messages
* fix(ci): date test
* feat: create file when uploading Assistant Avatar
* feat: file upload rate limiting from custom config with dynamic file route initialization
* refactor: use file upload limiters on post routes only
* refactor(fileConfig): add endpoints field for endpoint specific fileconfigs, add mergeConfig function, add tests
* refactor: fileConfig route, dynamic multer instances used on all '/' and '/images' POST routes, data service and query hook
* feat: supportedMimeTypesSchema, test for array of regex
* feat: configurable file config limits
* chore: clarify assistants file knowledge prereq.
* chore(useTextarea): default to localized 'Assistant' if assistant name is empty
* feat: configurable file limits and toggle file upload per endpoint
* fix(useUploadFileMutation): prevent updating assistant.files cache if file upload is a message_file attachment
* fix(AssistantSelect): set last selected assistant only when timeout successfully runs
* refactor(queries): disable assistant queries if assistants endpoint is not enabled
* chore(Switcher): add localization
* chore: pluralize `assistant` for `EModelEndpoint key and value
* feat: show/hide assistant UI components based on endpoint availability; librechat.yaml config for disabling builder section and setting polling/timeout intervals
* fix(compactEndpointSchemas): use EModelEndpoint for schema access
* feat(runAssistant): use configured values from `librechat.yaml` for `pollIntervalMs` and `timeout`
* fix: naming issue
* wip: revert landing
* 🎉 happy birthday LibreChat (#1768)
* happy birthday LibreChat
* Refactor endpoint condition in Landing component
* Update birthday message in Eng.tsx
* fix(/config): avoid nesting ternaries
* refactor(/config): check birthday
---------
Co-authored-by: Danny Avila <messagedaniel@protonmail.com>
* fix: landing
* fix: landing
* fix(useMessageHelpers): hardcoded check to use EModelEndpoint instead
* fix(ci): convo test revert to main
* fix(assistants/chat): fix issue where assistant_id was being saved as model for convo
* chore: added logging, promises racing to prevent longer timeouts, explicit setting of maxRetries and timeouts, robust catching of invalid abortRun params
* refactor: use recoil state for `showStopButton` and only show for assistants endpoint after syncing conversation data
* refactor: optimize abortRun strategy using localStorage, refactor `abortConversation` to use async/await and await the result, refactor how the abortKey cache is set for runs
* fix(checkMessageGaps): assign `assistant_id` to synced messages if defined; prevents UI from showing blank assistant for cancelled messages
* refactor: re-order sequence of chat route, only allow aborting messages after run is created, cancel abortRun if there was a cancelling error (likely due already cancelled in chat route), and add extra logging
* chore(typedefs): add httpAgent type to OpenAIClient
* refactor: use custom implementation of retrieving run with axios to allow for timing out run query
* fix(waitForRun): handle timed out run retrieval query
* refactor: update preset conditions:
- presets will retain settings when a different endpoint is selected; for existing convos, either when modular or is assistant switch
- no longer use `navigateToConvo` on preset select
* fix: temporary calculator hack as expects string input when invoked
* fix: cancel abortRun only when cancelling error is a result of the run already being cancelled
* chore: remove use of `fileMaxSizeMB` and total counterpart (redundant)
* docs: custom config documentation update
* docs: assistants api setup and dotenv, new custom config fields
* refactor(Switcher): make Assistant switcher sticky in SidePanel
* chore(useSSE): remove console log of data and message index
* refactor(AssistantPanel): button styling and add secondary select button to bottom of panel
* refactor(OpenAIClient): allow passing conversationId to RunManager through titleConvo and initializeLLM to properly record title context tokens used in cases where conversationId was not defined by the client
* feat(assistants): token tracking for assistant runs
* chore(spendTokens): improve logging
* feat: support/exclude specific assistant Ids
* chore: add update `librechat.example.yaml`, optimize `AppService` handling, new tests for `AppService`, optimize missing/outdate config logging
* chore: mount docker logs to root of project
* chore: condense axios errors
* chore: bump vite
* chore: vite hot reload fix using latest version
* chore(getOpenAIModels): sort instruct models to the end of models list
* fix(assistants): user provided key
* fix(assistants): user provided key, invalidate more queries on revoke
---------
Co-authored-by: Marco Beretta <81851188+Berry-13@users.noreply.github.com>
2024-02-13 20:42:27 -05:00
|
|
|
delete object.content;
|
|
|
|
|
}
|
|
|
|
|
|
feat: ChatGPT Plugins/OpenAPI specs for Plugins Endpoint (#620)
* wip: proof of concept for openapi chain
* chore(api): update langchain dependency to version 0.0.105
* feat(Plugins): use ChatGPT Plugins/OpenAPI specs (first pass)
* chore(manifest.json): update pluginKey for "Browser" tool to "web-browser"
chore(handleTools.js): update customConstructor key for "web-browser" tool
* fix(handleSubmit.js): set unfinished property to false for all endpoints
* fix(handlers.js): remove unnecessary capitalizeWords function and use action.tool directly
refactor(endpoints.js): rename availableTools to tools and transform it into a map
* feat(endpoints): add plugins selector to endpoints file
refactor(CodeBlock.tsx): refactor to typescript
refactor(Plugin.tsx): use recoil Map for plugin name and refactor to typescript
chore(Message.jsx): linting
chore(PluginsOptions/index.jsx): remove comment/linting
chore(svg): export Clipboard and CheckMark components from SVG index and refactor to typescript
* fix(OpenAPIPlugin.js): rename readYamlFile function to readSpecFile
fix(OpenAPIPlugin.js): handle JSON files in readSpecFile function
fix(OpenAPIPlugin.js): handle JSON URLs in getSpec function
fix(OpenAPIPlugin.js): handle JSON variables in createOpenAPIPlugin function
fix(OpenAPIPlugin.js): add description for variables in createOpenAPIPlugin function
fix(OpenAPIPlugin.js): add optional flag for is_user_authenticated and has_user_authentication in ManifestDefinition
fix(loadSpecs.js): add optional flag for is_user_authenticated and has_user_authentication in ManifestDefinition
fix(Plugin.tsx): remove unnecessary callback parameter in getPluginName function
fix(getDefaultConversation.js): fix browser console error: handle null value for lastConversationSetup in getDefaultConversation function
* feat(api): add new tools
Add Ai PDF tool for super-fast, interactive chats with PDFs of any size, complete with page references for fact checking.
Add VoxScript tool for searching through YouTube transcripts, financial data sources, Google Search results, and more.
Add WebPilot tool for browsing and QA of webpages, PDFs, and data. Generate articles from one or more URLs.
feat(api): update OpenAPIPlugin.js
- Add support for bearer token authorization in the OpenAPIPlugin.
- Add support for custom headers in the OpenAPIPlugin.
fix(api): fix loadTools.js
- Pass the user parameter to the loadSpecs function.
* feat(PluginsClient.js): import findMessageContent function from utils
feat(PluginsClient.js): add message parameter to options object in initializeCustomAgent function
feat(PluginsClient.js): add content to errorMessage if message content is found
feat(PluginsClient.js): break out of loop if message content is found
feat(PluginsClient.js): add delay option with value of 8 to generateTextStream function
feat(PluginsClient.js): add support for process.env.PORT environment variable in app.listen function
feat(askyourpdf.json): add askyourpdf plugin configuration
feat(metar.json): add metar plugin configuration
feat(askyourpdf.yaml): add askyourpdf plugin OpenAPI specification
feat(OpenAPIPlugin.js): add message parameter to createOpenAPIPlugin function
feat(OpenAPIPlugin.js): add description_for_model to chain run message
feat(addOpenAPISpecs.js): remove verbose option from loadSpecs function call
fix(loadSpecs.js): add 'message' parameter to the loadSpecs function
feat(findMessageContent.js): add utility function to find message content in JSON objects
* fix(PluginStoreDialog.tsx): update z-index value for the dialog container
The z-index value for the dialog container was updated to "102" to ensure it appears above other elements on the page.
* chore(web_pilot.json): add "params" field with "user_has_request" parameter set to true
* chore(eslintrc.js): update eslint rules
fix(Login.tsx): add missing semicolon after import statement
* fix(package-lock.json): update langchain dependency to version ^0.0.105
* fix(OpenAPIPlugin.js): change header key from 'id' to 'librechat_user_id' for consistency and clarity
feat(plugins): add documentation for using official ChatGPT Plugins with OpenAPI specs
This commit adds a new file `chatgpt_plugins_openapi.md` to the `docs/features/plugins` directory. The file provides detailed information on how to use official ChatGPT Plugins with OpenAPI specifications. It explains the components of a plugin, including the Plugin Manifest file and the OpenAPI spec. It also covers the process of adding a plugin, editing manifest files, and customizing OpenAPI spec files. Additionally, the commit includes disclaimers about the limitations and compatibility of plugins with LibreChat. The documentation also clarifies that the use of ChatGPT Plugins with LibreChat does not violate OpenAI's Terms of Service.
The purpose of this commit is to provide comprehensive documentation for developers who want to integrate ChatGPT Plugins into their projects using OpenAPI specs. It aims to guide them through the process of adding and configuring plugins, as well as addressing potential issues and
chore(introduction.md): update link to ChatGPT Plugins documentation
docs(introduction.md): clarify the purpose of the plugins endpoint and its capabilities
* fix(OpenAPIPlugin.js): update SUFFIX variable to provide a clearer description
docs(chatgpt_plugins_openapi.md): update information about adding plugins via url on the frontend
* feat(PluginsClient.js): sendIntermediateMessage on successful Agent load
fix(PluginsClient.js, server/index.js, gptPlugins.js): linting fixes
docs(chatgpt_plugins_openapi.md): update links and add additional information
* Update chatgpt_plugins_openapi.md
* chore: rebuild package-lock file
* chore: format/lint all files with new rules
* chore: format all files
* chore(README.md): update AI model selection list
The AI model selection list in the README.md file has been updated to reflect the current options available. The "Anthropic" model has been added as an alternative name for the "Claude" model.
* fix(Plugin.tsx): type issue
* feat(tools): add new tool WebPilot
feat(tools): remove tool Weather Report
feat(tools): add new tool Prompt Perfect
feat(tools): add new tool Scholarly Graph Link
* feat(OpenAPIPlugin.js): add getSpec and readSpecFile functions
feat(OpenAPIPlugin.spec.js): add tests for readSpecFile, getSpec, and createOpenAPIPlugin functions
* chore(agent-demo-1.js): remove unused code and dependencies
chore(agent-demo-2.js): remove unused code and dependencies
chore(demo.js): remove unused code and dependencies
* feat(addOpenAPISpecs): add function to transform OpenAPI specs into desired format
feat(addOpenAPISpecs.spec): add tests for transformSpec function
fix(loadSpecs): remove debugging code
* feat(loadSpecs.spec.js): add unit tests for ManifestDefinition, validateJson, and loadSpecs functions
* fix: package file resolution bug
* chore: move scholarly_graph_link manifest to 'has-issues'
* refactor(client/hooks): convert to TS and export from index
* Update introduction.md
* Update chatgpt_plugins_openapi.md
2023-07-16 12:19:47 -04:00
|
|
|
return object;
|
2023-07-08 11:20:57 +09:00
|
|
|
}
|
2023-03-22 01:31:01 -04:00
|
|
|
|
2025-03-08 20:37:33 +01:00
|
|
|
/**
|
|
|
|
|
* Adds the current document to the MeiliSearch index.
|
|
|
|
|
*
|
|
|
|
|
* The method preprocesses the document, adds it to MeiliSearch, and then updates
|
|
|
|
|
* the MongoDB document's `_meiliIndex` flag to true.
|
|
|
|
|
*
|
|
|
|
|
* @returns {Promise<void>}
|
|
|
|
|
*/
|
2023-07-08 11:20:57 +09:00
|
|
|
async addObjectToMeili() {
|
feat: ChatGPT Plugins/OpenAPI specs for Plugins Endpoint (#620)
* wip: proof of concept for openapi chain
* chore(api): update langchain dependency to version 0.0.105
* feat(Plugins): use ChatGPT Plugins/OpenAPI specs (first pass)
* chore(manifest.json): update pluginKey for "Browser" tool to "web-browser"
chore(handleTools.js): update customConstructor key for "web-browser" tool
* fix(handleSubmit.js): set unfinished property to false for all endpoints
* fix(handlers.js): remove unnecessary capitalizeWords function and use action.tool directly
refactor(endpoints.js): rename availableTools to tools and transform it into a map
* feat(endpoints): add plugins selector to endpoints file
refactor(CodeBlock.tsx): refactor to typescript
refactor(Plugin.tsx): use recoil Map for plugin name and refactor to typescript
chore(Message.jsx): linting
chore(PluginsOptions/index.jsx): remove comment/linting
chore(svg): export Clipboard and CheckMark components from SVG index and refactor to typescript
* fix(OpenAPIPlugin.js): rename readYamlFile function to readSpecFile
fix(OpenAPIPlugin.js): handle JSON files in readSpecFile function
fix(OpenAPIPlugin.js): handle JSON URLs in getSpec function
fix(OpenAPIPlugin.js): handle JSON variables in createOpenAPIPlugin function
fix(OpenAPIPlugin.js): add description for variables in createOpenAPIPlugin function
fix(OpenAPIPlugin.js): add optional flag for is_user_authenticated and has_user_authentication in ManifestDefinition
fix(loadSpecs.js): add optional flag for is_user_authenticated and has_user_authentication in ManifestDefinition
fix(Plugin.tsx): remove unnecessary callback parameter in getPluginName function
fix(getDefaultConversation.js): fix browser console error: handle null value for lastConversationSetup in getDefaultConversation function
* feat(api): add new tools
Add Ai PDF tool for super-fast, interactive chats with PDFs of any size, complete with page references for fact checking.
Add VoxScript tool for searching through YouTube transcripts, financial data sources, Google Search results, and more.
Add WebPilot tool for browsing and QA of webpages, PDFs, and data. Generate articles from one or more URLs.
feat(api): update OpenAPIPlugin.js
- Add support for bearer token authorization in the OpenAPIPlugin.
- Add support for custom headers in the OpenAPIPlugin.
fix(api): fix loadTools.js
- Pass the user parameter to the loadSpecs function.
* feat(PluginsClient.js): import findMessageContent function from utils
feat(PluginsClient.js): add message parameter to options object in initializeCustomAgent function
feat(PluginsClient.js): add content to errorMessage if message content is found
feat(PluginsClient.js): break out of loop if message content is found
feat(PluginsClient.js): add delay option with value of 8 to generateTextStream function
feat(PluginsClient.js): add support for process.env.PORT environment variable in app.listen function
feat(askyourpdf.json): add askyourpdf plugin configuration
feat(metar.json): add metar plugin configuration
feat(askyourpdf.yaml): add askyourpdf plugin OpenAPI specification
feat(OpenAPIPlugin.js): add message parameter to createOpenAPIPlugin function
feat(OpenAPIPlugin.js): add description_for_model to chain run message
feat(addOpenAPISpecs.js): remove verbose option from loadSpecs function call
fix(loadSpecs.js): add 'message' parameter to the loadSpecs function
feat(findMessageContent.js): add utility function to find message content in JSON objects
* fix(PluginStoreDialog.tsx): update z-index value for the dialog container
The z-index value for the dialog container was updated to "102" to ensure it appears above other elements on the page.
* chore(web_pilot.json): add "params" field with "user_has_request" parameter set to true
* chore(eslintrc.js): update eslint rules
fix(Login.tsx): add missing semicolon after import statement
* fix(package-lock.json): update langchain dependency to version ^0.0.105
* fix(OpenAPIPlugin.js): change header key from 'id' to 'librechat_user_id' for consistency and clarity
feat(plugins): add documentation for using official ChatGPT Plugins with OpenAPI specs
This commit adds a new file `chatgpt_plugins_openapi.md` to the `docs/features/plugins` directory. The file provides detailed information on how to use official ChatGPT Plugins with OpenAPI specifications. It explains the components of a plugin, including the Plugin Manifest file and the OpenAPI spec. It also covers the process of adding a plugin, editing manifest files, and customizing OpenAPI spec files. Additionally, the commit includes disclaimers about the limitations and compatibility of plugins with LibreChat. The documentation also clarifies that the use of ChatGPT Plugins with LibreChat does not violate OpenAI's Terms of Service.
The purpose of this commit is to provide comprehensive documentation for developers who want to integrate ChatGPT Plugins into their projects using OpenAPI specs. It aims to guide them through the process of adding and configuring plugins, as well as addressing potential issues and
chore(introduction.md): update link to ChatGPT Plugins documentation
docs(introduction.md): clarify the purpose of the plugins endpoint and its capabilities
* fix(OpenAPIPlugin.js): update SUFFIX variable to provide a clearer description
docs(chatgpt_plugins_openapi.md): update information about adding plugins via url on the frontend
* feat(PluginsClient.js): sendIntermediateMessage on successful Agent load
fix(PluginsClient.js, server/index.js, gptPlugins.js): linting fixes
docs(chatgpt_plugins_openapi.md): update links and add additional information
* Update chatgpt_plugins_openapi.md
* chore: rebuild package-lock file
* chore: format/lint all files with new rules
* chore: format all files
* chore(README.md): update AI model selection list
The AI model selection list in the README.md file has been updated to reflect the current options available. The "Anthropic" model has been added as an alternative name for the "Claude" model.
* fix(Plugin.tsx): type issue
* feat(tools): add new tool WebPilot
feat(tools): remove tool Weather Report
feat(tools): add new tool Prompt Perfect
feat(tools): add new tool Scholarly Graph Link
* feat(OpenAPIPlugin.js): add getSpec and readSpecFile functions
feat(OpenAPIPlugin.spec.js): add tests for readSpecFile, getSpec, and createOpenAPIPlugin functions
* chore(agent-demo-1.js): remove unused code and dependencies
chore(agent-demo-2.js): remove unused code and dependencies
chore(demo.js): remove unused code and dependencies
* feat(addOpenAPISpecs): add function to transform OpenAPI specs into desired format
feat(addOpenAPISpecs.spec): add tests for transformSpec function
fix(loadSpecs): remove debugging code
* feat(loadSpecs.spec.js): add unit tests for ManifestDefinition, validateJson, and loadSpecs functions
* fix: package file resolution bug
* chore: move scholarly_graph_link manifest to 'has-issues'
* refactor(client/hooks): convert to TS and export from index
* Update introduction.md
* Update chatgpt_plugins_openapi.md
2023-07-16 12:19:47 -04:00
|
|
|
const object = this.preprocessObjectForIndex();
|
2023-03-22 01:31:01 -04:00
|
|
|
try {
|
|
|
|
|
await index.addDocuments([object]);
|
|
|
|
|
} catch (error) {
|
2025-03-08 20:37:33 +01:00
|
|
|
// Error handling can be enhanced as needed.
|
|
|
|
|
logger.error('[addObjectToMeili] Error adding document to Meili', error);
|
2023-03-22 01:31:01 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
await this.collection.updateMany({ _id: this._id }, { $set: { _meiliIndex: true } });
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-08 20:37:33 +01:00
|
|
|
/**
|
|
|
|
|
* Updates the current document in the MeiliSearch index.
|
|
|
|
|
*
|
|
|
|
|
* @returns {Promise<void>}
|
|
|
|
|
*/
|
2023-03-22 01:31:01 -04:00
|
|
|
async updateObjectToMeili() {
|
2025-03-08 20:37:33 +01:00
|
|
|
const object = _.omitBy(_.pick(this.toJSON(), attributesToIndex), (v, k) =>
|
|
|
|
|
k.startsWith('$'),
|
|
|
|
|
);
|
2023-03-22 01:31:01 -04:00
|
|
|
await index.updateDocuments([object]);
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-08 20:37:33 +01:00
|
|
|
/**
|
|
|
|
|
* Deletes the current document from the MeiliSearch index.
|
|
|
|
|
*
|
|
|
|
|
* @returns {Promise<void>}
|
|
|
|
|
*/
|
2023-03-22 01:31:01 -04:00
|
|
|
async deleteObjectFromMeili() {
|
|
|
|
|
await index.deleteDocument(this._id);
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-08 20:37:33 +01:00
|
|
|
/**
|
|
|
|
|
* Post-save hook to synchronize the document with MeiliSearch.
|
|
|
|
|
*
|
|
|
|
|
* If the document is already indexed (i.e. `_meiliIndex` is true), it updates it;
|
|
|
|
|
* otherwise, it adds the document to the index.
|
|
|
|
|
*/
|
2023-03-22 01:31:01 -04:00
|
|
|
postSaveHook() {
|
|
|
|
|
if (this._meiliIndex) {
|
|
|
|
|
this.updateObjectToMeili();
|
|
|
|
|
} else {
|
|
|
|
|
this.addObjectToMeili();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-08 20:37:33 +01:00
|
|
|
/**
|
|
|
|
|
* Post-update hook to update the document in MeiliSearch.
|
|
|
|
|
*
|
|
|
|
|
* This hook is triggered after a document update, ensuring that changes are
|
|
|
|
|
* propagated to the MeiliSearch index if the document is indexed.
|
|
|
|
|
*/
|
2023-03-22 01:31:01 -04:00
|
|
|
postUpdateHook() {
|
|
|
|
|
if (this._meiliIndex) {
|
|
|
|
|
this.updateObjectToMeili();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-08 20:37:33 +01:00
|
|
|
/**
|
|
|
|
|
* Post-remove hook to delete the document from MeiliSearch.
|
|
|
|
|
*
|
|
|
|
|
* This hook is triggered after a document is removed, ensuring that the document
|
|
|
|
|
* is also removed from the MeiliSearch index if it was previously indexed.
|
|
|
|
|
*/
|
2023-03-22 01:31:01 -04:00
|
|
|
postRemoveHook() {
|
|
|
|
|
if (this._meiliIndex) {
|
|
|
|
|
this.deleteObjectFromMeili();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return MeiliMongooseModel;
|
|
|
|
|
};
|
|
|
|
|
|
2025-03-08 20:37:33 +01:00
|
|
|
/**
|
|
|
|
|
* Mongoose plugin to synchronize MongoDB collections with a MeiliSearch index.
|
|
|
|
|
*
|
|
|
|
|
* This plugin:
|
|
|
|
|
* - Validates the provided options.
|
|
|
|
|
* - Adds a `_meiliIndex` field to the schema to track indexing status.
|
|
|
|
|
* - Sets up a MeiliSearch client and creates an index if it doesn't already exist.
|
|
|
|
|
* - Loads class methods for syncing, searching, and managing documents in MeiliSearch.
|
|
|
|
|
* - Registers Mongoose hooks (post-save, post-update, post-remove, etc.) to maintain index consistency.
|
|
|
|
|
*
|
|
|
|
|
* @param {mongoose.Schema} schema - The Mongoose schema to which the plugin is applied.
|
|
|
|
|
* @param {Object} options - Configuration options.
|
|
|
|
|
* @param {string} options.host - The MeiliSearch host.
|
|
|
|
|
* @param {string} options.apiKey - The MeiliSearch API key.
|
|
|
|
|
* @param {string} options.indexName - The name of the MeiliSearch index.
|
|
|
|
|
* @param {string} options.primaryKey - The primary key field for indexing.
|
|
|
|
|
*/
|
2023-03-22 01:31:01 -04:00
|
|
|
module.exports = function mongoMeili(schema, options) {
|
|
|
|
|
validateOptions(options);
|
|
|
|
|
|
2025-03-08 20:37:33 +01:00
|
|
|
// Add _meiliIndex field to the schema to track if a document has been indexed in MeiliSearch.
|
2023-03-22 01:31:01 -04:00
|
|
|
schema.add({
|
|
|
|
|
_meiliIndex: {
|
|
|
|
|
type: Boolean,
|
|
|
|
|
required: false,
|
|
|
|
|
select: false,
|
2023-07-14 09:36:49 -04:00
|
|
|
default: false,
|
|
|
|
|
},
|
2023-03-22 01:31:01 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const { host, apiKey, indexName, primaryKey } = options;
|
|
|
|
|
|
2025-03-08 20:37:33 +01:00
|
|
|
// Setup the MeiliSearch client.
|
2023-03-22 01:31:01 -04:00
|
|
|
const client = new MeiliSearch({ host, apiKey });
|
|
|
|
|
|
2025-03-08 20:37:33 +01:00
|
|
|
// Create the index asynchronously if it doesn't exist.
|
2023-03-22 01:31:01 -04:00
|
|
|
client.createIndex(indexName, { primaryKey });
|
|
|
|
|
|
2025-03-08 20:37:33 +01:00
|
|
|
// Setup the MeiliSearch index for this schema.
|
2023-03-22 01:31:01 -04:00
|
|
|
const index = client.index(indexName);
|
|
|
|
|
|
2025-03-08 20:37:33 +01:00
|
|
|
// Collect attributes from the schema that should be indexed.
|
2023-03-22 01:31:01 -04:00
|
|
|
const attributesToIndex = [
|
|
|
|
|
..._.reduce(
|
|
|
|
|
schema.obj,
|
|
|
|
|
function (results, value, key) {
|
|
|
|
|
return value.meiliIndex ? [...results, key] : results;
|
|
|
|
|
},
|
2023-07-14 09:36:49 -04:00
|
|
|
[],
|
|
|
|
|
),
|
2023-03-22 01:31:01 -04:00
|
|
|
];
|
|
|
|
|
|
2025-03-08 20:37:33 +01:00
|
|
|
// Load the class methods into the schema.
|
2023-03-22 01:31:01 -04:00
|
|
|
schema.loadClass(createMeiliMongooseModel({ index, indexName, client, attributesToIndex }));
|
|
|
|
|
|
2025-03-08 20:37:33 +01:00
|
|
|
// Register Mongoose hooks to synchronize with MeiliSearch.
|
|
|
|
|
|
|
|
|
|
// Post-save: synchronize after a document is saved.
|
2023-03-22 01:31:01 -04:00
|
|
|
schema.post('save', function (doc) {
|
|
|
|
|
doc.postSaveHook();
|
|
|
|
|
});
|
2025-03-08 20:37:33 +01:00
|
|
|
|
|
|
|
|
// Post-update: synchronize after a document is updated.
|
2023-03-22 01:31:01 -04:00
|
|
|
schema.post('update', function (doc) {
|
|
|
|
|
doc.postUpdateHook();
|
|
|
|
|
});
|
2025-03-08 20:37:33 +01:00
|
|
|
|
|
|
|
|
// Post-remove: synchronize after a document is removed.
|
2023-03-22 01:31:01 -04:00
|
|
|
schema.post('remove', function (doc) {
|
|
|
|
|
doc.postRemoveHook();
|
|
|
|
|
});
|
2023-05-18 11:09:31 -07:00
|
|
|
|
2025-03-08 20:37:33 +01:00
|
|
|
// Pre-deleteMany hook: remove corresponding documents from MeiliSearch when multiple documents are deleted.
|
2023-07-07 02:03:23 -04:00
|
|
|
schema.pre('deleteMany', async function (next) {
|
2023-07-08 11:41:51 -04:00
|
|
|
if (!meiliEnabled) {
|
2025-03-08 20:37:33 +01:00
|
|
|
return next();
|
2023-07-08 11:41:51 -04:00
|
|
|
}
|
|
|
|
|
|
2023-07-07 02:03:23 -04:00
|
|
|
try {
|
2025-03-08 20:37:33 +01:00
|
|
|
// Check if the schema has a "messages" field to determine if it's a conversation schema.
|
2023-07-07 02:03:23 -04:00
|
|
|
if (Object.prototype.hasOwnProperty.call(schema.obj, 'messages')) {
|
|
|
|
|
const convoIndex = client.index('convos');
|
|
|
|
|
const deletedConvos = await mongoose.model('Conversation').find(this._conditions).lean();
|
2025-03-08 20:37:33 +01:00
|
|
|
const promises = deletedConvos.map((convo) =>
|
|
|
|
|
convoIndex.deleteDocument(convo.conversationId),
|
|
|
|
|
);
|
2023-07-07 02:03:23 -04:00
|
|
|
await Promise.all(promises);
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-08 20:37:33 +01:00
|
|
|
// Check if the schema has a "messageId" field to determine if it's a message schema.
|
2023-07-07 02:03:23 -04:00
|
|
|
if (Object.prototype.hasOwnProperty.call(schema.obj, 'messageId')) {
|
|
|
|
|
const messageIndex = client.index('messages');
|
|
|
|
|
const deletedMessages = await mongoose.model('Message').find(this._conditions).lean();
|
2025-03-08 20:37:33 +01:00
|
|
|
const promises = deletedMessages.map((message) =>
|
|
|
|
|
messageIndex.deleteDocument(message.messageId),
|
|
|
|
|
);
|
2023-07-07 02:03:23 -04:00
|
|
|
await Promise.all(promises);
|
|
|
|
|
}
|
|
|
|
|
return next();
|
|
|
|
|
} catch (error) {
|
2023-07-08 11:41:51 -04:00
|
|
|
if (meiliEnabled) {
|
2023-12-14 07:49:27 -05:00
|
|
|
logger.error(
|
2025-03-08 20:37:33 +01:00
|
|
|
'[MeiliMongooseModel.deleteMany] There was an issue deleting conversation indexes upon deletion. Next startup may be slow due to syncing.',
|
2023-12-14 07:49:27 -05:00
|
|
|
error,
|
feat: ChatGPT Plugins/OpenAPI specs for Plugins Endpoint (#620)
* wip: proof of concept for openapi chain
* chore(api): update langchain dependency to version 0.0.105
* feat(Plugins): use ChatGPT Plugins/OpenAPI specs (first pass)
* chore(manifest.json): update pluginKey for "Browser" tool to "web-browser"
chore(handleTools.js): update customConstructor key for "web-browser" tool
* fix(handleSubmit.js): set unfinished property to false for all endpoints
* fix(handlers.js): remove unnecessary capitalizeWords function and use action.tool directly
refactor(endpoints.js): rename availableTools to tools and transform it into a map
* feat(endpoints): add plugins selector to endpoints file
refactor(CodeBlock.tsx): refactor to typescript
refactor(Plugin.tsx): use recoil Map for plugin name and refactor to typescript
chore(Message.jsx): linting
chore(PluginsOptions/index.jsx): remove comment/linting
chore(svg): export Clipboard and CheckMark components from SVG index and refactor to typescript
* fix(OpenAPIPlugin.js): rename readYamlFile function to readSpecFile
fix(OpenAPIPlugin.js): handle JSON files in readSpecFile function
fix(OpenAPIPlugin.js): handle JSON URLs in getSpec function
fix(OpenAPIPlugin.js): handle JSON variables in createOpenAPIPlugin function
fix(OpenAPIPlugin.js): add description for variables in createOpenAPIPlugin function
fix(OpenAPIPlugin.js): add optional flag for is_user_authenticated and has_user_authentication in ManifestDefinition
fix(loadSpecs.js): add optional flag for is_user_authenticated and has_user_authentication in ManifestDefinition
fix(Plugin.tsx): remove unnecessary callback parameter in getPluginName function
fix(getDefaultConversation.js): fix browser console error: handle null value for lastConversationSetup in getDefaultConversation function
* feat(api): add new tools
Add Ai PDF tool for super-fast, interactive chats with PDFs of any size, complete with page references for fact checking.
Add VoxScript tool for searching through YouTube transcripts, financial data sources, Google Search results, and more.
Add WebPilot tool for browsing and QA of webpages, PDFs, and data. Generate articles from one or more URLs.
feat(api): update OpenAPIPlugin.js
- Add support for bearer token authorization in the OpenAPIPlugin.
- Add support for custom headers in the OpenAPIPlugin.
fix(api): fix loadTools.js
- Pass the user parameter to the loadSpecs function.
* feat(PluginsClient.js): import findMessageContent function from utils
feat(PluginsClient.js): add message parameter to options object in initializeCustomAgent function
feat(PluginsClient.js): add content to errorMessage if message content is found
feat(PluginsClient.js): break out of loop if message content is found
feat(PluginsClient.js): add delay option with value of 8 to generateTextStream function
feat(PluginsClient.js): add support for process.env.PORT environment variable in app.listen function
feat(askyourpdf.json): add askyourpdf plugin configuration
feat(metar.json): add metar plugin configuration
feat(askyourpdf.yaml): add askyourpdf plugin OpenAPI specification
feat(OpenAPIPlugin.js): add message parameter to createOpenAPIPlugin function
feat(OpenAPIPlugin.js): add description_for_model to chain run message
feat(addOpenAPISpecs.js): remove verbose option from loadSpecs function call
fix(loadSpecs.js): add 'message' parameter to the loadSpecs function
feat(findMessageContent.js): add utility function to find message content in JSON objects
* fix(PluginStoreDialog.tsx): update z-index value for the dialog container
The z-index value for the dialog container was updated to "102" to ensure it appears above other elements on the page.
* chore(web_pilot.json): add "params" field with "user_has_request" parameter set to true
* chore(eslintrc.js): update eslint rules
fix(Login.tsx): add missing semicolon after import statement
* fix(package-lock.json): update langchain dependency to version ^0.0.105
* fix(OpenAPIPlugin.js): change header key from 'id' to 'librechat_user_id' for consistency and clarity
feat(plugins): add documentation for using official ChatGPT Plugins with OpenAPI specs
This commit adds a new file `chatgpt_plugins_openapi.md` to the `docs/features/plugins` directory. The file provides detailed information on how to use official ChatGPT Plugins with OpenAPI specifications. It explains the components of a plugin, including the Plugin Manifest file and the OpenAPI spec. It also covers the process of adding a plugin, editing manifest files, and customizing OpenAPI spec files. Additionally, the commit includes disclaimers about the limitations and compatibility of plugins with LibreChat. The documentation also clarifies that the use of ChatGPT Plugins with LibreChat does not violate OpenAI's Terms of Service.
The purpose of this commit is to provide comprehensive documentation for developers who want to integrate ChatGPT Plugins into their projects using OpenAPI specs. It aims to guide them through the process of adding and configuring plugins, as well as addressing potential issues and
chore(introduction.md): update link to ChatGPT Plugins documentation
docs(introduction.md): clarify the purpose of the plugins endpoint and its capabilities
* fix(OpenAPIPlugin.js): update SUFFIX variable to provide a clearer description
docs(chatgpt_plugins_openapi.md): update information about adding plugins via url on the frontend
* feat(PluginsClient.js): sendIntermediateMessage on successful Agent load
fix(PluginsClient.js, server/index.js, gptPlugins.js): linting fixes
docs(chatgpt_plugins_openapi.md): update links and add additional information
* Update chatgpt_plugins_openapi.md
* chore: rebuild package-lock file
* chore: format/lint all files with new rules
* chore: format all files
* chore(README.md): update AI model selection list
The AI model selection list in the README.md file has been updated to reflect the current options available. The "Anthropic" model has been added as an alternative name for the "Claude" model.
* fix(Plugin.tsx): type issue
* feat(tools): add new tool WebPilot
feat(tools): remove tool Weather Report
feat(tools): add new tool Prompt Perfect
feat(tools): add new tool Scholarly Graph Link
* feat(OpenAPIPlugin.js): add getSpec and readSpecFile functions
feat(OpenAPIPlugin.spec.js): add tests for readSpecFile, getSpec, and createOpenAPIPlugin functions
* chore(agent-demo-1.js): remove unused code and dependencies
chore(agent-demo-2.js): remove unused code and dependencies
chore(demo.js): remove unused code and dependencies
* feat(addOpenAPISpecs): add function to transform OpenAPI specs into desired format
feat(addOpenAPISpecs.spec): add tests for transformSpec function
fix(loadSpecs): remove debugging code
* feat(loadSpecs.spec.js): add unit tests for ManifestDefinition, validateJson, and loadSpecs functions
* fix: package file resolution bug
* chore: move scholarly_graph_link manifest to 'has-issues'
* refactor(client/hooks): convert to TS and export from index
* Update introduction.md
* Update chatgpt_plugins_openapi.md
2023-07-16 12:19:47 -04:00
|
|
|
);
|
2023-07-08 11:41:51 -04:00
|
|
|
}
|
|
|
|
|
return next();
|
2023-03-22 19:52:38 -04:00
|
|
|
}
|
|
|
|
|
});
|
2023-07-07 02:03:23 -04:00
|
|
|
|
2025-03-08 20:37:33 +01:00
|
|
|
// Post-findOneAndUpdate hook: update MeiliSearch index after a document is updated via findOneAndUpdate.
|
2023-07-07 02:03:23 -04:00
|
|
|
schema.post('findOneAndUpdate', async function (doc) {
|
2023-07-08 11:41:51 -04:00
|
|
|
if (!meiliEnabled) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-08 20:37:33 +01:00
|
|
|
// If the document is unfinished, do not update the index.
|
2023-07-07 02:03:23 -04:00
|
|
|
if (doc.unfinished) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let meiliDoc;
|
2025-03-08 20:37:33 +01:00
|
|
|
// For conversation documents, try to fetch the document from the "convos" index.
|
2023-07-07 02:03:23 -04:00
|
|
|
if (doc.messages) {
|
|
|
|
|
try {
|
|
|
|
|
meiliDoc = await client.index('convos').getDocument(doc.conversationId);
|
|
|
|
|
} catch (error) {
|
2024-05-09 13:27:13 -04:00
|
|
|
logger.debug(
|
2023-12-14 07:49:27 -05:00
|
|
|
'[MeiliMongooseModel.findOneAndUpdate] Convo not found in MeiliSearch and will index ' +
|
|
|
|
|
doc.conversationId,
|
|
|
|
|
error,
|
|
|
|
|
);
|
2023-07-07 02:03:23 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-08 20:37:33 +01:00
|
|
|
// If the MeiliSearch document exists and the title is unchanged, do nothing.
|
2023-07-07 02:03:23 -04:00
|
|
|
if (meiliDoc && meiliDoc.title === doc.title) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-08 20:37:33 +01:00
|
|
|
// Otherwise, trigger a post-save hook to synchronize the document.
|
2023-03-22 01:31:01 -04:00
|
|
|
doc.postSaveHook();
|
|
|
|
|
});
|
|
|
|
|
};
|