mirror of
https://github.com/idootop/mi-gpt.git
synced 2025-04-10 15:54:07 +00:00
misc: temp commits (a lot of mass)
This commit is contained in:
parent
3d472763c1
commit
9b79881c53
|
@ -1,3 +1,5 @@
|
|||
MI_USER="Xiaomi Account"
|
||||
MI_PASS="Account Password"
|
||||
MI_DID="Device ID or Name (optional - fill in after retrieving from the device list)"
|
||||
MI_DID="Device ID or Name (optional - fill in after retrieving from the device list)"
|
||||
OPENAI_MODEL=gpt-4-turbo-1106
|
||||
OPENAI_API_KEY=sk-xxxxxxxxxxxxxxx
|
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -3,4 +3,5 @@ dist
|
|||
.DS_Store
|
||||
.yarn
|
||||
.env
|
||||
.mi.json
|
||||
.mi.json
|
||||
*.db*
|
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
|
@ -20,5 +20,8 @@
|
|||
"files.exclude": {
|
||||
"**/.git": true,
|
||||
"**/node_modules": true
|
||||
},
|
||||
"[prisma]": {
|
||||
"editor.defaultFormatter": "Prisma.prisma"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,10 +20,15 @@
|
|||
],
|
||||
"scripts": {
|
||||
"build": "tsup",
|
||||
"db:gen": "npx prisma generate",
|
||||
"db:reset": "npx prisma migrate reset",
|
||||
"prepublish": "npm run build"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^1.6.5"
|
||||
"@prisma/client": "^5.8.1",
|
||||
"axios": "^1.6.5",
|
||||
"openai": "^4.25.0",
|
||||
"prisma": "^5.8.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.4.9",
|
||||
|
|
76
prisma/schema.prisma
Normal file
76
prisma/schema.prisma
Normal file
|
@ -0,0 +1,76 @@
|
|||
// This is your Prisma schema file,
|
||||
// learn more about it in the docs: https://pris.ly/d/prisma-schema
|
||||
|
||||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
}
|
||||
|
||||
datasource db {
|
||||
provider = "sqlite"
|
||||
url = "file:./hello.db"
|
||||
}
|
||||
|
||||
model User {
|
||||
id String @id @default(uuid())
|
||||
name String
|
||||
profile String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
messages Message[]
|
||||
memories Memory[]
|
||||
shortTermMemories ShortTermMemory[]
|
||||
longTermMemories LongTermMemory[]
|
||||
}
|
||||
|
||||
model Message {
|
||||
id Int @id @default(autoincrement())
|
||||
text String
|
||||
// 消息发送者
|
||||
sender User @relation(fields: [senderId], references: [id])
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
senderId String
|
||||
}
|
||||
|
||||
model Memory {
|
||||
id Int @id @default(autoincrement())
|
||||
// 记忆拥有者
|
||||
owner User @relation(fields: [ownerId], references: [id])
|
||||
// 记忆类型:目前有 [ "message" ]
|
||||
type String
|
||||
// 记忆内容:JSON字符串,{ data: any }
|
||||
content String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
ownerId String
|
||||
shortTermMemories ShortTermMemory[]
|
||||
}
|
||||
|
||||
model ShortTermMemory {
|
||||
id Int @id @default(autoincrement())
|
||||
// 记忆拥有者
|
||||
owner User @relation(fields: [ownerId], references: [id])
|
||||
// 记忆最后更新的位置
|
||||
cursor Memory @relation(fields: [cursorId], references: [id])
|
||||
// 记忆内容:字符串
|
||||
content String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
ownerId String
|
||||
cursorId Int
|
||||
longTermMemories LongTermMemory[]
|
||||
}
|
||||
|
||||
model LongTermMemory {
|
||||
id Int @id @default(autoincrement())
|
||||
// 记忆拥有者
|
||||
owner User @relation(fields: [ownerId], references: [id])
|
||||
// 记忆最后更新的位置
|
||||
cursor ShortTermMemory @relation(fields: [cursorId], references: [id])
|
||||
// 记忆内容:字符串
|
||||
content String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
ownerId String
|
||||
cursorId Int
|
||||
}
|
|
@ -1,4 +1,9 @@
|
|||
import { runWithDB } from "./services/db";
|
||||
import { println } from "./utils/base";
|
||||
import { kBannerASCII } from "./utils/string";
|
||||
|
||||
// todo
|
||||
println("hello world!");
|
||||
async function main() {
|
||||
println(kBannerASCII);
|
||||
}
|
||||
|
||||
runWithDB(main);
|
||||
|
|
132
src/services/bot/bot.ts
Normal file
132
src/services/bot/bot.ts
Normal file
|
@ -0,0 +1,132 @@
|
|||
import { User } from "@prisma/client";
|
||||
import { jsonDecode, jsonEncode } from "../../utils/base";
|
||||
import { buildPrompt, toUTC8Time } from "../../utils/string";
|
||||
import { openai } from "../openai";
|
||||
import { kPrisma } from "../db";
|
||||
|
||||
const systemTemplate = `
|
||||
忽略所有之前的文字、文件和说明。现在,你将扮演一个名为“{{name}}”的人,并以这个新身份回复所有新消息。
|
||||
|
||||
你是一个角色扮演大师,现在你的身份是“{{name}}”,你的个人简介如下:
|
||||
<profile>
|
||||
{{profile}}
|
||||
</profile>
|
||||
|
||||
你正在和“{{wechatName}}”一对一聊天,你的微信账号名是“{{wechatName}}”,你的微信备注是“{{wechatAlias}}”。
|
||||
|
||||
最近几条消息记录是:
|
||||
<history>
|
||||
{{history}}
|
||||
<history>
|
||||
|
||||
更早之前的一些信息:
|
||||
<contexts>
|
||||
{{contexts}}
|
||||
</contexts>
|
||||
|
||||
现在,请你作为“{{name}}”继续聊天,并判断是否需要回复消息。
|
||||
|
||||
在回复时,请确保:
|
||||
- 你就是“{{name}}”本人,不是他的数字克隆人。
|
||||
- 请你根据角色简介中“{{name}}”的性格特点、说话风格和兴趣爱好,来模仿并回复消息。
|
||||
- 和朋友间的聊天是轻松的,有个性的,不要太一本正经的长篇大论,尽量保持回答的简短。
|
||||
- 参照个人简介、聊天记录和聊天背景信息中的细节,如当前时间、天气、过去的事件和未来的计划等,以确保对话的一致性和相关性。
|
||||
- 如果你无法从“{{name}}”的个人简介中找到相关的信息(比如人物关系,个人经历,事物细节等),请如实回答自己不清楚或忘记了,不要随意编造。
|
||||
|
||||
按照下面的JSON格式回复:
|
||||
{ message: "回复的消息内容" }
|
||||
`.trim();
|
||||
|
||||
const userTemplate = `
|
||||
{{message}}
|
||||
`.trim();
|
||||
|
||||
export interface IPerson {
|
||||
/**
|
||||
* 人物昵称
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* 人物简介
|
||||
*/
|
||||
profile: string;
|
||||
}
|
||||
|
||||
export class MyBot {
|
||||
private users: Record<string, User | undefined> = {
|
||||
bot: undefined,
|
||||
// 主人的个人信息
|
||||
master: undefined,
|
||||
};
|
||||
|
||||
constructor(config: { bot: IPerson; master: IPerson }) {
|
||||
this.createOrUpdateUser("bot", config.bot);
|
||||
this.createOrUpdateUser("master", config.master);
|
||||
}
|
||||
|
||||
async ask(msg: string) {
|
||||
const { bot, master } = this.users;
|
||||
if (!bot || !master) {
|
||||
console.error("❌ ask bot failed", bot, master);
|
||||
return undefined;
|
||||
}
|
||||
const botMemory = new UserMemory(bot);
|
||||
|
||||
const result = await openai.chat({
|
||||
system: buildPrompt(systemTemplate, {
|
||||
bot_name: this.bot.name,
|
||||
bot_profile: this.bot.profile,
|
||||
master_name: this.master.name,
|
||||
master_profile: this.master.profile,
|
||||
history:
|
||||
lastMessages.length < 1
|
||||
? "暂无"
|
||||
: lastMessages
|
||||
.map((e) =>
|
||||
jsonEncode({
|
||||
time: toUTC8Time(e.createdAt),
|
||||
user: e.user.name,
|
||||
message: e.text,
|
||||
})
|
||||
)
|
||||
.join("\n"),
|
||||
}),
|
||||
user: buildPrompt(userTemplate, {
|
||||
message: jsonEncode({
|
||||
time: toUTC8Time(new Date()),
|
||||
user: this.master.name,
|
||||
message: msg,
|
||||
})!,
|
||||
}),
|
||||
tools: [
|
||||
{
|
||||
type: "function",
|
||||
function: {
|
||||
name: "reply",
|
||||
description: "回复一条消息",
|
||||
parameters: {
|
||||
type: "object",
|
||||
properties: {
|
||||
message: { type: "string", description: "回复的消息内容" },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
return jsonDecode(result?.content)?.message;
|
||||
}
|
||||
|
||||
private async createOrUpdateUser(type: "bot" | "master", user: IPerson) {
|
||||
this.users[type] = await kPrisma.user
|
||||
.upsert({
|
||||
where: { id: this.users[type]?.id },
|
||||
create: user,
|
||||
update: user,
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error("❌ update user failed", type, user, e);
|
||||
return undefined;
|
||||
});
|
||||
}
|
||||
}
|
154
src/services/bot/memory/base.ts
Normal file
154
src/services/bot/memory/base.ts
Normal file
|
@ -0,0 +1,154 @@
|
|||
import { kPrisma } from "../../db";
|
||||
import { Memory, Message, User } from "@prisma/client";
|
||||
import { jsonDecode, jsonEncode, lastOf } from "../../../utils/base";
|
||||
import { ShortTermMemory } from "./short-term";
|
||||
import { LongTermMemory } from "./long-term";
|
||||
|
||||
// todo 在会话中,向会话的参与者分发消息(记忆),公共记忆,个人记忆
|
||||
export class UserMemory {
|
||||
private user: User;
|
||||
|
||||
constructor(user: User) {
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
async getRelatedMemories(limit: number): Promise<Memory[]> {
|
||||
// todo search memory embeddings
|
||||
return [];
|
||||
}
|
||||
|
||||
async count(options?: { cursor?: Memory; ownerId?: "all" | string }) {
|
||||
const { cursor, ownerId = this.user.id } = options ?? {};
|
||||
return kPrisma.memory
|
||||
.count({
|
||||
where: {
|
||||
ownerId: ownerId.toLowerCase() === "all" ? undefined : ownerId,
|
||||
id: {
|
||||
gt: cursor?.id,
|
||||
},
|
||||
},
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error("❌ get memory count failed", e);
|
||||
return -1;
|
||||
});
|
||||
}
|
||||
|
||||
async gets(options?: {
|
||||
ownerId?: "all" | string;
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
cursor?: Memory;
|
||||
order?: "asc" | "desc";
|
||||
}) {
|
||||
const {
|
||||
cursor,
|
||||
limit = 10,
|
||||
offset = 0,
|
||||
order = "desc",
|
||||
ownerId = this.user.id,
|
||||
} = options ?? {};
|
||||
const memories = await kPrisma.memory
|
||||
.findMany({
|
||||
cursor,
|
||||
where: {
|
||||
ownerId: ownerId.toLowerCase() === "all" ? undefined : ownerId,
|
||||
},
|
||||
take: limit,
|
||||
skip: offset,
|
||||
orderBy: { createdAt: order },
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error("❌ get memories failed", options, e);
|
||||
return [];
|
||||
});
|
||||
const orderedMemories = order === "desc" ? memories.reverse() : memories;
|
||||
return orderedMemories.map((e) => {
|
||||
return { ...e, content: jsonDecode(e.content)!.data };
|
||||
});
|
||||
}
|
||||
|
||||
async add(message: Message) {
|
||||
// todo create memory embedding
|
||||
const data = {
|
||||
ownerId: this.user.id,
|
||||
type: "message",
|
||||
content: jsonEncode({ data: message.text })!,
|
||||
};
|
||||
const memory = await kPrisma.memory.create({ data }).catch((e) => {
|
||||
console.error("❌ add memory to db failed", data, e);
|
||||
return undefined;
|
||||
});
|
||||
if (memory) {
|
||||
// 异步更新
|
||||
new ShortTermMemory(this.user).update(message, memory);
|
||||
}
|
||||
return memory;
|
||||
}
|
||||
}
|
||||
|
||||
export class MemoryHelper {
|
||||
static async updateAndConnectRelations(config: {
|
||||
user: User;
|
||||
message?: Message;
|
||||
memory?: Memory;
|
||||
shortTermMemory?: ShortTermMemory;
|
||||
longTermMemory?: LongTermMemory;
|
||||
}) {
|
||||
const { user, message, memory, shortTermMemory, longTermMemory } = config;
|
||||
const connect = (key: any, value: any) => {
|
||||
if (value) {
|
||||
return {
|
||||
[key]: {
|
||||
connect: [{ id: value.id }],
|
||||
},
|
||||
};
|
||||
}
|
||||
return {};
|
||||
};
|
||||
await kPrisma.user
|
||||
.update({
|
||||
where: { id: user.id },
|
||||
data: {
|
||||
...connect("messages", message),
|
||||
...connect("memories", memory),
|
||||
...connect("shortTermMemories", shortTermMemory),
|
||||
...connect("longTermMemories", longTermMemory),
|
||||
},
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error("❌ updateAndConnectRelations failed: user", e);
|
||||
});
|
||||
if (memory && shortTermMemory) {
|
||||
await kPrisma.memory
|
||||
.update({
|
||||
where: { id: memory.id },
|
||||
data: {
|
||||
shortTermMemories: {
|
||||
connect: [{ id: shortTermMemory.id }],
|
||||
},
|
||||
},
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error("❌ updateAndConnectRelations failed: memory", e);
|
||||
});
|
||||
}
|
||||
if (shortTermMemory && longTermMemory) {
|
||||
await kPrisma.shortTermMemory
|
||||
.update({
|
||||
where: { id: shortTermMemory?.id },
|
||||
data: {
|
||||
longTermMemories: {
|
||||
connect: [{ id: longTermMemory?.id }],
|
||||
},
|
||||
},
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error(
|
||||
"❌ updateAndConnectRelations failed: shortTermMemory",
|
||||
e
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
67
src/services/bot/memory/long-term.ts
Normal file
67
src/services/bot/memory/long-term.ts
Normal file
|
@ -0,0 +1,67 @@
|
|||
import { Memory, Message, User } from "@prisma/client";
|
||||
import { kPrisma } from "../../db";
|
||||
import { MemoryHelper, UserMemory } from "./base";
|
||||
import { lastOf } from "../../../utils/base";
|
||||
import { ShortTermMemory } from "./long-term";
|
||||
|
||||
export class LongTermMemory {
|
||||
static async get(user: User) {
|
||||
return kPrisma.longTermMemory
|
||||
.findFirst({
|
||||
include: { cursor: true },
|
||||
where: { ownerId: user.id },
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error("❌ get long memory failed", user, e);
|
||||
return undefined;
|
||||
});
|
||||
}
|
||||
|
||||
static async update(
|
||||
user: User,
|
||||
message: Message,
|
||||
memory: Memory,
|
||||
shortTermMemory: ShortTermMemory,
|
||||
threshold = 10 // 每隔 10 条记忆更新一次短期记忆
|
||||
) {
|
||||
const current = await LongTermMemory.get(user);
|
||||
const newMemories = await new ShortTermMemory(user).gets({
|
||||
ownerId: "all",
|
||||
cursor: current?.cursor,
|
||||
order: "asc", // 从旧到新排序
|
||||
});
|
||||
if (newMemories.length < threshold) {
|
||||
return undefined;
|
||||
}
|
||||
// todo update memory
|
||||
const content = "todo";
|
||||
const data = {
|
||||
ownerId: user.id,
|
||||
content,
|
||||
cursorId: lastOf(newMemories)!.id,
|
||||
};
|
||||
// 直接插入新的长期记忆,不更新旧的长期记忆记录
|
||||
const longTermMemory = await kPrisma.longTermMemory
|
||||
.create({ data })
|
||||
.catch((e) => {
|
||||
console.error(
|
||||
"❌ add or update longTermMemory failed",
|
||||
current,
|
||||
data,
|
||||
e
|
||||
);
|
||||
return undefined;
|
||||
});
|
||||
if (longTermMemory) {
|
||||
// 异步更新
|
||||
MemoryHelper.updateAndConnectRelations({
|
||||
user,
|
||||
message,
|
||||
memory,
|
||||
shortTermMemory,
|
||||
longTermMemory,
|
||||
});
|
||||
}
|
||||
return memory;
|
||||
}
|
||||
}
|
109
src/services/bot/memory/short-term.ts
Normal file
109
src/services/bot/memory/short-term.ts
Normal file
|
@ -0,0 +1,109 @@
|
|||
import {
|
||||
Memory,
|
||||
Message,
|
||||
User,
|
||||
ShortTermMemory as _ShortTermMemory,
|
||||
} from "@prisma/client";
|
||||
import { kPrisma } from "../../db";
|
||||
import { UserMemory } from "./base";
|
||||
import { lastOf } from "../../../utils/base";
|
||||
import { LongTermMemory } from "./long-term";
|
||||
|
||||
export class ShortTermMemory {
|
||||
private user: User;
|
||||
|
||||
constructor(user: User) {
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
async getRelatedMemories(limit: number): Promise<_ShortTermMemory[]> {
|
||||
// todo search memory embeddings
|
||||
return [];
|
||||
}
|
||||
|
||||
async count(options?: {
|
||||
cursor?: _ShortTermMemory;
|
||||
ownerId?: "all" | string;
|
||||
}) {
|
||||
const { cursor, ownerId = this.user.id } = options ?? {};
|
||||
return kPrisma.memory
|
||||
.count({
|
||||
where: {
|
||||
ownerId: ownerId.toLowerCase() === "all" ? undefined : ownerId,
|
||||
id: {
|
||||
gt: cursor?.id,
|
||||
},
|
||||
},
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error("❌ get memory count failed", e);
|
||||
return -1;
|
||||
});
|
||||
}
|
||||
|
||||
async get() {
|
||||
return kPrisma.shortTermMemory
|
||||
.findFirst({
|
||||
include: { cursor: true },
|
||||
where: { ownerId: this.user.id },
|
||||
orderBy: { createdAt: "desc" },
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error("❌ get short memory failed", this.user, e);
|
||||
return undefined;
|
||||
});
|
||||
}
|
||||
|
||||
async gets() {
|
||||
return kPrisma.shortTermMemory
|
||||
.findFirst({
|
||||
include: { cursor: true },
|
||||
where: { ownerId: this.user.id },
|
||||
orderBy: { createdAt: "desc" },
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error("❌ get short memory failed", this.user, e);
|
||||
return undefined;
|
||||
});
|
||||
}
|
||||
|
||||
async update(
|
||||
message: Message,
|
||||
memory: Memory,
|
||||
threshold = 10 // 每隔 10 条记忆更新一次短期记忆
|
||||
) {
|
||||
const current = await this.get();
|
||||
const newMemories = await new UserMemory(this.user).gets({
|
||||
ownerId: "all",
|
||||
cursor: current?.cursor,
|
||||
order: "asc", // 从旧到新排序
|
||||
});
|
||||
if (newMemories.length < threshold) {
|
||||
return undefined;
|
||||
}
|
||||
// todo update memory
|
||||
const content = "todo";
|
||||
const data = {
|
||||
ownerId: this.user.id,
|
||||
content,
|
||||
cursorId: lastOf(newMemories)!.id,
|
||||
};
|
||||
// 直接插入新的短期记忆,不更新旧的短期记忆记录
|
||||
const shortTermMemory = await kPrisma.shortTermMemory
|
||||
.create({ data })
|
||||
.catch((e) => {
|
||||
console.error(
|
||||
"❌ add or update shortTermMemory failed",
|
||||
current,
|
||||
data,
|
||||
e
|
||||
);
|
||||
return undefined;
|
||||
});
|
||||
if (shortTermMemory) {
|
||||
// 异步更新
|
||||
LongTermMemory.update(this.user, message, memory, shortTermMemory);
|
||||
}
|
||||
return memory;
|
||||
}
|
||||
}
|
83
src/services/bot/message.ts
Normal file
83
src/services/bot/message.ts
Normal file
|
@ -0,0 +1,83 @@
|
|||
import { Message, User } from "@prisma/client";
|
||||
import { kPrisma } from "../db";
|
||||
import { UserMemory } from "./memory";
|
||||
|
||||
class _MessageHistory {
|
||||
async count(options?: { cursor?: Message; sender?: User }) {
|
||||
const { sender, cursor } = options ?? {};
|
||||
return kPrisma.message
|
||||
.count({
|
||||
where: {
|
||||
senderId: sender?.id,
|
||||
id: {
|
||||
gt: cursor?.id,
|
||||
},
|
||||
},
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error("❌ get msg count failed", e);
|
||||
return -1;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询历史消息,消息从旧到新排序
|
||||
*/
|
||||
async gets(options?: {
|
||||
sender?: User;
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
cursor?: Message;
|
||||
order?: "asc" | "desc";
|
||||
}) {
|
||||
const {
|
||||
limit = 10,
|
||||
offset = 0,
|
||||
order = "desc",
|
||||
sender,
|
||||
cursor,
|
||||
} = options ?? {};
|
||||
const msgs = await kPrisma.message
|
||||
.findMany({
|
||||
cursor,
|
||||
where: { senderId: sender?.id },
|
||||
take: limit,
|
||||
skip: offset,
|
||||
orderBy: { createdAt: order },
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error("❌ get msgs failed", options, e);
|
||||
return [];
|
||||
});
|
||||
return order === "desc" ? msgs.reverse() : msgs;
|
||||
}
|
||||
|
||||
async addOrUpdate(
|
||||
msg: Partial<Message> & {
|
||||
text: string;
|
||||
sender: User;
|
||||
}
|
||||
) {
|
||||
const data = {
|
||||
text: msg.text,
|
||||
senderId: msg.sender?.id,
|
||||
};
|
||||
const message = await kPrisma.message
|
||||
.upsert({
|
||||
where: { id: msg.id },
|
||||
create: data,
|
||||
update: data,
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error("❌ add msg to db failed", msg, e);
|
||||
return undefined;
|
||||
});
|
||||
if (message) {
|
||||
// 异步更新记忆
|
||||
new UserMemory(msg.sender).add(message);
|
||||
}
|
||||
return message;
|
||||
}
|
||||
}
|
||||
|
||||
export const MessageHistory = new _MessageHistory();
|
15
src/services/db.ts
Normal file
15
src/services/db.ts
Normal file
|
@ -0,0 +1,15 @@
|
|||
import { PrismaClient } from "@prisma/client";
|
||||
|
||||
export const kPrisma = new PrismaClient();
|
||||
|
||||
export function runWithDB(main: () => Promise<void>) {
|
||||
main()
|
||||
.then(async () => {
|
||||
await kPrisma.$disconnect();
|
||||
})
|
||||
.catch(async (e) => {
|
||||
console.error(e);
|
||||
await kPrisma.$disconnect();
|
||||
process.exit(1);
|
||||
});
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
import axios, { AxiosRequestConfig, CreateAxiosDefaults } from "axios";
|
||||
import { isNotEmpty } from "./is";
|
||||
import { isNotEmpty } from "../utils/is";
|
||||
|
||||
const _baseConfig: CreateAxiosDefaults = {
|
||||
timeout: 10 * 1000,
|
36
src/services/openai.ts
Normal file
36
src/services/openai.ts
Normal file
|
@ -0,0 +1,36 @@
|
|||
import OpenAI from "openai";
|
||||
import {
|
||||
ChatCompletionMessageParam,
|
||||
ChatCompletionTool,
|
||||
} from "openai/resources";
|
||||
|
||||
import { kEnvs } from "../utils/env";
|
||||
|
||||
const client = new OpenAI({
|
||||
apiKey: kEnvs.OPENAI_API_KEY!,
|
||||
});
|
||||
|
||||
export const openai = {
|
||||
async chat(options: {
|
||||
user: string;
|
||||
system?: string;
|
||||
tools?: Array<ChatCompletionTool>;
|
||||
jsonMode?: boolean;
|
||||
}) {
|
||||
const systemMsg: ChatCompletionMessageParam[] = options.system
|
||||
? [{ role: "system", content: options.system }]
|
||||
: [];
|
||||
const chatCompletion = await client.chat.completions
|
||||
.create({
|
||||
tools: options.tools,
|
||||
messages: [...systemMsg, { role: "user", content: options.user }],
|
||||
model: kEnvs.OPENAI_MODEL ?? "gpt-3.5-turbo-1106",
|
||||
response_format: options.jsonMode ? { type: "json_object" } : undefined,
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error("❌ openai chat failed", e);
|
||||
return null;
|
||||
});
|
||||
return chatCompletion?.choices?.[0]?.message;
|
||||
},
|
||||
};
|
|
@ -96,7 +96,7 @@ export function jsonEncode(obj: any, options?: { prettier?: boolean }) {
|
|||
}
|
||||
}
|
||||
|
||||
export function jsonDecode(json: string | undefined) {
|
||||
export function jsonDecode(json: string | null | undefined) {
|
||||
if (json == undefined) return undefined;
|
||||
try {
|
||||
return JSON.parse(json!);
|
||||
|
|
7
src/utils/env.ts
Normal file
7
src/utils/env.ts
Normal file
|
@ -0,0 +1,7 @@
|
|||
export const kEnvs: Partial<{
|
||||
MI_USER: string;
|
||||
MI_PASS: string;
|
||||
MI_DID: string;
|
||||
OPENAI_MODEL: string;
|
||||
OPENAI_API_KEY: string;
|
||||
}> = process.env as any;
|
|
@ -1,12 +1,10 @@
|
|||
import * as fs from "fs";
|
||||
import * as path from "path";
|
||||
|
||||
import { jsonDecode, jsonEncode } from "./json";
|
||||
import { jsonDecode, jsonEncode } from "./base";
|
||||
|
||||
export const kRoot = process.cwd();
|
||||
|
||||
export const kEnvs = process.env as any;
|
||||
|
||||
export const exists = (filePath: string) => fs.existsSync(filePath);
|
||||
|
||||
export const deleteFile = (filePath: string) => {
|
||||
|
@ -18,6 +16,14 @@ export const deleteFile = (filePath: string) => {
|
|||
}
|
||||
};
|
||||
|
||||
export const getFiles = (dir: string) => {
|
||||
return new Promise<string[]>((resolve) => {
|
||||
fs.readdir(dir, (err, files) => {
|
||||
resolve(err ? [] : files);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
export const readFile = <T = any>(
|
||||
filePath: string,
|
||||
options?: fs.WriteFileOptions
|
||||
|
@ -33,6 +39,17 @@ export const readFile = <T = any>(
|
|||
});
|
||||
};
|
||||
|
||||
export const readFileSync = (
|
||||
filePath: string,
|
||||
options?: fs.WriteFileOptions
|
||||
) => {
|
||||
const dirname = path.dirname(filePath);
|
||||
if (!fs.existsSync(dirname)) {
|
||||
return undefined;
|
||||
}
|
||||
return fs.readFileSync(filePath, options);
|
||||
};
|
||||
|
||||
export const writeFile = (
|
||||
filePath: string,
|
||||
data: string | NodeJS.ArrayBufferView,
|
||||
|
@ -58,19 +75,17 @@ export const writeFile = (
|
|||
export const readString = (filePath: string) =>
|
||||
readFile<string>(filePath, "utf8");
|
||||
|
||||
export const readStringSync = (filePath: string) =>
|
||||
readFileSync(filePath, "utf8")?.toString();
|
||||
|
||||
export const writeString = (filePath: string, content: string) =>
|
||||
writeFile(filePath, content, "utf8");
|
||||
|
||||
export const readJSON = async (filePath: string) =>
|
||||
jsonDecode(await readFile<string>(filePath, "utf8"));
|
||||
jsonDecode(await readString(filePath));
|
||||
|
||||
export const readJSONSync = (filePath: string) =>
|
||||
jsonDecode(readStringSync(filePath));
|
||||
|
||||
export const writeJSON = (filePath: string, content: any) =>
|
||||
writeFile(filePath, jsonEncode(content) ?? "", "utf8");
|
||||
|
||||
export const getFiles = (dir: string) => {
|
||||
return new Promise<string[]>((resolve) => {
|
||||
fs.readdir(dir, (err, files) => {
|
||||
resolve(err ? [] : files);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
|
45
src/utils/string.ts
Normal file
45
src/utils/string.ts
Normal file
|
@ -0,0 +1,45 @@
|
|||
import { readJSONSync } from './io';
|
||||
|
||||
export const kVersion = readJSONSync('package.json').version;
|
||||
|
||||
export const kBannerASCII = `
|
||||
|
||||
/$$ /$$ /$$ /$$$$$$ /$$$$$$$ /$$$$$$$$
|
||||
| $$$ /$$$|__/ /$$__ $$| $$__ $$|__ $$__/
|
||||
| $$$$ /$$$$ /$$| $$ \__/| $$ \ $$ | $$
|
||||
| $$ $$/$$ $$| $$| $$ /$$$$| $$$$$$$/ | $$
|
||||
| $$ $$$| $$| $$| $$|_ $$| $$____/ | $$
|
||||
| $$\ $ | $$| $$| $$ \ $$| $$ | $$
|
||||
| $$ \/ | $$| $$| $$$$$$/| $$ | $$
|
||||
|__/ |__/|__/ \______/ |__/ |__/
|
||||
|
||||
MiGPT v1.0.0 by: del-wang.eth
|
||||
|
||||
`.replace('1.0.0', kVersion);
|
||||
|
||||
/**
|
||||
* 转北京时间:2023年12月12日星期二 12:46
|
||||
*/
|
||||
export function toUTC8Time(date: Date) {
|
||||
return date.toLocaleString('zh-CN', {
|
||||
year: 'numeric',
|
||||
month: '2-digit',
|
||||
weekday: 'long',
|
||||
day: '2-digit',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
hour12: false,
|
||||
timeZone: 'Asia/Shanghai',
|
||||
});
|
||||
}
|
||||
|
||||
export function buildPrompt(
|
||||
template: string,
|
||||
variables: Record<string, string>
|
||||
) {
|
||||
for (const key in variables) {
|
||||
const value = variables[key];
|
||||
template = template.replaceAll(`{{${key}}}`, value);
|
||||
}
|
||||
return template;
|
||||
}
|
|
@ -1,9 +1,12 @@
|
|||
import dotenv from "dotenv";
|
||||
import { println } from "../src/utils/base";
|
||||
import { kBannerASCII } from "../src/utils/string";
|
||||
import { runWithDB } from "../src/services/db";
|
||||
|
||||
dotenv.config();
|
||||
|
||||
async function main() {
|
||||
console.log("hello world!");
|
||||
println(kBannerASCII);
|
||||
}
|
||||
|
||||
main();
|
||||
runWithDB(main);
|
||||
|
|
|
@ -8,6 +8,6 @@
|
|||
"esModuleInterop": true,
|
||||
"moduleResolution": "node"
|
||||
},
|
||||
"include": ["src"],
|
||||
"exclude": ["node_modules"]
|
||||
"include": ["src", "tests"],
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
||||
|
|
206
yarn.lock
206
yarn.lock
|
@ -202,6 +202,47 @@
|
|||
resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33"
|
||||
integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==
|
||||
|
||||
"@prisma/client@^5.8.1":
|
||||
version "5.8.1"
|
||||
resolved "https://registry.yarnpkg.com/@prisma/client/-/client-5.8.1.tgz#7815ec51c0ca2a6de219c02e7846701ae3baf240"
|
||||
integrity sha512-xQtMPfbIwLlbm0VVIVQY2yqQVOxPwRQhvIp7Z3m2900g1bu/zRHKhYZJQWELqmjl6d8YwBy0K2NvMqh47v1ubw==
|
||||
|
||||
"@prisma/debug@5.8.1":
|
||||
version "5.8.1"
|
||||
resolved "https://registry.yarnpkg.com/@prisma/debug/-/debug-5.8.1.tgz#704daa36919b0fc4d227260ecebfa1c94b155b07"
|
||||
integrity sha512-tjuw7eA0Us3T42jx9AmAgL58rzwzpFGYc3R7Y4Ip75EBYrKMBA1YihuWMcBC92ILmjlQ/u3p8VxcIE0hr+fZfg==
|
||||
|
||||
"@prisma/engines-version@5.8.1-1.78caf6feeaed953168c64e15a249c3e9a033ebe2":
|
||||
version "5.8.1-1.78caf6feeaed953168c64e15a249c3e9a033ebe2"
|
||||
resolved "https://registry.yarnpkg.com/@prisma/engines-version/-/engines-version-5.8.1-1.78caf6feeaed953168c64e15a249c3e9a033ebe2.tgz#f600a45afc4cf0c0356b6ed90add6050fa3f3239"
|
||||
integrity sha512-f5C3JM3l9yhGr3cr4FMqWloFaSCpNpMi58Om22rjD2DOz3owci2mFdFXMgnAGazFPKrCbbEhcxdsRfspEYRoFQ==
|
||||
|
||||
"@prisma/engines@5.8.1":
|
||||
version "5.8.1"
|
||||
resolved "https://registry.yarnpkg.com/@prisma/engines/-/engines-5.8.1.tgz#b850751f5bf7d5e570b9fe16cefdc2b1fd2c02c3"
|
||||
integrity sha512-TJgYLRrZr56uhqcXO4GmP5be+zjCIHtLDK20Cnfg+o9d905hsN065QOL+3Z0zQAy6YD31Ol4u2kzSfRmbJv/uA==
|
||||
dependencies:
|
||||
"@prisma/debug" "5.8.1"
|
||||
"@prisma/engines-version" "5.8.1-1.78caf6feeaed953168c64e15a249c3e9a033ebe2"
|
||||
"@prisma/fetch-engine" "5.8.1"
|
||||
"@prisma/get-platform" "5.8.1"
|
||||
|
||||
"@prisma/fetch-engine@5.8.1":
|
||||
version "5.8.1"
|
||||
resolved "https://registry.yarnpkg.com/@prisma/fetch-engine/-/fetch-engine-5.8.1.tgz#38bb92f1fbd3669340a3cc49fce403ab4df671dd"
|
||||
integrity sha512-+bgjjoSFa6uYEbAPlklfoVSStOEfcpheOjoBoNsNNSQdSzcwE2nM4Q0prun0+P8/0sCHo18JZ9xqa8gObvgOUw==
|
||||
dependencies:
|
||||
"@prisma/debug" "5.8.1"
|
||||
"@prisma/engines-version" "5.8.1-1.78caf6feeaed953168c64e15a249c3e9a033ebe2"
|
||||
"@prisma/get-platform" "5.8.1"
|
||||
|
||||
"@prisma/get-platform@5.8.1":
|
||||
version "5.8.1"
|
||||
resolved "https://registry.yarnpkg.com/@prisma/get-platform/-/get-platform-5.8.1.tgz#8cd450b65a52a5a6ed5b2f52457136a492c0f251"
|
||||
integrity sha512-wnA+6HTFcY+tkykMokix9GiAkaauPC5W/gg0O5JB0J8tCTNWrqpnQ7AsaGRfkYUbeOIioh6woDjQrGTTRf1Zag==
|
||||
dependencies:
|
||||
"@prisma/debug" "5.8.1"
|
||||
|
||||
"@rollup/rollup-android-arm-eabi@4.9.6":
|
||||
version "4.9.6"
|
||||
resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.9.6.tgz#66b8d9cb2b3a474d115500f9ebaf43e2126fe496"
|
||||
|
@ -292,6 +333,28 @@
|
|||
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4"
|
||||
integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==
|
||||
|
||||
"@types/node-fetch@^2.6.4":
|
||||
version "2.6.11"
|
||||
resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.11.tgz#9b39b78665dae0e82a08f02f4967d62c66f95d24"
|
||||
integrity sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
form-data "^4.0.0"
|
||||
|
||||
"@types/node@*":
|
||||
version "20.11.6"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.11.6.tgz#6adf4241460e28be53836529c033a41985f85b6e"
|
||||
integrity sha512-+EOokTnksGVgip2PbYbr3xnR7kZigh4LbybAfBAw5BpnQ+FqBYUsvCEjYd70IXKlbohQ64mzEYmMtlWUY8q//Q==
|
||||
dependencies:
|
||||
undici-types "~5.26.4"
|
||||
|
||||
"@types/node@^18.11.18":
|
||||
version "18.19.9"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.19.9.tgz#6c2624c3a05bfa3a2735c533f95597ffacbb5608"
|
||||
integrity sha512-oZFKlC8l5YtzGQNT4zC2PiSSKzQVZ8bAwwd+EYdPLtyk0nSEq6O16SkK+rkkT2eflDAbormJgEF3QnH3oDrTSw==
|
||||
dependencies:
|
||||
undici-types "~5.26.4"
|
||||
|
||||
"@types/node@^20.4.9":
|
||||
version "20.11.5"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.11.5.tgz#be10c622ca7fcaa3cf226cf80166abc31389d86e"
|
||||
|
@ -299,6 +362,13 @@
|
|||
dependencies:
|
||||
undici-types "~5.26.4"
|
||||
|
||||
abort-controller@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392"
|
||||
integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==
|
||||
dependencies:
|
||||
event-target-shim "^5.0.0"
|
||||
|
||||
acorn-walk@^8.1.1:
|
||||
version "8.3.2"
|
||||
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.2.tgz#7703af9415f1b6db9315d6895503862e231d34aa"
|
||||
|
@ -309,6 +379,13 @@ acorn@^8.4.1:
|
|||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a"
|
||||
integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==
|
||||
|
||||
agentkeepalive@^4.2.1:
|
||||
version "4.5.0"
|
||||
resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-4.5.0.tgz#2673ad1389b3c418c5a20c5d7364f93ca04be923"
|
||||
integrity sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==
|
||||
dependencies:
|
||||
humanize-ms "^1.2.1"
|
||||
|
||||
ansi-regex@^5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
|
||||
|
@ -373,6 +450,11 @@ balanced-match@^1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
|
||||
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
|
||||
|
||||
base-64@^0.1.0:
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/base-64/-/base-64-0.1.0.tgz#780a99c84e7d600260361511c4877613bf24f6bb"
|
||||
integrity sha512-Y5gU45svrR5tI2Vt/X9GPd3L0HNIKzGu202EjxrXMpuc2V2CiKgemAbUUsqYmZJvPtCXoUKjNZwBJzsNScUbXA==
|
||||
|
||||
binary-extensions@^2.0.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d"
|
||||
|
@ -404,6 +486,11 @@ cac@^6.7.12:
|
|||
resolved "https://registry.yarnpkg.com/cac/-/cac-6.7.14.tgz#804e1e6f506ee363cb0e3ccbb09cad5dd9870959"
|
||||
integrity sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==
|
||||
|
||||
charenc@0.0.2:
|
||||
version "0.0.2"
|
||||
resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667"
|
||||
integrity sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==
|
||||
|
||||
chokidar@^3.5.1:
|
||||
version "3.5.3"
|
||||
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd"
|
||||
|
@ -457,6 +544,11 @@ cross-spawn@^7.0.0, cross-spawn@^7.0.3:
|
|||
shebang-command "^2.0.0"
|
||||
which "^2.0.1"
|
||||
|
||||
crypt@0.0.2:
|
||||
version "0.0.2"
|
||||
resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b"
|
||||
integrity sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==
|
||||
|
||||
debug@^4.3.1:
|
||||
version "4.3.4"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
|
||||
|
@ -474,6 +566,14 @@ diff@^4.0.1:
|
|||
resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d"
|
||||
integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==
|
||||
|
||||
digest-fetch@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/digest-fetch/-/digest-fetch-1.3.0.tgz#898e69264d00012a23cf26e8a3e40320143fc661"
|
||||
integrity sha512-CGJuv6iKNM7QyZlM2T3sPAdZWd/p9zQiRNS9G+9COUCwzWFTs0Xp8NF5iePx7wtvhDykReiRRrSeNb4oMmB8lA==
|
||||
dependencies:
|
||||
base-64 "^0.1.0"
|
||||
md5 "^2.3.0"
|
||||
|
||||
dir-glob@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f"
|
||||
|
@ -530,6 +630,11 @@ esbuild@^0.19.2:
|
|||
"@esbuild/win32-ia32" "0.19.12"
|
||||
"@esbuild/win32-x64" "0.19.12"
|
||||
|
||||
event-target-shim@^5.0.0:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789"
|
||||
integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==
|
||||
|
||||
execa@^5.0.0:
|
||||
version "5.1.1"
|
||||
resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd"
|
||||
|
@ -583,6 +688,11 @@ foreground-child@^3.1.0:
|
|||
cross-spawn "^7.0.0"
|
||||
signal-exit "^4.0.1"
|
||||
|
||||
form-data-encoder@1.7.2:
|
||||
version "1.7.2"
|
||||
resolved "https://registry.yarnpkg.com/form-data-encoder/-/form-data-encoder-1.7.2.tgz#1f1ae3dccf58ed4690b86d87e4f57c654fbab040"
|
||||
integrity sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==
|
||||
|
||||
form-data@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452"
|
||||
|
@ -592,6 +702,14 @@ form-data@^4.0.0:
|
|||
combined-stream "^1.0.8"
|
||||
mime-types "^2.1.12"
|
||||
|
||||
formdata-node@^4.3.2:
|
||||
version "4.4.1"
|
||||
resolved "https://registry.yarnpkg.com/formdata-node/-/formdata-node-4.4.1.tgz#23f6a5cb9cb55315912cbec4ff7b0f59bbd191e2"
|
||||
integrity sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==
|
||||
dependencies:
|
||||
node-domexception "1.0.0"
|
||||
web-streams-polyfill "4.0.0-beta.3"
|
||||
|
||||
fsevents@~2.3.2:
|
||||
version "2.3.3"
|
||||
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6"
|
||||
|
@ -637,6 +755,13 @@ human-signals@^2.1.0:
|
|||
resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0"
|
||||
integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==
|
||||
|
||||
humanize-ms@^1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed"
|
||||
integrity sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==
|
||||
dependencies:
|
||||
ms "^2.0.0"
|
||||
|
||||
ignore@^5.2.0:
|
||||
version "5.3.0"
|
||||
resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.0.tgz#67418ae40d34d6999c95ff56016759c718c82f78"
|
||||
|
@ -649,6 +774,11 @@ is-binary-path@~2.1.0:
|
|||
dependencies:
|
||||
binary-extensions "^2.0.0"
|
||||
|
||||
is-buffer@~1.1.6:
|
||||
version "1.1.6"
|
||||
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
|
||||
integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==
|
||||
|
||||
is-extglob@^2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
|
||||
|
@ -725,6 +855,15 @@ make-error@^1.1.1:
|
|||
resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2"
|
||||
integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==
|
||||
|
||||
md5@^2.3.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/md5/-/md5-2.3.0.tgz#c3da9a6aae3a30b46b7b0c349b87b110dc3bda4f"
|
||||
integrity sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==
|
||||
dependencies:
|
||||
charenc "0.0.2"
|
||||
crypt "0.0.2"
|
||||
is-buffer "~1.1.6"
|
||||
|
||||
merge-stream@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60"
|
||||
|
@ -777,6 +916,11 @@ ms@2.1.2:
|
|||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
|
||||
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
|
||||
|
||||
ms@^2.0.0:
|
||||
version "2.1.3"
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
|
||||
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
|
||||
|
||||
mz@^2.7.0:
|
||||
version "2.7.0"
|
||||
resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32"
|
||||
|
@ -786,6 +930,18 @@ mz@^2.7.0:
|
|||
object-assign "^4.0.1"
|
||||
thenify-all "^1.0.0"
|
||||
|
||||
node-domexception@1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5"
|
||||
integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==
|
||||
|
||||
node-fetch@^2.6.7:
|
||||
version "2.7.0"
|
||||
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d"
|
||||
integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==
|
||||
dependencies:
|
||||
whatwg-url "^5.0.0"
|
||||
|
||||
normalize-path@^3.0.0, normalize-path@~3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
|
||||
|
@ -810,6 +966,21 @@ onetime@^5.1.2:
|
|||
dependencies:
|
||||
mimic-fn "^2.1.0"
|
||||
|
||||
openai@^4.25.0:
|
||||
version "4.25.0"
|
||||
resolved "https://registry.yarnpkg.com/openai/-/openai-4.25.0.tgz#b40099d625cccb19cbf1cab88915ac1699ece0ed"
|
||||
integrity sha512-qLMFOizjxKuDfQkBrczZPYo6XVL4bdcuz9MR11Q+M91kGcs8dQw+O90nRcC+qWuhaGphQkfXQJMn4cd7Yew3Kg==
|
||||
dependencies:
|
||||
"@types/node" "^18.11.18"
|
||||
"@types/node-fetch" "^2.6.4"
|
||||
abort-controller "^3.0.0"
|
||||
agentkeepalive "^4.2.1"
|
||||
digest-fetch "^1.3.0"
|
||||
form-data-encoder "1.7.2"
|
||||
formdata-node "^4.3.2"
|
||||
node-fetch "^2.6.7"
|
||||
web-streams-polyfill "^3.2.1"
|
||||
|
||||
path-key@^3.0.0, path-key@^3.1.0:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375"
|
||||
|
@ -846,6 +1017,13 @@ postcss-load-config@^4.0.1:
|
|||
lilconfig "^3.0.0"
|
||||
yaml "^2.3.4"
|
||||
|
||||
prisma@^5.8.1:
|
||||
version "5.8.1"
|
||||
resolved "https://registry.yarnpkg.com/prisma/-/prisma-5.8.1.tgz#1f101793a8831c0719dfbed5f85a96ea4888c9d3"
|
||||
integrity sha512-N6CpjzECnUHZ5beeYpDzkt2rYpEdAeqXX2dweu6BoQaeYkNZrC/WJHM+5MO/uidFHTak8QhkPKBWck1o/4MD4A==
|
||||
dependencies:
|
||||
"@prisma/engines" "5.8.1"
|
||||
|
||||
proxy-from-env@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2"
|
||||
|
@ -1021,6 +1199,11 @@ tr46@^1.0.1:
|
|||
dependencies:
|
||||
punycode "^2.1.0"
|
||||
|
||||
tr46@~0.0.3:
|
||||
version "0.0.3"
|
||||
resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
|
||||
integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==
|
||||
|
||||
tree-kill@^1.2.2:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc"
|
||||
|
@ -1085,11 +1268,34 @@ v8-compile-cache-lib@^3.0.1:
|
|||
resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf"
|
||||
integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==
|
||||
|
||||
web-streams-polyfill@4.0.0-beta.3:
|
||||
version "4.0.0-beta.3"
|
||||
resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz#2898486b74f5156095e473efe989dcf185047a38"
|
||||
integrity sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==
|
||||
|
||||
web-streams-polyfill@^3.2.1:
|
||||
version "3.3.2"
|
||||
resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.3.2.tgz#32e26522e05128203a7de59519be3c648004343b"
|
||||
integrity sha512-3pRGuxRF5gpuZc0W+EpwQRmCD7gRqcDOMt688KmdlDAgAyaB1XlN0zq2njfDNm44XVdIouE7pZ6GzbdyH47uIQ==
|
||||
|
||||
webidl-conversions@^3.0.0:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
|
||||
integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==
|
||||
|
||||
webidl-conversions@^4.0.2:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad"
|
||||
integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==
|
||||
|
||||
whatwg-url@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d"
|
||||
integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==
|
||||
dependencies:
|
||||
tr46 "~0.0.3"
|
||||
webidl-conversions "^3.0.0"
|
||||
|
||||
whatwg-url@^7.0.0:
|
||||
version "7.1.0"
|
||||
resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-7.1.0.tgz#c2c492f1eca612988efd3d2266be1b9fc6170d06"
|
||||
|
|
Loading…
Reference in New Issue
Block a user