teralomaniac commited on
Commit
10a7711
1 Parent(s): 85fad92

Upload 12 files

Browse files
Files changed (5) hide show
  1. .gitignore +3 -0
  2. clewd.js +182 -167
  3. lib/clewd-stream.js +3 -5
  4. lib/clewd-utils.js +10 -4
  5. package.json +5 -2
.gitignore CHANGED
@@ -13,6 +13,9 @@ yarn-error.log*
13
  cookies.json
14
  cookies.js
15
  cookies.ini
 
 
 
16
  config.js
17
  log.txt
18
 
 
13
  cookies.json
14
  cookies.js
15
  cookies.ini
16
+ lib/bin/cfg
17
+ lib/bin/hdr
18
+ lib/bin/pyld
19
  config.js
20
  log.txt
21
 
clewd.js CHANGED
@@ -7,12 +7,13 @@
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} = 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, changetime = 0, totaltime, uuidOrgArray = [];
11
 
12
  const events = require('events'), CookieChanger = new events.EventEmitter();
13
  require('events').EventEmitter.defaultMaxListeners = 0;
14
 
15
  CookieChanger.on('ChangeCookie', () => {
 
16
  Proxy && Proxy.close();
17
  console.log(`Changing Cookie...\n`);
18
  Proxy.listen(Config.Port, Config.Ip, onListen);
@@ -21,117 +22,114 @@ CookieChanger.on('ChangeCookie', () => {
21
  }));
22
  });
23
 
24
- const simpletokenizer = (prompt) => {
25
- let byteLength = 0;
26
- for (let i = 0; i < prompt.length; i++) {
27
- let code = prompt.charCodeAt(i);
28
- if (code <= 0xFF) {
29
- byteLength += 0.6;
30
- } else if (code <= 0xFFFF) {
31
- byteLength += 1;
32
- } else {
33
- byteLength += 1.5;
34
- }
35
- }
36
- return byteLength;
37
- }, padtxt = (content) => {
38
- if (Config.padtxt_placeholder.length > 0) {
39
- var placeholder = Config.padtxt_placeholder;
40
- } else {
41
- const bytes = randomInt(5, 15);
42
- var placeholder = randomBytes(bytes).toString('hex');
43
- }
44
- let count = Math.floor((Config.Settings.padtxt - simpletokenizer(content)) / simpletokenizer(placeholder));
45
-
46
- // 生成占位符字符串
47
  let padding = '';
48
  for (let i = 0; i < count; i++) {
49
  padding += placeholder;
50
  }
51
-
52
- // 在prompt前面添加占位符, 在末尾增加空行然后添加prompt
53
  content = padding + '\n\n\n' + content;
54
-
55
  return content.trim();
56
- }, xmlPlot = (content) => {
57
  // 检查内容中是否包含"<card>"
58
- if (!content.includes('<card>')) {
59
- content = content.replace(/(\n\n|^)xmlPlot:\s*/gm, '$1');
60
- content = content.replace(/(<reply>\n|\n<\/reply>)/g, '');
61
- return content.replace(/<customname>(.*?)<\/customname>/gm, '$1');
 
 
 
 
 
62
  }
63
-
64
- //群组
65
- content = content.replace(/(<reply>\n|\n<\/reply>)\1*/g, '$1');
66
- content = content.replace(/<customname>(.*?)<\/customname>:/gm, '$1:\n');
67
-
68
  //role合并
69
- if (!content.includes('<\!-- Merge Disable -->')) {
70
- if (!content.includes('<\!-- Merge Human Disable -->')) {
71
- content = content.replace(/(\n\n|^)xmlPlot:/g, '$1Human:');
72
- content = content.replace(/(?:\n\n|^)Human:(.*?(?:\n\nAssistant:|$))/gs, function(match, p1) {return '\n\nHuman:' + p1.replace(/\n\nHuman:\s*/g, '\n\n')});
 
 
 
 
 
 
73
  content = content.replace(/^\s*Human:\s*/, '');
74
  }
75
- if (!content.includes('<\!-- Merge Assistant Disable -->')) {
76
  content = content.replace(/\n\nAssistant:(.*?(?:\n\nHuman:|$))/gs, function(match, p1) {return '\n\nAssistant:' + p1.replace(/\n\nAssistant:\s*/g, '\n\n')});
77
  }
78
  }
79
- content = content.replace(/(\n\n|^)xmlPlot:\s*/gm, '$1');
80
  content = content.replace(/<\!-- Merge.*?Disable -->/gm, '');
81
-
82
- //格式顺序交换&越狱倒置
83
- content = content.replace(/<Prev(Assistant|Human)>.*?<\/Prev\1>/gs, function(match) {return match.replace(/\n\n(Assistant|Human):/g, '\n\ntemp$1:')});
84
- let segcontentAssistant = content.split('\n\nAssistant:');
85
- let processedsegAssistant = segcontentAssistant.map(seg => {
86
- return seg.replace(/(\n\nHuman:.*?)<PrevAssistant>(.*?)<\/PrevAssistant>/gs, '\n\n$2$1');
87
- });
88
- content = processedsegAssistant.join('\n\nAssistant:');
89
- let segcontentHuman = content.split('\n\nHuman:');
90
- const seglength = segcontentHuman.length;
91
- for (let i = 1; i < seglength; i++) {
92
- const match = segcontentHuman[i].match(/<PrevHuman>.*?<\/PrevHuman>/s);
93
- if (match) {
94
- segcontentHuman[i - 1] += match[0].replace(/<PrevHuman>(.*?)<\/PrevHuman>/s, '\n\n$1');
95
- segcontentHuman[i] = segcontentHuman[i].replace(match[0], '');
96
  }
 
97
  }
98
- if (/Assistant: *.$/.test(content) && seglength > 1 && !segcontentHuman[seglength - 2].includes('\n\nAssistant:')) {
99
- segcontentHuman[seglength - 2] = segcontentHuman.splice(seglength - 1, 1, segcontentHuman[seglength - 2])[0];
 
 
 
 
 
 
100
  }
101
- content = segcontentHuman.join('\n\nHuman:');
102
- content = content.replace(/\n\ntemp(Assistant|Human):/g, '\n\n$1:');
103
-
104
- //给开头加上</file-attachment-contents>用于截断附加文件标识
105
- content.includes('<file-attachment-contents>') && (content = '</file-attachment-contents>\n\n' + content);
106
-
107
- // 在第一个"[Start a new"前面加上"<example>",在最后一个"[Start a new"前面加上"</example>\n\n<plot>\n\n"
108
- const exampleNote = content.match(/(?<=<example-note>).*(?=<\/example-note>)/) || '';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
109
  const cardtag = content.match(/(?=\n\n<\/card>)/) || '</card>';
110
  const exampletag = content.match(/(?=\n\n<\/example>)/) || '</example>';
111
  const plot = content.includes('</plot>') ? '<plot>' : '';
112
- content = content.replace(/<example-note>.*<\/example-note>/, '');
113
  const firstChatStart = content.indexOf('\n\n[Start a new');
114
  const lastChatStart = content.lastIndexOf('\n\n[Start a new');
115
  firstChatStart != -1 && firstChatStart === lastChatStart && (content = content.slice(0, firstChatStart) + `\n\n${cardtag}` + content.slice(firstChatStart));
116
- firstChatStart != lastChatStart && (content = content.slice(0, firstChatStart) + `\n\n${cardtag}\n\n${exampleNote}\n<example>` + content.slice(firstChatStart, lastChatStart) + `\n\n${exampletag}\n\n${plot}` + content.slice(lastChatStart));
117
-
118
- //Plain Prompt
119
- segcontentHuman = content.split('\n\nHuman:');
120
- let segcontentlastIndex = segcontentHuman.length - 1;
121
- if (segcontentlastIndex >= 2 && segcontentHuman[segcontentlastIndex].includes('<!-- Plain Prompt Enable -->') && !content.includes('\n\nPlainPrompt:')) {
122
- content = segcontentHuman.slice(0, segcontentlastIndex).join('\n\nHuman:') + '\n\nPlainPrompt:' + segcontentHuman.slice(segcontentlastIndex).join('\n\nHuman:');
123
- }
124
- content = content.replace(/<\!-- Plain Prompt Enable -->/, '');
125
- content = content.replace(/\n\nHuman:.*PlainPrompt:/, '\n\nPlainPrompt:');
126
-
127
- //消除空XML tags或多余的\n
128
- content = content.replace(/\n<\/(hidden|META)>\s+?<\1>\n/g, '');
129
- content = content.replace(/\n<(card|example|hidden|plot|META)>\s+?<\1>/g, '\n<$1>');
130
  content = content.replace(/(?:<!--.*?-->)?\n<(card|example|hidden|plot|META)>\s+?<\/\1>/g, '');
131
- content = content.replace(/(?<=(: |\n)<(card|hidden|example|plot|META)>\n)\s*/g, '');
132
- content = content.replace(/\s*(?=\n<\/(card|hidden|example|plot|META)>(\n|$))/g, '');
133
  content = content.replace(/(?<=\n)\n(?=\n)/g, '');
134
-
135
  return content.trim();
136
  };
