fix: 尝试修复同实例多窗口时点击超时,修复 Gemini 无法选择模型 (ref #30, ref #31)

This commit is contained in:
foxhui
2026-03-25 16:19:38 +08:00
Unverified
parent 2029ef345e
commit c234943fc2
5 changed files with 62 additions and 9 deletions
+8
View File
@@ -5,6 +5,14 @@ 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/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [3.5.9] - 2026-03-25
### 🐛 Fixed
- **适配器**
- 尝试修复同实例多窗口时出现点击超时的问题
- 修复 Gemini 文本适配器不选择模型的问题
- 修正 Gemini 文本适配器的模型 ID
## [3.5.8] - 2026-03-22
### ✨ Added
+8 -9
View File
@@ -87,8 +87,8 @@ async function generate(context, prompt, imgPaths, modelId, meta = {}) {
await page.keyboard.press('Enter');
await sleep(300, 500);
// 获取所有 menuitemradio 选项的文本
const menuItemsLocator = page.getByRole('menuitemradio');
// 获取所有 menuitem 选项的文本
const menuItemsLocator = page.getByRole('menuitem');
const menuItemsCount = await menuItemsLocator.count();
if (menuItemsCount === 0) {
@@ -107,16 +107,16 @@ async function generate(context, prompt, imgPaths, modelId, meta = {}) {
if (hasPro) {
// 有 Pro 选项的情况
if (modelId === 'gemini-3-pro' || modelId === 'gemini-exp-1206') {
if (modelId === 'gemini-3.1-pro') {
targetPrefix = 'Pro';
} else if (modelId === 'gemini-3-flash' || modelId === 'gemini-2.0-flash-exp') {
} else if (modelId === 'gemini-3.1-flash-thinking') {
targetPrefix = 'Thinking';
} else {
targetPrefix = 'Fast';
}
} else {
// 没有 Pro 选项的情况
if (modelId === 'gemini-3-pro' || modelId === 'gemini-exp-1206') {
if (modelId === 'gemini-3.1-pro' || modelId === 'gemini-3.1-flash-thinking') {
targetPrefix = 'Thinking';
} else {
targetPrefix = 'Fast';
@@ -214,10 +214,9 @@ export const manifest = {
},
models: [
{ id: 'gemini-2.0-flash-exp', imagePolicy: 'optional', type: 'text' },
{ id: 'gemini-exp-1206', imagePolicy: 'optional', type: 'text' },
{ id: 'gemini-3-pro', imagePolicy: 'optional', type: 'text' },
{ id: 'gemini-3-flash', imagePolicy: 'optional', type: 'text' }
{ id: 'gemini-3.1-flash', imagePolicy: 'optional', type: 'text' },
{ id: 'gemini-3.1-flash-thinking', imagePolicy: 'optional', type: 'text' },
{ id: 'gemini-3.1-pro', imagePolicy: 'optional', type: 'text' }
],
navigationHandlers: [],
+2
View File
@@ -108,6 +108,8 @@ export class PoolManager {
// 建立共享关系:设置所有者引用,并添加到所有者的共享列表
worker._browserOwner = existing.ownerWorker;
existing.ownerWorker._sharedWorkers.push(worker);
// 共享同一把浏览器互斥锁
worker._browserMutex = existing.ownerWorker._browserMutex;
} else {
await worker.init();
browserMap.set(worker.userDataDir, {
+10
View File
@@ -8,6 +8,7 @@ import { logger } from '../../utils/logger.js';
import { initBrowserBase, createCursor } from '../engine/launcher.js';
import { registry } from '../registry.js';
import { tryGotoWithCheck } from '../utils/page.js';
import { AsyncMutex } from '../../utils/asyncMutex.js';
/**
* Worker 类 - 封装单个浏览器实例
@@ -40,6 +41,9 @@ export class Worker {
this._isBrowserOwner = false; // 是否是浏览器的所有者(负责重启)
this._browserOwner = null; // 如果是共享者,指向所有者 Worker
this._sharedWorkers = []; // 如果是所有者,保存共享该浏览器的 Worker 列表
// 浏览器操作互斥锁(同一浏览器实例的 Worker 共享同一把锁)
this._browserMutex = new AsyncMutex();
}
/**
@@ -478,12 +482,18 @@ export class Worker {
userDataDir: this.userDataDir
};
// 获取浏览器互斥锁(防止同一浏览器实例的多个 Worker 并发操作鼠标)
const releaseLock = await this._browserMutex.acquire();
logger.debug('工作池', `[${this.name}] 已获取浏览器锁`, meta);
this.busyCount++;
try {
// 传递原始 modelId,由适配器自己解析
return await adapter.generate(subContext, prompt, paths, modelId, meta);
} finally {
this.busyCount--;
releaseLock();
logger.debug('工作池', `[${this.name}] 已释放浏览器锁`, meta);
}
}
+34
View File
@@ -0,0 +1,34 @@
/**
* @fileoverview 轻量异步互斥锁
* @description 保证同一时刻只有一个 async 任务持有锁,用于防止同一浏览器实例的多个 Worker 并发操作鼠标。
*/
export class AsyncMutex {
constructor() {
this._queue = [];
this._locked = false;
}
/**
* 获取锁,返回释放函数
* @returns {Promise<() => void>}
*/
acquire() {
return new Promise(resolve => {
const tryAcquire = () => {
if (!this._locked) {
this._locked = true;
resolve(() => {
this._locked = false;
if (this._queue.length > 0) {
this._queue.shift()();
}
});
} else {
this._queue.push(tryAcquire);
}
};
tryAcquire();
});
}
}