Skip to content

Commit 43c7156

Browse files
committed
feat: Add Upgrade Audit Tool and AI ChatInput POC for GSoC 2026 roadmap
1 parent 70ab95f commit 43c7156

2 files changed

Lines changed: 121 additions & 0 deletions

File tree

packages/react/src/views/ChatInput/ChatInput.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import useSearchEmoji from '../../hooks/useSearchEmoji';
3737
import formatSelection from '../../lib/formatSelection';
3838
import { parseEmoji } from '../../lib/emoji';
3939
import useDropBox from '../../hooks/useDropBox';
40+
import { GeminiAiAdapter } from '../../lib/ai/GeminiAiAdapter';
4041

4142
const ChatInput = ({ scrollToBottom, clearUnreadDividerRef }) => {
4243
const { styleOverrides, classNames } = useComponentOverrides('ChatInput');
@@ -64,6 +65,24 @@ const ChatInput = ({ scrollToBottom, clearUnreadDividerRef }) => {
6465
const [emojiIndex, setEmojiIndex] = useState(-1);
6566
const [startReadEmoji, setStartReadEmoji] = useState(false);
6667
const [isMsgLong, setIsMsgLong] = useState(false);
68+
const [isAiLoading, setIsAiLoading] = useState(false);
69+
70+
const handleAiAssist = async () => {
71+
setIsAiLoading(true);
72+
try {
73+
const adapter = new GeminiAiAdapter('dummy-key');
74+
const dummyContext = [{ msg: messageRef.current.value || 'Hello! What can I help you with today?' }];
75+
const replies = await adapter.getSmartReplies(dummyContext);
76+
if (replies && replies.length > 0) {
77+
messageRef.current.value = (messageRef.current.value + ' ' + replies[0]).trim();
78+
setDisableButton(false);
79+
}
80+
} catch (e) {
81+
console.error(e);
82+
dispatchToastMessage({ type: 'error', message: 'AI generation failed.' });
83+
}
84+
setIsAiLoading(false);
85+
};
6786

6887
const {
6988
isUserAuthenticated,
@@ -710,8 +729,21 @@ const ChatInput = ({ scrollToBottom, clearUnreadDividerRef }) => {
710729
<Box
711730
css={css`
712731
padding: 0.25rem;
732+
display: flex;
733+
gap: 0.5rem;
713734
`}
714735
>
736+
{!isChannelArchived && (
737+
<Button
738+
onClick={handleAiAssist}
739+
type="secondary"
740+
size="small"
741+
disabled={isAiLoading || disableButton === false && messageRef.current?.value?.length > 50}
742+
css={css`border-radius: 4px; border: 1px solid #ddd; background: #f0f0f0;`}
743+
>
744+
{isAiLoading ? '...' : '✨ AI'}
745+
</Button>
746+
)}
715747
{isUserAuthenticated ? (
716748
!isChannelArchived ? (
717749
<ActionButton

scripts/upgrade-audit.js

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
/**
2+
* POC: GSoC 2026 - Stack Modernization & API Audit Tool
3+
* This script demonstrates the automated assessment mechanism for upgrading
4+
* EmbeddedChat to modern versions (Node 20, React 18, latest Rocket.Chat APIs).
5+
*/
6+
7+
const fs = require('fs');
8+
const path = require('path');
9+
10+
const rootDir = process.cwd();
11+
const packagePath = path.join(rootDir, 'package.json');
12+
const reactPkgPath = path.join(rootDir, 'packages/react/package.json');
13+
14+
console.log('--- EmbeddedChat 2026: Upgrade & API Audit POC ---\n');
15+
16+
function auditPackageJson(filePath, label) {
17+
if (!fs.existsSync(filePath)) {
18+
console.error(`[Error] ${label} package.json not found.`);
19+
return;
20+
}
21+
const pkg = JSON.parse(fs.readFileSync(filePath, 'utf8'));
22+
console.log(`[Audit] Scanning ${label}...`);
23+
console.log(` - Name: ${pkg.name}`);
24+
console.log(` - Current Version: ${pkg.version}`);
25+
26+
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
27+
const criticalUpdates = [
28+
{ name: 'react', target: '^18.3.0', reason: 'Modernization requirement' },
29+
{ name: 'node', target: '>=20.0.0', reason: 'LTS requirement' },
30+
{ name: '@rocket.chat/sdk', target: '^1.0.0', reason: 'API Unified schema support' },
31+
{ name: 'eslint', target: '^8.0.0', reason: 'Compatibility with React 18 plugins' }
32+
];
33+
34+
criticalUpdates.forEach(update => {
35+
const current = deps[update.name] || 'Not found';
36+
const status = (current === update.target) ? 'OK' : 'NEEDS UPGRADE';
37+
console.log(` - ${update.name.padEnd(16)}: ${current.padEnd(10)} -> Target: ${update.target.padEnd(10)} [${status}]`);
38+
});
39+
}
40+
41+
function scanForDeprecatedPatterns(dir) {
42+
const patterns = [
43+
{ regex: /ReactDOM\.render/g, name: 'ReactDOM.render', fix: 'createRoot (React 18)' },
44+
{ regex: /componentWillReceiveProps/g, name: 'Legacy Lifecycle', fix: 'getDerivedStateFromProps' },
45+
{ regex: /stream-room-messages/g, name: 'Legacy WS Subscription', fix: 'Realtime API v2' }
46+
];
47+
48+
console.log('\n[Code Audit] Scanning for deprecated patterns in src/ ...');
49+
50+
const files = getAllFiles(dir).filter(f => f.endsWith('.js') || f.endsWith('.jsx'));
51+
const findings = [];
52+
53+
files.forEach(file => {
54+
const content = fs.readFileSync(file, 'utf8');
55+
patterns.forEach(p => {
56+
if (p.regex.test(content)) {
57+
findings.push(`[${p.name}] found in ${path.relative(rootDir, file)}. Suggested fix: ${p.fix}`);
58+
}
59+
});
60+
});
61+
62+
if (findings.length > 0) {
63+
findings.slice(0, 5).forEach(f => console.log(` ! ${f}`));
64+
if (findings.length > 5) console.log(` ... and ${findings.length - 5} more findings.`);
65+
} else {
66+
console.log(' - No deprecated patterns found in the sampled files.');
67+
}
68+
}
69+
70+
function getAllFiles(dirPath, arrayOfFiles) {
71+
const files = fs.readdirSync(dirPath);
72+
arrayOfFiles = arrayOfFiles || [];
73+
files.forEach(function(file) {
74+
if (fs.statSync(dirPath + "/" + file).isDirectory()) {
75+
if (file !== 'node_modules' && file !== 'dist') {
76+
arrayOfFiles = getAllFiles(dirPath + "/" + file, arrayOfFiles);
77+
}
78+
} else {
79+
arrayOfFiles.push(path.join(dirPath, "/", file));
80+
}
81+
});
82+
return arrayOfFiles;
83+
}
84+
85+
auditPackageJson(packagePath, 'Root Monorepo');
86+
auditPackageJson(reactPkgPath, 'React Package');
87+
scanForDeprecatedPatterns(path.join(rootDir, 'packages/react/src'));
88+
89+
console.log('\n[Conclusion] Automated audit complete. Summary generated for GSoC 2026 Roadmap.');

0 commit comments

Comments
 (0)