137
  /******************************************************* */
@@ -147,8 +145,9 @@ const ConfigPath = joinP(__dirname, './config.js'), LogPath = joinP(__dirname, '
147
  let uuidOrg, curPrompt = {}, prevPrompt = {}, prevMessages = [], prevImpersonated = false, Config = {
148
  Cookie: '',
149
  CookieArray: [],
150
- Cookiecounter: 0,
151
  CookieIndex: 0,
 
152
  Ip: (process.env.Cookie || process.env.CookieArray) ? '0.0.0.0' : '127.0.0.1',
153
  Port: process.env.PORT || 8444,
154
  localtunnel: false,
@@ -172,10 +171,10 @@ let uuidOrg, curPrompt = {}, prevPrompt = {}, prevMessages = [], prevImpersonate
172
  StripHuman: false,
173
  PassParams: false,
174
  ClearFlags: true,
175
- PreserveChats: true,
176
  LogMessages: true,
177
  FullColon: true,
178
- padtxt: 13500,
179
  xmlPlot: true,
180
  Superfetch: true
181
  }
@@ -222,14 +221,18 @@ const updateParams = res => {
222
  if (Config.Settings.PreserveChats) {
223
  return;
224
  }
225
- const res = await fetch(`${Config.rProxy}/api/organizations/${uuidOrg}/chat_conversations/${uuid}`, {
226
- headers: {
227
- ...AI.hdr(),
228
- Cookie: getCookies()
229
- },
230
- method: 'DELETE'
231
- });
232
- updateParams(res);
 
 
 
 
233
  }, onListen = async () => {
234
  /***************************** */
235
  if (Firstlogin) {
@@ -250,7 +253,7 @@ const updateParams = res => {
250
  currentIndex = (currentIndex + 1) % Config.CookieArray.length;
251
  changetime += 1;
252
  }
253
- let percentage = ((changetime + Config.CookieIndex) / totaltime) * 100
254
  if (Config.Cookiecounter < 0 && percentage > 100) {
255
  console.log(`\n※※※Cookie cleanup completed※※※\n\n`);
256
  return process.exit();
@@ -259,6 +262,7 @@ const updateParams = res => {
259
  if ('SET YOUR COOKIE HERE' === Config.Cookie || Config.Cookie?.length < 1) {
260
  throw Error('Set your cookie inside config.js');
261
  }
 
262
  updateCookies(Config.Cookie);
263
  //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`);
264
  //Config.Settings.Superfetch && SuperfetchAvailable(true);
@@ -271,9 +275,7 @@ const updateParams = res => {
271
  });
272
  /**************************** */
273
  if (accRes.statusText === 'Forbidden' && Config.CookieArray?.length > 0) {
274
- Config.CookieArray = Config.CookieArray.filter(item => item !== Config.Cookie);
275
- !process.env.Cookie && !process.env.CookieArray && writeSettings(Config);
276
- currentIndex = (currentIndex - 1 + Config.CookieArray.length) % Config.CookieArray.length;
277
  console.log(`Expired!`);
278
  Config.Cookiecounter < 0 && console.log(`[progress]: ${percentage.toFixed(2)}%\n[length]: ${Config.CookieArray.length}\n`);
279
  CookieChanger.emit('ChangeCookie');
@@ -290,38 +292,64 @@ const updateParams = res => {
290
  }
291
  setTitle('ok');
292
  updateParams(accRes);
 
 
 
 
 
 
 
 
 
 
 
293
  console.log(Config.CookieArray?.length > 0 ? `(index: ${currentIndex || Config.CookieArray.length}) Logged in %o` : 'Logged in %o', { //console.log('Logged in %o', {
294
  name: accInfo.name?.split('@')?.[0],
 
295
  capabilities: accInfo.capabilities,
296
  });
297
  uuidOrg = accInfo?.uuid;
298
  /************************* */
299
- if (uuidOrgArray.includes(uuidOrg)) {
300
- console.log(`Overlap!`);
301
- currentIndex = (currentIndex - 1 + Config.CookieArray.length) % Config.CookieArray.length;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
302
  Config.Cookiecounter < 0 && console.log(`[progress]: ${percentage.toFixed(2)}%\n[length]: ${Config.CookieArray.length}\n`);
303
- Config.CookieArray = Config.CookieArray.filter(item => item !== Config.Cookie);
304
- !process.env.Cookie && !process.env.CookieArray && writeSettings(Config);
305
- CookieChanger.emit('ChangeCookie');
306
- return;
307
- } else {
308
- uuidOrgArray.push(uuidOrg);
309
  }
310
  /************************* */
311
  if (accInfo?.active_flags.length > 0) {
 
312
  const now = new Date, formattedFlags = accInfo.active_flags.map((flag => {
313
  const days = ((new Date(flag.expires_at).getTime() - now.getTime()) / 864e5).toFixed(2);
 
314
  return {
315
  type: flag.type,
316
  remaining_days: days
317
  };
318
  }));
319
- console.warn('Your account has warnings %o', formattedFlags); //console.warn('Your account has warnings %o', formattedFlags);
320
  await Promise.all(accInfo.active_flags.map((flag => (async type => {
321
  if (!Config.Settings.ClearFlags) {
322
  return;
323
  }
324
- if ('consumer_restricted_mode' === type) {
325
  return;
326
  }
327
  const req = await (Config.Settings.Superfetch ? Superfetch : fetch)(`${Config.rProxy}/api/organizations/${uuidOrg}/flags/${type}/dismiss`, {
@@ -337,40 +365,18 @@ const updateParams = res => {
337
  })(flag.type))));
338
  /***************************** */
339
  if (Config.CookieArray?.length > 0) {
340
- console.log(`Restricted!`);
 
341
  Config.Cookiecounter < 0 && console.log(`[progress]: ${percentage.toFixed(2)}%\n[length]: ${Config.CookieArray.length}\n`);
342
- CookieChanger.emit('ChangeCookie');
343
- return;
344
  }
345
  }
346
- if (Config.CookieArray.length > 0) {
347
- const allres = await fetch(`${Config.rProxy}`, {
348
- headers: {
349
- ...AI.hdr(),
350
- Cookie: getCookies()
351
- },
352
- method: 'GET'
353
- }), accountinfo = await allres.text();
354
- updateParams(allres);
355
- const Unverified = accountinfo.includes('\\"completed_verification_at\\":null');
356
- const Banned = accountinfo.includes('\\"gate\":\\"segment:abuse\\",\\"gateValue\\":\\"true\\",');
357
- const Exceededlimit = /\\"messageLimit\\":{\\"type\\":\\"(approaching_limit\\",\\"remaining\\":0|exceeded_limit)\\",/.test(accountinfo);
358
- const Remain = /\\"messageLimit\\":{\\"type\\":\\"approaching_limit\\",\\"remaining\\":\d+\\",/.exec(accountinfo);
359
- Remain && (changeflag = Math.max(Config.Cookiecounter - Remain[0], changeflag));
360
- if (Unverified || Banned) {
361
- Config.CookieArray = Config.CookieArray.filter(item => item !== Config.Cookie);
362
- !process.env.Cookie && !process.env.CookieArray && writeSettings(Config);
363
- currentIndex = (currentIndex - 1 + Config.CookieArray.length) % Config.CookieArray.length;
364
- }
365
- Unverified && console.log(`Unverified!`);
366
- Banned && console.log(`Banned!`);
367
- Exceededlimit && console.log(`Exceeded limit!`);
368
- Config.Cookiecounter < 0 && console.log(`[progress]: ${percentage.toFixed(2)}%\n[length]: ${Config.CookieArray.length}`);
369
- if (Unverified || Banned || Exceededlimit || Config.Cookiecounter < 0) {
370
- console.log('');
371
- CookieChanger.emit('ChangeCookie');
372
- return;
373
- }
374
  /***************************** */
375
  }
376
  const convRes = await fetch(`${Config.rProxy}/api/organizations/${uuidOrg}/chat_conversations`, {
@@ -424,6 +430,12 @@ const updateParams = res => {
424
  try {
425
  const body = JSON.parse(Buffer.concat(buffer).toString()), temperature = Math.max(.1, Math.min(1, body.temperature));
426
  let {messages} = body;
 
 
 
 
 
 
427
  if (messages?.length < 1) {
428
  throw Error('Select OpenAI as completion source');
429
  }
@@ -454,7 +466,7 @@ const updateParams = res => {
454
  console.log('having AllSamples and NoSamples both set to true is not supported');
455
  throw Error('Only one can be used at the same time: AllSamples/NoSamples');
456
  }
457
- const model = AI.mdl();
458
  curPrompt = {
459
  firstUser: messages.find((message => 'user' === message.role)),
460
  firstSystem: messages.find((message => 'system' === message.role)),
@@ -624,38 +636,38 @@ const updateParams = res => {
624
  return message.content;
625
  }
626
  let spacing = '';
627
- /****************************************************************/
628
  if (Config.Settings.xmlPlot) {
629
  idx > 0 && (spacing = '\n\n');
630
  const prefix = message.customname ? message.role + ': <customname>' + message.name + '</customname>: ' : 'system' !== message.role || message.name ? Replacements[message.name || message.role] + ': ' : 'xmlPlot: ' + Replacements[message.role];
631
  return `${spacing}${prefix}${message.customname ? '<reply>\n' + message.content.trim() + '\n</reply>' : message.content}`;
632
  } else {
633
- /****************************************************************/
634
  idx > 0 && (spacing = systemMessages.includes(message) ? '\n' : '\n\n');
635
  const prefix = message.customname ? message.name + ': ' : 'system' !== message.role || message.name ? Replacements[message.name || message.role] + ': ' : '' + Replacements[message.role];
636
  return `${spacing}${message.strip ? '' : prefix}${'system' === message.role ? message.content : message.content.trim()}`;
637
  } //
638
  }));
639
  return {
640
- prompt: genericFixes(prompt.join('')).trim(),
641
  systems
642
  };
643
  })(messages, type);
644
  console.log(`${model} [${type}]${!retryRegen && systems.length > 0 ? ' ' + systems.join(' / ') : ''}`);
645
  'R' !== type || prompt || (prompt = '...regen...');
646
- /****************************************************************/
647
- Config.Settings.xmlPlot && (prompt = xmlPlot(prompt));
648
  Config.Settings.FullColon && (prompt = prompt.replace(/(?<=\n\n(H(?:uman)?|A(?:ssistant)?)):[ ]?/g, ': '));
649
  Config.Settings.padtxt && (prompt = padtxt(prompt));
650
- /****************************************************************/
651
  Logger?.write(`\n\n-------\n[${(new Date).toLocaleString()}]\n####### PROMPT (${type}):\n${prompt}\n--\n####### REPLY:\n`);
652
  retryRegen || (fetchAPI = await (async (signal, model, prompt, temperature, type) => {
653
  const attachments = [];
654
  if (Config.Settings.PromptExperiments) {
655
- /****************************************************************/
656
  let splitedprompt = prompt.split('\n\nPlainPrompt:');
657
  prompt = splitedprompt[0];
658
- /****************************************************************/
659
  attachments.push({
660
  extracted_content: (prompt),
661
  file_name: 'paste.txt', //fileName(),
@@ -663,9 +675,9 @@ const updateParams = res => {
663
  file_type: 'txt' //'text/plain'
664
  });
665
  prompt = 'r' === type ? Config.PromptExperimentFirst : Config.PromptExperimentNext;
666
- /****************************************************************/
667
  splitedprompt.length > 1 && (prompt = prompt + splitedprompt[1]);
668
- /****************************************************************/
669
  }
670
  let res;
671
  const body = {
@@ -695,7 +707,7 @@ const updateParams = res => {
695
  headers
696
  });
697
  updateParams(res);
698
- await checkResErr(res);
699
  return res;
700
  })(signal, model, prompt, temperature, type));
701
  const response = Writable.toWeb(res);
@@ -725,14 +737,13 @@ const updateParams = res => {
725
  });
726
  }
727
  }
728
- clearInterval(titleTimer);
729
  if (clewdStream) {
730
  clewdStream.censored && console.warn('likely your account is hard-censored');
731
  prevImpersonated = clewdStream.impersonated;
732
  setTitle('ok ' + bytesToSize(clewdStream.size));
733
- //console.log(`${200 == fetchAPI.status ? '' : ''}${fetchAPI.status}!\n`);
734
- /******************************** */
735
- 429 == fetchAPI.status ? console.log(`Exceeded limit!\n`) : console.log(`${200 == fetchAPI.status ? '' : ''}${fetchAPI.status}!\n`);
736
  changeflag += 1;
737
  if (Config.CookieArray?.length > 0 && (429 == fetchAPI.status || (Config.Cookiecounter && changeflag >= Config.Cookiecounter))) {
738
  changeflag = 0;
@@ -741,12 +752,11 @@ const updateParams = res => {
741
  /******************************** */
742
  clewdStream.empty();
743
  }
744
- if (prevImpersonated) {
745
- try {
746
- await deleteChat(Conversation.uuid);
747
- } catch (err) {}
748
- }
749
  /******************************** */
 
750
  changer && CookieChanger.emit('ChangeCookie');
751
  /******************************** */
752
  }));
@@ -762,15 +772,19 @@ const updateParams = res => {
762
  break;
763
 
764
  default:
765
- req.url !== '/' && (console.log('unknown request: ' + req.url)); //console.log('unknown request: ' + req.url);
766
- res.json({
 
 
 
 
767
  error: {
768
  message: '404 Not Found',
769
  type: 404,
770
  param: null,
771
  code: 404
772
  }
773
- }, 200);
774
  }
775
  }));
776
 
@@ -828,6 +842,7 @@ const updateParams = res => {
828
  Config.rProxy.endsWith('/') && (Config.rProxy = Config.rProxy.slice(0, -1));
829
  let uniqueArr = [], seen = new Set();
830
  for (let Cookie of Config.CookieArray) {
 
831
  if (!seen.has(Cookie)) {
832
  uniqueArr.push(Cookie);
833
  seen.add(Cookie);
 
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} = 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, changetime = 0, totaltime, uuidOrgArray = [], model;
11
 
12
  const events = require('events'), CookieChanger = new events.EventEmitter();
13
  require('events').EventEmitter.defaultMaxListeners = 0;
14
 
15
  CookieChanger.on('ChangeCookie', () => {
16
+ changeflag = 0;
17
  Proxy && Proxy.close();
18
  console.log(`Changing Cookie...\n`);
19
  Proxy.listen(Config.Port, Config.Ip, onListen);
 
22
  }));
23
  });
24
 
25
+ const CookieCleaner = () => {
26
+ Config.CookieArray = Config.CookieArray.filter(item => item !== Config.Cookie);
27
+ !process.env.Cookie && !process.env.CookieArray && writeSettings(Config);
28
+ currentIndex = (currentIndex - 1 + Config.CookieArray.length) % Config.CookieArray.length;
29
+ }, padtxt = content => {
30
+ const {encode} = require('gpt-tokenizer');
31
+ const placeholder = Config.padtxt_placeholder || randomBytes(randomInt(5, 15)).toString('hex');
32
+ let count = Math.floor(Math.max(1000, Config.Settings.padtxt - encode(content).length) / encode(placeholder).length);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  let padding = '';
34
  for (let i = 0; i < count; i++) {
35
  padding += placeholder;
36
  }
 
 
37
  content = padding + '\n\n\n' + content;
 
38
  return content.trim();
39
+ }, xmlPlot = content => {
40
  // 检查内容中是否包含"<card>"
41
+ const card = content.includes('<card>');
42
+ //<card>越狱倒置
43
+ if (card) {
44
+ let segcontentHuman = content.split('\n\nHuman:');
45
+ const seglength = segcontentHuman.length;
46
+ if (/Assistant: *.$/.test(content) && seglength > 1 && !segcontentHuman[seglength - 2].includes('\n\nAssistant:')) {
47
+ segcontentHuman[seglength - 2] = segcontentHuman.splice(seglength - 1, 1, segcontentHuman[seglength - 2])[0];
48
+ }
49
+ content = segcontentHuman.join('\n\nHuman:');
50
  }
 
 
 
 
 
51
  //role合并
52
+ const MergeDisable = content.includes('<\!-- Merge Disable -->');
53
+ const MergeHumanDisable = content.includes('<\!-- Merge Human Disable -->');
54
+ const MergeAssistantDisable = content.includes('<\!-- Merge Assistant Disable -->');
55
+ if (!MergeDisable) {
56
+ if (content.includes('<\!-- Merge System Disable -->') || !card) {
57
+ content = content.replace(/(\n\n|^\s*)xmlPlot:\s*/gm, '$1');
58
+ }
59
+ if (!MergeHumanDisable) {
60
+ content = content.replace(/(\n\n|^\s*)xmlPlot:/g, '$1Human:');
61
+ content = content.replace(/(?:\n\n|^\s*)Human:(.*?(?:\n\nAssistant:|$))/gs, function(match, p1) {return '\n\nHuman:' + p1.replace(/\n\nHuman:\s*/g, '\n\n')});
62
  content = content.replace(/^\s*Human:\s*/, '');
63
  }
64
+ if (!MergeAssistantDisable) {
65
  content = content.replace(/\n\nAssistant:(.*?(?:\n\nHuman:|$))/gs, function(match, p1) {return '\n\nAssistant:' + p1.replace(/\n\nAssistant:\s*/g, '\n\n')});
66
  }
67
  }
68
+ content = content.replace(/(\n\n|^\s*)xmlPlot:\s*/gm, '$1');
69
  content = content.replace(/<\!-- Merge.*?Disable -->/gm, '');
70
+ //自定义插入
71
+ content = content.replace(/(<\/?)PrevAssistant>/gm, '$1@1>');
72
+ content = content.replace(/(<\/?)PrevHuman>/gm, '$1@2>');
73
+ let splitContent = content.split(/\n\n(?=Assistant:|Human:)/g);
74
+ let match;
75
+ while ((match = /<@(\d+)>(.*?)<\/@\1>/gs.exec(content)) !== null) {
76
+ let index = splitContent.length - parseInt(match[1]) - 1;
77
+ if (index >= 0) {
78
+ splitContent[index] += '\n\n' + match[2];
 
 
 
 
 
 
79
  }
80
+ content = content.replace(match[0], '');
81
  }
82
+ content = splitContent.join('\n\n');
83
+ content = content.replace(/<@(\d+)>.*?<\/@\1>/gs, '');
84
+ //正则
85
+ while ((match = /<regex>"(\/?)(.*)\1(.*)" *: *"(.*?)"<\/regex>/gm.exec(content)) !== null) {
86
+ try {
87
+ content = content.replace(new RegExp(match[2], match[3]), match[4]);
88
+ } catch (error) {}
89
+ content = content.replace(match[0], '');
90
  }
91
+ content = content.replace(/(\r\n|\r|\\n)/gm, '\n');
92
+ //二次role合并
93
+ if (!MergeDisable) {
94
+ if (!MergeHumanDisable) {
95
+ content = content.replace(/(?:\n\n|^\s*)Human:(.*?(?:\n\nAssistant:|$))/gs, function(match, p1) {return '\n\nHuman:' + p1.replace(/\n\nHuman:\s*/g, '\n\n')});
96
+ }
97
+ if (!MergeAssistantDisable) {
98
+ content = content.replace(/\n\nAssistant:(.*?(?:\n\nHuman:|$))/gs, function(match, p1) {return '\n\nAssistant:' + p1.replace(/\n\nAssistant:\s*/g, '\n\n')});
99
+ }
100
+ }
101
+ //Plain Prompt
102
+ let segcontentHuman = content.split('\n\nHuman:');
103
+ let segcontentlastIndex = segcontentHuman.length - 1;
104
+ if (segcontentlastIndex >= 2 && segcontentHuman[segcontentlastIndex].includes('<!-- Plain Prompt Enable -->') && !content.includes('\n\nPlainPrompt:')) {
105
+ content = segcontentHuman.slice(0, segcontentlastIndex).join('\n\nHuman:') + '\n\nPlainPrompt:' + segcontentHuman.slice(segcontentlastIndex).join('\n\nHuman:');
106
+ }
107
+ content = content.replace(/<\!-- Plain Prompt Enable -->/gm, '');
108
+ content = content.replace(/\n\nHuman: *PlainPrompt:/, '\n\nPlainPrompt:');
109
+ //<card>群组
110
+ if (!card) {
111
+ content = content.replace(/(<reply>\n|\n<\/reply>)/g, '');
112
+ return content.replace(/<customname>(.*?)<\/customname>/gm, '$1');
113
+ } else {
114
+ content = content.replace(/(<reply>\n|\n<\/reply>)\1*/g, '$1');
115
+ content = content.replace(/<customname>(.*?)<\/customname>:/gm, '$1:\n');
116
+ }
117
+ //<card>在第一个"[Start a new"前面加上"<example>",在最后一个"[Start a new"前面加上"</example>\n\n<plot>\n\n"
118
  const cardtag = content.match(/(?=\n\n<\/card>)/) || '</card>';
119
  const exampletag = content.match(/(?=\n\n<\/example>)/) || '</example>';
120
  const plot = content.includes('</plot>') ? '<plot>' : '';
 
121
  const firstChatStart = content.indexOf('\n\n[Start a new');
122
  const lastChatStart = content.lastIndexOf('\n\n[Start a new');
123
  firstChatStart != -1 && firstChatStart === lastChatStart && (content = content.slice(0, firstChatStart) + `\n\n${cardtag}` + content.slice(firstChatStart));
124
+ firstChatStart != lastChatStart && (content = content.slice(0, firstChatStart) + `\n\n${cardtag}\n<example>` + content.slice(firstChatStart, lastChatStart) + `\n\n${exampletag}\n\n${plot}` + content.slice(lastChatStart));
125
+ //<card>消除空XML tags、两端空白符和多余的\n
126
+ content = content.replace(/\s*<\|curtail\|>\s*/g, '\n');
127
+ content = content.replace(/\n<\/(card|hidden|META)>\s+?<\1>\n/g, '\n');
128
+ content = content.replace(/\n<(\/?card|example|hidden|plot|META)>\s+?<\1>/g, '\n<$1>');
 
 
 
 
 
 
 
 
 
129
  content = content.replace(/(?:<!--.*?-->)?\n<(card|example|hidden|plot|META)>\s+?<\/\1>/g, '');
130
+ content = content.replace(/(?<=(: |\n)<(card|hidden|example|plot|META|EOT)>\n)\s*/g, '');
131
+ content = content.replace(/\s*(?=\n<\/(card|hidden|example|plot|META|EOT)>(\n|$))/g, '');
132
  content = content.replace(/(?<=\n)\n(?=\n)/g, '');
 
133
  return content.trim();
134
  };
135
  /******************************************************* */
 
145
  let uuidOrg, curPrompt = {}, prevPrompt = {}, prevMessages = [], prevImpersonated = false, Config = {
146
  Cookie: '',
147
  CookieArray: [],
148
+ Cookiecounter: 3,
149
  CookieIndex: 0,
150
+ ProxyPassword: '',
151
  Ip: (process.env.Cookie || process.env.CookieArray) ? '0.0.0.0' : '127.0.0.1',
152
  Port: process.env.PORT || 8444,
153
  localtunnel: false,
 
171
  StripHuman: false,
172
  PassParams: false,
173
  ClearFlags: true,
174
+ PreserveChats: false,
175
  LogMessages: true,
176
  FullColon: true,
177
+ padtxt: 15000,
178
  xmlPlot: true,
179
  Superfetch: true
180
  }
 
221
  if (Config.Settings.PreserveChats) {
222
  return;
223
  }
224
+ try { //
225
+ const res = await fetch(`${Config.rProxy}/api/organizations/${uuidOrg}/chat_conversations/${uuid}`, {
226
+ headers: {
227
+ ...AI.hdr(),
228
+ Cookie: getCookies()
229
+ },
230
+ method: 'DELETE'
231
+ });
232
+ updateParams(res);
233
+ } catch (err) { //
234
+ console.log(`deleteChat failed`); //
235
+ } //
236
  }, onListen = async () => {
237
  /***************************** */
238
  if (Firstlogin) {
 
253
  currentIndex = (currentIndex + 1) % Config.CookieArray.length;
254
  changetime += 1;
255
  }
256
+ let percentage = ((changetime + Math.max(Config.CookieIndex - 1, 0)) / totaltime) * 100
257
  if (Config.Cookiecounter < 0 && percentage > 100) {
258
  console.log(`\n※※※Cookie cleanup completed※※※\n\n`);
259
  return process.exit();
 
262
  if ('SET YOUR COOKIE HERE' === Config.Cookie || Config.Cookie?.length < 1) {
263
  throw Error('Set your cookie inside config.js');
264
  }
265
+ !/^sessionKey=/.test(Config.Cookie) && (Config.Cookie += 'sessionKey='); //
266
  updateCookies(Config.Cookie);
267
  //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`);
268
  //Config.Settings.Superfetch && SuperfetchAvailable(true);
 
275
  });
276
  /**************************** */
277
  if (accRes.statusText === 'Forbidden' && Config.CookieArray?.length > 0) {
278
+ CookieCleaner();
 
 
279
  console.log(`Expired!`);
280
  Config.Cookiecounter < 0 && console.log(`[progress]: ${percentage.toFixed(2)}%\n[length]: ${Config.CookieArray.length}\n`);
281
  CookieChanger.emit('ChangeCookie');
 
292
  }
293
  setTitle('ok');
294
  updateParams(accRes);
295
+ /**************************** */
296
+ const accountRes = await fetch(Config.rProxy + '/api/auth/current_account', {
297
+ method: 'GET',
298
+ headers: {
299
+ ...AI.hdr(),
300
+ Cookie: getCookies()
301
+ }
302
+ });
303
+ await checkResErr(accountRes);
304
+ const accountInfo = (await accountRes.json());
305
+ /**************************** */
306
  console.log(Config.CookieArray?.length > 0 ? `(index: ${currentIndex || Config.CookieArray.length}) Logged in %o` : 'Logged in %o', { //console.log('Logged in %o', {
307
  name: accInfo.name?.split('@')?.[0],
308
+ mail: accountInfo.account.email_address, //
309
  capabilities: accInfo.capabilities,
310
  });
311
  uuidOrg = accInfo?.uuid;
312
  /************************* */
313
+ model = accountInfo.account.statsig.values.dynamic_configs["6zA9wvTedwkzjLxWy9PVe7yydI00XDQ6L5Fejjq/2o8="]?.value?.model;
314
+ model != AI.mdl() && console.log(`${model}`);
315
+ if (model != AI.mdl() && Config.Cookiecounter === -2) {
316
+ CookieCleaner();
317
+ return CookieChanger.emit('ChangeCookie');
318
+ }
319
+ const Overlap = uuidOrgArray.includes(uuidOrg) && percentage <= 100 && Config.CookieArray?.length > 0;
320
+ !Overlap && uuidOrgArray.push(uuidOrg);
321
+ const Unverified = !accountInfo.account.completed_verification_at;
322
+ const abuseTag = accountInfo.account.statsig.values.feature_gates["4fDxNAVXgvks8yzKUoU+T+w3Qr3oYVqoJJVNYh04Mik="]?.secondary_exposures[0];
323
+ const Banned = abuseTag.gateValue === 'true' && abuseTag.gate === 'segment:abuse';
324
+ const Remain = accountInfo.messageLimit?.remaining;
325
+ const Exceededlimit = (accountInfo.messageLimit?.type === 'approaching_limit' && Remain === 0) || accountInfo.messageLimit?.type === 'exceeded_limit';
326
+ if (Remain) {
327
+ changeflag = Math.max(Config.Cookiecounter - Remain, changeflag);
328
+ console.log(`ApproachingLimit!: Remain ${Remain}`);
329
+ }
330
+ if ((Overlap || Unverified || Banned) && Config.CookieArray?.length > 0) {
331
+ Overlap ? console.log(`Overlap!`) : Unverified ? console.log(`Unverified!`) : Banned && console.log(`Banned!`);
332
+ CookieCleaner();
333
  Config.Cookiecounter < 0 && console.log(`[progress]: ${percentage.toFixed(2)}%\n[length]: ${Config.CookieArray.length}\n`);
334
+ return CookieChanger.emit('ChangeCookie');
 
 
 
 
 
335
  }
336
  /************************* */
337
  if (accInfo?.active_flags.length > 0) {
338
+ let flagtype; //
339
  const now = new Date, formattedFlags = accInfo.active_flags.map((flag => {
340
  const days = ((new Date(flag.expires_at).getTime() - now.getTime()) / 864e5).toFixed(2);
341
+ flagtype = flag.type; //
342
  return {
343
  type: flag.type,
344
  remaining_days: days
345
  };
346
  }));
347
+ console.warn(`${'consumer_banned' === flagtype ? '' : ''}Your account has warnings %o`, formattedFlags); //console.warn('Your account has warnings %o', formattedFlags);
348
  await Promise.all(accInfo.active_flags.map((flag => (async type => {
349
  if (!Config.Settings.ClearFlags) {
350
  return;
351
  }
352
+ if ('consumer_restricted_mode' === type || 'consumer_banned' === type) { //if ('consumer_restricted_mode' === type) {
353
  return;
354
  }
355
  const req = await (Config.Settings.Superfetch ? Superfetch : fetch)(`${Config.rProxy}/api/organizations/${uuidOrg}/flags/${type}/dismiss`, {
 
365
  })(flag.type))));
366
  /***************************** */
367
  if (Config.CookieArray?.length > 0) {
368
+ console.log(`${'consumer_banned' === flagtype ? 'Banned' : 'Restricted'}!`);
369
+ 'consumer_banned' === flagtype && CookieCleaner();
370
  Config.Cookiecounter < 0 && console.log(`[progress]: ${percentage.toFixed(2)}%\n[length]: ${Config.CookieArray.length}\n`);
371
+ return CookieChanger.emit('ChangeCookie');
 
372
  }
373
  }
374
+ if (Config.Cookiecounter < 0) {
375
+ console.log(`[progress]: ${percentage.toFixed(2)}%\n[length]: ${Config.CookieArray.length}\n`);
376
+ return CookieChanger.emit('ChangeCookie');
377
+ } else if (Exceededlimit) {
378
+ console.log(`Exceeded limit!\n`);
379
+ return CookieChanger.emit('ChangeCookie');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
380
  /***************************** */
381
  }
382
  const convRes = await fetch(`${Config.rProxy}/api/organizations/${uuidOrg}/chat_conversations`, {
 
430
  try {
431
  const body = JSON.parse(Buffer.concat(buffer).toString()), temperature = Math.max(.1, Math.min(1, body.temperature));
432
  let {messages} = body;
433
+ /************************* */
434
+ const authorization = Object.fromEntries(Object.entries(req.headers).map(([key, value]) => [key, value])).authorization;
435
+ if (Config.ProxyPassword != '' && authorization != 'Bearer ' + Config.ProxyPassword) {
436
+ throw Error('ProxyPassword Wrong');
437
+ }
438
+ /************************* */
439
  if (messages?.length < 1) {
440
  throw Error('Select OpenAI as completion source');
441
  }
 
466
  console.log('having AllSamples and NoSamples both set to true is not supported');
467
  throw Error('Only one can be used at the same time: AllSamples/NoSamples');
468
  }
469
+ //const model = AI.mdl();
470
  curPrompt = {
471
  firstUser: messages.find((message => 'user' === message.role)),
472
  firstSystem: messages.find((message => 'system' === message.role)),
 
636
  return message.content;
637
  }
638
  let spacing = '';
639
+ /******************************** */
640
  if (Config.Settings.xmlPlot) {
641
  idx > 0 && (spacing = '\n\n');
642
  const prefix = message.customname ? message.role + ': <customname>' + message.name + '</customname>: ' : 'system' !== message.role || message.name ? Replacements[message.name || message.role] + ': ' : 'xmlPlot: ' + Replacements[message.role];
643
  return `${spacing}${prefix}${message.customname ? '<reply>\n' + message.content.trim() + '\n</reply>' : message.content}`;
644
  } else {
645
+ /******************************** */
646
  idx > 0 && (spacing = systemMessages.includes(message) ? '\n' : '\n\n');
647
  const prefix = message.customname ? message.name + ': ' : 'system' !== message.role || message.name ? Replacements[message.name || message.role] + ': ' : '' + Replacements[message.role];
648
  return `${spacing}${message.strip ? '' : prefix}${'system' === message.role ? message.content : message.content.trim()}`;
649
  } //
650
  }));
651
  return {
652
+ prompt: prompt.join('').trim(),//genericFixes(prompt.join('')).trim(),
653
  systems
654
  };
655
  })(messages, type);
