@hpplay-lebo/cluster-hub 3.3.1 → 3.4.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.
- package/docs/GUIDE.md +9 -5
- package/package.json +1 -1
- package/src/feishu-tools.ts +56 -12
package/docs/GUIDE.md
CHANGED
|
@@ -44,17 +44,21 @@ openclaw plugins list
|
|
|
44
44
|
|
|
45
45
|
### 更新插件
|
|
46
46
|
|
|
47
|
-
|
|
47
|
+
插件自带更新脚本,一行命令即可:
|
|
48
48
|
|
|
49
49
|
```bash
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
~/.openclaw/extensions/cluster-hub/update.sh
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
脚本会自动检查 npm 最新版本,有更新则下载替换。更新后需重启 Gateway:
|
|
52
54
|
|
|
53
|
-
|
|
55
|
+
```bash
|
|
54
56
|
kill -9 $(pgrep -f "openclaw.*gateway")
|
|
55
57
|
openclaw gateway start
|
|
56
58
|
```
|
|
57
59
|
|
|
60
|
+
也可以直接告诉 AI:"**更新 Hub 插件**",它会自动执行更新 + 重启。
|
|
61
|
+
|
|
58
62
|
---
|
|
59
63
|
|
|
60
64
|
## 第二步:创建集群(根节点)
|
|
@@ -277,7 +281,7 @@ openclaw gateway start
|
|
|
277
281
|
|
|
278
282
|
```bash
|
|
279
283
|
# 更新插件
|
|
280
|
-
|
|
284
|
+
~/.openclaw/extensions/cluster-hub/update.sh
|
|
281
285
|
|
|
282
286
|
# 完全重启
|
|
283
287
|
kill -9 $(pgrep -f "openclaw.*gateway")
|
package/package.json
CHANGED
package/src/feishu-tools.ts
CHANGED
|
@@ -98,7 +98,13 @@ async function feishuPost(path: string, body: any): Promise<any> {
|
|
|
98
98
|
},
|
|
99
99
|
body: JSON.stringify(body),
|
|
100
100
|
});
|
|
101
|
-
const
|
|
101
|
+
const text = await res.text();
|
|
102
|
+
let data;
|
|
103
|
+
try {
|
|
104
|
+
data = JSON.parse(text);
|
|
105
|
+
} catch (e: any) {
|
|
106
|
+
throw new Error(`JSON Error: ${e.message}. Status: ${res.status}. Body: ${text.substring(0, 200)}`);
|
|
107
|
+
}
|
|
102
108
|
if (data.code !== 0) throw new Error(data.msg || `API error ${data.code}`);
|
|
103
109
|
return data.data;
|
|
104
110
|
}
|
|
@@ -210,13 +216,55 @@ async function docCreate(title: string, folderToken?: string) {
|
|
|
210
216
|
return result;
|
|
211
217
|
}
|
|
212
218
|
|
|
219
|
+
function simpleMarkdownToBlocks(markdown: string): any[] {
|
|
220
|
+
const blocks: any[] = [];
|
|
221
|
+
const lines = markdown.split('\n');
|
|
222
|
+
let inCodeBlock = false;
|
|
223
|
+
let codeContent = '';
|
|
224
|
+
|
|
225
|
+
for (const line of lines) {
|
|
226
|
+
if (line.trim().startsWith('```')) {
|
|
227
|
+
if (inCodeBlock) {
|
|
228
|
+
blocks.push({
|
|
229
|
+
block_type: 14,
|
|
230
|
+
code: { elements: [{ text_run: { content: codeContent.replace(/\n$/, '') } }], language: 1 }
|
|
231
|
+
});
|
|
232
|
+
inCodeBlock = false;
|
|
233
|
+
codeContent = '';
|
|
234
|
+
} else {
|
|
235
|
+
inCodeBlock = true;
|
|
236
|
+
}
|
|
237
|
+
continue;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
if (inCodeBlock) {
|
|
241
|
+
codeContent += line + '\n';
|
|
242
|
+
continue;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
const trimmed = line.trim();
|
|
246
|
+
if (!trimmed) continue;
|
|
247
|
+
|
|
248
|
+
if (trimmed.startsWith('# ')) {
|
|
249
|
+
blocks.push({ block_type: 3, heading1: { elements: [{ text_run: { content: trimmed.substring(2) } }] } });
|
|
250
|
+
} else if (trimmed.startsWith('## ')) {
|
|
251
|
+
blocks.push({ block_type: 4, heading2: { elements: [{ text_run: { content: trimmed.substring(3) } }] } });
|
|
252
|
+
} else if (trimmed.startsWith('### ')) {
|
|
253
|
+
blocks.push({ block_type: 5, heading3: { elements: [{ text_run: { content: trimmed.substring(4) } }] } });
|
|
254
|
+
} else if (trimmed.startsWith('- ') || trimmed.startsWith('* ')) {
|
|
255
|
+
blocks.push({ block_type: 12, bullet: { elements: [{ text_run: { content: trimmed.substring(2) } }] } });
|
|
256
|
+
} else if (trimmed.startsWith('> ')) {
|
|
257
|
+
blocks.push({ block_type: 15, quote: { elements: [{ text_run: { content: trimmed.substring(2) } }] } });
|
|
258
|
+
} else {
|
|
259
|
+
blocks.push({ block_type: 2, text: { elements: [{ text_run: { content: line } }] } });
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
return blocks;
|
|
263
|
+
}
|
|
264
|
+
|
|
213
265
|
async function docWrite(docToken: string, markdown: string) {
|
|
214
|
-
// 1. 转换 markdown 为 blocks
|
|
215
|
-
const
|
|
216
|
-
content_type: 'markdown',
|
|
217
|
-
content: markdown,
|
|
218
|
-
});
|
|
219
|
-
const blocks = converted?.blocks || [];
|
|
266
|
+
// 1. 转换 markdown 为 blocks (本地转换,不再依赖不稳定的 convert 接口)
|
|
267
|
+
const blocks = simpleMarkdownToBlocks(markdown);
|
|
220
268
|
|
|
221
269
|
// 2. 清除现有内容
|
|
222
270
|
const existing = await feishuGet(`/open-apis/docx/v1/documents/${docToken}/blocks`);
|
|
@@ -249,11 +297,7 @@ async function docWrite(docToken: string, markdown: string) {
|
|
|
249
297
|
}
|
|
250
298
|
|
|
251
299
|
async function docAppend(docToken: string, markdown: string) {
|
|
252
|
-
const
|
|
253
|
-
content_type: 'markdown',
|
|
254
|
-
content: markdown,
|
|
255
|
-
});
|
|
256
|
-
const blocks = converted?.blocks || [];
|
|
300
|
+
const blocks = simpleMarkdownToBlocks(markdown);
|
|
257
301
|
if (blocks.length === 0) throw new Error('Content is empty');
|
|
258
302
|
|
|
259
303
|
const inserted = await feishuPost(
|