remnote-bridge 0.1.12 → 0.1.14

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.
Files changed (50) hide show
  1. package/README.md +141 -28
  2. package/README.zh-CN.md +368 -0
  3. package/dist/cli/commands/edit-rem.js +5 -5
  4. package/dist/cli/commands/health.js +231 -112
  5. package/dist/cli/commands/read-rem-in-tree.js +84 -0
  6. package/dist/cli/commands/read-rem.js +3 -1
  7. package/dist/cli/config.js +2 -0
  8. package/dist/cli/daemon/registry.js +8 -0
  9. package/dist/cli/handlers/edit-handler.js +49 -140
  10. package/dist/cli/handlers/patch-engine.js +347 -0
  11. package/dist/cli/handlers/read-handler.js +5 -57
  12. package/dist/cli/handlers/rem-cache.js +10 -5
  13. package/dist/cli/handlers/rem-field-filter.js +102 -0
  14. package/dist/cli/handlers/tree-edit-handler.js +67 -7
  15. package/dist/cli/handlers/tree-read-handler.js +4 -1
  16. package/dist/cli/handlers/tree-rem-read-handler.js +73 -0
  17. package/dist/cli/main.js +71 -12
  18. package/dist/cli/server/ws-server.js +9 -1
  19. package/dist/mcp/daemon-client.js +22 -2
  20. package/dist/mcp/format.js +43 -0
  21. package/dist/mcp/index.js +0 -55
  22. package/dist/mcp/instructions.js +447 -284
  23. package/dist/mcp/resources/edit-rem-guide.js +37 -157
  24. package/dist/mcp/resources/edit-tree-guide.js +1 -1
  25. package/dist/mcp/resources/error-reference.js +9 -13
  26. package/dist/mcp/resources/rem-object-fields.js +3 -3
  27. package/dist/mcp/tools/edit-tools.js +76 -10
  28. package/dist/mcp/tools/infra-tools.js +30 -33
  29. package/dist/mcp/tools/read-tools.js +221 -26
  30. package/package.json +1 -1
  31. package/remnote-plugin/dist/index-sandbox.js +24 -24
  32. package/remnote-plugin/dist/index.js +24 -24
  33. package/remnote-plugin/src/bridge/message-router.ts +3 -0
  34. package/remnote-plugin/src/services/read-rem-in-tree.ts +43 -0
  35. package/remnote-plugin/src/services/read-rem.ts +15 -0
  36. package/remnote-plugin/src/services/read-tree.ts +5 -0
  37. package/skills/remnote-bridge/SKILL.md +71 -38
  38. package/skills/remnote-bridge/instructions/connect.md +12 -1
  39. package/skills/remnote-bridge/instructions/disconnect.md +5 -0
  40. package/skills/remnote-bridge/instructions/edit-rem.md +105 -347
  41. package/skills/remnote-bridge/instructions/edit-tree.md +71 -2
  42. package/skills/remnote-bridge/instructions/health.md +81 -53
  43. package/skills/remnote-bridge/instructions/overall.md +55 -21
  44. package/skills/remnote-bridge/instructions/read-rem-in-tree.md +100 -0
  45. package/skills/remnote-bridge/instructions/read-rem.md +35 -16
  46. package/skills/remnote-bridge/instructions/search.md +4 -4
  47. package/skills/remnote-bridge/instructions/setup.md +5 -6
  48. package/skills/remnote-bridge-test/SKILL.md +847 -0
  49. package/skills/remnote-bridge-test/references/regression-suite.md +960 -0
  50. package/skills/remnote-bridge-test/references/verification-guide.md +161 -0
@@ -9,7 +9,8 @@
9
9
  `read-rem` 通过 Rem ID 读取一个 Rem 的所有可获取属性,返回标准化的 RemObject。读取结果会被缓存在 daemon 内存中,供后续 `edit-rem` 使用。
10
10
 
11
11
  核心能力:
12
- - 返回 51 个字段的完整 Rem 数据(默认 33 个,Portal 简化 8 个,`--full` 时 51 个)
12
+ - **Token Slimming**(默认模式):省略处于默认值的字段,典型普通 Rem 仅输出 5-6 个差异字段,大幅减少 AI token 消耗。未显示的字段即为默认值
13
+ - Portal 简化 8 个字段,`--full` 时全部 51 个字段
13
14
  - 支持 `--fields` 指定字段子集