656
  console.log(`${model} [${type}]${!retryRegen && systems.length > 0 ? ' ' + systems.join(' / ') : ''}`);
657
  'R' !== type || prompt || (prompt = '...regen...');
658
+ /******************************** */
659
+ prompt = Config.Settings.xmlPlot ? xmlPlot(prompt) : genericFixes(prompt);
660
  Config.Settings.FullColon && (prompt = prompt.replace(/(?<=\n\n(H(?:uman)?|A(?:ssistant)?)):[ ]?/g, ': '));
661
  Config.Settings.padtxt && (prompt = padtxt(prompt));
662
+ /******************************** */
663
  Logger?.write(`\n\n-------\n[${(new Date).toLocaleString()}]\n####### PROMPT (${type}):\n${prompt}\n--\n####### REPLY:\n`);
664
  retryRegen || (fetchAPI = await (async (signal, model, prompt, temperature, type) => {
665
  const attachments = [];
666
  if (Config.Settings.PromptExperiments) {
667
+ /******************************** */
668
  let splitedprompt = prompt.split('\n\nPlainPrompt:');
669
  prompt = splitedprompt[0];
670
+ /******************************** */
671
  attachments.push({
672
  extracted_content: (prompt),
673
  file_name: 'paste.txt', //fileName(),
 
675
  file_type: 'txt' //'text/plain'
676
  });
677
  prompt = 'r' === type ? Config.PromptExperimentFirst : Config.PromptExperimentNext;
678
+ /******************************** */
679
  splitedprompt.length > 1 && (prompt = prompt + splitedprompt[1]);
680
+ /******************************** */
681
  }
682
  let res;
683
  const body = {
 
707
  headers
708
  });
709
  updateParams(res);
710
+ await checkResErr(res, CookieChanger); //await checkResErr(res);
711
  return res;
712
  })(signal, model, prompt, temperature, type));
