fix: address code review findings from Phase 2 final review

- ChatPanel: add 'chat-message ${role}' CSS classes to message wrappers
  so .chat-message.user and .chat-message.assistant rules apply correctly
- LoginPage: rename className 'login-error' -> 'error' to match the
  .login-card .error selector in globals.css
- MCPAppRenderer: verify event.source matches iframe contentWindow before
  processing postMessage to close cross-window injection vector
- App: remove redundant await refresh() after createNew() since
  createNew() already calls refresh() internally
- useArtifacts: wrap listArtifacts call in try/catch with console.error,
  matching the error-handling pattern already used in useSessions
This commit is contained in:
Ken
2026-05-26 19:46:38 +00:00
parent 9d118d60ce
commit 8e69ac185e
5 changed files with 9 additions and 5 deletions
-1
View File
@@ -31,7 +31,6 @@ function App() {
onSelect={(id) => switchTo(id)} onSelect={(id) => switchTo(id)}
onCreate={async () => { onCreate={async () => {
await createNew() await createNew()
await refresh()
}} }}
onLogout={logout} onLogout={logout}
/> />
+1 -1
View File
@@ -58,7 +58,7 @@ export function ChatPanel({ messages, isStreaming, onSend, sessionId }: ChatPane
<div className='chat-panel'> <div className='chat-panel'>
<div className='chat-messages'> <div className='chat-messages'>
{messages.map(message => ( {messages.map(message => (
<div key={message.id}> <div key={message.id} className={`chat-message ${message.role}`}>
{message.role === 'assistant' ? ( {message.role === 'assistant' ? (
<div> <div>
<ReactMarkdown>{message.content}</ReactMarkdown> <ReactMarkdown>{message.content}</ReactMarkdown>
+1 -1
View File
@@ -28,7 +28,7 @@ export function LoginPage({ onLogin }: LoginPageProps) {
<div className="login-page"> <div className="login-page">
<form className="login-card" onSubmit={handleSubmit}> <form className="login-card" onSubmit={handleSubmit}>
<h2>Research Workbench</h2> <h2>Research Workbench</h2>
{error && <div className="login-error">{error}</div>} {error && <div className="error">{error}</div>}
<label htmlFor="email">Email</label> <label htmlFor="email">Email</label>
<input <input
id="email" id="email"
@@ -53,6 +53,7 @@ export function MCPAppRenderer({
const handleMessage = useCallback( const handleMessage = useCallback(
(event: MessageEvent) => { (event: MessageEvent) => {
if (!iframeRef.current?.contentWindow) return if (!iframeRef.current?.contentWindow) return
if (event.source !== iframeRef.current.contentWindow) return
const msg = event.data const msg = event.data
if (!msg || msg.jsonrpc !== '2.0') return if (!msg || msg.jsonrpc !== '2.0') return
+4
View File
@@ -8,8 +8,12 @@ export function useArtifacts(sessionId: string | null) {
async function refresh() { async function refresh() {
if (!sessionId) return if (!sessionId) return
try {
const data = await api.listArtifacts(sessionId) const data = await api.listArtifacts(sessionId)
setArtifacts(data) setArtifacts(data)
} catch (err) {
console.error('Failed to list artifacts:', err)
}
} }
async function loadArtifact(name: string) { async function loadArtifact(name: string) {