diff --git a/frontend/src/app/components/feedback/ErrorSlime.tsx b/frontend/src/app/components/feedback/ErrorSlime.tsx
index 36a92a40..979f99b3 100644
--- a/frontend/src/app/components/feedback/ErrorSlime.tsx
+++ b/frontend/src/app/components/feedback/ErrorSlime.tsx
@@ -1,7 +1,10 @@
import React from 'react';
/** Slime illustration with X eyes and red badge for errors/warnings. */
-export const ErrorSlime: React.FC<{ size?: number }> = ({ size = 22 }) => (
+export const ErrorSlime: React.FC<{ size?: number }> = ({ size = 22 }) => {
+ // eslint-disable-next-line no-console
+ console.log('[diag][ErrorSlime:render]', 'size=', size);
+ return (
-);
+ );
+};
export default ErrorSlime;
diff --git a/frontend/src/app/pages/AgentChat/ChatInput.tsx b/frontend/src/app/pages/AgentChat/ChatInput.tsx
index 0850956c..ad443703 100644
--- a/frontend/src/app/pages/AgentChat/ChatInput.tsx
+++ b/frontend/src/app/pages/AgentChat/ChatInput.tsx
@@ -43,6 +43,8 @@ interface Props {
}
const ChatInput = forwardRef(({ onSend, disabled, mode, onModeChange, model, onModelChange, provider, onProviderChange, isRunning, onStop, autoRunMode, contextEstimate, embedded, autoFocus, sessionId, queueLength = 0, thinkingLevel = 'auto', onThinkingLevelChange }, ref) => {
+ // eslint-disable-next-line no-console
+ console.log('[diag][ChatInput:render]', sessionId, 'mode=', mode, 'isRunning=', isRunning);
const c = useClaudeTokens();
const editorRef = useRef(null);
const containerRef = useRef(null);
diff --git a/frontend/src/app/pages/AgentChat/bubbles/CompactionMarker.tsx b/frontend/src/app/pages/AgentChat/bubbles/CompactionMarker.tsx
index d5907e05..303daa86 100644
--- a/frontend/src/app/pages/AgentChat/bubbles/CompactionMarker.tsx
+++ b/frontend/src/app/pages/AgentChat/bubbles/CompactionMarker.tsx
@@ -6,6 +6,8 @@ import { useClaudeTokens } from '@/shared/styles/ThemeContext';
/** Chip marking where auto-compaction collapsed older turns, so the transcript doesn't just appear to skip. */
const CompactionMarker: React.FC<{ collapsedCount: number }> = ({ collapsedCount }) => {
+ // eslint-disable-next-line no-console
+ console.log('[diag][CompactionMarker:render]', 'collapsed=', collapsedCount);
const c = useClaudeTokens();
const label = collapsedCount > 0
? `${collapsedCount} earlier turn${collapsedCount === 1 ? '' : 's'} summarized`
diff --git a/frontend/src/app/pages/AgentChat/bubbles/MessageBubble.tsx b/frontend/src/app/pages/AgentChat/bubbles/MessageBubble.tsx
index 8c79e7fd..f0f2ec45 100644
--- a/frontend/src/app/pages/AgentChat/bubbles/MessageBubble.tsx
+++ b/frontend/src/app/pages/AgentChat/bubbles/MessageBubble.tsx
@@ -844,6 +844,8 @@ interface Props {
}
const MessageBubble: React.FC = React.memo(({ message, editing = false, onSaveEdit, onCancelEdit, isStreaming, dynamicTurnLabel }) => {
+ // eslint-disable-next-line no-console
+ console.log('[diag][MessageBubble:render]', message && message.id, 'role=', message && message.role, 'streaming=', isStreaming);
const c = useClaudeTokens();
const dispatch = useAppDispatch();
const [editText, setEditText] = useState('');
diff --git a/frontend/src/app/pages/AgentChat/bubbles/StreamingBubble.tsx b/frontend/src/app/pages/AgentChat/bubbles/StreamingBubble.tsx
index f4b4c0c5..823ff30e 100644
--- a/frontend/src/app/pages/AgentChat/bubbles/StreamingBubble.tsx
+++ b/frontend/src/app/pages/AgentChat/bubbles/StreamingBubble.tsx
@@ -12,6 +12,8 @@ interface Props {
/** Leaf subscriber for one session's streaming entry; isolates re-renders so AgentChat doesn't churn per character. */
const StreamingBubble: React.FC = ({ sessionId, activeBranchId, turnLabel, onStreamGrew }) => {
+ // eslint-disable-next-line no-console
+ console.log('[diag][StreamingBubble:render]', sessionId, 'branch=', activeBranchId);
const streamingMessage = useStreamingMessage(sessionId);
const typedContent = streamingMessage?.content ?? '';
// RAF-coalesce so onStreamGrew fires once per frame regardless of token rate.
diff --git a/frontend/src/app/pages/AgentChat/shell/ApprovalBar.tsx b/frontend/src/app/pages/AgentChat/shell/ApprovalBar.tsx
index 484c3819..276f42a9 100644
--- a/frontend/src/app/pages/AgentChat/shell/ApprovalBar.tsx
+++ b/frontend/src/app/pages/AgentChat/shell/ApprovalBar.tsx
@@ -899,6 +899,8 @@ const GenericApprovalBar: React.FC = ({ request, onApprove, onDeny }) =>
};
const ApprovalBar: React.FC = (props) => {
+ // eslint-disable-next-line no-console
+ console.log('[diag][ApprovalBar:render]', props.request && props.request.tool_name);
if (props.request.tool_name === 'AskUserQuestion') {
return ;
}
diff --git a/frontend/src/app/pages/AgentChat/shell/ContextDrawer.tsx b/frontend/src/app/pages/AgentChat/shell/ContextDrawer.tsx
index a6eeda15..2c480238 100644
--- a/frontend/src/app/pages/AgentChat/shell/ContextDrawer.tsx
+++ b/frontend/src/app/pages/AgentChat/shell/ContextDrawer.tsx
@@ -9,6 +9,8 @@ import { useClaudeTokens } from '@/shared/styles/ThemeContext';
/** /context drawer: shows session MCPs, ctx%, cache hits, compaction. Opened via window CustomEvent from ChatInput's slash handler. */
export default function ContextDrawer() {
+ // eslint-disable-next-line no-console
+ console.log('[diag][ContextDrawer:render]');
const c = useClaudeTokens();
const [openFor, setOpenFor] = useState(null);
const session = useAppSelector((state) => (openFor ? state.agents.sessions[openFor] : undefined));
diff --git a/frontend/src/app/pages/AgentChat/shell/MessageActionBar.tsx b/frontend/src/app/pages/AgentChat/shell/MessageActionBar.tsx
index 0530c4a8..f3d3699f 100644
--- a/frontend/src/app/pages/AgentChat/shell/MessageActionBar.tsx
+++ b/frontend/src/app/pages/AgentChat/shell/MessageActionBar.tsx
@@ -44,6 +44,8 @@ const MessageActionBar: React.FC = ({
onBranch,
branchNav,
}) => {
+ // eslint-disable-next-line no-console
+ console.log('[diag][MessageActionBar:render]', 'role=', role);
const c = useClaudeTokens();
const [copied, setCopied] = useState(false);
diff --git a/frontend/src/app/pages/AgentChat/tool-bubbles/ToolCallBubble.tsx b/frontend/src/app/pages/AgentChat/tool-bubbles/ToolCallBubble.tsx
index 8c15077f..332d611b 100644
--- a/frontend/src/app/pages/AgentChat/tool-bubbles/ToolCallBubble.tsx
+++ b/frontend/src/app/pages/AgentChat/tool-bubbles/ToolCallBubble.tsx
@@ -47,6 +47,8 @@ interface ToolCallBubbleProps {
const ToolCallBubble: React.FC = React.memo(
({ call, result = null, isPending = false, isStreaming = false, mcpCompact = false, sessionId }) => {
+ // eslint-disable-next-line no-console
+ console.log('[diag][ToolCallBubble:render]', call && call.id, 'name=', call && call.name);
ensureToolCallKeyframes();
const c = useClaudeTokens();
diff --git a/frontend/src/app/pages/AgentChat/tool-bubbles/ToolGroupBubble.tsx b/frontend/src/app/pages/AgentChat/tool-bubbles/ToolGroupBubble.tsx
index 0c4de468..c1c49eb3 100644
--- a/frontend/src/app/pages/AgentChat/tool-bubbles/ToolGroupBubble.tsx
+++ b/frontend/src/app/pages/AgentChat/tool-bubbles/ToolGroupBubble.tsx
@@ -70,6 +70,8 @@ interface Props {
}
const ToolGroupBubble: React.FC = React.memo(({ group, isSessionRunning = false, meta, sessionId }) => {
+ // eslint-disable-next-line no-console
+ console.log('[diag][ToolGroupBubble:render]', group && group.id, 'mcp=', !!(group && group.mcpServer), 'items=', group && group.items && group.items.length);
const c = useClaudeTokens();
const isMcp = !!group.mcpServer;
const [expanded, setExpanded] = useState(isMcp);