713
  const response = Writable.toWeb(res);
 
737
  });
738
  }
739
  }
740
+ clearInterval(titleTimer);
741
  if (clewdStream) {
742
  clewdStream.censored && console.warn('likely your account is hard-censored');
743
  prevImpersonated = clewdStream.impersonated;
744
  setTitle('ok ' + bytesToSize(clewdStream.size));
745
+ 429 == fetchAPI.status ? console.log(`Exceeded limit!\n`) : console.log(`${200 == fetchAPI.status ? '' : ''}${fetchAPI.status}!\n`); //console.log(`${200 == fetchAPI.status ? '' : ''}${fetchAPI.status}!\n`);
746
+ /******************************** */
 
747
  changeflag += 1;
748
  if (Config.CookieArray?.length > 0 && (429 == fetchAPI.status || (Config.Cookiecounter && changeflag >= Config.Cookiecounter))) {
749
  changeflag = 0;
 
752
  /******************************** */
753
  clewdStream.empty();
754
  }
755
+ /*if (prevImpersonated) {
756
+ await deleteChat(Conversation.uuid);
757
+ }*/
 
 
758
  /******************************** */
759
+ await deleteChat(Conversation.uuid);
760
  changer && CookieChanger.emit('ChangeCookie');
761
  /******************************** */
762
  }));
 
