Bothen commited on
Commit
0679865
·
verified ·
1 Parent(s): 727176c

Upload 4 files

Browse files
Files changed (4) hide show
  1. clewd.js +954 -0
  2. lib/clewd-stream.js +195 -0
  3. lib/clewd-superfetch.js +4 -0
  4. 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]: ${percentage.toFixed(2)}%\n[length]: ${Config.CookieArray.length}\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(`Regex error: ` + 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(`${Main}\nhttp://${Config.Ip}:${Config.Port}/v1\n\n${Object.keys(Config.Settings).map((setting => UnknownSettings?.includes(setting) ? `??? ${setting}: ${Config.Settings[setting]}` : `${setting}: ${ChangedSettings?.includes(setting) ? '' : ''}${Config.Settings[setting]}`)).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(`No cookie available, enter apiKey-only mode.\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(`Null!`);
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: ${currentIndex + 1 || Config.CookieArray.length}) 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(`${flag}!`);
312
+ return CookieCleaner(flag, percentage);
313
+ } else uuidOrgArray.push(bootAccInfo.uuid);
314
+ if (Config.Cookiecounter < 0) {
315
+ console.log(`[progress]: ${percentage.toFixed(2)}%\n[length]: ${Config.CookieArray.length}\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 ? '' : ''}Your account has warnings %o`, formattedFlags); //console.warn('Your account has warnings %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 ? 'Banned' : 'Restricted'}!`); //
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(`Invalid!`);
390
+ return CookieCleaner('Invalid', percentage);
391
+ }
392
+ console.error('Clewd:\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('config file created!\nedit config.js to set your settings and restart the program');
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('having AllSamples and NoSamples 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} [${type}]${!retryRegen && systems.length > 0 ? ' ' + systems.join(' / ') : ''}`);
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(`${err.status || 'Aborted'}!\n`) : console.error('Clewd:\n%o', err); //err.planned || console.error('Clewd:\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('likely your account is hard-censored');
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 ? '' : ''}${fetchAPI.status}!\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(`Exceeded limit!\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: ${config}`);
889
+ }));
890
+ UnknownSettings.forEach((setting => {
891
+ console.warn(`unknown setting in config.js: Settings.${setting}`);
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: ${config}`);
896
+ userConfig[config] = Config[config];
897
+ }));
898
+ missingSettings.forEach((setting => {
899
+ console.warn(`adding missing setting in config.js: Settings.${setting}`);
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 [err] unavailable for ${process.platform}-${process.arch}, use 3.8.5 for the time being\n`);return false}e&&console.log(`superfetch [found] ${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 [err]",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
+ };