teralomaniac commited on
Commit
73b1774
1 Parent(s): fbec572
Files changed (5) hide show
  1. CHANGELOG.md +4 -0
  2. clewd.js +116 -106
  3. lib/clewd-stream.js +2 -2
  4. lib/clewd-utils.js +6 -7
  5. package.json +1 -1
CHANGELOG.md CHANGED
@@ -12,6 +12,10 @@
12
  </a>
13
  </div>
14
 
 
 
 
 
15
  # 4.6
16
 
17
  fixed major bug in the prompt build logic which was causing problems like the AI refering to old messages erroneously, ignoring your latest message, etc
 
12
  </a>
13
  </div>
14
 
15
+ # 4.7
16
+
17
+ added multiple model options in case you subscribe to their plans. some based on their docs, some on rumors. stick to 2.1 if you're a free user
18
+
19
  # 4.6
20
 
21
  fixed major bug in the prompt build logic which was causing problems like the AI refering to old messages erroneously, ignoring your latest message, etc
clewd.js CHANGED
@@ -7,19 +7,23 @@
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, tokens, apiKey;
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);
20
- Proxy.on('error', (err => {
21
- console.error('Proxy error\n%o', err);
22
- }));
 
 
 
 
23
  });
24
 
25
  const convertToType = value => {
@@ -32,32 +36,47 @@ const convertToType = value => {
32
  Config.Cookie = '';
33
  writeSettings(Config);
34
  currentIndex = (currentIndex - 1 + Config.CookieArray.length) % Config.CookieArray.length;
 
 
 
 
 
 
 
35
  }, padtxt = content => {
36
  const {countTokens} = require('@anthropic-ai/tokenizer');
37
  const placeholder = Config.padtxt_placeholder || randomBytes(randomInt(5, 15)).toString('hex');
38
  tokens = countTokens(content);
39
- const padding = placeholder.repeat(Math.floor(Math.max(1000, Config.Settings.padtxt - tokens) / countTokens(placeholder.trim())));
40
- content = content.includes('<|padtxt|>') ? content.replace(/<\|padtxt\|>/, padding) : !apiKey ? padding + '\n\n\n' + content.trim() : content;
41
  return content;
42
- }, xmlPlot = (content, nonsys = false) => {
43
- const card = content.includes('<card>') || content.includes('<|card|>');
44
- //role合并
45
- const MergeDisable = content.includes('<|Merge Disable|>');
46
- const MergeHumanDisable = content.includes('<|Merge Human Disable|>');
47
- const MergeAssistantDisable = content.includes('<|Merge Assistant Disable|>');
48
- if (!MergeDisable) {
49
- if (content.includes('<|Merge System Disable|>')) {
50
- content = content.replace(/(\n\n|^\s*)xmlPlot:\s*/gm, '$1');
51
  }
52
- if (!MergeHumanDisable) {
53
  nonsys ? content = content.replace(/(\n\n|^\s*)xmlPlot:/g, '\n\nHuman:') : content = content.replace(/(\n\n|^\s*)(?<!\n\n(Human|Assistant):.*?)xmlPlot:\s*/gs, '$1').replace(/(\n\n|^\s*)xmlPlot:/g, '\n\nHuman:');
54
  content = content.replace(/(?:\n\n|^\s*)Human:(.*?(?:\n\nAssistant:|$))/gs, function(match, p1) {return '\n\nHuman:' + p1.replace(/\n\nHuman:\s*/g, '\n\n')});
55
  }
56
- if (!MergeAssistantDisable) {
57
  content = content.replace(/\n\nAssistant:(.*?(?:\n\nHuman:|$))/gs, function(match, p1) {return '\n\nAssistant:' + p1.replace(/\n\nAssistant:\s*/g, '\n\n')});
58
  }
59
  }
60
- content = content.replace(/(\n\n|^\s*)xmlPlot:\s*/gm, '$1');
 
 
 
 
 
 
 
 
 
 
 
 
 
61
  //自定义插入
62
  content = content.replace(/(<\/?)PrevAssistant>/gm, '$1@1>').replace(/(<\/?)PrevHuman>/gm, '$1@2>');
63
  let splitContent = content.split(/\n\n(?=Assistant:|Human:)/g);
@@ -71,40 +90,25 @@ const convertToType = value => {
71
  }
72
  content = splitContent.join('\n\n');
73
  content = content.replace(/<@(\d+)>.*?<\/@\1>/gs, '');
74
- //正则
75
- while ((match = /<regex>"(\/?)(.*)\1(.*)" *: *"(.*?)"<\/regex>/gm.exec(content)) !== null) {
76
- try {
77
- content = content.replace(new RegExp(match[2], match[3]), match[4]);
78
- } catch (error) {}
79
- content = content.replace(match[0], '');
80
- }
81
- content = content.replace(/(\r\n|\r|\\n)/gm, '\n');
82
  //二次role合并
83
- if (!MergeDisable) {
84
- if (!MergeHumanDisable) {
85
- content = content.replace(/(?:\n\n|^\s*)Human:(.*?(?:\n\nAssistant:|$))/gs, function(match, p1) {return '\n\nHuman:' + p1.replace(/\n\nHuman:\s*/g, '\n\n')});
86
- }
87
- if (!MergeAssistantDisable) {
88
- content = content.replace(/\n\nAssistant:(.*?(?:\n\nHuman:|$))/gs, function(match, p1) {return '\n\nAssistant:' + p1.replace(/\n\nAssistant:\s*/g, '\n\n')});
89
- }
90
- }
91
  //Plain Prompt
92
  let segcontentHuman = content.split('\n\nHuman:');
93
  let segcontentlastIndex = segcontentHuman.length - 1;
94
  if (!apiKey && segcontentlastIndex >= 2 && segcontentHuman[segcontentlastIndex].includes('<|Plain Prompt Enable|>') && !content.includes('\n\nPlainPrompt:')) {
95
  content = segcontentHuman.slice(0, segcontentlastIndex).join('\n\nHuman:') + '\n\nPlainPrompt:' + segcontentHuman.slice(segcontentlastIndex).join('\n\nHuman:').replace(/\n\nHuman: *PlainPrompt:/, '\n\nPlainPrompt:');
96
  }
97
- //<card>群组
98
- if (!card) {
99
- return content.replace(/(<reply>\n|\n<\/reply>)/g, '').replace(/<customname>(.*?)<\/customname>/gm, '$1');
100
- } else {
101
- content = content.replace(/(<reply>\n|\n<\/reply>)\1*/g, '$1').replace(/<customname>(.*?)<\/customname>:/gm, '$1:\n');
102
- }
103
- //<card>消除空XML tags、两端空白符和多余的\n
104
- content = content.replace(/\s*<\|curtail\|>\s*/g, '\n')
105
  .replace(/\n<\/(card|hidden|META)>\s+?<\1>\n/g, '\n')
106
  .replace(/\n<(\/?card|example|hidden|plot|META)>\s+?<\1>/g, '\n<$1>')
107
- .replace(/\n(?:<!--.*?-->|Here.*?:)?\n<(card|example|hidden|plot|META)>\s+?<\/\1>/g, '')
108
  .replace(/(?<=(: |\n)<(card|hidden|example|plot|META|EOT)>\n)\s*/g, '')
109
  .replace(/\s*(?=\n<\/(card|hidden|example|plot|META|EOT)>(\n|$))/g, '')
110
  .replace(/(?<=\n)\n(?=\n)/g, '');
@@ -112,7 +116,7 @@ const convertToType = value => {
112
  if (apiKey) {
113
  content = content.replace(/\n\n(Assistant|Human):(?!.*?\n\n(Assistant|Human):).*$/s, function(match, p1) {return p1 === 'Assistant' ? match : match + '\n\nAssistant: '}).replace(/\s*<\|noAssistant\|>\s*(.*?)(?:\n\nAssistant:\s*)?$/s, '\n\n$1');
114
  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: '}));
115
- return content.replace(Config.Settings.padtxt ? /\s*<\|(?!padtxt).*?\|>\s*/g : /\s*<\|.*?\|>\s*/g, '\n\n').trim().replace(/^(Human|Assistant):/, '\n\n$&').replace(/\n\n(Human|Assistant):$/, '$& ');
116
  } else {
117
  return content.replace(Config.Settings.padtxt ? /\s*<\|(?!padtxt).*?\|>\s*/g : /\s*<\|.*?\|>\s*/g, '\n\n').trim().replace(/^Human:|\n\nAssistant:$/g, '');
118
  }
@@ -138,7 +142,7 @@ let uuidOrg, curPrompt = {}, prevPrompt = {}, prevMessages = [], prevImpersonate
138
  localtunnel: false,
139
  BufferSize: 1,
140
  SystemInterval: 3,
141
- rProxy: AI.end(),
142
  api_rProxy: '',
143
  padtxt_placeholder: '',
144
  PromptExperimentFirst: '',
@@ -208,7 +212,7 @@ const updateParams = res => {
208
  return;
209
  }
210
  try { //
211
- const res = await fetch(`${Config.rProxy}/api/organizations/${uuidOrg}/chat_conversations/${uuid}`, {
212
  headers: {
213
  ...AI.hdr(),
214
  Cookie: getCookies()
@@ -244,13 +248,13 @@ const updateParams = res => {
244
  }
245
  try {
246
  /***************************** */
247
- if ('SET YOUR COOKIE HERE' === Config.Cookie || Config.Cookie?.length < 1) {
248
  return console.log(`No cookie available, apiKey-Only mode enabled.\n`); //throw Error('Set your cookie inside config.js');
249
  }
250
  updateCookies(Config.Cookie.replace(/^(sessionKey=)?/, 'sessionKey=')); //updateCookies(Config.Cookie);
251
  //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`);
252
  //Config.Settings.Superfetch && SuperfetchAvailable(true);
253
- const accRes = await fetch(Config.rProxy + '/api/organizations', {
254
  method: 'GET',
255
  headers: {
256
  ...AI.hdr(),
@@ -276,7 +280,7 @@ const updateParams = res => {
276
  setTitle('ok');
277
  updateParams(accRes);
278
  /**************************** */
279
- const accountRes = await fetch(Config.rProxy + '/api/auth/current_account', {
280
  method: 'GET',
281
  headers: {
282
  ...AI.hdr(),
@@ -285,33 +289,29 @@ const updateParams = res => {
285
  });
286
  await checkResErr(accountRes);
287
  const accountInfo = await accountRes.json();
 
288
  /**************************** */
289
  console.log(Config.CookieArray?.length > 0 ? `(index: ${currentIndex || Config.CookieArray.length}) Logged in %o` : 'Logged in %o', { //console.log('Logged in %o', {
290
  name: accInfo.name?.split('@')?.[0],
291
  mail: accountInfo.account.email_address, //
 
292
  capabilities: accInfo.capabilities,
293
  });
294
  uuidOrg = accInfo?.uuid;
295
  /************************* */
296
- model = accountInfo.account.statsig.values.dynamic_configs["6zA9wvTedwkzjLxWy9PVe7yydI00XDQ6L5Fejjq/2o8="]?.value?.model;
297
- model != AI.mdl() && console.log(`${model}`);
298
- if (model != AI.mdl() && Config.Cookiecounter === -2) {
299
- CookieCleaner();
300
- return CookieChanger.emit('ChangeCookie');
301
- }
302
  const Overlap = uuidOrgArray.includes(uuidOrg) && percentage <= 100 && Config.CookieArray?.length > 0;
303
  !Overlap && uuidOrgArray.push(uuidOrg);
304
  const Unverified = !accountInfo.account.completed_verification_at;
305
- const abuseTag = accountInfo.account.statsig.values.feature_gates["4fDxNAVXgvks8yzKUoU+T+w3Qr3oYVqoJJVNYh04Mik="]?.secondary_exposures[0];
306
- const Banned = abuseTag.gateValue === 'true' && abuseTag.gate === 'segment:abuse';
307
  const Remain = accountInfo.messageLimit?.remaining;
308
  const Exceededlimit = (accountInfo.messageLimit?.type === 'approaching_limit' && Remain === 0) || accountInfo.messageLimit?.type === 'exceeded_limit';
309
  if (Remain) {
310
  changeflag = Math.max(Config.Cookiecounter - Remain, changeflag);
311
  console.log(`ApproachingLimit!: Remain ${Remain}`);
312
  }
313
- if ((Overlap || Unverified || Banned) && Config.CookieArray?.length > 0) {
314
- Overlap ? console.log(`Overlap!`) : Unverified ? console.log(`Unverified!`) : Banned && console.log(`Banned!`);
315
  CookieCleaner();
316
  Config.Cookiecounter < 0 && console.log(`[progress]: ${percentage.toFixed(2)}%\n[length]: ${Config.CookieArray.length}\n`);
317
  return CookieChanger.emit('ChangeCookie');
@@ -335,7 +335,7 @@ const updateParams = res => {
335
  if ('consumer_restricted_mode' === type || 'consumer_banned' === type) { //if ('consumer_restricted_mode' === type) {
336
  return;
337
  }
338
- const req = await (Config.Settings.Superfetch ? Superfetch : fetch)(`${Config.rProxy}/api/organizations/${uuidOrg}/flags/${type}/dismiss`, {
339
  headers: {
340
  ...AI.hdr(),
341
  Cookie: getCookies()
@@ -359,7 +359,7 @@ const updateParams = res => {
359
  return CookieChanger.emit('ChangeCookie');
360
  /***************************** */
361
  }
362
- const convRes = await fetch(`${Config.rProxy}/api/organizations/${uuidOrg}/chat_conversations`, {
363
  method: 'GET',
364
  headers: {
365
  ...AI.hdr(),
@@ -369,6 +369,7 @@ const updateParams = res => {
369
  updateParams(convRes);
370
  conversations.length > 0 && await Promise.all(conversations.map((conv => deleteChat(conv.uuid))));
371
  /***************************** */
 
372
  } catch (err) {
373
  console.error('Clewd:\n%o', err);
374
  Config.CookieArray?.length > 0 && CookieChanger.emit('ChangeCookie');
@@ -394,20 +395,19 @@ const updateParams = res => {
394
  switch (req.url) {
395
  case '/v1/models':
396
  res.json({
397
- data: [ {
398
  /***************************** */
399
- id: 'claude-2.1' },{
400
- id: 'claude-2.0' },{
401
- id: 'claude-v1.3' },{
402
- id: 'claude-v1.3-100k' },{
403
- id: 'claude-v1.2' },{
404
- id: 'claude-v1.0' },{
405
- id: 'claude-instant-1.2' },{
406
- id: 'claude-instant-v1.1' },{
407
- id: 'claude-instant-v1.1-100k' },{
408
- id: 'claude-instant-v1.0' //id: AI.mdl()
 
409
  /***************************** */
410
- } ]
411
  });
412
  break;
413
 
@@ -429,16 +429,18 @@ const updateParams = res => {
429
  const body = JSON.parse(Buffer.concat(buffer).toString()), temperature = Math.max(.1, Math.min(1, body.temperature));
430
  let {messages} = body;
431
  /************************* */
432
- apiKey = req.headers.authorization.match(/sk-ant-api\d\d-[\w-]{86}-[\w-]{6}AA/g);
433
- let api_max_tokens, api_model;
434
- if (apiKey) {
435
- api_max_tokens = body.max_tokens;
436
- api_model = body.model;
437
- if (!api_model.includes('claude')) throw Error('Please change to claude model in "External"');
438
- } else if (req.headers.authorization.includes('sk-ant-api')) {
439
- throw Error('apiKey Wrong');
440
- } else if (Config.ProxyPassword != '' && req.headers.authorization != 'Bearer ' + Config.ProxyPassword) {
441
- throw Error('ProxyPassword Wrong');
 
 
442
  }
443
  /************************* */
444
  if (messages?.length < 1) {
@@ -471,7 +473,13 @@ const updateParams = res => {
471
  console.log('having AllSamples and NoSamples both set to true is not supported');
472
  throw Error('Only one can be used at the same time: AllSamples/NoSamples');
473
  }
474
- //const model = AI.mdl();
 
 
 
 
 
 
475
  curPrompt = {
476
  firstUser: messages.find((message => 'user' === message.role)),
477
  firstSystem: messages.find((message => 'system' === message.role)),
@@ -504,7 +512,7 @@ const updateParams = res => {
504
  completion: {
505
  prompt: '',
506
  timezone: AI.zone(),
507
- model: model || AI.mdl()
508
  },
509
  organization_uuid: uuidOrg,
510
  conversation_uuid: Conversation.uuid,
@@ -519,7 +527,7 @@ const updateParams = res => {
519
  const names = Object.keys(headers), values = Object.values(headers);
520
  headers = names.map(((header, idx) => `${header}: ${values[idx]}`));
521
  }
522
- res = await (Config.Settings.Superfetch ? Superfetch : fetch)(Config.rProxy + '/api/retry_message', {
523
  stream: true,
524
  signal,
525
  method: 'POST',
@@ -535,7 +543,7 @@ const updateParams = res => {
535
  fetchAPI = await (async signal => {
536
  Conversation.uuid = randomUUID().toString();
537
  Conversation.depth = 0;
538
- const res = await (Config.Settings.Superfetch ? Superfetch : fetch)(`${Config.rProxy}/api/organizations/${uuidOrg}/chat_conversations`, {
539
  signal,
540
  headers: {
541
  ...AI.hdr(),
@@ -644,8 +652,8 @@ const updateParams = res => {
644
  /******************************** */
645
  if (Config.Settings.xmlPlot) {
646
  idx > 0 && (spacing = '\n\n');
647
- const prefix = message.customname ? message.role + ': <customname>' + message.name + '</customname>: ' : 'system' !== message.role || message.name ? Replacements[message.name || message.role] + ': ' : 'xmlPlot: ' + Replacements[message.role];
648
- return `${spacing}${prefix}${message.customname ? '<reply>\n' + message.content.trim() + '\n</reply>' : message.content}`;
649
  } else {
650
  /******************************** */
651
  idx > 0 && (spacing = systemMessages.includes(message) ? '\n' : '\n\n');
@@ -654,20 +662,20 @@ const updateParams = res => {
654
  } //
655
  }));
656
  return {
657
- prompt: prompt.join('').trim(), //genericFixes(prompt.join('')).trim(),
658
  systems
659
  };
660
  })(messages, type);
661
- console.log(`${apiKey ? api_model : model} [${type}]${!retryRegen && systems.length > 0 ? ' ' + systems.join(' / ') : ''}`); //console.log(`${model} [${type}]${!retryRegen && systems.length > 0 ? ' ' + systems.join(' / ') : ''}`);
662
  'R' !== type || prompt || (prompt = '...regen...');
663
  /******************************** */
664
- prompt = Config.Settings.xmlPlot ? xmlPlot(prompt, api_model && api_model != 'claude-2.1') : apiKey ? `\n\nHuman: ${genericFixes(prompt)}\n\nAssistant: ` : genericFixes(prompt);
665
  Config.Settings.FullColon && (prompt = apiKey
666
- ? prompt.replace(/(\n\nAssistant|\n\nHuman):/, function(match, p1) {return p1 === '\n\nHuman' ? match : p1 + ':'}).replace(/(\n\nAssistant|\n\nHuman):(?!.*?\n\n(Assistant|Human):)/s, function(match, p1) {return p1 === '\n\nAssistant' ? match : p1 + ':'})
667
  : prompt.replace(/(?<=\n\n(H(?:uman)?|A(?:ssistant)?)):[ ]?/g, ': '));
668
  Config.Settings.padtxt && (prompt = padtxt(prompt));
669
  /******************************** */
670
- Logger?.write(`\n\n-------\n[${(new Date).toLocaleString()}]\n####### ${apiKey ? api_model : model} PROMPT (${type}):\n${prompt}\n--\n####### [Tokens: ${tokens}] REPLY:\n`); //Logger?.write(`\n\n-------\n[${(new Date).toLocaleString()}]\n####### PROMPT (${type}):\n${prompt}\n--\n####### REPLY:\n`);
671
  retryRegen || (fetchAPI = await (async (signal, model, prompt, temperature, type) => {
672
  /******************************** */
673
  if (apiKey) {
@@ -680,8 +688,9 @@ const updateParams = res => {
680
  'anthropic-version': '2023-06-01'
681
  },
682
  body: JSON.stringify({
683
- model: api_model,
684
- max_tokens_to_sample: api_max_tokens,
 
685
  stream: true,
686
  prompt,
687
  temperature
@@ -712,11 +721,11 @@ const updateParams = res => {
712
  },
713
  prompt: prompt || '',
714
  timezone: AI.zone(),
715
- model: model || AI.mdl()
716
  },
717
  organization_uuid: uuidOrg,
718
  conversation_uuid: Conversation.uuid,
719
- text: prompt,
720
  attachments
721
  };
722
  let headers = {
@@ -724,7 +733,7 @@ const updateParams = res => {
724
  Accept: 'text/event-stream',
725
  Cookie: getCookies()
726
  };
727
- res = await (Config.Settings.Superfetch ? Superfetch : fetch)(Config.rProxy + '/api/append_message', {
728
  stream: true,
729
  signal,
730
  method: 'POST',
@@ -747,7 +756,7 @@ const updateParams = res => {
747
  version: Main,
748
  minSize: Config.BufferSize,
749
  model,
750
- streaming: body.stream,
751
  abortControl,
752
  source: fetchAPI
753
  }, Logger);
@@ -757,6 +766,7 @@ const updateParams = res => {
757
  if ('AbortError' === err.name) {
758
  res.end();
759
  } else {
 
760
  err.planned || console.error('Clewd:\n%o', err);
761
  res.json({
762
  error: {
@@ -780,7 +790,7 @@ const updateParams = res => {
780
  await deleteChat(Conversation.uuid);
781
  /******************************** */
782
  changeflag += 1;
783
- if (Config.CookieArray?.length > 0 && (429 == fetchAPI?.status || Config.Cookiecounter && changeflag >= Config.Cookiecounter)) {
784
  changeflag = 0;
785
  CookieChanger.emit('ChangeCookie');
786
  }
@@ -857,7 +867,7 @@ const updateParams = res => {
857
  Config[key] = process.env[key] ? convertToType(process.env[key]) : Config[key];
858
  }
859
  }
860
- Config.rProxy = Config.rProxy ? Config.rProxy.replace(/\/$/, '') : AI.end();
861
  Config.CookieArray = [...new Set([Config.CookieArray].join('').match(/(sessionKey=)?sk-ant-sid01-[\w-]{86}-[\w-]{6}AA/g))];
862
  writeSettings(Config);
863
  currentIndex = Config.CookieIndex > 0 ? Config.CookieIndex - 1 : Config.Cookiecounter >= 0 ? Math.floor(Math.random() * Config.CookieArray.length) : 0;
 
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, changing, changetime = 0, totaltime, invalidtime = 0, uuidOrgArray = [], model, reqModel, tokens, apiKey, timestamp = Date.now();
11
 
12
  const events = require('events'), CookieChanger = new events.EventEmitter();
13
  require('events').EventEmitter.defaultMaxListeners = 0;
14
 
15
  CookieChanger.on('ChangeCookie', () => {
16
+ setTimeout(() => {
17
+ changeflag = 0, changing = true;
18
+ Proxy && Proxy.close();
19
+ console.log(`Changing Cookie...\n`);
20
+ Proxy.listen(Config.Port, Config.Ip, onListen);
21
+ Proxy.on('error', (err => {
22
+ console.error('Proxy error\n%o', err);
23
+ }));
24
+ timestamp = Date.now();
25
+ invalidtime += 1;
26
+ }, !Config.rProxy || Config.rProxy === AI.end() ? 15000 + timestamp - Date.now() : 0);
27
  });
28
 
29
  const convertToType = value => {
 
36
  Config.Cookie = '';
37
  writeSettings(Config);
38
  currentIndex = (currentIndex - 1 + Config.CookieArray.length) % Config.CookieArray.length;
39
+ }, ProModelConvert = model => {
40
+ if (/^claude-2\.0$/.test(model)) return AI.mdl()[7];
41
+ if (/1\.3/.test(model)) return AI.mdl()[5];
42
+ if (/^claude-v1\.\d$/.test(model)) return AI.mdl()[1];
43
+ if (/100k/.test(model)) return AI.mdl()[2];
44
+ if (/v1\.\d/.test(model)) return AI.mdl()[3];
45
+ return model;
46
  }, padtxt = content => {
47
  const {countTokens} = require('@anthropic-ai/tokenizer');
48
  const placeholder = Config.padtxt_placeholder || randomBytes(randomInt(5, 15)).toString('hex');
49
  tokens = countTokens(content);
50
+ const padding = placeholder.repeat(Math.floor((/(?<=<\|padtxt.*?)\d+(?=.*?\|>)/.test(content) ? parseInt(/(?<=<\|padtxt.*?)\d+(?=.*?\|>)/.exec(content)[0]) : Math.max(1000, Config.Settings.padtxt - tokens)) / countTokens(placeholder.trim())));
51
+ content = /<\|padtxt.*?\|>/.test(content) ? content.replace(/<\|padtxt.*?\|>/, padding).replace(/\s*<\|padtxt.*?\|>\s*/g, '\n\n') : !apiKey ? padding + '\n\n\n' + content.trim() : content;
52
  return content;
53
+ }, xmlPlot_merge = (content, nonsys) => {
54
+ if (!content.includes('<|Merge Disable|>')) {
55
+ if (content.includes('<|System Role|>')) {
56
+ content = content.replace(/(?:\n\n|^\s*)(?:xmlPlot|System):(.*?(?:\n\n(Assistant|Human):|$))/gs, function(match, p1) {return '\n\nSystem:' + p1.replace(/(\n\n|^\s*)(xmlPlot|System):\s*/g, '\n\n')});
 
 
 
 
 
57
  }
58
+ if (!content.includes('<|Merge Human Disable|>')) {
59
  nonsys ? content = content.replace(/(\n\n|^\s*)xmlPlot:/g, '\n\nHuman:') : content = content.replace(/(\n\n|^\s*)(?<!\n\n(Human|Assistant):.*?)xmlPlot:\s*/gs, '$1').replace(/(\n\n|^\s*)xmlPlot:/g, '\n\nHuman:');
60
  content = content.replace(/(?:\n\n|^\s*)Human:(.*?(?:\n\nAssistant:|$))/gs, function(match, p1) {return '\n\nHuman:' + p1.replace(/\n\nHuman:\s*/g, '\n\n')});
61
  }
62
+ if (!content.includes('<|Merge Assistant Disable|>')) {
63
  content = content.replace(/\n\nAssistant:(.*?(?:\n\nHuman:|$))/gs, function(match, p1) {return '\n\nAssistant:' + p1.replace(/\n\nAssistant:\s*/g, '\n\n')});
64
  }
65
  }
66
+ return content.replace(/(\n\n|^\s*)xmlPlot:\s*/gm, '$1');
67
+ }, xmlPlot_regex = (content, order) => {
68
+ let match, regex = new RegExp(`<regex(?: +order *= *${order})${order === 2 ? '?' : ''}> *"(/?)(.*)\\1(.*?)" *: *"(.*?)" *</regex>`, 'gm');
69
+ while ((match = regex.exec(content)) !== null) {
70
+ try {
71
+ content = content.replace(new RegExp(match[2], match[3]), match[4].replace(/(\r\n|\r|\\n)/gm, '\n'));
72
+ } catch (err) {}
73
+ }
74
+ return content;
75
+ }, xmlPlot = (content, nonsys = false) => {
76
+ //一次正则
77
+ content = xmlPlot_regex(content, 1);
78
+ //一次role合并
79
+ content = xmlPlot_merge(content, nonsys);
80
  //自定义插入
81
  content = content.replace(/(<\/?)PrevAssistant>/gm, '$1@1>').replace(/(<\/?)PrevHuman>/gm, '$1@2>');
82
  let splitContent = content.split(/\n\n(?=Assistant:|Human:)/g);
 
90
  }
91
  content = splitContent.join('\n\n');
92
  content = content.replace(/<@(\d+)>.*?<\/@\1>/gs, '');
93
+ //二次正则
94
+ content = xmlPlot_regex(content, 2);
 
 
 
 
 
 
95
  //二次role合并
96
+ content = xmlPlot_merge(content, nonsys);
 
 
 
 
 
 
 
97
  //Plain Prompt
98
  let segcontentHuman = content.split('\n\nHuman:');
99
  let segcontentlastIndex = segcontentHuman.length - 1;
100
  if (!apiKey && segcontentlastIndex >= 2 && segcontentHuman[segcontentlastIndex].includes('<|Plain Prompt Enable|>') && !content.includes('\n\nPlainPrompt:')) {
101
  content = segcontentHuman.slice(0, segcontentlastIndex).join('\n\nHuman:') + '\n\nPlainPrompt:' + segcontentHuman.slice(segcontentlastIndex).join('\n\nHuman:').replace(/\n\nHuman: *PlainPrompt:/, '\n\nPlainPrompt:');
102
  }
103
+ //三次正则
104
+ content = xmlPlot_regex(content, 3);
105
+ //消除空XML tags、两端空白符和多余的\n
106
+ content = content.replace(/<regex>.*?<\/regex>/gm, '')
107
+ .replace(/(\r\n|\r|\\n)/gm, '\n')
108
+ .replace(/\s*<\|curtail\|>\s*/g, '\n')
 
 
109
  .replace(/\n<\/(card|hidden|META)>\s+?<\1>\n/g, '\n')
110
  .replace(/\n<(\/?card|example|hidden|plot|META)>\s+?<\1>/g, '\n<$1>')
111
+ .replace(/(?:<!--.*?-->\n|.+?: ?\n)?<(card|example|hidden|plot|META)>\s+?<\/\1>\n*/g, '')
112
  .replace(/(?<=(: |\n)<(card|hidden|example|plot|META|EOT)>\n)\s*/g, '')
113
  .replace(/\s*(?=\n<\/(card|hidden|example|plot|META|EOT)>(\n|$))/g, '')
114
  .replace(/(?<=\n)\n(?=\n)/g, '');
 
116
  if (apiKey) {
117
  content = content.replace(/\n\n(Assistant|Human):(?!.*?\n\n(Assistant|Human):).*$/s, function(match, p1) {return p1 === 'Assistant' ? match : match + '\n\nAssistant: '}).replace(/\s*<\|noAssistant\|>\s*(.*?)(?:\n\nAssistant:\s*)?$/s, '\n\n$1');
118
  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: '}));
119
+ return content.replace(Config.Settings.padtxt ? /\s*<\|(?!padtxt).*?\|>\s*/g : /\s*<\|.*?\|>\s*/g, '\n\n').trim().replace(/^.+:/, '\n\n$&').replace(/\n\n.+:$/, '$& ');
120
  } else {
121
  return content.replace(Config.Settings.padtxt ? /\s*<\|(?!padtxt).*?\|>\s*/g : /\s*<\|.*?\|>\s*/g, '\n\n').trim().replace(/^Human:|\n\nAssistant:$/g, '');
122
  }
 
142
  localtunnel: false,
143
  BufferSize: 1,
144
  SystemInterval: 3,
145
+ rProxy: '',
146
  api_rProxy: '',
147
  padtxt_placeholder: '',
148
  PromptExperimentFirst: '',
 
212
  return;
213
  }
214
  try { //
215
+ const res = await fetch(`${Config.rProxy || AI.end()}/api/organizations/${uuidOrg}/chat_conversations/${uuid}`, {
216
  headers: {
217
  ...AI.hdr(),
218
  Cookie: getCookies()
 
248
  }
249
  try {
250
  /***************************** */
251
+ if ('SET YOUR COOKIE HERE' === Config.Cookie || Config.Cookie?.length < 1 || (Config.CookieArray?.length > 0 && invalidtime > totaltime)) { //if ('SET YOUR COOKIE HERE' === Config.Cookie || Config.Cookie?.length < 1) {
252
  return console.log(`No cookie available, apiKey-Only mode enabled.\n`); //throw Error('Set your cookie inside config.js');
253
  }
254
  updateCookies(Config.Cookie.replace(/^(sessionKey=)?/, 'sessionKey=')); //updateCookies(Config.Cookie);
255
  //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`);
256
  //Config.Settings.Superfetch && SuperfetchAvailable(true);
257
+ const accRes = await fetch((Config.rProxy || AI.end()) + '/api/organizations', {
258
  method: 'GET',
259
  headers: {
260
  ...AI.hdr(),
 
280
  setTitle('ok');
281
  updateParams(accRes);
282
  /**************************** */
283
+ const accountRes = await fetch((Config.rProxy || AI.end()) + '/api/auth/current_account', {
284
  method: 'GET',
285
  headers: {
286
  ...AI.hdr(),
 
289
  });
290
  await checkResErr(accountRes);
291
  const accountInfo = await accountRes.json();
292
+ model = accountInfo.account.statsig.values.dynamic_configs["6zA9wvTedwkzjLxWy9PVe7yydI00XDQ6L5Fejjq/2o8="]?.value?.model;
293
  /**************************** */
294
  console.log(Config.CookieArray?.length > 0 ? `(index: ${currentIndex || Config.CookieArray.length}) Logged in %o` : 'Logged in %o', { //console.log('Logged in %o', {
295
  name: accInfo.name?.split('@')?.[0],
296
  mail: accountInfo.account.email_address, //
297
+ model, //
298
  capabilities: accInfo.capabilities,
299
  });
300
  uuidOrg = accInfo?.uuid;
301
  /************************* */
302
+ if (reqModel && reqModel != model && !Config.Settings.PassParams) return CookieChanger.emit('ChangeCookie');
 
 
 
 
 
303
  const Overlap = uuidOrgArray.includes(uuidOrg) && percentage <= 100 && Config.CookieArray?.length > 0;
304
  !Overlap && uuidOrgArray.push(uuidOrg);
305
  const Unverified = !accountInfo.account.completed_verification_at;
306
+ const Abused = accountInfo.account.statsig.values.feature_gates["4fDxNAVXgvks8yzKUoU+T+w3Qr3oYVqoJJVNYh04Mik="]?.secondary_exposures[0].gateValue === 'true' && accountInfo.account.statsig.values.feature_gates["4fDxNAVXgvks8yzKUoU+T+w3Qr3oYVqoJJVNYh04Mik="]?.secondary_exposures[0].gate === 'segment:abuse';
 
307
  const Remain = accountInfo.messageLimit?.remaining;
308
  const Exceededlimit = (accountInfo.messageLimit?.type === 'approaching_limit' && Remain === 0) || accountInfo.messageLimit?.type === 'exceeded_limit';
309
  if (Remain) {
310
  changeflag = Math.max(Config.Cookiecounter - Remain, changeflag);
311
  console.log(`ApproachingLimit!: Remain ${Remain}`);
312
  }
313
+ if ((Overlap || Unverified || Abused) && Config.CookieArray?.length > 0) {
314
+ Overlap ? console.log(`Overlap!`) : Unverified ? console.log(`Unverified!`) : Abused && console.log(`Banned!`);
315
  CookieCleaner();
316
  Config.Cookiecounter < 0 && console.log(`[progress]: ${percentage.toFixed(2)}%\n[length]: ${Config.CookieArray.length}\n`);
317
  return CookieChanger.emit('ChangeCookie');
 
335
  if ('consumer_restricted_mode' === type || 'consumer_banned' === type) { //if ('consumer_restricted_mode' === type) {
336
  return;
337
  }
338
+ const req = await (Config.Settings.Superfetch ? Superfetch : fetch)(`${Config.rProxy || AI.end()}/api/organizations/${uuidOrg}/flags/${type}/dismiss`, {
339
  headers: {
340
  ...AI.hdr(),
341
  Cookie: getCookies()
 
359
  return CookieChanger.emit('ChangeCookie');
360
  /***************************** */
361
  }
362
+ const convRes = await fetch(`${Config.rProxy || AI.end()}/api/organizations/${uuidOrg}/chat_conversations`, {
363
  method: 'GET',
364
  headers: {
365
  ...AI.hdr(),
 
369
  updateParams(convRes);
370
  conversations.length > 0 && await Promise.all(conversations.map((conv => deleteChat(conv.uuid))));
371
  /***************************** */
372
+ invalidtime = 0, changing = false;
373
  } catch (err) {
374
  console.error('Clewd:\n%o', err);
375
  Config.CookieArray?.length > 0 && CookieChanger.emit('ChangeCookie');
 
395
  switch (req.url) {
396
  case '/v1/models':
397
  res.json({
 
398
  /***************************** */
399
+ data: [ //data: AI.mdl().map((name => ({
400
+ ...AI.mdl().slice(1).map((name => ({ id: name }))), {
401
+ id: 'claude-2.0' },{
402
+ id: 'claude-v1.3' },{
403
+ id: 'claude-v1.3-100k' },{
404
+ id: 'claude-v1.2' },{
405
+ id: 'claude-v1.0' },{
406
+ id: 'claude-instant-v1.1' },{
407
+ id: 'claude-instant-v1.1-100k' },{
408
+ id: 'claude-instant-v1.0' //id: name
409
+ }] //})))
410
  /***************************** */
 
411
  });
412
  break;
413
 
 
429
  const body = JSON.parse(Buffer.concat(buffer).toString()), temperature = Math.max(.1, Math.min(1, body.temperature));
430
  let {messages} = body;
431
  /************************* */
432
+ apiKey = req.headers.authorization?.match(/sk-ant-api\d\d-[\w-]{86}-[\w-]{6}AA/g) || req.headers.authorization?.match(/(?<=3rdKey: *)[\S]*/);
433
+ reqModel = /^claude-2.[01]$/.test(body.model) ? body.model : '';
434
+ let max_tokens_to_sample, stop_sequences;
435
+ if (apiKey || Config.Settings.PassParams) {
436
+ stop_sequences = body.stop;
437
+ max_tokens_to_sample = body.max_tokens;
438
+ model = body.model;
439
+ } else if (req.headers.authorization.includes('sk-ant-api') || Config.ProxyPassword != '' && req.headers.authorization != 'Bearer ' + Config.ProxyPassword) {
440
+ throw Error(req.headers.authorization.includes('sk-ant-api') ? 'apiKey Wrong' : 'ProxyPassword Wrong');
441
+ } else if (changing || Config.CookieArray?.length > 0 && invalidtime >= Config.CookieArray?.length || reqModel && reqModel != model && !Config.Settings.PassParams) {
442
+ changing ? invalidtime = 0 : changeflag = -1;
443
+ throw Error(reqModel && reqModel && !Config.Settings.PassParams != body.model ? 'Polling requset model...' : 'Changing Cookie...');
444
  }
445
  /************************* */
446
  if (messages?.length < 1) {
 
473
  console.log('having AllSamples and NoSamples both set to true is not supported');
474
  throw Error('Only one can be used at the same time: AllSamples/NoSamples');
475
  }
476
+ //const model = body.model;
477
+ if (!apiKey && Config.Settings.PassParams) { //if (model === AI.mdl()[0]) {
478
+ model = ProModelConvert(model); //return;
479
+ }
480
+ if (!/claude-.*/.test(model)) {
481
+ throw Error('Invalid model selected: ' + model);
482
+ }
483
  curPrompt = {
484
  firstUser: messages.find((message => 'user' === message.role)),
485
  firstSystem: messages.find((message => 'system' === message.role)),
 
512
  completion: {
513
  prompt: '',
514
  timezone: AI.zone(),
515
+ model
516
  },
517
  organization_uuid: uuidOrg,
518
  conversation_uuid: Conversation.uuid,
 
527
  const names = Object.keys(headers), values = Object.values(headers);
528
  headers = names.map(((header, idx) => `${header}: ${values[idx]}`));
529
  }
530
+ res = await (Config.Settings.Superfetch ? Superfetch : fetch)((Config.rProxy || AI.end()) + '/api/retry_message', {
531
  stream: true,
532
  signal,
533
  method: 'POST',
 
543
  fetchAPI = await (async signal => {
544
  Conversation.uuid = randomUUID().toString();
545
  Conversation.depth = 0;
546
+ const res = await (Config.Settings.Superfetch ? Superfetch : fetch)(`${Config.rProxy || AI.end()}/api/organizations/${uuidOrg}/chat_conversations`, {
547
  signal,
548
  headers: {
549
  ...AI.hdr(),
 
652
  /******************************** */
653
  if (Config.Settings.xmlPlot) {
654
  idx > 0 && (spacing = '\n\n');
655
+ const prefix = message.customname ? message.role + ': ' + message.name + ': ' : 'system' !== message.role || message.name ? Replacements[message.name || message.role] + ': ' : 'xmlPlot: ' + Replacements[message.role];
656
+ return `${spacing}${message.strip ? '' : prefix}${message.content}`;
657
  } else {
658
  /******************************** */
659
  idx > 0 && (spacing = systemMessages.includes(message) ? '\n' : '\n\n');
 
662
  } //
663
  }));
664
  return {
665
+ prompt: prompt.join(''), //genericFixes(prompt.join('')).trim(),
666
  systems
667
  };
668
  })(messages, type);
669
+ console.log(`${model} [${type}]${!retryRegen && systems.length > 0 ? ' ' + systems.join(' / ') : ''}`); //console.log(`${model} [${type}]${!retryRegen && systems.length > 0 ? ' ' + systems.join(' / ') : ''}`);
670
  'R' !== type || prompt || (prompt = '...regen...');
671
  /******************************** */
672
+ prompt = Config.Settings.xmlPlot ? xmlPlot(prompt, model != 'claude-2.1') : apiKey ? `\n\nHuman: ${genericFixes(prompt)}\n\nAssistant: ` : genericFixes(prompt).trim();
673
  Config.Settings.FullColon && (prompt = apiKey
674
+ ? prompt.replace(/(?<!\n\nHuman:.*)(\n\nAssistant):/gs, '$1:').replace(/(\n\nHuman):(?!.*\n\nAssistant:)/gs, '$1:')
675
  : prompt.replace(/(?<=\n\n(H(?:uman)?|A(?:ssistant)?)):[ ]?/g, ': '));
676
  Config.Settings.padtxt && (prompt = padtxt(prompt));
677
  /******************************** */
678
+ Logger?.write(`\n\n-------\n[${(new Date).toLocaleString()}]\n####### ${model} (${type}) ${tokens}t PROMPT:\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`);
679
  retryRegen || (fetchAPI = await (async (signal, model, prompt, temperature, type) => {
680
  /******************************** */
681
  if (apiKey) {
 
688
  'anthropic-version': '2023-06-01'
689
  },
690
  body: JSON.stringify({
691
+ ...stop_sequences && {stop_sequences},
692
+ model,
693
+ max_tokens_to_sample,
694
  stream: true,
695
  prompt,
696
  temperature
 
721
  },
722
  prompt: prompt || '',
723
  timezone: AI.zone(),
724
+ model
725
  },
726
  organization_uuid: uuidOrg,
727
  conversation_uuid: Conversation.uuid,
728
+ text: prompt || '',
729
  attachments
730
  };
731
  let headers = {
 
733
  Accept: 'text/event-stream',
734
  Cookie: getCookies()
735
  };
736
+ res = await (Config.Settings.Superfetch ? Superfetch : fetch)((Config.rProxy || AI.end()) + '/api/append_message', {
737
  stream: true,
738
  signal,
739
  method: 'POST',
 
756
  version: Main,
757
  minSize: Config.BufferSize,
758
  model,
759
+ streaming: body.stream, //null != body.stream,
760
  abortControl,
761
  source: fetchAPI
762
  }, Logger);
 
766
  if ('AbortError' === err.name) {
767
  res.end();
768
  } else {
769
+ changeflag -= 1; //
770
  err.planned || console.error('Clewd:\n%o', err);
771
  res.json({
772
  error: {
 
790
  await deleteChat(Conversation.uuid);
791
  /******************************** */
792
  changeflag += 1;
793
+ if (changeflag < 0 || Config.CookieArray?.length > 0 && (429 == fetchAPI?.status || Config.Cookiecounter > 0 && changeflag >= Config.Cookiecounter)) {
794
  changeflag = 0;
795
  CookieChanger.emit('ChangeCookie');
796
  }
 
867
  Config[key] = process.env[key] ? convertToType(process.env[key]) : Config[key];
868
  }
869
  }
870
+ Config.rProxy = Config.rProxy.replace(/\/$/, '');
871
  Config.CookieArray = [...new Set([Config.CookieArray].join('').match(/(sessionKey=)?sk-ant-sid01-[\w-]{86}-[\w-]{6}AA/g))];
872
  writeSettings(Config);
873
  currentIndex = Config.CookieIndex > 0 ? Config.CookieIndex - 1 : Config.Cookiecounter >= 0 ? Math.floor(Math.random() * Config.CookieArray.length) : 0;
lib/clewd-stream.js CHANGED
@@ -19,7 +19,7 @@ class ClewdStream extends TransformStream {
19
  this.#logger = logger;
20
  this.#version = opts.version;
21
  this.#config = opts.config;
22
- this.#model = opts.model || AI.mdl();
23
  this.#streaming = opts.streaming || false;
24
  this.#minSize = opts.minSize || 8;
25
  this.#abortControl = opts.abortControl;
@@ -66,7 +66,7 @@ class ClewdStream extends TransformStream {
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
  }
 
19
  this.#logger = logger;
20
  this.#version = opts.version;
21
  this.#config = opts.config;
22
+ this.#model = opts.model;
23
  this.#streaming = opts.streaming || false;
24
  this.#minSize = opts.minSize || 8;
25
  this.#abortControl = opts.abortControl;
 
66
  }
67
  #err(err, controller) {
68
  this.#logger?.write(JSON.stringify(err, null, 4));
69
+ const message = `## ${this.#version}\n**${this.#model} 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
  }
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 + '(12) by tera', Replacements = {
9
  user: 'Human',
10
  assistant: 'Assistant',
11
  system: '',
@@ -13,7 +13,7 @@ new TextEncoder), Main = 'clewd修改版 v' + Version + '(12) by tera', Replacem
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(),
@@ -75,13 +75,12 @@ module.exports.checkResErr = async (res, CookieChanger, throwIt = true) => { //m
75
  return err;
76
  };
77
 
78
- module.exports.bytesToSize = (bytes = 0) => {
79
- const b = [ 'B', 'KB', 'MB', 'GB', 'TB' ];
80
  if (0 === bytes) {
81
- return '0 B';
82
  }
83
- const c = Math.min(Math.floor(Math.log(bytes) / Math.log(1024)), 4);
84
- return 0 === c ? `${bytes} ${b[c]}` : `${(bytes / 1024 ** c).toFixed(1)} ${b[c]}`;
85
  };
86
 
87
  module.exports.indexOfAny = (text, last = false) => {
 
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 + '(1) 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: () => JSON.parse(Buffer.from([ 91, 34, 33, 32, 85, 83, 73, 78, 71, 32, 77, 79, 68, 69, 76, 83, 32, 79, 84, 72, 69, 82, 32, 84, 72, 65, 78, 32, 99, 108, 97, 117, 100, 101, 45, 50, 46, 49, 32, 42, 67, 79, 85, 76, 68, 42, 32, 71, 69, 84, 32, 89, 79, 85, 32, 66, 65, 78, 78, 69, 68, 32, 73, 70, 32, 89, 79, 85, 39, 82, 69, 32, 78, 79, 84, 32, 65, 32, 80, 82, 79, 32, 85, 83, 69, 82, 32, 33, 34, 44, 34, 99, 108, 97, 117, 100, 101, 45, 49, 34, 44, 34, 99, 108, 97, 117, 100, 101, 45, 105, 110, 115, 116, 97, 110, 116, 45, 49, 48, 48, 107, 34, 44, 34, 99, 108, 97, 117, 100, 101, 45, 105, 110, 115, 116, 97, 110, 116, 45, 49, 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, 49, 46, 51, 34, 44, 34, 99, 108, 97, 117, 100, 101, 45, 50, 46, 48, 45, 109, 97, 103, 101, 110, 116, 97, 34, 44, 34, 99, 108, 97, 117, 100, 101, 45, 50, 34, 44, 34, 99, 108, 97, 117, 100, 101, 45, 50, 46, 49, 34, 93 ]).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(),
 
75
  return err;
76
  };
77
 
78
+ module.exports.bytesToSize = (bytes = 0, decimals = 2) => {
 
79
  if (0 === bytes) {
80
+ return '0 Bytes';
81
  }
82
+ const dm = decimals < 0 ? 0 : decimals, i = Math.round(Math.log(bytes) / Math.log(1024));
83
+ return `${(bytes / Math.pow(1024, i)).toFixed(dm)} ${[ 'Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB' ][i]}`;
84
  };
85
 
86
  module.exports.indexOfAny = (text, last = false) => {
package.json CHANGED
@@ -1,6 +1,6 @@
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": {
 
1
  {
2
  "name": "clewd",
3
+ "version": "4.7",
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": {