772
  break;
773
 
774
  default:
775
+ !['/', '/v1', '/favicon.ico'].includes(req.url) && (console.log('unknown request: ' + req.url)); //console.log('unknown request: ' + req.url);
776
+ res.writeHead(200, {'Content-Type': 'text/html'});
777
+ res.write(`<!DOCTYPE html>\n<html>\n<head>\n<meta charset="utf-8">\n<script>\nfunction copyToClipboard(text) {\n var textarea = document.createElement("textarea");\n textarea.textContent = text;\n textarea.style.position = "fixed";\n document.body.appendChild(textarea);\n textarea.select();\n try {\n return document.execCommand("copy");\n } catch (ex) {\n console.warn("Copy to clipboard failed.", ex);\n return false;\n } finally {\n document.body.removeChild(textarea);\n }\n}\nfunction copyLink(event) {\n event.preventDefault();\n const url = new URL(window.location.href);\n const link = url.protocol + '//' + url.host + '/v1';\n copyToClipboard(link);\n alert('链接已复制: ' + link);\n}\n</script>\n</head>\n<body>\n${Main}<br/><br/>完全开源、免费且禁止商用<br/><br/>反向代理: <a href="v1" onclick="copyLink(event)">点击复制链接</a><br/>填入OpenAI API反向代理并选择OpenAI分类中的claude-2模型(酒馆需打开Show "External" models)<br/><br/>教程与FAQ: <a href="https://rentry.org/teralomaniac_clewd" target="FAQ">https://rentry.org/teralomaniac_clewd</a>\n</body>\n</html>`);
778
+ res.end();
779
+ /*res.json(
780
+ {
781
  error: {
782
  message: '404 Not Found',
783
  type: 404,
784
  param: null,
785
  code: 404
786
  }
787
+ }, 404);*/
788
  }
