-
Notifications
You must be signed in to change notification settings - Fork 13.2k
feat: Implement Model Context Protocol (MCP) Gateway and Tool Discovery #38096
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,18 +1,31 @@ | ||
| import type { ComponentType, ReactNode, ComponentProps } from 'react'; | ||
| import React, { ComponentType, ReactNode, ComponentProps } from 'react'; | ||
| import { ErrorBoundary } from 'react-error-boundary'; | ||
|
|
||
| function withErrorBoundary<T extends object>(Component: ComponentType<T>, fallback: ReactNode = null) { | ||
| const WrappedComponent = function (props: ComponentProps<typeof Component>) { | ||
| return ( | ||
| <ErrorBoundary fallback={<>{fallback}</>}> | ||
| <Component {...props} /> | ||
| </ErrorBoundary> | ||
| ); | ||
| }; | ||
| import { ComponentErrorFallback } from '../components/errors/ErrorFallbacks'; | ||
| import { errorTrackingService } from '../services/ErrorTrackingService'; | ||
|
|
||
| export function withErrorBoundary<T extends object>( | ||
| Component: ComponentType<T>, | ||
| fallback: ReactNode = <ComponentErrorFallback />, | ||
| scope: 'global' | 'feature' | 'component' = 'component', | ||
| ) { | ||
| const WrappedComponent = (props: ComponentProps<typeof Component>) => ( | ||
| <ErrorBoundary | ||
| fallback={<>{fallback}</>} | ||
| onError={(error) => { | ||
| errorTrackingService.reportError(error, { | ||
| scope, | ||
| severity: scope === 'global' ? 'critical' : 'high', | ||
| recoverable: true, | ||
| componentPath: Component.displayName || Component.name, | ||
| }); | ||
| }} | ||
| > | ||
| <Component {...props} /> | ||
| </ErrorBoundary> | ||
| ); | ||
|
|
||
| WrappedComponent.displayName = `withErrorBoundary(${Component.displayName ?? Component.name ?? 'Component'})`; | ||
|
|
||
| return WrappedComponent; | ||
| } | ||
|
|
||
| export { withErrorBoundary }; |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,47 @@ | ||||||
| import { Box, Option, Icon, States, StatesIcon, StatesTitle } from '@rocket.chat/fuselage'; | ||||||
| import React from 'react'; | ||||||
| import { useTranslation } from 'react-i18next'; | ||||||
|
|
||||||
| // FIX: Define proper interface to replace 'any[]' | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion | 🟠 Major Remove FIX comments per coding guidelines. The coding guidelines specify to avoid code comments in the implementation. The FIX comment on line 5 is also stale, referencing ♻️ Proposed refactor-// FIX: Define proper interface to replace 'any[]'
interface MCPTool {
name: string;
description: string;
}- // FIX: Defensive validation - filter out malformed data
const validTools = tools.filter((tool) => tool && typeof tool.name === 'string' && tool.name.trim() !== '');- // FIX: Use a unique key combining name and index for stability
<Option key={`${tool.name}-${index}`}> <Box mi='x8'>
- {/* FIX: Use nullish coalescing for display safety */}
<Box fontScale='p2m'>{tool.name ?? t('Unknown_Tool')}</Box>Also applies to: 18-18, 33-33, 37-37 🤖 Prompt for AI Agents |
||||||
| interface MCPTool { | ||||||
| name: string; | ||||||
| description: string; | ||||||
| } | ||||||
|
|
||||||
| interface MCPToolListProps { | ||||||
| tools: MCPTool[]; | ||||||
| } | ||||||
|
|
||||||
| export const MCPToolList = ({ tools }: MCPToolListProps) => { | ||||||
| const { t } = useTranslation(); | ||||||
|
|
||||||
| // FIX: Defensive validation - filter out malformed data | ||||||
| const validTools = tools.filter((tool) => tool && typeof tool.name === 'string' && tool.name.trim() !== ''); | ||||||
|
|
||||||
| if (validTools.length === 0) { | ||||||
| return ( | ||||||
| <States inline> | ||||||
| <StatesIcon name='ai' /> | ||||||
| <StatesTitle>{t('No_MCP_Tools_Available')}</StatesTitle> | ||||||
| </States> | ||||||
| ); | ||||||
| } | ||||||
|
|
||||||
| return ( | ||||||
| <Box> | ||||||
| {validTools.map((tool, index) => ( | ||||||
| // FIX: Use a unique key combining name and index for stability | ||||||
| <Option key={`${tool.name}-${index}`}> | ||||||
| <Icon name='robot' size='x20' /> | ||||||
| <Box mi='x8'> | ||||||
| {/* FIX: Use nullish coalescing for display safety */} | ||||||
| <Box fontScale='p2m'>{tool.name ?? t('Unknown_Tool')}</Box> | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove unreachable fallback code. The validation on line 19 ensures 🧹 Proposed fix- <Box fontScale='p2m'>{tool.name ?? t('Unknown_Tool')}</Box>
+ <Box fontScale='p2m'>{tool.name}</Box>📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||
| <Box fontScale='c1' color='hint'> | ||||||
| {tool.description ?? ''} | ||||||
| </Box> | ||||||
| </Box> | ||||||
| </Option> | ||||||
| ))} | ||||||
| </Box> | ||||||
| ); | ||||||
| }; | ||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,43 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { MCPClient } from '@modelcontextprotocol/sdk'; // Hypothetical SDK usage | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export interface MCPConfig { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| serverId: string; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| url: string; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| enabled: boolean; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| class MCPGatewayService { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private clients: Map<string, any> = new Map(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Replace Typing the Map value as 🔧 Proposed fix- private clients: Map<string, any> = new Map();
+ private clients: Map<string, MCPClient> = new Map();📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * Connects to a new MCP server provided by the user/admin | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public async connectServer(config: MCPConfig): Promise<void> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!config.enabled) return; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Initialize connection to the remote MCP server | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const client = new MCPClient({ url: config.url }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| await client.connect(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| this.clients.set(config.serverId, client); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.log(`[MCP] Connected to server: ${config.serverId}`); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } catch (error) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.error(`[MCP] Connection failed for ${config.serverId}:`, error); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+15
to
+28
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add resource cleanup and duplicate serverId handling. Multiple issues require attention:
🔧 Proposed fix public async connectServer(config: MCPConfig): Promise<void> {
if (!config.enabled) return;
+
+ // Validate URL
+ try {
+ new URL(config.url);
+ } catch {
+ throw new Error(`Invalid MCP server URL: ${config.url}`);
+ }
+
+ // Disconnect existing client if present
+ const existingClient = this.clients.get(config.serverId);
+ if (existingClient) {
+ await existingClient.disconnect?.();
+ }
try {
// Initialize connection to the remote MCP server
const client = new MCPClient({ url: config.url });
await client.connect();
this.clients.set(config.serverId, client);
console.log(`[MCP] Connected to server: ${config.serverId}`);
} catch (error) {
console.error(`[MCP] Connection failed for ${config.serverId}:`, error);
+ throw error;
}
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * Lists available tools from all connected MCP servers | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public async getAllTools() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const allTools = []; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for (const client of this.clients.values()) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const tools = await client.listTools(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| allTools.push(...tools); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return allTools; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+33
to
+40
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Handle individual client failures gracefully. If any 🛡️ Proposed fix for resilient tool aggregation public async getAllTools() {
const allTools = [];
for (const client of this.clients.values()) {
- const tools = await client.listTools();
- allTools.push(...tools);
+ try {
+ const tools = await client.listTools();
+ allTools.push(...tools);
+ } catch (error) {
+ console.error('[MCP] Failed to list tools from client:', error);
+ // Continue with other clients
+ }
}
return allTools;
}🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export const mcpGatewayService = new MCPGatewayService(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+9
to
+43
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion | 🟠 Major Add cleanup methods and replace console logging. To align with the PR's error tracking infrastructure and production-grade requirements:
♻️ Proposed additionsAdd cleanup methods: /**
* Disconnects a specific MCP server
*/
public async disconnectServer(serverId: string): Promise<void> {
const client = this.clients.get(serverId);
if (client) {
try {
await client.disconnect?.();
this.clients.delete(serverId);
} catch (error) {
console.error(`[MCP] Failed to disconnect ${serverId}:`, error);
}
}
}
/**
* Disconnects all MCP servers (cleanup on shutdown)
*/
public async disconnectAll(): Promise<void> {
const disconnectPromises = Array.from(this.clients.keys()).map(
serverId => this.disconnectServer(serverId)
);
await Promise.allSettled(disconnectPromises);
}Replace console logging with your error tracking service (refer to the ErrorTrackingService mentioned in the PR context). 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,28 +1,43 @@ | ||
| import * as UiKit from '@rocket.chat/ui-kit'; | ||
| import type { ReactElement } from 'react'; | ||
| import { ErrorBoundary } from 'react-error-boundary'; | ||
|
|
||
| import { FuselageSurfaceRenderer, renderTextObject } from './FuselageSurfaceRenderer'; | ||
| import VideoConferenceBlock from '../blocks/VideoConferenceBlock'; | ||
| import { AppIdProvider } from '../contexts/AppIdContext'; | ||
| import { ComponentErrorFallback } from '../components/errors/ErrorFallbacks'; | ||
| import { errorTrackingService } from '../services/ErrorTrackingService'; | ||
|
|
||
| export class FuselageMessageSurfaceRenderer extends FuselageSurfaceRenderer { | ||
| public constructor() { | ||
| super(['actions', 'context', 'divider', 'image', 'input', 'section', 'preview', 'video_conf', 'info_card']); | ||
| } | ||
| public constructor() { | ||
| super(['actions', 'context', 'divider', 'image', 'input', 'section', 'preview', 'video_conf', 'info_card']); | ||
| } | ||
|
|
||
| override plain_text = renderTextObject; | ||
| override plain_text = renderTextObject; | ||
|
|
||
| override mrkdwn = renderTextObject; | ||
| override mrkdwn = renderTextObject; | ||
|
|
||
| video_conf(block: UiKit.VideoConferenceBlock, context: UiKit.BlockContext, index: number): ReactElement | null { | ||
| if (context === UiKit.BlockContext.BLOCK) { | ||
| return ( | ||
| <AppIdProvider key={index} appId={block.appId}> | ||
| <VideoConferenceBlock block={block} context={context} index={index} surfaceRenderer={this} /> | ||
| </AppIdProvider> | ||
| ); | ||
| } | ||
| video_conf(block: UiKit.VideoConferenceBlock, context: UiKit.BlockContext, index: number): ReactElement | null { | ||
| if (context === UiKit.BlockContext.BLOCK) { | ||
| return ( | ||
|
|
||
| <ErrorBoundary | ||
| key={index} | ||
| fallback={<ComponentErrorFallback />} | ||
| onError={(error) => errorTrackingService.reportError(error, { | ||
| scope: 'component', | ||
| severity: 'medium', | ||
| recoverable: true, | ||
| componentPath: 'FuselageMessageSurfaceRenderer.video_conf' | ||
| })} | ||
| > | ||
| <AppIdProvider appId={block.appId}> | ||
| <VideoConferenceBlock block={block} context={context} index={index} surfaceRenderer={this} /> | ||
| </AppIdProvider> | ||
| </ErrorBoundary> | ||
| ); | ||
| } | ||
|
|
||
| return null; | ||
| } | ||
| return null; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,6 +3,7 @@ import i18next from 'i18next'; | |
| import { Component } from 'preact'; | ||
| import Router, { route } from 'preact-router'; | ||
| import { withTranslation } from 'react-i18next'; | ||
| import { ErrorBoundary } from 'react-error-boundary'; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P1: The Prompt for AI agents
Comment on lines
3
to
+6
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# First, check package.json for the livechat package to see alias configuration
echo "=== Checking livechat package.json ==="
cat packages/livechat/package.json
echo -e "\n=== Looking for preact/compat configuration ==="
# Search for preact/compat references
rg -n "preact/compat" packages/livechat/ --type json --type js --type ts
echo -e "\n=== Checking for react alias configuration ==="
# Look for alias config in package.json or build files
rg -n "alias.*react|\"react\":" packages/livechat/ --type json -A2 -B2
echo -e "\n=== Check webpack or build configuration ==="
find packages/livechat -name "webpack*.js" -o -name "vite.config.*" -o -name "rollup.config.*" -o -name "tsconfig.json" | head -20Repository: RocketChat/Rocket.Chat Length of output: 12601 🏁 Script executed: #!/bin/bash
# Check the root package.json for workspace configuration related to livechat
echo "=== Root monorepo config (package.json extract) ==="
rg -n "preact|alias" package.json -A2 -B2
echo -e "\n=== Check if react-error-boundary is installed ==="
rg -n "react-error-boundary" packages/livechat/package.json
echo -e "\n=== Look for any compatibility setup in livechat ==="
find packages/livechat -name ".babelrc*" -o -name "jest.config.*" | xargs cat 2>/dev/nullRepository: RocketChat/Rocket.Chat Length of output: 223 🏁 Script executed: #!/bin/bash
# Check the actual imports in App.tsx
cat -n packages/livechat/src/components/App/App.tsx | head -20Repository: RocketChat/Rocket.Chat Length of output: 1133 🏁 Script executed: #!/bin/bash
# Check if react-error-boundary appears anywhere in dependencies across the monorepo
rg "react-error-boundary" --type json | head -20Repository: RocketChat/Rocket.Chat Length of output: 194 🏁 Script executed: #!/bin/bash
# Check if react-error-boundary is a transitive dependency from other packages in livechat
echo "=== Checking if react-error-boundary might be transitive ==="
# Check react-i18next and other react packages in livechat
rg "react-i18next|react-hook-form" packages/livechat/package.json -A1 -B1
echo -e "\n=== Check package-lock or yarn.lock for react-error-boundary ==="
# Look for any reference in lock files
find . -maxdepth 1 -name "*lock*" -o -name "*yarn*" | head -5
echo -e "\n=== Verify if the build actually works ==="
# Check if there are any build errors or warnings in CI config related to this
find . -name "*.yml" -o -name "*.yaml" | xargs grep -l "livechat" 2>/dev/null | head -3Repository: RocketChat/Rocket.Chat Length of output: 395 🏁 Script executed: #!/bin/bash
# Simpler check: look at what react-i18next depends on
echo "=== Dependencies of packages that might pull in react-error-boundary ==="
cat packages/livechat/package.json | grep -A1 '"react-i18next"'
# Check if there's any documentation about the missing dependency
grep -r "react-error-boundary" packages/livechat --include="*.md" --include="*.ts" --include="*.tsx" --include="*.js" | grep -v node_modules | head -10Repository: RocketChat/Rocket.Chat Length of output: 302
The import on line 6 references 🤖 Prompt for AI Agents |
||
|
|
||
| import type { Department } from '../../definitions/departments'; | ||
| import { setInitCookies } from '../../helpers/cookies'; | ||
|
|
@@ -24,6 +25,10 @@ import SwitchDepartment from '../../routes/SwitchDepartment'; | |
| import TriggerMessage from '../../routes/TriggerMessage'; | ||
| import type { Dispatch, StoreState } from '../../store'; | ||
| import { ScreenProvider } from '../Screen/ScreenProvider'; | ||
| import { GlobalErrorFallback } from '../../../../ui-client/src/components/errors/ErrorFallbacks'; | ||
cubic-dev-ai[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| import { errorTrackingService } from '../../../../ui-client/src/services/ErrorTrackingService'; | ||
| import { ScreenProvider } from '../Screen/ScreenProvider'; | ||
| import { GlobalErrorFallback, errorTrackingService } from '@rocket.chat/ui-client'; | ||
|
|
||
| type AppProps = { | ||
| config: { | ||
|
|
@@ -164,7 +169,6 @@ export class App extends Component<AppProps, AppState> { | |
| } | ||
|
|
||
| protected async initialize() { | ||
| // TODO: split these behaviors into composable components | ||
| await Connection.init(); | ||
| CustomFields.init(); | ||
| userPresence.init(); | ||
|
|
@@ -203,19 +207,29 @@ export class App extends Component<AppProps, AppState> { | |
| } | ||
|
|
||
| return ( | ||
| <ScreenProvider> | ||
| <Router history={history} onChange={this.handleRoute}> | ||
| <ChatConnector path='/' default /> | ||
| <ChatFinished path='/chat-finished' /> | ||
| <GDPRAgreement path='/gdpr' /> | ||
| <LeaveMessage path='/leave-message' /> | ||
| <Register path='/register' /> | ||
| <SwitchDepartment path='/switch-department' /> | ||
| <TriggerMessage path='/trigger-messages' /> | ||
| </Router> | ||
| </ScreenProvider> | ||
| <ErrorBoundary | ||
| FallbackComponent={GlobalErrorFallback} | ||
| onError={(error) => errorTrackingService.reportError(error, { | ||
| scope: 'global', | ||
| severity: 'critical', | ||
| recoverable: false, | ||
| componentPath: 'LivechatApp' | ||
| })} | ||
| > | ||
| <ScreenProvider> | ||
| <Router history={history} onChange={this.handleRoute}> | ||
| <ChatConnector path='/' default /> | ||
| <ChatFinished path='/chat-finished' /> | ||
| <GDPRAgreement path='/gdpr' /> | ||
| <LeaveMessage path='/leave-message' /> | ||
| <Register path='/register' /> | ||
| <SwitchDepartment path='/switch-department' /> | ||
| <TriggerMessage path='/trigger-messages' /> | ||
| </Router> | ||
| </ScreenProvider> | ||
| </ErrorBoundary> | ||
| ); | ||
| }; | ||
| } | ||
|
|
||
| export default withTranslation()(App); | ||
| export default withTranslation()(App); | ||
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,6 +1,6 @@ | ||||||||||
| { | ||||||||||
| "name": "@rocket.chat/ui-client", | ||||||||||
| "version": "26.0.0-rc.1", | ||||||||||
| "name": "@rocket.chat/livechat", | ||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P0: Critical: This package is being renamed from Prompt for AI agents
Suggested change
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P0: Critical: Package name incorrectly changed from Prompt for AI agents
Suggested change
|
||||||||||
| "version": "1.0.0", | ||||||||||
|
Comment on lines
+2
to
+3
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Search for all references to the old package name @rocket.chat/ui-client
echo "=== Searching for import statements referencing @rocket.chat/ui-client ==="
rg -n '@rocket\.chat/ui-client' --type ts --type tsx --type js --type jsx -g '!node_modules' -g '!dist' -g '!*.lock' 2>/dev/null | head -50
echo ""
echo "=== Searching in all package.json files for @rocket.chat/ui-client ==="
fd -e json 'package.json' -x grep -H '@rocket\.chat/ui-client' {} \; | grep -v node_modules | head -30
echo ""
echo "=== Checking current directory structure ==="
ls -la packages/ | grep -E "(ui-client|livechat)"
echo ""
echo "=== Checking for references to @rocket.chat/livechat ==="
rg -n '@rocket\.chat/livechat' --type ts --type tsx --type js --type jsx -g '!node_modules' -g '!dist' 2>/dev/null | head -30
echo ""
echo "=== List all package.json files in packages directory ==="
fd 'package.json' packages/ | head -20Repository: RocketChat/Rocket.Chat Length of output: 1690 🏁 Script executed: #!/bin/bash
echo "=== packages/ui-client/package.json content ==="
cat packages/ui-client/package.json
echo ""
echo "=== packages/livechat/package.json content ==="
cat packages/livechat/package.jsonRepository: RocketChat/Rocket.Chat Length of output: 6840 Critical: Duplicate package name and broken dependencies prevent build. The package in
All references must be updated consistently, and the duplicate package name must be resolved before this can merge. 🤖 Prompt for AI Agents |
||||||||||
| "private": true, | ||||||||||
| "main": "./dist/index.js", | ||||||||||
| "typings": "./dist/index.d.ts", | ||||||||||
|
|
@@ -19,7 +19,9 @@ | |||||||||
| }, | ||||||||||
| "dependencies": { | ||||||||||
| "@rocket.chat/onboarding-ui": "~0.36.0", | ||||||||||
| "dompurify": "~3.2.7" | ||||||||||
| "@rocket.chat/ui-client": "workspace:~", | ||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P0: Adding Prompt for AI agents |
||||||||||
| "dompurify": "~3.2.7", | ||||||||||
| "react-error-boundary": "^5.0.0" | ||||||||||
|
Comment on lines
+23
to
+24
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🌐 Web query:
💡 Result: Short answer (as of Jan 8, 2026): the react-error-boundary package latest published version is 6.0.1, and there are no known direct security vulnerabilities reported for the package itself. [1][2] Sources:
If you want, I can list its release date, scan it for transitive (dependency) issues, or check npm advisories/CVE databases for further confirmation. 🌐 Web query:
💡 Result: Short answer
Known security issues (important ones from 2024–2025)
Recommendation
Sources 🏁 Script executed: #!/bin/bash
# Check npm registry data for both packages to get version info and vulnerability status
npm view react-error-boundary@5.0.0 --json 2>/dev/null | head -50
npm view dompurify@3.2.7 --json 2>/dev/null | head -50Repository: RocketChat/Rocket.Chat Length of output: 1506 Consider updating to more current versions. The versions specified are functional but outdated:
🤖 Prompt for AI Agents |
||||||||||
| }, | ||||||||||
| "devDependencies": { | ||||||||||
| "@react-aria/toolbar": "^3.0.0-nightly.5042", | ||||||||||
|
|
@@ -54,6 +56,7 @@ | |||||||||
| "jest": "~30.2.0", | ||||||||||
| "overlayscrollbars": "^2.11.4", | ||||||||||
| "overlayscrollbars-react": "^0.5.6", | ||||||||||
| "preact": "^10.0.0", | ||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Search for preact usage in the codebase
echo "=== Searching for preact imports ==="
rg -n "from ['\"]preact" packages/ui-client/ -g '!node_modules' -g '!dist' 2>/dev/null || echo "No matches found"
echo ""
echo "=== Searching for preact/compat usage ==="
rg -n "preact/compat" packages/ui-client/ -g '!node_modules' -g '!dist' 2>/dev/null || echo "No matches found"
echo ""
echo "=== Searching for preact in require statements ==="
rg -n "require.*preact" packages/ui-client/ -g '!node_modules' -g '!dist' 2>/dev/null || echo "No matches found"
echo ""
echo "=== Checking package.json for preact references ==="
cat packages/ui-client/package.json | grep -i preact || echo "No preact references in package.json"
echo ""
echo "=== Checking jest/webpack/vite configs ==="
fd -t f \( -name 'jest.config.*' -o -name 'webpack.config.*' -o -name 'vite.config.*' \) packages/ui-client/ 2>/dev/null | head -5 | xargs -I {} sh -c 'echo "File: {}"; grep -i preact {} 2>/dev/null || echo " (no preact references)"'Repository: RocketChat/Rocket.Chat Length of output: 368 Remove the unused The 🤖 Prompt for AI Agents |
||||||||||
| "re-resizable": "^6.10.1", | ||||||||||
| "react": "~18.3.1", | ||||||||||
| "react-dom": "~18.3.1", | ||||||||||
|
|
||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use the project's standard
useTranslationhook.The component imports
useTranslationfromreact-i18next, but the project uses its own implementation from@rocket.chat/ui-contexts. This inconsistency could cause i18n to fail or use an incorrect translation context.🔧 Proposed fix
📝 Committable suggestion
🤖 Prompt for AI Agents