您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
拦截 aistudio.google.com 的 GenerateContent 请求修改模型,支持在官方、预览及内部测试模型(例如 Kingfall)间切换,并提供带分类的下拉菜单。
// ==UserScript== // @name:zh_cn AI Studio 模型修改器 - 解锁 Kingfall 及更多隐藏模型 // @name AI Studio Model Modifier // @namespace http://tampermonkey.net/ // @version 1.1.1 // @description 拦截 aistudio.google.com 的 GenerateContent 请求修改模型,支持在官方、预览及内部测试模型(例如 Kingfall)间切换,并提供带分类的下拉菜单。 // @description:en Modify the model for aistudio.google.com requests, allowing switching between official, preview, and internal test models such as kingfall with a categorized dropdown menu. // @author Z_06 // @match *://aistudio.google.com/* // @icon https://www.google.com/s2/favicons?sz=64&domain=google.com // @license MIT // @grant GM_setValue // @grant GM_getValue // @grant GM_registerMenuCommand // @grant GM_addStyle // @homepageURL https://greasyfork.org/zh-CN/scripts/539130-ai-studio-model-modifier // @supportURL https://greasyfork.org/zh-CN/scripts/539130-ai-studio-model-modifier // ==/UserScript== (function() { 'use strict'; // --- 配置区域 --- const SCRIPT_NAME = "[AI Studio] 模型修改器"; const STORAGE_KEY = "aistudio_custom_model_name_v2"; const TARGET_URL = "https://alkalimakersuite-pa.clients6.google.com/$rpc/google.internal.alkali.applications.makersuite.v1.MakerSuiteService/GenerateContent"; const MODEL_SELECTOR_CONTAINER = 'div.settings-model-selector'; // 带分类的可选模型列表 const MODEL_OPTIONS = [ { label: "内部测试模型", options: [ { name: "Kingfall (内部测试)", value: "models/kingfall-ab-test" }, { name: "Calmriver (内部测试)", value: "models/calmriver-ab-test" }, { name: "Claybrook (内部测试)", value: "models/claybrook-ab-test" }, { name: "Frostwind (内部测试)", value: "models/frostwind-ab-test" }, { name: "Goldmane (内部测试)", value: "models/goldmane-ab-test" }, ] }, { label: "Gemini 2.5", options: [ { name: "2.5 Pro 预览版 (06-05)", value: "models/gemini-2.5-pro-preview-06-05" }, { name: "2.5 Flash 预览版 (05-20)", value: "models/gemini-2.5-flash-preview-05-20" }, { name: "2.5 Pro 预览 (05-06)", value: "models/gemini-2.5-pro-preview-05-06" }, { name: "2.5 Pro 预览 (03-25)", value: "models/gemini-2.5-pro-preview-03-25" }, { name: "2.5 Pro 预览 (03-25 AB-Test)", value: "models/gemini-2.5-pro-preview-03-25-ab-test" }, { name: "2.5 Pro EXP (03-25)", value: "models/gemini-2.5-pro-exp-03-25" }, { name: "2.5 Flash 预览 (04-17)", value: "models/gemini-2.5-flash-preview-04-17" }, { name: "2.5 Flash 预览 (04-17 Thinking)", value: "models/gemini-2.5-flash-preview-04-17-thinking" }, ] }, { label: "Gemini 2.0", options: [ { name: "2.0 Flash", value: "models/gemini-2.0-flash" }, { name: "2.0 Flash (图片生成)", value: "models/gemini-2.0-flash-preview-image-generation" }, { name: "2.0 Flash-Lite", value: "models/gemini-2.0-flash-lite" }, ] }, { label: "Gemini 1.5", options: [ { name: "1.5 Pro", value: "models/gemini-1.5-pro" }, { name: "1.5 Flash", value: "models/gemini-1.5-flash" }, { name: "1.5 Flash-8B", value: "models/gemini-1.5-flash-8b" }, ] } ]; // 默认模型 const DEFAULT_MODEL = MODEL_OPTIONS[0].options[0].value; // --- 获取已保存的或默认的模型名称 --- let customModelName = GM_getValue(STORAGE_KEY, DEFAULT_MODEL); // --- 注入CSS样式 --- GM_addStyle(` ${MODEL_SELECTOR_CONTAINER} ms-model-selector-two-column { display: none !important; } #custom-model-selector { width: 100%; padding: 8px 12px; margin-top: 4px; border: 1px solid #5f6368; border-radius: 8px; color: #e2e2e5; background-color: #35373a; font-family: 'Google Sans', 'Roboto', sans-serif; font-size: 14px; font-weight: 500; box-sizing: border-box; cursor: pointer; -webkit-appearance: none; -moz-appearance: none; appearance: none; background-image: url('data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22292.4%22%20height%3D%22292.4%22%3E%3Cpath%20fill%3D%22%23e2e2e5%22%20d%3D%22M287%2069.4a17.6%2017.6%200%200%200-13-5.4H18.4c-5%200-9.3%201.8-12.9%205.4A17.6%2017.6%200%200%200%200%2082.2c0%205%201.8%209.3%205.4%2012.9l128%20127.9c3.6%203.6%207.8%205.4%2012.8%205.4s9.2-1.8%2012.8-5.4L287%2095c3.5-3.5%205.4-7.8%205.4-12.8%200-5-1.9-9.4-5.4-13z%22%2F%3E%3C%2Fsvg%3E'); background-repeat: no-repeat; background-position: right 12px center; background-size: 10px; } #custom-model-selector optgroup { font-weight: bold; color: #8ab4f8; } `); // --- 菜单和UI更新逻辑 --- /** * 更新或创建下拉菜单中的选项,并选中指定的模型 * @param {string} modelValue - 要选中的模型的完整值 */ function updateAndSelectModel(modelValue) { const selector = document.getElementById('custom-model-selector'); if (!selector) return; // 使用 querySelector 检查选项是否已存在于任何分组中 if (!selector.querySelector(`option[value="${modelValue}"]`)) { // 选项不存在,动态创建它到 "自定义模型" 分组 let customGroup = document.getElementById('custom-model-optgroup'); if (!customGroup) { customGroup = document.createElement('optgroup'); customGroup.id = 'custom-model-optgroup'; customGroup.label = '自定义模型'; selector.appendChild(customGroup); } const newOption = document.createElement('option'); newOption.value = modelValue; newOption.textContent = `* ${modelValue.replace('models/', '')}`; customGroup.appendChild(newOption); } selector.value = modelValue; } /** * 创建并注入带分类的模型选择下拉菜单 * @param {HTMLElement} container - 用于注入UI的父容器元素 */ function createModelSelectorUI(container) { console.log(`[${SCRIPT_NAME}] 发现容器,注入带分类的UI...`); const selector = document.createElement('select'); selector.id = 'custom-model-selector'; selector.title = "所有请求都将被强制使用此下拉框选中的模型"; // 遍历分类和选项来创建 <optgroup> 和 <option> MODEL_OPTIONS.forEach(group => { const optgroup = document.createElement('optgroup'); optgroup.label = group.label; group.options.forEach(opt => { const option = document.createElement('option'); option.value = opt.value; option.textContent = opt.name; optgroup.appendChild(option); }); selector.appendChild(optgroup); }); selector.addEventListener('change', (event) => { const newModel = event.target.value; customModelName = newModel; GM_setValue(STORAGE_KEY, newModel); console.log(`[${SCRIPT_NAME}] 模型已切换并保存: ${newModel}`); }); const injectionPoint = container.querySelector('.item-input-form-field'); if (injectionPoint) { injectionPoint.appendChild(selector); // 初始化UI,确保它显示当前活动的模型(如果不在预设中,会动态添加) updateAndSelectModel(customModelName); console.log(`[${SCRIPT_NAME}] 自定义UI注入成功。`); } } // 注册油猴菜单命令 GM_registerMenuCommand(`添加/设置自定义模型`, () => { const newModel = prompt("请输入要强制使用的完整模型名称:", customModelName); if (newModel && newModel.trim() !== "") { const trimmedModel = newModel.trim(); customModelName = trimmedModel; GM_setValue(STORAGE_KEY, trimmedModel); alert(`模型已更新为:\n${trimmedModel}`); updateAndSelectModel(trimmedModel); } }); // --- DOM 变动监听,用于注入UI元素 --- const observer = new MutationObserver((mutations, obs) => { const container = document.querySelector(MODEL_SELECTOR_CONTAINER); if (container && !document.getElementById('custom-model-selector')) { createModelSelectorUI(container); } }); observer.observe(document.body, { childList: true, subtree: true }); // --- 核心:拦截和修改 XHR 请求 --- const originalOpen = XMLHttpRequest.prototype.open; XMLHttpRequest.prototype.open = function(method, url) { this._url = url; this._method = method; return originalOpen.apply(this, arguments); }; const originalSend = XMLHttpRequest.prototype.send; XMLHttpRequest.prototype.send = function(data) { if (this._url === TARGET_URL && this._method.toUpperCase() === 'POST' && data) { try { let payload = JSON.parse(data); const originalModel = payload[0]; if (typeof originalModel === 'string' && originalModel.startsWith('models/')) { console.log(`[${SCRIPT_NAME}] 拦截请求。原始: ${originalModel} -> 修改为: ${customModelName}`); payload[0] = customModelName; const modifiedData = JSON.stringify(payload); return originalSend.call(this, modifiedData); } } catch (e) { console.error(`[${SCRIPT_NAME}] 修改请求负载时出错:`, e); } } return originalSend.apply(this, arguments); }; console.log(`[${SCRIPT_NAME}] 已加载。当前强制模型为 "${customModelName}"。`); })();