diff --git a/frontend/src/app/pages/AgentChat/bubbles/MessageBubble.tsx b/frontend/src/app/pages/AgentChat/bubbles/MessageBubble.tsx
index 3ef9d940..082f8e7a 100644
--- a/frontend/src/app/pages/AgentChat/bubbles/MessageBubble.tsx
+++ b/frontend/src/app/pages/AgentChat/bubbles/MessageBubble.tsx
@@ -4,6 +4,7 @@ import Box from '@mui/material/Box';
import Typography from '@mui/material/Typography';
import IconButton from '@mui/material/IconButton';
import TextField from '@mui/material/TextField';
+import InputBase from '@mui/material/InputBase';
import Button from '@mui/material/Button';
import Chip from '@mui/material/Chip';
import Tooltip from '@mui/material/Tooltip';
@@ -16,6 +17,7 @@ import FolderOutlinedIcon from '@mui/icons-material/FolderOutlined';
import InsertDriveFileOutlinedIcon from '@mui/icons-material/InsertDriveFileOutlined';
import PsychologyOutlinedIcon from '@mui/icons-material/PsychologyOutlined';
import BuildOutlinedIcon from '@mui/icons-material/BuildOutlined';
+import LanguageIcon from '@mui/icons-material/Language';
import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
import WindowedMarkdown from './WindowedMarkdown';
@@ -354,16 +356,30 @@ function buildContextGroups(
const forcedTools = message.forced_tools;
if (forcedTools && forcedTools.length > 0) {
- groups.push({
- key: 'tools',
- icon: ,
- color: '#f59e0b',
- label: `${forcedTools.length} action${forcedTools.length > 1 ? 's' : ''} requested`,
- chips: forcedTools.map((t) => ({
- label: t,
- icon: ,
- })),
- });
+ // The web-search toggle forces WebSearch/WebFetch on every send; that's a MODE, not an
+ // attachment, so it reads as one quiet globe instead of an amber "2 actions requested" banner.
+ const visibleForced = forcedTools.filter((t) => t !== 'WebSearch' && t !== 'WebFetch');
+ if (visibleForced.length !== forcedTools.length) {
+ groups.push({
+ key: 'web',
+ icon: ,
+ color: '#8a8a94',
+ label: 'Web search',
+ chips: [],
+ });
+ }
+ if (visibleForced.length > 0) {
+ groups.push({
+ key: 'tools',
+ icon: ,
+ color: '#f59e0b',
+ label: `${visibleForced.length} action${visibleForced.length > 1 ? 's' : ''} requested`,
+ chips: visibleForced.map((t) => ({
+ label: t,
+ icon: ,
+ })),
+ });
+ }
}
return groups;
@@ -380,7 +396,8 @@ const AttachedContextSection: React.FC<{
if (groups.length === 0) return null;
return (
-
+ // Quiet metadata, not a banner: no divider, ghost text, tiny glyphs; detail stays one click away.
+
setExpanded(!expanded)}
sx={{
@@ -388,8 +405,9 @@ const AttachedContextSection: React.FC<{
alignItems: 'center',
gap: 0.5,
cursor: 'pointer',
- mb: 0.5,
- '&:hover': { opacity: 0.8 },
+ opacity: 0.75,
+ '&:hover': { opacity: 1 },
+ transition: 'opacity 120ms',
}}
>
{groups.map((g) => (
@@ -397,7 +415,7 @@ const AttachedContextSection: React.FC<{
{g.icon}
))}
-
+
{groups.map((g) => g.label).join(' ยท ')}
= React.memo(({ message, editing = false, o
>
{isUser ? (
editing ? (
-
-
+ setEditText(e.target.value)}
- variant="outlined"
- size="small"
autoFocus
onKeyDown={(e) => {
if (e.key === 'Enter' && !e.shiftKey) {
@@ -1088,35 +1106,36 @@ const MessageBubble: React.FC = React.memo(({ message, editing = false, o
if (e.key === 'Escape') handleCancelEdit();
}}
sx={{
- '& .MuiOutlinedInput-root': {
- color: c.text.primary,
- fontSize: '0.875rem',
- '& fieldset': { borderColor: c.border.strong },
- '&:hover fieldset': { borderColor: c.text.tertiary },
- '&.Mui-focused fieldset': { borderColor: c.accent.primary },
- },
+ color: c.text.primary,
+ fontSize: '0.875rem',
+ lineHeight: 1.55,
+ p: 0,
+ '& textarea': { p: 0 },
}}
/>
-
+