14
15
  - 支持 Powerup 噪音过滤(默认过滤)
15
16
  - 自动缓存,为 `edit-rem` 建立编辑基础
@@ -72,20 +73,17 @@ remnote-bridge read-rem --json '{"remId":"kLrIOHJLyMd8Y2lyA"}'
72
73
  "data": {
73
74
  "id": "kLrIOHJLyMd8Y2lyA",
74
75
  "text": [{ "i": "m", "text": "示例文本", "b": true }],
75
- "backText": null,
76
76
  "type": "concept",
77
- "isDocument": false,
78
77
  "parent": "parentRemId",
79
- "fontSize": null,
80
- "highlightColor": null,
81
- "isTodo": false,
82
- "todoStatus": null,
83
- "...": "(共 33 个字段,--full 时 51 个)"
78
+ "createdAt": 1709712000000,
79
+ "updatedAt": 1709712000000
84
80
  },
85
81
  "timestamp": "2026-03-06T10:00:00.000Z"
86
82
  }
87
83
  ```
88
84
 
85
+ > **Token Slimming**:默认模式省略了 backText(null)、isDocument(false)、fontSize(null) 等处于默认值的字段。未出现的字段即为默认值。`--full` 可输出全部 51 个字段。
86
+
89
87
  ### 成功(含缓存覆盖提示)
90
88
 
91
89
  当该 Rem 之前已有缓存时,输出中附加 `cacheOverridden` 字段:
@@ -159,7 +157,7 @@ remnote-bridge read-rem --json '{"remId":"kLrIOHJLyMd8Y2lyA"}'
159
157
  │ ├─ --full → 返回全部 51 字段
160
158
  │ ├─ --fields → 返回指定字段 + id
161
159
  │ ├─ type=portal → Portal 简化模式(返回 8 个关键字段)
162
- │ └─ 默认 → 排除 R-F 字段(返回 33 字段)
160
+ │ └─ 默认 → 排除 R-F 字段 + Token Slimming(省略匹配默认值的字段)
163
161
  └─ 附加 _cacheOverridden 元数据(若之前有缓存)
164
162
  4. CLI 格式化输出(人类模式 pretty-print / JSON 模式单行)
165
163
  ```
@@ -376,11 +374,32 @@ text | number | date | checkbox | single_select | multi_select | url | image | t
376
374
 
377
375
  | 模式 | 输出字段数 | 说明 |
378
376
  |------|:----------:|------|
379
- | 默认 | 33 | RW + R 字段,覆盖常用场景 |
377
+ | 默认(Token Slimming) | 5-6(典型) | 省略匹配默认值的字段,仅输出有差异的字段。始终输出:id、text、parent、createdAt、updatedAt |
380
378
  | Portal 简化 | 8 | type=portal 时自动使用(id、type、portalType、portalDirectlyIncludedRem、parent、positionAmongstSiblings、createdAt、updatedAt)。`--full` / `--fields` 可覆盖 |
381
- | `--full` | 51 | 全部字段(含 R-F 低频字段) |
379
+ | `--full` | 51 | 全部字段(含 R-F 低频字段),不省略默认值 |
382
380
  | `--fields` | 自选 + id | 仅返回指定字段(始终包含 id) |
383
381
 
382
+ ### 默认值参考表
383
+
384
+ 默认模式下,以下字段在值匹配默认值时被省略。**未出现在输出中的字段即为默认值。**
385
+
386
+ | 字段 | 默认值 | 字段 | 默认值 |
387
+ |------|--------|------|--------|
388
+ | `backText` | `null` | `type` | `"default"` |
389
+ | `isDocument` | `false` | `fontSize` | `null` |
390
+ | `highlightColor` | `null` | `isTodo` | `false` |
391
+ | `todoStatus` | `null` | `isCode` | `false` |
392
+ | `isQuote` | `false` | `isListItem` | `false` |
393
+ | `isCardItem` | `false` | `isTable` | `false` |
394
+ | `isSlot` | `false` | `isProperty` | `false` |
395
+ | `portalType` | `null` | `portalDirectlyIncludedRem` | `[]` |
396
+ | `propertyType` | `null` | `enablePractice` | `false` |
397
+ | `practiceDirection` | `"forward"` | `tags` | `[]` |
398
+ | `sources` | `[]` | `aliases` | `[]` |
399
+ | `remsBeingReferenced` | `[]` | `remsReferencingThis` | `[]` |
400
+ | `taggedRem` | `[]` | `descendants` | `[]` |
401
+ | `siblingRem` | `[]` | `positionAmongstSiblings` | `null` |
402
+
384
403
  ### R-F 字段列表(默认不输出,`--full` 时输出)
