remnote-bridge 0.1.15 → 0.1.17

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.
@@ -310,9 +310,10 @@ Agent 需要根据用户意图选择正确的读取命令:
310
310
  │ 适合:首次探索、了解知识库组织
311
311
 
312
312
  ├─ 用户当前在看什么 → read-context
313
- │ ├─ focus 模式(默认):以用户聚焦的 Rem 为中心的鱼眼视图
314
- │ │ 焦点本身展开 depth=3,siblings 浅层展开,祖先路径可见
315
- │ └─ page 模式:以当前打开页面为根展开子树
313
+ │ ├─ page 模式(默认,推荐):以当前打开页面为根展开子树
314
+ │ │ 只需有打开的页面即可,几乎总能成功
315
+ │ └─ focus 模式(仅特定场景):以用户光标所在 Rem 为中心的鱼眼视图
316
+ │ 需用户光标停在某个 Rem 上,否则报错;仅当需要定位光标位置时使用
316
317
 
317
318
  ├─ 某个具体 Rem 的子树 → read-tree <remId>
318
319
  │ 完整展开子树(支持深度/节点预算控制)
@@ -339,8 +340,8 @@ Agent 需要根据用户意图选择正确的读取命令:
339
340
  | 场景 | 命令 | 输出特点 |
340
341
  |:-----|:-----|:---------|
341
342
  | "看看知识库有什么" | `read-globe` | 仅 Document 层级,无内容 Rem |
342
- | "我现在在编辑什么" | `read-context --mode focus` | 鱼眼视图,焦点处详细 |
343
- | "当前页面的内容" | `read-context --mode page` | 以页面为根展开 |
343
+ | "当前页面的内容" | `read-context` | 以页面为根展开(默认,推荐) |
344
+ | "我光标在哪" / "我正在编辑的 Rem" | `read-context --mode focus` | 鱼眼视图(需光标在某 Rem 上,否则报错) |
344
345
  | "展开某个主题的细节" | `read-tree <id>` | 完整子树,可缓存供编辑 |
345
346
  | "展开子树并查看每个节点属性" | `read-rem-in-tree <id>` | 大纲 + RemObject,双重缓存 |
346
347
 
@@ -354,18 +355,25 @@ Agent 需要根据用户意图选择正确的读取命令:
354
355
 
355
356
  #### read-context 特性
356
357
 
357
- **focus 模式**(默认):
358
- - 获取用户当前聚焦的 Rem(需要用户在 RemNote 中点击某个 Rem)
359
- - 鱼眼视图展开策略:焦点 depth=3,焦点的 siblings depth=1,叔伯节点 depth=0
360
- - 向上追溯 `ancestorLevels` 层(默认 2)
361
- - 焦点 Rem 前标记 `* ` 前缀
362
- - 输出头部含 path 和 focus 信息
358
+ **模式选择指引**:
359
+ - **绝大多数场景用 page(默认)**——用户通常只是打开页面浏览,不会特意点击某个 Rem 让光标停在上面。page 只需有打开的页面就能工作,几乎总能成功
360
+ - **仅当需要定位用户光标时用 focus**——如用户说"我正在编辑的这个"、"光标所在的 Rem"。focus 要求光标停在某个 Rem 上,否则报错"当前没有聚焦的 Rem"
361
+ - **不确定时用 page**——最坏情况只是展开整个页面;focus 的最坏情况是报错
363
362
 
364
- **page 模式**:
363
+ **page 模式**(默认,推荐):
365
364
  - 获取当前面板打开的页面 Rem
366
365
  - 以该页面为根展开子树
367
366
  - 参数:`depth`(默认 3)、`maxNodes`、`maxSiblings`
368
367
  - 输出头部含 page 名和 breadcrumb path
368
+ - 前置条件宽松:只需有打开的页面
369
+
370
+ **focus 模式**(仅特定场景):
371
+ - 获取用户当前聚焦的 Rem(需要用户在 RemNote 中点击某个 Rem)
372
+ - 鱼眼视图展开策略:焦点 depth=3,焦点的 siblings depth=1,叔伯节点 depth=0
373
+ - 向上追溯 `ancestorLevels` 层(默认 2)
374
+ - 焦点 Rem 前标记 `* ` 前缀
375
+ - 输出头部含 path 和 focus 信息
376
+ - ⚠️ 前置条件严格:用户光标必须停在某个 Rem 上,否则报错
369
377
 
370
378
  两者共同点:不缓存、Portal 感知、Powerup 噪音过滤、返回 breadcrumb。
371
379
 
@@ -613,7 +621,7 @@ Portal:portalType [R], portalDirectlyIncludedRem [Portal-W]
613
621
 
614
622
  `h` 颜色值:0=无, 1=Red, 2=Orange, 3=Yellow, 4=Green, 5=Purple, 6=Blue, 7=Gray, 8=Brown, 9=Pink。
