Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions backend/core-api/src/connectionResolvers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,17 @@ import {
IExecutionModel,
loadClass as loadExecutionClass,
} from './modules/automations/db/models/Executions';
import { IRagInteractionDocument } from './modules/aiassistant/db/definitions/ragInteractions';
import { IRagInteractionModel } from './modules/aiassistant/db/models/RagInteractions';
import { loadRagInteractionClass } from './modules/aiassistant/db/models/loadInteractionClass';
import { IGeneralSettingsModel } from './modules/aiassistant/db/definitions/generalSettings';
import { IGeneralSettingsDocument } from './modules/aiassistant/db/definitions/generalSettings';
import { loadGeneralSettingsClass } from './modules/aiassistant/db/models/loadGeneralSettingsClass';
import { GeneralSettingsSchema } from './modules/aiassistant/db/models/GeneralSettings';
import { ISystemPromptDocument } from '~/modules/aiassistant/db/definitions/systemPrompt';
import { ISystemPromptModel } from '~/modules/aiassistant/db/definitions/systemPrompt';

import { SystemPromptSchema } from '~/modules/aiassistant/db/models/SystemPrompt';

export interface IModels {
Brands: IBrandModel;
Expand Down Expand Up @@ -190,6 +201,9 @@ export interface IModels {
Logs: ILogModel;
Notifications: Model<INotificationDocument>;
EmailDeliveries: Model<IEmailDeliveryDocument>;
RagInteractions: IRagInteractionModel;
GeneralSettings: IGeneralSettingsModel;
SystemPrompt: ISystemPromptModel;
}

export interface IContext extends IMainContext {
Expand Down Expand Up @@ -354,6 +368,23 @@ export const loadClasses = (
Model<IEmailDeliveryDocument>
>('email_deliveries', emailDeliverySchema);

models.RagInteractions = db.model<IRagInteractionDocument, IRagInteractionModel>(
'rag_interactions',
loadRagInteractionClass(models)
);


models.GeneralSettings = db.model<IGeneralSettingsDocument, IGeneralSettingsModel>(
'general_settings',
GeneralSettingsSchema
);

models.SystemPrompt = db.model<ISystemPromptDocument, ISystemPromptModel>(
'system_prompt',
SystemPromptSchema
);


const db_name = db.name;

const logDb = db.useDb(`${db_name}_logs`);
Expand Down
3 changes: 3 additions & 0 deletions backend/core-api/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { generateModels } from './connectionResolvers';
import meta from './meta';
import './meta/automations';
import './segments';
import AIassistant from './modules/aiassistant';
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Fix the import path casing to match the filesystem.

The pipeline failure indicates a case sensitivity issue where the import path doesn't match the actual file's casing. The error shows both aiassistant and AIassistant paths exist, which will cause problems on case-sensitive filesystems.

Verify the correct directory name and update the import accordingly:

#!/bin/bash
# Check which directory actually exists and what casing is used
fd -t d -i aiassistant backend/core-api/src/modules/

# Check all imports of this module to see the pattern
rg -n "from.*modules.*aiassistant" backend/core-api/src/
🤖 Prompt for AI Agents
In backend/core-api/src/main.ts around line 24, the import path casing for the
modules folder is incorrect (importing './modules/aiassistant') and causes
failures on case-sensitive filesystems; update the import to exactly match the
directory/file name on disk (e.g., change to './modules/AIassistant' if that is
the actual casing), then search the codebase for other imports of this module
and normalize them to the same casing so all imports match the filesystem.


const { DOMAIN, CLIENT_PORTAL_DOMAINS, ALLOWED_DOMAINS } = process.env;

Expand Down Expand Up @@ -69,6 +70,8 @@ const fileLimiter = rateLimit({
message: 'Too many requests from this IP, please try again later.',
});

AIassistant.initApp(app);

app.get('/subscriptionPlugin.js', fileLimiter, async (_req, res) => {
const apolloSubscriptionPath = path.join(
require('path').resolve(
Expand Down
38 changes: 38 additions & 0 deletions backend/core-api/src/meta/permission.ts
Original file line number Diff line number Diff line change
Expand Up @@ -546,4 +546,42 @@ export const moduleObjects = {
},
],
},

aiassistant: {
name: 'aiassistant',
description: 'AI Assistant',
actions: [
{
name: 'aiAssistantAll',
description: 'All',
use: [
'showAiAssistant',
'manageAiAssistant',
'ragUploadFile',
'ragAskQuestion',
'viewRagInteractions'
],
},
{
name: 'showAiAssistant',
description: 'Show AI Assistant',
},
{
name: 'manageAiAssistant',
description: 'Manage AI Assistant',
},
{
name: 'ragUploadFile',
description: 'Upload files to RAG',
},
{
name: 'ragAskQuestion',
description: 'Ask questions to RAG',
},
{
name: 'viewRagInteractions',
description: 'View RAG interactions',
},
],
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { Document, Model } from 'mongoose';


export interface IGeneralSettings {
assistantName: string;
conversationStarter: string;
description: string;
promptSuggestions: string[];
updatedAt?: Date;
}


export interface IGeneralSettingsDocument extends IGeneralSettings, Document {
userId: string;
createdAt: Date;
updatedAt: Date;
}


export interface IGeneralSettingsModel extends Model<IGeneralSettingsDocument> {
getSettings(): Promise<IGeneralSettingsDocument | null>;
updateSettings(doc: Partial<IGeneralSettings>): Promise<IGeneralSettingsDocument>;
}


export const generalSettingsFields = {
assistantName: { type: String, default: '' },
conversationStarter: { type: String, default: '' },
description: { type: String, default: '' },
promptSuggestions: { type: [String], default: [] },
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { Document } from 'mongoose';

export interface IRagInteraction {
question: string;
answer: string;
sourceDocuments?: string[];
userId: string;
orgId: string;
createdAt: Date;
modelUsed?: string;
responseTime?: number;
tokensUsed?: number;
confidenceScore?: number;
status: 'success' | 'error' | 'pending';
errorMessage?: string;
}

export interface IRagInteractionDocument extends IRagInteraction, Document {}

// Export the fields as a string
export const ragInteractionFields = `
question: String
answer: String
sourceDocuments: [String]
userId: String
orgId: String
createdAt: Date
modelUsed: String
responseTime: Float
tokensUsed: Float
confidenceScore: Float
status: String
errorMessage: String
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { Document, Model } from "mongoose";

export interface ISystemPrompt {
prompt: string;
updatedAt?: Date;
}

export interface ISystemPromptDocument extends ISystemPrompt, Document {
userId: string;
createdAt: Date;
updatedAt: Date;
}

export interface ISystemPromptModel extends Model<ISystemPromptDocument> {
getPrompt(): Promise<ISystemPromptDocument | null>;
updatePrompt(prompt: string): Promise<ISystemPromptDocument>;
}

export const systemPromptFields = {
userId: { type: String, required: true },
prompt: { type: String, default: "" },
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Schema, model, models, Model } from "mongoose";
import {
IGeneralSettingsDocument,
IGeneralSettingsModel,
generalSettingsFields,
} from "~/modules/aiassistant/db/definitions/generalSettings";

export const GeneralSettingsSchema = new Schema<IGeneralSettingsDocument>(
generalSettingsFields,
{
timestamps: true,
collection: "general_settings",
}
);

const MODEL_NAME = "GeneralSettings";

export const GeneralSettings =
(models[MODEL_NAME] as IGeneralSettingsModel) ||
model<IGeneralSettingsDocument, IGeneralSettingsModel>(
MODEL_NAME,
GeneralSettingsSchema
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { Schema, model, models, Document, Model } from 'mongoose';
import { field, stringField, numberField, dateField } from '../../utils/schemaField';
import { IRagInteraction } from '../definitions/ragInteractions';

export interface IRagInteractionDocument extends IRagInteraction, Document {}

export interface IRagInteractionModel extends Model<IRagInteractionDocument> {
getRagInteraction(_id: string): Promise<IRagInteractionDocument>;
}

export const ragInteractionSchema = new Schema({
question: stringField({ label: 'Question' }),
answer: stringField({ label: 'Answer' }),
sourceDocuments: field({
type: [String],
label: 'Source Documents',
optional: true
}),
userId: stringField({ label: 'User ID' }),
orgId: stringField({ label: 'Organization ID' }),
createdAt: dateField({
default: Date.now,
label: 'Created at',
immutable: true
}),
modelUsed: stringField({
label: 'Model Used',
optional: true
}),
responseTime: numberField({
label: 'Response Time (ms)',
optional: true,
min: 0
}),
tokensUsed: numberField({
label: 'Tokens Used',
optional: true,
min: 0
}),
confidenceScore: numberField({
label: 'Confidence Score',
optional: true,
min: 0,
max: 1
}),
status: stringField({
label: 'Status',
enum: ['success', 'error', 'pending'],
default: 'success'
}),
errorMessage: stringField({
label: 'Error Message',
optional: true
})
}, {
timestamps: true,
collection: 'rag_interactions'
});

// Add indexes for better query performance
ragInteractionSchema.index({ userId: 1, createdAt: -1 });
ragInteractionSchema.index({ orgId: 1 });
ragInteractionSchema.index({ status: 1 });

const MODEL_NAME = 'RagInteractions';

export const RagInteractions =
(models[MODEL_NAME] as IRagInteractionModel) ||
model<IRagInteractionDocument, IRagInteractionModel>(MODEL_NAME, ragInteractionSchema);
39 changes: 39 additions & 0 deletions backend/core-api/src/modules/AIassistant/db/models/SystemPrompt.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { Schema, model, Model } from "mongoose";
import {
ISystemPromptDocument,
ISystemPromptModel,
systemPromptFields,
} from "../definitions/systemPrompt";

export const SystemPromptSchema = new Schema<ISystemPromptDocument>(
systemPromptFields,
{
timestamps: true,
collection: 'system_prompts'
}
);

SystemPromptSchema.statics.getPrompt = function () {
return this.findOne().exec();
};

SystemPromptSchema.statics.updatePrompt = async function (prompt: string) {
const updated = await this.findOneAndUpdate(
{},
{
prompt,
updatedAt: new Date()
},
{
new: true,
upsert: true
}
).exec();

return updated;
};

export const SystemPromptModel = model<ISystemPromptDocument, ISystemPromptModel>(
"system_prompt",
SystemPromptSchema
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { IModels } from '~/connectionResolvers';
import { GeneralSettingsModel } from '~/modules/aiassistant/db/models/GeneralSettings';
import { IGeneralSettingsDocument } from '~/modules/aiassistant/db/definitions/generalSettings';


export const loadGeneralSettingsClass = (models: IModels) => {
class GeneralSettings {
// Example static method
public static async getSettings(): Promise<IGeneralSettingsDocument | null> {
return models.GeneralSettings.findOne({});
}


// You can add more static methods here
}


// Attach class methods to the existing model's schema
GeneralSettingsModel.schema.loadClass(GeneralSettings);


return GeneralSettingsModel;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { IModels } from '~/connectionResolvers';
import { ragInteractionSchema } from './RagInteractions';
import { IRagInteractionDocument, IRagInteraction } from '../definitions/ragInteractions';

export const loadRagInteractionClass = (models: IModels) => {
class RagInteraction {
public static async getRagInteraction(_id: string) {
const ragInteraction = await models.RagInteractions.findOne({ _id });

if (!ragInteraction) {
throw new Error('RagInteraction not found');
}

return ragInteraction;
}
}

ragInteractionSchema.loadClass(RagInteraction);
return ragInteractionSchema;
};
Loading
Loading