385
404
 
386
405
  ```
@@ -422,7 +441,7 @@ localUpdatedAt, lastPracticed
422
441
  | `tags` | `rem.addTag()` / `rem.removeTag()` | **Diff 机制**:对比当前 vs 目标,增删差异项。必须列出完整目标数组,缺少的会被删除 |
423
442
  | `sources` | `rem.addSource()` / `rem.removeSource()` | **Diff 机制**:同 tags |
424
443
  | `positionAmongstSiblings` | `rem.setParent(parent, position)` | 与 `parent` 联动(见下方说明) |
425
- | `portalDirectlyIncludedRem` | `rem.addToPortal()` / `rem.removeFromPortal()` | string[] | **Portal-W Diff 机制**:仅 type=portal 时可修改。对比当前 vs 目标数组,逐项增删。调用方向:在被引用 Rem 上调用,参数是 Portal Rem |
444
+ | `portalDirectlyIncludedRem` | `rem.addToPortal()` / `rem.removeFromPortal()` | **Portal-W Diff 机制**:仅 type=portal 时可修改。对比当前 vs 目标数组,逐项增删 |
426
445
 
427
446
  ### parent + positionAmongstSiblings 联动
428
447
 
@@ -434,7 +453,7 @@ localUpdatedAt, lastPracticed
434
453
  | 只有 `parent` 变更 | `setParent(newParent)` 不带 position(保持末尾) |
435
454
  | 只有 `positionAmongstSiblings` 变更 | 获取当前 parent → `setParent(currentParent, newPosition)` |
436
455
 
437
- **应在同一次 str_replace 中同时修改这两个字段。**
456
+ **应在同一次 edit-rem 的 changes 中同时传入这两个字段。**
438
457
 
439
458
  ---
440
459
 
@@ -561,7 +580,7 @@ RemObject 中的 `text` 和 `backText` 字段使用 RichText 格式——一个
561
580
 
562
581
  ### 序列化确定性
563
582
 
564
- RichText 对象元素内部按 **key 字母序排列**(Plugin 端 `sortRichTextKeys()` 处理),确保同一内容的序列化 JSON 始终一致。这对 `edit-rem` 的 str_replace 和乐观并发检测至关重要。
583
+ RichText 对象元素内部按 **key 字母序排列**(Plugin 端 `sortRichTextKeys()` 处理),确保同一内容的序列化 JSON 始终一致。这对乐观并发检测至关重要。
565
584
 
566
585
  - `_`(下划线)在 Unicode 中排在所有小写字母之前(`_` = U+005F,`a` = U+0061),所以 `_id` 总是排在第一位
567
586
  - 排序由 `Object.keys().sort()` 决定,即 JavaScript 默认的 Unicode 字典序
@@ -589,11 +608,11 @@ RichText 对象元素内部按 **key 字母序排列**(Plugin 端 `sortRichTex
589
608
  |------|------|
590
609
  | 读取成功 | 完整 JSON 写入缓存 `cache.set('rem:' + remId, fullJson)` |
591
610
  | 已有缓存 | 覆盖旧缓存,返回 `cacheOverridden` 元数据 |
592
- | 缓存用途 | 供 `edit-rem` 的三道防线使用(存在性检查 + 乐观并发检测 + str_replace) |
611
+ | 缓存用途 | 供 `edit-rem` 的防线检查使用(存在性检查 + 乐观并发检测) |
593
612
  | 缓存存储 | daemon 内存中的 LRU 缓存(最大 200 条目) |
594
613
  | 缓存清空 | daemon 关闭时自动消失 |
595
614
 
596
- **重要**:缓存存储的是 **完整 RemObject**(含 R-F 字段),不受 `--fields` / `--full` 选项影响。字段过滤仅作用于返回给 CLI 的输出。
615
+ **重要**:缓存存储的是 **完整 RemObject 对象**(含 R-F 字段),不受 `--fields` / `--full` 选项影响。字段过滤仅作用于返回给 CLI 的输出。
597
616
 
