remnote-bridge 0.1.13 → 0.1.15
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 +147 -28
- package/README.zh-CN.md +374 -0
- package/dist/cli/commands/health.js +231 -112
- package/dist/cli/commands/read-rem-in-tree.js +84 -0
- package/dist/cli/config.js +2 -0
- package/dist/cli/daemon/registry.js +8 -0
- package/dist/cli/handlers/edit-handler.js +14 -0
- package/dist/cli/handlers/patch-engine.js +347 -0
- package/dist/cli/handlers/read-handler.js +2 -53
- package/dist/cli/handlers/rem-field-filter.js +102 -0
- package/dist/cli/handlers/tree-edit-handler.js +67 -7
- package/dist/cli/handlers/tree-read-handler.js +4 -1
- package/dist/cli/handlers/tree-rem-read-handler.js +73 -0
- package/dist/cli/main.js +53 -2
- package/dist/cli/server/ws-server.js +9 -1
- package/dist/mcp/daemon-client.js +22 -2
- package/dist/mcp/instructions.js +99 -58
- package/dist/mcp/tools/edit-tools.js +7 -2
- package/dist/mcp/tools/infra-tools.js +20 -11
- package/dist/mcp/tools/read-tools.js +88 -2
- package/package.json +1 -1
- package/remnote-plugin/dist/index-sandbox.js +24 -24
- package/remnote-plugin/dist/index.js +24 -24
- 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/message-router.ts +3 -0
- package/remnote-plugin/src/services/read-rem-in-tree.ts +43 -0
- package/remnote-plugin/src/services/read-rem.ts +31 -16
- package/remnote-plugin/src/services/read-tree.ts +5 -0
- package/remnote-plugin/src/settings.ts +1 -1
- package/skills/remnote-bridge/SKILL.md +50 -8
- package/skills/remnote-bridge/instructions/connect.md +31 -8
- package/skills/remnote-bridge/instructions/disconnect.md +5 -0
- package/skills/remnote-bridge/instructions/edit-tree.md +117 -51
- package/skills/remnote-bridge/instructions/health.md +81 -53
- package/skills/remnote-bridge/instructions/overall.md +39 -8
- package/skills/remnote-bridge/instructions/read-rem-in-tree.md +100 -0
- package/skills/remnote-bridge/instructions/read-rem.md +30 -11
- package/skills/remnote-bridge-test/SKILL.md +847 -0
- package/skills/remnote-bridge-test/references/regression-suite.md +960 -0
- package/skills/remnote-bridge-test/references/verification-guide.md +161 -0
|
@@ -62,14 +62,16 @@ export function registerReadTools(server) {
|
|
|
62
62
|
'\\n- full(可选,默认 false):返回全部 51 个字段(含低频 R-F 字段,如 children、isPowerup 系列、deepRemsBeingReferenced 等)' +
|
|
63
63
|
'\\n- includePowerup(可选,默认 false):包含 Powerup 系统数据(默认过滤噪音)' +
|
|
64
64
|
'\\n\\n输出格式:Data JSON,核心为 RemObject 对象。' +
|
|
65
|
-
'\\n-
|
|
66
|
-
'\\n-
|
|
65
|
+
'\\n- 默认模式(Token Slimming):省略处于默认值的字段,典型普通 Rem 仅输出 5-6 个差异字段。未显示的字段即为默认值(如 type 未显示 = "default",isTodo 未显示 = false,tags 未显示 = [])。始终输出的字段:id, text, parent, createdAt, updatedAt' +
|
|
66
|
+
'\\n- full=true 时返回全部 51 个字段,Portal 类型自动简化为 8 个关键字段' +
|
|
67
|
+
'\\n- 关键字段:id, text, backText(null), type(concept/descriptor/default/portal), parent, isDocument(false), tags([]), fontSize(H1/H2/H3/null), highlightColor(Red/.../Pink/null), practiceDirection(forward/backward/both/none), isTodo(false), todoStatus(Finished/Unfinished/null)——括号内为默认值' +
|
|
67
68
|
'\\n- children 字段属于 R-F 层级,默认不输出,需 full=true 或 fields 指定' +
|
|
68
69
|
'\\n- text/backText 是 RichText JSON 数组,元素为纯字符串或带 i 字段的对象(i:"m" 格式化文本, i:"q" Rem 引用, i:"x" LaTeX, i:"i" 图片, i:"a" 音视频)' +
|
|
69
70
|
'\\n- 可能附加 cacheOverridden(覆盖旧缓存时)和 powerupFiltered(过滤统计)元数据' +
|
|
70
71
|
'\\n\\n关键约束:' +
|
|
71
72
|
'\\n- 结果自动写入缓存供 edit_rem 使用。缓存存储完整 RemObject,不受 fields/full 选项影响' +
|
|
72
73
|
'\\n- 默认过滤 Powerup 噪音(系统 Tag 和隐藏子 Rem),includePowerup=true 可恢复' +
|
|
74
|
+
'\\n\\n⚠️ 如果你需要读取多个 Rem 的属性(≥3 个),且它们在同一棵子树下,请改用 read_rem_in_tree(一次调用批量读取,省去逐个 read_rem 的开销)。' +
|
|
73
75
|
'\\n\\n典型工作流:search 定位 remId → read_rem 获取详情并建立缓存 → edit_rem 编辑属性。' +
|
|
74
76
|
'\\n关联工具:search(定位 remId)、edit_rem(编辑属性,需先 read_rem)、read_tree(查看子树大纲)',
|
|
75
77
|
parameters: z.object({
|
|
@@ -129,6 +131,7 @@ export function registerReadTools(server) {
|
|
|
129
131
|
'\\n- 结果自动写入缓存供 edit_tree 使用。edit_tree 的 oldStr 必须精确匹配此大纲中的文本' +
|
|
130
132
|
'\\n- 默认过滤 Powerup 噪音,includePowerup=true 可恢复' +
|
|
131
133
|
'\\n- Portal 感知:Portal 类型 Rem 标注 type:portal 和 refs:id1,id2(引用的 Rem ID)' +
|
|
134
|
+
'\\n\\n⚠️ 如果你需要读取子树后对其中多个节点执行 edit_rem,请改用 read_rem_in_tree(一次调用同时建立 tree 和 rem 双重缓存,省去逐个 read_rem 的开销)。' +
|
|
132
135
|
'\\n\\n典型工作流:search 定位 remId → read_tree 展开子树并建立缓存 → edit_tree 结构编辑。' +
|
|
133
136
|
'\\n关联工具:search(定位 remId)、edit_tree(结构编辑,需先 read_tree)、read_rem(单 Rem JSON 详情)、read_globe(全局鸟瞰)',
|
|
134
137
|
parameters: z.object({
|
|
@@ -182,6 +185,89 @@ export function registerReadTools(server) {
|
|
|
182
185
|
},
|
|
183
186
|
});
|
|
184
187
|
// -------------------------------------------------------------------------
|
|
188
|
+
// read_rem_in_tree
|
|
189
|
+
// -------------------------------------------------------------------------
|
|
190
|
+
server.addTool({
|
|
191
|
+
name: 'read_rem_in_tree',
|
|
192
|
+
description: '⭐ 批量编辑场景的首选工具。当你需要读取子树并修改其中多个节点的属性/富文本时,优先使用此工具而非 read_tree + N×read_rem。' +
|
|
193
|
+
'\\nread_tree + read_rem 的完美结合体:一次调用同时获取子树 Markdown 大纲和每个节点的完整 RemObject JSON。' +
|
|
194
|
+
'\\n\\n适用场景:需要同时查看子树结构和节点详细属性时(如批量编辑前的全量读取);一次调用同时建立 tree 缓存(供 edit_tree)和 rem 缓存(供 edit_rem)。' +
|
|
195
|
+
'\\n不适用场景:只需大纲不需属性(用 read_tree,更轻量);只需单个 Rem 属性(用 read_rem)。' +
|
|
196
|
+
'\\n\\n前置条件:daemon 已连接;需要有效的 remId。' +
|
|
197
|
+
'\\n\\n参数说明:' +
|
|
198
|
+
'\\n- remId(必需):子树根节点的 Rem ID' +
|
|
199
|
+
'\\n- depth(可选,默认 3,-1 无限):递归展开深度' +
|
|
200
|
+
'\\n- maxNodes(可选,默认 50):全局节点总预算。注意默认值比 read_tree 的 200 低,因为每节点需 40+ SDK 调用' +
|
|
201
|
+
'\\n- maxSiblings(可选,默认 20):单个父节点下最大可见子节点数' +
|
|
202
|
+
'\\n- ancestorLevels(可选,默认 0,上限 10):向上追溯祖先层数' +
|
|
203
|
+
'\\n- fields(可选):RemObject 字段过滤,只返回指定字段子集' +
|
|
204
|
+
'\\n- full(可选,默认 false):返回全部 51 个 RemObject 字段' +
|
|
205
|
+
'\\n- includePowerup(可选,默认 false):包含 Powerup 系统数据' +
|
|
206
|
+
'\\n\\n输出格式:Data JSON,包含:' +
|
|
207
|
+
'\\n- outline:Markdown 大纲文本(与 read_tree 输出格式完全一致)' +
|
|
208
|
+
'\\n- remObjects:扁平 map { remId → RemObject },每个 RemObject 与 read_rem 输出一致(受 fields/full 参数影响)' +
|
|
209
|
+
'\\n- rootId, depth, nodeCount 等元数据' +
|
|
210
|
+
'\\n\\n关键约束:' +
|
|
211
|
+
'\\n- 同时建立双重缓存:tree:{remId} 供 edit_tree 使用,rem:{nodeRemId} 供 edit_rem 使用' +
|
|
212
|
+
'\\n- 缓存条目约 N+4(1 tree + 3 参数 + N rem),注意 LRU 上限 200' +
|
|
213
|
+
'\\n- RemObject 默认启用 Token Slimming(与 read_rem 一致)' +
|
|
214
|
+
'\\n\\n典型工作流:read_rem_in_tree 一次获取全部信息 → edit_tree 结构编辑 + edit_rem 属性编辑。' +
|
|
215
|
+
'\\n关联工具:read_tree(只需大纲)、read_rem(只需单 Rem)、edit_tree(结构编辑)、edit_rem(属性编辑)',
|
|
216
|
+
parameters: z.object({
|
|
217
|
+
remId: z.string().describe('根 Rem 的 ID'),
|
|
218
|
+
depth: z
|
|
219
|
+
.number()
|
|
220
|
+
.optional()
|
|
221
|
+
.describe('展开深度(默认 3)'),
|
|
222
|
+
maxNodes: z
|
|
223
|
+
.number()
|
|
224
|
+
.optional()
|
|
225
|
+
.describe('节点总数上限(默认 50)'),
|
|
226
|
+
maxSiblings: z
|
|
227
|
+
.number()
|
|
228
|
+
.optional()
|
|
229
|
+
.describe('同级节点显示上限'),
|
|
230
|
+
ancestorLevels: z
|
|
231
|
+
.number()
|
|
232
|
+
.optional()
|
|
233
|
+
.describe('向上展示的祖先层级数'),
|
|
234
|
+
fields: z
|
|
235
|
+
.array(z.string())
|
|
236
|
+
.optional()
|
|
237
|
+
.describe('RemObject 字段过滤'),
|
|
238
|
+
full: z
|
|
239
|
+
.boolean()
|
|
240
|
+
.optional()
|
|
241
|
+
.describe('返回全部 RemObject 字段'),
|
|
242
|
+
includePowerup: z
|
|
243
|
+
.boolean()
|
|
244
|
+
.optional()
|
|
245
|
+
.describe('是否包含 Powerup 元信息'),
|
|
246
|
+
}),
|
|
247
|
+
execute: async (args) => {
|
|
248
|
+
const payload = { remId: args.remId };
|
|
249
|
+
if (args.depth !== undefined)
|
|
250
|
+
payload.depth = args.depth;
|
|
251
|
+
if (args.maxNodes !== undefined)
|
|
252
|
+
payload.maxNodes = args.maxNodes;
|
|
253
|
+
if (args.maxSiblings !== undefined)
|
|
254
|
+
payload.maxSiblings = args.maxSiblings;
|
|
255
|
+
if (args.ancestorLevels !== undefined)
|
|
256
|
+
payload.ancestorLevels = args.ancestorLevels;
|
|
257
|
+
if (args.fields !== undefined)
|
|
258
|
+
payload.fields = args.fields;
|
|
259
|
+
if (args.full !== undefined)
|
|
260
|
+
payload.full = args.full;
|
|
261
|
+
if (args.includePowerup !== undefined)
|
|
262
|
+
payload.includePowerup = args.includePowerup;
|
|
263
|
+
const response = await callCli('read-rem-in-tree', payload, { timeoutMs: 60_000 });
|
|
264
|
+
if (!response.data) {
|
|
265
|
+
return `read_rem_in_tree 返回了空的 data,remId: ${args.remId}。请检查该 Rem 是否存在。`;
|
|
266
|
+
}
|
|
267
|
+
return formatDataJson(response);
|
|
268
|
+
},
|
|
269
|
+
});
|
|
270
|
+
// -------------------------------------------------------------------------
|
|
185
271
|
// read_globe
|
|
186
272
|
// -------------------------------------------------------------------------
|
|
187
273
|
server.addTool({
|