remnote-bridge 0.1.11 → 0.1.13
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/dist/cli/addon/addon-manager.js +163 -0
- package/dist/cli/addon/registry.js +24 -0
- package/dist/cli/commands/addon.js +149 -0
- package/dist/cli/commands/clean.js +121 -52
- package/dist/cli/commands/connect.js +72 -33
- package/dist/cli/commands/disconnect.js +19 -19
- package/dist/cli/commands/edit-rem.js +8 -36
- package/dist/cli/commands/edit-tree.js +3 -20
- package/dist/cli/commands/health.js +19 -18
- package/dist/cli/commands/read-context.js +3 -20
- package/dist/cli/commands/read-globe.js +3 -20
- package/dist/cli/commands/read-rem.js +6 -32
- package/dist/cli/commands/read-tree.js +3 -20
- package/dist/cli/commands/search.js +97 -21
- package/dist/cli/config.js +148 -72
- package/dist/cli/daemon/daemon.js +104 -24
- package/dist/cli/daemon/dev-server.js +9 -1
- package/dist/cli/daemon/pid.js +36 -22
- package/dist/cli/daemon/registry.js +160 -0
- package/dist/cli/daemon/send-request.js +11 -11
- package/dist/cli/daemon/static-server.js +97 -34
- package/dist/cli/handlers/edit-handler.js +49 -140
- package/dist/cli/handlers/read-handler.js +9 -9
- package/dist/cli/handlers/rem-cache.js +10 -5
- package/dist/cli/handlers/tree-parser.js +16 -9
- package/dist/cli/main.js +67 -19
- package/dist/cli/protocol.js +18 -4
- package/dist/cli/server/config-server.js +280 -14
- package/dist/cli/server/ws-server.js +93 -44
- package/dist/cli/utils/output.js +29 -0
- package/dist/mcp/format.js +43 -0
- package/dist/mcp/index.js +0 -55
- package/dist/mcp/instructions.js +424 -216
- package/dist/mcp/resources/edit-rem-guide.js +37 -158
- package/dist/mcp/resources/edit-tree-guide.js +1 -1
- package/dist/mcp/resources/error-reference.js +9 -13
- package/dist/mcp/resources/rem-object-fields.js +6 -6
- package/dist/mcp/tools/edit-tools.js +69 -8
- package/dist/mcp/tools/infra-tools.js +44 -8
- package/dist/mcp/tools/read-tools.js +136 -20
- package/package.json +2 -2
- package/remnote-plugin/dist/bridge_widget-sandbox.js +17 -17
- package/remnote-plugin/dist/bridge_widget.js +17 -17
- package/remnote-plugin/dist/index-sandbox.js +31 -31
- package/remnote-plugin/dist/index.js +31 -31
- package/remnote-plugin/dist/manifest.json +1 -1
- package/remnote-plugin/package.json +1 -1
- package/remnote-plugin/public/manifest.json +1 -1
- package/remnote-plugin/src/bridge/multi-connection-manager.ts +151 -0
- package/remnote-plugin/src/bridge/websocket-client.ts +62 -16
- package/remnote-plugin/src/services/index.ts +0 -8
- package/remnote-plugin/src/services/read-rem.ts +1 -9
- package/remnote-plugin/src/services/search.ts +13 -10
- package/remnote-plugin/src/settings.ts +9 -7
- package/remnote-plugin/src/utils/index.ts +0 -5
- package/remnote-plugin/src/widgets/bridge_widget.tsx +105 -20
- package/remnote-plugin/src/widgets/index.tsx +41 -44
- package/remnote-plugin/webpack.config.js +35 -0
- package/skills/remnote-bridge/SKILL.md +45 -40
- package/skills/remnote-bridge/instructions/addon.md +134 -0
- package/skills/remnote-bridge/instructions/clean.md +110 -0
- package/skills/remnote-bridge/instructions/connect.md +80 -37
- package/skills/remnote-bridge/instructions/disconnect.md +22 -9
- package/skills/remnote-bridge/instructions/edit-rem.md +113 -327
- package/skills/remnote-bridge/instructions/health.md +23 -13
- package/skills/remnote-bridge/instructions/install-skill.md +58 -0
- package/skills/remnote-bridge/instructions/overall.md +99 -35
- package/skills/remnote-bridge/instructions/read-rem.md +15 -15
- package/skills/remnote-bridge/instructions/search.md +77 -18
- package/skills/remnote-bridge/instructions/setup.md +5 -6
|
@@ -6,11 +6,19 @@
|
|
|
6
6
|
|
|
7
7
|
## 功能
|
|
8
8
|
|
|
9
|
-
`health`
|
|
9
|
+
`health` 分两步检查指定实例的系统状态:
|
|
10
10
|
|
|
11
|
-
1.
|
|
11
|
+
1. **本地检查**:通过注册表查找实例,确认 daemon 进程是否存活
|
|
12
12
|
2. **远程检查**:通过 WS 连接 daemon,获取 Plugin 连接状态和 SDK 就绪状态
|
|
13
13
|
|
|
14
|
+
### 多实例支持
|
|
15
|
+
|
|
16
|
+
通过 `--instance <name>` 指定要检查的实例。不指定时检查 `default` 实例。
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
remnote-bridge health --instance work
|
|
20
|
+
```
|
|
21
|
+
|
|
14
22
|
---
|
|
15
23
|
|
|
16
24
|
## 用法
|
|
@@ -24,7 +32,7 @@ remnote-bridge health
|
|
|
24
32
|
输出示例(全部健康):
|
|
25
33
|
|
|
26
34
|
```
|
|
27
|
-
✅ 守护进程 运行中(PID: 12345,已运行 5 分钟)
|
|
35
|
+
✅ 守护进程 运行中(PID: 12345,实例: default,槽位: 0,已运行 5 分钟)
|
|
28
36
|
✅ Plugin 已连接
|
|
29
37
|
✅ SDK 就绪
|
|
30
38
|
|
|
@@ -34,7 +42,7 @@ remnote-bridge health
|
|
|
34
42
|
输出示例(部分不健康):
|
|
35
43
|
|
|
36
44
|
```
|
|
37
|
-
✅ 守护进程 运行中(PID: 12345,已运行 2 分钟)
|
|
45
|
+
✅ 守护进程 运行中(PID: 12345,实例: work,槽位: 1,已运行 2 分钟)
|
|
38
46
|
❌ Plugin 未连接
|
|
39
47
|
❌ SDK 未就绪
|
|
40
48
|
|
|
@@ -80,11 +88,12 @@ remnote-bridge health --reload
|
|
|
80
88
|
"ok": true,
|
|
81
89
|
"command": "health",
|
|
82
90
|
"exitCode": 0,
|
|
91
|
+
"instance": "default",
|
|
92
|
+
"slotIndex": 0,
|
|
83
93
|
"daemon": { "running": true, "pid": 12345, "reachable": true, "uptime": 300 },
|
|
84
94
|
"plugin": { "connected": true },
|
|
85
95
|
"sdk": { "ready": true },
|
|
86
|
-
"timeoutRemaining": 1500
|
|
87
|
-
"timestamp": "2026-03-06T10:00:00.000Z"
|
|
96
|
+
"timeoutRemaining": 1500
|
|
88
97
|
}
|
|
89
98
|
```
|
|
90
99
|
|
|
@@ -95,11 +104,12 @@ remnote-bridge health --reload
|
|
|
95
104
|
"ok": false,
|
|
96
105
|
"command": "health",
|
|
97
106
|
"exitCode": 1,
|
|
107
|
+
"instance": "work",
|
|
108
|
+
"slotIndex": 1,
|
|
98
109
|
"daemon": { "running": true, "pid": 12345, "reachable": true, "uptime": 120 },
|
|
99
110
|
"plugin": { "connected": false },
|
|
100
111
|
"sdk": { "ready": false },
|
|
101
|
-
"timeoutRemaining": 1680
|
|
102
|
-
"timestamp": "2026-03-06T10:00:00.000Z"
|
|
112
|
+
"timeoutRemaining": 1680
|
|
103
113
|
}
|
|
104
114
|
```
|
|
105
115
|
|
|
@@ -110,10 +120,10 @@ remnote-bridge health --reload
|
|
|
110
120
|
"ok": false,
|
|
111
121
|
"command": "health",
|
|
112
122
|
"exitCode": 2,
|
|
123
|
+
"instance": "default",
|
|
113
124
|
"daemon": { "running": false },
|
|
114
125
|
"plugin": { "connected": false },
|
|
115
|
-
"sdk": { "ready": false }
|
|
116
|
-
"timestamp": "2026-03-06T10:00:00.000Z"
|
|
126
|
+
"sdk": { "ready": false }
|
|
117
127
|
}
|
|
118
128
|
```
|
|
119
129
|
|
|
@@ -123,7 +133,7 @@ remnote-bridge health --reload
|
|
|
123
133
|
|
|
124
134
|
| 检查项 | 检查方式 | 含义 |
|
|
125
135
|
|--------|----------|------|
|
|
126
|
-
| **daemon** |
|
|
136
|
+
| **daemon** | 注册表查找 + `kill(pid, 0)` 探活 | 守护进程是否在运行且可达 |
|
|
127
137
|
| **plugin** | daemon 内部的 `pluginConnected` 状态 | RemNote Plugin 是否已通过 WS 连接到 daemon |
|
|
128
138
|
| **sdk** | Plugin 的 hello 握手中的 `sdkReady` 字段 | RemNote SDK 是否就绪(知识库已加载,可调用 API) |
|
|
129
139
|
|
|
@@ -179,7 +189,7 @@ headless 模式下 `health` 基础输出额外包含 `headless` 对象:
|
|
|
179
189
|
"headless": {
|
|
180
190
|
"status": "running",
|
|
181
191
|
"chromeConnected": true,
|
|
182
|
-
"pageUrl": "http://localhost:
|
|
192
|
+
"pageUrl": "http://localhost:29101",
|
|
183
193
|
"reloadCount": 0,
|
|
184
194
|
"lastError": null,
|
|
185
195
|
"recentConsoleErrors": []
|
|
@@ -218,7 +228,7 @@ headless 模式下 `health` 基础输出额外包含 `headless` 对象:
|
|
|
218
228
|
| 症状 | 可能原因 | 解决方案 |
|
|
219
229
|
|------|----------|----------|
|
|
220
230
|
| daemon 未运行 | 未执行 connect / 已超时关闭 | 执行 `connect` |
|
|
221
|
-
| daemon 运行但不可达 | WS 端口被占用或配置不匹配 | 检查
|
|
231
|
+
| daemon 运行但不可达 | WS 端口被占用或配置不匹配 | 检查 `~/.remnote-bridge/slots.json` 中的端口配置 |
|
|
222
232
|
| Plugin 未连接(标准模式) | RemNote 未打开 / Plugin 未安装 / URL 不匹配 | 打开 RemNote,确认 Plugin 中的 WS URL 设置 |
|
|
223
233
|
| Plugin 未连接(headless 模式) | Chrome 页面加载异常 | `health --diagnose` 查看截图和状态,`health --reload` 重载页面 |
|
|
224
234
|
| SDK 未就绪 | 知识库加载中 / Plugin 异常 | 等待几秒后重试,或刷新 RemNote 页面 |
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# install-skill
|
|
2
|
+
|
|
3
|
+
> 将 remnote-bridge Skill 安装到 AI Agent 环境中。
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 功能
|
|
8
|
+
|
|
9
|
+
`install-skill` 将 Skill 文档(SKILL.md + instructions/*.md)安装到 AI Agent 可发现的位置。支持两种安装方式:
|
|
10
|
+
|
|
11
|
+
| 方式 | 说明 |
|
|
12
|
+
|:-----|:-----|
|
|
13
|
+
| Vercel Skills CLI(默认) | 通过 `npx skills add` 安装,适用于支持 Vercel Skills 生态的 Agent |
|
|
14
|
+
| Claude Code 直接复制(fallback) | 将文件复制到 `~/.claude/skills/remnote-bridge/`,仅适用于 Claude Code |
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## 用法
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
# 通过 Vercel Skills CLI 安装(推荐)
|
|
22
|
+
remnote-bridge install-skill
|
|
23
|
+
|
|
24
|
+
# 直接复制到 Claude Code skills 目录
|
|
25
|
+
remnote-bridge install-skill-copy
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## 安装逻辑
|
|
31
|
+
|
|
32
|
+
### install-skill
|
|
33
|
+
|
|
34
|
+
1. 检测 `npx` 是否可用
|
|
35
|
+
2. 可用 → 执行 `npx skills add baobao700508/unofficial-remnote-bridge-cli -s remnote-bridge`
|
|
36
|
+
3. 不可用或执行失败 → 自动 fallback 到文件复制模式
|
|
37
|
+
|
|
38
|
+
### install-skill-copy
|
|
39
|
+
|
|
40
|
+
直接将 Skill 文件从 npm 包内复制到 `~/.claude/skills/remnote-bridge/`:
|
|
41
|
+
- `SKILL.md`
|
|
42
|
+
- `instructions/*.md`(所有 Markdown 文件)
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## 退出码
|
|
47
|
+
|
|
48
|
+
| 退出码 | 含义 |
|
|
49
|
+
|:-------|:-----|
|
|
50
|
+
| 0 | 安装成功 |
|
|
51
|
+
| 1 | 安装失败(找不到源文件、权限不足等) |
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## AI Agent 注意事项
|
|
56
|
+
|
|
57
|
+
- 此命令通常由用户在初始设置时手动执行,Agent 一般不需要调用
|
|
58
|
+
- 安装完成后,Agent 即可通过 Skill 接口发现和使用 remnote-bridge 功能
|
|
@@ -128,9 +128,9 @@ Rem 有两个**独立维度**的类型:
|
|
|
128
128
|
|:-----|:-----|:-----|
|
|
129
129
|
| 创建 Portal | `edit-tree` | 新增行 `<!--portal refs:id1,id2-->` |
|
|
130
130
|
| 删除 Portal | `edit-tree` | 从大纲中移除 Portal 行(与删除普通行相同) |
|
|
131
|
-
| 修改引用列表(增删引用的 Rem) | `edit-rem` |
|
|
131
|
+
| 修改引用列表(增删引用的 Rem) | `edit-rem` | 直接修改 changes 中的 `portalDirectlyIncludedRem` 数组 |
|
|
132
132
|
| 移动 Portal(换父节点/位置) | `edit-tree` | 与移动普通行相同 |
|
|
133
|
-
| 读取 Portal | `read-rem` | 自动输出
|
|
133
|
+
| 读取 Portal | `read-rem` | 自动输出 8 字段简化 JSON |
|
|
134
134
|
|
|
135
135
|
### 2.6 Powerup 机制简述
|
|
136
136
|
|
|
@@ -199,19 +199,53 @@ health → 确认三层就绪 → 会话可用
|
|
|
199
199
|
disconnect → daemon 关闭 → 会话结束,缓存清空
|
|
200
200
|
```
|
|
201
201
|
|
|
202
|
-
> **重要**:`connect` 成功只意味着 daemon 已启动,Plugin 并未自动连接。首次使用需用户在 RemNote
|
|
202
|
+
> **重要**:`connect` 成功只意味着 daemon 已启动,Plugin 并未自动连接。首次使用需用户在 RemNote「开发你的插件」中填入对应的 Plugin 服务地址;非首次只需刷新 RemNote 页面。必须引导用户完成此步后再用 `health` 确认就绪。
|
|
203
203
|
|
|
204
|
-
`connect`
|
|
204
|
+
`connect` 启动三个服务,端口由槽位自动分配:
|
|
205
205
|
|
|
206
|
-
| 服务 |
|
|
207
|
-
|
|
208
|
-
| WS Server |
|
|
209
|
-
| Plugin 服务 |
|
|
210
|
-
| ConfigServer |
|
|
206
|
+
| 服务 | 槽位 0 端口 | 用途 |
|
|
207
|
+
|:-----|:-----------|:-----|
|
|
208
|
+
| WS Server | 29100 | CLI ↔ daemon ↔ Plugin 通信 |
|
|
209
|
+
| Plugin 服务 | 29101 | 加载 Plugin 到 RemNote(默认静态服务器,`--dev` 时为 webpack-dev-server) |
|
|
210
|
+
| ConfigServer | 29102 | HTTP 配置界面 |
|
|
211
211
|
|
|
212
212
|
超时机制:daemon 默认 **30 分钟无活动**自动关闭。每次收到 CLI 请求时重置计时器。
|
|
213
213
|
|
|
214
|
-
### 3.3
|
|
214
|
+
### 3.3 多实例支持
|
|
215
|
+
|
|
216
|
+
系统支持最多 **4 个并发实例**,每个实例连接不同的 RemNote 知识库。
|
|
217
|
+
|
|
218
|
+
```bash
|
|
219
|
+
# 启动默认实例
|
|
220
|
+
remnote-bridge connect
|
|
221
|
+
|
|
222
|
+
# 启动额外实例
|
|
223
|
+
remnote-bridge connect --instance work
|
|
224
|
+
remnote-bridge connect --instance personal
|
|
225
|
+
|
|
226
|
+
# 查看指定实例状态
|
|
227
|
+
remnote-bridge health --instance work
|
|
228
|
+
|
|
229
|
+
# 停止指定实例
|
|
230
|
+
remnote-bridge disconnect --instance work
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
**槽位分配**:每个实例启动时自动占用第一个空闲槽位,端口固定分配:
|
|
234
|
+
|
|
235
|
+
| 槽位 | WS 端口 | Plugin 服务端口 | 配置端口 |
|
|
236
|
+
|:-----|:--------|:---------------|:---------|
|
|
237
|
+
| 0 | 29100 | 29101 | 29102 |
|
|
238
|
+
| 1 | 29110 | 29111 | 29112 |
|
|
239
|
+
| 2 | 29120 | 29121 | 29122 |
|
|
240
|
+
| 3 | 29130 | 29131 | 29132 |
|
|
241
|
+
|
|
242
|
+
**实例名解析优先级**:CLI `--instance` > 环境变量 `REMNOTE_BRIDGE_INSTANCE` > 默认值 `default`。
|
|
243
|
+
|
|
244
|
+
**Plugin 自动发现**:Plugin 启动后通过 `/api/discovery` 获取其孪生 daemon 的连接信息(WS 端口、槽位索引等),自动建立连接。一个 Plugin 可同时连接最多 4 个 daemon。
|
|
245
|
+
|
|
246
|
+
**业务命令的实例选择**:`read-rem`、`edit-rem` 等业务命令自动路由到 `--instance` 指定的实例(默认 `default`)。各实例的缓存相互独立。
|
|
247
|
+
|
|
248
|
+
### 3.4 健康状态
|
|
215
249
|
|
|
216
250
|
`health` 命令检查三层状态:
|
|
217
251
|
|
|
@@ -233,9 +267,12 @@ disconnect → daemon 关闭 → 会话结束,缓存清空
|
|
|
233
267
|
|
|
234
268
|
| 命令 | 功能 | 需要 Plugin | 详细文档 |
|
|
235
269
|
|:-----|:-----|:------------|:---------|
|
|
236
|
-
| `connect` |
|
|
237
|
-
| `health` |
|
|
238
|
-
| `disconnect` |
|
|
270
|
+
| `connect` | 启动守护进程(支持 `--instance`) | 否 | `connect.md` |
|
|
271
|
+
| `health` | 检查系统状态(支持 `--instance`) | 否 | `health.md` |
|
|
272
|
+
| `disconnect` | 停止守护进程(支持 `--instance`) | 否 | `disconnect.md` |
|
|
273
|
+
| `addon` | 管理增强项目(list/install/uninstall) | 否 | `addon.md` |
|
|
274
|
+
| `clean` | 清理所有进程、缓存和注册表 | 否 | `clean.md` |
|
|
275
|
+
| `install-skill` | 安装 Skill 到 Agent 环境 | 否 | `install-skill.md` |
|
|
239
276
|
|
|
240
277
|
#### 读取命令
|
|
241
278
|
|
|
@@ -251,7 +288,7 @@ disconnect → daemon 关闭 → 会话结束,缓存清空
|
|
|
251
288
|
|
|
252
289
|
| 命令 | 功能 | 前置条件 | 安全机制 | 详细文档 |
|
|
253
290
|
|:-----|:-----|:---------|:---------|:---------|
|
|
254
|
-
| `edit-rem` |
|
|
291
|
+
| `edit-rem` | 直接修改 Rem 属性字段 | 先 `read-rem` | 两道防线 + 字段白名单 | `edit-rem.md` |
|
|
255
292
|
| `edit-tree` | str_replace 编辑树结构 | 先 `read-tree` | 三道防线 + diff | `edit-tree.md` |
|
|
256
293
|
|
|
257
294
|
### 4.2 探索决策指南
|
|
@@ -373,7 +410,7 @@ Agent 需要根据用户意图选择正确的读取命令:
|
|
|
373
410
|
```bash
|
|
374
411
|
read-rem kLrIOHJLyMd8Y2lyA --fields text,type
|
|
375
412
|
read-tree kLrIOHJLyMd8Y2lyA --depth 2
|
|
376
|
-
edit-rem kLrIOHJLyMd8Y2lyA --
|
|
413
|
+
edit-rem kLrIOHJLyMd8Y2lyA --changes '{"type":"descriptor"}'
|
|
377
414
|
```
|
|
378
415
|
|
|
379
416
|
- 位置参数 = remId 或关键词
|
|
@@ -385,7 +422,7 @@ edit-rem kLrIOHJLyMd8Y2lyA --old-str '"concept"' --new-str '"descriptor"'
|
|
|
385
422
|
```bash
|
|
386
423
|
read-rem --json '{"remId":"kLrIOHJLyMd8Y2lyA","fields":["text","type"]}'
|
|
387
424
|
read-tree --json '{"remId":"kLrIOHJLyMd8Y2lyA","depth":2}'
|
|
388
|
-
edit-rem --json '{"remId":"kLrIOHJLyMd8Y2lyA","
|
|
425
|
+
edit-rem --json '{"remId":"kLrIOHJLyMd8Y2lyA","changes":{"type":"descriptor"}}'
|
|
389
426
|
```
|
|
390
427
|
|
|
391
428
|
- **位置参数 = JSON 字符串**,所有参数打包在 JSON 对象中
|
|
@@ -454,8 +491,8 @@ RemObject 是本项目对 RemNote Rem 的标准化表示,包含 51 个字段
|
|
|
454
491
|
| 标记 | 含义 | 数量 | 输出条件 |
|
|
455
492
|
|:-----|:-----|:-----|:---------|
|
|
456
493
|
| RW | 可读可写 | 20 | 默认输出 |
|
|
457
|
-
| R | 只读 |
|
|
458
|
-
| R-F | 只读低频 |
|
|
494
|
+
| R | 只读 | 13 | 默认输出 |
|
|
495
|
+
| R-F | 只读低频 | 18 | 仅 `--full` 输出 |
|
|
459
496
|
|
|
460
497
|
### 7.2 核心字段速览
|
|
461
498
|
|
|
@@ -463,7 +500,7 @@ RemObject 是本项目对 RemNote Rem 的标准化表示,包含 51 个字段
|
|
|
463
500
|
标识: id
|
|
464
501
|
内容: text [RW], backText [RW]
|
|
465
502
|
类型: type [RW], isDocument [RW]
|
|
466
|
-
结构: parent [RW], children [R]
|
|
503
|
+
结构: parent [RW], children [R-F]
|
|
467
504
|
格式: fontSize [RW], highlightColor [RW]
|
|
468
505
|
状态: isTodo [RW], todoStatus [RW], isCode [RW], isQuote [RW],
|
|
469
506
|
isListItem [RW], isCardItem [RW], isSlot [RW], isProperty [RW]
|
|
@@ -534,11 +571,18 @@ Portal:portalType [R], portalDirectlyIncludedRem [Portal-W]
|
|
|
534
571
|
{ "i": "a", "onlyAudio": true, "url": "..." } // 音频
|
|
535
572
|
```
|
|
536
573
|
|
|
537
|
-
> 在 RemObject 格式化 JSON 中,数组内对象展开为多行。构造 edit-
|
|
574
|
+
> 在 RemObject 格式化 JSON 中,数组内对象展开为多行。构造 edit-tree 的 oldStr/newStr 或 edit-rem 的 changes 中 RichText 值时,需注意多行格式。
|
|
575
|
+
|
|
576
|
+
**⚠️ highlightColor vs h — 两种完全不同的高亮**:
|
|
577
|
+
|
|
578
|
+
| 属性 | 位置 | 值类型 | 效果 |
|
|
579
|
+
|:-----|:-----|:-------|:-----|
|
|
580
|
+
| `highlightColor` | RemObject 顶层字段 | 字符串 `"Yellow"`/`"Red"` 等或 `null` | 整行背景色(左侧彩色竖条) |
|
|
581
|
+
| `h` | RichText 元素内部 | 数字 0-9 | 文字片段荧光底色 |
|
|
538
582
|
|
|
539
|
-
|
|
583
|
+
`h` 颜色值:0=无, 1=Red, 2=Orange, 3=Yellow, 4=Green, 5=Purple, 6=Blue, 7=Gray, 8=Brown, 9=Pink。
|
|
540
584
|
|
|
541
|
-
**序列化确定性**:RichText 对象内部按 key 字母序排列(`sortRichTextKeys()`)。`_id` 的 `_`(U+005F
|
|
585
|
+
**序列化确定性**:RichText 对象内部按 key 字母序排列(`sortRichTextKeys()`)。`_id` 的 `_`(U+005F)排在所有小写字母之前。这对乐观并发检测和 edit-tree 的 str_replace 至关重要。
|
|
542
586
|
|
|
543
587
|
---
|
|
544
588
|
|
|
@@ -646,7 +690,7 @@ read-tree / read-globe / read-context 的输出核心是 Markdown 大纲文本
|
|
|
646
690
|
|
|
647
691
|
| 前缀 | 用途 | 写入命令 |
|
|
648
692
|
|:-----|:-----|:---------|
|
|
649
|
-
| `rem:{remId}` | RemObject
|
|
693
|
+
| `rem:{remId}` | RemObject 对象 | read-rem |
|
|
650
694
|
| `tree:{remId}` | Markdown 大纲 | read-tree |
|
|
651
695
|
| `tree-depth:{remId}` 等 | read-tree 参数 | read-tree |
|
|
652
696
|
|
|
@@ -654,9 +698,9 @@ read-tree / read-globe / read-context 的输出核心是 Markdown 大纲文本
|
|
|
654
698
|
- disconnect 关闭 daemon 时缓存自动消失
|
|
655
699
|
- **没有 TTL**——三道防线的并发检测已能捕获所有陈旧数据
|
|
656
700
|
|
|
657
|
-
### 9.2
|
|
701
|
+
### 9.2 安全防线
|
|
658
702
|
|
|
659
|
-
`edit-rem` 和 `edit-tree`
|
|
703
|
+
`edit-rem` 和 `edit-tree` 编辑数据时,实施多道防线防止数据损坏:
|
|
660
704
|
|
|
661
705
|
#### 防线 1:缓存存在性检查
|
|
662
706
|
|
|
@@ -674,7 +718,16 @@ edit 时重新从 SDK 读取最新数据 → 与缓存严格比较
|
|
|
674
718
|
|
|
675
719
|
如果 Rem 在 read 之后被外部修改(用户在 RemNote UI 中编辑、其他 Agent 修改等),数据不一致时拒绝编辑,**且不更新缓存**——迫使 Agent 重新 read。
|
|
676
720
|
|
|
677
|
-
#### 防线 3
|
|
721
|
+
#### edit-rem 防线 3:字段白名单校验
|
|
722
|
+
|
|
723
|
+
```
|
|
724
|
+
changes 中的字段必须在 RW 白名单内,枚举值必须合法
|
|
725
|
+
```
|
|
726
|
+
|
|
727
|
+
- 只读字段(R / R-F)写入时**警告跳过**,不阻断其他字段
|
|
728
|
+
- 枚举值非法时**报错拒绝**(如 `type: "invalid"`)
|
|
729
|
+
|
|
730
|
+
#### edit-tree 防线 3:str_replace 精确匹配
|
|
678
731
|
|
|
679
732
|
```
|
|
680
733
|
oldStr 必须在目标文本中恰好匹配 1 次
|
|
@@ -689,7 +742,8 @@ oldStr 必须在目标文本中恰好匹配 1 次
|
|
|
689
742
|
| 场景 | 缓存行为 |
|
|
690
743
|
|:-----|:---------|
|
|
691
744
|
| 写入全部成功 | 从 SDK 重新读取最新状态 → **更新缓存** |
|
|
692
|
-
|
|
|
745
|
+
| 防线拒绝(缓存缺失 / 并发冲突) | **不更新缓存**(迫使 Agent 重新 read) |
|
|
746
|
+
| 枚举值非法 | **报错拒绝**,不更新缓存 |
|
|
693
747
|
| 部分写入失败 | **不更新缓存** |
|
|
694
748
|
|
|
695
749
|
---
|
|
@@ -751,13 +805,10 @@ RemNote 的格式设置通过 Powerup 机制实现,会向 Rem 注入隐藏的
|
|
|
751
805
|
|
|
752
806
|
## 12. 配置系统
|
|
753
807
|
|
|
754
|
-
|
|
808
|
+
配置文件位于全局目录:`~/.remnote-bridge/config.json`(所有实例共享)。
|
|
755
809
|
|
|
756
810
|
```json
|
|
757
811
|
{
|
|
758
|
-
"wsPort": 3002,
|
|
759
|
-
"devServerPort": 8080,
|
|
760
|
-
"configPort": 3003,
|
|
761
812
|
"daemonTimeoutMinutes": 30,
|
|
762
813
|
"defaults": {
|
|
763
814
|
"maxNodes": 200,
|
|
@@ -776,7 +827,21 @@ RemNote 的格式设置通过 Powerup 机制实现,会向 Rem 注入隐藏的
|
|
|
776
827
|
```
|
|
777
828
|
|
|
778
829
|
- 文件不存在时使用全部默认值
|
|
779
|
-
-
|
|
830
|
+
- 端口由槽位自动分配(`~/.remnote-bridge/slots.json`),通常无需手动配置
|
|
831
|
+
|
|
832
|
+
### 多实例文件布局
|
|
833
|
+
|
|
834
|
+
```
|
|
835
|
+
~/.remnote-bridge/
|
|
836
|
+
├── config.json — 全局配置(所有实例共享)
|
|
837
|
+
├── slots.json — 槽位端口定义(自动生成)
|
|
838
|
+
├── registry.json — 实例→槽位映射(运行时维护)
|
|
839
|
+
└── instances/
|
|
840
|
+
├── 0.pid / 0.log — 槽位 0 的 PID 和日志
|
|
841
|
+
├── 1.pid / 1.log — 槽位 1
|
|
842
|
+
├── 2.pid / 2.log — 槽位 2
|
|
843
|
+
└── 3.pid / 3.log — 槽位 3
|
|
844
|
+
```
|
|
780
845
|
|
|
781
846
|
---
|
|
782
847
|
|
|
@@ -799,13 +864,12 @@ Agent 遇到错误时的诊断和恢复指南:
|
|
|
799
864
|
| has not been read yet | 未先执行 read-rem / read-tree | 执行对应 read 命令后重试 |
|
|
800
865
|
| has been modified since last read | Rem 在 read 和 edit 之间被外部修改 | 重新执行 read 获取最新状态后重试 |
|
|
801
866
|
|
|
802
|
-
### str_replace 错误
|
|
867
|
+
### edit-tree str_replace 错误
|
|
803
868
|
|
|
804
869
|
| 错误 | 原因 | 恢复 |
|
|
805
870
|
|:-----|:-----|:-----|
|
|
806
|
-
| old_str not found | oldStr 在目标文本中不存在 | 检查 oldStr
|
|
871
|
+
| old_str not found | oldStr 在目标文本中不存在 | 检查 oldStr 是否精确匹配(含空格、换行、缩进) |
|
|
807
872
|
| old_str matches N locations | oldStr 匹配到多个位置 | 扩大 oldStr 范围,包含更多上下文以唯一定位 |
|
|
808
|
-
| invalid JSON | 替换后的文本不是合法 JSON | 检查 newStr 的引号、逗号、括号完整性 |
|
|
809
873
|
|
|
810
874
|
### edit-tree 专用错误
|
|
811
875
|
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
`read-rem` 通过 Rem ID 读取一个 Rem 的所有可获取属性,返回标准化的 RemObject。读取结果会被缓存在 daemon 内存中,供后续 `edit-rem` 使用。
|
|
10
10
|
|
|
11
11
|
核心能力:
|
|
12
|
-
- 返回 51 个字段的完整 Rem 数据(默认
|
|
12
|
+
- 返回 51 个字段的完整 Rem 数据(默认 33 个,Portal 简化 8 个,`--full` 时 51 个)
|
|
13
13
|
- 支持 `--fields` 指定字段子集
|
|
14
14
|
- 支持 Powerup 噪音过滤(默认过滤)
|
|
15
15
|
- 自动缓存,为 `edit-rem` 建立编辑基础
|
|
@@ -76,12 +76,11 @@ remnote-bridge read-rem --json '{"remId":"kLrIOHJLyMd8Y2lyA"}'
|
|
|
76
76
|
"type": "concept",
|
|
77
77
|
"isDocument": false,
|
|
78
78
|
"parent": "parentRemId",
|
|
79
|
-
"children": ["childId1", "childId2"],
|
|
80
79
|
"fontSize": null,
|
|
81
80
|
"highlightColor": null,
|
|
82
81
|
"isTodo": false,
|
|
83
82
|
"todoStatus": null,
|
|
84
|
-
"...": "(共
|
|
83
|
+
"...": "(共 33 个字段,--full 时 51 个)"
|
|
85
84
|
},
|
|
86
85
|
"timestamp": "2026-03-06T10:00:00.000Z"
|
|
87
86
|
}
|
|
@@ -159,8 +158,8 @@ remnote-bridge read-rem --json '{"remId":"kLrIOHJLyMd8Y2lyA"}'
|
|
|
159
158
|
├─ 字段过滤:
|
|
160
159
|
│ ├─ --full → 返回全部 51 字段
|
|
161
160
|
│ ├─ --fields → 返回指定字段 + id
|
|
162
|
-
│ ├─ type=portal → Portal 简化模式(返回
|
|
163
|
-
│ └─ 默认 → 排除 R-F 字段(返回
|
|
161
|
+
│ ├─ type=portal → Portal 简化模式(返回 8 个关键字段)
|
|
162
|
+
│ └─ 默认 → 排除 R-F 字段(返回 33 字段)
|
|
164
163
|
└─ 附加 _cacheOverridden 元数据(若之前有缓存)
|
|
165
164
|
4. CLI 格式化输出(人类模式 pretty-print / JSON 模式单行)
|
|
166
165
|
```
|
|
@@ -172,8 +171,8 @@ remnote-bridge read-rem --json '{"remId":"kLrIOHJLyMd8Y2lyA"}'
|
|
|
172
171
|
RemObject 共 51 个字段,按读写权限分为三类:
|
|
173
172
|
|
|
174
173
|
- **RW**(20 个):可读可写,SDK 有对应的 setter
|
|
175
|
-
- **R**(
|
|
176
|
-
- **R-F**(
|
|
174
|
+
- **R**(13 个):只读,默认输出
|
|
175
|
+
- **R-F**(18 个):只读,仅 `--full` 模式输出(低频 / 可由其他字段推导)
|
|
177
176
|
|
|
178
177
|
### 核心标识
|
|
179
178
|
|
|
@@ -200,7 +199,7 @@ RemObject 共 51 个字段,按读写权限分为三类:
|
|
|
200
199
|
| 字段 | 类型 | 权限 | 说明 |
|
|
201
200
|
|------|------|:----:|------|
|
|
202
201
|
| `parent` | `string \| null` | RW | 父 Rem ID。null=顶级。UI:Rem 从原位置消失,出现在新父级下 |
|
|
203
|
-
| `children` | `string[]` | R | 子 Rem ID 有序数组 |
|
|
202
|
+
| `children` | `string[]` | R-F | 子 Rem ID 有序数组 |
|
|
204
203
|
|
|
205
204
|
### 格式 / 显示
|
|
206
205
|
|
|
@@ -377,14 +376,15 @@ text | number | date | checkbox | single_select | multi_select | url | image | t
|
|
|
377
376
|
|
|
378
377
|
| 模式 | 输出字段数 | 说明 |
|
|
379
378
|
|------|:----------:|------|
|
|
380
|
-
| 默认 |
|
|
381
|
-
| Portal 简化 |
|
|
379
|
+
| 默认 | 33 | RW + R 字段,覆盖常用场景 |
|
|
380
|
+
| Portal 简化 | 8 | type=portal 时自动使用(id、type、portalType、portalDirectlyIncludedRem、parent、positionAmongstSiblings、createdAt、updatedAt)。`--full` / `--fields` 可覆盖 |
|
|
382
381
|
| `--full` | 51 | 全部字段(含 R-F 低频字段) |
|
|
383
382
|
| `--fields` | 自选 + id | 仅返回指定字段(始终包含 id) |
|
|
384
383
|
|
|
385
384
|
### R-F 字段列表(默认不输出,`--full` 时输出)
|
|
386
385
|
|
|
387
386
|
```
|
|
387
|
+
children,
|
|
388
388
|
isPowerup, isPowerupEnum, isPowerupProperty, isPowerupPropertyListItem, isPowerupSlot,
|
|
389
389
|
deepRemsBeingReferenced,
|
|
390
390
|
ancestorTagRem, descendantTagRem,
|
|
@@ -422,7 +422,7 @@ localUpdatedAt, lastPracticed
|
|
|
422
422
|
| `tags` | `rem.addTag()` / `rem.removeTag()` | **Diff 机制**:对比当前 vs 目标,增删差异项。必须列出完整目标数组,缺少的会被删除 |
|
|
423
423
|
| `sources` | `rem.addSource()` / `rem.removeSource()` | **Diff 机制**:同 tags |
|
|
424
424
|
| `positionAmongstSiblings` | `rem.setParent(parent, position)` | 与 `parent` 联动(见下方说明) |
|
|
425
|
-
| `portalDirectlyIncludedRem` | `rem.addToPortal()` / `rem.removeFromPortal()` |
|
|
425
|
+
| `portalDirectlyIncludedRem` | `rem.addToPortal()` / `rem.removeFromPortal()` | **Portal-W Diff 机制**:仅 type=portal 时可修改。对比当前 vs 目标数组,逐项增删 |
|
|
426
426
|
|
|
427
427
|
### parent + positionAmongstSiblings 联动
|
|
428
428
|
|
|
@@ -434,7 +434,7 @@ localUpdatedAt, lastPracticed
|
|
|
434
434
|
| 只有 `parent` 变更 | `setParent(newParent)` 不带 position(保持末尾) |
|
|
435
435
|
| 只有 `positionAmongstSiblings` 变更 | 获取当前 parent → `setParent(currentParent, newPosition)` |
|
|
436
436
|
|
|
437
|
-
**应在同一次
|
|
437
|
+
**应在同一次 edit-rem 的 changes 中同时传入这两个字段。**
|
|
438
438
|
|
|
439
439
|
---
|
|
440
440
|
|
|
@@ -561,7 +561,7 @@ RemObject 中的 `text` 和 `backText` 字段使用 RichText 格式——一个
|
|
|
561
561
|
|
|
562
562
|
### 序列化确定性
|
|
563
563
|
|
|
564
|
-
RichText 对象元素内部按 **key 字母序排列**(Plugin 端 `sortRichTextKeys()` 处理),确保同一内容的序列化 JSON
|
|
564
|
+
RichText 对象元素内部按 **key 字母序排列**(Plugin 端 `sortRichTextKeys()` 处理),确保同一内容的序列化 JSON 始终一致。这对乐观并发检测至关重要。
|
|
565
565
|
|
|
566
566
|
- `_`(下划线)在 Unicode 中排在所有小写字母之前(`_` = U+005F,`a` = U+0061),所以 `_id` 总是排在第一位
|
|
567
567
|
- 排序由 `Object.keys().sort()` 决定,即 JavaScript 默认的 Unicode 字典序
|
|
@@ -589,11 +589,11 @@ RichText 对象元素内部按 **key 字母序排列**(Plugin 端 `sortRichTex
|
|
|
589
589
|
|------|------|
|
|
590
590
|
| 读取成功 | 完整 JSON 写入缓存 `cache.set('rem:' + remId, fullJson)` |
|
|
591
591
|
| 已有缓存 | 覆盖旧缓存,返回 `cacheOverridden` 元数据 |
|
|
592
|
-
| 缓存用途 | 供 `edit-rem`
|
|
592
|
+
| 缓存用途 | 供 `edit-rem` 的防线检查使用(存在性检查 + 乐观并发检测) |
|
|
593
593
|
| 缓存存储 | daemon 内存中的 LRU 缓存(最大 200 条目) |
|
|
594
594
|
| 缓存清空 | daemon 关闭时自动消失 |
|
|
595
595
|
|
|
596
|
-
**重要**:缓存存储的是 **完整 RemObject
|
|
596
|
+
**重要**:缓存存储的是 **完整 RemObject 对象**(含 R-F 字段),不受 `--fields` / `--full` 选项影响。字段过滤仅作用于返回给 CLI 的输出。
|
|
597
597
|
|
|
598
598
|
---
|
|
599
599
|
|