@memtensor/memos-cloud-openclaw-plugin 0.1.8 → 0.1.10-beta.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/LICENSE +201 -201
- package/README.md +175 -155
- package/README_ZH.md +180 -161
- package/clawdbot.plugin.json +6 -1
- package/index.js +478 -285
- package/lib/check-update.js +270 -0
- package/lib/memos-cloud-api.js +573 -449
- package/moltbot.plugin.json +6 -1
- package/openclaw.plugin.json +6 -1
- package/package.json +46 -46
- package/scripts/sync-version.js +45 -45
- package/test/query-strip.test.mjs +152 -0
package/moltbot.plugin.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"id": "memos-cloud-openclaw-plugin",
|
|
3
3
|
"name": "MemOS Cloud OpenClaw Plugin",
|
|
4
4
|
"description": "MemOS Cloud recall + add memory via lifecycle hooks",
|
|
5
|
-
"version": "0.1.
|
|
5
|
+
"version": "0.1.10-beta.0",
|
|
6
6
|
"kind": "lifecycle",
|
|
7
7
|
"main": "./index.js",
|
|
8
8
|
"configSchema": {
|
|
@@ -78,6 +78,11 @@
|
|
|
78
78
|
"description": "Max chars per message when adding",
|
|
79
79
|
"default": 20000
|
|
80
80
|
},
|
|
81
|
+
"maxItemChars": {
|
|
82
|
+
"type": "integer",
|
|
83
|
+
"description": "Max chars per memory item when injecting prompt",
|
|
84
|
+
"default": 8000
|
|
85
|
+
},
|
|
81
86
|
"includeAssistant": {
|
|
82
87
|
"type": "boolean",
|
|
83
88
|
"default": true
|
package/openclaw.plugin.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"id": "memos-cloud-openclaw-plugin",
|
|
3
3
|
"name": "MemOS Cloud OpenClaw Plugin",
|
|
4
4
|
"description": "MemOS Cloud recall + add memory via lifecycle hooks",
|
|
5
|
-
"version": "0.1.
|
|
5
|
+
"version": "0.1.10-beta.0",
|
|
6
6
|
"kind": "lifecycle",
|
|
7
7
|
"main": "./index.js",
|
|
8
8
|
"configSchema": {
|
|
@@ -78,6 +78,11 @@
|
|
|
78
78
|
"description": "Max chars per message when adding",
|
|
79
79
|
"default": 20000
|
|
80
80
|
},
|
|
81
|
+
"maxItemChars": {
|
|
82
|
+
"type": "integer",
|
|
83
|
+
"description": "Max chars per memory item when injecting prompt",
|
|
84
|
+
"default": 8000
|
|
85
|
+
},
|
|
81
86
|
"includeAssistant": {
|
|
82
87
|
"type": "boolean",
|
|
83
88
|
"default": true
|
package/package.json
CHANGED
|
@@ -1,46 +1,46 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@memtensor/memos-cloud-openclaw-plugin",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "OpenClaw lifecycle plugin for MemOS Cloud (add + recall memory)",
|
|
5
|
-
"scripts": {
|
|
6
|
-
"sync-version": "node scripts/sync-version.js",
|
|
7
|
-
"version": "npm run sync-version && git add openclaw.plugin.json moltbot.plugin.json clawdbot.plugin.json",
|
|
8
|
-
"publish-beta": "npm publish --tag beta",
|
|
9
|
-
"publish-beta-patch": "npm version prepatch --preid=beta && npm publish --tag beta",
|
|
10
|
-
"publish-latest": "npm version $(node -p \"require('./package.json').version.split('-')[0]\") && npm publish",
|
|
11
|
-
"publish-latest-patch": "npm version patch && npm publish"
|
|
12
|
-
},
|
|
13
|
-
"keywords": [
|
|
14
|
-
"memos",
|
|
15
|
-
"memos-cloud",
|
|
16
|
-
"openclaw",
|
|
17
|
-
"plugin",
|
|
18
|
-
"memory"
|
|
19
|
-
],
|
|
20
|
-
"homepage": "https://github.com/MemTensor/MemOS-Cloud-OpenClaw-Plugin#readme",
|
|
21
|
-
"bugs": {
|
|
22
|
-
"url": "https://github.com/MemTensor/MemOS-Cloud-OpenClaw-Plugin/issues"
|
|
23
|
-
},
|
|
24
|
-
"repository": {
|
|
25
|
-
"type": "git",
|
|
26
|
-
"url": "git+https://github.com/MemTensor/MemOS-Cloud-OpenClaw-Plugin.git"
|
|
27
|
-
},
|
|
28
|
-
"type": "module",
|
|
29
|
-
"author": "MemTensor",
|
|
30
|
-
"license": "MIT",
|
|
31
|
-
"openclaw": {
|
|
32
|
-
"extensions": [
|
|
33
|
-
"./index.js"
|
|
34
|
-
]
|
|
35
|
-
},
|
|
36
|
-
"clawdbot": {
|
|
37
|
-
"extensions": [
|
|
38
|
-
"./index.js"
|
|
39
|
-
]
|
|
40
|
-
},
|
|
41
|
-
"moltbot": {
|
|
42
|
-
"extensions": [
|
|
43
|
-
"./index.js"
|
|
44
|
-
]
|
|
45
|
-
}
|
|
46
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@memtensor/memos-cloud-openclaw-plugin",
|
|
3
|
+
"version": "0.1.10-beta.0",
|
|
4
|
+
"description": "OpenClaw lifecycle plugin for MemOS Cloud (add + recall memory)",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"sync-version": "node scripts/sync-version.js",
|
|
7
|
+
"version": "npm run sync-version && git add openclaw.plugin.json moltbot.plugin.json clawdbot.plugin.json",
|
|
8
|
+
"publish-beta": "npm publish --tag beta",
|
|
9
|
+
"publish-beta-patch": "npm version prepatch --preid=beta && npm publish --tag beta",
|
|
10
|
+
"publish-latest": "npm version $(node -p \"require('./package.json').version.split('-')[0]\") && npm publish",
|
|
11
|
+
"publish-latest-patch": "npm version patch && npm publish"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"memos",
|
|
15
|
+
"memos-cloud",
|
|
16
|
+
"openclaw",
|
|
17
|
+
"plugin",
|
|
18
|
+
"memory"
|
|
19
|
+
],
|
|
20
|
+
"homepage": "https://github.com/MemTensor/MemOS-Cloud-OpenClaw-Plugin#readme",
|
|
21
|
+
"bugs": {
|
|
22
|
+
"url": "https://github.com/MemTensor/MemOS-Cloud-OpenClaw-Plugin/issues"
|
|
23
|
+
},
|
|
24
|
+
"repository": {
|
|
25
|
+
"type": "git",
|
|
26
|
+
"url": "git+https://github.com/MemTensor/MemOS-Cloud-OpenClaw-Plugin.git"
|
|
27
|
+
},
|
|
28
|
+
"type": "module",
|
|
29
|
+
"author": "MemTensor",
|
|
30
|
+
"license": "MIT",
|
|
31
|
+
"openclaw": {
|
|
32
|
+
"extensions": [
|
|
33
|
+
"./index.js"
|
|
34
|
+
]
|
|
35
|
+
},
|
|
36
|
+
"clawdbot": {
|
|
37
|
+
"extensions": [
|
|
38
|
+
"./index.js"
|
|
39
|
+
]
|
|
40
|
+
},
|
|
41
|
+
"moltbot": {
|
|
42
|
+
"extensions": [
|
|
43
|
+
"./index.js"
|
|
44
|
+
]
|
|
45
|
+
}
|
|
46
|
+
}
|
package/scripts/sync-version.js
CHANGED
|
@@ -1,45 +1,45 @@
|
|
|
1
|
-
import fs from 'fs';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
import { fileURLToPath } from 'url';
|
|
4
|
-
|
|
5
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
6
|
-
const __dirname = path.dirname(__filename);
|
|
7
|
-
|
|
8
|
-
// Read the updated package.json to get the new version
|
|
9
|
-
const packageJsonPath = path.resolve(__dirname, '../package.json');
|
|
10
|
-
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
11
|
-
const newVersion = packageJson.version;
|
|
12
|
-
|
|
13
|
-
console.log(`Syncing version to ${newVersion}...`);
|
|
14
|
-
|
|
15
|
-
const filesToUpdate = [
|
|
16
|
-
'openclaw.plugin.json',
|
|
17
|
-
'moltbot.plugin.json',
|
|
18
|
-
'clawdbot.plugin.json'
|
|
19
|
-
];
|
|
20
|
-
|
|
21
|
-
filesToUpdate.forEach(fileName => {
|
|
22
|
-
const filePath = path.resolve(__dirname, '..', fileName);
|
|
23
|
-
|
|
24
|
-
if (fs.existsSync(filePath)) {
|
|
25
|
-
try {
|
|
26
|
-
const content = JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
|
27
|
-
|
|
28
|
-
if (content.version !== newVersion) {
|
|
29
|
-
content.version = newVersion;
|
|
30
|
-
// Write back with 2 spaces indentation and a newline at the end
|
|
31
|
-
fs.writeFileSync(filePath, JSON.stringify(content, null, 2) + '\n', 'utf8');
|
|
32
|
-
console.log(`Updated ${fileName} to version ${newVersion}`);
|
|
33
|
-
} else {
|
|
34
|
-
console.log(`${fileName} is already at version ${newVersion}`);
|
|
35
|
-
}
|
|
36
|
-
} catch (error) {
|
|
37
|
-
console.error(`Error updating ${fileName}:`, error.message);
|
|
38
|
-
process.exit(1);
|
|
39
|
-
}
|
|
40
|
-
} else {
|
|
41
|
-
console.warn(`Warning: ${fileName} not found, skipping.`);
|
|
42
|
-
}
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
console.log('Version sync complete.');
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
|
|
5
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
6
|
+
const __dirname = path.dirname(__filename);
|
|
7
|
+
|
|
8
|
+
// Read the updated package.json to get the new version
|
|
9
|
+
const packageJsonPath = path.resolve(__dirname, '../package.json');
|
|
10
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
11
|
+
const newVersion = packageJson.version;
|
|
12
|
+
|
|
13
|
+
console.log(`Syncing version to ${newVersion}...`);
|
|
14
|
+
|
|
15
|
+
const filesToUpdate = [
|
|
16
|
+
'openclaw.plugin.json',
|
|
17
|
+
'moltbot.plugin.json',
|
|
18
|
+
'clawdbot.plugin.json'
|
|
19
|
+
];
|
|
20
|
+
|
|
21
|
+
filesToUpdate.forEach(fileName => {
|
|
22
|
+
const filePath = path.resolve(__dirname, '..', fileName);
|
|
23
|
+
|
|
24
|
+
if (fs.existsSync(filePath)) {
|
|
25
|
+
try {
|
|
26
|
+
const content = JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
|
27
|
+
|
|
28
|
+
if (content.version !== newVersion) {
|
|
29
|
+
content.version = newVersion;
|
|
30
|
+
// Write back with 2 spaces indentation and a newline at the end
|
|
31
|
+
fs.writeFileSync(filePath, JSON.stringify(content, null, 2) + '\n', 'utf8');
|
|
32
|
+
console.log(`Updated ${fileName} to version ${newVersion}`);
|
|
33
|
+
} else {
|
|
34
|
+
console.log(`${fileName} is already at version ${newVersion}`);
|
|
35
|
+
}
|
|
36
|
+
} catch (error) {
|
|
37
|
+
console.error(`Error updating ${fileName}:`, error.message);
|
|
38
|
+
process.exit(1);
|
|
39
|
+
}
|
|
40
|
+
} else {
|
|
41
|
+
console.warn(`Warning: ${fileName} not found, skipping.`);
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
console.log('Version sync complete.');
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import test from "node:test";
|
|
2
|
+
import assert from "node:assert/strict";
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
USER_QUERY_MARKER,
|
|
6
|
+
stripOpenClawInjectedPrefix,
|
|
7
|
+
} from "../lib/memos-cloud-api.js";
|
|
8
|
+
|
|
9
|
+
test("leaves plain user text unchanged", () => {
|
|
10
|
+
assert.equal(stripOpenClawInjectedPrefix("直接就是用户问题"), "直接就是用户问题");
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
test("strips MemOS recall marker and keeps original query", () => {
|
|
14
|
+
const input = `<memories>\n <facts>\n </facts>\n</memories>\n\n${USER_QUERY_MARKER}真正的问题`;
|
|
15
|
+
assert.equal(stripOpenClawInjectedPrefix(input), "真正的问题");
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
test("strips OpenClaw inbound metadata prefix blocks", () => {
|
|
19
|
+
const input = [
|
|
20
|
+
"Conversation info (untrusted metadata):",
|
|
21
|
+
"```json",
|
|
22
|
+
'{"message_id":"123"}',
|
|
23
|
+
"```",
|
|
24
|
+
"",
|
|
25
|
+
"Sender (untrusted metadata):",
|
|
26
|
+
"```json",
|
|
27
|
+
'{"label":"Aurora"}',
|
|
28
|
+
"```",
|
|
29
|
+
"",
|
|
30
|
+
"帮我看下这个问题",
|
|
31
|
+
].join("\n");
|
|
32
|
+
|
|
33
|
+
assert.equal(stripOpenClawInjectedPrefix(input), "帮我看下这个问题");
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
test("strips recall marker and inbound metadata together", () => {
|
|
37
|
+
const input = [
|
|
38
|
+
"<memories>",
|
|
39
|
+
" <facts>",
|
|
40
|
+
" </facts>",
|
|
41
|
+
"</memories>",
|
|
42
|
+
"",
|
|
43
|
+
`${USER_QUERY_MARKER}Conversation info (untrusted metadata):`,
|
|
44
|
+
"```json",
|
|
45
|
+
'{"message_id":"123","history_count":1}',
|
|
46
|
+
"```",
|
|
47
|
+
"",
|
|
48
|
+
"Chat history since last reply (untrusted, for context):",
|
|
49
|
+
"```json",
|
|
50
|
+
'[{"sender":"Aurora","body":"上一条"}]',
|
|
51
|
+
"```",
|
|
52
|
+
"",
|
|
53
|
+
"继续",
|
|
54
|
+
].join("\n");
|
|
55
|
+
|
|
56
|
+
assert.equal(stripOpenClawInjectedPrefix(input), "继续");
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
test("keeps content when metadata block is malformed", () => {
|
|
60
|
+
const input = [
|
|
61
|
+
"Conversation info (untrusted metadata):",
|
|
62
|
+
"not-a-json-fence",
|
|
63
|
+
"真正的问题",
|
|
64
|
+
].join("\n");
|
|
65
|
+
|
|
66
|
+
assert.equal(stripOpenClawInjectedPrefix(input), input);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
test("keeps content unchanged when sentinel appears in normal body", () => {
|
|
70
|
+
const input = [
|
|
71
|
+
"请原样解释下面这段文本:",
|
|
72
|
+
"Conversation info (untrusted metadata):",
|
|
73
|
+
"```json",
|
|
74
|
+
'{"message_id":"123"}',
|
|
75
|
+
"```",
|
|
76
|
+
].join("\n");
|
|
77
|
+
|
|
78
|
+
assert.equal(stripOpenClawInjectedPrefix(input), input);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
test("strips valid prefix even if body starts with a sentinel-like line", () => {
|
|
82
|
+
const input = [
|
|
83
|
+
"Sender (untrusted metadata):",
|
|
84
|
+
"```json",
|
|
85
|
+
'{"label":"Aurora"}',
|
|
86
|
+
"```",
|
|
87
|
+
"",
|
|
88
|
+
"Sender (untrusted metadata):",
|
|
89
|
+
"这行是正文,不是 OpenClaw 注入块",
|
|
90
|
+
].join("\n");
|
|
91
|
+
|
|
92
|
+
assert.equal(
|
|
93
|
+
stripOpenClawInjectedPrefix(input),
|
|
94
|
+
["Sender (untrusted metadata):", "这行是正文,不是 OpenClaw 注入块"].join("\n"),
|
|
95
|
+
);
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
test("supports leading blank lines before inbound metadata", () => {
|
|
99
|
+
const input = [
|
|
100
|
+
"",
|
|
101
|
+
"",
|
|
102
|
+
"Conversation info (untrusted metadata):",
|
|
103
|
+
"```json",
|
|
104
|
+
'{"message_id":"123"}',
|
|
105
|
+
"```",
|
|
106
|
+
"",
|
|
107
|
+
"真正的问题",
|
|
108
|
+
].join("\n");
|
|
109
|
+
|
|
110
|
+
assert.equal(stripOpenClawInjectedPrefix(input), "真正的问题");
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
test("supports windows newlines", () => {
|
|
114
|
+
const input =
|
|
115
|
+
"Conversation info (untrusted metadata):\r\n```json\r\n{\"message_id\":\"123\"}\r\n```\r\n\r\n继续";
|
|
116
|
+
|
|
117
|
+
assert.equal(stripOpenClawInjectedPrefix(input), "继续");
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
test("strips gateway-client sender block and leading weekday timestamp envelope", () => {
|
|
121
|
+
const input = [
|
|
122
|
+
"Sender (untrusted metadata):",
|
|
123
|
+
"```json",
|
|
124
|
+
'{"label":"openclaw-tui (gateway-client)","id":"gateway-client"}',
|
|
125
|
+
"```",
|
|
126
|
+
"",
|
|
127
|
+
"[Mon 2026-03-16 14:27 GMT+8] What is Melanie's hand-painted bowl a reminder of?",
|
|
128
|
+
].join("\n");
|
|
129
|
+
|
|
130
|
+
assert.equal(
|
|
131
|
+
stripOpenClawInjectedPrefix(input),
|
|
132
|
+
"What is Melanie's hand-painted bowl a reminder of?",
|
|
133
|
+
);
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
test("strips leading pm-on-date envelope after inbound metadata", () => {
|
|
137
|
+
const input = [
|
|
138
|
+
"Sender (untrusted metadata):",
|
|
139
|
+
"```json",
|
|
140
|
+
'{"label":"openclaw-tui (gateway-client)","id":"gateway-client"}',
|
|
141
|
+
"```",
|
|
142
|
+
"",
|
|
143
|
+
"[06:18 PM on 07 March, 2026]: 继续",
|
|
144
|
+
].join("\n");
|
|
145
|
+
|
|
146
|
+
assert.equal(stripOpenClawInjectedPrefix(input), "继续");
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
test("keeps bracketed content when it is not a recognized timestamp envelope", () => {
|
|
150
|
+
const input = "[Important] What is Melanie's hand-painted bowl a reminder of?";
|
|
151
|
+
assert.equal(stripOpenClawInjectedPrefix(input), input);
|
|
152
|
+
});
|