xiao
初始化
6a37520
raw
history blame
9.16 kB
// src/bing-chat.ts
import crypto from "node:crypto";
import WebSocket from "ws";
// src/fetch.ts
var fetch = globalThis.fetch;
if (typeof fetch !== "function") {
throw new Error("Invalid environment: global fetch not defined");
}
// src/bing-chat.ts
var terminalChar = "";
var BingChat = class {
constructor(opts) {
const { cookie, debug = false } = opts;
this._cookie = cookie;
this._debug = !!debug;
if (!this._cookie) {
throw new Error("Bing cookie is required");
}
}
/**
* Sends a message to Bing Chat, waits for the response to resolve, and returns
* the response.
*
* If you want to receive a stream of partial responses, use `opts.onProgress`.
*
* @param message - The prompt message to send
* @param opts.conversationId - Optional ID of a conversation to continue (defaults to a random UUID)
* @param opts.onProgress - Optional callback which will be invoked every time the partial response is updated
*
* @returns The response from Bing Chat
*/
async sendMessage(text, opts = {}) {
const {
invocationId = "1",
onProgress,
locale = "en-US",
market = "en-US",
region = "US",
location,
messageType = "Chat",
variant = "Balanced",
} = opts;
let { conversationId, clientId, conversationSignature } = opts;
const isStartOfSession = !(
conversationId &&
clientId &&
conversationSignature
);
if (isStartOfSession) {
const conversation = await this.createConversation();
conversationId = conversation.conversationId;
clientId = conversation.clientId;
conversationSignature = conversation.conversationSignature;
}
const result = {
author: "bot",
id: crypto.randomUUID(),
conversationId,
clientId,
conversationSignature,
invocationId: `${parseInt(invocationId, 10) + 1}`,
text: "",
};
const responseP = new Promise(async (resolve, reject) => {
const chatWebsocketUrl = "wss://sydney.bing.com/sydney/ChatHub";
const ws = new WebSocket(chatWebsocketUrl, {
perMessageDeflate: false,
headers: {
"accept-language": "en-US,en;q=0.9",
"cache-control": "no-cache",
pragma: "no-cache",
},
});
let isFulfilled = false;
function cleanup() {
ws.close();
ws.removeAllListeners();
}
ws.on("error", (error) => {
console.warn("WebSocket error:", error);
cleanup();
if (!isFulfilled) {
isFulfilled = true;
reject(new Error(`WebSocket error: ${error.toString()}`));
}
});
ws.on("close", () => {});
ws.on("open", () => {
ws.send(`{"protocol":"json","version":1}${terminalChar}`);
});
let stage = 0;
ws.on("message", (data) => {
var _a, _b;
const objects = data.toString().split(terminalChar);
const messages = objects
.map((object) => {
try {
return JSON.parse(object);
} catch (error) {
return object;
}
})
.filter(Boolean);
if (!messages.length) {
return;
}
if (stage === 0) {
ws.send(`{"type":6}${terminalChar}`);
const traceId = crypto.randomBytes(16).toString("hex");
const locationStr = location
? `lat:${location.lat};long:${location.lng};re=${
location.re || "1000m"
};`
: void 0;
const optionsSets = [
"nlu_direct_response_filter",
"deepleo",
"enable_debug_commands",
"disable_emoji_spoken_text",
"responsible_ai_policy_235",
"enablemm",
"trffovrd",
"h3toppfp3",
"forcerep",
"cpcttl1d",
"dv3sugg",
];
if (variant == "Balanced") {
optionsSets.push("galileo");
optionsSets.push("glprompt");
} else if (variant == "Creative") {
optionsSets.push("h3imaginative");
optionsSets.push("gencontentv3");
} else if (variant == "Precise") {
optionsSets.push("h3precise");
}
const params = {
arguments: [
{
source: "cib",
optionsSets,
allowedMessageTypes: [
"Chat",
"InternalSearchQuery",
"InternalSearchResult",
"InternalLoaderMessage",
"RenderCardRequest",
"AdsQuery",
"SemanticSerp",
],
sliceIds: [],
traceId,
isStartOfSession,
message: {
locale,
market,
region,
location: locationStr,
author: "user",
inputMethod: "Keyboard",
messageType,
text,
},
conversationSignature,
participant: { id: clientId },
conversationId,
},
],
invocationId,
target: "chat",
type: 4,
};
if (this._debug) {
console.log(chatWebsocketUrl, JSON.stringify(params, null, 2));
}
ws.send(`${JSON.stringify(params)}${terminalChar}`);
++stage;
return;
}
for (const message of messages) {
if (message.type === 1) {
const update = message;
const msg =
(_a = update.arguments[0].messages) == null ? void 0 : _a[0];
if (!msg) continue;
if (!msg.messageType) {
result.author = msg.author;
result.text = msg.text;
result.detail = msg;
onProgress == null ? void 0 : onProgress(result);
}
} else if (message.type === 2) {
const response = message;
if (this._debug) {
console.log("RESPONSE", JSON.stringify(response, null, 2));
}
const validMessages =
(_b = response.item.messages) == null
? void 0
: _b.filter((m) => !m.messageType);
const lastMessage =
validMessages == null
? void 0
: validMessages[
(validMessages == null ? void 0 : validMessages.length) - 1
];
if (lastMessage) {
result.conversationId = response.item.conversationId;
result.conversationExpiryTime =
response.item.conversationExpiryTime;
result.author = lastMessage.author;
result.text = lastMessage.text;
result.detail = lastMessage;
if (!isFulfilled) {
isFulfilled = true;
resolve(result);
}
}
} else if (message.type === 3) {
if (!isFulfilled) {
isFulfilled = true;
resolve(result);
}
cleanup();
return;
} else {
}
}
});
});
return responseP;
}
async createConversation() {
const requestId = crypto.randomUUID();
const cookie = this._cookie.includes(";")
? this._cookie
: `_U=${this._cookie}`;
return fetch("https://www.bing.com/turing/conversation/create", {
headers: {
accept: "application/json",
"accept-language": "en-US,en;q=0.9",
"content-type": "application/json",
"sec-ch-ua":
'"Not_A Brand";v="99", "Microsoft Edge";v="109", "Chromium";v="109"',
"sec-ch-ua-arch": '"x86"',
"sec-ch-ua-bitness": '"64"',
"sec-ch-ua-full-version": '"109.0.1518.78"',
"sec-ch-ua-full-version-list":
'"Not_A Brand";v="99.0.0.0", "Microsoft Edge";v="109.0.1518.78", "Chromium";v="109.0.5414.120"',
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-model": "",
"sec-ch-ua-platform": '"macOS"',
"sec-ch-ua-platform-version": '"12.6.0"',
"sec-fetch-dest": "empty",
"sec-fetch-mode": "cors",
"sec-fetch-site": "same-origin",
"x-edge-shopping-flag": "1",
"x-ms-client-request-id": requestId,
"x-ms-useragent":
"azsdk-js-api-client-factory/1.0.0-beta.1 core-rest-pipeline/1.10.0 OS/MacIntel",
"x-forwarded-for": "1.1.1.1",
cookie,
},
referrer: "https://www.bing.com/search",
referrerPolicy: "origin-when-cross-origin",
body: null,
method: "GET",
mode: "cors",
credentials: "include",
}).then((res) => {
if (res.ok) {
return res.json();
} else {
throw new Error(
`unexpected HTTP error createConversation ${res.status}: ${res.statusText}`,
);
}
});
}
};
export { BingChat };
//# sourceMappingURL=index.js.map