@yottameta/yotta-memory 0.8.4 → 0.8.5
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/CHANGELOG.md +10 -0
- package/README.md +3 -3
- package/README.zh-CN.md +4 -2
- package/SKILL.md +3 -3
- package/USER_GUIDE.md +1 -1
- package/bin/yotta-memory.js +74 -8
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# 更新日志
|
|
2
2
|
|
|
3
|
+
## v0.8.5 (2026-08-29)
|
|
4
|
+
|
|
5
|
+
安全修复(SkillHub 安全扫描发现高危,修复后三源同步升版):
|
|
6
|
+
|
|
7
|
+
- **MCP 命令执行入口封死**:MCP `distill` 不再接受 `--model`(`callTool` 在工具边界直接拒绝),远端智能体无法再借 MCP 在引擎主机执行任意命令。
|
|
8
|
+
- **MCP 任意路径读写封死**:MCP `export` / `import` 的 `out` / `src` 必须落在记忆库根内(新增 `resolveWithinRoot` 校验,防 `..` 穿越),库外路径直接拒绝,与「远程只能读写记忆」承诺对齐。
|
|
9
|
+
- **CLI 参数解析修复**:`--model` / `--subject` / `--reason` / `--merge` 此前被 valueOpts 消费但未写入 opts,导致 `distill --model` / `--subject` 实际不生效;本版补齐映射,CLI `distill --model` 现已真正走 `runDistillModel` 安全路径(`shell:false` + 允许清单)。
|
|
10
|
+
- **CLI distill 去 shell 注入**:`distill --model` 改走 `runDistillModel` —— `spawnSync(argv[0], argv.slice(1), { shell:false, windowsHide:true })` + `splitCommandArgv` 拆分 argv,彻底移除 shell 注入面;新增 `distillModelAllowlist`(环境变量 `YOTTA_DISTILL_MODELS` 或 `config.distill_models`,未配置时放行本地 CLI,但已无 shell 注入;MCP 层已直接禁 `--model`,不达此处)。
|
|
11
|
+
- 版本对齐:package.json / SKILL.md / CHANGELOG / 引擎 VERSION / 文档边界说明 = 0.8.5。
|
|
12
|
+
- 新增回归测试:`test/security-boundary.test.js`(MCP 禁 --model / export-import 限库内 / 合法操作仍可用,6 项断言)。
|
|
3
13
|
## v0.8.4 (2026-08-29)
|
|
4
14
|
|
|
5
15
|
- 安装方式统一为四方式(对齐发布规范 §3.3.1):方式一 `npx -y @yottameta/yotta-memory --agent <name>` / `--dir <dir>`(推荐,走 npm 源);方式二 `git clone https://github.com/YottaMeta/yotta-memory.git`;方式三 GitHub Download ZIP;方式四 `bash install.sh --agent/--dir/--list`。移除 `npx skills` 与 `-g` 推荐;中英双 README 安装节同步。
|
package/README.md
CHANGED
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
|
|
24
24
|
> 📖 The user-facing operations manual lives in [USER_GUIDE.md](USER_GUIDE.md).
|
|
25
25
|
|
|
26
|
-
> 🆕 **v0.8.
|
|
26
|
+
> 🆕 **v0.8.5**: security hardening — MCP `distill` no longer accepts `--model`; MCP `export` / `import` paths are restricted to the memory root; CLI `distill --model` no longer shells out (allowlist-based).
|
|
27
27
|
|
|
28
28
|
## Core value
|
|
29
29
|
|
|
@@ -93,7 +93,7 @@ Each agent has a globally unique agent ID: it is the ownership key for private m
|
|
|
93
93
|
- `maintain`: unified utility score (final score = confidence + usage + recency + type + structure) × weight; low-utility + over-age auto-archive; extreme low value listed as forget candidates (not really deleted by default; `--purge` deletes); `--dedup` dedup candidates; `--merge A,B` manual merge. Dry-run preview by default, `--apply` to execute; immutable / BOUND exempt; audit writes `.archive/audit-<date>.jsonl`.
|
|
94
94
|
- `archive`: moves low-value old memory into `.archive/` by "unified utility score + age" (immutable excluded) so the store never grows without bound.
|
|
95
95
|
- `feedback`: explicit usage feedback loop — useful → weight ×1.2 (cap 3.0) + confidence +0.05 + feedback_net +1; useless → weight ×0.8 (floor 0.2) + confidence −0.05 + feedback_net −1; `--undo` rolls back; audit writes `.archive/feedback-<date>.jsonl`.
|
|
96
|
-
- `distill`: psychological-log distillation — statistical summary (type / age / heat / feedback) + topic profile (clustered by subject) + knowledge map (type → tags); optional `--model <cmd>` external model stdin→stdout refinement; output to `private/<owner>/distills/` or `facts/distills/`.
|
|
96
|
+
- `distill`: psychological-log distillation — statistical summary (type / age / heat / feedback) + topic profile (clustered by subject) + knowledge map (type → tags); optional `--model <cmd>` external model stdin→stdout refinement (local CLI only; MCP distill does not expose `--model`); output to `private/<owner>/distills/` or `facts/distills/`.
|
|
97
97
|
- `explain`: view a single memory's utility components and archive / forget status decision.
|
|
98
98
|
- `forget`: delete a single memory (by type-dir path or file name).
|
|
99
99
|
- `reindex`: rebuild the index after manually editing `.md` files.
|
|
@@ -250,7 +250,7 @@ Register the connection in the agent's MCP config (`url` + two headers):
|
|
|
250
250
|
}
|
|
251
251
|
```
|
|
252
252
|
|
|
253
|
-
Once connected, MCP tools (remember / recall / search / forget / archive / reindex / export / import / agent_info) read/write memory and confirm identity; management actions (init / config / token / lan / serve) are not exposed via MCP, and token management is never exposed remotely. `X-Agent-Id` must match the token's registered agent; read-partition rules are the same as the CLI (FACT public-readable, PREF / BOUND / COMMIT private).
|
|
253
|
+
Once connected, MCP tools (remember / recall / search / forget / archive / reindex / export / import / agent_info) read/write memory and confirm identity; management actions (init / config / token / lan / serve) are not exposed via MCP, and token management is never exposed remotely. MCP `export` / `import` paths are restricted inside the memory root, and MCP `distill` does not support `--model` (local CLI only). `X-Agent-Id` must match the token's registered agent; read-partition rules are the same as the CLI (FACT public-readable, PREF / BOUND / COMMIT private).
|
|
254
254
|
|
|
255
255
|
### Location persistence
|
|
256
256
|
|
package/README.zh-CN.md
CHANGED
|
@@ -23,6 +23,8 @@
|
|
|
23
23
|
|
|
24
24
|
> 📖 面向用户的操作手册见 [USER_GUIDE.md](USER_GUIDE.md)。
|
|
25
25
|
|
|
26
|
+
> 🆕 **v0.8.5**:安全加固——MCP `distill` 不再接受 `--model`;MCP `export` / `import` 路径限记忆库内;CLI `distill --model` 不再走 shell(改为允许清单)。
|
|
27
|
+
|
|
26
28
|
> 🆕 **v0.8.2**:发布元数据修复——三次源重发带 `--name 元忆 yotta-memory`,修复 ClawHub 展示名缺失中文(原为裸 `yotta-memory`);无功能变更。
|
|
27
29
|
|
|
28
30
|
> 🆕 **v0.8.1**:`view` 用户查看平台改为服务端分页(记忆多了一次只渲染当前页,页码上下页);`recall` 增加候选预过滤(语义检索前先粗筛候选集,命中集不变,记忆量大时不再逐条全量语义 / 模糊 / 编辑距离);公共 `index.json` 超过 5000 条时按年份分片(`index-<year>.json`),避免单文件膨胀。
|
|
@@ -134,7 +136,7 @@
|
|
|
134
136
|
- **记忆库即引擎**:`serve` 把记忆目录挂成 MCP 服务,目录随盘走;引擎主机只需装 CLI 当存放点,无需装任何 AI 智能体。
|
|
135
137
|
- **双模式可并存**:本地 `serve --stdio` 零进程(客户端按需拉起);局域网 streamable HTTP(默认 `0.0.0.0:8787`)+ 每智能体 token 鉴权。
|
|
136
138
|
- **开机自启**:`lan enable` 注册开机自启——Windows 优先计划任务(默认登录自启,`--onstart` 开机即启需管理员),非管理员自动降级为**用户级 Startup 静默自启**(免管理员,启动脚本内联启动命令、被清理也会在开机时自动重建,v0.6.3 起不再弹 80070002);Linux 优先 **systemd 用户单元**(`systemctl --user`,登录自启;`--onstart` 附加 `loginctl enable-linger` 开机即启),systemd 不可用时自动降级**用户 crontab @reboot**(v0.6.4);`lan disable` 移除,`lan status` 查询。
|
|
137
|
-
- **安全边界**:管理动作(init / config / token / lan / serve)不进 MCP,token
|
|
139
|
+
- **安全边界**:管理动作(init / config / token / lan / serve)不进 MCP,token 不远程暴露;远程智能体只能读写记忆,且路径限记忆库内(export/import 的 out/src 必须落在库内)、distill 不支持 `--model`(仅本地 CLI),不能改配置、不能管 token。
|
|
138
140
|
- 完整操作步骤见上文「局域网多机共享」章节与 [USER_GUIDE.md](USER_GUIDE.md)。
|
|
139
141
|
|
|
140
142
|
## 与其他方案对比
|
|
@@ -288,7 +290,7 @@ yotta-memory recall --type FACT --limit 10
|
|
|
288
290
|
}
|
|
289
291
|
```
|
|
290
292
|
|
|
291
|
-
连接后可通过 MCP tools(remember / recall / search / forget / archive / reindex / export / import / agent_info)读写记忆与确认身份;管理动作(init / config / token / lan / serve)不进 MCP,token
|
|
293
|
+
连接后可通过 MCP tools(remember / recall / search / forget / archive / reindex / export / import / agent_info)读写记忆与确认身份;管理动作(init / config / token / lan / serve)不进 MCP,token 管理不远程暴露;MCP export/import 路径限记忆库内、distill 不支持 `--model`(仅本地 CLI)。`X-Agent-Id` 必须与 token 登记的智能体一致;读取分区规则与 CLI 相同(FACT 公共可读,PREF / BOUND / COMMIT 私密隔离)。
|
|
292
294
|
|
|
293
295
|
### 位置持久化
|
|
294
296
|
|
package/SKILL.md
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: yotta-memory
|
|
3
3
|
description: "元忆 —— 有权限边界的文件式智能体记忆。文件式、零依赖、可 diff/回滚:让任何 AI 智能体活过会话,开工 recall 恢复上下文、重要信息 remember 落盘、收工归档。类型体系 FACT(公共共享)/ PREF / BOUND / COMMIT(私密隔离)。触发:记住、别忘了、记一笔、记忆、remember、recall、跨会话、上次说到、续测、交接、归档、记忆盘、共享记忆、局域网记忆、画像、开工上下文、记忆守则、profile、context、越用越懂、语义检索、反馈、维护、蒸馏、feedback、maintain、distill、explain、自我学习、自我进化、自我提升、查看平台分页、recall 候选预过滤"
|
|
4
|
-
version: 0.8.
|
|
4
|
+
version: 0.8.5
|
|
5
5
|
license: MIT
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# yotta-memory(元忆)— 有权限边界的文件式智能体记忆
|
|
9
9
|
|
|
10
10
|
> 一句话:元忆 —— 有权限边界的文件式智能体记忆(不注入、可 diff、能回滚;FACT 共享、PREF / BOUND / COMMIT 私密隔离)。
|
|
11
|
-
> 版本:0.8.
|
|
11
|
+
> 版本:0.8.5 | 最后更新:2026-08-29
|
|
12
12
|
|
|
13
13
|
## 这是什么
|
|
14
14
|
|
|
@@ -291,7 +291,7 @@ license: MIT
|
|
|
291
291
|
4. 按当前智能体机制重载 MCP(必要时请用户重启会话);
|
|
292
292
|
5. 用 MCP tools 读写记忆。
|
|
293
293
|
|
|
294
|
-
> MCP 工具集与 CLI 一致:remember / recall / search / forget / archive / reindex / export / import / profile;管理动作(init / config / token / lan / serve)不进 MCP,token
|
|
294
|
+
> MCP 工具集与 CLI 一致:remember / recall / search / forget / archive / reindex / export / import / profile;管理动作(init / config / token / lan / serve)不进 MCP,token 管理不远程暴露;MCP export/import 路径限记忆库内、distill 不支持 `--model`(仅本地 CLI)。
|
|
295
295
|
|
|
296
296
|
### 4.7 MCP 配置位置表
|
|
297
297
|
| 智能体 | 常见 MCP 配置位置 |
|
package/USER_GUIDE.md
CHANGED
|
@@ -356,7 +356,7 @@ yotta-memory remember FACT 主题 内容 # 智能体落盘
|
|
|
356
356
|
- token 等同密码:只给需要接入的智能体,别外传。
|
|
357
357
|
- 私密区机制级加密(v0.7 起):PREF / BOUND / COMMIT 私密记忆默认落盘为密文(AES-256-GCM 信封加密),任何没有对应 owner 密钥的 AI 即使读到密文文件也解不开;隔离 = 权限边界(scope/owner)+ 机制层机密保护。用户是数据所有者,经 `yotta-memory view` 口令解锁可看全部。
|
|
358
358
|
- 记忆读写一律走 CLI / MCP;禁止用 shell(`Get-ChildItem` / `cat` / `ls` / `type` 等)直接读改记忆库目录下的文件——否则会绕过 scope/owner 权限边界。
|
|
359
|
-
- 管理动作(init / config / token / lan / serve)不通过 MCP
|
|
359
|
+
- 管理动作(init / config / token / lan / serve)不通过 MCP 暴露,远程只能读写记忆(路径限记忆库内,export/import 的 out/src 必须落在库内;distill 不支持 `--model`,仅本地 CLI),不能改配置、不能管 token。
|
|
360
360
|
- `--no-auth` 会关闭鉴权,仅限可信内网使用。
|
|
361
361
|
- 数据主权在用户:公共 FACT 明文、随时可看可改可删;私密区加密,用户经 `yotta-memory view` 口令解锁后同样可看、可改、可删、可导出。
|
|
362
362
|
- 「记忆守则」内置底线:陪伴不操控 / 理解不越界(不贴标签)/ 诚实不伪装 / 不降格;数据安全(被遗忘权 = `forget`);宿主隔离(只写本记忆库,不读写宿主 AI 自身 memory / 配置 / 系统文件)。
|
package/bin/yotta-memory.js
CHANGED
|
@@ -22,7 +22,7 @@ const crypto = require('crypto');
|
|
|
22
22
|
const http = require('http');
|
|
23
23
|
const child_process = require('child_process');
|
|
24
24
|
|
|
25
|
-
const VERSION = '0.8.
|
|
25
|
+
const VERSION = '0.8.5';
|
|
26
26
|
const TYPES = ['FACT', 'PREF', 'BOUND', 'COMMIT'];
|
|
27
27
|
const TYPE_DIRS = { FACT: 'facts', PREF: 'prefs', BOUND: 'bounds', COMMIT: 'commits' };
|
|
28
28
|
const PUBLIC_DIR = 'facts';
|
|
@@ -100,6 +100,56 @@ function typeSubdir(type, owner) {
|
|
|
100
100
|
function defaultScope(type) {
|
|
101
101
|
return PRIVATE_TYPES.indexOf(String(type).toUpperCase()) === -1 ? 'public' : 'private';
|
|
102
102
|
}
|
|
103
|
+
// ---- 安全边界:路径必须落在记忆库根内(防 MCP 任意路径读写,v0.8.5)----
|
|
104
|
+
function resolveWithinRoot(root, p) {
|
|
105
|
+
let abs = path.isAbsolute(p) ? path.resolve(p) : path.resolve(root, p);
|
|
106
|
+
const r = path.resolve(root);
|
|
107
|
+
if (abs === r) return abs;
|
|
108
|
+
if (abs.startsWith(r + path.sep)) return abs;
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
function isWithinRoot(root, p) { return !!resolveWithinRoot(root, p); }
|
|
112
|
+
// 把命令行安全拆分为 argv(支持 ' " 引号包参,但绝不经过 shell,防元字符注入)
|
|
113
|
+
function splitCommandArgv(s) {
|
|
114
|
+
const argv = [];
|
|
115
|
+
let cur = '';
|
|
116
|
+
let quote = null;
|
|
117
|
+
for (let i = 0; i < String(s).length; i++) {
|
|
118
|
+
const c = String(s)[i];
|
|
119
|
+
if (quote) {
|
|
120
|
+
if (c === quote) { quote = null; continue; }
|
|
121
|
+
if (c === '\\' && quote === '"') { cur += String(s)[i + 1] || ''; i++; continue; }
|
|
122
|
+
cur += c; continue;
|
|
123
|
+
}
|
|
124
|
+
if (c === '"' || c === "'") { quote = c; continue; }
|
|
125
|
+
if (c === ' ' || c === '\t') { if (cur) { argv.push(cur); cur = ''; } continue; }
|
|
126
|
+
cur += c;
|
|
127
|
+
}
|
|
128
|
+
if (cur) argv.push(cur);
|
|
129
|
+
return argv;
|
|
130
|
+
}
|
|
131
|
+
// 模型命令允许清单:环境变量 YOTTA_DISTILL_MODELS(逗号分隔可执行名,不含扩展名)或 config.distill_models;
|
|
132
|
+
// 未配置时放行(本地宿主 CLI 自担风险,但已去除 shell 注入面);MCP 已在上层直接拒绝 model,不达此处。
|
|
133
|
+
function distillModelAllowlist() {
|
|
134
|
+
const env = (process.env.YOTTA_DISTILL_MODELS || '').split(',').map(function (x) { return x.trim().toLowerCase(); }).filter(Boolean);
|
|
135
|
+
if (env.length) return env;
|
|
136
|
+
const cfg = loadConfig();
|
|
137
|
+
const c = cfg && (cfg.distill_models || []);
|
|
138
|
+
if (Array.isArray(c) && c.length) return c.map(function (x) { return String(x).trim().toLowerCase(); }).filter(Boolean);
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
141
|
+
// 安全执行外部模型命令:仅允许清单内可执行名;argv 分离、不经 shell。
|
|
142
|
+
function runDistillModel(modelStr, payload) {
|
|
143
|
+
const argv = splitCommandArgv(modelStr);
|
|
144
|
+
if (!argv.length) throw new Error('模型命令为空');
|
|
145
|
+
const base = path.basename(argv[0]).toLowerCase().replace(/\.exe$/i, '');
|
|
146
|
+
const allow = distillModelAllowlist();
|
|
147
|
+
if (allow && allow.length && allow.indexOf(base) === -1) {
|
|
148
|
+
throw new Error('模型命令不在允许清单内: ' + base + '(可用: ' + allow.join(', ') + ';或设环境变量 YOTTA_DISTILL_MODELS)');
|
|
149
|
+
}
|
|
150
|
+
const r = child_process.spawnSync(argv[0], argv.slice(1), { input: payload, encoding: 'utf8', maxBuffer: 1024 * 1024, shell: false, windowsHide: true });
|
|
151
|
+
return r;
|
|
152
|
+
}
|
|
103
153
|
function parseFrontmatter(text) {
|
|
104
154
|
const m = text.match(/^---\s*\n([\s\S]*?)\n---/);
|
|
105
155
|
if (!m) return { meta: {}, body: text };
|
|
@@ -1626,7 +1676,7 @@ function distillCore(opts) {
|
|
|
1626
1676
|
if (opts.model) {
|
|
1627
1677
|
try {
|
|
1628
1678
|
const payload = JSON.stringify({ summary: lines.join('\n'), entries: entries.map(function (e) { return { type: e.type, subject: e.subject, statement: e.statement, tags: e.tags, confidence: e.confidence, access_count: e.access_count, feedback_net: e.feedback_net }; }).slice(0, 200) });
|
|
1629
|
-
const r =
|
|
1679
|
+
const r = runDistillModel(String(opts.model), payload);
|
|
1630
1680
|
if (r.stdout) modelOut = String(r.stdout).trim();
|
|
1631
1681
|
if (!modelOut) modelOut = '(模型无输出)';
|
|
1632
1682
|
body += '\n## 四、模型提炼(--model ' + opts.model + ')\n\n' + modelOut + '\n';
|
|
@@ -2603,13 +2653,13 @@ function mcpTools() {
|
|
|
2603
2653
|
{ name: 'forget', description: '删除一条记忆。file 为记忆文件路径(如 facts/2026-08-24-0001.md 或文件名)', inputSchema: { type: 'object', properties: { file: { type: 'string' } }, required: ['file'] } },
|
|
2604
2654
|
{ name: 'archive', description: '归档旧记忆。days 默认 180;threshold 默认 0.4', inputSchema: { type: 'object', properties: { days: { type: 'number' }, threshold: { type: 'number' } } } },
|
|
2605
2655
|
{ name: 'reindex', description: '重建索引(手动改 .md 后校正;扫描 facts/prefs/bounds/commits 四目录)', inputSchema: { type: 'object', properties: {} } },
|
|
2606
|
-
{ name: 'export', description: '
|
|
2607
|
-
{ name: 'import', description: '
|
|
2656
|
+
{ name: 'export', description: '导出全部记忆到记忆库内的 JSON 文件。out 可选(默认 <记忆库>/yottamemory-export-<日期>.json;仅限记忆库内路径)', inputSchema: { type: 'object', properties: { out: { type: 'string' } } } },
|
|
2657
|
+
{ name: 'import', description: '从记忆库内的 JSON 文件导入记忆。src 为文件路径(相对记忆库目录,或记忆库内绝对路径;仅限记忆库内)', inputSchema: { type: 'object', properties: { src: { type: 'string' } }, required: ['src'] } },
|
|
2608
2658
|
{ name: 'agent_info', description: '查看当前智能体身份与登记状态(远端读经 token 校验的 X-Agent-Id;本机读 YOTTA_AGENT_ID)。开工先确认「我是谁」,禁止从记忆里抄别人的 ID', inputSchema: { type: 'object', properties: {} } },
|
|
2609
2659
|
{ name: 'profile', description: '生成当前智能体的用户画像(只读聚合 private/<owner>/ 下 PREF/BOUND/COMMIT 原文,零推断,写入 private/<owner>/profile.md)。owner 默认当前智能体', inputSchema: { type: 'object', properties: { owner: { type: 'string' } } } },
|
|
2610
2660
|
{ name: 'feedback', description: '显式使用反馈(自我学习):useful/useless 调整记忆 weight/confidence/feedback_net。file 为记忆文件路径或文件名', inputSchema: { type: 'object', properties: { file: { type: 'string' }, useful: { type: 'boolean' }, useless: { type: 'boolean' }, reason: { type: 'string' } }, required: ['file'] } },
|
|
2611
2661
|
{ name: 'maintain', description: '记忆自组织(自我进化):规则层归档/遗忘/去重预览。默认 dry-run;apply 才执行,purge 才真删', inputSchema: { type: 'object', properties: { apply: { type: 'boolean' }, purge: { type: 'boolean' }, dedup: { type: 'boolean' }, threshold: { type: 'number' }, age: { type: 'number' } } } },
|
|
2612
|
-
{ name: 'distill', description: '心理日志蒸馏(自我提升):统计摘要/主题画像/知识地图。owner
|
|
2662
|
+
{ name: 'distill', description: '心理日志蒸馏(自我提升):统计摘要/主题画像/知识地图。owner 默认当前智能体(MCP 不支持 --model 外部命令)', inputSchema: { type: 'object', properties: { owner: { type: 'string' }, subject: { type: 'string' } } } },
|
|
2613
2663
|
{ name: 'explain', description: '解释单条记忆效用分项(为什么靠前/归档/遗忘)。file 为记忆文件路径或文件名', inputSchema: { type: 'object', properties: { file: { type: 'string' } }, required: ['file'] } },
|
|
2614
2664
|
];
|
|
2615
2665
|
}
|
|
@@ -2641,11 +2691,22 @@ function callTool(name, args, ctx) {
|
|
|
2641
2691
|
return { text: '已重建索引 ' + root + '(' + cnt + ' 条)', error: false };
|
|
2642
2692
|
}
|
|
2643
2693
|
if (name === 'export') {
|
|
2644
|
-
const
|
|
2694
|
+
const root = userRoot();
|
|
2695
|
+
let out = null;
|
|
2696
|
+
if (args.out) {
|
|
2697
|
+
const safe = resolveWithinRoot(root, String(args.out));
|
|
2698
|
+
if (!safe) return { text: '拒绝: MCP 导出路径必须位于记忆库内(' + root + '),已阻止任意路径写入。', error: true };
|
|
2699
|
+
out = safe;
|
|
2700
|
+
}
|
|
2701
|
+
const r = exportCore(root, out);
|
|
2645
2702
|
return { text: r.text, error: r.error };
|
|
2646
2703
|
}
|
|
2647
2704
|
if (name === 'import') {
|
|
2648
|
-
const
|
|
2705
|
+
const root = userRoot();
|
|
2706
|
+
const src = String(args.src || '');
|
|
2707
|
+
const safe = resolveWithinRoot(root, src);
|
|
2708
|
+
if (!safe) return { text: '拒绝: MCP 导入路径必须位于记忆库内(' + root + '),已阻止任意路径读取。', error: true };
|
|
2709
|
+
const r = importCore(root, safe);
|
|
2649
2710
|
return { text: r.text, error: r.error };
|
|
2650
2711
|
}
|
|
2651
2712
|
if (name === 'agent_info') {
|
|
@@ -2681,7 +2742,8 @@ function callTool(name, args, ctx) {
|
|
|
2681
2742
|
return { text: r.text, error: r.error };
|
|
2682
2743
|
}
|
|
2683
2744
|
if (name === 'distill') {
|
|
2684
|
-
|
|
2745
|
+
if (args.model) return { text: '拒绝: MCP 不支持 --model(任意命令执行风险);请在引擎主机本地 CLI 执行 yotta-memory distill --model <命令>。', error: true };
|
|
2746
|
+
const r = distillCore({ selfAgent: agent, owner: args.owner ? String(args.owner) : agent, subject: args.subject ? String(args.subject) : '', model: '' });
|
|
2685
2747
|
return { text: r.text, error: r.error };
|
|
2686
2748
|
}
|
|
2687
2749
|
if (name === 'explain') {
|
|
@@ -3328,6 +3390,10 @@ async function main() {
|
|
|
3328
3390
|
else if (a === '--password') opts.password = v;
|
|
3329
3391
|
else if (a === '--new-password') opts.newPassword = v;
|
|
3330
3392
|
else if (a === '--recovery-key') opts.recoveryKey = v;
|
|
3393
|
+
else if (a === '--reason') opts.reason = v;
|
|
3394
|
+
else if (a === '--merge') opts.merge = v;
|
|
3395
|
+
else if (a === '--model') opts.model = v;
|
|
3396
|
+
else if (a === '--subject') opts.subject = v;
|
|
3331
3397
|
} else if (a.startsWith('--')) {
|
|
3332
3398
|
console.error('未知选项: ' + a);
|
|
3333
3399
|
process.exit(2);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yottameta/yotta-memory",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.5",
|
|
4
4
|
"description": "Yuanyi (元忆) — boundary-aware, file-based memory for AI agents. File-based, zero-dependency, diff/rollback-able; FACT/PREF/BOUND/COMMIT four types (public shared / private isolated), user-level + project-level storage; v0.8 semantic search + usage feedback loop + rule-layer self-organization + psychological-log distillation (self-learning/self-evolving/self-improving).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"keywords": [
|