615
623
 
616
- **序列化确定性**:RichText 对象内部按 key 字母序排列(`sortRichTextKeys()`)。`_id` 的 `_`(U+005F)排在所有小写字母之前。这对乐观并发检测和 edit-tree 的 str_replace 至关重要。
624
+ **序列化确定性**:RichText 对象内部按 key 字母序排列(`sortRichTextKeys()`)。`_id` 的 `_`(U+005F)排在所有小写字母之前。这对语义并发检测和 edit-tree 的 str_replace 至关重要。
617
625
 
618
626
  ---
619
627
 
@@ -642,9 +650,17 @@ read-tree / read-globe / read-context 的输出核心是 Markdown 大纲文本
642
650
  | `### ` | H3 标题 | `fontSize: 'H3'` |
643
651
  | `- [ ] ` | 未完成待办 | `isTodo: true, todoStatus: 'Unfinished'` |
644
652
  | `- [x] ` | 已完成待办 | `isTodo: true, todoStatus: 'Finished'` |
653
+ | `> ` | 引用块 | `isQuote: true` |
654
+ | `1. ` | 有序列表项(⚠️ 见下方说明) | `isListItem: true` |
645
655
  | `` `...` `` | 代码块 | `isCode: true` |
646
656
  | `---` | 分隔线 | Divider Powerup |
647
657
 
658
+ > **⚠️ 有序列表必须用 `1. ` 前缀(Lazy Numbering)**
659
+ >
660
+ > RemNote 有序列表采用 Lazy Numbering——所有列表项统一写 `1. `,RemNote 按层级自动编号(1./2./3./A./B./I./II.)。不要手动编号。
661
+ > - `2. `~`9. ` 会被容错处理(归一化为 `isListItem=true`,返回 `templateWarnings` 警告)
662
+ > - `10. ` 及以上**不会**被识别为有序列表,而是作为纯文本内容保留
663
+
648
664
  ### 8.3 箭头分隔符
649
665
 
650
666
  箭头编码 `practiceDirection`(闪卡练习方向),不编码 type(type 由元数据标记承载)。
@@ -741,13 +757,18 @@ read-tree / read-globe / read-context 的输出核心是 Markdown 大纲文本
741
757
 
742
758
  未缓存的 Rem 不允许编辑。确保 Agent 看到的数据和即将编辑的数据是同一份。
743
759
 
744
- #### 防线 2:乐观并发检测
760
+ #### 防线 2:语义并发检测
745
761
 
746
762
  ```
747
- edit 时重新从 SDK 读取最新数据 → 与缓存严格比较
763
+ edit 时重新从 SDK 读取最新数据 → 只比较语义字段(内容、类型、格式、标签等)
748
764
  ```
749
765
 
750
- 如果 Rem 在 read 之后被外部修改(用户在 RemNote UI 中编辑、其他 Agent 修改等),数据不一致时拒绝编辑,**且不更新缓存**——迫使 Agent 重新 read。
766
+ RemObject 字段分为三层:
767
+ - **语义字段**(text, backText, type, tags, highlightColor, fontSize 等):变化 → 硬拒绝,迫使 Agent 重新 read
768
+ - **敏感元数据**(parent):变化 → 放行 + `"⚠️ parent has changed (was: oldId, now: newId). The Rem has been moved to a different parent since last read. Proceeding with edit."`
769
+ - **普通元数据**(positionAmongstSiblings, updatedAt, siblingRem, children, descendants 等):变化 → 放行 + `"ℹ️ Metadata fields changed since last read: {fields}. This is expected after structural operations. Proceeding with edit."`
770
+
771
+ 这意味着 `edit-tree` 移动/重排 Rem 后,可以直接 `edit-rem` 修改受影响节点的文本格式,无需逐个重新 `read-rem`。只有真正的内容/属性并发冲突才会被拦截。
751
772
 
752
773
  #### edit-rem 防线 3:字段白名单校验
753
774
 
@@ -773,7 +794,8 @@ oldStr 必须在目标文本中恰好匹配 1 次
773
794
  | 场景 | 缓存行为 |
774
795
  |:-----|:---------|
775
796
  | 写入全部成功 | 从 SDK 重新读取最新状态 → **更新缓存** |
776
- | 防线拒绝(缓存缺失 / 并发冲突) | **不更新缓存**(迫使 Agent 重新 read) |
797
+ | 仅元数据变化(位置/时间戳等) | **静默刷新缓存并放行**(返回警告) |
798
+ | 语义字段冲突(内容/类型/格式等) | **不更新缓存**(迫使 Agent 重新 read) |
777
799
  | 枚举值非法 | **报错拒绝**,不更新缓存 |
778
800
  | 部分写入失败 | **不更新缓存** |
