From 56caabebbcf1ad9124c096195cd8afe55d0e1fda Mon Sep 17 00:00:00 2001 From: eric Date: Sun, 31 May 2026 18:40:33 -0700 Subject: [PATCH] [eric] fix: popup uses full width and matches app surface, error toast no longer red wall, summarize chunks small enough for dense pdf tokenization --- backend/apps/settings/settings.py | 14 ++--- .../ChatInput/view/ChatInputOverlays.tsx | 54 ++++++++++++++----- 2 files changed, 48 insertions(+), 20 deletions(-) diff --git a/backend/apps/settings/settings.py b/backend/apps/settings/settings.py index 34d1e9d1..acaac7b6 100644 --- a/backend/apps/settings/settings.py +++ b/backend/apps/settings/settings.py @@ -492,12 +492,14 @@ async def summarize_file(req: _SummarizeRequest): ) # Source can be bigger than the aux model's window (Haiku 4.5 is 200K). - # Chunk by characters, summarize each, then merge. Picked 480K chars - # (~120K tokens) so a Haiku-tier aux still has ~80K room for system + - # output + safety margin; bigger-window models would just see fewer - # chunks. Char-level cut intentionally; we re-summarize so a mid-sentence - # split is fine. - CHUNK_CHARS = 480_000 + # Chunk by characters, summarize each, then merge. PDFs and other + # binary-ish text tokenize WAY denser than the 4-chars-per-token rule + # of thumb implies; a 480K-char PDF blob was hitting 210K tokens and + # busting Haiku's 200K window. 200K chars / chunk caps the worst case + # at ~100K tokens even for binary garbage, leaving ~100K for system + + # output. Char-level cut intentionally; re-summarization tolerates a + # mid-sentence split. + CHUNK_CHARS = 200_000 is_chunked = len(raw) > CHUNK_CHARS async def _summarize_block(text: str, target_tokens: int, label: str) -> str: diff --git a/frontend/src/app/pages/AgentChat/ChatInput/view/ChatInputOverlays.tsx b/frontend/src/app/pages/AgentChat/ChatInput/view/ChatInputOverlays.tsx index 7a1b3f22..b7e22e08 100644 --- a/frontend/src/app/pages/AgentChat/ChatInput/view/ChatInputOverlays.tsx +++ b/frontend/src/app/pages/AgentChat/ChatInput/view/ChatInputOverlays.tsx @@ -3,10 +3,8 @@ import Box from '@mui/material/Box'; import IconButton from '@mui/material/IconButton'; import Modal from '@mui/material/Modal'; import Snackbar from '@mui/material/Snackbar'; -import Alert from '@mui/material/Alert'; import CloseIcon from '@mui/icons-material/Close'; import { ClaudeTokens } from '@/shared/styles/claudeTokens'; -import { formatTokenCount } from '../helpers'; interface Props { c: ClaudeTokens; @@ -72,19 +70,24 @@ export const ChatInputOverlays: React.FC = ({ 0} anchorOrigin={{ vertical: 'bottom', horizontal: 'center' }} - sx={{ mb: 10 }} + sx={{ mb: 10, '& .MuiSnackbarContent-root': { p: 0, minWidth: 0, bgcolor: 'transparent', boxShadow: 'none' } }} > {oversizeQueue[0] ? ( - - This file is too big to fit. Want me to shrink it down to a summary, or just remove it? + + This file is too big to send. Shrink it down to a summary, or remove it? ) : null} @@ -95,7 +98,8 @@ export const ChatInputOverlays: React.FC = ({ sx={{ bgcolor: c.accent.primary, color: '#fff', border: 'none', borderRadius: '6px', - px: 1.5, py: 0.6, fontSize: '0.8rem', fontWeight: 500, cursor: 'pointer', + px: 1.5, py: 0.7, fontSize: '0.82rem', fontWeight: 500, cursor: 'pointer', + whiteSpace: 'nowrap', '&:hover': { bgcolor: c.accent.hover }, '&:disabled': { opacity: 0.6, cursor: 'wait' }, }} @@ -108,7 +112,8 @@ export const ChatInputOverlays: React.FC = ({ sx={{ bgcolor: 'transparent', color: c.text.secondary, border: `1px solid ${c.border.medium}`, borderRadius: '6px', - px: 1.5, py: 0.6, fontSize: '0.8rem', cursor: 'pointer', + px: 1.5, py: 0.7, fontSize: '0.82rem', cursor: 'pointer', + whiteSpace: 'nowrap', '&:hover': { bgcolor: c.bg.secondary, color: c.text.primary }, }} > @@ -123,11 +128,32 @@ export const ChatInputOverlays: React.FC = ({ autoHideDuration={6000} anchorOrigin={{ vertical: 'bottom', horizontal: 'center' }} onClose={() => setSummarizeError(null)} - sx={{ mb: 18 }} + sx={{ mb: 18, '& .MuiSnackbarContent-root': { p: 0, minWidth: 0, bgcolor: 'transparent', boxShadow: 'none' } }} > - setSummarizeError(null)} sx={{ fontSize: '0.78rem', maxWidth: 520 }}> - {summarizeError} - + + + {summarizeError} + + setSummarizeError(null)} + size="small" + sx={{ color: c.text.secondary, flexShrink: 0, '&:hover': { color: c.text.primary } }} + > + + + );