mirror of
https://github.com/Litlyx/litlyx
synced 2025-12-10 07:48:37 +01:00
add ai plugins
This commit is contained in:
@@ -3,12 +3,13 @@ import type OpenAI from 'openai'
|
||||
|
||||
|
||||
export type AIPlugin_TTool<T extends string> = (OpenAI.Chat.Completions.ChatCompletionTool & { function: { name: T } });
|
||||
export type AIPlugin_TFunction<T extends string> = (...args: any[]) => any;
|
||||
|
||||
export type AIPlugin_TFunction = (...args: any[]) => any;
|
||||
|
||||
type AIPlugin_Constructor<Items extends string[]> = {
|
||||
[Key in Items[number]]: {
|
||||
tool: AIPlugin_TTool<Key>,
|
||||
handler: AIPlugin_TFunction<Key>
|
||||
handler: AIPlugin_TFunction
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
127
dashboard/server/ai/functions/AI_Billing.ts
Normal file
127
dashboard/server/ai/functions/AI_Billing.ts
Normal file
@@ -0,0 +1,127 @@
|
||||
|
||||
import { ProjectLimitModel } from "@schema/project/ProjectsLimits";
|
||||
import { AIPlugin } from "../Plugin";
|
||||
import { MAX_LOG_LIMIT_PERCENT } from "@data/broker/Limits";
|
||||
import { ProjectModel } from "@schema/project/ProjectSchema";
|
||||
import StripeService from "~/server/services/StripeService";
|
||||
import { InvoiceData } from "~/server/api/pay/invoices";
|
||||
|
||||
export class AiBilling extends AIPlugin<[
|
||||
'getBillingInfo',
|
||||
'getLimits',
|
||||
'getInvoices'
|
||||
]> {
|
||||
|
||||
constructor() {
|
||||
super({
|
||||
|
||||
'getInvoices': {
|
||||
handler: async (data: { project_id: string }) => {
|
||||
|
||||
const project = await ProjectModel.findOne({ _id: data.project_id });
|
||||
if (!project) return { error: 'Project not found' };
|
||||
const invoices = await StripeService.getInvoices(project.customer_id);
|
||||
if (!invoices) return [];
|
||||
|
||||
return invoices?.data.map(e => {
|
||||
const result: InvoiceData = {
|
||||
link: e.invoice_pdf || '',
|
||||
id: e.number || '',
|
||||
date: e.created * 1000,
|
||||
status: e.status || 'NO_STATUS',
|
||||
cost: e.amount_due
|
||||
}
|
||||
return result;
|
||||
});
|
||||
},
|
||||
tool: {
|
||||
type: 'function',
|
||||
function: {
|
||||
name: 'getInvoices',
|
||||
description: 'Gets the invoices of the user project',
|
||||
parameters: {}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
'getBillingInfo': {
|
||||
handler: async (data: { project_id: string }) => {
|
||||
|
||||
const project = await ProjectModel.findOne({ _id: data.project_id });
|
||||
if (!project) return { error: 'Project not found' };
|
||||
|
||||
if (project.subscription_id === 'onetime') {
|
||||
|
||||
const projectLimits = await ProjectLimitModel.findOne({ project_id: data.project_id });
|
||||
if (!projectLimits) return { error: 'Limits not found' }
|
||||
|
||||
const result = {
|
||||
premium: project.premium,
|
||||
premium_type: project.premium_type,
|
||||
billing_start_at: projectLimits.billing_start_at,
|
||||
billing_expire_at: projectLimits.billing_expire_at,
|
||||
limit: projectLimits.limit,
|
||||
count: projectLimits.events + projectLimits.visits,
|
||||
subscription_status: StripeService.isDisabled() ? 'Disabled mode' : ('One time payment')
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
const subscription = await StripeService.getSubscription(project.subscription_id);
|
||||
|
||||
const projectLimits = await ProjectLimitModel.findOne({ project_id: data.project_id });
|
||||
if (!projectLimits) return { error: 'Limits not found' }
|
||||
|
||||
|
||||
const result = {
|
||||
premium: project.premium,
|
||||
premium_type: project.premium_type,
|
||||
billing_start_at: projectLimits.billing_start_at,
|
||||
billing_expire_at: projectLimits.billing_expire_at,
|
||||
limit: projectLimits.limit,
|
||||
count: projectLimits.events + projectLimits.visits,
|
||||
subscription_status: StripeService.isDisabled() ? 'Disabled mode' : (subscription?.status ?? '?')
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
tool: {
|
||||
type: 'function',
|
||||
function: {
|
||||
name: 'getBillingInfo',
|
||||
description: 'Gets the informations about the billing of the user project, limits, count, subscription_status, is premium, premium type, billing start at, billing expire at',
|
||||
parameters: {}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
'getLimits': {
|
||||
handler: async (data: { project_id: string }) => {
|
||||
const projectLimits = await ProjectLimitModel.findOne({ project_id: data.project_id });
|
||||
if (!projectLimits) return { error: 'Project limits not found' };
|
||||
const TOTAL_COUNT = projectLimits.events + projectLimits.visits;
|
||||
const COUNT_LIMIT = projectLimits.limit;
|
||||
return {
|
||||
total: TOTAL_COUNT,
|
||||
limit: COUNT_LIMIT,
|
||||
limited: TOTAL_COUNT > COUNT_LIMIT * MAX_LOG_LIMIT_PERCENT,
|
||||
percent: Math.round(100 / COUNT_LIMIT * TOTAL_COUNT)
|
||||
}
|
||||
},
|
||||
tool: {
|
||||
type: 'function',
|
||||
function: {
|
||||
name: 'getLimits',
|
||||
description: 'Gets the informations about the limits of the user project',
|
||||
parameters: {}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export const AiBillingInstance = new AiBilling();
|
||||
78
dashboard/server/ai/functions/AI_Snapshots.ts
Normal file
78
dashboard/server/ai/functions/AI_Snapshots.ts
Normal file
@@ -0,0 +1,78 @@
|
||||
|
||||
import { AIPlugin } from "../Plugin";
|
||||
import { ProjectModel } from "@schema/project/ProjectSchema";
|
||||
import { ProjectSnapshotModel } from "@schema/project/ProjectSnapshot";
|
||||
|
||||
export class AiSnapshot extends AIPlugin<[
|
||||
'getSnapshots',
|
||||
'createSnapshot',
|
||||
]> {
|
||||
|
||||
constructor() {
|
||||
super({
|
||||
|
||||
'getSnapshots': {
|
||||
handler: async (data: { project_id: string }) => {
|
||||
const snapshots = await ProjectSnapshotModel.find({ project_id: data.project_id });
|
||||
return snapshots.map(e => e.toJSON());
|
||||
},
|
||||
tool: {
|
||||
type: 'function',
|
||||
function: {
|
||||
name: 'getSnapshots',
|
||||
description: 'Gets the snapshots list',
|
||||
parameters: {}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
'createSnapshot': {
|
||||
handler: async (data: { project_id: string, from: string, to: string, color: string, name: string }) => {
|
||||
|
||||
if (!data.name) return { error: 'SnapshotName too short' }
|
||||
if (data.name.length == 0) return { error: 'SnapshotName too short' }
|
||||
|
||||
if (!data.from) return { error: 'from is required' }
|
||||
if (!data.to) return { error: 'to is required' }
|
||||
if (!data.color) return { error: 'color is required' }
|
||||
|
||||
const project = await ProjectModel.findById(data.project_id);
|
||||
if (!project) return { error: 'Project not found' }
|
||||
|
||||
|
||||
const newSnapshot = await ProjectSnapshotModel.create({
|
||||
name: data.name,
|
||||
from: new Date(data.from),
|
||||
to: new Date(data.to),
|
||||
color: data.color,
|
||||
project_id: data.project_id
|
||||
});
|
||||
|
||||
return newSnapshot.id;
|
||||
|
||||
|
||||
},
|
||||
tool: {
|
||||
type: 'function',
|
||||
function: {
|
||||
name: 'createSnapshot',
|
||||
description: 'Create a snapshot',
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
from: { type: 'string', description: 'ISO string of start date' },
|
||||
to: { type: 'string', description: 'ISO string of end date' },
|
||||
color: { type: 'string', description: 'Color of the snapshot in HEX' },
|
||||
name: { type: 'string', description: 'Name of the snapshot' }
|
||||
},
|
||||
required: ['from', 'to', 'color', 'name']
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export const AiSnapshotInstance = new AiSnapshot();
|
||||
@@ -1,7 +1,6 @@
|
||||
import { ProjectModel } from "@schema/project/ProjectSchema";
|
||||
import { ProjectSnapshotModel } from "@schema/project/ProjectSnapshot";
|
||||
|
||||
|
||||
export default defineEventHandler(async event => {
|
||||
|
||||
const data = await getRequestData(event, { requireSchema: false, allowGuests: true, requireRange: false });
|
||||
|
||||
@@ -7,6 +7,8 @@ import { ProjectLimitModel } from '@schema/project/ProjectsLimits';
|
||||
import { AiEventsInstance } from '../ai/functions/AI_Events';
|
||||
import { AiVisitsInstance } from '../ai/functions/AI_Visits';
|
||||
import { AiSessionsInstance } from '../ai/functions/AI_Sessions';
|
||||
import { AiBillingInstance } from '../ai/functions/AI_Billing';
|
||||
import { AiSnapshotInstance } from '../ai/functions/AI_Snapshots';
|
||||
import { AiComposableChartInstance } from '../ai/functions/AI_ComposableChart';
|
||||
|
||||
const { AI_KEY, AI_ORG, AI_PROJECT } = useRuntimeConfig();
|
||||
@@ -19,6 +21,8 @@ const tools: OpenAI.Chat.Completions.ChatCompletionTool[] = [
|
||||
...AiVisitsInstance.getTools(),
|
||||
...AiEventsInstance.getTools(),
|
||||
...AiSessionsInstance.getTools(),
|
||||
...AiBillingInstance.getTools(),
|
||||
...AiSnapshotInstance.getTools(),
|
||||
...AiComposableChartInstance.getTools(),
|
||||
]
|
||||
|
||||
@@ -27,6 +31,8 @@ const functions: any = {
|
||||
...AiVisitsInstance.getHandlers(),
|
||||
...AiEventsInstance.getHandlers(),
|
||||
...AiSessionsInstance.getHandlers(),
|
||||
...AiBillingInstance.getHandlers(),
|
||||
...AiSnapshotInstance.getHandlers(),
|
||||
...AiComposableChartInstance.getHandlers()
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user