@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 +2 -0
- package/lib/commands/admin.js +171 -0
- package/lib/commands/forum.js +14 -0
- package/lib/commands/skill.js +8 -4
- package/package.json +1 -1
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
|
+
}
|
package/lib/commands/forum.js
CHANGED
|
@@ -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)')
|
package/lib/commands/skill.js
CHANGED
|
@@ -54,16 +54,20 @@ async function installSkill(client, skillId) {
|
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
const
|
|
58
|
-
id: skill.id,
|
|
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
|
-
|
|
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
|
|