mirror of
https://github.com/openswarm-ai/openswarm.git
synced 2026-08-26 14:32:22 +02:00
[eric] windows 1.1.59: production webpack and framer-motion shim
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "openswarm",
|
||||
"version": "1.1.58",
|
||||
"version": "1.1.59",
|
||||
"description": "OpenSwarm — AI Agent Orchestrator",
|
||||
"author": "openswarm-ai",
|
||||
"main": "main.js",
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"version": "1.0.0",
|
||||
"description": "Open Swarm — Agent Orchestrator frontend built with React",
|
||||
"scripts": {
|
||||
"build": "webpack --mode=development",
|
||||
"build": "webpack --mode=production",
|
||||
"build:watch": "webpack --mode=development --watch",
|
||||
"dev": "webpack serve --mode=development",
|
||||
"clean": "rm -rf dist"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useMemo, useEffect, useState, useRef, Suspense, lazy } from 'react';
|
||||
import React, { useMemo, useEffect, useState, useRef, Suspense } from 'react';
|
||||
import { Provider } from 'react-redux';
|
||||
import { HashRouter, Routes, Route } from 'react-router-dom';
|
||||
import { ThemeProvider as MuiThemeProvider, createTheme, CssBaseline } from '@mui/material';
|
||||
@@ -21,58 +21,19 @@ import AppShell from './components/Layout/AppShell';
|
||||
import DashboardSelection from './pages/DashboardSelection/DashboardSelection';
|
||||
import ErrorBoundary from './components/feedback/ErrorBoundary';
|
||||
import { setPanelMode, disableOnboardingAfterCrash } from '@/shared/state/onboardingProgressSlice';
|
||||
// Wrap every lazy() so each chunk load (request, success, failure) emits a diag line. Chunk-split race against React commit is one of the candidate causes of the packaged-only segfault, so this surfaces if a chunk failed to load in the moment leading up to a crash.
|
||||
function diagLazy<T extends React.ComponentType<any>>(name: string, loader: () => Promise<{ default: T } | T>): React.LazyExoticComponent<T> {
|
||||
return lazy(() => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('[diag][lazy:requested]', name);
|
||||
return Promise.resolve()
|
||||
.then(loader)
|
||||
.then((mod: any) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('[diag][lazy:loaded]', name);
|
||||
return mod && 'default' in mod ? mod : { default: mod };
|
||||
})
|
||||
.catch((err) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error('[diag][lazy:failed]', name, err && err.message, err && err.stack);
|
||||
throw err;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const Skills = diagLazy('Skills', () => import('./pages/Skills/Skills'));
|
||||
const Tools = diagLazy('Tools', () => import('./pages/Tools/Tools'));
|
||||
const Modes = diagLazy('Modes', () => import('./pages/Modes/Modes'));
|
||||
const Views = diagLazy('Views', () => import('./pages/Views/Views'));
|
||||
const Customization = diagLazy('Customization', () => import('./pages/Customization/Customization'));
|
||||
const Analytics = diagLazy('Analytics', () => import('./pages/Analytics/Analytics'));
|
||||
const OnboardingRoot = diagLazy('OnboardingRoot', () =>
|
||||
const Skills = React.lazy(() => import('./pages/Skills/Skills'));
|
||||
const Tools = React.lazy(() => import('./pages/Tools/Tools'));
|
||||
const Modes = React.lazy(() => import('./pages/Modes/Modes'));
|
||||
const Views = React.lazy(() => import('./pages/Views/Views'));
|
||||
const Customization = React.lazy(() => import('./pages/Customization/Customization'));
|
||||
const Analytics = React.lazy(() => import('./pages/Analytics/Analytics'));
|
||||
const OnboardingRoot = React.lazy(() =>
|
||||
import('./components/Onboarding').then((m) => ({ default: m.OnboardingRoot })),
|
||||
);
|
||||
const SignInGate = diagLazy('SignInGate', () => import('./components/overlays/SignInGate'));
|
||||
const SignInGate = React.lazy(() => import('./components/overlays/SignInGate'));
|
||||
|
||||
if (typeof window !== 'undefined') {
|
||||
// Boot-time env snapshot targets candidates #2 (React prod mode) and #3 (tree-shaking removed side-effectful import): we log NODE_ENV, React version, presence of Emotion's cache stylesheet, and any pre-existing emotion/MUI globals so a post-crash trace shows whether the runtime env matched what the bundle expected.
|
||||
try {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('[diag][env] NODE_ENV=', (typeof process !== 'undefined' && process.env && process.env.NODE_ENV) || 'undefined',
|
||||
'React=', (React as any).version,
|
||||
'origin=', window.location.origin,
|
||||
'href=', window.location.href);
|
||||
setTimeout(() => {
|
||||
try {
|
||||
const emotionStyles = document.querySelectorAll('style[data-emotion]');
|
||||
const muiStyles = document.querySelectorAll('style[data-styled],style[data-mui]');
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('[diag][env] emotion_styles=', emotionStyles.length, 'mui_styles=', muiStyles.length, 'all_styles=', document.styleSheets.length);
|
||||
} catch (err) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error('[diag][env] style probe failed:', err && (err as Error).message);
|
||||
}
|
||||
}, 100);
|
||||
} catch { /* never let the diag block crash */ }
|
||||
|
||||
// Diagnostic global error capture. The packaged bundle has no source maps, so without these handlers the only thing that reaches main-process stderr is "Uncaught TypeError: ... (bundle.js:2)" with zero stack context. Forward error.stack and Redux action.type when available so we can pinpoint the offender across the chat-spawn / workflow rendering paths even in minified prod.
|
||||
window.addEventListener('error', (e) => {
|
||||
try {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Docked onboarding home: a small, quiet handle on the right edge that reopens the tour.
|
||||
|
||||
import React, { useState } from 'react';
|
||||
import { motion, AnimatePresence } from 'framer-motion';
|
||||
import { motion, AnimatePresence } from './_motionWin';
|
||||
import { Box, IconButton, Typography, CircularProgress } from '@mui/material';
|
||||
import CloseIcon from '@mui/icons-material/Close';
|
||||
import { useClaudeTokens } from '@/shared/styles/ThemeContext';
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { createPortal } from 'react-dom';
|
||||
import { motion, AnimatePresence } from 'framer-motion';
|
||||
import { motion, AnimatePresence } from './_motionWin';
|
||||
import { Box, Typography, IconButton, Button, ButtonBase } from '@mui/material';
|
||||
import RemoveIcon from '@mui/icons-material/Remove';
|
||||
import ArrowForwardIcon from '@mui/icons-material/ArrowForward';
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import React from 'react';
|
||||
import { Modal, Box, Typography, IconButton, Button } from '@mui/material';
|
||||
import { motion, AnimatePresence } from 'framer-motion';
|
||||
import { motion, AnimatePresence } from './_motionWin';
|
||||
import RadioButtonUncheckedIcon from '@mui/icons-material/RadioButtonUnchecked';
|
||||
import CheckCircleIcon from '@mui/icons-material/CheckCircle';
|
||||
import LockIcon from '@mui/icons-material/Lock';
|
||||
|
||||
@@ -24,10 +24,6 @@ import { report } from './telemetry';
|
||||
const PERSIST_DEBOUNCE_MS = 200;
|
||||
|
||||
const OnboardingRoot: React.FC = () => {
|
||||
// Windows nuclear ablation v1.1.58: the AgenticCursor motion.div gate in 1.1.57 was not sufficient — OnboardingPanel / OnboardingDirector / popups have additional Framer Motion + portal subtrees that segfault on commit. Return null on Windows so the entire onboarding UI is suppressed; user can still use the app normally without the guided tour. Mac unchanged.
|
||||
if (typeof navigator !== 'undefined' && navigator.userAgent.includes('Windows')) {
|
||||
return null;
|
||||
}
|
||||
const acRef = useRef<AgenticCursorHandle | null>(null);
|
||||
const dispatch = useAppDispatch();
|
||||
const store = useStore<RootState>() as Store<RootState>;
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
// Windows-aware shim for framer-motion. On Mac, re-exports the real library; on Windows, motion.* becomes a plain HTML element (no animation, no Framer runtime, no segfault). AnimatePresence passes children through. Onboarding files import from here so a single Mac/Windows fork lives in one place.
|
||||
|
||||
import React from 'react';
|
||||
import * as fm from 'framer-motion';
|
||||
|
||||
const IS_WIN = typeof navigator !== 'undefined' && navigator.userAgent.includes('Windows');
|
||||
|
||||
const FRAMER_ONLY_PROPS = new Set([
|
||||
'initial', 'animate', 'exit', 'transition', 'variants', 'layoutId', 'layout',
|
||||
'drag', 'dragConstraints', 'dragElastic', 'dragMomentum', 'dragControls',
|
||||
'dragDirectionLock', 'dragListener', 'dragTransition', 'dragSnapToOrigin', 'dragPropagation',
|
||||
'onDragStart', 'onDragEnd', 'onDrag', 'onDirectionLock',
|
||||
'onAnimationStart', 'onAnimationComplete', 'onUpdate',
|
||||
'onLayoutAnimationStart', 'onLayoutAnimationComplete',
|
||||
'whileHover', 'whileTap', 'whileFocus', 'whileDrag', 'whileInView',
|
||||
'viewport', 'transformTemplate', 'custom', 'inherit',
|
||||
]);
|
||||
|
||||
const stripFramerProps = (props: any) => {
|
||||
const out: any = {};
|
||||
for (const k in props) {
|
||||
if (!FRAMER_ONLY_PROPS.has(k)) out[k] = props[k];
|
||||
}
|
||||
return out;
|
||||
};
|
||||
|
||||
const motionShim: any = new Proxy({}, {
|
||||
get: (_target, tag: string) => {
|
||||
return React.forwardRef((props: any, ref: any) =>
|
||||
React.createElement(tag, { ...stripFramerProps(props), ref })
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
export const motion: typeof fm.motion = IS_WIN ? motionShim : fm.motion;
|
||||
export const AnimatePresence: typeof fm.AnimatePresence = IS_WIN
|
||||
? (({ children }: any) => children) as any
|
||||
: fm.AnimatePresence;
|
||||
|
||||
const animationControlsStub = {
|
||||
start: () => Promise.resolve(),
|
||||
stop: () => {},
|
||||
set: () => {},
|
||||
mount: () => () => {},
|
||||
};
|
||||
export const useAnimationControls: typeof fm.useAnimationControls = IS_WIN
|
||||
? (() => animationControlsStub as any) as any
|
||||
: fm.useAnimationControls;
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { useLayoutEffect, useRef, useState } from 'react';
|
||||
import { Box, Typography, ButtonBase } from '@mui/material';
|
||||
import { motion } from 'framer-motion';
|
||||
import { motion } from '../_motionWin';
|
||||
import { useClaudeTokens } from '@/shared/styles/ThemeContext';
|
||||
import { useCursorPosition } from './cursorStore';
|
||||
import type { ACMultiChoiceOption } from '../steps/types';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { useEffect, useLayoutEffect, useRef, useState } from 'react';
|
||||
import { Box, Typography } from '@mui/material';
|
||||
import { motion } from 'framer-motion';
|
||||
import { motion } from '../_motionWin';
|
||||
import { useClaudeTokens } from '@/shared/styles/ThemeContext';
|
||||
import { useCursorPosition } from './cursorStore';
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import React, {
|
||||
useState,
|
||||
} from 'react';
|
||||
import { createPortal } from 'react-dom';
|
||||
import { motion, useAnimationControls, AnimatePresence } from 'framer-motion';
|
||||
import { motion, useAnimationControls, AnimatePresence } from '../_motionWin';
|
||||
import { useClaudeTokens } from '@/shared/styles/ThemeContext';
|
||||
import { cursorStore } from './cursorStore';
|
||||
import { resolveSelector } from '../selectors';
|
||||
|
||||
@@ -2,8 +2,6 @@ import React from 'react';
|
||||
|
||||
/** Slime illustration with X eyes and red badge for errors/warnings. */
|
||||
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
|
||||
|
||||
@@ -159,8 +159,6 @@ interface AgentChatProps {
|
||||
}
|
||||
|
||||
const AgentChat: React.FC<AgentChatProps> = ({ sessionId: sessionIdProp, onClose, embedded, autoFocus, isGlowing, onDismissGlow, initialContextPaths, onBranch }) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('[diag][AgentChat] render', { sessionIdProp, embedded });
|
||||
const c = useClaudeTokens();
|
||||
const STATUS_STYLES: Record<string, { color: string; bg: string }> = {
|
||||
running: { color: c.status.success, bg: c.status.successBg },
|
||||
@@ -836,9 +834,6 @@ const AgentChat: React.FC<AgentChatProps> = ({ sessionId: sessionIdProp, onClose
|
||||
const isActive = session.status === 'running' || session.status === 'waiting_approval' || session.status === 'draft';
|
||||
const statusStyle = STATUS_STYLES[session.status] || { color: c.text.tertiary, bg: c.bg.secondary };
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('[diag][AgentChat:before-jsx]', id, 'status=', session.status, 'isActive=', isActive);
|
||||
|
||||
return (
|
||||
<Box sx={{ display: 'flex', height: '100%' }}>
|
||||
<ContextDrawer />
|
||||
|
||||
@@ -43,8 +43,6 @@ 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);
|
||||
|
||||
@@ -44,12 +44,6 @@ interface Props {
|
||||
}
|
||||
|
||||
export const ModelPickerMenu: React.FC<Props> = (props) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('[diag][ModelPickerMenu:render]', 'model=', props.model, 'open=', !!props.modelAnchor);
|
||||
React.useEffect(() => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('[diag][ModelPickerMenu:committed]');
|
||||
});
|
||||
const {
|
||||
c, menuPaperProps, modelAnchor, setModelAnchor, model, onModelChange, onProviderChange,
|
||||
modelSearchRef, modelSearch, setModelSearch, pushRecentModel, pushRecentSearch,
|
||||
|
||||
@@ -51,12 +51,6 @@ interface Props {
|
||||
}
|
||||
|
||||
export const ChatInputToolbar: React.FC<Props> = (p) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('[diag][ChatInputToolbar:render]', p.sessionId);
|
||||
React.useEffect(() => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('[diag][ChatInputToolbar:committed]');
|
||||
});
|
||||
const {
|
||||
c, modeConf, modesArr, mode, onModeChange, iconMap,
|
||||
modeAnchor, setModeAnchor, modelAnchor, setModelAnchor, thinkingAnchor, setThinkingAnchor,
|
||||
|
||||
@@ -4,8 +4,6 @@ import Tooltip from '@mui/material/Tooltip';
|
||||
import { formatTokenCount } from '../helpers';
|
||||
|
||||
export const ContextRing: React.FC<{ used: number; limit: number; accentColor: string; trackColor: string }> = ({ used, limit, accentColor, trackColor }) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('[diag][ContextRing:render]', 'used=', used, 'limit=', limit);
|
||||
if (used === 0) return null;
|
||||
const pct = Math.min((used / limit) * 100, 100);
|
||||
const size = 20;
|
||||
|
||||
@@ -28,12 +28,6 @@ interface Props {
|
||||
export const ModeControl: React.FC<Props> = ({
|
||||
c, menuPaperProps, modeConf, modesArr, mode, onModeChange, iconMap, modeAnchor, setModeAnchor, setModelAnchor, allModelFlat, model,
|
||||
}) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('[diag][ModeControl:render]', 'mode=', mode);
|
||||
React.useEffect(() => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('[diag][ModeControl:committed]');
|
||||
});
|
||||
return (
|
||||
<>
|
||||
<Box
|
||||
|
||||
@@ -23,12 +23,6 @@ interface Props {
|
||||
export const ThinkingLevelControl: React.FC<Props> = ({
|
||||
c, model, allModelFlat, thinkingLevel, onThinkingLevelChange, thinkingAnchor, setThinkingAnchor, menuPaperProps,
|
||||
}) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('[diag][ThinkingLevelControl:render]', 'model=', model, 'level=', thinkingLevel);
|
||||
React.useEffect(() => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('[diag][ThinkingLevelControl:committed]');
|
||||
});
|
||||
const currentModel = allModelFlat.find((m: any) => m.value === model) as any;
|
||||
if (!currentModel?.reasoning || !onThinkingLevelChange) return null;
|
||||
const levels: Array<{ value: ThinkingLevel; label: string; desc: string }> = [
|
||||
|
||||
@@ -33,12 +33,6 @@ export const ToolbarActions: React.FC<Props> = ({
|
||||
c, elementSelection, autoRunMode, ownerId, sessionId, generalFileInputRef,
|
||||
addImageFiles, uploadAndAttachFiles, hasContent, disabled, isRunning, onStop, handleSend,
|
||||
}) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('[diag][ToolbarActions:render]', sessionId, 'isRunning=', isRunning);
|
||||
React.useEffect(() => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('[diag][ToolbarActions:committed]');
|
||||
});
|
||||
return (
|
||||
<>
|
||||
{elementSelection && !autoRunMode && (() => {
|
||||
|
||||
@@ -43,8 +43,6 @@ export const AttachmentChips: React.FC<Props> = ({
|
||||
forcedTools, setForcedTools,
|
||||
selectedElements, elementSelection, ownerId,
|
||||
}) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('[diag][AttachmentChips:render]', 'images=', images.length, 'paths=', contextPaths.length, 'tools=', forcedTools.length);
|
||||
return (
|
||||
<>
|
||||
{images.length > 0 && (
|
||||
|
||||
@@ -25,8 +25,6 @@ export const ChatInputOverlays: React.FC<Props> = ({
|
||||
c, lightboxSrc, setLightboxSrc, oversizeQueue, summarizingPath, summarizeOversize,
|
||||
detachOversize, currentModelCtx, summarizeError, setSummarizeError,
|
||||
}) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('[diag][ChatInputOverlays:render]', 'lightbox=', !!lightboxSrc, 'oversize=', oversizeQueue && oversizeQueue.length);
|
||||
return (
|
||||
<>
|
||||
<Modal
|
||||
|
||||
@@ -98,8 +98,6 @@ interface Props {
|
||||
}
|
||||
|
||||
export const ChatInputView: React.FC<Props> = (p) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('[diag][ChatInputView:render]', p.sessionId);
|
||||
const { c } = p;
|
||||
return (
|
||||
<Box
|
||||
|
||||
@@ -25,8 +25,6 @@ export const EditorSurface: React.FC<Props> = ({
|
||||
c, editorRef, disabled, hasContent, hasAttachments, autoRunMode, isRunning, queueLength,
|
||||
placeholderLabel, onInput, onClick, onKeyDown, onPaste,
|
||||
}) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('[diag][EditorSurface:render]', 'disabled=', disabled, 'hasContent=', hasContent, 'isWin=', IS_WIN);
|
||||
const placeholderText = disabled
|
||||
? 'Agent is working...'
|
||||
: autoRunMode
|
||||
|
||||
@@ -16,8 +16,6 @@ interface Props {
|
||||
}
|
||||
|
||||
export const SendBlockBanner: React.FC<Props> = ({ sendBlock, c, sessionId, setSendBlock, setContextPaths, setModelAnchor }) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('[diag][SendBlockBanner:render]', sessionId);
|
||||
const fmt = (n: number) => n >= 1000 ? `${(n / 1000).toFixed(1)}K` : String(n);
|
||||
const over = sendBlock.estimate - sendBlock.window;
|
||||
return (
|
||||
|
||||
@@ -6,8 +6,6 @@ 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,8 +844,6 @@ 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,8 +12,6 @@ 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,8 +899,6 @@ 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,8 +9,6 @@ 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,8 +44,6 @@ 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,8 +47,6 @@ 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,8 +70,6 @@ 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);
|
||||
|
||||
@@ -75,8 +75,6 @@ const HANDLE_DEFS: { dir: ResizeDir; sx: Record<string, any> }[] = [
|
||||
|
||||
// On Windows, force iframe fallback path: the <webview> tag mount segfaults the renderer during commit on Chromium 144 + this Electron 40 CastLabs build. iframe renders blank for sites with X-Frame-Options but does not crash. Mac keeps webview (full browser).
|
||||
const isElectron = navigator.userAgent.includes('Electron') && !navigator.userAgent.includes('Windows');
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('[diag][BrowserCard] isElectron=', isElectron, 'ua=', navigator.userAgent, 'hasOpenswarm=', !!(window as any).openswarm);
|
||||
|
||||
const chromeUserAgent = navigator.userAgent
|
||||
.replace(/\s*Electron\/\S+/, '')
|
||||
@@ -127,8 +125,6 @@ const BrowserCard: React.FC<Props> = ({
|
||||
isSelected = false, isHighlighted = false, multiDragDelta, onCardSelect, onDragStart, onDragMove, onDragEnd,
|
||||
cardZOrder = 0, onDoubleClick, onBringToFront,
|
||||
}) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('[diag][BrowserCard:render]', browserId, 'tabs=', tabs && tabs.length);
|
||||
const c = useClaudeTokens();
|
||||
const dispatch = useAppDispatch();
|
||||
const scrollOverlayRef = useOverlayScrollPassthrough(isSelected);
|
||||
@@ -1123,34 +1119,11 @@ const BrowserCard: React.FC<Props> = ({
|
||||
style={{ width: '100%', height: '100%', border: 'none' }}
|
||||
title="Browser"
|
||||
referrerPolicy="no-referrer-when-downgrade"
|
||||
onLoad={() => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('[diag][iframe:onLoad]', activeUrl);
|
||||
}}
|
||||
onError={(e) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error('[diag][iframe:onError]', activeUrl, (e as any)?.message || e);
|
||||
}}
|
||||
/>
|
||||
<Box
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bgcolor: `${c.status.warningBg}`,
|
||||
borderTop: `1px solid ${c.status.warning}`,
|
||||
px: 1.5,
|
||||
py: 0.5,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: 0.5,
|
||||
}}
|
||||
>
|
||||
<Typography sx={{ fontSize: '0.68rem', color: c.status.warning }}>
|
||||
iframe mode: some sites may not load. Use the Electron build for full browser support.
|
||||
</Typography>
|
||||
</Box>
|
||||
</Box>
|
||||
)}
|
||||
|
||||
|
||||
@@ -97,8 +97,6 @@ const WorkflowCard: React.FC<Props> = ({
|
||||
isSelected = false, isHighlighted = false, multiDragDelta,
|
||||
onCardSelect, onDragStart, onDragMove, onDragEnd, onDoubleClick, onBringToFront,
|
||||
}) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('[diag][WorkflowCard:render]', workflowId);
|
||||
const c = useClaudeTokens();
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
|
||||
@@ -291,19 +291,13 @@ export const fetchSession = createAsyncThunk(
|
||||
export const launchAndSendFirstMessage = createAsyncThunk(
|
||||
'agents/launchAndSendFirstMessage',
|
||||
async ({ draftId, config, prompt, mode, model, provider, images, contextPaths, forcedTools, attachedSkills, selectedBrowserIds }: LaunchAndSendPayload) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('[diag][thunk] launchAndSendFirstMessage START draft=', draftId, 'mode=', mode, 'model=', model, 'provider=', provider);
|
||||
const launchRes = await fetch(`${AGENTS_API}/launch`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(config),
|
||||
});
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('[diag][thunk] launch fetch ok=', launchRes.ok, 'status=', launchRes.status);
|
||||
const launchData = await launchRes.json();
|
||||
const session = launchData.session as AgentSession;
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('[diag][thunk] launch parsed, sessionId=', session && session.id);
|
||||
|
||||
await fetch(`${AGENTS_API}/sessions/${session.id}/message`, {
|
||||
method: 'POST',
|
||||
@@ -476,15 +470,9 @@ export const searchHistory = createAsyncThunk(
|
||||
export const resumeSession = createAsyncThunk(
|
||||
'agents/resumeSession',
|
||||
async ({ sessionId }: { sessionId: string }) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('[diag][thunk] resumeSession START', sessionId);
|
||||
try {
|
||||
const res = await fetch(`${AGENTS_API}/sessions/${sessionId}/resume`, { method: 'POST' });
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('[diag][thunk] resumeSession fetch ok=', res.ok, 'status=', res.status);
|
||||
const data = await res.json();
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('[diag][thunk] resumeSession parsed, keys=', Object.keys(data || {}).join(','));
|
||||
return data.session as AgentSession;
|
||||
} catch (e: any) {
|
||||
// eslint-disable-next-line no-console
|
||||
|
||||
@@ -115,7 +115,7 @@ const initialState: SettingsState = {
|
||||
theme: 'dark',
|
||||
new_agent_shortcut: 'Meta+l',
|
||||
anthropic_api_key: null,
|
||||
browser_homepage: 'https://www.google.com',
|
||||
browser_homepage: 'https://duckduckgo.com',
|
||||
auto_select_mode_on_new_agent: false,
|
||||
expand_new_chats_in_dashboard: false,
|
||||
auto_reveal_sub_agents: true,
|
||||
|
||||
@@ -192,8 +192,6 @@ class WebSocketManager {
|
||||
const token = _getAuthTokenSafe();
|
||||
const sep = this.url.includes('?') ? '&' : '?';
|
||||
const urlWithToken = token ? `${this.url}${sep}token=${encodeURIComponent(token)}` : this.url;
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('[diag][ws] connect', this.url, 'sessionId=', this.sessionId, 'hasToken=', !!token);
|
||||
this.ws = new WebSocket(urlWithToken);
|
||||
|
||||
this.ws.onopen = () => {
|
||||
|
||||
Reference in New Issue
Block a user