| "use strict"; |
| var __create = Object.create; |
| var __defProp = Object.defineProperty; |
| var __getOwnPropDesc = Object.getOwnPropertyDescriptor; |
| var __getOwnPropNames = Object.getOwnPropertyNames; |
| var __getProtoOf = Object.getPrototypeOf; |
| var __hasOwnProp = Object.prototype.hasOwnProperty; |
| var __copyProps = (to, from, except, desc) => { |
| if (from && typeof from === "object" || typeof from === "function") { |
| for (let key of __getOwnPropNames(from)) |
| if (!__hasOwnProp.call(to, key) && key !== except) |
| __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); |
| } |
| return to; |
| }; |
| var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( |
| |
| |
| |
| |
| isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, |
| mod |
| )); |
|
|
| |
| var import_path = __toESM(require("path"), 1); |
| var import_fs_extra = __toESM(require("fs-extra"), 1); |
| var import_minimist = __toESM(require("minimist"), 1); |
| var import_lodash = __toESM(require("lodash"), 1); |
| var cmdArgs = (0, import_minimist.default)(process.argv.slice(2)); |
| var envVars = process.env; |
| var Environment = class { |
| |
| cmdArgs; |
| |
| envVars; |
| |
| env; |
| |
| name; |
| |
| host; |
| |
| port; |
| |
| package; |
| constructor(options = {}) { |
| const { cmdArgs: cmdArgs2, envVars: envVars2, package: _package } = options; |
| this.cmdArgs = cmdArgs2; |
| this.envVars = envVars2; |
| this.env = import_lodash.default.defaultTo(cmdArgs2.env || envVars2.SERVER_ENV, "dev"); |
| this.name = cmdArgs2.name || envVars2.SERVER_NAME || void 0; |
| this.host = cmdArgs2.host || envVars2.SERVER_HOST || void 0; |
| this.port = Number(cmdArgs2.port || envVars2.SERVER_PORT) ? Number(cmdArgs2.port || envVars2.SERVER_PORT) : void 0; |
| this.package = _package; |
| } |
| }; |
| var environment_default = new Environment({ |
| cmdArgs, |
| envVars, |
| package: JSON.parse(import_fs_extra.default.readFileSync(import_path.default.join(import_path.default.resolve(), "package.json")).toString()) |
| }); |
|
|
| |
| var import_path3 = __toESM(require("path"), 1); |
| var import_fs_extra3 = __toESM(require("fs-extra"), 1); |
| var import_yaml = __toESM(require("yaml"), 1); |
| var import_lodash3 = __toESM(require("lodash"), 1); |
|
|
| |
| var import_os = __toESM(require("os"), 1); |
| var import_path2 = __toESM(require("path"), 1); |
| var import_crypto = __toESM(require("crypto"), 1); |
| var import_stream = require("stream"); |
| var import_colors = require("colors"); |
| var import_mime = __toESM(require("mime"), 1); |
| var import_axios = __toESM(require("axios"), 1); |
| var import_fs_extra2 = __toESM(require("fs-extra"), 1); |
| var import_uuid = require("uuid"); |
| var import_date_fns = require("date-fns"); |
| var import_crc_32 = __toESM(require("crc-32"), 1); |
| var import_randomstring = __toESM(require("randomstring"), 1); |
| var import_lodash2 = __toESM(require("lodash"), 1); |
| var import_cron = require("cron"); |
|
|
| |
| var http_status_codes_default = { |
| CONTINUE: 100, |
| |
| SWITCHING_PROTOCOLS: 101, |
| |
| PROCESSING: 102, |
| |
| OK: 200, |
| |
| CREATED: 201, |
| |
| ACCEPTED: 202, |
| |
| NON_AUTHORITATIVE_INFO: 203, |
| |
| NO_CONTENT: 204, |
| |
| RESET_CONTENT: 205, |
| |
| PARTIAL_CONTENT: 206, |
| |
| MULTIPLE_STATUS: 207, |
| |
| MULTIPLE_CHOICES: 300, |
| |
| MOVED_PERMANENTLY: 301, |
| |
| FOUND: 302, |
| |
| SEE_OTHER: 303, |
| |
| NOT_MODIFIED: 304, |
| |
| USE_PROXY: 305, |
| |
| UNUSED: 306, |
| |
| TEMPORARY_REDIRECT: 307, |
| |
| BAD_REQUEST: 400, |
| |
| UNAUTHORIZED: 401, |
| |
| PAYMENT_REQUIRED: 402, |
| |
| FORBIDDEN: 403, |
| |
| NOT_FOUND: 404, |
| |
| METHOD_NOT_ALLOWED: 405, |
| |
| NO_ACCEPTABLE: 406, |
| |
| PROXY_AUTHENTICATION_REQUIRED: 407, |
| |
| REQUEST_TIMEOUT: 408, |
| |
| CONFLICT: 409, |
| |
| GONE: 410, |
| |
| LENGTH_REQUIRED: 411, |
| |
| PRECONDITION_FAILED: 412, |
| |
| REQUEST_ENTITY_TOO_LARGE: 413, |
| |
| REQUEST_URI_TOO_LONG: 414, |
| |
| UNSUPPORTED_MEDIA_TYPE: 415, |
| |
| REQUESTED_RANGE_NOT_SATISFIABLE: 416, |
| |
| EXPECTION_FAILED: 417, |
| |
| TOO_MANY_CONNECTIONS: 421, |
| |
| UNPROCESSABLE_ENTITY: 422, |
| |
| FAILED_DEPENDENCY: 424, |
| |
| UNORDERED_COLLECTION: 425, |
| |
| UPGRADE_REQUIRED: 426, |
| |
| RETRY_WITH: 449, |
| |
| INTERNAL_SERVER_ERROR: 500, |
| |
| NOT_IMPLEMENTED: 501, |
| |
| BAD_GATEWAY: 502, |
| |
| SERVICE_UNAVAILABLE: 503, |
| |
| GATEWAY_TIMEOUT: 504, |
| |
| HTTP_VERSION_NOT_SUPPORTED: 505, |
| |
| VARIANT_ALSO_NEGOTIATES: 506, |
| |
| INSUFFICIENT_STORAGE: 507, |
| |
| BANDWIDTH_LIMIT_EXCEEDED: 509, |
| |
| NOT_EXTENDED: 510 |
| |
| }; |
|
|
| |
| var autoIdMap = new Map(); |
| var util = { |
| is2DArrays(value) { |
| return import_lodash2.default.isArray(value) && (!value[0] || import_lodash2.default.isArray(value[0]) && import_lodash2.default.isArray(value[value.length - 1])); |
| }, |
| uuid: (separator = true) => separator ? (0, import_uuid.v1)() : (0, import_uuid.v1)().replace(/\-/g, ""), |
| autoId: (prefix = "") => { |
| let index = autoIdMap.get(prefix); |
| if (index > 999999) index = 0; |
| autoIdMap.set(prefix, (index || 0) + 1); |
| return `${prefix}${index || 1}`; |
| }, |
| ignoreJSONParse(value) { |
| const result = import_lodash2.default.attempt(() => JSON.parse(value)); |
| if (import_lodash2.default.isError(result)) return null; |
| return result; |
| }, |
| generateRandomString(options) { |
| return import_randomstring.default.generate(options); |
| }, |
| getResponseContentType(value) { |
| return value.headers ? value.headers["content-type"] || value.headers["Content-Type"] : null; |
| }, |
| mimeToExtension(value) { |
| let extension = import_mime.default.getExtension(value); |
| if (extension == "mpga") return "mp3"; |
| return extension; |
| }, |
| extractURLExtension(value) { |
| const extname = import_path2.default.extname(new URL(value).pathname); |
| return extname.substring(1).toLowerCase(); |
| }, |
| createCronJob(cronPatterns, callback) { |
| if (!import_lodash2.default.isFunction(callback)) |
| throw new Error("callback must be an Function"); |
| return new import_cron.CronJob( |
| cronPatterns, |
| () => callback(), |
| null, |
| false, |
| "Asia/Shanghai" |
| ); |
| }, |
| getDateString(format = "yyyy-MM-dd", date = new Date()) { |
| return (0, import_date_fns.format)(date, format); |
| }, |
| getIPAddressesByIPv4() { |
| const interfaces = import_os.default.networkInterfaces(); |
| const addresses = []; |
| for (let name in interfaces) { |
| const networks = interfaces[name]; |
| const results = networks.filter( |
| (network) => network.family === "IPv4" && network.address !== "127.0.0.1" && !network.internal |
| ); |
| if (results[0] && results[0].address) addresses.push(results[0].address); |
| } |
| return addresses; |
| }, |
| getMACAddressesByIPv4() { |
| const interfaces = import_os.default.networkInterfaces(); |
| const addresses = []; |
| for (let name in interfaces) { |
| const networks = interfaces[name]; |
| const results = networks.filter( |
| (network) => network.family === "IPv4" && network.address !== "127.0.0.1" && !network.internal |
| ); |
| if (results[0] && results[0].mac) addresses.push(results[0].mac); |
| } |
| return addresses; |
| }, |
| generateSSEData(event, data, retry) { |
| return `event: ${event || "message"} |
| data: ${(data || "").replace(/\n/g, "\\n").replace(/\s/g, "\\s")} |
| retry: ${retry || 3e3} |
| |
| `; |
| }, |
| buildDataBASE64(type, ext, buffer) { |
| return `data:${type}/${ext.replace("jpg", "jpeg")};base64,${buffer.toString( |
| "base64" |
| )}`; |
| }, |
| isLinux() { |
| return import_os.default.platform() !== "win32"; |
| }, |
| isIPAddress(value) { |
| return import_lodash2.default.isString(value) && (/^((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)$/.test( |
| value |
| ) || /\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*/.test( |
| value |
| )); |
| }, |
| isPort(value) { |
| return import_lodash2.default.isNumber(value) && value > 0 && value < 65536; |
| }, |
| isReadStream(value) { |
| return value && (value instanceof import_stream.Readable || "readable" in value || value.readable); |
| }, |
| isWriteStream(value) { |
| return value && (value instanceof import_stream.Writable || "writable" in value || value.writable); |
| }, |
| isHttpStatusCode(value) { |
| return import_lodash2.default.isNumber(value) && Object.values(http_status_codes_default).includes(value); |
| }, |
| isURL(value) { |
| return !import_lodash2.default.isUndefined(value) && /^(http|https)/.test(value); |
| }, |
| isSrc(value) { |
| return !import_lodash2.default.isUndefined(value) && /^\/.+\.[0-9a-zA-Z]+(\?.+)?$/.test(value); |
| }, |
| isBASE64(value) { |
| return !import_lodash2.default.isUndefined(value) && /^[a-zA-Z0-9\/\+]+(=?)+$/.test(value); |
| }, |
| isBASE64Data(value) { |
| return /^data:/.test(value); |
| }, |
| extractBASE64DataFormat(value) { |
| const match = value.trim().match(/^data:(.+);base64,/); |
| if (!match) return null; |
| return match[1]; |
| }, |
| removeBASE64DataHeader(value) { |
| return value.replace(/^data:(.+);base64,/, ""); |
| }, |
| isDataString(value) { |
| return /^(base64|json):/.test(value); |
| }, |
| isStringNumber(value) { |
| return import_lodash2.default.isFinite(Number(value)); |
| }, |
| isUnixTimestamp(value) { |
| return /^[0-9]{10}$/.test(`${value}`); |
| }, |
| isTimestamp(value) { |
| return /^[0-9]{13}$/.test(`${value}`); |
| }, |
| isEmail(value) { |
| return /^([a-zA-Z0-9]+[_|\_|\.]?)*[a-zA-Z0-9]+@([a-zA-Z0-9]+[_|\_|\.]?)*[a-zA-Z0-9]+\.[a-zA-Z]{2,3}$/.test( |
| value |
| ); |
| }, |
| isAsyncFunction(value) { |
| return Object.prototype.toString.call(value) === "[object AsyncFunction]"; |
| }, |
| async isAPNG(filePath) { |
| let head; |
| const readStream = import_fs_extra2.default.createReadStream(filePath, { start: 37, end: 40 }); |
| const readPromise = new Promise((resolve, reject) => { |
| readStream.once("end", resolve); |
| readStream.once("error", reject); |
| }); |
| readStream.once("data", (data) => head = data); |
| await readPromise; |
| return head.compare(Buffer.from([97, 99, 84, 76])) === 0; |
| }, |
| unixTimestamp() { |
| return parseInt(`${Date.now() / 1e3}`); |
| }, |
| timestamp() { |
| return Date.now(); |
| }, |
| urlJoin(...values) { |
| let url = ""; |
| for (let i = 0; i < values.length; i++) |
| url += `${i > 0 ? "/" : ""}${values[i].replace(/^\/*/, "").replace(/\/*$/, "")}`; |
| return url; |
| }, |
| millisecondsToHmss(milliseconds) { |
| if (import_lodash2.default.isString(milliseconds)) return milliseconds; |
| milliseconds = parseInt(milliseconds); |
| const sec = Math.floor(milliseconds / 1e3); |
| const hours = Math.floor(sec / 3600); |
| const minutes = Math.floor((sec - hours * 3600) / 60); |
| const seconds = sec - hours * 3600 - minutes * 60; |
| const ms = milliseconds % 6e4 - seconds * 1e3; |
| return `${hours > 9 ? hours : "0" + hours}:${minutes > 9 ? minutes : "0" + minutes}:${seconds > 9 ? seconds : "0" + seconds}.${ms}`; |
| }, |
| millisecondsToTimeString(milliseconds) { |
| if (milliseconds < 1e3) return `${milliseconds}ms`; |
| if (milliseconds < 6e4) |
| return `${parseFloat((milliseconds / 1e3).toFixed(2))}s`; |
| return `${Math.floor(milliseconds / 1e3 / 60)}m${Math.floor( |
| milliseconds / 1e3 % 60 |
| )}s`; |
| }, |
| rgbToHex(r, g, b) { |
| return ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1); |
| }, |
| hexToRgb(hex) { |
| const value = parseInt(hex.replace(/^#/, ""), 16); |
| return [value >> 16 & 255, value >> 8 & 255, value & 255]; |
| }, |
| md5(value) { |
| return import_crypto.default.createHash("md5").update(value).digest("hex"); |
| }, |
| crc32(value) { |
| return import_lodash2.default.isBuffer(value) ? import_crc_32.default.buf(value) : import_crc_32.default.str(value); |
| }, |
| arrayParse(value) { |
| return import_lodash2.default.isArray(value) ? value : [value]; |
| }, |
| booleanParse(value) { |
| return value === "true" || value === true ? true : false; |
| }, |
| encodeBASE64(value) { |
| return Buffer.from(value).toString("base64"); |
| }, |
| decodeBASE64(value) { |
| return Buffer.from(value, "base64").toString(); |
| }, |
| async fetchFileBASE64(url) { |
| const result = await import_axios.default.get(url, { |
| responseType: "arraybuffer" |
| }); |
| return result.data.toString("base64"); |
| } |
| }; |
| var util_default = util; |
|
|
| |
| var CONFIG_PATH = import_path3.default.join(import_path3.default.resolve(), "configs/", environment_default.env, "/service.yml"); |
| var ServiceConfig = class _ServiceConfig { |
| |
| name; |
| |
| host; |
| |
| port; |
| |
| urlPrefix; |
| |
| bindAddress; |
| constructor(options) { |
| const { name, host, port, urlPrefix, bindAddress } = options || {}; |
| this.name = import_lodash3.default.defaultTo(name, "deepseek-free-api"); |
| this.host = import_lodash3.default.defaultTo(host, "0.0.0.0"); |
| this.port = import_lodash3.default.defaultTo(port, 5566); |
| this.urlPrefix = import_lodash3.default.defaultTo(urlPrefix, ""); |
| this.bindAddress = bindAddress; |
| } |
| get addressHost() { |
| if (this.bindAddress) return this.bindAddress; |
| const ipAddresses = util_default.getIPAddressesByIPv4(); |
| for (let ipAddress of ipAddresses) { |
| if (ipAddress === this.host) |
| return ipAddress; |
| } |
| return ipAddresses[0] || "127.0.0.1"; |
| } |
| get address() { |
| return `${this.addressHost}:${this.port}`; |
| } |
| get pageDirUrl() { |
| return `http://127.0.0.1:${this.port}/page`; |
| } |
| get publicDirUrl() { |
| return `http://127.0.0.1:${this.port}/public`; |
| } |
| static load() { |
| const external = import_lodash3.default.pickBy(environment_default, (v, k) => ["name", "host", "port"].includes(k) && !import_lodash3.default.isUndefined(v)); |
| if (!import_fs_extra3.default.pathExistsSync(CONFIG_PATH)) return new _ServiceConfig(external); |
| const data = import_yaml.default.parse(import_fs_extra3.default.readFileSync(CONFIG_PATH).toString()); |
| return new _ServiceConfig({ ...data, ...external }); |
| } |
| }; |
| var service_config_default = ServiceConfig.load(); |
|
|
| |
| var import_path4 = __toESM(require("path"), 1); |
| var import_fs_extra4 = __toESM(require("fs-extra"), 1); |
| var import_yaml2 = __toESM(require("yaml"), 1); |
| var import_lodash4 = __toESM(require("lodash"), 1); |
| var CONFIG_PATH2 = import_path4.default.join(import_path4.default.resolve(), "configs/", environment_default.env, "/system.yml"); |
| var SystemConfig = class _SystemConfig { |
| |
| requestLog; |
| |
| tmpDir; |
| |
| logDir; |
| |
| logWriteInterval; |
| |
| logFileExpires; |
| |
| publicDir; |
| |
| tmpFileExpires; |
| |
| requestBody; |
| |
| debug; |
| constructor(options) { |
| const { requestLog, tmpDir, logDir, logWriteInterval, logFileExpires, publicDir, tmpFileExpires, requestBody, debug } = options || {}; |
| this.requestLog = import_lodash4.default.defaultTo(requestLog, false); |
| this.tmpDir = import_lodash4.default.defaultTo(tmpDir, "./tmp"); |
| this.logDir = import_lodash4.default.defaultTo(logDir, "./logs"); |
| this.logWriteInterval = import_lodash4.default.defaultTo(logWriteInterval, 200); |
| this.logFileExpires = import_lodash4.default.defaultTo(logFileExpires, 262656e4); |
| this.publicDir = import_lodash4.default.defaultTo(publicDir, "./public"); |
| this.tmpFileExpires = import_lodash4.default.defaultTo(tmpFileExpires, 864e5); |
| this.requestBody = Object.assign(requestBody || {}, { |
| enableTypes: ["json", "form", "text", "xml"], |
| encoding: "utf-8", |
| formLimit: "100mb", |
| jsonLimit: "100mb", |
| textLimit: "100mb", |
| xmlLimit: "100mb", |
| formidable: { |
| maxFileSize: "100mb" |
| }, |
| multipart: true, |
| parsedMethods: ["POST", "PUT", "PATCH"] |
| }); |
| this.debug = import_lodash4.default.defaultTo(debug, true); |
| } |
| get rootDirPath() { |
| return import_path4.default.resolve(); |
| } |
| get tmpDirPath() { |
| return import_path4.default.resolve(this.tmpDir); |
| } |
| get logDirPath() { |
| return import_path4.default.resolve(this.logDir); |
| } |
| get publicDirPath() { |
| return import_path4.default.resolve(this.publicDir); |
| } |
| static load() { |
| if (!import_fs_extra4.default.pathExistsSync(CONFIG_PATH2)) return new _SystemConfig(); |
| const data = import_yaml2.default.parse(import_fs_extra4.default.readFileSync(CONFIG_PATH2).toString()); |
| return new _SystemConfig(data); |
| } |
| }; |
| var system_config_default = SystemConfig.load(); |
|
|
| |
| var Config = class { |
| |
| service = service_config_default; |
| |
| system = system_config_default; |
| }; |
| var config_default = new Config(); |
|
|
| |
| var import_path5 = __toESM(require("path"), 1); |
| var import_util2 = __toESM(require("util"), 1); |
| var import_colors2 = require("colors"); |
| var import_lodash5 = __toESM(require("lodash"), 1); |
| var import_fs_extra5 = __toESM(require("fs-extra"), 1); |
| var import_date_fns2 = require("date-fns"); |
| var isVercelEnv = process.env.VERCEL; |
| var LogWriter = class { |
| #buffers = []; |
| constructor() { |
| !isVercelEnv && import_fs_extra5.default.ensureDirSync(config_default.system.logDirPath); |
| !isVercelEnv && this.work(); |
| } |
| push(content) { |
| const buffer = Buffer.from(content); |
| this.#buffers.push(buffer); |
| } |
| writeSync(buffer) { |
| !isVercelEnv && import_fs_extra5.default.appendFileSync(import_path5.default.join(config_default.system.logDirPath, `/${util_default.getDateString()}.log`), buffer); |
| } |
| async write(buffer) { |
| !isVercelEnv && await import_fs_extra5.default.appendFile(import_path5.default.join(config_default.system.logDirPath, `/${util_default.getDateString()}.log`), buffer); |
| } |
| flush() { |
| if (!this.#buffers.length) return; |
| !isVercelEnv && import_fs_extra5.default.appendFileSync(import_path5.default.join(config_default.system.logDirPath, `/${util_default.getDateString()}.log`), Buffer.concat(this.#buffers)); |
| } |
| work() { |
| if (!this.#buffers.length) return setTimeout(this.work.bind(this), config_default.system.logWriteInterval); |
| const buffer = Buffer.concat(this.#buffers); |
| this.#buffers = []; |
| this.write(buffer).finally(() => setTimeout(this.work.bind(this), config_default.system.logWriteInterval)).catch((err) => console.error("Log write error:", err)); |
| } |
| }; |
| var LogText = class { |
| |
| level; |
| |
| text; |
| |
| source; |
| |
| time = new Date(); |
| constructor(level, ...params) { |
| this.level = level; |
| this.text = import_util2.default.format.apply(null, params); |
| this.source = this.#getStackTopCodeInfo(); |
| } |
| #getStackTopCodeInfo() { |
| const unknownInfo = { name: "unknown", codeLine: 0, codeColumn: 0 }; |
| const stackArray = new Error().stack.split("\n"); |
| const text = stackArray[4]; |
| if (!text) |
| return unknownInfo; |
| const match = text.match(/at (.+) \((.+)\)/) || text.match(/at (.+)/); |
| if (!match || !import_lodash5.default.isString(match[2] || match[1])) |
| return unknownInfo; |
| const temp = match[2] || match[1]; |
| const _match = temp.match(/([a-zA-Z0-9_\-\.]+)\:(\d+)\:(\d+)$/); |
| if (!_match) |
| return unknownInfo; |
| const [, scriptPath, codeLine, codeColumn] = _match; |
| return { |
| name: scriptPath ? scriptPath.replace(/.js$/, "") : "unknown", |
| path: scriptPath || null, |
| codeLine: parseInt(codeLine || 0), |
| codeColumn: parseInt(codeColumn || 0) |
| }; |
| } |
| toString() { |
| return `[${(0, import_date_fns2.format)(this.time, "yyyy-MM-dd HH:mm:ss.SSS")}][${this.level}][${this.source.name}<${this.source.codeLine},${this.source.codeColumn}>] ${this.text}`; |
| } |
| }; |
| var Logger = class _Logger { |
| |
| config = {}; |
| |
| static Level = { |
| Success: "success", |
| Info: "info", |
| Log: "log", |
| Debug: "debug", |
| Warning: "warning", |
| Error: "error", |
| Fatal: "fatal" |
| }; |
| |
| static LevelColor = { |
| [_Logger.Level.Success]: "green", |
| [_Logger.Level.Info]: "brightCyan", |
| [_Logger.Level.Debug]: "white", |
| [_Logger.Level.Warning]: "brightYellow", |
| [_Logger.Level.Error]: "brightRed", |
| [_Logger.Level.Fatal]: "red" |
| }; |
| #writer; |
| constructor() { |
| this.#writer = new LogWriter(); |
| } |
| header() { |
| this.#writer.writeSync(Buffer.from(` |
| |
| ===================== LOG START ${(0, import_date_fns2.format)(/* @__PURE__ */ new Date(), "yyyy-MM-dd HH:mm:ss.SSS")} ===================== |
| |
| `)); |
| } |
| footer() { |
| this.#writer.flush(); |
| this.#writer.writeSync(Buffer.from(` |
| |
| ===================== LOG END ${(0, import_date_fns2.format)(/* @__PURE__ */ new Date(), "yyyy-MM-dd HH:mm:ss.SSS")} ===================== |
| |
| `)); |
| } |
| success(...params) { |
| const content = new LogText(_Logger.Level.Success, ...params).toString(); |
| console.info(content[_Logger.LevelColor[_Logger.Level.Success]]); |
| this.#writer.push(content + "\n"); |
| } |
| info(...params) { |
| const content = new LogText(_Logger.Level.Info, ...params).toString(); |
| console.info(content[_Logger.LevelColor[_Logger.Level.Info]]); |
| this.#writer.push(content + "\n"); |
| } |
| log(...params) { |
| const content = new LogText(_Logger.Level.Log, ...params).toString(); |
| console.log(content[_Logger.LevelColor[_Logger.Level.Log]]); |
| this.#writer.push(content + "\n"); |
| } |
| debug(...params) { |
| if (!config_default.system.debug) return; |
| const content = new LogText(_Logger.Level.Debug, ...params).toString(); |
| console.debug(content[_Logger.LevelColor[_Logger.Level.Debug]]); |
| this.#writer.push(content + "\n"); |
| } |
| warn(...params) { |
| const content = new LogText(_Logger.Level.Warning, ...params).toString(); |
| console.warn(content[_Logger.LevelColor[_Logger.Level.Warning]]); |
| this.#writer.push(content + "\n"); |
| } |
| error(...params) { |
| const content = new LogText(_Logger.Level.Error, ...params).toString(); |
| console.error(content[_Logger.LevelColor[_Logger.Level.Error]]); |
| this.#writer.push(content); |
| } |
| fatal(...params) { |
| const content = new LogText(_Logger.Level.Fatal, ...params).toString(); |
| console.error(content[_Logger.LevelColor[_Logger.Level.Fatal]]); |
| this.#writer.push(content); |
| } |
| destory() { |
| this.#writer.destory(); |
| } |
| }; |
| var logger_default = new Logger(); |
|
|
| |
| process.setMaxListeners(Infinity); |
| process.on("uncaughtException", (err, origin) => { |
| logger_default.error(`An unhandled error occurred: ${origin}`, err); |
| }); |
| process.on("unhandledRejection", (_15, promise) => { |
| promise.catch((err) => logger_default.error("An unhandled rejection occurred:", err)); |
| }); |
| process.on("warning", (warning) => logger_default.warn("System warning: ", warning)); |
| process.on("exit", () => { |
| logger_default.info("Service exit"); |
| logger_default.footer(); |
| }); |
| process.on("SIGTERM", () => { |
| logger_default.warn("received kill signal"); |
| process.exit(2); |
| }); |
| process.on("SIGINT", () => { |
| process.exit(0); |
| }); |
|
|
| |
| var import_koa = __toESM(require("koa"), 1); |
| var import_koa_router = __toESM(require("koa-router"), 1); |
| var import_koa_range = __toESM(require("koa-range"), 1); |
| var import_koa2_cors = __toESM(require("koa2-cors"), 1); |
| var import_koa_body = __toESM(require("koa-body"), 1); |
| var import_lodash11 = __toESM(require("lodash"), 1); |
|
|
| |
| var import_lodash7 = __toESM(require("lodash"), 1); |
|
|
| |
| var import_assert = __toESM(require("assert"), 1); |
| var import_lodash6 = __toESM(require("lodash"), 1); |
| var Exception = class extends Error { |
| |
| errcode; |
| |
| errmsg; |
| |
| data; |
| |
| httpStatusCode; |
| |
| |
| |
| |
| |
| |
| constructor(exception, _errmsg) { |
| (0, import_assert.default)(import_lodash6.default.isArray(exception), "Exception must be Array"); |
| const [errcode, errmsg] = exception; |
| (0, import_assert.default)(import_lodash6.default.isFinite(errcode), "Exception errcode invalid"); |
| (0, import_assert.default)(import_lodash6.default.isString(errmsg), "Exception errmsg invalid"); |
| super(_errmsg || errmsg); |
| this.errcode = errcode; |
| this.errmsg = _errmsg || errmsg; |
| } |
| compare(exception) { |
| const [errcode] = exception; |
| return this.errcode == errcode; |
| } |
| setHTTPStatusCode(value) { |
| this.httpStatusCode = value; |
| return this; |
| } |
| setData(value) { |
| this.data = import_lodash6.default.defaultTo(value, null); |
| return this; |
| } |
| }; |
|
|
| |
| var APIException = class extends Exception { |
| |
| |
| |
| |
| |
| constructor(exception, errmsg) { |
| super(exception, errmsg); |
| } |
| }; |
|
|
| |
| var exceptions_default = { |
| API_TEST: [-9999, "API\u5F02\u5E38\u9519\u8BEF"], |
| API_REQUEST_PARAMS_INVALID: [-2e3, "\u8BF7\u6C42\u53C2\u6570\u975E\u6CD5"], |
| API_REQUEST_FAILED: [-2001, "\u8BF7\u6C42\u5931\u8D25"], |
| API_TOKEN_EXPIRES: [-2002, "Token\u5DF2\u5931\u6548"], |
| API_FILE_URL_INVALID: [-2003, "\u8FDC\u7A0B\u6587\u4EF6URL\u975E\u6CD5"], |
| API_FILE_EXECEEDS_SIZE: [-2004, "\u8FDC\u7A0B\u6587\u4EF6\u8D85\u51FA\u5927\u5C0F"], |
| API_CHAT_STREAM_PUSHING: [-2005, "\u5DF2\u6709\u5BF9\u8BDD\u6D41\u6B63\u5728\u8F93\u51FA"], |
| API_CONTENT_FILTERED: [-2006, "\u5185\u5BB9\u7531\u4E8E\u5408\u89C4\u95EE\u9898\u5DF2\u88AB\u963B\u6B62\u751F\u6210"], |
| API_IMAGE_GENERATION_FAILED: [-2007, "\u56FE\u50CF\u751F\u6210\u5931\u8D25"] |
| }; |
|
|
| |
| var Request = class { |
| |
| method; |
| |
| url; |
| |
| path; |
| |
| type; |
| |
| headers; |
| |
| search; |
| |
| query; |
| |
| params; |
| |
| body; |
| |
| files; |
| |
| remoteIP; |
| |
| time; |
| constructor(ctx, options = {}) { |
| const { time } = options; |
| this.method = ctx.request.method; |
| this.url = ctx.request.url; |
| this.path = ctx.request.path; |
| this.type = ctx.request.type; |
| this.headers = ctx.request.headers || {}; |
| this.search = ctx.request.search; |
| this.query = ctx.query || {}; |
| this.params = ctx.params || {}; |
| this.body = ctx.request.body || {}; |
| this.files = ctx.request.files || {}; |
| this.remoteIP = this.headers["X-Real-IP"] || this.headers["x-real-ip"] || this.headers["X-Forwarded-For"] || this.headers["x-forwarded-for"] || ctx.ip || null; |
| this.time = Number(import_lodash7.default.defaultTo(time, util_default.timestamp())); |
| } |
| validate(key, fn) { |
| try { |
| const value = import_lodash7.default.get(this, key); |
| if (fn) { |
| if (fn(value) === false) |
| throw `[Mismatch] -> ${fn}`; |
| } else if (import_lodash7.default.isUndefined(value)) |
| throw "[Undefined]"; |
| } catch (err) { |
| logger_default.warn(`Params ${key} invalid:`, err); |
| throw new APIException(exceptions_default.API_REQUEST_PARAMS_INVALID, `Params ${key} invalid`); |
| } |
| return this; |
| } |
| }; |
|
|
| |
| var import_mime2 = __toESM(require("mime"), 1); |
| var import_lodash9 = __toESM(require("lodash"), 1); |
|
|
| |
| var import_lodash8 = __toESM(require("lodash"), 1); |
| var Body = class _Body { |
| |
| code; |
| |
| message; |
| |
| data; |
| |
| statusCode; |
| constructor(options = {}) { |
| const { code, message, data, statusCode } = options; |
| this.code = Number(import_lodash8.default.defaultTo(code, 0)); |
| this.message = import_lodash8.default.defaultTo(message, "OK"); |
| this.data = import_lodash8.default.defaultTo(data, null); |
| this.statusCode = Number(import_lodash8.default.defaultTo(statusCode, 200)); |
| } |
| toObject() { |
| return { |
| code: this.code, |
| message: this.message, |
| data: this.data |
| }; |
| } |
| static isInstance(value) { |
| return value instanceof _Body; |
| } |
| }; |
|
|
| |
| var Response = class _Response { |
| |
| statusCode; |
| |
| type; |
| |
| headers; |
| |
| redirect; |
| |
| body; |
| |
| size; |
| |
| time; |
| constructor(body, options = {}) { |
| const { statusCode, type, headers, redirect, size, time } = options; |
| this.statusCode = Number(import_lodash9.default.defaultTo(statusCode, Body.isInstance(body) ? body.statusCode : void 0)); |
| this.type = type; |
| this.headers = headers; |
| this.redirect = redirect; |
| this.size = size; |
| this.time = Number(import_lodash9.default.defaultTo(time, util_default.timestamp())); |
| this.body = body; |
| } |
| injectTo(ctx) { |
| this.redirect && ctx.redirect(this.redirect); |
| this.statusCode && (ctx.status = this.statusCode); |
| this.type && (ctx.type = import_mime2.default.getType(this.type) || this.type); |
| const headers = this.headers || {}; |
| if (this.size && !headers["Content-Length"] && !headers["content-length"]) |
| headers["Content-Length"] = this.size; |
| ctx.set(headers); |
| if (Body.isInstance(this.body)) |
| ctx.body = this.body.toObject(); |
| else |
| ctx.body = this.body; |
| } |
| static isInstance(value) { |
| return value instanceof _Response; |
| } |
| }; |
|
|
| |
| var import_lodash10 = __toESM(require("lodash"), 1); |
|
|
| |
| var exceptions_default2 = { |
| SYSTEM_ERROR: [-1e3, "\u7CFB\u7EDF\u5F02\u5E38"], |
| SYSTEM_REQUEST_VALIDATION_ERROR: [-1001, "\u8BF7\u6C42\u53C2\u6570\u6821\u9A8C\u9519\u8BEF"], |
| SYSTEM_NOT_ROUTE_MATCHING: [-1002, "\u65E0\u5339\u914D\u7684\u8DEF\u7531"] |
| }; |
|
|
| |
| var FailureBody = class _FailureBody extends Body { |
| constructor(error, _data) { |
| let errcode, errmsg, data = _data, httpStatusCode = http_status_codes_default.OK; |
| ; |
| if (import_lodash10.default.isString(error)) |
| error = new Exception(exceptions_default2.SYSTEM_ERROR, error); |
| else if (error instanceof APIException || error instanceof Exception) |
| ({ errcode, errmsg, data, httpStatusCode } = error); |
| else if (import_lodash10.default.isError(error)) |
| ({ errcode, errmsg, data, httpStatusCode } = new Exception(exceptions_default2.SYSTEM_ERROR, error.message)); |
| super({ |
| code: errcode || -1, |
| message: errmsg || "Internal error", |
| data, |
| statusCode: httpStatusCode |
| }); |
| } |
| static isInstance(value) { |
| return value instanceof _FailureBody; |
| } |
| }; |
|
|
| |
| var Server = class { |
| app; |
| router; |
| constructor() { |
| this.app = new import_koa.default(); |
| this.app.use((0, import_koa2_cors.default)()); |
| this.app.use(import_koa_range.default); |
| this.router = new import_koa_router.default({ prefix: config_default.service.urlPrefix }); |
| this.app.use(async (ctx, next) => { |
| if (ctx.request.type === "application/xml" || ctx.request.type === "application/ssml+xml") |
| ctx.req.headers["content-type"] = "text/xml"; |
| try { |
| await next(); |
| } catch (err) { |
| logger_default.error(err); |
| const failureBody = new FailureBody(err); |
| new Response(failureBody).injectTo(ctx); |
| } |
| }); |
| this.app.use((0, import_koa_body.default)(import_lodash11.default.clone(config_default.system.requestBody))); |
| this.app.on("error", (err) => { |
| if (["ECONNRESET", "ECONNABORTED", "EPIPE", "ECANCELED"].includes(err.code)) return; |
| logger_default.error(err); |
| }); |
| logger_default.success("Server initialized"); |
| } |
| |
| |
| |
| |
| |
| attachRoutes(routes) { |
| routes.forEach((route) => { |
| const prefix = route.prefix || ""; |
| for (let method in route) { |
| if (method === "prefix") continue; |
| if (!import_lodash11.default.isObject(route[method])) { |
| logger_default.warn(`Router ${prefix} ${method} invalid`); |
| continue; |
| } |
| for (let uri in route[method]) { |
| this.router[method](`${prefix}${uri}`, async (ctx) => { |
| const { request, response } = await this.#requestProcessing(ctx, route[method][uri]); |
| if (response != null && config_default.system.requestLog) |
| logger_default.info(`<- ${request.method} ${request.url} ${response.time - request.time}ms`); |
| }); |
| } |
| } |
| logger_default.info(`Route ${config_default.service.urlPrefix || ""}${prefix} attached`); |
| }); |
| this.app.use(this.router.routes()); |
| this.app.use((ctx) => { |
| const request = new Request(ctx); |
| logger_default.debug(`-> ${ctx.request.method} ${ctx.request.url} request is not supported - ${request.remoteIP || "unknown"}`); |
| const message = `[\u8BF7\u6C42\u6709\u8BEF]: \u6B63\u786E\u8BF7\u6C42\u4E3A POST -> /v1/chat/completions\uFF0C\u5F53\u524D\u8BF7\u6C42\u4E3A ${ctx.request.method} -> ${ctx.request.url} \u8BF7\u7EA0\u6B63`; |
| logger_default.warn(message); |
| const failureBody = new FailureBody(new Error(message)); |
| const response = new Response(failureBody); |
| response.injectTo(ctx); |
| if (config_default.system.requestLog) |
| logger_default.info(`<- ${request.method} ${request.url} ${response.time - request.time}ms`); |
| }); |
| } |
| |
| |
| |
| |
| |
| |
| #requestProcessing(ctx, routeFn) { |
| return new Promise((resolve) => { |
| const request = new Request(ctx); |
| try { |
| if (config_default.system.requestLog) |
| logger_default.info(`-> ${request.method} ${request.url}`); |
| routeFn(request).then((response) => { |
| try { |
| if (!Response.isInstance(response)) { |
| const _response = new Response(response); |
| _response.injectTo(ctx); |
| return resolve({ request, response: _response }); |
| } |
| response.injectTo(ctx); |
| resolve({ request, response }); |
| } catch (err) { |
| logger_default.error(err); |
| const failureBody = new FailureBody(err); |
| const response2 = new Response(failureBody); |
| response2.injectTo(ctx); |
| resolve({ request, response: response2 }); |
| } |
| }).catch((err) => { |
| try { |
| logger_default.error(err); |
| const failureBody = new FailureBody(err); |
| const response = new Response(failureBody); |
| response.injectTo(ctx); |
| resolve({ request, response }); |
| } catch (err2) { |
| logger_default.error(err2); |
| const failureBody = new FailureBody(err2); |
| const response = new Response(failureBody); |
| response.injectTo(ctx); |
| resolve({ request, response }); |
| } |
| }); |
| } catch (err) { |
| logger_default.error(err); |
| const failureBody = new FailureBody(err); |
| const response = new Response(failureBody); |
| response.injectTo(ctx); |
| resolve({ request, response }); |
| } |
| }); |
| } |
| |
| |
| |
| async listen() { |
| const host = config_default.service.host; |
| const port = config_default.service.port; |
| await Promise.all([ |
| new Promise((resolve, reject) => { |
| if (host === "0.0.0.0" || host === "localhost" || host === "127.0.0.1") |
| return resolve(null); |
| this.app.listen(port, "localhost", (err) => { |
| if (err) return reject(err); |
| resolve(null); |
| }); |
| }), |
| new Promise((resolve, reject) => { |
| this.app.listen(port, host, (err) => { |
| if (err) return reject(err); |
| resolve(null); |
| }); |
| }) |
| ]); |
| logger_default.success(`Server listening on port ${port} (${host})`); |
| } |
| }; |
| var server_default = new Server(); |
|
|
| |
| var import_fs_extra6 = __toESM(require("fs-extra"), 1); |
|
|
| |
| var import_lodash13 = __toESM(require("lodash"), 1); |
|
|
| |
| var import_stream2 = require("stream"); |
| var import_lodash12 = __toESM(require("lodash"), 1); |
| var import_async_lock = __toESM(require("async-lock"), 1); |
| var import_axios2 = __toESM(require("axios"), 1); |
| var import_eventsource_parser = require("eventsource-parser"); |
| var MODEL_NAME = "deepseek-chat"; |
| var ACCESS_TOKEN_EXPIRES = 3600; |
| var MAX_RETRY_COUNT = 3; |
| var RETRY_DELAY = 5e3; |
| var FAKE_HEADERS = { |
| Accept: "*/*", |
| "Accept-Encoding": "gzip, deflate, br, zstd", |
| "Accept-Language": "zh-CN,zh;q=0.9", |
| Origin: "https://chat.deepseek.com", |
| Pragma: "no-cache", |
| Referer: "https://chat.deepseek.com/", |
| "Sec-Ch-Ua": '"Chromium";v="124", "Google Chrome";v="124", "Not-A.Brand";v="99"', |
| "Sec-Ch-Ua-Mobile": "?0", |
| "Sec-Ch-Ua-Platform": '"Windows"', |
| "Sec-Fetch-Dest": "empty", |
| "Sec-Fetch-Mode": "cors", |
| "Sec-Fetch-Site": "same-origin", |
| "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36", |
| "X-App-Version": "20240126.0" |
| }; |
| var accessTokenMap = new Map(); |
| var accessTokenRequestQueueMap = {}; |
| var chatLock = new import_async_lock.default(); |
| async function requestToken(refreshToken) { |
| if (accessTokenRequestQueueMap[refreshToken]) |
| return new Promise( |
| (resolve) => accessTokenRequestQueueMap[refreshToken].push(resolve) |
| ); |
| accessTokenRequestQueueMap[refreshToken] = []; |
| logger_default.info(`Refresh token: ${refreshToken}`); |
| const result = await (async () => { |
| const result2 = await import_axios2.default.get( |
| "https://chat.deepseek.com/api/v0/users/current", |
| { |
| headers: { |
| Authorization: `Bearer ${refreshToken}`, |
| ...FAKE_HEADERS |
| }, |
| timeout: 15e3, |
| validateStatus: () => true |
| } |
| ); |
| const { token } = checkResult(result2, refreshToken); |
| return { |
| accessToken: token, |
| refreshToken: token, |
| refreshTime: util_default.unixTimestamp() + ACCESS_TOKEN_EXPIRES |
| }; |
| })().then((result2) => { |
| if (accessTokenRequestQueueMap[refreshToken]) { |
| accessTokenRequestQueueMap[refreshToken].forEach( |
| (resolve) => resolve(result2) |
| ); |
| delete accessTokenRequestQueueMap[refreshToken]; |
| } |
| logger_default.success(`Refresh successful`); |
| return result2; |
| }).catch((err) => { |
| if (accessTokenRequestQueueMap[refreshToken]) { |
| accessTokenRequestQueueMap[refreshToken].forEach( |
| (resolve) => resolve(err) |
| ); |
| delete accessTokenRequestQueueMap[refreshToken]; |
| } |
| return err; |
| }); |
| if (import_lodash12.default.isError(result)) throw result; |
| return result; |
| } |
| async function acquireToken(refreshToken) { |
| let result = accessTokenMap.get(refreshToken); |
| if (!result) { |
| result = await requestToken(refreshToken); |
| accessTokenMap.set(refreshToken, result); |
| } |
| if (util_default.unixTimestamp() > result.refreshTime) { |
| result = await requestToken(refreshToken); |
| accessTokenMap.set(refreshToken, result); |
| } |
| return result.accessToken; |
| } |
| async function clearContext(model, refreshToken) { |
| const token = await acquireToken(refreshToken); |
| const result = await import_axios2.default.post( |
| "https://chat.deepseek.com/api/v0/chat/clear_context", |
| { |
| model_class: model, |
| append_welcome_message: false |
| }, |
| { |
| headers: { |
| Authorization: `Bearer ${token}`, |
| ...FAKE_HEADERS |
| }, |
| timeout: 15e3, |
| validateStatus: () => true |
| } |
| ); |
| checkResult(result, refreshToken); |
| } |
| async function createCompletion(model = MODEL_NAME, messages, refreshToken, retryCount = 0) { |
| return (async () => { |
| logger_default.info(messages); |
| const result = await chatLock.acquire(refreshToken, async () => { |
| await clearContext(model, refreshToken); |
| const token = await acquireToken(refreshToken); |
| return await import_axios2.default.post( |
| "https://chat.deepseek.com/api/v0/chat/completions", |
| { |
| message: messagesPrepare(messages), |
| stream: true, |
| model_preference: null, |
| model_class: model, |
| temperature: 0 |
| }, |
| { |
| headers: { |
| Authorization: `Bearer ${token}`, |
| ...FAKE_HEADERS |
| }, |
| |
| timeout: 12e4, |
| validateStatus: () => true, |
| responseType: "stream" |
| } |
| ); |
| }); |
| if (result.headers["content-type"].indexOf("text/event-stream") == -1) { |
| result.data.on("data", (buffer) => logger_default.error(buffer.toString())); |
| throw new APIException( |
| exceptions_default.API_REQUEST_FAILED, |
| `Stream response Content-Type invalid: ${result.headers["content-type"]}` |
| ); |
| } |
| const streamStartTime = util_default.timestamp(); |
| const answer = await receiveStream(model, result.data); |
| logger_default.success( |
| `Stream has completed transfer ${util_default.timestamp() - streamStartTime}ms` |
| ); |
| return answer; |
| })().catch((err) => { |
| if (retryCount < MAX_RETRY_COUNT) { |
| logger_default.error(`Stream response error: ${err.stack}`); |
| logger_default.warn(`Try again after ${RETRY_DELAY / 1e3}s...`); |
| return (async () => { |
| await new Promise((resolve) => setTimeout(resolve, RETRY_DELAY)); |
| return createCompletion( |
| model, |
| messages, |
| refreshToken, |
| retryCount + 1 |
| ); |
| })(); |
| } |
| throw err; |
| }); |
| } |
| async function createCompletionStream(model = MODEL_NAME, messages, refreshToken, retryCount = 0) { |
| return (async () => { |
| logger_default.info(messages); |
| const result = await chatLock.acquire(refreshToken, async () => { |
| await clearContext(model, refreshToken); |
| const token = await acquireToken(refreshToken); |
| return await import_axios2.default.post( |
| "https://chat.deepseek.com/api/v0/chat/completions", |
| { |
| message: messagesPrepare(messages), |
| stream: true, |
| model_preference: null, |
| model_class: model, |
| temperature: 0 |
| }, |
| { |
| headers: { |
| Authorization: `Bearer ${token}`, |
| ...FAKE_HEADERS |
| }, |
| |
| timeout: 12e4, |
| validateStatus: () => true, |
| responseType: "stream" |
| } |
| ); |
| }); |
| if (result.headers["content-type"].indexOf("text/event-stream") == -1) { |
| logger_default.error( |
| `Invalid response Content-Type:`, |
| result.headers["content-type"] |
| ); |
| result.data.on("data", (buffer) => logger_default.error(buffer.toString())); |
| const transStream = new import_stream2.PassThrough(); |
| transStream.end( |
| `data: ${JSON.stringify({ |
| id: "", |
| model: MODEL_NAME, |
| object: "chat.completion.chunk", |
| choices: [ |
| { |
| index: 0, |
| delta: { |
| role: "assistant", |
| content: "\u670D\u52A1\u6682\u65F6\u4E0D\u53EF\u7528\uFF0C\u7B2C\u4E09\u65B9\u54CD\u5E94\u9519\u8BEF" |
| }, |
| finish_reason: "stop" |
| } |
| ], |
| usage: { prompt_tokens: 1, completion_tokens: 1, total_tokens: 2 }, |
| created: util_default.unixTimestamp() |
| })} |
| |
| ` |
| ); |
| return transStream; |
| } |
| const streamStartTime = util_default.timestamp(); |
| return createTransStream(model, result.data, () => { |
| logger_default.success( |
| `Stream has completed transfer ${util_default.timestamp() - streamStartTime}ms` |
| ); |
| }); |
| })().catch((err) => { |
| if (retryCount < MAX_RETRY_COUNT) { |
| logger_default.error(`Stream response error: ${err.stack}`); |
| logger_default.warn(`Try again after ${RETRY_DELAY / 1e3}s...`); |
| return (async () => { |
| await new Promise((resolve) => setTimeout(resolve, RETRY_DELAY)); |
| return createCompletionStream( |
| model, |
| messages, |
| refreshToken, |
| retryCount + 1 |
| ); |
| })(); |
| } |
| throw err; |
| }); |
| } |
| function messagesPrepare(messages) { |
| let content; |
| if (messages.length < 2) { |
| content = messages.reduce((content2, message) => { |
| if (import_lodash12.default.isArray(message.content)) { |
| return message.content.reduce((_content, v) => { |
| if (!import_lodash12.default.isObject(v) || v["type"] != "text") return _content; |
| return _content + (v["text"] || "") + "\n"; |
| }, content2); |
| } |
| return content2 + `${message.content} |
| `; |
| }, ""); |
| logger_default.info("\n\u900F\u4F20\u5185\u5BB9\uFF1A\n" + content); |
| } else { |
| content = (messages.reduce((content2, message) => { |
| if (import_lodash12.default.isArray(message.content)) { |
| return message.content.reduce((_content, v) => { |
| if (!import_lodash12.default.isObject(v) || v["type"] != "text") return _content; |
| return _content + (`${message.role}:` + v["text"] || "") + "\n"; |
| }, content2); |
| } |
| return content2 += `${message.role}:${message.content} |
| `; |
| }, "") + "assistant:").replace(/\!\[.+\]\(.+\)/g, ""); |
| logger_default.info("\n\u5BF9\u8BDD\u5408\u5E76\uFF1A\n" + content); |
| } |
| return content; |
| } |
| function checkResult(result, refreshToken) { |
| if (!result.data) return null; |
| const { code, data, msg } = result.data; |
| if (!import_lodash12.default.isFinite(code)) return result.data; |
| if (code === 0) return data; |
| if (code == 40003) accessTokenMap.delete(refreshToken); |
| throw new APIException(exceptions_default.API_REQUEST_FAILED, `[\u8BF7\u6C42deepseek\u5931\u8D25]: ${msg}`); |
| } |
| async function receiveStream(model, stream) { |
| return new Promise((resolve, reject) => { |
| const data = { |
| id: "", |
| model, |
| object: "chat.completion", |
| choices: [ |
| { |
| index: 0, |
| message: { role: "assistant", content: "" }, |
| finish_reason: "stop" |
| } |
| ], |
| usage: { prompt_tokens: 1, completion_tokens: 1, total_tokens: 2 }, |
| created: util_default.unixTimestamp() |
| }; |
| const parser = (0, import_eventsource_parser.createParser)((event) => { |
| try { |
| if (event.type !== "event") return; |
| const result = import_lodash12.default.attempt(() => JSON.parse(event.data)); |
| if (import_lodash12.default.isError(result)) |
| throw new Error(`Stream response invalid: ${event.data}`); |
| if (!result.choices || !result.choices[0] || !result.choices[0].delta || !result.choices[0].delta.content || result.choices[0].delta.content == " ") |
| return; |
| data.choices[0].message.content += result.choices[0].delta.content; |
| if (result.choices && result.choices[0] && result.choices[0].finish_reason === "stop") |
| resolve(data); |
| } catch (err) { |
| logger_default.error(err); |
| reject(err); |
| } |
| }); |
| stream.on("data", (buffer) => parser.feed(buffer.toString())); |
| stream.once("error", (err) => reject(err)); |
| stream.once("close", () => resolve(data)); |
| }); |
| } |
| function createTransStream(model, stream, endCallback) { |
| const created = util_default.unixTimestamp(); |
| const transStream = new import_stream2.PassThrough(); |
| !transStream.closed && transStream.write( |
| `data: ${JSON.stringify({ |
| id: "", |
| model, |
| object: "chat.completion.chunk", |
| choices: [ |
| { |
| index: 0, |
| delta: { role: "assistant", content: "" }, |
| finish_reason: null |
| } |
| ], |
| created |
| })} |
| |
| ` |
| ); |
| const parser = (0, import_eventsource_parser.createParser)((event) => { |
| try { |
| if (event.type !== "event") return; |
| const result = import_lodash12.default.attempt(() => JSON.parse(event.data)); |
| if (import_lodash12.default.isError(result)) |
| throw new Error(`Stream response invalid: ${event.data}`); |
| if (!result.choices || !result.choices[0] || !result.choices[0].delta || !result.choices[0].delta.content || result.choices[0].delta.content == " ") |
| return; |
| result.model = model; |
| transStream.write(`data: ${JSON.stringify({ |
| id: result.id, |
| model: result.model, |
| object: "chat.completion.chunk", |
| choices: [ |
| { |
| index: 0, |
| delta: { role: "assistant", content: result.choices[0].delta.content }, |
| finish_reason: null |
| } |
| ], |
| created |
| })} |
| |
| `); |
| if (result.choices && result.choices[0] && result.choices[0].finish_reason === "stop") { |
| transStream.write(`data: ${JSON.stringify({ |
| id: result.id, |
| model: result.model, |
| object: "chat.completion.chunk", |
| choices: [ |
| { |
| index: 0, |
| delta: { role: "assistant", content: "" }, |
| finish_reason: "stop" |
| } |
| ], |
| created |
| })} |
| |
| `); |
| !transStream.closed && transStream.end("data: [DONE]\n\n"); |
| } |
| } catch (err) { |
| logger_default.error(err); |
| !transStream.closed && transStream.end("data: [DONE]\n\n"); |
| } |
| }); |
| stream.on("data", (buffer) => parser.feed(buffer.toString())); |
| stream.once( |
| "error", |
| () => !transStream.closed && transStream.end("data: [DONE]\n\n") |
| ); |
| stream.once( |
| "close", |
| () => !transStream.closed && transStream.end("data: [DONE]\n\n") |
| ); |
| return transStream; |
| } |
| function tokenSplit(authorization) { |
| return authorization.replace("Bearer ", "").split(","); |
| } |
| async function getTokenLiveStatus(refreshToken) { |
| const token = await acquireToken(refreshToken); |
| const result = await import_axios2.default.get( |
| "https://chat.deepseek.com/api/v0/users/current", |
| { |
| headers: { |
| Authorization: `Bearer ${token}`, |
| ...FAKE_HEADERS |
| }, |
| timeout: 15e3, |
| validateStatus: () => true |
| } |
| ); |
| try { |
| const { token: token2 } = checkResult(result, refreshToken); |
| return !!token2; |
| } catch (err) { |
| return false; |
| } |
| } |
| var chat_default = { |
| createCompletion, |
| createCompletionStream, |
| getTokenLiveStatus, |
| tokenSplit |
| }; |
|
|
| |
| var chat_default2 = { |
| |
| prefix: "/hf/v1/chat", |
| post: { |
| "/completions": async (request) => { |
| request.validate("body.conversation_id", (v) => import_lodash13.default.isUndefined(v) || import_lodash13.default.isString(v)).validate("body.messages", import_lodash13.default.isArray).validate("headers.authorization", import_lodash13.default.isString); |
| const tokens = chat_default.tokenSplit(request.headers.authorization); |
| const token = import_lodash13.default.sample(tokens); |
| let { model, messages, stream } = request.body; |
| if (["deepseek_chat", "deepseek_code", "deepseek-chat*", "deepseek-chat", "deepseek-coder"].includes(model)) |
| model = { |
| "deepseek-chat*": "deepseek_chat", |
| "deepseek-chat": "deepseek_chat", |
| "deepseek-coder": "deepseek_code" |
| }[model] || model; |
| else |
| model = "deepseek_chat"; |
| if (stream) { |
| const stream2 = await chat_default.createCompletionStream(model, messages, token); |
| return new Response(stream2, { |
| type: "text/event-stream" |
| }); |
| } else |
| return await chat_default.createCompletion(model, messages, token); |
| } |
| } |
| }; |
|
|
| |
| var ping_default = { |
| |
| prefix: "/hf/ping", |
| get: { |
| "": async () => "pong" |
| } |
| }; |
|
|
| |
| var import_lodash14 = __toESM(require("lodash"), 1); |
| var token_default = { |
| |
| prefix: "/hf/token", |
| post: { |
| "/check": async (request) => { |
| request.validate("body.token", import_lodash14.default.isString); |
| const live = await chat_default.getTokenLiveStatus(request.body.token); |
| return { |
| live |
| }; |
| } |
| } |
| }; |
|
|
| |
| var models_default = { |
| |
| prefix: "/hf/v1", |
| get: { |
| "/models": async () => { |
| return { |
| "data": [ |
| { |
| "id": "deepseek-chat", |
| "object": "model", |
| "owned_by": "deepseek-free-api" |
| }, |
| { |
| "id": "deepseek-coder", |
| "object": "model", |
| "owned_by": "deepseek-free-api" |
| } |
| ] |
| }; |
| } |
| } |
| }; |
|
|
| |
| var routes_default = [ |
| { |
| get: { |
| "/": async () => { |
| const content = await import_fs_extra6.default.readFile("public/welcome.html"); |
| return new Response(content, { |
| type: "html", |
| headers: { |
| Expires: "-1" |
| } |
| }); |
| } |
| } |
| }, |
| chat_default2, |
| ping_default, |
| token_default, |
| models_default |
| ]; |
|
|
| |
| var startupTime = performance.now(); |
| (async () => { |
| logger_default.header(); |
| logger_default.info("<<<< deepseek free server >>>>"); |
| logger_default.info("Version:", environment_default.package.version); |
| logger_default.info("Process id:", process.pid); |
| logger_default.info("Environment:", environment_default.env); |
| logger_default.info("Service name:", config_default.service.name); |
| server_default.attachRoutes(routes_default); |
| await server_default.listen(); |
| config_default.service.bindAddress && logger_default.success("Service bind address:", config_default.service.bindAddress); |
| })().then( |
| () => logger_default.success( |
| `Service startup completed (${Math.floor(performance.now() - startupTime)}ms)` |
| ) |
| ).catch((err) => console.error(err)); |
| |