789
  }));
790
 
 
842
  Config.rProxy.endsWith('/') && (Config.rProxy = Config.rProxy.slice(0, -1));
843
  let uniqueArr = [], seen = new Set();
844
  for (let Cookie of Config.CookieArray) {
845
+ !/^sessionKey=/.test(Cookie) && (Cookie += 'sessionKey=');
846
  if (!seen.has(Cookie)) {
847
  uniqueArr.push(Cookie);
848
  seen.add(Cookie);
lib/clewd-stream.js CHANGED
@@ -42,8 +42,6 @@ class ClewdStream extends TransformStream {
42
  #stopReason=void 0;
43
  #hardCensor=false;
44
  #impersonated=false;
45
- #cookiechange=false;
46
- #readonly=false;
47
  get size() {
48
  return this.#recvLength;
49
  }
@@ -68,7 +66,7 @@ class ClewdStream extends TransformStream {
68
  }
69
  #err(err, controller) {
70
  this.#logger?.write(JSON.stringify(err, null, 4));
71
- const message = `## ${this.#version}\n**${AI.mdl()} error**:\n${err.status || err.code || err.type}\n\n\`\`\`${err.message}\`\`\``;
72
  this.#enqueue(this.#build(message), controller);
73
  return this.#endEarly(controller);
74
  }
@@ -98,7 +96,7 @@ class ClewdStream extends TransformStream {
98
  this.#streaming ? this.#compOK.length > 0 && this.#enqueue(this.#build(this.#compOK), controller) : this.#enqueue(this.#build(this.#compAll.join('')), controller);
99
  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);
100
  if (!this.#ended && 0 === this.total) {
101
- const err = `## ${this.#version}\n**error**:\n\n\`\`\`Received no valid replies at all\`\`\``;
102
  this.#enqueue(this.#build(err), controller);
103
  }
104
  this.#streaming && this.#enqueue('data: [DONE]\n\n', controller);
@@ -157,7 +155,7 @@ class ClewdStream extends TransformStream {
157
  },
158
  status: this.#source.status,
159
  superfetch: this.#source.superfetch
160
- }), false);
161
  delete err.stack;
