All files messageController.ts

87.8% Statements 36/41
80% Branches 8/10
75% Functions 3/4
86.84% Lines 33/38

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99                      1x                       1x 6x 6x 6x   6x       5x 5x 5x                     5x   4x   1x 1x       1x 4x 4x 4x   4x       3x 3x 3x                     3x   2x   1x 1x       1x 6x 6x 6x     5x 4x   1x 1x      
import { Request, Response } from "express";
import { v4 as uuidv4 } from "uuid";
import { addItem, getItem, queryByPrefix } from "@deliverables.org/database";
 
interface IMessageLog {
    id: string; // same as userId
    userId: string;
    history: string; // newline-separated JSON messages
    updatedAt: string;
}
 
const MAX_HISTORY_LENGTH = 200;
 
function trimHistory(history: string, maxChars: number): string {
    const lines = history.split("\n");
    let trimmed = [...lines];
 
    while (trimmed.join("\n").length > maxChars && trimmed.length > 1) {
        trimmed.shift(); // remove oldest message
    }
    return trimmed.join("\n");
}
 
export const addUserMessage = async (req: Request, res: Response) => {
    try {
    const { userId } = req.params;
    const { content } = req.body;
 
    if (!content) return res.status(400).json({ message: "Message content is required." });
 
    // Store each message as a separate item under the user
    // PK: USER#<userId>, SK: MESSAGE#<timestamp>, type: 'message'
    const timestamp = Date.now();
    const messageId = uuidv4();
    const messageItem = {
        PK: `USER#${userId}`,
        SK: `MESSAGE#${timestamp}`,
        type: "message",
        messageId,
        userId,
        content,
        role: "user",
        createdAt: new Date(timestamp).toISOString(),
    };
 
    await addItem({ TableName: "MainTable", Item: messageItem });
 
    res.status(200).json({ message: "User message added.", log: messageItem });
    } catch (error) {
        console.error("Error adding user message:", error);
        res.status(500).json({ message: "Error adding user message" });
    }
};
 
export const addLLMMessage = async (req: Request, res: Response) => {
    try {
    const { userId } = req.params;
    const { content } = req.body;
 
    if (!content) return res.status(400).json({ message: "Message content is required." });
 
    // Store each LLM message as a separate item under the user
    // PK: USER#<userId>, SK: MESSAGE#<timestamp>, type: 'message'
    const timestamp = Date.now();
    const messageId = uuidv4();
    const messageItem = {
        PK: `USER#${userId}`,
        SK: `MESSAGE#${timestamp}`,
        type: "message",
        messageId,
        userId,
        content,
        role: "assistant",
        createdAt: new Date(timestamp).toISOString(),
    };
 
    await addItem({ TableName: "MainTable", Item: messageItem });
 
    res.status(200).json({ message: "LLM message added.", log: messageItem });
    } catch (error) {
        console.error("Error adding LLM message:", error);
        res.status(500).json({ message: "Error adding LLM message" });
    }
};
 
export const getChatHistory = async (req: Request, res: Response) => {
    try {
        const { userId } = req.params;
        if (!userId) return res.status(400).json({ message: "userId is required" });
 
        // Query all messages for this user
        const result = await queryByPrefix({ TableName: "MainTable", PK: `USER#${userId}`, SKPrefix: "MESSAGE#" });
        res.status(200).json({ userId, messages: result.Items || [] });
    } catch (error) {
        console.error("Error getting chat history:", error);
        res.status(500).json({ message: "Error getting chat history" });
    }
};