ℹ️ refactor: Remove use of Agenda for Conversation Imports (#3024)

* chore: remove agenda and npm audit fix

* refactor: import conversations without agenda

* chore: update package-lock.json and data-provider version to 0.6.7

* fix: import conversations

* chore: client npm audit fix
This commit is contained in:
Danny Avila 2024-06-10 13:00:34 -04:00 committed by GitHub
parent 92232afaca
commit 2e559137ae
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 52 additions and 402 deletions

View file

@ -41,7 +41,6 @@
"@langchain/community": "^0.0.46", "@langchain/community": "^0.0.46",
"@langchain/google-genai": "^0.0.11", "@langchain/google-genai": "^0.0.11",
"@langchain/google-vertexai": "^0.0.17", "@langchain/google-vertexai": "^0.0.17",
"agenda": "^5.0.0",
"axios": "^1.3.4", "axios": "^1.3.4",
"bcryptjs": "^2.4.3", "bcryptjs": "^2.4.3",
"cheerio": "^1.0.0-rc.12", "cheerio": "^1.0.0-rc.12",

View file

@ -3,12 +3,11 @@ const express = require('express');
const { CacheKeys } = require('librechat-data-provider'); const { CacheKeys } = require('librechat-data-provider');
const { initializeClient } = require('~/server/services/Endpoints/assistants'); const { initializeClient } = require('~/server/services/Endpoints/assistants');
const { getConvosByPage, deleteConvos, getConvo, saveConvo } = require('~/models/Conversation'); const { getConvosByPage, deleteConvos, getConvo, saveConvo } = require('~/models/Conversation');
const { IMPORT_CONVERSATION_JOB_NAME } = require('~/server/utils/import/jobDefinition');
const { storage, importFileFilter } = require('~/server/routes/files/multer'); const { storage, importFileFilter } = require('~/server/routes/files/multer');
const requireJwtAuth = require('~/server/middleware/requireJwtAuth'); const requireJwtAuth = require('~/server/middleware/requireJwtAuth');
const { forkConversation } = require('~/server/utils/import/fork'); const { forkConversation } = require('~/server/utils/import/fork');
const { importConversations } = require('~/server/utils/import');
const { createImportLimiters } = require('~/server/middleware'); const { createImportLimiters } = require('~/server/middleware');
const jobScheduler = require('~/server/utils/jobScheduler');
const getLogStores = require('~/cache/getLogStores'); const getLogStores = require('~/cache/getLogStores');
const { sleep } = require('~/server/utils'); const { sleep } = require('~/server/utils');
const { logger } = require('~/config'); const { logger } = require('~/config');
@ -129,10 +128,9 @@ router.post(
upload.single('file'), upload.single('file'),
async (req, res) => { async (req, res) => {
try { try {
const filepath = req.file.path; /* TODO: optimize to return imported conversations and add manually */
const job = await jobScheduler.now(IMPORT_CONVERSATION_JOB_NAME, filepath, req.user.id); await importConversations({ filepath: req.file.path, requestUserId: req.user.id });
res.status(201).json({ message: 'Conversation(s) imported successfully' });
res.status(201).json({ message: 'Import started', jobId: job.id });
} catch (error) { } catch (error) {
logger.error('Error processing file', error); logger.error('Error processing file', error);
res.status(500).send('Error processing file'); res.status(500).send('Error processing file');
@ -169,24 +167,4 @@ router.post('/fork', async (req, res) => {
} }
}); });
// Get the status of an import job for polling
router.get('/import/jobs/:jobId', async (req, res) => {
try {
const { jobId } = req.params;
const { userId, ...jobStatus } = await jobScheduler.getJobStatus(jobId);
if (!jobStatus) {
return res.status(404).json({ message: 'Job not found.' });
}
if (userId !== req.user.id) {
return res.status(403).json({ message: 'Unauthorized' });
}
res.json(jobStatus);
} catch (error) {
logger.error('Error getting job details', error);
res.status(500).send('Error getting job details');
}
});
module.exports = router; module.exports = router;

View file

@ -1,18 +1,14 @@
const fs = require('fs').promises; const fs = require('fs').promises;
const jobScheduler = require('~/server/utils/jobScheduler');
const { getImporter } = require('./importers'); const { getImporter } = require('./importers');
const { indexSync } = require('~/lib/db'); const { indexSync } = require('~/lib/db');
const { logger } = require('~/config'); const { logger } = require('~/config');
const IMPORT_CONVERSATION_JOB_NAME = 'import conversation';
/** /**
* Job definition for importing a conversation. * Job definition for importing a conversation.
* @param {import('agenda').Job} job - The job object. * @param {{ filepath, requestUserId }} job - The job object.
* @param {Function} done - The done function.
*/ */
const importConversationJob = async (job, done) => { const importConversations = async (job) => {
const { filepath, requestUserId } = job.attrs.data; const { filepath, requestUserId } = job;
try { try {
logger.debug(`user: ${requestUserId} | Importing conversation(s) from file...`); logger.debug(`user: ${requestUserId} | Importing conversation(s) from file...`);
const fileData = await fs.readFile(filepath, 'utf8'); const fileData = await fs.readFile(filepath, 'utf8');
@ -22,10 +18,8 @@ const importConversationJob = async (job, done) => {
// Sync Meilisearch index // Sync Meilisearch index
await indexSync(); await indexSync();
logger.debug(`user: ${requestUserId} | Finished importing conversations`); logger.debug(`user: ${requestUserId} | Finished importing conversations`);
done();
} catch (error) { } catch (error) {
logger.error(`user: ${requestUserId} | Failed to import conversation: `, error); logger.error(`user: ${requestUserId} | Failed to import conversation: `, error);
done(error);
} finally { } finally {
try { try {
await fs.unlink(filepath); await fs.unlink(filepath);
@ -35,7 +29,4 @@ const importConversationJob = async (job, done) => {
} }
}; };
// Call the jobScheduler.define function at startup module.exports = importConversations;
jobScheduler.define(IMPORT_CONVERSATION_JOB_NAME, importConversationJob);
module.exports = { IMPORT_CONVERSATION_JOB_NAME };

View file

@ -1,5 +1,7 @@
const importers = require('./importers'); const importers = require('./importers');
const importConversations = require('./importConversations');
module.exports = { module.exports = {
...importers, ...importers,
importConversations,
}; };

View file

@ -1,99 +0,0 @@
const Agenda = require('agenda');
const { logger } = require('~/config');
const mongodb = require('mongodb');
/**
* Class for scheduling and running jobs.
* The workflow is as follows: start the job scheduler, define a job, and then schedule the job using defined job name.
*/
class JobScheduler {
constructor() {
this.agenda = new Agenda({ db: { address: process.env.MONGO_URI } });
}
/**
* Starts the job scheduler.
*/
async start() {
try {
logger.info('Starting Agenda...');
await this.agenda.start();
logger.info('Agenda successfully started and connected to MongoDB.');
} catch (error) {
logger.error('Failed to start Agenda:', error);
}
}
/**
* Schedules a job to start immediately.
* @param {string} jobName - The name of the job to schedule.
* @param {string} filepath - The filepath to pass to the job.
* @param {string} userId - The ID of the user requesting the job.
* @returns {Promise<{ id: string }>} - A promise that resolves with the ID of the scheduled job.
* @throws {Error} - If the job fails to schedule.
*/
async now(jobName, filepath, userId) {
try {
const job = await this.agenda.now(jobName, { filepath, requestUserId: userId });
logger.debug(`Job '${job.attrs.name}' scheduled successfully.`);
return { id: job.attrs._id.toString() };
} catch (error) {
throw new Error(`Failed to schedule job '${jobName}': ${error}`);
}
}
/**
* Gets the status of a job.
* @param {string} jobId - The ID of the job to get the status of.
* @returns {Promise<{ id: string, userId: string, name: string, failReason: string, status: string } | null>} - A promise that resolves with the job status or null if the job is not found.
* @throws {Error} - If multiple jobs are found.
*/
async getJobStatus(jobId) {
const job = await this.agenda.jobs({ _id: new mongodb.ObjectId(jobId) });
if (!job || job.length === 0) {
return null;
}
if (job.length > 1) {
// This should never happen
throw new Error('Multiple jobs found.');
}
const jobDetails = {
id: job[0]._id,
userId: job[0].attrs.data.requestUserId,
name: job[0].attrs.name,
failReason: job[0].attrs.failReason,
status: !job[0].attrs.lastRunAt
? 'scheduled'
: job[0].attrs.failedAt
? 'failed'
: job[0].attrs.lastFinishedAt
? 'completed'
: 'running',
};
return jobDetails;
}
/**
* Defines a new job.
* @param {string} name - The name of the job.
* @param {Function} jobFunction - The function to run when the job is executed.
*/
define(name, jobFunction) {
this.agenda.define(name, async (job, done) => {
try {
await jobFunction(job, done);
} catch (error) {
logger.error(`Failed to run job '${name}': ${error}`);
done(error);
}
});
}
}
const jobScheduler = new JobScheduler();
jobScheduler.start();
module.exports = jobScheduler;

View file

@ -71,7 +71,7 @@ function ImportConversations() {
<span>{localize('com_ui_import_conversation_info')}</span> <span>{localize('com_ui_import_conversation_info')}</span>
<label <label
htmlFor={'import-conversations-file'} htmlFor={'import-conversations-file'}
className="flex h-auto cursor-pointer items-center rounded bg-transparent px-2 py-3 text-xs font-medium font-normal transition-colors hover:bg-gray-100 hover:text-green-700 dark:bg-transparent dark:text-white dark:hover:bg-gray-600 dark:hover:text-green-500" className="flex h-auto cursor-pointer items-center rounded bg-transparent px-2 py-3 text-xs font-medium transition-colors hover:bg-gray-100 hover:text-green-700 dark:bg-transparent dark:text-white dark:hover:bg-gray-600 dark:hover:text-green-500"
> >
{allowImport ? ( {allowImport ? (
<Import className="mr-1 flex h-4 w-4 items-center stroke-1" /> <Import className="mr-1 flex h-4 w-4 items-center stroke-1" />

View file

@ -344,81 +344,18 @@ export const useForkConvoMutation = (
}; };
export const useUploadConversationsMutation = ( export const useUploadConversationsMutation = (
_options?: t.MutationOptions<t.TImportJobStatus, FormData>, _options?: t.MutationOptions<t.TImportResponse, FormData>,
) => { ) => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const { onSuccess, onError, onMutate } = _options || {}; const { onSuccess, onError, onMutate } = _options || {};
// returns the job status or reason of failure return useMutation<t.TImportResponse, unknown, FormData>({
const checkJobStatus = async (jobId) => {
try {
const response = await dataService.queryImportConversationJobStatus(jobId);
return response;
} catch (error) {
throw new Error('Failed to check job status');
}
};
// Polls the job status until it is completed, failed, or timed out
const pollJobStatus = (jobId, onSuccess, onError) => {
let timeElapsed = 0;
const timeout = 60000; // Timeout after a minute
const pollInterval = 500; // Poll every 500ms
const intervalId = setInterval(async () => {
try {
const statusResponse = await checkJobStatus(jobId);
console.log('Polling job status', statusResponse);
if (statusResponse.status === 'completed' || statusResponse.status === 'failed') {
clearInterval(intervalId);
if (statusResponse.status === 'completed') {
onSuccess && onSuccess(statusResponse);
} else {
onError &&
onError(
new Error(
statusResponse.failReason
? statusResponse.failReason
: 'Failed to import conversations',
),
);
}
}
timeElapsed += pollInterval; // Increment time elapsed by polling interval
if (timeElapsed >= timeout) {
clearInterval(intervalId);
onError && onError(new Error('Polling timed out'));
}
} catch (error) {
clearInterval(intervalId);
onError && onError(error);
}
}, pollInterval);
};
return useMutation<t.TImportStartResponse, unknown, FormData>({
mutationFn: (formData: FormData) => dataService.importConversationsFile(formData), mutationFn: (formData: FormData) => dataService.importConversationsFile(formData),
onSuccess: (data, variables, context) => { onSuccess: (data, variables, context) => {
/* TODO: optimize to return imported conversations and add manually */
queryClient.invalidateQueries([QueryKeys.allConversations]); queryClient.invalidateQueries([QueryKeys.allConversations]);
// Assuming the job ID is in the response data if (onSuccess) {
const jobId = data.jobId; onSuccess(data, variables, context);
if (jobId) {
// Start polling for job status
pollJobStatus(
jobId,
(statusResponse) => {
// This is the final success callback when the job is completed
queryClient.invalidateQueries([QueryKeys.allConversations]); // Optionally refresh conversations query
if (onSuccess) {
onSuccess(statusResponse, variables, context);
}
},
(error) => {
// This is the error callback for job failure or polling errors
if (onError) {
onError(error, variables, context);
}
},
);
} }
}, },
onError: (err, variables, context) => { onError: (err, variables, context) => {

179
package-lock.json generated
View file

@ -49,7 +49,6 @@
"@langchain/community": "^0.0.46", "@langchain/community": "^0.0.46",
"@langchain/google-genai": "^0.0.11", "@langchain/google-genai": "^0.0.11",
"@langchain/google-vertexai": "^0.0.17", "@langchain/google-vertexai": "^0.0.17",
"agenda": "^5.0.0",
"axios": "^1.3.4", "axios": "^1.3.4",
"bcryptjs": "^2.4.3", "bcryptjs": "^2.4.3",
"cheerio": "^1.0.0-rc.12", "cheerio": "^1.0.0-rc.12",
@ -10673,73 +10672,6 @@
"node": ">=0.4.0" "node": ">=0.4.0"
} }
}, },
"node_modules/agenda": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/agenda/-/agenda-5.0.0.tgz",
"integrity": "sha512-jOoa7PvARpst/y2PI8h0wph4NmcjYJ/4wzFhQcHUbNgN+Hte/9h/MzKE0ZmHfIwdsSlnv3rhbBQ3Zd/gwFkThg==",
"dependencies": {
"cron-parser": "^3.5.0",
"date.js": "~0.3.3",
"debug": "~4.3.4",
"human-interval": "~2.0.1",
"moment-timezone": "~0.5.37",
"mongodb": "^4.11.0"
},
"engines": {
"node": ">=12.9.0"
}
},
"node_modules/agenda/node_modules/bson": {
"version": "4.7.2",
"resolved": "https://registry.npmjs.org/bson/-/bson-4.7.2.tgz",
"integrity": "sha512-Ry9wCtIZ5kGqkJoi6aD8KjxFZEx78guTQDnpXWiNthsxzrxAK/i8E6pCHAIZTbaEFWcOCvbecMukfK7XUvyLpQ==",
"dependencies": {
"buffer": "^5.6.0"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/agenda/node_modules/buffer": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"dependencies": {
"base64-js": "^1.3.1",
"ieee754": "^1.1.13"
}
},
"node_modules/agenda/node_modules/mongodb": {
"version": "4.17.2",
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-4.17.2.tgz",
"integrity": "sha512-mLV7SEiov2LHleRJPMPrK2PMyhXFZt2UQLC4VD4pnth3jMjYKHhtqfwwkkvS/NXuo/Fp3vbhaNcXrIDaLRb9Tg==",
"dependencies": {
"bson": "^4.7.2",
"mongodb-connection-string-url": "^2.6.0",
"socks": "^2.7.1"
},
"engines": {
"node": ">=12.9.0"
},
"optionalDependencies": {
"@aws-sdk/credential-providers": "^3.186.0",
"@mongodb-js/saslprep": "^1.1.0"
}
},
"node_modules/agent-base": { "node_modules/agent-base": {
"version": "6.0.2", "version": "6.0.2",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
@ -12909,18 +12841,6 @@
"integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
"dev": true "dev": true
}, },
"node_modules/cron-parser": {
"version": "3.5.0",
"resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-3.5.0.tgz",
"integrity": "sha512-wyVZtbRs6qDfFd8ap457w3XVntdvqcwBGxBoTvJQH9KGVKL/fB+h2k3C8AqiVxvUQKN1Ps/Ns46CNViOpVDhfQ==",
"dependencies": {
"is-nan": "^1.3.2",
"luxon": "^1.26.0"
},
"engines": {
"node": ">=0.8"
}
},
"node_modules/cross-env": { "node_modules/cross-env": {
"version": "7.0.3", "version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz",
@ -13171,27 +13091,6 @@
"url": "https://github.com/sponsors/kossnocorp" "url": "https://github.com/sponsors/kossnocorp"
} }
}, },
"node_modules/date.js": {
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/date.js/-/date.js-0.3.3.tgz",
"integrity": "sha512-HgigOS3h3k6HnW011nAb43c5xx5rBXk8P2v/WIT9Zv4koIaVXiH2BURguI78VVp+5Qc076T7OR378JViCnZtBw==",
"dependencies": {
"debug": "~3.1.0"
}
},
"node_modules/date.js/node_modules/debug": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
"dependencies": {
"ms": "2.0.0"
}
},
"node_modules/date.js/node_modules/ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
},
"node_modules/debug": { "node_modules/debug": {
"version": "4.3.4", "version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
@ -13351,6 +13250,7 @@
"version": "1.2.1", "version": "1.2.1",
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz",
"integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==",
"dev": true,
"dependencies": { "dependencies": {
"define-data-property": "^1.0.1", "define-data-property": "^1.0.1",
"has-property-descriptors": "^1.0.0", "has-property-descriptors": "^1.0.0",
@ -13668,9 +13568,9 @@
"integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
}, },
"node_modules/ejs": { "node_modules/ejs": {
"version": "3.1.9", "version": "3.1.10",
"resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.9.tgz", "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz",
"integrity": "sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ==", "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"jake": "^10.8.5" "jake": "^10.8.5"
@ -16533,14 +16433,6 @@
"node": ">= 6" "node": ">= 6"
} }
}, },
"node_modules/human-interval": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/human-interval/-/human-interval-2.0.1.tgz",
"integrity": "sha512-r4Aotzf+OtKIGQCB3odUowy4GfUDTy3aTWTfLd7ZF2gBCy3XW3v/dJLRefZnOFFnjqs5B1TypvS8WarpBkYUNQ==",
"dependencies": {
"numbered": "^1.1.0"
}
},
"node_modules/human-signals": { "node_modules/human-signals": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
@ -17071,10 +16963,22 @@
"url": "https://opencollective.com/ioredis" "url": "https://opencollective.com/ioredis"
} }
}, },
"node_modules/ip": { "node_modules/ip-address": {
"version": "2.0.1", "version": "9.0.5",
"resolved": "https://registry.npmjs.org/ip/-/ip-2.0.1.tgz", "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz",
"integrity": "sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ==" "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==",
"dependencies": {
"jsbn": "1.1.0",
"sprintf-js": "^1.1.3"
},
"engines": {
"node": ">= 12"
}
},
"node_modules/ip-address/node_modules/sprintf-js": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz",
"integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA=="
}, },
"node_modules/ipaddr.js": { "node_modules/ipaddr.js": {
"version": "1.9.1", "version": "1.9.1",
@ -17350,6 +17254,7 @@
"version": "1.3.2", "version": "1.3.2",
"resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz",
"integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==",
"dev": true,
"dependencies": { "dependencies": {
"call-bind": "^1.0.0", "call-bind": "^1.0.0",
"define-properties": "^1.1.3" "define-properties": "^1.1.3"
@ -18527,6 +18432,11 @@
"js-yaml": "bin/js-yaml.js" "js-yaml": "bin/js-yaml.js"
} }
}, },
"node_modules/jsbn": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz",
"integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A=="
},
"node_modules/jsdom": { "node_modules/jsdom": {
"version": "20.0.3", "version": "20.0.3",
"resolved": "https://registry.npmjs.org/jsdom/-/jsdom-20.0.3.tgz", "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-20.0.3.tgz",
@ -19758,14 +19668,6 @@
"react": "^16.5.1 || ^17.0.0 || ^18.0.0" "react": "^16.5.1 || ^17.0.0 || ^18.0.0"
} }
}, },
"node_modules/luxon": {
"version": "1.28.1",
"resolved": "https://registry.npmjs.org/luxon/-/luxon-1.28.1.tgz",
"integrity": "sha512-gYHAa180mKrNIUJCbwpmD0aTu9kV0dREDrwNnuyFAsO1Wt0EVYSZelPnJlbj9HplzXX/YWXHFTL45kvZ53M0pw==",
"engines": {
"node": "*"
}
},
"node_modules/lz-string": { "node_modules/lz-string": {
"version": "1.5.0", "version": "1.5.0",
"resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz",
@ -20919,17 +20821,6 @@
"node": "*" "node": "*"
} }
}, },
"node_modules/moment-timezone": {
"version": "0.5.45",
"resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.45.tgz",
"integrity": "sha512-HIWmqA86KcmCAhnMAN0wuDOARV/525R2+lOLotuGFzn4HO+FH+/645z2wx0Dt3iDv6/p61SIvKnDstISainhLQ==",
"dependencies": {
"moment": "^2.29.4"
},
"engines": {
"node": "*"
}
},
"node_modules/mongodb": { "node_modules/mongodb": {
"version": "5.9.2", "version": "5.9.2",
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-5.9.2.tgz", "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-5.9.2.tgz",
@ -21577,11 +21468,6 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/numbered": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/numbered/-/numbered-1.1.0.tgz",
"integrity": "sha512-pv/ue2Odr7IfYOO0byC1KgBI10wo5YDauLhxY6/saNzAdAs0r1SotGCPzzCLNPL0xtrAwWRialLu23AAu9xO1g=="
},
"node_modules/nwsapi": { "node_modules/nwsapi": {
"version": "2.2.7", "version": "2.2.7",
"resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.7.tgz", "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.7.tgz",
@ -21637,6 +21523,7 @@
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
"dev": true,
"engines": { "engines": {
"node": ">= 0.4" "node": ">= 0.4"
} }
@ -25849,15 +25736,15 @@
"dev": true "dev": true
}, },
"node_modules/socks": { "node_modules/socks": {
"version": "2.7.1", "version": "2.8.3",
"resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz",
"integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", "integrity": "sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==",
"dependencies": { "dependencies": {
"ip": "^2.0.0", "ip-address": "^9.0.5",
"smart-buffer": "^4.2.0" "smart-buffer": "^4.2.0"
}, },
"engines": { "engines": {
"node": ">= 10.13.0", "node": ">= 10.0.0",
"npm": ">= 3.0.0" "npm": ">= 3.0.0"
} }
}, },
@ -29432,7 +29319,7 @@
}, },
"packages/data-provider": { "packages/data-provider": {
"name": "librechat-data-provider", "name": "librechat-data-provider",
"version": "0.6.6", "version": "0.6.7",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@types/js-yaml": "^4.0.9", "@types/js-yaml": "^4.0.9",

View file

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

View file

@ -47,9 +47,6 @@ export const importConversation = () => `${conversationsRoot}/import`;
export const forkConversation = () => `${conversationsRoot}/fork`; export const forkConversation = () => `${conversationsRoot}/fork`;
export const importConversationJobStatus = (jobId: string) =>
`${conversationsRoot}/import/jobs/${jobId}`;
export const search = (q: string, pageNumber: string) => export const search = (q: string, pageNumber: string) =>
`/api/search?q=${q}&pageNumber=${pageNumber}`; `/api/search?q=${q}&pageNumber=${pageNumber}`;

View file

@ -305,22 +305,10 @@ export const uploadFile = (data: FormData): Promise<f.TFileUpload> => {
* @param data - The FormData containing the file to import. * @param data - The FormData containing the file to import.
* @returns A Promise that resolves to the import start response. * @returns A Promise that resolves to the import start response.
*/ */
export const importConversationsFile = (data: FormData): Promise<t.TImportStartResponse> => { export const importConversationsFile = (data: FormData): Promise<t.TImportResponse> => {
return request.postMultiPart(endpoints.importConversation(), data); return request.postMultiPart(endpoints.importConversation(), data);
}; };
/**
* Retrieves the status of an import conversation job.
*
* @param jobId - The ID of the import conversation job.
* @returns A promise that resolves to the import job status.
*/
export const queryImportConversationJobStatus = async (
jobId: string,
): Promise<t.TImportJobStatus> => {
return request.get(endpoints.importConversationJobStatus(jobId));
};
export const uploadAvatar = (data: FormData): Promise<f.AvatarUploadResponse> => { export const uploadAvatar = (data: FormData): Promise<f.AvatarUploadResponse> => {
return request.postMultiPart(endpoints.avatar(), data); return request.postMultiPart(endpoints.avatar(), data);
}; };

View file

@ -315,39 +315,9 @@ export type TRequestPasswordResetResponse = {
/** /**
* Represents the response from the import endpoint. * Represents the response from the import endpoint.
*/ */
export type TImportStartResponse = { export type TImportResponse = {
/** /**
* The message associated with the response. * The message associated with the response.
*/ */
message: string; message: string;
/**
* The ID of the job associated with the import.
*/
jobId: string;
};
/**
* Represents the status of an import job.
*/
export type TImportJobStatus = {
/**
* The name of the job.
*/
name: string;
/**
* The ID of the job.
*/
id: string;
/**
* The status of the job.
*/
status: 'scheduled' | 'running' | 'completed' | 'failed';
/**
* The reason the job failed, if applicable.
*/
failReason?: string;
}; };