From 9b0678da1656ea0dc8e8a97b2dd8a09dc58326ce Mon Sep 17 00:00:00 2001 From: Danny Avila Date: Sun, 6 Apr 2025 03:28:05 -0400 Subject: [PATCH 1/8] =?UTF-8?q?=E2=9A=99=EF=B8=8F=20refactor:=20OAuth=20Fl?= =?UTF-8?q?ow=20Signal,=20Type=20Safety,=20Tool=20Progress=20&=20Updated?= =?UTF-8?q?=20Packages=20(#6752)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: bump @librechat/agents and related packages * refactor: update message state for tool calls run step, in case no tool call chunks are received * fix: avoid combining finalized args createContentAggregator for tool calls * chore: bump @librechat/agents to version 2.3.99 * feat: add support for aborting flows with AbortSignal in createFlow methods * fix: improve handling of tool call arguments in useStepHandler * chore: bump @librechat/agents to version 2.4.0 * fix: update flow identifier format for OAuth login in createActionTool to allow uniqueness per run * fix: improve error message handling for aborted flows in FlowStateManager * refactor: allow possible multi-agent cross-over for oauth login * fix: add type safety for Sandpack files in ArtifactCodeEditor --- api/package.json | 10 +- api/server/services/ActionService.js | 27 +- .../Artifacts/ArtifactCodeEditor.tsx | 5 +- client/src/hooks/SSE/useStepHandler.ts | 34 +- package-lock.json | 1823 ++++++++--------- packages/mcp/src/flow/manager.ts | 35 +- 6 files changed, 953 insertions(+), 981 deletions(-) diff --git a/api/package.json b/api/package.json index 2a2c8be6de..644c0ce7a9 100644 --- a/api/package.json +++ b/api/package.json @@ -44,12 +44,12 @@ "@googleapis/youtube": "^20.0.0", "@keyv/mongo": "^2.1.8", "@keyv/redis": "^2.8.1", - "@langchain/community": "^0.3.34", - "@langchain/core": "^0.3.40", - "@langchain/google-genai": "^0.1.11", - "@langchain/google-vertexai": "^0.2.2", + "@langchain/community": "^0.3.39", + "@langchain/core": "^0.3.43", + "@langchain/google-genai": "^0.2.2", + "@langchain/google-vertexai": "^0.2.3", "@langchain/textsplitters": "^0.1.0", - "@librechat/agents": "^2.3.95", + "@librechat/agents": "^2.4.0", "@librechat/data-schemas": "*", "@waylaidwanderer/fetch-event-source": "^3.0.1", "axios": "^1.8.2", diff --git a/api/server/services/ActionService.js b/api/server/services/ActionService.js index 03157f7ad6..0dc8070f1a 100644 --- a/api/server/services/ActionService.js +++ b/api/server/services/ActionService.js @@ -191,24 +191,30 @@ async function createActionTool({ }; const flowManager = await getFlowStateManager(getLogStores); await flowManager.createFlowWithHandler( - `${identifier}:login`, + `${identifier}:oauth_login:${config.metadata.thread_id}:${config.metadata.run_id}`, 'oauth_login', async () => { sendEvent(res, { event: GraphEvents.ON_RUN_STEP_DELTA, data }); logger.debug('Sent OAuth login request to client', { action_id, identifier }); return true; }, + config?.signal, ); logger.debug('Waiting for OAuth Authorization response', { action_id, identifier }); - const result = await flowManager.createFlow(identifier, 'oauth', { - state: stateToken, - userId: req.user.id, - client_url: metadata.auth.client_url, - redirect_uri: `${process.env.DOMAIN_CLIENT}/api/actions/${action_id}/oauth/callback`, - /** Encrypted values */ - encrypted_oauth_client_id: encrypted.oauth_client_id, - encrypted_oauth_client_secret: encrypted.oauth_client_secret, - }); + const result = await flowManager.createFlow( + identifier, + 'oauth', + { + state: stateToken, + userId: req.user.id, + client_url: metadata.auth.client_url, + redirect_uri: `${process.env.DOMAIN_CLIENT}/api/actions/${action_id}/oauth/callback`, + /** Encrypted values */ + encrypted_oauth_client_id: encrypted.oauth_client_id, + encrypted_oauth_client_secret: encrypted.oauth_client_secret, + }, + config?.signal, + ); logger.debug('Received OAuth Authorization response', { action_id, identifier }); data.delta.auth = undefined; data.delta.expires_at = undefined; @@ -264,6 +270,7 @@ async function createActionTool({ `${identifier}:refresh`, 'oauth_refresh', refreshTokens, + config?.signal, ); metadata.oauth_access_token = refreshData.access_token; if (refreshData.refresh_token) { diff --git a/client/src/components/Artifacts/ArtifactCodeEditor.tsx b/client/src/components/Artifacts/ArtifactCodeEditor.tsx index af0f7bdc8e..c0b62c2916 100644 --- a/client/src/components/Artifacts/ArtifactCodeEditor.tsx +++ b/client/src/components/Artifacts/ArtifactCodeEditor.tsx @@ -5,7 +5,8 @@ import { SandpackCodeEditor, SandpackProvider as StyledProvider, } from '@codesandbox/sandpack-react'; -import { SandpackProviderProps } from '@codesandbox/sandpack-react/unstyled'; +import type { SandpackProviderProps } from '@codesandbox/sandpack-react/unstyled'; +import type { SandpackBundlerFile } from '@codesandbox/sandpack-client'; import type { CodeEditorRef } from '@codesandbox/sandpack-react'; import type { ArtifactFiles, Artifact } from '~/common'; import { useEditArtifact, useGetStartupConfig } from '~/data-provider'; @@ -66,7 +67,7 @@ const CodeEditor = ({ return; } - const currentCode = sandpack.files['/' + fileKey].code; + const currentCode = (sandpack.files['/' + fileKey] as SandpackBundlerFile | undefined)?.code; if (currentCode && artifact.content != null && currentCode.trim() !== artifact.content.trim()) { setCurrentCode(currentCode); diff --git a/client/src/hooks/SSE/useStepHandler.ts b/client/src/hooks/SSE/useStepHandler.ts index b54617d0bb..ec4d797627 100644 --- a/client/src/hooks/SSE/useStepHandler.ts +++ b/client/src/hooks/SSE/useStepHandler.ts @@ -123,11 +123,14 @@ export default function useStepHandler({ } else if (contentType === ContentTypes.TOOL_CALL && 'tool_call' in contentPart) { const existingContent = updatedContent[index] as Agents.ToolCallContent | undefined; const existingToolCall = existingContent?.tool_call; - const toolCallArgs = (contentPart.tool_call.args as unknown as string | undefined) ?? ''; - - const args = finalUpdate - ? contentPart.tool_call.args - : (existingToolCall?.args ?? '') + toolCallArgs; + const toolCallArgs = (contentPart.tool_call as Agents.ToolCall).args; + /** When args are a valid object, they are likely already invoked */ + const args = + finalUpdate || + typeof existingToolCall?.args === 'object' || + typeof toolCallArgs === 'object' + ? contentPart.tool_call.args + : (existingToolCall?.args ?? '') + (toolCallArgs ?? ''); const id = getNonEmptyValue([contentPart.tool_call.id, existingToolCall?.id]) ?? ''; const name = getNonEmptyValue([contentPart.tool_call.name, existingToolCall?.name]) ?? ''; @@ -195,12 +198,31 @@ export default function useStepHandler({ // Store tool call IDs if present if (runStep.stepDetails.type === StepTypes.TOOL_CALLS) { - runStep.stepDetails.tool_calls.forEach((toolCall) => { + let updatedResponse = { ...response }; + (runStep.stepDetails.tool_calls as Agents.ToolCall[]).forEach((toolCall) => { const toolCallId = toolCall.id ?? ''; if ('id' in toolCall && toolCallId) { toolCallIdMap.current.set(runStep.id, toolCallId); } + + const contentPart: Agents.MessageContentComplex = { + type: ContentTypes.TOOL_CALL, + tool_call: { + name: toolCall.name ?? '', + args: toolCall.args, + id: toolCallId, + }, + }; + + updatedResponse = updateContent(updatedResponse, runStep.index, contentPart); }); + + messageMap.current.set(responseMessageId, updatedResponse); + const updatedMessages = messages.map((msg) => + msg.messageId === runStep.runId ? updatedResponse : msg, + ); + + setMessages(updatedMessages); } } else if (event === 'on_agent_update') { const { agent_update } = data as Agents.AgentUpdate; diff --git a/package-lock.json b/package-lock.json index b31e67aeda..88f008db61 100644 --- a/package-lock.json +++ b/package-lock.json @@ -60,12 +60,12 @@ "@googleapis/youtube": "^20.0.0", "@keyv/mongo": "^2.1.8", "@keyv/redis": "^2.8.1", - "@langchain/community": "^0.3.34", - "@langchain/core": "^0.3.40", - "@langchain/google-genai": "^0.1.11", - "@langchain/google-vertexai": "^0.2.2", + "@langchain/community": "^0.3.39", + "@langchain/core": "^0.3.43", + "@langchain/google-genai": "^0.2.2", + "@langchain/google-vertexai": "^0.2.3", "@langchain/textsplitters": "^0.1.0", - "@librechat/agents": "^2.3.95", + "@librechat/agents": "^2.4.0", "@librechat/data-schemas": "*", "@waylaidwanderer/fetch-event-source": "^3.0.1", "axios": "^1.8.2", @@ -159,555 +159,11 @@ } }, "api/node_modules/@langchain/community": { - "version": "0.3.34", - "resolved": "https://registry.npmjs.org/@langchain/community/-/community-0.3.34.tgz", - "integrity": "sha512-s0KVulgVIPd90s3m6XZtWrCRGQPWsY93uY62seFMmNhzcyF+I65kKnN04Nbiouthrn/YJ9HB4hW8MJAFuX6RRg==", + "version": "0.3.39", + "resolved": "https://registry.npmjs.org/@langchain/community/-/community-0.3.39.tgz", + "integrity": "sha512-8sMJD22bUNlQVoh0b8PgRSpO2Hz5zO6BuZeNY3ElgW3cNVXCoywHW7FBmqbwrygGocJQDee76RqiIN0XQunhTg==", "dependencies": { - "@langchain/openai": ">=0.2.0 <0.5.0", - "binary-extensions": "^2.2.0", - "expr-eval": "^2.0.2", - "flat": "^5.0.2", - "js-yaml": "^4.1.0", - "langchain": ">=0.2.3 <0.3.0 || >=0.3.4 <0.4.0", - "langsmith": ">=0.2.8 <0.4.0", - "uuid": "^10.0.0", - "zod": "^3.22.3", - "zod-to-json-schema": "^3.22.5" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@arcjet/redact": "^v1.0.0-alpha.23", - "@aws-crypto/sha256-js": "^5.0.0", - "@aws-sdk/client-bedrock-agent-runtime": "^3.749.0", - "@aws-sdk/client-bedrock-runtime": "^3.749.0", - "@aws-sdk/client-dynamodb": "^3.749.0", - "@aws-sdk/client-kendra": "^3.749.0", - "@aws-sdk/client-lambda": "^3.749.0", - "@aws-sdk/client-s3": "^3.749.0", - "@aws-sdk/client-sagemaker-runtime": "^3.749.0", - "@aws-sdk/client-sfn": "^3.749.0", - "@aws-sdk/credential-provider-node": "^3.388.0", - "@azure/search-documents": "^12.0.0", - "@azure/storage-blob": "^12.15.0", - "@browserbasehq/sdk": "*", - "@browserbasehq/stagehand": "^1.0.0", - "@clickhouse/client": "^0.2.5", - "@cloudflare/ai": "*", - "@datastax/astra-db-ts": "^1.0.0", - "@elastic/elasticsearch": "^8.4.0", - "@getmetal/metal-sdk": "*", - "@getzep/zep-cloud": "^1.0.6", - "@getzep/zep-js": "^0.9.0", - "@gomomento/sdk": "^1.51.1", - "@gomomento/sdk-core": "^1.51.1", - "@google-ai/generativelanguage": "*", - "@google-cloud/storage": "^6.10.1 || ^7.7.0", - "@gradientai/nodejs-sdk": "^1.2.0", - "@huggingface/inference": "^2.6.4", - "@huggingface/transformers": "^3.2.3", - "@ibm-cloud/watsonx-ai": "*", - "@lancedb/lancedb": "^0.12.0", - "@langchain/core": ">=0.2.21 <0.4.0", - "@layerup/layerup-security": "^1.5.12", - "@libsql/client": "^0.14.0", - "@mendable/firecrawl-js": "^1.4.3", - "@mlc-ai/web-llm": "*", - "@mozilla/readability": "*", - "@neondatabase/serverless": "*", - "@notionhq/client": "^2.2.10", - "@opensearch-project/opensearch": "*", - "@pinecone-database/pinecone": "*", - "@planetscale/database": "^1.8.0", - "@premai/prem-sdk": "^0.3.25", - "@qdrant/js-client-rest": "^1.8.2", - "@raycast/api": "^1.55.2", - "@rockset/client": "^0.9.1", - "@smithy/eventstream-codec": "^2.0.5", - "@smithy/protocol-http": "^3.0.6", - "@smithy/signature-v4": "^2.0.10", - "@smithy/util-utf8": "^2.0.0", - "@spider-cloud/spider-client": "^0.0.21", - "@supabase/supabase-js": "^2.45.0", - "@tensorflow-models/universal-sentence-encoder": "*", - "@tensorflow/tfjs-converter": "*", - "@tensorflow/tfjs-core": "*", - "@upstash/ratelimit": "^1.1.3 || ^2.0.3", - "@upstash/redis": "^1.20.6", - "@upstash/vector": "^1.1.1", - "@vercel/kv": "*", - "@vercel/postgres": "*", - "@writerai/writer-sdk": "^0.40.2", - "@xata.io/client": "^0.28.0", - "@zilliz/milvus2-sdk-node": ">=2.3.5", - "apify-client": "^2.7.1", - "assemblyai": "^4.6.0", - "better-sqlite3": ">=9.4.0 <12.0.0", - "cassandra-driver": "^4.7.2", - "cborg": "^4.1.1", - "cheerio": "^1.0.0-rc.12", - "chromadb": "*", - "closevector-common": "0.1.3", - "closevector-node": "0.1.6", - "closevector-web": "0.1.6", - "cohere-ai": "*", - "convex": "^1.3.1", - "crypto-js": "^4.2.0", - "d3-dsv": "^2.0.0", - "discord.js": "^14.14.1", - "dria": "^0.0.3", - "duck-duck-scrape": "^2.2.5", - "epub2": "^3.0.1", - "fast-xml-parser": "*", - "firebase-admin": "^11.9.0 || ^12.0.0", - "google-auth-library": "*", - "googleapis": "*", - "hnswlib-node": "^3.0.0", - "html-to-text": "^9.0.5", - "ibm-cloud-sdk-core": "*", - "ignore": "^5.2.0", - "interface-datastore": "^8.2.11", - "ioredis": "^5.3.2", - "it-all": "^3.0.4", - "jsdom": "*", - "jsonwebtoken": "^9.0.2", - "llmonitor": "^0.5.9", - "lodash": "^4.17.21", - "lunary": "^0.7.10", - "mammoth": "^1.6.0", - "mongodb": ">=5.2.0", - "mysql2": "^3.9.8", - "neo4j-driver": "*", - "notion-to-md": "^3.1.0", - "officeparser": "^4.0.4", - "openai": "*", - "pdf-parse": "1.1.1", - "pg": "^8.11.0", - "pg-copy-streams": "^6.0.5", - "pickleparser": "^0.2.1", - "playwright": "^1.32.1", - "portkey-ai": "^0.1.11", - "puppeteer": "*", - "pyodide": ">=0.24.1 <0.27.0", - "redis": "*", - "replicate": "*", - "sonix-speech-recognition": "^2.1.1", - "srt-parser-2": "^1.2.3", - "typeorm": "^0.3.20", - "typesense": "^1.5.3", - "usearch": "^1.1.1", - "voy-search": "0.6.2", - "weaviate-ts-client": "*", - "web-auth-library": "^1.0.3", - "word-extractor": "*", - "ws": "^8.14.2", - "youtubei.js": "*" - }, - "peerDependenciesMeta": { - "@arcjet/redact": { - "optional": true - }, - "@aws-crypto/sha256-js": { - "optional": true - }, - "@aws-sdk/client-bedrock-agent-runtime": { - "optional": true - }, - "@aws-sdk/client-bedrock-runtime": { - "optional": true - }, - "@aws-sdk/client-dynamodb": { - "optional": true - }, - "@aws-sdk/client-kendra": { - "optional": true - }, - "@aws-sdk/client-lambda": { - "optional": true - }, - "@aws-sdk/client-s3": { - "optional": true - }, - "@aws-sdk/client-sagemaker-runtime": { - "optional": true - }, - "@aws-sdk/client-sfn": { - "optional": true - }, - "@aws-sdk/credential-provider-node": { - "optional": true - }, - "@aws-sdk/dsql-signer": { - "optional": true - }, - "@azure/search-documents": { - "optional": true - }, - "@azure/storage-blob": { - "optional": true - }, - "@browserbasehq/sdk": { - "optional": true - }, - "@clickhouse/client": { - "optional": true - }, - "@cloudflare/ai": { - "optional": true - }, - "@datastax/astra-db-ts": { - "optional": true - }, - "@elastic/elasticsearch": { - "optional": true - }, - "@getmetal/metal-sdk": { - "optional": true - }, - "@getzep/zep-cloud": { - "optional": true - }, - "@getzep/zep-js": { - "optional": true - }, - "@gomomento/sdk": { - "optional": true - }, - "@gomomento/sdk-core": { - "optional": true - }, - "@google-ai/generativelanguage": { - "optional": true - }, - "@google-cloud/storage": { - "optional": true - }, - "@gradientai/nodejs-sdk": { - "optional": true - }, - "@huggingface/inference": { - "optional": true - }, - "@huggingface/transformers": { - "optional": true - }, - "@lancedb/lancedb": { - "optional": true - }, - "@layerup/layerup-security": { - "optional": true - }, - "@libsql/client": { - "optional": true - }, - "@mendable/firecrawl-js": { - "optional": true - }, - "@mlc-ai/web-llm": { - "optional": true - }, - "@mozilla/readability": { - "optional": true - }, - "@neondatabase/serverless": { - "optional": true - }, - "@notionhq/client": { - "optional": true - }, - "@opensearch-project/opensearch": { - "optional": true - }, - "@pinecone-database/pinecone": { - "optional": true - }, - "@planetscale/database": { - "optional": true - }, - "@premai/prem-sdk": { - "optional": true - }, - "@qdrant/js-client-rest": { - "optional": true - }, - "@raycast/api": { - "optional": true - }, - "@rockset/client": { - "optional": true - }, - "@smithy/eventstream-codec": { - "optional": true - }, - "@smithy/protocol-http": { - "optional": true - }, - "@smithy/signature-v4": { - "optional": true - }, - "@smithy/util-utf8": { - "optional": true - }, - "@spider-cloud/spider-client": { - "optional": true - }, - "@supabase/supabase-js": { - "optional": true - }, - "@tensorflow-models/universal-sentence-encoder": { - "optional": true - }, - "@tensorflow/tfjs-converter": { - "optional": true - }, - "@tensorflow/tfjs-core": { - "optional": true - }, - "@upstash/ratelimit": { - "optional": true - }, - "@upstash/redis": { - "optional": true - }, - "@upstash/vector": { - "optional": true - }, - "@vercel/kv": { - "optional": true - }, - "@vercel/postgres": { - "optional": true - }, - "@writerai/writer-sdk": { - "optional": true - }, - "@xata.io/client": { - "optional": true - }, - "@zilliz/milvus2-sdk-node": { - "optional": true - }, - "apify-client": { - "optional": true - }, - "assemblyai": { - "optional": true - }, - "better-sqlite3": { - "optional": true - }, - "cassandra-driver": { - "optional": true - }, - "cborg": { - "optional": true - }, - "cheerio": { - "optional": true - }, - "chromadb": { - "optional": true - }, - "closevector-common": { - "optional": true - }, - "closevector-node": { - "optional": true - }, - "closevector-web": { - "optional": true - }, - "cohere-ai": { - "optional": true - }, - "convex": { - "optional": true - }, - "crypto-js": { - "optional": true - }, - "d3-dsv": { - "optional": true - }, - "discord.js": { - "optional": true - }, - "dria": { - "optional": true - }, - "duck-duck-scrape": { - "optional": true - }, - "epub2": { - "optional": true - }, - "fast-xml-parser": { - "optional": true - }, - "firebase-admin": { - "optional": true - }, - "google-auth-library": { - "optional": true - }, - "googleapis": { - "optional": true - }, - "hnswlib-node": { - "optional": true - }, - "html-to-text": { - "optional": true - }, - "ignore": { - "optional": true - }, - "interface-datastore": { - "optional": true - }, - "ioredis": { - "optional": true - }, - "it-all": { - "optional": true - }, - "jsdom": { - "optional": true - }, - "jsonwebtoken": { - "optional": true - }, - "llmonitor": { - "optional": true - }, - "lodash": { - "optional": true - }, - "lunary": { - "optional": true - }, - "mammoth": { - "optional": true - }, - "mongodb": { - "optional": true - }, - "mysql2": { - "optional": true - }, - "neo4j-driver": { - "optional": true - }, - "notion-to-md": { - "optional": true - }, - "officeparser": { - "optional": true - }, - "pdf-parse": { - "optional": true - }, - "pg": { - "optional": true - }, - "pg-copy-streams": { - "optional": true - }, - "pickleparser": { - "optional": true - }, - "playwright": { - "optional": true - }, - "portkey-ai": { - "optional": true - }, - "puppeteer": { - "optional": true - }, - "pyodide": { - "optional": true - }, - "redis": { - "optional": true - }, - "replicate": { - "optional": true - }, - "sonix-speech-recognition": { - "optional": true - }, - "srt-parser-2": { - "optional": true - }, - "typeorm": { - "optional": true - }, - "typesense": { - "optional": true - }, - "usearch": { - "optional": true - }, - "voy-search": { - "optional": true - }, - "weaviate-ts-client": { - "optional": true - }, - "web-auth-library": { - "optional": true - }, - "word-extractor": { - "optional": true - }, - "ws": { - "optional": true - }, - "youtubei.js": { - "optional": true - } - } - }, - "api/node_modules/@librechat/agents": { - "version": "2.3.95", - "resolved": "https://registry.npmjs.org/@librechat/agents/-/agents-2.3.95.tgz", - "integrity": "sha512-+yLo1HVKqh99sGdOSJN4ruYYvzXlIqr+EtVHUkcinRe6UyVYEw10yWWF2q7gHY75nC7RekycU+TxGVD6M/VaxA==", - "dependencies": { - "@aws-crypto/sha256-js": "^5.2.0", - "@aws-sdk/credential-provider-node": "^3.613.0", - "@aws-sdk/types": "^3.609.0", - "@langchain/anthropic": "^0.3.14", - "@langchain/aws": "^0.1.7", - "@langchain/community": "^0.3.35", - "@langchain/core": "^0.3.40", - "@langchain/deepseek": "^0.0.1", - "@langchain/google-genai": "^0.1.11", - "@langchain/google-vertexai": "^0.2.2", - "@langchain/langgraph": "^0.2.49", - "@langchain/mistralai": "^0.0.26", - "@langchain/ollama": "^0.1.5", - "@langchain/openai": "^0.4.2", - "@langchain/xai": "^0.0.2", - "@smithy/eventstream-codec": "^2.2.0", - "@smithy/protocol-http": "^3.0.6", - "@smithy/signature-v4": "^2.0.10", - "@smithy/util-utf8": "^2.0.0", - "dotenv": "^16.4.7", - "https-proxy-agent": "^7.0.6", - "nanoid": "^3.3.7" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "api/node_modules/@librechat/agents/node_modules/@langchain/community": { - "version": "0.3.37", - "resolved": "https://registry.npmjs.org/@langchain/community/-/community-0.3.37.tgz", - "integrity": "sha512-Ifug3Gc6JHOFNWr0bxT1ie0AUKn3hWkZ4PG+EGqVz8MyeNr68lOhchY4oj51pQCC65KryfZ5CPhXrvbd5Il1GQ==", - "dependencies": { - "@langchain/openai": ">=0.2.0 <0.5.0", + "@langchain/openai": ">=0.2.0 <0.6.0", "binary-extensions": "^2.2.0", "expr-eval": "^2.0.2", "flat": "^5.0.2", @@ -787,6 +243,7 @@ "@zilliz/milvus2-sdk-node": ">=2.3.5", "apify-client": "^2.7.1", "assemblyai": "^4.6.0", + "azion": "^1.11.1", "better-sqlite3": ">=9.4.0 <12.0.0", "cassandra-driver": "^4.7.2", "cborg": "^4.1.1", @@ -1040,6 +497,9 @@ "assemblyai": { "optional": true }, + "azion": { + "optional": true + }, "better-sqlite3": { "optional": true }, @@ -1222,6 +682,23 @@ } } }, + "api/node_modules/@langchain/openai": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/@langchain/openai/-/openai-0.5.4.tgz", + "integrity": "sha512-fBIEgaAMs1OHHjSuOwtonhtFTlRyFETAS9y/4SZxlXV5lLdwEU5OAbfaBTcCR0A58rrlmgt8iPnm2IWn4Onjjw==", + "dependencies": { + "js-tiktoken": "^1.0.12", + "openai": "^4.87.3", + "zod": "^3.22.4", + "zod-to-json-schema": "^3.22.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@langchain/core": ">=0.3.39 <0.4.0" + } + }, "api/node_modules/@types/node": { "version": "18.19.14", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.14.tgz", @@ -3950,6 +3427,8 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-3.0.0.tgz", "integrity": "sha512-IzSgsrxUcsrejQbPVilIKy16kAT52EwB6zSaI+M3xxIhKh5+aldEyvI+z6erM7TCLB2BJsFrtHjp6/4/sr+3dA==", + "optional": true, + "peer": true, "dependencies": { "@aws-crypto/util": "^3.0.0", "@aws-sdk/types": "^3.222.0", @@ -3959,7 +3438,9 @@ "node_modules/@aws-crypto/crc32/node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "optional": true, + "peer": true }, "node_modules/@aws-crypto/crc32c": { "version": "5.2.0", @@ -4067,6 +3548,8 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-3.0.0.tgz", "integrity": "sha512-2OJlpeJpCR48CC8r+uKVChzs9Iungj9wkZrl8Z041DWEWvyIHILYKCPNzJghKsivj+S3mLo6BVc7mBNzdxA46w==", + "optional": true, + "peer": true, "dependencies": { "@aws-sdk/types": "^3.222.0", "@aws-sdk/util-utf8-browser": "^3.0.0", @@ -4076,7 +3559,9 @@ "node_modules/@aws-crypto/util/node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "optional": true, + "peer": true }, "node_modules/@aws-sdk/client-bedrock-agent-runtime": { "version": "3.758.0", @@ -7267,55 +6752,6 @@ "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/nested-clients": { - "version": "3.758.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.758.0.tgz", - "integrity": "sha512-YZ5s7PSvyF3Mt2h1EQulCG93uybprNGbBkPmVuy/HMMfbFTt4iL3SbKjxqvOZelm86epFfj7pvK7FliI2WOEcg==", - "license": "Apache-2.0", - "dependencies": { - "@aws-crypto/sha256-browser": "5.2.0", - "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.758.0", - "@aws-sdk/middleware-host-header": "3.734.0", - "@aws-sdk/middleware-logger": "3.734.0", - "@aws-sdk/middleware-recursion-detection": "3.734.0", - "@aws-sdk/middleware-user-agent": "3.758.0", - "@aws-sdk/region-config-resolver": "3.734.0", - "@aws-sdk/types": "3.734.0", - "@aws-sdk/util-endpoints": "3.743.0", - "@aws-sdk/util-user-agent-browser": "3.734.0", - "@aws-sdk/util-user-agent-node": "3.758.0", - "@smithy/config-resolver": "^4.0.1", - "@smithy/core": "^3.1.5", - "@smithy/fetch-http-handler": "^5.0.1", - "@smithy/hash-node": "^4.0.1", - "@smithy/invalid-dependency": "^4.0.1", - "@smithy/middleware-content-length": "^4.0.1", - "@smithy/middleware-endpoint": "^4.0.6", - "@smithy/middleware-retry": "^4.0.7", - "@smithy/middleware-serde": "^4.0.2", - "@smithy/middleware-stack": "^4.0.1", - "@smithy/node-config-provider": "^4.0.1", - "@smithy/node-http-handler": "^4.0.3", - "@smithy/protocol-http": "^5.0.1", - "@smithy/smithy-client": "^4.1.6", - "@smithy/types": "^4.1.0", - "@smithy/url-parser": "^4.0.1", - "@smithy/util-base64": "^4.0.0", - "@smithy/util-body-length-browser": "^4.0.0", - "@smithy/util-body-length-node": "^4.0.0", - "@smithy/util-defaults-mode-browser": "^4.0.7", - "@smithy/util-defaults-mode-node": "^4.0.7", - "@smithy/util-endpoints": "^3.0.1", - "@smithy/util-middleware": "^4.0.1", - "@smithy/util-retry": "^4.0.1", - "@smithy/util-utf8": "^4.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@aws-sdk/client-s3/node_modules/@aws-sdk/region-config-resolver": { "version": "3.734.0", "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.734.0.tgz", @@ -7759,18 +7195,6 @@ "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/client-s3/node_modules/@smithy/types": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.1.0.tgz", - "integrity": "sha512-enhjdwp4D7CXmwLtD6zbcDMbo6/T6WtuuKCY49Xxc6OMOmUWlBEBDREsxxgV2LIdeQPW756+f97GzcgAwp3iLw==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@aws-sdk/client-s3/node_modules/@smithy/url-parser": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-4.0.1.tgz", @@ -7908,19 +7332,6 @@ "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/client-s3/node_modules/@smithy/util-middleware": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-4.0.1.tgz", - "integrity": "sha512-HiLAvlcqhbzhuiOa0Lyct5IIlyIz0PQO5dnMlmQ/ubYM46dPInB+3yQGkfxsk6Q24Y0n3/JmcA1v5iEhmOF5mA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.1.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@aws-sdk/client-s3/node_modules/@smithy/util-retry": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-4.0.1.tgz", @@ -7983,6 +7394,7 @@ "version": "3.623.0", "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.623.0.tgz", "integrity": "sha512-oEACriysQMnHIVcNp7TD6D1nzgiHfYK0tmMBMbUxgoFuCBkW9g9QYvspHN+S9KgoePfMEXHuPUe9mtG9AH9XeA==", + "optional": true, "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", @@ -8031,6 +7443,7 @@ "version": "3.623.0", "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.623.0.tgz", "integrity": "sha512-lMFEXCa6ES/FGV7hpyrppT1PiAkqQb51AbG0zVU3TIgI2IO4XX02uzMUXImRSRqRpGymRCbJCaCs9LtKvS/37Q==", + "optional": true, "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", @@ -8083,6 +7496,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", + "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -8094,6 +7508,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-4.1.0.tgz", "integrity": "sha512-dPVoHYQ2wcHooGXg3LQisa1hH0e4y0pAddPMeeUPipI1tEOqL6A4N0/G7abeq+K8wrwSgjk4C0wnD1XZpJm5aA==", + "optional": true, "dependencies": { "@smithy/types": "^3.3.0", "tslib": "^2.6.2" @@ -8106,6 +7521,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.3.0.tgz", "integrity": "sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA==", + "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -8117,6 +7533,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", + "optional": true, "dependencies": { "@smithy/is-array-buffer": "^3.0.0", "tslib": "^2.6.2" @@ -8129,6 +7546,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-3.0.3.tgz", "integrity": "sha512-l+StyYYK/eO3DlVPbU+4Bi06Jjal+PFLSMmlWM1BEwyLxZ3aKkf1ROnoIakfaA7mC6uw3ny7JBkau4Yc+5zfWw==", + "optional": true, "dependencies": { "@smithy/types": "^3.3.0", "tslib": "^2.6.2" @@ -8141,6 +7559,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", + "optional": true, "dependencies": { "@smithy/util-buffer-from": "^3.0.0", "tslib": "^2.6.2" @@ -8153,6 +7572,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", + "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -8164,6 +7584,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-4.1.0.tgz", "integrity": "sha512-dPVoHYQ2wcHooGXg3LQisa1hH0e4y0pAddPMeeUPipI1tEOqL6A4N0/G7abeq+K8wrwSgjk4C0wnD1XZpJm5aA==", + "optional": true, "dependencies": { "@smithy/types": "^3.3.0", "tslib": "^2.6.2" @@ -8176,6 +7597,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.3.0.tgz", "integrity": "sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA==", + "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -8187,6 +7609,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", + "optional": true, "dependencies": { "@smithy/is-array-buffer": "^3.0.0", "tslib": "^2.6.2" @@ -8199,6 +7622,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-3.0.3.tgz", "integrity": "sha512-l+StyYYK/eO3DlVPbU+4Bi06Jjal+PFLSMmlWM1BEwyLxZ3aKkf1ROnoIakfaA7mC6uw3ny7JBkau4Yc+5zfWw==", + "optional": true, "dependencies": { "@smithy/types": "^3.3.0", "tslib": "^2.6.2" @@ -8211,6 +7635,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", + "optional": true, "dependencies": { "@smithy/util-buffer-from": "^3.0.0", "tslib": "^2.6.2" @@ -8223,6 +7648,7 @@ "version": "3.623.0", "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.623.0.tgz", "integrity": "sha512-iJNdx76SOw0YjHAUv8aj3HXzSu3TKI7qSGuR+OGATwA/kpJZDd+4+WYBdGtr8YK+hPrGGqhfecuCkEg805O5iA==", + "optional": true, "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", @@ -8273,6 +7699,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", + "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -8284,6 +7711,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-4.1.0.tgz", "integrity": "sha512-dPVoHYQ2wcHooGXg3LQisa1hH0e4y0pAddPMeeUPipI1tEOqL6A4N0/G7abeq+K8wrwSgjk4C0wnD1XZpJm5aA==", + "optional": true, "dependencies": { "@smithy/types": "^3.3.0", "tslib": "^2.6.2" @@ -8296,6 +7724,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.3.0.tgz", "integrity": "sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA==", + "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -8307,6 +7736,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", + "optional": true, "dependencies": { "@smithy/is-array-buffer": "^3.0.0", "tslib": "^2.6.2" @@ -8319,6 +7749,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-3.0.3.tgz", "integrity": "sha512-l+StyYYK/eO3DlVPbU+4Bi06Jjal+PFLSMmlWM1BEwyLxZ3aKkf1ROnoIakfaA7mC6uw3ny7JBkau4Yc+5zfWw==", + "optional": true, "dependencies": { "@smithy/types": "^3.3.0", "tslib": "^2.6.2" @@ -8331,6 +7762,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", + "optional": true, "dependencies": { "@smithy/util-buffer-from": "^3.0.0", "tslib": "^2.6.2" @@ -8343,6 +7775,7 @@ "version": "3.623.0", "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.623.0.tgz", "integrity": "sha512-8Toq3X6trX/67obSdh4K0MFQY4f132bEbr1i0YPDWk/O3KdBt12mLC/sW3aVRnlIs110XMuX9yrWWqJ8fDW10g==", + "optional": true, "dependencies": { "@smithy/core": "^2.3.2", "@smithy/node-config-provider": "^3.1.4", @@ -8362,6 +7795,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", + "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -8373,6 +7807,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-4.1.0.tgz", "integrity": "sha512-dPVoHYQ2wcHooGXg3LQisa1hH0e4y0pAddPMeeUPipI1tEOqL6A4N0/G7abeq+K8wrwSgjk4C0wnD1XZpJm5aA==", + "optional": true, "dependencies": { "@smithy/types": "^3.3.0", "tslib": "^2.6.2" @@ -8385,6 +7820,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-4.1.0.tgz", "integrity": "sha512-aRryp2XNZeRcOtuJoxjydO6QTaVhxx/vjaR+gx7ZjaFgrgPRyZ3HCTbfwqYj6ZWEBHkCSUfcaymKPURaByukag==", + "optional": true, "dependencies": { "@smithy/is-array-buffer": "^3.0.0", "@smithy/protocol-http": "^4.1.0", @@ -8403,6 +7839,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.3.0.tgz", "integrity": "sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA==", + "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -8414,6 +7851,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", + "optional": true, "dependencies": { "@smithy/is-array-buffer": "^3.0.0", "tslib": "^2.6.2" @@ -8426,6 +7864,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-3.0.0.tgz", "integrity": "sha512-eFndh1WEK5YMUYvy3lPlVmYY/fZcQE1D8oSf41Id2vCeIkKJXPcYDCZD+4+xViI6b1XSd7tE+s5AmXzz5ilabQ==", + "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -8437,6 +7876,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-3.0.3.tgz", "integrity": "sha512-l+StyYYK/eO3DlVPbU+4Bi06Jjal+PFLSMmlWM1BEwyLxZ3aKkf1ROnoIakfaA7mC6uw3ny7JBkau4Yc+5zfWw==", + "optional": true, "dependencies": { "@smithy/types": "^3.3.0", "tslib": "^2.6.2" @@ -8449,6 +7889,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-3.0.0.tgz", "integrity": "sha512-LqR7qYLgZTD7nWLBecUi4aqolw8Mhza9ArpNEQ881MJJIU2sE5iHCK6TdyqqzcDLy0OPe10IY4T8ctVdtynubg==", + "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -8460,6 +7901,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", + "optional": true, "dependencies": { "@smithy/util-buffer-from": "^3.0.0", "tslib": "^2.6.2" @@ -8500,6 +7942,7 @@ "version": "3.620.1", "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.620.1.tgz", "integrity": "sha512-ExuILJ2qLW5ZO+rgkNRj0xiAipKT16Rk77buvPP8csR7kkCflT/gXTyzRe/uzIiETTxM7tr8xuO9MP/DQXqkfg==", + "optional": true, "dependencies": { "@aws-sdk/types": "3.609.0", "@smithy/property-provider": "^3.1.3", @@ -8514,6 +7957,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.3.0.tgz", "integrity": "sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA==", + "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -8525,6 +7969,7 @@ "version": "3.622.0", "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.622.0.tgz", "integrity": "sha512-VUHbr24Oll1RK3WR8XLUugLpgK9ZuxEm/NVeVqyFts1Ck9gsKpRg1x4eH7L7tW3SJ4TDEQNMbD7/7J+eoL2svg==", + "optional": true, "dependencies": { "@aws-sdk/types": "3.609.0", "@smithy/fetch-http-handler": "^3.2.4", @@ -8544,6 +7989,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-4.1.0.tgz", "integrity": "sha512-dPVoHYQ2wcHooGXg3LQisa1hH0e4y0pAddPMeeUPipI1tEOqL6A4N0/G7abeq+K8wrwSgjk4C0wnD1XZpJm5aA==", + "optional": true, "dependencies": { "@smithy/types": "^3.3.0", "tslib": "^2.6.2" @@ -8556,6 +8002,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.3.0.tgz", "integrity": "sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA==", + "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -8567,6 +8014,7 @@ "version": "3.623.0", "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.623.0.tgz", "integrity": "sha512-kvXA1SwGneqGzFwRZNpESitnmaENHGFFuuTvgGwtMe7mzXWuA/LkXdbiHmdyAzOo0iByKTCD8uetuwh3CXy4Pw==", + "optional": true, "dependencies": { "@aws-sdk/credential-provider-env": "3.620.1", "@aws-sdk/credential-provider-http": "3.622.0", @@ -8591,6 +8039,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.3.0.tgz", "integrity": "sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA==", + "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -8602,6 +8051,7 @@ "version": "3.623.0", "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.623.0.tgz", "integrity": "sha512-qDwCOkhbu5PfaQHyuQ+h57HEx3+eFhKdtIw7aISziWkGdFrMe07yIBd7TJqGe4nxXnRF1pfkg05xeOlMId997g==", + "optional": true, "dependencies": { "@aws-sdk/credential-provider-env": "3.620.1", "@aws-sdk/credential-provider-http": "3.622.0", @@ -8624,6 +8074,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.3.0.tgz", "integrity": "sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA==", + "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -8635,6 +8086,7 @@ "version": "3.620.1", "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.620.1.tgz", "integrity": "sha512-hWqFMidqLAkaV9G460+1at6qa9vySbjQKKc04p59OT7lZ5cO5VH5S4aI05e+m4j364MBROjjk2ugNvfNf/8ILg==", + "optional": true, "dependencies": { "@aws-sdk/types": "3.609.0", "@smithy/property-provider": "^3.1.3", @@ -8650,6 +8102,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.3.0.tgz", "integrity": "sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA==", + "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -8661,6 +8114,7 @@ "version": "3.623.0", "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.623.0.tgz", "integrity": "sha512-70LZhUb3l7cttEsg4A0S4Jq3qrCT/v5Jfyl8F7w1YZJt5zr3oPPcvDJxo/UYckFz4G4/5BhGa99jK8wMlNE9QA==", + "optional": true, "dependencies": { "@aws-sdk/client-sso": "3.623.0", "@aws-sdk/token-providers": "3.614.0", @@ -8678,6 +8132,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.3.0.tgz", "integrity": "sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA==", + "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -8689,6 +8144,7 @@ "version": "3.621.0", "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.621.0.tgz", "integrity": "sha512-w7ASSyfNvcx7+bYGep3VBgC3K6vEdLmlpjT7nSIHxxQf+WSdvy+HynwJosrpZax0sK5q0D1Jpn/5q+r5lwwW6w==", + "optional": true, "dependencies": { "@aws-sdk/types": "3.609.0", "@smithy/property-provider": "^3.1.3", @@ -8706,6 +8162,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.3.0.tgz", "integrity": "sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA==", + "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -8837,18 +8294,6 @@ "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/middleware-bucket-endpoint/node_modules/@smithy/types": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.1.0.tgz", - "integrity": "sha512-enhjdwp4D7CXmwLtD6zbcDMbo6/T6WtuuKCY49Xxc6OMOmUWlBEBDREsxxgV2LIdeQPW756+f97GzcgAwp3iLw==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@aws-sdk/middleware-bucket-endpoint/node_modules/@smithy/util-config-provider": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-4.0.0.tgz", @@ -8902,18 +8347,6 @@ "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/middleware-expect-continue/node_modules/@smithy/types": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.1.0.tgz", - "integrity": "sha512-enhjdwp4D7CXmwLtD6zbcDMbo6/T6WtuuKCY49Xxc6OMOmUWlBEBDREsxxgV2LIdeQPW756+f97GzcgAwp3iLw==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@aws-sdk/middleware-flexible-checksums": { "version": "3.758.0", "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.758.0.tgz", @@ -9275,18 +8708,6 @@ "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/middleware-flexible-checksums/node_modules/@smithy/types": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.1.0.tgz", - "integrity": "sha512-enhjdwp4D7CXmwLtD6zbcDMbo6/T6WtuuKCY49Xxc6OMOmUWlBEBDREsxxgV2LIdeQPW756+f97GzcgAwp3iLw==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@aws-sdk/middleware-flexible-checksums/node_modules/@smithy/url-parser": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-4.0.1.tgz", @@ -9352,19 +8773,6 @@ "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/middleware-flexible-checksums/node_modules/@smithy/util-middleware": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-4.0.1.tgz", - "integrity": "sha512-HiLAvlcqhbzhuiOa0Lyct5IIlyIz0PQO5dnMlmQ/ubYM46dPInB+3yQGkfxsk6Q24Y0n3/JmcA1v5iEhmOF5mA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.1.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@aws-sdk/middleware-flexible-checksums/node_modules/@smithy/util-stream": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.1.2.tgz", @@ -9413,6 +8821,7 @@ "version": "3.620.0", "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.620.0.tgz", "integrity": "sha512-VMtPEZwqYrII/oUkffYsNWY9PZ9xpNJpMgmyU0rlDQ25O1c0Hk3fJmZRe6pEkAJ0omD7kLrqGl1DUjQVxpd/Rg==", + "optional": true, "dependencies": { "@aws-sdk/types": "3.609.0", "@smithy/protocol-http": "^4.1.0", @@ -9427,6 +8836,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-4.1.0.tgz", "integrity": "sha512-dPVoHYQ2wcHooGXg3LQisa1hH0e4y0pAddPMeeUPipI1tEOqL6A4N0/G7abeq+K8wrwSgjk4C0wnD1XZpJm5aA==", + "optional": true, "dependencies": { "@smithy/types": "^3.3.0", "tslib": "^2.6.2" @@ -9439,6 +8849,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.3.0.tgz", "integrity": "sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA==", + "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -9473,22 +8884,11 @@ "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/middleware-location-constraint/node_modules/@smithy/types": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.1.0.tgz", - "integrity": "sha512-enhjdwp4D7CXmwLtD6zbcDMbo6/T6WtuuKCY49Xxc6OMOmUWlBEBDREsxxgV2LIdeQPW756+f97GzcgAwp3iLw==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@aws-sdk/middleware-logger": { "version": "3.609.0", "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.609.0.tgz", "integrity": "sha512-S62U2dy4jMDhDFDK5gZ4VxFdWzCtLzwbYyFZx2uvPYTECkepLUfzLic2BHg2Qvtu4QjX+oGE3P/7fwaGIsGNuQ==", + "optional": true, "dependencies": { "@aws-sdk/types": "3.609.0", "@smithy/types": "^3.3.0", @@ -9502,6 +8902,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.3.0.tgz", "integrity": "sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA==", + "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -9513,6 +8914,7 @@ "version": "3.620.0", "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.620.0.tgz", "integrity": "sha512-nh91S7aGK3e/o1ck64sA/CyoFw+gAYj2BDOnoNa6ouyCrVJED96ZXWbhye/fz9SgmNUZR2g7GdVpiLpMKZoI5w==", + "optional": true, "dependencies": { "@aws-sdk/types": "3.609.0", "@smithy/protocol-http": "^4.1.0", @@ -9527,6 +8929,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-4.1.0.tgz", "integrity": "sha512-dPVoHYQ2wcHooGXg3LQisa1hH0e4y0pAddPMeeUPipI1tEOqL6A4N0/G7abeq+K8wrwSgjk4C0wnD1XZpJm5aA==", + "optional": true, "dependencies": { "@smithy/types": "^3.3.0", "tslib": "^2.6.2" @@ -9539,6 +8942,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.3.0.tgz", "integrity": "sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA==", + "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -9845,18 +9249,6 @@ "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/middleware-sdk-s3/node_modules/@smithy/types": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.1.0.tgz", - "integrity": "sha512-enhjdwp4D7CXmwLtD6zbcDMbo6/T6WtuuKCY49Xxc6OMOmUWlBEBDREsxxgV2LIdeQPW756+f97GzcgAwp3iLw==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@aws-sdk/middleware-sdk-s3/node_modules/@smithy/url-parser": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-4.0.1.tgz", @@ -9934,19 +9326,6 @@ "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/middleware-sdk-s3/node_modules/@smithy/util-middleware": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-4.0.1.tgz", - "integrity": "sha512-HiLAvlcqhbzhuiOa0Lyct5IIlyIz0PQO5dnMlmQ/ubYM46dPInB+3yQGkfxsk6Q24Y0n3/JmcA1v5iEhmOF5mA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.1.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@aws-sdk/middleware-sdk-s3/node_modules/@smithy/util-stream": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.1.2.tgz", @@ -10018,22 +9397,11 @@ "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/middleware-ssec/node_modules/@smithy/types": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.1.0.tgz", - "integrity": "sha512-enhjdwp4D7CXmwLtD6zbcDMbo6/T6WtuuKCY49Xxc6OMOmUWlBEBDREsxxgV2LIdeQPW756+f97GzcgAwp3iLw==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@aws-sdk/middleware-user-agent": { "version": "3.620.0", "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.620.0.tgz", "integrity": "sha512-bvS6etn+KsuL32ubY5D3xNof1qkenpbJXf/ugGXbg0n98DvDFQ/F+SMLxHgbnER5dsKYchNnhmtI6/FC3HFu/A==", + "optional": true, "dependencies": { "@aws-sdk/types": "3.609.0", "@aws-sdk/util-endpoints": "3.614.0", @@ -10049,6 +9417,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-4.1.0.tgz", "integrity": "sha512-dPVoHYQ2wcHooGXg3LQisa1hH0e4y0pAddPMeeUPipI1tEOqL6A4N0/G7abeq+K8wrwSgjk4C0wnD1XZpJm5aA==", + "optional": true, "dependencies": { "@smithy/types": "^3.3.0", "tslib": "^2.6.2" @@ -10061,6 +9430,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.3.0.tgz", "integrity": "sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA==", + "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -10778,6 +10148,7 @@ "version": "3.614.0", "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.614.0.tgz", "integrity": "sha512-vDCeMXvic/LU0KFIUjpC3RiSTIkkvESsEfbVHiHH0YINfl8HnEqR5rj+L8+phsCeVg2+LmYwYxd5NRz4PHxt5g==", + "optional": true, "dependencies": { "@aws-sdk/types": "3.609.0", "@smithy/node-config-provider": "^3.1.4", @@ -10794,6 +10165,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.3.0.tgz", "integrity": "sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA==", + "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -10805,6 +10177,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-3.0.3.tgz", "integrity": "sha512-l+StyYYK/eO3DlVPbU+4Bi06Jjal+PFLSMmlWM1BEwyLxZ3aKkf1ROnoIakfaA7mC6uw3ny7JBkau4Yc+5zfWw==", + "optional": true, "dependencies": { "@smithy/types": "^3.3.0", "tslib": "^2.6.2" @@ -11065,18 +10438,6 @@ "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/s3-request-presigner/node_modules/@smithy/types": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.1.0.tgz", - "integrity": "sha512-enhjdwp4D7CXmwLtD6zbcDMbo6/T6WtuuKCY49Xxc6OMOmUWlBEBDREsxxgV2LIdeQPW756+f97GzcgAwp3iLw==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@aws-sdk/s3-request-presigner/node_modules/@smithy/url-parser": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-4.0.1.tgz", @@ -11142,19 +10503,6 @@ "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/s3-request-presigner/node_modules/@smithy/util-middleware": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-4.0.1.tgz", - "integrity": "sha512-HiLAvlcqhbzhuiOa0Lyct5IIlyIz0PQO5dnMlmQ/ubYM46dPInB+3yQGkfxsk6Q24Y0n3/JmcA1v5iEhmOF5mA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.1.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@aws-sdk/s3-request-presigner/node_modules/@smithy/util-stream": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.1.2.tgz", @@ -11273,18 +10621,6 @@ "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/signature-v4-multi-region/node_modules/@smithy/types": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.1.0.tgz", - "integrity": "sha512-enhjdwp4D7CXmwLtD6zbcDMbo6/T6WtuuKCY49Xxc6OMOmUWlBEBDREsxxgV2LIdeQPW756+f97GzcgAwp3iLw==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@aws-sdk/signature-v4-multi-region/node_modules/@smithy/util-buffer-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-4.0.0.tgz", @@ -11310,19 +10646,6 @@ "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/signature-v4-multi-region/node_modules/@smithy/util-middleware": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-4.0.1.tgz", - "integrity": "sha512-HiLAvlcqhbzhuiOa0Lyct5IIlyIz0PQO5dnMlmQ/ubYM46dPInB+3yQGkfxsk6Q24Y0n3/JmcA1v5iEhmOF5mA==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/types": "^4.1.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@aws-sdk/signature-v4-multi-region/node_modules/@smithy/util-uri-escape": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-4.0.0.tgz", @@ -11352,6 +10675,7 @@ "version": "3.614.0", "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.614.0.tgz", "integrity": "sha512-okItqyY6L9IHdxqs+Z116y5/nda7rHxLvROxtAJdLavWTYDydxrZstImNgGWTeVdmc0xX2gJCI77UYUTQWnhRw==", + "optional": true, "dependencies": { "@aws-sdk/types": "3.609.0", "@smithy/property-provider": "^3.1.3", @@ -11370,6 +10694,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.3.0.tgz", "integrity": "sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA==", + "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -11416,6 +10741,7 @@ "version": "3.614.0", "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.614.0.tgz", "integrity": "sha512-wK2cdrXHH4oz4IomV/yrGkftU9A+ITB6nFL+rxxyO78is2ifHJpFdV4aqk4LSkXYPi6CXWNru/Dqc7yiKXgJPw==", + "optional": true, "dependencies": { "@aws-sdk/types": "3.609.0", "@smithy/types": "^3.3.0", @@ -11430,6 +10756,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.3.0.tgz", "integrity": "sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA==", + "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -11479,18 +10806,6 @@ "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/util-format-url/node_modules/@smithy/types": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.1.0.tgz", - "integrity": "sha512-enhjdwp4D7CXmwLtD6zbcDMbo6/T6WtuuKCY49Xxc6OMOmUWlBEBDREsxxgV2LIdeQPW756+f97GzcgAwp3iLw==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@aws-sdk/util-format-url/node_modules/@smithy/util-uri-escape": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-4.0.0.tgz", @@ -11518,6 +10833,7 @@ "version": "3.609.0", "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.609.0.tgz", "integrity": "sha512-fojPU+mNahzQ0YHYBsx0ZIhmMA96H+ZIZ665ObU9tl+SGdbLneVZVikGve+NmHTQwHzwkFsZYYnVKAkreJLAtA==", + "optional": true, "dependencies": { "@aws-sdk/types": "3.609.0", "@smithy/types": "^3.3.0", @@ -11529,6 +10845,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.3.0.tgz", "integrity": "sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA==", + "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -11540,6 +10857,7 @@ "version": "3.614.0", "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.614.0.tgz", "integrity": "sha512-15ElZT88peoHnq5TEoEtZwoXTXRxNrk60TZNdpl/TUBJ5oNJ9Dqb5Z4ryb8ofN6nm9aFf59GVAerFDz8iUoHBA==", + "optional": true, "dependencies": { "@aws-sdk/types": "3.609.0", "@smithy/node-config-provider": "^3.1.4", @@ -11562,6 +10880,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.3.0.tgz", "integrity": "sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA==", + "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -11573,6 +10892,8 @@ "version": "3.259.0", "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.259.0.tgz", "integrity": "sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw==", + "optional": true, + "peer": true, "dependencies": { "tslib": "^2.3.1" } @@ -11590,18 +10911,6 @@ "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/xml-builder/node_modules/@smithy/types": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.1.0.tgz", - "integrity": "sha512-enhjdwp4D7CXmwLtD6zbcDMbo6/T6WtuuKCY49Xxc6OMOmUWlBEBDREsxxgV2LIdeQPW756+f97GzcgAwp3iLw==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@axe-core/playwright": { "version": "4.10.1", "resolved": "https://registry.npmjs.org/@axe-core/playwright/-/playwright-4.10.1.tgz", @@ -16064,10 +15373,9 @@ "license": "MIT" }, "node_modules/@google/generative-ai": { - "version": "0.21.0", - "resolved": "https://registry.npmjs.org/@google/generative-ai/-/generative-ai-0.21.0.tgz", - "integrity": "sha512-7XhUbtnlkSEZK15kN3t+tzIMxsbKm/dSkKBFalj+20NvPKe1kBY7mR2P7vuijEn+f06z5+A8bVGKO0v39cr6Wg==", - "license": "Apache-2.0", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@google/generative-ai/-/generative-ai-0.24.0.tgz", + "integrity": "sha512-fnEITCGEB7NdX0BhoYZ/cq/7WPZ1QS5IzJJfC3Tg/OwkvBetMiVJciyaan297OvE4B9Jg1xvo0zIazX/9sGu1Q==", "engines": { "node": ">=18.0.0" } @@ -17217,9 +16525,9 @@ } }, "node_modules/@langchain/anthropic": { - "version": "0.3.15", - "resolved": "https://registry.npmjs.org/@langchain/anthropic/-/anthropic-0.3.15.tgz", - "integrity": "sha512-Ar2viYcZ64idgV7EtCBCb36tIkNtPAhQRxSaMTWPHGspFgMfvwRoleVri9e90sCpjpS9xhlHsIQ0LlUS/Atsrw==", + "version": "0.3.16", + "resolved": "https://registry.npmjs.org/@langchain/anthropic/-/anthropic-0.3.16.tgz", + "integrity": "sha512-O8jhWDsJ175N4p7+ypqMWXMAIT/TRq7NGwMvXGI2IbLPVC7CpjrCZ12yggbYkqzbBDdkVW3bM4fWfINUKWOy2w==", "dependencies": { "@anthropic-ai/sdk": "^0.37.0", "fast-xml-parser": "^4.4.1", @@ -18127,9 +17435,9 @@ } }, "node_modules/@langchain/core": { - "version": "0.3.42", - "resolved": "https://registry.npmjs.org/@langchain/core/-/core-0.3.42.tgz", - "integrity": "sha512-pT/jC5lqWK3YGDq8dQwgKoa6anqAhMtG1x5JbnrOj9NdaLeBbCKBDQ+/Ykzk3nZ8o+0UMsaXNZo7IVL83VVjHg==", + "version": "0.3.43", + "resolved": "https://registry.npmjs.org/@langchain/core/-/core-0.3.43.tgz", + "integrity": "sha512-DwiSUwmZqcuOn7j8SFdeOH1nvaUqG7q8qn3LhobdQYEg5PmjLgd2yLr2KzuT/YWMBfjkOR+Di5K6HEdFmouTxg==", "dependencies": { "@cfworker/json-schema": "^4.0.2", "ansi-styles": "^5.0.0", @@ -18188,9 +17496,9 @@ } }, "node_modules/@langchain/google-common": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/@langchain/google-common/-/google-common-0.2.2.tgz", - "integrity": "sha512-w0811y4rQ/lSUZegcskVzMdSFA8HctWgTZQGjMSfhirVyJTJwJff81IjmQcbjaOyEgY6RA551lMpTPIGvaSl9w==", + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@langchain/google-common/-/google-common-0.2.3.tgz", + "integrity": "sha512-8jjLeMp3TeFP3kJbIZnQ9DQ7Sm7P86TA5M3A7c5TdWLrrh5VZXigqGM58YxO3OPMcFHhu2jN3ITqPUHwGCMIRw==", "dependencies": { "uuid": "^10.0.0", "zod-to-json-schema": "^3.22.4" @@ -18215,11 +17523,11 @@ } }, "node_modules/@langchain/google-gauth": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/@langchain/google-gauth/-/google-gauth-0.2.2.tgz", - "integrity": "sha512-x4tkogcLwJ9VwgY0JF9FSyGAZyzPkoOlBUO5uGTRILcLjR3iNrcWohW6Uy04zadE64w7MLW9d71F8l5ejdjmdA==", + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@langchain/google-gauth/-/google-gauth-0.2.3.tgz", + "integrity": "sha512-8Bd3yJUntu7RYCwcg5VbjJYyMV3DwrZsbwA0mLPYHxt4k353DuZuiLvR40Vev77cb8GAIXpzvfXA3rHkWFG7nw==", "dependencies": { - "@langchain/google-common": "^0.2.2", + "@langchain/google-common": "^0.2.3", "google-auth-library": "^9.15.1" }, "engines": { @@ -18230,11 +17538,12 @@ } }, "node_modules/@langchain/google-genai": { - "version": "0.1.11", - "resolved": "https://registry.npmjs.org/@langchain/google-genai/-/google-genai-0.1.11.tgz", - "integrity": "sha512-puNFwgW+yY3nI358R4wjG7EsCiCIMH0UaIMGcK/GF44opAlf6pBY9iql4CLVrUto1XBI3EETZuNZ9nOhzpnfgQ==", + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/@langchain/google-genai/-/google-genai-0.2.2.tgz", + "integrity": "sha512-fEuMoOjNoL9fudJmIu8P+ixCX/7n4eB6UT4/NsZubwtbm6BWCjuJWNNPNoHDX6aboXlabwnkuW9oTUy9ia2Ekg==", "dependencies": { - "@google/generative-ai": "^0.21.0", + "@google/generative-ai": "^0.24.0", + "uuid": "^11.1.0", "zod-to-json-schema": "^3.22.4" }, "engines": { @@ -18244,12 +17553,24 @@ "@langchain/core": ">=0.3.17 <0.4.0" } }, + "node_modules/@langchain/google-genai/node_modules/uuid": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz", + "integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/esm/bin/uuid" + } + }, "node_modules/@langchain/google-vertexai": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/@langchain/google-vertexai/-/google-vertexai-0.2.2.tgz", - "integrity": "sha512-DqlKD3VXGTwVS4lWUIYhryqFvTTDfWGulySnv/Gf6t4e3A9pXkapyCpxY4hb6hAGYAKV/55qg7CLMueRXWbpcA==", + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@langchain/google-vertexai/-/google-vertexai-0.2.3.tgz", + "integrity": "sha512-PO/dBoTsWpC7Q7MZ1CnZFYFV6efFdFsaDpE/p4XgK5QwiBBx3sZucJfR/hIcPXOpRgc+nrmiDyDYxcg855gxvA==", "dependencies": { - "@langchain/google-gauth": "~0.2.2" + "@langchain/google-gauth": "~0.2.3" }, "engines": { "node": ">=18" @@ -18259,9 +17580,9 @@ } }, "node_modules/@langchain/langgraph": { - "version": "0.2.57", - "resolved": "https://registry.npmjs.org/@langchain/langgraph/-/langgraph-0.2.57.tgz", - "integrity": "sha512-SolqE+HzwbxEEiqAVgHwE11r9lzjZAnAfEe7MMBUE77TUCaWK3GC0VvDfJMNas53ndlc0KRutmpEa0ODWdhcRQ==", + "version": "0.2.63", + "resolved": "https://registry.npmjs.org/@langchain/langgraph/-/langgraph-0.2.63.tgz", + "integrity": "sha512-gmivnxybyBQkR7lpoBz8emrWRt9jFp0csrlDZTI/SlMJ5F+3DvxbsRyH2edI0RPzL7XpiW9QnFGCLMp6wfGblw==", "dependencies": { "@langchain/langgraph-checkpoint": "~0.0.16", "@langchain/langgraph-sdk": "~0.0.32", @@ -18272,7 +17593,13 @@ "node": ">=18" }, "peerDependencies": { - "@langchain/core": ">=0.2.36 <0.3.0 || >=0.3.40 < 0.4.0" + "@langchain/core": ">=0.2.36 <0.3.0 || >=0.3.40 < 0.4.0", + "zod-to-json-schema": "^3.x" + }, + "peerDependenciesMeta": { + "zod-to-json-schema": { + "optional": true + } } }, "node_modules/@langchain/langgraph-checkpoint": { @@ -18302,9 +17629,9 @@ } }, "node_modules/@langchain/langgraph-sdk": { - "version": "0.0.60", - "resolved": "https://registry.npmjs.org/@langchain/langgraph-sdk/-/langgraph-sdk-0.0.60.tgz", - "integrity": "sha512-7ndeAdw1afVY72HpKEGw7AyuDlD7U3e4jxaJflxA+PXaFPiE0d/hQYvlPT84YmvqNzJN605hv7YcrOju2573bQ==", + "version": "0.0.62", + "resolved": "https://registry.npmjs.org/@langchain/langgraph-sdk/-/langgraph-sdk-0.0.62.tgz", + "integrity": "sha512-JJiQwjV5/uVtwiVH/lt+QXhuh0nGhylZSLkMQXc1923TBUC4SHwU0JIKEDqh820PlGNkUu0nODJSAzS/6zPRtQ==", "dependencies": { "@types/json-schema": "^7.0.15", "p-queue": "^6.6.2", @@ -18337,71 +17664,20 @@ } }, "node_modules/@langchain/mistralai": { - "version": "0.0.26", - "resolved": "https://registry.npmjs.org/@langchain/mistralai/-/mistralai-0.0.26.tgz", - "integrity": "sha512-NoXmOTrkHjfCcgWQprbPujCvFktJFPcFTAcJEc4jY0J+PRiwWfhe4Xx2MevWTSV9clWm2Pil454nJ1CYEvh3Ng==", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@langchain/mistralai/-/mistralai-0.2.0.tgz", + "integrity": "sha512-VdfbKZopAuSXf/vlXbriGWLK3c7j5s47DoB3S31xpprY2BMSKZZiX9vE9TsgxMfAPuIDPIYcfgU7p1upvTYt8g==", "dependencies": { - "@langchain/core": ">=0.2.16 <0.3.0", - "@mistralai/mistralai": "^0.4.0", + "@mistralai/mistralai": "^1.3.1", "uuid": "^10.0.0", - "zod": "^3.22.4", + "zod": "^3.23.8", "zod-to-json-schema": "^3.22.4" }, "engines": { "node": ">=18" - } - }, - "node_modules/@langchain/mistralai/node_modules/@langchain/core": { - "version": "0.2.36", - "resolved": "https://registry.npmjs.org/@langchain/core/-/core-0.2.36.tgz", - "integrity": "sha512-qHLvScqERDeH7y2cLuJaSAlMwg3f/3Oc9nayRSXRU2UuaK/SOhI42cxiPLj1FnuHJSmN0rBQFkrLx02gI4mcVg==", - "dependencies": { - "ansi-styles": "^5.0.0", - "camelcase": "6", - "decamelize": "1.2.0", - "js-tiktoken": "^1.0.12", - "langsmith": "^0.1.56-rc.1", - "mustache": "^4.2.0", - "p-queue": "^6.6.2", - "p-retry": "4", - "uuid": "^10.0.0", - "zod": "^3.22.4", - "zod-to-json-schema": "^3.22.3" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@langchain/mistralai/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@langchain/mistralai/node_modules/langsmith": { - "version": "0.1.68", - "resolved": "https://registry.npmjs.org/langsmith/-/langsmith-0.1.68.tgz", - "integrity": "sha512-otmiysWtVAqzMx3CJ4PrtUBhWRG5Co8Z4o7hSZENPjlit9/j3/vm3TSvbaxpDYakZxtMjhkcJTqrdYFipISEiQ==", - "dependencies": { - "@types/uuid": "^10.0.0", - "commander": "^10.0.1", - "p-queue": "^6.6.2", - "p-retry": "4", - "semver": "^7.6.3", - "uuid": "^10.0.0" }, "peerDependencies": { - "openai": "*" - }, - "peerDependenciesMeta": { - "openai": { - "optional": true - } + "@langchain/core": ">=0.3.7 <0.4.0" } }, "node_modules/@langchain/mistralai/node_modules/uuid": { @@ -18417,9 +17693,9 @@ } }, "node_modules/@langchain/ollama": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/@langchain/ollama/-/ollama-0.1.6.tgz", - "integrity": "sha512-hS+xHiRqKpq37eGyZQ0JoTghfNA7hWXK54XbILQ0KVm3v2MMWLKqBAep4LwMLrAr4NE7SIp+SJnQRdsjabR0jw==", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@langchain/ollama/-/ollama-0.2.0.tgz", + "integrity": "sha512-jLlYFqt+nbhaJKLakk7lRTWHZJ7wHeJLM6yuv4jToQ8zPzpL//372+MjggDoW0mnw8ofysg1T2C6mEJspKJtiA==", "dependencies": { "ollama": "^0.5.12", "uuid": "^10.0.0", @@ -18542,6 +17818,604 @@ "@lezer/common": "^1.0.0" } }, + "node_modules/@librechat/agents": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@librechat/agents/-/agents-2.4.0.tgz", + "integrity": "sha512-ijPJw+lMMPJ+Y66xSbh0cCiuODihl0TET3CWAxZweVGqynYqtL8PvPqlxtw+jftmrLjDFV04UM2NiDbzDb87HA==", + "dependencies": { + "@langchain/anthropic": "^0.3.16", + "@langchain/aws": "^0.1.7", + "@langchain/community": "^0.3.39", + "@langchain/core": "^0.3.43", + "@langchain/deepseek": "^0.0.1", + "@langchain/google-genai": "^0.2.2", + "@langchain/google-vertexai": "^0.2.3", + "@langchain/langgraph": "^0.2.62", + "@langchain/mistralai": "^0.2.0", + "@langchain/ollama": "^0.2.0", + "@langchain/openai": "^0.5.4", + "@langchain/xai": "^0.0.2", + "dotenv": "^16.4.7", + "https-proxy-agent": "^7.0.6", + "nanoid": "^3.3.7" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@librechat/agents/node_modules/@langchain/community": { + "version": "0.3.39", + "resolved": "https://registry.npmjs.org/@langchain/community/-/community-0.3.39.tgz", + "integrity": "sha512-8sMJD22bUNlQVoh0b8PgRSpO2Hz5zO6BuZeNY3ElgW3cNVXCoywHW7FBmqbwrygGocJQDee76RqiIN0XQunhTg==", + "dependencies": { + "@langchain/openai": ">=0.2.0 <0.6.0", + "binary-extensions": "^2.2.0", + "expr-eval": "^2.0.2", + "flat": "^5.0.2", + "js-yaml": "^4.1.0", + "langchain": ">=0.2.3 <0.3.0 || >=0.3.4 <0.4.0", + "langsmith": ">=0.2.8 <0.4.0", + "uuid": "^10.0.0", + "zod": "^3.22.3", + "zod-to-json-schema": "^3.22.5" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@arcjet/redact": "^v1.0.0-alpha.23", + "@aws-crypto/sha256-js": "^5.0.0", + "@aws-sdk/client-bedrock-agent-runtime": "^3.749.0", + "@aws-sdk/client-bedrock-runtime": "^3.749.0", + "@aws-sdk/client-dynamodb": "^3.749.0", + "@aws-sdk/client-kendra": "^3.749.0", + "@aws-sdk/client-lambda": "^3.749.0", + "@aws-sdk/client-s3": "^3.749.0", + "@aws-sdk/client-sagemaker-runtime": "^3.749.0", + "@aws-sdk/client-sfn": "^3.749.0", + "@aws-sdk/credential-provider-node": "^3.388.0", + "@azure/search-documents": "^12.0.0", + "@azure/storage-blob": "^12.15.0", + "@browserbasehq/sdk": "*", + "@browserbasehq/stagehand": "^1.0.0", + "@clickhouse/client": "^0.2.5", + "@cloudflare/ai": "*", + "@datastax/astra-db-ts": "^1.0.0", + "@elastic/elasticsearch": "^8.4.0", + "@getmetal/metal-sdk": "*", + "@getzep/zep-cloud": "^1.0.6", + "@getzep/zep-js": "^0.9.0", + "@gomomento/sdk": "^1.51.1", + "@gomomento/sdk-core": "^1.51.1", + "@google-ai/generativelanguage": "*", + "@google-cloud/storage": "^6.10.1 || ^7.7.0", + "@gradientai/nodejs-sdk": "^1.2.0", + "@huggingface/inference": "^2.6.4", + "@huggingface/transformers": "^3.2.3", + "@ibm-cloud/watsonx-ai": "*", + "@lancedb/lancedb": "^0.12.0", + "@langchain/core": ">=0.2.21 <0.4.0", + "@layerup/layerup-security": "^1.5.12", + "@libsql/client": "^0.14.0", + "@mendable/firecrawl-js": "^1.4.3", + "@mlc-ai/web-llm": "*", + "@mozilla/readability": "*", + "@neondatabase/serverless": "*", + "@notionhq/client": "^2.2.10", + "@opensearch-project/opensearch": "*", + "@pinecone-database/pinecone": "*", + "@planetscale/database": "^1.8.0", + "@premai/prem-sdk": "^0.3.25", + "@qdrant/js-client-rest": "^1.8.2", + "@raycast/api": "^1.55.2", + "@rockset/client": "^0.9.1", + "@smithy/eventstream-codec": "^2.0.5", + "@smithy/protocol-http": "^3.0.6", + "@smithy/signature-v4": "^2.0.10", + "@smithy/util-utf8": "^2.0.0", + "@spider-cloud/spider-client": "^0.0.21", + "@supabase/supabase-js": "^2.45.0", + "@tensorflow-models/universal-sentence-encoder": "*", + "@tensorflow/tfjs-converter": "*", + "@tensorflow/tfjs-core": "*", + "@upstash/ratelimit": "^1.1.3 || ^2.0.3", + "@upstash/redis": "^1.20.6", + "@upstash/vector": "^1.1.1", + "@vercel/kv": "*", + "@vercel/postgres": "*", + "@writerai/writer-sdk": "^0.40.2", + "@xata.io/client": "^0.28.0", + "@zilliz/milvus2-sdk-node": ">=2.3.5", + "apify-client": "^2.7.1", + "assemblyai": "^4.6.0", + "azion": "^1.11.1", + "better-sqlite3": ">=9.4.0 <12.0.0", + "cassandra-driver": "^4.7.2", + "cborg": "^4.1.1", + "cheerio": "^1.0.0-rc.12", + "chromadb": "*", + "closevector-common": "0.1.3", + "closevector-node": "0.1.6", + "closevector-web": "0.1.6", + "cohere-ai": "*", + "convex": "^1.3.1", + "crypto-js": "^4.2.0", + "d3-dsv": "^2.0.0", + "discord.js": "^14.14.1", + "dria": "^0.0.3", + "duck-duck-scrape": "^2.2.5", + "epub2": "^3.0.1", + "fast-xml-parser": "*", + "firebase-admin": "^11.9.0 || ^12.0.0", + "google-auth-library": "*", + "googleapis": "*", + "hnswlib-node": "^3.0.0", + "html-to-text": "^9.0.5", + "ibm-cloud-sdk-core": "*", + "ignore": "^5.2.0", + "interface-datastore": "^8.2.11", + "ioredis": "^5.3.2", + "it-all": "^3.0.4", + "jsdom": "*", + "jsonwebtoken": "^9.0.2", + "llmonitor": "^0.5.9", + "lodash": "^4.17.21", + "lunary": "^0.7.10", + "mammoth": "^1.6.0", + "mariadb": "^3.4.0", + "mem0ai": "^2.1.8", + "mongodb": ">=5.2.0", + "mysql2": "^3.9.8", + "neo4j-driver": "*", + "notion-to-md": "^3.1.0", + "officeparser": "^4.0.4", + "openai": "*", + "pdf-parse": "1.1.1", + "pg": "^8.11.0", + "pg-copy-streams": "^6.0.5", + "pickleparser": "^0.2.1", + "playwright": "^1.32.1", + "portkey-ai": "^0.1.11", + "puppeteer": "*", + "pyodide": ">=0.24.1 <0.27.0", + "redis": "*", + "replicate": "*", + "sonix-speech-recognition": "^2.1.1", + "srt-parser-2": "^1.2.3", + "typeorm": "^0.3.20", + "typesense": "^1.5.3", + "usearch": "^1.1.1", + "voy-search": "0.6.2", + "weaviate-ts-client": "*", + "web-auth-library": "^1.0.3", + "word-extractor": "*", + "ws": "^8.14.2", + "youtubei.js": "*" + }, + "peerDependenciesMeta": { + "@arcjet/redact": { + "optional": true + }, + "@aws-crypto/sha256-js": { + "optional": true + }, + "@aws-sdk/client-bedrock-agent-runtime": { + "optional": true + }, + "@aws-sdk/client-bedrock-runtime": { + "optional": true + }, + "@aws-sdk/client-dynamodb": { + "optional": true + }, + "@aws-sdk/client-kendra": { + "optional": true + }, + "@aws-sdk/client-lambda": { + "optional": true + }, + "@aws-sdk/client-s3": { + "optional": true + }, + "@aws-sdk/client-sagemaker-runtime": { + "optional": true + }, + "@aws-sdk/client-sfn": { + "optional": true + }, + "@aws-sdk/credential-provider-node": { + "optional": true + }, + "@aws-sdk/dsql-signer": { + "optional": true + }, + "@azure/search-documents": { + "optional": true + }, + "@azure/storage-blob": { + "optional": true + }, + "@browserbasehq/sdk": { + "optional": true + }, + "@clickhouse/client": { + "optional": true + }, + "@cloudflare/ai": { + "optional": true + }, + "@datastax/astra-db-ts": { + "optional": true + }, + "@elastic/elasticsearch": { + "optional": true + }, + "@getmetal/metal-sdk": { + "optional": true + }, + "@getzep/zep-cloud": { + "optional": true + }, + "@getzep/zep-js": { + "optional": true + }, + "@gomomento/sdk": { + "optional": true + }, + "@gomomento/sdk-core": { + "optional": true + }, + "@google-ai/generativelanguage": { + "optional": true + }, + "@google-cloud/storage": { + "optional": true + }, + "@gradientai/nodejs-sdk": { + "optional": true + }, + "@huggingface/inference": { + "optional": true + }, + "@huggingface/transformers": { + "optional": true + }, + "@lancedb/lancedb": { + "optional": true + }, + "@layerup/layerup-security": { + "optional": true + }, + "@libsql/client": { + "optional": true + }, + "@mendable/firecrawl-js": { + "optional": true + }, + "@mlc-ai/web-llm": { + "optional": true + }, + "@mozilla/readability": { + "optional": true + }, + "@neondatabase/serverless": { + "optional": true + }, + "@notionhq/client": { + "optional": true + }, + "@opensearch-project/opensearch": { + "optional": true + }, + "@pinecone-database/pinecone": { + "optional": true + }, + "@planetscale/database": { + "optional": true + }, + "@premai/prem-sdk": { + "optional": true + }, + "@qdrant/js-client-rest": { + "optional": true + }, + "@raycast/api": { + "optional": true + }, + "@rockset/client": { + "optional": true + }, + "@smithy/eventstream-codec": { + "optional": true + }, + "@smithy/protocol-http": { + "optional": true + }, + "@smithy/signature-v4": { + "optional": true + }, + "@smithy/util-utf8": { + "optional": true + }, + "@spider-cloud/spider-client": { + "optional": true + }, + "@supabase/supabase-js": { + "optional": true + }, + "@tensorflow-models/universal-sentence-encoder": { + "optional": true + }, + "@tensorflow/tfjs-converter": { + "optional": true + }, + "@tensorflow/tfjs-core": { + "optional": true + }, + "@upstash/ratelimit": { + "optional": true + }, + "@upstash/redis": { + "optional": true + }, + "@upstash/vector": { + "optional": true + }, + "@vercel/kv": { + "optional": true + }, + "@vercel/postgres": { + "optional": true + }, + "@writerai/writer-sdk": { + "optional": true + }, + "@xata.io/client": { + "optional": true + }, + "@zilliz/milvus2-sdk-node": { + "optional": true + }, + "apify-client": { + "optional": true + }, + "assemblyai": { + "optional": true + }, + "azion": { + "optional": true + }, + "better-sqlite3": { + "optional": true + }, + "cassandra-driver": { + "optional": true + }, + "cborg": { + "optional": true + }, + "cheerio": { + "optional": true + }, + "chromadb": { + "optional": true + }, + "closevector-common": { + "optional": true + }, + "closevector-node": { + "optional": true + }, + "closevector-web": { + "optional": true + }, + "cohere-ai": { + "optional": true + }, + "convex": { + "optional": true + }, + "crypto-js": { + "optional": true + }, + "d3-dsv": { + "optional": true + }, + "discord.js": { + "optional": true + }, + "dria": { + "optional": true + }, + "duck-duck-scrape": { + "optional": true + }, + "epub2": { + "optional": true + }, + "fast-xml-parser": { + "optional": true + }, + "firebase-admin": { + "optional": true + }, + "google-auth-library": { + "optional": true + }, + "googleapis": { + "optional": true + }, + "hnswlib-node": { + "optional": true + }, + "html-to-text": { + "optional": true + }, + "ignore": { + "optional": true + }, + "interface-datastore": { + "optional": true + }, + "ioredis": { + "optional": true + }, + "it-all": { + "optional": true + }, + "jsdom": { + "optional": true + }, + "jsonwebtoken": { + "optional": true + }, + "llmonitor": { + "optional": true + }, + "lodash": { + "optional": true + }, + "lunary": { + "optional": true + }, + "mammoth": { + "optional": true + }, + "mariadb": { + "optional": true + }, + "mem0ai": { + "optional": true + }, + "mongodb": { + "optional": true + }, + "mysql2": { + "optional": true + }, + "neo4j-driver": { + "optional": true + }, + "notion-to-md": { + "optional": true + }, + "officeparser": { + "optional": true + }, + "pdf-parse": { + "optional": true + }, + "pg": { + "optional": true + }, + "pg-copy-streams": { + "optional": true + }, + "pickleparser": { + "optional": true + }, + "playwright": { + "optional": true + }, + "portkey-ai": { + "optional": true + }, + "puppeteer": { + "optional": true + }, + "pyodide": { + "optional": true + }, + "redis": { + "optional": true + }, + "replicate": { + "optional": true + }, + "sonix-speech-recognition": { + "optional": true + }, + "srt-parser-2": { + "optional": true + }, + "typeorm": { + "optional": true + }, + "typesense": { + "optional": true + }, + "usearch": { + "optional": true + }, + "voy-search": { + "optional": true + }, + "weaviate-ts-client": { + "optional": true + }, + "web-auth-library": { + "optional": true + }, + "word-extractor": { + "optional": true + }, + "ws": { + "optional": true + }, + "youtubei.js": { + "optional": true + } + } + }, + "node_modules/@librechat/agents/node_modules/@langchain/openai": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/@langchain/openai/-/openai-0.5.4.tgz", + "integrity": "sha512-fBIEgaAMs1OHHjSuOwtonhtFTlRyFETAS9y/4SZxlXV5lLdwEU5OAbfaBTcCR0A58rrlmgt8iPnm2IWn4Onjjw==", + "dependencies": { + "js-tiktoken": "^1.0.12", + "openai": "^4.87.3", + "zod": "^3.22.4", + "zod-to-json-schema": "^3.22.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@langchain/core": ">=0.3.39 <0.4.0" + } + }, + "node_modules/@librechat/agents/node_modules/agent-base": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", + "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", + "engines": { + "node": ">= 14" + } + }, + "node_modules/@librechat/agents/node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@librechat/agents/node_modules/uuid": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/@librechat/backend": { "resolved": "api", "link": true @@ -18765,11 +18639,14 @@ "license": "MIT" }, "node_modules/@mistralai/mistralai": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@mistralai/mistralai/-/mistralai-0.4.0.tgz", - "integrity": "sha512-KmFzNro1RKxIFh19J3osmUQhucefBBauMXN5fa9doG6dT9OHR/moBvvn+riVlR7c0AVfuxO8Dfa03AyLYYzbyg==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@mistralai/mistralai/-/mistralai-1.5.2.tgz", + "integrity": "sha512-mBTIDQmuAX9RowMYteZFHJIYlEwDcHzzaxgXzrFtlvH9CkKXK7R1VnZ1sZSe+uLMg0dIXUVdPRUh1SwyFeSqXw==", "dependencies": { - "node-fetch": "^2.6.7" + "zod-to-json-schema": "^3.24.1" + }, + "peerDependencies": { + "zod": ">= 3" } }, "node_modules/@modelcontextprotocol/sdk": { @@ -21699,6 +21576,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-3.1.1.tgz", "integrity": "sha512-MBJBiidoe+0cTFhyxT8g+9g7CeVccLM0IOKKUMCNQ1CNMJ/eIfoo0RTfVrXOONEI1UCN1W+zkiHSbzUNE9dZtQ==", + "optional": true, "dependencies": { "@smithy/types": "^3.3.0", "tslib": "^2.6.2" @@ -21711,6 +21589,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.3.0.tgz", "integrity": "sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA==", + "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -21799,6 +21678,7 @@ "version": "3.0.5", "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-3.0.5.tgz", "integrity": "sha512-SkW5LxfkSI1bUC74OtfBbdz+grQXYiPYolyu8VfpLIjEoN/sHVBlLeGXMQ1vX4ejkgfv6sxVbQJ32yF2cl1veA==", + "optional": true, "dependencies": { "@smithy/node-config-provider": "^3.1.4", "@smithy/types": "^3.3.0", @@ -21814,6 +21694,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.3.0.tgz", "integrity": "sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA==", + "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -21825,6 +21706,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-3.0.3.tgz", "integrity": "sha512-l+StyYYK/eO3DlVPbU+4Bi06Jjal+PFLSMmlWM1BEwyLxZ3aKkf1ROnoIakfaA7mC6uw3ny7JBkau4Yc+5zfWw==", + "optional": true, "dependencies": { "@smithy/types": "^3.3.0", "tslib": "^2.6.2" @@ -21837,6 +21719,7 @@ "version": "2.4.0", "resolved": "https://registry.npmjs.org/@smithy/core/-/core-2.4.0.tgz", "integrity": "sha512-cHXq+FneIF/KJbt4q4pjN186+Jf4ZB0ZOqEaZMBhT79srEyGDDBV31NqBRBjazz8ppQ1bJbDJMY9ba5wKFV36w==", + "optional": true, "dependencies": { "@smithy/middleware-endpoint": "^3.1.0", "@smithy/middleware-retry": "^3.0.15", @@ -21857,6 +21740,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", + "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -21868,6 +21752,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-4.1.0.tgz", "integrity": "sha512-dPVoHYQ2wcHooGXg3LQisa1hH0e4y0pAddPMeeUPipI1tEOqL6A4N0/G7abeq+K8wrwSgjk4C0wnD1XZpJm5aA==", + "optional": true, "dependencies": { "@smithy/types": "^3.3.0", "tslib": "^2.6.2" @@ -21880,6 +21765,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.3.0.tgz", "integrity": "sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA==", + "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -21891,6 +21777,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", + "optional": true, "dependencies": { "@smithy/is-array-buffer": "^3.0.0", "tslib": "^2.6.2" @@ -21903,6 +21790,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-3.0.3.tgz", "integrity": "sha512-l+StyYYK/eO3DlVPbU+4Bi06Jjal+PFLSMmlWM1BEwyLxZ3aKkf1ROnoIakfaA7mC6uw3ny7JBkau4Yc+5zfWw==", + "optional": true, "dependencies": { "@smithy/types": "^3.3.0", "tslib": "^2.6.2" @@ -21915,6 +21803,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", + "optional": true, "dependencies": { "@smithy/util-buffer-from": "^3.0.0", "tslib": "^2.6.2" @@ -21927,6 +21816,7 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-3.2.0.tgz", "integrity": "sha512-0SCIzgd8LYZ9EJxUjLXBmEKSZR/P/w6l7Rz/pab9culE/RWuqelAKGJvn5qUOl8BgX8Yj5HWM50A5hiB/RzsgA==", + "optional": true, "dependencies": { "@smithy/node-config-provider": "^3.1.4", "@smithy/property-provider": "^3.1.3", @@ -21942,6 +21832,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.3.0.tgz", "integrity": "sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA==", + "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -21953,6 +21844,8 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-2.2.0.tgz", "integrity": "sha512-8janZoJw85nJmQZc4L8TuePp2pk1nxLgkxIR0TUjKJ5Dkj5oelB9WtiSSGXCQvNsJl0VSTvK/2ueMXxvpa9GVw==", + "optional": true, + "peer": true, "dependencies": { "@aws-crypto/crc32": "3.0.0", "@smithy/types": "^2.12.0", @@ -21964,6 +21857,8 @@ "version": "2.12.0", "resolved": "https://registry.npmjs.org/@smithy/types/-/types-2.12.0.tgz", "integrity": "sha512-QwYgloJ0sVNBeBuBs65cIkTbfzV/Q6ZNPCJ99EICFEdJYG50nGIY/uYXp+TbsdJReIuPr0a0kXmCvren3MbRRw==", + "optional": true, + "peer": true, "dependencies": { "tslib": "^2.6.2" }, @@ -22074,6 +21969,7 @@ "version": "3.2.4", "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-3.2.4.tgz", "integrity": "sha512-kBprh5Gs5h7ug4nBWZi1FZthdqSM+T7zMmsZxx0IBvWUn7dK3diz2SHn7Bs4dQGFDk8plDv375gzenDoNwrXjg==", + "optional": true, "dependencies": { "@smithy/protocol-http": "^4.1.0", "@smithy/querystring-builder": "^3.0.3", @@ -22086,6 +21982,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-4.1.0.tgz", "integrity": "sha512-dPVoHYQ2wcHooGXg3LQisa1hH0e4y0pAddPMeeUPipI1tEOqL6A4N0/G7abeq+K8wrwSgjk4C0wnD1XZpJm5aA==", + "optional": true, "dependencies": { "@smithy/types": "^3.3.0", "tslib": "^2.6.2" @@ -22098,6 +21995,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.3.0.tgz", "integrity": "sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA==", + "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -22120,22 +22018,11 @@ "node": ">=18.0.0" } }, - "node_modules/@smithy/hash-blob-browser/node_modules/@smithy/types": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.1.0.tgz", - "integrity": "sha512-enhjdwp4D7CXmwLtD6zbcDMbo6/T6WtuuKCY49Xxc6OMOmUWlBEBDREsxxgV2LIdeQPW756+f97GzcgAwp3iLw==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@smithy/hash-node": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-3.0.3.tgz", "integrity": "sha512-2ctBXpPMG+B3BtWSGNnKELJ7SH9e4TNefJS0cd2eSkOOROeBnnVBnAy9LtJ8tY4vUEoe55N4CNPxzbWvR39iBw==", + "optional": true, "dependencies": { "@smithy/types": "^3.3.0", "@smithy/util-buffer-from": "^3.0.0", @@ -22150,6 +22037,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", + "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -22161,6 +22049,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.3.0.tgz", "integrity": "sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA==", + "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -22172,6 +22061,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", + "optional": true, "dependencies": { "@smithy/is-array-buffer": "^3.0.0", "tslib": "^2.6.2" @@ -22184,6 +22074,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", + "optional": true, "dependencies": { "@smithy/util-buffer-from": "^3.0.0", "tslib": "^2.6.2" @@ -22218,18 +22109,6 @@ "node": ">=18.0.0" } }, - "node_modules/@smithy/hash-stream-node/node_modules/@smithy/types": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.1.0.tgz", - "integrity": "sha512-enhjdwp4D7CXmwLtD6zbcDMbo6/T6WtuuKCY49Xxc6OMOmUWlBEBDREsxxgV2LIdeQPW756+f97GzcgAwp3iLw==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@smithy/hash-stream-node/node_modules/@smithy/util-buffer-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-4.0.0.tgz", @@ -22260,6 +22139,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-3.0.3.tgz", "integrity": "sha512-ID1eL/zpDULmHJbflb864k72/SNOZCADRc9i7Exq3RUNJw6raWUSlFEQ+3PX3EYs++bTxZB2dE9mEHTQLv61tw==", + "optional": true, "dependencies": { "@smithy/types": "^3.3.0", "tslib": "^2.6.2" @@ -22269,6 +22149,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.3.0.tgz", "integrity": "sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA==", + "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -22313,18 +22194,6 @@ "node": ">=18.0.0" } }, - "node_modules/@smithy/md5-js/node_modules/@smithy/types": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.1.0.tgz", - "integrity": "sha512-enhjdwp4D7CXmwLtD6zbcDMbo6/T6WtuuKCY49Xxc6OMOmUWlBEBDREsxxgV2LIdeQPW756+f97GzcgAwp3iLw==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@smithy/md5-js/node_modules/@smithy/util-buffer-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-4.0.0.tgz", @@ -22355,6 +22224,7 @@ "version": "3.0.5", "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-3.0.5.tgz", "integrity": "sha512-ILEzC2eyxx6ncej3zZSwMpB5RJ0zuqH7eMptxC4KN3f+v9bqT8ohssKbhNR78k/2tWW+KS5Spw+tbPF4Ejyqvw==", + "optional": true, "dependencies": { "@smithy/protocol-http": "^4.1.0", "@smithy/types": "^3.3.0", @@ -22368,6 +22238,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-4.1.0.tgz", "integrity": "sha512-dPVoHYQ2wcHooGXg3LQisa1hH0e4y0pAddPMeeUPipI1tEOqL6A4N0/G7abeq+K8wrwSgjk4C0wnD1XZpJm5aA==", + "optional": true, "dependencies": { "@smithy/types": "^3.3.0", "tslib": "^2.6.2" @@ -22380,6 +22251,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.3.0.tgz", "integrity": "sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA==", + "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -22391,6 +22263,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-3.1.0.tgz", "integrity": "sha512-5y5aiKCEwg9TDPB4yFE7H6tYvGFf1OJHNczeY10/EFF8Ir8jZbNntQJxMWNfeQjC1mxPsaQ6mR9cvQbf+0YeMw==", + "optional": true, "dependencies": { "@smithy/middleware-serde": "^3.0.3", "@smithy/node-config-provider": "^3.1.4", @@ -22408,6 +22281,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.3.0.tgz", "integrity": "sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA==", + "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -22419,6 +22293,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-3.0.3.tgz", "integrity": "sha512-l+StyYYK/eO3DlVPbU+4Bi06Jjal+PFLSMmlWM1BEwyLxZ3aKkf1ROnoIakfaA7mC6uw3ny7JBkau4Yc+5zfWw==", + "optional": true, "dependencies": { "@smithy/types": "^3.3.0", "tslib": "^2.6.2" @@ -22431,6 +22306,7 @@ "version": "3.0.15", "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-3.0.15.tgz", "integrity": "sha512-iTMedvNt1ApdvkaoE8aSDuwaoc+BhvHqttbA/FO4Ty+y/S5hW6Ci/CTScG7vam4RYJWZxdTElc3MEfHRVH6cgQ==", + "optional": true, "dependencies": { "@smithy/node-config-provider": "^3.1.4", "@smithy/protocol-http": "^4.1.0", @@ -22450,6 +22326,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-4.1.0.tgz", "integrity": "sha512-dPVoHYQ2wcHooGXg3LQisa1hH0e4y0pAddPMeeUPipI1tEOqL6A4N0/G7abeq+K8wrwSgjk4C0wnD1XZpJm5aA==", + "optional": true, "dependencies": { "@smithy/types": "^3.3.0", "tslib": "^2.6.2" @@ -22462,6 +22339,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.3.0.tgz", "integrity": "sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA==", + "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -22473,6 +22351,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-3.0.3.tgz", "integrity": "sha512-l+StyYYK/eO3DlVPbU+4Bi06Jjal+PFLSMmlWM1BEwyLxZ3aKkf1ROnoIakfaA7mC6uw3ny7JBkau4Yc+5zfWw==", + "optional": true, "dependencies": { "@smithy/types": "^3.3.0", "tslib": "^2.6.2" @@ -22485,6 +22364,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-3.0.3.tgz", "integrity": "sha512-puUbyJQBcg9eSErFXjKNiGILJGtiqmuuNKEYNYfUD57fUl4i9+mfmThtQhvFXU0hCVG0iEJhvQUipUf+/SsFdA==", + "optional": true, "dependencies": { "@smithy/types": "^3.3.0", "tslib": "^2.6.2" @@ -22497,6 +22377,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.3.0.tgz", "integrity": "sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA==", + "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -22508,6 +22389,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-3.0.3.tgz", "integrity": "sha512-r4klY9nFudB0r9UdSMaGSyjyQK5adUyPnQN/ZM6M75phTxOdnc/AhpvGD1fQUvgmqjQEBGCwpnPbDm8pH5PapA==", + "optional": true, "dependencies": { "@smithy/types": "^3.3.0", "tslib": "^2.6.2" @@ -22520,6 +22402,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.3.0.tgz", "integrity": "sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA==", + "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -22531,6 +22414,7 @@ "version": "3.1.4", "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-3.1.4.tgz", "integrity": "sha512-YvnElQy8HR4vDcAjoy7Xkx9YT8xZP4cBXcbJSgm/kxmiQu08DwUwj8rkGnyoJTpfl/3xYHH+d8zE+eHqoDCSdQ==", + "optional": true, "dependencies": { "@smithy/property-provider": "^3.1.3", "@smithy/shared-ini-file-loader": "^3.1.4", @@ -22545,6 +22429,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.3.0.tgz", "integrity": "sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA==", + "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -22556,6 +22441,7 @@ "version": "3.1.4", "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-3.1.4.tgz", "integrity": "sha512-+UmxgixgOr/yLsUxcEKGH0fMNVteJFGkmRltYFHnBMlogyFdpzn2CwqWmxOrfJELhV34v0WSlaqG1UtE1uXlJg==", + "optional": true, "dependencies": { "@smithy/abort-controller": "^3.1.1", "@smithy/protocol-http": "^4.1.0", @@ -22571,6 +22457,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-4.1.0.tgz", "integrity": "sha512-dPVoHYQ2wcHooGXg3LQisa1hH0e4y0pAddPMeeUPipI1tEOqL6A4N0/G7abeq+K8wrwSgjk4C0wnD1XZpJm5aA==", + "optional": true, "dependencies": { "@smithy/types": "^3.3.0", "tslib": "^2.6.2" @@ -22583,6 +22470,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.3.0.tgz", "integrity": "sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA==", + "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -22594,6 +22482,7 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-3.1.3.tgz", "integrity": "sha512-zahyOVR9Q4PEoguJ/NrFP4O7SMAfYO1HLhB18M+q+Z4KFd4V2obiMnlVoUFzFLSPeVt1POyNWneHHrZaTMoc/g==", + "optional": true, "dependencies": { "@smithy/types": "^3.3.0", "tslib": "^2.6.2" @@ -22606,6 +22495,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.3.0.tgz", "integrity": "sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA==", + "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -22617,6 +22507,8 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-3.3.0.tgz", "integrity": "sha512-Xy5XK1AFWW2nlY/biWZXu6/krgbaf2dg0q492D8M5qthsnU2H+UgFeZLbM76FnH7s6RO/xhQRkj+T6KBO3JzgQ==", + "optional": true, + "peer": true, "dependencies": { "@smithy/types": "^2.12.0", "tslib": "^2.6.2" @@ -22629,6 +22521,8 @@ "version": "2.12.0", "resolved": "https://registry.npmjs.org/@smithy/types/-/types-2.12.0.tgz", "integrity": "sha512-QwYgloJ0sVNBeBuBs65cIkTbfzV/Q6ZNPCJ99EICFEdJYG50nGIY/uYXp+TbsdJReIuPr0a0kXmCvren3MbRRw==", + "optional": true, + "peer": true, "dependencies": { "tslib": "^2.6.2" }, @@ -22640,6 +22534,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-3.0.3.tgz", "integrity": "sha512-vyWckeUeesFKzCDaRwWLUA1Xym9McaA6XpFfAK5qI9DKJ4M33ooQGqvM4J+LalH4u/Dq9nFiC8U6Qn1qi0+9zw==", + "optional": true, "dependencies": { "@smithy/types": "^3.3.0", "@smithy/util-uri-escape": "^3.0.0", @@ -22653,6 +22548,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.3.0.tgz", "integrity": "sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA==", + "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -22664,6 +22560,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-3.0.0.tgz", "integrity": "sha512-LqR7qYLgZTD7nWLBecUi4aqolw8Mhza9ArpNEQ881MJJIU2sE5iHCK6TdyqqzcDLy0OPe10IY4T8ctVdtynubg==", + "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -22675,6 +22572,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-3.0.3.tgz", "integrity": "sha512-zahM1lQv2YjmznnfQsWbYojFe55l0SLG/988brlLv1i8z3dubloLF+75ATRsqPBboUXsW6I9CPGE5rQgLfY0vQ==", + "optional": true, "dependencies": { "@smithy/types": "^3.3.0", "tslib": "^2.6.2" @@ -22687,6 +22585,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.3.0.tgz", "integrity": "sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA==", + "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -22698,6 +22597,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-3.0.3.tgz", "integrity": "sha512-Jn39sSl8cim/VlkLsUhRFq/dKDnRUFlfRkvhOJaUbLBXUsLRLNf9WaxDv/z9BjuQ3A6k/qE8af1lsqcwm7+DaQ==", + "optional": true, "dependencies": { "@smithy/types": "^3.3.0" }, @@ -22709,6 +22609,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.3.0.tgz", "integrity": "sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA==", + "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -22720,6 +22621,7 @@ "version": "3.1.4", "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-3.1.4.tgz", "integrity": "sha512-qMxS4hBGB8FY2GQqshcRUy1K6k8aBWP5vwm8qKkCT3A9K2dawUwOIJfqh9Yste/Bl0J2lzosVyrXDj68kLcHXQ==", + "optional": true, "dependencies": { "@smithy/types": "^3.3.0", "tslib": "^2.6.2" @@ -22732,6 +22634,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.3.0.tgz", "integrity": "sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA==", + "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -22743,6 +22646,8 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-2.3.0.tgz", "integrity": "sha512-ui/NlpILU+6HAQBfJX8BBsDXuKSNrjTSuOYArRblcrErwKFutjrCNb/OExfVRyj9+26F9J+ZmfWT+fKWuDrH3Q==", + "optional": true, + "peer": true, "dependencies": { "@smithy/is-array-buffer": "^2.2.0", "@smithy/types": "^2.12.0", @@ -22760,6 +22665,8 @@ "version": "2.12.0", "resolved": "https://registry.npmjs.org/@smithy/types/-/types-2.12.0.tgz", "integrity": "sha512-QwYgloJ0sVNBeBuBs65cIkTbfzV/Q6ZNPCJ99EICFEdJYG50nGIY/uYXp+TbsdJReIuPr0a0kXmCvren3MbRRw==", + "optional": true, + "peer": true, "dependencies": { "tslib": "^2.6.2" }, @@ -22771,6 +22678,8 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-2.2.0.tgz", "integrity": "sha512-L1qpleXf9QD6LwLCJ5jddGkgWyuSvWBkJwWAZ6kFkdifdso+sk3L3O1HdmPvCdnCK3IS4qWyPxev01QMnfHSBw==", + "optional": true, + "peer": true, "dependencies": { "@smithy/types": "^2.12.0", "tslib": "^2.6.2" @@ -22783,6 +22692,7 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.2.0.tgz", "integrity": "sha512-pDbtxs8WOhJLJSeaF/eAbPgXg4VVYFlRcL/zoNYA5WbG3wBL06CHtBSg53ppkttDpAJ/hdiede+xApip1CwSLw==", + "optional": true, "dependencies": { "@smithy/middleware-endpoint": "^3.1.0", "@smithy/middleware-stack": "^3.0.3", @@ -22799,6 +22709,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-4.1.0.tgz", "integrity": "sha512-dPVoHYQ2wcHooGXg3LQisa1hH0e4y0pAddPMeeUPipI1tEOqL6A4N0/G7abeq+K8wrwSgjk4C0wnD1XZpJm5aA==", + "optional": true, "dependencies": { "@smithy/types": "^3.3.0", "tslib": "^2.6.2" @@ -22811,6 +22722,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.3.0.tgz", "integrity": "sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA==", + "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -22833,6 +22745,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-3.0.3.tgz", "integrity": "sha512-pw3VtZtX2rg+s6HMs6/+u9+hu6oY6U7IohGhVNnjbgKy86wcIsSZwgHrFR+t67Uyxvp4Xz3p3kGXXIpTNisq8A==", + "optional": true, "dependencies": { "@smithy/querystring-parser": "^3.0.3", "@smithy/types": "^3.3.0", @@ -22843,6 +22756,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.3.0.tgz", "integrity": "sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA==", + "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -22854,6 +22768,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-3.0.0.tgz", "integrity": "sha512-Kxvoh5Qtt0CDsfajiZOCpJxgtPHXOKwmM+Zy4waD43UoEMA+qPxxa98aE/7ZhdnBFZFXMOiBR5xbcaMhLtznQQ==", + "optional": true, "dependencies": { "@smithy/util-buffer-from": "^3.0.0", "@smithy/util-utf8": "^3.0.0", @@ -22867,6 +22782,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", + "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -22878,6 +22794,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", + "optional": true, "dependencies": { "@smithy/is-array-buffer": "^3.0.0", "tslib": "^2.6.2" @@ -22890,6 +22807,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", + "optional": true, "dependencies": { "@smithy/util-buffer-from": "^3.0.0", "tslib": "^2.6.2" @@ -22902,6 +22820,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-3.0.0.tgz", "integrity": "sha512-cbjJs2A1mLYmqmyVl80uoLTJhAcfzMOyPgjwAYusWKMdLeNtzmMz9YxNl3/jRLoxSS3wkqkf0jwNdtXWtyEBaQ==", + "optional": true, "dependencies": { "tslib": "^2.6.2" } @@ -22910,6 +22829,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-3.0.0.tgz", "integrity": "sha512-Tj7pZ4bUloNUP6PzwhN7K386tmSmEET9QtQg0TgdNOnxhZvCssHji+oZTUIuzxECRfG8rdm2PMw2WCFs6eIYkA==", + "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -22933,6 +22853,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-3.0.0.tgz", "integrity": "sha512-pbjk4s0fwq3Di/ANL+rCvJMKM5bzAQdE5S/6RL5NXgMExFAi6UgQMPOm5yPaIWPpr+EOXKXRonJ3FoxKf4mCJQ==", + "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -22944,6 +22865,7 @@ "version": "3.0.15", "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-3.0.15.tgz", "integrity": "sha512-FZ4Psa3vjp8kOXcd3HJOiDPBCWtiilLl57r0cnNtq/Ga9RSDrM5ERL6xt+tO43+2af6Pn5Yp92x2n5vPuduNfg==", + "optional": true, "dependencies": { "@smithy/property-provider": "^3.1.3", "@smithy/smithy-client": "^3.2.0", @@ -22959,6 +22881,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.3.0.tgz", "integrity": "sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA==", + "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -22970,6 +22893,7 @@ "version": "3.0.15", "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-3.0.15.tgz", "integrity": "sha512-KSyAAx2q6d0t6f/S4XB2+3+6aQacm3aLMhs9aLMqn18uYGUepbdssfogW5JQZpc6lXNBnp0tEnR5e9CEKmEd7A==", + "optional": true, "dependencies": { "@smithy/config-resolver": "^3.0.5", "@smithy/credential-provider-imds": "^3.2.0", @@ -22987,6 +22911,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.3.0.tgz", "integrity": "sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA==", + "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -22998,6 +22923,7 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-2.0.5.tgz", "integrity": "sha512-ReQP0BWihIE68OAblC/WQmDD40Gx+QY1Ez8mTdFMXpmjfxSyz2fVQu3A4zXRfQU9sZXtewk3GmhfOHswvX+eNg==", + "optional": true, "dependencies": { "@smithy/node-config-provider": "^3.1.4", "@smithy/types": "^3.3.0", @@ -23011,6 +22937,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.3.0.tgz", "integrity": "sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA==", + "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -23022,6 +22949,8 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-2.2.0.tgz", "integrity": "sha512-7iKXR+/4TpLK194pVjKiasIyqMtTYJsgKgM242Y9uzt5dhHnUDvMNb+3xIhRJ9QhvqGii/5cRUt4fJn3dtXNHQ==", + "optional": true, + "peer": true, "dependencies": { "tslib": "^2.6.2" }, @@ -23045,6 +22974,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-3.0.3.tgz", "integrity": "sha512-AFw+hjpbtVApzpNDhbjNG5NA3kyoMs7vx0gsgmlJF4s+yz1Zlepde7J58zpIRIsdjc+emhpAITxA88qLkPF26w==", + "optional": true, "dependencies": { "@smithy/service-error-classification": "^3.0.3", "@smithy/types": "^3.3.0", @@ -23058,6 +22988,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.3.0.tgz", "integrity": "sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA==", + "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -23069,6 +23000,7 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-3.1.3.tgz", "integrity": "sha512-FIv/bRhIlAxC0U7xM1BCnF2aDRPq0UaelqBHkM2lsCp26mcBbgI0tCVTv+jGdsQLUmAMybua/bjDsSu8RQHbmw==", + "optional": true, "dependencies": { "@smithy/fetch-http-handler": "^3.2.4", "@smithy/node-http-handler": "^3.1.4", @@ -23087,6 +23019,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", + "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -23098,6 +23031,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.3.0.tgz", "integrity": "sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA==", + "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -23109,6 +23043,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", + "optional": true, "dependencies": { "@smithy/is-array-buffer": "^3.0.0", "tslib": "^2.6.2" @@ -23121,6 +23056,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-3.0.0.tgz", "integrity": "sha512-eFndh1WEK5YMUYvy3lPlVmYY/fZcQE1D8oSf41Id2vCeIkKJXPcYDCZD+4+xViI6b1XSd7tE+s5AmXzz5ilabQ==", + "optional": true, "dependencies": { "tslib": "^2.6.2" }, @@ -23132,6 +23068,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", + "optional": true, "dependencies": { "@smithy/util-buffer-from": "^3.0.0", "tslib": "^2.6.2" @@ -23144,6 +23081,8 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-2.2.0.tgz", "integrity": "sha512-jtmJMyt1xMD/d8OtbVJ2gFZOSKc+ueYJZPW20ULW1GOp/q/YIM0wNh+u8ZFao9UaIGz4WoPW8hC64qlWLIfoDA==", + "optional": true, + "peer": true, "dependencies": { "tslib": "^2.6.2" }, @@ -23190,18 +23129,6 @@ "node": ">=18.0.0" } }, - "node_modules/@smithy/util-waiter/node_modules/@smithy/types": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.1.0.tgz", - "integrity": "sha512-enhjdwp4D7CXmwLtD6zbcDMbo6/T6WtuuKCY49Xxc6OMOmUWlBEBDREsxxgV2LIdeQPW756+f97GzcgAwp3iLw==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@stitches/core": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/@stitches/core/-/core-1.2.8.tgz", @@ -35531,9 +35458,9 @@ } }, "node_modules/openai": { - "version": "4.80.1", - "resolved": "https://registry.npmjs.org/openai/-/openai-4.80.1.tgz", - "integrity": "sha512-+6+bbXFwbIE88foZsBEt36bPkgZPdyFN82clAXG61gnHb2gXdZApDyRrcAHqEtpYICywpqaNo57kOm9dtnb7Cw==", + "version": "4.91.1", + "resolved": "https://registry.npmjs.org/openai/-/openai-4.91.1.tgz", + "integrity": "sha512-DbjrR0hIMQFbxz8+3qBsfPJnh3+I/skPgoSlT7f9eiZuhGBUissPQULNgx6gHNkLoZ3uS0uYS6eXPUdtg4nHzw==", "dependencies": { "@types/node": "^18.11.18", "@types/node-fetch": "^2.6.4", diff --git a/packages/mcp/src/flow/manager.ts b/packages/mcp/src/flow/manager.ts index f282bfad8c..0e629cc861 100644 --- a/packages/mcp/src/flow/manager.ts +++ b/packages/mcp/src/flow/manager.ts @@ -55,13 +55,18 @@ export class FlowStateManager { /** * Creates a new flow and waits for its completion */ - async createFlow(flowId: string, type: string, metadata: FlowMetadata = {}): Promise { + async createFlow( + flowId: string, + type: string, + metadata: FlowMetadata = {}, + signal?: AbortSignal, + ): Promise { const flowKey = this.getFlowKey(flowId, type); let existingState = (await this.keyv.get(flowKey)) as FlowState | undefined; if (existingState) { this.logger.debug(`[${flowKey}] Flow already exists`); - return this.monitorFlow(flowKey, type); + return this.monitorFlow(flowKey, type, signal); } await new Promise((resolve) => setTimeout(resolve, 250)); @@ -69,7 +74,7 @@ export class FlowStateManager { existingState = (await this.keyv.get(flowKey)) as FlowState | undefined; if (existingState) { this.logger.debug(`[${flowKey}] Flow exists on 2nd check`); - return this.monitorFlow(flowKey, type); + return this.monitorFlow(flowKey, type, signal); } const initialState: FlowState = { @@ -81,10 +86,10 @@ export class FlowStateManager { this.logger.debug('Creating initial flow state:', flowKey); await this.keyv.set(flowKey, initialState, this.ttl); - return this.monitorFlow(flowKey, type); + return this.monitorFlow(flowKey, type, signal); } - private monitorFlow(flowKey: string, type: string): Promise { + private monitorFlow(flowKey: string, type: string, signal?: AbortSignal): Promise { return new Promise((resolve, reject) => { const checkInterval = 2000; let elapsedTime = 0; @@ -101,6 +106,16 @@ export class FlowStateManager { return; } + if (signal?.aborted) { + clearInterval(intervalId); + this.intervals.delete(intervalId); + this.logger.warn(`[${flowKey}] Flow aborted`); + const message = `${type} flow aborted`; + await this.keyv.delete(flowKey); + reject(new Error(message)); + return; + } + if (flowState.status !== 'PENDING') { clearInterval(intervalId); this.intervals.delete(intervalId); @@ -197,19 +212,19 @@ export class FlowStateManager { * @param flowId - The ID of the flow * @param type - The type of flow * @param handler - Async function to execute if no existing flow is found - * @param metadata - Optional metadata for the flow + * @param signal - Optional AbortSignal to cancel the flow */ async createFlowWithHandler( flowId: string, type: string, handler: () => Promise, - metadata: FlowMetadata = {}, + signal?: AbortSignal, ): Promise { const flowKey = this.getFlowKey(flowId, type); let existingState = (await this.keyv.get(flowKey)) as FlowState | undefined; if (existingState) { this.logger.debug(`[${flowKey}] Flow already exists`); - return this.monitorFlow(flowKey, type); + return this.monitorFlow(flowKey, type, signal); } await new Promise((resolve) => setTimeout(resolve, 250)); @@ -217,13 +232,13 @@ export class FlowStateManager { existingState = (await this.keyv.get(flowKey)) as FlowState | undefined; if (existingState) { this.logger.debug(`[${flowKey}] Flow exists on 2nd check`); - return this.monitorFlow(flowKey, type); + return this.monitorFlow(flowKey, type, signal); } const initialState: FlowState = { type, status: 'PENDING', - metadata, + metadata: {}, createdAt: Date.now(), }; this.logger.debug(`[${flowKey}] Creating initial flow state`); From 175cfe8ffba239b36b3b793857964459a034fbde Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 6 Apr 2025 15:17:23 -0400 Subject: [PATCH 2/8] =?UTF-8?q?=F0=9F=93=A6=20chore:=20bump=20vite=20from?= =?UTF-8?q?=206.2.3=20to=206.2.5=20(#6745)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 6.2.3 to 6.2.5. - [Release notes](https://github.com/vitejs/vite/releases) - [Changelog](https://github.com/vitejs/vite/blob/v6.2.5/packages/vite/CHANGELOG.md) - [Commits](https://github.com/vitejs/vite/commits/v6.2.5/packages/vite) --- updated-dependencies: - dependency-name: vite dependency-version: 6.2.5 dependency-type: direct:development ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- client/package.json | 2 +- package-lock.json | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/client/package.json b/client/package.json index 32c3bc32b5..184e768c5f 100644 --- a/client/package.json +++ b/client/package.json @@ -141,7 +141,7 @@ "tailwindcss": "^3.4.1", "ts-jest": "^29.2.5", "typescript": "^5.3.3", - "vite": "^6.2.3", + "vite": "^6.2.5", "vite-plugin-compression2": "^1.3.3", "vite-plugin-node-polyfills": "^0.23.0", "vite-plugin-pwa": "^0.21.2" diff --git a/package-lock.json b/package-lock.json index 88f008db61..153b969ffd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1250,7 +1250,7 @@ "tailwindcss": "^3.4.1", "ts-jest": "^29.2.5", "typescript": "^5.3.3", - "vite": "^6.2.3", + "vite": "^6.2.5", "vite-plugin-compression2": "^1.3.3", "vite-plugin-node-polyfills": "^0.23.0", "vite-plugin-pwa": "^0.21.2" @@ -42269,9 +42269,9 @@ } }, "node_modules/vite": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.2.3.tgz", - "integrity": "sha512-IzwM54g4y9JA/xAeBPNaDXiBF8Jsgl3VBQ2YQ/wOY6fyW3xMdSoltIV3Bo59DErdqdE6RxUfv8W69DvUorE4Eg==", + "version": "6.2.5", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.2.5.tgz", + "integrity": "sha512-j023J/hCAa4pRIUH6J9HemwYfjB5llR2Ps0CWeikOtdR8+pAURAk0DoJC5/mm9kd+UgdnIy7d6HE4EAvlYhPhA==", "dev": true, "license": "MIT", "dependencies": { From 4afab52fc5d10fb057ae819286c72da7b1b980e0 Mon Sep 17 00:00:00 2001 From: Danny Avila Date: Mon, 7 Apr 2025 14:48:11 -0400 Subject: [PATCH 3/8] =?UTF-8?q?=F0=9F=AA=BA=20fix:=20Update=20Role=20Handl?= =?UTF-8?q?ing=20due=20to=20New=20Schema=20Shape=20(#6774)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 📝 fix: Update translation for shared agent message in English locale * 🪺 fix: Migrate role schema to new nested structure and update permissions handling where missed --- api/models/Role.js | 131 +++++++++++++++++- api/server/routes/roles.js | 30 ++-- .../src/components/Prompts/AdminSettings.tsx | 12 +- .../SidePanel/Agents/AdminSettings.tsx | 12 +- client/src/locales/en/translation.json | 2 +- packages/data-provider/src/roles.ts | 28 +++- 6 files changed, 185 insertions(+), 30 deletions(-) diff --git a/api/models/Role.js b/api/models/Role.js index c4abfedad2..07bf5a2ccb 100644 --- a/api/models/Role.js +++ b/api/models/Role.js @@ -99,6 +99,25 @@ async function updateAccessPermissions(roleName, permissionsUpdate) { const updatedPermissions = { ...currentPermissions }; let hasChanges = false; + const unsetFields = {}; + const permissionTypes = Object.keys(permissionsSchema.shape || {}); + for (const permType of permissionTypes) { + if (role[permType] && typeof role[permType] === 'object') { + logger.info( + `Migrating '${roleName}' role from old schema: found '${permType}' at top level`, + ); + + updatedPermissions[permType] = { + ...updatedPermissions[permType], + ...role[permType], + }; + + unsetFields[permType] = 1; + hasChanges = true; + } + } + + // Process the current updates for (const [permissionType, permissions] of Object.entries(updates)) { const currentTypePermissions = currentPermissions[permissionType] || {}; updatedPermissions[permissionType] = { ...currentTypePermissions }; @@ -115,8 +134,36 @@ async function updateAccessPermissions(roleName, permissionsUpdate) { } if (hasChanges) { - // Update only the permissions field. - await updateRoleByName(roleName, { permissions: updatedPermissions }); + const updateObj = { permissions: updatedPermissions }; + + if (Object.keys(unsetFields).length > 0) { + logger.info( + `Unsetting old schema fields for '${roleName}' role: ${Object.keys(unsetFields).join(', ')}`, + ); + + try { + await Role.updateOne( + { name: roleName }, + { + $set: updateObj, + $unset: unsetFields, + }, + ); + + const cache = getLogStores(CacheKeys.ROLES); + const updatedRole = await Role.findOne({ name: roleName }).select('-__v').lean().exec(); + await cache.set(roleName, updatedRole); + + logger.info(`Updated role '${roleName}' and removed old schema fields`); + } catch (updateError) { + logger.error(`Error during role migration update: ${updateError.message}`); + throw updateError; + } + } else { + // Standard update if no migration needed + await updateRoleByName(roleName, updateObj); + } + logger.info(`Updated '${roleName}' role permissions`); } else { logger.info(`No changes needed for '${roleName}' role permissions`); @@ -155,10 +202,90 @@ const initializeRoles = async function () { } }; +/** + * Migrates roles from old schema to new schema structure. + * This can be called directly to fix existing roles. + * + * @param {string} [roleName] - Optional specific role to migrate. If not provided, migrates all roles. + * @returns {Promise} Number of roles migrated. + */ +const migrateRoleSchema = async function (roleName) { + try { + // Get roles to migrate + let roles; + if (roleName) { + const role = await Role.findOne({ name: roleName }); + roles = role ? [role] : []; + } else { + roles = await Role.find({}); + } + + logger.info(`Migrating ${roles.length} roles to new schema structure`); + let migratedCount = 0; + + for (const role of roles) { + const permissionTypes = Object.keys(permissionsSchema.shape || {}); + const unsetFields = {}; + let hasOldSchema = false; + + // Check for old schema fields + for (const permType of permissionTypes) { + if (role[permType] && typeof role[permType] === 'object') { + hasOldSchema = true; + + // Ensure permissions object exists + role.permissions = role.permissions || {}; + + // Migrate permissions from old location to new + role.permissions[permType] = { + ...role.permissions[permType], + ...role[permType], + }; + + // Mark field for removal + unsetFields[permType] = 1; + } + } + + if (hasOldSchema) { + try { + logger.info(`Migrating role '${role.name}' from old schema structure`); + + // Simple update operation + await Role.updateOne( + { _id: role._id }, + { + $set: { permissions: role.permissions }, + $unset: unsetFields, + }, + ); + + // Refresh cache + const cache = getLogStores(CacheKeys.ROLES); + const updatedRole = await Role.findById(role._id).lean().exec(); + await cache.set(role.name, updatedRole); + + migratedCount++; + logger.info(`Migrated role '${role.name}'`); + } catch (error) { + logger.error(`Failed to migrate role '${role.name}': ${error.message}`); + } + } + } + + logger.info(`Migration complete: ${migratedCount} roles migrated`); + return migratedCount; + } catch (error) { + logger.error(`Role schema migration failed: ${error.message}`); + throw error; + } +}; + module.exports = { Role, getRoleByName, initializeRoles, updateRoleByName, updateAccessPermissions, + migrateRoleSchema, }; diff --git a/api/server/routes/roles.js b/api/server/routes/roles.js index e58ebb6fe7..17768c7de6 100644 --- a/api/server/routes/roles.js +++ b/api/server/routes/roles.js @@ -48,7 +48,7 @@ router.put('/:roleName/prompts', checkAdmin, async (req, res) => { const { roleName: _r } = req.params; // TODO: TEMP, use a better parsing for roleName const roleName = _r.toUpperCase(); - /** @type {TRole['PROMPTS']} */ + /** @type {TRole['permissions']['PROMPTS']} */ const updates = req.body; try { @@ -59,10 +59,16 @@ router.put('/:roleName/prompts', checkAdmin, async (req, res) => { return res.status(404).send({ message: 'Role not found' }); } + const currentPermissions = + role.permissions?.[PermissionTypes.PROMPTS] || role[PermissionTypes.PROMPTS] || {}; + const mergedUpdates = { - [PermissionTypes.PROMPTS]: { - ...role[PermissionTypes.PROMPTS], - ...parsedUpdates, + permissions: { + ...role.permissions, + [PermissionTypes.PROMPTS]: { + ...currentPermissions, + ...parsedUpdates, + }, }, }; @@ -81,7 +87,7 @@ router.put('/:roleName/agents', checkAdmin, async (req, res) => { const { roleName: _r } = req.params; // TODO: TEMP, use a better parsing for roleName const roleName = _r.toUpperCase(); - /** @type {TRole['AGENTS']} */ + /** @type {TRole['permissions']['AGENTS']} */ const updates = req.body; try { @@ -92,17 +98,23 @@ router.put('/:roleName/agents', checkAdmin, async (req, res) => { return res.status(404).send({ message: 'Role not found' }); } + const currentPermissions = + role.permissions?.[PermissionTypes.AGENTS] || role[PermissionTypes.AGENTS] || {}; + const mergedUpdates = { - [PermissionTypes.AGENTS]: { - ...role[PermissionTypes.AGENTS], - ...parsedUpdates, + permissions: { + ...role.permissions, + [PermissionTypes.AGENTS]: { + ...currentPermissions, + ...parsedUpdates, + }, }, }; const updatedRole = await updateRoleByName(roleName, mergedUpdates); res.status(200).send(updatedRole); } catch (error) { - return res.status(400).send({ message: 'Invalid prompt permissions.', error: error.errors }); + return res.status(400).send({ message: 'Invalid agent permissions.', error: error.errors }); } }); diff --git a/client/src/components/Prompts/AdminSettings.tsx b/client/src/components/Prompts/AdminSettings.tsx index 7f019fb343..5311e2b37c 100644 --- a/client/src/components/Prompts/AdminSettings.tsx +++ b/client/src/components/Prompts/AdminSettings.tsx @@ -80,10 +80,10 @@ const AdminSettings = () => { const [selectedRole, setSelectedRole] = useState(SystemRoles.USER); const defaultValues = useMemo(() => { - if (roles?.[selectedRole]) { - return roles[selectedRole][PermissionTypes.PROMPTS]; + if (roles?.[selectedRole]?.permissions) { + return roles[selectedRole].permissions[PermissionTypes.PROMPTS]; } - return roleDefaults[selectedRole][PermissionTypes.PROMPTS]; + return roleDefaults[selectedRole].permissions[PermissionTypes.PROMPTS]; }, [roles, selectedRole]); const { @@ -99,10 +99,10 @@ const AdminSettings = () => { }); useEffect(() => { - if (roles?.[selectedRole]?.[PermissionTypes.PROMPTS]) { - reset(roles[selectedRole][PermissionTypes.PROMPTS]); + if (roles?.[selectedRole]?.permissions?.[PermissionTypes.PROMPTS]) { + reset(roles[selectedRole].permissions[PermissionTypes.PROMPTS]); } else { - reset(roleDefaults[selectedRole][PermissionTypes.PROMPTS]); + reset(roleDefaults[selectedRole].permissions[PermissionTypes.PROMPTS]); } }, [roles, selectedRole, reset]); diff --git a/client/src/components/SidePanel/Agents/AdminSettings.tsx b/client/src/components/SidePanel/Agents/AdminSettings.tsx index 5fb13fd045..cd5c0679fc 100644 --- a/client/src/components/SidePanel/Agents/AdminSettings.tsx +++ b/client/src/components/SidePanel/Agents/AdminSettings.tsx @@ -72,10 +72,10 @@ const AdminSettings = () => { const [selectedRole, setSelectedRole] = useState(SystemRoles.USER); const defaultValues = useMemo(() => { - if (roles?.[selectedRole]) { - return roles[selectedRole][PermissionTypes.AGENTS]; + if (roles?.[selectedRole]?.permissions) { + return roles[selectedRole].permissions[PermissionTypes.AGENTS]; } - return roleDefaults[selectedRole][PermissionTypes.AGENTS]; + return roleDefaults[selectedRole].permissions[PermissionTypes.AGENTS]; }, [roles, selectedRole]); const { @@ -91,10 +91,10 @@ const AdminSettings = () => { }); useEffect(() => { - if (roles?.[selectedRole]?.[PermissionTypes.AGENTS]) { - reset(roles[selectedRole][PermissionTypes.AGENTS]); + if (roles?.[selectedRole]?.permissions?.[PermissionTypes.AGENTS]) { + reset(roles[selectedRole].permissions[PermissionTypes.AGENTS]); } else { - reset(roleDefaults[selectedRole][PermissionTypes.AGENTS]); + reset(roleDefaults[selectedRole].permissions[PermissionTypes.AGENTS]); } }, [roles, selectedRole, reset]); diff --git a/client/src/locales/en/translation.json b/client/src/locales/en/translation.json index 13635d453c..88b957d5a7 100644 --- a/client/src/locales/en/translation.json +++ b/client/src/locales/en/translation.json @@ -482,7 +482,7 @@ "com_ui_agent_editing_allowed": "Other users can already edit this agent", "com_ui_agent_recursion_limit": "Max Agent Steps", "com_ui_agent_recursion_limit_info": "Limits how many steps the agent can take in a run before giving a final response. Default is 25 steps. A step is either an AI API request or a tool usage round. For example, a basic tool interaction takes 3 steps: initial request, tool usage, and follow-up request.", - "com_ui_agent_shared_to_all": "something needs to go here. was empty", + "com_ui_agent_shared_to_all": "Agent is currently shared to all", "com_ui_agent_var": "{{0}} agent", "com_ui_agents": "Agents", "com_ui_agents_allow_create": "Allow creating Agents", diff --git a/packages/data-provider/src/roles.ts b/packages/data-provider/src/roles.ts index ec863fd94f..ca7d64b206 100644 --- a/packages/data-provider/src/roles.ts +++ b/packages/data-provider/src/roles.ts @@ -74,12 +74,28 @@ export const roleDefaults = defaultRolesSchema.parse({ [SystemRoles.ADMIN]: { name: SystemRoles.ADMIN, permissions: { - [PermissionTypes.PROMPTS]: {}, - [PermissionTypes.BOOKMARKS]: {}, - [PermissionTypes.AGENTS]: {}, - [PermissionTypes.MULTI_CONVO]: {}, - [PermissionTypes.TEMPORARY_CHAT]: {}, - [PermissionTypes.RUN_CODE]: {}, + [PermissionTypes.PROMPTS]: { + [Permissions.SHARED_GLOBAL]: true, + [Permissions.USE]: true, + [Permissions.CREATE]: true, + }, + [PermissionTypes.BOOKMARKS]: { + [Permissions.USE]: true, + }, + [PermissionTypes.AGENTS]: { + [Permissions.SHARED_GLOBAL]: true, + [Permissions.USE]: true, + [Permissions.CREATE]: true, + }, + [PermissionTypes.MULTI_CONVO]: { + [Permissions.USE]: true, + }, + [PermissionTypes.TEMPORARY_CHAT]: { + [Permissions.USE]: true, + }, + [PermissionTypes.RUN_CODE]: { + [Permissions.USE]: true, + }, }, }, [SystemRoles.USER]: { From 018143b5cc91a307647e4f161a82de0a0ee41725 Mon Sep 17 00:00:00 2001 From: Marco Beretta <81851188+berry-13@users.noreply.github.com> Date: Mon, 7 Apr 2025 21:57:49 +0200 Subject: [PATCH 4/8] =?UTF-8?q?=F0=9F=97=A8=EF=B8=8F=20fix:=20Show=20Model?= =?UTF-8?q?Spec=20Greeting=20(#6770)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/components/Chat/Landing.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/src/components/Chat/Landing.tsx b/client/src/components/Chat/Landing.tsx index 484a38b904..bd2945e242 100644 --- a/client/src/components/Chat/Landing.tsx +++ b/client/src/components/Chat/Landing.tsx @@ -52,7 +52,7 @@ export default function Landing({ centerFormOnLanding }: { centerFormOnLanding: }); const name = entity?.name ?? ''; - const description = entity?.description ?? ''; + const description = (entity?.description || conversation?.greeting) ?? ''; const getGreeting = useCallback(() => { if (typeof startupConfig?.interface?.customWelcome === 'string') { @@ -186,8 +186,8 @@ export default function Landing({ centerFormOnLanding }: { centerFormOnLanding: /> )} - {(isAgent || isAssistant) && description && ( -
+ {description && ( +
{description}
)} From 910c73359b81b9e7215a9c89ebf90dc14826c9f9 Mon Sep 17 00:00:00 2001 From: Danny Avila Date: Mon, 7 Apr 2025 19:16:56 -0400 Subject: [PATCH 5/8] =?UTF-8?q?=F0=9F=94=A6=20feat:=20MCP=20Support=20for?= =?UTF-8?q?=20Non-Agent=20Endpoints=20(#6775)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * wip: mcp select * refactor: Update useAvailableToolsQuery to support generic data types * feat: Enhance MCPSelect to dynamically load server options and improve MultiSelect component styling * WIP: ephemeral agents * wip: Add null check for MCPSelect and improve MultiSelect focus handling * feat: Pass conversationId prop to MCPSelect in BadgeRow to optimize badge rendering * feat: useApplyNewAgentTemplate hook to manage ephemeral agent upon conversation creation * WIP: eph. agent payload * refactor(OpenAIClient): streamline message processing by replacing content handling with parseTextParts function * feat: enhance applyAgentTemplate function to accept source conversation ID for improved template application * feat(parsers): add skipReasoning parameter to parseTextParts for conditional reasoning handling * WIP: first pass, ephemeral agent backend processing * chore: import order * feat: update loadEphemeralAgent and loadAgent functions to accept model_parameters for enhanced agent configuration * feat: add showMCPServers prop to BadgeRow for conditional rendering of MCPSelect, fix react rule violation * feat: enhance MCPSelect with localized placeholder and custom icon, add renderSelectedValues callback * feat: simplify message processing in AnthropicClient by replacing content handling with parseTextParts function * feat: implement useLocalStorage hook for managing MCP values and update MCPSelect to utilize it * chore: remove chatGPTBrowserSchema from endpoint schemas and update types for improved schema management * chore: remove compactChatGPTSchema from endpoint schemas and update types for better schema management * refactor: rename schemas for clarity and improve schema management * feat: extend model detection to include 'codestral' alongside 'mistral' * feat: add endpointType parameter to buildOptions and initializeClient functions * fix: update condition for handling completion in BaseClient to include agents client * refactor: simplify payload parsing logic in AgentClient and remove unused providerParsers * refactor: change useSetRecoilState to useRecoilState for better state management in MCPSelect component * refactor: streamline chat route handlers by consolidating middleware and improving endpoint structure * style: update MCPSelect and MultiSelect components for improved layout in mobile view * v0.7.790 * feat: add getMessageMapMethod to process message text and content in GoogleClient * chore: include LAST_MCP_ key prefix in clearLocalStorage function for proper teardown on logout --- api/app/clients/AnthropicClient.js | 12 +- api/app/clients/BaseClient.js | 3 +- api/app/clients/GoogleClient.js | 17 + api/app/clients/OpenAIClient.js | 12 +- api/models/Agent.js | 53 ++- api/server/controllers/agents/client.js | 54 ++- api/server/middleware/buildEndpointOption.js | 14 +- api/server/routes/agents/chat.js | 33 +- api/server/services/Endpoints/agents/build.js | 8 +- .../services/Endpoints/agents/initialize.js | 7 +- client/src/components/Chat/Input/BadgeRow.tsx | 12 +- client/src/components/Chat/Input/ChatForm.tsx | 8 +- .../src/components/Chat/Input/MCPSelect.tsx | 82 +++++ client/src/components/ui/MCPIcon.tsx | 31 ++ client/src/components/ui/MultiSelect.tsx | 128 +++++++ client/src/components/ui/index.ts | 1 + client/src/data-provider/queries.ts | 8 +- client/src/hooks/Chat/useChatFunctions.ts | 5 +- client/src/hooks/SSE/useEventHandlers.ts | 8 +- client/src/hooks/useLocalStorageAlt.tsx | 61 ++++ client/src/locales/en/translation.json | 8 +- client/src/store/agents.ts | 88 +++++ client/src/store/index.ts | 1 + client/src/utils/localStorage.ts | 1 + package-lock.json | 2 +- packages/data-provider/package.json | 2 +- packages/data-provider/src/config.ts | 4 + packages/data-provider/src/createPayload.ts | 15 +- packages/data-provider/src/parsers.ts | 31 +- packages/data-provider/src/schemas.ts | 311 ++++++++---------- packages/data-provider/src/types.ts | 6 + 31 files changed, 741 insertions(+), 285 deletions(-) create mode 100644 client/src/components/Chat/Input/MCPSelect.tsx create mode 100644 client/src/components/ui/MCPIcon.tsx create mode 100644 client/src/components/ui/MultiSelect.tsx create mode 100644 client/src/hooks/useLocalStorageAlt.tsx create mode 100644 client/src/store/agents.ts diff --git a/api/app/clients/AnthropicClient.js b/api/app/clients/AnthropicClient.js index a1fc03a256..bc2e6042c7 100644 --- a/api/app/clients/AnthropicClient.js +++ b/api/app/clients/AnthropicClient.js @@ -4,6 +4,7 @@ const { Constants, ErrorTypes, EModelEndpoint, + parseTextParts, anthropicSettings, getResponseSender, validateVisionModel, @@ -696,15 +697,8 @@ class AnthropicClient extends BaseClient { if (msg.text != null && msg.text && msg.text.startsWith(':::thinking')) { msg.text = msg.text.replace(/:::thinking.*?:::/gs, '').trim(); } else if (msg.content != null) { - /** @type {import('@librechat/agents').MessageContentComplex} */ - const newContent = []; - for (let part of msg.content) { - if (part.think != null) { - continue; - } - newContent.push(part); - } - msg.content = newContent; + msg.text = parseTextParts(msg.content, true); + delete msg.content; } return msg; diff --git a/api/app/clients/BaseClient.js b/api/app/clients/BaseClient.js index fd1a051832..f89f1b3a8e 100644 --- a/api/app/clients/BaseClient.js +++ b/api/app/clients/BaseClient.js @@ -676,7 +676,8 @@ class BaseClient { responseMessage.text = addSpaceIfNeeded(generation) + completion; } else if ( Array.isArray(completion) && - isParamEndpoint(this.options.endpoint, this.options.endpointType) + (this.clientName === EModelEndpoint.agents || + isParamEndpoint(this.options.endpoint, this.options.endpointType)) ) { responseMessage.text = ''; responseMessage.content = completion; diff --git a/api/app/clients/GoogleClient.js b/api/app/clients/GoogleClient.js index a9831649d4..575065d879 100644 --- a/api/app/clients/GoogleClient.js +++ b/api/app/clients/GoogleClient.js @@ -9,6 +9,7 @@ const { validateVisionModel, getResponseSender, endpointSettings, + parseTextParts, EModelEndpoint, ContentTypes, VisionModes, @@ -774,6 +775,22 @@ class GoogleClient extends BaseClient { return this.usage; } + getMessageMapMethod() { + /** + * @param {TMessage} msg + */ + return (msg) => { + if (msg.text != null && msg.text && msg.text.startsWith(':::thinking')) { + msg.text = msg.text.replace(/:::thinking.*?:::/gs, '').trim(); + } else if (msg.content != null) { + msg.text = parseTextParts(msg.content, true); + delete msg.content; + } + + return msg; + }; + } + /** * Calculates the correct token count for the current user message based on the token count map and API usage. * Edge case: If the calculation results in a negative value, it returns the original estimate. diff --git a/api/app/clients/OpenAIClient.js b/api/app/clients/OpenAIClient.js index 6b1afa389d..179f5c986e 100644 --- a/api/app/clients/OpenAIClient.js +++ b/api/app/clients/OpenAIClient.js @@ -6,6 +6,7 @@ const { Constants, ImageDetail, ContentTypes, + parseTextParts, EModelEndpoint, resolveHeaders, KnownEndpoints, @@ -1121,15 +1122,8 @@ ${convo} if (msg.text != null && msg.text && msg.text.startsWith(':::thinking')) { msg.text = msg.text.replace(/:::thinking.*?:::/gs, '').trim(); } else if (msg.content != null) { - /** @type {import('@librechat/agents').MessageContentComplex} */ - const newContent = []; - for (let part of msg.content) { - if (part.think != null) { - continue; - } - newContent.push(part); - } - msg.content = newContent; + msg.text = parseTextParts(msg.content, true); + delete msg.content; } return msg; diff --git a/api/models/Agent.js b/api/models/Agent.js index 5840c61d7b..7c0a630808 100644 --- a/api/models/Agent.js +++ b/api/models/Agent.js @@ -1,6 +1,8 @@ const mongoose = require('mongoose'); +const { agentSchema } = require('@librechat/data-schemas'); const { SystemRoles } = require('librechat-data-provider'); -const { GLOBAL_PROJECT_NAME } = require('librechat-data-provider').Constants; +const { GLOBAL_PROJECT_NAME, EPHEMERAL_AGENT_ID, mcp_delimiter } = + require('librechat-data-provider').Constants; const { CONFIG_STORE, STARTUP_CONFIG } = require('librechat-data-provider').CacheKeys; const { getProjectByName, @@ -9,7 +11,6 @@ const { removeAgentFromAllProjects, } = require('./Project'); const getLogStores = require('~/cache/getLogStores'); -const { agentSchema } = require('@librechat/data-schemas'); const Agent = mongoose.model('agent', agentSchema); @@ -39,9 +40,55 @@ const getAgent = async (searchParameter) => await Agent.findOne(searchParameter) * @param {Object} params * @param {ServerRequest} params.req * @param {string} params.agent_id + * @param {string} params.endpoint + * @param {import('@librechat/agents').ClientOptions} [params.model_parameters] + * @returns {Agent|null} The agent document as a plain object, or null if not found. + */ +const loadEphemeralAgent = ({ req, agent_id, endpoint, model_parameters: _m }) => { + const { model, ...model_parameters } = _m; + /** @type {Record} */ + const availableTools = req.app.locals.availableTools; + const mcpServers = new Set(req.body.ephemeralAgent?.mcp); + /** @type {string[]} */ + const tools = []; + + for (const toolName of Object.keys(availableTools)) { + if (!toolName.includes(mcp_delimiter)) { + continue; + } + const mcpServer = toolName.split(mcp_delimiter)?.[1]; + if (mcpServer && mcpServers.has(mcpServer)) { + tools.push(toolName); + } + } + const instructions = req.body.promptPrefix; + return { + id: agent_id, + instructions, + provider: endpoint, + model_parameters, + model, + tools, + }; +}; + +/** + * Load an agent based on the provided ID + * + * @param {Object} params + * @param {ServerRequest} params.req + * @param {string} params.agent_id + * @param {string} params.endpoint + * @param {import('@librechat/agents').ClientOptions} [params.model_parameters] * @returns {Promise} The agent document as a plain object, or null if not found. */ -const loadAgent = async ({ req, agent_id }) => { +const loadAgent = async ({ req, agent_id, endpoint, model_parameters }) => { + if (!agent_id) { + return null; + } + if (agent_id === EPHEMERAL_AGENT_ID) { + return loadEphemeralAgent({ req, agent_id, endpoint, model_parameters }); + } const agent = await getAgent({ id: agent_id, }); diff --git a/api/server/controllers/agents/client.js b/api/server/controllers/agents/client.js index ee23ee1db6..ff98d80a13 100644 --- a/api/server/controllers/agents/client.js +++ b/api/server/controllers/agents/client.js @@ -20,11 +20,9 @@ const { const { Constants, VisionModes, - openAISchema, ContentTypes, EModelEndpoint, KnownEndpoints, - anthropicSchema, isAgentsEndpoint, AgentCapabilities, bedrockInputSchema, @@ -43,11 +41,18 @@ const { createRun } = require('./run'); /** @typedef {import('@librechat/agents').MessageContentComplex} MessageContentComplex */ /** @typedef {import('@langchain/core/runnables').RunnableConfig} RunnableConfig */ -const providerParsers = { - [EModelEndpoint.openAI]: openAISchema.parse, - [EModelEndpoint.azureOpenAI]: openAISchema.parse, - [EModelEndpoint.anthropic]: anthropicSchema.parse, - [EModelEndpoint.bedrock]: bedrockInputSchema.parse, +/** + * @param {ServerRequest} req + * @param {Agent} agent + * @param {string} endpoint + */ +const payloadParser = ({ req, agent, endpoint }) => { + if (isAgentsEndpoint(endpoint)) { + return { model: undefined }; + } else if (endpoint === EModelEndpoint.bedrock) { + return bedrockInputSchema.parse(agent.model_parameters); + } + return req.body.endpointOption.model_parameters; }; const legacyContentEndpoints = new Set([KnownEndpoints.groq, KnownEndpoints.deepseek]); @@ -180,28 +185,19 @@ class AgentClient extends BaseClient { } getSaveOptions() { - const parseOptions = providerParsers[this.options.endpoint]; - let runOptions = - this.options.endpoint === EModelEndpoint.agents - ? { - model: undefined, - // TODO: - // would need to be override settings; otherwise, model needs to be undefined - // model: this.override.model, - // instructions: this.override.instructions, - // additional_instructions: this.override.additional_instructions, - } - : {}; - - if (parseOptions) { - try { - runOptions = parseOptions(this.options.agent.model_parameters); - } catch (error) { - logger.error( - '[api/server/controllers/agents/client.js #getSaveOptions] Error parsing options', - error, - ); - } + // TODO: + // would need to be override settings; otherwise, model needs to be undefined + // model: this.override.model, + // instructions: this.override.instructions, + // additional_instructions: this.override.additional_instructions, + let runOptions = {}; + try { + runOptions = payloadParser(this.options); + } catch (error) { + logger.error( + '[api/server/controllers/agents/client.js #getSaveOptions] Error parsing options', + error, + ); } return removeNullishValues( diff --git a/api/server/middleware/buildEndpointOption.js b/api/server/middleware/buildEndpointOption.js index 041864b025..8394223b5e 100644 --- a/api/server/middleware/buildEndpointOption.js +++ b/api/server/middleware/buildEndpointOption.js @@ -1,6 +1,11 @@ -const { parseCompactConvo, EModelEndpoint, isAgentsEndpoint } = require('librechat-data-provider'); -const { getModelsConfig } = require('~/server/controllers/ModelController'); +const { + parseCompactConvo, + EModelEndpoint, + isAgentsEndpoint, + EndpointURLs, +} = require('librechat-data-provider'); const azureAssistants = require('~/server/services/Endpoints/azureAssistants'); +const { getModelsConfig } = require('~/server/controllers/ModelController'); const assistants = require('~/server/services/Endpoints/assistants'); const gptPlugins = require('~/server/services/Endpoints/gptPlugins'); const { processFiles } = require('~/server/services/Files/process'); @@ -77,8 +82,9 @@ async function buildEndpointOption(req, res, next) { } try { - const isAgents = isAgentsEndpoint(endpoint); - const endpointFn = buildFunction[endpointType ?? endpoint]; + const isAgents = + isAgentsEndpoint(endpoint) || req.baseUrl.startsWith(EndpointURLs[EModelEndpoint.agents]); + const endpointFn = buildFunction[isAgents ? EModelEndpoint.agents : (endpointType ?? endpoint)]; const builder = isAgents ? (...args) => endpointFn(req, ...args) : endpointFn; // TODO: use object params diff --git a/api/server/routes/agents/chat.js b/api/server/routes/agents/chat.js index 42a18d0100..fe50fdc765 100644 --- a/api/server/routes/agents/chat.js +++ b/api/server/routes/agents/chat.js @@ -20,24 +20,33 @@ router.post('/abort', handleAbort()); const checkAgentAccess = generateCheckAccess(PermissionTypes.AGENTS, [Permissions.USE]); +router.use(checkAgentAccess); +router.use(validateConvoAccess); +router.use(buildEndpointOption); +router.use(setHeaders); + +const controller = async (req, res, next) => { + await AgentController(req, res, next, initializeClient, addTitle); +}; + /** - * @route POST / + * @route POST / (regular endpoint) * @desc Chat with an assistant * @access Public * @param {express.Request} req - The request object, containing the request data. * @param {express.Response} res - The response object, used to send back a response. * @returns {void} */ -router.post( - '/', - // validateModel, - checkAgentAccess, - validateConvoAccess, - buildEndpointOption, - setHeaders, - async (req, res, next) => { - await AgentController(req, res, next, initializeClient, addTitle); - }, -); +router.post('/', controller); + +/** + * @route POST /:endpoint (ephemeral agents) + * @desc Chat with an assistant + * @access Public + * @param {express.Request} req - The request object, containing the request data. + * @param {express.Response} res - The response object, used to send back a response. + * @returns {void} + */ +router.post('/:endpoint', controller); module.exports = router; diff --git a/api/server/services/Endpoints/agents/build.js b/api/server/services/Endpoints/agents/build.js index 999cdc16be..77ebbc58dc 100644 --- a/api/server/services/Endpoints/agents/build.js +++ b/api/server/services/Endpoints/agents/build.js @@ -1,12 +1,15 @@ +const { isAgentsEndpoint, Constants } = require('librechat-data-provider'); const { loadAgent } = require('~/models/Agent'); const { logger } = require('~/config'); -const buildOptions = (req, endpoint, parsedBody) => { +const buildOptions = (req, endpoint, parsedBody, endpointType) => { const { spec, iconURL, agent_id, instructions, maxContextTokens, ...model_parameters } = parsedBody; const agentPromise = loadAgent({ req, - agent_id, + agent_id: isAgentsEndpoint(endpoint) ? agent_id : Constants.EPHEMERAL_AGENT_ID, + endpoint, + model_parameters, }).catch((error) => { logger.error(`[/agents/:${agent_id}] Error retrieving agent during build options step`, error); return undefined; @@ -17,6 +20,7 @@ const buildOptions = (req, endpoint, parsedBody) => { iconURL, endpoint, agent_id, + endpointType, instructions, maxContextTokens, model_parameters, diff --git a/api/server/services/Endpoints/agents/initialize.js b/api/server/services/Endpoints/agents/initialize.js index 0a76f906e0..0186541750 100644 --- a/api/server/services/Endpoints/agents/initialize.js +++ b/api/server/services/Endpoints/agents/initialize.js @@ -1,5 +1,6 @@ const { createContentAggregator, Providers } = require('@librechat/agents'); const { + Constants, ErrorTypes, EModelEndpoint, getResponseSender, @@ -322,10 +323,14 @@ const initializeClient = async ({ req, res, endpointOption }) => { agent: primaryConfig, spec: endpointOption.spec, iconURL: endpointOption.iconURL, - endpoint: EModelEndpoint.agents, attachments: primaryConfig.attachments, + endpointType: endpointOption.endpointType, maxContextTokens: primaryConfig.maxContextTokens, resendFiles: primaryConfig.model_parameters?.resendFiles ?? true, + endpoint: + primaryConfig.id === Constants.EPHEMERAL_AGENT_ID + ? primaryConfig.endpoint + : EModelEndpoint.agents, }); return { client }; diff --git a/client/src/components/Chat/Input/BadgeRow.tsx b/client/src/components/Chat/Input/BadgeRow.tsx index 14309acf13..0de28cb347 100644 --- a/client/src/components/Chat/Input/BadgeRow.tsx +++ b/client/src/components/Chat/Input/BadgeRow.tsx @@ -1,4 +1,5 @@ import React, { + memo, useState, useRef, useEffect, @@ -12,11 +13,14 @@ import type { LucideIcon } from 'lucide-react'; import type { BadgeItem } from '~/common'; import { useChatBadges } from '~/hooks'; import { Badge } from '~/components/ui'; +import MCPSelect from './MCPSelect'; import store from '~/store'; interface BadgeRowProps { + showMCPServers?: boolean; onChange: (badges: Pick[]) => void; onToggle?: (badgeId: string, currentActive: boolean) => void; + conversationId?: string | null; isInChat: boolean; } @@ -33,7 +37,8 @@ interface BadgeWrapperProps { const BadgeWrapper = React.memo( forwardRef( ({ badge, isEditing, isInChat, onToggle, onDelete, onMouseDown, badgeRefs }, ref) => { - const isActive = badge.atom ? useRecoilValue(badge.atom) : false; + const atomBadge = useRecoilValue(badge.atom); + const isActive = badge.atom ? atomBadge : false; return (
{ } }; -export function BadgeRow({ onChange, onToggle, isInChat }: BadgeRowProps) { +function BadgeRow({ showMCPServers, conversationId, onChange, onToggle, isInChat }: BadgeRowProps) { const [orderedBadges, setOrderedBadges] = useState([]); const [dragState, dispatch] = useReducer(dragReducer, { draggedBadge: null, @@ -340,6 +345,7 @@ export function BadgeRow({ onChange, onToggle, isInChat }: BadgeRowProps) { />
)} + {showMCPServers === true && } {ghostBadge && (
); } + +export default memo(BadgeRow); diff --git a/client/src/components/Chat/Input/ChatForm.tsx b/client/src/components/Chat/Input/ChatForm.tsx index 8d8714f68f..007c139d76 100644 --- a/client/src/components/Chat/Input/ChatForm.tsx +++ b/client/src/components/Chat/Input/ChatForm.tsx @@ -1,7 +1,7 @@ import { memo, useRef, useMemo, useEffect, useState, useCallback } from 'react'; import { useWatch } from 'react-hook-form'; import { useRecoilState, useRecoilValue } from 'recoil'; -import { Constants, isAssistantsEndpoint } from 'librechat-data-provider'; +import { Constants, isAssistantsEndpoint, isAgentsEndpoint } from 'librechat-data-provider'; import { useChatContext, useChatFormContext, @@ -28,8 +28,8 @@ import CollapseChat from './CollapseChat'; import StreamAudio from './StreamAudio'; import StopButton from './StopButton'; import SendButton from './SendButton'; -import { BadgeRow } from './BadgeRow'; import EditBadges from './EditBadges'; +import BadgeRow from './BadgeRow'; import Mention from './Mention'; import store from '~/store'; @@ -289,7 +289,9 @@ const ChatForm = memo(({ index = 0 }: { index?: number }) => {
setBadges(newBadges)} + showMCPServers={!isAgentsEndpoint(endpoint) && !isAssistantsEndpoint(endpoint)} + conversationId={conversation?.conversationId ?? Constants.NEW_CONVO} + onChange={setBadges} isInChat={ Array.isArray(conversation?.messages) && conversation.messages.length >= 1 } diff --git a/client/src/components/Chat/Input/MCPSelect.tsx b/client/src/components/Chat/Input/MCPSelect.tsx new file mode 100644 index 0000000000..adbdc29750 --- /dev/null +++ b/client/src/components/Chat/Input/MCPSelect.tsx @@ -0,0 +1,82 @@ +import React, { memo, useCallback } from 'react'; +import { useRecoilState } from 'recoil'; +import { Constants, EModelEndpoint, LocalStorageKeys } from 'librechat-data-provider'; +import { useAvailableToolsQuery } from '~/data-provider'; +import useLocalStorage from '~/hooks/useLocalStorageAlt'; +import MultiSelect from '~/components/ui/MultiSelect'; +import { ephemeralAgentByConvoId } from '~/store'; +import MCPIcon from '~/components/ui/MCPIcon'; +import { useLocalize } from '~/hooks'; + +function MCPSelect({ conversationId }: { conversationId?: string | null }) { + const localize = useLocalize(); + const key = conversationId ?? Constants.NEW_CONVO; + const [ephemeralAgent, setEphemeralAgent] = useRecoilState(ephemeralAgentByConvoId(key)); + const setSelectedValues = useCallback( + (values: string[] | null | undefined) => { + if (!values) { + return; + } + if (!Array.isArray(values)) { + return; + } + setEphemeralAgent((prev) => ({ + ...prev, + mcp: values, + })); + }, + [setEphemeralAgent], + ); + const [mcpValues, setMCPValues] = useLocalStorage( + `${LocalStorageKeys.LAST_MCP_}${key}`, + ephemeralAgent?.mcp ?? [], + setSelectedValues, + ); + const { data: mcpServers } = useAvailableToolsQuery(EModelEndpoint.agents, { + select: (data) => { + const serverNames = new Set(); + data.forEach((tool) => { + if (tool.pluginKey.includes(Constants.mcp_delimiter)) { + const parts = tool.pluginKey.split(Constants.mcp_delimiter); + serverNames.add(parts[parts.length - 1]); + } + }); + return [...serverNames]; + }, + }); + + const renderSelectedValues = useCallback( + (values: string[], placeholder?: string) => { + if (values.length === 0) { + return placeholder || localize('com_ui_select') + '...'; + } + if (values.length === 1) { + return values[0]; + } + return localize('com_ui_x_selected', { 0: values.length }); + }, + [localize], + ); + + if (!mcpServers || mcpServers.length === 0) { + return null; + } + + return ( + } + selectItemsClassName="border border-blue-600/50 bg-blue-500/10 hover:bg-blue-700/10" + selectClassName="group relative inline-flex items-center justify-center md:justify-start gap-1.5 rounded-full border border-border-medium text-sm font-medium transition-shadow md:w-full size-9 p-2 md:p-3 bg-surface-chat shadow-sm hover:bg-surface-hover hover:shadow-md active:shadow-inner" + /> + ); +} + +export default memo(MCPSelect); diff --git a/client/src/components/ui/MCPIcon.tsx b/client/src/components/ui/MCPIcon.tsx new file mode 100644 index 0000000000..ff4ca27350 --- /dev/null +++ b/client/src/components/ui/MCPIcon.tsx @@ -0,0 +1,31 @@ +export default function MCPIcon({ className }: { className?: string }) { + return ( + + + + + + ); +} diff --git a/client/src/components/ui/MultiSelect.tsx b/client/src/components/ui/MultiSelect.tsx new file mode 100644 index 0000000000..9de2780721 --- /dev/null +++ b/client/src/components/ui/MultiSelect.tsx @@ -0,0 +1,128 @@ +import React, { useRef } from 'react'; +import { + Select, + SelectArrow, + SelectItem, + SelectItemCheck, + SelectLabel, + SelectPopover, + SelectProvider, +} from '@ariakit/react'; +import { cn } from '~/utils'; + +interface MultiSelectProps { + items: T[]; + label?: string; + placeholder?: string; + defaultSelectedValues?: T[]; + onSelectedValuesChange?: (values: T[]) => void; + renderSelectedValues?: (values: T[], placeholder?: string) => React.ReactNode; + className?: string; + itemClassName?: string; + labelClassName?: string; + selectClassName?: string; + selectIcon?: React.ReactNode; + popoverClassName?: string; + selectItemsClassName?: string; + selectedValues: T[]; + setSelectedValues: (values: T[]) => void; +} + +function defaultRender(values: T[], placeholder?: string) { + if (values.length === 0) { + return placeholder || 'Select...'; + } + if (values.length === 1) { + return values[0]; + } + return `${values.length} items selected`; +} + +export default function MultiSelect({ + items, + label, + placeholder = 'Select...', + defaultSelectedValues = [], + onSelectedValuesChange, + renderSelectedValues = defaultRender, + className, + selectIcon, + itemClassName, + labelClassName, + selectClassName, + popoverClassName, + selectItemsClassName, + selectedValues = [], + setSelectedValues, +}: MultiSelectProps) { + const selectRef = useRef(null); + // const [selectedValues, setSelectedValues] = React.useState(defaultSelectedValues); + + const handleValueChange = (values: T[]) => { + setSelectedValues(values); + if (onSelectedValuesChange) { + onSelectedValuesChange(values); + } + }; + + return ( +
+ + {label && ( + + {label} + + )} + + + {items.map((value) => ( + + + {value} + + ))} + + +
+ ); +} diff --git a/client/src/components/ui/index.ts b/client/src/components/ui/index.ts index 0e9ee85c5d..8d9eed0c85 100644 --- a/client/src/components/ui/index.ts +++ b/client/src/components/ui/index.ts @@ -27,6 +27,7 @@ export * from './Pagination'; export * from './Progress'; export * from './InputOTP'; export { default as Badge } from './Badge'; +export { default as MCPIcon } from './MCPIcon'; export { default as Combobox } from './Combobox'; export { default as Dropdown } from './Dropdown'; export { default as SplitText } from './SplitText'; diff --git a/client/src/data-provider/queries.ts b/client/src/data-provider/queries.ts index b88d0797e9..96f7a87e5f 100644 --- a/client/src/data-provider/queries.ts +++ b/client/src/data-provider/queries.ts @@ -191,9 +191,10 @@ export const useConversationTagsQuery = ( /** * Hook for getting all available tools for Assistants */ -export const useAvailableToolsQuery = ( +export const useAvailableToolsQuery = ( endpoint: t.AssistantsEndpoint | EModelEndpoint.agents, -): QueryObserverResult => { + config?: UseQueryOptions, +): QueryObserverResult => { const queryClient = useQueryClient(); const endpointsConfig = queryClient.getQueryData([QueryKeys.endpoints]); const keyExpiry = queryClient.getQueryData([QueryKeys.name, endpoint]); @@ -202,7 +203,7 @@ export const useAvailableToolsQuery = ( const enabled = !!endpointsConfig?.[endpoint] && keyProvided; const version: string | number | undefined = endpointsConfig?.[endpoint]?.version ?? defaultAssistantsVersion[endpoint]; - return useQuery( + return useQuery( [QueryKeys.tools], () => dataService.getAvailableTools(endpoint, version), { @@ -210,6 +211,7 @@ export const useAvailableToolsQuery = ( refetchOnReconnect: false, refetchOnMount: false, enabled, + ...config, }, ); }; diff --git a/client/src/hooks/Chat/useChatFunctions.ts b/client/src/hooks/Chat/useChatFunctions.ts index 7e4c30c8ff..d511a13597 100644 --- a/client/src/hooks/Chat/useChatFunctions.ts +++ b/client/src/hooks/Chat/useChatFunctions.ts @@ -20,10 +20,10 @@ import type { SetterOrUpdater } from 'recoil'; import type { TAskFunction, ExtendedFile } from '~/common'; import useSetFilesToDelete from '~/hooks/Files/useSetFilesToDelete'; import useGetSender from '~/hooks/Conversations/useGetSender'; +import store, { useGetEphemeralAgent } from '~/store'; import { getArtifactsMode } from '~/utils/artifacts'; import { getEndpointField, logger } from '~/utils'; import useUserKey from '~/hooks/Input/useUserKey'; -import store from '~/store'; const logChatRequest = (request: Record) => { logger.log('=====================================\nAsk function called with:'); @@ -64,6 +64,7 @@ export default function useChatFunctions({ setSubmission: SetterOrUpdater; setLatestMessage?: SetterOrUpdater; }) { + const getEphemeralAgent = useGetEphemeralAgent(); const codeArtifacts = useRecoilValue(store.codeArtifacts); const includeShadcnui = useRecoilValue(store.includeShadcnui); const customPromptMode = useRecoilValue(store.customPromptMode); @@ -118,6 +119,7 @@ export default function useChatFunctions({ return; } + const ephemeralAgent = getEphemeralAgent(conversationId ?? Constants.NEW_CONVO); const isEditOrContinue = isEdited || isContinued; let currentMessages: TMessage[] | null = overrideMessages ?? getMessages() ?? []; @@ -297,6 +299,7 @@ export default function useChatFunctions({ isRegenerate, initialResponse, isTemporary, + ephemeralAgent, }; if (isRegenerate) { diff --git a/client/src/hooks/SSE/useEventHandlers.ts b/client/src/hooks/SSE/useEventHandlers.ts index 55d1488197..6eb6941c8f 100644 --- a/client/src/hooks/SSE/useEventHandlers.ts +++ b/client/src/hooks/SSE/useEventHandlers.ts @@ -31,11 +31,11 @@ import { } from '~/utils'; import useAttachmentHandler from '~/hooks/SSE/useAttachmentHandler'; import useContentHandler from '~/hooks/SSE/useContentHandler'; +import store, { useApplyNewAgentTemplate } from '~/store'; import useStepHandler from '~/hooks/SSE/useStepHandler'; import { useAuthContext } from '~/hooks/AuthContext'; import { MESSAGE_UPDATE_INTERVAL } from '~/common'; import { useLiveAnnouncer } from '~/Providers'; -import store from '~/store'; type TSyncData = { sync: boolean; @@ -140,8 +140,9 @@ export default function useEventHandlers({ resetLatestMessage, }: EventHandlerParams) { const queryClient = useQueryClient(); - const setAbortScroll = useSetRecoilState(store.abortScroll); const { announcePolite } = useLiveAnnouncer(); + const applyAgentTemplate = useApplyNewAgentTemplate(); + const setAbortScroll = useSetRecoilState(store.abortScroll); const lastAnnouncementTimeRef = useRef(Date.now()); const { conversationId: paramId } = useParams(); @@ -364,6 +365,9 @@ export default function useEventHandlers({ }); let update = {} as TConversation; + if (conversationId) { + applyAgentTemplate(conversationId, submission.conversation.conversationId); + } if (setConversation && !isAddedRequest) { setConversation((prevState) => { let title = prevState?.title; diff --git a/client/src/hooks/useLocalStorageAlt.tsx b/client/src/hooks/useLocalStorageAlt.tsx new file mode 100644 index 0000000000..465d62c70b --- /dev/null +++ b/client/src/hooks/useLocalStorageAlt.tsx @@ -0,0 +1,61 @@ +/* `useLocalStorage` + * + * Features: + * - JSON Serializing + * - Also value will be updated everywhere, when value updated (via `storage` event) + */ + +import { useEffect, useState } from 'react'; + +export default function useLocalStorage( + key: string, + defaultValue: T, + globalSetState?: (value: T) => void, +): [T, (value: T) => void] { + const [value, setValue] = useState(defaultValue); + + useEffect(() => { + const item = localStorage.getItem(key); + + if (!item) { + localStorage.setItem(key, JSON.stringify(defaultValue)); + } + + const initialValue = item ? JSON.parse(item) : defaultValue; + setValue(initialValue); + if (globalSetState) { + globalSetState(initialValue); + } + + function handler(e: StorageEvent) { + if (e.key !== key) { + return; + } + + const lsi = localStorage.getItem(key); + setValue(JSON.parse(lsi ?? '')); + } + + window.addEventListener('storage', handler); + + return () => { + window.removeEventListener('storage', handler); + }; + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [key, globalSetState]); + + const setValueWrap = (value: T) => { + try { + setValue(value); + localStorage.setItem(key, JSON.stringify(value)); + if (typeof window !== 'undefined') { + window.dispatchEvent(new StorageEvent('storage', { key })); + } + globalSetState?.(value); + } catch (e) { + console.error(e); + } + }; + + return [value, setValueWrap]; +} diff --git a/client/src/locales/en/translation.json b/client/src/locales/en/translation.json index 88b957d5a7..67c7f9360b 100644 --- a/client/src/locales/en/translation.json +++ b/client/src/locales/en/translation.json @@ -689,6 +689,7 @@ "com_ui_include_shadcnui_agent": "Include shadcn/ui instructions", "com_ui_input": "Input", "com_ui_instructions": "Instructions", + "com_ui_x_selected": "{{0}} selected", "com_ui_late_night": "Happy late night", "com_ui_latest_footer": "Every AI for Everyone.", "com_ui_latest_production_version": "Latest production version", @@ -701,6 +702,7 @@ "com_ui_logo": "{{0}} Logo", "com_ui_manage": "Manage", "com_ui_max_tags": "Maximum number allowed is {{0}}, using latest values.", + "com_ui_mcp_servers": "MCP Servers", "com_ui_mention": "Mention an endpoint, assistant, or preset to quickly switch to it", "com_ui_min_tags": "Cannot remove more values, a minimum of {{0}} are required.", "com_ui_misc": "Misc.", @@ -855,12 +857,6 @@ "com_ui_write": "Writing", "com_ui_yes": "Yes", "com_ui_zoom": "Zoom", - "com_ui_save_badge_changes": "Save badge changes?", - "com_ui_late_night": "Happy late night", - "com_ui_weekend_morning": "Happy weekend", - "com_ui_good_morning": "Good morning", - "com_ui_good_afternoon": "Good afternoon", - "com_ui_good_evening": "Good evening", "com_endpoint_deprecated": "Deprecated", "com_endpoint_deprecated_info": "This endpoint is deprecated and may be removed in future versions, please use the agent endpoint instead", "com_endpoint_deprecated_info_a11y": "The plugin endpoint is deprecated and may be removed in future versions, please use the agent endpoint instead", diff --git a/client/src/store/agents.ts b/client/src/store/agents.ts new file mode 100644 index 0000000000..c539345ec0 --- /dev/null +++ b/client/src/store/agents.ts @@ -0,0 +1,88 @@ +import { Constants } from 'librechat-data-provider'; +import { atomFamily, useRecoilCallback } from 'recoil'; +import type { TEphemeralAgent } from 'librechat-data-provider'; +import { logger } from '~/utils'; + +export const ephemeralAgentByConvoId = atomFamily({ + key: 'ephemeralAgentByConvoId', + default: null, + effects: [ + ({ onSet, node }) => { + onSet(async (newValue) => { + const conversationId = node.key.split('__')[1]?.replaceAll('"', ''); + logger.log('agents', 'Setting ephemeral agent:', { conversationId, newValue }); + }); + }, + ] as const, +}); + +/** + * Creates a callback function to apply the ephemeral agent state + * from the "new" conversation template to a specified conversation ID. + */ +export function useApplyNewAgentTemplate() { + const applyTemplate = useRecoilCallback( + ({ snapshot, set }) => + async (targetId: string, _sourceId: string | null = Constants.NEW_CONVO) => { + const sourceId = _sourceId || Constants.NEW_CONVO; + logger.log('agents', `Attempting to apply template from "${sourceId}" to "${targetId}"`); + + if (targetId === sourceId) { + logger.warn('agents', `Attempted to apply template to itself ("${sourceId}"). Skipping.`); + return; + } + + try { + // 1. Get the current agent state from the "new" conversation template using snapshot + // getPromise reads the value without subscribing + const agentTemplate = await snapshot.getPromise(ephemeralAgentByConvoId(sourceId)); + + // 2. Check if a template state actually exists + if (agentTemplate) { + logger.log('agents', `Applying agent template to "${targetId}":`, agentTemplate); + // 3. Set the state for the target conversation ID using the template value + set(ephemeralAgentByConvoId(targetId), agentTemplate); + } else { + // 4. Handle the case where the "new" template has no agent state (is null) + logger.warn( + 'agents', + `Agent template from "${sourceId}" is null or unset. Setting agent for "${targetId}" to null.`, + ); + // Explicitly set to null (or a default empty state if preferred) + set(ephemeralAgentByConvoId(targetId), null); + // Example: Or set to a default empty state: + // set(ephemeralAgentByConvoId(targetId), { mcp: [] }); + } + } catch (error) { + logger.error( + 'agents', + `Error applying agent template from "${sourceId}" to "${targetId}":`, + error, + ); + set(ephemeralAgentByConvoId(targetId), null); + } + }, + [], + ); + + return applyTemplate; +} + +/** + * Creates a callback function to get the current ephemeral agent state + * for a specified conversation ID without subscribing the component. + * Returns a Loadable object synchronously. + */ +export function useGetEphemeralAgent() { + const getEphemeralAgent = useRecoilCallback( + ({ snapshot }) => + (conversationId: string): TEphemeralAgent | null => { + logger.log('agents', `[useGetEphemeralAgent] Getting loadable for ID: ${conversationId}`); + const agentLoadable = snapshot.getLoadable(ephemeralAgentByConvoId(conversationId)); + return agentLoadable.contents as TEphemeralAgent | null; + }, + [], + ); + + return getEphemeralAgent; +} diff --git a/client/src/store/index.ts b/client/src/store/index.ts index af326ae890..7b7e0f0831 100644 --- a/client/src/store/index.ts +++ b/client/src/store/index.ts @@ -12,6 +12,7 @@ import lang from './language'; import settings from './settings'; import misc from './misc'; import isTemporary from './temporary'; +export * from './agents'; export default { ...artifacts, diff --git a/client/src/utils/localStorage.ts b/client/src/utils/localStorage.ts index 3c44551b21..35bd12232f 100644 --- a/client/src/utils/localStorage.ts +++ b/client/src/utils/localStorage.ts @@ -31,6 +31,7 @@ export function clearLocalStorage(skipFirst?: boolean) { return; } if ( + key.startsWith(LocalStorageKeys.LAST_MCP_) || key.startsWith(LocalStorageKeys.ASST_ID_PREFIX) || key.startsWith(LocalStorageKeys.AGENT_ID_PREFIX) || key.startsWith(LocalStorageKeys.LAST_CONVO_SETUP) || diff --git a/package-lock.json b/package-lock.json index 153b969ffd..17e53223c3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -43615,7 +43615,7 @@ }, "packages/data-provider": { "name": "librechat-data-provider", - "version": "0.7.789", + "version": "0.7.790", "license": "ISC", "dependencies": { "axios": "^1.8.2", diff --git a/packages/data-provider/package.json b/packages/data-provider/package.json index 4326608983..64f120503c 100644 --- a/packages/data-provider/package.json +++ b/packages/data-provider/package.json @@ -1,6 +1,6 @@ { "name": "librechat-data-provider", - "version": "0.7.789", + "version": "0.7.790", "description": "data services for librechat apps", "main": "dist/index.js", "module": "dist/index.es.js", diff --git a/packages/data-provider/src/config.ts b/packages/data-provider/src/config.ts index d59d93f6b7..1b8d815a7b 100644 --- a/packages/data-provider/src/config.ts +++ b/packages/data-provider/src/config.ts @@ -1246,6 +1246,8 @@ export enum Constants { GLOBAL_PROJECT_NAME = 'instance', /** Delimiter for MCP tools */ mcp_delimiter = '_mcp_', + /** Placeholder Agent ID for Ephemeral Agents */ + EPHEMERAL_AGENT_ID = 'ephemeral', } export enum LocalStorageKeys { @@ -1281,6 +1283,8 @@ export enum LocalStorageKeys { ENABLE_USER_MSG_MARKDOWN = 'enableUserMsgMarkdown', /** Key for displaying analysis tool code input */ SHOW_ANALYSIS_CODE = 'showAnalysisCode', + /** Last selected MCP values per conversation ID */ + LAST_MCP_ = 'LAST_MCP_', } export enum ForkOptions { diff --git a/packages/data-provider/src/createPayload.ts b/packages/data-provider/src/createPayload.ts index a03d7db032..19d94cec4f 100644 --- a/packages/data-provider/src/createPayload.ts +++ b/packages/data-provider/src/createPayload.ts @@ -3,8 +3,15 @@ import { EndpointURLs } from './config'; import * as s from './schemas'; export default function createPayload(submission: t.TSubmission) { - const { conversation, userMessage, endpointOption, isEdited, isContinued, isTemporary } = - submission; + const { + conversation, + userMessage, + endpointOption, + isEdited, + isContinued, + isTemporary, + ephemeralAgent, + } = submission; const { conversationId } = s.tConvoUpdateSchema.parse(conversation); const { endpoint, endpointType } = endpointOption as { endpoint: s.EModelEndpoint; @@ -12,16 +19,20 @@ export default function createPayload(submission: t.TSubmission) { }; let server = EndpointURLs[endpointType ?? endpoint]; + const isEphemeralAgent = (ephemeralAgent?.mcp?.length ?? 0) > 0 && !s.isAgentsEndpoint(endpoint); if (isEdited && s.isAssistantsEndpoint(endpoint)) { server += '/modify'; } else if (isEdited) { server = server.replace('/ask/', '/edit/'); + } else if (isEphemeralAgent) { + server = `${EndpointURLs[s.EModelEndpoint.agents]}/${endpoint}`; } const payload: t.TPayload = { ...userMessage, ...endpointOption, + ephemeralAgent: isEphemeralAgent ? ephemeralAgent : undefined, isContinued: !!(isEdited && isContinued), conversationId, isTemporary, diff --git a/packages/data-provider/src/parsers.ts b/packages/data-provider/src/parsers.ts index 21040a70d5..a644f7301c 100644 --- a/packages/data-provider/src/parsers.ts +++ b/packages/data-provider/src/parsers.ts @@ -13,8 +13,6 @@ import { // agentsSchema, compactAgentsSchema, compactGoogleSchema, - compactChatGPTSchema, - chatGPTBrowserSchema, compactPluginsSchema, compactAssistantSchema, } from './schemas'; @@ -26,19 +24,19 @@ type EndpointSchema = | typeof openAISchema | typeof googleSchema | typeof anthropicSchema - | typeof chatGPTBrowserSchema | typeof gptPluginsSchema | typeof assistantSchema | typeof compactAgentsSchema | typeof bedrockInputSchema; -const endpointSchemas: Record = { +type EndpointSchemaKey = Exclude; + +const endpointSchemas: Record = { [EModelEndpoint.openAI]: openAISchema, [EModelEndpoint.azureOpenAI]: openAISchema, [EModelEndpoint.custom]: openAISchema, [EModelEndpoint.google]: googleSchema, [EModelEndpoint.anthropic]: anthropicSchema, - [EModelEndpoint.chatGPTBrowser]: chatGPTBrowserSchema, [EModelEndpoint.gptPlugins]: gptPluginsSchema, [EModelEndpoint.assistants]: assistantSchema, [EModelEndpoint.azureAssistants]: assistantSchema, @@ -167,8 +165,8 @@ export const parseConvo = ({ conversation, possibleValues, }: { - endpoint: EModelEndpoint; - endpointType?: EModelEndpoint | null; + endpoint: EndpointSchemaKey; + endpointType?: EndpointSchemaKey | null; conversation: Partial | null; possibleValues?: TPossibleValues; // TODO: POC for default schema @@ -252,7 +250,7 @@ export const getResponseSender = (endpointOption: t.TEndpointOption): string => return modelLabel; } else if (model && extractOmniVersion(model)) { return extractOmniVersion(model); - } else if (model && model.includes('mistral')) { + } else if (model && (model.includes('mistral') || model.includes('codestral'))) { return 'Mistral'; } else if (model && model.includes('gpt-')) { const gptVersion = extractGPTVersion(model); @@ -288,7 +286,7 @@ export const getResponseSender = (endpointOption: t.TEndpointOption): string => return chatGptLabel; } else if (model && extractOmniVersion(model)) { return extractOmniVersion(model); - } else if (model && model.includes('mistral')) { + } else if (model && (model.includes('mistral') || model.includes('codestral'))) { return 'Mistral'; } else if (model && model.includes('gpt-')) { const gptVersion = extractGPTVersion(model); @@ -309,11 +307,10 @@ type CompactEndpointSchema = | typeof compactAgentsSchema | typeof compactGoogleSchema | typeof anthropicSchema - | typeof compactChatGPTSchema | typeof bedrockInputSchema | typeof compactPluginsSchema; -const compactEndpointSchemas: Record = { +const compactEndpointSchemas: Record = { [EModelEndpoint.openAI]: openAISchema, [EModelEndpoint.azureOpenAI]: openAISchema, [EModelEndpoint.custom]: openAISchema, @@ -323,7 +320,6 @@ const compactEndpointSchemas: Record = { [EModelEndpoint.google]: compactGoogleSchema, [EModelEndpoint.bedrock]: bedrockInputSchema, [EModelEndpoint.anthropic]: anthropicSchema, - [EModelEndpoint.chatGPTBrowser]: compactChatGPTSchema, [EModelEndpoint.gptPlugins]: compactPluginsSchema, }; @@ -333,8 +329,8 @@ export const parseCompactConvo = ({ conversation, possibleValues, }: { - endpoint?: EModelEndpoint; - endpointType?: EModelEndpoint | null; + endpoint?: EndpointSchemaKey; + endpointType?: EndpointSchemaKey | null; conversation: Partial; possibleValues?: TPossibleValues; // TODO: POC for default schema @@ -371,7 +367,10 @@ export const parseCompactConvo = ({ return convo; }; -export function parseTextParts(contentParts: a.TMessageContentParts[]): string { +export function parseTextParts( + contentParts: a.TMessageContentParts[], + skipReasoning: boolean = false, +): string { let result = ''; for (const part of contentParts) { @@ -390,7 +389,7 @@ export function parseTextParts(contentParts: a.TMessageContentParts[]): string { result += ' '; } result += textValue; - } else if (part.type === ContentTypes.THINK) { + } else if (part.type === ContentTypes.THINK && !skipReasoning) { const textValue = typeof part.think === 'string' ? part.think : ''; if ( result.length > 0 && diff --git a/packages/data-provider/src/schemas.ts b/packages/data-provider/src/schemas.ts index 66609ff6ba..b923a1a467 100644 --- a/packages/data-provider/src/schemas.ts +++ b/packages/data-provider/src/schemas.ts @@ -752,22 +752,23 @@ export const tConversationTagSchema = z.object({ }); export type TConversationTag = z.infer; -export const googleSchema = tConversationSchema - .pick({ - model: true, - modelLabel: true, - promptPrefix: true, - examples: true, - temperature: true, - maxOutputTokens: true, - artifacts: true, - topP: true, - topK: true, - iconURL: true, - greeting: true, - spec: true, - maxContextTokens: true, - }) +export const googleBaseSchema = tConversationSchema.pick({ + model: true, + modelLabel: true, + promptPrefix: true, + examples: true, + temperature: true, + maxOutputTokens: true, + artifacts: true, + topP: true, + topK: true, + iconURL: true, + greeting: true, + spec: true, + maxContextTokens: true, +}); + +export const googleSchema = googleBaseSchema .transform((obj: Partial) => removeNullishValues(obj)) .catch(() => ({})); @@ -790,36 +791,25 @@ export const googleGenConfigSchema = z .strip() .optional(); -export const chatGPTBrowserSchema = tConversationSchema - .pick({ - model: true, - }) - .transform((obj) => ({ - ...obj, - model: obj.model ?? 'text-davinci-002-render-sha', - })) - .catch(() => ({ - model: 'text-davinci-002-render-sha', - })); +const gptPluginsBaseSchema = tConversationSchema.pick({ + model: true, + modelLabel: true, + chatGptLabel: true, + promptPrefix: true, + temperature: true, + artifacts: true, + top_p: true, + presence_penalty: true, + frequency_penalty: true, + tools: true, + agentOptions: true, + iconURL: true, + greeting: true, + spec: true, + maxContextTokens: true, +}); -export const gptPluginsSchema = tConversationSchema - .pick({ - model: true, - modelLabel: true, - chatGptLabel: true, - promptPrefix: true, - temperature: true, - artifacts: true, - top_p: true, - presence_penalty: true, - frequency_penalty: true, - tools: true, - agentOptions: true, - iconURL: true, - greeting: true, - spec: true, - maxContextTokens: true, - }) +export const gptPluginsSchema = gptPluginsBaseSchema .transform((obj) => { const result = { ...obj, @@ -889,18 +879,19 @@ export function removeNullishValues>( return newObj; } -export const assistantSchema = tConversationSchema - .pick({ - model: true, - assistant_id: true, - instructions: true, - artifacts: true, - promptPrefix: true, - iconURL: true, - greeting: true, - spec: true, - append_current_datetime: true, - }) +const assistantBaseSchema = tConversationSchema.pick({ + model: true, + assistant_id: true, + instructions: true, + artifacts: true, + promptPrefix: true, + iconURL: true, + greeting: true, + spec: true, + append_current_datetime: true, +}); + +export const assistantSchema = assistantBaseSchema .transform((obj) => ({ ...obj, model: obj.model ?? openAISettings.model.default, @@ -923,37 +914,39 @@ export const assistantSchema = tConversationSchema append_current_datetime: false, })); -export const compactAssistantSchema = tConversationSchema - .pick({ - model: true, - assistant_id: true, - instructions: true, - promptPrefix: true, - artifacts: true, - iconURL: true, - greeting: true, - spec: true, - }) +const compactAssistantBaseSchema = tConversationSchema.pick({ + model: true, + assistant_id: true, + instructions: true, + promptPrefix: true, + artifacts: true, + iconURL: true, + greeting: true, + spec: true, +}); + +export const compactAssistantSchema = compactAssistantBaseSchema .transform((obj) => removeNullishValues(obj)) .catch(() => ({})); -export const agentsSchema = tConversationSchema - .pick({ - model: true, - modelLabel: true, - temperature: true, - top_p: true, - presence_penalty: true, - frequency_penalty: true, - resendFiles: true, - imageDetail: true, - agent_id: true, - instructions: true, - promptPrefix: true, - iconURL: true, - greeting: true, - maxContextTokens: true, - }) +export const agentsBaseSchema = tConversationSchema.pick({ + model: true, + modelLabel: true, + temperature: true, + top_p: true, + presence_penalty: true, + frequency_penalty: true, + resendFiles: true, + imageDetail: true, + agent_id: true, + instructions: true, + promptPrefix: true, + iconURL: true, + greeting: true, + maxContextTokens: true, +}); + +export const agentsSchema = agentsBaseSchema .transform((obj) => ({ ...obj, model: obj.model ?? agentsSettings.model.default, @@ -989,46 +982,32 @@ export const agentsSchema = tConversationSchema maxContextTokens: undefined, })); -export const openAISchema = tConversationSchema - .pick({ - model: true, - modelLabel: true, - chatGptLabel: true, - promptPrefix: true, - temperature: true, - top_p: true, - presence_penalty: true, - frequency_penalty: true, - resendFiles: true, - artifacts: true, - imageDetail: true, - stop: true, - iconURL: true, - greeting: true, - spec: true, - maxContextTokens: true, - max_tokens: true, - reasoning_effort: true, - }) +export const openAIBaseSchema = tConversationSchema.pick({ + model: true, + modelLabel: true, + chatGptLabel: true, + promptPrefix: true, + temperature: true, + top_p: true, + presence_penalty: true, + frequency_penalty: true, + resendFiles: true, + artifacts: true, + imageDetail: true, + stop: true, + iconURL: true, + greeting: true, + spec: true, + maxContextTokens: true, + max_tokens: true, + reasoning_effort: true, +}); + +export const openAISchema = openAIBaseSchema .transform((obj: Partial) => removeNullishValues(obj)) .catch(() => ({})); -export const compactGoogleSchema = tConversationSchema - .pick({ - model: true, - modelLabel: true, - promptPrefix: true, - examples: true, - temperature: true, - maxOutputTokens: true, - artifacts: true, - topP: true, - topK: true, - iconURL: true, - greeting: true, - spec: true, - maxContextTokens: true, - }) +export const compactGoogleSchema = googleBaseSchema .transform((obj) => { const newObj: Partial = { ...obj }; if (newObj.temperature === google.temperature.default) { @@ -1048,55 +1027,30 @@ export const compactGoogleSchema = tConversationSchema }) .catch(() => ({})); -export const anthropicSchema = tConversationSchema - .pick({ - model: true, - modelLabel: true, - promptPrefix: true, - temperature: true, - maxOutputTokens: true, - topP: true, - topK: true, - resendFiles: true, - promptCache: true, - thinking: true, - thinkingBudget: true, - artifacts: true, - iconURL: true, - greeting: true, - spec: true, - maxContextTokens: true, - }) +export const anthropicBaseSchema = tConversationSchema.pick({ + model: true, + modelLabel: true, + promptPrefix: true, + temperature: true, + maxOutputTokens: true, + topP: true, + topK: true, + resendFiles: true, + promptCache: true, + thinking: true, + thinkingBudget: true, + artifacts: true, + iconURL: true, + greeting: true, + spec: true, + maxContextTokens: true, +}); + +export const anthropicSchema = anthropicBaseSchema .transform((obj) => removeNullishValues(obj)) .catch(() => ({})); -export const compactChatGPTSchema = tConversationSchema - .pick({ - model: true, - }) - .transform((obj) => { - const newObj: Partial = { ...obj }; - return removeNullishValues(newObj); - }) - .catch(() => ({})); - -export const compactPluginsSchema = tConversationSchema - .pick({ - model: true, - modelLabel: true, - chatGptLabel: true, - promptPrefix: true, - temperature: true, - top_p: true, - presence_penalty: true, - frequency_penalty: true, - tools: true, - agentOptions: true, - iconURL: true, - greeting: true, - spec: true, - maxContextTokens: true, - }) +export const compactPluginsSchema = gptPluginsBaseSchema .transform((obj) => { const newObj: Partial = { ...obj }; if (newObj.modelLabel === null) { @@ -1149,15 +1103,16 @@ export const tBannerSchema = z.object({ }); export type TBanner = z.infer; -export const compactAgentsSchema = tConversationSchema - .pick({ - spec: true, - // model: true, - iconURL: true, - greeting: true, - agent_id: true, - instructions: true, - additional_instructions: true, - }) +export const compactAgentsBaseSchema = tConversationSchema.pick({ + spec: true, + // model: true, + iconURL: true, + greeting: true, + agent_id: true, + instructions: true, + additional_instructions: true, +}); + +export const compactAgentsSchema = compactAgentsBaseSchema .transform((obj) => removeNullishValues(obj)) .catch(() => ({})); diff --git a/packages/data-provider/src/types.ts b/packages/data-provider/src/types.ts index f278810a5f..dabe89cdb0 100644 --- a/packages/data-provider/src/types.ts +++ b/packages/data-provider/src/types.ts @@ -41,12 +41,17 @@ export type TEndpointOption = { overrideUserMessageId?: string; }; +export type TEphemeralAgent = { + mcp: string[]; +}; + export type TPayload = Partial & Partial & { isContinued: boolean; conversationId: string | null; messages?: TMessages; isTemporary: boolean; + ephemeralAgent?: TEphemeralAgent | null; }; export type TSubmission = { @@ -63,6 +68,7 @@ export type TSubmission = { conversation: Partial; endpointOption: TEndpointOption; clientTimestamp?: string; + ephemeralAgent?: TEphemeralAgent | null; }; export type EventSubmission = Omit & { initialResponse: TMessage }; From 5d668748f9f52866f92ffb4c77c8c39385fde865 Mon Sep 17 00:00:00 2001 From: Danny Avila Date: Tue, 8 Apr 2025 23:18:50 -0400 Subject: [PATCH 6/8] =?UTF-8?q?=F0=9F=97=83=EF=B8=8F=20feat:=20Code=20Inte?= =?UTF-8?q?rpreter=20File=20Persistence=20between=20Sessions=20(#6790)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: Enhance FileContainer with customizable button and container styles, onClick button handling, and type override * refactor: Update file type handling to support partial file objects * refactor: Extract download handling into a custom hook for improved reusability * refactor: Replace LogContent with Stdout component and enhance Attachment rendering for added visibility * feat: Update @librechat/agents to version 2.4.1 for referencing generated files in subsequent code interpreter uses * feat: Add support for tab-separated values (TSV) in mime type handling and improve error logging for regex patterns * chore: Update @librechat/agents to version 2.4.11 for better `session_id` instructions when wanting to persist files between executions * chore: Update @librechat/agents to version 2.4.12 for improved functionality * fix: Enhance argument parsing in useParseArgs to support JSON input and improve code extraction * refactor: Update input handling in useAutoSave to require more than one character before saving to local storage --- api/package.json | 2 +- .../Chat/Input/Files/FileContainer.tsx | 32 +++++++++++++++---- .../Chat/Input/Files/FilePreview.tsx | 2 +- .../Messages/Content/Parts/Attachment.tsx | 23 ++++++++++++- .../Messages/Content/Parts/ExecuteCode.tsx | 25 +++++++++++---- .../Chat/Messages/Content/Parts/LogLink.tsx | 9 ++++-- .../Chat/Messages/Content/Parts/Stdout.tsx | 26 +++++++++++++++ client/src/components/svg/Files/FileIcon.tsx | 2 +- client/src/hooks/Input/useAutoSave.ts | 2 +- client/src/utils/files.ts | 1 + package-lock.json | 14 ++++---- packages/data-provider/src/file-config.ts | 5 +-- 12 files changed, 113 insertions(+), 30 deletions(-) create mode 100644 client/src/components/Chat/Messages/Content/Parts/Stdout.tsx diff --git a/api/package.json b/api/package.json index 644c0ce7a9..19bad78cf8 100644 --- a/api/package.json +++ b/api/package.json @@ -49,7 +49,7 @@ "@langchain/google-genai": "^0.2.2", "@langchain/google-vertexai": "^0.2.3", "@langchain/textsplitters": "^0.1.0", - "@librechat/agents": "^2.4.0", + "@librechat/agents": "^2.4.12", "@librechat/data-schemas": "*", "@waylaidwanderer/fetch-event-source": "^3.0.1", "axios": "^1.8.2", diff --git a/client/src/components/Chat/Input/Files/FileContainer.tsx b/client/src/components/Chat/Input/Files/FileContainer.tsx index 5131061f87..5a22fef256 100644 --- a/client/src/components/Chat/Input/Files/FileContainer.tsx +++ b/client/src/components/Chat/Input/Files/FileContainer.tsx @@ -1,22 +1,40 @@ import type { TFile } from 'librechat-data-provider'; import type { ExtendedFile } from '~/common'; +import { getFileType, cn } from '~/utils'; import FilePreview from './FilePreview'; import RemoveFile from './RemoveFile'; -import { getFileType } from '~/utils'; const FileContainer = ({ file, + overrideType, + buttonClassName, + containerClassName, onDelete, + onClick, }: { - file: ExtendedFile | TFile; + file: Partial; + overrideType?: string; + buttonClassName?: string; + containerClassName?: string; onDelete?: () => void; + onClick?: React.MouseEventHandler; }) => { - const fileType = getFileType(file.type); + const fileType = getFileType(overrideType ?? file.type); return ( -
-
-
+
+
+ {onDelete && }
); diff --git a/client/src/components/Chat/Input/Files/FilePreview.tsx b/client/src/components/Chat/Input/Files/FilePreview.tsx index 02851119af..31226ac65a 100644 --- a/client/src/components/Chat/Input/Files/FilePreview.tsx +++ b/client/src/components/Chat/Input/Files/FilePreview.tsx @@ -11,7 +11,7 @@ const FilePreview = ({ fileType, className = '', }: { - file?: ExtendedFile | TFile; + file?: Partial; fileType: { paths: React.FC; fill: string; diff --git a/client/src/components/Chat/Messages/Content/Parts/Attachment.tsx b/client/src/components/Chat/Messages/Content/Parts/Attachment.tsx index 8bc3192813..e1aeb86a5e 100644 --- a/client/src/components/Chat/Messages/Content/Parts/Attachment.tsx +++ b/client/src/components/Chat/Messages/Content/Parts/Attachment.tsx @@ -1,6 +1,27 @@ +import { memo } from 'react'; import { imageExtRegex } from 'librechat-data-provider'; import type { TAttachment, TFile, TAttachmentMetadata } from 'librechat-data-provider'; +import FileContainer from '~/components/Chat/Input/Files/FileContainer'; import Image from '~/components/Chat/Messages/Content/Image'; +import { useAttachmentLink } from './LogLink'; + +const FileAttachment = memo(({ attachment }: { attachment: TAttachment }) => { + const { handleDownload } = useAttachmentLink({ + href: attachment.filepath, + filename: attachment.filename, + }); + const extension = attachment.filename.split('.').pop(); + + return ( + + ); +}); export default function Attachment({ attachment }: { attachment?: TAttachment }) { if (!attachment) { @@ -21,5 +42,5 @@ export default function Attachment({ attachment }: { attachment?: TAttachment }) /> ); } - return null; + return ; } diff --git a/client/src/components/Chat/Messages/Content/Parts/ExecuteCode.tsx b/client/src/components/Chat/Messages/Content/Parts/ExecuteCode.tsx index 93fdab434e..40ad8c6a66 100644 --- a/client/src/components/Chat/Messages/Content/Parts/ExecuteCode.tsx +++ b/client/src/components/Chat/Messages/Content/Parts/ExecuteCode.tsx @@ -7,7 +7,7 @@ import MarkdownLite from '~/components/Chat/Messages/Content/MarkdownLite'; import { useProgress, useLocalize } from '~/hooks'; import { CodeInProgress } from './CodeProgress'; import Attachment from './Attachment'; -import LogContent from './LogContent'; +import Stdout from './Stdout'; import store from '~/store'; interface ParsedArgs { @@ -17,8 +17,17 @@ interface ParsedArgs { export function useParseArgs(args: string): ParsedArgs { return useMemo(() => { + let parsedArgs: ParsedArgs | string = args; + try { + parsedArgs = JSON.parse(args); + } catch { + // console.error('Failed to parse args:', e); + } + if (typeof parsedArgs === 'object') { + return parsedArgs; + } const langMatch = args.match(/"lang"\s*:\s*"(\w+)"/); - const codeMatch = args.match(/"code"\s*:\s*"(.+?)(?="\s*,\s*"args"|$)/s); + const codeMatch = args.match(/"code"\s*:\s*"(.+?)(?="\s*,\s*"(session_id|args)"|"\s*})/s); let code = ''; if (codeMatch) { @@ -26,7 +35,7 @@ export function useParseArgs(args: string): ParsedArgs { if (code.endsWith('"}')) { code = code.slice(0, -2); } - code = code.replace(/\\n/g, '\n').replace(/\\/g, ''); + code = code.replace(/\\n/g, '\n').replace(/\\"/g, '"').replace(/\\\\/g, '\\'); } return { @@ -99,15 +108,17 @@ export default function ExecuteCode({ color: 'white', }} > -
-                  
-                
+
)}
)} - {attachments?.map((attachment, index) => )} +
+ {attachments?.map((attachment, index) => ( + + ))} +
); } diff --git a/client/src/components/Chat/Messages/Content/Parts/LogLink.tsx b/client/src/components/Chat/Messages/Content/Parts/LogLink.tsx index c1886e7460..590b6d7b8a 100644 --- a/client/src/components/Chat/Messages/Content/Parts/LogLink.tsx +++ b/client/src/components/Chat/Messages/Content/Parts/LogLink.tsx @@ -8,11 +8,11 @@ interface LogLinkProps { children: React.ReactNode; } -const LogLink: React.FC = ({ href, filename, children }) => { +export const useAttachmentLink = ({ href, filename }: Pick) => { const { showToast } = useToastContext(); const { refetch: downloadFile } = useCodeOutputDownload(href); - const handleDownload = async (event: React.MouseEvent) => { + const handleDownload = async (event: React.MouseEvent) => { event.preventDefault(); try { const stream = await downloadFile(); @@ -36,6 +36,11 @@ const LogLink: React.FC = ({ href, filename, children }) => { } }; + return { handleDownload }; +}; + +const LogLink: React.FC = ({ href, filename, children }) => { + const { handleDownload } = useAttachmentLink({ href, filename }); return ( = ({ output = '' }) => { + const processedContent = useMemo(() => { + if (!output) { + return ''; + } + + const parts = output.split('Generated files:'); + return parts[0].trim(); + }, [output]); + + return ( + processedContent && ( +
+        
{processedContent}
+
+ ) + ); +}; + +export default Stdout; diff --git a/client/src/components/svg/Files/FileIcon.tsx b/client/src/components/svg/Files/FileIcon.tsx index 559121efbd..788615171e 100644 --- a/client/src/components/svg/Files/FileIcon.tsx +++ b/client/src/components/svg/Files/FileIcon.tsx @@ -5,7 +5,7 @@ export default function FileIcon({ file, fileType, }: { - file?: ExtendedFile | TFile; + file?: Partial; fileType: { fill: string; paths: React.FC; diff --git a/client/src/hooks/Input/useAutoSave.ts b/client/src/hooks/Input/useAutoSave.ts index bebf54af3f..233a175a53 100644 --- a/client/src/hooks/Input/useAutoSave.ts +++ b/client/src/hooks/Input/useAutoSave.ts @@ -128,7 +128,7 @@ export const useAutoSave = ({ const handleInput = debounce((e: React.ChangeEvent) => { const value = e.target.value; - if (value) { + if (value && value.length > 1) { localStorage.setItem( `${LocalStorageKeys.TEXT_DRAFT}${conversationId}`, encodeBase64(value), diff --git a/client/src/utils/files.ts b/client/src/utils/files.ts index 337d1cc84f..3ca07e51d0 100644 --- a/client/src/utils/files.ts +++ b/client/src/utils/files.ts @@ -48,6 +48,7 @@ export const fileTypes = { title: 'File', }, text: textDocument, + txt: textDocument, // application:, /* Partial matches */ diff --git a/package-lock.json b/package-lock.json index 17e53223c3..158ec0e959 100644 --- a/package-lock.json +++ b/package-lock.json @@ -65,7 +65,7 @@ "@langchain/google-genai": "^0.2.2", "@langchain/google-vertexai": "^0.2.3", "@langchain/textsplitters": "^0.1.0", - "@librechat/agents": "^2.4.0", + "@librechat/agents": "^2.4.12", "@librechat/data-schemas": "*", "@waylaidwanderer/fetch-event-source": "^3.0.1", "axios": "^1.8.2", @@ -17629,9 +17629,9 @@ } }, "node_modules/@langchain/langgraph-sdk": { - "version": "0.0.62", - "resolved": "https://registry.npmjs.org/@langchain/langgraph-sdk/-/langgraph-sdk-0.0.62.tgz", - "integrity": "sha512-JJiQwjV5/uVtwiVH/lt+QXhuh0nGhylZSLkMQXc1923TBUC4SHwU0JIKEDqh820PlGNkUu0nODJSAzS/6zPRtQ==", + "version": "0.0.65", + "resolved": "https://registry.npmjs.org/@langchain/langgraph-sdk/-/langgraph-sdk-0.0.65.tgz", + "integrity": "sha512-Zn1FhiKr/mYa1+W5NcuCPWmdTtJS4UZYu+YVEjxgESd0aMX19FTkqjaSV6tFDcRqHHwlIgHloCSqHLkYWF/Zug==", "dependencies": { "@types/json-schema": "^7.0.15", "p-queue": "^6.6.2", @@ -17819,9 +17819,9 @@ } }, "node_modules/@librechat/agents": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@librechat/agents/-/agents-2.4.0.tgz", - "integrity": "sha512-ijPJw+lMMPJ+Y66xSbh0cCiuODihl0TET3CWAxZweVGqynYqtL8PvPqlxtw+jftmrLjDFV04UM2NiDbzDb87HA==", + "version": "2.4.12", + "resolved": "https://registry.npmjs.org/@librechat/agents/-/agents-2.4.12.tgz", + "integrity": "sha512-m8CEVCjVeQDKXMS0ISG4h4YXU1x51yWGPLCuiNbQI3k+fmDvEFqVuzFi15OhVfoGGQxbKfzGiiF8fsKK2xIKEw==", "dependencies": { "@langchain/anthropic": "^0.3.16", "@langchain/aws": "^0.1.7", diff --git a/packages/data-provider/src/file-config.ts b/packages/data-provider/src/file-config.ts index c380dacf6b..3798b48d4d 100644 --- a/packages/data-provider/src/file-config.ts +++ b/packages/data-provider/src/file-config.ts @@ -112,7 +112,7 @@ export const excelMimeTypes = /^application\/(vnd\.ms-excel|msexcel|x-msexcel|x-ms-excel|x-excel|x-dos_ms_excel|xls|x-xls|vnd\.openxmlformats-officedocument\.spreadsheetml\.sheet)$/; export const textMimeTypes = - /^(text\/(x-c|x-csharp|x-c\+\+|x-java|html|markdown|x-php|x-python|x-script\.python|x-ruby|x-tex|plain|css|vtt|javascript|csv))$/; + /^(text\/(x-c|x-csharp|tab-separated-values|x-c\+\+|x-java|html|markdown|x-php|x-python|x-script\.python|x-ruby|x-tex|plain|css|vtt|javascript|csv))$/; export const applicationMimeTypes = /^(application\/(epub\+zip|csv|json|pdf|x-tar|typescript|vnd\.openxmlformats-officedocument\.(wordprocessingml\.document|presentationml\.presentation|spreadsheetml\.sheet)|xml|zip))$/; @@ -152,6 +152,7 @@ export const codeTypeMapping: { [key: string]: string } = { yml: 'application/x-yaml', yaml: 'application/x-yaml', log: 'text/plain', + tsv: 'text/tab-separated-values', }; export const retrievalMimeTypes = [ @@ -230,7 +231,7 @@ export const convertStringsToRegex = (patterns: string[]): RegExp[] => const regex = new RegExp(pattern); acc.push(regex); } catch (error) { - console.error(`Invalid regex pattern "${pattern}" skipped.`); + console.error(`Invalid regex pattern "${pattern}" skipped.`, error); } return acc; }, []); From 24c0433dcf3b84a82eafce055c9076de98efc57b Mon Sep 17 00:00:00 2001 From: Danny Avila Date: Wed, 9 Apr 2025 16:11:16 -0400 Subject: [PATCH 7/8] =?UTF-8?q?=F0=9F=96=A5=EF=B8=8F=20feat:=20Code=20Inte?= =?UTF-8?q?rpreter=20API=20for=20Non-Agent=20Endpoints=20(#6803)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: Prevent parsing 'undefined' string in useLocalStorage initialization * feat: first pass, code interpreter badge * feat: Integrate API key authentication and default checked value in Code Interpreter Badge * refactor: Rename showMCPServers to showEphemeralBadges and update related components, memoize values in useChatBadges * refactor: Enhance AttachFileChat to support ephemeral agents in file attachment logic * fix: Add baseURL configuration option to legacy function call * refactor: Update dependency array in useDragHelpers to include handleFiles * refactor: Update isEphemeralAgent function to accept optional endpoint parameter * refactor: Update file handling to support ephemeral agents in AttachFileMenu and useDragHelpers * fix: improve compatibility issues with OpenAI usage field handling in createRun function * refactor: usage field compatibility * fix: ensure mcp servers are no longer "selected" if mcp servers are now unavailable --- api/app/clients/llm/createLLM.js | 1 + api/models/Agent.js | 22 ++-- api/server/controllers/agents/run.js | 14 ++- client/src/components/Chat/Input/BadgeRow.tsx | 20 +++- client/src/components/Chat/Input/ChatForm.tsx | 2 +- .../components/Chat/Input/CodeInterpreter.tsx | 104 ++++++++++++++++++ .../Chat/Input/Files/AttachFileChat.tsx | 11 +- .../Chat/Input/Files/AttachFileMenu.tsx | 4 +- .../src/components/Chat/Input/MCPSelect.tsx | 28 ++++- client/src/components/ui/CheckboxButton.tsx | 62 +++++++++++ client/src/components/ui/MultiSelect.tsx | 5 +- client/src/hooks/Files/useDragHelpers.ts | 28 +++-- client/src/hooks/useChatBadges.ts | 28 +++-- client/src/hooks/useLocalStorageAlt.tsx | 2 +- client/src/utils/localStorage.ts | 1 + packages/data-provider/src/config.ts | 2 + packages/data-provider/src/createPayload.ts | 6 +- packages/data-provider/src/schemas.ts | 16 +++ packages/data-provider/src/types.ts | 3 +- 19 files changed, 311 insertions(+), 48 deletions(-) create mode 100644 client/src/components/Chat/Input/CodeInterpreter.tsx create mode 100644 client/src/components/ui/CheckboxButton.tsx diff --git a/api/app/clients/llm/createLLM.js b/api/app/clients/llm/createLLM.js index 7dc0d40ceb..c8d6666bce 100644 --- a/api/app/clients/llm/createLLM.js +++ b/api/app/clients/llm/createLLM.js @@ -34,6 +34,7 @@ function createLLM({ let credentials = { openAIApiKey }; let configuration = { apiKey: openAIApiKey, + ...(configOptions.basePath && { baseURL: configOptions.basePath }), }; /** @type {AzureOptions} */ diff --git a/api/models/Agent.js b/api/models/Agent.js index 7c0a630808..dba0c40ee9 100644 --- a/api/models/Agent.js +++ b/api/models/Agent.js @@ -1,6 +1,6 @@ const mongoose = require('mongoose'); const { agentSchema } = require('@librechat/data-schemas'); -const { SystemRoles } = require('librechat-data-provider'); +const { SystemRoles, Tools } = require('librechat-data-provider'); const { GLOBAL_PROJECT_NAME, EPHEMERAL_AGENT_ID, mcp_delimiter } = require('librechat-data-provider').Constants; const { CONFIG_STORE, STARTUP_CONFIG } = require('librechat-data-provider').CacheKeys; @@ -51,16 +51,22 @@ const loadEphemeralAgent = ({ req, agent_id, endpoint, model_parameters: _m }) = const mcpServers = new Set(req.body.ephemeralAgent?.mcp); /** @type {string[]} */ const tools = []; + if (req.body.ephemeralAgent?.execute_code === true) { + tools.push(Tools.execute_code); + } - for (const toolName of Object.keys(availableTools)) { - if (!toolName.includes(mcp_delimiter)) { - continue; - } - const mcpServer = toolName.split(mcp_delimiter)?.[1]; - if (mcpServer && mcpServers.has(mcpServer)) { - tools.push(toolName); + if (mcpServers.size > 0) { + for (const toolName of Object.keys(availableTools)) { + if (!toolName.includes(mcp_delimiter)) { + continue; + } + const mcpServer = toolName.split(mcp_delimiter)?.[1]; + if (mcpServer && mcpServers.has(mcpServer)) { + tools.push(toolName); + } } } + const instructions = req.body.promptPrefix; return { id: agent_id, diff --git a/api/server/controllers/agents/run.js b/api/server/controllers/agents/run.js index 2efde5d061..2452e66233 100644 --- a/api/server/controllers/agents/run.js +++ b/api/server/controllers/agents/run.js @@ -11,6 +11,13 @@ const { providerEndpointMap, KnownEndpoints } = require('librechat-data-provider * @typedef {import('@librechat/agents').IState} IState */ +const customProviders = new Set([ + Providers.XAI, + Providers.OLLAMA, + Providers.DEEPSEEK, + Providers.OPENROUTER, +]); + /** * Creates a new Run instance with custom handlers and configuration. * @@ -43,8 +50,11 @@ async function createRun({ agent.model_parameters, ); - /** Resolves Mistral type strictness due to new OpenAI usage field */ - if (agent.endpoint?.toLowerCase().includes(KnownEndpoints.mistral)) { + /** Resolves issues with new OpenAI usage field */ + if ( + customProviders.has(agent.provider) || + (agent.provider === Providers.OPENAI && agent.endpoint !== agent.provider) + ) { llmConfig.streamUsage = false; llmConfig.usage = true; } diff --git a/client/src/components/Chat/Input/BadgeRow.tsx b/client/src/components/Chat/Input/BadgeRow.tsx index 0de28cb347..15e99bd42f 100644 --- a/client/src/components/Chat/Input/BadgeRow.tsx +++ b/client/src/components/Chat/Input/BadgeRow.tsx @@ -10,6 +10,7 @@ import React, { } from 'react'; import { useRecoilValue, useRecoilCallback } from 'recoil'; import type { LucideIcon } from 'lucide-react'; +import CodeInterpreter from './CodeInterpreter'; import type { BadgeItem } from '~/common'; import { useChatBadges } from '~/hooks'; import { Badge } from '~/components/ui'; @@ -17,7 +18,7 @@ import MCPSelect from './MCPSelect'; import store from '~/store'; interface BadgeRowProps { - showMCPServers?: boolean; + showEphemeralBadges?: boolean; onChange: (badges: Pick[]) => void; onToggle?: (badgeId: string, currentActive: boolean) => void; conversationId?: string | null; @@ -131,7 +132,13 @@ const dragReducer = (state: DragState, action: DragAction): DragState => { } }; -function BadgeRow({ showMCPServers, conversationId, onChange, onToggle, isInChat }: BadgeRowProps) { +function BadgeRow({ + showEphemeralBadges, + conversationId, + onChange, + onToggle, + isInChat, +}: BadgeRowProps) { const [orderedBadges, setOrderedBadges] = useState([]); const [dragState, dispatch] = useReducer(dragReducer, { draggedBadge: null, @@ -146,7 +153,7 @@ function BadgeRow({ showMCPServers, conversationId, onChange, onToggle, isInChat const animationFrame = useRef(null); const containerRectRef = useRef(null); - const allBadges = useChatBadges() || []; + const allBadges = useChatBadges(); const isEditing = useRecoilValue(store.isEditingBadges); const badges = useMemo( @@ -345,7 +352,12 @@ function BadgeRow({ showMCPServers, conversationId, onChange, onToggle, isInChat /> )} - {showMCPServers === true && } + {showEphemeralBadges === true && ( + <> + + + + )} {ghostBadge && (
{
{ + return ephemeralAgent?.execute_code ?? false; + }, [ephemeralAgent?.execute_code]); + + const { data } = useVerifyAgentToolAuth( + { toolId: Tools.execute_code }, + { + retry: 1, + }, + ); + const authType = useMemo(() => data?.message ?? false, [data?.message]); + const isAuthenticated = useMemo(() => data?.authenticated ?? false, [data?.authenticated]); + const { methods, onSubmit, isDialogOpen, setIsDialogOpen, handleRevokeApiKey } = + useCodeApiKeyForm({}); + + const setValue = useCallback( + (isChecked: boolean) => { + setEphemeralAgent((prev) => ({ + ...prev, + execute_code: isChecked, + })); + }, + [setEphemeralAgent], + ); + + const [runCode, setRunCode] = useLocalStorage( + `${LocalStorageKeys.LAST_CODE_TOGGLE_}${key}`, + isCodeToggleEnabled, + setValue, + ); + + const handleChange = useCallback( + (isChecked: boolean) => { + if (!isAuthenticated) { + setIsDialogOpen(true); + return; + } + setRunCode(isChecked); + }, + [setRunCode, setIsDialogOpen, isAuthenticated], + ); + + const debouncedChange = useMemo( + () => debounce(handleChange, 50, { leading: true }), + [handleChange], + ); + + if (!canRunCode) { + return null; + } + + return ( + <> + } + /> + + + ); +} + +export default memo(CodeInterpreter); diff --git a/client/src/components/Chat/Input/Files/AttachFileChat.tsx b/client/src/components/Chat/Input/Files/AttachFileChat.tsx index b4b0de1a63..11bca082fe 100644 --- a/client/src/components/Chat/Input/Files/AttachFileChat.tsx +++ b/client/src/components/Chat/Input/Files/AttachFileChat.tsx @@ -1,24 +1,31 @@ import { memo, useMemo } from 'react'; import { useRecoilValue } from 'recoil'; import { + Constants, supportsFiles, mergeFileConfig, isAgentsEndpoint, + isEphemeralAgent, EndpointFileConfig, fileConfig as defaultFileConfig, } from 'librechat-data-provider'; import { useChatContext } from '~/Providers'; import { useGetFileConfig } from '~/data-provider'; +import { ephemeralAgentByConvoId } from '~/store'; import AttachFileMenu from './AttachFileMenu'; import AttachFile from './AttachFile'; -import store from '~/store'; function AttachFileChat({ disableInputs }: { disableInputs: boolean }) { const { conversation } = useChatContext(); const { endpoint: _endpoint, endpointType } = conversation ?? { endpoint: null }; - const isAgents = useMemo(() => isAgentsEndpoint(_endpoint), [_endpoint]); + const key = conversation?.conversationId ?? Constants.NEW_CONVO; + const ephemeralAgent = useRecoilValue(ephemeralAgentByConvoId(key)); + const isAgents = useMemo( + () => isAgentsEndpoint(_endpoint) || isEphemeralAgent(_endpoint, ephemeralAgent), + [_endpoint, ephemeralAgent], + ); const { data: fileConfig = defaultFileConfig } = useGetFileConfig({ select: (data) => mergeFileConfig(data), diff --git a/client/src/components/Chat/Input/Files/AttachFileMenu.tsx b/client/src/components/Chat/Input/Files/AttachFileMenu.tsx index 0f5f8e05a7..f827d39f4a 100644 --- a/client/src/components/Chat/Input/Files/AttachFileMenu.tsx +++ b/client/src/components/Chat/Input/Files/AttachFileMenu.tsx @@ -18,7 +18,9 @@ const AttachFile = ({ disabled }: AttachFileProps) => { const [isPopoverActive, setIsPopoverActive] = useState(false); const [toolResource, setToolResource] = useState(); const { data: endpointsConfig } = useGetEndpointsQuery(); - const { handleFileChange } = useFileHandling(); + const { handleFileChange } = useFileHandling({ + overrideEndpoint: EModelEndpoint.agents, + }); const capabilities = useMemo( () => endpointsConfig?.[EModelEndpoint.agents]?.capabilities ?? [], diff --git a/client/src/components/Chat/Input/MCPSelect.tsx b/client/src/components/Chat/Input/MCPSelect.tsx index adbdc29750..270228fe57 100644 --- a/client/src/components/Chat/Input/MCPSelect.tsx +++ b/client/src/components/Chat/Input/MCPSelect.tsx @@ -1,4 +1,4 @@ -import React, { memo, useCallback } from 'react'; +import React, { memo, useRef, useMemo, useEffect, useCallback } from 'react'; import { useRecoilState } from 'recoil'; import { Constants, EModelEndpoint, LocalStorageKeys } from 'librechat-data-provider'; import { useAvailableToolsQuery } from '~/data-provider'; @@ -10,8 +10,12 @@ import { useLocalize } from '~/hooks'; function MCPSelect({ conversationId }: { conversationId?: string | null }) { const localize = useLocalize(); + const hasSetFetched = useRef(false); const key = conversationId ?? Constants.NEW_CONVO; const [ephemeralAgent, setEphemeralAgent] = useRecoilState(ephemeralAgentByConvoId(key)); + const mcpState = useMemo(() => { + return ephemeralAgent?.mcp ?? []; + }, [ephemeralAgent?.mcp]); const setSelectedValues = useCallback( (values: string[] | null | undefined) => { if (!values) { @@ -29,10 +33,10 @@ function MCPSelect({ conversationId }: { conversationId?: string | null }) { ); const [mcpValues, setMCPValues] = useLocalStorage( `${LocalStorageKeys.LAST_MCP_}${key}`, - ephemeralAgent?.mcp ?? [], + mcpState, setSelectedValues, ); - const { data: mcpServers } = useAvailableToolsQuery(EModelEndpoint.agents, { + const { data: mcpServers, isFetched } = useAvailableToolsQuery(EModelEndpoint.agents, { select: (data) => { const serverNames = new Set(); data.forEach((tool) => { @@ -45,6 +49,20 @@ function MCPSelect({ conversationId }: { conversationId?: string | null }) { }, }); + useEffect(() => { + if (hasSetFetched.current) { + return; + } + if (!isFetched) { + return; + } + hasSetFetched.current = true; + if ((mcpServers?.length ?? 0) > 0) { + return; + } + setMCPValues([]); + }, [isFetched, setMCPValues, mcpServers?.length]); + const renderSelectedValues = useCallback( (values: string[], placeholder?: string) => { if (values.length === 0) { @@ -70,8 +88,8 @@ function MCPSelect({ conversationId }: { conversationId?: string | null }) { defaultSelectedValues={mcpValues ?? []} renderSelectedValues={renderSelectedValues} placeholder={localize('com_ui_mcp_servers')} - popoverClassName="min-w-[200px]" - className="badge-icon h-full min-w-[150px]" + popoverClassName="min-w-fit" + className="badge-icon min-w-fit" selectIcon={} selectItemsClassName="border border-blue-600/50 bg-blue-500/10 hover:bg-blue-700/10" selectClassName="group relative inline-flex items-center justify-center md:justify-start gap-1.5 rounded-full border border-border-medium text-sm font-medium transition-shadow md:w-full size-9 p-2 md:p-3 bg-surface-chat shadow-sm hover:bg-surface-hover hover:shadow-md active:shadow-inner" diff --git a/client/src/components/ui/CheckboxButton.tsx b/client/src/components/ui/CheckboxButton.tsx new file mode 100644 index 0000000000..988340c061 --- /dev/null +++ b/client/src/components/ui/CheckboxButton.tsx @@ -0,0 +1,62 @@ +import { useEffect } from 'react'; +import { Checkbox, useStoreState, useCheckboxStore } from '@ariakit/react'; +import { cn } from '~/utils'; + +export default function CheckboxButton({ + label, + icon, + setValue, + className, + defaultChecked, + isCheckedClassName, +}: { + label: string; + className?: string; + icon?: React.ReactNode; + defaultChecked?: boolean; + isCheckedClassName?: string; + setValue?: (isChecked: boolean) => void; +}) { + const checkbox = useCheckboxStore(); + const isChecked = useStoreState(checkbox, (state) => state?.value); + const onChange = (e: React.ChangeEvent) => { + e.stopPropagation(); + if (typeof isChecked !== 'boolean') { + return; + } + setValue?.(!isChecked); + }; + useEffect(() => { + if (defaultChecked) { + checkbox.setValue(defaultChecked); + } + }, [defaultChecked, checkbox]); + + return ( + } + > + {/* Icon if provided */} + {icon && {icon}} + + {/* Show the label on larger screens */} + {label} + + ); +} diff --git a/client/src/components/ui/MultiSelect.tsx b/client/src/components/ui/MultiSelect.tsx index 9de2780721..ddbd5c90a4 100644 --- a/client/src/components/ui/MultiSelect.tsx +++ b/client/src/components/ui/MultiSelect.tsx @@ -66,7 +66,7 @@ export default function MultiSelect({ }; return ( -
+
{label && ( @@ -82,9 +82,10 @@ export default function MultiSelect({ selectClassName, selectedValues.length > 0 && selectItemsClassName != null && selectItemsClassName, )} + onChange={(e) => e.stopPropagation()} > {selectIcon && selectIcon} - + {renderSelectedValues(selectedValues, placeholder)} diff --git a/client/src/hooks/Files/useDragHelpers.ts b/client/src/hooks/Files/useDragHelpers.ts index 32cd83f9b1..af4530e622 100644 --- a/client/src/hooks/Files/useDragHelpers.ts +++ b/client/src/hooks/Files/useDragHelpers.ts @@ -4,22 +4,28 @@ import { useRecoilValue } from 'recoil'; import { NativeTypes } from 'react-dnd-html5-backend'; import { useQueryClient } from '@tanstack/react-query'; import { - isAgentsEndpoint, - EModelEndpoint, - AgentCapabilities, + Constants, QueryKeys, + EModelEndpoint, + isAgentsEndpoint, + isEphemeralAgent, + AgentCapabilities, } from 'librechat-data-provider'; import type * as t from 'librechat-data-provider'; import type { DropTargetMonitor } from 'react-dnd'; import useFileHandling from './useFileHandling'; -import store from '~/store'; +import store, { ephemeralAgentByConvoId } from '~/store'; export default function useDragHelpers() { const queryClient = useQueryClient(); - const { handleFiles } = useFileHandling(); const [showModal, setShowModal] = useState(false); const [draggedFiles, setDraggedFiles] = useState([]); const conversation = useRecoilValue(store.conversationByIndex(0)) || undefined; + const key = useMemo( + () => conversation?.conversationId ?? Constants.NEW_CONVO, + [conversation?.conversationId], + ); + const ephemeralAgent = useRecoilValue(ephemeralAgentByConvoId(key)); const handleOptionSelect = (toolResource: string | undefined) => { handleFiles(draggedFiles, toolResource); @@ -28,10 +34,16 @@ export default function useDragHelpers() { }; const isAgents = useMemo( - () => isAgentsEndpoint(conversation?.endpoint), - [conversation?.endpoint], + () => + isAgentsEndpoint(conversation?.endpoint) || + isEphemeralAgent(conversation?.endpoint, ephemeralAgent), + [conversation?.endpoint, ephemeralAgent], ); + const { handleFiles } = useFileHandling({ + overrideEndpoint: isAgents ? EModelEndpoint.agents : undefined, + }); + const [{ canDrop, isOver }, drop] = useDrop( () => ({ accept: [NativeTypes.FILE], @@ -61,7 +73,7 @@ export default function useDragHelpers() { canDrop: monitor.canDrop(), }), }), - [], + [handleFiles], ); return { diff --git a/client/src/hooks/useChatBadges.ts b/client/src/hooks/useChatBadges.ts index 022f3f7a63..abc23ee300 100644 --- a/client/src/hooks/useChatBadges.ts +++ b/client/src/hooks/useChatBadges.ts @@ -1,8 +1,9 @@ +import { useMemo } from 'react'; import { useRecoilCallback } from 'recoil'; import { useRecoilValue } from 'recoil'; import { MessageCircleDashed, Box } from 'lucide-react'; import type { BadgeItem } from '~/common'; -import { useLocalize } from '~/hooks'; +import { useLocalize, TranslationKeys } from '~/hooks'; import store from '~/store'; interface ChatBadgeConfig { @@ -25,15 +26,22 @@ const badgeConfig: ReadonlyArray = [ export default function useChatBadges(): BadgeItem[] { const localize = useLocalize(); const activeBadges = useRecoilValue(store.chatBadges) as Array<{ id: string }>; - const activeBadgeIds = new Set(activeBadges.map((badge) => badge.id)); - - return badgeConfig.map((cfg) => ({ - id: cfg.id, - label: localize(cfg.label), - icon: cfg.icon, - atom: cfg.atom, - isAvailable: activeBadgeIds.has(cfg.id), - })); + const activeBadgeIds = useMemo( + () => new Set(activeBadges.map((badge) => badge.id)), + [activeBadges], + ); + const allBadges = useMemo(() => { + return ( + badgeConfig.map((cfg) => ({ + id: cfg.id, + label: localize(cfg.label as TranslationKeys), + icon: cfg.icon, + atom: cfg.atom, + isAvailable: activeBadgeIds.has(cfg.id), + })) || [] + ); + }, [activeBadgeIds, localize]); + return allBadges; } export function useResetChatBadges() { diff --git a/client/src/hooks/useLocalStorageAlt.tsx b/client/src/hooks/useLocalStorageAlt.tsx index 465d62c70b..ef63198242 100644 --- a/client/src/hooks/useLocalStorageAlt.tsx +++ b/client/src/hooks/useLocalStorageAlt.tsx @@ -21,7 +21,7 @@ export default function useLocalStorage( localStorage.setItem(key, JSON.stringify(defaultValue)); } - const initialValue = item ? JSON.parse(item) : defaultValue; + const initialValue = item && item !== 'undefined' ? JSON.parse(item) : defaultValue; setValue(initialValue); if (globalSetState) { globalSetState(initialValue); diff --git a/client/src/utils/localStorage.ts b/client/src/utils/localStorage.ts index 35bd12232f..cb1dee9403 100644 --- a/client/src/utils/localStorage.ts +++ b/client/src/utils/localStorage.ts @@ -32,6 +32,7 @@ export function clearLocalStorage(skipFirst?: boolean) { } if ( key.startsWith(LocalStorageKeys.LAST_MCP_) || + key.startsWith(LocalStorageKeys.LAST_CODE_TOGGLE_) || key.startsWith(LocalStorageKeys.ASST_ID_PREFIX) || key.startsWith(LocalStorageKeys.AGENT_ID_PREFIX) || key.startsWith(LocalStorageKeys.LAST_CONVO_SETUP) || diff --git a/packages/data-provider/src/config.ts b/packages/data-provider/src/config.ts index 1b8d815a7b..6e62919526 100644 --- a/packages/data-provider/src/config.ts +++ b/packages/data-provider/src/config.ts @@ -1285,6 +1285,8 @@ export enum LocalStorageKeys { SHOW_ANALYSIS_CODE = 'showAnalysisCode', /** Last selected MCP values per conversation ID */ LAST_MCP_ = 'LAST_MCP_', + /** Last checked toggle for Code Interpreter API per conversation ID */ + LAST_CODE_TOGGLE_ = 'LAST_CODE_TOGGLE_', } export enum ForkOptions { diff --git a/packages/data-provider/src/createPayload.ts b/packages/data-provider/src/createPayload.ts index 19d94cec4f..edd8f0e426 100644 --- a/packages/data-provider/src/createPayload.ts +++ b/packages/data-provider/src/createPayload.ts @@ -19,20 +19,20 @@ export default function createPayload(submission: t.TSubmission) { }; let server = EndpointURLs[endpointType ?? endpoint]; - const isEphemeralAgent = (ephemeralAgent?.mcp?.length ?? 0) > 0 && !s.isAgentsEndpoint(endpoint); + const isEphemeral = s.isEphemeralAgent(endpoint, ephemeralAgent); if (isEdited && s.isAssistantsEndpoint(endpoint)) { server += '/modify'; } else if (isEdited) { server = server.replace('/ask/', '/edit/'); - } else if (isEphemeralAgent) { + } else if (isEphemeral) { server = `${EndpointURLs[s.EModelEndpoint.agents]}/${endpoint}`; } const payload: t.TPayload = { ...userMessage, ...endpointOption, - ephemeralAgent: isEphemeralAgent ? ephemeralAgent : undefined, + ephemeralAgent: isEphemeral ? ephemeralAgent : undefined, isContinued: !!(isEdited && isContinued), conversationId, isTemporary, diff --git a/packages/data-provider/src/schemas.ts b/packages/data-provider/src/schemas.ts index b923a1a467..f3335a8942 100644 --- a/packages/data-provider/src/schemas.ts +++ b/packages/data-provider/src/schemas.ts @@ -1,6 +1,7 @@ import { z } from 'zod'; import { Tools } from './types/assistants'; import type { TMessageContentParts, FunctionTool, FunctionToolCall } from './types/assistants'; +import type { TEphemeralAgent } from './types'; import type { TFile } from './types/files'; export const isUUID = z.string().uuid(); @@ -88,6 +89,21 @@ export const isAgentsEndpoint = (_endpoint?: EModelEndpoint.agents | null | stri return endpoint === EModelEndpoint.agents; }; +export const isEphemeralAgent = ( + endpoint?: EModelEndpoint.agents | null | string, + ephemeralAgent?: TEphemeralAgent | null, +) => { + if (!ephemeralAgent) { + return false; + } + if (isAgentsEndpoint(endpoint)) { + return false; + } + const hasMCPSelected = (ephemeralAgent?.mcp?.length ?? 0) > 0; + const hasCodeSelected = (ephemeralAgent?.execute_code ?? false) === true; + return hasMCPSelected || hasCodeSelected; +}; + export const isParamEndpoint = ( endpoint: EModelEndpoint | string, endpointType?: EModelEndpoint | string, diff --git a/packages/data-provider/src/types.ts b/packages/data-provider/src/types.ts index dabe89cdb0..1ac3d1f46d 100644 --- a/packages/data-provider/src/types.ts +++ b/packages/data-provider/src/types.ts @@ -42,7 +42,8 @@ export type TEndpointOption = { }; export type TEphemeralAgent = { - mcp: string[]; + mcp?: string[]; + execute_code?: boolean; }; export type TPayload = Partial & From e16a6190a556602289d8c5bb226f540382f25aae Mon Sep 17 00:00:00 2001 From: Danny Avila Date: Wed, 9 Apr 2025 18:38:48 -0400 Subject: [PATCH 8/8] =?UTF-8?q?=F0=9F=92=BE=20chore:=20Enhance=20Local=20S?= =?UTF-8?q?torage=20Handling=20and=20Update=20MCP=20SDK=20(#6809)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: Update MCP package version and dependencies; refactor ToolContentPart type * refactor: Change module type to commonjs and update rollup configuration, remove unused dev dependency * refactor: Change async calls to synchronous for MCP and FlowStateManager retrieval * chore: Add eslint disable comment for i18next rule in DropdownPopup component * fix: improve statefulness of mcp servers selected if some were removed since last session * feat: implement conversation storage cleanup functions and integrate them into mutation success handlers * feat: enhance storage condition logic in useLocalStorageAlt to prevent unnecessary local storage writes * refactor: streamline local storage update logic in useLocalStorageAlt --- api/config/index.js | 11 +- api/server/controllers/PluginController.js | 2 +- api/server/routes/actions.js | 2 +- api/server/services/ActionService.js | 4 +- api/server/services/AppService.js | 2 +- api/server/services/MCP.js | 2 +- .../components/Chat/Input/CodeInterpreter.tsx | 15 + .../src/components/Chat/Input/MCPSelect.tsx | 59 +- .../Nav/SettingsTabs/Data/ClearChats.tsx | 2 + client/src/components/ui/DropdownPopup.tsx | 1 + client/src/data-provider/Auth/mutations.ts | 2 + client/src/data-provider/mutations.ts | 4 +- client/src/hooks/useLocalStorageAlt.tsx | 16 +- client/src/utils/localStorage.ts | 35 +- package-lock.json | 587 +++++++++--------- packages/mcp/package.json | 13 +- packages/mcp/rollup.config.js | 24 +- packages/mcp/src/types/mcp.ts | 21 +- 18 files changed, 420 insertions(+), 382 deletions(-) diff --git a/api/config/index.js b/api/config/index.js index 8f23e404c8..919919b55f 100644 --- a/api/config/index.js +++ b/api/config/index.js @@ -1,6 +1,7 @@ const axios = require('axios'); const { EventSource } = require('eventsource'); const { Time, CacheKeys } = require('librechat-data-provider'); +const { MCPManager, FlowStateManager } = require('librechat-mcp'); const logger = require('./winston'); global.EventSource = EventSource; @@ -9,11 +10,10 @@ let mcpManager = null; let flowManager = null; /** - * @returns {Promise} + * @returns {MCPManager} */ -async function getMCPManager() { +function getMCPManager() { if (!mcpManager) { - const { MCPManager } = await import('librechat-mcp'); mcpManager = MCPManager.getInstance(logger); } return mcpManager; @@ -21,11 +21,10 @@ async function getMCPManager() { /** * @param {(key: string) => Keyv} getLogStores - * @returns {Promise} + * @returns {FlowStateManager} */ -async function getFlowStateManager(getLogStores) { +function getFlowStateManager(getLogStores) { if (!flowManager) { - const { FlowStateManager } = await import('librechat-mcp'); flowManager = new FlowStateManager(getLogStores(CacheKeys.FLOWS), { ttl: Time.ONE_MINUTE * 3, logger, diff --git a/api/server/controllers/PluginController.js b/api/server/controllers/PluginController.js index 9e87b46289..71e7ed348e 100644 --- a/api/server/controllers/PluginController.js +++ b/api/server/controllers/PluginController.js @@ -108,7 +108,7 @@ const getAvailableTools = async (req, res) => { const pluginManifest = availableTools; const customConfig = await getCustomConfig(); if (customConfig?.mcpServers != null) { - const mcpManager = await getMCPManager(); + const mcpManager = getMCPManager(); await mcpManager.loadManifestTools(pluginManifest); } diff --git a/api/server/routes/actions.js b/api/server/routes/actions.js index 454f4be6c7..28845e3f15 100644 --- a/api/server/routes/actions.js +++ b/api/server/routes/actions.js @@ -20,7 +20,7 @@ router.get('/:action_id/oauth/callback', async (req, res) => { const { action_id } = req.params; const { code, state } = req.query; - const flowManager = await getFlowStateManager(getLogStores); + const flowManager = getFlowStateManager(getLogStores); let identifier = action_id; try { let decodedState; diff --git a/api/server/services/ActionService.js b/api/server/services/ActionService.js index 0dc8070f1a..12e30fd8b9 100644 --- a/api/server/services/ActionService.js +++ b/api/server/services/ActionService.js @@ -189,7 +189,7 @@ async function createActionTool({ expires_at: Date.now() + Time.TWO_MINUTES, }, }; - const flowManager = await getFlowStateManager(getLogStores); + const flowManager = getFlowStateManager(getLogStores); await flowManager.createFlowWithHandler( `${identifier}:oauth_login:${config.metadata.thread_id}:${config.metadata.run_id}`, 'oauth_login', @@ -265,7 +265,7 @@ async function createActionTool({ encrypted_oauth_client_id: encrypted.oauth_client_id, encrypted_oauth_client_secret: encrypted.oauth_client_secret, }); - const flowManager = await getFlowStateManager(getLogStores); + const flowManager = getFlowStateManager(getLogStores); const refreshData = await flowManager.createFlowWithHandler( `${identifier}:refresh`, 'oauth_refresh', diff --git a/api/server/services/AppService.js b/api/server/services/AppService.js index f245c1f737..1ad3aaace6 100644 --- a/api/server/services/AppService.js +++ b/api/server/services/AppService.js @@ -66,7 +66,7 @@ const AppService = async (app) => { }); if (config.mcpServers != null) { - const mcpManager = await getMCPManager(); + const mcpManager = getMCPManager(); await mcpManager.initializeMCP(config.mcpServers, processMCPEnv); await mcpManager.mapAvailableTools(availableTools); } diff --git a/api/server/services/MCP.js b/api/server/services/MCP.js index b64194b07b..0a2711c672 100644 --- a/api/server/services/MCP.js +++ b/api/server/services/MCP.js @@ -49,7 +49,7 @@ async function createMCPTool({ req, toolKey, provider }) { /** @type {(toolArguments: Object | string, config?: GraphRunnableConfig) => Promise} */ const _call = async (toolArguments, config) => { try { - const mcpManager = await getMCPManager(); + const mcpManager = getMCPManager(); const result = await mcpManager.callTool({ serverName, toolName, diff --git a/client/src/components/Chat/Input/CodeInterpreter.tsx b/client/src/components/Chat/Input/CodeInterpreter.tsx index 6bfc367cb1..3f2c282ffe 100644 --- a/client/src/components/Chat/Input/CodeInterpreter.tsx +++ b/client/src/components/Chat/Input/CodeInterpreter.tsx @@ -17,6 +17,20 @@ import useLocalStorage from '~/hooks/useLocalStorageAlt'; import { useVerifyAgentToolAuth } from '~/data-provider'; import { ephemeralAgentByConvoId } from '~/store'; +const storageCondition = (value: unknown, rawCurrentValue?: string | null) => { + if (rawCurrentValue) { + try { + const currentValue = rawCurrentValue?.trim() ?? ''; + if (currentValue === 'true' && value === false) { + return true; + } + } catch (e) { + console.error(e); + } + } + return value !== undefined && value !== null && value !== '' && value !== false; +}; + function CodeInterpreter({ conversationId }: { conversationId?: string | null }) { const localize = useLocalize(); const key = conversationId ?? Constants.NEW_CONVO; @@ -55,6 +69,7 @@ function CodeInterpreter({ conversationId }: { conversationId?: string | null }) `${LocalStorageKeys.LAST_CODE_TOGGLE_}${key}`, isCodeToggleEnabled, setValue, + storageCondition, ); const handleChange = useCallback( diff --git a/client/src/components/Chat/Input/MCPSelect.tsx b/client/src/components/Chat/Input/MCPSelect.tsx index 270228fe57..672713f6d6 100644 --- a/client/src/components/Chat/Input/MCPSelect.tsx +++ b/client/src/components/Chat/Input/MCPSelect.tsx @@ -8,14 +8,43 @@ import { ephemeralAgentByConvoId } from '~/store'; import MCPIcon from '~/components/ui/MCPIcon'; import { useLocalize } from '~/hooks'; +const storageCondition = (value: unknown, rawCurrentValue?: string | null) => { + if (rawCurrentValue) { + try { + const currentValue = rawCurrentValue?.trim() ?? ''; + if (currentValue.length > 2) { + return true; + } + } catch (e) { + console.error(e); + } + } + return Array.isArray(value) && value.length > 0; +}; + function MCPSelect({ conversationId }: { conversationId?: string | null }) { const localize = useLocalize(); - const hasSetFetched = useRef(false); const key = conversationId ?? Constants.NEW_CONVO; + const hasSetFetched = useRef(null); + + const { data: mcpServerSet, isFetched } = useAvailableToolsQuery(EModelEndpoint.agents, { + select: (data) => { + const serverNames = new Set(); + data.forEach((tool) => { + if (tool.pluginKey.includes(Constants.mcp_delimiter)) { + const parts = tool.pluginKey.split(Constants.mcp_delimiter); + serverNames.add(parts[parts.length - 1]); + } + }); + return serverNames; + }, + }); + const [ephemeralAgent, setEphemeralAgent] = useRecoilState(ephemeralAgentByConvoId(key)); const mcpState = useMemo(() => { return ephemeralAgent?.mcp ?? []; }, [ephemeralAgent?.mcp]); + const setSelectedValues = useCallback( (values: string[] | null | undefined) => { if (!values) { @@ -35,33 +64,23 @@ function MCPSelect({ conversationId }: { conversationId?: string | null }) { `${LocalStorageKeys.LAST_MCP_}${key}`, mcpState, setSelectedValues, + storageCondition, ); - const { data: mcpServers, isFetched } = useAvailableToolsQuery(EModelEndpoint.agents, { - select: (data) => { - const serverNames = new Set(); - data.forEach((tool) => { - if (tool.pluginKey.includes(Constants.mcp_delimiter)) { - const parts = tool.pluginKey.split(Constants.mcp_delimiter); - serverNames.add(parts[parts.length - 1]); - } - }); - return [...serverNames]; - }, - }); useEffect(() => { - if (hasSetFetched.current) { + if (hasSetFetched.current === key) { return; } if (!isFetched) { return; } - hasSetFetched.current = true; - if ((mcpServers?.length ?? 0) > 0) { + hasSetFetched.current = key; + if ((mcpServerSet?.size ?? 0) > 0) { + setMCPValues(mcpValues.filter((mcp) => mcpServerSet?.has(mcp))); return; } setMCPValues([]); - }, [isFetched, setMCPValues, mcpServers?.length]); + }, [isFetched, setMCPValues, mcpServerSet, key, mcpValues]); const renderSelectedValues = useCallback( (values: string[], placeholder?: string) => { @@ -76,7 +95,11 @@ function MCPSelect({ conversationId }: { conversationId?: string | null }) { [localize], ); - if (!mcpServers || mcpServers.length === 0) { + const mcpServers = useMemo(() => { + return Array.from(mcpServerSet ?? []); + }, [mcpServerSet]); + + if (!mcpServerSet || mcpServerSet.size === 0) { return null; } diff --git a/client/src/components/Nav/SettingsTabs/Data/ClearChats.tsx b/client/src/components/Nav/SettingsTabs/Data/ClearChats.tsx index dd7aacc2ab..11e53ba570 100644 --- a/client/src/components/Nav/SettingsTabs/Data/ClearChats.tsx +++ b/client/src/components/Nav/SettingsTabs/Data/ClearChats.tsx @@ -3,6 +3,7 @@ import { useClearConversationsMutation } from 'librechat-data-provider/react-que import { Label, Button, OGDialog, OGDialogTrigger, Spinner } from '~/components'; import { useLocalize, useNewConvo } from '~/hooks'; import OGDialogTemplate from '~/components/ui/OGDialogTemplate'; +import { clearAllConversationStorage } from '~/utils'; export const ClearChats = () => { const localize = useLocalize(); @@ -15,6 +16,7 @@ export const ClearChats = () => { {}, { onSuccess: () => { + clearAllConversationStorage(); newConversation(); }, }, diff --git a/client/src/components/ui/DropdownPopup.tsx b/client/src/components/ui/DropdownPopup.tsx index 8645d59736..919557eacb 100644 --- a/client/src/components/ui/DropdownPopup.tsx +++ b/client/src/components/ui/DropdownPopup.tsx @@ -83,6 +83,7 @@ const DropdownPopup: React.FC = ({ )} {item.label} {item.kbd != null && ( + // eslint-disable-next-line i18next/no-literal-string ⌘{item.kbd} diff --git a/client/src/data-provider/Auth/mutations.ts b/client/src/data-provider/Auth/mutations.ts index eb09868ec6..88fdcf06f1 100644 --- a/client/src/data-provider/Auth/mutations.ts +++ b/client/src/data-provider/Auth/mutations.ts @@ -4,6 +4,7 @@ import { MutationKeys, QueryKeys, dataService, request } from 'librechat-data-pr import type { UseMutationResult } from '@tanstack/react-query'; import type * as t from 'librechat-data-provider'; import useClearStates from '~/hooks/Config/useClearStates'; +import { clearAllConversationStorage } from '~/utils'; import store from '~/store'; /* login/logout */ @@ -79,6 +80,7 @@ export const useDeleteUserMutation = ( onSuccess: (...args) => { resetDefaultPreset(); clearStates(); + clearAllConversationStorage(); queryClient.removeQueries(); options?.onSuccess?.(...args); }, diff --git a/client/src/data-provider/mutations.ts b/client/src/data-provider/mutations.ts index 60f65eeeec..fb772f7a0d 100644 --- a/client/src/data-provider/mutations.ts +++ b/client/src/data-provider/mutations.ts @@ -18,6 +18,7 @@ import { updateConvoFields, updateConversation, deleteConversation, + clearConversationStorage, } from '~/utils'; export type TGenTitleMutation = UseMutationResult< @@ -562,6 +563,7 @@ export const useDeleteConversationMutation = ( const current = queryClient.getQueryData([QueryKeys.allConversations]); refetch({ refetchPage: (page, index) => index === (current?.pages.length ?? 1) - 1 }); onSuccess?.(_data, vars, context); + clearConversationStorage(conversationId); }, ..._options, }, @@ -897,7 +899,7 @@ export const useUploadAssistantAvatarMutation = ( unknown // context > => { return useMutation([MutationKeys.assistantAvatarUpload], { - // eslint-disable-next-line @typescript-eslint/no-unused-vars + mutationFn: ({ postCreation, ...variables }: t.AssistantAvatarVariables) => dataService.uploadAssistantAvatar(variables), ...(options || {}), diff --git a/client/src/hooks/useLocalStorageAlt.tsx b/client/src/hooks/useLocalStorageAlt.tsx index ef63198242..81b3e637ec 100644 --- a/client/src/hooks/useLocalStorageAlt.tsx +++ b/client/src/hooks/useLocalStorageAlt.tsx @@ -11,13 +11,16 @@ export default function useLocalStorage( key: string, defaultValue: T, globalSetState?: (value: T) => void, + storageCondition?: (value: T, rawCurrentValue?: string | null) => boolean, ): [T, (value: T) => void] { const [value, setValue] = useState(defaultValue); useEffect(() => { const item = localStorage.getItem(key); - if (!item) { + if (!item && !storageCondition) { + localStorage.setItem(key, JSON.stringify(defaultValue)); + } else if (!item && storageCondition && storageCondition(defaultValue)) { localStorage.setItem(key, JSON.stringify(defaultValue)); } @@ -47,9 +50,14 @@ export default function useLocalStorage( const setValueWrap = (value: T) => { try { setValue(value); - localStorage.setItem(key, JSON.stringify(value)); - if (typeof window !== 'undefined') { - window.dispatchEvent(new StorageEvent('storage', { key })); + const storeLocal = () => { + localStorage.setItem(key, JSON.stringify(value)); + window?.dispatchEvent(new StorageEvent('storage', { key })); + }; + if (!storageCondition) { + storeLocal(); + } else if (storageCondition(value, localStorage.getItem(key))) { + storeLocal(); } globalSetState?.(value); } catch (e) { diff --git a/client/src/utils/localStorage.ts b/client/src/utils/localStorage.ts index cb1dee9403..d1c9d1acf1 100644 --- a/client/src/utils/localStorage.ts +++ b/client/src/utils/localStorage.ts @@ -1,4 +1,4 @@ -import { LocalStorageKeys, TConversation } from 'librechat-data-provider'; +import { LocalStorageKeys, TConversation, isUUID } from 'librechat-data-provider'; export function getLocalStorageItems() { const items = { @@ -45,3 +45,36 @@ export function clearLocalStorage(skipFirst?: boolean) { } }); } + +export function clearConversationStorage(conversationId?: string | null) { + if (!conversationId) { + return; + } + if (!isUUID.safeParse(conversationId)?.success) { + console.warn( + `Conversation ID ${conversationId} is not a valid UUID. Skipping local storage cleanup.`, + ); + return; + } + const keys = Object.keys(localStorage); + keys.forEach((key) => { + if (key.includes(conversationId)) { + localStorage.removeItem(key); + } + }); +} +export function clearAllConversationStorage() { + const keys = Object.keys(localStorage); + keys.forEach((key) => { + if ( + key.startsWith(LocalStorageKeys.LAST_MCP_) || + key.startsWith(LocalStorageKeys.LAST_CODE_TOGGLE_) || + key.startsWith(LocalStorageKeys.TEXT_DRAFT) || + key.startsWith(LocalStorageKeys.ASST_ID_PREFIX) || + key.startsWith(LocalStorageKeys.AGENT_ID_PREFIX) || + key.startsWith(LocalStorageKeys.LAST_CONVO_SETUP) + ) { + localStorage.removeItem(key); + } + }); +} diff --git a/package-lock.json b/package-lock.json index 158ec0e959..a28245e651 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18649,304 +18649,6 @@ "zod": ">= 3" } }, - "node_modules/@modelcontextprotocol/sdk": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.8.0.tgz", - "integrity": "sha512-e06W7SwrontJDHwCawNO5SGxG+nU9AAx+jpHHZqGl/WrDBdWOpvirC+s58VpJTB5QemI4jTRcjWT4Pt3Q1NPQQ==", - "dependencies": { - "content-type": "^1.0.5", - "cors": "^2.8.5", - "cross-spawn": "^7.0.3", - "eventsource": "^3.0.2", - "express": "^5.0.1", - "express-rate-limit": "^7.5.0", - "pkce-challenge": "^4.1.0", - "raw-body": "^3.0.0", - "zod": "^3.23.8", - "zod-to-json-schema": "^3.24.1" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/accepts": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", - "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", - "dependencies": { - "mime-types": "^3.0.0", - "negotiator": "^1.0.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/body-parser": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", - "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==", - "dependencies": { - "bytes": "^3.1.2", - "content-type": "^1.0.5", - "debug": "^4.4.0", - "http-errors": "^2.0.0", - "iconv-lite": "^0.6.3", - "on-finished": "^2.4.1", - "qs": "^6.14.0", - "raw-body": "^3.0.0", - "type-is": "^2.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/body-parser/node_modules/qs": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", - "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", - "dependencies": { - "side-channel": "^1.1.0" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/content-disposition": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", - "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", - "dependencies": { - "safe-buffer": "5.2.1" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/cookie": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", - "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/cookie-signature": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", - "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", - "engines": { - "node": ">=6.6.0" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/express": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/express/-/express-5.0.1.tgz", - "integrity": "sha512-ORF7g6qGnD+YtUG9yx4DFoqCShNMmUKiXuT5oWMHiOvt/4WFbHC6yCwQMTSBMno7AqntNCAzzcnnjowRkTL9eQ==", - "dependencies": { - "accepts": "^2.0.0", - "body-parser": "^2.0.1", - "content-disposition": "^1.0.0", - "content-type": "~1.0.4", - "cookie": "0.7.1", - "cookie-signature": "^1.2.1", - "debug": "4.3.6", - "depd": "2.0.0", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "^2.0.0", - "fresh": "2.0.0", - "http-errors": "2.0.0", - "merge-descriptors": "^2.0.0", - "methods": "~1.1.2", - "mime-types": "^3.0.0", - "on-finished": "2.4.1", - "once": "1.4.0", - "parseurl": "~1.3.3", - "proxy-addr": "~2.0.7", - "qs": "6.13.0", - "range-parser": "~1.2.1", - "router": "^2.0.0", - "safe-buffer": "5.2.1", - "send": "^1.1.0", - "serve-static": "^2.1.0", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "type-is": "^2.0.0", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/express/node_modules/debug": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", - "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/express/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/finalhandler": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz", - "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==", - "dependencies": { - "debug": "^4.4.0", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "on-finished": "^2.4.1", - "parseurl": "^1.3.3", - "statuses": "^2.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/fresh": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", - "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/media-typer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", - "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/merge-descriptors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", - "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/mime-db": { - "version": "1.54.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", - "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/mime-types": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", - "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", - "dependencies": { - "mime-db": "^1.54.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/negotiator": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", - "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/raw-body": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz", - "integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==", - "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.6.3", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/send": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", - "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", - "dependencies": { - "debug": "^4.3.5", - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "etag": "^1.8.1", - "fresh": "^2.0.0", - "http-errors": "^2.0.0", - "mime-types": "^3.0.1", - "ms": "^2.1.3", - "on-finished": "^2.4.1", - "range-parser": "^1.2.1", - "statuses": "^2.0.1" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/serve-static": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", - "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==", - "dependencies": { - "encodeurl": "^2.0.0", - "escape-html": "^1.0.3", - "parseurl": "^1.3.3", - "send": "^1.2.0" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/@modelcontextprotocol/sdk/node_modules/type-is": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", - "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", - "dependencies": { - "content-type": "^1.0.5", - "media-typer": "^1.1.0", - "mime-types": "^3.0.0" - }, - "engines": { - "node": ">= 0.6" - } - }, "node_modules/@mongodb-js/saslprep": { "version": "1.1.9", "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.9.tgz", @@ -36071,14 +35773,6 @@ "node": ">= 6" } }, - "node_modules/pkce-challenge": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-4.1.0.tgz", - "integrity": "sha512-ZBmhE1C9LcPoH9XZSdwiPtbPHZROwAnMy+kIFQVrnMCxY4Cudlz3gBOpzilgc0jOgRaiT3sIWfpMomW2ar2orQ==", - "engines": { - "node": ">=16.20.0" - } - }, "node_modules/pkg-dir": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", @@ -43978,10 +43672,10 @@ }, "packages/mcp": { "name": "librechat-mcp", - "version": "1.1.0", + "version": "1.2.0", "license": "ISC", "dependencies": { - "@modelcontextprotocol/sdk": "^1.8.0", + "@modelcontextprotocol/sdk": "^1.9.0", "diff": "^7.0.0", "eventsource": "^3.0.2", "express": "^4.21.2" @@ -44010,7 +43704,6 @@ "rollup": "^4.22.4", "rollup-plugin-generate-package-json": "^3.2.0", "rollup-plugin-peer-deps-external": "^2.2.4", - "rollup-plugin-typescript2": "^0.35.0", "ts-node": "^10.9.2", "typescript": "^5.0.4" }, @@ -44018,6 +43711,98 @@ "keyv": "^4.5.4" } }, + "packages/mcp/node_modules/@modelcontextprotocol/sdk": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.9.0.tgz", + "integrity": "sha512-Jq2EUCQpe0iyO5FGpzVYDNFR6oR53AIrwph9yWl7uSc7IWUMsrmpmSaTGra5hQNunXpM+9oit85p924jWuHzUA==", + "dependencies": { + "content-type": "^1.0.5", + "cors": "^2.8.5", + "cross-spawn": "^7.0.3", + "eventsource": "^3.0.2", + "express": "^5.0.1", + "express-rate-limit": "^7.5.0", + "pkce-challenge": "^5.0.0", + "raw-body": "^3.0.0", + "zod": "^3.23.8", + "zod-to-json-schema": "^3.24.1" + }, + "engines": { + "node": ">=18" + } + }, + "packages/mcp/node_modules/@modelcontextprotocol/sdk/node_modules/express": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", + "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", + "dependencies": { + "accepts": "^2.0.0", + "body-parser": "^2.2.0", + "content-disposition": "^1.0.0", + "content-type": "^1.0.5", + "cookie": "^0.7.1", + "cookie-signature": "^1.2.1", + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "finalhandler": "^2.1.0", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "merge-descriptors": "^2.0.0", + "mime-types": "^3.0.0", + "on-finished": "^2.4.1", + "once": "^1.4.0", + "parseurl": "^1.3.3", + "proxy-addr": "^2.0.7", + "qs": "^6.14.0", + "range-parser": "^1.2.1", + "router": "^2.2.0", + "send": "^1.1.0", + "serve-static": "^2.2.0", + "statuses": "^2.0.1", + "type-is": "^2.0.1", + "vary": "^1.1.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "packages/mcp/node_modules/accepts": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", + "dependencies": { + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "packages/mcp/node_modules/body-parser": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", + "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==", + "dependencies": { + "bytes": "^3.1.2", + "content-type": "^1.0.5", + "debug": "^4.4.0", + "http-errors": "^2.0.0", + "iconv-lite": "^0.6.3", + "on-finished": "^2.4.1", + "qs": "^6.14.0", + "raw-body": "^3.0.0", + "type-is": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, "packages/mcp/node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", @@ -44027,6 +43812,49 @@ "balanced-match": "^1.0.0" } }, + "packages/mcp/node_modules/content-disposition": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", + "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "packages/mcp/node_modules/cookie-signature": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", + "engines": { + "node": ">=6.6.0" + } + }, + "packages/mcp/node_modules/finalhandler": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz", + "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==", + "dependencies": { + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "on-finished": "^2.4.1", + "parseurl": "^1.3.3", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "packages/mcp/node_modules/fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", + "engines": { + "node": ">= 0.8" + } + }, "packages/mcp/node_modules/glob": { "version": "10.4.5", "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", @@ -44047,6 +43875,17 @@ "url": "https://github.com/sponsors/isaacs" } }, + "packages/mcp/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "packages/mcp/node_modules/jackspeak": { "version": "3.4.3", "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", @@ -44062,6 +43901,44 @@ "@pkgjs/parseargs": "^0.11.0" } }, + "packages/mcp/node_modules/media-typer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", + "engines": { + "node": ">= 0.8" + } + }, + "packages/mcp/node_modules/merge-descriptors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", + "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "packages/mcp/node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "engines": { + "node": ">= 0.6" + } + }, + "packages/mcp/node_modules/mime-types": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", + "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", + "dependencies": { + "mime-db": "^1.54.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "packages/mcp/node_modules/minimatch": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", @@ -44077,6 +43954,50 @@ "url": "https://github.com/sponsors/isaacs" } }, + "packages/mcp/node_modules/negotiator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", + "engines": { + "node": ">= 0.6" + } + }, + "packages/mcp/node_modules/pkce-challenge": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-5.0.0.tgz", + "integrity": "sha512-ueGLflrrnvwB3xuo/uGob5pd5FN7l0MsLf0Z87o/UQmRtwjvfylfc9MurIxRAWywCYTgrvpXBcqjV4OfCYGCIQ==", + "engines": { + "node": ">=16.20.0" + } + }, + "packages/mcp/node_modules/qs": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "packages/mcp/node_modules/raw-body": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz", + "integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.6.3", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "packages/mcp/node_modules/rimraf": { "version": "5.0.10", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz", @@ -44091,6 +44012,54 @@ "funding": { "url": "https://github.com/sponsors/isaacs" } + }, + "packages/mcp/node_modules/send": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", + "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", + "dependencies": { + "debug": "^4.3.5", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "mime-types": "^3.0.1", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 18" + } + }, + "packages/mcp/node_modules/serve-static": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", + "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==", + "dependencies": { + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "parseurl": "^1.3.3", + "send": "^1.2.0" + }, + "engines": { + "node": ">= 18" + } + }, + "packages/mcp/node_modules/type-is": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", + "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", + "dependencies": { + "content-type": "^1.0.5", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" + }, + "engines": { + "node": ">= 0.6" + } } } } diff --git a/packages/mcp/package.json b/packages/mcp/package.json index 098efa8b5d..fcb17f7e69 100644 --- a/packages/mcp/package.json +++ b/packages/mcp/package.json @@ -1,21 +1,21 @@ { "name": "librechat-mcp", - "version": "1.1.0", - "type": "module", + "version": "1.2.0", + "type": "commonjs", "description": "MCP services for LibreChat", "main": "dist/index.js", "module": "dist/index.es.js", "types": "./dist/types/index.d.ts", "exports": { ".": { - "import": "./dist/index.es.js", + "require": "./dist/index.js", "types": "./dist/types/index.d.ts" } }, "scripts": { "clean": "rimraf dist", - "build": "npm run clean && rollup -c --configPlugin=@rollup/plugin-typescript", - "build:watch": "rollup -c -w --configPlugin=@rollup/plugin-typescript", + "build": "npm run clean && rollup -c --bundleConfigAsCjs", + "build:watch": "rollup -c -w --bundleConfigAsCjs", "test": "jest --coverage --watch", "test:ci": "jest --coverage --ci", "verify": "npm run test:ci", @@ -60,7 +60,6 @@ "rollup": "^4.22.4", "rollup-plugin-generate-package-json": "^3.2.0", "rollup-plugin-peer-deps-external": "^2.2.4", - "rollup-plugin-typescript2": "^0.35.0", "ts-node": "^10.9.2", "typescript": "^5.0.4" }, @@ -68,7 +67,7 @@ "registry": "https://registry.npmjs.org/" }, "dependencies": { - "@modelcontextprotocol/sdk": "^1.8.0", + "@modelcontextprotocol/sdk": "^1.9.0", "diff": "^7.0.0", "eventsource": "^3.0.2", "express": "^4.21.2" diff --git a/packages/mcp/rollup.config.js b/packages/mcp/rollup.config.js index 6bf8df24b2..6e17d6ee2f 100644 --- a/packages/mcp/rollup.config.js +++ b/packages/mcp/rollup.config.js @@ -1,11 +1,11 @@ // rollup.config.js -import typescript from 'rollup-plugin-typescript2'; -import resolve from '@rollup/plugin-node-resolve'; -import peerDepsExternal from 'rollup-plugin-peer-deps-external'; -import commonjs from '@rollup/plugin-commonjs'; -import replace from '@rollup/plugin-replace'; -import terser from '@rollup/plugin-terser'; import { readFileSync } from 'fs'; +import terser from '@rollup/plugin-terser'; +import replace from '@rollup/plugin-replace'; +import commonjs from '@rollup/plugin-commonjs'; +import resolve from '@rollup/plugin-node-resolve'; +import typescript from '@rollup/plugin-typescript'; +import peerDepsExternal from 'rollup-plugin-peer-deps-external'; const pkg = JSON.parse(readFileSync(new URL('./package.json', import.meta.url), 'utf8')); @@ -24,16 +24,18 @@ const plugins = [ }), typescript({ tsconfig: './tsconfig.json', - useTsconfigDeclarationDir: true, + outDir: './dist', + sourceMap: true, + inlineSourceMap: true, }), terser(), ]; -const esmBuild = { +const cjsBuild = { input: 'src/index.ts', output: { - file: pkg.module, - format: 'esm', + file: pkg.main, + format: 'cjs', sourcemap: true, exports: 'named', }, @@ -42,4 +44,4 @@ const esmBuild = { plugins, }; -export default esmBuild; +export default cjsBuild; diff --git a/packages/mcp/src/types/mcp.ts b/packages/mcp/src/types/mcp.ts index 106eb04e13..1ab99ff675 100644 --- a/packages/mcp/src/types/mcp.ts +++ b/packages/mcp/src/types/mcp.ts @@ -8,6 +8,7 @@ import { } from 'librechat-data-provider'; import type { JsonSchemaType, TPlugin } from 'librechat-data-provider'; import { ToolSchema, ListToolsResultSchema } from '@modelcontextprotocol/sdk/types.js'; +import type * as t from '@modelcontextprotocol/sdk/types.js'; export type StdioOptions = z.infer; export type WebSocketOptions = z.infer; @@ -44,25 +45,7 @@ export type ConnectionState = 'disconnected' | 'connecting' | 'connected' | 'err export type MCPTool = z.infer; export type MCPToolListResponse = z.infer; -export type ToolContentPart = - | { - type: 'text'; - text: string; - } - | { - type: 'image'; - data: string; - mimeType: string; - } - | { - type: 'resource'; - resource: { - uri: string; - mimeType?: string; - text?: string; - blob?: string; - }; - }; +export type ToolContentPart = t.TextContent | t.ImageContent | t.EmbeddedResource | t.AudioContent; export type ImageContent = Extract; export type MCPToolCallResponse = | undefined