@yottameta/yotta-memory 0.5.2 → 0.5.4
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 +5 -5
- package/SKILL.md +4 -4
- package/USER_GUIDE.md +3 -3
- package/bin/yotta-memory.js +153 -34
- package/package.json +1 -1
- package/references/protocol.md +1 -1
package/README.md
CHANGED
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
| **检索与生命周期** | 索引 + TF 打分(中文分词友好);质量分 / 盖棺分 / 自动归档,记忆库不会无限膨胀 |
|
|
41
41
|
| **生态分发** | GitHub + npm 双源同步发布;npx skills / npm / install.sh 三种方式,覆盖 17+ 类智能体目录 |
|
|
42
42
|
| **便携记忆盘(随盘走)** | 记忆库即引擎:装在硬盘 / 主机上,插上即恢复全部记忆;引擎主机只需装 CLI 当存放点,无需装任何 AI 智能体 |
|
|
43
|
-
| **局域网共享与自启** | 每智能体独立 token(Bearer + X-Agent-Id)鉴权、可吊销;`lan enable`
|
|
43
|
+
| **局域网共享与自启** | 每智能体独立 token(Bearer + X-Agent-Id)鉴权、可吊销;`lan enable` 注册开机自启(Windows:优先计划任务;非管理员自动降级用户级 Startup 静默自启);MCP 工具集与 CLI 一致(8 个工具),管理动作不远程暴露 |
|
|
44
44
|
| **本地 / 局域网双模式** | 本地 `serve --stdio` 零进程、按需拉起(无常驻);局域网 streamable HTTP 常驻——两种模式可并存、按需选用 |
|
|
45
45
|
|
|
46
46
|
## 功能详解
|
|
@@ -106,7 +106,7 @@
|
|
|
106
106
|
|
|
107
107
|
- **记忆库即引擎**:`serve` 把记忆目录挂成 MCP 服务,目录随盘走;引擎主机只需装 CLI 当存放点,无需装任何 AI 智能体。
|
|
108
108
|
- **双模式可并存**:本地 `serve --stdio` 零进程(客户端按需拉起);局域网 streamable HTTP(默认 `0.0.0.0:8787`)+ 每智能体 token 鉴权。
|
|
109
|
-
- **开机自启**:`lan enable` 注册 Windows
|
|
109
|
+
- **开机自启**:`lan enable` 注册 Windows 开机自启——优先计划任务(默认登录自启,`--onstart` 开机即启需管理员);非管理员(计划任务被拒)自动降级为**用户级 Startup 静默自启**(免管理员);`lan disable` 移除,`lan status` 查询。
|
|
110
110
|
- **安全边界**:管理动作(init / config / token / lan / serve)不进 MCP,token 不远程暴露;远程智能体只能读写记忆,不能改配置、不能管 token。
|
|
111
111
|
- 完整操作步骤见上文「局域网多机共享」章节与 [USER_GUIDE.md](USER_GUIDE.md)。
|
|
112
112
|
|
|
@@ -185,7 +185,7 @@ npm i -g @yottameta/yotta-memory
|
|
|
185
185
|
| `yotta-memory iam <id> [--force]` | 登记本智能体唯一身份并自动落自我档案(`agents.json`,ID 必须唯一)|
|
|
186
186
|
| `yotta-memory token new --agent <id> [--force]` / `token list` / `token revoke --agent <id>` | 为智能体生成 / 列出 / 吊销访问 token(登记于记忆库 `.server/tokens.json`;同 ID 已被其它来源占用需 `--force` 覆盖,防不同智能体合流)|
|
|
187
187
|
| `yotta-memory serve [--host 0.0.0.0] [--port 8787] [--no-auth] [--stdio]` | 启动 MCP 记忆引擎(streamable HTTP 局域网 / --stdio 本地零进程模式;Bearer token + X-Agent-Id 鉴权)|
|
|
188
|
-
| `yotta-memory lan enable [--onstart] / disable / status` | 开机自启管理(Windows
|
|
188
|
+
| `yotta-memory lan enable [--onstart] / disable / status` | 开机自启管理(Windows:计划任务,默认 ONLOGON 登录自启、--onstart 开机即启需管理员;非管理员自动降级用户级 Startup 静默自启)|
|
|
189
189
|
|
|
190
190
|
类型:`FACT`(事实,公共共享)/ `PREF`(偏好)/ `BOUND`(边界)/ `COMMIT`(承诺)。
|
|
191
191
|
|
|
@@ -226,10 +226,10 @@ yotta-memory recall --type FACT --limit 10
|
|
|
226
226
|
3. 启动服务(默认监听 0.0.0.0:8787,Bearer token + X-Agent-Id 鉴权)——临时运行或注册开机自启二选一:
|
|
227
227
|
```bash
|
|
228
228
|
yotta-memory serve # 临时前台运行
|
|
229
|
-
yotta-memory lan enable # 注册开机自启(Windows
|
|
229
|
+
yotta-memory lan enable # 注册开机自启(Windows:计划任务;非管理员自动降级用户级 Startup 静默自启)
|
|
230
230
|
yotta-memory lan status # 查看自启状态
|
|
231
231
|
```
|
|
232
|
-
> `lan enable --onstart`
|
|
232
|
+
> `lan enable --onstart` 改为开机即启(需管理员);非管理员时 `lan enable` 自动改用用户级 Startup 静默自启(无需管理员);`lan disable` 移除自启。
|
|
233
233
|
|
|
234
234
|
> 首次监听 0.0.0.0 时,Windows / 系统防火墙可能询问是否放行,需允许放行,否则局域网内其它主机无法访问;`--no-auth` 会关闭鉴权,仅限可信内网使用。
|
|
235
235
|
|
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、跨会话、上次说到、续测、交接、归档、记忆盘、共享记忆、局域网记忆"
|
|
4
|
-
version: 0.5.
|
|
4
|
+
version: 0.5.4
|
|
5
5
|
license: MIT
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# yotta-memory(元忆)— 有权限边界的文件式智能体记忆
|
|
9
9
|
|
|
10
10
|
> 一句话:元忆 —— 有权限边界的文件式智能体记忆(不注入、可 diff、能回滚;FACT 共享、PREF / BOUND / COMMIT 私密隔离)。
|
|
11
|
-
> 版本:0.5.
|
|
11
|
+
> 版本:0.5.4 | 最后更新:2026-08-25
|
|
12
12
|
|
|
13
13
|
## 这是什么
|
|
14
14
|
|
|
@@ -79,7 +79,7 @@ license: MIT
|
|
|
79
79
|
| `yotta-memory iam <id> [--force]` | 登记本智能体唯一身份并自动落自我档案(`agents.json`,ID 必须唯一)|
|
|
80
80
|
| `yotta-memory token new --agent <id> [--force]` / `token list` / `token revoke --agent <id>` | 每智能体访问 token:生成 / 列出 / 吊销(登记 `<记忆库>/.server/tokens.json`;同 ID 已被其它来源占用需 `--force` 覆盖,防不同智能体合流)|
|
|
81
81
|
| `yotta-memory serve [--host 0.0.0.0] [--port 8787] [--no-auth] [--stdio]` | 启动 MCP 记忆引擎(streamable HTTP 局域网 / --stdio 本地零进程模式;Bearer token + X-Agent-Id 鉴权)|
|
|
82
|
-
| `yotta-memory lan enable [--onstart] / disable / status` | 开机自启管理(Windows
|
|
82
|
+
| `yotta-memory lan enable [--onstart] / disable / status` | 开机自启管理(Windows:计划任务,默认 ONLOGON 登录自启、--onstart 开机即启需管理员;非管理员自动降级用户级 Startup 静默自启)|
|
|
83
83
|
|
|
84
84
|
## 存储格式(摘要)
|
|
85
85
|
|
|
@@ -137,7 +137,7 @@ yotta-memory --version # 或 command -v yotta-memory / where yotta-memory
|
|
|
137
137
|
> 记忆盘场景:硬盘插上 → AI 检查盘上目录是否有数据 → 有则接入 + config 记住 → 插盘即恢复,机器记住位置。
|
|
138
138
|
|
|
139
139
|
**步骤 0.5 启动记忆引擎(仅引擎主机,供远程接入)**
|
|
140
|
-
- 本机若作引擎:🔒 **征得同意后**启动服务——临时运行 `yotta-memory serve`(默认 `0.0.0.0:8787`,Bearer token + X-Agent-Id 鉴权;`--no-auth` 仅限可信内网),或注册开机自启 `yotta-memory lan enable`(Windows
|
|
140
|
+
- 本机若作引擎:🔒 **征得同意后**启动服务——临时运行 `yotta-memory serve`(默认 `0.0.0.0:8787`,Bearer token + X-Agent-Id 鉴权;`--no-auth` 仅限可信内网),或注册开机自启 `yotta-memory lan enable`(Windows:优先计划任务,默认登录自启;非管理员自动降级用户级 Startup 静默自启,免管理员)。
|
|
141
141
|
- 本地零进程模式:本机 AI 也可用 `serve --stdio` 由 MCP 客户端按需拉起 CLI(无常驻进程,照灵魂盘)。
|
|
142
142
|
- 远程客户端接入前,先确认引擎主机 serve 已运行(`lan status` 可查)。
|
|
143
143
|
|
package/USER_GUIDE.md
CHANGED
|
@@ -111,7 +111,7 @@ yotta-memory init --dir /srv/yotta-memory # 新库:初始化(
|
|
|
111
111
|
**第 3 步:注册开机自启(可选,推荐)**
|
|
112
112
|
|
|
113
113
|
```bash
|
|
114
|
-
# Windows
|
|
114
|
+
# Windows:内置命令(优先计划任务;非管理员自动降级用户级 Startup 静默自启)
|
|
115
115
|
yotta-memory lan enable # 登录后自动启动(默认)
|
|
116
116
|
yotta-memory lan enable --onstart # 开机即启(需管理员)
|
|
117
117
|
yotta-memory lan status # 查看状态
|
|
@@ -242,7 +242,7 @@ yotta-memory remember FACT 主题 内容 # 智能体落盘
|
|
|
242
242
|
| `yotta-memory iam <id> [--force]` | 登记本智能体唯一身份并自动落自我档案(`agents.json`,ID 必须唯一)|
|
|
243
243
|
| `yotta-memory token new --agent <id> [--force]` / `token list` / `token revoke --agent <id>` | 访问 token(同 ID 已被其它来源占用需 `--force` 覆盖)|
|
|
244
244
|
| `yotta-memory serve [--port 8787] [--stdio] [--no-auth]` | 启动记忆引擎(--no-auth 关闭鉴权,仅限可信内网)|
|
|
245
|
-
| `yotta-memory lan enable [--onstart] / disable / status` |
|
|
245
|
+
| `yotta-memory lan enable [--onstart] / disable / status` | 开机自启管理(Windows:计划任务;非管理员自动降级用户级 Startup 静默自启)|
|
|
246
246
|
|
|
247
247
|
类型:`FACT`(事实,共享)/ `PREF`(偏好)/ `BOUND`(边界)/ `COMMIT`(承诺),后三类按智能体物理分目录隔离(`private/<owner>/<type>/`)。
|
|
248
248
|
|
|
@@ -259,7 +259,7 @@ yotta-memory remember FACT 主题 内容 # 智能体落盘
|
|
|
259
259
|
- 返回 401:服务在运行,是鉴权问题(token / 请求头不对)。
|
|
260
260
|
- 连接被拒 / 超时:服务没启动,或防火墙拦截。
|
|
261
261
|
|
|
262
|
-
**`lan enable`
|
|
262
|
+
**`lan enable` 计划任务被拒(Access denied 等):** 无需担心——会自动降级为**用户级 Startup 静默自启**(免管理员,重新登录后生效,启动脚本位于用户 Startup 目录);如确需计划任务,请用管理员终端重新执行;`--onstart` 模式必须管理员。
|
|
263
263
|
|
|
264
264
|
**启动引擎报端口被占用(EADDRINUSE):** 用 `--port <其它端口>` 换端口启动,两端保持一致;或先查占用:Linux `ss -tlnp | grep 8787`,Windows `netstat -ano | findstr 8787`。
|
|
265
265
|
|
package/bin/yotta-memory.js
CHANGED
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
// v0.4.0 新增:lan(Windows 计划任务开机自启 serve)/ init --dir(显式指定位置)/ serve --stdio(本地零进程模式)/ MCP 工具补 reindex/export/import
|
|
4
4
|
// v0.5.0 新增:隐私硬隔离——私密物理分目录 private/<agent_id>/{prefs,bounds,commits}/ + 关闭 --agent 越权读 + 私密写跨智能体需 --unsafe + 禁 shell 直读写(文档红线)
|
|
5
5
|
// v0.4.2 新增:iam/whoami 智能体身份自注册(agents.json 唯一性)+ 自我档案 PREF + 私密记忆须声明 owner
|
|
6
|
+
// v0.5.3 新增:CLI 选项可前置(--agent 等允许放在子命令前,不再误报"未知命令")/ lan enable 成功补"服务不会立刻启动"提示(v0.5.2 lan 引号修复无回归)
|
|
7
|
+
// v0.5.4 新增:lan enable 在非管理员(schtasks Access denied)时自动降级为用户级 Startup 静默自启(VBS sh.Run 窗口0 + autostart.cmd,node 路径 process.execPath 自动探测);lan disable/status 同时管理计划任务与 Startup 双机制
|
|
6
8
|
'use strict';
|
|
7
9
|
|
|
8
10
|
const fs = require('fs');
|
|
@@ -12,7 +14,7 @@ const crypto = require('crypto');
|
|
|
12
14
|
const http = require('http');
|
|
13
15
|
const child_process = require('child_process');
|
|
14
16
|
|
|
15
|
-
const VERSION = '0.5.
|
|
17
|
+
const VERSION = '0.5.4';
|
|
16
18
|
const TYPES = ['FACT', 'PREF', 'BOUND', 'COMMIT'];
|
|
17
19
|
const TYPE_DIRS = { FACT: 'facts', PREF: 'prefs', BOUND: 'bounds', COMMIT: 'commits' };
|
|
18
20
|
const PUBLIC_DIR = 'facts';
|
|
@@ -959,8 +961,11 @@ function cmdServeStdio() {
|
|
|
959
961
|
process.stdin.on('end', function () { process.exit(0); });
|
|
960
962
|
}
|
|
961
963
|
|
|
962
|
-
// ---- lan 命令(Windows
|
|
964
|
+
// ---- lan 命令(Windows 开机自启管理 serve)----
|
|
965
|
+
// 双机制:① schtasks 计划任务(默认,需相应权限);② 非管理员(Access denied)自动降级为
|
|
966
|
+
// 用户级 Startup 静默自启(VBS sh.Run <autostart.cmd>, 0, False + autostart.cmd;node 路径 process.execPath 自动探测,0.5.4)
|
|
963
967
|
const LAN_TASK_NAME = 'YottaMemoryServe';
|
|
968
|
+
const LAN_GEN_MARKER = 'Generated by yotta-memory lan enable';
|
|
964
969
|
function lanTaskRunCmd(opts) {
|
|
965
970
|
const host = opts.host || '0.0.0.0';
|
|
966
971
|
const port = opts.port || 8787;
|
|
@@ -968,58 +973,158 @@ function lanTaskRunCmd(opts) {
|
|
|
968
973
|
const q = (p) => /[\s"]/.test(p) ? '\\"' + p.replace(/"/g, '\\"') + '\\"' : p;
|
|
969
974
|
return q(process.execPath) + ' ' + q(__filename) + ' serve --host ' + host + ' --port ' + port;
|
|
970
975
|
}
|
|
976
|
+
function lanStartupDir() {
|
|
977
|
+
// 测试/高级用途可用 YOTTA_LAN_STARTUP_DIR 覆盖(默认用户级 Startup 目录,免管理员)
|
|
978
|
+
if (process.env.YOTTA_LAN_STARTUP_DIR) return process.env.YOTTA_LAN_STARTUP_DIR;
|
|
979
|
+
const base = process.env.APPDATA || path.join(os.homedir(), 'AppData', 'Roaming');
|
|
980
|
+
return path.join(base, 'Microsoft', 'Windows', 'Start Menu', 'Programs', 'Startup');
|
|
981
|
+
}
|
|
982
|
+
function lanAutostartDir() {
|
|
983
|
+
// 产品自有目录 ~/.yottamemory/autostart/(引擎数据目录内,非系统配置);测试可用 YOTTA_LAN_AUTOSTART_DIR 覆盖
|
|
984
|
+
if (process.env.YOTTA_LAN_AUTOSTART_DIR) return process.env.YOTTA_LAN_AUTOSTART_DIR;
|
|
985
|
+
return path.join(os.homedir(), '.yottamemory', 'autostart');
|
|
986
|
+
}
|
|
987
|
+
function lanVbsPath() { return path.join(lanStartupDir(), 'yotta-memory-serve.vbs'); }
|
|
988
|
+
function lanAutostartCmdPath() { return path.join(lanAutostartDir(), 'yotta-memory-autostart.cmd'); }
|
|
989
|
+
function lanLogPath(opts) {
|
|
990
|
+
if (process.env.YOTTA_LAN_LOG_FILE) return process.env.YOTTA_LAN_LOG_FILE;
|
|
991
|
+
return path.join(os.homedir(), '.yottamemory', 'serve-' + (opts.port || 8787) + '.log');
|
|
992
|
+
}
|
|
993
|
+
function lanAutostartCmdContent(opts) {
|
|
994
|
+
const host = opts.host || '0.0.0.0';
|
|
995
|
+
const port = opts.port || 8787;
|
|
996
|
+
const q = (p) => '"' + String(p).replace(/"/g, '""') + '"';
|
|
997
|
+
// 生成文件用纯 ASCII(避免 cmd/VBS 按系统代码页读取中文注释乱码)
|
|
998
|
+
return '@echo off\r\n'
|
|
999
|
+
+ 'chcp 65001 >nul\r\n'
|
|
1000
|
+
+ 'rem ' + LAN_GEN_MARKER + '; remove with: yotta-memory lan disable\r\n'
|
|
1001
|
+
+ q(process.execPath) + ' ' + q(__filename) + ' serve --host ' + host + ' --port ' + port + ' >> ' + q(lanLogPath(opts)) + ' 2>&1\r\n';
|
|
1002
|
+
}
|
|
1003
|
+
function lanVbsContent() {
|
|
1004
|
+
return "' " + LAN_GEN_MARKER + '; remove with: yotta-memory lan disable\r\n'
|
|
1005
|
+
+ 'Set sh = CreateObject("WScript.Shell")\r\n'
|
|
1006
|
+
+ 'sh.Run "' + String(lanAutostartCmdPath()).replace(/"/g, '""') + '", 0, False\r\n';
|
|
1007
|
+
}
|
|
1008
|
+
function lanInstallStartup(opts) {
|
|
1009
|
+
fs.mkdirSync(lanAutostartDir(), { recursive: true });
|
|
1010
|
+
fs.writeFileSync(lanAutostartCmdPath(), lanAutostartCmdContent(opts), 'utf8');
|
|
1011
|
+
fs.mkdirSync(lanStartupDir(), { recursive: true });
|
|
1012
|
+
// VBS 用 UTF-16LE+BOM:wscript 按 Unicode 读取,中文路径不乱码(纯 ANSI 读取会按系统代码页误读)
|
|
1013
|
+
fs.writeFileSync(lanVbsPath(), '\ufeff' + lanVbsContent(), 'utf16le');
|
|
1014
|
+
}
|
|
1015
|
+
function lanRemoveStartupFiles() {
|
|
1016
|
+
// 只删除带产品标记的生成文件,绝不误删用户自己的 Startup 文件
|
|
1017
|
+
const removed = [];
|
|
1018
|
+
for (const f of [lanVbsPath(), lanAutostartCmdPath()]) {
|
|
1019
|
+
try {
|
|
1020
|
+
if (lanFileHasMarker(f)) { fs.unlinkSync(f); removed.push(f); }
|
|
1021
|
+
} catch (e) { /* 单个文件失败不阻断其它清理 */ }
|
|
1022
|
+
}
|
|
1023
|
+
return removed;
|
|
1024
|
+
}
|
|
1025
|
+
function lanFileHasMarker(f) {
|
|
1026
|
+
try {
|
|
1027
|
+
if (!fs.existsSync(f)) return false;
|
|
1028
|
+
const buf = fs.readFileSync(f);
|
|
1029
|
+
const m8 = Buffer.from(LAN_GEN_MARKER, 'utf8');
|
|
1030
|
+
const m16 = Buffer.from(LAN_GEN_MARKER, 'utf16le');
|
|
1031
|
+
return buf.indexOf(m8) !== -1 || buf.indexOf(m16) !== -1;
|
|
1032
|
+
} catch (e) { return false; }
|
|
1033
|
+
}
|
|
1034
|
+
function isSchtasksAccessDenied(e) {
|
|
1035
|
+
const msg = String((e && e.stderr) || (e && e.message) || e);
|
|
1036
|
+
return /access\s+is\s+denied|access\s+denied|拒绝访问/i.test(msg);
|
|
1037
|
+
}
|
|
971
1038
|
function cmdLanEnable(opts) {
|
|
972
1039
|
if (process.platform !== 'win32') {
|
|
973
|
-
console.error('lan 命令当前仅支持 Windows
|
|
1040
|
+
console.error('lan 命令当前仅支持 Windows(计划任务 / Startup 自启);本机平台: ' + process.platform);
|
|
974
1041
|
process.exit(2);
|
|
975
1042
|
}
|
|
976
1043
|
const trigger = opts.onstart ? 'onstart' : 'onlogon';
|
|
977
1044
|
const tr = lanTaskRunCmd(opts);
|
|
978
1045
|
try {
|
|
979
1046
|
child_process.execFileSync('schtasks', ['/create', '/tn', LAN_TASK_NAME, '/tr', tr, '/sc', trigger, '/f'], { stdio: 'inherit' });
|
|
1047
|
+
console.log('已注册开机自启: 计划任务 ' + LAN_TASK_NAME + '(触发器 ' + trigger + ')');
|
|
1048
|
+
console.log('运行命令: ' + tr);
|
|
1049
|
+
console.log('备注: 服务不会立刻启动,需重启/重新登录后自动启动;如需现在运行请执行 yotta-memory serve');
|
|
1050
|
+
return;
|
|
980
1051
|
} catch (e) {
|
|
981
|
-
|
|
982
|
-
|
|
1052
|
+
const firstLine = String((e && e.stderr) || (e && e.message) || e).split(/\r?\n/)[0];
|
|
1053
|
+
if (isSchtasksAccessDenied(e)) console.error('计划任务注册被拒绝(当前用户非管理员,Access denied): ' + firstLine);
|
|
1054
|
+
else console.error('计划任务注册失败(当前环境不可用计划任务): ' + firstLine);
|
|
1055
|
+
console.log('自动改用用户级 Startup 静默自启(免管理员)...');
|
|
1056
|
+
try {
|
|
1057
|
+
lanInstallStartup(opts);
|
|
1058
|
+
} catch (e2) {
|
|
1059
|
+
console.error('写 Startup 自启失败: ' + String((e2 && e2.message) || e2).split(/\r?\n/)[0]);
|
|
1060
|
+
console.error('请用管理员终端执行 yotta-memory lan enable,或将以下命令手动加入启动项: ' + tr);
|
|
1061
|
+
process.exit(1);
|
|
1062
|
+
}
|
|
1063
|
+
console.log('已启用用户级 Startup 静默自启(无需管理员)');
|
|
1064
|
+
console.log('启动脚本: ' + lanVbsPath());
|
|
1065
|
+
console.log('启动命令: ' + lanAutostartCmdPath());
|
|
1066
|
+
console.log('日志: ' + lanLogPath(opts));
|
|
1067
|
+
console.log('备注: 服务不会立刻启动,需重新登录后自动启动;如需现在运行请执行 yotta-memory serve');
|
|
1068
|
+
console.log('提示: 如需改回计划任务,请用管理员终端重新执行 yotta-memory lan enable');
|
|
1069
|
+
return;
|
|
983
1070
|
}
|
|
984
|
-
console.log('已注册开机自启: 计划任务 ' + LAN_TASK_NAME + '(触发器 ' + trigger + ')');
|
|
985
|
-
console.log('运行命令: ' + tr);
|
|
986
1071
|
}
|
|
987
1072
|
function cmdLanDisable() {
|
|
988
1073
|
if (process.platform !== 'win32') {
|
|
989
|
-
console.error('lan 命令当前仅支持 Windows
|
|
1074
|
+
console.error('lan 命令当前仅支持 Windows(计划任务 / Startup 自启);本机平台: ' + process.platform);
|
|
990
1075
|
process.exit(2);
|
|
991
1076
|
}
|
|
1077
|
+
let sawError = false;
|
|
1078
|
+
let removedAny = false;
|
|
992
1079
|
try {
|
|
993
|
-
child_process.execFileSync('schtasks', ['/delete', '/tn', LAN_TASK_NAME, '/f'], { stdio: ['ignore', 'pipe', '
|
|
1080
|
+
child_process.execFileSync('schtasks', ['/delete', '/tn', LAN_TASK_NAME, '/f'], { stdio: ['ignore', 'pipe', 'pipe'] });
|
|
1081
|
+
console.log('已移除开机自启计划任务 ' + LAN_TASK_NAME);
|
|
1082
|
+
removedAny = true;
|
|
994
1083
|
} catch (e) {
|
|
995
1084
|
const msg = String((e && e.stderr) || (e && e.message) || e);
|
|
996
|
-
if (
|
|
997
|
-
console.
|
|
998
|
-
|
|
1085
|
+
if (!/cannot find the (path|file)|没有找到|找不到|不存在/i.test(msg)) {
|
|
1086
|
+
console.error('移除计划任务失败: ' + msg.split(/\r?\n/)[0]);
|
|
1087
|
+
sawError = true;
|
|
999
1088
|
}
|
|
1000
|
-
console.error('移除计划任务失败: ' + msg.split(/\r?\n/)[0]);
|
|
1001
|
-
process.exit(1);
|
|
1002
1089
|
}
|
|
1003
|
-
|
|
1090
|
+
for (const f of lanRemoveStartupFiles()) {
|
|
1091
|
+
console.log('已移除 Startup 自启文件: ' + f);
|
|
1092
|
+
removedAny = true;
|
|
1093
|
+
}
|
|
1094
|
+
if (!removedAny && !sawError) console.log('未启用: 未发现任何自启配置(计划任务与 Startup 文件均不存在)');
|
|
1095
|
+
if (sawError) process.exit(1);
|
|
1004
1096
|
}
|
|
1005
1097
|
function cmdLanStatus() {
|
|
1006
1098
|
if (process.platform !== 'win32') {
|
|
1007
|
-
console.log('lan 命令当前仅支持 Windows
|
|
1099
|
+
console.log('lan 命令当前仅支持 Windows(计划任务 / Startup 自启);本机平台: ' + process.platform);
|
|
1008
1100
|
return;
|
|
1009
1101
|
}
|
|
1102
|
+
let taskFound = false;
|
|
1010
1103
|
try {
|
|
1011
1104
|
const out = child_process.execFileSync('schtasks', ['/query', '/tn', LAN_TASK_NAME, '/fo', 'LIST', '/v'], { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] });
|
|
1012
|
-
|
|
1105
|
+
taskFound = true;
|
|
1106
|
+
console.log('计划任务 ' + LAN_TASK_NAME + ': 已启用');
|
|
1013
1107
|
const re = /^(状态|Status)\s*:\s*(.+)$/;
|
|
1014
1108
|
for (const line of String(out).split(/\r?\n/)) {
|
|
1015
1109
|
const m = re.exec(line.trim());
|
|
1016
|
-
if (m) console.log(m[1] + ': ' + m[2]);
|
|
1110
|
+
if (m) console.log(' ' + m[1] + ': ' + m[2]);
|
|
1017
1111
|
}
|
|
1018
1112
|
} catch (e) {
|
|
1019
|
-
console.log('
|
|
1113
|
+
console.log('计划任务 ' + LAN_TASK_NAME + ': 未启用');
|
|
1020
1114
|
}
|
|
1115
|
+
const vbsOk = lanFileHasMarker(lanVbsPath());
|
|
1116
|
+
const cmdOk = lanFileHasMarker(lanAutostartCmdPath());
|
|
1117
|
+
if (vbsOk && cmdOk) {
|
|
1118
|
+
console.log('Startup 静默自启(免管理员): 已启用');
|
|
1119
|
+
console.log(' 启动脚本: ' + lanVbsPath());
|
|
1120
|
+
console.log(' 启动命令: ' + lanAutostartCmdPath());
|
|
1121
|
+
} else if (vbsOk || cmdOk) {
|
|
1122
|
+
console.log('Startup 静默自启: 部分残留(建议执行 yotta-memory lan disable 后重新 lan enable)');
|
|
1123
|
+
} else {
|
|
1124
|
+
console.log('Startup 静默自启(免管理员): 未启用');
|
|
1125
|
+
}
|
|
1126
|
+
if (!taskFound && !vbsOk && !cmdOk) console.log('未启用任何开机自启(可用 yotta-memory lan enable 注册)');
|
|
1021
1127
|
}
|
|
1022
|
-
|
|
1023
1128
|
// ---- usage / main ----
|
|
1024
1129
|
function usage() {
|
|
1025
1130
|
console.log([
|
|
@@ -1042,7 +1147,7 @@ function usage() {
|
|
|
1042
1147
|
' yotta-memory token list 列出已登记智能体',
|
|
1043
1148
|
' yotta-memory token revoke --agent <id> 吊销某智能体 token',
|
|
1044
1149
|
' yotta-memory serve [--host 0.0.0.0] [--port 8787] [--no-auth] [--stdio] 启动 MCP 记忆引擎(streamable HTTP;--stdio 本地零进程模式)',
|
|
1045
|
-
' yotta-memory lan enable [--onstart] | disable | status 开机自启管理(Windows 计划任务,默认 ONLOGON
|
|
1150
|
+
' yotta-memory lan enable [--onstart] | disable | status 开机自启管理(Windows 计划任务,默认 ONLOGON;非管理员自动降级用户级 Startup 静默自启)',
|
|
1046
1151
|
' yotta-memory --version 版本',
|
|
1047
1152
|
'',
|
|
1048
1153
|
'类型: FACT(公共共享) / PREF(偏好) / BOUND(边界) / COMMIT(承诺)',
|
|
@@ -1055,14 +1160,13 @@ function usage() {
|
|
|
1055
1160
|
function main() {
|
|
1056
1161
|
const args = process.argv.slice(2);
|
|
1057
1162
|
if (!args.length) { usage(); return; }
|
|
1058
|
-
const first = args[0];
|
|
1059
|
-
if (first === '--version' || first === '-v') { console.log(VERSION); return; }
|
|
1060
|
-
if (first === '--help' || first === '-h') { usage(); return; }
|
|
1061
1163
|
const opts = {};
|
|
1062
1164
|
const positional = [];
|
|
1063
1165
|
const valueOpts = new Set(['--type', '--limit', '--days', '--out', '--owner', '--agent', '--threshold', '--scope', '--host', '--port', '--dir']);
|
|
1064
|
-
for (let i =
|
|
1166
|
+
for (let i = 0; i < args.length; i++) {
|
|
1065
1167
|
const a = args[i];
|
|
1168
|
+
if (a === '--version' || a === '-v') { console.log(VERSION); return; }
|
|
1169
|
+
if (a === '--help' || a === '-h') { usage(); return; }
|
|
1066
1170
|
if (a === '--project') opts.project = true;
|
|
1067
1171
|
else if (a === '--all') opts.all = true;
|
|
1068
1172
|
else if (a === '--unsafe') opts.unsafe = true;
|
|
@@ -1090,26 +1194,28 @@ function main() {
|
|
|
1090
1194
|
positional.push(a);
|
|
1091
1195
|
}
|
|
1092
1196
|
}
|
|
1197
|
+
const first = positional[0];
|
|
1198
|
+
const rest = positional.slice(1);
|
|
1093
1199
|
switch (first) {
|
|
1094
1200
|
case 'init': cmdInit(opts); break;
|
|
1095
1201
|
case 'whoami': cmdWhoami(); break;
|
|
1096
|
-
case 'iam': cmdIam(
|
|
1202
|
+
case 'iam': cmdIam(rest[0], opts); break;
|
|
1097
1203
|
case 'config': {
|
|
1098
|
-
const sub =
|
|
1099
|
-
if (sub === 'set') cmdConfigSet(
|
|
1204
|
+
const sub = rest[0];
|
|
1205
|
+
if (sub === 'set') cmdConfigSet(rest[1], rest[2]);
|
|
1100
1206
|
else if (sub === 'get') cmdConfigGet();
|
|
1101
1207
|
else { console.error('config 子命令: set memory_home <目录> / get'); process.exit(2); }
|
|
1102
1208
|
break;
|
|
1103
1209
|
}
|
|
1104
|
-
case 'remember': cmdRemember(
|
|
1105
|
-
case 'recall': cmdRecall(
|
|
1106
|
-
case 'forget': cmdForget(
|
|
1210
|
+
case 'remember': cmdRemember(rest[0], rest[1], rest[2], opts); break;
|
|
1211
|
+
case 'recall': cmdRecall(rest[0] || null, opts); break;
|
|
1212
|
+
case 'forget': cmdForget(rest[0]); break;
|
|
1107
1213
|
case 'archive': cmdArchive(opts); break;
|
|
1108
1214
|
case 'reindex': cmdReindex(); break;
|
|
1109
1215
|
case 'export': cmdExport(opts.out); break;
|
|
1110
|
-
case 'import': cmdImport(
|
|
1216
|
+
case 'import': cmdImport(rest[0]); break;
|
|
1111
1217
|
case 'token': {
|
|
1112
|
-
const sub =
|
|
1218
|
+
const sub = rest[0];
|
|
1113
1219
|
if (sub === 'new') cmdTokenNew(opts.agent, opts);
|
|
1114
1220
|
else if (sub === 'list') cmdTokenList();
|
|
1115
1221
|
else if (sub === 'revoke') cmdTokenRevoke(opts.agent);
|
|
@@ -1118,7 +1224,7 @@ function main() {
|
|
|
1118
1224
|
}
|
|
1119
1225
|
case 'serve': cmdServe(opts); break;
|
|
1120
1226
|
case 'lan': {
|
|
1121
|
-
const sub =
|
|
1227
|
+
const sub = rest[0];
|
|
1122
1228
|
if (sub === 'enable') cmdLanEnable(opts);
|
|
1123
1229
|
else if (sub === 'disable') cmdLanDisable();
|
|
1124
1230
|
else if (sub === 'status') cmdLanStatus();
|
|
@@ -1126,6 +1232,7 @@ function main() {
|
|
|
1126
1232
|
break;
|
|
1127
1233
|
}
|
|
1128
1234
|
default:
|
|
1235
|
+
if (!first) { usage(); return; }
|
|
1129
1236
|
console.error('未知命令: ' + first);
|
|
1130
1237
|
usage();
|
|
1131
1238
|
process.exit(2);
|
|
@@ -1151,4 +1258,16 @@ module.exports = {
|
|
|
1151
1258
|
collectEntryFiles: collectEntryFiles,
|
|
1152
1259
|
migrateLayout: migrateLayout,
|
|
1153
1260
|
typeSubdir: typeSubdir,
|
|
1261
|
+
lanTaskRunCmd: lanTaskRunCmd,
|
|
1262
|
+
lanStartupDir: lanStartupDir,
|
|
1263
|
+
lanAutostartDir: lanAutostartDir,
|
|
1264
|
+
lanVbsPath: lanVbsPath,
|
|
1265
|
+
lanAutostartCmdPath: lanAutostartCmdPath,
|
|
1266
|
+
lanLogPath: lanLogPath,
|
|
1267
|
+
lanAutostartCmdContent: lanAutostartCmdContent,
|
|
1268
|
+
lanVbsContent: lanVbsContent,
|
|
1269
|
+
lanInstallStartup: lanInstallStartup,
|
|
1270
|
+
lanRemoveStartupFiles: lanRemoveStartupFiles,
|
|
1271
|
+
lanFileHasMarker: lanFileHasMarker,
|
|
1272
|
+
isSchtasksAccessDenied: isSchtasksAccessDenied,
|
|
1154
1273
|
};
|
package/package.json
CHANGED
package/references/protocol.md
CHANGED