wechaty-web-panel 1.5.2 → 1.5.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -0
- package/dist/cjs/src/lib/chatGPT.d.ts +61 -0
- package/dist/cjs/src/lib/chatGPT.js +561 -0
- package/dist/cjs/src/lib/pTimeout.d.ts +13 -0
- package/dist/cjs/src/lib/pTimeout.js +103 -0
- package/dist/cjs/src/package-json.d.ts +5 -1
- package/dist/cjs/src/package-json.js +6 -2
- package/dist/cjs/src/proxy/openAi.js +4 -27
- package/dist/cjs/src/proxy/openAiHook.js +3 -26
- package/dist/esm/src/lib/chatGPT.d.ts +61 -0
- package/dist/esm/src/lib/chatGPT.js +552 -0
- package/dist/esm/src/lib/pTimeout.d.ts +13 -0
- package/dist/esm/src/lib/pTimeout.js +97 -0
- package/dist/esm/src/package-json.d.ts +5 -1
- package/dist/esm/src/package-json.js +6 -2
- package/dist/esm/src/proxy/openAi.js +1 -1
- package/dist/esm/src/proxy/openAiHook.js +1 -1
- package/package.json +6 -2
package/CHANGELOG.md
CHANGED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
export let ChatGPTAPI: {
|
|
2
|
+
new (opts: any): {
|
|
3
|
+
_apiKey: any;
|
|
4
|
+
_apiOrg: any;
|
|
5
|
+
_apiBaseUrl: any;
|
|
6
|
+
_debug: boolean;
|
|
7
|
+
_fetch: any;
|
|
8
|
+
_completionParams: any;
|
|
9
|
+
_systemMessage: any;
|
|
10
|
+
_maxModelTokens: any;
|
|
11
|
+
_maxResponseTokens: any;
|
|
12
|
+
_getMessageById: any;
|
|
13
|
+
_upsertMessage: any;
|
|
14
|
+
_messageStore: any;
|
|
15
|
+
sendMessage(text: any, opts?: {}): Promise<any>;
|
|
16
|
+
apiKey: any;
|
|
17
|
+
apiOrg: any;
|
|
18
|
+
_buildMessages(text: any, opts: any): Promise<{
|
|
19
|
+
messages: {
|
|
20
|
+
role: string;
|
|
21
|
+
content: any;
|
|
22
|
+
}[];
|
|
23
|
+
maxTokens: number;
|
|
24
|
+
numTokens: number;
|
|
25
|
+
}>;
|
|
26
|
+
_getTokenCount(text: any): Promise<number>;
|
|
27
|
+
_defaultGetMessageById(id: any): Promise<any>;
|
|
28
|
+
_defaultUpsertMessage(message: any): Promise<void>;
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
export const ChatGPTError: {
|
|
32
|
+
new (message?: string | undefined): {
|
|
33
|
+
name: string;
|
|
34
|
+
message: string;
|
|
35
|
+
stack?: string | undefined;
|
|
36
|
+
cause?: unknown;
|
|
37
|
+
};
|
|
38
|
+
new (message?: string | undefined, options?: ErrorOptions | undefined): {
|
|
39
|
+
name: string;
|
|
40
|
+
message: string;
|
|
41
|
+
stack?: string | undefined;
|
|
42
|
+
cause?: unknown;
|
|
43
|
+
};
|
|
44
|
+
captureStackTrace(targetObject: object, constructorOpt?: Function | undefined): void;
|
|
45
|
+
prepareStackTrace?: ((err: Error, stackTraces: NodeJS.CallSite[]) => any) | undefined;
|
|
46
|
+
stackTraceLimit: number;
|
|
47
|
+
};
|
|
48
|
+
export let ChatGPTUnofficialProxyAPI: {
|
|
49
|
+
new (opts: any): {
|
|
50
|
+
_accessToken: any;
|
|
51
|
+
_apiReverseProxyUrl: any;
|
|
52
|
+
_debug: boolean;
|
|
53
|
+
_model: any;
|
|
54
|
+
_fetch: any;
|
|
55
|
+
_headers: any;
|
|
56
|
+
accessToken: any;
|
|
57
|
+
sendMessage(text: any, opts?: {}): Promise<any>;
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
export let openai: any;
|
|
61
|
+
//# sourceMappingURL=chatGPT.d.ts.map
|
|
@@ -0,0 +1,561 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.openai = exports.ChatGPTUnofficialProxyAPI = exports.ChatGPTError = exports.ChatGPTAPI = void 0;
|
|
7
|
+
const keyv_1 = __importDefault(require("keyv"));
|
|
8
|
+
const pTimeout_js_1 = __importDefault(require("./pTimeout.js"));
|
|
9
|
+
const quick_lru_1 = __importDefault(require("quick-lru"));
|
|
10
|
+
const uuid_1 = require("uuid");
|
|
11
|
+
const tiktoken_1 = require("@dqbd/tiktoken");
|
|
12
|
+
const eventsource_parser_1 = require("eventsource-parser");
|
|
13
|
+
const tokenizer = (0, tiktoken_1.get_encoding)("cl100k_base");
|
|
14
|
+
let openai;
|
|
15
|
+
exports.openai = openai;
|
|
16
|
+
((openai2) => {
|
|
17
|
+
})(openai || (exports.openai = openai = {}));
|
|
18
|
+
function encode(input) {
|
|
19
|
+
return tokenizer.encode(input);
|
|
20
|
+
}
|
|
21
|
+
const ChatGPTError = class extends Error {
|
|
22
|
+
};
|
|
23
|
+
exports.ChatGPTError = ChatGPTError;
|
|
24
|
+
const fetch = globalThis.fetch;
|
|
25
|
+
async function* streamAsyncIterable(stream) {
|
|
26
|
+
const reader = stream.getReader();
|
|
27
|
+
try {
|
|
28
|
+
while (true) {
|
|
29
|
+
const { done, value } = await reader.read();
|
|
30
|
+
if (done) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
yield value;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
finally {
|
|
37
|
+
reader.releaseLock();
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
async function fetchSSE(url, options, fetch2 = fetch) {
|
|
41
|
+
const { onMessage, onError, ...fetchOptions } = options;
|
|
42
|
+
const res = await fetch2(url, fetchOptions);
|
|
43
|
+
if (!res.ok) {
|
|
44
|
+
let reason;
|
|
45
|
+
try {
|
|
46
|
+
reason = await res.text();
|
|
47
|
+
}
|
|
48
|
+
catch (err) {
|
|
49
|
+
reason = res.statusText;
|
|
50
|
+
}
|
|
51
|
+
const msg = `ChatGPT error ${res.status}: ${reason}`;
|
|
52
|
+
const error = new ChatGPTError(msg, { cause: res });
|
|
53
|
+
error.statusCode = res.status;
|
|
54
|
+
error.statusText = res.statusText;
|
|
55
|
+
throw error;
|
|
56
|
+
}
|
|
57
|
+
const parser = (0, eventsource_parser_1.createParser)((event) => {
|
|
58
|
+
if (event.type === "event") {
|
|
59
|
+
onMessage(event.data);
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
const feed = (chunk) => {
|
|
63
|
+
let _a;
|
|
64
|
+
let response = null;
|
|
65
|
+
try {
|
|
66
|
+
response = JSON.parse(chunk);
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
}
|
|
70
|
+
if (((_a = response == null ? void 0 : response.detail) == null ? void 0 : _a.type) === "invalid_request_error") {
|
|
71
|
+
const msg = `ChatGPT error ${response?.detail.message}: ${response?.detail.code} (${response?.detail.type})`;
|
|
72
|
+
const error = new ChatGPTError(msg, { cause: response });
|
|
73
|
+
error.statusCode = response?.detail.code;
|
|
74
|
+
error.statusText = response?.detail.message;
|
|
75
|
+
if (onError) {
|
|
76
|
+
onError(error);
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
console.error(error);
|
|
80
|
+
}
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
parser.feed(chunk);
|
|
84
|
+
};
|
|
85
|
+
if (!res.body.getReader) {
|
|
86
|
+
const body = res.body;
|
|
87
|
+
if (!body.on || !body.read) {
|
|
88
|
+
throw new ChatGPTError("unsupported \"fetch\" implementation");
|
|
89
|
+
}
|
|
90
|
+
body.on("readable", () => {
|
|
91
|
+
let chunk;
|
|
92
|
+
while (null !== (chunk = body.read())) {
|
|
93
|
+
feed(chunk.toString());
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
for await (const chunk of streamAsyncIterable(res.body)) {
|
|
99
|
+
const str = new TextDecoder().decode(chunk);
|
|
100
|
+
feed(str);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
let CHATGPT_MODEL = "gpt-3.5-turbo";
|
|
105
|
+
let USER_LABEL_DEFAULT = "User";
|
|
106
|
+
let ASSISTANT_LABEL_DEFAULT = "ChatGPT";
|
|
107
|
+
let ChatGPTAPI = class {
|
|
108
|
+
constructor(opts) {
|
|
109
|
+
const { apiKey, apiOrg, apiBaseUrl = "https://api.openai.com/v1", debug = false, messageStore, completionParams, systemMessage, maxModelTokens = 4e3, maxResponseTokens = 1e3, getMessageById, upsertMessage, fetch: fetch2 = fetch } = opts;
|
|
110
|
+
this._apiKey = apiKey;
|
|
111
|
+
this._apiOrg = apiOrg;
|
|
112
|
+
this._apiBaseUrl = apiBaseUrl;
|
|
113
|
+
this._debug = !!debug;
|
|
114
|
+
this._fetch = fetch2;
|
|
115
|
+
this._completionParams = {
|
|
116
|
+
model: CHATGPT_MODEL,
|
|
117
|
+
temperature: 0.8,
|
|
118
|
+
top_p: 1,
|
|
119
|
+
presence_penalty: 1,
|
|
120
|
+
...completionParams
|
|
121
|
+
};
|
|
122
|
+
this._systemMessage = systemMessage;
|
|
123
|
+
if (this._systemMessage === void 0) {
|
|
124
|
+
const currentDate = new Date().toISOString().split("T")[0];
|
|
125
|
+
this._systemMessage = `You are ChatGPT, a large language model trained by OpenAI. Answer as concisely as possible.
|
|
126
|
+
Knowledge cutoff: 2021-09-01
|
|
127
|
+
Current date: ${currentDate}`;
|
|
128
|
+
}
|
|
129
|
+
this._maxModelTokens = maxModelTokens;
|
|
130
|
+
this._maxResponseTokens = maxResponseTokens;
|
|
131
|
+
this._getMessageById = getMessageById ?? this._defaultGetMessageById;
|
|
132
|
+
this._upsertMessage = upsertMessage ?? this._defaultUpsertMessage;
|
|
133
|
+
if (messageStore) {
|
|
134
|
+
this._messageStore = messageStore;
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
this._messageStore = new keyv_1.default({
|
|
138
|
+
store: new quick_lru_1.default({ maxSize: 1e4 })
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
if (!this._apiKey) {
|
|
142
|
+
throw new Error("OpenAI missing required apiKey");
|
|
143
|
+
}
|
|
144
|
+
if (!this._fetch) {
|
|
145
|
+
throw new Error("Invalid environment; fetch is not defined");
|
|
146
|
+
}
|
|
147
|
+
if (typeof this._fetch !== "function") {
|
|
148
|
+
throw new Error("Invalid \"fetch\" is not a function");
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
async sendMessage(text, opts = {}) {
|
|
152
|
+
const { parentMessageId, messageId = (0, uuid_1.v4)(), timeoutMs, onProgress, stream = !!onProgress, completionParams, conversationId } = opts;
|
|
153
|
+
let { abortSignal } = opts;
|
|
154
|
+
let abortController = null;
|
|
155
|
+
if (timeoutMs && !abortSignal) {
|
|
156
|
+
abortController = new AbortController();
|
|
157
|
+
abortSignal = abortController.signal;
|
|
158
|
+
}
|
|
159
|
+
const latestQuestion = {
|
|
160
|
+
role: "user",
|
|
161
|
+
id: messageId,
|
|
162
|
+
conversationId,
|
|
163
|
+
parentMessageId,
|
|
164
|
+
text
|
|
165
|
+
};
|
|
166
|
+
const { messages, maxTokens, numTokens } = await this._buildMessages(text, opts);
|
|
167
|
+
const result = {
|
|
168
|
+
role: "assistant",
|
|
169
|
+
id: (0, uuid_1.v4)(),
|
|
170
|
+
conversationId,
|
|
171
|
+
parentMessageId: messageId,
|
|
172
|
+
text: ""
|
|
173
|
+
};
|
|
174
|
+
const responseP = new Promise(async (resolve, reject) => {
|
|
175
|
+
let _a, _b;
|
|
176
|
+
const url = `${this._apiBaseUrl}/chat/completions`;
|
|
177
|
+
const headers = {
|
|
178
|
+
"Content-Type": "application/json",
|
|
179
|
+
Authorization: `Bearer ${this._apiKey}`
|
|
180
|
+
};
|
|
181
|
+
const body = {
|
|
182
|
+
max_tokens: maxTokens,
|
|
183
|
+
...this._completionParams,
|
|
184
|
+
...completionParams,
|
|
185
|
+
messages,
|
|
186
|
+
stream
|
|
187
|
+
};
|
|
188
|
+
if (this._apiOrg) {
|
|
189
|
+
headers["OpenAI-Organization"] = this._apiOrg;
|
|
190
|
+
}
|
|
191
|
+
if (this._debug) {
|
|
192
|
+
console.log(`sendMessage (${numTokens} tokens)`, body);
|
|
193
|
+
}
|
|
194
|
+
if (stream) {
|
|
195
|
+
fetchSSE(url, {
|
|
196
|
+
method: "POST",
|
|
197
|
+
headers,
|
|
198
|
+
body: JSON.stringify(body),
|
|
199
|
+
signal: abortSignal,
|
|
200
|
+
onMessage: (data) => {
|
|
201
|
+
let _a2;
|
|
202
|
+
if (data === "[DONE]") {
|
|
203
|
+
result.text = result.text.trim();
|
|
204
|
+
return resolve(result);
|
|
205
|
+
}
|
|
206
|
+
if (data && isJsonString(data)) {
|
|
207
|
+
try {
|
|
208
|
+
const response = JSON.parse(data);
|
|
209
|
+
if (response.id) {
|
|
210
|
+
result.id = response.id;
|
|
211
|
+
}
|
|
212
|
+
if ((_a2 = response.choices) == null ? void 0 : _a2.length) {
|
|
213
|
+
const delta = response.choices[0].delta;
|
|
214
|
+
result.delta = delta.content;
|
|
215
|
+
if (delta.content)
|
|
216
|
+
result.text += delta.content;
|
|
217
|
+
if (delta.role) {
|
|
218
|
+
result.role = delta.role;
|
|
219
|
+
}
|
|
220
|
+
result.detail = response;
|
|
221
|
+
onProgress == null ? void 0 : onProgress(result);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
catch (err) {
|
|
225
|
+
console.warn("OpenAI stream SEE event unexpected error", err);
|
|
226
|
+
return reject(err);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}, this._fetch).catch(reject);
|
|
231
|
+
}
|
|
232
|
+
else {
|
|
233
|
+
try {
|
|
234
|
+
const res = await this._fetch(url, {
|
|
235
|
+
method: "POST",
|
|
236
|
+
headers,
|
|
237
|
+
body: JSON.stringify(body),
|
|
238
|
+
signal: abortSignal
|
|
239
|
+
});
|
|
240
|
+
if (!res.ok) {
|
|
241
|
+
const reason = await res.text();
|
|
242
|
+
const msg = `OpenAI error ${res.status || res.statusText}: ${reason}`;
|
|
243
|
+
const error = new ChatGPTError(msg, { cause: res });
|
|
244
|
+
error.statusCode = res.status;
|
|
245
|
+
error.statusText = res.statusText;
|
|
246
|
+
return reject(error);
|
|
247
|
+
}
|
|
248
|
+
const response = await res.json();
|
|
249
|
+
if (this._debug) {
|
|
250
|
+
console.log(response);
|
|
251
|
+
}
|
|
252
|
+
if (response == null ? void 0 : response.id) {
|
|
253
|
+
result.id = response.id;
|
|
254
|
+
}
|
|
255
|
+
if ((_a = response == null ? void 0 : response.choices) == null ? void 0 : _a.length) {
|
|
256
|
+
const message2 = response.choices[0].message;
|
|
257
|
+
result.text = message2.content;
|
|
258
|
+
if (message2.role) {
|
|
259
|
+
result.role = message2.role;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
else {
|
|
263
|
+
const res2 = response;
|
|
264
|
+
return reject(new Error(`OpenAI error: ${((_b = res2 == null ? void 0 : res2.detail) == null ? void 0 : _b.message) || (res2 == null ? void 0 : res2.detail) || "unknown"}`));
|
|
265
|
+
}
|
|
266
|
+
result.detail = response;
|
|
267
|
+
return resolve(result);
|
|
268
|
+
}
|
|
269
|
+
catch (err) {
|
|
270
|
+
return reject(err);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}).then(async (message2) => {
|
|
274
|
+
if (message2.detail && !message2.detail.usage) {
|
|
275
|
+
try {
|
|
276
|
+
const promptTokens = numTokens;
|
|
277
|
+
const completionTokens = await this._getTokenCount(message2.text);
|
|
278
|
+
message2.detail.usage = {
|
|
279
|
+
prompt_tokens: promptTokens,
|
|
280
|
+
completion_tokens: completionTokens,
|
|
281
|
+
total_tokens: promptTokens + completionTokens,
|
|
282
|
+
estimated: true
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
catch (err) {
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
return Promise.all([
|
|
289
|
+
this._upsertMessage(latestQuestion),
|
|
290
|
+
this._upsertMessage(message2)
|
|
291
|
+
]).then(() => message2);
|
|
292
|
+
});
|
|
293
|
+
if (timeoutMs) {
|
|
294
|
+
if (abortController) {
|
|
295
|
+
responseP.cancel = () => {
|
|
296
|
+
abortController.abort();
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
return (0, pTimeout_js_1.default)(responseP, {
|
|
300
|
+
milliseconds: timeoutMs,
|
|
301
|
+
message: "OpenAI timed out waiting for response"
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
else {
|
|
305
|
+
return responseP;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
get apiKey() {
|
|
309
|
+
return this._apiKey;
|
|
310
|
+
}
|
|
311
|
+
set apiKey(apiKey) {
|
|
312
|
+
this._apiKey = apiKey;
|
|
313
|
+
}
|
|
314
|
+
get apiOrg() {
|
|
315
|
+
return this._apiOrg;
|
|
316
|
+
}
|
|
317
|
+
set apiOrg(apiOrg) {
|
|
318
|
+
this._apiOrg = apiOrg;
|
|
319
|
+
}
|
|
320
|
+
async _buildMessages(text, opts) {
|
|
321
|
+
const { systemMessage = this._systemMessage } = opts;
|
|
322
|
+
let { parentMessageId } = opts;
|
|
323
|
+
const userLabel = USER_LABEL_DEFAULT;
|
|
324
|
+
const assistantLabel = ASSISTANT_LABEL_DEFAULT;
|
|
325
|
+
const maxNumTokens = this._maxModelTokens - this._maxResponseTokens;
|
|
326
|
+
let messages = [];
|
|
327
|
+
if (systemMessage) {
|
|
328
|
+
messages.push({
|
|
329
|
+
role: "system",
|
|
330
|
+
content: systemMessage
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
const systemMessageOffset = messages.length;
|
|
334
|
+
let nextMessages = text ? messages.concat([
|
|
335
|
+
{
|
|
336
|
+
role: "user",
|
|
337
|
+
content: text,
|
|
338
|
+
name: opts.name
|
|
339
|
+
}
|
|
340
|
+
]) : messages;
|
|
341
|
+
let numTokens = 0;
|
|
342
|
+
do {
|
|
343
|
+
const prompt = nextMessages.reduce((prompt2, message) => {
|
|
344
|
+
switch (message.role) {
|
|
345
|
+
case "system":
|
|
346
|
+
return prompt2.concat([`Instructions:
|
|
347
|
+
${message.content}`]);
|
|
348
|
+
case "user":
|
|
349
|
+
return prompt2.concat([`${userLabel}:
|
|
350
|
+
${message.content}`]);
|
|
351
|
+
default:
|
|
352
|
+
return prompt2.concat([`${assistantLabel}:
|
|
353
|
+
${message.content}`]);
|
|
354
|
+
}
|
|
355
|
+
}, []).join("\n\n");
|
|
356
|
+
const nextNumTokensEstimate = await this._getTokenCount(prompt);
|
|
357
|
+
const isValidPrompt = nextNumTokensEstimate <= maxNumTokens;
|
|
358
|
+
if (prompt && !isValidPrompt) {
|
|
359
|
+
break;
|
|
360
|
+
}
|
|
361
|
+
messages = nextMessages;
|
|
362
|
+
numTokens = nextNumTokensEstimate;
|
|
363
|
+
if (!isValidPrompt) {
|
|
364
|
+
break;
|
|
365
|
+
}
|
|
366
|
+
if (!parentMessageId) {
|
|
367
|
+
break;
|
|
368
|
+
}
|
|
369
|
+
const parentMessage = await this._getMessageById(parentMessageId);
|
|
370
|
+
if (!parentMessage) {
|
|
371
|
+
break;
|
|
372
|
+
}
|
|
373
|
+
const parentMessageRole = parentMessage.role || "user";
|
|
374
|
+
nextMessages = nextMessages.slice(0, systemMessageOffset).concat([
|
|
375
|
+
{
|
|
376
|
+
role: parentMessageRole,
|
|
377
|
+
content: parentMessage.text,
|
|
378
|
+
name: parentMessage.name
|
|
379
|
+
},
|
|
380
|
+
...nextMessages.slice(systemMessageOffset)
|
|
381
|
+
]);
|
|
382
|
+
parentMessageId = parentMessage.parentMessageId;
|
|
383
|
+
} while (true);
|
|
384
|
+
const maxTokens = Math.max(1, Math.min(this._maxModelTokens - numTokens, this._maxResponseTokens));
|
|
385
|
+
return { messages, maxTokens, numTokens };
|
|
386
|
+
}
|
|
387
|
+
async _getTokenCount(text) {
|
|
388
|
+
text = text.replace(/<\|endoftext\|>/g, "");
|
|
389
|
+
return encode(text).length;
|
|
390
|
+
}
|
|
391
|
+
async _defaultGetMessageById(id) {
|
|
392
|
+
return await this._messageStore.get(id);
|
|
393
|
+
}
|
|
394
|
+
async _defaultUpsertMessage(message) {
|
|
395
|
+
await this._messageStore.set(message.id, message);
|
|
396
|
+
}
|
|
397
|
+
};
|
|
398
|
+
exports.ChatGPTAPI = ChatGPTAPI;
|
|
399
|
+
let uuidv4Re = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
400
|
+
function isValidUUIDv4(str) {
|
|
401
|
+
return str && uuidv4Re.test(str);
|
|
402
|
+
}
|
|
403
|
+
function isJsonString(str) {
|
|
404
|
+
try {
|
|
405
|
+
JSON.parse(str);
|
|
406
|
+
}
|
|
407
|
+
catch (e) {
|
|
408
|
+
return false;
|
|
409
|
+
}
|
|
410
|
+
return true;
|
|
411
|
+
}
|
|
412
|
+
let ChatGPTUnofficialProxyAPI = class {
|
|
413
|
+
/**
|
|
414
|
+
* @param fetch - Optional override for the `fetch` implementation to use. Defaults to the global `fetch` function.
|
|
415
|
+
*/
|
|
416
|
+
constructor(opts) {
|
|
417
|
+
const { accessToken, apiReverseProxyUrl = "https://bypass.duti.tech/api/conversation", model = "text-davinci-002-render-sha", debug = false, headers, fetch: fetch2 = fetch } = opts;
|
|
418
|
+
this._accessToken = accessToken;
|
|
419
|
+
this._apiReverseProxyUrl = apiReverseProxyUrl;
|
|
420
|
+
this._debug = !!debug;
|
|
421
|
+
this._model = model;
|
|
422
|
+
this._fetch = fetch2;
|
|
423
|
+
this._headers = headers;
|
|
424
|
+
if (!this._accessToken) {
|
|
425
|
+
throw new Error("ChatGPT invalid accessToken");
|
|
426
|
+
}
|
|
427
|
+
if (!this._fetch) {
|
|
428
|
+
throw new Error("Invalid environment; fetch is not defined");
|
|
429
|
+
}
|
|
430
|
+
if (typeof this._fetch !== "function") {
|
|
431
|
+
throw new Error("Invalid \"fetch\" is not a function");
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
get accessToken() {
|
|
435
|
+
return this._accessToken;
|
|
436
|
+
}
|
|
437
|
+
set accessToken(value) {
|
|
438
|
+
this._accessToken = value;
|
|
439
|
+
}
|
|
440
|
+
async sendMessage(text, opts = {}) {
|
|
441
|
+
if (!!opts.conversationId !== !!opts.parentMessageId) {
|
|
442
|
+
throw new Error("ChatGPTUnofficialProxyAPI.sendMessage: conversationId and parentMessageId must both be set or both be undefined");
|
|
443
|
+
}
|
|
444
|
+
if (opts.conversationId && !isValidUUIDv4(opts.conversationId)) {
|
|
445
|
+
throw new Error("ChatGPTUnofficialProxyAPI.sendMessage: conversationId is not a valid v4 UUID");
|
|
446
|
+
}
|
|
447
|
+
if (opts.parentMessageId && !isValidUUIDv4(opts.parentMessageId)) {
|
|
448
|
+
throw new Error("ChatGPTUnofficialProxyAPI.sendMessage: parentMessageId is not a valid v4 UUID");
|
|
449
|
+
}
|
|
450
|
+
if (opts.messageId && !isValidUUIDv4(opts.messageId)) {
|
|
451
|
+
throw new Error("ChatGPTUnofficialProxyAPI.sendMessage: messageId is not a valid v4 UUID");
|
|
452
|
+
}
|
|
453
|
+
const { conversationId, parentMessageId = (0, uuid_1.v4)(), messageId = (0, uuid_1.v4)(), action = "next", timeoutMs, onProgress } = opts;
|
|
454
|
+
let { abortSignal } = opts;
|
|
455
|
+
let abortController = null;
|
|
456
|
+
if (timeoutMs && !abortSignal) {
|
|
457
|
+
abortController = new AbortController();
|
|
458
|
+
abortSignal = abortController.signal;
|
|
459
|
+
}
|
|
460
|
+
const body = {
|
|
461
|
+
action,
|
|
462
|
+
messages: [
|
|
463
|
+
{
|
|
464
|
+
id: messageId,
|
|
465
|
+
role: "user",
|
|
466
|
+
content: {
|
|
467
|
+
content_type: "text",
|
|
468
|
+
parts: [text]
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
],
|
|
472
|
+
model: this._model,
|
|
473
|
+
parent_message_id: parentMessageId
|
|
474
|
+
};
|
|
475
|
+
if (conversationId) {
|
|
476
|
+
body.conversation_id = conversationId;
|
|
477
|
+
}
|
|
478
|
+
const result = {
|
|
479
|
+
role: "assistant",
|
|
480
|
+
id: (0, uuid_1.v4)(),
|
|
481
|
+
parentMessageId: messageId,
|
|
482
|
+
conversationId,
|
|
483
|
+
text: ""
|
|
484
|
+
};
|
|
485
|
+
const responseP = new Promise((resolve, reject) => {
|
|
486
|
+
const url = this._apiReverseProxyUrl;
|
|
487
|
+
const headers = {
|
|
488
|
+
...this._headers,
|
|
489
|
+
Authorization: `Bearer ${this._accessToken}`,
|
|
490
|
+
Accept: "text/event-stream",
|
|
491
|
+
"Content-Type": "application/json"
|
|
492
|
+
};
|
|
493
|
+
if (this._debug) {
|
|
494
|
+
console.log("POST", url, { body, headers });
|
|
495
|
+
}
|
|
496
|
+
fetchSSE(url, {
|
|
497
|
+
method: "POST",
|
|
498
|
+
headers,
|
|
499
|
+
body: JSON.stringify(body),
|
|
500
|
+
signal: abortSignal,
|
|
501
|
+
onMessage: (data) => {
|
|
502
|
+
let _a, _b, _c;
|
|
503
|
+
if (data === "[DONE]") {
|
|
504
|
+
return resolve(result);
|
|
505
|
+
}
|
|
506
|
+
if (data && isJsonString(data)) {
|
|
507
|
+
try {
|
|
508
|
+
const convoResponseEvent = JSON.parse(data);
|
|
509
|
+
if (convoResponseEvent.conversation_id) {
|
|
510
|
+
result.conversationId = convoResponseEvent.conversation_id;
|
|
511
|
+
}
|
|
512
|
+
if ((_a = convoResponseEvent.message) == null ? void 0 : _a.id) {
|
|
513
|
+
result.id = convoResponseEvent.message.id;
|
|
514
|
+
}
|
|
515
|
+
const message = convoResponseEvent.message;
|
|
516
|
+
if (message) {
|
|
517
|
+
let text2 = (_c = (_b = message.content) == null ? void 0 : _b.parts) == null ? void 0 : _c[0];
|
|
518
|
+
if (text2) {
|
|
519
|
+
result.text = text2;
|
|
520
|
+
if (onProgress) {
|
|
521
|
+
onProgress(result);
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
catch (err) {
|
|
527
|
+
reject(err);
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
},
|
|
531
|
+
onError: (err) => {
|
|
532
|
+
reject(err);
|
|
533
|
+
}
|
|
534
|
+
}, this._fetch).catch((err) => {
|
|
535
|
+
const errMessageL = err.toString().toLowerCase();
|
|
536
|
+
if (result.text && (errMessageL === "error: typeerror: terminated" || errMessageL === "typeerror: terminated")) {
|
|
537
|
+
return resolve(result);
|
|
538
|
+
}
|
|
539
|
+
else {
|
|
540
|
+
return reject(err);
|
|
541
|
+
}
|
|
542
|
+
});
|
|
543
|
+
});
|
|
544
|
+
if (timeoutMs) {
|
|
545
|
+
if (abortController) {
|
|
546
|
+
responseP.cancel = () => {
|
|
547
|
+
abortController.abort();
|
|
548
|
+
};
|
|
549
|
+
}
|
|
550
|
+
return (0, pTimeout_js_1.default)(responseP, {
|
|
551
|
+
milliseconds: timeoutMs,
|
|
552
|
+
message: "ChatGPT timed out waiting for response"
|
|
553
|
+
});
|
|
554
|
+
}
|
|
555
|
+
else {
|
|
556
|
+
return responseP;
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
};
|
|
560
|
+
exports.ChatGPTUnofficialProxyAPI = ChatGPTUnofficialProxyAPI;
|
|
561
|
+
//# sourceMappingURL=chatGPT.js.map
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export default function pTimeout(promise: any, options: any): Promise<any>;
|
|
2
|
+
export class TimeoutError extends Error {
|
|
3
|
+
constructor(message: any);
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
An error to be thrown when the request is aborted by AbortController.
|
|
7
|
+
DOMException is thrown instead of this Error when DOMException is available.
|
|
8
|
+
*/
|
|
9
|
+
export class AbortError extends Error {
|
|
10
|
+
constructor(message: any);
|
|
11
|
+
message: any;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=pTimeout.d.ts.map
|