First working prototype, but it has alzheimer's

This commit is contained in:
2025-07-21 15:55:45 -04:00
parent 5405e106c8
commit 5f3ff235f0
8 changed files with 166 additions and 1 deletions

View File

@@ -1,2 +1,2 @@
# Aisha
Don't mind my shitty code.

21
package-lock.json generated
View File

@@ -10,9 +10,15 @@
"license": "ISC",
"dependencies": {
"@google/genai": "^1.10.0",
"@types/dateformat": "^5.0.3",
"axios": "^1.10.0",
"dateformat": "^5.0.3",
"discord-api-types": "^0.38.16",
"discord.js": "^14.21.0",
"dotenv": "^17.2.0"
},
"devDependencies": {
"@types/node": "^24.0.15"
}
},
"node_modules/@discordjs/builders": {
@@ -196,6 +202,12 @@
"npm": ">=7.0.0"
}
},
"node_modules/@types/dateformat": {
"version": "5.0.3",
"resolved": "https://registry.npmjs.org/@types/dateformat/-/dateformat-5.0.3.tgz",
"integrity": "sha512-hvskLa9ObgUwJe0rtfkyBbU+VIK8Ia3BACsxRsp4CPnyPBAOyIHbqImfBGFfaVVxn82wGx5SD8Twll6jMc/BaQ==",
"license": "MIT"
},
"node_modules/@types/node": {
"version": "24.0.15",
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.0.15.tgz",
@@ -310,6 +322,15 @@
"node": ">= 0.8"
}
},
"node_modules/dateformat": {
"version": "5.0.3",
"resolved": "https://registry.npmjs.org/dateformat/-/dateformat-5.0.3.tgz",
"integrity": "sha512-Kvr6HmPXUMerlLcLF+Pwq3K7apHpYmGDVqrxcDasBg86UcKeTSNWbEzU8bwdXnxnR44FtMhJAxI4Bov6Y/KUfA==",
"license": "MIT",
"engines": {
"node": ">=12.20"
}
},
"node_modules/debug": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",

View File

@@ -3,6 +3,7 @@
"version": "0.0.0",
"description": "ai bot thingy",
"main": "app.ts",
"type": "module",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
@@ -10,8 +11,14 @@
"license": "ISC",
"dependencies": {
"@google/genai": "^1.10.0",
"@types/dateformat": "^5.0.3",
"axios": "^1.10.0",
"dateformat": "^5.0.3",
"discord-api-types": "^0.38.16",
"discord.js": "^14.21.0",
"dotenv": "^17.2.0"
},
"devDependencies": {
"@types/node": "^24.0.15"
}
}

View File

@@ -0,0 +1,14 @@
import * as Discord from "discord.js";
import dotenv from "dotenv";
import axios from "axios";
import { GoogleGenAI } from "@google/genai";
import { createShardManager } from "./utils.ts";
import path from "path";
dotenv.config();
const shardManager = createShardManager("src/shard.ts", process.env.BOT_TOKEN, "auto", false);
shardManager.on("shardCreate", shard => console.log(`[ShardManager] Launched shard ${shard.id}`));
shardManager.spawn().catch(console.error);

98
src/shard.ts Normal file
View File

@@ -0,0 +1,98 @@
import * as Discord from "discord.js";
import * as Utils from "@discordjs/util"
import * as Formatters from "@discordjs/formatters"
import * as Builders from "@discordjs/builders"
import * as Types from "discord-api-types/v10"
import * as fs from "node:fs"
import dateFormat, { masks } from "dateformat";
import { GoogleGenAI } from "@google/genai";
import EventEmitter from "events";
const Client:Discord.Client = new Discord.Client({
intents: ["MessageContent", "Guilds", "GuildMessages", "GuildMembers","GuildMessageReactions","GuildPresences","GuildVoiceStates","GuildIntegrations","GuildEmojisAndStickers","GuildInvites","GuildExpressions","GuildScheduledEvents","GuildMessageTyping","GuildMessagePolls"],
ws: { properties: { $browser: "Discord iOS" }},
presence: {status: "online", activities:
[{
name: "something",
state: "who am i?",
type: Discord.ActivityType.Custom
}]
},
shards: "auto",
allowedMentions: {parse: ["users", "roles"], repliedUser: true},
})
const ai = new GoogleGenAI({
apiKey: process.env.GEMINI_KEY,
project: process.env.GCP_PROJECT_ID||undefined,
});
const shardCacheMap = new Map<string,string|undefined>();
function logPrefix():string {return `[${dateFormat(new Date(), masks.isoTime)}] [Shard-${Client.shard?.ids[0]}]: `}
Client.on("ready", async () => {
console.log(logPrefix()+"Client is ready.")
//await createCaches();
})
function sevenDays():string {
const nextWeek = new Date();
nextWeek.setDate(nextWeek.getDate() + 7);
return nextWeek.toISOString();
}
async function createCaches() {
console.log(logPrefix()+"Creating caches...")
const guildList:string[] = Client.guilds.cache.map(guild => guild.id)
var cacheList = new Set<string>();
const caches = await ai.caches.list({config: {pageSize: 100}})
for await (const cache of caches) {
if (cache.displayName) {
cacheList.add(cache.displayName);
shardCacheMap.set(cache.displayName, cache.name);
}
}
for (const guildId of guildList) {
if (!cacheList.has(guildId)) {
console.log(logPrefix()+`Guild ${guildId} does not have a cache, creating one now.`)
const newCache = await ai.caches.create({
model: "gemini-2.5-flash",
config: {
displayName: guildId,
expireTime: sevenDays(), // im not gonna bother trying to fit all this in one value
systemInstruction: fs.readFileSync("systemprompt.txt").toString().replace("<GUILD>",Client.guilds.cache.get(guildId)?.name||"undefined"),
}
})
shardCacheMap.set(guildId, newCache.name);
}
}
}
function embedMessageInfo(message:Discord.Message) {
return `Message Author Username: ${message.author.username}
Message Author Name: ${message.author.displayName}
Message Content: ${message.cleanContent}`
}
Client.on("messageCreate", async message => {
if (message.content.includes("<@1396892425548730601>")) {
const genContent = await ai.models.generateContent({
model: "gemini-2.5-flash",
contents: embedMessageInfo(message),
config: {
//cachedContent: shardCacheMap.get(message.guildId || ""),
systemInstruction: fs.readFileSync("systemprompt.txt").toString().replace("<GUILD>",Client.guilds.cache.get(message.guildId||"")?.name||"undefined"),
}
})
const resContent:string = genContent.text?.toString()||"‎ ";
message.reply(resContent);
}
})
Client.login(process.env.TOKEN);

13
src/utils.ts Normal file
View File

@@ -0,0 +1,13 @@
import * as Discord from "discord.js";
function createShardManager(file:string, token:string|undefined, shards:number|"auto", silent?:boolean):Discord.ShardingManager {
const manager = new Discord.ShardingManager(file,{
token: token,
totalShards: shards,
mode: "process",
silent: silent||false
})
return manager;
}
export {createShardManager};

1
systemprompt.txt Normal file
View File

@@ -0,0 +1 @@
you are aisha, a human user on the messaging platform Discord. your job is to act like a human user of this platform and talk with people that interact with you. The server you are in is called <GUILD>. Users can talk to you by "mentioning" you with the mention sign @Aisha.

11
tsconfig.json Normal file
View File

@@ -0,0 +1,11 @@
{
"compilerOptions": {
"module": "commonjs",
"esModuleInterop": true,
"target": "es6",
"moduleResolution": "node",
"sourceMap": true,
"outDir": "dist"
},
"lib": ["es2015"]
}