@semalt-ai/code 1.7.0 → 1.8.0

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/lib/storage.js ADDED
@@ -0,0 +1,96 @@
1
+ 'use strict';
2
+
3
+ const crypto = require('crypto');
4
+ const fs = require('fs');
5
+ const os = require('os');
6
+ const path = require('path');
7
+
8
+ const SESSIONS_DIR = path.join(os.homedir(), '.semalt-ai', 'sessions');
9
+
10
+ class SessionStorage {
11
+ constructor() {
12
+ fs.mkdirSync(SESSIONS_DIR, { recursive: true });
13
+ }
14
+
15
+ generateId() {
16
+ return crypto.randomBytes(4).toString('hex');
17
+ }
18
+
19
+ save(session) {
20
+ const filename = `${session.created_at}-${session.id}.json`;
21
+ fs.writeFileSync(path.join(SESSIONS_DIR, filename), JSON.stringify(session, null, 2));
22
+ }
23
+
24
+ list() {
25
+ let files;
26
+ try {
27
+ files = fs.readdirSync(SESSIONS_DIR).filter((f) => f.endsWith('.json'));
28
+ } catch {
29
+ return [];
30
+ }
31
+ const sessions = [];
32
+ for (const file of files) {
33
+ try {
34
+ const data = JSON.parse(fs.readFileSync(path.join(SESSIONS_DIR, file), 'utf8'));
35
+ sessions.push({
36
+ id: data.id,
37
+ created_at: data.created_at,
38
+ model: data.model,
39
+ message_count: Array.isArray(data.messages)
40
+ ? data.messages.filter((m) => m.role !== 'system').length
41
+ : 0,
42
+ });
43
+ } catch {
44
+ // skip corrupt files
45
+ }
46
+ }
47
+ return sessions.sort((a, b) => b.created_at - a.created_at);
48
+ }
49
+
50
+ _findFile(id) {
51
+ let files;
52
+ try {
53
+ files = fs.readdirSync(SESSIONS_DIR).filter((f) => f.endsWith('.json'));
54
+ } catch {
55
+ return null;
56
+ }
57
+ return files.find((f) => f.includes(id)) || null;
58
+ }
59
+
60
+ load(id) {
61
+ const file = this._findFile(id);
62
+ if (!file) return null;
63
+ try {
64
+ return JSON.parse(fs.readFileSync(path.join(SESSIONS_DIR, file), 'utf8'));
65
+ } catch {
66
+ return null;
67
+ }
68
+ }
69
+
70
+ delete(id) {
71
+ const file = this._findFile(id);
72
+ if (file) fs.unlinkSync(path.join(SESSIONS_DIR, file));
73
+ }
74
+
75
+ pruneOlderThan(days) {
76
+ const cutoff = Date.now() - days * 86400000;
77
+ let files;
78
+ try {
79
+ files = fs.readdirSync(SESSIONS_DIR).filter((f) => f.endsWith('.json'));
80
+ } catch {
81
+ return;
82
+ }
83
+ for (const file of files) {
84
+ try {
85
+ const data = JSON.parse(fs.readFileSync(path.join(SESSIONS_DIR, file), 'utf8'));
86
+ if (data.created_at < cutoff) {
87
+ fs.unlinkSync(path.join(SESSIONS_DIR, file));
88
+ }
89
+ } catch {
90
+ // skip
91
+ }
92
+ }
93
+ }
94
+ }
95
+
96
+ module.exports = { SessionStorage };