remnote-bridge 0.1.0

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 (135) hide show
  1. package/dist/cli/commands/connect.d.ts +12 -0
  2. package/dist/cli/commands/connect.js +124 -0
  3. package/dist/cli/commands/disconnect.d.ts +11 -0
  4. package/dist/cli/commands/disconnect.js +100 -0
  5. package/dist/cli/commands/edit-rem.d.ts +13 -0
  6. package/dist/cli/commands/edit-rem.js +83 -0
  7. package/dist/cli/commands/edit-tree.d.ts +14 -0
  8. package/dist/cli/commands/edit-tree.js +67 -0
  9. package/dist/cli/commands/health.d.ts +12 -0
  10. package/dist/cli/commands/health.js +100 -0
  11. package/dist/cli/commands/install-skill.d.ts +6 -0
  12. package/dist/cli/commands/install-skill.js +39 -0
  13. package/dist/cli/commands/read-context.d.ts +20 -0
  14. package/dist/cli/commands/read-context.js +77 -0
  15. package/dist/cli/commands/read-globe.d.ts +16 -0
  16. package/dist/cli/commands/read-globe.js +60 -0
  17. package/dist/cli/commands/read-rem.d.ts +16 -0
  18. package/dist/cli/commands/read-rem.js +80 -0
  19. package/dist/cli/commands/read-tree.d.ts +17 -0
  20. package/dist/cli/commands/read-tree.js +85 -0
  21. package/dist/cli/commands/search.d.ts +12 -0
  22. package/dist/cli/commands/search.js +65 -0
  23. package/dist/cli/config.d.ts +55 -0
  24. package/dist/cli/config.js +139 -0
  25. package/dist/cli/daemon/daemon.d.ts +11 -0
  26. package/dist/cli/daemon/daemon.js +186 -0
  27. package/dist/cli/daemon/dev-server.d.ts +26 -0
  28. package/dist/cli/daemon/dev-server.js +81 -0
  29. package/dist/cli/daemon/pid.d.ts +34 -0
  30. package/dist/cli/daemon/pid.js +67 -0
  31. package/dist/cli/daemon/send-request.d.ts +24 -0
  32. package/dist/cli/daemon/send-request.js +92 -0
  33. package/dist/cli/handlers/context-read-handler.d.ts +18 -0
  34. package/dist/cli/handlers/context-read-handler.js +24 -0
  35. package/dist/cli/handlers/edit-handler.d.ts +30 -0
  36. package/dist/cli/handlers/edit-handler.js +133 -0
  37. package/dist/cli/handlers/globe-read-handler.d.ts +17 -0
  38. package/dist/cli/handlers/globe-read-handler.js +23 -0
  39. package/dist/cli/handlers/read-handler.d.ts +16 -0
  40. package/dist/cli/handlers/read-handler.js +78 -0
  41. package/dist/cli/handlers/rem-cache.d.ts +19 -0
  42. package/dist/cli/handlers/rem-cache.js +63 -0
  43. package/dist/cli/handlers/tree-edit-handler.d.ts +30 -0
  44. package/dist/cli/handlers/tree-edit-handler.js +188 -0
  45. package/dist/cli/handlers/tree-parser.d.ts +95 -0
  46. package/dist/cli/handlers/tree-parser.js +506 -0
  47. package/dist/cli/handlers/tree-read-handler.d.ts +28 -0
  48. package/dist/cli/handlers/tree-read-handler.js +53 -0
  49. package/dist/cli/main.d.ts +7 -0
  50. package/dist/cli/main.js +300 -0
  51. package/dist/cli/protocol.d.ts +39 -0
  52. package/dist/cli/protocol.js +35 -0
  53. package/dist/cli/server/config-server.d.ts +26 -0
  54. package/dist/cli/server/config-server.js +363 -0
  55. package/dist/cli/server/ws-server.d.ts +68 -0
  56. package/dist/cli/server/ws-server.js +335 -0
  57. package/dist/cli/utils/output.d.ts +11 -0
  58. package/dist/cli/utils/output.js +13 -0
  59. package/dist/mcp/daemon-client.d.ts +31 -0
  60. package/dist/mcp/daemon-client.js +99 -0
  61. package/dist/mcp/index.d.ts +7 -0
  62. package/dist/mcp/index.js +68 -0
  63. package/dist/mcp/instructions.d.ts +1 -0
  64. package/dist/mcp/instructions.js +249 -0
  65. package/dist/mcp/resources/edit-tree-guide.d.ts +1 -0
  66. package/dist/mcp/resources/edit-tree-guide.js +197 -0
  67. package/dist/mcp/resources/error-reference.d.ts +1 -0
  68. package/dist/mcp/resources/error-reference.js +132 -0
  69. package/dist/mcp/resources/outline-format.d.ts +1 -0
  70. package/dist/mcp/resources/outline-format.js +104 -0
  71. package/dist/mcp/resources/rem-object-fields.d.ts +1 -0
  72. package/dist/mcp/resources/rem-object-fields.js +331 -0
  73. package/dist/mcp/resources/separator-flashcard.d.ts +1 -0
  74. package/dist/mcp/resources/separator-flashcard.js +120 -0
  75. package/dist/mcp/tools/edit-tools.d.ts +5 -0
  76. package/dist/mcp/tools/edit-tools.js +47 -0
  77. package/dist/mcp/tools/infra-tools.d.ts +5 -0
  78. package/dist/mcp/tools/infra-tools.js +43 -0
  79. package/dist/mcp/tools/read-tools.d.ts +5 -0
  80. package/dist/mcp/tools/read-tools.js +195 -0
  81. package/dist/mcp/types.d.ts +12 -0
  82. package/dist/mcp/types.js +4 -0
  83. package/docs/instruction/connect.md +158 -0
  84. package/docs/instruction/disconnect.md +146 -0
  85. package/docs/instruction/edit-rem.md +509 -0
  86. package/docs/instruction/edit-tree.md +419 -0
  87. package/docs/instruction/health.md +159 -0
  88. package/docs/instruction/overall.md +751 -0
  89. package/docs/instruction/read-context.md +353 -0
  90. package/docs/instruction/read-globe.md +206 -0
  91. package/docs/instruction/read-rem.md +476 -0
  92. package/docs/instruction/read-tree.md +428 -0
  93. package/docs/instruction/search.md +196 -0
  94. package/package.json +41 -0
  95. package/remnote-plugin/package.json +48 -0
  96. package/remnote-plugin/postcss.config.js +5 -0
  97. package/remnote-plugin/public/bridge-icon.svg +8 -0
  98. package/remnote-plugin/public/manifest.json +22 -0
  99. package/remnote-plugin/src/bridge/message-router.ts +57 -0
  100. package/remnote-plugin/src/bridge/websocket-client.ts +245 -0
  101. package/remnote-plugin/src/index.css +1 -0
  102. package/remnote-plugin/src/services/breadcrumb.ts +26 -0
  103. package/remnote-plugin/src/services/create-rem.ts +59 -0
  104. package/remnote-plugin/src/services/delete-rem.ts +29 -0
  105. package/remnote-plugin/src/services/index.ts +16 -0
  106. package/remnote-plugin/src/services/move-rem.ts +39 -0
  107. package/remnote-plugin/src/services/powerup-filter.ts +31 -0
  108. package/remnote-plugin/src/services/read-context.ts +368 -0
  109. package/remnote-plugin/src/services/read-globe.ts +197 -0
  110. package/remnote-plugin/src/services/read-rem.ts +284 -0
  111. package/remnote-plugin/src/services/read-tree.ts +222 -0
  112. package/remnote-plugin/src/services/rem-builder.ts +124 -0
  113. package/remnote-plugin/src/services/reorder-children.ts +61 -0
  114. package/remnote-plugin/src/services/search.ts +56 -0
  115. package/remnote-plugin/src/services/write-rem-fields.ts +254 -0
  116. package/remnote-plugin/src/settings.ts +12 -0
  117. package/remnote-plugin/src/style.css +45 -0
  118. package/remnote-plugin/src/test-scripts/AGENTS.md +46 -0
  119. package/remnote-plugin/src/test-scripts/test-actions.ts +230 -0
  120. package/remnote-plugin/src/test-scripts/test-powerup-rendering.ts +722 -0
  121. package/remnote-plugin/src/test-scripts/test-rem-type-mapping.ts +283 -0
  122. package/remnote-plugin/src/test-scripts/test-richtext-builder.ts +207 -0
  123. package/remnote-plugin/src/test-scripts/test-richtext-matrix.ts +332 -0
  124. package/remnote-plugin/src/test-scripts/test-richtext-remaining.ts +245 -0
  125. package/remnote-plugin/src/test-scripts/test-rw-fields.ts +399 -0
  126. package/remnote-plugin/src/types.ts +419 -0
  127. package/remnote-plugin/src/utils/elision.ts +45 -0
  128. package/remnote-plugin/src/utils/index.ts +10 -0
  129. package/remnote-plugin/src/utils/tree-serializer.ts +269 -0
  130. package/remnote-plugin/src/widgets/bridge_widget.tsx +170 -0
  131. package/remnote-plugin/src/widgets/index.tsx +82 -0
  132. package/remnote-plugin/tailwind.config.js +7 -0
  133. package/remnote-plugin/tsconfig.json +21 -0
  134. package/remnote-plugin/webpack.config.js +125 -0
  135. package/skill/SKILL.md +428 -0
