From 562ca6c1f15fb3abb9868b3b20ed05f5b228f25b Mon Sep 17 00:00:00 2001 From: miao <1468212639@qq.com> Date: Tue, 7 Apr 2026 13:58:38 +0800 Subject: [PATCH] fix(tools): fix OpenClaw connection test and multimodal format compatibility - Use safe .get() for server URL to avoid KeyError - Support both api_key and token in connection test auth - Add OpenAI/Volcano image format (image_url) support - Add aiohttp import in _test_openclaw_connection --- api/app/core/tools/custom/base.py | 10 ++++++++-- api/app/services/draft_run_service.py | 1 - api/app/services/tool_service.py | 8 ++++++-- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/api/app/core/tools/custom/base.py b/api/app/core/tools/custom/base.py index 3f3daad7..c7858a7b 100644 --- a/api/app/core/tools/custom/base.py +++ b/api/app/core/tools/custom/base.py @@ -220,7 +220,9 @@ class CustomTool(BaseTool): image_url = None if self._uploaded_files: for f in self._uploaded_files: - if f.get("type") == "image": + f_type = f.get("type", "") + if f_type == "image": + # Bedrock/Anthropic 格式:{"type": "image", "source": {"type": "base64", ...}} source = f.get("source", {}) if source.get("type") == "base64": media_type = source.get("media_type", "image/jpeg") @@ -232,7 +234,11 @@ class CustomTool(BaseTool): elif f.get("url"): # 其他格式:{"type": "image", "url": "https://..."} image_url = f.get("url") - break # 只取第一张图片 + break + elif f_type == "image_url": + # OpenAI/Volcano 格式:{"type": "image_url", "image_url": {"url": "..."}} + image_url = f.get("image_url", {}).get("url", "") + break # 如果 image_url 是服务器中转 URL,直接下载图片转 base64 # 避免 OSS 签名 URL 在重定向解析过程中被破坏 diff --git a/api/app/services/draft_run_service.py b/api/app/services/draft_run_service.py index 62d7ea71..fa307ec5 100644 --- a/api/app/services/draft_run_service.py +++ b/api/app/services/draft_run_service.py @@ -642,7 +642,6 @@ class AgentRunService: logger.info(f"处理了 {len(processed_files)} 个文件,provider={provider}") #================= 为 OpenClaw 工具注入运行时上下文========== for t in tools: - logger.info(f"检查工具: {type(t).__name__}, has_tool_instance={hasattr(t, 'tool_instance')}, is_openclaw={getattr(getattr(t, 'tool_instance', None), '_is_openclaw', 'N/A')}") if hasattr(t, 'tool_instance') and hasattr(t.tool_instance, '_is_openclaw'): if t.tool_instance._is_openclaw: t.tool_instance._user_id = user_id or "anonymous" diff --git a/api/app/services/tool_service.py b/api/app/services/tool_service.py index 0f88a65e..9c9faf69 100644 --- a/api/app/services/tool_service.py +++ b/api/app/services/tool_service.py @@ -358,11 +358,15 @@ class ToolService: self, custom_config: CustomToolConfig, schema: dict ) -> Dict[str, Any]: """测试 OpenClaw 连接""" + import aiohttp try: info = schema.get("info", {}) servers = schema.get("servers", []) - base_url = servers[0]["url"] if servers else "" - token = (custom_config.auth_config or {}).get("token", "") + base_url = servers[0].get("url", "") if servers else "" + if not base_url: + return {"success": False, "message": "OpenClaw 未配置 server URL"} + auth = custom_config.auth_config or {} + token = auth.get("api_key") or auth.get("token") or "" agent_id = info.get("x-openclaw-agent-id", "main") model = info.get("x-openclaw-default-model", "openclaw")