From a792858793f1170c3c0a697071bd1b1f79d931db Mon Sep 17 00:00:00 2001 From: diegosouzapw Date: Tue, 7 Apr 2026 23:04:52 -0300 Subject: [PATCH 01/26] fix: add third-party app 400 error pattern to combo fallback (#1024) --- open-sse/services/combo.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/open-sse/services/combo.ts b/open-sse/services/combo.ts index 83d981d088..04c8771e86 100644 --- a/open-sse/services/combo.ts +++ b/open-sse/services/combo.ts @@ -29,6 +29,7 @@ const COMBO_BAD_REQUEST_FALLBACK_PATTERNS = [ /no such tool available/i, /unsupported content part type/i, /tool(?:_call|_use)? .* not (?:available|found)/i, + /third-party apps/i, ]; const MAX_COMBO_DEPTH = 3; From 6635540a6da79202039b2a5db36daf2a78a7dd1f Mon Sep 17 00:00:00 2001 From: diegosouzapw Date: Tue, 7 Apr 2026 23:04:52 -0300 Subject: [PATCH 02/26] fix: map max_output_tokens to max_tokens for strict openai-compatible providers (#994) --- open-sse/translator/helpers/openaiHelper.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/open-sse/translator/helpers/openaiHelper.ts b/open-sse/translator/helpers/openaiHelper.ts index f3ae1c1ee4..bbc4995c35 100644 --- a/open-sse/translator/helpers/openaiHelper.ts +++ b/open-sse/translator/helpers/openaiHelper.ts @@ -106,6 +106,14 @@ export function filterToOpenAIFormat(body) { delete body.metadata; delete body.anthropic_version; + // Map max_output_tokens (from Vercel AI SDK) to max_tokens logic + if (body.max_output_tokens !== undefined) { + if (body.max_tokens === undefined) { + body.max_tokens = body.max_output_tokens; + } + delete body.max_output_tokens; + } + // Normalize tools to OpenAI format (from Claude, Gemini, etc.) if (body.tools && Array.isArray(body.tools) && body.tools.length > 0) { body.tools = body.tools From ab2d174a0b7138ba7e838814f91d4d4208725a57 Mon Sep 17 00:00:00 2001 From: diegosouzapw Date: Tue, 7 Apr 2026 23:04:52 -0300 Subject: [PATCH 03/26] fix: properly parse inline_data and generic base64 sources for gemini pdf routing (#993) --- open-sse/translator/helpers/geminiHelper.ts | 36 +++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/open-sse/translator/helpers/geminiHelper.ts b/open-sse/translator/helpers/geminiHelper.ts index 312e90ae7c..01a9fc2392 100644 --- a/open-sse/translator/helpers/geminiHelper.ts +++ b/open-sse/translator/helpers/geminiHelper.ts @@ -76,6 +76,42 @@ export function convertOpenAIContentToParts(content) { if (item.type === "text") { parts.push({ text: item.text }); } else { + // 1. Handle Gemini native inline_data injected into OpenAI arrays (e.g. Cherry Studio) + const geminiInline = item.inline_data || item.inlineData; + if (geminiInline?.data) { + parts.push({ + inlineData: { + mimeType: geminiInline.mime_type || geminiInline.mimeType || "application/pdf", + data: geminiInline.data.replace(/^data:[a-zA-Z0-9/+-]+;base64,/, ""), + }, + }); + continue; + } + + // 2. Handle Claude-style source blocks commonly used by AI clients + if (item.source?.type === "base64" && item.source?.data) { + parts.push({ + inlineData: { + mimeType: item.source.media_type || "application/pdf", + data: item.source.data.replace(/^data:[a-zA-Z0-9/+-]+;base64,/, ""), + }, + }); + continue; + } + + // 3. Handle raw data strings (e.g. {"type": "file", "data": "JVBER...", "mime_type": "..."}) + if (typeof item.data === "string" && !item.data.startsWith("http")) { + const rawData = item.data.replace(/^data:[a-zA-Z0-9/+-]+;base64,/, ""); + parts.push({ + inlineData: { + mimeType: item.mime_type || item.media_type || "application/octet-stream", + data: rawData, + }, + }); + continue; + } + + // 4. Standard OpenAI Data URIs const fileData = item.image_url?.url || item.file_url?.url || item.file?.url || item.document?.url; if (typeof fileData === "string" && fileData.startsWith("data:")) { From c1f363fde20c8eb4f2e00800a9482d6ccb54926b Mon Sep 17 00:00:00 2001 From: diegosouzapw Date: Tue, 7 Apr 2026 23:28:50 -0300 Subject: [PATCH 04/26] fix(desktop-ui): improve macOS sidebar layout (PR #1001) --- src/app/globals.css | 8 ++ src/shared/components/Header.tsx | 13 ++- src/shared/components/Sidebar.tsx | 87 +++++++++++-------- .../components/layouts/DashboardLayout.tsx | 33 +++++-- test-cherry.js | 2 + test_gemini.mjs | 9 ++ 6 files changed, 110 insertions(+), 42 deletions(-) create mode 100644 test-cherry.js create mode 100644 test_gemini.mjs diff --git a/src/app/globals.css b/src/app/globals.css index a157baac9d..bb0df11691 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -13,6 +13,9 @@ /* OpenClaw × ClawHub Color Palette */ :root { + --desktop-safe-top: 0px; + --desktop-safe-bottom: 0px; + /* Primary - Coral Red (OpenClaw) */ --color-primary: #e54d5e; --color-primary-hover: #c93d4e; @@ -152,6 +155,11 @@ body { -moz-osx-font-smoothing: grayscale; } +body.electron-macos { + --desktop-safe-top: 30px; + --desktop-safe-bottom: 8px; +} + /* Selection — with fallback for browsers that don't support color-mix() */ ::selection { background-color: rgba(229, 77, 94, 0.22); diff --git a/src/shared/components/Header.tsx b/src/shared/components/Header.tsx index 8522d3fd76..fa7c09536a 100644 --- a/src/shared/components/Header.tsx +++ b/src/shared/components/Header.tsx @@ -18,6 +18,7 @@ import { OPENAI_COMPATIBLE_PREFIX, ANTHROPIC_COMPATIBLE_PREFIX, } from "@/shared/constants/providers"; +import { useIsElectron } from "@/shared/hooks/useElectron"; const isE2EMode = process.env.NEXT_PUBLIC_OMNIROUTE_E2E_MODE === "1"; @@ -122,8 +123,11 @@ function usePageInfo(pathname: string | null): { export default function Header({ onMenuClick, showMenuButton = true }) { const pathname = usePathname(); const router = useRouter(); + const isElectron = useIsElectron(); const t = useTranslations("header"); const { title, description, breadcrumbs } = usePageInfo(pathname); + const isMacElectron = + isElectron && typeof window !== "undefined" && window.electronAPI?.platform === "darwin"; const handleLogout = async () => { try { @@ -138,7 +142,14 @@ export default function Header({ onMenuClick, showMenuButton = true }) { }; return ( -
+
{/* Mobile menu button */}
{showMenuButton && ( diff --git a/src/shared/components/Sidebar.tsx b/src/shared/components/Sidebar.tsx index 47180f19ce..2a69041e72 100644 --- a/src/shared/components/Sidebar.tsx +++ b/src/shared/components/Sidebar.tsx @@ -24,10 +24,12 @@ export default function Sidebar({ onClose, collapsed = false, onToggleCollapse, + isMacElectron = false, }: { onClose?: any; collapsed?: boolean; onToggleCollapse?: any; + isMacElectron?: boolean; }) { const pathname = usePathname(); const t = useTranslations("sidebar"); @@ -192,9 +194,12 @@ export default function Sidebar({ <>