✨ feat: add Model Context Protocol (MCP) support (#2809)
* ✨ feat: add Model Context Protocol (MCP) server configuration (main) - Added `@modelcontextprotocol/sdk` dependency for MCP integration. - Introduced MCP server configuration UI in settings with add, edit, delete, and activation functionalities. - Created `useMCPServers` hook to manage MCP server state and actions. - Added i18n support for MCP settings with translation keys. - Integrated MCP settings into the application's settings navigation and routing. - Implemented Redux state management for MCP servers. - Updated `yarn.lock` with new dependencies and their resolutions. * 🌟 feat: implement mcp service and integrate with ipc handlers - Added `MCPService` class to manage Model Context Protocol servers. - Implemented various handlers in `ipc.ts` for managing MCP servers including listing, adding, updating, deleting, and activating/deactivating servers. - Integrated MCP related types into existing type declarations for consistency across the application. - Updated `preload` to expose new MCP related APIs to the renderer process. - Enhanced `MCPSettings` component to interact directly with the new MCP service for adding, updating, deleting servers and setting their active states. - Introduced selectors in the MCP Redux slice for fetching active and all servers from the store. - Moved MCP types to a centralized location in `@renderer/types` for reuse across different parts of the application. * feat: enhance MCPService initialization to prevent recursive calls and improve error handling * feat: enhance MCP integration by adding MCPTool type and updating related methods * feat: implement streaming support for tool calls in OpenAIProvider and enhance message processing
This commit is contained in:
parent
ed23e9395c
commit
c95c7faa5f
@ -63,6 +63,7 @@
|
|||||||
"@llm-tools/embedjs-loader-web": "^0.1.28",
|
"@llm-tools/embedjs-loader-web": "^0.1.28",
|
||||||
"@llm-tools/embedjs-loader-xml": "^0.1.28",
|
"@llm-tools/embedjs-loader-xml": "^0.1.28",
|
||||||
"@llm-tools/embedjs-openai": "^0.1.28",
|
"@llm-tools/embedjs-openai": "^0.1.28",
|
||||||
|
"@modelcontextprotocol/sdk": "^1.6.1",
|
||||||
"@notionhq/client": "^2.2.15",
|
"@notionhq/client": "^2.2.15",
|
||||||
"@types/react-infinite-scroll-component": "^5.0.0",
|
"@types/react-infinite-scroll-component": "^5.0.0",
|
||||||
"adm-zip": "^0.5.16",
|
"adm-zip": "^0.5.16",
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import fs from 'node:fs'
|
import fs from 'node:fs'
|
||||||
import path from 'node:path'
|
import path from 'node:path'
|
||||||
|
|
||||||
import { Shortcut, ThemeMode } from '@types'
|
import { MCPServer, Shortcut, ThemeMode } from '@types'
|
||||||
import { BrowserWindow, ipcMain, ProxyConfig, session, shell } from 'electron'
|
import { BrowserWindow, ipcMain, ProxyConfig, session, shell } from 'electron'
|
||||||
import log from 'electron-log'
|
import log from 'electron-log'
|
||||||
|
|
||||||
@ -14,17 +14,18 @@ import FileService from './services/FileService'
|
|||||||
import FileStorage from './services/FileStorage'
|
import FileStorage from './services/FileStorage'
|
||||||
import { GeminiService } from './services/GeminiService'
|
import { GeminiService } from './services/GeminiService'
|
||||||
import KnowledgeService from './services/KnowledgeService'
|
import KnowledgeService from './services/KnowledgeService'
|
||||||
|
import MCPService from './services/mcp'
|
||||||
import { registerShortcuts, unregisterAllShortcuts } from './services/ShortcutService'
|
import { registerShortcuts, unregisterAllShortcuts } from './services/ShortcutService'
|
||||||
import { TrayService } from './services/TrayService'
|
import { TrayService } from './services/TrayService'
|
||||||
import { windowService } from './services/WindowService'
|
import { windowService } from './services/WindowService'
|
||||||
import { getResourcePath } from './utils'
|
import { getResourcePath } from './utils'
|
||||||
import { decrypt } from './utils/aes'
|
import { decrypt, encrypt } from './utils/aes'
|
||||||
import { encrypt } from './utils/aes'
|
|
||||||
import { compress, decompress } from './utils/zip'
|
import { compress, decompress } from './utils/zip'
|
||||||
|
|
||||||
const fileManager = new FileStorage()
|
const fileManager = new FileStorage()
|
||||||
const backupManager = new BackupManager()
|
const backupManager = new BackupManager()
|
||||||
const exportService = new ExportService(fileManager)
|
const exportService = new ExportService(fileManager)
|
||||||
|
const mcpService = new MCPService()
|
||||||
|
|
||||||
export function registerIpc(mainWindow: BrowserWindow, app: Electron.App) {
|
export function registerIpc(mainWindow: BrowserWindow, app: Electron.App) {
|
||||||
const appUpdater = new AppUpdater(mainWindow)
|
const appUpdater = new AppUpdater(mainWindow)
|
||||||
@ -210,4 +211,44 @@ export function registerIpc(mainWindow: BrowserWindow, app: Electron.App) {
|
|||||||
ipcMain.handle('aes:decrypt', (_, encryptedData: string, iv: string, secretKey: string) =>
|
ipcMain.handle('aes:decrypt', (_, encryptedData: string, iv: string, secretKey: string) =>
|
||||||
decrypt(encryptedData, iv, secretKey)
|
decrypt(encryptedData, iv, secretKey)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Register MCP handlers
|
||||||
|
ipcMain.handle('mcp:list-servers', async () => {
|
||||||
|
return mcpService.listAvailableServices()
|
||||||
|
})
|
||||||
|
|
||||||
|
ipcMain.handle('mcp:add-server', async (_, server: MCPServer) => {
|
||||||
|
return mcpService.addServer(server)
|
||||||
|
})
|
||||||
|
|
||||||
|
ipcMain.handle('mcp:update-server', async (_, server: MCPServer) => {
|
||||||
|
return mcpService.updateServer(server)
|
||||||
|
})
|
||||||
|
|
||||||
|
ipcMain.handle('mcp:delete-server', async (_, serverName: string) => {
|
||||||
|
return mcpService.deleteServer(serverName)
|
||||||
|
})
|
||||||
|
|
||||||
|
ipcMain.handle('mcp:set-server-active', async (_, { name, isActive }) => {
|
||||||
|
return mcpService.setServerActive({ name, isActive })
|
||||||
|
})
|
||||||
|
|
||||||
|
// According to preload, this should take no parameters, but our implementation accepts
|
||||||
|
// an optional serverName for better flexibility
|
||||||
|
ipcMain.handle('mcp:list-tools', async (_, serverName?: string) => {
|
||||||
|
return mcpService.listTools(serverName)
|
||||||
|
})
|
||||||
|
|
||||||
|
ipcMain.handle('mcp:call-tool', async (_, params: { client: string; name: string; args: any }) => {
|
||||||
|
return mcpService.callTool(params)
|
||||||
|
})
|
||||||
|
|
||||||
|
ipcMain.handle('mcp:cleanup', async () => {
|
||||||
|
return mcpService.cleanup()
|
||||||
|
})
|
||||||
|
|
||||||
|
// Clean up MCP services when app quits
|
||||||
|
app.on('before-quit', async () => {
|
||||||
|
await mcpService.cleanup()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
337
src/main/services/mcp.ts
Normal file
337
src/main/services/mcp.ts
Normal file
@ -0,0 +1,337 @@
|
|||||||
|
import { MCPServer, MCPTool } from '@types'
|
||||||
|
import log from 'electron-log'
|
||||||
|
import Store from 'electron-store'
|
||||||
|
import { EventEmitter } from 'events'
|
||||||
|
|
||||||
|
const store = new Store()
|
||||||
|
|
||||||
|
export default class MCPService extends EventEmitter {
|
||||||
|
private activeServers: Map<string, any> = new Map()
|
||||||
|
private clients: { [key: string]: any } = {}
|
||||||
|
private Client: any
|
||||||
|
private Transport: any
|
||||||
|
private initialized = false
|
||||||
|
private initPromise: Promise<void> | null = null
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super()
|
||||||
|
this.init().catch((err) => {
|
||||||
|
log.error('[MCP] Failed to initialize MCP service:', err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
private getServersFromStore(): MCPServer[] {
|
||||||
|
return store.get('mcp.servers', []) as MCPServer[]
|
||||||
|
}
|
||||||
|
|
||||||
|
public async init() {
|
||||||
|
// If already initialized, return immediately
|
||||||
|
if (this.initialized) return
|
||||||
|
|
||||||
|
// If initialization is in progress, return that promise
|
||||||
|
if (this.initPromise) return this.initPromise
|
||||||
|
|
||||||
|
// Create and store the initialization promise
|
||||||
|
this.initPromise = (async () => {
|
||||||
|
try {
|
||||||
|
log.info('[MCP] Starting initialization')
|
||||||
|
this.Client = await this.importClient()
|
||||||
|
this.Transport = await this.importTransport()
|
||||||
|
|
||||||
|
// Mark as initialized before loading servers to prevent recursive initialization
|
||||||
|
this.initialized = true
|
||||||
|
|
||||||
|
await this.load(this.getServersFromStore())
|
||||||
|
log.info('[MCP] Initialization completed successfully')
|
||||||
|
} catch (err) {
|
||||||
|
this.initialized = false // Reset flag on error
|
||||||
|
log.error('[MCP] Failed to initialize:', err)
|
||||||
|
throw err
|
||||||
|
} finally {
|
||||||
|
this.initPromise = null
|
||||||
|
}
|
||||||
|
})()
|
||||||
|
|
||||||
|
return this.initPromise
|
||||||
|
}
|
||||||
|
|
||||||
|
private async importClient() {
|
||||||
|
try {
|
||||||
|
const { Client } = await import('@modelcontextprotocol/sdk/client/index.js')
|
||||||
|
return Client
|
||||||
|
} catch (err) {
|
||||||
|
log.error('[MCP] Failed to import Client:', err)
|
||||||
|
throw err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async importTransport() {
|
||||||
|
try {
|
||||||
|
const { StdioClientTransport } = await import('@modelcontextprotocol/sdk/client/stdio.js')
|
||||||
|
return StdioClientTransport
|
||||||
|
} catch (err) {
|
||||||
|
log.error('[MCP] Failed to import Transport:', err)
|
||||||
|
throw err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async listAvailableServices(): Promise<MCPServer[]> {
|
||||||
|
await this.ensureInitialized()
|
||||||
|
return this.getServersFromStore()
|
||||||
|
}
|
||||||
|
|
||||||
|
private async ensureInitialized() {
|
||||||
|
if (!this.initialized) {
|
||||||
|
log.debug('[MCP] Ensuring initialization')
|
||||||
|
await this.init()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async addServer(server: MCPServer): Promise<void> {
|
||||||
|
await this.ensureInitialized()
|
||||||
|
try {
|
||||||
|
const servers = this.getServersFromStore()
|
||||||
|
if (servers.some((s) => s.name === server.name)) {
|
||||||
|
throw new Error(`Server with name ${server.name} already exists`)
|
||||||
|
}
|
||||||
|
|
||||||
|
servers.push(server)
|
||||||
|
store.set('mcp.servers', servers)
|
||||||
|
|
||||||
|
if (server.isActive) {
|
||||||
|
await this.activate(server)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
log.error('Failed to add MCP server:', error)
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async updateServer(server: MCPServer): Promise<void> {
|
||||||
|
await this.ensureInitialized()
|
||||||
|
try {
|
||||||
|
const servers = this.getServersFromStore()
|
||||||
|
const index = servers.findIndex((s) => s.name === server.name)
|
||||||
|
|
||||||
|
if (index === -1) {
|
||||||
|
throw new Error(`Server ${server.name} not found`)
|
||||||
|
}
|
||||||
|
|
||||||
|
const wasActive = servers[index].isActive
|
||||||
|
if (wasActive && !server.isActive) {
|
||||||
|
await this.deactivate(server.name)
|
||||||
|
} else if (!wasActive && server.isActive) {
|
||||||
|
await this.activate(server)
|
||||||
|
}
|
||||||
|
|
||||||
|
servers[index] = server
|
||||||
|
store.set('mcp.servers', servers)
|
||||||
|
} catch (error) {
|
||||||
|
log.error('Failed to update MCP server:', error)
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async deleteServer(serverName: string): Promise<void> {
|
||||||
|
await this.ensureInitialized()
|
||||||
|
try {
|
||||||
|
if (this.clients[serverName]) {
|
||||||
|
await this.deactivate(serverName)
|
||||||
|
}
|
||||||
|
|
||||||
|
const servers = this.getServersFromStore()
|
||||||
|
const filteredServers = servers.filter((s) => s.name !== serverName)
|
||||||
|
store.set('mcp.servers', filteredServers)
|
||||||
|
} catch (error) {
|
||||||
|
log.error('Failed to delete MCP server:', error)
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async setServerActive(params: { name: string; isActive: boolean }): Promise<void> {
|
||||||
|
await this.ensureInitialized()
|
||||||
|
try {
|
||||||
|
const { name, isActive } = params
|
||||||
|
const servers = this.getServersFromStore()
|
||||||
|
const server = servers.find((s) => s.name === name)
|
||||||
|
|
||||||
|
if (!server) {
|
||||||
|
throw new Error(`Server ${name} not found`)
|
||||||
|
}
|
||||||
|
|
||||||
|
server.isActive = isActive
|
||||||
|
store.set('mcp.servers', servers)
|
||||||
|
|
||||||
|
if (isActive) {
|
||||||
|
await this.activate(server)
|
||||||
|
} else {
|
||||||
|
await this.deactivate(name)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
log.error('Failed to set MCP server active status:', error)
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async activate(server: MCPServer): Promise<void> {
|
||||||
|
await this.ensureInitialized()
|
||||||
|
try {
|
||||||
|
const { name, command, args, env } = server
|
||||||
|
|
||||||
|
if (this.clients[name]) {
|
||||||
|
log.info(`[MCP] Server ${name} is already running`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let cmd: string = command
|
||||||
|
if (command === 'npx') {
|
||||||
|
cmd = process.platform === 'win32' ? `${command}.cmd` : command
|
||||||
|
}
|
||||||
|
|
||||||
|
const mergedEnv = {
|
||||||
|
...env,
|
||||||
|
PATH: process.env.PATH
|
||||||
|
}
|
||||||
|
|
||||||
|
const client = new this.Client(
|
||||||
|
{
|
||||||
|
name: name,
|
||||||
|
version: '1.0.0'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
capabilities: {}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
const transport = new this.Transport({
|
||||||
|
command: cmd,
|
||||||
|
args,
|
||||||
|
stderr: process.platform === 'win32' ? 'pipe' : 'inherit',
|
||||||
|
env: mergedEnv
|
||||||
|
})
|
||||||
|
|
||||||
|
await client.connect(transport)
|
||||||
|
this.clients[name] = client
|
||||||
|
this.activeServers.set(name, { client, server })
|
||||||
|
|
||||||
|
log.info(`[MCP] Server ${name} started successfully`)
|
||||||
|
this.emit('server-started', { name })
|
||||||
|
} catch (error) {
|
||||||
|
log.error('[MCP] Error activating server:', error)
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async deactivate(name: string): Promise<void> {
|
||||||
|
await this.ensureInitialized()
|
||||||
|
try {
|
||||||
|
if (this.clients[name]) {
|
||||||
|
log.info(`[MCP] Stopping server: ${name}`)
|
||||||
|
await this.clients[name].close()
|
||||||
|
delete this.clients[name]
|
||||||
|
this.activeServers.delete(name)
|
||||||
|
this.emit('server-stopped', { name })
|
||||||
|
} else {
|
||||||
|
log.warn(`[MCP] Server ${name} is not running`)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
log.error('[MCP] Error deactivating server:', error)
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async listTools(serverName?: string): Promise<MCPTool[]> {
|
||||||
|
await this.ensureInitialized()
|
||||||
|
try {
|
||||||
|
if (serverName) {
|
||||||
|
if (!this.clients[serverName]) {
|
||||||
|
throw new Error(`MCP Client ${serverName} not found`)
|
||||||
|
}
|
||||||
|
const { tools } = await this.clients[serverName].listTools()
|
||||||
|
return tools.map((tool: any) => {
|
||||||
|
return tool
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
let allTools: MCPTool[] = []
|
||||||
|
for (const clientName in this.clients) {
|
||||||
|
try {
|
||||||
|
const { tools } = await this.clients[clientName].listTools()
|
||||||
|
log.info(`[MCP] Tools for ${clientName}:`, tools)
|
||||||
|
allTools = allTools.concat(
|
||||||
|
tools.map((tool: MCPTool) => {
|
||||||
|
tool.serverName = clientName
|
||||||
|
return tool
|
||||||
|
})
|
||||||
|
)
|
||||||
|
} catch (error) {
|
||||||
|
log.error(`[MCP] Error listing tools for ${clientName}:`, error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.info(`[MCP] Total tools listed: ${allTools.length}`)
|
||||||
|
return allTools
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
log.error('[MCP] Error listing tools:', error)
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async callTool(params: { client: string; name: string; args: any }): Promise<any> {
|
||||||
|
await this.ensureInitialized()
|
||||||
|
try {
|
||||||
|
const { client, name, args } = params
|
||||||
|
if (!this.clients[client]) {
|
||||||
|
throw new Error(`MCP Client ${client} not found`)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info('[MCP] Calling:', client, name, args)
|
||||||
|
const result = await this.clients[client].callTool({
|
||||||
|
name,
|
||||||
|
arguments: args
|
||||||
|
})
|
||||||
|
return result
|
||||||
|
} catch (error) {
|
||||||
|
log.error(`[MCP] Error calling tool ${params.name} on ${params.client}:`, error)
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async cleanup(): Promise<void> {
|
||||||
|
try {
|
||||||
|
for (const name in this.clients) {
|
||||||
|
await this.deactivate(name).catch((err) => {
|
||||||
|
log.error(`[MCP] Error during cleanup of ${name}:`, err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.clients = {}
|
||||||
|
this.activeServers.clear()
|
||||||
|
log.info('[MCP] All servers cleaned up')
|
||||||
|
} catch (error) {
|
||||||
|
log.error('[MCP] Failed to clean up servers:', error)
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async load(servers: MCPServer[]): Promise<void> {
|
||||||
|
log.info(`[MCP] Loading ${servers.length} servers`)
|
||||||
|
|
||||||
|
const activeServers = servers.filter((server) => server.isActive)
|
||||||
|
|
||||||
|
if (activeServers.length === 0) {
|
||||||
|
log.info('[MCP] No active servers to load')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const server of activeServers) {
|
||||||
|
log.info(`[MCP] Activating server: ${server.name}`)
|
||||||
|
try {
|
||||||
|
await this.activate(server)
|
||||||
|
log.info(`[MCP] Successfully activated server: ${server.name}`)
|
||||||
|
} catch (error) {
|
||||||
|
log.error(`[MCP] Failed to activate server ${server.name}:`, error)
|
||||||
|
this.emit('server-error', { name: server.name, error })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info(`[MCP] Loaded and activated ${Object.keys(this.clients).length} servers`)
|
||||||
|
}
|
||||||
|
}
|
||||||
17
src/preload/index.d.ts
vendored
17
src/preload/index.d.ts
vendored
@ -1,9 +1,7 @@
|
|||||||
import { ElectronAPI } from '@electron-toolkit/preload'
|
import { ElectronAPI } from '@electron-toolkit/preload'
|
||||||
import type { FileMetadataResponse, ListFilesResponse, UploadFileResponse } from '@google/generative-ai/server'
|
import type { FileMetadataResponse, ListFilesResponse, UploadFileResponse } from '@google/generative-ai/server'
|
||||||
import { ExtractChunkData } from '@llm-tools/embedjs-interfaces'
|
import { ExtractChunkData } from '@llm-tools/embedjs-interfaces'
|
||||||
import { FileType } from '@renderer/types'
|
import { AppInfo, FileType, KnowledgeBaseParams, KnowledgeItem, LanguageVarious, WebDavConfig } from '@renderer/types'
|
||||||
import { WebDavConfig } from '@renderer/types'
|
|
||||||
import { AppInfo, KnowledgeBaseParams, KnowledgeItem, LanguageVarious } from '@renderer/types'
|
|
||||||
import type { LoaderReturn } from '@shared/config/types'
|
import type { LoaderReturn } from '@shared/config/types'
|
||||||
import type { OpenDialogOptions } from 'electron'
|
import type { OpenDialogOptions } from 'electron'
|
||||||
import type { UpdateInfo } from 'electron-updater'
|
import type { UpdateInfo } from 'electron-updater'
|
||||||
@ -123,6 +121,19 @@ declare global {
|
|||||||
shell: {
|
shell: {
|
||||||
openExternal: (url: string, options?: OpenExternalOptions) => Promise<void>
|
openExternal: (url: string, options?: OpenExternalOptions) => Promise<void>
|
||||||
}
|
}
|
||||||
|
mcp: {
|
||||||
|
// servers
|
||||||
|
listServers: () => Promise<MCPServer[]>
|
||||||
|
addServer: (server: MCPServer) => Promise<void>
|
||||||
|
updateServer: (server: MCPServer) => Promise<void>
|
||||||
|
deleteServer: (serverName: string) => Promise<void>
|
||||||
|
setServerActive: (name: string, isActive: boolean) => Promise<void>
|
||||||
|
// tools
|
||||||
|
listTools: () => Promise<MCPTool>
|
||||||
|
callTool: ({ client, name, args }: { client: string; name: string; args: any }) => Promise<any>
|
||||||
|
// status
|
||||||
|
cleanup: () => Promise<void>
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { electronAPI } from '@electron-toolkit/preload'
|
import { electronAPI } from '@electron-toolkit/preload'
|
||||||
import { FileType, KnowledgeBaseParams, KnowledgeItem, Shortcut, WebDavConfig } from '@types'
|
import { FileType, KnowledgeBaseParams, KnowledgeItem, MCPServer, Shortcut, WebDavConfig } from '@types'
|
||||||
import { contextBridge, ipcRenderer, OpenDialogOptions, shell } from 'electron'
|
import { contextBridge, ipcRenderer, OpenDialogOptions, shell } from 'electron'
|
||||||
|
|
||||||
// Custom APIs for renderer
|
// Custom APIs for renderer
|
||||||
@ -106,6 +106,17 @@ const api = {
|
|||||||
decrypt: (encryptedData: string, iv: string, secretKey: string) =>
|
decrypt: (encryptedData: string, iv: string, secretKey: string) =>
|
||||||
ipcRenderer.invoke('aes:decrypt', encryptedData, iv, secretKey)
|
ipcRenderer.invoke('aes:decrypt', encryptedData, iv, secretKey)
|
||||||
},
|
},
|
||||||
|
mcp: {
|
||||||
|
listServers: () => ipcRenderer.invoke('mcp:list-servers'),
|
||||||
|
addServer: (server: MCPServer) => ipcRenderer.invoke('mcp:add-server', server),
|
||||||
|
updateServer: (server: MCPServer) => ipcRenderer.invoke('mcp:update-server', server),
|
||||||
|
deleteServer: (serverName: string) => ipcRenderer.invoke('mcp:delete-server', serverName),
|
||||||
|
setServerActive: (name: string, isActive: boolean) =>
|
||||||
|
ipcRenderer.invoke('mcp:set-server-active', { name, isActive }),
|
||||||
|
listTools: (serverName?: string) => ipcRenderer.invoke('mcp:list-tools', serverName),
|
||||||
|
callTool: (params: { client: string; name: string; args: any }) => ipcRenderer.invoke('mcp:call-tool', params),
|
||||||
|
cleanup: () => ipcRenderer.invoke('mcp:cleanup')
|
||||||
|
},
|
||||||
shell: {
|
shell: {
|
||||||
openExternal: shell.openExternal
|
openExternal: shell.openExternal
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,8 +19,7 @@ import {
|
|||||||
updateItemProcessingStatus,
|
updateItemProcessingStatus,
|
||||||
updateNotes
|
updateNotes
|
||||||
} from '@renderer/store/knowledge'
|
} from '@renderer/store/knowledge'
|
||||||
import { FileType, KnowledgeBase, ProcessingStatus } from '@renderer/types'
|
import { FileType, KnowledgeBase, KnowledgeItem, ProcessingStatus } from '@renderer/types'
|
||||||
import { KnowledgeItem } from '@renderer/types'
|
|
||||||
import { runAsyncFunction } from '@renderer/utils'
|
import { runAsyncFunction } from '@renderer/utils'
|
||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import { useDispatch, useSelector } from 'react-redux'
|
import { useDispatch, useSelector } from 'react-redux'
|
||||||
|
|||||||
42
src/renderer/src/hooks/useMCPServers.ts
Normal file
42
src/renderer/src/hooks/useMCPServers.ts
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
import { useAppDispatch, useAppSelector } from '@renderer/store'
|
||||||
|
import {
|
||||||
|
addMCPServer as _addMCPServer,
|
||||||
|
deleteMCPServer as _deleteMCPServer,
|
||||||
|
setMCPServerActive as _setMCPServerActive,
|
||||||
|
updateMCPServer as _updateMCPServer
|
||||||
|
} from '@renderer/store/mcp'
|
||||||
|
import { MCPServer } from '@renderer/types'
|
||||||
|
|
||||||
|
export const useMCPServers = () => {
|
||||||
|
const mcpServers = useAppSelector((state) => state.mcp.servers)
|
||||||
|
const dispatch = useAppDispatch()
|
||||||
|
|
||||||
|
const addMCPServer = (server: MCPServer) => {
|
||||||
|
dispatch(_addMCPServer(server))
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateMCPServer = (server: MCPServer) => {
|
||||||
|
dispatch(_updateMCPServer(server))
|
||||||
|
}
|
||||||
|
|
||||||
|
const deleteMCPServer = (name: string) => {
|
||||||
|
dispatch(_deleteMCPServer(name))
|
||||||
|
}
|
||||||
|
|
||||||
|
const setMCPServerActive = (name: string, isActive: boolean) => {
|
||||||
|
dispatch(_setMCPServerActive({ name, isActive }))
|
||||||
|
}
|
||||||
|
|
||||||
|
const getActiveMCPServers = () => {
|
||||||
|
return mcpServers.filter((server) => server.isActive)
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
mcpServers,
|
||||||
|
addMCPServer,
|
||||||
|
updateMCPServer,
|
||||||
|
deleteMCPServer,
|
||||||
|
setMCPServerActive,
|
||||||
|
getActiveMCPServers
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -859,6 +859,32 @@
|
|||||||
"blacklist_tooltip": "Please use the following format (separated by line breaks)\nexample.com\nhttps://www.example.com\nhttps://example.com\n*://*.example.com",
|
"blacklist_tooltip": "Please use the following format (separated by line breaks)\nexample.com\nhttps://www.example.com\nhttps://example.com\n*://*.example.com",
|
||||||
"search_max_result": "Number of search results",
|
"search_max_result": "Number of search results",
|
||||||
"search_result_default": "Default"
|
"search_result_default": "Default"
|
||||||
|
},
|
||||||
|
"mcp": {
|
||||||
|
"title": "MCP Servers",
|
||||||
|
"config_description": "Configure Model Context Protocol servers",
|
||||||
|
"description": "Description",
|
||||||
|
"addServer": "Add Server",
|
||||||
|
"editServer": "Edit Server",
|
||||||
|
"name": "Name",
|
||||||
|
"command": "Command",
|
||||||
|
"args": "Arguments",
|
||||||
|
"argsTooltip": "Each argument on a new line",
|
||||||
|
"env": "Environment Variables",
|
||||||
|
"envTooltip": "Format: KEY=value, one per line",
|
||||||
|
"active": "Active",
|
||||||
|
"actions": "Actions",
|
||||||
|
"noServers": "No servers configured",
|
||||||
|
"nameRequired": "Please enter a server name",
|
||||||
|
"commandRequired": "Please enter a command",
|
||||||
|
"confirmDelete": "Delete Server",
|
||||||
|
"confirmDeleteMessage": "Are you sure you want to delete the server?",
|
||||||
|
"addSuccess": "Server added successfully",
|
||||||
|
"updateSuccess": "Server updated successfully",
|
||||||
|
"deleteSuccess": "Server deleted successfully",
|
||||||
|
"duplicateName": "A server with this name already exists",
|
||||||
|
"serverSingular": "server",
|
||||||
|
"serverPlural": "servers"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"translate": {
|
"translate": {
|
||||||
|
|||||||
299
src/renderer/src/pages/settings/MCPSettings.tsx
Normal file
299
src/renderer/src/pages/settings/MCPSettings.tsx
Normal file
@ -0,0 +1,299 @@
|
|||||||
|
import { DeleteOutlined, EditOutlined, PlusOutlined, QuestionCircleOutlined } from '@ant-design/icons'
|
||||||
|
import { useTheme } from '@renderer/context/ThemeProvider'
|
||||||
|
import { useAppDispatch, useAppSelector } from '@renderer/store'
|
||||||
|
import { addMCPServer, deleteMCPServer, setMCPServerActive, updateMCPServer } from '@renderer/store/mcp'
|
||||||
|
import { MCPServer } from '@renderer/types'
|
||||||
|
import { Button, Card, Form, Input, message, Modal, Space, Switch, Table, Tooltip, Typography } from 'antd'
|
||||||
|
import TextArea from 'antd/es/input/TextArea'
|
||||||
|
import { FC, useState } from 'react'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
|
import { SettingContainer, SettingDivider, SettingGroup, SettingTitle } from '.'
|
||||||
|
|
||||||
|
interface MCPFormValues {
|
||||||
|
name: string
|
||||||
|
command: string
|
||||||
|
description?: string
|
||||||
|
args: string
|
||||||
|
env?: string
|
||||||
|
isActive: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
const MCPSettings: FC = () => {
|
||||||
|
const { t } = useTranslation()
|
||||||
|
const { theme } = useTheme()
|
||||||
|
const { Paragraph, Text } = Typography
|
||||||
|
const dispatch = useAppDispatch()
|
||||||
|
const mcpServers = useAppSelector((state) => state.mcp.servers)
|
||||||
|
|
||||||
|
const [isModalVisible, setIsModalVisible] = useState(false)
|
||||||
|
const [editingServer, setEditingServer] = useState<MCPServer | null>(null)
|
||||||
|
const [loading, setLoading] = useState(false)
|
||||||
|
const [form] = Form.useForm<MCPFormValues>()
|
||||||
|
|
||||||
|
const showAddModal = () => {
|
||||||
|
form.resetFields()
|
||||||
|
setEditingServer(null)
|
||||||
|
setIsModalVisible(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
const showEditModal = (server: MCPServer) => {
|
||||||
|
setEditingServer(server)
|
||||||
|
form.setFieldsValue({
|
||||||
|
name: server.name,
|
||||||
|
command: server.command,
|
||||||
|
description: server.description,
|
||||||
|
args: server.args.join('\n'),
|
||||||
|
env: server.env
|
||||||
|
? Object.entries(server.env)
|
||||||
|
.map(([key, value]) => `${key}=${value}`)
|
||||||
|
.join('\n')
|
||||||
|
: '',
|
||||||
|
isActive: server.isActive
|
||||||
|
})
|
||||||
|
setIsModalVisible(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleCancel = () => {
|
||||||
|
setIsModalVisible(false)
|
||||||
|
form.resetFields()
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSubmit = () => {
|
||||||
|
setLoading(true)
|
||||||
|
form
|
||||||
|
.validateFields()
|
||||||
|
.then((values) => {
|
||||||
|
const args = values.args ? values.args.split('\n').filter((arg) => arg.trim() !== '') : []
|
||||||
|
|
||||||
|
const env: Record<string, string> = {}
|
||||||
|
if (values.env) {
|
||||||
|
values.env.split('\n').forEach((line) => {
|
||||||
|
if (line.trim()) {
|
||||||
|
const [key, value] = line.split('=')
|
||||||
|
if (key && value) {
|
||||||
|
env[key.trim()] = value.trim()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const mcpServer: MCPServer = {
|
||||||
|
name: values.name,
|
||||||
|
command: values.command,
|
||||||
|
description: values.description,
|
||||||
|
args,
|
||||||
|
env: Object.keys(env).length > 0 ? env : undefined,
|
||||||
|
isActive: values.isActive
|
||||||
|
}
|
||||||
|
|
||||||
|
if (editingServer) {
|
||||||
|
window.api.mcp
|
||||||
|
.updateServer(mcpServer)
|
||||||
|
.then(() => {
|
||||||
|
message.success(t('settings.mcp.updateSuccess'))
|
||||||
|
setLoading(false)
|
||||||
|
setIsModalVisible(false)
|
||||||
|
form.resetFields()
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
message.error(`${t('settings.mcp.updateError')}: ${error.message}`)
|
||||||
|
setLoading(false)
|
||||||
|
})
|
||||||
|
dispatch(updateMCPServer(mcpServer))
|
||||||
|
} else {
|
||||||
|
// Check for duplicate name
|
||||||
|
if (mcpServers.some((server: MCPServer) => server.name === mcpServer.name)) {
|
||||||
|
message.error(t('settings.mcp.duplicateName'))
|
||||||
|
setLoading(false)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
window.api.mcp
|
||||||
|
.addServer(mcpServer)
|
||||||
|
.then(() => {
|
||||||
|
message.success(t('settings.mcp.addSuccess'))
|
||||||
|
setLoading(false)
|
||||||
|
setIsModalVisible(false)
|
||||||
|
form.resetFields()
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
message.error(`${t('settings.mcp.addError')}: ${error.message}`)
|
||||||
|
setLoading(false)
|
||||||
|
})
|
||||||
|
dispatch(addMCPServer(mcpServer))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
setLoading(false)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleDelete = (serverName: string) => {
|
||||||
|
Modal.confirm({
|
||||||
|
title: t('settings.mcp.confirmDelete'),
|
||||||
|
content: t('settings.mcp.confirmDeleteMessage'),
|
||||||
|
okText: t('common.delete'),
|
||||||
|
okButtonProps: { danger: true },
|
||||||
|
cancelText: t('common.cancel'),
|
||||||
|
onOk: () => {
|
||||||
|
window.api.mcp
|
||||||
|
.deleteServer(serverName)
|
||||||
|
.then(() => {
|
||||||
|
message.success(t('settings.mcp.deleteSuccess'))
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
message.error(`${t('settings.mcp.deleteError')}: ${error.message}`)
|
||||||
|
})
|
||||||
|
dispatch(deleteMCPServer(serverName))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleToggleActive = (name: string, isActive: boolean) => {
|
||||||
|
window.api.mcp
|
||||||
|
.setServerActive(name, isActive)
|
||||||
|
.then(() => {
|
||||||
|
// Optional: Show success message or update UI
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
message.error(`${t('settings.mcp.toggleError')}: ${error.message}`)
|
||||||
|
})
|
||||||
|
dispatch(setMCPServerActive({ name, isActive }))
|
||||||
|
}
|
||||||
|
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
title: t('settings.mcp.name'),
|
||||||
|
dataIndex: 'name',
|
||||||
|
key: 'name',
|
||||||
|
width: '20%',
|
||||||
|
render: (text: string, record: MCPServer) => <Text strong={record.isActive}>{text}</Text>
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t('settings.mcp.description'),
|
||||||
|
dataIndex: 'description',
|
||||||
|
key: 'description',
|
||||||
|
width: '40%',
|
||||||
|
render: (text: string) =>
|
||||||
|
text || (
|
||||||
|
<Text type="secondary" italic>
|
||||||
|
{t('common.description')}
|
||||||
|
</Text>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t('settings.mcp.active'),
|
||||||
|
dataIndex: 'isActive',
|
||||||
|
key: 'isActive',
|
||||||
|
width: '15%',
|
||||||
|
render: (isActive: boolean, record: MCPServer) => (
|
||||||
|
<Switch checked={isActive} onChange={(checked) => handleToggleActive(record.name, checked)} />
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t('settings.mcp.actions'),
|
||||||
|
key: 'actions',
|
||||||
|
width: '25%',
|
||||||
|
render: (_: any, record: MCPServer) => (
|
||||||
|
<Space>
|
||||||
|
<Tooltip title={t('common.edit')}>
|
||||||
|
<Button type="primary" ghost icon={<EditOutlined />} onClick={() => showEditModal(record)} />
|
||||||
|
</Tooltip>
|
||||||
|
<Tooltip title={t('common.delete')}>
|
||||||
|
<Button danger icon={<DeleteOutlined />} onClick={() => handleDelete(record.name)} />
|
||||||
|
</Tooltip>
|
||||||
|
</Space>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
// Create a CSS class for inactive rows instead of using jsx global
|
||||||
|
const inactiveRowStyle = {
|
||||||
|
opacity: 0.7,
|
||||||
|
backgroundColor: theme === 'dark' ? '#1a1a1a' : '#f5f5f5'
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SettingContainer theme={theme}>
|
||||||
|
<SettingGroup theme={theme}>
|
||||||
|
<SettingTitle>
|
||||||
|
{t('settings.mcp.title')}
|
||||||
|
<Tooltip title={t('settings.mcp.config_description')}>
|
||||||
|
<QuestionCircleOutlined style={{ marginLeft: 8, fontSize: 14 }} />
|
||||||
|
</Tooltip>
|
||||||
|
</SettingTitle>
|
||||||
|
<SettingDivider />
|
||||||
|
<Paragraph type="secondary" style={{ margin: '0 0 20px 0' }}>
|
||||||
|
{t('settings.mcp.config_description')}
|
||||||
|
</Paragraph>
|
||||||
|
|
||||||
|
<div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 16 }}>
|
||||||
|
<Button type="primary" icon={<PlusOutlined />} onClick={showAddModal}>
|
||||||
|
{t('settings.mcp.addServer')}
|
||||||
|
</Button>
|
||||||
|
<Text type="secondary">
|
||||||
|
{mcpServers.length}{' '}
|
||||||
|
{mcpServers.length === 1 ? t('settings.mcp.serverSingular') : t('settings.mcp.serverPlural')}
|
||||||
|
</Text>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Card bordered={false} style={{ background: theme === 'dark' ? '#1f1f1f' : '#fff' }}>
|
||||||
|
<Table
|
||||||
|
dataSource={mcpServers}
|
||||||
|
columns={columns}
|
||||||
|
rowKey="name"
|
||||||
|
pagination={false}
|
||||||
|
locale={{ emptyText: t('settings.mcp.noServers') }}
|
||||||
|
rowClassName={(record) => (!record.isActive ? 'inactive-row' : '')}
|
||||||
|
onRow={(record) => ({
|
||||||
|
style: !record.isActive ? inactiveRowStyle : {}
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
<Modal
|
||||||
|
title={editingServer ? t('settings.mcp.editServer') : t('settings.mcp.addServer')}
|
||||||
|
open={isModalVisible}
|
||||||
|
onCancel={handleCancel}
|
||||||
|
onOk={handleSubmit}
|
||||||
|
confirmLoading={loading}
|
||||||
|
width={600}>
|
||||||
|
<Form form={form} layout="vertical">
|
||||||
|
<Form.Item
|
||||||
|
name="name"
|
||||||
|
label={t('settings.mcp.name')}
|
||||||
|
rules={[{ required: true, message: t('settings.mcp.nameRequired') }]}>
|
||||||
|
<Input disabled={!!editingServer} placeholder={t('common.name')} />
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
|
<Form.Item name="description" label={t('settings.mcp.description')}>
|
||||||
|
<TextArea rows={2} placeholder={t('common.description')} />
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
|
<Form.Item
|
||||||
|
name="command"
|
||||||
|
label={t('settings.mcp.command')}
|
||||||
|
rules={[{ required: true, message: t('settings.mcp.commandRequired') }]}>
|
||||||
|
<Input placeholder="python script.py" />
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
|
<Form.Item name="args" label={t('settings.mcp.args')} tooltip={t('settings.mcp.argsTooltip')}>
|
||||||
|
<TextArea rows={3} placeholder="{--param1}\n{--param2 value}" style={{ fontFamily: 'monospace' }} />
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
|
<Form.Item name="env" label={t('settings.mcp.env')} tooltip={t('settings.mcp.envTooltip')}>
|
||||||
|
<TextArea rows={3} placeholder="KEY1=value1\nKEY2=value2" style={{ fontFamily: 'monospace' }} />
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
|
<Form.Item name="isActive" label={t('settings.mcp.active')} valuePropName="checked" initialValue={true}>
|
||||||
|
<Switch />
|
||||||
|
</Form.Item>
|
||||||
|
</Form>
|
||||||
|
</Modal>
|
||||||
|
</SettingGroup>
|
||||||
|
</SettingContainer>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MCPSettings
|
||||||
@ -1,5 +1,6 @@
|
|||||||
import {
|
import {
|
||||||
CloudOutlined,
|
CloudOutlined,
|
||||||
|
CodeOutlined,
|
||||||
GlobalOutlined,
|
GlobalOutlined,
|
||||||
InfoCircleOutlined,
|
InfoCircleOutlined,
|
||||||
LayoutOutlined,
|
LayoutOutlined,
|
||||||
@ -20,6 +21,7 @@ import AboutSettings from './AboutSettings'
|
|||||||
import DataSettings from './DataSettings/DataSettings'
|
import DataSettings from './DataSettings/DataSettings'
|
||||||
import DisplaySettings from './DisplaySettings/DisplaySettings'
|
import DisplaySettings from './DisplaySettings/DisplaySettings'
|
||||||
import GeneralSettings from './GeneralSettings'
|
import GeneralSettings from './GeneralSettings'
|
||||||
|
import MCPSettings from './MCPSettings'
|
||||||
import ProvidersList from './ProviderSettings'
|
import ProvidersList from './ProviderSettings'
|
||||||
import QuickAssistantSettings from './QuickAssistantSettings'
|
import QuickAssistantSettings from './QuickAssistantSettings'
|
||||||
import ShortcutSettings from './ShortcutSettings'
|
import ShortcutSettings from './ShortcutSettings'
|
||||||
@ -60,6 +62,12 @@ const SettingsPage: FC = () => {
|
|||||||
{t('settings.websearch.title')}
|
{t('settings.websearch.title')}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
</MenuItemLink>
|
</MenuItemLink>
|
||||||
|
<MenuItemLink to="/settings/mcp">
|
||||||
|
<MenuItem className={isRoute('/settings/mcp')}>
|
||||||
|
<CodeOutlined />
|
||||||
|
{t('settings.mcp.title')}
|
||||||
|
</MenuItem>
|
||||||
|
</MenuItemLink>
|
||||||
<MenuItemLink to="/settings/general">
|
<MenuItemLink to="/settings/general">
|
||||||
<MenuItem className={isRoute('/settings/general')}>
|
<MenuItem className={isRoute('/settings/general')}>
|
||||||
<SettingOutlined />
|
<SettingOutlined />
|
||||||
@ -102,6 +110,7 @@ const SettingsPage: FC = () => {
|
|||||||
<Route path="provider" element={<ProvidersList />} />
|
<Route path="provider" element={<ProvidersList />} />
|
||||||
<Route path="model" element={<ModelSettings />} />
|
<Route path="model" element={<ModelSettings />} />
|
||||||
<Route path="web-search" element={<WebSearchSettings />} />
|
<Route path="web-search" element={<WebSearchSettings />} />
|
||||||
|
<Route path="mcp" element={<MCPSettings />} />
|
||||||
<Route path="general/*" element={<GeneralSettings />} />
|
<Route path="general/*" element={<GeneralSettings />} />
|
||||||
<Route path="display" element={<DisplaySettings />} />
|
<Route path="display" element={<DisplaySettings />} />
|
||||||
<Route path="data/*" element={<DataSettings />} />
|
<Route path="data/*" element={<DataSettings />} />
|
||||||
|
|||||||
@ -16,8 +16,14 @@ export default class AiProvider {
|
|||||||
return this.sdk.fakeCompletions(params)
|
return this.sdk.fakeCompletions(params)
|
||||||
}
|
}
|
||||||
|
|
||||||
public async completions({ messages, assistant, onChunk, onFilterMessages }: CompletionsParams): Promise<void> {
|
public async completions({
|
||||||
return this.sdk.completions({ messages, assistant, onChunk, onFilterMessages })
|
messages,
|
||||||
|
assistant,
|
||||||
|
onChunk,
|
||||||
|
onFilterMessages,
|
||||||
|
mcpTools
|
||||||
|
}: CompletionsParams): Promise<void> {
|
||||||
|
return this.sdk.completions({ messages, assistant, onChunk, onFilterMessages, mcpTools })
|
||||||
}
|
}
|
||||||
|
|
||||||
public async translate(message: Message, assistant: Assistant, onResponse?: (text: string) => void): Promise<string> {
|
public async translate(message: Message, assistant: Assistant, onResponse?: (text: string) => void): Promise<string> {
|
||||||
|
|||||||
@ -11,14 +11,27 @@ import i18n from '@renderer/i18n'
|
|||||||
import { getAssistantSettings, getDefaultModel, getTopNamingModel } from '@renderer/services/AssistantService'
|
import { getAssistantSettings, getDefaultModel, getTopNamingModel } from '@renderer/services/AssistantService'
|
||||||
import { EVENT_NAMES } from '@renderer/services/EventService'
|
import { EVENT_NAMES } from '@renderer/services/EventService'
|
||||||
import { filterContextMessages, filterUserRoleStartMessages } from '@renderer/services/MessagesService'
|
import { filterContextMessages, filterUserRoleStartMessages } from '@renderer/services/MessagesService'
|
||||||
import { Assistant, FileTypes, GenerateImageParams, Message, Model, Provider, Suggestion } from '@renderer/types'
|
import {
|
||||||
|
Assistant,
|
||||||
|
FileTypes,
|
||||||
|
GenerateImageParams,
|
||||||
|
MCPTool,
|
||||||
|
Message,
|
||||||
|
Model,
|
||||||
|
Provider,
|
||||||
|
Suggestion
|
||||||
|
} from '@renderer/types'
|
||||||
import { removeSpecialCharacters } from '@renderer/utils'
|
import { removeSpecialCharacters } from '@renderer/utils'
|
||||||
import { takeRight } from 'lodash'
|
import { takeRight } from 'lodash'
|
||||||
import OpenAI, { AzureOpenAI } from 'openai'
|
import OpenAI, { AzureOpenAI } from 'openai'
|
||||||
import {
|
import {
|
||||||
|
ChatCompletionAssistantMessageParam,
|
||||||
ChatCompletionContentPart,
|
ChatCompletionContentPart,
|
||||||
ChatCompletionCreateParamsNonStreaming,
|
ChatCompletionCreateParamsNonStreaming,
|
||||||
ChatCompletionMessageParam
|
ChatCompletionMessageParam,
|
||||||
|
ChatCompletionMessageToolCall,
|
||||||
|
ChatCompletionTool,
|
||||||
|
ChatCompletionToolMessageParam
|
||||||
} from 'openai/resources'
|
} from 'openai/resources'
|
||||||
|
|
||||||
import { CompletionsParams } from '.'
|
import { CompletionsParams } from '.'
|
||||||
@ -213,7 +226,37 @@ export default class OpenAIProvider extends BaseProvider {
|
|||||||
return model.id.startsWith('o1')
|
return model.id.startsWith('o1')
|
||||||
}
|
}
|
||||||
|
|
||||||
async completions({ messages, assistant, onChunk, onFilterMessages }: CompletionsParams): Promise<void> {
|
private mcpToolsToOpenAITools(mcpTools: MCPTool[]): Array<ChatCompletionTool> {
|
||||||
|
return mcpTools.map((tool) => ({
|
||||||
|
type: 'function',
|
||||||
|
function: {
|
||||||
|
name: `mcp.${tool.serverName}.${tool.name}`,
|
||||||
|
description: tool.description,
|
||||||
|
parameters: {
|
||||||
|
type: 'object',
|
||||||
|
properties: tool.inputSchema
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
private openAIToolsToMcpTool(tool: ChatCompletionMessageToolCall): MCPTool | undefined {
|
||||||
|
const parts = tool.function.name.split('.')
|
||||||
|
if (parts[0] !== 'mcp') {
|
||||||
|
console.log('Invalid tool name', tool.function.name)
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
const serverName = parts[1]
|
||||||
|
const name = parts[2]
|
||||||
|
|
||||||
|
return {
|
||||||
|
serverName: serverName,
|
||||||
|
name: name,
|
||||||
|
inputSchema: JSON.parse(tool.function.arguments)
|
||||||
|
} as MCPTool
|
||||||
|
}
|
||||||
|
|
||||||
|
async completions({ messages, assistant, onChunk, onFilterMessages, mcpTools }: CompletionsParams): Promise<void> {
|
||||||
const defaultModel = getDefaultModel()
|
const defaultModel = getDefaultModel()
|
||||||
const model = assistant.model || defaultModel
|
const model = assistant.model || defaultModel
|
||||||
const { contextCount, maxTokens, streamOutput } = getAssistantSettings(assistant)
|
const { contextCount, maxTokens, streamOutput } = getAssistantSettings(assistant)
|
||||||
@ -285,28 +328,13 @@ export default class OpenAIProvider extends BaseProvider {
|
|||||||
const { abortController, cleanup } = this.createAbortController(lastUserMessage?.id)
|
const { abortController, cleanup } = this.createAbortController(lastUserMessage?.id)
|
||||||
const { signal } = abortController
|
const { signal } = abortController
|
||||||
|
|
||||||
const stream = await this.sdk.chat.completions
|
const tools = mcpTools ? this.mcpToolsToOpenAITools(mcpTools) : undefined
|
||||||
// @ts-ignore key is not typed
|
|
||||||
.create(
|
|
||||||
{
|
|
||||||
model: model.id,
|
|
||||||
messages: [systemMessage, ...userMessages].filter(Boolean) as ChatCompletionMessageParam[],
|
|
||||||
temperature: this.getTemperature(assistant, model),
|
|
||||||
top_p: this.getTopP(assistant, model),
|
|
||||||
max_tokens: maxTokens,
|
|
||||||
keep_alive: this.keepAliveTime,
|
|
||||||
stream: isSupportStreamOutput(),
|
|
||||||
...getOpenAIWebSearchParams(assistant, model),
|
|
||||||
...this.getReasoningEffort(assistant, model),
|
|
||||||
...this.getProviderSpecificParameters(assistant, model),
|
|
||||||
...this.getCustomParameters(assistant)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
signal
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.finally(cleanup)
|
|
||||||
|
|
||||||
|
const reqMessages: ChatCompletionMessageParam[] = [systemMessage, ...userMessages].filter(
|
||||||
|
Boolean
|
||||||
|
) as ChatCompletionMessageParam[]
|
||||||
|
|
||||||
|
const processStream = async (stream: any) => {
|
||||||
if (!isSupportStreamOutput()) {
|
if (!isSupportStreamOutput()) {
|
||||||
const time_completion_millsec = new Date().getTime() - start_time_millsec
|
const time_completion_millsec = new Date().getTime() - start_time_millsec
|
||||||
return onChunk({
|
return onChunk({
|
||||||
@ -320,7 +348,8 @@ export default class OpenAIProvider extends BaseProvider {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// @ts-expect-error `stream` is not typed
|
const toolCalls: ChatCompletionMessageToolCall[] = []
|
||||||
|
|
||||||
for await (const chunk of stream) {
|
for await (const chunk of stream) {
|
||||||
if (window.keyv.get(EVENT_NAMES.CHAT_COMPLETION_PAUSED)) {
|
if (window.keyv.get(EVENT_NAMES.CHAT_COMPLETION_PAUSED)) {
|
||||||
break
|
break
|
||||||
@ -346,6 +375,77 @@ export default class OpenAIProvider extends BaseProvider {
|
|||||||
// Extract citations from the raw response if available
|
// Extract citations from the raw response if available
|
||||||
const citations = (chunk as OpenAI.Chat.Completions.ChatCompletionChunk & { citations?: string[] })?.citations
|
const citations = (chunk as OpenAI.Chat.Completions.ChatCompletionChunk & { citations?: string[] })?.citations
|
||||||
|
|
||||||
|
if (delta?.tool_calls) {
|
||||||
|
const chunkToolCalls: OpenAI.Chat.Completions.ChatCompletionChunk.Choice.Delta.ToolCall[] = delta.tool_calls
|
||||||
|
if (chunk.choices[0].finish_reason !== 'tool_calls') {
|
||||||
|
if (toolCalls.length === 0) {
|
||||||
|
for (const toolCall of chunkToolCalls) {
|
||||||
|
toolCalls.push(toolCall as ChatCompletionMessageToolCall)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (let i = 0; i < chunkToolCalls.length; i++) {
|
||||||
|
toolCalls[i].function.arguments += chunkToolCalls[i].function?.arguments || ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chunk.choices[0].finish_reason === 'tool_calls') {
|
||||||
|
console.log('start invoke tools', toolCalls)
|
||||||
|
reqMessages.push({
|
||||||
|
role: 'assistant',
|
||||||
|
tool_calls: toolCalls
|
||||||
|
} as ChatCompletionAssistantMessageParam)
|
||||||
|
|
||||||
|
for (const toolCall of toolCalls) {
|
||||||
|
const mcpTool = this.openAIToolsToMcpTool(toolCall)
|
||||||
|
console.log('mcpTool', JSON.stringify(mcpTool, null, 2))
|
||||||
|
if (!mcpTool) {
|
||||||
|
console.log('Invalid tool', toolCall)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
const toolCallResponse = await window.api.mcp.callTool({
|
||||||
|
client: mcpTool.serverName,
|
||||||
|
name: mcpTool.name,
|
||||||
|
args: mcpTool.inputSchema
|
||||||
|
})
|
||||||
|
console.log(`Tool ${mcpTool.serverName} - ${mcpTool.name} Call Response:`)
|
||||||
|
console.log(toolCallResponse)
|
||||||
|
|
||||||
|
reqMessages.push({
|
||||||
|
role: 'tool',
|
||||||
|
content: JSON.stringify(toolCallResponse, null, 2),
|
||||||
|
tool_call_id: toolCall.id
|
||||||
|
} as ChatCompletionToolMessageParam)
|
||||||
|
}
|
||||||
|
|
||||||
|
const newStream = await this.sdk.chat.completions
|
||||||
|
// @ts-ignore key is not typed
|
||||||
|
.create(
|
||||||
|
{
|
||||||
|
model: model.id,
|
||||||
|
messages: reqMessages,
|
||||||
|
temperature: this.getTemperature(assistant, model),
|
||||||
|
top_p: this.getTopP(assistant, model),
|
||||||
|
max_tokens: maxTokens,
|
||||||
|
keep_alive: this.keepAliveTime,
|
||||||
|
stream: isSupportStreamOutput(),
|
||||||
|
tools: tools,
|
||||||
|
...getOpenAIWebSearchParams(assistant, model),
|
||||||
|
...this.getReasoningEffort(assistant, model),
|
||||||
|
...this.getProviderSpecificParameters(assistant, model),
|
||||||
|
...this.getCustomParameters(assistant)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
signal
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.finally(cleanup)
|
||||||
|
await processStream(newStream)
|
||||||
|
}
|
||||||
|
|
||||||
onChunk({
|
onChunk({
|
||||||
text: delta?.content || '',
|
text: delta?.content || '',
|
||||||
// @ts-ignore key is not typed
|
// @ts-ignore key is not typed
|
||||||
@ -361,6 +461,31 @@ export default class OpenAIProvider extends BaseProvider {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const stream = await this.sdk.chat.completions
|
||||||
|
// @ts-ignore key is not typed
|
||||||
|
.create(
|
||||||
|
{
|
||||||
|
model: model.id,
|
||||||
|
messages: reqMessages,
|
||||||
|
temperature: this.getTemperature(assistant, model),
|
||||||
|
top_p: this.getTopP(assistant, model),
|
||||||
|
max_tokens: maxTokens,
|
||||||
|
keep_alive: this.keepAliveTime,
|
||||||
|
stream: isSupportStreamOutput(),
|
||||||
|
tools: tools,
|
||||||
|
...getOpenAIWebSearchParams(assistant, model),
|
||||||
|
...this.getReasoningEffort(assistant, model),
|
||||||
|
...this.getProviderSpecificParameters(assistant, model),
|
||||||
|
...this.getCustomParameters(assistant)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
signal
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.finally(cleanup)
|
||||||
|
|
||||||
|
await processStream(stream)
|
||||||
|
}
|
||||||
|
|
||||||
async translate(message: Message, assistant: Assistant, onResponse?: (text: string) => void) {
|
async translate(message: Message, assistant: Assistant, onResponse?: (text: string) => void) {
|
||||||
const defaultModel = getDefaultModel()
|
const defaultModel = getDefaultModel()
|
||||||
|
|||||||
1
src/renderer/src/providers/index.d.ts
vendored
1
src/renderer/src/providers/index.d.ts
vendored
@ -15,4 +15,5 @@ interface CompletionsParams {
|
|||||||
assistant: Assistant
|
assistant: Assistant
|
||||||
onChunk: ({ text, reasoning_content, usage, metrics, search, citations }: ChunkCallbackData) => void
|
onChunk: ({ text, reasoning_content, usage, metrics, search, citations }: ChunkCallbackData) => void
|
||||||
onFilterMessages: (messages: Message[]) => void
|
onFilterMessages: (messages: Message[]) => void
|
||||||
|
mcpTools?: MCPTool[]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -77,6 +77,10 @@ export async function fetchChatCompletion({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const allMCPTools = await window.api.mcp.listTools()
|
||||||
|
if (allMCPTools.length > 0) {
|
||||||
|
console.log('Available MCP tools:', allMCPTools)
|
||||||
|
}
|
||||||
await AI.completions({
|
await AI.completions({
|
||||||
messages: filterUsefulMessages(messages),
|
messages: filterUsefulMessages(messages),
|
||||||
assistant,
|
assistant,
|
||||||
@ -104,7 +108,8 @@ export async function fetchChatCompletion({
|
|||||||
}
|
}
|
||||||
|
|
||||||
onResponse({ ...message, status: 'pending' })
|
onResponse({ ...message, status: 'pending' })
|
||||||
}
|
},
|
||||||
|
mcpTools: allMCPTools
|
||||||
})
|
})
|
||||||
|
|
||||||
message.status = 'success'
|
message.status = 'success'
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import agents from './agents'
|
|||||||
import assistants from './assistants'
|
import assistants from './assistants'
|
||||||
import knowledge from './knowledge'
|
import knowledge from './knowledge'
|
||||||
import llm from './llm'
|
import llm from './llm'
|
||||||
|
import mcp from './mcp'
|
||||||
import migrate from './migrate'
|
import migrate from './migrate'
|
||||||
import minapps from './minapps'
|
import minapps from './minapps'
|
||||||
import paintings from './paintings'
|
import paintings from './paintings'
|
||||||
@ -25,7 +26,8 @@ const rootReducer = combineReducers({
|
|||||||
shortcuts,
|
shortcuts,
|
||||||
knowledge,
|
knowledge,
|
||||||
minapps,
|
minapps,
|
||||||
websearch
|
websearch,
|
||||||
|
mcp
|
||||||
})
|
})
|
||||||
|
|
||||||
const persistedReducer = persistReducer(
|
const persistedReducer = persistReducer(
|
||||||
|
|||||||
51
src/renderer/src/store/mcp.ts
Normal file
51
src/renderer/src/store/mcp.ts
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
|
||||||
|
import { MCPConfig, MCPServer } from '@renderer/types'
|
||||||
|
|
||||||
|
const initialState: MCPConfig = {
|
||||||
|
servers: []
|
||||||
|
}
|
||||||
|
|
||||||
|
const mcpSlice = createSlice({
|
||||||
|
name: 'mcp',
|
||||||
|
initialState,
|
||||||
|
reducers: {
|
||||||
|
setMCPServers: (state, action: PayloadAction<MCPServer[]>) => {
|
||||||
|
state.servers = action.payload
|
||||||
|
},
|
||||||
|
addMCPServer: (state, action: PayloadAction<MCPServer>) => {
|
||||||
|
state.servers.push(action.payload)
|
||||||
|
},
|
||||||
|
updateMCPServer: (state, action: PayloadAction<MCPServer>) => {
|
||||||
|
const index = state.servers.findIndex((server) => server.name === action.payload.name)
|
||||||
|
if (index !== -1) {
|
||||||
|
state.servers[index] = action.payload
|
||||||
|
}
|
||||||
|
},
|
||||||
|
deleteMCPServer: (state, action: PayloadAction<string>) => {
|
||||||
|
state.servers = state.servers.filter((server) => server.name !== action.payload)
|
||||||
|
},
|
||||||
|
setMCPServerActive: (state, action: PayloadAction<{ name: string; isActive: boolean }>) => {
|
||||||
|
const index = state.servers.findIndex((server) => server.name === action.payload.name)
|
||||||
|
if (index !== -1) {
|
||||||
|
state.servers[index].isActive = action.payload.isActive
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
selectors: {
|
||||||
|
getActiveServers: (state) => {
|
||||||
|
return state.servers.filter((server) => server.isActive)
|
||||||
|
},
|
||||||
|
getAllServers: (state) => state.servers
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
export const { setMCPServers, addMCPServer, updateMCPServer, deleteMCPServer, setMCPServerActive } = mcpSlice.actions
|
||||||
|
|
||||||
|
// Export the generated selectors from the slice
|
||||||
|
export const { getActiveServers, getAllServers } = mcpSlice.selectors
|
||||||
|
|
||||||
|
// Type-safe selector for accessing this slice from the root state
|
||||||
|
export const selectMCP = (state: { mcp: MCPConfig }) => state.mcp
|
||||||
|
|
||||||
|
// Export the reducer as default export
|
||||||
|
export default mcpSlice.reducer
|
||||||
@ -301,3 +301,42 @@ export type KnowledgeReference = {
|
|||||||
type: KnowledgeItemType
|
type: KnowledgeItemType
|
||||||
file?: FileType
|
file?: FileType
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type MCPArgType = 'string' | 'list' | 'number'
|
||||||
|
export type MCPEnvType = 'string' | 'number'
|
||||||
|
export type MCPArgParameter = { [key: string]: MCPArgType }
|
||||||
|
export type MCPEnvParameter = { [key: string]: MCPEnvType }
|
||||||
|
|
||||||
|
export interface MCPServerParameter {
|
||||||
|
name: string
|
||||||
|
type: MCPArgType | MCPEnvType
|
||||||
|
description: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MCPServer {
|
||||||
|
name: string
|
||||||
|
command: string
|
||||||
|
description?: string
|
||||||
|
args: string[]
|
||||||
|
env?: Record<string, string>
|
||||||
|
isActive: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MCPToolInputSchema {
|
||||||
|
type: string
|
||||||
|
title: string
|
||||||
|
description?: string
|
||||||
|
required?: string[]
|
||||||
|
properties: Record<string, object>
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MCPTool {
|
||||||
|
serverName: string
|
||||||
|
name: string
|
||||||
|
description?: string
|
||||||
|
inputSchema: MCPToolInputSchema
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MCPConfig {
|
||||||
|
servers: MCPServer[]
|
||||||
|
}
|
||||||
|
|||||||
561
yarn.lock
561
yarn.lock
@ -1740,6 +1740,23 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"@modelcontextprotocol/sdk@npm:^1.6.1":
|
||||||
|
version: 1.6.1
|
||||||
|
resolution: "@modelcontextprotocol/sdk@npm:1.6.1"
|
||||||
|
dependencies:
|
||||||
|
content-type: "npm:^1.0.5"
|
||||||
|
cors: "npm:^2.8.5"
|
||||||
|
eventsource: "npm:^3.0.2"
|
||||||
|
express: "npm:^5.0.1"
|
||||||
|
express-rate-limit: "npm:^7.5.0"
|
||||||
|
pkce-challenge: "npm:^4.1.0"
|
||||||
|
raw-body: "npm:^3.0.0"
|
||||||
|
zod: "npm:^3.23.8"
|
||||||
|
zod-to-json-schema: "npm:^3.24.1"
|
||||||
|
checksum: 10c0/767aca8096c06aabfa9432fab6a4e7bafb671833b1bddb2797b8089e102a9d6ac0486e7a353b28df9984eff5c5291bde76cd5ad079b576ae70666cdff10c5b2a
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"@neon-rs/load@npm:^0.0.4":
|
"@neon-rs/load@npm:^0.0.4":
|
||||||
version: 0.0.4
|
version: 0.0.4
|
||||||
resolution: "@neon-rs/load@npm:0.0.4"
|
resolution: "@neon-rs/load@npm:0.0.4"
|
||||||
@ -3055,6 +3072,7 @@ __metadata:
|
|||||||
"@llm-tools/embedjs-loader-web": "npm:^0.1.28"
|
"@llm-tools/embedjs-loader-web": "npm:^0.1.28"
|
||||||
"@llm-tools/embedjs-loader-xml": "npm:^0.1.28"
|
"@llm-tools/embedjs-loader-xml": "npm:^0.1.28"
|
||||||
"@llm-tools/embedjs-openai": "npm:^0.1.28"
|
"@llm-tools/embedjs-openai": "npm:^0.1.28"
|
||||||
|
"@modelcontextprotocol/sdk": "npm:^1.6.1"
|
||||||
"@notionhq/client": "npm:^2.2.15"
|
"@notionhq/client": "npm:^2.2.15"
|
||||||
"@reduxjs/toolkit": "npm:^2.2.5"
|
"@reduxjs/toolkit": "npm:^2.2.5"
|
||||||
"@tavily/core": "patch:@tavily/core@npm%3A0.3.1#~/.yarn/patches/@tavily-core-npm-0.3.1-fe69bf2bea.patch"
|
"@tavily/core": "patch:@tavily/core@npm%3A0.3.1#~/.yarn/patches/@tavily-core-npm-0.3.1-fe69bf2bea.patch"
|
||||||
@ -3165,6 +3183,16 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"accepts@npm:^2.0.0":
|
||||||
|
version: 2.0.0
|
||||||
|
resolution: "accepts@npm:2.0.0"
|
||||||
|
dependencies:
|
||||||
|
mime-types: "npm:^3.0.0"
|
||||||
|
negotiator: "npm:^1.0.0"
|
||||||
|
checksum: 10c0/98374742097e140891546076215f90c32644feacf652db48412329de4c2a529178a81aa500fbb13dd3e6cbf6e68d829037b123ac037fc9a08bcec4b87b358eef
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"acorn-jsx@npm:^5.3.2":
|
"acorn-jsx@npm:^5.3.2":
|
||||||
version: 5.3.2
|
version: 5.3.2
|
||||||
resolution: "acorn-jsx@npm:5.3.2"
|
resolution: "acorn-jsx@npm:5.3.2"
|
||||||
@ -3864,6 +3892,23 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"body-parser@npm:^2.0.1":
|
||||||
|
version: 2.1.0
|
||||||
|
resolution: "body-parser@npm:2.1.0"
|
||||||
|
dependencies:
|
||||||
|
bytes: "npm:^3.1.2"
|
||||||
|
content-type: "npm:^1.0.5"
|
||||||
|
debug: "npm:^4.4.0"
|
||||||
|
http-errors: "npm:^2.0.0"
|
||||||
|
iconv-lite: "npm:^0.5.2"
|
||||||
|
on-finished: "npm:^2.4.1"
|
||||||
|
qs: "npm:^6.14.0"
|
||||||
|
raw-body: "npm:^3.0.0"
|
||||||
|
type-is: "npm:^2.0.0"
|
||||||
|
checksum: 10c0/aec9bb327ba025808f04f86350ae9152ff9a6a8bc7429b69827cb7721b09f477ffd5e18cc954152a6a259b765322e33ebc4c50ab940f66d8e45ff1466e49ff2e
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"boolean@npm:^3.0.1":
|
"boolean@npm:^3.0.1":
|
||||||
version: 3.2.0
|
version: 3.2.0
|
||||||
resolution: "boolean@npm:3.2.0"
|
resolution: "boolean@npm:3.2.0"
|
||||||
@ -4045,6 +4090,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"bytes@npm:3.1.2, bytes@npm:^3.1.2":
|
||||||
|
version: 3.1.2
|
||||||
|
resolution: "bytes@npm:3.1.2"
|
||||||
|
checksum: 10c0/76d1c43cbd602794ad8ad2ae94095cddeb1de78c5dddaa7005c51af10b0176c69971a6d88e805a90c2b6550d76636e43c40d8427a808b8645ede885de4a0358e
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"cac@npm:^6.7.14":
|
"cac@npm:^6.7.14":
|
||||||
version: 6.7.14
|
version: 6.7.14
|
||||||
resolution: "cac@npm:6.7.14"
|
resolution: "cac@npm:6.7.14"
|
||||||
@ -4210,9 +4262,9 @@ __metadata:
|
|||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"caniuse-lite@npm:^1.0.30001688":
|
"caniuse-lite@npm:^1.0.30001688":
|
||||||
version: 1.0.30001701
|
version: 1.0.30001702
|
||||||
resolution: "caniuse-lite@npm:1.0.30001701"
|
resolution: "caniuse-lite@npm:1.0.30001702"
|
||||||
checksum: 10c0/a814bd4dd8b49645ca51bc6ee42120660a36394bb54eb6084801d3f2bbb9471e5e1a9a8a25f44f83086a032d46e66b33031e2aa345f699b90a7e84a9836b819c
|
checksum: 10c0/52d46f41a96d179fd4e387bb6b26898148c31b626ff9aba105d207d2b0f869c7cb32ac67a6e8e0aeba3f03f33145ccfbee237250dfb58dba8b6526b4dd395ac6
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@ -4603,6 +4655,22 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"content-disposition@npm:^1.0.0":
|
||||||
|
version: 1.0.0
|
||||||
|
resolution: "content-disposition@npm:1.0.0"
|
||||||
|
dependencies:
|
||||||
|
safe-buffer: "npm:5.2.1"
|
||||||
|
checksum: 10c0/c7b1ba0cea2829da0352ebc1b7f14787c73884bc707c8bc2271d9e3bf447b372270d09f5d3980dc5037c749ceef56b9a13fccd0b0001c87c3f12579967e4dd27
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"content-type@npm:^1.0.5, content-type@npm:~1.0.4":
|
||||||
|
version: 1.0.5
|
||||||
|
resolution: "content-type@npm:1.0.5"
|
||||||
|
checksum: 10c0/b76ebed15c000aee4678c3707e0860cb6abd4e680a598c0a26e17f0bfae723ec9cc2802f0ff1bc6e4d80603719010431d2231018373d4dde10f9ccff9dadf5af
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"convert-source-map@npm:^2.0.0":
|
"convert-source-map@npm:^2.0.0":
|
||||||
version: 2.0.0
|
version: 2.0.0
|
||||||
resolution: "convert-source-map@npm:2.0.0"
|
resolution: "convert-source-map@npm:2.0.0"
|
||||||
@ -4610,6 +4678,20 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"cookie-signature@npm:^1.2.1":
|
||||||
|
version: 1.2.2
|
||||||
|
resolution: "cookie-signature@npm:1.2.2"
|
||||||
|
checksum: 10c0/54e05df1a293b3ce81589b27dddc445f462f6fa6812147c033350cd3561a42bc14481674e05ed14c7bd0ce1e8bb3dc0e40851bad75415733711294ddce0b7bc6
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"cookie@npm:0.7.1":
|
||||||
|
version: 0.7.1
|
||||||
|
resolution: "cookie@npm:0.7.1"
|
||||||
|
checksum: 10c0/5de60c67a410e7c8dc8a46a4b72eb0fe925871d057c9a5d2c0e8145c4270a4f81076de83410c4d397179744b478e33cd80ccbcc457abf40a9409ad27dcd21dde
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"copy-to-clipboard@npm:^3.3.3":
|
"copy-to-clipboard@npm:^3.3.3":
|
||||||
version: 3.3.3
|
version: 3.3.3
|
||||||
resolution: "copy-to-clipboard@npm:3.3.3"
|
resolution: "copy-to-clipboard@npm:3.3.3"
|
||||||
@ -4633,6 +4715,16 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"cors@npm:^2.8.5":
|
||||||
|
version: 2.8.5
|
||||||
|
resolution: "cors@npm:2.8.5"
|
||||||
|
dependencies:
|
||||||
|
object-assign: "npm:^4"
|
||||||
|
vary: "npm:^1"
|
||||||
|
checksum: 10c0/373702b7999409922da80de4a61938aabba6929aea5b6fd9096fefb9e8342f626c0ebd7507b0e8b0b311380744cc985f27edebc0a26e0ddb784b54e1085de761
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"crc@npm:^3.8.0":
|
"crc@npm:^3.8.0":
|
||||||
version: 3.8.0
|
version: 3.8.0
|
||||||
resolution: "crc@npm:3.8.0"
|
resolution: "crc@npm:3.8.0"
|
||||||
@ -4775,7 +4867,16 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"debug@npm:4, debug@npm:^4.0.0, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.3, debug@npm:^4.3.4, debug@npm:^4.4.0":
|
"debug@npm:2.6.9, debug@npm:^2.6.9":
|
||||||
|
version: 2.6.9
|
||||||
|
resolution: "debug@npm:2.6.9"
|
||||||
|
dependencies:
|
||||||
|
ms: "npm:2.0.0"
|
||||||
|
checksum: 10c0/121908fb839f7801180b69a7e218a40b5a0b718813b886b7d6bdb82001b931c938e2941d1e4450f33a1b1df1da653f5f7a0440c197f29fbf8a6e9d45ff6ef589
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"debug@npm:4, debug@npm:^4.0.0, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.3, debug@npm:^4.3.4, debug@npm:^4.3.5, debug@npm:^4.4.0":
|
||||||
version: 4.4.0
|
version: 4.4.0
|
||||||
resolution: "debug@npm:4.4.0"
|
resolution: "debug@npm:4.4.0"
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -4787,12 +4888,15 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"debug@npm:^2.6.9":
|
"debug@npm:4.3.6":
|
||||||
version: 2.6.9
|
version: 4.3.6
|
||||||
resolution: "debug@npm:2.6.9"
|
resolution: "debug@npm:4.3.6"
|
||||||
dependencies:
|
dependencies:
|
||||||
ms: "npm:2.0.0"
|
ms: "npm:2.1.2"
|
||||||
checksum: 10c0/121908fb839f7801180b69a7e218a40b5a0b718813b886b7d6bdb82001b931c938e2941d1e4450f33a1b1df1da653f5f7a0440c197f29fbf8a6e9d45ff6ef589
|
peerDependenciesMeta:
|
||||||
|
supports-color:
|
||||||
|
optional: true
|
||||||
|
checksum: 10c0/3293416bff072389c101697d4611c402a6bacd1900ac20c0492f61a9cdd6b3b29750fc7f5e299f8058469ef60ff8fb79b86395a30374fbd2490113c1c7112285
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@ -4980,6 +5084,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"depd@npm:2.0.0":
|
||||||
|
version: 2.0.0
|
||||||
|
resolution: "depd@npm:2.0.0"
|
||||||
|
checksum: 10c0/58bd06ec20e19529b06f7ad07ddab60e504d9e0faca4bd23079fac2d279c3594334d736508dc350e06e510aba5e22e4594483b3a6562ce7c17dd797f4cc4ad2c
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"dequal@npm:^2.0.0":
|
"dequal@npm:^2.0.0":
|
||||||
version: 2.0.3
|
version: 2.0.3
|
||||||
resolution: "dequal@npm:2.0.3"
|
resolution: "dequal@npm:2.0.3"
|
||||||
@ -4987,6 +5098,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"destroy@npm:^1.2.0":
|
||||||
|
version: 1.2.0
|
||||||
|
resolution: "destroy@npm:1.2.0"
|
||||||
|
checksum: 10c0/bd7633942f57418f5a3b80d5cb53898127bcf53e24cdf5d5f4396be471417671f0fee48a4ebe9a1e9defbde2a31280011af58a57e090ff822f589b443ed4e643
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"detect-libc@npm:2.0.2":
|
"detect-libc@npm:2.0.2":
|
||||||
version: 2.0.2
|
version: 2.0.2
|
||||||
resolution: "detect-libc@npm:2.0.2"
|
resolution: "detect-libc@npm:2.0.2"
|
||||||
@ -5271,6 +5389,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"ee-first@npm:1.1.1":
|
||||||
|
version: 1.1.1
|
||||||
|
resolution: "ee-first@npm:1.1.1"
|
||||||
|
checksum: 10c0/b5bb125ee93161bc16bfe6e56c6b04de5ad2aa44234d8f644813cc95d861a6910903132b05093706de2b706599367c4130eb6d170f6b46895686b95f87d017b7
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"ejs@npm:^3.1.8":
|
"ejs@npm:^3.1.8":
|
||||||
version: 3.1.10
|
version: 3.1.10
|
||||||
resolution: "ejs@npm:3.1.10"
|
resolution: "ejs@npm:3.1.10"
|
||||||
@ -5362,9 +5487,9 @@ __metadata:
|
|||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"electron-to-chromium@npm:^1.5.73":
|
"electron-to-chromium@npm:^1.5.73":
|
||||||
version: 1.5.109
|
version: 1.5.112
|
||||||
resolution: "electron-to-chromium@npm:1.5.109"
|
resolution: "electron-to-chromium@npm:1.5.112"
|
||||||
checksum: 10c0/19d86b95b1288b2e73d9d6084f64b14d4ef2c51d8551d85697ea68da690542d26e6d07878ff053f137e561e3e6c8c2b062d0353bc159930569831f7960bb6ed7
|
checksum: 10c0/fc597268d6d3d7458b55141c436802a6c51078855f021823cdb380b80ad1a69e1c2899fdfc9cffa501d47feb3791ea6a75893fe802a608c7845e979a48f5ac25
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@ -5471,6 +5596,20 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"encodeurl@npm:^2.0.0, encodeurl@npm:~2.0.0":
|
||||||
|
version: 2.0.0
|
||||||
|
resolution: "encodeurl@npm:2.0.0"
|
||||||
|
checksum: 10c0/5d317306acb13e6590e28e27924c754163946a2480de11865c991a3a7eed4315cd3fba378b543ca145829569eefe9b899f3d84bb09870f675ae60bc924b01ceb
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"encodeurl@npm:~1.0.2":
|
||||||
|
version: 1.0.2
|
||||||
|
resolution: "encodeurl@npm:1.0.2"
|
||||||
|
checksum: 10c0/f6c2387379a9e7c1156c1c3d4f9cb7bb11cf16dd4c1682e1f6746512564b053df5781029b6061296832b59fb22f459dbe250386d217c2f6e203601abb2ee0bec
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"encoding@npm:^0.1.12, encoding@npm:^0.1.13":
|
"encoding@npm:^0.1.12, encoding@npm:^0.1.13":
|
||||||
version: 0.1.13
|
version: 0.1.13
|
||||||
resolution: "encoding@npm:0.1.13"
|
resolution: "encoding@npm:0.1.13"
|
||||||
@ -5772,6 +5911,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"escape-html@npm:^1.0.3, escape-html@npm:~1.0.3":
|
||||||
|
version: 1.0.3
|
||||||
|
resolution: "escape-html@npm:1.0.3"
|
||||||
|
checksum: 10c0/524c739d776b36c3d29fa08a22e03e8824e3b2fd57500e5e44ecf3cc4707c34c60f9ca0781c0e33d191f2991161504c295e98f68c78fe7baa6e57081ec6ac0a3
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"escape-string-regexp@npm:^1.0.5":
|
"escape-string-regexp@npm:^1.0.5":
|
||||||
version: 1.0.5
|
version: 1.0.5
|
||||||
resolution: "escape-string-regexp@npm:1.0.5"
|
resolution: "escape-string-regexp@npm:1.0.5"
|
||||||
@ -6015,6 +6161,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"etag@npm:^1.8.1, etag@npm:~1.8.1":
|
||||||
|
version: 1.8.1
|
||||||
|
resolution: "etag@npm:1.8.1"
|
||||||
|
checksum: 10c0/12be11ef62fb9817314d790089a0a49fae4e1b50594135dcb8076312b7d7e470884b5100d249b28c18581b7fd52f8b485689ffae22a11ed9ec17377a33a08f84
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"event-target-shim@npm:^5.0.0":
|
"event-target-shim@npm:^5.0.0":
|
||||||
version: 5.0.1
|
version: 5.0.1
|
||||||
resolution: "event-target-shim@npm:5.0.1"
|
resolution: "event-target-shim@npm:5.0.1"
|
||||||
@ -6036,6 +6189,22 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"eventsource-parser@npm:^3.0.0":
|
||||||
|
version: 3.0.0
|
||||||
|
resolution: "eventsource-parser@npm:3.0.0"
|
||||||
|
checksum: 10c0/74ded91ff93330bd95243bd5a8fc61c805ea1843dd7ffac8e8ac36287fff419a7eec21b2fadf50d4e554ce0506de72f47928513e3c5b886fa4613fd49ef0024f
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"eventsource@npm:^3.0.2":
|
||||||
|
version: 3.0.5
|
||||||
|
resolution: "eventsource@npm:3.0.5"
|
||||||
|
dependencies:
|
||||||
|
eventsource-parser: "npm:^3.0.0"
|
||||||
|
checksum: 10c0/0283045a70b7ab7501fc290e60ee5ebd6e24648e0f0a6d6a1c1bbb7a421971e8140b85d6239d08c360e0a0b196205ca86b4ff7f9efe3c06877ba628136856489
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"exif-parser@npm:^0.1.12":
|
"exif-parser@npm:^0.1.12":
|
||||||
version: 0.1.12
|
version: 0.1.12
|
||||||
resolution: "exif-parser@npm:0.1.12"
|
resolution: "exif-parser@npm:0.1.12"
|
||||||
@ -6064,6 +6233,55 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"express-rate-limit@npm:^7.5.0":
|
||||||
|
version: 7.5.0
|
||||||
|
resolution: "express-rate-limit@npm:7.5.0"
|
||||||
|
peerDependencies:
|
||||||
|
express: ^4.11 || 5 || ^5.0.0-beta.1
|
||||||
|
checksum: 10c0/3e96afa05b4f577395688ede37e0cb19901f20c350b32575fb076f3d25176209fb88d3648151755c232aaf304147c58531f070757978f376e2f08326449299fd
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"express@npm:^5.0.1":
|
||||||
|
version: 5.0.1
|
||||||
|
resolution: "express@npm:5.0.1"
|
||||||
|
dependencies:
|
||||||
|
accepts: "npm:^2.0.0"
|
||||||
|
body-parser: "npm:^2.0.1"
|
||||||
|
content-disposition: "npm:^1.0.0"
|
||||||
|
content-type: "npm:~1.0.4"
|
||||||
|
cookie: "npm:0.7.1"
|
||||||
|
cookie-signature: "npm:^1.2.1"
|
||||||
|
debug: "npm:4.3.6"
|
||||||
|
depd: "npm:2.0.0"
|
||||||
|
encodeurl: "npm:~2.0.0"
|
||||||
|
escape-html: "npm:~1.0.3"
|
||||||
|
etag: "npm:~1.8.1"
|
||||||
|
finalhandler: "npm:^2.0.0"
|
||||||
|
fresh: "npm:2.0.0"
|
||||||
|
http-errors: "npm:2.0.0"
|
||||||
|
merge-descriptors: "npm:^2.0.0"
|
||||||
|
methods: "npm:~1.1.2"
|
||||||
|
mime-types: "npm:^3.0.0"
|
||||||
|
on-finished: "npm:2.4.1"
|
||||||
|
once: "npm:1.4.0"
|
||||||
|
parseurl: "npm:~1.3.3"
|
||||||
|
proxy-addr: "npm:~2.0.7"
|
||||||
|
qs: "npm:6.13.0"
|
||||||
|
range-parser: "npm:~1.2.1"
|
||||||
|
router: "npm:^2.0.0"
|
||||||
|
safe-buffer: "npm:5.2.1"
|
||||||
|
send: "npm:^1.1.0"
|
||||||
|
serve-static: "npm:^2.1.0"
|
||||||
|
setprototypeof: "npm:1.2.0"
|
||||||
|
statuses: "npm:2.0.1"
|
||||||
|
type-is: "npm:^2.0.0"
|
||||||
|
utils-merge: "npm:1.0.1"
|
||||||
|
vary: "npm:~1.1.2"
|
||||||
|
checksum: 10c0/6e533f28adb64178c90c3e357cbcdb5d1f233ca1290d023b3c4936c4ac67c6699aaba726edf6c148979220ec7ce6ed2e5e374cff904e3a2bf9ce91620cf8afff
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"extend@npm:^3.0.0, extend@npm:~3.0.2":
|
"extend@npm:^3.0.0, extend@npm:~3.0.2":
|
||||||
version: 3.0.2
|
version: 3.0.2
|
||||||
resolution: "extend@npm:3.0.2"
|
resolution: "extend@npm:3.0.2"
|
||||||
@ -6305,6 +6523,21 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"finalhandler@npm:^2.0.0":
|
||||||
|
version: 2.0.0
|
||||||
|
resolution: "finalhandler@npm:2.0.0"
|
||||||
|
dependencies:
|
||||||
|
debug: "npm:2.6.9"
|
||||||
|
encodeurl: "npm:~1.0.2"
|
||||||
|
escape-html: "npm:~1.0.3"
|
||||||
|
on-finished: "npm:2.4.1"
|
||||||
|
parseurl: "npm:~1.3.3"
|
||||||
|
statuses: "npm:2.0.1"
|
||||||
|
unpipe: "npm:~1.0.0"
|
||||||
|
checksum: 10c0/ca6f69d69797eebc900d7627bde4bb7d38417112911eb11ce4e40011195b6ad1a09413ad082da9bb64da789a4ecfffdd0e6a5ea1ccb4147062224c3050f134ea
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"find-replace@npm:^3.0.0":
|
"find-replace@npm:^3.0.0":
|
||||||
version: 3.0.0
|
version: 3.0.0
|
||||||
resolution: "find-replace@npm:3.0.0"
|
resolution: "find-replace@npm:3.0.0"
|
||||||
@ -6460,6 +6693,27 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"forwarded@npm:0.2.0":
|
||||||
|
version: 0.2.0
|
||||||
|
resolution: "forwarded@npm:0.2.0"
|
||||||
|
checksum: 10c0/9b67c3fac86acdbc9ae47ba1ddd5f2f81526fa4c8226863ede5600a3f7c7416ef451f6f1e240a3cc32d0fd79fcfe6beb08fd0da454f360032bde70bf80afbb33
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"fresh@npm:2.0.0":
|
||||||
|
version: 2.0.0
|
||||||
|
resolution: "fresh@npm:2.0.0"
|
||||||
|
checksum: 10c0/0557548194cb9a809a435bf92bcfbc20c89e8b5eb38861b73ced36750437251e39a111fc3a18b98531be9dd91fe1411e4969f229dc579ec0251ce6c5d4900bbc
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"fresh@npm:^0.5.2":
|
||||||
|
version: 0.5.2
|
||||||
|
resolution: "fresh@npm:0.5.2"
|
||||||
|
checksum: 10c0/c6d27f3ed86cc5b601404822f31c900dd165ba63fff8152a3ef714e2012e7535027063bc67ded4cb5b3a49fa596495d46cacd9f47d6328459cf570f08b7d9e5a
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"fs-constants@npm:^1.0.0":
|
"fs-constants@npm:^1.0.0":
|
||||||
version: 1.0.0
|
version: 1.0.0
|
||||||
resolution: "fs-constants@npm:1.0.0"
|
resolution: "fs-constants@npm:1.0.0"
|
||||||
@ -7320,6 +7574,19 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"http-errors@npm:2.0.0, http-errors@npm:^2.0.0":
|
||||||
|
version: 2.0.0
|
||||||
|
resolution: "http-errors@npm:2.0.0"
|
||||||
|
dependencies:
|
||||||
|
depd: "npm:2.0.0"
|
||||||
|
inherits: "npm:2.0.4"
|
||||||
|
setprototypeof: "npm:1.2.0"
|
||||||
|
statuses: "npm:2.0.1"
|
||||||
|
toidentifier: "npm:1.0.1"
|
||||||
|
checksum: 10c0/fc6f2715fe188d091274b5ffc8b3657bd85c63e969daa68ccb77afb05b071a4b62841acb7a21e417b5539014dff2ebf9550f0b14a9ff126f2734a7c1387f8e19
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"http-proxy-agent@npm:^4.0.1":
|
"http-proxy-agent@npm:^4.0.1":
|
||||||
version: 4.0.1
|
version: 4.0.1
|
||||||
resolution: "http-proxy-agent@npm:4.0.1"
|
resolution: "http-proxy-agent@npm:4.0.1"
|
||||||
@ -7447,6 +7714,15 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"iconv-lite@npm:0.6.3, iconv-lite@npm:^0.6.2":
|
||||||
|
version: 0.6.3
|
||||||
|
resolution: "iconv-lite@npm:0.6.3"
|
||||||
|
dependencies:
|
||||||
|
safer-buffer: "npm:>= 2.1.2 < 3.0.0"
|
||||||
|
checksum: 10c0/98102bc66b33fcf5ac044099d1257ba0b7ad5e3ccd3221f34dd508ab4070edff183276221684e1e0555b145fce0850c9f7d2b60a9fcac50fbb4ea0d6e845a3b1
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"iconv-lite@npm:^0.4.4":
|
"iconv-lite@npm:^0.4.4":
|
||||||
version: 0.4.24
|
version: 0.4.24
|
||||||
resolution: "iconv-lite@npm:0.4.24"
|
resolution: "iconv-lite@npm:0.4.24"
|
||||||
@ -7456,12 +7732,12 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"iconv-lite@npm:^0.6.2":
|
"iconv-lite@npm:^0.5.2":
|
||||||
version: 0.6.3
|
version: 0.5.2
|
||||||
resolution: "iconv-lite@npm:0.6.3"
|
resolution: "iconv-lite@npm:0.5.2"
|
||||||
dependencies:
|
dependencies:
|
||||||
safer-buffer: "npm:>= 2.1.2 < 3.0.0"
|
safer-buffer: "npm:>= 2.1.2 < 3"
|
||||||
checksum: 10c0/98102bc66b33fcf5ac044099d1257ba0b7ad5e3ccd3221f34dd508ab4070edff183276221684e1e0555b145fce0850c9f7d2b60a9fcac50fbb4ea0d6e845a3b1
|
checksum: 10c0/6c51c9996fe360b03f501c0f76f122f007c6a9be924cfdf0b007044cfbcdeeb9c9decb5435465934dbd3804f37e67fdc2fb3ed8c9948464299165776541dff25
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@ -7559,7 +7835,7 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"inherits@npm:2, inherits@npm:^2.0.3, inherits@npm:^2.0.4, inherits@npm:~2.0.3":
|
"inherits@npm:2, inherits@npm:2.0.4, inherits@npm:^2.0.3, inherits@npm:^2.0.4, inherits@npm:~2.0.3":
|
||||||
version: 2.0.4
|
version: 2.0.4
|
||||||
resolution: "inherits@npm:2.0.4"
|
resolution: "inherits@npm:2.0.4"
|
||||||
checksum: 10c0/4e531f648b29039fb7426fb94075e6545faa1eb9fe83c29f0b6d9e7263aceb4289d2d4557db0d428188eeb449cc7c5e77b0a0b2c4e248ff2a65933a0dee49ef2
|
checksum: 10c0/4e531f648b29039fb7426fb94075e6545faa1eb9fe83c29f0b6d9e7263aceb4289d2d4557db0d428188eeb449cc7c5e77b0a0b2c4e248ff2a65933a0dee49ef2
|
||||||
@ -7608,6 +7884,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"ipaddr.js@npm:1.9.1":
|
||||||
|
version: 1.9.1
|
||||||
|
resolution: "ipaddr.js@npm:1.9.1"
|
||||||
|
checksum: 10c0/0486e775047971d3fdb5fb4f063829bac45af299ae0b82dcf3afa2145338e08290563a2a70f34b732d795ecc8311902e541a8530eeb30d75860a78ff4e94ce2a
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"is-alphabetical@npm:^2.0.0":
|
"is-alphabetical@npm:^2.0.0":
|
||||||
version: 2.0.1
|
version: 2.0.1
|
||||||
resolution: "is-alphabetical@npm:2.0.1"
|
resolution: "is-alphabetical@npm:2.0.1"
|
||||||
@ -7886,6 +8169,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"is-promise@npm:^4.0.0":
|
||||||
|
version: 4.0.0
|
||||||
|
resolution: "is-promise@npm:4.0.0"
|
||||||
|
checksum: 10c0/ebd5c672d73db781ab33ccb155fb9969d6028e37414d609b115cc534654c91ccd061821d5b987eefaa97cf4c62f0b909bb2f04db88306de26e91bfe8ddc01503
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"is-regex@npm:^1.2.1":
|
"is-regex@npm:^1.2.1":
|
||||||
version: 1.2.1
|
version: 1.2.1
|
||||||
resolution: "is-regex@npm:1.2.1"
|
resolution: "is-regex@npm:1.2.1"
|
||||||
@ -8435,8 +8725,8 @@ __metadata:
|
|||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"langsmith@npm:>=0.2.8 <0.4.0":
|
"langsmith@npm:>=0.2.8 <0.4.0":
|
||||||
version: 0.3.11
|
version: 0.3.12
|
||||||
resolution: "langsmith@npm:0.3.11"
|
resolution: "langsmith@npm:0.3.12"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/uuid": "npm:^10.0.0"
|
"@types/uuid": "npm:^10.0.0"
|
||||||
chalk: "npm:^4.1.2"
|
chalk: "npm:^4.1.2"
|
||||||
@ -8450,7 +8740,7 @@ __metadata:
|
|||||||
peerDependenciesMeta:
|
peerDependenciesMeta:
|
||||||
openai:
|
openai:
|
||||||
optional: true
|
optional: true
|
||||||
checksum: 10c0/e4049c9661f92f7f3100eaa9a32b85608b209ff0e41c854c76ec98cf1aa87dcc07aa90fbaf2bd875f55861951faa402d8b5838e50bbe88c8878da2d94e6bb9a3
|
checksum: 10c0/f83b43cca2369842a3fd49f74ad6f81baa41d6ee20cc0c2ed169e0cb1f76e637f72c7e1394dff693a4fcdd417477a72639c61575d2ced8665221163c2d3e1759
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@ -9078,6 +9368,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"media-typer@npm:^1.1.0":
|
||||||
|
version: 1.1.0
|
||||||
|
resolution: "media-typer@npm:1.1.0"
|
||||||
|
checksum: 10c0/7b4baa40b25964bb90e2121ee489ec38642127e48d0cc2b6baa442688d3fde6262bfdca86d6bbf6ba708784afcac168c06840c71facac70e390f5f759ac121b9
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"memoize-one@npm:^6.0.0":
|
"memoize-one@npm:^6.0.0":
|
||||||
version: 6.0.0
|
version: 6.0.0
|
||||||
resolution: "memoize-one@npm:6.0.0"
|
resolution: "memoize-one@npm:6.0.0"
|
||||||
@ -9085,6 +9382,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"merge-descriptors@npm:^2.0.0":
|
||||||
|
version: 2.0.0
|
||||||
|
resolution: "merge-descriptors@npm:2.0.0"
|
||||||
|
checksum: 10c0/95389b7ced3f9b36fbdcf32eb946dc3dd1774c2fdf164609e55b18d03aa499b12bd3aae3a76c1c7185b96279e9803525550d3eb292b5224866060a288f335cb3
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"merge2@npm:^1.3.0, merge2@npm:^1.4.1":
|
"merge2@npm:^1.3.0, merge2@npm:^1.4.1":
|
||||||
version: 1.4.1
|
version: 1.4.1
|
||||||
resolution: "merge2@npm:1.4.1"
|
resolution: "merge2@npm:1.4.1"
|
||||||
@ -9092,6 +9396,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"methods@npm:~1.1.2":
|
||||||
|
version: 1.1.2
|
||||||
|
resolution: "methods@npm:1.1.2"
|
||||||
|
checksum: 10c0/bdf7cc72ff0a33e3eede03708c08983c4d7a173f91348b4b1e4f47d4cdbf734433ad971e7d1e8c77247d9e5cd8adb81ea4c67b0a2db526b758b2233d7814b8b2
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"mhchemparser@npm:^4.1.0":
|
"mhchemparser@npm:^4.1.0":
|
||||||
version: 4.2.1
|
version: 4.2.1
|
||||||
resolution: "mhchemparser@npm:4.2.1"
|
resolution: "mhchemparser@npm:4.2.1"
|
||||||
@ -9512,6 +9823,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"mime-db@npm:^1.53.0":
|
||||||
|
version: 1.53.0
|
||||||
|
resolution: "mime-db@npm:1.53.0"
|
||||||
|
checksum: 10c0/1dcc37ba8ed5d1c179f5c6f0837e8db19371d5f2ea3690c3c2f3fa8c3858f976851d3460b172b4dee78ebd606762cbb407aa398545fbacd539e519f858cd7bf4
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"mime-types@npm:^2.1.12, mime-types@npm:^2.1.35, mime-types@npm:~2.1.19":
|
"mime-types@npm:^2.1.12, mime-types@npm:^2.1.35, mime-types@npm:~2.1.19":
|
||||||
version: 2.1.35
|
version: 2.1.35
|
||||||
resolution: "mime-types@npm:2.1.35"
|
resolution: "mime-types@npm:2.1.35"
|
||||||
@ -9521,6 +9839,15 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"mime-types@npm:^3.0.0":
|
||||||
|
version: 3.0.0
|
||||||
|
resolution: "mime-types@npm:3.0.0"
|
||||||
|
dependencies:
|
||||||
|
mime-db: "npm:^1.53.0"
|
||||||
|
checksum: 10c0/8624501c75568f14e53fd9e12327fa18e70d6a85047c5beb9146990178f3adb31f893cb54d25ab58145cabf3e06c61953f2c5427ccd05b6b38fe09db8c5f5e7f
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"mime@npm:^1.3.4":
|
"mime@npm:^1.3.4":
|
||||||
version: 1.6.0
|
version: 1.6.0
|
||||||
resolution: "mime@npm:1.6.0"
|
resolution: "mime@npm:1.6.0"
|
||||||
@ -9836,6 +10163,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"ms@npm:2.1.2":
|
||||||
|
version: 2.1.2
|
||||||
|
resolution: "ms@npm:2.1.2"
|
||||||
|
checksum: 10c0/a437714e2f90dbf881b5191d35a6db792efbca5badf112f87b9e1c712aace4b4b9b742dd6537f3edf90fd6f684de897cec230abde57e87883766712ddda297cc
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"ms@npm:^2.0.0, ms@npm:^2.1.1, ms@npm:^2.1.3":
|
"ms@npm:^2.0.0, ms@npm:^2.1.1, ms@npm:^2.1.3":
|
||||||
version: 2.1.3
|
version: 2.1.3
|
||||||
resolution: "ms@npm:2.1.3"
|
resolution: "ms@npm:2.1.3"
|
||||||
@ -10185,7 +10519,7 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"object-assign@npm:^4.0.1, object-assign@npm:^4.1.0, object-assign@npm:^4.1.1":
|
"object-assign@npm:^4, object-assign@npm:^4.0.1, object-assign@npm:^4.1.0, object-assign@npm:^4.1.1":
|
||||||
version: 4.1.1
|
version: 4.1.1
|
||||||
resolution: "object-assign@npm:4.1.1"
|
resolution: "object-assign@npm:4.1.1"
|
||||||
checksum: 10c0/1f4df9945120325d041ccf7b86f31e8bcc14e73d29171e37a7903050e96b81323784ec59f93f102ec635bcf6fa8034ba3ea0a8c7e69fa202b87ae3b6cec5a414
|
checksum: 10c0/1f4df9945120325d041ccf7b86f31e8bcc14e73d29171e37a7903050e96b81323784ec59f93f102ec635bcf6fa8034ba3ea0a8c7e69fa202b87ae3b6cec5a414
|
||||||
@ -10294,7 +10628,16 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"once@npm:^1.3.0, once@npm:^1.3.1, once@npm:^1.4.0":
|
"on-finished@npm:2.4.1, on-finished@npm:^2.4.1":
|
||||||
|
version: 2.4.1
|
||||||
|
resolution: "on-finished@npm:2.4.1"
|
||||||
|
dependencies:
|
||||||
|
ee-first: "npm:1.1.1"
|
||||||
|
checksum: 10c0/46fb11b9063782f2d9968863d9cbba33d77aa13c17f895f56129c274318b86500b22af3a160fe9995aa41317efcd22941b6eba747f718ced08d9a73afdb087b4
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"once@npm:1.4.0, once@npm:^1.3.0, once@npm:^1.3.1, once@npm:^1.4.0":
|
||||||
version: 1.4.0
|
version: 1.4.0
|
||||||
resolution: "once@npm:1.4.0"
|
resolution: "once@npm:1.4.0"
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -10656,6 +10999,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"parseurl@npm:^1.3.3, parseurl@npm:~1.3.3":
|
||||||
|
version: 1.3.3
|
||||||
|
resolution: "parseurl@npm:1.3.3"
|
||||||
|
checksum: 10c0/90dd4760d6f6174adb9f20cf0965ae12e23879b5f5464f38e92fce8073354341e4b3b76fa3d878351efe7d01e617121955284cfd002ab087fba1a0726ec0b4f5
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"path-exists@npm:^2.0.0":
|
"path-exists@npm:^2.0.0":
|
||||||
version: 2.1.0
|
version: 2.1.0
|
||||||
resolution: "path-exists@npm:2.1.0"
|
resolution: "path-exists@npm:2.1.0"
|
||||||
@ -10717,6 +11067,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"path-to-regexp@npm:^8.0.0":
|
||||||
|
version: 8.2.0
|
||||||
|
resolution: "path-to-regexp@npm:8.2.0"
|
||||||
|
checksum: 10c0/ef7d0a887b603c0a142fad16ccebdcdc42910f0b14830517c724466ad676107476bba2fe9fffd28fd4c141391ccd42ea426f32bb44c2c82ecaefe10c37b90f5a
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"path-type@npm:^1.0.0":
|
"path-type@npm:^1.0.0":
|
||||||
version: 1.1.0
|
version: 1.1.0
|
||||||
resolution: "path-type@npm:1.1.0"
|
resolution: "path-type@npm:1.1.0"
|
||||||
@ -10887,6 +11244,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"pkce-challenge@npm:^4.1.0":
|
||||||
|
version: 4.1.0
|
||||||
|
resolution: "pkce-challenge@npm:4.1.0"
|
||||||
|
checksum: 10c0/7cdc45977eb9af6f561a6f48ffcf19bd3e6f0c651727d00feef1c501384b1ed3c32d92ee67636f02011168959aedf099003a7c0bed668e7943444b20558c54e4
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"pkg-up@npm:^3.1.0":
|
"pkg-up@npm:^3.1.0":
|
||||||
version: 3.1.0
|
version: 3.1.0
|
||||||
resolution: "pkg-up@npm:3.1.0"
|
resolution: "pkg-up@npm:3.1.0"
|
||||||
@ -11095,6 +11459,16 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"proxy-addr@npm:~2.0.7":
|
||||||
|
version: 2.0.7
|
||||||
|
resolution: "proxy-addr@npm:2.0.7"
|
||||||
|
dependencies:
|
||||||
|
forwarded: "npm:0.2.0"
|
||||||
|
ipaddr.js: "npm:1.9.1"
|
||||||
|
checksum: 10c0/c3eed999781a35f7fd935f398b6d8920b6fb00bbc14287bc6de78128ccc1a02c89b95b56742bf7cf0362cc333c61d138532049c7dedc7a328ef13343eff81210
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"proxy-from-env@npm:^1.1.0":
|
"proxy-from-env@npm:^1.1.0":
|
||||||
version: 1.1.0
|
version: 1.1.0
|
||||||
resolution: "proxy-from-env@npm:1.1.0"
|
resolution: "proxy-from-env@npm:1.1.0"
|
||||||
@ -11135,6 +11509,24 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"qs@npm:6.13.0":
|
||||||
|
version: 6.13.0
|
||||||
|
resolution: "qs@npm:6.13.0"
|
||||||
|
dependencies:
|
||||||
|
side-channel: "npm:^1.0.6"
|
||||||
|
checksum: 10c0/62372cdeec24dc83a9fb240b7533c0fdcf0c5f7e0b83343edd7310f0ab4c8205a5e7c56406531f2e47e1b4878a3821d652be4192c841de5b032ca83619d8f860
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"qs@npm:^6.14.0":
|
||||||
|
version: 6.14.0
|
||||||
|
resolution: "qs@npm:6.14.0"
|
||||||
|
dependencies:
|
||||||
|
side-channel: "npm:^1.1.0"
|
||||||
|
checksum: 10c0/8ea5d91bf34f440598ee389d4a7d95820e3b837d3fd9f433871f7924801becaa0cd3b3b4628d49a7784d06a8aea9bc4554d2b6d8d584e2d221dc06238a42909c
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"qs@npm:~6.5.2":
|
"qs@npm:~6.5.2":
|
||||||
version: 6.5.3
|
version: 6.5.3
|
||||||
resolution: "qs@npm:6.5.3"
|
resolution: "qs@npm:6.5.3"
|
||||||
@ -11170,6 +11562,25 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"range-parser@npm:^1.2.1, range-parser@npm:~1.2.1":
|
||||||
|
version: 1.2.1
|
||||||
|
resolution: "range-parser@npm:1.2.1"
|
||||||
|
checksum: 10c0/96c032ac2475c8027b7a4e9fe22dc0dfe0f6d90b85e496e0f016fbdb99d6d066de0112e680805075bd989905e2123b3b3d002765149294dce0c1f7f01fcc2ea0
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"raw-body@npm:^3.0.0":
|
||||||
|
version: 3.0.0
|
||||||
|
resolution: "raw-body@npm:3.0.0"
|
||||||
|
dependencies:
|
||||||
|
bytes: "npm:3.1.2"
|
||||||
|
http-errors: "npm:2.0.0"
|
||||||
|
iconv-lite: "npm:0.6.3"
|
||||||
|
unpipe: "npm:1.0.0"
|
||||||
|
checksum: 10c0/f8daf4b724064a4811d118745a781ca0fb4676298b8adadfd6591155549cfea0a067523cf7dd3baeb1265fecc9ce5dfb2fc788c12c66b85202a336593ece0f87
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"rc-cascader@npm:~3.33.0":
|
"rc-cascader@npm:~3.33.0":
|
||||||
version: 3.33.1
|
version: 3.33.1
|
||||||
resolution: "rc-cascader@npm:3.33.1"
|
resolution: "rc-cascader@npm:3.33.1"
|
||||||
@ -12529,6 +12940,17 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"router@npm:^2.0.0":
|
||||||
|
version: 2.1.0
|
||||||
|
resolution: "router@npm:2.1.0"
|
||||||
|
dependencies:
|
||||||
|
is-promise: "npm:^4.0.0"
|
||||||
|
parseurl: "npm:^1.3.3"
|
||||||
|
path-to-regexp: "npm:^8.0.0"
|
||||||
|
checksum: 10c0/df17c5c07210cb72922185ea9378b318676c1e1af9110c52cfa8339bff43004f240cb6660d3b23c932f7867ab6a3ed3fe9d8e8fb0d7ac7402d0b7e7a59f9ba07
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"run-parallel@npm:^1.1.9":
|
"run-parallel@npm:^1.1.9":
|
||||||
version: 1.2.0
|
version: 1.2.0
|
||||||
resolution: "run-parallel@npm:1.2.0"
|
resolution: "run-parallel@npm:1.2.0"
|
||||||
@ -12551,7 +12973,7 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"safe-buffer@npm:^5.0.1, safe-buffer@npm:^5.1.1, safe-buffer@npm:^5.1.2, safe-buffer@npm:^5.2.1, safe-buffer@npm:~5.2.0":
|
"safe-buffer@npm:5.2.1, safe-buffer@npm:^5.0.1, safe-buffer@npm:^5.1.1, safe-buffer@npm:^5.1.2, safe-buffer@npm:^5.2.1, safe-buffer@npm:~5.2.0":
|
||||||
version: 5.2.1
|
version: 5.2.1
|
||||||
resolution: "safe-buffer@npm:5.2.1"
|
resolution: "safe-buffer@npm:5.2.1"
|
||||||
checksum: 10c0/6501914237c0a86e9675d4e51d89ca3c21ffd6a31642efeba25ad65720bce6921c9e7e974e5be91a786b25aa058b5303285d3c15dbabf983a919f5f630d349f3
|
checksum: 10c0/6501914237c0a86e9675d4e51d89ca3c21ffd6a31642efeba25ad65720bce6921c9e7e974e5be91a786b25aa058b5303285d3c15dbabf983a919f5f630d349f3
|
||||||
@ -12699,6 +13121,26 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"send@npm:^1.0.0, send@npm:^1.1.0":
|
||||||
|
version: 1.1.0
|
||||||
|
resolution: "send@npm:1.1.0"
|
||||||
|
dependencies:
|
||||||
|
debug: "npm:^4.3.5"
|
||||||
|
destroy: "npm:^1.2.0"
|
||||||
|
encodeurl: "npm:^2.0.0"
|
||||||
|
escape-html: "npm:^1.0.3"
|
||||||
|
etag: "npm:^1.8.1"
|
||||||
|
fresh: "npm:^0.5.2"
|
||||||
|
http-errors: "npm:^2.0.0"
|
||||||
|
mime-types: "npm:^2.1.35"
|
||||||
|
ms: "npm:^2.1.3"
|
||||||
|
on-finished: "npm:^2.4.1"
|
||||||
|
range-parser: "npm:^1.2.1"
|
||||||
|
statuses: "npm:^2.0.1"
|
||||||
|
checksum: 10c0/0d73408bccfd008bb50cb97225434cf565f653b66cb7961befa962a321a936eaefa6c481a1a9c30606f341afb1f08d990bcbf44949f48a68e06d63344eb91105
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"serialize-error@npm:^7.0.1":
|
"serialize-error@npm:^7.0.1":
|
||||||
version: 7.0.1
|
version: 7.0.1
|
||||||
resolution: "serialize-error@npm:7.0.1"
|
resolution: "serialize-error@npm:7.0.1"
|
||||||
@ -12708,6 +13150,18 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"serve-static@npm:^2.1.0":
|
||||||
|
version: 2.1.0
|
||||||
|
resolution: "serve-static@npm:2.1.0"
|
||||||
|
dependencies:
|
||||||
|
encodeurl: "npm:^2.0.0"
|
||||||
|
escape-html: "npm:^1.0.3"
|
||||||
|
parseurl: "npm:^1.3.3"
|
||||||
|
send: "npm:^1.0.0"
|
||||||
|
checksum: 10c0/f5b36fd3a763cdb4bf367c9be2eff587c0e52685fcf9109aa28428457c4aad0f83d8b6a1bf4929488963270026f3647f2d221c898e6dbdf9f4f5b09ed0b1f51a
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"set-blocking@npm:^2.0.0, set-blocking@npm:~2.0.0":
|
"set-blocking@npm:^2.0.0, set-blocking@npm:~2.0.0":
|
||||||
version: 2.0.0
|
version: 2.0.0
|
||||||
resolution: "set-blocking@npm:2.0.0"
|
resolution: "set-blocking@npm:2.0.0"
|
||||||
@ -12759,6 +13213,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"setprototypeof@npm:1.2.0":
|
||||||
|
version: 1.2.0
|
||||||
|
resolution: "setprototypeof@npm:1.2.0"
|
||||||
|
checksum: 10c0/68733173026766fa0d9ecaeb07f0483f4c2dc70ca376b3b7c40b7cda909f94b0918f6c5ad5ce27a9160bdfb475efaa9d5e705a11d8eaae18f9835d20976028bc
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"shallowequal@npm:1.1.0":
|
"shallowequal@npm:1.1.0":
|
||||||
version: 1.1.0
|
version: 1.1.0
|
||||||
resolution: "shallowequal@npm:1.1.0"
|
resolution: "shallowequal@npm:1.1.0"
|
||||||
@ -12833,7 +13294,7 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"side-channel@npm:^1.1.0":
|
"side-channel@npm:^1.0.6, side-channel@npm:^1.1.0":
|
||||||
version: 1.1.0
|
version: 1.1.0
|
||||||
resolution: "side-channel@npm:1.1.0"
|
resolution: "side-channel@npm:1.1.0"
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -13129,6 +13590,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"statuses@npm:2.0.1, statuses@npm:^2.0.1":
|
||||||
|
version: 2.0.1
|
||||||
|
resolution: "statuses@npm:2.0.1"
|
||||||
|
checksum: 10c0/34378b207a1620a24804ce8b5d230fea0c279f00b18a7209646d5d47e419d1cc23e7cbf33a25a1e51ac38973dc2ac2e1e9c647a8e481ef365f77668d72becfd0
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"stream-head@npm:^3.0.0":
|
"stream-head@npm:^3.0.0":
|
||||||
version: 3.0.0
|
version: 3.0.0
|
||||||
resolution: "stream-head@npm:3.0.0"
|
resolution: "stream-head@npm:3.0.0"
|
||||||
@ -13705,6 +14173,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"toidentifier@npm:1.0.1":
|
||||||
|
version: 1.0.1
|
||||||
|
resolution: "toidentifier@npm:1.0.1"
|
||||||
|
checksum: 10c0/93937279934bd66cc3270016dd8d0afec14fb7c94a05c72dc57321f8bd1fa97e5bea6d1f7c89e728d077ca31ea125b78320a616a6c6cd0e6b9cb94cb864381c1
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"token-types@npm:^4.1.1":
|
"token-types@npm:^4.1.1":
|
||||||
version: 4.2.1
|
version: 4.2.1
|
||||||
resolution: "token-types@npm:4.2.1"
|
resolution: "token-types@npm:4.2.1"
|
||||||
@ -13841,6 +14316,17 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"type-is@npm:^2.0.0":
|
||||||
|
version: 2.0.0
|
||||||
|
resolution: "type-is@npm:2.0.0"
|
||||||
|
dependencies:
|
||||||
|
content-type: "npm:^1.0.5"
|
||||||
|
media-typer: "npm:^1.1.0"
|
||||||
|
mime-types: "npm:^3.0.0"
|
||||||
|
checksum: 10c0/c1fa697c8cb77bcb3f4aa3673a3fdbe3f1c2fe51ce8c9736e9773f25c3118562723369b471063c3945722bcda5d8bf969a0693ab7b6e7da012ff667294efe988
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"typed-array-buffer@npm:^1.0.3":
|
"typed-array-buffer@npm:^1.0.3":
|
||||||
version: 1.0.3
|
version: 1.0.3
|
||||||
resolution: "typed-array-buffer@npm:1.0.3"
|
resolution: "typed-array-buffer@npm:1.0.3"
|
||||||
@ -14134,6 +14620,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"unpipe@npm:1.0.0, unpipe@npm:~1.0.0":
|
||||||
|
version: 1.0.0
|
||||||
|
resolution: "unpipe@npm:1.0.0"
|
||||||
|
checksum: 10c0/193400255bd48968e5c5383730344fbb4fa114cdedfab26e329e50dd2d81b134244bb8a72c6ac1b10ab0281a58b363d06405632c9d49ca9dfd5e90cbd7d0f32c
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"unzip-crx-3@npm:^0.2.0":
|
"unzip-crx-3@npm:^0.2.0":
|
||||||
version: 0.2.0
|
version: 0.2.0
|
||||||
resolution: "unzip-crx-3@npm:0.2.0"
|
resolution: "unzip-crx-3@npm:0.2.0"
|
||||||
@ -14226,6 +14719,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"utils-merge@npm:1.0.1":
|
||||||
|
version: 1.0.1
|
||||||
|
resolution: "utils-merge@npm:1.0.1"
|
||||||
|
checksum: 10c0/02ba649de1b7ca8854bfe20a82f1dfbdda3fb57a22ab4a8972a63a34553cf7aa51bc9081cf7e001b035b88186d23689d69e71b510e610a09a4c66f68aa95b672
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"uuid@npm:^10.0.0":
|
"uuid@npm:^10.0.0":
|
||||||
version: 10.0.0
|
version: 10.0.0
|
||||||
resolution: "uuid@npm:10.0.0"
|
resolution: "uuid@npm:10.0.0"
|
||||||
@ -14279,6 +14779,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"vary@npm:^1, vary@npm:~1.1.2":
|
||||||
|
version: 1.1.2
|
||||||
|
resolution: "vary@npm:1.1.2"
|
||||||
|
checksum: 10c0/f15d588d79f3675135ba783c91a4083dcd290a2a5be9fcb6514220a1634e23df116847b1cc51f66bfb0644cf9353b2abb7815ae499bab06e46dd33c1a6bf1f4f
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"verror@npm:1.10.0":
|
"verror@npm:1.10.0":
|
||||||
version: 1.10.0
|
version: 1.10.0
|
||||||
resolution: "verror@npm:1.10.0"
|
resolution: "verror@npm:1.10.0"
|
||||||
@ -14867,7 +15374,7 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"zod-to-json-schema@npm:^3.22.3":
|
"zod-to-json-schema@npm:^3.22.3, zod-to-json-schema@npm:^3.24.1":
|
||||||
version: 3.24.3
|
version: 3.24.3
|
||||||
resolution: "zod-to-json-schema@npm:3.24.3"
|
resolution: "zod-to-json-schema@npm:3.24.3"
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@ -14876,7 +15383,7 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"zod@npm:^3.22.4":
|
"zod@npm:^3.22.4, zod@npm:^3.23.8":
|
||||||
version: 3.24.2
|
version: 3.24.2
|
||||||
resolution: "zod@npm:3.24.2"
|
resolution: "zod@npm:3.24.2"
|
||||||
checksum: 10c0/c638c7220150847f13ad90635b3e7d0321b36cce36f3fc6050ed960689594c949c326dfe2c6fa87c14b126ee5d370ccdebd6efb304f41ef5557a4aaca2824565
|
checksum: 10c0/c638c7220150847f13ad90635b3e7d0321b36cce36f3fc6050ed960689594c949c326dfe2c6fa87c14b126ee5d370ccdebd6efb304f41ef5557a4aaca2824565
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user