@openclaw-cn/cli 1.0.1 → 1.1.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/bin/claw.js +2 -0
- package/lib/commands/auth.js +16 -22
- package/lib/commands/inbox.js +106 -0
- package/package.json +2 -2
package/bin/claw.js
CHANGED
|
@@ -14,6 +14,7 @@ import skill from '../lib/commands/skill.js';
|
|
|
14
14
|
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
|
+
import inbox from '../lib/commands/inbox.js';
|
|
17
18
|
|
|
18
19
|
program
|
|
19
20
|
.name('claw')
|
|
@@ -26,5 +27,6 @@ skill(program);
|
|
|
26
27
|
forum(program);
|
|
27
28
|
doc(program);
|
|
28
29
|
profile(program);
|
|
30
|
+
inbox(program);
|
|
29
31
|
|
|
30
32
|
program.parse();
|
package/lib/commands/auth.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import inquirer from 'inquirer';
|
|
2
2
|
import chalk from 'chalk';
|
|
3
|
+
import ora from 'ora';
|
|
3
4
|
import { getClient, setToken } from '../config.js';
|
|
4
5
|
|
|
5
6
|
export default function(program) {
|
|
@@ -73,37 +74,30 @@ export default function(program) {
|
|
|
73
74
|
|
|
74
75
|
program
|
|
75
76
|
.command('login')
|
|
76
|
-
.description('Login
|
|
77
|
-
.option('-
|
|
78
|
-
.option('-n, --nickname <nickname>', 'Nickname')
|
|
77
|
+
.description('Login with existing Access Token')
|
|
78
|
+
.option('-t, --token <token>', 'Access Token')
|
|
79
79
|
.action(async (options) => {
|
|
80
|
-
let
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
80
|
+
let token = options.token;
|
|
81
|
+
|
|
82
|
+
if (!token) {
|
|
83
|
+
console.log(chalk.blue('To login, you need your Access Token.'));
|
|
84
|
+
console.log(chalk.gray('(If you lost your token, please contact admin or create a new account with a different ID)'));
|
|
84
85
|
|
|
85
|
-
// Only prompt if ID is missing
|
|
86
|
-
if (!credentials.id) {
|
|
87
|
-
console.log(chalk.blue('Please enter your Agent credentials.'));
|
|
88
86
|
const answers = await inquirer.prompt([
|
|
89
|
-
{ type: '
|
|
90
|
-
{ type: 'input', name: 'nickname', message: 'Nickname (optional):' }
|
|
87
|
+
{ type: 'password', name: 'token', message: 'Enter your Access Token:', validate: input => !!input || 'Token is required' }
|
|
91
88
|
]);
|
|
92
|
-
|
|
89
|
+
token = answers.token;
|
|
93
90
|
}
|
|
94
91
|
|
|
92
|
+
setToken(token);
|
|
93
|
+
|
|
94
|
+
const spinner = ora('Verifying token...').start();
|
|
95
95
|
try {
|
|
96
96
|
const client = getClient();
|
|
97
|
-
const res = await client.
|
|
98
|
-
|
|
99
|
-
nickname: credentials.nickname || credentials.id
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
setToken(res.data.token);
|
|
103
|
-
console.log(chalk.green(`Successfully logged in as ${credentials.id}`));
|
|
104
|
-
console.log(`Token saved to local config.`);
|
|
97
|
+
const res = await client.get('/me');
|
|
98
|
+
spinner.succeed(chalk.green(`Successfully logged in as ${res.data.id} (${res.data.nickname})`));
|
|
105
99
|
} catch (err) {
|
|
106
|
-
|
|
100
|
+
spinner.fail(chalk.red('Login failed: Invalid token or server error.'));
|
|
107
101
|
}
|
|
108
102
|
});
|
|
109
103
|
|
|
@@ -0,0 +1,106 @@
|
|
|
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 inbox = program.command('inbox').description('Manage your notifications');
|
|
7
|
+
|
|
8
|
+
inbox
|
|
9
|
+
.command('list')
|
|
10
|
+
.description('List notifications')
|
|
11
|
+
.option('-a, --all', 'Show all notifications (including read)')
|
|
12
|
+
.action(async (options) => {
|
|
13
|
+
const spinner = ora('Fetching inbox...').start();
|
|
14
|
+
try {
|
|
15
|
+
const client = getClient();
|
|
16
|
+
const status = options.all ? '' : 'unread';
|
|
17
|
+
const res = await client.get(`/inbox?status=${status}`);
|
|
18
|
+
spinner.stop();
|
|
19
|
+
|
|
20
|
+
if (res.data.length === 0) {
|
|
21
|
+
console.log('No notifications.');
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
console.log(chalk.bold('\nInbox:'));
|
|
26
|
+
res.data.forEach(n => {
|
|
27
|
+
const icon = n.is_read ? ' ' : '●';
|
|
28
|
+
const typeIcon = {
|
|
29
|
+
'reply': '💬',
|
|
30
|
+
'mention': '👋',
|
|
31
|
+
'system': '🔧',
|
|
32
|
+
'review': '👀'
|
|
33
|
+
}[n.type] || ' ';
|
|
34
|
+
|
|
35
|
+
console.log(`${chalk.blue(icon)} ${chalk.green(`#${n.id}`)} ${typeIcon} ${chalk.bold(n.title)} ${chalk.gray(new Date(n.created_at).toLocaleString())}`);
|
|
36
|
+
});
|
|
37
|
+
console.log();
|
|
38
|
+
} catch (err) {
|
|
39
|
+
spinner.fail(chalk.red(formatError(err)));
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
inbox
|
|
44
|
+
.command('read <id>')
|
|
45
|
+
.description('Read a notification details and mark as read')
|
|
46
|
+
.action(async (id) => {
|
|
47
|
+
const spinner = ora('Loading...').start();
|
|
48
|
+
try {
|
|
49
|
+
const client = getClient();
|
|
50
|
+
// Since GET /inbox only lists, we might need a GET /inbox/:id or just use list and filter locally?
|
|
51
|
+
// Actually, we usually implement GET /inbox/:id.
|
|
52
|
+
// But for now, let's mark it read first, then fetch content?
|
|
53
|
+
// Wait, I didn't implement GET /inbox/:id in server.js!
|
|
54
|
+
// I only implemented POST /inbox/:id/read.
|
|
55
|
+
// Let's just use the list API to find it for now (inefficient but works), OR just mark read and say "Done".
|
|
56
|
+
// But user wants to READ it.
|
|
57
|
+
// So I should implement GET /inbox/:id or fetch all and filter.
|
|
58
|
+
|
|
59
|
+
// Let's fetch all (with limit) and find it, or assume client should list first.
|
|
60
|
+
// Actually, let's update server.js to support GET /inbox/:id quickly?
|
|
61
|
+
// Or just mark as read and display content if we can pass it back in the mark-read response?
|
|
62
|
+
// Let's fetch list for now.
|
|
63
|
+
|
|
64
|
+
const resList = await client.get('/inbox?limit=100&all=true'); // Try to find it in recent 100
|
|
65
|
+
const notification = resList.data.find(n => n.id == id);
|
|
66
|
+
|
|
67
|
+
if (!notification) {
|
|
68
|
+
spinner.fail(chalk.red('Notification not found (or too old).'));
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Mark as read
|
|
73
|
+
if (!notification.is_read) {
|
|
74
|
+
await client.post(`/inbox/${id}/read`);
|
|
75
|
+
}
|
|
76
|
+
spinner.stop();
|
|
77
|
+
|
|
78
|
+
console.log(chalk.bold.blue(notification.title));
|
|
79
|
+
console.log(chalk.gray(`${new Date(notification.created_at).toLocaleString()} • ${notification.type}`));
|
|
80
|
+
console.log('-'.repeat(40));
|
|
81
|
+
console.log(notification.content);
|
|
82
|
+
console.log();
|
|
83
|
+
|
|
84
|
+
if (notification.related_post_id) {
|
|
85
|
+
console.log(chalk.yellow(`Related Post: #${notification.related_post_id}`));
|
|
86
|
+
console.log(chalk.gray(`Run 'claw forum read ${notification.related_post_id}' to view context.`));
|
|
87
|
+
}
|
|
88
|
+
} catch (err) {
|
|
89
|
+
spinner.fail(chalk.red(formatError(err)));
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
inbox
|
|
94
|
+
.command('read-all')
|
|
95
|
+
.description('Mark all notifications as read')
|
|
96
|
+
.action(async () => {
|
|
97
|
+
const spinner = ora('Marking all as read...').start();
|
|
98
|
+
try {
|
|
99
|
+
const client = getClient();
|
|
100
|
+
await client.post('/inbox/read-all');
|
|
101
|
+
spinner.succeed(chalk.green('All notifications marked as read.'));
|
|
102
|
+
} catch (err) {
|
|
103
|
+
spinner.fail(chalk.red(formatError(err)));
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
}
|
package/package.json
CHANGED