使用浏览器 localStorage(前端保存)
// openclaw-local-storage.js
class OpenClawLocalStorage {
constructor(namespace = 'openclaw') {
this.namespace = namespace;
}
// 保存会话
saveSession(sessionId, data) {
const sessions = this.getSessions();
sessions[sessionId] = {
...data,
updatedAt: new Date().toISOString(),
};
localStorage.setItem(`${this.namespace}_sessions`, JSON.stringify(sessions));
return sessionId;
}
// 获取所有会话
getSessions() {
const sessions = localStorage.getItem(`${this.namespace}_sessions`);
return sessions ? JSON.parse(sessions) : {};
}
// 获取单个会话
getSession(sessionId) {
const sessions = this.getSessions();
return sessions[sessionId] || null;
}
// 删除会话
deleteSession(sessionId) {
const sessions = this.getSessions();
delete sessions[sessionId];
localStorage.setItem(`${this.namespace}_sessions`, JSON.stringify(sessions));
}
// 导出数据
exportData() {
const data = {
sessions: this.getSessions(),
version: '1.0',
exportDate: new Date().toISOString(),
};
return JSON.stringify(data, null, 2);
}
// 导入数据
importData(jsonString) {
try {
const data = JSON.parse(jsonString);
if (data.sessions) {
const existing = this.getSessions();
const merged = { ...existing, ...data.sessions };
localStorage.setItem(`${this.namespace}_sessions`, JSON.stringify(merged));
return true;
}
return false;
} catch (error) {
console.error('导入数据失败:', error);
return false;
}
}
}
使用 IndexedDB(支持更大数据量)
// openclaw-indexeddb.js
class OpenClawIndexedDB {
constructor(dbName = 'OpenClawDB', version = 1) {
this.dbName = dbName;
this.version = version;
this.db = null;
}
// 初始化数据库
async init() {
return new Promise((resolve, reject) => {
const request = indexedDB.open(this.dbName, this.version);
request.onupgradeneeded = (event) => {
const db = event.target.result;
// 创建会话存储
if (!db.objectStoreNames.contains('sessions')) {
const sessionsStore = db.createObjectStore('sessions', { keyPath: 'id' });
sessionsStore.createIndex('updatedAt', 'updatedAt', { unique: false });
}
// 创建消息存储
if (!db.objectStoreNames.contains('messages')) {
const messagesStore = db.createObjectStore('messages', { keyPath: 'id', autoIncrement: true });
messagesStore.createIndex('sessionId', 'sessionId', { unique: false });
}
};
request.onsuccess = (event) => {
this.db = event.target.result;
resolve(this);
};
request.onerror = (event) => {
reject(event.target.error);
};
});
}
// 保存会话
async saveSession(session) {
return new Promise((resolve, reject) => {
const transaction = this.db.transaction(['sessions'], 'readwrite');
const store = transaction.objectStore('sessions');
const sessionData = {
...session,
id: session.id || Date.now().toString(),
updatedAt: new Date().toISOString(),
createdAt: session.createdAt || new Date().toISOString(),
};
const request = store.put(sessionData);
request.onsuccess = () => resolve(sessionData.id);
request.onerror = (event) => reject(event.target.error);
});
}
// 获取所有会话
async getAllSessions() {
return new Promise((resolve, reject) => {
const transaction = this.db.transaction(['sessions'], 'readonly');
const store = transaction.objectStore('sessions');
const request = store.getAll();
request.onsuccess = (event) => resolve(event.target.result);
request.onerror = (event) => reject(event.target.error);
});
}
// 保存消息
async saveMessage(sessionId, message) {
return new Promise((resolve, reject) => {
const transaction = this.db.transaction(['messages'], 'readwrite');
const store = transaction.objectStore('messages');
const messageData = {
...message,
sessionId,
timestamp: new Date().toISOString(),
};
const request = store.add(messageData);
request.onsuccess = () => resolve(request.result);
request.onerror = (event) => reject(event.target.error);
});
}
// 获取会话消息
async getSessionMessages(sessionId) {
return new Promise((resolve, reject) => {
const transaction = this.db.transaction(['messages'], 'readonly');
const store = transaction.objectStore('messages');
const index = store.index('sessionId');
const request = index.getAll(sessionId);
request.onsuccess = (event) => resolve(event.target.result);
request.onerror = (event) => reject(event.target.error);
});
}
}
保存到文件(Node.js 环境)
// openclaw-file-saver.js
const fs = require('fs');
const path = require('path');
class OpenClawFileSaver {
constructor(baseDir = './saves') {
this.baseDir = baseDir;
this.ensureDirExists();
}
ensureDirExists() {
if (!fs.existsSync(this.baseDir)) {
fs.mkdirSync(this.baseDir, { recursive: true });
}
}
// 保存会话到文件
saveSession(sessionId, data) {
const filename = path.join(this.baseDir, `${sessionId}.json`);
const sessionData = {
...data,
sessionId,
savedAt: new Date().toISOString(),
};
fs.writeFileSync(filename, JSON.stringify(sessionData, null, 2));
return filename;
}
// 加载会话
loadSession(sessionId) {
const filename = path.join(this.baseDir, `${sessionId}.json`);
if (fs.existsSync(filename)) {
const content = fs.readFileSync(filename, 'utf-8');
return JSON.parse(content);
}
return null;
}
// 列出所有保存的会话
listSessions() {
const files = fs.readdirSync(this.baseDir);
return files
.filter(file => file.endsWith('.json'))
.map(file => {
const filepath = path.join(this.baseDir, file);
const content = fs.readFileSync(filepath, 'utf-8');
return JSON.parse(content);
});
}
// 导出为单个文件
exportAll(outputPath = './openclaw_backup.json') {
const sessions = this.listSessions();
const exportData = {
sessions,
exportDate: new Date().toISOString(),
version: '1.0',
};
fs.writeFileSync(outputPath, JSON.stringify(exportData, null, 2));
return outputPath;
}
}
使用示例
// 示例:在前端使用 localStorage
const storage = new OpenClawLocalStorage();
// 保存会话
const sessionId = storage.saveSession('session-1', { 'OpenClaw 对话',
messages: [
{ role: 'user', content: '你好' },
{ role: 'assistant', content: '你好!我是OpenClaw助手' }
],
model: 'gpt-3.5-turbo',
temperature: 0.7
});
// 获取所有会话
const sessions = storage.getSessions();
// 导出数据
const exportData = storage.exportData();
// 导入数据
storage.importData(exportData);
自动保存功能
// openclaw-autosave.js
class OpenClawAutoSave {
constructor(storage, options = {}) {
this.storage = storage; // 可以是 localStorage 或 IndexedDB 实例
this.autoSaveInterval = options.autoSaveInterval || 30000; // 30秒
this.lastSaveTime = null;
this.isSaving = false;
this.queue = [];
if (options.autoSave) {
this.startAutoSave();
}
}
startAutoSave() {
this.autoSaveTimer = setInterval(() => {
this.saveQueuedData();
}, this.autoSaveInterval);
}
stopAutoSave() {
if (this.autoSaveTimer) {
clearInterval(this.autoSaveTimer);
}
}
queueSave(sessionId, data) {
this.queue.push({ sessionId, data });
}
async saveQueuedData() {
if (this.isSaving || this.queue.length === 0) return;
this.isSaving = true;
const items = [...this.queue];
this.queue = [];
try {
for (const item of items) {
await this.storage.saveSession(item.sessionId, item.data);
}
this.lastSaveTime = new Date();
console.log('自动保存完成', items.length, '个项目');
} catch (error) {
console.error('自动保存失败:', error);
} finally {
this.isSaving = false;
}
}
}
选择哪种方案取决于你的具体需求:

- localStorage:简单、快速,适合小数据量
- IndexedDB:适合大量数据,支持索引查询
- 文件保存:适合Node.js环境
需要我帮你集成到具体的项目中吗?
版权声明:除非特别标注,否则均为本站原创文章,转载时请以链接形式注明文章出处。