clawsocial-plugin 1.6.5 → 1.6.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/store.ts +121 -11
- package/src/tools/match.ts +0 -1
package/package.json
CHANGED
package/src/store.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
|
+
import os from "node:os";
|
|
2
3
|
import path from "node:path";
|
|
3
4
|
|
|
4
5
|
let _stateDir: string | null = null;
|
|
@@ -78,12 +79,26 @@ function settingsFile(): string {
|
|
|
78
79
|
}
|
|
79
80
|
|
|
80
81
|
export function getSettings(): Settings {
|
|
81
|
-
|
|
82
|
+
const s = readJSON<Partial<Settings>>(settingsFile(), {});
|
|
83
|
+
if (Object.keys(s).length === 0) {
|
|
84
|
+
const agentId = getState().agent_id;
|
|
85
|
+
if (agentId) {
|
|
86
|
+
const backup = backupRead<Partial<Settings>>(agentId, "settings.json", {});
|
|
87
|
+
if (Object.keys(backup).length > 0) {
|
|
88
|
+
writeJSON(settingsFile(), backup);
|
|
89
|
+
return { ...DEFAULT_SETTINGS, ...backup };
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return { ...DEFAULT_SETTINGS, ...s };
|
|
82
94
|
}
|
|
83
95
|
|
|
84
96
|
export function setSettings(data: Partial<Settings>): void {
|
|
85
97
|
const s = getSettings();
|
|
86
|
-
|
|
98
|
+
const merged = { ...s, ...data };
|
|
99
|
+
writeJSON(settingsFile(), merged);
|
|
100
|
+
const agentId = readJSON<AgentState>(stateFile(), {}).agent_id;
|
|
101
|
+
if (agentId) backupWrite(agentId, "settings.json", merged);
|
|
87
102
|
}
|
|
88
103
|
|
|
89
104
|
// ── Agent state ─────────────────────────────────────────────────────
|
|
@@ -100,17 +115,34 @@ export type AgentState = {
|
|
|
100
115
|
// ── Sessions ────────────────────────────────────────────────────────
|
|
101
116
|
|
|
102
117
|
export function getSessions(): SessionsMap {
|
|
103
|
-
|
|
118
|
+
const sessions = readJSON<SessionsMap>(sessionsFile(), {});
|
|
119
|
+
if (Object.keys(sessions).length === 0) {
|
|
120
|
+
const agentId = getState().agent_id;
|
|
121
|
+
if (agentId) {
|
|
122
|
+
const backup = backupRead<SessionsMap>(agentId, "sessions.json", {});
|
|
123
|
+
if (Object.keys(backup).length > 0) {
|
|
124
|
+
writeJSON(sessionsFile(), backup);
|
|
125
|
+
return backup;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return sessions;
|
|
104
130
|
}
|
|
105
131
|
|
|
106
132
|
export function getSession(id: string): LocalSession | null {
|
|
107
133
|
return getSessions()[id] ?? null;
|
|
108
134
|
}
|
|
109
135
|
|
|
136
|
+
function writeSessions(sessions: SessionsMap): void {
|
|
137
|
+
writeJSON(sessionsFile(), sessions);
|
|
138
|
+
const agentId = readJSON<AgentState>(stateFile(), {}).agent_id;
|
|
139
|
+
if (agentId) backupWrite(agentId, "sessions.json", sessions);
|
|
140
|
+
}
|
|
141
|
+
|
|
110
142
|
export function upsertSession(id: string, data: Partial<LocalSession>): LocalSession {
|
|
111
143
|
const sessions = getSessions();
|
|
112
144
|
sessions[id] = { ...(sessions[id] ?? { id, messages: [], unread: 0 }), ...data, id };
|
|
113
|
-
|
|
145
|
+
writeSessions(sessions);
|
|
114
146
|
return sessions[id];
|
|
115
147
|
}
|
|
116
148
|
|
|
@@ -126,26 +158,91 @@ export function addMessage(sessionId: string, msg: LocalMessage): void {
|
|
|
126
158
|
sessions[sessionId].unread = (sessions[sessionId].unread ?? 0) + 1;
|
|
127
159
|
}
|
|
128
160
|
sessions[sessionId].updated_at = Math.floor(Date.now() / 1000);
|
|
129
|
-
|
|
161
|
+
writeSessions(sessions);
|
|
130
162
|
}
|
|
131
163
|
|
|
132
164
|
export function markRead(sessionId: string): void {
|
|
133
165
|
const sessions = getSessions();
|
|
134
166
|
if (sessions[sessionId]) {
|
|
135
167
|
sessions[sessionId].unread = 0;
|
|
136
|
-
|
|
168
|
+
writeSessions(sessions);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// ── Backup (survives plugin/OpenClaw reinstall) ─────────────────────
|
|
173
|
+
// Backup layout:
|
|
174
|
+
// ~/.clawsocial/
|
|
175
|
+
// last_active ← agent_id of most recently used account
|
|
176
|
+
// <agent_id>/
|
|
177
|
+
// credentials.json
|
|
178
|
+
// sessions.json
|
|
179
|
+
// settings.json
|
|
180
|
+
// contacts.json
|
|
181
|
+
|
|
182
|
+
const BACKUP_ROOT = path.join(os.homedir(), ".clawsocial");
|
|
183
|
+
|
|
184
|
+
function backupDir(agentId: string): string {
|
|
185
|
+
return path.join(BACKUP_ROOT, agentId);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function backupWrite(agentId: string, name: string, data: unknown): void {
|
|
189
|
+
try {
|
|
190
|
+
const dir = backupDir(agentId);
|
|
191
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
192
|
+
writeJSON(path.join(dir, name), data);
|
|
193
|
+
// Update last_active marker
|
|
194
|
+
fs.writeFileSync(path.join(BACKUP_ROOT, "last_active"), agentId);
|
|
195
|
+
} catch {
|
|
196
|
+
// best-effort backup, don't fail if write fails
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function backupRead<T>(agentId: string, name: string, fallback: T): T {
|
|
201
|
+
try {
|
|
202
|
+
return readJSON<T>(path.join(backupDir(agentId), name), fallback);
|
|
203
|
+
} catch {
|
|
204
|
+
return fallback;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
function getLastActiveAgentId(): string | null {
|
|
209
|
+
try {
|
|
210
|
+
return fs.readFileSync(path.join(BACKUP_ROOT, "last_active"), "utf8").trim() || null;
|
|
211
|
+
} catch {
|
|
212
|
+
return null;
|
|
137
213
|
}
|
|
138
214
|
}
|
|
139
215
|
|
|
140
216
|
// ── Agent state ─────────────────────────────────────────────────────
|
|
141
217
|
|
|
142
218
|
export function getState(): AgentState {
|
|
143
|
-
|
|
219
|
+
const state = readJSON<AgentState>(stateFile(), {});
|
|
220
|
+
if (!state.agent_id || !state.api_key) {
|
|
221
|
+
// Try restoring from backup using last_active agent
|
|
222
|
+
const lastId = getLastActiveAgentId();
|
|
223
|
+
if (lastId) {
|
|
224
|
+
const backup = backupRead<AgentState>(lastId, "credentials.json", {});
|
|
225
|
+
if (backup.agent_id && backup.api_key) {
|
|
226
|
+
writeJSON(stateFile(), backup);
|
|
227
|
+
return backup;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
return state;
|
|
144
232
|
}
|
|
145
233
|
|
|
146
234
|
export function setState(data: Partial<AgentState>): void {
|
|
147
235
|
const s = getState();
|
|
148
|
-
|
|
236
|
+
const merged = { ...s, ...data };
|
|
237
|
+
writeJSON(stateFile(), merged);
|
|
238
|
+
if (merged.agent_id && merged.api_key) {
|
|
239
|
+
backupWrite(merged.agent_id, "credentials.json", {
|
|
240
|
+
agent_id: merged.agent_id,
|
|
241
|
+
api_key: merged.api_key,
|
|
242
|
+
public_name: merged.public_name,
|
|
243
|
+
lang: merged.lang,
|
|
244
|
+
});
|
|
245
|
+
}
|
|
149
246
|
}
|
|
150
247
|
|
|
151
248
|
// ── Contacts ─────────────────────────────────────────────────────────
|
|
@@ -166,10 +263,20 @@ function contactsFile(): string {
|
|
|
166
263
|
export function readContacts(): Contact[] {
|
|
167
264
|
try {
|
|
168
265
|
const data = JSON.parse(fs.readFileSync(contactsFile(), "utf8"));
|
|
169
|
-
|
|
266
|
+
if (Array.isArray(data?.contacts) && data.contacts.length > 0) return data.contacts;
|
|
170
267
|
} catch {
|
|
171
|
-
|
|
268
|
+
// fall through to backup
|
|
269
|
+
}
|
|
270
|
+
const agentId = getState().agent_id;
|
|
271
|
+
if (agentId) {
|
|
272
|
+
const backup = backupRead<{ contacts?: Contact[] }>(agentId, "contacts.json", {});
|
|
273
|
+
if (Array.isArray(backup?.contacts) && backup.contacts.length > 0) {
|
|
274
|
+
fs.mkdirSync(path.dirname(contactsFile()), { recursive: true });
|
|
275
|
+
fs.writeFileSync(contactsFile(), JSON.stringify({ contacts: backup.contacts }, null, 2));
|
|
276
|
+
return backup.contacts;
|
|
277
|
+
}
|
|
172
278
|
}
|
|
279
|
+
return [];
|
|
173
280
|
}
|
|
174
281
|
|
|
175
282
|
export function upsertContact(contact: Omit<Contact, "added_at"> & { added_at?: number }): void {
|
|
@@ -181,7 +288,10 @@ export function upsertContact(contact: Omit<Contact, "added_at"> & { added_at?:
|
|
|
181
288
|
} else {
|
|
182
289
|
contacts.push(entry);
|
|
183
290
|
}
|
|
184
|
-
|
|
291
|
+
const data = { contacts };
|
|
292
|
+
fs.writeFileSync(contactsFile(), JSON.stringify(data, null, 2));
|
|
293
|
+
const agentId = readJSON<AgentState>(stateFile(), {}).agent_id;
|
|
294
|
+
if (agentId) backupWrite(agentId, "contacts.json", data);
|
|
185
295
|
}
|
|
186
296
|
|
|
187
297
|
export function lookupContactByName(name: string): Contact[] {
|
package/src/tools/match.ts
CHANGED
|
@@ -41,7 +41,6 @@ export function createMatchTool(): AnyAgentTool {
|
|
|
41
41
|
public_name: c.public_name,
|
|
42
42
|
topic_tags: c.topic_tags,
|
|
43
43
|
match_score: Math.round(c.match_score * 100) + "%",
|
|
44
|
-
availability: c.availability,
|
|
45
44
|
completeness: Math.round((c.completeness_score ?? 0.1) * 100) + "%",
|
|
46
45
|
...(c.manual_intro ? { manual_intro: c.manual_intro } : {}),
|
|
47
46
|
...(c.auto_bio ? { auto_bio: c.auto_bio } : {}),
|