@cup319/mmpl 2.7.1 → 2.8.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 +3 -2
- package/dist/auto-context-NUQFETSY.js +0 -0
- package/dist/checkpoint-ABRNCBCA.js +0 -0
- package/dist/chunk-2H7UOFLK.js +0 -0
- package/dist/chunk-CHVFXR24.js +0 -0
- package/dist/chunk-JL66S7P7.js +0 -0
- package/dist/chunk-SSDURI3I.js +0 -0
- package/dist/index.js +167 -14
- package/dist/index.js.map +1 -1
- package/dist/mermaid-injector-ROQAAM7B.js +0 -0
- package/dist/observability-6AMQYVCF.js +0 -0
- package/dist/offload-engine-BF5IXXBH.js +0 -0
- package/dist/persona-generator-NZQVIVDA.js +0 -0
- package/dist/pipeline-manager-IJ2JLUMK.js +0 -0
- package/dist/scene-builder-TLVG23BJ.js +0 -0
- package/dist/scene-index-SU6GMVDL.js +0 -0
- package/dist/symbolic-A4XAGBBB.js +0 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
## 核心特性
|
|
9
9
|
|
|
10
|
-
- **
|
|
10
|
+
- **9 个精简工具**:write、search、list、manage、evolve、compress、palace、symbol、stats
|
|
11
11
|
- **模型自动下载**:首次启动自动从 HuggingFace 下载 ONNX 模型(默认 all-MiniLM-L6-v2,90MB,384维)
|
|
12
12
|
- **跨平台支持**:Windows + Linux,自动适配路径和信号处理
|
|
13
13
|
- **记忆生命周期**:Active → Infrequent → Archived → Permanent(含衰减、强化、SM-2 间隔复习)
|
|
@@ -140,7 +140,7 @@ curl http://127.0.0.1:7680/
|
|
|
140
140
|
{ "type": "summary" }
|
|
141
141
|
```
|
|
142
142
|
|
|
143
|
-
到这里你已经跑通了完整闭环。
|
|
143
|
+
到这里你已经跑通了完整闭环。9 个工具的完整说明见下文「工具一览」。
|
|
144
144
|
|
|
145
145
|
> **常驻保活**:HTTP server 自身不会自我守护。Windows 推荐 `nssm install MMPL node D:\path\to\dist\index.js`,Linux/macOS 推荐 `systemd` 或 `pm2 start dist/index.js --name mmpl`。
|
|
146
146
|
|
|
@@ -231,6 +231,7 @@ v2.5.1 之前默认走 stdio,每个 client 各 spawn 一个进程。该模式
|
|
|
231
231
|
|------|------|
|
|
232
232
|
| `memory_write` | 写入记忆(encode 编码 + capture 捕获) |
|
|
233
233
|
| `memory_search` | 检索记忆(quick/deep/hybrid/keyword + drill 钻取) |
|
|
234
|
+
| `memory_list` | 列出记忆(分页 + 状态/类型/强度/关键词过滤 + 排序) |
|
|
234
235
|
| `memory_manage` | 管理生命周期(forget/reinforce/consolidate/reclaim/reembed) |
|
|
235
236
|
| `memory_evolve` | 自动进化(extract 提取 + persona 画像更新) |
|
|
236
237
|
| `memory_compress` | 压缩记忆(compress/decompress/offload) |
|
|
File without changes
|
|
File without changes
|
package/dist/chunk-2H7UOFLK.js
CHANGED
|
File without changes
|
package/dist/chunk-CHVFXR24.js
CHANGED
|
File without changes
|
package/dist/chunk-JL66S7P7.js
CHANGED
|
File without changes
|
package/dist/chunk-SSDURI3I.js
CHANGED
|
File without changes
|
package/dist/index.js
CHANGED
|
@@ -943,6 +943,40 @@ var Storage = class _Storage {
|
|
|
943
943
|
`);
|
|
944
944
|
return rows.map((r) => this.rowToMemory(r));
|
|
945
945
|
}
|
|
946
|
+
/**
|
|
947
|
+
* 分页列出记忆,支持按 status / type / permanent / 强度区间 / 关键词过滤,
|
|
948
|
+
* 支持白名单字段排序。返回 { items, total } —— total 是过滤后总条数
|
|
949
|
+
* (不受分页影响),用于客户端计算 has_more / 总页数。
|
|
950
|
+
*
|
|
951
|
+
* 与 getActiveMemories/getMemoriesByStatus 的区别:本方法做确定性分页浏览,
|
|
952
|
+
* 不依赖语义检索,专供 memory_list 工具浏览全库使用。
|
|
953
|
+
*/
|
|
954
|
+
async listMemories(opts) {
|
|
955
|
+
const conditions = [];
|
|
956
|
+
if (opts.status) conditions.push(`status = '${this.escape(opts.status)}'`);
|
|
957
|
+
if (opts.type) conditions.push(`type = '${this.escape(opts.type)}'`);
|
|
958
|
+
if (opts.permanent !== void 0) conditions.push(`permanent = ${opts.permanent ? "true" : "false"}`);
|
|
959
|
+
if (opts.minStrength !== void 0) conditions.push(`strength >= ${Number(opts.minStrength)}`);
|
|
960
|
+
if (opts.maxStrength !== void 0) conditions.push(`strength <= ${Number(opts.maxStrength)}`);
|
|
961
|
+
if (opts.q) conditions.push(`content LIKE '%${this.escape(opts.q)}%'`);
|
|
962
|
+
const where = conditions.length ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
963
|
+
const validOrderBy = /* @__PURE__ */ new Set([
|
|
964
|
+
"created_at",
|
|
965
|
+
"strength",
|
|
966
|
+
"importance",
|
|
967
|
+
"last_accessed",
|
|
968
|
+
"access_count"
|
|
969
|
+
]);
|
|
970
|
+
const orderBy = validOrderBy.has(opts.orderBy ?? "") ? opts.orderBy : "created_at";
|
|
971
|
+
const order = opts.order === "asc" ? "ASC" : "DESC";
|
|
972
|
+
const limit = Math.min(Math.max(opts.limit ?? 20, 1), 500);
|
|
973
|
+
const offset = Math.max(opts.offset ?? 0, 0);
|
|
974
|
+
const total = this.N((await this.get(`SELECT COUNT(*) as c FROM memories ${where}`))?.c) ?? 0;
|
|
975
|
+
const rows = await this.all(
|
|
976
|
+
`SELECT * FROM memories ${where} ORDER BY ${orderBy} ${order} LIMIT ${limit} OFFSET ${offset}`
|
|
977
|
+
);
|
|
978
|
+
return { items: rows.map((r) => this.rowToMemory(r)), total };
|
|
979
|
+
}
|
|
946
980
|
async updateMemoryBatch(ids, updates) {
|
|
947
981
|
for (const id of ids) {
|
|
948
982
|
await this.updateMemory(id, updates);
|
|
@@ -21662,6 +21696,111 @@ async function handleMetrics(deps) {
|
|
|
21662
21696
|
return { content: [{ type: "text", text: JSON.stringify({ metrics, report }, null, 2) }] };
|
|
21663
21697
|
}
|
|
21664
21698
|
|
|
21699
|
+
// src/tools/memory-list.ts
|
|
21700
|
+
var TRUNC_LIGHT = 100;
|
|
21701
|
+
function serializeLight(m, fullContent) {
|
|
21702
|
+
const item = {
|
|
21703
|
+
memory_id: m.id,
|
|
21704
|
+
type: m.type,
|
|
21705
|
+
status: m.status,
|
|
21706
|
+
strength: Number(m.strength?.toFixed(3)),
|
|
21707
|
+
permanent: m.permanent
|
|
21708
|
+
};
|
|
21709
|
+
if (fullContent || m.content.length <= TRUNC_LIGHT) {
|
|
21710
|
+
item.content = m.content;
|
|
21711
|
+
item.content_length = m.content.length;
|
|
21712
|
+
} else {
|
|
21713
|
+
item.content = m.content.slice(0, TRUNC_LIGHT) + "...";
|
|
21714
|
+
item.content_length = m.content.length;
|
|
21715
|
+
item.content_truncated = true;
|
|
21716
|
+
}
|
|
21717
|
+
item.created_at_iso = m.created_at ? new Date(m.created_at).toISOString() : null;
|
|
21718
|
+
return item;
|
|
21719
|
+
}
|
|
21720
|
+
function serializeDetail(m, fullContent) {
|
|
21721
|
+
const TRUNC_DETAIL = 300;
|
|
21722
|
+
const item = {
|
|
21723
|
+
memory_id: m.id,
|
|
21724
|
+
type: m.type,
|
|
21725
|
+
status: m.status,
|
|
21726
|
+
strength: Number(m.strength?.toFixed(3)),
|
|
21727
|
+
importance: Number(m.importance?.toFixed(3)),
|
|
21728
|
+
permanent: m.permanent,
|
|
21729
|
+
tags: m.tags,
|
|
21730
|
+
access_count: m.access_count,
|
|
21731
|
+
created_at: m.created_at,
|
|
21732
|
+
created_at_iso: m.created_at ? new Date(m.created_at).toISOString() : null,
|
|
21733
|
+
last_accessed: m.last_accessed,
|
|
21734
|
+
last_accessed_iso: m.last_accessed ? new Date(m.last_accessed).toISOString() : null,
|
|
21735
|
+
anchor_id: m.anchor_id,
|
|
21736
|
+
compressed: m.compressed
|
|
21737
|
+
};
|
|
21738
|
+
if (fullContent || m.content.length <= TRUNC_DETAIL) {
|
|
21739
|
+
item.content = m.content;
|
|
21740
|
+
item.content_length = m.content.length;
|
|
21741
|
+
} else {
|
|
21742
|
+
item.content = m.content.slice(0, TRUNC_DETAIL) + "...";
|
|
21743
|
+
item.content_length = m.content.length;
|
|
21744
|
+
item.content_truncated = true;
|
|
21745
|
+
}
|
|
21746
|
+
return item;
|
|
21747
|
+
}
|
|
21748
|
+
function registerMemoryList(server, deps) {
|
|
21749
|
+
server.tool(
|
|
21750
|
+
"memory_list",
|
|
21751
|
+
"\u5217\u51FA\u8BB0\u5FC6\uFF1A\u5206\u9875\u67E5\u8BE2\u3001\u6309\u7C7B\u578B/\u72B6\u6001/\u5F3A\u5EA6/\u5173\u952E\u8BCD\u8FC7\u6EE4\u3001\u652F\u6301\u6392\u5E8F",
|
|
21752
|
+
{
|
|
21753
|
+
status: external_exports.enum(["active", "infrequent", "archived"]).optional().describe("\u72B6\u6001\u8FC7\u6EE4\uFF1B\u4E0D\u4F20=\u5168\u90E8"),
|
|
21754
|
+
type: external_exports.enum(["fact", "preference", "instruction", "event", "skill"]).optional().describe("\u7C7B\u578B\u8FC7\u6EE4"),
|
|
21755
|
+
permanent: external_exports.boolean().optional().describe("\u53EA\u770B\u6C38\u4E45\u8BB0\u5FC6\uFF08true\uFF09/\u53EA\u770B\u975E\u6C38\u4E45\uFF08false\uFF09\uFF1B\u4E0D\u4F20=\u5168\u90E8"),
|
|
21756
|
+
min_strength: external_exports.number().optional().describe("\u6700\u4F4E\u5F3A\u5EA6\u8FC7\u6EE4\uFF080-1\uFF09"),
|
|
21757
|
+
max_strength: external_exports.number().optional().describe("\u6700\u9AD8\u5F3A\u5EA6\u8FC7\u6EE4\uFF080-1\uFF09"),
|
|
21758
|
+
q: external_exports.string().optional().describe("\u5173\u952E\u8BCD\u6A21\u7CCA\u5339\u914D\uFF08LIKE\uFF09\uFF0C\u53EF\u9009"),
|
|
21759
|
+
order_by: external_exports.enum(["created_at", "strength", "importance", "last_accessed", "access_count"]).optional().describe("\u6392\u5E8F\u5B57\u6BB5\uFF0C\u9ED8\u8BA4 created_at"),
|
|
21760
|
+
order: external_exports.enum(["asc", "desc"]).optional().describe("\u6392\u5E8F\u65B9\u5411\uFF0C\u9ED8\u8BA4 desc"),
|
|
21761
|
+
limit: external_exports.number().optional().describe("\u6BCF\u9875\u6570\u91CF\uFF0C\u9ED8\u8BA4 20\uFF0C\u786C\u4E0A\u9650 500"),
|
|
21762
|
+
offset: external_exports.number().optional().describe("\u504F\u79FB\u91CF\uFF0C\u9ED8\u8BA4 0"),
|
|
21763
|
+
detail: external_exports.boolean().optional().describe("\u8FD4\u56DE\u5168\u5B57\u6BB5\uFF08importance/tags/access_count \u7B49\uFF09\uFF1B\u9ED8\u8BA4 false \u53EA\u8FD4\u56DE\u6838\u5FC3\u5B57\u6BB5"),
|
|
21764
|
+
full_content: external_exports.boolean().optional().describe("\u8FD4\u56DE\u5B8C\u6574 content\uFF08\u9ED8\u8BA4 light \u622A\u65AD\u5230 100 \u5B57\u7B26\uFF0Cdetail \u622A\u65AD\u5230 300\uFF09")
|
|
21765
|
+
},
|
|
21766
|
+
async (params) => {
|
|
21767
|
+
const { storage } = deps;
|
|
21768
|
+
const limit = Math.min(Math.max(params.limit ?? 20, 1), 500);
|
|
21769
|
+
const offset = Math.max(params.offset ?? 0, 0);
|
|
21770
|
+
const fullContent = params.full_content ?? false;
|
|
21771
|
+
const detail = params.detail ?? false;
|
|
21772
|
+
const { items, total } = await storage.listMemories({
|
|
21773
|
+
status: params.status,
|
|
21774
|
+
type: params.type,
|
|
21775
|
+
permanent: params.permanent,
|
|
21776
|
+
minStrength: params.min_strength,
|
|
21777
|
+
maxStrength: params.max_strength,
|
|
21778
|
+
q: params.q,
|
|
21779
|
+
orderBy: params.order_by,
|
|
21780
|
+
order: params.order,
|
|
21781
|
+
limit,
|
|
21782
|
+
offset
|
|
21783
|
+
});
|
|
21784
|
+
const serialized = items.map(
|
|
21785
|
+
(m) => detail ? serializeDetail(m, fullContent) : serializeLight(m, fullContent)
|
|
21786
|
+
);
|
|
21787
|
+
return {
|
|
21788
|
+
content: [{
|
|
21789
|
+
type: "text",
|
|
21790
|
+
text: JSON.stringify({
|
|
21791
|
+
items: serialized,
|
|
21792
|
+
total,
|
|
21793
|
+
limit,
|
|
21794
|
+
offset,
|
|
21795
|
+
mode: detail ? "detail" : "light",
|
|
21796
|
+
has_more: offset + items.length < total
|
|
21797
|
+
}, null, 2)
|
|
21798
|
+
}]
|
|
21799
|
+
};
|
|
21800
|
+
}
|
|
21801
|
+
);
|
|
21802
|
+
}
|
|
21803
|
+
|
|
21665
21804
|
// src/index.ts
|
|
21666
21805
|
BigInt.prototype.toJSON = function() {
|
|
21667
21806
|
return Number(this);
|
|
@@ -21748,7 +21887,7 @@ async function main() {
|
|
|
21748
21887
|
const createMcpServer = () => {
|
|
21749
21888
|
const server = new McpServer({
|
|
21750
21889
|
name: "MMPL",
|
|
21751
|
-
version: "2.
|
|
21890
|
+
version: "2.8.1"
|
|
21752
21891
|
});
|
|
21753
21892
|
registerMemoryWrite(server, deps);
|
|
21754
21893
|
registerMemorySearch(server, deps);
|
|
@@ -21758,6 +21897,7 @@ async function main() {
|
|
|
21758
21897
|
registerMemoryPalace(server, deps);
|
|
21759
21898
|
registerMemorySymbol(server, deps);
|
|
21760
21899
|
registerMemoryStats(server, deps);
|
|
21900
|
+
registerMemoryList(server, deps);
|
|
21761
21901
|
return server;
|
|
21762
21902
|
};
|
|
21763
21903
|
const httpHost = process.env.MCP_HTTP_HOST ?? "127.0.0.1";
|
|
@@ -21771,10 +21911,13 @@ async function main() {
|
|
|
21771
21911
|
void embeddingService.ready().catch((err) => {
|
|
21772
21912
|
console.error("[startup] embedding service init failed:", err);
|
|
21773
21913
|
});
|
|
21774
|
-
console.error(`MMPL (Memory Palace) MCP Server v2.
|
|
21775
|
-
|
|
21914
|
+
console.error(`MMPL (Memory Palace) MCP Server v2.8.1 listening on http://${httpHost}:${httpPort}${httpPath}`);
|
|
21915
|
+
let shuttingDown = false;
|
|
21916
|
+
const gracefulShutdown = async (reason) => {
|
|
21917
|
+
if (shuttingDown) return;
|
|
21918
|
+
shuttingDown = true;
|
|
21776
21919
|
console.error(`
|
|
21777
|
-
[shutdown]
|
|
21920
|
+
[shutdown] Triggered by ${reason}, gracefully shutting down...`);
|
|
21778
21921
|
try {
|
|
21779
21922
|
pipeline2.stop();
|
|
21780
21923
|
console.error("[shutdown] PipelineManager stopped");
|
|
@@ -21796,21 +21939,31 @@ async function main() {
|
|
|
21796
21939
|
console.error("[shutdown] Clean shutdown complete");
|
|
21797
21940
|
process.exit(0);
|
|
21798
21941
|
};
|
|
21942
|
+
const armForceExitTimer = (reason) => {
|
|
21943
|
+
setTimeout(() => {
|
|
21944
|
+
console.error(`[shutdown] Timed out after 5s (${reason}), forcing exit`);
|
|
21945
|
+
process.exit(0);
|
|
21946
|
+
}, 5e3);
|
|
21947
|
+
};
|
|
21799
21948
|
if (process.platform !== "win32") {
|
|
21800
21949
|
process.on("SIGTERM", () => {
|
|
21801
|
-
|
|
21802
|
-
|
|
21803
|
-
process.exit(0);
|
|
21804
|
-
}, 1e4);
|
|
21805
|
-
gracefulShutdown("SIGTERM").finally(() => clearTimeout(timeout));
|
|
21950
|
+
armForceExitTimer("SIGTERM");
|
|
21951
|
+
gracefulShutdown("SIGTERM");
|
|
21806
21952
|
});
|
|
21807
21953
|
}
|
|
21808
21954
|
process.on("SIGINT", () => {
|
|
21809
|
-
|
|
21810
|
-
|
|
21811
|
-
|
|
21812
|
-
|
|
21813
|
-
|
|
21955
|
+
armForceExitTimer("SIGINT");
|
|
21956
|
+
gracefulShutdown("SIGINT");
|
|
21957
|
+
});
|
|
21958
|
+
process.on("uncaughtException", (err) => {
|
|
21959
|
+
console.error("[shutdown] uncaughtException:", err);
|
|
21960
|
+
armForceExitTimer("uncaughtException");
|
|
21961
|
+
gracefulShutdown("uncaughtException");
|
|
21962
|
+
});
|
|
21963
|
+
process.on("unhandledRejection", (reason) => {
|
|
21964
|
+
console.error("[shutdown] unhandledRejection:", reason);
|
|
21965
|
+
armForceExitTimer("unhandledRejection");
|
|
21966
|
+
gracefulShutdown("unhandledRejection");
|
|
21814
21967
|
});
|
|
21815
21968
|
const providerStatus = embeddingService.getProviderStatus();
|
|
21816
21969
|
console.error(` Embedding: ${providerStatus.active} (\u7EF4\u5EA6: ${embeddingService.dimension}, \u53EF\u7528: ${embeddingService.available ? "\u2705" : "\u274C"})`);
|