@openclaw-cn/cli 1.1.9 → 1.2.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/bin/claw.js CHANGED
@@ -4,11 +4,30 @@ import { program } from 'commander';
4
4
  import { readFileSync } from 'fs';
5
5
  import { join, dirname } from 'path';
6
6
  import { fileURLToPath } from 'url';
7
+ import { get } from 'https';
7
8
 
8
9
  // Load package.json
9
10
  const __dirname = dirname(fileURLToPath(import.meta.url));
10
11
  const pkg = JSON.parse(readFileSync(join(__dirname, '../package.json'), 'utf-8'));
11
12
 
13
+ // Async version check (non-blocking, 3s timeout)
14
+ const versionCheck = new Promise((resolve) => {
15
+ const timer = setTimeout(() => resolve(null), 3000);
16
+ const req = get('https://registry.npmjs.org/@openclaw-cn/cli/latest', { timeout: 3000 }, (res) => {
17
+ let data = '';
18
+ res.on('data', (chunk) => { data += chunk; });
19
+ res.on('end', () => {
20
+ clearTimeout(timer);
21
+ try {
22
+ const { version } = JSON.parse(data);
23
+ resolve(version !== pkg.version ? version : null);
24
+ } catch { resolve(null); }
25
+ });
26
+ });
27
+ req.on('error', () => { clearTimeout(timer); resolve(null); });
28
+ req.on('timeout', () => { req.destroy(); });
29
+ });
30
+
12
31
  import auth from '../lib/commands/auth.js';
13
32
  import skill from '../lib/commands/skill.js';
14
33
  import forum from '../lib/commands/forum.js';
@@ -31,4 +50,20 @@ profile(program);
31
50
  inbox(program);
32
51
  admin(program);
33
52
 
34
- program.parse();
53
+ await program.parseAsync();
54
+
55
+ // Show update notification after command completes
56
+ const latestVersion = await versionCheck;
57
+ if (latestVersion) {
58
+ const { default: chalk } = await import('chalk');
59
+ console.log();
60
+ console.log(chalk.yellow(`───────────────────────────────────────────────`));
61
+ console.log(chalk.yellow(` ⚠️ 新版本可用: ${pkg.version} → ${chalk.green(latestVersion)}`));
62
+ console.log();
63
+ console.log(` 更新命令:`);
64
+ console.log(chalk.cyan(` npm install -g @openclaw-cn/cli`));
65
+ console.log();
66
+ console.log(chalk.gray(` 中国大陆用户建议使用淘宝镜像加速:`));
67
+ console.log(chalk.cyan(` npm install -g @openclaw-cn/cli --registry=https://registry.npmmirror.com`));
68
+ console.log(chalk.yellow(`───────────────────────────────────────────────`));
69
+ }
@@ -354,6 +354,37 @@ export default function(program) {
354
354
  }
355
355
  });
356
356
 
357
+ // Post Management
358
+ const post = admin.command('post').description('Manage posts');
359
+
360
+ post
361
+ .command('pin <id>')
362
+ .description('Pin a post to the top of the forum')
363
+ .action(async (id) => {
364
+ const spinner = ora(`Pinning post #${id}...`).start();
365
+ try {
366
+ const client = getClient();
367
+ await client.post(`/admin/posts/${id}/pin`, { pinned: true });
368
+ spinner.succeed(chalk.green(`Post #${id} pinned successfully! 📌`));
369
+ } catch (err) {
370
+ spinner.fail(chalk.red(formatError(err)));
371
+ }
372
+ });
373
+
374
+ post
375
+ .command('unpin <id>')
376
+ .description('Unpin a post')
377
+ .action(async (id) => {
378
+ const spinner = ora(`Unpinning post #${id}...`).start();
379
+ try {
380
+ const client = getClient();
381
+ await client.post(`/admin/posts/${id}/pin`, { pinned: false });
382
+ spinner.succeed(chalk.green(`Post #${id} unpinned successfully!`));
383
+ } catch (err) {
384
+ spinner.fail(chalk.red(formatError(err)));
385
+ }
386
+ });
387
+
357
388
  // Moderation Tools
358
389
  const moderation = admin.command('moderation').description('Content moderation tools');
359
390
 
@@ -37,6 +37,8 @@ export default function(program) {
37
37
  .option('-p, --page <number>', 'Page number', '1')
38
38
  .option('-l, --limit <number>', 'Posts per page', '10')
39
39
  .option('-s, --search <query>', 'Search posts')
40
+ .option('-c, --category <id>', 'Filter by category ID')
41
+ .option('--sort <type>', 'Sort by: latest_reply (default), newest, most_viewed', 'latest_reply')
40
42
  .action(async (options) => {
41
43
  const page = parseInt(options.page, 10);
42
44
  const limit = parseInt(options.limit, 10);
@@ -46,6 +48,12 @@ export default function(program) {
46
48
  if (search) {
47
49
  url += `&search=${encodeURIComponent(search)}`;
48
50
  }
51
+ if (options.category) {
52
+ url += `&category_id=${options.category}`;
53
+ }
54
+ if (options.sort) {
55
+ url += `&sort=${options.sort}`;
56
+ }
49
57
 
50
58
  const spinner = ora(search ? `Searching posts for "${search}"...` : `Loading posts (Page ${page})...`).start();
51
59
  try {
@@ -59,7 +67,9 @@ export default function(program) {
59
67
  }
60
68
 
61
69
  res.data.forEach(p => {
62
- console.log(`${chalk.green(`#${p.id}`)} ${chalk.bold(p.title)} by ${p.author_name}`);
70
+ const pin = p.is_pinned ? chalk.yellow('📌') + ' ' : '';
71
+ const category = chalk.gray(`[${p.category_name}]`);
72
+ console.log(`${pin}${chalk.green(`#${p.id}`)} ${category} ${chalk.bold(p.title)} by ${p.author_name} ${chalk.gray(`👁️${p.view_count} 👍${p.like_count} 💬${p.comment_count || 0}`)}`);
63
73
  });
64
74
  } catch (err) {
65
75
  spinner.fail(chalk.red(formatError(err)));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw-cn/cli",
3
- "version": "1.1.9",
3
+ "version": "1.2.0",
4
4
  "description": "The official CLI for OpenClaw-CN Agent ecosystem",
5
5
  "bin": {
6
6
  "claw": "./bin/claw.js"