osai-agent 4.2.29 → 4.2.30
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/package.json +1 -1
- package/src/commands/admin.js +1 -0
- package/src/commands/run.js +13 -0
- package/src/commands/usage.js +75 -0
- package/src/index.js +14 -3
package/package.json
CHANGED
package/src/commands/admin.js
CHANGED
|
@@ -43,6 +43,7 @@ const adminFetch = async (serverArg, path, method = 'GET', body = null, pathPref
|
|
|
43
43
|
return data;
|
|
44
44
|
};
|
|
45
45
|
|
|
46
|
+
export { adminFetch };
|
|
46
47
|
export const listUsers = async ({ server }) => {
|
|
47
48
|
const data = await adminFetch(server, '/admin/users');
|
|
48
49
|
const users = data.users || [];
|
package/src/commands/run.js
CHANGED
|
@@ -31,6 +31,19 @@ export const run = async ({ server: serverOverride, noConfirm = false, osOverrid
|
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
if (!effectiveLocal && token && server) {
|
|
35
|
+
try {
|
|
36
|
+
const res = await fetch(`${server}/auth/check-status`, {
|
|
37
|
+
headers: { 'Authorization': `Bearer ${token}` }
|
|
38
|
+
});
|
|
39
|
+
const data = await res.json();
|
|
40
|
+
if (data.status === 'disabled') {
|
|
41
|
+
console.log(chalk.red(`\n ${data.error}\n`));
|
|
42
|
+
process.exit(1);
|
|
43
|
+
}
|
|
44
|
+
} catch {}
|
|
45
|
+
}
|
|
46
|
+
|
|
34
47
|
const resumedMode = Object.values(MODES).includes(fromSession?.mode) ? fromSession.mode : null;
|
|
35
48
|
const resumedOS = fromSession?.os;
|
|
36
49
|
const userOS = osOverride || resumedOS || config.get('os') || detectDefaultOS();
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { adminFetch } from './admin.js';
|
|
3
|
+
|
|
4
|
+
export const usageStats = async ({ server, days, json }) => {
|
|
5
|
+
const daysVal = Math.min(Math.max(parseInt(days || '7', 10) || 7, 1), 365);
|
|
6
|
+
const qs = daysVal !== 7 ? `?days=${daysVal}` : '';
|
|
7
|
+
const data = await adminFetch(server, `/admin/usage-stats${qs}`, 'GET', null, '/auth');
|
|
8
|
+
const { summary, users } = data;
|
|
9
|
+
|
|
10
|
+
if (json) {
|
|
11
|
+
console.log(JSON.stringify(data, null, 2));
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
console.log(chalk.hex('#4a9eff').bold(`\n Admin — Usage Stats (last ${summary.period_days} days)\n`));
|
|
16
|
+
console.log(` ${chalk.white('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━')}`);
|
|
17
|
+
|
|
18
|
+
const activePct = summary.total_users > 0 ? Math.round(summary.active / summary.total_users * 100) : 0;
|
|
19
|
+
const proPct = summary.total_users > 0 ? Math.round(summary.pro / summary.total_users * 100) : 0;
|
|
20
|
+
|
|
21
|
+
console.log(
|
|
22
|
+
` Users: ${chalk.white(summary.total_users)}` +
|
|
23
|
+
` (${chalk.green(`${summary.active} active`)} ` +
|
|
24
|
+
`· ${chalk.red(`${summary.disabled} disabled`)})`
|
|
25
|
+
);
|
|
26
|
+
console.log(
|
|
27
|
+
` Plans: ${chalk.white(summary.free)} free` +
|
|
28
|
+
` · ${chalk.hex('#ff9e64')(`${summary.pro} pro`)}` +
|
|
29
|
+
` (${chalk.gray(`${proPct}%`)} pro, ${chalk.gray(`+${summary.new_users} new`)})`
|
|
30
|
+
);
|
|
31
|
+
console.log(
|
|
32
|
+
` Sessions: ${chalk.white(summary.total_sessions)}` +
|
|
33
|
+
` | Commands: ${chalk.white(summary.total_commands.toLocaleString())}` +
|
|
34
|
+
` | Pro keys claimed: ${chalk.white(summary.claimed_pro_keys)}`
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
console.log(` ${chalk.white('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━')}\n`);
|
|
38
|
+
|
|
39
|
+
if (users.length === 0) {
|
|
40
|
+
console.log(chalk.yellow(' No users found.\n'));
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const header = ` ${chalk.dim('Email'.padEnd(36))}${chalk.dim('Plan'.padEnd(6))}${chalk.dim('Status'.padEnd(9))}${chalk.dim('Logs'.padEnd(6))}${chalk.dim('Cmd'.padEnd(8))}${chalk.dim('Last active')}`;
|
|
45
|
+
console.log(header);
|
|
46
|
+
|
|
47
|
+
for (const u of users) {
|
|
48
|
+
const planBadge = u.plan === 'pro' ? chalk.hex('#ff9e64')('pro') : chalk.gray('free');
|
|
49
|
+
const statusBadge = u.status === 'disabled' ? chalk.red('disabled') : chalk.green('active');
|
|
50
|
+
const lastActive = u.last_active
|
|
51
|
+
? (() => {
|
|
52
|
+
const d = new Date(u.last_active);
|
|
53
|
+
const now = Date.now();
|
|
54
|
+
const diff = now - d.getTime();
|
|
55
|
+
if (diff < 60000) return 'just now';
|
|
56
|
+
if (diff < 3600000) return `${Math.floor(diff / 60000)}m ago`;
|
|
57
|
+
if (diff < 86400000) return `${Math.floor(diff / 3600000)}h ago`;
|
|
58
|
+
return d.toLocaleDateString();
|
|
59
|
+
})()
|
|
60
|
+
: chalk.gray('never');
|
|
61
|
+
|
|
62
|
+
const logsStr = u.total_logs > 0 ? chalk.white(u.total_logs) : chalk.gray('0');
|
|
63
|
+
const cmdStr = u.total_commands > 0 ? chalk.white(u.total_commands) : chalk.gray('0');
|
|
64
|
+
|
|
65
|
+
console.log(
|
|
66
|
+
` ${chalk.white(u.email.padEnd(36))}` +
|
|
67
|
+
`${planBadge.padEnd(6)}` +
|
|
68
|
+
`${statusBadge.padEnd(9)}` +
|
|
69
|
+
`${logsStr.padEnd(6)}` +
|
|
70
|
+
`${cmdStr.padEnd(8)}` +
|
|
71
|
+
`${lastActive}`
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
console.log();
|
|
75
|
+
};
|
package/src/index.js
CHANGED
|
@@ -27,6 +27,7 @@ import { stopSubagent } from './commands/stop-subagent.js';
|
|
|
27
27
|
import { claimProKey } from './commands/pro.js';
|
|
28
28
|
import { deleteAccount } from './commands/account.js';
|
|
29
29
|
import { listUsers, disableUser, enableUser, generateProKeys } from './commands/admin.js';
|
|
30
|
+
import { usageStats } from './commands/usage.js';
|
|
30
31
|
import minimist from 'minimist';
|
|
31
32
|
import updateNotifier from 'update-notifier';
|
|
32
33
|
import { createRequire } from 'module';
|
|
@@ -144,6 +145,15 @@ switch (cmd) {
|
|
|
144
145
|
}
|
|
145
146
|
break;
|
|
146
147
|
|
|
148
|
+
case 'usage':
|
|
149
|
+
if (args._[1] === 'stats') {
|
|
150
|
+
await usageStats({ server: args.server, days: args.days, json: args.json });
|
|
151
|
+
} else {
|
|
152
|
+
console.log('Usage: osai-agent usage stats [--days 7] [--json]');
|
|
153
|
+
process.exit(1);
|
|
154
|
+
}
|
|
155
|
+
break;
|
|
156
|
+
|
|
147
157
|
case 'admin':
|
|
148
158
|
if (args._[1] === 'users') {
|
|
149
159
|
await listUsers({ server: args.server });
|
|
@@ -193,9 +203,10 @@ switch (cmd) {
|
|
|
193
203
|
console.log(' skills Manage skills');
|
|
194
204
|
console.log(' mcp Manage MCP servers');
|
|
195
205
|
console.log(' stop-subagent Stop a running subagent');
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
206
|
+
console.log(' pro Activate a pro access code');
|
|
207
|
+
console.log(' usage stats Show admin usage statistics (--days 7, --json)');
|
|
208
|
+
console.log(' account delete Permanently delete your account and all data');
|
|
209
|
+
console.log();
|
|
199
210
|
process.exit(cmd ? 1 : 0);
|
|
200
211
|
}
|
|
201
212
|
|