diff --git a/ai-hub/app/api/routes/mcp.py b/ai-hub/app/api/routes/mcp.py index 895f8e8..6f0f77c 100644 --- a/ai-hub/app/api/routes/mcp.py +++ b/ai-hub/app/api/routes/mcp.py @@ -180,14 +180,14 @@ if isinstance(body, list): results = [] for item in body: - results.append(await _handle_single(item, token, services)) + results.append(await _handle_single(item, user_id, services)) return JSONResponse( [r for r in results if r is not None], headers={"Access-Control-Allow-Origin": "*", "MCP-Protocol-Version": MCP_VERSION}, ) # Single request - response = await _handle_single(body, token, services) + response = await _handle_single(body, user_id, services) if response is None: # notification — no id return JSONResponse( None, status_code=202, @@ -538,9 +538,12 @@ raise ValueError("node_id and path are required.") def _execute_write(): - orchestrator = services.orchestrator - res = orchestrator.assistant.write(node_id, path, content, is_dir, session_id=session_id) - return res + from app.db.session import get_db_session + with get_db_session() as db: + services.mesh_service.require_node_access(token, node_id, db) + orchestrator = services.orchestrator + res = orchestrator.assistant.write(node_id, path, content, is_dir, session_id=session_id) + return res return _ok(await loop.run_in_executor(None, _execute_write)) @@ -555,9 +558,12 @@ raise ValueError("node_id and path are required.") def _execute_delete(): - orchestrator = services.orchestrator - res = orchestrator.assistant.rm(node_id, path, session_id=session_id) - return res + from app.db.session import get_db_session + with get_db_session() as db: + services.mesh_service.require_node_access(token, node_id, db) + orchestrator = services.orchestrator + res = orchestrator.assistant.rm(node_id, path, session_id=session_id) + return res return _ok(await loop.run_in_executor(None, _execute_delete)) diff --git a/frontend/src/features/chat/components/ChatWindow.js b/frontend/src/features/chat/components/ChatWindow.js index ca4dff4..30218b1 100644 --- a/frontend/src/features/chat/components/ChatWindow.js +++ b/frontend/src/features/chat/components/ChatWindow.js @@ -7,6 +7,7 @@ // Individual message component const ChatMessage = ({ message, index, onSynthesize, featureName = "default", activePlayingId, onPlayStateChange, evaluationMetadata }) => { const [isReasoningExpanded, setIsReasoningExpanded] = useState(false); + const [isEvalExpanded, setIsEvalExpanded] = useState(false); const [audioUrl, setAudioUrl] = useState(null); const [isPlaying, setIsPlaying] = useState(false); const audioRef = useRef(null); @@ -135,10 +136,12 @@
- {message.reasoning} + {isReasoningExpanded && ( + {message.reasoning} + )}
)} @@ -151,7 +154,7 @@ {/* Per-Answer Evaluation Metadata (Area 4: Quality Rubric / Feedback / History) */} {!message.isUser && effectiveEval && (effectiveEval.rubric || effectiveEval.feedback || (effectiveEval.history && effectiveEval.history.length > 0)) && (
-
+
setIsEvalExpanded(e.target.open)}>
@@ -159,55 +162,59 @@
-
- {/* Rubric snippet */} - {effectiveEval.rubric && ( -
-
-
📝 Quality Rubric -
-
- {effectiveEval.rubric} -
-
- )} - - {/* Feedback snippet */} - {effectiveEval.feedback && ( -
-
-
🤖 Co-Worker Feedback -
-
- {effectiveEval.feedback} -
-
- )} -
+ {isEvalExpanded && ( + <> +
+ {/* Rubric snippet */} + {effectiveEval.rubric && ( +
+
+
📝 Quality Rubric +
+
+ {effectiveEval.rubric} +
+
+ )} + + {/* Feedback snippet */} + {effectiveEval.feedback && ( +
+
+
🤖 Co-Worker Feedback +
+
+ {effectiveEval.feedback} +
+
+ )} +
- {/* History Timeline snippet */} - {effectiveEval.history && effectiveEval.history.length > 0 && ( -
-
-
🕒 Rework History Timeline -
-
- {effectiveEval.history.map((h, i) => ( -
-
- - {h.type === 'attempt' ? `Attempt ${h.round}` : h.name} - {h.score !== undefined && Score: {h.score}%} - - {h.reason || h.message || h.details} -
- - {h.timestamp ? new Date(h.timestamp * (h.timestamp < 2000000000 ? 1000 : 1)).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }) : 'Recent'} - -
- ))} -
-
+ {/* History Timeline snippet */} + {effectiveEval.history && effectiveEval.history.length > 0 && ( +
+
+
🕒 Rework History Timeline +
+
+ {effectiveEval.history.map((h, i) => ( +
+
+ + {h.type === 'attempt' ? `Attempt ${h.round}` : h.name} + {h.score !== undefined && Score: {h.score}%} + + {h.reason || h.message || h.details} +
+ + {h.timestamp ? new Date(h.timestamp * (h.timestamp < 2000000000 ? 1000 : 1)).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }) : 'Recent'} + +
+ ))} +
+
+ )} + )}