feat: 支持豆包 Pro 模型并修复豆包回复截断的问题 (closes #23, closes #24)

This commit is contained in:
foxhui
2026-03-19 17:01:10 +08:00
parent a9240c2375
commit fd83422e97
2 changed files with 59 additions and 27 deletions
+9
View File
@@ -5,6 +5,15 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [3.5.5] - 2026-03-05
### ✨ Added
- **豆包**
- 增加豆包 Pro 模型的支持
### 🐛 Fixed
- **适配器**
- 修复豆包文本被截断的问题
## [3.5.5] - 2026-03-05 ## [3.5.5] - 2026-03-05
### ✨ Added ### ✨ Added
+50 -27
View File
@@ -31,7 +31,14 @@ async function generate(context, prompt, imgPaths, modelId, meta = {}) {
const { page } = context; const { page } = context;
// 是否使用深度思考模式 // 是否使用深度思考模式
const useThinking = modelId === 'seed-thinking'; const useThinking = modelId === 'seed-thinking' || modelId === 'seed-pro';
// 模型 ID 到菜单项无障碍名称的映射
const MODEL_MENU_MAP = {
'seed': 'Fast Solves most questions',
'seed-thinking': 'Think Solves more complex problems',
'seed-pro': 'Pro Advanced Pro model'
};
try { try {
logger.info('适配器', '开启新会话...', meta); logger.info('适配器', '开启新会话...', meta);
@@ -63,7 +70,7 @@ async function generate(context, prompt, imgPaths, modelId, meta = {}) {
try { try {
// 点击上传菜单按钮 // 点击上传菜单按钮
const uploadMenuBtn = page.locator('main button[aria-haspopup="menu"]').first(); const uploadMenuBtn = page.locator('main button[aria-haspopup="menu"]:not(:has(div[data-testid="deep-thinking-action-button"]))').first();
await safeClick(page, uploadMenuBtn, { bias: 'button' }); await safeClick(page, uploadMenuBtn, { bias: 'button' });
await sleep(300, 500); await sleep(300, 500);
@@ -86,20 +93,21 @@ async function generate(context, prompt, imgPaths, modelId, meta = {}) {
logger.info('适配器', '图片上传完成', meta); logger.info('适配器', '图片上传完成', meta);
} }
// 3. 切换深度思考模式 (如需) // 3. 选择模型
const deepThinkBtn = page.locator('div[data-testid="use-deep-thinking-switch-btn"] button'); const modelMenuName = MODEL_MENU_MAP[modelId] || MODEL_MENU_MAP['seed'];
const btnExists = await deepThinkBtn.count() > 0; logger.debug('适配器', `选择模型: ${modelId} -> ${modelMenuName}`, meta);
if (btnExists) { const modelSelectorBtn = page.locator('div[data-testid="deep-thinking-action-button"]');
const isChecked = await deepThinkBtn.getAttribute('data-checked') === 'true'; const selectorExists = await modelSelectorBtn.count() > 0;
if (useThinking && !isChecked) { if (selectorExists) {
logger.debug('适配器', '启用深度思考模式...', meta); await safeClick(page, modelSelectorBtn, { bias: 'button' });
await safeClick(page, deepThinkBtn, { bias: 'button' }); await sleep(300, 500);
} else if (!useThinking && isChecked) {
logger.debug('适配器', '关闭深度思考模式...', meta); const menuItem = page.getByRole('menuitem', { name: modelMenuName });
await safeClick(page, deepThinkBtn, { bias: 'button' }); await menuItem.waitFor({ state: 'visible', timeout: 5000 });
} await safeClick(page, menuItem, { bias: 'button' });
await sleep(200, 400);
} }
// 4. 填写提示词 // 4. 填写提示词
@@ -212,13 +220,16 @@ function parseSSEResponse(body, useThinking) {
try { try {
const data = JSON.parse(dataLine); const data = JSON.parse(dataLine);
// SSE_REPLY_END with end_type: 1 包含完整回复 // SSE_REPLY_END with end_type: 1 的 brief 仅作兜底
if (eventType === 'SSE_REPLY_END' && data.end_type === 1) { if (eventType === 'SSE_REPLY_END' && data.end_type === 1) {
resultText = data.msg_finish_attr?.brief || ''; const brief = data.msg_finish_attr?.brief || '';
if (!resultText && brief) {
resultText = brief;
}
} }
// STREAM_MSG_NOTIFY 检测深度思考块 // STREAM_MSG_NOTIFY 检测深度思考块
if (eventType === 'STREAM_MSG_NOTIFY' && useThinking) { if (eventType === 'STREAM_MSG_NOTIFY') {
const blocks = data.content?.content_block || []; const blocks = data.content?.content_block || [];
for (const block of blocks) { for (const block of blocks) {
if (block.block_type === 10040 && block.content?.thinking_block) { if (block.block_type === 10040 && block.content?.thinking_block) {
@@ -229,28 +240,39 @@ function parseSSEResponse(body, useThinking) {
} }
// STREAM_CHUNK 处理内容块 // STREAM_CHUNK 处理内容块
if (eventType === 'STREAM_CHUNK' && useThinking && data.patch_op) { if (eventType === 'STREAM_CHUNK' && data.patch_op) {
for (const op of data.patch_op) { for (const op of data.patch_op) {
if (op.patch_object === 1 && op.patch_value?.content_block) { if (op.patch_object === 1 && op.patch_value?.content_block) {
for (const block of op.patch_value.content_block) { for (const block of op.patch_value.content_block) {
// 如果有 parent_id 指向 thinking_block,则是思考内容
if (block.parent_id === thinkingBlockId) {
const text = block.content?.text_block?.text || '';
if (text) reasoningText += text;
}
// 思考块结束标记 // 思考块结束标记
if (block.block_type === 10040 && block.is_finish) { if (block.block_type === 10040 && block.is_finish) {
inThinkingBlock = false; inThinkingBlock = false;
} }
// 思考内容 (parent_id 指向 thinking_block)
if (useThinking && block.parent_id === thinkingBlockId) {
const text = block.content?.text_block?.text || '';
if (text) reasoningText += text;
}
// 正文内容 (block_type 10000,非思考子块)
else if (block.block_type === 10000 && block.parent_id !== thinkingBlockId) {
const text = block.content?.text_block?.text || '';
if (text) resultText += text;
}
} }
} }
} }
} }
// CHUNK_DELTA 增量文本 (思考过程中的增量) // CHUNK_DELTA 增量文本
if (eventType === 'CHUNK_DELTA' && useThinking && inThinkingBlock) { if (eventType === 'CHUNK_DELTA') {
const text = data.text || ''; const text = data.text || '';
if (text) reasoningText += text; if (text) {
if (useThinking && inThinkingBlock) {
reasoningText += text;
} else {
resultText += text;
}
}
} }
} catch (e) { } catch (e) {
@@ -277,7 +299,8 @@ export const manifest = {
models: [ models: [
{ id: 'seed', imagePolicy: 'optional', type: 'text' }, { id: 'seed', imagePolicy: 'optional', type: 'text' },
{ id: 'seed-thinking', imagePolicy: 'optional', type: 'text' } { id: 'seed-thinking', imagePolicy: 'optional', type: 'text' },
{ id: 'seed-pro', imagePolicy: 'optional', type: 'text' }
], ],
navigationHandlers: [], navigationHandlers: [],