mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-17 17:00:15 +01:00
🚧 WIP: Merge Dev Build (#4611)
* refactor: Agent CodeFiles, abortUpload WIP * feat: code environment file upload * refactor: useLazyEffect * refactor: - Add `watch` from `useFormContext` to check if code execution is enabled - Disable file upload button if `agent_id` is not selected or code execution is disabled * WIP: primeCodeFiles; refactor: rename sessionId to session_id for uniformity * Refactor: Rename session_id to sessionId for uniformity in AuthService.js * chore: bump @librechat/agents to version 1.7.1 * WIP: prime code files * refactor: Update code env file upload method to use read stream * feat: reupload code env file if no longer active * refactor: isAssistantTool -> isEntityTool + address type issues * feat: execute code tool hook * refactor: Rename isPluginAuthenticated to checkPluginAuth in PluginController.js * refactor: Update PluginController.js to use AuthType constant for comparison * feat: verify tool authentication (execute_code) * feat: enter librechat_code_api_key * refactor: Remove unused imports in BookmarkForm.tsx * feat: authenticate code tool * refactor: Update Action.tsx to conditionally render the key and revoke key buttons * refactor(Code/Action): prevent uncheck-able 'Run Code' capability when key is revoked * refactor(Code/Action): Update Action.tsx to conditionally render the key and revoke key buttons * fix: agent file upload edge cases * chore: bump @librechat/agents * fix: custom endpoint providerValue icon * feat: ollama meta modal token values + context * feat: ollama agents * refactor: Update token models for Ollama models * chore: Comment out CodeForm * refactor: Update token models for Ollama and Meta models
This commit is contained in:
parent
1909efd6ba
commit
95011ce349
58 changed files with 1418 additions and 1002 deletions
22
api/server/routes/agents/tools.js
Normal file
22
api/server/routes/agents/tools.js
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
const express = require('express');
|
||||
const { getAvailableTools } = require('~/server/controllers/PluginController');
|
||||
const { verifyToolAuth } = require('~/server/controllers/tools');
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
/**
|
||||
* Get a list of available tools for agents.
|
||||
* @route GET /agents/tools
|
||||
* @returns {TPlugin[]} 200 - application/json
|
||||
*/
|
||||
router.get('/', getAvailableTools);
|
||||
|
||||
/**
|
||||
* Verify authentication for a specific tool
|
||||
* @route GET /agents/tools/:toolId/auth
|
||||
* @param {string} toolId - The ID of the tool to verify
|
||||
* @returns {{ authenticated?: boolean; message?: string }}
|
||||
*/
|
||||
router.get('/:toolId/auth', verifyToolAuth);
|
||||
|
||||
module.exports = router;
|
||||
|
|
@ -2,9 +2,9 @@ const multer = require('multer');
|
|||
const express = require('express');
|
||||
const { PermissionTypes, Permissions } = require('librechat-data-provider');
|
||||
const { requireJwtAuth, generateCheckAccess } = require('~/server/middleware');
|
||||
const { getAvailableTools } = require('~/server/controllers/PluginController');
|
||||
const v1 = require('~/server/controllers/agents/v1');
|
||||
const actions = require('./actions');
|
||||
const tools = require('./tools');
|
||||
|
||||
const upload = multer();
|
||||
const router = express.Router();
|
||||
|
|
@ -35,9 +35,8 @@ router.use('/actions', actions);
|
|||
/**
|
||||
* Get a list of available tools for agents.
|
||||
* @route GET /agents/tools
|
||||
* @returns {TPlugin[]} 200 - application/json
|
||||
*/
|
||||
router.use('/tools', getAvailableTools);
|
||||
router.use('/tools', tools);
|
||||
|
||||
/**
|
||||
* Creates an agent.
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ const {
|
|||
const { getStrategyFunctions } = require('~/server/services/Files/strategies');
|
||||
const { getOpenAIClient } = require('~/server/controllers/assistants/helpers');
|
||||
const { loadAuthValues } = require('~/app/clients/tools/util');
|
||||
const { getAgent } = require('~/models/Agent');
|
||||
const { getFiles } = require('~/models/File');
|
||||
const { logger } = require('~/config');
|
||||
|
||||
|
|
@ -67,12 +68,31 @@ router.delete('/', async (req, res) => {
|
|||
}
|
||||
|
||||
const fileIds = files.map((file) => file.file_id);
|
||||
const userFiles = await getFiles({ file_id: { $in: fileIds }, user: req.user.id });
|
||||
if (userFiles.length !== files.length) {
|
||||
return res.status(403).json({ message: 'You can only delete your own files' });
|
||||
const dbFiles = await getFiles({ file_id: { $in: fileIds } });
|
||||
const unauthorizedFiles = dbFiles.filter((file) => file.user.toString() !== req.user.id);
|
||||
|
||||
if (unauthorizedFiles.length > 0) {
|
||||
return res.status(403).json({
|
||||
message: 'You can only delete your own files',
|
||||
unauthorizedFiles: unauthorizedFiles.map((f) => f.file_id),
|
||||
});
|
||||
}
|
||||
|
||||
await processDeleteRequest({ req, files: userFiles });
|
||||
/* Handle entity unlinking even if no valid files to delete */
|
||||
if (req.body.agent_id && req.body.tool_resource && dbFiles.length === 0) {
|
||||
const agent = await getAgent({
|
||||
id: req.body.agent_id,
|
||||
});
|
||||
|
||||
const toolResourceFiles = agent.tool_resources?.[req.body.tool_resource]?.file_ids ?? [];
|
||||
const agentFiles = files.filter((f) => toolResourceFiles.includes(f.file_id));
|
||||
|
||||
await processDeleteRequest({ req, files: agentFiles });
|
||||
res.status(200).json({ message: 'File associations removed successfully' });
|
||||
return;
|
||||
}
|
||||
|
||||
await processDeleteRequest({ req, files: dbFiles });
|
||||
|
||||
logger.debug(
|
||||
`[/files] Files deleted successfully: ${files
|
||||
|
|
@ -87,13 +107,13 @@ router.delete('/', async (req, res) => {
|
|||
}
|
||||
});
|
||||
|
||||
router.get('/code/download/:sessionId/:fileId', async (req, res) => {
|
||||
router.get('/code/download/:session_id/:fileId', async (req, res) => {
|
||||
try {
|
||||
const { sessionId, fileId } = req.params;
|
||||
const logPrefix = `Session ID: ${sessionId} | File ID: ${fileId} | Code output download requested by user `;
|
||||
const { session_id, fileId } = req.params;
|
||||
const logPrefix = `Session ID: ${session_id} | File ID: ${fileId} | Code output download requested by user `;
|
||||
logger.debug(logPrefix);
|
||||
|
||||
if (!sessionId || !fileId) {
|
||||
if (!session_id || !fileId) {
|
||||
return res.status(400).send('Bad request');
|
||||
}
|
||||
|
||||
|
|
@ -108,7 +128,10 @@ router.get('/code/download/:sessionId/:fileId', async (req, res) => {
|
|||
const result = await loadAuthValues({ userId: req.user.id, authFields: [EnvVar.CODE_API_KEY] });
|
||||
|
||||
/** @type {AxiosResponse<ReadableStream> | undefined} */
|
||||
const response = await getDownloadStream(`${sessionId}/${fileId}`, result[EnvVar.CODE_API_KEY]);
|
||||
const response = await getDownloadStream(
|
||||
`${session_id}/${fileId}`,
|
||||
result[EnvVar.CODE_API_KEY],
|
||||
);
|
||||
res.set(response.headers);
|
||||
response.data.pipe(res);
|
||||
} catch (error) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue