Spaces:
Running
Running
File size: 6,570 Bytes
3d50167 798bcc6 8c89f37 798bcc6 3d50167 d48e96e 3d50167 798bcc6 3d50167 798bcc6 3d50167 798bcc6 3d50167 798bcc6 3d50167 798bcc6 |
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 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
// ===== KIMI MEMORY MANAGER =====
class KimiMemory {
constructor(database) {
this.db = database;
this.preferences = {
voiceRate: 1.1,
voicePitch: 1.1,
voiceVolume: 0.8,
lastInteraction: null,
totalInteractions: 0,
favoriteWords: [],
emotionalState: "neutral"
};
this.isReady = false;
// affectionTrait will be loaded from database during init()
this.affectionTrait = 50; // Temporary default until loaded from DB
}
async init() {
if (!this.db) {
console.warn("Database not available, using local mode");
return;
}
try {
this.selectedCharacter = await this.db.getSelectedCharacter();
// Start with lower favorability level - relationships must be built over time
this.favorabilityLevel = await this.db.getPreference(`favorabilityLevel_${this.selectedCharacter}`, 50);
// Load affection trait from personality database with coherent defaults
const charDefAff =
(window.KIMI_CHARACTERS && window.KIMI_CHARACTERS[this.selectedCharacter]?.traits?.affection) || null;
const genericAff = (window.getTraitDefaults && window.getTraitDefaults().affection) || 55;
const defaultAff = typeof charDefAff === "number" ? charDefAff : genericAff;
this.affectionTrait = await this.db.getPersonalityTrait("affection", defaultAff, this.selectedCharacter);
this.preferences = {
voiceRate: await this.db.getPreference("voiceRate", 1.1),
voicePitch: await this.db.getPreference("voicePitch", 1.1),
voiceVolume: await this.db.getPreference("voiceVolume", 0.8),
lastInteraction: await this.db.getPreference(`lastInteraction_${this.selectedCharacter}`, null),
totalInteractions: await this.db.getPreference(`totalInteractions_${this.selectedCharacter}`, 0),
favoriteWords: await this.db.getPreference(`favoriteWords_${this.selectedCharacter}`, []),
emotionalState: await this.db.getPreference(`emotionalState_${this.selectedCharacter}`, "neutral")
};
// affectionTrait already loaded above with coherent default
this.isReady = true;
this.updateFavorabilityBar();
} catch (error) {
console.error("KimiMemory initialization error:", error);
}
}
async saveConversation(userText, kimiResponse, tokenInfo = null) {
if (!this.db) return;
try {
const character = await this.db.getSelectedCharacter();
await this.db.saveConversation(userText, kimiResponse, this.favorabilityLevel, new Date(), character);
// Legacy interactions counter kept for backward compatibility (not shown in UI now)
let total = await this.db.getPreference(`totalInteractions_${character}`, 0);
total = Number(total) + 1;
await this.db.setPreference(`totalInteractions_${character}`, total);
this.preferences.totalInteractions = total;
// Update tokens usage if provided (in/out)
if (tokenInfo && typeof tokenInfo.tokensIn === "number" && typeof tokenInfo.tokensOut === "number") {
const prevIn = Number(await this.db.getPreference(`totalTokensIn_${character}`, 0)) || 0;
const prevOut = Number(await this.db.getPreference(`totalTokensOut_${character}`, 0)) || 0;
await this.db.setPreference(`totalTokensIn_${character}`, prevIn + tokenInfo.tokensIn);
await this.db.setPreference(`totalTokensOut_${character}`, prevOut + tokenInfo.tokensOut);
}
let first = await this.db.getPreference(`firstInteraction_${character}`, null);
if (!first) {
first = new Date().toISOString();
await this.db.setPreference(`firstInteraction_${character}`, first);
}
this.preferences.lastInteraction = new Date().toISOString();
await this.db.setPreference(`lastInteraction_${character}`, this.preferences.lastInteraction);
} catch (error) {
console.error("Error saving conversation:", error);
}
}
async updateFavorability(change) {
try {
this.affectionTrait = Math.max(0, Math.min(100, this.affectionTrait + change));
if (this.db) {
await this.db.setPersonalityTrait("affection", this.affectionTrait, this.selectedCharacter);
}
this.updateFavorabilityBar();
} catch (error) {
console.error("Error updating favorability:", error);
}
}
async updateAffectionTrait() {
if (!this.db) return;
try {
this.selectedCharacter = await this.db.getSelectedCharacter();
// Use unified default that matches KimiEmotionSystem
this.affectionTrait = await this.db.getPersonalityTrait("affection", 50, this.selectedCharacter);
this.updateFavorabilityBar();
} catch (error) {
console.error("Error updating affection trait:", error);
}
}
updateFavorabilityBar() {
try {
const favorabilityBar = document.getElementById("favorability-bar");
const favorabilityText = document.getElementById("favorability-text");
const value = Number(this.affectionTrait) || 0;
const clamped = Math.max(0, Math.min(100, value));
if (favorabilityBar) {
favorabilityBar.style.width = `${clamped}%`;
}
if (favorabilityText) {
favorabilityText.textContent = `${clamped.toFixed(2)}%`;
}
} catch (error) {
console.error("Error updating favorability bar:", error);
}
}
getGreeting() {
const i18n = window.kimiI18nManager;
if (this.affectionTrait <= 10) {
return i18n?.t("greeting_low") || "Hello.";
}
if (this.affectionTrait < 40) {
return i18n?.t("greeting_mid") || "Hi. How can I help you?";
}
return i18n?.t("greeting_high") || "Hello my love! π";
}
}
// Export to global scope
window.KimiMemory = KimiMemory;
export default KimiMemory;
|