162
  return this.#err(err, controller);
163
  }
 
42
  #stopReason=void 0;
43
  #hardCensor=false;
44
  #impersonated=false;
 
 
45
  get size() {
46
  return this.#recvLength;
47
  }
 
66
  }
67
  #err(err, controller) {
68
  this.#logger?.write(JSON.stringify(err, null, 4));
69
+ const message = `## ${this.#version}\n**${AI.mdl()} error**:\n${err.status || err.code || err.type}\n\n\`\`\`${err.message}\`\`\`\n\nFAQ: https://rentry.org/teralomaniac_clewd`;
70
  this.#enqueue(this.#build(message), controller);
71
  return this.#endEarly(controller);
72
  }
 
96
  this.#streaming ? this.#compOK.length > 0 && this.#enqueue(this.#build(this.#compOK), controller) : this.#enqueue(this.#build(this.#compAll.join('')), controller);
97
  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);
98
  if (!this.#ended && 0 === this.total) {
99
+ const err = `## ${this.#version}\n**error**:\n\n\`\`\`Received no valid replies at all\`\`\`\n\nFAQ: https://rentry.org/teralomaniac_clewd`;
100
  this.#enqueue(this.#build(err), controller);
101
  }
102
  this.#streaming && this.#enqueue('data: [DONE]\n\n', controller);
 
