Skip to content

Commit 2b102db

Browse files
authored
Merge pull request #215 from CJackHwang/dev
同步Dev分支
2 parents 2ab8d68 + 03d40b1 commit 2b102db

9 files changed

Lines changed: 313 additions & 299 deletions

File tree

.env.example

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ DEFAULT_TOP_P=0.95
8686
DEFAULT_STOP_SEQUENCES=["用户:"]
8787

8888
# 是否在处理请求时自动打开并使用 "URL Context" 功能,此工具功能详情可参考:https://ai.google.dev/gemini-api/docs/url-context
89-
ENABLE_URL_CONTEXT=true
89+
ENABLE_URL_CONTEXT=false
9090

9191
# 是否默认启用 "指定思考预算" 功能 (true/false),不启用时模型一般将自行决定思考预算
9292
# 当 API 请求中未提供 reasoning_effort 参数时将使用此值。

api_utils/utils.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,8 @@ def prepare_combined_prompt(messages: List[Message], req_id: str) -> str:
250250
combined_parts = []
251251
system_prompt_content: Optional[str] = None
252252
processed_system_message_indices = set()
253-
253+
images_list = [] # 将 image_list 的初始化移到循环外部
254+
254255
# 处理系统消息
255256
for i, msg in enumerate(messages):
256257
if msg.role == 'system':
@@ -284,7 +285,6 @@ def prepare_combined_prompt(messages: List[Message], req_id: str) -> str:
284285
role = msg.role or 'unknown'
285286
role_prefix_ui = f"{role_map_ui.get(role, role.capitalize())}:\n"
286287
current_turn_parts = [role_prefix_ui]
287-
images_list = []
288288

289289
content = msg.content or ''
290290
content_str = ""

browser_utils/model_management.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ async def _verify_ui_state_settings(page: AsyncPage, req_id: str = "unknown") ->
5151
are_tools_open = prefs.get('areToolsOpen')
5252

5353
# 检查是否需要更新
54-
needs_update = (is_advanced_open is not True) or (are_tools_open is not False)
54+
needs_update = (is_advanced_open is not True) or (are_tools_open is not True)
5555

5656
result = {
5757
'exists': True,
@@ -61,7 +61,7 @@ async def _verify_ui_state_settings(page: AsyncPage, req_id: str = "unknown") ->
6161
'prefs': prefs
6262
}
6363

64-
logger.info(f"[{req_id}] UI状态验证结果: isAdvancedOpen={is_advanced_open}, areToolsOpen={are_tools_open}, needsUpdate={needs_update}")
64+
logger.info(f"[{req_id}] UI状态验证结果: isAdvancedOpen={is_advanced_open}, areToolsOpen={are_tools_open} (期望: True), needsUpdate={needs_update}")
6565
return result
6666

6767
except json.JSONDecodeError as e:
@@ -110,13 +110,13 @@ async def _force_ui_state_settings(page: AsyncPage, req_id: str = "unknown") ->
110110

111111
# 强制设置关键配置
112112
prefs['isAdvancedOpen'] = True
113-
prefs['areToolsOpen'] = False
113+
prefs['areToolsOpen'] = True
114114

115115
# 保存到localStorage
116116
prefs_str = json.dumps(prefs)
117117
await page.evaluate("(prefsStr) => localStorage.setItem('aiStudioUserPreference', prefsStr)", prefs_str)
118118

119-
logger.info(f"[{req_id}] 已强制设置: isAdvancedOpen=true, areToolsOpen=false")
119+
logger.info(f"[{req_id}] 已强制设置: isAdvancedOpen=true, areToolsOpen=true")
120120

121121
# 验证设置是否成功
122122
verify_state = await _verify_ui_state_settings(page, req_id)
@@ -231,7 +231,7 @@ async def switch_ai_studio_model(page: AsyncPage, model_id: str, req_id: str) ->
231231

