Spaces:
Running
Running
Upload 33 files
Browse files- CHANGELOG.md +10 -0
- index.html +47 -57
- kimi-js/kimi-data-manager.js +318 -0
- kimi-js/kimi-module.js +3 -312
- kimi-js/kimi-script.js +1 -0
CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
| 1 |
# Virtual Kimi App Changelog
|
| 2 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3 |
# [1.1.4.1] - 2025-09-03
|
| 4 |
|
| 5 |
### Bug Fixes
|
|
|
|
| 1 |
# Virtual Kimi App Changelog
|
| 2 |
|
| 3 |
+
# [1.1.5] - 2025-09-03
|
| 4 |
+
|
| 5 |
+
### Bug Fixes
|
| 6 |
+
|
| 7 |
+
- Fixed some issues.
|
| 8 |
+
|
| 9 |
+
### Changed
|
| 10 |
+
|
| 11 |
+
- Separated the KimiDataManager class and moved logic into the new file `kimi-data-manager.js`.
|
| 12 |
+
|
| 13 |
# [1.1.4.1] - 2025-09-03
|
| 14 |
|
| 15 |
### Bug Fixes
|
index.html
CHANGED
|
@@ -37,29 +37,44 @@
|
|
| 37 |
content="Virtual AI companion with evolving personality and advanced voice recognition.">
|
| 38 |
<meta property="twitter:image" content="kimi-icons/virtualkimi-logo.png">
|
| 39 |
|
| 40 |
-
<!-- Schema.org
|
| 41 |
<script type="application/ld+json">
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
|
| 48 |
-
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
|
| 62 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 63 |
|
| 64 |
<!-- Favicon -->
|
| 65 |
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
|
@@ -1072,7 +1087,7 @@
|
|
| 1072 |
<h3><i class="fas fa-code"></i> Technical Information</h3>
|
| 1073 |
<div class="tech-info">
|
| 1074 |
<p><strong>Created date :</strong> July 16, 2025</p>
|
| 1075 |
-
<p><strong>Version :</strong> v1.1.
|
| 1076 |
<p><strong>Last update :</strong> September 03, 2025</p>
|
| 1077 |
<p><strong>Technologies :</strong> HTML5, CSS3, JavaScript ES6+, IndexedDB, Web Speech
|
| 1078 |
API</p>
|
|
@@ -1083,10 +1098,16 @@
|
|
| 1083 |
</div>
|
| 1084 |
</div>
|
| 1085 |
</div>
|
| 1086 |
-
</div>
|
| 1087 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1088 |
<script src="dexie.min.js"></script>
|
| 1089 |
-
<script src="kimi-locale/i18n.js"
|
| 1090 |
<script type="module" src="kimi-js/kimi-personality-utils.js"></script>
|
| 1091 |
<script type="module" src="kimi-js/kimi-utils.js"></script>
|
| 1092 |
<script type="module" src="kimi-js/kimi-main.js"></script>
|
|
@@ -1097,41 +1118,10 @@
|
|
| 1097 |
<script type="module" src="kimi-js/kimi-constants.js"></script>
|
| 1098 |
<script type="module" src="kimi-js/kimi-memory-ui.js"></script>
|
| 1099 |
<script type="module" src="kimi-js/kimi-appearance.js"></script>
|
|
|
|
| 1100 |
<script type="module" src="kimi-js/kimi-module.js"></script>
|
| 1101 |
<script type="module" src="kimi-js/kimi-script.js"></script>
|
| 1102 |
<script type="module" src="kimi-js/kimi-plugin-manager.js"></script>
|
| 1103 |
-
|
| 1104 |
-
<!-- Schema.org JSON-LD for better SEO -->
|
| 1105 |
-
<script type="application/ld+json">
|
| 1106 |
-
{
|
| 1107 |
-
"@context": "https://schema.org",
|
| 1108 |
-
"@type": "WebPage",
|
| 1109 |
-
"name": "Virtual Kimi - Virtual AI Companion",
|
| 1110 |
-
"description": "Virtual Kimi, your virtual AI girlfriend and companion with an evolving personality, multi-provider AI support, advanced voice recognition and immersive interface. The future of human-AI girlfriend relationships.",
|
| 1111 |
-
"url": "https://virtualkimi.com/virtual-kimi-app/index.html",
|
| 1112 |
-
"mainEntity": {
|
| 1113 |
-
"@type": "SoftwareApplication",
|
| 1114 |
-
"name": "Virtual Kimi",
|
| 1115 |
-
"applicationCategory": "AI Companion",
|
| 1116 |
-
"operatingSystem": "Web Browser",
|
| 1117 |
-
"description": "Virtual Kimi, a virtual AI girlfriend and companion with an evolving personality, multi-provider AI support, voice recognition and immersive interface",
|
| 1118 |
-
"features": [
|
| 1119 |
-
"Advanced voice recognition",
|
| 1120 |
-
"Evolving personality with 6 adjustable traits",
|
| 1121 |
-
"Premium LLM integration",
|
| 1122 |
-
"5 customizable visual themes",
|
| 1123 |
-
"Persistent memory",
|
| 1124 |
-
"Intelligent affection system"
|
| 1125 |
-
],
|
| 1126 |
-
"author": {
|
| 1127 |
-
"@type": "Person",
|
| 1128 |
-
"name": "Jean & Kimi"
|
| 1129 |
-
},
|
| 1130 |
-
"dateCreated": "2025-07-16",
|
| 1131 |
-
"version": "v1.1.4.1"
|
| 1132 |
-
}
|
| 1133 |
-
}
|
| 1134 |
-
</script>
|
| 1135 |
</body>
|
| 1136 |
|
| 1137 |
</html>
|
|
|
|
| 37 |
content="Virtual AI companion with evolving personality and advanced voice recognition.">
|
| 38 |
<meta property="twitter:image" content="kimi-icons/virtualkimi-logo.png">
|
| 39 |
|
| 40 |
+
<!-- Schema.org consolidated JSON-LD (WebPage + mainEntity SoftwareApplication) -->
|
| 41 |
<script type="application/ld+json">
|
| 42 |
+
{
|
| 43 |
+
"@context": "https://schema.org",
|
| 44 |
+
"@type": "WebPage",
|
| 45 |
+
"name": "Virtual Kimi - Virtual AI Companion",
|
| 46 |
+
"description": "Virtual Kimi, your virtual AI girlfriend and companion with an evolving personality, multi-provider AI support, advanced voice recognition and immersive interface.",
|
| 47 |
+
"url": "https://virtualkimi.com/virtual-kimi-app/index.html",
|
| 48 |
+
"mainEntity": {
|
| 49 |
+
"@type": "SoftwareApplication",
|
| 50 |
+
"@id": "https://virtualkimi.com/virtual-kimi-app/#app",
|
| 51 |
+
"name": "Virtual Kimi",
|
| 52 |
+
"description": "Virtual Kimi, your virtual AI girlfriend and companion with an evolving personality, multi-provider AI support, voice recognition and immersive interface",
|
| 53 |
+
"applicationCategory": "AI Companion",
|
| 54 |
+
"operatingSystem": "Web Browser",
|
| 55 |
+
"offers": {
|
| 56 |
+
"@type": "Offer",
|
| 57 |
+
"price": "0",
|
| 58 |
+
"priceCurrency": "USD"
|
| 59 |
+
},
|
| 60 |
+
"creator": {
|
| 61 |
+
"@type": "Person",
|
| 62 |
+
"name": "Jean & Kimi"
|
| 63 |
+
},
|
| 64 |
+
"dateCreated": "2025-07-16",
|
| 65 |
+
"dateModified": "2025-09-03",
|
| 66 |
+
"version": "v1.1.5",
|
| 67 |
+
"features": [
|
| 68 |
+
"Advanced voice recognition",
|
| 69 |
+
"Evolving personality with 6 adjustable traits",
|
| 70 |
+
"Premium LLM integration",
|
| 71 |
+
"5 customizable visual themes",
|
| 72 |
+
"Persistent memory",
|
| 73 |
+
"Intelligent affection system"
|
| 74 |
+
]
|
| 75 |
+
}
|
| 76 |
+
}
|
| 77 |
+
</script>
|
| 78 |
|
| 79 |
<!-- Favicon -->
|
| 80 |
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
|
|
|
| 1087 |
<h3><i class="fas fa-code"></i> Technical Information</h3>
|
| 1088 |
<div class="tech-info">
|
| 1089 |
<p><strong>Created date :</strong> July 16, 2025</p>
|
| 1090 |
+
<p><strong>Version :</strong> v1.1.5</p>
|
| 1091 |
<p><strong>Last update :</strong> September 03, 2025</p>
|
| 1092 |
<p><strong>Technologies :</strong> HTML5, CSS3, JavaScript ES6+, IndexedDB, Web Speech
|
| 1093 |
API</p>
|
|
|
|
| 1098 |
</div>
|
| 1099 |
</div>
|
| 1100 |
</div>
|
|
|
|
| 1101 |
|
| 1102 |
+
<!-- Script load order (critical):
|
| 1103 |
+
1. Legacy globals (dexie, i18n) must load before modules needing them.
|
| 1104 |
+
2. Base utilities (kimi-utils.js) define KimiBaseManager and helpers.
|
| 1105 |
+
3. Managers that extend base (appearance, data) after utils.
|
| 1106 |
+
4. Core module wiring (kimi-module.js) after managers so window.* hooks exist.
|
| 1107 |
+
5. Initialization / orchestration (kimi-script.js) last.
|
| 1108 |
+
Keep this order when adding new managers. -->
|
| 1109 |
<script src="dexie.min.js"></script>
|
| 1110 |
+
<script src="kimi-locale/i18n.js"></script>
|
| 1111 |
<script type="module" src="kimi-js/kimi-personality-utils.js"></script>
|
| 1112 |
<script type="module" src="kimi-js/kimi-utils.js"></script>
|
| 1113 |
<script type="module" src="kimi-js/kimi-main.js"></script>
|
|
|
|
| 1118 |
<script type="module" src="kimi-js/kimi-constants.js"></script>
|
| 1119 |
<script type="module" src="kimi-js/kimi-memory-ui.js"></script>
|
| 1120 |
<script type="module" src="kimi-js/kimi-appearance.js"></script>
|
| 1121 |
+
<script type="module" src="kimi-js/kimi-data-manager.js"></script>
|
| 1122 |
<script type="module" src="kimi-js/kimi-module.js"></script>
|
| 1123 |
<script type="module" src="kimi-js/kimi-script.js"></script>
|
| 1124 |
<script type="module" src="kimi-js/kimi-plugin-manager.js"></script>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1125 |
</body>
|
| 1126 |
|
| 1127 |
</html>
|
kimi-js/kimi-data-manager.js
ADDED
|
@@ -0,0 +1,318 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// KIMI DATA MANAGER (extracted from kimi-module.js)
|
| 2 |
+
// This file contains only the KimiDataManager class and its global exposure.
|
| 3 |
+
// Depends on: KimiBaseManager (defined in kimi-utils.js) and DOM APIs.
|
| 4 |
+
|
| 5 |
+
class KimiDataManager extends KimiBaseManager {
|
| 6 |
+
constructor(database) {
|
| 7 |
+
super();
|
| 8 |
+
this.db = database;
|
| 9 |
+
}
|
| 10 |
+
|
| 11 |
+
async init() {
|
| 12 |
+
this.setupDataControls();
|
| 13 |
+
await this.updateStorageInfo();
|
| 14 |
+
}
|
| 15 |
+
|
| 16 |
+
setupDataControls() {
|
| 17 |
+
const exportButton = document.getElementById("export-data");
|
| 18 |
+
if (exportButton) {
|
| 19 |
+
exportButton.addEventListener("click", () => this.exportAllData());
|
| 20 |
+
}
|
| 21 |
+
|
| 22 |
+
const importButton = document.getElementById("import-data");
|
| 23 |
+
const importFile = document.getElementById("import-file");
|
| 24 |
+
if (importButton && importFile) {
|
| 25 |
+
importButton.addEventListener("click", () => importFile.click());
|
| 26 |
+
importFile.addEventListener("change", e => this.importData(e));
|
| 27 |
+
}
|
| 28 |
+
|
| 29 |
+
const cleanButton = document.getElementById("clean-old-data");
|
| 30 |
+
if (cleanButton) {
|
| 31 |
+
cleanButton.addEventListener("click", async () => {
|
| 32 |
+
if (!this.db) return;
|
| 33 |
+
|
| 34 |
+
const confirmClean = confirm(
|
| 35 |
+
"Delete all conversation messages?\n\n" +
|
| 36 |
+
"This will remove all chat history but keep your preferences and settings.\n\n" +
|
| 37 |
+
"This action cannot be undone."
|
| 38 |
+
);
|
| 39 |
+
|
| 40 |
+
if (!confirmClean) {
|
| 41 |
+
return;
|
| 42 |
+
}
|
| 43 |
+
|
| 44 |
+
try {
|
| 45 |
+
// Clear all conversations directly
|
| 46 |
+
await this.db.db.conversations.clear();
|
| 47 |
+
|
| 48 |
+
// Clear chat UI
|
| 49 |
+
const chatMessages = document.getElementById("chat-messages");
|
| 50 |
+
if (chatMessages) {
|
| 51 |
+
chatMessages.textContent = "";
|
| 52 |
+
}
|
| 53 |
+
|
| 54 |
+
// Reload chat history
|
| 55 |
+
if (typeof window.loadChatHistory === "function") {
|
| 56 |
+
window.loadChatHistory();
|
| 57 |
+
}
|
| 58 |
+
|
| 59 |
+
await this.updateStorageInfo();
|
| 60 |
+
alert("All conversation messages have been deleted successfully!");
|
| 61 |
+
} catch (error) {
|
| 62 |
+
console.error("Error cleaning conversations:", error);
|
| 63 |
+
alert("Error while cleaning conversations. Please try again.");
|
| 64 |
+
}
|
| 65 |
+
});
|
| 66 |
+
}
|
| 67 |
+
|
| 68 |
+
const resetButton = document.getElementById("reset-all-data");
|
| 69 |
+
if (resetButton) {
|
| 70 |
+
resetButton.addEventListener("click", () => this.resetAllData());
|
| 71 |
+
}
|
| 72 |
+
}
|
| 73 |
+
|
| 74 |
+
async exportAllData() {
|
| 75 |
+
if (!this.db) {
|
| 76 |
+
console.error("Database not available");
|
| 77 |
+
return;
|
| 78 |
+
}
|
| 79 |
+
|
| 80 |
+
try {
|
| 81 |
+
const conversations = await this.db.getAllConversations();
|
| 82 |
+
const preferencesObj = await this.db.getAllPreferences();
|
| 83 |
+
// Export preferences as an array of {key,value} so export is directly re-importable
|
| 84 |
+
const preferences = Array.isArray(preferencesObj)
|
| 85 |
+
? preferencesObj
|
| 86 |
+
: Object.keys(preferencesObj).map(k => ({ key: k, value: preferencesObj[k] }));
|
| 87 |
+
const personalityTraits = await this.db.getAllPersonalityTraits();
|
| 88 |
+
const models = await this.db.getAllLLMModels();
|
| 89 |
+
const memories = await this.db.getAllMemories();
|
| 90 |
+
|
| 91 |
+
const exportData = {
|
| 92 |
+
version: "1.0",
|
| 93 |
+
exportDate: new Date().toISOString(),
|
| 94 |
+
conversations: conversations,
|
| 95 |
+
preferences: preferences,
|
| 96 |
+
personalityTraits: personalityTraits,
|
| 97 |
+
models: models,
|
| 98 |
+
memories: memories,
|
| 99 |
+
metadata: {
|
| 100 |
+
totalConversations: conversations.length,
|
| 101 |
+
totalPreferences: Object.keys(preferences).length,
|
| 102 |
+
totalTraits: Object.keys(personalityTraits).length,
|
| 103 |
+
totalModels: models.length,
|
| 104 |
+
totalMemories: memories.length
|
| 105 |
+
}
|
| 106 |
+
};
|
| 107 |
+
|
| 108 |
+
const dataStr = JSON.stringify(exportData, null, 2);
|
| 109 |
+
const dataBlob = new Blob([dataStr], { type: "application/json" });
|
| 110 |
+
|
| 111 |
+
const url = URL.createObjectURL(dataBlob);
|
| 112 |
+
const a = document.createElement("a");
|
| 113 |
+
a.href = url;
|
| 114 |
+
a.download = `kimi-backup-${new Date().toISOString().split("T")[0]}.json`;
|
| 115 |
+
document.body.appendChild(a);
|
| 116 |
+
a.click();
|
| 117 |
+
document.body.removeChild(a);
|
| 118 |
+
URL.revokeObjectURL(url);
|
| 119 |
+
} catch (error) {
|
| 120 |
+
console.error("Error during export:", error);
|
| 121 |
+
}
|
| 122 |
+
}
|
| 123 |
+
|
| 124 |
+
async importData(event) {
|
| 125 |
+
const file = event.target.files[0];
|
| 126 |
+
if (!file) {
|
| 127 |
+
alert("No file selected.");
|
| 128 |
+
return;
|
| 129 |
+
}
|
| 130 |
+
const reader = new FileReader();
|
| 131 |
+
reader.onload = async e => {
|
| 132 |
+
try {
|
| 133 |
+
const data = JSON.parse(e.target.result);
|
| 134 |
+
try {
|
| 135 |
+
console.log("Import file keys:", Object.keys(data));
|
| 136 |
+
} catch (ex) {}
|
| 137 |
+
|
| 138 |
+
if (data.preferences) {
|
| 139 |
+
try {
|
| 140 |
+
const isArray = Array.isArray(data.preferences);
|
| 141 |
+
const len = isArray ? data.preferences.length : Object.keys(data.preferences).length;
|
| 142 |
+
console.log("Import: preferences type=", isArray ? "array" : "object", "length=", len);
|
| 143 |
+
} catch (ex) {}
|
| 144 |
+
await this.db.setPreferencesBatch(data.preferences);
|
| 145 |
+
} else {
|
| 146 |
+
console.log("Import: no preferences found");
|
| 147 |
+
}
|
| 148 |
+
|
| 149 |
+
if (data.conversations) {
|
| 150 |
+
try {
|
| 151 |
+
console.log(
|
| 152 |
+
"Import: conversations length=",
|
| 153 |
+
Array.isArray(data.conversations) ? data.conversations.length : "not-array"
|
| 154 |
+
);
|
| 155 |
+
} catch (ex) {}
|
| 156 |
+
await this.db.setConversationsBatch(data.conversations);
|
| 157 |
+
} else {
|
| 158 |
+
console.log("Import: no conversations found");
|
| 159 |
+
}
|
| 160 |
+
|
| 161 |
+
if (data.personalityTraits) {
|
| 162 |
+
try {
|
| 163 |
+
console.log("Import: personalityTraits type=", typeof data.personalityTraits);
|
| 164 |
+
} catch (ex) {}
|
| 165 |
+
await this.db.setPersonalityBatch(data.personalityTraits);
|
| 166 |
+
} else {
|
| 167 |
+
console.log("Import: no personalityTraits found");
|
| 168 |
+
}
|
| 169 |
+
|
| 170 |
+
if (data.models) {
|
| 171 |
+
try {
|
| 172 |
+
console.log("Import: models length=", Array.isArray(data.models) ? data.models.length : "not-array");
|
| 173 |
+
} catch (ex) {}
|
| 174 |
+
await this.db.setLLMModelsBatch(data.models);
|
| 175 |
+
} else {
|
| 176 |
+
console.log("Import: no models found");
|
| 177 |
+
}
|
| 178 |
+
|
| 179 |
+
if (data.memories) {
|
| 180 |
+
try {
|
| 181 |
+
console.log(
|
| 182 |
+
"Import: memories length=",
|
| 183 |
+
Array.isArray(data.memories) ? data.memories.length : "not-array"
|
| 184 |
+
);
|
| 185 |
+
} catch (ex) {}
|
| 186 |
+
await this.db.setAllMemories(data.memories);
|
| 187 |
+
} else {
|
| 188 |
+
console.log("Import: no memories found");
|
| 189 |
+
}
|
| 190 |
+
|
| 191 |
+
alert("Import successful!");
|
| 192 |
+
await this.updateStorageInfo();
|
| 193 |
+
|
| 194 |
+
// Reload the page to ensure all UI state is rebuilt from the newly imported DB
|
| 195 |
+
setTimeout(() => {
|
| 196 |
+
location.reload();
|
| 197 |
+
}, 200);
|
| 198 |
+
} catch (err) {
|
| 199 |
+
console.error("Import failed:", err);
|
| 200 |
+
alert("Import failed. Invalid file or format.");
|
| 201 |
+
}
|
| 202 |
+
};
|
| 203 |
+
reader.readAsText(file);
|
| 204 |
+
}
|
| 205 |
+
|
| 206 |
+
async cleanOldData() {
|
| 207 |
+
if (!this.db) {
|
| 208 |
+
console.error("Database not available");
|
| 209 |
+
return;
|
| 210 |
+
}
|
| 211 |
+
|
| 212 |
+
const confirmClean = confirm("Do you want to delete ALL conversations?\n\nThis action is irreversible!");
|
| 213 |
+
if (!confirmClean) {
|
| 214 |
+
return;
|
| 215 |
+
}
|
| 216 |
+
|
| 217 |
+
try {
|
| 218 |
+
// Centralized: use kimi-database.js cleanOldConversations for all deletion logic
|
| 219 |
+
await this.db.cleanOldConversations();
|
| 220 |
+
|
| 221 |
+
if (typeof window.loadChatHistory === "function") {
|
| 222 |
+
window.loadChatHistory();
|
| 223 |
+
}
|
| 224 |
+
const chatMessages = document.getElementById("chat-messages");
|
| 225 |
+
if (chatMessages) {
|
| 226 |
+
chatMessages.textContent = "";
|
| 227 |
+
}
|
| 228 |
+
|
| 229 |
+
await this.updateStorageInfo();
|
| 230 |
+
} catch (error) {
|
| 231 |
+
console.error("Error during cleaning:", error);
|
| 232 |
+
}
|
| 233 |
+
}
|
| 234 |
+
|
| 235 |
+
async resetAllData() {
|
| 236 |
+
if (!this.db) {
|
| 237 |
+
console.error("Database not available");
|
| 238 |
+
return;
|
| 239 |
+
}
|
| 240 |
+
|
| 241 |
+
const confirmReset = confirm(
|
| 242 |
+
"WARNING!\n\n" +
|
| 243 |
+
"Do you REALLY want to delete ALL data?\n\n" +
|
| 244 |
+
"• All conversations\n" +
|
| 245 |
+
"• All preferences\n" +
|
| 246 |
+
"• All configured models\n" +
|
| 247 |
+
"• All personality traits\n\n" +
|
| 248 |
+
"This action is IRREVERSIBLE!"
|
| 249 |
+
);
|
| 250 |
+
|
| 251 |
+
if (!confirmReset) {
|
| 252 |
+
return;
|
| 253 |
+
}
|
| 254 |
+
|
| 255 |
+
try {
|
| 256 |
+
if (this.db.db) {
|
| 257 |
+
this.db.db.close();
|
| 258 |
+
}
|
| 259 |
+
|
| 260 |
+
const deleteRequest = indexedDB.deleteDatabase(this.db.dbName);
|
| 261 |
+
|
| 262 |
+
deleteRequest.onsuccess = () => {
|
| 263 |
+
setTimeout(() => {
|
| 264 |
+
alert("The page will reload to complete the reset.");
|
| 265 |
+
location.reload();
|
| 266 |
+
}, 500);
|
| 267 |
+
};
|
| 268 |
+
|
| 269 |
+
deleteRequest.onerror = () => {
|
| 270 |
+
alert("Error while deleting the database. Please try again.");
|
| 271 |
+
};
|
| 272 |
+
} catch (error) {
|
| 273 |
+
console.error("Error during reset:", error);
|
| 274 |
+
alert("Error during reset. Please try again.");
|
| 275 |
+
}
|
| 276 |
+
}
|
| 277 |
+
|
| 278 |
+
async updateStorageInfo() {
|
| 279 |
+
if (!this.db) return;
|
| 280 |
+
|
| 281 |
+
try {
|
| 282 |
+
// Add a small delay to ensure database operations are complete
|
| 283 |
+
await new Promise(resolve => setTimeout(resolve, 100));
|
| 284 |
+
|
| 285 |
+
const stats = await this.db.getStorageStats();
|
| 286 |
+
|
| 287 |
+
const dbSizeEl = document.getElementById("db-size");
|
| 288 |
+
const storageUsedEl = document.getElementById("storage-used");
|
| 289 |
+
|
| 290 |
+
if (dbSizeEl) {
|
| 291 |
+
dbSizeEl.textContent = this.formatFileSize(stats.totalSize || 0);
|
| 292 |
+
}
|
| 293 |
+
|
| 294 |
+
if (storageUsedEl) {
|
| 295 |
+
const estimate = navigator.storage && navigator.storage.estimate ? await navigator.storage.estimate() : null;
|
| 296 |
+
|
| 297 |
+
if (estimate) {
|
| 298 |
+
storageUsedEl.textContent = this.formatFileSize(estimate.usage || 0);
|
| 299 |
+
} else {
|
| 300 |
+
storageUsedEl.textContent = "N/A";
|
| 301 |
+
}
|
| 302 |
+
}
|
| 303 |
+
} catch (error) {
|
| 304 |
+
console.error("Error while calculating storage:", error);
|
| 305 |
+
|
| 306 |
+
const dbSizeEl = document.getElementById("db-size");
|
| 307 |
+
const storageUsedEl = document.getElementById("storage-used");
|
| 308 |
+
|
| 309 |
+
if (dbSizeEl) dbSizeEl.textContent = "Error";
|
| 310 |
+
if (storageUsedEl) storageUsedEl.textContent = "Error";
|
| 311 |
+
}
|
| 312 |
+
}
|
| 313 |
+
}
|
| 314 |
+
|
| 315 |
+
// Global exposure (legacy pattern). Will be phased out; prefer: import { KimiDataManager } from "./kimi-data-manager.js";
|
| 316 |
+
window.KimiDataManager = KimiDataManager; // DEPRECATED access path (kept for backward compatibility)
|
| 317 |
+
|
| 318 |
+
export { KimiDataManager };
|
kimi-js/kimi-module.js
CHANGED
|
@@ -1,314 +1,6 @@
|
|
| 1 |
// KIMI MODULE SYSTEM
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
constructor(database) {
|
| 5 |
-
super();
|
| 6 |
-
this.db = database;
|
| 7 |
-
}
|
| 8 |
-
|
| 9 |
-
async init() {
|
| 10 |
-
this.setupDataControls();
|
| 11 |
-
await this.updateStorageInfo();
|
| 12 |
-
}
|
| 13 |
-
|
| 14 |
-
setupDataControls() {
|
| 15 |
-
const exportButton = document.getElementById("export-data");
|
| 16 |
-
if (exportButton) {
|
| 17 |
-
exportButton.addEventListener("click", () => this.exportAllData());
|
| 18 |
-
}
|
| 19 |
-
|
| 20 |
-
const importButton = document.getElementById("import-data");
|
| 21 |
-
const importFile = document.getElementById("import-file");
|
| 22 |
-
if (importButton && importFile) {
|
| 23 |
-
importButton.addEventListener("click", () => importFile.click());
|
| 24 |
-
importFile.addEventListener("change", e => this.importData(e));
|
| 25 |
-
}
|
| 26 |
-
|
| 27 |
-
const cleanButton = document.getElementById("clean-old-data");
|
| 28 |
-
if (cleanButton) {
|
| 29 |
-
cleanButton.addEventListener("click", async () => {
|
| 30 |
-
if (!this.db) return;
|
| 31 |
-
|
| 32 |
-
const confirmClean = confirm(
|
| 33 |
-
"Delete all conversation messages?\n\n" +
|
| 34 |
-
"This will remove all chat history but keep your preferences and settings.\n\n" +
|
| 35 |
-
"This action cannot be undone."
|
| 36 |
-
);
|
| 37 |
-
|
| 38 |
-
if (!confirmClean) {
|
| 39 |
-
return;
|
| 40 |
-
}
|
| 41 |
-
|
| 42 |
-
try {
|
| 43 |
-
// Clear all conversations directly
|
| 44 |
-
await this.db.db.conversations.clear();
|
| 45 |
-
|
| 46 |
-
// Clear chat UI
|
| 47 |
-
const chatMessages = document.getElementById("chat-messages");
|
| 48 |
-
if (chatMessages) {
|
| 49 |
-
chatMessages.textContent = "";
|
| 50 |
-
}
|
| 51 |
-
|
| 52 |
-
// Reload chat history
|
| 53 |
-
if (typeof window.loadChatHistory === "function") {
|
| 54 |
-
window.loadChatHistory();
|
| 55 |
-
}
|
| 56 |
-
|
| 57 |
-
await this.updateStorageInfo();
|
| 58 |
-
alert("All conversation messages have been deleted successfully!");
|
| 59 |
-
} catch (error) {
|
| 60 |
-
console.error("Error cleaning conversations:", error);
|
| 61 |
-
alert("Error while cleaning conversations. Please try again.");
|
| 62 |
-
}
|
| 63 |
-
});
|
| 64 |
-
}
|
| 65 |
-
|
| 66 |
-
const resetButton = document.getElementById("reset-all-data");
|
| 67 |
-
if (resetButton) {
|
| 68 |
-
resetButton.addEventListener("click", () => this.resetAllData());
|
| 69 |
-
}
|
| 70 |
-
}
|
| 71 |
-
|
| 72 |
-
async exportAllData() {
|
| 73 |
-
if (!this.db) {
|
| 74 |
-
console.error("Database not available");
|
| 75 |
-
return;
|
| 76 |
-
}
|
| 77 |
-
|
| 78 |
-
try {
|
| 79 |
-
const conversations = await this.db.getAllConversations();
|
| 80 |
-
const preferencesObj = await this.db.getAllPreferences();
|
| 81 |
-
// Export preferences as an array of {key,value} so export is directly re-importable
|
| 82 |
-
const preferences = Array.isArray(preferencesObj)
|
| 83 |
-
? preferencesObj
|
| 84 |
-
: Object.keys(preferencesObj).map(k => ({ key: k, value: preferencesObj[k] }));
|
| 85 |
-
const personalityTraits = await this.db.getAllPersonalityTraits();
|
| 86 |
-
const models = await this.db.getAllLLMModels();
|
| 87 |
-
const memories = await this.db.getAllMemories();
|
| 88 |
-
|
| 89 |
-
const exportData = {
|
| 90 |
-
version: "1.0",
|
| 91 |
-
exportDate: new Date().toISOString(),
|
| 92 |
-
conversations: conversations,
|
| 93 |
-
preferences: preferences,
|
| 94 |
-
personalityTraits: personalityTraits,
|
| 95 |
-
models: models,
|
| 96 |
-
memories: memories,
|
| 97 |
-
metadata: {
|
| 98 |
-
totalConversations: conversations.length,
|
| 99 |
-
totalPreferences: Object.keys(preferences).length,
|
| 100 |
-
totalTraits: Object.keys(personalityTraits).length,
|
| 101 |
-
totalModels: models.length,
|
| 102 |
-
totalMemories: memories.length
|
| 103 |
-
}
|
| 104 |
-
};
|
| 105 |
-
|
| 106 |
-
const dataStr = JSON.stringify(exportData, null, 2);
|
| 107 |
-
const dataBlob = new Blob([dataStr], { type: "application/json" });
|
| 108 |
-
|
| 109 |
-
const url = URL.createObjectURL(dataBlob);
|
| 110 |
-
const a = document.createElement("a");
|
| 111 |
-
a.href = url;
|
| 112 |
-
a.download = `kimi-backup-${new Date().toISOString().split("T")[0]}.json`;
|
| 113 |
-
document.body.appendChild(a);
|
| 114 |
-
a.click();
|
| 115 |
-
document.body.removeChild(a);
|
| 116 |
-
URL.revokeObjectURL(url);
|
| 117 |
-
} catch (error) {
|
| 118 |
-
console.error("Error during export:", error);
|
| 119 |
-
}
|
| 120 |
-
}
|
| 121 |
-
|
| 122 |
-
async importData(event) {
|
| 123 |
-
const file = event.target.files[0];
|
| 124 |
-
if (!file) {
|
| 125 |
-
alert("No file selected.");
|
| 126 |
-
return;
|
| 127 |
-
}
|
| 128 |
-
const reader = new FileReader();
|
| 129 |
-
reader.onload = async e => {
|
| 130 |
-
try {
|
| 131 |
-
const data = JSON.parse(e.target.result);
|
| 132 |
-
try {
|
| 133 |
-
console.log("Import file keys:", Object.keys(data));
|
| 134 |
-
} catch (ex) {}
|
| 135 |
-
|
| 136 |
-
if (data.preferences) {
|
| 137 |
-
try {
|
| 138 |
-
const isArray = Array.isArray(data.preferences);
|
| 139 |
-
const len = isArray ? data.preferences.length : Object.keys(data.preferences).length;
|
| 140 |
-
console.log("Import: preferences type=", isArray ? "array" : "object", "length=", len);
|
| 141 |
-
} catch (ex) {}
|
| 142 |
-
await this.db.setPreferencesBatch(data.preferences);
|
| 143 |
-
} else {
|
| 144 |
-
console.log("Import: no preferences found");
|
| 145 |
-
}
|
| 146 |
-
|
| 147 |
-
if (data.conversations) {
|
| 148 |
-
try {
|
| 149 |
-
console.log(
|
| 150 |
-
"Import: conversations length=",
|
| 151 |
-
Array.isArray(data.conversations) ? data.conversations.length : "not-array"
|
| 152 |
-
);
|
| 153 |
-
} catch (ex) {}
|
| 154 |
-
await this.db.setConversationsBatch(data.conversations);
|
| 155 |
-
} else {
|
| 156 |
-
console.log("Import: no conversations found");
|
| 157 |
-
}
|
| 158 |
-
|
| 159 |
-
if (data.personalityTraits) {
|
| 160 |
-
try {
|
| 161 |
-
console.log("Import: personalityTraits type=", typeof data.personalityTraits);
|
| 162 |
-
} catch (ex) {}
|
| 163 |
-
await this.db.setPersonalityBatch(data.personalityTraits);
|
| 164 |
-
} else {
|
| 165 |
-
console.log("Import: no personalityTraits found");
|
| 166 |
-
}
|
| 167 |
-
|
| 168 |
-
if (data.models) {
|
| 169 |
-
try {
|
| 170 |
-
console.log("Import: models length=", Array.isArray(data.models) ? data.models.length : "not-array");
|
| 171 |
-
} catch (ex) {}
|
| 172 |
-
await this.db.setLLMModelsBatch(data.models);
|
| 173 |
-
} else {
|
| 174 |
-
console.log("Import: no models found");
|
| 175 |
-
}
|
| 176 |
-
|
| 177 |
-
if (data.memories) {
|
| 178 |
-
try {
|
| 179 |
-
console.log(
|
| 180 |
-
"Import: memories length=",
|
| 181 |
-
Array.isArray(data.memories) ? data.memories.length : "not-array"
|
| 182 |
-
);
|
| 183 |
-
} catch (ex) {}
|
| 184 |
-
await this.db.setAllMemories(data.memories);
|
| 185 |
-
} else {
|
| 186 |
-
console.log("Import: no memories found");
|
| 187 |
-
}
|
| 188 |
-
|
| 189 |
-
alert("Import successful!");
|
| 190 |
-
await this.updateStorageInfo();
|
| 191 |
-
|
| 192 |
-
// Reload the page to ensure all UI state is rebuilt from the newly imported DB
|
| 193 |
-
setTimeout(() => {
|
| 194 |
-
location.reload();
|
| 195 |
-
}, 200);
|
| 196 |
-
} catch (err) {
|
| 197 |
-
console.error("Import failed:", err);
|
| 198 |
-
alert("Import failed. Invalid file or format.");
|
| 199 |
-
}
|
| 200 |
-
};
|
| 201 |
-
reader.readAsText(file);
|
| 202 |
-
}
|
| 203 |
-
|
| 204 |
-
async cleanOldData() {
|
| 205 |
-
if (!this.db) {
|
| 206 |
-
console.error("Database not available");
|
| 207 |
-
return;
|
| 208 |
-
}
|
| 209 |
-
|
| 210 |
-
const confirmClean = confirm("Do you want to delete ALL conversations?\n\nThis action is irreversible!");
|
| 211 |
-
if (!confirmClean) {
|
| 212 |
-
return;
|
| 213 |
-
}
|
| 214 |
-
|
| 215 |
-
try {
|
| 216 |
-
// Centralized: use kimi-database.js cleanOldConversations for all deletion logic
|
| 217 |
-
await this.db.cleanOldConversations();
|
| 218 |
-
|
| 219 |
-
if (typeof window.loadChatHistory === "function") {
|
| 220 |
-
window.loadChatHistory();
|
| 221 |
-
}
|
| 222 |
-
const chatMessages = document.getElementById("chat-messages");
|
| 223 |
-
if (chatMessages) {
|
| 224 |
-
chatMessages.textContent = "";
|
| 225 |
-
}
|
| 226 |
-
|
| 227 |
-
await this.updateStorageInfo();
|
| 228 |
-
} catch (error) {
|
| 229 |
-
console.error("Error during cleaning:", error);
|
| 230 |
-
}
|
| 231 |
-
}
|
| 232 |
-
|
| 233 |
-
async resetAllData() {
|
| 234 |
-
if (!this.db) {
|
| 235 |
-
console.error("Database not available");
|
| 236 |
-
return;
|
| 237 |
-
}
|
| 238 |
-
|
| 239 |
-
const confirmReset = confirm(
|
| 240 |
-
"WARNING!\n\n" +
|
| 241 |
-
"Do you REALLY want to delete ALL data?\n\n" +
|
| 242 |
-
"• All conversations\n" +
|
| 243 |
-
"• All preferences\n" +
|
| 244 |
-
"• All configured models\n" +
|
| 245 |
-
"• All personality traits\n\n" +
|
| 246 |
-
"This action is IRREVERSIBLE!"
|
| 247 |
-
);
|
| 248 |
-
|
| 249 |
-
if (!confirmReset) {
|
| 250 |
-
return;
|
| 251 |
-
}
|
| 252 |
-
|
| 253 |
-
try {
|
| 254 |
-
if (this.db.db) {
|
| 255 |
-
this.db.db.close();
|
| 256 |
-
}
|
| 257 |
-
|
| 258 |
-
const deleteRequest = indexedDB.deleteDatabase(this.db.dbName);
|
| 259 |
-
|
| 260 |
-
deleteRequest.onsuccess = () => {
|
| 261 |
-
setTimeout(() => {
|
| 262 |
-
alert("The page will reload to complete the reset.");
|
| 263 |
-
location.reload();
|
| 264 |
-
}, 500);
|
| 265 |
-
};
|
| 266 |
-
|
| 267 |
-
deleteRequest.onerror = () => {
|
| 268 |
-
alert("Error while deleting the database. Please try again.");
|
| 269 |
-
};
|
| 270 |
-
} catch (error) {
|
| 271 |
-
console.error("Error during reset:", error);
|
| 272 |
-
alert("Error during reset. Please try again.");
|
| 273 |
-
}
|
| 274 |
-
}
|
| 275 |
-
|
| 276 |
-
async updateStorageInfo() {
|
| 277 |
-
if (!this.db) return;
|
| 278 |
-
|
| 279 |
-
try {
|
| 280 |
-
// Add a small delay to ensure database operations are complete
|
| 281 |
-
await new Promise(resolve => setTimeout(resolve, 100));
|
| 282 |
-
|
| 283 |
-
const stats = await this.db.getStorageStats();
|
| 284 |
-
|
| 285 |
-
const dbSizeEl = document.getElementById("db-size");
|
| 286 |
-
const storageUsedEl = document.getElementById("storage-used");
|
| 287 |
-
|
| 288 |
-
if (dbSizeEl) {
|
| 289 |
-
dbSizeEl.textContent = this.formatFileSize(stats.totalSize || 0);
|
| 290 |
-
}
|
| 291 |
-
|
| 292 |
-
if (storageUsedEl) {
|
| 293 |
-
const estimate = navigator.storage && navigator.storage.estimate ? await navigator.storage.estimate() : null;
|
| 294 |
-
|
| 295 |
-
if (estimate) {
|
| 296 |
-
storageUsedEl.textContent = this.formatFileSize(estimate.usage || 0);
|
| 297 |
-
} else {
|
| 298 |
-
storageUsedEl.textContent = "N/A";
|
| 299 |
-
}
|
| 300 |
-
}
|
| 301 |
-
} catch (error) {
|
| 302 |
-
console.error("Error while calculating storage:", error);
|
| 303 |
-
|
| 304 |
-
const dbSizeEl = document.getElementById("db-size");
|
| 305 |
-
const storageUsedEl = document.getElementById("storage-used");
|
| 306 |
-
|
| 307 |
-
if (dbSizeEl) dbSizeEl.textContent = "Error";
|
| 308 |
-
if (storageUsedEl) storageUsedEl.textContent = "Error";
|
| 309 |
-
}
|
| 310 |
-
}
|
| 311 |
-
}
|
| 312 |
|
| 313 |
// Fonctions utilitaires et logique (référencent window.*)
|
| 314 |
|
|
@@ -2052,8 +1744,7 @@ function setupSettingsListeners(kimiDB, kimiMemory) {
|
|
| 2052 |
}
|
| 2053 |
}
|
| 2054 |
|
| 2055 |
-
// Exposer globalement
|
| 2056 |
-
window.KimiDataManager = KimiDataManager;
|
| 2057 |
window.updateFavorabilityLabel = updateFavorabilityLabel;
|
| 2058 |
window.loadCharacterSection = loadCharacterSection;
|
| 2059 |
window.getBasicResponse = getBasicResponse;
|
|
|
|
| 1 |
// KIMI MODULE SYSTEM
|
| 2 |
+
// KimiDataManager has been extracted to kimi-data-manager.js
|
| 3 |
+
// (kept global via window.KimiDataManager)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4 |
|
| 5 |
// Fonctions utilitaires et logique (référencent window.*)
|
| 6 |
|
|
|
|
| 1744 |
}
|
| 1745 |
}
|
| 1746 |
|
| 1747 |
+
// Exposer globalement (KimiDataManager already exposed in kimi-data-manager.js)
|
|
|
|
| 1748 |
window.updateFavorabilityLabel = updateFavorabilityLabel;
|
| 1749 |
window.loadCharacterSection = loadCharacterSection;
|
| 1750 |
window.getBasicResponse = getBasicResponse;
|
kimi-js/kimi-script.js
CHANGED
|
@@ -3,6 +3,7 @@ import KimiLLMManager from "./kimi-llm-manager.js";
|
|
| 3 |
import KimiEmotionSystem from "./kimi-emotion-system.js";
|
| 4 |
import KimiMemorySystem from "./kimi-memory-system.js";
|
| 5 |
import KimiMemory from "./kimi-memory.js";
|
|
|
|
| 6 |
|
| 7 |
document.addEventListener("DOMContentLoaded", async function () {
|
| 8 |
const DEFAULT_SYSTEM_PROMPT = window.DEFAULT_SYSTEM_PROMPT;
|
|
|
|
| 3 |
import KimiEmotionSystem from "./kimi-emotion-system.js";
|
| 4 |
import KimiMemorySystem from "./kimi-memory-system.js";
|
| 5 |
import KimiMemory from "./kimi-memory.js";
|
| 6 |
+
import { KimiDataManager } from "./kimi-data-manager.js"; // Explicit import (phasing out window.KimiDataManager)
|
| 7 |
|
| 8 |
document.addEventListener("DOMContentLoaded", async function () {
|
| 9 |
const DEFAULT_SYSTEM_PROMPT = window.DEFAULT_SYSTEM_PROMPT;
|