new selfhosted version

This commit is contained in:
antonio
2025-11-28 14:11:51 +01:00
parent afda29997d
commit 951860f67e
1046 changed files with 72586 additions and 574750 deletions

View File

@@ -1,16 +0,0 @@
import { AiChatModel } from "@schema/ai/AiChatSchema";
export default defineEventHandler(async event => {
const data = await getRequestData(event, [], ['AI']);
if (!data) return;
const { project_id } = data;
if (!event.context.params) return;
const chat_id = event.context.params['chat_id'];
const result = await AiChatModel.updateOne({ _id: chat_id, project_id }, { deleted: true });
return result.modifiedCount > 0;
});

View File

@@ -1,30 +0,0 @@
import { getUserProjectFromId } from "~/server/LIVE_DEMO_DATA";
import { AiChatModel } from "@schema/ai/AiChatSchema";
import type OpenAI from "openai";
import { getChartsInMessage } from "~/server/services/AiService";
export default defineEventHandler(async event => {
const data = await getRequestData(event, [], ['AI']);
if (!data) return;
const isAdmin = data.user.user.roles.includes('ADMIN');
const { project_id } = data;
if (!event.context.params) return;
const chat_id = event.context.params['chat_id'];
const chat = await AiChatModel.findOne({ _id: chat_id, project_id });
if (!chat) return;
return (chat.messages as OpenAI.Chat.Completions.ChatCompletionMessageParam[])
.filter(e => isAdmin ? true : (e.role === 'assistant' || e.role === 'user'))
.map(e => {
const charts = getChartsInMessage(e);
const content = e.content;
return { ...e, charts }
})
.filter(e => {
return isAdmin ? true : (e.charts.length > 0 || e.content);
})
});

View File

@@ -1,17 +0,0 @@
import { AiChatModel } from "@schema/ai/AiChatSchema";
export default defineEventHandler(async event => {
const data = await getRequestData(event, [], ['AI']);
if (!data) return;
const { project_id } = data;
if (!event.context.params) return;
const chat_id = event.context.params['chat_id'];
const chat = await AiChatModel.findOne({ _id: chat_id, project_id }, { status: 1, completed: 1 });
if (!chat) return;
return { status: chat.status, completed: chat.completed || false }
});

View File

@@ -0,0 +1,22 @@
import { AiService } from "~/server/services/ai/AiService";
export default defineEventHandler(async event => {
const ctx = await getRequestContext(event, 'pid');
const { user_email, pid } = ctx;
const query = getQuery(event);
const { message } = await readBody(event);
if (!message) throw createError({ status: 400, message: 'message is required' });
const chat_id = await AiService.handleUserMessage({
name: user_email.split('@')[0],
pid,
text: message,
chat_id: query.chat_id?.toString()
});
return { chat_id }
});

View File

@@ -0,0 +1,16 @@
import { AiNewChatModel } from "~/shared/schema/ai/AiNewChatSchema";
export default defineEventHandler(async event => {
const ctx = await getRequestContext(event, 'pid');
const { project_id } = ctx;
const { id } = getQuery(event);
const chat = await AiNewChatModel.findOne({ _id: id, project_id });
if (!chat) return;
return chat;
});

View File

@@ -1,16 +0,0 @@
import { getUserProjectFromId } from "~/server/LIVE_DEMO_DATA";
import { AiChatModel } from "@schema/ai/AiChatSchema";
export default defineEventHandler(async event => {
const data = await getRequestDataOld(event);
if (!data) return;
const { project_id } = data;
const chatList = await AiChatModel.find({ project_id, deleted: false }, { _id: 1, title: 1 }, { sort: { updated_at: 1 } });
return chatList.map(e => e.toJSON());
});

View File

@@ -1,20 +0,0 @@
import { ProjectLimitModel } from "@schema/project/ProjectsLimits";
export async function getAiChatRemainings(project_id: string) {
const limits = await ProjectLimitModel.findOne({ project_id })
if (!limits) return 0;
const chatsRemaining = limits.ai_limit - limits.ai_messages;
if (isNaN(chatsRemaining)) return 0;
return chatsRemaining;
}
export default defineEventHandler(async event => {
const data = await getRequestData(event, [], ['AI']);
if (!data) return;
const { pid } = data;
const chatsRemaining = await getAiChatRemainings(pid);
return chatsRemaining;
});

View File

