@t0ken.ai/memoryx-openclaw-plugin 1.0.8 → 1.1.1
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/README.md +6 -0
- package/dist/index.d.ts +1 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +94 -46
- package/openclaw.plugin.json +1 -1
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -35,6 +35,9 @@ Edit `~/.openclaw/openclaw.json`:
|
|
|
35
35
|
},
|
|
36
36
|
"memory-core": {
|
|
37
37
|
"enabled": false
|
|
38
|
+
},
|
|
39
|
+
"memory-lancedb": {
|
|
40
|
+
"enabled": false
|
|
38
41
|
}
|
|
39
42
|
}
|
|
40
43
|
}
|
|
@@ -58,6 +61,9 @@ For self-hosted MemoryX:
|
|
|
58
61
|
},
|
|
59
62
|
"memory-core": {
|
|
60
63
|
"enabled": false
|
|
64
|
+
},
|
|
65
|
+
"memory-lancedb": {
|
|
66
|
+
"enabled": false
|
|
61
67
|
}
|
|
62
68
|
}
|
|
63
69
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* MemoryX Realtime Plugin for OpenClaw
|
|
2
|
+
* MemoryX Realtime Plugin for OpenClaw
|
|
3
3
|
*
|
|
4
4
|
* Features:
|
|
5
5
|
* - ConversationBuffer with token counting
|
|
@@ -8,10 +8,6 @@
|
|
|
8
8
|
* - Sensitive data filtered on server
|
|
9
9
|
* - Configurable API base URL
|
|
10
10
|
* - Precise token counting with tiktoken
|
|
11
|
-
*
|
|
12
|
-
* Model Downloads (CDN):
|
|
13
|
-
* - INT8 Model (122MB, recommended): https://static.t0ken.ai/models/model_int8.onnx
|
|
14
|
-
* - FP32 Model (489MB): https://static.t0ken.ai/models/model.onnx
|
|
15
11
|
*/
|
|
16
12
|
interface PluginConfig {
|
|
17
13
|
apiBaseUrl?: string;
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAWH,UAAU,YAAY;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;AAUD,UAAU,OAAO;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACrB;AAED,UAAU,YAAY;IAClB,QAAQ,EAAE,KAAK,CAAC;QACZ,EAAE,EAAE,MAAM,CAAC;QACX,OAAO,EAAE,MAAM,CAAC;QAChB,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,EAAE,MAAM,CAAC;KACjB,CAAC,CAAC;IACH,SAAS,EAAE,OAAO,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;CACxB;AA6ED,cAAM,kBAAkB;IACpB,OAAO,CAAC,QAAQ,CAAiB;IACjC,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,QAAQ,CAAc;IAC9B,OAAO,CAAC,cAAc,CAAc;IACpC,OAAO,CAAC,SAAS,CAAsB;IACvC,OAAO,CAAC,cAAc,CAAsB;IAC5C,OAAO,CAAC,OAAO,CAAW;IAE1B,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAK;IACrC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAkB;IAC7C,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAQ;;IAO/C,OAAO,CAAC,UAAU;IAIlB,OAAO,CAAC,WAAW;IAInB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO;IA6BlD,WAAW,IAAI,OAAO;IAiBtB,KAAK,IAAI;QAAE,eAAe,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,OAAO,EAAE,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE;IAkB/E,UAAU,IAAI;QAAE,eAAe,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,OAAO,EAAE,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAO3F,SAAS,IAAI;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,cAAc,EAAE,MAAM,CAAA;KAAE;CAOpF;AAED,cAAM,aAAa;IACf,OAAO,CAAC,MAAM,CAMZ;IAEF,OAAO,CAAC,MAAM,CAAgD;IAC9D,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAS;IAC9C,OAAO,CAAC,YAAY,CAA6B;gBAErC,YAAY,CAAC,EAAE,YAAY;IAQvC,OAAO,KAAK,OAAO,GAElB;YAEa,IAAI;IAWlB,OAAO,CAAC,UAAU;IAWlB,OAAO,CAAC,UAAU;YAIJ,YAAY;IAgC1B,OAAO,CAAC,qBAAqB;IAa7B,OAAO,CAAC,eAAe;YAQT,iBAAiB;IAqClB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAyB1D,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,GAAE,MAAU,GAAG,OAAO,CAAC,YAAY,CAAC;IAoD/D,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC;IAKtC,SAAS,IAAI;QAChB,WAAW,EAAE,OAAO,CAAC;QACrB,SAAS,EAAE,OAAO,CAAC;QACnB,YAAY,EAAE;YAAE,YAAY,EAAE,MAAM,CAAC;YAAC,UAAU,EAAE,MAAM,CAAA;SAAE,CAAA;KAC7D;CAOJ;;;;;;kBAUiB,GAAG,iBAAiB,YAAY,GAAG,IAAI;;AANzD,wBAqEE;AAEF,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* MemoryX Realtime Plugin for OpenClaw
|
|
2
|
+
* MemoryX Realtime Plugin for OpenClaw
|
|
3
3
|
*
|
|
4
4
|
* Features:
|
|
5
5
|
* - ConversationBuffer with token counting
|
|
@@ -8,13 +8,80 @@
|
|
|
8
8
|
* - Sensitive data filtered on server
|
|
9
9
|
* - Configurable API base URL
|
|
10
10
|
* - Precise token counting with tiktoken
|
|
11
|
-
*
|
|
12
|
-
* Model Downloads (CDN):
|
|
13
|
-
* - INT8 Model (122MB, recommended): https://static.t0ken.ai/models/model_int8.onnx
|
|
14
|
-
* - FP32 Model (489MB): https://static.t0ken.ai/models/model.onnx
|
|
15
11
|
*/
|
|
16
12
|
import { getEncoding } from "js-tiktoken";
|
|
13
|
+
import * as fs from "fs";
|
|
14
|
+
import * as path from "path";
|
|
15
|
+
import * as os from "os";
|
|
16
|
+
import * as crypto from "crypto";
|
|
17
|
+
import Database from "better-sqlite3";
|
|
17
18
|
const DEFAULT_API_BASE = "https://t0ken.ai/api";
|
|
19
|
+
let db = null;
|
|
20
|
+
let dbPath = "";
|
|
21
|
+
function getDbPath() {
|
|
22
|
+
if (dbPath)
|
|
23
|
+
return dbPath;
|
|
24
|
+
const possiblePaths = [
|
|
25
|
+
path.join(process.cwd(), "memoryx.sqlite"),
|
|
26
|
+
path.join(os.homedir(), ".openclaw", "extensions", "memoryx-openclaw-plugin", "memoryx.sqlite"),
|
|
27
|
+
path.join(os.homedir(), ".t0ken", "memoryx.sqlite")
|
|
28
|
+
];
|
|
29
|
+
for (const p of possiblePaths) {
|
|
30
|
+
if (fs.existsSync(p)) {
|
|
31
|
+
dbPath = p;
|
|
32
|
+
return dbPath;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
dbPath = path.join(os.homedir(), ".openclaw", "extensions", "memoryx-openclaw-plugin", "memoryx.sqlite");
|
|
36
|
+
const dir = path.dirname(dbPath);
|
|
37
|
+
if (!fs.existsSync(dir)) {
|
|
38
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
39
|
+
}
|
|
40
|
+
return dbPath;
|
|
41
|
+
}
|
|
42
|
+
function initDb() {
|
|
43
|
+
const dbFile = getDbPath();
|
|
44
|
+
const database = new Database(dbFile);
|
|
45
|
+
database.exec(`
|
|
46
|
+
CREATE TABLE IF NOT EXISTS config (
|
|
47
|
+
key TEXT PRIMARY KEY,
|
|
48
|
+
value TEXT
|
|
49
|
+
)
|
|
50
|
+
`);
|
|
51
|
+
return database;
|
|
52
|
+
}
|
|
53
|
+
function getDb() {
|
|
54
|
+
if (!db) {
|
|
55
|
+
db = initDb();
|
|
56
|
+
}
|
|
57
|
+
return db;
|
|
58
|
+
}
|
|
59
|
+
class SQLiteStorage {
|
|
60
|
+
static load() {
|
|
61
|
+
try {
|
|
62
|
+
const database = getDb();
|
|
63
|
+
const row = database.prepare("SELECT value FROM config WHERE key = 'config'").get();
|
|
64
|
+
if (row) {
|
|
65
|
+
return JSON.parse(row.value);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
catch (e) {
|
|
69
|
+
console.warn("[MemoryX] Failed to load config:", e);
|
|
70
|
+
}
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
static save(config) {
|
|
74
|
+
try {
|
|
75
|
+
const database = getDb();
|
|
76
|
+
database.prepare(`
|
|
77
|
+
INSERT OR REPLACE INTO config (key, value) VALUES ('config', ?)
|
|
78
|
+
`).run(JSON.stringify(config));
|
|
79
|
+
}
|
|
80
|
+
catch (e) {
|
|
81
|
+
console.warn("[MemoryX] Failed to save config:", e);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
18
85
|
class ConversationBuffer {
|
|
19
86
|
messages = [];
|
|
20
87
|
tokenCount = 0;
|
|
@@ -125,40 +192,29 @@ class MemoryXPlugin {
|
|
|
125
192
|
return this.config.apiBaseUrl || DEFAULT_API_BASE;
|
|
126
193
|
}
|
|
127
194
|
async init() {
|
|
128
|
-
|
|
195
|
+
this.loadConfig();
|
|
129
196
|
if (!this.config.apiKey) {
|
|
130
197
|
await this.autoRegister();
|
|
131
198
|
}
|
|
132
199
|
this.startFlushTimer();
|
|
133
200
|
this.config.initialized = true;
|
|
134
201
|
}
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
apiBaseUrl: storedConfig.apiBaseUrl || this.config.apiBaseUrl
|
|
144
|
-
};
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
catch (e) {
|
|
148
|
-
console.warn("[MemoryX] Failed to load config:", e);
|
|
202
|
+
loadConfig() {
|
|
203
|
+
const stored = SQLiteStorage.load();
|
|
204
|
+
if (stored) {
|
|
205
|
+
this.config = {
|
|
206
|
+
...this.config,
|
|
207
|
+
...stored,
|
|
208
|
+
apiBaseUrl: this.pluginConfig?.apiBaseUrl || stored.apiBaseUrl || this.config.apiBaseUrl
|
|
209
|
+
};
|
|
149
210
|
}
|
|
150
211
|
}
|
|
151
212
|
saveConfig() {
|
|
152
|
-
|
|
153
|
-
localStorage.setItem("memoryx_config", JSON.stringify(this.config));
|
|
154
|
-
}
|
|
155
|
-
catch (e) {
|
|
156
|
-
console.warn("[MemoryX] Failed to save config:", e);
|
|
157
|
-
}
|
|
213
|
+
SQLiteStorage.save(this.config);
|
|
158
214
|
}
|
|
159
215
|
async autoRegister() {
|
|
160
216
|
try {
|
|
161
|
-
const fingerprint =
|
|
217
|
+
const fingerprint = this.getMachineFingerprint();
|
|
162
218
|
const response = await fetch(`${this.apiBase}/agents/auto-register`, {
|
|
163
219
|
method: "POST",
|
|
164
220
|
headers: { "Content-Type": "application/json" },
|
|
@@ -166,8 +222,8 @@ class MemoryXPlugin {
|
|
|
166
222
|
machine_fingerprint: fingerprint,
|
|
167
223
|
agent_type: "openclaw",
|
|
168
224
|
agent_name: "openclaw-agent",
|
|
169
|
-
platform:
|
|
170
|
-
platform_version:
|
|
225
|
+
platform: os.platform(),
|
|
226
|
+
platform_version: os.release()
|
|
171
227
|
})
|
|
172
228
|
});
|
|
173
229
|
if (!response.ok) {
|
|
@@ -184,21 +240,16 @@ class MemoryXPlugin {
|
|
|
184
240
|
console.error("[MemoryX] Auto-register failed:", e);
|
|
185
241
|
}
|
|
186
242
|
}
|
|
187
|
-
|
|
243
|
+
getMachineFingerprint() {
|
|
188
244
|
const components = [
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
new Date().getTimezoneOffset()
|
|
245
|
+
os.hostname(),
|
|
246
|
+
os.platform(),
|
|
247
|
+
os.arch(),
|
|
248
|
+
os.cpus()[0]?.model || "unknown",
|
|
249
|
+
os.totalmem()
|
|
195
250
|
];
|
|
196
251
|
const raw = components.join("|");
|
|
197
|
-
|
|
198
|
-
const data = encoder.encode(raw);
|
|
199
|
-
const hashBuffer = await crypto.subtle.digest("SHA-256", data);
|
|
200
|
-
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
|
201
|
-
return hashArray.slice(0, 32).map(b => b.toString(16).padStart(2, "0")).join("");
|
|
252
|
+
return crypto.createHash("sha256").update(raw).digest("hex").slice(0, 32);
|
|
202
253
|
}
|
|
203
254
|
startFlushTimer() {
|
|
204
255
|
this.flushTimer = setInterval(() => {
|
|
@@ -323,17 +374,14 @@ let plugin;
|
|
|
323
374
|
export default {
|
|
324
375
|
id: "memoryx-openclaw-plugin",
|
|
325
376
|
name: "MemoryX Real-time Plugin",
|
|
326
|
-
version: "1.
|
|
377
|
+
version: "1.1.1",
|
|
327
378
|
description: "Real-time memory capture and recall for OpenClaw",
|
|
328
379
|
register(api, pluginConfig) {
|
|
329
380
|
api.logger.info("[MemoryX] Plugin registering...");
|
|
330
381
|
if (pluginConfig?.apiBaseUrl) {
|
|
331
382
|
api.logger.info(`[MemoryX] API Base: \`${pluginConfig.apiBaseUrl}\``);
|
|
332
383
|
}
|
|
333
|
-
|
|
334
|
-
if (storedConfig) {
|
|
335
|
-
api.logger.info(`[MemoryX] Database: ${storedConfig.split('"apiBaseUrl"')[0].match(/"([^"]+)"/)?.[1] || 'unknown'}`);
|
|
336
|
-
}
|
|
384
|
+
api.logger.info(`[MemoryX] Database: ${getDbPath()}`);
|
|
337
385
|
plugin = new MemoryXPlugin(pluginConfig);
|
|
338
386
|
api.on("message_received", async (event, ctx) => {
|
|
339
387
|
const { content, from, timestamp } = event;
|
package/openclaw.plugin.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@t0ken.ai/memoryx-openclaw-plugin",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "MemoryX real-time memory capture and recall plugin for OpenClaw",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "MemoryX Team",
|
|
@@ -29,11 +29,13 @@
|
|
|
29
29
|
"extensions": ["./dist/index.js"]
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
|
+
"@types/better-sqlite3": "^7.6.0",
|
|
32
33
|
"@types/node": "^20.0.0",
|
|
33
34
|
"typescript": "^5.0.0"
|
|
34
35
|
},
|
|
35
36
|
"dependencies": {
|
|
36
37
|
"@huggingface/transformers": "^3.8.1",
|
|
38
|
+
"better-sqlite3": "^11.0.0",
|
|
37
39
|
"js-tiktoken": "^1.0.21",
|
|
38
40
|
"onnxruntime-node": "^1.24.1",
|
|
39
41
|
"onnxruntime-web": "^1.24.1"
|