Spaces:
Paused
Paused
| const os = require('os'); | |
| const zlib = require('zlib'); | |
| const crypto = require('crypto'); | |
| const { v4: uuidv4 } = require('uuid'); | |
| const $root = require('../proto/message.js'); | |
| function generateCursorBody(messages, modelName) { | |
| const instruction = messages | |
| .filter(msg => msg.role === 'system') | |
| .map(msg => msg.content) | |
| .join('\n') | |
| const formattedMessages = messages | |
| .filter(msg => msg.role !== 'system') | |
| .map(msg => ({ | |
| content: msg.content, | |
| role: msg.role === 'user' ? 1 : 2, | |
| messageId: uuidv4(), | |
| ...(msg.role === 'user' ? { chatModeEnum: 1 } : {}) | |
| //...(msg.role !== 'user' ? { summaryId: uuidv4() } : {}) | |
| })); | |
| const messageIds = formattedMessages.map(msg => { | |
| const { role, messageId, summaryId } = msg; | |
| return summaryId ? { role, messageId, summaryId } : { role, messageId }; | |
| }); | |
| const body = { | |
| request:{ | |
| messages: formattedMessages, | |
| unknown2: 1, | |
| instruction: { | |
| instruction: instruction | |
| }, | |
| unknown4: 1, | |
| model: { | |
| name: modelName, | |
| empty: '', | |
| }, | |
| webTool: "", | |
| unknown13: 1, | |
| cursorSetting: { | |
| name: "cursor\\aisettings", | |
| unknown3: "", | |
| unknown6: { | |
| unknwon1: "", | |
| unknown2: "" | |
| }, | |
| unknown8: 1, | |
| unknown9: 1 | |
| }, | |
| unknown19: 1, | |
| //unknown22: 1, | |
| conversationId: uuidv4(), | |
| metadata: { | |
| os: "win32", | |
| arch: "x64", | |
| version: "10.0.22631", | |
| path: "C:\\Program Files\\PowerShell\\7\\pwsh.exe", | |
| timestamp: new Date().toISOString(), | |
| }, | |
| unknown27: 0, | |
| //unknown29: "", | |
| messageIds: messageIds, | |
| largeContext: 0, | |
| unknown38: 0, | |
| chatModeEnum: 1, | |
| unknown47: "", | |
| unknown48: 0, | |
| unknown49: 0, | |
| unknown51: 0, | |
| unknown53: 1, | |
| chatMode: "Ask" | |
| } | |
| }; | |
| const errMsg = $root.StreamUnifiedChatWithToolsRequest.verify(body); | |
| if (errMsg) throw Error(errMsg); | |
| const instance = $root.StreamUnifiedChatWithToolsRequest.create(body); | |
| let buffer = $root.StreamUnifiedChatWithToolsRequest.encode(instance).finish(); | |
| let magicNumber = 0x00 | |
| if (formattedMessages.length >= 3){ | |
| buffer = zlib.gzipSync(buffer) | |
| magicNumber = 0x01 | |
| } | |
| const finalBody = Buffer.concat([ | |
| Buffer.from([magicNumber]), | |
| Buffer.from(buffer.length.toString(16).padStart(8, '0'), 'hex'), | |
| buffer | |
| ]) | |
| return finalBody | |
| } | |
| function chunkToUtf8String(chunk) { | |
| const results = [] | |
| const errorResults = { hasError: false, errorMessage: '' } | |
| const buffer = Buffer.from(chunk, 'hex'); | |
| //console.log("Chunk buffer:", buffer.toString('hex')) | |
| try { | |
| for(let i = 0; i < buffer.length; i++){ | |
| const magicNumber = parseInt(buffer.subarray(i, i + 1).toString('hex'), 16) | |
| const dataLength = parseInt(buffer.subarray(i + 1, i + 5).toString('hex'), 16) | |
| const data = buffer.subarray(i + 5, i + 5 + dataLength) | |
| //console.log("Parsed buffer:", magicNumber, dataLength, data.toString('hex')) | |
| if (magicNumber == 0 || magicNumber == 1) { | |
| const gunzipData = magicNumber == 0 ? data : zlib.gunzipSync(data) | |
| const response = $root.StreamUnifiedChatWithToolsResponse.decode(gunzipData); | |
| const thinking = response?.message?.thinking?.content | |
| if (thinking !== undefined){ | |
| results.push(thinking); | |
| //console.log(thinking); | |
| } | |
| const content = response?.message?.content | |
| if (content !== undefined){ | |
| results.push(content) | |
| //console.log(content) | |
| } | |
| } | |
| else if (magicNumber == 2 || magicNumber == 3) { | |
| // Json message | |
| const gunzipData = magicNumber == 2 ? data : zlib.gunzipSync(data) | |
| const utf8 = gunzipData.toString('utf-8') | |
| const message = JSON.parse(utf8) | |
| if (message != null && (typeof message !== 'object' || | |
| (Array.isArray(message) ? message.length > 0 : Object.keys(message).length > 0))){ | |
| //results.push(utf8) | |
| console.error(utf8) | |
| // 检查是否为错误消息 | |
| if (message && message.error) { | |
| errorResults.hasError = true; | |
| errorResults.errorMessage = utf8; | |
| } | |
| } | |
| } | |
| else { | |
| //console.log('Unknown magic number when parsing chunk response: ' + magicNumber) | |
| } | |
| i += 5 + dataLength - 1 | |
| } | |
| } catch (err) { | |
| console.log('Error parsing chunk response:', err) | |
| } | |
| // 如果存在错误,返回错误对象 | |
| if (errorResults.hasError) { | |
| return { error: errorResults.errorMessage }; | |
| } | |
| return results.join('') | |
| } | |
| function generateHashed64Hex(input, salt = '') { | |
| const hash = crypto.createHash('sha256'); | |
| hash.update(input + salt); | |
| return hash.digest('hex'); | |
| } | |
| function obfuscateBytes(byteArray) { | |
| let t = 165; | |
| for (let r = 0; r < byteArray.length; r++) { | |
| byteArray[r] = (byteArray[r] ^ t) + (r % 256); | |
| t = byteArray[r]; | |
| } | |
| return byteArray; | |
| } | |
| function generateCursorChecksum(token) { | |
| const machineId = generateHashed64Hex(token, 'machineId'); | |
| const macMachineId = generateHashed64Hex(token, 'macMachineId'); | |
| const timestamp = Math.floor(Date.now() / 1e6); | |
| const byteArray = new Uint8Array([ | |
| (timestamp >> 40) & 255, | |
| (timestamp >> 32) & 255, | |
| (timestamp >> 24) & 255, | |
| (timestamp >> 16) & 255, | |
| (timestamp >> 8) & 255, | |
| 255 & timestamp, | |
| ]); | |
| const obfuscatedBytes = obfuscateBytes(byteArray); | |
| const encodedChecksum = Buffer.from(obfuscatedBytes).toString('base64'); | |
| return `${encodedChecksum}${machineId}/${macMachineId}`; | |
| } | |
| module.exports = { | |
| generateCursorBody, | |
| chunkToUtf8String, | |
| generateHashed64Hex, | |
| generateCursorChecksum | |
| }; | |