155
  },
156
  status: this.#source.status,
157
  superfetch: this.#source.superfetch
158
+ }), false, false); //}), false);
159
  delete err.stack;
160
  return this.#err(err, controller);
161
  }
lib/clewd-utils.js CHANGED
@@ -5,7 +5,7 @@
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 + '修改版 by tera', Replacements = {
9
  user: 'Human',
10
  assistant: 'Assistant',
11
  system: '',
@@ -13,8 +13,8 @@ new TextEncoder), Main = 'clewd v' + Version + '修改版 by tera', Replacements
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, 99, 108, 97, 117, 100, 101, 46, 97, 105 ]).toString(),
16
- mdl: () => Buffer.from([ 99, 108, 97, 117, 100, 101, 45, 50 ]).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, 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, 49, 52, 46, 48, 46, 48, 46, 48, 32, 83, 97, 102, 97, 114, 105, 47, 53, 51, 55, 46, 51, 54, 32, 69, 100, 103, 47, 49, 49, 52, 46, 48, 46, 49, 56, 50, 51, 46, 55, 57 ]).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
  hdr: refPath => ({
@@ -42,7 +42,7 @@ module.exports.Replacements = Replacements;
42
 
43
  module.exports.DangerChars = DangerChars;
44
 
45
- module.exports.checkResErr = async (res, throwIt = true) => {
46
  let err, json, errAPI;
47
  if ('string' == typeof res) {
48
  json = JSON.parse(res);
@@ -61,6 +61,12 @@ module.exports.checkResErr = async (res, throwIt = true) => {
61
  if ((429 === res.status || 429 === json.status) && errAPI.resets_at) {
62
  const hours = ((new Date(1e3 * errAPI.resets_at).getTime() - Date.now()) / 1e3 / 60 / 60).toFixed(1);
63
  err.message += `, expires in ${hours} hours`;
 
 
 
 
 
 
64
  }
65
  if (throwIt) {
66
  throw err;
 
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 + '(10) by tera', Replacements = {
9
  user: 'Human',
10
  assistant: 'Assistant',
11
  system: '',
 
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, 99, 108, 97, 117, 100, 101, 46, 97, 105 ]).toString(),
16
+ mdl: () => Buffer.from([ 99, 108, 97, 117, 100, 101, 45, 50, 46, 49 ]).toString(),
17
+ zone: () => Buffer.from([ 65, 115, 105, 97, 47, 83, 104, 97, 110, 103, 104, 97, 105 ]).toString(), //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, 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, 49, 52, 46, 48, 46, 48, 46, 48, 32, 83, 97, 102, 97, 114, 105, 47, 53, 51, 55, 46, 51, 54, 32, 69, 100, 103, 47, 49, 49, 52, 46, 48, 46, 49, 56, 50, 51, 46, 55, 57 ]).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
  hdr: refPath => ({
 
42
 
43
  module.exports.DangerChars = DangerChars;
44
 
45
+ module.exports.checkResErr = async (res, CookieChanger, throwIt = true) => { //module.exports.checkResErr = async (res, throwIt = true) => {
46
  let err, json, errAPI;
47
  if ('string' == typeof res) {
48
  json = JSON.parse(res);
 
61
  if ((429 === res.status || 429 === json.status) && errAPI.resets_at) {
62
  const hours = ((new Date(1e3 * errAPI.resets_at).getTime() - Date.now()) / 1e3 / 60 / 60).toFixed(1);
63
  err.message += `, expires in ${hours} hours`;
64
+ /************************** */
65
+ if (CookieChanger) {
66
+ console.log(`Exceeded limit!\n`);
67
+ CookieChanger && CookieChanger.emit('ChangeCookie');
68
+ }
69
+ /************************** */
70
  }
71
  if (throwIt) {
72
  throw err;
package.json CHANGED
@@ -1,7 +1,7 @@
1
  {
2
  "name": "clewd",
3
  "version": "4.6",
4
- "description": ":^)",
5
  "main": "clewd.js",
6
  "engines": {
7
  "node": ">=20.4.0"
@@ -35,5 +35,8 @@
35
  "bugs": {
36
  "url": "https://gitgud.io/ahsk/clewd/-/issues"
37
  },
38
- "dependencies": {"localtunnel": "^2.0.2"}
 
 
 
39
  }
 
1
  {
2
  "name": "clewd",
3
  "version": "4.6",
4
+ "description": "<div align=\"center\"> <a href=\"https://github.com/teralomaniac/clewd\"> <h1>Clewd</h1> <img height=\"120\" width=\"120\" alt=\"Clewd\" title=\"Clewd\" src=\"https://gitgud.io/ahsk/clewd/-/raw/master/media/logo.png\" align=\"left\" />",
5
  "main": "clewd.js",
6
  "engines": {
7
  "node": ">=20.4.0"
 
35
  "bugs": {
36
  "url": "https://gitgud.io/ahsk/clewd/-/issues"
37
  },
38
+ "dependencies": {
39
+ "localtunnel": "^2.0.2",
40
+ "gpt-tokenizer": "^2.1.2"
41
+ }
42
  }