Files changed (16) hide show
  1. .gitattributes +40 -0
  2. .gitignore +0 -3
  3. .gitkeep +0 -0
  4. CHANGELOG.md +0 -4
  5. README.md +0 -1
  6. clewd.js +274 -317
  7. config.js +61 -0
  8. docker-compose.yml +4 -4
  9. lib/clewd-stream.js +11 -17
  10. lib/clewd-superfetch.js +3 -3
  11. lib/clewd-utils.js +78 -72
  12. package.json +3 -6
  13. start.bat +5 -0
  14. start.sh +12 -0
  15. update.bat +37 -0
  16. update.sh +20 -0
.gitattributes ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ *.7z filter=lfs diff=lfs merge=lfs -text
2
+ *.arrow filter=lfs diff=lfs merge=lfs -text
3
+ *.bin filter=lfs diff=lfs merge=lfs -text
4
+ *.bz2 filter=lfs diff=lfs merge=lfs -text
5
+ *.ckpt filter=lfs diff=lfs merge=lfs -text
6
+ *.ftz filter=lfs diff=lfs merge=lfs -text
7
+ *.gz filter=lfs diff=lfs merge=lfs -text
8
+ *.h5 filter=lfs diff=lfs merge=lfs -text
9
+ *.joblib filter=lfs diff=lfs merge=lfs -text
10
+ *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
+ *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
+ *.model filter=lfs diff=lfs merge=lfs -text
13
+ *.msgpack filter=lfs diff=lfs merge=lfs -text
14
+ *.npy filter=lfs diff=lfs merge=lfs -text
15
+ *.npz filter=lfs diff=lfs merge=lfs -text
16
+ *.onnx filter=lfs diff=lfs merge=lfs -text
17
+ *.ot filter=lfs diff=lfs merge=lfs -text
18
+ *.parquet filter=lfs diff=lfs merge=lfs -text
19
+ *.pb filter=lfs diff=lfs merge=lfs -text
20
+ *.pickle filter=lfs diff=lfs merge=lfs -text
21
+ *.pkl filter=lfs diff=lfs merge=lfs -text
22
+ *.pt filter=lfs diff=lfs merge=lfs -text
23
+ *.pth filter=lfs diff=lfs merge=lfs -text
24
+ *.rar filter=lfs diff=lfs merge=lfs -text
25
+ *.safetensors filter=lfs diff=lfs merge=lfs -text
26
+ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
+ *.tar.* filter=lfs diff=lfs merge=lfs -text
28
+ *.tar filter=lfs diff=lfs merge=lfs -text
29
+ *.tflite filter=lfs diff=lfs merge=lfs -text
30
+ *.tgz filter=lfs diff=lfs merge=lfs -text
31
+ *.wasm filter=lfs diff=lfs merge=lfs -text
32
+ *.xz filter=lfs diff=lfs merge=lfs -text
33
+ *.zip filter=lfs diff=lfs merge=lfs -text
34
+ *.zst filter=lfs diff=lfs merge=lfs -text
35
+ *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ lib/bin/clewd-superfetch-android-arm filter=lfs diff=lfs merge=lfs -text
37
+ lib/bin/clewd-superfetch-linux-amd64 filter=lfs diff=lfs merge=lfs -text
38
+ lib/bin/clewd-superfetch-linux-arm64 filter=lfs diff=lfs merge=lfs -text
39
+ lib/bin/clewd-superfetch-mac-amd64 filter=lfs diff=lfs merge=lfs -text
40
+ lib/bin/clewd-superfetch-win-amd64.exe filter=lfs diff=lfs merge=lfs -text
.gitignore CHANGED
@@ -13,9 +13,6 @@ yarn-error.log*
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
 
 
13
  cookies.json
14
  cookies.js
15
  cookies.ini
 
 
 
16
  config.js
17
  log.txt
18
 
.gitkeep ADDED
File without changes
CHANGELOG.md CHANGED
@@ -12,10 +12,6 @@
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
 
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
README.md CHANGED
@@ -5,7 +5,6 @@ colorFrom: blue
5
  colorTo: red
6
  sdk: docker
7
  pinned: false
8
- app_port: 8444
9
  ---
10
 
11
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
5
  colorTo: red
6
  sdk: docker
7
  pinned: false
 
8
  ---
9
 
10
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
clewd.js CHANGED
@@ -7,124 +7,132 @@
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, cookieModel, tokens, apiKey, timestamp;
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++;
26
- }, !Config.rProxy || Config.rProxy === AI.end() ? 15000 + timestamp - Date.now() : 0);
27
  });
28
 
29
- const asyncPool = async (poolLimit, array, iteratorFn) => {
30
- const ret = [], executing = [];
31
- for (const item of array) {
32
- const p = Promise.resolve().then(() => iteratorFn(item));
33
- ret.push(p);
34
- if (poolLimit <= array.length) {
35
- const e = p.then(() => executing.splice(executing.indexOf(e), 1));
36
- executing.push(e);
37
- if (executing.length >= poolLimit) await Promise.race(executing);
38
- }
39
- }
40
- return Promise.all(ret);
41
- }, convertToType = value => {
42
- if (value === 'true') return true;
43
- if (value === 'false') return false;
44
- if (/^\d+$/.test(value)) return parseInt(value);
45
- return value;
46
- }, CookieCleaner = () => {
47
- Config.CookieArray.splice(Config.CookieArray.indexOf(Config.Cookie), 1);
48
- Config.Cookie = '';
49
- writeSettings(Config);
50
- currentIndex = (currentIndex - 1 + Config.CookieArray.length) % Config.CookieArray.length;
51
- }, padtxt = content => {
52
- const {countTokens} = require('@anthropic-ai/tokenizer');
53
- const placeholder = Config.padtxt_placeholder || randomBytes(randomInt(5, 15)).toString('hex');
54
- tokens = countTokens(content);
55
- 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())));
56
- content = /<\|padtxt.*?\|>/.test(content) ? content.replace(/<\|padtxt.*?\|>/, padding).replace(/\s*<\|padtxt.*?\|>\s*/g, '\n\n') : !apiKey ? padding + '\n\n\n' + content.trim() : content;
57
- return content;
58
- }, xmlPlot_merge = (content, nonsys) => {
59
- if (!content.includes('<|Merge Disable|>')) {
60
- if (content.includes('<|System Role|>')) {
61
- 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')});
62
  }
63
- if (!content.includes('<|Merge Human Disable|>')) {
64
- 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:');
65
- content = content.replace(/(?:\n\n|^\s*)Human:(.*?(?:\n\nAssistant:|$))/gs, function(match, p1) {return '\n\nHuman:' + p1.replace(/\n\nHuman:\s*/g, '\n\n')});
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
  }
67
- if (!content.includes('<|Merge Assistant Disable|>')) {
68
  content = content.replace(/\n\nAssistant:(.*?(?:\n\nHuman:|$))/gs, function(match, p1) {return '\n\nAssistant:' + p1.replace(/\n\nAssistant:\s*/g, '\n\n')});
69
  }
70
  }
71
- return content.replace(/(\n\n|^\s*)xmlPlot:\s*/gm, '$1');
72
- }, xmlPlot_regex = (content, order) => {
73
- let match, regex = new RegExp(`<regex(?: +order *= *${order})${order === 2 ? '?' : ''}> *"(/?)(.*)\\1(.*?)" *: *"(.*?)" *</regex>`, 'gm');
74
- while ((match = regex.exec(content)) !== null) {
75
- try {
76
- content = content.replace(new RegExp(match[2], match[3]), match[4].replace(/(\r\n|\r|\\n)/gm, '\n'));
77
- } catch (err) {}
78
- }
79
- return content;
80
- }, xmlPlot = (content, nonsys = false) => {
81
- //一次正则
82
- content = xmlPlot_regex(content, 1);
83
- //一次role合并
84
- content = xmlPlot_merge(content, nonsys);
85
- //自定义插入
86
- content = content.replace(/(<\/?)PrevAssistant>/gm, '$1@1>').replace(/(<\/?)PrevHuman>/gm, '$1@2>');
87
- let splitContent = content.split(/\n\n(?=Assistant:|Human:)/g);
88
- let match;
89
- while ((match = /<@(\d+)>(.*?)<\/@\1>/gs.exec(content)) !== null) {
90
- let index = splitContent.length - parseInt(match[1]) - 1;
91
- if (index >= 0) {
92
- splitContent[index] += '\n\n' + match[2];
93
  }
94
- content = content.replace(match[0], '');
95
  }
96
- content = splitContent.join('\n\n');
97
- content = content.replace(/<@(\d+)>.*?<\/@\1>/gs, '');
98
- //二次正则
99
- content = xmlPlot_regex(content, 2);
100
- //二次role合并
101
- content = xmlPlot_merge(content, nonsys);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
102
  //Plain Prompt
103
- let segcontentHuman = content.split('\n\nHuman:');
104
  let segcontentlastIndex = segcontentHuman.length - 1;
105
- if (!apiKey && segcontentlastIndex >= 2 && segcontentHuman[segcontentlastIndex].includes('<|Plain Prompt Enable|>') && !content.includes('\n\nPlainPrompt:')) {
106
- content = segcontentHuman.slice(0, segcontentlastIndex).join('\n\nHuman:') + '\n\nPlainPrompt:' + segcontentHuman.slice(segcontentlastIndex).join('\n\nHuman:').replace(/\n\nHuman: *PlainPrompt:/, '\n\nPlainPrompt:');
107
- }
108
- //三次正则
109
- content = xmlPlot_regex(content, 3);
110
- //消除空XML tags、两端空白符和多余的\n
111
- content = content.replace(/<regex>.*?<\/regex>/gm, '')
112
- .replace(/(\r\n|\r|\\n)/gm, '\n')
113
- .replace(/\s*<\|curtail\|>\s*/g, '\n')
114
- .replace(/\n<\/(card|hidden|META)>\s+?<\1>\n/g, '\n')
115
- .replace(/\n<(\/?card|example|hidden|plot|META)>\s+?<\1>/g, '\n<$1>')
116
- .replace(/(?:<!--.*?-->\n|.+?: ?\n)?<(card|example|hidden|plot|META)>\s+?<\/\1>\n*/g, '')
117
- .replace(/(?<=(: |\n)<(card|hidden|example|plot|META|EOT)>\n)\s*/g, '')
118
- .replace(/\s*(?=\n<\/(card|hidden|example|plot|META|EOT)>(\n|$))/g, '')
119
- .replace(/(?<=\n)\n(?=\n)/g, '');
120
- //确保格式正确
121
- if (apiKey) {
122
- 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');
123
- 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: '}));
124
- return content.replace(Config.Settings.padtxt ? /\s*<\|(?!padtxt).*?\|>\s*/g : /\s*<\|.*?\|>\s*/g, '\n\n').trim().replace(/^.+:/, '\n\n$&').replace(/\n\n.+:$/, '$& ');
125
- } else {
126
- return content.replace(Config.Settings.padtxt ? /\s*<\|(?!padtxt).*?\|>\s*/g : /\s*<\|.*?\|>\s*/g, '\n\n').trim().replace(/^Human:|\n\nAssistant:$/g, '');
127
  }
 
 
 
 
 
 
 
 
 
 
 
 
128
  };
