From d639d29d6b50d32c8de9bd9c04a728db5cd9e919 Mon Sep 17 00:00:00 2001 From: josc146 Date: Sun, 15 Oct 2023 00:50:13 +0800 Subject: [PATCH] upgrade bing client (merge https://github.com/waylaidwanderer/node-chatgpt-api/pull/481) and some other adaptations (#505, #519, #525) --- src/background/index.mjs | 1 + src/services/apis/bing-web.mjs | 4 +-- src/services/apis/waylaidwanderer-api.mjs | 8 ++--- src/services/clients/bing/index.mjs | 38 ++++++++++++++++------- src/services/init-session.mjs | 4 +-- src/utils/fetch-bg.mjs | 1 + 6 files changed, 37 insertions(+), 19 deletions(-) diff --git a/src/background/index.mjs b/src/background/index.mjs index a396cc65..c38b11e3 100644 --- a/src/background/index.mjs +++ b/src/background/index.mjs @@ -216,6 +216,7 @@ Browser.runtime.onMessage.addListener(async (message, sender) => { body: text, status: response.status, statusText: response.statusText, + headers: Object.fromEntries(response.headers), }, null, ] diff --git a/src/services/apis/bing-web.mjs b/src/services/apis/bing-web.mjs index 46cba5e6..c1393ce9 100644 --- a/src/services/apis/bing-web.mjs +++ b/src/services/apis/bing-web.mjs @@ -46,7 +46,7 @@ export async function generateAnswersWithBingWebApi( ...(session.bingWeb_conversationId ? { conversationId: session.bingWeb_conversationId, - conversationSignature: session.bingWeb_conversationSignature, + encryptedConversationSignature: session.bingWeb_encryptedConversationSignature, clientId: session.bingWeb_clientId, invocationId: session.bingWeb_invocationId, } @@ -64,7 +64,7 @@ export async function generateAnswersWithBingWebApi( }) if (!sydneyMode) { - session.bingWeb_conversationSignature = response.conversationSignature + session.bingWeb_encryptedConversationSignature = response.encryptedConversationSignature session.bingWeb_conversationId = response.conversationId session.bingWeb_clientId = response.clientId session.bingWeb_invocationId = response.invocationId diff --git a/src/services/apis/waylaidwanderer-api.mjs b/src/services/apis/waylaidwanderer-api.mjs index c8c3053b..d3060348 100644 --- a/src/services/apis/waylaidwanderer-api.mjs +++ b/src/services/apis/waylaidwanderer-api.mjs @@ -23,9 +23,9 @@ export async function generateAnswersWithWaylaidwandererApi(port, question, sess body: JSON.stringify({ message: question, stream: true, - ...(session.bingWeb_conversationSignature && { + ...(session.bingWeb_encryptedConversationSignature && { conversationId: session.bingWeb_conversationId, - conversationSignature: session.bingWeb_conversationSignature, + encryptedConversationSignature: session.bingWeb_encryptedConversationSignature, clientId: session.bingWeb_clientId, invocationId: session.bingWeb_invocationId, }), @@ -51,8 +51,8 @@ export async function generateAnswersWithWaylaidwandererApi(port, question, sess } if (data.conversationId) session.conversationId = data.conversationId if (data.parentMessageId) session.parentMessageId = data.parentMessageId - if (data.conversationSignature) - session.bingWeb_conversationSignature = data.conversationSignature + if (data.encryptedConversationSignature) + session.bingWeb_encryptedConversationSignature = data.encryptedConversationSignature if (data.conversationId) session.bingWeb_conversationId = data.conversationId if (data.clientId) session.bingWeb_clientId = data.clientId if (data.invocationId) session.bingWeb_invocationId = data.invocationId diff --git a/src/services/clients/bing/index.mjs b/src/services/clients/bing/index.mjs index a780147c..b4ed126e 100644 --- a/src/services/clients/bing/index.mjs +++ b/src/services/clients/bing/index.mjs @@ -118,23 +118,33 @@ export default class BingAIClient { // } else { // fetchOptions.dispatcher = new Agent({ connect: { timeout: 20_000 } }) // } - const response = await fetchBg(`${this.options.host}/turing/conversation/create`, fetchOptions) + const response = await fetchBg( + `${this.options.host}/turing/conversation/create?bundleVersion=1.864.15`, + fetchOptions, + ) const body = await response.text() try { - return JSON.parse(body) + const res = JSON.parse(body) + res.encryptedConversationSignature = + response.headers.get('x-sydney-encryptedconversationsignature') ?? null + return res } catch (err) { throw new Error(`/turing/conversation/create: failed to parse response body.\n${body}`) } } - async createWebSocketConnection() { + async createWebSocketConnection(encryptedConversationSignature) { return new Promise((resolve, reject) => { // let agent // if (this.options.proxy) { // agent = new HttpsProxyAgent(this.options.proxy) // } - const ws = new WebSocket('wss://sydney.bing.com/sydney/ChatHub') + const ws = new WebSocket( + `wss://sydney.bing.com/sydney/ChatHub?sec_access_token=${encodeURIComponent( + encryptedConversationSignature, + )}`, + ) ws.onerror = (err) => { reject(err) @@ -201,7 +211,7 @@ export default class BingAIClient { let { jailbreakConversationId = false, // set to `true` for the first message to enable jailbreak mode conversationId, - conversationSignature, + encryptedConversationSignature, clientId, onProgress, } = opts @@ -219,13 +229,18 @@ export default class BingAIClient { onProgress = () => {} } - if (jailbreakConversationId || !conversationSignature || !conversationId || !clientId) { + if ( + jailbreakConversationId || + !encryptedConversationSignature || + !conversationId || + !clientId + ) { const createNewConversationResponse = await this.createNewConversation() if (this.debug) { console.debug(createNewConversationResponse) } if ( - !createNewConversationResponse.conversationSignature || + !createNewConversationResponse.encryptedConversationSignature || !createNewConversationResponse.conversationId || !createNewConversationResponse.clientId ) { @@ -240,7 +255,8 @@ export default class BingAIClient { ) } // eslint-disable-next-line - ;({ conversationSignature, conversationId, clientId } = createNewConversationResponse) + ;({ encryptedConversationSignature, conversationId, clientId } = + createNewConversationResponse) } // Due to this jailbreak, the AI will occasionally start responding as the user. It only happens rarely (and happens with the non-jailbroken Bing too), but since we are handling conversations ourselves now, we can use this system to ignore the part of the generated message that is replying as the user. @@ -319,7 +335,7 @@ export default class BingAIClient { conversation.messages.push(userMessage) } - const ws = await this.createWebSocketConnection() + const ws = await this.createWebSocketConnection(encryptedConversationSignature) ws.onerror = (error) => { console.error(error) @@ -367,7 +383,7 @@ export default class BingAIClient { : message, messageType: jailbreakConversationId ? 'SearchQuery' : 'Chat', }, - conversationSignature, + encryptedConversationSignature, participant: { id: clientId, }, @@ -604,7 +620,7 @@ export default class BingAIClient { const returnData = { conversationId, - conversationSignature, + encryptedConversationSignature, clientId, invocationId: invocationId + 1, conversationExpiryTime, diff --git a/src/services/init-session.mjs b/src/services/init-session.mjs index c5515bb8..909f1355 100644 --- a/src/services/init-session.mjs +++ b/src/services/init-session.mjs @@ -16,7 +16,7 @@ import { v4 as uuidv4 } from 'uuid' * @property {string|null} conversationId - chatGPT web mode * @property {string|null} messageId - chatGPT web mode * @property {string|null} parentMessageId - chatGPT web mode - * @property {string|null} bingWeb_conversationSignature + * @property {string|null} bingWeb_encryptedConversationSignature * @property {string|null} bingWeb_conversationId * @property {string|null} bingWeb_clientId * @property {string|null} bingWeb_invocationId @@ -64,7 +64,7 @@ export function initSession({ parentMessageId: null, // bing - bingWeb_conversationSignature: null, + bingWeb_encryptedConversationSignature: null, bingWeb_conversationId: null, bingWeb_clientId: null, bingWeb_invocationId: null, diff --git a/src/utils/fetch-bg.mjs b/src/utils/fetch-bg.mjs index 83e0bf5b..6d0cb52e 100644 --- a/src/utils/fetch-bg.mjs +++ b/src/utils/fetch-bg.mjs @@ -22,6 +22,7 @@ export function fetchBg(input, init) { new Response(body, { status: response.status, statusText: response.statusText, + headers: new Headers(response.headers), }), ) }