Upload 4 files
Browse files- clewd.js +954 -0
- lib/clewd-stream.js +195 -0
- lib/clewd-superfetch.js +4 -0
- lib/clewd-utils.js +111 -0
clewd.js
ADDED
|
@@ -0,0 +1,954 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/*
|
| 2 |
+
* https://rentry.org/teralomaniac_clewd
|
| 3 |
+
* https://github.com/teralomaniac/clewd
|
| 4 |
+
*/
|
| 5 |
+
'use strict';
|
| 6 |
+
|
| 7 |
+
const {createServer: Server, IncomingMessage, ServerResponse} = require('node:http'), {createHash: Hash, randomUUID, randomInt, randomBytes} = require('node:crypto'), {TransformStream, ReadableStream} = require('node:stream/web'), {Readable, Writable} = require('node:stream'), {Blob} = require('node:buffer'), {existsSync: exists, writeFileSync: write, createWriteStream} = require('node:fs'), {join: joinP} = require('node:path'), {ClewdSuperfetch: Superfetch, SuperfetchAvailable, SuperfetchFoldersMk, SuperfetchFoldersRm} = require('./lib/clewd-superfetch'), {AI, fileName, genericFixes, bytesToSize, setTitle, checkResErr, Replacements, Main} = require('./lib/clewd-utils'), ClewdStream = require('./lib/clewd-stream');
|
| 8 |
+
|
| 9 |
+
/******************************************************* */
|
| 10 |
+
let currentIndex, Firstlogin = true, changeflag = 0, changing, changetime = 0, totaltime, uuidOrgArray = [], model, cookieModel, tokens, apiKey, timestamp, regexLog, isPro, modelList = [];
|
| 11 |
+
|
| 12 |
+
const url = require('url');
|
| 13 |
+
const asyncPool = async (poolLimit, array, iteratorFn) => {
|
| 14 |
+
const ret = [], executing = [];
|
| 15 |
+
for (const item of array) {
|
| 16 |
+
const p = Promise.resolve().then(() => iteratorFn(item));
|
| 17 |
+
ret.push(p);
|
| 18 |
+
if (poolLimit <= array.length) {
|
| 19 |
+
const e = p.then(() => executing.splice(executing.indexOf(e), 1));
|
| 20 |
+
executing.push(e);
|
| 21 |
+
if (executing.length >= poolLimit) await Promise.race(executing);
|
| 22 |
+
}
|
| 23 |
+
}
|
| 24 |
+
return Promise.all(ret);
|
| 25 |
+
}, convertToType = value => {
|
| 26 |
+
if (value === 'true') return true;
|
| 27 |
+
if (value === 'false') return false;
|
| 28 |
+
if (/^\d+$/.test(value)) return parseInt(value);
|
| 29 |
+
return value;
|
| 30 |
+
}, CookieChanger = (resetTimer = true, cleanup = false) => {
|
| 31 |
+
if (Config.CookieArray?.length <= 1) {
|
| 32 |
+
return changing = false;
|
| 33 |
+
} else {
|
| 34 |
+
changeflag = 0, changing = true;
|
| 35 |
+
if(!cleanup) {
|
| 36 |
+
currentIndex = (currentIndex + 1) % Config.CookieArray.length;
|
| 37 |
+
console.log(`Changing Cookie...\n`);
|
| 38 |
+
}
|
| 39 |
+
setTimeout(() => {
|
| 40 |
+
onListen();
|
| 41 |
+
resetTimer && (timestamp = Date.now());
|
| 42 |
+
}, !Config.rProxy || Config.rProxy === AI.end() ? 15000 + timestamp - Date.now() : 0);
|
| 43 |
+
}
|
| 44 |
+
}, CookieCleaner = (flag, percentage) => {
|
| 45 |
+
Config.WastedCookie.push(flag + '@' + Config.CookieArray[currentIndex].split('@').toReversed()[0]);
|
| 46 |
+
Config.CookieArray.splice(currentIndex, 1), Config.Cookie = '';
|
| 47 |
+
Config.Cookiecounter < 0 && console.log(`[progress]: [32m${percentage.toFixed(2)}%[0m\n[length]: [33m${Config.CookieArray.length}[0m\n`);
|
| 48 |
+
console.log(`Cleaning Cookie...\n`);
|
| 49 |
+
writeSettings(Config);
|
| 50 |
+
return CookieChanger(true, true);
|
| 51 |
+
}, padtxt = content => {
|
| 52 |
+
const {countTokens} = require('@anthropic-ai/tokenizer');
|
| 53 |
+
tokens = countTokens(content);
|
| 54 |
+
const padtxt = String(Config.Settings.padtxt).split(',').reverse(), maxtokens = parseInt(padtxt[0]), extralimit = parseInt(padtxt[1]) || 1000, minlimit = parseInt(padtxt[2]);
|
| 55 |
+
const placeholder = (tokens > maxtokens - extralimit && minlimit ? Config.placeholder_byte : Config.placeholder_token) || randomBytes(randomInt(5, 15)).toString('hex');
|
| 56 |
+
const placeholdertokens = countTokens(placeholder.trim());
|
| 57 |
+
for (let match; match = content.match(/<\|padtxt.*?(\d+)t.*?\|>/); content = content.replace(match[0], placeholder.repeat(parseInt(match[1]) / placeholdertokens))) tokens += parseInt(match[1]);
|
| 58 |
+
if(/<\|padtxt off.*?\|>/.test(content)) return content.replace(/\s*<\|padtxt.*?\|>\s*/g, '\n\n');
|
| 59 |
+
const padding = placeholder.repeat(Math.min(maxtokens, (tokens <= maxtokens - extralimit ? maxtokens - tokens : minlimit ? minlimit : extralimit)) / placeholdertokens);
|
| 60 |
+
content = /<\|padtxt.*?\|>/.test(content) ? content.replace(/<\|padtxt.*?\|>/, padding).replace(/\s*<\|padtxt.*?\|>\s*/g, '\n\n') : !apiKey ? padding + '\n\n\n' + content.trim() : content;
|
| 61 |
+
return content;
|
| 62 |
+
}, xmlPlot_merge = (content, mergeTag, nonsys) => {
|
| 63 |
+
if (/(\n\n|^\s*)xmlPlot:\s*/.test(content)) {
|
| 64 |
+
content = (nonsys ? content : content.replace(/(\n\n|^\s*)(?<!\n\n(Human|Assistant):.*?)xmlPlot:\s*/gs, '$1')).replace(/(\n\n|^\s*)xmlPlot: */g, mergeTag.system && mergeTag.human && mergeTag.all ? '\n\nHuman: ' : '$1' );
|
| 65 |
+
}
|
| 66 |
+
mergeTag.all && mergeTag.human && (content = content.replace(/(?:\n\n|^\s*)Human:(.*?(?:\n\nAssistant:|$))/gs, function(match, p1) {return '\n\nHuman:' + p1.replace(/\n\nHuman:\s*/g, '\n\n')}));
|
| 67 |
+
mergeTag.all && mergeTag.assistant && (content = content.replace(/\n\nAssistant:(.*?(?:\n\nHuman:|$))/gs, function(match, p1) {return '\n\nAssistant:' + p1.replace(/\n\nAssistant:\s*/g, '\n\n')}));
|
| 68 |
+
return content;
|
| 69 |
+
}, xmlPlot_regex = (content, order) => {
|
| 70 |
+
let matches = content.match(new RegExp(`<regex(?: +order *= *${order})${order === 2 ? '?' : ''}> *"(/?)(.*)\\1(.*?)" *: *"(.*?)" *</regex>`, 'gm'));
|
| 71 |
+
matches && matches.forEach(match => {
|
| 72 |
+
try {
|
| 73 |
+
const reg = /<regex(?: +order *= *\d)?> *"(\/?)(.*)\1(.*?)" *: *"(.*?)" *<\/regex>/.exec(match);
|
| 74 |
+
regexLog += match + '\n';
|
| 75 |
+
content = content.replace(new RegExp(reg[2], reg[3]), JSON.parse(`"${reg[4].replace(/\\?"/g, '\\"')}"`));
|
| 76 |
+
} catch (err) {
|
| 77 |
+
console.log(`[33mRegex error: [0m` + match + '\n' + err);
|
| 78 |
+
}
|
| 79 |
+
});
|
| 80 |
+
return content;
|
| 81 |
+
}, xmlPlot = (content, nonsys = false) => {
|
| 82 |
+
regexLog = '';
|
| 83 |
+
//一次正则
|
| 84 |
+
content = xmlPlot_regex(content, 1);
|
| 85 |
+
//一次role合并
|
| 86 |
+
const mergeTag = {
|
| 87 |
+
all: !content.includes('<|Merge Disable|>'),
|
| 88 |
+
system: !content.includes('<|Merge System Disable|>'),
|
| 89 |
+
human: !content.includes('<|Merge Human Disable|>'),
|
| 90 |
+
assistant: !content.includes('<|Merge Assistant Disable|>')
|
| 91 |
+
};
|
| 92 |
+
content = xmlPlot_merge(content, mergeTag, nonsys);
|
| 93 |
+
//自定义插入
|
| 94 |
+
let splitContent = content.split(/\n\n(?=Assistant:|Human:)/g), match;
|
| 95 |
+
while ((match = /<@(\d+)>(.*?)<\/@\1>/gs.exec(content)) !== null) {
|
| 96 |
+
let index = splitContent.length - parseInt(match[1]) - 1;
|
| 97 |
+
index >= 0 && (splitContent[index] += '\n\n' + match[2]);
|
| 98 |
+
content = content.replace(match[0], '');
|
| 99 |
+
}
|
| 100 |
+
content = splitContent.join('\n\n').replace(/<@(\d+)>.*?<\/@\1>/gs, '');
|
| 101 |
+
//二次正则
|
| 102 |
+
content = xmlPlot_regex(content, 2);
|
| 103 |
+
//二次role合并
|
| 104 |
+
content = xmlPlot_merge(content, mergeTag, nonsys);
|
| 105 |
+
//Plain Prompt
|
| 106 |
+
let segcontentHuman = content.split('\n\nHuman:');
|
| 107 |
+
let segcontentlastIndex = segcontentHuman.length - 1;
|
| 108 |
+
if (!apiKey && segcontentlastIndex >= 2 && segcontentHuman[segcontentlastIndex].includes('<|Plain Prompt Enable|>') && !content.includes('\n\nPlainPrompt:')) {
|
| 109 |
+
content = segcontentHuman.slice(0, segcontentlastIndex).join('\n\nHuman:') + '\n\nPlainPrompt:' + segcontentHuman.slice(segcontentlastIndex).join('\n\nHuman:').replace(/\n\nHuman: *PlainPrompt:/, '\n\nPlainPrompt:');
|
| 110 |
+
}
|
| 111 |
+
//三次正则
|
| 112 |
+
content = xmlPlot_regex(content, 3);
|
| 113 |
+
//消除空XML tags、两端空白符和多余的\n
|
| 114 |
+
content = content.replace(/<regex( +order *= *\d)?>.*?<\/regex>/gm, '')
|
| 115 |
+
.replace(/\r\n|\r/gm, '\n')
|
| 116 |
+
.replace(/\s*<\|curtail\|>\s*/g, '\n')
|
| 117 |
+
.replace(/\s*<\|join\|>\s*/g, '')
|
| 118 |
+
.replace(/\s*<\|space\|>\s*/g, ' ')
|
| 119 |
+
.replace(/\s*\n\n(H(uman)?|A(ssistant)?): +/g, '\n\n$1: ')
|
| 120 |
+
.replace(/<\|(\\.*?)\|>/g, function(match, p1) {
|
| 121 |
+
try {
|
| 122 |
+
return JSON.parse(`"${p1.replace(/\\?"/g, '\\"')}"`);
|
| 123 |
+
} catch { return match }
|
| 124 |
+
});
|
| 125 |
+
//确保格式正确
|
| 126 |
+
if (apiKey) {
|
| 127 |
+
content = content.replace(/(\n\nHuman:(?!.*?\n\nAssistant:).*?|(?<!\n\nAssistant:.*?))$/s, '$&\n\nAssistant:').replace(/\s*<\|noAssistant\|>\s*(.*?)(?:\n\nAssistant:\s*)?$/s, '\n\n$1');
|
| 128 |
+
content.includes('<|reverseHA|>') && (content = content.replace(/\s*<\|reverseHA\|>\s*/g, '\n\n').replace(/Assistant|Human/g, function(match) {return match === 'Human' ? 'Assistant' : 'Human'}).replace(/\n(A|H): /g, function(match, p1) {return p1 === 'A' ? '\nH: ' : '\nA: '}));
|
| 129 |
+
return content.replace(Config.Settings.padtxt ? /\s*<\|(?!padtxt).*?\|>\s*/g : /\s*<\|.*?\|>\s*/g, '\n\n').trim().replace(/^.+:/, '\n\n$&').replace(/(?<=\n)\n(?=\n)/g, '');
|
| 130 |
+
} else {
|
| 131 |
+
return content.replace(Config.Settings.padtxt ? /\s*<\|(?!padtxt).*?\|>\s*/g : /\s*<\|.*?\|>\s*/g, '\n\n').trim().replace(/^Human: *|\n\nAssistant: *$/g, '').replace(/(?<=\n)\n(?=\n)/g, '');
|
| 132 |
+
}
|
| 133 |
+
}, waitForChange = () => {
|
| 134 |
+
return new Promise(resolve => {
|
| 135 |
+
const interval = setInterval(() => {
|
| 136 |
+
if (!changing) {
|
| 137 |
+
clearInterval(interval);
|
| 138 |
+
resolve();
|
| 139 |
+
}
|
| 140 |
+
}, 100);
|
| 141 |
+
});
|
| 142 |
+
};
|
| 143 |
+
/******************************************************* */
|
| 144 |
+
|
| 145 |
+
let ChangedSettings, UnknownSettings, Logger;
|
| 146 |
+
|
| 147 |
+
const ConfigPath = joinP(__dirname, './config.js'), LogPath = joinP(__dirname, './log.txt'), Conversation = {
|
| 148 |
+
char: null,
|
| 149 |
+
uuid: null,
|
| 150 |
+
depth: 0
|
| 151 |
+
}, cookies = {};
|
| 152 |
+
|
| 153 |
+
let uuidOrg, curPrompt = {}, prevPrompt = {}, prevMessages = [], prevImpersonated = false, Config = {
|
| 154 |
+
Cookie: '',
|
| 155 |
+
CookieArray: [],
|
| 156 |
+
WastedCookie: [],
|
| 157 |
+
unknownModels: [],
|
| 158 |
+
Cookiecounter: 3,
|
| 159 |
+
CookieIndex: 0,
|
| 160 |
+
ProxyPassword: '',
|
| 161 |
+
Ip: (process.env.Cookie || process.env.CookieArray) ? '0.0.0.0' : '127.0.0.1',
|
| 162 |
+
Port: process.env.PORT || 8444,
|
| 163 |
+
localtunnel: false,
|
| 164 |
+
BufferSize: 1,
|
| 165 |
+
SystemInterval: 3,
|
| 166 |
+
rProxy: '',
|
| 167 |
+
api_rProxy: '',
|
| 168 |
+
placeholder_token: '',
|
| 169 |
+
placeholder_byte: '',
|
| 170 |
+
PromptExperimentFirst: '',
|
| 171 |
+
PromptExperimentNext: '',
|
| 172 |
+
PersonalityFormat: '{{char}}\'s personality: {{personality}}',
|
| 173 |
+
ScenarioFormat: 'Dialogue scenario: {{scenario}}',
|
| 174 |
+
Settings: {
|
| 175 |
+
RenewAlways: true,
|
| 176 |
+
RetryRegenerate: false,
|
| 177 |
+
PromptExperiments: true,
|
| 178 |
+
SystemExperiments: true,
|
| 179 |
+
PreventImperson: true,
|
| 180 |
+
AllSamples: false,
|
| 181 |
+
NoSamples: false,
|
| 182 |
+
StripAssistant: false,
|
| 183 |
+
StripHuman: false,
|
| 184 |
+
PassParams: true,
|
| 185 |
+
ClearFlags: true,
|
| 186 |
+
PreserveChats: false,
|
| 187 |
+
LogMessages: true,
|
| 188 |
+
FullColon: true,
|
| 189 |
+
padtxt: "1000,1000,15000",
|
| 190 |
+
xmlPlot: true,
|
| 191 |
+
SkipRestricted: false,
|
| 192 |
+
Artifacts: false,
|
| 193 |
+
Superfetch: true
|
| 194 |
+
}
|
| 195 |
+
};
|
| 196 |
+
|
| 197 |
+
ServerResponse.prototype.json = async function(body, statusCode = 200, headers) {
|
| 198 |
+
body = body instanceof Promise ? await body : body;
|
| 199 |
+
this.headersSent || this.writeHead(statusCode, {
|
| 200 |
+
'Content-Type': 'application/json',
|
| 201 |
+
...headers && headers
|
| 202 |
+
});
|
| 203 |
+
this.end('object' == typeof body ? JSON.stringify(body) : body);
|
| 204 |
+
return this;
|
| 205 |
+
};
|
| 206 |
+
|
| 207 |
+
Array.prototype.sample = function() {
|
| 208 |
+
return this[Math.floor(Math.random() * this.length)];
|
| 209 |
+
};
|
| 210 |
+
|
| 211 |
+
const updateParams = res => {
|
| 212 |
+
updateCookies(res);
|
| 213 |
+
}, updateCookies = res => {
|
| 214 |
+
let cookieNew = '';
|
| 215 |
+
res instanceof Response ? cookieNew = res.headers?.get('set-cookie') : res?.superfetch ? cookieNew = res.headers?.['set-cookie'] : 'string' == typeof res && (cookieNew = res.split('\n').join(''));
|
| 216 |
+
if (!cookieNew) {
|
| 217 |
+
return;
|
| 218 |
+
}
|
| 219 |
+
let cookieArr = cookieNew.split(/;\s?/gi).filter((prop => false === /^(path|expires|domain|HttpOnly|Secure|SameSite)[=;]*/i.test(prop)));
|
| 220 |
+
for (const cookie of cookieArr) {
|
| 221 |
+
const divide = cookie.split(/^(.*?)=\s*(.*)/), cookieName = divide[1], cookieVal = divide[2];
|
| 222 |
+
cookies[cookieName] = cookieVal;
|
| 223 |
+
}
|
| 224 |
+
}, getCookies = () => {
|
| 225 |
+
const cookieNames = Object.keys(cookies);
|
| 226 |
+
return cookieNames.map(((name, idx) => `${name}=${cookies[name]}${idx === cookieNames.length - 1 ? '' : ';'}`)).join(' ').replace(/(\s+)$/gi, '');
|
| 227 |
+
}, deleteChat = async uuid => {
|
| 228 |
+
if (!uuid) {
|
| 229 |
+
return;
|
| 230 |
+
}
|
| 231 |
+
if (uuid === Conversation.uuid) {
|
| 232 |
+
Conversation.uuid = null;
|
| 233 |
+
Conversation.depth = 0;
|
| 234 |
+
}
|
| 235 |
+
if (Config.Settings.PreserveChats) {
|
| 236 |
+
return;
|
| 237 |
+
}
|
| 238 |
+
const res = await (Config.Settings.Superfetch ? Superfetch : fetch)(`${Config.rProxy || AI.end()}/api/organizations/${uuidOrg}/chat_conversations/${uuid}`, {
|
| 239 |
+
headers: {
|
| 240 |
+
...AI.hdr(),
|
| 241 |
+
Cookie: getCookies()
|
| 242 |
+
},
|
| 243 |
+
method: 'DELETE'
|
| 244 |
+
});
|
| 245 |
+
updateParams(res);
|
| 246 |
+
}, onListen = async () => {
|
| 247 |
+
/***************************** */
|
| 248 |
+
if (Firstlogin) {
|
| 249 |
+
Firstlogin = false, timestamp = Date.now(), totaltime = Config.CookieArray.length;
|
| 250 |
+
console.log(`[2m${Main}[0m\n[33mhttp://${Config.Ip}:${Config.Port}/v1[0m\n\n${Object.keys(Config.Settings).map((setting => UnknownSettings?.includes(setting) ? `??? [31m${setting}: ${Config.Settings[setting]}[0m` : `[1m${setting}:[0m ${ChangedSettings?.includes(setting) ? '[33m' : '[36m'}${Config.Settings[setting]}[0m`)).sort().join('\n')}\n`); //↓
|
| 251 |
+
if (Config.Settings.Superfetch) {
|
| 252 |
+
SuperfetchAvailable(true);
|
| 253 |
+
SuperfetchFoldersMk();
|
| 254 |
+
}
|
| 255 |
+
if (Config.localtunnel) {
|
| 256 |
+
const localtunnel = require('localtunnel');
|
| 257 |
+
localtunnel({ port: Config.Port }).then((tunnel) => {
|
| 258 |
+
console.log(`\nTunnel URL for outer websites: ${tunnel.url}/v1\n`);
|
| 259 |
+
})
|
| 260 |
+
}
|
| 261 |
+
}
|
| 262 |
+
if (Config.CookieArray?.length > 0) {
|
| 263 |
+
const cookieInfo = /(?:(claude[-_][a-z0-9-_]*?)@)?(?:sessionKey=)?(sk-ant-sid01-[\w-]{86}-[\w-]{6}AA)/.exec(Config.CookieArray[currentIndex]);
|
| 264 |
+
cookieInfo?.[2] && (Config.Cookie = 'sessionKey=' + cookieInfo[2]);
|
| 265 |
+
changetime++;
|
| 266 |
+
if (model && cookieInfo?.[1] && !/claude[\w]*?_pro/.test(cookieInfo?.[1]) && cookieInfo?.[1] != model) return CookieChanger(false);
|
| 267 |
+
}
|
| 268 |
+
let percentage = ((changetime + Math.max(Config.CookieIndex - 1, 0)) / totaltime) * 100
|
| 269 |
+
if (Config.Cookiecounter < 0 && percentage > 100) {
|
| 270 |
+
console.log(`\n※※※Cookie cleanup completed※※※\n\n`);
|
| 271 |
+
return process.exit();
|
| 272 |
+
}
|
| 273 |
+
try {
|
| 274 |
+
/***************************** */
|
| 275 |
+
if ('SET YOUR COOKIE HERE' === Config.Cookie || Config.Cookie?.length < 1) {
|
| 276 |
+
return changing = false, console.log(`[33mNo cookie available, enter apiKey-only mode.[0m\n`); //throw Error('Set your cookie inside config.js');
|
| 277 |
+
}
|
| 278 |
+
updateCookies(Config.Cookie);
|
| 279 |
+
/**************************** */
|
| 280 |
+
const bootstrapRes = await (Config.Settings.Superfetch ? Superfetch : fetch)((Config.rProxy || AI.end()) + `/api/bootstrap`, {
|
| 281 |
+
method: 'GET',
|
| 282 |
+
headers: {
|
| 283 |
+
...AI.hdr(),
|
| 284 |
+
Cookie: getCookies()
|
| 285 |
+
}
|
| 286 |
+
});
|
| 287 |
+
await checkResErr(bootstrapRes);
|
| 288 |
+
const bootstrap = await bootstrapRes.json();
|
| 289 |
+
if (bootstrap.account === null) {
|
| 290 |
+
console.log(`[35mNull![0m`);
|
| 291 |
+
return CookieCleaner('Null', percentage);
|
| 292 |
+
}
|
| 293 |
+
const bootAccInfo = bootstrap.account.memberships.find(item => item.organization.capabilities.includes('chat')).organization;
|
| 294 |
+
cookieModel = bootstrap.statsig.values.layer_configs["HPOHwBLNLQLxkj5Yn4bfSkgCQnBX28kPR7h/BNKdVLw="]?.value?.console_default_model_override?.model || bootstrap.statsig.values.dynamic_configs["6zA9wvTedwkzjLxWy9PVe7yydI00XDQ6L5Fejjq/2o8="]?.value?.model;
|
| 295 |
+
isPro = bootAccInfo.capabilities.includes('claude_pro') && 'claude_pro' || bootAccInfo.capabilities.includes('raven') && 'claude_team_pro';
|
| 296 |
+
const unknown = cookieModel && !(AI.mdl().includes(cookieModel) || Config.unknownModels.includes(cookieModel));
|
| 297 |
+
if (Config.CookieArray?.length > 0 && (isPro || cookieModel) != Config.CookieArray[currentIndex].split('@')[0] || unknown) {
|
| 298 |
+
Config.CookieArray[currentIndex] = (isPro || cookieModel) + '@' + Config.Cookie;
|
| 299 |
+
unknown && Config.unknownModels.push(cookieModel);
|
| 300 |
+
writeSettings(Config);
|
| 301 |
+
}
|
| 302 |
+
if (!isPro && model && model != cookieModel) return CookieChanger();
|
| 303 |
+
console.log(Config.CookieArray?.length > 0 ? `(index: [36m${currentIndex + 1 || Config.CookieArray.length}[0m) Logged in %o` : 'Logged in %o', { //console.log('Logged in %o', { ↓
|
| 304 |
+
name: bootAccInfo.name?.split('@')?.[0],
|
| 305 |
+
mail: bootstrap.account.email_address, //
|
| 306 |
+
cookieModel, //
|
| 307 |
+
capabilities: bootAccInfo.capabilities
|
| 308 |
+
}); //↓
|
| 309 |
+
if (uuidOrgArray.includes(bootAccInfo.uuid) && percentage <= 100 && Config.CookieArray?.length > 0 || bootAccInfo.api_disabled_reason && !bootAccInfo.api_disabled_until || !bootstrap.account.completed_verification_at) {
|
| 310 |
+
const flag = bootAccInfo.api_disabled_reason ? 'Disabled' : !bootstrap.account.completed_verification_at ? 'Unverified' : 'Overlap';
|
| 311 |
+
console.log(`[31m${flag}![0m`);
|
| 312 |
+
return CookieCleaner(flag, percentage);
|
| 313 |
+
} else uuidOrgArray.push(bootAccInfo.uuid);
|
| 314 |
+
if (Config.Cookiecounter < 0) {
|
| 315 |
+
console.log(`[progress]: [32m${percentage.toFixed(2)}%[0m\n[length]: [33m${Config.CookieArray.length}[0m\n`);
|
| 316 |
+
return CookieChanger();
|
| 317 |
+
}
|
| 318 |
+
/**************************** */
|
| 319 |
+
const accRes = await (Config.Settings.Superfetch ? Superfetch : fetch)((Config.rProxy || AI.end()) + '/api/organizations', {
|
| 320 |
+
method: 'GET',
|
| 321 |
+
headers: {
|
| 322 |
+
...AI.hdr(),
|
| 323 |
+
Cookie: getCookies()
|
| 324 |
+
}
|
| 325 |
+
});
|
| 326 |
+
await checkResErr(accRes);
|
| 327 |
+
const accInfo = (await accRes.json())?.find(item => item.capabilities.includes('chat')); //const accInfo = (await accRes.json())?.[0];\nif (!accInfo || accInfo.error) {\n throw Error(`Couldn't get account info: "${accInfo?.error?.message || accRes.statusText}"`);\n}\nif (!accInfo?.uuid) {\n throw Error('Invalid account id');\n}
|
| 328 |
+
setTitle('ok');
|
| 329 |
+
updateParams(accRes);
|
| 330 |
+
uuidOrg = accInfo?.uuid;
|
| 331 |
+
if (accInfo?.active_flags.length > 0) {
|
| 332 |
+
let banned = false; //
|
| 333 |
+
const now = new Date, formattedFlags = accInfo.active_flags.map((flag => {
|
| 334 |
+
const days = ((new Date(flag.expires_at).getTime() - now.getTime()) / 864e5).toFixed(2);
|
| 335 |
+
'consumer_banned' === flag.type && (banned = true); //
|
| 336 |
+
return {
|
| 337 |
+
type: flag.type,
|
| 338 |
+
remaining_days: days
|
| 339 |
+
};
|
| 340 |
+
}));
|
| 341 |
+
console.warn(`${banned ? '[31m' : '[35m'}Your account has warnings[0m %o`, formattedFlags); //console.warn('[31mYour account has warnings[0m %o', formattedFlags);
|
| 342 |
+
await Promise.all(accInfo.active_flags.map((flag => (async type => {
|
| 343 |
+
if (!Config.Settings.ClearFlags) {
|
| 344 |
+
return;
|
| 345 |
+
}
|
| 346 |
+
if ('consumer_restricted_mode' === type || 'consumer_banned' === type) { //if ('consumer_restricted_mode' === type) {
|
| 347 |
+
return;
|
| 348 |
+
}
|
| 349 |
+
const req = await (Config.Settings.Superfetch ? Superfetch : fetch)(`${Config.rProxy || AI.end()}/api/organizations/${uuidOrg}/flags/${type}/dismiss`, {
|
| 350 |
+
headers: {
|
| 351 |
+
...AI.hdr(),
|
| 352 |
+
Cookie: getCookies()
|
| 353 |
+
},
|
| 354 |
+
method: 'POST'
|
| 355 |
+
});
|
| 356 |
+
updateParams(req);
|
| 357 |
+
const json = await req.json();
|
| 358 |
+
console.log(`${type}: ${json.error ? json.error.message || json.error.type || json.detail : 'OK'}`);
|
| 359 |
+
})(flag.type))));
|
| 360 |
+
console.log(`${banned ? '[31mBanned' : '[35mRestricted'}![0m`); //
|
| 361 |
+
if (banned) return CookieCleaner('Banned') //
|
| 362 |
+
else if (Config.Settings.SkipRestricted) return CookieChanger(); //
|
| 363 |
+
}
|
| 364 |
+
if (bootstrap.account.settings.preview_feature_uses_artifacts != Config.Settings.Artifacts) {
|
| 365 |
+
const settingsRes = await (Config.Settings.Superfetch ? Superfetch : fetch)((Config.rProxy || AI.end()) + `/api/account`, {
|
| 366 |
+
method: 'PUT',
|
| 367 |
+
headers: {
|
| 368 |
+
...AI.hdr(),
|
| 369 |
+
Cookie: getCookies()
|
| 370 |
+
},
|
| 371 |
+
body: JSON.stringify({ settings: Object.assign(bootstrap.account.settings, { preview_feature_uses_artifacts: Config.Settings.Artifacts }) }),
|
| 372 |
+
});
|
| 373 |
+
await checkResErr(settingsRes);
|
| 374 |
+
updateParams(settingsRes);
|
| 375 |
+
}
|
| 376 |
+
changing = false;
|
| 377 |
+
const convRes = await (Config.Settings.Superfetch ? Superfetch : fetch)(`${Config.rProxy || AI.end()}/api/organizations/${accInfo.uuid}/chat_conversations`, { //const convRes = await fetch(`${Config.rProxy || AI.end()}/api/organizations/${uuidOrg}/chat_conversations`, {
|
| 378 |
+
method: 'GET',
|
| 379 |
+
headers: {
|
| 380 |
+
...AI.hdr(),
|
| 381 |
+
Cookie: getCookies()
|
| 382 |
+
}
|
| 383 |
+
}), conversations = await convRes.json();
|
| 384 |
+
updateParams(convRes);
|
| 385 |
+
conversations.length > 0 && await asyncPool(10, conversations, async (conv) => await deleteChat(conv.uuid)); //await Promise.all(conversations.map((conv => deleteChat(conv.uuid))));
|
| 386 |
+
/***************************** */
|
| 387 |
+
} catch (err) {
|
| 388 |
+
if (err.message === 'Invalid authorization') {
|
| 389 |
+
console.log(`[31mInvalid![0m`);
|
| 390 |
+
return CookieCleaner('Invalid', percentage);
|
| 391 |
+
}
|
| 392 |
+
console.error('[33mClewd:[0m\n%o', err);
|
| 393 |
+
CookieChanger();
|
| 394 |
+
}
|
| 395 |
+
/***************************** */
|
| 396 |
+
}, writeSettings = async (config, firstRun = false) => {
|
| 397 |
+
if (process.env.Cookie || process.env.CookieArray) return; //
|
| 398 |
+
write(ConfigPath, `/*\n* https://rentry.org/teralomaniac_clewd\n* https://github.com/teralomaniac/clewd\n*/\n\n// SET YOUR COOKIE BELOW\n\nmodule.exports = ${JSON.stringify(config, null, 4)}\n\n/*\n BufferSize\n * How many characters will be buffered before the AI types once\n * lower = less chance of \`PreventImperson\` working properly\n\n ---\n\n SystemInterval\n * How many messages until \`SystemExperiments alternates\`\n\n ---\n\n Other settings\n * https://gitgud.io/ahsk/clewd/#defaults\n * and\n * https://gitgud.io/ahsk/clewd/-/blob/master/CHANGELOG.md\n */`.trim().replace(/((?<!\r)\n|\r(?!\n))/g, '\r\n'));
|
| 399 |
+
if (firstRun) {
|
| 400 |
+
console.warn('[33mconfig file created!\nedit[0m [1mconfig.js[0m [33mto set your settings and restart the program[0m');
|
| 401 |
+
process.exit(0);
|
| 402 |
+
}
|
| 403 |
+
}, Proxy = Server((async (req, res) => {
|
| 404 |
+
if ('OPTIONS' === req.method) {
|
| 405 |
+
return ((req, res) => {
|
| 406 |
+
res.writeHead(200, {
|
| 407 |
+
'Access-Control-Allow-Origin': '*',
|
| 408 |
+
'Access-Control-Allow-Headers': 'Authorization, Content-Type',
|
| 409 |
+
'Access-Control-Allow-Methods': 'POST, GET, OPTIONS'
|
| 410 |
+
}).end();
|
| 411 |
+
})(0, res);
|
| 412 |
+
}
|
| 413 |
+
const URL = url.parse(req.url.replace(/\/v1(\?.*)\$(\/.*)$/, '/v1$2$1'), true);
|
| 414 |
+
const api_rProxy = URL.query?.api_rProxy || Config.api_rProxy;
|
| 415 |
+
req.url = URL.pathname;
|
| 416 |
+
switch (req.url) {
|
| 417 |
+
case '/api/v1/models':
|
| 418 |
+
/***************************** */
|
| 419 |
+
(async (req, res) => {
|
| 420 |
+
let models;
|
| 421 |
+
if (/oaiKey:/.test(req.headers.authorization)) {
|
| 422 |
+
try {
|
| 423 |
+
const modelsRes = await fetch(api_rProxy.replace(/(\/v1)?\/? *$/, '') + '/v1/models', {
|
| 424 |
+
method: 'GET',
|
| 425 |
+
headers: { authorization: req.headers.authorization.match(/(?<=oaiKey:).*/)?.[0].split(',')[0].trim() }
|
| 426 |
+
});
|
| 427 |
+
models = await modelsRes.json();
|
| 428 |
+
} catch(err) {}
|
| 429 |
+
}
|
| 430 |
+
res.json({
|
| 431 |
+
data: [
|
| 432 |
+
...AI.mdl().concat(Config.unknownModels).map((name => ({ id: name })))
|
| 433 |
+
].concat(models?.data).reduce((acc, current, index) => {
|
| 434 |
+
index === 0 && modelList.splice(0);
|
| 435 |
+
if (current?.id && acc.every(model => model.id != current.id)) {
|
| 436 |
+
acc.push(current);
|
| 437 |
+
modelList.push(current.id);
|
| 438 |
+
}
|
| 439 |
+
return acc;
|
| 440 |
+
}, [])
|
| 441 |
+
});
|
| 442 |
+
})(req, res); //res.json({\n data: AI.mdl().map((name => ({\n id: name\n })))\n});
|
| 443 |
+
/***************************** */
|
| 444 |
+
break;
|
| 445 |
+
|
| 446 |
+
case '/api/v1/chat/completions':
|
| 447 |
+
((req, res) => {
|
| 448 |
+
setTitle('recv...');
|
| 449 |
+
let fetchAPI;
|
| 450 |
+
const abortControl = new AbortController, {signal} = abortControl;
|
| 451 |
+
res.socket.on('close', (async () => {
|
| 452 |
+
abortControl.signal.aborted || abortControl.abort();
|
| 453 |
+
}));
|
| 454 |
+
const buffer = [];
|
| 455 |
+
req.on('data', (chunk => {
|
| 456 |
+
buffer.push(chunk);
|
| 457 |
+
}));
|
| 458 |
+
req.on('end', (async () => {
|
| 459 |
+
let clewdStream, titleTimer, samePrompt = false, shouldRenew = true, retryRegen = false, exceeded_limit = false, nochange = false; //let clewdStream, titleTimer, samePrompt = false, shouldRenew = true, retryRegen = false;
|
| 460 |
+
try {
|
| 461 |
+
const body = JSON.parse(Buffer.concat(buffer).toString());
|
| 462 |
+
let {temperature} = body;
|
| 463 |
+
temperature = typeof temperature === 'number' ? Math.max(.1, Math.min(1, temperature)) : undefined; //temperature = Math.max(.1, Math.min(1, temperature));
|
| 464 |
+
let {messages} = body;
|
| 465 |
+
/************************* */
|
| 466 |
+
const thirdKey = req.headers.authorization?.match(/(?<=(3rd|oai)Key:).*/), oaiAPI = /oaiKey:/.test(req.headers.authorization), forceModel = /--force/.test(body.model);
|
| 467 |
+
apiKey = thirdKey?.[0].split(',').map(item => item.trim()) || req.headers.authorization?.match(/sk-ant-api\d\d-[\w-]{86}-[\w-]{6}AA/g);
|
| 468 |
+
model = apiKey || forceModel || isPro ? body.model.replace(/--force/, '').trim() : cookieModel;
|
| 469 |
+
let max_tokens_to_sample = body.max_tokens, stop_sequences = body.stop, top_p = typeof body.top_p === 'number' ? body.top_p : undefined, top_k = typeof body.top_k === 'number' ? body.top_k : undefined;
|
| 470 |
+
if (!apiKey && (Config.ProxyPassword != '' && req.headers.authorization != 'Bearer ' + Config.ProxyPassword || !uuidOrg)) {
|
| 471 |
+
throw Error(uuidOrg ? 'ProxyPassword Wrong' : 'No cookie available or apiKey format wrong');
|
| 472 |
+
} else if (!changing && !apiKey && (!isPro && model != cookieModel)) CookieChanger();
|
| 473 |
+
await waitForChange();
|
| 474 |
+
/************************* */
|
| 475 |
+
if (messages?.length < 1) {
|
| 476 |
+
throw Error('Select OpenAI as completion source');
|
| 477 |
+
}
|
| 478 |
+
if (!body.stream && 1 === messages.length && JSON.stringify(messages.sort() || []) === JSON.stringify([ {
|
| 479 |
+
role: 'user',
|
| 480 |
+
content: 'Hi'
|
| 481 |
+
} ].sort())) {
|
| 482 |
+
return res.json({
|
| 483 |
+
choices: [ {
|
| 484 |
+
message: {
|
| 485 |
+
content: Main
|
| 486 |
+
}
|
| 487 |
+
} ]
|
| 488 |
+
});
|
| 489 |
+
}
|
| 490 |
+
res.setHeader('Access-Control-Allow-Origin', '*');
|
| 491 |
+
body.stream && res.setHeader('Content-Type', 'text/event-stream');
|
| 492 |
+
if (!body.stream && messages?.[0]?.content?.startsWith('From the list below, choose a word that best represents a character\'s outfit description, action, or emotion in their dialogue')) {
|
| 493 |
+
return res.json({
|
| 494 |
+
choices: [ {
|
| 495 |
+
message: {
|
| 496 |
+
content: 'neutral'
|
| 497 |
+
}
|
| 498 |
+
} ]
|
| 499 |
+
});
|
| 500 |
+
}
|
| 501 |
+
if (Config.Settings.AllSamples && Config.Settings.NoSamples) {
|
| 502 |
+
console.log('[33mhaving[0m [1mAllSamples[0m and [1mNoSamples[0m both set to true is not supported');
|
| 503 |
+
throw Error('Only one can be used at the same time: AllSamples/NoSamples');
|
| 504 |
+
}
|
| 505 |
+
//const model = body.model;//if (model === AI.mdl()[0]) {// return;//}
|
| 506 |
+
if (!modelList.includes(model) && !/claude-.*/.test(model) && !forceModel) {
|
| 507 |
+
throw Error('Invalid model selected: ' + model);
|
| 508 |
+
}
|
| 509 |
+
curPrompt = {
|
| 510 |
+
firstUser: messages.find((message => 'user' === message.role)),
|
| 511 |
+
firstSystem: messages.find((message => 'system' === message.role)),
|
| 512 |
+
firstAssistant: messages.find((message => 'assistant' === message.role)),
|
| 513 |
+
lastUser: messages.findLast((message => 'user' === message.role)),
|
| 514 |
+
lastSystem: messages.findLast((message => 'system' === message.role && '[Start a new chat]' !== message.content)),
|
| 515 |
+
lastAssistant: messages.findLast((message => 'assistant' === message.role))
|
| 516 |
+
};
|
| 517 |
+
prevPrompt = {
|
| 518 |
+
...prevMessages.length > 0 && {
|
| 519 |
+
firstUser: prevMessages.find((message => 'user' === message.role)),
|
| 520 |
+
firstSystem: prevMessages.find((message => 'system' === message.role)),
|
| 521 |
+
firstAssistant: prevMessages.find((message => 'assistant' === message.role)),
|
| 522 |
+
lastUser: prevMessages.findLast((message => 'user' === message.role)),
|
| 523 |
+
lastSystem: prevMessages.find((message => 'system' === message.role && '[Start a new chat]' !== message.content)),
|
| 524 |
+
lastAssistant: prevMessages.findLast((message => 'assistant' === message.role))
|
| 525 |
+
}
|
| 526 |
+
};
|
| 527 |
+
samePrompt = JSON.stringify(messages.filter((message => 'system' !== message.role)).sort()) === JSON.stringify(prevMessages.filter((message => 'system' !== message.role)).sort());
|
| 528 |
+
const sameCharDiffChat = !samePrompt && curPrompt.firstSystem?.content === prevPrompt.firstSystem?.content && curPrompt.firstUser?.content !== prevPrompt.firstUser?.content;
|
| 529 |
+
shouldRenew = Config.Settings.RenewAlways || !Conversation.uuid || prevImpersonated || !Config.Settings.RenewAlways && samePrompt || sameCharDiffChat;
|
| 530 |
+
retryRegen = Config.Settings.RetryRegenerate && samePrompt && null != Conversation.uuid;
|
| 531 |
+
samePrompt || (prevMessages = JSON.parse(JSON.stringify(messages)));
|
| 532 |
+
let type = '';
|
| 533 |
+
if (apiKey) { type = 'api'; } else if (retryRegen) { //if (retryRegen) {
|
| 534 |
+
type = 'R';
|
| 535 |
+
fetchAPI = await (async (signal, model) => {
|
| 536 |
+
let res;
|
| 537 |
+
const body = {
|
| 538 |
+
prompt: '',
|
| 539 |
+
parent_message_uuid: '',
|
| 540 |
+
timezone: AI.zone(),
|
| 541 |
+
attachments: [],
|
| 542 |
+
files: [],
|
| 543 |
+
rendering_mode: 'raw'
|
| 544 |
+
};
|
| 545 |
+
let headers = {
|
| 546 |
+
...AI.hdr(Conversation.uuid || ''),
|
| 547 |
+
Accept: 'text/event-stream',
|
| 548 |
+
Cookie: getCookies()
|
| 549 |
+
};
|
| 550 |
+
if (Config.Settings.Superfetch) {
|
| 551 |
+
const names = Object.keys(headers), values = Object.values(headers);
|
| 552 |
+
headers = names.map(((header, idx) => `${header}: ${values[idx]}`));
|
| 553 |
+
}
|
| 554 |
+
res = await (Config.Settings.Superfetch ? Superfetch : fetch)((Config.rProxy || AI.end()) + `/api/organizations/${uuidOrg || ''}/chat_conversations/${Conversation.uuid || ''}/retry_completion`, {
|
| 555 |
+
stream: true,
|
| 556 |
+
signal,
|
| 557 |
+
method: 'POST',
|
| 558 |
+
body: JSON.stringify(body),
|
| 559 |
+
headers
|
| 560 |
+
});
|
| 561 |
+
updateParams(res);
|
| 562 |
+
await checkResErr(res);
|
| 563 |
+
return res;
|
| 564 |
+
})(signal, model);
|
| 565 |
+
} else if (shouldRenew) {
|
| 566 |
+
Conversation.uuid && await deleteChat(Conversation.uuid);
|
| 567 |
+
fetchAPI = await (async signal => {
|
| 568 |
+
Conversation.uuid = randomUUID().toString();
|
| 569 |
+
Conversation.depth = 0;
|
| 570 |
+
const res = await (Config.Settings.Superfetch ? Superfetch : fetch)(`${Config.rProxy || AI.end()}/api/organizations/${uuidOrg}/chat_conversations`, {
|
| 571 |
+
signal,
|
| 572 |
+
headers: {
|
| 573 |
+
...AI.hdr(),
|
| 574 |
+
Cookie: getCookies()
|
| 575 |
+
},
|
| 576 |
+
method: 'POST',
|
| 577 |
+
body: JSON.stringify({
|
| 578 |
+
uuid: Conversation.uuid,
|
| 579 |
+
name: ''
|
| 580 |
+
})
|
| 581 |
+
});
|
| 582 |
+
updateParams(res);
|
| 583 |
+
await checkResErr(res);
|
| 584 |
+
return res;
|
| 585 |
+
})(signal);
|
| 586 |
+
type = 'r';
|
| 587 |
+
} else if (samePrompt) {} else {
|
| 588 |
+
const systemExperiment = !Config.Settings.RenewAlways && Config.Settings.SystemExperiments;
|
| 589 |
+
if (!systemExperiment || systemExperiment && Conversation.depth >= Config.SystemInterval) {
|
| 590 |
+
type = 'c-r';
|
| 591 |
+
Conversation.depth = 0;
|
| 592 |
+
} else {
|
| 593 |
+
type = 'c-c';
|
| 594 |
+
Conversation.depth++;
|
| 595 |
+
}
|
| 596 |
+
}
|
| 597 |
+
let {prompt, systems} = ((messages, type) => {
|
| 598 |
+
const rgxScenario = /^\[Circumstances and context of the dialogue: ([\s\S]+?)\.?\]$/i, rgxPerson = /^\[([\s\S]+?)'s personality: ([\s\S]+?)\]$/i, messagesClone = JSON.parse(JSON.stringify(messages)), realLogs = messagesClone.filter((message => [ 'user', 'assistant' ].includes(message.role))), sampleLogs = messagesClone.filter((message => message.name)), mergedLogs = [ ...sampleLogs, ...realLogs ];
|
| 599 |
+
mergedLogs.forEach(((message, idx) => {
|
| 600 |
+
const next = mergedLogs[idx + 1];
|
| 601 |
+
message.customname = (message => [ 'assistant', 'user' ].includes(message.role) && null != message.name && !(message.name in Replacements))(message);
|
| 602 |
+
if (next && !Config.Settings.xmlPlot) { //if (next) {
|
| 603 |
+
if ('name' in message && 'name' in next) {
|
| 604 |
+
if (message.name === next.name) {
|
| 605 |
+
message.content += '\n' + next.content;
|
| 606 |
+
next.merged = true;
|
| 607 |
+
}
|
| 608 |
+
} else if ('system' !== next.role) {
|
| 609 |
+
if (next.role === message.role) {
|
| 610 |
+
message.content += '\n' + next.content;
|
| 611 |
+
next.merged = true;
|
| 612 |
+
}
|
| 613 |
+
} else {
|
| 614 |
+
message.content += '\n' + next.content;
|
| 615 |
+
next.merged = true;
|
| 616 |
+
}
|
| 617 |
+
}
|
| 618 |
+
}));
|
| 619 |
+
const lastAssistant = realLogs.findLast((message => !message.merged && 'assistant' === message.role));
|
| 620 |
+
lastAssistant && Config.Settings.StripAssistant && (lastAssistant.strip = true);
|
| 621 |
+
const lastUser = realLogs.findLast((message => !message.merged && 'user' === message.role));
|
| 622 |
+
lastUser && Config.Settings.StripHuman && (lastUser.strip = true);
|
| 623 |
+
const systemMessages = messagesClone.filter((message => 'system' === message.role && !('name' in message)));
|
| 624 |
+
systemMessages.forEach(((message, idx) => {
|
| 625 |
+
const scenario = message.content.match(rgxScenario)?.[1], personality = message.content.match(rgxPerson);
|
| 626 |
+
if (scenario) {
|
| 627 |
+
message.content = Config.ScenarioFormat.replace(/{{scenario}}/gim, scenario);
|
| 628 |
+
message.scenario = true;
|
| 629 |
+
}
|
| 630 |
+
if (3 === personality?.length) {
|
| 631 |
+
message.content = Config.PersonalityFormat.replace(/{{char}}/gim, personality[1]).replace(/{{personality}}/gim, personality[2]);
|
| 632 |
+
message.personality = true;
|
| 633 |
+
}
|
| 634 |
+
message.main = 0 === idx;
|
| 635 |
+
message.jailbreak = idx === systemMessages.length - 1;
|
| 636 |
+
' ' === message.content && (message.discard = true);
|
| 637 |
+
}));
|
| 638 |
+
Config.Settings.AllSamples && !Config.Settings.NoSamples && realLogs.forEach((message => {
|
| 639 |
+
if (![ lastUser, lastAssistant ].includes(message)) {
|
| 640 |
+
if ('user' === message.role) {
|
| 641 |
+
message.name = message.customname ? message.name : 'example_user';
|
| 642 |
+
message.role = 'system';
|
| 643 |
+
} else if ('assistant' === message.role) {
|
| 644 |
+
message.name = message.customname ? message.name : 'example_assistant';
|
| 645 |
+
message.role = 'system';
|
| 646 |
+
} else if (!message.customname) {
|
| 647 |
+
throw Error('Invalid role ' + message.name);
|
| 648 |
+
}
|
| 649 |
+
}
|
| 650 |
+
}));
|
| 651 |
+
Config.Settings.NoSamples && !Config.Settings.AllSamples && sampleLogs.forEach((message => {
|
| 652 |
+
if ('example_user' === message.name) {
|
| 653 |
+
message.role = 'user';
|
| 654 |
+
} else if ('example_assistant' === message.name) {
|
| 655 |
+
message.role = 'assistant';
|
| 656 |
+
} else if (!message.customname) {
|
| 657 |
+
throw Error('Invalid role ' + message.name);
|
| 658 |
+
}
|
| 659 |
+
message.customname || delete message.name;
|
| 660 |
+
}));
|
| 661 |
+
let systems = [];
|
| 662 |
+
if (![ 'r', 'R', 'api' ].includes(type)) {
|
| 663 |
+
lastUser.strip = true;
|
| 664 |
+
systemMessages.forEach((message => message.discard = message.discard || 'c-c' === type ? !message.jailbreak : !message.jailbreak && !message.main));
|
| 665 |
+
systems = systemMessages.filter((message => !message.discard)).map((message => `"${message.content.substring(0, 25).replace(/\n/g, '\\n').trim()}..."`));
|
| 666 |
+
messagesClone.forEach((message => message.discard = message.discard || mergedLogs.includes(message) && ![ lastUser ].includes(message)));
|
| 667 |
+
}
|
| 668 |
+
const prompt = messagesClone.map(((message, idx) => {
|
| 669 |
+
if (message.merged || message.discard) {
|
| 670 |
+
return '';
|
| 671 |
+
}
|
| 672 |
+
if (message.content.length < 1) {
|
| 673 |
+
return message.content;
|
| 674 |
+
}
|
| 675 |
+
let spacing = '';
|
| 676 |
+
/******************************** */
|
| 677 |
+
if (Config.Settings.xmlPlot) {
|
| 678 |
+
idx > 0 && (spacing = '\n\n');
|
| 679 |
+
const prefix = message.customname ? message.role + ': ' + message.name.replaceAll('_', ' ') + ': ' : 'system' !== message.role || message.name ? Replacements[message.name || message.role] + ': ' : 'xmlPlot: ' + Replacements[message.role];
|
| 680 |
+
return `${spacing}${message.strip ? '' : prefix}${message.content}`;
|
| 681 |
+
} else {
|
| 682 |
+
/******************************** */
|
| 683 |
+
idx > 0 && (spacing = systemMessages.includes(message) ? '\n' : '\n\n');
|
| 684 |
+
const prefix = message.customname ? message.name.replaceAll('_', ' ') + ': ' : 'system' !== message.role || message.name ? Replacements[message.name || message.role] + ': ' : '' + Replacements[message.role];
|
| 685 |
+
return `${spacing}${message.strip ? '' : prefix}${'system' === message.role ? message.content : message.content.trim()}`;
|
| 686 |
+
} //
|
| 687 |
+
}));
|
| 688 |
+
return {
|
| 689 |
+
prompt: prompt.join(''), //genericFixes(prompt.join('')).trim(),
|
| 690 |
+
systems
|
| 691 |
+
};
|
| 692 |
+
})(messages, type);
|
| 693 |
+
/******************************** */
|
| 694 |
+
const legacy = /claude-([12]|instant)/i.test(model), messagesAPI = thirdKey || !legacy && !/<\|completeAPI\|>/.test(prompt) || /<\|messagesAPI\|>/.test(prompt), messagesLog = /<\|messagesLog\|>/.test(prompt), fusion = apiKey && messagesAPI && /<\|Fusion Mode\|>/.test(prompt), wedge = '\r';
|
| 695 |
+
const stopSet = /<\|stopSet *(\[.*?\]) *\|>/.exec(prompt)?.[1], stopRevoke = /<\|stopRevoke *(\[.*?\]) *\|>/.exec(prompt)?.[1];
|
| 696 |
+
if (stop_sequences || stopSet || stopRevoke) stop_sequences = JSON.parse(stopSet || '[]').concat(stop_sequences).concat(['\n\nHuman:', '\n\nAssistant:']).filter(item => !JSON.parse(stopRevoke || '[]').includes(item) && item);
|
| 697 |
+
apiKey && (type = oaiAPI ? 'oai_api' : messagesAPI ? 'msg_api' : type);
|
| 698 |
+
prompt = Config.Settings.xmlPlot ? xmlPlot(prompt, legacy && !/claude-2\.1/i.test(model)) : apiKey ? `\n\nHuman: ${genericFixes(prompt)}\n\nAssistant:` : genericFixes(prompt).trim();
|
| 699 |
+
Config.Settings.FullColon && (prompt = !legacy ?
|
| 700 |
+
prompt.replace(fusion ? /\n(?!\nAssistant:\s*$)(?=\n(Human|Assistant):)/gs : apiKey ? /(?<!\n\nHuman:.*)\n(?=\nAssistant:)|\n(?=\nHuman:)(?!.*\n\nAssistant:)/gs : /\n(?=\n(Human|Assistant):)/g, '\n' + wedge) :
|
| 701 |
+
prompt.replace(fusion ? /(?<=\n\nAssistant):(?!\s*$)|(?<=\n\nHuman):/gs : apiKey ? /(?<!\n\nHuman:.*)(?<=\n\nAssistant):|(?<=\n\nHuman):(?!.*\n\nAssistant:)/gs : /(?<=\n\n(Human|Assistant)):/g, '﹕'));
|
| 702 |
+
prompt = padtxt(prompt);
|
| 703 |
+
/******************************** */
|
| 704 |
+
console.log(`${model} [[2m${type}[0m]${!retryRegen && systems.length > 0 ? ' ' + systems.join(' [33m/[0m ') : ''}`);
|
| 705 |
+
'R' !== type || prompt || (prompt = '...regen...');
|
| 706 |
+
Logger?.write(`\n\n-------\n[${(new Date).toLocaleString()}]\n${Main}\n####### ${model} (${type})\n${JSON.stringify({FusionMode: fusion, PassParams: Config.Settings.PassParams, stop_sequences, temperature, top_k, top_p}, null, 2)}\n\n####### regex:\n${regexLog}\n####### PROMPT ${tokens}t:\n${prompt}\n--\n####### REPLY:\n`); //Logger?.write(`\n\n-------\n[${(new Date).toLocaleString()}]\n####### MODEL: ${model}\n####### PROMPT (${type}):\n${prompt}\n--\n####### REPLY:\n`);
|
| 707 |
+
retryRegen || (fetchAPI = await (async (signal, model, prompt, temperature, type) => {
|
| 708 |
+
/******************************** */
|
| 709 |
+
if (apiKey) {
|
| 710 |
+
let messages, system, key = apiKey[Math.floor(Math.random() * apiKey.length)];
|
| 711 |
+
if (messagesAPI) {
|
| 712 |
+
const rounds = prompt.replace(/^(?!.*\n\nHuman:)/s, '\n\nHuman:').split('\n\nHuman:');
|
| 713 |
+
messages = rounds.slice(1).flatMap(round => {
|
| 714 |
+
const turns = round.split('\n\nAssistant:');
|
| 715 |
+
return [{role: 'user', content: turns[0].trim()}].concat(turns.slice(1).flatMap(turn => [{role: 'assistant', content: turn.trim()}]));
|
| 716 |
+
}).reduce((acc, current) => {
|
| 717 |
+
if (Config.Settings.FullColon && acc.length > 0 && (acc[acc.length - 1].role === current.role || !acc[acc.length - 1].content)) {
|
| 718 |
+
acc[acc.length - 1].content += (current.role === 'user' ? 'Human' : 'Assistant').replace(/.*/, legacy ? '\n$&﹕ ' : '\n' + wedge + '\n$&: ') + current.content;
|
| 719 |
+
} else acc.push(current);
|
| 720 |
+
return acc;
|
| 721 |
+
}, []).filter(message => message.content), oaiAPI ? messages.unshift({role: 'system', content: rounds[0].trim()}) : system = rounds[0].trim();
|
| 722 |
+
messagesLog && console.log({system, messages});
|
| 723 |
+
}
|
| 724 |
+
const res = await fetch((api_rProxy || 'https://api.anthropic.com').replace(/(\/v1)? *$/, thirdKey ? '$1' : '/v1').trim('/') + (oaiAPI ? '/chat/completions' : messagesAPI ? '/messages' : '/complete'), {
|
| 725 |
+
method: 'POST',
|
| 726 |
+
signal,
|
| 727 |
+
headers: {
|
| 728 |
+
'anthropic-version': '2023-06-01',
|
| 729 |
+
'authorization': 'Bearer ' + key,
|
| 730 |
+
'Content-Type': 'application/json',
|
| 731 |
+
'User-Agent': AI.agent(),
|
| 732 |
+
'x-api-key': key,
|
| 733 |
+
},
|
| 734 |
+
body: JSON.stringify({
|
| 735 |
+
...oaiAPI || messagesAPI ? {
|
| 736 |
+
max_tokens : max_tokens_to_sample,
|
| 737 |
+
messages,
|
| 738 |
+
system
|
| 739 |
+
} : {
|
| 740 |
+
max_tokens_to_sample,
|
| 741 |
+
prompt
|
| 742 |
+
},
|
| 743 |
+
model,
|
| 744 |
+
stop_sequences,
|
| 745 |
+
stream: true,
|
| 746 |
+
// temperature,
|
| 747 |
+
top_k,
|
| 748 |
+
top_p
|
| 749 |
+
}),
|
| 750 |
+
});
|
| 751 |
+
await checkResErr(res);
|
| 752 |
+
return res;
|
| 753 |
+
}
|
| 754 |
+
/******************************** */
|
| 755 |
+
const attachments = [];
|
| 756 |
+
if (Config.Settings.PromptExperiments) {
|
| 757 |
+
let splitedprompt = prompt.split('\n\nPlainPrompt:'); //
|
| 758 |
+
prompt = splitedprompt[0]; //
|
| 759 |
+
attachments.push({
|
| 760 |
+
extracted_content: prompt,
|
| 761 |
+
file_name: 'paste.txt', //fileName(),
|
| 762 |
+
file_type: 'txt', //'text/plain',
|
| 763 |
+
file_size: Buffer.from(prompt).byteLength
|
| 764 |
+
});
|
| 765 |
+
prompt = 'r' === type ? Config.PromptExperimentFirst : Config.PromptExperimentNext;
|
| 766 |
+
splitedprompt.length > 1 && (prompt += splitedprompt[1]); //
|
| 767 |
+
}
|
| 768 |
+
let res;
|
| 769 |
+
const body = {
|
| 770 |
+
attachments,
|
| 771 |
+
files: [],
|
| 772 |
+
model: isPro || forceModel ? model : undefined,
|
| 773 |
+
rendering_mode: 'raw',
|
| 774 |
+
...Config.Settings.PassParams && {
|
| 775 |
+
max_tokens_to_sample, //
|
| 776 |
+
//stop_sequences, //
|
| 777 |
+
top_k, //
|
| 778 |
+
top_p, //
|
| 779 |
+
// temperature
|
| 780 |
+
},
|
| 781 |
+
prompt: prompt || '',
|
| 782 |
+
timezone: AI.zone()
|
| 783 |
+
};
|
| 784 |
+
let headers = {
|
| 785 |
+
...AI.hdr(Conversation.uuid || ''),
|
| 786 |
+
Accept: 'text/event-stream',
|
| 787 |
+
Cookie: getCookies()
|
| 788 |
+
};
|
| 789 |
+
res = await (Config.Settings.Superfetch ? Superfetch : fetch)(`${Config.rProxy || AI.end()}/api/organizations/${uuidOrg || ''}/chat_conversations/${Conversation.uuid || ''}/completion`, {
|
| 790 |
+
stream: true,
|
| 791 |
+
signal,
|
| 792 |
+
method: 'POST',
|
| 793 |
+
body: JSON.stringify(body),
|
| 794 |
+
headers
|
| 795 |
+
});
|
| 796 |
+
updateParams(res);
|
| 797 |
+
await checkResErr(res);
|
| 798 |
+
return res;
|
| 799 |
+
})(signal, model, prompt, temperature, type));
|
| 800 |
+
const response = Writable.toWeb(res);
|
| 801 |
+
clewdStream = new ClewdStream({
|
| 802 |
+
config: {
|
| 803 |
+
...Config,
|
| 804 |
+
Settings: {
|
| 805 |
+
...Config.Settings,
|
| 806 |
+
Superfetch: apiKey ? false : Config.Settings.Superfetch
|
| 807 |
+
}
|
| 808 |
+
}, //config: Config,
|
| 809 |
+
version: Main,
|
| 810 |
+
minSize: Config.BufferSize,
|
| 811 |
+
model,
|
| 812 |
+
streaming: true === body.stream,
|
| 813 |
+
abortControl,
|
| 814 |
+
source: fetchAPI
|
| 815 |
+
}, Logger);
|
| 816 |
+
titleTimer = setInterval((() => setTitle('recv ' + bytesToSize(clewdStream.size))), 300);
|
| 817 |
+
(!apiKey && Config.Settings.Superfetch) ? await Readable.toWeb(fetchAPI.body).pipeThrough(clewdStream).pipeTo(response) : await fetchAPI.body.pipeThrough(clewdStream).pipeTo(response); //Config.Settings.Superfetch ? await Readable.toWeb(fetchAPI.body).pipeThrough(clewdStream).pipeTo(response) : await fetchAPI.body.pipeThrough(clewdStream).pipeTo(response);
|
| 818 |
+
} catch (err) {
|
| 819 |
+
if ('AbortError' === err.name) {
|
| 820 |
+
res.end();
|
| 821 |
+
} else {
|
| 822 |
+
nochange = true, exceeded_limit = err.exceeded_limit; //
|
| 823 |
+
err.planned ? console.log(`[33m${err.status || 'Aborted'}![0m\n`) : console.error('[33mClewd:[0m\n%o', err); //err.planned || console.error('[33mClewd:[0m\n%o', err);
|
| 824 |
+
res.json({
|
| 825 |
+
error: {
|
| 826 |
+
message: 'clewd: ' + (err.message || err.name || err.type),
|
| 827 |
+
type: err.type || err.name || err.code,
|
| 828 |
+
param: null,
|
| 829 |
+
code: err.code || 500
|
| 830 |
+
}
|
| 831 |
+
}, 500);
|
| 832 |
+
}
|
| 833 |
+
}
|
| 834 |
+
clearInterval(titleTimer);
|
| 835 |
+
if (clewdStream) {
|
| 836 |
+
clewdStream.censored && console.warn('[33mlikely your account is hard-censored[0m');
|
| 837 |
+
prevImpersonated = clewdStream.impersonated;
|
| 838 |
+
exceeded_limit = clewdStream.error.exceeded_limit; //
|
| 839 |
+
clewdStream.error.status < 200 || clewdStream.error.status >= 300 || clewdStream.error.message === 'Overloaded' && (nochange = true); //
|
| 840 |
+
setTitle('ok ' + bytesToSize(clewdStream.size));
|
| 841 |
+
if (clewdStream.compModel && !(AI.mdl().includes(clewdStream.compModel) || Config.unknownModels.includes(clewdStream.compModel)) && !apiKey) {
|
| 842 |
+
Config.unknownModels.push(clewdStream.compModel);
|
| 843 |
+
writeSettings(Config);
|
| 844 |
+
}
|
| 845 |
+
console.log(`${200 == fetchAPI.status ? '[32m' : '[33m'}${fetchAPI.status}![0m\n`);
|
| 846 |
+
clewdStream.empty();
|
| 847 |
+
}
|
| 848 |
+
const shouldChange = exceeded_limit || !nochange && Config.Cookiecounter > 0 && changeflag++ >= Config.Cookiecounter - 1; //
|
| 849 |
+
if (!apiKey && (shouldChange || prevImpersonated)) { //if (prevImpersonated) {
|
| 850 |
+
try {
|
| 851 |
+
await deleteChat(Conversation.uuid);
|
| 852 |
+
} catch (err) {}
|
| 853 |
+
/******************************** */
|
| 854 |
+
if (shouldChange) {
|
| 855 |
+
exceeded_limit && console.log(`[35mExceeded limit![0m\n`);
|
| 856 |
+
changeflag = 0;
|
| 857 |
+
CookieChanger();
|
| 858 |
+
}
|
| 859 |
+
/******************************** */
|
| 860 |
+
}
|
| 861 |
+
}));
|
| 862 |
+
})(req, res);
|
| 863 |
+
break;
|
| 864 |
+
|
| 865 |
+
case '/v1/complete':
|
| 866 |
+
res.json({
|
| 867 |
+
error: {
|
| 868 |
+
message: 'clewd: Set "Chat Completion source" to OpenAI instead of Claude. Enable "External" models aswell',
|
| 869 |
+
code: 404
|
| 870 |
+
}
|
| 871 |
+
}, 404);
|
| 872 |
+
break;
|
| 873 |
+
|
| 874 |
+
default:
|
| 875 |
+
!['/', '/api', '/v1', '/favicon.ico'].includes(req.url) && (console.log('unknown request: ' + req.url)); //console.log('unknown request: ' + req.url);
|
| 876 |
+
res.writeHead(200, {'Content-Type': 'text/html'}); //
|
| 877 |
+
res.write(`Cannot Get`); //
|
| 878 |
+
res.end(); //res.json(// {// error: {// message: '404 Not Found',// type: 404,// param: null,// code: 404// }//}, 404);
|
| 879 |
+
}
|
| 880 |
+
}));
|
| 881 |
+
|
| 882 |
+
!async function() {
|
| 883 |
+
await (async () => {
|
| 884 |
+
if (exists(ConfigPath)) {
|
| 885 |
+
const userConfig = require(ConfigPath), validConfigs = Object.keys(Config), parsedConfigs = Object.keys(userConfig), parsedSettings = Object.keys(userConfig.Settings), invalidConfigs = parsedConfigs.filter((config => !validConfigs.includes(config))), validSettings = Object.keys(Config.Settings);
|
| 886 |
+
UnknownSettings = parsedSettings.filter((setting => !validSettings.includes(setting)));
|
| 887 |
+
invalidConfigs.forEach((config => {
|
| 888 |
+
console.warn(`unknown config in config.js: [33m${config}[0m`);
|
| 889 |
+
}));
|
| 890 |
+
UnknownSettings.forEach((setting => {
|
| 891 |
+
console.warn(`unknown setting in config.js: [33mSettings.${setting}[0m`);
|
| 892 |
+
}));
|
| 893 |
+
const missingConfigs = validConfigs.filter((config => !parsedConfigs.includes(config))), missingSettings = validSettings.filter((config => !parsedSettings.includes(config)));
|
| 894 |
+
missingConfigs.forEach((config => {
|
| 895 |
+
console.warn(`adding missing config in config.js: [33m${config}[0m`);
|
| 896 |
+
userConfig[config] = Config[config];
|
| 897 |
+
}));
|
| 898 |
+
missingSettings.forEach((setting => {
|
| 899 |
+
console.warn(`adding missing setting in config.js: [33mSettings.${setting}[0m`);
|
| 900 |
+
userConfig.Settings[setting] = Config.Settings[setting];
|
| 901 |
+
}));
|
| 902 |
+
ChangedSettings = parsedSettings.filter((setting => Config.Settings[setting] !== userConfig.Settings[setting]));
|
| 903 |
+
(missingConfigs.length > 0 || missingSettings.length > 0) && await writeSettings(userConfig);
|
| 904 |
+
userConfig.Settings.LogMessages && (Logger = createWriteStream(LogPath));
|
| 905 |
+
Config = {
|
| 906 |
+
...Config,
|
| 907 |
+
...userConfig
|
| 908 |
+
};
|
| 909 |
+
} else {
|
| 910 |
+
Config.Cookie = 'SET YOUR COOKIE HERE';
|
| 911 |
+
writeSettings(Config, true);
|
| 912 |
+
}
|
| 913 |
+
})();
|
| 914 |
+
/***************************** */
|
| 915 |
+
for (let key in Config) {
|
| 916 |
+
if (key === 'Settings') {
|
| 917 |
+
for (let setting in Config.Settings) {
|
| 918 |
+
Config.Settings[setting] = process.env[setting] ? convertToType(process.env[setting]) : Config.Settings[setting];
|
| 919 |
+
}
|
| 920 |
+
} else {
|
| 921 |
+
Config[key] = process.env[key] ? convertToType(process.env[key]) : Config[key];
|
| 922 |
+
}
|
| 923 |
+
}
|
| 924 |
+
Config.rProxy = Config.rProxy.replace(/\/$/, '');
|
| 925 |
+
Config.CookieArray = [...new Set([Config.CookieArray].join(',').match(/(claude[-_][a-z0-9-_]*?@)?(sessionKey=)?sk-ant-sid01-[\w-]{86}-[\w-]{6}AA/g))];
|
| 926 |
+
Config.unknownModels = Config.unknownModels.reduce((prev, cur) => !cur || prev.includes(cur) || AI.mdl().includes(cur) ? prev : [...prev, cur], []);
|
| 927 |
+
writeSettings(Config);
|
| 928 |
+
currentIndex = Config.CookieIndex > 0 ? Config.CookieIndex - 1 : Config.Cookiecounter >= 0 ? Math.floor(Math.random() * Config.CookieArray.length) : 0;
|
| 929 |
+
/***************************** */
|
| 930 |
+
Proxy.listen(Config.Port, Config.Ip, onListen);
|
| 931 |
+
Proxy.on('error', (err => {
|
| 932 |
+
console.error('Proxy error\n%o', err);
|
| 933 |
+
}));
|
| 934 |
+
}();
|
| 935 |
+
|
| 936 |
+
const cleanup = async () => {
|
| 937 |
+
console.log('cleaning...');
|
| 938 |
+
try {
|
| 939 |
+
await deleteChat(Conversation.uuid);
|
| 940 |
+
SuperfetchFoldersRm();
|
| 941 |
+
Logger?.close();
|
| 942 |
+
} catch (err) {}
|
| 943 |
+
process.exit();
|
| 944 |
+
};
|
| 945 |
+
|
| 946 |
+
process.on('SIGHUP', cleanup);
|
| 947 |
+
|
| 948 |
+
process.on('SIGTERM', cleanup);
|
| 949 |
+
|
| 950 |
+
process.on('SIGINT', cleanup);
|
| 951 |
+
|
| 952 |
+
process.on('exit', (async () => {
|
| 953 |
+
console.log('exiting...');
|
| 954 |
+
}));
|
lib/clewd-stream.js
ADDED
|
@@ -0,0 +1,195 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/*
|
| 2 |
+
* https://rentry.org/teralomaniac_clewd
|
| 3 |
+
* https://github.com/teralomaniac/clewd
|
| 4 |
+
*/
|
| 5 |
+
'use strict';
|
| 6 |
+
|
| 7 |
+
const {AI, genericFixes, DangerChars, encodeDataJSON, indexOfAny, cleanJSON, checkResErr} = require('./clewd-utils'), Decoder = new TextDecoder;
|
| 8 |
+
|
| 9 |
+
class ClewdStream extends TransformStream {
|
| 10 |
+
constructor(opts, logger) {
|
| 11 |
+
super({
|
| 12 |
+
transform: (chunk, controller) => {
|
| 13 |
+
this.#handle(chunk, controller);
|
| 14 |
+
},
|
| 15 |
+
flush: controller => {
|
| 16 |
+
this.#done(controller);
|
| 17 |
+
}
|
| 18 |
+
});
|
| 19 |
+
this.#logger = logger;
|
| 20 |
+
this.#version = opts.version;
|
| 21 |
+
this.#config = opts.config;
|
| 22 |
+
this.#model = opts.model;
|
| 23 |
+
this.#streaming = opts.streaming;
|
| 24 |
+
this.#minSize = opts.minSize || 8;
|
| 25 |
+
this.#abortControl = opts.abortControl;
|
| 26 |
+
this.#source = opts.source;
|
| 27 |
+
}
|
| 28 |
+
#source=void 0;
|
| 29 |
+
#ended=false;
|
| 30 |
+
#streaming=void 0;
|
| 31 |
+
#minSize=void 0;
|
| 32 |
+
#compOK='';
|
| 33 |
+
#compRaw='';
|
| 34 |
+
#logger=void 0;
|
| 35 |
+
#version=void 0;
|
| 36 |
+
#config=void 0;
|
| 37 |
+
#abortControl=void 0;
|
| 38 |
+
#model=void 0;
|
| 39 |
+
#compAll=[];
|
| 40 |
+
#recvLength=0;
|
| 41 |
+
#stopLoc=void 0;
|
| 42 |
+
#stopReason=void 0;
|
| 43 |
+
#hardCensor=false;
|
| 44 |
+
#impersonated=false;
|
| 45 |
+
#error={}; //
|
| 46 |
+
#compModel=''; //
|
| 47 |
+
get size() {
|
| 48 |
+
return this.#recvLength;
|
| 49 |
+
}
|
| 50 |
+
get total() {
|
| 51 |
+
return this.#compAll.length;
|
| 52 |
+
}
|
| 53 |
+
get censored() {
|
| 54 |
+
return this.#hardCensor;
|
| 55 |
+
}
|
| 56 |
+
get impersonated() {
|
| 57 |
+
return this.#impersonated;
|
| 58 |
+
}
|
| 59 |
+
/************************ */
|
| 60 |
+
get error() {
|
| 61 |
+
return this.#error;
|
| 62 |
+
}
|
| 63 |
+
get compModel() {
|
| 64 |
+
return this.#compModel;
|
| 65 |
+
}
|
| 66 |
+
/************************ */
|
| 67 |
+
empty() {
|
| 68 |
+
this.#compOK = this.#compRaw = '';
|
| 69 |
+
this.#compAll = [];
|
| 70 |
+
this.#recvLength = 0;
|
| 71 |
+
}
|
| 72 |
+
#collectBuf() {
|
| 73 |
+
const valid = [ ...this.#compOK ], selection = valid.splice(0, Math.min(this.#minSize, valid.length)).join('');
|
| 74 |
+
this.#compOK = valid.join('');
|
| 75 |
+
return selection;
|
| 76 |
+
}
|
| 77 |
+
#err(err, controller) {
|
| 78 |
+
this.#logger?.write(JSON.stringify(err, null, 4));
|
| 79 |
+
const message = `## ${this.#version}\n**${this.#model} error**:\n${err.status || err.code || err.type}\n\n\`\`\`${err.message}\`\`\`\n\nFAQ: <a href="https://rentry.org/teralomaniac_clewd" target="FAQ">https://rentry.org/teralomaniac_clewd</a>`;
|
| 80 |
+
this.#error = err; //
|
| 81 |
+
this.#enqueue(this.#build(message), controller);
|
| 82 |
+
return this.#endEarly(controller);
|
| 83 |
+
}
|
| 84 |
+
#build(selection) {
|
| 85 |
+
this.#logger?.write(selection);
|
| 86 |
+
const completion = this.#streaming ? {
|
| 87 |
+
choices: [ {
|
| 88 |
+
delta: {
|
| 89 |
+
content: genericFixes(selection)
|
| 90 |
+
}
|
| 91 |
+
} ]
|
| 92 |
+
} : {
|
| 93 |
+
choices: [ {
|
| 94 |
+
message: {
|
| 95 |
+
content: genericFixes(selection)
|
| 96 |
+
}
|
| 97 |
+
} ]
|
| 98 |
+
};
|
| 99 |
+
return this.#streaming ? encodeDataJSON(completion) : JSON.stringify(completion);
|
| 100 |
+
}
|
| 101 |
+
#enqueue(selection, controller) {
|
| 102 |
+
this.#ended || controller.enqueue(selection);
|
| 103 |
+
}
|
| 104 |
+
#print() {}
|
| 105 |
+
async #done(controller) {
|
| 106 |
+
this.#compRaw.length > 0 && await this.#parseBuf(this.#compRaw, controller);
|
| 107 |
+
this.#streaming ? this.#compOK.length > 0 && this.#enqueue(this.#build(this.#compOK), controller) : this.#enqueue(this.#build(this.#compAll.join('')), controller);
|
| 108 |
+
this.#compAll?.[0] === Buffer.from([ 73, 32, 97, 112, 111, 108, 111, 103, 105, 122, 101, 44, 32, 98, 117, 116, 32, 73, 32, 119, 105, 108, 108, 32, 110, 111, 116, 32, 112, 114, 111, 118, 105, 100, 101, 32, 97, 110, 121, 32, 114, 101, 115, 112, 111, 110, 115, 101, 115, 32, 116, 104, 97, 116, 32, 118, 105, 111, 108, 97, 116, 101, 32, 65, 110, 116, 104, 114, 111, 112, 105, 99, 39, 115, 32, 65, 99, 99, 101, 112, 116, 97, 98, 108, 101, 32, 85, 115, 101, 32, 80, 111, 108, 105, 99, 121, 32, 111, 114, 32, 99, 111, 117, 108, 100, 32, 112, 114, 111, 109, 111, 116, 101, 32, 104, 97, 114, 109, 46 ]).toString() && (this.#hardCensor = true);
|
| 109 |
+
if (!this.#ended && 0 === this.total) {
|
| 110 |
+
const err = `## ${this.#version}\n**error**:\n\n\`\`\`Received no valid replies at all\`\`\`\n\nFAQ: <a href="https://rentry.org/teralomaniac_clewd" target="FAQ">https://rentry.org/teralomaniac_clewd</a>`;
|
| 111 |
+
this.#enqueue(this.#build(err), controller);
|
| 112 |
+
}
|
| 113 |
+
this.#streaming && this.#enqueue('data: [DONE]\n\n', controller);
|
| 114 |
+
this.#print();
|
| 115 |
+
this.#ended = true;
|
| 116 |
+
}
|
| 117 |
+
#endEarly(controller) {
|
| 118 |
+
if (!this.#ended) {
|
| 119 |
+
this.#streaming && this.#enqueue('data: [DONE]\n\n', controller);
|
| 120 |
+
this.#config.Settings.Superfetch && this.#source.rape();
|
| 121 |
+
this.#abortControl.abort();
|
| 122 |
+
controller.terminate();
|
| 123 |
+
this.#print();
|
| 124 |
+
this.#ended = true;
|
| 125 |
+
}
|
| 126 |
+
}
|
| 127 |
+
#impersonationCheck(reply, controller) {
|
| 128 |
+
const fakeAny = indexOfAny(reply);
|
| 129 |
+
if (fakeAny > -1) {
|
| 130 |
+
this.#impersonated = true;
|
| 131 |
+
if (this.#config.Settings.PreventImperson) {
|
| 132 |
+
const selection = reply.substring(0, fakeAny);
|
| 133 |
+
this.#enqueue(this.#build(selection), controller);
|
| 134 |
+
this.#endEarly(controller);
|
| 135 |
+
}
|
| 136 |
+
}
|
| 137 |
+
}
|
| 138 |
+
async #handle(chunk, controller) {
|
| 139 |
+
if ('string' != typeof chunk) {
|
| 140 |
+
this.#recvLength += chunk.byteLength;
|
| 141 |
+
chunk = Decoder.decode(chunk, {'stream': true}); //chunk = Decoder.decode(chunk);
|
| 142 |
+
} else {
|
| 143 |
+
this.#recvLength += Buffer.byteLength(chunk);
|
| 144 |
+
}
|
| 145 |
+
this.#compRaw += chunk.replace(/event: [\w]+\s*|\r/gi,''); //this.#compRaw += chunk;
|
| 146 |
+
const substr = this.#compRaw.split('\n\n'), lastMsg = substr.length - 1;
|
| 147 |
+
0 !== substr[lastMsg].length ? this.#compRaw = substr[lastMsg] : this.#compRaw = '';
|
| 148 |
+
for (let i = 0; i < lastMsg; i++) {
|
| 149 |
+
await this.#parseBuf(substr[i], controller);
|
| 150 |
+
}
|
| 151 |
+
}
|
| 152 |
+
async #parseBuf(json, controller) {
|
| 153 |
+
if (!json) {
|
| 154 |
+
return;
|
| 155 |
+
}
|
| 156 |
+
if (this.#ended) {
|
| 157 |
+
return;
|
| 158 |
+
}
|
| 159 |
+
let parsed, delayChunk;
|
| 160 |
+
try {
|
| 161 |
+
parsed = JSON.parse(cleanJSON(json));
|
| 162 |
+
if (parsed.error) {
|
| 163 |
+
const err = await checkResErr(JSON.stringify({
|
| 164 |
+
error: {
|
| 165 |
+
...parsed.error
|
| 166 |
+
},
|
| 167 |
+
status: this.#source.status,
|
| 168 |
+
superfetch: this.#source.superfetch
|
| 169 |
+
}), false);
|
| 170 |
+
delete err.stack;
|
| 171 |
+
return this.#err(err, controller);
|
| 172 |
+
}
|
| 173 |
+
if (!this.#compModel && parsed.model) this.#compModel = parsed.model;
|
| 174 |
+
if (parsed.completion || parsed.delta?.text || parsed.choices?.[0]?.delta?.content) { //if (parsed.completion) {
|
| 175 |
+
parsed.completion = genericFixes(parsed.completion || parsed.delta?.text || parsed.choices?.[0]?.delta?.content); //parsed.completion = genericFixes(parsed.completion);
|
| 176 |
+
this.#compOK += parsed.completion;
|
| 177 |
+
this.#compAll.push(parsed.completion);
|
| 178 |
+
delayChunk = DangerChars.some((char => this.#compOK.endsWith(char) || parsed.completion.startsWith(char)));
|
| 179 |
+
}
|
| 180 |
+
!this.#stopLoc && parsed.stop && (this.#stopLoc = parsed.stop.replace(/\n/g, '\\n'));
|
| 181 |
+
!this.#stopReason && parsed.stop_reason && (this.#stopReason = parsed.stop_reason);
|
| 182 |
+
if (this.#streaming) {
|
| 183 |
+
delayChunk && this.#impersonationCheck(this.#compOK, controller);
|
| 184 |
+
for (;!delayChunk && this.#compOK.length >= this.#minSize; ) {
|
| 185 |
+
const selection = this.#collectBuf();
|
| 186 |
+
this.#enqueue(this.#build(selection), controller);
|
| 187 |
+
}
|
| 188 |
+
} else {
|
| 189 |
+
delayChunk && this.#impersonationCheck(this.#compAll.join(''), controller);
|
| 190 |
+
}
|
| 191 |
+
} catch (err) {}
|
| 192 |
+
}
|
| 193 |
+
}
|
| 194 |
+
|
| 195 |
+
module.exports = ClewdStream;
|
lib/clewd-superfetch.js
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/*
|
| 2 |
+
* https://gitgud.io/ahsk/clewd
|
| 3 |
+
* https://github.com/h-a-s-k/clewd
|
| 4 |
+
*/"use strict";const{spawn:e}=require("node:child_process"),{randomInt:r}=require("node:crypto"),{relative:t,resolve:s,join:n,normalize:o,basename:i,dirname:a}=require("node:path"),{writeFileSync:d,unlinkSync:c,existsSync:u,mkdirSync:m,rmdirSync:l}=require("node:fs"),{ReadableStream:f}=require("node:stream/web"),p=e=>"win32"===process.platform?".\\"+e:e,h=e=>"win32"===process.platform||e.indexOf(" ")>-1?`"${e}"`:e,w={win32:{x64:"clewd-superfetch-win-amd64.exe",ia32:"clewd-superfetch-win-ia32.exe"},darwin:{x64:"clewd-superfetch-linux-amd64",arm64:"clewd-superfetch-linux-arm64"},linux:{x64:"clewd-superfetch-linux-amd64",arm64:"clewd-superfetch-linux-arm64"},android:{x64:"clewd-superfetch-linux-amd64",arm64:"clewd-superfetch-linux-arm64"}}[process.platform]?.[process.arch],y=""+o(t("./","./bin/"+w)),b=o(s(__dirname,y,"../","../")),S=s(b,y),x=a(S),_=""+o(s(x,"./cfg")),g=""+o(s(x,"./pyld")),v=""+o(s(x,"./hdr")),O=[123,34,115,101,99,45,99,104,45,117,97,34,58,34,92,34,78,111,116,95,65,32,66,114,97,110,100,92,34,59,118,61,92,34,56,92,34,44,32,92,34,67,104,114,111,109,105,117,109,92,34,59,118,61,92,34,49,50,48,92,34,44,32,92,34,71,111,111,103,108,101,32,67,104,114,111,109,101,92,34,59,118,61,92,34,49,50,48,92,34,34,44,34,115,101,99,45,99,104,45,117,97,45,109,111,98,105,108,101,34,58,34,63,48,34,44,34,115,101,99,45,99,104,45,117,97,45,112,108,97,116,102,111,114,109,34,58,34,92,34,109,97,99,79,83,92,34,34,44,34,85,112,103,114,97,100,101,45,73,110,115,101,99,117,114,101,45,82,101,113,117,101,115,116,115,34,58,49,44,34,85,115,101,114,45,65,103,101,110,116,34,58,34,77,111,122,105,108,108,97,47,53,46,48,32,40,77,97,99,105,110,116,111,115,104,59,32,73,110,116,101,108,32,77,97,99,32,79,83,32,88,32,49,48,95,49,53,95,55,41,32,65,112,112,108,101,87,101,98,75,105,116,47,53,51,55,46,51,54,32,40,75,72,84,77,76,44,32,108,105,107,101,32,71,101,99,107,111,41,32,67,104,114,111,109,101,47,49,50,48,46,48,46,48,46,48,32,83,97,102,97,114,105,47,53,51,55,46,51,54,34,44,34,65,99,99,101,112,116,34,58,34,116,101,120,116,47,104,116,109,108,44,97,112,112,108,105,99,97,116,105,111,110,47,120,104,116,109,108,43,120,109,108,44,97,112,112,108,105,99,97,116,105,111,110,47,120,109,108,59,113,61,48,46,57,44,105,109,97,103,101,47,97,118,105,102,44,105,109,97,103,101,47,119,101,98,112,44,105,109,97,103,101,47,97,112,110,103,44,42,47,42,59,113,61,48,46,56,44,97,112,112,108,105,99,97,116,105,111,110,47,115,105,103,110,101,100,45,101,120,99,104,97,110,103,101,59,118,61,98,51,59,113,61,48,46,55,34,44,34,83,101,99,45,70,101,116,99,104,45,83,105,116,101,34,58,34,110,111,110,101,34,44,34,83,101,99,45,70,101,116,99,104,45,77,111,100,101,34,58,34,110,97,118,105,103,97,116,101,34,44,34,83,101,99,45,70,101,116,99,104,45,85,115,101,114,34,58,34,63,49,34,44,34,83,101,99,45,70,101,116,99,104,45,68,101,115,116,34,58,34,100,111,99,117,109,101,110,116,34,44,34,65,99,99,101,112,116,45,69,110,99,111,100,105,110,103,34,58,34,103,122,105,112,44,32,100,101,102,108,97,116,101,44,32,98,114,34,44,34,65,99,99,101,112,116,45,76,97,110,103,117,97,103,101,34,58,34,101,110,45,85,83,44,101,110,59,113,61,48,46,57,34,125],j=[91,34,45,45,99,105,112,104,101,114,115,32,84,76,83,95,65,69,83,95,49,50,56,95,71,67,77,95,83,72,65,50,53,54,44,84,76,83,95,65,69,83,95,50,53,54,95,71,67,77,95,83,72,65,51,56,52,44,84,76,83,95,67,72,65,67,72,65,50,48,95,80,79,76,89,49,51,48,53,95,83,72,65,50,53,54,44,69,67,68,72,69,45,69,67,68,83,65,45,65,69,83,49,50,56,45,71,67,77,45,83,72,65,50,53,54,44,69,67,68,72,69,45,82,83,65,45,65,69,83,49,50,56,45,71,67,77,45,83,72,65,50,53,54,44,69,67,68,72,69,45,69,67,68,83,65,45,65,69,83,50,53,54,45,71,67,77,45,83,72,65,51,56,52,44,69,67,68,72,69,45,82,83,65,45,65,69,83,50,53,54,45,71,67,77,45,83,72,65,51,56,52,44,69,67,68,72,69,45,69,67,68,83,65,45,67,72,65,67,72,65,50,48,45,80,79,76,89,49,51,48,53,44,69,67,68,72,69,45,82,83,65,45,67,72,65,67,72,65,50,48,45,80,79,76,89,49,51,48,53,44,69,67,68,72,69,45,82,83,65,45,65,69,83,49,50,56,45,83,72,65,44,69,67,68,72,69,45,82,83,65,45,65,69,83,50,53,54,45,83,72,65,44,65,69,83,49,50,56,45,71,67,77,45,83,72,65,50,53,54,44,65,69,83,50,53,54,45,71,67,77,45,83,72,65,51,56,52,44,65,69,83,49,50,56,45,83,72,65,44,65,69,83,50,53,54,45,83,72,65,34,44,34,45,45,104,116,116,112,50,34,44,34,45,45,104,116,116,112,50,45,115,101,116,116,105,110,103,115,32,39,49,58,54,53,53,51,54,59,50,58,48,59,52,58,54,50,57,49,52,53,54,59,54,58,50,54,50,49,52,52,39,34,44,34,45,45,104,116,116,112,50,45,119,105,110,100,111,119,45,117,112,100,97,116,101,32,49,53,54,54,51,49,48,53,34,44,34,45,45,99,111,109,112,114,101,115,115,101,100,34,44,34,45,45,101,99,104,32,71,82,69,65,83,69,34,44,34,45,45,116,108,115,118,49,46,50,34,44,34,45,45,97,108,112,115,34,44,34,45,45,116,108,115,45,112,101,114,109,117,116,101,45,101,120,116,101,110,115,105,111,110,115,34,44,34,45,45,99,101,114,116,45,99,111,109,112,114,101,115,115,105,111,110,32,98,114,111,116,108,105,34,93],$=(e=false)=>{if(!w||!u(S)){e&&console.warn(`superfetch [[31merr[0m] unavailable for ${process.platform}-${process.arch}, use 3.8.5 for the time being\n`);return false}e&&console.log(`superfetch [[32mfound[0m] ${t(__dirname,S)}\n`);return true},q=(i,a)=>{a.headers??={};"string"!=typeof a.body&&(a.body=a.body?JSON.stringify(a.body):"");if(!$())return;const u=r(1,2e4).toString(),m=o(t(b,s(_,u))),l=o(t(b,s(g,u))),f=o(t(b,s(v,u))),w=o(t("./","bin/ca"));let x={...JSON.parse(Buffer.from(O).toString()),...a.headers};x=Object.entries(x).map((([e,r])=>`${e}: ${r}`));const q=h(p(m)),A=h(p(f)),L=h(p(l)),k=["-v","--http2","--cacert",""+h(p(w)),"--config",""+q,"--header","@"+A],J=[...JSON.parse(Buffer.from(j).toString()),"-X "+(a.method||"GET")];d(n(__dirname,m),J.join("\n"));d(n(__dirname,f),x.join("\n"));a.body&&d(n(__dirname,l),a.body);if("POST"===a.method||"PUT"===a.method||"PATCH"===a.method){k.push("--data");k.push("@"+L)}return new Promise((r=>{const t=e("android"===process.platform?S:y,[...k,""+i],{cwd:b,windowsHide:true,killSignal:"SIGKILL",windowsVerbatimArguments:true,detached:"win32"!==process.platform});t.superfetch=true;t.rape=function(){this.stdout?.end();this.stderr?.end()}.bind(t);t.once("spawn",(()=>{t.stream=a.stream||false;t.id=u;if(t.stream){Object.defineProperty(t,"body",{get:()=>t.stdout});return r(t)}t.body="";t.stdout.on("data",(e=>t.body+=e.toString()));t.json=async()=>JSON.parse(t.body);t.text=async()=>t.body;t.stdout.once("end",(()=>r(t)))}));t.once("error",(e=>{console.warn("superfetch [[31merr[0m]",e)}));t.once("close",(()=>{(e=>{try{c(n(__dirname,m));c(n(__dirname,f));a.body&&c(n(__dirname,l))}catch(e){}e.stdout.removeAllListeners();e.stderr.removeAllListeners();e.stream&&e.body.removeAllListeners()})(t)}));t.stderr.on("data",(e=>{const r=/HTTP\/2 (\d{3})+/g,s=(e=e.toString().trim()).match(r);if(!t.status&&s){const s=r.exec(e);t.status=+s[1]}const n=/(?:< )(.+?)(?:: )(.+)/g,o=e.match(n);if(o){const e={};o.forEach((r=>{const t=r.split(n);e[t?.[1]]=t?.[2]}));t.headers=e}}))}))};module.exports={SuperfetchFoldersMk:()=>{m(_,{recursive:true});m(g,{recursive:true});m(v,{recursive:true})},SuperfetchFoldersRm:()=>{l(_,{recursive:true});l(g,{recursive:true});l(v,{recursive:true})},ClewdSuperfetch:q,SuperfetchAvailable:$,SuperfetchRelative:y};
|
lib/clewd-utils.js
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/*
|
| 2 |
+
* https://rentry.org/teralomaniac_clewd
|
| 3 |
+
* https://github.com/teralomaniac/clewd
|
| 4 |
+
*/
|
| 5 |
+
'use strict';
|
| 6 |
+
|
| 7 |
+
const {randomInt, randomBytes} = require('node:crypto'), {version: Version} = require('../package.json'), Encoder = (new TextDecoder,
|
| 8 |
+
new TextEncoder), Main = 'clewd修改版 v' + Version + '(11) by tera', Replacements = {
|
| 9 |
+
user: 'Human',
|
| 10 |
+
assistant: 'Assistant',
|
| 11 |
+
system: '',
|
| 12 |
+
example_user: 'H',
|
| 13 |
+
example_assistant: 'A'
|
| 14 |
+
}, DangerChars = [ ...new Set([ ...Object.values(Replacements).join(''), ...'\n', ...':', ...'\\n' ]) ].filter((char => ' ' !== char)).sort(), AI = {
|
| 15 |
+
end: () => Buffer.from([ 104, 116, 116, 112, 115, 58, 47, 47, 97, 112, 105, 46, 99, 108, 97, 117, 100, 101, 46, 97, 105 ]).toString(),
|
| 16 |
+
mdl: () => JSON.parse(Buffer.from([ 91, 34, 99, 108, 97, 117, 100, 101, 45, 51, 45, 53, 45, 115, 111, 110, 110, 101, 116, 45, 50, 48, 50, 52, 48, 54, 50, 48, 34, 44, 34, 99, 108, 97, 117, 100, 101, 45, 51, 45, 111, 112, 117, 115, 45, 50, 48, 50, 52, 48, 50, 50, 57, 34, 44, 34, 99, 108, 97, 117, 100, 101, 45, 51, 45, 115, 111, 110, 110, 101, 116, 45, 50, 48, 50, 52, 48, 50, 50, 57, 34, 44, 34, 99, 108, 97, 117, 100, 101, 45, 51, 45, 104, 97, 105, 107, 117, 45, 50, 48, 50, 52, 48, 51, 48, 55, 34, 44, 34, 99, 108, 97, 117, 100, 101, 45, 50, 46, 49, 34, 44, 34, 99, 108, 97, 117, 100, 101, 45, 50, 46, 48, 34, 44, 34, 99, 108, 97, 117, 100, 101, 45, 49, 46, 51, 34, 44, 34, 99, 108, 97, 117, 100, 101, 45, 105, 110, 115, 116, 97, 110, 116, 45, 49, 46, 50, 34, 44, 34, 99, 108, 97, 117, 100, 101, 45, 105, 110, 115, 116, 97, 110, 116, 45, 49, 46, 49, 34, 93 ]).toString()),
|
| 17 |
+
zone: () => Buffer.from([ 65, 109, 101, 114, 105, 99, 97, 47, 78, 101, 119, 95, 89, 111, 114, 107 ]).toString(),
|
| 18 |
+
agent: () => Buffer.from([ 77, 111, 122, 105, 108, 108, 97, 47, 53, 46, 48, 32, 40, 87, 105, 110, 100, 111, 119, 115, 32, 78, 84, 32, 49, 48, 46, 48, 59, 32, 87, 105, 110, 54, 52, 59, 32, 120, 54, 52, 41, 32, 65, 112, 112, 108, 101, 87, 101, 98, 75, 105, 116, 47, 53, 51, 55, 46, 51, 54, 32, 40, 75, 72, 84, 77, 76, 44, 32, 108, 105, 107, 101, 32, 71, 101, 99, 107, 111, 41, 32, 67, 104, 114, 111, 109, 101, 47, 49, 49, 54, 46, 48, 46, 48, 46, 48, 32, 83, 97, 102, 97, 114, 105, 47, 53, 51, 55, 46, 51, 54 ]).toString(),
|
| 19 |
+
cp: () => Buffer.from([ 55, 55, 49, 44, 52, 56, 54, 53, 45, 52, 56, 54, 54, 45, 52, 56, 54, 55, 45, 52, 57, 49, 57, 53, 45, 52, 57, 49, 57, 57, 45, 52, 57, 49, 57, 54, 45, 52, 57, 50, 48, 48, 45, 53, 50, 51, 57, 51, 45, 53, 50, 51, 57, 50, 45, 52, 57, 49, 55, 49, 45, 52, 57, 49, 55, 50, 45, 49, 53, 54, 45, 49, 53, 55, 45, 52, 55, 45, 53, 51, 44, 48, 45, 50, 51, 45, 54, 53, 50, 56, 49, 45, 49, 48, 45, 49, 49, 45, 51, 53, 45, 49, 54, 45, 53, 45, 49, 51, 45, 49, 56, 45, 53, 49, 45, 52, 53, 45, 52, 51, 45, 50, 55, 45, 49, 55, 53, 49, 51, 45, 50, 49, 44, 50, 57, 45, 50, 51, 45, 50, 52, 44, 48 ]).toString(),
|
| 20 |
+
extra: () => JSON.parse(Buffer.from([ 123, 34, 115, 101, 99, 45, 99, 104, 45, 117, 97, 34, 58, 34, 92, 34, 67, 104, 114, 111, 109, 105, 117, 109, 92, 34, 59, 118, 61, 92, 34, 49, 49, 54, 92, 34, 44, 32, 92, 34, 78, 111, 116, 59, 65, 61, 66, 114, 97, 110, 100, 92, 34, 59, 118, 61, 92, 34, 50, 52, 92, 34, 44, 32, 92, 34, 77, 105, 99, 114, 111, 115, 111, 102, 116, 32, 69, 100, 103, 101, 92, 34, 59, 118, 61, 92, 34, 49, 49, 54, 92, 34, 34, 44, 34, 115, 101, 99, 45, 99, 104, 45, 117, 97, 45, 109, 111, 98, 105, 108, 101, 34, 58, 34, 63, 48, 34, 44, 34, 115, 101, 99, 45, 99, 104, 45, 117, 97, 45, 112, 108, 97, 116, 102, 111, 114, 109, 34, 58, 34, 92, 34, 87, 105, 110, 100, 111, 119, 115, 92, 34, 34, 44, 34, 115, 101, 99, 45, 102, 101, 116, 99, 104, 45, 100, 101, 115, 116, 34, 58, 34, 101, 109, 112, 116, 121, 34, 44, 34, 115, 101, 99, 45, 102, 101, 116, 99, 104, 45, 109, 111, 100, 101, 34, 58, 34, 110, 97, 118, 105, 103, 97, 116, 101, 34, 44, 34, 115, 101, 99, 45, 102, 101, 116, 99, 104, 45, 115, 105, 116, 101, 34, 58, 34, 110, 111, 110, 101, 34, 44, 34, 115, 101, 99, 45, 102, 101, 116, 99, 104, 45, 117, 115, 101, 114, 34, 58, 34, 63, 49, 34, 44, 34, 117, 112, 103, 114, 97, 100, 101, 45, 105, 110, 115, 101, 99, 117, 114, 101, 45, 114, 101, 113, 117, 101, 115, 116, 115, 34, 58, 49, 125 ]).toString()),
|
| 21 |
+
hdr: refPath => ({
|
| 22 |
+
...AI.extra(),
|
| 23 |
+
'Content-Type': 'application/json',
|
| 24 |
+
'User-Agent': AI.agent(),
|
| 25 |
+
Referer: `${AI.end()}/${refPath ? 'chat/' + refPath : ''}`,
|
| 26 |
+
Origin: '' + AI.end()
|
| 27 |
+
})
|
| 28 |
+
}, indexOfH = (text, last = false) => {
|
| 29 |
+
let location = -1;
|
| 30 |
+
const matchesH = text.match(/(?:(?:\\n)|\r|\n){2}((?:Human|H)[:︓:﹕] ?)/gm); //const matchesH = text.match(/(?:(?:\\n)|\n){2}((?:Human|H): ?)/gm);
|
| 31 |
+
matchesH?.length > 0 && (location = last ? text.lastIndexOf(matchesH[matchesH.length - 1]) : text.indexOf(matchesH[0]));
|
| 32 |
+
return location;
|
| 33 |
+
}, indexOfA = (text, last = false) => {
|
| 34 |
+
let location = -1;
|
| 35 |
+
const matchesA = text.match(/(?:(?:\\n)|\r|\n){2}((?:Assistant|A)[:︓:﹕] ?)/gm); //const matchesA = text.match(/(?:(?:\\n)|\n){2}((?:Assistant|A): ?)/gm);
|
| 36 |
+
matchesA?.length > 0 && (location = last ? text.lastIndexOf(matchesA[matchesA.length - 1]) : text.indexOf(matchesA[0]));
|
| 37 |
+
return location;
|
| 38 |
+
};
|
| 39 |
+
|
| 40 |
+
module.exports = {
|
| 41 |
+
Main,
|
| 42 |
+
AI,
|
| 43 |
+
Replacements,
|
| 44 |
+
DangerChars,
|
| 45 |
+
encodeDataJSON: completion => Encoder.encode(`data: ${JSON.stringify(completion)}\n\n`),
|
| 46 |
+
genericFixes: text => text.replace(/(\r\n|\r|\\n)/gm, '\n'),
|
| 47 |
+
checkResErr: async (res, throwIt = true) => {
|
| 48 |
+
let err, json, errAPI;
|
| 49 |
+
if ('string' == typeof res) {
|
| 50 |
+
json = JSON.parse(res);
|
| 51 |
+
errAPI = json.error;
|
| 52 |
+
err = Error(errAPI.message);
|
| 53 |
+
} else if (res.status < 200 || res.status >= 300) {
|
| 54 |
+
err = Error('Unexpected response code: ' + (res.status || json.status));
|
| 55 |
+
const text = await res.text();
|
| 56 |
+
try { //
|
| 57 |
+
json = JSON.parse(text);
|
| 58 |
+
errAPI = json.error;
|
| 59 |
+
} catch { //
|
| 60 |
+
console.log(text); //
|
| 61 |
+
throw err; //
|
| 62 |
+
} //
|
| 63 |
+
}
|
| 64 |
+
if (errAPI) {
|
| 65 |
+
err.status = res.status || json.status;
|
| 66 |
+
err.planned = true;
|
| 67 |
+
errAPI.message && (err.message = errAPI.message);
|
| 68 |
+
errAPI.type && (err.type = errAPI.type);
|
| 69 |
+
if (429 === res.status || 429 === json.status) { //if ((429 === res.status || 429 === json.status) && errAPI.resets_at) {
|
| 70 |
+
try { //
|
| 71 |
+
const hours = ((new Date(1e3 * JSON.parse(errAPI.message).resetsAt).getTime() - Date.now()) / 1e3 / 60 / 60).toFixed(1); //const hours = ((new Date(1e3 * errAPI.resets_at).getTime() - Date.now()) / 1e3 / 60 / 60).toFixed(1);
|
| 72 |
+
err.message += `, expires in ${hours} hours`;
|
| 73 |
+
err.exceeded_limit = true; //
|
| 74 |
+
} catch {} //
|
| 75 |
+
}
|
| 76 |
+
if (throwIt) {
|
| 77 |
+
throw err;
|
| 78 |
+
}
|
| 79 |
+
}
|
| 80 |
+
return err;
|
| 81 |
+
},
|
| 82 |
+
bytesToSize: (bytes = 0, decimals = 2) => {
|
| 83 |
+
if (0 === bytes) {
|
| 84 |
+
return '0 B';
|
| 85 |
+
}
|
| 86 |
+
const dm = decimals < 0 ? 0 : decimals, i = Math.round(Math.log(bytes) / Math.log(1024));
|
| 87 |
+
return `${(bytes / Math.pow(1024, i)).toFixed(dm)} ${[ 'B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB' ][i]}`;
|
| 88 |
+
},
|
| 89 |
+
indexOfAny: (text, last = false) => {
|
| 90 |
+
let location = -1;
|
| 91 |
+
const fakes = [ indexOfH(text, last), indexOfA(text, last) ].filter((idx => idx > -1)).sort();
|
| 92 |
+
location = last ? fakes.reverse()[0] : fakes[0];
|
| 93 |
+
return isNaN(location) ? -1 : location;
|
| 94 |
+
},
|
| 95 |
+
cleanJSON: json => json.indexOf('data:') > -1 ? json.split('data: ')?.[1] : json,
|
| 96 |
+
fileName: () => {
|
| 97 |
+
const len = randomInt(5, 15);
|
| 98 |
+
let name = randomBytes(len).toString('hex');
|
| 99 |
+
for (let i = 0; i < name.length; i++) {
|
| 100 |
+
const char = name.charAt(i);
|
| 101 |
+
isNaN(char) && randomInt(1, 5) % 2 == 0 && ' ' !== name.charAt(i - 1) && (name = name.slice(0, i) + ' ' + name.slice(i));
|
| 102 |
+
}
|
| 103 |
+
return name + '.txt';
|
| 104 |
+
},
|
| 105 |
+
indexOfA,
|
| 106 |
+
indexOfH,
|
| 107 |
+
setTitle: title => {
|
| 108 |
+
title = `${Main} - ${title}`;
|
| 109 |
+
process.title !== title && (process.title = title);
|
| 110 |
+
}
|
| 111 |
+
};
|