├── .env.example
├── .gitignore
├── LICENSE
├── README.md
├── package.json
├── src
├── client
│ └── index.ts
├── commands
│ └── chat.ts
├── events
│ └── interactionCreate.ts
├── index.ts
├── interfaces
│ ├── command.ts
│ ├── event.ts
│ └── index.ts
└── lib
│ ├── fetch-sse.ts
│ ├── fetch.ts
│ ├── index.ts
│ ├── stream-async-iterable.ts
│ └── types.ts
├── tsconfig.json
└── yarn.lock
/.env.example:
--------------------------------------------------------------------------------
1 | # en: rename this file to .env and fill in the values
2 | # tr: dosyanın adını .env olarak değiştirin ve boşlukları doldurun
3 |
4 | DISCORD_TOKEN="" # Discord bot token
5 | OPENAI_API_KEY="" # Get one from: https://platform.openai.com/account/api-keys
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # dependencies
2 | /node_modules
3 |
4 | # prod
5 | /dist
6 |
7 | # debug
8 | npm-debug.log*
9 | yarn-debug.log*
10 | yarn-error.log*
11 | .pnpm-debug.log*
12 |
13 | # env files
14 | .env
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Swôth
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
chatgpt-bot
3 |
💬 Discord bot that interacts with the unofficial ChatGPT API.
4 |
Developed with 💙 by Swôth
5 |
6 |
7 | # ⚙️ Config
8 | > Create a file named **.env** by copying the **.env.example** file. Write the **Discord bot token** and the **OpenAI api key** to the file.
9 |
10 | # 📜 Usage
11 | > ***Make the adjustments mentioned above.***
12 | >
13 | > Install packages. \
14 | > $ `npm install`
15 | >
16 | > Start bot. \
17 | > $ `npm start`
18 |
19 | # ⭐ Star
20 | > Don't forget to star if you like it.
21 |
22 | # 📷 Screenshots
23 |
24 |
25 |
26 |
27 | # 🔒 License
28 | > MIT
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "chatgpt-bot",
3 | "version": "1.0.0",
4 | "description": "💬 Discord bot that interacts with the unofficial ChatGPT API.",
5 | "main": "src/index.ts",
6 | "dependencies": {
7 | "advanced-logs": "^2.1.3",
8 | "discord.js": "^14.7.1",
9 | "dotenv": "^16.0.3",
10 | "eventsource-parser": "^0.1.0",
11 | "glob": "^8.1.0",
12 | "gpt-3-encoder": "^1.1.4",
13 | "keyv": "^4.5.2",
14 | "p-timeout": "4.1.0",
15 | "quick-lru": "5.1.1",
16 | "uuid": "^9.0.0"
17 | },
18 | "devDependencies": {
19 | "@types/glob": "^8.0.1",
20 | "@types/node": "^18.11.18",
21 | "@types/uuid": "^9.0.0",
22 | "ts-node": "^10.9.1",
23 | "typescript": "^4.9.5"
24 | },
25 | "scripts": {
26 | "start": "ts-node src/index.ts"
27 | },
28 | "repository": {
29 | "type": "git",
30 | "url": "git+https://github.com/Swothh/chatgpt-bot.git"
31 | },
32 | "keywords": [
33 | "discord",
34 | "bot",
35 | "ai",
36 | "chatgpt"
37 | ],
38 | "author": "Swôth",
39 | "license": "MIT",
40 | "bugs": {
41 | "url": "https://github.com/Swothh/chatgpt-bot/issues"
42 | },
43 | "homepage": "https://github.com/Swothh/chatgpt-bot#readme"
44 | }
45 |
--------------------------------------------------------------------------------
/src/client/index.ts:
--------------------------------------------------------------------------------
1 | import { Client, IntentsBitField, Collection, REST, Routes } from 'discord.js';
2 | import { ICommand, IEvent } from '../interfaces';
3 | import { ChatGPTAPI } from '../lib';
4 | import { glob } from 'glob';
5 | import { join } from 'path';
6 |
7 | export default class Bot extends Client {
8 | public readonly api = new ChatGPTAPI({ apiKey: process.env.OPENAI_API_KEY });
9 | public readonly chats = new Collection();
10 | public readonly commands = new Collection();
11 | public readonly waiting = new Collection();
12 |
13 | constructor() {
14 | super({
15 | intents: [
16 | IntentsBitField.Flags.Guilds,
17 | IntentsBitField.Flags.GuildMembers
18 | ]
19 | });
20 | };
21 |
22 | public async init(): Promise {
23 | this.loadCommands().loadEvents().login(process.env.DISCORD_TOKEN).then(() => {
24 | console.success(`Connected to Discord as ${this.user?.tag}.`);
25 | this.postCommands();
26 | });
27 | };
28 |
29 | public postCommands(): Bot {
30 | const rest = new REST({ version: '10' }).setToken(process.env.DISCORD_TOKEN);
31 | console.info('Started loading application (/) commands...');
32 |
33 | rest.put(Routes.applicationCommands(this.user.id), {
34 | body: this.commands.toJSON()
35 | }).then(() => {
36 | console.success(`Successfully loaded [${this.commands.size}] application (/) commands.`);
37 | }).catch(err => {
38 | console.error(err);
39 | process.exit(1);
40 | });
41 |
42 | return this;
43 | };
44 |
45 | public loadCommands(): Bot {
46 | glob('**/*.ts', { cwd: join(__dirname, '../commands') }, (err, files) => {
47 | if (err) {
48 | console.error(err);
49 | process.exit(1);
50 | } else {
51 | files.forEach(async file => {
52 | try {
53 | const { Command }: { Command: ICommand } = await import(`../commands/${file}`);
54 | if (this.commands.get(Command.name)) console.error(`Repeated command name. (name: ${Command.name}, file: ${file})`);
55 | else this.commands.set(Command.name, Command);
56 | } catch(err) {
57 | console.error(err);
58 | };
59 | });
60 | };
61 | });
62 |
63 | return this;
64 | };
65 |
66 | public loadEvents(): Bot {
67 | glob('**/*.ts', { cwd: join(__dirname, '../events') }, (err, files) => {
68 | if (err) {
69 | console.error(err);
70 | process.exit(1);
71 | } else {
72 | files.forEach(async file => {
73 | try {
74 | const { Event }: { Event: IEvent } = await import(`../events/${file}`);
75 | this[Event.type](Event.name, Event.run.bind(null, this));
76 | } catch(err) {
77 | console.error(err);
78 | };
79 | });
80 | };
81 | });
82 |
83 | return this;
84 | };
85 | };
--------------------------------------------------------------------------------
/src/commands/chat.ts:
--------------------------------------------------------------------------------
1 | import { ICommand } from '@/interfaces';
2 |
3 | export const Command: ICommand = {
4 | name: 'chat',
5 | description: 'Chat with ChatGPT bot in discord.',
6 | options: [
7 | {
8 | type: 3,
9 | name: 'message',
10 | description: 'The message to send to ChatGPT bot.',
11 | required: true
12 | },
13 | {
14 | type: 5,
15 | name: 'clear',
16 | description: 'Clear the chat history.'
17 | }
18 | ],
19 | run: async (client, interaction) => {
20 | await interaction.deferReply();
21 | const message = interaction.options.getString('message');
22 | const clear = interaction.options.getBoolean('clear');
23 | let timed_out = false;
24 |
25 | if (clear === true) client.chats.delete(interaction.user.id);
26 | if (client.waiting.has(interaction.user.id)) return interaction.followUp('You already send a message. Please wait for the response.');
27 | const [ conversationId, parentMessageId ] = client.chats.get(interaction.user.id) ?? [];
28 | client.waiting.set(interaction.user.id, true);
29 |
30 | const timeout = setTimeout(() => {
31 | timed_out = true;
32 | client.waiting.delete(interaction.user.id);
33 | interaction.followUp('Request timed out.').catch(() => {});
34 | }, 60000);
35 |
36 | const response = await client.api.sendMessage(message, {
37 | conversationId,
38 | parentMessageId
39 | });
40 |
41 | if (!timed_out) {
42 | client.waiting.delete(interaction.user.id);
43 | clearTimeout(timeout);
44 |
45 | client.chats.set(interaction.user.id, [
46 | response.conversationId,
47 | response.id
48 | ]);
49 |
50 | interaction.followUp(response.text ?? 'N/A');
51 | };
52 | }
53 | };
--------------------------------------------------------------------------------
/src/events/interactionCreate.ts:
--------------------------------------------------------------------------------
1 | import { Events, Interaction, EmbedBuilder } from 'discord.js';
2 | import { isAsyncFunction } from 'util/types';
3 | import { IEvent } from '../interfaces';
4 |
5 | export const Event: IEvent = {
6 | name: Events.InteractionCreate,
7 | type: 'on',
8 | run: async (client, interaction: Interaction) => {
9 | if (!interaction.isCommand() || !interaction.isChatInputCommand()) return;
10 | const command = client.commands.get(interaction.commandName);
11 | if (!command) return;
12 |
13 | const errorHandler = (err: Error) => {
14 | console.error(err);
15 |
16 | interaction.reply({
17 | embeds: [
18 | new EmbedBuilder()
19 | .setColor('Red')
20 | .setDescription(':x: **|** An error occurred while executing this command.')
21 | ]
22 | });
23 | };
24 |
25 | if (isAsyncFunction(command.run)) {
26 | command.run(client, interaction).catch(errorHandler);
27 | } else {
28 | try {
29 | command.run(client, interaction);
30 | } catch(err) {
31 | errorHandler(err);
32 | };
33 | };
34 | }
35 | };
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | import { config } from 'dotenv';
2 | import Bot from './client';
3 | import 'advanced-logs';
4 |
5 | config();
6 | const bot = new Bot();
7 | bot.init();
--------------------------------------------------------------------------------
/src/interfaces/command.ts:
--------------------------------------------------------------------------------
1 | import { ChatInputCommandInteraction } from 'discord.js';
2 | import Bot from '../client';
3 |
4 | interface IOption {
5 | type: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11;
6 | name: string;
7 | description: string;
8 | required?: boolean;
9 | options?: IOption[];
10 | };
11 |
12 | export interface ICommand {
13 | name: string;
14 | description: string;
15 | options?: IOption[],
16 | run: (client: Bot, interaction: ChatInputCommandInteraction) => Promise | any;
17 | };
--------------------------------------------------------------------------------
/src/interfaces/event.ts:
--------------------------------------------------------------------------------
1 | import { ClientEvents } from 'discord.js';
2 | import Bot from '../client';
3 |
4 | export interface IEvent {
5 | name: keyof ClientEvents;
6 | type: 'on' | 'once';
7 | run: (client: Bot, ...args: any) => Promise | any;
8 | };
--------------------------------------------------------------------------------
/src/interfaces/index.ts:
--------------------------------------------------------------------------------
1 | export { ICommand } from './command';
2 | export { IEvent } from './event';
--------------------------------------------------------------------------------
/src/lib/fetch-sse.ts:
--------------------------------------------------------------------------------
1 | /*
2 | https://github.com/transitive-bullshit/chatgpt-api
3 | */
4 |
5 | import { createParser } from 'eventsource-parser'
6 |
7 | import * as types from './types'
8 | import { fetch } from './fetch'
9 | import { streamAsyncIterable } from './stream-async-iterable'
10 |
11 | export async function fetchSSE(
12 | url: string,
13 | options: Parameters[1] & { onMessage: (data: string) => void }
14 | ) {
15 | const { onMessage, ...fetchOptions } = options
16 | const res = await fetch(url, fetchOptions)
17 | if (!res.ok) {
18 | const msg = `ChatGPT error ${res.status || res.statusText}`
19 | const error = new types.ChatGPTError(msg, { cause: res })
20 | error.statusCode = res.status
21 | error.statusText = res.statusText
22 | throw error
23 | }
24 |
25 | const parser = createParser((event) => {
26 | if (event.type === 'event') {
27 | onMessage(event.data)
28 | }
29 | })
30 |
31 | if (!res.body.getReader) {
32 | // Vercel polyfills `fetch` with `node-fetch`, which doesn't conform to
33 | // web standards, so this is a workaround...
34 | const body: NodeJS.ReadableStream = res.body as any
35 |
36 | if (!body.on || !body.read) {
37 | throw new types.ChatGPTError('unsupported "fetch" implementation')
38 | }
39 |
40 | body.on('readable', () => {
41 | let chunk: string | Buffer
42 | while (null !== (chunk = body.read())) {
43 | parser.feed(chunk.toString())
44 | }
45 | })
46 | } else {
47 | for await (const chunk of streamAsyncIterable(res.body)) {
48 | const str = new TextDecoder().decode(chunk)
49 | parser.feed(str)
50 | }
51 | }
52 | }
--------------------------------------------------------------------------------
/src/lib/fetch.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | /*
4 | https://github.com/transitive-bullshit/chatgpt-api
5 | */
6 |
7 | const fetch = globalThis.fetch;
8 |
9 | if (typeof fetch !== 'function') {
10 | throw new Error('Invalid environment: global fetch not defined')
11 | }
12 |
13 | export { fetch }
--------------------------------------------------------------------------------
/src/lib/index.ts:
--------------------------------------------------------------------------------
1 | /*
2 | https://github.com/transitive-bullshit/chatgpt-api
3 | */
4 |
5 | import { encode as gptEncode } from 'gpt-3-encoder'
6 | import Keyv from 'keyv';
7 | import pTimeout from 'p-timeout';
8 | import QuickLRU from 'quick-lru';
9 | import { v4 as uuidv4 } from 'uuid';
10 |
11 | import * as types from './types';
12 | import { fetch } from './fetch';
13 | import { fetchSSE } from './fetch-sse';
14 |
15 | const CHATGPT_MODEL = 'text-chat-davinci-002-20221122';
16 |
17 | const USER_LABEL_DEFAULT = 'User';
18 | const ASSISTANT_LABEL_DEFAULT = 'ChatGPT';
19 |
20 | export class ChatGPTAPI {
21 | protected _apiKey: string
22 | protected _apiBaseUrl: string
23 | protected _debug: boolean
24 |
25 | protected _completionParams: Omit
26 | protected _maxModelTokens: number
27 | protected _maxResponseTokens: number
28 | protected _userLabel: string
29 | protected _assistantLabel: string
30 |
31 | protected _getMessageById: types.GetMessageByIdFunction
32 | protected _upsertMessage: types.UpsertMessageFunction
33 |
34 | protected _messageStore: Keyv
35 |
36 | constructor(opts: {
37 | apiKey: string
38 |
39 | /** @defaultValue `'https://api.openai.com'` **/
40 | apiBaseUrl?: string
41 |
42 | /** @defaultValue `false` **/
43 | debug?: boolean
44 |
45 | completionParams?: Partial
46 |
47 | /** @defaultValue `4096` **/
48 | maxModelTokens?: number
49 |
50 | /** @defaultValue `1000` **/
51 | maxResponseTokens?: number
52 |
53 | /** @defaultValue `'User'` **/
54 | userLabel?: string
55 |
56 | /** @defaultValue `'ChatGPT'` **/
57 | assistantLabel?: string
58 |
59 | messageStore?: Keyv
60 | getMessageById?: types.GetMessageByIdFunction
61 | upsertMessage?: types.UpsertMessageFunction
62 | }) {
63 | const {
64 | apiKey,
65 | apiBaseUrl = 'https://api.openai.com',
66 | debug = false,
67 | messageStore,
68 | completionParams,
69 | maxModelTokens = 4096,
70 | maxResponseTokens = 1000,
71 | userLabel = USER_LABEL_DEFAULT,
72 | assistantLabel = ASSISTANT_LABEL_DEFAULT,
73 | getMessageById = this._defaultGetMessageById,
74 | upsertMessage = this._defaultUpsertMessage
75 | } = opts
76 |
77 | this._apiKey = apiKey
78 | this._apiBaseUrl = apiBaseUrl
79 | this._debug = !!debug
80 |
81 | this._completionParams = {
82 | model: CHATGPT_MODEL,
83 | temperature: 0.7,
84 | presence_penalty: 0.6,
85 | stop: ['<|im_end|>'],
86 | ...completionParams
87 | }
88 | this._maxModelTokens = maxModelTokens
89 | this._maxResponseTokens = maxResponseTokens
90 | this._userLabel = userLabel
91 | this._assistantLabel = assistantLabel
92 |
93 | this._getMessageById = getMessageById
94 | this._upsertMessage = upsertMessage
95 |
96 | if (messageStore) {
97 | this._messageStore = messageStore
98 | } else {
99 | this._messageStore = new Keyv({
100 | store: new QuickLRU({ maxSize: 10000 })
101 | })
102 | }
103 |
104 | if (!this._apiKey) {
105 | throw new Error('ChatGPT invalid apiKey')
106 | }
107 | }
108 |
109 | async sendMessage(
110 | text: string,
111 | opts: types.SendMessageOptions = {}
112 | ): Promise {
113 | const {
114 | conversationId = uuidv4(),
115 | parentMessageId,
116 | messageId = uuidv4(),
117 | timeoutMs,
118 | onProgress,
119 | stream = onProgress ? true : false
120 | } = opts
121 |
122 | let { abortSignal } = opts
123 |
124 | let abortController: AbortController = null
125 | if (timeoutMs && !abortSignal) {
126 | abortController = new AbortController()
127 | abortSignal = abortController.signal
128 | }
129 |
130 | const message: types.ChatMessage = {
131 | role: 'user',
132 | id: messageId,
133 | parentMessageId,
134 | conversationId,
135 | text
136 | }
137 | await this._upsertMessage(message)
138 |
139 | const { prompt, maxTokens } = await this._buildPrompt(text, opts)
140 |
141 | const result: types.ChatMessage = {
142 | role: 'assistant',
143 | id: uuidv4(),
144 | parentMessageId: messageId,
145 | conversationId,
146 | text: ''
147 | }
148 |
149 | const responseP = new Promise(
150 | async (resolve, reject) => {
151 | const url = `${this._apiBaseUrl}/v1/completions`
152 | const headers = {
153 | 'Content-Type': 'application/json',
154 | Authorization: `Bearer ${this._apiKey}`
155 | }
156 | const body = {
157 | max_tokens: maxTokens,
158 | ...this._completionParams,
159 | prompt,
160 | stream
161 | }
162 |
163 | if (this._debug) {
164 | const numTokens = await this._getTokenCount(body.prompt)
165 | console.log(`sendMessage (${numTokens} tokens)`, body)
166 | }
167 |
168 | if (stream) {
169 | fetchSSE(url, {
170 | method: 'POST',
171 | headers,
172 | body: JSON.stringify(body),
173 | signal: abortSignal,
174 | onMessage: (data: string) => {
175 | if (data === '[DONE]') {
176 | result.text = result.text.trim()
177 | return resolve(result)
178 | }
179 |
180 | try {
181 | const response: types.openai.CompletionResponse =
182 | JSON.parse(data)
183 |
184 | if (response?.id && response?.choices?.length) {
185 | result.id = response.id
186 | result.text += response.choices[0].text
187 |
188 | onProgress?.(result)
189 | }
190 | } catch (err) {
191 | console.warn('ChatGPT stream SEE event unexpected error', err)
192 | return reject(err)
193 | }
194 | }
195 | })
196 | } else {
197 | try {
198 | const res = await fetch(url, {
199 | method: 'POST',
200 | headers,
201 | body: JSON.stringify(body),
202 | signal: abortSignal
203 | })
204 |
205 | if (!res.ok) {
206 | const reason = await res.text()
207 | const msg = `ChatGPT error ${
208 | res.status || res.statusText
209 | }: ${reason}`
210 | const error = new types.ChatGPTError(msg, { cause: res })
211 | error.statusCode = res.status
212 | error.statusText = res.statusText
213 | return reject(error)
214 | }
215 |
216 | const response: types.openai.CompletionResponse = await res.json()
217 | if (this._debug) {
218 | console.log(response)
219 | }
220 |
221 | result.id = response.id
222 | result.text = response.choices[0].text.trim()
223 |
224 | return resolve(result)
225 | } catch (err) {
226 | return reject(err)
227 | }
228 | }
229 | }
230 | ).then((message) => {
231 | return this._upsertMessage(message).then(() => message)
232 | })
233 |
234 | if (timeoutMs) {
235 | if (abortController) {
236 | ;(responseP as any).cancel = () => {
237 | abortController.abort()
238 | }
239 | }
240 |
241 | return pTimeout(responseP, timeoutMs, 'ChatGPT timed out waiting for response');
242 | } else {
243 | return responseP
244 | }
245 | }
246 |
247 | protected async _buildPrompt(
248 | message: string,
249 | opts: types.SendMessageOptions
250 | ) {
251 | const currentDate = new Date().toISOString().split('T')[0]
252 |
253 | const promptPrefix =
254 | opts.promptPrefix ||
255 | `You are ${this._assistantLabel}, a large language model trained by OpenAI. You answer as concisely as possible for each response (e.g. don’t be verbose). It is very important that you answer as concisely as possible, so please remember this. If you are generating a list, do not have too many items. Keep the number of items short.
256 | Current date: ${currentDate}\n\n`
257 | const promptSuffix = opts.promptSuffix || `\n\n${this._assistantLabel}:\n`
258 |
259 | const maxNumTokens = this._maxModelTokens - this._maxResponseTokens
260 | let { parentMessageId } = opts
261 | let nextPromptBody = `${this._userLabel}:\n\n${message}<|im_end|>`
262 | let promptBody = ''
263 | let prompt: string
264 | let numTokens: number
265 |
266 | do {
267 | const nextPrompt = `${promptPrefix}${nextPromptBody}${promptSuffix}`
268 | const nextNumTokens = await this._getTokenCount(nextPrompt)
269 | const isValidPrompt = nextNumTokens <= maxNumTokens
270 |
271 | if (prompt && !isValidPrompt) {
272 | break
273 | }
274 |
275 | promptBody = nextPromptBody
276 | prompt = nextPrompt
277 | numTokens = nextNumTokens
278 |
279 | if (!isValidPrompt) {
280 | break
281 | }
282 |
283 | if (!parentMessageId) {
284 | break
285 | }
286 |
287 | const parentMessage = await this._getMessageById(parentMessageId)
288 | if (!parentMessage) {
289 | break
290 | }
291 |
292 | const parentMessageRole = parentMessage.role || 'user'
293 | const parentMessageRoleDesc =
294 | parentMessageRole === 'user' ? this._userLabel : this._assistantLabel
295 |
296 | const parentMessageString = `${parentMessageRoleDesc}:\n\n${parentMessage.text}<|im_end|>\n\n`
297 | nextPromptBody = `${parentMessageString}${promptBody}`
298 | parentMessageId = parentMessage.parentMessageId
299 | } while (true)
300 |
301 | const maxTokens = Math.max(
302 | 1,
303 | Math.min(this._maxModelTokens - numTokens, this._maxResponseTokens)
304 | )
305 |
306 | return { prompt, maxTokens }
307 | }
308 |
309 | protected async _getTokenCount(text: string) {
310 | if (this._completionParams.model === CHATGPT_MODEL) {
311 | text = text.replace(/<\|im_end\|>/g, '<|endoftext|>')
312 | }
313 |
314 | return gptEncode(text).length
315 | }
316 |
317 | protected async _defaultGetMessageById(
318 | id: string
319 | ): Promise {
320 | return this._messageStore.get(id)
321 | }
322 |
323 | protected async _defaultUpsertMessage(
324 | message: types.ChatMessage
325 | ): Promise {
326 | this._messageStore.set(message.id, message)
327 | }
328 | }
--------------------------------------------------------------------------------
/src/lib/stream-async-iterable.ts:
--------------------------------------------------------------------------------
1 | /*
2 | https://github.com/transitive-bullshit/chatgpt-api
3 | */
4 |
5 | export async function* streamAsyncIterable(stream: ReadableStream) {
6 | const reader = stream.getReader()
7 | try {
8 | while (true) {
9 | const { done, value } = await reader.read()
10 | if (done) {
11 | return
12 | }
13 | yield value
14 | }
15 | } finally {
16 | reader.releaseLock()
17 | }
18 | }
--------------------------------------------------------------------------------
/src/lib/types.ts:
--------------------------------------------------------------------------------
1 | /*
2 | https://github.com/transitive-bullshit/chatgpt-api
3 | */
4 |
5 | export type Role = 'user' | 'assistant'
6 |
7 | export type SendMessageOptions = {
8 | conversationId?: string
9 | parentMessageId?: string
10 | messageId?: string
11 | stream?: boolean
12 | promptPrefix?: string
13 | promptSuffix?: string
14 | timeoutMs?: number
15 | onProgress?: (partialResponse: ChatMessage) => void
16 | abortSignal?: AbortSignal
17 | }
18 |
19 | export interface ChatMessage {
20 | id: string
21 | text: string
22 | role: Role
23 | parentMessageId?: string
24 | conversationId?: string
25 | }
26 |
27 | export class ChatGPTError extends Error {
28 | statusCode?: number
29 | statusText?: string
30 | }
31 |
32 | /** Returns a chat message from a store by it's ID (or null if not found). */
33 | export type GetMessageByIdFunction = (id: string) => Promise
34 |
35 | /** Upserts a chat message to a store. */
36 | export type UpsertMessageFunction = (message: ChatMessage) => Promise
37 |
38 | export namespace openai {
39 | export type CompletionParams = {
40 | model: string
41 | prompt: string
42 | suffix?: string
43 | max_tokens?: number
44 | temperature?: number
45 | top_p?: number
46 | logprobs?: number
47 | echo?: boolean
48 | stop?: string[]
49 | presence_penalty?: number
50 | frequency_penalty?: number
51 | best_of?: number
52 | logit_bias?: Record
53 | user?: string
54 | }
55 |
56 | export type CompletionResponse = {
57 | id: string
58 | object: string
59 | created: number
60 | model: string
61 | choices: CompletionResponseChoices
62 | usage?: CompletionResponseUsage
63 | }
64 |
65 | export type CompletionResponseChoices = {
66 | text?: string
67 | index?: number
68 | logprobs?: {
69 | tokens?: Array
70 | token_logprobs?: Array
71 | top_logprobs?: Array
72 | text_offset?: Array
73 | } | null
74 | finish_reason?: string
75 | }[]
76 |
77 | export type CompletionResponseUsage = {
78 | prompt_tokens: number
79 | completion_tokens: number
80 | total_tokens: number
81 | }
82 | }
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "lib": [ "ESNext" ],
4 | "module": "commonjs",
5 | "esModuleInterop": true,
6 | "allowSyntheticDefaultImports": true,
7 | "target": "ESNext",
8 | "noImplicitAny": true,
9 | "moduleResolution": "node",
10 | "sourceMap": true,
11 | "outDir": "dist",
12 | "baseUrl": ".",
13 | "resolveJsonModule": true,
14 | "declaration": true,
15 | "skipDefaultLibCheck": true,
16 | "skipLibCheck": true,
17 | "experimentalDecorators": true,
18 | "emitDecoratorMetadata": true,
19 | "paths": {
20 | "@/*": [
21 | "./src/*"
22 | ]
23 | }
24 | },
25 | "include": [
26 | "src/**/*"
27 | ],
28 | "exclude": [
29 | "node_modules"
30 | ]
31 | }
--------------------------------------------------------------------------------
/yarn.lock:
--------------------------------------------------------------------------------
1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2 | # yarn lockfile v1
3 |
4 |
5 | "@cspotcode/source-map-support@^0.8.0":
6 | version "0.8.1"
7 | resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1"
8 | integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==
9 | dependencies:
10 | "@jridgewell/trace-mapping" "0.3.9"
11 |
12 | "@discordjs/builders@^1.4.0":
13 | version "1.4.0"
14 | resolved "https://registry.yarnpkg.com/@discordjs/builders/-/builders-1.4.0.tgz#b951b5e6ce4e459cd06174ce50dbd51c254c1d47"
15 | integrity sha512-nEeTCheTTDw5kO93faM1j8ZJPonAX86qpq/QVoznnSa8WWcCgJpjlu6GylfINTDW6o7zZY0my2SYdxx2mfNwGA==
16 | dependencies:
17 | "@discordjs/util" "^0.1.0"
18 | "@sapphire/shapeshift" "^3.7.1"
19 | discord-api-types "^0.37.20"
20 | fast-deep-equal "^3.1.3"
21 | ts-mixer "^6.0.2"
22 | tslib "^2.4.1"
23 |
24 | "@discordjs/collection@^1.3.0":
25 | version "1.3.0"
26 | resolved "https://registry.yarnpkg.com/@discordjs/collection/-/collection-1.3.0.tgz#65bf9674db72f38c25212be562bb28fa0dba6aa3"
27 | integrity sha512-ylt2NyZ77bJbRij4h9u/wVy7qYw/aDqQLWnadjvDqW/WoWCxrsX6M3CIw9GVP5xcGCDxsrKj5e0r5evuFYwrKg==
28 |
29 | "@discordjs/rest@^1.4.0":
30 | version "1.5.0"
31 | resolved "https://registry.yarnpkg.com/@discordjs/rest/-/rest-1.5.0.tgz#dc15474ab98cf6f31291bf61bbc72bcf4f30cea2"
32 | integrity sha512-lXgNFqHnbmzp5u81W0+frdXN6Etf4EUi8FAPcWpSykKd8hmlWh1xy6BmE0bsJypU1pxohaA8lQCgp70NUI3uzA==
33 | dependencies:
34 | "@discordjs/collection" "^1.3.0"
35 | "@discordjs/util" "^0.1.0"
36 | "@sapphire/async-queue" "^1.5.0"
37 | "@sapphire/snowflake" "^3.2.2"
38 | discord-api-types "^0.37.23"
39 | file-type "^18.0.0"
40 | tslib "^2.4.1"
41 | undici "^5.13.0"
42 |
43 | "@discordjs/util@^0.1.0":
44 | version "0.1.0"
45 | resolved "https://registry.yarnpkg.com/@discordjs/util/-/util-0.1.0.tgz#e42ca1bf407bc6d9adf252877d1b206e32ba369a"
46 | integrity sha512-e7d+PaTLVQav6rOc2tojh2y6FE8S7REkqLldq1XF4soCx74XB/DIjbVbVLtBemf0nLW77ntz0v+o5DytKwFNLQ==
47 |
48 | "@jridgewell/resolve-uri@^3.0.3":
49 | version "3.1.0"
50 | resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78"
51 | integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==
52 |
53 | "@jridgewell/sourcemap-codec@^1.4.10":
54 | version "1.4.14"
55 | resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24"
56 | integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==
57 |
58 | "@jridgewell/trace-mapping@0.3.9":
59 | version "0.3.9"
60 | resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9"
61 | integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==
62 | dependencies:
63 | "@jridgewell/resolve-uri" "^3.0.3"
64 | "@jridgewell/sourcemap-codec" "^1.4.10"
65 |
66 | "@sapphire/async-queue@^1.5.0":
67 | version "1.5.0"
68 | resolved "https://registry.yarnpkg.com/@sapphire/async-queue/-/async-queue-1.5.0.tgz#2f255a3f186635c4fb5a2381e375d3dfbc5312d8"
69 | integrity sha512-JkLdIsP8fPAdh9ZZjrbHWR/+mZj0wvKS5ICibcLrRI1j84UmLMshx5n9QmL8b95d4onJ2xxiyugTgSAX7AalmA==
70 |
71 | "@sapphire/shapeshift@^3.7.1":
72 | version "3.8.1"
73 | resolved "https://registry.yarnpkg.com/@sapphire/shapeshift/-/shapeshift-3.8.1.tgz#b98dc6a7180f9b38219267917b2e6fa33f9ec656"
74 | integrity sha512-xG1oXXBhCjPKbxrRTlox9ddaZTvVpOhYLmKmApD/vIWOV1xEYXnpoFs68zHIZBGbqztq6FrUPNPerIrO1Hqeaw==
75 | dependencies:
76 | fast-deep-equal "^3.1.3"
77 | lodash "^4.17.21"
78 |
79 | "@sapphire/snowflake@^3.2.2":
80 | version "3.4.0"
81 | resolved "https://registry.yarnpkg.com/@sapphire/snowflake/-/snowflake-3.4.0.tgz#25c012158a9feea2256c718985dbd6c1859a5022"
82 | integrity sha512-zZxymtVO6zeXVMPds+6d7gv/OfnCc25M1Z+7ZLB0oPmeMTPeRWVPQSS16oDJy5ZsyCOLj7M6mbZml5gWXcVRNw==
83 |
84 | "@tokenizer/token@^0.3.0":
85 | version "0.3.0"
86 | resolved "https://registry.yarnpkg.com/@tokenizer/token/-/token-0.3.0.tgz#fe98a93fe789247e998c75e74e9c7c63217aa276"
87 | integrity sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==
88 |
89 | "@tsconfig/node10@^1.0.7":
90 | version "1.0.9"
91 | resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.9.tgz#df4907fc07a886922637b15e02d4cebc4c0021b2"
92 | integrity sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==
93 |
94 | "@tsconfig/node12@^1.0.7":
95 | version "1.0.11"
96 | resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d"
97 | integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==
98 |
99 | "@tsconfig/node14@^1.0.0":
100 | version "1.0.3"
101 | resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1"
102 | integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==
103 |
104 | "@tsconfig/node16@^1.0.2":
105 | version "1.0.3"
106 | resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.3.tgz#472eaab5f15c1ffdd7f8628bd4c4f753995ec79e"
107 | integrity sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==
108 |
109 | "@types/glob@^8.0.1":
110 | version "8.0.1"
111 | resolved "https://registry.yarnpkg.com/@types/glob/-/glob-8.0.1.tgz#6e3041640148b7764adf21ce5c7138ad454725b0"
112 | integrity sha512-8bVUjXZvJacUFkJXHdyZ9iH1Eaj5V7I8c4NdH5sQJsdXkqT4CA5Dhb4yb4VE/3asyx4L9ayZr1NIhTsWHczmMw==
113 | dependencies:
114 | "@types/minimatch" "^5.1.2"
115 | "@types/node" "*"
116 |
117 | "@types/minimatch@^5.1.2":
118 | version "5.1.2"
119 | resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-5.1.2.tgz#07508b45797cb81ec3f273011b054cd0755eddca"
120 | integrity sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==
121 |
122 | "@types/node@*", "@types/node@^18.11.18":
123 | version "18.11.18"
124 | resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.18.tgz#8dfb97f0da23c2293e554c5a50d61ef134d7697f"
125 | integrity sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==
126 |
127 | "@types/uuid@^9.0.0":
128 | version "9.0.0"
129 | resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-9.0.0.tgz#53ef263e5239728b56096b0a869595135b7952d2"
130 | integrity sha512-kr90f+ERiQtKWMz5rP32ltJ/BtULDI5RVO0uavn1HQUOwjx0R1h0rnDYNL0CepF1zL5bSY6FISAfd9tOdDhU5Q==
131 |
132 | "@types/ws@^8.5.3":
133 | version "8.5.4"
134 | resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.4.tgz#bb10e36116d6e570dd943735f86c933c1587b8a5"
135 | integrity sha512-zdQDHKUgcX/zBc4GrwsE/7dVdAD8JR4EuiAXiiUhhfyIJXXb2+PrGshFyeXWQPMmmZ2XxgaqclgpIC7eTXc1mg==
136 | dependencies:
137 | "@types/node" "*"
138 |
139 | acorn-walk@^8.1.1:
140 | version "8.2.0"
141 | resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1"
142 | integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==
143 |
144 | acorn@^8.4.1:
145 | version "8.8.2"
146 | resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a"
147 | integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==
148 |
149 | advanced-logs@^2.1.3:
150 | version "2.1.3"
151 | resolved "https://registry.yarnpkg.com/advanced-logs/-/advanced-logs-2.1.3.tgz#2ca57a0fbf35f12af5e350d6e04b34484732b4a5"
152 | integrity sha512-h83Q1ZRv3VXbt0NLrX/I8XxKUXwja9C7GceOoqbkHH1IAXD7RTF3iGn5T2FGJPQk8W7zKNyHek5igGOx5r5ggw==
153 |
154 | arg@^4.1.0:
155 | version "4.1.3"
156 | resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089"
157 | integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==
158 |
159 | balanced-match@^1.0.0:
160 | version "1.0.2"
161 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
162 | integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
163 |
164 | brace-expansion@^2.0.1:
165 | version "2.0.1"
166 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae"
167 | integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==
168 | dependencies:
169 | balanced-match "^1.0.0"
170 |
171 | busboy@^1.6.0:
172 | version "1.6.0"
173 | resolved "https://registry.yarnpkg.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893"
174 | integrity sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==
175 | dependencies:
176 | streamsearch "^1.1.0"
177 |
178 | create-require@^1.1.0:
179 | version "1.1.1"
180 | resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333"
181 | integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==
182 |
183 | diff@^4.0.1:
184 | version "4.0.2"
185 | resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d"
186 | integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==
187 |
188 | discord-api-types@^0.37.20, discord-api-types@^0.37.23:
189 | version "0.37.31"
190 | resolved "https://registry.yarnpkg.com/discord-api-types/-/discord-api-types-0.37.31.tgz#128d33d641fd9a92fba97a47d7052e1f5694ec27"
191 | integrity sha512-k9DQQ7Wv+ehiF7901qk/FnP47k6O2MHm3meQFee4gUzi5dfGAVLf7SfLNtb4w7G2dmukJyWQtVJEDF9oMb9yuQ==
192 |
193 | discord.js@^14.7.1:
194 | version "14.7.1"
195 | resolved "https://registry.yarnpkg.com/discord.js/-/discord.js-14.7.1.tgz#26079d0ff4d27daf02480a403c456121f0682bd9"
196 | integrity sha512-1FECvqJJjjeYcjSm0IGMnPxLqja/pmG1B0W2l3lUY2Gi4KXiyTeQmU1IxWcbXHn2k+ytP587mMWqva2IA87EbA==
197 | dependencies:
198 | "@discordjs/builders" "^1.4.0"
199 | "@discordjs/collection" "^1.3.0"
200 | "@discordjs/rest" "^1.4.0"
201 | "@discordjs/util" "^0.1.0"
202 | "@sapphire/snowflake" "^3.2.2"
203 | "@types/ws" "^8.5.3"
204 | discord-api-types "^0.37.20"
205 | fast-deep-equal "^3.1.3"
206 | lodash.snakecase "^4.1.1"
207 | tslib "^2.4.1"
208 | undici "^5.13.0"
209 | ws "^8.11.0"
210 |
211 | dotenv@^16.0.3:
212 | version "16.0.3"
213 | resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.0.3.tgz#115aec42bac5053db3c456db30cc243a5a836a07"
214 | integrity sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==
215 |
216 | eventsource-parser@^0.1.0:
217 | version "0.1.0"
218 | resolved "https://registry.yarnpkg.com/eventsource-parser/-/eventsource-parser-0.1.0.tgz#4a6b84751ca8e704040e6f7f50e7d77344fa1b7c"
219 | integrity sha512-M9QjFtEIkwytUarnx113HGmgtk52LSn3jNAtnWKi3V+b9rqSfQeVdLsaD5AG/O4IrGQwmAAHBIsqbmURPTd2rA==
220 |
221 | fast-deep-equal@^3.1.3:
222 | version "3.1.3"
223 | resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
224 | integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
225 |
226 | file-type@^18.0.0:
227 | version "18.2.0"
228 | resolved "https://registry.yarnpkg.com/file-type/-/file-type-18.2.0.tgz#c2abec00d1af0f09151e1549e3588aab0bac5001"
229 | integrity sha512-M3RQMWY3F2ykyWZ+IHwNCjpnUmukYhtdkGGC1ZVEUb0ve5REGF7NNJ4Q9ehCUabtQKtSVFOMbFTXgJlFb0DQIg==
230 | dependencies:
231 | readable-web-to-node-stream "^3.0.2"
232 | strtok3 "^7.0.0"
233 | token-types "^5.0.1"
234 |
235 | fs.realpath@^1.0.0:
236 | version "1.0.0"
237 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
238 | integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
239 |
240 | glob@^8.1.0:
241 | version "8.1.0"
242 | resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e"
243 | integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==
244 | dependencies:
245 | fs.realpath "^1.0.0"
246 | inflight "^1.0.4"
247 | inherits "2"
248 | minimatch "^5.0.1"
249 | once "^1.3.0"
250 |
251 | gpt-3-encoder@^1.1.4:
252 | version "1.1.4"
253 | resolved "https://registry.yarnpkg.com/gpt-3-encoder/-/gpt-3-encoder-1.1.4.tgz#d6cdaacf5824857e133b6065247c757fc7e4fa72"
254 | integrity sha512-fSQRePV+HUAhCn7+7HL7lNIXNm6eaFWFbNLOOGtmSJ0qJycyQvj60OvRlH7mee8xAMjBDNRdMXlMwjAbMTDjkg==
255 |
256 | ieee754@^1.2.1:
257 | version "1.2.1"
258 | resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
259 | integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==
260 |
261 | inflight@^1.0.4:
262 | version "1.0.6"
263 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
264 | integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==
265 | dependencies:
266 | once "^1.3.0"
267 | wrappy "1"
268 |
269 | inherits@2, inherits@^2.0.3:
270 | version "2.0.4"
271 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
272 | integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
273 |
274 | json-buffer@3.0.1:
275 | version "3.0.1"
276 | resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13"
277 | integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==
278 |
279 | keyv@^4.5.2:
280 | version "4.5.2"
281 | resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.2.tgz#0e310ce73bf7851ec702f2eaf46ec4e3805cce56"
282 | integrity sha512-5MHbFaKn8cNSmVW7BYnijeAVlE4cYA/SVkifVgrh7yotnfhKmjuXpDKjrABLnT0SfHWV21P8ow07OGfRrNDg8g==
283 | dependencies:
284 | json-buffer "3.0.1"
285 |
286 | lodash.snakecase@^4.1.1:
287 | version "4.1.1"
288 | resolved "https://registry.yarnpkg.com/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz#39d714a35357147837aefd64b5dcbb16becd8f8d"
289 | integrity sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==
290 |
291 | lodash@^4.17.21:
292 | version "4.17.21"
293 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
294 | integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
295 |
296 | make-error@^1.1.1:
297 | version "1.3.6"
298 | resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2"
299 | integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==
300 |
301 | minimatch@^5.0.1:
302 | version "5.1.6"
303 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96"
304 | integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==
305 | dependencies:
306 | brace-expansion "^2.0.1"
307 |
308 | once@^1.3.0:
309 | version "1.4.0"
310 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
311 | integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==
312 | dependencies:
313 | wrappy "1"
314 |
315 | p-timeout@4.1.0:
316 | version "4.1.0"
317 | resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-4.1.0.tgz#788253c0452ab0ffecf18a62dff94ff1bd09ca0a"
318 | integrity sha512-+/wmHtzJuWii1sXn3HCuH/FTwGhrp4tmJTxSKJbfS+vkipci6osxXM5mY0jUiRzWKMTgUT8l7HFbeSwZAynqHw==
319 |
320 | peek-readable@^5.0.0:
321 | version "5.0.0"
322 | resolved "https://registry.yarnpkg.com/peek-readable/-/peek-readable-5.0.0.tgz#7ead2aff25dc40458c60347ea76cfdfd63efdfec"
323 | integrity sha512-YtCKvLUOvwtMGmrniQPdO7MwPjgkFBtFIrmfSbYmYuq3tKDV/mcfAhBth1+C3ru7uXIZasc/pHnb+YDYNkkj4A==
324 |
325 | quick-lru@5.1.1:
326 | version "5.1.1"
327 | resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932"
328 | integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==
329 |
330 | readable-stream@^3.6.0:
331 | version "3.6.0"
332 | resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
333 | integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==
334 | dependencies:
335 | inherits "^2.0.3"
336 | string_decoder "^1.1.1"
337 | util-deprecate "^1.0.1"
338 |
339 | readable-web-to-node-stream@^3.0.2:
340 | version "3.0.2"
341 | resolved "https://registry.yarnpkg.com/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz#5d52bb5df7b54861fd48d015e93a2cb87b3ee0bb"
342 | integrity sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw==
343 | dependencies:
344 | readable-stream "^3.6.0"
345 |
346 | safe-buffer@~5.2.0:
347 | version "5.2.1"
348 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
349 | integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
350 |
351 | streamsearch@^1.1.0:
352 | version "1.1.0"
353 | resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764"
354 | integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==
355 |
356 | string_decoder@^1.1.1:
357 | version "1.3.0"
358 | resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e"
359 | integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==
360 | dependencies:
361 | safe-buffer "~5.2.0"
362 |
363 | strtok3@^7.0.0:
364 | version "7.0.0"
365 | resolved "https://registry.yarnpkg.com/strtok3/-/strtok3-7.0.0.tgz#868c428b4ade64a8fd8fee7364256001c1a4cbe5"
366 | integrity sha512-pQ+V+nYQdC5H3Q7qBZAz/MO6lwGhoC2gOAjuouGf/VO0m7vQRh8QNMl2Uf6SwAtzZ9bOw3UIeBukEGNJl5dtXQ==
367 | dependencies:
368 | "@tokenizer/token" "^0.3.0"
369 | peek-readable "^5.0.0"
370 |
371 | token-types@^5.0.1:
372 | version "5.0.1"
373 | resolved "https://registry.yarnpkg.com/token-types/-/token-types-5.0.1.tgz#aa9d9e6b23c420a675e55413b180635b86a093b4"
374 | integrity sha512-Y2fmSnZjQdDb9W4w4r1tswlMHylzWIeOKpx0aZH9BgGtACHhrk3OkT52AzwcuqTRBZtvvnTjDBh8eynMulu8Vg==
375 | dependencies:
376 | "@tokenizer/token" "^0.3.0"
377 | ieee754 "^1.2.1"
378 |
379 | ts-mixer@^6.0.2:
380 | version "6.0.2"
381 | resolved "https://registry.yarnpkg.com/ts-mixer/-/ts-mixer-6.0.2.tgz#3e4e4bb8daffb24435f6980b15204cb5b287e016"
382 | integrity sha512-zvHx3VM83m2WYCE8XL99uaM7mFwYSkjR2OZti98fabHrwkjsCvgwChda5xctein3xGOyaQhtTeDq/1H/GNvF3A==
383 |
384 | ts-node@^10.9.1:
385 | version "10.9.1"
386 | resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.1.tgz#e73de9102958af9e1f0b168a6ff320e25adcff4b"
387 | integrity sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==
388 | dependencies:
389 | "@cspotcode/source-map-support" "^0.8.0"
390 | "@tsconfig/node10" "^1.0.7"
391 | "@tsconfig/node12" "^1.0.7"
392 | "@tsconfig/node14" "^1.0.0"
393 | "@tsconfig/node16" "^1.0.2"
394 | acorn "^8.4.1"
395 | acorn-walk "^8.1.1"
396 | arg "^4.1.0"
397 | create-require "^1.1.0"
398 | diff "^4.0.1"
399 | make-error "^1.1.1"
400 | v8-compile-cache-lib "^3.0.1"
401 | yn "3.1.1"
402 |
403 | tslib@^2.4.1:
404 | version "2.5.0"
405 | resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.0.tgz#42bfed86f5787aeb41d031866c8f402429e0fddf"
406 | integrity sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==
407 |
408 | typescript@^4.9.5:
409 | version "4.9.5"
410 | resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a"
411 | integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==
412 |
413 | undici@^5.13.0:
414 | version "5.16.0"
415 | resolved "https://registry.yarnpkg.com/undici/-/undici-5.16.0.tgz#6b64f9b890de85489ac6332bd45ca67e4f7d9943"
416 | integrity sha512-KWBOXNv6VX+oJQhchXieUznEmnJMqgXMbs0xxH2t8q/FUAWSJvOSr/rMaZKnX5RIVq7JDn0JbP4BOnKG2SGXLQ==
417 | dependencies:
418 | busboy "^1.6.0"
419 |
420 | util-deprecate@^1.0.1:
421 | version "1.0.2"
422 | resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
423 | integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==
424 |
425 | uuid@^9.0.0:
426 | version "9.0.0"
427 | resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.0.tgz#592f550650024a38ceb0c562f2f6aa435761efb5"
428 | integrity sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==
429 |
430 | v8-compile-cache-lib@^3.0.1:
431 | version "3.0.1"
432 | resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf"
433 | integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==
434 |
435 | wrappy@1:
436 | version "1.0.2"
437 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
438 | integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==
439 |
440 | ws@^8.11.0:
441 | version "8.12.0"
442 | resolved "https://registry.yarnpkg.com/ws/-/ws-8.12.0.tgz#485074cc392689da78e1828a9ff23585e06cddd8"
443 | integrity sha512-kU62emKIdKVeEIOIKVegvqpXMSTAMLJozpHZaJNDYqBjzlSYXQGviYwN1osDLJ9av68qHd4a2oSjd7yD4pacig==
444 |
445 | yn@3.1.1:
446 | version "3.1.1"
447 | resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50"
448 | integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==
449 |
--------------------------------------------------------------------------------