@@ -0,0 +1,476 @@
1
+ # read-rem
2
+
3
+ > 读取单个 Rem 的完整属性,返回 RemObject(51 字段的标准化数据对象)。
4
+
5
+ ---
6
+
7
+ ## 功能
8
+
9
+ `read-rem` 通过 Rem ID 读取一个 Rem 的所有可获取属性,返回标准化的 RemObject。读取结果会被缓存在 daemon 内存中,供后续 `edit-rem` 使用。
10
+
11
+ 核心能力:
12
+ - 返回 51 个字段的完整 Rem 数据(默认 34 个,`--full` 时 51 个)
13
+ - 支持 `--fields` 指定字段子集
14
+ - 支持 Powerup 噪音过滤(默认过滤)
15
+ - 自动缓存,为 `edit-rem` 建立编辑基础
16
+
17
+ ---
18
+
19
+ ## 用法
20
+
21
+ ### 人类模式
22
+
23
+ ```bash
24
+ remnote-bridge read-rem <remId> [--fields <fieldList>] [--full] [--includePowerup]
25
+ ```
26
+
27
+ | 参数/选项 | 类型 | 必需 | 说明 |
28
+ |-----------|------|:----:|------|
29
+ | `remId` | string(位置参数) | 是 | Rem ID |
30
+ | `--fields <fieldList>` | string | 否 | 逗号分隔的字段列表,返回指定字段子集 |
31
+ | `--full` | boolean | 否 | 输出全部 51 个字段(含 R-F 低频字段) |
32
+ | `--includePowerup` | boolean | 否 | 包含 Powerup 系统数据(默认过滤) |
33
+
34
+ 输出示例:
35
+
36
+ ```
37
+ {
38
+ "id": "kLrIOHJLyMd8Y2lyA",
39
+ "text": [...],
40
+ "type": "concept",
41
+ ...
42
+ }
43
+ ```
44
+
45
+ ### JSON 模式
46
+
47
+ ```bash
48
+ remnote-bridge read-rem --json '{"remId":"kLrIOHJLyMd8Y2lyA"}'
49
+ ```
50
+
51
+ ---
52
+
53
+ ## JSON 输入参数
54
+
55
+ | 字段 | 类型 | 必需 | 说明 |
56
+ |------|------|:----:|------|
57
+ | `remId` | string | 是 | Rem ID |
58
+ | `fields` | string[] | 否 | 字段数组,返回指定字段子集(始终包含 `id`) |
59
+ | `full` | boolean | 否 | 返回全部 51 个字段 |
60
+ | `includePowerup` | boolean | 否 | 包含 Powerup 系统数据 |
61
+
62
+ ---
63
+
64
+ ## JSON 输出
65
+
66
+ ### 成功
67
+
68
+ ```json
69
+ {
70
+ "ok": true,
71
+ "command": "read-rem",
72
+ "data": {
73
+ "id": "kLrIOHJLyMd8Y2lyA",
74
+ "text": [{ "i": "m", "text": "示例文本", "b": true }],
75
+ "backText": null,
76
+ "type": "concept",
77
+ "isDocument": false,
78
+ "parent": "parentRemId",
79
+ "children": ["childId1", "childId2"],
80
+ "fontSize": null,
81
+ "highlightColor": null,
82
+ "isTodo": false,
83
+ "todoStatus": null,
84
+ "...": "(共 34 个字段,--full 时 51 个)"
85
+ },
86
+ "timestamp": "2026-03-06T10:00:00.000Z"
87
+ }
88
+ ```
89
+
90
+ ### 成功(含缓存覆盖提示)
91
+
92
+ 当该 Rem 之前已有缓存时,输出中附加 `cacheOverridden` 字段:
93
+
94
+ ```json
95
+ {
96
+ "ok": true,
97
+ "command": "read-rem",
98
+ "data": { "...": "RemObject" },
99
+ "cacheOverridden": {
100
+ "id": "kLrIOHJLyMd8Y2lyA",
101
+ "previousCachedAt": "2026-03-06T09:55:00.000Z"
102
+ },
103
+ "timestamp": "2026-03-06T10:00:00.000Z"
104
+ }
105
+ ```
106
+
107
+ ### 成功(含 Powerup 过滤统计)
108
+
109
+ 当默认过滤了 Powerup 系统数据时:
110
+
111
+ ```json
112
+ {
113
+ "ok": true,
114
+ "command": "read-rem",
115
+ "data": { "...": "RemObject" },
116
+ "powerupFiltered": { "tags": 3, "children": 5 },
117
+ "timestamp": "2026-03-06T10:00:00.000Z"
118
+ }
119
+ ```
120
+
121
+ ### Rem 不存在
122
+
123
+ ```json
124
+ {
125
+ "ok": false,
126
+ "command": "read-rem",
127
+ "error": "Rem not found: kLrIOHJLyMd8Y2lyA",
128
+ "timestamp": "2026-03-06T10:00:00.000Z"
129
+ }
130
+ ```
131
+
132
+ ### daemon 不可达
133
+
134
+ ```json
135
+ {
136
+ "ok": false,
137
+ "command": "read-rem",
138
+ "error": "守护进程未运行,请先执行 remnote-bridge connect",
139
+ "timestamp": "2026-03-06T10:00:00.000Z"
140
+ }
141
+ ```
142
+
143
+ ---
144
+
145
+ ## 内部流程
146
+
147
+ ```
148
+ 1. CLI 解析参数(remId, fields, full, includePowerup)
149
+ 2. sendRequest → WS → daemon
150
+ 3. daemon ReadHandler:
151
+ ├─ 记录旧缓存时间(若存在)
152
+ ├─ forwardToPlugin('read_rem', { remId, includePowerup })
153
+ ├─ Plugin 端:
154
+ │ ├─ plugin.rem.findOne(remId) → 获取 SDK Rem 对象
155
+ │ ├─ 并行调用 40+ SDK getter(text, backText, type, children, tags...)
156
+ │ ├─ 构造 RemObject(含 RichText key 排序,确保序列化确定性)
157
+ │ └─ 可选:Powerup 噪音过滤(filterNoisyTags + filterNoisyChildren)
158
+ ├─ 缓存完整 JSON:cache.set('rem:' + remId, fullJson)
159
+ ├─ 字段过滤:
160
+ │ ├─ --full → 返回全部 51 字段
161
+ │ ├─ --fields → 返回指定字段 + id
162
+ │ └─ 默认 → 排除 R-F 字段(返回 34 字段)
163
+ └─ 附加 _cacheOverridden 元数据(若之前有缓存)
164
+ 4. CLI 格式化输出(人类模式 pretty-print / JSON 模式单行)
165
+ ```
166
+
167
+ ---
168
+
169
+ ## RemObject 完整字段表
170
+
171
+ RemObject 共 51 个字段,按读写权限分为三类:
172
+
173
+ - **RW**(20 个):可读可写,SDK 有对应的 setter
174
+ - **R**(14 个):只读,默认输出
175
+ - **R-F**(17 个):只读,仅 `--full` 模式输出(低频 / 可由其他字段推导)
176
+
177
+ ### 核心标识
178
+
179
+ | 字段 | 类型 | 权限 | 说明 |
180
+ |------|------|:----:|------|
181
+ | `id` | `string` | R | Rem 唯一 ID |
182
+
183
+ ### 内容
184
+
185
+ | 字段 | 类型 | 权限 | 说明 |
186
+ |------|------|:----:|------|
187
+ | `text` | `RichText` | RW | 正面文本(RichText 数组) |
188
+ | `backText` | `RichText \| null` | RW | 背面文本。null=无背面;设值即产生闪卡正反面结构 |
189
+
190
+ ### 类型系统
191
+
192
+ | 字段 | 类型 | 权限 | 说明 |
193
+ |------|------|:----:|------|
194
+ | `type` | `RemTypeValue` | RW | `concept` / `descriptor` / `default` / `portal` |
195
+ | `isDocument` | `boolean` | RW | 是否作为独立文档页面。独立于 type |
196
+
197
+ ### 结构
198
+
199
+ | 字段 | 类型 | 权限 | 说明 |
200
+ |------|------|:----:|------|
201
+ | `parent` | `string \| null` | RW | 父 Rem ID。null=顶级 |
202
+ | `children` | `string[]` | R | 子 Rem ID 有序数组 |
203
+
204
+ ### 格式 / 显示
205
+
206
+ | 字段 | 类型 | 权限 | 说明 |
207
+ |------|------|:----:|------|
208
+ | `fontSize` | `FontSize \| null` | RW | 标题大小:`H1` / `H2` / `H3`。null=普通 |
209
+ | `highlightColor` | `HighlightColor \| null` | RW | 高亮颜色(9 种)。null=无高亮 |
210
+
211
+ ### 状态标记
212
+
213
+ | 字段 | 类型 | 权限 | 说明 |
214
+ |------|------|:----:|------|
215
+ | `isTodo` | `boolean` | RW | 是否待办。设为 true 时自动初始化 todoStatus |
216
+ | `todoStatus` | `TodoStatus \| null` | RW | `Finished` / `Unfinished`。需先 isTodo=true |
217
+ | `isCode` | `boolean` | RW | 是否代码块 |
218
+ | `isQuote` | `boolean` | RW | 是否引用块 |
219
+ | `isListItem` | `boolean` | RW | 是否列表项(有序列表样式) |
220
+ | `isCardItem` | `boolean` | RW | 是否卡片项(多行答案行标记) |
221
+ | `isTable` | `boolean` | R | 是否表格(只读) |
222
+ | `isSlot` | `boolean` | RW | 是否 Powerup 插槽。与 isProperty 底层相同 |
223
+ | `isProperty` | `boolean` | RW | 是否 Tag 属性(表格列)。与 isSlot 底层相同 |
224
+
225
+ ### Powerup 系统标识
226
+
227
+ | 字段 | 类型 | 权限 | 说明 |
228
+ |------|------|:----:|------|
229
+ | `isPowerup` | `boolean` | R-F | 是否 Powerup |
230
+ | `isPowerupEnum` | `boolean` | R-F | 是否 Powerup 枚举 |
231
+ | `isPowerupProperty` | `boolean` | R-F | 是否 Powerup 属性 |
232
+ | `isPowerupPropertyListItem` | `boolean` | R-F | 是否 Powerup 属性列表项 |
233
+ | `isPowerupSlot` | `boolean` | R-F | 是否 Powerup 插槽 |
234
+
235
+ ### Portal 专用
236
+
237
+ | 字段 | 类型 | 权限 | 说明 |
238
+ |------|------|:----:|------|
239
+ | `portalType` | `PortalType \| null` | R | Portal 子类型。仅 type=portal 时有值 |
240
+ | `portalDirectlyIncludedRem` | `string[]` | R | Portal 直接包含的 Rem ID |
241
+
242
+ ### 属性类型
243
+
244
+ | 字段 | 类型 | 权限 | 说明 |
245
+ |------|------|:----:|------|
246
+ | `propertyType` | `PropertyTypeValue \| null` | R | 属性数据类型(当此 Rem 是 Tag 的属性时) |
247
+
248
+ ### 练习设置
249
+
250
+ | 字段 | 类型 | 权限 | 说明 |
251
+ |------|------|:----:|------|
252
+ | `enablePractice` | `boolean` | RW | 是否启用间隔重复练习 |
253
+ | `practiceDirection` | `PracticeDirection` | RW | 练习方向:`forward` / `backward` / `both` / `none` |
254
+
255
+ ### 关联 — 直接关系
256
+
257
+ | 字段 | 类型 | 权限 | 说明 |
258
+ |------|------|:----:|------|
259
+ | `tags` | `string[]` | RW | 标签 Rem ID 数组。写入时使用 diff 机制(add/remove) |
260
+ | `sources` | `string[]` | RW | 来源 Rem ID 数组。写入时使用 diff 机制 |
261
+ | `aliases` | `string[]` | R | 别名 Rem ID 数组 |
262
+
263
+ ### 关联 — 引用关系
264
+
265
+ | 字段 | 类型 | 权限 | 说明 |
266
+ |------|------|:----:|------|
267
+ | `remsBeingReferenced` | `string[]` | R | 本 Rem 引用的其他 Rem |
268
+ | `deepRemsBeingReferenced` | `string[]` | R-F | 本 Rem 深层引用的 Rem |
269
+ | `remsReferencingThis` | `string[]` | R | 引用本 Rem 的 Rem(反向链接) |
270
+
271
+ ### 关联 — 标签体系
272
+
273
+ | 字段 | 类型 | 权限 | 说明 |
274
+ |------|------|:----:|------|
275
+ | `taggedRem` | `string[]` | R | 被本 Rem 标记的 Rem(本 Rem 作为 tag 时) |
276
+ | `ancestorTagRem` | `string[]` | R-F | 祖先标签 Rem(标签继承链) |
277
+ | `descendantTagRem` | `string[]` | R-F | 后代标签 Rem(标签继承链) |
278
+
279
+ ### 关联 — 层级遍历
280
+
281
+ | 字段 | 类型 | 权限 | 说明 |
282
+ |------|------|:----:|------|
283
+ | `descendants` | `string[]` | R | 所有后代 Rem |
284
+ | `siblingRem` | `string[]` | R | 兄弟 Rem |
285
+ | `portalsAndDocumentsIn` | `string[]` | R-F | 所在的 Portal 和文档 |
286
+ | `allRemInDocumentOrPortal` | `string[]` | R-F | 文档/Portal 中的所有 Rem |
287
+ | `allRemInFolderQueue` | `string[]` | R-F | 文件夹队列中的 Rem |
288
+
289
+ ### 位置 / 统计
290
+
291
+ | 字段 | 类型 | 权限 | 说明 |
292
+ |------|------|:----:|------|
293
+ | `positionAmongstSiblings` | `number \| null` | RW | 在兄弟间的位置(0 起始) |
294
+ | `timesSelectedInSearch` | `number` | R-F | 搜索中被选次数 |
295
+ | `lastTimeMovedTo` | `number` | R-F | 上次移动时间(毫秒时间戳) |
296
+ | `schemaVersion` | `number` | R-F | Schema 版本号 |
297
+
298
+ ### 队列视图
299
+
300
+ | 字段 | 类型 | 权限 | 说明 |
301
+ |------|------|:----:|------|
302
+ | `embeddedQueueViewMode` | `boolean` | R-F | 嵌入式队列视图模式 |
303
+
304
+ ### 元数据 / 时间戳
305
+
306
+ | 字段 | 类型 | 权限 | 说明 |
307
+ |------|------|:----:|------|
308
+ | `createdAt` | `number` | R | 创建时间(毫秒时间戳) |
309
+ | `updatedAt` | `number` | R | 最后更新时间(毫秒时间戳) |
310
+ | `localUpdatedAt` | `number` | R-F | 本地最后更新时间 |
311
+ | `lastPracticed` | `number` | R-F | 上次练习时间 |
312
+
313
+ ---
314
+
315
+ ## 枚举类型参考
316
+
317
+ ### RemTypeValue
318
+
319
+ | 值 | 含义 | UI 表现 |
320
+ |----|------|---------|
321
+ | `concept` | 概念(双向闪卡) | 文字加粗 |
322
+ | `descriptor` | 描述(单向闪卡) | 正常字重 |
323
+ | `default` | 普通 Rem | 正常字重 |
324
+ | `portal` | 嵌入引用容器 | 紫色左边框(只读,不可通过 setType 设置) |
325
+
326
+ ### FontSize
327
+
328
+ | 值 | UI 表现 |
329
+ |----|---------|
330
+ | `H1` | 超大粗体 |
331
+ | `H2` | 大粗体 |
332
+ | `H3` | 中粗体 |
333
+
334
+ ### TodoStatus
335
+
336
+ | 值 | UI 表现 |
337
+ |----|---------|
338
+ | `Finished` | 蓝色已勾选 + 文本删除线 |
339
+ | `Unfinished` | 空心未勾选 |
340
+
341
+ ### HighlightColor
342
+
343
+ ```
344
+ Red | Orange | Yellow | Green | Blue | Purple | Gray | Brown | Pink
345
+ ```
346
+
347
+ ### PortalType
348
+
349
+ | 值 | 含义 |
350
+ |----|------|
351
+ | `portal` | 标准 Portal |
352
+ | `embedded_queue` | 嵌入式队列视图 |
353
+ | `scaffold` | 脚手架模式 |
354
+ | `search_portal` | 搜索 Portal |
355
+
356
+ ### PracticeDirection
357
+
358
+ | 值 | 含义 |
359
+ |----|------|
360
+ | `forward` | 正向:看 text 回忆 backText |
361
+ | `backward` | 反向:看 backText 回忆 text |
362
+ | `both` | 双向:正反两个方向都练习 |
363
+ | `none` | 不生成闪卡 |
364
+
365
+ ### PropertyTypeValue
366
+
367
+ ```
368
+ text | number | date | checkbox | single_select | multi_select | url | image | title | definition | created_at | last_updated | 0
369
+ ```
370
+
371
+ `0` 表示隐式文本类型(IMPLICIT_TEXT)。
372
+
373
+ ---
374
+
375
+ ## 字段输出层级
376
+
377
+ | 模式 | 输出字段数 | 说明 |
378
+ |------|:----------:|------|
379
+ | 默认 | 34 | RW + R 字段,覆盖常用场景 |
380
+ | `--full` | 51 | 全部字段(含 R-F 低频字段) |
381
+ | `--fields` | 自选 + id | 仅返回指定字段(始终包含 id) |
382
+
383
+ ### R-F 字段列表(默认不输出,`--full` 时输出)
384
+
385
+ ```
386
+ isPowerup, isPowerupEnum, isPowerupProperty, isPowerupPropertyListItem, isPowerupSlot,
387
+ deepRemsBeingReferenced,
388
+ ancestorTagRem, descendantTagRem,
389
+ portalsAndDocumentsIn, allRemInDocumentOrPortal, allRemInFolderQueue,
390
+ timesSelectedInSearch, lastTimeMovedTo, schemaVersion,
391
+ embeddedQueueViewMode,
392
+ localUpdatedAt, lastPracticed
393
+ ```
394
+
395
+ ---
396
+
397
+ ## RichText 格式
398
+
399
+ RemObject 中的 `text` 和 `backText` 字段使用 RichText 格式——一个 JSON 数组,每个元素为纯字符串或带 `i` 字段的格式化对象。
400
+
401
+ ### 元素类型
402
+
403
+ | `i` 值 | 含义 | 核心字段 |
404
+ |--------|------|----------|
405
+ | (纯 string) | 纯文本片段 | — |
406
+ | `"m"` | 带格式文本 | `text` + 格式标记 |
407
+ | `"q"` | Rem 引用 | `_id`(被引用 Rem ID) |
408
+ | `"i"` | 图片 | `url`, `width`, `height` |
409
+ | `"x"` | LaTeX | `text` |
410
+ | `"a"` | 音频 | `url` |
411
+
412
+ ### 行内格式标记(`i:"m"` 元素内)
413
+
414
+ | 字段 | 类型 | 含义 |
415
+ |------|------|------|
416
+ | `b` | `true` | 加粗 |
417
+ | `l` | `true` | 斜体 |
418
+ | `u` | `true` | 下划线 |
419
+ | `h` | `number` | 高亮颜色(1=红, 2=橙, 3=黄, 4=绿, 5=蓝, 6=紫) |
420
+ | `tc` | `number` | 文字颜色 |
421
+ | `code` | `true` | 行内代码 |
422
+ | `cId` | `string` | 完形填空 ID |
423
+ | `iUrl` | `string` | 外部链接 URL |
424
+
425
+ ### 序列化确定性
426
+
427
+ RichText 对象元素内部按 **key 字母序排列**(Plugin 端 `sortRichTextKeys()` 处理),确保同一内容的序列化 JSON 始终一致。这对 `edit-rem` 的 str_replace 和乐观并发检测至关重要。
428
+
429
+ ---
430
+
431
+ ## Powerup 过滤
432
+
433
+ 默认 `includePowerup=false` 时,系统会过滤掉 Powerup 产生的噪音数据:
434
+
435
+ | 过滤对象 | 过滤条件 | 说明 |
436
+ |----------|----------|------|
437
+ | **tags** | `isPowerup()=true` 的 Tag | 系统 Powerup Tag(如"标题"、"高亮"、"代码"等) |
438
+ | **children** | `isPowerupProperty()` / `isPowerupSlot()` / `isPowerupPropertyListItem()` / `isPowerupEnum()` 为 true 的子 Rem | Powerup 产生的隐藏子 Rem(如 `[Size];;[H1]` descriptor) |
439
+
440
+ 过滤统计通过 `powerupFiltered` 字段返回(如 `{"tags": 3, "children": 5}`)。
441
+
442
+ `--includePowerup` 可恢复完整数据,用于调试或分析 Powerup 机制。
443
+
444
+ ---
445
+
446
+ ## 缓存行为
447
+
448
+ | 时机 | 行为 |
449
+ |------|------|
450
+ | 读取成功 | 完整 JSON 写入缓存 `cache.set('rem:' + remId, fullJson)` |
451
+ | 已有缓存 | 覆盖旧缓存,返回 `cacheOverridden` 元数据 |
452
+ | 缓存用途 | 供 `edit-rem` 的三道防线使用(存在性检查 + 乐观并发检测 + str_replace) |
453
+ | 缓存存储 | daemon 内存中的 LRU 缓存(最大 200 条目) |
454
+ | 缓存清空 | daemon 关闭时自动消失 |
455
+
456
+ **重要**:缓存存储的是 **完整 RemObject**(含 R-F 字段),不受 `--fields` / `--full` 选项影响。字段过滤仅作用于返回给 CLI 的输出。
457
+
458
+ ---
459
+
460
+ ## 退出码
461
+
462
+ | 退出码 | 含义 | 触发条件 |
463
+ |:------:|------|----------|
464
+ | 0 | 成功 | Rem 读取成功 |
465
+ | 1 | 业务错误 | Rem 不存在、Plugin 未连接等 |
466
+ | 2 | daemon 不可达 | daemon 未运行或 WS 连接失败 |
467
+
468
+ ---
469
+
470
+ ## 输出字段说明
471
+
472
+ | 字段 | 类型 | 说明 |
473
+ |------|------|------|
474
+ | `data` | RemObject | Rem 的完整属性对象 |
475
+ | `cacheOverridden` | object | 之前有缓存时附加:`id`=Rem ID、`previousCachedAt`=旧缓存创建时间 |
476
+ | `powerupFiltered` | object | Powerup 过滤统计:`tags`=被过滤的 Tag 数、`children`=被过滤的子 Rem 数 |