From aa6ab799c4906d57f65a3ecb8deca52eb7133c9e Mon Sep 17 00:00:00 2001 From: foxhui Date: Mon, 16 Feb 2026 14:20:05 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E8=B1=86=E5=8C=85?= =?UTF-8?q?=E9=80=82=E9=85=8D=E5=9B=BE=E7=89=87=E4=B8=8A=E4=BC=A0=E8=BF=9B?= =?UTF-8?q?=E5=BA=A6=E9=AA=8C=E8=AF=81=E5=A4=B1=E8=B4=A5=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98=20(ref=20#17)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + src/backend/adapter/doubao.js | 42 +++++++++++++++++++------ src/backend/adapter/doubao_text.js | 50 +++++++++++++++++++++--------- 3 files changed, 69 insertions(+), 24 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d7dbb50..52c92da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### 🐛 Fixed - **适配器** - 修复 DeepSeek 文本生成适配器因接口格式更新导致无法获取生成结果 + - 修复 豆包 适配器图片上传逻辑更改导致上传进度验证失败的问题 ## [3.5.2] - 2026-02-10 diff --git a/src/backend/adapter/doubao.js b/src/backend/adapter/doubao.js index 13bd1ad..8dd0590 100644 --- a/src/backend/adapter/doubao.js +++ b/src/backend/adapter/doubao.js @@ -60,17 +60,39 @@ async function generate(context, prompt, imgPaths, modelId, meta = {}) { if (imgPaths && imgPaths.length > 0) { logger.info('适配器', `开始上传 ${imgPaths.length} 张图片...`, meta); - const uploadBtn = page.locator('button[data-testid="image-creation-chat-input-picture-reference-button"]'); - await uploadBtn.waitFor({ state: 'visible', timeout: 10000 }); - - await uploadFilesViaChooser(page, uploadBtn, imgPaths, { - uploadValidator: (response) => { + // 预先拦截 ApplyImageUpload 响应,动态收集实际上传路径 + const expectedUploadPaths = new Set(); + const applyUploadHandler = async (response) => { + try { const url = response.url(); - return response.status() === 200 && - url.includes('bytedanceapi.com') && - url.includes('Action=CommitImageUpload'); - } - }, meta); + if (!url.includes('Action=ApplyImageUpload') || response.status() !== 200) return; + const json = await response.json(); + const storeUri = json.Result?.UploadAddress?.StoreInfos?.[0]?.StoreUri; + if (storeUri) { + expectedUploadPaths.add(storeUri); + logger.debug('适配器', `已获取上传路径: ${storeUri}`, meta); + } + } catch { /* 忽略解析错误 */ } + }; + page.on('response', applyUploadHandler); + + try { + const uploadBtn = page.locator('button[data-testid="image-creation-chat-input-picture-reference-button"]'); + await uploadBtn.waitFor({ state: 'visible', timeout: 10000 }); + + await uploadFilesViaChooser(page, uploadBtn, imgPaths, { + uploadValidator: (response) => { + if (response.status() !== 200 || response.request().method() !== 'POST') return false; + const url = response.url(); + for (const path of expectedUploadPaths) { + if (url.includes(path)) return true; + } + return false; + } + }, meta); + } finally { + page.off('response', applyUploadHandler); + } logger.info('适配器', '图片上传完成', meta); } diff --git a/src/backend/adapter/doubao_text.js b/src/backend/adapter/doubao_text.js index 43c236c..4a9eb36 100644 --- a/src/backend/adapter/doubao_text.js +++ b/src/backend/adapter/doubao_text.js @@ -45,21 +45,43 @@ async function generate(context, prompt, imgPaths, modelId, meta = {}) { if (imgPaths && imgPaths.length > 0) { logger.info('适配器', `开始上传 ${imgPaths.length} 张图片...`, meta); - // 点击上传菜单按钮 - const uploadMenuBtn = page.locator('main button[aria-haspopup="menu"]').first(); - await safeClick(page, uploadMenuBtn, { bias: 'button' }); - await sleep(300, 500); - - // 点击上传文件选项 - const uploadItem = page.locator('div[data-testid="upload_file_panel_upload_item"][role="menuitem"]'); - await uploadFilesViaChooser(page, uploadItem, imgPaths, { - uploadValidator: (response) => { + // 预先拦截 ApplyImageUpload 响应,动态收集实际上传路径 + const expectedUploadPaths = new Set(); + const applyUploadHandler = async (response) => { + try { const url = response.url(); - return response.status() === 200 && - url.includes('bytedanceapi.com') && - url.includes('Action=CommitImageUpload'); - } - }, meta); + if (!url.includes('Action=ApplyImageUpload') || response.status() !== 200) return; + const json = await response.json(); + const storeUri = json.Result?.UploadAddress?.StoreInfos?.[0]?.StoreUri; + if (storeUri) { + expectedUploadPaths.add(storeUri); + logger.debug('适配器', `已获取上传路径: ${storeUri}`, meta); + } + } catch { /* 忽略解析错误 */ } + }; + page.on('response', applyUploadHandler); + + try { + // 点击上传菜单按钮 + const uploadMenuBtn = page.locator('main button[aria-haspopup="menu"]').first(); + await safeClick(page, uploadMenuBtn, { bias: 'button' }); + await sleep(300, 500); + + // 点击上传文件选项 + const uploadItem = page.locator('div[data-testid="upload_file_panel_upload_item"][role="menuitem"]'); + await uploadFilesViaChooser(page, uploadItem, imgPaths, { + uploadValidator: (response) => { + if (response.status() !== 200 || response.request().method() !== 'POST') return false; + const url = response.url(); + for (const path of expectedUploadPaths) { + if (url.includes(path)) return true; + } + return false; + } + }, meta); + } finally { + page.off('response', applyUploadHandler); + } logger.info('适配器', '图片上传完成', meta); }