129
  /******************************************************* */
130
 
@@ -139,16 +147,14 @@ const ConfigPath = joinP(__dirname, './config.js'), LogPath = joinP(__dirname, '
139
  let uuidOrg, curPrompt = {}, prevPrompt = {}, prevMessages = [], prevImpersonated = false, Config = {
140
  Cookie: '',
141
  CookieArray: [],
142
- Cookiecounter: 3,
143
  CookieIndex: 0,
144
- ProxyPassword: '',
145
  Ip: (process.env.Cookie || process.env.CookieArray) ? '0.0.0.0' : '127.0.0.1',
146
  Port: process.env.PORT || 8444,
147
  localtunnel: false,
148
  BufferSize: 1,
149
  SystemInterval: 3,
150
- rProxy: '',
151
- api_rProxy: '',
152
  padtxt_placeholder: '',
153
  PromptExperimentFirst: '',
154
  PromptExperimentNext: '',
@@ -166,10 +172,10 @@ let uuidOrg, curPrompt = {}, prevPrompt = {}, prevMessages = [], prevImpersonate
166
  StripHuman: false,
167
  PassParams: false,
168
  ClearFlags: true,
169
- PreserveChats: false,
170
  LogMessages: true,
171
  FullColon: true,
172
- padtxt: 15000,
173
  xmlPlot: true,
174
  Superfetch: true
175
  }
@@ -216,21 +222,19 @@ const updateParams = res => {
216
  if (Config.Settings.PreserveChats) {
217
  return;
218
  }
219
- try { //
220
- const res = await fetch(`${Config.rProxy || AI.end()}/api/organizations/${uuidOrg}/chat_conversations/${uuid}`, {
221
- headers: {
222
- ...AI.hdr(),
223
- Cookie: getCookies()
224
- },
225
- method: 'DELETE'
226
- });
227
- updateParams(res);
228
- } catch (err) {console.log(`deleteChat failed`)}; //
229
  }, onListen = async () => {
230
  /***************************** */
231
  if (Firstlogin) {
232
- Firstlogin = false, timestamp = Date.now(), totaltime = Config.CookieArray.length;
233
- 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`);
234
  Config.Settings.Superfetch && SuperfetchAvailable(true);
235
  if (Config.localtunnel) {
236
  const localtunnel = require('localtunnel');
@@ -239,27 +243,26 @@ const updateParams = res => {
239
  console.log(`\nTunnel URL for outer websites: ${tunnel.url}/v1\n`);
240
  })
241
  }
 
242
  }
243
  if (Config.CookieArray?.length > 0) {
244
  Config.Cookie = Config.CookieArray[currentIndex];
245
  currentIndex = (currentIndex + 1) % Config.CookieArray.length;
246
- changetime++;
247
  }
248
- let percentage = ((changetime + Math.max(Config.CookieIndex - 1, 0)) / totaltime) * 100
249
  if (Config.Cookiecounter < 0 && percentage > 100) {
250
  console.log(`\n※※※Cookie cleanup completed※※※\n\n`);
251
  return process.exit();
252
  }
253
- try {
254
  /***************************** */
255
- 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) {
256
- changing = false; //
257
- return console.log(`No cookie available, apiKey-Only mode enabled.\n`); //throw Error('Set your cookie inside config.js');
258
  }
259
- updateCookies(Config.Cookie.replace(/^(sessionKey=)?/, 'sessionKey=')); //updateCookies(Config.Cookie);
260
  //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`);
261
  //Config.Settings.Superfetch && SuperfetchAvailable(true);
262
- const accRes = await fetch((Config.rProxy || AI.end()) + '/api/organizations', {
263
  method: 'GET',
264
  headers: {
265
  ...AI.hdr(),
@@ -268,10 +271,13 @@ const updateParams = res => {
268
  });
269
  /**************************** */
270
  if (accRes.statusText === 'Forbidden' && Config.CookieArray?.length > 0) {
271
- CookieCleaner();
 
 
272
  console.log(`Expired!`);
273
  Config.Cookiecounter < 0 && console.log(`[progress]: ${percentage.toFixed(2)}%\n[length]: ${Config.CookieArray.length}\n`);
274
- return CookieChanger.emit('ChangeCookie');
 
275
  }
276
  /**************************** */
277
  await checkResErr(accRes);
@@ -284,63 +290,41 @@ const updateParams = res => {
284
  }
285
  setTitle('ok');
286
  updateParams(accRes);
287
- /**************************** */
288
- const accountRes = await fetch((Config.rProxy || AI.end()) + '/api/auth/current_account', {
289
- method: 'GET',
290
- headers: {
291
- ...AI.hdr(),
292
- Cookie: getCookies()
293
- }
294
- });
295
- await checkResErr(accountRes);
296
- const accountInfo = await accountRes.json();
297
- model = accountInfo.account.statsig.values.dynamic_configs["6zA9wvTedwkzjLxWy9PVe7yydI00XDQ6L5Fejjq/2o8="]?.value?.model, cookieModel = model;
298
- /**************************** */
299
  console.log(Config.CookieArray?.length > 0 ? `(index: ${currentIndex || Config.CookieArray.length}) Logged in %o` : 'Logged in %o', { //console.log('Logged in %o', {
300
  name: accInfo.name?.split('@')?.[0],
301
- mail: accountInfo.account.email_address, //
302
- model, //
303
- capabilities: accInfo.capabilities
304
  });
305
  uuidOrg = accInfo?.uuid;
306
  /************************* */
307
- if (reqModel && reqModel != cookieModel && !Config.Settings.PassParams) return CookieChanger.emit('ChangeCookie');
308
- const Overlap = uuidOrgArray.includes(uuidOrg) && percentage <= 100 && Config.CookieArray?.length > 0;
309
- !Overlap && uuidOrgArray.push(uuidOrg);
310
- const Unverified = !accountInfo.account.completed_verification_at;
311
- 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';
312
- const Remain = accountInfo.messageLimit?.remaining;
313
- const Exceededlimit = (accountInfo.messageLimit?.type === 'approaching_limit' && Remain === 0) || accountInfo.messageLimit?.type === 'exceeded_limit';
314
- if (Remain) {
315
- changeflag = Math.max(Config.Cookiecounter - Remain, changeflag);
316
- console.log(`ApproachingLimit!: Remain ${Remain}`);
317
- }
318
- if ((Overlap || Unverified || Abused) && Config.CookieArray?.length > 0) {
319
- Overlap ? console.log(`Overlap!`) : Unverified ? console.log(`Unverified!`) : Abused && console.log(`Banned!`);
320
- CookieCleaner();
321
  Config.Cookiecounter < 0 && console.log(`[progress]: ${percentage.toFixed(2)}%\n[length]: ${Config.CookieArray.length}\n`);
322
- return CookieChanger.emit('ChangeCookie');
 
 
 
 
 
323
  }
324
  /************************* */
325
  if (accInfo?.active_flags.length > 0) {
326
- let flagtype; //
327
  const now = new Date, formattedFlags = accInfo.active_flags.map((flag => {
328
  const days = ((new Date(flag.expires_at).getTime() - now.getTime()) / 864e5).toFixed(2);
329
- flagtype = flag.type; //
330
  return {
331
  type: flag.type,
332
  remaining_days: days
333
  };
334
  }));
335
- console.warn(`${'consumer_banned' === flagtype ? '' : ''}Your account has warnings %o`, formattedFlags); //console.warn('Your account has warnings %o', formattedFlags);
336
  await Promise.all(accInfo.active_flags.map((flag => (async type => {
337
  if (!Config.Settings.ClearFlags) {
338
  return;
339
  }
340
- if ('consumer_restricted_mode' === type || 'consumer_banned' === type) { //if ('consumer_restricted_mode' === type) {
341
  return;
342
  }
343
- const req = await (Config.Settings.Superfetch ? Superfetch : fetch)(`${Config.rProxy || AI.end()}/api/organizations/${uuidOrg}/flags/${type}/dismiss`, {
344
  headers: {
345
  ...AI.hdr(),
346
  Cookie: getCookies()
@@ -352,19 +336,44 @@ const updateParams = res => {
352
  console.log(`${type}: ${json.error ? json.error.message || json.error.type || json.detail : 'OK'}`);
353
  })(flag.type))));
354
  /***************************** */
355
- if (Config.CookieArray?.length > 0) { //}
356
- console.log(`${'consumer_banned' === flagtype ? 'Banned' : 'Restricted'}!`);
357
- 'consumer_banned' === flagtype && CookieCleaner();
358
  Config.Cookiecounter < 0 && console.log(`[progress]: ${percentage.toFixed(2)}%\n[length]: ${Config.CookieArray.length}\n`);
359
- return CookieChanger.emit('ChangeCookie');
 
360
  }
361
  }
362
- if (Config.Cookiecounter < 0 || Exceededlimit) {
363
- console.log(Config.Cookiecounter < 0 ? `[progress]: ${percentage.toFixed(2)}%\n[length]: ${Config.CookieArray.length}\n` : 'Exceeded limit!\n');
364
- return CookieChanger.emit('ChangeCookie');
365
- } else changing = false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
366
  /***************************** */
367
- const convRes = await fetch(`${Config.rProxy || AI.end()}/api/organizations/${uuidOrg}/chat_conversations`, {
 
368
  method: 'GET',
369
  headers: {
370
  ...AI.hdr(),
@@ -372,16 +381,8 @@ const updateParams = res => {
372
  }
373
  }), conversations = await convRes.json();
374
  updateParams(convRes);
375
- conversations.length > 0 && await asyncPool(10, conversations, async (conv) => await deleteChat(conv.uuid)); //await Promise.all(conversations.map((conv => deleteChat(conv.uuid))));
376
- /***************************** */
377
- invalidtime = 0;
378
- } catch (err) {
379
- console.error('Clewd:\n%o', err);
380
- Config.CookieArray?.length > 0 && CookieChanger.emit('ChangeCookie');
381
- }
382
- /***************************** */
383
  }, writeSettings = async (config, firstRun = false) => {
384
- if (process.env.Cookie || process.env.CookieArray) return; //
385
  write(ConfigPath, `/*\n* https://rentry.org/teralomaniac_clewd\n* https://github.com/teralomaniac/clewd\n*/\n\n// SET YOUR COOKIE BELOW\n\nmodule.exports = ${JSON.stringify(config, null, 4)}\n\n/*\n BufferSize\n * How many characters will be buffered before the AI types once\n * lower = less chance of \`PreventImperson\` working properly\n\n ---\n\n SystemInterval\n * How many messages until \`SystemExperiments alternates\`\n\n ---\n\n Other settings\n * https://gitgud.io/ahsk/clewd/#defaults\n * and\n * https://gitgud.io/ahsk/clewd/-/blob/master/CHANGELOG.md\n */`.trim().replace(/((?<!\r)\n|\r(?!\n))/g, '\r\n'));
386
  if (firstRun) {
387
  console.warn('config file created!\nedit config.js to set your settings and restart the program');
@@ -400,26 +401,16 @@ const updateParams = res => {
400
  switch (req.url) {
401
  case '/v1/models':
402
  res.json({
403
- /***************************** */
404
- data: [ //data: AI.mdl().map((name => ({
405
- ...AI.mdl().slice(1).map((name => ({ id: name }))), {
406
- id: 'claude-2' },{
407
- id: 'claude-v1.3' },{
408
- id: 'claude-v1.3-100k' },{
409
- id: 'claude-v1.2' },{
410
- id: 'claude-v1.0' },{
411
- id: 'claude-instant-v1.1' },{
412
- id: 'claude-instant-v1.1-100k' },{
413
- id: 'claude-instant-v1.0' //id: name
414
- }] //})))
415
- /***************************** */
416
  });
417
  break;
418
 
419
  case '/v1/chat/completions':
420
  ((req, res) => {
421
  setTitle('recv...');
422
- let fetchAPI;
423
  const abortControl = new AbortController, {signal} = abortControl;
424
  res.socket.on('close', (async () => {
425
  abortControl.signal.aborted || abortControl.abort();
@@ -431,25 +422,8 @@ const updateParams = res => {
431
  req.on('end', (async () => {
432
  let clewdStream, titleTimer, samePrompt = false, shouldRenew = true, retryRegen = false;
433
  try {
434
- const body = JSON.parse(Buffer.concat(buffer).toString());
435
- let {temperature} = body;
436
- temperature = Math.max(.1, Math.min(1, temperature));
437
  let {messages} = body;
438
- /************************* */
439
- apiKey = req.headers.authorization?.match(/sk-ant-api\d\d-[\w-]{86}-[\w-]{6}AA/g) || req.headers.authorization?.match(/(?<=3rdKey: *)[\S]*/);
440
- reqModel = /^claude-2.[01]$/.test(body.model) ? body.model : '';
441
- let max_tokens_to_sample, stop_sequences;
442
- if (apiKey || Config.Settings.PassParams) {
443
- stop_sequences = body.stop;
444
- max_tokens_to_sample = body.max_tokens;
445
- model = body.model;
446
- } else if (req.headers.authorization.includes('sk-ant-api') || Config.ProxyPassword != '' && req.headers.authorization != 'Bearer ' + Config.ProxyPassword) {
447
- throw Error(req.headers.authorization.includes('sk-ant-api') ? 'apiKey Wrong' : 'ProxyPassword Wrong');
448
- } else if (changing || Config.CookieArray?.length > 0 && invalidtime >= Config.CookieArray?.length || reqModel && reqModel != cookieModel && !Config.Settings.PassParams) {
449
- changing ? invalidtime = 0 : changeflag = -1;
450
- throw Error(reqModel && reqModel != cookieModel && !Config.Settings.PassParams ? 'Polling requset model...' : 'Changing Cookie...');
451
- }
452
- /************************* */
453
  if (messages?.length < 1) {
454
  throw Error('Select OpenAI as completion source');
455
  }
@@ -480,13 +454,7 @@ const updateParams = res => {
480
  console.log('having AllSamples and NoSamples both set to true is not supported');
481
  throw Error('Only one can be used at the same time: AllSamples/NoSamples');
482
  }
483
- //const model = body.model;
484
- //if (model === AI.mdl()[0]) {
485
- // return;
486
- //}
487
- if (!/claude-.*/.test(model)) {
488
- throw Error('Invalid model selected: ' + model);
489
- }
490
  curPrompt = {
491
  firstUser: messages.find((message => 'user' === message.role)),
492
  firstSystem: messages.find((message => 'system' === message.role)),
@@ -511,7 +479,7 @@ const updateParams = res => {
511
  retryRegen = Config.Settings.RetryRegenerate && samePrompt && null != Conversation.uuid;
512
  samePrompt || (prevMessages = JSON.parse(JSON.stringify(messages)));
513
  let type = '';
514
- if (apiKey) { type = 'api'; } else if (retryRegen) { //if (retryRegen) {
515
  type = 'R';
516
  fetchAPI = await (async (signal, model) => {
517
  let res;
@@ -519,7 +487,7 @@ const updateParams = res => {
519
  completion: {
520
  prompt: '',
521
  timezone: AI.zone(),
522
- model
523
  },
524
  organization_uuid: uuidOrg,
525
  conversation_uuid: Conversation.uuid,
@@ -534,7 +502,7 @@ const updateParams = res => {
534
  const names = Object.keys(headers), values = Object.values(headers);
535
  headers = names.map(((header, idx) => `${header}: ${values[idx]}`));
536
  }
537
- res = await (Config.Settings.Superfetch ? Superfetch : fetch)((Config.rProxy || AI.end()) + '/api/retry_message', {
538
  stream: true,
539
  signal,
540
  method: 'POST',
@@ -550,7 +518,7 @@ const updateParams = res => {
550
  fetchAPI = await (async signal => {
551
  Conversation.uuid = randomUUID().toString();
552
  Conversation.depth = 0;
553
- const res = await (Config.Settings.Superfetch ? Superfetch : fetch)(`${Config.rProxy || AI.end()}/api/organizations/${uuidOrg}/chat_conversations`, {
554
  signal,
555
  headers: {
556
  ...AI.hdr(),
@@ -585,16 +553,16 @@ const updateParams = res => {
585
  if (next && !Config.Settings.xmlPlot) { //if (next) {
586
  if ('name' in message && 'name' in next) {
587
  if (message.name === next.name) {
588
- message.content += '\n' + next.content;
589
  next.merged = true;
590
  }
591
  } else if ('system' !== next.role) {
592
  if (next.role === message.role) {
593
- message.content += '\n' + next.content;
594
  next.merged = true;
595
  }
596
  } else {
597
- message.content += '\n' + next.content;
598
  next.merged = true;
599
  }
600
  }
@@ -642,7 +610,7 @@ const updateParams = res => {
642
  message.customname || delete message.name;
643
  }));
644
  let systems = [];
645
- if (![ 'r', 'R', 'api' ].includes(type)) {
646
  lastUser.strip = true;
647
  systemMessages.forEach((message => message.discard = message.discard || 'c-c' === type ? !message.jailbreak : !message.jailbreak && !message.main));
648
  systems = systemMessages.filter((message => !message.discard)).map((message => `"${message.content.substring(0, 25).replace(/\n/g, '\\n').trim()}..."`));
@@ -656,61 +624,38 @@ const updateParams = res => {
656
  return message.content;
657
  }
658
  let spacing = '';
659
- /******************************** */
660
  if (Config.Settings.xmlPlot) {
661
  idx > 0 && (spacing = '\n\n');
662
- const prefix = message.customname ? message.role + ': ' + message.name + ': ' : 'system' !== message.role || message.name ? Replacements[message.name || message.role] + ': ' : 'xmlPlot: ' + Replacements[message.role];
663
- return `${spacing}${message.strip ? '' : prefix}${message.content}`;
664
  } else {
665
- /******************************** */
666
  idx > 0 && (spacing = systemMessages.includes(message) ? '\n' : '\n\n');
667
  const prefix = message.customname ? message.name + ': ' : 'system' !== message.role || message.name ? Replacements[message.name || message.role] + ': ' : '' + Replacements[message.role];
668
  return `${spacing}${message.strip ? '' : prefix}${'system' === message.role ? message.content : message.content.trim()}`;
669
  } //
670
  }));
671
  return {
672
- prompt: prompt.join(''), //genericFixes(prompt.join('')).trim(),
673
  systems
674
  };
675
  })(messages, type);
676
- console.log(`${model} [${type}]${!retryRegen && systems.length > 0 ? ' ' + systems.join(' / ') : ''}`); //console.log(`${model} [${type}]${!retryRegen && systems.length > 0 ? ' ' + systems.join(' / ') : ''}`);
677
  'R' !== type || prompt || (prompt = '...regen...');
678
- /******************************** */
679
- prompt = Config.Settings.xmlPlot ? xmlPlot(prompt, model != 'claude-2.1') : apiKey ? `\n\nHuman: ${genericFixes(prompt)}\n\nAssistant: ` : genericFixes(prompt).trim();
680
- Config.Settings.FullColon && (prompt = apiKey
681
- ? prompt.replace(/(?<!\n\nHuman:.*)(\n\nAssistant):/gs, '$1:').replace(/(\n\nHuman):(?!.*\n\nAssistant:)/gs, '$1:')
682
- : prompt.replace(/(?<=\n\n(H(?:uman)?|A(?:ssistant)?)):[ ]?/g, ': '));
683
  Config.Settings.padtxt && (prompt = padtxt(prompt));
684
- /******************************** */
685
- 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`);
686
  retryRegen || (fetchAPI = await (async (signal, model, prompt, temperature, type) => {
687
- /******************************** */
688
- if (apiKey) {
689
- const res = await fetch(`${Config.api_rProxy ? Config.api_rProxy : 'https://api.anthropic.com'}/v1/complete`, {
690
- method: 'POST',
691
- signal,
692
- headers: {
693
- 'Content-Type': 'application/json',
694
- 'x-api-key': apiKey[Math.floor(Math.random() * apiKey.length)],
695
- 'anthropic-version': '2023-06-01'
696
- },
697
- body: JSON.stringify({
698
- ...stop_sequences && {stop_sequences},
699
- model,
700
- max_tokens_to_sample,
701
- stream: true,
702
- prompt,
703
- temperature
704
- }),
705
- });
706
- await checkResErr(res);
707
- return res;
708
- }
709
- /******************************** */
710
  const attachments = [];
711
  if (Config.Settings.PromptExperiments) {
712
- let splitedprompt = prompt.split('\n\nPlainPrompt:'); //
713
- prompt = splitedprompt[0]; //
 
 
714
  attachments.push({
715
  extracted_content: (prompt),
716
  file_name: 'paste.txt', //fileName(),
@@ -718,7 +663,9 @@ const updateParams = res => {
718
  file_type: 'txt' //'text/plain'
719
  });
720
  prompt = 'r' === type ? Config.PromptExperimentFirst : Config.PromptExperimentNext;
721
- splitedprompt.length > 1 && (prompt += splitedprompt[1]); //
 
 
722
  }
723
  let res;
724
  const body = {
@@ -728,11 +675,11 @@ const updateParams = res => {
728
  },
729
  prompt: prompt || '',
730
  timezone: AI.zone(),
731
- model
732
  },
733
- conversation_uuid: Conversation.uuid,
734
  organization_uuid: uuidOrg,
735
- text: prompt || '',
 
736
  attachments
737
  };
738
  let headers = {
@@ -740,7 +687,7 @@ const updateParams = res => {
740
  Accept: 'text/event-stream',
741
  Cookie: getCookies()
742
  };
743
- res = await (Config.Settings.Superfetch ? Superfetch : fetch)((Config.rProxy || AI.end()) + '/api/append_message', {
744
  stream: true,
745
  signal,
746
  method: 'POST',
@@ -748,32 +695,25 @@ const updateParams = res => {
748
  headers
749
  });
750
  updateParams(res);
751
- await checkResErr(res, CookieChanger); //await checkResErr(res);
752
  return res;
753
  })(signal, model, prompt, temperature, type));
754
  const response = Writable.toWeb(res);
755
  clewdStream = new ClewdStream({
756
- config: {
757
- ...Config,
758
- Settings: {
759
- ...Config.Settings,
760
- Superfetch: apiKey ? false : Config.Settings.Superfetch
761
- }
762
- }, //config: Config,
763
  version: Main,
764
  minSize: Config.BufferSize,
765
  model,
766
- streaming: true === body.stream,
767
  abortControl,
768
  source: fetchAPI
769
  }, Logger);
770
  titleTimer = setInterval((() => setTitle('recv ' + bytesToSize(clewdStream.size))), 300);
771
- (!apiKey && Config.Settings.Superfetch) ? await Readable.toWeb(fetchAPI.body).pipeThrough(clewdStream).pipeTo(response) : await fetchAPI.body.pipeThrough(clewdStream).pipeTo(response); //Config.Settings.Superfetch ? await Readable.toWeb(fetchAPI.body).pipeThrough(clewdStream).pipeTo(response) : await fetchAPI.body.pipeThrough(clewdStream).pipeTo(response);
772
  } catch (err) {
773
  if ('AbortError' === err.name) {
774
  res.end();
775
  } else {
776
- changeflag -= 1; //
777
  err.planned || console.error('Clewd:\n%o', err);
778
  res.json({
779
  error: {
@@ -782,27 +722,33 @@ const updateParams = res => {
782
  param: null,
783
  code: err.code || 500
784
  }
785
- }, 500);
786
  }
787
  }
788
- clearInterval(titleTimer);
789
  if (clewdStream) {
790
  clewdStream.censored && console.warn('likely your account is hard-censored');
791
- clewdStream.nochange && changeflag--; //prevImpersonated = clewdStream.impersonated;
792
  setTitle('ok ' + bytesToSize(clewdStream.size));
793
- 429 == fetchAPI?.status ? console.log(`Exceeded limit!\n`) : console.log(`${200 == fetchAPI?.status ? '' : ''}${fetchAPI?.status}!\n`); //console.log(`${200 == fetchAPI.status ? '' : ''}${fetchAPI.status}!\n`);
794
- clewdStream.empty();
795
- }
796
- if (!apiKey) { //if (prevImpersonated) { try {
797
- await deleteChat(Conversation.uuid); //} catch (err) {}
798
- /******************************** */
799
- changeflag++;
800
- if (changeflag < 0 || Config.CookieArray?.length > 0 && (429 == fetchAPI?.status || Config.Cookiecounter > 0 && changeflag >= Config.Cookiecounter)) {
801
  changeflag = 0;
802
- CookieChanger.emit('ChangeCookie');
803
  }
804
  /******************************** */
 
 
 
 
 
 
805
  }
 
 
 
806
  }));
807
  })(req, res);
808
  break;
@@ -810,26 +756,21 @@ const updateParams = res => {
810
  case '/v1/complete':
811
  res.json({
812
  error: {
813
- message: 'clewd: Set "Chat Completion source" to OpenAI instead of Claude. Enable "External" models aswell',
814
- code: 404
815
  }
816
- }, 404);
817
  break;
818
 
819
  default:
820
- !['/', '/v1', '/favicon.ico'].includes(req.url) && (console.log('unknown request: ' + req.url)); //console.log('unknown request: ' + req.url);
821
- res.writeHead(200, {'Content-Type': 'text/html'});
822
- 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)">Copy Link</a><br/>填入OpenAI API反向代理并选择OpenAI分类中的claude模型(酒馆需打开Show "External" models,仅在api模式有模型选择差异)<br/><br/>教程与FAQ: <a href="https://rentry.org/teralomaniac_clewd" target="FAQ">Rentry</a> | <a href="https://discord.com/invite/B7Wr25Z7BZ" target="FAQ">Discord</a><br/><br/><br/>请举报恶意盗用/商用本教程及Clewd修改版的这个B 站up<a href="https://space.bilibili.com/35307060" target="FAQ">浅睡一天一夜</a>\n</body>\n</html>`);
823
- res.end();
824
- /*res.json(
825
- {
826
  error: {
827
  message: '404 Not Found',
828
  type: 404,
829
  param: null,
830
  code: 404
831
  }
832
- }, 404);*/
833
  }
834
  }));
835
 
@@ -864,21 +805,37 @@ const updateParams = res => {
864
  Config.Cookie = 'SET YOUR COOKIE HERE';
865
  writeSettings(Config, true);
866
  }
867
- })();
868
  /***************************** */
869
- for (let key in Config) {
870
- if (key === 'Settings') {
871
- for (let setting in Config.Settings) {
872
- Config.Settings[setting] = process.env[setting] ? convertToType(process.env[setting]) : Config.Settings[setting];
 
 
 
 
 
 
 
 
 
873
  }
874
- } else {
875
- Config[key] = process.env[key] ? convertToType(process.env[key]) : Config[key];
 
 
 
 
 
 
 
 
 
876
  }
877
  }
878
- Config.rProxy = Config.rProxy.replace(/\/$/, '');
879
- Config.CookieArray = [...new Set([Config.CookieArray].join('').match(/(sessionKey=)?sk-ant-sid01-[\w-]{86}-[\w-]{6}AA/g))];
880
- writeSettings(Config);
881
- currentIndex = Config.CookieIndex > 0 ? Config.CookieIndex - 1 : Config.Cookiecounter >= 0 ? Math.floor(Math.random() * Config.CookieArray.length) : 0;
882
  /***************************** */
883
  Proxy.listen(Config.Port, Config.Ip, onListen);
884
  Proxy.on('error', (err => {
@@ -903,4 +860,4 @@ process.on('SIGINT', cleanup);
903
 
904
  process.on('exit', (async () => {
905
  console.log('exiting...');
906
- }));
 
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);
19
+ Proxy.on('error', (err => {
20
+ console.error('Proxy error\n%o', err);
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
  /******************************************************* */
138
 
 
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,
155
  BufferSize: 1,
156
  SystemInterval: 3,
157
+ rProxy: AI.end(),
 
158
  padtxt_placeholder: '',
159
  PromptExperimentFirst: '',
160
  PromptExperimentNext: '',
 
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
  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) {
236
+ Firstlogin = false;
237
+ 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`);
238
  Config.Settings.Superfetch && SuperfetchAvailable(true);
239
  if (Config.localtunnel) {
240
  const localtunnel = require('localtunnel');
 
243
  console.log(`\nTunnel URL for outer websites: ${tunnel.url}/v1\n`);
244
  })
245
  }
246
+ totaltime = Config.CookieArray.length;
247
  }
248
  if (Config.CookieArray?.length > 0) {
249
  Config.Cookie = Config.CookieArray[currentIndex];
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();
257
  }
 
258
  /***************************** */
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);
265
+ const accRes = await fetch(Config.rProxy + '/api/organizations', {
266
  method: 'GET',
267
  headers: {
268
  ...AI.hdr(),
 
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');
280
+ return;
281
  }
282
  /**************************** */
283
  await checkResErr(accRes);
 
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`, {
328
  headers: {
329
  ...AI.hdr(),
330
  Cookie: getCookies()
 
336
  console.log(`${type}: ${json.error ? json.error.message || json.error.type || json.detail : 'OK'}`);
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`, {
377
  method: 'GET',
378
  headers: {
379
  ...AI.hdr(),
 
381
  }
382
  }), conversations = await convRes.json();
383
  updateParams(convRes);
384
+ conversations.length > 0 && await Promise.all(conversations.map((conv => deleteChat(conv.uuid))));
 
 
 
 
 
 
 
385
  }, writeSettings = async (config, firstRun = false) => {
 
386
  write(ConfigPath, `/*\n* https://rentry.org/teralomaniac_clewd\n* https://github.com/teralomaniac/clewd\n*/\n\n// SET YOUR COOKIE BELOW\n\nmodule.exports = ${JSON.stringify(config, null, 4)}\n\n/*\n BufferSize\n * How many characters will be buffered before the AI types once\n * lower = less chance of \`PreventImperson\` working properly\n\n ---\n\n SystemInterval\n * How many messages until \`SystemExperiments alternates\`\n\n ---\n\n Other settings\n * https://gitgud.io/ahsk/clewd/#defaults\n * and\n * https://gitgud.io/ahsk/clewd/-/blob/master/CHANGELOG.md\n */`.trim().replace(/((?<!\r)\n|\r(?!\n))/g, '\r\n'));
387
  if (firstRun) {
388
  console.warn('config file created!\nedit config.js to set your settings and restart the program');
 
401
  switch (req.url) {
402
  case '/v1/models':
403
  res.json({
404
+ data: [ {
405
+ id: AI.mdl()
406
+ } ]
 
 
 
 
 
 
 
 
 
 
407
  });
408
  break;
409
 
410
  case '/v1/chat/completions':
411
  ((req, res) => {
412
  setTitle('recv...');
413
+ let fetchAPI, changer; //let fetchAPI;
414
  const abortControl = new AbortController, {signal} = abortControl;
415
  res.socket.on('close', (async () => {
416
  abortControl.signal.aborted || abortControl.abort();
 
422
  req.on('end', (async () => {
423
  let clewdStream, titleTimer, samePrompt = false, shouldRenew = true, retryRegen = false;
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
  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)),
 
479
  retryRegen = Config.Settings.RetryRegenerate && samePrompt && null != Conversation.uuid;
480
  samePrompt || (prevMessages = JSON.parse(JSON.stringify(messages)));
481
  let type = '';
482
+ if (retryRegen) {
483
  type = 'R';
484
  fetchAPI = await (async (signal, model) => {
485
  let res;
 
487
  completion: {
488
  prompt: '',
489
  timezone: AI.zone(),
490
+ model: model || AI.mdl()
491
  },
492
  organization_uuid: uuidOrg,
493
  conversation_uuid: Conversation.uuid,
 
502
  const names = Object.keys(headers), values = Object.values(headers);
503
  headers = names.map(((header, idx) => `${header}: ${values[idx]}`));
504
  }
505
+ res = await (Config.Settings.Superfetch ? Superfetch : fetch)(Config.rProxy + '/api/retry_message', {
506
  stream: true,
507
  signal,
508
  method: 'POST',
 
518
  fetchAPI = await (async signal => {
519
  Conversation.uuid = randomUUID().toString();
520
  Conversation.depth = 0;
521
+ const res = await (Config.Settings.Superfetch ? Superfetch : fetch)(`${Config.rProxy}/api/organizations/${uuidOrg}/chat_conversations`, {
522
  signal,
523
  headers: {
524
  ...AI.hdr(),
 
553
  if (next && !Config.Settings.xmlPlot) { //if (next) {
554
  if ('name' in message && 'name' in next) {
555
  if (message.name === next.name) {
556
+ message.content += '\n\n' + next.content; //message.content += '\n' + next.content;
557
  next.merged = true;
558
  }
559
  } else if ('system' !== next.role) {
560
  if (next.role === message.role) {
561
+ message.content += '\n\n' + next.content; //message.content += '\n' + next.content;
562
  next.merged = true;
563
  }
564
  } else {
565
+ message.content += '\n\n' + next.content; //message.content += '\n' + next.content;
566
  next.merged = true;
567
  }
568
  }
 
610
  message.customname || delete message.name;
611
  }));
612
  let systems = [];
613
+ if (![ 'r', 'R' ].includes(type)) {
614
  lastUser.strip = true;
615
  systemMessages.forEach((message => message.discard = message.discard || 'c-c' === type ? !message.jailbreak : !message.jailbreak && !message.main));
616
  systems = systemMessages.filter((message => !message.discard)).map((message => `"${message.content.substring(0, 25).replace(/\n/g, '\\n').trim()}..."`));
 
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
  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 = {
 
675
  },
676
  prompt: prompt || '',
677
  timezone: AI.zone(),
678
+ model: model || AI.mdl()
679
  },
 
680
  organization_uuid: uuidOrg,
681
+ conversation_uuid: Conversation.uuid,
682
+ text: prompt,
683
  attachments
684
  };
685
  let headers = {
 
687
  Accept: 'text/event-stream',
688
  Cookie: getCookies()
689
  };
690
+ res = await (Config.Settings.Superfetch ? Superfetch : fetch)(Config.rProxy + '/api/append_message', {
691
  stream: true,
692
  signal,
693
  method: 'POST',
 
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);
702
  clewdStream = new ClewdStream({
703
+ config: Config,
 
 
 
 
 
 
704
  version: Main,
705
  minSize: Config.BufferSize,
706
  model,
707
+ streaming: body.stream,
708
  abortControl,
709
  source: fetchAPI
710
  }, Logger);
711
  titleTimer = setInterval((() => setTitle('recv ' + bytesToSize(clewdStream.size))), 300);
712
+ Config.Settings.Superfetch ? await Readable.toWeb(fetchAPI.body).pipeThrough(clewdStream).pipeTo(response) : await fetchAPI.body.pipeThrough(clewdStream).pipeTo(response);
713
  } catch (err) {
714
  if ('AbortError' === err.name) {
715
  res.end();
716
  } else {
 
717
  err.planned || console.error('Clewd:\n%o', err);
718
  res.json({
719
  error: {
 
722
  param: null,
723
  code: err.code || 500
724
  }
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;
739
+ changer = true;
740
  }
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
  }));
753
  })(req, res);
754
  break;
 
756
  case '/v1/complete':
757
  res.json({
758
  error: {
759
+ message: 'clewd: Set "Chat Completion" to OpenAI instead of Claude. Enable "External" models aswell'
 
760
  }
761
+ });
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
 
 
805
  Config.Cookie = 'SET YOUR COOKIE HERE';
806
  writeSettings(Config, true);
807
  }
 
808
  /***************************** */
809
+ function convertToType(value) {
810
+ if (value === "true") return true;
811
+ if (value === "false") return false;
812
+ if (/^\d+$/.test(value)) return parseInt(value);
813
+ return value;
814
+ }
815
+ for (let key in Config) {
816
+ if (key === 'Settings') {
817
+ for (let setting in Config.Settings) {
818
+ Config.Settings[setting] = convertToType(process.env[setting]) ?? Config.Settings[setting];
819
+ }
820
+ } else {
821
+ Config[key] = key === 'CookieArray' ? (process.env[key]?.split(',')?.map(x => x.replace(/[\[\]"\s]/g, '')) ?? Config[key]) : (convertToType(process.env[key]) ?? Config[key]);
822
  }
823
+ }
824
+ /***************************** */
825
+ })();
826
+ /***************************** */
827
+ !Config.rProxy && (Config.rProxy = AI.end());
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);
834
  }
835
  }
836
+ Config.CookieArray = uniqueArr;
837
+ !process.env.Cookie && !process.env.CookieArray && writeSettings(Config);
838
+ currentIndex = Config.CookieIndex > 0 ? Config.CookieIndex - 1 : Config.Cookiecounter >= 0 ? Math.floor(Math.random()*Config.CookieArray.length) : 0;
 
839
  /***************************** */
840
  Proxy.listen(Config.Port, Config.Ip, onListen);
841
  Proxy.on('error', (err => {
 
860
 
861
  process.on('exit', (async () => {
862
  console.log('exiting...');
863
+ }));
config.js ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * https://rentry.org/teralomaniac_clewd
3
+ * https://github.com/teralomaniac/clewd
4
+ */
5
+
6
+ // SET YOUR COOKIE BELOW
7
+
8
+ module.exports = {
9
+ "Cookie": "",
10
+ "CookieArray": [],
11
+ "Cookiecounter": 0,
12
+ "CookieIndex": 0,
13
+ "Ip": "0.0.0.0",
14
+ "Port": 7860,
15
+ "localtunnel": false,
16
+ "BufferSize": 1,
17
+ "SystemInterval": 3,
18
+ "rProxy": "https://claude.ai",
19
+ "padtxt_placeholder": "",
20
+ "PromptExperimentFirst": "",
21
+ "PromptExperimentNext": "",
22
+ "PersonalityFormat": "{{char}}'s personality: {{personality}}",
23
+ "ScenarioFormat": "Dialogue scenario: {{scenario}}",
24
+ "Settings": {
25
+ "RenewAlways": true,
26
+ "RetryRegenerate": false,
27
+ "PromptExperiments": true,
28
+ "SystemExperiments": true,
29
+ "PreventImperson": false,
30
+ "AllSamples": false,
31
+ "NoSamples": false,
32
+ "StripAssistant": false,
33
+ "StripHuman": false,
34
+ "PassParams": false,
35
+ "ClearFlags": true,
36
+ "PreserveChats": true,
37
+ "LogMessages": true,
38
+ "FullColon": true,
39
+ "padtxt": 13500,
40
+ "xmlPlot": true,
41
+ "Superfetch": true
42
+ }
43
+ }
44
+
45
+ /*
46
+ BufferSize
47
+ * How many characters will be buffered before the AI types once
48
+ * lower = less chance of `PreventImperson` working properly
49
+
50
+ ---
51
+
52
+ SystemInterval
53
+ * How many messages until `SystemExperiments alternates`
54
+
55
+ ---
56
+
57
+ Other settings
58
+ * https://gitgud.io/ahsk/clewd/#defaults
59
+ * and
60
+ * https://gitgud.io/ahsk/clewd/-/blob/master/CHANGELOG.md
61
+ */
docker-compose.yml CHANGED
@@ -2,10 +2,10 @@ version: '3'
2
  services:
3
  app:
4
  build:
5
- context: .
6
- dockerfile: Dockerfile
7
 
8
  ports:
9
- - 8444:8444
10
  volumes:
11
- - .:/app
 
2
  services:
3
  app:
4
  build:
5
+ context: ..
6
+ dockerfile: docker/Dockerfile
7
 
8
  ports:
9
+ - 7860:7860
10
  volumes:
11
+ - ..:/app
lib/clewd-stream.js CHANGED
@@ -1,6 +1,6 @@
1
  /*
2
- * https://rentry.org/teralomaniac_clewd
3
- * https://github.com/teralomaniac/clewd
4
  */
5
  'use strict';
6
 
@@ -19,8 +19,8 @@ class ClewdStream extends TransformStream {
19
  this.#logger = logger;
20
  this.#version = opts.version;
21
  this.#config = opts.config;
22
- this.#model = opts.model;
23
- this.#streaming = opts.streaming;
24
  this.#minSize = opts.minSize || 8;
25
  this.#abortControl = opts.abortControl;
26
  this.#source = opts.source;
@@ -42,7 +42,8 @@ class ClewdStream extends TransformStream {
42
  #stopReason=void 0;
43
  #hardCensor=false;
44
  #impersonated=false;
45
- #nochange=false; //
 
46
  get size() {
47
  return this.#recvLength;
48
  }
@@ -54,12 +55,7 @@ class ClewdStream extends TransformStream {
54
  }
55
  get impersonated() {
56
  return this.#impersonated;
57
- }
58
- /************************ */
59
- get nochange() {
60
- return this.#nochange;
61
- }
62
- /************************ */
63
  empty() {
64
  this.#compOK = this.#compRaw = '';
65
  this.#compAll = [];
@@ -72,8 +68,7 @@ class ClewdStream extends TransformStream {
72
  }
73
  #err(err, controller) {
74
  this.#logger?.write(JSON.stringify(err, null, 4));
75
- 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`;
76
- this.#nochange = true; //
77
  this.#enqueue(this.#build(message), controller);
78
  return this.#endEarly(controller);
79
  }
@@ -103,8 +98,7 @@ class ClewdStream extends TransformStream {
103
  this.#streaming ? this.#compOK.length > 0 && this.#enqueue(this.#build(this.#compOK), controller) : this.#enqueue(this.#build(this.#compAll.join('')), controller);
104
  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);
105
  if (!this.#ended && 0 === this.total) {
106
- const err = `## ${this.#version}\n**error**:\n\n\`\`\`Received no valid replies at all\`\`\`\n\nFAQ: https://rentry.org/teralomaniac_clewd`;
107
- this.#nochange = true; //
108
  this.#enqueue(this.#build(err), controller);
109
  }
110
  this.#streaming && this.#enqueue('data: [DONE]\n\n', controller);
@@ -139,7 +133,7 @@ class ClewdStream extends TransformStream {
139
  } else {
140
  this.#recvLength += Buffer.byteLength(chunk);
141
  }
142
- this.#compRaw += chunk.replace(/event: (completion|ping)\s*|\r/gi,''); //this.#compRaw += chunk;
143
  const substr = this.#compRaw.split('\n\n'), lastMsg = substr.length - 1;
144
  0 !== substr[lastMsg].length ? this.#compRaw = substr[lastMsg] : this.#compRaw = '';
145
  for (let i = 0; i < lastMsg; i++) {
@@ -163,7 +157,7 @@ class ClewdStream extends TransformStream {
163
  },
164
  status: this.#source.status,
165
  superfetch: this.#source.superfetch
166
- }), false, false); //}), false);
167
  delete err.stack;
168
  return this.#err(err, controller);
169
  }
 
1
  /*
2
+ * https://gitgud.io/ahsk/clewd
3
+ * https://github.com/h-a-s-k/clewd
4
  */
5
  'use strict';
6
 
 
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;
26
  this.#source = opts.source;
 
42
  #stopReason=void 0;
43
  #hardCensor=false;
44
  #impersonated=false;
45
+ #cookiechange=false;
46
+ #readonly=false;
47
  get size() {
48
  return this.#recvLength;
49
  }
 
55
  }
56
  get impersonated() {
57
  return this.#impersonated;
58
+ }
 
 
 
 
 
59
  empty() {
60
  this.#compOK = this.#compRaw = '';
61
  this.#compAll = [];
 
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
  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);
 
133
  } else {
134
  this.#recvLength += Buffer.byteLength(chunk);
135
  }
136
+ this.#compRaw += chunk;
137
  const substr = this.#compRaw.split('\n\n'), lastMsg = substr.length - 1;
138
  0 !== substr[lastMsg].length ? this.#compRaw = substr[lastMsg] : this.#compRaw = '';
139
  for (let i = 0; i < lastMsg; i++) {
 
157
  },
158
  status: this.#source.status,
159
  superfetch: this.#source.superfetch
160
+ }), false);
161
  delete err.stack;
162
  return this.#err(err, controller);
163
  }
lib/clewd-superfetch.js CHANGED
@@ -1,4 +1,4 @@
1
  /*
2
- * https://rentry.org/teralomaniac_clewd
3
- * https://github.com/teralomaniac/clewd
4
- */"use strict";const{spawn:e}=require("node:child_process"),{relative:r,resolve:t,join:s,normalize:n,basename:o}=require("node:path"),{writeFileSync:a,unlinkSync:d,existsSync:i}=require("node:fs"),{ReadableStream:c}=require("node:stream/web"),m=e=>"win32"===process.platform?".\\"+e:e,l=e=>"win32"===process.platform||e.indexOf(" ")>-1?`"${e}"`:e,u={win32:{x64:"clewd-superfetch-win-amd64.exe"},darwin:{x64:"clewd-superfetch-mac-amd64",arm64:"clewd-superfetch-linux-arm64"},linux:{x64:"clewd-superfetch-linux-amd64",arm64:"clewd-superfetch-linux-arm64"},android:{x64:"clewd-superfetch-linux-amd64",arm64:"clewd-superfetch-linux-arm64",arm:"clewd-superfetch-android-arm"}}[process.platform]?.[process.arch],f=""+n(r("./","./bin/"+u)),p=n(t(__dirname,f,"../","../")),h=t(p,f),b=[123,34,115,101,99,45,99,104,45,117,97,34,58,34,92,34,67,104,114,111,109,105,117,109,92,34,59,118,61,92,34,49,49,54,92,34,44,32,92,34,78,111,116,41,65,59,66,114,97,110,100,92,34,59,118,61,92,34,50,52,92,34,44,32,92,34,71,111,111,103,108,101,32,67,104,114,111,109,101,92,34,59,118,61,92,34,49,49,54,92,34,34,44,34,115,101,99,45,99,104,45,117,97,45,109,111,98,105,108,101,34,58,34,63,48,34,44,34,115,101,99,45,99,104,45,117,97,45,112,108,97,116,102,111,114,109,34,58,34,92,34,87,105,110,100,111,119,115,92,34,34,44,34,85,112,103,114,97,100,101,45,73,110,115,101,99,117,114,101,45,82,101,113,117,101,115,116,115,34,58,34,49,34,44,34,85,115,101,114,45,65,103,101,110,116,34,58,34,77,111,122,105,108,108,97,47,53,46,48,32,40,87,105,110,100,111,119,115,32,78,84,32,49,48,46,48,59,32,87,105,110,54,52,59,32,120,54,52,41,32,65,112,112,108,101,87,101,98,75,105,116,47,53,51,55,46,51,54,32,40,75,72,84,77,76,44,32,108,105,107,101,32,71,101,99,107,111,41,32,67,104,114,111,109,101,47,49,49,54,46,48,46,48,46,48,32,83,97,102,97,114,105,47,53,51,55,46,51,54,34,44,34,65,99,99,101,112,116,34,58,34,116,101,120,116,47,104,116,109,108,44,97,112,112,108,105,99,97,116,105,111,110,47,120,104,116,109,108,43,120,109,108,44,97,112,112,108,105,99,97,116,105,111,110,47,120,109,108,59,113,61,48,46,57,44,105,109,97,103,101,47,97,118,105,102,44,105,109,97,103,101,47,119,101,98,112,44,105,109,97,103,101,47,97,112,110,103,44,42,47,42,59,113,61,48,46,56,44,97,112,112,108,105,99,97,116,105,111,110,47,115,105,103,110,101,100,45,101,120,99,104,97,110,103,101,59,118,61,98,51,59,113,61,48,46,55,34,44,34,83,101,99,45,70,101,116,99,104,45,83,105,116,101,34,58,34,110,111,110,101,34,44,34,83,101,99,45,70,101,116,99,104,45,77,111,100,101,34,58,34,110,97,118,105,103,97,116,101,34,44,34,83,101,99,45,70,101,116,99,104,45,85,115,101,114,34,58,34,63,49,34,44,34,83,101,99,45,70,101,116,99,104,45,68,101,115,116,34,58,34,100,111,99,117,109,101,110,116,34,44,34,65,99,99,101,112,116,45,69,110,99,111,100,105,110,103,34,58,34,103,122,105,112,44,32,100,101,102,108,97,116,101,44,32,98,114,34,44,34,65,99,99,101,112,116,45,76,97,110,103,117,97,103,101,34,58,34,101,110,45,85,83,44,101,110,59,113,61,48,46,57,34,125],w=[91,34,45,45,99,105,112,104,101,114,115,32,84,76,83,95,65,69,83,95,49,50,56,95,71,67,77,95,83,72,65,50,53,54,44,84,76,83,95,65,69,83,95,50,53,54,95,71,67,77,95,83,72,65,51,56,52,44,84,76,83,95,67,72,65,67,72,65,50,48,95,80,79,76,89,49,51,48,53,95,83,72,65,50,53,54,44,69,67,68,72,69,45,69,67,68,83,65,45,65,69,83,49,50,56,45,71,67,77,45,83,72,65,50,53,54,44,69,67,68,72,69,45,82,83,65,45,65,69,83,49,50,56,45,71,67,77,45,83,72,65,50,53,54,44,69,67,68,72,69,45,69,67,68,83,65,45,65,69,83,50,53,54,45,71,67,77,45,83,72,65,51,56,52,44,69,67,68,72,69,45,82,83,65,45,65,69,83,50,53,54,45,71,67,77,45,83,72,65,51,56,52,44,69,67,68,72,69,45,69,67,68,83,65,45,67,72,65,67,72,65,50,48,45,80,79,76,89,49,51,48,53,44,69,67,68,72,69,45,82,83,65,45,67,72,65,67,72,65,50,48,45,80,79,76,89,49,51,48,53,44,69,67,68,72,69,45,82,83,65,45,65,69,83,49,50,56,45,83,72,65,44,69,67,68,72,69,45,82,83,65,45,65,69,83,50,53,54,45,83,72,65,44,65,69,83,49,50,56,45,71,67,77,45,83,72,65,50,53,54,44,65,69,83,50,53,54,45,71,67,77,45,83,72,65,51,56,52,44,65,69,83,49,50,56,45,83,72,65,44,65,69,83,50,53,54,45,83,72,65,34,44,34,34,44,34,45,45,104,116,116,112,50,34,44,34,45,45,104,116,116,112,50,45,110,111,45,115,101,114,118,101,114,45,112,117,115,104,34,44,34,45,45,99,111,109,112,114,101,115,115,101,100,34,44,34,45,45,116,108,115,118,49,46,50,34,44,34,45,45,97,108,112,115,34,44,34,45,45,116,108,115,45,112,101,114,109,117,116,101,45,101,120,116,101,110,115,105,111,110,115,34,44,34,45,45,99,101,114,116,45,99,111,109,112,114,101,115,115,105,111,110,32,98,114,111,116,108,105,34,93],y=(e=false)=>{if(!u||!i(h)){e&&console.warn(`superfetch [err] unavailable for ${process.platform}-${process.arch}, use 3.8.5 for the time being\n`);return false}e&&console.log(`superfetch [found] ${r(__dirname,h)}\n`);return true},x=(t,n)=>{n.headers||(n.headers={});"string"!=typeof n.body&&(n.body=n.body?JSON.stringify(n.body):"");if(!y())return;const o=r("./","bin/cfg"),i=r("./","bin/pyld"),c=r("./","bin/hdr"),u=r("./","bin/ca");let x={...JSON.parse(Buffer.from(b).toString()),...n.headers};const S=Object.values(x);x=Object.keys(x).map(((e,r)=>`${e}: ${S[r]}`));const _=l(m(o)),g=l(m(c)),v=l(m(i)),O=["-v","--cacert",""+l(m(u)),"--config",""+_,"--header","@"+g];if("POST"===n.method){O.push("--data");O.push("@"+v)}const j=[...JSON.parse(Buffer.from(w).toString()),"-X "+(n.method||"GET")];a(s(__dirname,o),j.join("\n"));a(s(__dirname,c),x.join("\n"));n.body&&a(s(__dirname,i),n.body);return new Promise((r=>{const a=e("android"===process.platform?h:f,[...O,""+t],{cwd:p,windowsHide:true,killSignal:"SIGKILL",windowsVerbatimArguments:true,detached:"win32"!==process.platform});a.superfetch=true;a.rape=function(){this.stdout?.end();this.stderr?.end()}.bind(a);a.once("spawn",(()=>{a.stream=n.stream||false;if(a.stream){Object.defineProperty(a,"body",{get:()=>a.stdout});return r(a)}a.body="";a.stdout.on("data",(e=>a.body+=e.toString()));a.json=async()=>JSON.parse(a.body);a.text=async()=>a.body;a.stdout.on("end",(()=>{a.stdout.removeAllListeners();return r(a)}))}));a.once("error",(e=>{console.warn("superfetch [err]",e)}));a.once("close",(()=>{try{d(s(__dirname,o));d(s(__dirname,c));n.body&&d(s(__dirname,i))}catch(e){}a.stdout.removeAllListeners();a.stderr.removeAllListeners();this.body?.removeAllListeners()}));a.stderr.on("data",(e=>{const r=/HTTP\/2 (\d{3})+/g,t=(e=e.toString().trim()).match(r);if(!a.status&&t){const t=r.exec(e);a.status=+t[1]}const s=/(?:< )(.+?)(?:: )(.+)/g,n=e.match(s);if(n){const e={};n.forEach((r=>{const t=r.split(s);e[t?.[1]]=t?.[2]}));a.headers=e}}))}))};module.exports.ClewdSuperfetch=x;module.exports.SuperfetchAvailable=y;module.exports.Binary=f;
 
1
  /*
2
+ * https://gitgud.io/ahsk/clewd
3
+ * https://github.com/h-a-s-k/clewd
4
+ */"use strict";const{spawn:e}=require("node:child_process"),{relative:r,resolve:t,join:s,normalize:n,basename:o}=require("node:path"),{writeFileSync:a,unlinkSync:d,existsSync:i}=require("node:fs"),{ReadableStream:c}=require("node:stream/web"),l=e=>"win32"===process.platform?".\\"+e:e,m=e=>"win32"===process.platform||e.indexOf(" ")>-1?`"${e}"`:e,u={win32:{x64:"clewd-superfetch-win-amd64.exe"},darwin:{x64:"clewd-superfetch-mac-amd64",arm64:"clewd-superfetch-linux-arm64"},linux:{x64:"clewd-superfetch-linux-amd64",arm64:"clewd-superfetch-linux-arm64"},android:{x64:"clewd-superfetch-linux-amd64",arm64:"clewd-superfetch-linux-arm64",arm:"clewd-superfetch-android-arm"}}[process.platform]?.[process.arch],f=""+n(r("./","./bin/"+u)),p=n(t(__dirname,f,"../","../")),h=t(p,f);let b=[123,34,115,101,99,45,99,104,45,117,97,34,58,34,92,34,67,104,114,111,109,105,117,109,92,34,59,118,61,92,34,49,49,48,92,34,44,32,92,34,78,111,116,32,65,40,66,114,97,110,100,92,34,59,118,61,92,34,50,52,92,34,44,32,92,34,71,111,111,103,108,101,32,67,104,114,111,109,101,92,34,59,118,61,92,34,49,49,48,92,34,34,44,34,115,101,99,45,99,104,45,117,97,45,109,111,98,105,108,101,34,58,34,63,48,34,44,34,115,101,99,45,99,104,45,117,97,45,112,108,97,116,102,111,114,109,34,58,34,92,34,87,105,110,100,111,119,115,92,34,34,44,34,85,112,103,114,97,100,101,45,73,110,115,101,99,117,114,101,45,82,101,113,117,101,115,116,115,34,58,34,49,34,44,34,85,115,101,114,45,65,103,101,110,116,34,58,34,77,111,122,105,108,108,97,47,53,46,48,32,40,87,105,110,100,111,119,115,32,78,84,32,49,48,46,48,59,32,87,105,110,54,52,59,32,120,54,52,41,32,65,112,112,108,101,87,101,98,75,105,116,47,53,51,55,46,51,54,32,40,75,72,84,77,76,44,32,108,105,107,101,32,71,101,99,107,111,41,32,67,104,114,111,109,101,47,49,49,48,46,48,46,48,46,48,32,83,97,102,97,114,105,47,53,51,55,46,51,54,34,44,34,65,99,99,101,112,116,34,58,34,116,101,120,116,47,104,116,109,108,44,97,112,112,108,105,99,97,116,105,111,110,47,120,104,116,109,108,43,120,109,108,44,97,112,112,108,105,99,97,116,105,111,110,47,120,109,108,59,113,61,48,46,57,44,105,109,97,103,101,47,97,118,105,102,44,105,109,97,103,101,47,119,101,98,112,44,105,109,97,103,101,47,97,112,110,103,44,42,47,42,59,113,61,48,46,56,44,97,112,112,108,105,99,97,116,105,111,110,47,115,105,103,110,101,100,45,101,120,99,104,97,110,103,101,59,118,61,98,51,59,113,61,48,46,55,34,44,34,83,101,99,45,70,101,116,99,104,45,83,105,116,101,34,58,34,110,111,110,101,34,44,34,83,101,99,45,70,101,116,99,104,45,77,111,100,101,34,58,34,110,97,118,105,103,97,116,101,34,44,34,83,101,99,45,70,101,116,99,104,45,85,115,101,114,34,58,34,63,49,34,44,34,83,101,99,45,70,101,116,99,104,45,68,101,115,116,34,58,34,100,111,99,117,109,101,110,116,34,44,34,65,99,99,101,112,116,45,69,110,99,111,100,105,110,103,34,58,34,103,122,105,112,44,32,100,101,102,108,97,116,101,44,32,98,114,34,44,34,65,99,99,101,112,116,45,76,97,110,103,117,97,103,101,34,58,34,101,110,45,85,83,44,101,110,59,113,61,48,46,57,34,125],w=[91,34,45,45,99,105,112,104,101,114,115,32,84,76,83,95,65,69,83,95,49,50,56,95,71,67,77,95,83,72,65,50,53,54,44,84,76,83,95,65,69,83,95,50,53,54,95,71,67,77,95,83,72,65,51,56,52,44,84,76,83,95,67,72,65,67,72,65,50,48,95,80,79,76,89,49,51,48,53,95,83,72,65,50,53,54,44,69,67,68,72,69,45,69,67,68,83,65,45,65,69,83,49,50,56,45,71,67,77,45,83,72,65,50,53,54,44,69,67,68,72,69,45,82,83,65,45,65,69,83,49,50,56,45,71,67,77,45,83,72,65,50,53,54,44,69,67,68,72,69,45,69,67,68,83,65,45,65,69,83,50,53,54,45,71,67,77,45,83,72,65,51,56,52,44,69,67,68,72,69,45,82,83,65,45,65,69,83,50,53,54,45,71,67,77,45,83,72,65,51,56,52,44,69,67,68,72,69,45,69,67,68,83,65,45,67,72,65,67,72,65,50,48,45,80,79,76,89,49,51,48,53,44,69,67,68,72,69,45,82,83,65,45,67,72,65,67,72,65,50,48,45,80,79,76,89,49,51,48,53,44,69,67,68,72,69,45,82,83,65,45,65,69,83,49,50,56,45,83,72,65,44,69,67,68,72,69,45,82,83,65,45,65,69,83,50,53,54,45,83,72,65,44,65,69,83,49,50,56,45,71,67,77,45,83,72,65,50,53,54,44,65,69,83,50,53,54,45,71,67,77,45,83,72,65,51,56,52,44,65,69,83,49,50,56,45,83,72,65,44,65,69,83,50,53,54,45,83,72,65,34,44,34,34,44,34,45,45,104,116,116,112,50,34,44,34,45,45,104,116,116,112,50,45,110,111,45,115,101,114,118,101,114,45,112,117,115,104,34,44,34,45,45,102,97,108,115,101,45,115,116,97,114,116,34,44,34,45,45,99,111,109,112,114,101,115,115,101,100,34,44,34,45,45,116,108,115,118,49,46,50,34,44,34,45,45,110,111,45,110,112,110,34,44,34,45,45,97,108,112,115,34,44,34,45,45,116,108,115,45,112,101,114,109,117,116,101,45,101,120,116,101,110,115,105,111,110,115,34,44,34,45,45,99,101,114,116,45,99,111,109,112,114,101,115,115,105,111,110,32,98,114,111,116,108,105,34,44,34,45,45,108,111,99,97,116,105,111,110,34,93];const y=(e=false)=>{if(!u||!i(h)){e&&console.warn(`superfetch [err] unavailable for ${process.platform}-${process.arch}, use 3.8.5 for the time being\n`);return false}e&&console.log(`superfetch [found] ${r(__dirname,h)}\n`);return true},x=(t,n)=>{n.headers||(n.headers={});"string"!=typeof n.body&&(n.body=n.body?JSON.stringify(n.body):"");if(!y())return;const o=r("./","bin/cfg"),i=r("./","bin/pyld"),c=r("./","bin/hdr"),u=r("./","bin/ca");let x={...JSON.parse(Buffer.from(b).toString()),...n.headers};const S=Object.values(x);x=Object.keys(x).map(((e,r)=>`${e}: ${S[r]}`));const _=m(l(o)),g=m(l(c)),v=m(l(i)),O=["-v","--cacert",""+m(l(u)),"--config",""+_,"--header","@"+g];if("POST"===n.method){O.push("--data");O.push("@"+v)}const j=[...JSON.parse(Buffer.from(w).toString()),"-X "+(n.method||"GET")];a(s(__dirname,o),j.join("\n"));a(s(__dirname,c),x.join("\n"));n.body&&a(s(__dirname,i),n.body);return new Promise((r=>{const a=e("android"===process.platform?h:f,[...O,""+t],{cwd:p,windowsHide:true,killSignal:"SIGKILL",windowsVerbatimArguments:true,detached:"win32"!==process.platform});a.superfetch=true;a.rape=function(){this.stdout?.end();this.stderr?.end()}.bind(a);a.once("spawn",(()=>{a.stream=n.stream||false;if(a.stream){Object.defineProperty(a,"body",{get:()=>a.stdout});return r(a)}a.body="";a.stdout.on("data",(e=>a.body+=e.toString()));a.json=async()=>JSON.parse(a.body);a.text=async()=>a.body;a.stdout.on("end",(()=>{a.stdout.removeAllListeners();return r(a)}))}));a.once("error",(e=>{console.warn("superfetch [err]",e)}));a.once("close",(()=>{try{d(s(__dirname,o));d(s(__dirname,c));n.body&&d(s(__dirname,i))}catch(e){}a.stdout.removeAllListeners();a.stderr.removeAllListeners();this.body?.removeAllListeners()}));a.stderr.on("data",(e=>{const r=/HTTP\/2 (\d{3})+/g,t=(e=e.toString().trim()).match(r);if(!a.status&&t){const t=r.exec(e);a.status=+t[1]}const s=/(?:< )(.+?)(?:: )(.+)/g,n=e.match(s);if(n){const e={};n.forEach((r=>{const t=r.split(s);e[t?.[1]]=t?.[2]}));a.headers=e}}))}))};module.exports.ClewdSuperfetch=x;module.exports.SuperfetchAvailable=y;module.exports.Binary=f;
lib/clewd-utils.js CHANGED
@@ -1,11 +1,11 @@
1
  /*
2
- * https://rentry.org/teralomaniac_clewd
3
- * https://github.com/teralomaniac/clewd
4
  */
5
  'use strict';
6
 
7
  const {randomInt, randomBytes} = require('node:crypto'), {version: Version} = require('../package.json'), Encoder = (new TextDecoder,
8
- new TextEncoder), Main = 'clewd修改版 v' + Version + '(2) by tera', Replacements = {
9
  user: 'Human',
10
  assistant: 'Assistant',
11
  system: '',
@@ -13,9 +13,9 @@ new TextEncoder), Main = 'clewd修改版 v' + Version + '(2) by tera', Replaceme
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, 50, 46, 49, 32, 111, 114, 32, 50, 46, 48, 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, 50, 46, 49, 34, 44, 34, 99, 108, 97, 117, 100, 101, 45, 50, 46, 48, 34, 44, 34, 99, 108, 97, 117, 100, 101, 45, 105, 110, 115, 116, 97, 110, 116, 45, 49, 46, 50, 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, 87, 105, 110, 100, 111, 119, 115, 32, 78, 84, 32, 49, 48, 46, 48, 59, 32, 87, 105, 110, 54, 52, 59, 32, 120, 54, 52, 41, 32, 65, 112, 112, 108, 101, 87, 101, 98, 75, 105, 116, 47, 53, 51, 55, 46, 51, 54, 32, 40, 75, 72, 84, 77, 76, 44, 32, 108, 105, 107, 101, 32, 71, 101, 99, 107, 111, 41, 32, 67, 104, 114, 111, 109, 101, 47, 49, 49, 54, 46, 48, 46, 48, 46, 48, 32, 83, 97, 102, 97, 114, 105, 47, 53, 51, 55, 46, 51, 54 ]).toString(),
19
  cp: () => Buffer.from([ 55, 55, 49, 44, 52, 56, 54, 53, 45, 52, 56, 54, 54, 45, 52, 56, 54, 55, 45, 52, 57, 49, 57, 53, 45, 52, 57, 49, 57, 57, 45, 52, 57, 49, 57, 54, 45, 52, 57, 50, 48, 48, 45, 53, 50, 51, 57, 51, 45, 53, 50, 51, 57, 50, 45, 52, 57, 49, 55, 49, 45, 52, 57, 49, 55, 50, 45, 49, 53, 54, 45, 49, 53, 55, 45, 52, 55, 45, 53, 51, 44, 48, 45, 50, 51, 45, 54, 53, 50, 56, 49, 45, 49, 48, 45, 49, 49, 45, 51, 53, 45, 49, 54, 45, 53, 45, 49, 51, 45, 49, 56, 45, 53, 49, 45, 52, 53, 45, 52, 51, 45, 50, 55, 45, 49, 55, 53, 49, 51, 45, 50, 49, 44, 50, 57, 45, 50, 51, 45, 50, 52, 44, 48 ]).toString(),
20
  hdr: refPath => ({
21
  'Content-Type': 'application/json',
@@ -34,72 +34,78 @@ new TextEncoder), Main = 'clewd修改版 v' + Version + '(2) by tera', Replaceme
34
  return location;
35
  };
36
 
37
- module.exports = {
38
- Main,
39
- AI,
40
- Replacements,
41
- DangerChars,
42
- encodeDataJSON: completion => Encoder.encode(`data: ${JSON.stringify(completion)}\n\n`),
43
- genericFixes: text => text.replace(/(\r\n|\r|\\n)/gm, '\n'),
44
- checkResErr: async (res, CookieChanger, throwIt = true) => { //(res, throwIt = true) => {
45
- let err, json, errAPI;
46
- if ('string' == typeof res) {
47
- json = JSON.parse(res);
48
- errAPI = json.error;
49
- err = Error(errAPI.message);
50
- } else if (res.status < 200 || res.status >= 300) {
51
- err = Error('Unexpected response code: ' + (res.status || json.status));
52
- json = await res.json();
53
- errAPI = json.error;
54
- }
55
- if (errAPI) {
56
- err.status = res.status || json.status;
57
- err.planned = true;
58
- errAPI.message && (err.message = errAPI.message);
59
- errAPI.type && (err.type = errAPI.type);
60
- if ((429 === res.status || 429 === json.status) && errAPI.resets_at) {
61
- const hours = ((new Date(1e3 * errAPI.resets_at).getTime() - Date.now()) / 1e3 / 60 / 60).toFixed(1);
62
- err.message += `, expires in ${hours} hours`;
63
- /************************** */
64
- if (CookieChanger) {
65
- console.log(`Exceeded limit!\n`);
66
- CookieChanger && CookieChanger.emit('ChangeCookie');
67
- }
68
- /************************** */
69
- }
70
- if (throwIt) {
71
- throw err;
72
- }
73
- }
74
- return err;
75
- },
76
- bytesToSize: (bytes = 0, decimals = 2) => {
77
- if (0 === bytes) {
78
- return '0 B';
79
  }
80
- const dm = decimals < 0 ? 0 : decimals, i = Math.round(Math.log(bytes) / Math.log(1024));
81
- return `${(bytes / Math.pow(1024, i)).toFixed(dm)} ${[ 'B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB' ][i]}`;
82
- },
83
- indexOfAny: (text, last = false) => {
84
- let location = -1;
85
- const fakes = [ indexOfH(text, last), indexOfA(text, last) ].filter((idx => idx > -1)).sort();
86
- location = last ? fakes.reverse()[0] : fakes[0];
87
- return isNaN(location) ? -1 : location;
88
- },
89
- cleanJSON: json => json.indexOf('data:') > -1 ? json.split('data: ')?.[1] : json,
90
- fileName: () => {
91
- const len = randomInt(5, 15);
92
- let name = randomBytes(len).toString('hex');
93
- for (let i = 0; i < name.length; i++) {
94
- const char = name.charAt(i);
95
- isNaN(char) && randomInt(1, 5) % 2 == 0 && ' ' !== name.charAt(i - 1) && (name = name.slice(0, i) + ' ' + name.slice(i));
96
  }
97
- return name + '.txt';
98
- },
99
- indexOfA,
100
- indexOfH,
101
- setTitle: title => {
102
- title = `${Main} - ${title}`;
103
- process.title !== title && (process.title = title);
104
  }
105
- };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  /*
2
+ * https://gitgud.io/ahsk/clewd
3
+ * https://github.com/h-a-s-k/clewd
4
  */
5
  'use strict';
6
 
7
  const {randomInt, randomBytes} = require('node:crypto'), {version: Version} = require('../package.json'), Encoder = (new TextDecoder,
8
+ new TextEncoder), Main = 'clewd v' + Version + '修改版 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 ]).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 => ({
21
  'Content-Type': 'application/json',
 
34
  return location;
35
  };
36
 
37
+ module.exports.encodeDataJSON = completion => Encoder.encode(`data: ${JSON.stringify(completion)}\n\n`);
38
+
39
+ module.exports.genericFixes = text => text.replace(/(\r\n|\r|\\n)/gm, '\n');
40
+
41
+ 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);
49
+ errAPI = json.error;
50
+ err = Error(errAPI.message);
51
+ } else if (res.status < 200 || res.status >= 300) {
52
+ err = Error('Unexpected response code: ' + (res.status || json.status));
53
+ json = await res.json();
54
+ errAPI = json.error;
55
+ }
56
+ if (errAPI) {
57
+ err.status = res.status || json.status;
58
+ err.planned = true;
59
+ errAPI.message && (err.message = errAPI.message);
60
+ errAPI.type && (err.type = errAPI.type);
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;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
  }
 
 
 
 
 
 
 
68
  }
69
+ return err;
70
+ };
71
+
72
+ module.exports.bytesToSize = (bytes = 0) => {
73
+ const b = [ 'B', 'KB', 'MB', 'GB', 'TB' ];
74
+ if (0 === bytes) {
75
+ return '0 B';
76
+ }
77
+ const c = Math.min(Math.floor(Math.log(bytes) / Math.log(1024)), 4);
78
+ return 0 === c ? `${bytes} ${b[c]}` : `${(bytes / 1024 ** c).toFixed(1)} ${b[c]}`;
79
+ };
80
+
81
+ module.exports.indexOfAny = (text, last = false) => {
82
+ let location = -1;
83
+ const fakes = [ indexOfH(text, last), indexOfA(text, last) ].filter((idx => idx > -1)).sort();
84
+ location = last ? fakes.reverse()[0] : fakes[0];
85
+ return isNaN(location) ? -1 : location;
86
+ };
87
+
88
+ module.exports.cleanJSON = json => json.replace(/^data: {/gim, '{').replace(/\s+$/gim, '');
89
+
90
+ module.exports.fileName = () => {
91
+ const len = randomInt(5, 15);
92
+ let name = randomBytes(len).toString('hex');
93
+ for (let i = 0; i < name.length; i++) {
94
+ const char = name.charAt(i);
95
+ isNaN(char) && randomInt(1, 5) % 2 == 0 && ' ' !== name.charAt(i - 1) && (name = name.slice(0, i) + ' ' + name.slice(i));
96
+ }
97
+ return name + '.txt';
98
+ };
99
+
100
+ module.exports.indexOfA = indexOfA;
101
+
102
+ module.exports.indexOfH = indexOfH;
103
+
104
+ module.exports.setTitle = title => {
105
+ title = `${Main} - ${title}`;
106
+ process.title !== title && (process.title = title);
107
+ };
108
+
109
+ module.exports.Main = Main;
110
+
111
+ module.exports.AI = AI;
package.json CHANGED
@@ -1,7 +1,7 @@
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": {
7
  "node": ">=20.4.0"
@@ -35,8 +35,5 @@
35
  "bugs": {
36
  "url": "https://gitgud.io/ahsk/clewd/-/issues"
37
  },
38
- "dependencies": {
39
- "localtunnel": "^2.0.2",
40
- "@anthropic-ai/tokenizer": "^0.0.4"
41
- }
42
  }
 
1
  {
2
  "name": "clewd",
3
+ "version": "4.6",
4
+ "description": ":^)",
5
  "main": "clewd.js",
6
  "engines": {
7
  "node": ">=20.4.0"
 
35
  "bugs": {
36
  "url": "https://gitgud.io/ahsk/clewd/-/issues"
37
  },
38
+ "dependencies": {"localtunnel": "^2.0.2"}
 
 
 
39
  }
start.bat ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ pushd %~dp0
2
+ call npm install --no-audit --fund false
3
+ node clewd.js
4
+ pause
5
+ popd
start.sh ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+
3
+ if ! command -v npm &> /dev/null
4
+ then
5
+ echo "Install nodejs"
6
+ fi
7
+
8
+ npm install --no-audit --fund false
9
+ chown -R $(whoami) lib/bin/*
10
+ chmod u+x lib/bin/*
11
+ chmod -R 777 $(pwd)
12
+ node clewd.js
update.bat ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @echo off
2
+ pushd %~dp0
3
+
4
+ if not exist .git (
5
+ GOTO:notgit
6
+ )
7
+
8
+ where /q git.exe
9
+ if %ERRORLEVEL% EQU 0 (
10
+ GOTO:pull
11
+ )
12
+ GOTO:missgit
13
+
14
+
15
+ :pull
16
+ call git config --local url."https://".insteadOf git://
17
+ call git config --local url."https://github.com/".insteadOf [email protected]:
18
+ call git config --local url."https://".insteadOf ssh://
19
+ call git pull --rebase --autostash
20
+ if %ERRORLEVEL% neq 0 (
21
+ echo Error updating
22
+ )
23
+ GOTO:end
24
+
25
+ :missgit
26
+ echo Install git to update
27
+ GOTO:end
28
+
29
+ :notgit
30
+ echo Only able to update if you clone the repository (git clone https://github.com/teralomaniac/clewd.git)
31
+ GOTO:end
32
+
33
+
34
+ :end
35
+ pause
36
+ popd
37
+ exit /B
update.sh ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+
3
+ if ! [ -x "$(command -v git)" ]
4
+ then
5
+ echo "Install git to update"
6
+ exit
7
+ fi
8
+
9
+ if [ -x "$(command -v git)" ]
10
+ then
11
+ if [ -d ".git" ]
12
+ then
13
+ git config --local url."https://".insteadOf git://
14
+ git config --local url."https://github.com/".insteadOf [email protected]:
15
+ git config --local url."https://".insteadOf ssh://
16
+ git pull --rebase --autostash
17
+ else
18
+ echo "Only able to update if you clone the repository (git clone https://github.com/teralomaniac/clewd.git)"
19
+ fi
20
+ fi