@lanonasis/cli 3.9.5 → 3.9.7
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/CHANGELOG.md +49 -0
- package/README.md +28 -16
- package/dist/core/welcome.js +4 -4
- package/dist/index-simple.js +13 -1
- package/dist/index.js +130 -13
- package/dist/mcp/schemas/tool-schemas.d.ts +186 -538
- package/dist/mcp/schemas/tool-schemas.js +7 -7
- package/dist/utils/api.d.ts +25 -0
- package/dist/utils/api.js +161 -7
- package/dist/utils/config.d.ts +21 -1
- package/dist/utils/config.js +262 -47
- package/package.json +23 -23
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,54 @@
|
|
|
1
1
|
# Changelog - @lanonasis/cli
|
|
2
2
|
|
|
3
|
+
## [3.9.7] - 2026-02-21
|
|
4
|
+
|
|
5
|
+
### ✨ New Features
|
|
6
|
+
|
|
7
|
+
- **`onasis whoami` command**: Display full authenticated user profile including email, name, role, OAuth provider, project scope, and last login time. Fetches live data from `GET /v1/auth/me`.
|
|
8
|
+
- **Live profile on `auth status`**: `onasis auth status` now fetches the real user profile from the auth gateway and displays email, role, and plan — no longer relies solely on cached local state.
|
|
9
|
+
- **Live memory API probe on `auth status`**: After local auth check passes, `auth status` issues a real memory list request to confirm end-to-end API access, reporting `✓ accessible` or `✖ rejected (401)` with actionable guidance.
|
|
10
|
+
- **Manual endpoint override warning**: `auth status` now warns when `manualEndpointOverrides` is active and shows the configured endpoint URLs.
|
|
11
|
+
|
|
12
|
+
### 🐛 Bug Fixes
|
|
13
|
+
|
|
14
|
+
- **OAuth sessions no longer show "Not Authenticated"**: Fixed `auth status` incorrectly reporting unauthenticated for valid OAuth PKCE sessions — was checking `if (isAuth && user)` when `user` may be undefined for OAuth sessions.
|
|
15
|
+
- **`process.exit(1)` no longer kills status probe**: Added `noExit` flag to `APIClient` so callers like `auth status` can catch 401/403 from the memory probe without the interceptor terminating the process.
|
|
16
|
+
- **Stale auth cache cleared on 401**: When the memory API returns 401, the CLI now calls `invalidateAuthCache()` to clear the 5-minute in-memory cache and the persisted `lastValidated` timestamp, preventing the 24-hour grace bypass.
|
|
17
|
+
- **24-hour `lastValidated` skip removed**: Eliminated a security hole that bypassed server re-validation for 24 hours after any successful auth check.
|
|
18
|
+
- **7-day offline grace restricted to network errors**: The offline grace period no longer applies to explicit 401/403 auth rejections — only genuine network failures.
|
|
19
|
+
- **Bogus vendor key always passed auth check**: `pingAuthHealth()` was hitting the unauthenticated `/health` endpoint. Replaced with `probeVendorKeyAuth()` which calls `POST /api/v1/memories/search` — a real protected endpoint. Interprets 401/403 as auth rejection, any other response (400, 405, 5xx) as auth accepted with a backend concern.
|
|
20
|
+
- **`discoverServices()` overwrote manual overrides**: Fixed auto-discovery ignoring `manualEndpointOverrides`; discovery now short-circuits when manual overrides are active.
|
|
21
|
+
- **Stale JWT cleared on vendor key switch**: When `setVendorKey()` sets `authMethod: 'vendor_key'`, any existing JWT tokens are now removed from config to prevent auth-method confusion in the API client.
|
|
22
|
+
- **Zod v4 compatibility**: Fixed `z.record(z.any())` → `z.record(z.string(), z.any())` (5 instances in `tool-schemas.ts`) and `error.errors` → `error.issues` (2 instances in schema validator).
|
|
23
|
+
- **Inquirer v9 compatibility**: Fixed deprecated `type: 'list'` → `type: 'select'` prompt type in `welcome.ts`.
|
|
24
|
+
|
|
25
|
+
### 📡 Auth Gateway Integration (coordinated release)
|
|
26
|
+
|
|
27
|
+
These CLI changes are paired with server-side fixes in the same release:
|
|
28
|
+
- **Auth Gateway `requireAuth`**: Added opaque OAuth PKCE token introspection path — OAuth CLI sessions can now access `GET /v1/auth/me` and other protected endpoints.
|
|
29
|
+
- **Central API Gateway (`onasis-gateway`)**: `validateJWTToken()` now falls back to `POST /verify-token` when the session endpoint returns 401, enabling OAuth token passthrough for all proxied services. Added `get-me` tool to the auth-gateway MCP adapter.
|
|
30
|
+
|
|
31
|
+
### 📚 Documentation
|
|
32
|
+
|
|
33
|
+
- Updated README with `onasis whoami` command reference.
|
|
34
|
+
- Added `auth status` live probe behavior to authentication section.
|
|
35
|
+
- Added `--no-mcp` flag to memory command examples.
|
|
36
|
+
|
|
37
|
+
## [3.9.6] - 2026-02-21
|
|
38
|
+
|
|
39
|
+
### 🐛 Bug Fixes
|
|
40
|
+
|
|
41
|
+
- **Reliable Memory Auth Routing**: Memory CRUD and search operations now consistently route through the API gateway (`https://api.lanonasis.com`) to avoid MCP endpoint contract mismatches.
|
|
42
|
+
- **Legacy Endpoint Compatibility**: Added fallback support for deployments that still expose RPC-style memory routes (`/api/v1/memory/*`) when REST routes return `400/405`.
|
|
43
|
+
- **Auth Status Accuracy**: `status` now validates live auth state against the auth verify endpoint before reporting authenticated session state.
|
|
44
|
+
- **OAuth Session Stability**: Requests proactively refresh OAuth/JWT sessions to reduce intermittent `memory login required` errors during long-running CLI usage.
|
|
45
|
+
- **Response Normalization**: Memory get/list/search handlers normalize wrapped gateway responses (`{ data: ... }`) for consistent CLI behavior across environments.
|
|
46
|
+
|
|
47
|
+
### 📚 Documentation
|
|
48
|
+
|
|
49
|
+
- Clarified auth flow behavior for vendor keys and bearer tokens.
|
|
50
|
+
- Added release notes for endpoint override guidance and memory transport behavior.
|
|
51
|
+
|
|
3
52
|
## [3.9.3] - 2026-02-02
|
|
4
53
|
|
|
5
54
|
### ✨ Features
|
package/README.md
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
# @lanonasis/cli v3.9.
|
|
1
|
+
# @lanonasis/cli v3.9.7 - OAuth PKCE Auth & whoami
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/@lanonasis/cli)
|
|
4
4
|
[](https://www.npmjs.com/package/@lanonasis/cli)
|
|
5
5
|
[](https://opensource.org/licenses/MIT)
|
|
6
6
|
[](https://api.lanonasis.com/.well-known/onasis.json)
|
|
7
7
|
|
|
8
|
-
🎉 **NEW IN v3.9.
|
|
8
|
+
🎉 **NEW IN v3.9.7**: Full OAuth PKCE session support across CLI and API gateway. New `onasis whoami` command. `auth status` now shows live user profile and probes real memory API access. Seven auth verification fixes eliminate false-positive "Authenticated: Yes" reports.
|
|
9
9
|
|
|
10
10
|
## 🚀 Quick Start
|
|
11
11
|
|
|
@@ -129,23 +129,19 @@ maas memory list
|
|
|
129
129
|
|
|
130
130
|
## 🔐 Security & Authentication
|
|
131
131
|
|
|
132
|
-
### Enterprise-Grade
|
|
132
|
+
### Enterprise-Grade API Key Handling
|
|
133
133
|
|
|
134
|
-
|
|
134
|
+
The CLI uses secure local storage and sends credentials in the expected wire format:
|
|
135
135
|
|
|
136
|
-
- ✅ **
|
|
137
|
-
- ✅ **
|
|
138
|
-
- ✅ **
|
|
139
|
-
- ✅ **
|
|
140
|
-
|
|
141
|
-
```typescript
|
|
142
|
-
// Hash utilities are built-in and automatic
|
|
143
|
-
// Your vendor keys are automatically secured
|
|
144
|
-
onasis login --vendor-key pk_xxxxx.sk_xxxxx // ✅ Automatically hashed
|
|
145
|
-
```
|
|
136
|
+
- ✅ **Encrypted At Rest**: Vendor keys are stored in encrypted local storage (keytar when available, encrypted file fallback otherwise).
|
|
137
|
+
- ✅ **Correct On-Wire Format**: Vendor key auth sends the raw vendor key in `X-API-Key` over HTTPS.
|
|
138
|
+
- ✅ **Single Server-Side Hash Validation**: The API validates keys with server-side hashing and does not require client-side hashing.
|
|
139
|
+
- ✅ **Token-First Sessions**: OAuth/JWT sessions use `Authorization: Bearer <token>` and refresh automatically before expiry.
|
|
146
140
|
|
|
147
141
|
### Authentication Methods
|
|
148
142
|
|
|
143
|
+
> Transport note: for memory commands, keep `manualEndpointOverrides=false` so requests route through `https://api.lanonasis.com`.
|
|
144
|
+
|
|
149
145
|
### 1. Vendor Key Authentication (Recommended)
|
|
150
146
|
|
|
151
147
|
Best for API integrations and automation. Copy the vendor key value exactly as shown in your LanOnasis dashboard (keys may vary in format):
|
|
@@ -176,13 +172,28 @@ Traditional username/password authentication:
|
|
|
176
172
|
onasis login # Will prompt for email and password
|
|
177
173
|
```
|
|
178
174
|
|
|
179
|
-
### Authentication Status
|
|
175
|
+
### Authentication Status & Profile
|
|
180
176
|
|
|
181
177
|
```bash
|
|
182
|
-
onasis auth status # Check current authentication
|
|
178
|
+
onasis auth status # Check current authentication (probes live memory API access)
|
|
183
179
|
onasis auth logout # Logout from current session
|
|
180
|
+
onasis whoami # Display full authenticated user profile
|
|
184
181
|
```
|
|
185
182
|
|
|
183
|
+
`auth status` now performs a live end-to-end check:
|
|
184
|
+
1. Validates the local credential (vendor key probe hits a real protected endpoint, not `/health`)
|
|
185
|
+
2. Fetches and displays your user profile from `GET /v1/auth/me`
|
|
186
|
+
3. Issues a real memory list request to confirm API access is working
|
|
187
|
+
4. Warns if manual endpoint overrides are active
|
|
188
|
+
|
|
189
|
+
`onasis whoami` displays:
|
|
190
|
+
- Email address and display name
|
|
191
|
+
- Role (admin, user, authenticated)
|
|
192
|
+
- Plan tier (free, pro, enterprise)
|
|
193
|
+
- OAuth provider (if applicable)
|
|
194
|
+
- Project scope
|
|
195
|
+
- Last login time
|
|
196
|
+
|
|
186
197
|
**Auth Login Options:**
|
|
187
198
|
| Short | Long | Description |
|
|
188
199
|
|-------|------|-------------|
|
|
@@ -226,6 +237,7 @@ echo 'onasis --completion fish | source' >> ~/.config/fish/config.fish
|
|
|
226
237
|
```bash
|
|
227
238
|
onasis health # Comprehensive system health check
|
|
228
239
|
onasis status # Quick status overview
|
|
240
|
+
onasis whoami # Display authenticated user profile (email, role, plan, provider)
|
|
229
241
|
onasis init # Initialize CLI configuration
|
|
230
242
|
onasis guide # Interactive setup guide
|
|
231
243
|
onasis quickstart # Essential commands reference
|
package/dist/core/welcome.js
CHANGED
|
@@ -73,7 +73,7 @@ export class WelcomeExperience {
|
|
|
73
73
|
const choices = isAuthenticated ? existingUserOptions : newUserOptions;
|
|
74
74
|
const { choice } = await inquirer.prompt([
|
|
75
75
|
{
|
|
76
|
-
type: '
|
|
76
|
+
type: 'select',
|
|
77
77
|
name: 'choice',
|
|
78
78
|
message: isAuthenticated ?
|
|
79
79
|
'Welcome back! What would you like to do?' :
|
|
@@ -229,7 +229,7 @@ export class InteractiveSetup {
|
|
|
229
229
|
console.log("Let's connect to your Onasis service\n");
|
|
230
230
|
const { connectionType } = await inquirer.prompt([
|
|
231
231
|
{
|
|
232
|
-
type: '
|
|
232
|
+
type: 'select',
|
|
233
233
|
name: 'connectionType',
|
|
234
234
|
message: 'Where is your Onasis service hosted?',
|
|
235
235
|
choices: [
|
|
@@ -291,7 +291,7 @@ export class InteractiveSetup {
|
|
|
291
291
|
};
|
|
292
292
|
const { authMethod } = await inquirer.prompt([
|
|
293
293
|
{
|
|
294
|
-
type: '
|
|
294
|
+
type: 'select',
|
|
295
295
|
name: 'authMethod',
|
|
296
296
|
message: 'Select authentication method:',
|
|
297
297
|
choices: [
|
|
@@ -395,7 +395,7 @@ export class InteractiveSetup {
|
|
|
395
395
|
console.log("Let's personalize your experience\n");
|
|
396
396
|
const answers = await inquirer.prompt([
|
|
397
397
|
{
|
|
398
|
-
type: '
|
|
398
|
+
type: 'select',
|
|
399
399
|
name: 'outputFormat',
|
|
400
400
|
message: 'Preferred output format:',
|
|
401
401
|
choices: [
|
package/dist/index-simple.js
CHANGED
|
@@ -553,18 +553,30 @@ program
|
|
|
553
553
|
.action(async () => {
|
|
554
554
|
// Initialize config first
|
|
555
555
|
await cliConfig.init();
|
|
556
|
-
const
|
|
556
|
+
const verification = await cliConfig.verifyCurrentCredentialsWithServer().catch((error) => ({
|
|
557
|
+
valid: false,
|
|
558
|
+
method: 'none',
|
|
559
|
+
endpoint: undefined,
|
|
560
|
+
reason: error instanceof Error ? error.message : String(error)
|
|
561
|
+
}));
|
|
562
|
+
const isAuth = verification.valid;
|
|
557
563
|
const apiUrl = cliConfig.getApiUrl();
|
|
558
564
|
console.log(chalk.blue.bold('MaaS CLI Status'));
|
|
559
565
|
console.log(`API URL: ${apiUrl}`);
|
|
560
566
|
console.log(`Authenticated: ${isAuth ? chalk.green('Yes') : chalk.red('No')}`);
|
|
567
|
+
if (process.env.CLI_VERBOSE === 'true' && verification.endpoint) {
|
|
568
|
+
console.log(`Verified via: ${verification.endpoint}`);
|
|
569
|
+
}
|
|
561
570
|
if (isAuth) {
|
|
562
571
|
const user = await cliConfig.getCurrentUser();
|
|
563
572
|
if (user) {
|
|
564
573
|
console.log(`User: ${user.email}`);
|
|
565
574
|
console.log(`Plan: ${user.plan}`);
|
|
566
575
|
}
|
|
576
|
+
return;
|
|
567
577
|
}
|
|
578
|
+
console.log(chalk.yellow(`Auth check: ${verification.reason || 'Credential validation failed'}`));
|
|
579
|
+
console.log(chalk.yellow('Please run:'), chalk.white('lanonasis auth login'));
|
|
568
580
|
});
|
|
569
581
|
// Health command using the healthCheck function
|
|
570
582
|
program
|
package/dist/index.js
CHANGED
|
@@ -11,6 +11,7 @@ import { orgCommands } from './commands/organization.js';
|
|
|
11
11
|
import { mcpCommands } from './commands/mcp.js';
|
|
12
12
|
import apiKeysCommand from './commands/api-keys.js';
|
|
13
13
|
import { CLIConfig } from './utils/config.js';
|
|
14
|
+
import { APIClient } from './utils/api.js';
|
|
14
15
|
import { getMCPClient } from './utils/mcp-client.js';
|
|
15
16
|
import { dirname, join } from 'path';
|
|
16
17
|
import { createOnboardingFlow } from './ux/index.js';
|
|
@@ -253,29 +254,77 @@ authCmd
|
|
|
253
254
|
.description('Show authentication status')
|
|
254
255
|
.action(async () => {
|
|
255
256
|
const isAuth = await cliConfig.isAuthenticated();
|
|
256
|
-
const user = await cliConfig.getCurrentUser();
|
|
257
257
|
const failureCount = cliConfig.getFailureCount();
|
|
258
258
|
const lastFailure = cliConfig.getLastAuthFailure();
|
|
259
259
|
const authMethod = cliConfig.get('authMethod');
|
|
260
260
|
const lastValidated = cliConfig.get('lastValidated');
|
|
261
261
|
console.log(chalk.blue.bold('🔐 Authentication Status'));
|
|
262
262
|
console.log('━'.repeat(40));
|
|
263
|
-
if (isAuth
|
|
263
|
+
if (isAuth) {
|
|
264
264
|
console.log(chalk.green('✓ Authenticated'));
|
|
265
|
-
console.log(`Email: ${user.email}`);
|
|
266
|
-
console.log(`Organization: ${user.organization_id}`);
|
|
267
|
-
console.log(`Plan: ${user.plan}`);
|
|
268
265
|
if (authMethod) {
|
|
269
266
|
console.log(`Method: ${authMethod}`);
|
|
270
267
|
}
|
|
271
268
|
if (lastValidated) {
|
|
272
|
-
|
|
273
|
-
|
|
269
|
+
console.log(`Last validated: ${new Date(lastValidated).toLocaleString()}`);
|
|
270
|
+
}
|
|
271
|
+
// Fetch live profile from auth gateway
|
|
272
|
+
try {
|
|
273
|
+
const profileClient = new APIClient();
|
|
274
|
+
profileClient.noExit = true;
|
|
275
|
+
const profile = await profileClient.getUserProfile();
|
|
276
|
+
console.log(`Email: ${profile.email}`);
|
|
277
|
+
if (profile.name)
|
|
278
|
+
console.log(`Name: ${profile.name}`);
|
|
279
|
+
console.log(`Role: ${profile.role}`);
|
|
280
|
+
if (profile.provider)
|
|
281
|
+
console.log(`Provider: ${profile.provider}`);
|
|
282
|
+
if (profile.last_sign_in_at) {
|
|
283
|
+
console.log(`Last sign-in: ${new Date(profile.last_sign_in_at).toLocaleString()}`);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
catch {
|
|
287
|
+
// Profile fetch failed (e.g. auth gateway offline) — show cached info if available
|
|
288
|
+
const cached = await cliConfig.getCurrentUser();
|
|
289
|
+
if (cached?.email)
|
|
290
|
+
console.log(`Email: ${cached.email} (cached)`);
|
|
274
291
|
}
|
|
275
292
|
}
|
|
276
293
|
else {
|
|
277
294
|
console.log(chalk.red('✖ Not authenticated'));
|
|
278
|
-
console.log(chalk.yellow('Run:'), chalk.white('
|
|
295
|
+
console.log(chalk.yellow('Run:'), chalk.white('lanonasis auth login'));
|
|
296
|
+
}
|
|
297
|
+
// Warn when manual endpoint overrides are active
|
|
298
|
+
if (cliConfig.hasManualEndpointOverrides()) {
|
|
299
|
+
console.log();
|
|
300
|
+
console.log(chalk.yellow('⚠️ Manual endpoint overrides are active (manualEndpointOverrides=true)'));
|
|
301
|
+
const services = cliConfig.get('discoveredServices');
|
|
302
|
+
if (services) {
|
|
303
|
+
console.log(chalk.gray(` auth: ${services['auth_base']}`));
|
|
304
|
+
console.log(chalk.gray(` memory: ${services['memory_base']}`));
|
|
305
|
+
}
|
|
306
|
+
console.log(chalk.gray(' Run: lanonasis config clear-overrides to restore auto-discovery'));
|
|
307
|
+
}
|
|
308
|
+
// Live memory API probe — shows whether credentials actually work end-to-end
|
|
309
|
+
if (isAuth) {
|
|
310
|
+
console.log();
|
|
311
|
+
process.stdout.write('Memory API access: ');
|
|
312
|
+
try {
|
|
313
|
+
const apiClient = new APIClient();
|
|
314
|
+
apiClient.noExit = true; // catch 401 in our try/catch below instead of process.exit
|
|
315
|
+
await apiClient.getMemories({ limit: 1 });
|
|
316
|
+
console.log(chalk.green('✓ accessible'));
|
|
317
|
+
}
|
|
318
|
+
catch (err) {
|
|
319
|
+
const status = err?.response?.status;
|
|
320
|
+
if (status === 401 || status === 403) {
|
|
321
|
+
console.log(chalk.red(`✖ rejected (${status}) — credentials are stale or revoked`));
|
|
322
|
+
console.log(chalk.yellow(' Run: lanonasis auth login'));
|
|
323
|
+
}
|
|
324
|
+
else {
|
|
325
|
+
console.log(chalk.yellow(`⚠ reachable (status: ${status ?? 'network error'})`));
|
|
326
|
+
}
|
|
327
|
+
}
|
|
279
328
|
}
|
|
280
329
|
// Show failure tracking information
|
|
281
330
|
if (failureCount > 0) {
|
|
@@ -630,17 +679,85 @@ program
|
|
|
630
679
|
.description('Show overall system status')
|
|
631
680
|
.action(async () => {
|
|
632
681
|
await cliConfig.init();
|
|
633
|
-
const
|
|
682
|
+
const verification = await cliConfig.verifyCurrentCredentialsWithServer().catch((error) => ({
|
|
683
|
+
valid: false,
|
|
684
|
+
method: 'none',
|
|
685
|
+
endpoint: undefined,
|
|
686
|
+
reason: error instanceof Error ? error.message : String(error)
|
|
687
|
+
}));
|
|
688
|
+
const isAuth = verification.valid;
|
|
634
689
|
const apiUrl = cliConfig.getApiUrl();
|
|
635
690
|
console.log(chalk.blue.bold('MaaS CLI Status'));
|
|
636
691
|
console.log(`API URL: ${apiUrl}`);
|
|
637
692
|
console.log(`Authenticated: ${isAuth ? chalk.green('Yes') : chalk.red('No')}`);
|
|
693
|
+
if (process.env.CLI_VERBOSE === 'true' && verification.endpoint) {
|
|
694
|
+
console.log(`Verified via: ${verification.endpoint}`);
|
|
695
|
+
}
|
|
638
696
|
if (isAuth) {
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
697
|
+
try {
|
|
698
|
+
const profileClient = new APIClient();
|
|
699
|
+
profileClient.noExit = true;
|
|
700
|
+
const profile = await profileClient.getUserProfile();
|
|
701
|
+
console.log(`User: ${profile.email}`);
|
|
702
|
+
if (profile.name)
|
|
703
|
+
console.log(`Name: ${profile.name}`);
|
|
704
|
+
console.log(`Role: ${profile.role}`);
|
|
643
705
|
}
|
|
706
|
+
catch {
|
|
707
|
+
const cached = await cliConfig.getCurrentUser();
|
|
708
|
+
if (cached?.email)
|
|
709
|
+
console.log(`User: ${cached.email} (cached)`);
|
|
710
|
+
}
|
|
711
|
+
return;
|
|
712
|
+
}
|
|
713
|
+
console.log(chalk.yellow(`Auth check: ${verification.reason || 'Credential validation failed'}`));
|
|
714
|
+
console.log(chalk.yellow('Please run:'), chalk.white('lanonasis auth login'));
|
|
715
|
+
});
|
|
716
|
+
// Whoami command — live profile from auth gateway
|
|
717
|
+
program
|
|
718
|
+
.command('whoami')
|
|
719
|
+
.description('Show the currently authenticated user profile')
|
|
720
|
+
.action(async () => {
|
|
721
|
+
await cliConfig.init();
|
|
722
|
+
const isAuth = await cliConfig.isAuthenticated();
|
|
723
|
+
if (!isAuth) {
|
|
724
|
+
console.log(chalk.red('✖ Not authenticated'));
|
|
725
|
+
console.log(chalk.yellow('Run:'), chalk.white('lanonasis auth login'));
|
|
726
|
+
process.exit(1);
|
|
727
|
+
}
|
|
728
|
+
try {
|
|
729
|
+
const profileClient = new APIClient();
|
|
730
|
+
profileClient.noExit = true;
|
|
731
|
+
const profile = await profileClient.getUserProfile();
|
|
732
|
+
console.log(chalk.blue.bold('👤 Current User'));
|
|
733
|
+
console.log('━'.repeat(40));
|
|
734
|
+
console.log(`Email: ${chalk.white(profile.email)}`);
|
|
735
|
+
if (profile.name) {
|
|
736
|
+
console.log(`Name: ${chalk.white(profile.name)}`);
|
|
737
|
+
}
|
|
738
|
+
console.log(`Role: ${chalk.white(profile.role)}`);
|
|
739
|
+
if (profile.provider) {
|
|
740
|
+
console.log(`Provider: ${chalk.white(profile.provider)}`);
|
|
741
|
+
}
|
|
742
|
+
if (profile.project_scope) {
|
|
743
|
+
console.log(`Scope: ${chalk.white(profile.project_scope)}`);
|
|
744
|
+
}
|
|
745
|
+
if (profile.last_sign_in_at) {
|
|
746
|
+
console.log(`Last login: ${chalk.white(new Date(profile.last_sign_in_at).toLocaleString())}`);
|
|
747
|
+
}
|
|
748
|
+
if (profile.created_at) {
|
|
749
|
+
console.log(`Member since: ${chalk.white(new Date(profile.created_at).toLocaleString())}`);
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
catch (err) {
|
|
753
|
+
const status = err?.response?.status;
|
|
754
|
+
if (status === 401 || status === 403) {
|
|
755
|
+
console.log(chalk.red('✖ Session expired — please log in again'));
|
|
756
|
+
console.log(chalk.yellow('Run:'), chalk.white('lanonasis auth login'));
|
|
757
|
+
process.exit(1);
|
|
758
|
+
}
|
|
759
|
+
console.error(chalk.red('✖ Failed to fetch profile:'), err instanceof Error ? err.message : String(err));
|
|
760
|
+
process.exit(1);
|
|
644
761
|
}
|
|
645
762
|
});
|
|
646
763
|
// Health command using the healthCheck function
|