diff --git a/electron/main.js b/electron/main.js index 06f56b66..5a83afaf 100644 --- a/electron/main.js +++ b/electron/main.js @@ -1103,6 +1103,26 @@ app.whenReady().then(async () => { return allowed.includes(permission); }); + // Strip X-Frame-Options and CSP frame-ancestors directives on iframe subframe loads so the Windows BrowserCard iframe fallback (used because tag commit segfaults on Chromium 144 + this Electron 40 CastLabs build) can render sites that normally refuse to be embedded. Scoped to types:['sub_frame'] so OAuth popups, the main app frame, deep-link redirects, and DRM license fetches keep their security headers intact. urls filter limits to http/https so file:// loads of the bundled frontend are untouched. + session.defaultSession.webRequest.onHeadersReceived( + { urls: ['http://*/*', 'https://*/*'], types: ['sub_frame'] }, + (details, callback) => { + const headers = { ...(details.responseHeaders || {}) }; + for (const k of Object.keys(headers)) { + const lk = k.toLowerCase(); + if (lk === 'x-frame-options') { + delete headers[k]; + } else if (lk === 'content-security-policy' || lk === 'content-security-policy-report-only') { + const cleaned = (headers[k] || []) + .map((v) => v.split(';').filter((d) => !/^\s*frame-ancestors\b/i.test(d)).join(';').trim()) + .filter(Boolean); + if (cleaned.length) headers[k] = cleaned; else delete headers[k]; + } + } + callback({ responseHeaders: headers }); + }, + ); + // Read-only logging for DRM license requests — no modifying interceptors // so the network stack can set Content-Type and other headers normally. session.defaultSession.webRequest.onSendHeaders( diff --git a/electron/package.json b/electron/package.json index 01bee89b..4bfdad82 100644 --- a/electron/package.json +++ b/electron/package.json @@ -1,6 +1,6 @@ { "name": "openswarm", - "version": "1.1.54", + "version": "1.1.55", "description": "OpenSwarm — AI Agent Orchestrator", "author": "openswarm-ai", "main": "main.js", diff --git a/frontend/src/app/components/Onboarding/OnboardingPanel.tsx b/frontend/src/app/components/Onboarding/OnboardingPanel.tsx index 0b2f857d..4c4daff3 100644 --- a/frontend/src/app/components/Onboarding/OnboardingPanel.tsx +++ b/frontend/src/app/components/Onboarding/OnboardingPanel.tsx @@ -447,7 +447,7 @@ const StepCardBody: React.FC = ({ = ({ (({ onSend, disabled, mode, useImperativeHandle(ref, () => ({ getConfig: () => { const editor = editorRef.current; - const prompt = editor ? serializeEditorContent(editor, attachedSkillsRef.current).trim() : ''; + const prompt = editor + ? (editor.tagName === 'TEXTAREA' + ? (editor as unknown as HTMLTextAreaElement).value.trim() + : serializeEditorContent(editor, attachedSkillsRef.current).trim()) + : ''; return { prompt, contextPaths, forcedTools }; }, setContent: (prompt: string, newContextPaths?: ContextPath[], newForcedTools?: ForcedToolGroup[]) => { const editor = editorRef.current; if (editor) { - editor.textContent = prompt; + if (editor.tagName === 'TEXTAREA') (editor as unknown as HTMLTextAreaElement).value = prompt; else editor.textContent = prompt; setHasContent(!!prompt); } if (newContextPaths) setContextPaths(newContextPaths); @@ -124,7 +128,9 @@ const ChatInput = forwardRef(({ onSend, disabled, mode, if (!editor || disabled) return; if (summarizingPath) return; if (oversizeQueue.length > 0) return; - const serialized = serializeEditorContent(editor, attachedSkillsRef.current); + const serialized = editor.tagName === 'TEXTAREA' + ? (editor as unknown as HTMLTextAreaElement).value + : serializeEditorContent(editor, attachedSkillsRef.current); let trimmed = serialized.trim(); if (!trimmed) return; @@ -144,7 +150,7 @@ const ChatInput = forwardRef(({ onSend, disabled, mode, const cmd = trimmed.split(/\s+/)[0].toLowerCase(); const handled = await handleSlashCommand(cmd, sessionId); if (handled) { - editor.innerHTML = ''; + if (editor.tagName === 'TEXTAREA') (editor as unknown as HTMLTextAreaElement).value = ''; else editor.innerHTML = ''; deleteDraft(ownerId); setHasContent(false); return; diff --git a/frontend/src/app/pages/AgentChat/ChatInput/hooks/useEditorHandlers.ts b/frontend/src/app/pages/AgentChat/ChatInput/hooks/useEditorHandlers.ts index 37035dd9..d4e233f0 100644 --- a/frontend/src/app/pages/AgentChat/ChatInput/hooks/useEditorHandlers.ts +++ b/frontend/src/app/pages/AgentChat/ChatInput/hooks/useEditorHandlers.ts @@ -18,6 +18,26 @@ import { ForcedToolGroup } from '../types'; type Skill = { id: string; name: string; content: string }; +// Editor element type abstraction. On Windows we render a