779
801
 
@@ -811,6 +833,8 @@ edit-tree 使用 str_replace 对 Markdown 大纲进行结构编辑。详细文
811
833
  # 新标题 H1
812
834
  新闪卡 → 答案
813
835
  - [ ] 新待办
836
+ > 引用内容
837
+ 1. 列表项
814
838
  `代码块内容`
815
839
  ```
816
840
 
@@ -849,7 +873,7 @@ RemNote 的格式设置通过 Powerup 机制实现,会向 Rem 注入隐藏的
849
873
  "readTreeAncestorLevels": 0,
850
874
  "readTreeIncludePowerup": false,
851
875
  "readGlobeDepth": -1,
852
- "readContextMode": "focus",
876
+ "readContextMode": "page",
853
877
  "readContextAncestorLevels": 2,
854
878
  "readContextDepth": 3,
855
879
  "searchNumResults": 20
@@ -893,7 +917,7 @@ Agent 遇到错误时的诊断和恢复指南:
893
917
  | 错误 | 原因 | 恢复 |
894
918
  |:-----|:-----|:-----|
895
919
  | has not been read yet | 未先执行 read-rem / read-tree | 执行对应 read 命令后重试 |
896
- | has been modified since last read | Rem read 和 edit 之间被外部修改 | 重新执行 read 获取最新状态后重试 |
920
+ | has been modified since last read | Rem 的语义字段在 read 和 edit 之间被外部修改 | 重新执行 read 获取最新状态后重试 |
897
921
 
898
922
  ### edit-tree str_replace 错误
899
923
 
@@ -8,8 +8,13 @@
8
8
 
9
9
  `read-context` 根据用户在 RemNote 中的当前位置,生成上下文感知的 Markdown 大纲。两种模式适用于不同场景:
10
10
 
11
- - **focus 模式**(默认):以当前焦点 Rem 为中心,向上追溯祖先,构建鱼眼视图——焦点完全展开,周围递减
12
- - **page 模式**:以当前打开的页面 Rem 为根,均匀展开子树
11
+ - **page 模式**(默认,推荐):以当前打开的页面 Rem 为根,均匀展开子树。只需有打开的页面即可,几乎总能成功
12
+ - **focus 模式**(仅特定场景):以当前焦点 Rem 为中心,向上追溯祖先,构建鱼眼视图——焦点完全展开,周围递减。需用户光标停在某个 Rem 上,否则报错
13
+
14
+ **何时用哪个模式**:
15
+ - 绝大多数场景用 page(默认)——用户通常只是打开页面浏览,不会特意让光标停在某个 Rem 上
16
+ - 仅当需要知道用户光标具体在哪个 Rem 上时才用 focus——如用户说"我正在编辑的这个"、"光标所在位置"
17
+ - 不确定时用 page——最坏情况只是展开整个页面;focus 的最坏情况是报错"当前没有聚焦的 Rem"
13
18
 
14
19
  核心能力:
15
20
  - 鱼眼深度梯度(focus 模式):焦点 depth=3、siblings depth=1、叔伯 depth=0
@@ -32,7 +37,7 @@ remnote-bridge read-context [--mode <mode>] [--ancestor-levels <N>] [--depth <N>
32
37
 
33
38
  | 参数/选项 | 类型 | 必需 | 说明 |
34
39
  |-----------|------|:----:|------|
35
- | `--mode <mode>` | string | 否 | 模式:`focus`(默认)或 `page` |
40
+ | `--mode <mode>` | string | 否 | 模式:`page`(默认)或 `focus` |
36
41
  | `--ancestor-levels <N>` | integer | 否 | 向上追溯几层祖先(默认 2,仅 focus 模式) |
37
42
  | `--depth <N>` | integer | 否 | 展开深度(默认 3,仅 page 模式) |
38
43
  | `--max-nodes <N>` | integer | 否 | 全局节点上限(默认 200) |
@@ -84,7 +89,7 @@ remnote-bridge read-context --json '{"mode":"page","depth":5,"maxSiblings":10}'
84
89
 
85
90
  | 字段 | 类型 | 必需 | 说明 |
86
91
  |------|------|:----:|------|
87
- | `mode` | string | 否 | 模式:`"focus"` 或 `"page"`(默认 `"focus"`) |
92
+ | `mode` | string | 否 | 模式:`"page"` 或 `"focus"`(默认 `"page"`) |
88
93
  | `ancestorLevels` | number | 否 | 向上追溯几层祖先(默认 2,仅 focus 模式) |
89
94
  | `depth` | number | 否 | 展开深度(默认 3,仅 page 模式) |
90
95
  | `maxNodes` | number | 否 | 全局节点上限(默认 200) |
@@ -359,7 +364,7 @@ focus 模式的核心特点是**渐进式展开**——离焦点越近,展开
359
364
 
360
365
  | 配置项 | 默认值 | 说明 |
361
366
  |--------|--------|------|
362
- | `defaults.readContextMode` | `"focus"` | 默认模式 |
367
+ | `defaults.readContextMode` | `"page"` | 默认模式 |
363
368
  | `defaults.readContextAncestorLevels` | 2 | focus 模式默认祖先层数 |
364
369
  | `defaults.readContextDepth` | 3 | page 模式默认展开深度 |
365
370
  | `defaults.maxNodes` | 200 | 默认全局节点上限 |
@@ -140,6 +140,9 @@ Skill 接口加 `s` 后缀(**s** = Skill)。这样两个 subagent 创建的
140
140
  ### Step 2:构造 subagent 并执行
141
141
 
142
142
  使用 haiku subagent 执行测试。
143
+ 严禁只使用单个 sub-agent 进行测试。
144
+ 除非测试用例有特别说明,否则必须同时启用 MCP 和 Skill 两个 sub-agent 进行测试。根据测试要求,动态决定是否并行。
145
+ 严禁只测一个 sub-agent 的行为。
143
146
 
144
147
  #### 双接口策略
145
148
 
@@ -270,6 +270,70 @@
270
270
 
271
271
  ---
272
272
 
273
+ ### L2-05: Markdown 前缀转换(有序列表 + 引用块)
274
+
275
+ **task_description**:
276
+ ```
277
+ 测试 Markdown 前缀(有序列表 `1. ` 和引用块 `> `)的双向转换能力。
278
+
279
+ 1. 确认连接正常
280
+ 2. 读取测试页面的子树(read_tree)
281
+ 3. 在测试页面下创建以下结构(edit_tree),包含有序列表和引用块,层级嵌套到 4 层:
282
+
283
+ {prefix} Markdown 前缀测试
284
+ ## 有序列表测试
285
+ 1. 第一层列表项A
286
+ 1. 第二层列表项A-1
287
+ 1. 第三层列表项A-1-a
288
+ 1. 第四层列表项A-1-a-i
289
+ 1. 第四层列表项A-1-a-ii
290
+ 1. 第三层列表项A-1-b
291
+ 1. 第二层列表项A-2
292
+ 1. 第一层列表项B
293
+ 1. 第二层列表项B-1
294
+ 1. 第二层列表项B-2
295
+ 1. 第三层列表项B-2-a
296
+ ## 引用块测试
297
+ > 这是一段引用文本
298
+ > 这是另一段引用
299
+ 普通文本(不是引用)
300
+ ## 混合格式测试
301
+ 1. 有序列表项带闪卡 → 答案内容
302
+ > 引用块带闪卡 → 引用中的答案
303
+ - [ ] 待办事项
304
+ `代码块内容`
305
+
306
+ 4. 重新读取子树(read_tree,depth=5),验证:
307
+ - 有序列表项都有 `1. ` 前缀
308
+ - 引用块都有 `> ` 前缀
309
+ - 4 层嵌套的有序列表层级正确
310
+ - 普通文本没有 `1. ` 或 `> ` 前缀
311
+ - 混合格式中各前缀正确(`1. `、`> `、`- [ ] `、反引号)
312
+
313
+ 5. 对任意 2 个有序列表节点和 1 个引用块节点执行 read_rem,验证:
314
+ - 有序列表节点 isListItem=true
315
+ - 引用块节点 isQuote=true
316
+ - 普通文本节点 isListItem=false, isQuote=false
317
+ ```
318
+
319
+ **Chrome 验证**:
320
+ - ⬜ "{prefix} Markdown 前缀测试" 存在
321
+ - ⬜ "有序列表测试" 下的节点显示为数字编号(1. 2. 3...),而非 bullet
322
+ - ⬜ 有序列表嵌套到 4 层,每层都有数字编号
323
+ - ⬜ "引用块测试" 下有灰色引用样式(左侧竖线 + 浅灰背景)
324
+ - ⬜ "普通文本(不是引用)" 是正常样式,没有引用标记
325
+ - ⬜ 混合格式区域各格式正确(有序列表、引用、待办、代码块共存)
326
+
327
+ **断言**:
328
+ - [ ] edit_tree 成功创建包含 `1. ` 和 `> ` 前缀的结构
329
+ - [ ] read_tree 输出中有序列表项带 `1. ` 前缀
330
+ - [ ] read_tree 输出中引用块带 `> ` 前缀
331
+ - [ ] 4 层嵌套有序列表结构完整
332
+ - [ ] read_rem 确认 isListItem=true / isQuote=true
333
+ - [ ] 混合格式互不干扰
334
+
335
+ ---
336
+
273
337
  ## L3 多步工作流
274
338
 
275
339
  > 多步骤组合链路,模拟真实的知识整理流程。