232232
# 为了保持兼容性,也更新当前的prefs对象
233233
current_prefs_for_modification["isAdvancedOpen"] = True
234-
current_prefs_for_modification["areToolsOpen"] = False
234+
current_prefs_for_modification["areToolsOpen"] = True
235235
await page.evaluate("(prefsStr) => localStorage.setItem('aiStudioUserPreference', prefsStr)", json.dumps(current_prefs_for_modification))
236236

237237
logger.info(f"[{req_id}] localStorage 已更新,导航到 '{new_chat_url}' 应用新模型...")
@@ -362,7 +362,7 @@ async def switch_ai_studio_model(page: AsyncPage, model_id: str, req_id: str) ->
362362

363363
# 为了保持兼容性,也更新当前的prefs对象
364364
base_prefs_for_final_revert["isAdvancedOpen"] = True
365-
base_prefs_for_final_revert["areToolsOpen"] = False
365+
base_prefs_for_final_revert["areToolsOpen"] = True
366366
logger.info(f"[{req_id}] 恢复:准备将 localStorage.promptModel 设置回页面实际显示的模型的路径: '{path_to_revert_to}',并强制设置配置选项")
367367
await page.evaluate("(prefsStr) => localStorage.setItem('aiStudioUserPreference', prefsStr)", json.dumps(base_prefs_for_final_revert))
368368
logger.info(f"[{req_id}] 恢复:导航到 '{new_chat_url}' 以应用恢复到 '{model_id_to_revert_to}' 的 localStorage 设置...")
@@ -463,7 +463,7 @@ async def _handle_initial_model_state_and_storage(page: AsyncPage):
463463
ui_state = await _verify_ui_state_settings(page, "initial")
464464
if ui_state['needsUpdate']:
465465
needs_reload_and_storage_update = True
466-
reason_for_reload = f"UI状态需要更新: isAdvancedOpen={ui_state['isAdvancedOpen']}, areToolsOpen={ui_state['areToolsOpen']}"
466+
reason_for_reload = f"UI状态需要更新: isAdvancedOpen={ui_state['isAdvancedOpen']}, areToolsOpen={ui_state['areToolsOpen']} (期望: True)"
467467
logger.info(f" 判定需要刷新和存储更新: {reason_for_reload}")
468468
else:
469469
server.current_ai_studio_model_id = prompt_model_path.split('/')[-1]
@@ -577,12 +577,12 @@ async def _set_model_from_page_display(page: AsyncPage, set_storage: bool = Fals
577577
if not ui_state_success:
578578
logger.warning(f" UI状态设置失败,使用传统方法")
579579
prefs_to_set["isAdvancedOpen"] = True
580-
prefs_to_set["areToolsOpen"] = False
580+
prefs_to_set["areToolsOpen"] = True
581581
else:
582582
# 确保prefs_to_set也包含正确的设置
583583
prefs_to_set["isAdvancedOpen"] = True
584-
prefs_to_set["areToolsOpen"] = False
585-
logger.info(f" 强制 isAdvancedOpen: true, areToolsOpen: false")
584+
prefs_to_set["areToolsOpen"] = True
585+
logger.info(f" 强制 isAdvancedOpen: true, areToolsOpen: true")
586586

587587
if found_model_id_from_display:
588588
new_prompt_model_path = f"models/{found_model_id_from_display}"
@@ -609,6 +609,6 @@ async def _set_model_from_page_display(page: AsyncPage, set_storage: bool = Fals
609609
prefs_to_set[key] = val_default
610610

611611
await page.evaluate("(prefsStr) => localStorage.setItem('aiStudioUserPreference', prefsStr)", json.dumps(prefs_to_set))
612-
logger.info(f" ✅ localStorage.aiStudioUserPreference 已更新。isAdvancedOpen: {prefs_to_set.get('isAdvancedOpen')}, areToolsOpen: {prefs_to_set.get('areToolsOpen')}, promptModel: '{prefs_to_set.get('promptModel', '未设置/保留原样')}'。")
612+
logger.info(f" ✅ localStorage.aiStudioUserPreference 已更新。isAdvancedOpen: {prefs_to_set.get('isAdvancedOpen')}, areToolsOpen: {prefs_to_set.get('areToolsOpen')} (期望: True), promptModel: '{prefs_to_set.get('promptModel', '未设置/保留原样')}'。")
613613
except Exception as e_set_disp:
614614
logger.error(f" 尝试从页面显示设置模型时出错: {e_set_disp}", exc_info=True)

browser_utils/more_modles.js

Lines changed: 12 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -23,44 +23,18 @@
2323
// 模型配置列表
2424
// 已按要求将 jfdksal98a 放到 blacktooth 的下面
2525
const MODELS_TO_INJECT = [
26-
// Blacktooth 模型 (原 Toothless)
27-
{
28-
name: 'models/blacktooth-ab-test', // 已改为 blacktooth-ab-test
29-
displayName: `🏴‍☠️ Blacktooth (脚本 ${SCRIPT_VERSION})`, // emoji 改为 🏴‍☠️,名称改为 Blacktooth
30-
description: `由脚本 ${SCRIPT_VERSION} 注入的模型`
31-
},
32-
// --- jfdksal98a 模型已移动到此处 ---
33-
{
34-
name: 'models/jfdksal98a',
35-
displayName: `🪐 jfdksal98a (脚本 ${SCRIPT_VERSION})`,
36-
description: `由脚本 ${SCRIPT_VERSION} 注入的模型`
37-
},
38-
// --- 其他模型 ---
39-
{
40-
name: 'models/gemini-2.5-pro-preview-03-25',
41-
displayName: `✨ Gemini 2.5 Pro 03-25 (脚本 ${SCRIPT_VERSION})`,
42-
description: `由脚本 ${SCRIPT_VERSION} 注入的模型`
43-
},
44-
{
45-
name: 'models/goldmane-ab-test',
46-
displayName: `🦁 Goldmane (脚本 ${SCRIPT_VERSION})`,
47-
description: `由脚本 ${SCRIPT_VERSION} 注入的模型`
48-
},
49-
{
50-
name: 'models/claybrook-ab-test',
51-
displayName: `💧 Claybrook (脚本 ${SCRIPT_VERSION})`,
52-
description: `由脚本 ${SCRIPT_VERSION} 注入的模型`
53-
},
54-
{
55-
name: 'models/frostwind-ab-test',
56-
displayName: `❄️ Frostwind (脚本 ${SCRIPT_VERSION})`,
57-
description: `由脚本 ${SCRIPT_VERSION} 注入的模型`
58-
},
59-
{
60-
name: 'models/calmriver-ab-test',
61-
displayName: `🌊 Calmriver (脚本 ${SCRIPT_VERSION})`,
62-
description: `由脚本 ${SCRIPT_VERSION} 注入的模型`
63-
}
26+
{ name: 'models/gemini-2.5-pro-preview-03-25', displayName: `✨ Gemini 2.5 Pro 03-25 (Script ${SCRIPT_VERSION})`, description: `Model injected by script ${SCRIPT_VERSION}` },
27+
{ name: 'models/gemini-2.5-pro-exp-03-25', displayName: `✨ Gemini 2.5 Pro 03-25 (Script ${SCRIPT_VERSION})`, description: `Model injected by script ${SCRIPT_VERSION}` },
28+
{ name: 'models/gemini-2.5-pro-preview-06-05', displayName: `✨ Gemini 2.5 Pro 03-25 (Script ${SCRIPT_VERSION})`, description: `Model injected by script ${SCRIPT_VERSION}` },
29+
30+
//下面模型已经失效,留下来怀念
31+
// { name: 'models/blacktooth-ab-test', displayName: `🏴‍☠️ Blacktooth (脚本 ${SCRIPT_VERSION})`, description: `由脚本 ${SCRIPT_VERSION} 注入的模型` },
32+
// { name: 'models/jfdksal98a', displayName: `🪐 jfdksal98a (脚本 ${SCRIPT_VERSION})`, description: `由脚本 ${SCRIPT_VERSION} 注入的模型` },
33+
// { name: 'models/gemini-2.5-pro-preview-03-25', displayName: `✨ Gemini 2.5 Pro 03-25 (脚本 ${SCRIPT_VERSION})`, description: `由脚本 ${SCRIPT_VERSION} 注入的模型` },
34+
// { name: 'models/goldmane-ab-test', displayName: `🦁 Goldmane (脚本 ${SCRIPT_VERSION})`, description: `由脚本 ${SCRIPT_VERSION} 注入的模型` },
35+
// { name: 'models/claybrook-ab-test', displayName: `💧 Claybrook (脚本 ${SCRIPT_VERSION})`, description: `由脚本 ${SCRIPT_VERSION} 注入的模型` },
36+
// { name: 'models/frostwind-ab-test', displayName: `❄️ Frostwind (脚本 ${SCRIPT_VERSION})`, description: `由脚本 ${SCRIPT_VERSION} 注入的模型` },
37+
// { name: 'models/calmriver-ab-test', displayName: `🌊 Calmriver (脚本 ${SCRIPT_VERSION})`, description: `由脚本 ${SCRIPT_VERSION} 注入的模型` }
6438
];
6539

6640
// JSON 结构中的字段索引

browser_utils/page_controller.py

Lines changed: 46 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ async def adjust_parameters(self, request_params: Dict[str, Any], page_params_ca
6262
await self._adjust_top_p(top_p_to_set, check_client_disconnected)
6363
await self._check_disconnect(check_client_disconnected, "End Parameter Adjustment")
6464

65+
# 确保工具面板已展开,以便调整高级设置
66+
await self._ensure_tools_panel_expanded(check_client_disconnected)
67+
6568
# 调整URL CONTEXT
6669
if ENABLE_URL_CONTEXT:
6770
await self._open_url_content(check_client_disconnected)
@@ -77,9 +80,16 @@ async def adjust_parameters(self, request_params: Dict[str, Any], page_params_ca
7780
async def _handle_thinking_budget(self, request_params: Dict[str, Any], check_client_disconnected: Callable):
7881
"""处理思考预算的调整逻辑。"""
7982
reasoning_effort = request_params.get('reasoning_effort')
80-
if reasoning_effort is not None:
81-
# 用户指定了,则开启并设置
82-
self.logger.info(f"[{self.req_id}] 用户指定了 reasoning_effort: {reasoning_effort}。")
83+
84+
# 检查用户是否明确禁用了思考预算
85+
should_disable_budget = isinstance(reasoning_effort, str) and reasoning_effort.lower() == 'none'
86+
87+
if should_disable_budget:
88+
self.logger.info(f"[{self.req_id}] 用户通过 reasoning_effort='none' 明确禁用思考预算。")
89+
await self._control_thinking_budget_toggle(should_be_checked=False, check_client_disconnected=check_client_disconnected)
90+
elif reasoning_effort is not None:
91+
# 用户指定了非 'none' 的值,则开启并设置
92+
self.logger.info(f"[{self.req_id}] 用户指定了 reasoning_effort: {reasoning_effort},将启用并设置思考预算。")
8393
await self._control_thinking_budget_toggle(should_be_checked=True, check_client_disconnected=check_client_disconnected)
8494
await self._adjust_thinking_budget(reasoning_effort, check_client_disconnected)
8595
else:
@@ -209,27 +219,50 @@ async def _adjust_google_search(self, request_params: Dict[str, Any], check_clie
209219
if isinstance(e, ClientDisconnectedError):
210220
raise
211221

212-
async def _open_url_content(self,check_client_disconnected: Callable):
222+
async def _ensure_tools_panel_expanded(self, check_client_disconnected: Callable):
223+
"""确保包含高级工具(URL上下文、思考预算等)的面板是展开的。"""
224+
self.logger.info(f"[{self.req_id}] 检查并确保工具面板已展开...")
213225
try:
214226
collapse_tools_locator = self.page.locator('button[aria-label="Expand or collapse tools"]')
227+
await expect_async(collapse_tools_locator).to_be_visible(timeout=5000)
228+
215229
grandparent_locator = collapse_tools_locator.locator("xpath=../..")
230+
class_string = await grandparent_locator.get_attribute("class", timeout=3000)
216231

217-
# 3. 获取祖父级元素的 class 属性值
218-
# get_attribute 返回一个包含所有 class 的字符串,例如 "menu dropdown active"
219-
class_string = await grandparent_locator.get_attribute("class")
220-
221-
# 4. 在 Python 中进行判断
222-
# 确保 class_string 不是 None,并且 'expanded' 是一个独立的 class
223232
if class_string and "expanded" not in class_string.split():
233+
self.logger.info(f"[{self.req_id}] 工具面板未展开,正在点击以展开...")
224234
await collapse_tools_locator.click(timeout=CLICK_TIMEOUT_MS)
225-
await asyncio.sleep(0.5)
235+
await self._check_disconnect(check_client_disconnected, "展开工具面板后")
236+
# 等待展开动画完成
237+
await expect_async(grandparent_locator).to_have_class(re.compile(r'.*expanded.*'), timeout=5000)
238+
self.logger.info(f"[{self.req_id}] ✅ 工具面板已成功展开。")
239+
else:
240+
self.logger.info(f"[{self.req_id}] 工具面板已处于展开状态。")
241+
except Exception as e:
242+
self.logger.error(f"[{self.req_id}] ❌ 展开工具面板时发生错误: {e}")
243+
# 即使出错,也继续尝试执行后续操作,但记录错误
244+
if isinstance(e, ClientDisconnectedError):
245+
raise
246+
247+
async def _open_url_content(self,check_client_disconnected: Callable):
248+
"""仅负责打开 URL Context 开关,前提是面板已展开。"""
249+
try:
250+
self.logger.info(f"[{self.req_id}] 检查并启用 URL Context 开关...")
226251
use_url_content_selector = self.page.locator(USE_URL_CONTEXT_SELECTOR)
252+
await expect_async(use_url_content_selector).to_be_visible(timeout=5000)
253+
227254
is_checked = await use_url_content_selector.get_attribute("aria-checked")
228255
if "false" == is_checked:
256+
self.logger.info(f"[{self.req_id}] URL Context 开关未开启,正在点击以开启...")
229257
await use_url_content_selector.click(timeout=CLICK_TIMEOUT_MS)
230-
await self._check_disconnect(check_client_disconnected, "点击URLCONTEXT")
258+
await self._check_disconnect(check_client_disconnected, "点击URLCONTEXT后")
259+
self.logger.info(f"[{self.req_id}] ✅ URL Context 开关已点击。")
260+
else:
261+
self.logger.info(f"[{self.req_id}] URL Context 开关已处于开启状态。")
231262
except Exception as e:
232-
self.logger.error(f"[{self.req_id}] ❌ 操作USE_URL_CONTEXT_SELECTOR时发生错误:{e}。")
263+
self.logger.error(f"[{self.req_id}] ❌ 操作 USE_URL_CONTEXT_SELECTOR 时发生错误:{e}。")
264+
if isinstance(e, ClientDisconnectedError):
265+
raise
233266

234267
async def _control_thinking_budget_toggle(self, should_be_checked: bool, check_client_disconnected: Callable):
235268
"""

0 commit comments

Comments
 (0)