598
617
  ---
599
618
 
@@ -56,7 +56,7 @@ remnote-bridge search <query> [--limit <N>]
56
56
  ### JSON 模式
57
57
 
58
58
  ```bash
59
- remnote-bridge search --json '{"query":"机器学习","numResults":10}'
59
+ remnote-bridge search --json '{"query":"机器学习","limit":10}'
60
60
  ```
61
61
 
62
62
  ---
@@ -66,7 +66,7 @@ remnote-bridge search --json '{"query":"机器学习","numResults":10}'
66
66
  | 字段 | 类型 | 必需 | 说明 |
67
67
  |------|------|:----:|------|
68
68
  | `query` | string | 是 | 搜索关键词(不能为空) |
69
- | `numResults` | number | 否 | 结果数量上限(默认 20) |
69
+ | `limit` | number | 否 | 结果数量上限(默认 20) |
70
70
 
71
71
  ---
72
72
 
@@ -159,7 +159,7 @@ remnote-bridge search --json '{"query":"机器学习","numResults":10}'
159
159
  ## 内部流程
160
160
 
161
161
  ```
162
- 1. CLI 解析参数(query, numResults
162
+ 1. CLI 解析参数(query, limit
163
163
  2. 检查配置:addons.remnote-rag.enabled
164
164
  ├─ 未启用 → 跳到步骤 4
165
165
  └─ 已启用 → 继续步骤 3
@@ -250,6 +250,6 @@ RemNote 的 Web 版搜索索引按单字符拆分非空格语言的文本。搜
250
250
  ## 注意事项
251
251
 
252
252
  - 搜索结果的 `text` 字段是 Markdown 格式的单行文本(多行换行符已替换为空格)
253
- - `totalFound` 等于 `results.length`,即实际返回的数量(受 `numResults` 限制)
253
+ - `totalFound` 等于 `results.length`,即实际返回的数量(受 `limit` 限制)
254
254
  - 搜索不会触发缓存写入——search 结果不进入 RemCache
255
255
  - 如需获取某个搜索结果的完整属性,需对其 `remId` 执行 `read-rem`
@@ -83,22 +83,21 @@ remnote-bridge --json setup
83
83
 
84
84
  ## AI Agent 使用流程
85
85
 
86
- setup 会弹出 Chrome 窗口,用户需要完成两件事:登录 RemNote + 配置 dev plugin
86
+ setup 会弹出 Chrome 窗口,用户只需**登录 RemNote**,然后彻底退出 Chrome
87
+
88
+ setup 只负责保存登录凭证——配置 dev plugin 是 connect 之后的事(见 `connect.md` 标准模式说明)。
87
89
 
88
90
  ### 交互步骤
89
91
 
90
92
  1. 调用 `setup`
91
93
  2. **立即告知用户**:
92
- > 已打开 Chrome 浏览器。请完成以下操作:
93
- > 1. 登录 RemNote
94
- > 2. 在 RemNote 中配置开发插件:点击左下角插件图标 → 开发你的插件 → 输入 connect 输出的 Plugin 服务地址(如 `http://localhost:29101`)
95
- > 3. 完成后彻底退出 Chrome(macOS 请按 Cmd+Q,仅关窗口不够)
94
+ > 已打开 Chrome 浏览器。请登录 RemNote,完成后彻底退出 Chrome(macOS 请按 Cmd+Q,仅关窗口不够)
96
95
  3. 等待 `setup` 命令返回(阻塞式,超时 600 秒)
97
96
  4. 收到成功 → 继续执行 `connect --headless`
98
97
 
99
98
  ### setup 之后
100
99
 
101
- `setup` 只需执行一次。登录凭证和 plugin 配置都已保存,之后每次只需 `connect --headless` 即可自动连接,无需用户操作。
100
+ `setup` 只需执行一次。登录凭证已保存,之后每次只需 `connect --headless` 即可自动连接,无需用户操作。
102
101
 
103
102
  如果后续 headless 模式下 Plugin 始终不连接,可能是 RemNote 登录 session 过期,需重新 setup(删除 `~/.remnote-bridge/chrome-profile/.setup-done` 后重新执行)。
104
103