Fixes; Logging

This commit is contained in:
Aslan 2025-12-29 21:21:45 +01:00
parent 76e496bd38
commit 1e94df499c
8 changed files with 79 additions and 33 deletions

View file

@ -1,6 +1,6 @@
{ {
"name": "aslobot-matrix", "name": "aslobot-matrix",
"version": "1.2.0", "version": "1.2.1",
"description": "", "description": "",
"license": "ISC", "license": "ISC",
"author": "", "author": "",

View file

@ -2,8 +2,8 @@
"baseUrl": "https://", "baseUrl": "https://",
"server": "", "server": "",
"userId": "@", "userId": "@",
"authPath": "auth.json",
"storePath": "store.json", "storePath": "store.json",
"logPath": "log.log",
"auth": { "auth": {
"accessToken": "", "accessToken": "",
"deviceId": "" "deviceId": ""

View file

@ -3,6 +3,7 @@ import { config } from "./config.js";
import { state } from "./store/store.js"; import { state } from "./store/store.js";
import { type IUser, type TRole } from "./store/types.js"; import { type IUser, type TRole } from "./store/types.js";
import type { ILevel } from "./types.js"; import type { ILevel } from "./types.js";
import { appendFileSync } from "fs";
const fixUserData = (user: IUser) => { const fixUserData = (user: IUser) => {
if (!user.experience) { if (!user.experience) {
@ -25,6 +26,7 @@ const fixUserData = (user: IUser) => {
const getUserById = (userId: string): IUser => { const getUserById = (userId: string): IUser => {
const user = state.users.find((user) => user.id === userId); const user = state.users.find((user) => user.id === userId);
if (!user) { if (!user) {
log(`Tried to get a non existing user ${userId}}`);
return { return {
id: ":", id: ":",
role: "NONE", role: "NONE",
@ -110,17 +112,25 @@ const changePersonality = (
return false; return false;
} }
const name =
personalityName.charAt(0).toUpperCase() + personalityName.slice(1);
state.personality = { state.personality = {
index: personalityIndex, index: personalityIndex,
startTime: Date.now(), startTime: Date.now(),
}; };
client.setDisplayName( client.setDisplayName(name);
`AsloBot (${config.app.ai.personalities[state.personality.index]?.personalityName})`,
);
return true; return true;
}; };
const log = (logMessage: string) => {
appendFileSync(
config.logPath,
`[${new Date().toLocaleString()}] ${logMessage}`,
);
};
export { export {
fixUserData, fixUserData,
getUserById, getUserById,
@ -129,4 +139,5 @@ export {
getUserName, getUserName,
getUserFromMention, getUserFromMention,
changePersonality, changePersonality,
log,
}; };

View file

@ -4,7 +4,7 @@ import { config } from "../../config.js";
import { getTextGemini, getImageGemini } from "../../services/ai/ai.js"; import { getTextGemini, getImageGemini } from "../../services/ai/ai.js";
import { alts } from "./alts.js"; import { alts } from "./alts.js";
import type { IAIInstructions } from "./types.js"; import type { IAIInstructions } from "./types.js";
import { getUserById, getUserName } from "../../helpers.js"; import { changePersonality, getUserById, getUserName } from "../../helpers.js";
import { prices } from "./prices.js"; import { prices } from "./prices.js";
import { state } from "../../store/store.js"; import { state } from "../../store/store.js";
@ -43,24 +43,8 @@ const onAI = async (
const user = getUserById(sender); const user = getUserById(sender);
const date = Date.now();
let personality = config.app.ai.personalities[state.personality.index]; let personality = config.app.ai.personalities[state.personality.index];
if (date > state.personality.startTime + (personality?.timeout ?? 0)) {
const randomInt = Math.floor(
Math.random() * config.app.ai.personalities.length,
);
state.personality = {
index: randomInt,
startTime: date,
};
client.setDisplayName(
`AsloBot (${config.app.ai.personalities[state.personality.index]?.personalityName})`,
);
}
personality = config.app.ai.personalities[state.personality.index];
let textMod = text.replace("!ai", "").trim(); let textMod = text.replace("!ai", "").trim();
let instructions = { let instructions = {
prefferedLanguages: ["english", "slovak"], prefferedLanguages: ["english", "slovak"],
@ -96,6 +80,19 @@ const onAI = async (
user.aiCost += responseAI.tokens * prices.text; user.aiCost += responseAI.tokens * prices.text;
client.sendTextMessage(roomId, responseAI.text); client.sendTextMessage(roomId, responseAI.text);
const date = Date.now();
if (date > state.personality.startTime + (personality?.timeout ?? 0)) {
const randomInt = Math.floor(
Math.random() * config.app.ai.personalities.length,
);
const newPersonalityName =
config.app.ai.personalities[randomInt]?.personalityName;
if (newPersonalityName) {
changePersonality(client, newPersonalityName);
}
}
}; };
const onImageGen = async (text: string, roomId: string, sender: string) => { const onImageGen = async (text: string, roomId: string, sender: string) => {

View file

@ -1,6 +1,6 @@
import type { MatrixClient } from "matrix-js-sdk"; import type { MatrixClient } from "matrix-js-sdk";
import type { TRole } from "../store/types.js"; import type { TRole } from "../store/types.js";
import { getLevel, getUserById } from "../helpers.js"; import { getLevel, getUserById, log } from "../helpers.js";
import { config } from "../config.js"; import { config } from "../config.js";
import { state } from "../store/store.js"; import { state } from "../store/store.js";
@ -35,11 +35,13 @@ const onAnyMessage = (
) { ) {
user.experience += config.app.experience.gain; user.experience += config.app.experience.gain;
user.lastExperienceGainTimestamp = date; user.lastExperienceGainTimestamp = date;
log(`${user.id} gained ${config.app.experience.gain} experience`);
} }
if (date > user.lastMoneyGainTimestamp + config.app.money.timeout) { if (date > user.lastMoneyGainTimestamp + config.app.money.timeout) {
user.money += config.app.money.gain; user.money += config.app.money.gain;
user.lastMoneyGainTimestamp = date; user.lastMoneyGainTimestamp = date;
log(`${user.id} gained ${config.app.money.gain} money`);
} }
user.lastMessageTimestamp = date; user.lastMessageTimestamp = date;

View file

@ -10,7 +10,7 @@ import { registerModuleBase } from "./base/base.js";
import { registerModuleAdmin } from "./admin/admin.js"; import { registerModuleAdmin } from "./admin/admin.js";
import { registerModuleUser } from "./user/user.js"; import { registerModuleUser } from "./user/user.js";
import { registerModuleAI } from "./ai/ai.js"; import { registerModuleAI } from "./ai/ai.js";
import { checkRoles, getUserById } from "../helpers.js"; import { checkRoles, getUserById, log } from "../helpers.js";
import { onAnyMessage, onMissingRole } from "./global.js"; import { onAnyMessage, onMissingRole } from "./global.js";
import { config } from "../config.js"; import { config } from "../config.js";
@ -129,6 +129,7 @@ const registerModules = (client: MatrixClient) => {
} }
console.log(`Message from ${sender} in ${roomId}: ${body}`); console.log(`Message from ${sender} in ${roomId}: ${body}`);
log(`Message from ${sender} in ${roomId}: ${body}`);
onAnyMessage(client, body.toString(), roomId, sender); onAnyMessage(client, body.toString(), roomId, sender);

View file

@ -10,6 +10,7 @@ import { FunctionCallingConfigMode } from "@google/genai";
import { toolFunctions, tools } from "./tools.js"; import { toolFunctions, tools } from "./tools.js";
import type { FunctionResponse } from "@google/genai"; import type { FunctionResponse } from "@google/genai";
import type { Content } from "@google/genai"; import type { Content } from "@google/genai";
import { log } from "../../helpers.js";
const googleAI = new GoogleGenAI({ const googleAI = new GoogleGenAI({
apiKey: config.app.ai.api.key, apiKey: config.app.ai.api.key,
@ -22,6 +23,16 @@ const getTextGemini = async (
oldInput?: string, oldInput?: string,
inputImage?: Buffer<ArrayBuffer>, inputImage?: Buffer<ArrayBuffer>,
): Promise<AIResponseText> => { ): Promise<AIResponseText> => {
log(`AI Text Request: ${input}`);
const oldInputContent: Content = {
role: "user",
parts: [
{
text: oldInput ?? "",
},
],
};
const inputContent: Content = inputImage const inputContent: Content = inputImage
? { ? {
role: "user", role: "user",
@ -45,14 +56,6 @@ const getTextGemini = async (
}, },
], ],
}; };
const oldInputContent: Content = {
role: "user",
parts: [
{
text: oldInput ?? "",
},
],
};
const contents: Content[] = oldInput const contents: Content[] = oldInput
? [oldInputContent, inputContent] ? [oldInputContent, inputContent]
@ -91,12 +94,14 @@ const getTextGemini = async (
(func) => func.name === functionCall.name, (func) => func.name === functionCall.name,
)?.function; )?.function;
if (!func) { if (!func) {
log(`Failed to tool: ${functionCall.name}`);
return { return {
text: text, text: text,
tokens: token, tokens: token,
}; };
} }
log(`Calling tool: ${functionCall.name}...`);
const output = func(matrixData, functionCall.args); const output = func(matrixData, functionCall.args);
const functionResponse: FunctionResponse = { const functionResponse: FunctionResponse = {
id: functionCall.id ?? "", id: functionCall.id ?? "",

View file

@ -4,6 +4,7 @@ import type { AIToolFunction } from "./types.js";
import { save, state } from "../../store/store.js"; import { save, state } from "../../store/store.js";
import { EventType, RelationType } from "matrix-js-sdk"; import { EventType, RelationType } from "matrix-js-sdk";
import { changePersonality } from "../../helpers.js"; import { changePersonality } from "../../helpers.js";
import { readFileSync } from "fs";
const tools: FunctionDeclaration[] = [ const tools: FunctionDeclaration[] = [
{ {
@ -110,6 +111,16 @@ const tools: FunctionDeclaration[] = [
required: [], required: [],
}, },
}, },
{
name: "getBotLog",
description:
"Gets the recent log about the activity of this bot from a log file",
parametersJsonSchema: {
type: "object",
properties: {},
required: [],
},
},
]; ];
const toolFunctions: AIToolFunction[] = [ const toolFunctions: AIToolFunction[] = [
@ -202,7 +213,12 @@ const toolFunctions: AIToolFunction[] = [
}; };
} }
state.aiMemory.splice(index, 1); state.aiMemory = state.aiMemory.filter(
(memory) =>
memory !== args.knowledge &&
memory !== null &&
memory !== undefined,
);
return { return {
message: "success", message: "success",
@ -246,6 +262,20 @@ const toolFunctions: AIToolFunction[] = [
}; };
}, },
}, },
{
name: "getBotLog",
function: (_matrix, _args) => {
const delimeter = "\n";
const logFile = readFileSync(config.logPath);
let lines = logFile.toString().trim();
lines = lines.split(delimeter).slice(-20).join(delimeter);
return {
log: lines,
};
},
},
]; ];
export { tools, toolFunctions }; export { tools, toolFunctions };