[eric] diag: webpack --mode=development for packaged frontend + render logs on every AgentChat child (ContextDrawer / MessageBubble / StreamingBubble / CompactionMarker / ToolCallBubble / ToolGroupBubble / ApprovalBar / ChatInput / MessageActionBar / ErrorSlime) so the next 0xC0000005 crash trace shows the exact last component that committed before the segfault since http origin already disproved file://; retag v1.1.44

This commit is contained in:
Eric
2026-05-25 19:20:16 -07:00
parent 0c2cf3fc20
commit 1ec3d473f3
10 changed files with 24 additions and 2 deletions
@@ -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 (
<svg width={size} height={size} viewBox="0 0 28 28" fill="none" style={{ flexShrink: 0 }}>
<path
d="M4 20 Q4 7 14 7 Q24 7 24 20 Q22 22 19 21.5 Q16 23 14 22 Q12 23 9 21.5 Q6 22 4 20Z"
@@ -16,6 +19,7 @@ export const ErrorSlime: React.FC<{ size?: number }> = ({ size = 22 }) => (
<circle cx="22" cy="5" r="4" fill="#ef4444" stroke="rgba(0,0,0,0.15)" strokeWidth="0.5" />
<text x="22" y="6.8" textAnchor="middle" fontSize="5.5" fill="white" fontWeight="bold" fontFamily="sans-serif">!</text>
</svg>
);
);
};
export default ErrorSlime;
@@ -43,6 +43,8 @@ interface Props {
}
const ChatInput = forwardRef<ChatInputHandle, Props>(({ 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<HTMLDivElement>(null);
const containerRef = useRef<HTMLDivElement>(null);
@@ -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`
@@ -844,6 +844,8 @@ interface Props {
}
const MessageBubble: React.FC<Props> = 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('');
@@ -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<Props> = ({ 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.
@@ -899,6 +899,8 @@ const GenericApprovalBar: React.FC<Props> = ({ request, onApprove, onDeny }) =>
};
const ApprovalBar: React.FC<Props> = (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 <QuestionForm request={props.request} onApprove={props.onApprove} onDeny={props.onDeny} />;
}
@@ -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<string | null>(null);
const session = useAppSelector((state) => (openFor ? state.agents.sessions[openFor] : undefined));
@@ -44,6 +44,8 @@ const MessageActionBar: React.FC<Props> = ({
onBranch,
branchNav,
}) => {
// eslint-disable-next-line no-console
console.log('[diag][MessageActionBar:render]', 'role=', role);
const c = useClaudeTokens();
const [copied, setCopied] = useState(false);
@@ -47,6 +47,8 @@ interface ToolCallBubbleProps {
const ToolCallBubble: React.FC<ToolCallBubbleProps> = 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();
@@ -70,6 +70,8 @@ interface Props {
}
const ToolGroupBubble: React.FC<Props> = 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);