mirror of
https://github.com/foxhui/WebAI2API.git
synced 2026-06-16 21:03:59 +08:00
feat: 为项目添加 WebUI
This commit is contained in:
@@ -29,7 +29,7 @@ const TARGET_URL = 'https://gemini.google.com/app?hl=en';
|
||||
* @param {object} [meta={}] - 日志元数据
|
||||
* @returns {Promise<{image?: string, error?: string}>}
|
||||
*/
|
||||
async function generateImage(context, prompt, imgPaths, modelId, meta = {}) {
|
||||
async function generate(context, prompt, imgPaths, modelId, meta = {}) {
|
||||
const { page } = context;
|
||||
const inputLocator = page.getByRole('textbox');
|
||||
const sendBtnLocator = page.getByRole('button', { name: 'Send message' });
|
||||
@@ -192,5 +192,5 @@ export const manifest = {
|
||||
navigationHandlers: [],
|
||||
|
||||
// 核心生图方法
|
||||
generateImage
|
||||
generate
|
||||
};
|
||||
@@ -97,7 +97,7 @@ async function handleAccountChooser(page) {
|
||||
* @param {string} modelId - 模型 ID (目前未使用,固定为 gemini-3-pro-preview)
|
||||
* @returns {Promise<{image?: string, error?: string}>} 生成结果
|
||||
*/
|
||||
async function generateImage(context, prompt, imgPaths, modelId, meta = {}) {
|
||||
async function generate(context, prompt, imgPaths, modelId, meta = {}) {
|
||||
const { page, config } = context;
|
||||
|
||||
try {
|
||||
@@ -266,6 +266,17 @@ export const manifest = {
|
||||
id: 'gemini_biz',
|
||||
displayName: 'Gemini Business',
|
||||
|
||||
// 配置表单定义
|
||||
configSchema: [
|
||||
{
|
||||
key: 'entryUrl',
|
||||
label: '入口 URL',
|
||||
type: 'string',
|
||||
required: true,
|
||||
placeholder: 'https://business.gemini.google/home/cid/8888a888-b6e0-88be-86e1-888cf3ee8cf4'
|
||||
}
|
||||
],
|
||||
|
||||
// 入口 URL (从配置读取,支持新旧路径)
|
||||
getTargetUrl(config, workerConfig) {
|
||||
return config?.backend?.adapter?.gemini_biz?.entryUrl || config?.backend?.geminiBiz?.entryUrl || null;
|
||||
@@ -286,5 +297,5 @@ export const manifest = {
|
||||
navigationHandlers: [handleAccountChooser],
|
||||
|
||||
// 核心生图方法
|
||||
generateImage
|
||||
generate
|
||||
};
|
||||
|
||||
@@ -97,7 +97,7 @@ async function handleAccountChooser(page) {
|
||||
* @param {string} modelId - 模型 ID (目前未使用,固定为 gemini-3-pro-preview)
|
||||
* @returns {Promise<{image?: string, error?: string}>} 生成结果
|
||||
*/
|
||||
async function generateImage(context, prompt, imgPaths, modelId, meta = {}) {
|
||||
async function generate(context, prompt, imgPaths, modelId, meta = {}) {
|
||||
const { page, config } = context;
|
||||
|
||||
try {
|
||||
@@ -309,7 +309,19 @@ export const manifest = {
|
||||
id: 'gemini_biz_text',
|
||||
displayName: 'Gemini Business (Text)',
|
||||
|
||||
// 入口 URL (从配置读取,支持新旧路径)
|
||||
// 配置表单定义(与 gemini_biz 共享配置)
|
||||
configSchema: [
|
||||
{
|
||||
key: 'entryUrl',
|
||||
label: '入口 URL',
|
||||
type: 'string',
|
||||
required: true,
|
||||
placeholder: 'https://business.gemini.google/home/cid/8888a888-b6e0-88be-86e1-888cf3ee8cf4',
|
||||
note: '与 gemini_biz 共享配置'
|
||||
}
|
||||
],
|
||||
|
||||
// 入口 URL (从配置读取,与 gemini_biz 共享)
|
||||
getTargetUrl(config, workerConfig) {
|
||||
return config?.backend?.adapter?.gemini_biz?.entryUrl || config?.backend?.geminiBiz?.entryUrl || null;
|
||||
},
|
||||
@@ -334,5 +346,5 @@ export const manifest = {
|
||||
navigationHandlers: [handleAccountChooser],
|
||||
|
||||
// 核心生图方法
|
||||
generateImage
|
||||
generate
|
||||
};
|
||||
|
||||
@@ -52,7 +52,7 @@ function extractImage(text) {
|
||||
* @param {object} [meta={}] - 日志元数据
|
||||
* @returns {Promise<{image?: string, text?: string, error?: string}>} 生成结果
|
||||
*/
|
||||
async function generateImage(context, prompt, imgPaths, modelId, meta = {}) {
|
||||
async function generate(context, prompt, imgPaths, modelId, meta = {}) {
|
||||
const { page, config } = context;
|
||||
const textareaSelector = 'textarea';
|
||||
|
||||
@@ -222,5 +222,5 @@ export const manifest = {
|
||||
navigationHandlers: [],
|
||||
|
||||
// 核心生图方法
|
||||
generateImage
|
||||
generate
|
||||
};
|
||||
|
||||
@@ -33,7 +33,7 @@ const TARGET_URL_SEARCH = 'https://lmarena.ai/zh/c/new?mode=direct&chat-modality
|
||||
* @param {object} [meta={}] - 日志元数据
|
||||
* @returns {Promise<{image?: string, text?: string, error?: string}>} 生成结果
|
||||
*/
|
||||
async function generateImage(context, prompt, imgPaths, modelId, meta = {}) {
|
||||
async function generate(context, prompt, imgPaths, modelId, meta = {}) {
|
||||
const { page, config } = context;
|
||||
const textareaSelector = 'textarea';
|
||||
|
||||
@@ -305,5 +305,5 @@ export const manifest = {
|
||||
navigationHandlers: [],
|
||||
|
||||
// 核心生图方法
|
||||
generateImage
|
||||
generate
|
||||
};
|
||||
|
||||
@@ -32,7 +32,7 @@ const TARGET_URL = 'https://nanobananafree.ai/';
|
||||
* @param {object} [meta={}] - 日志元数据
|
||||
* @returns {Promise<{image?: string, text?: string, error?: string}>} 生成结果
|
||||
*/
|
||||
async function generateImage(context, prompt, imgPaths, modelId, meta = {}) {
|
||||
async function generate(context, prompt, imgPaths, modelId, meta = {}) {
|
||||
const { page } = context;
|
||||
const textareaSelector = 'textarea';
|
||||
|
||||
@@ -157,5 +157,5 @@ export const manifest = {
|
||||
navigationHandlers: [],
|
||||
|
||||
// 核心生图方法
|
||||
generateImage
|
||||
generate
|
||||
};
|
||||
|
||||
@@ -40,7 +40,7 @@ async function findElementWithShadowRoot(hostHandle) {
|
||||
/**
|
||||
* 执行 Turnstile 验证任务
|
||||
*/
|
||||
async function generateImage(context, prompt, imgPaths, modelId, meta = {}) {
|
||||
async function generate(context, prompt, imgPaths, modelId, meta = {}) {
|
||||
const { page } = context;
|
||||
|
||||
try {
|
||||
@@ -212,5 +212,5 @@ export const manifest = {
|
||||
},
|
||||
|
||||
navigationHandlers: [],
|
||||
generateImage
|
||||
generate
|
||||
};
|
||||
|
||||
@@ -119,7 +119,7 @@ async function handleDiscordAuth(page) {
|
||||
* @param {object} meta - 日志元数据
|
||||
* @returns {Promise<{image?: string, error?: string}>} 生成结果
|
||||
*/
|
||||
async function generateImage(context, prompt, imgPaths, modelId, meta = {}) {
|
||||
async function generate(context, prompt, imgPaths, modelId, meta = {}) {
|
||||
const { page, config } = context;
|
||||
|
||||
try {
|
||||
@@ -371,5 +371,5 @@ export const manifest = {
|
||||
navigationHandlers: [handleDiscordAuth],
|
||||
|
||||
// 核心生图方法
|
||||
generateImage
|
||||
generate
|
||||
};
|
||||
@@ -4,7 +4,7 @@
|
||||
*
|
||||
* 对外统一能力:
|
||||
* - `initBrowser(cfg)` → 初始化 Pool
|
||||
* - `generateImage(ctx, prompt, imagePaths, modelId, meta)`
|
||||
* - `generate(ctx, prompt, imagePaths, modelId, meta)`
|
||||
* - `resolveModelId(modelKey)` / `getModels()` / `getImagePolicy(modelKey)`
|
||||
* - `getCookies(workerName, domain)` - 获取指定 Worker 的 Cookies
|
||||
*/
|
||||
@@ -67,11 +67,11 @@ export function getBackend() {
|
||||
* @param {string} modelId - 模型 ID
|
||||
* @param {object} meta - 元信息
|
||||
*/
|
||||
generateImage: async (ctx, prompt, paths, modelId, meta) => {
|
||||
generate: async (ctx, prompt, paths, modelId, meta) => {
|
||||
if (!poolManager) {
|
||||
return { error: 'Pool 未初始化' };
|
||||
}
|
||||
return await poolManager.generateImage(ctx, prompt, paths, modelId, meta);
|
||||
return await poolManager.generate(ctx, prompt, paths, modelId, meta);
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
@@ -156,7 +156,7 @@ export class PoolManager {
|
||||
/**
|
||||
* 分发生图任务(支持故障转移)
|
||||
*/
|
||||
async generateImage(ctx, prompt, paths, modelId, meta) {
|
||||
async generate(ctx, prompt, paths, modelId, meta) {
|
||||
const failoverConfig = this.config.backend?.pool?.failover || {};
|
||||
const failoverEnabled = failoverConfig.enabled !== false;
|
||||
const maxRetries = failoverConfig.maxRetries || 2;
|
||||
@@ -213,7 +213,7 @@ export class PoolManager {
|
||||
*/
|
||||
async _safeExecuteWorker(worker, ctx, prompt, paths, modelId, meta) {
|
||||
try {
|
||||
return await worker.generateImage(ctx, prompt, paths, modelId, meta);
|
||||
return await worker.generate(ctx, prompt, paths, modelId, meta);
|
||||
} catch (err) {
|
||||
logger.error('工作池', `[${worker.name}] 执行异常`, { error: err.message, ...meta });
|
||||
return normalizeError(err.message || '执行异常');
|
||||
|
||||
@@ -240,12 +240,12 @@ export class Worker {
|
||||
/**
|
||||
* 生成图片
|
||||
*/
|
||||
async generateImage(ctx, prompt, paths, modelId, meta) {
|
||||
async generate(ctx, prompt, paths, modelId, meta) {
|
||||
const failoverConfig = this.globalConfig.backend?.pool?.failover || {};
|
||||
const failoverEnabled = failoverConfig.enabled !== false;
|
||||
|
||||
if (this.type === 'merge' && failoverEnabled) {
|
||||
return this._generateImageWithFailover(ctx, prompt, paths, modelId, meta, failoverConfig);
|
||||
return this._generateWithFailover(ctx, prompt, paths, modelId, meta, failoverConfig);
|
||||
}
|
||||
|
||||
const resolved = this.resolveModelId(modelId);
|
||||
@@ -261,7 +261,7 @@ export class Worker {
|
||||
* Merge 模式下的故障转移生成
|
||||
* @private
|
||||
*/
|
||||
async _generateImageWithFailover(ctx, prompt, paths, modelId, meta, failoverConfig = {}) {
|
||||
async _generateWithFailover(ctx, prompt, paths, modelId, meta, failoverConfig = {}) {
|
||||
const maxRetries = failoverConfig.maxRetries || 2;
|
||||
const candidateTypes = this._getCandidateTypes(modelId);
|
||||
|
||||
@@ -339,7 +339,7 @@ export class Worker {
|
||||
|
||||
this.busyCount++;
|
||||
try {
|
||||
return await adapter.generateImage(subContext, prompt, paths, realId, meta);
|
||||
return await adapter.generate(subContext, prompt, paths, realId, meta);
|
||||
} finally {
|
||||
this.busyCount--;
|
||||
}
|
||||
|
||||
@@ -89,8 +89,8 @@ class AdapterRegistry {
|
||||
errors.push('缺少 id 或类型不正确');
|
||||
}
|
||||
|
||||
if (!manifest.generateImage || typeof manifest.generateImage !== 'function') {
|
||||
errors.push('缺少 generateImage 函数');
|
||||
if (!manifest.generate || typeof manifest.generate !== 'function') {
|
||||
errors.push('缺少 generate 函数');
|
||||
}
|
||||
|
||||
if (!manifest.models || !Array.isArray(manifest.models)) {
|
||||
|
||||
Reference in New Issue
Block a user