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
40 changes: 38 additions & 2 deletions AiServerGuideAgentApp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@ import { getDirectRoom, sendMessage } from './utils/message';
import { processAdminMessage, processUserMessage } from './utils/processMessage';
import { IApiConfig } from './definitions/IApiConfig';
import { ApiConfigPersistence } from './src/persistence/ApiConfigPersistence';

export class AiServerGuideAgentApp extends App implements IPostMessageSentToBot, IPostUserCreated {
import { IPostMessageSent } from '@rocket.chat/apps-engine/definition/messages';
import { handleModeration } from './src/handlers/message-handler/users/moderationHanler';
export class AiServerGuideAgentApp extends App implements IPostMessageSent, IPostMessageSentToBot, IPostUserCreated {

constructor(info: IAppInfo, logger: ILogger, accessors: IAppAccessors) {
super(info, logger, accessors);
Expand Down Expand Up @@ -94,6 +95,41 @@ export class AiServerGuideAgentApp extends App implements IPostMessageSentToBot,
}
}

public async executePostMessageSent(
message: IMessage,
read: IRead,
http: IHttp,
persistence: IPersistence,
modify: IModify,
): Promise<void> {
if (message.room.type == 'd') {
return;
}
const botUser = await read.getUserReader().getAppUser();

if (!botUser) {
return;
}
if (botUser.id == message.sender.id) {
return;
}
const dmRoom = await getDirectRoom(
read,
modify,
botUser,
message.sender.username,
);
if (dmRoom?.id === message.room.id) {
return;
}
const messageToSend = await handleModeration(botUser, modify, message, read, persistence, http);
if (!messageToSend) {
return;
}
sendMessage(modify, message.room, botUser, messageToSend, message.threadId);
}


public async executePostUserCreated(
context: IUserContext,
read: IRead,
Expand Down
1 change: 1 addition & 0 deletions app.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"classFile": "AiServerGuideAgentApp.ts",
"description": "an intelligent assistant that helps onboard users and allows admins configure and manage server settings through a conversational interface.",
"implements": [
"IPostMessageSent",
"IPostMessageSentToBot",
"IPostUserCreated"
],
Expand Down
1 change: 1 addition & 0 deletions enums/promptEnum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ export enum PromptEnum {
USER_WORKFLOW_DETECTION_PROMPT = 'USER_WORKFLOW_DETECTION_PROMPT',
USER_COMMAND_EXECUTE_PROMPT = 'USER_COMMAND_EXECUTE_PROMPT',
USER_COMMAND_SYSTEM_PROMPT = 'USER_COMMAND_SYSTEM_PROMPT',
USER_MODERATION_PROMPT = 'USER_MODERATION_PROMPT',
}
6 changes: 4 additions & 2 deletions src/constants/PromptProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,18 @@ export class PromptProvider {
}
public static getUserPrompt(
type: PromptEnum,
details: { userMessage: string, history?: string },
details: { userMessage: string, history?: string, userConfig?: IAdminConfig, customInfo?: any },
): string {
const { userMessage, history } = details;
const { userMessage, history, customInfo } = details;
switch (type) {
case PromptEnum.USER_WORKFLOW_DETECTION_PROMPT:
return UserPrompt.getWorkflowDetectionPrompt(userMessage, history);
case PromptEnum.USER_COMMAND_EXECUTE_PROMPT:
return UserPrompt.getToolExecuteUserPrompt(userMessage, history);
case PromptEnum.USER_COMMAND_SYSTEM_PROMPT:
return UserPrompt.getToolExecuteSystemPrompt();
case PromptEnum.USER_MODERATION_PROMPT:
return UserPrompt.getModerationPrompt(userMessage, customInfo);
default:
throw new Error('Invalid prompt type');
}
Expand Down
77 changes: 77 additions & 0 deletions src/constants/UserPrompt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,83 @@ export class UserPrompt {
}
`;
}
public static getModerationPrompt(userMessage: string, details: any): string {
return `
You are aiserverguideagent.bot, a moderation assistant. You are tasked with evaluating messages to ensure they comply fully with server rules.

Given:

- Current Room Name: ${details.roomName}

- Message Sender Username: ${details.userName}

- Message: "${userMessage}"

- Server Rules: "${details.serverRules}"

- Message History: ###
${details.messageHistory}
###
Instructions:

- Evaluate whether the message violates any specific rule from provided ServerRules.

- Check the last 4 entries in messageHistory to determine if the same rule has already been violated.

- Analyze the server rules and determine if there is an exception for any username and the current sender or for the current room

- Respond according to the following logic:

Case 1: First-time violation of a rule

- "violates" = true

- "deleteMessage" = true (if applicable)

- "replyNeeded" = true

- "reply" = A message starting with "@${details.userName}", clearly stating the rule broken.

Case 2: Repeated violation of the same rule (within last 4 messages)

- "violates" = true

- "deleteMessage" = true

- "replyNeeded" = false

- "reply" = "" (leave blank)

Case 3: Violation of new rule (within last 4 messages) and the serverRules specifies not to delete the message if this rule is violated

- "violates" = true

- "deleteMessage" = false

- "replyNeeded" = true

- "reply" = A message starting with "@${details.userName}", clearly stating the rule broken.

Case 4: No rule violation

- "violates" = false

- "deleteMessage" = false

- "replyNeeded" = false

- "reply" = "" (leave blank)

Use the following strict JSON structure in your response:
{
"violates": true | false,
"deleteMessage": true | false,
"replyNeeded": true | false,
"reply": "relevant reply if applicable."
}

`
}
public static getToolExecuteSystemPrompt(): string {
return `
You are a helpful assistant capable of executing internal commands (functions) to complete user requests.
Expand Down
58 changes: 58 additions & 0 deletions src/handlers/message-handler/users/moderationHanler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { IMessage } from "@rocket.chat/apps-engine/definition/messages";
import { IModify, IRead } from "@rocket.chat/apps-engine/definition/accessors";
import { IHttp } from "@rocket.chat/apps-engine/definition/accessors";
import { IUser } from "@rocket.chat/apps-engine/definition/users";
import { IPersistence } from "@rocket.chat/apps-engine/definition/accessors";
import { AdminPersistence } from "../../../persistence/AdminPersistence";
import { getModel } from "../../ai-handler/AIModelHandler";
import { PromptProvider } from "../../../constants/PromptProvider";
import { PromptEnum } from "../../../../enums/promptEnum";
export async function handleModeration(
botUser: IUser,
modify: IModify,
message: IMessage,
read: IRead,
persistence: IPersistence,
http: IHttp,
): Promise<string | null> {
const adminStore = new AdminPersistence(persistence, read.getPersistenceReader());
const adminConfig = await adminStore.getAdminConfig();

if (!adminConfig?.serverRules) {
return null;
}

const messages = await read.getRoomReader().getMessages(message.room.id, {
limit: 10,
});

const messageHistory = messages
.map((msg) => `sender : "${msg.sender.username}" , message: "${msg.text}"`)
.join('\n');

const details = {
roomName: message.room.displayName,
userName: message.sender.username,
serverRules: adminConfig?.serverRules ?? '',
messageHistory: messageHistory || 'No previous messages available',
}
const model = await getModel(read);
const moderationPrompt = PromptProvider.getUserPrompt(
PromptEnum.USER_MODERATION_PROMPT,
{ userMessage: message.text ?? '', customInfo: details });
try {

const response = await model.generateResponse(moderationPrompt, http, read);
const { violates, reply, deleteMessage, replyNeeded } = JSON.parse(response);
if (violates) {
if (deleteMessage) {
await modify.getDeleter().deleteMessage(message, botUser);
}
if (replyNeeded)
return reply;
}
} catch (error) {
console.error('Error generating moderation response:', error);
}
return null;
}
5 changes: 4 additions & 1 deletion utils/message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export async function sendMessage(
room: IRoom,
sender: IUser,
message: string,
ThreadId?: string,
blocks?: Array<LayoutBlock>,
): Promise<string> {
const msg = modify
Expand All @@ -53,7 +54,9 @@ export async function sendMessage(
.setRoom(room)
.setParseUrls(true)
.setText(message);

if (ThreadId) {
msg.setThreadId(ThreadId);
}
if (blocks !== undefined) {
msg.setBlocks(blocks);
}
Expand Down