remnote-bridge 0.1.11 → 0.1.12
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 +3 -31
- 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 +3 -31
- 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/read-handler.js +4 -3
- package/dist/cli/handlers/tree-parser.js +16 -9
- package/dist/cli/main.js +49 -9
- 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/instructions.js +101 -9
- package/dist/mcp/resources/edit-rem-guide.js +3 -4
- package/dist/mcp/resources/error-reference.js +2 -2
- package/dist/mcp/resources/rem-object-fields.js +3 -3
- package/dist/mcp/tools/infra-tools.js +54 -6
- package/dist/mcp/tools/read-tools.js +9 -2
- 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 +14 -9
- 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 +37 -9
- 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 +76 -21
- package/skills/remnote-bridge/instructions/read-rem.md +10 -10
- package/skills/remnote-bridge/instructions/search.md +73 -14
- package/skills/remnote-bridge/instructions/setup.md +1 -1
|
@@ -1,55 +1,59 @@
|
|
|
1
1
|
import { declareIndexPlugin, type ReactRNPlugin, WidgetLocation } from '@remnote/plugin-sdk';
|
|
2
2
|
import '../style.css';
|
|
3
3
|
import '../index.css';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import { DEFAULT_PLUGIN_VERSION } from '../settings';
|
|
5
|
+
import { MultiConnectionManager } from '../bridge/multi-connection-manager';
|
|
6
6
|
import { createMessageRouter } from '../bridge/message-router';
|
|
7
|
-
// test-scripts 已完成数据收集,不再打包进生产代码
|
|
8
|
-
// 如需重跑,取消注释对应 import 和 onActivate 调用
|
|
9
|
-
// import { runActionTests } from '../test-scripts/test-actions';
|
|
10
|
-
// import { runRichTextBuilderTest } from '../test-scripts/test-richtext-builder';
|
|
11
|
-
// import { runRichTextRemainingTest } from '../test-scripts/test-richtext-remaining';
|
|
12
|
-
// import { runRichTextMatrixTest } from '../test-scripts/test-richtext-matrix';
|
|
13
|
-
// import { runPowerupRenderingTest } from '../test-scripts/test-powerup-rendering';
|
|
14
7
|
|
|
15
|
-
let
|
|
8
|
+
let connectionManager: MultiConnectionManager | null = null;
|
|
16
9
|
// 本地日志缓冲区:避免 onLog 并发读写 plugin.storage 的竞态
|
|
17
10
|
const logBuffer: Array<{ time: number; message: string; level: string }> = [];
|
|
18
11
|
let logFlushPending = false;
|
|
19
12
|
|
|
20
13
|
async function onActivate(plugin: ReactRNPlugin) {
|
|
21
|
-
// 注册 WS Server URL 设置
|
|
22
|
-
await plugin.settings.registerStringSetting({
|
|
23
|
-
id: SETTING_WS_URL,
|
|
24
|
-
title: 'Bridge WS Server URL',
|
|
25
|
-
description: '守护进程 WebSocket Server 地址(默认 ws://127.0.0.1:3002)',
|
|
26
|
-
defaultValue: DEFAULT_WS_URL,
|
|
27
|
-
});
|
|
28
|
-
|
|
29
14
|
// 注册 Bridge Widget(右侧边栏)
|
|
30
15
|
await plugin.app.registerWidget('bridge_widget', WidgetLocation.RightSidebar, {
|
|
31
16
|
dimensions: { height: 'auto', width: '100%' },
|
|
32
17
|
widgetTabIcon: 'https://cdn.jsdelivr.net/npm/lucide-static@0.460.0/icons/globe.svg',
|
|
33
18
|
});
|
|
34
19
|
|
|
35
|
-
//
|
|
36
|
-
|
|
37
|
-
|
|
20
|
+
// 自动发现孪生槽位:Plugin 由 daemon 的 static-server 提供服务,
|
|
21
|
+
// fetch('/api/discovery') 是同源请求,返回 daemon 的 slotIndex 等信息
|
|
22
|
+
let twinSlotIndex = 0;
|
|
23
|
+
let instanceName = '';
|
|
24
|
+
let configPort = 29102;
|
|
25
|
+
try {
|
|
26
|
+
const resp = await fetch('/api/discovery');
|
|
27
|
+
if (resp.ok) {
|
|
28
|
+
const data = await resp.json();
|
|
29
|
+
if (typeof data.slotIndex === 'number') {
|
|
30
|
+
twinSlotIndex = data.slotIndex;
|
|
31
|
+
}
|
|
32
|
+
if (data.instance) {
|
|
33
|
+
instanceName = data.instance;
|
|
34
|
+
}
|
|
35
|
+
if (data.configPort) {
|
|
36
|
+
configPort = data.configPort;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
} catch {
|
|
40
|
+
// discovery 失败(dev 模式 / 非 daemon 环境),使用默认值
|
|
41
|
+
}
|
|
42
|
+
// 存储实例名和配置端口,供 widget 显示
|
|
43
|
+
await plugin.storage.setSession('bridge-instance', instanceName);
|
|
44
|
+
await plugin.storage.setSession('bridge-config-port', configPort);
|
|
38
45
|
|
|
39
|
-
//
|
|
40
|
-
|
|
41
|
-
|
|
46
|
+
// 创建 MultiConnectionManager
|
|
47
|
+
connectionManager = new MultiConnectionManager({
|
|
48
|
+
twinSlotIndex,
|
|
42
49
|
pluginVersion: DEFAULT_PLUGIN_VERSION,
|
|
43
50
|
sdkReady: true,
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
maxReconnectDelay: 30000,
|
|
47
|
-
onStatusChange: (status) => {
|
|
48
|
-
void plugin.storage.setSession('bridge-status', status);
|
|
51
|
+
onSlotsChange: (slots) => {
|
|
52
|
+
void plugin.storage.setSession('bridge-slots', slots);
|
|
49
53
|
},
|
|
50
|
-
onLog: (message, level) => {
|
|
51
|
-
logBuffer.push({ time: Date.now(), message
|
|
52
|
-
if (logBuffer.length >
|
|
54
|
+
onLog: (slotIndex, message, level) => {
|
|
55
|
+
logBuffer.push({ time: Date.now(), message: `[${slotIndex}] ${message}`, level });
|
|
56
|
+
if (logBuffer.length > 50) logBuffer.splice(0, logBuffer.length - 50);
|
|
53
57
|
// 合并写入:避免并发 read-modify-write 竞态
|
|
54
58
|
if (!logFlushPending) {
|
|
55
59
|
logFlushPending = true;
|
|
@@ -61,22 +65,15 @@ async function onActivate(plugin: ReactRNPlugin) {
|
|
|
61
65
|
},
|
|
62
66
|
});
|
|
63
67
|
|
|
64
|
-
// 路由守护进程转发的请求到 services
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
wsClient.connect();
|
|
68
|
+
// 路由守护进程转发的请求到 services 层(所有连接共享同一个 router)
|
|
69
|
+
connectionManager.setMessageHandler(createMessageRouter(plugin));
|
|
68
70
|
|
|
69
|
-
|
|
70
|
-
// runActionTests(plugin).catch((err) => console.error('[ACTION-TEST] 顶层错误:', err));
|
|
71
|
-
// runRichTextBuilderTest(plugin).catch((err) => console.error('[RICHTEXT-BUILDER-TEST] 顶层错误:', err));
|
|
72
|
-
// runRichTextRemainingTest(plugin).catch((err) => console.error('[RICHTEXT-REMAINING-TEST] 顶层错误:', err));
|
|
73
|
-
// runRichTextMatrixTest(plugin).catch((err) => console.error('[RICHTEXT-MATRIX-TEST] 顶层错误:', err));
|
|
74
|
-
// runPowerupRenderingTest(plugin).catch((err) => console.error('[POWERUP-RENDER] 顶层错误:', err));
|
|
71
|
+
connectionManager.start();
|
|
75
72
|
}
|
|
76
73
|
|
|
77
74
|
async function onDeactivate(_: ReactRNPlugin) {
|
|
78
|
-
|
|
79
|
-
|
|
75
|
+
connectionManager?.stop();
|
|
76
|
+
connectionManager = null;
|
|
80
77
|
}
|
|
81
78
|
|
|
82
79
|
declareIndexPlugin(onActivate, onDeactivate);
|
|
@@ -119,6 +119,41 @@ if (isProd) {
|
|
|
119
119
|
'Access-Control-Allow-Origin': '*',
|
|
120
120
|
'Access-Control-Allow-Headers': 'baggage, sentry-trace',
|
|
121
121
|
},
|
|
122
|
+
// 劫持 /api/discovery 和 /manifest.json,与 StaticServer 行为一致
|
|
123
|
+
setupMiddlewares: (middlewares, devServer) => {
|
|
124
|
+
const instance = process.env.DISCOVERY_INSTANCE || 'default';
|
|
125
|
+
|
|
126
|
+
devServer.app.get('/api/discovery', (req, res) => {
|
|
127
|
+
res.json({
|
|
128
|
+
wsPort: parseInt(process.env.DISCOVERY_WS_PORT || '29100', 10),
|
|
129
|
+
configPort: parseInt(process.env.DISCOVERY_CONFIG_PORT || '29102', 10),
|
|
130
|
+
instance,
|
|
131
|
+
slotIndex: parseInt(process.env.DISCOVERY_SLOT_INDEX || '0', 10),
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
// 多实例支持:非 default 实例动态修改 manifest 的 id 和 name,
|
|
136
|
+
// 使 RemNote 能同时加载多个同源 Plugin(RemNote 按 id 去重)
|
|
137
|
+
if (instance !== 'default') {
|
|
138
|
+
devServer.app.get('/manifest.json', (req, res) => {
|
|
139
|
+
const fs = require('fs');
|
|
140
|
+
const manifestPath = path.resolve(__dirname, 'public', 'manifest.json');
|
|
141
|
+
try {
|
|
142
|
+
const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf-8'));
|
|
143
|
+
manifest.id = `${manifest.id}_${instance}`;
|
|
144
|
+
manifest.name = `${manifest.name} (${instance})`;
|
|
145
|
+
// webpack-dev-server 的 headers 配置不覆盖自定义路由,需手动设置 CORS
|
|
146
|
+
res.set('Access-Control-Allow-Origin', '*');
|
|
147
|
+
res.set('Cache-Control', 'no-cache, no-store, must-revalidate');
|
|
148
|
+
res.json(manifest);
|
|
149
|
+
} catch (err) {
|
|
150
|
+
res.status(500).send('manifest parse error');
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return middlewares;
|
|
156
|
+
},
|
|
122
157
|
};
|
|
123
158
|
}
|
|
124
159
|
|
|
@@ -22,6 +22,9 @@ description: "RemNote 知识库操作指南。通过 remnote-bridge 命令行工
|
|
|
22
22
|
| read-globe | `instructions/read-globe.md` |
|
|
23
23
|
| read-context | `instructions/read-context.md` |
|
|
24
24
|
| search | `instructions/search.md` |
|
|
25
|
+
| addon | `instructions/addon.md` |
|
|
26
|
+
| clean | `instructions/clean.md` |
|
|
27
|
+
| install-skill | `instructions/install-skill.md` |
|
|
25
28
|
| 全局概览 | `instructions/overall.md` |
|
|
26
29
|
|
|
27
30
|
---
|
|
@@ -99,7 +102,7 @@ Portal 的编辑同步意味着修改一处会影响另一处。Portal 引用的
|
|
|
99
102
|
| 删除 Portal | `edit-tree` | 从大纲中移除 Portal 行(与删除普通行相同) |
|
|
100
103
|
| 修改引用列表(增删引用的 Rem) | `edit-rem` | str_replace 简化 JSON 中的 `portalDirectlyIncludedRem` 数组 |
|
|
101
104
|
| 移动 Portal(换父节点/位置) | `edit-tree` | 与移动普通行相同 |
|
|
102
|
-
| 读取 Portal | `read-rem` | 自动输出
|
|
105
|
+
| 读取 Portal | `read-rem` | 自动输出 8 字段简化 JSON |
|
|
103
106
|
|
|
104
107
|
### RichText 格式
|
|
105
108
|
|
|
@@ -255,7 +258,7 @@ Rem 的属性(文本、类型、格式、标签) → edit-rem (前置
|
|
|
255
258
|
1. 打开 RemNote 桌面端或网页端
|
|
256
259
|
2. 点击左侧边栏底部的插件图标(拼图形状)
|
|
257
260
|
3. 点击「开发你的插件」(Develop Your Plugin)
|
|
258
|
-
4. 在输入框中填入
|
|
261
|
+
4. 在输入框中填入 connect 输出的 Plugin 服务地址(如 `http://localhost:29101`)
|
|
259
262
|
5. 等待插件加载完成
|
|
260
263
|
|
|
261
264
|
**非首次使用**(之前已加载过此插件):
|
|
@@ -273,7 +276,7 @@ Rem 的属性(文本、类型、格式、标签) → edit-rem (前置
|
|
|
273
276
|
|
|
274
277
|
setup 会弹出 Chrome 窗口,用户需要完成两件事:
|
|
275
278
|
1. **登录 RemNote**
|
|
276
|
-
2. **配置 dev plugin**:插件图标 → 开发你的插件 → 填入 `http://localhost:
|
|
279
|
+
2. **配置 dev plugin**:插件图标 → 开发你的插件 → 填入 connect 输出的 Plugin 服务地址(如 `http://localhost:29101`)
|
|
277
280
|
|
|
278
281
|
完成后**彻底退出 Chrome**(macOS 必须 Cmd+Q,仅关窗口不够)。
|
|
279
282
|
|
|
@@ -283,7 +286,7 @@ setup 会弹出 Chrome 窗口,用户需要完成两件事:
|
|
|
283
286
|
2. 立即告知用户:
|
|
284
287
|
"已打开 Chrome 浏览器。请完成以下操作:
|
|
285
288
|
1. 登录 RemNote
|
|
286
|
-
2. 在 RemNote 中配置开发插件:点击左下角插件图标 → 开发你的插件 → 输入
|
|
289
|
+
2. 在 RemNote 中配置开发插件:点击左下角插件图标 → 开发你的插件 → 输入 connect 输出的 Plugin 服务地址
|
|
287
290
|
3. 完成后彻底退出 Chrome(macOS 请按 Cmd+Q)"
|
|
288
291
|
3. 等待 setup 返回(阻塞,最长 10 分钟)
|
|
289
292
|
4. 成功 → 进入下一步 connect --headless
|
|
@@ -575,7 +578,7 @@ tags, sources, positionAmongstSiblings, portalDirectlyIncludedRem
|
|
|
575
578
|
| `type` | 不可设为 `portal`(只能通过 SDK `createPortal()` 创建) |
|
|
576
579
|
| `parent` + `positionAmongstSiblings` | 共享同一 SDK 调用 `setParent(parentId, position)`,**应在同一次 str_replace 中同时修改** |
|
|
577
580
|
| `tags` / `sources` | **Diff 机制**:对比当前 vs 目标数组,逐项 add/remove。必须列出完整目标数组,缺少的会被删除 |
|
|
578
|
-
| `portalDirectlyIncludedRem` | Portal 专用可写。**Diff 机制**:对比当前 vs 目标数组,逐项 addToPortal/removeFromPortal。仅 type=portal 时可修改。edit-rem 对 Portal 使用
|
|
581
|
+
| `portalDirectlyIncludedRem` | Portal 专用可写。**Diff 机制**:对比当前 vs 目标数组,逐项 addToPortal/removeFromPortal。仅 type=portal 时可修改。edit-rem 对 Portal 使用 8 字段简化 JSON |
|
|
579
582
|
|
|
580
583
|
### 常用只读字段(修改只产生警告,不生效)
|
|
581
584
|
|
|
@@ -588,8 +591,8 @@ aliases, descendants, siblingRem, isTable, portalType, propertyType
|
|
|
588
591
|
|
|
589
592
|
| 模式 | 字段数 | 用法 |
|
|
590
593
|
|:-----|:-------|:-----|
|
|
591
|
-
| 默认 |
|
|
592
|
-
| Portal 简化 |
|
|
594
|
+
| 默认 | 33(RW + R) | 常用场景 |
|
|
595
|
+
| Portal 简化 | 8(id, type, portalType, portalDirectlyIncludedRem, parent, positionAmongstSiblings, createdAt, updatedAt) | type=portal 时自动切换,`--full` 和 `--fields` 可覆盖 |
|
|
593
596
|
| `--full` | 51(含低频 R-F) | 需要 Powerup 标识、时间戳等 |
|
|
594
597
|
| `--fields` | 自选 + id | 精确获取特定字段 |
|
|
595
598
|
|
|
@@ -621,6 +624,8 @@ aliases, descendants, siblingRem, isTable, portalType, propertyType
|
|
|
621
624
|
|
|
622
625
|
## 10. 配置
|
|
623
626
|
|
|
624
|
-
|
|
627
|
+
配置文件:`~/.remnote-bridge/config.json`(全局目录,所有实例共享)
|
|
625
628
|
|
|
626
|
-
|
|
629
|
+
端口由槽位自动分配(槽位 0: 29100/29101/29102,槽位 1: 29110/29111/29112,以此类推),最多 4 个并发实例。
|
|
630
|
+
|
|
631
|
+
关键默认值:超时 30 分钟、maxNodes 200、maxSiblings 20、readTreeDepth 3、readGlobeDepth -1(无限)、缓存上限 200 条。
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# addon
|
|
2
|
+
|
|
3
|
+
> 管理增强项目(addon):查看状态、安装、卸载。
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 功能
|
|
8
|
+
|
|
9
|
+
`addon` 命令组管理 remnote-bridge 的增强项目(如 `remnote-rag` 语义搜索)。增强项目是独立安装的可选组件,扩展核心功能。
|
|
10
|
+
|
|
11
|
+
三个子命令:
|
|
12
|
+
|
|
13
|
+
| 子命令 | 功能 |
|
|
14
|
+
|:-------|:-----|
|
|
15
|
+
| `addon list` | 查看所有可用增强项目的状态 |
|
|
16
|
+
| `addon install <name>` | 安装并启用指定增强项目 |
|
|
17
|
+
| `addon uninstall <name>` | 卸载指定增强项目 |
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## 用法
|
|
22
|
+
|
|
23
|
+
### 人类模式
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
# 查看所有增强项目
|
|
27
|
+
remnote-bridge addon list
|
|
28
|
+
|
|
29
|
+
# 安装增强项目
|
|
30
|
+
remnote-bridge addon install remnote-rag
|
|
31
|
+
|
|
32
|
+
# 卸载增强项目
|
|
33
|
+
remnote-bridge addon uninstall remnote-rag
|
|
34
|
+
|
|
35
|
+
# 卸载并清理数据目录
|
|
36
|
+
remnote-bridge addon uninstall remnote-rag --purge
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### JSON 模式
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
remnote-bridge --json addon list
|
|
43
|
+
remnote-bridge --json addon install remnote-rag
|
|
44
|
+
remnote-bridge --json addon uninstall remnote-rag
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## JSON 输出
|
|
50
|
+
|
|
51
|
+
### addon list
|
|
52
|
+
|
|
53
|
+
```json
|
|
54
|
+
{
|
|
55
|
+
"ok": true,
|
|
56
|
+
"command": "addon-list",
|
|
57
|
+
"addons": [
|
|
58
|
+
{
|
|
59
|
+
"name": "remnote-rag",
|
|
60
|
+
"enabled": true,
|
|
61
|
+
"installed": true,
|
|
62
|
+
"settingsValid": true,
|
|
63
|
+
"missingSettings": [],
|
|
64
|
+
"description": "语义搜索增强"
|
|
65
|
+
}
|
|
66
|
+
]
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### addon install(成功)
|
|
71
|
+
|
|
72
|
+
```json
|
|
73
|
+
{
|
|
74
|
+
"ok": true,
|
|
75
|
+
"command": "addon-install",
|
|
76
|
+
"name": "remnote-rag",
|
|
77
|
+
"action": "installed"
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### addon install(已安装)
|
|
82
|
+
|
|
83
|
+
```json
|
|
84
|
+
{
|
|
85
|
+
"ok": true,
|
|
86
|
+
"command": "addon-install",
|
|
87
|
+
"name": "remnote-rag",
|
|
88
|
+
"action": "already-installed"
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### addon uninstall
|
|
93
|
+
|
|
94
|
+
```json
|
|
95
|
+
{
|
|
96
|
+
"ok": true,
|
|
97
|
+
"command": "addon-uninstall",
|
|
98
|
+
"name": "remnote-rag",
|
|
99
|
+
"purged": false
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### 失败
|
|
104
|
+
|
|
105
|
+
```json
|
|
106
|
+
{
|
|
107
|
+
"ok": false,
|
|
108
|
+
"command": "addon-install",
|
|
109
|
+
"name": "unknown-addon",
|
|
110
|
+
"error": "未知的增强项目: unknown-addon。可用项目: remnote-rag"
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## 退出码
|
|
117
|
+
|
|
118
|
+
| 退出码 | 含义 |
|
|
119
|
+
|:-------|:-----|
|
|
120
|
+
| 0 | 操作成功 |
|
|
121
|
+
| 1 | 操作失败(未知名称、安装/卸载错误等) |
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## 幂等性
|
|
126
|
+
|
|
127
|
+
- `addon install`:已安装时返回 `action: "already-installed"`,自动标记为启用
|
|
128
|
+
- `addon uninstall`:已卸载时安全返回
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## 配置依赖
|
|
133
|
+
|
|
134
|
+
增强项目的启用/禁用状态保存在全局配置 `~/.remnote-bridge/config.json` 中。每个 addon 的独立配置存储在 `~/.remnote-bridge/addons/<name>/config.json` 中。安装后需要在配置页面或配置文件中填写必需的配置项(如 API Key)。
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# clean
|
|
2
|
+
|
|
3
|
+
> 清理所有 daemon 进程、PID 文件、日志、注册表和 addon 数据。
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 功能
|
|
8
|
+
|
|
9
|
+
`clean` 执行全面清理,适用于系统状态异常或需要彻底重置的场景。
|
|
10
|
+
|
|
11
|
+
按顺序执行以下清理步骤:
|
|
12
|
+
|
|
13
|
+
1. **停止所有运行中的 daemon**(遍历注册表,SIGTERM → 5 秒后 SIGKILL)
|
|
14
|
+
2. **清理实例文件**(`~/.remnote-bridge/instances/` 下的 PID 和日志文件)
|
|
15
|
+
3. **清理注册表**(`~/.remnote-bridge/registry.json`)
|
|
16
|
+
4. **清理旧版项目根文件**(`.remnote-bridge.pid`、`.remnote-bridge.log`、`.remnote-bridge.json`,向后兼容)
|
|
17
|
+
5. **清理已安装的 Skill**(`~/.claude/skills/remnote-bridge/`)
|
|
18
|
+
6. **清理 addon 数据目录**(如 remnote-rag 的索引数据)
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## 用法
|
|
23
|
+
|
|
24
|
+
### 人类模式
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
remnote-bridge clean
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
输出示例:
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
已删除: /Users/xxx/.remnote-bridge/instances/0.pid
|
|
34
|
+
已删除: /Users/xxx/.remnote-bridge/instances/0.log
|
|
35
|
+
已删除: /Users/xxx/.remnote-bridge/registry.json
|
|
36
|
+
|
|
37
|
+
清理完成,共删除 3 项
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### JSON 模式
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
remnote-bridge --json clean
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## JSON 输出
|
|
49
|
+
|
|
50
|
+
### 清理成功
|
|
51
|
+
|
|
52
|
+
```json
|
|
53
|
+
{
|
|
54
|
+
"ok": true,
|
|
55
|
+
"command": "clean",
|
|
56
|
+
"removed": [
|
|
57
|
+
"/Users/xxx/.remnote-bridge/instances/0.pid",
|
|
58
|
+
"/Users/xxx/.remnote-bridge/instances/0.log",
|
|
59
|
+
"/Users/xxx/.remnote-bridge/registry.json"
|
|
60
|
+
]
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### 部分失败
|
|
65
|
+
|
|
66
|
+
```json
|
|
67
|
+
{
|
|
68
|
+
"ok": false,
|
|
69
|
+
"command": "clean",
|
|
70
|
+
"removed": ["/Users/xxx/.remnote-bridge/instances/0.pid"],
|
|
71
|
+
"errors": ["删除失败: /Users/xxx/.remnote-bridge/instances/0.log — EPERM"]
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### 无需清理
|
|
76
|
+
|
|
77
|
+
```json
|
|
78
|
+
{
|
|
79
|
+
"ok": true,
|
|
80
|
+
"command": "clean",
|
|
81
|
+
"removed": []
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## 退出码
|
|
88
|
+
|
|
89
|
+
| 退出码 | 含义 |
|
|
90
|
+
|:-------|:-----|
|
|
91
|
+
| 0 | 清理完成(包括无需清理的情况) |
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## 适用场景
|
|
96
|
+
|
|
97
|
+
| 场景 | 说明 |
|
|
98
|
+
|:-----|:-----|
|
|
99
|
+
| daemon 进程残留 | `disconnect` 无法正常停止时 |
|
|
100
|
+
| 端口被占用 | 多次启动失败后的端口残留 |
|
|
101
|
+
| 注册表损坏 | 注册表文件不一致时重置 |
|
|
102
|
+
| 完整重装 | 清除所有状态从零开始 |
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## AI Agent 注意事项
|
|
107
|
+
|
|
108
|
+
- `clean` 是**破坏性操作**——会停止所有 daemon、清空所有缓存和注册表
|
|
109
|
+
- 执行 `clean` 后需要重新 `connect` 才能继续操作
|
|
110
|
+
- 通常只在排查问题或重置环境时使用,正常流程不需要
|