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
|
@@ -3,26 +3,48 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { z } from 'zod';
|
|
5
5
|
import { callCli } from '../daemon-client.js';
|
|
6
|
+
import { formatFrontmatter, formatDataJson } from '../format.js';
|
|
6
7
|
export function registerReadTools(server) {
|
|
7
8
|
// -------------------------------------------------------------------------
|
|
8
9
|
// search
|
|
9
10
|
// -------------------------------------------------------------------------
|
|
10
11
|
server.addTool({
|
|
11
12
|
name: 'search',
|
|
12
|
-
description: '在 RemNote
|
|
13
|
+
description: '在 RemNote 知识库中搜索 Rem,返回匹配结果列表。' +
|
|
14
|
+
'\\n\\n搜索来源(配置驱动):在 ~/.remnote-bridge/config.json 中启用 addons.remnote-rag(enabled:true)后,优先使用 RAG 语义向量搜索(source:"rag",中文支持好);未启用、未安装或调用失败时自动降级到 SDK 全文搜索(source:"sdk")。' +
|
|
15
|
+
'\\n\\n适用场景:知道关键词但不知道位置时使用。不适合按结构浏览(用 read_globe)。' +
|
|
16
|
+
'\\n不适用场景:搜索结果不写入缓存,不能作为 edit_rem / edit_tree 的前置步骤。需要详情请拿 remId 调用 read_rem 或 read_tree。' +
|
|
17
|
+
'\\n\\n前置条件:daemon 已连接(先执行 connect)。' +
|
|
18
|
+
'\\n\\n参数说明:' +
|
|
19
|
+
'\\n- query(必需):搜索关键词,不能为空' +
|
|
20
|
+
'\\n- limit(可选,默认 20):结果数量上限' +
|
|
21
|
+
'\\n\\n输出格式:Data JSON。核心字段:' +
|
|
22
|
+
'\\n- results 数组:每项含 remId、text、isDocument' +
|
|
23
|
+
'\\n- totalFound:返回的结果数量' +
|
|
24
|
+
'\\n- source:"rag" 或 "sdk",标识搜索来源' +
|
|
25
|
+
'\\nRAG 模式额外返回:backText、ancestorPath、type、tags、score(语义相关性 0-1)' +
|
|
26
|
+
'\\n\\n关键约束与常见问题:' +
|
|
27
|
+
'\\n- SDK 模式对中文/日文/韩文等无空格语言搜索效果差(基于空格分词)。应对策略:(1) 用最具区分度的单个字搜索再筛选;(2) 尝试英文/拼音关键词;(3) 搜索失败时改用 read_globe + read_tree 按结构浏览定位' +
|
|
28
|
+
'\\n- RAG 模式中文支持好,但需先安装并配置 remnote-rag addon' +
|
|
29
|
+
'\\n- 搜索结果的 text 是 Markdown 格式单行文本(多行换行符已替换为空格)' +
|
|
30
|
+
'\\n\\n典型工作流:search 定位 → read_rem 获取详情 / read_tree 展开子树。' +
|
|
31
|
+
'\\n关联工具:read_rem(单 Rem 详情)、read_tree(子树大纲)、read_globe(知识库结构浏览)',
|
|
13
32
|
parameters: z.object({
|
|
14
33
|
query: z.string().describe('搜索关键词'),
|
|
15
|
-
|
|
34
|
+
limit: z
|
|
16
35
|
.number()
|
|
17
36
|
.optional()
|
|
18
37
|
.describe('结果数量上限,默认 20'),
|
|
19
38
|
}),
|
|
20
39
|
execute: async (args) => {
|
|
21
40
|
const payload = { query: args.query };
|
|
22
|
-
if (args.
|
|
23
|
-
payload.numResults = args.
|
|
41
|
+
if (args.limit !== undefined)
|
|
42
|
+
payload.numResults = args.limit;
|
|
24
43
|
const response = await callCli('search', payload);
|
|
25
|
-
|
|
44
|
+
if (!response.data) {
|
|
45
|
+
return 'search 返回了空结果,请检查 query 参数或 daemon 状态。';
|
|
46
|
+
}
|
|
47
|
+
return formatDataJson(response);
|
|
26
48
|
},
|
|
27
49
|
});
|
|
28
50
|
// -------------------------------------------------------------------------
|
|
@@ -30,7 +52,26 @@ export function registerReadTools(server) {
|
|
|
30
52
|
// -------------------------------------------------------------------------
|
|
31
53
|
server.addTool({
|
|
32
54
|
name: 'read_rem',
|
|
33
|
-
description: '通过 Rem ID 读取单个 Rem 的完整属性,返回标准化的 RemObject(JSON
|
|
55
|
+
description: '通过 Rem ID 读取单个 Rem 的完整属性,返回标准化的 RemObject(JSON 格式)。' +
|
|
56
|
+
'\\n\\n适用场景:查看 Rem 的详细属性(文本、类型、标签、父子关系、练习方向等);作为 edit_rem 的强制前置步骤——必须先 read_rem 建立缓存才能 edit_rem。' +
|
|
57
|
+
'\\n不适用场景:查看子树结构(用 read_tree);按结构浏览知识库(用 read_globe)。' +
|
|
58
|
+
'\\n\\n前置条件:daemon 已连接;需要有效的 remId(可通过 search 获取)。' +
|
|
59
|
+
'\\n\\n参数说明:' +
|
|
60
|
+
'\\n- remId(必需):目标 Rem 的 ID' +
|
|
61
|
+
'\\n- fields(可选):字符串数组,只返回指定字段子集(始终包含 id)' +
|
|
62
|
+
'\\n- full(可选,默认 false):返回全部 51 个字段(含低频 R-F 字段,如 children、isPowerup 系列、deepRemsBeingReferenced 等)' +
|
|
63
|
+
'\\n- includePowerup(可选,默认 false):包含 Powerup 系统数据(默认过滤噪音)' +
|
|
64
|
+
'\\n\\n输出格式:Data JSON,核心为 RemObject 对象。' +
|
|
65
|
+
'\\n- 默认 33 个常用字段(RW + R),full=true 时 51 个,Portal 类型自动简化为 8 个关键字段' +
|
|
66
|
+
'\\n- 关键字段:id, text, backText, type(concept/descriptor/default/portal), parent, isDocument, tags, fontSize(H1/H2/H3/null), highlightColor(Red/Orange/Yellow/Green/Blue/Purple/Gray/Brown/Pink/null), practiceDirection(forward/backward/both/none), isTodo, todoStatus(Finished/Unfinished/null)' +
|
|
67
|
+
'\\n- children 字段属于 R-F 层级,默认不输出,需 full=true 或 fields 指定' +
|
|
68
|
+
'\\n- text/backText 是 RichText JSON 数组,元素为纯字符串或带 i 字段的对象(i:"m" 格式化文本, i:"q" Rem 引用, i:"x" LaTeX, i:"i" 图片, i:"a" 音视频)' +
|
|
69
|
+
'\\n- 可能附加 cacheOverridden(覆盖旧缓存时)和 powerupFiltered(过滤统计)元数据' +
|
|
70
|
+
'\\n\\n关键约束:' +
|
|
71
|
+
'\\n- 结果自动写入缓存供 edit_rem 使用。缓存存储完整 RemObject,不受 fields/full 选项影响' +
|
|
72
|
+
'\\n- 默认过滤 Powerup 噪音(系统 Tag 和隐藏子 Rem),includePowerup=true 可恢复' +
|
|
73
|
+
'\\n\\n典型工作流:search 定位 remId → read_rem 获取详情并建立缓存 → edit_rem 编辑属性。' +
|
|
74
|
+
'\\n关联工具:search(定位 remId)、edit_rem(编辑属性,需先 read_rem)、read_tree(查看子树大纲)',
|
|
34
75
|
parameters: z.object({
|
|
35
76
|
remId: z.string().describe('目标 Rem 的 ID'),
|
|
36
77
|
fields: z
|
|
@@ -55,7 +96,10 @@ export function registerReadTools(server) {
|
|
|
55
96
|
if (args.includePowerup !== undefined)
|
|
56
97
|
payload.includePowerup = args.includePowerup;
|
|
57
98
|
const response = await callCli('read-rem', payload);
|
|
58
|
-
|
|
99
|
+
if (!response.data) {
|
|
100
|
+
return `read_rem 返回了空的 data,remId: ${args.remId}。请检查该 Rem 是否存在。`;
|
|
101
|
+
}
|
|
102
|
+
return formatDataJson(response);
|
|
59
103
|
},
|
|
60
104
|
});
|
|
61
105
|
// -------------------------------------------------------------------------
|
|
@@ -63,7 +107,30 @@ export function registerReadTools(server) {
|
|
|
63
107
|
// -------------------------------------------------------------------------
|
|
64
108
|
server.addTool({
|
|
65
109
|
name: 'read_tree',
|
|
66
|
-
description: '将指定 Rem 的子树序列化为 Markdown
|
|
110
|
+
description: '将指定 Rem 的子树序列化为 Markdown 大纲,支持深度/节点预算控制和祖先路径追溯。' +
|
|
111
|
+
'\\n\\n适用场景:查看 Rem 的子树结构和内容;作为 edit_tree 的强制前置步骤——必须先 read_tree 建立缓存才能 edit_tree。' +
|
|
112
|
+
'\\n不适用场景:查看单个 Rem 属性(用 read_rem);全局鸟瞰知识库(用 read_globe)。' +
|
|
113
|
+
'\\n\\n前置条件:daemon 已连接;需要有效的 remId(可通过 search 获取)。' +
|
|
114
|
+
'\\n\\n参数说明:' +
|
|
115
|
+
'\\n- remId(必需):子树根节点的 Rem ID' +
|
|
116
|
+
'\\n- depth(可选,默认 3,-1 无限):递归展开深度,超限节点标记 children:N 不展开' +
|
|
117
|
+
'\\n- maxNodes(可选,默认 200):全局节点总预算,耗尽后剩余节点生成省略占位符' +
|
|
118
|
+
'\\n- maxSiblings(可选,默认 20):单个父节点下最大可见子节点数,超限时保留前 70% + 后 30%,中间省略' +
|
|
119
|
+
'\\n- ancestorLevels(可选,默认 0,上限 10):向上追溯祖先层数,提供面包屑上下文' +
|
|
120
|
+
'\\n- includePowerup(可选,默认 false):包含 Powerup 系统数据(默认过滤噪音)' +
|
|
121
|
+
'\\n\\n输出格式:Frontmatter + Body。Frontmatter 含 rootId、depth、nodeCount 等元数据;Body 为 Markdown 大纲文本。' +
|
|
122
|
+
'\\n大纲每行格式:{缩进}{Markdown前缀}{内容}{箭头}{backText} <!-- {remId} {元数据标记} -->' +
|
|
123
|
+
'\\n- 缩进:每级 2 空格' +
|
|
124
|
+
'\\n- Markdown 前缀:# ## ### (标题), - [ ] - [x] (待办), ` (代码)' +
|
|
125
|
+
'\\n- 箭头编码 practiceDirection:→←↔(单行闪卡,text→backText);↓↑↕(多行闪卡,答案在子节点)' +
|
|
126
|
+
'\\n- 元数据标记:type:concept/descriptor/portal, doc, children:N, tag:Name(id), role:card-item, top, refs:id1,id2(Portal引用)' +
|
|
127
|
+
'\\n- 省略占位符:<!--...elided N siblings (parent:id range:x-y total:z)-->(精确)或 >=N nodes(预算耗尽)' +
|
|
128
|
+
'\\n\\n关键约束:' +
|
|
129
|
+
'\\n- 结果自动写入缓存供 edit_tree 使用。edit_tree 的 oldStr 必须精确匹配此大纲中的文本' +
|
|
130
|
+
'\\n- 默认过滤 Powerup 噪音,includePowerup=true 可恢复' +
|
|
131
|
+
'\\n- Portal 感知:Portal 类型 Rem 标注 type:portal 和 refs:id1,id2(引用的 Rem ID)' +
|
|
132
|
+
'\\n\\n典型工作流:search 定位 remId → read_tree 展开子树并建立缓存 → edit_tree 结构编辑。' +
|
|
133
|
+
'\\n关联工具:search(定位 remId)、edit_tree(结构编辑,需先 read_tree)、read_rem(单 Rem JSON 详情)、read_globe(全局鸟瞰)',
|
|
67
134
|
parameters: z.object({
|
|
68
135
|
remId: z.string().describe('根 Rem 的 ID'),
|
|
69
136
|
depth: z
|
|
@@ -100,12 +167,18 @@ export function registerReadTools(server) {
|
|
|
100
167
|
if (args.includePowerup !== undefined)
|
|
101
168
|
payload.includePowerup = args.includePowerup;
|
|
102
169
|
const response = await callCli('read-tree', payload);
|
|
103
|
-
// read-tree 返回的大纲在 response.data.outline 中
|
|
104
170
|
const data = response.data;
|
|
105
|
-
if (data?.outline
|
|
106
|
-
return
|
|
171
|
+
if (!data?.outline || typeof data.outline !== 'string') {
|
|
172
|
+
return `read_tree 返回了空的大纲,remId: ${args.remId}。请检查该 Rem 是否存在或是否有子节点。`;
|
|
107
173
|
}
|
|
108
|
-
return
|
|
174
|
+
return formatFrontmatter({
|
|
175
|
+
rootId: data.rootId,
|
|
176
|
+
depth: data.depth,
|
|
177
|
+
nodeCount: data.nodeCount,
|
|
178
|
+
ancestors: response.ancestors,
|
|
179
|
+
cacheOverridden: response.cacheOverridden,
|
|
180
|
+
powerupFiltered: response.powerupFiltered,
|
|
181
|
+
}, data.outline);
|
|
109
182
|
},
|
|
110
183
|
});
|
|
111
184
|
// -------------------------------------------------------------------------
|
|
@@ -113,7 +186,24 @@ export function registerReadTools(server) {
|
|
|
113
186
|
// -------------------------------------------------------------------------
|
|
114
187
|
server.addTool({
|
|
115
188
|
name: 'read_globe',
|
|
116
|
-
description: '读取知识库全局 Document
|
|
189
|
+
description: '读取知识库全局 Document 层级鸟瞰图,生成 Markdown 大纲。无需指定 remId。' +
|
|
190
|
+
'\\n\\n适用场景:首次探索知识库,了解有哪些文档及其层级关系;用户说"有哪些文档"、"知识库里有什么"时使用。' +
|
|
191
|
+
'\\n不适用场景:搜索特定内容(用 search);查看某 Rem 内部子节点(用 read_tree);获取单 Rem 详情(用 read_rem)。' +
|
|
192
|
+
'\\n\\n前置条件:daemon 已连接。' +
|
|
193
|
+
'\\n\\n参数说明:' +
|
|
194
|
+
'\\n- depth(可选,默认 -1 无限):Document 嵌套展开深度' +
|
|
195
|
+
'\\n- maxNodes(可选,默认 200):全局节点上限' +
|
|
196
|
+
'\\n- maxSiblings(可选,默认 20):每个父节点下展示的 Document 子节点上限,超限时保留前 70% + 后 30%,中间省略' +
|
|
197
|
+
'\\n\\n输出格式:Frontmatter + Body。Frontmatter 含 nodeCount;Body 为 Markdown 大纲,格式同 read_tree。' +
|
|
198
|
+
'\\n- 仅递归展开 Document 类型节点,非 Document 子节点不展开,仅标注 children:N' +
|
|
199
|
+
'\\n- 不包含 backText、practiceDirection 等详细信息——仅提供文档层级结构概览' +
|
|
200
|
+
'\\n- Powerup 节点硬编码过滤(无选项关闭)' +
|
|
201
|
+
'\\n- Portal 感知:Portal 类型标注 type:portal 和 refs:id1,id2' +
|
|
202
|
+
'\\n\\n关键约束:' +
|
|
203
|
+
'\\n- 不缓存结果,每次调用获取最新数据' +
|
|
204
|
+
'\\n- nodeCount 仅统计 Document 节点,不含非 Document 子 Rem' +
|
|
205
|
+
'\\n\\n典型工作流:read_globe 获取宏观结构 → search 搜索特定内容 / read_tree 深入某文档子树。' +
|
|
206
|
+
'\\n关联工具:search(关键词搜索)、read_tree(子树详细大纲)、read_rem(单 Rem 属性)',
|
|
117
207
|
parameters: z.object({
|
|
118
208
|
depth: z
|
|
119
209
|
.number()
|
|
@@ -138,10 +228,10 @@ export function registerReadTools(server) {
|
|
|
138
228
|
payload.maxSiblings = args.maxSiblings;
|
|
139
229
|
const response = await callCli('read-globe', payload);
|
|
140
230
|
const data = response.data;
|
|
141
|
-
if (data?.outline
|
|
142
|
-
return
|
|
231
|
+
if (!data?.outline || typeof data.outline !== 'string') {
|
|
232
|
+
return 'read_globe 返回了空的大纲。请检查知识库中是否有 Document。';
|
|
143
233
|
}
|
|
144
|
-
return
|
|
234
|
+
return formatFrontmatter({ nodeCount: data.nodeCount }, data.outline);
|
|
145
235
|
},
|
|
146
236
|
});
|
|
147
237
|
// -------------------------------------------------------------------------
|
|
@@ -149,7 +239,29 @@ export function registerReadTools(server) {
|
|
|
149
239
|
// -------------------------------------------------------------------------
|
|
150
240
|
server.addTool({
|
|
151
241
|
name: 'read_context',
|
|
152
|
-
description: '读取用户在 RemNote 中的当前上下文视图,生成带面包屑路径的 Markdown
|
|
242
|
+
description: '读取用户在 RemNote 中的当前上下文视图,生成带面包屑路径的 Markdown 大纲。无需指定 remId。' +
|
|
243
|
+
'\\n\\n重要:用户正在看的页面对 AI 不可见。当用户说"这个"、"当前页面"、"这里",或描述与已知信息对不上时,必须主动调用 read_context 对齐信息。' +
|
|
244
|
+
'\\n\\n适用场景:了解用户当前焦点位置或打开的页面;用户说"我现在在看什么"、"当前页面是什么"时使用;需要上下文才能理解用户指代时使用。' +
|
|
245
|
+
'\\n不适用场景:查看特定 Rem(已知 remId 用 read_tree);搜索内容(用 search)。' +
|
|
246
|
+
'\\n\\n前置条件:daemon 已连接。focus 模式需用户在 RemNote 中有焦点 Rem(光标在某个 Rem 上)或指定 focusRemId;page 模式需有打开的页面。' +
|
|
247
|
+
'\\n\\n参数说明:' +
|
|
248
|
+
'\\n- mode(可选,默认 "focus"):视图模式' +
|
|
249
|
+
'\\n - focus:以焦点 Rem 为中心的鱼眼视图。焦点完全展开(depth=3),siblings 浅层预览(depth=1,前3个children可见),叔伯不展开。焦点行以 * 前缀标记' +
|
|
250
|
+
'\\n - page:以当前打开的页面为根,均匀展开子树' +
|
|
251
|
+
'\\n- focusRemId(可选,仅 focus 模式):指定任意 Rem 作为鱼眼中心,此时不依赖用户实际焦点。page 模式下传入会报错' +
|
|
252
|
+
'\\n- ancestorLevels(可选,默认 2,仅 focus 模式生效):从焦点向上追溯几层祖先作为上下文起点' +
|
|
253
|
+
'\\n- depth(可选,默认 3,仅 page 模式生效):向下展开深度(-1 无限)' +
|
|
254
|
+
'\\n- maxNodes(可选,默认 200):全局节点上限' +
|
|
255
|
+
'\\n- maxSiblings(可选,默认 20):单层子节点上限,超限时前 70% + 后 30%,中间省略' +
|
|
256
|
+
'\\n\\n输出格式:Frontmatter + Body。Frontmatter 含 mode、nodeCount、breadcrumb(从根到当前位置的路径数组);Body 为 Markdown 大纲。' +
|
|
257
|
+
'\\n- focus 模式大纲头部:<!-- path: ... --> + <!-- focus: Name (id) -->,焦点 Rem 以 * 前缀标记' +
|
|
258
|
+
'\\n- page 模式大纲头部:<!-- page: Name --> + <!-- path: ... -->' +
|
|
259
|
+
'\\n- Powerup 硬编码过滤(无选项关闭);Portal 感知标注 type:portal 和 refs' +
|
|
260
|
+
'\\n\\n关键约束:' +
|
|
261
|
+
'\\n- 不缓存结果,每次调用获取最新数据' +
|
|
262
|
+
'\\n- 输出使用最小序列化,不含 backText、practiceDirection 等详细信息——需要详情用 read_tree 或 read_rem' +
|
|
263
|
+
'\\n\\n典型工作流:read_context 了解用户当前位置 → read_tree / read_rem 深入查看具体内容。' +
|
|
264
|
+
'\\n关联工具:read_tree(指定 Rem 子树详情)、read_rem(单 Rem 属性)、search(关键词搜索)',
|
|
153
265
|
parameters: z.object({
|
|
154
266
|
mode: z
|
|
155
267
|
.enum(['focus', 'page'])
|
|
@@ -192,10 +304,14 @@ export function registerReadTools(server) {
|
|
|
192
304
|
payload.focusRemId = args.focusRemId;
|
|
193
305
|
const response = await callCli('read-context', payload);
|
|
194
306
|
const data = response.data;
|
|
195
|
-
if (data?.outline
|
|
196
|
-
return
|
|
307
|
+
if (!data?.outline || typeof data.outline !== 'string') {
|
|
308
|
+
return 'read_context 返回了空的大纲。请检查用户是否有焦点 Rem 或已打开的页面。';
|
|
197
309
|
}
|
|
198
|
-
return
|
|
310
|
+
return formatFrontmatter({
|
|
311
|
+
mode: data.mode,
|
|
312
|
+
nodeCount: data.nodeCount,
|
|
313
|
+
breadcrumb: data.breadcrumb,
|
|
314
|
+
}, data.outline);
|
|
199
315
|
},
|
|
200
316
|
});
|
|
201
317
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "remnote-bridge",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.13",
|
|
4
4
|
"description": "RemNote 自动化桥接工具集:CLI + MCP Server + Plugin",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"commander": "^12.1.0",
|
|
39
39
|
"puppeteer-core": "^24.0.0",
|
|
40
40
|
"ws": "^8.16.0",
|
|
41
|
-
"fastmcp": "
|
|
41
|
+
"fastmcp": "^3.34.0",
|
|
42
42
|
"zod": "^3.23.0"
|
|
43
43
|
},
|
|
44
44
|
"license": "MIT",
|