@leikeduntech/leiai-js 4.0.1 → 4.0.3

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/build/index.js CHANGED
@@ -1,1284 +1,1287 @@
1
- // src/chatgpt-api.ts
2
- import { Spark } from "@leikeduntech/spark-nodejs";
3
- import Keyv from "keyv";
4
- import pTimeout from "p-timeout";
5
- import QuickLRU from "quick-lru";
6
- import { v4 as uuidv4 } from "uuid";
7
-
8
- // src/tokenizer.ts
9
- import { getEncoding } from "js-tiktoken";
10
- var tokenizer = getEncoding("cl100k_base");
11
- function encode(input) {
12
- return new Uint32Array(tokenizer.encode(input));
13
- }
14
-
15
- // src/types.ts
16
- var ChatGPTError = class extends Error {
17
- };
18
- var openai;
19
- ((openai2) => {
20
- })(openai || (openai = {}));
21
-
22
- // src/fetch.ts
23
- var fetch = globalThis.fetch;
24
-
25
- // src/fetch-sse.ts
26
- import { createParser } from "eventsource-parser";
27
-
28
- // src/stream-async-iterable.ts
29
- async function* streamAsyncIterable(stream) {
30
- const reader = stream.getReader();
31
- try {
32
- while (true) {
33
- const { done, value } = await reader.read();
34
- if (done) {
35
- return;
36
- }
37
- yield value;
38
- }
39
- } finally {
40
- reader.releaseLock();
41
- }
42
- }
43
-
44
- // src/fetch-sse.ts
45
- async function fetchSSE(url, options, fetch2 = fetch, manufacturer = "OpenAI") {
46
- const { onMessage, onError, ...fetchOptions } = options;
47
- const res = await fetch2(url, fetchOptions);
48
- if (!res.ok) {
49
- let reason;
50
- try {
51
- reason = await res.text();
52
- } catch (err) {
53
- reason = res.statusText;
54
- }
55
- const msg = `${manufacturer} error ${res.status}: ${reason}`;
56
- const error = new ChatGPTError(msg, { cause: res });
57
- error.statusCode = res.status;
58
- error.statusText = res.statusText;
59
- throw error;
60
- }
61
- const parser = createParser((event) => {
62
- if (event.type === "event") {
63
- if (manufacturer.toLowerCase() === "zhipu") {
64
- onMessage(JSON.stringify(event));
65
- } else {
66
- onMessage(event.data);
67
- }
68
- }
69
- });
70
- const feed = (chunk) => {
71
- var _a;
72
- let response = null;
73
- try {
74
- response = JSON.parse(chunk);
75
- } catch {
76
- }
77
- if (((_a = response == null ? void 0 : response.detail) == null ? void 0 : _a.type) === "invalid_request_error") {
78
- const msg = `${manufacturer} error ${response.detail.message}: ${response.detail.code} (${response.detail.type})`;
79
- const error = new ChatGPTError(msg, { cause: response });
80
- error.statusCode = response.detail.code;
81
- error.statusText = response.detail.message;
82
- if (onError) {
83
- onError(error);
84
- } else {
85
- console.error(error);
86
- }
87
- return;
88
- }
89
- parser.feed(chunk);
90
- };
91
- if (!res.body.getReader) {
92
- const body = res.body;
93
- if (!body.on || !body.read) {
94
- throw new ChatGPTError('unsupported "fetch" implementation');
95
- }
96
- body.on("readable", () => {
97
- let chunk;
98
- while (null !== (chunk = body.read())) {
99
- feed(chunk.toString());
100
- }
101
- });
102
- } else {
103
- for await (const chunk of streamAsyncIterable(res.body)) {
104
- const str = new TextDecoder().decode(chunk);
105
- feed(str);
106
- }
107
- }
108
- }
109
-
110
- // src/utils.ts
111
- import CryptoJS from "crypto-js";
112
- var 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;
113
- function isValidUUIDv4(str) {
114
- return str && uuidv4Re.test(str);
115
- }
116
- function convertArrayToString(arr) {
117
- let result = "[";
118
- for (let i = 0; i < arr.length; i++) {
119
- const obj = arr[i];
120
- const keys = Object.keys(obj);
121
- result += "{";
122
- for (let j = 0; j < keys.length; j++) {
123
- const key = keys[j];
124
- const value = obj[key];
125
- result += '"' + key + '":' + (typeof value === "string" ? '"' + value + '"' : value) + ",";
126
- }
127
- result = result.slice(0, -1);
128
- result += "},";
129
- }
130
- result = result.slice(0, -1);
131
- result += "]";
132
- return result;
133
- }
134
- function signTencentHunyuan(bodyData, url, keyList) {
135
- const sortedObj = {};
136
- Object.keys(bodyData).sort().forEach((key) => {
137
- sortedObj[key] = bodyData[key];
138
- });
139
- let signStr = "";
140
- for (let key in sortedObj) {
141
- if (signStr) {
142
- if (typeof sortedObj[key] === "object") {
143
- signStr += `&${key}=${convertArrayToString(sortedObj[key])}`;
144
- } else {
145
- signStr += `&${key}=${sortedObj[key]}`;
146
- }
147
- } else {
148
- signStr += `${key}=${sortedObj[key]}`;
149
- }
150
- }
151
- signStr = `${url.replace("https://", "")}?${signStr}`;
152
- const hmac = CryptoJS.HmacSHA1(signStr, keyList[2]);
153
- const signBase64 = CryptoJS.enc.Base64.stringify(hmac);
154
- return signBase64;
155
- }
156
- function isPositiveNumber(str) {
157
- return /^[1-9]\d*$/.test(str);
158
- }
159
-
160
- // src/chatgpt-api.ts
161
- var CHATGPT_MODEL = "gpt-3.5-turbo";
162
- var USER_LABEL_DEFAULT = "User";
163
- var ASSISTANT_LABEL_DEFAULT = "ChatGPT";
164
- var ChatGPTAPI = class {
165
- /**
166
- * Creates a new client wrapper around OpenAI's chat completion API, mimicing the official ChatGPT webapp's functionality as closely as possible.
167
- *
168
- * @param apiKey - OpenAI API key (required).
169
- * @param apiOrg - Optional OpenAI API organization (optional).
170
- * @param apiBaseUrl - Optional override for the OpenAI API base URL.
171
- * @param debug - Optional enables logging debugging info to stdout.
172
- * @param completionParams - Param overrides to send to the [OpenAI chat completion API](https://platform.openai.com/docs/api-reference/chat/create). Options like `temperature` and `presence_penalty` can be tweaked to change the personality of the assistant.
173
- * @param maxModelTokens - Optional override for the maximum number of tokens allowed by the model's context. Defaults to 4096.
174
- * @param maxResponseTokens - Optional override for the minimum number of tokens allowed for the model's response. Defaults to 1000.
175
- * @param messageStore - Optional [Keyv](https://github.com/jaredwray/keyv) store to persist chat messages to. If not provided, messages will be lost when the process exits.
176
- * @param getMessageById - Optional function to retrieve a message by its ID. If not provided, the default implementation will be used (using an in-memory `messageStore`).
177
- * @param upsertMessage - Optional function to insert or update a message. If not provided, the default implementation will be used (using an in-memory `messageStore`).
178
- * @param fetch - Optional override for the `fetch` implementation to use. Defaults to the global `fetch` function.
179
- */
180
- constructor(opts) {
181
- const {
182
- manufacturer = "OpenAI",
183
- apiKey,
184
- apiOrg,
185
- apiBaseUrl = "https://api.openai.com/v1",
186
- debug = false,
187
- messageStore,
188
- completionParams,
189
- systemMessage,
190
- maxModelTokens = 0,
191
- maxResponseTokens = -1e7,
192
- getMessageById,
193
- upsertMessage,
194
- fetch: fetch2 = fetch
195
- } = opts;
196
- this._manufacturer = manufacturer;
197
- this._apiKey = apiKey;
198
- this._apiOrg = apiOrg;
199
- this._apiBaseUrl = apiBaseUrl;
200
- this._debug = !!debug;
201
- this._fetch = fetch2;
202
- this._completionParams = {
203
- model: CHATGPT_MODEL,
204
- ...completionParams
205
- };
206
- this._systemMessage = systemMessage;
207
- this._maxModelTokens = maxModelTokens;
208
- this._maxResponseTokens = maxResponseTokens;
209
- this._getMessageById = getMessageById ?? this._defaultGetMessageById;
210
- this._upsertMessage = upsertMessage ?? this._defaultUpsertMessage;
211
- if (messageStore) {
212
- this._messageStore = messageStore;
213
- } else {
214
- this._messageStore = new Keyv({
215
- store: new QuickLRU({ maxSize: 1e4 })
216
- });
217
- }
218
- if (!this._apiKey) {
219
- throw new Error(`${this._manufacturer} missing required apiKey`);
220
- }
221
- if (!this._fetch) {
222
- throw new Error("Invalid environment; fetch is not defined");
223
- }
224
- if (typeof this._fetch !== "function") {
225
- throw new Error('Invalid "fetch" is not a function');
226
- }
227
- }
228
- pluginListMap(pluginList) {
229
- const list = {
230
- "dall-e-3": {
231
- name: "DallE3Fun",
232
- description: "\u4F7F\u7528DALL-E3\u6A21\u578B\u6839\u636E\u7528\u6237\u63CF\u8FF0\u63D0\u793A\u521B\u4F5C\u4E00\u5F20\u65B0\u7684\u56FE\u7247"
233
- },
234
- "dall-e-2": {
235
- name: "DallE2Fun",
236
- description: "\u4F7F\u7528DALL-E2\u6A21\u578B\u628A\u7528\u6237\u63D0\u4F9B\u7684\u56FE\u7247\u548C\u6839\u636E\u63D0\u793A\u8BCD\u91CD\u65B0\u753B\u56FE\u4FEE\u6539\u56FE\u7247\u7F16\u8F91\u56FE\u7247\u66FF\u6362\u56FE\u7247\u90E8\u4EFD\u5185\u5BB9\u6362\u6539\u91CD\u753B\u56FE\u7247"
237
- }
238
- };
239
- return list[pluginList];
240
- }
241
- /**
242
- * Sends a message to the OpenAI chat completions endpoint, waits for the response
243
- * to resolve, and returns the response.
244
- *
245
- * If you want your response to have historical context, you must provide a valid `parentMessageId`.
246
- *
247
- * If you want to receive a stream of partial responses, use `opts.onProgress`.
248
- *
249
- * Set `debug: true` in the `ChatGPTAPI` constructor to log more info on the full prompt sent to the OpenAI chat completions API. You can override the `systemMessage` in `opts` to customize the assistant's instructions.
250
- *
251
- * @param message - The prompt message to send
252
- * @param opts.parentMessageId - Optional ID of the previous message in the conversation (defaults to `undefined`)
253
- * @param opts.conversationId - Optional ID of the conversation (defaults to `undefined`)
254
- * @param opts.messageId - Optional ID of the message to send (defaults to a random UUID)
255
- * @param opts.systemMessage - Optional override for the chat "system message" which acts as instructions to the model (defaults to the ChatGPT system message)
256
- * @param opts.timeoutMs - Optional timeout in milliseconds (defaults to no timeout)
257
- * @param opts.onProgress - Optional callback which will be invoked every time the partial response is updated
258
- * @param opts.abortSignal - Optional callback used to abort the underlying `fetch` call using an [AbortController](https://developer.mozilla.org/en-US/docs/Web/API/AbortController)
259
- * @param completionParams - Optional overrides to send to the [OpenAI chat completion API](https://platform.openai.com/docs/api-reference/chat/create). Options like `temperature` and `presence_penalty` can be tweaked to change the personality of the assistant.
260
- *
261
- * @returns The response from ChatGPT
262
- */
263
- async sendMessage(text, opts = {}, pluginParams) {
264
- let parentMsg;
265
- if (pluginParams) {
266
- parentMsg = await this._getMessageById(pluginParams.assistant_res.id);
267
- opts.parentMessageId = parentMsg.id;
268
- }
269
- let {
270
- parentMessageId,
271
- messageId = uuidv4(),
272
- timeoutMs,
273
- onProgress,
274
- stream = onProgress ? true : false,
275
- completionParams,
276
- conversationId
277
- } = opts;
278
- let { abortSignal } = opts;
279
- let abortController = null;
280
- if (timeoutMs && !abortSignal) {
281
- abortController = new AbortController();
282
- abortSignal = abortController.signal;
283
- }
284
- let message = {
285
- role: "user",
286
- id: messageId,
287
- conversationId,
288
- parentMessageId,
289
- text
290
- };
291
- if (this._debug)
292
- console.log("\u8DDF\u8E2A1, \u8D85\u65F6\u65F6\u95F4ms", timeoutMs);
293
- let latestQuestion = message, last_assistant_res_message = null, last_assistant_res = null, last_plugin_res = null;
294
- if (pluginParams) {
295
- last_assistant_res_message = pluginParams.assistant_res.detail.choices[0];
296
- last_assistant_res = {
297
- role: last_assistant_res_message.message.role,
298
- id: parentMsg.id,
299
- conversationId,
300
- parentMessageId: parentMsg.parentMessageId,
301
- text,
302
- content: last_assistant_res_message
303
- };
304
- let r = "tool";
305
- if (this._manufacturer.toLowerCase() === "azure") {
306
- r = "function";
307
- }
308
- last_plugin_res = {
309
- role: r,
310
- id: messageId,
311
- name: last_assistant_res_message.message.tool_calls[0].function.name,
312
- conversationId,
313
- parentMessageId: pluginParams.assistant_res.id,
314
- text,
315
- content: pluginParams.plugin_res,
316
- tool_call_id: last_assistant_res_message.message.tool_calls[0].id
317
- };
318
- await this._upsertMessage(last_assistant_res);
319
- latestQuestion = last_plugin_res;
320
- }
321
- if (this._debug)
322
- console.log("\u8DDF\u8E2A2");
323
- const { messages, maxTokens, numTokens, errorMessage, objText } = await this._buildMessages(text, opts, last_plugin_res);
324
- latestQuestion.text = objText;
325
- if (this._debug)
326
- console.log(
327
- `typeof errorMessage ${typeof errorMessage},numTokens:${numTokens}, _maxModelTokens:${this._maxModelTokens},errorMessage: ${errorMessage}`
328
- );
329
- if (errorMessage !== "" && errorMessage !== null && errorMessage.length > 0) {
330
- return new Promise((resolve, reject) => {
331
- const errMsg = {
332
- manufacturer: this._manufacturer,
333
- statusCode: 400,
334
- message: errorMessage
335
- };
336
- return reject(errMsg);
337
- });
338
- }
339
- const result = {
340
- role: "assistant",
341
- id: uuidv4(),
342
- conversationId,
343
- parentMessageId: messageId,
344
- text: "",
345
- result: "",
346
- detail: { usage: null }
347
- };
348
- const responseP = new Promise(
349
- async (resolve, reject) => {
350
- var _a, _b, _c, _d, _e, _f, _g, _h, _i;
351
- let url = `${this._apiBaseUrl}/chat/completions`;
352
- const headers = {
353
- "Content-Type": "application/json",
354
- Authorization: `Bearer ${this._apiKey}`
355
- };
356
- if (this._manufacturer.toLowerCase() === "baidu") {
357
- url = this._apiBaseUrl;
358
- delete headers.Authorization;
359
- } else if (this._manufacturer.toLowerCase() === "aliyun") {
360
- url = this._apiBaseUrl;
361
- if (stream)
362
- headers["X-DashScope-SSE"] = "enable";
363
- } else if (this._manufacturer.toLowerCase() === "zhipu") {
364
- url = this._apiBaseUrl;
365
- headers["Authorization"] = this._apiKey;
366
- if (stream)
367
- headers["accept"] = "text/event-stream";
368
- } else if (this._manufacturer.toLowerCase() === "azure") {
369
- url = this._apiBaseUrl;
370
- headers["api-key"] = this._apiKey;
371
- delete headers.Authorization;
372
- } else if (this._manufacturer.toLowerCase() === "xunfei") {
373
- url = "";
374
- delete headers.Authorization;
375
- } else if (this._manufacturer.toLowerCase() === "chatdoc") {
376
- url = this._apiBaseUrl;
377
- } else if (this._manufacturer.toLocaleLowerCase() === "anthropic") {
378
- url = this._apiBaseUrl;
379
- }
380
- let pluginList;
381
- if (completionParams.pluginList) {
382
- pluginList = completionParams.pluginList;
383
- }
384
- if (typeof completionParams.pluginList !== "undefined")
385
- delete completionParams.pluginList;
386
- if (typeof completionParams.fileList !== "undefined")
387
- delete completionParams.fileList;
388
- let body = {
389
- max_tokens: maxTokens,
390
- ...this._completionParams,
391
- ...completionParams,
392
- messages,
393
- stream
394
- };
395
- if (!isPositiveNumber(maxTokens)) {
396
- delete body.max_tokens;
397
- }
398
- if (this._manufacturer.toLowerCase() === "baidu" && typeof pluginList === "string" && pluginList.indexOf("zhishiku") > -1) {
399
- if (body.model)
400
- delete body.model;
401
- if (body.max_tokens)
402
- delete body.max_tokens;
403
- if (body.temperature)
404
- delete body.temperature;
405
- } else {
406
- if (typeof body.plugins !== void 0)
407
- delete body.plugins;
408
- }
409
- if (["openai", "azure"].indexOf(this._manufacturer.toLowerCase()) > -1) {
410
- switch (pluginList) {
411
- case "dall-e-3":
412
- let tools_key = "tools", tool_choice_key = "tool_choice", funArr = null;
413
- if (this._manufacturer.toLowerCase() === "azure")
414
- tools_key = "functions", tool_choice_key = "function_call";
415
- funArr = [
416
- {
417
- type: "function",
418
- function: {
419
- name: "DallE2Fun",
420
- description: this.pluginListMap(pluginList).description,
421
- parameters: {
422
- type: "object",
423
- properties: {
424
- prompt: {
425
- type: "string",
426
- description: "\u7528\u6237\u5BF9\u9700\u8981\u7F16\u8F91\u7684\u56FE\u7247\u4FEE\u6539\u7684\u63D0\u793A\u5185\u5BB9"
427
- },
428
- image_url: {
429
- type: "string",
430
- description: "\u4ECE\u5BF9\u8BDD\u5386\u53F2\u8BB0\u5F55\u548C\u7528\u6237\u63D0\u793A\u8BCD\u91CC\u5339\u914D\u6700\u8FD1\u4E00\u6B21\u51FA\u73B0\u7684\u4EE5http\u5F00\u5934\u7684\u56FE\u7247\u7684\u94FE\u63A5\u5730\u5740"
431
- }
432
- },
433
- required: ["prompt", "image_url"]
434
- }
435
- }
436
- },
437
- {
438
- type: "function",
439
- function: {
440
- name: "DallE3Fun",
441
- description: this.pluginListMap(pluginList).description,
442
- parameters: {
443
- type: "object",
444
- properties: {
445
- prompt: {
446
- type: "string",
447
- description: "\u7ED8\u56FE\u7684\u63D0\u793A\u8BCD"
448
- }
449
- },
450
- required: ["prompt"]
451
- }
452
- }
453
- }
454
- ];
455
- if (this._manufacturer.toLowerCase() === "azure") {
456
- funArr = funArr.map((item) => {
457
- return item.function;
458
- });
459
- }
460
- body = Object.assign(body, {
461
- [tools_key]: funArr,
462
- [tool_choice_key]: "auto"
463
- });
464
- break;
465
- default:
466
- break;
467
- }
468
- } else if (this._manufacturer.toLowerCase() === "aliyun") {
469
- body = Object.assign(body, {
470
- parameters: { result_format: "message" },
471
- input: { messages }
472
- });
473
- delete body.messages;
474
- } else if (this._manufacturer.toLowerCase() === "zhipu") {
475
- if (completionParams.model === "glm-4") {
476
- } else {
477
- delete body.messages;
478
- body = Object.assign(body, { prompt: messages });
479
- }
480
- } else if (this._manufacturer.toLowerCase() === "tencent") {
481
- url = this._apiBaseUrl;
482
- const timestamp = Math.ceil((/* @__PURE__ */ new Date()).getTime() / 1e3) + 1;
483
- const keyList = this._apiKey.split(".");
484
- body = Object.assign(body, {
485
- app_id: parseInt(keyList[0]),
486
- secret_id: keyList[1],
487
- timestamp,
488
- expired: timestamp + 24 * 60 * 60,
489
- stream: stream ? 1 : 0
490
- });
491
- delete body.model;
492
- delete body.max_tokens;
493
- headers["Authorization"] = signTencentHunyuan(body, url, keyList);
494
- } else if (this._manufacturer.toLowerCase() === "baidu") {
495
- if (pluginList && pluginList.indexOf("zhishiku") > -1) {
496
- let query = messages.splice(messages.length - 1, 1);
497
- body = Object.assign(body, {
498
- query: (_a = query[0]) == null ? void 0 : _a.content,
499
- history: messages
500
- });
501
- delete body.messages;
502
- }
503
- } else if (this._manufacturer.toLowerCase() === "chatdoc") {
504
- let query = messages.splice(messages.length - 1, 1);
505
- body = Object.assign(body, {
506
- upload_id: (_b = completionParams == null ? void 0 : completionParams.extParams) == null ? void 0 : _b.upload_id,
507
- question: (_c = query[0]) == null ? void 0 : _c.content,
508
- history: messages
509
- });
510
- if (body.extParams)
511
- delete body.extParams;
512
- if (body.model)
513
- delete body.model;
514
- if (body.max_tokens)
515
- delete body.max_tokens;
516
- if (body.temperature)
517
- delete body.temperature;
518
- if (body.messages)
519
- delete body.messages;
520
- }
521
- if (this._apiOrg && this._manufacturer.toLowerCase() === "openai") {
522
- headers["OpenAI-Organization"] = this._apiOrg;
523
- }
524
- if (this._debug) {
525
- console.log(`api url ${url}`);
526
- console.log(`api header ${JSON.stringify(headers)}`);
527
- console.log(`sendMessage (${numTokens} tokens) body: `, body);
528
- console.log(
529
- `sendMessage (${numTokens} tokens) message : `,
530
- messages,
531
- typeof messages
532
- );
533
- }
534
- if (this._manufacturer.toLowerCase() === "xunfei") {
535
- const self = this;
536
- const keyList = this._apiKey.split(".");
537
- const options = {
538
- secret: keyList[2],
539
- key: keyList[1],
540
- appid: keyList[0],
541
- temperature: body == null ? void 0 : body.temperature,
542
- useHistory: !!parentMessageId,
543
- chatId: ""
544
- };
545
- if (message == null ? void 0 : message.conversationId)
546
- options.chatId = message == null ? void 0 : message.conversationId;
547
- if (self._debug)
548
- console.log("spark options ", options);
549
- const sparkIns = new Spark(options);
550
- const url2 = sparkIns.chat({
551
- content: messages && JSON.stringify(messages),
552
- // onData 表示分段拿到返回结果
553
- onData({ content, start, end, seq }) {
554
- if (self._debug)
555
- console.log("onData", content, start, end, seq);
556
- result.id = `xunfei-${Math.floor(
557
- Math.random() * 1e7
558
- )}${(/* @__PURE__ */ new Date()).getTime()}`;
559
- result.delta = content;
560
- if (content)
561
- result.text += content;
562
- result.role = "assistant";
563
- onProgress == null ? void 0 : onProgress(result);
564
- },
565
- onEnd({ content, tokens, questionTokens }) {
566
- if (self._debug)
567
- console.log("onEnd", content, tokens, questionTokens);
568
- result.detail = {
569
- usage: {
570
- prompt_tokens: questionTokens,
571
- completion_tokens: tokens,
572
- total_tokens: questionTokens + tokens
573
- }
574
- };
575
- result.text = content.trim();
576
- return resolve(result);
577
- }
578
- });
579
- } else {
580
- if (stream) {
581
- fetchSSE(
582
- url,
583
- {
584
- method: "POST",
585
- headers,
586
- body: JSON.stringify(body),
587
- signal: abortSignal,
588
- onMessage: (data) => {
589
- var _a2, _b2, _c2, _d2, _e2, _f2, _g2, _h2, _i2, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B;
590
- if (data === "[DONE]") {
591
- result.text = result.text.trim();
592
- return resolve(result);
593
- }
594
- try {
595
- const response = JSON.parse(data);
596
- if (this._debug) {
597
- console.log(
598
- `row data ${typeof response} : `,
599
- response,
600
- response == null ? void 0 : response.choices
601
- );
602
- }
603
- if (this._manufacturer.toLowerCase() === "baidu") {
604
- if ((response == null ? void 0 : response.is_end) === true) {
605
- result.text += response.result.trim();
606
- result.detail = response;
607
- return resolve(result);
608
- }
609
- } else if (this._manufacturer.toLowerCase() === "azure") {
610
- if (((_a2 = response.choices[0]) == null ? void 0 : _a2.finish_reason) === "stop") {
611
- result.text = result.text.trim();
612
- return resolve(result);
613
- }
614
- } else if (this._manufacturer.toLowerCase() === "aliyun") {
615
- if (["stop", "length"].indexOf(
616
- (_c2 = (_b2 = response == null ? void 0 : response.output) == null ? void 0 : _b2.choices[0]) == null ? void 0 : _c2.finish_reason
617
- ) > -1) {
618
- result.text = (_f2 = (_e2 = (_d2 = response == null ? void 0 : response.output) == null ? void 0 : _d2.choices[0]) == null ? void 0 : _e2.message) == null ? void 0 : _f2.content.trim();
619
- return resolve(result);
620
- }
621
- } else if (this._manufacturer.toLowerCase() === "zhipu") {
622
- if (completionParams.model === "glm-4") {
623
- const gelResponse = JSON.parse(response.data);
624
- if (((_h2 = (_g2 = gelResponse == null ? void 0 : gelResponse.choices) == null ? void 0 : _g2[0]) == null ? void 0 : _h2.finish_reason) === "stop") {
625
- result.text = result.text.trim();
626
- return resolve(result);
627
- }
628
- } else {
629
- if ((response == null ? void 0 : response.event) === "finish") {
630
- result.text += response == null ? void 0 : response.data.trim();
631
- return resolve(result);
632
- }
633
- }
634
- } else if (this._manufacturer.toLowerCase() === "tencent") {
635
- if (((_i2 = response.choices[0]) == null ? void 0 : _i2.finish_reason) === "stop") {
636
- result.text += (_k = (_j = response == null ? void 0 : response.choices[0]) == null ? void 0 : _j.delta) == null ? void 0 : _k.content.trim();
637
- return resolve(result);
638
- }
639
- } else if (this._manufacturer.toLowerCase() === "chatdoc") {
640
- result.id = `chatdoc-${Math.floor(
641
- Math.random() * 1e7
642
- )}${(/* @__PURE__ */ new Date()).getTime()}`;
643
- if (response == null ? void 0 : response.source_info) {
644
- result.text += response == null ? void 0 : response.answer;
645
- return resolve(result);
646
- }
647
- }
648
- if (this._manufacturer.toLowerCase() === "aliyun") {
649
- if (response == null ? void 0 : response.request_id) {
650
- result.id = response.request_id;
651
- }
652
- } else {
653
- if (response == null ? void 0 : response.id) {
654
- result.id = response.id;
655
- }
656
- }
657
- if (((_l = response.choices) == null ? void 0 : _l.length) && ["openai", "azure", "tencent", "anthropic"].indexOf(
658
- this._manufacturer.toLowerCase()
659
- ) > -1) {
660
- const delta = response.choices[0].delta;
661
- result.delta = "";
662
- if (response.choices[0].finish_reason === "tool_calls") {
663
- result.delta = text;
664
- } else if (delta.content) {
665
- result.delta = delta.content;
666
- }
667
- if (delta == null ? void 0 : delta.content)
668
- result.text += result.delta;
669
- result.role = "assistant";
670
- if (response.choices[0].finish_reason === "tool_calls") {
671
- } else if (delta.role) {
672
- result.role = delta.role;
673
- }
674
- result.detail = response;
675
- onProgress == null ? void 0 : onProgress(result);
676
- } else if ((response == null ? void 0 : response.result) && this._manufacturer.toLowerCase() === "baidu") {
677
- result.delta = response.result;
678
- if (response == null ? void 0 : response.result)
679
- result.text += response.result;
680
- result.role = "assistant";
681
- result.detail = response;
682
- onProgress == null ? void 0 : onProgress(result);
683
- } else if ((response == null ? void 0 : response.output) && this._manufacturer.toLowerCase() === "aliyun") {
684
- response.usage = Object.assign(response.usage, {
685
- prompt_tokens: (_m = response.usage) == null ? void 0 : _m.input_tokens,
686
- completion_tokens: (_n = response.usage) == null ? void 0 : _n.output_tokens,
687
- total_tokens: ((_o = response.usage) == null ? void 0 : _o.input_tokens) + ((_p = response.usage) == null ? void 0 : _p.output_tokens)
688
- });
689
- result.delta = "";
690
- if ((_s = (_r = (_q = response == null ? void 0 : response.output) == null ? void 0 : _q.choices[0]) == null ? void 0 : _r.message) == null ? void 0 : _s.content)
691
- result.text = (_v = (_u = (_t = response == null ? void 0 : response.output) == null ? void 0 : _t.choices[0]) == null ? void 0 : _u.message) == null ? void 0 : _v.content;
692
- result.role = "assistant";
693
- result.detail = response;
694
- onProgress == null ? void 0 : onProgress(result);
695
- } else if ((response == null ? void 0 : response.data) && this._manufacturer.toLowerCase() === "zhipu") {
696
- if (completionParams.model === "glm-4") {
697
- const glmResponse = JSON.parse(response.data);
698
- if (((_x = (_w = glmResponse == null ? void 0 : glmResponse.choices) == null ? void 0 : _w[0]) == null ? void 0 : _x.finish_reason) === "stop") {
699
- response.usage = glmResponse.usage;
700
- }
701
- let data2 = (_z = (_y = glmResponse == null ? void 0 : glmResponse.choices) == null ? void 0 : _y[0]) == null ? void 0 : _z.delta.content;
702
- result.delta = data2;
703
- if (data2) {
704
- result.text += data2;
705
- }
706
- result.role = "assistant";
707
- result.detail = response;
708
- onProgress == null ? void 0 : onProgress(result);
709
- } else {
710
- if (response.event === "finish") {
711
- if ((_A = response == null ? void 0 : response.meta) == null ? void 0 : _A.usage) {
712
- response.usage = (_B = response == null ? void 0 : response.meta) == null ? void 0 : _B.usage;
713
- } else {
714
- response.usage = {
715
- prompt_tokens: 1,
716
- completion_tokens: 1,
717
- total_tokens: 2
718
- };
719
- }
720
- }
721
- result.delta = response.data;
722
- if (response == null ? void 0 : response.data)
723
- result.text += response == null ? void 0 : response.data;
724
- result.role = "assistant";
725
- result.detail = response;
726
- onProgress == null ? void 0 : onProgress(result);
727
- }
728
- } else if ((response == null ? void 0 : response.answer) && this._manufacturer.toLowerCase() === "chatdoc") {
729
- result.delta = response.answer;
730
- if (response == null ? void 0 : response.answer)
731
- result.text += response.answer;
732
- result.role = "assistant";
733
- result.detail = response;
734
- onProgress == null ? void 0 : onProgress(result);
735
- }
736
- } catch (err) {
737
- console.warn(
738
- `${this._manufacturer} stream SEE event unexpected error`,
739
- err
740
- );
741
- return reject(err);
742
- }
743
- }
744
- },
745
- this._fetch,
746
- this._manufacturer
747
- ).catch(reject);
748
- } else {
749
- try {
750
- if (this._debug)
751
- console.log("\u8DDF\u8E2A3");
752
- const res = await this._fetch(url, {
753
- method: "POST",
754
- headers,
755
- body: JSON.stringify(body),
756
- signal: abortSignal
757
- });
758
- if (this._debug)
759
- console.log("\u8DDF\u8E2A4");
760
- if (!res.ok) {
761
- const reason = await res.text();
762
- const msg = `${this._manufacturer} error ${res.status || res.statusText}: ${reason}`;
763
- const error = new ChatGPTError(msg, { cause: res });
764
- error.statusCode = res.status;
765
- error.statusText = res.statusText;
766
- return reject(error);
767
- }
768
- const response = await res.json();
769
- if (this._debug) {
770
- console.log(
771
- `row data ${typeof response} : `,
772
- response,
773
- (response == null ? void 0 : response.choices) && ((_d = response == null ? void 0 : response.choices[0]) == null ? void 0 : _d.message)
774
- );
775
- }
776
- if (this._manufacturer.toLowerCase() === "aliyun") {
777
- if (response == null ? void 0 : response.request_id) {
778
- result.id = response.request_id;
779
- }
780
- } else {
781
- if (response == null ? void 0 : response.id) {
782
- result.id = response.id;
783
- }
784
- }
785
- if (((_e = response == null ? void 0 : response.choices) == null ? void 0 : _e.length) && ["openai", "azure"].indexOf(this._manufacturer.toLowerCase()) > -1) {
786
- const message2 = response.choices[0].message;
787
- result.text = message2.content;
788
- if (message2.role) {
789
- result.role = message2.role;
790
- }
791
- } else if ((response == null ? void 0 : response.result) && this._manufacturer.toLowerCase() === "baidu") {
792
- result.text = response.result;
793
- result.role = "assistant";
794
- } else if (((_f = response == null ? void 0 : response.output) == null ? void 0 : _f.text) && this._manufacturer.toLowerCase() === "aliyun") {
795
- result.text = (_g = response == null ? void 0 : response.output) == null ? void 0 : _g.text;
796
- result.role = "assistant";
797
- } else {
798
- const res2 = response;
799
- return reject(
800
- new Error(
801
- `${this._manufacturer} error: ${((_h = res2 == null ? void 0 : res2.detail) == null ? void 0 : _h.message) || ((_i = res2 == null ? void 0 : res2.detail) == null ? void 0 : _i.error_msg) || (res2 == null ? void 0 : res2.detail) || "unknown"}`
802
- )
803
- );
804
- }
805
- result.detail = response;
806
- if (this._debug)
807
- console.log("\u8DDF\u8E2A5");
808
- return resolve(result);
809
- } catch (err) {
810
- if (this._debug)
811
- console.log("\u8DDF\u8E2A6");
812
- return reject(err);
813
- }
814
- }
815
- }
816
- }
817
- ).then(async (message2) => {
818
- var _a, _b, _c, _d, _e;
819
- if (this._debug)
820
- console.log("\u8DDF\u8E2A7", JSON.stringify(message2));
821
- if (message2.detail) {
822
- if (!message2.detail.usage) {
823
- try {
824
- const promptTokens = numTokens;
825
- let completionTokens = 0;
826
- if (["baidu", "aliyun"].indexOf(this._manufacturer.toLowerCase()) > -1) {
827
- completionTokens = (_b = (_a = message2.detail) == null ? void 0 : _a.usage) == null ? void 0 : _b.total_tokens;
828
- } else {
829
- completionTokens = await this._getTokenCount(message2.text);
830
- }
831
- message2.detail.usage = {
832
- prompt_tokens: promptTokens,
833
- completion_tokens: completionTokens,
834
- total_tokens: promptTokens + completionTokens,
835
- estimated: true
836
- };
837
- } catch (err) {
838
- }
839
- }
840
- if (this._manufacturer.toLowerCase() === "azure") {
841
- if (((_d = (_c = message2.detail) == null ? void 0 : _c.choices[0]) == null ? void 0 : _d.finish_reason) === "function_call") {
842
- message2.detail.choices[0].finish_reason = "tool_calls";
843
- message2.detail.choices[0].message = {
844
- role: message2.detail.choices[0].message.role,
845
- tool_calls: [
846
- {
847
- id: `call_${uuidv4()}`,
848
- type: "function",
849
- function: (_e = message2.detail.choices[0].message) == null ? void 0 : _e.function_call
850
- }
851
- ]
852
- };
853
- }
854
- }
855
- }
856
- const pRes = Promise.all([
857
- this._upsertMessage(latestQuestion),
858
- this._upsertMessage(message2)
859
- ]).then(() => message2);
860
- return pRes;
861
- });
862
- if (this._debug)
863
- console.log("\u8DDF\u8E2A8");
864
- if (timeoutMs) {
865
- if (this._debug)
866
- console.log("\u8DDF\u8E2A9");
867
- if (abortController) {
868
- ;
869
- responseP.cancel = () => {
870
- console.log("responseP cancel error ", responseP);
871
- abortController.abort();
872
- };
873
- }
874
- return pTimeout(responseP, {
875
- milliseconds: timeoutMs,
876
- message: `${this._manufacturer} timed out waiting for response`
877
- });
878
- } else {
879
- if (this._debug)
880
- console.log("\u8DDF\u8E2A10");
881
- return responseP;
882
- }
883
- }
884
- get manufacturer() {
885
- return this._manufacturer;
886
- }
887
- set manufacturer(manufacturer) {
888
- this._manufacturer = manufacturer;
889
- }
890
- get maxModelTokens() {
891
- return this._maxModelTokens;
892
- }
893
- set maxModelTokens(maxModelTokens) {
894
- this._maxModelTokens = maxModelTokens;
895
- }
896
- get maxResponseTokens() {
897
- return this._maxResponseTokens;
898
- }
899
- set maxResponseTokens(maxResponseTokens) {
900
- this._maxResponseTokens = maxResponseTokens;
901
- }
902
- get apiBaseUrl() {
903
- return this._apiBaseUrl;
904
- }
905
- set apiBaseUrl(apiBaseUrl) {
906
- this._apiBaseUrl = apiBaseUrl;
907
- }
908
- get apiKey() {
909
- return this._apiKey;
910
- }
911
- set apiKey(apiKey) {
912
- this._apiKey = apiKey;
913
- }
914
- get apiOrg() {
915
- return this._apiOrg;
916
- }
917
- set apiOrg(apiOrg) {
918
- this._apiOrg = apiOrg;
919
- }
920
- async _buildMessages(text, opts, pluginData) {
921
- var _a, _b;
922
- const { systemMessage = this._systemMessage, completionParams } = opts;
923
- let { parentMessageId, contextRestriction } = opts;
924
- let errorMessage = "";
925
- const userLabel = USER_LABEL_DEFAULT;
926
- const assistantLabel = ASSISTANT_LABEL_DEFAULT;
927
- const maxNumTokens = this._maxModelTokens - this._maxResponseTokens;
928
- let messages = [];
929
- if (systemMessage) {
930
- messages.push({
931
- role: "system",
932
- content: systemMessage
933
- });
934
- }
935
- let objText = [{ type: "text", text }];
936
- if (completionParams.fileList && completionParams.fileList.length > 0) {
937
- completionParams.fileList.forEach((item) => {
938
- if ((item == null ? void 0 : item.type.indexOf("image")) > -1) {
939
- objText.push({
940
- type: "image_url",
941
- image_url: {
942
- url: item.imgUrl
943
- }
944
- });
945
- }
946
- });
947
- if (["openai", "azure"].indexOf(this._manufacturer.toLowerCase()) > -1) {
948
- text = objText;
949
- }
950
- }
951
- const systemMessageOffset = messages.length;
952
- let userMessage = null;
953
- if ([
954
- "baidu",
955
- "zhipu",
956
- "xunfei",
957
- "aliyun",
958
- "tencent",
959
- "chatdoc",
960
- "anthropic"
961
- ].indexOf(this._manufacturer.toLowerCase()) > -1) {
962
- userMessage = [{ role: "user", content: text }];
963
- } else if (pluginData) {
964
- userMessage = {
965
- role: pluginData.role,
966
- name: pluginData.name,
967
- content: JSON.stringify(pluginData.content),
968
- tool_call_id: pluginData.tool_call_id
969
- };
970
- if (["azure"].indexOf(this._manufacturer.toLowerCase()) > -1) {
971
- delete userMessage.tool_call_id;
972
- }
973
- } else {
974
- userMessage = [{ role: "user", content: text, name: opts.name }];
975
- }
976
- let nextMessages = messages;
977
- if (pluginData || text) {
978
- nextMessages = nextMessages.concat(userMessage);
979
- }
980
- let numTokens = 0;
981
- do {
982
- const prompt = nextMessages.reduce((prompt2, message) => {
983
- switch (message.role) {
984
- case "tool":
985
- return prompt2.concat([`Tool:
986
- function call`]);
987
- case "system":
988
- return prompt2.concat([`Instructions:
989
- ${message.content}`]);
990
- case "user":
991
- return prompt2.concat([`${userLabel}:
992
- ${message.content}`]);
993
- default:
994
- return prompt2.concat([`${assistantLabel}:
995
- ${message.content}`]);
996
- }
997
- }, []).join("\n\n");
998
- const nextNumTokensEstimate = await this._getTokenCount(prompt);
999
- const isValidPrompt = nextNumTokensEstimate <= maxNumTokens;
1000
- if (prompt && !isValidPrompt && ["openai", "azure"].indexOf(this._manufacturer.toLowerCase()) > -1) {
1001
- break;
1002
- }
1003
- messages = nextMessages;
1004
- numTokens = nextNumTokensEstimate;
1005
- if (!isValidPrompt && ["openai", "azure"].indexOf(this._manufacturer.toLowerCase()) > -1) {
1006
- break;
1007
- }
1008
- if (!parentMessageId) {
1009
- break;
1010
- }
1011
- const parentMessage = await this._getMessageById(parentMessageId);
1012
- if (!parentMessage) {
1013
- break;
1014
- }
1015
- const parentMessageRole = parentMessage.role || "user";
1016
- let parentMessageItem = null;
1017
- if ([
1018
- "baidu",
1019
- "zhipu",
1020
- "xunfei",
1021
- "aliyun",
1022
- "tencent",
1023
- "chatdoc",
1024
- "anthropic"
1025
- ].indexOf(this._manufacturer.toLowerCase()) > -1) {
1026
- parentMessageItem = {
1027
- role: parentMessageRole,
1028
- content: parentMessage.text
1029
- };
1030
- } else if (parentMessage.content && ((_a = parentMessage.content) == null ? void 0 : _a.finish_reason) === "tool_calls") {
1031
- if (["azure"].indexOf(this._manufacturer.toLowerCase()) > -1) {
1032
- parentMessageItem = Object.assign(parentMessage.content.message, {
1033
- function_call: (_b = parentMessage.content.message.tool_calls[0]) == null ? void 0 : _b.function,
1034
- content: parentMessage.text || parentMessage.content
1035
- });
1036
- delete parentMessage.content.message.tool_calls;
1037
- } else {
1038
- parentMessageItem = parentMessage.content.message;
1039
- }
1040
- } else {
1041
- parentMessageItem = {
1042
- role: parentMessageRole,
1043
- content: parentMessage.text || parentMessage.content,
1044
- name: parentMessage.name
1045
- };
1046
- if (parentMessage.tool_call_id)
1047
- parentMessageItem.tool_call_id = parentMessage.tool_call_id;
1048
- }
1049
- nextMessages = nextMessages.slice(0, systemMessageOffset).concat([parentMessageItem, ...nextMessages.slice(systemMessageOffset)]);
1050
- if (nextMessages.length >= contextRestriction)
1051
- break;
1052
- parentMessageId = parentMessage.parentMessageId;
1053
- } while (true);
1054
- let maxTokens = this._maxModelTokens;
1055
- if (isPositiveNumber(maxTokens)) {
1056
- if (["openai", "azure"].indexOf(this._manufacturer.toLowerCase()) > -1) {
1057
- maxTokens = Math.max(
1058
- 1,
1059
- Math.min(this._maxModelTokens - numTokens, this._maxResponseTokens)
1060
- );
1061
- } else if (numTokens > this._maxModelTokens) {
1062
- maxTokens = this._maxModelTokens;
1063
- errorMessage = `${this._manufacturer}\uFF1A\u5F53\u524D\u63D0\u95EE\u4E0A\u4E0B\u6587\u5185\u5BB9\u957F\u5EA6${numTokens}tokns\u8D85\u957F\uFF0C\u8BE5\u6A21\u578B\u6700\u5927\u63D0\u95EE\u957F\u5EA6\u4E3A${this._maxModelTokens}tokens\uFF0C\u8BF7\u5207\u6362\u5176\u4ED6\u589E\u5F3AAI\u6A21\u578B\u6216\u51CF\u5C11\u5B57\u6570\u6216\u8005\u5173\u95ED\u4E0A\u4E0B\u6587\u5386\u53F2\u63D0\u9AD8\u5355\u6B21\u63D0\u95EE\u957F\u5EA6\uFF01`;
1064
- }
1065
- }
1066
- return { messages, maxTokens, numTokens, errorMessage, objText };
1067
- }
1068
- async _getTokenCount(text) {
1069
- text = text.replace(/<\|endoftext\|>/g, "");
1070
- return encode(text).length;
1071
- }
1072
- async _defaultGetMessageById(id) {
1073
- const res = await this._messageStore.get(id);
1074
- return res;
1075
- }
1076
- async _defaultUpsertMessage(message) {
1077
- await this._messageStore.set(message.id, message);
1078
- }
1079
- };
1080
-
1081
- // src/chatgpt-unofficial-proxy-api.ts
1082
- import pTimeout2 from "p-timeout";
1083
- import { v4 as uuidv42 } from "uuid";
1084
- var ChatGPTUnofficialProxyAPI = class {
1085
- /**
1086
- * @param fetch - Optional override for the `fetch` implementation to use. Defaults to the global `fetch` function.
1087
- */
1088
- constructor(opts) {
1089
- const {
1090
- accessToken,
1091
- apiReverseProxyUrl = "https://bypass.duti.tech/api/conversation",
1092
- model = "text-davinci-002-render-sha",
1093
- debug = false,
1094
- headers,
1095
- fetch: fetch2 = fetch
1096
- } = opts;
1097
- this._accessToken = accessToken;
1098
- this._apiReverseProxyUrl = apiReverseProxyUrl;
1099
- this._debug = !!debug;
1100
- this._model = model;
1101
- this._fetch = fetch2;
1102
- this._headers = headers;
1103
- if (!this._accessToken) {
1104
- throw new Error("ChatGPT invalid accessToken");
1105
- }
1106
- if (!this._fetch) {
1107
- throw new Error("Invalid environment; fetch is not defined");
1108
- }
1109
- if (typeof this._fetch !== "function") {
1110
- throw new Error('Invalid "fetch" is not a function');
1111
- }
1112
- }
1113
- get accessToken() {
1114
- return this._accessToken;
1115
- }
1116
- set accessToken(value) {
1117
- this._accessToken = value;
1118
- }
1119
- /**
1120
- * Sends a message to ChatGPT, waits for the response to resolve, and returns
1121
- * the response.
1122
- *
1123
- * If you want your response to have historical context, you must provide a valid `parentMessageId`.
1124
- *
1125
- * If you want to receive a stream of partial responses, use `opts.onProgress`.
1126
- * If you want to receive the full response, including message and conversation IDs,
1127
- * you can use `opts.onConversationResponse` or use the `ChatGPTAPI.getConversation`
1128
- * helper.
1129
- *
1130
- * Set `debug: true` in the `ChatGPTAPI` constructor to log more info on the full prompt sent to the OpenAI completions API. You can override the `promptPrefix` and `promptSuffix` in `opts` to customize the prompt.
1131
- *
1132
- * @param message - The prompt message to send
1133
- * @param opts.conversationId - Optional ID of a conversation to continue (defaults to a random UUID)
1134
- * @param opts.parentMessageId - Optional ID of the previous message in the conversation (defaults to `undefined`)
1135
- * @param opts.messageId - Optional ID of the message to send (defaults to a random UUID)
1136
- * @param opts.timeoutMs - Optional timeout in milliseconds (defaults to no timeout)
1137
- * @param opts.onProgress - Optional callback which will be invoked every time the partial response is updated
1138
- * @param opts.abortSignal - Optional callback used to abort the underlying `fetch` call using an [AbortController](https://developer.mozilla.org/en-US/docs/Web/API/AbortController)
1139
- *
1140
- * @returns The response from ChatGPT
1141
- */
1142
- async sendMessage(text, opts = {}) {
1143
- if (!!opts.conversationId !== !!opts.parentMessageId) {
1144
- throw new Error(
1145
- "ChatGPTUnofficialProxyAPI.sendMessage: conversationId and parentMessageId must both be set or both be undefined"
1146
- );
1147
- }
1148
- if (opts.conversationId && !isValidUUIDv4(opts.conversationId)) {
1149
- throw new Error(
1150
- "ChatGPTUnofficialProxyAPI.sendMessage: conversationId is not a valid v4 UUID"
1151
- );
1152
- }
1153
- if (opts.parentMessageId && !isValidUUIDv4(opts.parentMessageId)) {
1154
- throw new Error(
1155
- "ChatGPTUnofficialProxyAPI.sendMessage: parentMessageId is not a valid v4 UUID"
1156
- );
1157
- }
1158
- if (opts.messageId && !isValidUUIDv4(opts.messageId)) {
1159
- throw new Error(
1160
- "ChatGPTUnofficialProxyAPI.sendMessage: messageId is not a valid v4 UUID"
1161
- );
1162
- }
1163
- const {
1164
- conversationId,
1165
- parentMessageId = uuidv42(),
1166
- messageId = uuidv42(),
1167
- action = "next",
1168
- timeoutMs,
1169
- onProgress
1170
- } = opts;
1171
- let { abortSignal } = opts;
1172
- let abortController = null;
1173
- if (timeoutMs && !abortSignal) {
1174
- abortController = new AbortController();
1175
- abortSignal = abortController.signal;
1176
- }
1177
- const body = {
1178
- action,
1179
- messages: [
1180
- {
1181
- id: messageId,
1182
- role: "user",
1183
- content: {
1184
- content_type: "text",
1185
- parts: [text]
1186
- }
1187
- }
1188
- ],
1189
- model: this._model,
1190
- parent_message_id: parentMessageId
1191
- };
1192
- if (conversationId) {
1193
- body.conversation_id = conversationId;
1194
- }
1195
- const result = {
1196
- role: "assistant",
1197
- id: uuidv42(),
1198
- parentMessageId: messageId,
1199
- conversationId,
1200
- text: ""
1201
- };
1202
- const responseP = new Promise((resolve, reject) => {
1203
- const url = this._apiReverseProxyUrl;
1204
- const headers = {
1205
- ...this._headers,
1206
- Authorization: `Bearer ${this._accessToken}`,
1207
- Accept: "text/event-stream",
1208
- "Content-Type": "application/json"
1209
- };
1210
- if (this._debug) {
1211
- console.log("POST", url, { body, headers });
1212
- }
1213
- fetchSSE(
1214
- url,
1215
- {
1216
- method: "POST",
1217
- headers,
1218
- body: JSON.stringify(body),
1219
- signal: abortSignal,
1220
- onMessage: (data) => {
1221
- var _a, _b, _c;
1222
- if (data === "[DONE]") {
1223
- return resolve(result);
1224
- }
1225
- try {
1226
- const convoResponseEvent = JSON.parse(data);
1227
- if (convoResponseEvent.conversation_id) {
1228
- result.conversationId = convoResponseEvent.conversation_id;
1229
- }
1230
- if ((_a = convoResponseEvent.message) == null ? void 0 : _a.id) {
1231
- result.id = convoResponseEvent.message.id;
1232
- }
1233
- const message = convoResponseEvent.message;
1234
- if (message) {
1235
- let text2 = (_c = (_b = message == null ? void 0 : message.content) == null ? void 0 : _b.parts) == null ? void 0 : _c[0];
1236
- if (text2) {
1237
- result.text = text2;
1238
- if (onProgress) {
1239
- onProgress(result);
1240
- }
1241
- }
1242
- }
1243
- } catch (err) {
1244
- if (this._debug) {
1245
- console.warn("chatgpt unexpected JSON error", err);
1246
- }
1247
- }
1248
- },
1249
- onError: (err) => {
1250
- reject(err);
1251
- }
1252
- },
1253
- this._fetch
1254
- ).catch((err) => {
1255
- const errMessageL = err.toString().toLowerCase();
1256
- if (result.text && (errMessageL === "error: typeerror: terminated" || errMessageL === "typeerror: terminated")) {
1257
- return resolve(result);
1258
- } else {
1259
- return reject(err);
1260
- }
1261
- });
1262
- });
1263
- if (timeoutMs) {
1264
- if (abortController) {
1265
- ;
1266
- responseP.cancel = () => {
1267
- abortController.abort();
1268
- };
1269
- }
1270
- return pTimeout2(responseP, {
1271
- milliseconds: timeoutMs,
1272
- message: "ChatGPT timed out waiting for response"
1273
- });
1274
- } else {
1275
- return responseP;
1276
- }
1277
- }
1278
- };
1279
- export {
1280
- ChatGPTAPI,
1281
- ChatGPTError,
1282
- ChatGPTUnofficialProxyAPI,
1283
- openai
1284
- };
1
+ // src/chatgpt-api.ts
2
+ import { Spark } from "@leikeduntech/spark-nodejs";
3
+ import Keyv from "keyv";
4
+ import pTimeout from "p-timeout";
5
+ import QuickLRU from "quick-lru";
6
+ import { v4 as uuidv4 } from "uuid";
7
+
8
+ // src/tokenizer.ts
9
+ import { getEncoding } from "js-tiktoken";
10
+ var tokenizer = getEncoding("cl100k_base");
11
+ function encode(input) {
12
+ return new Uint32Array(tokenizer.encode(input));
13
+ }
14
+
15
+ // src/types.ts
16
+ var ChatGPTError = class extends Error {
17
+ };
18
+ var openai;
19
+ ((openai2) => {
20
+ })(openai || (openai = {}));
21
+
22
+ // src/fetch.ts
23
+ var fetch = globalThis.fetch;
24
+
25
+ // src/fetch-sse.ts
26
+ import { createParser } from "eventsource-parser";
27
+
28
+ // src/stream-async-iterable.ts
29
+ async function* streamAsyncIterable(stream) {
30
+ const reader = stream.getReader();
31
+ try {
32
+ while (true) {
33
+ const { done, value } = await reader.read();
34
+ if (done) {
35
+ return;
36
+ }
37
+ yield value;
38
+ }
39
+ } finally {
40
+ reader.releaseLock();
41
+ }
42
+ }
43
+
44
+ // src/fetch-sse.ts
45
+ async function fetchSSE(url, options, fetch2 = fetch, manufacturer = "OpenAI") {
46
+ const { onMessage, onError, ...fetchOptions } = options;
47
+ const res = await fetch2(url, fetchOptions);
48
+ if (!res.ok) {
49
+ let reason;
50
+ try {
51
+ reason = await res.text();
52
+ } catch (err) {
53
+ reason = res.statusText;
54
+ }
55
+ const msg = `${manufacturer} error ${res.status}: ${reason}`;
56
+ const error = new ChatGPTError(msg, { cause: res });
57
+ error.statusCode = res.status;
58
+ error.statusText = res.statusText;
59
+ throw error;
60
+ }
61
+ const parser = createParser((event) => {
62
+ if (event.type === "event") {
63
+ if (manufacturer.toLowerCase() === "zhipu") {
64
+ onMessage(JSON.stringify(event));
65
+ } else {
66
+ onMessage(event.data);
67
+ }
68
+ }
69
+ });
70
+ const feed = (chunk) => {
71
+ var _a;
72
+ let response = null;
73
+ try {
74
+ response = JSON.parse(chunk);
75
+ } catch {
76
+ }
77
+ if (((_a = response == null ? void 0 : response.detail) == null ? void 0 : _a.type) === "invalid_request_error") {
78
+ const msg = `${manufacturer} error ${response.detail.message}: ${response.detail.code} (${response.detail.type})`;
79
+ const error = new ChatGPTError(msg, { cause: response });
80
+ error.statusCode = response.detail.code;
81
+ error.statusText = response.detail.message;
82
+ if (onError) {
83
+ onError(error);
84
+ } else {
85
+ console.error(error);
86
+ }
87
+ return;
88
+ }
89
+ parser.feed(chunk);
90
+ };
91
+ if (!res.body.getReader) {
92
+ const body = res.body;
93
+ if (!body.on || !body.read) {
94
+ throw new ChatGPTError('unsupported "fetch" implementation');
95
+ }
96
+ body.on("readable", () => {
97
+ let chunk;
98
+ while (null !== (chunk = body.read())) {
99
+ feed(chunk.toString());
100
+ }
101
+ });
102
+ } else {
103
+ for await (const chunk of streamAsyncIterable(res.body)) {
104
+ const str = new TextDecoder().decode(chunk);
105
+ feed(str);
106
+ }
107
+ }
108
+ }
109
+
110
+ // src/utils.ts
111
+ import CryptoJS from "crypto-js";
112
+ var 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;
113
+ function isValidUUIDv4(str) {
114
+ return str && uuidv4Re.test(str);
115
+ }
116
+ function convertArrayToString(arr) {
117
+ let result = "[";
118
+ for (let i = 0; i < arr.length; i++) {
119
+ const obj = arr[i];
120
+ const keys = Object.keys(obj);
121
+ result += "{";
122
+ for (let j = 0; j < keys.length; j++) {
123
+ const key = keys[j];
124
+ const value = obj[key];
125
+ result += '"' + key + '":' + (typeof value === "string" ? '"' + value + '"' : value) + ",";
126
+ }
127
+ result = result.slice(0, -1);
128
+ result += "},";
129
+ }
130
+ result = result.slice(0, -1);
131
+ result += "]";
132
+ return result;
133
+ }
134
+ function signTencentHunyuan(bodyData, url, keyList) {
135
+ const sortedObj = {};
136
+ Object.keys(bodyData).sort().forEach((key) => {
137
+ sortedObj[key] = bodyData[key];
138
+ });
139
+ let signStr = "";
140
+ for (let key in sortedObj) {
141
+ if (signStr) {
142
+ if (typeof sortedObj[key] === "object") {
143
+ signStr += `&${key}=${convertArrayToString(sortedObj[key])}`;
144
+ } else {
145
+ signStr += `&${key}=${sortedObj[key]}`;
146
+ }
147
+ } else {
148
+ signStr += `${key}=${sortedObj[key]}`;
149
+ }
150
+ }
151
+ signStr = `${url.replace("https://", "")}?${signStr}`;
152
+ const hmac = CryptoJS.HmacSHA1(signStr, keyList[2]);
153
+ const signBase64 = CryptoJS.enc.Base64.stringify(hmac);
154
+ return signBase64;
155
+ }
156
+ function isPositiveNumber(str) {
157
+ return /^[1-9]\d*$/.test(str);
158
+ }
159
+
160
+ // src/chatgpt-api.ts
161
+ var CHATGPT_MODEL = "gpt-3.5-turbo";
162
+ var USER_LABEL_DEFAULT = "User";
163
+ var ASSISTANT_LABEL_DEFAULT = "ChatGPT";
164
+ var ChatGPTAPI = class {
165
+ /**
166
+ * Creates a new client wrapper around OpenAI's chat completion API, mimicing the official ChatGPT webapp's functionality as closely as possible.
167
+ *
168
+ * @param apiKey - OpenAI API key (required).
169
+ * @param apiOrg - Optional OpenAI API organization (optional).
170
+ * @param apiBaseUrl - Optional override for the OpenAI API base URL.
171
+ * @param debug - Optional enables logging debugging info to stdout.
172
+ * @param completionParams - Param overrides to send to the [OpenAI chat completion API](https://platform.openai.com/docs/api-reference/chat/create). Options like `temperature` and `presence_penalty` can be tweaked to change the personality of the assistant.
173
+ * @param maxModelTokens - Optional override for the maximum number of tokens allowed by the model's context. Defaults to 4096.
174
+ * @param maxResponseTokens - Optional override for the minimum number of tokens allowed for the model's response. Defaults to 1000.
175
+ * @param messageStore - Optional [Keyv](https://github.com/jaredwray/keyv) store to persist chat messages to. If not provided, messages will be lost when the process exits.
176
+ * @param getMessageById - Optional function to retrieve a message by its ID. If not provided, the default implementation will be used (using an in-memory `messageStore`).
177
+ * @param upsertMessage - Optional function to insert or update a message. If not provided, the default implementation will be used (using an in-memory `messageStore`).
178
+ * @param fetch - Optional override for the `fetch` implementation to use. Defaults to the global `fetch` function.
179
+ */
180
+ constructor(opts) {
181
+ const {
182
+ manufacturer = "OpenAI",
183
+ apiKey,
184
+ apiOrg,
185
+ apiBaseUrl = "https://api.openai.com/v1",
186
+ debug = false,
187
+ messageStore,
188
+ completionParams,
189
+ systemMessage,
190
+ maxModelTokens = 0,
191
+ maxResponseTokens = -1e7,
192
+ getMessageById,
193
+ upsertMessage,
194
+ fetch: fetch2 = fetch
195
+ } = opts;
196
+ this._manufacturer = manufacturer;
197
+ this._apiKey = apiKey;
198
+ this._apiOrg = apiOrg;
199
+ this._apiBaseUrl = apiBaseUrl;
200
+ this._debug = !!debug;
201
+ this._fetch = fetch2;
202
+ this._completionParams = {
203
+ model: CHATGPT_MODEL,
204
+ ...completionParams
205
+ };
206
+ this._systemMessage = systemMessage;
207
+ this._maxModelTokens = maxModelTokens;
208
+ this._maxResponseTokens = maxResponseTokens;
209
+ this._getMessageById = getMessageById ?? this._defaultGetMessageById;
210
+ this._upsertMessage = upsertMessage ?? this._defaultUpsertMessage;
211
+ if (messageStore) {
212
+ this._messageStore = messageStore;
213
+ } else {
214
+ this._messageStore = new Keyv({
215
+ store: new QuickLRU({ maxSize: 1e4 })
216
+ });
217
+ }
218
+ if (!this._apiKey) {
219
+ throw new Error(`${this._manufacturer} missing required apiKey`);
220
+ }
221
+ if (!this._fetch) {
222
+ throw new Error("Invalid environment; fetch is not defined");
223
+ }
224
+ if (typeof this._fetch !== "function") {
225
+ throw new Error('Invalid "fetch" is not a function');
226
+ }
227
+ }
228
+ pluginListMap(pluginList) {
229
+ const list = {
230
+ "dall-e-3": {
231
+ name: "DallE3Fun",
232
+ description: "\u4F7F\u7528DALL-E3\u6A21\u578B\u6839\u636E\u7528\u6237\u63CF\u8FF0\u63D0\u793A\u521B\u4F5C\u4E00\u5F20\u65B0\u7684\u56FE\u7247"
233
+ },
234
+ "dall-e-2": {
235
+ name: "DallE2Fun",
236
+ description: "\u4F7F\u7528DALL-E2\u6A21\u578B\u628A\u7528\u6237\u63D0\u4F9B\u7684\u56FE\u7247\u548C\u6839\u636E\u63D0\u793A\u8BCD\u91CD\u65B0\u753B\u56FE\u4FEE\u6539\u56FE\u7247\u7F16\u8F91\u56FE\u7247\u66FF\u6362\u56FE\u7247\u90E8\u4EFD\u5185\u5BB9\u6362\u6539\u91CD\u753B\u56FE\u7247"
237
+ }
238
+ };
239
+ return list[pluginList];
240
+ }
241
+ /**
242
+ * Sends a message to the OpenAI chat completions endpoint, waits for the response
243
+ * to resolve, and returns the response.
244
+ *
245
+ * If you want your response to have historical context, you must provide a valid `parentMessageId`.
246
+ *
247
+ * If you want to receive a stream of partial responses, use `opts.onProgress`.
248
+ *
249
+ * Set `debug: true` in the `ChatGPTAPI` constructor to log more info on the full prompt sent to the OpenAI chat completions API. You can override the `systemMessage` in `opts` to customize the assistant's instructions.
250
+ *
251
+ * @param message - The prompt message to send
252
+ * @param opts.parentMessageId - Optional ID of the previous message in the conversation (defaults to `undefined`)
253
+ * @param opts.conversationId - Optional ID of the conversation (defaults to `undefined`)
254
+ * @param opts.messageId - Optional ID of the message to send (defaults to a random UUID)
255
+ * @param opts.systemMessage - Optional override for the chat "system message" which acts as instructions to the model (defaults to the ChatGPT system message)
256
+ * @param opts.timeoutMs - Optional timeout in milliseconds (defaults to no timeout)
257
+ * @param opts.onProgress - Optional callback which will be invoked every time the partial response is updated
258
+ * @param opts.abortSignal - Optional callback used to abort the underlying `fetch` call using an [AbortController](https://developer.mozilla.org/en-US/docs/Web/API/AbortController)
259
+ * @param completionParams - Optional overrides to send to the [OpenAI chat completion API](https://platform.openai.com/docs/api-reference/chat/create). Options like `temperature` and `presence_penalty` can be tweaked to change the personality of the assistant.
260
+ *
261
+ * @returns The response from ChatGPT
262
+ */
263
+ async sendMessage(text, opts = {}, pluginParams) {
264
+ let parentMsg;
265
+ if (pluginParams) {
266
+ parentMsg = await this._getMessageById(pluginParams.assistant_res.id);
267
+ opts.parentMessageId = parentMsg.id;
268
+ }
269
+ let {
270
+ parentMessageId,
271
+ messageId = uuidv4(),
272
+ timeoutMs,
273
+ onProgress,
274
+ stream = onProgress ? true : false,
275
+ completionParams,
276
+ conversationId
277
+ } = opts;
278
+ let { abortSignal } = opts;
279
+ let abortController = null;
280
+ if (timeoutMs && !abortSignal) {
281
+ abortController = new AbortController();
282
+ abortSignal = abortController.signal;
283
+ }
284
+ let message = {
285
+ role: "user",
286
+ id: messageId,
287
+ conversationId,
288
+ parentMessageId,
289
+ text
290
+ };
291
+ if (this._debug)
292
+ console.log("\u8DDF\u8E2A1, \u8D85\u65F6\u65F6\u95F4ms", timeoutMs);
293
+ let latestQuestion = message, last_assistant_res_message = null, last_assistant_res = null, last_plugin_res = null;
294
+ if (pluginParams) {
295
+ last_assistant_res_message = pluginParams.assistant_res.detail.choices[0];
296
+ last_assistant_res = {
297
+ role: last_assistant_res_message.message.role,
298
+ id: parentMsg.id,
299
+ conversationId,
300
+ parentMessageId: parentMsg.parentMessageId,
301
+ text,
302
+ content: last_assistant_res_message
303
+ };
304
+ let r = "tool";
305
+ if (this._manufacturer.toLowerCase() === "azure") {
306
+ r = "function";
307
+ }
308
+ last_plugin_res = {
309
+ role: r,
310
+ id: messageId,
311
+ name: last_assistant_res_message.message.tool_calls[0].function.name,
312
+ conversationId,
313
+ parentMessageId: pluginParams.assistant_res.id,
314
+ text,
315
+ content: pluginParams.plugin_res,
316
+ tool_call_id: last_assistant_res_message.message.tool_calls[0].id
317
+ };
318
+ await this._upsertMessage(last_assistant_res);
319
+ latestQuestion = last_plugin_res;
320
+ }
321
+ if (this._debug)
322
+ console.log("\u8DDF\u8E2A2");
323
+ const { messages, maxTokens, numTokens, errorMessage, objText } = await this._buildMessages(text, opts, last_plugin_res);
324
+ latestQuestion.text = objText;
325
+ if (this._debug)
326
+ console.log(
327
+ `typeof errorMessage ${typeof errorMessage},numTokens:${numTokens}, _maxModelTokens:${this._maxModelTokens},errorMessage: ${errorMessage}`
328
+ );
329
+ if (errorMessage !== "" && errorMessage !== null && errorMessage.length > 0) {
330
+ return new Promise((resolve, reject) => {
331
+ const errMsg = {
332
+ manufacturer: this._manufacturer,
333
+ statusCode: 400,
334
+ message: errorMessage
335
+ };
336
+ return reject(errMsg);
337
+ });
338
+ }
339
+ const result = {
340
+ role: "assistant",
341
+ id: uuidv4(),
342
+ conversationId,
343
+ parentMessageId: messageId,
344
+ text: "",
345
+ result: "",
346
+ detail: { usage: null }
347
+ };
348
+ const responseP = new Promise(
349
+ async (resolve, reject) => {
350
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i;
351
+ let url = `${this._apiBaseUrl}/chat/completions`;
352
+ const headers = {
353
+ "Content-Type": "application/json",
354
+ Authorization: `Bearer ${this._apiKey}`
355
+ };
356
+ if (this._manufacturer.toLowerCase() === "baidu") {
357
+ url = this._apiBaseUrl;
358
+ delete headers.Authorization;
359
+ } else if (this._manufacturer.toLowerCase() === "aliyun") {
360
+ url = this._apiBaseUrl;
361
+ if (stream)
362
+ headers["X-DashScope-SSE"] = "enable";
363
+ } else if (this._manufacturer.toLowerCase() === "zhipu") {
364
+ url = this._apiBaseUrl;
365
+ headers["Authorization"] = this._apiKey;
366
+ if (stream)
367
+ headers["accept"] = "text/event-stream";
368
+ } else if (this._manufacturer.toLowerCase() === "azure") {
369
+ url = this._apiBaseUrl;
370
+ headers["api-key"] = this._apiKey;
371
+ delete headers.Authorization;
372
+ } else if (this._manufacturer.toLowerCase() === "xunfei") {
373
+ url = "";
374
+ delete headers.Authorization;
375
+ } else if (this._manufacturer.toLowerCase() === "chatdoc") {
376
+ url = this._apiBaseUrl;
377
+ } else if (this._manufacturer.toLocaleLowerCase() === "anthropic") {
378
+ url = this._apiBaseUrl;
379
+ }
380
+ let pluginList;
381
+ if (completionParams.pluginList) {
382
+ pluginList = completionParams.pluginList;
383
+ }
384
+ if (typeof completionParams.pluginList !== "undefined")
385
+ delete completionParams.pluginList;
386
+ if (typeof completionParams.fileList !== "undefined")
387
+ delete completionParams.fileList;
388
+ let body = {
389
+ max_tokens: maxTokens,
390
+ ...this._completionParams,
391
+ ...completionParams,
392
+ messages,
393
+ stream
394
+ };
395
+ if (!isPositiveNumber(maxTokens)) {
396
+ delete body.max_tokens;
397
+ }
398
+ if (this._manufacturer.toLowerCase() === "baidu" && typeof pluginList === "string" && pluginList.indexOf("zhishiku") > -1) {
399
+ if (body.model)
400
+ delete body.model;
401
+ if (body.max_tokens)
402
+ delete body.max_tokens;
403
+ if (body.temperature)
404
+ delete body.temperature;
405
+ } else {
406
+ if (typeof body.plugins !== void 0)
407
+ delete body.plugins;
408
+ }
409
+ if (["openai", "azure"].indexOf(this._manufacturer.toLowerCase()) > -1) {
410
+ switch (pluginList) {
411
+ case "dall-e-3":
412
+ let tools_key = "tools", tool_choice_key = "tool_choice", funArr = null;
413
+ if (this._manufacturer.toLowerCase() === "azure")
414
+ tools_key = "functions", tool_choice_key = "function_call";
415
+ funArr = [
416
+ {
417
+ type: "function",
418
+ function: {
419
+ name: "DallE2Fun",
420
+ description: this.pluginListMap(pluginList).description,
421
+ parameters: {
422
+ type: "object",
423
+ properties: {
424
+ prompt: {
425
+ type: "string",
426
+ description: "\u7528\u6237\u5BF9\u9700\u8981\u7F16\u8F91\u7684\u56FE\u7247\u4FEE\u6539\u7684\u63D0\u793A\u5185\u5BB9"
427
+ },
428
+ image_url: {
429
+ type: "string",
430
+ description: "\u4ECE\u5BF9\u8BDD\u5386\u53F2\u8BB0\u5F55\u548C\u7528\u6237\u63D0\u793A\u8BCD\u91CC\u5339\u914D\u6700\u8FD1\u4E00\u6B21\u51FA\u73B0\u7684\u4EE5http\u5F00\u5934\u7684\u56FE\u7247\u7684\u94FE\u63A5\u5730\u5740"
431
+ }
432
+ },
433
+ required: ["prompt", "image_url"]
434
+ }
435
+ }
436
+ },
437
+ {
438
+ type: "function",
439
+ function: {
440
+ name: "DallE3Fun",
441
+ description: this.pluginListMap(pluginList).description,
442
+ parameters: {
443
+ type: "object",
444
+ properties: {
445
+ prompt: {
446
+ type: "string",
447
+ description: "\u7ED8\u56FE\u7684\u63D0\u793A\u8BCD"
448
+ }
449
+ },
450
+ required: ["prompt"]
451
+ }
452
+ }
453
+ }
454
+ ];
455
+ if (this._manufacturer.toLowerCase() === "azure") {
456
+ funArr = funArr.map((item) => {
457
+ return item.function;
458
+ });
459
+ }
460
+ body = Object.assign(body, {
461
+ [tools_key]: funArr,
462
+ [tool_choice_key]: "auto"
463
+ });
464
+ break;
465
+ default:
466
+ break;
467
+ }
468
+ } else if (this._manufacturer.toLowerCase() === "aliyun") {
469
+ body = Object.assign(body, {
470
+ parameters: { result_format: "message" },
471
+ input: { messages }
472
+ });
473
+ delete body.messages;
474
+ } else if (this._manufacturer.toLowerCase() === "zhipu") {
475
+ if (completionParams.model === "glm-4") {
476
+ } else {
477
+ delete body.messages;
478
+ body = Object.assign(body, { prompt: messages });
479
+ }
480
+ } else if (this._manufacturer.toLowerCase() === "tencent") {
481
+ url = this._apiBaseUrl;
482
+ const timestamp = Math.ceil((/* @__PURE__ */ new Date()).getTime() / 1e3) + 1;
483
+ const keyList = this._apiKey.split(".");
484
+ body = Object.assign(body, {
485
+ app_id: parseInt(keyList[0]),
486
+ secret_id: keyList[1],
487
+ timestamp,
488
+ expired: timestamp + 24 * 60 * 60,
489
+ stream: stream ? 1 : 0
490
+ });
491
+ delete body.model;
492
+ delete body.max_tokens;
493
+ headers["Authorization"] = signTencentHunyuan(body, url, keyList);
494
+ } else if (this._manufacturer.toLowerCase() === "baidu") {
495
+ if (pluginList && pluginList.indexOf("zhishiku") > -1) {
496
+ let query = messages.splice(messages.length - 1, 1);
497
+ body = Object.assign(body, {
498
+ query: (_a = query[0]) == null ? void 0 : _a.content,
499
+ history: messages
500
+ });
501
+ delete body.messages;
502
+ }
503
+ } else if (this._manufacturer.toLowerCase() === "chatdoc") {
504
+ let query = messages.splice(messages.length - 1, 1);
505
+ body = Object.assign(body, {
506
+ upload_id: (_b = completionParams == null ? void 0 : completionParams.extParams) == null ? void 0 : _b.upload_id,
507
+ question: (_c = query[0]) == null ? void 0 : _c.content,
508
+ history: messages
509
+ });
510
+ if (body.extParams)
511
+ delete body.extParams;
512
+ if (body.model)
513
+ delete body.model;
514
+ if (body.max_tokens)
515
+ delete body.max_tokens;
516
+ if (body.temperature)
517
+ delete body.temperature;
518
+ if (body.messages)
519
+ delete body.messages;
520
+ }
521
+ if (this._apiOrg && this._manufacturer.toLowerCase() === "openai") {
522
+ headers["OpenAI-Organization"] = this._apiOrg;
523
+ }
524
+ if (this._debug) {
525
+ console.log(`api url ${url}`);
526
+ console.log(`api header ${JSON.stringify(headers)}`);
527
+ console.log(`sendMessage (${numTokens} tokens) body: `, body);
528
+ console.log(
529
+ `sendMessage (${numTokens} tokens) message : `,
530
+ messages,
531
+ typeof messages
532
+ );
533
+ }
534
+ if (this._manufacturer.toLowerCase() === "xunfei") {
535
+ const self = this;
536
+ const keyList = this._apiKey.split(".");
537
+ const options = {
538
+ secret: keyList[2],
539
+ key: keyList[1],
540
+ appid: keyList[0],
541
+ temperature: body == null ? void 0 : body.temperature,
542
+ useHistory: !!parentMessageId,
543
+ chatId: ""
544
+ };
545
+ if (message == null ? void 0 : message.conversationId)
546
+ options.chatId = message == null ? void 0 : message.conversationId;
547
+ if (self._debug)
548
+ console.log("spark options ", options);
549
+ const sparkIns = new Spark(options);
550
+ const url2 = sparkIns.chat({
551
+ content: messages && JSON.stringify(messages),
552
+ // onData 表示分段拿到返回结果
553
+ onData({ content, start, end, seq }) {
554
+ if (self._debug)
555
+ console.log("onData", content, start, end, seq);
556
+ result.id = `xunfei-${Math.floor(
557
+ Math.random() * 1e7
558
+ )}${(/* @__PURE__ */ new Date()).getTime()}`;
559
+ result.delta = content;
560
+ if (content)
561
+ result.text += content;
562
+ result.role = "assistant";
563
+ onProgress == null ? void 0 : onProgress(result);
564
+ },
565
+ onEnd({ content, tokens, questionTokens }) {
566
+ if (self._debug)
567
+ console.log("onEnd", content, tokens, questionTokens);
568
+ result.detail = {
569
+ usage: {
570
+ prompt_tokens: questionTokens,
571
+ completion_tokens: tokens,
572
+ total_tokens: questionTokens + tokens
573
+ }
574
+ };
575
+ result.text = content.trim();
576
+ return resolve(result);
577
+ }
578
+ });
579
+ } else {
580
+ if (stream) {
581
+ fetchSSE(
582
+ url,
583
+ {
584
+ method: "POST",
585
+ headers,
586
+ body: JSON.stringify(body),
587
+ signal: abortSignal,
588
+ onMessage: (data) => {
589
+ var _a2, _b2, _c2, _d2, _e2, _f2, _g2, _h2, _i2, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B;
590
+ if (data === "[DONE]") {
591
+ result.text = result.text.trim();
592
+ return resolve(result);
593
+ }
594
+ try {
595
+ const response = JSON.parse(data);
596
+ if (this._debug) {
597
+ console.log(
598
+ `row data ${typeof response} : `,
599
+ response,
600
+ response == null ? void 0 : response.choices
601
+ );
602
+ }
603
+ if (this._manufacturer.toLowerCase() === "baidu") {
604
+ if ((response == null ? void 0 : response.is_end) === true) {
605
+ result.text += response.result.trim();
606
+ result.detail = response;
607
+ return resolve(result);
608
+ }
609
+ } else if (this._manufacturer.toLowerCase() === "azure") {
610
+ if (((_a2 = response.choices[0]) == null ? void 0 : _a2.finish_reason) === "stop") {
611
+ result.text = result.text.trim();
612
+ return resolve(result);
613
+ }
614
+ } else if (this._manufacturer.toLowerCase() === "aliyun") {
615
+ if (["stop", "length"].indexOf(
616
+ (_c2 = (_b2 = response == null ? void 0 : response.output) == null ? void 0 : _b2.choices[0]) == null ? void 0 : _c2.finish_reason
617
+ ) > -1) {
618
+ result.text = (_f2 = (_e2 = (_d2 = response == null ? void 0 : response.output) == null ? void 0 : _d2.choices[0]) == null ? void 0 : _e2.message) == null ? void 0 : _f2.content.trim();
619
+ return resolve(result);
620
+ }
621
+ } else if (this._manufacturer.toLowerCase() === "zhipu") {
622
+ if (completionParams.model === "glm-4") {
623
+ const gelResponse = JSON.parse(response.data);
624
+ if (((_h2 = (_g2 = gelResponse == null ? void 0 : gelResponse.choices) == null ? void 0 : _g2[0]) == null ? void 0 : _h2.finish_reason) === "stop") {
625
+ result.text = result.text.trim();
626
+ return resolve(result);
627
+ }
628
+ } else {
629
+ if ((response == null ? void 0 : response.event) === "finish") {
630
+ result.text += response == null ? void 0 : response.data.trim();
631
+ return resolve(result);
632
+ }
633
+ }
634
+ } else if (this._manufacturer.toLowerCase() === "tencent") {
635
+ if (((_i2 = response.choices[0]) == null ? void 0 : _i2.finish_reason) === "stop") {
636
+ result.text += (_k = (_j = response == null ? void 0 : response.choices[0]) == null ? void 0 : _j.delta) == null ? void 0 : _k.content.trim();
637
+ return resolve(result);
638
+ }
639
+ } else if (this._manufacturer.toLowerCase() === "chatdoc") {
640
+ result.id = `chatdoc-${Math.floor(
641
+ Math.random() * 1e7
642
+ )}${(/* @__PURE__ */ new Date()).getTime()}`;
643
+ if (response == null ? void 0 : response.source_info) {
644
+ result.text += response == null ? void 0 : response.answer;
645
+ return resolve(result);
646
+ }
647
+ }
648
+ if (this._manufacturer.toLowerCase() === "aliyun") {
649
+ if (response == null ? void 0 : response.request_id) {
650
+ result.id = response.request_id;
651
+ }
652
+ } else {
653
+ if (response == null ? void 0 : response.id) {
654
+ result.id = response.id;
655
+ }
656
+ }
657
+ if (((_l = response.choices) == null ? void 0 : _l.length) && ["openai", "azure", "tencent", "anthropic"].indexOf(
658
+ this._manufacturer.toLowerCase()
659
+ ) > -1) {
660
+ const delta = response.choices[0].delta;
661
+ result.delta = "";
662
+ if (response.choices[0].finish_reason === "tool_calls") {
663
+ result.delta = text;
664
+ } else if (delta.content) {
665
+ result.delta = delta.content;
666
+ }
667
+ if (delta.reasoning_content) {
668
+ result.delta = `<think>${delta.reasoning_content}</think>${result.delta}`;
669
+ }
670
+ if ((delta == null ? void 0 : delta.content) || (delta == null ? void 0 : delta.reasoning_content))
671
+ result.text += result.delta;
672
+ result.role = "assistant";
673
+ if (response.choices[0].finish_reason === "tool_calls") {
674
+ } else if (delta.role) {
675
+ result.role = delta.role;
676
+ }
677
+ result.detail = response;
678
+ onProgress == null ? void 0 : onProgress(result);
679
+ } else if ((response == null ? void 0 : response.result) && this._manufacturer.toLowerCase() === "baidu") {
680
+ result.delta = response.result;
681
+ if (response == null ? void 0 : response.result)
682
+ result.text += response.result;
683
+ result.role = "assistant";
684
+ result.detail = response;
685
+ onProgress == null ? void 0 : onProgress(result);
686
+ } else if ((response == null ? void 0 : response.output) && this._manufacturer.toLowerCase() === "aliyun") {
687
+ response.usage = Object.assign(response.usage, {
688
+ prompt_tokens: (_m = response.usage) == null ? void 0 : _m.input_tokens,
689
+ completion_tokens: (_n = response.usage) == null ? void 0 : _n.output_tokens,
690
+ total_tokens: ((_o = response.usage) == null ? void 0 : _o.input_tokens) + ((_p = response.usage) == null ? void 0 : _p.output_tokens)
691
+ });
692
+ result.delta = "";
693
+ if ((_s = (_r = (_q = response == null ? void 0 : response.output) == null ? void 0 : _q.choices[0]) == null ? void 0 : _r.message) == null ? void 0 : _s.content)
694
+ result.text = (_v = (_u = (_t = response == null ? void 0 : response.output) == null ? void 0 : _t.choices[0]) == null ? void 0 : _u.message) == null ? void 0 : _v.content;
695
+ result.role = "assistant";
696
+ result.detail = response;
697
+ onProgress == null ? void 0 : onProgress(result);
698
+ } else if ((response == null ? void 0 : response.data) && this._manufacturer.toLowerCase() === "zhipu") {
699
+ if (completionParams.model === "glm-4") {
700
+ const glmResponse = JSON.parse(response.data);
701
+ if (((_x = (_w = glmResponse == null ? void 0 : glmResponse.choices) == null ? void 0 : _w[0]) == null ? void 0 : _x.finish_reason) === "stop") {
702
+ response.usage = glmResponse.usage;
703
+ }
704
+ let data2 = (_z = (_y = glmResponse == null ? void 0 : glmResponse.choices) == null ? void 0 : _y[0]) == null ? void 0 : _z.delta.content;
705
+ result.delta = data2;
706
+ if (data2) {
707
+ result.text += data2;
708
+ }
709
+ result.role = "assistant";
710
+ result.detail = response;
711
+ onProgress == null ? void 0 : onProgress(result);
712
+ } else {
713
+ if (response.event === "finish") {
714
+ if ((_A = response == null ? void 0 : response.meta) == null ? void 0 : _A.usage) {
715
+ response.usage = (_B = response == null ? void 0 : response.meta) == null ? void 0 : _B.usage;
716
+ } else {
717
+ response.usage = {
718
+ prompt_tokens: 1,
719
+ completion_tokens: 1,
720
+ total_tokens: 2
721
+ };
722
+ }
723
+ }
724
+ result.delta = response.data;
725
+ if (response == null ? void 0 : response.data)
726
+ result.text += response == null ? void 0 : response.data;
727
+ result.role = "assistant";
728
+ result.detail = response;
729
+ onProgress == null ? void 0 : onProgress(result);
730
+ }
731
+ } else if ((response == null ? void 0 : response.answer) && this._manufacturer.toLowerCase() === "chatdoc") {
732
+ result.delta = response.answer;
733
+ if (response == null ? void 0 : response.answer)
734
+ result.text += response.answer;
735
+ result.role = "assistant";
736
+ result.detail = response;
737
+ onProgress == null ? void 0 : onProgress(result);
738
+ }
739
+ } catch (err) {
740
+ console.warn(
741
+ `${this._manufacturer} stream SEE event unexpected error`,
742
+ err
743
+ );
744
+ return reject(err);
745
+ }
746
+ }
747
+ },
748
+ this._fetch,
749
+ this._manufacturer
750
+ ).catch(reject);
751
+ } else {
752
+ try {
753
+ if (this._debug)
754
+ console.log("\u8DDF\u8E2A3");
755
+ const res = await this._fetch(url, {
756
+ method: "POST",
757
+ headers,
758
+ body: JSON.stringify(body),
759
+ signal: abortSignal
760
+ });
761
+ if (this._debug)
762
+ console.log("\u8DDF\u8E2A4");
763
+ if (!res.ok) {
764
+ const reason = await res.text();
765
+ const msg = `${this._manufacturer} error ${res.status || res.statusText}: ${reason}`;
766
+ const error = new ChatGPTError(msg, { cause: res });
767
+ error.statusCode = res.status;
768
+ error.statusText = res.statusText;
769
+ return reject(error);
770
+ }
771
+ const response = await res.json();
772
+ if (this._debug) {
773
+ console.log(
774
+ `row data ${typeof response} : `,
775
+ response,
776
+ (response == null ? void 0 : response.choices) && ((_d = response == null ? void 0 : response.choices[0]) == null ? void 0 : _d.message)
777
+ );
778
+ }
779
+ if (this._manufacturer.toLowerCase() === "aliyun") {
780
+ if (response == null ? void 0 : response.request_id) {
781
+ result.id = response.request_id;
782
+ }
783
+ } else {
784
+ if (response == null ? void 0 : response.id) {
785
+ result.id = response.id;
786
+ }
787
+ }
788
+ if (((_e = response == null ? void 0 : response.choices) == null ? void 0 : _e.length) && ["openai", "azure"].indexOf(this._manufacturer.toLowerCase()) > -1) {
789
+ const message2 = response.choices[0].message;
790
+ result.text = message2.content;
791
+ if (message2.role) {
792
+ result.role = message2.role;
793
+ }
794
+ } else if ((response == null ? void 0 : response.result) && this._manufacturer.toLowerCase() === "baidu") {
795
+ result.text = response.result;
796
+ result.role = "assistant";
797
+ } else if (((_f = response == null ? void 0 : response.output) == null ? void 0 : _f.text) && this._manufacturer.toLowerCase() === "aliyun") {
798
+ result.text = (_g = response == null ? void 0 : response.output) == null ? void 0 : _g.text;
799
+ result.role = "assistant";
800
+ } else {
801
+ const res2 = response;
802
+ return reject(
803
+ new Error(
804
+ `${this._manufacturer} error: ${((_h = res2 == null ? void 0 : res2.detail) == null ? void 0 : _h.message) || ((_i = res2 == null ? void 0 : res2.detail) == null ? void 0 : _i.error_msg) || (res2 == null ? void 0 : res2.detail) || "unknown"}`
805
+ )
806
+ );
807
+ }
808
+ result.detail = response;
809
+ if (this._debug)
810
+ console.log("\u8DDF\u8E2A5");
811
+ return resolve(result);
812
+ } catch (err) {
813
+ if (this._debug)
814
+ console.log("\u8DDF\u8E2A6");
815
+ return reject(err);
816
+ }
817
+ }
818
+ }
819
+ }
820
+ ).then(async (message2) => {
821
+ var _a, _b, _c, _d, _e;
822
+ if (this._debug)
823
+ console.log("\u8DDF\u8E2A7", JSON.stringify(message2));
824
+ if (message2.detail) {
825
+ if (!message2.detail.usage) {
826
+ try {
827
+ const promptTokens = numTokens;
828
+ let completionTokens = 0;
829
+ if (["baidu", "aliyun"].indexOf(this._manufacturer.toLowerCase()) > -1) {
830
+ completionTokens = (_b = (_a = message2.detail) == null ? void 0 : _a.usage) == null ? void 0 : _b.total_tokens;
831
+ } else {
832
+ completionTokens = await this._getTokenCount(message2.text);
833
+ }
834
+ message2.detail.usage = {
835
+ prompt_tokens: promptTokens,
836
+ completion_tokens: completionTokens,
837
+ total_tokens: promptTokens + completionTokens,
838
+ estimated: true
839
+ };
840
+ } catch (err) {
841
+ }
842
+ }
843
+ if (this._manufacturer.toLowerCase() === "azure") {
844
+ if (((_d = (_c = message2.detail) == null ? void 0 : _c.choices[0]) == null ? void 0 : _d.finish_reason) === "function_call") {
845
+ message2.detail.choices[0].finish_reason = "tool_calls";
846
+ message2.detail.choices[0].message = {
847
+ role: message2.detail.choices[0].message.role,
848
+ tool_calls: [
849
+ {
850
+ id: `call_${uuidv4()}`,
851
+ type: "function",
852
+ function: (_e = message2.detail.choices[0].message) == null ? void 0 : _e.function_call
853
+ }
854
+ ]
855
+ };
856
+ }
857
+ }
858
+ }
859
+ const pRes = Promise.all([
860
+ this._upsertMessage(latestQuestion),
861
+ this._upsertMessage(message2)
862
+ ]).then(() => message2);
863
+ return pRes;
864
+ });
865
+ if (this._debug)
866
+ console.log("\u8DDF\u8E2A8");
867
+ if (timeoutMs) {
868
+ if (this._debug)
869
+ console.log("\u8DDF\u8E2A9");
870
+ if (abortController) {
871
+ ;
872
+ responseP.cancel = () => {
873
+ console.log("responseP cancel error ", responseP);
874
+ abortController.abort();
875
+ };
876
+ }
877
+ return pTimeout(responseP, {
878
+ milliseconds: timeoutMs,
879
+ message: `${this._manufacturer} timed out waiting for response`
880
+ });
881
+ } else {
882
+ if (this._debug)
883
+ console.log("\u8DDF\u8E2A10");
884
+ return responseP;
885
+ }
886
+ }
887
+ get manufacturer() {
888
+ return this._manufacturer;
889
+ }
890
+ set manufacturer(manufacturer) {
891
+ this._manufacturer = manufacturer;
892
+ }
893
+ get maxModelTokens() {
894
+ return this._maxModelTokens;
895
+ }
896
+ set maxModelTokens(maxModelTokens) {
897
+ this._maxModelTokens = maxModelTokens;
898
+ }
899
+ get maxResponseTokens() {
900
+ return this._maxResponseTokens;
901
+ }
902
+ set maxResponseTokens(maxResponseTokens) {
903
+ this._maxResponseTokens = maxResponseTokens;
904
+ }
905
+ get apiBaseUrl() {
906
+ return this._apiBaseUrl;
907
+ }
908
+ set apiBaseUrl(apiBaseUrl) {
909
+ this._apiBaseUrl = apiBaseUrl;
910
+ }
911
+ get apiKey() {
912
+ return this._apiKey;
913
+ }
914
+ set apiKey(apiKey) {
915
+ this._apiKey = apiKey;
916
+ }
917
+ get apiOrg() {
918
+ return this._apiOrg;
919
+ }
920
+ set apiOrg(apiOrg) {
921
+ this._apiOrg = apiOrg;
922
+ }
923
+ async _buildMessages(text, opts, pluginData) {
924
+ var _a, _b;
925
+ const { systemMessage = this._systemMessage, completionParams } = opts;
926
+ let { parentMessageId, contextRestriction } = opts;
927
+ let errorMessage = "";
928
+ const userLabel = USER_LABEL_DEFAULT;
929
+ const assistantLabel = ASSISTANT_LABEL_DEFAULT;
930
+ const maxNumTokens = this._maxModelTokens - this._maxResponseTokens;
931
+ let messages = [];
932
+ if (systemMessage) {
933
+ messages.push({
934
+ role: "system",
935
+ content: systemMessage
936
+ });
937
+ }
938
+ let objText = [{ type: "text", text }];
939
+ if (completionParams.fileList && completionParams.fileList.length > 0) {
940
+ completionParams.fileList.forEach((item) => {
941
+ if ((item == null ? void 0 : item.type.indexOf("image")) > -1) {
942
+ objText.push({
943
+ type: "image_url",
944
+ image_url: {
945
+ url: item.imgUrl
946
+ }
947
+ });
948
+ }
949
+ });
950
+ if (["openai", "azure"].indexOf(this._manufacturer.toLowerCase()) > -1) {
951
+ text = objText;
952
+ }
953
+ }
954
+ const systemMessageOffset = messages.length;
955
+ let userMessage = null;
956
+ if ([
957
+ "baidu",
958
+ "zhipu",
959
+ "xunfei",
960
+ "aliyun",
961
+ "tencent",
962
+ "chatdoc",
963
+ "anthropic"
964
+ ].indexOf(this._manufacturer.toLowerCase()) > -1) {
965
+ userMessage = [{ role: "user", content: text }];
966
+ } else if (pluginData) {
967
+ userMessage = {
968
+ role: pluginData.role,
969
+ name: pluginData.name,
970
+ content: JSON.stringify(pluginData.content),
971
+ tool_call_id: pluginData.tool_call_id
972
+ };
973
+ if (["azure"].indexOf(this._manufacturer.toLowerCase()) > -1) {
974
+ delete userMessage.tool_call_id;
975
+ }
976
+ } else {
977
+ userMessage = [{ role: "user", content: text, name: opts.name }];
978
+ }
979
+ let nextMessages = messages;
980
+ if (pluginData || text) {
981
+ nextMessages = nextMessages.concat(userMessage);
982
+ }
983
+ let numTokens = 0;
984
+ do {
985
+ const prompt = nextMessages.reduce((prompt2, message) => {
986
+ switch (message.role) {
987
+ case "tool":
988
+ return prompt2.concat([`Tool:
989
+ function call`]);
990
+ case "system":
991
+ return prompt2.concat([`Instructions:
992
+ ${message.content}`]);
993
+ case "user":
994
+ return prompt2.concat([`${userLabel}:
995
+ ${message.content}`]);
996
+ default:
997
+ return prompt2.concat([`${assistantLabel}:
998
+ ${message.content}`]);
999
+ }
1000
+ }, []).join("\n\n");
1001
+ const nextNumTokensEstimate = await this._getTokenCount(prompt);
1002
+ const isValidPrompt = nextNumTokensEstimate <= maxNumTokens;
1003
+ if (prompt && !isValidPrompt && ["openai", "azure"].indexOf(this._manufacturer.toLowerCase()) > -1) {
1004
+ break;
1005
+ }
1006
+ messages = nextMessages;
1007
+ numTokens = nextNumTokensEstimate;
1008
+ if (!isValidPrompt && ["openai", "azure"].indexOf(this._manufacturer.toLowerCase()) > -1) {
1009
+ break;
1010
+ }
1011
+ if (!parentMessageId) {
1012
+ break;
1013
+ }
1014
+ const parentMessage = await this._getMessageById(parentMessageId);
1015
+ if (!parentMessage) {
1016
+ break;
1017
+ }
1018
+ const parentMessageRole = parentMessage.role || "user";
1019
+ let parentMessageItem = null;
1020
+ if ([
1021
+ "baidu",
1022
+ "zhipu",
1023
+ "xunfei",
1024
+ "aliyun",
1025
+ "tencent",
1026
+ "chatdoc",
1027
+ "anthropic"
1028
+ ].indexOf(this._manufacturer.toLowerCase()) > -1) {
1029
+ parentMessageItem = {
1030
+ role: parentMessageRole,
1031
+ content: parentMessage.text
1032
+ };
1033
+ } else if (parentMessage.content && ((_a = parentMessage.content) == null ? void 0 : _a.finish_reason) === "tool_calls") {
1034
+ if (["azure"].indexOf(this._manufacturer.toLowerCase()) > -1) {
1035
+ parentMessageItem = Object.assign(parentMessage.content.message, {
1036
+ function_call: (_b = parentMessage.content.message.tool_calls[0]) == null ? void 0 : _b.function,
1037
+ content: parentMessage.text || parentMessage.content
1038
+ });
1039
+ delete parentMessage.content.message.tool_calls;
1040
+ } else {
1041
+ parentMessageItem = parentMessage.content.message;
1042
+ }
1043
+ } else {
1044
+ parentMessageItem = {
1045
+ role: parentMessageRole,
1046
+ content: parentMessage.text || parentMessage.content,
1047
+ name: parentMessage.name
1048
+ };
1049
+ if (parentMessage.tool_call_id)
1050
+ parentMessageItem.tool_call_id = parentMessage.tool_call_id;
1051
+ }
1052
+ nextMessages = nextMessages.slice(0, systemMessageOffset).concat([parentMessageItem, ...nextMessages.slice(systemMessageOffset)]);
1053
+ if (nextMessages.length >= contextRestriction)
1054
+ break;
1055
+ parentMessageId = parentMessage.parentMessageId;
1056
+ } while (true);
1057
+ let maxTokens = this._maxModelTokens;
1058
+ if (isPositiveNumber(maxTokens)) {
1059
+ if (["openai", "azure"].indexOf(this._manufacturer.toLowerCase()) > -1) {
1060
+ maxTokens = Math.max(
1061
+ 1,
1062
+ Math.min(this._maxModelTokens - numTokens, this._maxResponseTokens)
1063
+ );
1064
+ } else if (numTokens > this._maxModelTokens) {
1065
+ maxTokens = this._maxModelTokens;
1066
+ errorMessage = `${this._manufacturer}\uFF1A\u5F53\u524D\u63D0\u95EE\u4E0A\u4E0B\u6587\u5185\u5BB9\u957F\u5EA6${numTokens}tokns\u8D85\u957F\uFF0C\u8BE5\u6A21\u578B\u6700\u5927\u63D0\u95EE\u957F\u5EA6\u4E3A${this._maxModelTokens}tokens\uFF0C\u8BF7\u5207\u6362\u5176\u4ED6\u589E\u5F3AAI\u6A21\u578B\u6216\u51CF\u5C11\u5B57\u6570\u6216\u8005\u5173\u95ED\u4E0A\u4E0B\u6587\u5386\u53F2\u63D0\u9AD8\u5355\u6B21\u63D0\u95EE\u957F\u5EA6\uFF01`;
1067
+ }
1068
+ }
1069
+ return { messages, maxTokens, numTokens, errorMessage, objText };
1070
+ }
1071
+ async _getTokenCount(text) {
1072
+ text = text.replace(/<\|endoftext\|>/g, "");
1073
+ return encode(text).length;
1074
+ }
1075
+ async _defaultGetMessageById(id) {
1076
+ const res = await this._messageStore.get(id);
1077
+ return res;
1078
+ }
1079
+ async _defaultUpsertMessage(message) {
1080
+ await this._messageStore.set(message.id, message);
1081
+ }
1082
+ };
1083
+
1084
+ // src/chatgpt-unofficial-proxy-api.ts
1085
+ import pTimeout2 from "p-timeout";
1086
+ import { v4 as uuidv42 } from "uuid";
1087
+ var ChatGPTUnofficialProxyAPI = class {
1088
+ /**
1089
+ * @param fetch - Optional override for the `fetch` implementation to use. Defaults to the global `fetch` function.
1090
+ */
1091
+ constructor(opts) {
1092
+ const {
1093
+ accessToken,
1094
+ apiReverseProxyUrl = "https://bypass.duti.tech/api/conversation",
1095
+ model = "text-davinci-002-render-sha",
1096
+ debug = false,
1097
+ headers,
1098
+ fetch: fetch2 = fetch
1099
+ } = opts;
1100
+ this._accessToken = accessToken;
1101
+ this._apiReverseProxyUrl = apiReverseProxyUrl;
1102
+ this._debug = !!debug;
1103
+ this._model = model;
1104
+ this._fetch = fetch2;
1105
+ this._headers = headers;
1106
+ if (!this._accessToken) {
1107
+ throw new Error("ChatGPT invalid accessToken");
1108
+ }
1109
+ if (!this._fetch) {
1110
+ throw new Error("Invalid environment; fetch is not defined");
1111
+ }
1112
+ if (typeof this._fetch !== "function") {
1113
+ throw new Error('Invalid "fetch" is not a function');
1114
+ }
1115
+ }
1116
+ get accessToken() {
1117
+ return this._accessToken;
1118
+ }
1119
+ set accessToken(value) {
1120
+ this._accessToken = value;
1121
+ }
1122
+ /**
1123
+ * Sends a message to ChatGPT, waits for the response to resolve, and returns
1124
+ * the response.
1125
+ *
1126
+ * If you want your response to have historical context, you must provide a valid `parentMessageId`.
1127
+ *
1128
+ * If you want to receive a stream of partial responses, use `opts.onProgress`.
1129
+ * If you want to receive the full response, including message and conversation IDs,
1130
+ * you can use `opts.onConversationResponse` or use the `ChatGPTAPI.getConversation`
1131
+ * helper.
1132
+ *
1133
+ * Set `debug: true` in the `ChatGPTAPI` constructor to log more info on the full prompt sent to the OpenAI completions API. You can override the `promptPrefix` and `promptSuffix` in `opts` to customize the prompt.
1134
+ *
1135
+ * @param message - The prompt message to send
1136
+ * @param opts.conversationId - Optional ID of a conversation to continue (defaults to a random UUID)
1137
+ * @param opts.parentMessageId - Optional ID of the previous message in the conversation (defaults to `undefined`)
1138
+ * @param opts.messageId - Optional ID of the message to send (defaults to a random UUID)
1139
+ * @param opts.timeoutMs - Optional timeout in milliseconds (defaults to no timeout)
1140
+ * @param opts.onProgress - Optional callback which will be invoked every time the partial response is updated
1141
+ * @param opts.abortSignal - Optional callback used to abort the underlying `fetch` call using an [AbortController](https://developer.mozilla.org/en-US/docs/Web/API/AbortController)
1142
+ *
1143
+ * @returns The response from ChatGPT
1144
+ */
1145
+ async sendMessage(text, opts = {}) {
1146
+ if (!!opts.conversationId !== !!opts.parentMessageId) {
1147
+ throw new Error(
1148
+ "ChatGPTUnofficialProxyAPI.sendMessage: conversationId and parentMessageId must both be set or both be undefined"
1149
+ );
1150
+ }
1151
+ if (opts.conversationId && !isValidUUIDv4(opts.conversationId)) {
1152
+ throw new Error(
1153
+ "ChatGPTUnofficialProxyAPI.sendMessage: conversationId is not a valid v4 UUID"
1154
+ );
1155
+ }
1156
+ if (opts.parentMessageId && !isValidUUIDv4(opts.parentMessageId)) {
1157
+ throw new Error(
1158
+ "ChatGPTUnofficialProxyAPI.sendMessage: parentMessageId is not a valid v4 UUID"
1159
+ );
1160
+ }
1161
+ if (opts.messageId && !isValidUUIDv4(opts.messageId)) {
1162
+ throw new Error(
1163
+ "ChatGPTUnofficialProxyAPI.sendMessage: messageId is not a valid v4 UUID"
1164
+ );
1165
+ }
1166
+ const {
1167
+ conversationId,
1168
+ parentMessageId = uuidv42(),
1169
+ messageId = uuidv42(),
1170
+ action = "next",
1171
+ timeoutMs,
1172
+ onProgress
1173
+ } = opts;
1174
+ let { abortSignal } = opts;
1175
+ let abortController = null;
1176
+ if (timeoutMs && !abortSignal) {
1177
+ abortController = new AbortController();
1178
+ abortSignal = abortController.signal;
1179
+ }
1180
+ const body = {
1181
+ action,
1182
+ messages: [
1183
+ {
1184
+ id: messageId,
1185
+ role: "user",
1186
+ content: {
1187
+ content_type: "text",
1188
+ parts: [text]
1189
+ }
1190
+ }
1191
+ ],
1192
+ model: this._model,
1193
+ parent_message_id: parentMessageId
1194
+ };
1195
+ if (conversationId) {
1196
+ body.conversation_id = conversationId;
1197
+ }
1198
+ const result = {
1199
+ role: "assistant",
1200
+ id: uuidv42(),
1201
+ parentMessageId: messageId,
1202
+ conversationId,
1203
+ text: ""
1204
+ };
1205
+ const responseP = new Promise((resolve, reject) => {
1206
+ const url = this._apiReverseProxyUrl;
1207
+ const headers = {
1208
+ ...this._headers,
1209
+ Authorization: `Bearer ${this._accessToken}`,
1210
+ Accept: "text/event-stream",
1211
+ "Content-Type": "application/json"
1212
+ };
1213
+ if (this._debug) {
1214
+ console.log("POST", url, { body, headers });
1215
+ }
1216
+ fetchSSE(
1217
+ url,
1218
+ {
1219
+ method: "POST",
1220
+ headers,
1221
+ body: JSON.stringify(body),
1222
+ signal: abortSignal,
1223
+ onMessage: (data) => {
1224
+ var _a, _b, _c;
1225
+ if (data === "[DONE]") {
1226
+ return resolve(result);
1227
+ }
1228
+ try {
1229
+ const convoResponseEvent = JSON.parse(data);
1230
+ if (convoResponseEvent.conversation_id) {
1231
+ result.conversationId = convoResponseEvent.conversation_id;
1232
+ }
1233
+ if ((_a = convoResponseEvent.message) == null ? void 0 : _a.id) {
1234
+ result.id = convoResponseEvent.message.id;
1235
+ }
1236
+ const message = convoResponseEvent.message;
1237
+ if (message) {
1238
+ let text2 = (_c = (_b = message == null ? void 0 : message.content) == null ? void 0 : _b.parts) == null ? void 0 : _c[0];
1239
+ if (text2) {
1240
+ result.text = text2;
1241
+ if (onProgress) {
1242
+ onProgress(result);
1243
+ }
1244
+ }
1245
+ }
1246
+ } catch (err) {
1247
+ if (this._debug) {
1248
+ console.warn("chatgpt unexpected JSON error", err);
1249
+ }
1250
+ }
1251
+ },
1252
+ onError: (err) => {
1253
+ reject(err);
1254
+ }
1255
+ },
1256
+ this._fetch
1257
+ ).catch((err) => {
1258
+ const errMessageL = err.toString().toLowerCase();
1259
+ if (result.text && (errMessageL === "error: typeerror: terminated" || errMessageL === "typeerror: terminated")) {
1260
+ return resolve(result);
1261
+ } else {
1262
+ return reject(err);
1263
+ }
1264
+ });
1265
+ });
1266
+ if (timeoutMs) {
1267
+ if (abortController) {
1268
+ ;
1269
+ responseP.cancel = () => {
1270
+ abortController.abort();
1271
+ };
1272
+ }
1273
+ return pTimeout2(responseP, {
1274
+ milliseconds: timeoutMs,
1275
+ message: "ChatGPT timed out waiting for response"
1276
+ });
1277
+ } else {
1278
+ return responseP;
1279
+ }
1280
+ }
1281
+ };
1282
+ export {
1283
+ ChatGPTAPI,
1284
+ ChatGPTError,
1285
+ ChatGPTUnofficialProxyAPI,
1286
+ openai
1287
+ };