首次提交
This commit is contained in:
@@ -0,0 +1,125 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const crypto = require('crypto');
|
||||
const { app } = require('electron');
|
||||
|
||||
function dataDir() {
|
||||
const dir = path.join(app.getPath('userData'), 'data');
|
||||
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
||||
return dir;
|
||||
}
|
||||
|
||||
function providersPath() {
|
||||
return path.join(dataDir(), 'providers.json');
|
||||
}
|
||||
|
||||
function conversationsDir() {
|
||||
const dir = path.join(dataDir(), 'conversations');
|
||||
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
||||
return dir;
|
||||
}
|
||||
|
||||
function readJSON(file, fallback) {
|
||||
try {
|
||||
if (!fs.existsSync(file)) return fallback;
|
||||
return JSON.parse(fs.readFileSync(file, 'utf8'));
|
||||
} catch {
|
||||
return fallback;
|
||||
}
|
||||
}
|
||||
|
||||
function writeJSON(file, data) {
|
||||
fs.writeFileSync(file, JSON.stringify(data, null, 2), 'utf8');
|
||||
}
|
||||
|
||||
function getProviders() {
|
||||
return readJSON(providersPath(), []);
|
||||
}
|
||||
|
||||
function saveProviders(list) {
|
||||
writeJSON(providersPath(), list);
|
||||
}
|
||||
|
||||
function upsertProvider(provider) {
|
||||
const list = getProviders();
|
||||
if (!provider.id) provider.id = crypto.randomUUID();
|
||||
const idx = list.findIndex((p) => p.id === provider.id);
|
||||
if (idx >= 0) list[idx] = { ...list[idx], ...provider };
|
||||
else list.push(provider);
|
||||
saveProviders(list);
|
||||
return provider;
|
||||
}
|
||||
|
||||
function deleteProvider(id) {
|
||||
saveProviders(getProviders().filter((p) => p.id !== id));
|
||||
}
|
||||
|
||||
function getConversationList() {
|
||||
const dir = conversationsDir();
|
||||
const files = fs.readdirSync(dir).filter((f) => f.endsWith('.json'));
|
||||
const items = files.map((f) => {
|
||||
try {
|
||||
const c = JSON.parse(fs.readFileSync(path.join(dir, f), 'utf8'));
|
||||
return {
|
||||
id: c.id,
|
||||
title: c.title,
|
||||
providerId: c.providerId,
|
||||
model: c.model,
|
||||
createdAt: c.createdAt,
|
||||
updatedAt: c.updatedAt,
|
||||
messageCount: (c.messages || []).length,
|
||||
};
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}).filter(Boolean);
|
||||
items.sort((a, b) => (b.updatedAt || 0) - (a.updatedAt || 0));
|
||||
return items;
|
||||
}
|
||||
|
||||
function getConversation(id) {
|
||||
const file = path.join(conversationsDir(), `${id}.json`);
|
||||
return readJSON(file, null);
|
||||
}
|
||||
|
||||
function saveConversation(conv) {
|
||||
if (!conv.id) conv.id = crypto.randomUUID();
|
||||
const now = Date.now();
|
||||
if (!conv.createdAt) conv.createdAt = now;
|
||||
conv.updatedAt = now;
|
||||
writeJSON(path.join(conversationsDir(), `${conv.id}.json`), conv);
|
||||
return conv;
|
||||
}
|
||||
|
||||
function deleteConversation(id) {
|
||||
const file = path.join(conversationsDir(), `${id}.json`);
|
||||
if (fs.existsSync(file)) fs.unlinkSync(file);
|
||||
}
|
||||
|
||||
function clearAllConversations() {
|
||||
const dir = conversationsDir();
|
||||
fs.readdirSync(dir).filter((f) => f.endsWith('.json')).forEach((f) => {
|
||||
fs.unlinkSync(path.join(dir, f));
|
||||
});
|
||||
}
|
||||
|
||||
function renameConversation(id, title) {
|
||||
const conv = getConversation(id);
|
||||
if (!conv) return null;
|
||||
conv.title = title;
|
||||
conv.updatedAt = Date.now();
|
||||
writeJSON(path.join(conversationsDir(), `${id}.json`), conv);
|
||||
return conv;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getProviders,
|
||||
upsertProvider,
|
||||
deleteProvider,
|
||||
getConversationList,
|
||||
getConversation,
|
||||
saveConversation,
|
||||
deleteConversation,
|
||||
clearAllConversations,
|
||||
renameConversation,
|
||||
};
|
||||
Reference in New Issue
Block a user