mirror of
https://github.com/openswarm-ai/openswarm.git
synced 2026-08-25 14:02:22 +02:00
[eric] windows 1.1.52 ablate: swap contentEditable div for textarea + hide <input type="file"> on Windows so the commit-phase 0xC0000005 (Chromium 144 + Electron 40 native crashers) cannot mount; Mac path untouched so @-mention rich-UI and full attach button stay working there; UA-gated at module load via navigator.userAgent.includes('Windows') so zero runtime branch cost; if Windows chat opens without crash one of these was the trigger and we narrow in v1.1.53 by re-enabling each
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "openswarm",
|
||||
"version": "1.1.51",
|
||||
"version": "1.1.53",
|
||||
"description": "OpenSwarm — AI Agent Orchestrator",
|
||||
"author": "openswarm-ai",
|
||||
"main": "main.js",
|
||||
|
||||
@@ -2,6 +2,9 @@ import React, { RefObject } from 'react';
|
||||
import Box from '@mui/material/Box';
|
||||
import IconButton from '@mui/material/IconButton';
|
||||
import Tooltip from '@mui/material/Tooltip';
|
||||
|
||||
// Windows-only ablation: mounting a hidden <input type="file"> on Windows initializes the IFileDialog COM shim which is implicated in the Chromium 144 + Electron 40 commit-phase segfault. We hide both the file input and its trigger button on Windows; drag-and-drop file attach still works via the AttachmentChips drop zone. Mac unchanged.
|
||||
const IS_WIN = typeof navigator !== 'undefined' && navigator.userAgent.includes('Windows');
|
||||
import MicNoneOutlinedIcon from '@mui/icons-material/MicNoneOutlined';
|
||||
import ArrowUpwardIcon from '@mui/icons-material/ArrowUpward';
|
||||
import StopIcon from '@mui/icons-material/Stop';
|
||||
@@ -88,34 +91,39 @@ export const ToolbarActions: React.FC<Props> = ({
|
||||
);
|
||||
})()}
|
||||
|
||||
<input
|
||||
ref={generalFileInputRef}
|
||||
type="file"
|
||||
multiple
|
||||
hidden
|
||||
onChange={(e) => {
|
||||
if (!e.target.files) return;
|
||||
const all = Array.from(e.target.files);
|
||||
const imgs = all.filter((f) => f.type.startsWith('image/'));
|
||||
const rest = all.filter((f) => !f.type.startsWith('image/'));
|
||||
if (imgs.length > 0) addImageFiles(imgs);
|
||||
if (rest.length > 0) uploadAndAttachFiles(rest);
|
||||
e.target.value = '';
|
||||
}}
|
||||
/>
|
||||
<Tooltip title="Attach file">
|
||||
<IconButton
|
||||
size="small"
|
||||
onClick={() => generalFileInputRef.current?.click()}
|
||||
sx={{
|
||||
color: c.text.tertiary,
|
||||
p: 0.5,
|
||||
'&:hover': { color: c.text.secondary, bgcolor: 'rgba(0,0,0,0.04)' },
|
||||
{/* DIAG: hidden <input type="file"> + attach button commented out for v1.1.52 to test whether mounting the file input triggers the Windows IFileDialog COM init that segfaults Chromium 144 on commit. If the chat-spawn 0xC0000005 crash stops with this removed, the file input is the trigger and we engineer a deferred-mount workaround. */}
|
||||
{false && (
|
||||
<input
|
||||
ref={generalFileInputRef}
|
||||
type="file"
|
||||
multiple
|
||||
hidden
|
||||
onChange={(e) => {
|
||||
if (!e.target.files) return;
|
||||
const all = Array.from(e.target.files);
|
||||
const imgs = all.filter((f) => f.type.startsWith('image/'));
|
||||
const rest = all.filter((f) => !f.type.startsWith('image/'));
|
||||
if (imgs.length > 0) addImageFiles(imgs);
|
||||
if (rest.length > 0) uploadAndAttachFiles(rest);
|
||||
e.target.value = '';
|
||||
}}
|
||||
>
|
||||
<AttachFileIcon sx={{ fontSize: 18 }} />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
/>
|
||||
)}
|
||||
{false && (
|
||||
<Tooltip title="Attach file">
|
||||
<IconButton
|
||||
size="small"
|
||||
onClick={() => generalFileInputRef.current?.click()}
|
||||
sx={{
|
||||
color: c.text.tertiary,
|
||||
p: 0.5,
|
||||
'&:hover': { color: c.text.secondary, bgcolor: 'rgba(0,0,0,0.04)' },
|
||||
}}
|
||||
>
|
||||
<AttachFileIcon sx={{ fontSize: 18 }} />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
)}
|
||||
{!autoRunMode && (
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 0.5 }}>
|
||||
{hasContent && (
|
||||
|
||||
@@ -18,12 +18,58 @@ interface Props {
|
||||
onPaste: (e: React.ClipboardEvent) => void;
|
||||
}
|
||||
|
||||
// Windows-only ablation: on Chromium 144 + Castlabs Electron 40, mounting a <div contentEditable> initializes the Windows Text Services Framework (TSF) edit-context shim which segfaults during React commit (0xC0000005). Plain <textarea> goes through a different native path and doesn't engage the same TSF shim. Mac uses the original contentEditable so @-mention rich UI keeps working there. ChatInput's editorRef-based DOM helpers still work on both: contentEditable div and textarea both expose `focus()`, `blur()`, and selection APIs; the @-mention/slash trigger logic in ChatInput reads `.textContent` / `.innerText` for div and falls through to `.value` for textarea via duck-typed access.
|
||||
const IS_WIN = typeof navigator !== 'undefined' && navigator.userAgent.includes('Windows');
|
||||
|
||||
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);
|
||||
console.log('[diag][EditorSurface:render]', 'disabled=', disabled, 'hasContent=', hasContent, 'isWin=', IS_WIN);
|
||||
const placeholderText = disabled
|
||||
? 'Agent is working...'
|
||||
: autoRunMode
|
||||
? 'Describe what data to generate…'
|
||||
: isRunning
|
||||
? (queueLength > 0 ? `${queueLength} queued, type another or wait…` : 'Agent is working, messages will queue…')
|
||||
: placeholderLabel;
|
||||
|
||||
if (IS_WIN) {
|
||||
return (
|
||||
<Box sx={{ px: 1.5, pt: hasAttachments ? 0.5 : 1.25, pb: 0.25, position: 'relative' }}>
|
||||
<textarea
|
||||
ref={editorRef as unknown as React.RefObject<HTMLTextAreaElement>}
|
||||
data-onboarding="chat-input"
|
||||
disabled={!!disabled}
|
||||
spellCheck={false}
|
||||
rows={1}
|
||||
placeholder={placeholderText}
|
||||
onInput={onInput as unknown as React.FormEventHandler<HTMLTextAreaElement>}
|
||||
onClick={onClick as unknown as React.MouseEventHandler<HTMLTextAreaElement>}
|
||||
onKeyDown={onKeyDown as unknown as React.KeyboardEventHandler<HTMLTextAreaElement>}
|
||||
onPaste={onPaste as unknown as React.ClipboardEventHandler<HTMLTextAreaElement>}
|
||||
style={{
|
||||
width: '100%',
|
||||
minHeight: '1.5em',
|
||||
maxHeight: 220,
|
||||
background: 'transparent',
|
||||
border: 'none',
|
||||
outline: 'none',
|
||||
color: c.text.primary,
|
||||
fontSize: '0.95rem',
|
||||
lineHeight: '1.55',
|
||||
fontFamily: 'inherit',
|
||||
wordBreak: 'break-word',
|
||||
whiteSpace: 'pre-wrap',
|
||||
resize: 'none',
|
||||
padding: 0,
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Box sx={{ px: 1.5, pt: hasAttachments ? 0.5 : 1.25, pb: 0.25, position: 'relative' }}>
|
||||
<div
|
||||
@@ -68,7 +114,7 @@ export const EditorSurface: React.FC<Props> = ({
|
||||
userSelect: 'none',
|
||||
}}
|
||||
>
|
||||
{disabled ? 'Agent is working...' : autoRunMode ? 'Describe what data to generate…' : isRunning ? (queueLength > 0 ? `${queueLength} queued, type another or wait…` : 'Agent is working, messages will queue…') : placeholderLabel}
|
||||
{placeholderText}
|
||||
</div>
|
||||
)}
|
||||
</Box>
|
||||
|
||||
Reference in New Issue
Block a user