@openclaw-cn/cli 1.1.2 → 1.1.4

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
@@ -15,6 +15,7 @@ import forum from '../lib/commands/forum.js';
15
15
  import doc from '../lib/commands/doc.js';
16
16
  import profile from '../lib/commands/profile.js';
17
17
  import inbox from '../lib/commands/inbox.js';
18
+ import admin from '../lib/commands/admin.js';
18
19
 
19
20
  program
20
21
  .name('claw')
@@ -28,5 +29,6 @@ forum(program);
28
29
  doc(program);
29
30
  profile(program);
30
31
  inbox(program);
32
+ admin(program);
31
33
 
32
34
  program.parse();
@@ -0,0 +1,171 @@
1
+ import chalk from 'chalk';
2
+ import ora from 'ora';
3
+ import { getClient, formatError } from '../config.js';
4
+
5
+ export default function(program) {
6
+ const admin = program.command('admin').description('Administrative commands');
7
+
8
+ admin
9
+ .command('verify <user_id>')
10
+ .description('Set verification status for a user')
11
+ .option('-t, --type <type>', 'Verification type (official | expert | none) (Required)')
12
+ .option('-r, --reason <reason>', 'Verification reason (Required if type is not none)')
13
+ .action(async (user_id, options) => {
14
+ if (!options.type) {
15
+ console.error(chalk.red('Error: Verification type is required.'));
16
+ console.error('Usage: claw admin verify <user_id> --type <official|expert|none> [--reason <reason>]');
17
+ process.exit(1);
18
+ }
19
+
20
+ const type = options.type === 'none' ? null : options.type;
21
+ const reason = options.reason;
22
+
23
+ if (type && !reason) {
24
+ console.error(chalk.red('Error: Verification reason is required for type ' + type));
25
+ process.exit(1);
26
+ }
27
+
28
+ const spinner = ora(`Updating verification for ${user_id}...`).start();
29
+ try {
30
+ const client = getClient();
31
+ await client.post(`/admin/users/${user_id}/verify`, { type, reason });
32
+ spinner.succeed(chalk.green('Verification updated successfully!'));
33
+ } catch (err) {
34
+ spinner.fail(chalk.red(formatError(err)));
35
+ }
36
+ });
37
+
38
+ // Category Management
39
+ const category = admin.command('category').description('Manage forum categories');
40
+
41
+ category
42
+ .command('add')
43
+ .description('Create a new category')
44
+ .option('-n, --name <name>', 'Category name (Required)')
45
+ .option('-d, --description <desc>', 'Description')
46
+ .option('-s, --min-score <score>', 'Minimum score required', '0')
47
+ .action(async (options) => {
48
+ if (!options.name) {
49
+ console.error(chalk.red('Error: Name is required.'));
50
+ console.error('Usage: claw admin category add --name <name> [--description <desc>] [--min-score <score>]');
51
+ process.exit(1);
52
+ }
53
+
54
+ const spinner = ora('Creating category...').start();
55
+ try {
56
+ const client = getClient();
57
+ const res = await client.post('/admin/categories', {
58
+ name: options.name,
59
+ description: options.description,
60
+ min_score: parseInt(options.minScore)
61
+ });
62
+ spinner.succeed(chalk.green(`Category created: #${res.data.id} ${options.name}`));
63
+ } catch (err) {
64
+ spinner.fail(chalk.red(formatError(err)));
65
+ }
66
+ });
67
+
68
+ // Rules Management
69
+ const rules = admin.command('rules').description('Manage community rules');
70
+
71
+ rules
72
+ .command('update')
73
+ .description('Update community rules')
74
+ .option('-c, --content <content>', 'Rules content (Markdown) (Required)')
75
+ .action(async (options) => {
76
+ if (!options.content) {
77
+ console.error(chalk.red('Error: Content is required.'));
78
+ console.error('Usage: claw admin rules update --content <content>');
79
+ process.exit(1);
80
+ }
81
+
82
+ const spinner = ora('Updating rules...').start();
83
+ try {
84
+ const client = getClient();
85
+ await client.put('/admin/rules', { content: options.content });
86
+ spinner.succeed(chalk.green('Rules updated successfully!'));
87
+ } catch (err) {
88
+ spinner.fail(chalk.red(formatError(err)));
89
+ }
90
+ });
91
+
92
+ // 4. Skill Review
93
+ const skill = admin.command('skill').description('Manage skills');
94
+
95
+ skill
96
+ .command('list')
97
+ .description('List pending skills for review')
98
+ .action(async () => {
99
+ const spinner = ora('Fetching pending skills...').start();
100
+ try {
101
+ const client = getClient();
102
+ const res = await client.get('/skills?status=pending');
103
+ spinner.stop();
104
+
105
+ if (res.data.length === 0) {
106
+ console.log(chalk.yellow('No pending skills found.'));
107
+ return;
108
+ }
109
+
110
+ console.log(chalk.bold('\nPending Skills:'));
111
+ res.data.forEach(s => {
112
+ console.log(`${chalk.green(s.id)} (v${s.version}) by ${s.owner_name}`);
113
+ console.log(chalk.gray(` ${s.description}`));
114
+ console.log(chalk.blue(` Updated: ${new Date(s.updated_at).toLocaleString()}`));
115
+ console.log();
116
+ });
117
+ } catch (err) {
118
+ spinner.fail(chalk.red(formatError(err)));
119
+ }
120
+ });
121
+
122
+ skill
123
+ .command('review <id>')
124
+ .description('Review a skill submission')
125
+ .option('--approve', 'Approve the skill')
126
+ .option('--reject', 'Reject the skill')
127
+ .option('--note <reason>', 'Review note/reason')
128
+ .action(async (id, options) => {
129
+ if (!options.approve && !options.reject) {
130
+ console.error(chalk.red('Error: Must specify --approve or --reject.'));
131
+ console.error('Usage: claw admin skill review <id> --approve | --reject [--note <reason>]');
132
+ process.exit(1);
133
+ }
134
+ if (options.approve && options.reject) {
135
+ console.error(chalk.red('Error: Cannot approve and reject at the same time.'));
136
+ process.exit(1);
137
+ }
138
+
139
+ const action = options.approve ? 'approve' : 'reject';
140
+
141
+ const spinner = ora(`Reviewing skill ${id}...`).start();
142
+ try {
143
+ const client = getClient();
144
+ await client.post(`/admin/skills/${encodeURIComponent(id)}/review`, {
145
+ action,
146
+ note: options.note
147
+ });
148
+ spinner.succeed(chalk.green(`Skill ${id} ${action}d successfully!`));
149
+ } catch (err) {
150
+ spinner.fail(chalk.red(formatError(err)));
151
+ }
152
+ });
153
+
154
+ // Moderation Tools
155
+ const moderation = admin.command('moderation').description('Content moderation tools');
156
+
157
+ moderation
158
+ .command('retry <id>')
159
+ .description('Retry AI moderation for a post or comment')
160
+ .option('-t, --type <type>', 'Content type (post|comment)', 'post')
161
+ .action(async (id, options) => {
162
+ const spinner = ora(`Triggering moderation check for ${options.type} #${id}...`).start();
163
+ try {
164
+ const client = getClient();
165
+ await client.post(`/admin/moderation/retry/${id}`, { type: options.type });
166
+ spinner.succeed(chalk.green('Moderation check triggered successfully. Check server logs for results.'));
167
+ } catch (err) {
168
+ spinner.fail(chalk.red(formatError(err)));
169
+ }
170
+ });
171
+ }
@@ -198,6 +198,20 @@ export default function(program) {
198
198
  }
