Files

167 lines
6.3 KiB
JavaScript
Raw Permalink Normal View History

2026-08-06 17:29:37 +01:00
const fs = require('fs');
const path = require('path');
const DB_PATH = path.join(__dirname, '../Data/ai-memory.json');
function load() {
try {
const raw = fs.readFileSync(DB_PATH, 'utf8');
return JSON.parse(raw);
} catch (e) {
return {
ai_conversations: [],
ai_summaries: [],
ai_facts: [],
ai_knowledge: [],
ai_sessions: [],
};
}
}
2026-03-11 18:58:15 +00:00
2026-08-06 17:29:37 +01:00
function save(state) {
try {
fs.mkdirSync(path.dirname(DB_PATH), { recursive: true });
fs.writeFileSync(DB_PATH, JSON.stringify(state, null, 2), 'utf8');
} catch (e) {
console.error('Failed to persist ai-memory:', e);
}
}
2026-03-11 18:58:15 +00:00
2026-08-06 17:29:37 +01:00
const state = load();
2026-03-11 18:58:15 +00:00
2026-08-06 17:29:37 +01:00
function nextId(arr) {
return arr.length === 0 ? 1 : Math.max(...arr.map(a => a.id || 0)) + 1;
2026-03-11 18:58:15 +00:00
}
module.exports = {
saveUserFact({ guildId, userId, factType, factKey, factValue }) {
2026-08-06 17:29:37 +01:00
const existing = state.ai_facts.find(f => f.guild_id === (guildId || null) && f.user_id === (userId || null) && f.fact_type === factType && f.fact_key === factKey);
2026-03-11 18:58:15 +00:00
if (existing) {
2026-08-06 17:29:37 +01:00
existing.fact_value = factValue;
existing.updated_at = Date.now();
save(state);
2026-03-11 18:58:15 +00:00
return;
}
2026-08-06 17:29:37 +01:00
const id = nextId(state.ai_facts);
state.ai_facts.push({ id, guild_id: guildId || null, channel_id: null, user_id: userId || null, fact_type: factType, fact_key: factKey, fact_value: factValue, created_at: Date.now(), updated_at: Date.now() });
save(state);
2026-03-11 18:58:15 +00:00
},
getUserFacts(guildId, userId) {
2026-08-06 17:29:37 +01:00
return state.ai_facts.filter(f => f.guild_id === (guildId || null) && f.user_id === (userId || null)).sort((a,b) => b.updated_at - a.updated_at);
2026-03-11 18:58:15 +00:00
},
2026-03-27 16:25:59 +00:00
getUserFactsByScope({ guildId = null, userId = null, scope = "guild" }) {
if (!userId) return [];
if (scope === "global") {
2026-08-06 17:29:37 +01:00
return state.ai_facts.filter(f => f.user_id === (userId || null)).sort((a,b) => b.updated_at - a.updated_at);
2026-03-27 16:25:59 +00:00
}
2026-08-06 17:29:37 +01:00
return state.ai_facts.filter(f => f.guild_id === (guildId || null) && f.user_id === (userId || null)).sort((a,b) => b.updated_at - a.updated_at);
2026-03-27 16:25:59 +00:00
},
2026-03-11 18:58:15 +00:00
addMessage({ guildId, channelId, userId, role, content }) {
2026-08-06 17:29:37 +01:00
const id = nextId(state.ai_conversations);
state.ai_conversations.push({ id, guild_id: guildId || null, channel_id: channelId || null, user_id: userId || null, role, content, created_at: Date.now() });
save(state);
2026-03-11 18:58:15 +00:00
},
getRecentMessages(channelId, limit = 15) {
2026-08-06 17:29:37 +01:00
const msgs = state.ai_conversations.filter(m => m.channel_id === channelId).sort((a,b) => b.created_at - a.created_at).slice(0, limit).reverse();
return msgs;
2026-03-11 18:58:15 +00:00
},
2026-03-27 16:25:59 +00:00
getRecentMessagesByScope({ guildId = null, channelId = null, limit = 15, scope = "guild" }) {
if (scope === "channel") {
2026-08-06 17:29:37 +01:00
return state.ai_conversations.filter(m => m.channel_id === (channelId || null)).sort((a,b) => b.created_at - a.created_at).slice(0, limit).reverse();
2026-03-27 16:25:59 +00:00
}
if (scope === "global") {
2026-08-06 17:29:37 +01:00
return state.ai_conversations.sort((a,b) => b.created_at - a.created_at).slice(0, limit).reverse();
2026-03-27 16:25:59 +00:00
}
2026-08-06 17:29:37 +01:00
return state.ai_conversations.filter(m => m.guild_id === (guildId || null)).sort((a,b) => b.created_at - a.created_at).slice(0, limit).reverse();
2026-03-27 16:25:59 +00:00
},
2026-03-11 18:58:15 +00:00
saveSummary({ guildId, channelId, summary }) {
2026-08-06 17:29:37 +01:00
const existing = state.ai_summaries.find(s => s.guild_id === (guildId || null) && s.channel_id === (channelId || null));
2026-03-11 18:58:15 +00:00
if (existing) {
2026-08-06 17:29:37 +01:00
existing.summary = summary;
existing.updated_at = Date.now();
save(state);
2026-03-11 18:58:15 +00:00
return;
}
2026-08-06 17:29:37 +01:00
const id = nextId(state.ai_summaries);
state.ai_summaries.push({ id, guild_id: guildId || null, channel_id: channelId || null, summary, created_at: Date.now(), updated_at: Date.now() });
save(state);
2026-03-11 18:58:15 +00:00
},
getLatestSummary(channelId) {
2026-08-06 17:29:37 +01:00
const arr = state.ai_summaries.filter(s => s.channel_id === channelId).sort((a,b) => b.updated_at - a.updated_at);
return arr.length ? arr[0] : null;
2026-03-11 18:58:15 +00:00
},
2026-03-27 16:25:59 +00:00
getLatestSummaryByScope({ guildId = null, channelId = null, scope = "guild" }) {
if (scope === "channel") {
2026-08-06 17:29:37 +01:00
const arr = state.ai_summaries.filter(s => s.channel_id === (channelId || null)).sort((a,b) => b.updated_at - a.updated_at);
return arr.length ? arr[0] : null;
2026-03-27 16:25:59 +00:00
}
if (scope === "global") {
2026-08-06 17:29:37 +01:00
const arr = state.ai_summaries.sort((a,b) => b.updated_at - a.updated_at);
return arr.length ? arr[0] : null;
2026-03-27 16:25:59 +00:00
}
2026-08-06 17:29:37 +01:00
const arr = state.ai_summaries.filter(s => s.guild_id === (guildId || null)).sort((a,b) => b.updated_at - a.updated_at);
return arr.length ? arr[0] : null;
2026-03-27 16:25:59 +00:00
},
2026-03-11 18:58:15 +00:00
saveFact({ guildId, channelId, factType, factKey, factValue }) {
2026-08-06 17:29:37 +01:00
const existing = state.ai_facts.find(f => f.guild_id === (guildId || null) && f.channel_id === (channelId || null) && f.fact_type === factType && f.fact_key === factKey);
2026-03-11 18:58:15 +00:00
if (existing) {
2026-08-06 17:29:37 +01:00
existing.fact_value = factValue;
existing.updated_at = Date.now();
save(state);
2026-03-11 18:58:15 +00:00
return;
}
2026-08-06 17:29:37 +01:00
const id = nextId(state.ai_facts);
state.ai_facts.push({ id, guild_id: guildId || null, channel_id: channelId || null, user_id: null, fact_type: factType, fact_key: factKey, fact_value: factValue, created_at: Date.now(), updated_at: Date.now() });
save(state);
2026-03-11 18:58:15 +00:00
},
getFacts(channelId) {
2026-08-06 17:29:37 +01:00
return state.ai_facts.filter(f => f.channel_id === channelId).sort((a,b) => b.updated_at - a.updated_at);
2026-03-11 18:58:15 +00:00
},
2026-03-27 16:25:59 +00:00
getFactsByScope({ guildId = null, channelId = null, scope = "guild" }) {
if (scope === "channel") {
2026-08-06 17:29:37 +01:00
return state.ai_facts.filter(f => f.channel_id === (channelId || null) && f.user_id == null).sort((a,b) => b.updated_at - a.updated_at);
2026-03-27 16:25:59 +00:00
}
if (scope === "global") {
2026-08-06 17:29:37 +01:00
return state.ai_facts.filter(f => f.user_id == null).sort((a,b) => b.updated_at - a.updated_at);
2026-03-27 16:25:59 +00:00
}
2026-08-06 17:29:37 +01:00
return state.ai_facts.filter(f => f.guild_id === (guildId || null) && f.user_id == null).sort((a,b) => b.updated_at - a.updated_at);
2026-03-27 16:25:59 +00:00
},
2026-03-11 18:58:15 +00:00
addKnowledge({ sourceType, sourceName, title, content }) {
2026-08-06 17:29:37 +01:00
const id = nextId(state.ai_knowledge);
state.ai_knowledge.push({ id, source_type: sourceType, source_name: sourceName, title, content, created_at: Date.now(), updated_at: Date.now() });
save(state);
2026-03-11 18:58:15 +00:00
},
getKnowledge(limit = 25) {
2026-08-06 17:29:37 +01:00
return state.ai_knowledge.sort((a,b) => b.updated_at - a.updated_at).slice(0, limit);
2026-03-11 18:58:15 +00:00
},
2026-04-21 13:37:39 +01:00
clearKnowledge() {
2026-08-06 17:29:37 +01:00
state.ai_knowledge = [];
save(state);
2026-04-21 13:37:39 +01:00
},
clearConversations(channelId) {
if (!channelId) return;
2026-08-06 17:29:37 +01:00
state.ai_conversations = state.ai_conversations.filter(c => c.channel_id !== channelId);
save(state);
2026-04-21 13:37:39 +01:00
},
2026-03-27 16:25:59 +00:00
};