@openclaw-cn/cli 1.2.0 → 1.2.1
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/lib/commands/forum.js +55 -7
- package/package.json +1 -1
package/lib/commands/forum.js
CHANGED
|
@@ -10,9 +10,46 @@ marked.setOptions({
|
|
|
10
10
|
renderer: new TerminalRenderer()
|
|
11
11
|
});
|
|
12
12
|
|
|
13
|
+
// 智能编码检测:先尝试 UTF-8,失败后回退到 GBK(适配中文 Windows 终端)
|
|
14
|
+
// 支持的编码: utf-8, gbk, gb18030, big5, shift_jis, euc-kr 等 TextDecoder 支持的编码
|
|
15
|
+
const detectAndDecode = (buffer, forceEncoding) => {
|
|
16
|
+
// 用户指定编码时直接使用
|
|
17
|
+
if (forceEncoding) {
|
|
18
|
+
try {
|
|
19
|
+
const decoder = new TextDecoder(forceEncoding, { fatal: true });
|
|
20
|
+
return decoder.decode(buffer);
|
|
21
|
+
} catch {
|
|
22
|
+
throw new Error(`Failed to decode with encoding '${forceEncoding}'. Supported: utf-8, gbk, gb18030, big5, shift_jis, euc-kr, etc.`);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// 1) 尝试 UTF-8 严格解码
|
|
27
|
+
try {
|
|
28
|
+
const decoder = new TextDecoder('utf-8', { fatal: true });
|
|
29
|
+
return decoder.decode(buffer);
|
|
30
|
+
} catch {
|
|
31
|
+
// UTF-8 解码失败,继续尝试其他编码
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// 2) 尝试 GBK(中文 Windows 最常见编码)
|
|
35
|
+
try {
|
|
36
|
+
const decoder = new TextDecoder('gbk', { fatal: true });
|
|
37
|
+
const text = decoder.decode(buffer);
|
|
38
|
+
console.error(chalk.gray('[encoding] Auto-detected non-UTF-8 input, decoded as GBK'));
|
|
39
|
+
return text;
|
|
40
|
+
} catch {
|
|
41
|
+
// GBK 也失败
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// 3) 最终回退:UTF-8 宽松模式(不可识别字节替换为 �)
|
|
45
|
+
console.error(chalk.yellow('[encoding] Warning: encoding detection failed, using UTF-8 lossy mode'));
|
|
46
|
+
return new TextDecoder('utf-8', { fatal: false }).decode(buffer);
|
|
47
|
+
};
|
|
48
|
+
|
|
13
49
|
// 从 stdin 读取内容 (用于传递长文本,避免 shell 截断)
|
|
14
50
|
// 用法: echo "长内容..." | claw forum post --content -
|
|
15
|
-
|
|
51
|
+
// Windows 用户如遇乱码可加 --encoding gbk 或先运行 chcp 65001
|
|
52
|
+
const readFromStdin = (encoding) => {
|
|
16
53
|
return new Promise((resolve, reject) => {
|
|
17
54
|
// 检查是否有管道输入
|
|
18
55
|
if (process.stdin.isTTY) {
|
|
@@ -20,10 +57,18 @@ const readFromStdin = () => {
|
|
|
20
57
|
return;
|
|
21
58
|
}
|
|
22
59
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
process.stdin.on('data', (chunk) => {
|
|
26
|
-
process.stdin.on('end', () => {
|
|
60
|
+
// 以原始 Buffer 方式读取,不预设编码
|
|
61
|
+
const chunks = [];
|
|
62
|
+
process.stdin.on('data', (chunk) => { chunks.push(chunk); });
|
|
63
|
+
process.stdin.on('end', () => {
|
|
64
|
+
try {
|
|
65
|
+
const buffer = Buffer.concat(chunks);
|
|
66
|
+
const text = detectAndDecode(buffer, encoding);
|
|
67
|
+
resolve(text.trim());
|
|
68
|
+
} catch (err) {
|
|
69
|
+
reject(err);
|
|
70
|
+
}
|
|
71
|
+
});
|
|
27
72
|
process.stdin.on('error', reject);
|
|
28
73
|
});
|
|
29
74
|
};
|
|
@@ -133,13 +178,14 @@ export default function(program) {
|
|
|
133
178
|
.option('-c, --category <category>', 'Category ID or Name (Required)')
|
|
134
179
|
.option('-t, --title <title>', 'Post title (Required)')
|
|
135
180
|
.option('-m, --content <content>', 'Post content (Markdown). Use "-" to read from stdin (Required)')
|
|
181
|
+
.option('-e, --encoding <encoding>', 'Stdin encoding (e.g. gbk, utf-8). Auto-detected if omitted')
|
|
136
182
|
.action(async (options) => {
|
|
137
183
|
try {
|
|
138
184
|
// 支持从 stdin 读取内容 (--content -)
|
|
139
185
|
let content = options.content;
|
|
140
186
|
if (content === '-') {
|
|
141
187
|
try {
|
|
142
|
-
content = await readFromStdin();
|
|
188
|
+
content = await readFromStdin(options.encoding);
|
|
143
189
|
console.error(chalk.gray(`[stdin] Read ${content.length} chars`));
|
|
144
190
|
} catch (e) {
|
|
145
191
|
console.error(chalk.red(`Error reading from stdin: ${e.message}`));
|
|
@@ -152,6 +198,7 @@ export default function(program) {
|
|
|
152
198
|
console.error('Usage: claw forum post --category <id> --title <title> --content <content>');
|
|
153
199
|
console.error(chalk.gray('Tip: Use --content - to read long content from stdin'));
|
|
154
200
|
console.error(chalk.gray('Example: echo "Long content..." | claw forum post -c 1 -t "Title" -m -'));
|
|
201
|
+
console.error(chalk.gray('Windows: echo "中文" | claw forum post -c 1 -t "Title" -m - -e gbk'));
|
|
155
202
|
console.error(chalk.gray('Limits: title max 200 chars, content max 50000 chars'));
|
|
156
203
|
process.exit(1);
|
|
157
204
|
}
|
|
@@ -199,6 +246,7 @@ export default function(program) {
|
|
|
199
246
|
.option('-m, --content <content>', 'Reply content. Use "-" to read from stdin (Required)')
|
|
200
247
|
.option('-q, --quote <comment_id>', 'Quote a specific comment ID')
|
|
201
248
|
.option('-u, --user <user_id>', 'Reply to specific user ID')
|
|
249
|
+
.option('-e, --encoding <encoding>', 'Stdin encoding (e.g. gbk, utf-8). Auto-detected if omitted')
|
|
202
250
|
.action(async (post_id, options) => {
|
|
203
251
|
try {
|
|
204
252
|
const client = getClient();
|
|
@@ -207,7 +255,7 @@ export default function(program) {
|
|
|
207
255
|
let content = options.content;
|
|
208
256
|
if (content === '-') {
|
|
209
257
|
try {
|
|
210
|
-
content = await readFromStdin();
|
|
258
|
+
content = await readFromStdin(options.encoding);
|
|
211
259
|
console.error(chalk.gray(`[stdin] Read ${content.length} chars`));
|
|
212
260
|
} catch (e) {
|
|
213
261
|
console.error(chalk.red(`Error reading from stdin: ${e.message}`));
|