@bsbofmusic/memos-memu-local-memory-tools-for-agent 1.0.5 → 1.2.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/package.json +1 -1
- package/src/shared/db.js +7 -11
- package/src/tools/memos.js +30 -1
- package/src/tools/memuk.js +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bsbofmusic/memos-memu-local-memory-tools-for-agent",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "MCP server — one-shot install + query for memos (PostgreSQL) and memuK (SQLite) local memory. Designed for OpenClaw agents.",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"type": "module",
|
package/src/shared/db.js
CHANGED
|
@@ -44,7 +44,7 @@ export function sqlite(sql, dbPath) {
|
|
|
44
44
|
const safeSql = sql.replace(/"/g, '""');
|
|
45
45
|
try {
|
|
46
46
|
const out = execSync(
|
|
47
|
-
`/usr/bin/sqlite3 "${db}" "${safeSql}"`,
|
|
47
|
+
`/usr/bin/sqlite3 -json "${db}" "${safeSql}"`,
|
|
48
48
|
{ timeout: 10000 }
|
|
49
49
|
).toString();
|
|
50
50
|
return out;
|
|
@@ -92,16 +92,12 @@ export function dockerContainerRunning(name) {
|
|
|
92
92
|
}
|
|
93
93
|
|
|
94
94
|
export function parseSqlite(output) {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
memory_type: pipe[2]?.trim() ?? '',
|
|
102
|
-
happened_at: pipe[3]?.trim() ?? '',
|
|
103
|
-
};
|
|
104
|
-
});
|
|
95
|
+
try {
|
|
96
|
+
const rows = JSON.parse(output.trim());
|
|
97
|
+
return Array.isArray(rows) ? rows : [];
|
|
98
|
+
} catch {
|
|
99
|
+
return [];
|
|
100
|
+
}
|
|
105
101
|
}
|
|
106
102
|
|
|
107
103
|
export function parsePsqlJson(output) {
|
package/src/tools/memos.js
CHANGED
|
@@ -11,7 +11,8 @@ export async function memos_query({ query, limit = 10 }) {
|
|
|
11
11
|
const safe = s => s.replace(/'/g, "''");
|
|
12
12
|
const lim = Math.min(parseInt(limit) || 10, 20);
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
// 方案4:先整句搜索,没结果再拆关键词OR
|
|
15
|
+
let sql = `
|
|
15
16
|
SELECT jsonb_agg(q ORDER BY created_ts DESC)
|
|
16
17
|
FROM (
|
|
17
18
|
SELECT
|
|
@@ -39,6 +40,34 @@ FROM (
|
|
|
39
40
|
|
|
40
41
|
let rows = parsePsqlJson(raw);
|
|
41
42
|
|
|
43
|
+
// 方案4:如果整句没结果,再拆关键词OR搜索
|
|
44
|
+
if (!Array.isArray(rows) || rows.length === 0) {
|
|
45
|
+
// 方案2:按空格拆关键词,OR连接
|
|
46
|
+
const keywords = query.split(/\s+/).filter(k => k.trim().length > 0);
|
|
47
|
+
if (keywords.length > 0) {
|
|
48
|
+
const whereClauses = keywords.map(k => `content ILIKE '%${safe(k)}%'`).join(' OR ');
|
|
49
|
+
sql = `
|
|
50
|
+
SELECT jsonb_agg(q ORDER BY created_ts DESC)
|
|
51
|
+
FROM (
|
|
52
|
+
SELECT
|
|
53
|
+
id,
|
|
54
|
+
substr(content, 1, 500) AS content,
|
|
55
|
+
created_ts,
|
|
56
|
+
visibility
|
|
57
|
+
FROM memo
|
|
58
|
+
WHERE ${whereClauses}
|
|
59
|
+
ORDER BY created_ts DESC
|
|
60
|
+
LIMIT ${lim}
|
|
61
|
+
) q;`.trim();
|
|
62
|
+
try {
|
|
63
|
+
raw = psql(sql);
|
|
64
|
+
rows = parsePsqlJson(raw);
|
|
65
|
+
} catch (err) {
|
|
66
|
+
// 关键词OR搜索也失败,返回空
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
42
71
|
// Defensive slice: enforce limit cap at application level
|
|
43
72
|
if (!Array.isArray(rows)) rows = [];
|
|
44
73
|
if (rows.length > lim) rows = rows.slice(0, lim);
|
package/src/tools/memuk.js
CHANGED
|
@@ -47,7 +47,7 @@ LIMIT ${lim};`.trim();
|
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
const lines = rows.map(
|
|
50
|
-
(r, i) => `─── ${i + 1}. [${r.memory_type}] ${r.happened_at || 'n/a'} ───\n${r.summary}`
|
|
50
|
+
(r, i) => `─── ${i + 1}. [${r.memory_type || 'imported'}] ${r.happened_at || 'n/a'} ───\n${r.summary || ''}`
|
|
51
51
|
);
|
|
52
52
|
|
|
53
53
|
return {
|