diff --git a/src/background/index.mjs b/src/background/index.mjs index 6fde2d48..601afa90 100644 --- a/src/background/index.mjs +++ b/src/background/index.mjs @@ -27,6 +27,7 @@ import { isUsingOllamaApiModel, isUsingAzureOpenAiApiModel, isUsingClaudeApiModel, + isUsingYouWebModel, isUsingChatGLMApiModel, isUsingGithubThirdPartyApiModel, isUsingGeminiWebModel, @@ -41,8 +42,10 @@ import { getBingAccessToken, getChatGptAccessToken, getClaudeSessionKey, + getYouSessionKey, registerPortListener, } from '../services/wrappers.mjs' +import { generateAnswersWithYouWebApi } from '../services/apis/you-web.mjs' import { refreshMenu } from './menus.mjs' import { registerCommands } from './commands.mjs' import { generateAnswersWithBardWebApi } from '../services/apis/bard-web.mjs' @@ -119,6 +122,9 @@ async function executeApi(session, port, config) { } else if (isUsingClaudeWebModel(session)) { const sessionKey = await getClaudeSessionKey() await generateAnswersWithClaudeWebApi(port, session.question, session, sessionKey) + } else if (isUsingYouWebModel(session)) { + const sessionKey = await getYouSessionKey() + await generateAnswersWithYouWebApi(port, session.question, session, sessionKey) } else if (isUsingMoonshotWebModel(session)) { await generateAnswersWithMoonshotWebApi(port, session.question, session, config) } else if (isUsingBingWebModel(session)) { diff --git a/src/config/index.mjs b/src/config/index.mjs index ecc1620e..a2766ef8 100644 --- a/src/config/index.mjs +++ b/src/config/index.mjs @@ -39,6 +39,33 @@ export const chatgptWebModelKeys = [ export const bingWebModelKeys = ['bingFree4', 'bingFreeSydney'] export const bardWebModelKeys = ['bardWebFree'] export const claudeWebModelKeys = ['claude2WebFree'] +export const youWebModelKeys = [ + 'create', + 'openai_o1', + 'openai_o1_preview', + 'openai_o1_mini', + 'gpt_4o_mini', + 'gpt_4o', + 'gpt_4_turbo', + 'gpt_4', + 'grok_2', + 'claude_3_5_sonnet', + 'claude_3_opus', + 'claude_3_sonnet', + 'claude_3_5_haiku', + 'llama3_3_70b', + 'llama3_2_90b', + 'llama3_1_405b', + 'mistral_large_2', + 'gemini_1_5_flash', + 'gemini_1_5_pro', + 'databricks_dbrx_instruct', + 'qwen2p5_72b', + 'qwen2p5_coder_32b', + 'command_r_plus', + 'solar_1_mini', + 'dolphin_2_5', +] export const moonshotWebModelKeys = ['moonshotWebFree'] export const gptApiModelKeys = ['gptApiInstruct', 'gptApiDavinci'] export const chatgptApiModelKeys = [ @@ -100,10 +127,14 @@ export const ModelGroups = { value: chatgptWebModelKeys, desc: 'ChatGPT (Web)', }, - claudeWebModelKeys: { + claudeWebModelKeys: { value: claudeWebModelKeys, desc: 'Claude.ai (Web)', }, + youWebModelKeys: { + value: youWebModelKeys, + desc: 'You.com (Web)', + }, moonshotWebModelKeys: { value: moonshotWebModelKeys, desc: 'Kimi.Moonshot (Web)', @@ -217,6 +248,8 @@ export const Models = { moonshotWebFree: { value: '', desc: 'Kimi.Moonshot (Web, 100k)' }, bardWebFree: { value: '', desc: 'Gemini (Web)' }, + youWebFree: { value: "", desc: "You.com (Web)" }, // Added You.com model + create: { value: "create", desc: "You.com (Web, Create Mode)" }, // Added You.com create model chatglmTurbo: { value: 'GLM-4-Air', desc: 'ChatGLM (GLM-4-Air, 128k)' }, chatglm4: { value: 'GLM-4-0520', desc: 'ChatGLM (GLM-4-0520, 128k)' }, @@ -233,6 +266,33 @@ export const Models = { gptApiInstruct: { value: 'gpt-3.5-turbo-instruct', desc: 'GPT-3.5-turbo Instruct' }, gptApiDavinci: { value: 'text-davinci-003', desc: 'GPT-3.5' }, + + create: { value: 'create', desc: 'YouWeb create' }, + openai_o1: { value: 'openai_o1', desc: 'YouWeb openai_o1' }, + openai_o1_preview: { value: 'openai_o1_preview', desc: 'YouWeb openai_o1_preview' }, + openai_o1_mini: { value: 'openai_o1_mini', desc: 'YouWeb openai_o1_mini' }, + gpt_4o_mini: { value: 'gpt_4o_mini', desc: 'YouWeb gpt_4o_mini' }, + gpt_4o: { value: 'gpt_4o', desc: 'YouWeb gpt_4o' }, + gpt_4_turbo: { value: 'gpt_4_turbo', desc: 'YouWeb gpt_4_turbo' }, + gpt_4: { value: 'gpt_4', desc: 'YouWeb gpt_4' }, + grok_2: { value: 'grok_2', desc: 'YouWeb grok_2' }, + claude_3_5_sonnet: { value: 'claude_3_5_sonnet', desc: 'YouWeb claude_3_5_sonnet' }, + claude_3_opus: { value: 'claude_3_opus', desc: 'YouWeb claude_3_opus' }, + claude_3_sonnet: { value: 'claude_3_sonnet', desc: 'YouWeb claude_3_sonnet' }, + claude_3_5_haiku: { value: 'claude_3_5_haiku', desc: 'YouWeb claude_3_5_haiku' }, + llama3_3_70b: { value: 'llama3_3_70b', desc: 'YouWeb llama3_3_70b' }, + llama3_2_90b: { value: 'llama3_2_90b', desc: 'YouWeb llama3_2_90b' }, + llama3_1_405b: { value: 'llama3_1_405b', desc: 'YouWeb llama3_1_405b' }, + mistral_large_2: { value: 'mistral_large_2', desc: 'YouWeb mistral_large_2' }, + gemini_1_5_flash: { value: 'gemini_1_5_flash', desc: 'YouWeb gemini_1_5_flash' }, + gemini_1_5_pro: { value: 'gemini_1_5_pro', desc: 'YouWeb gemini_1_5_pro' }, + databricks_dbrx_instruct: { value: 'databricks_dbrx_instruct', desc: 'YouWeb databricks_dbrx_instruct' }, + qwen2p5_72b: { value: 'qwen2p5_72b', desc: 'YouWeb qwen2p5_72b' }, + qwen2p5_coder_32b: { value: 'qwen2p5_coder_32b', desc: 'YouWeb qwen2p5_coder_32b' }, + command_r_plus: { value: 'command_r_plus', desc: 'YouWeb command_r_plus' }, + solar_1_mini: { value: 'solar_1_mini', desc: 'YouWeb solar_1_mini' }, + dolphin_2_5: { value: 'dolphin_2_5', desc: 'YouWeb dolphin_2_5' }, + customModel: { value: '', desc: 'Custom Model' }, ollamaModel: { value: '', desc: 'Ollama API' }, @@ -355,18 +415,31 @@ export const defaultConfig = { // It allows the content of activeApiModes to change with version updates when the user has not customized ApiModes. // If it were directly written into customApiModes, the value would become fixed, even if the user has not made any customizations. activeApiModes: [ - 'chatgptFree35', - 'chatgptFree4o', - 'chatgptApi35', - 'chatgptApi4o_128k', - 'claude2WebFree', - 'claude35SonnetApi', - 'bingFree4', - 'moonshotWebFree', - 'moonshot_v1_8k', - 'chatglmTurbo', - 'customModel', - 'azureOpenAi', + 'create', + 'openai_o1', + 'openai_o1_preview', + 'openai_o1_mini', + 'gpt_4o_mini', + 'gpt_4o', + 'gpt_4_turbo', + 'gpt_4', + 'grok_2', + 'claude_3_5_sonnet', + 'claude_3_opus', + 'claude_3_sonnet', + 'claude_3_5_haiku', + 'llama3_3_70b', + 'llama3_2_90b', + 'llama3_1_405b', + 'mistral_large_2', + 'gemini_1_5_flash', + 'gemini_1_5_pro', + 'databricks_dbrx_instruct', + 'qwen2p5_72b', + 'qwen2p5_coder_32b', + 'command_r_plus', + 'solar_1_mini', + 'dolphin_2_5', ], customApiModes: [ { @@ -470,6 +543,10 @@ export function isUsingClaudeWebModel(configOrSession) { return isInApiModeGroup(claudeWebModelKeys, configOrSession) } +export function isUsingYouWebModel(configOrSession) { + return isInApiModeGroup(youWebModelKeys, configOrSession) +} + export function isUsingMoonshotWebModel(configOrSession) { return isInApiModeGroup(moonshotWebModelKeys, configOrSession) } diff --git a/src/services/apis/you-web.mjs b/src/services/apis/you-web.mjs new file mode 100644 index 00000000..3a7475d1 --- /dev/null +++ b/src/services/apis/you-web.mjs @@ -0,0 +1,114 @@ +// path/to/services/apis/you-web.mjs + +import { pushRecord, setAbortController } from '../../services/apis/shared.mjs' +import { fetchSSE } from '../../utils/fetch-sse.mjs' +import { getUserConfig, youWebModelKeys } from '../../config/index.mjs' +import { getConversationPairs } from '../../utils/get-conversation-pairs.mjs' +import { getModelValue, isUsingModelName } from '../../utils/model-name-convert.mjs' + +/** + * @param {Runtime.Port} port + * @param {string} question + * @param {Session} session + * @param {string} sessionCookie + */ +export async function generateAnswersWithYouWebApi(port, question, session, sessionCookie) { + const { controller, cleanController } = setAbortController(port) + const config = await getUserConfig() + const model = getModelValue(session) + + const apiUrl = 'https://you.com/api/streamingSearch' + + // Use the existing chatId from the session or generate a new one + if (!session.chatId) { + session.chatId = generateUUID() // You need a function to generate UUIDs + } + + // Always include the conversation history + const conversationContext = getConversationPairs(session.conversationRecords, false) + + const traceId = `${session.chatId}|${session.messageId}|${new Date().toISOString()}` + + const params = new URLSearchParams() + params.append('page', '1') + params.append('count', '10') + params.append('safeSearch', 'Off') + params.append('q', question) + params.append('chatId', session.chatId) // Use the existing or new chatId + params.append('traceId', traceId) + params.append('conversationTurnId', session.messageId) + params.append('selectedAiModel', model) + + // Conditional chatMode based on modelName + let chatMode = 'custom' + if (isUsingModelName('create', session)) { + chatMode = 'create' + } + params.append('selectedChatMode', chatMode) + + params.append('pastChatLength', session.conversationRecords.length.toString()) + params.append('queryTraceId', traceId) + params.append('use_personalization_extraction', 'false') + params.append('domain', 'youchat') + params.append('mkt', 'en-US') + params.append('chat', JSON.stringify(conversationContext)) + + const url = `${apiUrl}?${params.toString()}` + + let answer = '' + + await fetchSSE(url, { + method: 'GET', + signal: controller.signal, + headers: { + 'Content-Type': 'text/event-stream;charset=utf-8', + Cookie: `sessionKey=${sessionCookie}`, + 'User-Agent': navigator.userAgent, + }, + onMessage(message) { + if (message.trim() === '[DONE]') { + finishMessage() + return + } + + let data + try { + data = JSON.parse(message) + } catch (error) { + console.error('SSE message parse error:', error) + return + } + + if (data.youChatToken) { + answer += data.youChatToken + port.postMessage({ answer: answer, done: false, session: null }) + } + }, + onStart() { + // Handle start if needed + }, + onEnd() { + finishMessage() + port.postMessage({ done: true }) + cleanController() + }, + onError(error) { + cleanController() + port.postMessage({ error: error.message, done: true }) + }, + }) + + function finishMessage() { + pushRecord(session, question, answer) + port.postMessage({ answer: answer, done: true, session: session }) + } +} + +// Helper function to generate UUIDs (you can use a library for this if you prefer) +function generateUUID() { + return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { + var r = (Math.random() * 16) | 0, + v = c == 'x' ? r : (r & 0x3) | 0x8 + return v.toString(16) + }) +} diff --git a/src/services/wrappers.mjs b/src/services/wrappers.mjs index c828f903..7cfd36ac 100644 --- a/src/services/wrappers.mjs +++ b/src/services/wrappers.mjs @@ -51,6 +51,10 @@ export async function getClaudeSessionKey() { return (await Browser.cookies.get({ url: 'https://claude.ai/', name: 'sessionKey' }))?.value } +export async function getYouSessionKey() { + return (await Browser.cookies.get({ url: 'https://you.com/', name: 'sessionKey' }))?.value +} + export function handlePortError(session, port, err) { console.error(err) if (err.message) {