@@ -1,13 +1,14 @@
import { AiChatModel } from "@schema/ai/AiChatSchema";
import { AiNewChatModel } from "~/shared/schema/ai/AiNewChatSchema";
export default defineEventHandler(async event => {
const data = await getRequestData(event, [], ['AI']);
if (!data) return;
const ctx = await getRequestContext(event, 'pid');
const { project_id } = ctx;
const { project_id } = data;
const chat = await AiNewChatModel.updateMany({ project_id }, { deleted: true });
if (!chat) return;
return chat;
const result = await AiChatModel.updateMany({ project_id }, { deleted: true });
return result.modifiedCount > 0;
});

View File

@@ -0,0 +1,16 @@
import { AiNewChatModel } from "~/shared/schema/ai/AiNewChatSchema";
export default defineEventHandler(async event => {
const ctx = await getRequestContext(event, 'pid');
const { project_id } = ctx;
const { chat_id } = getQuery(event);
const chat = await AiNewChatModel.updateOne({ _id: chat_id, project_id }, { deleted: true });
if (!chat) return;
return chat;
});

View File

@@ -0,0 +1,21 @@
import { Types } from "mongoose";
import { AiNewChatModel } from "~/shared/schema/ai/AiNewChatSchema";
export default defineEventHandler(async event => {
const ctx = await getRequestContext(event, 'pid');
const { project_id } = ctx;
const { chat_id, message_index } = getQuery(event);
if (!chat_id) throw createError({ status: 400, message: 'chat_id is required' });
if (!message_index) throw createError({ status: 400, message: 'message_index is required' });
const index = parseInt(message_index as string);
if (isNaN(index)) throw createError({ status: 400, message: 'message_index must be a number' });
const update = await AiNewChatModel.updateOne({ _id: new Types.ObjectId(chat_id as string), project_id }, { $set: { [`messages.${index}.downvoted`]: true } });
return update;
});

View File

@@ -0,0 +1,9 @@
import { AiService } from "~/server/services/ai/AiService";
export default defineEventHandler(async event => {
const ctx = await getRequestContext(event, 'pid', 'permission:ai');
const { project_id } = ctx;
const res = await AiService.generateInsight(project_id.toString());
return res;
});

View File

@@ -0,0 +1,12 @@
import { AiNewChatModel } from "~/shared/schema/ai/AiNewChatSchema";
export default defineEventHandler(async event => {
const ctx = await getRequestContext(event, 'pid');
const { project_id } = ctx;
const chats = await AiNewChatModel.find({ project_id, deleted: false }, { _id: 1, title: 1, created_at: 1, updated_at: 1, status: 1 });
return chats;
});

View File

@@ -1,61 +0,0 @@
import { sendMessageOnChat, updateChatStatus } from "~/server/services/AiService";
import { getAiChatRemainings } from "./chats_remaining";
import { ProjectLimitModel } from "@schema/project/ProjectsLimits";
export default defineEventHandler(async event => {
const data = await getRequestData(event, [], ['AI']);
if (!data) return;
const { pid } = data;
const { text, chat_id, timeOffset } = await readBody(event);
if (!text) return setResponseStatus(event, 400, 'text parameter missing');
const chatsRemaining = await getAiChatRemainings(pid);
if (chatsRemaining <= 0) return setResponseStatus(event, 400, 'CHAT_LIMIT_REACHED');
await ProjectLimitModel.updateOne({ project_id: pid }, { $inc: { ai_messages: 1 } });
const currentStatus: string[] = [];
let responseSent = false;
let targetChatId = '';
await sendMessageOnChat(text, pid, timeOffset, chat_id, {
onChatId: async chat_id => {
if (!responseSent) {
event.node.res.setHeader('Content-Type', 'application/json');
event.node.res.end(JSON.stringify({ chat_id }));
targetChatId = chat_id;
responseSent = true;
}
},
onDelta: async text => {
currentStatus.push(text);
await updateChatStatus(targetChatId, currentStatus.join(''), false);
},
onFunctionName: async name => {
currentStatus.push('[data:FunctionName]');
await updateChatStatus(targetChatId, currentStatus.join(''), false);
},
onFunctionCall: async name => {
currentStatus.push('[data:FunctionCall]');
await updateChatStatus(targetChatId, currentStatus.join(''), false);
},
onFunctionResult: async (name, result) => {
currentStatus.push('[data:FunctionResult]');
await updateChatStatus(targetChatId, currentStatus.join(''), false);
},
onFinish: async calls => {
// currentStatus.push('[data:FunctionFinish]');
// await updateChatStatus(targetChatId, currentStatus.join(''), false);
}
});
await updateChatStatus(targetChatId, '', true);
});