[eric] windows 1.1.59: production webpack and framer-motion shim

This commit is contained in:
Eric
2026-05-26 00:29:17 -07:00
parent 7407e6cb37
commit bb2de72f6f
38 changed files with 66 additions and 171 deletions
+1 -1
View File
@@ -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",
+1 -1
View File
@@ -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"
+9 -48
View File
@@ -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();
-12
View File
@@ -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
+1 -1
View File
@@ -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 = () => {