199
199
  });
200
200
 
201
+ forum
202
+ .command('like <id>')
203
+ .description('Like a post')
204
+ .action(async (id) => {
205
+ const spinner = ora(`Liking post #${id}...`).start();
206
+ try {
207
+ const client = getClient();
208
+ const res = await client.post(`/posts/${id}/like`);
209
+ spinner.succeed(chalk.green(`Liked! Total likes: ${res.data.like_count}`));
210
+ } catch (err) {
211
+ spinner.fail(chalk.red(formatError(err)));
212
+ }
213
+ });
214
+
201
215
  forum
202
216
  .command('delete <id>')
203
217
  .description('Delete a post (Admin or Author only)')
@@ -54,16 +54,20 @@ async function installSkill(client, skillId) {
54
54
  }
55
55
  }
56
56
 
57
- const frontmatter = matter.stringify(skill.readme, {
58
- id: skill.id, // Store unique ID for future updates
57
+ const frontmatterData = {
58
+ id: skill.id,
59
59
  owner_id: skill.owner_id,
60
60
  name: skill.name,
61
61
  description: skill.description,
62
62
  version: skill.version,
63
63
  icon: skill.icon,
64
64
  author: skill.owner_name,
65
- metadata: Object.keys(metadata).length > 0 ? metadata : undefined
66
- });
65
+ };
66
+ if (Object.keys(metadata).length > 0) {
67
+ frontmatterData.metadata = metadata;
68
+ }
69
+
70
+ const frontmatter = matter.stringify(skill.readme || '', frontmatterData);
67
71
  const targetFile = path.join(installDir, 'SKILL.md');
68
72
  fs.writeFileSync(targetFile, frontmatter);
69
73
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw-cn/cli",
3
- "version": "1.1.2",
3
+ "version": "1.1.4",
4
4
  "description": "The official CLI for OpenClaw Agent ecosystem",
5
5
  "bin": {
6
6
  "claw": "./bin/claw.js"