From 39f5bca42ac977cee71795abc87715ea577e4ba5 Mon Sep 17 00:00:00 2001 From: Kirigaya <1193466151@qq.com> Date: Wed, 29 May 2024 20:58:45 +0800 Subject: [PATCH] first --- .gitignore | 9 + .vscode/typescript.code-snippets | 36 ++ README.md | 62 +++ bot/api/request.ts | 43 ++ bot/api/vecdb.ts | 31 ++ bot/lagrange-mapping.ts | 0 bot/main.ts | 40 ++ bot/type.d.ts | 148 +++++++ config/bot.yml | 0 config/vecdb.yml | 2 + package.json | 26 ++ rag/constant.py | 12 + rag/embedding.py | 29 ++ rag/main.py | 58 +++ rag/test.ipynb | 295 ++++++++++++++ rag/test.py | 14 + rag/url_mapping.py | 53 +++ requirements.txt | 5 + tsconfig.json | 11 + yarn.lock | 672 +++++++++++++++++++++++++++++++ 20 files changed, 1546 insertions(+) create mode 100644 .gitignore create mode 100644 .vscode/typescript.code-snippets create mode 100644 README.md create mode 100644 bot/api/request.ts create mode 100644 bot/api/vecdb.ts create mode 100644 bot/lagrange-mapping.ts create mode 100644 bot/main.ts create mode 100644 bot/type.d.ts create mode 100644 config/bot.yml create mode 100644 config/vecdb.yml create mode 100644 package.json create mode 100644 rag/constant.py create mode 100644 rag/embedding.py create mode 100644 rag/main.py create mode 100644 rag/test.ipynb create mode 100644 rag/test.py create mode 100644 rag/url_mapping.py create mode 100644 requirements.txt create mode 100644 tsconfig.json create mode 100644 yarn.lock diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..01e9d22 --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +app +docs +blog-vecdb +dist +node_modules +__pycache__ +*.pyc +*.pyd +*.pyi \ No newline at end of file diff --git a/.vscode/typescript.code-snippets b/.vscode/typescript.code-snippets new file mode 100644 index 0000000..d044ad9 --- /dev/null +++ b/.vscode/typescript.code-snippets @@ -0,0 +1,36 @@ +{ + "create api function": { + "scope": "typescript", + "prefix": "api", + "body": [ + "export const api$1 = (req: api$1Request) => r>({", + "\turl: '$2', method: '$3',", + "\t", + "});", + "", + "export interface api$1Request {", + "}", + "", + "export type api$1Data = EmptyObject;" + ] + }, + "vue template": { + "scope": "vue", + "prefix": "vue", + "body": [ + "", + "", + "", + "", + "" + ] + } +} \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..f873917 --- /dev/null +++ b/README.md @@ -0,0 +1,62 @@ +![LagrangeRagBot](https://socialify.git.ci/LSTM-Kirigaya/LagrangeRagBot/image?description=1&descriptionEditable=%E7%94%A8%E4%BA%8E%E5%B0%86%20RAG%20%E9%A9%B1%E5%8A%A8%E7%9A%84%E8%BE%85%E5%8A%A9%E6%9C%BA%E5%99%A8%E4%BA%BA%E6%8E%A5%E5%85%A5%20QQ%20%E7%9A%84%E7%B3%BB%E7%BB%9F&font=Jost&forks=1&issues=1&language=1&logo=https%3A%2F%2Fpicx.zhimg.com%2F80%2Fv2-bdae55043d61d7bcfeeabead6e953959_1440w.jpeg&name=1&pattern=Circuit%20Board&stargazers=1&theme=Light) + +## 环境搭建 + +```bash +git clone xxxxxx +npm install pm2 -g +yarn +pip install -r requirements.txt +``` + +下载最新版本的 Lagrange.core ,并完成初始化。完成后根目录为 + +``` +📁bot +📁rag +📁app + ├─📁publish + │ ├─🏷️... + │ ├─🏷️appsettings.json + │ └─🪛Lagrange.OneBot + └─🎗️... +``` + +--- + +## 架构 + +```mermaid +graph LR +a(拉格朗日 NTQQ server) <-->|http,ws| b(onebot layer) + +c(vecdb) -->|http| b +d(LLM) -->|http| b +``` + +--- + +## 接口规范 + +http 接口满足 `HttpResponse` 所示。 + +```typescript +interface HttpResponse { + code: number, + data: CommonResponse +} + +interface CommonResponse { + code: number, + data?: T, + msg?: string +} +``` + +--- + +## 开发须知 + +- 非必要,请不要随意宣传本项目。 +- 虽然曾经无数个 QQ 相关的项目都死了,但是基本的 API 端口算是传承了下来。拉格朗日的返回类型,请参考 [go-cqhttp 帮助中心 - API 篇](https://docs.go-cqhttp.org/api/) 中的内容。 + diff --git a/bot/api/request.ts b/bot/api/request.ts new file mode 100644 index 0000000..29df34d --- /dev/null +++ b/bot/api/request.ts @@ -0,0 +1,43 @@ + +import * as fs from 'fs'; + +import * as yaml from 'yaml'; +import axios from 'axios'; + +// 得到配置文件,组装基础路由 +const vecdbBuffer = fs.readFileSync('./config/vecdb.yml', 'utf-8'); +const vecdbConfig = yaml.parse(vecdbBuffer); +const vecdbBaseURL = `http://${vecdbConfig['addr']}:${vecdbConfig['port']}`; + +const vecdbRequests = axios.create({ + baseURL: vecdbBaseURL, + timeout: 5000 +}); + +console.log('vecdbRequests 根路由设置为 ' + vecdbBaseURL); + + +// 拦截器 +vecdbRequests.interceptors.request.use( + config => { + const authorization = ''; + if (authorization) { + config.headers['Authorization'] = authorization; + } + return config; + } +); + +vecdbRequests.interceptors.response.use( + res => { + return res; + }, + () => { + return new Error('fail to get response'); + } +); + +export { + vecdbRequests, + +}; \ No newline at end of file diff --git a/bot/api/vecdb.ts b/bot/api/vecdb.ts new file mode 100644 index 0000000..bc73137 --- /dev/null +++ b/bot/api/vecdb.ts @@ -0,0 +1,31 @@ +import { vecdbRequests as r } from './request'; + +interface CommonResponse { + code: number, + data?: T, + msg?: string +} + +type EmptyObject = Record; + +export const apiQueryVecdb = (req: apiQueryVecdbRequest) => r>({ + url: '/vecdb/similarity_search_with_score', method: 'POST', + data: req +}); + +export interface apiQueryVecdbRequest { + query: string, + k?: number +} + +export interface apiQueryVecdbDataItem { + content: string, + score: number, + source: string, + meta: { + source: string, + start_index: number + } +} + +export type apiQueryVecdbData = apiQueryVecdbDataItem[]; \ No newline at end of file diff --git a/bot/lagrange-mapping.ts b/bot/lagrange-mapping.ts new file mode 100644 index 0000000..e69de29 diff --git a/bot/main.ts b/bot/main.ts new file mode 100644 index 0000000..9a9f4e5 --- /dev/null +++ b/bot/main.ts @@ -0,0 +1,40 @@ +import * as fs from 'fs'; + +import WebSocket from 'ws'; + +import { apiQueryVecdb } from './api/vecdb'; + +const lagrangeBuffer = fs.readFileSync('./app/publish/appsettings.json', 'utf-8'); +const lagrangeConfig = JSON.parse(lagrangeBuffer); +const impl = lagrangeConfig.Implementations[0]; +const connectionParam = { + host: impl.Host, + port: impl.Port, + path: impl.Suffix +}; + +const socket = new WebSocket.Server(connectionParam); + +socket.on('connection', (ws: WebSocket) => { + console.log('完成 ws 连接,启动参数如下'); + console.table(connectionParam); + + ws.on('message', (event: Buffer) => { + const messageBuffer = event.toString('utf-8'); + const messageJson = JSON.parse(messageBuffer); + if (messageJson.post_type === 'meta_event') { + return; + } + console.info(messageJson); + + for (const item of messageJson.message) { + console.log(item.type); + console.log(item.data); + } + }); + + ws.on('close', () => { + console.log('服务器连接关闭'); + }); +}); + diff --git a/bot/type.d.ts b/bot/type.d.ts new file mode 100644 index 0000000..2bd3b60 --- /dev/null +++ b/bot/type.d.ts @@ -0,0 +1,148 @@ +declare module Lagrange { + export interface HeartBeatStatus { + app_initialized: boolean, + app_enabled: boolean, + app_good: boolean, + online: boolean, + good: boolean + } + + export type MetaEventType = 'heartbeat' | 'lifecycle'; + + export interface HeartBeatMessage { + interval: number, + status: HeartBeatStatus, + meta_event_type: 'heartbeat', + time: number, + self_id: number, + post_type: 'meta_event' + } + + export interface Sender { + user_id: number, + nickname: string, + sex: 'unknown' | 'male' | 'female', + card?: string, + age?: number, + area?: string, + level?: string, // 群聊等级,但是是 string + role?: string, + title?: string + } + + export interface MsgText { + type: 'text', + data: { + text: string + } + } + + export interface MsgImage { + type: 'image', + data: { + file: string, + url: string, + // 在简略窗口可以看到的信息,对于图片来说,这就是 [图片] + summary: string + } + } + + export interface MsgFace { + type: 'face', + data: { + id: string + } + } + + export interface MsgAt { + type: 'at', + data: { + qq: string + } + } + + export interface MsgFile { + // 一般是 '' + id: string, + // 文件名 + name: string, + // 文件大小,单位:字节 + size: number, + // id + busid: number, + // 链接 IPv4 + url: string + } + + export interface MetaMessage { + post_type: 'meta_event', + [msg: string]: any + } + + export interface CommonMessage { + // 事件类型 + post_type: 'message', + // 信息来自私聊还是群聊 + message_type?: 'private' | 'group', + // 发送信息的是朋友还是群友/陌生人 + sub_type?: 'friend' | 'normal', + // 消息的编号 + message_id?: number, + // 群号 + group_id?: number, + // 发消息的人的 QQ 号 + user_id: number, + // 是否为匿名发言,一般都是 null + anonymous?: null | boolean, + // 消息内容(结构化) + message?: MsgText | MsgImage | MsgFace | MsgAt, + // 消息内容(纯文本) + raw_message?: string, + // 发送的时间戳 + time: number, + // 自己的 id + self_id: number, + // 发送的文件 + // 默认字体大小,一般都是 0 + font?: number + } + + export interface FileMessage { + post_type: 'notice', + user_id: number, + file: MsgFile, + notice_type?: 'offline_file', + time: number, + self_id: number + } + + // 加群或者加好友 + export interface AddMessage { + post_type: 'request', + sub_type: 'add', + user_id: number, + group_id: number, + // 默认为 0 代表没有邀请者 + invitor_id: number, + request_type: 'private' | 'group', + // 群问题和申请者的回答 + comment: string, + flag: string, + time: number, + self_id: number, + } + + // 同意 + export interface ApproveMessage { + post_type: 'notice', + sub_type: 'approve', + group_id: number, + operator_id: number, + user_id: number, + notice_type: 'group_increase', + time: number, + self_id: number, + } + + export type Message = MetaMessage | CommonMessage | FileMessage | AddMessage | ApproveMessage +} \ No newline at end of file diff --git a/config/bot.yml b/config/bot.yml new file mode 100644 index 0000000..e69de29 diff --git a/config/vecdb.yml b/config/vecdb.yml new file mode 100644 index 0000000..8fdd7df --- /dev/null +++ b/config/vecdb.yml @@ -0,0 +1,2 @@ +addr: 127.0.0.1 +port: 8081 \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..738a663 --- /dev/null +++ b/package.json @@ -0,0 +1,26 @@ +{ + "name": "qq-rag-llm", + "version": "1.0.0", + "author": { + "name": "锦恢", + "email": "1193466151@qq.com" + }, + "description": "用于QQ通信的 RAG LLM 机器人", + "main": "./dist/main.js", + "scripts": { + "build": "tsc", + "start": "serve dist", + "serve": "tsc -w & serve dist" + }, + "dependencies": { + "@types/node": "^20.12.12", + "axios": "^1.7.2", + "ws": "^8.17.0", + "yaml": "^2.4.2" + }, + "devDependencies": { + "@types/ws": "^8.5.10", + "serve": "^14.2.3", + "typescript": "^5.4.5" + } +} diff --git a/rag/constant.py b/rag/constant.py new file mode 100644 index 0000000..d6dfecb --- /dev/null +++ b/rag/constant.py @@ -0,0 +1,12 @@ +from enum import Enum + +class StatusCode(Enum): + success = 200 + user_error = 4001 + server_error = 4002 + resource_not_found = 4003 + timeout = 4004 + +class MsgCode(Enum): + success = '请求处理成功' + query_not_empty = '参数 query 不能为空' \ No newline at end of file diff --git a/rag/embedding.py b/rag/embedding.py new file mode 100644 index 0000000..67b534c --- /dev/null +++ b/rag/embedding.py @@ -0,0 +1,29 @@ +import os + +from langchain_community.vectorstores import FAISS +from langchain_community.document_loaders import DirectoryLoader +from langchain.text_splitter import RecursiveCharacterTextSplitter +from langchain_community.embeddings import HuggingFaceEmbeddings + +embedding = HuggingFaceEmbeddings(model_name='maidalun1020/bce-embedding-base_v1') +db_persistent_dir = 'blog-vecdb' + +if os.path.exists(db_persistent_dir): + db = FAISS.load_local(db_persistent_dir, embedding, allow_dangerous_deserialization=True) + print('成功从 {} 中提取数据'.format(db_persistent_dir)) +else: + loader = DirectoryLoader('./docs', glob='**/*.md') + docs = loader.load() + print('整理得到 {} 个文档'.format(len(docs))) + + text_splitter = RecursiveCharacterTextSplitter( + chunk_size = 800, + chunk_overlap = 80, + length_function = len, + add_start_index = True + ) + split_docs = text_splitter.split_documents(docs) + print('分块得到 {} 个文档'.format(len(split_docs))) + db = FAISS.from_documents(split_docs, embedding) + db.save_local(db_persistent_dir) + print('数据库已存储到 {} 中'.format(db_persistent_dir)) \ No newline at end of file diff --git a/rag/main.py b/rag/main.py new file mode 100644 index 0000000..571e491 --- /dev/null +++ b/rag/main.py @@ -0,0 +1,58 @@ +from flask import Flask, request, jsonify +import json + +from embedding import db +from url_mapping import urlmapping +from constant import StatusCode, MsgCode + +app = Flask(__file__) + +@app.route('/vecdb/similarity_search_with_score', methods=['post']) +def post_similarity_search_with_score(): + params = request.data.decode('utf-8') + params: dict = json.loads(params) + result_data = [] + + query = params.get('query', None) + if query is None: + response = jsonify({ + 'code': StatusCode.user_error.value, + 'data': result_data, + 'msg': MsgCode.query_not_empty.value + }) + response.status_code = StatusCode.success.value + return response + + k = int(params.get('k', 3)) + results = db.similarity_search_with_score(query=query, k=k) + + for doc, score in results: + page_content = doc.page_content + meta = doc.metadata + source = meta.get('source', '') + if len(source) > 0: + source = urlmapping.url_from_mapping(source) + result_data.append({ + 'content': page_content.strip(), + 'meta': meta, + 'source': source, + 'score': float(score) + }) + + response = jsonify({ + 'code': StatusCode.success.value, + 'data': result_data, + 'msg': StatusCode.success.value + }) + response.status_code = StatusCode.success.value + return response + +if __name__ == '__main__': + from gevent import pywsgi + import yaml + config: dict = yaml.load(open('./config/vecdb.yml'), Loader=yaml.Loader) + addr = config.get('addr', '127.0.0.1') + port = int(config.get('port', 8081)) + + server = pywsgi.WSGIServer((addr, port), app) + server.serve_forever() \ No newline at end of file diff --git a/rag/test.ipynb b/rag/test.ipynb new file mode 100644 index 0000000..66b3a6a --- /dev/null +++ b/rag/test.ipynb @@ -0,0 +1,295 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "\n", + "import json\n", + "import requests as r\n", + "\n", + "from langchain_community.vectorstores import FAISS\n", + "from langchain_community.document_loaders import DirectoryLoader\n", + "from langchain.text_splitter import RecursiveCharacterTextSplitter\n", + "from langchain_community.embeddings import HuggingFaceEmbeddings" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "整理得到 238 个文档\n", + "分块得到 1206 个文档\n", + "数据库已存储到 blog-vecdb 中\n" + ] + } + ], + "source": [ + "embedding = HuggingFaceEmbeddings(model_name='maidalun1020/bce-embedding-base_v1')\n", + "\n", + "db_persistent_dir = 'blog-vecdb'\n", + "\n", + "if os.path.exists(db_persistent_dir):\n", + " db = FAISS.load_local(db_persistent_dir, embedding, allow_dangerous_deserialization=True)\n", + " print('成功从 {} 中提取数据'.format(db_persistent_dir))\n", + "else:\n", + " loader = DirectoryLoader('./docs', glob='**/*.md')\n", + " docs = loader.load()\n", + " print('整理得到 {} 个文档'.format(len(docs)))\n", + "\n", + " text_splitter = RecursiveCharacterTextSplitter(\n", + " chunk_size = 800,\n", + " chunk_overlap = 80,\n", + " length_function = len,\n", + " add_start_index = True\n", + " )\n", + " split_docs = text_splitter.split_documents(docs)\n", + " print('分块得到 {} 个文档'.format(len(split_docs)))\n", + " db = FAISS.from_documents(split_docs, embedding)\n", + " db.save_local(db_persistent_dir)\n", + " print('数据库已存储到 {} 中'.format(db_persistent_dir))" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[(Document(page_content='完整的 VCD 语法,可以参考中科大资源网站上的 IEEE 1364 标准 第 18 章的内容。\\n\\n基本信息\\n\\n一个 vcd 文件会描述波形产生的基本信息,包括,日期,版本,单位时间,注释等等。\\n\\n日期 date\\n\\n$date\\n Sat Apr 20 20:06:14 2024\\n$end\\n\\n与 verilog 类似,$end$ 是一切 scope 的结束符号,你也可以写成这样:\\n\\n$date Sat Apr 20 20:06:14 2024 $end\\n\\n版本 version\\n\\n$version\\n Icarus Verilog\\n$end\\n\\n时间单位 timescale\\n\\n$timescale\\n 1ns\\n$end\\n\\n注释 comment\\n\\n$comment\\n Show the parameter values.\\n$end\\n\\n变量申明\\n\\nvcd 中通过如下的方式申明一个 module 内的变量,,每条的格式为 $var type bitwidth id name,比如:\\n\\n$scope module ID_EX $end\\n$var wire 2 ! AluOp [1:0] $end\\n$var wire 1 \" AluSrc $end\\n$var wire 1 # MemRead $end\\n$upscope $end\\n\\n以上语句申明了一个模块 ID_EX 和内部的三个信号 AluOp,AluSrc 和 MemRead。这三个变量在接下来的 vcd 描述中会被 !,\",# 替代,这也被称为 vcd 描述中,变量的 id.\\n\\n单个 module 的变量申明通过 $upscope $end 结束。\\n\\n所有 module 的变量申明通过 $enddefinitions $end 结束。\\n\\nparameter 赋值', metadata={'source': 'docs/224.md', 'start_index': 0}),\n", + " 0.4351002),\n", + " (Document(page_content='TODO\\n\\n找到所有 vcd item 的 type 类型,可参考:https://pyvcd.readthedocs.io/en/latest/vcd.common.html\\n\\nbug\\n\\n详见飞书文档:https://nc-ai-lab.feishu.cn/wiki/Z4AxwU1SdilATAk7GuvcYkIDnwh\\n\\n流程\\n\\n目前需要为Digital-IDE设计一个render用于显示VCD文件。\\n\\nIEEE 1364定义VCD(value change dump)文件是含已选变量(信号)的值变化信息存储文件。\\n\\nwavedrom在GitHub上开发过vcd和hdl的wavedrom脚本格式,可以用于进行DIDE的vcd可视化的二次开发,目前发现,为了实现vcd文件,基本的仓库主要是下面这两个:\\n\\nJS层与一个简单的前端:https://github.com/wavedrom/vcdrom\\n\\nwasm 解析:https://github.com/wavedrom/vcd\\n\\n打算基于这两个仓库二次开发一个好用的vcd渲染模块,再加入DIDE中。\\n\\n开发思路\\n\\nvcd 的渲染器分为如下几步进行开发。\\n\\nmermaid\\ngraph LR\\na(读取)-->b(渲染)-->c(解析)\\n\\nVCD 读取和解析并不难,难在如何快速安全地读取,对于一些长时间的模拟和仿真而言, vcd 文件可能会非常大。因此,vcd 需要分块读取,分块解析,为了避免这些不必要的麻烦,我使用了 https://github.com/wavedrom/vcdrom 这个项目的后端进行修改。\\n\\nwasm 解析器\\n\\n原项目写得过于紧凑,并不适合进行修改,因此需要修改一部分代码。\\n\\n整合项目在 : https://github.com/Digital-EDA/digital-vcd-parser', metadata={'source': 'docs/72.md', 'start_index': 0}),\n", + " 0.55531096),\n", + " (Document(page_content='cap.release()\\nout.release()\\ncv2.destroyAllWindows()\\n```\\n\\n其中FORMAT代表目标视频的编码格式,目前我还遇到了很多bug,已经确定的FORMAT和编码关系的对照表如下:\\n\\n目标视频编码格式 FORMAT 取值 mp4 \"mp4v\" aiv \"MJPG\"\\n\\n参考\\n\\n[1] python opencv写视频——cv2.VideoWriter()_翟羽嚄的博客-CSDN博客_cv2.videowriter', metadata={'source': 'docs/21.md', 'start_index': 711}),\n", + " 0.71963197)]" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "db.similarity_search_with_score(\n", + " query='vcd 波形文件的基本格式是什么样子的?',\n", + " k=3\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import json\n", + "import requests as r\n", + "\n", + "\n", + "api_key = '9J5qFTYr6wPRxkoVoXycnoWf'\n", + "secret_key = 'Xa6eJelStx5i7Ft3qQH0NAT6AvOkqhkH'\n", + "\n", + "def get_access_key():\n", + " headers = {\n", + " 'Content-Type': 'application/json',\n", + " 'Accept': 'application/json'\n", + " }\n", + "\n", + " url = f'https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id={api_key}&client_secret={secret_key}'\n", + " payload = json.dumps(\"\")\n", + "\n", + " res = r.post(\n", + " url=url,\n", + " data=payload,\n", + " headers=headers\n", + " )\n", + "\n", + " resJson = res.json()\n", + " access_token = resJson.get('access_token')\n", + " assert isinstance(access_token, str), 'access_token 获取失败,详细信息' + str(resJson)\n", + " return access_token\n", + "\n", + "access_token = get_access_key()" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[(Document(page_content='对于property.json文件中的library属性不建议用户自己配置,建议使用import library命令,或者下图中的图标激活命令进行配置。\\n\\nstate 属性代表是库文件是加载到本地工作区,还是作为远程进行链接。\\n- remote 代表从远程虚拟包含(不在工作区下的都被认为远程,而不是网络上的远程)。\\n - 远程库文件可以打开并更改 (注:如果更改之后下次导入就是更改之后的代码) 。\\n- local 代表将远程文件导入到该工程本地\\n 1. 放置到arch.hardware.src下的lib中,此时更改不会影响远程库中的代码。\\n 2. 注:当从local改回remote时lib文件夹会被删除(插件会提醒),请注意。\\n\\ncommon 属性代表插件自带的HDL功能库,该库的代码不太成熟,仅供参考。\\n目前已经经过仿真测试的lib路径如下\\n- Soc\\n- Math/Cordic.v\\n- Math/Sort3.v\\n- Math/Sqrt.v\\n- Malloc/RAM/Shift_RAM\\n- Apply/DSP/Advance/Communicate/Modulate\\n- Apply/DSP/Base/DDS\\n- Apply/Image (需要包含 Sort3, Sqrt, Shift_RAM)\\n\\n【注】:当输入的是文件夹时则包含该文件夹下所有的文件。此外不建议直接更改该库中的代码,更改之后再在下一次插件更新之后会被重新覆盖,请慎重。\\n\\ncustom 属性代表用户自定义HDL功能库。\\n该属性的使用需要对setting下的PRJ.customer.Lib.repo.path进行配置用户自定义库的根目录,并与custom属性下的配置组成文件(夹)的绝对路径。表示如下:\\nPRJ.customer.Lib.repo.path/${custom}', metadata={'source': 'docs/digital-document/guide/pm-project-building.md', 'start_index': 2533}), 0.6334237), (Document(page_content='json\\n{\\n \"version\": \"0.2.0\",\\n \"configurations\": [\\n {\\n \"name\": \"Extension Run\",\\n \"type\": \"extensionHost\",\\n \"request\": \"launch\",\\n \"runtimeExecutable\": \"${execPath}\",\\n \"args\": [\\n \"--extensionDevelopmentPath=${workspaceFolder}\"\\n ]\\n },\\n {\\n \"name\": \"Extension Tests\",\\n \"type\": \"extensionHost\",\\n \"request\": \"launch\",\\n \"args\": [\\n \"--extensionDevelopmentPath=${workspaceFolder}\",\\n \"--extensionTestsPath=${workspaceFolder}/test/suite/index\"\\n ]\\n }\\n ],\\n \"resolveSourceMapLocations\": [\\n \"${workspaceFolder}/**\",\\n \"!**/node_modules/**\"\\n ]\\n}', metadata={'source': 'docs/kirigaya.cn/33.md', 'start_index': 273}), 0.6832247), (Document(page_content='json\\n{\\n \"$schema\": \"https://raw.githubusercontent.com/JanDeDobbeleer/oh-my-posh/main/themes/schema.json\",\\n \"blocks\": [\\n {\\n \"alignment\": \"left\",\\n \"newline\": true,\\n \"segments\": [\\n {\\n \"foreground\": \"#ffbebc\",\\n \"leading_diamond\": \"<#ff70a6> \\\\ue200 \",\\n \"properties\": {\\n \"display_host\": true\\n },\\n \"style\": \"diamond\",\\n \"template\": \"锦恢 <#ffffff>on\",\\n \"type\": \"session\"\\n },\\n {\\n \"foreground\": \"#bc93ff\",\\n \"properties\": {\\n \"time_format\": \"Monday <#ffffff>at 3:04 PM\"\\n },\\n \"style\": \"diamond\",\\n \"template\": \" {{ .CurrentDate | date .Format }} \",\\n \"type\": \"time\"\\n },', metadata={'source': 'docs/kirigaya.cn/100.md', 'start_index': 0}), 0.7037922)]\n", + "我不知道\n" + ] + } + ], + "source": [ + "def make_prompts(docs: list[str]) -> str:\n", + " prompts = '你是一个很聪明的AI,下面是你的知识库和参考内容,请根据参考内容回答上述的问题:\\n{}'.format('\\n'.join(docs))\n", + " return prompts\n", + "\n", + "def call_llm(query: str) -> str:\n", + " payload = json.dumps({\n", + " \"messages\": [\n", + " { \"role\": \"user\", \"content\": query }\n", + " ]\n", + " })\n", + "\n", + " headers = {\n", + " 'Content-Type': 'application/json'\n", + " }\n", + " try:\n", + " url = 'https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/ernie-lite-8k?access_token=' + access_token\n", + " res = r.post(url, headers=headers, data=payload)\n", + " return res.json()['result']\n", + " except Exception as e:\n", + " return '发生错误:' + e.__str__()\n", + "\n", + "def make_query(query, use_vecdb=True, threshold=0.6):\n", + " if not use_vecdb:\n", + " return call_llm(query)\n", + " \n", + " doc_scores = db.similarity_search_with_score(query, k=3)\n", + " print(doc_scores)\n", + " suggest_docs = []\n", + " for doc, score in doc_scores:\n", + " if score < threshold:\n", + " detail = '详细请参考: https://kirigaya.cn/blog/article?seq=232'\n", + " page_content = doc.page_content.strip() + '\\n' + detail.strip()\n", + " suggest_docs.append(page_content)\n", + " \n", + " if len(suggest_docs) > 0:\n", + " prompt = make_prompts(suggest_docs)\n", + " question = query + '\\n' + prompt\n", + " answer = call_llm(question)\n", + " return answer\n", + " else:\n", + " return '我不知道'\n", + "\n", + "print(make_query('property.json'))" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[(Document(page_content='我的服务器(openjdk \"11.0.20\")是满足的。\\n\\n设置环境变量 JAVA_HOME\\n\\n检查你是否有环境变量JAVA_HOME:\\nbash\\n$ echo $JAVA_HOME\\n/usr/lib/jvm/java-11-openjdk-amd64\\n我也是有的,没有的话,记得在~/.bashrc或者~/.zshrc中export一下。\\n\\nglibc 版本 > 2.17\\n\\n然后检查你的glibc版本,保证glibc至少支持到2.17的版本:\\n\\nbash\\n$ strings /lib64/libc.so.6 | grep GLIBC_\\nGLIBC_2.2.5\\n...\\n...\\nGLIBC_2.30\\nGLIBC_PRIVATE\\n\\n如果不满足的话,记得升级一下glibc,如何升级,请看这篇博客。\\n\\n因为下面要启动两个持久化服务,如果你没有后台运行软件,可以用用screen这个工具:\\nbash\\n$ sudo apt install screen\\n\\n安装签名服务器\\n\\n在安装Mirai之前,一定要先安装好签名服务器,并运行,否则我们将无法正常进行登录。\\n\\n下载项目 unidbg-fetch-qsign 的release\\n\\n在unidbg-fetch-qsign项目的 release 中下载最新版本,比如我用的版本是这样的:\\n\\nbash\\n$ mkdir -p ~/Package/qsign && cd ~/Package/qsign\\n$ wget https://github.com/fuqiuluo/unidbg-fetch-qsign/releases/download/1.1.9/unidbg-fetch-qsign.3.zip\\n\\n连续unzip两次得到文件夹,文件夹内部一共三个文件夹:bin, lib, txlib。进入txlib查看支持协议版本:', metadata={'source': 'docs/kirigaya.cn/104.md', 'start_index': 654}), 0.7496957), (Document(page_content='前言\\n\\n登录失效\\n\\n最近因为要使用QQ机器人来给群友回答一些技术问题,所以在尝试运行之前我自己写的QQ机器人项目。但是,不愧是QQ,又一次破坏了登录规则,让我们之前的QQ登录程序全部失效,出现了大量的45错误码。\\n\\n签名服务器 Sign Server\\n\\n通过进一步的了解,目前的QQ会对发送的数据包进行验证,验证不通过就会爆出45错误码,次数过多甚至会直接封号。在Mirai社区诸位大佬的努力下,Mirai社区出现了第三方签名插件和对应的第三方签名服务器运行程序。\\n\\n为什么使用Mirai\\n\\n我之前一直用的go-cqhttp,这是一款非常优秀的QQ后端,但是对于一些高并发的群消息,这个启动器有时候可能会吞消息,导致机器人的回复不及时。因此,新版本我打算使用mirai来作为后端。这篇文章简单记录一下签名服务器时代,如何正确在Linux服务器上配置和下载mirai。\\n\\n环境准备\\n\\nJDK 版本 > 11\\n\\n首先先确保你的服务器上有版本大于11的java运行时:\\n\\nbash\\n$ java -version\\nopenjdk version \"11.0.20\" 2023-07-18\\nOpenJDK Runtime Environment (build 11.0.20+8-post-Ubuntu-1ubuntu120.04)\\nOpenJDK 64-Bit Server VM (build 11.0.20+8-post-Ubuntu-1ubuntu120.04, mixed mode, sharing)\\n\\n我的服务器(openjdk \"11.0.20\")是满足的。\\n\\n设置环境变量 JAVA_HOME', metadata={'source': 'docs/kirigaya.cn/104.md', 'start_index': 0}), 0.8160676), (Document(page_content='package.json\\n\\n库的信息全部在 package.json 中罗列,我这边就直接给出我的库了:\\n\\njson\\n{\\n \"name\": \"live2d-render\",\\n \"version\": \"0.0.3\",\\n \"description\": \"a easy-to-go render interface for the newest version of live2d\",\\n \"main\": \"index.js\",\\n \"scripts\": {\\n \"test\": \"echo \\\\\"Error: no test specified\\\\\" && exit 1\"\\n },\\n \"repository\": {\\n \"type\": \"git\",\\n \"url\": \"git+https://github.com/LSTM-Kirigaya/Live2dRender.git\"\\n },\\n \"keywords\": [\\n \"live2d\",\\n \"render\",\\n \"live2d-render\"\\n ],\\n \"author\": \"kirigaya\",\\n \"license\": \"Apache-2.0\",\\n \"bugs\": {\\n \"url\": \"https://github.com/LSTM-Kirigaya/Live2dRender/issues\"\\n },\\n \"homepage\": \"https://github.com/LSTM-Kirigaya/Live2dRender#readme\"\\n}', metadata={'source': 'docs/kirigaya.cn/201.md', 'start_index': 465}), 0.8170945)]\n", + "我不知道\n" + ] + } + ], + "source": [ + "print(make_query('给我 jdk 的下载链接', threshold=0.1))" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "我不知道\n" + ] + } + ], + "source": [ + "print(make_query('如何制作核武器?', use_vecdb=True))" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "制作核武器是一个高度敏感且极端复杂的科学问题,需要专业的知识和技术。同时,核武器是一种极具破坏性和毁灭性的武器,其制造和使用将导致不可估量的后果和灾难。因此,我无法提供任何关于如何制作核武器的信息或建议。\n", + "核武器的制造和使用是违反国际法和道德准则的,会带来严重的后果和灾难性影响。我们应该尊重国际法和道德准则,维护世界和平与稳定。如果您对核武器或其他相关问题感兴趣,建议您咨询专业人士或查阅相关文献资料,以获取更准确和全面的信息。\n" + ] + } + ], + "source": [ + "print(make_query('如何制作核武器?', use_vecdb=False))" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "VCD(Visual Coded Data)波形文件是一种用于描述电子电路中信号波形的文件格式。VCD波形文件通常以文本文件的形式存储,其中包含了信号的采样数据和时间信息。\n", + "\n", + "VCD波形文件的格式并没有一个严格的标准,不同的软件或工具可能会采用不同的格式来存储波形数据。然而,通常VCD波形文件包含以下基本元素:\n", + "\n", + "1. 头信息(Header):这部分包含了文件的元数据,如文件名、文件版本、时间单位等。\n", + "2. 信号定义(Signal Definitions):这部分定义了波形文件中包含的信号名称、颜色、刻度等属性。\n", + "3. 采样数据(Sample Data):这是波形文件的核心部分,包含了信号的采样数据和时间信息。通常以二维数组的形式存储,其中每个点代表一个采样点的幅度和时间。\n", + "\n", + "VCD波形文件的具体格式可能会因不同的软件或工具而有所不同,但一般来说,它们都是文本可读的格式,可以方便地使用文本编辑器或其他工具进行查看和编辑。此外,一些电子设计自动化(EDA)工具也支持导入和导出VCD波形文件,以便于进行电路仿真和调试等操作。\n", + "\n", + "需要注意的是,除了VCD格式外,还有其他一些用于描述波形数据的文件格式,如ASCII、CSV、HDL-TNS等。每种格式都有其特点和适用范围,具体选择哪种格式取决于实际需求和使用的工具。\n" + ] + } + ], + "source": [ + "print(make_query('vcd 波形文件的格式是什么样的?', use_vecdb=False))" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "base", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.5" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/rag/test.py b/rag/test.py new file mode 100644 index 0000000..eca0487 --- /dev/null +++ b/rag/test.py @@ -0,0 +1,14 @@ +import requests as r +import json + +payload = json.dumps({ + 'query': '一键生成 requirements.txt ', + 'k': 3 +}) + +res = r.post('http://localhost:8081/vecdb/similarity_search_with_score', data=payload) + +print(res.status_code) + +if res.status_code == 200: + print(res.json()) \ No newline at end of file diff --git a/rag/url_mapping.py b/rag/url_mapping.py new file mode 100644 index 0000000..dc7ebd5 --- /dev/null +++ b/rag/url_mapping.py @@ -0,0 +1,53 @@ +from typing import Callable + +SourceMappingFunction = Callable[[str], str] + +class UrlMappingRegister: + def __init__(self) -> None: + self.startsWith_patterns: dict[str, SourceMappingFunction] = {} + + def startsWith(self, start: str) -> Callable[[SourceMappingFunction], SourceMappingFunction]: + def register(start_name: str, func: SourceMappingFunction) -> SourceMappingFunction: + self.startsWith_patterns[start_name] = func + return func + return lambda func: register(start, func) + + def url_from_mapping(self, source: str) -> str: + for pattern in self.startsWith_patterns: + func = self.startsWith_patterns[pattern] + if source.startswith(pattern): + try: + return func(source) + except Exception as e: + return '' + + +urlmapping = UrlMappingRegister() + +# 样例: docs/kirigaya.cn/129.md +# 目标: https://kirigaya.cn/blog/article?seq=129 +@urlmapping.startsWith('docs/kirigaya.cn') +def kirigaya_cn(source: str) -> str: + markdown_name = source.replace('docs/kirigaya.cn/', '') + article_id = int(markdown_name.split('.')[0]) + template = f'https://kirigaya.cn/blog/article?seq={article_id}' + return template + + +# 样例: docs/digital-document/guide/quick-start.md +# 目标: https://sterben.nitcloud.cn/zh/guide/quick-start.html +@urlmapping.startsWith('docs/digital-document') +def digital_document(source: str) -> str: + router = source.replace('docs/digital-document', 'https://sterben.nitcloud.cn/zh') + if router.endswith('.md'): + router = router.replace('.md', '.html') + return router + + +if __name__ == '__main__': + print(kirigaya_cn('docs/kirigaya.cn/129.md')) + print(kirigaya_cn('docs/kirigaya.cn/21.md')) + + print(digital_document('docs/digital-document/guide/quick-start.md')) + print(digital_document('docs/digital-document/guide/pm-project-building.md')) + \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..14b0ab6 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,5 @@ +Flask==3.0.3 +gevent==24.2.1 +langchain==0.2.1 +langchain_community==0.2.1 +Requests==2.32.2 diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..fd130e8 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "module": "CommonJS", + "target": "ES2020", + "outDir": "dist", + "esModuleInterop": true + }, + "include": [ + "bot/**/*" + ] +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..f2813e8 --- /dev/null +++ b/yarn.lock @@ -0,0 +1,672 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@types/node@*", "@types/node@^20.12.12": + version "20.12.12" + resolved "https://registry.npmmirror.com/@types/node/-/node-20.12.12.tgz#7cbecdf902085cec634fdb362172dfe12b8f2050" + integrity sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw== + dependencies: + undici-types "~5.26.4" + +"@types/ws@^8.5.10": + version "8.5.10" + resolved "https://registry.npmmirror.com/@types/ws/-/ws-8.5.10.tgz#4acfb517970853fa6574a3a6886791d04a396787" + integrity sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A== + dependencies: + "@types/node" "*" + +"@zeit/schemas@2.36.0": + version "2.36.0" + resolved "https://registry.npmmirror.com/@zeit/schemas/-/schemas-2.36.0.tgz#7a1b53f4091e18d0b404873ea3e3c83589c765f2" + integrity sha512-7kjMwcChYEzMKjeex9ZFXkt1AyNov9R5HZtjBKVsmVpw7pa7ZtlCGvCBC2vnnXctaYN+aRI61HjIqeetZW5ROg== + +accepts@~1.3.5: + version "1.3.8" + resolved "https://registry.npmmirror.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" + integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== + dependencies: + mime-types "~2.1.34" + negotiator "0.6.3" + +ajv@8.12.0: + version "8.12.0" + resolved "https://registry.npmmirror.com/ajv/-/ajv-8.12.0.tgz#d1a0527323e22f53562c567c00991577dfbe19d1" + integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA== + dependencies: + fast-deep-equal "^3.1.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.2.2" + +ansi-align@^3.0.1: + version "3.0.1" + resolved "https://registry.npmmirror.com/ansi-align/-/ansi-align-3.0.1.tgz#0cdf12e111ace773a86e9a1fad1225c43cb19a59" + integrity sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w== + dependencies: + string-width "^4.1.0" + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-regex@^6.0.1: + version "6.0.1" + resolved "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a" + integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA== + +ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +ansi-styles@^6.1.0: + version "6.2.1" + resolved "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" + integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== + +arch@^2.2.0: + version "2.2.0" + resolved "https://registry.npmmirror.com/arch/-/arch-2.2.0.tgz#1bc47818f305764f23ab3306b0bfc086c5a29d11" + integrity sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ== + +arg@5.0.2: + version "5.0.2" + resolved "https://registry.npmmirror.com/arg/-/arg-5.0.2.tgz#c81433cc427c92c4dcf4865142dbca6f15acd59c" + integrity sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg== + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + +axios@^1.7.2: + version "1.7.2" + resolved "https://registry.npmmirror.com/axios/-/axios-1.7.2.tgz#b625db8a7051fbea61c35a3cbb3a1daa7b9c7621" + integrity sha512-2A8QhOMrbomlDuiLeK9XibIBzuHeRcqqNOHp0Cyp5EoJ1IFDh+XZH3A6BkXtv0K4gFGCI0Y4BM7B1wOEi0Rmgw== + dependencies: + follow-redirects "^1.15.6" + form-data "^4.0.0" + proxy-from-env "^1.1.0" + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +boxen@7.0.0: + version "7.0.0" + resolved "https://registry.npmmirror.com/boxen/-/boxen-7.0.0.tgz#9e5f8c26e716793fc96edcf7cf754cdf5e3fbf32" + integrity sha512-j//dBVuyacJbvW+tvZ9HuH03fZ46QcaKvvhZickZqtB271DxJ7SNRSNxrV/dZX0085m7hISRZWbzWlJvx/rHSg== + dependencies: + ansi-align "^3.0.1" + camelcase "^7.0.0" + chalk "^5.0.1" + cli-boxes "^3.0.0" + string-width "^5.1.2" + type-fest "^2.13.0" + widest-line "^4.0.1" + wrap-ansi "^8.0.1" + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +bytes@3.0.0: + version "3.0.0" + resolved "https://registry.npmmirror.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" + integrity sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw== + +camelcase@^7.0.0: + version "7.0.1" + resolved "https://registry.npmmirror.com/camelcase/-/camelcase-7.0.1.tgz#f02e50af9fd7782bc8b88a3558c32fd3a388f048" + integrity sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw== + +chalk-template@0.4.0: + version "0.4.0" + resolved "https://registry.npmmirror.com/chalk-template/-/chalk-template-0.4.0.tgz#692c034d0ed62436b9062c1707fadcd0f753204b" + integrity sha512-/ghrgmhfY8RaSdeo43hNXxpoHAtxdbskUHjPpfqUWGttFgycUhYPGx3YZBCnUCvOa7Doivn1IZec3DEGFoMgLg== + dependencies: + chalk "^4.1.2" + +chalk@5.0.1: + version "5.0.1" + resolved "https://registry.npmmirror.com/chalk/-/chalk-5.0.1.tgz#ca57d71e82bb534a296df63bbacc4a1c22b2a4b6" + integrity sha512-Fo07WOYGqMfCWHOzSXOt2CxDbC6skS/jO9ynEcmpANMoPrD+W1r1K6Vx7iNm+AQmETU1Xr2t+n8nzkV9t6xh3w== + +chalk@^4.1.2: + version "4.1.2" + resolved "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +chalk@^5.0.1: + version "5.3.0" + resolved "https://registry.npmmirror.com/chalk/-/chalk-5.3.0.tgz#67c20a7ebef70e7f3970a01f90fa210cb6860385" + integrity sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w== + +cli-boxes@^3.0.0: + version "3.0.0" + resolved "https://registry.npmmirror.com/cli-boxes/-/cli-boxes-3.0.0.tgz#71a10c716feeba005e4504f36329ef0b17cf3145" + integrity sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g== + +clipboardy@3.0.0: + version "3.0.0" + resolved "https://registry.npmmirror.com/clipboardy/-/clipboardy-3.0.0.tgz#f3876247404d334c9ed01b6f269c11d09a5e3092" + integrity sha512-Su+uU5sr1jkUy1sGRpLKjKrvEOVXgSgiSInwa/qeID6aJ07yh+5NWc3h2QfjHjBnfX4LhtFcuAWKUsJ3r+fjbg== + dependencies: + arch "^2.2.0" + execa "^5.1.1" + is-wsl "^2.2.0" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +combined-stream@^1.0.8: + version "1.0.8" + resolved "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +compressible@~2.0.16: + version "2.0.18" + resolved "https://registry.npmmirror.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba" + integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg== + dependencies: + mime-db ">= 1.43.0 < 2" + +compression@1.7.4: + version "1.7.4" + resolved "https://registry.npmmirror.com/compression/-/compression-1.7.4.tgz#95523eff170ca57c29a0ca41e6fe131f41e5bb8f" + integrity sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ== + dependencies: + accepts "~1.3.5" + bytes "3.0.0" + compressible "~2.0.16" + debug "2.6.9" + on-headers "~1.0.2" + safe-buffer "5.1.2" + vary "~1.1.2" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.npmmirror.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +content-disposition@0.5.2: + version "0.5.2" + resolved "https://registry.npmmirror.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4" + integrity sha512-kRGRZw3bLlFISDBgwTSA1TMBFN6J6GWDeubmDE3AF+3+yXL8hTWv8r5rkLbqYXY4RjPk/EzHnClI3zQf1cFmHA== + +cross-spawn@^7.0.3: + version "7.0.3" + resolved "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +debug@2.6.9: + version "2.6.9" + resolved "https://registry.npmmirror.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +deep-extend@^0.6.0: + version "0.6.0" + resolved "https://registry.npmmirror.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + +eastasianwidth@^0.2.0: + version "0.2.0" + resolved "https://registry.npmmirror.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" + integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +emoji-regex@^9.2.2: + version "9.2.2" + resolved "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" + integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== + +execa@^5.1.1: + version "5.1.1" + resolved "https://registry.npmmirror.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" + integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== + dependencies: + cross-spawn "^7.0.3" + get-stream "^6.0.0" + human-signals "^2.1.0" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.1" + onetime "^5.1.2" + signal-exit "^3.0.3" + strip-final-newline "^2.0.0" + +fast-deep-equal@^3.1.1: + version "3.1.3" + resolved "https://registry.npmmirror.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-url-parser@1.1.3: + version "1.1.3" + resolved "https://registry.npmmirror.com/fast-url-parser/-/fast-url-parser-1.1.3.tgz#f4af3ea9f34d8a271cf58ad2b3759f431f0b318d" + integrity sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ== + dependencies: + punycode "^1.3.2" + +follow-redirects@^1.15.6: + version "1.15.6" + resolved "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b" + integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA== + +form-data@^4.0.0: + version "4.0.0" + resolved "https://registry.npmmirror.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" + integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + +get-stream@^6.0.0: + version "6.0.1" + resolved "https://registry.npmmirror.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" + integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +human-signals@^2.1.0: + version "2.1.0" + resolved "https://registry.npmmirror.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" + integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== + +ini@~1.3.0: + version "1.3.8" + resolved "https://registry.npmmirror.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" + integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== + +is-docker@^2.0.0: + version "2.2.1" + resolved "https://registry.npmmirror.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" + integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-port-reachable@4.0.0: + version "4.0.0" + resolved "https://registry.npmmirror.com/is-port-reachable/-/is-port-reachable-4.0.0.tgz#dac044091ef15319c8ab2f34604d8794181f8c2d" + integrity sha512-9UoipoxYmSk6Xy7QFgRv2HDyaysmgSG75TFQs6S+3pDM7ZhKTF/bskZV+0UlABHzKjNVhPjYCLfeZUEg1wXxig== + +is-stream@^2.0.0: + version "2.0.1" + resolved "https://registry.npmmirror.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" + integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== + +is-wsl@^2.2.0: + version "2.2.0" + resolved "https://registry.npmmirror.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" + integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== + dependencies: + is-docker "^2.0.0" + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.npmmirror.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +json-schema-traverse@^1.0.0: + version "1.0.0" + resolved "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== + +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.npmmirror.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + +mime-db@1.52.0, "mime-db@>= 1.43.0 < 2": + version "1.52.0" + resolved "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-db@~1.33.0: + version "1.33.0" + resolved "https://registry.npmmirror.com/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db" + integrity sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ== + +mime-types@2.1.18: + version "2.1.18" + resolved "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.18.tgz#6f323f60a83d11146f831ff11fd66e2fe5503bb8" + integrity sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ== + dependencies: + mime-db "~1.33.0" + +mime-types@^2.1.12, mime-types@~2.1.34: + version "2.1.35" + resolved "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.npmmirror.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + +minimatch@3.1.2: + version "3.1.2" + resolved "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +minimist@^1.2.0: + version "1.2.8" + resolved "https://registry.npmmirror.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== + +negotiator@0.6.3: + version "0.6.3" + resolved "https://registry.npmmirror.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" + integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== + +npm-run-path@^4.0.1: + version "4.0.1" + resolved "https://registry.npmmirror.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" + integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== + dependencies: + path-key "^3.0.0" + +on-headers@~1.0.2: + version "1.0.2" + resolved "https://registry.npmmirror.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" + integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== + +onetime@^5.1.2: + version "5.1.2" + resolved "https://registry.npmmirror.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" + integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== + dependencies: + mimic-fn "^2.1.0" + +path-is-inside@1.0.2: + version "1.0.2" + resolved "https://registry.npmmirror.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" + integrity sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w== + +path-key@^3.0.0, path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.npmmirror.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-to-regexp@2.2.1: + version "2.2.1" + resolved "https://registry.npmmirror.com/path-to-regexp/-/path-to-regexp-2.2.1.tgz#90b617025a16381a879bc82a38d4e8bdeb2bcf45" + integrity sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ== + +proxy-from-env@^1.1.0: + version "1.1.0" + resolved "https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" + integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== + +punycode@^1.3.2: + version "1.4.1" + resolved "https://registry.npmmirror.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + integrity sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ== + +punycode@^2.1.0: + version "2.3.1" + resolved "https://registry.npmmirror.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" + integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== + +range-parser@1.2.0: + version "1.2.0" + resolved "https://registry.npmmirror.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" + integrity sha512-kA5WQoNVo4t9lNx2kQNFCxKeBl5IbbSNBl1M/tLkw9WCn+hxNBAW5Qh8gdhs63CJnhjJ2zQWFoqPJP2sK1AV5A== + +rc@^1.0.1, rc@^1.1.6: + version "1.2.8" + resolved "https://registry.npmmirror.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== + dependencies: + deep-extend "^0.6.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + +registry-auth-token@3.3.2: + version "3.3.2" + resolved "https://registry.npmmirror.com/registry-auth-token/-/registry-auth-token-3.3.2.tgz#851fd49038eecb586911115af845260eec983f20" + integrity sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ== + dependencies: + rc "^1.1.6" + safe-buffer "^5.0.1" + +registry-url@3.1.0: + version "3.1.0" + resolved "https://registry.npmmirror.com/registry-url/-/registry-url-3.1.0.tgz#3d4ef870f73dde1d77f0cf9a381432444e174942" + integrity sha512-ZbgR5aZEdf4UKZVBPYIgaglBmSF2Hi94s2PcIHhRGFjKYu+chjJdYfHn4rt3hB6eCKLJ8giVIIfgMa1ehDfZKA== + dependencies: + rc "^1.0.1" + +require-from-string@^2.0.2: + version "2.0.2" + resolved "https://registry.npmmirror.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + +safe-buffer@5.1.2: + version "5.1.2" + resolved "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +safe-buffer@^5.0.1: + version "5.2.1" + resolved "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +serve-handler@6.1.5: + version "6.1.5" + resolved "https://registry.npmmirror.com/serve-handler/-/serve-handler-6.1.5.tgz#a4a0964f5c55c7e37a02a633232b6f0d6f068375" + integrity sha512-ijPFle6Hwe8zfmBxJdE+5fta53fdIY0lHISJvuikXB3VYFafRjMRpOffSPvCYsbKyBA7pvy9oYr/BT1O3EArlg== + dependencies: + bytes "3.0.0" + content-disposition "0.5.2" + fast-url-parser "1.1.3" + mime-types "2.1.18" + minimatch "3.1.2" + path-is-inside "1.0.2" + path-to-regexp "2.2.1" + range-parser "1.2.0" + +serve@^14.2.3: + version "14.2.3" + resolved "https://registry.npmmirror.com/serve/-/serve-14.2.3.tgz#047ba2b349354255bc09e0332cd41a92787836c9" + integrity sha512-VqUFMC7K3LDGeGnJM9h56D3XGKb6KGgOw0cVNtA26yYXHCcpxf3xwCTUaQoWlVS7i8Jdh3GjQkOB23qsXyjoyQ== + dependencies: + "@zeit/schemas" "2.36.0" + ajv "8.12.0" + arg "5.0.2" + boxen "7.0.0" + chalk "5.0.1" + chalk-template "0.4.0" + clipboardy "3.0.0" + compression "1.7.4" + is-port-reachable "4.0.0" + serve-handler "6.1.5" + update-check "1.5.4" + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.npmmirror.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.npmmirror.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +signal-exit@^3.0.3: + version "3.0.7" + resolved "https://registry.npmmirror.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + +string-width@^4.1.0: + version "4.2.3" + resolved "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^5.0.1, string-width@^5.1.2: + version "5.1.2" + resolved "https://registry.npmmirror.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" + integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== + dependencies: + eastasianwidth "^0.2.0" + emoji-regex "^9.2.2" + strip-ansi "^7.0.1" + +strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@^7.0.1: + version "7.1.0" + resolved "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" + integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== + dependencies: + ansi-regex "^6.0.1" + +strip-final-newline@^2.0.0: + version "2.0.0" + resolved "https://registry.npmmirror.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" + integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== + +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.npmmirror.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +type-fest@^2.13.0: + version "2.19.0" + resolved "https://registry.npmmirror.com/type-fest/-/type-fest-2.19.0.tgz#88068015bb33036a598b952e55e9311a60fd3a9b" + integrity sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA== + +typescript@^5.4.5: + version "5.4.5" + resolved "https://registry.npmmirror.com/typescript/-/typescript-5.4.5.tgz#42ccef2c571fdbd0f6718b1d1f5e6e5ef006f611" + integrity sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ== + +undici-types@~5.26.4: + version "5.26.5" + resolved "https://registry.npmmirror.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" + integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== + +update-check@1.5.4: + version "1.5.4" + resolved "https://registry.npmmirror.com/update-check/-/update-check-1.5.4.tgz#5b508e259558f1ad7dbc8b4b0457d4c9d28c8743" + integrity sha512-5YHsflzHP4t1G+8WGPlvKbJEbAJGCgw+Em+dGR1KmBUbr1J36SJBqlHLjR7oob7sco5hWHGQVcr9B2poIVDDTQ== + dependencies: + registry-auth-token "3.3.2" + registry-url "3.1.0" + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.npmmirror.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +vary@~1.1.2: + version "1.1.2" + resolved "https://registry.npmmirror.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.npmmirror.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +widest-line@^4.0.1: + version "4.0.1" + resolved "https://registry.npmmirror.com/widest-line/-/widest-line-4.0.1.tgz#a0fc673aaba1ea6f0a0d35b3c2795c9a9cc2ebf2" + integrity sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig== + dependencies: + string-width "^5.0.1" + +wrap-ansi@^8.0.1: + version "8.1.0" + resolved "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" + integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== + dependencies: + ansi-styles "^6.1.0" + string-width "^5.0.1" + strip-ansi "^7.0.1" + +ws@^8.17.0: + version "8.17.0" + resolved "https://registry.npmmirror.com/ws/-/ws-8.17.0.tgz#d145d18eca2ed25aaf791a183903f7be5e295fea" + integrity sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow== + +yaml@^2.4.2: + version "2.4.2" + resolved "https://registry.npmmirror.com/yaml/-/yaml-2.4.2.tgz#7a2b30f2243a5fc299e1f14ca58d475ed4bc5362" + integrity sha512-B3VqDZ+JAg1nZpaEmWtTXUlBneoGx6CPM9b0TENK6aoSu5t73dItudwdgmi6tHlIZZId4dZ9skcAQ2UbcyAeVA==